The FINGERPRINT mechanism MUST be used for connectivity checks

git.mgm/mediaproxy-ng/2.2
Richard Fuchs 13 years ago
parent 9c8075ca87
commit 4aa3017555

@ -2,6 +2,7 @@ CC= gcc
CFLAGS= -g -Wall -pthread -fno-strict-aliasing CFLAGS= -g -Wall -pthread -fno-strict-aliasing
CFLAGS+= `pkg-config --cflags glib-2.0` CFLAGS+= `pkg-config --cflags glib-2.0`
CFLAGS+= `pkg-config --cflags gthread-2.0` CFLAGS+= `pkg-config --cflags gthread-2.0`
CFLAGS+= `pkg-config --cflags zlib`
CFLAGS+= `pcre-config --cflags` CFLAGS+= `pcre-config --cflags`
CFLAGS+= -I/lib/modules/`uname -r`/build/include/ -I../kernel-module/ CFLAGS+= -I/lib/modules/`uname -r`/build/include/ -I../kernel-module/
CFLAGS+= -D_GNU_SOURCE CFLAGS+= -D_GNU_SOURCE
@ -17,6 +18,7 @@ endif
LDFLAGS= -ldl -rdynamic LDFLAGS= -ldl -rdynamic
LDFLAGS+= `pkg-config --libs glib-2.0` LDFLAGS+= `pkg-config --libs glib-2.0`
LDFLAGS+= `pkg-config --libs gthread-2.0` LDFLAGS+= `pkg-config --libs gthread-2.0`
LDFLAGS+= `pkg-config --libs zlib`
LDFLAGS+= `pcre-config --libs` LDFLAGS+= `pcre-config --libs`
LDFLAGS+= `xmlrpc-c-config client --libs` LDFLAGS+= `xmlrpc-c-config client --libs`

@ -3,6 +3,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <string.h> #include <string.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <zlib.h>
#include "str.h" #include "str.h"
#include "aux.h" #include "aux.h"
@ -22,7 +23,9 @@ struct tlv {
struct stun_attrs { struct stun_attrs {
str username; str username;
str msg_integrity; str msg_integrity;
char *fingerprint_attr;
u_int32_t priority; u_int32_t priority;
u_int32_t fingerprint;
int use:1, int use:1,
controlled:1, controlled:1,
controlling:1; controlling:1;
@ -32,7 +35,12 @@ struct stun_error {
struct stun stun; struct stun stun;
struct tlv error_code; struct tlv error_code;
u_int32_t codes; 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)) if (str_shift(s, len))
return -1; return -1;
if (out->msg_integrity.s && ntohs(tlv->type) != 0x8028)
return -1;
switch (ntohs(tlv->type)) { switch (ntohs(tlv->type)) {
case 0x0006: /* username */ case 0x0006: /* username */
out->username = attr; out->username = attr;
break; break;
case 0x0008: /* message-integrity */ case 0x0008: /* message-integrity */
out->msg_integrity = attr; 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; goto out;
case 0x0025: /* use-candidate */ 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) int code, char *reason, int len)
{ {
struct stun_error err; struct stun_error err;
struct stun_fingerprint fp;
struct msghdr mh; struct msghdr mh;
struct iovec iov[2]; struct iovec iov[3];
err.stun.msg_type = htons(0x0111); /* binding error response */ err.stun.msg_type = htons(0x0111); /* binding error response */
err.stun.cookie = htonl(STUN_COOKIE); 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[0].iov_len = sizeof(err);
iov[1].iov_base = reason; iov[1].iov_base = reason;
iov[1].iov_len = (len + 3) & 0xfffc; 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_name = sin;
mh.msg_namelen = sizeof(*sin); mh.msg_namelen = sizeof(*sin);
mh.msg_iov = iov; mh.msg_iov = iov;
mh.msg_iovlen = 2; mh.msg_iovlen = 3;
sendmsg(fd, &mh, 0); 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) \ #define stun_error(fd, sin, str, code, reason) \
stun_error_len(fd, sin, str, code, reason "\0\0\0", strlen(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 */ /* XXX add error reporting */
int stun(str *b, struct streamrelay *sr, struct sockaddr_in6 *sin) { int stun(str *b, struct streamrelay *sr, struct sockaddr_in6 *sin) {
struct stun *s = (void *) b->s; 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)) if (stun_attributes(&attrs, &attr_str))
return -1; return -1;
if (class == 0x0) { /* request */ if (class != 0x0)
if (!attrs.username.s || !attrs.msg_integrity.s) return -1; /* XXX ? */
/* request */
if (!attrs.username.s || !attrs.msg_integrity.s || !attrs.fingerprint_attr)
goto bad_req; goto bad_req;
}
if (check_fingerprint(b, &attrs))
return -1;
return 0; return 0;

3
debian/control vendored

@ -8,7 +8,8 @@ Build-Depends: debhelper (>= 5),
libcurl3-openssl-dev | libcurl3-gnutls-dev, libcurl3-openssl-dev | libcurl3-gnutls-dev,
libglib2.0-dev, libglib2.0-dev,
libpcre3-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 Standards-Version: 3.9.3
Homepage: http://sipwise.com/ Homepage: http://sipwise.com/

Loading…
Cancel
Save