24 #include <boost/crc.hpp> 27 #include <openssl/evp.h> 28 #include <openssl/hmac.h> 29 #include <openssl/md5.h> 31 #define COMMON_DIGEST_FOR_OPENSSL 32 #include <CommonCrypto/CommonCrypto.h> 96 return (pAttrib != NULL);
105 boost::crc_32_type crc;
106 uint32_t computedValue=1;
107 uint32_t readValue=0;
125 ptr = spBuffer->GetData();
128 crc.process_bytes(ptr, size-8);
129 computedValue = crc.checksum();
132 readValue = *(uint32_t*)(ptr+pAttrib->
offset);
133 readValue = ntohl(readValue);
134 hr = (readValue==computedValue) ?
S_OK :
E_FAIL;
150 bool fFingerprintAdjustment =
false;
151 bool fNoOtherAttributesAfterIntegrity =
false;
152 const size_t c_hmacsize = 20;
153 uint8_t hmaccomputed[c_hmacsize] = {};
154 unsigned int hmaclength = c_hmacsize;
158 CCHmacContext ctx = {};
169 bool fContextInit =
false;
189 ChkIf(fNoOtherAttributesAfterIntegrity==
false,
E_FAIL);
194 stream.
Attach(spBuffer,
false);
199 HMAC_Init(&ctx, key, keylength, EVP_sha1());
201 CCHmacInit(&ctx, kCCHmacAlgSHA1, key, keylength);
208 HMAC_Update(&ctx, (
unsigned char*)&chunk16,
sizeof(chunk16));
210 CCHmacUpdate(&ctx, &chunk16,
sizeof(chunk16));
215 if (fFingerprintAdjustment)
220 uint16_t lengthHeader = ntohs(chunk16);
221 uint16_t adjustedlengthHeader = lengthHeader - 8;
224 chunk16 = htons(adjustedlengthHeader);
228 HMAC_Update(&ctx, (
unsigned char*)&chunk16,
sizeof(chunk16));
230 CCHmacUpdate(&ctx, &chunk16,
sizeof(chunk16));
234 len = pAttribIntegrity->
offset;
242 for (
size_t count = 0; count < nChunks; count++)
246 HMAC_Update(&ctx, (
unsigned char*)&chunk32,
sizeof(chunk32));
248 CCHmacUpdate(&ctx, &chunk32,
sizeof(chunk32));
253 HMAC_Final(&ctx, hmaccomputed, &hmaclength);
255 CCHmacFinal(&ctx, hmaccomputed);
260 cmp = memcmp(hmaccomputed, spBuffer->GetData() + pAttribIntegrity->
offset, c_hmacsize);
268 HMAC_CTX_cleanup(&ctx);
286 uint8_t key[MAX_KEY_SIZE + 1];
287 uint8_t* pData = NULL;
289 size_t totallength = 0;
291 size_t passwordlength = pszPassword ? strlen(pszPassword) : 0;
292 size_t userLength = pszUser ? strlen(pszUser) : 0;
293 size_t realmLength = pszRealm ? strlen(pszRealm) : 0;
295 uint8_t hash[MD5_DIGEST_LENGTH] = {};
299 totallength = userLength + realmLength + passwordlength + 2;
306 memcpy(pDst, pszUser, userLength);
315 memcpy(pDst, pszRealm, realmLength);
321 if (passwordlength > 0)
323 memcpy(pDst, pszPassword, passwordlength);
324 pDst += passwordlength;
328 ASSERT((pDst-key) == totallength);
333 CC_MD5(key, totallength, hash);
357 *pAttribute = *pFound;
373 *pAttribute = *pFound;
389 uint8_t *pData = NULL;
402 *pPort = ntohs(portNBO);
410 uint8_t *pData = NULL;
426 value = ntohl(value);
428 pChangeRequest->
fChangeIP = !!(value & 0x0004);
432 if (
FAILED(hr) && pChangeRequest)
455 *pSizePadding = pAttrib->
size;
482 *pErrorNumber = cl * 100 + num;
493 uint8_t *pAddrStart = NULL;
577 pszValue[pAttrib->
size] =
'\0';
590 bool fHeaderValid =
false;
602 msgType = ntohs(msgType);
603 msgLength = ntohs(msgLength);
605 memcpy(&cookie, transID.
id, 4);
606 cookie = ntohl(cookie);
610 fHeaderValid = ( (0==(msgType & 0xc000)) && ((msgLength%4)==0) );
617 _msgTypeNormalized = ( (msgType & 0x000f) | ((msgType & 0x00e0)>>1) | ((msgType & 0x3E00)>>2) );
662 while (
SUCCEEDED(hr) && (bytesConsumed < currentSize))
664 uint16_t attributeType;
665 uint16_t attributeLength;
666 uint16_t attributeOffset;
679 attributeType = ntohs(attributeType);
680 attributeLength = ntohs(attributeLength);
683 if (attributeLength % 4)
685 paddingLength = 4 - attributeLength % 4;
696 attrib.
size = attributeLength;
697 attrib.
offset = attributeOffset;
730 if (paddingLength > 0)
738 bytesConsumed +=
sizeof(attributeType) +
sizeof(attributeLength) + attributeLength + paddingLength;
743 hr = (bytesConsumed == currentSize) ?
S_OK :
E_FAIL;
const uint32_t MAX_STUN_MESSAGE_SIZE
HRESULT GetAddressHelper(uint16_t attribType, CSocketAddress *pAddr)
HRESULT GetChangeRequest(StunChangeRequestAttribute *pChangeRequest)
CDataStream & GetStream()
uint16_t GetMessageType()
const uint16_t STUN_ATTRIBUTE_ERRORCODE
HRESULT GetAttributeByType(uint16_t attributeType, StunAttribute *pAttribute)
const uint16_t STUN_ATTRIBUTE_PADDING
HRESULT ValidateMessageIntegrityLong(const char *pszUser, const char *pszRealm, const char *pszPassword)
const uint16_t STUN_ATTRIBUTE_RESPONSE_ORIGIN
HRESULT SeekRelative(int nOffset)
HRESULT Read(void *data, size_t size)
HRESULT GetBuffer(CRefCountedBuffer *pRefBuffer)
void ApplyStunXorMap(const StunTransactionId &id)
void GetTransactionId(StunTransactionId *pTransId)
HRESULT GetBuffer(CRefCountedBuffer *pRefCountedBuffer)
const uint32_t STUN_COOKIE
bool HasFingerprintAttribute()
HRESULT GetMappedAddress(CSocketAddress *pAddress)
StunMessageClass _msgClass
#define UNREFERENCED_VARIABLE(unrefparam)
int Insert(const K &key, V &value)
#define STUN_IS_SUCCESS_RESP(msg_type)
const uint16_t STUN_ATTRIBUTE_FINGERPRINT
#define ChkIf(expr, hrerror)
ReaderParseState AddBytes(const uint8_t *pData, uint32_t size)
#define STUN_IS_INDICATION(msg_type)
bool IsMessageLegacyFormat()
HRESULT ReadUint16(uint16_t *pVal)
V * LookupValueByIndex(size_t index)
HRESULT GetOtherAddress(CSocketAddress *pAddress)
const uint16_t STUN_ATTRIBUTE_CHANGEREQUEST
const uint16_t STUN_ATTRIBUTE_XORMAPPEDADDRESS
const uint32_t MAX_STUN_AUTH_STRING_SIZE
const uint16_t STUN_ATTRIBUTE_RESPONSE_PORT
uint16_t _msgTypeNormalized
ReaderParseState GetState()
const uint16_t STUN_ATTRIBUTE_MAPPEDADDRESS
const uint16_t STUN_ATTRIBUTE_RESPONSE_PORT_SIZE
HRESULT GetErrorCode(uint16_t *pErrorNumber)
HRESULT ValidateMessageIntegrityShort(const char *pszPassword)
HRESULT GetResponsePort(uint16_t *pPort)
HRESULT GetPaddingAttributeSize(uint16_t *pSizePadding)
const uint16_t STUN_ATTRIBUTE_CHANGEDADDRESS
HRESULT ValidateMessageIntegrity(uint8_t *key, size_t keylength)
#define STUN_IS_REQUEST(msg_type)
const uint32_t MAX_STUN_ATTRIBUTE_SIZE
uint8_t * GetDataPointerUnsafe()
HRESULT Write(const void *data, size_t size)
bool IsFingerprintAttributeValid()
const uint16_t STUN_ATTRIBUTE_XORMAPPEDADDRESS_OPTIONAL
bool _fMessageIsLegacyFormat
uint8_t id[STUN_TRANSACTION_ID_LENGTH]
HRESULT SeekDirect(size_t pos)
StunMessageClass GetMessageClass()
const uint16_t STUN_ATTRIBUTE_SOURCEADDRESS
const uint16_t STUN_ATTRIBUTE_CHANGEREQUEST_SIZE
const uint16_t STUN_ATTRIBUTE_MESSAGEINTEGRITY
bool HasMessageIntegrityAttribute()
#define STUN_IS_ERR_RESP(msg_type)
const uint32_t STUN_FINGERPRINT_XOR
HRESULT ReadUint32(uint32_t *pVal)
boost::shared_ptr< CBuffer > CRefCountedBuffer
void SetAllowLegacyFormat(bool fAllowLegacyFormat)
HRESULT GetStringAttributeByType(uint16_t attributeType, char *pszValue, size_t size)
StunTransactionId _transactionid
void Attach(CRefCountedBuffer &buffer, bool fForWriting)
AttributeHashTable _mapAttributes
uint16_t HowManyBytesNeeded()
#define ChkIfA(expr, hrerror)
HRESULT GetAttributeByIndex(int index, StunAttribute *pAttribute)
const uint32_t STUN_HEADER_SIZE
HRESULT GetXorMappedAddress(CSocketAddress *pAddress)
int _indexMessageIntegrity
const uint16_t STUN_ATTRIBUTE_OTHER_ADDRESS
HRESULT GetResponseOriginAddress(CSocketAddress *pAddress)