vpnengine/vpnipsecpolparser/src/spdb.cpp
changeset 0 33413c0669b9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vpnengine/vpnipsecpolparser/src/spdb.cpp	Thu Dec 17 09:14:51 2009 +0200
@@ -0,0 +1,665 @@
+/*
+* Copyright (c) 2002-2006 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: 
+* Security policy database module. 
+* "Runtime" methods of "CSecurityPolicy" class.
+*
+*/
+
+
+#include <networking/pfkeyv2.h>
+#include "spdb.h"
+#include "logvpncommon.h"
+
+//
+//  CPolicySelector
+//
+CPolicySelector::CPolicySelector()
+    {}
+
+EXPORT_C CPolicySelector*
+CPolicySelector::NewL()
+    {
+    CPolicySelector* self = new (ELeave) CPolicySelector();
+    self->Construct();
+    return self;
+    }
+
+EXPORT_C void
+CPolicySelector::Construct()
+    {
+    iIcmpType = -1;           // used, if != -1
+    iType = -1;               // used, if != -1
+    iIcmpCode = -1;           // used, if != -1
+    iGlobalSelector = EFalse; // the global flag defaults to false
+    iIsFinal = EFalse;
+    iIsMerge = EFalse;
+    iDirection = KPolicySelector_SYMMETRIC;
+    iDropAction = EFalse;
+    iProtocol = 0;
+
+    // Init addresses to undefined    
+    iLocal.SetFamily(KAFUnspec);
+    iLocalMask.SetFamily(KAFUnspec);
+    iRemote.SetFamily(KAFUnspec);
+    iRemoteMask.SetFamily(KAFUnspec);
+    
+    // Clear interface name
+    iInterface.Zero();
+    
+    // Init Endpoint names to NULL
+    iLocSelEpName = NULL;
+    iLocMaskEpName = NULL;
+    iRemSelEpName = NULL;
+    iRemMaskEpName = NULL;
+    
+    iSequenceNumber = 0;
+    iCompWord = 0;
+    }
+
+EXPORT_C CPolicySelector*
+CPolicySelector::NewL(CPolicySelector* aPS)
+    {
+    CPolicySelector* self = new (ELeave) CPolicySelector();
+    CleanupStack::PushL(self);
+    self->ConstructL(aPS);
+    CleanupStack::Pop();
+    return self;
+    }
+
+EXPORT_C void
+CPolicySelector::ConstructL(CPolicySelector* aPS)
+    {
+    iDirection = aPS->iDirection;
+    iRemote = aPS->iRemote;         // including port selector, if port non-zero
+    iRemoteMask = aPS->iRemoteMask; // only address part used, as a mask
+    iLocal = aPS->iLocal;           // including port selector, if port non-zero
+    iLocalMask = aPS->iLocalMask;   // only address part used, as a mask
+    iProtocol = aPS->iProtocol;     // used, if non-zero
+    iIcmpType = aPS->iIcmpType;     // used, if != -1
+    iType = aPS->iType;             // used, if != -1
+    iIcmpCode = aPS->iIcmpCode;     // used, if != -1
+    iGlobalSelector = aPS->iGlobalSelector;
+    iIsFinal = aPS->iIsFinal;
+    iIsMerge = aPS->iIsMerge;
+    iDropAction = aPS->iDropAction;
+    iInterface = aPS->iInterface;
+    
+    iSequenceNumber = aPS->iSequenceNumber;
+    iCompWord = aPS->iSequenceNumber;
+
+    // Copy EndPoint names    
+    if (aPS->iLocSelEpName && aPS->iLocSelEpName->Length())
+        {
+        iLocSelEpName = HBufC8::NewL(aPS->iLocSelEpName->Length());
+        *iLocSelEpName = *aPS->iLocSelEpName;
+        }
+    if (aPS->iLocMaskEpName && aPS->iLocMaskEpName->Length())
+        {
+        iLocMaskEpName = HBufC8::NewL(aPS->iLocMaskEpName->Length());
+        *iLocMaskEpName = *aPS->iLocMaskEpName;
+        }
+    if (aPS->iRemSelEpName && aPS->iRemSelEpName->Length())
+        {
+        iRemSelEpName = HBufC8::NewL(aPS->iRemSelEpName->Length());
+        *iRemSelEpName = *aPS->iRemSelEpName;
+        }
+    if (aPS->iRemMaskEpName && aPS->iRemMaskEpName->Length())
+        {
+        iRemMaskEpName = HBufC8::NewL(aPS->iRemMaskEpName->Length());
+        *iRemMaskEpName = *aPS->iRemMaskEpName;
+        }
+
+    TSecpolBundleIter iterl(aPS->iBundle);
+    CSecpolBundleItem* itemL(NULL);
+    CSecpolBundleItem* newItemL(NULL);
+    while ((itemL = iterl++) != NULL)
+        {
+        newItemL = new (ELeave) CSecpolBundleItem;
+        
+        // Points to the same SA
+        newItemL->iSpec = itemL->iSpec;      
+        
+        // No need to fill iNext. Is filled when adding
+        newItemL->iTunnel = itemL->iTunnel;  
+        iBundle.AddLast(*newItemL);
+        }
+
+    iNext = aPS->iNext;
+    }
+
+CSecpolBundleItem*
+CPolicySelector::FindBundleL(TInt aIndex)
+    {
+    TSecpolBundleIter iterL(iBundle);
+    CSecpolBundleItem* itemL(NULL);
+    CSecpolBundleItem* newItemL(NULL);
+    TInt i = 0;
+    while (((itemL = iterL++) != NULL) && (i < aIndex))
+        {
+        i++;
+        }
+
+    // The element exists. We create a copy
+    if ((i == aIndex) && (itemL != NULL))    
+        {
+        newItemL = new (ELeave) CSecpolBundleItem;
+        
+        // Need a copy to have separed bundle lists
+        newItemL->iSpec = itemL->iSpec;      
+        
+        // No need to fill iNext. Is filled when adding
+        newItemL->iTunnel = itemL->iTunnel;  
+        }
+
+    return newItemL;
+    }
+
+CSecpolBundleItem::~CSecpolBundleItem()
+    {
+    delete iTunnelEpName;
+    delete iTunnelEpFQDN;
+    }
+
+void CPolicySelector::GetFQDNAddressListL(CSecPolBundleList& aPolList) 
+    {
+    LOG_("CPolicySelector::GetFQDNAddressListL() entry\n");
+    TSecpolBundleIter iterl(iBundle);
+    CSecpolBundleItem* itemL(NULL);
+    while ((itemL = iterl++) != NULL)
+        {
+        if (itemL->iTunnelEpFQDN) 
+            {
+            LOG_1("Found FQDN: '%S', appending to the list\n", &(*itemL->iTunnelEpFQDN));
+            aPolList.AppendL(itemL);
+            LOG_("Append complete\n");
+            }
+        else 
+            {
+            TBuf<40> addrstr;
+            itemL->iTunnel.Output(addrstr);
+            LOG_1("Found IP: '%S', no need to add\n", &addrstr);
+            }
+        }
+    LOG_("CPolicySelector::GetFQDNAddressListL() exit\n");
+    }
+
+EXPORT_C
+CPolicySelector::~CPolicySelector()
+    {
+    TSecpolBundleIter iterl(iBundle);
+    CSecpolBundleItem* iteml(NULL);
+    while ((iteml = iterl++) != NULL)
+        {
+        iBundle.Remove(*iteml);
+        delete iteml;
+        }
+
+    delete iRemSelEpName;
+    delete iRemMaskEpName;
+    delete iLocMaskEpName;
+    delete iLocSelEpName;
+    }
+
+// Match a selector against the packet information
+//
+// Returns 0, if selector does not match the information
+//         1, if selector matches the information
+TInt
+CPolicySelector::Match(
+    const TInetAddr &aSrc,         // The src address, and port if known
+    const TInetAddr &aDst,         // The dst address, and port if known
+    TInt aProtocol,                // Transport protocol, if > 0 (known)
+    TInt aIcmpType,                // ICMP Type, if ICMP (-1 otherwise)
+    TInt aIcmpCode,                // ICMP Code, if ICMP (-1 otherwise)
+    TInt aType) const              // Type code, (-1 if not used)
+    {
+    return (aDst.Match(iRemote, iRemoteMask)
+            && aSrc.Match(iLocal, iLocalMask)
+            && (iProtocol == 0 || iProtocol == aProtocol)
+            && (iRemote.Port() == 0 || iRemote.Port() == aDst.Port())
+            && (iLocal.Port() == 0 || iLocal.Port() == aDst.Port())
+            && (iIcmpType == -1 || iIcmpType == aIcmpType)
+            && (iIcmpCode == -1 || iIcmpCode == aIcmpCode)
+            && (iType == -1 || iType == aType));
+    }
+
+// Checks if this policy is using this SA
+EXPORT_C TBool
+CPolicySelector::UseSA(CPolicySpec* aSA, TInetAddr* tunnel)
+    {
+    TSecpolBundleIter iterBundle(iBundle);
+    CSecpolBundleItem* itemBundle(NULL);
+
+    while ((itemBundle = iterBundle++) != NULL)
+        {
+        if (itemBundle->iSpec)
+            {
+            // SA used in a Policy. 2 SA cannot have the same name
+            if (!(itemBundle->iSpec->iName->Compare(*aSA->iName)))
+                {
+                if (tunnel)
+                    {
+                    *tunnel = itemBundle->iTunnel;
+                    }
+                return ETrue;
+                }
+            }
+        }
+
+    return EFalse;  // This selector doesn't use the SA
+    }
+
+//
+// CSAPairList: Translation table used when copying a policy
+CSAPairList::~CSAPairList()
+    {
+    TSAPairNode* next(NULL);
+    TSAPairNode* node(iList);
+    while (node)
+        {
+        next = node->iNext;
+        delete node;
+        node = next;
+        }
+    }
+
+//
+// Add at the begining to make it faster
+void
+CSAPairList::AddL(CPolicySpec* aOldSA, CPolicySpec* aNewSA)
+    {
+    TSAPairNode* node = new (ELeave) TSAPairNode;
+    node->iOldSA = aOldSA;
+    node->iNewSA = aNewSA;
+    node->iNext = iList;
+    iList = node;
+    }
+
+CPolicySpec*
+CSAPairList::Translate(CPolicySpec* aOldSA)
+    {
+    TSAPairNode* node = iList;
+    while (node)
+        {
+        if (node->iOldSA == aOldSA)
+            return node->iNewSA;
+        node = node->iNext;
+        }
+
+    // Not found
+    return(NULL);
+    }
+
+void CSecurityPolicy::GetFQDNAddressListL(CSecPolBundleList& aPolList) 
+    {
+    LOG_("CSecurityPolicy::GetFQDNAddressListL()\n");
+    if (iSelectors) 
+        {
+        TInt count(iSelectors->Count());
+        for (TInt i = 0; i < count; i++) 
+            {
+            iSelectors->At(i)->GetFQDNAddressListL(aPolList);
+            }
+        }
+    }
+
+EXPORT_C
+CSecurityPolicy::CSecurityPolicy()
+    {}
+
+EXPORT_C void
+CSecurityPolicy::ConstructL()
+    {
+    iSpecs = CSAList::NewL(1);
+    iSelectors = CSelectorList::NewL(1);
+    }
+
+// Creates a Security Policy from an existing one
+EXPORT_C void
+CSecurityPolicy::ConstructL(CSecurityPolicy* aSecPol)
+    {
+    // Creates a new SA List with new SA nodes!!!
+    if (aSecPol->SAList()->Count() > 0)
+        {
+        iSpecs = CSAList::NewL(aSecPol->SAList());
+        }
+    else
+        {
+        iSpecs = CSAList::NewL(1);
+        }
+
+    // The selector bundles use references to the old SA nodes
+    // so if we copy only the content we'll have invalid references.
+    // Therefore, we need a translations tables from old nodes to new
+    // ones to pass it to the selector constructor
+    if (aSecPol->SelectorList()->Count() > 0)
+        {
+        CSAPairList* table = CreateTranslationTableL(aSecPol->SAList(), iSpecs);
+        CleanupStack::PushL(table);
+        iSelectors = CSelectorList::NewL(aSecPol->SelectorList(), table);
+
+        // The table is not needed anymore
+        CleanupStack::PopAndDestroy();
+        }
+    else
+        {
+        iSelectors = CSelectorList::NewL(1);
+        }
+    }
+
+CSAPairList*
+CSecurityPolicy::CreateTranslationTableL(
+    CSAList* aOldSAList,
+    CSAList* aNewSAList)
+    {
+    CSAPairList* table = new (ELeave) CSAPairList;
+    CleanupStack::PushL(table);
+    TInt count(aOldSAList->Count());
+    for (TInt i = 0; i < count; i++)
+        {
+        table->AddL(aOldSAList->At(i), aNewSAList->At(i));
+        }
+    CleanupStack::Pop();
+    return (table);
+    }
+
+CSecurityPolicy::~CSecurityPolicy()
+    {
+    if (iSpecs)
+        {
+        // Deletes all the elems in the list
+        TInt count(iSpecs->Count());
+        for (TInt i = 0; i < count; i++) 
+            {
+            delete iSpecs->At(i);
+            }
+        delete iSpecs;
+        iSpecs = NULL;
+        }
+
+    if (iSelectors)
+        {
+        // Deletes all the elems in the list
+        TInt count(iSelectors->Count());
+        for (TInt i = 0; i < count; i++) 
+            {
+            delete iSelectors->At(i);
+            }
+        delete iSelectors;
+        iSelectors = NULL;
+        }
+    }
+
+TSecpolBundle*
+CSecurityPolicy::FindBundle(
+    TUint aDirection,              // Direction flag
+    const TInetAddr& aSrc,         // Source Address (and optionally port)
+    const TInetAddr& aDst,         // Destination Address (and optionally port)
+    TInt aProtocol,                // Transport protocol (if > 0)
+    TInt aIcmpType,                // (if != -1)
+    TInt aIcmpCode,                // (if != -1)
+    TInt aType)                    // (if != -1)
+    {
+    TInt count(iSelectors->Count());
+    for (TInt i = 0; i < count; i++)
+        {
+        CPolicySelector* selector = iSelectors->At(i);
+        if ((selector->iDirection & aDirection)
+            && selector->Match(aSrc, 
+                               aDst, 
+                               aProtocol, 
+                               aIcmpType, 
+                               aIcmpCode, 
+                               aType))
+            {
+            return (&selector->iBundle);
+            }
+        }
+
+    return (NULL);
+    }
+
+TInt
+CSecurityPolicy::SearchForEPNameL(TDesC& aTokenString)
+    {
+    TInt err(KErrNotFound);
+    HBufC8* name = HBufC8::NewL(aTokenString.Length());
+    name->Des().Copy(aTokenString);
+
+    // Iterate through the policy specification list
+    TInt count(iSpecs->Count());
+    for (TInt i = 0; i < count; i++)
+        {
+        CPolicySpec* polSpec = iSpecs->At(i);
+        // Check if spesification type is EndPoint and name for it exists
+        if (polSpec->iSpectype == EPolSpecEP && polSpec->iName)
+            {
+            // Compare EndPoint name against given name
+            if (name->Des().Compare(polSpec->iName->Des()) == 0)
+                {
+                // Match found so set return value to success
+                err = KErrNone;
+                break;
+                }
+            }
+        }
+
+    // Free memory allocated for name and then return
+    delete name;
+    return (err);
+    }
+
+EXPORT_C CPolicySpec*
+CSecurityPolicy::FindSpec(const TDesC8& aName)
+    {
+    CPolicySpec* spec(NULL);
+    TInt count(iSpecs->Count());
+    for (TInt i = 0; i < count; i++)
+        {
+        spec = iSpecs->At(i);
+        if ((*spec->iName).Compare(aName) == 0)
+            {
+            return spec;
+            }
+        }
+    return (NULL);
+    }
+
+//
+//  CPolicySpec
+//
+CPolicySpec::CPolicySpec()
+    {}
+
+EXPORT_C CPolicySpec*
+CPolicySpec::NewL()
+    {
+    CPolicySpec* self = new (ELeave) CPolicySpec();
+    self->Construct();
+    return self;
+    }
+
+EXPORT_C void
+CPolicySpec::Construct()
+    {
+    iEpSpec.iIsOptional = EFalse;
+    iEpSpec.iEpAddr = NULL;
+    }
+
+EXPORT_C CPolicySpec*
+CPolicySpec::NewL(TDesC& aName, TPolicySpecType iSpectype)
+    {
+    CPolicySpec* self = new (ELeave) CPolicySpec();
+    CleanupStack::PushL(self);
+    self->ConstructL(aName, iSpectype);
+    CleanupStack::Pop();
+    return self;
+    }
+
+EXPORT_C void
+CPolicySpec::ConstructL(TDesC& aName, TPolicySpecType aSpectype)
+    {
+    iName = HBufC8::NewL(aName.Length());
+    iName->Des().Copy(aName);
+    iSpectype = aSpectype;
+    }
+
+// Used to initialize with an existing CPolicySpec
+EXPORT_C CPolicySpec*
+CPolicySpec::NewL(CPolicySpec* aPolSpec)
+    {
+    CPolicySpec* self = new (ELeave) CPolicySpec();
+    CleanupStack::PushL(self);
+    self->ConstructL(aPolSpec);
+    CleanupStack::Pop();
+    return self;
+    }
+
+EXPORT_C void
+CPolicySpec::ConstructL(CPolicySpec* aPolSpec)
+    {
+    // Always bigger than 0
+    iName = HBufC8::NewL(aPolSpec->iName->Length()); 
+    *iName = *aPolSpec->iName;
+
+    if (aPolSpec->iRemoteIdentity)
+        {
+        iRemoteIdentity = HBufC8::NewL(aPolSpec->iRemoteIdentity->Length());
+        *iRemoteIdentity = *aPolSpec->iRemoteIdentity;
+        }
+
+    if (aPolSpec->iLocalIdentity)
+        {
+        iLocalIdentity = HBufC8::NewL(aPolSpec->iLocalIdentity->Length());
+        *iLocalIdentity = *aPolSpec->iLocalIdentity;
+        }
+    iSpec = aPolSpec->iSpec;
+    // Even the queue position is cloned    
+    iNext = aPolSpec->iNext;  
+    }
+
+EXPORT_C
+CPolicySpec::~CPolicySpec()
+    {
+    delete iName;
+    delete iRemoteIdentity;
+    delete iLocalIdentity;
+    }
+
+// CSAList
+CSAList::CSAList(TInt aGranularity) :
+    CArrayFixFlat<CPolicySpec *>(aGranularity)
+    {}
+
+EXPORT_C CSAList*
+CSAList::NewL(TInt aGranularity)
+    {
+    CSAList* self = new (ELeave) CSAList(aGranularity);
+    self->Construct(aGranularity);
+    return self;
+    }
+
+EXPORT_C void
+CSAList::Construct(TInt /* aGranularity */)
+    {}
+
+CSAList::CSAList(CSAList* aSAList) :
+    CArrayFixFlat<CPolicySpec *>(aSAList->Count())
+    {}
+
+EXPORT_C CSAList*
+CSAList::NewL(CSAList* aSAList)
+    {
+    CSAList* self = new (ELeave) CSAList(aSAList);
+    CleanupStack::PushL(self);
+    self->ConstructL(aSAList);
+    CleanupStack::Pop();
+    return self;
+    }
+
+EXPORT_C void
+CSAList::ConstructL(CSAList* aSAList)
+    {
+    TInt count(aSAList->Count());
+    for (TInt i = 0; i < count; i++)
+        {
+        CPolicySpec* policy = CPolicySpec::NewL(aSAList->At(i));
+        CleanupStack::PushL(policy);
+        AppendL(policy);
+        CleanupStack::Pop();
+        }
+    }
+
+//
+// CSelectorList
+//
+CSelectorList::CSelectorList(TInt aGranularity) :
+    CArrayFixFlat<CPolicySelector *>(aGranularity)
+    {}
+
+EXPORT_C CSelectorList*
+CSelectorList::NewL(TInt aGranularity)
+    {
+    CSelectorList* self = new (ELeave) CSelectorList(aGranularity);
+    self->Construct(aGranularity);
+    return self;
+    }
+
+EXPORT_C void
+CSelectorList::Construct(TInt /*aGranularity*/)
+    {}
+
+CSelectorList::CSelectorList(CSelectorList* aSelList,
+                             CSAPairList* /* aTable */) :
+    CArrayFixFlat<CPolicySelector *>(aSelList->Count())
+    {}
+
+EXPORT_C CSelectorList*
+CSelectorList::NewL(CSelectorList* aSelList,
+                    CSAPairList* aTable)
+    {
+    CSelectorList* self = new (ELeave) CSelectorList(aSelList, aTable);
+    CleanupStack::PushL(self);
+    self->ConstructL(aSelList, aTable);
+    CleanupStack::Pop();
+    return self;
+    }
+
+EXPORT_C void
+CSelectorList::ConstructL(CSelectorList* aSelList,
+                          CSAPairList* aTable)
+    {
+    TInt count(aSelList->Count());
+    for (TInt i = 0; i < count; i++)
+        {
+        CPolicySelector* selector = CPolicySelector::NewL(aSelList->At(i));
+        // Bundle translation
+        TSecpolBundleIter iterL(selector->iBundle);
+        CSecpolBundleItem* itemL(NULL);
+        while (((itemL = iterL++) != NULL))
+            {
+            if (itemL->iSpec)
+                {
+                itemL->iSpec = aTable->Translate(itemL->iSpec);
+                }
+            }
+
+        // Specs in the Bundle translated
+        CleanupStack::PushL(selector);
+        AppendL(selector);
+        CleanupStack::Pop();
+        }
+    }
+