HRESULT CFilteringTest::GetMessage(CRefCountedBuffer& spMsg, CSocketAddress* pAddrDest)
{
    CStunMessageBuilder builder;
    StunChangeRequestAttribute change;


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

    StartBindingRequest(builder);

    *pAddrDest = _pConfig->addrServer;

    if (_fIsTest3 == false)
    {
        change.fChangeIP = true;
        change.fChangePort = true;
        builder.AddChangeRequest(change);
    }
    else
    {
        change.fChangeIP = false;
        change.fChangePort = true;
        builder.AddChangeRequest(change);
    }

    builder.FixLengthField();


    return S_OK;
}
Esempio n. 2
0
HRESULT CBehaviorTest::GetMessage(CRefCountedBuffer& spMsg, CSocketAddress* pAddrDest)
{
    HRESULT hr = S_OK;
    ASSERT(spMsg->GetAllocatedSize() > 0);
    ASSERT(pAddrDest);
    
    StunChangeRequestAttribute attribChangeRequest = {};

    CStunMessageBuilder builder;
    builder.GetStream().Attach(spMsg, true);
    StartBindingRequest(builder);
    
    builder.AddChangeRequest(attribChangeRequest); // adding a blank CHANGE-REQUEST, because a JSTUN server will not respond if the request doesn't have one
    
    builder.FixLengthField();

    if (_fIsTest3 == false)
    {
        *pAddrDest = _pResults->addrAP;
    }
    else
    {
        *pAddrDest = _pResults->addrAA;
    }

    return hr;
}
Esempio n. 3
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;
}
// 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;
}
void CStunThreadMessageHandler::SendErrorResponse()
{
    HRESULT hr = S_OK;

    CStunMessageBuilder builder;
    CRefCountedBuffer spBuffer;

    _spResponseBuffer->SetSize(0);
    builder.GetStream().Attach(_spResponseBuffer, true);

    builder.AddHeader((StunMessageType)_error.msgtype, _error.msgclass);
    builder.AddTransactionId(_transid);
    builder.AddErrorCode(_error.errorcode, "FAILED");
    if ((_error.errorcode == ::STUN_ERROR_UNKNOWNATTRIB) && (_error.attribUnknown != 0))
    {
        builder.AddUnknownAttributes(&_error.attribUnknown, 1);
    }
    else if ((_error.errorcode == ::STUN_ERROR_STALENONCE) || (_error.errorcode == ::STUN_ERROR_UNAUTHORIZED))
    {
        if (_error.szNonce[0])
        {
            builder.AddStringAttribute(STUN_ATTRIBUTE_NONCE, _error.szNonce);
        }
        
        if (_error.szRealm[0])
        {
            builder.AddStringAttribute(STUN_ATTRIBUTE_REALM, _error.szRealm);
        }
    }

    ChkIfA(_spStunResponder == NULL, E_FAIL);

    builder.GetResult(&spBuffer);

    ASSERT(spBuffer->GetSize() != 0);
    ASSERT(spBuffer == _spResponseBuffer);

    _spStunResponder->SendResponse(_socketOutput, _addrResponse, spBuffer);

Cleanup:
    return;

}
HRESULT CBasicBindingTest::GetMessage(CRefCountedBuffer& spMsg, CSocketAddress* pAddrDest)
{
    HRESULT hr = S_OK;
    ASSERT(spMsg->GetAllocatedSize() > 0);
    ASSERT(pAddrDest);
    ASSERT(_fInit);

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

    Chk(StartBindingRequest(builder));
    builder.FixLengthField();

    *pAddrDest = _pConfig->addrServer;


Cleanup:
    return hr;
}
HRESULT CBehaviorTest::GetMessage(CRefCountedBuffer& spMsg, CSocketAddress* pAddrDest)
{
    HRESULT hr = S_OK;
    ASSERT(spMsg->GetAllocatedSize() > 0);
    ASSERT(pAddrDest);

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

    if (_fIsTest3 == false)
    {
        *pAddrDest = _pResults->addrAP;
    }
    else
    {
        *pAddrDest = _pResults->addrAA;
    }

    return hr;
}
Esempio n. 8
0
HRESULT CBasicBindingTest::GetMessage(CRefCountedBuffer& spMsg, CSocketAddress* pAddrDest)
{
    StunChangeRequestAttribute attribChangeRequest = {};
        
    HRESULT hr = S_OK;
    ASSERT(spMsg->GetAllocatedSize() > 0);
    ASSERT(pAddrDest);
    ASSERT(_fInit);

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

    Chk(StartBindingRequest(builder));
    
    builder.AddChangeRequest(attribChangeRequest); // adding a blank CHANGE-REQUEST, because a JSTUN server will not respond if the request doesn't have one
    
    builder.FixLengthField();

    *pAddrDest = _pConfig->addrServer;


Cleanup:
    return hr;
}
HRESULT CStunThreadMessageHandler::ProcessBindingRequest(CStunMessageReader& reader)
{

    HRESULT hrTmp;
    bool fRequestHasPaddingAttribute = false;
    SocketRole socketOutput = _message.localSocket;
    StunChangeRequestAttribute changerequest = {};
    bool fSendOtherAddress = false;
    bool fSendOriginAddress = false;
    SocketRole socketOther;
    CSocketAddress addrOrigin;
    CSocketAddress addrOther;
    CStunMessageBuilder builder;
    uint16_t paddingSize = 0;
    bool fLegacyFormat = false; // set to true if the client appears to be rfc3489 based instead of based on rfc 5789


    _spResponseBuffer->SetSize(0);
    builder.GetStream().Attach(_spResponseBuffer, true);
    
    fLegacyFormat = reader.IsMessageLegacyFormat();

    // check for an alternate response port
    // check for padding attribute (todo - figure out how to inject padding into the response)
    // check for a change request and validate we can do it.  If so, set _socketOutput.  If not, fill out _error and return.
    // determine if we have an "other" address to notify the caller about


    // did the request come with a padding request
    if (SUCCEEDED(reader.GetPaddingAttributeSize(&paddingSize)))
    {
        // todo - figure out how we're going to get the MTU size of the outgoing interface
        fRequestHasPaddingAttribute = true;
    }

    // as per 5780, section 6.1, If the Request contained a PADDING attribute...
    // "If the Request also contains the RESPONSE-PORT attribute the server MUST return an error response of type 400."
    if (_fRequestHasResponsePort && fRequestHasPaddingAttribute)
    {
        _error.errorcode = STUN_ERROR_BADREQUEST;
        return E_FAIL;
    }

    // handle change request logic and figure out what "other-address" attribute is going to be
    if (SUCCEEDED(reader.GetChangeRequest(&changerequest)))
    {
        if (changerequest.fChangeIP)
        {
            socketOutput = SocketRoleSwapIP(socketOutput);
        }
        if(changerequest.fChangePort)
        {
            socketOutput = SocketRoleSwapPort(socketOutput);
        }

        // IsValidSocketRole just validates the enum, not whether or not we can send on it
        ASSERT(IsValidSocketRole(socketOutput));

        // now, make sure we have the ability to send from another socket
        if (_spStunResponder->HasAddress(socketOutput) == false)
        {
            // send back an error.  We're being asked to respond using another address that we don't have a socket for
            _error.errorcode = STUN_ERROR_BADREQUEST;
            return E_FAIL;
        }
    }

    // If we're only working one socket, then that's ok, we just don't send back an "other address" unless we have all four sockets confgiured

    // now here's a problem.  If we binded to "INADDR_ANY", all of the sockets will have "0.0.0.0" for an address (same for IPV6)
    // So we effectively can't send back "other address" if don't really know our own IP address
    // Fortunately, recvfromex and the ioctls on the socket allow address discovery a bit better

    fSendOtherAddress = (_spStunResponder->HasAddress(RolePP) && _spStunResponder->HasAddress(RolePA) && _spStunResponder->HasAddress(RoleAP) && _spStunResponder->HasAddress(RoleAA));

    if (fSendOtherAddress)
    {
        socketOther = SocketRoleSwapIP(SocketRoleSwapPort(_message.localSocket));

        hrTmp = _spStunResponder->GetSocketAddressForRole(socketOther, &addrOther);
        ASSERT(SUCCEEDED(hrTmp));

        // so if our ip address is "0.0.0.0", disable this attribute
        fSendOtherAddress = (SUCCEEDED(hrTmp) && (addrOther.IsIPAddressZero()==false));
    }

    // What's our address origin?
    VERIFY(SUCCEEDED(_spStunResponder->GetSocketAddressForRole(socketOutput, &addrOrigin)));
    if (addrOrigin.IsIPAddressZero())
    {
        // Since we're sending back from the IP address we received on, we can just use the address the message came in on
        // Otherwise, we don't actually know it
        if (socketOutput == _message.localSocket)
        {
            addrOrigin = _message.localAddr;
        }
    }
    fSendOriginAddress = (false == addrOrigin.IsIPAddressZero());

    // Success - we're all clear to build the response

    _socketOutput = socketOutput;

    _spResponseBuffer->SetSize(0);
    builder.GetStream().Attach(_spResponseBuffer, true);

    builder.AddHeader(StunMsgTypeBinding, StunMsgClassSuccessResponse);
    builder.AddTransactionId(_transid);
    builder.AddMappedAddress(_message.remoteAddr);

    if (fLegacyFormat == false)
    {
        builder.AddXorMappedAddress(_message.remoteAddr);
    }

    if (fSendOriginAddress)
    {
        builder.AddResponseOriginAddress(addrOrigin);
    }

    if (fSendOtherAddress)
    {
        builder.AddOtherAddress(addrOther, fLegacyFormat); // pass true to send back CHANGED-ADDRESS, otherwise, pass false to send back OTHER-ADDRESS
    }
    
    // finally - if we're supposed to have a message integrity attribute as a result of authorization, add it at the very end
    if (_integrity.fSendWithIntegrity)
    {
        if (_integrity.fUseLongTerm == false)
        {
            builder.AddMessageIntegrityShortTerm(_integrity.szPassword);
        }
        else
        {
            builder.AddMessageIntegrityLongTerm(_integrity.szUser, _integrity.szRealm, _integrity.szPassword);
        }
    }

    builder.FixLengthField();

    return S_OK;
}