--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pkiutilities/securitydialognotifiersrv/src/securitydialogoperserverauthfail.cpp Fri Aug 20 11:27:50 2010 +0300
@@ -0,0 +1,498 @@
+/*
+* Copyright (c) 2010 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: Server authentication failure operation in security dialog
+*
+*/
+
+#include "securitydialogoperserverauthfail.h" // CServerAuthFailOperation
+#include "securitydialogoperationobserver.h" // MSecurityDialogOperationObserver
+#include "untrustedcertquery.h" // CUntrustedCertQuery
+#include "../../DeviceToken/Inc/TrustedSitesStore.h" // CTrustSitesStore
+#include <mctwritablecertstore.h> // MCTWritableCertStore
+#include <unifiedcertstore.h> // CUnifiedCertStore
+#include <cctcertinfo.h> // CCTCertInfo
+#include <x509cert.h> // CX509Certificate
+#include "securitydialogstrace.h" // TRACE macro
+
+const TUid KTrustedSiteCertificatesTokenTypeUid = { 0x101FB66F };
+const TInt KMaxCommonNameLength = 64; // from RFC3280
+
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// CServerAuthFailOperation::NewL()
+// ---------------------------------------------------------------------------
+//
+CServerAuthFailOperation* CServerAuthFailOperation::NewL(
+ MSecurityDialogOperationObserver& aObserver, const RMessage2& aMessage,
+ TInt aReplySlot )
+ {
+ TRACE( "CServerAuthFailOperation::NewL, aMessage 0x%08x", aMessage.Handle() );
+ return new( ELeave ) CServerAuthFailOperation( aObserver, aMessage, aReplySlot );
+ }
+
+// ---------------------------------------------------------------------------
+// CServerAuthFailOperation::~CServerAuthFailOperation()
+// ---------------------------------------------------------------------------
+//
+CServerAuthFailOperation::~CServerAuthFailOperation()
+ {
+ TRACE( "CServerAuthFailOperation::~CServerAuthFailOperation, begin" );
+ Cancel();
+
+ delete iUntrustedCertQuery;
+ iUntrustedCertQuery = NULL;
+
+ delete iInput;
+ iInput = NULL;
+ delete iCertLabel;
+ iCertLabel = NULL;
+ delete iServerName;
+ iServerName = NULL;
+
+ delete iCertStore;
+ iCertStore = NULL;
+ iTrustedSiteCertStore = NULL; // not owned
+
+ delete iCertAttributeFilter;
+ iCertAttributeFilter = NULL;
+ delete iRetrievedCertBuffer;
+ iRetrievedCertBuffer = NULL;
+
+ iCertInfos.Close();
+ iFs.Close();
+ TRACE( "CServerAuthFailOperation::~CServerAuthFailOperation, end" );
+ }
+
+// ---------------------------------------------------------------------------
+// CServerAuthFailOperation::StartL()
+// ---------------------------------------------------------------------------
+//
+void CServerAuthFailOperation::StartL( const TDesC8& aBuffer )
+ {
+ TRACE( "CServerAuthFailOperation::StartL, begin" );
+ __ASSERT_DEBUG( iInput == NULL, User::Invariant() );
+ iInput = CServerAuthenticationFailureInput::NewL( aBuffer );
+
+ iInput->GetEncodedCert( iEncodedServerCert );
+
+ TPtrC8 serverName;
+ iInput->GetServerName( serverName );
+ __ASSERT_DEBUG( iServerName == NULL, User::Invariant() );
+ iServerName = HBufC::NewL( serverName.Length() );
+ iServerName->Des().Copy( serverName );
+ TRACE( "CServerAuthFailOperation::StartL, iServerName=%S", iServerName );
+
+ iAuthFailReason = iInput->FailureReason();
+ TRACE( "CServerAuthFailOperation::StartL, iAuthFailReason=%d", iAuthFailReason );
+
+ InitializeUnifiedCertStoreL();
+ // This is async function, processing continues in RunL().
+ // Basically trusted site certificates are fetched and the
+ // server certificate is compared to them. If the server
+ // certificate is already in trusted site cert store, then
+ // connection is accepted silently. If it is not, then
+ // untrusted certificate dialog is displayed.
+ }
+
+// ---------------------------------------------------------------------------
+// CServerAuthFailOperation::CancelOperation()
+// ---------------------------------------------------------------------------
+//
+void CServerAuthFailOperation::CancelOperation()
+ {
+ TRACE( "CServerAuthFailOperation::CancelOperation, begin" );
+ Cancel();
+ if( iUntrustedCertQuery )
+ {
+ TRACE( "CServerAuthFailOperation::CancelOperation, cancelling untrusted query" );
+ iUntrustedCertQuery->Cancel();
+ }
+ if( !iMessage.IsNull() )
+ {
+ TRACE( "CServerAuthFailOperation::CancelOperation, completing message 0x%08x",
+ iMessage.Handle() );
+ iMessage.Complete( KErrCancel );
+ }
+ TRACE( "CServerAuthFailOperation::CancelOperation, end" );
+ }
+
+// ---------------------------------------------------------------------------
+// CServerAuthFailOperation::RunL()
+// ---------------------------------------------------------------------------
+//
+void CServerAuthFailOperation::RunL()
+ {
+ TRACE( "CServerAuthFailOperation::RunL, iStatus.Int()=%d, iMode=%d",
+ iStatus.Int(), iMode );
+ User::LeaveIfError( iStatus.Int() );
+ switch( iMode )
+ {
+ case EInitialiseCertStore:
+ ProcessServerAuthorizationFailureL();
+ break;
+ case EListTrustedSiteCerts:
+ RetrieveFirstTrustedSiteCertL();
+ break;
+ case ERetrieveTrustedSiteCert:
+ if( IsRetrievedCertSameAsServerCertL() )
+ {
+ ReturnResultL( EContinue );
+ }
+ else
+ {
+ RetrieveNextTrustedSiteCertL();
+ }
+ break;
+ case ESavingServerCert:
+ SaveServerNameToTrustedSitesStoreL();
+ ReturnResultL( EContinue );
+ break;
+ default:
+ User::Leave( KErrGeneral );
+ break;
+ }
+ TRACE( "CServerAuthFailOperation::RunL(), end" );
+ }
+
+// ---------------------------------------------------------------------------
+// CServerAuthFailOperation::DoCancel()
+// ---------------------------------------------------------------------------
+//
+void CServerAuthFailOperation::DoCancel()
+ {
+ TRACE( "CServerAuthFailOperation::DoCancel, iMode=%d", iMode );
+ switch( iMode )
+ {
+ case EInitialiseCertStore:
+ if( iCertStore )
+ {
+ iCertStore->CancelInitialize();
+ }
+ break;
+ case EListTrustedSiteCerts:
+ if( iTrustedSiteCertStore )
+ {
+ iTrustedSiteCertStore->CancelList();
+ }
+ break;
+ case ERetrieveTrustedSiteCert:
+ if( iTrustedSiteCertStore )
+ {
+ iTrustedSiteCertStore->CancelRetrieve();
+ }
+ break;
+ case ESavingServerCert:
+ if( iTrustedSiteCertStore )
+ {
+ iTrustedSiteCertStore->CancelAdd();
+ }
+ break;
+ default:
+ break;
+ }
+ TRACE( "CServerAuthFailOperation::DoCancel, end" );
+ }
+
+// ---------------------------------------------------------------------------
+// CServerAuthFailOperation::CServerAuthFailOperation()
+// ---------------------------------------------------------------------------
+//
+CServerAuthFailOperation::CServerAuthFailOperation(
+ MSecurityDialogOperationObserver& aObserver, const RMessage2& aMessage,
+ TInt aReplySlot ) : CSecurityDialogOperation( aObserver, aMessage, aReplySlot )
+ {
+ TRACE( "CServerAuthFailOperation::CServerAuthFailOperation" );
+ }
+
+// ---------------------------------------------------------------------------
+// CServerAuthFailOperation::InitializeUnifiedCertStoreL()
+// ---------------------------------------------------------------------------
+//
+void CServerAuthFailOperation::InitializeUnifiedCertStoreL()
+ {
+ TRACE( "CServerAuthFailOperation::InitializeUnifiedCertStoreL" );
+ User::LeaveIfError( iFs.Connect() );
+ iCertStore = CUnifiedCertStore::NewL( iFs, ETrue );
+
+ iCertStore->Initialize( iStatus );
+ iMode = EInitialiseCertStore;
+ SetActive();
+ }
+
+// ---------------------------------------------------------------------------
+// CServerAuthFailOperation::ProcessServerAuthorizationFailureL()
+// ---------------------------------------------------------------------------
+//
+void CServerAuthFailOperation::ProcessServerAuthorizationFailureL()
+ {
+ TRACE( "CServerAuthFailOperation::ProcessServerAuthorizationFailureL" );
+ OpenTrustedSiteCertificateStoreL();
+ if( IsAlreadyTrustedSiteL() )
+ {
+ StartFetchingTrustedSiteCertsL();
+ }
+ else
+ {
+ ShowUntrustedCertificateDialogL();
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CServerAuthFailOperation::OpenTrustedSiteCertificateStoreL()
+// ---------------------------------------------------------------------------
+//
+void CServerAuthFailOperation::OpenTrustedSiteCertificateStoreL()
+ {
+ TRACE( "CServerAuthFailOperation::OpenTrustedSiteCertificateStoreL, begin" );
+ TInt count = iCertStore->WritableCertStoreCount();
+ for( TInt index = 0; ( index < count ) && !iTrustedSiteCertStore; index++ )
+ {
+ MCTWritableCertStore* certstore = &( iCertStore->WritableCertStore( index ) );
+ TUid tokenTypeUid = certstore->Token().Handle().iTokenTypeUid;
+ if( tokenTypeUid == KTrustedSiteCertificatesTokenTypeUid )
+ {
+ iTrustedSiteCertStore = certstore;
+ }
+ }
+ TRACE( "CServerAuthFailOperation::OpenTrustedSiteCertificateStoreL, store 0x%08x",
+ iTrustedSiteCertStore );
+ }
+
+// ---------------------------------------------------------------------------
+// CServerAuthFailOperation::IsAlreadyTrustedSiteL()
+// ---------------------------------------------------------------------------
+//
+TBool CServerAuthFailOperation::IsAlreadyTrustedSiteL()
+ {
+ TRACE( "CServerAuthFailOperation::IsAlreadyTrustedSiteL, begin" );
+ TBool isTrustedSite = EFalse;
+ if( iTrustedSiteCertStore )
+ {
+ CTrustSitesStore* trustedSitesStore = CTrustSitesStore::NewL();
+ CleanupStack::PushL( trustedSitesStore );
+
+ isTrustedSite = trustedSitesStore->IsTrustedSiteL( iEncodedServerCert, *iServerName );
+ if( isTrustedSite )
+ {
+ TBool isExpiredAccepted = trustedSitesStore->IsOutOfDateAllowedL(
+ iEncodedServerCert, *iServerName );
+ TRACE( "CServerAuthFailOperation::IsAlreadyTrustedSiteL, isExpiredAccepted=%d",
+ isExpiredAccepted );
+ if( !isExpiredAccepted && iAuthFailReason == EDateOutOfRange )
+ {
+ TRACE( "CServerAuthFailOperation::IsAlreadyTrustedSiteL, not accepted" );
+ isTrustedSite = EFalse;
+ }
+ }
+
+ CleanupStack::PopAndDestroy( trustedSitesStore );
+ }
+ TRACE( "CServerAuthFailOperation::IsAlreadyTrustedSiteL, isTrustedSite=%d", isTrustedSite );
+ return isTrustedSite;
+ }
+
+// ---------------------------------------------------------------------------
+// CServerAuthFailOperation::StartFetchingTrustedSiteCertsL()
+// ---------------------------------------------------------------------------
+//
+void CServerAuthFailOperation::StartFetchingTrustedSiteCertsL()
+ {
+ TRACE( "CServerAuthFailOperation::StartFetchingTrustedSiteCertsL" );
+ __ASSERT_DEBUG( iCertAttributeFilter == NULL, User::Invariant() );
+ iCertAttributeFilter = CCertAttributeFilter::NewL();
+ iCertAttributeFilter->SetOwnerType( EPeerCertificate );
+ __ASSERT_DEBUG( iTrustedSiteCertStore != NULL, User::Invariant() );
+ iTrustedSiteCertStore->List( iCertInfos, *iCertAttributeFilter, iStatus );
+ iMode = EListTrustedSiteCerts;
+ SetActive();
+ }
+
+// ---------------------------------------------------------------------------
+// CServerAuthFailOperation::ShowUntrustedCertificateDialogL()
+// ---------------------------------------------------------------------------
+//
+void CServerAuthFailOperation::ShowUntrustedCertificateDialogL()
+ {
+ TRACE( "CServerAuthFailOperation::ShowUntrustedCertificateDialogL, begin" );
+
+ // If trusted site certstore open has failed, then it is not possible to save
+ // the host name for permanent use. Hence, choice for permanent accept is not
+ // displayed if trusted site certstore open has failed. Other restrictions for
+ // permanent accept are defined in device dialog (UntrustedCertificateWidget).
+ TBool isTrustedSiteCertStoreOpened = ( iTrustedSiteCertStore != NULL );
+ __ASSERT_DEBUG( iUntrustedCertQuery == NULL, User::Invariant() );
+ iUntrustedCertQuery = CUntrustedCertQuery::NewL( iAuthFailReason, iEncodedServerCert,
+ *iServerName, isTrustedSiteCertStoreOpened );
+
+ CUntrustedCertQuery::TResponse response = CUntrustedCertQuery::EQueryRejected;
+ iUntrustedCertQuery->ShowQueryAndWaitForResponseL( response );
+ switch( response )
+ {
+ case CUntrustedCertQuery::EQueryAccepted:
+ ReturnResultL( EContinue );
+ break;
+ case CUntrustedCertQuery::EQueryAcceptedPermanently:
+ SaveServerCertToTrustedSiteCertStoreL();
+ break;
+ case CUntrustedCertQuery::EQueryRejected:
+ default:
+ ReturnResultL( EStop );
+ break;
+ }
+
+ TRACE( "CServerAuthFailOperation::ShowUntrustedCertificateDialogL, end" );
+ }
+
+// ---------------------------------------------------------------------------
+// CServerAuthFailOperation::SaveServerCertToTrustedSiteCertStoreL()
+// ---------------------------------------------------------------------------
+//
+void CServerAuthFailOperation::SaveServerCertToTrustedSiteCertStoreL()
+ {
+ TRACE( "CServerAuthFailOperation::SaveServerCertToTrustedSiteCertStoreL" );
+
+ __ASSERT_DEBUG( iCertLabel == NULL, User::Invariant() );
+ CX509Certificate* serverCert = CX509Certificate::NewLC( iEncodedServerCert );
+ const CX500DistinguishedName& dName = serverCert->SubjectName();
+ HBufC* commonName = dName.ExtractFieldL( KX520CommonName );
+ if( commonName )
+ {
+ CleanupStack::PushL( commonName );
+ TInt commonNameLen = commonName->Length();
+ if( commonNameLen > 0 && commonNameLen <= KMaxCommonNameLength )
+ {
+ iCertLabel = commonName->AllocL();
+ }
+ CleanupStack::PopAndDestroy( commonName );
+ }
+ CleanupStack::PopAndDestroy( serverCert );
+
+ if( !iCertLabel )
+ {
+ iCertLabel = iServerName->AllocL();
+ }
+
+ iTrustedSiteCertStore->Add( *iCertLabel, EX509Certificate, EPeerCertificate,
+ NULL, NULL, iEncodedServerCert, iStatus );
+ iMode = ESavingServerCert;
+ SetActive();
+ }
+
+// ---------------------------------------------------------------------------
+// CServerAuthFailOperation::SaveServerNameToTrustedSitesStoreL()
+// ---------------------------------------------------------------------------
+//
+void CServerAuthFailOperation::SaveServerNameToTrustedSitesStoreL()
+ {
+ TRACE( "CServerAuthFailOperation::SaveServerNameToTrustedSitesStoreL, begin" );
+ CTrustSitesStore* trustedSitesStore = CTrustSitesStore::NewL();
+ CleanupStack::PushL( trustedSitesStore );
+
+ // CTrustSitesStore::AddL() may leave or it may return an error code.
+ // It leaves if parameters are incorrect, and it returns error code if
+ // saving fails. Both kinds of errors are handled here in the same way.
+ TInt err = trustedSitesStore->AddL( iEncodedServerCert, *iServerName );
+ TRACE( "CServerAuthFailOperation::SaveServerNameToTrustedSitesStoreL, err=%d", err );
+ User::LeaveIfError( err );
+
+ CleanupStack::PopAndDestroy( trustedSitesStore );
+ }
+
+// ---------------------------------------------------------------------------
+// CServerAuthFailOperation::ReturnResultL()
+// ---------------------------------------------------------------------------
+//
+void CServerAuthFailOperation::ReturnResultL( TServerAuthenticationFailureDialogResult aResult )
+ {
+ TRACE( "CServerAuthFailOperation::ReturnResultL, aResult=%d", aResult );
+ TServerAuthenticationFailureOutputBuf output( aResult );
+ iMessage.WriteL( iReplySlot, output );
+ TRACE( "CServerAuthFailOperation::ReturnResultL, completing msg 0x%08x", iMessage.Handle() );
+ iMessage.Complete( KErrNone );
+ TRACE( "CServerAuthFailOperation::ReturnResultL, informing observer" );
+ iObserver.OperationComplete();
+ TRACE( "CServerAuthFailOperation::ReturnResultL, end" );
+ }
+
+// ---------------------------------------------------------------------------
+// CServerAuthFailOperation::RetrieveFirstTrustedSiteCertL()
+// ---------------------------------------------------------------------------
+//
+void CServerAuthFailOperation::RetrieveFirstTrustedSiteCertL()
+ {
+ TRACE( "CServerAuthFailOperation::RetrieveFirstTrustedSiteCertL" );
+ __ASSERT_DEBUG( iRetrievedCertBuffer == NULL, User::Invariant() );
+ iRetrieveCertIndex = 0;
+
+ RetrieveNextTrustedSiteCertL();
+ }
+
+// ---------------------------------------------------------------------------
+// CServerAuthFailOperation::RetrieveNextTrustedSiteCertL()
+// ---------------------------------------------------------------------------
+//
+void CServerAuthFailOperation::RetrieveNextTrustedSiteCertL()
+ {
+ TRACE( "CServerAuthFailOperation::RetrieveNextTrustedSiteCertL" );
+ if( iRetrieveCertIndex < iCertInfos.Count() )
+ {
+ CCTCertInfo& cert = *( iCertInfos[ iRetrieveCertIndex ] );
+
+ if( iRetrievedCertBuffer )
+ {
+ delete iRetrievedCertBuffer;
+ iRetrievedCertBuffer = NULL;
+ }
+ iRetrievedCertBuffer = HBufC8::NewL( cert.Size() );
+ TPtr8 buffer = iRetrievedCertBuffer->Des();
+
+ iTrustedSiteCertStore->Retrieve( cert, buffer, iStatus );
+ iMode = ERetrieveTrustedSiteCert;
+ SetActive();
+ }
+ else
+ {
+ ShowUntrustedCertificateDialogL();
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CServerAuthFailOperation::IsRetrievedCertSameAsServerCertL()
+// ---------------------------------------------------------------------------
+//
+TBool CServerAuthFailOperation::IsRetrievedCertSameAsServerCertL()
+ {
+ TRACE( "CServerAuthFailOperation::IsRetrievedCertSameAsServerCertL, begin" );
+ TBool isSame = EFalse;
+ CX509Certificate* cert = CX509Certificate::NewLC( *iRetrievedCertBuffer );
+
+ if( !iServerCertFingerprint )
+ {
+ CX509Certificate* serverCert = CX509Certificate::NewLC( iEncodedServerCert );
+ iServerCertFingerprint = serverCert->Fingerprint().AllocL();
+ CleanupStack::PopAndDestroy( serverCert );
+ }
+
+ if( cert->Fingerprint() == *iServerCertFingerprint )
+ {
+ isSame = ETrue;
+ }
+
+ CleanupStack::PopAndDestroy( cert );
+ TRACE( "CServerAuthFailOperation::IsRetrievedCertSameAsServerCertL, isSame=%d", isSame );
+ return isSame;
+ }
+