[sslh] [PATCH 01/10] Make probes work even in the face of arbitrary data

ondra+sslh at mistotebe.net ondra+sslh at mistotebe.net
Tue Sep 24 00:30:31 CEST 2013


From: Ondřej Kuzník <ondra at mistotebe.net>

---
 probe.c | 60 +++++++++++++++++++++++++++++++++++++-----------------------
 1 file changed, 37 insertions(+), 23 deletions(-)

diff --git a/probe.c b/probe.c
index d693797..25a1f27 100644
--- a/probe.c
+++ b/probe.c
@@ -124,7 +124,7 @@ void hexdump(const char *mem, unsigned int len)
 /* Is the buffer the beginning of an SSH connection? */
 static int is_ssh_protocol(const char *p, int len, struct proto *proto)
 {
-    if (!strncmp(p, "SSH-", 4)) {
+    if (len >= 4 && !strncmp(p, "SSH-", 4)) {
         return 1;
     }
     return 0;
@@ -142,8 +142,12 @@ static int is_ssh_protocol(const char *p, int len, struct proto *proto)
  */
 static int is_openvpn_protocol (const char*p,int len, struct proto *proto)
 {
-    int packet_len = ntohs(*(uint16_t*)p);
+    int packet_len;
 
+    if (len < 2)
+        return 0;
+
+    packet_len = ntohs(*(uint16_t*)p);
     return packet_len == len - 2;
 }
 
@@ -152,6 +156,9 @@ static int is_openvpn_protocol (const char*p,int len, struct proto *proto)
  * */
 static int is_tinc_protocol( const char *p, int len, struct proto *proto)
 {
+    if (len < 2)
+        return 0;
+
     return !strncmp(p, "0 ", 2);
 }
 
@@ -161,37 +168,47 @@ static int is_tinc_protocol( const char *p, int len, struct proto *proto)
  * */
 static int is_xmpp_protocol( const char *p, int len, struct proto *proto)
 {
-    return strstr(p, "jabber") ? 1 : 0;
+    return memmem(p, len, "jabber", 6) ? 1 : 0;
 }
 
-static int probe_http_method(const char *p, const char *opt)
+static int probe_http_method(const char *p, int len, const char *opt)
 {
-    return !strcmp(p, opt);
+    if (len < strlen(opt))
+        return 0;
+
+    return !strncmp(p, opt, len);
 }
 
 /* Is the buffer the beginning of an HTTP connection?  */
 static int is_http_protocol(const char *p, int len, struct proto *proto)
 {
     /* If it's got HTTP in the request (HTTP/1.1) then it's HTTP */
-    if (strstr(p, "HTTP"))
+    if (memmem(p, len, "HTTP", 4))
         return 1;
 
+#define PROBE_HTTP_METHOD(opt) if (probe_http_method(p, len, opt)) return 1
+
     /* Otherwise it could be HTTP/1.0 without version: check if it's got an
      * HTTP method (RFC2616 5.1.1) */
-    probe_http_method(p, "OPTIONS");
-    probe_http_method(p, "GET");
-    probe_http_method(p, "HEAD");
-    probe_http_method(p, "POST");
-    probe_http_method(p, "PUT");
-    probe_http_method(p, "DELETE");
-    probe_http_method(p, "TRACE");
-    probe_http_method(p, "CONNECT");
+    PROBE_HTTP_METHOD("OPTIONS");
+    PROBE_HTTP_METHOD("GET");
+    PROBE_HTTP_METHOD("HEAD");
+    PROBE_HTTP_METHOD("POST");
+    PROBE_HTTP_METHOD("PUT");
+    PROBE_HTTP_METHOD("DELETE");
+    PROBE_HTTP_METHOD("TRACE");
+    PROBE_HTTP_METHOD("CONNECT");
+
+#undef PROBE_HTTP_METHOD
 
     return 0;
 }
 
 static int is_tls_protocol(const char *p, int len, struct proto *proto)
 {
+    if (len < 3)
+        return 0;
+
     /* TLS packet starts with a record "Hello" (0x16), followed by version
      * (0x03 0x00-0x03) (RFC6101 A.1)
      * This means we reject SSLv2 and lower, which is actually a good thing (RFC6176)
@@ -201,16 +218,13 @@ static int is_tls_protocol(const char *p, int len, struct proto *proto)
 
 static int regex_probe(const char *p, int len, struct proto *proto)
 {
-    regex_t** probe_list = (regex_t**)(proto->data);
-    int i=0;
+    regex_t **probe = proto->data;
+    regmatch_t pos = { 0, len };
 
-    while (probe_list[i]) {
-        if (!regexec(probe_list[i], p, 0, NULL, 0)) {
-            return 1;
-        }
-        i++;
-    }
-    return 0;
+    for (; *probe && regexec(*probe, p, 0, &pos, REG_STARTEND); probe++)
+        /* try them all */;
+
+    return (probe != NULL);
 }
 
 /* 
-- 
1.8.4.rc3




More information about the sslh mailing list