--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/vpnengine/pkiservice/src/pkimapper.cpp Thu Dec 17 09:14:51 2009 +0200
@@ -0,0 +1,984 @@
+/*
+* Copyright (c) 2006-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:
+* CPKIMapper class holds the information required to map API set to
+* use the storage model which is not native for that API.
+*
+*/
+
+
+#include <x500dn.h>
+#include <x509cert.h>
+
+#include "PKIMapper.h"
+#include "pkcs10.h"
+#include "log_r6.h"
+#include "pkiserviceassert.h"
+
+
+CMapDescriptor::CMapDescriptor(TSecurityObjectDescriptor &aDesc)
+ {
+ this->iSubjectKeyId = aDesc.iSubjectKeyId;
+ this->iOwnerType = aDesc.iOwnerType;
+ this->iKeySize = aDesc.iKeySize;
+ this->iKeyAlgorithm = aDesc.iKeyAlgorithm;
+ this->iIsDeletable = aDesc.iIsDeletable;
+ }
+
+CMapDescriptor& CMapDescriptor::operator=(CMapDescriptor& aMapDesc)
+{
+ delete this->iTrustedAuthority;
+ this->iTrustedAuthority = NULL;
+ if(aMapDesc.iTrustedAuthority != NULL)
+ {
+ this->iTrustedAuthority = aMapDesc.iTrustedAuthority->Des().AllocL(); // Cert TrustedAuthority
+ }
+ delete this->iIdentitySubjectName;
+ this->iIdentitySubjectName = NULL;
+ if(aMapDesc.iIdentitySubjectName != NULL)
+ {
+ this->iIdentitySubjectName = aMapDesc.iIdentitySubjectName->Des().AllocL(); // Identity subject name
+ }
+ delete this->iIdentityRfc822Name;
+ this->iIdentityRfc822Name = NULL;
+ if(aMapDesc.iIdentityRfc822Name != NULL)
+ {
+ this->iIdentityRfc822Name = aMapDesc.iIdentityRfc822Name->Des().AllocL(); // Identity subjectAltName rfc822 name
+ }
+ delete this->iSerialNumber;
+ this->iSerialNumber = NULL;
+ if(aMapDesc.iSerialNumber != NULL)
+ {
+ this->iSerialNumber = aMapDesc.iSerialNumber->Des().AllocL(); // Serialnumber
+ }
+
+ this->iSubjectKeyId = aMapDesc.iSubjectKeyId; // SHA1 hash of the corresponding private key
+ this->iOwnerType = aMapDesc.iOwnerType; // User, CA or peer. If user certificate, at least key usage must be set
+ this->iKeyUsageDer = aMapDesc.iKeyUsageDer; // Der format flags
+ this->iObjectName = aMapDesc.iObjectName;
+ this->iKeySize = aMapDesc.iKeySize; // Key size
+ this->iKeyAlgorithm = aMapDesc.iKeyAlgorithm; // RSA, DSA
+ this->iStartTime = aMapDesc.iStartTime;
+ this->iEndTime = aMapDesc.iEndTime;
+ this->iIsDeletable = aMapDesc.iIsDeletable;
+ TInt i;
+ for(i=0;i<aMapDesc.iApplUids.Count();i++)
+ {
+ this->iApplUids.Append(aMapDesc.iApplUids[i]);
+ }
+
+ this->iCertStoreType = aMapDesc.iCertStoreType;
+ return *this;
+}
+
+
+TBool CMapDescriptor::IsMatchingL(TSecurityObjectDescriptor &aDesc,
+ const TBool aInfoOnly,
+ TPkiServiceStoreType aCertStoreType) const
+ {
+ TBool match(EFalse);
+
+ LOG(Log::Printf(_L("Matching")));
+ LOG_1(" Pure informational: %d", aInfoOnly);
+
+ LOG(Log::Printf(_L("Matching: certificate %S"), &iObjectName));
+ for(;;)
+ {
+ if (aDesc.iOwnerType != EPKICACertificate &&
+ aCertStoreType != EPkiStoreTypeAny)
+ {
+ if (iCertStoreType != aCertStoreType)
+ {
+ LOG(Log::Printf(_L(" Store doesn't match, aborting")));
+ match = EFalse;
+ break;
+ }
+ }
+ else
+ {
+ LOG(Log::Printf(_L("Skipping store check, not relevant")));
+ }
+
+
+ if (aDesc.iSubjectKeyIdUsed)
+ {
+ if(iSubjectKeyId == aDesc.iSubjectKeyId)
+ {
+ match = ETrue;
+ }
+ else
+ {
+ match = EFalse;
+ break;
+ }
+ }
+
+ if(aDesc.iTrustedAuthorityUsed)
+ {
+ if(iTrustedAuthority == NULL)
+ {
+ match = EFalse;
+ break;
+ }
+ else
+ {
+ CX500DistinguishedName* dnSuffix1 = CX500DistinguishedName::NewLC(*iTrustedAuthority);
+ CX500DistinguishedName* dnSuffix2;
+ TInt popCount = 3;
+
+ // ASN1 or plain text
+ if((aDesc.iTrustedAuthority[0] != 0x30)
+ || ((aDesc.iTrustedAuthority[1] != 0x81)
+ && (aDesc.iTrustedAuthority[1] != 0x82)
+ && ((aDesc.iTrustedAuthority[1] + 2) != aDesc.iTrustedAuthority.Length())))
+ {
+ HBufC8* name2Der;
+ CPkcs10Req::BuildDistinguishedNameDerFromTextL(name2Der,
+ aDesc.iTrustedAuthority,
+ EFalse, KNullDesC8);
+ CleanupStack::PushL(name2Der);
+
+ dnSuffix2 = CX500DistinguishedName::NewLC(*name2Der);
+ }
+ else
+ {
+ dnSuffix2 = CX500DistinguishedName::NewLC(aDesc.iTrustedAuthority);
+ popCount = 2;
+ }
+
+
+ if(PkiUtil::MatchL(*dnSuffix1, *dnSuffix2))
+ {
+ match = ETrue;
+ CleanupStack::PopAndDestroy(popCount);
+ }
+ else
+ {
+ match = EFalse;
+ CleanupStack::PopAndDestroy(popCount);
+ break;
+ }
+ }
+ }
+ if(aDesc.iOwnerTypeUsed)
+ {
+ if(iOwnerType == aDesc.iOwnerType)
+ {
+ match = ETrue;
+ }
+ else
+ {
+ match = EFalse;
+ break;
+ }
+ }
+ if(aDesc.iSerialNumberUsed)
+ {
+ if ((iSerialNumber != NULL) && ((*iSerialNumber).Compare(aDesc.iSerialNumber) == 0))
+ {
+ match = ETrue;
+ }
+ else
+ {
+ match = EFalse;
+ break;
+ }
+ }
+
+ if(aDesc.iIdentitySubjectNameUsed)
+ {
+ if(iIdentitySubjectName == NULL)
+ {
+ match = EFalse;
+ break;
+ }
+ else
+ {
+ CX500DistinguishedName* dnSuffix1 = CX500DistinguishedName::NewLC(*iIdentitySubjectName);
+ CX500DistinguishedName* dnSuffix2;
+ TInt popCount = 3;
+ // ASN1 or plain text
+ if((aDesc.iIdentitySubjectName[0] != 0x30)
+ || ((aDesc.iIdentitySubjectName[1] != 0x81)
+ && (aDesc.iIdentitySubjectName[1] != 0x82)
+ && ((aDesc.iIdentitySubjectName[1] + 2) != aDesc.iIdentitySubjectName.Length())))
+ {
+ HBufC8* name2Der;
+ CPkcs10Req::BuildDistinguishedNameDerFromTextL(name2Der,
+ aDesc.iIdentitySubjectName,
+ EFalse, KNullDesC8);
+ CleanupStack::PushL(name2Der);
+
+ dnSuffix2 = CX500DistinguishedName::NewLC(*name2Der);
+ }
+ else
+ {
+ dnSuffix2 = CX500DistinguishedName::NewLC(aDesc.iIdentitySubjectName);
+ popCount = 2;
+ }
+
+ if(PkiUtil::MatchL(*dnSuffix1, *dnSuffix2))
+ {
+ CleanupStack::PopAndDestroy(popCount);
+ match = ETrue;
+ }
+ else
+ {
+ CleanupStack::PopAndDestroy(popCount);
+ match = EFalse;
+ break;
+ }
+ }
+ }
+
+ if(aDesc.iIdentityRfc822NameUsed)
+ {
+ if(iIdentityRfc822Name == NULL)
+ {
+ match = EFalse;
+ break;
+ }
+ else
+ {
+ TInt bytes = aDesc.iIdentityRfc822Name.Length();
+ TPtrC8 tail = (*iIdentityRfc822Name).Right(bytes);
+ if (tail.CompareF(aDesc.iIdentityRfc822Name) == 0)
+ {
+ match = ETrue;
+ }
+ else
+ {
+ match = EFalse;
+ break;
+ }
+ }
+ }
+
+ if(aDesc.iKeyUsageUsed)
+ {
+ CX509KeyUsageExt* tempUsage = NULL;
+ if(iKeyUsageDer.Length() != 0)
+ {
+ tempUsage = CX509KeyUsageExt::NewL(iKeyUsageDer);
+ }
+ if((tempUsage == NULL) || tempUsage->IsSet(aDesc.iKeyUsage))
+ {
+ delete tempUsage;
+ match = ETrue;
+ }
+ else
+ {
+ delete tempUsage;
+ match = EFalse;
+ break;
+ }
+ }
+
+ if(aDesc.iKeySizeUsed)
+ {
+ if(iKeySize == aDesc.iKeySize)
+ {
+ match = ETrue;
+ }
+ else
+ {
+ match = EFalse;
+ break;
+ }
+ }
+
+ if (match && !aInfoOnly)
+ {
+ TValidity val = CPKIMapper::CertValidity(iStartTime, iEndTime);
+ // Treat future certificates as valid
+ if((val == EValid) || (val == ENotValidYet))
+ {
+ match = ETrue;
+ }
+ else
+ {
+ LOG_("Matching: Expired, and not an informational request");
+ match = EFalse;
+ break;
+ }
+ }
+
+ break;
+ }
+
+ return match;
+ }
+
+TBool CMapDescriptor::IsEqual(CMapDescriptor &aDesc)
+ {
+ TBool match = EFalse;
+
+ for(;;)
+ {
+ if((iTrustedAuthority != NULL) && (aDesc.iTrustedAuthority != NULL) && (iTrustedAuthority->Des().Compare(*aDesc.iTrustedAuthority) == 0))
+ {
+ match = ETrue;
+ }
+ else
+ {
+ match = EFalse;
+ break;
+ }
+
+ if((iSerialNumber != NULL) && (aDesc.iSerialNumber != NULL) && (iSerialNumber->Des().Compare(*aDesc.iSerialNumber) == 0))
+ {
+ match = ETrue;
+ }
+ else
+ {
+ match = EFalse;
+ break;
+ }
+
+ break;
+ }
+
+ return match;
+ }
+
+
+void CMapDescriptor::SetCertStoreType(TPkiServiceStoreType aCertStoreType)
+ {
+ iCertStoreType = aCertStoreType;
+ }
+
+CPKIMapper* CPKIMapper::NewL()
+ {
+ CPKIMapper* self = new (ELeave) CPKIMapper();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+CPKIMapper::~CPKIMapper()
+ {
+ if ( iMapping )
+ {
+ iMapping->ResetAndDestroy();
+ delete iMapping;
+ }
+ }
+
+
+CPKIMapper::CPKIMapper()
+ {
+ }
+
+void CPKIMapper::ConstructL()
+ {
+ LOG_("CPKIMapper::ConstructL");
+ // Allocate mapping vector. Approx granularity 20
+ iMapping = new (ELeave) RPointerArray<CMapDescriptor>(20);
+ }
+
+void CPKIMapper::SetCacheCreated()
+ {
+ iCacheCreated = ETrue;
+ }
+TBool CPKIMapper::CacheCreated()
+ {
+ return iCacheCreated;
+ }
+
+TInt CPKIMapper::AddMapping(CMapDescriptor& aMap)
+ {
+ // Insert as first element, so that newest object will be found first
+ return iMapping->Insert(&aMap, 0);
+ }
+
+void CPKIMapper::LogMap(CMapDescriptor &aDescriptor) const
+ {
+ TInt len = aDescriptor.iSubjectKeyId.Length();
+ LOG(Log::Printf(_L("====CertificateObject====\n")));
+ LOG(Log::Printf(_L("ObjectName: %S\n"), &(aDescriptor.iObjectName)));
+ LOG(Log::Printf(_L("KeyId:")));
+ LOG(Log::HexDump(NULL, NULL, aDescriptor.iSubjectKeyId.Ptr(), len));
+ }
+
+
+void CPKIMapper::DeleteMapping(TInt aIndex)
+ {
+ // Delete mapping at index
+ LOG(Log::Printf(_L("Delete mapping entry")));
+ LogMap(*(*iMapping)[aIndex]);
+ delete (*iMapping)[aIndex];
+ iMapping->Remove(aIndex);
+ iMapping->Compress();
+ }
+
+TInt CPKIMapper::DeleteMapping(CMapDescriptor &aDesc)
+ {
+ TInt status(KErrNotFound);
+
+ for(TInt i(0); i < iMapping->Count(); i++)
+ {
+ if((*iMapping)[i]->IsEqual(aDesc))
+ {
+ DeleteMapping(i);
+ status = KErrNone;
+ break;
+ }
+ }
+ return status;
+ }
+
+TInt CPKIMapper::CertCount()
+ {
+ TInt count(0);
+
+ for(TInt i(0); i < iMapping->Count(); i++)
+ {
+ CMapDescriptor* mapping = (*iMapping)[i];
+ count++;
+ if (CertValidity(mapping->iStartTime, mapping->iEndTime) == EExpired)
+ {
+ // do not count expider certificates
+ count--;
+ }
+ }
+ iCount = count;
+ return count;
+ }
+
+TInt CPKIMapper::ApplicableCertCount(const RArray<TUid>& aUidArray)
+{
+ TInt count(0);
+ TBool uidMatch(EFalse);
+
+ for(TInt i(0); i < iMapping->Count(); i++)
+ {
+ CMapDescriptor* mapping = (*iMapping)[i];
+ if(mapping->iOwnerType == EPKICACertificate)
+ {
+ if(CertValidity(mapping->iStartTime, mapping->iEndTime) != EExpired)
+ {
+ uidMatch = EFalse;
+ for(TInt j = 0; j < mapping->iApplUids.Count(); j++)
+ {
+ for(TInt k = 0; k < aUidArray.Count(); k++)
+ {
+ if(mapping->iApplUids[j].iUid == aUidArray[k].iUid)
+ {
+ uidMatch = ETrue;
+ break;
+ }
+ }
+ if(uidMatch)
+ {
+ count++;
+ break;
+ }
+ }
+ }
+ }
+ }
+ iCount = count;
+ return count;
+}
+
+
+TInt CPKIMapper::GetCertListL(const RMessage2 &aMessage, TPkiServiceStoreType aStoreType,
+ TBool aDescUsed)
+{
+ TInt pos = 0;
+ TInt iLast = 0;
+ TInt iFirst = 0;
+
+ if(aDescUsed)
+ {
+ aMessage.ReadL(1, iCurrentDescriptor);
+ TSecurityObjectDescriptor& secDesc = iCurrentDescriptor();
+ TInt status = ResolveCertMappingL(
+ iCurrentDescriptor(), iObjectName, iFirst, EFalse, aStoreType);
+ if(status == KErrNone)
+ {
+ iCount = 1;
+ iLast = iFirst + 1;
+ }
+ }
+ else
+ {
+ iLast = iMapping->Count();
+ }
+
+ CBufFlat* list = CBufFlat::NewL(sizeof(TCertificateListEntry));
+ CleanupStack::PushL(list);
+ list->ResizeL(iCount * sizeof(TCertificateListEntry));
+ TCertificateListEntry certInfo;
+
+ for(TInt i = iFirst; i < iLast; i++)
+ {
+ CMapDescriptor* mapping = (*iMapping)[i];
+ if(CertValidity(mapping->iStartTime, mapping->iEndTime) != EExpired)
+ {
+ certInfo.iObjectName = mapping->iObjectName;
+ certInfo.iOwnerType = mapping->iOwnerType;
+ if(mapping->iTrustedAuthority != NULL)
+ {
+ certInfo.iTrustedAuthority = *(mapping->iTrustedAuthority);
+ }
+ if(mapping->iIdentitySubjectName != NULL)
+ {
+ certInfo.iIdentitySubjectName = *(mapping->iIdentitySubjectName);
+ }
+ if(mapping->iSerialNumber != NULL)
+ {
+ certInfo.iSerialNumber = *(mapping->iSerialNumber);
+ }
+ certInfo.iSubjectKeyId = mapping->iSubjectKeyId;
+ certInfo.iKeySize = mapping->iKeySize; // Key size
+ certInfo.iKeyAlgorithm = mapping->iKeyAlgorithm; // RSA, DSA
+ certInfo.iIsDeletable = mapping->iIsDeletable; // IsDeletable
+
+ list->Write(pos * sizeof(TCertificateListEntry),
+ (TAny*)&certInfo,
+ sizeof(TCertificateListEntry));
+ pos++;
+ if(pos >= iCount)
+ {
+ break;
+ }
+ }
+ }
+ TPtr8 ptrList = list->Ptr(0);
+ aMessage.WriteL(0, ptrList);
+
+ CleanupStack::PopAndDestroy(1); // list
+ return KErrNone;
+}
+
+
+void CPKIMapper::GetApplicableCertListL(const RMessage2& aMessage, const RArray<TUid>& aUidArray)
+{
+ TBool uidMatch = EFalse;
+ TInt pos(0);
+
+ CBufFlat* list = CBufFlat::NewL(sizeof(TCertificateListEntry));
+ CleanupStack::PushL(list);
+ list->ResizeL(iCount * sizeof(TCertificateListEntry));
+ TCertificateListEntry certInfo;
+
+ for(TInt i = 0; (i < iMapping->Count()) && (pos < iCount); i++)
+ {
+ CMapDescriptor* mapping = (*iMapping)[i];
+ if(mapping->iOwnerType == EPKICACertificate)
+ {
+ if(CertValidity(mapping->iStartTime, mapping->iEndTime) != EExpired)
+ {
+ uidMatch = EFalse;
+ for(TInt j = 0; j < mapping->iApplUids.Count(); j++)
+ {
+ for(TInt k = 0; k < aUidArray.Count(); k++)
+ {
+ if(mapping->iApplUids[j].iUid == aUidArray[k].iUid)
+ {
+ uidMatch = ETrue;
+ break;
+ }
+ }
+ if(uidMatch)
+ {
+ certInfo.iObjectName = mapping->iObjectName;
+ certInfo.iOwnerType = mapping->iOwnerType;
+ if(mapping->iTrustedAuthority != NULL)
+ {
+ certInfo.iTrustedAuthority = *(mapping->iTrustedAuthority);
+ }
+ if(mapping->iIdentitySubjectName != NULL)
+ {
+ certInfo.iIdentitySubjectName = *(mapping->iIdentitySubjectName);
+ }
+ if(mapping->iSerialNumber != NULL)
+ {
+ certInfo.iSerialNumber = *(mapping->iSerialNumber);
+ }
+ certInfo.iSubjectKeyId = mapping->iSubjectKeyId;
+ certInfo.iKeySize = mapping->iKeySize; // Key size
+ certInfo.iKeyAlgorithm = mapping->iKeyAlgorithm; // RSA, DSA
+ certInfo.iIsDeletable = mapping->iIsDeletable; // IsDeletable
+
+ list->Write(pos * sizeof(TCertificateListEntry),
+ (TAny*)&certInfo,
+ sizeof(TCertificateListEntry));
+ pos++;
+ break;
+ }
+ }
+ }
+ }
+ }
+ TPtr8 ptrList = list->Ptr(0);
+ aMessage.WriteL(0, ptrList);
+
+ CleanupStack::PopAndDestroy(1); // list
+}
+
+
+
+CMapDescriptor& CPKIMapper::GetMapDescriptorAtIndex(TInt aIndex)
+{
+ PKISERVICE_ASSERT(aIndex < iMapping->Count());
+ return *(*iMapping)[aIndex];
+}
+
+
+void CPKIMapper::GetCertificateKeyIdL(TSecurityObjectDescriptor &aDescriptor, TPKIKeyIdentifier &aKeyId,
+ TPkiServiceStoreType aStoreType) const
+ {
+ LOG(Log::Printf(_L("-> CPKIMapper::GetCertificateKeyIdL"), aStoreType));
+ aKeyId.Zero();
+
+ TInt index;
+
+ TFileName* fileName = new (ELeave) TFileName;
+ CleanupDeletePushL(fileName);
+ fileName->Zero();
+
+ TInt status = ResolveCertMappingL(aDescriptor, *fileName, index, EFalse, aStoreType);
+
+ CleanupStack::PopAndDestroy(fileName);
+
+
+ if(status == KErrNone)
+ {
+ aKeyId.Copy((*iMapping)[index]->iSubjectKeyId);
+ }
+ else
+ {
+ LOG(Log::Printf(_L("ResolveKeyMapping: key NOT found\n")));
+ LogSearchArguments(aDescriptor);
+ }
+ LOG(Log::Printf(_L("<- CPKIMapper::GetCertificateKeyIdL"), aStoreType));
+ }
+
+/**
+ Check whether the given label is unique among all VPN certs.
+ @return True only if the given label doesn't exist
+*/
+TBool CPKIMapper::LabelIsUnique(const TDesC& aLabel) const
+ {
+ for (TInt i(0); i < iMapping->Count(); i++)
+ {
+ if ((*iMapping)[i]->iObjectName.Compare(aLabel) == 0)
+ {
+ return EFalse;
+ }
+ }
+ return ETrue;
+ }
+
+/**
+ Check whether the given certificate already exists among VPN certs.
+ @return True only if the given certificate does not exist in VPN's cert list.
+*/
+TBool CPKIMapper::CertificateIsUniqueL(const TDesC8& aCertData)
+ {
+ TBool ret(ETrue);
+
+ LOG(Log::Printf(_L("Verifying the uniqueness of certificate:")));
+
+ CX509Certificate* certificate = CX509Certificate::NewLC(aCertData);
+ const TPtrC8* issuername = certificate->DataElementEncoding(CX509Certificate::EIssuerName);
+ const TPtrC8* subjectname = certificate->DataElementEncoding(CX509Certificate::ESubjectName);
+
+ HBufC* issuerdispname = certificate->IssuerName().DisplayNameL();
+ CleanupStack::PushL(issuerdispname);
+ HBufC* subjectdispname = certificate->SubjectName().DisplayNameL();
+ CleanupStack::PushL(subjectdispname);
+
+ TInt count(iMapping->Count());
+
+ for (TInt i(0); i < count; i++)
+ {
+ CMapDescriptor* mapitem = (*iMapping)[i];
+
+ // Use subject name for uniqueness criterion
+ if (mapitem->iIdentitySubjectName)
+ {
+ if (subjectname->Compare(*(mapitem->iIdentitySubjectName)) == 0)
+ {
+ LOG(Log::Printf(_L("Found an existing cert that matches subject")));
+ if (issuername->Compare(*(mapitem->iTrustedAuthority)) == 0)
+ {
+ ret = EFalse;
+ break;
+ }
+ }
+ }
+ else if (mapitem->iTrustedAuthority && (subjectname->Compare(*issuername) == 0))
+ {
+ if (subjectname->Compare(*(mapitem->iTrustedAuthority)) == 0)
+ {
+ LOG(Log::Printf(_L("Found an existing cert that matches subject (CA)")));
+ ret = EFalse;
+ break;
+ }
+ }
+ }
+
+ CleanupStack::PopAndDestroy(3, certificate); // issuerdispname, subjectdispname
+
+ return ret;
+ }
+
+/**
+ Generates an unique label name for a certificate, based on its subject name.
+ @param1 The binary data describing the certificate
+ @param2 Return value for the generated unique name
+ @param3 Certificate owner type -- currently not supported.
+ @return none
+*/
+void CPKIMapper::GenerateUniqueNameL(
+ const TDesC8 &aCertData, TDes& aName,
+ TCertificateOwnerType /*aOwnerType*/ )
+ {
+ LOG(Log::Printf(_L("CPKIMapper::GenerateUniqueNameL() entry")));
+
+ CX509Certificate* certificate = CX509Certificate::NewLC(aCertData);
+
+ HBufC* baseline = certificate->SubjectName().DisplayNameL();
+ CleanupStack::PushL(baseline);
+ // +5 for (999) suffix
+ HBufC* variation = HBufC::NewLC(baseline->Length() + 5);
+ variation->Des().Append(*baseline);
+
+ if (baseline->Length() == 0)
+ {
+ TPtr ptr = variation->Des();
+ ptr.Format(_L("(1)"));
+ }
+
+ // See whether the initial label is already unique
+ TInt iter(2);
+ while (!LabelIsUnique(*variation))
+ {
+ // Iterate a new version of the label
+ if (iter > 999)
+ {
+ // too long name, just go with the previous.
+ break;
+ }
+ TPtr ptr = variation->Des();
+ ptr.Format(_L("%S(%d)"), &(*baseline), iter);
+ iter++;
+ }
+
+ // Sanity check for string lengths
+ aName = variation->Left(MAX_FILENAME_LENGTH);
+
+ CleanupStack::PopAndDestroy(3); //variation, baseline, certificate
+
+ LOG(Log::Printf(_L("CPKIMapper::GenerateUniqueNameL() exit")));
+ }
+
+TInt CPKIMapper::ResolveCertMappingL(TSecurityObjectDescriptor &aDescriptor, TDes16 &aFilename,
+ TInt &aIndex, const TBool aInfoOnly,
+ TPkiServiceStoreType aStoreType) const
+ {
+ TInt i;
+ TInt status = KErrNotFound;
+ TInt foundIndex = -1;
+ TTime furthestEndTime = TTime(0);
+
+ LOG(Log::Printf(_L("Resolving cert mapping, STORETYPE: %d\n"), aStoreType));
+
+ LOG(LogSearchArguments(aDescriptor));
+
+ // Scan available mappings
+ for(i = 0; i < iMapping->Count(); i++)
+ {
+ // Bypass entry in case that function leaves
+ // (issuer/subject name can be invalid)
+ CMapDescriptor* mapping = (*iMapping)[i];
+ if(mapping->IsMatchingL(aDescriptor, aInfoOnly, aStoreType))
+ {
+ // If we found a match, process it further
+ _LIT(KMidp2Label, "MIDP2");
+ TBuf<12> buf;
+ buf.Append(KMidp2Label);
+ // Discard all MIDP2 certificates to avoid label-mapping problem
+ if (buf.Compare(mapping->iObjectName) != 0)
+ {
+ if(mapping->iEndTime > furthestEndTime)
+ {
+ furthestEndTime = mapping->iEndTime;
+ foundIndex = i;
+ LOG(Log::Printf(_L("Resolve cert mapping: Tentatively found a suitable one")));
+ // Continue to search the longest lasting certificate
+ }
+ }
+ else
+ {
+ LOG(Log::Printf(_L("Found a cert, but it was a MIDP2 one - continuing search")));
+ }
+ }
+ }
+
+ if(foundIndex == -1)
+ {
+ LOG(Log::Printf(_L("Resolve cert mapping: No matching certificate found")));
+ status = KErrNotFound;
+ }
+ else
+ {
+ aFilename.Zero();
+ status = KErrNone;
+ if(status == KErrNone)
+ {
+ aFilename.Append((*iMapping)[foundIndex]->iObjectName);
+ status = KErrNone;
+ aIndex = foundIndex;
+ }
+ LOG(Log::Printf(_L("ResolveCertMapping: certificate found\n")));
+ LogSearchArguments(aDescriptor);
+ LOG(Log::Printf(_L("ResolveCertMapping: Object info\n")));
+ LogMap(*(*iMapping)[aIndex]);
+ }
+ return status;
+ }
+
+
+TValidity CPKIMapper::CertValidity(const TTime &aStartTime, const TTime &aEndTime)
+ {
+ TTimeIntervalSeconds tolerance(120);
+ TTime currentTime;
+ currentTime.UniversalTime();
+
+ if (aEndTime <= currentTime)
+ {
+ return EExpired;
+ }
+
+ if (aStartTime >= currentTime + tolerance)
+ {
+ return ENotValidYet;
+ }
+
+ return EValid;
+ }
+
+void CPKIMapper::LogSearchArguments(TSecurityObjectDescriptor &aDescriptor) const
+ {
+ TBuf<256> temp;
+ LOG(Log::Printf(_L("====Object Search arguments====\n")));
+ if(aDescriptor.iTrustedAuthorityUsed)
+ {
+ temp.Copy(aDescriptor.iTrustedAuthority);
+ if((aDescriptor.iTrustedAuthority[0] != 0x30)
+ || ((aDescriptor.iTrustedAuthority[1] != 0x81)
+ && (aDescriptor.iTrustedAuthority[1] != 0x82)
+ && ((aDescriptor.iTrustedAuthority[1] + 2) != aDescriptor.iTrustedAuthority.Length())))
+ {
+ LOG(Log::Printf(_L("Trusted authority: %S\n"), &temp));
+ }
+ else
+ {
+ LOG(Log::Printf(_L("Trusted authority:")));
+ LOG(Log::HexDump(NULL, NULL, aDescriptor.iTrustedAuthority.Ptr(), aDescriptor.iTrustedAuthority.Length()));
+ }
+ }
+ if(aDescriptor.iIdentitySubjectNameUsed)
+ {
+ temp.Copy(aDescriptor.iIdentitySubjectName);
+ if((aDescriptor.iIdentitySubjectName[0] != 0x30)
+ || ((aDescriptor.iIdentitySubjectName[1] != 0x81)
+ && (aDescriptor.iIdentitySubjectName[1] != 0x82)
+ && ((aDescriptor.iIdentitySubjectName[1] + 2) != aDescriptor.iIdentitySubjectName.Length())))
+ {
+ LOG(Log::Printf(_L("SubjectName: %S\n"), &temp));
+ }
+ else
+ {
+ LOG(Log::Printf(_L("SubjectName:")));
+ LOG(Log::HexDump(NULL, NULL, aDescriptor.iIdentitySubjectName.Ptr(), aDescriptor.iIdentitySubjectName.Length()));
+ }
+ }
+ if(aDescriptor.iIdentityRfc822NameUsed)
+ {
+ temp.Copy(aDescriptor.iIdentityRfc822Name);
+ LOG(Log::Printf(_L("Rfc822Name: %S\n"), &temp));
+ }
+ if(aDescriptor.iSerialNumberUsed)
+ {
+ LOG(Log::Printf(_L("SerialNumber:")));
+ LOG(Log::HexDump(NULL, NULL, aDescriptor.iSerialNumber.Ptr(), aDescriptor.iSerialNumber.Length()));
+ }
+ if(aDescriptor.iSubjectKeyIdUsed)
+ {
+ LOG(Log::Printf(_L("KeyId:")));
+ LOG(Log::HexDump(NULL, NULL, aDescriptor.iSubjectKeyId.Ptr(), aDescriptor.iSubjectKeyId.Length()));
+ }
+ if(aDescriptor.iOwnerTypeUsed)
+ {
+ LOG(Log::Printf(_L("OwnerType: %d\n"), aDescriptor.iOwnerType));
+ }
+ if(aDescriptor.iKeyUsageUsed)
+ {
+ LOG(Log::Printf(_L("KeyUsage:")));
+ LOG(Log::HexDump(NULL, NULL, aDescriptor.iKeyUsageDer.Ptr(), aDescriptor.iKeyUsageDer.Length()));
+ }
+ if(aDescriptor.iKeySizeUsed)
+ {
+ LOG(Log::Printf(_L("KeySize: %d\n"), aDescriptor.iKeySize));
+ }
+ if(aDescriptor.iKeyAlgorithmUsed)
+ {
+ LOG(Log::Printf(_L("KeyAlgorithm: %d\n"), aDescriptor.iKeyAlgorithm));
+ }
+ }
+
+TBool PkiUtil::MatchL(const CX500DistinguishedName& aDn1, const CX500DistinguishedName& aDn2)
+{
+ if((aDn1.Count() == 0) || (aDn2.Count() == 0))
+ {
+ return EFalse;
+ }
+
+ if (aDn1.Count() < aDn2.Count())
+ {
+ return EFalse;
+ }
+ else
+ {
+ // For each field in aDn2, aDn1 must contain a field with the same value
+ for (TInt i = 0; i < aDn2.Count(); i++)
+ {
+ if (!HasElementL(aDn1, aDn2.Element(i)))
+ {
+ return EFalse;
+ }
+ }
+ }
+
+ return ETrue;
+}
+
+TBool PkiUtil::HasElementL(const CX500DistinguishedName& aDn, const CX520AttributeTypeAndValue& aElement)
+{
+ for (TInt i = 0; i < aDn.Count(); i++)
+ {
+ if (aElement.ExactMatchL(aDn.Element(i)))
+ {
+ return ETrue;
+ }
+ }
+ return EFalse;
+}
+