diff -r 000000000000 -r 1bce908db942 natfw/natfwunsaf_protocols/unsaf_codec/src/natfwunsafmessage.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/natfw/natfwunsaf_protocols/unsaf_codec/src/natfwunsafmessage.cpp Tue Feb 02 01:04:58 2010 +0200 @@ -0,0 +1,300 @@ +/* +* Copyright (c) 2006-2007 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + + + + +#include +#include "natfwunsafmessage.h" +#include "natfwunsaftransactionid.h" +#include "natfwunsafmessageintegrityattribute.h" +#include "natfwunsaffingerprintattribute.h" +#include "natfwunsafutils.h" + + +// ----------------------------------------------------------------------------- +// CNATFWUNSAFMessage::CNATFWUNSAFMessage +// ----------------------------------------------------------------------------- +// +CNATFWUNSAFMessage::CNATFWUNSAFMessage( + const TNATFWUNSAFTransactionID& aTransactionID) +#ifdef TEST_EUNIT + : iAttributes(1) +#endif + { + iTransactionID = aTransactionID; + } + +// ----------------------------------------------------------------------------- +// CNATFWUNSAFMessage::~CNATFWUNSAFMessage +// ----------------------------------------------------------------------------- +// +CNATFWUNSAFMessage::~CNATFWUNSAFMessage() + { + iAttributes.ResetAndDestroy(); + } + +// ----------------------------------------------------------------------------- +// CNATFWUNSAFMessage::TransactionID +// ----------------------------------------------------------------------------- +// +EXPORT_C TNATFWUNSAFTransactionID CNATFWUNSAFMessage::TransactionID() const + { + return iTransactionID; + } + +// ----------------------------------------------------------------------------- +// CNATFWUNSAFMessage::HasAttribute +// ----------------------------------------------------------------------------- +// +EXPORT_C TBool CNATFWUNSAFMessage::HasAttribute( + CNATFWUNSAFAttribute::TType aType) const + { + return Attribute(aType) ? ETrue : EFalse; + } + +// ----------------------------------------------------------------------------- +// CNATFWUNSAFMessage::Attribute +// ----------------------------------------------------------------------------- +// +EXPORT_C CNATFWUNSAFAttribute* CNATFWUNSAFMessage::Attribute( + CNATFWUNSAFAttribute::TType aType) const + { + for (TInt i = 0; i < iAttributes.Count(); ++i) + { + if (iAttributes[i]->Type() == aType) + { + return iAttributes[i]; + } + } + + return NULL; + } + +// ----------------------------------------------------------------------------- +// CNATFWUNSAFMessage::AddAttributeL +// ----------------------------------------------------------------------------- +// +EXPORT_C void CNATFWUNSAFMessage::AddAttributeL( + CNATFWUNSAFAttribute* aAttribute) + { + __ASSERT_ALWAYS(aAttribute, User::Leave(KErrArgument)); + + iAttributes.AppendL(aAttribute); + } + +// ----------------------------------------------------------------------------- +// CNATFWUNSAFMessage::DetachAttribute +// ----------------------------------------------------------------------------- +// +EXPORT_C void CNATFWUNSAFMessage::DetachAttribute( + const CNATFWUNSAFAttribute* aAttribute) + { + TInt pos = iAttributes.Find(aAttribute); + if (pos != KErrNotFound) + { + iAttributes.Remove(pos); + } + } + +// ----------------------------------------------------------------------------- +// CNATFWUNSAFMessage::DeleteAttribute +// Start search from the end of the array, so that deleting an attribute doesn't +// affect the positions of those attributes which haven't yet been checked. +// ----------------------------------------------------------------------------- +// +EXPORT_C void CNATFWUNSAFMessage::DeleteAttribute(TUint16 aType) + { + for (TInt i = iAttributes.Count() - 1; i >= 0; --i) + { + if (iAttributes[i]->Type() == aType) + { + CNATFWUNSAFAttribute* attr = iAttributes[i]; + DetachAttribute(attr); + delete attr; + } + } + } + +// ----------------------------------------------------------------------------- +// CNATFWUNSAFMessage::EncodeL +// ----------------------------------------------------------------------------- +// +EXPORT_C CBufBase* CNATFWUNSAFMessage::EncodeL() const + { + CBufBase* msg = EncodeMessageHeaderLC(); + + for (TInt i = 0; i < iAttributes.Count(); ++i) + { + if (iAttributes[i]->Type() != CNATFWUNSAFAttribute::EMessageIntegrity && + iAttributes[i]->Type() != CNATFWUNSAFAttribute::EFingerprint) + { + HBufC8* attribute = iAttributes[i]->EncodeL(); + CleanupStack::PushL(attribute); + msg->InsertL(msg->Size(), *attribute); + CleanupStack::PopAndDestroy(attribute); + } + } + CleanupStack::Pop(msg); + msg->Compress(); + SetMessageLength(*msg); + + return msg; + } + +// ----------------------------------------------------------------------------- +// CNATFWUNSAFMessage::EncodeL +// 1. Encode the UNSAF message normally. +// 2. Create a MESSAGE-INTEGRITY attribute. This updates also the header's +// length field to include the MESSAGE-INTEGRITY before computing the hash. +// 3. Encode it to the last attribute of the UNSAF message. +// 4. Create a FINGERPRINT attribute. This updates also the header's +// length field to include the FINGERPRINT before computing the hash. +// 5. Encode it to the last attribute of the UNSAF message. +// ----------------------------------------------------------------------------- +// +EXPORT_C CBufBase* CNATFWUNSAFMessage::EncodeL( + const TDesC8& aSharedSecret, + TBool aUseFingerprint) const + { + CBufBase* msg = EncodeL(); + CleanupStack::PushL(msg); + if ( aSharedSecret.Length() ) + { + //Long term credentials need be used if there's a REALM attribute + CNATFWUNSAFMessageIntegrityAttribute* msgIntegrity = + CNATFWUNSAFMessageIntegrityAttribute::NewLC(aSharedSecret, *msg, + HasAttribute( CNATFWUNSAFAttribute::ERealm )); + + HBufC8* encodedMsgIntegrity = msgIntegrity->EncodeL(); + CleanupStack::PushL(encodedMsgIntegrity); + msg->InsertL(msg->Size(), *encodedMsgIntegrity); + CleanupStack::PopAndDestroy(encodedMsgIntegrity); + CleanupStack::PopAndDestroy(msgIntegrity); + } + if ( aUseFingerprint ) + { + CNATFWUNSAFFingerprintAttribute* fingerprint = + CNATFWUNSAFFingerprintAttribute::NewLC(*msg); + + HBufC8* encodedFingerprint = fingerprint->EncodeL(); + CleanupStack::PushL(encodedFingerprint); + msg->InsertL(msg->Size(), *encodedFingerprint); + CleanupStack::PopAndDestroy(encodedFingerprint); + CleanupStack::PopAndDestroy(fingerprint); + } + + CleanupStack::Pop(msg); + msg->Compress(); + + return msg; + } + +// ----------------------------------------------------------------------------- +// CNATFWUNSAFMessage::UnknownMandatoryAttributeFound +// ----------------------------------------------------------------------------- +// +void CNATFWUNSAFMessage::UnknownMandatoryAttributeFound() + { + iUnknownMandatoryAttributes = ETrue; + } + +// ----------------------------------------------------------------------------- +// CNATFWUNSAFMessage::HasUnknownMandatoryAttributes +// ----------------------------------------------------------------------------- +// +EXPORT_C TBool CNATFWUNSAFMessage::HasUnknownMandatoryAttributes() const + { + return iUnknownMandatoryAttributes; + } + +// ----------------------------------------------------------------------------- +// CNATFWUNSAFMessage::EncodeMessageHeaderLC +// ----------------------------------------------------------------------------- +// +CBufBase* CNATFWUNSAFMessage::EncodeMessageHeaderLC() const + { + CBufBase* header = CBufFlat::NewL(EHeaderSize); + CleanupStack::PushL(header); + + TUint16 messageType = Type(); + TUint16 bigEndianType(0); + BigEndian::Put16(reinterpret_cast(&bigEndianType), messageType); + //First two bits of a STUN message are zero + bigEndianType = bigEndianType & EMessageTypeMask; + header->InsertL(EMessageTypeOffset, &bigEndianType, sizeof(bigEndianType)); + + + TUint16 msgLength = 0; + //Value is zero, so it is same also in the big endian representation + header->InsertL(EMessageLengthOffset, &msgLength, sizeof(msgLength)); + + TUint32 bigEndianCookie(0); + BigEndian::Put32(reinterpret_cast(&bigEndianCookie), EMagicCookie); + header->InsertL(EMagicCookieOffset, + &bigEndianCookie, + sizeof(bigEndianCookie)); + + header->InsertL(ETransactionIDOffset, + iTransactionID, + KMaxNATFWUNSAFTransactionIdLength); + return header; + } + +// ----------------------------------------------------------------------------- +// CNATFWUNSAFMessage::MessageLength +// TInt is guaranteed to be at least 32 bits. +// ----------------------------------------------------------------------------- +// +TInt CNATFWUNSAFMessage::MessageLength(const TDesC8& aNATFWUNSAFMessage) + { + if (aNATFWUNSAFMessage.Length() < EHeaderSize) + { + return KErrNotFound; + } + + return BigEndian::Get16(aNATFWUNSAFMessage.Mid(EMessageLengthOffset).Ptr()); + } + +// ----------------------------------------------------------------------------- +// CNATFWUNSAFMessage::SetMessageLength +// UNSAF message length does not include the NATFWUNSAF header +// ----------------------------------------------------------------------------- +// +void CNATFWUNSAFMessage::SetMessageLength(CBufBase& aNATFWUNSAFMessage) + { + SetMessageLength(aNATFWUNSAFMessage, + aNATFWUNSAFMessage.Size() - EHeaderSize); + } + +// ----------------------------------------------------------------------------- +// CNATFWUNSAFMessage::SetMessageLength +// ----------------------------------------------------------------------------- +// +void CNATFWUNSAFMessage::SetMessageLength(CBufBase& aNATFWUNSAFMessage, + TInt aLength) + { + __ASSERT_ALWAYS(aLength >= 0, User::Panic(KNullDesC, KErrUnderflow)); + + TUint16 bigEndianLength(0); + BigEndian::Put16(reinterpret_cast(&bigEndianLength), + static_cast(aLength)); + + aNATFWUNSAFMessage.Write(EMessageLengthOffset, + &bigEndianLength, + sizeof(bigEndianLength)); + }