diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..63177e3dfcbc9db2a754b7936ac2b395a3186e4b --- /dev/null +++ b/.gitignore @@ -0,0 +1,30 @@ +HELP.md +.gradle +/build/ +!gradle/wrapper/gradle-wrapper.jar + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr +/out/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ diff --git a/README.md b/README.md index 4c1b22901f4c410542dfc0c0deed61572d884453..b08b5d686dcbc684d238bc198d2d3cfa31aa2733 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ -# CUREX Distr +# DISTRIBUTED NODE diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000000000000000000000000000000000000..4e79e46bad7eeac14508ade16a52d94844330917 --- /dev/null +++ b/build.gradle @@ -0,0 +1,60 @@ +plugins { + id 'org.springframework.boot' version '2.1.5.RELEASE' + id 'java' +} + +apply plugin: 'io.spring.dependency-management' + +group = 'adt' +version = '0.0.1-SNAPSHOT' +sourceCompatibility = '1.8' + +configurations { + compileOnly { + extendsFrom annotationProcessor + } +} + +repositories { + mavenCentral() + maven { + url "https://jitpack.io" + } + maven { + url "http://mvn.martiansoftware.com" + } +} +dependencies { + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springframework.boot:spring-boot-starter-data-rest' + implementation 'org.springframework.cloud:spring-cloud-starter-openfeign:2.1.1.RELEASE' + implementation 'org.springframework.cloud:spring-cloud-starter-netflix-ribbon:2.1.1.RELEASE' + compile 'commons-codec:commons-codec:1.13' + compile 'org.json:json:20171018' + compileOnly 'org.projectlombok:lombok' + runtimeOnly 'com.h2database:h2' + annotationProcessor 'org.projectlombok:lombok' + testImplementation 'org.springframework.boot:spring-boot-starter-test' + implementation "com.github.stealthcopter:AndroidNetworkTools:0.4.3" + implementation "com.martiansoftware:macnificent:0.2.0" + implementation 'com.google.guava:guava:27.1-jre' + compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.0' + compile group: 'javax.json', name: 'javax.json-api', version: '1.0-b01' + compile 'org.json:json:20171018' + runtimeOnly 'mysql:mysql-connector-java' + annotationProcessor 'org.projectlombok:lombok' + testImplementation 'org.springframework.boot:spring-boot-starter-test' + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.webjars:bootstrap:4.1.3' + compile 'org.apache.tomcat.embed:tomcat-embed-jasper' + runtimeOnly 'javax.servlet:jstl' + compileOnly 'javax.servlet:javax.servlet-api:3.0.1' + compile group: 'com.google.code.gson', name: 'gson', version: '2.8.6' + compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.9' + compile group: 'javax.ws.rs', name: 'javax.ws.rs-api', version: '2.1.1' + compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.10' + compile group: 'org.apache.httpcomponents', name: 'httpmime', version: '4.5.10' + compile group: 'com.sun.mail', name: 'javax.mail', version: '1.6.2' + compile group: 'com.googlecode.json-simple', name: 'json-simple', version: '1.1.1' + +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..87b738cbd051603d91cc39de6cb000dd98fe6b02 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000000000000000000000000000000000..44e7c4d1d7bbfb00dfb4b96fef50d50fd87bbb7a --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 0000000000000000000000000000000000000000..af6708ff229fda75da4f7cc4da4747217bac4d53 --- /dev/null +++ b/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000000000000000000000000000000000000..6d57edc706c93465988754383a2d7ff353d4e79f --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000000000000000000000000000000000000..3064bb227e048eeb854e43c3ed62f456ded93398 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,6 @@ +pluginManagement { + repositories { + gradlePluginPortal() + } +} +rootProject.name = 'adt' diff --git a/src/main/java/adt/AdtApplication.java b/src/main/java/adt/AdtApplication.java new file mode 100644 index 0000000000000000000000000000000000000000..3bd808c19d130b77f5bede9e0f6dfa3b0d6cc69c --- /dev/null +++ b/src/main/java/adt/AdtApplication.java @@ -0,0 +1,23 @@ +package adt; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.scheduling.annotation.EnableScheduling; + +@SpringBootApplication +@EnableFeignClients +@EnableScheduling +public class AdtApplication { + + public static void main(String[] args) { + + try { + SpringApplication.run(AdtApplication.class, args); + } catch (Exception e) { + //handled + } + + } + +} diff --git a/src/main/java/adt/client/MainNodeClient.java b/src/main/java/adt/client/MainNodeClient.java new file mode 100644 index 0000000000000000000000000000000000000000..481a120e5bbc37d04ad446d36174f6716b990f2d --- /dev/null +++ b/src/main/java/adt/client/MainNodeClient.java @@ -0,0 +1,28 @@ +package adt.client; + +import adt.dto.Asset; +import adt.dto.Node; +import adt.entity.ScanInfo; +import adt.entity.Vlan; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestMethod; + +import java.util.List; + +@FeignClient(name = "main-node", url = "${main-node.address}:${main-node.port}") +public interface MainNodeClient { + + @RequestMapping(value = "/vlans", method = RequestMethod.POST) + Long sendAssets(Asset asset, @RequestParam String token); + + @RequestMapping(value = "/configurations", method = RequestMethod.GET) + Node initialize(@RequestParam String token); + + @RequestMapping(value="/ip", method = RequestMethod.GET) + int checkIP(@RequestParam String params); + +} diff --git a/src/main/java/adt/client/MainNodeCom.java b/src/main/java/adt/client/MainNodeCom.java new file mode 100644 index 0000000000000000000000000000000000000000..c13ab7d3321452fff5def30681d6169871fa92f2 --- /dev/null +++ b/src/main/java/adt/client/MainNodeCom.java @@ -0,0 +1,220 @@ +package adt.client; + +import adt.dto.Asset; +import adt.dto.Node; +import adt.entity.ScanInfo; +import adt.entity.Vlan; +import org.springframework.beans.factory.annotation.Value; +import lombok.extern.slf4j.Slf4j; +import java.util.List; + +import java.util.List; +import java.util.concurrent.Executors; +import javax.servlet.http.HttpServletRequest; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectWriter; +import com.fasterxml.jackson.databind.*; +import com.fasterxml.jackson.core.JsonProcessingException; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.*; + +import java.io.FileWriter; +import java.io.IOException; +import java.io.*; + +import java.util.Arrays; +import java.util.ArrayList; +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.core.Response.Status; + +import java.util.*; + +import java.net.*; + +import org.apache.http.client.methods.*; +import org.apache.http.impl.client.*; +import org.apache.http.entity.mime.*; +import org.apache.http.entity.*; +import org.apache.http.*; +import org.apache.http.util.*; + +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.JSONArray; + +import com.fasterxml.jackson.databind.DeserializationFeature; + + +@Slf4j +@Service +public class MainNodeCom { + + @Value("${main-node.address}") + private String mainNodeAddress; + @Value("${main-node.port}") + private String mainNodePort; + + + public Long sendAssets(Asset asset, String token){ + + String urlQuery = "http://" + mainNodeAddress + ":" + mainNodePort + "/vlans?token=" + token; + + log.info("SENDING ASSETS TO: {}", urlQuery); + + + log.info("SENDING THESE ASSETS: \n{}", asset); + + + Long newDelay = null; + + try { + URL url = new URL(urlQuery); + + HttpURLConnection con = (HttpURLConnection) url.openConnection(); + con.setRequestMethod("POST"); + con.setRequestProperty("Content-Type", "application/json; utf-8"); + con.setRequestProperty("Accept", "application/json"); + con.setDoOutput(true); + + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + final ObjectMapper mapper = new ObjectMapper(); + + mapper.writeValue(out, asset); + + final byte[] data = out.toByteArray(); + + try (OutputStream os = con.getOutputStream()) { + //byte[] input = jsonInputString.getBytes("utf-8"); + os.write(data, 0, data.length); + } + + try (BufferedReader br = new BufferedReader( + new InputStreamReader(con.getInputStream(), "utf-8"))) { + + StringBuilder response = new StringBuilder(); + String responseLine = null; + + while ((responseLine = br.readLine()) != null) { + + response.append(responseLine.trim()); + } + + newDelay = Long.parseLong(response.toString()); + + } catch (Exception ex) { + // handled + log.info("##############{}",ex); + } + + } catch (Exception ex) { + // handled + log.info("##############{}",ex); + + } + + return newDelay; + + } + + + public Node initialize(String token){ + + log.info("[--INITIALIZATION PROCESS--] Querying the Main Node for a scanning configuration..."); + + String urlQuery = "http://" + mainNodeAddress + ":" + mainNodePort + "/configurations?token=" + token; + + Node node = null; + + try { + URL url = new URL(urlQuery); + + HttpURLConnection con = (HttpURLConnection) url.openConnection(); + con.setRequestMethod("GET"); + con.setRequestProperty("Content-Type", "application/json; utf-8"); + con.setRequestProperty("Accept", "application/json"); + con.setDoOutput(true); + + try (BufferedReader br = new BufferedReader( + new InputStreamReader(con.getInputStream(), "utf-8"))) { + + StringBuilder response = new StringBuilder(); + String responseLine = null; + + while ((responseLine = br.readLine()) != null) { + + response.append(responseLine.trim()); + } + + ObjectMapper objectMapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + node = objectMapper.readValue(response.toString(), Node.class); + + } catch (Exception ex) { + // handled + log.info("##############{}",ex); + } + + } catch (Exception ex) { + // handled + log.info("##############{}",ex); + + } + + return node; + + } + + + public int checkIP(String token, String clientIP, String mac){ + + log.info("[--DHCP SNIFING PROCESS--] Querying the Main Node for checking the existence of records for IP {}.", clientIP); + + String urlQuery = "http://" + mainNodeAddress + ":" + mainNodePort + "/presence_check?ip=" + clientIP + "&mac=" + mac + "&token=" + token; + + int answer = -1; + + try { + URL url = new URL(urlQuery); + + HttpURLConnection con = (HttpURLConnection) url.openConnection(); + con.setRequestMethod("GET"); + con.setRequestProperty("Content-Type", "application/json; utf-8"); + con.setRequestProperty("Accept", "application/json"); + con.setDoOutput(true); + + try (BufferedReader br = new BufferedReader( + new InputStreamReader(con.getInputStream(), "utf-8"))) { + + StringBuilder response = new StringBuilder(); + String responseLine = null; + + while ((responseLine = br.readLine()) != null) { + + response.append(responseLine.trim()); + } + + answer = Integer.parseInt(response.toString()); + + } catch (Exception ex) { + // handled + log.info("##############{}",ex); + } + + } catch (Exception ex) { + // handled + log.info("##############{}",ex); + + } + + return answer; + } + + +} diff --git a/src/main/java/adt/dto/Asset.java b/src/main/java/adt/dto/Asset.java new file mode 100644 index 0000000000000000000000000000000000000000..9d0fc0cf41fdabc99d54cf85626ab37c759ddd21 --- /dev/null +++ b/src/main/java/adt/dto/Asset.java @@ -0,0 +1,36 @@ +package adt.dto; + +import adt.entity.Host; +import adt.entity.Port; +import adt.entity.ScanInfo; +import adt.entity.Vlan; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import java.util.Date; + +import java.util.List; + +@Data +@NoArgsConstructor +@AllArgsConstructor +//@JsonPropertyOrder({ "scanInfo", "iniTimestampScan", "endTimestampScan", "host", "ports" }) +public class Asset { + + List scanInfo; + String discoveryMethod; + + public static Asset createAsset(List scanInfo, String discovery_method){ + + Asset asset = new Asset(); + + asset.setScanInfo(scanInfo); + asset.setDiscoveryMethod(discovery_method); + + return asset; + } + +} diff --git a/src/main/java/adt/dto/HostDto.java b/src/main/java/adt/dto/HostDto.java new file mode 100644 index 0000000000000000000000000000000000000000..83cc968bc114840abe0dfbb8b0bb6c9337b2354c --- /dev/null +++ b/src/main/java/adt/dto/HostDto.java @@ -0,0 +1,52 @@ +package adt.dto; + +import adt.entity.Host; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import java.util.List; +import java.util.Date; +import adt.entity.Port; + +import javax.persistence.Id; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class HostDto { + + @Id + @JsonProperty("ip_address") + private String ip; + + @JsonProperty("hostname") + private String hostname; + + @JsonProperty("mac_address") + private String mac; + + @JsonProperty("mac_manufacturer") + private String macManufacturer; + + @JsonProperty("timestamp_device_scan_start") + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") + private Date timestamp_ini; + + @JsonProperty("timestamp_device_scan_end") + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") + private Date timestamp_end; + + @JsonProperty("ports") + private List ports; + + public static HostDto createHostDto(String ip, String hostname, String mac) { + HostDto host = new HostDto(); + host.setIp(ip); + host.setHostname(hostname); + host.setMac(mac); + host.setMacManufacturer(""); + return host; + } +} diff --git a/src/main/java/adt/dto/Node.java b/src/main/java/adt/dto/Node.java new file mode 100644 index 0000000000000000000000000000000000000000..80722862cc8efb1339e4592e8b5b0b4b984c8f70 --- /dev/null +++ b/src/main/java/adt/dto/Node.java @@ -0,0 +1,38 @@ +package adt.dto; + +import adt.entity.Vlan; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import java.util.List; +//import com.fasterxml.jackson.annotation.JsonIgnore; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +public class Node { + + //@JsonIgnore + private int id; + + private String ip; + + @Setter(AccessLevel.PRIVATE) + private String vlanName; + + @Setter(AccessLevel.PRIVATE) + //@JsonIgnore + private String osType; + + //@JsonIgnore + //private Vlan vlan; + private List vlan; + + public static Node createNode(String vlanName, String osType) { + Node node = new Node(); + node.setVlanName(vlanName); + node.setOsType(osType); + return node; + } + +} diff --git a/src/main/java/adt/dto/ScanInfoDto.java b/src/main/java/adt/dto/ScanInfoDto.java new file mode 100644 index 0000000000000000000000000000000000000000..0c5a6e1383fe465602560749514d58293b483d93 --- /dev/null +++ b/src/main/java/adt/dto/ScanInfoDto.java @@ -0,0 +1,72 @@ +package adt.dto; + +import adt.entity.Host; +import adt.entity.Port; +import adt.entity.ScanInfo; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.Id; +import javax.persistence.Transient; +import java.util.Date; +import java.util.List; +import java.net.NetworkInterface; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.net.SocketException; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class ScanInfoDto { + + @Id + @JsonProperty("vlan_id") + String vlanName; + + @JsonProperty("node_ip_address") + String nodeIp; + + @JsonProperty("timestamp_dist_node_scan_start") + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") + private Date iniTimestampScan; + + @JsonProperty("timestamp_dist_node_scan_end") + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") + private Date endTimestampScan; + + @JsonProperty("mac_address") + private String macAddress; + + @JsonProperty("devices") + private List host; + + public static ScanInfoDto createScanInfoDto(String vlanName, String ip, Date iniTimestampScan, Date endTimestampScan) { + + ScanInfoDto scanInfo = new ScanInfoDto(); + scanInfo.setVlanName(vlanName); + scanInfo.setNodeIp(ip); + scanInfo.setIniTimestampScan(iniTimestampScan); + scanInfo.setEndTimestampScan(endTimestampScan); + + String ipAddress = ip.toString(); + byte[] mac = null; + try { + InetAddress add = InetAddress.getByName(ipAddress); + NetworkInterface network = NetworkInterface.getByInetAddress(add); + mac = network.getHardwareAddress(); + }catch(UnknownHostException ue){ + // Handled + }catch(SocketException se){ + // Handled + } + scanInfo.setMacAddress(mac.toString()); + //scanInfo.setHosts(new ArrayList<>()); + + return scanInfo; + } + +} diff --git a/src/main/java/adt/entity/Host.java b/src/main/java/adt/entity/Host.java new file mode 100644 index 0000000000000000000000000000000000000000..d21d50876d55c81be1a820c738e7c0e39c1a5968 --- /dev/null +++ b/src/main/java/adt/entity/Host.java @@ -0,0 +1,81 @@ +package adt.entity; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Transient; +import java.util.Date; +import java.util.List; +import com.fasterxml.jackson.annotation.JsonIgnore; +import javax.persistence.*; + +@Data +@Entity +public class Host { + + @Id + @JsonProperty("ip_address") + private String ip; + + @JsonProperty("hostname") + private String hostname; + + @ManyToOne + @JsonProperty("scan_info") + private ScanInfo scanInfo; + + @JsonProperty("mac_address") + private String mac; + + @JsonProperty("mac_manufacturer") + private String macManufacturer; + + @JsonProperty("timestamp_device_scan_start") + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") + private Date timestamp_ini; + + @JsonProperty("timestamp_device_scan_end") + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") + private Date timestamp_end; + + @Transient + @JsonProperty("ports") + private List ports; + + @JsonProperty("operating_system") + private String operatingSystem; + + @JsonIgnore + @JsonProperty("vlan_id") + private String vlanName; + + @JsonProperty("discovery_method") + private String discoveryMethod; + + public static Host createHost(String ip, String hostname, String mac, String discoveryMethod) { + Host host = new Host(); + host.setIp(ip); + host.setHostname(hostname); + host.setMac(mac); + host.setMacManufacturer(""); + host.setDiscoveryMethod(discoveryMethod); + return host; + } + + public static Host createHost(String ip, String hostname, String mac, String vlanName, Date timestampIni, ScanInfo scanInfo, String discoveryMethod) { + Host host = new Host(); + host.setIp(ip); + host.setHostname(hostname); + host.setMac(mac); + host.setScanInfo(scanInfo); + host.setMacManufacturer(""); + host.setVlanName(vlanName); + host.setTimestamp_ini(timestampIni); + host.setDiscoveryMethod(discoveryMethod); + return host; + } + +} + diff --git a/src/main/java/adt/entity/Port.java b/src/main/java/adt/entity/Port.java new file mode 100644 index 0000000000000000000000000000000000000000..dea3fa789bec90626730652d95b500a0f5d5357f --- /dev/null +++ b/src/main/java/adt/entity/Port.java @@ -0,0 +1,66 @@ +package adt.entity; + +import lombok.Data; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + +import javax.persistence.*; + +import org.apache.commons.codec.digest.DigestUtils; + +@Data +@Entity +public class Port { + + //@GeneratedValue(strategy = GenerationType.IDENTITY) + @Id + @JsonProperty("id") + private String id; + + @JsonProperty("port") + private String portNumber; + + @ManyToOne + @JsonIgnore + private Host host; + + @JsonProperty("service") + private String serviceRunning; + + @JsonProperty("service_version") + private String serviceVersion; + + @JsonProperty("discovery_method") + private String discoveryMethod; + + @JsonProperty("protocol") + private String protocol; + + @JsonProperty("state") + private String state; + + @JsonProperty("discovery_method_trigger") + private String discoveryMethodTrigger; + + public static Port createPort(String portNumber, Host host, String protocol, String discoveryMethod) { + Port port = new Port(); + String generatedHash = DigestUtils.md5Hex( DigestUtils.md5Hex(portNumber) + DigestUtils.md5Hex(host.getIp()) ); + + //System.out.println(generatedHash); + + port.setId(generatedHash); + port.setPortNumber(portNumber); + port.setHost(host); + port.setProtocol(protocol); + port.setDiscoveryMethodTrigger(discoveryMethod); + return port; + } + + @Override + public String toString() { + return String.format("Port %s open on host %s with protocol %s", portNumber, host.getIp(), protocol); + } + + + +} diff --git a/src/main/java/adt/entity/ScanInfo.java b/src/main/java/adt/entity/ScanInfo.java new file mode 100644 index 0000000000000000000000000000000000000000..2a79cb3dceb4865580dd4ac983078e7e888a7c18 --- /dev/null +++ b/src/main/java/adt/entity/ScanInfo.java @@ -0,0 +1,155 @@ +package adt.entity; + +import adt.entity.Host; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Getter; +import lombok.Setter; +import lombok.NoArgsConstructor; +import com.fasterxml.jackson.annotation.JsonIgnore; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Transient; +import java.util.Date; +import java.util.List; +import java.util.ArrayList; +import java.net.NetworkInterface; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.net.SocketException; + +import lombok.extern.slf4j.Slf4j; +import javax.persistence.*; + + +@Slf4j +@Entity +@Getter +@Setter +@NoArgsConstructor +public class ScanInfo { + + @Id + @JsonProperty("vlan_id") + String vlanName; + + @JsonProperty("node_ip_address") + String nodeIp; + + @JsonProperty("timestamp_dist_node_scan_start") + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") + private Date iniTimestampScan; + + @JsonProperty("timestamp_dist_node_scan_end") + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") + private Date endTimestampScan; + + @JsonProperty("mac_address") + private String macAddress; + + @Transient + @JsonProperty("devices") + private List host; + + @JsonProperty("discovery_method") + private String discoveryMethod; + + public static ScanInfo createScanInfo(String vlanName, String ip, Date iniTimestampScan, String discoveryMethod) { + + ScanInfo scanInfo = new ScanInfo(); + scanInfo.setVlanName(vlanName); + scanInfo.setNodeIp(ip); + scanInfo.setIniTimestampScan(iniTimestampScan); + + scanInfo.setDiscoveryMethod(discoveryMethod); + + String ipAddress = ip.toString(); + String auxMac = null; + byte[] mac = null; + try { + + InetAddress add = InetAddress.getByName(ipAddress); + + NetworkInterface network = NetworkInterface.getByInetAddress(add); + + if(network != null) { + mac = network.getHardwareAddress(); + }else{ + auxMac = "unknown"; + } + }catch(UnknownHostException ue){ + // Handled + }catch(SocketException se){ + // Handled + } + + if(mac != null) { + + StringBuilder sb = new StringBuilder(); + + for (int i = 0; i < mac.length; i++) { + sb.append(String.format("%02X%s", mac[i], + (i < mac.length - 1) ? "-" : "")); + } + + scanInfo.setMacAddress(sb.toString()); + + }else{ + + scanInfo.setMacAddress(auxMac); + } + + return scanInfo; + } + + public static ScanInfo createScanInfo(String vlanName, String ip, Date iniTimestampScan, Date endTimestampScan, String discoveryMethod) { + + ScanInfo scanInfo = new ScanInfo(); + scanInfo.setVlanName(vlanName); + scanInfo.setNodeIp(ip); + scanInfo.setIniTimestampScan(iniTimestampScan); + scanInfo.setEndTimestampScan(endTimestampScan); + + scanInfo.setDiscoveryMethod(discoveryMethod); + + String ipAddress = ip.toString(); + String auxMac = null; + byte[] mac = null; + try { + + InetAddress add = InetAddress.getByName(ipAddress); + + NetworkInterface network = NetworkInterface.getByInetAddress(add); + + if(network != null) { + mac = network.getHardwareAddress(); + }else{ + auxMac = "unknown"; + } + }catch(UnknownHostException ue){ + // Handled + }catch(SocketException se){ + // Handled + } + + if(mac != null) { + + StringBuilder sb = new StringBuilder(); + + for (int i = 0; i < mac.length; i++) { + sb.append(String.format("%02X%s", mac[i], + (i < mac.length - 1) ? "-" : "")); + } + + scanInfo.setMacAddress(sb.toString()); + + }else{ + + scanInfo.setMacAddress(auxMac); + } + + return scanInfo; + } + +} + diff --git a/src/main/java/adt/entity/Vlan.java b/src/main/java/adt/entity/Vlan.java new file mode 100644 index 0000000000000000000000000000000000000000..bb02586f4a8d44330b26697c1d3bcab7573b03b1 --- /dev/null +++ b/src/main/java/adt/entity/Vlan.java @@ -0,0 +1,35 @@ +package adt.entity; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Getter; +import lombok.Setter; +import lombok.NoArgsConstructor; +import com.fasterxml.jackson.annotation.JsonIgnore; +import javax.persistence.Entity; +import javax.persistence.Id; + +@Entity +@Getter +@Setter +@NoArgsConstructor +public class Vlan { + + @Id + @JsonProperty("vlan_name") + String vlanName; + + //@JsonIgnore + Long delay; // Value in seconds + + /*@JsonProperty("node_ip") + String nodeIp;*/ + + String netAddress; + + //@JsonIgnore + String gateway; + + //@JsonIgnore + String mask; + +} diff --git a/src/main/java/adt/nmap/reader/NmapXmlReader.java b/src/main/java/adt/nmap/reader/NmapXmlReader.java new file mode 100644 index 0000000000000000000000000000000000000000..82388eae2d4ef96cd361494026f77a360b7d8aea --- /dev/null +++ b/src/main/java/adt/nmap/reader/NmapXmlReader.java @@ -0,0 +1,14 @@ +package adt.nmap.reader; + +import org.w3c.dom.Element; + +import java.util.List; + +public interface NmapXmlReader { + + void openFile(String fileName); + List getOpenPorts(); + List getServiceOnPort(); + Element getOperativeSystem(); + +} diff --git a/src/main/java/adt/nmap/reader/NmapXmlReaderImpl.java b/src/main/java/adt/nmap/reader/NmapXmlReaderImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..9f61cfab96251f9be3323a49f67aa7cc45e27d1b --- /dev/null +++ b/src/main/java/adt/nmap/reader/NmapXmlReaderImpl.java @@ -0,0 +1,127 @@ +package adt.nmap.reader; + +import lombok.extern.slf4j.Slf4j; +import net.bytebuddy.dynamic.scaffold.MethodGraph; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +@Slf4j +public class NmapXmlReaderImpl implements NmapXmlReader { + + private DocumentBuilderFactory factory; + private Document doc; + + @Override + public void openFile(String fileName) { + factory.setIgnoringElementContentWhitespace(true); + DocumentBuilder builder = getNewDocumentBuilder(factory); + + if (builder != null) { + Document doc = getNewDocument(builder, fileName); + if (doc != null) { + doc.getDocumentElement().normalize(); + this.doc = doc; + } + } + } + + private Document getNewDocument(DocumentBuilder builder, String fileName) { + File file = new File(fileName); + Document doc = null; + + try { + doc = builder.parse(file); + } catch (SAXException | IOException e) { + log.error("XML file {} does not have a correct structure.", fileName); + } + + return doc; + } + + private DocumentBuilder getNewDocumentBuilder(DocumentBuilderFactory factory) { + DocumentBuilder builder = null; + + try { + builder = factory.newDocumentBuilder(); + } catch (ParserConfigurationException e) { + e.printStackTrace(); + } + + return builder; + } + + @Override + public List getOpenPorts() { + + List elements = new ArrayList<>(); + NodeList elementsByTagName = doc.getElementsByTagName("port"); + + for (int i = 0; i < elementsByTagName.getLength(); i++) { + elements.add((Element) elementsByTagName.item(i)); + } + + return elements; + + } + + @Override + public List getServiceOnPort() { + + List elements = new ArrayList<>(); + Node node = doc.getElementsByTagName("port").item(0); + + NodeList childNodes = null; + + if(node != null) { + childNodes = node.getChildNodes(); + + for (int i = 0; i < childNodes.getLength(); i++) { + if ("state".equals(childNodes.item(i).getNodeName()) || "service".equals(childNodes.item(i).getNodeName())) + elements.add((Element) childNodes.item(i)); + } + + return elements; + } + + return null; + + } + + + @Override + public Element/*List*/ getOperativeSystem() { + + //List elements = new ArrayList<>(); + Element element = null; + NodeList elementsByTagName = doc.getElementsByTagName("osmatch"); + + /* + for (int i = 0; i < elementsByTagName.getLength(); i++) { + + elements.add((Element) elementsByTagName.item(i)); + + } + */ + + element = (Element) elementsByTagName.item(0); + + return element; + + } + + public NmapXmlReaderImpl() { + this.factory = DocumentBuilderFactory.newInstance(); + } + +} diff --git a/src/main/java/adt/nmap/runner/NmapRunner.java b/src/main/java/adt/nmap/runner/NmapRunner.java new file mode 100644 index 0000000000000000000000000000000000000000..aed1f7dafeb7da5a4e8bad05ed42e43edb4efb4e --- /dev/null +++ b/src/main/java/adt/nmap/runner/NmapRunner.java @@ -0,0 +1,17 @@ +package adt.nmap.runner; + +import org.w3c.dom.Element; + +import java.util.List; + +public interface NmapRunner { + + String PORTS_RESULTS_FILENAME_FORMAT = "open_ports_on_%s"; + String SERVICE_RUNNING_FILENAME_FORMAT = "service_running_on_port_%s_on_host_%s"; + //String OPERATIVE_SYSTEM_FILENAME_FORMAT = "os_running_on_%s"; + + List scanPortsOnHost(String ip); + List detectServiceRunningOnPort(String ip, String port); + //List detectOperativeSystem(String ip); + +} diff --git a/src/main/java/adt/nmap/runner/NmapRunnerImpl.java b/src/main/java/adt/nmap/runner/NmapRunnerImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..b8902baee550cb5ffdc843976cf6aa6f81450139 --- /dev/null +++ b/src/main/java/adt/nmap/runner/NmapRunnerImpl.java @@ -0,0 +1,82 @@ +package adt.nmap.runner; + +import adt.nmap.reader.NmapXmlReader; +import adt.nmap.reader.NmapXmlReaderImpl; +import lombok.extern.slf4j.Slf4j; +import org.w3c.dom.Element; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +@Slf4j +public class NmapRunnerImpl implements NmapRunner { + + @Override + public List scanPortsOnHost(String ip) { + + List result = new ArrayList<>(); + + String fileName = "/tmp/" + String.format(PORTS_RESULTS_FILENAME_FORMAT, ip); + + final String command = String.format("nmap -sT -T5 -p - %s -oX %s", ip, fileName); + Process process = getProcessFromCommand(command); + + if (process != null) { + + NmapXmlReader nmapXmlReader = new NmapXmlReaderImpl(); + nmapXmlReader.openFile(fileName); + result = nmapXmlReader.getOpenPorts(); + + } + + return result; + + } + + private Process getProcessFromCommand(String command) { + Process process = null; + try { + process = Runtime.getRuntime().exec(command); + process.waitFor(); + } catch (IOException | InterruptedException e) { + log.error("Command {} interrupted.", command); + } + + return process; + } + + + @Override + public List detectServiceRunningOnPort(String ip, String port) { + // Also allows to get OS info (-A option) + + List result = new ArrayList<>(); + + String fileName = "/tmp/" + String.format(SERVICE_RUNNING_FILENAME_FORMAT, ip, port); + + final String command = String.format("nmap -sV -O -T5 %s -p %s -oX %s", ip, port, fileName); + + Process process = getProcessFromCommand(command); + log.info("Service discovery for IP {} || PORT {} successfully completed.", ip, port); + if (process != null) { + NmapXmlReader nmapXmlReader = new NmapXmlReaderImpl(); + nmapXmlReader.openFile(fileName); + + result = nmapXmlReader.getServiceOnPort(); + + if(result != null) { + + Element os = nmapXmlReader.getOperativeSystem(); + if (os != null) { + result.add(os); + } + + } + } + log.info("Finished iteration for IP {} || PORT {} \n\n", ip, port); + return result; + } + + +} diff --git a/src/main/java/adt/repository/HostRepository.java b/src/main/java/adt/repository/HostRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..337aeacc912d0ac67889bce2fae43cf058c590c6 --- /dev/null +++ b/src/main/java/adt/repository/HostRepository.java @@ -0,0 +1,17 @@ +package adt.repository; + +import adt.entity.ScanInfo; +import adt.entity.Host; +import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; +import java.util.Date; + +public interface HostRepository extends JpaRepository { + + List findAllByVlanName(String VlanName); + List findAllByIp(String ip); + List findAllByVlanNameAndDiscoveryMethod(String VlanName, String discoveryMethod); + long deleteByDiscoveryMethod(String discoveryMethod); + long deleteAllByScanInfoAndDiscoveryMethod(ScanInfo scanInfo, String discoveryMethod); + List findAllByScanInfoAndDiscoveryMethod(ScanInfo scanInfo, String discoveryMethod); +} diff --git a/src/main/java/adt/repository/PortRepository.java b/src/main/java/adt/repository/PortRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..a0d736f1b925dab33b0d577cb1879e73d75f34e2 --- /dev/null +++ b/src/main/java/adt/repository/PortRepository.java @@ -0,0 +1,17 @@ +package adt.repository; + +import adt.entity.Host; +import adt.entity.Port; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; +import java.util.Date; + +public interface PortRepository extends JpaRepository { + + List findAllByHost(Host host); + List findAllByHostAndDiscoveryMethodTrigger(Host host, String discoveryMethod); + long deleteByDiscoveryMethodTrigger(String discoveryMethod); + long deleteAllByHostAndDiscoveryMethodTrigger(Host host, String discoveryMethod); + +} diff --git a/src/main/java/adt/repository/ScanInfoRepository.java b/src/main/java/adt/repository/ScanInfoRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..26f740dbd57be047e5eff4367daf8a2dffbf13e1 --- /dev/null +++ b/src/main/java/adt/repository/ScanInfoRepository.java @@ -0,0 +1,19 @@ +package adt.repository; + +import java.util.Date; +import adt.entity.ScanInfo; +import adt.entity.Host; +import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; + +public interface ScanInfoRepository extends JpaRepository { + + ScanInfo findFirstByDiscoveryMethodOrderByEndTimestampScan(String discoveryMethod); + List findByVlanNameIn(List vlan_names); + List findFirstByDiscoveryMethodAndVlanNameInOrderByEndTimestampScan(String discoveryMethod, List vlan_names); + long deleteByDiscoveryMethod(String discoveryMethod); + long deleteAllByIniTimestampScanAndDiscoveryMethod(Date time, String discoveryMethod); + + List findAllByIniTimestampScanAndDiscoveryMethod(Date iniTimestampScan, String discoveryMethod); + +} diff --git a/src/main/java/adt/repository/VlanRepository.java b/src/main/java/adt/repository/VlanRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..a73f5884ded75aa17448e836f5316daf03861ebf --- /dev/null +++ b/src/main/java/adt/repository/VlanRepository.java @@ -0,0 +1,7 @@ +package adt.repository; + +import adt.entity.Vlan; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface VlanRepository extends JpaRepository { +} diff --git a/src/main/java/adt/scanner/HostScanner.java b/src/main/java/adt/scanner/HostScanner.java new file mode 100644 index 0000000000000000000000000000000000000000..92f3e80c015bf3dc2186e1023e44ed9b05030c2f --- /dev/null +++ b/src/main/java/adt/scanner/HostScanner.java @@ -0,0 +1,465 @@ +package adt.scanner; + +import adt.entity.Host; +import java.util.*; +import adt.service.PortScannerService; +import adt.service.WrittingService; +import com.google.common.net.InetAddresses; +import java.net.NetworkInterface; +import com.stealthcopter.networktools.ARPInfo; +import lombok.extern.slf4j.Slf4j; +import lombok.Getter; +import java.util.concurrent.CountDownLatch; +import java.util.Stack; +import java.io.IOException; +import java.io.*; +import java.net.InetAddress; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.tomcat.jni.File; +import java.net.SocketException; +import java.util.function.Consumer; +import java.util.stream.Stream; + +@Slf4j +@Getter +public class HostScanner { + + private String subnetIPAddress; + private Integer subnetMask; + private int timeout; + private Consumer onHostFound; + private final PortScannerService portScannerService; + List hostsList; + + private String netAddress; + private String broadAddress; + + /** + * Performs host scan with {@code this} configuration + * @return + */ + public void scan() { + + getNetworkAndBroadcast(subnetIPAddress, subnetMask); + + CountDownLatch latch = new CountDownLatch((int) Math.pow(2, 32 - subnetMask) - 2); + ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool((int) Math.pow(2, 32 - subnetMask) - 1); + + generateIPs().forEach(addr -> executor.submit(() -> { + + // PUEDE QUE LO USEMOS: ip -o -f inet addr show | awk '/scope global/ {print $4}' > test.txt + if (addrIsReachable(addr, timeout) && !addr.getHostAddress().equals(netAddress) && !addr.getHostAddress().equals(broadAddress) ) { + + + // TimestampINI device + Date iniTimestamp_device = new Date(); + + String mac = ARPInfo.getMACFromIPAddress(addr.getHostAddress()); + log.info("MAC for this ip ({}): {}", addr.getHostAddress(), mac); + if (mac == null) { + + try { + mac = checkNetworkInterfaces(addr.getHostAddress()); + } catch (Exception e) { + + } + //log.info("No tenia pero ahora MAC for this ip ({}): {}", addr.getHostAddress(), mac); + } + + + Host host = Host.createHost(addr.getHostAddress(), addr.getCanonicalHostName(), mac, "scan"); + host.setTimestamp_ini(iniTimestamp_device); + + String macManufacturer = MacScanner.getMacScanner().getMacManufacturer(host); + host.setMacManufacturer(macManufacturer); + log.info("Host {} found with mac {} manufactured by {}", host.getIp(), host.getMac(), host.getMacManufacturer()); + + // Once found, scan this host's ports + portScannerService.scanHost(host, "scan"); + + synchronized (hostsList) { + hostsList.add(host); + } + + } + + latch.countDown(); + + })); + + try { + latch.await(); + } catch (InterruptedException E) { + // handle + } + + executor.shutdown(); + } + + /** + * + * @param addr The address to be checked + * @param timeout Timeout in miliseconds + * @return Whether {@code addr} is reachable or not + */ + private static boolean addrIsReachable(InetAddress addr, int timeout) { + + if(addr != null){ + try { + return addr.isReachable(timeout); + } catch (IOException e) { + //e.printStackTrace(); + //log.warn("SOCKET EXCEPTION HANDLED"); + } + } + return false; + } + + /** + * Callback method executed every time a new host is found. + * + * @param onHostFound Void function receiving a {@link adt.entity.Host Host} as a parameter + * @return {@code this} for chaining + */ + public HostScanner setOnHostFound(Consumer onHostFound) { + this.onHostFound = onHostFound; + return this; + } + + /** + * Set the timeout for {@code this} scanner. + * + * @param timeout Timeout in miliseconds + * @return {@code this} for chaining + */ + public HostScanner setTimeout(int timeout) { + if (timeout < 1) throw new IllegalArgumentException("Timeout must be an integer greater than 0."); + this.timeout = timeout; + return this; + } + + /** + * Generate all the possible IPs for {@code this} configuration. The stream generated will be limited to the maximum + * number of devices on the subnet specified to {@code this}. Also, the first address is skipped as it should be a + * network address. + * + * @return A spliterator for the generated stream + */ + private Stream generateIPs() { + long limit = (long) (Math.pow(2, 32 - subnetMask) - 1); + InetAddress firstAddress = InetAddresses.forString(subnetIPAddress); + + return Stream.iterate(firstAddress, InetAddresses::increment) + .limit(limit); + } + + /** + * @param subnetAddress A subnet address with or without mask specified from where the scan will start + * @return A new {@link HostScanner} + */ + public static HostScanner fromSubnetAddress(String subnetAddress, PortScannerService portScannerService) { + + String subnetIPAddress = subnetAddress; + int subnetMask = 24; + + if (subnetAddress.contains("/")) { + String[] split = subnetAddress.split("/"); + subnetIPAddress = split[0]; + subnetMask = Integer.parseInt(split[1]); + } + + if (!InetAddresses.isInetAddress(subnetIPAddress)) + throw new IllegalArgumentException(subnetIPAddress + " does not seem to be a valid IP address"); + + if (subnetMask < 0 || subnetMask > 32) + throw new IllegalArgumentException("/" + subnetMask + " is not a valid mask"); + + return new HostScanner(subnetIPAddress, subnetMask, portScannerService); + + } + + /** + * Creates a new {@link HostScanner} instance. + *

