vpnengine/vpnmanager/src/policypatcher.cpp
changeset 0 33413c0669b9
child 2 ef893827b4d1
equal deleted inserted replaced
-1:000000000000 0:33413c0669b9
       
     1 /*
       
     2 * Copyright (c) 2003-2008 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:   Policy importer
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 #include "policypatcher.h"
       
    21 #include "vpnapidefs.h"
       
    22 
       
    23 
       
    24 TAny* TPatchKeyArrayPtr::At(TInt aIndex) const
       
    25     {
       
    26     if (aIndex==KIndexPtr)
       
    27         {
       
    28         TAny* base = *(TUint8**)iPtr;
       
    29         CPolicyPatchInfo* info = (CPolicyPatchInfo*)base;
       
    30         return (TAny*)&(info->iPatchOffset);
       
    31         }
       
    32     else
       
    33         {
       
    34         TAny* base = *(TUint8**)iBase->Ptr(aIndex*sizeof(TUint8**)).Ptr();
       
    35         CPolicyPatchInfo* info = (CPolicyPatchInfo*)base;
       
    36         return (TAny*)&(info->iPatchOffset);
       
    37         }
       
    38     }
       
    39 
       
    40 
       
    41 CPolicyPatcher* CPolicyPatcher::NewL()
       
    42     {
       
    43     CPolicyPatcher* self = new (ELeave) CPolicyPatcher();
       
    44     CleanupStack::PushL(self);
       
    45     self->ConstructL();
       
    46     CleanupStack::Pop();
       
    47     return self;
       
    48     }
       
    49 
       
    50 CPolicyPatcher::CPolicyPatcher()
       
    51     {
       
    52     }
       
    53 
       
    54 CPolicyPatcher::~CPolicyPatcher()
       
    55     {
       
    56     }
       
    57 
       
    58 void CPolicyPatcher::ConstructL()
       
    59     {
       
    60     }
       
    61 
       
    62 /*
       
    63  * The policy file is patched as follows:
       
    64  * - CA certificate references are changed from filenames
       
    65  *   into CA subject names (correspondingly, the reference
       
    66  *   type is changed from BIN to NAME)
       
    67  * - User private key and certificate references are not
       
    68  *   removed although they are no longer in use
       
    69  */
       
    70 HBufC8* CPolicyPatcher::PatchPolicyL(const TDesC8& aPolicyData,
       
    71                                      CPolicyPatchInfoList* aPatchInfoList)
       
    72     {
       
    73     iInput.Set(aPolicyData);
       
    74     iPatchInfoList = aPatchInfoList;
       
    75 
       
    76     FindOffsetsL();
       
    77 
       
    78     // Sort the resulting array to ascending order, using key
       
    79     // patchInfo->iPatchOffset
       
    80     TPatchKeyArrayPtr sortedCerts(_FOFF(CPatchData, iPatchOffset), ECmpTInt32);
       
    81     iPatchInfoList->Sort(sortedCerts);
       
    82 
       
    83     return CreateOutputL();
       
    84     }
       
    85 
       
    86 void CPolicyPatcher::FindOffsetsL()
       
    87     {
       
    88     TInt formatValueOffset = KErrGeneral;
       
    89 
       
    90     for (TInt i = 0; i < iPatchInfoList->Count(); i++)
       
    91         {
       
    92         CPolicyPatchInfo* patchInfo = iPatchInfoList->At(i);
       
    93 
       
    94         TInt fileNameOffset = iInput.FindF(patchInfo->iCertFileName);
       
    95 
       
    96         if (fileNameOffset != KErrNotFound)
       
    97             {
       
    98             TPtrC8 precedingInput = iInput.Left(fileNameOffset);
       
    99 
       
   100             if (0 == patchInfo->UserCertKeyLen())
       
   101                 {
       
   102                 // CA cert
       
   103                 formatValueOffset = precedingInput.LocateReverseF(KBinChar);
       
   104                 }
       
   105             else
       
   106                 {
       
   107                 // User cert
       
   108                 formatValueOffset = precedingInput.LocateReverseF(KFormatChar);
       
   109                 }
       
   110 
       
   111             if (formatValueOffset != KErrNone)
       
   112                 {
       
   113                 patchInfo->iPatchOffset = formatValueOffset;
       
   114                 }
       
   115             else
       
   116                 {
       
   117                 User::Leave(KVpnErrInvalidPolicyFile);
       
   118                 }
       
   119 
       
   120             patchInfo->iReminderOffset = fileNameOffset + patchInfo->iCertFileName.Length();
       
   121             }
       
   122         }
       
   123     }
       
   124 
       
   125 HBufC8* CPolicyPatcher::CreateOutputL()
       
   126     {
       
   127     TInt patchInfoCount = iPatchInfoList->Count();
       
   128 
       
   129     CPatchDataList* patchDataList = new (ELeave) CPatchDataList(2);
       
   130     CleanupStack::PushL(patchDataList);
       
   131 
       
   132     for (TInt i = 0; i < patchInfoCount; i++)
       
   133         {
       
   134         CPolicyPatchInfo* patchInfo = iPatchInfoList->At(i);
       
   135 
       
   136         if (patchInfo->iPatchOffset != KUndefinedOffset)
       
   137             {
       
   138             CPatchData* patchData = new (ELeave) CPatchData;
       
   139             CleanupStack::PushL(patchData);
       
   140 
       
   141             patchData->iPatchOffset = patchInfo->iPatchOffset;
       
   142             patchData->iReminderOffset = patchInfo->iReminderOffset;
       
   143             patchData->iData = CreatePatchDataL(patchInfo);
       
   144 
       
   145             patchDataList->AppendL(patchData);
       
   146 
       
   147             CleanupStack::Pop(); // patchData (now owned by the list)
       
   148             }
       
   149         }
       
   150 
       
   151     TInt outputLength = iInput.Length();
       
   152     TInt patchDataCount = patchDataList->Count();
       
   153 
       
   154     for (TInt j = 0; j < patchDataCount; j++)
       
   155         {
       
   156         outputLength += patchDataList->At(j)->iData->Length();
       
   157         }
       
   158 
       
   159     HBufC8* output = HBufC8::NewL(outputLength);
       
   160     TPtr8 ptrOutput = output->Des();
       
   161 
       
   162     if (patchDataCount == 0)
       
   163         {
       
   164         ptrOutput.Append(iInput);
       
   165         }
       
   166     else
       
   167         {
       
   168         // Append all patches and the input data before,
       
   169         // between and after them to the outout
       
   170         for (TInt k = 0; k < patchDataCount; k++)
       
   171             {
       
   172             TInt startOffset;
       
   173 
       
   174             // If this is the first patch...
       
   175             if (k == 0)
       
   176                 {
       
   177                 // ...there is no previous patch whose
       
   178                 // reminder offset we could use
       
   179                 startOffset = 0;
       
   180                 }
       
   181             else
       
   182                 {
       
   183                 // There is a previous patch whose reminder offset we can use
       
   184                 startOffset = patchDataList->At(k - 1)->iReminderOffset;
       
   185                 }
       
   186 
       
   187             CPatchData* currPatchData = patchDataList->At(k);
       
   188 
       
   189             TInt endOffset = currPatchData->iPatchOffset;
       
   190 
       
   191             // Append to the output the input data between the previous
       
   192             // patch (or the beginning of input if this is the first patch)
       
   193             // and the current patch
       
   194             ptrOutput.Append(iInput.Mid(startOffset, endOffset - startOffset));
       
   195 
       
   196             // Append the current patch data to the output
       
   197             ptrOutput.Append(*(currPatchData->iData));
       
   198 
       
   199             // If this is the last patch...
       
   200             if (k == (patchDataCount -1))
       
   201                 {
       
   202                 if(EFalse != iUserCertPatched)
       
   203                     {
       
   204                     // The data after user cert patch is not needed.
       
   205                     // Append new line instead.
       
   206                     // In practise this removes the PRIVATE_KEY_FORMAT
       
   207                     // and PRIVATE_KEY_DATA lines.
       
   208                     ptrOutput.Append(KNewLine);
       
   209                     }
       
   210                 else
       
   211                     {
       
   212                     // ...append to the output the input data between the
       
   213                     // last patch and the end of the input
       
   214                     ptrOutput.Append(iInput.Mid(currPatchData->iReminderOffset));
       
   215                     }
       
   216                 }
       
   217             }
       
   218         }
       
   219 
       
   220     CleanupStack::PopAndDestroy(); // patchDataList
       
   221 
       
   222     return output;
       
   223     }
       
   224 
       
   225 HBufC8* CPolicyPatcher::CreatePatchDataL(const CPolicyPatchInfo* aPatchInfo)
       
   226     {
       
   227     TInt patchDataLength = 0;
       
   228 
       
   229     TBuf8<20> keyBuf;
       
   230 
       
   231     const TDesC8& certSubjectName = aPatchInfo->CertSubjectName();
       
   232 
       
   233     if (0 == aPatchInfo->UserCertKeyLen())
       
   234         {
       
   235         // CA cert patch
       
   236         patchDataLength = KName().Length() + KNewLine().Length() +
       
   237                           KDataField().Length() + KSpace().Length() +
       
   238                           certSubjectName.Length();
       
   239         }
       
   240     else
       
   241         {
       
   242         // user cert patch
       
   243         keyBuf.Num(aPatchInfo->UserCertKeyLen());
       
   244         patchDataLength = KDNField().Length() + certSubjectName.Length() +
       
   245                           KNewLine().Length() + KKeyLenField().Length() +
       
   246                           keyBuf.Length();
       
   247         }
       
   248 
       
   249     HBufC8* patchData = HBufC8::NewL(patchDataLength);
       
   250     CleanupStack::PushL(patchData);
       
   251 
       
   252     TPtr8 ptrPatchData(patchData->Des());
       
   253 
       
   254     if (0 == aPatchInfo->UserCertKeyLen())
       
   255         {
       
   256         // CA cert patch
       
   257         ptrPatchData.Append(KName);
       
   258         ptrPatchData.Append(KNewLine);
       
   259         ptrPatchData.Append(KDataField);
       
   260         ptrPatchData.Append(KSpace);
       
   261         ptrPatchData.Append(certSubjectName);
       
   262         }
       
   263     else
       
   264         {
       
   265         // User cert patch
       
   266         ptrPatchData.Append(KKeyLenField);
       
   267         ptrPatchData.Append(keyBuf);
       
   268         ptrPatchData.Append(KNewLine);
       
   269         ptrPatchData.Append(KDNField);
       
   270         ptrPatchData.Append(certSubjectName);
       
   271         iUserCertPatched = ETrue;
       
   272         }
       
   273 
       
   274     CleanupStack::Pop(); // patchData
       
   275 
       
   276     return patchData;
       
   277     }
       
   278 
       
   279 
       
   280 // CPolicyPatchInfo
       
   281 
       
   282 CPolicyPatchInfo::CPolicyPatchInfo()
       
   283     {
       
   284     iCertFileName.SetLength(0);
       
   285     iPatchOffset = KUndefinedOffset;
       
   286     iReminderOffset = KUndefinedOffset;
       
   287     iUserCertKeyLen = 0;
       
   288     }
       
   289 
       
   290 CPolicyPatchInfo::~CPolicyPatchInfo()
       
   291     {
       
   292     delete iCertSubjectName;
       
   293     }
       
   294 
       
   295 const TDesC8& CPolicyPatchInfo::CertSubjectName() const
       
   296     {
       
   297     return *iCertSubjectName;
       
   298     }
       
   299 
       
   300 void CPolicyPatchInfo::SetCertSubjectNameL(const TDesC8& aCertSubjectName)
       
   301     {
       
   302     delete iCertSubjectName;
       
   303     iCertSubjectName = NULL;
       
   304     HBufC8* certSubjectBuf = CheckSubjectNameSyntaxL(aCertSubjectName);  
       
   305     iCertSubjectName = certSubjectBuf;
       
   306     }
       
   307 
       
   308 void CPolicyPatchInfo::SetUserCertKeyLen(TInt aKeyLen)
       
   309     {
       
   310     iUserCertKeyLen = aKeyLen;
       
   311     }
       
   312 
       
   313 TInt CPolicyPatchInfo::UserCertKeyLen() const
       
   314     {
       
   315     return iUserCertKeyLen;
       
   316     }
       
   317     
       
   318 HBufC8* CPolicyPatchInfo::CheckSubjectNameSyntaxL(const TDesC8& aSubj)
       
   319     {
       
   320     const TInt KMaxSubjectItems = 20;
       
   321     
       
   322     _LIT8(KEqualSign, "=");
       
   323     _LIT8(KCommaSign, ",");
       
   324     _LIT8(KReplacementChar, "\"");
       
   325     
       
   326     //counts positions for equal sign characters
       
   327     CArrayFixFlat<TInt>* equalSignArr=new (ELeave) CArrayFixFlat<TInt> (KMaxSubjectItems); 
       
   328     
       
   329     //counts positions for comma characters
       
   330     CArrayFixFlat<TInt>* commaSignArr=new (ELeave) CArrayFixFlat<TInt> (KMaxSubjectItems); 
       
   331     
       
   332     //counts positions for double quatiation characters
       
   333     CArrayFixFlat<TInt>* updateArr=new (ELeave) CArrayFixFlat<TInt> (KMaxSubjectItems);
       
   334     
       
   335     TInt subjLth=aSubj.Length();
       
   336     TInt equalArrItemCount=0;
       
   337     TInt commaArrItemCount=0;
       
   338     TInt updateArrCount=0;
       
   339     
       
   340     CleanupStack::PushL(equalSignArr);
       
   341     CleanupStack::PushL(commaSignArr);
       
   342     
       
   343     //register '=' and ',' character positions 
       
   344     for (TInt i=0; i<subjLth; i++)
       
   345         {
       
   346         if ( aSubj.Mid(i, 1)== KEqualSign )
       
   347             {
       
   348             equalSignArr->AppendL(i);
       
   349             equalArrItemCount++;
       
   350             }
       
   351         
       
   352         if ( aSubj.Mid(i, 1)== KCommaSign )
       
   353             {
       
   354             commaSignArr->AppendL(i);
       
   355             commaArrItemCount++;
       
   356             }
       
   357         }
       
   358     
       
   359     CleanupStack::PushL(updateArr);
       
   360     
       
   361     TInt i=0;
       
   362     TInt j=0;
       
   363     
       
   364     // At least one comma required. Otherwise there is no chance for extra commas
       
   365     if ( commaArrItemCount )
       
   366         {
       
   367         while ( i< equalArrItemCount )
       
   368             {
       
   369             
       
   370             //advance starting position for every iteration
       
   371             TInt eqSignStartIndex=i;
       
   372             
       
   373             TInt cmCount=0;
       
   374         
       
   375             //check wether there is more than one comma between two adjacent fields.
       
   376             while ( commaSignArr->At(j)< equalSignArr->At(eqSignStartIndex) )
       
   377                 {
       
   378                 cmCount++;
       
   379                 
       
   380                 j++;
       
   381                 
       
   382                 if ( j==commaArrItemCount )
       
   383                     break;
       
   384                 }
       
   385             
       
   386             //at least one extra comma character found. Mark positions for mofifications.
       
   387             if (cmCount>1)
       
   388                 {
       
   389                 TInt equalPos=equalSignArr->At(eqSignStartIndex-1) + 1;
       
   390                 updateArr->AppendL(equalPos);
       
   391                 
       
   392                 TInt commaPos=commaSignArr->At(j-1);
       
   393                 updateArr->AppendL(commaPos);
       
   394                 
       
   395                 updateArrCount++;
       
   396                 updateArrCount++;
       
   397                 }
       
   398             i++;    
       
   399             }
       
   400         }
       
   401         
       
   402         //Checking also last attribute of Subject Name string
       
   403         if ( j<commaArrItemCount )
       
   404             {
       
   405             updateArr->AppendL(equalSignArr->At(equalArrItemCount-1));
       
   406             updateArr->AppendL(subjLth-1);
       
   407             }
       
   408        
       
   409        TBuf8<256> resultBuf;
       
   410        resultBuf.Copy(aSubj);
       
   411        
       
   412        i=0;       
       
   413        
       
   414        //update subjectname acoording to updateArr array.
       
   415        if ( updateArr->Count()>0 )
       
   416            {
       
   417            while (i<updateArrCount)
       
   418                {
       
   419                TBuf8<3> updateStr(KReplacementChar);
       
   420                
       
   421                updateStr.Append(aSubj.Mid(updateArr->At(i),1));
       
   422                
       
   423                if ( resultBuf.Length()<256 )
       
   424                    resultBuf.Insert(updateArr->At(i) + i, KReplacementChar);
       
   425                else
       
   426                    User::Leave(KErrNotSupported);
       
   427                i++;
       
   428                }
       
   429            }
       
   430        
       
   431        CleanupStack::Pop(updateArr);
       
   432        CleanupStack::Pop(commaSignArr);
       
   433        CleanupStack::Pop(equalSignArr);
       
   434        
       
   435        delete equalSignArr;
       
   436        equalSignArr=NULL;
       
   437        
       
   438        delete commaSignArr;
       
   439        commaSignArr=NULL;
       
   440        
       
   441        delete updateArr;
       
   442        updateArr=NULL;
       
   443        
       
   444        HBufC8* resultHeap = resultBuf.AllocL();
       
   445        
       
   446        return resultHeap;
       
   447     }
       
   448 
       
   449 
       
   450 // CPolicyPatchInfoList
       
   451 
       
   452 CPolicyPatchInfoList::CPolicyPatchInfoList(TInt aGranularity)
       
   453     : CArrayPtrFlat<CPolicyPatchInfo>(aGranularity)
       
   454     {
       
   455     }
       
   456 
       
   457 CPolicyPatchInfoList::~CPolicyPatchInfoList()
       
   458     {
       
   459     ResetAndDestroy();
       
   460     }
       
   461 
       
   462 
       
   463 // CPatchData
       
   464 
       
   465 CPatchData::~CPatchData()
       
   466     {
       
   467     delete iData;
       
   468     }
       
   469 
       
   470 
       
   471 // CPatchDataList
       
   472 
       
   473 CPatchDataList::CPatchDataList(TInt aGranularity)
       
   474     : CArrayPtrFlat<CPatchData>(aGranularity)
       
   475     {
       
   476     }
       
   477 
       
   478 CPatchDataList::~CPatchDataList()
       
   479     {
       
   480     ResetAndDestroy();
       
   481     }
       
   482 
       
   483 
       
   484 /***/