Make probes work even in the face of arbitrary data

This commit is contained in:
Ondřej Kuzník 2013-09-23 23:30:31 +01:00 committed by Yves Rutschle
parent ce170814f5
commit 708c3b0177

60
probe.c
View File

@ -125,7 +125,7 @@ void hexdump(const char *mem, unsigned int len)
/* Is the buffer the beginning of an SSH connection? */ /* Is the buffer the beginning of an SSH connection? */
static int is_ssh_protocol(const char *p, int len, struct proto *proto) 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 1;
} }
return 0; return 0;
@ -143,8 +143,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) 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; return packet_len == len - 2;
} }
@ -153,6 +157,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) static int is_tinc_protocol( const char *p, int len, struct proto *proto)
{ {
if (len < 2)
return 0;
return !strncmp(p, "0 ", 2); return !strncmp(p, "0 ", 2);
} }
@ -162,37 +169,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) 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? */ /* Is the buffer the beginning of an HTTP connection? */
static int is_http_protocol(const char *p, int len, struct proto *proto) 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 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; 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 /* Otherwise it could be HTTP/1.0 without version: check if it's got an
* HTTP method (RFC2616 5.1.1) */ * HTTP method (RFC2616 5.1.1) */
probe_http_method(p, "OPTIONS"); PROBE_HTTP_METHOD("OPTIONS");
probe_http_method(p, "GET"); PROBE_HTTP_METHOD("GET");
probe_http_method(p, "HEAD"); PROBE_HTTP_METHOD("HEAD");
probe_http_method(p, "POST"); PROBE_HTTP_METHOD("POST");
probe_http_method(p, "PUT"); PROBE_HTTP_METHOD("PUT");
probe_http_method(p, "DELETE"); PROBE_HTTP_METHOD("DELETE");
probe_http_method(p, "TRACE"); PROBE_HTTP_METHOD("TRACE");
probe_http_method(p, "CONNECT"); PROBE_HTTP_METHOD("CONNECT");
#undef PROBE_HTTP_METHOD
return 0; return 0;
} }
static int is_tls_protocol(const char *p, int len, struct proto *proto) 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 /* TLS packet starts with a record "Hello" (0x16), followed by version
* (0x03 0x00-0x03) (RFC6101 A.1) * (0x03 0x00-0x03) (RFC6101 A.1)
* This means we reject SSLv2 and lower, which is actually a good thing (RFC6176) * This means we reject SSLv2 and lower, which is actually a good thing (RFC6176)
@ -202,16 +219,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) static int regex_probe(const char *p, int len, struct proto *proto)
{ {
regex_t** probe_list = (regex_t**)(proto->data); regex_t **probe = proto->data;
int i=0; regmatch_t pos = { 0, len };
while (probe_list[i]) { for (; *probe && regexec(*probe, p, 0, &pos, REG_STARTEND); probe++)
if (!regexec(probe_list[i], p, 0, NULL, 0)) { /* try them all */;
return 1;
} return (probe != NULL);
i++;
}
return 0;
} }
/* /*