diff -r 000000000000 -r 33413c0669b9 vpnengine/vpnmanager/src/policypatcher.cpp --- /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* equalSignArr=new (ELeave) CArrayFixFlat (KMaxSubjectItems); + + //counts positions for comma characters + CArrayFixFlat* commaSignArr=new (ELeave) CArrayFixFlat (KMaxSubjectItems); + + //counts positions for double quatiation characters + CArrayFixFlat* updateArr=new (ELeave) CArrayFixFlat (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; iAppendL(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 ( jAppendL(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 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(aGranularity) + { + } + +CPolicyPatchInfoList::~CPolicyPatchInfoList() + { + ResetAndDestroy(); + } + + +// CPatchData + +CPatchData::~CPatchData() + { + delete iData; + } + + +// CPatchDataList + +CPatchDataList::CPatchDataList(TInt aGranularity) + : CArrayPtrFlat(aGranularity) + { + } + +CPatchDataList::~CPatchDataList() + { + ResetAndDestroy(); + } + + +/***/