certutil.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:76k
源码类别:

CA认证

开发平台:

WINDOWS

  1. /*
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is the Netscape security libraries.
  13.  * 
  14.  * The Initial Developer of the Original Code is Netscape
  15.  * Communications Corporation.  Portions created by Netscape are 
  16.  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
  17.  * Rights Reserved.
  18.  * 
  19.  * Contributor(s):
  20.  * 
  21.  * Alternatively, the contents of this file may be used under the
  22.  * terms of the GNU General Public License Version 2 or later (the
  23.  * "GPL"), in which case the provisions of the GPL are applicable 
  24.  * instead of those above.  If you wish to allow use of your 
  25.  * version of this file only under the terms of the GPL and not to
  26.  * allow others to use your version of this file under the MPL,
  27.  * indicate your decision by deleting the provisions above and
  28.  * replace them with the notice and other provisions required by
  29.  * the GPL.  If you do not delete the provisions above, a recipient
  30.  * may use your version of this file under either the MPL or the
  31.  * GPL.
  32.  */
  33. /*
  34. ** certutil.c
  35. **
  36. ** utility for managing certificates and the cert database
  37. **
  38. */
  39. #include <stdio.h>
  40. #include <string.h>
  41. #if defined(WIN32)
  42. #include "fcntl.h"
  43. #include "io.h"
  44. #endif
  45. #include "secutil.h"
  46. #if defined(XP_UNIX)
  47. #include <unistd.h>
  48. #endif
  49. #include "nspr.h"
  50. #include "prtypes.h"
  51. #include "prtime.h"
  52. #include "prlong.h"
  53. #include "pk11func.h"
  54. #include "secasn1.h"
  55. #include "cert.h"
  56. #include "cryptohi.h"
  57. #include "secoid.h"
  58. #include "certdb.h"
  59. #include "cdbhdl.h"
  60. /* SEC_Init is now declared in secutil.h */
  61. /* We really should convert to using NSS, but it doesn't provide all
  62.  * of the functionality we need (like opening the databases writeable). */
  63. #define MIN_KEY_BITS 512
  64. #define MAX_KEY_BITS 2048
  65. #define DEFAULT_KEY_BITS 1024
  66. #define GEN_BREAK(e) rv=e; break;
  67. extern SECKEYPrivateKey *CERTUTIL_GeneratePrivateKey(KeyType keytype,
  68.      PK11SlotInfo *slot, 
  69.                                                      int rsasize,
  70.      int publicExponent,
  71.      char *noise,
  72.      SECKEYPublicKey **pubkeyp,
  73.      char *pqgFile,
  74.                                                      char *passFile);
  75. static char *progName;
  76. static CERTGeneralName *
  77. GetGeneralName (PRArenaPool *arena)
  78. {
  79.     CERTGeneralName *namesList = NULL;
  80.     CERTGeneralName *current;
  81.     CERTGeneralName *tail = NULL;
  82.     SECStatus rv = SECSuccess;
  83.     int intValue;
  84.     char buffer[512];
  85.     void *mark;
  86.     PORT_Assert (arena);
  87.     mark = PORT_ArenaMark (arena);
  88.     do {
  89. puts ("nSelect one of the following general name type: n");
  90. puts ("t1 - instance of other nament2 - rfc822Nament3 - dnsNamen");
  91. puts ("t4 - x400Addressnt5 - directoryNament6 - ediPartyNamen");
  92. puts ("t7 - uniformResourceidentifiernt8 - ipAddressnt9 - registerIDn");
  93. puts ("tOther - omitnttChoice:");
  94. scanf ("%d", &intValue);
  95. if (intValue >= certOtherName || intValue <= certRegisterID) {
  96.     if (namesList == NULL) {
  97. namesList = current = tail = (CERTGeneralName *) PORT_ArenaAlloc 
  98.                                   (arena, sizeof (CERTGeneralName));
  99.     } else {
  100. current = (CERTGeneralName *) PORT_ArenaAlloc(arena, 
  101.       sizeof (CERTGeneralName));
  102.     }
  103.     if (current == NULL) {
  104. GEN_BREAK (SECFailure);
  105.     }
  106. } else {
  107.     break;
  108. }
  109. current->type = intValue;
  110. puts ("nEnter data:");
  111. fflush (stdout);
  112. gets (buffer);
  113. switch (current->type) {
  114.     case certURI:
  115.     case certDNSName:
  116.     case certRFC822Name:
  117. current->name.other.data = PORT_ArenaAlloc (arena, strlen (buffer));
  118. if (current->name.other.data == NULL) {
  119.     GEN_BREAK (SECFailure);
  120. }
  121. PORT_Memcpy
  122.   (current->name.other.data, buffer, current->name.other.len = strlen(buffer));
  123. break;
  124.     case certEDIPartyName:
  125.     case certIPAddress:
  126.     case certOtherName:
  127.     case certRegisterID:
  128.     case certX400Address: {
  129. current->name.other.data = PORT_ArenaAlloc (arena, strlen (buffer) + 2);
  130. if (current->name.other.data == NULL) {
  131.     GEN_BREAK (SECFailure);
  132. }
  133. PORT_Memcpy (current->name.other.data + 2, buffer, strlen (buffer));
  134. /* This may not be accurate for all cases.  For now, use this tag type */
  135. current->name.other.data[0] = (char)(((current->type - 1) & 0x1f)| 0x80);
  136. current->name.other.data[1] = (char)strlen (buffer);
  137. current->name.other.len = strlen (buffer) + 2;
  138. break;
  139.     }
  140.     case certDirectoryName: {
  141. CERTName *directoryName = NULL;
  142. directoryName = CERT_AsciiToName (buffer);
  143. if (!directoryName) {
  144.     fprintf(stderr, "certutil: improperly formatted name: "%s"n", buffer);
  145.     break;
  146. }
  147.     
  148. rv = CERT_CopyName (arena, &current->name.directoryName, directoryName);
  149. CERT_DestroyName (directoryName);
  150. break;
  151.     }
  152. }
  153. if (rv != SECSuccess)
  154.     break;
  155. current->l.next = &(namesList->l);
  156. current->l.prev = &(tail->l);
  157. tail->l.next = &(current->l);
  158. tail = current;
  159.     }while (1);
  160.     if (rv != SECSuccess) {
  161. PORT_SetError (rv);
  162. PORT_ArenaRelease (arena, mark);
  163. namesList = NULL;
  164.     }
  165.     return (namesList);
  166. }
  167. static SECStatus 
  168. GetString(PRArenaPool *arena, char *prompt, SECItem *value)
  169. {
  170.     char buffer[251];
  171.     value->data = NULL;
  172.     value->len = 0;
  173.     
  174.     puts (prompt);
  175.     gets (buffer);
  176.     if (strlen (buffer) > 0) {
  177. value->data = PORT_ArenaAlloc (arena, strlen (buffer));
  178. if (value->data == NULL) {
  179.     PORT_SetError (SEC_ERROR_NO_MEMORY);
  180.     return (SECFailure);
  181. }
  182. PORT_Memcpy (value->data, buffer, value->len = strlen(buffer));
  183.     }
  184.     return (SECSuccess);
  185. }
  186. static CERTCertificateRequest *
  187. GetCertRequest(PRFileDesc *inFile)
  188. {
  189.     CERTCertificateRequest *certReq = NULL;
  190.     CERTSignedData signedData;
  191.     PRArenaPool *arena = NULL;
  192.     SECItem reqDER;
  193.     SECStatus rv;
  194.     reqDER.data = NULL;
  195.     do {
  196. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  197. if (arena == NULL) {
  198.     GEN_BREAK (SEC_ERROR_NO_MEMORY);
  199. }
  200.   rv = SECU_ReadDERFromFile(&reqDER, inFile, PR_FALSE);
  201. if (rv) 
  202.     break;
  203.         certReq = (CERTCertificateRequest*) PORT_ArenaZAlloc
  204.   (arena, sizeof(CERTCertificateRequest));
  205.         if (!certReq) 
  206.     break;
  207. certReq->arena = arena;
  208. /* Since cert request is a signed data, must decode to get the inner
  209.    data
  210.  */
  211. PORT_Memset(&signedData, 0, sizeof(signedData));
  212. rv = SEC_ASN1DecodeItem(arena, &signedData, CERT_SignedDataTemplate, 
  213. &reqDER);
  214. if (rv)
  215.     break;
  216.         rv = SEC_ASN1DecodeItem(arena, certReq, CERT_CertificateRequestTemplate,
  217. &signedData.data);
  218.    } while (0);
  219.    if (rv) {
  220.        PRErrorCode  perr = PR_GetError();
  221.        fprintf(stderr, "%s: unable to decode DER cert request (%s)n", progName,
  222.                SECU_Strerror(perr));
  223.    }
  224.    return (certReq);
  225. }
  226. static PRBool 
  227. GetYesNo(char *prompt) 
  228. {
  229.     char buf[3];
  230.     PR_Sync(PR_STDIN);
  231.     PR_Write(PR_STDOUT, prompt, strlen(prompt)+1);
  232.     PR_Read(PR_STDIN, buf, sizeof(buf));
  233.     return (buf[0] == 'y' || buf[0] == 'Y') ? PR_TRUE : PR_FALSE;
  234. #if 0
  235.     char charValue;
  236.     puts (prompt);
  237.     scanf ("%c", &charValue);
  238.     if (charValue != 'y' && charValue != 'Y')
  239. return (0);
  240.     return (1);
  241. #endif
  242. }
  243. static SECStatus
  244. AddCert(PK11SlotInfo *slot, CERTCertDBHandle *handle, char *name, char *trusts, 
  245.         PRFileDesc *inFile, PRBool ascii, PRBool emailcert)
  246. {
  247.     CERTCertTrust *trust = NULL;
  248.     CERTCertificate *cert = NULL, *tempCert = NULL;
  249.     SECItem certDER;
  250.     SECStatus rv;
  251.     certDER.data = NULL;
  252.     do {
  253. /* Read in the entire file specified with the -i argument */
  254. rv = SECU_ReadDERFromFile(&certDER, inFile, ascii);
  255. if (rv != SECSuccess) {
  256.     SECU_PrintError(progName, "unable to read input file");
  257.     break;
  258. }
  259. /* Read in an ASCII cert and return a CERTCertificate */
  260. cert = CERT_DecodeCertFromPackage((char *)certDER.data, certDER.len);
  261. if (!cert) {
  262.     SECU_PrintError(progName, "could not obtain certificate from file"); 
  263.     GEN_BREAK(SECFailure);
  264. }
  265. /* Create a cert trust to pass to SEC_AddPermCertificate */
  266. trust = (CERTCertTrust *)PORT_ZAlloc(sizeof(CERTCertTrust));
  267. if (!trust) {
  268.     SECU_PrintError(progName, "unable to allocate cert trust");
  269.     GEN_BREAK(SECFailure);
  270. }
  271. rv = CERT_DecodeTrustString(trust, trusts);
  272. if (rv) {
  273.     SECU_PrintError(progName, "unable to decode trust string");
  274.     GEN_BREAK(SECFailure);
  275. }
  276. /* CERT_ImportCert only collects certificates and returns the
  277. * first certficate.  It does not insert these certificates into
  278. * the dbase.  For now, just call CERT_NewTempCertificate.
  279. * This will result in decoding the der twice.  This have to
  280. * be handle properly.
  281. */
  282. tempCert = CERT_NewTempCertificate(handle, &cert->derCert, NULL,
  283.                                    PR_FALSE, PR_TRUE);
  284. if (!PK11_IsInternal(slot)) {
  285.     tempCert->trust = trust;
  286.     rv = PK11_ImportCertForKeyToSlot(slot, tempCert, name,
  287.                                      PR_FALSE, NULL);
  288. }
  289. if (tempCert == NULL) {
  290.     SECU_PrintError(progName,"unable to add cert to the temp database");
  291.     GEN_BREAK(SECFailure);
  292. }
  293. rv = CERT_AddTempCertToPerm(tempCert, name, trust);
  294. if (rv) {
  295.     SECU_PrintError(progName, "could not add certificate to database");
  296.     GEN_BREAK(SECFailure);
  297. }
  298. if ( emailcert )
  299.     CERT_SaveSMimeProfile(tempCert, NULL, NULL);
  300.     } while (0);
  301.     CERT_DestroyCertificate (tempCert);
  302.     CERT_DestroyCertificate (cert);
  303.     PORT_Free(trust);
  304.     PORT_Free(certDER.data);
  305.     return rv;
  306. }
  307. static SECStatus
  308. CertReq(SECKEYPrivateKey *privk, SECKEYPublicKey *pubk, KeyType keyType,
  309. CERTName *subject, char *phone, int ascii, PRFileDesc *outFile)
  310. {
  311.     CERTSubjectPublicKeyInfo *spki;
  312.     CERTCertificateRequest *cr;
  313.     SECItem *encoding;
  314.     SECItem result;
  315.     SECStatus rv;
  316.     PRArenaPool *arena;
  317.     PRInt32 numBytes;
  318.     /* Create info about public key */
  319.     spki = SECKEY_CreateSubjectPublicKeyInfo(pubk);
  320.     if (!spki) {
  321. SECU_PrintError(progName, "unable to create subject public key");
  322. return SECFailure;
  323.     }
  324.     /* Generate certificate request */
  325.     cr = CERT_CreateCertificateRequest(subject, spki, 0);
  326.     if (!cr) {
  327. SECU_PrintError(progName, "unable to make certificate request");
  328. return SECFailure;
  329.     }
  330.     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  331.     if ( !arena ) {
  332. SECU_PrintError(progName, "out of memory");
  333. return SECFailure;
  334.     }
  335.     
  336.     /* Der encode the request */
  337.     encoding = SEC_ASN1EncodeItem(arena, NULL, cr,
  338.   CERT_CertificateRequestTemplate);
  339.     if (encoding == NULL) {
  340. SECU_PrintError(progName, "der encoding of request failed");
  341. return SECFailure;
  342.     }
  343.     /* Sign the request */
  344.     switch (keyType) {
  345.     case rsaKey:
  346. rv = SEC_DerSignData(arena, &result, encoding->data, encoding->len, 
  347.                      privk, SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION);
  348. break;
  349.     case dsaKey:
  350. rv = SEC_DerSignData(arena, &result, encoding->data, encoding->len, 
  351.                  privk, SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST);
  352. break;
  353.     default:
  354. SECU_PrintError(progName, "Must use rsa or dsa key type");
  355. return SECFailure;
  356.     }
  357.     if (rv) {
  358. SECU_PrintError(progName, "signing of data failed");
  359. return SECFailure;
  360.     }
  361.     /* Encode request in specified format */
  362.     if (ascii) {
  363. char *obuf;
  364. char *name, *email, *org, *state, *country;
  365. SECItem *it;
  366. int total;
  367. it = &result;
  368. obuf = BTOA_ConvertItemToAscii(it);
  369. total = PL_strlen(obuf);
  370. name = CERT_GetCommonName(subject);
  371. if (!name) {
  372.     fprintf(stderr, "You must specify a common namen");
  373.     return SECFailure;
  374. }
  375. if (!phone)
  376.     phone = strdup("(not specified)");
  377. email = CERT_GetCertEmailAddress(subject);
  378. if (!email)
  379.     email = strdup("(not specified)");
  380. org = CERT_GetOrgName(subject);
  381. if (!org)
  382.     org = strdup("(not specified)");
  383. state = CERT_GetStateName(subject);
  384. if (!state)
  385.     state = strdup("(not specified)");
  386. country = CERT_GetCountryName(subject);
  387. if (!country)
  388.     country = strdup("(not specified)");
  389. PR_fprintf(outFile, 
  390.            "nCertificate request generated by Netscape certutiln");
  391. PR_fprintf(outFile, "Phone: %snn", phone);
  392. PR_fprintf(outFile, "Common Name: %sn", name);
  393. PR_fprintf(outFile, "Email: %sn", email);
  394. PR_fprintf(outFile, "Organization: %sn", org);
  395. PR_fprintf(outFile, "State: %sn", state);
  396. PR_fprintf(outFile, "Country: %snn", country);
  397. PR_fprintf(outFile, "%sn", NS_CERTREQ_HEADER);
  398. numBytes = PR_Write(outFile, obuf, total);
  399. if (numBytes != total) {
  400.     SECU_PrintSystemError(progName, "write error");
  401.     return SECFailure;
  402. }
  403. PR_fprintf(outFile, "%sn", NS_CERTREQ_TRAILER);
  404.     } else {
  405. numBytes = PR_Write(outFile, result.data, result.len);
  406. if (numBytes != (int)result.len) {
  407.     SECU_PrintSystemError(progName, "write error");
  408.     return SECFailure;
  409. }
  410.     }
  411.     return SECSuccess;
  412. }
  413. static SECStatus 
  414. ChangeTrustAttributes(CERTCertDBHandle *handle, char *name, char *trusts)
  415. {
  416.     SECStatus rv;
  417.     CERTCertificate *cert;
  418.     CERTCertTrust *trust;
  419.     
  420.     cert = CERT_FindCertByNicknameOrEmailAddr(handle, name);
  421.     if (!cert) {
  422. SECU_PrintError(progName, "could not find certificate named "%s"",
  423. name);
  424. return SECFailure;
  425.     }
  426.     trust = (CERTCertTrust *)PORT_ZAlloc(sizeof(CERTCertTrust));
  427.     if (!trust) {
  428. SECU_PrintError(progName, "unable to allocate cert trust");
  429. return SECFailure;
  430.     }
  431.     /* This function only decodes these characters: pPwcTCu, */
  432.     rv = CERT_DecodeTrustString(trust, trusts);
  433.     if (rv) {
  434. SECU_PrintError(progName, "unable to decode trust string");
  435. return SECFailure;
  436.     }
  437.     rv = CERT_ChangeCertTrust(handle, cert, trust);
  438.     if (rv) {
  439. SECU_PrintError(progName, "unable to modify trust attributes");
  440. return SECFailure;
  441.     }
  442.     return SECSuccess;
  443. }
  444. static SECStatus
  445. printCertCB(CERTCertificate *cert, void *arg)
  446. {
  447.     SECStatus rv;
  448.     SECItem data;
  449.     
  450.     data.data = cert->derCert.data;
  451.     data.len = cert->derCert.len;
  452.     rv = SECU_PrintSignedData(stdout, &data, "Certificate", 0,
  453.       SECU_PrintCertificate);
  454.     if (rv) {
  455. SECU_PrintError(progName, "problem printing certificate");
  456. return(SECFailure);
  457.     }
  458.     SECU_PrintTrustFlags(stdout, &cert->dbEntry->trust,
  459.  "Certificate Trust Flags", 1);
  460.     printf("n");
  461.     return(SECSuccess);
  462. }
  463. static SECStatus
  464. listCerts(CERTCertDBHandle *handle, char *name, PK11SlotInfo *slot,
  465.           PRBool raw, PRBool ascii, PRFileDesc *outfile, void *pwarg)
  466. {
  467.     CERTCertificate *cert;
  468.     SECItem data;
  469.     PRInt32 numBytes;
  470.     SECStatus rv;
  471.     /* For now, split handling of slot to internal vs. other.  slot should
  472.      * probably be allowed to be NULL so that all slots can be listed.
  473.      * In that case, need to add a call to PK11_TraverseSlotCerts().
  474.      */
  475.     if (PK11_IsInternal(slot)) {
  476. if (name == NULL) {
  477.     /* Print all certs in internal slot db. */
  478.     rv = SECU_PrintCertificateNames(handle, PR_STDOUT, 
  479.                                     PR_FALSE, PR_TRUE);
  480.     if (rv) {
  481. SECU_PrintError(progName, 
  482.                 "problem printing certificate nicknames");
  483. return SECFailure;
  484.     }
  485. } else if (raw || ascii) {
  486.     /* Dump binary or ascii DER for the cert to stdout. */
  487.     cert = CERT_FindCertByNicknameOrEmailAddr(handle, name);
  488.     if (!cert) {
  489. SECU_PrintError(progName,
  490.                "could not find certificate named "%s"", name);
  491. return SECFailure;
  492.     }
  493.     data.data = cert->derCert.data;
  494.     data.len = cert->derCert.len;
  495.     if (ascii) {
  496. PR_fprintf(outfile, "%sn%sn%sn", NS_CERT_HEADER, 
  497.         BTOA_DataToAscii(data.data, data.len), NS_CERT_TRAILER);
  498.     } else if (raw) {
  499.         numBytes = PR_Write(outfile, data.data, data.len);
  500.         if (numBytes != data.len) {
  501.     SECU_PrintSystemError(progName, "error writing raw cert");
  502.     return SECFailure;
  503. }
  504.     }
  505. } else {
  506.     /* Pretty-print cert. */
  507.     rv = CERT_TraversePermCertsForNickname(handle, name, printCertCB,
  508.                                            NULL);
  509. }
  510.     } else {
  511. /* List certs on a non-internal slot. */
  512. if (PK11_NeedLogin(slot))
  513.     PK11_Authenticate(slot, PR_TRUE, pwarg);
  514. rv = PK11_TraverseCertsInSlot(slot, SECU_PrintCertNickname, stdout);
  515. if (rv) {
  516.     SECU_PrintError(progName, "problem printing certificate nicknames");
  517.     return SECFailure;
  518. }
  519.     }
  520.     return SECSuccess; /* not rv ?? */
  521. }
  522. static SECStatus
  523. ListCerts(CERTCertDBHandle *handle, char *name, PK11SlotInfo *slot,
  524.           PRBool raw, PRBool ascii, PRFileDesc *outfile, char *passFile)
  525. {
  526.     SECStatus rv;
  527.     secuPWData pwdata = { PW_NONE, 0 };
  528.     if (passFile) {
  529.         pwdata.source = PW_FROMFILE;
  530.         pwdata.data = passFile;
  531.     }
  532.     if (slot == NULL) {
  533. PK11SlotList *list;
  534. PK11SlotListElement *le;
  535. list= PK11_GetAllTokens(CKM_INVALID_MECHANISM,
  536. PR_FALSE,PR_FALSE,&pwdata);
  537. if (list) for (le = list->head; le; le = le->next) {
  538.     rv = listCerts(handle,name,le->slot,raw,ascii,outfile,&pwdata);
  539. }
  540.     } else {
  541. rv = listCerts(handle,name,slot,raw,ascii,outfile,&pwdata);
  542.     }
  543.     return rv;
  544. }
  545. static SECStatus 
  546. DeleteCert(CERTCertDBHandle *handle, char *name)
  547. {
  548.     SECStatus rv;
  549.     CERTCertificate *cert;
  550.     cert = CERT_FindCertByNicknameOrEmailAddr(handle, name);
  551.     if (!cert) {
  552. SECU_PrintError(progName, "could not find certificate named "%s"",
  553. name);
  554. return SECFailure;
  555.     }
  556.     rv = SEC_DeletePermCertificate(cert);
  557.     if (rv) {
  558. SECU_PrintError(progName, "unable to delete certificate");
  559. return SECFailure;
  560.     }
  561.     return SECSuccess;
  562. }
  563. static SECStatus
  564. ValidateCert(CERTCertDBHandle *handle, char *name, char *date,
  565.      char *certUsage, PRBool checkSig, PRBool logit)
  566. {
  567.     SECStatus rv;
  568.     CERTCertificate *cert;
  569.     int64 timeBoundary;
  570.     SECCertUsage usage;
  571.     CERTVerifyLog reallog;
  572.     CERTVerifyLog *log = NULL;
  573.     
  574.     switch (*certUsage) {
  575. case 'C':
  576.     usage = certUsageSSLClient;
  577.     break;
  578. case 'V':
  579.     usage = certUsageSSLServer;
  580.     break;
  581. case 'S':
  582.     usage = certUsageEmailSigner;
  583.     break;
  584. case 'R':
  585.     usage = certUsageEmailRecipient;
  586.     break;
  587. default:
  588.     PORT_SetError (SEC_ERROR_INVALID_ARGS);
  589.     return (SECFailure);
  590.     }
  591.     do {
  592. cert = CERT_FindCertByNicknameOrEmailAddr(handle, name);
  593. if (!cert) {
  594.     SECU_PrintError(progName, "could not find certificate named "%s"",
  595.     name);
  596.     GEN_BREAK (SECFailure)
  597. }
  598. if (date != NULL) {
  599.     rv = DER_AsciiToTime(&timeBoundary, date);
  600.     if (rv) {
  601. SECU_PrintError(progName, "invalid input date");
  602. GEN_BREAK (SECFailure)
  603.     }
  604. } else {
  605.     timeBoundary = PR_Now();
  606. }
  607. if ( logit ) {
  608.     log = &reallog;
  609.     
  610.     log->count = 0;
  611.     log->head = NULL;
  612.     log->tail = NULL;
  613.     log->arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  614.     if ( log->arena == NULL ) {
  615. SECU_PrintError(progName, "out of memory");
  616. GEN_BREAK (SECFailure)
  617.     }
  618. }
  619.  
  620. rv = CERT_VerifyCert(handle, cert, checkSig, usage,
  621.      timeBoundary, NULL, log);
  622. if ( log ) {
  623.     if ( log->head == NULL ) {
  624. fprintf(stdout, "%s: certificate is validn", progName);
  625. GEN_BREAK (SECSuccess)
  626.     } else {
  627. char *name;
  628. CERTVerifyLogNode *node;
  629. node = log->head;
  630. while ( node ) {
  631.     if ( node->cert->nickname != NULL ) {
  632. name = node->cert->nickname;
  633.     } else {
  634. name = node->cert->subjectName;
  635.     }
  636.     fprintf(stderr, "%s : %sn", name, 
  637.      SECU_Strerror(node->error));
  638.     CERT_DestroyCertificate(node->cert);
  639.     node = node->next;
  640. }
  641.     }
  642. } else {
  643.     if (rv != SECSuccess) {
  644. PRErrorCode perr = PORT_GetError();
  645. fprintf(stdout, "%s: certificate is invalid: %sn",
  646. progName, SECU_Strerror(perr));
  647. GEN_BREAK (SECFailure)
  648.     }
  649.     fprintf(stdout, "%s: certificate is validn", progName);
  650.     GEN_BREAK (SECSuccess)
  651. }
  652.     } while (0);
  653.     return (rv);
  654. }
  655. SECKEYLowPrivateKey*
  656. GetPrivKeyFromNickname(char *nickname)
  657. {
  658.     /* check if key actually exists */
  659.     if (SECU_CheckKeyNameExists(NULL, nickname) == PR_FALSE) {
  660. SECU_PrintError(progName, "the key "%s" does not exist", nickname);
  661. return NULL;
  662.     }
  663.     /* Read in key */
  664.     return SECU_GetPrivateKey(NULL, nickname);
  665. }
  666. static SECStatus
  667. DumpPublicKey(int dbindex, char *nickname, FILE *out)
  668. {
  669.     SECKEYLowPrivateKey *privKey;
  670.     SECKEYLowPublicKey *publicKey;
  671.     if (dbindex) {
  672. /*privKey = secu_GetPrivKeyFromIndex(dbindex);*/
  673.     } else {
  674. privKey = GetPrivKeyFromNickname(nickname);
  675.     }
  676.     publicKey = SECKEY_LowConvertToPublicKey(privKey);
  677.     /* Output public key (in the clear) */
  678.     switch(publicKey->keyType) {
  679.       case rsaKey:
  680. fprintf(out, "RSA Public-Key:n");
  681. SECU_PrintInteger(out, &publicKey->u.rsa.modulus, "modulus", 1);
  682. SECU_PrintInteger(out, &publicKey->u.rsa.publicExponent,
  683.   "publicExponent", 1);
  684. break;
  685.       case dsaKey:
  686. fprintf(out, "DSA Public-Key:n");
  687. SECU_PrintInteger(out, &publicKey->u.dsa.params.prime, "prime", 1);
  688. SECU_PrintInteger(out, &publicKey->u.dsa.params.subPrime,
  689.   "subPrime", 1);
  690. SECU_PrintInteger(out, &publicKey->u.dsa.params.base, "base", 1);
  691. SECU_PrintInteger(out, &publicKey->u.dsa.publicValue, "publicValue", 1);
  692. break;
  693.       default:
  694. fprintf(out, "unknown key typen");
  695. break;
  696.     }
  697.     return SECSuccess;
  698. }
  699. static SECStatus
  700. DumpPrivateKey(int dbindex, char *nickname, FILE *out)
  701. {
  702.     SECKEYLowPrivateKey *key;
  703.     if (dbindex) {
  704. /*key = secu_GetPrivKeyFromIndex(dbindex);*/
  705.     } else {
  706. key = GetPrivKeyFromNickname(nickname);
  707.     }
  708.     switch(key->keyType) {
  709.       case rsaKey:
  710. fprintf(out, "RSA Private-Key:n");
  711. SECU_PrintInteger(out, &key->u.rsa.modulus, "modulus", 1);
  712. SECU_PrintInteger(out, &key->u.rsa.publicExponent, "publicExponent", 1);
  713. SECU_PrintInteger(out, &key->u.rsa.privateExponent,
  714.   "privateExponent", 1);
  715. SECU_PrintInteger(out, &key->u.rsa.prime1, "prime1", 1);
  716. SECU_PrintInteger(out, &key->u.rsa.prime2, "prime2", 1);
  717. SECU_PrintInteger(out, &key->u.rsa.exponent1, "exponent2", 1);
  718. SECU_PrintInteger(out, &key->u.rsa.exponent2, "exponent2", 1);
  719. SECU_PrintInteger(out, &key->u.rsa.coefficient, "coefficient", 1);
  720. break;
  721.       case dsaKey:
  722. fprintf(out, "DSA Private-Key:n");
  723. SECU_PrintInteger(out, &key->u.dsa.params.prime, "prime", 1);
  724. SECU_PrintInteger(out, &key->u.dsa.params.subPrime, "subPrime", 1);
  725. SECU_PrintInteger(out, &key->u.dsa.params.base, "base", 1);
  726. SECU_PrintInteger(out, &key->u.dsa.publicValue, "publicValue", 1);
  727. SECU_PrintInteger(out, &key->u.dsa.privateValue, "privateValue", 1);
  728. break;
  729.       default:
  730. fprintf(out, "unknown key typen");
  731. break;
  732.     }
  733.     return SECSuccess;
  734. }
  735. static SECStatus
  736. printKeyCB(SECKEYPublicKey *key, SECItem *data, void *arg)
  737. {
  738.     if (key->keyType == rsaKey) {
  739. fprintf(stdout, "RSA Public-Key:n");
  740. SECU_PrintInteger(stdout, &key->u.rsa.modulus, "modulus", 1);
  741.     } else {
  742. fprintf(stdout, "DSA Public-Key:n");
  743. SECU_PrintInteger(stdout, &key->u.dsa.publicValue, "publicValue", 1);
  744.     }
  745.     return SECSuccess;
  746. }
  747. /* callback for listing certs through pkcs11 */
  748. SECStatus
  749. secu_PrintKeyFromCert(CERTCertificate *cert, void *data)
  750. {
  751.     FILE *out;
  752.     char *name;
  753.     SECKEYPublicKey *key;
  754.     out = (FILE *)data;
  755.     key = CERT_ExtractPublicKey(cert);
  756.     if (!key) {
  757. fprintf(out, "XXX could not extract key for %s.n", cert->nickname);
  758. return SECFailure;
  759.     }
  760.     /* XXX should have a type field also */
  761.     fprintf(out, "<%d> %sn", 0, cert->nickname);
  762.     return SECSuccess;
  763. }
  764. static SECStatus
  765. listKeys(PK11SlotInfo *slot, KeyType keyType, void *pwarg)
  766. {
  767.     SECStatus rv = SECSuccess;
  768.     if (PK11_IsInternal(slot)) {
  769. /* Print all certs in internal slot db. */
  770. rv = SECU_PrintKeyNames(SECKEY_GetDefaultKeyDB(), stdout);
  771. if (rv) {
  772.     SECU_PrintError(progName, "problem listing keys");
  773.     return SECFailure;
  774. }
  775.     } else {
  776. /* XXX need a function as below */
  777. /* could iterate over certs on slot and print keys */
  778. /* this would miss stranded keys */
  779.     /*rv = PK11_TraverseSlotKeys(slotname, keyType, printKeyCB, NULL, NULL);*/
  780. if (PK11_NeedLogin(slot))
  781.     PK11_Authenticate(slot, PR_TRUE, pwarg);
  782. rv = PK11_TraverseCertsInSlot(slot, secu_PrintKeyFromCert, stdout);
  783. if (rv) {
  784.     SECU_PrintError(progName, "problem listing keys");
  785.     return SECFailure;
  786. }
  787. return SECFailure;
  788.     }
  789.     return rv;
  790. }
  791. static SECStatus
  792. ListKeys(PK11SlotInfo *slot, char *keyname, int index, 
  793.          KeyType keyType, PRBool dopriv, char *passFile)
  794. {
  795.     SECStatus rv = SECSuccess;
  796.     secuPWData pwdata = { PW_NONE, 0 };
  797.     if (passFile) {
  798.         pwdata.source = PW_FROMFILE;
  799.         pwdata.data = passFile;
  800.     }
  801.     if (keyname) {
  802. if (dopriv) {
  803.     return DumpPrivateKey(index, keyname, stdout);
  804. } else {
  805.     return DumpPublicKey(index, keyname, stdout);
  806. }
  807.     }
  808.     /* For now, split handling of slot to internal vs. other.  slot should
  809.      * probably be allowed to be NULL so that all slots can be listed.
  810.      * In that case, need to add a call to PK11_TraverseSlotCerts().
  811.      */
  812.     if (slot == NULL) {
  813. PK11SlotList *list;
  814. PK11SlotListElement *le;
  815. list= PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_FALSE,&pwdata);
  816. if (list) for (le = list->head; le; le = le->next) {
  817.     rv = listKeys(le->slot,keyType,&pwdata);
  818. }
  819.     } else {
  820. rv = listKeys(slot,keyType,&pwdata);
  821.     }
  822.     return rv;
  823. }
  824. static SECStatus
  825. DeleteKey(SECKEYKeyDBHandle *handle, char *nickname)
  826. {
  827.     SECStatus rv;
  828.     rv = SECU_DeleteKeyByName(handle, nickname);
  829.     if (rv != SECSuccess) {
  830. SECU_PrintError("problem deleting private key "%s"n", nickname);
  831.     }
  832.     return rv;
  833. }
  834. /*
  835.  *  L i s t M o d u l e s
  836.  *
  837.  *  Print a list of the PKCS11 modules that are
  838.  *  available. This is useful for smartcard people to
  839.  *  make sure they have the drivers loaded.
  840.  *
  841.  */
  842. static SECStatus
  843. ListModules(void)
  844. {
  845.     PK11SlotList *list;
  846.     PK11SlotListElement *le;
  847.     /* get them all! */
  848.     list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_FALSE,NULL);
  849.     if (list == NULL) return SECFailure;
  850.     /* look at each slot*/
  851.     for (le = list->head ; le; le = le->next) {
  852.       printf ("n");
  853.       printf ("    slot: %sn", PK11_GetSlotName(le->slot));
  854.       printf ("   token: %sn", PK11_GetTokenName(le->slot));
  855.     }
  856.     PK11_FreeSlotList(list);
  857.     return SECSuccess;
  858. }
  859. static void 
  860. Usage(char *progName)
  861. {
  862. #define FPS fprintf(stderr, 
  863.     FPS "Type %s -H for more detailed descriptionsn", progName);
  864.     FPS "Usage:  %s -N [-d certdir] [-f pwfile]n", progName);
  865.     FPS "t%s -A -n cert-name -t trustargs [-d certdir] [-a] [-i input]n", 
  866.      progName);
  867.     FPS "t%s -C [-c issuer-name | -x] -i cert-request-file -o cert-filen"
  868. "tt [-m serial-number] [-w warp-months] [-v months-valid]n"
  869.         "tt [-f pwfile] [-d certdir] [-1] [-2] [-3] [-4] [-5] [-6]n",
  870. progName);
  871.     FPS "t%s -D -n cert-name [-d certdir]n", progName);
  872.     FPS "t%s -E -n cert-name -t trustargs [-d certdir] [-a] [-i input]n", 
  873. progName);
  874.     FPS "t%s -G -n key-name [-h token-name] [-k rsa] [-g key-size] [-y exp]n" 
  875. "tt [-f pwfile] [-z noisefile] [-d certdir]n", progName);
  876.     FPS "t%s -G [-h token-name] -k dsa [-q pqgfile -g key-size] [-f pwfile]n"
  877. "tt [-z noisefile] [-d certdir]n", progName);
  878.     FPS "t%s -K [-n key-name] [-h token-name] [-k dsa|rsa|all]n", 
  879. progName);
  880.     FPS "tt [-f pwfile] [-d certdir]n");
  881.     FPS "t%s -L [-n cert-name] [-d certdir] [-r] [-a]n", progName);
  882.     FPS "t%s -M -n cert-name -t trustargs [-d certdir]n",
  883. progName);
  884.     FPS "t%s -R -s subj -o cert-request-file [-d certdir] [-p phone] [-a]n"
  885. "tt [-k key-type] [-h token-name] [-f pwfile] [-g key-size]n",
  886. progName);
  887.     FPS "t%s -V -n cert-name -u usage [-b time] [-e] [-d certdir]n",
  888. progName);
  889.     FPS "t%s -S -n cert-name -s subj [-c issuer-name | -x]  -t trustargsn"
  890. "tt [-k key-type] [-h token-name] [-g key-size]n"
  891.         "tt [-m serial-number] [-w warp-months] [-v months-valid]n"
  892. "tt [-f pwfile] [-d certdir]n"
  893.         "tt [-p phone] [-1] [-2] [-3] [-4] [-5] [-6]n",
  894. progName);
  895.     FPS "t%s -U [-d certdir]n", progName);
  896.     exit(-1);
  897. }
  898. static void LongUsage(char *progName)
  899. {
  900.     FPS "%-15s Add a certificate to the database        (create if needed)n",
  901. "-A");
  902.     FPS "%-15s Add an Email certificate to the database (create if needed)n",
  903. "-E");
  904.     FPS "%-20s Specify the nickname of the certificate to addn",
  905. "   -n cert-name");
  906.     FPS "%-20s Set the certificate trust attributes:n",
  907. "   -t trustargs");
  908.     FPS "%-25s p t valid peern", "");
  909.     FPS "%-25s P t trusted peer (implies p)n", "");
  910.     FPS "%-25s c t valid CAn", "");
  911.     FPS "%-25s T t trusted CA to issue client certs (implies c)n", "");
  912.     FPS "%-25s C t trusted CA to issue server certs (implies c)n", "");
  913.     FPS "%-25s u t user certn", "");
  914.     FPS "%-25s w t send warningn", "");
  915. #ifdef DEBUG_NSSTEAM_ONLY
  916.     FPS "%-25s g t make step-up certn", "");
  917. #endif /* DEBUG_NSSTEAM_ONLY */
  918.     FPS "%-20s Specify the password filen",
  919. "   -f pwfile");
  920.     FPS "%-20s Cert database directory (default is ~/.netscape)n",
  921. "   -d certdir");
  922.     FPS "%-20s The input certificate is encoded in ASCII (RFC1113)n",
  923. "   -a");
  924.     FPS "%-20s Specify the certificate file (default is stdin)n",
  925. "   -i input");
  926.     FPS "n");
  927.     FPS "%-15s Create a new binary certificate from a BINARY cert requestn",
  928. "-C");
  929.     FPS "%-20s The nickname of the issuer certn",
  930. "   -c issuer-name");
  931.     FPS "%-20s The BINARY certificate request filen",
  932. "   -i cert-request ");
  933.     FPS "%-20s Output binary cert to this file (default is stdout)n",
  934. "   -o output-cert");
  935.     FPS "%-20s Self signn",
  936. "   -x");
  937.     FPS "%-20s Cert serial numbern",
  938. "   -m serial-number");
  939.     FPS "%-20s Time Warpn",
  940. "   -w warp-months");
  941.     FPS "%-20s Months valid (default is 3)n",
  942.         "   -v months-valid");
  943.     FPS "%-20s Specify the password filen",
  944. "   -f pwfile");
  945.     FPS "%-20s Cert database directory (default is ~/.netscape)n",
  946. "   -d certdir");
  947.     FPS "%-20s Create key usage extensionn",
  948. "   -1 ");
  949.     FPS "%-20s Create basic constraint extensionn",
  950. "   -2 ");
  951.     FPS "%-20s Create authority key ID extensionn",
  952. "   -3 ");
  953.     FPS "%-20s Create crl distribution point extensionn",
  954. "   -4 ");
  955.     FPS "%-20s Create netscape cert type extensionn",
  956. "   -5 ");
  957.     FPS "%-20s Create extended key usage extensionn",
  958. "   -6 ");
  959.     FPS "n");
  960.     FPS "%-15s Generate a new key pairn",
  961. "-G");
  962.     FPS "%-20s Name of token in which to generate key (default is internal)n",
  963. "   -h token-name");
  964.     FPS "%-20s Type of key pair to generate ("dsa", "rsa" (default))n",
  965. "   -k key-type");
  966.     FPS "%-20s Key size in bits, (min %d, max %d, default %d)n",
  967. "   -g key-size", MIN_KEY_BITS, MAX_KEY_BITS, DEFAULT_KEY_BITS);
  968.     FPS "%-20s Set the public exponent value (3, 17, 65537) (rsa only)n",
  969. "   -y exp");
  970.     FPS "%-20s Specify the password filen",
  971.         "   -f password-file");
  972.     FPS "%-20s Specify the noise file to be usedn",
  973. "   -z noisefile");
  974.     FPS "%-20s read PQG value from pqgfile (dsa only)n",
  975. "   -q pqgfile");
  976.     FPS "%-20s Key database directory (default is ~/.netscape)n",
  977. "   -d keydir");
  978.     FPS "n");
  979.     FPS "%-15s Delete a certificate from the databasen",
  980. "-D");
  981.     FPS "%-20s The nickname of the cert to deleten",
  982. "   -n cert-name");
  983.     FPS "%-20s Cert database directory (default is ~/.netscape)n",
  984. "   -d certdir");
  985.     FPS "n");
  986.     FPS "%-15s List all modulesn", /*, or print out a single named modulen",*/
  987.         "-U");
  988.     FPS "%-20s Module database directory (default is '~/.netscape')n",
  989.         "   -d moddir");
  990.     FPS "%-15s List all keysn", /*, or print out a single named keyn",*/
  991.         "-K");
  992.     FPS "%-20s Name of token in which to look for keys (default is internal,"
  993. " use "all" to list keys on all tokens)n",
  994. "   -h token-name ");
  995.     FPS "%-20s Type of key pair to list ("all", "dsa", "rsa" (default))n",
  996. "   -k key-type");
  997.     FPS "%-20s Specify the password filen",
  998.         "   -f password-file");
  999.     FPS "%-20s Key database directory (default is ~/.netscape)n",
  1000. "   -d keydir");
  1001.     FPS "n");
  1002.     FPS "%-15s List all certs, or print out a single named certn",
  1003. "-L");
  1004.     FPS "%-20s Pretty print named cert (list all if unspecified)n",
  1005. "   -n cert-name");
  1006.     FPS "%-20s Cert database directory (default is ~/.netscape)n",
  1007. "   -d certdir");
  1008.     FPS "%-20s For single cert, print binary DER encodingn",
  1009. "   -r");
  1010.     FPS "%-20s For single cert, print ASCII encoding (RFC1113)n",
  1011. "   -a");
  1012.     FPS "n");
  1013.     FPS "%-15s Modify trust attributes of certificaten",
  1014. "-M");
  1015.     FPS "%-20s The nickname of the cert to modifyn",
  1016. "   -n cert-name");
  1017.     FPS "%-20s Set the certificate trust attributes (see -A above)n",
  1018. "   -t trustargs");
  1019.     FPS "%-20s Cert database directory (default is ~/.netscape)n",
  1020. "   -d certdir");
  1021.     FPS "n");
  1022.     FPS "%-15s Create a new certificate databasen",
  1023. "-N");
  1024.     FPS "%-20s Cert database directory (default is ~/.netscape)n",
  1025. "   -d certdir");
  1026.     FPS "n");
  1027.     FPS "%-15s Generate a certificate request (stdout)n",
  1028. "-R");
  1029.     FPS "%-20s Specify the subject name (using RFC1485)n",
  1030. "   -s subject");
  1031.     FPS "%-20s Output the cert request to this filen",
  1032. "   -o output-req");
  1033.     FPS "%-20s Type of key pair to generate ("dsa", "rsa" (default))n",
  1034. "   -k key-type");
  1035.     FPS "%-20s Name of token in which to generate key (default is internal)n",
  1036. "   -h token-name");
  1037.     FPS "%-20s Key size in bits, RSA keys only (min %d, max %d, default %d)n",
  1038. "   -g key-size", MIN_KEY_BITS, MAX_KEY_BITS, DEFAULT_KEY_BITS);
  1039.     FPS "%-20s Specify the password filen",
  1040. "   -f pwfile");
  1041.     FPS "%-20s Key database directory (default is ~/.netscape)n",
  1042. "   -d keydir");
  1043.     FPS "%-20s Specify the contact phone number ("123-456-7890")n",
  1044. "   -p phone");
  1045.     FPS "%-20s Output the cert request in ASCII (RFC1113); default is binaryn",
  1046. "   -a");
  1047.     FPS "n");
  1048.     FPS "%-15s Validate a certificaten",
  1049. "-V");
  1050.     FPS "%-20s The nickname of the cert to Validaten",
  1051. "   -n cert-name");
  1052.     FPS "%-20s validity time ("YYMMDDHHMMSS[+HHMM|-HHMM|Z]")n",
  1053. "   -b time");
  1054.     FPS "%-20s Check certificate signature n",
  1055. "   -e ");   
  1056.     FPS "%-20s Specify certificate usage:n", "   -u certusage");
  1057.     FPS "%-25s C t SSL Clientn", "");
  1058.     FPS "%-25s V t SSL Servern", "");
  1059.     FPS "%-25s S t Email signern", "");
  1060.     FPS "%-25s R t Email Recipientn", "");   
  1061.     FPS "%-20s Cert database directory (default is ~/.netscape)n",
  1062. "   -d certdir");
  1063.     FPS "n");
  1064.     FPS "%-15s Make a certificate and add to databasen",
  1065.         "-S");
  1066.     FPS "%-20s Specify the nickname of the certn",
  1067.         "   -n key-name");
  1068.     FPS "%-20s Specify the subject name (using RFC1485)n",
  1069.         "   -s subject");
  1070.     FPS "%-20s The nickname of the issuer certn",
  1071. "   -c issuer-name");
  1072.     FPS "%-20s Set the certificate trust attributes (see -A above)n",
  1073. "   -t trustargs");
  1074.     FPS "%-20s Type of key pair to generate ("dsa", "rsa" (default))n",
  1075. "   -k key-type");
  1076.     FPS "%-20s Name of token in which to generate key (default is internal)n",
  1077. "   -h token-name");
  1078.     FPS "%-20s Key size in bits, RSA keys only (min %d, max %d, default %d)n",
  1079. "   -g key-size", MIN_KEY_BITS, MAX_KEY_BITS, DEFAULT_KEY_BITS);
  1080.     FPS "%-20s Self signn",
  1081. "   -x");
  1082.     FPS "%-20s Cert serial numbern",
  1083. "   -m serial-number");
  1084.     FPS "%-20s Time Warpn",
  1085. "   -w warp-months");
  1086.     FPS "%-20s Months valid (default is 3)n",
  1087.         "   -v months-valid");
  1088.     FPS "%-20s Specify the password filen",
  1089. "   -f pwfile");
  1090.     FPS "%-20s Cert database directory (default is ~/.netscape)n",
  1091. "   -d certdir");
  1092.     FPS "%-20s Specify the contact phone number ("123-456-7890")n",
  1093. "   -p phone");
  1094.     FPS "%-20s Create key usage extensionn",
  1095. "   -1 ");
  1096.     FPS "%-20s Create basic constraint extensionn",
  1097. "   -2 ");
  1098.     FPS "%-20s Create authority key ID extensionn",
  1099. "   -3 ");
  1100.     FPS "%-20s Create crl distribution point extensionn",
  1101. "   -4 ");
  1102.     FPS "%-20s Create netscape cert type extensionn",
  1103. "   -5 ");
  1104.     FPS "%-20s Create extended key usage extensionn",
  1105. "   -6 ");
  1106.     FPS "n");
  1107.     exit(-1);
  1108. #undef FPS
  1109. }
  1110. static CERTCertificate *
  1111. MakeV1Cert( CERTCertDBHandle * handle, 
  1112. CERTCertificateRequest *req,
  1113.      char * issuerNickName, 
  1114. PRBool  selfsign, 
  1115. int  serialNumber,
  1116. int  warpmonths,
  1117.                 int                     validitylength)
  1118. {
  1119.     CERTCertificate *issuerCert = NULL;
  1120.     CERTValidity *validity;
  1121.     CERTCertificate *cert = NULL;
  1122. #ifndef NSPR20    
  1123.     PRTime printableTime;
  1124.     int64 now, after;
  1125. #else
  1126.     PRExplodedTime printableTime;
  1127.     PRTime now, after;
  1128. #endif    
  1129.    
  1130.     
  1131.     if ( !selfsign ) {
  1132. issuerCert = CERT_FindCertByNicknameOrEmailAddr(handle, issuerNickName);
  1133. if (!issuerCert) {
  1134.     SECU_PrintError(progName, "could not find certificate named "%s"",
  1135.     issuerNickName);
  1136.     return NULL;
  1137. }
  1138.     }
  1139.     now = PR_Now();
  1140. #ifndef NSPR20
  1141.     PR_ExplodeGMTTime (&printableTime, now);
  1142. #else    
  1143.     PR_ExplodeTime (now, PR_GMTParameters, &printableTime);
  1144. #endif
  1145.     if ( warpmonths ) {
  1146. #ifndef NSPR20    
  1147. printableTime.tm_mon += warpmonths;
  1148. now = PR_ImplodeTime (&printableTime, 0, 0);
  1149. PR_ExplodeGMTTime (&printableTime, now);
  1150. #else
  1151. printableTime.tm_month += warpmonths;
  1152. now = PR_ImplodeTime (&printableTime);
  1153. PR_ExplodeTime (now, PR_GMTParameters, &printableTime);
  1154. #endif
  1155.     }
  1156. #ifndef NSPR20  
  1157.     printableTime.tm_mon += validitylength;  
  1158.     printableTime.tm_mon += 3;
  1159.     after = PR_ImplodeTime (&printableTime, 0, 0);
  1160. #else
  1161.     printableTime.tm_month += validitylength;
  1162.     printableTime.tm_month += 3;
  1163.     after = PR_ImplodeTime (&printableTime);
  1164. #endif    
  1165.     /* note that the time is now in micro-second unit */
  1166.     validity = CERT_CreateValidity (now, after);
  1167.     if ( selfsign ) {
  1168. cert = CERT_CreateCertificate
  1169.     (serialNumber,&(req->subject), validity, req);
  1170.     } else {
  1171. cert = CERT_CreateCertificate
  1172.     (serialNumber,&(issuerCert->subject), validity, req);
  1173.     }
  1174.     
  1175.     CERT_DestroyValidity(validity);
  1176.     if ( issuerCert ) {
  1177. CERT_DestroyCertificate (issuerCert);
  1178.     }
  1179.     
  1180.     return(cert);
  1181. }
  1182. static SECStatus 
  1183. AddKeyUsage (void *extHandle)
  1184. {
  1185.     SECItem bitStringValue;
  1186.     unsigned char keyUsage = 0x0;
  1187.     char buffer[5];
  1188.     int value;
  1189.     while (1) {
  1190. fprintf(stdout, "%-25s 0 - Digital Signaturen", "");
  1191. fprintf(stdout, "%-25s 1 - Non-repudiationn", "");
  1192. fprintf(stdout, "%-25s 2 - Key enciphermentn", "");
  1193. fprintf(stdout, "%-25s 3 - Data enciphermentn", "");   
  1194. fprintf(stdout, "%-25s 4 - Key agreementn", "");
  1195. fprintf(stdout, "%-25s 5 - Cert signning keyn", "");   
  1196. fprintf(stdout, "%-25s 6 - CRL signning keyn", "");
  1197. fprintf(stdout, "%-25s Other to finishn", "");
  1198. gets (buffer);
  1199. value = atoi (buffer);
  1200. if (value < 0 || value > 6)
  1201.     break;
  1202. keyUsage |= (0x80 >> value);
  1203.     }
  1204.     bitStringValue.data = &keyUsage;
  1205.     bitStringValue.len = 1;
  1206.     buffer[0] = 'n';
  1207.     puts ("Is this a critical extension [y/n]? ");
  1208.     gets (buffer);
  1209.     return (CERT_EncodeAndAddBitStrExtension
  1210.     (extHandle, SEC_OID_X509_KEY_USAGE, &bitStringValue,
  1211.      (buffer[0] == 'y' || buffer[0] == 'Y') ? PR_TRUE : PR_FALSE));
  1212. }
  1213. static CERTOidSequence *
  1214. CreateOidSequence(void)
  1215. {
  1216.   CERTOidSequence *rv = (CERTOidSequence *)NULL;
  1217.   PRArenaPool *arena = (PRArenaPool *)NULL;
  1218.   arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1219.   if( (PRArenaPool *)NULL == arena ) {
  1220.     goto loser;
  1221.   }
  1222.   rv = (CERTOidSequence *)PORT_ArenaZAlloc(arena, sizeof(CERTOidSequence));
  1223.   if( (CERTOidSequence *)NULL == rv ) {
  1224.     goto loser;
  1225.   }
  1226.   rv->oids = (SECItem **)PORT_ArenaZAlloc(arena, sizeof(SECItem *));
  1227.   if( (SECItem **)NULL == rv->oids ) {
  1228.     goto loser;
  1229.   }
  1230.   rv->arena = arena;
  1231.   return rv;
  1232.  loser:
  1233.   if( (PRArenaPool *)NULL != arena ) {
  1234.     PORT_FreeArena(arena, PR_FALSE);
  1235.   }
  1236.   return (CERTOidSequence *)NULL;
  1237. }
  1238. static SECStatus
  1239. AddOidToSequence(CERTOidSequence *os, SECOidTag oidTag)
  1240. {
  1241.   SECItem **oids;
  1242.   PRUint32 count = 0;
  1243.   SECOidData *od;
  1244.   od = SECOID_FindOIDByTag(oidTag);
  1245.   if( (SECOidData *)NULL == od ) {
  1246.     return SECFailure;
  1247.   }
  1248.   for( oids = os->oids; (SECItem *)NULL != *oids; oids++ ) {
  1249.     count++;
  1250.   }
  1251.   /* ArenaZRealloc */
  1252.   {
  1253.     PRUint32 i;
  1254.     oids = (SECItem **)PORT_ArenaZAlloc(os->arena, sizeof(SECItem *) * (count+2));
  1255.     if( (SECItem **)NULL == oids ) {
  1256.       return SECFailure;
  1257.     }
  1258.     
  1259.     for( i = 0; i < count; i++ ) {
  1260.       oids[i] = os->oids[i];
  1261.     }
  1262.     /* ArenaZFree(os->oids); */
  1263.   }
  1264.   os->oids = oids;
  1265.   os->oids[count] = &od->oid;
  1266.   return SECSuccess;
  1267. }
  1268. static SECItem *
  1269. EncodeOidSequence(CERTOidSequence *os)
  1270. {
  1271.   SECItem *rv;
  1272.   extern const SEC_ASN1Template CERT_OidSeqTemplate[];
  1273.   rv = (SECItem *)PORT_ArenaZAlloc(os->arena, sizeof(SECItem));
  1274.   if( (SECItem *)NULL == rv ) {
  1275.     goto loser;
  1276.   }
  1277.   if( !SEC_ASN1EncodeItem(os->arena, rv, os, CERT_OidSeqTemplate) ) {
  1278.     goto loser;
  1279.   }
  1280.   return rv;
  1281.  loser:
  1282.   return (SECItem *)NULL;
  1283. }
  1284. static SECStatus 
  1285. AddExtKeyUsage (void *extHandle)
  1286. {
  1287.   char buffer[5];
  1288.   int value;
  1289.   CERTOidSequence *os;
  1290.   SECStatus rv;
  1291.   SECItem *item;
  1292.   os = CreateOidSequence();
  1293.   if( (CERTOidSequence *)NULL == os ) {
  1294.     return SECFailure;
  1295.   }
  1296.   while (1) {
  1297.     fprintf(stdout, "%-25s 0 - Server Authn", "");
  1298.     fprintf(stdout, "%-25s 1 - Client Authn", "");
  1299.     fprintf(stdout, "%-25s 2 - Code Signingn", "");
  1300.     fprintf(stdout, "%-25s 3 - Email Protectionn", "");
  1301.     fprintf(stdout, "%-25s 4 - Timestampn", "");
  1302.     fprintf(stdout, "%-25s 5 - OSCP Respondern", "");
  1303. #ifdef DEBUG_NSSTEAM_ONLY
  1304.     fprintf(stdout, "%-25s 6 - Step-upn", "");
  1305. #endif /* DEBUG_NSSTEAM_ONLY */
  1306.     fprintf(stdout, "%-25s Other to finishn", "");
  1307.     gets(buffer);
  1308.     value = atoi(buffer);
  1309.     switch( value ) {
  1310.     case 0:
  1311.       rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_SERVER_AUTH);
  1312.       break;
  1313.     case 1:
  1314.       rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH);
  1315.       break;
  1316.     case 2:
  1317.       rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_CODE_SIGN);
  1318.       break;
  1319.     case 3:
  1320.       rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT);
  1321.       break;
  1322.     case 4:
  1323.       rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_TIME_STAMP);
  1324.       break;
  1325.     case 5:
  1326.       rv = AddOidToSequence(os, SEC_OID_OCSP_RESPONDER);
  1327.       break;
  1328. #ifdef DEBUG_NSSTEAM_ONLY
  1329.     case 6:
  1330.       rv = AddOidToSequence(os, SEC_OID_NS_KEY_USAGE_GOVT_APPROVED);
  1331.       break;
  1332. #endif /* DEBUG_NSSTEAM_ONLY */
  1333.     default:
  1334.       goto endloop;
  1335.     }
  1336.     if( SECSuccess != rv ) goto loser;
  1337.   }
  1338.  endloop:;
  1339.   item = EncodeOidSequence(os);
  1340.   buffer[0] = 'n';
  1341.   puts ("Is this a critical extension [y/n]? ");
  1342.   gets (buffer);
  1343.   rv = CERT_AddExtension(extHandle, SEC_OID_X509_EXT_KEY_USAGE, item,
  1344.                          ((buffer[0] == 'y' || buffer[0] == 'Y')
  1345.                           ? PR_TRUE : PR_FALSE), PR_TRUE);
  1346.   /*FALLTHROUGH*/
  1347.  loser:
  1348.   CERT_DestroyOidSequence(os);
  1349.   return rv;
  1350. }
  1351. static SECStatus 
  1352. AddNscpCertType (void *extHandle)
  1353. {
  1354.     SECItem bitStringValue;
  1355.     unsigned char keyUsage = 0x0;
  1356.     char buffer[5];
  1357.     int value;
  1358.     while (1) {
  1359. fprintf(stdout, "%-25s 0 - SSL Clientn", "");
  1360. fprintf(stdout, "%-25s 1 - SSL Servern", "");
  1361. fprintf(stdout, "%-25s 2 - S/MIMEn", "");
  1362. fprintf(stdout, "%-25s 3 - Object Signingn", "");   
  1363. fprintf(stdout, "%-25s 4 - Reserved for futuer usen", "");
  1364. fprintf(stdout, "%-25s 5 - SSL CAn", "");   
  1365. fprintf(stdout, "%-25s 6 - S/MIME CAn", "");
  1366. fprintf(stdout, "%-25s 7 - Object Signing CAn", "");
  1367. fprintf(stdout, "%-25s Other to finishn", "");
  1368. gets (buffer);
  1369. value = atoi (buffer);
  1370. if (value < 0 || value > 7)
  1371.     break;
  1372. keyUsage |= (0x80 >> value);
  1373.     }
  1374.     bitStringValue.data = &keyUsage;
  1375.     bitStringValue.len = 1;
  1376.     buffer[0] = 'n';
  1377.     puts ("Is this a critical extension [y/n]? ");
  1378.     gets (buffer);
  1379.     return (CERT_EncodeAndAddBitStrExtension
  1380.     (extHandle, SEC_OID_NS_CERT_EXT_CERT_TYPE, &bitStringValue,
  1381.      (buffer[0] == 'y' || buffer[0] == 'Y') ? PR_TRUE : PR_FALSE));
  1382. }
  1383. typedef SECStatus (* EXTEN_VALUE_ENCODER)
  1384. (PRArenaPool *extHandle, void *value, SECItem *encodedValue);
  1385. static SECStatus 
  1386. EncodeAndAddExtensionValue(
  1387. PRArenaPool * arena, 
  1388. void * extHandle, 
  1389. void * value, 
  1390. PRBool  criticality,
  1391. int  extenType, 
  1392. EXTEN_VALUE_ENCODER EncodeValueFn)
  1393. {
  1394.     SECItem encodedValue;
  1395.     SECStatus rv;
  1396.     encodedValue.data = NULL;
  1397.     encodedValue.len = 0;
  1398.     do {
  1399. rv = (*EncodeValueFn)(arena, value, &encodedValue);
  1400. if (rv != SECSuccess)
  1401. break;
  1402. rv = CERT_AddExtension
  1403.      (extHandle, extenType, &encodedValue, criticality,PR_TRUE);
  1404.     } while (0);
  1405.     return (rv);
  1406. }
  1407. static SECStatus 
  1408. AddBasicConstraint(void *extHandle)
  1409. {
  1410.     CERTBasicConstraints basicConstraint;    
  1411.     SECItem encodedValue;
  1412.     SECStatus rv;
  1413.     char buffer[10];
  1414.     encodedValue.data = NULL;
  1415.     encodedValue.len = 0;
  1416.     do {
  1417. basicConstraint.pathLenConstraint = CERT_UNLIMITED_PATH_CONSTRAINT;
  1418. puts ("Is this a CA certificate [y/n]?");
  1419. gets (buffer);
  1420. basicConstraint.isCA = (buffer[0] == 'Y' || buffer[0] == 'y') ?
  1421.                                 PR_TRUE : PR_FALSE;
  1422. puts ("Enter the path length constraint, enter to skip [<0 for unlimited path]:");
  1423. gets (buffer);
  1424. if (PORT_Strlen (buffer) > 0)
  1425.     basicConstraint.pathLenConstraint = atoi (buffer);
  1426. rv = CERT_EncodeBasicConstraintValue (NULL, &basicConstraint, &encodedValue);
  1427. if (rv)
  1428.     return (rv);
  1429. buffer[0] = 'n';
  1430. puts ("Is this a critical extension [y/n]? ");
  1431. gets (buffer);
  1432. rv = CERT_AddExtension
  1433.      (extHandle, SEC_OID_X509_BASIC_CONSTRAINTS,
  1434.       &encodedValue, (buffer[0] == 'y' || buffer[0] == 'Y') ?
  1435.               PR_TRUE : PR_FALSE ,PR_TRUE);
  1436.     } while (0);
  1437.     PORT_Free (encodedValue.data);
  1438.     return (rv);
  1439. }
  1440. static SECItem *
  1441. SignCert(CERTCertDBHandle *handle, 
  1442. CERTCertificate *cert, PRBool selfsign, 
  1443. SECKEYPrivateKey *selfsignprivkey, char *issuerNickName, void *pwarg)
  1444. {
  1445.     SECItem der;
  1446.     SECItem *result = NULL;
  1447.     SECKEYPrivateKey *caPrivateKey = NULL;    
  1448.     SECStatus rv;
  1449.     PRArenaPool *arena;
  1450.     SECOidTag algID;
  1451.     void *dummy;
  1452.     if( selfsign ) {
  1453.       caPrivateKey = selfsignprivkey;
  1454.     } else {
  1455.       /*CERTCertificate *issuer = CERT_FindCertByNickname(handle, issuerNickName);*/
  1456.       CERTCertificate *issuer = PK11_FindCertFromNickname(issuerNickName, pwarg);
  1457.       if( (CERTCertificate *)NULL == issuer ) {
  1458.         SECU_PrintError(progName, "unable to find issuer with nickname %s", 
  1459.                 issuerNickName);
  1460.         return (SECItem *)NULL;
  1461.       }
  1462.       caPrivateKey = PK11_FindKeyByAnyCert(issuer, pwarg);
  1463.     if (caPrivateKey == NULL) {
  1464. SECU_PrintError(progName, "unable to retrieve key %s", issuerNickName);
  1465. return NULL;
  1466.     }
  1467.     }
  1468.     arena = cert->arena;
  1469.     switch(caPrivateKey->keyType) {
  1470.       case rsaKey:
  1471. algID = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
  1472. break;
  1473.       case dsaKey:
  1474. algID = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
  1475. break;
  1476.       default:
  1477. fprintf(stderr, "Unknown key type for issuer.");
  1478. goto done;
  1479. break;
  1480.     }
  1481.     rv = SECOID_SetAlgorithmID(arena, &cert->signature, algID, 0);
  1482.     if (rv != SECSuccess) {
  1483. fprintf(stderr, "Could not set signature algorithm id.");
  1484. goto done;
  1485.     }
  1486.     /* we only deal with cert v3 here */
  1487.     *(cert->version.data) = 2;
  1488.     cert->version.len = 1;
  1489.     der.len = 0;
  1490.     der.data = NULL;
  1491.     dummy = SEC_ASN1EncodeItem (arena, &der, cert, CERT_CertificateTemplate);
  1492.     if (!dummy) {
  1493. fprintf (stderr, "Could not encode certificate.n");
  1494. goto done;
  1495.     }
  1496.     result = (SECItem *) PORT_ArenaZAlloc (arena, sizeof (SECItem));
  1497.     if (result == NULL) {
  1498. fprintf (stderr, "Could not allocate item for certificate data.n");
  1499. goto done;
  1500.     }
  1501.     rv = SEC_DerSignData (arena, result, der.data, der.len, caPrivateKey,
  1502.   algID);
  1503.     if (rv != SECSuccess) {
  1504. fprintf (stderr, "Could not sign encoded certificate data.n");
  1505. PORT_Free(result);
  1506. result = NULL;
  1507. goto done;
  1508.     }
  1509.     cert->derCert = *result;
  1510. done:
  1511.     SECKEY_DestroyPrivateKey(caPrivateKey);
  1512.     return result;
  1513. }
  1514. static SECStatus 
  1515. AddAuthKeyID (void *extHandle)
  1516. {
  1517.     CERTAuthKeyID *authKeyID = NULL;    
  1518.     PRArenaPool *arena = NULL;
  1519.     SECStatus rv = SECSuccess;
  1520.     char buffer[512];
  1521.     do {
  1522. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1523. if ( !arena ) {
  1524.     SECU_PrintError(progName, "out of memory");
  1525.     GEN_BREAK (SECFailure);
  1526. }
  1527. if (GetYesNo ("Enter value for the authKeyID extension [y/n]?n") == 0)
  1528.     break;
  1529. authKeyID = PORT_ArenaZAlloc (arena, sizeof (CERTAuthKeyID));
  1530. if (authKeyID == NULL) {
  1531.     GEN_BREAK (SECFailure);
  1532. }
  1533. rv = GetString (arena, "Enter value for the key identifier fields, enter to omit:",
  1534. &authKeyID->keyID);
  1535. if (rv != SECSuccess)
  1536.     break;
  1537. authKeyID->authCertIssuer = GetGeneralName (arena);
  1538. if (authKeyID->authCertIssuer == NULL && SECFailure == PORT_GetError ())
  1539. break;
  1540. rv = GetString (arena, "Enter value for the authCertSerial field, enter to omit:",
  1541. &authKeyID->authCertSerialNumber);
  1542. buffer[0] = 'n';
  1543. puts ("Is this a critical extension [y/n]? ");
  1544. gets (buffer);
  1545. rv = EncodeAndAddExtensionValue
  1546.     (arena, extHandle, authKeyID,
  1547.      (buffer[0] == 'y' || buffer[0] == 'Y') ? PR_TRUE : PR_FALSE,
  1548.      SEC_OID_X509_AUTH_KEY_ID, 
  1549.      (EXTEN_VALUE_ENCODER) CERT_EncodeAuthKeyID);
  1550. if (rv)
  1551.     break;
  1552.     } while (0);
  1553.     if (arena)
  1554. PORT_FreeArena (arena, PR_FALSE);
  1555.     return (rv);
  1556. }   
  1557.     
  1558. static SECStatus 
  1559. AddCrlDistPoint(void *extHandle)
  1560. {
  1561.     PRArenaPool *arena = NULL;
  1562.     CERTCrlDistributionPoints *crlDistPoints = NULL;
  1563.     CRLDistributionPoint *current;
  1564.     SECStatus rv = SECSuccess;
  1565.     int count = 0, intValue;
  1566.     char buffer[5];
  1567.     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1568.     if ( !arena )
  1569. return (SECFailure);
  1570.     do {
  1571. current = NULL;
  1572. current = PORT_ArenaZAlloc (arena, sizeof (*current));
  1573.         if (current == NULL) {
  1574.     GEN_BREAK (SECFailure);
  1575. }   
  1576. /* Get the distributionPointName fields - this field is optional */
  1577. puts ("Enter the type of the distribution point name:n");
  1578. puts ("t1 - Full Nament2 - Relative NamentOther - omitnttChoice: ");
  1579. scanf ("%d", &intValue);
  1580. switch (intValue) {
  1581.     case generalName:
  1582. current->distPointType = intValue;
  1583. current->distPoint.fullName = GetGeneralName (arena);
  1584. rv = PORT_GetError();
  1585. break;
  1586.     case relativeDistinguishedName: {
  1587. CERTName *name;
  1588. char buffer[512];
  1589. current->distPointType = intValue;
  1590. puts ("Enter the relative name: ");
  1591. fflush (stdout);
  1592. gets (buffer);
  1593. /* For simplicity, use CERT_AsciiToName to converse from a string
  1594.    to NAME, but we only interest in the first RDN */
  1595. name = CERT_AsciiToName (buffer);
  1596. if (!name) {
  1597.     GEN_BREAK (SECFailure);
  1598. }
  1599. rv = CERT_CopyRDN (arena, &current->distPoint.relativeName, name->rdns[0]);
  1600. CERT_DestroyName (name);
  1601. break;
  1602.     }
  1603. }
  1604. if (rv != SECSuccess)
  1605.     break;
  1606. /* Get the reason flags */
  1607. puts ("nSelect one of the following for the reason flagsn");
  1608. puts ("t0 - unusednt1 - keyCompromisent2 - caCompromisent3 - affiliationChangedn");
  1609. puts ("t4 - supersedednt5 - cessationOfOperationnt6 - certificateHoldn");
  1610. puts ("tother - omitttChoice: ");
  1611. scanf ("%d", &intValue);
  1612. if (intValue >= 0 && intValue <8) {
  1613.     current->reasons.data = PORT_ArenaAlloc (arena, sizeof(char));
  1614.     if (current->reasons.data == NULL) {
  1615. GEN_BREAK (SECFailure);
  1616.     }
  1617.     *current->reasons.data = (char)(0x80 >> intValue);
  1618.     current->reasons.len = 1;
  1619. }
  1620. puts ("Enter value for the CRL Issuer name:n");
  1621.         current->crlIssuer = GetGeneralName (arena);
  1622. if (current->crlIssuer == NULL && (rv = PORT_GetError()) == SECFailure)
  1623.     break;
  1624. if (crlDistPoints == NULL) {
  1625.     crlDistPoints = PORT_ArenaZAlloc (arena, sizeof (*crlDistPoints));
  1626.     if (crlDistPoints == NULL) {
  1627. GEN_BREAK (SECFailure);
  1628.     }
  1629. }
  1630.     
  1631. crlDistPoints->distPoints = PORT_ArenaGrow (arena, 
  1632.      crlDistPoints->distPoints,
  1633.      sizeof (*crlDistPoints->distPoints) * count,
  1634.      sizeof (*crlDistPoints->distPoints) *(count + 1));
  1635. if (crlDistPoints->distPoints == NULL) {
  1636.     GEN_BREAK (SECFailure);
  1637. }
  1638. crlDistPoints->distPoints[count] = current;
  1639. ++count;
  1640. if (GetYesNo ("Enter more value for the CRL distribution point extension [y/n]n") == 0) {
  1641.     /* Add null to the end of the crlDistPoints to mark end of data */
  1642.     crlDistPoints->distPoints = PORT_ArenaGrow(arena, 
  1643.  crlDistPoints->distPoints,
  1644.  sizeof (*crlDistPoints->distPoints) * count,
  1645.  sizeof (*crlDistPoints->distPoints) *(count + 1));
  1646.     crlDistPoints->distPoints[count] = NULL;     
  1647.     break;
  1648. }
  1649.     } while (1);
  1650.     
  1651.     if (rv == SECSuccess) {
  1652. buffer[0] = 'n';
  1653. puts ("Is this a critical extension [y/n]? ");
  1654. gets (buffer);
  1655. rv = EncodeAndAddExtensionValue(arena, extHandle, crlDistPoints,
  1656.       (buffer[0] == 'Y' || buffer[0] == 'y') ? PR_TRUE : PR_FALSE,
  1657.       SEC_OID_X509_CRL_DIST_POINTS,
  1658.       (EXTEN_VALUE_ENCODER)  CERT_EncodeCRLDistributionPoints);
  1659.     }
  1660.     if (arena)
  1661. PORT_FreeArena (arena, PR_FALSE);
  1662.     return (rv);
  1663. }
  1664. static SECStatus
  1665. CreateCert(
  1666. CERTCertDBHandle *handle, 
  1667. char *  issuerNickName, 
  1668. PRFileDesc *inFile,
  1669. PRFileDesc *outFile, 
  1670. SECKEYPrivateKey *selfsignprivkey,
  1671. void  *pwarg,
  1672. int     serialNumber, 
  1673. int     warpmonths,
  1674. int     validitylength,
  1675. PRBool  selfsign,
  1676. PRBool keyUsage, 
  1677. PRBool  extKeyUsage,
  1678. PRBool  basicConstraint, 
  1679. PRBool  authKeyID,
  1680. PRBool  crlDistPoints, 
  1681. PRBool  nscpCertType)
  1682. {
  1683.     void * extHandle;
  1684.     SECItem * certDER;
  1685.     PRArenaPool *arena = NULL;
  1686.     CERTCertificate *subjectCert  = NULL;
  1687.     /*CERTCertificate *issuerCert  = NULL;*/
  1688.     CERTCertificateRequest *certReq = NULL;
  1689.     SECStatus  rv  = SECSuccess;
  1690.     SECItem  reqDER;
  1691.     reqDER.data = NULL;
  1692.     do {
  1693. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1694. if (!arena) {
  1695.     GEN_BREAK (SEC_ERROR_NO_MEMORY);
  1696. }
  1697. /* Create a certrequest object from the input cert request der */
  1698. certReq = GetCertRequest(inFile);
  1699. if (certReq == NULL) {
  1700.     GEN_BREAK (SECFailure)
  1701. }
  1702. subjectCert = MakeV1Cert (handle, certReq, issuerNickName, selfsign,
  1703.   serialNumber, warpmonths, validitylength);
  1704. if (subjectCert == NULL) {
  1705.     GEN_BREAK (SECFailure)
  1706. }
  1707. extHandle = CERT_StartCertExtensions (subjectCert);
  1708. if (extHandle == NULL) {
  1709.     GEN_BREAK (SECFailure)
  1710. }
  1711. /* Add key usage extension */
  1712. if (keyUsage) {
  1713.     rv = AddKeyUsage(extHandle);
  1714.     if (rv)
  1715. break;
  1716. }
  1717. /* Add extended key usage extension */
  1718. if (extKeyUsage) {
  1719.     rv = AddExtKeyUsage(extHandle);
  1720.     if (rv)
  1721. break;
  1722. }
  1723. /* Add basic constraint extension */
  1724. if (basicConstraint) {
  1725.     rv = AddBasicConstraint(extHandle);
  1726.     if (rv)
  1727. break;
  1728. }
  1729. if (authKeyID) {
  1730.     rv = AddAuthKeyID (extHandle);
  1731.     if (rv)
  1732. break;
  1733. }    
  1734. if (crlDistPoints) {
  1735.     rv = AddCrlDistPoint (extHandle);
  1736.     if (rv)
  1737. break;
  1738. }
  1739. if (nscpCertType) {
  1740.     rv = AddNscpCertType(extHandle);
  1741.     if (rv)
  1742. break;
  1743. }
  1744.        
  1745. CERT_FinishExtensions(extHandle);
  1746. certDER = SignCert (handle, subjectCert, selfsign, selfsignprivkey, issuerNickName,pwarg);
  1747. if (certDER)
  1748.    PR_Write(outFile, certDER->data, certDER->len);
  1749.        /*fwrite (certDER->data, 1, certDER->len, outFile);*/
  1750.     } while (0);
  1751.     CERT_DestroyCertificateRequest (certReq);
  1752.     CERT_DestroyCertificate (subjectCert);
  1753.     PORT_FreeArena (arena, PR_FALSE);
  1754.     if (rv != SECSuccess) {
  1755. PRErrorCode  perr = PR_GetError();
  1756.         fprintf(stderr, "%s: unable to create cert (%s)n", progName,
  1757.                SECU_Strerror(perr));
  1758.     }
  1759.     return (rv);
  1760. }
  1761. /*  Certutil commands  */
  1762. enum {
  1763.     cmd_AddCert = 0,
  1764.     cmd_CreateNewCert,
  1765.     cmd_DeleteCert,
  1766.     cmd_AddEmailCert,
  1767.     cmd_DeleteKey,
  1768.     cmd_GenKeyPair,
  1769.     cmd_PrintHelp,
  1770.     cmd_ListKeys,
  1771.     cmd_ListCerts,
  1772.     cmd_ModifyCertTrust,
  1773.     cmd_NewDBs,
  1774.     cmd_CertReq,
  1775.     cmd_CreateAndAddCert,
  1776.     cmd_ListModules,
  1777.     cmd_CheckCertValidity,
  1778.     cmd_ChangePassword
  1779. };
  1780. /*  Certutil options */
  1781. enum {
  1782.     opt_AddKeyUsageExt = 0,
  1783.     opt_AddBasicConstraintExt,
  1784.     opt_AddAuthorityKeyIDExt,
  1785.     opt_AddCRLDistPtsExt,
  1786.     opt_AddNSCertTypeExt,
  1787.     opt_AddExtKeyUsageExt,
  1788.     opt_ASCIIForIO,
  1789.     opt_ValidityTime,
  1790.     opt_IssuerName,
  1791.     opt_CertDir,
  1792.     opt_VerifySig,
  1793.     opt_PasswordFile,
  1794.     opt_KeySize,
  1795.     opt_TokenName,
  1796.     opt_InputFile,
  1797.     opt_KeyIndex,
  1798.     opt_KeyType,
  1799.     opt_DetailedInfo,
  1800.     opt_SerialNumber,
  1801.     opt_Nickname,
  1802.     opt_OutputFile,
  1803.     opt_PhoneNumber,
  1804.     opt_PQGFile,
  1805.     opt_BinaryDER,
  1806.     opt_Subject,
  1807.     opt_Trust,
  1808.     opt_Usage,
  1809.     opt_Validity,
  1810.     opt_OffsetMonths,
  1811.     opt_SelfSign,
  1812.     opt_Exponent,
  1813.     opt_NoiseFile
  1814. };
  1815. static secuCommandFlag certutil_commands[] =
  1816. {
  1817. { /* cmd_AddCert             */  'A', PR_FALSE, 0, PR_FALSE },
  1818. { /* cmd_CreateNewCert       */  'C', PR_FALSE, 0, PR_FALSE },
  1819. { /* cmd_DeleteCert          */  'D', PR_FALSE, 0, PR_FALSE },
  1820. { /* cmd_AddEmailCert        */  'E', PR_FALSE, 0, PR_FALSE },
  1821. { /* cmd_DeleteKey           */  'F', PR_FALSE, 0, PR_FALSE },
  1822. { /* cmd_GenKeyPair          */  'G', PR_FALSE, 0, PR_FALSE },
  1823. { /* cmd_PrintHelp           */  'H', PR_FALSE, 0, PR_FALSE },
  1824. { /* cmd_ListKeys            */  'K', PR_FALSE, 0, PR_FALSE },
  1825. { /* cmd_ListCerts           */  'L', PR_FALSE, 0, PR_FALSE },
  1826. { /* cmd_ModifyCertTrust     */  'M', PR_FALSE, 0, PR_FALSE },
  1827. { /* cmd_NewDBs              */  'N', PR_FALSE, 0, PR_FALSE },
  1828. { /* cmd_CertReq             */  'R', PR_FALSE, 0, PR_FALSE },
  1829. { /* cmd_CreateAndAddCert    */  'S', PR_FALSE, 0, PR_FALSE },
  1830. { /* cmd_ListModules         */  'U', PR_FALSE, 0, PR_FALSE },
  1831. { /* cmd_CheckCertValidity   */  'V', PR_FALSE, 0, PR_FALSE },
  1832. { /* cmd_ChangePassword      */  'W', PR_FALSE, 0, PR_FALSE }
  1833. };
  1834. static secuCommandFlag certutil_options[] =
  1835. {
  1836. { /* opt_AddKeyUsageExt      */  '1', PR_FALSE, 0, PR_FALSE },
  1837. { /* opt_AddBasicConstraintExt*/ '2', PR_FALSE, 0, PR_FALSE },
  1838. { /* opt_AddAuthorityKeyIDExt*/  '3', PR_FALSE, 0, PR_FALSE },
  1839. { /* opt_AddCRLDistPtsExt    */  '4', PR_FALSE, 0, PR_FALSE },
  1840. { /* opt_AddNSCertTypeExt    */  '5', PR_FALSE, 0, PR_FALSE },
  1841. { /* opt_AddExtKeyUsageExt   */  '6', PR_FALSE, 0, PR_FALSE },
  1842. { /* opt_ASCIIForIO          */  'a', PR_FALSE, 0, PR_FALSE },
  1843. { /* opt_ValidityTime        */  'b', PR_TRUE,  0, PR_FALSE },
  1844. { /* opt_IssuerName          */  'c', PR_TRUE,  0, PR_FALSE },
  1845. { /* opt_CertDir             */  'd', PR_TRUE,  0, PR_FALSE },
  1846. { /* opt_VerifySig           */  'e', PR_FALSE, 0, PR_FALSE },
  1847. { /* opt_PasswordFile        */  'f', PR_TRUE,  0, PR_FALSE },
  1848. { /* opt_KeySize             */  'g', PR_TRUE,  0, PR_FALSE },
  1849. { /* opt_TokenName           */  'h', PR_TRUE,  0, PR_FALSE },
  1850. { /* opt_InputFile           */  'i', PR_TRUE,  0, PR_FALSE },
  1851. { /* opt_KeyIndex            */  'j', PR_TRUE,  0, PR_FALSE },
  1852. { /* opt_KeyType             */  'k', PR_TRUE,  0, PR_FALSE },
  1853. { /* opt_DetailedInfo        */  'l', PR_FALSE, 0, PR_FALSE },
  1854. { /* opt_SerialNumber        */  'm', PR_TRUE,  0, PR_FALSE },
  1855. { /* opt_Nickname            */  'n', PR_TRUE,  0, PR_FALSE },
  1856. { /* opt_OutputFile          */  'o', PR_TRUE,  0, PR_FALSE },
  1857. { /* opt_PhoneNumber         */  'p', PR_TRUE,  0, PR_FALSE },
  1858. { /* opt_PQGFile             */  'q', PR_TRUE,  0, PR_FALSE },
  1859. { /* opt_BinaryDER           */  'r', PR_FALSE, 0, PR_FALSE },
  1860. { /* opt_Subject             */  's', PR_TRUE,  0, PR_FALSE },
  1861. { /* opt_Trust               */  't', PR_TRUE,  0, PR_FALSE },
  1862. { /* opt_Usage               */  'u', PR_TRUE,  0, PR_FALSE },
  1863. { /* opt_Validity            */  'v', PR_TRUE,  0, PR_FALSE },
  1864. { /* opt_OffsetMonths        */  'w', PR_TRUE,  0, PR_FALSE },
  1865. { /* opt_SelfSign            */  'x', PR_FALSE, 0, PR_FALSE },
  1866. { /* opt_Exponent            */  'y', PR_TRUE,  0, PR_FALSE },
  1867. { /* opt_NoiseFile           */  'z', PR_TRUE,  0, PR_FALSE }
  1868. };
  1869. int 
  1870. main(int argc, char **argv)
  1871. {
  1872.     CERTCertDBHandle *certHandle;
  1873.     SECKEYKeyDBHandle *keyHandle;
  1874.     PK11SlotInfo *slot = NULL;
  1875.     CERTName *  subject         = 0;
  1876.     PRFileDesc *inFile          = 0;
  1877.     PRFileDesc *outFile         = 0;
  1878.     char *      certfile        = "tempcert";
  1879.     char *      certreqfile     = "tempcertreq";
  1880.     char *      slotname        = "internal";
  1881.     KeyType     keytype         = rsaKey;
  1882.     /*char * keyslot         = NULL;*/
  1883.     /*char *      keynickname     = NULL;*/
  1884.     char *      name            = NULL;
  1885.     int         keysize         = DEFAULT_KEY_BITS;
  1886.     int         publicExponent  = 0x010001;
  1887.     int         serialNumber    = 0;
  1888.     int         warpmonths      = 0;
  1889.     int         validitylength  = 0;
  1890.     int         commandsEntered = 0;
  1891.     char        commandToRun    = '';
  1892.     secuPWData  pwdata          = { PW_NONE, 0 };
  1893.     SECKEYPrivateKey *privkey;
  1894.     SECKEYPublicKey *pubkey = NULL;
  1895.     int i;
  1896.     SECStatus rv;
  1897.     secuCommand certutil;
  1898.     certutil.numCommands = sizeof(certutil_commands) / sizeof(secuCommandFlag);
  1899.     certutil.numOptions = sizeof(certutil_options) / sizeof(secuCommandFlag);
  1900.     certutil.commands = certutil_commands;
  1901.     certutil.options = certutil_options;
  1902.     progName = strrchr(argv[0], '/');
  1903.     progName = progName ? progName+1 : argv[0];
  1904.     rv = SECU_ParseCommandLine(argc, argv, progName, &certutil);
  1905.     if (rv != SECSuccess)
  1906. Usage(progName);
  1907.     if (certutil.commands[cmd_PrintHelp].activated)
  1908. LongUsage(progName);
  1909.     if (certutil.options[opt_PasswordFile].arg) {
  1910. pwdata.source = PW_FROMFILE;
  1911. pwdata.data = certutil.options[opt_PasswordFile].arg;
  1912.     }
  1913.     if (certutil.options[opt_CertDir].activated)
  1914. SECU_ConfigDirectory(certutil.options[opt_CertDir].arg);
  1915.     if (certutil.options[opt_KeySize].activated) {
  1916. keysize = PORT_Atoi(certutil.options[opt_KeySize].arg);
  1917. if ((keysize < MIN_KEY_BITS) || (keysize > MAX_KEY_BITS)) {
  1918.     PR_fprintf(PR_STDERR, 
  1919.                        "%s -g:  Keysize must be between %d and %d.n",
  1920.                MIN_KEY_BITS, MAX_KEY_BITS);
  1921.     return -1;
  1922. }
  1923.     }
  1924.     /*  -h specify token name  */
  1925.     if (certutil.options[opt_TokenName].activated) {
  1926. if (PL_strcmp(certutil.options[opt_TokenName].arg, "all") == 0)
  1927.     slotname = NULL;
  1928. else
  1929.     slotname = PL_strdup(certutil.options[opt_TokenName].arg);
  1930.     }
  1931.     /*  -k key type  */
  1932.     if (certutil.options[opt_KeyType].activated) {
  1933. if (PL_strcmp(certutil.options[opt_KeyType].arg, "rsa") == 0) {
  1934.     keytype = rsaKey;
  1935. } else if (PL_strcmp(certutil.options[opt_KeyType].arg, "dsa") == 0) {
  1936.     keytype = dsaKey;
  1937. } else if (PL_strcmp(certutil.options[opt_KeyType].arg, "all") == 0) {
  1938.     keytype = nullKey;
  1939. } else {
  1940.     PR_fprintf(PR_STDERR, "%s -k:  %s is not a recognized type.n",
  1941.                progName, certutil.options[opt_KeyType].arg);
  1942.     return -1;
  1943. }
  1944.     }
  1945.     /*  -m serial number */
  1946.     if (certutil.options[opt_SerialNumber].activated) {
  1947. serialNumber = PORT_Atoi(certutil.options[opt_SerialNumber].arg);
  1948. if (serialNumber < 0) {
  1949.     PR_fprintf(PR_STDERR, "%s -m:  %s is not a valid serial number.n",
  1950.                progName, certutil.options[opt_SerialNumber].arg);
  1951.     return -1;
  1952. }
  1953.     }
  1954.     /*  -q PQG file  */
  1955.     if (certutil.options[opt_PQGFile].activated) {
  1956. if (keytype != dsaKey) {
  1957.     PR_fprintf(PR_STDERR, "%s -q: PQG file is for DSA key (-k dsa).n)",
  1958.                progName);
  1959.     return -1;
  1960. }
  1961.     }
  1962.     /*  -s subject name  */
  1963.     if (certutil.options[opt_Subject].activated) {
  1964. subject = CERT_AsciiToName(certutil.options[opt_Subject].arg);
  1965. if (!subject) {
  1966.     PR_fprintf(PR_STDERR, "%s -s: improperly formatted name: "%s"n",
  1967.                progName, certutil.options[opt_Subject].arg);
  1968.     return -1;
  1969. }
  1970.     }
  1971.     /*  -v validity period  */
  1972.     if (certutil.options[opt_Validity].activated) {
  1973. validitylength = PORT_Atoi(certutil.options[opt_Validity].arg);
  1974. if (validitylength < 0) {
  1975.     PR_fprintf(PR_STDERR, "%s -v: incorrect validity period: "%s"n",
  1976.                progName, certutil.options[opt_Validity].arg);
  1977.     return -1;
  1978. }
  1979.     }
  1980.     /*  -w warp months  */
  1981.     if (certutil.options[opt_OffsetMonths].activated)
  1982. warpmonths = PORT_Atoi(certutil.options[opt_OffsetMonths].arg);
  1983.     /*  -y public exponent (for RSA)  */
  1984.     if (certutil.options[opt_Exponent].activated) {
  1985. publicExponent = PORT_Atoi(certutil.options[opt_Exponent].arg);
  1986. if ((publicExponent != 3) &&
  1987.     (publicExponent != 17) &&
  1988.     (publicExponent != 65537)) {
  1989.     PR_fprintf(PR_STDERR, "%s -y: incorrect public exponent %d.", 
  1990.                            progName, publicExponent);
  1991.     PR_fprintf(PR_STDERR, "Must be 3, 17, or 65537.n");
  1992.     return -1;
  1993. }
  1994.     }
  1995.     /*  Check number of commands entered.  */
  1996.     commandsEntered = 0;
  1997.     for (i=0; i< certutil.numCommands; i++) {
  1998. if (certutil.commands[i].activated) {
  1999.     commandToRun = certutil.commands[i].flag;
  2000.     commandsEntered++;
  2001. }
  2002. if (commandsEntered > 1)
  2003.     break;
  2004.     }
  2005.     if (commandsEntered > 1) {
  2006. PR_fprintf(PR_STDERR, "%s: only one command at a time!n", progName);
  2007. PR_fprintf(PR_STDERR, "You entered: ");
  2008. for (i=0; i< certutil.numCommands; i++) {
  2009.     if (certutil.commands[i].activated)
  2010. PR_fprintf(PR_STDERR, " -%c", certutil.commands[i].flag);
  2011. }
  2012. PR_fprintf(PR_STDERR, "n");
  2013. return -1;
  2014.     }
  2015.     if (commandsEntered == 0) {
  2016. PR_fprintf(PR_STDERR, "%s: you must enter a command!n", progName);
  2017. Usage(progName);
  2018.     }
  2019.     /*  -A, -D, -F, -M, -S, -V, and all require -n  */
  2020.     if ((certutil.commands[cmd_AddCert].activated ||
  2021.          certutil.commands[cmd_DeleteCert].activated ||
  2022.          certutil.commands[cmd_DeleteKey].activated ||
  2023.          certutil.commands[cmd_ModifyCertTrust].activated ||
  2024.          certutil.commands[cmd_CreateAndAddCert].activated ||
  2025.          certutil.commands[cmd_CheckCertValidity].activated) &&
  2026.         !certutil.options[opt_Nickname].activated) {
  2027. PR_fprintf(PR_STDERR, 
  2028.           "%s -%c: nickname is required for this command (-n).n",
  2029.            progName, commandToRun);
  2030. return -1;
  2031.     }
  2032.     /*  -A, -E, -M, -S require trust  */
  2033.     if ((certutil.commands[cmd_AddCert].activated ||
  2034.          certutil.commands[cmd_AddEmailCert].activated ||
  2035.          certutil.commands[cmd_ModifyCertTrust].activated ||
  2036.          certutil.commands[cmd_CreateAndAddCert].activated) &&
  2037.         !certutil.options[opt_Trust].activated) {
  2038. PR_fprintf(PR_STDERR, 
  2039.           "%s -%c: trust is required for this command (-t).n",
  2040.            progName, commandToRun);
  2041. return -1;
  2042.     }
  2043.     /*  if -L is given raw or ascii mode, it must be for only one cert.  */
  2044.     if (certutil.commands[cmd_ListCerts].activated &&
  2045.         (certutil.options[opt_ASCIIForIO].activated ||
  2046.          certutil.options[opt_BinaryDER].activated) &&
  2047.         !certutil.options[opt_Nickname].activated) {
  2048. PR_fprintf(PR_STDERR, 
  2049.         "%s: nickname is required to dump cert in raw or ascii mode.n",
  2050.            progName);
  2051. return -1;
  2052.     }
  2053.     
  2054.     /*  -L can only be in (raw || ascii).  */
  2055.     if (certutil.commands[cmd_ListCerts].activated &&
  2056.         certutil.options[opt_ASCIIForIO].activated &&
  2057.         certutil.options[opt_BinaryDER].activated) {
  2058. PR_fprintf(PR_STDERR, 
  2059.            "%s: cannot specify both -r and -a when dumping cert.n",
  2060.            progName);
  2061. return -1;
  2062.     }
  2063.     /*  If making a cert request, need a subject.  */
  2064.     if ((certutil.commands[cmd_CertReq].activated ||
  2065.          certutil.commands[cmd_CreateAndAddCert].activated) &&
  2066.         !certutil.options[opt_Subject].activated) {
  2067. PR_fprintf(PR_STDERR, 
  2068.            "%s -%c: subject is required to create a cert request.n",
  2069.            progName, commandToRun);
  2070. return -1;
  2071.     }
  2072.     /*  If making a cert, need a serial number.  */
  2073.     if ((certutil.commands[cmd_CreateNewCert].activated ||
  2074.          certutil.commands[cmd_CreateAndAddCert].activated) &&
  2075.          !certutil.options[opt_SerialNumber].activated) {
  2076. /*  Make a default serial number from the current time.  */
  2077. PRTime now = PR_Now();
  2078. serialNumber = LL_L2UI(serialNumber, now);
  2079.     }
  2080.     /*  Validation needs the usage to validate for.  */
  2081.     if (certutil.commands[cmd_CheckCertValidity].activated &&
  2082.         !certutil.options[opt_Usage].activated) {
  2083. PR_fprintf(PR_STDERR, 
  2084.            "%s -V: specify a usage to validate the cert for (-u).n",
  2085.            progName);
  2086. return -1;
  2087.     }
  2088.     
  2089.     /*  To make a cert, need either a issuer or to self-sign it.  */
  2090.     if (certutil.commands[cmd_CreateAndAddCert].activated &&
  2091. !(certutil.options[opt_IssuerName].activated ||
  2092.           certutil.options[opt_SelfSign].activated)) {
  2093. PR_fprintf(PR_STDERR,
  2094.            "%s -S: must specify issuer (-c) or self-sign (-x).n",
  2095.            progName);
  2096. return -1;
  2097.     }
  2098.     /*  Using slotname == NULL for listing keys and certs on all slots, 
  2099.      *  but only that. */
  2100.     if (!(certutil.commands[cmd_ListKeys].activated ||
  2101.        certutil.commands[cmd_ListCerts].activated) && slotname == NULL) {
  2102. PR_fprintf(PR_STDERR,
  2103.            "%s -%c: cannot use "-h all" for this command.n",
  2104.            progName, commandToRun);
  2105. return -1;
  2106.     }
  2107.     /*  Using keytype == nullKey for list all key types, but only that.  */
  2108.     if (!certutil.commands[cmd_ListKeys].activated && keytype == nullKey) {
  2109. PR_fprintf(PR_STDERR,
  2110.            "%s -%c: cannot use "-k all" for this command.n",
  2111.            progName, commandToRun);
  2112. return -1;
  2113.     }
  2114.     /*  -S  open outFile, temporary file for cert request.  */
  2115.     if (certutil.commands[cmd_CreateAndAddCert].activated) {
  2116. outFile = PR_Open(certreqfile, PR_RDWR | PR_CREATE_FILE, 00660);
  2117. if (!outFile) {
  2118.     PR_fprintf(PR_STDERR, "%s -o: unable to open "%s" for writing (%ld, %ld)n",
  2119.                           progName, certreqfile,
  2120.                           PR_GetError(), PR_GetOSError());
  2121.     return -1;
  2122. }
  2123.     }
  2124.     /*  Open the input file.  */
  2125.     if (certutil.options[opt_InputFile].activated) {
  2126. inFile = PR_Open(certutil.options[opt_InputFile].arg, PR_RDONLY, 0);
  2127. if (!inFile) {
  2128.     PR_fprintf(PR_STDERR,
  2129.                "%s:  unable to open "%s" for reading (%ld, %ld).n",
  2130.                progName, certutil.options[opt_InputFile].arg,
  2131.                PR_GetError(), PR_GetOSError());
  2132.     return -1;
  2133. }
  2134.     }
  2135.     /*  Open the output file.  */
  2136.     if (certutil.options[opt_OutputFile].activated && !outFile) {
  2137. outFile = PR_Open(certutil.options[opt_OutputFile].arg, 
  2138.                           PR_CREATE_FILE | PR_RDWR, 00660);
  2139. if (!outFile) {
  2140.     PR_fprintf(PR_STDERR,
  2141.                "%s:  unable to open "%s" for writing (%ld, %ld).n",
  2142.                progName, certutil.options[opt_OutputFile].arg,
  2143.                PR_GetError(), PR_GetOSError());
  2144.     return -1;
  2145. }
  2146.     }
  2147.     name = SECU_GetOptionArg(&certutil, opt_Nickname);
  2148.     PK11_SetPasswordFunc(SECU_GetModulePassword);
  2149.     /*  Initialize NSPR and NSS.  */
  2150.     PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
  2151.     SEC_Init();
  2152.     certHandle = SECU_OpenCertDB(PR_FALSE);
  2153.     if (certHandle == NULL) {
  2154. SECU_PrintError(progName, "unable to open cert database");
  2155. return -1;
  2156.     }
  2157.     CERT_SetDefaultCertDB(certHandle);
  2158.     keyHandle = SECKEY_GetDefaultKeyDB();
  2159.     SECU_PKCS11Init(PR_FALSE);
  2160.     if (PL_strcmp(slotname, "internal") == 0)
  2161. slot = PK11_GetInternalKeySlot();
  2162.     else if (slotname != NULL)
  2163. slot = PK11_FindSlotByName(slotname);
  2164.     /*  If creating new database, initialize the password.  */
  2165.     if (certutil.commands[cmd_NewDBs].activated) {
  2166. SECU_ChangePW(slot, 0, certutil.options[opt_PasswordFile].arg);
  2167.     }
  2168.     /* The following 8 options are mutually exclusive with all others. */
  2169.     /*  List certs (-L)  */
  2170.     if (certutil.commands[cmd_ListCerts].activated) {
  2171. rv = ListCerts(certHandle, name, slot,
  2172.                certutil.options[opt_BinaryDER].activated,
  2173.                certutil.options[opt_ASCIIForIO].activated, 
  2174.                        (outFile) ? outFile : PR_STDOUT,
  2175.        certutil.options[opt_PasswordFile].arg);
  2176. return !rv - 1;
  2177.     }
  2178.     /*  XXX needs work  */
  2179.     /*  List keys (-K)  */
  2180.     if (certutil.commands[cmd_ListKeys].activated) {
  2181. rv = ListKeys(slot, name, 0 /*keyindex*/, keytype, PR_FALSE /*dopriv*/,
  2182.        certutil.options[opt_PasswordFile].arg);
  2183. return !rv - 1;
  2184.     }
  2185.     /*  List modules (-U)  */
  2186.     if (certutil.commands[cmd_ListModules].activated) {
  2187. rv = ListModules();
  2188. return !rv - 1;
  2189.     }
  2190.     /*  Delete cert (-D)  */
  2191.     if (certutil.commands[cmd_DeleteCert].activated) {
  2192. rv = DeleteCert(certHandle, name);
  2193. return !rv - 1;
  2194.     }
  2195.     /*  Delete key (-F)  */
  2196.     if (certutil.commands[cmd_DeleteKey].activated) {
  2197. rv = DeleteKey(keyHandle, name);
  2198. return !rv - 1;
  2199.     }
  2200.     /*  Modify trust attribute for cert (-M)  */
  2201.     if (certutil.commands[cmd_ModifyCertTrust].activated) {
  2202. rv = ChangeTrustAttributes(certHandle, name, 
  2203.                            certutil.options[opt_Trust].arg);
  2204. return !rv - 1;
  2205.     }
  2206.     /*  Change key db password (-W) (future - change pw to slot?)  */
  2207.     if (certutil.commands[cmd_ChangePassword].activated) {
  2208. rv = SECU_ChangePW(slot, 0, certutil.options[opt_PasswordFile].arg);
  2209. return !rv - 1;
  2210.     }
  2211.     /*  Check cert validity against current time (-V)  */
  2212.     if (certutil.commands[cmd_CheckCertValidity].activated) {
  2213. rv = ValidateCert(certHandle, name, 
  2214.                   certutil.options[opt_ValidityTime].arg,
  2215.   certutil.options[opt_Usage].arg,
  2216.   certutil.options[opt_VerifySig].activated,
  2217.   certutil.options[opt_DetailedInfo].activated);
  2218. return !rv - 1;
  2219.     }
  2220.     /*
  2221.      *  Key generation
  2222.      */
  2223.     /*  These commands require keygen.  */
  2224.     if (certutil.commands[cmd_CertReq].activated ||
  2225.         certutil.commands[cmd_CreateAndAddCert].activated ||
  2226. certutil.commands[cmd_GenKeyPair].activated) {
  2227. /*  XXX Give it a nickname.  */
  2228. privkey = 
  2229.     CERTUTIL_GeneratePrivateKey(keytype, slot, keysize,
  2230.                                 publicExponent, 
  2231.                                 certutil.options[opt_NoiseFile].arg,
  2232.                                 &pubkey, 
  2233.                                 certutil.options[opt_PQGFile].arg,
  2234.                                 certutil.options[opt_PasswordFile].arg);
  2235. if (privkey == NULL) {
  2236.     SECU_PrintError(progName, "unable to generate key(s)n");
  2237.     return -1;
  2238. }
  2239. PORT_Assert(pubkey != NULL);
  2240. /*  If all that was needed was keygen, exit.  */
  2241. if (certutil.commands[cmd_GenKeyPair].activated) {
  2242.     return SECSuccess;
  2243. }
  2244.     }
  2245.     /*
  2246.      *  Certificate request
  2247.      */
  2248.     /*  Make a cert request (-R or -S).  */
  2249.     if (certutil.commands[cmd_CreateAndAddCert].activated ||
  2250.          certutil.commands[cmd_CertReq].activated) {
  2251. rv = CertReq(privkey, pubkey, keytype, subject,
  2252.              certutil.options[opt_PhoneNumber].arg,
  2253.              certutil.options[opt_ASCIIForIO].activated,
  2254.      outFile ? outFile : PR_STDOUT);
  2255. if (rv) 
  2256.     return -1;
  2257.     }
  2258.     /*
  2259.      *  Certificate creation
  2260.      */
  2261.     /*  If making and adding a cert, load the cert request file
  2262.      *  and output the cert to another file.
  2263.      */
  2264.     if (certutil.commands[cmd_CreateAndAddCert].activated) {
  2265. PR_Close(outFile);
  2266. inFile  = PR_Open(certreqfile, PR_RDONLY, 0);
  2267. if (!inFile) {
  2268.     PR_fprintf(PR_STDERR, "Failed to open file "%s" (%ld, %ld).n",
  2269.                        certreqfile, PR_GetError(), PR_GetOSError());
  2270.     return -1;
  2271. }
  2272. outFile = PR_Open(certfile, PR_RDWR | PR_CREATE_FILE, 00660);
  2273. if (!outFile) {
  2274.     PR_fprintf(PR_STDERR, "Failed to open file "%s" (%ld, %ld).n",
  2275.                        certfile, PR_GetError(), PR_GetOSError());
  2276.     return -1;
  2277. }
  2278.     }
  2279.     /*  Create a certificate (-C or -S).  */
  2280.     if (certutil.commands[cmd_CreateAndAddCert].activated ||
  2281.          certutil.commands[cmd_CreateNewCert].activated) {
  2282. rv = CreateCert(certHandle, 
  2283.                 certutil.options[opt_IssuerName].arg,
  2284.                 inFile, outFile, privkey, &pwdata,
  2285.                 serialNumber, warpmonths, validitylength,
  2286.                 certutil.options[opt_SelfSign].activated,
  2287.                 certutil.options[opt_AddKeyUsageExt].activated,
  2288.                 certutil.options[opt_AddExtKeyUsageExt].activated,
  2289.                 certutil.options[opt_AddBasicConstraintExt].activated,
  2290.                 certutil.options[opt_AddAuthorityKeyIDExt].activated,
  2291.                 certutil.options[opt_AddCRLDistPtsExt].activated,
  2292.                 certutil.options[opt_AddNSCertTypeExt].activated);
  2293. if (rv) 
  2294.     return -1;
  2295.     }
  2296.     /* 
  2297.      * Adding a cert to the database (or slot)
  2298.      */
  2299.  
  2300.     if (certutil.commands[cmd_CreateAndAddCert].activated) { 
  2301. PR_Close(inFile);
  2302. PR_Close(outFile);
  2303. inFile = PR_Open(certfile, PR_RDONLY, 0);
  2304. if (!inFile) {
  2305.     PR_fprintf(PR_STDERR, "Failed to open file "%s" (%ld, %ld).n",
  2306.                        certfile, PR_GetError(), PR_GetOSError());
  2307.     return -1;
  2308. }
  2309.     }
  2310.     if (certutil.commands[cmd_CreateAndAddCert].activated ||
  2311.          certutil.commands[cmd_AddCert].activated ||
  2312.  certutil.commands[cmd_AddEmailCert].activated) {
  2313. rv = AddCert(slot, certHandle, name, 
  2314.              certutil.options[opt_Trust].arg,
  2315.              inFile, 
  2316.              certutil.options[opt_ASCIIForIO].activated,
  2317.              certutil.commands[cmd_AddEmailCert].activated);
  2318. if (rv) 
  2319.     return -1;
  2320.     }
  2321.     if (certutil.commands[cmd_CreateAndAddCert].activated) {
  2322. PR_Close(inFile);
  2323. PR_Delete(certfile);
  2324. PR_Delete(certreqfile);
  2325.     }
  2326.     if ( certHandle ) {
  2327. CERT_ClosePermCertDB(certHandle);
  2328.     }
  2329.     return rv;  
  2330. }