+ * {@code timeout} default value is 1000 + *
+ * {@code onHostFound} default value is {@code System.out::println} + * + * @param subnetIPAddress Subnet IP Address + * @param subnetMask Subnet mask + */ + private HostScanner(String subnetIPAddress, Integer subnetMask, PortScannerService portScannerService) { + this.subnetIPAddress = subnetIPAddress; + this.subnetMask = subnetMask; + this.timeout = 1000; + this.onHostFound = System.out::println; + this.portScannerService = portScannerService; + this.hostsList = new ArrayList<>(); + } + + private int[] bina(String[] str) + { + int re[] = new int[32]; + int a, b, c, d, i, rem; + a = b = c = d = 1; + Stack st = new Stack(); + + // Separate each number of the IP address + if (str != null) + { + a = Integer.parseInt(str[0]); + b = Integer.parseInt(str[1]); + c = Integer.parseInt(str[2]); + d = Integer.parseInt(str[3]); + } + + // convert first number to binary + for (i = 0; i <= 7; i++) + { + rem = a % 2; + st.push(rem); + a = a / 2; + } + + // Obtain First octet + for (i = 0; i <= 7; i++) { + re[i] = st.pop(); + } + + // convert second number to binary + for (i = 8; i <= 15; i++) { + rem = b % 2; + st.push(rem); + b = b / 2; + } + + // Obtain Second octet + for (i = 8; i <= 15; i++) { + re[i] = st.pop(); + } + + // convert Third number to binary + for (i = 16; i <= 23; i++) { + rem = c % 2; + st.push(rem); + c = c / 2; + } + + // Obtain Third octet + for (i = 16; i <= 23; i++) { + re[i] = st.pop(); + } + + // convert fourth number to binary + for (i = 24; i <= 31; i++) { + rem = d % 2; + st.push(rem); + d = d / 2; + } + + // Obtain Fourth octet + for (i = 24; i <= 31; i++) { + re[i] = st.pop(); + } + + return (re); + } + + // cls returns class of given IP address + private char cls(String[] str) + { + int a = Integer.parseInt(str[0]); + if (a >= 0 && a <= 127) + return ('A'); + else if (a >= 128 && a <= 191) + return ('B'); + else if (a >= 192 && a <= 223) + return ('C'); + else if (a >= 224 && a <= 239) + return ('D'); + else + return ('E'); + } + + // Converts IP address + // from binary to decimal form + private int[] deci(int[] bi) + { + + int[] arr = new int[4]; + int a, b, c, d, i, j; + a = b = c = d = 0; + j = 7; + + for (i = 0; i < 8; i++) { + + a = a + (int)(Math.pow(2, j)) * bi[i]; + j--; + } + + j = 7; + for (i = 8; i < 16; i++) { + + b = b + bi[i] * (int)(Math.pow(2, j)); + j--; + } + + j = 7; + for (i = 16; i < 24; i++) { + + c = c + bi[i] * (int)(Math.pow(2, j)); + j--; + } + + j = 7; + for (i = 24; i < 32; i++) { + + d = d + bi[i] * (int)(Math.pow(2, j)); + j--; + } + + arr[0] = a; + arr[1] = b; + arr[2] = c; + arr[3] = d; + return arr; + } + + private void getNetworkAndBroadcast(String ip, int mask){ + + int i; + String[] str = new String[4]; + + String tr = ip;//str1[0]; + + // Split IP address into 4 subparts x, y, z, t + str = tr.split("\\."); + + int[] b = new int[32]; + + // Convert IP address to binary form + b = bina(str); + + int n = mask;//Integer.parseInt(mask); + int[] ntwk = new int[32]; + int[] brd = new int[32]; + int t = 32 - n; + + // Obtanining network address + for (i = 0; i <= (31 - t); i++) { + + ntwk[i] = b[i]; + brd[i] = b[i]; + } + + // Set 32-n bits to 0 + for (i = 31; i > (31 - t); i--) { + + ntwk[i] = 0; + } + + // Obtaining Broadcast address + // by setting 32-n bits to 1 + for (i = 31; i > (31 - t); i--) { + + brd[i] = 1; + } + + // Converting network address to decimal + int[] nt = deci(ntwk); + + // Converting broadcast address to decimal + int[] br = deci(brd); + + + netAddress = nt[0] + "." + nt[1] + "." + nt[2] + "." + nt[3]; + + broadAddress = br[0] + "." + br[1] + "." + br[2] + "." + br[3]; + } + + + // UNUSED + private void checkARPTable(){ + + String[] arpCheck = {"arp", "-a"}; + try { + Process p = new ProcessBuilder(arpCheck).start(); + BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream())); + String arpOut = null; + + while ((arpOut = in.readLine()) != null) { + + log.info("FOUND MAC {}", arpOut); + } + }catch(Exception io){ + //handled + } + } + + /**************/ + public String checkNetworkInterfaces(String toMatch) throws SocketException { + Enumeration nets = NetworkInterface.getNetworkInterfaces(); + String mac = null; + for (NetworkInterface netint : Collections.list(nets)) { + mac = displayInterfaceInformation(netint, toMatch); + if (mac.length() > 0 ) { + break; + //return netName; + } + } + + return mac; + } + + /**************/ + public String displayInterfaceInformation(NetworkInterface netint, String toMatch) throws SocketException { + + Enumeration inetAddresses = netint.getInetAddresses(); + String matched = null; + String macToStore = ""; + for (InetAddress inetAddress : Collections.list(inetAddresses)) { + + if(inetAddress.getHostAddress().equals(toMatch)){ + + matched = netint.getName(); + + byte[] mac = netint.getHardwareAddress(); + + + if(mac != null) { + + for (int i = 0; i < mac.length; i++) { + + String toCheck = Integer.toHexString(mac[i]); + if(toCheck.length() > 2){ + + toCheck = toCheck.substring(toCheck.length()-3, toCheck.length()-1); + } + + if(i < mac.length-1){ + macToStore = macToStore + toCheck + ":"; + }else{ + macToStore = macToStore + toCheck; + } + } + + } + + break; + } + } + + return macToStore; + } + + + +} + + diff --git a/src/main/java/adt/scanner/MacScanner.java b/src/main/java/adt/scanner/MacScanner.java new file mode 100644 index 0000000000000000000000000000000000000000..5cbd961ae7dee0e00e167e3d6b05085e652b57d9 --- /dev/null +++ b/src/main/java/adt/scanner/MacScanner.java @@ -0,0 +1,49 @@ +package adt.scanner; + +import adt.entity.Host; +import com.martiansoftware.macnificent.MacAddress; +import com.martiansoftware.macnificent.Oui; +import com.martiansoftware.macnificent.OuiRegistry; +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; +import java.io.InputStream; + +@Slf4j +public class MacScanner { + + private static MacScanner MAC_SCANNER = null; + private OuiRegistry ouiRegistry; + + public synchronized static MacScanner getMacScanner() { + if (MAC_SCANNER == null) { + MAC_SCANNER = new MacScanner(); + } + return MAC_SCANNER; + } + + public String getMacManufacturer(Host host) { + + if (host.getMac() != null && host.getMac().length() > 0 && !host.getMac().equals("null")) { + MacAddress macAddress = new MacAddress(host.getMac()); + if (!macAddress.toString().equals("null")){ + Oui oui = ouiRegistry.getOui(macAddress); + if (oui != null) + return oui.getManufacturer(); + } + } + + return null; + + } + + private MacScanner() { + InputStream ouiData = getClass().getClassLoader().getResourceAsStream("macnificent.dat"); + try { + this.ouiRegistry = new OuiRegistry(ouiData); + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/main/java/adt/scanner/PortScanner.java b/src/main/java/adt/scanner/PortScanner.java new file mode 100644 index 0000000000000000000000000000000000000000..71f4b367396c803dba6df4a8f1a230ae0703d2ab --- /dev/null +++ b/src/main/java/adt/scanner/PortScanner.java @@ -0,0 +1,116 @@ +package adt.scanner; + +import adt.entity.Host; +import adt.entity.Port; +import adt.nmap.runner.NmapRunner; +import adt.nmap.runner.NmapRunnerImpl; +import lombok.extern.slf4j.Slf4j; +import org.w3c.dom.Element; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; + +@Slf4j +public class PortScanner { + + private final List hosts; + private Host host; + private long timeout; + private Consumer onPortFound; + + + public List scan(Host host, String discMethod) { + + List portsList = new ArrayList<>(); + + NmapRunner nmapRunner = new NmapRunnerImpl(); + List portsOpen = nmapRunner.scanPortsOnHost(host.getIp()); + + log.info("Scanning {} ports for {}", portsOpen.size(), host.getIp()); + + portsOpen.forEach(element -> { + Port port = Port.createPort(element.getAttribute("portid"), host, element.getAttribute("protocol"), discMethod); + + log.info("Port {} found running on host {}", port.getPortNumber(), port.getHost().getIp()); + + List service = nmapRunner.detectServiceRunningOnPort(port.getHost().getIp(), port.getPortNumber()); + + if(service != null){ + + service.forEach(serviceDetails -> { + + switch (serviceDetails.getNodeName()) { + case "state": + port.setState(serviceDetails.getAttribute("state")); + break; + case "service": + port.setServiceRunning(serviceDetails.getAttribute("product")); + port.setServiceVersion(serviceDetails.getAttribute("version")); + port.setDiscoveryMethod(serviceDetails.getAttribute("method")); + break; + case "osmatch": + host.setOperatingSystem(serviceDetails.getAttribute("name")); + break; + default: + break; + } + }); + + portsList.add(port); + } + + }); + + Date endTimestamp_device = new Date(); + host.setTimestamp_end(endTimestamp_device); + + return portsList; + } + + + + /** + * + * @param onPortFound Callback function to be called every time a port is found + * @return this for chaining + */ + public PortScanner setOnPortFound(Consumer onPortFound) { + this.onPortFound = onPortFound; + return this; + } + + /** + * + * @param timeout Waiting time in SECONDS. + * @return this for chaining + */ + public PortScanner setTimeout(long timeout) { + this.timeout = timeout; + return this; + } + + public static PortScanner fromHosts(List hosts) { + return new PortScanner(hosts); + } + + public static PortScanner fromUniqueHost(Host host) { + return new PortScanner(host); + } + + private PortScanner(List hosts) { + this.hosts = hosts; + this.onPortFound = System.out::println; + } + + private PortScanner(Host host) { + this.host = host; + this.hosts = null; + this.onPortFound = System.out::println; + } + +} diff --git a/src/main/java/adt/service/HostScannerService.java b/src/main/java/adt/service/HostScannerService.java new file mode 100644 index 0000000000000000000000000000000000000000..4d38a8049fc72f85408fcf800eec8bf5a7848d52 --- /dev/null +++ b/src/main/java/adt/service/HostScannerService.java @@ -0,0 +1,69 @@ +package adt.service; + +import adt.entity.Host; +import adt.entity.Port; +import adt.repository.HostRepository; +import adt.repository.PortRepository; +import adt.scanner.HostScanner; +import adt.scanner.MacScanner; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +@Slf4j +public class HostScannerService { + + private final HostRepository hostRepository; + private final PortRepository portRepository; + private final PortScannerService portScannerService; + private final WrittingService writtingService; + + @Value("${vlan.address}") + private String vlanAddress; + @Value("${vlan.mask}") + private String vlanMask; + + @Autowired + public HostScannerService(HostRepository hostRepository, PortRepository portRepository, PortScannerService portScannerService, WrittingService writtingService) { + this.hostRepository = hostRepository; + this.portRepository = portRepository; + this.portScannerService = portScannerService; + this.writtingService = writtingService; + } + + + void scanNetwork(String vlanName, String netAddress, String mask) { + + HostScanner hostScanner = HostScanner.fromSubnetAddress(String.format("%s/%s", netAddress, mask/*vlanAddress, vlanMask*/), portScannerService); + hostScanner.setTimeout(5000) + .setOnHostFound(this::onHostFound) + .scan(); + + List hostsList = hostScanner.getHostsList(); + + for(int i=0; i { + + @Value("${token}") + private String token; + + @Value("${output.path}") + private String outputPath; + + @Value("${execution.mode}") + private String executionMode; + + private final SendAssetService sendAssetService; + private final ScheduleService scheduleService; + private final OsDetectorService osDetectorService; + + private final WrittingService writtingService; + + private final PortScannerService portScannerService; + + private final VlanRepository vlanRepository; + private final HostRepository hostRepository; + private final PortRepository portRepository; + private final ScanInfoRepository scanInfoRepository; + + ////// MAIN NODE COMMUNICATION + private final MainNodeClient mainNodeClient; + private final MainNodeCom mainNodeCom; + + + @Autowired + public OnStartupService(ScanInfoRepository scanInfoRepository, PortRepository portRepository, + HostRepository hostRepository, PortScannerService portScannerService, + SendAssetService sendAssetService, ScheduleService scheduleService, + OsDetectorService osDetectorService, WrittingService writtingService, + VlanRepository vlanRepository, MainNodeClient mainNodeClient, + MainNodeCom mainNodeCom) { + + this.scanInfoRepository = scanInfoRepository; + this.portRepository = portRepository; + this.sendAssetService = sendAssetService; + this.hostRepository = hostRepository; + this.scheduleService = scheduleService; + this.osDetectorService = osDetectorService; + this.writtingService = writtingService; + this.portScannerService = portScannerService; + this.vlanRepository = vlanRepository; + + ////// MAIN NODE COMMUNICATION + this.mainNodeClient = mainNodeClient; + this.mainNodeCom = mainNodeCom; + } + + + @Override + public void onApplicationEvent(@NonNull ApplicationReadyEvent event) { + + Node node = initialize(); + + List vlanIps = new ArrayList(); + + for(Vlan vlan: node.getVlan()){ + + String [] toAdd = {vlan.getNetAddress(), vlan.getVlanName()}; + vlanIps.add(toAdd); + } + + launchDHCPDiscovery(vlanIps, node.getIp()); + + vlanRepository.saveAll(node.getVlan()); + + sendAssetService.sendAssets(true, null);//, "scan"); + + scheduleService.scheduleSetUp(node); + } + + + private Node initialize() { + + //Node node = mainNodeClient.initialize(token); + + Node node = mainNodeCom.initialize(token); + + if(node == null){ + log.error("[--INITIALIZATION PROCESS--] Unrecognized token. Aborting execution."); + System.exit(0); + } + + log.info("[--INITIALIZATION PROCESS--] Successfully obtained a scanning configuration."); + + return node; + } + + + private void launchDHCPDiscovery(List info, String nodeIp){ + + for(int i=0; i < info.size(); i++) { + + String[] infoDetail = info.get(i); + TCPDumpThread tcpDumpThread = new TCPDumpThread(token, mainNodeCom, sendAssetService, portScannerService, nodeIp, infoDetail[0], infoDetail[1], hostRepository, portRepository, scanInfoRepository); + tcpDumpThread.start(); + } + } + + +} diff --git a/src/main/java/adt/service/OsDetectorService.java b/src/main/java/adt/service/OsDetectorService.java new file mode 100644 index 0000000000000000000000000000000000000000..7a14191caaf6f52bb9f3bfaa0ba1a306a1bdea2c --- /dev/null +++ b/src/main/java/adt/service/OsDetectorService.java @@ -0,0 +1,46 @@ +package adt.service; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Service +@Slf4j +public class OsDetectorService { + + private static String OS = System.getProperty("os.name").toLowerCase(); + + public enum OperatingSystem { + WINDOWS, MAC, UNIX, SOLARIS, UNKNOWN + } + + public static boolean isWindows() { + return (OS.contains("win")); + } + + public static boolean isMac() { + return (OS.contains("mac")); + } + + public static boolean isUnix() { + return (OS.contains("nix") || OS.contains("nux") || OS.indexOf("aix") > 0); + } + + public static boolean isSolaris() { + return (OS.contains("sunos")); + } + + OperatingSystem getOS() { + if (isWindows()) + return OperatingSystem.WINDOWS; + if (isMac()) + return OperatingSystem.MAC; + if (isUnix()) + return OperatingSystem.UNIX; + if (isSolaris()) + return OperatingSystem.SOLARIS; + else + return OperatingSystem.UNKNOWN; + } + + // ip r | grep -E 'default.*wlp3s0' +} diff --git a/src/main/java/adt/service/PortScannerService.java b/src/main/java/adt/service/PortScannerService.java new file mode 100644 index 0000000000000000000000000000000000000000..761a005c5ba3666ce27cd97344f1f7ce8ca9f9c3 --- /dev/null +++ b/src/main/java/adt/service/PortScannerService.java @@ -0,0 +1,92 @@ +package adt.service; + +import adt.entity.Host; +import adt.entity.Port; +import adt.nmap.runner.NmapRunner; +import adt.nmap.runner.NmapRunnerImpl; +import adt.repository.PortRepository; +import adt.scanner.PortScanner; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.w3c.dom.Element; + +import java.util.List; +import lombok.Getter; +import lombok.Setter; + +@Service +@Slf4j +@Getter +@Setter +public class PortScannerService { + + private final PortRepository portRepository; + + private List portList; + + private List portListDHCP; + + @Value("${vlan.port_timeout}") + private long timeout; + + @Autowired + public PortScannerService(PortRepository portRepository, List portList, List portListDHCP) { + this.portRepository = portRepository; + this.portList = portList; + this.portListDHCP = portListDHCP; + } + + public void scanHost(Host host, String discMethod) { + + log.info("Starting port scanning from host {}", host.getIp()); + List aux = PortScanner.fromUniqueHost(host) + .setOnPortFound(this::onPortFound) + .setTimeout(timeout) + .scan(host, discMethod); + log.info("Port scanning from host {} successfully finished.", host.getIp()); + + if( discMethod == "dhcp") { + + try { + synchronized (portListDHCP) { + portListDHCP.addAll(aux); + } + }catch(Exception e){ + log.info("[RUNTIME ERROR --PORT SCANNER SERVICE--] --- {}", e); + } + + }else if( discMethod == "scan") { + + synchronized (portList) { + portList.addAll(aux); + } + + } + } + + + private void onPortFound(Port port) { + + log.info("Port {} found running on host {}", port.getPortNumber(), port.getHost().getIp()); + + NmapRunner nmapRunner = new NmapRunnerImpl(); + List service = nmapRunner.detectServiceRunningOnPort(port.getHost().getIp(), port.getPortNumber()); + + service.forEach(element -> { + switch (element.getNodeName()) { + case "state": + port.setState(element.getAttribute("state")); + case "service": + port.setServiceRunning(element.getAttribute("product")); + port.setServiceVersion(element.getAttribute("version")); + port.setDiscoveryMethod(element.getAttribute("method")); + } + }); + + portRepository.save(port); + } + + +} diff --git a/src/main/java/adt/service/ScheduleService.java b/src/main/java/adt/service/ScheduleService.java new file mode 100644 index 0000000000000000000000000000000000000000..44b154c1a9a573a92902434e891947d84364d0de --- /dev/null +++ b/src/main/java/adt/service/ScheduleService.java @@ -0,0 +1,172 @@ +package adt.service; + +import adt.client.MainNodeClient; +import adt.entity.Port; +import adt.entity.ScanInfo; +import adt.entity.Vlan; +import adt.dto.Node; +import adt.repository.PortRepository; +import adt.repository.ScanInfoRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + + +import java.util.concurrent.CountDownLatch; + +import java.io.IOException; +import java.net.InetAddress; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; +import java.util.stream.Stream; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.ExecutionException; +import java.lang.InterruptedException; +import java.lang.Thread; +import lombok.extern.slf4j.Slf4j; + +@Service +@Slf4j +public class ScheduleService { + + private final MainNodeClient mainNodeClient; + private final HostScannerService hostScannerService; + private final PortScannerService portScannerService; + private final SendAssetService sendAssetService; + + private final ScanInfoRepository scanInfoRepository; + private final PortRepository portRepository; + + private List vlan; + private Node node; + + private ScheduledExecutorService scheduledExecutorService; + private ScheduledFuture futureTask; + private Runnable task; + + private Long prevSystemDelay; + private Long iniExecutionTime; + + + private class ScheduledTask implements Runnable { + + @Override + public void run() { + + log.info("NEW EXECUTION SCHEDULED. Number of Vlans to scan: {}", vlan.size()); + iniExecutionTime = System.currentTimeMillis(); + + CountDownLatch latch = new CountDownLatch(vlan.size()); + ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(vlan.size()); + + // Timestamp ini + Date iniTimestamp_scan = new Date(); + + vlan.forEach(element -> executor.submit(() -> { + + log.info("Vlan address ready to scan: " + element.getNetAddress()); + + hostScannerService.scanNetwork(element.getVlanName(), element.getNetAddress(), element.getMask()); + log.info("SCANNING OF NETWORK {} SUCCESSFULLY COMPLETED", element.getNetAddress()); + + Date endTimestamp_scan = new Date(); + + ScanInfo scanInfo = ScanInfo.createScanInfo(element.getVlanName(), node.getIp(), iniTimestamp_scan, endTimestamp_scan, "scan"); + + scanInfoRepository.save(scanInfo); + + latch.countDown(); + + })); + + try { + latch.await(); + } catch (InterruptedException E) { + // handle + } + executor.shutdown(); + + List ports = portScannerService.getPortList(); + + portRepository.saveAll(ports); + + //boolean iniFlag = false; + + log.info("All networks have been successfully scanned and its assets detected. Now managing this information...\n"); + Long systemDelay = sendAssetService.sendAssets(false, vlan);//, "scan"); + + boolean flag = true; + if(systemDelay == null){ + flag = false; + }else { + flag = !Long.toString(systemDelay).equals(Long.toString(vlan.get(0).getDelay())); + } + if( flag ){ + + futureTask.cancel(false); + prevSystemDelay = vlan.get(0).getDelay(); + + + log.info("ATTENTION, a new execution delay has been set for this scanning process.\n--Previous: {} seconds.\n--New: {} seconds.\nNext iterations will use this new delay.\n", vlan.get(0).getDelay(), systemDelay); + + vlan.get(0).setDelay(systemDelay); // PONERSELO A TODOS + + /* At this point in the execution, it is guaranteed that the futureTask's thread has finished, so it is safely cancelled and we can schedule a new futureTask. */ + scheduleSetUp(node); + } + + } + } + + @Autowired + public ScheduleService(HostScannerService hostScannerService, PortRepository portRepository,PortScannerService portScannerService, SendAssetService sendAssetService, MainNodeClient mainNodeClient, ScanInfoRepository scanInfoRepository) { + this.mainNodeClient = mainNodeClient; + this.hostScannerService = hostScannerService; + this.sendAssetService = sendAssetService; + this.portRepository = portRepository; + this.portScannerService = portScannerService; + this.scanInfoRepository = scanInfoRepository; + scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); + + task = new ScheduledTask(); + } + + void scheduleSetUp(Node node) { + + if (this.vlan == null){ + this.node = node; + this.vlan = node.getVlan(); + } + + if(this.prevSystemDelay != null){ + + Long diff = (System.currentTimeMillis() - this.iniExecutionTime) / 1000; + if( (diff) < this.prevSystemDelay ){ + + Long remaining = (this.prevSystemDelay - diff) * 1000; + log.info("Stalling execution until a delay of " + this.prevSystemDelay + " seconds between tasks is satisfied.\n--Time already covered: " + diff + " seconds.\n--Remaining: " + (remaining/1000) + " seconds."); + log.info("Stalling execution until a delay of {} seconds between tasks is satisfied.\n--Time already covered: {} seconds.\n--Remaining: {} seconds.", this.prevSystemDelay, diff, (remaining/1000)); + + try{ + Thread.sleep(remaining); + }catch(InterruptedException ie){ + // Handled exception + } + + } + + this.prevSystemDelay = null; + } + + log.info("VLAN DELAY INFO: {} seconds.", vlan.get(0).getDelay()); + + + futureTask = scheduledExecutorService.scheduleAtFixedRate(task, 0, vlan.get(0).getDelay(), TimeUnit.SECONDS); + } + +} diff --git a/src/main/java/adt/service/SendAssetService.java b/src/main/java/adt/service/SendAssetService.java new file mode 100644 index 0000000000000000000000000000000000000000..ec28de6a0871948e83b8179a3e2eb34e7107007b --- /dev/null +++ b/src/main/java/adt/service/SendAssetService.java @@ -0,0 +1,265 @@ +package adt.service; + +import adt.client.MainNodeClient; +import adt.client.MainNodeCom; +import adt.dto.Asset; +import adt.dto.Node; +import adt.dto.ScanInfoDto; +import adt.entity.ScanInfo; +import adt.entity.Host; +import adt.entity.Vlan; +import adt.entity.Port; +import adt.repository.HostRepository; +import adt.repository.PortRepository; +import adt.repository.ScanInfoRepository; +import adt.repository.VlanRepository; +import com.google.common.net.InetAddresses; +import com.netflix.hystrix.exception.HystrixRuntimeException; +import lombok.extern.slf4j.Slf4j; +import org.hibernate.mapping.Array; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.io.IOException; +import java.net.InetAddress; +import java.util.List; +import java.util.ArrayList; +import java.util.stream.Collectors; +import java.util.Date; + +@Service +@Slf4j +public class SendAssetService { + + private final MainNodeClient mainNodeClient; + private final MainNodeCom mainNodeCom; + private final HostRepository hostRepository; + private final PortRepository portRepository; + private final VlanRepository vlanRepository; + private final ScanInfoRepository scanInfoRepository; + private final VlanService vlanService; + private final WrittingService writtingService; + + //@Value("${vlan.name}") + //private String vlanName; + + @Value("${token}") + private String token; + + @Value("${execution.mode}") + private String executionMode; + + @Value("${output.path}") + private String outputPath; + + @Value("${main.node.address}") + private String mainNode_ip; + + @Autowired + public SendAssetService(MainNodeCom mainNodeCom, MainNodeClient mainNodeClient, HostRepository hostRepository, PortRepository portRepository, VlanRepository vlanRepository, ScanInfoRepository scanInfoRepository, VlanService vlanService, WrittingService writtingService) { + this.mainNodeCom = mainNodeCom; + this.mainNodeClient = mainNodeClient; + this.hostRepository = hostRepository; + this.portRepository = portRepository; + this.vlanRepository = vlanRepository; + this.scanInfoRepository = scanInfoRepository; + this.vlanService = vlanService; + this.writtingService = writtingService; + } + + Long sendAssets(boolean iniFlag, List vlan){//, String discoveryMethod) { + + String discoveryMethod = "scan"; + + List scansToSend = new ArrayList<>(); + + if(iniFlag){ + ScanInfo check = scanInfoRepository.findFirstByDiscoveryMethodOrderByEndTimestampScan(discoveryMethod); + if(check != null) { + scansToSend.add(check); + } + }else{ + + List vlan_names = new ArrayList<>(); + /* May re-implement later. Seems to be quite inefficient. */ + for (int i = 0; i < vlan.size(); i++) { + + vlan_names.add(vlan.get(i).getVlanName()); + } + + List check = scanInfoRepository.findFirstByDiscoveryMethodAndVlanNameInOrderByEndTimestampScan(discoveryMethod, vlan_names);//findByVlanNameIn(vlan_names);//scanInfoRepository.findAll(); + + /*log.info("##################################"); + for(int i=0; i 0 && iniFlag == false) { + + scansToSend.forEach(element -> { + //List hosts = hostRepository.findAll(); + List hosts = hostRepository.findAllByVlanNameAndDiscoveryMethod(element.getVlanName(), discoveryMethod); + + for (int i = 0; i < hosts.size(); i++) { + + List ports = portRepository.findAllByHostAndDiscoveryMethodTrigger(hosts.get(i), discoveryMethod); + + //log.info("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!{}", ports.size()); + hosts.get(i).setPorts(ports); + } + + element.setHost(hosts); + }); + + Asset asset = Asset.createAsset(scansToSend, discoveryMethod); + + if (executionMode.equals("manual")) { + + log.info("[Manual mode execution] Assets will not be sent to Main Node. Storing data in this path: {}assets_info.json", outputPath); + writtingService.writeJSONOutput(outputPath + "assets_info.json", asset); + } else { + + log.info("[Automatic mode execution] Assets will be sent to Main Node. Communicating with its endpoints..."); + try { + //newDelay = mainNodeClient.sendAssets(/*vlanName,*/ asset, token); + newDelay = mainNodeCom.sendAssets(asset, token); + } catch (Exception e){//HystrixRuntimeException ex) { + // handle hystrix exception here + log.info("exception{}", e); + // log.warn("{}",ex);//""Unable to connect with REST API. Scanning results have been stored and will be sent when connection is restablished."); + } + + if (newDelay != null) { + + log.info("Assets successfully sent!\n"); + /*portRepository.deleteAll(); + hostRepository.deleteAll(); + scanInfoRepository.deleteAll();*/ + /*try { + portRepository.deleteByDiscoveryMethodTrigger(discoveryMethod); + hostRepository.deleteByDiscoveryMethod(discoveryMethod); + scanInfoRepository.deleteByDiscoveryMethod(discoveryMethod); + }catch (Exception e){ + log.warn("_______{}",e); + }*/ + log.info("The delay value received from ADT Main Node is of " + newDelay + " seconds.\n"); + } + } + + } + + if(iniFlag){ + + log.info("STARTUP PROCESS COMPLETED SUCCESFULLY. Initiating scanning process...\n\n"); + }else { + + if (newDelay != null){ + + log.info("ITERATION SUCCESSFULLY COMPLETED. Preparing for next one...\n\n"); + }else{ + + log.info("Communication with ADT's Main Node was not possible. Scanning results will be stored and sent when possible.\n\n"); + } + } + return newDelay; + } + + + + public Long sendAssetsDHCP(String vlan_id, String discoveryMethod, Date time) { + + List check = null; + try { + check = scanInfoRepository.findAllByIniTimestampScanAndDiscoveryMethod(time, "dhcp");//findByVlanNameIn(vlan_names);//scanInfoRepository.findAll(); + }catch(Exception e){ + log.info("########{}", e); + } + + /*for(int i=0; i hosts = hostRepository.findAll(); + List host = null; + try{ + host = hostRepository.findAllByScanInfoAndDiscoveryMethod(check.get(0), "dhcp"); + }catch(Exception e){ + log.info("########{}", e); + } + + List ports = null; + try{ + ports = portRepository.findAllByHostAndDiscoveryMethodTrigger(host.get(0), "dhcp"); + }catch(Exception e){ + log.info("########{}", e); + } + host.get(0).setPorts(ports); + + List hosts = new ArrayList<>(); + hosts.add(host.get(0)); + + check.get(0).setHost(hosts); + + List scansToSend = new ArrayList<>(); + scansToSend.add(check.get(0)); + + Asset asset = Asset.createAsset(scansToSend, discoveryMethod); + + Long newDelay = null; + + if (executionMode.equals("manual")) { + + log.info("[Manual mode execution] Assets will not be sent to Main Node. Storing data in this path: {}assets_info.json", outputPath); + writtingService.writeJSONOutput(outputPath + "dhcp_assets_info.json", asset); + } else { + + writtingService.writeJSONOutput("./dhcp_assets_info"+ time.toString() +".json", asset); + + log.info("[Automatic mode execution] Assets will be sent to Main Node. Communicating with its endpoints..."); + + newDelay = mainNodeCom.sendAssets(asset, token); + /*try { + + } catch (HystrixRuntimeException ex) { + // handle hystrix exception here + // log.warn("{}",ex);//""Unable to connect with REST API. Scanning results have been stored and will be sent when connection is restablished."); + }*/ + + if (newDelay != null) { + + log.info("Assets successfully sent!\n"); + /*portRepository.deleteAll(); + hostRepository.deleteAll(); + scanInfoRepository.deleteAll(); + + hostRepository.deleteAllByScanInfoAndDiscoveryMethod(check.get(0), "dhcp"); + portRepository.deleteAllByHostAndDiscoveryMethodTrigger(host.get(0), "dhcp"); + scanInfoRepository.deleteAllByIniTimestampScanAndDiscoveryMethod(time, discoveryMethod); + */ + //log.info("The delay value received from ADT Main Node is of " + newDelay + " seconds.\n"); + } + } + + if (newDelay != null){ + + //log.info("DHCP ITERATION SUCCESSFULLY COMPLETED. Preparing for next one...\n\n"); + }else{ + + log.info("Communication with ADT's Main Node was not possible. DHCP Scanning results will be stored and sent when possible.\n\n"); + } + + return newDelay; + } + +} diff --git a/src/main/java/adt/service/VlanService.java b/src/main/java/adt/service/VlanService.java new file mode 100644 index 0000000000000000000000000000000000000000..6ec0da1f4cbd8785664892f1e1d726e5d3922f8d --- /dev/null +++ b/src/main/java/adt/service/VlanService.java @@ -0,0 +1,22 @@ +package adt.service; + +import adt.entity.Vlan; +import adt.repository.VlanRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class VlanService { + + private final VlanRepository vlanRepository; + + @Autowired + public VlanService(VlanRepository vlanRepository) { + this.vlanRepository = vlanRepository; + } + + public Vlan saveConfig(Vlan vlan) { + return vlanRepository.save(vlan); + } + +} diff --git a/src/main/java/adt/service/WrittingService.java b/src/main/java/adt/service/WrittingService.java new file mode 100644 index 0000000000000000000000000000000000000000..f8b8520bffc046066641a8f8edceb89fae7ea808 --- /dev/null +++ b/src/main/java/adt/service/WrittingService.java @@ -0,0 +1,59 @@ +package adt.service; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectWriter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import com.fasterxml.jackson.databind.*; +import org.json.JSONObject; +import com.fasterxml.jackson.core.JsonProcessingException; +import java.io.FileWriter; +import java.io.IOException; + +@Service +public class WrittingService { + + private ObjectWriter ow; + + @Value("${output.path}") + private String outputPath; + + @Autowired + public WrittingService() { + this.ow = new ObjectMapper().writer().withDefaultPrettyPrinter(); + } + + + public void writeJSONOutput(String filename, Object o) { + + ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter(); + + JSONObject json = null; + try { + json = new JSONObject(ow.writeValueAsString(o));//ow.writeValueAsString(vlan); + + }catch (JsonProcessingException e){ + // Handled exception + } + + if(json != null) { + + String myFile = outputPath + filename; + + try (FileWriter file = new FileWriter(myFile, true)) { + + file.write(json.toString()); + file.write("\n\n"); + System.out.println("Successfully Copied JSON Object to file " + myFile); + + }catch(IOException e){ + // Handled exception + } + } + + } + + +} diff --git a/src/main/java/adt/tcpdump/TCPDumpThread.java b/src/main/java/adt/tcpdump/TCPDumpThread.java new file mode 100644 index 0000000000000000000000000000000000000000..7c702096fcac38e23a3e0388f923d081b3cca6c9 --- /dev/null +++ b/src/main/java/adt/tcpdump/TCPDumpThread.java @@ -0,0 +1,53 @@ +package adt.tcpdump; + +import java.lang.Thread; +import adt.tcpdump.runner.TCPDumpRunner; +import adt.tcpdump.runner.TCPDumpRunnerImpl; +import adt.repository.HostRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import adt.repository.*; +import adt.service.PortScannerService; +import adt.service.SendAssetService; +import adt.client.MainNodeCom; +import org.springframework.beans.factory.annotation.Value; + +//@Service +public class TCPDumpThread extends Thread { + + private String token; + private final MainNodeCom mainNodeCom; + private final PortScannerService portScannerService; + private final SendAssetService sendAssetService; + private String ip; + private String vlanName; + private String nodeIp; + + private final PortRepository portRepository; + private final ScanInfoRepository scanInfoRepository; + private final HostRepository hostRepository; + + @Autowired + public TCPDumpThread(String token, MainNodeCom mainNodeCom, SendAssetService sendAssetService, PortScannerService portScannerService, String nodeIp, String ip, String vlanName, HostRepository hostRepository, PortRepository portRepository, ScanInfoRepository scanInfoRepository) { + + this.token = token; + this.scanInfoRepository = scanInfoRepository; + this.portRepository = portRepository; + this.hostRepository = hostRepository; + this.nodeIp = nodeIp; + this.mainNodeCom = mainNodeCom; + this.ip = ip; + this.vlanName = vlanName; + this.sendAssetService = sendAssetService; + this.portScannerService = portScannerService; + } + + @Override + public void run() { + + TCPDumpRunner tcpRunner = new TCPDumpRunnerImpl(mainNodeCom, sendAssetService, portScannerService, nodeIp, token, ip, vlanName, hostRepository, portRepository, scanInfoRepository); + tcpRunner.sniffTraffic(); + } + + +} \ No newline at end of file diff --git a/src/main/java/adt/tcpdump/runner/TCPDumpRunner.java b/src/main/java/adt/tcpdump/runner/TCPDumpRunner.java new file mode 100644 index 0000000000000000000000000000000000000000..cb370e989173cbd3f99cf7ae9f85d702bb8f844f --- /dev/null +++ b/src/main/java/adt/tcpdump/runner/TCPDumpRunner.java @@ -0,0 +1,13 @@ +package adt.tcpdump.runner; + +import org.w3c.dom.Element; + +import java.util.List; + +public interface TCPDumpRunner { + + String DHCP_RESULTS_FILENAME_FORMAT = "dhcp_sniff"; + + void sniffTraffic(/*String ip*/); + +} diff --git a/src/main/java/adt/tcpdump/runner/TCPDumpRunnerImpl.java b/src/main/java/adt/tcpdump/runner/TCPDumpRunnerImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..4d8eec9061079842fb4b34e7cf8994dda333566f --- /dev/null +++ b/src/main/java/adt/tcpdump/runner/TCPDumpRunnerImpl.java @@ -0,0 +1,247 @@ +package adt.tcpdump.runner; + +import adt.nmap.reader.NmapXmlReader; +import adt.nmap.reader.NmapXmlReaderImpl; +import lombok.extern.slf4j.Slf4j; +import org.w3c.dom.Element; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import adt.repository.*; +import java.lang.ProcessBuilder; +import java.lang.Process; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.IOException; +import java.lang.Exception; + +import adt.repository.HostRepository; +import adt.entity.Host; +import adt.entity.Port; +//import adt.client.MainNodeClient; +import adt.client.MainNodeCom; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; + +import adt.service.PortScannerService; +import adt.service.SendAssetService; + +import java.io.*; +import java.net.*; +import java.util.*; +import adt.entity.ScanInfo; + +@Slf4j +public class TCPDumpRunnerImpl implements TCPDumpRunner { + + //private final MainNodeClient mainNodeClient; + private final MainNodeCom mainNodeCom; + + private final PortScannerService portScannerService; + private final SendAssetService sendAssetService; + + private String token; + + private String ip; + + private String vlanName; + + private String nodeIp; + + private final PortRepository portRepository; + private final ScanInfoRepository scanInfoRepository; + private final HostRepository hostRepository; + + @Autowired + public TCPDumpRunnerImpl(MainNodeCom mainNodeCom, SendAssetService sendAssetService, PortScannerService portScannerService, + String nodeIp, String token, String ip, String vlanName, HostRepository hostRepository, + PortRepository portRepository, ScanInfoRepository scanInfoRepository) { + + this.scanInfoRepository = scanInfoRepository; + this.portRepository = portRepository; + this.hostRepository = hostRepository; + //this.mainNodeClient = mainNodeClient; + this.mainNodeCom = mainNodeCom; + this.token = token; + this.nodeIp = nodeIp; + this.ip = ip; + this.vlanName = vlanName; + this.portScannerService = portScannerService; + this.sendAssetService = sendAssetService; + } + + + @Override + public void sniffTraffic() { + + log.info("[DHCP Sniffing service] Initializing with network address {}", ip); + + String netName = null; + try { + int ctr = 0; + String[] pieces = null; + + while(ctr < 255) { + pieces = ip.split("\\."); + String ipToSend = pieces[0] +"."+ pieces[1] +"."+ pieces[2] +"."+ ctr; + + netName = checkNetworkInterfaces(ipToSend); + + if(netName != null){ + break; + } + ctr = ctr +1; + } + }catch(SocketException se){ + //handled + } + + if(netName != null){ + + log.info("[DHCP Sniffing service] Network interface with name {} was found. Now sniffing...", netName); + + String[] tcpdumpCmd = {"tcpdump", "-i", netName, "-n", "-e", "port 67 and port 68", "-v", "-l"}; + try { + Process p = new ProcessBuilder(tcpdumpCmd).start(); + BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream())); + String tcpdumpOut = null; + + while ((tcpdumpOut = in.readLine()) != null) { + + //log.info("{}",tcpdumpOut); + if(tcpdumpOut.contains("Client-IP") || tcpdumpOut.contains("Your-IP")) { + + String[] clientIP_arr = tcpdumpOut.split(" "); + String clientIP = clientIP_arr[clientIP_arr.length - 1]; + + String mac = ""; + String hostname = ""; + + while (tcpdumpOut != null && !tcpdumpOut.contains("Parameter-Request")) { + //log.info("{}",tcpdumpOut); + tcpdumpOut = in.readLine(); + + if (tcpdumpOut.contains("Client-Ethernet-Address")) { + String[] mac_arr = tcpdumpOut.split(" "); + mac = mac_arr[mac_arr.length - 1]; + } + if (tcpdumpOut.contains("Hostname Option 12")) { + String[] hostname_arr = tcpdumpOut.split(" "); + hostname = hostname_arr[hostname_arr.length - 1]; + hostname = hostname.substring(1, hostname.length() - 2); + } + + } + + + log.info("[DHCP Sniffing service] Discovered ACK Packet for Client IP: {} \n With hostname {} and mac {}", clientIP, hostname, mac); + + //String params = token + "&" + clientIP + "&" + mac; + //int alreadyPresent = mainNodeClient.checkIP(params); + int alreadyPresent = mainNodeCom.checkIP(token, clientIP, mac); + + if (alreadyPresent == 0) { + log.info("[DHCP Sniffing service] {} has not been discovered until now. Preparing further scannign...", clientIP); + // New nmap to be scheduled + Date iniTime = new Date(); + + ScanInfo scanInfo = ScanInfo.createScanInfo(vlanName, nodeIp, iniTime, "dhcp"); + + Host dhcp_host = Host.createHost(clientIP, hostname, mac, vlanName, iniTime, scanInfo, "dhcp"); + + portScannerService.scanHost(dhcp_host, "dhcp"); + + Date endTime = new Date(); + scanInfo.setEndTimestampScan(endTime); + dhcp_host.setTimestamp_end(endTime); + + try { + scanInfoRepository.save(scanInfo); + + hostRepository.save(dhcp_host); + + portRepository.saveAll(portScannerService.getPortListDHCP()); + portScannerService.setPortListDHCP(new ArrayList()); + + }catch(Exception e){ + log.info("[RUNTIME ERROR--DHCP SNIFFING SERVICE--]---{}",e); + } + + sendAssetService.sendAssetsDHCP(vlanName, "dhcp", iniTime); + + } + + } + } + }catch(Exception io){ + //handled + } + + }else{ + + log.info("[DHCP Sniffing service] No network interface was found with address {}. Aborting...", ip); + + } + + } + + + public String checkNetworkInterfaces(String toMatch) throws SocketException { + Enumeration nets = NetworkInterface.getNetworkInterfaces(); + String netName = null; + for (NetworkInterface netint : Collections.list(nets)) { + netName = displayInterfaceInformation(netint, toMatch); + if (netName != null) { + break; + //return netName; + } + } + + return netName; + } + + + public String displayInterfaceInformation(NetworkInterface netint, String toMatch) throws SocketException { + + Enumeration inetAddresses = netint.getInetAddresses(); + String matched = null; + for (InetAddress inetAddress : Collections.list(inetAddresses)) { + + if(inetAddress.getHostAddress().equals(toMatch)){ + + matched = netint.getName(); + + /*byte[] mac = netint.getHardwareAddress(); + String macToStore = ""; + + if(mac != null) { + + for (int i = 0; i < mac.length; i++) { + + String toCheck = Integer.toHexString(mac[i]); + if(toCheck.length() > 2){ + + toCheck = toCheck.substring(toCheck.length()-3, toCheck.length()-1); + } + + if(i < mac.length-1){ + macToStore = macToStore + toCheck + ":"; + }else{ + macToStore = macToStore + toCheck; + } + } + + } + */ + + break; + } + } + + return matched; + } + + + +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000000000000000000000000000000000000..434b323ffb443c4b6f63e6915e5a562e4655e1c0 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,56 @@ +http: + port: ${ADT_PORT:8081} + +server: + port: ${ADT_PORT:8081} + ssl: + enabled: false + +logging: + file: logs/childNode.log + +feign: + client.config.default.connectTimeout: 16000 + client.config.default.readTimeout: 16000 + hystrix: + enabled: true + command: + default: + execution: + isolation: + thread: + timeoutInMilliseconds: 10000 + +spring: + + ssl: + enabled: false + + datasource: + url: jdbc:h2:file:${H2_PATH:/mnt/sdb2/Midas/Curex/adt/h2} + driver-class-name: org.h2.Driver + username: curex_adt + password: f4k64g6a65fWGTYmE488NJsfu + jpa: + database-platform: org.hibernate.dialect.H2Dialect + hibernate: + ddl-auto: update + properties: + hibernate: + show_sql: false + format_sql: true + h2: + console: + enabled: true + settings: + web-allow-others: true + +vlan: + name: ${VLAN_NAME:test} + address: ${VLAN_ADDRESS:192.168.1.0} + mask: ${VLAN_MASK:24} + port_timeout: ${VLAN_PORT_TIMEOUT:600} + +main-node: + address: ${MAIN_NODE_ADDRESS:localhost} + port: ${MAIN_NODE_PORT:8080} diff --git a/src/main/resources/macnificent.dat b/src/main/resources/macnificent.dat new file mode 100644 index 0000000000000000000000000000000000000000..7a72de6ad067be8b6907e76c58b86e6c7ef9e5aa Binary files /dev/null and b/src/main/resources/macnificent.dat differ