diff -r 000000000000 -r e4d67989cc36 ssl/libcrypto/src/crypto/certretriever/certretriever.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ssl/libcrypto/src/crypto/certretriever/certretriever.cpp Tue Feb 02 02:01:42 2010 +0200 @@ -0,0 +1,336 @@ +/* +Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +* Neither the name of Nokia Corporation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Description: Contains implementation for x509_add_symbian_cert - to use certificates installed in Symbian with OpenSSL code. +*/ + + +#include "certretriever.h" +#include "createx509.h" + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif +int X509_add_symbian_certs(X509_STORE * store) +{ + CActiveScheduler* activeScheduler; + CActiveScheduler* CurrentActiveScheduler = CActiveScheduler::Current(); + if(CurrentActiveScheduler == NULL) + { + activeScheduler = new (ELeave) CActiveScheduler; + CleanupStack::PushL(activeScheduler); + + CActiveScheduler::Install(activeScheduler); + } + + + TRequestStatus status; + CCertRetriever* certRetriever; + TRAPD(error, certRetriever = CCertRetriever::NewL(store, status, CActiveScheduler::Current())); + + // create CActiveSchedulerWait + if (CurrentActiveScheduler) + { + certRetriever->activeSchedulerwait = new (ELeave) CActiveSchedulerWait; + certRetriever->OwnScheduler = EFalse; + } + + + if(error != KErrNone) + { + CleanupStack::PopAndDestroy(); // activeScheduler + return 0; + } + + CleanupStack::PushL(certRetriever); + + TRAP(error,certRetriever->RetriveCertificateL()); + if(error != KErrNone) + { + if(CurrentActiveScheduler == NULL) + { + CleanupStack::PopAndDestroy(2); // activeScheduler, certRetriever + } + else + CleanupStack::PopAndDestroy(); // certRetriever + return 0; + } + + + if(CurrentActiveScheduler == NULL) + { + activeScheduler->Start(); + CleanupStack::PopAndDestroy(2); // If you destroy the object it will not be there + // in the iActiveQ, and hence stray signal. + + //CleanupStack::Pop(2); // So just pop it. // activeScheduler, certRetriever + } + else + { + // CurrentActiveScheduler->Start();// If you are using CActiveScheduler::Current(); + // Why u want to start it again? + + // CleanupStack::PopAndDestroy(); // If you destroy the object it will not be there + // in the iActiveQ, and hence stray signal. + + // should wait here untill it finish loading certificates, ths API is synchronous + certRetriever->activeSchedulerwait->Start(); + + CleanupStack::Pop(); // So just pop it. // certRetriever + } + + + + if(status == KErrNone) + return 1; + else + return 0; +} +#ifdef __cplusplus +} +#endif + +CCertRetriever::CCertRetriever(X509_STORE* aStore, + TRequestStatus& aStatus, + const CActiveScheduler* aActiveScheduler) + : CActive(CActive::EPriorityHigh), + iStore(aStore), + iFinStatus ( aStatus ), + iActiveScheduler(aActiveScheduler), + iCertPtr(0,0) + + { + + OwnScheduler = ETrue; + if(iActiveScheduler) + iActiveScheduler->Add(this); + } + +CCertRetriever::~CCertRetriever() + { + Cancel(); + delete iBuf; + delete iCertFilter; + + iCerts.Close(); + delete iCertStore; + iFs.Close(); + if(!OwnScheduler) + delete activeSchedulerwait; + } + +CCertRetriever* CCertRetriever::NewLC(X509_STORE* aStore, + TRequestStatus& aStatus, + const CActiveScheduler* aActiveScheduler) + { + CCertRetriever* self = new (ELeave) CCertRetriever(aStore, aStatus, aActiveScheduler); + CleanupStack::PushL(self); + TRAPD(err,self->ConstructL()); + if(err != KErrNotFound) + return self; + + CleanupStack::PopAndDestroy(self); + return NULL; + } + +CCertRetriever* CCertRetriever::NewL(X509_STORE* aStore, + TRequestStatus& aStatus, + const CActiveScheduler* aActiveScheduler) + { + CCertRetriever* self = CCertRetriever::NewLC(aStore, aStatus, aActiveScheduler); + if(self) + CleanupStack::Pop(); + return self; + } + +void CCertRetriever::ConstructL() + { + TInt err = iFs.Connect(); + if(err != KErrNone) + User::Leave(err); + + iState = EInitializeCertStore; + iBuf = HBufC8::NewL(KMaxCertLength); + } + + +void CCertRetriever::RunL() + { + // 1. All certificates retrieved. + // 2. yes. check iActiveScheduler. if null then call User::RequestComplete(iStatus) else iActiveScheduler->Stop(); + User::LeaveIfError(iStatus.Int()); + + switch(iState) + { + case EInitializeCertStore: + OpenUnifiedCertStoreL(); + break; + + case EListCerts: + ListCertsL(); + break; + case EAppendCerts: + if (!iCerts.Count()) // no certificate in store. + { + iState = ENoCerts; + } + else + { + AppendCerts(); + break; + } + + case EDone: + if (iState != ENoCerts) + { + ProcessCerts(); //Process the last certificate + iCertCount = 0; + } + case ENoCerts: + + if(iActiveScheduler) + { + if(OwnScheduler) + iActiveScheduler->Stop(); + else + activeSchedulerwait->AsyncStop(); + + iFinStatus = iStatus; + } + else + { + TRequestStatus *s = &iFinStatus; + User::RequestComplete(s, KErrNone); + } + + + break; + + default: + User::Leave(KErrNotFound); + break; + } + } + + +void CCertRetriever::DoCancel() + { + } + +TInt CCertRetriever::RunError(TInt aError) + { + //Can do some error handling here + if(iActiveScheduler) + { + iActiveScheduler->Stop(); + iFinStatus = iStatus; + } + else + { + TRequestStatus *s = &iFinStatus; + User::RequestComplete(s, aError); + } + + return KErrNone; + } + +void CCertRetriever::RetriveCertificateL() + { + OpenUnifiedCertStoreL(); + } + + +void CCertRetriever::OpenUnifiedCertStoreL() + { + + iState = EListCerts; + delete iCertStore; + iCertStore = NULL; + iCertStore = CUnifiedCertStore::NewL(iFs, EFalse); + iCertStore->Initialize(iStatus); + SetActive(); + } + +void CCertRetriever::ListCertsL() +{ + // Create filter object + + delete iCertFilter; + iCertFilter = NULL; + iCertFilter = CCertAttributeFilter::NewL(); + iCertFilter->SetFormat(EX509Certificate); + iCertFilter->SetOwnerType(ECACertificate); + iCertFilter->SetUid(KTlsApplicabilityUid); + + iStatus = KRequestPending; + SetActive(); + iCertStore->List(iCerts, *iCertFilter, iStatus); + iState = EAppendCerts; +} + +void CCertRetriever::AppendCerts() +{ + if(iCertCount>0) + ProcessCerts(); + + CCTCertInfo *cert = iCerts[iCertCount]; + + SetActive(); + iStatus == KRequestPending; + + iCertPtr.Set( iBuf->Des() ); + iCertStore->Retrieve((*cert),iCertPtr,iStatus); + + iCertCount++; + + if(iCertCount == iCerts.Count()) + iState = EDone; +} + + +void CCertRetriever::ProcessCerts() +{ + CX509Certificate *X509Cert; + TRAPD(error, X509Cert = CX509Certificate::NewL( iCertPtr )); + if(error !=KErrNone) + return; + + CleanupStack::PushL(X509Cert); + + X509* x509 = CX509_Initializer::CreateX509(X509Cert); + + if(x509) + { + X509_STORE_add_cert(iStore,x509); + X509_free(x509); + } + + CleanupStack::PopAndDestroy(); //X509Cert + +}