PageRenderTime 93ms CodeModel.GetById 15ms app.highlight 67ms RepoModel.GetById 1ms app.codeStats 0ms

/security/nss/cmd/certutil/certext.c

http://github.com/zpao/v8monkey
C | 1817 lines | 1471 code | 238 blank | 108 comment | 385 complexity | 80abf726914889ad06d1182531db211d MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/* ***** BEGIN LICENSE BLOCK *****
   2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
   3 *
   4 * The contents of this file are subject to the Mozilla Public License Version
   5 * 1.1 (the "License"); you may not use this file except in compliance with
   6 * the License. You may obtain a copy of the License at
   7 * http://www.mozilla.org/MPL/
   8 *
   9 * Software distributed under the License is distributed on an "AS IS" basis,
  10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11 * for the specific language governing rights and limitations under the
  12 * License.
  13 *
  14 * The Original Code is the Netscape security libraries.
  15 *
  16 * The Initial Developer of the Original Code is
  17 * Netscape Communications Corporation.
  18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
  19 * the Initial Developer. All Rights Reserved.
  20 *
  21 * Contributor(s):
  22 *   Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
  23 *
  24 * Alternatively, the contents of this file may be used under the terms of
  25 * either the GNU General Public License Version 2 or later (the "GPL"), or
  26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  27 * in which case the provisions of the GPL or the LGPL are applicable instead
  28 * of those above. If you wish to allow use of your version of this file only
  29 * under the terms of either the GPL or the LGPL, and not to allow others to
  30 * use your version of this file under the terms of the MPL, indicate your
  31 * decision by deleting the provisions above and replace them with the notice
  32 * and other provisions required by the GPL or the LGPL. If you do not delete
  33 * the provisions above, a recipient may use your version of this file under
  34 * the terms of any one of the MPL, the GPL or the LGPL.
  35 *
  36 * ***** END LICENSE BLOCK ***** */
  37
  38/*
  39** certext.c
  40**
  41** part of certutil for managing certificates extensions
  42**
  43*/
  44#include <stdio.h>
  45#include <string.h>
  46#include <stdlib.h>
  47
  48#if defined(WIN32)
  49#include "fcntl.h"
  50#include "io.h"
  51#endif
  52
  53#include "secutil.h"
  54
  55#if defined(XP_UNIX)
  56#include <unistd.h>
  57#endif
  58
  59#include "cert.h"
  60#include "xconst.h"
  61#include "prprf.h"
  62#include "certutil.h"
  63
  64#define GEN_BREAK(e) rv=e; break;
  65
  66static char *
  67Gets_s(char *buff, size_t size) {
  68    char *str;
  69    
  70    if (buff == NULL || size < 1) {
  71        PORT_Assert(0);
  72        return NULL;
  73    }
  74    if ((str = fgets(buff, size, stdin)) != NULL) {
  75        int len = PORT_Strlen(str);
  76        /*
  77         * fgets() automatically converts native text file
  78         * line endings to '\n'.  As defensive programming
  79         * (just in case fgets has a bug or we put stdin in
  80         * binary mode by mistake), we handle three native 
  81         * text file line endings here:
  82         *   '\n'      Unix (including Linux and Mac OS X)
  83         *   '\r''\n'  DOS/Windows & OS/2
  84         *   '\r'      Mac OS Classic
  85         * len can not be less then 1, since in case with
  86         * empty string it has at least '\n' in the buffer
  87         */
  88        if (buff[len - 1] == '\n' || buff[len - 1] == '\r') {
  89            buff[len - 1] = '\0';
  90            if (len > 1 && buff[len - 2] == '\r')
  91                buff[len - 2] = '\0';
  92        }
  93    } else {
  94        buff[0] = '\0';
  95    }
  96    return str;
  97}
  98
  99
 100static SECStatus
 101PrintChoicesAndGetAnswer(char* str, char* rBuff, int rSize)
 102{
 103    fputs(str, stdout);
 104    fputs(" > ", stdout);
 105    fflush (stdout);
 106    if (Gets_s(rBuff, rSize) == NULL) {
 107        PORT_SetError(SEC_ERROR_INPUT_LEN);
 108        return SECFailure;
 109    }
 110    return SECSuccess;
 111}
 112
 113static CERTGeneralName *
 114GetGeneralName (PRArenaPool *arena)
 115{
 116    CERTGeneralName *namesList = NULL;
 117    CERTGeneralName *current;
 118    CERTGeneralName *tail = NULL;
 119    SECStatus rv = SECSuccess;
 120    int intValue;
 121    char buffer[512];
 122    void *mark;
 123
 124    PORT_Assert (arena);
 125    mark = PORT_ArenaMark (arena);
 126    do {
 127        if (PrintChoicesAndGetAnswer(
 128		"\nSelect one of the following general name type: \n"
 129		"\t2 - rfc822Name\n"
 130		"\t3 - dnsName\n"
 131		"\t5 - directoryName\n"
 132		"\t7 - uniformResourceidentifier\n"
 133		"\t8 - ipAddress\n"
 134		"\t9 - registerID\n"
 135		"\tAny other number to finish\n"
 136		"\t\tChoice:", buffer, sizeof(buffer)) == SECFailure) {
 137            GEN_BREAK (SECFailure);
 138        }
 139        intValue = PORT_Atoi (buffer);
 140        /*
 141         * Should use ZAlloc instead of Alloc to avoid problem with garbage
 142         * initialized pointers in CERT_CopyName
 143         */
 144        switch (intValue) {
 145        case certRFC822Name:
 146        case certDNSName:
 147        case certDirectoryName:
 148        case certURI:
 149        case certIPAddress:
 150        case certRegisterID:
 151	    break;
 152	default:
 153	    intValue = 0;   /* force a break for anything else */
 154	}
 155
 156        if (intValue == 0)
 157	    break;
 158	
 159	if (namesList == NULL) {
 160	    namesList = current = tail =
 161		PORT_ArenaZNew(arena, CERTGeneralName);
 162	} else {
 163	    current = PORT_ArenaZNew(arena, CERTGeneralName);
 164	}
 165	if (current == NULL) {
 166	    GEN_BREAK (SECFailure);
 167	}
 168
 169        current->type = intValue;
 170        puts ("\nEnter data:");
 171        fflush (stdout);
 172        if (Gets_s (buffer, sizeof(buffer)) == NULL) {
 173            PORT_SetError(SEC_ERROR_INPUT_LEN);
 174            GEN_BREAK (SECFailure);
 175        }
 176        switch (current->type) {
 177        case certURI:
 178        case certDNSName:
 179        case certRFC822Name:
 180            current->name.other.data =
 181                PORT_ArenaAlloc (arena, strlen (buffer));
 182            if (current->name.other.data == NULL) {
 183                GEN_BREAK (SECFailure);
 184            }
 185            PORT_Memcpy(current->name.other.data, buffer,
 186                        current->name.other.len = strlen(buffer));
 187            break;
 188
 189        case certEDIPartyName:
 190        case certIPAddress:
 191        case certOtherName:
 192        case certRegisterID:
 193        case certX400Address: {
 194
 195            current->name.other.data =
 196                PORT_ArenaAlloc (arena, strlen (buffer) + 2);
 197            if (current->name.other.data == NULL) {
 198                GEN_BREAK (SECFailure);
 199            }
 200            
 201            PORT_Memcpy (current->name.other.data + 2, buffer,
 202                         strlen (buffer));
 203            /* This may not be accurate for all cases.  For now,
 204             * use this tag type */
 205            current->name.other.data[0] =
 206                (char)(((current->type - 1) & 0x1f)| 0x80);
 207            current->name.other.data[1] = (char)strlen (buffer);
 208            current->name.other.len = strlen (buffer) + 2;
 209            break;
 210        }
 211
 212        case certDirectoryName: {
 213            CERTName *directoryName = NULL;
 214            
 215            directoryName = CERT_AsciiToName (buffer);
 216            if (!directoryName) {
 217                fprintf(stderr, "certutil: improperly formatted name: "
 218                        "\"%s\"\n", buffer);
 219                break;
 220            }
 221            
 222            rv = CERT_CopyName (arena, &current->name.directoryName,
 223                                directoryName);
 224            CERT_DestroyName (directoryName);
 225            
 226            break;
 227        }
 228        }
 229        if (rv != SECSuccess)
 230            break;
 231        current->l.next = &(namesList->l);
 232        current->l.prev = &(tail->l);
 233        tail->l.next = &(current->l);
 234        tail = current;
 235        
 236    }while (1);
 237
 238    if (rv != SECSuccess) {
 239        PORT_ArenaRelease (arena, mark);
 240        namesList = NULL;
 241    }
 242    return (namesList);
 243}
 244
 245static SECStatus 
 246GetString(PRArenaPool *arena, char *prompt, SECItem *value)
 247{
 248    char buffer[251];
 249    char *buffPrt;
 250
 251    buffer[0] = '\0';
 252    value->data = NULL;
 253    value->len = 0;
 254    
 255    puts (prompt);
 256    buffPrt = Gets_s (buffer, sizeof(buffer));
 257    /* returned NULL here treated the same way as empty string */
 258    if (buffPrt && strlen (buffer) > 0) {
 259        value->data = PORT_ArenaAlloc (arena, strlen (buffer));
 260        if (value->data == NULL) {
 261            PORT_SetError (SEC_ERROR_NO_MEMORY);
 262            return (SECFailure);
 263        }
 264        PORT_Memcpy (value->data, buffer, value->len = strlen(buffer));
 265    }
 266    return (SECSuccess);
 267}
 268
 269static PRBool 
 270GetYesNo(char *prompt) 
 271{
 272    char buf[3];
 273    char *buffPrt;
 274
 275    buf[0] = 'n';
 276    puts(prompt);
 277    buffPrt = Gets_s(buf, sizeof(buf));
 278    return (buffPrt && (buf[0] == 'y' || buf[0] == 'Y')) ? PR_TRUE : PR_FALSE;
 279}
 280
 281/* Parses comma separated values out of the string pointed by nextPos.
 282 * Parsed value is compared to an array of possible values(valueArray).
 283 * If match is found, a value index is returned, otherwise returns SECFailue.
 284 * nextPos is set to the token after found comma separator or to NULL.
 285 * NULL in nextPos should be used as indication of the last parsed token.
 286 * A special value "critical" can be parsed out from the supplied sting.*/
 287
 288static SECStatus
 289parseNextCmdInput(const char * const *valueArray, int *value,  char **nextPos,
 290                  PRBool *critical)
 291{
 292    char *thisPos = *nextPos;
 293    int keyLen = 0;
 294    int arrIndex = 0;
 295
 296    if (!valueArray || !value || !nextPos || !critical) {
 297        PORT_SetError(SEC_ERROR_INVALID_ARGS);
 298        return SECFailure;
 299    }
 300    while (1) {
 301        if ((*nextPos = strchr(thisPos, ',')) == NULL) {
 302            keyLen = strlen(thisPos);
 303        } else {
 304            keyLen = *nextPos - thisPos;
 305            *nextPos += 1;
 306        }
 307        /* if critical keyword is found, go for another loop,
 308         * but check, if it is the last keyword of
 309         * the string.*/
 310        if (!strncmp("critical", thisPos, keyLen)) {
 311            *critical = PR_TRUE;
 312            if (*nextPos == NULL) {
 313                return SECSuccess;
 314            }
 315            thisPos = *nextPos;
 316            continue;
 317        }
 318        break;
 319    }
 320    for (arrIndex = 0; valueArray[arrIndex]; arrIndex++) {
 321        if (!strncmp(valueArray[arrIndex], thisPos, keyLen)) {
 322            *value = arrIndex;
 323            return SECSuccess;
 324        }
 325    }
 326    PORT_SetError(SEC_ERROR_INVALID_ARGS);
 327    return SECFailure;
 328}
 329
 330static const char * const
 331keyUsageKeyWordArray[] = { "digitalSignature",
 332                           "nonRepudiation",
 333                           "keyEncipherment",
 334                           "dataEncipherment",
 335                           "keyAgreement",
 336                           "certSigning",
 337                           "crlSigning",
 338                           NULL};
 339
 340static SECStatus 
 341AddKeyUsage (void *extHandle, const char *userSuppliedValue)
 342{
 343    SECItem bitStringValue;
 344    unsigned char keyUsage = 0x0;
 345    char buffer[5];
 346    int value;
 347    char *nextPos = (char*)userSuppliedValue;
 348    PRBool isCriticalExt = PR_FALSE;
 349
 350    if (!userSuppliedValue) {
 351        while (1) {
 352            if (PrintChoicesAndGetAnswer(
 353                    "\t\t0 - Digital Signature\n"
 354                    "\t\t1 - Non-repudiation\n"
 355                    "\t\t2 - Key encipherment\n"
 356                    "\t\t3 - Data encipherment\n"   
 357                    "\t\t4 - Key agreement\n"
 358                    "\t\t5 - Cert signing key\n"   
 359                    "\t\t6 - CRL signing key\n"
 360                    "\t\tOther to finish\n",
 361                    buffer, sizeof(buffer)) == SECFailure) {
 362                return SECFailure;
 363            }
 364            value = PORT_Atoi (buffer);
 365            if (value < 0 || value > 6)
 366                break;
 367            if (value == 0) {
 368                /* Checking that zero value of variable 'value'
 369                 * corresponds to '0' input made by user */
 370                char *chPtr = strchr(buffer, '0');
 371                if (chPtr == NULL) {
 372                    continue;
 373                }
 374            }
 375            keyUsage |= (0x80 >> value);
 376        }
 377        isCriticalExt = GetYesNo("Is this a critical extension [y/N]?");
 378    } else {
 379        while (1) {
 380            if (parseNextCmdInput(keyUsageKeyWordArray, &value, &nextPos,
 381                                  &isCriticalExt) == SECFailure) {
 382                return SECFailure;
 383            }
 384            keyUsage |= (0x80 >> value);
 385            if (!nextPos)
 386                break;
 387        }
 388    }
 389
 390    bitStringValue.data = &keyUsage;
 391    bitStringValue.len = 1;
 392
 393    return (CERT_EncodeAndAddBitStrExtension
 394            (extHandle, SEC_OID_X509_KEY_USAGE, &bitStringValue,
 395             isCriticalExt));
 396
 397}
 398
 399
 400static CERTOidSequence *
 401CreateOidSequence(void)
 402{
 403    CERTOidSequence *rv = (CERTOidSequence *)NULL;
 404    PRArenaPool *arena = (PRArenaPool *)NULL;
 405
 406    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
 407    if( (PRArenaPool *)NULL == arena ) {
 408        goto loser;
 409    }
 410
 411    rv = (CERTOidSequence *)PORT_ArenaZNew(arena, CERTOidSequence);
 412    if( (CERTOidSequence *)NULL == rv ) {
 413        goto loser;
 414    }
 415
 416    rv->oids = (SECItem **)PORT_ArenaZNew(arena, SECItem *);
 417    if( (SECItem **)NULL == rv->oids ) {
 418        goto loser;
 419    }
 420
 421    rv->arena = arena;
 422    return rv;
 423
 424loser:
 425    if( (PRArenaPool *)NULL != arena ) {
 426        PORT_FreeArena(arena, PR_FALSE);
 427    }
 428
 429    return (CERTOidSequence *)NULL;
 430}
 431
 432static void
 433DestroyOidSequence(CERTOidSequence *os)
 434{
 435    if (os->arena) {
 436        PORT_FreeArena(os->arena, PR_FALSE);
 437    }
 438}
 439
 440static SECStatus
 441AddOidToSequence(CERTOidSequence *os, SECOidTag oidTag)
 442{
 443    SECItem **oids;
 444    PRUint32 count = 0;
 445    SECOidData *od;
 446
 447    od = SECOID_FindOIDByTag(oidTag);
 448    if( (SECOidData *)NULL == od ) {
 449        return SECFailure;
 450    }
 451
 452    for( oids = os->oids; (SECItem *)NULL != *oids; oids++ ) {
 453        if (*oids == &od->oid) {
 454            /* We already have this oid */
 455            return SECSuccess;
 456        }
 457        count++;
 458    }
 459
 460    /* ArenaZRealloc */
 461
 462    {
 463        PRUint32 i;
 464
 465        oids = (SECItem **)PORT_ArenaZNewArray(os->arena, SECItem *, count + 2);
 466        if( (SECItem **)NULL == oids ) {
 467            return SECFailure;
 468        }
 469    
 470        for( i = 0; i < count; i++ ) {
 471            oids[i] = os->oids[i];
 472        }
 473
 474        /* ArenaZFree(os->oids); */
 475    }
 476
 477    os->oids = oids;
 478    os->oids[count] = &od->oid;
 479
 480    return SECSuccess;
 481}
 482
 483SEC_ASN1_MKSUB(SEC_ObjectIDTemplate)
 484
 485const SEC_ASN1Template CERT_OidSeqTemplate[] = {
 486    { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN, offsetof(CERTOidSequence, oids),
 487      SEC_ASN1_SUB(SEC_ObjectIDTemplate) }
 488};
 489
 490
 491static SECItem *
 492EncodeOidSequence(CERTOidSequence *os)
 493{
 494    SECItem *rv;
 495
 496    rv = (SECItem *)PORT_ArenaZNew(os->arena, SECItem);
 497    if( (SECItem *)NULL == rv ) {
 498        goto loser;
 499    }
 500
 501    if( !SEC_ASN1EncodeItem(os->arena, rv, os, CERT_OidSeqTemplate) ) {
 502        goto loser;
 503    }
 504
 505    return rv;
 506
 507loser:
 508    return (SECItem *)NULL;
 509}
 510
 511static const char * const 
 512extKeyUsageKeyWordArray[] = { "serverAuth",
 513                              "clientAuth",
 514                              "codeSigning",
 515                              "emailProtection",
 516                              "timeStamp",
 517                              "ocspResponder",
 518                              "stepUp",
 519                              NULL};
 520
 521static SECStatus 
 522AddExtKeyUsage (void *extHandle, const char *userSuppliedValue)
 523{
 524    char buffer[5];
 525    int value;
 526    CERTOidSequence *os;
 527    SECStatus rv;
 528    SECItem *item;
 529    PRBool isCriticalExt = PR_FALSE;
 530    char *nextPos = (char*)userSuppliedValue;
 531    
 532    os = CreateOidSequence();
 533    if( (CERTOidSequence *)NULL == os ) {
 534        return SECFailure;
 535    }
 536
 537    while (1) {
 538        if (!userSuppliedValue) {
 539            if (PrintChoicesAndGetAnswer(
 540                    "\t\t0 - Server Auth\n"
 541                    "\t\t1 - Client Auth\n"
 542                    "\t\t2 - Code Signing\n"
 543                    "\t\t3 - Email Protection\n"
 544                    "\t\t4 - Timestamp\n"
 545                    "\t\t5 - OCSP Responder\n"
 546                    "\t\t6 - Step-up\n"
 547                    "\t\tOther to finish\n",
 548                    buffer, sizeof(buffer)) == SECFailure) {
 549                GEN_BREAK(SECFailure);
 550            }
 551            value = PORT_Atoi(buffer);
 552            
 553            if (value == 0) {
 554                /* Checking that zero value of variable 'value'
 555                 * corresponds to '0' input made by user */
 556                char *chPtr = strchr(buffer, '0');
 557                if (chPtr == NULL) {
 558                    continue;
 559                }
 560            }
 561        } else {
 562            if (parseNextCmdInput(extKeyUsageKeyWordArray, &value, &nextPos,
 563                                  &isCriticalExt) == SECFailure) {
 564                return SECFailure;
 565            }
 566        }
 567
 568        switch( value ) {
 569        case 0:
 570            rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_SERVER_AUTH);
 571            break;
 572        case 1:
 573            rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH);
 574            break;
 575        case 2:
 576            rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_CODE_SIGN);
 577            break;
 578        case 3:
 579            rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT);
 580            break;
 581        case 4:
 582            rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_TIME_STAMP);
 583            break;
 584        case 5:
 585            rv = AddOidToSequence(os, SEC_OID_OCSP_RESPONDER);
 586            break;
 587        case 6:
 588            rv = AddOidToSequence(os, SEC_OID_NS_KEY_USAGE_GOVT_APPROVED);
 589            break;
 590        default:
 591            goto endloop;
 592        }
 593
 594        if (userSuppliedValue && !nextPos)
 595            break;
 596        if( SECSuccess != rv )
 597            goto loser;
 598    }
 599
 600endloop:
 601    item = EncodeOidSequence(os);
 602
 603    if (!userSuppliedValue) {
 604        isCriticalExt = GetYesNo("Is this a critical extension [y/N]?");
 605    }
 606
 607    rv = CERT_AddExtension(extHandle, SEC_OID_X509_EXT_KEY_USAGE, item,
 608                           isCriticalExt, PR_TRUE);
 609    /*FALLTHROUGH*/
 610loser:
 611    DestroyOidSequence(os);
 612    return rv;
 613}
 614
 615static const char * const
 616nsCertTypeKeyWordArray[] = { "sslClient",
 617                             "sslServer",
 618                             "smime",
 619                             "objectSigning",
 620                             "Not!Used",
 621                             "sslCA",
 622                             "smimeCA",
 623                             "objectSigningCA",
 624                            NULL };
 625
 626static SECStatus 
 627AddNscpCertType (void *extHandle, const char *userSuppliedValue)
 628{
 629    SECItem bitStringValue;
 630    unsigned char keyUsage = 0x0;
 631    char buffer[5];
 632    int value;
 633    char *nextPos = (char*)userSuppliedValue;
 634    PRBool isCriticalExt = PR_FALSE;
 635
 636    if (!userSuppliedValue) {
 637        while (1) {
 638            if (PrintChoicesAndGetAnswer(
 639                    "\t\t0 - SSL Client\n"
 640                    "\t\t1 - SSL Server\n"
 641                    "\t\t2 - S/MIME\n"
 642                    "\t\t3 - Object Signing\n"   
 643                    "\t\t4 - Reserved for future use\n"
 644                    "\t\t5 - SSL CA\n"   
 645                    "\t\t6 - S/MIME CA\n"
 646                    "\t\t7 - Object Signing CA\n"
 647                    "\t\tOther to finish\n",
 648                    buffer, sizeof(buffer)) == SECFailure) {
 649                return SECFailure;
 650            }
 651            value = PORT_Atoi (buffer);
 652            if (value < 0 || value > 7)
 653                break;
 654            if (value == 0) {
 655                /* Checking that zero value of variable 'value'
 656                 * corresponds to '0' input made by user */
 657                char *chPtr = strchr(buffer, '0');
 658                if (chPtr == NULL) {
 659                    continue;
 660                }
 661            }
 662            keyUsage |= (0x80 >> value);
 663        }
 664        isCriticalExt = GetYesNo("Is this a critical extension [y/N]?");
 665    } else {
 666        while (1) {
 667            if (parseNextCmdInput(nsCertTypeKeyWordArray, &value, &nextPos,
 668                                  &isCriticalExt) == SECFailure) {
 669                return SECFailure;
 670            }
 671            keyUsage |= (0x80 >> value);
 672            if (!nextPos)
 673                break;
 674        }
 675    }
 676
 677    bitStringValue.data = &keyUsage;
 678    bitStringValue.len = 1;
 679
 680    return (CERT_EncodeAndAddBitStrExtension
 681            (extHandle, SEC_OID_NS_CERT_EXT_CERT_TYPE, &bitStringValue,
 682             isCriticalExt));
 683
 684}
 685
 686static SECStatus 
 687AddSubjectAltNames(PRArenaPool *arena, CERTGeneralName **existingListp,
 688                   const char *names, CERTGeneralNameType type)
 689{
 690    CERTGeneralName *nameList = NULL;
 691    CERTGeneralName *current = NULL;
 692    PRCList *prev = NULL;
 693    const char *cp;
 694    char *tbuf;
 695    SECStatus rv = SECSuccess;
 696
 697    /*
 698     * walk down the comma separated list of names. NOTE: there is
 699     * no sanity checks to see if the email address look like
 700     * email addresses.
 701     */
 702    for (cp=names; cp; cp = PORT_Strchr(cp,',')) {
 703        int len;
 704        char *end;
 705
 706        if (*cp == ',') {
 707            cp++;
 708        }
 709        end = PORT_Strchr(cp,',');
 710        len = end ? end-cp : PORT_Strlen(cp);
 711        if (len <= 0) {
 712            continue;
 713        }
 714        tbuf = PORT_ArenaAlloc(arena,len+1);
 715        PORT_Memcpy(tbuf,cp,len);
 716        tbuf[len] = 0;
 717        current = (CERTGeneralName *) PORT_ZAlloc(sizeof(CERTGeneralName));
 718        if (!current) {
 719            rv = SECFailure;
 720            break;
 721        }
 722        if (prev) {
 723            current->l.prev = prev;
 724            prev->next = &(current->l);
 725        } else {
 726            nameList = current;
 727        }
 728        current->type = type;
 729        current->name.other.data = (unsigned char *)tbuf;
 730        current->name.other.len = PORT_Strlen(tbuf);
 731        prev = &(current->l);
 732    }
 733    /* at this point nameList points to the head of a doubly linked,
 734     * but not yet circular, list and current points to its tail. */
 735    if (rv == SECSuccess && nameList) {
 736        if (*existingListp != NULL) {
 737            PRCList *existingprev;
 738            /* add nameList to the end of the existing list */
 739            existingprev = (*existingListp)->l.prev;
 740            (*existingListp)->l.prev = &(current->l);
 741            nameList->l.prev = existingprev;
 742            existingprev->next = &(nameList->l);
 743            current->l.next = &((*existingListp)->l);
 744        }
 745        else {
 746            /* make nameList circular and set it as the new existingList */
 747            nameList->l.prev = prev;
 748            current->l.next = &(nameList->l);
 749            *existingListp = nameList;
 750        }
 751    }
 752    return rv;
 753}
 754
 755static SECStatus 
 756AddEmailSubjectAlt(PRArenaPool *arena, CERTGeneralName **existingListp,
 757                   const char *emailAddrs)
 758{
 759    return AddSubjectAltNames(arena, existingListp, emailAddrs, 
 760                              certRFC822Name);
 761}
 762
 763static SECStatus 
 764AddDNSSubjectAlt(PRArenaPool *arena, CERTGeneralName **existingListp,
 765                 const char *dnsNames)
 766{
 767    return AddSubjectAltNames(arena, existingListp, dnsNames, certDNSName);
 768}
 769
 770
 771static SECStatus 
 772AddBasicConstraint(void *extHandle)
 773{
 774    CERTBasicConstraints basicConstraint;    
 775    SECStatus rv;
 776    char buffer[10];
 777    PRBool yesNoAns;
 778
 779    do {
 780        basicConstraint.pathLenConstraint = CERT_UNLIMITED_PATH_CONSTRAINT;
 781        basicConstraint.isCA = GetYesNo ("Is this a CA certificate [y/N]?");
 782
 783        buffer[0] = '\0';
 784        if (PrintChoicesAndGetAnswer("Enter the path length constraint, "
 785                                     "enter to skip [<0 for unlimited path]:",
 786                                     buffer, sizeof(buffer)) == SECFailure) {
 787            GEN_BREAK(SECFailure);
 788        }
 789        if (PORT_Strlen (buffer) > 0)
 790            basicConstraint.pathLenConstraint = PORT_Atoi (buffer);
 791
 792        yesNoAns = GetYesNo ("Is this a critical extension [y/N]?");
 793
 794        rv = SECU_EncodeAndAddExtensionValue(NULL, extHandle,
 795		 &basicConstraint, yesNoAns, SEC_OID_X509_BASIC_CONSTRAINTS,
 796		 (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeBasicConstraintValue);
 797    } while (0);
 798
 799    return (rv);
 800}
 801
 802static SECStatus 
 803AddAuthKeyID (void *extHandle)
 804{
 805    CERTAuthKeyID *authKeyID = NULL;    
 806    PRArenaPool *arena = NULL;
 807    SECStatus rv = SECSuccess;
 808    PRBool yesNoAns;
 809
 810    do {
 811        arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
 812        if ( !arena ) {
 813            SECU_PrintError(progName, "out of memory");
 814            GEN_BREAK (SECFailure);
 815        }
 816
 817        if (GetYesNo ("Enter value for the authKeyID extension [y/N]?") == 0)
 818            break;
 819
 820        authKeyID = PORT_ArenaZNew(arena, CERTAuthKeyID);
 821        if (authKeyID == NULL) {
 822            GEN_BREAK (SECFailure);
 823        }
 824
 825        rv = GetString (arena, "Enter value for the key identifier fields,"
 826                        "enter to omit:", &authKeyID->keyID);
 827        if (rv != SECSuccess)
 828            break;
 829
 830        SECU_SECItemHexStringToBinary(&authKeyID->keyID);
 831
 832        authKeyID->authCertIssuer = GetGeneralName (arena);
 833        if (authKeyID->authCertIssuer == NULL && 
 834            SECFailure == PORT_GetError ())
 835            break;
 836
 837
 838        rv = GetString (arena, "Enter value for the authCertSerial field, "
 839                        "enter to omit:", &authKeyID->authCertSerialNumber);
 840
 841        yesNoAns = GetYesNo ("Is this a critical extension [y/N]?");
 842
 843        rv = SECU_EncodeAndAddExtensionValue(arena, extHandle,
 844		     authKeyID, yesNoAns, SEC_OID_X509_AUTH_KEY_ID, 
 845		     (EXTEN_EXT_VALUE_ENCODER) CERT_EncodeAuthKeyID);
 846        if (rv)
 847            break;
 848
 849    } while (0);
 850    if (arena)
 851        PORT_FreeArena (arena, PR_FALSE);
 852    return (rv);
 853}   
 854    
 855static SECStatus 
 856AddSubjKeyID (void *extHandle)
 857{
 858    SECItem keyID;
 859    PRArenaPool *arena = NULL;
 860    SECStatus rv = SECSuccess;
 861    PRBool yesNoAns;
 862
 863    do {
 864        arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
 865        if ( !arena ) {
 866            SECU_PrintError(progName, "out of memory");
 867            GEN_BREAK (SECFailure);
 868        }
 869        printf("Adding Subject Key ID extension.\n");
 870
 871        rv = GetString (arena, "Enter value for the key identifier fields,"
 872                        "enter to omit:", &keyID);
 873        if (rv != SECSuccess)
 874            break;
 875
 876        SECU_SECItemHexStringToBinary(&keyID);
 877
 878        yesNoAns = GetYesNo ("Is this a critical extension [y/N]?");
 879
 880        rv = SECU_EncodeAndAddExtensionValue(arena, extHandle,
 881		     &keyID, yesNoAns, SEC_OID_X509_SUBJECT_KEY_ID, 
 882		     (EXTEN_EXT_VALUE_ENCODER) CERT_EncodeSubjectKeyID);
 883        if (rv)
 884            break;
 885
 886    } while (0);
 887    if (arena)
 888        PORT_FreeArena (arena, PR_FALSE);
 889    return (rv);
 890}   
 891
 892static SECStatus 
 893AddCrlDistPoint(void *extHandle)
 894{
 895    PRArenaPool *arena = NULL;
 896    CERTCrlDistributionPoints *crlDistPoints = NULL;
 897    CRLDistributionPoint *current;
 898    SECStatus rv = SECSuccess;
 899    int count = 0, intValue;
 900    char buffer[512];
 901
 902    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
 903    if ( !arena )
 904        return (SECFailure);
 905
 906    do {
 907        current = NULL;
 908
 909        current = PORT_ArenaZNew(arena, CRLDistributionPoint);
 910        if (current == NULL) {
 911            GEN_BREAK (SECFailure);
 912        }   
 913
 914        /* Get the distributionPointName fields - this field is optional */
 915        if (PrintChoicesAndGetAnswer(
 916                "Enter the type of the distribution point name:\n"
 917                "\t1 - Full Name\n\t2 - Relative Name\n\tAny other "
 918                "number to finish\n\t\tChoice: ",
 919                buffer, sizeof(buffer)) == SECFailure) {
 920	    GEN_BREAK (SECFailure);
 921	}
 922        intValue = PORT_Atoi (buffer);
 923        switch (intValue) {
 924        case generalName:
 925            current->distPointType = intValue;
 926            current->distPoint.fullName = GetGeneralName (arena);
 927            rv = PORT_GetError();
 928            break;
 929
 930        case relativeDistinguishedName: {
 931            CERTName *name;
 932
 933            current->distPointType = intValue;
 934            puts ("Enter the relative name: ");
 935            fflush (stdout);
 936            if (Gets_s (buffer, sizeof(buffer)) == NULL) {
 937                GEN_BREAK (SECFailure);
 938            }
 939            /* For simplicity, use CERT_AsciiToName to converse from a string
 940               to NAME, but we only interest in the first RDN */
 941            name = CERT_AsciiToName (buffer);
 942            if (!name) {
 943                GEN_BREAK (SECFailure);
 944            }
 945            rv = CERT_CopyRDN (arena, &current->distPoint.relativeName,
 946                               name->rdns[0]);
 947            CERT_DestroyName (name);
 948            break;
 949          }
 950        }
 951        if (rv != SECSuccess)
 952            break;
 953
 954        /* Get the reason flags */
 955        if (PrintChoicesAndGetAnswer(
 956                "\nSelect one of the following for the reason flags\n"
 957                "\t0 - unused\n\t1 - keyCompromise\n"
 958                "\t2 - caCompromise\n\t3 - affiliationChanged\n"
 959                "\t4 - superseded\n\t5 - cessationOfOperation\n"
 960                "\t6 - certificateHold\n"
 961                "\tAny other number to finish\t\tChoice: ",
 962                buffer, sizeof(buffer)) == SECFailure) {
 963            GEN_BREAK(SECFailure);
 964        }
 965        intValue = PORT_Atoi (buffer);
 966        if (intValue == 0) {
 967            /* Checking that zero value of variable 'value'
 968             * corresponds to '0' input made by user */
 969            char *chPtr = strchr(buffer, '0');
 970            if (chPtr == NULL) {
 971                intValue = -1;
 972            }
 973        }
 974        if (intValue >= 0 && intValue <8) {
 975            current->reasons.data = PORT_ArenaAlloc (arena, sizeof(char));
 976            if (current->reasons.data == NULL) {
 977                GEN_BREAK (SECFailure);
 978            }
 979            *current->reasons.data = (char)(0x80 >> intValue);
 980            current->reasons.len = 1;
 981        }
 982        puts ("Enter value for the CRL Issuer name:\n");
 983        current->crlIssuer = GetGeneralName (arena);
 984        if (current->crlIssuer == NULL && (rv = PORT_GetError()) == SECFailure)
 985            break;
 986
 987        if (crlDistPoints == NULL) {
 988            crlDistPoints = PORT_ArenaZNew(arena, CERTCrlDistributionPoints);
 989            if (crlDistPoints == NULL) {
 990                GEN_BREAK (SECFailure);
 991            }
 992        }
 993
 994        crlDistPoints->distPoints =
 995            PORT_ArenaGrow (arena, crlDistPoints->distPoints,
 996                            sizeof (*crlDistPoints->distPoints) * count,
 997                            sizeof (*crlDistPoints->distPoints) *(count + 1));
 998        if (crlDistPoints->distPoints == NULL) {
 999            GEN_BREAK (SECFailure);
1000        }
1001
1002        crlDistPoints->distPoints[count] = current;
1003        ++count;
1004        if (GetYesNo("Enter another value for the CRLDistributionPoint "
1005                      "extension [y/N]?") == 0) {
1006            /* Add null to the end to mark end of data */
1007            crlDistPoints->distPoints =
1008                PORT_ArenaGrow(arena, crlDistPoints->distPoints,
1009			   sizeof (*crlDistPoints->distPoints) * count,
1010			   sizeof (*crlDistPoints->distPoints) *(count + 1));
1011            crlDistPoints->distPoints[count] = NULL;    
1012            break;
1013        }
1014
1015
1016    } while (1);
1017    
1018    if (rv == SECSuccess) {
1019        PRBool yesNoAns = GetYesNo ("Is this a critical extension [y/N]?");
1020
1021        rv = SECU_EncodeAndAddExtensionValue(arena, extHandle,
1022		 crlDistPoints, yesNoAns, SEC_OID_X509_CRL_DIST_POINTS,
1023		 (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeCRLDistributionPoints);
1024    }
1025    if (arena)
1026        PORT_FreeArena (arena, PR_FALSE);
1027    return (rv);
1028}
1029
1030
1031
1032static SECStatus 
1033AddPolicyConstraints(void *extHandle)
1034{
1035    CERTCertificatePolicyConstraints *policyConstr;
1036    PRArenaPool *arena = NULL;
1037    SECStatus rv = SECSuccess;
1038    SECItem *item, *dummy;
1039    char buffer[512];
1040    int value;
1041    PRBool yesNoAns;
1042    PRBool skipExt = PR_TRUE;
1043
1044    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1045    if ( !arena ) {
1046        SECU_PrintError(progName, "out of memory");
1047        return SECFailure;
1048    }
1049
1050    policyConstr = PORT_ArenaZNew(arena, CERTCertificatePolicyConstraints);
1051    if (policyConstr == NULL) {
1052        SECU_PrintError(progName, "out of memory");
1053        goto loser;
1054    }
1055
1056    if (PrintChoicesAndGetAnswer("for requireExplicitPolicy enter the number "
1057               "of certs in path\nbefore explicit policy is required\n"
1058               "(press Enter to omit)", buffer, sizeof(buffer)) == SECFailure) {
1059        goto loser;
1060    }
1061
1062    if (PORT_Strlen(buffer)) {
1063        value = PORT_Atoi(buffer);
1064	if (value < 0) {
1065            goto loser;
1066        }
1067        item = &policyConstr->explicitPolicySkipCerts;
1068        dummy = SEC_ASN1EncodeInteger(arena, item, value);
1069        if (!dummy) {
1070            goto loser;
1071        }
1072        skipExt = PR_FALSE;
1073    }
1074
1075    if (PrintChoicesAndGetAnswer("for inihibitPolicyMapping enter "
1076               "the number of certs in path\n"
1077	       "after which policy mapping is not allowed\n"
1078               "(press Enter to omit)", buffer, sizeof(buffer)) == SECFailure) {
1079        goto loser;
1080    }
1081
1082    if (PORT_Strlen(buffer)) {
1083        value = PORT_Atoi(buffer);
1084	if (value < 0) {
1085            goto loser;
1086        }
1087        item = &policyConstr->inhibitMappingSkipCerts;
1088        dummy = SEC_ASN1EncodeInteger(arena, item, value);
1089        if (!dummy) {
1090            goto loser;
1091        }
1092        skipExt = PR_FALSE;
1093    }
1094 
1095    
1096    if (!skipExt) {
1097        yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
1098
1099        rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, policyConstr,
1100	     yesNoAns, SEC_OID_X509_POLICY_CONSTRAINTS,
1101	     (EXTEN_EXT_VALUE_ENCODER)CERT_EncodePolicyConstraintsExtension);
1102    } else {
1103	fprintf(stdout, "Policy Constraint extensions must contain "
1104                        "at least one policy field\n");
1105	rv = SECFailure;
1106    }
1107   
1108loser:
1109    if (arena) {
1110        PORT_FreeArena (arena, PR_FALSE);
1111    }
1112    return (rv);
1113}
1114
1115
1116static SECStatus 
1117AddInhibitAnyPolicy(void *extHandle)
1118{
1119    CERTCertificateInhibitAny certInhibitAny;
1120    PRArenaPool *arena = NULL;
1121    SECStatus rv = SECSuccess;
1122    SECItem *item, *dummy;
1123    char buffer[10];
1124    int value;
1125    PRBool yesNoAns;
1126    
1127
1128    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1129    if ( !arena ) {
1130        SECU_PrintError(progName, "out of memory");
1131        return SECFailure;
1132    }
1133
1134    if (PrintChoicesAndGetAnswer("Enter the number of certs in the path "
1135                                 "permitted to use anyPolicy.\n"
1136                                 "(press Enter for 0)",
1137                                 buffer, sizeof(buffer)) == SECFailure) {
1138        goto loser;
1139    }
1140
1141    item = &certInhibitAny.inhibitAnySkipCerts;
1142    value = PORT_Atoi(buffer);
1143    if (value < 0) {
1144        goto loser;
1145    }
1146    dummy = SEC_ASN1EncodeInteger(arena, item, value);
1147    if (!dummy) {
1148        goto loser;
1149    }
1150    
1151    yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
1152    
1153    rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, &certInhibitAny,
1154		 yesNoAns, SEC_OID_X509_INHIBIT_ANY_POLICY,
1155		 (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeInhibitAnyExtension);
1156loser:
1157    if (arena) {
1158        PORT_FreeArena (arena, PR_FALSE);
1159    }
1160    return (rv);
1161}
1162
1163
1164static SECStatus 
1165AddPolicyMappings(void *extHandle)
1166{
1167    CERTPolicyMap **policyMapArr = NULL;
1168    CERTPolicyMap *current;
1169    PRArenaPool *arena = NULL;
1170    SECStatus rv = SECSuccess;
1171    int count = 0;
1172    char buffer[512];
1173    
1174    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1175    if ( !arena ) {
1176        SECU_PrintError(progName, "out of memory");
1177        return SECFailure;
1178    }
1179
1180    do {
1181        if (PrintChoicesAndGetAnswer("Enter an Object Identifier (dotted "
1182                                     "decimal format) for Issuer Domain Policy",
1183                                     buffer, sizeof(buffer)) == SECFailure) {
1184            GEN_BREAK (SECFailure);
1185        }
1186
1187        current = PORT_ArenaZNew(arena, CERTPolicyMap);
1188        if (current == NULL) {
1189            GEN_BREAK(SECFailure);
1190        }
1191
1192        rv = SEC_StringToOID(arena, &current->issuerDomainPolicy, buffer, 0);
1193        if (rv == SECFailure) {
1194            GEN_BREAK(SECFailure);
1195        }
1196
1197        if (PrintChoicesAndGetAnswer("Enter an Object Identifier for "
1198                                     "Subject Domain Policy",
1199                                     buffer, sizeof(buffer)) == SECFailure) {
1200            GEN_BREAK (SECFailure);
1201        }
1202
1203        rv = SEC_StringToOID(arena, &current->subjectDomainPolicy, buffer, 0);
1204        if (rv == SECFailure) {
1205            GEN_BREAK(SECFailure);
1206        }
1207
1208        if (policyMapArr == NULL) {
1209            policyMapArr = PORT_ArenaZNew(arena, CERTPolicyMap *);
1210            if (policyMapArr == NULL) {
1211                GEN_BREAK (SECFailure);
1212            }
1213        }
1214
1215        policyMapArr = PORT_ArenaGrow(arena, policyMapArr,
1216                                         sizeof (current) * count,
1217                                         sizeof (current) *(count + 1));
1218        if (policyMapArr == NULL) {
1219            GEN_BREAK (SECFailure);
1220        }
1221    
1222        policyMapArr[count] = current;
1223        ++count;
1224        
1225        if (!GetYesNo("Enter another Policy Mapping [y/N]")) {
1226            /* Add null to the end to mark end of data */
1227            policyMapArr = PORT_ArenaGrow (arena, policyMapArr,
1228                                           sizeof (current) * count,
1229                                           sizeof (current) *(count + 1));
1230            if (policyMapArr == NULL) {
1231                GEN_BREAK (SECFailure);
1232            }
1233            policyMapArr[count] = NULL;        
1234            break;
1235        }
1236
1237    } while (1);
1238
1239    if (rv == SECSuccess) {
1240        CERTCertificatePolicyMappings mappings;
1241        PRBool yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
1242
1243        mappings.arena = arena;
1244        mappings.policyMaps = policyMapArr;
1245        rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, &mappings,
1246		 yesNoAns, SEC_OID_X509_POLICY_MAPPINGS,
1247		 (EXTEN_EXT_VALUE_ENCODER)CERT_EncodePolicyMappingExtension);
1248    }
1249    if (arena)
1250        PORT_FreeArena (arena, PR_FALSE);
1251    return (rv);
1252}
1253
1254enum PoliciQualifierEnum {
1255    cpsPointer = 1,
1256    userNotice = 2
1257};
1258
1259
1260static CERTPolicyQualifier **
1261RequestPolicyQualifiers(PRArenaPool *arena, SECItem *policyID)
1262{
1263    CERTPolicyQualifier **policyQualifArr = NULL;
1264    CERTPolicyQualifier *current;
1265    SECStatus rv = SECSuccess;
1266    int count = 0;
1267    char buffer[512];
1268    void *mark;
1269    SECOidData *oid = NULL;
1270    int intValue = 0;
1271    int inCount = 0;
1272
1273    PORT_Assert(arena);
1274    mark = PORT_ArenaMark(arena);
1275    do {
1276        current = PORT_ArenaZNew(arena, CERTPolicyQualifier);
1277        if (current == NULL) {
1278            GEN_BREAK(SECFailure);
1279        }
1280
1281        /* Get the accessMethod fields */
1282        SECU_PrintObjectID(stdout, policyID,
1283                           "Choose the type of qualifier for policy" , 0);
1284
1285        if (PrintChoicesAndGetAnswer(
1286                "\t1 - CPS Pointer qualifier\n"
1287                "\t2 - User notice qualifier\n"
1288                "\tAny other number to finish\n"
1289                "\t\tChoice: ", buffer, sizeof(buffer)) == SECFailure) {
1290            GEN_BREAK (SECFailure);
1291        }
1292        intValue = PORT_Atoi(buffer);
1293        switch (intValue) {
1294        case cpsPointer: {
1295            SECItem input;
1296
1297            oid = SECOID_FindOIDByTag(SEC_OID_PKIX_CPS_POINTER_QUALIFIER);
1298            if (PrintChoicesAndGetAnswer("Enter CPS pointer URI: ",
1299				     buffer, sizeof(buffer)) == SECFailure) {
1300                GEN_BREAK (SECFailure);
1301            }
1302            input.len = PORT_Strlen(buffer);
1303            input.data = (void*)PORT_ArenaStrdup(arena, buffer);
1304            if (input.data == NULL ||
1305	        SEC_ASN1EncodeItem(arena, &current->qualifierValue, &input,
1306			       SEC_ASN1_GET(SEC_IA5StringTemplate)) == NULL) {
1307                GEN_BREAK (SECFailure);
1308	    }
1309            break;
1310        }
1311        case userNotice: {
1312            SECItem **noticeNumArr;
1313            CERTUserNotice *notice = PORT_ArenaZNew(arena, CERTUserNotice);
1314            if (!notice) {
1315                GEN_BREAK(SECFailure);
1316            }
1317            
1318            oid = SECOID_FindOIDByTag(SEC_OID_PKIX_USER_NOTICE_QUALIFIER);
1319
1320            if (GetYesNo("\t add a User Notice reference? [y/N]")) {
1321
1322                if (PrintChoicesAndGetAnswer("Enter user organization string: ",
1323				 buffer, sizeof(buffer)) == SECFailure) {
1324                    GEN_BREAK (SECFailure);
1325                }
1326
1327                notice->noticeReference.organization.type = siAsciiString;
1328                notice->noticeReference.organization.len =
1329                    PORT_Strlen(buffer);
1330                notice->noticeReference.organization.data =
1331                    (void*)PORT_ArenaStrdup(arena, buffer);
1332
1333
1334                noticeNumArr = PORT_ArenaZNewArray(arena, SECItem *, 2);
1335		if (!noticeNumArr) {
1336                    GEN_BREAK (SECFailure);
1337		}
1338                
1339                do {
1340                    SECItem *noticeNum;
1341                    
1342                    noticeNum = PORT_ArenaZNew(arena, SECItem);
1343                    
1344                    if (PrintChoicesAndGetAnswer(
1345				      "Enter User Notice reference number "
1346				      "(or -1 to quit): ",
1347                                      buffer, sizeof(buffer)) == SECFailure) {
1348                        GEN_BREAK (SECFailure);
1349                    }
1350                    
1351                    intValue = PORT_Atoi(buffer);
1352		    if (noticeNum == NULL) {
1353			if (intValue < 0) {
1354			    fprintf(stdout, "a noticeReference must have at "
1355                                    "least one reference number\n");
1356                            GEN_BREAK (SECFailure);
1357			}
1358		    } else {
1359			if (intValue >= 0) {
1360                            noticeNumArr = PORT_ArenaGrow(arena, noticeNumArr,
1361					      sizeof (current) * inCount,
1362					      sizeof (current) *(inCount + 1));
1363                            if (noticeNumArr == NULL) {
1364                                GEN_BREAK (SECFailure);
1365                            }
1366			} else {
1367			    break;
1368			}
1369                    }
1370                    if (!SEC_ASN1EncodeInteger(arena, noticeNum, intValue)) {
1371                        GEN_BREAK (SECFailure);
1372		    }
1373                    noticeNumArr[inCount++] = noticeNum;
1374                    noticeNumArr[inCount] = NULL;
1375                    
1376                } while (1);
1377                if (rv == SECFailure) {
1378                    GEN_BREAK(SECFailure);
1379                }
1380                notice->noticeReference.noticeNumbers = noticeNumArr;
1381                rv = CERT_EncodeNoticeReference(arena, &notice->noticeReference,
1382                                                &notice->derNoticeReference);
1383                if (rv == SECFailure) {
1384                    GEN_BREAK(SECFailure);
1385                }
1386            }
1387            if (GetYesNo("\t EnterUser Notice explicit text? [y/N]")) {
1388                /* Getting only 200 bytes - RFC limitation */
1389                if (PrintChoicesAndGetAnswer(
1390                        "\t", buffer, 200) == SECFailure) {
1391                        GEN_BREAK (SECFailure);
1392                }
1393                notice->displayText.type = siAsciiString;
1394                notice->displayText.len = PORT_Strlen(buffer);
1395                notice->displayText.data = 
1396		                        (void*)PORT_ArenaStrdup(arena, buffer);
1397		if (notice->displayText.data == NULL) {
1398		    GEN_BREAK(SECFailure);
1399		}
1400            }
1401
1402            rv = CERT_EncodeUserNotice(arena, notice, &current->qualifierValue);
1403            if (rv == SECFailure) {
1404                GEN_BREAK(SECFailure);
1405            }
1406
1407            break;
1408        }
1409        }
1410        if (rv == SECFailure || oid == NULL ||
1411            SECITEM_CopyItem(arena, &current->qualifierID, &oid->oid) 
1412	    == SECFailure) {
1413            GEN_BREAK (SECFailure);
1414        }
1415
1416        if (!policyQualifArr) {
1417            policyQualifArr = PORT_ArenaZNew(arena, CERTPolicyQualifier *);
1418        } else {
1419	    policyQualifArr = PORT_ArenaGrow (arena, policyQualifArr,
1420                                         sizeof (current) * count,
1421                                         sizeof (current) *(count + 1));
1422	}
1423        if (policyQualifArr == NULL) {
1424            GEN_BREAK (SECFailure);
1425        }
1426    
1427        policyQualifArr[count] = current;
1428        ++count;
1429
1430        if (!GetYesNo ("Enter another policy qualifier [y/N]")) {
1431            /* Add null to the end to mark end of data */
1432            policyQualifArr = PORT_ArenaGrow(arena, policyQualifArr,
1433                                              sizeof (current) * count,
1434                                              sizeof (current) *(count + 1));
1435            if (policyQualifArr == NULL) {
1436                GEN_BREAK (SECFailure);
1437            }
1438            policyQualifArr[count] = NULL;        
1439            break;
1440        }
1441
1442    } while (1);
1443
1444    if (rv != SECSuccess) {
1445        PORT_ArenaRelease (arena, mark);
1446        policyQualifArr = NULL;
1447    }
1448    return (policyQualifArr);
1449}
1450
1451static SECStatus 
1452AddCertPolicies(void *extHandle)
1453{
1454    CERTPolicyInfo **certPoliciesArr = NULL;
1455    CERTPolicyInfo *current;
1456    PRArenaPool *arena = NULL;
1457    SECStatus rv = SECSuccess;
1458    int count = 0;
1459    char buffer[512];
1460
1461    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1462    if ( !arena ) {
1463        SECU_PrintError(progName, "out of memory");
1464        return SECFailure;
1465    }
1466
1467    do {
1468        current = PORT_ArenaZNew(arena, CERTPolicyInfo);
1469        if (current == NULL) {
1470            GEN_BREAK(SECFailure);
1471        }
1472
1473        if (PrintChoicesAndGetAnswer("Enter a CertPolicy Object Identifier "
1474                                     "(dotted decimal format)\n"
1475				     "or \"any\" for AnyPolicy:",
1476                                     buffer, sizeof(buffer)) == SECFailure) {
1477            GEN_BREAK (SECFailure);
1478        }
1479	
1480	if (strncmp(buffer, "any", 3) == 0) {
1481	    /* use string version of X509_CERTIFICATE_POLICIES.anyPolicy */
1482	    strcpy(buffer, "OID.2.5.29.32.0");
1483	}
1484        rv = SEC_StringToOID(arena, &current->policyID, buffer, 0);
1485
1486        if (rv == SECFailure) {
1487            GEN_BREAK(SECFailure);
1488        }
1489        
1490        current->policyQualifiers = 
1491            RequestPolicyQualifiers(arena, &current->policyID); 
1492
1493        if (!certPoliciesArr) {
1494            certPoliciesArr = PORT_ArenaZNew(arena, CERTPolicyInfo *);
1495        } else {
1496	    certPoliciesArr = PORT_ArenaGrow(arena, certPoliciesArr,
1497                                         sizeof (current) * count,
1498                                         sizeof (current) *(count + 1));
1499	}
1500        if (certPoliciesArr == NULL) {
1501            GEN_BREAK (SECFailure);
1502        }
1503    
1504        certPoliciesArr[count] = current;
1505        ++count;
1506        
1507        if (!GetYesNo ("Enter another PolicyInformation field [y/N]?")) {
1508            /* Add null to the end to mark end of data */
1509            certPoliciesArr = PORT_ArenaGrow(arena, certPoliciesArr,
1510                                              sizeof (current) * count,
1511                                              sizeof (current) *(count + 1));
1512            if (certPoliciesArr == NULL) {
1513                GEN_BREAK (SECFailure);
1514            }
1515            certPoliciesArr[count] = NULL;        
1516            break;
1517        }
1518
1519    } while (1);
1520
1521    if (rv == SECSuccess) {
1522        CERTCertificatePolicies policies;
1523        PRBool yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
1524
1525        policies.arena = arena;
1526        policies.policyInfos = certPoliciesArr;
1527        
1528        rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, &policies,
1529		 yesNoAns, SEC_OID_X509_CERTIFICATE_POLICIES,
1530		 (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeCertPoliciesExtension);
1531    }
1532    if (arena)
1533	PORT_FreeArena(arena, PR_FALSE);
1534    return (rv);
1535}
1536
1537enum AuthInfoAccessTypesEnum {
1538    caIssuers = 1,
1539    ocsp = 2
1540};
1541
1542enum SubjInfoAccessTypesEnum {
1543    caRepository = 1,
1544    timeStamping = 2
1545};
1546    
1547/* Encode and add an AIA or SIA extension */
1548static SECStatus 
1549AddInfoAccess(void *extHandle, PRBool addSIAExt, PRBool isCACert)
1550{
1551    CERTAuthInfoAccess **infoAccArr = NULL;
1552    CERTAuthInfoAccess *current;
1553    PRArenaPool *arena = NULL;
1554    SECStatus rv = SECSuccess;
1555    int count = 0;
1556    char buffer[512];
1557    SECOidData *oid = NULL;
1558    int intValue = 0;
1559
1560    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1561    if ( !arena ) {
1562        SECU_PrintError(progName, "out of memory");
1563        return SECFailure;
1564    }
1565
1566    do {
1567        current = NULL;
1568        current = PORT_ArenaZNew(arena, CERTAuthInfoAccess);
1569        if (current == NULL) {
1570            GEN_BREAK(SECFailure);
1571        }
1572
1573        /* Get the accessMethod fields */
1574        if (addSIAExt) {
1575            if (isCACert) {
1576                puts("Adding \"CA Repository\" access method type for "
1577                    "Subject Information Access extension:\n");
1578                intValue = caRepository;
1579            } else {
1580                puts("Adding \"Time Stamping Services\" access method type for "
1581                    "Subject Information Access extension:\n");
1582                intValue = timeStamping;
1583            }
1584        } else {
1585            PrintChoicesAndGetAnswer("Enter access method type "
1586                "for Authority Information Access extension:\n"
1587                "\t1 - CA Issuers\n\t2 - OCSP\n\tAny"
1588                "other number to finish\n\tChoice",
1589                buffer, sizeof(buffer));
1590            intValue = PORT_Atoi(buffer);
1591        }
1592        if (addSIAExt) {
1593            switch (intValue) {
1594              case caRepository:
1595                  oid = SECOID_FindOIDByTag(SEC_OID_PKIX_CA_REPOSITORY);
1596                  break;
1597                  
1598              case timeStamping:
1599                  oid = SECOID_FindOIDByTag(SEC_OID_PKIX_TIMESTAMPING);
1600                  break;
1601            } 
1602        } else {
1603            switch (intValue) {
1604              case caIssuers:
1605                  oid = SECOID_FindOIDByTag(SEC_OID_PKIX_CA_ISSUERS);
1606                  break;
1607                  
1608              case ocsp:
1609                  oid = SECOID_FindOIDByTag(SEC_OID_PKIX_OCSP);
1610                  break;
1611            } 
1612        }
1613        if (oid == NULL ||
1614            SECITEM_CopyItem(arena, &current->method, &oid->oid) 
1615	    == SECFailure) {
1616            GEN_BRE

Large files files are truncated, but you can click here to view the full file