--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pkiutilities/DeviceToken/Src/Certstore/server/DevandTruSrvCertStoreServer.cpp Tue Jan 26 15:20:08 2010 +0200
@@ -0,0 +1,684 @@
+/*
+* Copyright (c) 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: Implementation of DevandTruSrvCertStoreServer
+*
+*/
+
+
+#include <ccertattributefilter.h>
+#include <signed.h>
+#include <x509cert.h>
+#include <x509certext.h>
+#include <x509keys.h>
+#include <wtlscert.h>
+#include <x500dn.h>
+#include "DevandTruSrvCertStoreServer.h"
+#include "DevandTruSrvCertStoreConduit.h"
+#include "DevandTruSrvCertStoreSession.h"
+#include "DevandTruSrvCertStoreEntry.h"
+#include "DevandTruSrvCertStoreEntryList.h"
+#include "DevTokenCliServ.h"
+#include "DevTokenUtil.h"
+#include "DevTokenDataTypes.h"
+#include "TrustedSitesServer.h"
+
+_LIT(KCertStoreFilename,"devandtrusrvcerts.dat");
+
+const TInt KSHA1Length = 20;
+
+// API policing
+_LIT_SECURITY_POLICY_PASS(KPolicyAlwaysPass);
+_LIT_SECURITY_POLICY_FAIL(KPolicyAlwaysFail);
+_LIT_SECURITY_POLICY_C1(KPolicyRequireReadUserData, ECapabilityReadUserData);
+_LIT_SECURITY_POLICY_C1(KPolicyRequireWriteDeviceData, ECapabilityWriteDeviceData);
+
+// ======== MEMBER FUNCTIONS ========
+
+//CDevandTruSrvCertStoreServer
+
+// ---------------------------------------------------------------------------
+// CDevandTruSrvCertStoreServer::NewL()
+// ---------------------------------------------------------------------------
+//
+CDevandTruSrvCertStoreServer* CDevandTruSrvCertStoreServer::NewL(CTrustedSitesServer* aTrustedSitesServer )
+ {
+ CDevandTruSrvCertStoreServer* self = new (ELeave) CDevandTruSrvCertStoreServer( aTrustedSitesServer );
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevandTruSrvCertStoreServer::CDevandTruSrvCertStoreServer()
+// ---------------------------------------------------------------------------
+//
+CDevandTruSrvCertStoreServer::CDevandTruSrvCertStoreServer( CTrustedSitesServer* aTrustedSitesServer )
+: iTrustedSitesServer( aTrustedSitesServer )
+ {
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevandTruSrvCertStoreServer::ConstructL()
+// ---------------------------------------------------------------------------
+//
+void CDevandTruSrvCertStoreServer::ConstructL()
+ {
+ iConduit = CDevandTruSrvCertStoreConduit::NewL(*this);
+ User::LeaveIfError(iFs.Connect());
+ OpenStoreL();
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevandTruSrvCertStoreServer::~CDevandTruSrvCertStoreServer()
+// ---------------------------------------------------------------------------
+//
+CDevandTruSrvCertStoreServer::~CDevandTruSrvCertStoreServer()
+ {
+ delete iStore;
+ delete iEntryList;
+ delete iConduit;
+ iFs.Close();
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevandTruSrvCertStoreServer::CreateSessionL()
+// ---------------------------------------------------------------------------
+//
+CDevandTruSrvCertStoreSession* CDevandTruSrvCertStoreServer::CreateSessionL()
+ {
+ return CDevandTruSrvCertStoreSession::NewL(*iConduit);
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevandTruSrvCertStoreServer::ListPolicy()
+// ---------------------------------------------------------------------------
+//
+const TSecurityPolicy& CDevandTruSrvCertStoreServer::ListPolicy(TCertificateOwnerType aOwnerType) const
+ {
+ switch (aOwnerType)
+ {
+ case EUserCertificate:
+ return KPolicyAlwaysPass;
+ case EPeerCertificate:
+ return KPolicyRequireReadUserData;
+
+ default:
+ return KPolicyAlwaysFail;
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevandTruSrvCertStoreServer::AddRemovePolicy()
+// ---------------------------------------------------------------------------
+//
+const TSecurityPolicy& CDevandTruSrvCertStoreServer::AddRemovePolicy(TCertificateOwnerType aOwnerType) const
+ {
+ switch (aOwnerType)
+ {
+ case EUserCertificate:
+ case EPeerCertificate:
+ return KPolicyRequireWriteDeviceData;
+
+ default:
+ return KPolicyAlwaysFail;
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevandTruSrvCertStoreServer::RetrievePolicy()
+// ---------------------------------------------------------------------------
+//
+const TSecurityPolicy& CDevandTruSrvCertStoreServer::RetrievePolicy(TCertificateOwnerType aOwnerType) const
+ {
+ switch (aOwnerType)
+ {
+ case EUserCertificate:
+ case EPeerCertificate:
+ return KPolicyRequireReadUserData;
+
+ default:
+ return KPolicyAlwaysFail;
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevandTruSrvCertStoreServer::WriteTrustSettingsPolicy()
+// ---------------------------------------------------------------------------
+//
+const TSecurityPolicy& CDevandTruSrvCertStoreServer::WriteTrustSettingsPolicy() const
+ {
+ return KPolicyRequireWriteDeviceData;
+ }
+
+
+// Read-only interface
+
+// ---------------------------------------------------------------------------
+// CDevandTruSrvCertStoreServer::ListL()
+// ---------------------------------------------------------------------------
+//
+void CDevandTruSrvCertStoreServer::ListL(const CCertAttributeFilter& aFilter,
+ RPointerArray<CDevTokenCertInfo>& aCertsOut,
+ const RMessage2& aMessage, TBool aFromTruSiteSrv ) const
+ {
+
+ // check that if KeyUsage is set, only User certificates are requested
+ if (aFilter.iKeyUsage != EX509UsageAll &&
+ (!aFilter.iOwnerTypeIsSet || aFilter.iOwnerType != EUserCertificate))
+ {
+ User::Leave(KErrArgument);
+ }
+
+ // API policing
+ if (!aFromTruSiteSrv)
+ {
+ if (!ListPolicy( aFilter.iOwnerType ).CheckPolicy(aMessage))
+ {
+ User::Leave(KErrPermissionDenied);
+ }
+ }
+
+ TInt count = iEntryList->Count();
+ for (TInt index = 0; index < count; index++)
+ {
+ const CDevandTruSrvCertStoreEntry& entry = iEntryList->GetByIndex(index);
+
+ if (CertEntryMatchesFilter(aFilter, entry))
+ {
+ User::LeaveIfError(aCertsOut.Append(&entry.CertInfo()));
+ }
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevandTruSrvCertStoreServer::CertEntryMatchesFilter()
+// ---------------------------------------------------------------------------
+//
+TBool CDevandTruSrvCertStoreServer::CertEntryMatchesFilter(const CCertAttributeFilter& aFilter,
+ const CDevandTruSrvCertStoreEntry& aEntry) const
+ {
+ if (aFilter.iUidIsSet && !aEntry.IsApplicable(aFilter.iUid))
+ {
+ return EFalse;
+ }
+
+ const CDevTokenCertInfo& certInfo = aEntry.CertInfo();
+
+ if (aFilter.iFormatIsSet && aFilter.iFormat != certInfo.CertificateFormat())
+ {
+ return EFalse;
+ }
+
+ if (aFilter.iOwnerTypeIsSet && aFilter.iOwnerType != certInfo.CertificateOwnerType())
+ {
+ return EFalse;
+ }
+
+ if (aFilter.iSubjectKeyIdIsSet && aFilter.iSubjectKeyId != certInfo.SubjectKeyId())
+ {
+ return EFalse;
+ }
+
+ if (aFilter.iLabelIsSet && aFilter.iLabel != certInfo.Label())
+ {
+ return EFalse;
+ }
+
+ return ETrue;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevandTruSrvCertStoreServer::GetCertL()
+// ---------------------------------------------------------------------------
+//
+const CDevTokenCertInfo& CDevandTruSrvCertStoreServer::GetCertL(TInt aHandle) const
+ {
+ // Leaves if not found
+ return iEntryList->GetByHandleL(aHandle).CertInfo();
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevandTruSrvCertStoreServer::ApplicationsL()
+// ---------------------------------------------------------------------------
+//
+const RArray<TUid>& CDevandTruSrvCertStoreServer::ApplicationsL(TInt aHandle) const
+ {
+ return iEntryList->GetByHandleL(aHandle).CertificateApps();
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevandTruSrvCertStoreServer::IsApplicableL()
+// ---------------------------------------------------------------------------
+//
+TBool CDevandTruSrvCertStoreServer::IsApplicableL(TInt aHandle, TUid aApplication) const
+ {
+ return iEntryList->GetByHandleL(aHandle).IsApplicable(aApplication);
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevandTruSrvCertStoreServer::TrustedL()
+// ---------------------------------------------------------------------------
+//
+TBool CDevandTruSrvCertStoreServer::TrustedL(TInt aHandle) const
+ {
+ return iEntryList->GetByHandleL(aHandle).Trusted();
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevandTruSrvCertStoreServer::RetrieveLC()
+// ---------------------------------------------------------------------------
+//
+HBufC8* CDevandTruSrvCertStoreServer::RetrieveLC(TInt aHandle, const RMessage2& aMessage, TBool aFromTruSiteSrv) const
+ {
+ const CDevandTruSrvCertStoreEntry& entry = iEntryList->GetByHandleL(aHandle);
+
+ // API policing
+ if ( !aFromTruSiteSrv )
+ {
+ if (!RetrievePolicy(entry.CertInfo().CertificateOwnerType()).CheckPolicy(aMessage))
+ {
+ User::Leave( KErrPermissionDenied );
+ }
+ }
+
+ TInt size = entry.CertInfo().Size();
+ HBufC8* buf = HBufC8::NewMaxLC(size);
+ TPtr8 ptr = buf->Des();
+ ptr.FillZ();
+
+ RStoreReadStream stream;
+ stream.OpenLC(*iStore, entry.DataStreamId());
+ stream.ReadL(ptr, size);
+ CleanupStack::PopAndDestroy(&stream);
+
+ return buf;
+ }
+
+
+// Writable interface
+
+// ---------------------------------------------------------------------------
+// CDevandTruSrvCertStoreServer::AddL()
+// ---------------------------------------------------------------------------
+//
+void CDevandTruSrvCertStoreServer::AddL(const TDevTokenAddCertDataStruct& aInfo,
+ const TDesC8& aCert,
+ const RMessage2& aMessage, TBool aFromTruSiteSrv )
+ {
+ // Check if a certificate with this name already exists
+ if (iEntryList->LabelExists(aInfo.iLabel))
+ {
+ User::Leave(KErrBadName);
+ }
+
+ // Check subject key id and cert data are supplied, issuer key id is optional
+ if (aInfo.iSubjectKeyId == KNullDesC8 || aCert == KNullDesC8)
+ {
+ User::Leave(KErrArgument);
+ }
+
+ // Create cert entry (this sanity checks the rest of the arguments)
+ CDevTokenCertInfo* certInfo = CDevTokenCertInfo::NewLC(
+ aInfo.iLabel,
+ aInfo.iFormat,
+ aInfo.iCertificateOwnerType,
+ aCert.Length(),
+ &aInfo.iSubjectKeyId,
+ &aInfo.iIssuerKeyId,
+ iEntryList->NextFreeHandle(),
+ aInfo.iDeletable);
+
+ // API policing
+ if ( !aFromTruSiteSrv )
+ {
+ if (!AddRemovePolicy(aInfo.iCertificateOwnerType).CheckPolicy(aMessage))
+ {
+ User::Leave(KErrPermissionDenied);
+ }
+ }
+
+ CompactStoreL();
+
+ TRAPD(err, DoAddL(*certInfo, aCert));
+ CleanupStack::PopAndDestroy(certInfo);
+
+ if (err != KErrNone)
+ {
+ iStore->Revert();
+ User::Leave(err);
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevandTruSrvCertStoreServer::DoAddL()
+// ---------------------------------------------------------------------------
+//
+void CDevandTruSrvCertStoreServer::DoAddL(const CDevTokenCertInfo& aCertInfo, const TDesC8& aCertData)
+ {
+ TStreamId dataStreamId = WriteCertDataStreamL(aCertData);
+
+ RArray<TUid> initialApps;
+ CleanupClosePushL(initialApps);
+
+ CDevandTruSrvCertStoreEntry* entry = CDevandTruSrvCertStoreEntry::NewL(
+ aCertInfo,
+ initialApps,
+ EFalse,
+ dataStreamId);
+ CleanupStack::PopAndDestroy(&initialApps);
+ CleanupStack::PushL(entry);
+
+ TInt index = iEntryList->AppendL(entry);
+ CleanupStack::Pop(entry); // iEntryList has taken ownership
+
+ TRAPD(err, UpdateStoreL());
+ if ( (err == KErrNone) && (aCertInfo.CertificateOwnerType() == EPeerCertificate ))
+ {
+ CX509Certificate* cert = CX509Certificate::NewLC( aCertData );
+ TBuf8<KSHA1Length> certHash;
+ certHash.Copy(cert->Fingerprint());
+
+
+ const CX500DistinguishedName& dName = cert->SubjectName();
+ // Retrieve CN
+ HBufC* cn = dName.ExtractFieldL( KX520CommonName );
+ CleanupStack::PushL(cn);
+ iTrustedSitesServer->AddL( certHash, *cn );
+
+ CleanupStack::PopAndDestroy( 2 );//cert, cn
+ }
+ if (err != KErrNone)
+ {
+ iEntryList->Remove(index);
+ delete entry;
+ User::Leave(err);
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevandTruSrvCertStoreServer::WriteCertDataStreamL()
+// ---------------------------------------------------------------------------
+//
+TStreamId CDevandTruSrvCertStoreServer::WriteCertDataStreamL(const TDesC8& aData)
+ {
+ RStoreWriteStream stream;
+ TStreamId streamId = stream.CreateLC(*iStore);
+ stream.WriteL(aData);
+ stream.CommitL();
+ CleanupStack::PopAndDestroy(&stream);
+ return streamId;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevandTruSrvCertStoreServer::RemoveL()
+// ---------------------------------------------------------------------------
+//
+void CDevandTruSrvCertStoreServer::RemoveL(TInt aHandle, const RMessage2& aMessage, TBool aFromTruSiteSrv)
+ {
+ TInt index = iEntryList->IndexForHandle(aHandle);
+ User::LeaveIfError(index);
+
+ // API policing
+ const CDevandTruSrvCertStoreEntry& entry = iEntryList->GetByIndex(index);
+ if (!aFromTruSiteSrv)
+ {
+ if (!AddRemovePolicy(entry.CertInfo().CertificateOwnerType()).CheckPolicy(aMessage))
+ {
+ User::Leave(KErrPermissionDenied);
+ }
+ }
+
+ CompactStoreL();
+
+ CDevandTruSrvCertStoreEntry* oldEntry = iEntryList->Remove(index);
+ TRAPD(err, UpdateStoreL());
+ if (err == KErrNone)
+ {
+ // If trusted site certificate is removed, the corresponding records
+ // in trusted site store should also be removed to stop trusting.
+ if( oldEntry->CertInfo().CertificateOwnerType() == EPeerCertificate )
+ {
+ TInt size = oldEntry->CertInfo().Size();
+ HBufC8* buf = HBufC8::NewMaxLC(size);
+ TPtr8 ptr = buf->Des();
+ ptr.FillZ();
+
+ RStoreReadStream stream;
+ stream.OpenLC(*iStore, oldEntry->DataStreamId());
+ stream.ReadL(ptr, size);
+ CleanupStack::PopAndDestroy(&stream);
+
+
+ CX509Certificate* cert = CX509Certificate::NewLC(*buf);
+ TBuf8<KSHA1Length> certHash;
+ certHash.Copy(cert->Fingerprint());
+
+ iTrustedSitesServer->RemoveL( certHash );
+
+ CleanupStack::PopAndDestroy( 2 );//buf, cert
+ }
+ delete oldEntry;
+ }
+ else
+ {
+ iStore->Revert();
+ // This will always succeed because we just did a remove
+ iEntryList->AppendL(oldEntry);
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevandTruSrvCertStoreServer::SetApplicabilityL()
+// ---------------------------------------------------------------------------
+//
+void CDevandTruSrvCertStoreServer::SetApplicabilityL(TInt /*aHandle*/,
+ const RArray<TUid>& /*aApps*/,
+ const RMessage2& aMessage)
+ {
+ // Setting Applicability is meant for CA certificate only.
+ // in DevandTruSrvCertStore, we only store Personal ceritificate(Device Cert )
+ // and Peer certificate( trust server cert ).
+
+ aMessage.Complete( KErrNotSupported );
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevandTruSrvCertStoreServer::SetTrustL()
+// ---------------------------------------------------------------------------
+//
+void CDevandTruSrvCertStoreServer::SetTrustL(TInt /*aHandle*/,
+ TBool /*aTrusted*/,
+ const RMessage2& aMessage)
+ {
+ // Setting Trust is meant for CA certificate only.
+ // in DevandTruSrvCertStore, we only store Personal ceritificate(Device Cert )
+ // and Peer certificate( trust server cert ).
+
+ aMessage.Complete( KErrNotSupported );
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevandTruSrvCertStoreServer::UpdateStoreL()
+// ---------------------------------------------------------------------------
+//
+void CDevandTruSrvCertStoreServer::UpdateStoreL()
+ {
+ RStoreWriteStream stream;
+ stream.ReplaceLC(*iStore, iStreamId);
+ stream << *iEntryList;
+ stream.CommitL();
+ CleanupStack::PopAndDestroy(&stream);
+
+ iStore->CommitL();
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevandTruSrvCertStoreServer::CompactStoreL()
+// ---------------------------------------------------------------------------
+//
+void CDevandTruSrvCertStoreServer::CompactStoreL()
+ {
+ iStore->ReclaimL();
+ iStore->CompactL();
+ iStore->CommitL();
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevandTruSrvCertStoreServer::RestoreL()
+// ---------------------------------------------------------------------------
+//
+void CDevandTruSrvCertStoreServer::RestoreL(const TDesC& aFilename)
+ {
+ // Make sure the store is not read-only
+ User::LeaveIfError(iFs.SetAtt(aFilename, KEntryAttNormal, KEntryAttReadOnly));
+
+ // Open the store
+ RFile file;
+ User::LeaveIfError(file.Open(iFs, aFilename, EFileRead | EFileWrite));
+ CleanupClosePushL(file);
+ CPermanentFileStore* store = CPermanentFileStore::FromL(file);
+ CleanupStack::Pop(&file); // now owned by store
+ CleanupStack::PushL(store);
+
+ // Read id of cert list stream
+ TStreamId caCertEntryStreamId;
+ RStoreReadStream stream;
+ stream.OpenLC(*store, store->Root());
+ stream >> iStreamId;
+ CleanupStack::PopAndDestroy(&stream);
+
+ // Read the certificate list
+ RStoreReadStream caCertEntryStream;
+ caCertEntryStream.OpenLC(*store, iStreamId);
+ iEntryList = CDevandTruSrvCertStoreEntryList::NewL(caCertEntryStream);
+ CleanupStack::PopAndDestroy(&caCertEntryStream);
+
+ assert(!iStore, EPanicCertStoreRestoreState);
+ iStore = store;
+ CleanupStack::Pop(store);
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevandTruSrvCertStoreServer::OpenStoreL()
+// ---------------------------------------------------------------------------
+//
+void CDevandTruSrvCertStoreServer::OpenStoreL()
+ {
+ TBuf<KMaxFilenameLength> filename;
+ FileUtils::MakePrivateFilenameL(iFs, KCertStoreFilename, filename);
+
+ TRAPD(err, RestoreL(filename));
+
+ if (err == KErrNoMemory || err == KErrInUse)
+ {
+ User::Leave(err);
+ }
+
+ if (err != KErrNone)
+ {
+ // Couldn't open RAM based store, copy from ROM
+
+ FileUtils::EnsurePathL(iFs, filename);
+
+ TBuf<KMaxFilenameLength> romFilename;
+ FileUtils::MakePrivateROMFilenameL(iFs, KCertStoreFilename, romFilename);
+
+ if (FileUtils::ExistsL(iFs, romFilename))
+ {
+ FileUtils::CopyL(iFs, romFilename, filename);
+ }
+ else
+ {
+ CreateStoreFileL(filename);
+ }
+
+ // Retry open, and leave on failure
+ RestoreL(filename);
+ }
+
+ assert(iStore, EPanicCertStoreOpenState);
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevandTruSrvCertStoreServer::CreateStoreFileL()
+// ---------------------------------------------------------------------------
+//
+void CDevandTruSrvCertStoreServer::CreateStoreFileL(const TDesC& aFile)
+ {
+ TRAPD(err, DoCreateStoreFileL(aFile));
+ if (err != KErrNone)
+ {
+ // Attempt to delete file, but don't complain if it fails
+ iFs.Delete(aFile);
+ User::Leave(err);
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevandTruSrvCertStoreServer::DoCreateStoreFileL()
+// ---------------------------------------------------------------------------
+//
+void CDevandTruSrvCertStoreServer::DoCreateStoreFileL(const TDesC& aFile)
+ {
+ CPermanentFileStore* fileStore = CPermanentFileStore::ReplaceLC(iFs, aFile, EFileRead | EFileWrite | EFileShareExclusive);
+ fileStore->SetTypeL(KPermanentFileStoreLayoutUid);
+
+ // Create info stream
+ CDevandTruSrvCertStoreEntryList* emptyCertList = CDevandTruSrvCertStoreEntryList::NewLC();
+ RStoreWriteStream infoStream;
+ TStreamId streamId = infoStream.CreateLC(*fileStore);
+ infoStream << *emptyCertList;
+ infoStream.CommitL();
+ CleanupStack::PopAndDestroy(2, emptyCertList);
+
+ // Create root stream - just contains id of info stream
+ RStoreWriteStream rootStream;
+ TStreamId rootStreamId = rootStream.CreateLC(*fileStore);
+ fileStore->SetRootL(rootStreamId);
+ rootStream << streamId;
+ rootStream.CommitL();
+ CleanupStack::PopAndDestroy(&rootStream);
+
+ fileStore->CommitL();
+ CleanupStack::PopAndDestroy(fileStore);
+ }
+
+//EOF
+