From 4aa30175551d889a3bd78895af5c7d4c833c7e6b Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Thu, 28 Feb 2013 14:48:45 -0500 Subject: [PATCH] The FINGERPRINT mechanism MUST be used for connectivity checks --- daemon/Makefile | 2 ++ daemon/stun.c | 61 ++++++++++++++++++++++++++++++++++++++++++------- debian/control | 3 ++- 3 files changed, 57 insertions(+), 9 deletions(-) diff --git a/daemon/Makefile b/daemon/Makefile index cca427178..6a7a0b6ff 100644 --- a/daemon/Makefile +++ b/daemon/Makefile @@ -2,6 +2,7 @@ CC= gcc CFLAGS= -g -Wall -pthread -fno-strict-aliasing CFLAGS+= `pkg-config --cflags glib-2.0` CFLAGS+= `pkg-config --cflags gthread-2.0` +CFLAGS+= `pkg-config --cflags zlib` CFLAGS+= `pcre-config --cflags` CFLAGS+= -I/lib/modules/`uname -r`/build/include/ -I../kernel-module/ CFLAGS+= -D_GNU_SOURCE @@ -17,6 +18,7 @@ endif LDFLAGS= -ldl -rdynamic LDFLAGS+= `pkg-config --libs glib-2.0` LDFLAGS+= `pkg-config --libs gthread-2.0` +LDFLAGS+= `pkg-config --libs zlib` LDFLAGS+= `pcre-config --libs` LDFLAGS+= `xmlrpc-c-config client --libs` diff --git a/daemon/stun.c b/daemon/stun.c index 193a46e30..454f0b940 100644 --- a/daemon/stun.c +++ b/daemon/stun.c @@ -3,6 +3,7 @@ #include #include #include +#include #include "str.h" #include "aux.h" @@ -22,7 +23,9 @@ struct tlv { struct stun_attrs { str username; str msg_integrity; + char *fingerprint_attr; u_int32_t priority; + u_int32_t fingerprint; int use:1, controlled:1, controlling:1; @@ -32,7 +35,12 @@ struct stun_error { struct stun stun; struct tlv error_code; u_int32_t codes; -}; +} __attribute__ ((packed)); + +struct stun_fingerprint { + struct tlv tlv; + u_int32_t crc; +} __attribute__ ((packed)); @@ -59,12 +67,21 @@ static int stun_attributes(struct stun_attrs *out, str *s) { if (str_shift(s, len)) return -1; + if (out->msg_integrity.s && ntohs(tlv->type) != 0x8028) + return -1; + switch (ntohs(tlv->type)) { case 0x0006: /* username */ out->username = attr; break; case 0x0008: /* message-integrity */ out->msg_integrity = attr; + break; + case 0x8028: /* fingerprint */ + if (attr.len != 4) + return -1; + out->fingerprint_attr = (void *) tlv; + out->fingerprint = ntohl(*(u_int32_t *) attr.s); goto out; case 0x0025: /* use-candidate */ @@ -93,8 +110,9 @@ static inline void stun_error_len(int fd, struct sockaddr_in6 *sin, struct stun int code, char *reason, int len) { struct stun_error err; + struct stun_fingerprint fp; struct msghdr mh; - struct iovec iov[2]; + struct iovec iov[3]; err.stun.msg_type = htons(0x0111); /* binding error response */ err.stun.cookie = htonl(STUN_COOKIE); @@ -110,13 +128,22 @@ static inline void stun_error_len(int fd, struct sockaddr_in6 *sin, struct stun iov[0].iov_len = sizeof(err); iov[1].iov_base = reason; iov[1].iov_len = (len + 3) & 0xfffc; + iov[2].iov_base = &fp; + iov[2].iov_len = sizeof(fp); - err.stun.msg_len = htons(iov[1].iov_len + sizeof(err.codes) + sizeof(err.error_code)); + err.stun.msg_len = htons(iov[1].iov_len + sizeof(err.codes) + sizeof(err.error_code) + + iov[2].iov_len); + + fp.crc = crc32(0, iov[0].iov_base, iov[0].iov_len); + fp.crc = crc32(fp.crc, iov[1].iov_base, iov[1].iov_len); + fp.crc = htonl(fp.crc ^ 0x5354554eUL); + fp.tlv.type = htons(0x8028); + fp.tlv.len = htons(4); mh.msg_name = sin; mh.msg_namelen = sizeof(*sin); mh.msg_iov = iov; - mh.msg_iovlen = 2; + mh.msg_iovlen = 3; sendmsg(fd, &mh, 0); } @@ -124,6 +151,19 @@ static inline void stun_error_len(int fd, struct sockaddr_in6 *sin, struct stun #define stun_error(fd, sin, str, code, reason) \ stun_error_len(fd, sin, str, code, reason "\0\0\0", strlen(reason)) +static int check_fingerprint(str *msg, struct stun_attrs *attrs) { + int len; + u_int32_t crc; + + len = attrs->fingerprint_attr - msg->s; + crc = crc32(0, (void *) msg->s, len); + crc ^= 0x5354554eUL; + if (crc != attrs->fingerprint) + return -1; + + return 0; +} + /* XXX add error reporting */ int stun(str *b, struct streamrelay *sr, struct sockaddr_in6 *sin) { struct stun *s = (void *) b->s; @@ -146,10 +186,15 @@ int stun(str *b, struct streamrelay *sr, struct sockaddr_in6 *sin) { if (stun_attributes(&attrs, &attr_str)) return -1; - if (class == 0x0) { /* request */ - if (!attrs.username.s || !attrs.msg_integrity.s) - goto bad_req; - } + if (class != 0x0) + return -1; /* XXX ? */ + + /* request */ + if (!attrs.username.s || !attrs.msg_integrity.s || !attrs.fingerprint_attr) + goto bad_req; + + if (check_fingerprint(b, &attrs)) + return -1; return 0; diff --git a/debian/control b/debian/control index 6315c2ddf..9224a2e4b 100644 --- a/debian/control +++ b/debian/control @@ -8,7 +8,8 @@ Build-Depends: debhelper (>= 5), libcurl3-openssl-dev | libcurl3-gnutls-dev, libglib2.0-dev, libpcre3-dev, - libxmlrpc-c3-dev (>= 1.16.07) | libxmlrpc-core-c3-dev (>= 1.16.07) + libxmlrpc-c3-dev (>= 1.16.07) | libxmlrpc-core-c3-dev (>= 1.16.07), + zlib1g-dev Standards-Version: 3.9.3 Homepage: http://sipwise.com/