HRESULT CStunMessageBuilder::AddRandomTransactionId(StunTransactionId* pTransId) { StunTransactionId transid; uint32_t stun_cookie_nbo = htonl(STUN_COOKIE); uint32_t entropy=0; // on x86, the rdtsc instruction is about as good as it gets for a random sequence number // on linux, there's /dev/urandom #ifdef _WIN32 // on windows, there's lots of simple stuff we can get at to give us a random number // the rdtsc instruction is about as good as it gets uint64_t clock = __rdtsc(); entropy ^= (uint32_t)(clock); #else // on linux, /dev/urandom should be sufficient { int randomfile = ::open("/dev/urandom", O_RDONLY); if (randomfile >= 0) { int readret = read(randomfile, &entropy, sizeof(entropy)); UNREFERENCED_VARIABLE(readret); ASSERT(readret > 0); close(randomfile); } } if (entropy == 0) { entropy ^= getpid(); entropy ^= reinterpret_cast<uintptr_t>(this); entropy ^= time(NULL); entropy ^= AtomicIncrement(&g_sequence_number); } #endif srand(entropy); // the first four bytes of the transaction id is always the magic cookie // followed by 12 bytes of the real transaction id memcpy(transid.id, &stun_cookie_nbo, sizeof(stun_cookie_nbo)); for (int x = 4; x < (STUN_TRANSACTION_ID_LENGTH-4); x++) { transid.id[x] = (uint8_t)(rand() % 256); } if (pTransId) { *pTransId = transid; } return AddTransactionId(transid); }
HRESULT CStunMessageBuilder::AddMessageIntegrityLongTerm(const char* pszUserName, const char* pszRealm, const char* pszPassword) { HRESULT hr = S_OK; const size_t MAX_KEY_SIZE = MAX_STUN_AUTH_STRING_SIZE*3 + 2; uint8_t key[MAX_KEY_SIZE + 1]; // long enough for 64-char strings and two semicolons and a null char for debugging uint8_t hash[MD5_DIGEST_LENGTH] = {}; uint8_t* pResult = NULL; uint8_t* pDst = key; size_t lenUserName = pszUserName ? strlen(pszUserName) : 0; size_t lenRealm = pszRealm ? strlen(pszRealm) : 0; size_t lenPassword = pszPassword ? strlen(pszPassword) : 0; size_t lenTotal = lenUserName + lenRealm + lenPassword + 2; // +2 for the two colons UNREFERENCED_VARIABLE(pResult); ChkIfA(lenTotal > MAX_KEY_SIZE, E_INVALIDARG); // if we ever hit this limit, just increase MAX_STUN_AUTH_STRING_SIZE // too bad CDatastream really only works on refcounted buffers. Otherwise, we wouldn't have to do all this messed up pointer math // We could create a refcounted buffer in this function, but that would mean a call to "new and delete", and we're trying to avoid memory allocations in // critical code paths because they are a proven perf hit // TODO - Fix CDataStream and CBuffer so that "ref counted buffers" are no longer needed pDst = key; memcpy(pDst, pszUserName, lenUserName); pDst += lenUserName; *pDst = ':'; pDst++; memcpy(pDst, pszRealm, lenRealm); pDst += lenRealm; *pDst = ':'; pDst++; memcpy(pDst, pszPassword, lenPassword); pDst += lenPassword; *pDst ='\0'; // null terminate for debugging (this char doesn not get hashed ASSERT((pDst-key) == lenTotal); #ifndef __APPLE__ pResult = MD5(key, lenTotal, hash); #else pResult = CC_MD5(key, lenTotal, hash); #endif ASSERT(pResult != NULL); hr= AddMessageIntegrityImpl(hash, MD5_DIGEST_LENGTH); Cleanup: return hr; }
HRESULT CStunMessageBuilder::AddMessageIntegrityImpl(uint8_t* key, size_t keysize) { HRESULT hr = S_OK; const size_t c_hmacsize = 20; uint8_t hmacvaluedummy[c_hmacsize] = {}; // zero-init unsigned int resultlength = c_hmacsize; uint8_t* pDstBuf = NULL; CRefCountedBuffer spBuffer; void* pData = NULL; size_t length = 0; unsigned char* pHashResult = NULL; UNREFERENCED_VARIABLE(pHashResult); ChkIfA(key==NULL || keysize <= 0, E_INVALIDARG); // add in a "zero-init" HMAC value. This adds 24 bytes to the length Chk(AddAttribute(STUN_ATTRIBUTE_MESSAGEINTEGRITY, hmacvaluedummy, ARRAYSIZE(hmacvaluedummy))); Chk(FixLengthField()); // now do a SHA1 on everything but the last 24 bytes (4 bytes of the attribute header and 20 bytes for the dummy content) ChkA(_stream.GetBuffer(&spBuffer)); pData = spBuffer->GetData(); length = spBuffer->GetSize(); ASSERT(length > 24); length = length-24; // now do a little pointer math so that HMAC can write exactly to where the hash bytes will appear pDstBuf = ((uint8_t*)pData) + length + 4; #ifndef __APPLE__ pHashResult = HMAC(EVP_sha1(), key, keysize, (uint8_t*)pData, length, pDstBuf, &resultlength); ASSERT(resultlength == 20); ASSERT(pHashResult != NULL); #else CCHmac(kCCHmacAlgSHA1, key, keysize,(uint8_t*)pData, length, pDstBuf); UNREFERENCED_VARIABLE(resultlength); #endif Cleanup: return hr; }
void CTestMessageHandler::ToAddr(const char* pszIP, uint16_t port, CSocketAddress* pAddr) { sockaddr_in addr={}; int result; UNREFERENCED_VARIABLE(result); addr.sin_family = AF_INET; addr.sin_port = htons(port); result = ::inet_pton(AF_INET, pszIP, &addr.sin_addr); ASSERT(result == 1); *pAddr = addr; }
// ---------------------------------------------------------------------------------------------- // this function must *always* return a valid Resource, even for 'missing' resources. Resource* ResourceManager::LoadAsync(const WCHAR* filename, Resource* def) { AutoSync sync(&m_criticalSection); // CRITICAL SECTION - ENTIRE FUNCTION Resource * res = NULL; // check cache, use if already there. if(NULL == res) { auto it = m_loaded.find(filename); if(it != m_loaded.end() ) res = it->second; } // check pending, use if already there. if(NULL == res) { auto it = m_pending.find(filename); if(it != m_pending.end() ) res = it->second; } // create new info and add it to pending list to be loaded. if(NULL == res) { ResourceFactory * factory = GetFactory(filename); if (!factory) { return NULL; } res = factory->CreateResource(def); m_pending[filename] = res; BOOL success = SetEvent(m_EventHandle); #ifdef NDEBUG UNREFERENCED_VARIABLE(success); #endif assert(success); } assert(res); res->AddRef(); return res; }
// ---------------------------------------------------------------------------------------------- Resource* ColladaModelFactory::CreateResource(Resource* def) { UNREFERENCED_VARIABLE(def); return new Model(); }