--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/networksecurity/ipsec/ipsec6/src/key_prt.cpp Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,376 @@
+// Copyright (c) 2005-2009 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:
+// key_prt.cpp - IPv6/IPv4 IPSEC PFKEY protocol
+//
+
+#include "ipsec.h"
+#include "sadb.h"
+#include "sa_crypt.h"
+#include <networking/pfkeyv2.h>
+#include "pfkey.h"
+#include "ipseclog.h"
+#include <networking/in6_ipsec.h>
+#include <es_prot_internal.h>
+
+
+CProtocolBase *IPSEC::NewPfkeyL()
+ /**
+ * Return new instance of PFKEY protocol object.
+ *
+ * @return The PFKEY protocol.
+ */
+ {
+ return new (ELeave) CProtocolKey();
+ }
+
+void IPSEC::IdentifyPfkey(TServerProtocolDesc &aEntry)
+ /**
+ * Return PFKEY protocol description
+ *
+ * @retval aEntry The description
+ */
+ {
+ _LIT(Kpfkey, "pfkey");
+
+ aEntry.iName = Kpfkey;
+ aEntry.iAddrFamily = KAfIpsec;
+ aEntry.iSockType = KSockRaw;
+ aEntry.iProtocol = KProtocolKey;
+ aEntry.iVersion = TVersion(1, 0, 0);
+ aEntry.iByteOrder = ELittleEndian;
+ aEntry.iServiceInfo = KSIConnectionLess | KSIMessageBased;
+ aEntry.iNamingServices = 0;
+ aEntry.iSecurity = KSocketNoSecurity;
+ aEntry.iMessageSize = 0xffff;
+ aEntry.iServiceTypeInfo = ESocketSupport | ENeedMBufs;
+ aEntry.iNumSockets = KUnlimitedSockets;
+ }
+
+MAssociationManager *IPSEC::FindAssociationManager(const CProtocolBase *aProtocol, TUint aId)
+ /**
+ * Return MAssociationManager, if aProtocol is CProtocolKey instance.
+ *
+ * @param aProtocol The protocol instance
+ * @param aId The protocol Id
+ * @return NULL, if aProtocol is not CProtocolKey, otherwise return MAssociationManager
+ */
+ {
+ if (aId == KProtocolKey)
+ return (CProtocolKey *)aProtocol;
+ return NULL;
+ }
+
+#pragma warning (disable:4355)
+CProtocolKey::CProtocolKey() : iEngineAH(this), iEngineESP(this), iEngineNATT(this)
+ /**
+ * Constructor.
+ */
+ {
+ iSAPlist.SetOffset(_FOFF(CProviderKey,iSAPlink));
+ }
+#pragma warning (default:4355)
+
+
+void CProtocolKey::Open()
+ /**
+ * Increase reference count.
+ *
+ * The specific implementation exists only, because MAssociationManager::Open()
+ * must be mapped CProtocolBase::Open.
+ */
+ {
+ CProtocolBase::Open();
+ }
+
+void CProtocolKey::Close()
+ /**
+ * Descrease reference count.
+ *
+ * The specific implementation exists only, because MAssociationManager::Close()
+ * must be mapped CProtocolBase::Close.
+ */
+ {
+ CProtocolBase::Close();
+ }
+
+
+CServProviderBase* CProtocolKey::NewSAPL(TUint aSockType)
+ /**
+ * Create new PFKEY SAP.
+ *
+ * @param aSockType == KSockRaw
+ * @return CProviderKey instance
+ */
+ {
+ if (aSockType!=KSockRaw)
+ User::Leave(KErrNotSupported);
+ CProviderKey *pSAP = new (ELeave) CProviderKey(*this);
+ iSAPlist.AddLast(*pSAP);
+ return pSAP;
+ }
+
+CProtocolKey::~CProtocolKey()
+ /**
+ * Destructor.
+ */
+ {
+ // release End Points recorded by SetOpt
+ for (TInt i = iEndPoints.Count(); --i >= 0; )
+ {
+ iEndPoints[i].Close();
+ }
+ iEndPoints.Close();
+
+ delete iCrypto; // Relese crypto libraries
+ delete iTimer; // Disconnect Timer system.
+ //
+ // Release Security Associations
+ //
+ for (TInt j = 0; j < HashSize(); ++j)
+ while (iHash[j])
+ {
+ CSecurityAssoc *sa = iHash[j];
+ iHash[j] = sa->iNext;
+ delete sa;
+ }
+ // If assumptions are correct, iSAPlist should be empty!!
+ ASSERT(iSAPlist.IsEmpty());
+#if __WINS__
+ LOG(Log::Printf(_L("CProtocolKey::~CProtocolKey() done IPSEC_OBJECT_COUNT=%d"), IPSEC_OBJECT_COUNT));
+#endif
+ }
+
+void CProtocolKey::InitL(TDesC& /*aTag*/)
+ /**
+ * Initialize.
+ *
+ * Initialize the CProtocolKey. Create cryptographic library manager
+ * and timer handler.
+ */
+ {
+ iCrypto = CIpsecCryptoManager::NewL();
+ MAssociationManager *const mgr = this;
+ iTimer = TimeoutFactory::NewL(1, mgr);
+ }
+
+// Unnecessary function, could use the default in CProtocolBase
+void CProtocolKey::StartL()
+ /**
+ * StartL has nothing to do.
+ */
+ {
+ }
+
+void CProtocolKey::BindToL(CProtocolBase* aProtocol)
+ /**
+ * Bind requests protocols "below".
+ *
+ * The PFKEY allows here only cryptographic libraries, which are
+ * recognized from their protocol number #KProtocolCrypto .
+ *
+ * @param aProtocol The Cryptographic library.
+ */
+ {
+ ASSERT(this != aProtocol);
+
+ // Find out the ID of given protocol object
+ TUint id;
+ {
+ TServerProtocolDesc info;
+ aProtocol->Identify(&info);
+ id = info.iProtocol;
+ }
+
+ if (id == STATIC_CAST(TUint, KProtocolCrypto))
+ iCrypto->AddLibraryL((CProtocolCrypto *)aProtocol);
+ else
+ User::Leave(KErrGeneral); // Only Crypto libraries can be bound to PFKEY!
+ }
+
+
+void CProtocolKey::BindL(CProtocolBase * /*aProtocol*/, TUint /*id*/)
+ /**
+ * Bind request from a protocol "above".
+ *
+ * This is normally only used by the SECPOL protocol. The PFKEY
+ * does not keep track of these binds, and thus it accepts
+ * all BindL's as is (without any checks).
+ *
+ * @param aProtocol The protocol doing the bind.
+ * @param id The protocol number
+ */
+ {
+ // This function is just to allow standard BindToL sequence
+ // to complete, currently PFKEY is not insterested in keeping
+ // track of who binds to it, thus nothing is done here.
+ }
+
+void CProtocolKey::Identify(TServerProtocolDesc *aInfo) const
+ /**
+ * Return PFKEY protocol description
+ *
+ * @retval aEntry The description
+ */
+ {
+ IPSEC::IdentifyPfkey(*aInfo);
+ }
+
+
+TInt CProtocolKey::GetOption(TUint aLevel, TUint aName, TDes8& aOption, CProtocolBase* /*aSourceProtocol*/)
+ /**
+ * Supported GetOpt's for the PFKEY socket
+ *
+ * PFKEY SAP GetOption calls this.
+ *
+ * @param aLevel The option level
+ * @param aName The option name
+ * @param aOption The option argument
+ * @param aSourceProtocol Not used.
+ *
+ * Get Named EndPoint:
+ * @code aLevel = KSolIpsecControl, aName = KSoIpsecEndpoint, aOption = TNameRecord
+ * @endcode
+ */
+ {
+ if (aLevel == KSolIpsecControl && aName == KSoIpsecEndpoint)
+ {
+ // A problematic option: the aOption is both input (iName) and output (iAddr)!
+
+
+ // Return the address (TNameRecord::iAddr) of a named end point (TNameRecord::iName)
+ // If the named endpoint does not exist, return KErrNotFound and set address to unspecified.
+
+ if (aOption.Length() != sizeof(TNameRecord))
+ return KErrArgument;
+ TNameRecord &record = (TNameRecord &)*aOption.Ptr();
+ // ** should check that TNameRecord::iName and iAddr are valid TBuf
+ // ** descriptors which do not cause a panic, when accessed! How?
+ RIpAddress ep;
+ const TInt res = ep.Open(iEndPointCollection, record.iName);
+ // (if Open fails, ep() return unspecified address)
+ TInetAddr::Cast(record.iAddr).SetAddress(ep());
+ TInetAddr::Cast(record.iAddr).SetScope(ep().iScope);
+ // ep is closed implicitly by destructor
+ return res;
+ }
+ return KErrNotSupported;
+ }
+
+TInt CProtocolKey::SetOption(TUint aLevel, TUint aName,const TDesC8& aOption, CProtocolBase* /*aSourceProtocol*/)
+ /**
+ * Supported SetOpt's for the PFKEY socket
+ *
+ * PFKEY SAP SetOption calls this.
+ *
+ * @param aLevel The option level
+ * @param aName The option name
+ * @param aOption The option argument
+ * @param aSourceProtocol Not used.
+ *
+ * Set Named EndPoint.
+ * @code aLevel = KSolIpsecControl, aName = KSoIpsecEndpoint, aOption = TNameRecord
+ * @endcode
+ */
+ {
+ if (aLevel == KSolIpsecControl && aName == KSoIpsecEndpoint)
+ {
+
+ // Set the named end point (TNameRecord::iName) to specified address (TNameRecord::iAddr).
+ if (aOption.Length() != sizeof(TNameRecord))
+ return KErrArgument;
+ const TNameRecord &record = (const TNameRecord &)*aOption.Ptr();
+ // ** should check that TNameRecord::iName and iAddr are valid TBuf
+ // ** descriptors which do not cause a panic, when accessed! How?
+
+ RIpAddress ep;
+ TInt res = ep.Open(iEndPointCollection, record.iName, TIpAddress(record.iAddr));
+ if (res != KErrNone)
+ return res;
+ // Need to look if this EP is already recorded
+ // If the EP reference is not stored any other place, it would
+ // get deleted automaticly. Thus, need to record the EP's that
+ // have been set with SetOpt, so that they stay around even if
+ // no other reference exist yet.
+ const TInt count = iEndPoints.Count();
+ for (TInt i = count; --i >= 0; )
+ {
+ if (&iEndPoints[i]() == &ep()) // (Compare TIpAddress pointers directly)
+ return KErrNone; // Already recorded, nothing else to do.
+ }
+ // Unfortunately RArray Append does not execute RIpAddress copy
+ // constructor or assignment, need to do some arm twisting here...
+ RIpAddress dummy;
+ res = iEndPoints.Append(dummy);
+ if (res == KErrNone)
+ {
+ // Try with assigment...
+ iEndPoints[count] = ep;
+ }
+ return res;
+ // ep is closed implicitly by destructor
+ }
+ return KErrNotSupported;
+ }
+
+void CProtocolKey::SetAlgorithms(CAlgorithmList*& aList)
+ /**
+ * Receive Algorithm map from the policy.
+ *
+ * @param aList The algorithm mapping.
+ */
+ {
+ ASSERT(iCrypto != NULL); // Should never happen.
+ iCrypto->SetAlgorithms(aList);
+ }
+
+void CProtocolKey::Deliver(const TPfkeyMessage &aMsg)
+ /**
+ * Deliver PFKEY Messages to SAP's that are willing to receive them.
+ *
+ * @param aMsg The PFKEY message
+ */
+ {
+ CProviderKey* sap;
+ TDblQueIter<CProviderKey> iter(iSAPlist);
+
+ while (sap = iter++, sap != NULL)
+ {
+ sap->Deliver(aMsg);
+ }
+ LOG(aMsg.LogPrint(_L("---->"), iCrypto->Algorithms()));
+ }
+
+void CProtocolKey::DeliverRegistered(const TPfkeyMessage &aMsg)
+ /**
+ * Deliver PFKEY Messages selectively.
+ *
+ * Same as CProtocolKey::Deliver, but sends message only to SAP's that
+ * have REGISTERED for this type of Security Associtation.
+ *
+ * @param aMsg The PFKEY message
+ */
+ {
+ CProviderKey* sap;
+ TDblQueIter<CProviderKey> iter(iSAPlist);
+
+ TUint i = aMsg.iBase.iMsg->sadb_msg_satype;
+ TUint8 m = (TUint8)(1 << (i % 8));
+ i = i / 8;
+ while (sap = iter++, sap != NULL)
+ if (sap->iRegistered[i] & m)
+ {
+ sap->Deliver(aMsg);
+ }
+ LOG(aMsg.LogPrint(_L("---->"), iCrypto->Algorithms()));
+ }