--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/vpnengine/vpnmanager/src/policypatcher.cpp Thu Dec 17 09:14:51 2009 +0200
@@ -0,0 +1,484 @@
+/*
+* Copyright (c) 2003-2008 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: Policy importer
+*
+*/
+
+
+
+#include "policypatcher.h"
+#include "vpnapidefs.h"
+
+
+TAny* TPatchKeyArrayPtr::At(TInt aIndex) const
+ {
+ if (aIndex==KIndexPtr)
+ {
+ TAny* base = *(TUint8**)iPtr;
+ CPolicyPatchInfo* info = (CPolicyPatchInfo*)base;
+ return (TAny*)&(info->iPatchOffset);
+ }
+ else
+ {
+ TAny* base = *(TUint8**)iBase->Ptr(aIndex*sizeof(TUint8**)).Ptr();
+ CPolicyPatchInfo* info = (CPolicyPatchInfo*)base;
+ return (TAny*)&(info->iPatchOffset);
+ }
+ }
+
+
+CPolicyPatcher* CPolicyPatcher::NewL()
+ {
+ CPolicyPatcher* self = new (ELeave) CPolicyPatcher();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop();
+ return self;
+ }
+
+CPolicyPatcher::CPolicyPatcher()
+ {
+ }
+
+CPolicyPatcher::~CPolicyPatcher()
+ {
+ }
+
+void CPolicyPatcher::ConstructL()
+ {
+ }
+
+/*
+ * The policy file is patched as follows:
+ * - CA certificate references are changed from filenames
+ * into CA subject names (correspondingly, the reference
+ * type is changed from BIN to NAME)
+ * - User private key and certificate references are not
+ * removed although they are no longer in use
+ */
+HBufC8* CPolicyPatcher::PatchPolicyL(const TDesC8& aPolicyData,
+ CPolicyPatchInfoList* aPatchInfoList)
+ {
+ iInput.Set(aPolicyData);
+ iPatchInfoList = aPatchInfoList;
+
+ FindOffsetsL();
+
+ // Sort the resulting array to ascending order, using key
+ // patchInfo->iPatchOffset
+ TPatchKeyArrayPtr sortedCerts(_FOFF(CPatchData, iPatchOffset), ECmpTInt32);
+ iPatchInfoList->Sort(sortedCerts);
+
+ return CreateOutputL();
+ }
+
+void CPolicyPatcher::FindOffsetsL()
+ {
+ TInt formatValueOffset = KErrGeneral;
+
+ for (TInt i = 0; i < iPatchInfoList->Count(); i++)
+ {
+ CPolicyPatchInfo* patchInfo = iPatchInfoList->At(i);
+
+ TInt fileNameOffset = iInput.FindF(patchInfo->iCertFileName);
+
+ if (fileNameOffset != KErrNotFound)
+ {
+ TPtrC8 precedingInput = iInput.Left(fileNameOffset);
+
+ if (0 == patchInfo->UserCertKeyLen())
+ {
+ // CA cert
+ formatValueOffset = precedingInput.LocateReverseF(KBinChar);
+ }
+ else
+ {
+ // User cert
+ formatValueOffset = precedingInput.LocateReverseF(KFormatChar);
+ }
+
+ if (formatValueOffset != KErrNone)
+ {
+ patchInfo->iPatchOffset = formatValueOffset;
+ }
+ else
+ {
+ User::Leave(KVpnErrInvalidPolicyFile);
+ }
+
+ patchInfo->iReminderOffset = fileNameOffset + patchInfo->iCertFileName.Length();
+ }
+ }
+ }
+
+HBufC8* CPolicyPatcher::CreateOutputL()
+ {
+ TInt patchInfoCount = iPatchInfoList->Count();
+
+ CPatchDataList* patchDataList = new (ELeave) CPatchDataList(2);
+ CleanupStack::PushL(patchDataList);
+
+ for (TInt i = 0; i < patchInfoCount; i++)
+ {
+ CPolicyPatchInfo* patchInfo = iPatchInfoList->At(i);
+
+ if (patchInfo->iPatchOffset != KUndefinedOffset)
+ {
+ CPatchData* patchData = new (ELeave) CPatchData;
+ CleanupStack::PushL(patchData);
+
+ patchData->iPatchOffset = patchInfo->iPatchOffset;
+ patchData->iReminderOffset = patchInfo->iReminderOffset;
+ patchData->iData = CreatePatchDataL(patchInfo);
+
+ patchDataList->AppendL(patchData);
+
+ CleanupStack::Pop(); // patchData (now owned by the list)
+ }
+ }
+
+ TInt outputLength = iInput.Length();
+ TInt patchDataCount = patchDataList->Count();
+
+ for (TInt j = 0; j < patchDataCount; j++)
+ {
+ outputLength += patchDataList->At(j)->iData->Length();
+ }
+
+ HBufC8* output = HBufC8::NewL(outputLength);
+ TPtr8 ptrOutput = output->Des();
+
+ if (patchDataCount == 0)
+ {
+ ptrOutput.Append(iInput);
+ }
+ else
+ {
+ // Append all patches and the input data before,
+ // between and after them to the outout
+ for (TInt k = 0; k < patchDataCount; k++)
+ {
+ TInt startOffset;
+
+ // If this is the first patch...
+ if (k == 0)
+ {
+ // ...there is no previous patch whose
+ // reminder offset we could use
+ startOffset = 0;
+ }
+ else
+ {
+ // There is a previous patch whose reminder offset we can use
+ startOffset = patchDataList->At(k - 1)->iReminderOffset;
+ }
+
+ CPatchData* currPatchData = patchDataList->At(k);
+
+ TInt endOffset = currPatchData->iPatchOffset;
+
+ // Append to the output the input data between the previous
+ // patch (or the beginning of input if this is the first patch)
+ // and the current patch
+ ptrOutput.Append(iInput.Mid(startOffset, endOffset - startOffset));
+
+ // Append the current patch data to the output
+ ptrOutput.Append(*(currPatchData->iData));
+
+ // If this is the last patch...
+ if (k == (patchDataCount -1))
+ {
+ if(EFalse != iUserCertPatched)
+ {
+ // The data after user cert patch is not needed.
+ // Append new line instead.
+ // In practise this removes the PRIVATE_KEY_FORMAT
+ // and PRIVATE_KEY_DATA lines.
+ ptrOutput.Append(KNewLine);
+ }
+ else
+ {
+ // ...append to the output the input data between the
+ // last patch and the end of the input
+ ptrOutput.Append(iInput.Mid(currPatchData->iReminderOffset));
+ }
+ }
+ }
+ }
+
+ CleanupStack::PopAndDestroy(); // patchDataList
+
+ return output;
+ }
+
+HBufC8* CPolicyPatcher::CreatePatchDataL(const CPolicyPatchInfo* aPatchInfo)
+ {
+ TInt patchDataLength = 0;
+
+ TBuf8<20> keyBuf;
+
+ const TDesC8& certSubjectName = aPatchInfo->CertSubjectName();
+
+ if (0 == aPatchInfo->UserCertKeyLen())
+ {
+ // CA cert patch
+ patchDataLength = KName().Length() + KNewLine().Length() +
+ KDataField().Length() + KSpace().Length() +
+ certSubjectName.Length();
+ }
+ else
+ {
+ // user cert patch
+ keyBuf.Num(aPatchInfo->UserCertKeyLen());
+ patchDataLength = KDNField().Length() + certSubjectName.Length() +
+ KNewLine().Length() + KKeyLenField().Length() +
+ keyBuf.Length();
+ }
+
+ HBufC8* patchData = HBufC8::NewL(patchDataLength);
+ CleanupStack::PushL(patchData);
+
+ TPtr8 ptrPatchData(patchData->Des());
+
+ if (0 == aPatchInfo->UserCertKeyLen())
+ {
+ // CA cert patch
+ ptrPatchData.Append(KName);
+ ptrPatchData.Append(KNewLine);
+ ptrPatchData.Append(KDataField);
+ ptrPatchData.Append(KSpace);
+ ptrPatchData.Append(certSubjectName);
+ }
+ else
+ {
+ // User cert patch
+ ptrPatchData.Append(KKeyLenField);
+ ptrPatchData.Append(keyBuf);
+ ptrPatchData.Append(KNewLine);
+ ptrPatchData.Append(KDNField);
+ ptrPatchData.Append(certSubjectName);
+ iUserCertPatched = ETrue;
+ }
+
+ CleanupStack::Pop(); // patchData
+
+ return patchData;
+ }
+
+
+// CPolicyPatchInfo
+
+CPolicyPatchInfo::CPolicyPatchInfo()
+ {
+ iCertFileName.SetLength(0);
+ iPatchOffset = KUndefinedOffset;
+ iReminderOffset = KUndefinedOffset;
+ iUserCertKeyLen = 0;
+ }
+
+CPolicyPatchInfo::~CPolicyPatchInfo()
+ {
+ delete iCertSubjectName;
+ }
+
+const TDesC8& CPolicyPatchInfo::CertSubjectName() const
+ {
+ return *iCertSubjectName;
+ }
+
+void CPolicyPatchInfo::SetCertSubjectNameL(const TDesC8& aCertSubjectName)
+ {
+ delete iCertSubjectName;
+ iCertSubjectName = NULL;
+ HBufC8* certSubjectBuf = CheckSubjectNameSyntaxL(aCertSubjectName);
+ iCertSubjectName = certSubjectBuf;
+ }
+
+void CPolicyPatchInfo::SetUserCertKeyLen(TInt aKeyLen)
+ {
+ iUserCertKeyLen = aKeyLen;
+ }
+
+TInt CPolicyPatchInfo::UserCertKeyLen() const
+ {
+ return iUserCertKeyLen;
+ }
+
+HBufC8* CPolicyPatchInfo::CheckSubjectNameSyntaxL(const TDesC8& aSubj)
+ {
+ const TInt KMaxSubjectItems = 20;
+
+ _LIT8(KEqualSign, "=");
+ _LIT8(KCommaSign, ",");
+ _LIT8(KReplacementChar, "\"");
+
+ //counts positions for equal sign characters
+ CArrayFixFlat<TInt>* equalSignArr=new (ELeave) CArrayFixFlat<TInt> (KMaxSubjectItems);
+
+ //counts positions for comma characters
+ CArrayFixFlat<TInt>* commaSignArr=new (ELeave) CArrayFixFlat<TInt> (KMaxSubjectItems);
+
+ //counts positions for double quatiation characters
+ CArrayFixFlat<TInt>* updateArr=new (ELeave) CArrayFixFlat<TInt> (KMaxSubjectItems);
+
+ TInt subjLth=aSubj.Length();
+ TInt equalArrItemCount=0;
+ TInt commaArrItemCount=0;
+ TInt updateArrCount=0;
+
+ CleanupStack::PushL(equalSignArr);
+ CleanupStack::PushL(commaSignArr);
+
+ //register '=' and ',' character positions
+ for (TInt i=0; i<subjLth; i++)
+ {
+ if ( aSubj.Mid(i, 1)== KEqualSign )
+ {
+ equalSignArr->AppendL(i);
+ equalArrItemCount++;
+ }
+
+ if ( aSubj.Mid(i, 1)== KCommaSign )
+ {
+ commaSignArr->AppendL(i);
+ commaArrItemCount++;
+ }
+ }
+
+ CleanupStack::PushL(updateArr);
+
+ TInt i=0;
+ TInt j=0;
+
+ // At least one comma required. Otherwise there is no chance for extra commas
+ if ( commaArrItemCount )
+ {
+ while ( i< equalArrItemCount )
+ {
+
+ //advance starting position for every iteration
+ TInt eqSignStartIndex=i;
+
+ TInt cmCount=0;
+
+ //check wether there is more than one comma between two adjacent fields.
+ while ( commaSignArr->At(j)< equalSignArr->At(eqSignStartIndex) )
+ {
+ cmCount++;
+
+ j++;
+
+ if ( j==commaArrItemCount )
+ break;
+ }
+
+ //at least one extra comma character found. Mark positions for mofifications.
+ if (cmCount>1)
+ {
+ TInt equalPos=equalSignArr->At(eqSignStartIndex-1) + 1;
+ updateArr->AppendL(equalPos);
+
+ TInt commaPos=commaSignArr->At(j-1);
+ updateArr->AppendL(commaPos);
+
+ updateArrCount++;
+ updateArrCount++;
+ }
+ i++;
+ }
+ }
+
+ //Checking also last attribute of Subject Name string
+ if ( j<commaArrItemCount )
+ {
+ updateArr->AppendL(equalSignArr->At(equalArrItemCount-1));
+ updateArr->AppendL(subjLth-1);
+ }
+
+ TBuf8<256> resultBuf;
+ resultBuf.Copy(aSubj);
+
+ i=0;
+
+ //update subjectname acoording to updateArr array.
+ if ( updateArr->Count()>0 )
+ {
+ while (i<updateArrCount)
+ {
+ TBuf8<3> updateStr(KReplacementChar);
+
+ updateStr.Append(aSubj.Mid(updateArr->At(i),1));
+
+ if ( resultBuf.Length()<256 )
+ resultBuf.Insert(updateArr->At(i) + i, KReplacementChar);
+ else
+ User::Leave(KErrNotSupported);
+ i++;
+ }
+ }
+
+ CleanupStack::Pop(updateArr);
+ CleanupStack::Pop(commaSignArr);
+ CleanupStack::Pop(equalSignArr);
+
+ delete equalSignArr;
+ equalSignArr=NULL;
+
+ delete commaSignArr;
+ commaSignArr=NULL;
+
+ delete updateArr;
+ updateArr=NULL;
+
+ HBufC8* resultHeap = resultBuf.AllocL();
+
+ return resultHeap;
+ }
+
+
+// CPolicyPatchInfoList
+
+CPolicyPatchInfoList::CPolicyPatchInfoList(TInt aGranularity)
+ : CArrayPtrFlat<CPolicyPatchInfo>(aGranularity)
+ {
+ }
+
+CPolicyPatchInfoList::~CPolicyPatchInfoList()
+ {
+ ResetAndDestroy();
+ }
+
+
+// CPatchData
+
+CPatchData::~CPatchData()
+ {
+ delete iData;
+ }
+
+
+// CPatchDataList
+
+CPatchDataList::CPatchDataList(TInt aGranularity)
+ : CArrayPtrFlat<CPatchData>(aGranularity)
+ {
+ }
+
+CPatchDataList::~CPatchDataList()
+ {
+ ResetAndDestroy();
+ }
+
+
+/***/