diff --git a/build.gradle b/build.gradle index 57e79ba..3a167dd 100644 --- a/build.gradle +++ b/build.gradle @@ -35,6 +35,7 @@ dependencies { compile group: 'org.java-websocket', name: 'Java-WebSocket', version: '1.5.1' compile group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.65' compile group: 'org.bouncycastle', name: 'bctls-jdk15on', version: '1.65' + compile group: 'org.modelmapper', name: 'modelmapper', version: '2.3.0' compileOnly 'org.projectlombok:lombok' runtimeOnly 'org.springframework.boot:spring-boot-devtools' runtimeOnly 'org.postgresql:postgresql' diff --git a/src/main/java/ru/serega6531/packmate/controller/PacketController.java b/src/main/java/ru/serega6531/packmate/controller/PacketController.java index 84b353d..4d9db1b 100644 --- a/src/main/java/ru/serega6531/packmate/controller/PacketController.java +++ b/src/main/java/ru/serega6531/packmate/controller/PacketController.java @@ -5,13 +5,14 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import ru.serega6531.packmate.model.Packet; import ru.serega6531.packmate.model.Stream; +import ru.serega6531.packmate.model.pojo.PacketDto; import ru.serega6531.packmate.service.StreamService; import java.util.Collections; import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; @RestController @RequestMapping("/api/packet/") @@ -25,10 +26,12 @@ public class PacketController { } @PostMapping("/{streamId}") - public List getPacketsForStream(@PathVariable long streamId) { + public List getPacketsForStream(@PathVariable long streamId) { final Optional stream = streamService.find(streamId); if (stream.isPresent()) { - return stream.get().getPackets(); + return stream.get().getPackets().stream() + .map(streamService::packetToDto) + .collect(Collectors.toList()); } else { return Collections.emptyList(); } diff --git a/src/main/java/ru/serega6531/packmate/controller/PatternController.java b/src/main/java/ru/serega6531/packmate/controller/PatternController.java index 143ab1e..335b55f 100644 --- a/src/main/java/ru/serega6531/packmate/controller/PatternController.java +++ b/src/main/java/ru/serega6531/packmate/controller/PatternController.java @@ -3,9 +3,11 @@ package ru.serega6531.packmate.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import ru.serega6531.packmate.model.Pattern; +import ru.serega6531.packmate.model.pojo.PatternDto; import ru.serega6531.packmate.service.PatternService; -import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; @RestController @RequestMapping("/api/pattern/") @@ -19,8 +21,10 @@ public class PatternController { } @GetMapping - public Collection getPatterns() { - return service.findAll(); + public List getPatterns() { + return service.findAll() + .stream().map(service::toDto) + .collect(Collectors.toList()); } @PostMapping("/{id}") @@ -29,9 +33,11 @@ public class PatternController { } @PostMapping - public Pattern addPattern(@RequestBody Pattern pattern) { - pattern.setEnabled(true); - return service.save(pattern); + public PatternDto addPattern(@RequestBody PatternDto dto) { + dto.setEnabled(true); + Pattern pattern = service.fromDto(dto); + Pattern saved = service.save(pattern); + return service.toDto(saved); } } diff --git a/src/main/java/ru/serega6531/packmate/controller/ServiceController.java b/src/main/java/ru/serega6531/packmate/controller/ServiceController.java index e27f54e..b317c6b 100644 --- a/src/main/java/ru/serega6531/packmate/controller/ServiceController.java +++ b/src/main/java/ru/serega6531/packmate/controller/ServiceController.java @@ -3,9 +3,11 @@ package ru.serega6531.packmate.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import ru.serega6531.packmate.model.CtfService; +import ru.serega6531.packmate.model.pojo.ServiceDto; import ru.serega6531.packmate.service.ServicesService; -import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; @RestController @RequestMapping("/api/service/") @@ -19,8 +21,10 @@ public class ServiceController { } @GetMapping - public Collection getServices() { - return service.findAll(); + public List getServices() { + return service.findAll().stream() + .map(service::toDto) + .collect(Collectors.toList()); } @DeleteMapping("/{port}") @@ -29,8 +33,9 @@ public class ServiceController { } @PostMapping - public CtfService addService(@RequestBody CtfService ctfService) { - return service.save(ctfService); + public CtfService addService(@RequestBody ServiceDto dto) { + CtfService newService = this.service.fromDto(dto); + return this.service.save(newService); } } diff --git a/src/main/java/ru/serega6531/packmate/controller/StreamController.java b/src/main/java/ru/serega6531/packmate/controller/StreamController.java index 6f50ef7..e8697b8 100644 --- a/src/main/java/ru/serega6531/packmate/controller/StreamController.java +++ b/src/main/java/ru/serega6531/packmate/controller/StreamController.java @@ -2,42 +2,47 @@ package ru.serega6531.packmate.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; -import ru.serega6531.packmate.model.Stream; import ru.serega6531.packmate.model.pojo.Pagination; +import ru.serega6531.packmate.model.pojo.StreamDto; import ru.serega6531.packmate.service.StreamService; import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; @RestController @RequestMapping("/api/stream/") public class StreamController { - private final StreamService streamService; + private final StreamService service; @Autowired - public StreamController(StreamService streamService) { - this.streamService = streamService; + public StreamController(StreamService service) { + this.service = service; } @PostMapping("/all") - public List getStreams(@RequestBody Pagination pagination) { - return streamService.findAll(pagination, Optional.empty(), pagination.isFavorites()); + public List getStreams(@RequestBody Pagination pagination) { + return service.findAll(pagination, Optional.empty(), pagination.isFavorites()).stream() + .map(service::streamToDto) + .collect(Collectors.toList()); } @PostMapping("/{port}") - public List getStreams(@PathVariable int port, @RequestBody Pagination pagination) { - return streamService.findAll(pagination, Optional.of(port), pagination.isFavorites()); + public List getStreams(@PathVariable int port, @RequestBody Pagination pagination) { + return service.findAll(pagination, Optional.of(port), pagination.isFavorites()).stream() + .map(service::streamToDto) + .collect(Collectors.toList()); } @PostMapping("/{id}/favorite") public void favoriteStream(@PathVariable long id) { - streamService.setFavorite(id, true); + service.setFavorite(id, true); } @PostMapping("/{id}/unfavorite") public void unfavoriteStream(@PathVariable long id) { - streamService.setFavorite(id, false); + service.setFavorite(id, false); } } diff --git a/src/main/java/ru/serega6531/packmate/model/FoundPattern.java b/src/main/java/ru/serega6531/packmate/model/FoundPattern.java index 1d33786..1c76e9a 100644 --- a/src/main/java/ru/serega6531/packmate/model/FoundPattern.java +++ b/src/main/java/ru/serega6531/packmate/model/FoundPattern.java @@ -1,6 +1,5 @@ package ru.serega6531.packmate.model; -import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.*; import org.hibernate.annotations.GenericGenerator; @@ -28,10 +27,12 @@ public class FoundPattern { @Id @GeneratedValue(generator = "found_pattern_generator") - @JsonIgnore private int id; + private int patternId; + private int startPosition; + private int endPosition; } diff --git a/src/main/java/ru/serega6531/packmate/model/Packet.java b/src/main/java/ru/serega6531/packmate/model/Packet.java index e1690da..f8fe5a2 100644 --- a/src/main/java/ru/serega6531/packmate/model/Packet.java +++ b/src/main/java/ru/serega6531/packmate/model/Packet.java @@ -1,6 +1,5 @@ package ru.serega6531.packmate.model; -import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -32,16 +31,13 @@ public class Packet { private Long id; @Transient - @JsonIgnore private Long tempId; @Transient - @JsonIgnore private byte ttl; @ManyToOne @JoinColumn(name = "stream_id", nullable = false) - @JsonIgnore private Stream stream; @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) @@ -60,7 +56,6 @@ public class Packet { private byte[] content; @Transient - @JsonIgnore public String getContentString() { return new String(content); } diff --git a/src/main/java/ru/serega6531/packmate/model/Pattern.java b/src/main/java/ru/serega6531/packmate/model/Pattern.java index 80f10f6..e417ba5 100644 --- a/src/main/java/ru/serega6531/packmate/model/Pattern.java +++ b/src/main/java/ru/serega6531/packmate/model/Pattern.java @@ -1,6 +1,5 @@ package ru.serega6531.packmate.model; -import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.Data; import lombok.ToString; import org.hibernate.annotations.GenericGenerator; @@ -41,7 +40,6 @@ public class Pattern { private PatternDirectionType directionType; @ManyToMany(mappedBy = "foundPatterns", fetch = FetchType.LAZY) - @JsonIgnore private List matchedStreams; } diff --git a/src/main/java/ru/serega6531/packmate/model/Stream.java b/src/main/java/ru/serega6531/packmate/model/Stream.java index 3023d2f..6df12e6 100644 --- a/src/main/java/ru/serega6531/packmate/model/Stream.java +++ b/src/main/java/ru/serega6531/packmate/model/Stream.java @@ -1,6 +1,5 @@ package ru.serega6531.packmate.model; -import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.Data; import lombok.ToString; import org.hibernate.annotations.GenericGenerator; @@ -34,7 +33,6 @@ public class Stream { private Protocol protocol; @OneToMany(mappedBy = "stream", cascade = CascadeType.ALL) - @JsonIgnore @OrderBy("id") private List packets; diff --git a/src/main/java/ru/serega6531/packmate/model/pojo/FoundPatternDto.java b/src/main/java/ru/serega6531/packmate/model/pojo/FoundPatternDto.java new file mode 100644 index 0000000..51ac15a --- /dev/null +++ b/src/main/java/ru/serega6531/packmate/model/pojo/FoundPatternDto.java @@ -0,0 +1,12 @@ +package ru.serega6531.packmate.model.pojo; + +import lombok.Data; + +@Data +public class FoundPatternDto { + + private int patternId; + private int startPosition; + private int endPosition; + +} diff --git a/src/main/java/ru/serega6531/packmate/model/pojo/PacketDto.java b/src/main/java/ru/serega6531/packmate/model/pojo/PacketDto.java new file mode 100644 index 0000000..b276786 --- /dev/null +++ b/src/main/java/ru/serega6531/packmate/model/pojo/PacketDto.java @@ -0,0 +1,19 @@ +package ru.serega6531.packmate.model.pojo; + +import lombok.Data; + +import java.util.Set; + +@Data +public class PacketDto { + + private Long id; + private Set matches; + private long timestamp; + private boolean incoming; + private boolean ungzipped; + private boolean webSocketParsed; + private boolean tlsDecrypted; + private byte[] content; + +} diff --git a/src/main/java/ru/serega6531/packmate/model/pojo/PatternDto.java b/src/main/java/ru/serega6531/packmate/model/pojo/PatternDto.java new file mode 100644 index 0000000..b37a933 --- /dev/null +++ b/src/main/java/ru/serega6531/packmate/model/pojo/PatternDto.java @@ -0,0 +1,18 @@ +package ru.serega6531.packmate.model.pojo; + +import lombok.Data; +import ru.serega6531.packmate.model.enums.PatternDirectionType; +import ru.serega6531.packmate.model.enums.PatternSearchType; + +@Data +public class PatternDto { + + private int id; + private boolean enabled; + private String name; + private String value; + private String color; // для вставки в css + private PatternSearchType searchType; + private PatternDirectionType directionType; + +} diff --git a/src/main/java/ru/serega6531/packmate/model/pojo/ServiceDto.java b/src/main/java/ru/serega6531/packmate/model/pojo/ServiceDto.java new file mode 100644 index 0000000..0955ecd --- /dev/null +++ b/src/main/java/ru/serega6531/packmate/model/pojo/ServiceDto.java @@ -0,0 +1,17 @@ +package ru.serega6531.packmate.model.pojo; + +import lombok.Data; + +@Data +public class ServiceDto { + + private int port; + private String name; + private boolean decryptTls; + private boolean processChunkedEncoding; + private boolean ungzipHttp; + private boolean urldecodeHttpRequests; + private boolean mergeAdjacentPackets; + private boolean parseWebSockets; + +} diff --git a/src/main/java/ru/serega6531/packmate/model/pojo/StreamDto.java b/src/main/java/ru/serega6531/packmate/model/pojo/StreamDto.java new file mode 100644 index 0000000..74e4a52 --- /dev/null +++ b/src/main/java/ru/serega6531/packmate/model/pojo/StreamDto.java @@ -0,0 +1,21 @@ +package ru.serega6531.packmate.model.pojo; + +import lombok.Data; +import ru.serega6531.packmate.model.enums.Protocol; + +import java.util.Set; + +@Data +public class StreamDto { + + private Long id; + private int service; + private Protocol protocol; + private long startTimestamp; + private long endTimestamp; + private Set foundPatterns; + private boolean favorite; + private byte ttl; + private String userAgentHash; + +} diff --git a/src/main/java/ru/serega6531/packmate/service/PatternService.java b/src/main/java/ru/serega6531/packmate/service/PatternService.java index b6c719d..bb702e7 100644 --- a/src/main/java/ru/serega6531/packmate/service/PatternService.java +++ b/src/main/java/ru/serega6531/packmate/service/PatternService.java @@ -1,6 +1,7 @@ package ru.serega6531.packmate.service; import lombok.extern.slf4j.Slf4j; +import org.modelmapper.ModelMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import ru.serega6531.packmate.model.FoundPattern; @@ -8,6 +9,7 @@ import ru.serega6531.packmate.model.Pattern; import ru.serega6531.packmate.model.enums.PatternDirectionType; import ru.serega6531.packmate.model.enums.PatternSearchType; import ru.serega6531.packmate.model.enums.SubscriptionMessageType; +import ru.serega6531.packmate.model.pojo.PatternDto; import ru.serega6531.packmate.model.pojo.SubscriptionMessage; import ru.serega6531.packmate.repository.PatternRepository; @@ -23,6 +25,7 @@ public class PatternService { private final SubscriptionService subscriptionService; private final Map patterns = new HashMap<>(); + private final ModelMapper modelMapper = new ModelMapper(); @Autowired public PatternService(PatternRepository repository, @@ -80,8 +83,16 @@ public class PatternService { final Pattern saved = repository.save(pattern); patterns.put(saved.getId(), saved); log.info("Added new pattern '{}' with value '{}'", pattern.getName(), pattern.getValue()); - subscriptionService.broadcast(new SubscriptionMessage(SubscriptionMessageType.SAVE_PATTERN, saved)); + subscriptionService.broadcast(new SubscriptionMessage(SubscriptionMessageType.SAVE_PATTERN, toDto(saved))); return saved; } + public Pattern fromDto(PatternDto dto) { + return modelMapper.map(dto, Pattern.class); + } + + public PatternDto toDto(Pattern pattern) { + return modelMapper.map(pattern, PatternDto.class); + } + } diff --git a/src/main/java/ru/serega6531/packmate/service/ServicesService.java b/src/main/java/ru/serega6531/packmate/service/ServicesService.java index 2d53ea0..075e056 100644 --- a/src/main/java/ru/serega6531/packmate/service/ServicesService.java +++ b/src/main/java/ru/serega6531/packmate/service/ServicesService.java @@ -1,12 +1,14 @@ package ru.serega6531.packmate.service; import lombok.extern.slf4j.Slf4j; +import org.modelmapper.ModelMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import ru.serega6531.packmate.model.CtfService; import ru.serega6531.packmate.model.enums.SubscriptionMessageType; +import ru.serega6531.packmate.model.pojo.ServiceDto; import ru.serega6531.packmate.model.pojo.SubscriptionMessage; import ru.serega6531.packmate.repository.ServiceRepository; @@ -29,6 +31,7 @@ public class ServicesService { private final InetAddress localIp; private final Map services = new HashMap<>(); + private final ModelMapper modelMapper = new ModelMapper(); @Autowired public ServicesService(ServiceRepository repository, @@ -44,6 +47,10 @@ public class ServicesService { log.info("Loaded {} services", services.size()); } + public CtfService find(int id) { + return services.get(id); + } + public Optional findService(Inet4Address firstIp, int firstPort, Inet4Address secondIp, int secondPort) { if (firstIp.equals(localIp)) { return findByPort(firstPort); @@ -79,11 +86,19 @@ public class ServicesService { final CtfService saved = repository.save(service); services.put(saved.getPort(), saved); - subscriptionService.broadcast(new SubscriptionMessage(SubscriptionMessageType.SAVE_SERVICE, saved)); + subscriptionService.broadcast(new SubscriptionMessage(SubscriptionMessageType.SAVE_SERVICE, toDto(saved))); pcapService.updateFilter(findAll()); return saved; } + public ServiceDto toDto(CtfService service) { + return modelMapper.map(service, ServiceDto.class); + } + + public CtfService fromDto(ServiceDto dto) { + return modelMapper.map(dto, CtfService.class); + } + } diff --git a/src/main/java/ru/serega6531/packmate/service/StreamService.java b/src/main/java/ru/serega6531/packmate/service/StreamService.java index 9e8a77f..b59121d 100644 --- a/src/main/java/ru/serega6531/packmate/service/StreamService.java +++ b/src/main/java/ru/serega6531/packmate/service/StreamService.java @@ -1,6 +1,7 @@ package ru.serega6531.packmate.service; import lombok.extern.slf4j.Slf4j; +import org.modelmapper.ModelMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.domain.PageRequest; @@ -11,9 +12,7 @@ import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import ru.serega6531.packmate.model.*; import ru.serega6531.packmate.model.enums.SubscriptionMessageType; -import ru.serega6531.packmate.model.pojo.Pagination; -import ru.serega6531.packmate.model.pojo.SubscriptionMessage; -import ru.serega6531.packmate.model.pojo.UnfinishedStream; +import ru.serega6531.packmate.model.pojo.*; import ru.serega6531.packmate.repository.StreamRepository; import ru.serega6531.packmate.service.optimization.RsaKeysHolder; import ru.serega6531.packmate.service.optimization.StreamOptimizer; @@ -39,6 +38,7 @@ public class StreamService { private final boolean ignoreEmptyPackets; private final java.util.regex.Pattern userAgentPattern = java.util.regex.Pattern.compile("User-Agent: (.+)\\r\\n"); + private final ModelMapper modelMapper = new ModelMapper(); @Autowired public StreamService(StreamRepository repository, @@ -108,7 +108,7 @@ public class StreamService { savedStream.setPackets(packets); savedStream = save(savedStream); - subscriptionService.broadcast(new SubscriptionMessage(SubscriptionMessageType.NEW_STREAM, savedStream)); + subscriptionService.broadcast(new SubscriptionMessage(SubscriptionMessageType.NEW_STREAM, streamToDto(savedStream))); return true; } @@ -132,7 +132,7 @@ public class StreamService { char[] alphabet = "abcdefghijklmnopqrstuvwxyz0123456789".toCharArray(); int l = alphabet.length; int hashCode = ua.hashCode(); - if(hashCode == Integer.MIN_VALUE) { // abs(MIN_VALUE) вернет то же значение + if (hashCode == Integer.MIN_VALUE) { // abs(MIN_VALUE) вернет то же значение hashCode = Integer.MAX_VALUE; } final int hash = Math.abs(hashCode) % (l * l * l); @@ -182,27 +182,35 @@ public class StreamService { PageRequest page = PageRequest.of(0, pagination.getPageSize(), pagination.getDirection(), "id"); Specification spec; - if(pagination.getDirection() == Sort.Direction.ASC) { + if (pagination.getDirection() == Sort.Direction.ASC) { spec = streamIdGreaterThan(pagination.getStartingFrom()); } else { spec = streamIdLessThan(pagination.getStartingFrom()); } - if(service.isPresent()) { + if (service.isPresent()) { spec = spec.and(streamServiceEquals(service.get())); } - if(onlyFavorites) { + if (onlyFavorites) { spec = spec.and(streamIsFavorite()); } - if(pagination.getPattern() != null) { + if (pagination.getPattern() != null) { spec = spec.and(streamPatternsContains(pagination.getPattern())); } return repository.findAll(spec, page).getContent(); } + public StreamDto streamToDto(Stream stream) { + return modelMapper.map(stream, StreamDto.class); + } + + public PacketDto packetToDto(Packet packet) { + return modelMapper.map(packet, PacketDto.class); + } + private Specification streamServiceEquals(long service) { return (root, query, cb) -> cb.equal(root.get("service"), service); }