Exemple #1
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;
}
Exemple #3
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;
}
// 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;
    
}
HRESULT CStunThreadMessageHandler::ValidateAuth(CStunMessageReader& reader)
{
    AuthAttributes authattributes;
    AuthResponse authresponse;
    HRESULT hr = S_OK;
    HRESULT hrRet = S_OK;
    
    if (_spAuth == NULL)
    {
        return S_OK; // nothing to do if there is no auth mechanism in place
    }
    
    memset(&authattributes, '\0', sizeof(authattributes));
    memset(&authresponse, '\0', sizeof(authresponse));
    
    reader.GetStringAttributeByType(STUN_ATTRIBUTE_USERNAME, authattributes.szUser, ARRAYSIZE(authattributes.szUser));
    reader.GetStringAttributeByType(STUN_ATTRIBUTE_REALM, authattributes.szRealm, ARRAYSIZE(authattributes.szRealm));
    reader.GetStringAttributeByType(STUN_ATTRIBUTE_NONCE, authattributes.szNonce, ARRAYSIZE(authattributes.szNonce));
    reader.GetStringAttributeByType(::STUN_ATTRIBUTE_LEGACY_PASSWORD, authattributes.szLegacyPassword, ARRAYSIZE(authattributes.szLegacyPassword));
    authattributes.fMessageIntegrityPresent = reader.HasMessageIntegrityAttribute();
    
    Chk(_spAuth->DoAuthCheck(&authattributes, &authresponse));
    
    // enforce that everything is null terminated
    authresponse.szNonce[ARRAYSIZE(authresponse.szNonce)-1] = 0;
    authresponse.szRealm[ARRAYSIZE(authresponse.szRealm)-1] = 0;
    authresponse.szPassword[ARRAYSIZE(authresponse.szPassword)-1] = 0;

    
    // now decide how to handle the auth
    
    if (authresponse.responseType == StaleNonce)
    {
        _error.errorcode = STUN_ERROR_STALENONCE;
    }
    else if (authresponse.responseType == Unauthorized)
    {
        _error.errorcode = STUN_ERROR_UNAUTHORIZED;
    }
    else if (authresponse.responseType == Reject)
    {
        _error.errorcode = STUN_ERROR_BADREQUEST;
    }
    else if (authresponse.responseType == Allow)
    {
        // nothing to do!
    }
    else if (authresponse.responseType == AllowConditional)
    {
        // validate the message in    // if either ValidateAuth or ProcessBindingRequest set an errorcode....

        if (authresponse.authCredMech == AuthCredLongTerm)
        {
            hrRet = reader.ValidateMessageIntegrityLong(authattributes.szUser, authattributes.szRealm, authresponse.szPassword);
        }
        else
        {
            hrRet = reader.ValidateMessageIntegrityShort(authresponse.szPassword);
        }
        
        if (SUCCEEDED(hrRet))
        {
            _integrity.fSendWithIntegrity = true;
            _integrity.fUseLongTerm = (authresponse.authCredMech == AuthCredLongTerm);
            
            COMPILE_TIME_ASSERT(sizeof(_integrity.szPassword)==sizeof(authresponse.szPassword));
            
            strcpy(_integrity.szPassword, authresponse.szPassword);
            strcpy(_integrity.szUser, authattributes.szUser);
            strcpy(_integrity.szRealm, authattributes.szRealm);
        }
        else
        {
            // bad password - so now turn this thing into a 401
            _error.errorcode = STUN_ERROR_UNAUTHORIZED;
        }
    }
    
    if ((_error.errorcode == STUN_ERROR_UNAUTHORIZED) || (_error.errorcode == STUN_ERROR_STALENONCE))
    {
        strcpy(_error.szRealm, authresponse.szRealm);
        strcpy(_error.szNonce, authresponse.szNonce);
    }

Cleanup:
    return hr;
}