Commit b9669017 authored by Youness Alaoui's avatar Youness Alaoui

Updating stun to include an agent

parent c07afc9a
......@@ -19,16 +19,18 @@ CLEANFILES += $(BUILT_SOURCES)
noinst_LTLIBRARIES = libstun.la
dist_noinst_SCRIPTS = build-unknown.sh
libstun_la_SOURCES = \
stun-msg.h stunsend.c stunrecv.c \
stun3489bis.c \
utils.c \
unknown.c \
crc32.c hmac.c \
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_SOURCES = stun.h constants.h \
stunagent.c stunagent.h \
stunmessage.c stunmessage.h \
stun3489bis.c stun3489bis.h \
stuncrc32.c stuncrc32.h \
stunhmac.c stunhmac.h \
utils.c utils.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)
......
......@@ -67,9 +67,9 @@
#define STUN_ID_LEN 16
#define STUN_AGENT_MAX_SAVED_IDS 20
#define STUN_AGENT_MAX_UNKNOWN_ATTRIBUTES 256
#define STUN_COOKIE 0x2112A442
#define STUN_MAGIC_COOKIE 0x2112A442
#ifndef TRUE
#define TRUE (1 == 1)
......
This diff is collapsed.
......@@ -35,19 +35,24 @@
* file under either the MPL or the LGPL.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <sys/socket.h>
#include <netinet/in.h> /* htons() */
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include "crc32.h"
#include "stun-msg.h"
#include "stuncrc32.h"
#include "stunmessage.h"
uint32_t stun_fingerprint (const uint8_t *msg, size_t len)
{
struct iovec iov[3];
uint16_t fakelen = htons (len - 20u);
assert (len >= 28u);
// assert (len >= 28u);
iov[0].iov_base = (void *)msg;
iov[0].iov_len = 2;
......@@ -57,5 +62,22 @@ uint32_t stun_fingerprint (const uint8_t *msg, size_t len)
/* first 4 bytes done, last 8 bytes not summed */
iov[2].iov_len = len - 12u;
return crc32 (iov, sizeof (iov) / sizeof (iov[0])) ^ 0x5354554e;
return htonl (crc32 (iov, sizeof (iov) / sizeof (iov[0])) ^ 0x5354554e);
}
bool stun_has_cookie (const StunMessage *msg)
{
stun_transid_t id;
stun_message_id (msg, id);
uint32_t cookie = htonl (STUN_MAGIC_COOKIE);
return memcmp (id, &cookie, sizeof (cookie)) == 0;
}
int stun_message_append_server (StunMessage *msg)
{
static const char server[] = PACKAGE_STRING;
// assert (strlen (server) < 128);
return stun_message_append_string (msg, STUN_ATTRIBUTE_SERVER, server);
}
......@@ -54,8 +54,10 @@
*/
uint32_t stun_fingerprint (const uint8_t *msg, size_t len);
bool stun_has_cookie (const StunMessage *msg);
int stun_message_append_server (StunMessage *msg);
bool stun_has_cookie (const uint8_t *msg);
#endif /* _STUN_3489BIS_H */
This diff is collapsed.
/*
* This file is part of the Nice GLib ICE library.
*
* (C) 2008 Collabora Ltd.
* (C) 2008 Nokia Corporation. All rights reserved.
* Contact: Youness Alaoui
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Nice GLib ICE library.
*
* The Initial Developers of the Original Code are Collabora Ltd and Nokia
* Corporation. All Rights Reserved.
*
*
* Alternatively, the contents of this file may be used under the terms of the
* the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
* case the provisions of LGPL are applicable instead of those above. If you
* wish to allow use of your version of this file only under the terms of the
* LGPL and not to allow others to use your version of this file under the
* MPL, indicate your decision by deleting the provisions above and replace
* them with the notice and other provisions required by the LGPL. If you do
* not delete the provisions above, a recipient may use your version of this
* file under either the MPL or the LGPL.
*/
#ifndef _STUN_AGENT_H
#define _STUN_AGENT_H
#include <stdint.h>
#include <sys/types.h>
#include <stdbool.h>
typedef struct stun_agent_t StunAgent;
#include "stunmessage.h"
typedef enum {
STUN_COMPATIBILITY_RFC3489,
STUN_COMPATIBILITY_3489BIS,
STUN_COMPATIBILITY_LAST = STUN_COMPATIBILITY_3489BIS
} StunCompatibility;
typedef enum {
STUN_VALIDATION_SUCCESS,
STUN_VALIDATION_NOT_STUN,
STUN_VALIDATION_INCOMPLETE_STUN,
STUN_VALIDATION_BAD_REQUEST,
STUN_VALIDATION_UNAUTHORIZED,
STUN_VALIDATION_UNMATCHED_RESPONSE,
STUN_VALIDATION_UNKNOWN_ATTRIBUTE,
STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE
} StunValidationStatus;
#define STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS 0x0001
#define STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS 0x0002
#define STUN_AGENT_USAGE_USE_FINGERPRINT 0x0004
#define STUN_AGENT_USAGE_ADD_SERVER 0x0008
#define STUN_AGENT_USAGE_IGNORE_CREDENTIALS 0x000F
typedef struct {
stun_transid_t id;
stun_method_t method;
uint8_t *key;
size_t key_len;
bool valid;
} StunAgentSavedIds;
struct stun_agent_t {
StunCompatibility compatibility;
StunAgentSavedIds sent_ids[STUN_AGENT_MAX_SAVED_IDS];
uint16_t *known_attributes;
uint32_t usage_flags;
};
typedef bool (*StunMessageIntegrityValidate) (StunAgent *agent,
StunMessage *message, uint8_t *username, uint16_t username_len,
uint8_t **password, size_t *password_len, void *user_data);
void stun_agent_init (StunAgent *agent, const uint16_t *known_attributes,
StunCompatibility compatibility, uint32_t usage_flags);
StunValidationStatus stun_agent_validate (StunAgent *agent, StunMessage *msg,
const uint8_t *buffer, size_t buffer_len,
StunMessageIntegrityValidate validater, void * validater_data);
bool stun_agent_init_request (StunAgent *agent, StunMessage *msg,
uint8_t *buffer, size_t buffer_len, stun_method_t m);
bool stun_agent_init_indication (StunAgent *agent, StunMessage *msg,
uint8_t *buffer, size_t buffer_len, stun_method_t m);
bool stun_agent_init_response (StunAgent *agent, StunMessage *msg,
uint8_t *buffer, size_t buffer_len, stun_method_t m, StunMessage *request);
bool stun_agent_init_error (StunAgent *agent, StunMessage *msg,
uint8_t *buffer, size_t buffer_len, StunMessage *request,
stun_error_t err);
size_t stun_agent_build_unknown_attributes_error (StunAgent *agent,
StunMessage *msg, uint8_t *buffer, size_t buffer_len, StunMessage *request);
size_t stun_agent_finish_message (StunAgent *agent, StunMessage *msg,
uint8_t *key, size_t key_len);
#endif /* _STUN_AGENT_H */
......@@ -87,7 +87,7 @@
# include <config.h>
#endif
#include "crc32.h"
#include "stuncrc32.h"
static const uint32_t crc32_tab[] = {
......
......@@ -45,7 +45,7 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>
#include "stun-msg.h"
#include "stunmessage.h"
#include "stunhmac.h"
#include <string.h>
......
......@@ -35,6 +35,8 @@
#ifndef _STUN_HMAC_H
#define _STUN_HMAC_H
#include "stunmessage.h"
/**
* Computes the MESSAGE-INTEGRITY hash of a STUN message.
* @param msg pointer to the STUN message
......@@ -61,4 +63,4 @@ void stun_hash_creds (const char *realm, const char *login, const char *pw,
void stun_make_transid (stun_transid_t id);
/* _STUN_HMAC_H */
#endif /* _STUN_HMAC_H */
......@@ -61,12 +61,8 @@ bool stun_message_init (StunMessage *msg, stun_class_t c, stun_method_t m,
memset (msg->buffer, 0, 4);
stun_set_type (msg->buffer, c, m);
if (msg->buffer != id)
{
uint32_t cookie = htonl (STUN_COOKIE);
memcpy (msg->buffer + 4, &cookie, sizeof (cookie));
memcpy (msg->buffer + 8, id, 12);
}
memcpy (msg->buffer + STUN_MESSAGE_TRANS_ID_POS,
id, sizeof (STUN_MESSAGE_TRANS_ID_LEN));
return TRUE;
}
......@@ -107,12 +103,12 @@ stun_message_find (const StunMessage *msg, stun_attr_type_t type,
/* Look for and ignore misordered attributes */
switch (atype)
{
case STUN_MESSAGE_INTEGRITY:
case STUN_ATTRIBUTE_MESSAGE_INTEGRITY:
/* Only fingerprint may come after M-I */
if (type == STUN_FINGERPRINT)
if (type == STUN_ATTRIBUTE_FINGERPRINT)
break;
case STUN_FINGERPRINT:
case STUN_ATTRIBUTE_FINGERPRINT:
/* Nothing may come after FPR */
return NULL;
}
......@@ -273,10 +269,10 @@ stun_message_find_xor_addr (const StunMessage *msg, stun_attr_type_t type,
return stun_xor_address (msg, addr, *addrlen);
}
int stun_message_find_errno (const StunMessage *msg, int *restrict code)
int stun_message_find_error (const StunMessage *msg, int *restrict code)
{
uint16_t alen;
const uint8_t *ptr = stun_message_find (msg, STUN_ERROR_CODE, &alen);
const uint8_t *ptr = stun_message_find (msg, STUN_ATTRIBUTE_ERROR_CODE, &alen);
uint8_t class, number;
if (ptr == NULL)
......@@ -319,7 +315,7 @@ stun_message_append (StunMessage *msg, stun_attr_type_t type, size_t length)
a = stun_setw (a, type);
/* NOTE: If cookie is not present, we need to force the attribute length
* to a multiple of 4 for compatibility with old RFC3489 */
a = stun_setw (a, stun_has_cookie (msg->buffer) ? length : stun_align (length));
a = stun_setw (a, stun_has_cookie (msg) ? length : stun_align (length));
mlen += 4 + length;
/* Add padding if needed */
......@@ -473,7 +469,7 @@ stun_message_append_error (StunMessage *msg, stun_error_t code)
size_t len = strlen (str);
div_t d = div (code, 100);
uint8_t *ptr = stun_message_append (msg, STUN_ERROR_CODE, 4 + len);
uint8_t *ptr = stun_message_append (msg, STUN_ATTRIBUTE_ERROR_CODE, 4 + len);
if (ptr == NULL)
return ENOBUFS;
......@@ -484,7 +480,7 @@ stun_message_append_error (StunMessage *msg, stun_error_t code)
return 0;
}
bool stun_message_is_valid (const uint8_t *msg, size_t length)
int stun_message_validate_buffer_length (const uint8_t *msg, size_t length)
{
size_t mlen;
size_t len;
......@@ -492,19 +488,19 @@ bool stun_message_is_valid (const uint8_t *msg, size_t length)
if (length < 1)
{
stun_debug ("STUN error: No data!\n");
return FALSE;
return STUN_MESSAGE_BUFFER_INVALID;
}
if (msg[0] >> 6)
{
stun_debug ("STUN error: RTP or other non-protocol packet!\n");
return FALSE; // RTP or other non-STUN packet
return STUN_MESSAGE_BUFFER_INVALID; // RTP or other non-STUN packet
}
if (length < 4)
{
stun_debug ("STUN error: Incomplete STUN message header!\n");
return FALSE;
return STUN_MESSAGE_BUFFER_INCOMPLETE;
}
mlen = stun_getw (msg + STUN_MESSAGE_LENGTH_POS) +
......@@ -513,14 +509,14 @@ bool stun_message_is_valid (const uint8_t *msg, size_t length)
if (stun_padding (mlen))
{
stun_debug ("STUN error: Invalid message length: %u!\n", (unsigned)mlen);
return FALSE; // wrong padding
return STUN_MESSAGE_BUFFER_INVALID; // wrong padding
}
if (length < mlen)
{
stun_debug ("STUN error: Incomplete message: %u of %u bytes!\n",
(unsigned)length, (unsigned)mlen);
return FALSE; // partial message
return STUN_MESSAGE_BUFFER_INCOMPLETE; // partial message
}
msg += 20;
......@@ -539,12 +535,54 @@ bool stun_message_is_valid (const uint8_t *msg, size_t length)
{
stun_debug ("STUN error: %u instead of %u bytes for attribute!\n",
(unsigned)len, (unsigned)alen);
return -1; // no room for attribute value + padding
return STUN_MESSAGE_BUFFER_INVALID; // no room for attribute value + padding
}
len -= alen;
msg += 4 + alen;
}
return mlen == length;
return mlen;
}
/**
* copies STUN message transaction ID
*/
void stun_message_id (const StunMessage *msg, stun_transid_t id)
{
memcpy (id, msg->buffer + STUN_MESSAGE_TRANS_ID_POS, STUN_MESSAGE_TRANS_ID_LEN);
}
/**
* @return STUN message method (value from 0 to 0xfff)
*/
stun_method_t stun_message_get_method (const StunMessage *msg)
{
uint16_t t = stun_getw (msg->buffer);
return (stun_method_t)(((t & 0x3e00) >> 2) | ((t & 0x00e0) >> 1) |
(t & 0x000f));
}
/**
* @return STUN message class in host byte order (value from 0 to 3)
*/
stun_class_t stun_message_get_class (const StunMessage *msg)
{
uint16_t t = stun_getw (msg->buffer);
return (stun_class_t)(((t & 0x0100) >> 7) | ((t & 0x0010) >> 4));
}
/**
* Checks if an attribute is present within a STUN message.
*
* @param msg valid STUN message
* @param type STUN attribute type (host byte order)
*
* @return whether there is a MESSAGE-INTEGRITY attribute
*/
bool stun_message_has_attribute (const StunMessage *msg, stun_attr_type_t type)
{
uint16_t dummy;
return stun_message_find (msg, type, &dummy) != NULL;
}
......@@ -41,12 +41,7 @@
#include <stdbool.h>
#include "constants.h"
typedef struct {
uint8_t *buffer;
size_t buffer_len;
bool message_id_validated;
} StunMessage;
typedef struct stun_message_t StunMessage;
/* Message classes */
typedef enum
......@@ -78,65 +73,65 @@ typedef enum
{
/* Mandatory attributes */
/* 0x0000 */ /* reserved */
STUN_MAPPED_ADDRESS=0x0001, /* RFC3489bis-11 */
STUN_OLD_RESPONSE_ADDRESS=0x0002, /* old RFC3489 */
STUN_OLD_CHANGE_REQUEST=0x0003, /* old RFC3489 */
STUN_OLD_SOURCE_ADDRESS=0x0004, /* old RFC3489 */
STUN_OLD_CHANGED_ADDRESS=0x0005, /* old RFC3489 */
STUN_USERNAME=0x0006, /* RFC3489bis-11 */
STUN_OLD_PASSWORD=0x0007, /* old RFC3489 */
STUN_MESSAGE_INTEGRITY=0x0008, /* RFC3489bis-11 */
STUN_ERROR_CODE=0x0009, /* RFC3489bis-11 */
STUN_UNKNOWN_ATTRIBUTES=0x000A, /* RFC3489bis-11 */
STUN_OLD_REFLECTED_FROM=0x000B, /* old RFC3489 */
STUN_ATTRIBUTE_MAPPED_ADDRESS=0x0001, /* RFC3489bis-11 */
STUN_ATTRIBUTE_OLD_RESPONSE_ADDRESS=0x0002, /* old RFC3489 */
STUN_ATTRIBUTE_OLD_CHANGE_REQUEST=0x0003, /* old RFC3489 */
STUN_ATTRIBUTE_OLD_SOURCE_ADDRESS=0x0004, /* old RFC3489 */
STUN_ATTRIBUTE_OLD_CHANGED_ADDRESS=0x0005, /* old RFC3489 */
STUN_ATTRIBUTE_USERNAME=0x0006, /* RFC3489bis-11 */
STUN_ATTRIBUTE_OLD_PASSWORD=0x0007, /* old RFC3489 */
STUN_ATTRIBUTE_MESSAGE_INTEGRITY=0x0008, /* RFC3489bis-11 */
STUN_ATTRIBUTE_ERROR_CODE=0x0009, /* RFC3489bis-11 */
STUN_ATTRIBUTE_UNKNOWN_ATTRIBUTES=0x000A, /* RFC3489bis-11 */
STUN_ATTRIBUTE_OLD_REFLECTED_FROM=0x000B, /* old RFC3489 */
/* 0x000C */ /* reserved */
STUN_LIFETIME=0x000D, /* TURN-04 */
STUN_ATTRIBUTE_LIFETIME=0x000D, /* TURN-04 */
/* 0x000E */ /* reserved */
/* 0x000F */ /* reserved */
STUN_BANDWIDTH=0x0010, /* TURN-04 */
STUN_ATTRIBUTE_BANDWIDTH=0x0010, /* TURN-04 */
/* 0x0011 */ /* reserved */
STUN_REMOTE_ADDRESS=0x0012, /* TURN-04 */
STUN_DATA=0x0013, /* TURN-04 */
STUN_REALM=0x0014, /* RFC3489bis-11 */
STUN_NONCE=0x0015, /* RFC3489bis-11 */
STUN_RELAY_ADDRESS=0x0016, /* TURN-04 */
STUN_REQUESTED_ADDRESS_TYPE=0x0017, /* TURN-IPv6-03 */
STUN_REQUESTED_PORT_PROPS=0x0018, /* TURN-04 */
STUN_REQUESTED_TRANSPORT=0x0019, /* TURN-04 */
STUN_ATTRIBUTE_REMOTE_ADDRESS=0x0012, /* TURN-04 */
STUN_ATTRIBUTE_DATA=0x0013, /* TURN-04 */
STUN_ATTRIBUTE_REALM=0x0014, /* RFC3489bis-11 */
STUN_ATTRIBUTE_NONCE=0x0015, /* RFC3489bis-11 */
STUN_ATTRIBUTE_RELAY_ADDRESS=0x0016, /* TURN-04 */
STUN_ATTRIBUTE_REQUESTED_ADDRESS_TYPE=0x0017, /* TURN-IPv6-03 */
STUN_ATTRIBUTE_REQUESTED_PORT_PROPS=0x0018, /* TURN-04 */
STUN_ATTRIBUTE_REQUESTED_TRANSPORT=0x0019, /* TURN-04 */
/* 0x001A */ /* reserved */
/* 0x001B */ /* reserved */
/* 0x001C */ /* reserved */
/* 0x001D */ /* reserved */
/* 0x001E */ /* reserved */
/* 0x001F */ /* reserved */
STUN_XOR_MAPPED_ADDRESS=0x0020, /* RFC3489bis-11 */
STUN_TIMER_VAL=0x0021, /* TURN-04 */
STUN_REQUESTED_IP=0x0022, /* TURN-04 */
STUN_CONNECT_STAT=0x0023, /* TURN-04 */
STUN_PRIORITY=0x0024, /* ICE-18 */
STUN_USE_CANDIDATE=0x0025, /* ICE-18 */
STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS=0x0020, /* RFC3489bis-11 */
STUN_ATTRIBUTE_TIMER_VAL=0x0021, /* TURN-04 */
STUN_ATTRIBUTE_REQUESTED_IP=0x0022, /* TURN-04 */
STUN_ATTRIBUTE_CONNECT_STAT=0x0023, /* TURN-04 */
STUN_ATTRIBUTE_PRIORITY=0x0024, /* ICE-18 */
STUN_ATTRIBUTE_USE_CANDIDATE=0x0025, /* ICE-18 */
/* 0x0026 */ /* reserved */
/* 0x0027 */ /* reserved */
/* 0x0028 */ /* reserved */
STUN_XOR_INTERNAL_ADDRESS=0x0029, /* wing-nat-control-04 */
STUN_ATTRIBUTE_XOR_INTERNAL_ADDRESS=0x0029, /* wing-nat-control-04 */
/* 0x002A-0x7fff */ /* reserved */
/* Optional attributes */
/* 0x8000-0x8021 */ /* reserved */
STUN_SERVER=0x8022, /* RFC3489bis-11 */
STUN_ALTERNATE_SERVER=0x8023, /* RFC3489bis-11 */
STUN_REFRESH_INTERVAL=0x8024, /* wing-nat-control-04 */
STUN_ATTRIBUTE_SERVER=0x8022, /* RFC3489bis-11 */
STUN_ATTRIBUTE_ALTERNATE_SERVER=0x8023, /* RFC3489bis-11 */
STUN_ATTRIBUTE_REFRESH_INTERVAL=0x8024, /* wing-nat-control-04 */
/* 0x8025 */ /* reserved */
/* 0x8026 */ /* reserved */
/* 0x8027 */ /* reserved */
STUN_FINGERPRINT=0x8028, /* RFC3489bis-11 */
STUN_ICE_CONTROLLED=0x8029, /* ICE-18 */
STUN_ICE_CONTROLLING=0x802A, /* ICE-18 */
STUN_ATTRIBUTE_FINGERPRINT=0x8028, /* RFC3489bis-11 */
STUN_ATTRIBUTE_ICE_CONTROLLED=0x8029, /* ICE-18 */
STUN_ATTRIBUTE_ICE_CONTROLLING=0x802A, /* ICE-18 */
/* 0x802B-0xFFFF */ /* reserved */
} stun_attr_type_t;
typedef uint8_t stun_transid_t[12];
typedef uint8_t stun_transid_t[STUN_MESSAGE_TRANS_ID_LEN];
/**
......@@ -145,32 +140,41 @@ typedef uint8_t stun_transid_t[12];
*/
typedef enum
{
STUN_TRY_ALTERNATE=300, /* RFC3489bis-11 */
STUN_BAD_REQUEST=400, /* RFC3489bis-11 */
STUN_UNAUTHORIZED=401, /* RFC3489bis-11 */
STUN_UNKNOWN_ATTRIBUTE=420, /* RFC3489bis-11 */
STUN_NO_BINDING=437, /* TURN-04 */
STUN_STALE_NONCE=438, /* RFC3489bis-11 */
STUN_ACT_DST_ALREADY=439, /* TURN-04 */
STUN_UNSUPP_FAMILY=440, /* TURN-IPv6-03 */
STUN_UNSUPP_TRANSPORT=442, /* TURN-04 */
STUN_INVALID_IP=443, /* TURN-04 */
STUN_INVALID_PORT=444, /* TURN-04 */
STUN_OP_TCP_ONLY=445, /* TURN-04 */
STUN_CONN_ALREADY=446, /* TURN-04 */
STUN_ALLOC_OVER_QUOTA=486, /* TURN-04 */
STUN_ROLE_CONFLICT=487, /* ICE-18 */
STUN_SERVER_ERROR=500, /* RFC3489bis-11 */
STUN_SERVER_CAPACITY=507, /* TURN-04 */
STUN_ERROR_TRY_ALTERNATE=300, /* RFC3489bis-11 */
STUN_ERROR_BAD_REQUEST=400, /* RFC3489bis-11 */
STUN_ERROR_UNAUTHORIZED=401, /* RFC3489bis-11 */
STUN_ERROR_UNKNOWN_ATTRIBUTE=420, /* RFC3489bis-11 */
STUN_ERROR_NO_BINDING=437, /* TURN-04 */
STUN_ERROR_STALE_NONCE=438, /* RFC3489bis-11 */
STUN_ERROR_ACT_DST_ALREADY=439, /* TURN-04 */
STUN_ERROR_UNSUPP_FAMILY=440, /* TURN-IPv6-03 */
STUN_ERROR_UNSUPP_TRANSPORT=442, /* TURN-04 */
STUN_ERROR_INVALID_IP=443, /* TURN-04 */
STUN_ERROR_INVALID_PORT=444, /* TURN-04 */
STUN_ERROR_OP_TCP_ONLY=445, /* TURN-04 */
STUN_ERROR_CONN_ALREADY=446, /* TURN-04 */
STUN_ERROR_ALLOC_OVER_QUOTA=486, /* TURN-04 */
STUN_ERROR_ROLE_CONFLICT=487, /* ICE-18 */
STUN_ERROR_SERVER_ERROR=500, /* RFC3489bis-11 */
STUN_ERROR_SERVER_CAPACITY=507, /* TURN-04 */
STUN_ERROR_MAX=699
} stun_error_t;
#include "stunagent.h"
#include "stunhmac.h"
#include "stuncrc32.h"
#include "utils.h"
#include "stun3489bis.h"
struct stun_message_t {
StunAgent *agent;
uint8_t *buffer;
size_t buffer_len;
uint8_t *key;
size_t key_len;
};
/**
* Initializes a STUN message buffer, with no attributes.
* @param c STUN message class (host byte order)
......@@ -281,7 +285,7 @@ int stun_message_find_xor_addr (const StunMessage *msg, stun_attr_type_t type,
struct sockaddr *restrict addr, socklen_t *restrict addrlen);
int stun_message_find_errno (const StunMessage *msg, int *restrict code);
int stun_message_find_error (const StunMessage *msg, int *restrict code);
void *stun_message_append (StunMessage *msg, stun_attr_type_t type,
size_t length);
......@@ -368,7 +372,16 @@ int stun_message_append_xor_addr (StunMessage * msg, stun_attr_type_t type,
*/
int stun_message_append_error (StunMessage * msg, stun_error_t code);
bool stun_message_is_valid (const uint8_t *msg, size_t length);
#define STUN_MESSAGE_BUFFER_INCOMPLETE 0
#define STUN_MESSAGE_BUFFER_INVALID -1
int stun_message_validate_buffer_length (const uint8_t *msg, size_t length);
void stun_message_id (const StunMessage *msg, stun_transid_t id);
stun_class_t stun_message_get_class (const StunMessage *msg);
stun_method_t stun_message_get_method (const StunMessage *msg);
bool stun_message_has_attribute (const StunMessage *msg, stun_attr_type_t type);
#endif /* _STUN_MESSAGE_H */
This diff is collapsed.
This diff is collapsed.
......@@ -50,6 +50,9 @@
#include <errno.h>
# define STUN_MAX_STR (763u)
# define STUN_MAX_CP (127u)
static void fatal (const char *msg, ...)
{
va_list ap;
......
......@@ -39,7 +39,7 @@
#include <sys/types.h>
#include <sys/socket.h>
#include "stun/usages/bind.h"
#include "stunagent.h"
#include <unistd.h>
#include <getopt.h>
......
......@@ -38,9 +38,13 @@
#endif
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include "utils.h"
/** Compares two socket addresses */
......@@ -115,97 +119,180 @@ uint16_t stun_getw (const uint8_t *ptr)
return ((ptr)[0] << 8) | ptr[1];
}
uint16_t stun_length (const uint8_t *ptr)
{
return stun_getw (ptr + 2);
}
/**
* @return STUN message class in host byte order (value from 0 to 3)
*/
stun_class_t stun_get_class (const uint8_t *msg)
/* /\** */
/* * @param msg valid STUN message */
/* * @return true if there is at least one unknown mandatory attribute. */
/* *\/ */
/* bool stun_has_unknown (const void *msg) */
/* { */
/* uint16_t dummy; */
/* return stun_find_unknown (msg, &dummy, 1); */
/* } */
void stun_debug (const char *fmt, ...)
{
uint16_t t = stun_getw (msg);
return (stun_class_t)(((t & 0x0100) >> 7) | ((t & 0x0010) >> 4));
va_list ap;
va_start (ap, fmt);
vfprintf (stderr, fmt, ap);
va_end (ap);
}
/**
* @return STUN message method (value from 0 to 0xfff)
*/
stun_method_t stun_get_method (const uint8_t *msg)
void stun_debug_bytes (const void *data, size_t len)
{
uint16_t t = stun_getw (msg);
return (stun_method_t)(((t & 0x3e00) >> 2) | ((t & 0x00e0) >> 1) |
(t & 0x000f));
}
size_t i;
stun_debug ("0x");
for (i = 0; i < len; i++)
stun_debug ("%02x", ((const unsigned char *)data)[i]);
}
/**
* @return STUN message transaction ID
*/
const uint8_t *stun_id (const uint8_t *msg)
int stun_xor_address (const StunMessage *msg,
struct sockaddr *restrict addr, socklen_t addrlen)
{
//assert (stun_valid (req));
return msg + 8;
switch (addr->sa_family)
{
case AF_INET:
{
struct sockaddr_in *ip4 = (struct sockaddr_in *)addr;
if (addrlen < sizeof (*ip4))
return EINVAL;
ip4->sin_port ^= htons (STUN_MAGIC_COOKIE >> 16);
ip4->sin_addr.s_addr ^= htonl (STUN_MAGIC_COOKIE);
return 0;
}
case AF_INET6:
{
struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)addr;
unsigned short i;
if (addrlen < sizeof (*ip6))
return EINVAL;
ip6->sin6_port ^= htons (STUN_MAGIC_COOKIE >> 16);
for (i = 0; i < 16; i++)
ip6->sin6_addr.s6_addr[i] ^= msg->buffer[4 + i];
return 0;
}
}
return EAFNOSUPPORT;
}
/**
* Checks if an attribute is present within a STUN message.
* Compares the length and content of an attribute.
*
* @param msg valid STUN message
* @param msg valid STUN message buffer
* @param type STUN attribute type (host byte order)
*
* @return whether there i