Back to index

lightning-sunbird  0.9+nobinonly
nsCertVerificationThread.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is mozilla.org code.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Red Hat, Inc.
00018  * Portions created by the Initial Developer are Copyright (C) 2006
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   Kai Engert <kengert@redhat.com>
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "nsMemory.h"
00039 #include "nsAutoLock.h"
00040 #include "nsAutoPtr.h"
00041 #include "nsCertVerificationThread.h"
00042 
00043 nsCertVerificationThread *nsCertVerificationThread::verification_thread_singleton;
00044 
00045 NS_IMPL_THREADSAFE_ISUPPORTS1(nsCertVerificationResult, nsICertVerificationResult)
00046 
00047 void nsCertVerificationJob::Run()
00048 {
00049   if (!mListener || !mCert)
00050     return;
00051 
00052   PRUint32 verified;
00053   PRUint32 count;
00054   PRUnichar **usages;
00055 
00056   nsCOMPtr<nsICertVerificationResult> ires;
00057   nsRefPtr<nsCertVerificationResult> vres = new nsCertVerificationResult;
00058   if (vres)
00059   {
00060     nsresult rv = mCert->GetUsagesArray(PR_FALSE, // do not ignore OCSP
00061                                         &verified,
00062                                         &count,
00063                                         &usages);
00064     vres->mRV = rv;
00065     if (NS_SUCCEEDED(rv))
00066     {
00067       vres->mVerified = verified;
00068       vres->mCount = count;
00069       vres->mUsages = usages;
00070     }
00071 
00072     ires = vres;
00073   }
00074   
00075   nsCOMPtr<nsIX509Cert3> c3 = do_QueryInterface(mCert);
00076   mListener->Notify(c3, ires);
00077 }
00078 
00079 void nsSMimeVerificationJob::Run()
00080 {
00081   if (!mMessage || !mListener)
00082     return;
00083   
00084   nsresult rv;
00085   
00086   if (digest_data)
00087     rv = mMessage->VerifyDetachedSignature(digest_data, digest_len);
00088   else
00089     rv = mMessage->VerifySignature();
00090   
00091   nsCOMPtr<nsICMSMessage2> m2 = do_QueryInterface(mMessage);
00092   mListener->Notify(m2, rv);
00093 }
00094 
00095 nsCertVerificationThread::nsCertVerificationThread()
00096 : mJobQ(nsnull)
00097 {
00098   NS_ASSERTION(!verification_thread_singleton, 
00099                "nsCertVerificationThread is a singleton, caller attempts"
00100                " to create another instance!");
00101   
00102   verification_thread_singleton = this;
00103 }
00104 
00105 nsCertVerificationThread::~nsCertVerificationThread()
00106 {
00107   verification_thread_singleton = nsnull;
00108 }
00109 
00110 nsresult nsCertVerificationThread::addJob(nsBaseVerificationJob *aJob)
00111 {
00112   if (!aJob || !verification_thread_singleton)
00113     return NS_ERROR_FAILURE;
00114   
00115   if (!verification_thread_singleton->mThreadHandle)
00116     return NS_ERROR_OUT_OF_MEMORY;
00117 
00118   nsAutoLock threadLock(verification_thread_singleton->mMutex);
00119 
00120   verification_thread_singleton->mJobQ.Push(aJob);
00121   PR_NotifyAllCondVar(verification_thread_singleton->mCond);
00122   
00123   return NS_OK;
00124 }
00125 
00126 void nsCertVerificationThread::Run(void)
00127 {
00128   while (PR_TRUE) {
00129 
00130     nsBaseVerificationJob *job = nsnull;
00131 
00132     {
00133       nsAutoLock threadLock(verification_thread_singleton->mMutex);
00134       
00135       while (!mExitRequested && (0 == verification_thread_singleton->mJobQ.GetSize())) {
00136         // no work to do ? let's wait a moment
00137 
00138         PR_WaitCondVar(mCond, PR_INTERVAL_NO_TIMEOUT);
00139       }
00140       
00141       if (mExitRequested)
00142         break;
00143       
00144       job = NS_STATIC_CAST(nsBaseVerificationJob*, mJobQ.PopFront());
00145     }
00146 
00147     if (job)
00148     {
00149       job->Run();
00150       delete job;
00151     }
00152   }
00153   
00154   {
00155     nsAutoLock threadLock(verification_thread_singleton->mMutex);
00156 
00157     while (verification_thread_singleton->mJobQ.GetSize()) {
00158       nsCertVerificationJob *job = 
00159         NS_STATIC_CAST(nsCertVerificationJob*, mJobQ.PopFront());
00160       delete job;
00161     }
00162   }
00163 }
00164 
00165 nsCertVerificationResult::nsCertVerificationResult()
00166 : mRV(0),
00167   mVerified(0),
00168   mCount(0),
00169   mUsages(0)
00170 {
00171 }
00172 
00173 nsCertVerificationResult::~nsCertVerificationResult()
00174 {
00175   if (mUsages)
00176   {
00177     NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(mCount, mUsages);
00178   }
00179 }
00180 
00181 NS_IMETHODIMP
00182 nsCertVerificationResult::GetUsagesArrayResult(PRUint32 *aVerified,
00183                                                PRUint32 *aCount,
00184                                                PRUnichar ***aUsages)
00185 {
00186   if (NS_FAILED(mRV))
00187     return mRV;
00188   
00189   // transfer ownership
00190   
00191   *aVerified = mVerified;
00192   *aCount = mCount;
00193   *aUsages = mUsages;
00194   
00195   mVerified = 0;
00196   mCount = 0;
00197   mUsages = 0;
00198   
00199   nsresult rv = mRV;
00200   
00201   mRV = NS_ERROR_FAILURE; // this object works only once...
00202   
00203   return rv;
00204 }