// Test1 - just do a basic binding request HRESULT CTestMessageHandler::Test1() { HRESULT hr=S_OK; CStunMessageBuilder builder; CSocketAddress clientaddr(0x12345678, 9876); CRefCountedBuffer spBuffer; CStunThreadMessageHandler handler; CStunMessageReader reader; CStunMessageReader::ReaderParseState state; StunMessageEnvelope message; _spTransport->Reset(); _spTransport->AddPP(CSocketAddress(0xaaaaaaaa, 1234)); InitBindingRequest(builder); builder.GetStream().GetBuffer(&spBuffer); handler.SetResponder(_spTransport); message.localSocket = RolePP; message.remoteAddr = clientaddr; message.spBuffer = spBuffer; _spTransport->GetSocketAddressForRole(message.localSocket, &(message.localAddr)); handler.ProcessRequest(message); spBuffer.reset(); _spTransport->GetOutputStream().GetBuffer(&spBuffer); state = reader.AddBytes(spBuffer->GetData(), spBuffer->GetSize()); ChkIfA(state != CStunMessageReader::BodyValidated, E_FAIL); // validate that the binding response matches our expectations ChkA(ValidateMappedAddress(reader, clientaddr)); // validate that it came from the server port we expected ChkA(ValidateOriginAddress(reader, RolePP)); // did we get back the binding request we expected ChkA(ValidateResponseAddress(clientaddr)); Cleanup: return hr; }
// test long-credential authentication HRESULT CTestMessageHandler::Test4() { HRESULT hr=S_OK; CStunMessageBuilder builder1, builder2; CStunMessageReader reader1, reader2; CSocketAddress clientaddr(0x12345678, 9876); CSocketAddress addrMapped; CRefCountedBuffer spBuffer; CStunThreadMessageHandler handler; uint16_t errorcode = 0; char szNonce[MAX_STUN_AUTH_STRING_SIZE+1]; char szRealm[MAX_STUN_AUTH_STRING_SIZE+1]; CStunMessageReader::ReaderParseState state; StunMessageEnvelope message; _spTransport->Reset(); _spTransport->AddPP(CSocketAddress(0xaaaaaaaa, 1234)); handler.SetAuth(_spAuthLong); handler.SetResponder(_spTransport); // ----------------------------------------------------------------------- // simulate a user making a request with no message integrity attribute (or username, or realm) InitBindingRequest(builder1); builder1.GetResult(&spBuffer); message.localSocket = RolePP; message.remoteAddr = clientaddr; message.spBuffer = spBuffer; _spTransport->GetSocketAddressForRole(message.localSocket, &(message.localAddr)); handler.ProcessRequest(message); spBuffer.reset(); _spTransport->m_outputstream.GetBuffer(&spBuffer); state = reader1.AddBytes(spBuffer->GetData(), spBuffer->GetSize()); ChkIfA(state != CStunMessageReader::BodyValidated, E_FAIL); // we expect the response back will be a 401 with a provided nonce and realm Chk(reader1.GetErrorCode(&errorcode)); ChkIfA(reader1.GetMessageClass() != ::StunMsgClassFailureResponse, E_UNEXPECTED); ChkIf(errorcode != ::STUN_ERROR_UNAUTHORIZED, E_UNEXPECTED); reader1.GetStringAttributeByType(STUN_ATTRIBUTE_REALM, szRealm, ARRAYSIZE(szRealm)); reader1.GetStringAttributeByType(STUN_ATTRIBUTE_NONCE, szNonce, ARRAYSIZE(szNonce)); // -------------------------------------------------------------------------------- // now simulate the follow-up request _spTransport->ClearStream(); spBuffer.reset(); InitBindingRequest(builder2); builder2.AddNonce(szNonce); builder2.AddRealm(szRealm); builder2.AddUserName("AuthorizedUser"); builder2.AddMessageIntegrityLongTerm("AuthorizedUser", szRealm, "password"); builder2.GetResult(&spBuffer); message.localSocket = RolePP; message.remoteAddr = clientaddr; message.spBuffer = spBuffer; _spTransport->GetSocketAddressForRole(message.localSocket, &(message.localAddr)); handler.ProcessRequest(message); spBuffer.reset(); _spTransport->m_outputstream.GetBuffer(&spBuffer); state = reader2.AddBytes(spBuffer->GetData(), spBuffer->GetSize()); ChkIfA(state != CStunMessageReader::BodyValidated, E_FAIL); ChkIfA(reader2.GetMessageClass() != ::StunMsgClassSuccessResponse, E_UNEXPECTED); // should have a mapped address ChkA(reader2.GetMappedAddress(&addrMapped)); // and the message integrity field should be valid ChkA(reader2.ValidateMessageIntegrityLong("AuthorizedUser", szRealm, "password")); Cleanup: return hr; }
// test simple authentication HRESULT CTestMessageHandler::Test3() { HRESULT hr=S_OK; CStunMessageBuilder builder1, builder2, builder3; CStunMessageReader reader1, reader2, reader3; CSocketAddress clientaddr(0x12345678, 9876); CRefCountedBuffer spBuffer; CStunThreadMessageHandler handler; uint16_t errorcode = 0; CStunMessageReader::ReaderParseState state; StunMessageEnvelope message; _spTransport->Reset(); _spTransport->AddPP(CSocketAddress(0xaaaaaaaa, 1234)); handler.SetAuth(_spAuthShort); handler.SetResponder(_spTransport); // ----------------------------------------------------------------------- // simulate an authorized user making a request with a valid password InitBindingRequest(builder1); builder1.AddStringAttribute(STUN_ATTRIBUTE_USERNAME, "AuthorizedUser"); builder1.AddMessageIntegrityShortTerm("password"); builder1.GetResult(&spBuffer); message.localSocket = RolePP; message.remoteAddr = clientaddr; message.spBuffer = spBuffer; _spTransport->GetSocketAddressForRole(message.localSocket, &(message.localAddr)); handler.ProcessRequest(message); // we expect back a response with a valid message integrity field spBuffer.reset(); _spTransport->m_outputstream.GetBuffer(&spBuffer); state = reader1.AddBytes(spBuffer->GetData(), spBuffer->GetSize()); ChkIfA(state != CStunMessageReader::BodyValidated, E_FAIL); ChkA(reader1.ValidateMessageIntegrityShort("password")); // ----------------------------------------------------------------------- // simulate a user with a bad password spBuffer.reset(); InitBindingRequest(builder2); builder2.AddStringAttribute(STUN_ATTRIBUTE_USERNAME, "WrongUser"); builder2.AddMessageIntegrityShortTerm("wrongpassword"); builder2.GetResult(&spBuffer); message.localSocket = RolePP; message.remoteAddr = clientaddr; message.spBuffer = spBuffer; _spTransport->GetSocketAddressForRole(message.localSocket, &(message.localAddr)); _spTransport->ClearStream(); handler.ProcessRequest(message); spBuffer.reset(); _spTransport->m_outputstream.GetBuffer(&spBuffer); state = reader2.AddBytes(spBuffer->GetData(), spBuffer->GetSize()); ChkIfA(state != CStunMessageReader::BodyValidated, E_FAIL); errorcode = 0; ChkA(reader2.GetErrorCode(&errorcode)); ChkIfA(errorcode != ::STUN_ERROR_UNAUTHORIZED, E_FAIL); // ----------------------------------------------------------------------- // simulate a client sending no credentials - we expect it to fire back with a 400/bad-request spBuffer.reset(); InitBindingRequest(builder3); builder3.GetResult(&spBuffer); message.localSocket = RolePP; message.remoteAddr = clientaddr; message.spBuffer = spBuffer; _spTransport->GetSocketAddressForRole(message.localSocket, &(message.localAddr)); _spTransport->ClearStream(); handler.ProcessRequest(message); spBuffer.reset(); _spTransport->m_outputstream.GetBuffer(&spBuffer); state = reader3.AddBytes(spBuffer->GetData(), spBuffer->GetSize()); ChkIfA(state != CStunMessageReader::BodyValidated, E_FAIL); errorcode = 0; ChkA(reader3.GetErrorCode(&errorcode)); ChkIfA(errorcode != ::STUN_ERROR_BADREQUEST, E_FAIL); Cleanup: return hr; }