Back to index

lightning-sunbird  0.9+nobinonly
nsNSSCertHelper.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   Ian McGreer <mcgreer@netscape.com>
00023  *   Javier Delgadillo <javi@netscape.com>
00024  *   John Gardiner Myers <jgmyers@speakeasy.net>
00025  *   Martin v. Loewis <martin@v.loewis.de>
00026  *
00027  * Alternatively, the contents of this file may be used under the terms of
00028  * either the GNU General Public License Version 2 or later (the "GPL"), or
00029  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00030  * in which case the provisions of the GPL or the LGPL are applicable instead
00031  * of those above. If you wish to allow use of your version of this file only
00032  * under the terms of either the GPL or the LGPL, and not to allow others to
00033  * use your version of this file under the terms of the MPL, indicate your
00034  * decision by deleting the provisions above and replace them with the notice
00035  * and other provisions required by the GPL or the LGPL. If you do not delete
00036  * the provisions above, a recipient may use your version of this file under
00037  * the terms of any one of the MPL, the GPL or the LGPL.
00038  *
00039  * ***** END LICENSE BLOCK ***** */
00040 
00041 #include "prmem.h"
00042 #include "prerror.h"
00043 #include "prprf.h"
00044 
00045 #include "nsNSSCertHelper.h"
00046 #include "nsCOMPtr.h"
00047 #include "nsNSSCertificate.h"
00048 #include "cert.h"
00049 #include "nsNSSCertValidity.h"
00050 #include "nsNSSASN1Object.h"
00051 #include "nsNSSComponent.h"
00052 #include "nsNSSCertTrust.h"
00053 #include "nsIDateTimeFormat.h"
00054 #include "nsDateTimeFormatCID.h"
00055  
00056 static NS_DEFINE_CID(kDateTimeFormatCID, NS_DATETIMEFORMAT_CID);
00057 static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
00058 
00059 #ifndef INET6_ADDRSTRLEN
00060 #define INET6_ADDRSTRLEN 46
00061 #endif
00062 
00063 /* Object Identifier constants */
00064 #define CONST_OID static const unsigned char
00065 #define MICROSOFT_OID 0x2b, 0x6, 0x1, 0x4, 0x1, 0x82, 0x37
00066 #define PKIX_OID 0x2b, 0x6, 0x01, 0x05, 0x05, 0x07
00067 CONST_OID msCertExtCerttype[]      = { MICROSOFT_OID, 20, 2};
00068 CONST_OID msNTPrincipalName[]      = { MICROSOFT_OID, 20, 2, 3 };
00069 CONST_OID msCertsrvCAVersion[]     = { MICROSOFT_OID, 21, 1 };
00070 CONST_OID msNTDSReplication[]      = { MICROSOFT_OID, 25, 1 };
00071 CONST_OID pkixLogotype[]           = { PKIX_OID, 1, 12 };
00072 
00073 #define OI(x) { siDEROID, (unsigned char *)x, sizeof x }
00074 #define OD(oid,desc,mech,ext) {OI(oid), SEC_OID_UNKNOWN, desc, mech, ext}
00075 #define SEC_OID(tag) more_oids[tag].offset
00076 
00077 static SECOidData more_oids[] = {
00078     /* Microsoft OIDs */
00079     #define MS_CERT_EXT_CERTTYPE 0
00080     OD( msCertExtCerttype,
00081         "Microsoft Certificate Template Name", 
00082         CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION ),
00083 
00084     #define MS_NT_PRINCIPAL_NAME 1
00085     OD( msNTPrincipalName,
00086         "Microsoft Principal Name", 
00087         CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION ),
00088 
00089     #define MS_CERTSERV_CA_VERSION 2
00090     OD( msCertsrvCAVersion,
00091         "Microsoft CA Version", 
00092         CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION ),
00093 
00094     #define MS_NTDS_REPLICATION 3
00095     OD( msNTDSReplication,
00096         "Microsoft Domain GUID", 
00097         CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION ),
00098 
00099     #define PKIX_LOGOTYPE 4
00100     OD( pkixLogotype,
00101         "Logotype", 
00102         CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION ),
00103 };
00104 
00105 static const unsigned int numOids = (sizeof more_oids) / (sizeof more_oids[0]);
00106 
00107 static nsresult
00108 GetIntValue(SECItem *versionItem, 
00109             unsigned long *version)
00110 {
00111   SECStatus srv;
00112 
00113   srv = SEC_ASN1DecodeInteger(versionItem,version);
00114   if (srv != SECSuccess) {
00115     NS_ASSERTION(0,"Could not decode version of cert");
00116     return NS_ERROR_FAILURE;
00117   }
00118   return NS_OK;
00119 }
00120 
00121 static nsresult
00122 ProcessVersion(SECItem         *versionItem,
00123                nsINSSComponent *nssComponent,
00124                nsIASN1PrintableItem **retItem)
00125 {
00126   nsresult rv;
00127   nsAutoString text;
00128   nsCOMPtr<nsIASN1PrintableItem> printableItem = new nsNSSASN1PrintableItem();
00129   if (printableItem == nsnull)
00130     return NS_ERROR_OUT_OF_MEMORY;
00131  
00132   nssComponent->GetPIPNSSBundleString("CertDumpVersion", text);
00133   rv = printableItem->SetDisplayName(text);
00134   if (NS_FAILED(rv))
00135     return rv;
00136 
00137   // Now to figure out what version this certificate is.
00138   unsigned long version;
00139 
00140   if (versionItem->data) {
00141     rv = GetIntValue(versionItem, &version);
00142     if (NS_FAILED(rv))
00143       return rv;
00144   } else {
00145     // If there is no version present in the cert, then rfc2459
00146     // says we default to v1 (0)
00147     version = 0;
00148   }
00149 
00150   switch (version){
00151   case 0:
00152     rv = nssComponent->GetPIPNSSBundleString("CertDumpVersion1", text);
00153     break;
00154   case 1:
00155     rv = nssComponent->GetPIPNSSBundleString("CertDumpVersion2", text);
00156     break;
00157   case 2:
00158     rv = nssComponent->GetPIPNSSBundleString("CertDumpVersion3", text);
00159     break;
00160   default:
00161     NS_ASSERTION(0,"Bad value for cert version");
00162     rv = NS_ERROR_FAILURE;
00163   }
00164     
00165   if (NS_FAILED(rv))
00166     return rv;
00167 
00168   rv = printableItem->SetDisplayValue(text);
00169   if (NS_FAILED(rv))
00170     return rv;
00171 
00172   *retItem = printableItem;
00173   NS_ADDREF(*retItem);
00174   return NS_OK;
00175 }
00176 
00177 static nsresult 
00178 ProcessSerialNumberDER(SECItem         *serialItem, 
00179                        nsINSSComponent *nssComponent,
00180                        nsIASN1PrintableItem **retItem)
00181 {
00182   nsresult rv;
00183   nsAutoString text;
00184   nsCOMPtr<nsIASN1PrintableItem> printableItem = new nsNSSASN1PrintableItem();
00185 
00186   if (printableItem == nsnull)
00187     return NS_ERROR_OUT_OF_MEMORY;
00188 
00189   rv = nssComponent->GetPIPNSSBundleString("CertDumpSerialNo", text); 
00190   if (NS_FAILED(rv))
00191     return rv;
00192 
00193   rv = printableItem->SetDisplayName(text);
00194   if (NS_FAILED(rv))
00195     return rv;
00196 
00197   nsXPIDLCString serialNumber;
00198   serialNumber.Adopt(CERT_Hexify(serialItem, 1));
00199   if (serialNumber == nsnull)
00200     return NS_ERROR_OUT_OF_MEMORY;
00201 
00202   rv = printableItem->SetDisplayValue(NS_ConvertASCIItoUCS2(serialNumber));
00203   *retItem = printableItem;
00204   NS_ADDREF(*retItem);
00205   return rv;
00206 }
00207 
00208 static nsresult
00209 GetDefaultOIDFormat(SECItem *oid,
00210                     nsAString &outString,
00211                   char separator)
00212 {
00213   char buf[300];
00214   unsigned int len;
00215   int written;
00216     
00217   unsigned long val  = oid->data[0];
00218   unsigned int  i    = val % 40;
00219   val /= 40;
00220   written = PR_snprintf(buf, 300, "%lu%c%u", val, separator, i);
00221   if (written < 0)
00222     return NS_ERROR_FAILURE;       
00223   len = written;
00224 
00225   val = 0;
00226   for (i = 1; i < oid->len; ++i) {
00227     // In this loop, we have to parse a DER formatted 
00228     // If the first bit is a 1, then the integer is 
00229     // represented by more than one byte.  If the 
00230     // first bit is set then we continue on and add
00231     // the values of the later bytes until we get 
00232     // a byte without the first bit set.
00233     unsigned long j;
00234 
00235     j = oid->data[i];
00236     val = (val << 7) | (j & 0x7f);
00237     if (j & 0x80)
00238       continue;
00239     written = PR_snprintf(&buf[len], sizeof(buf)-len, "%c%lu", 
00240                        separator, val);
00241     if (written < 0)
00242       return NS_ERROR_FAILURE;
00243 
00244     len += written;
00245     NS_ASSERTION(len < sizeof(buf), "OID data to big to display in 300 chars.");
00246     val = 0;      
00247   }
00248 
00249   CopyASCIItoUTF16(buf, outString);
00250   return NS_OK; 
00251 }
00252 
00253 static nsresult
00254 GetOIDText(SECItem *oid, nsINSSComponent *nssComponent, nsAString &text)
00255 { 
00256   nsresult rv;
00257   SECOidTag oidTag = SECOID_FindOIDTag(oid);
00258   const char *bundlekey = 0;
00259 
00260   switch (oidTag) {
00261   case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
00262     bundlekey = "CertDumpMD2WithRSA";
00263     break;
00264   case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
00265     bundlekey = "CertDumpMD5WithRSA";
00266     break;
00267   case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
00268     bundlekey = "CertDumpSHA1WithRSA";
00269     break;
00270   case SEC_OID_PKCS1_RSA_ENCRYPTION:
00271     bundlekey = "CertDumpRSAEncr";
00272     break;
00273   case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
00274     bundlekey = "CertDumpSHA256WithRSA";
00275     break;
00276   case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
00277     bundlekey = "CertDumpSHA384WithRSA";
00278     break;
00279   case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
00280     bundlekey = "CertDumpSHA512WithRSA";
00281     break;
00282   case SEC_OID_NS_CERT_EXT_CERT_TYPE:
00283     bundlekey = "CertDumpCertType";
00284     break;
00285   case SEC_OID_NS_CERT_EXT_BASE_URL:
00286     bundlekey = "CertDumpNSCertExtBaseUrl";
00287     break;
00288   case SEC_OID_NS_CERT_EXT_REVOCATION_URL:
00289     bundlekey = "CertDumpNSCertExtRevocationUrl";
00290     break;
00291   case SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL:
00292     bundlekey = "CertDumpNSCertExtCARevocationUrl";
00293     break;
00294   case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL:
00295     bundlekey = "CertDumpNSCertExtCertRenewalUrl";
00296     break;
00297   case SEC_OID_NS_CERT_EXT_CA_POLICY_URL:
00298     bundlekey = "CertDumpNSCertExtCAPolicyUrl";
00299     break;
00300   case SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME:
00301     bundlekey = "CertDumpNSCertExtSslServerName";
00302     break;
00303   case SEC_OID_NS_CERT_EXT_COMMENT:
00304     bundlekey = "CertDumpNSCertExtComment";
00305     break;
00306   case SEC_OID_NS_CERT_EXT_LOST_PASSWORD_URL:
00307     bundlekey = "CertDumpNSCertExtLostPasswordUrl";
00308     break;
00309   case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_TIME:
00310     bundlekey = "CertDumpNSCertExtCertRenewalTime";
00311     break;
00312   case SEC_OID_NETSCAPE_AOLSCREENNAME:
00313     bundlekey = "CertDumpNetscapeAolScreenname";
00314     break;
00315   case SEC_OID_AVA_COUNTRY_NAME:
00316     bundlekey = "CertDumpAVACountry";
00317     break;
00318   case SEC_OID_AVA_COMMON_NAME:
00319     bundlekey = "CertDumpAVACN";
00320     break;
00321   case SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME:
00322     bundlekey = "CertDumpAVAOU";
00323     break;
00324   case SEC_OID_AVA_ORGANIZATION_NAME:
00325     bundlekey = "CertDumpAVAOrg";
00326     break;
00327   case SEC_OID_AVA_LOCALITY:
00328     bundlekey = "CertDumpAVALocality";
00329     break;
00330   case SEC_OID_AVA_DN_QUALIFIER:
00331     bundlekey = "CertDumpAVADN";
00332     break;
00333   case SEC_OID_AVA_DC:
00334     bundlekey = "CertDumpAVADC";
00335     break;
00336   case SEC_OID_AVA_STATE_OR_PROVINCE:
00337     bundlekey = "CertDumpAVAState";
00338     break;
00339   case SEC_OID_X509_SUBJECT_DIRECTORY_ATTR:
00340     bundlekey = "CertDumpSubjectDirectoryAttr";
00341     break;
00342   case SEC_OID_X509_SUBJECT_KEY_ID:
00343     bundlekey = "CertDumpSubjectKeyID";
00344     break;
00345   case SEC_OID_X509_KEY_USAGE:
00346     bundlekey = "CertDumpKeyUsage";
00347     break;
00348   case SEC_OID_X509_SUBJECT_ALT_NAME:
00349     bundlekey = "CertDumpSubjectAltName";
00350     break;
00351   case SEC_OID_X509_ISSUER_ALT_NAME:
00352     bundlekey = "CertDumpIssuerAltName";
00353     break;
00354   case SEC_OID_X509_BASIC_CONSTRAINTS:
00355     bundlekey = "CertDumpBasicConstraints";
00356     break;
00357   case SEC_OID_X509_NAME_CONSTRAINTS:
00358     bundlekey = "CertDumpNameConstraints";
00359     break;
00360   case SEC_OID_X509_CRL_DIST_POINTS:
00361     bundlekey = "CertDumpCrlDistPoints";
00362     break;
00363   case SEC_OID_X509_CERTIFICATE_POLICIES:
00364     bundlekey = "CertDumpCertPolicies";
00365     break;
00366   case SEC_OID_X509_POLICY_MAPPINGS:
00367     bundlekey = "CertDumpPolicyMappings";
00368     break;
00369   case SEC_OID_X509_POLICY_CONSTRAINTS:
00370     bundlekey = "CertDumpPolicyConstraints";
00371     break;
00372   case SEC_OID_X509_AUTH_KEY_ID:
00373     bundlekey = "CertDumpAuthKeyID";
00374     break;
00375   case SEC_OID_X509_EXT_KEY_USAGE:
00376     bundlekey = "CertDumpExtKeyUsage";
00377     break;
00378   case SEC_OID_X509_AUTH_INFO_ACCESS:
00379     bundlekey = "CertDumpAuthInfoAccess";
00380     break;
00381   case SEC_OID_ANSIX9_DSA_SIGNATURE:
00382     bundlekey = "CertDumpAnsiX9DsaSignature";
00383     break;
00384   case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
00385     bundlekey = "CertDumpAnsiX9DsaSignatureWithSha1";
00386     break;
00387   case SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST:
00388     bundlekey = "CertDumpAnsiX962ECDsaSignatureWithSha1";
00389     break;
00390   case SEC_OID_RFC1274_UID:
00391     bundlekey = "CertDumpUserID";
00392     break;
00393   case SEC_OID_PKCS9_EMAIL_ADDRESS:
00394     bundlekey = "CertDumpPK9Email";
00395     break;
00396   case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
00397     bundlekey = "CertDumpECPublicKey";
00398     break;
00399   /* ANSI X9.62 named elliptic curves (prime field) */
00400   case SEC_OID_ANSIX962_EC_PRIME192V1:
00401     /* same as SEC_OID_SECG_EC_SECP192r1 */
00402     bundlekey = "CertDumpECprime192v1";
00403     break;
00404   case SEC_OID_ANSIX962_EC_PRIME192V2:
00405     bundlekey = "CertDumpECprime192v2";
00406     break;
00407   case SEC_OID_ANSIX962_EC_PRIME192V3:
00408     bundlekey = "CertDumpECprime192v3";
00409     break;
00410   case SEC_OID_ANSIX962_EC_PRIME239V1:
00411     bundlekey = "CertDumpECprime239v1";
00412     break;
00413   case SEC_OID_ANSIX962_EC_PRIME239V2:
00414     bundlekey = "CertDumpECprime239v2";
00415     break;
00416   case SEC_OID_ANSIX962_EC_PRIME239V3:
00417     bundlekey = "CertDumpECprime239v3";
00418     break;
00419   case SEC_OID_ANSIX962_EC_PRIME256V1:
00420     /* same as SEC_OID_SECG_EC_SECP256r1 */
00421     bundlekey = "CertDumpECprime256v1";
00422     break;
00423   /* SECG named elliptic curves (prime field) */
00424   case SEC_OID_SECG_EC_SECP112R1:
00425     bundlekey = "CertDumpECsecp112r1";
00426     break;
00427   case SEC_OID_SECG_EC_SECP112R2:
00428     bundlekey = "CertDumpECsecp112r2";
00429     break;
00430   case SEC_OID_SECG_EC_SECP128R1:
00431     bundlekey = "CertDumpECsecp128r1";
00432     break;
00433   case SEC_OID_SECG_EC_SECP128R2:
00434     bundlekey = "CertDumpECsecp128r2";
00435     break;
00436   case SEC_OID_SECG_EC_SECP160K1:
00437     bundlekey = "CertDumpECsecp160k1";
00438     break;
00439   case SEC_OID_SECG_EC_SECP160R1:
00440     bundlekey = "CertDumpECsecp160r1";
00441     break;
00442   case SEC_OID_SECG_EC_SECP160R2:
00443     bundlekey = "CertDumpECsecp160r2";
00444     break;
00445   case SEC_OID_SECG_EC_SECP192K1:
00446     bundlekey = "CertDumpECsecp192k1";
00447     break;
00448   case SEC_OID_SECG_EC_SECP224K1:
00449     bundlekey = "CertDumpECsecp224k1";
00450     break;
00451   case SEC_OID_SECG_EC_SECP224R1:
00452     bundlekey = "CertDumpECsecp224r1";
00453     break;
00454   case SEC_OID_SECG_EC_SECP256K1:
00455     bundlekey = "CertDumpECsecp256k1";
00456     break;
00457   case SEC_OID_SECG_EC_SECP384R1:
00458     bundlekey = "CertDumpECsecp384r1";
00459     break;
00460 
00461   case SEC_OID_SECG_EC_SECP521R1:
00462     bundlekey = "CertDumpECsecp521r1";
00463     break;
00464   /* ANSI X9.62 named elliptic curves (characteristic two field) */
00465   case SEC_OID_ANSIX962_EC_C2PNB163V1:
00466     bundlekey = "CertDumpECc2pnb163v1";
00467     break;
00468   case SEC_OID_ANSIX962_EC_C2PNB163V2:
00469     bundlekey = "CertDumpECc2pnb163v2";
00470     break;
00471   case SEC_OID_ANSIX962_EC_C2PNB163V3:
00472     bundlekey = "CertDumpECc2pnb163v3";
00473     break;
00474   case SEC_OID_ANSIX962_EC_C2PNB176V1:
00475     bundlekey = "CertDumpECc2pnb176v1";
00476     break;
00477   case SEC_OID_ANSIX962_EC_C2TNB191V1:
00478     bundlekey = "CertDumpECc2tnb191v1";
00479     break;
00480   case SEC_OID_ANSIX962_EC_C2TNB191V2:
00481     bundlekey = "CertDumpECc2tnb191v2";
00482     break;
00483   case SEC_OID_ANSIX962_EC_C2TNB191V3:
00484     bundlekey = "CertDumpECc2tnb191v3";
00485     break;
00486   case SEC_OID_ANSIX962_EC_C2ONB191V4:
00487     bundlekey = "CertDumpECc2onb191v4";
00488     break;
00489   case SEC_OID_ANSIX962_EC_C2ONB191V5:
00490     bundlekey = "CertDumpECc2onb191v5";
00491     break;
00492   case SEC_OID_ANSIX962_EC_C2PNB208W1:
00493     bundlekey = "CertDumpECc2pnb208w1";
00494     break;
00495   case SEC_OID_ANSIX962_EC_C2TNB239V1:
00496     bundlekey = "CertDumpECc2tnb239v1";
00497     break;
00498   case SEC_OID_ANSIX962_EC_C2TNB239V2:
00499     bundlekey = "CertDumpECc2tnb239v2";
00500     break;
00501   case SEC_OID_ANSIX962_EC_C2TNB239V3:
00502     bundlekey = "CertDumpECc2tnb239v3";
00503     break;
00504   case SEC_OID_ANSIX962_EC_C2ONB239V4:
00505     bundlekey = "CertDumpECc2onb239v4";
00506     break;
00507   case SEC_OID_ANSIX962_EC_C2ONB239V5:
00508     bundlekey = "CertDumpECc2onb239v5";
00509     break;
00510   case SEC_OID_ANSIX962_EC_C2PNB272W1:
00511     bundlekey = "CertDumpECc2pnb272w1";
00512     break;
00513   case SEC_OID_ANSIX962_EC_C2PNB304W1:
00514     bundlekey = "CertDumpECc2pnb304w1";
00515     break;
00516   case SEC_OID_ANSIX962_EC_C2TNB359V1:
00517     bundlekey = "CertDumpECc2tnb359v1";
00518     break;
00519   case SEC_OID_ANSIX962_EC_C2PNB368W1:
00520     bundlekey = "CertDumpECc2pnb368w1";
00521     break;
00522   case SEC_OID_ANSIX962_EC_C2TNB431R1:
00523     bundlekey = "CertDumpECc2tnb431r1";
00524     break;
00525   /* SECG named elliptic curves (characteristic two field) */
00526   case SEC_OID_SECG_EC_SECT113R1:
00527     bundlekey = "CertDumpECsect113r1";
00528     break;
00529   case SEC_OID_SECG_EC_SECT113R2:
00530     bundlekey = "CertDumpECsect113r2";
00531     break;
00532   case SEC_OID_SECG_EC_SECT131R1:
00533     bundlekey = "CertDumpECsect131r1";
00534     break;
00535   case SEC_OID_SECG_EC_SECT131R2:
00536     bundlekey = "CertDumpECsect131r2";
00537     break;
00538   case SEC_OID_SECG_EC_SECT163K1:
00539     bundlekey = "CertDumpECsect163k1";
00540     break;
00541   case SEC_OID_SECG_EC_SECT163R1:
00542     bundlekey = "CertDumpECsect163r1";
00543     break;
00544   case SEC_OID_SECG_EC_SECT163R2:
00545     bundlekey = "CertDumpECsect163r2";
00546     break;
00547   case SEC_OID_SECG_EC_SECT193R1:
00548     bundlekey = "CertDumpECsect193r1";
00549     break;
00550   case SEC_OID_SECG_EC_SECT193R2:
00551     bundlekey = "CertDumpECsect193r2";
00552     break;
00553   case SEC_OID_SECG_EC_SECT233K1:
00554     bundlekey = "CertDumpECsect233k1";
00555     break;
00556   case SEC_OID_SECG_EC_SECT233R1:
00557     bundlekey = "CertDumpECsect233r1";
00558     break;
00559   case SEC_OID_SECG_EC_SECT239K1:
00560     bundlekey = "CertDumpECsect239k1";
00561     break;
00562   case SEC_OID_SECG_EC_SECT283K1:
00563     bundlekey = "CertDumpECsect283k1";
00564     break;
00565   case SEC_OID_SECG_EC_SECT283R1:
00566     bundlekey = "CertDumpECsect283r1";
00567     break;
00568   case SEC_OID_SECG_EC_SECT409K1:
00569     bundlekey = "CertDumpECsect409k1";
00570     break;
00571   case SEC_OID_SECG_EC_SECT409R1:
00572     bundlekey = "CertDumpECsect409r1";
00573     break;
00574   case SEC_OID_SECG_EC_SECT571K1:
00575     bundlekey = "CertDumpECsect571k1";
00576     break;
00577   case SEC_OID_SECG_EC_SECT571R1:
00578     bundlekey = "CertDumpECsect571r1";
00579     break;
00580   default: 
00581     if (oidTag == SEC_OID(MS_CERT_EXT_CERTTYPE)) {
00582       bundlekey = "CertDumpMSCerttype";
00583       break;
00584     }
00585     if (oidTag == SEC_OID(MS_CERTSERV_CA_VERSION)) {
00586       bundlekey = "CertDumpMSCAVersion";
00587       break;
00588     }
00589     if (oidTag == SEC_OID(PKIX_LOGOTYPE)) {
00590       bundlekey = "CertDumpLogotype";
00591       break;
00592     }
00593     /* fallthrough */
00594   }
00595 
00596   if (bundlekey) {
00597     rv = nssComponent->GetPIPNSSBundleString(bundlekey, text);
00598   } else {
00599     nsAutoString text2;
00600     rv = GetDefaultOIDFormat(oid, text2, ' ');
00601     if (NS_FAILED(rv))
00602       return rv;
00603 
00604     const PRUnichar *params[1] = {text2.get()};
00605     rv = nssComponent->PIPBundleFormatStringFromName("CertDumpDefOID",
00606                                                      params, 1, text);
00607   }
00608   return rv;  
00609 }
00610 
00611 #define SEPARATOR "\n"
00612 
00613 static nsresult
00614 ProcessRawBytes(nsINSSComponent *nssComponent, SECItem *data, nsAString &text)
00615 {
00616   // This function is used to display some DER bytes
00617   // that we have not added support for decoding.
00618   // It prints the value of the byte out into a 
00619   // string that can later be displayed as a byte
00620   // string.  We place a new line after 24 bytes
00621   // to break up extermaly long sequence of bytes.
00622 
00623   nsAutoString bytelen, bitlen;
00624   bytelen.AppendInt(data->len);
00625   bitlen.AppendInt(data->len*8);
00626 
00627   const PRUnichar *params[2] = {bytelen.get(), bitlen.get()};
00628   nsresult rv = nssComponent->PIPBundleFormatStringFromName("CertDumpRawBytesHeader",
00629                                                             params, 2, text);
00630   if (NS_FAILED(rv))
00631     return rv;
00632 
00633   text.Append(NS_LITERAL_STRING(SEPARATOR).get());
00634 
00635   PRUint32 i;
00636   char buffer[5];
00637   for (i=0; i<data->len; i++) {
00638     PR_snprintf(buffer, 5, "%02x ", data->data[i]);
00639     AppendASCIItoUTF16(buffer, text);
00640     if ((i+1)%16 == 0) {
00641       text.Append(NS_LITERAL_STRING(SEPARATOR).get());
00642     }
00643   }
00644   return NS_OK;
00645 }    
00646 
00647 static nsresult
00648 ProcessNSCertTypeExtensions(SECItem  *extData, 
00649                             nsAString &text,
00650                             nsINSSComponent *nssComponent)
00651 {
00652   nsAutoString local;
00653   SECItem decoded;
00654   decoded.data = nsnull;
00655   decoded.len  = 0;
00656   if (SECSuccess != SEC_ASN1DecodeItem(nsnull, &decoded, 
00657               SEC_ASN1_GET(SEC_BitStringTemplate), extData)) {
00658     nssComponent->GetPIPNSSBundleString("CertDumpExtensionFailure", local);
00659     text.Append(local.get());
00660     return NS_OK;
00661   }
00662   unsigned char nsCertType = decoded.data[0];
00663   nsMemory::Free(decoded.data);
00664   if (nsCertType & NS_CERT_TYPE_SSL_CLIENT) {
00665     nssComponent->GetPIPNSSBundleString("VerifySSLClient", local);
00666     text.Append(local.get());
00667     text.Append(NS_LITERAL_STRING(SEPARATOR).get());
00668   }
00669   if (nsCertType & NS_CERT_TYPE_SSL_SERVER) {
00670     nssComponent->GetPIPNSSBundleString("VerifySSLServer", local);
00671     text.Append(local.get());
00672     text.Append(NS_LITERAL_STRING(SEPARATOR).get());
00673   }
00674   if (nsCertType & NS_CERT_TYPE_EMAIL) {
00675     nssComponent->GetPIPNSSBundleString("CertDumpCertTypeEmail", local);
00676     text.Append(local.get());
00677     text.Append(NS_LITERAL_STRING(SEPARATOR).get());
00678   }
00679   if (nsCertType & NS_CERT_TYPE_OBJECT_SIGNING) {
00680     nssComponent->GetPIPNSSBundleString("VerifyObjSign", local);
00681     text.Append(local.get());
00682     text.Append(NS_LITERAL_STRING(SEPARATOR).get());
00683   }
00684   if (nsCertType & NS_CERT_TYPE_SSL_CA) {
00685     nssComponent->GetPIPNSSBundleString("VerifySSLCA", local);
00686     text.Append(local.get());
00687     text.Append(NS_LITERAL_STRING(SEPARATOR).get());
00688   }
00689   if (nsCertType & NS_CERT_TYPE_EMAIL_CA) {
00690     nssComponent->GetPIPNSSBundleString("CertDumpEmailCA", local);
00691     text.Append(local.get());
00692     text.Append(NS_LITERAL_STRING(SEPARATOR).get());
00693   }
00694   if (nsCertType & NS_CERT_TYPE_OBJECT_SIGNING_CA) {
00695     nssComponent->GetPIPNSSBundleString("VerifyObjSign", local);
00696     text.Append(local.get());
00697     text.Append(NS_LITERAL_STRING(SEPARATOR).get());
00698   }
00699   return NS_OK;
00700 }
00701 
00702 static nsresult
00703 ProcessKeyUsageExtension(SECItem *extData, nsAString &text,
00704                          nsINSSComponent *nssComponent)
00705 {
00706   nsAutoString local;
00707   SECItem decoded;
00708   decoded.data = nsnull;
00709   decoded.len  = 0;
00710   if (SECSuccess != SEC_ASN1DecodeItem(nsnull, &decoded, 
00711                             SEC_ASN1_GET(SEC_BitStringTemplate), extData)) {
00712     nssComponent->GetPIPNSSBundleString("CertDumpExtensionFailure", local);
00713     text.Append(local.get());
00714     return NS_OK;
00715   }
00716   unsigned char keyUsage = decoded.data[0];
00717   nsMemory::Free(decoded.data);  
00718   if (keyUsage & KU_DIGITAL_SIGNATURE) {
00719     nssComponent->GetPIPNSSBundleString("CertDumpKUSign", local);
00720     text.Append(local.get());
00721     text.Append(NS_LITERAL_STRING(SEPARATOR).get());
00722   }
00723   if (keyUsage & KU_NON_REPUDIATION) {
00724     nssComponent->GetPIPNSSBundleString("CertDumpKUNonRep", local);
00725     text.Append(local.get());
00726     text.Append(NS_LITERAL_STRING(SEPARATOR).get());
00727   }
00728   if (keyUsage & KU_KEY_ENCIPHERMENT) {
00729     nssComponent->GetPIPNSSBundleString("CertDumpKUEnc", local);
00730     text.Append(local.get());
00731     text.Append(NS_LITERAL_STRING(SEPARATOR).get());
00732   }
00733   if (keyUsage & KU_DATA_ENCIPHERMENT) {
00734     nssComponent->GetPIPNSSBundleString("CertDumpKUDEnc", local);
00735     text.Append(local.get());
00736     text.Append(NS_LITERAL_STRING(SEPARATOR).get());
00737   }
00738   if (keyUsage & KU_KEY_AGREEMENT) {
00739     nssComponent->GetPIPNSSBundleString("CertDumpKUKA", local);
00740     text.Append(local.get());
00741     text.Append(NS_LITERAL_STRING(SEPARATOR).get());
00742   }
00743   if (keyUsage & KU_KEY_CERT_SIGN) {
00744     nssComponent->GetPIPNSSBundleString("CertDumpKUCertSign", local);
00745     text.Append(local.get());
00746     text.Append(NS_LITERAL_STRING(SEPARATOR).get());
00747   }
00748   if (keyUsage & KU_CRL_SIGN) {
00749     nssComponent->GetPIPNSSBundleString("CertDumpKUCRLSigner", local);
00750     text.Append(local.get());
00751     text.Append(NS_LITERAL_STRING(SEPARATOR).get());
00752   }
00753 
00754   return NS_OK;
00755 }
00756 
00757 static nsresult
00758 ProcessBasicConstraints(SECItem  *extData, 
00759                         nsAString &text,
00760                         nsINSSComponent *nssComponent)
00761 {
00762   nsAutoString local;
00763   CERTBasicConstraints value;
00764   SECStatus rv;
00765   nsresult rv2;
00766 
00767   value.pathLenConstraint = -1;
00768   rv = CERT_DecodeBasicConstraintValue (&value, extData);
00769   if (rv != SECSuccess) {
00770     ProcessRawBytes(nssComponent, extData, text);
00771     return NS_OK;
00772   }
00773   if (value.isCA)
00774     rv2 = nssComponent->GetPIPNSSBundleString("CertDumpIsCA", local);
00775   else
00776     rv2 = nssComponent->GetPIPNSSBundleString("CertDumpIsNotCA", local);
00777   if (NS_FAILED(rv2))
00778     return rv2;
00779   text.Append(local.get());
00780   if (value.pathLenConstraint != -1) {
00781     nsAutoString depth;
00782     if (value.pathLenConstraint == CERT_UNLIMITED_PATH_CONSTRAINT)
00783       nssComponent->GetPIPNSSBundleString("CertDumpPathLenUnlimited", depth);
00784     else
00785       depth.AppendInt(value.pathLenConstraint);
00786     const PRUnichar *params[1] = {depth.get()};
00787     rv2 = nssComponent->PIPBundleFormatStringFromName("CertDumpPathLen",
00788                                                       params, 1, local);
00789     if (NS_FAILED(rv2))
00790       return rv2;
00791     text.Append(NS_LITERAL_STRING(SEPARATOR).get());
00792     text.Append(local.get());
00793   }
00794   return NS_OK;
00795 }
00796 
00797 static nsresult
00798 ProcessExtKeyUsage(SECItem  *extData, 
00799                    nsAString &text,
00800                    nsINSSComponent *nssComponent)
00801 {
00802   nsAutoString local;
00803   CERTOidSequence *extKeyUsage = NULL;
00804   SECItem **oids;
00805   SECItem *oid;
00806   nsresult rv;
00807   
00808   extKeyUsage = CERT_DecodeOidSequence(extData);
00809   if (extKeyUsage == NULL)
00810     return NS_ERROR_FAILURE;
00811 
00812   oids = extKeyUsage->oids;
00813   while (oids != NULL && *oids != NULL) {
00814     // For each OID, try to find a bundle string
00815     // of the form CertDumpEKU_<underlined-OID>
00816     nsAutoString oidname;
00817     oid = *oids;
00818     rv = GetDefaultOIDFormat(oid, oidname, '_');
00819     if (NS_FAILED(rv))
00820       return rv;
00821     nsAutoString bundlekey = NS_LITERAL_STRING("CertDumpEKU_")+ oidname;
00822     NS_ConvertUTF16toUTF8 bk_ascii(bundlekey);
00823     
00824     rv = nssComponent->GetPIPNSSBundleString(bk_ascii.get(), local);
00825     nsresult rv2 = GetDefaultOIDFormat(oid, oidname, '.');
00826     if (NS_FAILED(rv2))
00827       return rv2;
00828     if (NS_SUCCEEDED(rv)) {
00829       // display name and OID in parentheses
00830       text.Append(local);
00831       text.Append(NS_LITERAL_STRING(" ("));
00832       text.Append(oidname);
00833       text.Append(NS_LITERAL_STRING(")"));
00834     } else
00835       // If there is no bundle string, just display the OID itself
00836       text.Append(oidname);
00837 
00838     text.Append(NS_LITERAL_STRING(SEPARATOR).get());
00839     oids++;
00840   }
00841 
00842   CERT_DestroyOidSequence(extKeyUsage);
00843   return NS_OK;
00844 }
00845 
00846 static nsresult
00847 ProcessRDN(CERTRDN* rdn, nsAString &finalString, nsINSSComponent *nssComponent)
00848 {
00849   nsresult rv;
00850   CERTAVA** avas;
00851   CERTAVA* ava;
00852   SECItem *decodeItem = nsnull;
00853   nsString avavalue;
00854   nsString type;
00855   nsAutoString temp;
00856   const PRUnichar *params[2];
00857 
00858   avas = rdn->avas;
00859   while ((ava = *avas++) != 0) {
00860     rv = GetOIDText(&ava->type, nssComponent, type);
00861     if (NS_FAILED(rv))
00862       return rv;
00863     
00864     //This function returns a string in UTF8 format.
00865     decodeItem = CERT_DecodeAVAValue(&ava->value);
00866     if(!decodeItem) {
00867       return NS_ERROR_FAILURE;
00868     }
00869     avavalue = NS_ConvertUTF8toUTF16((char*)decodeItem->data, decodeItem->len);
00870     
00871     SECITEM_FreeItem(decodeItem, PR_TRUE);
00872     params[0] = type.get();
00873     params[1] = avavalue.get();
00874     nssComponent->PIPBundleFormatStringFromName("AVATemplate",
00875                                                   params, 2, temp);
00876     finalString += temp + NS_LITERAL_STRING("\n");
00877   }
00878   return NS_OK;
00879 }
00880 
00881 static nsresult
00882 ProcessName(CERTName *name, nsINSSComponent *nssComponent, PRUnichar **value)
00883 {
00884   CERTRDN** rdns;
00885   CERTRDN** rdn;
00886   nsString finalString;
00887 
00888   rdns = name->rdns;
00889 
00890   nsresult rv;
00891   CERTRDN **lastRdn;
00892   lastRdn = rdns;
00893 
00894 
00895   /* find last RDN */
00896   lastRdn = rdns;
00897   while (*lastRdn) lastRdn++;
00898   // The above whille loop will put us at the last member
00899   // of the array which is a NULL pointer.  So let's back
00900   // up one spot so that we have the last non-NULL entry in 
00901   // the array in preparation for traversing the 
00902   // RDN's (Relative Distinguished Name) in reverse oder.
00903   lastRdn--;
00904    
00905   /*
00906    * Loop over name contents in _reverse_ RDN order appending to string
00907    * When building the Ascii string, NSS loops over these entries in 
00908    * reverse order, so I will as well.  The difference is that NSS
00909    * will always place them in a one line string separated by commas,
00910    * where I want each entry on a single line.  I can't just use a comma
00911    * as my delimitter because it is a valid character to have in the 
00912    * value portion of the AVA and could cause trouble when parsing.
00913    */
00914   for (rdn = lastRdn; rdn >= rdns; rdn--) {
00915     rv = ProcessRDN(*rdn, finalString, nssComponent);
00916     if (NS_FAILED(rv))
00917       return rv;
00918   }
00919   *value = ToNewUnicode(finalString);    
00920   return NS_OK;
00921 }
00922 
00923 static nsresult
00924 ProcessIA5String(SECItem  *extData, 
00925                nsAString &text,
00926                nsINSSComponent *nssComponent)
00927 {
00928   SECItem item;
00929   nsAutoString local;
00930   if (SECSuccess != SEC_ASN1DecodeItem(nsnull, &item, 
00931                                    SEC_ASN1_GET(SEC_IA5StringTemplate),
00932                                    extData))
00933     return NS_ERROR_FAILURE;
00934   local.AssignASCII((char*)item.data, item.len);
00935   nsMemory::Free(item.data);
00936   text.Append(local);
00937   return NS_OK;
00938 }
00939 
00940 static nsresult
00941 AppendBMPtoUTF16(PRArenaPool *arena,
00942                unsigned char* data, unsigned int len,
00943                nsAString& text)
00944 {
00945   unsigned int   utf8ValLen;
00946   unsigned char *utf8Val;
00947 
00948   if (len % 2 != 0)
00949     return NS_ERROR_FAILURE;
00950 
00951   /* XXX instead of converting to and from UTF-8, it would
00952      be sufficient to just swap bytes, or do nothing */
00953   utf8ValLen = len * 3 + 1;
00954   utf8Val = (unsigned char*)PORT_ArenaZAlloc(arena, utf8ValLen);
00955   if (!PORT_UCS2_UTF8Conversion(PR_FALSE, data, len,
00956                             utf8Val, utf8ValLen, &utf8ValLen))
00957     return NS_ERROR_FAILURE;
00958   AppendUTF8toUTF16((char*)utf8Val, text);
00959   return NS_OK;
00960 }
00961 
00962 static nsresult
00963 ProcessBMPString(SECItem  *extData, 
00964                nsAString &text,
00965                nsINSSComponent *nssComponent)
00966 {
00967   SECItem item;
00968   PRArenaPool *arena;
00969   nsresult rv = NS_ERROR_FAILURE;
00970   
00971   arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
00972   if (!arena)
00973     return NS_ERROR_FAILURE;
00974 
00975   if (SECSuccess == SEC_ASN1DecodeItem(arena, &item, 
00976                                    SEC_ASN1_GET(SEC_BMPStringTemplate),
00977                                    extData))
00978     rv = AppendBMPtoUTF16(arena, item.data, item.len, text);
00979   PORT_FreeArena(arena, PR_FALSE);
00980   return rv;
00981 }
00982 
00983 static nsresult
00984 ProcessGeneralName(PRArenaPool *arena,
00985                  CERTGeneralName *current,
00986                  nsAString &text,
00987                  nsINSSComponent *nssComponent)
00988 {
00989   nsAutoString key;
00990   nsXPIDLString value;
00991   nsresult rv = NS_OK;
00992 
00993   switch (current->type) {
00994   case certOtherName: {
00995     SECOidTag oidTag = SECOID_FindOIDTag(&current->name.OthName.oid);
00996     if (oidTag == SEC_OID(MS_NT_PRINCIPAL_NAME)) {
00997        /* The type of this name is apparently nowhere explicitly
00998           documented. However, in the generated templates, it is always
00999           UTF-8. So try to decode this as UTF-8; if that fails, dump the
01000           raw data. */
01001        SECItem decoded;
01002        nssComponent->GetPIPNSSBundleString("CertDumpMSNTPrincipal", key);
01003        if (SEC_ASN1DecodeItem(arena, &decoded, 
01004                             SEC_ASN1_GET(SEC_UTF8StringTemplate), 
01005                             &current->name.OthName.name) == SECSuccess) {
01006          AppendUTF8toUTF16(nsCAutoString((char*)decoded.data, decoded.len),
01007                          value);
01008        } else {
01009          ProcessRawBytes(nssComponent, &current->name.OthName.name, value);
01010        }
01011        break;
01012     } else if (oidTag == SEC_OID(MS_NTDS_REPLICATION)) {
01013        /* This should be a 16-byte GUID */
01014        SECItem guid;
01015        nssComponent->GetPIPNSSBundleString("CertDumpMSDomainGUID", key);
01016        if (SEC_ASN1DecodeItem(arena, &guid,
01017                             SEC_ASN1_GET(SEC_OctetStringTemplate),
01018                             &current->name.OthName.name) == SECSuccess
01019            && guid.len == 16) {
01020          char buf[40];
01021          unsigned char *d = guid.data;
01022          PR_snprintf(buf, sizeof(buf), 
01023                     "{%.2x%.2x%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x%.2x%.2x%.2x%.2x}",
01024                     d[3], d[2], d[1], d[0], d[5], d[4], d[7], d[6],
01025                     d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
01026          value.AssignASCII(buf);
01027        } else {
01028          ProcessRawBytes(nssComponent, &current->name.OthName.name, value);
01029        }
01030     } else {
01031       rv = GetDefaultOIDFormat(&current->name.OthName.oid, key, ' ');
01032       if (NS_FAILED(rv))
01033        goto finish;
01034       ProcessRawBytes(nssComponent, &current->name.OthName.name, value);
01035     }
01036     break;
01037   }
01038   case certRFC822Name:
01039     nssComponent->GetPIPNSSBundleString("CertDumpRFC822Name", key);
01040     value.AssignASCII((char*)current->name.other.data, current->name.other.len);
01041     break;
01042   case certDNSName:
01043     nssComponent->GetPIPNSSBundleString("CertDumpDNSName", key);
01044     value.AssignASCII((char*)current->name.other.data, current->name.other.len);
01045     break;
01046   case certX400Address:
01047     nssComponent->GetPIPNSSBundleString("CertDumpX400Address", key);
01048     ProcessRawBytes(nssComponent, &current->name.other, value);
01049     break;
01050   case certDirectoryName:
01051     nssComponent->GetPIPNSSBundleString("CertDumpDirectoryName", key);
01052     rv = ProcessName(&current->name.directoryName, nssComponent, 
01053                    getter_Copies(value));
01054     if (NS_FAILED(rv))
01055       goto finish;
01056     break;
01057   case certEDIPartyName:
01058     nssComponent->GetPIPNSSBundleString("CertDumpEDIPartyName", key);
01059     ProcessRawBytes(nssComponent, &current->name.other, value);
01060     break;
01061   case certURI:
01062     nssComponent->GetPIPNSSBundleString("CertDumpURI", key);
01063     value.AssignASCII((char*)current->name.other.data, current->name.other.len);
01064     break;
01065   case certIPAddress:
01066     {
01067       char buf[INET6_ADDRSTRLEN];
01068       PRStatus status = PR_FAILURE;
01069       PRNetAddr addr;
01070       memset(&addr, 0, sizeof(addr));
01071       nssComponent->GetPIPNSSBundleString("CertDumpIPAddress", key);
01072       if (current->name.other.len == 4) {
01073         addr.inet.family = PR_AF_INET;
01074         memcpy(&addr.inet.ip, current->name.other.data, current->name.other.len);
01075         status = PR_NetAddrToString(&addr, buf, sizeof(buf));
01076       } else if (current->name.other.len == 16) {
01077         addr.ipv6.family = PR_AF_INET6;
01078         memcpy(&addr.ipv6.ip, current->name.other.data, current->name.other.len);
01079         status = PR_NetAddrToString(&addr, buf, sizeof(buf));
01080       }
01081       if (status == PR_SUCCESS) {
01082         value.AssignASCII(buf);
01083       } else {
01084         /* invalid IP address */
01085         ProcessRawBytes(nssComponent, &current->name.other, value);
01086       }
01087       break;
01088     }
01089   case certRegisterID:
01090     nssComponent->GetPIPNSSBundleString("CertDumpRegisterID", key);
01091     rv = GetDefaultOIDFormat(&current->name.other, value, '.');
01092     if (NS_FAILED(rv))
01093       goto finish;
01094     break;
01095   }
01096   text.Append(key);
01097   text.Append(NS_LITERAL_STRING(": "));
01098   text.Append(value);
01099   text.Append(NS_LITERAL_STRING(SEPARATOR));
01100  finish:
01101     return rv;
01102 }
01103 
01104 static nsresult
01105 ProcessGeneralNames(PRArenaPool *arena,
01106                   CERTGeneralName *nameList,
01107                   nsAString &text,
01108                   nsINSSComponent *nssComponent)
01109 {
01110   CERTGeneralName *current = nameList;
01111   nsresult rv;
01112 
01113   do {
01114     rv = ProcessGeneralName(arena, current, text, nssComponent);
01115     if (NS_FAILED(rv))
01116       break;
01117     current = CERT_GetNextGeneralName(current);
01118   } while (current != nameList);
01119   return rv;
01120 }
01121 
01122 static nsresult
01123 ProcessAltName(SECItem  *extData, 
01124               nsAString &text,
01125               nsINSSComponent *nssComponent)
01126 {
01127   nsresult rv = NS_OK;
01128   PRArenaPool *arena;
01129   CERTGeneralName *nameList;
01130 
01131   arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
01132   if (!arena)
01133     return NS_ERROR_FAILURE;
01134 
01135   nameList = CERT_DecodeAltNameExtension(arena, extData);
01136   if (!nameList)
01137     goto finish;
01138 
01139   rv = ProcessGeneralNames(arena, nameList, text, nssComponent);
01140 
01141  finish:
01142   PORT_FreeArena(arena, PR_FALSE);
01143   return rv;
01144 }
01145 
01146 static nsresult
01147 ProcessSubjectKeyId(SECItem  *extData, 
01148                   nsAString &text,
01149                   nsINSSComponent *nssComponent)
01150 {
01151   PRArenaPool *arena;
01152   nsresult rv = NS_OK;
01153   SECItem decoded;
01154   nsAutoString local;
01155 
01156   arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
01157   if (!arena)
01158     return NS_ERROR_FAILURE;
01159 
01160   if (SEC_QuickDERDecodeItem(arena, &decoded, 
01161                           SEC_ASN1_GET(SEC_OctetStringTemplate), 
01162                           extData) != SECSuccess) {
01163     rv = NS_ERROR_FAILURE;
01164     goto finish;
01165   }
01166   
01167   nssComponent->GetPIPNSSBundleString("CertDumpKeyID", local);
01168   text.Append(local);
01169   text.Append(NS_LITERAL_STRING(": "));
01170   ProcessRawBytes(nssComponent, &decoded, text);
01171 
01172  finish:
01173   PORT_FreeArena(arena, PR_FALSE);
01174   return rv;
01175 }
01176 
01177 static nsresult
01178 ProcessAuthKeyId(SECItem  *extData, 
01179                nsAString &text,
01180                nsINSSComponent *nssComponent)
01181 {
01182   CERTAuthKeyID *ret;
01183   PRArenaPool *arena;
01184   nsresult rv = NS_OK;
01185   nsAutoString local;
01186 
01187   arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
01188   if (!arena)
01189     return NS_ERROR_FAILURE;
01190 
01191   ret = CERT_DecodeAuthKeyID (arena, extData);
01192 
01193   if (ret->keyID.len > 0) {
01194     nssComponent->GetPIPNSSBundleString("CertDumpKeyID", local);
01195     text.Append(local);
01196     text.Append(NS_LITERAL_STRING(": "));
01197     ProcessRawBytes(nssComponent, &ret->keyID, text);
01198     text.Append(NS_LITERAL_STRING(SEPARATOR));
01199   }
01200 
01201   if (ret->authCertIssuer) {
01202     nssComponent->GetPIPNSSBundleString("CertDumpIssuer", local);
01203     text.Append(local);
01204     text.Append(NS_LITERAL_STRING(": "));
01205     rv = ProcessGeneralNames(arena, ret->authCertIssuer, text, nssComponent);
01206     if (NS_FAILED(rv))
01207       goto finish;
01208   }
01209 
01210   if (ret->authCertSerialNumber.len > 0) {
01211     nssComponent->GetPIPNSSBundleString("CertDumpSerialNo", local);
01212     text.Append(local);
01213     text.Append(NS_LITERAL_STRING(": "));
01214     ProcessRawBytes(nssComponent, &ret->authCertSerialNumber, text);
01215   }
01216 
01217  finish:
01218   PORT_FreeArena(arena, PR_FALSE);
01219   return rv;
01220 }
01221 
01222 enum DisplayTextForm { VisibleForm, BMPForm, UTF8Form };
01223 
01224 struct DisplayText {
01225   DisplayTextForm variant;
01226   SECItem value;
01227 };
01228 
01229 const SEC_ASN1Template DisplayTextTemplate[] = {
01230     { SEC_ASN1_CHOICE,
01231       offsetof(DisplayText, variant), NULL,
01232       sizeof(DisplayText) },
01233     { SEC_ASN1_IA5_STRING, 
01234       offsetof(DisplayText, value), NULL, VisibleForm },
01235     { SEC_ASN1_VISIBLE_STRING, 
01236       offsetof(DisplayText, value), NULL, VisibleForm },
01237     { SEC_ASN1_BMP_STRING, 
01238       offsetof(DisplayText, value), NULL, BMPForm },
01239     { SEC_ASN1_UTF8_STRING, 
01240       offsetof(DisplayText, value), NULL, UTF8Form },
01241     { 0 }
01242 };
01243 
01244 static nsresult
01245 ProcessUserNotice(SECItem *der_notice,
01246                 nsAString &text,
01247                 nsINSSComponent *nssComponent)
01248 {
01249   nsresult rv = NS_OK;
01250   CERTUserNotice *notice = NULL;
01251   SECItem **itemList;
01252   DisplayText display;
01253   PRArenaPool *arena;
01254   char *buf;
01255 
01256   arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
01257   if (!arena)
01258     return NS_ERROR_FAILURE;
01259 
01260   notice = CERT_DecodeUserNotice(der_notice);
01261   /* XXX: currently, polcyxtn.c assumes that organization
01262      is an IA5String, whereas it really ought to be a
01263      choice of VisibleString, BMPString, and UTF8String.
01264      So if decoding of the user notice fails, it is most likely
01265      that the organization was encoded in an unexpected way.
01266      Make this function return "something" in this case,
01267      instead letting the decode for the entire certificate
01268      fail.
01269   */
01270   if (notice == NULL) {
01271     text.Append(NS_LITERAL_STRING("<implementation limitation>"));
01272     goto finish;
01273   }
01274 
01275   if (notice->noticeReference.organization.len != 0) {
01276     rv = ProcessIA5String(&notice->noticeReference.organization,
01277                        text, nssComponent);
01278     if (NS_FAILED(rv))
01279       goto finish;
01280 
01281     itemList = notice->noticeReference.noticeNumbers;
01282     while (*itemList) {
01283       unsigned long number;
01284       char buffer[60];
01285       if (SEC_ASN1DecodeInteger(*itemList, &number) != SECSuccess) {
01286        rv = NS_ERROR_FAILURE;
01287        goto finish;
01288       }
01289       PR_snprintf(buffer, sizeof(buffer), "%d ", number);
01290       AppendASCIItoUTF16(buffer, text);
01291       itemList++;
01292     }
01293   }
01294   if (notice->displayText.len != 0) {
01295     if (SEC_QuickDERDecodeItem(arena, &display,
01296                             DisplayTextTemplate,
01297                             &notice->displayText) != SECSuccess) {
01298       rv = NS_ERROR_FAILURE;
01299       goto finish;
01300     }
01301     switch (display.variant) {
01302     case VisibleForm:
01303       /* Need to null-terminate string before appending it. */
01304       buf = (char*)PORT_ArenaAlloc(arena, display.value.len+1);
01305       PORT_Memcpy(buf, display.value.data, display.value.len);
01306       buf[display.value.len] = '\0';
01307       text.AppendASCII(buf);
01308       break;
01309     case BMPForm:
01310       AppendBMPtoUTF16(arena, display.value.data, display.value.len,
01311                      text);
01312       break;
01313     case UTF8Form:
01314       buf = (char*)PORT_ArenaAlloc(arena, display.value.len+1);
01315       PORT_Memcpy(buf, display.value.data, display.value.len);
01316       buf[display.value.len] = '\0';
01317       AppendUTF8toUTF16(buf, text);
01318       break;
01319     }
01320   }
01321  finish:
01322   if (notice)
01323     CERT_DestroyUserNotice(notice);
01324   PORT_FreeArena(arena, PR_FALSE);
01325   return rv;
01326 }
01327 
01328 static nsresult
01329 ProcessCertificatePolicies(SECItem  *extData, 
01330                         nsAString &text,
01331                         nsINSSComponent *nssComponent)
01332 {
01333   CERTCertificatePolicies *policies;
01334   CERTPolicyInfo **policyInfos, *policyInfo;
01335   CERTPolicyQualifier **policyQualifiers, *policyQualifier;
01336   nsAutoString local;
01337   nsresult rv = NS_OK;
01338 
01339   policies = CERT_DecodeCertificatePoliciesExtension(extData);
01340   if ( policies == NULL )
01341     return NS_ERROR_FAILURE;
01342 
01343   policyInfos = policies->policyInfos;
01344   while (*policyInfos != NULL ) {
01345     policyInfo = *policyInfos++;
01346     switch (policyInfo->oid) {
01347     case SEC_OID_VERISIGN_USER_NOTICES:
01348       nssComponent->GetPIPNSSBundleString("CertDumpVerisignNotices", local);
01349       text.Append(local);
01350       break;
01351     default:
01352       GetDefaultOIDFormat(&policyInfo->policyID, local, '.');
01353       text.Append(local);
01354     }
01355     if (policyInfo->policyQualifiers) {
01356       /* Add all qualifiers on separate lines, indented */
01357       policyQualifiers = policyInfo->policyQualifiers;
01358       text.Append(NS_LITERAL_STRING(":"));
01359       text.Append(NS_LITERAL_STRING(SEPARATOR));
01360       while (*policyQualifiers != NULL) {
01361        text.Append(NS_LITERAL_STRING("  "));
01362        policyQualifier = *policyQualifiers++;
01363        switch(policyQualifier->oid) {
01364        case SEC_OID_PKIX_CPS_POINTER_QUALIFIER:
01365          nssComponent->GetPIPNSSBundleString("CertDumpCPSPointer", local);
01366          text.Append(local);
01367          text.Append(NS_LITERAL_STRING(":"));
01368          text.Append(NS_LITERAL_STRING(SEPARATOR));
01369          text.Append(NS_LITERAL_STRING("    "));
01370          /* The CPS pointer ought to be the cPSuri alternative
01371             of the Qualifier choice. */
01372          rv = ProcessIA5String(&policyQualifier->qualifierValue,
01373                             text, nssComponent);
01374          if (NS_FAILED(rv))
01375            goto finish;
01376          break;
01377        case SEC_OID_PKIX_USER_NOTICE_QUALIFIER:
01378          nssComponent->GetPIPNSSBundleString("CertDumpUserNotice", local);
01379          text.Append(local);
01380          text.Append(NS_LITERAL_STRING(": "));
01381          rv = ProcessUserNotice(&policyQualifier->qualifierValue,
01382                              text, nssComponent);
01383          break;
01384        default:
01385          GetDefaultOIDFormat(&policyQualifier->qualifierID, local, '.');
01386          text.Append(local);
01387          text.Append(NS_LITERAL_STRING(": "));
01388          ProcessRawBytes(nssComponent, &policyQualifier->qualifierValue, text);
01389        }
01390        text.Append(NS_LITERAL_STRING(SEPARATOR));
01391       } /* while policyQualifiers */
01392     } /* if policyQualifiers */
01393     text.Append(NS_LITERAL_STRING(SEPARATOR));
01394   }
01395 
01396  finish:
01397   CERT_DestroyCertificatePoliciesExtension(policies);
01398   return rv;
01399 }
01400 
01401 static nsresult
01402 ProcessCrlDistPoints(SECItem  *extData, 
01403                    nsAString &text,
01404                    nsINSSComponent *nssComponent)
01405 {
01406   CERTCrlDistributionPoints *crldp;
01407   CRLDistributionPoint **points, *point;
01408   PRArenaPool *arena;
01409   nsresult rv = NS_OK;
01410   nsAutoString local;
01411   int reasons, comma;
01412 
01413   arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
01414   if (!arena)
01415     return NS_ERROR_FAILURE;
01416 
01417   crldp = CERT_DecodeCRLDistributionPoints(arena, extData);
01418   if (!crldp || !crldp->distPoints) {
01419     rv = NS_ERROR_FAILURE;
01420     goto finish;
01421   }
01422 
01423   for(points = crldp->distPoints; *points; points++) {
01424     point = *points;
01425     switch (point->distPointType) {
01426     case generalName:
01427       rv = ProcessGeneralName(arena, point->distPoint.fullName,
01428                            text, nssComponent);
01429       if (NS_FAILED(rv))
01430        goto finish;
01431       break;
01432     case relativeDistinguishedName:
01433       rv = ProcessRDN(&point->distPoint.relativeName, 
01434                     text, nssComponent);
01435       if (NS_FAILED(rv))
01436        goto finish;
01437       break;
01438     }
01439     if (point->reasons.len) { 
01440       reasons = point->reasons.data[0];
01441       text.Append(NS_LITERAL_STRING(" "));
01442       comma = 0;
01443       if (reasons & RF_UNUSED) {
01444        nssComponent->GetPIPNSSBundleString("CertDumpUnused", local);
01445        text.Append(local); comma = 1;
01446       }
01447       if (reasons & RF_KEY_COMPROMISE) {
01448        if (comma) text.Append(NS_LITERAL_STRING(", "));
01449        nssComponent->GetPIPNSSBundleString("CertDumpKeyCompromise", local);
01450        text.Append(local); comma = 1;
01451       }
01452       if (reasons & RF_CA_COMPROMISE) {
01453        if (comma) text.Append(NS_LITERAL_STRING(", "));
01454        nssComponent->GetPIPNSSBundleString("CertDumpCACompromise", local);
01455        text.Append(local); comma = 1;
01456       }
01457       if (reasons & RF_AFFILIATION_CHANGED) {
01458        if (comma) text.Append(NS_LITERAL_STRING(", "));
01459        nssComponent->GetPIPNSSBundleString("CertDumpAffiliationChanged", local);
01460        text.Append(local); comma = 1;
01461       }
01462       if (reasons & RF_SUPERSEDED) {
01463        if (comma) text.Append(NS_LITERAL_STRING(", "));
01464        nssComponent->GetPIPNSSBundleString("CertDumpSuperseded", local);
01465        text.Append(local); comma = 1;
01466       }
01467       if (reasons & RF_CESSATION_OF_OPERATION) {
01468        if (comma) text.Append(NS_LITERAL_STRING(", "));
01469        nssComponent->GetPIPNSSBundleString("CertDumpCessation", local);
01470        text.Append(local); comma = 1;
01471       }
01472       if (reasons & RF_CERTIFICATE_HOLD) {
01473        if (comma) text.Append(NS_LITERAL_STRING(", "));
01474        nssComponent->GetPIPNSSBundleString("CertDumpHold", local);
01475        text.Append(local); comma = 1;
01476       }
01477       text.Append(NS_LITERAL_STRING(SEPARATOR));
01478     }
01479     if (point->crlIssuer) {
01480       nssComponent->GetPIPNSSBundleString("CertDumpIssuer", local);
01481       text.Append(local);
01482       text.Append(NS_LITERAL_STRING(": "));
01483       rv = ProcessGeneralNames(arena, point->crlIssuer,
01484                             text, nssComponent);
01485       if (NS_FAILED(rv))
01486        goto finish;
01487     }
01488   }
01489   
01490  finish:
01491   PORT_FreeArena(arena, PR_FALSE);
01492   return NS_OK;
01493 }
01494 
01495 static nsresult
01496 ProcessAuthInfoAccess(SECItem  *extData, 
01497                     nsAString &text,
01498                     nsINSSComponent *nssComponent)
01499 {
01500   CERTAuthInfoAccess **aia, *desc;
01501   PRArenaPool *arena;
01502   nsresult rv = NS_OK;
01503   nsAutoString local;
01504 
01505   arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
01506   if (!arena)
01507     return NS_ERROR_FAILURE;
01508 
01509   aia = CERT_DecodeAuthInfoAccessExtension(arena, extData);
01510   if (aia == NULL)
01511     goto finish;
01512 
01513   while (*aia != NULL) {
01514     desc = *aia++;
01515     switch (SECOID_FindOIDTag(&desc->method)) {
01516     case SEC_OID_PKIX_OCSP:
01517       nssComponent->GetPIPNSSBundleString("CertDumpOCSPResponder", local);
01518       break;
01519     case SEC_OID_PKIX_CA_ISSUERS:
01520       nssComponent->GetPIPNSSBundleString("CertDumpCAIssuers", local);
01521       break;
01522     default:
01523       rv = GetDefaultOIDFormat(&desc->method, local, '.');
01524       if (NS_FAILED(rv))
01525        goto finish;
01526     }
01527     text.Append(local);
01528     text.Append(NS_LITERAL_STRING(": "));
01529     rv = ProcessGeneralName(arena, desc->location, text, nssComponent);
01530     if (NS_FAILED(rv))
01531       goto finish;
01532   }
01533 
01534  finish:
01535   PORT_FreeArena(arena, PR_FALSE);
01536   return rv;
01537 }
01538 
01539 static nsresult
01540 ProcessMSCAVersion(SECItem  *extData, 
01541                  nsAString &text,
01542                  nsINSSComponent *nssComponent)
01543 {
01544   unsigned long version;
01545   nsresult rv;
01546   char buf[50];
01547   SECItem decoded;
01548 
01549   if (SECSuccess != SEC_ASN1DecodeItem(nsnull, &decoded, 
01550                                    SEC_ASN1_GET(SEC_IntegerTemplate), 
01551                                    extData))
01552     /* This extension used to be an Integer when this code
01553        was written, but apparently isn't anymore. Display
01554        the raw bytes instead. */
01555     return ProcessRawBytes(nssComponent, extData, text);
01556 
01557   rv = GetIntValue(&decoded, &version);
01558   nsMemory::Free(decoded.data);
01559   if (NS_FAILED(rv))
01560     /* Value out of range, display raw bytes */
01561     return ProcessRawBytes(nssComponent, extData, text);
01562 
01563   /* Apparently, the encoding is <minor><major>, with 16 bits each */
01564   PR_snprintf(buf, sizeof(buf), "%d.%d", version & 0xFFFF, version>>16);
01565   text.AppendASCII(buf);
01566   return NS_OK;
01567 }
01568 
01569 static nsresult
01570 ProcessExtensionData(SECOidTag oidTag, SECItem *extData, 
01571                      nsAString &text, nsINSSComponent *nssComponent)
01572 {
01573   nsresult rv;
01574   switch (oidTag) {
01575   case SEC_OID_NS_CERT_EXT_CERT_TYPE:
01576     rv = ProcessNSCertTypeExtensions(extData, text, nssComponent);
01577     break;
01578   case SEC_OID_X509_KEY_USAGE:
01579     rv = ProcessKeyUsageExtension(extData, text, nssComponent);
01580     break;
01581   case SEC_OID_X509_BASIC_CONSTRAINTS:
01582     rv = ProcessBasicConstraints(extData, text, nssComponent);
01583     break;
01584   case SEC_OID_X509_EXT_KEY_USAGE:
01585     rv = ProcessExtKeyUsage(extData, text, nssComponent);
01586     break;
01587   case SEC_OID_X509_ISSUER_ALT_NAME:
01588   case SEC_OID_X509_SUBJECT_ALT_NAME:
01589     rv = ProcessAltName(extData, text, nssComponent);
01590     break;
01591   case SEC_OID_X509_SUBJECT_KEY_ID:
01592     rv = ProcessSubjectKeyId(extData, text, nssComponent);
01593     break;
01594   case SEC_OID_X509_AUTH_KEY_ID:
01595     rv = ProcessAuthKeyId(extData, text, nssComponent);
01596     break;
01597   case SEC_OID_X509_CERTIFICATE_POLICIES:
01598     rv = ProcessCertificatePolicies(extData, text, nssComponent);
01599     break;
01600   case SEC_OID_X509_CRL_DIST_POINTS:
01601     rv = ProcessCrlDistPoints(extData, text, nssComponent);
01602     break;
01603   case SEC_OID_X509_AUTH_INFO_ACCESS:
01604     rv = ProcessAuthInfoAccess(extData, text, nssComponent);
01605     break;
01606   case SEC_OID_NS_CERT_EXT_BASE_URL:
01607   case SEC_OID_NS_CERT_EXT_REVOCATION_URL:
01608   case SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL:
01609   case SEC_OID_NS_CERT_EXT_CA_CERT_URL:
01610   case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL:
01611   case SEC_OID_NS_CERT_EXT_CA_POLICY_URL:
01612   case SEC_OID_NS_CERT_EXT_HOMEPAGE_URL:
01613   case SEC_OID_NS_CERT_EXT_COMMENT:
01614   case SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME:
01615   case SEC_OID_NS_CERT_EXT_LOST_PASSWORD_URL:
01616     rv = ProcessIA5String(extData, text, nssComponent);
01617     break;
01618   default:
01619     if (oidTag == SEC_OID(MS_CERT_EXT_CERTTYPE)) {
01620       rv = ProcessBMPString(extData, text, nssComponent);
01621       break;
01622     }
01623     if (oidTag == SEC_OID(MS_CERTSERV_CA_VERSION)) {
01624       rv = ProcessMSCAVersion(extData, text, nssComponent);
01625       break;
01626     }
01627     rv = ProcessRawBytes(nssComponent, extData, text);
01628     break; 
01629   }
01630   return rv;
01631 }
01632 
01633 static nsresult
01634 ProcessSingleExtension(CERTCertExtension *extension,
01635                        nsINSSComponent *nssComponent,
01636                        nsIASN1PrintableItem **retExtension)
01637 {
01638   nsAutoString text;
01639   GetOIDText(&extension->id, nssComponent, text);
01640   nsCOMPtr<nsIASN1PrintableItem>extensionItem = new nsNSSASN1PrintableItem();
01641   if (extensionItem == nsnull)
01642     return NS_ERROR_OUT_OF_MEMORY;
01643 
01644   extensionItem->SetDisplayName(text);
01645   SECOidTag oidTag = SECOID_FindOIDTag(&extension->id);
01646   text.Truncate();
01647   if (extension->critical.data != nsnull) {
01648     if (extension->critical.data[0]) {
01649       nssComponent->GetPIPNSSBundleString("CertDumpCritical", text);
01650     } else {
01651       nssComponent->GetPIPNSSBundleString("CertDumpNonCritical", text);
01652     }
01653   } else {
01654     nssComponent->GetPIPNSSBundleString("CertDumpNonCritical", text);
01655   }
01656   text.Append(NS_LITERAL_STRING(SEPARATOR).get());
01657   nsresult rv = ProcessExtensionData(oidTag, &extension->value, text, 
01658                                      nssComponent);
01659   if (NS_FAILED(rv))
01660     return rv;
01661 
01662   extensionItem->SetDisplayValue(text);
01663   *retExtension = extensionItem;
01664   NS_ADDREF(*retExtension);
01665   return NS_OK;
01666 }
01667 
01668 static nsresult
01669 ProcessSECAlgorithmID(SECAlgorithmID *algID,
01670                       nsINSSComponent *nssComponent,
01671                       nsIASN1Sequence **retSequence)
01672 {
01673   SECOidTag algOIDTag = SECOID_FindOIDTag(&algID->algorithm);
01674   SECItem paramsOID = { siBuffer, NULL, 0 };
01675   nsCOMPtr<nsIASN1Sequence> sequence = new nsNSSASN1Sequence();
01676   if (sequence == nsnull)
01677     return NS_ERROR_OUT_OF_MEMORY;
01678 
01679   *retSequence = nsnull;
01680   nsString text;
01681   GetOIDText(&algID->algorithm, nssComponent, text);
01682   if (!algID->parameters.len || algID->parameters.data[0] == nsIASN1Object::ASN1_NULL) {
01683     sequence->SetDisplayValue(text);
01684     sequence->SetIsValidContainer(PR_FALSE);
01685   } else {
01686     nsCOMPtr<nsIASN1PrintableItem> printableItem = new nsNSSASN1PrintableItem();
01687     if (printableItem == nsnull)
01688       return NS_ERROR_OUT_OF_MEMORY;
01689 
01690     printableItem->SetDisplayValue(text);
01691     nsCOMPtr<nsIMutableArray> asn1Objects;
01692     sequence->GetASN1Objects(getter_AddRefs(asn1Objects));
01693     asn1Objects->AppendElement(printableItem, PR_FALSE);
01694     nssComponent->GetPIPNSSBundleString("CertDumpAlgID", text);
01695     printableItem->SetDisplayName(text);
01696 
01697     printableItem = new nsNSSASN1PrintableItem();
01698     if (printableItem == nsnull)
01699       return NS_ERROR_OUT_OF_MEMORY;
01700 
01701     asn1Objects->AppendElement(printableItem, PR_FALSE);
01702     nssComponent->GetPIPNSSBundleString("CertDumpParams", text);
01703     printableItem->SetDisplayName(text);
01704     if ((algOIDTag == SEC_OID_ANSIX962_EC_PUBLIC_KEY) &&
01705         (algID->parameters.len > 2) && 
01706         (algID->parameters.data[0] == nsIASN1Object::ASN1_OBJECT_ID)) {
01707        paramsOID.len = algID->parameters.len - 2;
01708        paramsOID.data = algID->parameters.data + 2;
01709        GetOIDText(&paramsOID, nssComponent, text);
01710     } else {
01711        ProcessRawBytes(nssComponent, &algID->parameters,text);
01712     }
01713     printableItem->SetDisplayValue(text);
01714   }
01715   *retSequence = sequence;
01716   NS_ADDREF(*retSequence);
01717   return NS_OK;
01718 }
01719 
01720 static nsresult
01721 ProcessTime(PRTime dispTime, const PRUnichar *displayName, 
01722             nsIASN1Sequence *parentSequence)
01723 {
01724   nsresult rv;
01725   nsCOMPtr<nsIDateTimeFormat> dateFormatter =
01726      do_CreateInstance(kDateTimeFormatCID, &rv);
01727   if (NS_FAILED(rv)) 
01728     return rv;
01729 
01730   nsString text;
01731   nsString tempString;
01732 
01733   PRExplodedTime explodedTime;
01734   PR_ExplodeTime(dispTime, PR_LocalTimeParameters, &explodedTime);
01735 
01736   dateFormatter->FormatPRExplodedTime(nsnull, kDateFormatShort, kTimeFormatSecondsForce24Hour,
01737                               &explodedTime, tempString);
01738 
01739   text.Append(tempString);
01740   text.AppendLiteral("\n(");
01741 
01742   PRExplodedTime explodedTimeGMT;
01743   PR_ExplodeTime(dispTime, PR_GMTParameters, &explodedTimeGMT);
01744 
01745   dateFormatter->FormatPRExplodedTime(nsnull, kDateFormatShort, kTimeFormatSecondsForce24Hour,
01746                               &explodedTimeGMT, tempString);
01747 
01748   text.Append(tempString);
01749   text.Append(NS_LITERAL_STRING(" GMT)"));
01750 
01751   nsCOMPtr<nsIASN1PrintableItem> printableItem = new nsNSSASN1PrintableItem();
01752   if (printableItem == nsnull)
01753     return NS_ERROR_OUT_OF_MEMORY;
01754 
01755   printableItem->SetDisplayValue(text);
01756   printableItem->SetDisplayName(nsDependentString(displayName));
01757   nsCOMPtr<nsIMutableArray> asn1Objects;
01758   parentSequence->GetASN1Objects(getter_AddRefs(asn1Objects));
01759   asn1Objects->AppendElement(printableItem, PR_FALSE);
01760   return NS_OK;
01761 }
01762 
01763 static nsresult
01764 ProcessSubjectPublicKeyInfo(CERTSubjectPublicKeyInfo *spki, 
01765                             nsIASN1Sequence *parentSequence,
01766                             nsINSSComponent *nssComponent)
01767 {
01768   nsCOMPtr<nsIASN1Sequence> spkiSequence = new nsNSSASN1Sequence();
01769 
01770   if (spkiSequence == nsnull)
01771     return NS_ERROR_OUT_OF_MEMORY;
01772 
01773   nsString text;
01774   nssComponent->GetPIPNSSBundleString("CertDumpSPKI", text);
01775   spkiSequence->SetDisplayName(text);
01776 
01777   nssComponent->GetPIPNSSBundleString("CertDumpSPKIAlg", text);
01778   nsCOMPtr<nsIASN1Sequence> sequenceItem;
01779   nsresult rv = ProcessSECAlgorithmID(&spki->algorithm, nssComponent,
01780                                       getter_AddRefs(sequenceItem));
01781   if (NS_FAILED(rv))
01782     return rv;
01783   sequenceItem->SetDisplayName(text);
01784   nsCOMPtr<nsIMutableArray> asn1Objects;
01785   spkiSequence->GetASN1Objects(getter_AddRefs(asn1Objects));
01786   asn1Objects->AppendElement(sequenceItem, PR_FALSE);
01787 
01788   // The subjectPublicKey field is encoded as a bit string.
01789   // ProcessRawBytes expects the lenght to be in bytes, so 
01790   // let's convert the lenght into a temporary SECItem.
01791   SECItem data;
01792   data.data = spki->subjectPublicKey.data;
01793   data.len  = spki->subjectPublicKey.len / 8;
01794   text.Truncate();
01795   ProcessRawBytes(nssComponent, &data, text);
01796   nsCOMPtr<nsIASN1PrintableItem> printableItem = new nsNSSASN1PrintableItem();
01797   if (printableItem == nsnull)
01798     return NS_ERROR_OUT_OF_MEMORY;
01799 
01800   printableItem->SetDisplayValue(text);
01801   nssComponent->GetPIPNSSBundleString("CertDumpSubjPubKey", text);
01802   printableItem->SetDisplayName(text);
01803   asn1Objects->AppendElement(printableItem, PR_FALSE);
01804   
01805   parentSequence->GetASN1Objects(getter_AddRefs(asn1Objects));
01806   asn1Objects->AppendElement(spkiSequence, PR_FALSE);
01807   return NS_OK;
01808 }
01809 
01810 static nsresult
01811 ProcessExtensions(CERTCertExtension **extensions, 
01812                   nsIASN1Sequence *parentSequence, 
01813                   nsINSSComponent *nssComponent)
01814 {
01815   nsCOMPtr<nsIASN1Sequence> extensionSequence = new nsNSSASN1Sequence;
01816   if (extensionSequence == nsnull)
01817     return NS_ERROR_OUT_OF_MEMORY;
01818 
01819   nsString text;
01820   nssComponent->GetPIPNSSBundleString("CertDumpExtensions", text);
01821   extensionSequence->SetDisplayName(text);
01822   PRInt32 i;
01823   nsresult rv;
01824   nsCOMPtr<nsIASN1PrintableItem> newExtension;
01825   nsCOMPtr<nsIMutableArray> asn1Objects;
01826   extensionSequence->GetASN1Objects(getter_AddRefs(asn1Objects));
01827   for (i=0; extensions[i] != nsnull; i++) {
01828     rv = ProcessSingleExtension(extensions[i], nssComponent,
01829                                 getter_AddRefs(newExtension));
01830     if (NS_FAILED(rv))
01831       return rv;
01832 
01833     asn1Objects->AppendElement(newExtension, PR_FALSE);
01834   }
01835   parentSequence->GetASN1Objects(getter_AddRefs(asn1Objects));
01836   asn1Objects->AppendElement(extensionSequence, PR_FALSE);
01837   return NS_OK;
01838 }
01839 
01840 static bool registered;
01841 static SECStatus RegisterDynamicOids()
01842 {
01843   unsigned int i;
01844   SECStatus rv = SECSuccess;
01845 
01846   if (registered)
01847     return rv;
01848 
01849   for (i = 0; i < numOids; i++) {
01850     SECOidTag tag = SECOID_AddEntry(&more_oids[i]);
01851     if (tag == SEC_OID_UNKNOWN) {
01852       rv = SECFailure;
01853       continue;
01854     }
01855     more_oids[i].offset = tag;
01856   }
01857   registered = true;
01858   return rv;
01859 }
01860 
01861 nsresult
01862 nsNSSCertificate::CreateTBSCertificateASN1Struct(nsIASN1Sequence **retSequence,
01863                                                  nsINSSComponent *nssComponent)
01864 {
01865   nsNSSShutDownPreventionLock locker;
01866   if (isAlreadyShutDown())
01867     return NS_ERROR_NOT_AVAILABLE;
01868 
01869   if (RegisterDynamicOids() != SECSuccess)
01870     return NS_ERROR_FAILURE;
01871 
01872   //
01873   //   TBSCertificate  ::=  SEQUENCE  {
01874   //        version         [0]  EXPLICIT Version DEFAULT v1,
01875   //        serialNumber         CertificateSerialNumber,
01876   //        signature            AlgorithmIdentifier,
01877   //        issuer               Name,
01878   //        validity             Validity,
01879   //        subject              Name,
01880   //        subjectPublicKeyInfo SubjectPublicKeyInfo,
01881   //        issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
01882   //                             -- If present, version shall be v2 or v3
01883   //        subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
01884   //                             -- If present, version shall be v2 or v3
01885   //        extensions      [3]  EXPLICIT Extensions OPTIONAL
01886   //                            -- If present, version shall be v3
01887   //        }
01888   //
01889   // This is the ASN1 structure we should be dealing with at this point.
01890   // The code in this method will assert this is the structure we're dealing
01891   // and then add more user friendly text for that field.
01892   nsCOMPtr<nsIASN1Sequence> sequence = new nsNSSASN1Sequence();
01893   if (sequence == nsnull)
01894     return NS_ERROR_OUT_OF_MEMORY;
01895 
01896   nsString text;
01897   nssComponent->GetPIPNSSBundleString("CertDumpCertificate", text);
01898   sequence->SetDisplayName(text);
01899   nsCOMPtr<nsIASN1PrintableItem> printableItem;
01900   
01901   nsCOMPtr<nsIMutableArray> asn1Objects;
01902   sequence->GetASN1Objects(getter_AddRefs(asn1Objects));
01903 
01904   nsresult rv = ProcessVersion(&mCert->version, nssComponent,
01905                                getter_AddRefs(printableItem));
01906   if (NS_FAILED(rv))
01907     return rv;
01908 
01909   asn1Objects->AppendElement(printableItem, PR_FALSE);
01910   
01911   rv = ProcessSerialNumberDER(&mCert->serialNumber, nssComponent,
01912                               getter_AddRefs(printableItem));
01913 
01914   if (NS_FAILED(rv))
01915     return rv;
01916   asn1Objects->AppendElement(printableItem, PR_FALSE);
01917 
01918   nsCOMPtr<nsIASN1Sequence> algID;
01919   rv = ProcessSECAlgorithmID(&mCert->signature,
01920                              nssComponent, getter_AddRefs(algID));
01921   if (NS_FAILED(rv))
01922     return rv;
01923 
01924   nssComponent->GetPIPNSSBundleString("CertDumpSigAlg", text);
01925   algID->SetDisplayName(text);
01926   asn1Objects->AppendElement(algID, PR_FALSE);
01927 
01928   nsXPIDLString value;
01929   ProcessName(&mCert->issuer, nssComponent, getter_Copies(value));
01930 
01931   printableItem = new nsNSSASN1PrintableItem();
01932   if (printableItem == nsnull)
01933     return NS_ERROR_OUT_OF_MEMORY;
01934 
01935   printableItem->SetDisplayValue(value);
01936   nssComponent->GetPIPNSSBundleString("CertDumpIssuer", text);
01937   printableItem->SetDisplayName(text);
01938   asn1Objects->AppendElement(printableItem, PR_FALSE);
01939   
01940   nsCOMPtr<nsIASN1Sequence> validitySequence = new nsNSSASN1Sequence();
01941   nssComponent->GetPIPNSSBundleString("CertDumpValidity", text);
01942   validitySequence->SetDisplayName(text);
01943   asn1Objects->AppendElement(validitySequence, PR_FALSE);
01944   nssComponent->GetPIPNSSBundleString("CertDumpNotBefore", text);
01945   nsCOMPtr<nsIX509CertValidity> validityData;
01946   GetValidity(getter_AddRefs(validityData));
01947   PRTime notBefore, notAfter;
01948 
01949   validityData->GetNotBefore(&notBefore);
01950   validityData->GetNotAfter(&notAfter);
01951   validityData = 0;
01952   rv = ProcessTime(notBefore, text.get(), validitySequence);
01953   if (NS_FAILED(rv))
01954     return rv;
01955 
01956   nssComponent->GetPIPNSSBundleString("CertDumpNotAfter", text);
01957   rv = ProcessTime(notAfter, text.get(), validitySequence);
01958   if (NS_FAILED(rv))
01959     return rv;
01960 
01961   nssComponent->GetPIPNSSBundleString("CertDumpSubject", text);
01962 
01963   printableItem = new nsNSSASN1PrintableItem();
01964   if (printableItem == nsnull)
01965     return NS_ERROR_OUT_OF_MEMORY;
01966 
01967   printableItem->SetDisplayName(text);
01968   ProcessName(&mCert->subject, nssComponent,getter_Copies(value));
01969   printableItem->SetDisplayValue(value);
01970   asn1Objects->AppendElement(printableItem, PR_FALSE);
01971 
01972   rv = ProcessSubjectPublicKeyInfo(&mCert->subjectPublicKeyInfo, sequence,
01973                                    nssComponent); 
01974   if (NS_FAILED(rv))
01975     return rv;
01976  
01977   SECItem data; 
01978   // Is there an issuerUniqueID?
01979   if (mCert->issuerID.data != nsnull) {
01980     // The issuerID is encoded as a bit string.
01981     // The function ProcessRawBytes expects the
01982     // length to be in bytes, so let's convert the
01983     // length in a temporary SECItem
01984     data.data = mCert->issuerID.data;
01985     data.len  = mCert->issuerID.len / 8;
01986 
01987     ProcessRawBytes(nssComponent, &data, text);
01988     printableItem = new nsNSSASN1PrintableItem();
01989     if (printableItem == nsnull)
01990       return NS_ERROR_OUT_OF_MEMORY;
01991 
01992     printableItem->SetDisplayValue(text);
01993     nssComponent->GetPIPNSSBundleString("CertDumpIssuerUniqueID", text);
01994     printableItem->SetDisplayName(text);
01995     asn1Objects->AppendElement(printableItem, PR_FALSE);
01996   }
01997 
01998   if (mCert->subjectID.data) {
01999     // The subjectID is encoded as a bit string.
02000     // The function ProcessRawBytes expects the
02001     // length to be in bytes, so let's convert the
02002     // length in a temporary SECItem
02003     data.data = mCert->issuerID.data;
02004     data.len  = mCert->issuerID.len / 8;
02005 
02006     ProcessRawBytes(nssComponent, &data, text);
02007     printableItem = new nsNSSASN1PrintableItem();
02008     if (printableItem == nsnull)
02009       return NS_ERROR_OUT_OF_MEMORY;
02010 
02011     printableItem->SetDisplayValue(text);
02012     nssComponent->GetPIPNSSBundleString("CertDumpSubjectUniqueID", text);
02013     printableItem->SetDisplayName(text);
02014     asn1Objects->AppendElement(printableItem, PR_FALSE);
02015 
02016   }
02017   if (mCert->extensions) {
02018     rv = ProcessExtensions(mCert->extensions, sequence, nssComponent);
02019     if (NS_FAILED(rv))
02020       return rv;
02021   }
02022   *retSequence = sequence;
02023   NS_ADDREF(*retSequence);  
02024   return NS_OK;
02025 }
02026 
02027 nsresult
02028 nsNSSCertificate::CreateASN1Struct()
02029 {
02030   nsNSSShutDownPreventionLock locker;
02031   if (isAlreadyShutDown())
02032     return NS_ERROR_NOT_AVAILABLE;
02033 
02034   nsCOMPtr<nsIASN1Sequence> sequence = new nsNSSASN1Sequence();
02035 
02036   mASN1Structure = sequence; 
02037   if (mASN1Structure == nsnull) {
02038     return NS_ERROR_OUT_OF_MEMORY;
02039   }
02040 
02041   nsCOMPtr<nsIMutableArray> asn1Objects;
02042   sequence->GetASN1Objects(getter_AddRefs(asn1Objects));
02043   nsXPIDLCString title;
02044   GetWindowTitle(getter_Copies(title));
02045   
02046   mASN1Structure->SetDisplayName(NS_ConvertUTF8toUCS2(title));
02047   // This sequence will be contain the tbsCertificate, signatureAlgorithm,
02048   // and signatureValue.
02049   nsresult rv;
02050   nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
02051   if (NS_FAILED(rv))
02052     return rv;
02053 
02054   rv = CreateTBSCertificateASN1Struct(getter_AddRefs(sequence),
02055                                       nssComponent);
02056   if (NS_FAILED(rv))
02057     return rv;
02058 
02059   asn1Objects->AppendElement(sequence, PR_FALSE);
02060   nsCOMPtr<nsIASN1Sequence> algID;
02061 
02062   rv = ProcessSECAlgorithmID(&mCert->signatureWrap.signatureAlgorithm, 
02063                              nssComponent, getter_AddRefs(algID));
02064   if (NS_FAILED(rv))
02065     return rv;
02066   nsString text;
02067   nssComponent->GetPIPNSSBundleString("CertDumpSigAlg", text);
02068   algID->SetDisplayName(text);
02069   asn1Objects->AppendElement(algID, PR_FALSE);
02070   nsCOMPtr<nsIASN1PrintableItem>printableItem = new nsNSSASN1PrintableItem();
02071   nssComponent->GetPIPNSSBundleString("CertDumpCertSig", text);
02072   printableItem->SetDisplayName(text);
02073   // The signatureWrap is encoded as a bit string.
02074   // The function ProcessRawBytes expects the
02075   // length to be in bytes, so let's convert the
02076   // length in a temporary SECItem
02077   SECItem temp;
02078   temp.data = mCert->signatureWrap.signature.data;
02079   temp.len  = mCert->signatureWrap.signature.len / 8;
02080   text.Truncate();
02081   ProcessRawBytes(nssComponent, &temp,text);
02082   printableItem->SetDisplayValue(text);
02083   asn1Objects->AppendElement(printableItem, PR_FALSE);
02084   return NS_OK;
02085 }
02086 
02087 PRUint32 
02088 getCertType(CERTCertificate *cert)
02089 {
02090   nsNSSCertTrust trust(cert->trust);
02091   if (cert->nickname && trust.HasAnyUser())
02092     return nsIX509Cert::USER_CERT;
02093   if (trust.HasAnyCA())
02094     return nsIX509Cert::CA_CERT;
02095   if (trust.HasPeer(PR_TRUE, PR_FALSE, PR_FALSE))
02096     return nsIX509Cert::SERVER_CERT;
02097   if (trust.HasPeer(PR_FALSE, PR_TRUE, PR_FALSE) && cert->emailAddr)
02098     return nsIX509Cert::EMAIL_CERT;
02099   if (CERT_IsCACert(cert,NULL))
02100     return nsIX509Cert::CA_CERT;
02101   if (cert->emailAddr)
02102     return nsIX509Cert::EMAIL_CERT;
02103   return nsIX509Cert::SERVER_CERT;
02104 }
02105 
02106 CERTCertNicknames *
02107 getNSSCertNicknamesFromCertList(CERTCertList *certList)
02108 {
02109   nsresult rv;
02110 
02111   nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
02112   if (NS_FAILED(rv))
02113     return nsnull;
02114 
02115   nsAutoString expiredString, notYetValidString;
02116   nsAutoString expiredStringLeadingSpace, notYetValidStringLeadingSpace;
02117 
02118   nssComponent->GetPIPNSSBundleString("NicknameExpired", expiredString);
02119   nssComponent->GetPIPNSSBundleString("NicknameNotYetValid", notYetValidString);
02120 
02121   expiredStringLeadingSpace.Append(NS_LITERAL_STRING(" "));
02122   expiredStringLeadingSpace.Append(expiredString);
02123 
02124   notYetValidStringLeadingSpace.Append(NS_LITERAL_STRING(" "));
02125   notYetValidStringLeadingSpace.Append(notYetValidString);
02126 
02127   NS_ConvertUCS2toUTF8 aUtf8ExpiredString(expiredStringLeadingSpace);
02128   NS_ConvertUCS2toUTF8 aUtf8NotYetValidString(notYetValidStringLeadingSpace);
02129 
02130   return CERT_NicknameStringsFromCertList(certList,
02131                                           NS_CONST_CAST(char*, aUtf8ExpiredString.get()),
02132                                           NS_CONST_CAST(char*, aUtf8NotYetValidString.get()));
02133   
02134 }