Example #1
0
HRESULT CTCPStunThread::CreateListenSockets()
{
    HRESULT hr = S_OK;
    int ret;
   
    
    for (int r = (int)RolePP; r <= (int)RoleAA; r++)
    {
        if (_tsaListen.set[r].fValid)
        {
            ChkA(_socketListenArray[r].TCPInit(_tsaListen.set[r].addr, (SocketRole)r, true));
            _socketTable[r] = _socketListenArray[r].GetSocketHandle();
            ChkA(_socketListenArray[r].SetNonBlocking(true));
            ret = listen(_socketTable[r], 128); // 128 - large backlog.
            ChkIfA(ret == -1, ERRNOHR);
            _countSocks++;
        }
        else
        {
            _socketTable[r] = -1;
        }
    }
    
    _fListenSocketsOnEpoll = false;
    
Cleanup:
    return hr;
}
Example #2
0
HRESULT CTCPStunThread::SetListenSocketsOnEpoll(bool fEnable)
{
    HRESULT hr = S_OK;
    
    if (fEnable != _fListenSocketsOnEpoll)
    {
        for (int role = 0; role < 4; role++)
        {
            int sock = _socketTable[role];
            
            if (sock == -1)
            {
                continue;
            }
            
            if (fEnable)
            {
                ChkA(_spPolling->Add(sock, EPOLL_LISTEN_SOCKET_EVENT_SET));
            }
            else
            {
                ChkA(_spPolling->Remove(sock));
            }
        }
        
        _fListenSocketsOnEpoll = fEnable;
    }
    
Cleanup:
    return hr;
}
Example #3
0
HRESULT CTestReader::Test1()
{
    HRESULT hr = S_OK;

    StunAttribute attrib;
    const char* pszExpectedSoftwareAttribute = "STUN test client";
    const char* pszExpectedUserName = "******";
    CRefCountedBuffer spBuffer;
    char szStringValue[100];
    
    const unsigned char *req = c_requestbytes;
    size_t requestsize = sizeof(c_requestbytes)-1; // -1 to get rid of the trailing null

    CStunMessageReader reader;
    CStunMessageReader::ReaderParseState state;

    // reader is expecting at least enough bytes to fill the header
    ChkIfA(reader.AddBytes(NULL, 0) != CStunMessageReader::HeaderNotRead, E_FAIL);
    ChkIfA(reader.HowManyBytesNeeded() != STUN_HEADER_SIZE, E_FAIL);

    state = reader.AddBytes(req, requestsize);
    ChkIfA(state != CStunMessageReader::BodyValidated, E_FAIL);

    ChkIfA(reader.HowManyBytesNeeded() != 0, E_FAIL);

    ChkA(reader.GetBuffer(&spBuffer));

    ChkIfA(reader.GetMessageClass() != StunMsgClassRequest, E_FAIL);

    ChkIfA(reader.GetMessageType() != StunMsgTypeBinding, E_FAIL);

    ChkA(reader.GetAttributeByType(STUN_ATTRIBUTE_SOFTWARE, &attrib));

    ChkIfA(attrib.attributeType != STUN_ATTRIBUTE_SOFTWARE, E_FAIL);

    ChkIfA(0 != ::strncmp(pszExpectedSoftwareAttribute, (const char*)(spBuffer->GetData() + attrib.offset), attrib.size), E_FAIL);

    ChkA(reader.GetAttributeByType(STUN_ATTRIBUTE_USERNAME, &attrib));

    ChkIfA(attrib.attributeType != STUN_ATTRIBUTE_USERNAME, E_FAIL);

    ChkIfA(0 != ::strncmp(pszExpectedUserName, (const char*)(spBuffer->GetData() + attrib.offset), attrib.size), E_FAIL);
    
    
    ChkA(reader.GetStringAttributeByType(STUN_ATTRIBUTE_SOFTWARE, szStringValue, ARRAYSIZE(szStringValue)));
    ChkIfA(0 != ::strcmp(pszExpectedSoftwareAttribute, szStringValue), E_FAIL);

    ChkIfA(reader.HasFingerprintAttribute() == false, E_FAIL);

    ChkIfA(reader.IsFingerprintAttributeValid() == false, E_FAIL);
    
    ChkIfA(reader.HasMessageIntegrityAttribute() == false, E_FAIL);
    
    ChkA(reader.ValidateMessageIntegrityShort(c_password));

Cleanup:
    return hr;
 }
