Commit 03590520 authored by Youness Alaoui's avatar Youness Alaoui

Fixed tools and binding usage to work with new API

parent 3f3c7e4d
...@@ -13,11 +13,7 @@ include $(top_srcdir)/common.mk ...@@ -13,11 +13,7 @@ include $(top_srcdir)/common.mk
AM_CFLAGS = -std=gnu99 $(ERROR_CFLAGS) $(OPENSSL_CFLAGS) AM_CFLAGS = -std=gnu99 $(ERROR_CFLAGS) $(OPENSSL_CFLAGS)
AM_CPPFLAGS = -I$(top_srcdir) AM_CPPFLAGS = -I$(top_srcdir)
BUILT_SOURCES = unknown.c
CLEANFILES += $(BUILT_SOURCES)
noinst_LTLIBRARIES = libstun.la noinst_LTLIBRARIES = libstun.la
dist_noinst_SCRIPTS = build-unknown.sh
libstun_la_SOURCES = stun.h constants.h \ libstun_la_SOURCES = stun.h constants.h \
stunagent.c stunagent.h \ stunagent.c stunagent.h \
...@@ -25,16 +21,8 @@ libstun_la_SOURCES = stun.h constants.h \ ...@@ -25,16 +21,8 @@ libstun_la_SOURCES = stun.h constants.h \
stun3489bis.c stun3489bis.h \ stun3489bis.c stun3489bis.h \
stuncrc32.c stuncrc32.h \ stuncrc32.c stuncrc32.h \
stunhmac.c stunhmac.h \ stunhmac.c stunhmac.h \
utils.c utils.h utils.c utils.h
# usages/stun-ice.c usages/stun-ice.h
# usages/timer.h usages/timer.c \
# usages/trans.h usages/trans.c \
# usages/stun-ice.c usages/stun-ice.h \
# usages/bind.c usages/bind.h
libstun_la_LIBADD = $(OPENSSL_LIBS) $(LIBRT) libstun_la_LIBADD = $(OPENSSL_LIBS) $(LIBRT)
unknown.c: stun-msg.h build-unknown.sh
rm -f unknown.c
$(SHELL) "$(srcdir)/build-unknown.sh" < "$(srcdir)/stun-msg.h" > unknown.c
...@@ -62,7 +62,7 @@ ...@@ -62,7 +62,7 @@
#define STUN_MAX_MESSAGE_SIZE_IPV4 576 #define STUN_MAX_MESSAGE_SIZE_IPV4 576
#define STUN_MAX_MESSAGE_SIZE_IPV6 1280 #define STUN_MAX_MESSAGE_SIZE_IPV6 1280
#define STUN_MAX_MESSAGE_SIZE MAX_STUN_SIZE_IPV4 #define STUN_MAX_MESSAGE_SIZE STUN_MAX_MESSAGE_SIZE_IPV4
#define STUN_ID_LEN 16 #define STUN_ID_LEN 16
......
...@@ -85,6 +85,7 @@ StunValidationStatus stun_agent_validate (StunAgent *agent, StunMessage *msg, ...@@ -85,6 +85,7 @@ StunValidationStatus stun_agent_validate (StunAgent *agent, StunMessage *msg,
uint8_t sha[20]; uint8_t sha[20];
uint16_t hlen; uint16_t hlen;
int sent_id_idx = -1; int sent_id_idx = -1;
uint16_t unknown;
len = stun_message_validate_buffer_length (buffer, buffer_len); len = stun_message_validate_buffer_length (buffer, buffer_len);
if (len == STUN_MESSAGE_BUFFER_INVALID) { if (len == STUN_MESSAGE_BUFFER_INVALID) {
...@@ -182,8 +183,8 @@ StunValidationStatus stun_agent_validate (StunAgent *agent, StunMessage *msg, ...@@ -182,8 +183,8 @@ StunValidationStatus stun_agent_validate (StunAgent *agent, StunMessage *msg,
} }
if (key != NULL && key_len > 0) { if (key != NULL && key_len > 0) {
hash = (uint8_t *) stun_message_find (msg, STUN_ATTRIBUTE_MESSAGE_INTEGRITY, hash = (uint8_t *) stun_message_find (msg,
&hlen); STUN_ATTRIBUTE_MESSAGE_INTEGRITY, &hlen);
stun_sha1 (msg->buffer, stun_message_length (msg), sha, key, key_len); stun_sha1 (msg->buffer, stun_message_length (msg), sha, key, key_len);
stun_debug (" Message HMAC-SHA1 fingerprint:"); stun_debug (" Message HMAC-SHA1 fingerprint:");
...@@ -206,6 +207,13 @@ StunValidationStatus stun_agent_validate (StunAgent *agent, StunMessage *msg, ...@@ -206,6 +207,13 @@ StunValidationStatus stun_agent_validate (StunAgent *agent, StunMessage *msg,
if (sent_id_idx != -1 && sent_id_idx < STUN_AGENT_MAX_SAVED_IDS) { if (sent_id_idx != -1 && sent_id_idx < STUN_AGENT_MAX_SAVED_IDS) {
agent->sent_ids[sent_id_idx].valid = FALSE; agent->sent_ids[sent_id_idx].valid = FALSE;
} }
if (stun_agent_find_unknowns (agent, msg, &unknown, 1) > 0) {
if (stun_message_get_class (msg) == STUN_REQUEST)
return STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE;
else
return STUN_VALIDATION_UNKNOWN_ATTRIBUTE;
}
return STUN_VALIDATION_SUCCESS; return STUN_VALIDATION_SUCCESS;
} }
...@@ -265,7 +273,7 @@ bool stun_agent_init_indication (StunAgent *agent, StunMessage *msg, ...@@ -265,7 +273,7 @@ bool stun_agent_init_indication (StunAgent *agent, StunMessage *msg,
bool stun_agent_init_response (StunAgent *agent, StunMessage *msg, bool stun_agent_init_response (StunAgent *agent, StunMessage *msg,
uint8_t *buffer, size_t buffer_len, stun_method_t m, StunMessage *request) uint8_t *buffer, size_t buffer_len, const StunMessage *request)
{ {
stun_transid_t id; stun_transid_t id;
...@@ -296,7 +304,7 @@ bool stun_agent_init_response (StunAgent *agent, StunMessage *msg, ...@@ -296,7 +304,7 @@ bool stun_agent_init_response (StunAgent *agent, StunMessage *msg,
bool stun_agent_init_error (StunAgent *agent, StunMessage *msg, bool stun_agent_init_error (StunAgent *agent, StunMessage *msg,
uint8_t *buffer, size_t buffer_len, StunMessage *request, uint8_t *buffer, size_t buffer_len, const StunMessage *request,
stun_error_t err) stun_error_t err)
{ {
stun_transid_t id; stun_transid_t id;
...@@ -330,7 +338,8 @@ bool stun_agent_init_error (StunAgent *agent, StunMessage *msg, ...@@ -330,7 +338,8 @@ bool stun_agent_init_error (StunAgent *agent, StunMessage *msg,
size_t stun_agent_build_unknown_attributes_error (StunAgent *agent, size_t stun_agent_build_unknown_attributes_error (StunAgent *agent,
StunMessage *msg, uint8_t *buffer, size_t buffer_len, StunMessage *request) StunMessage *msg, uint8_t *buffer, size_t buffer_len,
const StunMessage *request)
{ {
unsigned counter; unsigned counter;
...@@ -359,7 +368,7 @@ size_t stun_agent_build_unknown_attributes_error (StunAgent *agent, ...@@ -359,7 +368,7 @@ size_t stun_agent_build_unknown_attributes_error (StunAgent *agent,
size_t stun_agent_finish_message (StunAgent *agent, StunMessage *msg, size_t stun_agent_finish_message (StunAgent *agent, StunMessage *msg,
uint8_t *key, size_t key_len) const uint8_t *key, size_t key_len)
{ {
uint8_t *ptr; uint8_t *ptr;
uint32_t fpr; uint32_t fpr;
...@@ -374,7 +383,7 @@ size_t stun_agent_finish_message (StunAgent *agent, StunMessage *msg, ...@@ -374,7 +383,7 @@ size_t stun_agent_finish_message (StunAgent *agent, StunMessage *msg,
stun_sha1 (msg->buffer, stun_message_length (msg), ptr, key, key_len); stun_sha1 (msg->buffer, stun_message_length (msg), ptr, key, key_len);
stun_debug (" Message HMAC-SHA1 fingerprint:" stun_debug (" Message HMAC-SHA1 message integrity:"
"\n key : "); "\n key : ");
stun_debug_bytes (key, key_len); stun_debug_bytes (key, key_len);
stun_debug ("\n sent : "); stun_debug ("\n sent : ");
...@@ -390,8 +399,13 @@ size_t stun_agent_finish_message (StunAgent *agent, StunMessage *msg, ...@@ -390,8 +399,13 @@ size_t stun_agent_finish_message (StunAgent *agent, StunMessage *msg,
return 0; return 0;
} }
fpr = stun_fingerprint (msg->buffer, stun_message_length (msg)); fpr = stun_fingerprint (msg->buffer, stun_message_length (msg));
memcpy (ptr, &fpr, sizeof (fpr)); memcpy (ptr, &fpr, sizeof (fpr));
stun_debug (" Message HMAC-SHA1 fingerprint: ");
stun_debug_bytes (ptr, 4);
stun_debug ("\n");
} }
...@@ -401,7 +415,7 @@ size_t stun_agent_finish_message (StunAgent *agent, StunMessage *msg, ...@@ -401,7 +415,7 @@ size_t stun_agent_finish_message (StunAgent *agent, StunMessage *msg,
stun_message_id (msg, id); stun_message_id (msg, id);
memcpy (agent->sent_ids[i].id, id, sizeof(stun_transid_t)); memcpy (agent->sent_ids[i].id, id, sizeof(stun_transid_t));
agent->sent_ids[i].method = stun_message_get_method (msg); agent->sent_ids[i].method = stun_message_get_method (msg);
agent->sent_ids[i].key = key; agent->sent_ids[i].key = (uint8_t *) key;
agent->sent_ids[i].key_len = key_len; agent->sent_ids[i].key_len = key_len;
agent->sent_ids[i].valid = TRUE; agent->sent_ids[i].valid = TRUE;
break; break;
...@@ -409,7 +423,7 @@ size_t stun_agent_finish_message (StunAgent *agent, StunMessage *msg, ...@@ -409,7 +423,7 @@ size_t stun_agent_finish_message (StunAgent *agent, StunMessage *msg,
} }
} }
msg->key = key; msg->key = (uint8_t *) key;
msg->key_len = key_len; msg->key_len = key_len;
return stun_message_length (msg); return stun_message_length (msg);
......
...@@ -99,13 +99,14 @@ bool stun_agent_init_request (StunAgent *agent, StunMessage *msg, ...@@ -99,13 +99,14 @@ bool stun_agent_init_request (StunAgent *agent, StunMessage *msg,
bool stun_agent_init_indication (StunAgent *agent, StunMessage *msg, bool stun_agent_init_indication (StunAgent *agent, StunMessage *msg,
uint8_t *buffer, size_t buffer_len, stun_method_t m); uint8_t *buffer, size_t buffer_len, stun_method_t m);
bool stun_agent_init_response (StunAgent *agent, StunMessage *msg, bool stun_agent_init_response (StunAgent *agent, StunMessage *msg,
uint8_t *buffer, size_t buffer_len, stun_method_t m, StunMessage *request); uint8_t *buffer, size_t buffer_len, const StunMessage *request);
bool stun_agent_init_error (StunAgent *agent, StunMessage *msg, bool stun_agent_init_error (StunAgent *agent, StunMessage *msg,
uint8_t *buffer, size_t buffer_len, StunMessage *request, uint8_t *buffer, size_t buffer_len, const StunMessage *request,
stun_error_t err); stun_error_t err);
size_t stun_agent_build_unknown_attributes_error (StunAgent *agent, size_t stun_agent_build_unknown_attributes_error (StunAgent *agent,
StunMessage *msg, uint8_t *buffer, size_t buffer_len, StunMessage *request); StunMessage *msg, uint8_t *buffer, size_t buffer_len,
const StunMessage *request);
size_t stun_agent_finish_message (StunAgent *agent, StunMessage *msg, size_t stun_agent_finish_message (StunAgent *agent, StunMessage *msg,
uint8_t *key, size_t key_len); const uint8_t *key, size_t key_len);
#endif /* _STUN_AGENT_H */ #endif /* _STUN_AGENT_H */
...@@ -120,5 +120,5 @@ void stun_make_transid (stun_transid_t id) ...@@ -120,5 +120,5 @@ void stun_make_transid (stun_transid_t id)
/* Computes hash out of contentious area */ /* Computes hash out of contentious area */
HMAC (EVP_sha1 (), key, sizeof (key), counter.bytes, sizeof (counter), HMAC (EVP_sha1 (), key, sizeof (key), counter.bytes, sizeof (counter),
sha, NULL); sha, NULL);
memcpy (id, sha, 12); memcpy (id, sha, 16);
} }
...@@ -62,7 +62,7 @@ bool stun_message_init (StunMessage *msg, stun_class_t c, stun_method_t m, ...@@ -62,7 +62,7 @@ bool stun_message_init (StunMessage *msg, stun_class_t c, stun_method_t m,
stun_set_type (msg->buffer, c, m); stun_set_type (msg->buffer, c, m);
memcpy (msg->buffer + STUN_MESSAGE_TRANS_ID_POS, memcpy (msg->buffer + STUN_MESSAGE_TRANS_ID_POS,
id, sizeof (STUN_MESSAGE_TRANS_ID_LEN)); id, STUN_MESSAGE_TRANS_ID_LEN);
return TRUE; return TRUE;
} }
...@@ -304,8 +304,7 @@ void * ...@@ -304,8 +304,7 @@ void *
stun_message_append (StunMessage *msg, stun_attr_type_t type, size_t length) stun_message_append (StunMessage *msg, stun_attr_type_t type, size_t length)
{ {
uint8_t *a; uint8_t *a;
uint16_t mlen = stun_message_length (msg); uint16_t mlen = stun_message_length (msg) - STUN_MESSAGE_HEADER_LENGTH;
if ((((size_t)mlen) + STUN_ATTRIBUTE_HEADER_LENGTH + length) > msg->buffer_len) if ((((size_t)mlen) + STUN_ATTRIBUTE_HEADER_LENGTH + length) > msg->buffer_len)
return NULL; return NULL;
......
...@@ -8,16 +8,21 @@ ...@@ -8,16 +8,21 @@
# #
include $(top_srcdir)/common.mk include $(top_srcdir)/common.mk
AM_CFLAGS = -std=gnu99 AM_CFLAGS = -std=gnu99
AM_CPPFLAGS = -I$(top_srcdir) AM_CPPFLAGS = -I$(top_srcdir)
bin_PROGRAMS = stunbdc stund bin_PROGRAMS = stunbdc stund
check_PROGRAMS = stund check_PROGRAMS = stund
stund_SOURCES = stund.c stund.h stund_SOURCES = stund.c stund.h
stund_LDADD = ../libstun.la -lpthread stund_LDADD = ../libstun.la -lpthread
stunbdc_SOURCES = stunbdc.c \
bind.c bind.h \
trans.c trans.h \
timer.c timer.h
stunbdc_LDADD = ../libstun.la stunbdc_LDADD = ../libstun.la
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
#include <sys/socket.h> #include <sys/socket.h>
#include "bind.h" #include "bind.h"
#include "stun-msg.h" #include "stun/stunagent.h"
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
...@@ -60,8 +60,23 @@ ...@@ -60,8 +60,23 @@
struct stun_bind_s struct stun_bind_s
{ {
stun_trans_t trans; stun_trans_t trans;
StunAgent agent;
}; };
static const uint16_t known_attributes[] = {
STUN_ATTRIBUTE_MAPPED_ADDRESS,
STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
STUN_ATTRIBUTE_XOR_INTERNAL_ADDRESS,
STUN_ATTRIBUTE_FINGERPRINT,
STUN_ATTRIBUTE_ALTERNATE_SERVER,
STUN_ATTRIBUTE_PRIORITY,
STUN_ATTRIBUTE_USE_CANDIDATE,
STUN_ATTRIBUTE_ICE_CONTROLLING,
STUN_ATTRIBUTE_ICE_CONTROLLED,
STUN_ATTRIBUTE_USERNAME,
STUN_ATTRIBUTE_REFRESH_INTERVAL,
0
};
/** Initialization/deinitization */ /** Initialization/deinitization */
...@@ -100,8 +115,14 @@ stun_bind_alloc (stun_bind_t **restrict context, int fd, ...@@ -100,8 +115,14 @@ stun_bind_alloc (stun_bind_t **restrict context, int fd,
return val; return val;
} }
stun_init_request (ctx->trans.msg.buf, STUN_BINDING); stun_agent_init (&ctx->agent, known_attributes,
ctx->trans.msg.length = sizeof (ctx->trans.msg.buf); STUN_COMPATIBILITY_3489BIS,
STUN_AGENT_USAGE_ADD_SERVER);
stun_agent_init_request (&ctx->agent, &ctx->trans.message,
ctx->trans.msg.buf, sizeof (ctx->trans.msg.buf), STUN_BINDING);
ctx->trans.msg.length = ctx->trans.message.buffer_len;
return 0; return 0;
} }
...@@ -117,9 +138,12 @@ int stun_bind_start (stun_bind_t **restrict context, int fd, ...@@ -117,9 +138,12 @@ int stun_bind_start (stun_bind_t **restrict context, int fd,
return val; return val;
ctx = *context; ctx = *context;
val = stun_finish (ctx->trans.msg.buf, &ctx->trans.msg.length, compat);
if (val) val = stun_agent_finish_message (&ctx->agent, &ctx->trans.message, NULL, 0);
if (val == 0)
goto error; goto error;
ctx->trans.msg.length = val;
val = stun_trans_start (&ctx->trans); val = stun_trans_start (&ctx->trans);
if (val) if (val)
...@@ -168,7 +192,7 @@ int stun_bind_process (stun_bind_t *restrict ctx, ...@@ -168,7 +192,7 @@ int stun_bind_process (stun_bind_t *restrict ctx,
assert (ctx != NULL); assert (ctx != NULL);
val = stun_trans_preprocess (&ctx->trans, &code, buf, len); val = stun_trans_preprocess (&ctx->agent, &ctx->trans, &code, buf, len);
switch (val) switch (val)
{ {
case EAGAIN: case EAGAIN:
...@@ -176,26 +200,28 @@ int stun_bind_process (stun_bind_t *restrict ctx, ...@@ -176,26 +200,28 @@ int stun_bind_process (stun_bind_t *restrict ctx,
case 0: case 0:
break; break;
default: default:
if (code == STUN_ROLE_CONFLICT) if (code == STUN_ERROR_ROLE_CONFLICT)
val = ECONNRESET; val = ECONNRESET;
stun_bind_cancel (ctx); stun_bind_cancel (ctx);
return val; return val;
} }
val = stun_find_xor_addr (buf, STUN_XOR_MAPPED_ADDRESS, addr, addrlen); val = stun_message_find_xor_addr (&ctx->trans.message,
STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, addr, addrlen);
if (val) if (val)
{ {
DBG (" No XOR-MAPPED-ADDRESS: %s\n", strerror (val)); stun_debug (" No XOR-MAPPED-ADDRESS: %s\n", strerror (val));
val = stun_find_addr (buf, STUN_MAPPED_ADDRESS, addr, addrlen); val = stun_message_find_addr (&ctx->trans.message,
STUN_ATTRIBUTE_MAPPED_ADDRESS, addr, addrlen);
if (val) if (val)
{ {
DBG (" No MAPPED-ADDRESS: %s\n", strerror (val)); stun_debug (" No MAPPED-ADDRESS: %s\n", strerror (val));
stun_bind_cancel (ctx); stun_bind_cancel (ctx);
return val; return val;
} }
} }
DBG (" Mapped address found!\n"); stun_debug (" Mapped address found!\n");
stun_bind_cancel (ctx); stun_bind_cancel (ctx);
return 0; return 0;
} }
...@@ -208,7 +234,7 @@ int stun_bind_run (int fd, ...@@ -208,7 +234,7 @@ int stun_bind_run (int fd,
struct sockaddr *restrict addr, socklen_t *addrlen, int compat) struct sockaddr *restrict addr, socklen_t *addrlen, int compat)
{ {
stun_bind_t *ctx; stun_bind_t *ctx;
uint8_t buf[STUN_MAXMSG]; uint8_t buf[STUN_MAX_MESSAGE_SIZE];
ssize_t val; ssize_t val;
val = stun_bind_start (&ctx, fd, srv, srvlen, compat); val = stun_bind_start (&ctx, fd, srv, srvlen, compat);
...@@ -231,7 +257,7 @@ int stun_bind_run (int fd, ...@@ -231,7 +257,7 @@ int stun_bind_run (int fd,
return val; return val;
} }
#if 0
/** ICE keep-alives (Binding discovery indication!) */ /** ICE keep-alives (Binding discovery indication!) */
int int
...@@ -240,23 +266,26 @@ stun_bind_keepalive (int fd, const struct sockaddr *restrict srv, ...@@ -240,23 +266,26 @@ stun_bind_keepalive (int fd, const struct sockaddr *restrict srv,
{ {
uint8_t buf[28]; uint8_t buf[28];
size_t len = sizeof (buf); size_t len = sizeof (buf);
int val; StunAgent agent;
StunMessage msg;
stun_agent_init (&agent, known_attributes,
STUN_COMPATIBILITY_3489BIS,
STUN_AGENT_USAGE_USE_FINGERPRINT);
stun_agent_init_indication (&agent, &msg,
buf, sizeof (buf), STUN_BINDING);
len = stun_agent_finish_message (&agent, &msg, NULL, 0);
stun_init_indication (buf, STUN_BINDING); assert (len == sizeof(buf));
val = stun_finish (buf, &len, compat);
assert (val == 0);
(void)val;
/* NOTE: hopefully, this is only needed for non-stream sockets */ /* NOTE: hopefully, this is only needed for non-stream sockets */
if (stun_sendto (fd, buf, len, srv, srvlen) == -1) if (stun_sendto (fd, buf, len, srv, srvlen) == -1)
return errno; return errno;
return 0; return 0;
} }
#endif
/** Connectivity checks */
#include "stun-ice.h"
int int
stun_conncheck_start (stun_bind_t **restrict context, int fd, stun_conncheck_start (stun_bind_t **restrict context, int fd,
const struct sockaddr *restrict srv, socklen_t srvlen, const struct sockaddr *restrict srv, socklen_t srvlen,
...@@ -290,29 +319,38 @@ stun_conncheck_start (stun_bind_t **restrict context, int fd, ...@@ -290,29 +319,38 @@ stun_conncheck_start (stun_bind_t **restrict context, int fd,
if (compat != 1) { if (compat != 1) {
if (cand_use) if (cand_use)
{ {
val = stun_append_flag (ctx->trans.msg.buf, val = stun_message_append_flag (&ctx->trans.message,
sizeof (ctx->trans.msg.buf), STUN_ATTRIBUTE_USE_CANDIDATE);
STUN_USE_CANDIDATE);
if (val) if (val)
goto error; goto error;
} }
val = stun_append32 (ctx->trans.msg.buf, sizeof (ctx->trans.msg.buf), val = stun_message_append32 (&ctx->trans.message,
STUN_PRIORITY, priority); STUN_ATTRIBUTE_PRIORITY, priority);
if (val) if (val)
goto error; goto error;
val = stun_append64 (ctx->trans.msg.buf, sizeof (ctx->trans.msg.buf), val = stun_message_append64 (&ctx->trans.message,
controlling ? STUN_ICE_CONTROLLING controlling ? STUN_ATTRIBUTE_ICE_CONTROLLING
: STUN_ICE_CONTROLLED, tie); : STUN_ATTRIBUTE_ICE_CONTROLLED, tie);
if (val) if (val)
goto error; goto error;
} }
val = stun_finish_short (ctx->trans.msg.buf, &ctx->trans.msg.length, if (username) {
username, compat == 1 ? NULL : password, NULL, compat); val = stun_message_append_string (&ctx->trans.message,
if (val) STUN_ATTRIBUTE_USERNAME, username);
if (val)
goto error;
}
val = stun_agent_finish_message (&ctx->agent, &ctx->trans.message,
compat == 1 ? NULL : (const uint8_t *) password,
compat == 1 ? 0 : strlen (password));
if (val == 0)
goto error; goto error;
ctx->trans.msg.length = val;
val = stun_trans_start (&ctx->trans); val = stun_trans_start (&ctx->trans);
if (val) if (val)
...@@ -359,15 +397,13 @@ int stun_nested_start (stun_nested_t **restrict context, int fd, ...@@ -359,15 +397,13 @@ int stun_nested_start (stun_nested_t **restrict context, int fd,
*context = ctx; *context = ctx;
val = stun_append32 (ctx->bind->trans.msg.buf, val = stun_message_append32 (&ctx->bind->trans.message,
sizeof (ctx->bind->trans.msg.buf), STUN_ATTRIBUTE_REFRESH_INTERVAL, refresh);
STUN_REFRESH_INTERVAL, refresh);
if (val) if (val)
goto error; goto error;
val = stun_finish (ctx->bind->trans.msg.buf, val = stun_agent_finish_message (&ctx->bind->agent,
&ctx->bind->trans.msg.length, &ctx->bind->trans.message, NULL, 0);
compat);
if (val) if (val)
goto error; goto error;
...@@ -403,21 +439,24 @@ int stun_nested_process (stun_nested_t *restrict ctx, ...@@ -403,21 +439,24 @@ int stun_nested_process (stun_nested_t *restrict ctx,
if (sockaddrcmp ((struct sockaddr *)&mapped, if (sockaddrcmp ((struct sockaddr *)&mapped,
(struct sockaddr *)&ctx->mapped)) (struct sockaddr *)&ctx->mapped))
{ {
DBG (" Mapped address mismatch! (Symmetric NAT?)\n"); stun_debug (" Mapped address mismatch! (Symmetric NAT?)\n");
return ECONNREFUSED; return ECONNREFUSED;
} }
val = stun_find_xor_addr (buf, STUN_XOR_INTERNAL_ADDRESS, intad, adlen); val = stun_message_find_xor_addr (&ctx->bind->trans.message,
STUN_ATTRIBUTE_XOR_INTERNAL_ADDRESS,
intad, adlen);
if (val) if (val)
{ {
DBG (" No XOR-INTERNAL-ADDRESS: %s\n", strerror (val)); stun_debug (" No XOR-INTERNAL-ADDRESS: %s\n", strerror (val));
return val; return val;
} }
stun_find32 (buf, STUN_REFRESH_INTERVAL, &ctx->refresh); stun_message_find32 (&ctx->bind->trans.message,
STUN_ATTRIBUTE_REFRESH_INTERVAL, &ctx->refresh);
/* TODO: give this to caller */ /* TODO: give this to caller */
DBG (" Internal address found!\n"); stun_debug (" Internal address found!\n");
stun_bind_cancel (ctx->bind); stun_bind_cancel (ctx->bind);
ctx->bind = NULL; ctx->bind = NULL;
return 0; return 0;
......
...@@ -39,7 +39,8 @@ ...@@ -39,7 +39,8 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include "stunagent.h" #include "stun/stunagent.h"
#include "bind.h"
#include <unistd.h> #include <unistd.h>
#include <getopt.h> #include <getopt.h>
......
...@@ -62,9 +62,13 @@ ...@@ -62,9 +62,13 @@
/** Default port for STUN binding discovery */ /** Default port for STUN binding discovery */
#define IPPORT_STUN 3478 #define IPPORT_STUN 3478
#include "stun/stun-msg.h" #include "stun/stunagent.h"
#include "stund.h" #include "stund.h"
static const uint16_t known_attributes[] = {
0
};
/** /**
* Creates a listening socket * Creates a listening socket
*/ */
...@@ -185,12 +189,16 @@ ssize_t send_safe (int fd, const struct msghdr *msg) ...@@ -185,12 +189,16 @@ ssize_t send_safe (int fd, const struct msghdr *msg)
} }
static int dgram_process (int sock) static int dgram_process (int sock, StunAgent *agent)
{ {
struct sockaddr_storage addr; struct sockaddr_storage addr;
uint8_t buf[STUN_MAXMSG]; uint8_t buf[STUN_MAX_MESSAGE_SIZE];
char ctlbuf[CMSG_SPACE (sizeof (struct in6_pktinfo))]; char ctlbuf[CMSG_SPACE (sizeof (struct in6_pktinfo))];
struct iovec iov = { buf, sizeof (buf) }; struct iovec iov = { buf, sizeof (buf) };
StunMessage request;
StunMessage response;
StunValidationStatus validation;
struct msghdr mh = struct msghdr mh =
{ {
.msg_name = (struct sockaddr *)&addr, .msg_name = (struct sockaddr *)&addr,
...@@ -205,37 +213,42 @@ static int dgram_process (int sock) ...@@ -205,37 +213,42 @@ static int dgram_process (int sock)
if (len == (size_t)-1) if (len == (size_t)-1)
return -1; return -1;
/* Mal-formatted packets */ validation = stun_agent_validate (agent, &request, buf, len, NULL, 0);
if ((stun_validate (buf, len) <= 0)
|| (stun_get_class (buf) != STUN_REQUEST))
return -1;
/* Unknown attributes */ /* Unknown attributes */
if (stun_has_unknown (buf)) if (validation == STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE)
{ {
stun_init_error_unknown (buf, sizeof (buf), buf, 0); stun_agent_build_unknown_attributes_error (agent, &response, buf,
goto finish; sizeof (buf), &request);
goto send_buf;
}
/* Mal-formatted packets */
if (validation != STUN_VALIDATION_SUCCESS ||
stun_message_get_class (&request) != STUN_REQUEST) {
return -1;
} }
switch (stun_get_method (buf)) switch (stun_message_get_method (&request))
{ {
case STUN_BINDING: case STUN_BINDING:
stun_init_response (buf, sizeof (buf), buf, 0); stun_agent_init_response (agent, &response, buf, sizeof (buf), &request);
if (stun_has_cookie (buf)) if (stun_has_cookie (&request))
stun_append_xor_addr (buf, sizeof (buf), stun_message_append_xor_addr (&response,
STUN_XOR_MAPPED_ADDRESS, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
mh.msg_name, mh.msg_namelen); mh.msg_name, mh.msg_namelen);
else else
stun_append_addr (buf, sizeof (buf), STUN_MAPPED_ADDRESS, stun_message_append_addr (&response, STUN_ATTRIBUTE_MAPPED_ADDRESS,
mh.msg_name, mh.msg_namelen); mh.msg_name, mh.msg_namelen);
break; break;
default: default:
stun_init_error (buf, sizeof (buf), buf, STUN_BAD_REQUEST, 0); stun_agent_init_error (agent, &response, buf, sizeof (buf),
&request, STUN_ERROR_BAD_REQUEST);
} }
finish: iov.iov_len = stun_agent_finish_message (agent, &response, NULL, 0);
stun_finish (buf, &iov.iov_len, 0); send_buf:
len = send_safe (sock, &mh); len = send_safe (sock, &mh);
return (len < iov.iov_len) ? -1 : 0; return (len < iov.iov_len) ? -1 : 0;
...@@ -244,12 +257,17 @@ finish: ...@@ -244,12 +257,17 @@ finish:
static int run (int family, int protocol, unsigned port) static int run (int family, int protocol, unsigned port)
{ {
StunAgent agent;
int sock = listen_socket (family, SOCK_DGRAM, protocol, htons (port)); int sock = listen_socket (family, SOCK_DGRAM, protocol, htons (port));
if (sock == -1) if (sock == -1)
return -1; return -1;
stun_agent_init (&agent, known_attributes,
STUN_COMPATIBILITY_3489BIS, STUN_AGENT_USAGE_ADD_SERVER);
for (;;) for (;;)
dgram_process (sock); dgram_process (sock, &agent);
} }
......
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
# include <poll.h> # include <poll.h>
#endif #endif
#include "stun-msg.h" #include "stun/stunagent.h"
#include "trans.h" #include "trans.h"
#define TRANS_OWN_FD 0x1 /* descriptor belongs to us */ #define TRANS_OWN_FD 0x1 /* descriptor belongs to us */
...@@ -199,7 +199,7 @@ int stun_trans_start (stun_trans_t *tr) ...@@ -199,7 +199,7 @@ int stun_trans_start (stun_trans_t *tr)
else else
stun_timer_start (&tr->timer); stun_timer_start (&tr->timer);
DBG ("STUN transaction @%p started (timeout: %ums)\n", tr, stun_debug ("STUN transaction @%p started (timeout: %ums)\n", tr,
stun_trans_timeout (tr)); stun_trans_timeout (tr));
val = stun_trans_send (tr); val = stun_trans_send (tr);
...@@ -324,7 +324,7 @@ int stun_trans_tick (stun_trans_t *tr) ...@@ -324,7 +324,7 @@ int stun_trans_tick (stun_trans_t *tr)
switch (stun_timer_refresh (&tr->timer)) switch (stun_timer_refresh (&tr->timer))
{ {
case -1: case -1:
DBG ("STUN transaction @%p failed: time out.\n", tr); stun_debug ("STUN transaction @%p failed: time out.\n", tr);
return ETIMEDOUT; // fatal error! return ETIMEDOUT; // fatal error!
case 0: case 0:
...@@ -333,7 +333,7 @@ int stun_trans_tick (stun_trans_t *tr) ...@@ -333,7 +333,7 @@ int stun_trans_tick (stun_trans_t *tr)
tr->msg.offset = 0; tr->msg.offset = 0;
stun_trans_send (tr); stun_trans_send (tr);
DBG ("STUN transaction @%p retransmitted (timeout: %ums).\n", tr, stun_debug ("STUN transaction @%p retransmitted (timeout: %ums).\n", tr,
stun_trans_timeout (tr)); stun_trans_timeout (tr));
} }
return EAGAIN; return EAGAIN;
...@@ -401,27 +401,32 @@ int stun_trans_recv (stun_trans_t *tr, uint8_t *buf, size_t buflen) ...@@ -401,27 +401,32 @@ int stun_trans_recv (stun_trans_t *tr, uint8_t *buf, size_t buflen)
int stun_trans_preprocess (stun_trans_t *restrict tr, int *pcode, int stun_trans_preprocess (StunAgent *agent,
const void *restrict buf, size_t len) stun_trans_t *restrict tr, int *pcode,
const void *restrict buf, size_t len)
{ {
StunValidationStatus valid;
assert (pcode != NULL); assert (pcode != NULL);
/* FIXME: possible infinite loop */ *pcode = -1;
if (stun_validate (buf, len) <= 0)
return EAGAIN;
DBG ("Received %u-bytes STUN message\n", valid = stun_agent_validate (agent, &tr->message, buf, len, NULL, NULL);
(unsigned)stun_validate (buf, len)); if (valid == STUN_VALIDATION_UNKNOWN_ATTRIBUTE)
/* NOTE: currently we ignore unauthenticated messages if the context return EPROTO;
* is authenticated, for security reasons. */
if (!stun_match_messages (buf, tr->msg.buf, tr->key.value, tr->key.length, if (valid != STUN_VALIDATION_SUCCESS)
pcode))
return EAGAIN; return EAGAIN;
stun_debug ("Received %u-bytes STUN message\n", (unsigned)len);
/* NOTE: currently we ignore unauthenticated messages if the context
* is authenticated, for security reasons. */
if (stun_message_get_class (&tr->message) == STUN_ERROR) {
stun_message_find_error (&tr->message, pcode);
}
if (*pcode >= 0) if (*pcode >= 0)
{ {
DBG (" STUN error message received (code: %d)\n", *pcode); stun_debug (" STUN error message received (code: %d)\n", *pcode);
/* ALTERNATE-SERVER mechanism */ /* ALTERNATE-SERVER mechanism */
if ((tr->key.value != NULL) && ((*pcode / 100) == 3)) if ((tr->key.value != NULL) && ((*pcode / 100) == 3))
...@@ -429,10 +434,10 @@ int stun_trans_preprocess (stun_trans_t *restrict tr, int *pcode, ...@@ -429,10 +434,10 @@ int stun_trans_preprocess (stun_trans_t *restrict tr, int *pcode,
struct sockaddr_storage srv; struct sockaddr_storage srv;
socklen_t slen = sizeof (srv); socklen_t slen = sizeof (srv);
if (stun_find_addr (buf, STUN_ALTERNATE_SERVER, if (stun_message_find_addr (&tr->message, STUN_ATTRIBUTE_ALTERNATE_SERVER,
(struct sockaddr *)&srv, &slen)) (struct sockaddr *)&srv, &slen))
{ {
DBG (" Unexpectedly missing ALTERNATE-SERVER attribute\n"); stun_debug (" Unexpectedly missing ALTERNATE-SERVER attribute\n");
return ECONNREFUSED; return ECONNREFUSED;
} }
...@@ -441,7 +446,7 @@ int stun_trans_preprocess (stun_trans_t *restrict tr, int *pcode, ...@@ -441,7 +446,7 @@ int stun_trans_preprocess (stun_trans_t *restrict tr, int *pcode,
if (connect (tr->sock.fd, (struct sockaddr *)&srv, slen)) if (connect (tr->sock.fd, (struct sockaddr *)&srv, slen))
{ {
/* This error case includes address family mismatch */ /* This error case includes address family mismatch */
DBG (" Error switching to alternate server: %s\n", stun_debug (" Error switching to alternate server: %s\n",
strerror (errno)); strerror (errno));
return ECONNREFUSED; return ECONNREFUSED;
} }
...@@ -451,26 +456,23 @@ int stun_trans_preprocess (stun_trans_t *restrict tr, int *pcode, ...@@ -451,26 +456,23 @@ int stun_trans_preprocess (stun_trans_t *restrict tr, int *pcode,
if ((tr->sock.dst.ss_family != srv.ss_family) if ((tr->sock.dst.ss_family != srv.ss_family)
|| (slen > sizeof (tr->sock.dst))) || (slen > sizeof (tr->sock.dst)))
{ {
DBG (" Unsupported alternate server\n"); stun_debug (" Unsupported alternate server\n");
return ECONNREFUSED; return ECONNREFUSED;
} }
memcpy (&tr->sock.dst, &srv, tr->sock.dstlen = slen); memcpy (&tr->sock.dst, &srv, tr->sock.dstlen = slen);
} }
DBG (" Restarting with alternate server\n"); stun_debug (" Restarting with alternate server\n");
if (stun_trans_start (tr) == 0) if (stun_trans_start (tr) == 0)
return EAGAIN; return EAGAIN;
DBG (" Restart failed!\n"); stun_debug (" Restart failed!\n");
} }
return ECONNREFUSED; return ECONNREFUSED;
} }
if (stun_has_unknown (buf))
return EPROTO;
return 0; return 0;
} }
......
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
# include <sys/socket.h> # include <sys/socket.h>
# include "timer.h" # include "timer.h"
#include "stun/stunagent.h"
typedef struct stun_trans_s typedef struct stun_trans_s
{ {
...@@ -54,8 +55,9 @@ typedef struct stun_trans_s ...@@ -54,8 +55,9 @@ typedef struct stun_trans_s
struct struct
{ {
size_t length, offset; size_t length, offset;
uint8_t buf[STUN_MAXMSG]; uint8_t buf[STUN_MAX_MESSAGE_SIZE];
} msg; } msg;
StunMessage message;
struct struct
{ {
...@@ -149,8 +151,9 @@ int stun_trans_tick (stun_trans_t *tr); ...@@ -149,8 +151,9 @@ int stun_trans_tick (stun_trans_t *tr);
int stun_trans_recv (stun_trans_t *tr, uint8_t *buf, size_t buflen); int stun_trans_recv (stun_trans_t *tr, uint8_t *buf, size_t buflen);
int stun_trans_preprocess (stun_trans_t *restrict tr, int *code, int stun_trans_preprocess (StunAgent *agent,
const void *restrict buf, size_t len); stun_trans_t *restrict tr, int *code,
const void *restrict buf, size_t len);
/** /**
* Safe wrapper around sendto() * Safe wrapper around sendto()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment