예제 #1
0
HRESULT CTestClientLogic::GetMappedAddressForDestinationAddress(const CSocketAddress& addrDest, CSocketAddress* pAddrMapped)
{
    HRESULT hr = S_OK;
    if (addrDest.IsSameIP_and_Port(_addrServerPP))
    {
        *pAddrMapped = _addrMappedPP;
    }
    else if (addrDest.IsSameIP_and_Port(_addrServerPA))
    {
        *pAddrMapped = _addrMappedPA;
    }
    else if (addrDest.IsSameIP_and_Port(_addrServerAP))
    {
        *pAddrMapped = _addrMappedAP;
    }
    else if (addrDest.IsSameIP_and_Port(_addrServerAA))
    {
        *pAddrMapped = _addrMappedAA;
    }
    else
    {
        ASSERT(false);
        hr = E_FAIL;
    }

    return hr;
}
HRESULT CTestMessageHandler::ValidateMappedAddress(CStunMessageReader& reader, const CSocketAddress& addrClient)
{
    HRESULT hr = S_OK;
    StunTransactionId transid;
    CSocketAddress mappedaddr;
    
    CRefCountedBuffer spBuffer;
    
    Chk(reader.GetStream().GetBuffer(&spBuffer));
    
    reader.GetTransactionId(&transid);

    //ChkA(reader.GetAttributeByType(STUN_ATTRIBUTE_XORMAPPEDADDRESS, &attrib));
    //ChkA(GetXorMappedAddress(spBuffer->GetData()+attrib.offset, attrib.size, transid, &mappedaddr));
    reader.GetXorMappedAddress(&mappedaddr);
    ChkIfA(false == addrClient.IsSameIP_and_Port(mappedaddr), E_FAIL);    
    
    //ChkA(reader.GetAttributeByType(STUN_ATTRIBUTE_MAPPEDADDRESS, &attrib));
    //ChkA(GetMappedAddress(spBuffer->GetData()+attrib.offset, attrib.size, &mappedaddr));
    
    reader.GetMappedAddress(&mappedaddr);
    ChkIfA(false == addrClient.IsSameIP_and_Port(mappedaddr), E_FAIL);    
    
Cleanup:
    return hr;
}
예제 #3
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;
}
예제 #4
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;
}
HRESULT CBehaviorTest::ProcessResponse(CRefCountedBuffer& spMsg, CSocketAddress& addrRemote, CSocketAddress& addrLocal)
{
    HRESULT hr = S_OK;
    CStunMessageReader reader;
    CSocketAddress addrMapped;


    Chk(BasicReaderValidation(spMsg, reader));

    hr = reader.GetXorMappedAddress(&addrMapped);
    if (FAILED(hr))
    {
        hr = reader.GetMappedAddress(&addrMapped);
    }
    Chk(hr); // again drop the message if we can't parse the binding response

    _fCompleted = true;


    if (_fIsTest3)
    {
        _pResults->addrMappingAA = addrMapped;
        _pResults->fBehaviorTestSuccess = true;

        if (addrMapped.IsSameIP_and_Port(_pResults->addrMappingAP))
        {
            _pResults->behavior = ::AddressDependentMapping;
        }
        else
        {
            _pResults->behavior = ::AddressAndPortDependentMapping;
        }
    }
    else
    {
        _pResults->addrMappingAP = addrMapped;
        if (addrMapped.IsSameIP_and_Port(_pResults->addrMapped))
        {
            _pResults->fBehaviorTestSuccess = true;
            _pResults->behavior = ::EndpointIndependentMapping;
        }
    }

Cleanup:
    return hr;
}
예제 #6
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;
}
예제 #7
0
SocketRole CTestClientLogic::GetSocketRoleForDestinationAddress(const CSocketAddress& addrDest)
{
    if (addrDest.IsSameIP_and_Port(_addrServerPP))
    {
        return RolePP;
    }
    else if (addrDest.IsSameIP_and_Port(_addrServerPA))
    {
        return RolePA;
    }
    else if (addrDest.IsSameIP_and_Port(_addrServerAP))
    {
        return RoleAP;
    }
    else if (addrDest.IsSameIP_and_Port(_addrServerAA))
    {
        return RoleAA;
    }
    ASSERT(false);
    return RolePP;

}
HRESULT CBasicBindingTest::ProcessResponse(CRefCountedBuffer& spMsg, CSocketAddress& addrRemote, CSocketAddress& addrLocal)
{
    HRESULT hr = S_OK;
    CStunMessageReader reader;
    CSocketAddress addrMapped;
    CSocketAddress addrOther;
    bool fHasOtherAddress = false;

    // todo - figure out a way to make buffering TCP fragments work
    Chk(BasicReaderValidation(spMsg, reader));

    hr = reader.GetXorMappedAddress(&addrMapped);
    if (FAILED(hr))
    {
        hr = reader.GetMappedAddress(&addrMapped);
    }
    Chk(hr); // again drop the message if we can't parse the binding response

    fHasOtherAddress = SUCCEEDED(reader.GetOtherAddress(&addrOther));

    // ok, we got a response.  So we are done
    _fCompleted = true;
    _pResults->fBindingTestSuccess = true;
    _pResults->fIsDirect = addrLocal.IsSameIP_and_Port(addrMapped);
    _pResults->addrLocal = addrLocal;
    _pResults->addrMapped = addrMapped;
    _pResults->fHasOtherAddress = fHasOtherAddress;


    if (fHasOtherAddress)
    {
        _pResults->addrAA = addrOther;

        _pResults->addrPA = _pConfig->addrServer;
        _pResults->addrPA.SetPort(addrOther.GetPort());

        _pResults->addrAP = addrOther;
        _pResults->addrAP.SetPort(_pConfig->addrServer.GetPort());

        if (Logging::GetLogLevel() >= LL_DEBUG)
        {
            char sz[100];
            addrOther.ToStringBuffer(sz, 100);
            Logging::LogMsg(LL_DEBUG, "Other address is %s\n",sz);
        }

    }

Cleanup:
    return hr;
}
예제 #9
0
HRESULT CTestClientLogic::TestBehaviorAndFiltering(bool fBehaviorTest, NatBehavior behavior, bool fFilteringTest, NatFiltering filtering)
{
    HRESULT hr = S_OK;
    StunClientLogicConfig config;
    HRESULT hrRet;
    uint32_t time = 0;
    CRefCountedBuffer spMsgOut(new CBuffer(MAX_STUN_MESSAGE_SIZE));
    CRefCountedBuffer spMsgResponse(new CBuffer(MAX_STUN_MESSAGE_SIZE));
    SocketRole outputRole;
    CSocketAddress addrDummy;

    StunMessageIn stunmsgIn;
    StunMessageOut stunmsgOut;


    CSocketAddress addrDest;
    CSocketAddress addrMapped;
    CSocketAddress addrServerResponse; // what address the fake server responded back on
    StunClientResults results;
    StunTransactionId transid= {};
    //std::string strAddr;


    ChkA(CommonInit(behavior, filtering));


    config.addrServer = _addrServerPP;
    config.fBehaviorTest = fBehaviorTest;
    config.fFilteringTest = fFilteringTest;
    config.timeoutSeconds = 5;
    config.uMaxAttempts = 10;

    ChkA(_spClientLogic->Initialize(config));

    while (true)
    {
        CStunMessageReader reader;

        bool fDropMessage = false;

        time += 1000;

        hrRet = _spClientLogic->GetNextMessage(spMsgOut, &addrDest, time);
        if (hrRet == E_STUNCLIENT_STILL_WAITING)
        {
            //printf("GetNextMessage returned 'still waiting'\n");
            continue;
        }

        if (hrRet == E_STUNCLIENT_RESULTS_READY)
        {
            //printf("GetNextMessage returned 'results ready'\n");
            break;
        }

        //addrDest.ToString(&strAddr);
        //printf("Client is sending stun packet to %s\n", strAddr.c_str());

        ChkA(GetMappedAddressForDestinationAddress(addrDest, &addrMapped));

        //addrMapped.ToString(&strAddr);
        //printf("Server is receiving stun packet from %s\n", strAddr.c_str());

        ChkA(ValidateBindingRequest(spMsgOut, &transid));

        // --------------------------------------------------

        reader.AddBytes(spMsgOut->GetData(), spMsgOut->GetSize());

        ChkIfA(reader.GetState() != CStunMessageReader::BodyValidated, E_UNEXPECTED);

        // Simulate sending the binding request and getting a response back
        stunmsgIn.socketrole = GetSocketRoleForDestinationAddress(addrDest);
        stunmsgIn.addrLocal = addrDest;
        stunmsgIn.addrRemote = addrMapped;
        stunmsgIn.fConnectionOriented = false;
        stunmsgIn.pReader = &reader;

        stunmsgOut.socketrole = (SocketRole)-1; // intentionally setting it wrong
        stunmsgOut.addrDest = addrDummy;  // we don't care what address the server sent back to
        stunmsgOut.spBufferOut = spMsgResponse;
        spMsgResponse->SetSize(0);

        ChkA(::CStunRequestHandler::ProcessRequest(stunmsgIn, stunmsgOut, &_tsa, NULL));

        // simulate the message coming back

        // make sure we got something!
        outputRole = stunmsgOut.socketrole;
        ChkIfA(::IsValidSocketRole(outputRole)==false, E_FAIL);

        ChkIfA(spMsgResponse->GetSize() == 0, E_FAIL);

        addrServerResponse = _tsa.set[stunmsgOut.socketrole].addr;

        // --------------------------------------------------


        //addrServerResponse.ToString(&strAddr);
        //printf("Server is sending back from %s\n", strAddr.c_str());

        // if the request went to PP, but came back from AA or AP, then it's likely a filtering test
        // decide if we need to drop the response

        fDropMessage = ( addrDest.IsSameIP_and_Port(_addrServerPP) &&
                         ( ((outputRole == RoleAA) && (_fAllowChangeRequestAA==false)) ||
                           ((outputRole == RolePA) && (_fAllowChangeRequestPA==false))
                         )
                       );


        //{
        //    CStunMessageReader::ReaderParseState state;
        //    CStunMessageReader readerDebug;
        //    state = readerDebug.AddBytes(spMsgResponse->GetData(), spMsgResponse->GetSize());
        //    if (state != CStunMessageReader::BodyValidated)
        //    {
        //        printf("Error - response from server doesn't look valid");
        //    }
        //    else
        //    {
        //        CSocketAddress addr;
        //        readerDebug.GetMappedAddress(&addr);
        //        addr.ToString(&strAddr);
        //        printf("Response from server indicates our mapped address is %s\n", strAddr.c_str());
        //    }
        //}

        if (fDropMessage == false)
        {
            ChkA(_spClientLogic->ProcessResponse(spMsgResponse, addrServerResponse, _addrLocal));
        }
    }

    // now validate the results
    results.Init(); // zero it out
    _spClientLogic->GetResults(&results);

    ChkIfA(results.behavior != behavior, E_UNEXPECTED);

Cleanup:

    return hr;

}
예제 #10
0
// Test2 - send a binding request to a duplex server instructing it to send back on it's alternate port and alternate IP to an alternate client port
HRESULT CTestMessageHandler::Test2()
{
    HRESULT hr = S_OK;
    CStunMessageBuilder builder;
    CRefCountedBuffer spBuffer, spBufferOut(new CBuffer(MAX_STUN_MESSAGE_SIZE));
    CStunMessageReader reader;
    StunMessageIn msgIn;
    StunMessageOut msgOut;
    TransportAddressSet tas = {};
    uint16_t responsePort = 2222;
    StunChangeRequestAttribute changereq;
    CStunMessageReader::ReaderParseState state;
    CSocketAddress addrDestExpected;
    
    
    InitTransportAddressSet(tas, true, true, true, true);
    
    
    InitBindingRequest(builder);
    
    
    builder.AddResponsePort(responsePort);
    
    changereq.fChangeIP = true;
    changereq.fChangePort = true;
    builder.AddChangeRequest(changereq);
    builder.AddResponsePort(responsePort);
    builder.GetResult(&spBuffer);
    
    ChkIfA(CStunMessageReader::BodyValidated != reader.AddBytes(spBuffer->GetData(), spBuffer->GetSize()), E_FAIL);

    msgIn.fConnectionOriented = false;
    msgIn.addrLocal = _addrServerPP;
    msgIn.pReader = &reader;
    msgIn.socketrole = RolePP;
    msgIn.addrRemote = _addrMapped;
    
    msgOut.socketrole = RolePP; // deliberate initialized wrong
    msgOut.spBufferOut = spBufferOut;
    
    ChkA(CStunRequestHandler::ProcessRequest(msgIn, msgOut, &tas, NULL));
    
    // parse the response
    reader.Reset();
    state = reader.AddBytes(spBufferOut->GetData(), spBufferOut->GetSize());
    ChkIfA(state != CStunMessageReader::BodyValidated, E_FAIL);
    
    // validate that the message was sent back from the AA
    ChkIfA(msgOut.socketrole != RoleAA, E_FAIL);
    // validate that the server though it was sending back from the AA
    ChkA(ValidateResponseOriginAddress(reader, _addrServerAA));
    
    // validate that the message was sent to the response port requested
    addrDestExpected = _addrMapped;
    addrDestExpected.SetPort(responsePort);
    ChkIfA(addrDestExpected.IsSameIP_and_Port(msgOut.addrDest)==false, E_FAIL);
    
    // validate that the binding response came back
    ChkA(ValidateMappedAddress(reader, _addrMapped, false));
    
    // the "other" address is still AA (See RFC 3489 - section 8.1)
    ChkA(ValidateOtherAddress(reader, _addrServerAA));
    

Cleanup:

    return hr;
}