diff --git a/include/Flow.h b/include/Flow.h index d7336352b5..ab6bf527f3 100644 --- a/include/Flow.h +++ b/include/Flow.h @@ -110,6 +110,10 @@ class Flow : public GenericHashEntry { struct { char *client_signature, *server_signature; + struct { + /* https://engineering.salesforce.com/open-sourcing-hassh-abed3ae5044c */ + char *client_hash, *server_hash; + } hassh; } ssh; struct { diff --git a/include/ntop_defines.h b/include/ntop_defines.h index 90a8a2a35c..07e71036fe 100644 --- a/include/ntop_defines.h +++ b/include/ntop_defines.h @@ -136,7 +136,7 @@ #define NO_UID ((u_int32_t)-1) #define NO_PID ((u_int32_t)-1) #define NO_NDPI_PROTOCOL ((u_int)-1) -#define NDPI_MIN_NUM_PACKETS 10 +#define NDPI_MIN_NUM_PACKETS 12 #define GTP_U_V1_PORT 2152 #define TZSP_PORT 37008 #define CAPWAP_DATA_PORT 5247 diff --git a/scripts/lua/flow_details.lua b/scripts/lua/flow_details.lua index 16b1b4878c..719447ee40 100644 --- a/scripts/lua/flow_details.lua +++ b/scripts/lua/flow_details.lua @@ -1018,14 +1018,18 @@ else print("\n") end - if(not isEmptyString(flow["bittorrent_hash"])) then - print(""..i18n("flow_details.bittorrent_hash").."".. flow["bittorrent_hash"].."\n") + if not isEmptyString(flow["protos.ssh.hassh.client_hash"]) or not isEmptyString(flow["protos.ssh.hassh.server_hash"]) then + print("HASSH"..i18n("client")..": "..(flow["protos.ssh.hassh.client_hash"] or '')..""..i18n("server")..": "..(flow["protos.ssh.hassh.server_hash"] or '').."\n") end if(not isEmptyString(flow["protos.ssh.client_signature"])) then print(""..i18n("flow_details.ssh_signature")..""..i18n("client")..": "..(flow["protos.ssh.client_signature"] or '')..""..i18n("server")..": "..(flow["protos.ssh.server_signature"] or '').."\n") end + if(not isEmptyString(flow["bittorrent_hash"])) then + print(""..i18n("flow_details.bittorrent_hash").."".. flow["bittorrent_hash"].."\n") + end + if(flow["protos.http.last_url"] ~= nil) then print(""..i18n("http").."") print(""..i18n("flow_details.http_method")..""..(flow["protos.http.last_method"] or '').."") diff --git a/src/Flow.cpp b/src/Flow.cpp index a670fdab88..7679a13a51 100644 --- a/src/Flow.cpp +++ b/src/Flow.cpp @@ -236,6 +236,8 @@ Flow::~Flow() { } else if(isSSH()) { if(protos.ssh.client_signature) free(protos.ssh.client_signature); if(protos.ssh.server_signature) free(protos.ssh.server_signature); + if(protos.ssh.hassh.client_hash) free(protos.ssh.hassh.client_hash); + if(protos.ssh.hassh.server_hash) free(protos.ssh.hassh.server_hash); } else if(isSSL()) { if(protos.ssl.certificate) free(protos.ssl.certificate); if(protos.ssl.server_certificate) free(protos.ssl.server_certificate); @@ -525,10 +527,19 @@ void Flow::processDetectedProtocol() { break; case NDPI_PROTOCOL_SSH: - if(protos.ssh.client_signature) free(protos.ssh.client_signature); - if(protos.ssh.server_signature) free(protos.ssh.server_signature); - protos.ssh.client_signature = strdup(ndpiFlow->protos.ssh.client_signature); - protos.ssh.server_signature = strdup(ndpiFlow->protos.ssh.server_signature); + if(protos.ssh.client_signature == NULL) + protos.ssh.client_signature = strdup(ndpiFlow->protos.ssh.client_signature); + if(protos.ssh.server_signature == NULL) + protos.ssh.server_signature = strdup(ndpiFlow->protos.ssh.server_signature); + + if(protos.ssh.hassh.client_hash == NULL + && ndpiFlow->protos.ssh.hassh_client[0] != '\0') + protos.ssh.hassh.client_hash = strdup(ndpiFlow->protos.ssh.hassh_client); + + if(protos.ssh.hassh.server_hash == NULL + && ndpiFlow->protos.ssh.hassh_server[0] != '\0') + protos.ssh.hassh.server_hash = strdup(ndpiFlow->protos.ssh.hassh_server); + break; case NDPI_PROTOCOL_TOR: @@ -624,12 +635,19 @@ void Flow::setDetectedProtocol(ndpi_protocol proto_id, bool forceDetection) { /* Let the client SSL certificate win over the server SSL certificate this addresses detection for youtube, e.g., when the client requests s.youtube.com but the server responds with google.com */ - if((!forceDetection) - && (proto_id.master_protocol == NDPI_PROTOCOL_TLS) - && (get_packets() < NDPI_MIN_NUM_PACKETS) + + if(!forceDetection + && get_packets() < NDPI_MIN_NUM_PACKETS && (ndpif = get_ndpi_flow()) - && ((ndpif->protos.stun_ssl.ssl.client_certificate[0] == '\0') - || (ndpif->protos.stun_ssl.ssl.server_certificate[0] == '\0'))) { + && ( + (proto_id.master_protocol == NDPI_PROTOCOL_TLS + && (ndpif->protos.stun_ssl.ssl.client_certificate[0] == '\0' + || ndpif->protos.stun_ssl.ssl.server_certificate[0] == '\0')) + || (proto_id.app_protocol == NDPI_PROTOCOL_SSH + && (ndpif->protos.ssh.hassh_client[0] == '\0' + || ndpif->protos.ssh.hassh_server[0] == '\0')) + ) + ) { ndpif->detected_protocol_stack[0] = NDPI_PROTOCOL_UNKNOWN; return; } @@ -1906,6 +1924,9 @@ void Flow::lua(lua_State* vm, AddressTree * ptree, if(isSSH()) { if(protos.ssh.client_signature) lua_push_str_table_entry(vm, "protos.ssh.client_signature", protos.ssh.client_signature); if(protos.ssh.server_signature) lua_push_str_table_entry(vm, "protos.ssh.server_signature", protos.ssh.server_signature); + + if(protos.ssh.hassh.client_hash) lua_push_str_table_entry(vm, "protos.ssh.hassh.client_hash", protos.ssh.hassh.client_hash); + if(protos.ssh.hassh.server_hash) lua_push_str_table_entry(vm, "protos.ssh.hassh.server_hash", protos.ssh.hassh.server_hash); } if(isSSL()) {