installationservices/swi/source/sisregistry/server/sisrevocationmanager.cpp
changeset 0 ba25891c3a9e
child 25 7333d7932ef7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/installationservices/swi/source/sisregistry/server/sisrevocationmanager.cpp	Thu Dec 17 08:51:10 2009 +0200
@@ -0,0 +1,375 @@
+/*
+* Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "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: 
+*
+*/
+
+
+/**
+ @file 
+ @released
+ @internalTechnology
+*/
+
+#include "log.h"
+
+#include "securitymanager.h"
+#include "sistruststatus.h"
+#include "sisrevocationmanager.h"
+#include "sisregistryserversession.h"
+#include "sisinfo.h"
+#include "sisuid.h"
+#include "swi/msisuihandlers.h"
+
+_LIT(KMyModuleName, "_SISREVOCATION_MANAGER_");
+
+using namespace Swi;
+
+//
+// Life Cycle methods
+//
+
+EXPORT_C CSisRevocationManager* CSisRevocationManager::NewL(CSisRegistrySession& aSession)
+	{
+	CSisRevocationManager* self = CSisRevocationManager::NewLC(aSession);
+	CleanupStack::Pop(self);
+	return self;
+	}
+ 
+EXPORT_C CSisRevocationManager* CSisRevocationManager::NewLC(CSisRegistrySession& aSession)
+	{
+	CSisRevocationManager* self = new(ELeave) CSisRevocationManager(aSession);
+	CleanupStack::PushL(self);
+	return self;
+	}
+
+CSisRevocationManager::CSisRevocationManager(CSisRegistrySession& aSession) : 
+    CActive(EPriorityNormal),
+    iSession(&aSession)
+	{
+	CActiveScheduler::Add(this);	
+	}
+
+CSisRevocationManager::~CSisRevocationManager()
+	{
+	// Remove active object from active scheduler
+	Deque(); 
+	Cleanup();
+	}
+	
+//
+// Active Objects methods
+//
+
+void CSisRevocationManager::RunL()
+	{
+	DEBUG_PRINTF2(_L8("Sis Registry Server - CSisrevocationManager::RunL (State: %d.)"), iState);
+	
+	if (iStatus.Int() != KErrNone)
+		{
+		User::Leave(iStatus.Int());     // Hop into RunError()
+		}
+		
+	switch (iState)
+		{ 			
+		case EVerifyChains:
+			VerifcationRequestL();
+			break;
+			
+		case ERevocationCheck:
+			{
+			switch (iSignatureValidationResult)
+				{
+				case EValidationSucceeded:
+					PerformOcspRequestL();	
+					break;
+				default:
+					iState = ERevocationComplete;
+					// Self complete
+					TRequestStatus* status  = &iStatus;
+					User::RequestComplete(status, KErrNone);
+					SetActive();
+					break;
+				}	
+			}
+
+			break;
+			
+		case ERevocationComplete:
+			{
+			SetTrustStatusL();	
+			
+			// Complete the client
+			iMessage.Complete(KErrNone);	
+            Cleanup();	
+			}
+			break;
+			
+		default:
+			{
+			User::Panic(KMyModuleName, 1); 		
+			}
+		}
+	}
+
+void CSisRevocationManager::DoCancel()
+	{
+	DEBUG_PRINTF(_L8("Sis Registry Server - Cancelling Revocation Manager"));
+	
+	if (iSecurityManager)
+	    {
+		iSecurityManager->Cancel();
+		}
+	if (iState != EIdle)
+	    {
+	    iMessage.Complete(KErrCancel);
+	    iState = EIdle;	
+	    }
+	}
+
+TInt CSisRevocationManager::RunError(TInt aError)
+	{
+	DEBUG_PRINTF2(_L8("Sis Registry Server - Revocation Manager Failed with error code %d."), aError);
+	
+	iMessage.Complete(aError);	
+	Cleanup();
+	return KErrNone; 
+	}
+
+//
+// Business methods
+//	
+EXPORT_C void CSisRevocationManager::RevocationStatusRequestL(
+														HBufC8* aRawController,
+                                                        const Sis::CController* aController,
+                                                        TSisTrustStatus& aTrustStatus,
+                                                        const RArray<TInt>& aCertChainIndices, 
+													    const TDesC8& aOcspUri,
+														const RMessage2& aMessage)
+	{
+	__ASSERT_ALWAYS(!IsActive(), User::Panic(KMyModuleName, KErrInUse));
+	ASSERT(EIdle == iState);
+	
+	iStatus = KRequestPending;
+	iRawController = aRawController;
+	iController = aController;
+	iChains = aController->SignatureCertificateChains();	
+	iSecurityManager = CSecurityManager::NewL();	
+	
+	// Store caller's request status
+	iMessage = aMessage;
+
+	iState = EVerifyChains;
+		
+	iTrustStatus = aTrustStatus;
+	
+	iOcspUri = aOcspUri.AllocL();
+
+	// Make a copy of the cert chain indicies array
+	TInt count = aCertChainIndices.Count();
+	for (TInt index = 0; index < count; ++index)
+		{
+		iCertChainIndices.AppendL(aCertChainIndices[index]);
+		}
+	
+	// Self complete
+	TRequestStatus* status  = &iStatus;
+	User::RequestComplete(status, KErrNone);
+
+	SetActive();
+	}
+
+void CSisRevocationManager::VerifcationRequestL()
+	{
+	ASSERT(EVerifyChains == iState);
+	
+	// Get current controller data.
+	TPtrC8 data(iRawController->Mid(iController->DataOffset()));
+
+	iSecurityManager->ReverifyControllerL(data,
+										  *iController,
+										  iCertChainIndices,
+										  &iSignatureValidationResult,
+										  iValidationResultsOut,
+										  iEndCertificates,
+										  &iCapabilitySet,
+										  iAllowUnsigned,
+										  iStatus);	
+	
+	iState = ERevocationCheck;
+	SetActive();
+	}
+
+void CSisRevocationManager::PerformOcspRequestL()
+	{
+	iIap = 0;
+	iSecurityManager->PerformOcspL(iOcspUri->Des(),
+								   iIap,
+								   &iOcspMsg,
+								   iOcspOutcomeOut,
+								   iEndCertificates,
+								   iStatus);
+	iState = ERevocationComplete;
+	SetActive();
+	}
+	
+void CSisRevocationManager::SetTrustStatusL()
+	{		
+	TBool validated = EFalse;
+	
+	TValidationStatus validationStatus = EUnknown;
+	
+	switch (iSignatureValidationResult)
+		{	
+		case EValidationSucceeded:
+			validated = ETrue;
+			validationStatus = EValidatedToAnchor;
+			break;
+			
+		case ESignatureSelfSigned:
+			validated = ETrue;
+			validationStatus = EValidated;			
+			break;		
+
+		case ESignatureNotPresent:
+			validationStatus = EUnsigned;
+			break;	
+			
+        case ECertificateValidationError:
+		case ENoCertificate:
+		case ENoCodeSigningExtension:
+		case ENoSupportedPolicyExtension:
+		case ESignatureCouldNotBeValidated:
+		case EMandatorySignatureMissing:
+            validationStatus = EInvalid;
+			break;
+		default:
+			// BC break, unknown validation code, abort
+			User::Leave(KErrNotSupported);
+			break;			
+		}
+		
+	TRevocationStatus revocationStatus = EUnknown2;
+		
+	if (validated)
+		{
+	
+		for (TInt index = 0; index < iOcspOutcomeOut.Count(); index++)
+			{
+			if (iOcspOutcomeOut[index]->iResult == OCSP::EUnknown)
+				{	
+				switch (iOcspOutcomeOut[index]->iStatus)	
+					{	
+					case OCSP::ETransportError:
+					case OCSP::EInvalidURI:
+					case OCSP::EServerInternalError:
+					case OCSP::ETryLater:
+					case OCSP::EMissingCertificates:
+					case OCSP::EResponseSignatureValidationFailure:
+						// Possibly transient error, may retry.
+						revocationStatus = EOcspTransient;
+						break;
+		
+					case OCSP::EClientInternalError:
+					case OCSP::ENoServerSpecified:
+					case OCSP::EMalformedResponse:
+					case OCSP::EUnknownResponseType:
+					case OCSP::EUnknownCriticalExtension:
+					case OCSP::ESignatureRequired:
+					case OCSP::EClientUnauthorised:
+					case OCSP::EThisUpdateTooLate:
+					case OCSP::EThisUpdateTooEarly:
+					case OCSP::ENextUpdateTooEarly:
+					case OCSP::ECertificateNotValidAtValidationTime:
+					case OCSP::ENonceMismatch:	
+					case OCSP::EMissingNonce:		
+					case OCSP::EMalformedRequest:
+						// This is a permanent error, unable to retry.
+						revocationStatus = EOcspUnknown;
+						break;
+		
+					case OCSP::EValid:
+                        revocationStatus = EOcspUnknown;
+						break;
+
+						// not a valid status for this state
+					default:
+						// Unknown value, must be a BC break!
+						User::Leave(KErrNotSupported);
+						break;			
+					}	
+					
+				break;
+				}
+			else if (iOcspOutcomeOut[index]->iResult == OCSP::ERevoked)
+				{
+				revocationStatus = EOcspRevoked;
+				break;		
+				}
+			else 
+				{
+				// OCSP of chain is good
+				revocationStatus = EOcspGood;
+				}	
+			}
+		}
+	else // not validated
+		{	
+		revocationStatus = EOcspNotPerformed;
+		}	
+
+	
+	// set trust status		
+	TTime time;
+	time.UniversalTime();
+	iTrustStatus.SetLastCheckDate(time);
+	
+	iTrustStatus.SetValidationStatus(validationStatus);		
+	iTrustStatus.SetRevocationStatus(revocationStatus);
+	if (validated 
+	    && (revocationStatus == EOcspGood 
+	        || revocationStatus == EOcspUnknown 
+	        || revocationStatus == EOcspRevoked ))
+		{
+		iTrustStatus.SetResultDate(iTrustStatus.LastCheckDate());
+		}
+
+	iSession->UpdateTrustStatusL(iController->Info().Uid().Uid(),
+	                            iTrustStatus);
+	}
+
+void CSisRevocationManager::Cleanup()
+	{
+    iState = EIdle;
+	
+    delete iController;
+	iController = 0;
+	
+    delete iRawController;
+	iRawController = 0;
+        
+	iEndCertificates.ResetAndDestroy();			
+    
+    iOcspOutcomeOut.ResetAndDestroy();
+    
+    iValidationResultsOut.ResetAndDestroy();	
+
+    iCertChainIndices.Close();
+
+    delete iOcspUri;
+    iOcspUri = 0;
+
+    delete iSecurityManager;
+	iSecurityManager = 0;
+	}