diff options
Diffstat (limited to 'branches/1.0/tinyNET/src/stun/tnet_stun_message.c')
-rw-r--r-- | branches/1.0/tinyNET/src/stun/tnet_stun_message.c | 440 |
1 files changed, 0 insertions, 440 deletions
diff --git a/branches/1.0/tinyNET/src/stun/tnet_stun_message.c b/branches/1.0/tinyNET/src/stun/tnet_stun_message.c deleted file mode 100644 index 9769092..0000000 --- a/branches/1.0/tinyNET/src/stun/tnet_stun_message.c +++ /dev/null @@ -1,440 +0,0 @@ -/* -* Copyright (C) 2009-2010 Mamadou Diop. -* -* Contact: Mamadou Diop <diopmamadou(at)doubango.org> -* -* This file is part of Open Source Doubango Framework. -* -* DOUBANGO is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* DOUBANGO is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with DOUBANGO. -* -*/ - -/**@file tnet_stun_message.c - * @brief STUN2 (RFC 5389) message parser. - * - * @author Mamadou Diop <diopmamadou(at)doubango.org> - * - * @date Created: Sat Nov 8 16:54:58 2009 mdiop - */ -#include "tnet_stun_message.h" - -#include "tnet_stun.h" - -#include "../tnet_types.h" -#include "../tnet_endianness.h" -#include "../turn/tnet_turn_attribute.h" - -#include "tsk_memory.h" -#include "tsk_hmac.h" -#include "tsk_string.h" -#include "tsk_ppfcs32.h" - -#include <string.h> - - -/**@ingroup tnet_stun_group -* Creates new STUN message. -* @retval @ref tnet_stun_message_t object. -* @sa tnet_stun_message_create_null. -*/ - -tnet_stun_message_t* tnet_stun_message_create(const char* username, const char* password) -{ - return tsk_object_new(tnet_stun_message_def_t, username, password); -} - -/**@ingroup tnet_stun_group -* Creates new STUN message. -* @retval @ref tnet_stun_message_t object. -* @sa tnet_stun_message_create. -*/ -tnet_stun_message_t* tnet_stun_message_create_null() -{ - return tnet_stun_message_create(tsk_null, tsk_null); -} - -#define SERIALIZE_N_ADD_ATTRIBUTE(att_name, payload, payload_size) \ - attribute = (tnet_stun_attribute_t *)tnet_stun_attribute_##att_name##_create(payload, payload_size); \ - tnet_stun_attribute_serialize(attribute, output); \ - tnet_stun_attribute_pad(attribute, output); \ - TSK_OBJECT_SAFE_FREE(attribute); - -/**@ingroup tnet_stun_group - * Serializes a STUN message as binary data. - * @param [in,out] self The STUN message to serialize. - * @retval A buffer holding the binary data (result) if serialization succeed and zero otherwise. -**/ -tsk_buffer_t* tnet_stun_message_serialize(const tnet_stun_message_t *self) -{ - tsk_buffer_t *output = 0; - tnet_stun_attribute_t *attribute; - unsigned compute_integrity = self->integrity; - - if(!self){ - goto bail; - } - - output = tsk_buffer_create_null(); - - /* RFC 5389 - 6. STUN Message Structure - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - |0 0| STUN Message Type | Message Length | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Magic Cookie | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | - | Transaction ID (96 bits) | - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - */ - - /* STUN Message Type - */ - { - uint16_t type = tnet_htons(self->type); - tsk_buffer_append(output, &(type), 2); - } - - /* Message Length ==> Will be updated after attributes have been added. */ - { - uint16_t length = 0; - tsk_buffer_append(output, &(length), 2); - } - - /* Magic Cookie - */ - { - uint32_t cookie = tnet_htonl(self->cookie); - tsk_buffer_append(output, &(cookie), 4); - } - - - /* Transaction ID (96 bits==>16bytes) - */ - tsk_buffer_append(output, self->transaction_id, TNET_STUN_TRANSACID_SIZE); - - /* DONT-FRAGMENT - */ - if(self->dontfrag){ - attribute = (tnet_stun_attribute_t *)tnet_turn_attribute_dontfrag_create(); - tnet_stun_attribute_serialize(attribute, output); - TSK_OBJECT_SAFE_FREE(attribute); - } - - /*=== Attributes === - */ - { - tsk_list_item_t *item; - tsk_list_foreach(item, self->attributes) - { - attribute = item->data; - tnet_stun_attribute_serialize(attribute, output); - tnet_stun_attribute_pad(attribute, output); - } - } - - /* AUTHENTICATION */ - if(self->realm && self->nonce){ - SERIALIZE_N_ADD_ATTRIBUTE(username, self->username, tsk_strlen(self->username)); - SERIALIZE_N_ADD_ATTRIBUTE(realm, self->realm, tsk_strlen(self->realm)); - SERIALIZE_N_ADD_ATTRIBUTE(nonce, self->nonce, tsk_strlen(self->nonce)); - - compute_integrity = 1; - } - - /* Message Length: The message length MUST contain the size, in bytes, of the message - not including the 20-byte STUN header. - */ - { - uint16_t length = (output->size) - TNET_STUN_HEADER_SIZE; - if(self->fingerprint) - length += (2/* Type */ + 2 /* Length */+ 4 /* FINGERPRINT VALUE*/); - - if(compute_integrity) - length += (2/* Type */ + 2 /* Length */+ TSK_SHA1_DIGEST_SIZE /* INTEGRITY VALUE*/); - - *(((uint16_t*)output->data)+1) = tnet_htons(length); - } - - /* MESSAGE-INTEGRITY */ - if(compute_integrity){ - /* RFC 5389 - 15.4. MESSAGE-INTEGRITY - The MESSAGE-INTEGRITY attribute contains an HMAC-SHA1 [RFC2104] of the STUN message. - - For long-term credentials ==> key = MD5(username ":" realm ":" SASLprep(password)) - For short-term credentials ==> key = SASLprep(password) - FIXME: what about short term credentials? - FIXME: what about SASLprep - */ - char* keystr = 0; - tsk_sha1digest_t hmac; - tsk_md5digest_t md5; - - tsk_sprintf(&keystr, "%s:%s:%s", self->username, self->realm, self->password); - TSK_MD5_DIGEST_CALC(keystr, tsk_strlen(keystr), md5); - hmac_sha1digest_compute(output->data, output->size, (const char*)md5, TSK_MD5_DIGEST_SIZE, hmac); - - SERIALIZE_N_ADD_ATTRIBUTE(integrity, hmac, TSK_SHA1_DIGEST_SIZE); - - TSK_FREE(keystr); - } - - /* FINGERPRINT */ - if(self->fingerprint){ - /* RFC 5389 - 15.5. FINGERPRINT - The FINGERPRINT attribute MAY be present in all STUN messages. The - value of the attribute is computed as the CRC-32 of the STUN message - up to (but excluding) the FINGERPRINT attribute itself, XOR'ed with - the 32-bit value 0x5354554e - */ - uint32_t fingerprint = tsk_pppfcs32(TSK_PPPINITFCS32, output->data, output->size); - fingerprint ^= 0x5354554e; - fingerprint = tnet_htonl(fingerprint); - - attribute = (tnet_stun_attribute_t *)tnet_stun_attribute_fingerprint_create(fingerprint); - tnet_stun_attribute_serialize(attribute, output); - TSK_OBJECT_SAFE_FREE(attribute); - } - -bail: - return output; -} - - -/**@ingroup tnet_stun_group - * - * Deserializes a STUN message from binary data. - * - * @param [in,out] data A pointer to the binary data. - * @param size The size of the binary data. - * - * @retval A STUN message if deserialization succeed or NULL otherwise. -**/ -tnet_stun_message_t* tnet_stun_message_deserialize(const uint8_t *data, tsk_size_t size) -{ - tnet_stun_message_t *message = 0; - uint8_t* dataPtr, *dataEnd; - - - if(!data || (size < TNET_STUN_HEADER_SIZE) || !TNET_IS_STUN2(data)) - { - goto bail; - } - - dataPtr = (uint8_t*)data; - dataEnd = (dataPtr + size); - - message = tnet_stun_message_create_null(); - - /* Message Type - */ - message->type = (tnet_stun_message_type_t)tnet_ntohs_2(dataPtr); - dataPtr += 2; - - /* Message Length - */ - message->length = tnet_ntohs_2(dataPtr); - dataPtr += 2; - - /* Check message validity - */ - if((message->length + TNET_STUN_HEADER_SIZE) != size) - { - TSK_OBJECT_SAFE_FREE(message); - goto bail; - } - - /* Magic Cookie - ==> already set by the constructor and checked by @ref TNET_IS_STUN2 - */ - dataPtr += 4; - - /* Transaction ID - */ - memcpy(message->transaction_id, dataPtr, TNET_STUN_TRANSACID_SIZE); - dataPtr += TNET_STUN_TRANSACID_SIZE; - - /* == Parse attributes - */ - while(dataPtr < dataEnd){ - tnet_stun_attribute_t *attribute = tnet_stun_attribute_deserialize(dataPtr, (dataEnd - dataPtr)); - if(attribute){ - tsk_size_t att_size = (attribute->length + 2 /* Type*/ + 2/* Length */); - att_size += (att_size%4) ? 4-(att_size%4) : 0; // Skip zero bytes used to pad the attribute. - - dataPtr += att_size; - tsk_list_push_back_data(message->attributes, (void**)&attribute); - - continue; - } - else{ - continue; - } - - - - - } - - -bail: - return message; -} - -/**@ingroup tnet_stun_group -* Adds an attribute to a STUN message. -* @param self The STUN message into which to add the attribute. -* @param attribute The attribute to add. -* @retval Zero if succeed and non-zero error code otherwise. -*/ -int tnet_stun_message_add_attribute(tnet_stun_message_t *self, tnet_stun_attribute_t** attribute) -{ - //if(self && attribute) - { - tsk_list_push_back_data(self->attributes, (void**)attribute); - return 0; - } - return -1; -} - -/**@ingroup tnet_stun_group -* Gets a STUN attribute from a message. -* @param self The message from which to get the attribute. -* @param type The type of the attribute to retrieve. -* @retval @ref tnet_stun_attribute_t object if found and NULL otherwise. -*/ -const tnet_stun_attribute_t* tnet_stun_message_get_attribute(const tnet_stun_message_t *self, tnet_stun_attribute_type_t type) -{ - tnet_stun_attribute_t* attribute; - - if(self && !TSK_LIST_IS_EMPTY(self->attributes)){ - tsk_list_item_t *item; - tsk_list_foreach(item, self->attributes){ - if((attribute = item->data) && attribute->type == type){ - return attribute; - } - } - } - return 0; -} - -/**@ingroup tnet_stun_group -* Gets the STUN error-code attribute value from the message. -* @param self The STUN message from which to get the error code. -* @retval The error code if the message contain such attribute or -1 otherwise. -*/ -short tnet_stun_message_get_errorcode(const tnet_stun_message_t *self) -{ - const tnet_stun_attribute_errorcode_t* error = (const tnet_stun_attribute_errorcode_t*)tnet_stun_message_get_attribute(self, stun_error_code); - if(error){ - return ((error->_class*100) + error->number); - } - return -1; -} - -/**@ingroup tnet_stun_group -* Gets the STUN @b realm attribute value from the message. -* @param self The STUN message from which to get the @b realm. -* @retval The @b realm as a string pointer code if the message contain such attribute or NULL otherwise. -*/ -const char* tnet_stun_message_get_realm(const tnet_stun_message_t *self) -{ - const tnet_stun_attribute_realm_t* realm = (const tnet_stun_attribute_realm_t*)tnet_stun_message_get_attribute(self, stun_realm); - if(realm){ - return realm->value; - } - return 0; -} - -/**@ingroup tnet_stun_group -* Gets the STUN @b nonce attribute value from the message. -* @param self The STUN message from which to get the @b nonce. -* @retval The @b nonce as a string pointer code if the message contain such attribute or NULL otherwise. -*/ -const char* tnet_stun_message_get_nonce(const tnet_stun_message_t *self) -{ - const tnet_stun_attribute_nonce_t* nonce = (const tnet_stun_attribute_nonce_t*)tnet_stun_message_get_attribute(self, stun_nonce); - if(nonce){ - return nonce->value; - } - return 0; -} - -/**@ingroup tnet_stun_group -* Gets the STUN @b lifetime attribute value from the message. -* @param self The STUN message from which to get the @b lifetime. -* @retval The @b lifetime (any positive value) if the message contain such attribute or -1 otherwise. -*/ -int32_t tnet_stun_message_get_lifetime(const tnet_stun_message_t *self) -{ - const tnet_turn_attribute_lifetime_t* lifetime = (const tnet_turn_attribute_lifetime_t*)tnet_stun_message_get_attribute(self, stun_lifetime); - if(lifetime){ - return lifetime->value; - } - return -1; -} - - - - - - - - - -//================================================================================================= -// STUN2 MESSAGE object definition -// -static tsk_object_t* tnet_stun_message_ctor(tsk_object_t * self, va_list * app) -{ - tnet_stun_message_t *message = self; - if(message){ - message->username = tsk_strdup(va_arg(*app, const char*)); - message->password = tsk_strdup(va_arg(*app, const char*)); - - message->cookie = TNET_STUN_MAGIC_COOKIE; - message->attributes = tsk_list_create(); - - message->fingerprint = 1; - message->integrity = 0; - } - return self; -} - -static tsk_object_t* tnet_stun_message_dtor(tsk_object_t * self) -{ - tnet_stun_message_t *message = self; - if(message){ - TSK_FREE(message->username); - TSK_FREE(message->password); - TSK_FREE(message->realm); - TSK_FREE(message->nonce); - - TSK_OBJECT_SAFE_FREE(message->attributes); - } - - return self; -} - -static const tsk_object_def_t tnet_stun_message_def_s = -{ - sizeof(tnet_stun_message_t), - tnet_stun_message_ctor, - tnet_stun_message_dtor, - tsk_null, -}; -const tsk_object_def_t *tnet_stun_message_def_t = &tnet_stun_message_def_s; - |