// This test validates that the construction and parsing of the message integrity attribute in a stun message works as expected
// The test also validates both short term and long term credential modes with or without the presence of a fingerprint attribute
HRESULT CTestIntegrity::TestMessageIntegrity(bool fWithFingerprint, bool fLongCredentials)
{
    HRESULT hr = S_OK;
    
    const char* pszUserName = "******";
    const char* pszRealm = "stunrealm";
    const char* pszPassword = "******";
    
    CStunMessageBuilder builder;
    CStunMessageReader reader;
    uint8_t *pMsg = NULL;
    size_t sizeMsg = 0;
    CStunMessageReader::ReaderParseState state;
    CRefCountedBuffer spBuffer;
    
    builder.AddBindingRequestHeader();
    builder.AddRandomTransactionId(NULL);
    builder.AddUserName(pszUserName);
    builder.AddRealm(pszRealm);
    
    
    if (fLongCredentials == false)
    {
        Chk(builder.AddMessageIntegrityShortTerm(pszPassword));
    }
    else
    {
        Chk(builder.AddMessageIntegrityLongTerm(pszUserName, pszRealm, pszPassword));
    }
    
    if (fWithFingerprint)
    {
        builder.AddFingerprintAttribute();
    }
    
    Chk(builder.GetResult(&spBuffer));
    
    pMsg = spBuffer->GetData();
    sizeMsg = spBuffer->GetSize();
    
    state = reader.AddBytes(pMsg, sizeMsg);
    
    ChkIfA(state != CStunMessageReader::BodyValidated, E_FAIL);
    
    ChkIfA(reader.HasMessageIntegrityAttribute()==false, E_FAIL);
    
    if (fLongCredentials == false)
    {
        ChkA(reader.ValidateMessageIntegrityShort(pszPassword));
    }
    else
    {
        ChkA(reader.ValidateMessageIntegrityLong(pszUserName, pszRealm, pszPassword));
    }
    
Cleanup:
    return hr;
}
// Test1 - just do a basic binding request
HRESULT CTestMessageHandler::Test1()
{
    HRESULT hr = S_OK;
    CStunMessageBuilder builder;
    CRefCountedBuffer spBuffer, spBufferOut(new CBuffer(MAX_STUN_MESSAGE_SIZE));
    CStunMessageReader reader;
    StunMessageIn msgIn;
    StunMessageOut msgOut;
    TransportAddressSet tas = {};
    
    InitTransportAddressSet(tas, true, true, true, true);
    
    ChkA(InitBindingRequest(builder));
    
  
    Chk(builder.GetResult(&spBuffer));
    
    ChkIfA(CStunMessageReader::BodyValidated != reader.AddBytes(spBuffer->GetData(), spBuffer->GetSize()), E_FAIL);

    // a message send to the PP socket on the server from the 
    msgIn.socketrole = RolePP;
    msgIn.addrRemote = _addrMapped;
    msgIn.pReader = &reader;
    msgIn.addrLocal = _addrServerPP;
    msgIn.fConnectionOriented = false;
    
    spBuffer.reset();
    
    msgOut.spBufferOut = spBufferOut;
    msgOut.socketrole = RoleAA; // deliberately wrong - so we can validate if it got changed to RolePP
    
    ChkA(CStunRequestHandler::ProcessRequest(msgIn, msgOut, &tas, NULL));
    
    reader.Reset();
    ChkIfA(CStunMessageReader::BodyValidated != reader.AddBytes(spBufferOut->GetData(), spBufferOut->GetSize()), E_FAIL);

    
    // validate that the message returned is a success response for a binding request
    ChkIfA(reader.GetMessageClass() != StunMsgClassSuccessResponse, E_FAIL);
    ChkIfA(reader.GetMessageType() != (uint16_t)StunMsgTypeBinding, E_FAIL);
    
    
    // Validate that the message came from the server port we expected
    //    and that it's the same address the server set for the origin address
    ChkIfA(msgOut.socketrole != RolePP, E_FAIL);
    ChkA(ValidateResponseOriginAddress(reader, _addrServerPP));
    ChkIfA(msgOut.addrDest.IsSameIP_and_Port(_addrMapped)==false, E_FAIL);
    
    // validate that the mapping was done correctly
    ChkA(ValidateMappedAddress(reader, _addrMapped, false));
    
    ChkA(ValidateOtherAddress(reader, _addrServerAA));

    
Cleanup:
    return hr;
}
Example #6
0
HRESULT CTestClientLogic::Run()
{
    HRESULT hr = S_OK;

    ChkA(Test1());

    printf("Testing detection for DirectMapping\n");
    ChkA(TestBehaviorAndFiltering(true, DirectMapping, false, EndpointIndependentFiltering));

    printf("Testing detection for EndpointIndependent mapping\n");
    ChkA(TestBehaviorAndFiltering(true, EndpointIndependentMapping, false, EndpointIndependentFiltering));

    printf("Testing detection for AddressDependentMapping\n");
    ChkA(TestBehaviorAndFiltering(true, AddressDependentMapping, false, EndpointIndependentFiltering));

    printf("Testing detection for AddressAndPortDependentMapping\n");
    ChkA(TestBehaviorAndFiltering(true, AddressAndPortDependentMapping, false, EndpointIndependentFiltering));

    printf("Testing detection for EndpointIndependentFiltering\n");
    ChkA(TestBehaviorAndFiltering(true, EndpointIndependentMapping, true, EndpointIndependentFiltering));

    printf("Testing detection for AddressDependentFiltering\n");
    ChkA(TestBehaviorAndFiltering(true, EndpointIndependentMapping, true, AddressDependentFiltering));

    printf("Testing detection for AddressAndPortDependentFiltering\n");
    ChkA(TestBehaviorAndFiltering(true, EndpointIndependentMapping, true, AddressAndPortDependentFiltering));



Cleanup:
    return hr;
}
Example #7
0
HRESULT CTestClientLogic::GenerateBindingResponseMessage(const CSocketAddress& addrMapped, const StunTransactionId& transid, CRefCountedBuffer& spMsg)
{
    HRESULT hr = S_OK;

    CStunMessageBuilder builder;
    builder.GetStream().Attach(spMsg, true);

    ChkA(builder.AddBindingResponseHeader(true));
    ChkA(builder.AddTransactionId(transid));
    ChkA(builder.AddXorMappedAddress(addrMapped));
    ChkA(builder.FixLengthField());
Cleanup:
    return hr;
}
HRESULT CTestIntegrity::Run()
{
    HRESULT hr = S_OK;
    
    Chk(TestMessageIntegrity(false, false));
    ChkA(TestMessageIntegrity(true, false));
    
    Chk(TestMessageIntegrity(false, true));
    ChkA(TestMessageIntegrity(true, true));
    
    
Cleanup:
    return hr;
}
// test long-credential authentication
HRESULT CTestMessageHandler::Test4()
{
    HRESULT hr=S_OK;
    CStunMessageBuilder builder1, builder2;
    CStunMessageReader readerResponse;
    CSocketAddress addrMapped;
    uint16_t errorcode = 0;
    char szNonce[MAX_STUN_AUTH_STRING_SIZE+1];
    char szRealm[MAX_STUN_AUTH_STRING_SIZE+1];
    

    // -----------------------------------------------------------------------
    // simulate a user making a request with no message integrity attribute (or username, or realm)
    InitBindingRequest(builder1);
    builder1.FixLengthField();
    
    ChkA(SendHelper(builder1, &readerResponse, _spAuthLong));
    
    Chk(readerResponse.GetErrorCode(&errorcode));
    
    ChkIfA(readerResponse.GetMessageClass() != ::StunMsgClassFailureResponse, E_UNEXPECTED);
    ChkIf(errorcode != ::STUN_ERROR_UNAUTHORIZED, E_UNEXPECTED);

    readerResponse.GetStringAttributeByType(STUN_ATTRIBUTE_REALM, szRealm, ARRAYSIZE(szRealm));
    readerResponse.GetStringAttributeByType(STUN_ATTRIBUTE_NONCE, szNonce, ARRAYSIZE(szNonce));
    
    
    // --------------------------------------------------------------------------------
    // now simulate the follow-up request
    readerResponse.Reset();
    InitBindingRequest(builder2);
    builder2.AddNonce(szNonce);
    builder2.AddRealm(szRealm);
    builder2.AddUserName("AuthorizedUser");
    builder2.AddMessageIntegrityLongTerm("AuthorizedUser", szRealm, "password");
    builder2.FixLengthField();
    
    ChkA(SendHelper(builder2, &readerResponse, _spAuthLong));
    
    ChkIfA(readerResponse.GetMessageClass() != ::StunMsgClassSuccessResponse, E_UNEXPECTED);
    
    // should have a mapped address
    ChkA(readerResponse.GetMappedAddress(&addrMapped));
    
    // and the message integrity field should be valid
    ChkA(readerResponse.ValidateMessageIntegrityLong("AuthorizedUser", szRealm, "password"));
    
Cleanup:
    return hr;
}
// 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;
}
Example #11
0
HRESULT CTestMessageHandler::SendHelper(CStunMessageBuilder& builderRequest, CStunMessageReader* pReaderResponse, IStunAuth* pAuth)
{
    CRefCountedBuffer spBufferRequest;
    CRefCountedBuffer spBufferResponse(new CBuffer(MAX_STUN_MESSAGE_SIZE));
    StunMessageIn msgIn;
    StunMessageOut msgOut;
    CStunMessageReader reader;
    CSocketAddress addrDest;
    TransportAddressSet tas;
    HRESULT hr = S_OK;
    
    
    InitTransportAddressSet(tas, true, true, true, true);
    
    builderRequest.GetResult(&spBufferRequest);
    
    ChkIf(CStunMessageReader::BodyValidated != reader.AddBytes(spBufferRequest->GetData(), spBufferRequest->GetSize()), E_FAIL);
    
    msgIn.fConnectionOriented = false;
    msgIn.addrLocal = _addrServerPP;
    msgIn.pReader = &reader;
    msgIn.socketrole = RolePP;
    msgIn.addrRemote = _addrMapped;
    
    msgOut.spBufferOut = spBufferResponse;
    
    ChkA(CStunRequestHandler::ProcessRequest(msgIn, msgOut, &tas, pAuth));
    
    ChkIf(CStunMessageReader::BodyValidated != pReaderResponse->AddBytes(spBufferResponse->GetData(), spBufferResponse->GetSize()), E_FAIL);
    
Cleanup:
    
    return hr;
    
}
Example #12
0
HRESULT CTestMessageHandler::ValidateMappedAddress(CStunMessageReader& reader, const CSocketAddress& addrExpected, bool fLegacyOnly)
{
    HRESULT hr = S_OK;
    CSocketAddress addrMapped;
    CSocketAddress addrXorMapped;
    HRESULT hrResult;

    hrResult = reader.GetXorMappedAddress(&addrXorMapped);
    
    if (SUCCEEDED(hrResult))
    {
        ChkIfA(false == addrExpected.IsSameIP_and_Port(addrXorMapped), E_FAIL);
        ChkIfA(fLegacyOnly, E_FAIL); // legacy responses should not include XOR mapped
    }
    else
    {
        ChkIfA(fLegacyOnly==false, E_FAIL); // non-legacy responses should include XOR Mapped address
    }
    
    ChkA(reader.GetMappedAddress(&addrMapped));
    ChkIfA(false == addrExpected.IsSameIP_and_Port(addrMapped), E_FAIL);
    
Cleanup:
    return hr;
}
Example #13
0
HRESULT CTestPolling::TestInit(size_t sizePolling, size_t sizePipeArray)
{
    HRESULT hr = S_OK;
    
    TestUnInit();
    
    ChkA(CreatePollingInstance(_polltype, sizePolling, _spPolling.GetPointerPointer()));
    
    for (size_t index = 0; index < sizePipeArray; index++)
    {
        ChkA(CreateAndAddPipe());
    }
    
Cleanup:
    return hr;
}
Example #14
0
HRESULT CTCPServer::Initialize(const CStunServerConfig& config)
{
    HRESULT hr = S_OK;
    TransportAddressSet tsaListen;
    TransportAddressSet tsaHandler;
    
    ChkIfA(_threads[0] != NULL, E_UNEXPECTED); // we can't already be initialized, right?
    
    // optional code: create an authentication provider and initialize it here (if you want authentication)
    // set the _spAuth member to reference it
    // Chk(CYourAuthProvider::CreateInstanceNoInit(&_spAuth));    

    // tsaHandler is sort of a hack for TCP.  It's really just a glorified indication to the the
    // CStunRequestHandler code to figure out if can offer a CHANGED-ADDRESS attribute.
    
    tsaHandler.set[RolePP].fValid = config.fHasPP;
    tsaHandler.set[RolePP].addr = config.addrPP;

    tsaHandler.set[RolePA].fValid = config.fHasPA;
    tsaHandler.set[RolePA].addr = config.addrPA;

    tsaHandler.set[RoleAP].fValid = config.fHasAP;
    tsaHandler.set[RoleAP].addr = config.addrAP;

    tsaHandler.set[RoleAA].fValid = config.fHasAA;
    tsaHandler.set[RoleAA].addr = config.addrAA;    
    
    if (config.fMultiThreadedMode == false)
    {
        tsaListen = tsaHandler;
        _threads[0] = new CTCPStunThread();
        
        ChkA(_threads[0]->Init(tsaListen, tsaHandler, _spAuth, config.nMaxConnections));
    }
    else
    {
        for (int threadindex = 0; threadindex < 4; threadindex++)
        {
            memset(&tsaListen, '\0', sizeof(tsaListen));
            
            if (tsaHandler.set[threadindex].fValid)
            {
                tsaListen.set[threadindex] = tsaHandler.set[threadindex];
                
                _threads[threadindex] = new CTCPStunThread();
                

                Chk(_threads[threadindex]->Init(tsaListen, tsaHandler, _spAuth, config.nMaxConnections));
            }
        }
    }
    
Cleanup:
    if (FAILED(hr))
    {
        Shutdown();
    }
    return hr;
}
Example #15
0
HRESULT CTestPolling::Run()
{
    HRESULT hr = S_OK;
    
#ifdef HAS_EPOLL
    _polltype = IPOLLING_TYPE_EPOLL;
    ChkA(Test1());
    ChkA(Test2());
#endif
    
    _polltype = IPOLLING_TYPE_POLL;
    ChkA(Test1());
    ChkA(Test2());
    ChkA(Test3());
Cleanup:
    return hr;
}
Example #16
0
HRESULT CTestClientLogic::Test1()
{
    HRESULT hr = S_OK;
    HRESULT hrTmp = 0;
    CStunClientLogic clientlogic;
    ::StunClientLogicConfig config;
    CRefCountedBuffer spMsgOut(new CBuffer(MAX_STUN_MESSAGE_SIZE));
    CRefCountedBuffer spMsgIn(new CBuffer(MAX_STUN_MESSAGE_SIZE));
    StunClientResults results;
    StunTransactionId transid;

    CSocketAddress addrDest;

    CSocketAddress addrServerPP = CSocketAddress(0xaaaaaaaa, 1001);
    CSocketAddress addrLocal =  CSocketAddress(0xdddddddd, 4444);
    CSocketAddress addrMapped = CSocketAddress(0xeeeeeeee, 5555);

    config.addrServer = addrServerPP;
    config.fBehaviorTest = false;
    config.fFilteringTest = false;
    config.timeoutSeconds = 10;
    config.uMaxAttempts = 2;
    config.fTimeoutIsInstant = false;

    ChkA(clientlogic.Initialize(config));

    ChkA(clientlogic.GetNextMessage(spMsgOut, &addrDest, 0));

    // we expect to get back a message for the serverPP
    ChkIfA(addrDest.IsSameIP_and_Port(addrServerPP)==false, E_UNEXPECTED);

    // check to make sure out timeout logic appears to work
    hrTmp = clientlogic.GetNextMessage(spMsgOut, &addrDest, 1);
    ChkIfA(hrTmp != E_STUNCLIENT_STILL_WAITING, E_UNEXPECTED);

    // now we should get a dupe of what we had before
    ChkA(clientlogic.GetNextMessage(spMsgOut, &addrDest, 11000));

    // the message should be a binding request
    ChkA(ValidateBindingRequest(spMsgOut, &transid));

    // now let's generate a response
    ChkA(GenerateBindingResponseMessage(addrMapped, transid, spMsgIn));
    ChkA(clientlogic.ProcessResponse(spMsgIn, addrServerPP, addrLocal));

    // results should be ready
    hrTmp = clientlogic.GetNextMessage(spMsgOut, &addrDest, 12000);
    ChkIfA(hrTmp != E_STUNCLIENT_RESULTS_READY, E_UNEXPECTED);

    ChkA(clientlogic.GetResults(&results));

    // results should have a successful binding result
    ChkIfA(results.fBindingTestSuccess==false, E_UNEXPECTED);
    ChkIfA(results.fIsDirect, E_UNEXPECTED);
    ChkIfA(results.addrMapped.IsSameIP_and_Port(addrMapped)==false, E_UNEXPECTED);
    ChkIfA(results.addrLocal.IsSameIP_and_Port(addrLocal)==false, E_UNEXPECTED);

Cleanup:
    return hr;
}
Example #17
0
HRESULT CStunMessageBuilder::AddHeader(StunMessageType msgType, StunMessageClass msgClass)
{
    uint16_t msgTypeField=0;
    HRESULT hr = S_OK;

    ChkA(_stream.SetSizeHint(200));

    // merge the _msgType and _msgClass, and the leading zero bits into a 16-bit field
    msgTypeField =  (msgType & 0x0f80) << 2;
    msgTypeField |= (msgType & 0x0070) << 1;
    msgTypeField |= (msgType & 0x000f);
    msgTypeField |= (msgClass & 0x02) << 7;
    msgTypeField |= (msgClass & 0x01) << 4;

    ChkA(_stream.WriteUint16(htons(msgTypeField))); // htons for big-endian
    ChkA(_stream.WriteUint16(0)); // place holder for length

Cleanup:
    return hr;
}
Example #18
0
HRESULT CTestMessageHandler::ValidateOtherAddress(CStunMessageReader& reader, const CSocketAddress& addrExpected)
{
    HRESULT hr = S_OK;
    CSocketAddress addr;
    
    ChkA(reader.GetOtherAddress(&addr));
    ChkIfA(false == addrExpected.IsSameIP_and_Port(addr), E_FAIL);
    
Cleanup:
    return hr;
}
Example #19
0
HRESULT CTestReader::TestFixedReadSizes(size_t chunksize)
{

    HRESULT hr = S_OK;
    CStunMessageReader reader;
    CStunMessageReader::ReaderParseState prevState, state;
    size_t bytesread = 0;
    bool fRandomChunkSizing = (chunksize==0);
    
    
    prevState = CStunMessageReader::HeaderNotRead;
    state = prevState;
    size_t msgSize = sizeof(c_requestbytes)-1; // c_requestbytes is a string, hence the -1
    while (bytesread < msgSize)
    {
        size_t remaining, toread;
        
        if (fRandomChunkSizing)
        {
            chunksize = (rand() % 17) + 1;
        }
        
        remaining = msgSize - bytesread;
        toread = (remaining > chunksize) ? chunksize : remaining;
        
        state = reader.AddBytes(&c_requestbytes[bytesread], toread);
        bytesread += toread;
        
        ChkIfA(state == CStunMessageReader::ParseError, E_UNEXPECTED);
        
        if ((state == CStunMessageReader::HeaderValidated) && (prevState != CStunMessageReader::HeaderValidated))
        {
            ChkIfA(bytesread < STUN_HEADER_SIZE, E_UNEXPECTED);
        }
        
        if ((state == CStunMessageReader::BodyValidated) && (prevState != CStunMessageReader::BodyValidated))
        {
            ChkIfA(prevState != CStunMessageReader::HeaderValidated, E_UNEXPECTED);
            ChkIfA(bytesread != msgSize, E_UNEXPECTED);
        }
        
        prevState = state;
    }
    
    ChkIfA(reader.GetState() != CStunMessageReader::BodyValidated, E_UNEXPECTED);
    
    // just validate the integrity and fingerprint, that should cover all the attributes
    ChkA(reader.ValidateMessageIntegrityShort(c_password));
    ChkIfA(reader.IsFingerprintAttributeValid() == false, E_FAIL);
    
Cleanup:
    return hr;
}
Example #20
0
// this test validates that IPV6 addresses work fine with CStunMessageBuilder and CStunMessageReader
HRESULT CTestBuilder::Test2()
{
    HRESULT hr = S_OK;
    CSocketAddress addr(0,0);
    CSocketAddress addrValidate(0,0);
    const char* ip6addr = "ABCDEFGHIJKLMNOP";
    sockaddr_in6 addr6 = {};
    CStunMessageReader reader;
    StunTransactionId transid;
    CStunMessageBuilder builder;
    CRefCountedBuffer spBuffer;

    addr6.sin6_family = AF_INET6;
    addr6.sin6_port = htons(9999);
    memcpy(addr6.sin6_addr.s6_addr, ip6addr, 16);
    addr = CSocketAddress(addr6);

    ChkA(builder.AddHeader(StunMsgTypeBinding, StunMsgClassRequest));
    ChkA(builder.AddRandomTransactionId(&transid));
    ChkA(builder.AddMappedAddress(addr));
    ChkA(builder.AddXorMappedAddress(addr));
    ChkA(builder.GetResult(&spBuffer));

    ChkIfA(CStunMessageReader::BodyValidated != reader.AddBytes(spBuffer->GetData(), spBuffer->GetSize()), E_FAIL);

    ChkA(reader.GetXorMappedAddress(&addrValidate));
    
    ChkIf(addrValidate.IsSameIP_and_Port(addr) == false, E_FAIL);

Cleanup:
    return hr;
}
Example #21
0
// test simple authentication
HRESULT CTestMessageHandler::Test3()
{
    CStunMessageBuilder builder1, builder2, builder3;
    CStunMessageReader readerResponse;
    uint16_t errorcode = 0;
    HRESULT hr = S_OK;
    

    // -----------------------------------------------------------------------
    // simulate an authorized user making a request with a valid password
    
    ChkA(InitBindingRequest(builder1));
    builder1.AddStringAttribute(STUN_ATTRIBUTE_USERNAME, "AuthorizedUser");
    builder1.AddMessageIntegrityShortTerm("password");
    builder1.FixLengthField();
    
    ChkA(SendHelper(builder1, &readerResponse, _spAuthShort));
    ChkA(readerResponse.ValidateMessageIntegrityShort("password"));
    

    // -----------------------------------------------------------------------
    // simulate a user with a bad password
    readerResponse.Reset();
    InitBindingRequest(builder2);
    builder2.AddStringAttribute(STUN_ATTRIBUTE_USERNAME, "WrongUser");
    builder2.AddMessageIntegrityShortTerm("wrongpassword");
    builder2.FixLengthField();
    
    ChkA(SendHelper(builder2, &readerResponse, _spAuthShort))
    
    errorcode = 0;
    ChkA(readerResponse.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
    readerResponse.Reset();
    ChkA(InitBindingRequest(builder3));
    
    ChkA(SendHelper(builder3, &readerResponse, _spAuthShort));
    
    errorcode = 0;
    ChkA(readerResponse.GetErrorCode(&errorcode));
    ChkIfA(errorcode != ::STUN_ERROR_BADREQUEST, E_FAIL);
    
Cleanup:
    return hr;
    
}
Example #22
0
// simplest of all tests. Just set a file descriptor and see that it's available
// repeat many times
HRESULT CTestPolling::Test1()
{
    HRESULT hr = S_OK;
    HRESULT hrResult;
    size_t size;
    PollEvent event;    
    int fd;
    int count = 0;
    
    srand(100);

    ChkA(TestInit(10, 10));
    
    size = _pipes.size();
    
    hrResult = _spPolling->WaitForNextEvent(&event, 0);
    ChkIfA(hrResult != S_FALSE, E_UNEXPECTED);    
    
    // one event at a time model
    for (int index = 0; index < 100; index++)
    {

        size_t item = rand() % size;
        
        ChkA(WritePipe(&_pipes[item]));
        
        ConsumeEvent(&fd, &count);
        
        ChkIfA(fd != _pipes[item].readpipe, E_UNEXPECTED);
        ChkIfA(count != 1, E_UNEXPECTED);
    }
    
    hrResult = _spPolling->WaitForNextEvent(&event, 0);
    ChkIfA(hrResult != S_FALSE, E_UNEXPECTED);
    
Cleanup:
    return hr;
}
HRESULT CTestMessageHandler::ValidateOriginAddress(CStunMessageReader& reader, SocketRole socketExpected)
{
    HRESULT hr = S_OK;
    StunAttribute attrib;
    CSocketAddress addrExpected, mappedaddr;
    
    CRefCountedBuffer spBuffer;
    Chk(reader.GetStream().GetBuffer(&spBuffer));
    
    Chk(_spTransport->GetSocketAddressForRole(socketExpected, &addrExpected));
    

    ChkA(reader.GetAttributeByType(STUN_ATTRIBUTE_RESPONSE_ORIGIN, &attrib));

    
    ChkA(GetMappedAddress(spBuffer->GetData()+attrib.offset, attrib.size, &mappedaddr));
    ChkIfA(false == addrExpected.IsSameIP_and_Port(mappedaddr), E_FAIL);    
    
    ChkIfA(socketExpected != _spTransport->m_outputRole, E_FAIL);
    
Cleanup:
    return hr;
}
Example #24
0
HRESULT CTCPServer::Start()
{
    HRESULT hr = S_OK;
    
    for (int role = (int)RolePP; role <= (int)RoleAA; role++)
    {
        if (_threads[role])
        {
            ChkA(_threads[role]->Start());
        }
    }
Cleanup:
    return hr;
}
Example #25
0
HRESULT CStunMessageBuilder::FixLengthField()
{
    size_t size = _stream.GetSize();
    size_t currentPos = _stream.GetPos();
    HRESULT hr = S_OK;

    ChkIfA(size < STUN_HEADER_SIZE, E_UNEXPECTED);

    if (size < STUN_HEADER_SIZE)
    {
        size = 0;
    }
    else
    {
        size = size - STUN_HEADER_SIZE;
    }

    ChkA(_stream.SeekDirect(2)); // 2 bytes into the stream is the length
    ChkA(_stream.WriteUint16(ntohs(size)));
    ChkA(_stream.SeekDirect(currentPos));

Cleanup:
    return hr;
}
Example #26
0
HRESULT CTestPolling::CreateAndAddPipe()
{
    HRESULT hr = S_OK;
    PipePair pp = {};
    int ret = -1;
    int fds[2];
    ret = ::pipe(fds);
    
    ChkIfA(ret == -1, ERRNOHR);

    pp.readpipe = fds[0];
    pp.writepipe = fds[1];
    pp.fDataPending = false;

    ChkA(SetNonBlocking(pp.readpipe));
    ChkA(SetNonBlocking(pp.writepipe));

    _pipes.push_back(pp);

    ChkA(_spPolling->Add(fds[0], IPOLLING_READ)); 
    
Cleanup:
    return hr;
}
Example #27
0
HRESULT CTestPolling::ConsumeEvent(int* pFD, int* pCount)
{
    HRESULT hr = S_OK;
    HRESULT hrResult = S_OK;
    PollEvent event;
    char ch;
    int result;
    int count = 0;
    int fd = -1;
    int pipesindex = -1;
    
    hrResult = _spPolling->WaitForNextEvent(&event, 0);
    ChkA(hrResult);
    
    ChkIfA(hrResult == S_FALSE, S_FALSE);
    
    fd = event.fd;
    
    while (true)
    {
        result = ::read(fd, &ch, 1);
        if (result <= 0)
        {
            break;
        }
        count++;
    }
    
    pipesindex = FindPipePairIndex(fd);
    ChkIfA(pipesindex == -1, E_UNEXPECTED);
    
    ChkIfA(count == 0, E_UNEXPECTED);
    
    ChkIfA(_pipes[pipesindex].fDataPending == false, E_UNEXPECTED);
    _pipes[pipesindex].fDataPending = false;
    
Cleanup:
    if (pFD)    
    {
        *pFD = fd;
    }
    if (pCount)
    {
        *pCount = count;
    }
    return hr;
}
Example #28
0
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;
}
HRESULT CSocketAddress::ToStringBuffer(char* pszAddrBytes, size_t length) const
{
    HRESULT hr = S_OK;
    int family = GetFamily();
    const void *pAddrBytes = NULL;
    const char* pszResult = NULL;
    const size_t portLength = 6; // colon plus 5 digit string e.g. ":55555"
    char szPort[portLength+1];


    ChkIfA(pszAddrBytes == NULL, E_INVALIDARG);
    ChkIf(length <= 0, E_INVALIDARG);
    pszAddrBytes[0] = 0;

    if (family == AF_INET)
    {
        pAddrBytes = &(_address.addr4.sin_addr);
        ChkIf(length < (INET_ADDRSTRLEN+portLength), E_INVALIDARG);
    }
    else if (family == AF_INET6)
    {
        pAddrBytes = &(_address.addr6.sin6_addr);
        ChkIf(length < (INET6_ADDRSTRLEN+portLength), E_INVALIDARG);
    }
    else
    {
        ChkA(E_FAIL);
    }

    pszResult = ::inet_ntop(family, pAddrBytes, pszAddrBytes, length);

    ChkIf(pszResult == NULL, ERRNOHR);

    sprintf(szPort, ":%d", GetPort());
#if DEBUG
    ChkIfA(strlen(szPort) > portLength, E_FAIL);
#endif

    strcat(pszAddrBytes, szPort);

Cleanup:
    return hr;
}
Example #30
0
HRESULT CTestPolling::RemovePipe(int pipeindex)
{
    HRESULT hr = S_OK;
    
    size_t size = _pipes.size();
    
    ChkIfA(pipeindex < 0, E_FAIL);
    ChkIfA(pipeindex >= (int)size, E_FAIL);
    
    ChkA(_spPolling->Remove(_pipes[pipeindex].readpipe));
    
    close(_pipes[pipeindex].readpipe);
    _pipes[pipeindex].readpipe = -1;
    
    close(_pipes[pipeindex].writepipe);
    _pipes[pipeindex].writepipe = -1;
    
    _pipes.erase(_pipes.begin()+pipeindex);
    
Cleanup:
    return hr;
}