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()) {
|---|