security/nss/cmd/certcgi/certcgi.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/nss/cmd/certcgi/certcgi.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,2381 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +/* Cert-O-Matic CGI */
     1.9 +
    1.10 +
    1.11 +#include "nspr.h"
    1.12 +#include "prtypes.h"
    1.13 +#include "prtime.h"
    1.14 +#include "prlong.h"
    1.15 +
    1.16 +#include "pk11func.h"
    1.17 +#include "cert.h"
    1.18 +#include "cryptohi.h"
    1.19 +#include "secoid.h"
    1.20 +#include "secder.h"
    1.21 +#include "genname.h"
    1.22 +#include "xconst.h"
    1.23 +#include "secutil.h"
    1.24 +#include "pk11pqg.h"
    1.25 +#include "certxutl.h"
    1.26 +#include "nss.h"
    1.27 +
    1.28 +
    1.29 +/* #define TEST           1 */
    1.30 +/* #define FILEOUT        1 */
    1.31 +/* #define OFFLINE        1 */
    1.32 +#define START_FIELDS   100
    1.33 +#define PREFIX_LEN     6
    1.34 +#define SERIAL_FILE    "../serial"
    1.35 +#define DB_DIRECTORY   ".."
    1.36 +
    1.37 +static char *progName;
    1.38 +
    1.39 +typedef struct PairStr Pair;
    1.40 +
    1.41 +struct PairStr {
    1.42 +    char *name;
    1.43 +    char *data;
    1.44 +};
    1.45 +
    1.46 +
    1.47 +char prefix[PREFIX_LEN];
    1.48 +
    1.49 +
    1.50 +const SEC_ASN1Template CERTIA5TypeTemplate[] = {
    1.51 +    { SEC_ASN1_IA5_STRING }
    1.52 +};
    1.53 +
    1.54 +
    1.55 +
    1.56 +SECKEYPrivateKey *privkeys[9] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL,
    1.57 +				 NULL, NULL};
    1.58 +
    1.59 +
    1.60 +#ifdef notdef
    1.61 +const SEC_ASN1Template CERT_GeneralNameTemplate[] = {
    1.62 +    { SEC_ASN1_SEQUENCE_OF, 0, SEC_AnyTemplate }
    1.63 +};
    1.64 +#endif
    1.65 +
    1.66 +
    1.67 +static void
    1.68 +error_out(char  *error_string)
    1.69 +{
    1.70 +    printf("Content-type: text/plain\n\n");
    1.71 +    printf("%s", error_string);
    1.72 +    fflush(stderr);
    1.73 +    fflush(stdout);
    1.74 +    exit(1);
    1.75 +}
    1.76 +
    1.77 +static void
    1.78 +error_allocate(void)
    1.79 +{
    1.80 +    error_out("ERROR: Unable to allocate memory");
    1.81 +}
    1.82 +
    1.83 +
    1.84 +static char *
    1.85 +make_copy_string(char  *read_pos, 
    1.86 +		 int   length, 
    1.87 +		 char  sentinal_value)
    1.88 +    /* copys string from to a new string it creates and 
    1.89 +       returns a pointer to the new string */
    1.90 +{
    1.91 +    int                remaining = length;
    1.92 +    char               *write_pos;
    1.93 +    char               *new;
    1.94 +
    1.95 +    new = write_pos = (char *) PORT_Alloc (length);
    1.96 +    if (new == NULL) {
    1.97 +	error_allocate();
    1.98 +    }
    1.99 +    while (*read_pos != sentinal_value) {
   1.100 +	if (remaining == 1) {
   1.101 +	    remaining += length;
   1.102 +	    length = length * 2;
   1.103 +	    new = PORT_Realloc(new,length);
   1.104 +	    if (new == NULL) {
   1.105 +		error_allocate();
   1.106 +	    }
   1.107 +	    write_pos = new + length - remaining;
   1.108 +	}
   1.109 +	*write_pos = *read_pos;
   1.110 +	++write_pos;
   1.111 +	++read_pos;
   1.112 +	remaining = remaining - 1;
   1.113 +    }
   1.114 +    *write_pos = '\0';
   1.115 +    return new;
   1.116 +}
   1.117 +
   1.118 +
   1.119 +static SECStatus
   1.120 +clean_input(Pair *data)
   1.121 +    /* converts the non-alphanumeric characters in a form post 
   1.122 +       from hex codes back to characters */
   1.123 +{
   1.124 +    int           length;
   1.125 +    int           hi_digit;
   1.126 +    int           low_digit;
   1.127 +    char          character;
   1.128 +    char          *begin_pos;
   1.129 +    char          *read_pos;
   1.130 +    char          *write_pos;
   1.131 +    PRBool        name = PR_TRUE;
   1.132 +
   1.133 +    begin_pos = data->name;
   1.134 +    while (begin_pos != NULL) {
   1.135 +	length = strlen(begin_pos);
   1.136 +	read_pos = write_pos = begin_pos;
   1.137 +	while ((read_pos - begin_pos) < length) {
   1.138 +	    if (*read_pos == '+') {
   1.139 +		*read_pos = ' ';
   1.140 +	    }
   1.141 +	    if (*read_pos == '%') {
   1.142 +		hi_digit = *(read_pos + 1);
   1.143 +		low_digit = *(read_pos +2);
   1.144 +		read_pos += 3;
   1.145 +		if (isdigit(hi_digit)){
   1.146 +		    hi_digit = hi_digit - '0';
   1.147 +		} else {
   1.148 +		    hi_digit = toupper(hi_digit);
   1.149 +		    if (isxdigit(hi_digit)) {
   1.150 +			hi_digit = (hi_digit - 'A') + 10;
   1.151 +		    } else {
   1.152 +			error_out("ERROR: Form data incorrectly formated");
   1.153 +		    }
   1.154 +		}
   1.155 +		if (isdigit(low_digit)){
   1.156 +		    low_digit = low_digit - '0';
   1.157 +		} else {
   1.158 +		    low_digit = toupper(low_digit);
   1.159 +		    if ((low_digit >='A') && (low_digit <= 'F')) {
   1.160 +			low_digit = (low_digit - 'A') + 10;
   1.161 +		    } else {
   1.162 +			error_out("ERROR: Form data incorrectly formated");
   1.163 +		    }
   1.164 +		}
   1.165 +		character = (hi_digit << 4) | low_digit;
   1.166 +		if (character != 10) {
   1.167 +		    *write_pos = character;
   1.168 +		    ++write_pos;
   1.169 +		}
   1.170 +	    } else {
   1.171 +		*write_pos = *read_pos;
   1.172 +		++write_pos;
   1.173 +		++read_pos;
   1.174 +	    }
   1.175 +	}
   1.176 +	*write_pos = '\0';
   1.177 +	if (name == PR_TRUE) {
   1.178 +	    begin_pos = data->data;
   1.179 +	    name = PR_FALSE;
   1.180 +	} else {
   1.181 +	    data++;
   1.182 +	    begin_pos = data->name;
   1.183 +	    name = PR_TRUE;
   1.184 +	}
   1.185 +    }
   1.186 +    return SECSuccess;
   1.187 +}
   1.188 +
   1.189 +static char *
   1.190 +make_name(char  *new_data)
   1.191 +    /* gets the next field name in the input string and returns
   1.192 +       a pointer to a string containing a copy of it */
   1.193 +{
   1.194 +    int         length = 20;
   1.195 +    char        *name;
   1.196 +
   1.197 +    name = make_copy_string(new_data, length, '=');
   1.198 +    return name;
   1.199 +}
   1.200 +	
   1.201 +static char *
   1.202 +make_data(char  *new_data)
   1.203 +    /* gets the data for the next field in the input string 
   1.204 +       and returns a pointer to a string containing it */
   1.205 +{
   1.206 +    int         length = 100;
   1.207 +    char        *data;
   1.208 +    char        *read_pos;
   1.209 +
   1.210 +    read_pos = new_data;
   1.211 +    while (*(read_pos - 1) != '=') {
   1.212 +	++read_pos;
   1.213 +    }
   1.214 +    data = make_copy_string(read_pos, length, '&');
   1.215 +    return data;
   1.216 +}
   1.217 +
   1.218 +
   1.219 +static Pair
   1.220 +make_pair(char  *new_data)
   1.221 +    /* makes a pair name/data pair from the input string */
   1.222 +{
   1.223 +    Pair        temp;
   1.224 +
   1.225 +    temp.name = make_name(new_data);
   1.226 +    temp.data = make_data(new_data);
   1.227 +    return temp;
   1.228 +}
   1.229 +
   1.230 +
   1.231 +
   1.232 +static Pair *
   1.233 +make_datastruct(char  *data, int len)
   1.234 +    /* parses the input from the form post into a data 
   1.235 +       structure of field name/data pairs */
   1.236 +{
   1.237 +    Pair              *datastruct;
   1.238 +    Pair              *current;
   1.239 +    char              *curr_pos;
   1.240 +    int               fields = START_FIELDS;
   1.241 +    int               remaining = START_FIELDS;
   1.242 +
   1.243 +    curr_pos = data;
   1.244 +    datastruct = current = (Pair *) PORT_Alloc(fields * sizeof(Pair));
   1.245 +    if (datastruct == NULL) {
   1.246 +	error_allocate();
   1.247 +    }
   1.248 +    while (curr_pos - data < len) {
   1.249 +	if (remaining == 1) {
   1.250 +	    remaining += fields;
   1.251 +	    fields = fields * 2;
   1.252 +	    datastruct = (Pair *) PORT_Realloc
   1.253 +		(datastruct, fields * sizeof(Pair));
   1.254 +	    if (datastruct == NULL) {
   1.255 +		error_allocate();
   1.256 +	    }
   1.257 +	    current = datastruct + (fields - remaining);
   1.258 +	}
   1.259 +	*current = make_pair(curr_pos);
   1.260 +	while (*curr_pos != '&') {
   1.261 +	    ++curr_pos;
   1.262 +	}
   1.263 +	++curr_pos;
   1.264 +	++current;
   1.265 +	remaining = remaining - 1;
   1.266 +    }
   1.267 +    current->name = NULL;
   1.268 +    return datastruct;
   1.269 +}
   1.270 +
   1.271 +static char *
   1.272 +return_name(Pair  *data_struct,
   1.273 +	    int   n)
   1.274 +    /* returns a pointer to the name of the nth 
   1.275 +       (starting from 0) item in the data structure */
   1.276 +{
   1.277 +    char          *name;
   1.278 +
   1.279 +    if ((data_struct + n)->name != NULL) {
   1.280 +	name = (data_struct + n)->name;
   1.281 +	return name;
   1.282 +    } else {
   1.283 +	return NULL;
   1.284 +    }
   1.285 +}
   1.286 +
   1.287 +static char *
   1.288 +return_data(Pair  *data_struct,int n)
   1.289 +    /* returns a pointer to the data of the nth (starting from 0) 
   1.290 +       itme in the data structure */
   1.291 +{
   1.292 +    char          *data;
   1.293 +
   1.294 +    data = (data_struct + n)->data;
   1.295 +    return data;
   1.296 +}
   1.297 +
   1.298 +
   1.299 +static char *
   1.300 +add_prefix(char  *field_name)
   1.301 +{
   1.302 +    extern char  prefix[PREFIX_LEN];
   1.303 +    int          i = 0;
   1.304 +    char         *rv;
   1.305 +    char         *write;
   1.306 +
   1.307 +    rv = write = PORT_Alloc(PORT_Strlen(prefix) + PORT_Strlen(field_name) + 1);
   1.308 +    for(i = 0; i < PORT_Strlen(prefix); i++) {
   1.309 +	*write = prefix[i];
   1.310 +	write++;
   1.311 +    }
   1.312 +    *write = '\0';
   1.313 +    rv = PORT_Strcat(rv,field_name);
   1.314 +    return rv;
   1.315 +}
   1.316 +
   1.317 +
   1.318 +static char *
   1.319 +find_field(Pair    *data, 
   1.320 +	   char    *field_name, 
   1.321 +	   PRBool  add_pre)
   1.322 +    /* returns a pointer to the data of the first pair 
   1.323 +       thats name matches the string it is passed */
   1.324 +{
   1.325 +    int            i = 0;
   1.326 +    char           *retrieved;
   1.327 +    int            found = 0;
   1.328 +
   1.329 +    if (add_pre) {
   1.330 +	field_name = add_prefix(field_name);
   1.331 +    }
   1.332 +    while(return_name(data, i) != NULL) {
   1.333 +	if (PORT_Strcmp(return_name(data, i), field_name) == 0) {
   1.334 +	    retrieved = return_data(data, i);
   1.335 +	    found = 1;
   1.336 +	    break;
   1.337 +	}
   1.338 +	i++;
   1.339 +    }
   1.340 +    if (!found) {
   1.341 +	retrieved = NULL;
   1.342 +    }
   1.343 +    return retrieved;
   1.344 +}
   1.345 +
   1.346 +static PRBool
   1.347 +find_field_bool(Pair    *data, 
   1.348 +		char    *fieldname, 
   1.349 +		PRBool  add_pre)
   1.350 +{
   1.351 +    char                *rv;
   1.352 +
   1.353 +    rv = find_field(data, fieldname, add_pre);
   1.354 +	
   1.355 +    if  ((rv != NULL) && (PORT_Strcmp(rv, "true")) == 0) {
   1.356 +	return PR_TRUE;
   1.357 +    } else {
   1.358 +	return PR_FALSE;
   1.359 +    }
   1.360 +}
   1.361 +
   1.362 +static char *
   1.363 +update_data_by_name(Pair  *data, 
   1.364 +		    char  *field_name,
   1.365 +                    char  *new_data)
   1.366 +    /* replaces the data in the data structure associated with 
   1.367 +       a name with new data, returns null if not found */
   1.368 +{
   1.369 +    int                   i = 0;
   1.370 +    int                   found = 0;
   1.371 +    int                   length = 100;
   1.372 +    char                  *new;
   1.373 +
   1.374 +    while (return_name(data, i) != NULL) {
   1.375 +	if (PORT_Strcmp(return_name(data, i), field_name) == 0) {
   1.376 +	    new = make_copy_string( new_data, length, '\0');
   1.377 +	    PORT_Free(return_data(data, i));
   1.378 +	    found = 1;
   1.379 +	    (*(data + i)).data = new;
   1.380 +	    break;
   1.381 +	}
   1.382 +	i++;
   1.383 +    }
   1.384 +    if (!found) {
   1.385 +	new = NULL;
   1.386 +    }
   1.387 +    return new;
   1.388 +}
   1.389 +
   1.390 +static char *
   1.391 +update_data_by_index(Pair  *data, 
   1.392 +		     int   n, 
   1.393 +		     char  *new_data)
   1.394 +    /* replaces the data of a particular index in the data structure */
   1.395 +{
   1.396 +    int                    length = 100;
   1.397 +    char                   *new;
   1.398 +
   1.399 +    new = make_copy_string(new_data, length, '\0');
   1.400 +    PORT_Free(return_data(data, n));
   1.401 +    (*(data + n)).data = new;
   1.402 +    return new;
   1.403 +}
   1.404 +
   1.405 +
   1.406 +static Pair *
   1.407 +add_field(Pair   *data, 
   1.408 +	  char*  field_name, 
   1.409 +	  char*  field_data)
   1.410 +    /* adds a new name/data pair to the data structure */
   1.411 +{
   1.412 +    int          i = 0;
   1.413 +    int          j;
   1.414 +    int          name_length = 100;
   1.415 +    int          data_length = 100;
   1.416 +
   1.417 +    while(return_name(data, i) != NULL) {
   1.418 +	i++;
   1.419 +    }
   1.420 +    j = START_FIELDS;
   1.421 +    while ( j < (i + 1) ) {
   1.422 +	j = j * 2;
   1.423 +    }
   1.424 +    if (j == (i + 1)) {
   1.425 +	data = (Pair *) PORT_Realloc(data, (j * 2) * sizeof(Pair));
   1.426 +	if (data == NULL) {
   1.427 +	    error_allocate();
   1.428 +	}
   1.429 +    }
   1.430 +    (*(data + i)).name = make_copy_string(field_name, name_length, '\0');
   1.431 +    (*(data + i)).data = make_copy_string(field_data, data_length, '\0');
   1.432 +    (data + i + 1)->name = NULL;
   1.433 +    return data;
   1.434 +}
   1.435 +
   1.436 +
   1.437 +static CERTCertificateRequest *
   1.438 +makeCertReq(Pair             *form_data,
   1.439 +	    int              which_priv_key)
   1.440 +    /* makes and encodes a certrequest */
   1.441 +{
   1.442 +
   1.443 +    PK11SlotInfo             *slot;
   1.444 +    CERTCertificateRequest   *certReq = NULL;
   1.445 +    CERTSubjectPublicKeyInfo *spki;
   1.446 +    SECKEYPrivateKey         *privkey = NULL;
   1.447 +    SECKEYPublicKey          *pubkey = NULL;
   1.448 +    CERTName                 *name;
   1.449 +    char                     *key;
   1.450 +    extern SECKEYPrivateKey  *privkeys[9];
   1.451 +    int                      keySizeInBits;
   1.452 +    char                     *challenge = "foo";
   1.453 +    SECStatus                rv = SECSuccess;
   1.454 +    PQGParams                *pqgParams = NULL;
   1.455 +    PQGVerify                *pqgVfy = NULL;
   1.456 +
   1.457 +    name = CERT_AsciiToName(find_field(form_data, "subject", PR_TRUE));
   1.458 +    if (name == NULL) {
   1.459 +	error_out("ERROR: Unable to create Subject Name");
   1.460 +    }
   1.461 +    key = find_field(form_data, "key", PR_TRUE);
   1.462 +    if (key == NULL) {
   1.463 +	switch (*find_field(form_data, "keysize", PR_TRUE)) {
   1.464 +	  case '0':
   1.465 +	    keySizeInBits = 2048;
   1.466 +	    break;
   1.467 +	  case '1':
   1.468 +	    keySizeInBits = 1024;
   1.469 +	    break;
   1.470 +	  case '2':
   1.471 +	    keySizeInBits = 512;
   1.472 +	    break;
   1.473 +	  default:
   1.474 +	    error_out("ERROR: Unsupported Key length selected");
   1.475 +	}
   1.476 +	if (find_field_bool(form_data, "keyType-dsa", PR_TRUE)) {
   1.477 +	    rv = PK11_PQG_ParamGen(keySizeInBits, &pqgParams, &pqgVfy);
   1.478 +	    if (rv != SECSuccess) {
   1.479 +		error_out("ERROR: Unable to generate PQG parameters");
   1.480 +	    }
   1.481 +	    slot = PK11_GetBestSlot(CKM_DSA_KEY_PAIR_GEN, NULL);
   1.482 +	    privkey = PK11_GenerateKeyPair(slot, CKM_DSA_KEY_PAIR_GEN, 
   1.483 +					   pqgParams,&pubkey, PR_FALSE, 
   1.484 +					   PR_TRUE, NULL);
   1.485 +	} else {
   1.486 +	    privkey = SECKEY_CreateRSAPrivateKey(keySizeInBits, &pubkey, NULL);
   1.487 +	}
   1.488 +	privkeys[which_priv_key] = privkey;
   1.489 +	spki = SECKEY_CreateSubjectPublicKeyInfo(pubkey);
   1.490 +    } else {
   1.491 +	spki = SECKEY_ConvertAndDecodePublicKeyAndChallenge(key, challenge, 
   1.492 +							    NULL);
   1.493 +	if (spki == NULL) {
   1.494 +	    error_out("ERROR: Unable to decode Public Key and Challenge String");
   1.495 +	}
   1.496 +    }
   1.497 +    certReq = CERT_CreateCertificateRequest(name, spki, NULL);
   1.498 +    if (certReq == NULL) {
   1.499 +	error_out("ERROR: Unable to create Certificate Request");
   1.500 +    }
   1.501 +    if (pubkey != NULL) {
   1.502 +	SECKEY_DestroyPublicKey(pubkey);
   1.503 +    }
   1.504 +    if (spki != NULL) {
   1.505 +	SECKEY_DestroySubjectPublicKeyInfo(spki);
   1.506 +    }
   1.507 +    if (pqgParams != NULL) {
   1.508 +	PK11_PQG_DestroyParams(pqgParams);
   1.509 +    }
   1.510 +    if (pqgVfy != NULL) {
   1.511 +	PK11_PQG_DestroyVerify(pqgVfy);
   1.512 +    }
   1.513 +    return certReq;
   1.514 +}
   1.515 +
   1.516 +
   1.517 +
   1.518 +static CERTCertificate *
   1.519 +MakeV1Cert(CERTCertDBHandle        *handle, 
   1.520 +	   CERTCertificateRequest  *req,
   1.521 +	   char                    *issuerNameStr, 
   1.522 +	   PRBool                  selfsign, 
   1.523 +	   int                     serialNumber,
   1.524 +	   int                     warpmonths,
   1.525 +	   Pair                    *data)
   1.526 +{
   1.527 +    CERTCertificate                 *issuerCert = NULL;
   1.528 +    CERTValidity                    *validity;
   1.529 +    CERTCertificate                 *cert = NULL;
   1.530 +    PRExplodedTime                  printableTime;
   1.531 +    PRTime                          now, 
   1.532 +	                            after;
   1.533 +    SECStatus rv;
   1.534 +   
   1.535 +    
   1.536 +
   1.537 +    if ( !selfsign ) {
   1.538 +	issuerCert = CERT_FindCertByNameString(handle, issuerNameStr);
   1.539 +	if (!issuerCert) {
   1.540 +	    error_out("ERROR: Could not find issuer's certificate");
   1.541 +	    return NULL;
   1.542 +	}
   1.543 +    }
   1.544 +    if (find_field_bool(data, "manValidity", PR_TRUE)) {
   1.545 +	rv = DER_AsciiToTime(&now, find_field(data, "notBefore", PR_TRUE));
   1.546 +    } else {
   1.547 +	now = PR_Now();
   1.548 +    }
   1.549 +    PR_ExplodeTime (now, PR_GMTParameters, &printableTime);
   1.550 +    if ( warpmonths ) {
   1.551 +	printableTime.tm_month += warpmonths;
   1.552 +	now = PR_ImplodeTime (&printableTime);
   1.553 +	PR_ExplodeTime (now, PR_GMTParameters, &printableTime);
   1.554 +    }
   1.555 +    if (find_field_bool(data, "manValidity", PR_TRUE)) {
   1.556 +	rv = DER_AsciiToTime(&after, find_field(data, "notAfter", PR_TRUE));
   1.557 +	PR_ExplodeTime (after, PR_GMTParameters, &printableTime);
   1.558 +    } else {
   1.559 +	printableTime.tm_month += 3;
   1.560 +	after = PR_ImplodeTime (&printableTime);
   1.561 +    }
   1.562 +    /* note that the time is now in micro-second unit */
   1.563 +    validity = CERT_CreateValidity (now, after);
   1.564 +
   1.565 +    if ( selfsign ) {
   1.566 +	cert = CERT_CreateCertificate
   1.567 +	    (serialNumber,&(req->subject), validity, req);
   1.568 +    } else {
   1.569 +	cert = CERT_CreateCertificate
   1.570 +	    (serialNumber,&(issuerCert->subject), validity, req);
   1.571 +    }
   1.572 +    
   1.573 +    CERT_DestroyValidity(validity);
   1.574 +    if ( issuerCert ) {
   1.575 +	CERT_DestroyCertificate (issuerCert);
   1.576 +    }
   1.577 +    return(cert);
   1.578 +}
   1.579 +
   1.580 +static int
   1.581 +get_serial_number(Pair  *data)
   1.582 +{
   1.583 +    int                 serial = 0;
   1.584 +    int                 error;
   1.585 +    char                *filename = SERIAL_FILE;
   1.586 +    char                *SN;
   1.587 +    FILE                *serialFile;
   1.588 +
   1.589 +
   1.590 +    if (find_field_bool(data, "serial-auto", PR_TRUE)) {
   1.591 +	serialFile = fopen(filename, "r");
   1.592 +	if (serialFile != NULL) {
   1.593 +	    fread(&serial, sizeof(int), 1, serialFile);
   1.594 +	    if (ferror(serialFile) != 0) {
   1.595 +		error_out("Error: Unable to read serial number file");
   1.596 +	    }
   1.597 +	    if (serial == 4294967295) {
   1.598 +		serial = 21;
   1.599 +	    }
   1.600 +	    fclose(serialFile);
   1.601 +	    ++serial;
   1.602 +	    serialFile = fopen(filename,"w");
   1.603 +	    if (serialFile == NULL) {
   1.604 +	        error_out("ERROR: Unable to open serial number file for writing");
   1.605 +	    }
   1.606 +	    fwrite(&serial, sizeof(int), 1, serialFile);
   1.607 +	    if (ferror(serialFile) != 0) {
   1.608 +		error_out("Error: Unable to write to serial number file");
   1.609 +	    }
   1.610 +	} else {
   1.611 +	    fclose(serialFile);
   1.612 +	    serialFile = fopen(filename,"w");
   1.613 +	    if (serialFile == NULL) {
   1.614 +		error_out("ERROR: Unable to open serial number file");
   1.615 +	    }
   1.616 +	    serial = 21;
   1.617 +	    fwrite(&serial, sizeof(int), 1, serialFile);
   1.618 +	    if (ferror(serialFile) != 0) {
   1.619 +		error_out("Error: Unable to write to serial number file");
   1.620 +	    }
   1.621 +	    error = ferror(serialFile);
   1.622 +	    if (error != 0) {
   1.623 +		error_out("ERROR: Unable to write to serial file");
   1.624 +	    }
   1.625 +	}
   1.626 +	fclose(serialFile);
   1.627 +    } else {
   1.628 +	SN = find_field(data, "serial_value", PR_TRUE);
   1.629 +	while (*SN != '\0') {
   1.630 +	    serial = serial * 16;
   1.631 +	    if ((*SN >= 'A') && (*SN <='F')) {
   1.632 +		serial += *SN - 'A' + 10; 
   1.633 +	    } else {
   1.634 +		if ((*SN >= 'a') && (*SN <='f')) {
   1.635 +		    serial += *SN - 'a' + 10;
   1.636 +		} else {
   1.637 +		    serial += *SN - '0';
   1.638 +		}
   1.639 +	    }
   1.640 +	    ++SN;
   1.641 +	}
   1.642 +    }
   1.643 +    return serial;
   1.644 +}
   1.645 +	
   1.646 +
   1.647 +
   1.648 +typedef SECStatus (* EXTEN_VALUE_ENCODER)
   1.649 +		(PLArenaPool *extHandle, void *value, SECItem *encodedValue);
   1.650 +
   1.651 +static SECStatus 
   1.652 +EncodeAndAddExtensionValue(
   1.653 +	PLArenaPool          *arena,
   1.654 +	void                 *extHandle, 
   1.655 +	void                 *value, 
   1.656 +	PRBool 		     criticality,
   1.657 +	int 		     extenType, 
   1.658 +	EXTEN_VALUE_ENCODER  EncodeValueFn)
   1.659 +{
   1.660 +    SECItem                  encodedValue;
   1.661 +    SECStatus                rv;
   1.662 +	
   1.663 +
   1.664 +    encodedValue.data = NULL;
   1.665 +    encodedValue.len = 0;
   1.666 +    rv = (*EncodeValueFn)(arena, value, &encodedValue);
   1.667 +    if (rv != SECSuccess) {
   1.668 +	error_out("ERROR: Unable to encode extension value");
   1.669 +    }
   1.670 +    rv = CERT_AddExtension
   1.671 +	(extHandle, extenType, &encodedValue, criticality, PR_TRUE);
   1.672 +    return (rv);
   1.673 +}
   1.674 +
   1.675 +
   1.676 +
   1.677 +static SECStatus 
   1.678 +AddKeyUsage (void  *extHandle, 
   1.679 +	     Pair  *data)
   1.680 +{
   1.681 +    SECItem        bitStringValue;
   1.682 +    unsigned char  keyUsage = 0x0;
   1.683 +
   1.684 +    if (find_field_bool(data,"keyUsage-digitalSignature", PR_TRUE)){
   1.685 +	keyUsage |= (0x80 >> 0);
   1.686 +    }
   1.687 +    if (find_field_bool(data,"keyUsage-nonRepudiation", PR_TRUE)){
   1.688 +	keyUsage |= (0x80 >> 1);
   1.689 +    }
   1.690 +    if (find_field_bool(data,"keyUsage-keyEncipherment", PR_TRUE)){
   1.691 +	keyUsage |= (0x80 >> 2);
   1.692 +    }
   1.693 +    if (find_field_bool(data,"keyUsage-dataEncipherment", PR_TRUE)){
   1.694 +	keyUsage |= (0x80 >> 3);
   1.695 +    }
   1.696 +    if (find_field_bool(data,"keyUsage-keyAgreement", PR_TRUE)){
   1.697 +	keyUsage |= (0x80 >> 4);
   1.698 +    }
   1.699 +    if (find_field_bool(data,"keyUsage-keyCertSign", PR_TRUE)) {
   1.700 +	keyUsage |= (0x80 >> 5);
   1.701 +    }
   1.702 +    if (find_field_bool(data,"keyUsage-cRLSign", PR_TRUE)) {
   1.703 +	keyUsage |= (0x80 >> 6);
   1.704 +    }
   1.705 +
   1.706 +    bitStringValue.data = &keyUsage;
   1.707 +    bitStringValue.len = 1;
   1.708 +
   1.709 +    return (CERT_EncodeAndAddBitStrExtension
   1.710 +	    (extHandle, SEC_OID_X509_KEY_USAGE, &bitStringValue,
   1.711 +	     (find_field_bool(data, "keyUsage-crit", PR_TRUE))));
   1.712 +
   1.713 +}
   1.714 +
   1.715 +static CERTOidSequence *
   1.716 +CreateOidSequence(void)
   1.717 +{
   1.718 +  CERTOidSequence *rv = (CERTOidSequence *)NULL;
   1.719 +  PLArenaPool *arena = (PLArenaPool *)NULL;
   1.720 +
   1.721 +  arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   1.722 +  if( (PLArenaPool *)NULL == arena ) {
   1.723 +    goto loser;
   1.724 +  }
   1.725 +
   1.726 +  rv = (CERTOidSequence *)PORT_ArenaZAlloc(arena, sizeof(CERTOidSequence));
   1.727 +  if( (CERTOidSequence *)NULL == rv ) {
   1.728 +    goto loser;
   1.729 +  }
   1.730 +
   1.731 +  rv->oids = (SECItem **)PORT_ArenaZAlloc(arena, sizeof(SECItem *));
   1.732 +  if( (SECItem **)NULL == rv->oids ) {
   1.733 +    goto loser;
   1.734 +  }
   1.735 +
   1.736 +  rv->arena = arena;
   1.737 +  return rv;
   1.738 +
   1.739 + loser:
   1.740 +  if( (PLArenaPool *)NULL != arena ) {
   1.741 +    PORT_FreeArena(arena, PR_FALSE);
   1.742 +  }
   1.743 +
   1.744 +  return (CERTOidSequence *)NULL;
   1.745 +}
   1.746 +
   1.747 +static SECStatus
   1.748 +AddOidToSequence(CERTOidSequence *os, SECOidTag oidTag)
   1.749 +{
   1.750 +  SECItem **oids;
   1.751 +  PRUint32 count = 0;
   1.752 +  SECOidData *od;
   1.753 +
   1.754 +  od = SECOID_FindOIDByTag(oidTag);
   1.755 +  if( (SECOidData *)NULL == od ) {
   1.756 +    return SECFailure;
   1.757 +  }
   1.758 +
   1.759 +  for( oids = os->oids; (SECItem *)NULL != *oids; oids++ ) {
   1.760 +    count++;
   1.761 +  }
   1.762 +
   1.763 +  /* ArenaZRealloc */
   1.764 +
   1.765 +  {
   1.766 +    PRUint32 i;
   1.767 +
   1.768 +    oids = (SECItem **)PORT_ArenaZAlloc(os->arena, sizeof(SECItem *) * (count+2));
   1.769 +    if( (SECItem **)NULL == oids ) {
   1.770 +      return SECFailure;
   1.771 +    }
   1.772 +    
   1.773 +    for( i = 0; i < count; i++ ) {
   1.774 +      oids[i] = os->oids[i];
   1.775 +    }
   1.776 +
   1.777 +    /* ArenaZFree(os->oids); */
   1.778 +  }
   1.779 +
   1.780 +  os->oids = oids;
   1.781 +  os->oids[count] = &od->oid;
   1.782 +
   1.783 +  return SECSuccess;
   1.784 +}
   1.785 +
   1.786 +static SECItem *
   1.787 +EncodeOidSequence(CERTOidSequence *os)
   1.788 +{
   1.789 +  SECItem *rv;
   1.790 +  extern const SEC_ASN1Template CERT_OidSeqTemplate[];
   1.791 +
   1.792 +  rv = (SECItem *)PORT_ArenaZAlloc(os->arena, sizeof(SECItem));
   1.793 +  if( (SECItem *)NULL == rv ) {
   1.794 +    goto loser;
   1.795 +  }
   1.796 +
   1.797 +  if( !SEC_ASN1EncodeItem(os->arena, rv, os, CERT_OidSeqTemplate) ) {
   1.798 +    goto loser;
   1.799 +  }
   1.800 +
   1.801 +  return rv;
   1.802 +
   1.803 + loser:
   1.804 +  return (SECItem *)NULL;
   1.805 +}
   1.806 +
   1.807 +static SECStatus
   1.808 +AddExtKeyUsage(void *extHandle, Pair *data)
   1.809 +{
   1.810 +  SECStatus rv;
   1.811 +  CERTOidSequence *os;
   1.812 +  SECItem *value;
   1.813 +  PRBool crit;
   1.814 +
   1.815 +  os = CreateOidSequence();
   1.816 +  if( (CERTOidSequence *)NULL == os ) {
   1.817 +    return SECFailure;
   1.818 +  }
   1.819 +
   1.820 +  if( find_field_bool(data, "extKeyUsage-serverAuth", PR_TRUE) ) {
   1.821 +    rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_SERVER_AUTH);
   1.822 +    if( SECSuccess != rv ) goto loser;
   1.823 +  }
   1.824 +
   1.825 +  if( find_field_bool(data, "extKeyUsage-msTrustListSign", PR_TRUE) ) {
   1.826 +    rv = AddOidToSequence(os, SEC_OID_MS_EXT_KEY_USAGE_CTL_SIGNING);
   1.827 +    if( SECSuccess != rv ) goto loser;
   1.828 +  }
   1.829 +
   1.830 +  if( find_field_bool(data, "extKeyUsage-clientAuth", PR_TRUE) ) {
   1.831 +    rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH);
   1.832 +    if( SECSuccess != rv ) goto loser;
   1.833 +  }
   1.834 +
   1.835 +  if( find_field_bool(data, "extKeyUsage-codeSign", PR_TRUE) ) {
   1.836 +    rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_CODE_SIGN);
   1.837 +    if( SECSuccess != rv ) goto loser;
   1.838 +  }
   1.839 +
   1.840 +  if( find_field_bool(data, "extKeyUsage-emailProtect", PR_TRUE) ) {
   1.841 +    rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT);
   1.842 +    if( SECSuccess != rv ) goto loser;
   1.843 +  }
   1.844 +
   1.845 +  if( find_field_bool(data, "extKeyUsage-timeStamp", PR_TRUE) ) {
   1.846 +    rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_TIME_STAMP);
   1.847 +    if( SECSuccess != rv ) goto loser;
   1.848 +  }
   1.849 +
   1.850 +  if( find_field_bool(data, "extKeyUsage-ocspResponder", PR_TRUE) ) {
   1.851 +    rv = AddOidToSequence(os, SEC_OID_OCSP_RESPONDER);
   1.852 +    if( SECSuccess != rv ) goto loser;
   1.853 +  }
   1.854 +
   1.855 +  if( find_field_bool(data, "extKeyUsage-NS-govtApproved", PR_TRUE) ) {
   1.856 +    rv = AddOidToSequence(os, SEC_OID_NS_KEY_USAGE_GOVT_APPROVED);
   1.857 +    if( SECSuccess != rv ) goto loser;
   1.858 +  }
   1.859 +
   1.860 +  value = EncodeOidSequence(os);
   1.861 +
   1.862 +  crit = find_field_bool(data, "extKeyUsage-crit", PR_TRUE);
   1.863 +
   1.864 +  rv = CERT_AddExtension(extHandle, SEC_OID_X509_EXT_KEY_USAGE, value,
   1.865 +                         crit, PR_TRUE);
   1.866 +  /*FALLTHROUGH*/
   1.867 + loser:
   1.868 +  CERT_DestroyOidSequence(os);
   1.869 +  return rv;
   1.870 +}
   1.871 +
   1.872 +static SECStatus
   1.873 +AddSubKeyID(void             *extHandle, 
   1.874 +	    Pair             *data, 
   1.875 +	    CERTCertificate  *subjectCert)
   1.876 +{
   1.877 +    SECItem                  encodedValue;
   1.878 +    SECStatus                rv;
   1.879 +    char                     *read;
   1.880 +    char                     *write;
   1.881 +    char                     *first;
   1.882 +    char                     character;
   1.883 +    int                      high_digit = 0,
   1.884 +	                     low_digit = 0;
   1.885 +    int                      len;
   1.886 +    PRBool                   odd = PR_FALSE;
   1.887 +
   1.888 +
   1.889 +    encodedValue.data = NULL;
   1.890 +    encodedValue.len = 0;
   1.891 +    first = read = write = find_field(data,"subjectKeyIdentifier-text", 
   1.892 +				      PR_TRUE);
   1.893 +    len = PORT_Strlen(first);
   1.894 +    odd = ((len % 2) != 0 ) ? PR_TRUE : PR_FALSE;
   1.895 +    if (find_field_bool(data, "subjectKeyIdentifier-radio-hex", PR_TRUE)) {
   1.896 +	if (odd) {
   1.897 +	    error_out("ERROR: Improperly formated subject key identifier, hex values must be expressed as an octet string");
   1.898 +	}
   1.899 +	while (*read != '\0') {
   1.900 +	    if (!isxdigit(*read)) {
   1.901 +		error_out("ERROR: Improperly formated subject key identifier");
   1.902 +	    }
   1.903 +	    *read = toupper(*read);
   1.904 +	    if ((*read >= 'A') && (*read <= 'F')) {
   1.905 +		high_digit = *read - 'A' + 10;
   1.906 +	    }  else {
   1.907 +		high_digit = *read - '0';
   1.908 +	    }
   1.909 +	    ++read;
   1.910 +	    if (!isxdigit(*read)) {
   1.911 +		error_out("ERROR: Improperly formated subject key identifier");
   1.912 +	    }
   1.913 +	    *read = toupper(*read);
   1.914 +	    if ((*read >= 'A') && (*read <= 'F')) {
   1.915 +		low_digit = *(read) - 'A' + 10;
   1.916 +	    } else {
   1.917 +		low_digit = *(read) - '0';
   1.918 +	    }
   1.919 +	    character = (high_digit << 4) | low_digit;
   1.920 +	    *write = character;
   1.921 +	    ++write;
   1.922 +	    ++read;
   1.923 +	}
   1.924 +	*write = '\0';
   1.925 +	len = write - first;
   1.926 +    }
   1.927 +    subjectCert->subjectKeyID.data = (unsigned char *) find_field
   1.928 +	(data,"subjectKeyIdentifier-text", PR_TRUE);
   1.929 +    subjectCert->subjectKeyID.len = len;
   1.930 +    rv = CERT_EncodeSubjectKeyID
   1.931 +	(NULL, &subjectCert->subjectKeyID, &encodedValue);
   1.932 +    if (rv) {
   1.933 +	return (rv);
   1.934 +    }
   1.935 +    return (CERT_AddExtension(extHandle,  SEC_OID_X509_SUBJECT_KEY_ID, 
   1.936 +			      &encodedValue, PR_FALSE, PR_TRUE));
   1.937 +}
   1.938 +
   1.939 +
   1.940 +static SECStatus 
   1.941 +AddAuthKeyID (void              *extHandle,
   1.942 +	      Pair              *data, 
   1.943 +	      char              *issuerNameStr, 
   1.944 +	      CERTCertDBHandle  *handle)
   1.945 +{
   1.946 +    CERTAuthKeyID               *authKeyID = NULL;    
   1.947 +    PLArenaPool                 *arena = NULL;
   1.948 +    SECStatus                   rv = SECSuccess;
   1.949 +    CERTCertificate             *issuerCert = NULL;
   1.950 +    CERTGeneralName             *genNames;
   1.951 +    CERTName                    *directoryName = NULL;
   1.952 +
   1.953 +
   1.954 +    issuerCert = CERT_FindCertByNameString(handle, issuerNameStr);
   1.955 +    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   1.956 +    if ( !arena ) {
   1.957 +	error_allocate();
   1.958 +    }
   1.959 +
   1.960 +    authKeyID = PORT_ArenaZAlloc (arena, sizeof (CERTAuthKeyID));
   1.961 +    if (authKeyID == NULL) {
   1.962 +	error_allocate();
   1.963 +    }
   1.964 +    if (find_field_bool(data, "authorityKeyIdentifier-radio-keyIdentifier", 
   1.965 +			PR_TRUE)) {
   1.966 +	authKeyID->keyID.data = PORT_ArenaAlloc (arena, PORT_Strlen 
   1.967 +				       ((char *)issuerCert->subjectKeyID.data));
   1.968 +	if (authKeyID->keyID.data == NULL) {
   1.969 +	    error_allocate();
   1.970 +	}
   1.971 +	PORT_Memcpy (authKeyID->keyID.data, issuerCert->subjectKeyID.data, 
   1.972 +		     authKeyID->keyID.len = 
   1.973 +		        PORT_Strlen((char *)issuerCert->subjectKeyID.data));
   1.974 +    } else {
   1.975 +	
   1.976 +	PORT_Assert (arena);
   1.977 +	genNames = (CERTGeneralName *) PORT_ArenaZAlloc (arena, (sizeof(CERTGeneralName)));
   1.978 +	if (genNames == NULL){
   1.979 +	    error_allocate();
   1.980 +	}
   1.981 +	genNames->l.next = genNames->l.prev = &(genNames->l);
   1.982 +	genNames->type = certDirectoryName;
   1.983 +
   1.984 +	directoryName = CERT_AsciiToName(issuerCert->subjectName);
   1.985 +	if (!directoryName) {
   1.986 +	    error_out("ERROR: Unable to create Directory Name");
   1.987 +	}
   1.988 +	rv = CERT_CopyName (arena, &genNames->name.directoryName, 
   1.989 +			    directoryName);
   1.990 +        CERT_DestroyName (directoryName);
   1.991 +	if (rv != SECSuccess) {
   1.992 +	    error_out("ERROR: Unable to copy Directory Name");
   1.993 +	}
   1.994 +	authKeyID->authCertIssuer = genNames;
   1.995 +	if (authKeyID->authCertIssuer == NULL && SECFailure == 
   1.996 +	                                            PORT_GetError ()) {
   1.997 +	    error_out("ERROR: Unable to get Issuer General Name for Authority Key ID Extension");
   1.998 +	}
   1.999 +	authKeyID->authCertSerialNumber = issuerCert->serialNumber;
  1.1000 +    }
  1.1001 +    rv = EncodeAndAddExtensionValue(arena, extHandle, authKeyID, PR_FALSE, 
  1.1002 +				    SEC_OID_X509_AUTH_KEY_ID, 
  1.1003 +				    (EXTEN_VALUE_ENCODER)
  1.1004 +				    CERT_EncodeAuthKeyID);
  1.1005 +    if (arena) {
  1.1006 +	PORT_FreeArena (arena, PR_FALSE);
  1.1007 +    }
  1.1008 +    return (rv);
  1.1009 +}
  1.1010 +
  1.1011 +
  1.1012 +static SECStatus 
  1.1013 +AddPrivKeyUsagePeriod(void             *extHandle, 
  1.1014 +		      Pair             *data, 
  1.1015 +		      CERTCertificate  *cert)
  1.1016 +{
  1.1017 +    char *notBeforeStr;
  1.1018 +    char *notAfterStr;
  1.1019 +    PLArenaPool *arena = NULL;
  1.1020 +    SECStatus rv = SECSuccess;
  1.1021 +    CERTPrivKeyUsagePeriod *pkup;
  1.1022 +
  1.1023 +
  1.1024 +    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1.1025 +    if ( !arena ) {
  1.1026 +	error_allocate();
  1.1027 +    }
  1.1028 +    pkup = PORT_ArenaZNew (arena, CERTPrivKeyUsagePeriod);
  1.1029 +    if (pkup == NULL) {
  1.1030 +	error_allocate();
  1.1031 +    }
  1.1032 +    notBeforeStr = (char *) PORT_Alloc(16 );
  1.1033 +    notAfterStr = (char *) PORT_Alloc(16 );
  1.1034 +    *notBeforeStr = '\0';
  1.1035 +    *notAfterStr = '\0';
  1.1036 +    pkup->arena = arena;
  1.1037 +    pkup->notBefore.len = 0;
  1.1038 +    pkup->notBefore.data = NULL;
  1.1039 +    pkup->notAfter.len = 0;
  1.1040 +    pkup->notAfter.data = NULL;
  1.1041 +    if (find_field_bool(data, "privKeyUsagePeriod-radio-notBefore", PR_TRUE) ||
  1.1042 +	find_field_bool(data, "privKeyUsagePeriod-radio-both", PR_TRUE)) {
  1.1043 +	pkup->notBefore.len = 15;
  1.1044 +	pkup->notBefore.data = (unsigned char *)notBeforeStr;
  1.1045 +	if (find_field_bool(data, "privKeyUsagePeriod-notBefore-radio-manual", 
  1.1046 +			    PR_TRUE)) {
  1.1047 +	    PORT_Strcat(notBeforeStr,find_field(data,
  1.1048 +					   "privKeyUsagePeriod-notBefore-year",
  1.1049 +					   PR_TRUE));
  1.1050 +	    PORT_Strcat(notBeforeStr,find_field(data,
  1.1051 +					   "privKeyUsagePeriod-notBefore-month",
  1.1052 +					   PR_TRUE));
  1.1053 +	    PORT_Strcat(notBeforeStr,find_field(data,
  1.1054 +					   "privKeyUsagePeriod-notBefore-day",
  1.1055 +					   PR_TRUE));
  1.1056 +	    PORT_Strcat(notBeforeStr,find_field(data,
  1.1057 +					   "privKeyUsagePeriod-notBefore-hour",
  1.1058 +					   PR_TRUE));
  1.1059 +	    PORT_Strcat(notBeforeStr,find_field(data,
  1.1060 +					  "privKeyUsagePeriod-notBefore-minute",
  1.1061 +					   PR_TRUE));
  1.1062 +	    PORT_Strcat(notBeforeStr,find_field(data,
  1.1063 +					  "privKeyUsagePeriod-notBefore-second",
  1.1064 +					   PR_TRUE));
  1.1065 +	    if ((*(notBeforeStr + 14) != '\0') ||
  1.1066 +		(!isdigit(*(notBeforeStr + 13))) ||
  1.1067 +		(*(notBeforeStr + 12) >= '5' && *(notBeforeStr + 12) <= '0') ||
  1.1068 +		(!isdigit(*(notBeforeStr + 11))) ||
  1.1069 +		(*(notBeforeStr + 10) >= '5' && *(notBeforeStr + 10) <= '0') ||
  1.1070 +		(!isdigit(*(notBeforeStr + 9))) ||
  1.1071 +		(*(notBeforeStr + 8) >= '2' && *(notBeforeStr + 8) <= '0') ||
  1.1072 +		(!isdigit(*(notBeforeStr + 7))) ||
  1.1073 +		(*(notBeforeStr + 6) >= '3' && *(notBeforeStr + 6) <= '0') ||
  1.1074 +		(!isdigit(*(notBeforeStr + 5))) ||
  1.1075 +		(*(notBeforeStr + 4) >= '1' && *(notBeforeStr + 4) <= '0') ||
  1.1076 +		(!isdigit(*(notBeforeStr + 3))) ||
  1.1077 +		(!isdigit(*(notBeforeStr + 2))) ||
  1.1078 +		(!isdigit(*(notBeforeStr + 1))) ||
  1.1079 +		(!isdigit(*(notBeforeStr + 0))) ||
  1.1080 +		(*(notBeforeStr + 8) == '2' && *(notBeforeStr + 9) >= '4') ||
  1.1081 +		(*(notBeforeStr + 6) == '3' && *(notBeforeStr + 7) >= '1') ||
  1.1082 +		(*(notBeforeStr + 4) == '1' && *(notBeforeStr + 5) >= '2')) {
  1.1083 +		error_out("ERROR: Improperly formated private key usage period");
  1.1084 +	    }
  1.1085 +	    *(notBeforeStr + 14) = 'Z';
  1.1086 +	    *(notBeforeStr + 15) = '\0';
  1.1087 +	} else {
  1.1088 +	    if ((*(cert->validity.notBefore.data) > '5') || 
  1.1089 +		((*(cert->validity.notBefore.data) == '5') &&
  1.1090 +		 (*(cert->validity.notBefore.data + 1) != '0'))) {
  1.1091 +		PORT_Strcat(notBeforeStr, "19");
  1.1092 +	    } else {
  1.1093 +		PORT_Strcat(notBeforeStr, "20");
  1.1094 +	    }
  1.1095 +	    PORT_Strcat(notBeforeStr, (char *)cert->validity.notBefore.data);
  1.1096 +	}
  1.1097 +    }
  1.1098 +    if (find_field_bool(data, "privKeyUsagePeriod-radio-notAfter", PR_TRUE) ||
  1.1099 +	find_field_bool(data, "privKeyUsagePeriod-radio-both", PR_TRUE)) {
  1.1100 +	pkup->notAfter.len = 15;
  1.1101 +	pkup->notAfter.data = (unsigned char *)notAfterStr;
  1.1102 +	PORT_Strcat(notAfterStr,find_field(data,"privKeyUsagePeriod-notAfter-year", 
  1.1103 +				      PR_TRUE));
  1.1104 +	PORT_Strcat(notAfterStr,find_field(data,"privKeyUsagePeriod-notAfter-month",
  1.1105 +				      PR_TRUE));
  1.1106 +	PORT_Strcat(notAfterStr,find_field(data,"privKeyUsagePeriod-notAfter-day", 
  1.1107 +				      PR_TRUE));
  1.1108 +	PORT_Strcat(notAfterStr,find_field(data,"privKeyUsagePeriod-notAfter-hour", 
  1.1109 +				      PR_TRUE));
  1.1110 +	PORT_Strcat(notAfterStr,find_field(data,"privKeyUsagePeriod-notAfter-minute",
  1.1111 +				      PR_TRUE));
  1.1112 +	PORT_Strcat(notAfterStr,find_field(data,"privKeyUsagePeriod-notAfter-second",
  1.1113 +				      PR_TRUE));
  1.1114 +	if ((*(notAfterStr + 14) != '\0') ||
  1.1115 +	    (!isdigit(*(notAfterStr + 13))) ||
  1.1116 +	    (*(notAfterStr + 12) >= '5' && *(notAfterStr + 12) <= '0') ||
  1.1117 +	    (!isdigit(*(notAfterStr + 11))) ||
  1.1118 +	    (*(notAfterStr + 10) >= '5' && *(notAfterStr + 10) <= '0') ||
  1.1119 +	    (!isdigit(*(notAfterStr + 9))) ||
  1.1120 +	    (*(notAfterStr + 8) >= '2' && *(notAfterStr + 8) <= '0') ||
  1.1121 +	    (!isdigit(*(notAfterStr + 7))) ||
  1.1122 +	    (*(notAfterStr + 6) >= '3' && *(notAfterStr + 6) <= '0') ||
  1.1123 +	    (!isdigit(*(notAfterStr + 5))) ||
  1.1124 +	    (*(notAfterStr + 4) >= '1' && *(notAfterStr + 4) <= '0') ||
  1.1125 +	    (!isdigit(*(notAfterStr + 3))) ||
  1.1126 +	    (!isdigit(*(notAfterStr + 2))) ||
  1.1127 +	    (!isdigit(*(notAfterStr + 1))) ||
  1.1128 +	    (!isdigit(*(notAfterStr + 0))) ||
  1.1129 +	    (*(notAfterStr + 8) == '2' && *(notAfterStr + 9) >= '4') ||
  1.1130 +	    (*(notAfterStr + 6) == '3' && *(notAfterStr + 7) >= '1') ||
  1.1131 +	    (*(notAfterStr + 4) == '1' && *(notAfterStr + 5) >= '2')) {
  1.1132 +	    error_out("ERROR: Improperly formated private key usage period");
  1.1133 +	}
  1.1134 +	*(notAfterStr + 14) = 'Z';
  1.1135 +	*(notAfterStr + 15) = '\0';
  1.1136 +    }
  1.1137 +	
  1.1138 +    PORT_Assert (arena);
  1.1139 +
  1.1140 +    rv = EncodeAndAddExtensionValue(arena, extHandle, pkup, 
  1.1141 +				    find_field_bool(data,
  1.1142 +						    "privKeyUsagePeriod-crit", 
  1.1143 +						    PR_TRUE), 
  1.1144 +				    SEC_OID_X509_PRIVATE_KEY_USAGE_PERIOD, 
  1.1145 +				    (EXTEN_VALUE_ENCODER)
  1.1146 +				    CERT_EncodePrivateKeyUsagePeriod);
  1.1147 +    if (arena) {
  1.1148 +	PORT_FreeArena (arena, PR_FALSE);
  1.1149 +    }
  1.1150 +    if (notBeforeStr != NULL) {
  1.1151 +	PORT_Free(notBeforeStr);
  1.1152 +    }
  1.1153 +    if (notAfterStr != NULL) {
  1.1154 +	PORT_Free(notAfterStr);
  1.1155 +    }
  1.1156 +    return (rv);
  1.1157 +}    
  1.1158 +
  1.1159 +static SECStatus 
  1.1160 +AddBasicConstraint(void   *extHandle, 
  1.1161 +		   Pair   *data)
  1.1162 +{
  1.1163 +    CERTBasicConstraints  basicConstraint;
  1.1164 +    SECItem               encodedValue;
  1.1165 +    SECStatus             rv;
  1.1166 +
  1.1167 +    encodedValue.data = NULL;
  1.1168 +    encodedValue.len = 0;
  1.1169 +    basicConstraint.pathLenConstraint = CERT_UNLIMITED_PATH_CONSTRAINT;
  1.1170 +    basicConstraint.isCA = (find_field_bool(data,"basicConstraints-cA-radio-CA",
  1.1171 +					    PR_TRUE));
  1.1172 +    if (find_field_bool(data,"basicConstraints-pathLengthConstraint", PR_TRUE)){
  1.1173 +	basicConstraint.pathLenConstraint = atoi 
  1.1174 +	    (find_field(data,"basicConstraints-pathLengthConstraint-text", 
  1.1175 +			PR_TRUE));
  1.1176 +    }
  1.1177 +    
  1.1178 +    rv = CERT_EncodeBasicConstraintValue (NULL, &basicConstraint, 
  1.1179 +					  &encodedValue);
  1.1180 +    if (rv)
  1.1181 +	return (rv);
  1.1182 +    rv = CERT_AddExtension(extHandle, SEC_OID_X509_BASIC_CONSTRAINTS, 
  1.1183 +			   &encodedValue, 
  1.1184 +			   (find_field_bool(data,"basicConstraints-crit", 
  1.1185 +					    PR_TRUE)), PR_TRUE);
  1.1186 +
  1.1187 +    PORT_Free (encodedValue.data);
  1.1188 +    return (rv);
  1.1189 +}
  1.1190 +
  1.1191 +
  1.1192 +
  1.1193 +static SECStatus 
  1.1194 +AddNscpCertType (void  *extHandle, 
  1.1195 +		 Pair  *data)
  1.1196 +{
  1.1197 +    SECItem            bitStringValue;
  1.1198 +    unsigned char      CertType = 0x0;
  1.1199 +
  1.1200 +    if (find_field_bool(data,"netscape-cert-type-ssl-client", PR_TRUE)){
  1.1201 +	CertType |= (0x80 >> 0);
  1.1202 +    }
  1.1203 +    if (find_field_bool(data,"netscape-cert-type-ssl-server", PR_TRUE)){
  1.1204 +	CertType |= (0x80 >> 1);
  1.1205 +    }
  1.1206 +    if (find_field_bool(data,"netscape-cert-type-smime", PR_TRUE)){
  1.1207 +	CertType |= (0x80 >> 2);
  1.1208 +    }
  1.1209 +    if (find_field_bool(data,"netscape-cert-type-object-signing", PR_TRUE)){
  1.1210 +	CertType |= (0x80 >> 3);
  1.1211 +    }
  1.1212 +    if (find_field_bool(data,"netscape-cert-type-reserved", PR_TRUE)){
  1.1213 +	CertType |= (0x80 >> 4);
  1.1214 +    }
  1.1215 +    if (find_field_bool(data,"netscape-cert-type-ssl-ca", PR_TRUE)) {
  1.1216 +	CertType |= (0x80 >> 5);
  1.1217 +    }
  1.1218 +    if (find_field_bool(data,"netscape-cert-type-smime-ca", PR_TRUE)) {
  1.1219 +	CertType |= (0x80 >> 6);
  1.1220 +    }
  1.1221 +    if (find_field_bool(data,"netscape-cert-type-object-signing-ca", PR_TRUE)) {
  1.1222 +	CertType |= (0x80 >> 7);
  1.1223 +    }
  1.1224 +
  1.1225 +    bitStringValue.data = &CertType;
  1.1226 +    bitStringValue.len = 1;
  1.1227 +
  1.1228 +    return (CERT_EncodeAndAddBitStrExtension
  1.1229 +	    (extHandle, SEC_OID_NS_CERT_EXT_CERT_TYPE, &bitStringValue,
  1.1230 +	     (find_field_bool(data, "netscape-cert-type-crit", PR_TRUE))));
  1.1231 +}
  1.1232 +
  1.1233 +
  1.1234 +static SECStatus
  1.1235 +add_IA5StringExtension(void    *extHandle, 
  1.1236 +		       char    *string, 
  1.1237 +		       PRBool  crit, 
  1.1238 +		       int     idtag)
  1.1239 +{
  1.1240 +    SECItem                    encodedValue;
  1.1241 +    SECStatus                  rv;
  1.1242 +
  1.1243 +    encodedValue.data = NULL;
  1.1244 +    encodedValue.len = 0;
  1.1245 +
  1.1246 +    rv = CERT_EncodeIA5TypeExtension(NULL, string, &encodedValue);
  1.1247 +    if (rv) {
  1.1248 +	return (rv);
  1.1249 +    }
  1.1250 +    return (CERT_AddExtension(extHandle, idtag, &encodedValue, crit, PR_TRUE));
  1.1251 +}
  1.1252 +
  1.1253 +static SECItem *
  1.1254 +string_to_oid(char  *string)
  1.1255 +{
  1.1256 +    int             i;
  1.1257 +    int             length = 20;
  1.1258 +    int             remaining;
  1.1259 +    int             first_value;
  1.1260 +    int             second_value;
  1.1261 +    int             value;
  1.1262 +    int             oidLength;
  1.1263 +    unsigned char   *oidString;
  1.1264 +    unsigned char   *write;
  1.1265 +    unsigned char   *read;
  1.1266 +    unsigned char   *temp;
  1.1267 +    SECItem         *oid;
  1.1268 +    
  1.1269 +    
  1.1270 +    remaining = length;
  1.1271 +    i = 0;
  1.1272 +    while (*string == ' ') {
  1.1273 +	string++;
  1.1274 +    }
  1.1275 +    while (isdigit(*(string + i))) {
  1.1276 +	i++;
  1.1277 +    }
  1.1278 +    if (*(string + i) == '.') {
  1.1279 +	*(string + i) = '\0';
  1.1280 +    } else {
  1.1281 +	error_out("ERROR: Improperly formated OID");
  1.1282 +    }
  1.1283 +    first_value = atoi(string);
  1.1284 +    if (first_value < 0 || first_value > 2) {
  1.1285 +	error_out("ERROR: Improperly formated OID");
  1.1286 +    }
  1.1287 +    string += i + 1;
  1.1288 +    i = 0;
  1.1289 +    while (isdigit(*(string + i))) {
  1.1290 +	i++;
  1.1291 +    }
  1.1292 +    if (*(string + i) == '.') {
  1.1293 +	*(string + i) = '\0';
  1.1294 +    } else {
  1.1295 +	error_out("ERROR: Improperly formated OID");
  1.1296 +    }
  1.1297 +    second_value = atoi(string);
  1.1298 +    if (second_value < 0 || second_value > 39) {
  1.1299 +	error_out("ERROR: Improperly formated OID");
  1.1300 +    }
  1.1301 +    oidString = PORT_ZAlloc(2);
  1.1302 +    *oidString = (first_value * 40) + second_value;
  1.1303 +    *(oidString + 1) = '\0';
  1.1304 +    oidLength = 1;
  1.1305 +    string += i + 1;
  1.1306 +    i = 0;
  1.1307 +    temp = write = PORT_ZAlloc(length);
  1.1308 +    while (*string != '\0') {
  1.1309 +	value = 0;
  1.1310 +	while(isdigit(*(string + i))) {
  1.1311 +	    i++;
  1.1312 +	}
  1.1313 +	if (*(string + i) == '\0') {
  1.1314 +	    value = atoi(string);
  1.1315 +	    string += i;
  1.1316 +	} else {
  1.1317 +	    if (*(string + i) == '.') {
  1.1318 +		*(string + i) = '\0';
  1.1319 +		value = atoi(string);
  1.1320 +		string += i + 1;
  1.1321 +	    } else {
  1.1322 +		*(string + i) = '\0';
  1.1323 +		i++;
  1.1324 +		value = atoi(string);
  1.1325 +		while (*(string + i) == ' ')
  1.1326 +		    i++;
  1.1327 +		if (*(string + i) != '\0') {
  1.1328 +		    error_out("ERROR: Improperly formated OID");
  1.1329 +		}
  1.1330 +	    }
  1.1331 +	}
  1.1332 +	i = 0;
  1.1333 +	while (value != 0) {
  1.1334 +	    if (remaining < 1) {
  1.1335 +		remaining += length;
  1.1336 +		length = length * 2;
  1.1337 +		temp = PORT_Realloc(temp, length);
  1.1338 +		write = temp + length - remaining;
  1.1339 +	    }
  1.1340 +	    *write = (value & 0x7f) | (0x80);
  1.1341 +	    write++;
  1.1342 +	    remaining--;
  1.1343 +	    value = value >> 7;
  1.1344 +	}
  1.1345 +	*temp = *temp & (0x7f);
  1.1346 +	oidLength += write - temp;
  1.1347 +	oidString = PORT_Realloc(oidString, (oidLength + 1));
  1.1348 +	read = write - 1;
  1.1349 +	write = oidLength + oidString - 1;
  1.1350 +	for (i = 0; i < (length - remaining); i++) {
  1.1351 +	    *write = *read;
  1.1352 +	    write--;
  1.1353 +	    read++;
  1.1354 +	}
  1.1355 +	write = temp;
  1.1356 +	remaining = length;
  1.1357 +    }
  1.1358 +    *(oidString + oidLength) = '\0';
  1.1359 +    oid = (SECItem *) PORT_ZAlloc(sizeof(SECItem));
  1.1360 +    oid->data = oidString;
  1.1361 +    oid->len  = oidLength;
  1.1362 +    PORT_Free(temp);
  1.1363 +    return oid;
  1.1364 +}
  1.1365 +
  1.1366 +static SECItem *
  1.1367 +string_to_ipaddress(char *string)
  1.1368 +{
  1.1369 +    int      i = 0;
  1.1370 +    int      value;
  1.1371 +    int      j = 0;
  1.1372 +    SECItem  *ipaddress;
  1.1373 +    
  1.1374 +
  1.1375 +    while (*string == ' ') {
  1.1376 +	string++;
  1.1377 +    }
  1.1378 +    ipaddress = (SECItem *) PORT_ZAlloc(sizeof(SECItem));
  1.1379 +    ipaddress->data = PORT_ZAlloc(9);
  1.1380 +    while (*string != '\0' && j < 8) {
  1.1381 +	while (isdigit(*(string + i))) {
  1.1382 +	    i++;
  1.1383 +	}
  1.1384 +	if (*(string + i) == '.') {
  1.1385 +	    *(string + i) = '\0';
  1.1386 +	    value = atoi(string);
  1.1387 +	    string = string + i + 1;
  1.1388 +	    i = 0;
  1.1389 +	} else {
  1.1390 +	    if (*(string + i) == '\0') {
  1.1391 +		value = atoi(string);
  1.1392 +		string = string + i;
  1.1393 +		i = 0;
  1.1394 +	    } else {
  1.1395 +		*(string + i) = '\0';
  1.1396 +		while (*(string + i) == ' ') {
  1.1397 +		    i++;
  1.1398 +		}
  1.1399 +		if (*(string + i) == '\0') {
  1.1400 +		    value = atoi(string);
  1.1401 +		    string = string + i;
  1.1402 +		    i = 0;
  1.1403 +		} else {
  1.1404 +		    error_out("ERROR: Improperly formated IP Address");
  1.1405 +		}
  1.1406 +	    }
  1.1407 +	}
  1.1408 +	if (value >= 0 && value < 256) {
  1.1409 +	    *(ipaddress->data + j) = value;
  1.1410 +	} else {
  1.1411 +	    error_out("ERROR: Improperly formated IP Address");
  1.1412 +	}
  1.1413 +	j++;
  1.1414 +    }
  1.1415 +    *(ipaddress->data + j) = '\0';
  1.1416 +    if (j != 4 && j != 8) {
  1.1417 +	error_out("ERROR: Improperly formated IP Address");
  1.1418 +    }
  1.1419 +    ipaddress->len = j;
  1.1420 +    return ipaddress;
  1.1421 +}
  1.1422 +
  1.1423 +static SECItem *
  1.1424 +string_to_binary(char  *string)
  1.1425 +{
  1.1426 +    SECItem            *rv;
  1.1427 +    int                high_digit;
  1.1428 +    int                low_digit;
  1.1429 +
  1.1430 +    rv = (SECItem *) PORT_ZAlloc(sizeof(SECItem));
  1.1431 +    if (rv == NULL) {
  1.1432 +	error_allocate();
  1.1433 +    }
  1.1434 +    rv->data = (unsigned char *) PORT_ZAlloc((PORT_Strlen(string))/3 + 2);
  1.1435 +    while (!isxdigit(*string)) {
  1.1436 +	string++;
  1.1437 +    }
  1.1438 +    rv->len = 0;
  1.1439 +    while (*string != '\0') {
  1.1440 +	if (isxdigit(*string)) {
  1.1441 +	    if (*string >= '0' && *string <= '9') {
  1.1442 +		high_digit = *string - '0';
  1.1443 +	    } else {
  1.1444 +		*string = toupper(*string);
  1.1445 +		high_digit = *string - 'A' + 10;
  1.1446 +	    }
  1.1447 +	    string++;
  1.1448 +	    if (*string >= '0' && *string <= '9') {
  1.1449 +		low_digit = *string - '0';
  1.1450 +	    } else {
  1.1451 +		*string = toupper(*string);
  1.1452 +		low_digit = *string - 'A' + 10;
  1.1453 +	    }
  1.1454 +	    (rv->len)++;
  1.1455 +	} else {
  1.1456 +	    if (*string == ':') {
  1.1457 +		string++;
  1.1458 +	    } else {
  1.1459 +		if (*string == ' ') {
  1.1460 +		    while (*string == ' ') {
  1.1461 +			string++;
  1.1462 +		    }
  1.1463 +		}
  1.1464 +		if (*string != '\0') {
  1.1465 +		    error_out("ERROR: Improperly formated binary encoding");
  1.1466 +		}
  1.1467 +	    }
  1.1468 +	} 
  1.1469 +    }
  1.1470 +
  1.1471 +    return rv;
  1.1472 +}
  1.1473 +
  1.1474 +static SECStatus
  1.1475 +MakeGeneralName(char             *name, 
  1.1476 +		CERTGeneralName  *genName,
  1.1477 +		PLArenaPool      *arena)
  1.1478 +{
  1.1479 +    SECItem                      *oid;
  1.1480 +    SECOidData                   *oidData;
  1.1481 +    SECItem                      *ipaddress;
  1.1482 +    SECItem                      *temp = NULL;
  1.1483 +    int                          i;
  1.1484 +    int                          nameType;
  1.1485 +    PRBool                       binary = PR_FALSE;
  1.1486 +    SECStatus                    rv = SECSuccess;
  1.1487 +    PRBool                       nickname = PR_FALSE;
  1.1488 +
  1.1489 +    PORT_Assert(genName);
  1.1490 +    PORT_Assert(arena);
  1.1491 +    nameType = *(name + PORT_Strlen(name) - 1) - '0';
  1.1492 +    if (nameType == 0  && *(name +PORT_Strlen(name) - 2) == '1') {
  1.1493 +	nickname = PR_TRUE;
  1.1494 +	nameType = certOtherName;
  1.1495 +    }
  1.1496 +    if (nameType < 1 || nameType > 9) {
  1.1497 +	error_out("ERROR: Unknown General Name Type");
  1.1498 +    }
  1.1499 +    *(name + PORT_Strlen(name) - 4) = '\0';
  1.1500 +    genName->type = nameType;
  1.1501 +    
  1.1502 +    switch (genName->type) {
  1.1503 +      case certURI:
  1.1504 +      case certRFC822Name:
  1.1505 +      case certDNSName: {
  1.1506 +	  genName->name.other.data = (unsigned char *)name;
  1.1507 +	  genName->name.other.len = PORT_Strlen(name);
  1.1508 +	  break;
  1.1509 +      }
  1.1510 +      
  1.1511 +      case certIPAddress: {
  1.1512 +	  ipaddress = string_to_ipaddress(name);
  1.1513 +	  genName->name.other.data = ipaddress->data;
  1.1514 +	  genName->name.other.len = ipaddress->len;
  1.1515 +	  break;
  1.1516 +      }
  1.1517 +      
  1.1518 +      case certRegisterID: {
  1.1519 +	  oid = string_to_oid(name);
  1.1520 +	  genName->name.other.data = oid->data;
  1.1521 +	  genName->name.other.len = oid->len;
  1.1522 +	  break;
  1.1523 +      }
  1.1524 +      
  1.1525 +      case certEDIPartyName:
  1.1526 +      case certX400Address: {
  1.1527 +	  
  1.1528 +	  genName->name.other.data = PORT_ArenaAlloc (arena, 
  1.1529 +						      PORT_Strlen (name) + 2);
  1.1530 +	  if (genName->name.other.data == NULL) {
  1.1531 +	      error_allocate();
  1.1532 +	  }
  1.1533 +	  
  1.1534 +	  PORT_Memcpy (genName->name.other.data + 2, name, PORT_Strlen (name));
  1.1535 +	  /* This may not be accurate for all cases.  
  1.1536 +	     For now, use this tag type */
  1.1537 +	  genName->name.other.data[0] = (char)(((genName->type - 1) & 
  1.1538 +						0x1f)| 0x80);
  1.1539 +	  genName->name.other.data[1] = (char)PORT_Strlen (name);
  1.1540 +	  genName->name.other.len = PORT_Strlen (name) + 2;
  1.1541 +	  break;
  1.1542 +      }
  1.1543 +      
  1.1544 +      case certOtherName: {
  1.1545 +	  i = 0;
  1.1546 +	  if (!nickname) {
  1.1547 +	      while (!isdigit(*(name + PORT_Strlen(name) - i))) {
  1.1548 +		  i++;
  1.1549 +	      }
  1.1550 +	      if (*(name + PORT_Strlen(name) - i) == '1') {
  1.1551 +		  binary = PR_TRUE;
  1.1552 +	      } else {
  1.1553 +		  binary = PR_FALSE;
  1.1554 +	      }  
  1.1555 +	      while (*(name + PORT_Strlen(name) - i) != '-') {
  1.1556 +		  i++;
  1.1557 +	      }
  1.1558 +	      *(name + PORT_Strlen(name) - i - 1) = '\0';
  1.1559 +	      i = 0;
  1.1560 +	      while (*(name + i) != '-') {
  1.1561 +		  i++;
  1.1562 +	      }
  1.1563 +	      *(name + i - 1) = '\0';
  1.1564 +	      oid = string_to_oid(name + i + 2);
  1.1565 +	  } else {
  1.1566 +	      oidData = SECOID_FindOIDByTag(SEC_OID_NETSCAPE_NICKNAME);
  1.1567 +	      oid = &oidData->oid;
  1.1568 +	      while (*(name + PORT_Strlen(name) - i) != '-') {
  1.1569 +		  i++;
  1.1570 +	      }
  1.1571 +	      *(name + PORT_Strlen(name) - i) = '\0';
  1.1572 +	  }
  1.1573 +	  genName->name.OthName.oid.data = oid->data;
  1.1574 +	  genName->name.OthName.oid.len  = oid->len;
  1.1575 +	  if (binary) {
  1.1576 +	      temp = string_to_binary(name);
  1.1577 +	      genName->name.OthName.name.data = temp->data;
  1.1578 +	      genName->name.OthName.name.len = temp->len;
  1.1579 +	  } else {
  1.1580 +	      temp = (SECItem *) PORT_ZAlloc(sizeof(SECItem));
  1.1581 +	      if (temp == NULL) {
  1.1582 +		  error_allocate();
  1.1583 +	      }
  1.1584 +	      temp->data = (unsigned char *)name;
  1.1585 +	      temp->len = PORT_Strlen(name);
  1.1586 +	      SEC_ASN1EncodeItem (arena, &(genName->name.OthName.name), temp,
  1.1587 +				  CERTIA5TypeTemplate);
  1.1588 +	  }
  1.1589 +	  PORT_Free(temp);
  1.1590 +	  break;
  1.1591 +      }
  1.1592 +      
  1.1593 +      case certDirectoryName: {
  1.1594 +	  CERTName *directoryName = NULL;
  1.1595 +	  
  1.1596 +	  directoryName = CERT_AsciiToName (name);
  1.1597 +	  if (!directoryName) {
  1.1598 +	      error_out("ERROR: Improperly formated alternative name");
  1.1599 +	      break;
  1.1600 +	  }
  1.1601 +	  rv = CERT_CopyName (arena, &genName->name.directoryName, 
  1.1602 +			      directoryName);
  1.1603 +	  CERT_DestroyName (directoryName);
  1.1604 +	  
  1.1605 +	  break;
  1.1606 +      }
  1.1607 +    }
  1.1608 +    genName->l.next = &(genName->l);
  1.1609 +    genName->l.prev = &(genName->l);
  1.1610 +    return rv;
  1.1611 +}
  1.1612 +
  1.1613 +
  1.1614 +static CERTGeneralName *
  1.1615 +MakeAltName(Pair             *data, 
  1.1616 +	    char             *which, 
  1.1617 +	    PLArenaPool      *arena)
  1.1618 +{
  1.1619 +    CERTGeneralName          *SubAltName;
  1.1620 +    CERTGeneralName          *current;
  1.1621 +    CERTGeneralName          *newname;
  1.1622 +    char                     *name = NULL;
  1.1623 +    SECStatus                rv = SECSuccess;
  1.1624 +    int                      len;
  1.1625 +    
  1.1626 +
  1.1627 +    len = PORT_Strlen(which);
  1.1628 +    name = find_field(data, which, PR_TRUE);
  1.1629 +    SubAltName = current = (CERTGeneralName *) PORT_ZAlloc
  1.1630 +	                                        (sizeof(CERTGeneralName));
  1.1631 +    if (current == NULL) {
  1.1632 +	error_allocate();
  1.1633 +    }
  1.1634 +    while (name != NULL) {
  1.1635 +
  1.1636 +	rv = MakeGeneralName(name, current, arena);
  1.1637 +
  1.1638 +	if (rv != SECSuccess) {
  1.1639 +	    break;
  1.1640 +	}
  1.1641 +	if (*(which + len -1) < '9') {
  1.1642 +	    *(which + len - 1) = *(which + len - 1) + 1;
  1.1643 +	} else {
  1.1644 +	    if (isdigit(*(which + len - 2) )) {
  1.1645 +		*(which + len - 2) = *(which + len - 2) + 1;
  1.1646 +		*(which + len - 1) = '0';
  1.1647 +	    } else {
  1.1648 +		*(which + len - 1) = '1';
  1.1649 +		*(which + len) = '0';
  1.1650 +		*(which + len + 1) = '\0';
  1.1651 +		len++;
  1.1652 +	    }
  1.1653 +	}
  1.1654 +	len = PORT_Strlen(which);
  1.1655 +	name = find_field(data, which, PR_TRUE);
  1.1656 +	if (name != NULL) {
  1.1657 +	    newname = (CERTGeneralName *) PORT_ZAlloc(sizeof(CERTGeneralName));
  1.1658 +	    if (newname == NULL) {
  1.1659 +		error_allocate();
  1.1660 +	    }
  1.1661 +	    current->l.next = &(newname->l);
  1.1662 +	    newname->l.prev = &(current->l);
  1.1663 +	    current = newname;
  1.1664 +            newname = NULL;
  1.1665 +	} else {
  1.1666 +	    current->l.next = &(SubAltName->l);
  1.1667 +	    SubAltName->l.prev = &(current->l);
  1.1668 +	}
  1.1669 +    }
  1.1670 +    if (rv == SECFailure) {
  1.1671 +	return NULL;
  1.1672 +    }
  1.1673 +    return SubAltName;
  1.1674 +}
  1.1675 +
  1.1676 +static CERTNameConstraints *
  1.1677 +MakeNameConstraints(Pair             *data, 
  1.1678 +		    PLArenaPool      *arena)
  1.1679 +{
  1.1680 +    CERTNameConstraints      *NameConstraints;
  1.1681 +    CERTNameConstraint       *current = NULL;
  1.1682 +    CERTNameConstraint       *last_permited = NULL;
  1.1683 +    CERTNameConstraint       *last_excluded = NULL;
  1.1684 +    char                     *constraint = NULL;
  1.1685 +    char                     *which;
  1.1686 +    SECStatus                rv = SECSuccess;
  1.1687 +    int                      len;
  1.1688 +    int                      i;
  1.1689 +    long                     max;
  1.1690 +    long                     min;
  1.1691 +    PRBool                   permited;
  1.1692 +    
  1.1693 +
  1.1694 +    NameConstraints = (CERTNameConstraints *) PORT_ZAlloc
  1.1695 +	                            (sizeof(CERTNameConstraints));
  1.1696 +    which = make_copy_string("NameConstraintSelect0", 25,'\0');
  1.1697 +    len = PORT_Strlen(which);
  1.1698 +    constraint = find_field(data, which, PR_TRUE);
  1.1699 +    NameConstraints->permited = NameConstraints->excluded = NULL;
  1.1700 +    while (constraint != NULL) {
  1.1701 +	current = (CERTNameConstraint *) PORT_ZAlloc
  1.1702 +	                       (sizeof(CERTNameConstraint));
  1.1703 +	if (current == NULL) {
  1.1704 +	    error_allocate();
  1.1705 +	}
  1.1706 +	i = 0;
  1.1707 +	while (*(constraint + PORT_Strlen(constraint) - i) != '-') {
  1.1708 +	    i++;
  1.1709 +	}
  1.1710 +        *(constraint + PORT_Strlen(constraint) - i - 1) = '\0'; 
  1.1711 +	max = (long) atoi(constraint + PORT_Strlen(constraint) + 3);
  1.1712 +	if (max > 0) {
  1.1713 +	    (void) SEC_ASN1EncodeInteger(arena, &current->max, max);
  1.1714 +	}
  1.1715 +	i = 0;
  1.1716 +	while (*(constraint + PORT_Strlen(constraint) - i) != '-') {
  1.1717 +	    i++;
  1.1718 +	}
  1.1719 +        *(constraint + PORT_Strlen(constraint) - i - 1) = '\0';
  1.1720 +	min = (long) atoi(constraint + PORT_Strlen(constraint) + 3);
  1.1721 +	(void) SEC_ASN1EncodeInteger(arena, &current->min, min);
  1.1722 +	while (*(constraint + PORT_Strlen(constraint) - i) != '-') {
  1.1723 +	    i++;
  1.1724 +	}
  1.1725 +        *(constraint + PORT_Strlen(constraint) - i - 1) = '\0';
  1.1726 +	if (*(constraint + PORT_Strlen(constraint) + 3) == 'p') {
  1.1727 +	    permited = PR_TRUE;
  1.1728 +	} else {
  1.1729 +	    permited = PR_FALSE;
  1.1730 +	}
  1.1731 +	rv = MakeGeneralName(constraint, &(current->name), arena);
  1.1732 +
  1.1733 +	if (rv != SECSuccess) {
  1.1734 +	    break;
  1.1735 +	}
  1.1736 +	if (*(which + len - 1) < '9') {
  1.1737 +	    *(which + len - 1) = *(which + len - 1) + 1;
  1.1738 +	} else {
  1.1739 +	    if (isdigit(*(which + len - 2) )) {
  1.1740 +		*(which + len - 2) = *(which + len - 2) + 1;
  1.1741 +		*(which + len - 1) = '0';
  1.1742 +	    } else {
  1.1743 +		*(which + len - 1) = '1';
  1.1744 +		*(which + len) = '0';
  1.1745 +		*(which + len + 1) = '\0';
  1.1746 +		len++;
  1.1747 +	    }
  1.1748 +	}
  1.1749 +	len = PORT_Strlen(which);
  1.1750 +	if (permited) {
  1.1751 +	    if (NameConstraints->permited == NULL) {
  1.1752 +		NameConstraints->permited = last_permited = current;
  1.1753 +	    }
  1.1754 +	    last_permited->l.next = &(current->l);
  1.1755 +	    current->l.prev = &(last_permited->l);
  1.1756 +	    last_permited = current;
  1.1757 +	} else {
  1.1758 +	    if (NameConstraints->excluded == NULL) {
  1.1759 +		NameConstraints->excluded = last_excluded = current;
  1.1760 +	    }
  1.1761 +	    last_excluded->l.next = &(current->l);
  1.1762 +	    current->l.prev = &(last_excluded->l);
  1.1763 +	    last_excluded = current;
  1.1764 +	}
  1.1765 +	constraint = find_field(data, which, PR_TRUE);
  1.1766 +	if (constraint != NULL) {
  1.1767 +	    current = (CERTNameConstraint *) PORT_ZAlloc(sizeof(CERTNameConstraint));
  1.1768 +	    if (current == NULL) {
  1.1769 +		error_allocate();
  1.1770 +	    }
  1.1771 +	}
  1.1772 +    }
  1.1773 +    if (NameConstraints->permited != NULL) {
  1.1774 +	last_permited->l.next = &(NameConstraints->permited->l);
  1.1775 +	NameConstraints->permited->l.prev = &(last_permited->l);
  1.1776 +    }
  1.1777 +    if (NameConstraints->excluded != NULL) {
  1.1778 +	last_excluded->l.next = &(NameConstraints->excluded->l);
  1.1779 +	NameConstraints->excluded->l.prev = &(last_excluded->l);
  1.1780 +    }
  1.1781 +    if (which != NULL) {
  1.1782 +	PORT_Free(which);
  1.1783 +    }
  1.1784 +    if (rv == SECFailure) {
  1.1785 +	return NULL;
  1.1786 +    }
  1.1787 +    return NameConstraints;
  1.1788 +}
  1.1789 +
  1.1790 +
  1.1791 +
  1.1792 +static SECStatus
  1.1793 +AddAltName(void              *extHandle,
  1.1794 +	   Pair              *data,
  1.1795 +	   char              *issuerNameStr, 
  1.1796 +	   CERTCertDBHandle  *handle,
  1.1797 +	   int               type)
  1.1798 +{
  1.1799 +    PRBool             autoIssuer = PR_FALSE;
  1.1800 +    PLArenaPool        *arena = NULL;
  1.1801 +    CERTGeneralName    *genName = NULL;
  1.1802 +    char               *which = NULL;
  1.1803 +    char               *name = NULL;
  1.1804 +    SECStatus          rv = SECSuccess;
  1.1805 +    SECItem            *issuersAltName = NULL;
  1.1806 +    CERTCertificate    *issuerCert = NULL;
  1.1807 +
  1.1808 +    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1.1809 +    if (arena == NULL) {
  1.1810 +	error_allocate();
  1.1811 +    }
  1.1812 +    if (type == 0) {
  1.1813 +	which = make_copy_string("SubAltNameSelect0", 20,'\0');
  1.1814 +	genName = MakeAltName(data, which, arena);
  1.1815 +    } else {
  1.1816 +	if (autoIssuer) {
  1.1817 +	    autoIssuer = find_field_bool(data,"IssuerAltNameSourceRadio-auto",
  1.1818 +					 PR_TRUE);
  1.1819 +	    issuerCert = CERT_FindCertByNameString(handle, issuerNameStr);
  1.1820 +	    rv = cert_FindExtension((*issuerCert).extensions, 
  1.1821 +				    SEC_OID_X509_SUBJECT_ALT_NAME, 
  1.1822 +				    issuersAltName);
  1.1823 +	    if (issuersAltName == NULL) {
  1.1824 +		name = PORT_Alloc(PORT_Strlen((*issuerCert).subjectName) + 4);
  1.1825 +		PORT_Strcpy(name, (*issuerCert).subjectName);
  1.1826 +		PORT_Strcat(name, " - 5");
  1.1827 +	    }
  1.1828 +	} else {
  1.1829 +	    which = make_copy_string("IssuerAltNameSelect0", 20,'\0');
  1.1830 +	    genName = MakeAltName(data, which, arena);
  1.1831 +	}
  1.1832 +    }
  1.1833 +    if (type == 0) {
  1.1834 +	EncodeAndAddExtensionValue(arena, extHandle, genName, 
  1.1835 +				   find_field_bool(data, "SubAltName-crit", 
  1.1836 +						   PR_TRUE), 
  1.1837 +				   SEC_OID_X509_SUBJECT_ALT_NAME, 
  1.1838 +				   (EXTEN_VALUE_ENCODER)
  1.1839 +				   CERT_EncodeAltNameExtension);
  1.1840 +
  1.1841 +    } else {
  1.1842 +	if (autoIssuer && (name == NULL)) {
  1.1843 +	    rv = CERT_AddExtension
  1.1844 +		(extHandle, SEC_OID_X509_ISSUER_ALT_NAME, issuersAltName,
  1.1845 +		 find_field_bool(data, "IssuerAltName-crit", PR_TRUE), PR_TRUE);
  1.1846 +	} else {
  1.1847 +	    EncodeAndAddExtensionValue(arena, extHandle, genName, 
  1.1848 +				       find_field_bool(data, 
  1.1849 +						       "IssuerAltName-crit", 
  1.1850 +						       PR_TRUE), 
  1.1851 +				       SEC_OID_X509_ISSUER_ALT_NAME, 
  1.1852 +				       (EXTEN_VALUE_ENCODER)
  1.1853 +				       CERT_EncodeAltNameExtension);
  1.1854 +	}
  1.1855 +    }
  1.1856 +    if (which != NULL) {
  1.1857 +	PORT_Free(which);
  1.1858 +    }
  1.1859 +    if (issuerCert != NULL) {
  1.1860 +	CERT_DestroyCertificate(issuerCert);
  1.1861 +    }
  1.1862 +    return rv;
  1.1863 +}
  1.1864 +
  1.1865 +
  1.1866 +static SECStatus
  1.1867 +AddNameConstraints(void  *extHandle,
  1.1868 +		   Pair  *data)
  1.1869 +{
  1.1870 +    PLArenaPool         *arena = NULL;
  1.1871 +    CERTNameConstraints *constraints = NULL;
  1.1872 +    SECStatus           rv = SECSuccess;
  1.1873 +
  1.1874 +
  1.1875 +    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1.1876 +    if (arena == NULL) {
  1.1877 +	error_allocate();
  1.1878 +    }
  1.1879 +    constraints = MakeNameConstraints(data, arena);
  1.1880 +    if (constraints != NULL) {
  1.1881 +	EncodeAndAddExtensionValue(arena, extHandle, constraints, PR_TRUE, 
  1.1882 +				   SEC_OID_X509_NAME_CONSTRAINTS, 
  1.1883 +				   (EXTEN_VALUE_ENCODER)
  1.1884 +				   CERT_EncodeNameConstraintsExtension);
  1.1885 +    }
  1.1886 +    if (arena != NULL) {
  1.1887 +	PORT_ArenaRelease (arena, NULL);
  1.1888 +    }
  1.1889 +    return rv;
  1.1890 +}
  1.1891 +
  1.1892 +
  1.1893 +static SECStatus
  1.1894 +add_extensions(CERTCertificate   *subjectCert, 
  1.1895 +	       Pair              *data, 
  1.1896 +	       char              *issuerNameStr, 
  1.1897 +	       CERTCertDBHandle  *handle)
  1.1898 +{
  1.1899 +    void                         *extHandle;
  1.1900 +    SECStatus                    rv = SECSuccess;
  1.1901 +
  1.1902 +
  1.1903 +    extHandle = CERT_StartCertExtensions (subjectCert);
  1.1904 +    if (extHandle == NULL) {
  1.1905 +	error_out("ERROR: Unable to get certificates extension handle");
  1.1906 +    }
  1.1907 +    if (find_field_bool(data, "keyUsage", PR_TRUE)) {
  1.1908 +	rv = AddKeyUsage(extHandle, data);
  1.1909 +	if (rv != SECSuccess) {
  1.1910 +	    error_out("ERROR: Unable to add Key Usage extension");
  1.1911 +	}
  1.1912 +    }
  1.1913 +
  1.1914 +    if( find_field_bool(data, "extKeyUsage", PR_TRUE) ) {
  1.1915 +      rv = AddExtKeyUsage(extHandle, data);
  1.1916 +      if( SECSuccess != rv ) {
  1.1917 +        error_out("ERROR: Unable to add Extended Key Usage extension");
  1.1918 +      }
  1.1919 +    }
  1.1920 +
  1.1921 +    if (find_field_bool(data, "basicConstraints", PR_TRUE)) {
  1.1922 +	rv = AddBasicConstraint(extHandle, data);
  1.1923 +	if (rv != SECSuccess) {
  1.1924 +	    error_out("ERROR: Unable to add Basic Constraint extension");
  1.1925 +	}
  1.1926 +    }
  1.1927 +    if (find_field_bool(data, "subjectKeyIdentifier", PR_TRUE)) {
  1.1928 +	rv = AddSubKeyID(extHandle, data, subjectCert);
  1.1929 +	if (rv != SECSuccess) {
  1.1930 +	    error_out("ERROR: Unable to add Subject Key Identifier Extension");
  1.1931 +	}
  1.1932 +    }
  1.1933 +    if (find_field_bool(data, "authorityKeyIdentifier", PR_TRUE)) {
  1.1934 +	rv = AddAuthKeyID (extHandle, data, issuerNameStr, handle);
  1.1935 +	if (rv != SECSuccess) {
  1.1936 +	    error_out("ERROR: Unable to add Authority Key Identifier extension");
  1.1937 +	}
  1.1938 +    }
  1.1939 +    if (find_field_bool(data, "privKeyUsagePeriod", PR_TRUE)) {
  1.1940 +	rv = AddPrivKeyUsagePeriod (extHandle, data, subjectCert);
  1.1941 +	if (rv != SECSuccess) {
  1.1942 +	    error_out("ERROR: Unable to add Private Key Usage Period extension");
  1.1943 +	}
  1.1944 +    }
  1.1945 +    if (find_field_bool(data, "SubAltName", PR_TRUE)) {
  1.1946 +	rv = AddAltName (extHandle, data, NULL, NULL, 0);
  1.1947 +	if (rv != SECSuccess) {
  1.1948 +	    error_out("ERROR: Unable to add Subject Alternative Name extension");
  1.1949 +	}
  1.1950 +    }
  1.1951 +    if (find_field_bool(data, "IssuerAltName", PR_TRUE)) {
  1.1952 +	rv = AddAltName (extHandle, data, issuerNameStr, handle, 1);
  1.1953 +	if (rv != SECSuccess) {
  1.1954 +	    error_out("ERROR: Unable to add Issuer Alternative Name Extension");
  1.1955 +	}
  1.1956 +    }
  1.1957 +    if (find_field_bool(data, "NameConstraints", PR_TRUE)) {
  1.1958 +	rv = AddNameConstraints(extHandle, data);
  1.1959 +	if (rv != SECSuccess) {
  1.1960 +	    error_out("ERROR: Unable to add Name Constraints Extension");
  1.1961 +	}
  1.1962 +    }
  1.1963 +    if (find_field_bool(data, "netscape-cert-type", PR_TRUE)) {
  1.1964 +	rv = AddNscpCertType(extHandle, data);
  1.1965 +	if (rv != SECSuccess) {
  1.1966 +	    error_out("ERROR: Unable to add Netscape Certificate Type Extension");
  1.1967 +	}
  1.1968 +    }
  1.1969 +    if (find_field_bool(data, "netscape-base-url", PR_TRUE)) {
  1.1970 +	rv = add_IA5StringExtension(extHandle, 
  1.1971 +				    find_field(data, "netscape-base-url-text", 
  1.1972 +					       PR_TRUE), 
  1.1973 +				    find_field_bool(data, 
  1.1974 +						    "netscape-base-url-crit", 
  1.1975 +						    PR_TRUE),
  1.1976 +				    SEC_OID_NS_CERT_EXT_BASE_URL);
  1.1977 +	if (rv != SECSuccess) {
  1.1978 +	    error_out("ERROR: Unable to add Netscape Base URL Extension");
  1.1979 +	}
  1.1980 +    }
  1.1981 +    if (find_field_bool(data, "netscape-revocation-url", PR_TRUE)) {
  1.1982 +	rv = add_IA5StringExtension(extHandle, 
  1.1983 +				    find_field(data, 
  1.1984 +					       "netscape-revocation-url-text", 
  1.1985 +					       PR_TRUE), 
  1.1986 +				    find_field_bool
  1.1987 +				       (data, "netscape-revocation-url-crit", 
  1.1988 +					PR_TRUE),
  1.1989 +				    SEC_OID_NS_CERT_EXT_REVOCATION_URL);
  1.1990 +	if (rv != SECSuccess) {
  1.1991 +	    error_out("ERROR: Unable to add Netscape Revocation URL Extension");
  1.1992 +	}
  1.1993 +    }
  1.1994 +    if (find_field_bool(data, "netscape-ca-revocation-url", PR_TRUE)) {
  1.1995 +	rv = add_IA5StringExtension(extHandle, 
  1.1996 +				    find_field(data, 
  1.1997 +					      "netscape-ca-revocation-url-text",
  1.1998 +					       PR_TRUE), 
  1.1999 +				    find_field_bool
  1.2000 +				        (data, "netscape-ca-revocation-url-crit"
  1.2001 +					 , PR_TRUE),
  1.2002 +				    SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL);
  1.2003 +	if (rv != SECSuccess) {
  1.2004 +	    error_out("ERROR: Unable to add Netscape CA Revocation URL Extension");
  1.2005 +	}
  1.2006 +    }
  1.2007 +    if (find_field_bool(data, "netscape-cert-renewal-url", PR_TRUE)) {
  1.2008 +	rv = add_IA5StringExtension(extHandle, 
  1.2009 +				    find_field(data, 
  1.2010 +					       "netscape-cert-renewal-url-text",
  1.2011 +					       PR_TRUE), 
  1.2012 +				    find_field_bool
  1.2013 +				        (data, "netscape-cert-renewal-url-crit",
  1.2014 +					 PR_TRUE),
  1.2015 +				    SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL);
  1.2016 +	if (rv != SECSuccess) {
  1.2017 +	    error_out("ERROR: Unable to add Netscape Certificate Renewal URL Extension");
  1.2018 +	}
  1.2019 +    }
  1.2020 +    if (find_field_bool(data, "netscape-ca-policy-url", PR_TRUE)) {
  1.2021 +	rv = add_IA5StringExtension(extHandle, 
  1.2022 +				    find_field(data, 
  1.2023 +					       "netscape-ca-policy-url-text", 
  1.2024 +					       PR_TRUE), 
  1.2025 +				    find_field_bool
  1.2026 +				         (data, "netscape-ca-policy-url-crit", 
  1.2027 +					  PR_TRUE),
  1.2028 +				    SEC_OID_NS_CERT_EXT_CA_POLICY_URL);
  1.2029 +	if (rv != SECSuccess) {
  1.2030 +	    error_out("ERROR: Unable to add Netscape CA Policy URL Extension");
  1.2031 +	}
  1.2032 +    }
  1.2033 +    if (find_field_bool(data, "netscape-ssl-server-name", PR_TRUE)) {
  1.2034 +	rv = add_IA5StringExtension(extHandle, 
  1.2035 +				    find_field(data, 
  1.2036 +					       "netscape-ssl-server-name-text", 
  1.2037 +					       PR_TRUE), 
  1.2038 +				    find_field_bool
  1.2039 +				         (data, "netscape-ssl-server-name-crit",
  1.2040 +					  PR_TRUE),
  1.2041 +				    SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME);
  1.2042 +	if (rv != SECSuccess) {
  1.2043 +	    error_out("ERROR: Unable to add Netscape SSL Server Name Extension");
  1.2044 +	}
  1.2045 +    }
  1.2046 +    if (find_field_bool(data, "netscape-comment", PR_TRUE)) {
  1.2047 +	rv = add_IA5StringExtension(extHandle, 
  1.2048 +				    find_field(data, "netscape-comment-text", 
  1.2049 +					       PR_TRUE), 
  1.2050 +				    find_field_bool(data, 
  1.2051 +						    "netscape-comment-crit", 
  1.2052 +						    PR_TRUE),
  1.2053 +				    SEC_OID_NS_CERT_EXT_COMMENT);
  1.2054 +	if (rv != SECSuccess) {
  1.2055 +	    error_out("ERROR: Unable to add Netscape Comment Extension");
  1.2056 +	}
  1.2057 +    }
  1.2058 +    CERT_FinishExtensions(extHandle);
  1.2059 +    return (rv);
  1.2060 +}
  1.2061 +
  1.2062 +
  1.2063 +
  1.2064 +char *
  1.2065 +return_dbpasswd(PK11SlotInfo *slot, PRBool retry, void *data)
  1.2066 +{
  1.2067 +    char *rv;
  1.2068 +
  1.2069 +    /* don't clobber our poor smart card */
  1.2070 +    if (retry == PR_TRUE) {
  1.2071 +	return NULL;
  1.2072 +    }
  1.2073 +    rv = PORT_Alloc(4);
  1.2074 +    PORT_Strcpy(rv, "foo");
  1.2075 +    return rv;
  1.2076 +}
  1.2077 +
  1.2078 +
  1.2079 +SECKEYPrivateKey *
  1.2080 +FindPrivateKeyFromNameStr(char              *name, 
  1.2081 +			  CERTCertDBHandle  *certHandle)
  1.2082 +{
  1.2083 +    SECKEYPrivateKey                        *key;
  1.2084 +    CERTCertificate                         *cert;
  1.2085 +    CERTCertificate                         *p11Cert;
  1.2086 +
  1.2087 +
  1.2088 +    /* We don't presently have a PK11 function to find a cert by 
  1.2089 +    ** subject name.  
  1.2090 +    ** We do have a function to find a cert in the internal slot's
  1.2091 +    ** cert db by subject name, but it doesn't setup the slot info.
  1.2092 +    ** So, this HACK works, but should be replaced as soon as we 
  1.2093 +    ** have a function to search for certs accross slots by subject name.
  1.2094 +    */
  1.2095 +    cert = CERT_FindCertByNameString(certHandle, name);
  1.2096 +    if (cert == NULL || cert->nickname == NULL) {
  1.2097 +	error_out("ERROR: Unable to retrieve issuers certificate");
  1.2098 +    }
  1.2099 +    p11Cert = PK11_FindCertFromNickname(cert->nickname, NULL);
  1.2100 +    if (p11Cert == NULL) {
  1.2101 +	error_out("ERROR: Unable to retrieve issuers certificate");
  1.2102 +    }
  1.2103 +    key = PK11_FindKeyByAnyCert(p11Cert, NULL);
  1.2104 +    return key;
  1.2105 +}
  1.2106 +
  1.2107 +static SECItem *
  1.2108 +SignCert(CERTCertificate   *cert,
  1.2109 +	 char              *issuerNameStr,
  1.2110 +	 Pair              *data,
  1.2111 +	 CERTCertDBHandle  *handle,
  1.2112 +         int               which_key)
  1.2113 +{
  1.2114 +    SECItem                der;
  1.2115 +    SECKEYPrivateKey       *caPrivateKey = NULL;
  1.2116 +    SECStatus              rv;
  1.2117 +    PLArenaPool            *arena;
  1.2118 +    SECOidTag              algID;
  1.2119 +
  1.2120 +    if (which_key == 0) {
  1.2121 +	caPrivateKey = FindPrivateKeyFromNameStr(issuerNameStr, handle); 
  1.2122 +    } else {
  1.2123 +	caPrivateKey = privkeys[which_key - 1];
  1.2124 +    }
  1.2125 +    if (caPrivateKey == NULL) {
  1.2126 +	error_out("ERROR: unable to retrieve issuers key");
  1.2127 +    }
  1.2128 +	
  1.2129 +    arena = cert->arena;
  1.2130 +
  1.2131 +    algID = SEC_GetSignatureAlgorithmOidTag(caPrivateKey->keyType,
  1.2132 +					    SEC_OID_UNKNOWN);
  1.2133 +    if (algID == SEC_OID_UNKNOWN) {
  1.2134 +	error_out("ERROR: Unknown key type for issuer.");
  1.2135 +	goto done;
  1.2136 +    }
  1.2137 +
  1.2138 +    rv = SECOID_SetAlgorithmID(arena, &cert->signature, algID, 0);
  1.2139 +    if (rv != SECSuccess) {
  1.2140 +	error_out("ERROR: Could not set signature algorithm id.");
  1.2141 +    }
  1.2142 +
  1.2143 +    if (find_field_bool(data,"ver-1", PR_TRUE)) {
  1.2144 +	*(cert->version.data) = 0;
  1.2145 +	cert->version.len = 1;
  1.2146 +    } else {
  1.2147 +	*(cert->version.data) = 2;
  1.2148 +	cert->version.len = 1;
  1.2149 +    }
  1.2150 +    der.data = NULL;
  1.2151 +    der.len = 0;
  1.2152 +    (void) SEC_ASN1EncodeItem (arena, &der, cert, CERT_CertificateTemplate);
  1.2153 +    if (der.data == NULL) {
  1.2154 +	error_out("ERROR: Could not encode certificate.\n");
  1.2155 +    }
  1.2156 +    rv = SEC_DerSignData (arena, &(cert->derCert), der.data, der.len, caPrivateKey,
  1.2157 +			  algID);
  1.2158 +    if (rv != SECSuccess) {
  1.2159 +	error_out("ERROR: Could not sign encoded certificate data.\n");
  1.2160 +    }
  1.2161 +done:
  1.2162 +    SECKEY_DestroyPrivateKey(caPrivateKey);
  1.2163 +    return &(cert->derCert);
  1.2164 +}
  1.2165 +
  1.2166 +
  1.2167 +int
  1.2168 +main(int argc, char **argv)
  1.2169 +{
  1.2170 +    int                    length = 500;
  1.2171 +    int                    remaining = 500;
  1.2172 +    int                    n;
  1.2173 +    int                    i;
  1.2174 +    int                    serial;
  1.2175 +    int                    chainLen;
  1.2176 +    int                    which_key;
  1.2177 +    char                   *pos;
  1.2178 +#ifdef OFFLINE
  1.2179 +    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";
  1.2180 +#else
  1.2181 +    char                   *form_output;
  1.2182 +#endif
  1.2183 +    char                   *issuerNameStr;
  1.2184 +    char                   *certName;
  1.2185 +    char                   *DBdir = DB_DIRECTORY;
  1.2186 +    char                   *prefixs[10] = {"CA#1-", "CA#2-", "CA#3-", 
  1.2187 +					   "CA#4-", "CA#5-", "CA#6-", 
  1.2188 +					   "CA#7-", "CA#8-", "CA#9-", ""};
  1.2189 +    Pair                   *form_data;
  1.2190 +    CERTCertificate        *cert;
  1.2191 +    CERTCertDBHandle       *handle;
  1.2192 +    CERTCertificateRequest *certReq = NULL;
  1.2193 +    int                    warpmonths = 0;
  1.2194 +    SECItem                *certDER;
  1.2195 +#ifdef FILEOUT
  1.2196 +    FILE                   *outfile;
  1.2197 +#endif
  1.2198 +    SECStatus              status = SECSuccess;
  1.2199 +    extern                 char prefix[PREFIX_LEN];
  1.2200 +    SEC_PKCS7ContentInfo   *certChain;
  1.2201 +    SECItem                *encodedCertChain;
  1.2202 +    PRBool                 UChain = PR_FALSE;
  1.2203 +
  1.2204 +
  1.2205 +    progName = strrchr(argv[0], '/');
  1.2206 +    progName = progName ? progName+1 : argv[0];
  1.2207 +
  1.2208 +
  1.2209 +#ifdef TEST
  1.2210 +    sleep(20);
  1.2211 +#endif
  1.2212 +    SECU_ConfigDirectory(DBdir);
  1.2213 +
  1.2214 +    PK11_SetPasswordFunc(return_dbpasswd);
  1.2215 +    status = NSS_InitReadWrite(DBdir);
  1.2216 +    if (status != SECSuccess) {
  1.2217 +	SECU_PrintPRandOSError(progName);
  1.2218 +	return -1;
  1.2219 +    }
  1.2220 +    handle = CERT_GetDefaultCertDB();
  1.2221 +
  1.2222 +    prefix[0]= '\0';
  1.2223 +#if !defined(OFFLINE)
  1.2224 +    form_output = (char*) PORT_Alloc(length);
  1.2225 +    if (form_output == NULL) {
  1.2226 +	error_allocate();
  1.2227 +    }
  1.2228 +    pos = form_output;
  1.2229 +    while (feof(stdin) == 0 ) {
  1.2230 +	if (remaining <= 1) {
  1.2231 +	    remaining += length;
  1.2232 +	    length = length * 2;
  1.2233 +	    form_output = PORT_Realloc(form_output, (length));
  1.2234 +	    if (form_output == NULL) {
  1.2235 +		error_allocate();
  1.2236 +	    }
  1.2237 +	    pos = form_output + length - remaining;
  1.2238 +	}
  1.2239 +	n = fread(pos, 1, (size_t) (remaining - 1), stdin);
  1.2240 +	pos += n;
  1.2241 +	remaining -= n;
  1.2242 +    }
  1.2243 +    *pos = '&';
  1.2244 +    pos++;
  1.2245 +    length = pos - form_output;
  1.2246 +#else
  1.2247 +    length = PORT_Strlen(form_output);
  1.2248 +#endif
  1.2249 +#ifdef FILEOUT
  1.2250 +    printf("Content-type: text/plain\n\n");
  1.2251 +    fwrite(form_output, 1, (size_t)length, stdout);
  1.2252 +    printf("\n");
  1.2253 +#endif
  1.2254 +#ifdef FILEOUT
  1.2255 +    fwrite(form_output, 1, (size_t)length, stdout);
  1.2256 +    printf("\n");
  1.2257 +    fflush(stdout);
  1.2258 +#endif
  1.2259 +    form_data = make_datastruct(form_output, length);
  1.2260 +    status = clean_input(form_data);
  1.2261 +#if !defined(OFFLINE)
  1.2262 +    PORT_Free(form_output);
  1.2263 +#endif
  1.2264 +#ifdef FILEOUT
  1.2265 +    i = 0;
  1.2266 +    while(return_name(form_data, i) != NULL) {
  1.2267 +        printf("%s",return_name(form_data,i));
  1.2268 +        printf("=\n");
  1.2269 +        printf("%s",return_data(form_data,i));
  1.2270 +        printf("\n");
  1.2271 +	i++;
  1.2272 +    }
  1.2273 +    printf("I got that done, woo hoo\n");
  1.2274 +    fflush(stdout);
  1.2275 +#endif
  1.2276 +    issuerNameStr = PORT_Alloc(200);
  1.2277 +    if (find_field_bool(form_data, "caChoiceradio-SignWithSpecifiedChain",
  1.2278 +			PR_FALSE)) {
  1.2279 +	UChain = PR_TRUE;
  1.2280 +	chainLen = atoi(find_field(form_data, "manCAs", PR_FALSE));
  1.2281 +	PORT_Strcpy(prefix, prefixs[0]);
  1.2282 +	issuerNameStr = PORT_Strcpy(issuerNameStr,
  1.2283 +			       "CN=Cert-O-Matic II, O=Cert-O-Matic II");
  1.2284 +	if (chainLen == 0) {
  1.2285 +	    UChain =  PR_FALSE;
  1.2286 +	}
  1.2287 +    } else {
  1.2288 +	if (find_field_bool(form_data, "caChoiceradio-SignWithRandomChain", 
  1.2289 +			    PR_FALSE)) {
  1.2290 +	    PORT_Strcpy(prefix,prefixs[9]);
  1.2291 +	    chainLen = atoi(find_field(form_data, "autoCAs", PR_FALSE));
  1.2292 +	    if (chainLen < 1 || chainLen > 18) {
  1.2293 +		issuerNameStr = PORT_Strcpy(issuerNameStr, 
  1.2294 +				       "CN=CA18, O=Cert-O-Matic II");
  1.2295 +	    }
  1.2296 +	    issuerNameStr = PORT_Strcpy(issuerNameStr, "CN=CA");
  1.2297 +	    issuerNameStr = PORT_Strcat(issuerNameStr, 
  1.2298 +				   find_field(form_data,"autoCAs", PR_FALSE));
  1.2299 +	    issuerNameStr = PORT_Strcat(issuerNameStr,", O=Cert-O-Matic II");
  1.2300 +	} else {
  1.2301 +	    issuerNameStr = PORT_Strcpy(issuerNameStr, 
  1.2302 +				   "CN=Cert-O-Matic II, O=Cert-O-Matic II");
  1.2303 +	}
  1.2304 +	chainLen = 0;
  1.2305 +    }
  1.2306 +
  1.2307 +    i = -1;
  1.2308 +    which_key = 0;
  1.2309 +    do {
  1.2310 +    	extern SECStatus cert_GetKeyID(CERTCertificate *cert);
  1.2311 +	i++;
  1.2312 +	if (i != 0 && UChain) {
  1.2313 +	    PORT_Strcpy(prefix, prefixs[i]);
  1.2314 +	}
  1.2315 +	/*        find_field(form_data,"subject", PR_TRUE); */
  1.2316 +	certReq = makeCertReq(form_data, which_key);
  1.2317 +#ifdef OFFLINE
  1.2318 +	serial = 900;
  1.2319 +#else
  1.2320 +	serial = get_serial_number(form_data);
  1.2321 +#endif
  1.2322 +	cert = MakeV1Cert(handle, certReq, issuerNameStr, PR_FALSE, 
  1.2323 +			  serial, warpmonths, form_data);
  1.2324 +	if (certReq != NULL) {
  1.2325 +	    CERT_DestroyCertificateRequest(certReq);
  1.2326 +	}
  1.2327 +	if (find_field_bool(form_data,"ver-3", PR_TRUE)) {
  1.2328 +	    status = add_extensions(cert, form_data, issuerNameStr, handle);
  1.2329 +	    if (status != SECSuccess) {
  1.2330 +		error_out("ERROR: Unable to add extensions");
  1.2331 +	    }
  1.2332 +	}
  1.2333 +	status = cert_GetKeyID(cert);
  1.2334 +	if (status == SECFailure) {
  1.2335 +	    error_out("ERROR: Unable to get Key ID.");
  1.2336 +	}
  1.2337 +	certDER = SignCert(cert, issuerNameStr, form_data, handle, which_key);
  1.2338 +	CERT_NewTempCertificate(handle, certDER, NULL, PR_FALSE, PR_TRUE);
  1.2339 +	issuerNameStr = find_field(form_data, "subject", PR_TRUE);
  1.2340 +	/*        SECITEM_FreeItem(certDER, PR_TRUE); */
  1.2341 +	CERT_DestroyCertificate(cert);
  1.2342 +	if (i == (chainLen - 1)) {
  1.2343 +	    i = 8;
  1.2344 +	}
  1.2345 +	++which_key;
  1.2346 +    } while (i < 9 && UChain);
  1.2347 +
  1.2348 +
  1.2349 +
  1.2350 +#ifdef FILEOUT
  1.2351 +    outfile = fopen("../certout", "wb");
  1.2352 +#endif
  1.2353 +    certName = find_field(form_data, "subject", PR_FALSE);
  1.2354 +    cert = CERT_FindCertByNameString(handle, certName);
  1.2355 +    certChain = SEC_PKCS7CreateCertsOnly (cert, PR_TRUE, handle);
  1.2356 +    if (certChain == NULL) {
  1.2357 +	error_out("ERROR: No certificates in cert chain");
  1.2358 +    }
  1.2359 +    encodedCertChain = SEC_PKCS7EncodeItem (NULL, NULL, certChain, NULL, NULL, 
  1.2360 +					    NULL);
  1.2361 +    if (encodedCertChain) {
  1.2362 +#if !defined(FILEOUT)
  1.2363 +	printf("Content-type: application/x-x509-user-cert\r\n");
  1.2364 +	printf("Content-length: %d\r\n\r\n", encodedCertChain->len);
  1.2365 +	fwrite (encodedCertChain->data, 1, encodedCertChain->len, stdout);
  1.2366 +#else
  1.2367 +	fwrite (encodedCertChain->data, 1, encodedCertChain->len, outfile);
  1.2368 +#endif
  1.2369 +
  1.2370 +    } else {
  1.2371 +	error_out("Error: Unable to DER encode certificate");
  1.2372 +    }
  1.2373 +#ifdef FILEOUT
  1.2374 +    printf("\nI got here!\n");
  1.2375 +    fflush(outfile);
  1.2376 +    fclose(outfile);
  1.2377 +#endif
  1.2378 +    fflush(stdout);
  1.2379 +    if (NSS_Shutdown() != SECSuccess) {
  1.2380 +        exit(1);
  1.2381 +    }
  1.2382 +    return 0;
  1.2383 +}
  1.2384 +

mercurial