LCOV - code coverage report
Current view: directory - security/manager/ssl/src - nsNSSCertificateDB.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 879 10 1.1 %
Date: 2012-06-02 Functions: 44 7 15.9 %

       1                 : /* ***** BEGIN LICENSE BLOCK *****
       2                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       3                 :  *
       4                 :  * The contents of this file are subject to the Mozilla Public License Version
       5                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       6                 :  * the License. You may obtain a copy of the License at
       7                 :  * http://www.mozilla.org/MPL/
       8                 :  *
       9                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      10                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      11                 :  * for the specific language governing rights and limitations under the
      12                 :  * License.
      13                 :  *
      14                 :  * The Original Code is the Netscape security libraries.
      15                 :  *
      16                 :  * The Initial Developer of the Original Code is
      17                 :  * Netscape Communications Corporation.
      18                 :  * Portions created by the Initial Developer are Copyright (C) 2000
      19                 :  * the Initial Developer. All Rights Reserved.
      20                 :  *
      21                 :  * Contributor(s):
      22                 :  *   Ian McGreer <mcgreer@netscape.com>
      23                 :  *   Javier Delgadillo <javi@netscape.com>
      24                 :  *
      25                 :  * Alternatively, the contents of this file may be used under the terms of
      26                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      27                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      29                 :  * of those above. If you wish to allow use of your version of this file only
      30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      31                 :  * use your version of this file under the terms of the MPL, indicate your
      32                 :  * decision by deleting the provisions above and replace them with the notice
      33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      34                 :  * the provisions above, a recipient may use your version of this file under
      35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      36                 :  *
      37                 :  * ***** END LICENSE BLOCK ***** */
      38                 : 
      39                 : #include "nsNSSComponent.h"
      40                 : #include "nsNSSCertificateDB.h"
      41                 : #include "nsCOMPtr.h"
      42                 : #include "nsNSSCertificate.h"
      43                 : #include "nsNSSHelper.h"
      44                 : #include "nsNSSCertHelper.h"
      45                 : #include "nsNSSCertCache.h"
      46                 : #include "nsCRT.h"
      47                 : #include "nsICertificateDialogs.h"
      48                 : #include "nsNSSCertTrust.h"
      49                 : #include "nsILocalFile.h"
      50                 : #include "nsPKCS12Blob.h"
      51                 : #include "nsPK11TokenDB.h"
      52                 : #include "nsOCSPResponder.h"
      53                 : #include "nsReadableUtils.h"
      54                 : #include "nsIMutableArray.h"
      55                 : #include "nsArrayUtils.h"
      56                 : #include "nsNSSShutDown.h"
      57                 : #include "nsIPrefService.h"
      58                 : #include "nsIPrefBranch.h"
      59                 : #include "nsComponentManagerUtils.h"
      60                 : #include "nsIPrompt.h"
      61                 : #include "nsThreadUtils.h"
      62                 : 
      63                 : #include "nspr.h"
      64                 : extern "C" {
      65                 : #include "pk11func.h"
      66                 : #include "certdb.h"
      67                 : #include "cert.h"
      68                 : #include "secerr.h"
      69                 : #include "nssb64.h"
      70                 : #include "secasn1.h"
      71                 : #include "secder.h"
      72                 : }
      73                 : #include "ssl.h"
      74                 : #include "ocsp.h"
      75                 : #include "plbase64.h"
      76                 : 
      77                 : #ifdef PR_LOGGING
      78                 : extern PRLogModuleInfo* gPIPNSSLog;
      79                 : #endif
      80                 : 
      81                 : #include "nsNSSCleaner.h"
      82               0 : NSSCleanupAutoPtrClass(CERTCertificate, CERT_DestroyCertificate)
      83               0 : NSSCleanupAutoPtrClass(CERTCertList, CERT_DestroyCertList)
      84               0 : NSSCleanupAutoPtrClass(CERTCertificateList, CERT_DestroyCertificateList)
      85               0 : NSSCleanupAutoPtrClass(PK11SlotInfo, PK11_FreeSlot)
      86                 : 
      87                 : static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
      88                 : 
      89                 : 
      90              36 : NS_IMPL_THREADSAFE_ISUPPORTS2(nsNSSCertificateDB, nsIX509CertDB, nsIX509CertDB2)
      91                 : 
      92               4 : nsNSSCertificateDB::nsNSSCertificateDB()
      93                 : {
      94               4 : }
      95                 : 
      96               8 : nsNSSCertificateDB::~nsNSSCertificateDB()
      97                 : {
      98              16 : }
      99                 : 
     100                 : NS_IMETHODIMP
     101               0 : nsNSSCertificateDB::FindCertByNickname(nsISupports *aToken,
     102                 :                                       const nsAString &nickname,
     103                 :                                       nsIX509Cert **_rvCert)
     104                 : {
     105               0 :   nsNSSShutDownPreventionLock locker;
     106               0 :   CERTCertificate *cert = NULL;
     107               0 :   char *asciiname = NULL;
     108               0 :   NS_ConvertUTF16toUTF8 aUtf8Nickname(nickname);
     109               0 :   asciiname = const_cast<char*>(aUtf8Nickname.get());
     110               0 :   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Getting \"%s\"\n", asciiname));
     111                 : #if 0
     112                 :   // what it should be, but for now...
     113                 :   if (aToken) {
     114                 :     cert = PK11_FindCertFromNickname(asciiname, NULL);
     115                 :   } else {
     116                 :     cert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), asciiname);
     117                 :   }
     118                 : #endif
     119               0 :   cert = PK11_FindCertFromNickname(asciiname, NULL);
     120               0 :   if (!cert) {
     121               0 :     cert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), asciiname);
     122                 :   }
     123               0 :   if (cert) {
     124               0 :     PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("got it\n"));
     125               0 :     nsCOMPtr<nsIX509Cert> pCert = nsNSSCertificate::Create(cert);
     126               0 :     CERT_DestroyCertificate(cert);
     127               0 :     if (pCert) {
     128               0 :       *_rvCert = pCert;
     129               0 :       NS_ADDREF(*_rvCert);
     130               0 :       return NS_OK;
     131                 :     }
     132                 :   }
     133               0 :   *_rvCert = nsnull;
     134               0 :   return NS_ERROR_FAILURE;
     135                 : }
     136                 : 
     137                 : NS_IMETHODIMP 
     138               0 : nsNSSCertificateDB::FindCertByDBKey(const char *aDBkey, nsISupports *aToken,
     139                 :                                    nsIX509Cert **_cert)
     140                 : {
     141               0 :   nsNSSShutDownPreventionLock locker;
     142               0 :   SECItem keyItem = {siBuffer, nsnull, 0};
     143                 :   SECItem *dummy;
     144                 :   CERTIssuerAndSN issuerSN;
     145                 :   //unsigned long moduleID,slotID;
     146               0 :   *_cert = nsnull; 
     147               0 :   if (!aDBkey || !*aDBkey)
     148               0 :     return NS_ERROR_INVALID_ARG;
     149                 : 
     150                 :   dummy = NSSBase64_DecodeBuffer(nsnull, &keyItem, aDBkey,
     151               0 :                                  (PRUint32)PL_strlen(aDBkey)); 
     152               0 :   if (!dummy || keyItem.len < NS_NSS_LONG*4) {
     153               0 :     PR_FREEIF(keyItem.data);
     154               0 :     return NS_ERROR_INVALID_ARG;
     155                 :   }
     156                 : 
     157                 :   CERTCertificate *cert;
     158                 :   // someday maybe we can speed up the search using the moduleID and slotID
     159                 :   // moduleID = NS_NSS_GET_LONG(keyItem.data);
     160                 :   // slotID = NS_NSS_GET_LONG(&keyItem.data[NS_NSS_LONG]);
     161                 : 
     162                 :   // build the issuer/SN structure
     163               0 :   issuerSN.serialNumber.len = NS_NSS_GET_LONG(&keyItem.data[NS_NSS_LONG*2]);
     164               0 :   issuerSN.derIssuer.len = NS_NSS_GET_LONG(&keyItem.data[NS_NSS_LONG*3]);
     165               0 :   if (issuerSN.serialNumber.len == 0 || issuerSN.derIssuer.len == 0
     166                 :       || issuerSN.serialNumber.len + issuerSN.derIssuer.len
     167                 :          != keyItem.len - NS_NSS_LONG*4) {
     168               0 :     PR_FREEIF(keyItem.data);
     169               0 :     return NS_ERROR_INVALID_ARG;
     170                 :   }
     171               0 :   issuerSN.serialNumber.data= &keyItem.data[NS_NSS_LONG*4];
     172                 :   issuerSN.derIssuer.data= &keyItem.data[NS_NSS_LONG*4+
     173               0 :                                               issuerSN.serialNumber.len];
     174                 : 
     175               0 :   cert = CERT_FindCertByIssuerAndSN(CERT_GetDefaultCertDB(), &issuerSN);
     176               0 :   PR_FREEIF(keyItem.data);
     177               0 :   if (cert) {
     178               0 :     nsNSSCertificate *nssCert = nsNSSCertificate::Create(cert);
     179               0 :     CERT_DestroyCertificate(cert);
     180               0 :     if (nssCert == nsnull)
     181               0 :       return NS_ERROR_OUT_OF_MEMORY;
     182               0 :     NS_ADDREF(nssCert);
     183               0 :     *_cert = static_cast<nsIX509Cert*>(nssCert);
     184                 :   }
     185               0 :   return NS_OK;
     186                 : }
     187                 : 
     188                 : NS_IMETHODIMP 
     189               0 : nsNSSCertificateDB::FindCertNicknames(nsISupports *aToken, 
     190                 :                                      PRUint32      aType,
     191                 :                                      PRUint32     *_count,
     192                 :                                      PRUnichar  ***_certNames)
     193                 : {
     194               0 :   nsNSSShutDownPreventionLock locker;
     195               0 :   nsresult rv = NS_ERROR_FAILURE;
     196                 :   /*
     197                 :    * obtain the cert list from NSS
     198                 :    */
     199               0 :   CERTCertList *certList = NULL;
     200                 :   PK11CertListType pk11type;
     201                 : #if 0
     202                 :   // this would seem right, but it didn't work...
     203                 :   // oh, I know why - bonks out on internal slot certs
     204                 :   if (aType == nsIX509Cert::USER_CERT)
     205                 :     pk11type = PK11CertListUser;
     206                 :   else 
     207                 : #endif
     208               0 :     pk11type = PK11CertListUnique;
     209               0 :   certList = PK11_ListCerts(pk11type, NULL);
     210               0 :   if (!certList)
     211               0 :     goto cleanup;
     212                 :   /*
     213                 :    * get list of cert names from list of certs
     214                 :    * XXX also cull the list (NSS only distinguishes based on user/non-user
     215                 :    */
     216               0 :   getCertNames(certList, aType, _count, _certNames);
     217               0 :   rv = NS_OK;
     218                 :   /*
     219                 :    * finish up
     220                 :    */
     221                 : cleanup:
     222               0 :   if (certList)
     223               0 :     CERT_DestroyCertList(certList);
     224               0 :   return rv;
     225                 : }
     226                 : 
     227                 : SECStatus PR_CALLBACK
     228               0 : collect_certs(void *arg, SECItem **certs, int numcerts)
     229                 : {
     230                 :   CERTDERCerts *collectArgs;
     231                 :   SECItem *cert;
     232                 :   SECStatus rv;
     233                 : 
     234               0 :   collectArgs = (CERTDERCerts *)arg;
     235                 : 
     236               0 :   collectArgs->numcerts = numcerts;
     237                 :   collectArgs->rawCerts = (SECItem *) PORT_ArenaZAlloc(collectArgs->arena,
     238               0 :                                            sizeof(SECItem) * numcerts);
     239               0 :   if ( collectArgs->rawCerts == NULL )
     240               0 :     return(SECFailure);
     241                 : 
     242               0 :   cert = collectArgs->rawCerts;
     243                 : 
     244               0 :   while ( numcerts-- ) {
     245               0 :     rv = SECITEM_CopyItem(collectArgs->arena, cert, *certs);
     246               0 :     if ( rv == SECFailure )
     247               0 :       return(SECFailure);
     248               0 :     cert++;
     249               0 :     certs++;
     250                 :   }
     251                 : 
     252               0 :   return (SECSuccess);
     253                 : }
     254                 : 
     255                 : CERTDERCerts*
     256               0 : nsNSSCertificateDB::getCertsFromPackage(PRArenaPool *arena, PRUint8 *data, 
     257                 :                                         PRUint32 length)
     258                 : {
     259               0 :   nsNSSShutDownPreventionLock locker;
     260                 :   CERTDERCerts *collectArgs = 
     261               0 :                (CERTDERCerts *)PORT_ArenaZAlloc(arena, sizeof(CERTDERCerts));
     262               0 :   if ( collectArgs == nsnull ) 
     263               0 :     return nsnull;
     264                 : 
     265               0 :   collectArgs->arena = arena;
     266                 :   SECStatus sec_rv = CERT_DecodeCertPackage(reinterpret_cast<char *>(data), 
     267                 :                                             length, collect_certs, 
     268               0 :                                             (void *)collectArgs);
     269               0 :   if (sec_rv != SECSuccess)
     270               0 :     return nsnull;
     271                 : 
     272               0 :   return collectArgs;
     273                 : }
     274                 : 
     275                 : nsresult
     276               0 : nsNSSCertificateDB::handleCACertDownload(nsIArray *x509Certs,
     277                 :                                          nsIInterfaceRequestor *ctx)
     278                 : {
     279                 :   // First thing we have to do is figure out which certificate we're 
     280                 :   // gonna present to the user.  The CA may have sent down a list of 
     281                 :   // certs which may or may not be a chained list of certs.  Until
     282                 :   // the day we can design some solid UI for the general case, we'll
     283                 :   // code to the > 90% case.  That case is where a CA sends down a
     284                 :   // list that is a hierarchy whose root is either the first or 
     285                 :   // the last cert.  What we're gonna do is compare the first 
     286                 :   // 2 entries, if the second was signed by the first, we assume
     287                 :   // the root cert is the first cert and display it.  Otherwise,
     288                 :   // we compare the last 2 entries, if the second to last cert was
     289                 :   // signed by the last cert, then we assume the last cert is the
     290                 :   // root and display it.
     291                 : 
     292               0 :   nsNSSShutDownPreventionLock locker;
     293                 : 
     294                 :   PRUint32 numCerts;
     295                 : 
     296               0 :   x509Certs->GetLength(&numCerts);
     297               0 :   NS_ASSERTION(numCerts > 0, "Didn't get any certs to import.");
     298               0 :   if (numCerts == 0)
     299               0 :     return NS_OK; // Nothing to import, so nothing to do.
     300                 : 
     301               0 :   nsCOMPtr<nsIX509Cert> certToShow;
     302               0 :   nsCOMPtr<nsISupports> isupports;
     303                 :   PRUint32 selCertIndex;
     304               0 :   if (numCerts == 1) {
     305                 :     // There's only one cert, so let's show it.
     306               0 :     selCertIndex = 0;
     307               0 :     certToShow = do_QueryElementAt(x509Certs, selCertIndex);
     308                 :   } else {
     309               0 :     nsCOMPtr<nsIX509Cert> cert0;    // first cert
     310               0 :     nsCOMPtr<nsIX509Cert> cert1;    // second cert
     311               0 :     nsCOMPtr<nsIX509Cert> certn_2;  // second to last cert
     312               0 :     nsCOMPtr<nsIX509Cert> certn_1;  // last cert
     313                 : 
     314               0 :     cert0 = do_QueryElementAt(x509Certs, 0);
     315               0 :     cert1 = do_QueryElementAt(x509Certs, 1);
     316               0 :     certn_2 = do_QueryElementAt(x509Certs, numCerts-2);
     317               0 :     certn_1 = do_QueryElementAt(x509Certs, numCerts-1);
     318                 : 
     319               0 :     nsXPIDLString cert0SubjectName;
     320               0 :     nsXPIDLString cert1IssuerName;
     321               0 :     nsXPIDLString certn_2IssuerName;
     322               0 :     nsXPIDLString certn_1SubjectName;
     323                 : 
     324               0 :     cert0->GetSubjectName(cert0SubjectName);
     325               0 :     cert1->GetIssuerName(cert1IssuerName);
     326               0 :     certn_2->GetIssuerName(certn_2IssuerName);
     327               0 :     certn_1->GetSubjectName(certn_1SubjectName);
     328                 : 
     329               0 :     if (cert1IssuerName.Equals(cert0SubjectName)) {
     330                 :       // In this case, the first cert in the list signed the second,
     331                 :       // so the first cert is the root.  Let's display it. 
     332               0 :       selCertIndex = 0;
     333               0 :       certToShow = cert0;
     334                 :     } else 
     335               0 :     if (certn_2IssuerName.Equals(certn_1SubjectName)) { 
     336                 :       // In this case the last cert has signed the second to last cert.
     337                 :       // The last cert is the root, so let's display it.
     338               0 :       selCertIndex = numCerts-1;
     339               0 :       certToShow = certn_1;
     340                 :     } else {
     341                 :       // It's not a chain, so let's just show the first one in the 
     342                 :       // downloaded list.
     343               0 :       selCertIndex = 0;
     344               0 :       certToShow = cert0;
     345                 :     }
     346                 :   }
     347                 : 
     348               0 :   if (!certToShow)
     349               0 :     return NS_ERROR_FAILURE;
     350                 : 
     351               0 :   nsCOMPtr<nsICertificateDialogs> dialogs;
     352               0 :   nsresult rv = ::getNSSDialogs(getter_AddRefs(dialogs), 
     353                 :                                 NS_GET_IID(nsICertificateDialogs),
     354               0 :                                 NS_CERTIFICATEDIALOGS_CONTRACTID);
     355                 :                        
     356               0 :   if (NS_FAILED(rv))
     357               0 :     return rv;
     358                 :  
     359                 :   SECItem der;
     360               0 :   rv=certToShow->GetRawDER(&der.len, (PRUint8 **)&der.data);
     361                 : 
     362               0 :   if (NS_FAILED(rv))
     363               0 :     return rv;
     364                 : 
     365               0 :   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Creating temp cert\n"));
     366                 :   CERTCertificate *tmpCert;
     367               0 :   CERTCertDBHandle *certdb = CERT_GetDefaultCertDB();
     368               0 :   tmpCert = CERT_FindCertByDERCert(certdb, &der);
     369               0 :   if (!tmpCert) {
     370                 :     tmpCert = CERT_NewTempCertificate(certdb, &der,
     371               0 :                                       nsnull, false, true);
     372                 :   }
     373               0 :   nsMemory::Free(der.data);
     374               0 :   der.data = nsnull;
     375               0 :   der.len = 0;
     376                 :   
     377               0 :   if (!tmpCert) {
     378               0 :     NS_ERROR("Couldn't create cert from DER blob");
     379               0 :     return NS_ERROR_FAILURE;
     380                 :   }
     381                 : 
     382               0 :   CERTCertificateCleaner tmpCertCleaner(tmpCert);
     383                 : 
     384               0 :   if (!CERT_IsCACert(tmpCert, NULL)) {
     385               0 :     DisplayCertificateAlert(ctx, "NotACACert", certToShow);
     386               0 :     return NS_ERROR_FAILURE;
     387                 :   }
     388                 : 
     389               0 :   if (tmpCert->isperm) {
     390               0 :     DisplayCertificateAlert(ctx, "CaCertExists", certToShow);
     391               0 :     return NS_ERROR_FAILURE;
     392                 :   }
     393                 : 
     394                 :   PRUint32 trustBits;
     395                 :   bool allows;
     396               0 :   rv = dialogs->ConfirmDownloadCACert(ctx, certToShow, &trustBits, &allows);
     397               0 :   if (NS_FAILED(rv))
     398               0 :     return rv;
     399                 : 
     400               0 :   if (!allows)
     401               0 :     return NS_ERROR_NOT_AVAILABLE;
     402                 : 
     403               0 :   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("trust is %d\n", trustBits));
     404               0 :   nsXPIDLCString nickname;
     405               0 :   nickname.Adopt(CERT_MakeCANickname(tmpCert));
     406                 : 
     407               0 :   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Created nick \"%s\"\n", nickname.get()));
     408                 : 
     409               0 :   nsNSSCertTrust trust;
     410               0 :   trust.SetValidCA();
     411                 :   trust.AddCATrust(!!(trustBits & nsIX509CertDB::TRUSTED_SSL),
     412                 :                    !!(trustBits & nsIX509CertDB::TRUSTED_EMAIL),
     413               0 :                    !!(trustBits & nsIX509CertDB::TRUSTED_OBJSIGN));
     414                 : 
     415                 :   SECStatus srv = CERT_AddTempCertToPerm(tmpCert, 
     416               0 :                                          const_cast<char*>(nickname.get()), 
     417               0 :                                          trust.GetTrust()); 
     418                 : 
     419               0 :   if (srv != SECSuccess)
     420               0 :     return NS_ERROR_FAILURE;
     421                 : 
     422                 :   // Import additional delivered certificates that can be verified.
     423                 : 
     424                 :   // build a CertList for filtering
     425               0 :   CERTCertList *certList = CERT_NewCertList();
     426               0 :   if (certList == NULL) {
     427               0 :     return NS_ERROR_FAILURE;
     428                 :   }
     429                 : 
     430               0 :   CERTCertListCleaner listCleaner(certList);
     431                 : 
     432                 :   // get all remaining certs into temp store
     433                 : 
     434               0 :   for (PRUint32 i=0; i<numCerts; i++) {
     435               0 :     if (i == selCertIndex) {
     436                 :       // we already processed that one
     437               0 :       continue;
     438                 :     }
     439                 : 
     440               0 :     certToShow = do_QueryElementAt(x509Certs, i);
     441               0 :     certToShow->GetRawDER(&der.len, (PRUint8 **)&der.data);
     442                 : 
     443                 :     CERTCertificate *tmpCert2 = 
     444               0 :       CERT_NewTempCertificate(certdb, &der, nsnull, false, true);
     445                 : 
     446               0 :     nsMemory::Free(der.data);
     447               0 :     der.data = nsnull;
     448               0 :     der.len = 0;
     449                 : 
     450               0 :     if (!tmpCert2) {
     451               0 :       NS_ERROR("Couldn't create temp cert from DER blob");
     452               0 :       continue;  // Let's try to import the rest of 'em
     453                 :     }
     454                 :     
     455               0 :     CERT_AddCertToListTail(certList, tmpCert2);
     456                 :   }
     457                 : 
     458               0 :   return ImportValidCACertsInList(certList, ctx);
     459                 : }
     460                 : 
     461                 : /*
     462                 :  *  [noscript] void importCertificates(in charPtr data, in unsigned long length,
     463                 :  *                                     in unsigned long type, 
     464                 :  *                                     in nsIInterfaceRequestor ctx);
     465                 :  */
     466                 : NS_IMETHODIMP 
     467               0 : nsNSSCertificateDB::ImportCertificates(PRUint8 * data, PRUint32 length, 
     468                 :                                        PRUint32 type, 
     469                 :                                        nsIInterfaceRequestor *ctx)
     470                 : 
     471                 : {
     472               0 :   nsNSSShutDownPreventionLock locker;
     473                 :   nsresult nsrv;
     474                 : 
     475               0 :   PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
     476               0 :   if (!arena)
     477               0 :     return NS_ERROR_OUT_OF_MEMORY;
     478                 : 
     479               0 :   CERTDERCerts *certCollection = getCertsFromPackage(arena, data, length);
     480               0 :   if (!certCollection) {
     481               0 :     PORT_FreeArena(arena, false);
     482               0 :     return NS_ERROR_FAILURE;
     483                 :   }
     484                 :   nsCOMPtr<nsIMutableArray> array =
     485               0 :     do_CreateInstance(NS_ARRAY_CONTRACTID, &nsrv);
     486               0 :   if (NS_FAILED(nsrv)) {
     487               0 :     PORT_FreeArena(arena, false);
     488               0 :     return nsrv;
     489                 :   }
     490                 : 
     491                 :   // Now let's create some certs to work with
     492               0 :   nsCOMPtr<nsIX509Cert> x509Cert;
     493                 :   nsNSSCertificate *nssCert;
     494                 :   SECItem *currItem;
     495               0 :   for (int i=0; i<certCollection->numcerts; i++) {
     496               0 :      currItem = &certCollection->rawCerts[i];
     497               0 :      nssCert = nsNSSCertificate::ConstructFromDER((char*)currItem->data, currItem->len);
     498               0 :      if (!nssCert)
     499               0 :        return NS_ERROR_FAILURE;
     500               0 :      x509Cert = do_QueryInterface((nsIX509Cert*)nssCert);
     501               0 :      array->AppendElement(x509Cert, false);
     502                 :   }
     503               0 :   switch (type) {
     504                 :   case nsIX509Cert::CA_CERT:
     505               0 :     nsrv = handleCACertDownload(array, ctx);
     506               0 :     break;
     507                 :   default:
     508                 :     // We only deal with import CA certs in this method currently.
     509               0 :      nsrv = NS_ERROR_FAILURE;
     510               0 :      break;
     511                 :   }  
     512               0 :   PORT_FreeArena(arena, false);
     513               0 :   return nsrv;
     514                 : }
     515                 : 
     516                 : 
     517                 : /*
     518                 :  *  [noscript] void importEmailCertificates(in charPtr data, in unsigned long length,
     519                 :  *                                     in nsIInterfaceRequestor ctx);
     520                 :  */
     521                 : NS_IMETHODIMP
     522               0 : nsNSSCertificateDB::ImportEmailCertificate(PRUint8 * data, PRUint32 length, 
     523                 :                                        nsIInterfaceRequestor *ctx)
     524                 : 
     525                 : {
     526               0 :   nsNSSShutDownPreventionLock locker;
     527               0 :   SECStatus srv = SECFailure;
     528               0 :   nsresult nsrv = NS_OK;
     529                 :   CERTCertDBHandle *certdb;
     530               0 :   CERTCertificate **certArray = NULL;
     531               0 :   CERTCertList *certList = NULL;
     532                 :   CERTCertListNode *node;
     533                 :   PRTime now;
     534                 :   SECCertUsage certusage;
     535                 :   SECCertificateUsage certificateusage;
     536                 :   SECItem **rawArray;
     537                 :   int numcerts;
     538                 :   int i;
     539                 :   CERTValOutParam cvout[1];
     540               0 :   cvout[0].type = cert_po_end;
     541                 : 
     542               0 :   nsCOMPtr<nsINSSComponent> inss = do_GetService(kNSSComponentCID, &nsrv);
     543               0 :   if (!inss)
     544               0 :     return nsrv;
     545               0 :   nsRefPtr<nsCERTValInParamWrapper> survivingParams;
     546               0 :   nsrv = inss->GetDefaultCERTValInParam(survivingParams);
     547               0 :   if (NS_FAILED(nsrv))
     548               0 :     return nsrv;
     549                 :  
     550               0 :   PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
     551               0 :   if (!arena)
     552               0 :     return NS_ERROR_OUT_OF_MEMORY;
     553                 : 
     554               0 :   CERTDERCerts *certCollection = getCertsFromPackage(arena, data, length);
     555               0 :   if (!certCollection) {
     556               0 :     PORT_FreeArena(arena, false);
     557               0 :     return NS_ERROR_FAILURE;
     558                 :   }
     559                 : 
     560               0 :   certdb = CERT_GetDefaultCertDB();
     561               0 :   certusage = certUsageEmailRecipient;
     562               0 :   certificateusage = certificateUsageEmailRecipient;
     563                 : 
     564               0 :   numcerts = certCollection->numcerts;
     565                 : 
     566               0 :   rawArray = (SECItem **) PORT_Alloc(sizeof(SECItem *) * numcerts);
     567               0 :   if ( !rawArray ) {
     568               0 :     nsrv = NS_ERROR_FAILURE;
     569               0 :     goto loser;
     570                 :   }
     571                 : 
     572               0 :   for (i=0; i < numcerts; i++) {
     573               0 :     rawArray[i] = &certCollection->rawCerts[i];
     574                 :   }
     575                 : 
     576                 :   srv = CERT_ImportCerts(certdb, certusage, numcerts, rawArray, 
     577               0 :                          &certArray, false, false, NULL);
     578                 : 
     579               0 :   PORT_Free(rawArray);
     580               0 :   rawArray = NULL;
     581                 : 
     582               0 :   if (srv != SECSuccess) {
     583               0 :     nsrv = NS_ERROR_FAILURE;
     584               0 :     goto loser;
     585                 :   }
     586                 : 
     587                 :   // build a CertList for filtering
     588               0 :   certList = CERT_NewCertList();
     589               0 :   if (certList == NULL) {
     590               0 :     nsrv = NS_ERROR_FAILURE;
     591               0 :     goto loser;
     592                 :   }
     593               0 :   for (i=0; i < numcerts; i++) {
     594               0 :     CERTCertificate *cert = certArray[i];
     595               0 :     if (cert)
     596               0 :       cert = CERT_DupCertificate(cert);
     597               0 :     if (cert)
     598               0 :       CERT_AddCertToListTail(certList, cert);
     599                 :   }
     600                 : 
     601                 :   /* go down the remaining list of certs and verify that they have
     602                 :    * valid chains, then import them.
     603                 :    */
     604               0 :   now = PR_Now();
     605                 : 
     606               0 :   for (node = CERT_LIST_HEAD(certList);
     607               0 :        !CERT_LIST_END(node,certList);
     608                 :        node = CERT_LIST_NEXT(node)) {
     609                 : 
     610               0 :     bool alert_and_skip = false;
     611                 : 
     612               0 :     if (!node->cert) {
     613               0 :       continue;
     614                 :     }
     615                 : 
     616               0 :     if (!nsNSSComponent::globalConstFlagUsePKIXVerification) {
     617               0 :       if (CERT_VerifyCert(certdb, node->cert,
     618               0 :           true, certusage, now, ctx, NULL) != SECSuccess) {
     619               0 :         alert_and_skip = true;
     620                 :       }
     621                 :     }
     622                 :     else {
     623               0 :       if (CERT_PKIXVerifyCert(node->cert, certificateusage,
     624                 :                               survivingParams->GetRawPointerForNSS(),
     625               0 :                               cvout, ctx)
     626                 :           != SECSuccess) {
     627               0 :         alert_and_skip = true;
     628                 :       }
     629                 :     }
     630                 : 
     631               0 :     CERTCertificateList *certChain = nsnull;
     632               0 :     CERTCertificateListCleaner chainCleaner(certChain);
     633                 : 
     634               0 :     if (!alert_and_skip) {
     635               0 :       certChain = CERT_CertChainFromCert(node->cert, certusage, false);
     636               0 :       if (!certChain) {
     637               0 :         alert_and_skip = true;
     638                 :       }
     639                 :     }
     640                 : 
     641               0 :     if (alert_and_skip) {    
     642               0 :       nsCOMPtr<nsIX509Cert> certToShow = nsNSSCertificate::Create(node->cert);
     643               0 :       DisplayCertificateAlert(ctx, "NotImportingUnverifiedCert", certToShow);
     644               0 :       continue;
     645                 :     }
     646                 : 
     647                 :     /*
     648                 :      * CertChain returns an array of SECItems, import expects an array of
     649                 :      * SECItem pointers. Create the SECItem Pointers from the array of
     650                 :      * SECItems.
     651                 :      */
     652               0 :     rawArray = (SECItem **) PORT_Alloc(certChain->len * sizeof(SECItem *));
     653               0 :     if (!rawArray) {
     654               0 :       continue;
     655                 :     }
     656               0 :     for (i=0; i < certChain->len; i++) {
     657               0 :       rawArray[i] = &certChain->certs[i];
     658                 :     }
     659                 :     CERT_ImportCerts(certdb, certusage, certChain->len, 
     660               0 :                             rawArray,  NULL, true, false, NULL);
     661                 : 
     662               0 :     CERT_SaveSMimeProfile(node->cert, NULL, NULL);
     663                 : 
     664               0 :     PORT_Free(rawArray);
     665                 :   }
     666                 : 
     667                 : loser:
     668               0 :   if (certArray) {
     669               0 :     CERT_DestroyCertArray(certArray, numcerts);
     670                 :   }
     671               0 :   if (certList) {
     672               0 :     CERT_DestroyCertList(certList);
     673                 :   }
     674               0 :   if (arena) 
     675               0 :     PORT_FreeArena(arena, true);
     676               0 :   return nsrv;
     677                 : }
     678                 : 
     679                 : NS_IMETHODIMP
     680               0 : nsNSSCertificateDB::ImportServerCertificate(PRUint8 * data, PRUint32 length, 
     681                 :                                             nsIInterfaceRequestor *ctx)
     682                 : 
     683                 : {
     684               0 :   nsNSSShutDownPreventionLock locker;
     685               0 :   SECStatus srv = SECFailure;
     686               0 :   nsresult nsrv = NS_OK;
     687                 :   CERTCertificate * cert;
     688               0 :   SECItem **rawCerts = nsnull;
     689                 :   int numcerts;
     690                 :   int i;
     691               0 :   nsNSSCertTrust trust;
     692               0 :   char *serverNickname = nsnull;
     693                 :  
     694               0 :   PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
     695               0 :   if (!arena)
     696               0 :     return NS_ERROR_OUT_OF_MEMORY;
     697                 : 
     698               0 :   CERTDERCerts *certCollection = getCertsFromPackage(arena, data, length);
     699               0 :   if (!certCollection) {
     700               0 :     PORT_FreeArena(arena, false);
     701               0 :     return NS_ERROR_FAILURE;
     702                 :   }
     703                 :   cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), certCollection->rawCerts,
     704               0 :                           (char *)NULL, false, true);
     705               0 :   if (!cert) {
     706               0 :     nsrv = NS_ERROR_FAILURE;
     707               0 :     goto loser;
     708                 :   }
     709               0 :   numcerts = certCollection->numcerts;
     710               0 :   rawCerts = (SECItem **) PORT_Alloc(sizeof(SECItem *) * numcerts);
     711               0 :   if ( !rawCerts ) {
     712               0 :     nsrv = NS_ERROR_FAILURE;
     713               0 :     goto loser;
     714                 :   }
     715                 : 
     716               0 :   for ( i = 0; i < numcerts; i++ ) {
     717               0 :     rawCerts[i] = &certCollection->rawCerts[i];
     718                 :   }
     719                 : 
     720               0 :   serverNickname = nsNSSCertificate::defaultServerNickname(cert);
     721                 :   srv = CERT_ImportCerts(CERT_GetDefaultCertDB(), certUsageSSLServer,
     722                 :              numcerts, rawCerts, NULL, true, false,
     723               0 :              serverNickname);
     724               0 :   PR_FREEIF(serverNickname);
     725               0 :   if ( srv != SECSuccess ) {
     726               0 :     nsrv = NS_ERROR_FAILURE;
     727               0 :     goto loser;
     728                 :   }
     729                 : 
     730               0 :   trust.SetValidServerPeer();
     731               0 :   srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), cert, trust.GetTrust());
     732               0 :   if ( srv != SECSuccess ) {
     733               0 :     nsrv = NS_ERROR_FAILURE;
     734               0 :     goto loser;
     735                 :   }
     736                 : loser:
     737               0 :   PORT_Free(rawCerts);
     738               0 :   if (cert)
     739               0 :     CERT_DestroyCertificate(cert);
     740               0 :   if (arena) 
     741               0 :     PORT_FreeArena(arena, true);
     742               0 :   return nsrv;
     743                 : }
     744                 : 
     745                 : nsresult
     746               0 : nsNSSCertificateDB::ImportValidCACerts(int numCACerts, SECItem *CACerts, nsIInterfaceRequestor *ctx)
     747                 : {
     748               0 :   CERTCertList *certList = NULL;
     749                 :   SECItem **rawArray;
     750                 : 
     751                 :   // build a CertList for filtering
     752               0 :   certList = CERT_NewCertList();
     753               0 :   if (certList == NULL) {
     754               0 :     return NS_ERROR_FAILURE;
     755                 :   }
     756                 : 
     757               0 :   CERTCertListCleaner listCleaner(certList);
     758                 : 
     759                 :   // get all certs into temp store
     760               0 :   SECStatus srv = SECFailure;
     761               0 :   CERTCertificate **certArray = NULL;
     762                 : 
     763               0 :   rawArray = (SECItem **) PORT_Alloc(sizeof(SECItem *) * numCACerts);
     764               0 :   if ( !rawArray ) {
     765               0 :     return NS_ERROR_FAILURE;
     766                 :   }
     767                 : 
     768               0 :   for (int i=0; i < numCACerts; i++) {
     769               0 :     rawArray[i] = &CACerts[i];
     770                 :   }
     771                 : 
     772                 :   srv = CERT_ImportCerts(CERT_GetDefaultCertDB(), certUsageAnyCA, numCACerts, rawArray, 
     773               0 :                          &certArray, false, true, NULL);
     774                 : 
     775               0 :   PORT_Free(rawArray);
     776               0 :   rawArray = NULL;
     777                 : 
     778               0 :   if (srv != SECSuccess) {
     779               0 :     return NS_ERROR_FAILURE;
     780                 :   }
     781                 : 
     782               0 :   for (int i2=0; i2 < numCACerts; i2++) {
     783               0 :     CERTCertificate *cacert = certArray[i2];
     784               0 :     if (cacert)
     785               0 :       cacert = CERT_DupCertificate(cacert);
     786               0 :     if (cacert)
     787               0 :       CERT_AddCertToListTail(certList, cacert);
     788                 :   }
     789                 : 
     790               0 :   CERT_DestroyCertArray(certArray, numCACerts);
     791                 : 
     792               0 :   return ImportValidCACertsInList(certList, ctx);
     793                 : }
     794                 : 
     795                 : nsresult
     796               0 : nsNSSCertificateDB::ImportValidCACertsInList(CERTCertList *certList, nsIInterfaceRequestor *ctx)
     797                 : {
     798                 :   SECItem **rawArray;
     799                 :   nsresult nsrv;
     800               0 :   nsCOMPtr<nsINSSComponent> inss = do_GetService(kNSSComponentCID, &nsrv);
     801               0 :   if (!inss)
     802               0 :     return nsrv;
     803               0 :   nsRefPtr<nsCERTValInParamWrapper> survivingParams;
     804               0 :   nsrv = inss->GetDefaultCERTValInParam(survivingParams);
     805               0 :   if (NS_FAILED(nsrv))
     806               0 :     return nsrv;
     807                 : 
     808                 :   /* filter out the certs we don't want */
     809               0 :   SECStatus srv = CERT_FilterCertListByUsage(certList, certUsageAnyCA, true);
     810               0 :   if (srv != SECSuccess) {
     811               0 :     return NS_ERROR_FAILURE;
     812                 :   }
     813                 : 
     814                 :   /* go down the remaining list of certs and verify that they have
     815                 :    * valid chains, if yes, then import.
     816                 :    */
     817                 :   CERTCertListNode *node;
     818                 :   CERTValOutParam cvout[1];
     819               0 :   cvout[0].type = cert_po_end;
     820                 : 
     821               0 :   for (node = CERT_LIST_HEAD(certList);
     822               0 :        !CERT_LIST_END(node,certList);
     823                 :        node = CERT_LIST_NEXT(node)) {
     824                 : 
     825               0 :     bool alert_and_skip = false;
     826                 : 
     827               0 :     if (!nsNSSComponent::globalConstFlagUsePKIXVerification) {
     828               0 :       if (CERT_VerifyCert(CERT_GetDefaultCertDB(), node->cert, 
     829               0 :           true, certUsageVerifyCA, PR_Now(), ctx, NULL) != SECSuccess) {
     830               0 :         alert_and_skip = true;
     831                 :       }
     832                 :     }
     833                 :     else {
     834               0 :       if (CERT_PKIXVerifyCert(node->cert, certificateUsageVerifyCA,
     835                 :                               survivingParams->GetRawPointerForNSS(),
     836               0 :                               cvout, ctx)
     837                 :           != SECSuccess) {
     838               0 :         alert_and_skip = true;
     839                 :       }
     840                 :     }
     841                 : 
     842               0 :     CERTCertificateList *certChain = nsnull;
     843               0 :     CERTCertificateListCleaner chainCleaner(certChain);
     844                 : 
     845               0 :     if (!alert_and_skip) {    
     846               0 :       certChain = CERT_CertChainFromCert(node->cert, certUsageAnyCA, false);
     847               0 :       if (!certChain) {
     848               0 :         alert_and_skip = true;
     849                 :       }
     850                 :     }
     851                 : 
     852               0 :     if (alert_and_skip) {    
     853               0 :       nsCOMPtr<nsIX509Cert> certToShow = nsNSSCertificate::Create(node->cert);
     854               0 :       DisplayCertificateAlert(ctx, "NotImportingUnverifiedCert", certToShow);
     855               0 :       continue;
     856                 :     }
     857                 : 
     858                 :     /*
     859                 :      * CertChain returns an array of SECItems, import expects an array of
     860                 :      * SECItem pointers. Create the SECItem Pointers from the array of
     861                 :      * SECItems.
     862                 :      */
     863               0 :     rawArray = (SECItem **) PORT_Alloc(certChain->len * sizeof(SECItem *));
     864               0 :     if (!rawArray) {
     865               0 :       continue;
     866                 :     }
     867               0 :     for (int i=0; i < certChain->len; i++) {
     868               0 :       rawArray[i] = &certChain->certs[i];
     869                 :     }
     870                 :     CERT_ImportCerts(CERT_GetDefaultCertDB(), certUsageAnyCA, certChain->len, 
     871               0 :                             rawArray,  NULL, true, true, NULL);
     872                 : 
     873               0 :     PORT_Free(rawArray);
     874                 :   }
     875                 :   
     876               0 :   return NS_OK;
     877                 : }
     878                 : 
     879               0 : void nsNSSCertificateDB::DisplayCertificateAlert(nsIInterfaceRequestor *ctx, 
     880                 :                                                  const char *stringID, 
     881                 :                                                  nsIX509Cert *certToShow)
     882                 : {
     883               0 :   if (!NS_IsMainThread()) {
     884               0 :     NS_ERROR("nsNSSCertificateDB::DisplayCertificateAlert called off the main thread");
     885               0 :     return;
     886                 :   }
     887                 : 
     888               0 :   nsPSMUITracker tracker;
     889               0 :   if (!tracker.isUIForbidden()) {
     890                 : 
     891               0 :     nsCOMPtr<nsIInterfaceRequestor> my_ctx = ctx;
     892               0 :     if (!my_ctx)
     893               0 :       my_ctx = new PipUIContext();
     894                 : 
     895                 :     // This shall be replaced by embedding ovverridable prompts
     896                 :     // as discussed in bug 310446, and should make use of certToShow.
     897                 : 
     898                 :     nsresult rv;
     899               0 :     nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
     900               0 :     if (NS_SUCCEEDED(rv)) {
     901               0 :       nsAutoString tmpMessage;
     902               0 :       nssComponent->GetPIPNSSBundleString(stringID, tmpMessage);
     903                 : 
     904               0 :       nsCOMPtr<nsIPrompt> prompt (do_GetInterface(my_ctx));
     905               0 :       if (!prompt)
     906                 :         return;
     907                 :     
     908               0 :       prompt->Alert(nsnull, tmpMessage.get());
     909                 :     }
     910                 :   }
     911                 : }
     912                 : 
     913                 : 
     914                 : NS_IMETHODIMP 
     915               0 : nsNSSCertificateDB::ImportUserCertificate(PRUint8 *data, PRUint32 length, nsIInterfaceRequestor *ctx)
     916                 : {
     917               0 :   if (!NS_IsMainThread()) {
     918               0 :     NS_ERROR("nsNSSCertificateDB::ImportUserCertificate called off the main thread");
     919               0 :     return NS_ERROR_NOT_SAME_THREAD;
     920                 :   }
     921                 :   
     922               0 :   nsNSSShutDownPreventionLock locker;
     923                 :   PK11SlotInfo *slot;
     924               0 :   nsCAutoString nickname;
     925               0 :   nsresult rv = NS_ERROR_FAILURE;
     926                 :   int numCACerts;
     927                 :   SECItem *CACerts;
     928                 :   CERTDERCerts * collectArgs;
     929                 :   PRArenaPool *arena;
     930               0 :   CERTCertificate * cert=NULL;
     931                 : 
     932               0 :   arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
     933               0 :   if ( arena == NULL ) {
     934               0 :     goto loser;
     935                 :   }
     936                 : 
     937               0 :   collectArgs = getCertsFromPackage(arena, data, length);
     938               0 :   if (!collectArgs) {
     939               0 :     goto loser;
     940                 :   }
     941                 : 
     942                 :   cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), collectArgs->rawCerts,
     943               0 :                                (char *)NULL, false, true);
     944               0 :   if (!cert) {
     945               0 :     goto loser;
     946                 :   }
     947                 : 
     948               0 :   slot = PK11_KeyForCertExists(cert, NULL, ctx);
     949               0 :   if ( slot == NULL ) {
     950               0 :     nsCOMPtr<nsIX509Cert> certToShow = nsNSSCertificate::Create(cert);
     951               0 :     DisplayCertificateAlert(ctx, "UserCertIgnoredNoPrivateKey", certToShow);
     952                 :     goto loser;
     953                 :   }
     954               0 :   PK11_FreeSlot(slot);
     955                 : 
     956                 :   /* pick a nickname for the cert */
     957               0 :   if (cert->nickname) {
     958                 :         /* sigh, we need a call to look up other certs with this subject and
     959                 :          * identify nicknames from them. We can no longer walk down internal
     960                 :          * database structures  rjr */
     961               0 :         nickname = cert->nickname;
     962                 :   }
     963                 :   else {
     964               0 :     get_default_nickname(cert, ctx, nickname);
     965                 :   }
     966                 : 
     967                 :   /* user wants to import the cert */
     968                 :   {
     969               0 :     char *cast_const_away = const_cast<char*>(nickname.get());
     970               0 :     slot = PK11_ImportCertForKey(cert, cast_const_away, ctx);
     971                 :   }
     972               0 :   if (!slot) {
     973               0 :     goto loser;
     974                 :   }
     975               0 :   PK11_FreeSlot(slot);
     976                 : 
     977                 :   {
     978               0 :     nsCOMPtr<nsIX509Cert> certToShow = nsNSSCertificate::Create(cert);
     979               0 :     DisplayCertificateAlert(ctx, "UserCertImported", certToShow);
     980                 :   }
     981               0 :   rv = NS_OK;
     982                 : 
     983               0 :   numCACerts = collectArgs->numcerts - 1;
     984               0 :   if (numCACerts) {
     985               0 :     CACerts = collectArgs->rawCerts+1;
     986               0 :     rv = ImportValidCACerts(numCACerts, CACerts, ctx);
     987                 :   }
     988                 :   
     989                 : loser:
     990               0 :   if (arena) {
     991               0 :     PORT_FreeArena(arena, false);
     992                 :   }
     993               0 :   if ( cert ) {
     994               0 :     CERT_DestroyCertificate(cert);
     995                 :   }
     996               0 :   return rv;
     997                 : }
     998                 : 
     999                 : /*
    1000                 :  * void deleteCertificate(in nsIX509Cert aCert);
    1001                 :  */
    1002                 : NS_IMETHODIMP 
    1003               0 : nsNSSCertificateDB::DeleteCertificate(nsIX509Cert *aCert)
    1004                 : {
    1005               0 :   nsNSSShutDownPreventionLock locker;
    1006               0 :   nsCOMPtr<nsIX509Cert2> nssCert = do_QueryInterface(aCert);
    1007               0 :   CERTCertificate *cert = nssCert->GetCert();
    1008               0 :   if (!cert) return NS_ERROR_FAILURE;
    1009               0 :   CERTCertificateCleaner certCleaner(cert);
    1010               0 :   SECStatus srv = SECSuccess;
    1011                 : 
    1012                 :   PRUint32 certType;
    1013               0 :   nssCert->GetCertType(&certType);
    1014               0 :   if (NS_FAILED(nssCert->MarkForPermDeletion()))
    1015                 :   {
    1016               0 :     return NS_ERROR_FAILURE;
    1017                 :   }
    1018                 : 
    1019               0 :   if (cert->slot && certType != nsIX509Cert::USER_CERT) {
    1020                 :     // To delete a cert of a slot (builtin, most likely), mark it as
    1021                 :     // completely untrusted.  This way we keep a copy cached in the
    1022                 :     // local database, and next time we try to load it off of the 
    1023                 :     // external token/slot, we'll know not to trust it.  We don't 
    1024                 :     // want to do that with user certs, because a user may  re-store
    1025                 :     // the cert onto the card again at which point we *will* want to 
    1026                 :     // trust that cert if it chains up properly.
    1027               0 :     nsNSSCertTrust trust(0, 0, 0);
    1028                 :     srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), 
    1029               0 :                                cert, trust.GetTrust());
    1030                 :   }
    1031               0 :   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("cert deleted: %d", srv));
    1032               0 :   return (srv) ? NS_ERROR_FAILURE : NS_OK;
    1033                 : }
    1034                 : 
    1035                 : /*
    1036                 :  * void setCertTrust(in nsIX509Cert cert,
    1037                 :  *                   in unsigned long type,
    1038                 :  *                   in unsigned long trust);
    1039                 :  */
    1040                 : NS_IMETHODIMP 
    1041               0 : nsNSSCertificateDB::SetCertTrust(nsIX509Cert *cert, 
    1042                 :                                  PRUint32 type,
    1043                 :                                  PRUint32 trusted)
    1044                 : {
    1045               0 :   nsNSSShutDownPreventionLock locker;
    1046                 :   SECStatus srv;
    1047               0 :   nsNSSCertTrust trust;
    1048               0 :   nsCOMPtr<nsIX509Cert2> pipCert = do_QueryInterface(cert);
    1049               0 :   if (!pipCert)
    1050               0 :     return NS_ERROR_FAILURE;
    1051               0 :   CERTCertificate *nsscert = pipCert->GetCert();
    1052               0 :   CERTCertificateCleaner certCleaner(nsscert);
    1053               0 :   if (type == nsIX509Cert::CA_CERT) {
    1054                 :     // always start with untrusted and move up
    1055               0 :     trust.SetValidCA();
    1056                 :     trust.AddCATrust(!!(trusted & nsIX509CertDB::TRUSTED_SSL),
    1057                 :                      !!(trusted & nsIX509CertDB::TRUSTED_EMAIL),
    1058               0 :                      !!(trusted & nsIX509CertDB::TRUSTED_OBJSIGN));
    1059                 :     srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), 
    1060                 :                                nsscert,
    1061               0 :                                trust.GetTrust());
    1062               0 :   } else if (type == nsIX509Cert::SERVER_CERT) {
    1063                 :     // always start with untrusted and move up
    1064               0 :     trust.SetValidPeer();
    1065               0 :     trust.AddPeerTrust(trusted & nsIX509CertDB::TRUSTED_SSL, 0, 0);
    1066                 :     srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), 
    1067                 :                                nsscert,
    1068               0 :                                trust.GetTrust());
    1069               0 :   } else if (type == nsIX509Cert::EMAIL_CERT) {
    1070                 :     // always start with untrusted and move up
    1071               0 :     trust.SetValidPeer();
    1072               0 :     trust.AddPeerTrust(0, !!(trusted & nsIX509CertDB::TRUSTED_EMAIL), 0);
    1073                 :     srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), 
    1074                 :                                nsscert,
    1075               0 :                                trust.GetTrust());
    1076                 :   } else {
    1077                 :     // ignore user certs
    1078               0 :     return NS_OK;
    1079                 :   }
    1080               0 :   return (srv) ? NS_ERROR_FAILURE : NS_OK;
    1081                 : }
    1082                 : 
    1083                 : NS_IMETHODIMP 
    1084               0 : nsNSSCertificateDB::IsCertTrusted(nsIX509Cert *cert, 
    1085                 :                                   PRUint32 certType,
    1086                 :                                   PRUint32 trustType,
    1087                 :                                   bool *_isTrusted)
    1088                 : {
    1089               0 :   NS_ENSURE_ARG_POINTER(_isTrusted);
    1090               0 :   *_isTrusted = false;
    1091                 : 
    1092               0 :   nsNSSShutDownPreventionLock locker;
    1093                 :   SECStatus srv;
    1094               0 :   nsCOMPtr<nsIX509Cert2> pipCert = do_QueryInterface(cert);
    1095               0 :   CERTCertificate *nsscert = pipCert->GetCert();
    1096                 :   CERTCertTrust nsstrust;
    1097               0 :   srv = CERT_GetCertTrust(nsscert, &nsstrust);
    1098               0 :   if (srv != SECSuccess)
    1099               0 :     return NS_ERROR_FAILURE;
    1100                 : 
    1101               0 :   nsNSSCertTrust trust(&nsstrust);
    1102               0 :   CERT_DestroyCertificate(nsscert);
    1103               0 :   if (certType == nsIX509Cert::CA_CERT) {
    1104               0 :     if (trustType & nsIX509CertDB::TRUSTED_SSL) {
    1105               0 :       *_isTrusted = trust.HasTrustedCA(true, false, false);
    1106               0 :     } else if (trustType & nsIX509CertDB::TRUSTED_EMAIL) {
    1107               0 :       *_isTrusted = trust.HasTrustedCA(false, true, false);
    1108               0 :     } else if (trustType & nsIX509CertDB::TRUSTED_OBJSIGN) {
    1109               0 :       *_isTrusted = trust.HasTrustedCA(false, false, true);
    1110                 :     } else {
    1111               0 :       return NS_ERROR_FAILURE;
    1112                 :     }
    1113               0 :   } else if (certType == nsIX509Cert::SERVER_CERT) {
    1114               0 :     if (trustType & nsIX509CertDB::TRUSTED_SSL) {
    1115               0 :       *_isTrusted = trust.HasTrustedPeer(true, false, false);
    1116               0 :     } else if (trustType & nsIX509CertDB::TRUSTED_EMAIL) {
    1117               0 :       *_isTrusted = trust.HasTrustedPeer(false, true, false);
    1118               0 :     } else if (trustType & nsIX509CertDB::TRUSTED_OBJSIGN) {
    1119               0 :       *_isTrusted = trust.HasTrustedPeer(false, false, true);
    1120                 :     } else {
    1121               0 :       return NS_ERROR_FAILURE;
    1122                 :     }
    1123               0 :   } else if (certType == nsIX509Cert::EMAIL_CERT) {
    1124               0 :     if (trustType & nsIX509CertDB::TRUSTED_SSL) {
    1125               0 :       *_isTrusted = trust.HasTrustedPeer(true, false, false);
    1126               0 :     } else if (trustType & nsIX509CertDB::TRUSTED_EMAIL) {
    1127               0 :       *_isTrusted = trust.HasTrustedPeer(false, true, false);
    1128               0 :     } else if (trustType & nsIX509CertDB::TRUSTED_OBJSIGN) {
    1129               0 :       *_isTrusted = trust.HasTrustedPeer(false, false, true);
    1130                 :     } else {
    1131               0 :       return NS_ERROR_FAILURE;
    1132                 :     }
    1133                 :   } /* user: ignore */
    1134               0 :   return NS_OK;
    1135                 : }
    1136                 : 
    1137                 : 
    1138                 : NS_IMETHODIMP 
    1139               0 : nsNSSCertificateDB::ImportCertsFromFile(nsISupports *aToken, 
    1140                 :                                         nsILocalFile *aFile,
    1141                 :                                         PRUint32 aType)
    1142                 : {
    1143               0 :   NS_ENSURE_ARG(aFile);
    1144               0 :   switch (aType) {
    1145                 :     case nsIX509Cert::CA_CERT:
    1146                 :     case nsIX509Cert::EMAIL_CERT:
    1147                 :     case nsIX509Cert::SERVER_CERT:
    1148                 :       // good
    1149                 :       break;
    1150                 :     
    1151                 :     default:
    1152                 :       // not supported (yet)
    1153               0 :       return NS_ERROR_FAILURE;
    1154                 :   }
    1155                 : 
    1156                 :   nsresult rv;
    1157               0 :   PRFileDesc *fd = nsnull;
    1158                 : 
    1159               0 :   rv = aFile->OpenNSPRFileDesc(PR_RDONLY, 0, &fd);
    1160                 : 
    1161               0 :   if (NS_FAILED(rv))
    1162               0 :     return rv;
    1163                 : 
    1164               0 :   if (!fd)
    1165               0 :     return NS_ERROR_FAILURE;
    1166                 : 
    1167                 :   PRFileInfo file_info;
    1168               0 :   if (PR_SUCCESS != PR_GetOpenFileInfo(fd, &file_info))
    1169               0 :     return NS_ERROR_FAILURE;
    1170                 :   
    1171               0 :   unsigned char *buf = new unsigned char[file_info.size];
    1172               0 :   if (!buf)
    1173               0 :     return NS_ERROR_OUT_OF_MEMORY;
    1174                 :   
    1175               0 :   PRInt32 bytes_obtained = PR_Read(fd, buf, file_info.size);
    1176               0 :   PR_Close(fd);
    1177                 :   
    1178               0 :   if (bytes_obtained != file_info.size)
    1179               0 :     rv = NS_ERROR_FAILURE;
    1180                 :   else {
    1181               0 :           nsCOMPtr<nsIInterfaceRequestor> cxt = new PipUIContext();
    1182                 : 
    1183               0 :     switch (aType) {
    1184                 :       case nsIX509Cert::CA_CERT:
    1185               0 :         rv = ImportCertificates(buf, bytes_obtained, aType, cxt);
    1186               0 :         break;
    1187                 :         
    1188                 :       case nsIX509Cert::SERVER_CERT:
    1189               0 :         rv = ImportServerCertificate(buf, bytes_obtained, cxt);
    1190               0 :         break;
    1191                 : 
    1192                 :       case nsIX509Cert::EMAIL_CERT:
    1193               0 :         rv = ImportEmailCertificate(buf, bytes_obtained, cxt);
    1194               0 :         break;
    1195                 :       
    1196                 :       default:
    1197               0 :         break;
    1198                 :     }
    1199                 :   }
    1200                 : 
    1201               0 :   delete [] buf;
    1202               0 :   return rv;  
    1203                 : }
    1204                 : 
    1205                 : NS_IMETHODIMP 
    1206               0 : nsNSSCertificateDB::ImportPKCS12File(nsISupports *aToken, 
    1207                 :                                      nsILocalFile *aFile)
    1208                 : {
    1209               0 :   NS_ENSURE_ARG(aFile);
    1210               0 :   nsPKCS12Blob blob;
    1211               0 :   nsCOMPtr<nsIPK11Token> token = do_QueryInterface(aToken);
    1212               0 :   if (token) {
    1213               0 :     blob.SetToken(token);
    1214                 :   }
    1215               0 :   return blob.ImportFromFile(aFile);
    1216                 : }
    1217                 : 
    1218                 : NS_IMETHODIMP 
    1219               0 : nsNSSCertificateDB::ExportPKCS12File(nsISupports     *aToken, 
    1220                 :                                      nsILocalFile     *aFile,
    1221                 :                                      PRUint32          count,
    1222                 :                                      nsIX509Cert     **certs)
    1223                 :                                      //const PRUnichar **aCertNames)
    1224                 : {
    1225               0 :   nsNSSShutDownPreventionLock locker;
    1226               0 :   NS_ENSURE_ARG(aFile);
    1227               0 :   nsPKCS12Blob blob;
    1228               0 :   if (count == 0) return NS_OK;
    1229               0 :   nsCOMPtr<nsIPK11Token> localRef;
    1230               0 :   if (!aToken) {
    1231               0 :     PK11SlotInfo *keySlot = PK11_GetInternalKeySlot();
    1232               0 :     NS_ASSERTION(keySlot,"Failed to get the internal key slot");
    1233               0 :     localRef = new nsPK11Token(keySlot);
    1234               0 :     PK11_FreeSlot(keySlot);
    1235                 :   }
    1236                 :   else {
    1237               0 :     localRef = do_QueryInterface(aToken);
    1238                 :   }
    1239               0 :   blob.SetToken(localRef);
    1240                 :   //blob.LoadCerts(aCertNames, count);
    1241                 :   //return blob.ExportToFile(aFile);
    1242               0 :   return blob.ExportToFile(aFile, certs, count);
    1243                 : }
    1244                 : 
    1245                 : 
    1246                 : static SECStatus PR_CALLBACK 
    1247               0 : GetOCSPResponders (CERTCertificate *aCert,
    1248                 :                    SECItem         *aDBKey,
    1249                 :                    void            *aArg)
    1250                 : {
    1251               0 :   nsIMutableArray *array = static_cast<nsIMutableArray*>(aArg);
    1252               0 :   PRUnichar* nn = nsnull;
    1253               0 :   PRUnichar* url = nsnull;
    1254               0 :   char *serviceURL = nsnull;
    1255               0 :   char *nickname = nsnull;
    1256                 :   PRUint32 i, count;
    1257                 : 
    1258                 :   // Are we interested in this cert //
    1259               0 :   if (!nsOCSPResponder::IncludeCert(aCert)) {
    1260               0 :     return SECSuccess;
    1261                 :   }
    1262                 : 
    1263                 :   // Get the AIA and nickname //
    1264               0 :   serviceURL = CERT_GetOCSPAuthorityInfoAccessLocation(aCert);
    1265               0 :   if (serviceURL) {
    1266               0 :     url = ToNewUnicode(NS_ConvertUTF8toUTF16(serviceURL));
    1267               0 :     PORT_Free(serviceURL);
    1268                 :   }
    1269                 : 
    1270               0 :   nickname = aCert->nickname;
    1271               0 :   nn = ToNewUnicode(NS_ConvertUTF8toUTF16(nickname));
    1272                 : 
    1273               0 :   nsCOMPtr<nsIOCSPResponder> new_entry = new nsOCSPResponder(nn, url);
    1274               0 :   nsMemory::Free(nn);
    1275               0 :   nsMemory::Free(url);
    1276                 : 
    1277                 :   // Sort the items according to nickname //
    1278               0 :   array->GetLength(&count);
    1279               0 :   for (i=0; i < count; ++i) {
    1280               0 :     nsCOMPtr<nsIOCSPResponder> entry = do_QueryElementAt(array, i);
    1281               0 :     if (nsOCSPResponder::CompareEntries(new_entry, entry) < 0) {
    1282               0 :       array->InsertElementAt(new_entry, i, false);
    1283                 :       break;
    1284                 :     }
    1285                 :   }
    1286               0 :   if (i == count) {
    1287               0 :     array->AppendElement(new_entry, false);
    1288                 :   }
    1289               0 :   return SECSuccess;
    1290                 : }
    1291                 : 
    1292                 : 
    1293                 : 
    1294                 : /*
    1295                 :  * getOCSPResponders
    1296                 :  *
    1297                 :  * Export a set of certs and keys from the database to a PKCS#12 file.
    1298                 : */
    1299                 : NS_IMETHODIMP 
    1300               0 : nsNSSCertificateDB::GetOCSPResponders(nsIArray ** aResponders)
    1301                 : {
    1302               0 :   nsNSSShutDownPreventionLock locker;
    1303                 :   SECStatus sec_rv;
    1304                 :   nsCOMPtr<nsIMutableArray> respondersArray =
    1305               0 :     do_CreateInstance(NS_ARRAY_CONTRACTID);
    1306               0 :   if (!respondersArray) {
    1307               0 :     return NS_ERROR_OUT_OF_MEMORY;
    1308                 :   }
    1309                 : 
    1310                 :   sec_rv = PK11_TraverseSlotCerts(::GetOCSPResponders,
    1311                 :                                   respondersArray,
    1312               0 :                                   nsnull);
    1313               0 :   if (sec_rv != SECSuccess) {
    1314               0 :     goto loser;
    1315                 :   }
    1316                 : 
    1317               0 :   *aResponders = respondersArray;
    1318               0 :   NS_IF_ADDREF(*aResponders);
    1319               0 :   return NS_OK;
    1320                 : loser:
    1321               0 :   return NS_ERROR_FAILURE;
    1322                 : }
    1323                 : 
    1324                 : /*
    1325                 :  * NSS Helper Routines (private to nsNSSCertificateDB)
    1326                 :  */
    1327                 : 
    1328                 : #define DELIM '\001'
    1329                 : 
    1330                 : /*
    1331                 :  * GetSortedNameList
    1332                 :  *
    1333                 :  * Converts a CERTCertList to a list of certificate names
    1334                 :  */
    1335                 : void
    1336               0 : nsNSSCertificateDB::getCertNames(CERTCertList *certList,
    1337                 :                                  PRUint32      type, 
    1338                 :                                  PRUint32     *_count,
    1339                 :                                  PRUnichar  ***_certNames)
    1340                 : {
    1341               0 :   nsNSSShutDownPreventionLock locker;
    1342                 :   CERTCertListNode *node;
    1343               0 :   PRUint32 numcerts = 0, i=0;
    1344               0 :   PRUnichar **tmpArray = NULL;
    1345               0 :   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("List of certs %d:\n", type));
    1346               0 :   for (node = CERT_LIST_HEAD(certList);
    1347               0 :        !CERT_LIST_END(node, certList);
    1348                 :        node = CERT_LIST_NEXT(node)) {
    1349               0 :     if (getCertType(node->cert) == type) {
    1350               0 :       numcerts++;
    1351                 :     }
    1352                 :   }
    1353               0 :   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("num certs: %d\n", numcerts));
    1354               0 :   int nc = (numcerts == 0) ? 1 : numcerts;
    1355               0 :   tmpArray = (PRUnichar **)nsMemory::Alloc(sizeof(PRUnichar *) * nc);
    1356               0 :   if (numcerts == 0) goto finish;
    1357               0 :   for (node = CERT_LIST_HEAD(certList);
    1358               0 :        !CERT_LIST_END(node, certList);
    1359                 :        node = CERT_LIST_NEXT(node)) {
    1360               0 :     if (getCertType(node->cert) == type) {
    1361               0 :       nsNSSCertificate pipCert(node->cert);
    1362               0 :       char *dbkey = NULL;
    1363               0 :       char *namestr = NULL;
    1364               0 :       nsAutoString certstr;
    1365               0 :       pipCert.GetDbKey(&dbkey);
    1366               0 :       nsAutoString keystr = NS_ConvertASCIItoUTF16(dbkey);
    1367               0 :       PR_FREEIF(dbkey);
    1368               0 :       if (type == nsIX509Cert::EMAIL_CERT) {
    1369               0 :         namestr = node->cert->emailAddr;
    1370                 :       } else {
    1371               0 :         namestr = node->cert->nickname;
    1372               0 :         if (namestr) {
    1373               0 :           char *sc = strchr(namestr, ':');
    1374               0 :           if (sc) *sc = DELIM;
    1375                 :         }
    1376                 :       }
    1377               0 :       nsAutoString certname = NS_ConvertASCIItoUTF16(namestr ? namestr : "");
    1378               0 :       certstr.Append(PRUnichar(DELIM));
    1379               0 :       certstr += certname;
    1380               0 :       certstr.Append(PRUnichar(DELIM));
    1381               0 :       certstr += keystr;
    1382               0 :       tmpArray[i++] = ToNewUnicode(certstr);
    1383                 :     }
    1384                 :   }
    1385                 : finish:
    1386               0 :   *_count = numcerts;
    1387               0 :   *_certNames = tmpArray;
    1388               0 : }
    1389                 : 
    1390                 : /* somewhat follows logic of cert_list_include_cert from PSM 1.x */
    1391                 : 
    1392                 : 
    1393                 : NS_IMETHODIMP 
    1394               4 : nsNSSCertificateDB::GetIsOcspOn(bool *aOcspOn)
    1395                 : {
    1396               8 :   nsCOMPtr<nsIPrefBranch> pref = do_GetService(NS_PREFSERVICE_CONTRACTID);
    1397                 : 
    1398                 :   PRInt32 ocspEnabled;
    1399               4 :   pref->GetIntPref("security.OCSP.enabled", &ocspEnabled);
    1400               4 :   *aOcspOn = ( ocspEnabled == 0 ) ? false : true; 
    1401               4 :   return NS_OK;
    1402                 : }
    1403                 : 
    1404                 : /* nsIX509Cert getDefaultEmailEncryptionCert (); */
    1405                 : NS_IMETHODIMP
    1406               0 : nsNSSCertificateDB::FindEmailEncryptionCert(const nsAString &aNickname, nsIX509Cert **_retval)
    1407                 : {
    1408               0 :   if (!_retval)
    1409               0 :     return NS_ERROR_FAILURE;
    1410                 : 
    1411               0 :   *_retval = 0;
    1412                 : 
    1413               0 :   if (aNickname.IsEmpty())
    1414               0 :     return NS_OK;
    1415                 : 
    1416               0 :   nsNSSShutDownPreventionLock locker;
    1417               0 :   nsresult rv = NS_OK;
    1418               0 :   CERTCertificate *cert = 0;
    1419               0 :   nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
    1420               0 :   nsNSSCertificate *nssCert = nsnull;
    1421               0 :   char *asciiname = NULL;
    1422               0 :   NS_ConvertUTF16toUTF8 aUtf8Nickname(aNickname);
    1423               0 :   asciiname = const_cast<char*>(aUtf8Nickname.get());
    1424                 : 
    1425                 :   /* Find a good cert in the user's database */
    1426                 :   cert = CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(), asciiname, 
    1427               0 :            certUsageEmailRecipient, true, ctx);
    1428                 : 
    1429               0 :   if (!cert) { goto loser; }  
    1430                 : 
    1431               0 :   nssCert = nsNSSCertificate::Create(cert);
    1432               0 :   if (nssCert == nsnull) {
    1433               0 :     rv = NS_ERROR_OUT_OF_MEMORY;
    1434                 :   }
    1435               0 :   NS_ADDREF(nssCert);
    1436                 : 
    1437               0 :   *_retval = static_cast<nsIX509Cert*>(nssCert);
    1438                 : 
    1439                 : loser:
    1440               0 :   if (cert) CERT_DestroyCertificate(cert);
    1441               0 :   return rv;
    1442                 : }
    1443                 : 
    1444                 : /* nsIX509Cert getDefaultEmailSigningCert (); */
    1445                 : NS_IMETHODIMP
    1446               0 : nsNSSCertificateDB::FindEmailSigningCert(const nsAString &aNickname, nsIX509Cert **_retval)
    1447                 : {
    1448               0 :   if (!_retval)
    1449               0 :     return NS_ERROR_FAILURE;
    1450                 : 
    1451               0 :   *_retval = 0;
    1452                 : 
    1453               0 :   if (aNickname.IsEmpty())
    1454               0 :     return NS_OK;
    1455                 : 
    1456               0 :   nsNSSShutDownPreventionLock locker;
    1457               0 :   nsresult rv = NS_OK;
    1458               0 :   CERTCertificate *cert = 0;
    1459               0 :   nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
    1460               0 :   nsNSSCertificate *nssCert = nsnull;
    1461               0 :   char *asciiname = NULL;
    1462               0 :   NS_ConvertUTF16toUTF8 aUtf8Nickname(aNickname);
    1463               0 :   asciiname = const_cast<char*>(aUtf8Nickname.get());
    1464                 : 
    1465                 :   /* Find a good cert in the user's database */
    1466                 :   cert = CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(), asciiname, 
    1467               0 :            certUsageEmailSigner, true, ctx);
    1468                 : 
    1469               0 :   if (!cert) { goto loser; }  
    1470                 : 
    1471               0 :   nssCert = nsNSSCertificate::Create(cert);
    1472               0 :   if (nssCert == nsnull) {
    1473               0 :     rv = NS_ERROR_OUT_OF_MEMORY;
    1474                 :   }
    1475               0 :   NS_ADDREF(nssCert);
    1476                 : 
    1477               0 :   *_retval = static_cast<nsIX509Cert*>(nssCert);
    1478                 : 
    1479                 : loser:
    1480               0 :   if (cert) CERT_DestroyCertificate(cert);
    1481               0 :   return rv;
    1482                 : }
    1483                 : 
    1484                 : NS_IMETHODIMP
    1485               0 : nsNSSCertificateDB::FindCertByEmailAddress(nsISupports *aToken, const char *aEmailAddress, nsIX509Cert **_retval)
    1486                 : {
    1487               0 :   nsNSSShutDownPreventionLock locker;
    1488                 :   
    1489               0 :   nsCOMPtr<nsINSSComponent> inss;
    1490               0 :   nsRefPtr<nsCERTValInParamWrapper> survivingParams;
    1491                 :   nsresult nsrv;
    1492                 :   
    1493               0 :   if (nsNSSComponent::globalConstFlagUsePKIXVerification) {
    1494               0 :     inss = do_GetService(kNSSComponentCID, &nsrv);
    1495               0 :     if (!inss)
    1496               0 :       return nsrv;
    1497               0 :     nsrv = inss->GetDefaultCERTValInParam(survivingParams);
    1498               0 :     if (NS_FAILED(nsrv))
    1499               0 :       return nsrv;
    1500                 :   }
    1501                 : 
    1502               0 :   CERTCertList *certlist = PK11_FindCertsFromEmailAddress(aEmailAddress, nsnull);
    1503               0 :   if (!certlist)
    1504               0 :     return NS_ERROR_FAILURE;  
    1505                 : 
    1506                 :   // certlist now contains certificates with the right email address,
    1507                 :   // but they might not have the correct usage or might even be invalid
    1508                 : 
    1509               0 :   CERTCertListCleaner listCleaner(certlist);
    1510                 : 
    1511               0 :   if (CERT_LIST_END(CERT_LIST_HEAD(certlist), certlist))
    1512               0 :     return NS_ERROR_FAILURE; // no certs found
    1513                 : 
    1514                 :   CERTCertListNode *node;
    1515                 :   // search for a valid certificate
    1516               0 :   for (node = CERT_LIST_HEAD(certlist);
    1517               0 :        !CERT_LIST_END(node, certlist);
    1518                 :        node = CERT_LIST_NEXT(node)) {
    1519                 : 
    1520               0 :     if (!nsNSSComponent::globalConstFlagUsePKIXVerification) {
    1521               0 :       if (CERT_VerifyCert(CERT_GetDefaultCertDB(), node->cert,
    1522               0 :           true, certUsageEmailRecipient, PR_Now(), nsnull, nsnull) == SECSuccess) {
    1523                 :         // found a valid certificate
    1524               0 :         break;
    1525                 :       }
    1526                 :     }
    1527                 :     else {
    1528                 :       CERTValOutParam cvout[1];
    1529               0 :       cvout[0].type = cert_po_end;
    1530               0 :       if (CERT_PKIXVerifyCert(node->cert, certificateUsageEmailRecipient,
    1531                 :                               survivingParams->GetRawPointerForNSS(),
    1532               0 :                               cvout, nsnull)
    1533                 :           == SECSuccess) {
    1534                 :         // found a valid certificate
    1535               0 :         break;
    1536                 :       }
    1537                 :     }
    1538                 :   }
    1539                 : 
    1540               0 :   if (CERT_LIST_END(node, certlist)) {
    1541                 :     // no valid cert found
    1542               0 :     return NS_ERROR_FAILURE;
    1543                 :   }
    1544                 : 
    1545                 :   // node now contains the first valid certificate with correct usage 
    1546               0 :   nsNSSCertificate *nssCert = nsNSSCertificate::Create(node->cert);
    1547               0 :   if (!nssCert)
    1548               0 :     return NS_ERROR_OUT_OF_MEMORY;
    1549                 : 
    1550               0 :   NS_ADDREF(nssCert);
    1551               0 :   *_retval = static_cast<nsIX509Cert*>(nssCert);
    1552               0 :   return NS_OK;
    1553                 : }
    1554                 : 
    1555                 : /* nsIX509Cert constructX509FromBase64 (in string base64); */
    1556                 : NS_IMETHODIMP
    1557               0 : nsNSSCertificateDB::ConstructX509FromBase64(const char *base64,
    1558                 :                                             nsIX509Cert **_retval)
    1559                 : {
    1560               0 :   NS_ENSURE_ARG_POINTER(_retval);
    1561                 : 
    1562                 :   // sure would be nice to have a smart pointer class for PL_ allocations
    1563                 :   // unfortunately, we cannot distinguish out-of-memory from bad-input here
    1564               0 :   PRUint32 len = PL_strlen(base64);
    1565               0 :   char *certDER = PL_Base64Decode(base64, len, NULL);
    1566               0 :   if (!certDER)
    1567               0 :     return NS_ERROR_ILLEGAL_VALUE;
    1568               0 :   if (!*certDER) {
    1569               0 :     PL_strfree(certDER);
    1570               0 :     return NS_ERROR_ILLEGAL_VALUE;
    1571                 :   }
    1572                 : 
    1573                 :   // If we get to this point, we know we had well-formed base64 input;
    1574                 :   // therefore the input string cannot have been less than two
    1575                 :   // characters long.  Compute the unpadded length of the decoded data.
    1576               0 :   PRUint32 lengthDER = (len * 3) / 4;
    1577               0 :   if (base64[len-1] == '=') {
    1578               0 :     lengthDER--;
    1579               0 :     if (base64[len-2] == '=')
    1580               0 :       lengthDER--;
    1581                 :   }
    1582                 : 
    1583               0 :   nsNSSShutDownPreventionLock locker;
    1584                 :   SECItem secitem_cert;
    1585               0 :   secitem_cert.type = siDERCertBuffer;
    1586               0 :   secitem_cert.data = (unsigned char*)certDER;
    1587               0 :   secitem_cert.len = lengthDER;
    1588                 : 
    1589                 :   CERTCertificate *cert =
    1590                 :     CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &secitem_cert,
    1591               0 :                             nsnull, false, true);
    1592               0 :   PL_strfree(certDER);
    1593                 : 
    1594               0 :   if (!cert)
    1595               0 :     return (PORT_GetError() == SEC_ERROR_NO_MEMORY)
    1596               0 :       ? NS_ERROR_OUT_OF_MEMORY : NS_ERROR_FAILURE;
    1597                 : 
    1598               0 :   nsNSSCertificate *nsNSS = nsNSSCertificate::Create(cert);
    1599               0 :   CERT_DestroyCertificate(cert);
    1600                 : 
    1601               0 :   if (!nsNSS)
    1602               0 :     return NS_ERROR_OUT_OF_MEMORY;
    1603                 : 
    1604               0 :   return CallQueryInterface(nsNSS, _retval);
    1605                 : }
    1606                 : 
    1607                 : void
    1608               0 : nsNSSCertificateDB::get_default_nickname(CERTCertificate *cert, 
    1609                 :                                          nsIInterfaceRequestor* ctx,
    1610                 :                                          nsCString &nickname)
    1611                 : {
    1612               0 :   nickname.Truncate();
    1613                 : 
    1614               0 :   nsNSSShutDownPreventionLock locker;
    1615                 :   nsresult rv;
    1616                 :   CK_OBJECT_HANDLE keyHandle;
    1617                 : 
    1618               0 :   CERTCertDBHandle *defaultcertdb = CERT_GetDefaultCertDB();
    1619               0 :   nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
    1620               0 :   if (NS_FAILED(rv))
    1621                 :     return;
    1622                 : 
    1623               0 :   nsCAutoString username;
    1624               0 :   char *temp_un = CERT_GetCommonName(&cert->subject);
    1625               0 :   if (temp_un) {
    1626               0 :     username = temp_un;
    1627               0 :     PORT_Free(temp_un);
    1628               0 :     temp_un = nsnull;
    1629                 :   }
    1630                 : 
    1631               0 :   nsCAutoString caname;
    1632               0 :   char *temp_ca = CERT_GetOrgName(&cert->issuer);
    1633               0 :   if (temp_ca) {
    1634               0 :     caname = temp_ca;
    1635               0 :     PORT_Free(temp_ca);
    1636               0 :     temp_ca = nsnull;
    1637                 :   }
    1638                 : 
    1639               0 :   nsAutoString tmpNickFmt;
    1640               0 :   nssComponent->GetPIPNSSBundleString("nick_template", tmpNickFmt);
    1641               0 :   NS_ConvertUTF16toUTF8 nickFmt(tmpNickFmt);
    1642                 : 
    1643               0 :   nsCAutoString baseName;
    1644               0 :   char *temp_nn = PR_smprintf(nickFmt.get(), username.get(), caname.get());
    1645               0 :   if (!temp_nn) {
    1646                 :     return;
    1647                 :   } else {
    1648               0 :     baseName = temp_nn;
    1649               0 :     PR_smprintf_free(temp_nn);
    1650               0 :     temp_nn = nsnull;
    1651                 :   }
    1652                 : 
    1653               0 :   nickname = baseName;
    1654                 : 
    1655                 :   /*
    1656                 :    * We need to see if the private key exists on a token, if it does
    1657                 :    * then we need to check for nicknames that already exist on the smart
    1658                 :    * card.
    1659                 :    */
    1660               0 :   PK11SlotInfo *slot = PK11_KeyForCertExists(cert, &keyHandle, ctx);
    1661               0 :   PK11SlotInfoCleaner slotCleaner(slot);
    1662               0 :   if (!slot)
    1663                 :     return;
    1664                 : 
    1665               0 :   if (!PK11_IsInternal(slot)) {
    1666               0 :     char *tmp = PR_smprintf("%s:%s", PK11_GetTokenName(slot), baseName.get());
    1667               0 :     if (!tmp) {
    1668               0 :       nickname.Truncate();
    1669                 :       return;
    1670                 :     }
    1671               0 :     baseName = tmp;
    1672               0 :     PR_smprintf_free(tmp);
    1673                 : 
    1674               0 :     nickname = baseName;
    1675                 :   }
    1676                 : 
    1677               0 :   int count = 1;
    1678               0 :   while (true) {
    1679               0 :     if ( count > 1 ) {
    1680               0 :       char *tmp = PR_smprintf("%s #%d", baseName.get(), count);
    1681               0 :       if (!tmp) {
    1682               0 :         nickname.Truncate();
    1683                 :         return;
    1684                 :       }
    1685               0 :       nickname = tmp;
    1686               0 :       PR_smprintf_free(tmp);
    1687                 :     }
    1688                 : 
    1689               0 :     CERTCertificate *dummycert = nsnull;
    1690               0 :     CERTCertificateCleaner dummycertCleaner(dummycert);
    1691                 : 
    1692               0 :     if (PK11_IsInternal(slot)) {
    1693                 :       /* look up the nickname to make sure it isn't in use already */
    1694               0 :       dummycert = CERT_FindCertByNickname(defaultcertdb, nickname.get());
    1695                 : 
    1696                 :     } else {
    1697                 :       /*
    1698                 :        * Check the cert against others that already live on the smart 
    1699                 :        * card.
    1700                 :        */
    1701               0 :       dummycert = PK11_FindCertFromNickname(nickname.get(), ctx);
    1702               0 :       if (dummycert != NULL) {
    1703                 :         /*
    1704                 :          * Make sure the subject names are different.
    1705                 :          */ 
    1706               0 :         if (CERT_CompareName(&cert->subject, &dummycert->subject) == SECEqual)
    1707                 :         {
    1708                 :           /*
    1709                 :            * There is another certificate with the same nickname and
    1710                 :            * the same subject name on the smart card, so let's use this
    1711                 :            * nickname.
    1712                 :            */
    1713               0 :           CERT_DestroyCertificate(dummycert);
    1714               0 :           dummycert = NULL;
    1715                 :         }
    1716                 :       }
    1717                 :     }
    1718               0 :     if (!dummycert) 
    1719                 :       break;
    1720                 :     
    1721               0 :     count++;
    1722                 :   }
    1723                 : }
    1724                 : 
    1725               0 : NS_IMETHODIMP nsNSSCertificateDB::AddCertFromBase64(const char *aBase64, const char *aTrust, const char *aName)
    1726                 : {
    1727               0 :   NS_ENSURE_ARG_POINTER(aBase64);
    1728               0 :   nsCOMPtr <nsIX509Cert> newCert;
    1729                 : 
    1730               0 :   nsNSSCertTrust trust;
    1731                 : 
    1732                 :   // need to calculate the trust bits from the aTrust string.
    1733               0 :   nsresult rv = CERT_DecodeTrustString(trust.GetTrust(), /* this is const, but not declared that way */(char *) aTrust);
    1734               0 :   NS_ENSURE_SUCCESS(rv, rv); // if bad trust passed in, return error.
    1735                 : 
    1736                 : 
    1737               0 :   rv = ConstructX509FromBase64(aBase64, getter_AddRefs(newCert));
    1738               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1739                 : 
    1740                 :   SECItem der;
    1741               0 :   rv = newCert->GetRawDER(&der.len, (PRUint8 **)&der.data);
    1742               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1743                 : 
    1744               0 :   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Creating temp cert\n"));
    1745                 :   CERTCertificate *tmpCert;
    1746               0 :   CERTCertDBHandle *certdb = CERT_GetDefaultCertDB();
    1747               0 :   tmpCert = CERT_FindCertByDERCert(certdb, &der);
    1748               0 :   if (!tmpCert) 
    1749                 :     tmpCert = CERT_NewTempCertificate(certdb, &der,
    1750               0 :                                       nsnull, false, true);
    1751               0 :   nsMemory::Free(der.data);
    1752               0 :   der.data = nsnull;
    1753               0 :   der.len = 0;
    1754                 : 
    1755               0 :   if (!tmpCert) {
    1756               0 :     NS_ERROR("Couldn't create cert from DER blob");
    1757               0 :     return NS_ERROR_FAILURE;
    1758                 :   }
    1759                 : 
    1760               0 :   if (tmpCert->isperm) {
    1761               0 :     CERT_DestroyCertificate(tmpCert);
    1762               0 :     return NS_OK;
    1763                 :   }
    1764                 : 
    1765               0 :   CERTCertificateCleaner tmpCertCleaner(tmpCert);
    1766                 : 
    1767               0 :   nsXPIDLCString nickname;
    1768               0 :   nickname.Adopt(CERT_MakeCANickname(tmpCert));
    1769                 : 
    1770               0 :   PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Created nick \"%s\"\n", nickname.get()));
    1771                 : 
    1772                 :   SECStatus srv = CERT_AddTempCertToPerm(tmpCert, 
    1773               0 :                                          const_cast<char*>(nickname.get()), 
    1774               0 :                                          trust.GetTrust()); 
    1775                 : 
    1776                 : 
    1777               0 :   return (srv == SECSuccess) ? NS_OK : NS_ERROR_FAILURE;
    1778                 : }
    1779                 : 
    1780                 : NS_IMETHODIMP 
    1781               0 : nsNSSCertificateDB::GetCerts(nsIX509CertList **_retval)
    1782                 : {
    1783                 :   CERTCertList *certList;
    1784                 : 
    1785               0 :   nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
    1786               0 :   nsCOMPtr<nsIX509CertList> nssCertList;
    1787               0 :   certList = PK11_ListCerts(PK11CertListUnique, ctx);
    1788                 : 
    1789                 :   // nsNSSCertList 1) adopts certList, and 2) handles the NULL case fine.
    1790                 :   // (returns an empty list) 
    1791               0 :   nssCertList = new nsNSSCertList(certList, true);
    1792               0 :   if (!nssCertList) { return NS_ERROR_OUT_OF_MEMORY; }
    1793                 : 
    1794               0 :   *_retval = nssCertList;
    1795               0 :   NS_ADDREF(*_retval);
    1796               0 :   return NS_OK;
    1797                 : }

Generated by: LCOV version 1.7