security/nss/cmd/certcgi/certcgi.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 /* Cert-O-Matic CGI */
     8 #include "nspr.h"
     9 #include "prtypes.h"
    10 #include "prtime.h"
    11 #include "prlong.h"
    13 #include "pk11func.h"
    14 #include "cert.h"
    15 #include "cryptohi.h"
    16 #include "secoid.h"
    17 #include "secder.h"
    18 #include "genname.h"
    19 #include "xconst.h"
    20 #include "secutil.h"
    21 #include "pk11pqg.h"
    22 #include "certxutl.h"
    23 #include "nss.h"
    26 /* #define TEST           1 */
    27 /* #define FILEOUT        1 */
    28 /* #define OFFLINE        1 */
    29 #define START_FIELDS   100
    30 #define PREFIX_LEN     6
    31 #define SERIAL_FILE    "../serial"
    32 #define DB_DIRECTORY   ".."
    34 static char *progName;
    36 typedef struct PairStr Pair;
    38 struct PairStr {
    39     char *name;
    40     char *data;
    41 };
    44 char prefix[PREFIX_LEN];
    47 const SEC_ASN1Template CERTIA5TypeTemplate[] = {
    48     { SEC_ASN1_IA5_STRING }
    49 };
    53 SECKEYPrivateKey *privkeys[9] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    54 				 NULL, NULL};
    57 #ifdef notdef
    58 const SEC_ASN1Template CERT_GeneralNameTemplate[] = {
    59     { SEC_ASN1_SEQUENCE_OF, 0, SEC_AnyTemplate }
    60 };
    61 #endif
    64 static void
    65 error_out(char  *error_string)
    66 {
    67     printf("Content-type: text/plain\n\n");
    68     printf("%s", error_string);
    69     fflush(stderr);
    70     fflush(stdout);
    71     exit(1);
    72 }
    74 static void
    75 error_allocate(void)
    76 {
    77     error_out("ERROR: Unable to allocate memory");
    78 }
    81 static char *
    82 make_copy_string(char  *read_pos, 
    83 		 int   length, 
    84 		 char  sentinal_value)
    85     /* copys string from to a new string it creates and 
    86        returns a pointer to the new string */
    87 {
    88     int                remaining = length;
    89     char               *write_pos;
    90     char               *new;
    92     new = write_pos = (char *) PORT_Alloc (length);
    93     if (new == NULL) {
    94 	error_allocate();
    95     }
    96     while (*read_pos != sentinal_value) {
    97 	if (remaining == 1) {
    98 	    remaining += length;
    99 	    length = length * 2;
   100 	    new = PORT_Realloc(new,length);
   101 	    if (new == NULL) {
   102 		error_allocate();
   103 	    }
   104 	    write_pos = new + length - remaining;
   105 	}
   106 	*write_pos = *read_pos;
   107 	++write_pos;
   108 	++read_pos;
   109 	remaining = remaining - 1;
   110     }
   111     *write_pos = '\0';
   112     return new;
   113 }
   116 static SECStatus
   117 clean_input(Pair *data)
   118     /* converts the non-alphanumeric characters in a form post 
   119        from hex codes back to characters */
   120 {
   121     int           length;
   122     int           hi_digit;
   123     int           low_digit;
   124     char          character;
   125     char          *begin_pos;
   126     char          *read_pos;
   127     char          *write_pos;
   128     PRBool        name = PR_TRUE;
   130     begin_pos = data->name;
   131     while (begin_pos != NULL) {
   132 	length = strlen(begin_pos);
   133 	read_pos = write_pos = begin_pos;
   134 	while ((read_pos - begin_pos) < length) {
   135 	    if (*read_pos == '+') {
   136 		*read_pos = ' ';
   137 	    }
   138 	    if (*read_pos == '%') {
   139 		hi_digit = *(read_pos + 1);
   140 		low_digit = *(read_pos +2);
   141 		read_pos += 3;
   142 		if (isdigit(hi_digit)){
   143 		    hi_digit = hi_digit - '0';
   144 		} else {
   145 		    hi_digit = toupper(hi_digit);
   146 		    if (isxdigit(hi_digit)) {
   147 			hi_digit = (hi_digit - 'A') + 10;
   148 		    } else {
   149 			error_out("ERROR: Form data incorrectly formated");
   150 		    }
   151 		}
   152 		if (isdigit(low_digit)){
   153 		    low_digit = low_digit - '0';
   154 		} else {
   155 		    low_digit = toupper(low_digit);
   156 		    if ((low_digit >='A') && (low_digit <= 'F')) {
   157 			low_digit = (low_digit - 'A') + 10;
   158 		    } else {
   159 			error_out("ERROR: Form data incorrectly formated");
   160 		    }
   161 		}
   162 		character = (hi_digit << 4) | low_digit;
   163 		if (character != 10) {
   164 		    *write_pos = character;
   165 		    ++write_pos;
   166 		}
   167 	    } else {
   168 		*write_pos = *read_pos;
   169 		++write_pos;
   170 		++read_pos;
   171 	    }
   172 	}
   173 	*write_pos = '\0';
   174 	if (name == PR_TRUE) {
   175 	    begin_pos = data->data;
   176 	    name = PR_FALSE;
   177 	} else {
   178 	    data++;
   179 	    begin_pos = data->name;
   180 	    name = PR_TRUE;
   181 	}
   182     }
   183     return SECSuccess;
   184 }
   186 static char *
   187 make_name(char  *new_data)
   188     /* gets the next field name in the input string and returns
   189        a pointer to a string containing a copy of it */
   190 {
   191     int         length = 20;
   192     char        *name;
   194     name = make_copy_string(new_data, length, '=');
   195     return name;
   196 }
   198 static char *
   199 make_data(char  *new_data)
   200     /* gets the data for the next field in the input string 
   201        and returns a pointer to a string containing it */
   202 {
   203     int         length = 100;
   204     char        *data;
   205     char        *read_pos;
   207     read_pos = new_data;
   208     while (*(read_pos - 1) != '=') {
   209 	++read_pos;
   210     }
   211     data = make_copy_string(read_pos, length, '&');
   212     return data;
   213 }
   216 static Pair
   217 make_pair(char  *new_data)
   218     /* makes a pair name/data pair from the input string */
   219 {
   220     Pair        temp;
   222     temp.name = make_name(new_data);
   223     temp.data = make_data(new_data);
   224     return temp;
   225 }
   229 static Pair *
   230 make_datastruct(char  *data, int len)
   231     /* parses the input from the form post into a data 
   232        structure of field name/data pairs */
   233 {
   234     Pair              *datastruct;
   235     Pair              *current;
   236     char              *curr_pos;
   237     int               fields = START_FIELDS;
   238     int               remaining = START_FIELDS;
   240     curr_pos = data;
   241     datastruct = current = (Pair *) PORT_Alloc(fields * sizeof(Pair));
   242     if (datastruct == NULL) {
   243 	error_allocate();
   244     }
   245     while (curr_pos - data < len) {
   246 	if (remaining == 1) {
   247 	    remaining += fields;
   248 	    fields = fields * 2;
   249 	    datastruct = (Pair *) PORT_Realloc
   250 		(datastruct, fields * sizeof(Pair));
   251 	    if (datastruct == NULL) {
   252 		error_allocate();
   253 	    }
   254 	    current = datastruct + (fields - remaining);
   255 	}
   256 	*current = make_pair(curr_pos);
   257 	while (*curr_pos != '&') {
   258 	    ++curr_pos;
   259 	}
   260 	++curr_pos;
   261 	++current;
   262 	remaining = remaining - 1;
   263     }
   264     current->name = NULL;
   265     return datastruct;
   266 }
   268 static char *
   269 return_name(Pair  *data_struct,
   270 	    int   n)
   271     /* returns a pointer to the name of the nth 
   272        (starting from 0) item in the data structure */
   273 {
   274     char          *name;
   276     if ((data_struct + n)->name != NULL) {
   277 	name = (data_struct + n)->name;
   278 	return name;
   279     } else {
   280 	return NULL;
   281     }
   282 }
   284 static char *
   285 return_data(Pair  *data_struct,int n)
   286     /* returns a pointer to the data of the nth (starting from 0) 
   287        itme in the data structure */
   288 {
   289     char          *data;
   291     data = (data_struct + n)->data;
   292     return data;
   293 }
   296 static char *
   297 add_prefix(char  *field_name)
   298 {
   299     extern char  prefix[PREFIX_LEN];
   300     int          i = 0;
   301     char         *rv;
   302     char         *write;
   304     rv = write = PORT_Alloc(PORT_Strlen(prefix) + PORT_Strlen(field_name) + 1);
   305     for(i = 0; i < PORT_Strlen(prefix); i++) {
   306 	*write = prefix[i];
   307 	write++;
   308     }
   309     *write = '\0';
   310     rv = PORT_Strcat(rv,field_name);
   311     return rv;
   312 }
   315 static char *
   316 find_field(Pair    *data, 
   317 	   char    *field_name, 
   318 	   PRBool  add_pre)
   319     /* returns a pointer to the data of the first pair 
   320        thats name matches the string it is passed */
   321 {
   322     int            i = 0;
   323     char           *retrieved;
   324     int            found = 0;
   326     if (add_pre) {
   327 	field_name = add_prefix(field_name);
   328     }
   329     while(return_name(data, i) != NULL) {
   330 	if (PORT_Strcmp(return_name(data, i), field_name) == 0) {
   331 	    retrieved = return_data(data, i);
   332 	    found = 1;
   333 	    break;
   334 	}
   335 	i++;
   336     }
   337     if (!found) {
   338 	retrieved = NULL;
   339     }
   340     return retrieved;
   341 }
   343 static PRBool
   344 find_field_bool(Pair    *data, 
   345 		char    *fieldname, 
   346 		PRBool  add_pre)
   347 {
   348     char                *rv;
   350     rv = find_field(data, fieldname, add_pre);
   352     if  ((rv != NULL) && (PORT_Strcmp(rv, "true")) == 0) {
   353 	return PR_TRUE;
   354     } else {
   355 	return PR_FALSE;
   356     }
   357 }
   359 static char *
   360 update_data_by_name(Pair  *data, 
   361 		    char  *field_name,
   362                     char  *new_data)
   363     /* replaces the data in the data structure associated with 
   364        a name with new data, returns null if not found */
   365 {
   366     int                   i = 0;
   367     int                   found = 0;
   368     int                   length = 100;
   369     char                  *new;
   371     while (return_name(data, i) != NULL) {
   372 	if (PORT_Strcmp(return_name(data, i), field_name) == 0) {
   373 	    new = make_copy_string( new_data, length, '\0');
   374 	    PORT_Free(return_data(data, i));
   375 	    found = 1;
   376 	    (*(data + i)).data = new;
   377 	    break;
   378 	}
   379 	i++;
   380     }
   381     if (!found) {
   382 	new = NULL;
   383     }
   384     return new;
   385 }
   387 static char *
   388 update_data_by_index(Pair  *data, 
   389 		     int   n, 
   390 		     char  *new_data)
   391     /* replaces the data of a particular index in the data structure */
   392 {
   393     int                    length = 100;
   394     char                   *new;
   396     new = make_copy_string(new_data, length, '\0');
   397     PORT_Free(return_data(data, n));
   398     (*(data + n)).data = new;
   399     return new;
   400 }
   403 static Pair *
   404 add_field(Pair   *data, 
   405 	  char*  field_name, 
   406 	  char*  field_data)
   407     /* adds a new name/data pair to the data structure */
   408 {
   409     int          i = 0;
   410     int          j;
   411     int          name_length = 100;
   412     int          data_length = 100;
   414     while(return_name(data, i) != NULL) {
   415 	i++;
   416     }
   417     j = START_FIELDS;
   418     while ( j < (i + 1) ) {
   419 	j = j * 2;
   420     }
   421     if (j == (i + 1)) {
   422 	data = (Pair *) PORT_Realloc(data, (j * 2) * sizeof(Pair));
   423 	if (data == NULL) {
   424 	    error_allocate();
   425 	}
   426     }
   427     (*(data + i)).name = make_copy_string(field_name, name_length, '\0');
   428     (*(data + i)).data = make_copy_string(field_data, data_length, '\0');
   429     (data + i + 1)->name = NULL;
   430     return data;
   431 }
   434 static CERTCertificateRequest *
   435 makeCertReq(Pair             *form_data,
   436 	    int              which_priv_key)
   437     /* makes and encodes a certrequest */
   438 {
   440     PK11SlotInfo             *slot;
   441     CERTCertificateRequest   *certReq = NULL;
   442     CERTSubjectPublicKeyInfo *spki;
   443     SECKEYPrivateKey         *privkey = NULL;
   444     SECKEYPublicKey          *pubkey = NULL;
   445     CERTName                 *name;
   446     char                     *key;
   447     extern SECKEYPrivateKey  *privkeys[9];
   448     int                      keySizeInBits;
   449     char                     *challenge = "foo";
   450     SECStatus                rv = SECSuccess;
   451     PQGParams                *pqgParams = NULL;
   452     PQGVerify                *pqgVfy = NULL;
   454     name = CERT_AsciiToName(find_field(form_data, "subject", PR_TRUE));
   455     if (name == NULL) {
   456 	error_out("ERROR: Unable to create Subject Name");
   457     }
   458     key = find_field(form_data, "key", PR_TRUE);
   459     if (key == NULL) {
   460 	switch (*find_field(form_data, "keysize", PR_TRUE)) {
   461 	  case '0':
   462 	    keySizeInBits = 2048;
   463 	    break;
   464 	  case '1':
   465 	    keySizeInBits = 1024;
   466 	    break;
   467 	  case '2':
   468 	    keySizeInBits = 512;
   469 	    break;
   470 	  default:
   471 	    error_out("ERROR: Unsupported Key length selected");
   472 	}
   473 	if (find_field_bool(form_data, "keyType-dsa", PR_TRUE)) {
   474 	    rv = PK11_PQG_ParamGen(keySizeInBits, &pqgParams, &pqgVfy);
   475 	    if (rv != SECSuccess) {
   476 		error_out("ERROR: Unable to generate PQG parameters");
   477 	    }
   478 	    slot = PK11_GetBestSlot(CKM_DSA_KEY_PAIR_GEN, NULL);
   479 	    privkey = PK11_GenerateKeyPair(slot, CKM_DSA_KEY_PAIR_GEN, 
   480 					   pqgParams,&pubkey, PR_FALSE, 
   481 					   PR_TRUE, NULL);
   482 	} else {
   483 	    privkey = SECKEY_CreateRSAPrivateKey(keySizeInBits, &pubkey, NULL);
   484 	}
   485 	privkeys[which_priv_key] = privkey;
   486 	spki = SECKEY_CreateSubjectPublicKeyInfo(pubkey);
   487     } else {
   488 	spki = SECKEY_ConvertAndDecodePublicKeyAndChallenge(key, challenge, 
   489 							    NULL);
   490 	if (spki == NULL) {
   491 	    error_out("ERROR: Unable to decode Public Key and Challenge String");
   492 	}
   493     }
   494     certReq = CERT_CreateCertificateRequest(name, spki, NULL);
   495     if (certReq == NULL) {
   496 	error_out("ERROR: Unable to create Certificate Request");
   497     }
   498     if (pubkey != NULL) {
   499 	SECKEY_DestroyPublicKey(pubkey);
   500     }
   501     if (spki != NULL) {
   502 	SECKEY_DestroySubjectPublicKeyInfo(spki);
   503     }
   504     if (pqgParams != NULL) {
   505 	PK11_PQG_DestroyParams(pqgParams);
   506     }
   507     if (pqgVfy != NULL) {
   508 	PK11_PQG_DestroyVerify(pqgVfy);
   509     }
   510     return certReq;
   511 }
   515 static CERTCertificate *
   516 MakeV1Cert(CERTCertDBHandle        *handle, 
   517 	   CERTCertificateRequest  *req,
   518 	   char                    *issuerNameStr, 
   519 	   PRBool                  selfsign, 
   520 	   int                     serialNumber,
   521 	   int                     warpmonths,
   522 	   Pair                    *data)
   523 {
   524     CERTCertificate                 *issuerCert = NULL;
   525     CERTValidity                    *validity;
   526     CERTCertificate                 *cert = NULL;
   527     PRExplodedTime                  printableTime;
   528     PRTime                          now, 
   529 	                            after;
   530     SECStatus rv;
   534     if ( !selfsign ) {
   535 	issuerCert = CERT_FindCertByNameString(handle, issuerNameStr);
   536 	if (!issuerCert) {
   537 	    error_out("ERROR: Could not find issuer's certificate");
   538 	    return NULL;
   539 	}
   540     }
   541     if (find_field_bool(data, "manValidity", PR_TRUE)) {
   542 	rv = DER_AsciiToTime(&now, find_field(data, "notBefore", PR_TRUE));
   543     } else {
   544 	now = PR_Now();
   545     }
   546     PR_ExplodeTime (now, PR_GMTParameters, &printableTime);
   547     if ( warpmonths ) {
   548 	printableTime.tm_month += warpmonths;
   549 	now = PR_ImplodeTime (&printableTime);
   550 	PR_ExplodeTime (now, PR_GMTParameters, &printableTime);
   551     }
   552     if (find_field_bool(data, "manValidity", PR_TRUE)) {
   553 	rv = DER_AsciiToTime(&after, find_field(data, "notAfter", PR_TRUE));
   554 	PR_ExplodeTime (after, PR_GMTParameters, &printableTime);
   555     } else {
   556 	printableTime.tm_month += 3;
   557 	after = PR_ImplodeTime (&printableTime);
   558     }
   559     /* note that the time is now in micro-second unit */
   560     validity = CERT_CreateValidity (now, after);
   562     if ( selfsign ) {
   563 	cert = CERT_CreateCertificate
   564 	    (serialNumber,&(req->subject), validity, req);
   565     } else {
   566 	cert = CERT_CreateCertificate
   567 	    (serialNumber,&(issuerCert->subject), validity, req);
   568     }
   570     CERT_DestroyValidity(validity);
   571     if ( issuerCert ) {
   572 	CERT_DestroyCertificate (issuerCert);
   573     }
   574     return(cert);
   575 }
   577 static int
   578 get_serial_number(Pair  *data)
   579 {
   580     int                 serial = 0;
   581     int                 error;
   582     char                *filename = SERIAL_FILE;
   583     char                *SN;
   584     FILE                *serialFile;
   587     if (find_field_bool(data, "serial-auto", PR_TRUE)) {
   588 	serialFile = fopen(filename, "r");
   589 	if (serialFile != NULL) {
   590 	    fread(&serial, sizeof(int), 1, serialFile);
   591 	    if (ferror(serialFile) != 0) {
   592 		error_out("Error: Unable to read serial number file");
   593 	    }
   594 	    if (serial == 4294967295) {
   595 		serial = 21;
   596 	    }
   597 	    fclose(serialFile);
   598 	    ++serial;
   599 	    serialFile = fopen(filename,"w");
   600 	    if (serialFile == NULL) {
   601 	        error_out("ERROR: Unable to open serial number file for writing");
   602 	    }
   603 	    fwrite(&serial, sizeof(int), 1, serialFile);
   604 	    if (ferror(serialFile) != 0) {
   605 		error_out("Error: Unable to write to serial number file");
   606 	    }
   607 	} else {
   608 	    fclose(serialFile);
   609 	    serialFile = fopen(filename,"w");
   610 	    if (serialFile == NULL) {
   611 		error_out("ERROR: Unable to open serial number file");
   612 	    }
   613 	    serial = 21;
   614 	    fwrite(&serial, sizeof(int), 1, serialFile);
   615 	    if (ferror(serialFile) != 0) {
   616 		error_out("Error: Unable to write to serial number file");
   617 	    }
   618 	    error = ferror(serialFile);
   619 	    if (error != 0) {
   620 		error_out("ERROR: Unable to write to serial file");
   621 	    }
   622 	}
   623 	fclose(serialFile);
   624     } else {
   625 	SN = find_field(data, "serial_value", PR_TRUE);
   626 	while (*SN != '\0') {
   627 	    serial = serial * 16;
   628 	    if ((*SN >= 'A') && (*SN <='F')) {
   629 		serial += *SN - 'A' + 10; 
   630 	    } else {
   631 		if ((*SN >= 'a') && (*SN <='f')) {
   632 		    serial += *SN - 'a' + 10;
   633 		} else {
   634 		    serial += *SN - '0';
   635 		}
   636 	    }
   637 	    ++SN;
   638 	}
   639     }
   640     return serial;
   641 }
   645 typedef SECStatus (* EXTEN_VALUE_ENCODER)
   646 		(PLArenaPool *extHandle, void *value, SECItem *encodedValue);
   648 static SECStatus 
   649 EncodeAndAddExtensionValue(
   650 	PLArenaPool          *arena,
   651 	void                 *extHandle, 
   652 	void                 *value, 
   653 	PRBool 		     criticality,
   654 	int 		     extenType, 
   655 	EXTEN_VALUE_ENCODER  EncodeValueFn)
   656 {
   657     SECItem                  encodedValue;
   658     SECStatus                rv;
   661     encodedValue.data = NULL;
   662     encodedValue.len = 0;
   663     rv = (*EncodeValueFn)(arena, value, &encodedValue);
   664     if (rv != SECSuccess) {
   665 	error_out("ERROR: Unable to encode extension value");
   666     }
   667     rv = CERT_AddExtension
   668 	(extHandle, extenType, &encodedValue, criticality, PR_TRUE);
   669     return (rv);
   670 }
   674 static SECStatus 
   675 AddKeyUsage (void  *extHandle, 
   676 	     Pair  *data)
   677 {
   678     SECItem        bitStringValue;
   679     unsigned char  keyUsage = 0x0;
   681     if (find_field_bool(data,"keyUsage-digitalSignature", PR_TRUE)){
   682 	keyUsage |= (0x80 >> 0);
   683     }
   684     if (find_field_bool(data,"keyUsage-nonRepudiation", PR_TRUE)){
   685 	keyUsage |= (0x80 >> 1);
   686     }
   687     if (find_field_bool(data,"keyUsage-keyEncipherment", PR_TRUE)){
   688 	keyUsage |= (0x80 >> 2);
   689     }
   690     if (find_field_bool(data,"keyUsage-dataEncipherment", PR_TRUE)){
   691 	keyUsage |= (0x80 >> 3);
   692     }
   693     if (find_field_bool(data,"keyUsage-keyAgreement", PR_TRUE)){
   694 	keyUsage |= (0x80 >> 4);
   695     }
   696     if (find_field_bool(data,"keyUsage-keyCertSign", PR_TRUE)) {
   697 	keyUsage |= (0x80 >> 5);
   698     }
   699     if (find_field_bool(data,"keyUsage-cRLSign", PR_TRUE)) {
   700 	keyUsage |= (0x80 >> 6);
   701     }
   703     bitStringValue.data = &keyUsage;
   704     bitStringValue.len = 1;
   706     return (CERT_EncodeAndAddBitStrExtension
   707 	    (extHandle, SEC_OID_X509_KEY_USAGE, &bitStringValue,
   708 	     (find_field_bool(data, "keyUsage-crit", PR_TRUE))));
   710 }
   712 static CERTOidSequence *
   713 CreateOidSequence(void)
   714 {
   715   CERTOidSequence *rv = (CERTOidSequence *)NULL;
   716   PLArenaPool *arena = (PLArenaPool *)NULL;
   718   arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   719   if( (PLArenaPool *)NULL == arena ) {
   720     goto loser;
   721   }
   723   rv = (CERTOidSequence *)PORT_ArenaZAlloc(arena, sizeof(CERTOidSequence));
   724   if( (CERTOidSequence *)NULL == rv ) {
   725     goto loser;
   726   }
   728   rv->oids = (SECItem **)PORT_ArenaZAlloc(arena, sizeof(SECItem *));
   729   if( (SECItem **)NULL == rv->oids ) {
   730     goto loser;
   731   }
   733   rv->arena = arena;
   734   return rv;
   736  loser:
   737   if( (PLArenaPool *)NULL != arena ) {
   738     PORT_FreeArena(arena, PR_FALSE);
   739   }
   741   return (CERTOidSequence *)NULL;
   742 }
   744 static SECStatus
   745 AddOidToSequence(CERTOidSequence *os, SECOidTag oidTag)
   746 {
   747   SECItem **oids;
   748   PRUint32 count = 0;
   749   SECOidData *od;
   751   od = SECOID_FindOIDByTag(oidTag);
   752   if( (SECOidData *)NULL == od ) {
   753     return SECFailure;
   754   }
   756   for( oids = os->oids; (SECItem *)NULL != *oids; oids++ ) {
   757     count++;
   758   }
   760   /* ArenaZRealloc */
   762   {
   763     PRUint32 i;
   765     oids = (SECItem **)PORT_ArenaZAlloc(os->arena, sizeof(SECItem *) * (count+2));
   766     if( (SECItem **)NULL == oids ) {
   767       return SECFailure;
   768     }
   770     for( i = 0; i < count; i++ ) {
   771       oids[i] = os->oids[i];
   772     }
   774     /* ArenaZFree(os->oids); */
   775   }
   777   os->oids = oids;
   778   os->oids[count] = &od->oid;
   780   return SECSuccess;
   781 }
   783 static SECItem *
   784 EncodeOidSequence(CERTOidSequence *os)
   785 {
   786   SECItem *rv;
   787   extern const SEC_ASN1Template CERT_OidSeqTemplate[];
   789   rv = (SECItem *)PORT_ArenaZAlloc(os->arena, sizeof(SECItem));
   790   if( (SECItem *)NULL == rv ) {
   791     goto loser;
   792   }
   794   if( !SEC_ASN1EncodeItem(os->arena, rv, os, CERT_OidSeqTemplate) ) {
   795     goto loser;
   796   }
   798   return rv;
   800  loser:
   801   return (SECItem *)NULL;
   802 }
   804 static SECStatus
   805 AddExtKeyUsage(void *extHandle, Pair *data)
   806 {
   807   SECStatus rv;
   808   CERTOidSequence *os;
   809   SECItem *value;
   810   PRBool crit;
   812   os = CreateOidSequence();
   813   if( (CERTOidSequence *)NULL == os ) {
   814     return SECFailure;
   815   }
   817   if( find_field_bool(data, "extKeyUsage-serverAuth", PR_TRUE) ) {
   818     rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_SERVER_AUTH);
   819     if( SECSuccess != rv ) goto loser;
   820   }
   822   if( find_field_bool(data, "extKeyUsage-msTrustListSign", PR_TRUE) ) {
   823     rv = AddOidToSequence(os, SEC_OID_MS_EXT_KEY_USAGE_CTL_SIGNING);
   824     if( SECSuccess != rv ) goto loser;
   825   }
   827   if( find_field_bool(data, "extKeyUsage-clientAuth", PR_TRUE) ) {
   828     rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH);
   829     if( SECSuccess != rv ) goto loser;
   830   }
   832   if( find_field_bool(data, "extKeyUsage-codeSign", PR_TRUE) ) {
   833     rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_CODE_SIGN);
   834     if( SECSuccess != rv ) goto loser;
   835   }
   837   if( find_field_bool(data, "extKeyUsage-emailProtect", PR_TRUE) ) {
   838     rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT);
   839     if( SECSuccess != rv ) goto loser;
   840   }
   842   if( find_field_bool(data, "extKeyUsage-timeStamp", PR_TRUE) ) {
   843     rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_TIME_STAMP);
   844     if( SECSuccess != rv ) goto loser;
   845   }
   847   if( find_field_bool(data, "extKeyUsage-ocspResponder", PR_TRUE) ) {
   848     rv = AddOidToSequence(os, SEC_OID_OCSP_RESPONDER);
   849     if( SECSuccess != rv ) goto loser;
   850   }
   852   if( find_field_bool(data, "extKeyUsage-NS-govtApproved", PR_TRUE) ) {
   853     rv = AddOidToSequence(os, SEC_OID_NS_KEY_USAGE_GOVT_APPROVED);
   854     if( SECSuccess != rv ) goto loser;
   855   }
   857   value = EncodeOidSequence(os);
   859   crit = find_field_bool(data, "extKeyUsage-crit", PR_TRUE);
   861   rv = CERT_AddExtension(extHandle, SEC_OID_X509_EXT_KEY_USAGE, value,
   862                          crit, PR_TRUE);
   863   /*FALLTHROUGH*/
   864  loser:
   865   CERT_DestroyOidSequence(os);
   866   return rv;
   867 }
   869 static SECStatus
   870 AddSubKeyID(void             *extHandle, 
   871 	    Pair             *data, 
   872 	    CERTCertificate  *subjectCert)
   873 {
   874     SECItem                  encodedValue;
   875     SECStatus                rv;
   876     char                     *read;
   877     char                     *write;
   878     char                     *first;
   879     char                     character;
   880     int                      high_digit = 0,
   881 	                     low_digit = 0;
   882     int                      len;
   883     PRBool                   odd = PR_FALSE;
   886     encodedValue.data = NULL;
   887     encodedValue.len = 0;
   888     first = read = write = find_field(data,"subjectKeyIdentifier-text", 
   889 				      PR_TRUE);
   890     len = PORT_Strlen(first);
   891     odd = ((len % 2) != 0 ) ? PR_TRUE : PR_FALSE;
   892     if (find_field_bool(data, "subjectKeyIdentifier-radio-hex", PR_TRUE)) {
   893 	if (odd) {
   894 	    error_out("ERROR: Improperly formated subject key identifier, hex values must be expressed as an octet string");
   895 	}
   896 	while (*read != '\0') {
   897 	    if (!isxdigit(*read)) {
   898 		error_out("ERROR: Improperly formated subject key identifier");
   899 	    }
   900 	    *read = toupper(*read);
   901 	    if ((*read >= 'A') && (*read <= 'F')) {
   902 		high_digit = *read - 'A' + 10;
   903 	    }  else {
   904 		high_digit = *read - '0';
   905 	    }
   906 	    ++read;
   907 	    if (!isxdigit(*read)) {
   908 		error_out("ERROR: Improperly formated subject key identifier");
   909 	    }
   910 	    *read = toupper(*read);
   911 	    if ((*read >= 'A') && (*read <= 'F')) {
   912 		low_digit = *(read) - 'A' + 10;
   913 	    } else {
   914 		low_digit = *(read) - '0';
   915 	    }
   916 	    character = (high_digit << 4) | low_digit;
   917 	    *write = character;
   918 	    ++write;
   919 	    ++read;
   920 	}
   921 	*write = '\0';
   922 	len = write - first;
   923     }
   924     subjectCert->subjectKeyID.data = (unsigned char *) find_field
   925 	(data,"subjectKeyIdentifier-text", PR_TRUE);
   926     subjectCert->subjectKeyID.len = len;
   927     rv = CERT_EncodeSubjectKeyID
   928 	(NULL, &subjectCert->subjectKeyID, &encodedValue);
   929     if (rv) {
   930 	return (rv);
   931     }
   932     return (CERT_AddExtension(extHandle,  SEC_OID_X509_SUBJECT_KEY_ID, 
   933 			      &encodedValue, PR_FALSE, PR_TRUE));
   934 }
   937 static SECStatus 
   938 AddAuthKeyID (void              *extHandle,
   939 	      Pair              *data, 
   940 	      char              *issuerNameStr, 
   941 	      CERTCertDBHandle  *handle)
   942 {
   943     CERTAuthKeyID               *authKeyID = NULL;    
   944     PLArenaPool                 *arena = NULL;
   945     SECStatus                   rv = SECSuccess;
   946     CERTCertificate             *issuerCert = NULL;
   947     CERTGeneralName             *genNames;
   948     CERTName                    *directoryName = NULL;
   951     issuerCert = CERT_FindCertByNameString(handle, issuerNameStr);
   952     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   953     if ( !arena ) {
   954 	error_allocate();
   955     }
   957     authKeyID = PORT_ArenaZAlloc (arena, sizeof (CERTAuthKeyID));
   958     if (authKeyID == NULL) {
   959 	error_allocate();
   960     }
   961     if (find_field_bool(data, "authorityKeyIdentifier-radio-keyIdentifier", 
   962 			PR_TRUE)) {
   963 	authKeyID->keyID.data = PORT_ArenaAlloc (arena, PORT_Strlen 
   964 				       ((char *)issuerCert->subjectKeyID.data));
   965 	if (authKeyID->keyID.data == NULL) {
   966 	    error_allocate();
   967 	}
   968 	PORT_Memcpy (authKeyID->keyID.data, issuerCert->subjectKeyID.data, 
   969 		     authKeyID->keyID.len = 
   970 		        PORT_Strlen((char *)issuerCert->subjectKeyID.data));
   971     } else {
   973 	PORT_Assert (arena);
   974 	genNames = (CERTGeneralName *) PORT_ArenaZAlloc (arena, (sizeof(CERTGeneralName)));
   975 	if (genNames == NULL){
   976 	    error_allocate();
   977 	}
   978 	genNames->l.next = genNames->l.prev = &(genNames->l);
   979 	genNames->type = certDirectoryName;
   981 	directoryName = CERT_AsciiToName(issuerCert->subjectName);
   982 	if (!directoryName) {
   983 	    error_out("ERROR: Unable to create Directory Name");
   984 	}
   985 	rv = CERT_CopyName (arena, &genNames->name.directoryName, 
   986 			    directoryName);
   987         CERT_DestroyName (directoryName);
   988 	if (rv != SECSuccess) {
   989 	    error_out("ERROR: Unable to copy Directory Name");
   990 	}
   991 	authKeyID->authCertIssuer = genNames;
   992 	if (authKeyID->authCertIssuer == NULL && SECFailure == 
   993 	                                            PORT_GetError ()) {
   994 	    error_out("ERROR: Unable to get Issuer General Name for Authority Key ID Extension");
   995 	}
   996 	authKeyID->authCertSerialNumber = issuerCert->serialNumber;
   997     }
   998     rv = EncodeAndAddExtensionValue(arena, extHandle, authKeyID, PR_FALSE, 
   999 				    SEC_OID_X509_AUTH_KEY_ID, 
  1000 				    (EXTEN_VALUE_ENCODER)
  1001 				    CERT_EncodeAuthKeyID);
  1002     if (arena) {
  1003 	PORT_FreeArena (arena, PR_FALSE);
  1005     return (rv);
  1009 static SECStatus 
  1010 AddPrivKeyUsagePeriod(void             *extHandle, 
  1011 		      Pair             *data, 
  1012 		      CERTCertificate  *cert)
  1014     char *notBeforeStr;
  1015     char *notAfterStr;
  1016     PLArenaPool *arena = NULL;
  1017     SECStatus rv = SECSuccess;
  1018     CERTPrivKeyUsagePeriod *pkup;
  1021     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1022     if ( !arena ) {
  1023 	error_allocate();
  1025     pkup = PORT_ArenaZNew (arena, CERTPrivKeyUsagePeriod);
  1026     if (pkup == NULL) {
  1027 	error_allocate();
  1029     notBeforeStr = (char *) PORT_Alloc(16 );
  1030     notAfterStr = (char *) PORT_Alloc(16 );
  1031     *notBeforeStr = '\0';
  1032     *notAfterStr = '\0';
  1033     pkup->arena = arena;
  1034     pkup->notBefore.len = 0;
  1035     pkup->notBefore.data = NULL;
  1036     pkup->notAfter.len = 0;
  1037     pkup->notAfter.data = NULL;
  1038     if (find_field_bool(data, "privKeyUsagePeriod-radio-notBefore", PR_TRUE) ||
  1039 	find_field_bool(data, "privKeyUsagePeriod-radio-both", PR_TRUE)) {
  1040 	pkup->notBefore.len = 15;
  1041 	pkup->notBefore.data = (unsigned char *)notBeforeStr;
  1042 	if (find_field_bool(data, "privKeyUsagePeriod-notBefore-radio-manual", 
  1043 			    PR_TRUE)) {
  1044 	    PORT_Strcat(notBeforeStr,find_field(data,
  1045 					   "privKeyUsagePeriod-notBefore-year",
  1046 					   PR_TRUE));
  1047 	    PORT_Strcat(notBeforeStr,find_field(data,
  1048 					   "privKeyUsagePeriod-notBefore-month",
  1049 					   PR_TRUE));
  1050 	    PORT_Strcat(notBeforeStr,find_field(data,
  1051 					   "privKeyUsagePeriod-notBefore-day",
  1052 					   PR_TRUE));
  1053 	    PORT_Strcat(notBeforeStr,find_field(data,
  1054 					   "privKeyUsagePeriod-notBefore-hour",
  1055 					   PR_TRUE));
  1056 	    PORT_Strcat(notBeforeStr,find_field(data,
  1057 					  "privKeyUsagePeriod-notBefore-minute",
  1058 					   PR_TRUE));
  1059 	    PORT_Strcat(notBeforeStr,find_field(data,
  1060 					  "privKeyUsagePeriod-notBefore-second",
  1061 					   PR_TRUE));
  1062 	    if ((*(notBeforeStr + 14) != '\0') ||
  1063 		(!isdigit(*(notBeforeStr + 13))) ||
  1064 		(*(notBeforeStr + 12) >= '5' && *(notBeforeStr + 12) <= '0') ||
  1065 		(!isdigit(*(notBeforeStr + 11))) ||
  1066 		(*(notBeforeStr + 10) >= '5' && *(notBeforeStr + 10) <= '0') ||
  1067 		(!isdigit(*(notBeforeStr + 9))) ||
  1068 		(*(notBeforeStr + 8) >= '2' && *(notBeforeStr + 8) <= '0') ||
  1069 		(!isdigit(*(notBeforeStr + 7))) ||
  1070 		(*(notBeforeStr + 6) >= '3' && *(notBeforeStr + 6) <= '0') ||
  1071 		(!isdigit(*(notBeforeStr + 5))) ||
  1072 		(*(notBeforeStr + 4) >= '1' && *(notBeforeStr + 4) <= '0') ||
  1073 		(!isdigit(*(notBeforeStr + 3))) ||
  1074 		(!isdigit(*(notBeforeStr + 2))) ||
  1075 		(!isdigit(*(notBeforeStr + 1))) ||
  1076 		(!isdigit(*(notBeforeStr + 0))) ||
  1077 		(*(notBeforeStr + 8) == '2' && *(notBeforeStr + 9) >= '4') ||
  1078 		(*(notBeforeStr + 6) == '3' && *(notBeforeStr + 7) >= '1') ||
  1079 		(*(notBeforeStr + 4) == '1' && *(notBeforeStr + 5) >= '2')) {
  1080 		error_out("ERROR: Improperly formated private key usage period");
  1082 	    *(notBeforeStr + 14) = 'Z';
  1083 	    *(notBeforeStr + 15) = '\0';
  1084 	} else {
  1085 	    if ((*(cert->validity.notBefore.data) > '5') || 
  1086 		((*(cert->validity.notBefore.data) == '5') &&
  1087 		 (*(cert->validity.notBefore.data + 1) != '0'))) {
  1088 		PORT_Strcat(notBeforeStr, "19");
  1089 	    } else {
  1090 		PORT_Strcat(notBeforeStr, "20");
  1092 	    PORT_Strcat(notBeforeStr, (char *)cert->validity.notBefore.data);
  1095     if (find_field_bool(data, "privKeyUsagePeriod-radio-notAfter", PR_TRUE) ||
  1096 	find_field_bool(data, "privKeyUsagePeriod-radio-both", PR_TRUE)) {
  1097 	pkup->notAfter.len = 15;
  1098 	pkup->notAfter.data = (unsigned char *)notAfterStr;
  1099 	PORT_Strcat(notAfterStr,find_field(data,"privKeyUsagePeriod-notAfter-year", 
  1100 				      PR_TRUE));
  1101 	PORT_Strcat(notAfterStr,find_field(data,"privKeyUsagePeriod-notAfter-month",
  1102 				      PR_TRUE));
  1103 	PORT_Strcat(notAfterStr,find_field(data,"privKeyUsagePeriod-notAfter-day", 
  1104 				      PR_TRUE));
  1105 	PORT_Strcat(notAfterStr,find_field(data,"privKeyUsagePeriod-notAfter-hour", 
  1106 				      PR_TRUE));
  1107 	PORT_Strcat(notAfterStr,find_field(data,"privKeyUsagePeriod-notAfter-minute",
  1108 				      PR_TRUE));
  1109 	PORT_Strcat(notAfterStr,find_field(data,"privKeyUsagePeriod-notAfter-second",
  1110 				      PR_TRUE));
  1111 	if ((*(notAfterStr + 14) != '\0') ||
  1112 	    (!isdigit(*(notAfterStr + 13))) ||
  1113 	    (*(notAfterStr + 12) >= '5' && *(notAfterStr + 12) <= '0') ||
  1114 	    (!isdigit(*(notAfterStr + 11))) ||
  1115 	    (*(notAfterStr + 10) >= '5' && *(notAfterStr + 10) <= '0') ||
  1116 	    (!isdigit(*(notAfterStr + 9))) ||
  1117 	    (*(notAfterStr + 8) >= '2' && *(notAfterStr + 8) <= '0') ||
  1118 	    (!isdigit(*(notAfterStr + 7))) ||
  1119 	    (*(notAfterStr + 6) >= '3' && *(notAfterStr + 6) <= '0') ||
  1120 	    (!isdigit(*(notAfterStr + 5))) ||
  1121 	    (*(notAfterStr + 4) >= '1' && *(notAfterStr + 4) <= '0') ||
  1122 	    (!isdigit(*(notAfterStr + 3))) ||
  1123 	    (!isdigit(*(notAfterStr + 2))) ||
  1124 	    (!isdigit(*(notAfterStr + 1))) ||
  1125 	    (!isdigit(*(notAfterStr + 0))) ||
  1126 	    (*(notAfterStr + 8) == '2' && *(notAfterStr + 9) >= '4') ||
  1127 	    (*(notAfterStr + 6) == '3' && *(notAfterStr + 7) >= '1') ||
  1128 	    (*(notAfterStr + 4) == '1' && *(notAfterStr + 5) >= '2')) {
  1129 	    error_out("ERROR: Improperly formated private key usage period");
  1131 	*(notAfterStr + 14) = 'Z';
  1132 	*(notAfterStr + 15) = '\0';
  1135     PORT_Assert (arena);
  1137     rv = EncodeAndAddExtensionValue(arena, extHandle, pkup, 
  1138 				    find_field_bool(data,
  1139 						    "privKeyUsagePeriod-crit", 
  1140 						    PR_TRUE), 
  1141 				    SEC_OID_X509_PRIVATE_KEY_USAGE_PERIOD, 
  1142 				    (EXTEN_VALUE_ENCODER)
  1143 				    CERT_EncodePrivateKeyUsagePeriod);
  1144     if (arena) {
  1145 	PORT_FreeArena (arena, PR_FALSE);
  1147     if (notBeforeStr != NULL) {
  1148 	PORT_Free(notBeforeStr);
  1150     if (notAfterStr != NULL) {
  1151 	PORT_Free(notAfterStr);
  1153     return (rv);
  1156 static SECStatus 
  1157 AddBasicConstraint(void   *extHandle, 
  1158 		   Pair   *data)
  1160     CERTBasicConstraints  basicConstraint;
  1161     SECItem               encodedValue;
  1162     SECStatus             rv;
  1164     encodedValue.data = NULL;
  1165     encodedValue.len = 0;
  1166     basicConstraint.pathLenConstraint = CERT_UNLIMITED_PATH_CONSTRAINT;
  1167     basicConstraint.isCA = (find_field_bool(data,"basicConstraints-cA-radio-CA",
  1168 					    PR_TRUE));
  1169     if (find_field_bool(data,"basicConstraints-pathLengthConstraint", PR_TRUE)){
  1170 	basicConstraint.pathLenConstraint = atoi 
  1171 	    (find_field(data,"basicConstraints-pathLengthConstraint-text", 
  1172 			PR_TRUE));
  1175     rv = CERT_EncodeBasicConstraintValue (NULL, &basicConstraint, 
  1176 					  &encodedValue);
  1177     if (rv)
  1178 	return (rv);
  1179     rv = CERT_AddExtension(extHandle, SEC_OID_X509_BASIC_CONSTRAINTS, 
  1180 			   &encodedValue, 
  1181 			   (find_field_bool(data,"basicConstraints-crit", 
  1182 					    PR_TRUE)), PR_TRUE);
  1184     PORT_Free (encodedValue.data);
  1185     return (rv);
  1190 static SECStatus 
  1191 AddNscpCertType (void  *extHandle, 
  1192 		 Pair  *data)
  1194     SECItem            bitStringValue;
  1195     unsigned char      CertType = 0x0;
  1197     if (find_field_bool(data,"netscape-cert-type-ssl-client", PR_TRUE)){
  1198 	CertType |= (0x80 >> 0);
  1200     if (find_field_bool(data,"netscape-cert-type-ssl-server", PR_TRUE)){
  1201 	CertType |= (0x80 >> 1);
  1203     if (find_field_bool(data,"netscape-cert-type-smime", PR_TRUE)){
  1204 	CertType |= (0x80 >> 2);
  1206     if (find_field_bool(data,"netscape-cert-type-object-signing", PR_TRUE)){
  1207 	CertType |= (0x80 >> 3);
  1209     if (find_field_bool(data,"netscape-cert-type-reserved", PR_TRUE)){
  1210 	CertType |= (0x80 >> 4);
  1212     if (find_field_bool(data,"netscape-cert-type-ssl-ca", PR_TRUE)) {
  1213 	CertType |= (0x80 >> 5);
  1215     if (find_field_bool(data,"netscape-cert-type-smime-ca", PR_TRUE)) {
  1216 	CertType |= (0x80 >> 6);
  1218     if (find_field_bool(data,"netscape-cert-type-object-signing-ca", PR_TRUE)) {
  1219 	CertType |= (0x80 >> 7);
  1222     bitStringValue.data = &CertType;
  1223     bitStringValue.len = 1;
  1225     return (CERT_EncodeAndAddBitStrExtension
  1226 	    (extHandle, SEC_OID_NS_CERT_EXT_CERT_TYPE, &bitStringValue,
  1227 	     (find_field_bool(data, "netscape-cert-type-crit", PR_TRUE))));
  1231 static SECStatus
  1232 add_IA5StringExtension(void    *extHandle, 
  1233 		       char    *string, 
  1234 		       PRBool  crit, 
  1235 		       int     idtag)
  1237     SECItem                    encodedValue;
  1238     SECStatus                  rv;
  1240     encodedValue.data = NULL;
  1241     encodedValue.len = 0;
  1243     rv = CERT_EncodeIA5TypeExtension(NULL, string, &encodedValue);
  1244     if (rv) {
  1245 	return (rv);
  1247     return (CERT_AddExtension(extHandle, idtag, &encodedValue, crit, PR_TRUE));
  1250 static SECItem *
  1251 string_to_oid(char  *string)
  1253     int             i;
  1254     int             length = 20;
  1255     int             remaining;
  1256     int             first_value;
  1257     int             second_value;
  1258     int             value;
  1259     int             oidLength;
  1260     unsigned char   *oidString;
  1261     unsigned char   *write;
  1262     unsigned char   *read;
  1263     unsigned char   *temp;
  1264     SECItem         *oid;
  1267     remaining = length;
  1268     i = 0;
  1269     while (*string == ' ') {
  1270 	string++;
  1272     while (isdigit(*(string + i))) {
  1273 	i++;
  1275     if (*(string + i) == '.') {
  1276 	*(string + i) = '\0';
  1277     } else {
  1278 	error_out("ERROR: Improperly formated OID");
  1280     first_value = atoi(string);
  1281     if (first_value < 0 || first_value > 2) {
  1282 	error_out("ERROR: Improperly formated OID");
  1284     string += i + 1;
  1285     i = 0;
  1286     while (isdigit(*(string + i))) {
  1287 	i++;
  1289     if (*(string + i) == '.') {
  1290 	*(string + i) = '\0';
  1291     } else {
  1292 	error_out("ERROR: Improperly formated OID");
  1294     second_value = atoi(string);
  1295     if (second_value < 0 || second_value > 39) {
  1296 	error_out("ERROR: Improperly formated OID");
  1298     oidString = PORT_ZAlloc(2);
  1299     *oidString = (first_value * 40) + second_value;
  1300     *(oidString + 1) = '\0';
  1301     oidLength = 1;
  1302     string += i + 1;
  1303     i = 0;
  1304     temp = write = PORT_ZAlloc(length);
  1305     while (*string != '\0') {
  1306 	value = 0;
  1307 	while(isdigit(*(string + i))) {
  1308 	    i++;
  1310 	if (*(string + i) == '\0') {
  1311 	    value = atoi(string);
  1312 	    string += i;
  1313 	} else {
  1314 	    if (*(string + i) == '.') {
  1315 		*(string + i) = '\0';
  1316 		value = atoi(string);
  1317 		string += i + 1;
  1318 	    } else {
  1319 		*(string + i) = '\0';
  1320 		i++;
  1321 		value = atoi(string);
  1322 		while (*(string + i) == ' ')
  1323 		    i++;
  1324 		if (*(string + i) != '\0') {
  1325 		    error_out("ERROR: Improperly formated OID");
  1329 	i = 0;
  1330 	while (value != 0) {
  1331 	    if (remaining < 1) {
  1332 		remaining += length;
  1333 		length = length * 2;
  1334 		temp = PORT_Realloc(temp, length);
  1335 		write = temp + length - remaining;
  1337 	    *write = (value & 0x7f) | (0x80);
  1338 	    write++;
  1339 	    remaining--;
  1340 	    value = value >> 7;
  1342 	*temp = *temp & (0x7f);
  1343 	oidLength += write - temp;
  1344 	oidString = PORT_Realloc(oidString, (oidLength + 1));
  1345 	read = write - 1;
  1346 	write = oidLength + oidString - 1;
  1347 	for (i = 0; i < (length - remaining); i++) {
  1348 	    *write = *read;
  1349 	    write--;
  1350 	    read++;
  1352 	write = temp;
  1353 	remaining = length;
  1355     *(oidString + oidLength) = '\0';
  1356     oid = (SECItem *) PORT_ZAlloc(sizeof(SECItem));
  1357     oid->data = oidString;
  1358     oid->len  = oidLength;
  1359     PORT_Free(temp);
  1360     return oid;
  1363 static SECItem *
  1364 string_to_ipaddress(char *string)
  1366     int      i = 0;
  1367     int      value;
  1368     int      j = 0;
  1369     SECItem  *ipaddress;
  1372     while (*string == ' ') {
  1373 	string++;
  1375     ipaddress = (SECItem *) PORT_ZAlloc(sizeof(SECItem));
  1376     ipaddress->data = PORT_ZAlloc(9);
  1377     while (*string != '\0' && j < 8) {
  1378 	while (isdigit(*(string + i))) {
  1379 	    i++;
  1381 	if (*(string + i) == '.') {
  1382 	    *(string + i) = '\0';
  1383 	    value = atoi(string);
  1384 	    string = string + i + 1;
  1385 	    i = 0;
  1386 	} else {
  1387 	    if (*(string + i) == '\0') {
  1388 		value = atoi(string);
  1389 		string = string + i;
  1390 		i = 0;
  1391 	    } else {
  1392 		*(string + i) = '\0';
  1393 		while (*(string + i) == ' ') {
  1394 		    i++;
  1396 		if (*(string + i) == '\0') {
  1397 		    value = atoi(string);
  1398 		    string = string + i;
  1399 		    i = 0;
  1400 		} else {
  1401 		    error_out("ERROR: Improperly formated IP Address");
  1405 	if (value >= 0 && value < 256) {
  1406 	    *(ipaddress->data + j) = value;
  1407 	} else {
  1408 	    error_out("ERROR: Improperly formated IP Address");
  1410 	j++;
  1412     *(ipaddress->data + j) = '\0';
  1413     if (j != 4 && j != 8) {
  1414 	error_out("ERROR: Improperly formated IP Address");
  1416     ipaddress->len = j;
  1417     return ipaddress;
  1420 static SECItem *
  1421 string_to_binary(char  *string)
  1423     SECItem            *rv;
  1424     int                high_digit;
  1425     int                low_digit;
  1427     rv = (SECItem *) PORT_ZAlloc(sizeof(SECItem));
  1428     if (rv == NULL) {
  1429 	error_allocate();
  1431     rv->data = (unsigned char *) PORT_ZAlloc((PORT_Strlen(string))/3 + 2);
  1432     while (!isxdigit(*string)) {
  1433 	string++;
  1435     rv->len = 0;
  1436     while (*string != '\0') {
  1437 	if (isxdigit(*string)) {
  1438 	    if (*string >= '0' && *string <= '9') {
  1439 		high_digit = *string - '0';
  1440 	    } else {
  1441 		*string = toupper(*string);
  1442 		high_digit = *string - 'A' + 10;
  1444 	    string++;
  1445 	    if (*string >= '0' && *string <= '9') {
  1446 		low_digit = *string - '0';
  1447 	    } else {
  1448 		*string = toupper(*string);
  1449 		low_digit = *string - 'A' + 10;
  1451 	    (rv->len)++;
  1452 	} else {
  1453 	    if (*string == ':') {
  1454 		string++;
  1455 	    } else {
  1456 		if (*string == ' ') {
  1457 		    while (*string == ' ') {
  1458 			string++;
  1461 		if (*string != '\0') {
  1462 		    error_out("ERROR: Improperly formated binary encoding");
  1468     return rv;
  1471 static SECStatus
  1472 MakeGeneralName(char             *name, 
  1473 		CERTGeneralName  *genName,
  1474 		PLArenaPool      *arena)
  1476     SECItem                      *oid;
  1477     SECOidData                   *oidData;
  1478     SECItem                      *ipaddress;
  1479     SECItem                      *temp = NULL;
  1480     int                          i;
  1481     int                          nameType;
  1482     PRBool                       binary = PR_FALSE;
  1483     SECStatus                    rv = SECSuccess;
  1484     PRBool                       nickname = PR_FALSE;
  1486     PORT_Assert(genName);
  1487     PORT_Assert(arena);
  1488     nameType = *(name + PORT_Strlen(name) - 1) - '0';
  1489     if (nameType == 0  && *(name +PORT_Strlen(name) - 2) == '1') {
  1490 	nickname = PR_TRUE;
  1491 	nameType = certOtherName;
  1493     if (nameType < 1 || nameType > 9) {
  1494 	error_out("ERROR: Unknown General Name Type");
  1496     *(name + PORT_Strlen(name) - 4) = '\0';
  1497     genName->type = nameType;
  1499     switch (genName->type) {
  1500       case certURI:
  1501       case certRFC822Name:
  1502       case certDNSName: {
  1503 	  genName->name.other.data = (unsigned char *)name;
  1504 	  genName->name.other.len = PORT_Strlen(name);
  1505 	  break;
  1508       case certIPAddress: {
  1509 	  ipaddress = string_to_ipaddress(name);
  1510 	  genName->name.other.data = ipaddress->data;
  1511 	  genName->name.other.len = ipaddress->len;
  1512 	  break;
  1515       case certRegisterID: {
  1516 	  oid = string_to_oid(name);
  1517 	  genName->name.other.data = oid->data;
  1518 	  genName->name.other.len = oid->len;
  1519 	  break;
  1522       case certEDIPartyName:
  1523       case certX400Address: {
  1525 	  genName->name.other.data = PORT_ArenaAlloc (arena, 
  1526 						      PORT_Strlen (name) + 2);
  1527 	  if (genName->name.other.data == NULL) {
  1528 	      error_allocate();
  1531 	  PORT_Memcpy (genName->name.other.data + 2, name, PORT_Strlen (name));
  1532 	  /* This may not be accurate for all cases.  
  1533 	     For now, use this tag type */
  1534 	  genName->name.other.data[0] = (char)(((genName->type - 1) & 
  1535 						0x1f)| 0x80);
  1536 	  genName->name.other.data[1] = (char)PORT_Strlen (name);
  1537 	  genName->name.other.len = PORT_Strlen (name) + 2;
  1538 	  break;
  1541       case certOtherName: {
  1542 	  i = 0;
  1543 	  if (!nickname) {
  1544 	      while (!isdigit(*(name + PORT_Strlen(name) - i))) {
  1545 		  i++;
  1547 	      if (*(name + PORT_Strlen(name) - i) == '1') {
  1548 		  binary = PR_TRUE;
  1549 	      } else {
  1550 		  binary = PR_FALSE;
  1552 	      while (*(name + PORT_Strlen(name) - i) != '-') {
  1553 		  i++;
  1555 	      *(name + PORT_Strlen(name) - i - 1) = '\0';
  1556 	      i = 0;
  1557 	      while (*(name + i) != '-') {
  1558 		  i++;
  1560 	      *(name + i - 1) = '\0';
  1561 	      oid = string_to_oid(name + i + 2);
  1562 	  } else {
  1563 	      oidData = SECOID_FindOIDByTag(SEC_OID_NETSCAPE_NICKNAME);
  1564 	      oid = &oidData->oid;
  1565 	      while (*(name + PORT_Strlen(name) - i) != '-') {
  1566 		  i++;
  1568 	      *(name + PORT_Strlen(name) - i) = '\0';
  1570 	  genName->name.OthName.oid.data = oid->data;
  1571 	  genName->name.OthName.oid.len  = oid->len;
  1572 	  if (binary) {
  1573 	      temp = string_to_binary(name);
  1574 	      genName->name.OthName.name.data = temp->data;
  1575 	      genName->name.OthName.name.len = temp->len;
  1576 	  } else {
  1577 	      temp = (SECItem *) PORT_ZAlloc(sizeof(SECItem));
  1578 	      if (temp == NULL) {
  1579 		  error_allocate();
  1581 	      temp->data = (unsigned char *)name;
  1582 	      temp->len = PORT_Strlen(name);
  1583 	      SEC_ASN1EncodeItem (arena, &(genName->name.OthName.name), temp,
  1584 				  CERTIA5TypeTemplate);
  1586 	  PORT_Free(temp);
  1587 	  break;
  1590       case certDirectoryName: {
  1591 	  CERTName *directoryName = NULL;
  1593 	  directoryName = CERT_AsciiToName (name);
  1594 	  if (!directoryName) {
  1595 	      error_out("ERROR: Improperly formated alternative name");
  1596 	      break;
  1598 	  rv = CERT_CopyName (arena, &genName->name.directoryName, 
  1599 			      directoryName);
  1600 	  CERT_DestroyName (directoryName);
  1602 	  break;
  1605     genName->l.next = &(genName->l);
  1606     genName->l.prev = &(genName->l);
  1607     return rv;
  1611 static CERTGeneralName *
  1612 MakeAltName(Pair             *data, 
  1613 	    char             *which, 
  1614 	    PLArenaPool      *arena)
  1616     CERTGeneralName          *SubAltName;
  1617     CERTGeneralName          *current;
  1618     CERTGeneralName          *newname;
  1619     char                     *name = NULL;
  1620     SECStatus                rv = SECSuccess;
  1621     int                      len;
  1624     len = PORT_Strlen(which);
  1625     name = find_field(data, which, PR_TRUE);
  1626     SubAltName = current = (CERTGeneralName *) PORT_ZAlloc
  1627 	                                        (sizeof(CERTGeneralName));
  1628     if (current == NULL) {
  1629 	error_allocate();
  1631     while (name != NULL) {
  1633 	rv = MakeGeneralName(name, current, arena);
  1635 	if (rv != SECSuccess) {
  1636 	    break;
  1638 	if (*(which + len -1) < '9') {
  1639 	    *(which + len - 1) = *(which + len - 1) + 1;
  1640 	} else {
  1641 	    if (isdigit(*(which + len - 2) )) {
  1642 		*(which + len - 2) = *(which + len - 2) + 1;
  1643 		*(which + len - 1) = '0';
  1644 	    } else {
  1645 		*(which + len - 1) = '1';
  1646 		*(which + len) = '0';
  1647 		*(which + len + 1) = '\0';
  1648 		len++;
  1651 	len = PORT_Strlen(which);
  1652 	name = find_field(data, which, PR_TRUE);
  1653 	if (name != NULL) {
  1654 	    newname = (CERTGeneralName *) PORT_ZAlloc(sizeof(CERTGeneralName));
  1655 	    if (newname == NULL) {
  1656 		error_allocate();
  1658 	    current->l.next = &(newname->l);
  1659 	    newname->l.prev = &(current->l);
  1660 	    current = newname;
  1661             newname = NULL;
  1662 	} else {
  1663 	    current->l.next = &(SubAltName->l);
  1664 	    SubAltName->l.prev = &(current->l);
  1667     if (rv == SECFailure) {
  1668 	return NULL;
  1670     return SubAltName;
  1673 static CERTNameConstraints *
  1674 MakeNameConstraints(Pair             *data, 
  1675 		    PLArenaPool      *arena)
  1677     CERTNameConstraints      *NameConstraints;
  1678     CERTNameConstraint       *current = NULL;
  1679     CERTNameConstraint       *last_permited = NULL;
  1680     CERTNameConstraint       *last_excluded = NULL;
  1681     char                     *constraint = NULL;
  1682     char                     *which;
  1683     SECStatus                rv = SECSuccess;
  1684     int                      len;
  1685     int                      i;
  1686     long                     max;
  1687     long                     min;
  1688     PRBool                   permited;
  1691     NameConstraints = (CERTNameConstraints *) PORT_ZAlloc
  1692 	                            (sizeof(CERTNameConstraints));
  1693     which = make_copy_string("NameConstraintSelect0", 25,'\0');
  1694     len = PORT_Strlen(which);
  1695     constraint = find_field(data, which, PR_TRUE);
  1696     NameConstraints->permited = NameConstraints->excluded = NULL;
  1697     while (constraint != NULL) {
  1698 	current = (CERTNameConstraint *) PORT_ZAlloc
  1699 	                       (sizeof(CERTNameConstraint));
  1700 	if (current == NULL) {
  1701 	    error_allocate();
  1703 	i = 0;
  1704 	while (*(constraint + PORT_Strlen(constraint) - i) != '-') {
  1705 	    i++;
  1707         *(constraint + PORT_Strlen(constraint) - i - 1) = '\0'; 
  1708 	max = (long) atoi(constraint + PORT_Strlen(constraint) + 3);
  1709 	if (max > 0) {
  1710 	    (void) SEC_ASN1EncodeInteger(arena, &current->max, max);
  1712 	i = 0;
  1713 	while (*(constraint + PORT_Strlen(constraint) - i) != '-') {
  1714 	    i++;
  1716         *(constraint + PORT_Strlen(constraint) - i - 1) = '\0';
  1717 	min = (long) atoi(constraint + PORT_Strlen(constraint) + 3);
  1718 	(void) SEC_ASN1EncodeInteger(arena, &current->min, min);
  1719 	while (*(constraint + PORT_Strlen(constraint) - i) != '-') {
  1720 	    i++;
  1722         *(constraint + PORT_Strlen(constraint) - i - 1) = '\0';
  1723 	if (*(constraint + PORT_Strlen(constraint) + 3) == 'p') {
  1724 	    permited = PR_TRUE;
  1725 	} else {
  1726 	    permited = PR_FALSE;
  1728 	rv = MakeGeneralName(constraint, &(current->name), arena);
  1730 	if (rv != SECSuccess) {
  1731 	    break;
  1733 	if (*(which + len - 1) < '9') {
  1734 	    *(which + len - 1) = *(which + len - 1) + 1;
  1735 	} else {
  1736 	    if (isdigit(*(which + len - 2) )) {
  1737 		*(which + len - 2) = *(which + len - 2) + 1;
  1738 		*(which + len - 1) = '0';
  1739 	    } else {
  1740 		*(which + len - 1) = '1';
  1741 		*(which + len) = '0';
  1742 		*(which + len + 1) = '\0';
  1743 		len++;
  1746 	len = PORT_Strlen(which);
  1747 	if (permited) {
  1748 	    if (NameConstraints->permited == NULL) {
  1749 		NameConstraints->permited = last_permited = current;
  1751 	    last_permited->l.next = &(current->l);
  1752 	    current->l.prev = &(last_permited->l);
  1753 	    last_permited = current;
  1754 	} else {
  1755 	    if (NameConstraints->excluded == NULL) {
  1756 		NameConstraints->excluded = last_excluded = current;
  1758 	    last_excluded->l.next = &(current->l);
  1759 	    current->l.prev = &(last_excluded->l);
  1760 	    last_excluded = current;
  1762 	constraint = find_field(data, which, PR_TRUE);
  1763 	if (constraint != NULL) {
  1764 	    current = (CERTNameConstraint *) PORT_ZAlloc(sizeof(CERTNameConstraint));
  1765 	    if (current == NULL) {
  1766 		error_allocate();
  1770     if (NameConstraints->permited != NULL) {
  1771 	last_permited->l.next = &(NameConstraints->permited->l);
  1772 	NameConstraints->permited->l.prev = &(last_permited->l);
  1774     if (NameConstraints->excluded != NULL) {
  1775 	last_excluded->l.next = &(NameConstraints->excluded->l);
  1776 	NameConstraints->excluded->l.prev = &(last_excluded->l);
  1778     if (which != NULL) {
  1779 	PORT_Free(which);
  1781     if (rv == SECFailure) {
  1782 	return NULL;
  1784     return NameConstraints;
  1789 static SECStatus
  1790 AddAltName(void              *extHandle,
  1791 	   Pair              *data,
  1792 	   char              *issuerNameStr, 
  1793 	   CERTCertDBHandle  *handle,
  1794 	   int               type)
  1796     PRBool             autoIssuer = PR_FALSE;
  1797     PLArenaPool        *arena = NULL;
  1798     CERTGeneralName    *genName = NULL;
  1799     char               *which = NULL;
  1800     char               *name = NULL;
  1801     SECStatus          rv = SECSuccess;
  1802     SECItem            *issuersAltName = NULL;
  1803     CERTCertificate    *issuerCert = NULL;
  1805     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1806     if (arena == NULL) {
  1807 	error_allocate();
  1809     if (type == 0) {
  1810 	which = make_copy_string("SubAltNameSelect0", 20,'\0');
  1811 	genName = MakeAltName(data, which, arena);
  1812     } else {
  1813 	if (autoIssuer) {
  1814 	    autoIssuer = find_field_bool(data,"IssuerAltNameSourceRadio-auto",
  1815 					 PR_TRUE);
  1816 	    issuerCert = CERT_FindCertByNameString(handle, issuerNameStr);
  1817 	    rv = cert_FindExtension((*issuerCert).extensions, 
  1818 				    SEC_OID_X509_SUBJECT_ALT_NAME, 
  1819 				    issuersAltName);
  1820 	    if (issuersAltName == NULL) {
  1821 		name = PORT_Alloc(PORT_Strlen((*issuerCert).subjectName) + 4);
  1822 		PORT_Strcpy(name, (*issuerCert).subjectName);
  1823 		PORT_Strcat(name, " - 5");
  1825 	} else {
  1826 	    which = make_copy_string("IssuerAltNameSelect0", 20,'\0');
  1827 	    genName = MakeAltName(data, which, arena);
  1830     if (type == 0) {
  1831 	EncodeAndAddExtensionValue(arena, extHandle, genName, 
  1832 				   find_field_bool(data, "SubAltName-crit", 
  1833 						   PR_TRUE), 
  1834 				   SEC_OID_X509_SUBJECT_ALT_NAME, 
  1835 				   (EXTEN_VALUE_ENCODER)
  1836 				   CERT_EncodeAltNameExtension);
  1838     } else {
  1839 	if (autoIssuer && (name == NULL)) {
  1840 	    rv = CERT_AddExtension
  1841 		(extHandle, SEC_OID_X509_ISSUER_ALT_NAME, issuersAltName,
  1842 		 find_field_bool(data, "IssuerAltName-crit", PR_TRUE), PR_TRUE);
  1843 	} else {
  1844 	    EncodeAndAddExtensionValue(arena, extHandle, genName, 
  1845 				       find_field_bool(data, 
  1846 						       "IssuerAltName-crit", 
  1847 						       PR_TRUE), 
  1848 				       SEC_OID_X509_ISSUER_ALT_NAME, 
  1849 				       (EXTEN_VALUE_ENCODER)
  1850 				       CERT_EncodeAltNameExtension);
  1853     if (which != NULL) {
  1854 	PORT_Free(which);
  1856     if (issuerCert != NULL) {
  1857 	CERT_DestroyCertificate(issuerCert);
  1859     return rv;
  1863 static SECStatus
  1864 AddNameConstraints(void  *extHandle,
  1865 		   Pair  *data)
  1867     PLArenaPool         *arena = NULL;
  1868     CERTNameConstraints *constraints = NULL;
  1869     SECStatus           rv = SECSuccess;
  1872     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1873     if (arena == NULL) {
  1874 	error_allocate();
  1876     constraints = MakeNameConstraints(data, arena);
  1877     if (constraints != NULL) {
  1878 	EncodeAndAddExtensionValue(arena, extHandle, constraints, PR_TRUE, 
  1879 				   SEC_OID_X509_NAME_CONSTRAINTS, 
  1880 				   (EXTEN_VALUE_ENCODER)
  1881 				   CERT_EncodeNameConstraintsExtension);
  1883     if (arena != NULL) {
  1884 	PORT_ArenaRelease (arena, NULL);
  1886     return rv;
  1890 static SECStatus
  1891 add_extensions(CERTCertificate   *subjectCert, 
  1892 	       Pair              *data, 
  1893 	       char              *issuerNameStr, 
  1894 	       CERTCertDBHandle  *handle)
  1896     void                         *extHandle;
  1897     SECStatus                    rv = SECSuccess;
  1900     extHandle = CERT_StartCertExtensions (subjectCert);
  1901     if (extHandle == NULL) {
  1902 	error_out("ERROR: Unable to get certificates extension handle");
  1904     if (find_field_bool(data, "keyUsage", PR_TRUE)) {
  1905 	rv = AddKeyUsage(extHandle, data);
  1906 	if (rv != SECSuccess) {
  1907 	    error_out("ERROR: Unable to add Key Usage extension");
  1911     if( find_field_bool(data, "extKeyUsage", PR_TRUE) ) {
  1912       rv = AddExtKeyUsage(extHandle, data);
  1913       if( SECSuccess != rv ) {
  1914         error_out("ERROR: Unable to add Extended Key Usage extension");
  1918     if (find_field_bool(data, "basicConstraints", PR_TRUE)) {
  1919 	rv = AddBasicConstraint(extHandle, data);
  1920 	if (rv != SECSuccess) {
  1921 	    error_out("ERROR: Unable to add Basic Constraint extension");
  1924     if (find_field_bool(data, "subjectKeyIdentifier", PR_TRUE)) {
  1925 	rv = AddSubKeyID(extHandle, data, subjectCert);
  1926 	if (rv != SECSuccess) {
  1927 	    error_out("ERROR: Unable to add Subject Key Identifier Extension");
  1930     if (find_field_bool(data, "authorityKeyIdentifier", PR_TRUE)) {
  1931 	rv = AddAuthKeyID (extHandle, data, issuerNameStr, handle);
  1932 	if (rv != SECSuccess) {
  1933 	    error_out("ERROR: Unable to add Authority Key Identifier extension");
  1936     if (find_field_bool(data, "privKeyUsagePeriod", PR_TRUE)) {
  1937 	rv = AddPrivKeyUsagePeriod (extHandle, data, subjectCert);
  1938 	if (rv != SECSuccess) {
  1939 	    error_out("ERROR: Unable to add Private Key Usage Period extension");
  1942     if (find_field_bool(data, "SubAltName", PR_TRUE)) {
  1943 	rv = AddAltName (extHandle, data, NULL, NULL, 0);
  1944 	if (rv != SECSuccess) {
  1945 	    error_out("ERROR: Unable to add Subject Alternative Name extension");
  1948     if (find_field_bool(data, "IssuerAltName", PR_TRUE)) {
  1949 	rv = AddAltName (extHandle, data, issuerNameStr, handle, 1);
  1950 	if (rv != SECSuccess) {
  1951 	    error_out("ERROR: Unable to add Issuer Alternative Name Extension");
  1954     if (find_field_bool(data, "NameConstraints", PR_TRUE)) {
  1955 	rv = AddNameConstraints(extHandle, data);
  1956 	if (rv != SECSuccess) {
  1957 	    error_out("ERROR: Unable to add Name Constraints Extension");
  1960     if (find_field_bool(data, "netscape-cert-type", PR_TRUE)) {
  1961 	rv = AddNscpCertType(extHandle, data);
  1962 	if (rv != SECSuccess) {
  1963 	    error_out("ERROR: Unable to add Netscape Certificate Type Extension");
  1966     if (find_field_bool(data, "netscape-base-url", PR_TRUE)) {
  1967 	rv = add_IA5StringExtension(extHandle, 
  1968 				    find_field(data, "netscape-base-url-text", 
  1969 					       PR_TRUE), 
  1970 				    find_field_bool(data, 
  1971 						    "netscape-base-url-crit", 
  1972 						    PR_TRUE),
  1973 				    SEC_OID_NS_CERT_EXT_BASE_URL);
  1974 	if (rv != SECSuccess) {
  1975 	    error_out("ERROR: Unable to add Netscape Base URL Extension");
  1978     if (find_field_bool(data, "netscape-revocation-url", PR_TRUE)) {
  1979 	rv = add_IA5StringExtension(extHandle, 
  1980 				    find_field(data, 
  1981 					       "netscape-revocation-url-text", 
  1982 					       PR_TRUE), 
  1983 				    find_field_bool
  1984 				       (data, "netscape-revocation-url-crit", 
  1985 					PR_TRUE),
  1986 				    SEC_OID_NS_CERT_EXT_REVOCATION_URL);
  1987 	if (rv != SECSuccess) {
  1988 	    error_out("ERROR: Unable to add Netscape Revocation URL Extension");
  1991     if (find_field_bool(data, "netscape-ca-revocation-url", PR_TRUE)) {
  1992 	rv = add_IA5StringExtension(extHandle, 
  1993 				    find_field(data, 
  1994 					      "netscape-ca-revocation-url-text",
  1995 					       PR_TRUE), 
  1996 				    find_field_bool
  1997 				        (data, "netscape-ca-revocation-url-crit"
  1998 					 , PR_TRUE),
  1999 				    SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL);
  2000 	if (rv != SECSuccess) {
  2001 	    error_out("ERROR: Unable to add Netscape CA Revocation URL Extension");
  2004     if (find_field_bool(data, "netscape-cert-renewal-url", PR_TRUE)) {
  2005 	rv = add_IA5StringExtension(extHandle, 
  2006 				    find_field(data, 
  2007 					       "netscape-cert-renewal-url-text",
  2008 					       PR_TRUE), 
  2009 				    find_field_bool
  2010 				        (data, "netscape-cert-renewal-url-crit",
  2011 					 PR_TRUE),
  2012 				    SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL);
  2013 	if (rv != SECSuccess) {
  2014 	    error_out("ERROR: Unable to add Netscape Certificate Renewal URL Extension");
  2017     if (find_field_bool(data, "netscape-ca-policy-url", PR_TRUE)) {
  2018 	rv = add_IA5StringExtension(extHandle, 
  2019 				    find_field(data, 
  2020 					       "netscape-ca-policy-url-text", 
  2021 					       PR_TRUE), 
  2022 				    find_field_bool
  2023 				         (data, "netscape-ca-policy-url-crit", 
  2024 					  PR_TRUE),
  2025 				    SEC_OID_NS_CERT_EXT_CA_POLICY_URL);
  2026 	if (rv != SECSuccess) {
  2027 	    error_out("ERROR: Unable to add Netscape CA Policy URL Extension");
  2030     if (find_field_bool(data, "netscape-ssl-server-name", PR_TRUE)) {
  2031 	rv = add_IA5StringExtension(extHandle, 
  2032 				    find_field(data, 
  2033 					       "netscape-ssl-server-name-text", 
  2034 					       PR_TRUE), 
  2035 				    find_field_bool
  2036 				         (data, "netscape-ssl-server-name-crit",
  2037 					  PR_TRUE),
  2038 				    SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME);
  2039 	if (rv != SECSuccess) {
  2040 	    error_out("ERROR: Unable to add Netscape SSL Server Name Extension");
  2043     if (find_field_bool(data, "netscape-comment", PR_TRUE)) {
  2044 	rv = add_IA5StringExtension(extHandle, 
  2045 				    find_field(data, "netscape-comment-text", 
  2046 					       PR_TRUE), 
  2047 				    find_field_bool(data, 
  2048 						    "netscape-comment-crit", 
  2049 						    PR_TRUE),
  2050 				    SEC_OID_NS_CERT_EXT_COMMENT);
  2051 	if (rv != SECSuccess) {
  2052 	    error_out("ERROR: Unable to add Netscape Comment Extension");
  2055     CERT_FinishExtensions(extHandle);
  2056     return (rv);
  2061 char *
  2062 return_dbpasswd(PK11SlotInfo *slot, PRBool retry, void *data)
  2064     char *rv;
  2066     /* don't clobber our poor smart card */
  2067     if (retry == PR_TRUE) {
  2068 	return NULL;
  2070     rv = PORT_Alloc(4);
  2071     PORT_Strcpy(rv, "foo");
  2072     return rv;
  2076 SECKEYPrivateKey *
  2077 FindPrivateKeyFromNameStr(char              *name, 
  2078 			  CERTCertDBHandle  *certHandle)
  2080     SECKEYPrivateKey                        *key;
  2081     CERTCertificate                         *cert;
  2082     CERTCertificate                         *p11Cert;
  2085     /* We don't presently have a PK11 function to find a cert by 
  2086     ** subject name.  
  2087     ** We do have a function to find a cert in the internal slot's
  2088     ** cert db by subject name, but it doesn't setup the slot info.
  2089     ** So, this HACK works, but should be replaced as soon as we 
  2090     ** have a function to search for certs accross slots by subject name.
  2091     */
  2092     cert = CERT_FindCertByNameString(certHandle, name);
  2093     if (cert == NULL || cert->nickname == NULL) {
  2094 	error_out("ERROR: Unable to retrieve issuers certificate");
  2096     p11Cert = PK11_FindCertFromNickname(cert->nickname, NULL);
  2097     if (p11Cert == NULL) {
  2098 	error_out("ERROR: Unable to retrieve issuers certificate");
  2100     key = PK11_FindKeyByAnyCert(p11Cert, NULL);
  2101     return key;
  2104 static SECItem *
  2105 SignCert(CERTCertificate   *cert,
  2106 	 char              *issuerNameStr,
  2107 	 Pair              *data,
  2108 	 CERTCertDBHandle  *handle,
  2109          int               which_key)
  2111     SECItem                der;
  2112     SECKEYPrivateKey       *caPrivateKey = NULL;
  2113     SECStatus              rv;
  2114     PLArenaPool            *arena;
  2115     SECOidTag              algID;
  2117     if (which_key == 0) {
  2118 	caPrivateKey = FindPrivateKeyFromNameStr(issuerNameStr, handle); 
  2119     } else {
  2120 	caPrivateKey = privkeys[which_key - 1];
  2122     if (caPrivateKey == NULL) {
  2123 	error_out("ERROR: unable to retrieve issuers key");
  2126     arena = cert->arena;
  2128     algID = SEC_GetSignatureAlgorithmOidTag(caPrivateKey->keyType,
  2129 					    SEC_OID_UNKNOWN);
  2130     if (algID == SEC_OID_UNKNOWN) {
  2131 	error_out("ERROR: Unknown key type for issuer.");
  2132 	goto done;
  2135     rv = SECOID_SetAlgorithmID(arena, &cert->signature, algID, 0);
  2136     if (rv != SECSuccess) {
  2137 	error_out("ERROR: Could not set signature algorithm id.");
  2140     if (find_field_bool(data,"ver-1", PR_TRUE)) {
  2141 	*(cert->version.data) = 0;
  2142 	cert->version.len = 1;
  2143     } else {
  2144 	*(cert->version.data) = 2;
  2145 	cert->version.len = 1;
  2147     der.data = NULL;
  2148     der.len = 0;
  2149     (void) SEC_ASN1EncodeItem (arena, &der, cert, CERT_CertificateTemplate);
  2150     if (der.data == NULL) {
  2151 	error_out("ERROR: Could not encode certificate.\n");
  2153     rv = SEC_DerSignData (arena, &(cert->derCert), der.data, der.len, caPrivateKey,
  2154 			  algID);
  2155     if (rv != SECSuccess) {
  2156 	error_out("ERROR: Could not sign encoded certificate data.\n");
  2158 done:
  2159     SECKEY_DestroyPrivateKey(caPrivateKey);
  2160     return &(cert->derCert);
  2164 int
  2165 main(int argc, char **argv)
  2167     int                    length = 500;
  2168     int                    remaining = 500;
  2169     int                    n;
  2170     int                    i;
  2171     int                    serial;
  2172     int                    chainLen;
  2173     int                    which_key;
  2174     char                   *pos;
  2175 #ifdef OFFLINE
  2176     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";
  2177 #else
  2178     char                   *form_output;
  2179 #endif
  2180     char                   *issuerNameStr;
  2181     char                   *certName;
  2182     char                   *DBdir = DB_DIRECTORY;
  2183     char                   *prefixs[10] = {"CA#1-", "CA#2-", "CA#3-", 
  2184 					   "CA#4-", "CA#5-", "CA#6-", 
  2185 					   "CA#7-", "CA#8-", "CA#9-", ""};
  2186     Pair                   *form_data;
  2187     CERTCertificate        *cert;
  2188     CERTCertDBHandle       *handle;
  2189     CERTCertificateRequest *certReq = NULL;
  2190     int                    warpmonths = 0;
  2191     SECItem                *certDER;
  2192 #ifdef FILEOUT
  2193     FILE                   *outfile;
  2194 #endif
  2195     SECStatus              status = SECSuccess;
  2196     extern                 char prefix[PREFIX_LEN];
  2197     SEC_PKCS7ContentInfo   *certChain;
  2198     SECItem                *encodedCertChain;
  2199     PRBool                 UChain = PR_FALSE;
  2202     progName = strrchr(argv[0], '/');
  2203     progName = progName ? progName+1 : argv[0];
  2206 #ifdef TEST
  2207     sleep(20);
  2208 #endif
  2209     SECU_ConfigDirectory(DBdir);
  2211     PK11_SetPasswordFunc(return_dbpasswd);
  2212     status = NSS_InitReadWrite(DBdir);
  2213     if (status != SECSuccess) {
  2214 	SECU_PrintPRandOSError(progName);
  2215 	return -1;
  2217     handle = CERT_GetDefaultCertDB();
  2219     prefix[0]= '\0';
  2220 #if !defined(OFFLINE)
  2221     form_output = (char*) PORT_Alloc(length);
  2222     if (form_output == NULL) {
  2223 	error_allocate();
  2225     pos = form_output;
  2226     while (feof(stdin) == 0 ) {
  2227 	if (remaining <= 1) {
  2228 	    remaining += length;
  2229 	    length = length * 2;
  2230 	    form_output = PORT_Realloc(form_output, (length));
  2231 	    if (form_output == NULL) {
  2232 		error_allocate();
  2234 	    pos = form_output + length - remaining;
  2236 	n = fread(pos, 1, (size_t) (remaining - 1), stdin);
  2237 	pos += n;
  2238 	remaining -= n;
  2240     *pos = '&';
  2241     pos++;
  2242     length = pos - form_output;
  2243 #else
  2244     length = PORT_Strlen(form_output);
  2245 #endif
  2246 #ifdef FILEOUT
  2247     printf("Content-type: text/plain\n\n");
  2248     fwrite(form_output, 1, (size_t)length, stdout);
  2249     printf("\n");
  2250 #endif
  2251 #ifdef FILEOUT
  2252     fwrite(form_output, 1, (size_t)length, stdout);
  2253     printf("\n");
  2254     fflush(stdout);
  2255 #endif
  2256     form_data = make_datastruct(form_output, length);
  2257     status = clean_input(form_data);
  2258 #if !defined(OFFLINE)
  2259     PORT_Free(form_output);
  2260 #endif
  2261 #ifdef FILEOUT
  2262     i = 0;
  2263     while(return_name(form_data, i) != NULL) {
  2264         printf("%s",return_name(form_data,i));
  2265         printf("=\n");
  2266         printf("%s",return_data(form_data,i));
  2267         printf("\n");
  2268 	i++;
  2270     printf("I got that done, woo hoo\n");
  2271     fflush(stdout);
  2272 #endif
  2273     issuerNameStr = PORT_Alloc(200);
  2274     if (find_field_bool(form_data, "caChoiceradio-SignWithSpecifiedChain",
  2275 			PR_FALSE)) {
  2276 	UChain = PR_TRUE;
  2277 	chainLen = atoi(find_field(form_data, "manCAs", PR_FALSE));
  2278 	PORT_Strcpy(prefix, prefixs[0]);
  2279 	issuerNameStr = PORT_Strcpy(issuerNameStr,
  2280 			       "CN=Cert-O-Matic II, O=Cert-O-Matic II");
  2281 	if (chainLen == 0) {
  2282 	    UChain =  PR_FALSE;
  2284     } else {
  2285 	if (find_field_bool(form_data, "caChoiceradio-SignWithRandomChain", 
  2286 			    PR_FALSE)) {
  2287 	    PORT_Strcpy(prefix,prefixs[9]);
  2288 	    chainLen = atoi(find_field(form_data, "autoCAs", PR_FALSE));
  2289 	    if (chainLen < 1 || chainLen > 18) {
  2290 		issuerNameStr = PORT_Strcpy(issuerNameStr, 
  2291 				       "CN=CA18, O=Cert-O-Matic II");
  2293 	    issuerNameStr = PORT_Strcpy(issuerNameStr, "CN=CA");
  2294 	    issuerNameStr = PORT_Strcat(issuerNameStr, 
  2295 				   find_field(form_data,"autoCAs", PR_FALSE));
  2296 	    issuerNameStr = PORT_Strcat(issuerNameStr,", O=Cert-O-Matic II");
  2297 	} else {
  2298 	    issuerNameStr = PORT_Strcpy(issuerNameStr, 
  2299 				   "CN=Cert-O-Matic II, O=Cert-O-Matic II");
  2301 	chainLen = 0;
  2304     i = -1;
  2305     which_key = 0;
  2306     do {
  2307     	extern SECStatus cert_GetKeyID(CERTCertificate *cert);
  2308 	i++;
  2309 	if (i != 0 && UChain) {
  2310 	    PORT_Strcpy(prefix, prefixs[i]);
  2312 	/*        find_field(form_data,"subject", PR_TRUE); */
  2313 	certReq = makeCertReq(form_data, which_key);
  2314 #ifdef OFFLINE
  2315 	serial = 900;
  2316 #else
  2317 	serial = get_serial_number(form_data);
  2318 #endif
  2319 	cert = MakeV1Cert(handle, certReq, issuerNameStr, PR_FALSE, 
  2320 			  serial, warpmonths, form_data);
  2321 	if (certReq != NULL) {
  2322 	    CERT_DestroyCertificateRequest(certReq);
  2324 	if (find_field_bool(form_data,"ver-3", PR_TRUE)) {
  2325 	    status = add_extensions(cert, form_data, issuerNameStr, handle);
  2326 	    if (status != SECSuccess) {
  2327 		error_out("ERROR: Unable to add extensions");
  2330 	status = cert_GetKeyID(cert);
  2331 	if (status == SECFailure) {
  2332 	    error_out("ERROR: Unable to get Key ID.");
  2334 	certDER = SignCert(cert, issuerNameStr, form_data, handle, which_key);
  2335 	CERT_NewTempCertificate(handle, certDER, NULL, PR_FALSE, PR_TRUE);
  2336 	issuerNameStr = find_field(form_data, "subject", PR_TRUE);
  2337 	/*        SECITEM_FreeItem(certDER, PR_TRUE); */
  2338 	CERT_DestroyCertificate(cert);
  2339 	if (i == (chainLen - 1)) {
  2340 	    i = 8;
  2342 	++which_key;
  2343     } while (i < 9 && UChain);
  2347 #ifdef FILEOUT
  2348     outfile = fopen("../certout", "wb");
  2349 #endif
  2350     certName = find_field(form_data, "subject", PR_FALSE);
  2351     cert = CERT_FindCertByNameString(handle, certName);
  2352     certChain = SEC_PKCS7CreateCertsOnly (cert, PR_TRUE, handle);
  2353     if (certChain == NULL) {
  2354 	error_out("ERROR: No certificates in cert chain");
  2356     encodedCertChain = SEC_PKCS7EncodeItem (NULL, NULL, certChain, NULL, NULL, 
  2357 					    NULL);
  2358     if (encodedCertChain) {
  2359 #if !defined(FILEOUT)
  2360 	printf("Content-type: application/x-x509-user-cert\r\n");
  2361 	printf("Content-length: %d\r\n\r\n", encodedCertChain->len);
  2362 	fwrite (encodedCertChain->data, 1, encodedCertChain->len, stdout);
  2363 #else
  2364 	fwrite (encodedCertChain->data, 1, encodedCertChain->len, outfile);
  2365 #endif
  2367     } else {
  2368 	error_out("Error: Unable to DER encode certificate");
  2370 #ifdef FILEOUT
  2371     printf("\nI got here!\n");
  2372     fflush(outfile);
  2373     fclose(outfile);
  2374 #endif
  2375     fflush(stdout);
  2376     if (NSS_Shutdown() != SECSuccess) {
  2377         exit(1);
  2379     return 0;

mercurial