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

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. /* Cert-O-Matic CGI */
  34. #include "nspr.h"
  35. #include "prtypes.h"
  36. #include "prtime.h"
  37. #include "prlong.h"
  38. #include "pk11func.h"
  39. #include "cert.h"
  40. #include "cdbhdl.h"
  41. #include "cryptohi.h"
  42. #include "secoid.h"
  43. #include "secder.h"
  44. #include "genname.h"
  45. #include "xconst.h"
  46. #include "secutil.h"
  47. #include "pqgutil.h"
  48. #include "certxutl.h"
  49. #include "secrng.h" /* for RNG_ */
  50. /* #define TEST           1 */
  51. /* #define FILEOUT        1 */
  52. /* #define OFFLINE        1 */
  53. #define START_FIELDS   100
  54. #define PREFIX_LEN     6
  55. #define SERIAL_FILE    "../serial"
  56. #define DB_DIRECTORY   ".."
  57. typedef struct PairStr Pair;
  58. struct PairStr {
  59.     char *name;
  60.     char *data;
  61. };
  62. char prefix[PREFIX_LEN];
  63. const SEC_ASN1Template CERTIA5TypeTemplate[] = {
  64.     { SEC_ASN1_IA5_STRING }
  65. };
  66. SECKEYPrivateKey *privkeys[9] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  67.  NULL, NULL};
  68. #ifdef notdef
  69. const SEC_ASN1Template CERT_GeneralNameTemplate[] = {
  70.     { SEC_ASN1_SEQUENCE_OF, 0, SEC_AnyTemplate }
  71. };
  72. #endif
  73. static void
  74. error_out(char  *error_string)
  75. {
  76.     printf("Content-type: text/plainnn");
  77.     printf(error_string);
  78.     fflush(stderr);
  79.     fflush(stdout);
  80.     exit(1);
  81. }
  82. static void
  83. error_allocate(void)
  84. {
  85.     error_out("ERROR: Unable to allocate memory");
  86. }
  87. static char *
  88. make_copy_string(char  *read_pos, 
  89.  int   length, 
  90.  char  sentinal_value)
  91.     /* copys string from to a new string it creates and 
  92.        returns a pointer to the new string */
  93. {
  94.     int                remaining = length;
  95.     char               *write_pos;
  96.     char               *new;
  97.     new = write_pos = (char *) PORT_Alloc (length);
  98.     if (new == NULL) {
  99. error_allocate();
  100.     }
  101.     while (*read_pos != sentinal_value) {
  102. if (remaining == 1) {
  103.     remaining += length;
  104.     length = length * 2;
  105.     new = PORT_Realloc(new,length);
  106.     if (new == NULL) {
  107. error_allocate();
  108.     }
  109.     write_pos = new + length - remaining;
  110. }
  111. *write_pos = *read_pos;
  112. ++write_pos;
  113. ++read_pos;
  114. remaining = remaining - 1;
  115.     }
  116.     *write_pos = '';
  117.     return new;
  118. }
  119. static char *
  120. PasswordStub(PK11SlotInfo  *slot, 
  121.      void          *cx)
  122. {
  123. return NULL;
  124. }
  125. static SECStatus
  126. clean_input(Pair *data)
  127.     /* converts the non-alphanumeric characters in a form post 
  128.        from hex codes back to characters */
  129. {
  130.     int           length;
  131.     int           hi_digit;
  132.     int           low_digit;
  133.     char          character;
  134.     char          *begin_pos;
  135.     char          *read_pos;
  136.     char          *write_pos;
  137.     PRBool        name = PR_TRUE;
  138.     begin_pos = data->name;
  139.     while (begin_pos != NULL) {
  140. length = strlen(begin_pos);
  141. read_pos = write_pos = begin_pos;
  142. while ((read_pos - begin_pos) < length) {
  143.     if (*read_pos == '+') {
  144. *read_pos = ' ';
  145.     }
  146.     if (*read_pos == '%') {
  147. hi_digit = *(read_pos + 1);
  148. low_digit = *(read_pos +2);
  149. read_pos += 3;
  150. if (isdigit(hi_digit)){
  151.     hi_digit = hi_digit - '0';
  152. } else {
  153.     hi_digit = toupper(hi_digit);
  154.     if (isxdigit(hi_digit)) {
  155. hi_digit = (hi_digit - 'A') + 10;
  156.     } else {
  157. error_out("ERROR: Form data incorrectly formated");
  158.     }
  159. }
  160. if (isdigit(low_digit)){
  161.     low_digit = low_digit - '0';
  162. } else {
  163.     low_digit = toupper(low_digit);
  164.     if ((low_digit >='A') && (low_digit <= 'F')) {
  165. low_digit = (low_digit - 'A') + 10;
  166.     } else {
  167. error_out("ERROR: Form data incorrectly formated");
  168.     }
  169. }
  170. character = (hi_digit << 4) | low_digit;
  171. if (character != 10) {
  172.     *write_pos = character;
  173.     ++write_pos;
  174. }
  175.     } else {
  176. *write_pos = *read_pos;
  177. ++write_pos;
  178. ++read_pos;
  179.     }
  180. }
  181. *write_pos = '';
  182. if (name == PR_TRUE) {
  183.     begin_pos = data->data;
  184.     name = PR_FALSE;
  185. } else {
  186.     data++;
  187.     begin_pos = data->name;
  188.     name = PR_TRUE;
  189. }
  190.     }
  191.     return SECSuccess;
  192. }
  193. static char *
  194. make_name(char  *new_data)
  195.     /* gets the next field name in the input string and returns
  196.        a pointer to a string containing a copy of it */
  197. {
  198.     int         length = 20;
  199.     char        *name;
  200.     name = make_copy_string(new_data, length, '=');
  201.     return name;
  202. }
  203. static char *
  204. make_data(char  *new_data)
  205.     /* gets the data for the next field in the input string 
  206.        and returns a pointer to a string containing it */
  207. {
  208.     int         length = 100;
  209.     char        *data;
  210.     char        *read_pos;
  211.     read_pos = new_data;
  212.     while (*(read_pos - 1) != '=') {
  213. ++read_pos;
  214.     }
  215.     data = make_copy_string(read_pos, length, '&');
  216.     return data;
  217. }
  218. static Pair
  219. make_pair(char  *new_data)
  220.     /* makes a pair name/data pair from the input string */
  221. {
  222.     Pair        temp;
  223.     temp.name = make_name(new_data);
  224.     temp.data = make_data(new_data);
  225.     return temp;
  226. }
  227. static Pair *
  228. make_datastruct(char  *data, int len)
  229.     /* parses the input from the form post into a data 
  230.        structure of field name/data pairs */
  231. {
  232.     Pair              *datastruct;
  233.     Pair              *current;
  234.     char              *curr_pos;
  235.     int               fields = START_FIELDS;
  236.     int               remaining = START_FIELDS;
  237.     curr_pos = data;
  238.     datastruct = current = (Pair *) PORT_Alloc(fields * sizeof(Pair));
  239.     if (datastruct == NULL) {
  240. error_allocate();
  241.     }
  242.     while (curr_pos - data < len) {
  243. if (remaining == 1) {
  244.     remaining += fields;
  245.     fields = fields * 2;
  246.     datastruct = (Pair *) PORT_Realloc
  247. (datastruct, fields * sizeof(Pair));
  248.     if (datastruct == NULL) {
  249. error_allocate;
  250.     }
  251.     current = datastruct + (fields - remaining);
  252. }
  253. *current = make_pair(curr_pos);
  254. while (*curr_pos != '&') {
  255.     ++curr_pos;
  256. }
  257. ++curr_pos;
  258. ++current;
  259. remaining = remaining - 1;
  260.     }
  261.     current->name = NULL;
  262.     return datastruct;
  263. }
  264. static char *
  265. return_name(Pair  *data_struct,
  266.     int   n)
  267.     /* returns a pointer to the name of the nth 
  268.        (starting from 0) item in the data structure */
  269. {
  270.     char          *name;
  271.     if ((data_struct + n)->name != NULL) {
  272. name = (data_struct + n)->name;
  273. return name;
  274.     } else {
  275. return NULL;
  276.     }
  277. }
  278. static char *
  279. return_data(Pair  *data_struct,int n)
  280.     /* returns a pointer to the data of the nth (starting from 0) 
  281.        itme in the data structure */
  282. {
  283.     char          *data;
  284.     data = (data_struct + n)->data;
  285.     return data;
  286. }
  287. static char *
  288. add_prefix(char  *field_name)
  289. {
  290.     extern char  prefix[PREFIX_LEN];
  291.     int          i = 0;
  292.     char         *rv;
  293.     char         *write;
  294.     rv = write = PORT_Alloc(PORT_Strlen(prefix) + PORT_Strlen(field_name) + 1);
  295.     for(i = 0; i < PORT_Strlen(prefix); i++) {
  296. *write = prefix[i];
  297. write++;
  298.     }
  299.     *write = '';
  300.     rv = PORT_Strcat(rv,field_name);
  301.     return rv;
  302. }
  303. static char *
  304. find_field(Pair    *data, 
  305.    char    *field_name, 
  306.    PRBool  add_pre)
  307.     /* returns a pointer to the data of the first pair 
  308.        thats name matches the string it is passed */
  309. {
  310.     int            i = 0;
  311.     char           *retrieved;
  312.     int            found = 0;
  313.     if (add_pre) {
  314. field_name = add_prefix(field_name);
  315.     }
  316.     while(return_name(data, i) != NULL) {
  317. if (PORT_Strcmp(return_name(data, i), field_name) == 0) {
  318.     retrieved = return_data(data, i);
  319.     found = 1;
  320.     break;
  321. }
  322. i++;
  323.     }
  324.     if (!found) {
  325. retrieved = NULL;
  326.     }
  327.     return retrieved;
  328. }
  329. static PRBool
  330. find_field_bool(Pair    *data, 
  331. char    *fieldname, 
  332. PRBool  add_pre)
  333. {
  334.     char                *rv;
  335.     rv = find_field(data, fieldname, add_pre);
  336.     if  ((rv != NULL) && (PORT_Strcmp(rv, "true")) == 0) {
  337. return PR_TRUE;
  338.     } else {
  339. return PR_FALSE;
  340.     }
  341. }
  342. static char *
  343. update_data_by_name(Pair  *data, 
  344.     char  *field_name,
  345.                     char  *new_data)
  346.     /* replaces the data in the data structure associated with 
  347.        a name with new data, returns null if not found */
  348. {
  349.     int                   i = 0;
  350.     int                   found = 0;
  351.     int                   length = 100;
  352.     char                  *new;
  353.     while (return_name(data, i) != NULL) {
  354. if (PORT_Strcmp(return_name(data, i), field_name) == 0) {
  355.     new = make_copy_string( new_data, length, '');
  356.     PORT_Free(return_data(data, i));
  357.     found = 1;
  358.     (*(data + i)).data = new;
  359.     break;
  360. }
  361. i++;
  362.     }
  363.     if (!found) {
  364. new = NULL;
  365.     }
  366.     return new;
  367. }
  368. static char *
  369. update_data_by_index(Pair  *data, 
  370.      int   n, 
  371.      char  *new_data)
  372.     /* replaces the data of a particular index in the data structure */
  373. {
  374.     int                    length = 100;
  375.     char                   *new;
  376.     new = make_copy_string(new_data, length, '');
  377.     PORT_Free(return_data(data, n));
  378.     (*(data + n)).data = new;
  379.     return new;
  380. }
  381. static Pair *
  382. add_field(Pair   *data, 
  383.   char*  field_name, 
  384.   char*  field_data)
  385.     /* adds a new name/data pair to the data structure */
  386. {
  387.     int          i = 0;
  388.     int          j;
  389.     int          name_length = 100;
  390.     int          data_length = 100;
  391.     while(return_name(data, i) != NULL) {
  392. i++;
  393.     }
  394.     j = START_FIELDS;
  395.     while ( j < (i + 1) ) {
  396. j = j * 2;
  397.     }
  398.     if (j == (i + 1)) {
  399. data = (Pair *) PORT_Realloc(data, (j * 2) * sizeof(Pair));
  400. if (data == NULL) {
  401.     error_allocate();
  402. }
  403.     }
  404.     (*(data + i)).name = make_copy_string(field_name, name_length, '');
  405.     (*(data + i)).data = make_copy_string(field_data, data_length, '');
  406.     (data + i + 1)->name = NULL;
  407.     return data;
  408. }
  409. static CERTCertificateRequest *
  410. makeCertReq(Pair             *form_data,
  411.     int              which_priv_key)
  412.     /* makes and encodes a certrequest */
  413. {
  414.     PK11SlotInfo             *slot;
  415.     CERTCertificateRequest   *certReq = NULL;
  416.     CERTSubjectPublicKeyInfo *spki;
  417.     SECKEYPrivateKey         *privkey = NULL;
  418.     SECKEYPublicKey          *pubkey = NULL;
  419.     CERTName                 *name;
  420.     char                     *key;
  421.     extern SECKEYPrivateKey  *privkeys[9];
  422.     int                      keySizeInBits;
  423.     char                     *challenge = "foo";
  424.     SECStatus                rv = SECSuccess;
  425.     PQGParams                *pqgParams = NULL;
  426.     PQGVerify                *pqgVfy = NULL;
  427.     name = CERT_AsciiToName(find_field(form_data, "subject", PR_TRUE));
  428.     if (name == NULL) {
  429. error_out("ERROR: Unable to create Subject Name");
  430.     }
  431.     key = find_field(form_data, "key", PR_TRUE);
  432.     if (key == NULL) {
  433. switch (*find_field(form_data, "keysize", PR_TRUE)) {
  434.   case '0':
  435.     keySizeInBits = 2048;
  436.     break;
  437.   case '1':
  438.     keySizeInBits = 1024;
  439.     break;
  440.   case '2':
  441.     keySizeInBits = 512;
  442.     break;
  443.   default:
  444.     error_out("ERROR: Unsupported Key length selected");
  445. }
  446. if (find_field_bool(form_data, "keyType-dsa", PR_TRUE)) {
  447.     rv = PQG_ParamGen(keySizeInBits, &pqgParams, &pqgVfy);
  448.     if (rv != SECSuccess) {
  449. error_out("ERROR: Unable to generate PQG parameters");
  450.     }
  451.     slot = PK11_GetBestSlot(CKM_DSA_KEY_PAIR_GEN, NULL);
  452.     privkey = PK11_GenerateKeyPair(slot, CKM_DSA_KEY_PAIR_GEN, 
  453.    pqgParams,&pubkey, PR_FALSE, 
  454.    PR_TRUE, NULL);
  455. } else {
  456.     privkey = SECKEY_CreateRSAPrivateKey(keySizeInBits, &pubkey, NULL);
  457. }
  458. privkeys[which_priv_key] = privkey;
  459. spki = SECKEY_CreateSubjectPublicKeyInfo(pubkey);
  460.     } else {
  461. spki = SECKEY_ConvertAndDecodePublicKeyAndChallenge(key, challenge, 
  462.     NULL);
  463. if (spki == NULL) {
  464.     error_out("ERROR: Unable to decode Public Key and Challenge String");
  465. }
  466.     }
  467.     certReq = CERT_CreateCertificateRequest(name, spki, NULL);
  468.     if (certReq == NULL) {
  469. error_out("ERROR: Unable to create Certificate Request");
  470.     }
  471.     if (pubkey != NULL) {
  472. SECKEY_DestroyPublicKey(pubkey);
  473.     }
  474.     if (spki != NULL) {
  475. SECKEY_DestroySubjectPublicKeyInfo(spki);
  476.     }
  477.     if (pqgParams != NULL) {
  478. PQG_DestroyParams(pqgParams);
  479.     }
  480.     if (pqgVfy != NULL) {
  481. PQG_DestroyVerify(pqgVfy);
  482.     }
  483.     return certReq;
  484. }
  485. static CERTCertificate *
  486. MakeV1Cert(CERTCertDBHandle        *handle, 
  487.    CERTCertificateRequest  *req,
  488.    char                    *issuerNameStr, 
  489.    PRBool                  selfsign, 
  490.    int                     serialNumber,
  491.    int                     warpmonths,
  492.    Pair                    *data)
  493. {
  494.     CERTCertificate                 *issuerCert = NULL;
  495.     CERTValidity                    *validity;
  496.     CERTCertificate                 *cert = NULL;
  497.     PRExplodedTime                  printableTime;
  498.     PRTime                          now, 
  499.                             after;
  500.     SECStatus rv;
  501.    
  502.     
  503.     if ( !selfsign ) {
  504. issuerCert = CERT_FindCertByNameString(handle, issuerNameStr);
  505. if (!issuerCert) {
  506.     error_out("ERROR: Could not find issuer's certificate");
  507.     return NULL;
  508. }
  509.     }
  510.     if (find_field_bool(data, "manValidity", PR_TRUE)) {
  511. rv = DER_AsciiToTime(&now, find_field(data, "notBefore", PR_TRUE));
  512.     } else {
  513. now = PR_Now();
  514.     }
  515.     PR_ExplodeTime (now, PR_GMTParameters, &printableTime);
  516.     if ( warpmonths ) {
  517. printableTime.tm_month += warpmonths;
  518. now = PR_ImplodeTime (&printableTime);
  519. PR_ExplodeTime (now, PR_GMTParameters, &printableTime);
  520.     }
  521.     if (find_field_bool(data, "manValidity", PR_TRUE)) {
  522. rv = DER_AsciiToTime(&after, find_field(data, "notAfter", PR_TRUE));
  523. PR_ExplodeTime (after, PR_GMTParameters, &printableTime);
  524.     } else {
  525. printableTime.tm_month += 3;
  526. after = PR_ImplodeTime (&printableTime);
  527.     }
  528.     /* note that the time is now in micro-second unit */
  529.     validity = CERT_CreateValidity (now, after);
  530.     if ( selfsign ) {
  531. cert = CERT_CreateCertificate
  532.     (serialNumber,&(req->subject), validity, req);
  533.     } else {
  534. cert = CERT_CreateCertificate
  535.     (serialNumber,&(issuerCert->subject), validity, req);
  536.     }
  537.     
  538.     CERT_DestroyValidity(validity);
  539.     if ( issuerCert ) {
  540. CERT_DestroyCertificate (issuerCert);
  541.     }
  542.     return(cert);
  543. }
  544. static int
  545. get_serial_number(Pair  *data)
  546. {
  547.     int                 serial = 0;
  548.     int                 error;
  549.     char                *filename = SERIAL_FILE;
  550.     char                *SN;
  551.     FILE                *serialFile;
  552.     if (find_field_bool(data, "serial-auto", PR_TRUE)) {
  553. serialFile = fopen(filename, "r");
  554. if (serialFile != NULL) {
  555.     fread(&serial, sizeof(int), 1, serialFile);
  556.     if (ferror(serialFile) != 0) {
  557. error_out("Error: Unable to read serial number file");
  558.     }
  559.     if (serial == 4294967295) {
  560. serial = 21;
  561.     }
  562.     fclose(serialFile);
  563.     ++serial;
  564.     serialFile = fopen(filename,"w");
  565.     if (serialFile == NULL) {
  566.         error_out("ERROR: Unable to open serial number file for writing");
  567.     }
  568.     fwrite(&serial, sizeof(int), 1, serialFile);
  569.     if (ferror(serialFile) != 0) {
  570. error_out("Error: Unable to write to serial number file");
  571.     }
  572. } else {
  573.     fclose(serialFile);
  574.     serialFile = fopen(filename,"w");
  575.     if (serialFile == NULL) {
  576. error_out("ERROR: Unable to open serial number file");
  577.     }
  578.     serial = 21;
  579.     fwrite(&serial, sizeof(int), 1, serialFile);
  580.     if (ferror(serialFile) != 0) {
  581. error_out("Error: Unable to write to serial number file");
  582.     }
  583.     error = ferror(serialFile);
  584.     if (error != 0) {
  585. error_out("ERROR: Unable to write to serial file");
  586.     }
  587. }
  588. fclose(serialFile);
  589.     } else {
  590. SN = find_field(data, "serial_value", PR_TRUE);
  591. while (*SN != '') {
  592.     serial = serial * 16;
  593.     if ((*SN >= 'A') && (*SN <='F')) {
  594. serial += *SN - 'A' + 10; 
  595.     } else {
  596. if ((*SN >= 'a') && (*SN <='f')) {
  597.     serial += *SN - 'a' + 10;
  598. } else {
  599.     serial += *SN - '0';
  600. }
  601.     }
  602.     ++SN;
  603. }
  604.     }
  605.     return serial;
  606. }
  607.        
  608. static CERTCertDBHandle
  609. *OpenCertDB(void)
  610.   /* NOTE: This routine has been modified to allow the libsec/pcertdb.c
  611.    * routines to automatically find and convert the old cert database
  612.    * into the new v3.0 format (cert db version 5).
  613.    */
  614. {
  615.     CERTCertDBHandle  *certHandle;
  616.     SECStatus         rv;
  617.     /* Allocate a handle to fill with CERT_OpenCertDB below */
  618.     certHandle = (CERTCertDBHandle *)PORT_ZAlloc(sizeof(CERTCertDBHandle));
  619.     if (!certHandle) {
  620. error_out("ERROR: unable to get database handle");
  621. return NULL;
  622.     }
  623.     rv = CERT_OpenCertDB(certHandle, PR_FALSE, SECU_CertDBNameCallback, NULL);
  624.     if (rv) {
  625. error_out("ERROR: Could not open certificate database");
  626. if (certHandle) free (certHandle);  /* we don't want to leave 
  627.        anything behind... */
  628. return NULL;
  629.     } else {
  630. CERT_SetDefaultCertDB(certHandle);
  631.     }
  632.     return certHandle;
  633. }
  634. typedef SECStatus (* EXTEN_VALUE_ENCODER)
  635. (PRArenaPool *extHandle, void *value, SECItem *encodedValue);
  636. static SECStatus 
  637. EncodeAndAddExtensionValue(
  638. PRArenaPool          *arena, 
  639. void                 *extHandle, 
  640. void                 *value, 
  641. PRBool       criticality,
  642. int       extenType, 
  643. EXTEN_VALUE_ENCODER  EncodeValueFn)
  644. {
  645.     SECItem                  encodedValue;
  646.     SECStatus                rv;
  647.     encodedValue.data = NULL;
  648.     encodedValue.len = 0;
  649.     rv = (*EncodeValueFn)(arena, value, &encodedValue);
  650.     if (rv != SECSuccess) {
  651. error_out("ERROR: Unable to encode extension value");
  652.     }
  653.     rv = CERT_AddExtension
  654. (extHandle, extenType, &encodedValue, criticality, PR_TRUE);
  655.     return (rv);
  656. }
  657. static SECStatus 
  658. AddKeyUsage (void  *extHandle, 
  659.      Pair  *data)
  660. {
  661.     SECItem        bitStringValue;
  662.     unsigned char  keyUsage = 0x0;
  663.     if (find_field_bool(data,"keyUsage-digitalSignature", PR_TRUE)){
  664. keyUsage |= (0x80 >> 0);
  665.     }
  666.     if (find_field_bool(data,"keyUsage-nonRepudiation", PR_TRUE)){
  667. keyUsage |= (0x80 >> 1);
  668.     }
  669.     if (find_field_bool(data,"keyUsage-keyEncipherment", PR_TRUE)){
  670. keyUsage |= (0x80 >> 2);
  671.     }
  672.     if (find_field_bool(data,"keyUsage-dataEncipherment", PR_TRUE)){
  673. keyUsage |= (0x80 >> 3);
  674.     }
  675.     if (find_field_bool(data,"keyUsage-keyAgreement", PR_TRUE)){
  676. keyUsage |= (0x80 >> 4);
  677.     }
  678.     if (find_field_bool(data,"keyUsage-keyCertSign", PR_TRUE)) {
  679. keyUsage |= (0x80 >> 5);
  680.     }
  681.     if (find_field_bool(data,"keyUsage-cRLSign", PR_TRUE)) {
  682. keyUsage |= (0x80 >> 6);
  683.     }
  684.     bitStringValue.data = &keyUsage;
  685.     bitStringValue.len = 1;
  686.     return (CERT_EncodeAndAddBitStrExtension
  687.     (extHandle, SEC_OID_X509_KEY_USAGE, &bitStringValue,
  688.      (find_field_bool(data, "keyUsage-crit", PR_TRUE))));
  689. }
  690. static CERTOidSequence *
  691. CreateOidSequence(void)
  692. {
  693.   CERTOidSequence *rv = (CERTOidSequence *)NULL;
  694.   PRArenaPool *arena = (PRArenaPool *)NULL;
  695.   arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  696.   if( (PRArenaPool *)NULL == arena ) {
  697.     goto loser;
  698.   }
  699.   rv = (CERTOidSequence *)PORT_ArenaZAlloc(arena, sizeof(CERTOidSequence));
  700.   if( (CERTOidSequence *)NULL == rv ) {
  701.     goto loser;
  702.   }
  703.   rv->oids = (SECItem **)PORT_ArenaZAlloc(arena, sizeof(SECItem *));
  704.   if( (SECItem **)NULL == rv->oids ) {
  705.     goto loser;
  706.   }
  707.   rv->arena = arena;
  708.   return rv;
  709.  loser:
  710.   if( (PRArenaPool *)NULL != arena ) {
  711.     PORT_FreeArena(arena, PR_FALSE);
  712.   }
  713.   return (CERTOidSequence *)NULL;
  714. }
  715. static SECStatus
  716. AddOidToSequence(CERTOidSequence *os, SECOidTag oidTag)
  717. {
  718.   SECItem **oids;
  719.   PRUint32 count = 0;
  720.   SECOidData *od;
  721.   od = SECOID_FindOIDByTag(oidTag);
  722.   if( (SECOidData *)NULL == od ) {
  723.     return SECFailure;
  724.   }
  725.   for( oids = os->oids; (SECItem *)NULL != *oids; oids++ ) {
  726.     count++;
  727.   }
  728.   /* ArenaZRealloc */
  729.   {
  730.     PRUint32 i;
  731.     oids = (SECItem **)PORT_ArenaZAlloc(os->arena, sizeof(SECItem *) * (count+2));
  732.     if( (SECItem **)NULL == oids ) {
  733.       return SECFailure;
  734.     }
  735.     
  736.     for( i = 0; i < count; i++ ) {
  737.       oids[i] = os->oids[i];
  738.     }
  739.     /* ArenaZFree(os->oids); */
  740.   }
  741.   os->oids = oids;
  742.   os->oids[count] = &od->oid;
  743.   return SECSuccess;
  744. }
  745. static SECItem *
  746. EncodeOidSequence(CERTOidSequence *os)
  747. {
  748.   SECItem *rv;
  749.   extern const SEC_ASN1Template CERT_OidSeqTemplate[];
  750.   rv = (SECItem *)PORT_ArenaZAlloc(os->arena, sizeof(SECItem));
  751.   if( (SECItem *)NULL == rv ) {
  752.     goto loser;
  753.   }
  754.   if( !SEC_ASN1EncodeItem(os->arena, rv, os, CERT_OidSeqTemplate) ) {
  755.     goto loser;
  756.   }
  757.   return rv;
  758.  loser:
  759.   return (SECItem *)NULL;
  760. }
  761. static SECStatus
  762. AddExtKeyUsage(void *extHandle, Pair *data)
  763. {
  764.   SECStatus rv;
  765.   CERTOidSequence *os;
  766.   SECItem *value;
  767.   PRBool crit;
  768.   os = CreateOidSequence();
  769.   if( (CERTOidSequence *)NULL == os ) {
  770.     return SECFailure;
  771.   }
  772.   if( find_field_bool(data, "extKeyUsage-serverAuth", PR_TRUE) ) {
  773.     rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_SERVER_AUTH);
  774.     if( SECSuccess != rv ) goto loser;
  775.   }
  776.   if( find_field_bool(data, "extKeyUsage-clientAuth", PR_TRUE) ) {
  777.     rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH);
  778.     if( SECSuccess != rv ) goto loser;
  779.   }
  780.   if( find_field_bool(data, "extKeyUsage-codeSign", PR_TRUE) ) {
  781.     rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_CODE_SIGN);
  782.     if( SECSuccess != rv ) goto loser;
  783.   }
  784.   if( find_field_bool(data, "extKeyUsage-emailProtect", PR_TRUE) ) {
  785.     rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT);
  786.     if( SECSuccess != rv ) goto loser;
  787.   }
  788.   if( find_field_bool(data, "extKeyUsage-timeStamp", PR_TRUE) ) {
  789.     rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_TIME_STAMP);
  790.     if( SECSuccess != rv ) goto loser;
  791.   }
  792.   if( find_field_bool(data, "extKeyUsage-ocspResponder", PR_TRUE) ) {
  793.     rv = AddOidToSequence(os, SEC_OID_OCSP_RESPONDER);
  794.     if( SECSuccess != rv ) goto loser;
  795.   }
  796.   if( find_field_bool(data, "extKeyUsage-NS-govtApproved", PR_TRUE) ) {
  797.     rv = AddOidToSequence(os, SEC_OID_NS_KEY_USAGE_GOVT_APPROVED);
  798.     if( SECSuccess != rv ) goto loser;
  799.   }
  800.   value = EncodeOidSequence(os);
  801.   crit = find_field_bool(data, "extKeyUsage-crit", PR_TRUE);
  802.   rv = CERT_AddExtension(extHandle, SEC_OID_X509_EXT_KEY_USAGE, value,
  803.                          crit, PR_TRUE);
  804.   /*FALLTHROUGH*/
  805.  loser:
  806.   CERT_DestroyOidSequence(os);
  807.   return rv;
  808. }
  809. static SECStatus
  810. AddSubKeyID(void             *extHandle, 
  811.     Pair             *data, 
  812.     CERTCertificate  *subjectCert)
  813. {
  814.     SECItem                  encodedValue;
  815.     SECStatus                rv;
  816.     char                     *read;
  817.     char                     *write;
  818.     char                     *first;
  819.     char                     character;
  820.     int                      high_digit = 0,
  821.                      low_digit = 0;
  822.     int                      len;
  823.     PRBool                   odd = PR_FALSE;
  824.     encodedValue.data = NULL;
  825.     encodedValue.len = 0;
  826.     first = read = write = find_field(data,"subjectKeyIdentifier-text", 
  827.       PR_TRUE);
  828.     len = PORT_Strlen(first);
  829.     odd = ((len % 2) != 0 ) ? PR_TRUE : PR_FALSE;
  830.     if (find_field_bool(data, "subjectKeyIdentifier-radio-hex", PR_TRUE)) {
  831. if (odd) {
  832.     error_out("ERROR: Improperly formated subject key identifier, hex values must be expressed as an octet string");
  833. }
  834. while (*read != '') {
  835.     if (!isxdigit(*read)) {
  836. error_out("ERROR: Improperly formated subject key identifier");
  837.     }
  838.     *read = toupper(*read);
  839.     if ((*read >= 'A') && (*read <= 'F')) {
  840. high_digit = *read - 'A' + 10;
  841.     }  else {
  842. high_digit = *read - '0';
  843.     }
  844.     ++read;
  845.     if (!isxdigit(*read)) {
  846. error_out("ERROR: Improperly formated subject key identifier");
  847.     }
  848.     *read = toupper(*read);
  849.     if ((*read >= 'A') && (*read <= 'F')) {
  850. low_digit = *(read) - 'A' + 10;
  851.     } else {
  852. low_digit = *(read) - '0';
  853.     }
  854.     character = (high_digit << 4) | low_digit;
  855.     *write = character;
  856.     ++write;
  857.     ++read;
  858. }
  859. *write = '';
  860. len = write - first;
  861.     }
  862.     subjectCert->subjectKeyID.data = (unsigned char *) find_field
  863. (data,"subjectKeyIdentifier-text", PR_TRUE);
  864.     subjectCert->subjectKeyID.len = len;
  865.     rv = CERT_EncodeSubjectKeyID
  866. (NULL, find_field(data,"subjectKeyIdentifier-text", PR_TRUE),
  867.  len, &encodedValue);
  868.     if (rv) {
  869. return (rv);
  870.     }
  871.     return (CERT_AddExtension(extHandle,  SEC_OID_X509_SUBJECT_KEY_ID, 
  872.       &encodedValue, PR_FALSE, PR_TRUE));
  873. }
  874. static SECStatus 
  875. AddAuthKeyID (void              *extHandle,
  876.       Pair              *data, 
  877.       char              *issuerNameStr, 
  878.       CERTCertDBHandle  *handle)
  879. {
  880.     CERTAuthKeyID               *authKeyID = NULL;    
  881.     PRArenaPool                 *arena = NULL;
  882.     SECStatus                   rv = SECSuccess;
  883.     CERTCertificate             *issuerCert = NULL;
  884.     CERTGeneralName             *genNames;
  885.     CERTName                    *directoryName = NULL;
  886.     issuerCert = CERT_FindCertByNameString(handle, issuerNameStr);
  887.     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  888.     if ( !arena ) {
  889. error_allocate();
  890.     }
  891.     authKeyID = PORT_ArenaZAlloc (arena, sizeof (CERTAuthKeyID));
  892.     if (authKeyID == NULL) {
  893. error_allocate();
  894.     }
  895.     if (find_field_bool(data, "authorityKeyIdentifier-radio-keyIdentifier", 
  896. PR_TRUE)) {
  897. authKeyID->keyID.data = PORT_ArenaAlloc (arena, PORT_Strlen 
  898.        ((char *)issuerCert->subjectKeyID.data));
  899. if (authKeyID->keyID.data == NULL) {
  900.     error_allocate();
  901. }
  902. PORT_Memcpy (authKeyID->keyID.data, issuerCert->subjectKeyID.data, 
  903.      authKeyID->keyID.len = 
  904.         PORT_Strlen((char *)issuerCert->subjectKeyID.data));
  905.     } else {
  906. PORT_Assert (arena);
  907. genNames = (CERTGeneralName *) PORT_ArenaZAlloc (arena, (sizeof(CERTGeneralName)));
  908. if (genNames == NULL){
  909.     error_allocate();
  910. }
  911. genNames->l.next = genNames->l.prev = &(genNames->l);
  912. genNames->type = certDirectoryName;
  913. directoryName = CERT_AsciiToName(issuerCert->subjectName);
  914. if (!directoryName) {
  915.     error_out("ERROR: Unable to create Directory Name");
  916. }
  917. rv = CERT_CopyName (arena, &genNames->name.directoryName, 
  918.     directoryName);
  919.         CERT_DestroyName (directoryName);
  920. if (rv != SECSuccess) {
  921.     error_out("ERROR: Unable to copy Directory Name");
  922. }
  923. authKeyID->authCertIssuer = genNames;
  924. if (authKeyID->authCertIssuer == NULL && SECFailure == 
  925.                                             PORT_GetError ()) {
  926.     error_out("ERROR: Unable to get Issuer General Name for Authority Key ID Extension");
  927. }
  928. authKeyID->authCertSerialNumber = issuerCert->serialNumber;
  929.     }
  930.     rv = EncodeAndAddExtensionValue(arena, extHandle, authKeyID, PR_FALSE, 
  931.     SEC_OID_X509_AUTH_KEY_ID, 
  932.     (EXTEN_VALUE_ENCODER)
  933.     CERT_EncodeAuthKeyID);
  934.     if (arena) {
  935. PORT_FreeArena (arena, PR_FALSE);
  936.     }
  937.     return (rv);
  938. }
  939. static SECStatus 
  940. AddPrivKeyUsagePeriod(void             *extHandle, 
  941.       Pair             *data, 
  942.       CERTCertificate  *cert)
  943. {
  944.     char *notBeforeStr;
  945.     char *notAfterStr;
  946.     PRArenaPool *arena = NULL;
  947.     SECStatus rv = SECSuccess;
  948.     PKUPEncodedContext *pkup;
  949.     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  950.     if ( !arena ) {
  951. error_allocate();
  952.     }
  953.     pkup = PORT_ArenaZAlloc (arena, sizeof (PKUPEncodedContext));
  954.     if (pkup == NULL) {
  955. error_allocate();
  956.     }
  957.     notBeforeStr = (char *) PORT_Alloc(16 * sizeof(char));
  958.     notAfterStr = (char *) PORT_Alloc(16 * sizeof(char));
  959.     *notBeforeStr = '';
  960.     *notAfterStr = '';
  961.     pkup->arena = arena;
  962.     pkup->notBefore.len = 0;
  963.     pkup->notBefore.data = NULL;
  964.     pkup->notAfter.len = 0;
  965.     pkup->notAfter.data = NULL;
  966.     if (find_field_bool(data, "privKeyUsagePeriod-radio-notBefore", PR_TRUE) ||
  967. find_field_bool(data, "privKeyUsagePeriod-radio-both", PR_TRUE)) {
  968. pkup->notBefore.len = 15;
  969. pkup->notBefore.data = (unsigned char *)notBeforeStr;
  970. if (find_field_bool(data, "privKeyUsagePeriod-notBefore-radio-manual", 
  971.     PR_TRUE)) {
  972.     PORT_Strcat(notBeforeStr,find_field(data,
  973.    "privKeyUsagePeriod-notBefore-year",
  974.    PR_TRUE));
  975.     PORT_Strcat(notBeforeStr,find_field(data,
  976.    "privKeyUsagePeriod-notBefore-month",
  977.    PR_TRUE));
  978.     PORT_Strcat(notBeforeStr,find_field(data,
  979.    "privKeyUsagePeriod-notBefore-day",
  980.    PR_TRUE));
  981.     PORT_Strcat(notBeforeStr,find_field(data,
  982.    "privKeyUsagePeriod-notBefore-hour",
  983.    PR_TRUE));
  984.     PORT_Strcat(notBeforeStr,find_field(data,
  985.   "privKeyUsagePeriod-notBefore-minute",
  986.    PR_TRUE));
  987.     PORT_Strcat(notBeforeStr,find_field(data,
  988.   "privKeyUsagePeriod-notBefore-second",
  989.    PR_TRUE));
  990.     if ((*(notBeforeStr + 14) != '') ||
  991. (!isdigit(*(notBeforeStr + 13))) ||
  992. (*(notBeforeStr + 12) >= '5' && *(notBeforeStr + 12) <= '0') ||
  993. (!isdigit(*(notBeforeStr + 11))) ||
  994. (*(notBeforeStr + 10) >= '5' && *(notBeforeStr + 10) <= '0') ||
  995. (!isdigit(*(notBeforeStr + 9))) ||
  996. (*(notBeforeStr + 8) >= '2' && *(notBeforeStr + 8) <= '0') ||
  997. (!isdigit(*(notBeforeStr + 7))) ||
  998. (*(notBeforeStr + 6) >= '3' && *(notBeforeStr + 6) <= '0') ||
  999. (!isdigit(*(notBeforeStr + 5))) ||
  1000. (*(notBeforeStr + 4) >= '1' && *(notBeforeStr + 4) <= '0') ||
  1001. (!isdigit(*(notBeforeStr + 3))) ||
  1002. (!isdigit(*(notBeforeStr + 2))) ||
  1003. (!isdigit(*(notBeforeStr + 1))) ||
  1004. (!isdigit(*(notBeforeStr + 0))) ||
  1005. (*(notBeforeStr + 8) == '2' && *(notBeforeStr + 9) >= '4') ||
  1006. (*(notBeforeStr + 6) == '3' && *(notBeforeStr + 7) >= '1') ||
  1007. (*(notBeforeStr + 4) == '1' && *(notBeforeStr + 5) >= '2')) {
  1008. error_out("ERROR: Improperly formated private key usage period");
  1009.     }
  1010.     *(notBeforeStr + 14) = 'Z';
  1011.     *(notBeforeStr + 15) = '';
  1012. } else {
  1013.     if ((*(cert->validity.notBefore.data) > '5') || 
  1014. ((*(cert->validity.notBefore.data) == '5') &&
  1015.  (*(cert->validity.notBefore.data + 1) != '0'))) {
  1016. PORT_Strcat(notBeforeStr, "19");
  1017.     } else {
  1018. PORT_Strcat(notBeforeStr, "20");
  1019.     }
  1020.     PORT_Strcat(notBeforeStr, (char *)cert->validity.notBefore.data);
  1021. }
  1022.     }
  1023.     if (find_field_bool(data, "privKeyUsagePeriod-radio-notAfter", PR_TRUE) ||
  1024. find_field_bool(data, "privKeyUsagePeriod-radio-both", PR_TRUE)) {
  1025. pkup->notAfter.len = 15;
  1026. pkup->notAfter.data = (unsigned char *)notAfterStr;
  1027. PORT_Strcat(notAfterStr,find_field(data,"privKeyUsagePeriod-notAfter-year", 
  1028.       PR_TRUE));
  1029. PORT_Strcat(notAfterStr,find_field(data,"privKeyUsagePeriod-notAfter-month",
  1030.       PR_TRUE));
  1031. PORT_Strcat(notAfterStr,find_field(data,"privKeyUsagePeriod-notAfter-day", 
  1032.       PR_TRUE));
  1033. PORT_Strcat(notAfterStr,find_field(data,"privKeyUsagePeriod-notAfter-hour", 
  1034.       PR_TRUE));
  1035. PORT_Strcat(notAfterStr,find_field(data,"privKeyUsagePeriod-notAfter-minute",
  1036.       PR_TRUE));
  1037. PORT_Strcat(notAfterStr,find_field(data,"privKeyUsagePeriod-notAfter-second",
  1038.       PR_TRUE));
  1039. if ((*(notAfterStr + 14) != '') ||
  1040.     (!isdigit(*(notAfterStr + 13))) ||
  1041.     (*(notAfterStr + 12) >= '5' && *(notAfterStr + 12) <= '0') ||
  1042.     (!isdigit(*(notAfterStr + 11))) ||
  1043.     (*(notAfterStr + 10) >= '5' && *(notAfterStr + 10) <= '0') ||
  1044.     (!isdigit(*(notAfterStr + 9))) ||
  1045.     (*(notAfterStr + 8) >= '2' && *(notAfterStr + 8) <= '0') ||
  1046.     (!isdigit(*(notAfterStr + 7))) ||
  1047.     (*(notAfterStr + 6) >= '3' && *(notAfterStr + 6) <= '0') ||
  1048.     (!isdigit(*(notAfterStr + 5))) ||
  1049.     (*(notAfterStr + 4) >= '1' && *(notAfterStr + 4) <= '0') ||
  1050.     (!isdigit(*(notAfterStr + 3))) ||
  1051.     (!isdigit(*(notAfterStr + 2))) ||
  1052.     (!isdigit(*(notAfterStr + 1))) ||
  1053.     (!isdigit(*(notAfterStr + 0))) ||
  1054.     (*(notAfterStr + 8) == '2' && *(notAfterStr + 9) >= '4') ||
  1055.     (*(notAfterStr + 6) == '3' && *(notAfterStr + 7) >= '1') ||
  1056.     (*(notAfterStr + 4) == '1' && *(notAfterStr + 5) >= '2')) {
  1057.     error_out("ERROR: Improperly formated private key usage period");
  1058. }
  1059. *(notAfterStr + 14) = 'Z';
  1060. *(notAfterStr + 15) = '';
  1061.     }
  1062.     PORT_Assert (arena);
  1063.     rv = EncodeAndAddExtensionValue(arena, extHandle, pkup, 
  1064.     find_field_bool(data,
  1065.     "privKeyUsagePeriod-crit", 
  1066.     PR_TRUE), 
  1067.     SEC_OID_X509_PRIVATE_KEY_USAGE_PERIOD, 
  1068.     (EXTEN_VALUE_ENCODER)
  1069.     CERT_EncodePublicKeyUsagePeriod);
  1070.     if (arena) {
  1071. PORT_FreeArena (arena, PR_FALSE);
  1072.     }
  1073.     if (notBeforeStr != NULL) {
  1074. PORT_Free(notBeforeStr);
  1075.     }
  1076.     if (notAfterStr != NULL) {
  1077. PORT_Free(notAfterStr);
  1078.     }
  1079.     return (rv);
  1080. }    
  1081. static SECStatus 
  1082. AddBasicConstraint(void   *extHandle, 
  1083.    Pair   *data)
  1084. {
  1085.     CERTBasicConstraints  basicConstraint;
  1086.     SECItem               encodedValue;
  1087.     SECStatus             rv;
  1088.     encodedValue.data = NULL;
  1089.     encodedValue.len = 0;
  1090.     basicConstraint.pathLenConstraint = CERT_UNLIMITED_PATH_CONSTRAINT;
  1091.     basicConstraint.isCA = (find_field_bool(data,"basicConstraints-cA-radio-CA",
  1092.     PR_TRUE));
  1093.     if (find_field_bool(data,"basicConstraints-pathLengthConstraint", PR_TRUE)){
  1094. basicConstraint.pathLenConstraint = atoi 
  1095.     (find_field(data,"basicConstraints-pathLengthConstraint-text", 
  1096. PR_TRUE));
  1097.     }
  1098.     
  1099.     rv = CERT_EncodeBasicConstraintValue (NULL, &basicConstraint, 
  1100.   &encodedValue);
  1101.     if (rv)
  1102. return (rv);
  1103.     rv = CERT_AddExtension(extHandle, SEC_OID_X509_BASIC_CONSTRAINTS, 
  1104.    &encodedValue, 
  1105.    (find_field_bool(data,"basicConstraints-crit", 
  1106.     PR_TRUE)), PR_TRUE);
  1107.     PORT_Free (encodedValue.data);
  1108.     return (rv);
  1109. }
  1110. static SECStatus 
  1111. AddNscpCertType (void  *extHandle, 
  1112.  Pair  *data)
  1113. {
  1114.     SECItem            bitStringValue;
  1115.     unsigned char      CertType = 0x0;
  1116.     if (find_field_bool(data,"netscape-cert-type-ssl-client", PR_TRUE)){
  1117. CertType |= (0x80 >> 0);
  1118.     }
  1119.     if (find_field_bool(data,"netscape-cert-type-ssl-server", PR_TRUE)){
  1120. CertType |= (0x80 >> 1);
  1121.     }
  1122.     if (find_field_bool(data,"netscape-cert-type-smime", PR_TRUE)){
  1123. CertType |= (0x80 >> 2);
  1124.     }
  1125.     if (find_field_bool(data,"netscape-cert-type-object-signing", PR_TRUE)){
  1126. CertType |= (0x80 >> 3);
  1127.     }
  1128.     if (find_field_bool(data,"netscape-cert-type-reserved", PR_TRUE)){
  1129. CertType |= (0x80 >> 4);
  1130.     }
  1131.     if (find_field_bool(data,"netscape-cert-type-ssl-ca", PR_TRUE)) {
  1132. CertType |= (0x80 >> 5);
  1133.     }
  1134.     if (find_field_bool(data,"netscape-cert-type-smime-ca", PR_TRUE)) {
  1135. CertType |= (0x80 >> 6);
  1136.     }
  1137.     if (find_field_bool(data,"netscape-cert-type-object-signing-ca", PR_TRUE)) {
  1138. CertType |= (0x80 >> 7);
  1139.     }
  1140.     bitStringValue.data = &CertType;
  1141.     bitStringValue.len = 1;
  1142.     return (CERT_EncodeAndAddBitStrExtension
  1143.     (extHandle, SEC_OID_NS_CERT_EXT_CERT_TYPE, &bitStringValue,
  1144.      (find_field_bool(data, "netscape-cert-type-crit", PR_TRUE))));
  1145. }
  1146. static SECStatus
  1147. add_IA5StringExtension(void    *extHandle, 
  1148.        char    *string, 
  1149.        PRBool  crit, 
  1150.        int     idtag)
  1151. {
  1152.     SECItem                    encodedValue;
  1153.     SECStatus                  rv;
  1154.     encodedValue.data = NULL;
  1155.     encodedValue.len = 0;
  1156.     rv = CERT_EncodeIA5TypeExtension(NULL, string, &encodedValue);
  1157.     if (rv) {
  1158. return (rv);
  1159.     }
  1160.     return (CERT_AddExtension(extHandle, idtag, &encodedValue, crit, PR_TRUE));
  1161. }
  1162. static SECItem *
  1163. string_to_oid(char  *string)
  1164. {
  1165.     int             i;
  1166.     int             length = 20;
  1167.     int             remaining;
  1168.     int             first_value;
  1169.     int             second_value;
  1170.     int             value;
  1171.     int             oidLength;
  1172.     unsigned char   *oidString;
  1173.     unsigned char   *write;
  1174.     unsigned char   *read;
  1175.     unsigned char   *temp;
  1176.     SECItem         *oid;
  1177.     
  1178.     
  1179.     remaining = length;
  1180.     i = 0;
  1181.     while (*string == ' ') {
  1182. string++;
  1183.     }
  1184.     while (isdigit(*(string + i))) {
  1185. i++;
  1186.     }
  1187.     if (*(string + i) == '.') {
  1188. *(string + i) = '';
  1189.     } else {
  1190. error_out("ERROR: Improperly formated OID");
  1191.     }
  1192.     first_value = atoi(string);
  1193.     if (first_value < 0 || first_value > 2) {
  1194. error_out("ERROR: Improperly formated OID");
  1195.     }
  1196.     string += i + 1;
  1197.     i = 0;
  1198.     while (isdigit(*(string + i))) {
  1199. i++;
  1200.     }
  1201.     if (*(string + i) == '.') {
  1202. *(string + i) = '';
  1203.     } else {
  1204. error_out("ERROR: Improperly formated OID");
  1205.     }
  1206.     second_value = atoi(string);
  1207.     if (second_value < 0 || second_value > 39) {
  1208. error_out("ERROR: Improperly formated OID");
  1209.     }
  1210.     oidString = PORT_ZAlloc(2);
  1211.     *oidString = (first_value * 40) + second_value;
  1212.     *(oidString + 1) = '';
  1213.     oidLength = 1;
  1214.     string += i + 1;
  1215.     i = 0;
  1216.     temp = write = PORT_ZAlloc(length);
  1217.     while (*string != '') {
  1218. value = 0;
  1219. while(isdigit(*(string + i))) {
  1220.     i++;
  1221. }
  1222. if (*(string + i) == '') {
  1223.     value = atoi(string);
  1224.     string += i;
  1225. } else {
  1226.     if (*(string + i) == '.') {
  1227. *(string + i) == '';
  1228. value = atoi(string);
  1229. string += i + 1;
  1230.     } else {
  1231. *(string + i) = '';
  1232. i++;
  1233. value = atoi(string);
  1234. if (*(string + i) == ' ') {
  1235.     while (*(string + i) == ' ')
  1236. i++;
  1237. }
  1238. if (*(string + i) != '') {
  1239.     error_out("ERROR: Improperly formated OID");
  1240. }
  1241.     }
  1242. }
  1243. i = 0;
  1244. while (value != 0) {
  1245.     if (remaining < 1) {
  1246. remaining += length;
  1247. length = length * 2;
  1248. temp = PORT_Realloc(temp, length);
  1249. write = temp + length - remaining;
  1250.     }
  1251.     *write = (value & 0x7f) | (0x80);
  1252.     write++;
  1253.     remaining--;
  1254.     value = value >> 7;
  1255. }
  1256. *temp = *temp & (0x7f);
  1257. oidLength += write - temp;
  1258. oidString = PORT_Realloc(oidString, (oidLength + 1));
  1259. read = write - 1;
  1260. write = oidLength + oidString - 1;
  1261. for (i = 0; i < (length - remaining); i++) {
  1262.     *write = *read;
  1263.     write--;
  1264.     read++;
  1265. }
  1266. write = temp;
  1267. remaining = length;
  1268.     }
  1269.     *(oidString + oidLength) = '';
  1270.     oid = (SECItem *) PORT_ZAlloc(sizeof(SECItem));
  1271.     oid->data = oidString;
  1272.     oid->len  = oidLength;
  1273.     PORT_Free(temp);
  1274.     return oid;
  1275. }
  1276. static SECItem *
  1277. string_to_ipaddress(char *string)
  1278. {
  1279.     int      i = 0;
  1280.     int      value;
  1281.     int      j = 0;
  1282.     SECItem  *ipaddress;
  1283.     
  1284.     while (*string == ' ') {
  1285. string++;
  1286.     }
  1287.     ipaddress = (SECItem *) PORT_ZAlloc(sizeof(SECItem));
  1288.     ipaddress->data = PORT_ZAlloc(9);
  1289.     while (*string != '' && j < 8) {
  1290. while (isdigit(*(string + i))) {
  1291.     i++;
  1292. }
  1293. if (*(string + i) == '.') {
  1294.     *(string + i) = '';
  1295.     value = atoi(string);
  1296.     string = string + i + 1;
  1297.     i = 0;
  1298. } else {
  1299.     if (*(string + i) == '') {
  1300. value = atoi(string);
  1301. string = string + i;
  1302. i = 0;
  1303.     } else {
  1304. *(string + i) = '';
  1305. while (*(string + i) == ' ') {
  1306.     i++;
  1307. }
  1308. if (*(string + i) == '') {
  1309.     value = atoi(string);
  1310.     string = string + i;
  1311.     i = 0;
  1312. } else {
  1313.     error_out("ERROR: Improperly formated IP Address");
  1314. }
  1315.     }
  1316. }
  1317. if (value >= 0 || value < 256) {
  1318.     *(ipaddress->data + j) = value;
  1319. } else {
  1320.     error_out("ERROR: Improperly formated IP Address");
  1321. }
  1322. j++;
  1323.     }
  1324.     *(ipaddress->data + j) = '';
  1325.     if (j != 4 && j != 8) {
  1326. error_out("ERROR: Improperly formated IP Address");
  1327.     }
  1328.     ipaddress->len = j;
  1329.     return ipaddress;
  1330. }
  1331. static SECItem *
  1332. string_to_binary(char  *string)
  1333. {
  1334.     SECItem            *rv;
  1335.     int                high_digit;
  1336.     int                low_digit;
  1337.     rv = (SECItem *) PORT_ZAlloc(sizeof(SECItem));
  1338.     if (rv == NULL) {
  1339. error_allocate();
  1340.     }
  1341.     rv->data = (unsigned char *) PORT_ZAlloc((PORT_Strlen(string))/3 + 2);
  1342.     while (!isxdigit(*string)) {
  1343. string++;
  1344.     }
  1345.     rv->len = 0;
  1346.     while (*string != '') {
  1347. if (isxdigit(*string)) {
  1348.     if (*string >= '0' && *string <= '9') {
  1349. high_digit = *string - '0';
  1350.     } else {
  1351. *string = toupper(*string);
  1352. high_digit = *string - 'A';
  1353.     }
  1354.     string++;
  1355.     if (*string >= '0' && *string <= '9') {
  1356. low_digit = *string - '0';
  1357.     } else {
  1358. *string = toupper(*string);
  1359. low_digit = *string = 'A';
  1360.     }
  1361.     (rv->len)++;
  1362. } else {
  1363.     if (*string == ':') {
  1364. string++;
  1365.     } else {
  1366. if (*string == ' ') {
  1367.     while (*string == ' ') {
  1368. string++;
  1369.     }
  1370. }
  1371. if (*string != '') {
  1372.     error_out("ERROR: Improperly formated binary encoding");
  1373. }
  1374.     }
  1375.     }
  1376.     return rv;
  1377. }
  1378. static SECStatus
  1379. MakeGeneralName(char             *name, 
  1380. CERTGeneralName  *genName,
  1381. PRArenaPool      *arena)
  1382. {
  1383.     SECItem                      *oid;
  1384.     SECOidData                   *oidData;
  1385.     SECItem                      *ipaddress;
  1386.     SECItem                      *temp = NULL;
  1387.     int                          i;
  1388.     int                          nameType;
  1389.     PRBool                       binary = PR_FALSE;
  1390.     SECStatus                    rv = SECSuccess;
  1391.     PRBool                       nickname;
  1392.     PORT_Assert(genName);
  1393.     PORT_Assert(arena);
  1394.     nameType = *(name + PORT_Strlen(name) - 1) - '0';
  1395.     if (nameType == 0  && *(name +PORT_Strlen(name) - 2) == '1') {
  1396. nickname = PR_TRUE;
  1397. nameType = certOtherName;
  1398.     }
  1399.     if (nameType < 1 || nameType > 9) {
  1400. error_out("ERROR: Unknown General Name Type");
  1401.     }
  1402.     *(name + PORT_Strlen(name) - 4) = '';
  1403.     genName->type = nameType;
  1404.     
  1405.     switch (genName->type) {
  1406.       case certURI:
  1407.       case certRFC822Name:
  1408.       case certDNSName: {
  1409.   genName->name.other.data = (unsigned char *)name;
  1410.   genName->name.other.len = PORT_Strlen(name);
  1411.   break;
  1412.       }
  1413.       
  1414.       case certIPAddress: {
  1415.   ipaddress = string_to_ipaddress(name);
  1416.   genName->name.other.data = ipaddress->data;
  1417.   genName->name.other.len = ipaddress->len;
  1418.   break;
  1419.       }
  1420.       
  1421.       case certRegisterID: {
  1422.   oid = string_to_oid(name);
  1423.   genName->name.other.data = oid->data;
  1424.   genName->name.other.len = oid->len;
  1425.   break;
  1426.       }
  1427.       
  1428.       case certEDIPartyName:
  1429.       case certX400Address: {
  1430.   
  1431.   genName->name.other.data = PORT_ArenaAlloc (arena, 
  1432.       PORT_Strlen (name) + 2);
  1433.   if (genName->name.other.data == NULL) {
  1434.       error_allocate();
  1435.   }
  1436.   
  1437.   PORT_Memcpy (genName->name.other.data + 2, name, PORT_Strlen (name));
  1438.   /* This may not be accurate for all cases.  
  1439.      For now, use this tag type */
  1440.   genName->name.other.data[0] = (char)(((genName->type - 1) & 
  1441. 0x1f)| 0x80);
  1442.   genName->name.other.data[1] = (char)PORT_Strlen (name);
  1443.   genName->name.other.len = PORT_Strlen (name) + 2;
  1444.   break;
  1445.       }
  1446.       
  1447.       case certOtherName: {
  1448.   i = 0;
  1449.   if (!nickname) {
  1450.       while (!isdigit(*(name + PORT_Strlen(name) - i))) {
  1451.   i++;
  1452.       }
  1453.       if (*(name + PORT_Strlen(name) - i) == '1') {
  1454.   binary = PR_TRUE;
  1455.       } else {
  1456.   binary = PR_FALSE;
  1457.       }  
  1458.       while (*(name + PORT_Strlen(name) - i) != '-') {
  1459.   i++;
  1460.       }
  1461.       *(name + PORT_Strlen(name) - i - 1) = '';
  1462.       i = 0;
  1463.       while (*(name + i) != '-') {
  1464.   i++;
  1465.       }
  1466.       *(name + i - 1) = '';
  1467.       oid = string_to_oid(name + i + 2);
  1468.   } else {
  1469.       oidData = SECOID_FindOIDByTag(SEC_OID_NETSCAPE_NICKNAME);
  1470.       oid = &oidData->oid;
  1471.       while (*(name + PORT_Strlen(name) - i) != '-') {
  1472.   i++;
  1473.       }
  1474.       *(name + PORT_Strlen(name) - i) = '';
  1475.   }
  1476.   genName->name.OthName.oid.data = oid->data;
  1477.   genName->name.OthName.oid.len  = oid->len;
  1478.   if (binary) {
  1479.       temp = string_to_binary(name);
  1480.       genName->name.OthName.name.data = temp->data;
  1481.       genName->name.OthName.name.len = temp->len;
  1482.   } else {
  1483.       temp = (SECItem *) PORT_ZAlloc(sizeof(SECItem));
  1484.       if (temp == NULL) {
  1485.   error_allocate();
  1486.       }
  1487.       temp->data = (unsigned char *)name;
  1488.       temp->len = PORT_Strlen(name);
  1489.       SEC_ASN1EncodeItem (arena, &(genName->name.OthName.name), temp,
  1490.   CERTIA5TypeTemplate);
  1491.   }
  1492.   PORT_Free(temp);
  1493.   break;
  1494.       }
  1495.       
  1496.       case certDirectoryName: {
  1497.   CERTName *directoryName = NULL;
  1498.   
  1499.   directoryName = CERT_AsciiToName (name);
  1500.   if (!directoryName) {
  1501.       error_out("ERROR: Improperly formated alternative name");
  1502.       break;
  1503.   }
  1504.   rv = CERT_CopyName (arena, &genName->name.directoryName, 
  1505.       directoryName);
  1506.   CERT_DestroyName (directoryName);
  1507.   
  1508.   break;
  1509.       }
  1510.     }
  1511.     genName->l.next = &(genName->l);
  1512.     genName->l.prev = &(genName->l);
  1513.     return rv;
  1514. }
  1515. static CERTGeneralName *
  1516. MakeAltName(Pair             *data, 
  1517.     char             *which, 
  1518.     PRArenaPool      *arena)
  1519. {
  1520.     CERTGeneralName          *SubAltName;
  1521.     CERTGeneralName          *current;
  1522.     CERTGeneralName          *newname;
  1523.     char                     *name = NULL;
  1524.     SECStatus                rv = SECSuccess;
  1525.     int                      len;
  1526.     
  1527.     len = PORT_Strlen(which);
  1528.     name = find_field(data, which, PR_TRUE);
  1529.     SubAltName = current = (CERTGeneralName *) PORT_ZAlloc
  1530.                                         (sizeof(CERTGeneralName));
  1531.     if (current == NULL) {
  1532. error_allocate();
  1533.     }
  1534.     while (name != NULL) {
  1535. rv = MakeGeneralName(name, current, arena);
  1536. if (rv != SECSuccess) {
  1537.     break;
  1538. }
  1539. if (*(which + len -1) < '9') {
  1540.     *(which + len - 1) = *(which + len - 1) + 1;
  1541. } else {
  1542.     if (isdigit(*(which + len - 2) )) {
  1543. *(which + len - 2) = *(which + len - 2) + 1;
  1544. *(which + len - 1) = '0';
  1545.     } else {
  1546. *(which + len - 1) = '1';
  1547. *(which + len) = '0';
  1548. *(which + len + 1) = '';
  1549. len++;
  1550.     }
  1551. }
  1552. len = PORT_Strlen(which);
  1553. name = find_field(data, which, PR_TRUE);
  1554. if (name != NULL) {
  1555.     newname = (CERTGeneralName *) PORT_ZAlloc(sizeof(CERTGeneralName));
  1556.     if (newname == NULL) {
  1557. error_allocate();
  1558.     }
  1559.     current->l.next = &(newname->l);
  1560.     newname->l.prev = &(current->l);
  1561.     current = newname;
  1562.             newname = NULL;
  1563. } else {
  1564.     current->l.next = &(SubAltName->l);
  1565.     SubAltName->l.prev = &(current->l);
  1566. }
  1567.     }
  1568.     if (rv == SECFailure) {
  1569. return NULL;
  1570.     }
  1571.     return SubAltName;
  1572. }
  1573. static CERTNameConstraints *
  1574. MakeNameConstraints(Pair             *data, 
  1575.     PRArenaPool      *arena)
  1576. {
  1577.     CERTNameConstraints      *NameConstraints;
  1578.     CERTNameConstraint       *current = NULL;
  1579.     CERTNameConstraint       *last_permited = NULL;
  1580.     CERTNameConstraint       *last_excluded = NULL;
  1581.     char                     *constraint = NULL;
  1582.     char                     *which;
  1583.     SECStatus                rv = SECSuccess;
  1584.     int                      len;
  1585.     int                      i;
  1586.     long                     max;
  1587.     long                     min;
  1588.     PRBool                   permited;
  1589.     
  1590.     NameConstraints = (CERTNameConstraints *) PORT_ZAlloc
  1591.                             (sizeof(CERTNameConstraints));
  1592.     which = make_copy_string("NameConstraintSelect0", 25,'');
  1593.     len = PORT_Strlen(which);
  1594.     constraint = find_field(data, which, PR_TRUE);
  1595.     NameConstraints->permited = NameConstraints->excluded = NULL;
  1596.     while (constraint != NULL) {
  1597. current = (CERTNameConstraint *) PORT_ZAlloc
  1598.                        (sizeof(CERTNameConstraint));
  1599. if (current == NULL) {
  1600.     error_allocate();
  1601. }
  1602. i = 0;
  1603. while (*(constraint + PORT_Strlen(constraint) - i) != '-') {
  1604.     i++;
  1605. }
  1606.         *(constraint + PORT_Strlen(constraint) - i - 1) = ''; 
  1607. max = (long) atoi(constraint + PORT_Strlen(constraint) + 3);
  1608. if (max > 0) {
  1609.     (void) SEC_ASN1EncodeInteger(arena, &current->max, max);
  1610. }
  1611. i = 0;
  1612. while (*(constraint + PORT_Strlen(constraint) - i) != '-') {
  1613.     i++;
  1614. }
  1615.         *(constraint + PORT_Strlen(constraint) - i - 1) = '';
  1616. min = (long) atoi(constraint + PORT_Strlen(constraint) + 3);
  1617. (void) SEC_ASN1EncodeInteger(arena, &current->min, min);
  1618. while (*(constraint + PORT_Strlen(constraint) - i) != '-') {
  1619.     i++;
  1620. }
  1621.         *(constraint + PORT_Strlen(constraint) - i - 1) = '';
  1622. if (*(constraint + PORT_Strlen(constraint) + 3) == 'p') {
  1623.     permited = PR_TRUE;
  1624. } else {
  1625.     permited = PR_FALSE;
  1626. }
  1627. rv = MakeGeneralName(constraint, &(current->name), arena);
  1628. if (rv != SECSuccess) {
  1629.     break;
  1630. }
  1631. if (*(which + len - 1) < '9') {
  1632.     *(which + len - 1) = *(which + len - 1) + 1;
  1633. } else {
  1634.     if (isdigit(*(which + len - 2) )) {
  1635. *(which + len - 2) = *(which + len - 2) + 1;
  1636. *(which + len - 1) = '0';
  1637.     } else {
  1638. *(which + len - 1) = '1';
  1639. *(which + len) = '0';
  1640. *(which + len + 1) = '';
  1641. len++;
  1642.     }
  1643. }
  1644. len = PORT_Strlen(which);
  1645. if (permited) {
  1646.     if (NameConstraints->permited == NULL) {
  1647. NameConstraints->permited = last_permited = current;
  1648.     }
  1649.     last_permited->l.next = &(current->l);
  1650.     current->l.prev = &(last_permited->l);
  1651.     last_permited = current;
  1652. } else {
  1653.     if (NameConstraints->excluded == NULL) {
  1654. NameConstraints->excluded = last_excluded = current;
  1655.     }
  1656.     last_excluded->l.next = &(current->l);
  1657.     current->l.prev = &(last_excluded->l);
  1658.     last_excluded = current;
  1659. }
  1660. constraint = find_field(data, which, PR_TRUE);
  1661. if (constraint != NULL) {
  1662.     current = (CERTNameConstraint *) PORT_ZAlloc(sizeof(CERTNameConstraint));
  1663.     if (current = NULL) {
  1664. error_allocate();
  1665.     }
  1666. }
  1667.     }
  1668.     if (NameConstraints->permited != NULL) {
  1669. last_permited->l.next = &(NameConstraints->permited->l);
  1670. NameConstraints->permited->l.prev = &(last_permited->l);
  1671.     }
  1672.     if (NameConstraints->excluded != NULL) {
  1673. last_excluded->l.next = &(NameConstraints->excluded->l);
  1674. NameConstraints->excluded->l.prev = &(last_excluded->l);
  1675.     }
  1676.     if (which != NULL) {
  1677. PORT_Free(which);
  1678.     }
  1679.     if (rv == SECFailure) {
  1680. return NULL;
  1681.     }
  1682.     return NameConstraints;
  1683. }
  1684. static SECStatus
  1685. AddAltName(void              *extHandle,
  1686.    Pair              *data,
  1687.    char              *issuerNameStr, 
  1688.    CERTCertDBHandle  *handle,
  1689.    int               type)
  1690. {
  1691.     PRBool             autoIssuer = PR_FALSE;
  1692.     PRArenaPool        *arena = NULL;
  1693.     CERTGeneralName    *genName = NULL;
  1694.     CERTName           *directoryName = NULL;
  1695.     char               *which = NULL;
  1696.     char               *name = NULL;
  1697.     SECStatus          rv = SECSuccess;
  1698.     SECItem            *issuersAltName = NULL;
  1699.     CERTCertificate    *issuerCert = NULL;
  1700.     void               *mark;
  1701.     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1702.     if (arena == NULL) {
  1703. error_allocate();
  1704.     }
  1705.     if (type == 0) {
  1706. which = make_copy_string("SubAltNameSelect0", 20,'');
  1707. genName = MakeAltName(data, which, arena);
  1708.     } else {
  1709. if (autoIssuer) {
  1710.     autoIssuer = find_field_bool(data,"IssuerAltNameSourceRadio-auto",
  1711.  PR_TRUE);
  1712.     issuerCert = CERT_FindCertByNameString(handle, issuerNameStr);
  1713.     rv = cert_FindExtension((*issuerCert).extensions, 
  1714.     SEC_OID_X509_SUBJECT_ALT_NAME, 
  1715.     issuersAltName);
  1716.     if (issuersAltName == NULL) {
  1717. name = PORT_Alloc(PORT_Strlen((*issuerCert).subjectName) + 4);
  1718. PORT_Strcpy(name, (*issuerCert).subjectName);
  1719. PORT_Strcat(name, " - 5");
  1720.     }
  1721. } else {
  1722.     which = make_copy_string("IssuerAltNameSelect0", 20,'');
  1723.     genName = MakeAltName(data, which, arena);
  1724. }
  1725.     }
  1726.     if (type == 0) {
  1727. EncodeAndAddExtensionValue(arena, extHandle, genName, 
  1728.    find_field_bool(data, "SubAltName-crit", 
  1729.    PR_TRUE), 
  1730.    SEC_OID_X509_SUBJECT_ALT_NAME, 
  1731.    (EXTEN_VALUE_ENCODER)
  1732.    CERT_EncodeAltNameExtension);
  1733.     } else {
  1734. if (autoIssuer && (name == NULL)) {
  1735.     rv = CERT_AddExtension
  1736. (extHandle, SEC_OID_X509_ISSUER_ALT_NAME, issuersAltName,
  1737.  find_field_bool(data, "IssuerAltName-crit", PR_TRUE), PR_TRUE);
  1738. } else {
  1739.     EncodeAndAddExtensionValue(arena, extHandle, genName, 
  1740.        find_field_bool(data, 
  1741.        "IssuerAltName-crit", 
  1742.        PR_TRUE), 
  1743.        SEC_OID_X509_ISSUER_ALT_NAME, 
  1744.        (EXTEN_VALUE_ENCODER)
  1745.        CERT_EncodeAltNameExtension);
  1746. }
  1747.     }
  1748.     if (which != NULL) {
  1749. PORT_Free(which);
  1750.     }
  1751.     if (issuerCert != NULL) {
  1752. CERT_DestroyCertificate(issuerCert);
  1753.     }
  1754.     if (arena != NULL) {
  1755. PORT_ArenaRelease (arena, mark);
  1756.     }
  1757.     return rv;
  1758. }
  1759. static SECStatus
  1760. AddNameConstraints(void  *extHandle,
  1761.    Pair  *data)
  1762. {
  1763.     PRBool              autoIssuer = PR_FALSE;
  1764.     PRArenaPool         *arena = NULL;
  1765.     CERTNameConstraints *constraints = NULL;
  1766.     char                *constraint = NULL;
  1767.     SECStatus           rv = SECSuccess;
  1768.     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1769.     if (arena == NULL) {
  1770. error_allocate();
  1771.     }
  1772.     constraints = MakeNameConstraints(data, arena);
  1773.     if (constraints != NULL) {
  1774. EncodeAndAddExtensionValue(arena, extHandle, constraints, PR_TRUE, 
  1775.    SEC_OID_X509_NAME_CONSTRAINTS, 
  1776.    (EXTEN_VALUE_ENCODER)
  1777.    CERT_EncodeNameConstraintsExtension);
  1778.     }
  1779.     if (arena != NULL) {
  1780. PORT_ArenaRelease (arena, NULL);
  1781.     }
  1782.     return rv;
  1783. }
  1784. static SECStatus
  1785. add_extensions(CERTCertificate   *subjectCert, 
  1786.        Pair              *data, 
  1787.        char              *issuerNameStr, 
  1788.        CERTCertDBHandle  *handle)
  1789. {
  1790.     void                         *extHandle;
  1791.     SECStatus                    rv = SECSuccess;
  1792.     extHandle = CERT_StartCertExtensions (subjectCert);
  1793.     if (extHandle == NULL) {
  1794. error_out("ERROR: Unable to get certificates extension handle");
  1795.     }
  1796.     if (find_field_bool(data, "keyUsage", PR_TRUE)) {
  1797. rv = AddKeyUsage(extHandle, data);
  1798. if (rv != SECSuccess) {
  1799.     error_out("ERROR: Unable to add Key Usage extension");
  1800. }
  1801.     }
  1802.     if( find_field_bool(data, "extKeyUsage", PR_TRUE) ) {
  1803.       rv = AddExtKeyUsage(extHandle, data);
  1804.       if( SECSuccess != rv ) {
  1805.         error_out("ERROR: Unable to add Extended Key Usage extension");
  1806.       }
  1807.     }
  1808.     if (find_field_bool(data, "basicConstraints", PR_TRUE)) {
  1809. rv = AddBasicConstraint(extHandle, data);
  1810. if (rv != SECSuccess) {
  1811.     error_out("ERROR: Unable to add Basic Constraint extension");
  1812. }
  1813.     }
  1814.     if (find_field_bool(data, "subjectKeyIdentifier", PR_TRUE)) {
  1815. rv = AddSubKeyID(extHandle, data, subjectCert);
  1816. if (rv != SECSuccess) {
  1817.     error_out("ERROR: Unable to add Subject Key Identifier Extension");
  1818. }
  1819.     }
  1820.     if (find_field_bool(data, "authorityKeyIdentifier", PR_TRUE)) {
  1821. rv = AddAuthKeyID (extHandle, data, issuerNameStr, handle);
  1822. if (rv != SECSuccess) {
  1823.     error_out("ERROR: Unable to add Authority Key Identifier extension");
  1824. }
  1825.     }
  1826.     if (find_field_bool(data, "privKeyUsagePeriod", PR_TRUE)) {
  1827. rv = AddPrivKeyUsagePeriod (extHandle, data, subjectCert);
  1828. if (rv != SECSuccess) {
  1829.     error_out("ERROR: Unable to add Private Key Usage Period extension");
  1830. }
  1831.     }
  1832.     if (find_field_bool(data, "SubAltName", PR_TRUE)) {
  1833. rv = AddAltName (extHandle, data, NULL, NULL, 0);
  1834. if (rv != SECSuccess) {
  1835.     error_out("ERROR: Unable to add Subject Alternative Name extension");
  1836. }
  1837.     }
  1838.     if (find_field_bool(data, "IssuerAltName", PR_TRUE)) {
  1839. rv = AddAltName (extHandle, data, issuerNameStr, handle, 1);
  1840. if (rv != SECSuccess) {
  1841.     error_out("ERROR: Unable to add Issuer Alternative Name Extension");
  1842. }
  1843.     }
  1844.     if (find_field_bool(data, "NameConstraints", PR_TRUE)) {
  1845. rv = AddNameConstraints(extHandle, data);
  1846. if (rv != SECSuccess) {
  1847.     error_out("ERROR: Unable to add Name Constraints Extension");
  1848. }
  1849.     }
  1850.     if (find_field_bool(data, "netscape-cert-type", PR_TRUE)) {
  1851. rv = AddNscpCertType(extHandle, data);
  1852. if (rv != SECSuccess) {
  1853.     error_out("ERROR: Unable to add Netscape Certificate Type Extension");
  1854. }
  1855.     }
  1856.     if (find_field_bool(data, "netscape-base-url", PR_TRUE)) {
  1857. rv = add_IA5StringExtension(extHandle, 
  1858.     find_field(data, "netscape-base-url-text", 
  1859.        PR_TRUE), 
  1860.     find_field_bool(data, 
  1861.     "netscape-base-url-crit", 
  1862.     PR_TRUE),
  1863.     SEC_OID_NS_CERT_EXT_BASE_URL);
  1864. if (rv != SECSuccess) {
  1865.     error_out("ERROR: Unable to add Netscape Base URL Extension");
  1866. }
  1867.     }
  1868.     if (find_field_bool(data, "netscape-revocation-url", PR_TRUE)) {
  1869. rv = add_IA5StringExtension(extHandle, 
  1870.     find_field(data, 
  1871.        "netscape-revocation-url-text", 
  1872.        PR_TRUE), 
  1873.     find_field_bool
  1874.        (data, "netscape-revocation-url-crit", 
  1875. PR_TRUE),
  1876.     SEC_OID_NS_CERT_EXT_REVOCATION_URL);
  1877. if (rv != SECSuccess) {
  1878.     error_out("ERROR: Unable to add Netscape Revocation URL Extension");
  1879. }
  1880.     }
  1881.     if (find_field_bool(data, "netscape-ca-revocation-url", PR_TRUE)) {
  1882. rv = add_IA5StringExtension(extHandle, 
  1883.     find_field(data, 
  1884.       "netscape-ca-revocation-url-text",
  1885.        PR_TRUE), 
  1886.     find_field_bool
  1887.         (data, "netscape-ca-revocation-url-crit"
  1888.  , PR_TRUE),
  1889.     SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL);
  1890. if (rv != SECSuccess) {
  1891.     error_out("ERROR: Unable to add Netscape CA Revocation URL Extension");
  1892. }
  1893.     }
  1894.     if (find_field_bool(data, "netscape-cert-renewal-url", PR_TRUE)) {
  1895. rv = add_IA5StringExtension(extHandle, 
  1896.     find_field(data, 
  1897.        "netscape-cert-renewal-url-text",
  1898.        PR_TRUE), 
  1899.     find_field_bool
  1900.         (data, "netscape-cert-renewal-url-crit",
  1901.  PR_TRUE),
  1902.     SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL);
  1903. if (rv != SECSuccess) {
  1904.     error_out("ERROR: Unable to add Netscape Certificate Renewal URL Extension");
  1905. }
  1906.     }
  1907.     if (find_field_bool(data, "netscape-ca-policy-url", PR_TRUE)) {
  1908. rv = add_IA5StringExtension(extHandle, 
  1909.     find_field(data, 
  1910.        "netscape-ca-policy-url-text", 
  1911.        PR_TRUE), 
  1912.     find_field_bool
  1913.          (data, "netscape-ca-policy-url-crit", 
  1914.   PR_TRUE),
  1915.     SEC_OID_NS_CERT_EXT_CA_POLICY_URL);
  1916. if (rv != SECSuccess) {
  1917.     error_out("ERROR: Unable to add Netscape CA Policy URL Extension");
  1918. }
  1919.     }
  1920.     if (find_field_bool(data, "netscape-ssl-server-name", PR_TRUE)) {
  1921. rv = add_IA5StringExtension(extHandle, 
  1922.     find_field(data, 
  1923.        "netscape-ssl-server-name-text", 
  1924.        PR_TRUE), 
  1925.     find_field_bool
  1926.          (data, "netscape-ssl-server-name-crit",
  1927.   PR_TRUE),
  1928.     SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME);
  1929. if (rv != SECSuccess) {
  1930.     error_out("ERROR: Unable to add Netscape SSL Server Name Extension");
  1931. }
  1932.     }
  1933.     if (find_field_bool(data, "netscape-comment", PR_TRUE)) {
  1934. rv = add_IA5StringExtension(extHandle, 
  1935.     find_field(data, "netscape-comment-text", 
  1936.        PR_TRUE), 
  1937.     find_field_bool(data, 
  1938.     "netscape-comment-crit", 
  1939.     PR_TRUE),
  1940.     SEC_OID_NS_CERT_EXT_COMMENT);
  1941. if (rv != SECSuccess) {
  1942.     error_out("ERROR: Unable to add Netscape Comment Extension");
  1943. }
  1944.     }
  1945.     CERT_FinishExtensions(extHandle);
  1946.     return (rv);
  1947. }
  1948. char *
  1949. return_dbpasswd(PK11SlotInfo *slot, PRBool retry, void *data)
  1950. {
  1951.     char *rv;
  1952.     /* don't clobber our poor smart card */
  1953.     if (retry == PR_TRUE) {
  1954. return NULL;
  1955.     }
  1956.     rv = PORT_Alloc(sizeof(char) * 4);
  1957.     PORT_Strcpy(rv, "foo");
  1958.     return rv;
  1959. }
  1960. SECKEYPrivateKey *
  1961. FindPrivateKeyFromNameStr(char              *name, 
  1962.   CERTCertDBHandle  *certHandle)
  1963. {
  1964.     SECKEYPrivateKey                        *key;
  1965.     CERTCertificate                         *cert;
  1966.     SECStatus                               status = SECSuccess;
  1967.     cert = CERT_FindCertByNameString(certHandle, name);
  1968.     if (cert == NULL) {
  1969. error_out("ERROR: Unable to retrieve issuers certificate");
  1970.     }
  1971.     key = PK11_FindKeyByAnyCert(cert, NULL);
  1972.     return key;
  1973. }
  1974. static SECItem *
  1975. SignCert(CERTCertificate   *cert,
  1976.  char              *issuerNameStr,
  1977.  Pair              *data,
  1978.  CERTCertDBHandle  *handle,
  1979.          int               which_key)
  1980. {
  1981.     SECItem                der;
  1982.     SECItem                *result = NULL;
  1983.     SECKEYPrivateKey       *caPrivateKey = NULL;
  1984.     SECStatus              rv;
  1985.     PRArenaPool            *arena;
  1986.     SECOidTag              algID;
  1987.     if (which_key == 0) {
  1988. caPrivateKey = FindPrivateKeyFromNameStr(issuerNameStr, handle); 
  1989.     } else {
  1990. caPrivateKey = privkeys[which_key - 1];
  1991.     }
  1992.     if (caPrivateKey == NULL) {
  1993. error_out("ERROR: unable to retrieve issuers key");
  1994.     }
  1995.     arena = cert->arena;
  1996.     switch(caPrivateKey->keyType) {
  1997.       case rsaKey:
  1998. algID = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
  1999. break;
  2000.       case dsaKey:
  2001. algID = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
  2002. break;
  2003.       default:
  2004. error_out("ERROR: Unknown key type for issuer.");
  2005. goto done;
  2006. break;
  2007.     }
  2008.     rv = SECOID_SetAlgorithmID(arena, &cert->signature, algID, 0);
  2009.     if (rv != SECSuccess) {
  2010. error_out("ERROR: Could not set signature algorithm id.");
  2011.     }
  2012.     if (find_field_bool(data,"ver-1", PR_TRUE)) {
  2013. *(cert->version.data) = 0;
  2014. cert->version.len = 1;
  2015.     } else {
  2016. *(cert->version.data) = 2;
  2017. cert->version.len = 1;
  2018.     }
  2019.     der.data = NULL;
  2020.     der.len = 0;
  2021.     (void) SEC_ASN1EncodeItem (arena, &der, cert, CERT_CertificateTemplate);
  2022.     if (der.data == NULL) {
  2023. error_out("ERROR: Could not encode certificate.n");
  2024.     }
  2025.     rv = SEC_DerSignData (arena, &(cert->derCert), der.data, der.len, caPrivateKey,
  2026.   algID);
  2027.     if (rv != SECSuccess) {
  2028. error_out("ERROR: Could not sign encoded certificate data.n");
  2029.     }
  2030. done:
  2031.     SECKEY_DestroyPrivateKey(caPrivateKey);
  2032.     return &(cert->derCert);
  2033. }
  2034. void
  2035. main()
  2036. {
  2037.     int                    length = 500;
  2038.     int                    remaining = 500;
  2039.     int                    n;
  2040.     int                    fields = 3;
  2041.     int                    i;
  2042.     int                    serial;
  2043.     int                    chainLen;
  2044.     int                    which_key;
  2045.     char                   *pos;
  2046. #ifdef OFFLINE
  2047.     char                   *form_output = "key=MIIBPTCBpzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA7SLqjWBL9Wl11Vlg%0AaMqZCvcQOL%2FnvSqYPPRP0XZy9SoAeyWzQnBOiCm2t8H5mK7r2jnKdAQOmfhjaJil%0A3hNVu3SekHOXF6Ze7bkWa6%2FSGVcY%2FojkydxFSgY43nd1iydzPQDp8WWLL%2BpVpt%2B%2B%0ATRhFtVXbF0fQI03j9h3BoTgP2lkCAwEAARYDZm9vMA0GCSqGSIb3DQEBBAUAA4GB%0AAJ8UfRKJ0GtG%2B%2BufCC6tAfTzKrq3CTBHnom55EyXcsAsv6WbDqI%2F0rLAPkn2Xo1r%0AnNhtMxIuj441blMt%2Fa3AGLOy5zmC7Qawt8IytvQikQ1XTpTBCXevytrmLjCmlURr%0ANJryTM48WaMQHiMiJpbXCqVJC1d%2FpEWBtqvALzZaOOIy&subject=CN%3D%22test%22%26serial-auto%3Dtrue%26serial_value%3D%26ver-1%3Dtrue%26ver-3%3Dfalse%26caChoiceradio-SignWithDefaultkey%3Dtrue%26caChoiceradio-SignWithRandomChain%3Dfalse%26autoCAs%3D%26caChoiceradio-SignWithSpecifiedChain%3Dfalse%26manCAs%3D%26%24";
  2048. #else
  2049.     char                   *form_output;
  2050. #endif
  2051.     char                   *issuerNameStr;
  2052.     char                   *certName;
  2053.     char                   *DBdir = DB_DIRECTORY;
  2054.     char                   *prefixs[10] = {"CA#1-", "CA#2-", "CA#3-", 
  2055.    "CA#4-", "CA#5-", "CA#6-", 
  2056.    "CA#7-", "CA#8-", "CA#9-", ""};
  2057.     Pair                   *form_data;
  2058.     CERTCertificate        *cert;
  2059.     CERTCertDBHandle       *handle;
  2060.     CERTCertificateRequest *certReq = NULL;
  2061.     int                    warpmonths = 0;
  2062.     SECItem                *certDER;
  2063. #ifdef FILEOUT
  2064.     FILE                   *outfile;
  2065. #endif
  2066.     SECStatus              status = SECSuccess;
  2067.     extern                 char prefix[PREFIX_LEN];
  2068.     SEC_PKCS7ContentInfo   *certChain;
  2069.     SECItem                *encodedCertChain;
  2070.     PRBool                 UChain = PR_FALSE;
  2071. #ifdef TEST
  2072.     sleep(20);
  2073. #endif
  2074.     RNG_SystemInfoForRNG();
  2075.     SECU_ConfigDirectory(DBdir);
  2076.     PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
  2077.     SECU_PKCS11Init(PR_FALSE);     
  2078.     SEC_Init();
  2079.     PK11_SetPasswordFunc(return_dbpasswd);
  2080.     handle = NULL;
  2081.     handle = OpenCertDB();
  2082.     if (handle == NULL) {
  2083. error_out("Error: Unable to open certificate database");
  2084.     }
  2085.     prefix[0]= '';
  2086. #if !defined(OFFLINE)
  2087.     form_output = (char*) PORT_Alloc(length);
  2088.     if (form_output == NULL) {
  2089. error_allocate();
  2090.     }
  2091.     pos = form_output;
  2092.     while (feof(stdin) == 0 ) {
  2093. if (remaining <= 1) {
  2094.     remaining += length;
  2095.     length = length * 2;
  2096.     form_output = PORT_Realloc(form_output, (length));
  2097.     if (form_output == NULL) {
  2098. error_allocate();
  2099.     }
  2100.     pos = form_output + length - remaining;
  2101. }
  2102. n = fread(pos, sizeof(char), (size_t) (remaining - 1), stdin);
  2103. pos += n;
  2104. remaining -= n;
  2105.     }
  2106.     *pos = '&';
  2107.     pos++;
  2108.     length = pos - form_output;
  2109. #else
  2110.     length = PORT_Strlen(form_output);
  2111. #endif
  2112. #ifdef FILEOUT
  2113.     printf("Content-type: text/plainnn");
  2114.     fwrite(form_output, sizeof(char), (size_t)length, stdout);
  2115.     printf("n");
  2116. #endif
  2117. #ifdef FILEOUT
  2118.     fwrite(form_output, sizeof(char), (size_t)length, stdout);
  2119.     printf("n");
  2120.     fflush(stdout);
  2121. #endif
  2122.     form_data = make_datastruct(form_output, length);
  2123.     status = clean_input(form_data);
  2124. #if !defined(OFFLINE)
  2125.     PORT_Free(form_output);
  2126. #endif
  2127. #ifdef FILEOUT
  2128.     i = 0;
  2129.     while(return_name(form_data, i) != NULL) {
  2130.         printf("%s",return_name(form_data,i));
  2131.         printf("=n");
  2132.         printf("%s",return_data(form_data,i));
  2133.         printf("n");
  2134. i++;
  2135.     }
  2136.     printf("I got that done, woo hoon");
  2137.     fflush(stdout);
  2138. #endif
  2139.     issuerNameStr = PORT_Alloc(35 * sizeof(char));
  2140.     if (find_field_bool(form_data, "caChoiceradio-SignWithSpecifiedChain",
  2141. PR_FALSE)) {
  2142. UChain = PR_TRUE;
  2143. chainLen = atoi(find_field(form_data, "manCAs", PR_FALSE));
  2144. PORT_Strcpy(prefix, prefixs[0]);
  2145. issuerNameStr = PORT_Strcpy(issuerNameStr,
  2146.        "CN=Cert-O-Matic II, O=Cert-O-Matic II");
  2147. if (chainLen == 0) {
  2148.     UChain =  PR_FALSE;
  2149. }
  2150.     } else {
  2151. if (find_field_bool(form_data, "caChoiceradio-SignWithRandomChain", 
  2152.     PR_FALSE)) {
  2153.     PORT_Strcpy(prefix,prefixs[9]);
  2154.     chainLen = atoi(find_field(form_data, "autoCAs", PR_FALSE));
  2155.     if (chainLen < 1 || chainLen > 18) {
  2156. issuerNameStr = PORT_Strcpy(issuerNameStr, 
  2157.        "CN=CA18, O=Cert-O-Matic II");
  2158.     }
  2159.     issuerNameStr = PORT_Strcpy(issuerNameStr, "CN=CA");
  2160.     issuerNameStr = PORT_Strcat(issuerNameStr, 
  2161.    find_field(form_data,"autoCAs", PR_FALSE));
  2162.     issuerNameStr = PORT_Strcat(issuerNameStr,", O=Cert-O-Matic II");
  2163. } else {
  2164.     issuerNameStr = PORT_Strcpy(issuerNameStr, 
  2165.    "CN=Cert-O-Matic II, O=Cert-O-Matic II");
  2166. }
  2167. chainLen = 0;
  2168.     }
  2169.     i = -1;
  2170.     which_key = 0;
  2171.     do {
  2172.      extern SECStatus cert_GetKeyID(CERTCertificate *cert);
  2173. i++;
  2174. if (i != 0 && UChain) {
  2175.     PORT_Strcpy(prefix, prefixs[i]);
  2176. }
  2177. /*        find_field(form_data,"subject", PR_TRUE); */
  2178. certReq = makeCertReq(form_data, which_key);
  2179. #ifdef OFFLINE
  2180. serial = 900;
  2181. #else
  2182. serial = get_serial_number(form_data);
  2183. #endif
  2184. cert = MakeV1Cert(handle, certReq, issuerNameStr, PR_FALSE, 
  2185.   serial, warpmonths, form_data);
  2186. if (certReq != NULL) {
  2187.     CERT_DestroyCertificateRequest(certReq);
  2188. }
  2189. if (find_field_bool(form_data,"ver-3", PR_TRUE)) {
  2190.     status = add_extensions(cert, form_data, issuerNameStr, handle);
  2191.     if (status != SECSuccess) {
  2192. error_out("ERROR: Unable to add extensions");
  2193.     }
  2194. }
  2195. status = cert_GetKeyID(cert);
  2196. if (status == SECFailure) {
  2197.     error_out("ERROR: Unable to get Key ID.");
  2198. }
  2199. certDER = SignCert(cert, issuerNameStr, form_data, handle, which_key);
  2200. CERT_NewTempCertificate(handle, certDER, NULL, PR_FALSE, PR_TRUE);
  2201. issuerNameStr = find_field(form_data, "subject", PR_TRUE);
  2202. /*        SECITEM_FreeItem(certDER, PR_TRUE); */
  2203. CERT_DestroyCertificate(cert);
  2204. if (i == (chainLen - 1)) {
  2205.     i = 8;
  2206. }
  2207. ++which_key;
  2208.     } while (i < 9 && UChain);
  2209. #ifdef FILEOUT
  2210.     outfile = fopen("../certout", "wb");
  2211. #endif
  2212.     certName = find_field(form_data, "subject", PR_FALSE);
  2213.     cert = CERT_FindCertByNameString(handle, certName);
  2214.     certChain = SEC_PKCS7CreateCertsOnly (cert, PR_TRUE, handle);
  2215.     if (certChain == NULL) {
  2216. error_out("ERROR: No certificates in cert chain");
  2217.     }
  2218.     encodedCertChain = SEC_PKCS7EncodeItem (NULL, NULL, certChain, NULL, NULL, 
  2219.     NULL);
  2220.     if (encodedCertChain) {
  2221. #if !defined(FILEOUT)
  2222. printf("Content-type: application/x-x509-user-certnn");
  2223. fwrite (encodedCertChain->data, 1, encodedCertChain->len, stdout);
  2224. #else
  2225. fwrite (encodedCertChain->data, 1, encodedCertChain->len, outfile);
  2226. #endif
  2227.     } else {
  2228. error_out("Error: Unable to DER encode certificate");
  2229.     }
  2230. #ifdef FILEOUT
  2231.     printf("nI got here!n");
  2232.     fflush(outfile);
  2233.     fclose(outfile);
  2234. #endif
  2235.     fflush(stdout);
  2236.     return;
  2237. }