Blame SOURCES/certext.c

4418f4
/*
4418f4
   Copyright 2005 Red Hat, Inc.
4418f4
4418f4
   This program is free software; you can redistribute it and/or modify
4418f4
   it under the terms of the GNU General Public License as published by
4418f4
   the Free Software Foundation; either version 2 of the License, or
4418f4
   (at your option) any later version.
4418f4
  
4418f4
   This program is distributed in the hope that it will be useful,
4418f4
   but WITHOUT ANY WARRANTY; without even the implied warranty of
4418f4
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
4418f4
   GNU General Public License for more details.
4418f4
  
4418f4
   You should have received a copy of the GNU General Public License
4418f4
   along with this program; if not, write to the Free Software
4418f4
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
4418f4
   
4418f4
   In addition, as a special exception, Red Hat, Inc. gives permission
4418f4
   to link the code of this program with the OpenSSL library (or with
4418f4
   modified versions of OpenSSL that use the same license as OpenSSL),
4418f4
   and distribute linked combinations including the two. You must obey
4418f4
   the GNU General Public License in all respects for all of the code
4418f4
   used other than OpenSSL. If you modify this file, you may extend
4418f4
   this exception to your version of the file, but you are not
4418f4
   obligated to do so. If you do not wish to do so, delete this
4418f4
   exception statement from your version.
4418f4
4418f4
*/
4418f4
4418f4
/* ***** BEGIN LICENSE BLOCK *****
4418f4
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4418f4
 *
4418f4
 * The contents of this file are subject to the Mozilla Public License Version
4418f4
 * 1.1 (the "License"); you may not use this file except in compliance with
4418f4
 * the License. You may obtain a copy of the License at
4418f4
 * http://www.mozilla.org/MPL/
4418f4
 *
4418f4
 * Software distributed under the License is distributed on an "AS IS" basis,
4418f4
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
4418f4
 * for the specific language governing rights and limitations under the
4418f4
 * License.
4418f4
 *
4418f4
 * The Original Code is the Netscape security libraries.
4418f4
 *
4418f4
 * The Initial Developer of the Original Code is
4418f4
 * Netscape Communications Corporation.
4418f4
 * Portions created by the Initial Developer are Copyright (C) 1994-2000
4418f4
 * the Initial Developer. All Rights Reserved.
4418f4
 *
4418f4
 * Contributor(s):
4418f4
 *   Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
4418f4
 *
4418f4
 * Alternatively, the contents of this file may be used under the terms of
4418f4
 * either the GNU General Public License Version 2 or later (the "GPL"), or
4418f4
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
4418f4
 * in which case the provisions of the GPL or the LGPL are applicable instead
4418f4
 * of those above. If you wish to allow use of your version of this file only
4418f4
 * under the terms of either the GPL or the LGPL, and not to allow others to
4418f4
 * use your version of this file under the terms of the MPL, indicate your
4418f4
 * decision by deleting the provisions above and replace them with the notice
4418f4
 * and other provisions required by the GPL or the LGPL. If you do not delete
4418f4
 * the provisions above, a recipient may use your version of this file under
4418f4
 * the terms of any one of the MPL, the GPL or the LGPL.
4418f4
 *
4418f4
 * ***** END LICENSE BLOCK ***** */
4418f4
4418f4
/*
4418f4
** certext.c
4418f4
**
4418f4
** part of certutil for managing certificates extensions
4418f4
**
4418f4
*/
4418f4
#include <stdio.h>
4418f4
#include <string.h>
4418f4
#include <stdlib.h>
4418f4
4418f4
#include "secutil.h"
4418f4
4418f4
#include <unistd.h>
4418f4
4418f4
#include <cert.h>
4418f4
#include <prprf.h>
4418f4
#include <certt.h>
4418f4
4418f4
#include "keyutil.h"
4418f4
4418f4
#define GEN_BREAK(e) rv=e; break;
4418f4
4418f4
/* CERT_EncodeSubjectKeyID is a private function decleared in <xconst.h> */
4418f4
4418f4
/* Begin From NSS's xconst.c */
4418f4
static const SEC_ASN1Template CERTSubjectKeyIDTemplate[] = {
4418f4
    { SEC_ASN1_OCTET_STRING }
4418f4
};
4418f4
4418f4
SECStatus 
4418f4
CERT_EncodeSubjectKeyID(PRArenaPool *arena, const SECItem* srcString,
4418f4
                        SECItem *encodedValue)
4418f4
{
4418f4
    SECStatus rv = SECSuccess;
4418f4
4418f4
    if (!srcString) {
4418f4
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
4418f4
        return SECFailure;
4418f4
    }
4418f4
    if (SEC_ASN1EncodeItem (arena, encodedValue, srcString,
4418f4
                CERTSubjectKeyIDTemplate) == NULL) {
4418f4
        rv = SECFailure;
4418f4
    }
4418f4
    
4418f4
    return(rv);
4418f4
}
4418f4
/* End From xconst.c */
4418f4
4418f4
4418f4
/* From oidstring.c */
4418f4
/* if to->data is not NULL, and to->len is large enough to hold the result,
4418f4
 * then the resultant OID will be copyed into to->data, and to->len will be
4418f4
 * changed to show the actual OID length.
4418f4
 * Otherwise, memory for the OID will be allocated (from the caller's 
4418f4
 * PLArenaPool, if pool is non-NULL) and to->data will receive the address
4418f4
 * of the allocated data, and to->len will receive the OID length.
4418f4
 * The original value of to->data is not freed when a new buffer is allocated.
4418f4
 * 
4418f4
 * The input string may begin with "OID." and this still be ignored.
4418f4
 * The length of the input string is given in len.  If len == 0, then 
4418f4
 * len will be computed as strlen(from), meaning it must be NUL terminated.
4418f4
 * It is an error if from == NULL, or if *from == '\0'.
4418f4
 */
4418f4
4418f4
SECStatus
4418f4
SEC_StringToOID(PLArenaPool *pool, SECItem *to, const char *from, PRUint32 len)
4418f4
{
4418f4
    /*PRUint32 result_len = 0;*/
4418f4
    PRUint32 decimal_numbers = 0;
4418f4
    PRUint32 result_bytes = 0;
4418f4
    SECStatus rv;
4418f4
    PRUint8 result[1024];
4418f4
4418f4
    static const PRUint32 max_decimal = (0xffffffff / 10);
4418f4
    static const char OIDstring[] = {"OID."};
4418f4
4418f4
    if (!from || !to) {
4418f4
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
4418f4
    return SECFailure;
4418f4
    }
4418f4
    if (!len) {
4418f4
        len = PL_strlen(from);
4418f4
    }
4418f4
    if (len >= 4 && !PL_strncasecmp(from, OIDstring, 4)) {
4418f4
        from += 4; /* skip leading "OID." if present */
4418f4
        len  -= 4;
4418f4
    }
4418f4
    if (!len) {
4418f4
bad_data:
4418f4
        PORT_SetError(SEC_ERROR_BAD_DATA);
4418f4
        return SECFailure;
4418f4
    }
4418f4
    do {
4418f4
        PRUint32 decimal = 0;
4418f4
            while (len > 0 && isdigit(*from)) {
4418f4
            PRUint32 addend = (*from++ - '0');
4418f4
            --len;
4418f4
            if (decimal > max_decimal)  /* overflow */
4418f4
            goto bad_data;
4418f4
            decimal = (decimal * 10) + addend;
4418f4
            if (decimal < addend)   /* overflow */
4418f4
            goto bad_data;
4418f4
        }
4418f4
        if (len != 0 && *from != '.') {
4418f4
            goto bad_data;
4418f4
        }
4418f4
        if (decimal_numbers == 0) {
4418f4
            if (decimal > 2)
4418f4
                goto bad_data;
4418f4
            result[0] = decimal * 40;
4418f4
            result_bytes = 1;
4418f4
        } else if (decimal_numbers == 1) {
4418f4
            if (decimal > 40)
4418f4
                goto bad_data;
4418f4
            result[0] += decimal;
4418f4
        } else {
4418f4
            /* encode the decimal number,  */
4418f4
            PRUint8 * rp;
4418f4
            PRUint32 num_bytes = 0;
4418f4
            PRUint32 tmp = decimal;
4418f4
            while (tmp) {
4418f4
                num_bytes++;
4418f4
                tmp >>= 7;
4418f4
            }
4418f4
            if (!num_bytes )
4418f4
                ++num_bytes;  /* use one byte for a zero value */
4418f4
            if (num_bytes + result_bytes > sizeof result)
4418f4
                goto bad_data;
4418f4
            tmp = num_bytes;
4418f4
            rp = result + result_bytes - 1;
4418f4
            rp[tmp] = (PRUint8)(decimal & 0x7f);
4418f4
            decimal >>= 7;
4418f4
            while (--tmp > 0) {
4418f4
                rp[tmp] = (PRUint8)(decimal | 0x80);
4418f4
                decimal >>= 7;
4418f4
            }
4418f4
            result_bytes += num_bytes;
4418f4
        }
4418f4
        ++decimal_numbers;
4418f4
        if (len > 0) { /* skip trailing '.' */
4418f4
            ++from;
4418f4
            --len;
4418f4
        }
4418f4
    } while (len > 0);
4418f4
    /* now result contains result_bytes of data */
4418f4
    if (to->data && to->len >= result_bytes) {
4418f4
        PORT_Memcpy(to->data, result, to->len = result_bytes);
4418f4
        rv = SECSuccess;
4418f4
    } else {
4418f4
        SECItem result_item = {siBuffer, NULL, 0 };
4418f4
        result_item.data = result;
4418f4
        result_item.len  = result_bytes;
4418f4
        rv = SECITEM_CopyItem(pool, to, &result_item);
4418f4
    }
4418f4
    return rv;
4418f4
}
4418f4
4418f4
static char *
4418f4
Gets_s(char *buff, size_t size) {
4418f4
    char *str;
4418f4
    
4418f4
    if (buff == NULL || size < 1) {
4418f4
        PORT_Assert(0);
4418f4
        return NULL;
4418f4
    }
4418f4
    if ((str = fgets(buff, size, stdin)) != NULL) {
4418f4
        int len = PORT_Strlen(str);
4418f4
        /*
4418f4
         * fgets() automatically converts native text file
4418f4
         * line endings to '\n'.  As defensive programming
4418f4
         * (just in case fgets has a bug or we put stdin in
4418f4
         * binary mode by mistake), we handle three native 
4418f4
         * text file line endings here:
4418f4
         *   '\n'      Unix (including Linux and Mac OS X)
4418f4
         *   '\r''\n'  DOS/Windows & OS/2
4418f4
         *   '\r'      Mac OS Classic
4418f4
         * len can not be less then 1, since in case with
4418f4
         * empty string it has at least '\n' in the buffer
4418f4
         */
4418f4
        if (buff[len - 1] == '\n' || buff[len - 1] == '\r') {
4418f4
            buff[len - 1] = '\0';
4418f4
            if (len > 1 && buff[len - 2] == '\r')
4418f4
                buff[len - 2] = '\0';
4418f4
        }
4418f4
    } else {
4418f4
        buff[0] = '\0';
4418f4
    }
4418f4
    return str;
4418f4
}
4418f4
4418f4
4418f4
static SECStatus
4418f4
PrintChoicesAndGetAnswer(char* str, char* rBuff, int rSize)
4418f4
{
4418f4
    fprintf(stdout, str);
4418f4
    fprintf(stdout, " > ");
4418f4
    fflush (stdout);
4418f4
    if (Gets_s(rBuff, rSize) == NULL) {
4418f4
        PORT_SetError(SEC_ERROR_INPUT_LEN);
4418f4
        return SECFailure;
4418f4
    }
4418f4
    return SECSuccess;
4418f4
}
4418f4
4418f4
static CERTGeneralName *
4418f4
GetGeneralName (PRArenaPool *arena)
4418f4
{
4418f4
    CERTGeneralName *namesList = NULL;
4418f4
    CERTGeneralName *current;
4418f4
    CERTGeneralName *tail = NULL;
4418f4
    SECStatus rv = SECSuccess;
4418f4
    int intValue;
4418f4
    char buffer[512];
4418f4
    void *mark;
4418f4
4418f4
    PORT_Assert (arena);
4418f4
    mark = PORT_ArenaMark (arena);
4418f4
    do {
4418f4
        if (PrintChoicesAndGetAnswer(
4418f4
        "\nSelect one of the following general name type: \n"
4418f4
        "\t2 - rfc822Name\n"
4418f4
        "\t3 - dnsName\n"
4418f4
        "\t5 - directoryName\n"
4418f4
        "\t7 - uniformResourceidentifier\n"
4418f4
        "\t8 - ipAddress\n"
4418f4
        "\t9 - registerID\n"
4418f4
        "\tAny other number to finish\n"
4418f4
        "\t\tChoice:", buffer, sizeof(buffer)) == SECFailure) {
4418f4
            GEN_BREAK (SECFailure);
4418f4
        }
4418f4
        intValue = PORT_Atoi (buffer);
4418f4
        /*
4418f4
         * Should use ZAlloc instead of Alloc to avoid problem with garbage
4418f4
         * initialized pointers in CERT_CopyName
4418f4
         */
4418f4
        switch (intValue) {
4418f4
        case certRFC822Name:
4418f4
        case certDNSName:
4418f4
        case certDirectoryName:
4418f4
        case certURI:
4418f4
        case certIPAddress:
4418f4
        case certRegisterID:
4418f4
        break;
4418f4
        default:
4418f4
        intValue = 0;   /* force a break for anything else */
4418f4
        }
4418f4
4418f4
        if (intValue == 0)
4418f4
            break;
4418f4
    
4418f4
        if (namesList == NULL) {
4418f4
            namesList = current = tail =
4418f4
            PORT_ArenaZNew(arena, CERTGeneralName);
4418f4
        } else {
4418f4
            current = PORT_ArenaZNew(arena, CERTGeneralName);
4418f4
        }
4418f4
        if (current == NULL) {
4418f4
            GEN_BREAK (SECFailure);
4418f4
        }
4418f4
4418f4
        current->type = intValue;
4418f4
        puts ("\nEnter data:");
4418f4
        fflush (stdout);
4418f4
        if (Gets_s (buffer, sizeof(buffer)) == NULL) {
4418f4
            PORT_SetError(SEC_ERROR_INPUT_LEN);
4418f4
            GEN_BREAK (SECFailure);
4418f4
        }
4418f4
        switch (current->type) {
4418f4
        case certURI:
4418f4
        case certDNSName:
4418f4
        case certRFC822Name:
4418f4
            current->name.other.data =
4418f4
                PORT_ArenaAlloc (arena, strlen (buffer));
4418f4
            if (current->name.other.data == NULL) {
4418f4
                GEN_BREAK (SECFailure);
4418f4
            }
4418f4
            PORT_Memcpy(current->name.other.data, buffer,
4418f4
                        current->name.other.len = strlen(buffer));
4418f4
            break;
4418f4
4418f4
        case certEDIPartyName:
4418f4
        case certIPAddress:
4418f4
        case certOtherName:
4418f4
        case certRegisterID:
4418f4
        case certX400Address: {
4418f4
4418f4
            current->name.other.data =
4418f4
                PORT_ArenaAlloc (arena, strlen (buffer) + 2);
4418f4
            if (current->name.other.data == NULL) {
4418f4
                GEN_BREAK (SECFailure);
4418f4
            }
4418f4
            
4418f4
            PORT_Memcpy (current->name.other.data + 2, buffer,
4418f4
                         strlen (buffer));
4418f4
            /* This may not be accurate for all cases.  For now,
4418f4
             * use this tag type */
4418f4
            current->name.other.data[0] =
4418f4
                (char)(((current->type - 1) & 0x1f)| 0x80);
4418f4
            current->name.other.data[1] = (char)strlen (buffer);
4418f4
            current->name.other.len = strlen (buffer) + 2;
4418f4
            break;
4418f4
        }
4418f4
4418f4
        case certDirectoryName: {
4418f4
                CERTName *directoryName = NULL;
4418f4
                
4418f4
                directoryName = CERT_AsciiToName (buffer);
4418f4
                if (!directoryName) {
4418f4
                    fprintf(stderr, "certutil: improperly formatted name: "
4418f4
                            "\"%s\"\n", buffer);
4418f4
                    break;
4418f4
                }
4418f4
                
4418f4
                rv = CERT_CopyName (arena, &current->name.directoryName,
4418f4
                                    directoryName);
4418f4
                CERT_DestroyName (directoryName);
4418f4
                
4418f4
                break;
4418f4
            }
4418f4
        }
4418f4
        if (rv != SECSuccess)
4418f4
            break;
4418f4
        current->l.next = &(namesList->l);
4418f4
        current->l.prev = &(tail->l);
4418f4
        tail->l.next = &(current->l);
4418f4
        tail = current;
4418f4
        
4418f4
    } while (1);
4418f4
4418f4
    if (rv != SECSuccess) {
4418f4
        PORT_ArenaRelease (arena, mark);
4418f4
        namesList = NULL;
4418f4
    }
4418f4
    return (namesList);
4418f4
}
4418f4
4418f4
static SECStatus 
4418f4
GetString(PRArenaPool *arena, char *prompt, SECItem *value)
4418f4
{
4418f4
    char buffer[251];
4418f4
    char *buffPrt;
4418f4
4418f4
    buffer[0] = '\0';
4418f4
    value->data = NULL;
4418f4
    value->len = 0;
4418f4
    
4418f4
    puts (prompt);
4418f4
    buffPrt = Gets_s (buffer, sizeof(buffer));
4418f4
    /* returned NULL here treated the same way as empty string */
4418f4
    if (buffPrt && strlen (buffer) > 0) {
4418f4
        value->data = PORT_ArenaAlloc (arena, strlen (buffer));
4418f4
        if (value->data == NULL) {
4418f4
            PORT_SetError (SEC_ERROR_NO_MEMORY);
4418f4
            return (SECFailure);
4418f4
        }
4418f4
        PORT_Memcpy (value->data, buffer, value->len = strlen(buffer));
4418f4
    }
4418f4
    return (SECSuccess);
4418f4
}
4418f4
4418f4
static PRBool 
4418f4
GetYesNo(char *prompt) 
4418f4
{
4418f4
    char buf[3];
4418f4
    char *buffPrt;
4418f4
4418f4
    buf[0] = 'n';
4418f4
    puts(prompt);
4418f4
    buffPrt = Gets_s(buf, sizeof(buf));
4418f4
    return (buffPrt && (buf[0] == 'y' || buf[0] == 'Y')) ? PR_TRUE : PR_FALSE;
4418f4
}
4418f4
4418f4
static SECStatus 
4418f4
AddKeyUsage (void *extHandle)
4418f4
{
4418f4
    SECItem bitStringValue;
4418f4
    unsigned char keyUsage = 0x0;
4418f4
    char buffer[5];
4418f4
    int value;
4418f4
    PRBool yesNoAns;
4418f4
4418f4
    while (1) {
4418f4
        if (PrintChoicesAndGetAnswer(
4418f4
                "\t\t0 - Digital Signature\n"
4418f4
                "\t\t1 - Non-repudiation\n"
4418f4
                "\t\t2 - Key encipherment\n"
4418f4
                "\t\t3 - Data encipherment\n"   
4418f4
                "\t\t4 - Key agreement\n"
4418f4
                "\t\t5 - Cert signing key\n"   
4418f4
                "\t\t6 - CRL signing key\n"
4418f4
                "\t\tOther to finish\n",
4418f4
                buffer, sizeof(buffer)) == SECFailure) {
4418f4
            return SECFailure;
4418f4
        }
4418f4
        value = PORT_Atoi (buffer);
4418f4
        if (value < 0 || value > 6)
4418f4
            break;
4418f4
        if (value == 0) {
4418f4
            /* Checking that zero value of variable 'value'
4418f4
             * corresponds to '0' input made by user */
4418f4
            char *chPtr = strchr(buffer, '0');
4418f4
            if (chPtr == NULL) {
4418f4
                continue;
4418f4
            }
4418f4
        }
4418f4
        keyUsage |= (0x80 >> value);
4418f4
    }
4418f4
4418f4
    bitStringValue.data = &keyUsage;
4418f4
    bitStringValue.len = 1;
4418f4
    yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
4418f4
4418f4
    return (CERT_EncodeAndAddBitStrExtension
4418f4
            (extHandle, SEC_OID_X509_KEY_USAGE, &bitStringValue,
4418f4
             yesNoAns));
4418f4
4418f4
}
4418f4
4418f4
4418f4
static CERTOidSequence *
4418f4
CreateOidSequence(void)
4418f4
{
4418f4
    CERTOidSequence *rv = (CERTOidSequence *)NULL;
4418f4
    PRArenaPool *arena = (PRArenaPool *)NULL;
4418f4
4418f4
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
4418f4
    if( (PRArenaPool *)NULL == arena ) {
4418f4
        goto loser;
4418f4
    }
4418f4
4418f4
    rv = (CERTOidSequence *)PORT_ArenaZNew(arena, CERTOidSequence);
4418f4
    if( (CERTOidSequence *)NULL == rv ) {
4418f4
        goto loser;
4418f4
    }
4418f4
4418f4
    rv->oids = (SECItem **)PORT_ArenaZNew(arena, SECItem *);
4418f4
    if( (SECItem **)NULL == rv->oids ) {
4418f4
        goto loser;
4418f4
    }
4418f4
4418f4
    rv->arena = arena;
4418f4
    return rv;
4418f4
4418f4
loser:
4418f4
    if( (PRArenaPool *)NULL != arena ) {
4418f4
        PORT_FreeArena(arena, PR_FALSE);
4418f4
    }
4418f4
4418f4
    return (CERTOidSequence *)NULL;
4418f4
}
4418f4
4418f4
static void
4418f4
DestroyOidSequence(CERTOidSequence *os)
4418f4
{
4418f4
    if (os->arena) {
4418f4
        PORT_FreeArena(os->arena, PR_FALSE);
4418f4
    }
4418f4
}
4418f4
4418f4
static SECStatus
4418f4
AddOidToSequence(CERTOidSequence *os, SECOidTag oidTag)
4418f4
{
4418f4
    SECItem **oids;
4418f4
    PRUint32 count = 0;
4418f4
    SECOidData *od;
4418f4
4418f4
    od = SECOID_FindOIDByTag(oidTag);
4418f4
    if( (SECOidData *)NULL == od ) {
4418f4
        return SECFailure;
4418f4
    }
4418f4
4418f4
    for( oids = os->oids; (SECItem *)NULL != *oids; oids++ ) {
4418f4
        count++;
4418f4
    }
4418f4
4418f4
    /* ArenaZRealloc */
4418f4
4418f4
    {
4418f4
        PRUint32 i;
4418f4
4418f4
        oids = (SECItem **)PORT_ArenaZNewArray(os->arena, SECItem *, count + 2);
4418f4
        if( (SECItem **)NULL == oids ) {
4418f4
            return SECFailure;
4418f4
        }
4418f4
    
4418f4
        for( i = 0; i < count; i++ ) {
4418f4
            oids[i] = os->oids[i];
4418f4
        }
4418f4
4418f4
        /* ArenaZFree(os->oids); */
4418f4
    }
4418f4
4418f4
    os->oids = oids;
4418f4
    os->oids[count] = &od->oid;
4418f4
4418f4
    return SECSuccess;
4418f4
}
4418f4
4418f4
SEC_ASN1_MKSUB(SEC_ObjectIDTemplate)
4418f4
4418f4
const SEC_ASN1Template CERT_OidSeqTemplate[] = {
4418f4
    { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN, offsetof(CERTOidSequence, oids),
4418f4
      SEC_ASN1_SUB(SEC_ObjectIDTemplate) }
4418f4
};
4418f4
4418f4
4418f4
static SECItem *
4418f4
EncodeOidSequence(CERTOidSequence *os)
4418f4
{
4418f4
    SECItem *rv;
4418f4
4418f4
    rv = (SECItem *)PORT_ArenaZNew(os->arena, SECItem);
4418f4
    if( (SECItem *)NULL == rv ) {
4418f4
        goto loser;
4418f4
    }
4418f4
4418f4
    if( !SEC_ASN1EncodeItem(os->arena, rv, os, CERT_OidSeqTemplate) ) {
4418f4
        goto loser;
4418f4
    }
4418f4
4418f4
    return rv;
4418f4
4418f4
loser:
4418f4
    return (SECItem *)NULL;
4418f4
}
4418f4
4418f4
static SECStatus 
4418f4
AddExtKeyUsage (void *extHandle)
4418f4
{
4418f4
    char buffer[5];
4418f4
    int value;
4418f4
    CERTOidSequence *os;
4418f4
    SECStatus rv;
4418f4
    SECItem *item;
4418f4
    PRBool yesNoAns;
4418f4
4418f4
    os = CreateOidSequence();
4418f4
    if( (CERTOidSequence *)NULL == os ) {
4418f4
        return SECFailure;
4418f4
    }
4418f4
4418f4
    while (1) {
4418f4
        if (PrintChoicesAndGetAnswer(
4418f4
                "\t\t0 - Server Auth\n"
4418f4
                "\t\t1 - Client Auth\n"
4418f4
                "\t\t2 - Code Signing\n"
4418f4
                "\t\t3 - Email Protection\n"
4418f4
                "\t\t4 - Timestamp\n"
4418f4
                "\t\t5 - OCSP Responder\n"
4418f4
                "\t\t6 - Step-up\n"
4418f4
                "\t\tOther to finish\n",
4418f4
                buffer, sizeof(buffer)) == SECFailure) {
4418f4
            GEN_BREAK(SECFailure);
4418f4
        }
4418f4
        value = PORT_Atoi(buffer);
4418f4
4418f4
        if (value == 0) {
4418f4
            /* Checking that zero value of variable 'value'
4418f4
             * corresponds to '0' input made by user */
4418f4
            char *chPtr = strchr(buffer, '0');
4418f4
            if (chPtr == NULL) {
4418f4
                continue;
4418f4
            }
4418f4
        }
4418f4
4418f4
        switch( value ) {
4418f4
        case 0:
4418f4
            rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_SERVER_AUTH);
4418f4
            break;
4418f4
        case 1:
4418f4
            rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH);
4418f4
            break;
4418f4
        case 2:
4418f4
            rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_CODE_SIGN);
4418f4
            break;
4418f4
        case 3:
4418f4
            rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT);
4418f4
            break;
4418f4
        case 4:
4418f4
            rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_TIME_STAMP);
4418f4
            break;
4418f4
        case 5:
4418f4
            rv = AddOidToSequence(os, SEC_OID_OCSP_RESPONDER);
4418f4
            break;
4418f4
        case 6:
4418f4
            rv = AddOidToSequence(os, SEC_OID_NS_KEY_USAGE_GOVT_APPROVED);
4418f4
            break;
4418f4
        default:
4418f4
            goto endloop;
4418f4
        }
4418f4
4418f4
        if( SECSuccess != rv ) goto loser;
4418f4
    }
4418f4
4418f4
endloop:
4418f4
    item = EncodeOidSequence(os);
4418f4
4418f4
    yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
4418f4
4418f4
    rv = CERT_AddExtension(extHandle, SEC_OID_X509_EXT_KEY_USAGE, item,
4418f4
                           yesNoAns, PR_TRUE);
4418f4
    /*FALLTHROUGH*/
4418f4
loser:
4418f4
    DestroyOidSequence(os);
4418f4
    return rv;
4418f4
}
4418f4
4418f4
static SECStatus 
4418f4
AddNscpCertType (void *extHandle)
4418f4
{
4418f4
    SECItem bitStringValue;
4418f4
    unsigned char keyUsage = 0x0;
4418f4
    char buffer[5];
4418f4
    int value;
4418f4
    PRBool yesNoAns;
4418f4
4418f4
    while (1) {
4418f4
        if (PrintChoicesAndGetAnswer(
4418f4
                "\t\t0 - SSL Client\n"
4418f4
                "\t\t1 - SSL Server\n"
4418f4
                "\t\t2 - S/MIME\n"
4418f4
                "\t\t3 - Object Signing\n"   
4418f4
                "\t\t4 - Reserved for future use\n"
4418f4
                "\t\t5 - SSL CA\n"   
4418f4
                "\t\t6 - S/MIME CA\n"
4418f4
                "\t\t7 - Object Signing CA\n"
4418f4
                "\t\tOther to finish\n",
4418f4
                buffer, sizeof(buffer)) == SECFailure) {
4418f4
            return SECFailure;
4418f4
        }
4418f4
        value = PORT_Atoi (buffer);
4418f4
        if (value < 0 || value > 7)
4418f4
            break;
4418f4
        if (value == 0) {
4418f4
            /* Checking that zero value of variable 'value'
4418f4
             * corresponds to '0' input made by user */
4418f4
            char *chPtr = strchr(buffer, '0');
4418f4
            if (chPtr == NULL) {
4418f4
                continue;
4418f4
            }
4418f4
        }
4418f4
        keyUsage |= (0x80 >> value);
4418f4
    }
4418f4
4418f4
    bitStringValue.data = &keyUsage;
4418f4
    bitStringValue.len = 1;
4418f4
    yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
4418f4
4418f4
    return (CERT_EncodeAndAddBitStrExtension
4418f4
            (extHandle, SEC_OID_NS_CERT_EXT_CERT_TYPE, &bitStringValue,
4418f4
             yesNoAns));
4418f4
4418f4
}
4418f4
4418f4
static SECStatus 
4418f4
AddSubjectAltNames(PRArenaPool *arena, CERTGeneralName **existingListp,
4418f4
                   const char *names, CERTGeneralNameType type)
4418f4
{
4418f4
    CERTGeneralName *nameList = NULL;
4418f4
    CERTGeneralName *current = NULL;
4418f4
    PRCList *prev = NULL;
4418f4
    const char *cp;
4418f4
    char *tbuf;
4418f4
    SECStatus rv = SECSuccess;
4418f4
4418f4
4418f4
    /*
4418f4
     * walk down the comma separated list of names. NOTE: there is
4418f4
     * no sanity checks to see if the email address look like
4418f4
     * email addresses.
4418f4
     */
4418f4
    for (cp=names; cp; cp = PORT_Strchr(cp,',')) {
4418f4
        int len;
4418f4
        char *end;
4418f4
4418f4
        if (*cp == ',') {
4418f4
            cp++;
4418f4
        }
4418f4
        end = PORT_Strchr(cp,',');
4418f4
        len = end ? end-cp : PORT_Strlen(cp);
4418f4
        if (len <= 0) {
4418f4
            continue;
4418f4
        }
4418f4
        tbuf = PORT_ArenaAlloc(arena,len+1);
4418f4
        PORT_Memcpy(tbuf,cp,len);
4418f4
        tbuf[len] = 0;
4418f4
        current = (CERTGeneralName *) PORT_ZAlloc(sizeof(CERTGeneralName));
4418f4
        if (!current) {
4418f4
            rv = SECFailure;
4418f4
            break;
4418f4
        }
4418f4
        if (prev) {
4418f4
            current->l.prev = prev;
4418f4
            prev->next = &(current->l);
4418f4
        } else {
4418f4
            nameList = current;
4418f4
        }
4418f4
        current->type = type;
4418f4
        current->name.other.data = (unsigned char *)tbuf;
4418f4
        current->name.other.len = PORT_Strlen(tbuf);
4418f4
        prev = &(current->l);
4418f4
    }
4418f4
    /* at this point nameList points to the head of a doubly linked,
4418f4
     * but not yet circular, list and current points to its tail. */
4418f4
    if (rv == SECSuccess && nameList) {
4418f4
        if (*existingListp != NULL) {
4418f4
            PRCList *existingprev;
4418f4
            /* add nameList to the end of the existing list */
4418f4
            existingprev = (*existingListp)->l.prev;
4418f4
            (*existingListp)->l.prev = &(current->l);
4418f4
            nameList->l.prev = existingprev;
4418f4
            existingprev->next = &(nameList->l);
4418f4
            current->l.next = &((*existingListp)->l);
4418f4
        }
4418f4
        else {
4418f4
            /* make nameList circular and set it as the new existingList */
4418f4
            nameList->l.prev = prev;
4418f4
            current->l.next = &(nameList->l);
4418f4
            *existingListp = nameList;
4418f4
        }
4418f4
    }
4418f4
    return rv;
4418f4
}
4418f4
4418f4
static SECStatus 
4418f4
AddEmailSubjectAlt(PRArenaPool *arena, CERTGeneralName **existingListp,
4418f4
                   const char *emailAddrs)
4418f4
{
4418f4
    return AddSubjectAltNames(arena, existingListp, emailAddrs, 
4418f4
                              certRFC822Name);
4418f4
}
4418f4
4418f4
static SECStatus 
4418f4
AddDNSSubjectAlt(PRArenaPool *arena, CERTGeneralName **existingListp,
4418f4
                 const char *dnsNames)
4418f4
{
4418f4
    return AddSubjectAltNames(arena, existingListp, dnsNames, certDNSName);
4418f4
}
4418f4
4418f4
4418f4
static SECStatus 
4418f4
AddBasicConstraint(void *extHandle)
4418f4
{
4418f4
    CERTBasicConstraints basicConstraint;    
4418f4
    SECStatus rv;
4418f4
    char buffer[10];
4418f4
    PRBool yesNoAns;
4418f4
4418f4
    do {
4418f4
        basicConstraint.pathLenConstraint = CERT_UNLIMITED_PATH_CONSTRAINT;
4418f4
        basicConstraint.isCA = GetYesNo ("Is this a CA certificate [y/N]?");
4418f4
4418f4
        buffer[0] = '\0';
4418f4
        if (PrintChoicesAndGetAnswer("Enter the path length constraint, "
4418f4
                                     "enter to skip [<0 for unlimited path]:",
4418f4
                                     buffer, sizeof(buffer)) == SECFailure) {
4418f4
            GEN_BREAK(SECFailure);
4418f4
        }
4418f4
        if (PORT_Strlen (buffer) > 0)
4418f4
            basicConstraint.pathLenConstraint = PORT_Atoi (buffer);
4418f4
4418f4
        yesNoAns = GetYesNo ("Is this a critical extension [y/N]?");
4418f4
4418f4
        rv = SECU_EncodeAndAddExtensionValue(NULL, extHandle,
4418f4
         &basicConstraint, yesNoAns, SEC_OID_X509_BASIC_CONSTRAINTS,
4418f4
         (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeBasicConstraintValue);
4418f4
    } while (0);
4418f4
4418f4
    return (rv);
4418f4
}
4418f4
4418f4
static SECStatus 
4418f4
AddAuthKeyID (void *extHandle)
4418f4
{
4418f4
    CERTAuthKeyID *authKeyID = NULL;    
4418f4
    PRArenaPool *arena = NULL;
4418f4
    SECStatus rv = SECSuccess;
4418f4
    PRBool yesNoAns;
4418f4
4418f4
    do {
4418f4
        arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
4418f4
        if ( !arena ) {
4418f4
            SECU_PrintError(progName, "out of memory");
4418f4
            GEN_BREAK (SECFailure);
4418f4
        }
4418f4
4418f4
        if (GetYesNo ("Enter value for the authKeyID extension [y/N]?") == 0)
4418f4
            break;
4418f4
4418f4
        authKeyID = PORT_ArenaZNew(arena, CERTAuthKeyID);
4418f4
        if (authKeyID == NULL) {
4418f4
            GEN_BREAK (SECFailure);
4418f4
        }
4418f4
4418f4
        rv = GetString (arena, "Enter value for the key identifier fields,"
4418f4
                        "enter to omit:", &authKeyID->keyID);
4418f4
        if (rv != SECSuccess)
4418f4
            break;
4418f4
4418f4
        SECU_SECItemHexStringToBinary(&authKeyID->keyID);
4418f4
4418f4
        authKeyID->authCertIssuer = GetGeneralName (arena);
4418f4
        if (authKeyID->authCertIssuer == NULL && 
4418f4
            SECFailure == PORT_GetError ())
4418f4
            break;
4418f4
4418f4
4418f4
        rv = GetString (arena, "Enter value for the authCertSerial field, "
4418f4
                        "enter to omit:", &authKeyID->authCertSerialNumber);
4418f4
4418f4
        yesNoAns = GetYesNo ("Is this a critical extension [y/N]?");
4418f4
4418f4
        rv = SECU_EncodeAndAddExtensionValue(arena, extHandle,
4418f4
             authKeyID, yesNoAns, SEC_OID_X509_AUTH_KEY_ID, 
4418f4
             (EXTEN_EXT_VALUE_ENCODER) CERT_EncodeAuthKeyID);
4418f4
        if (rv)
4418f4
            break;
4418f4
4418f4
    } while (0);
4418f4
    if (arena)
4418f4
        PORT_FreeArena (arena, PR_FALSE);
4418f4
    return (rv);
4418f4
}   
4418f4
    
4418f4
static SECStatus 
4418f4
AddSubjKeyID (void *extHandle)
4418f4
{
4418f4
    SECItem keyID;
4418f4
    PRArenaPool *arena = NULL;
4418f4
    SECStatus rv = SECSuccess;
4418f4
    PRBool yesNoAns;
4418f4
4418f4
    do {
4418f4
        arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
4418f4
        if ( !arena ) {
4418f4
            SECU_PrintError(progName, "out of memory");
4418f4
            GEN_BREAK (SECFailure);
4418f4
        }
4418f4
        printf("Adding Subject Key ID extension.\n");
4418f4
4418f4
        rv = GetString (arena, "Enter value for the key identifier fields,"
4418f4
                        "enter to omit:", &keyID);
4418f4
        if (rv != SECSuccess)
4418f4
            break;
4418f4
4418f4
        SECU_SECItemHexStringToBinary(&keyID);
4418f4
4418f4
        yesNoAns = GetYesNo ("Is this a critical extension [y/N]?");
4418f4
4418f4
        rv = SECU_EncodeAndAddExtensionValue(arena, extHandle,
4418f4
             &keyID, yesNoAns, SEC_OID_X509_SUBJECT_KEY_ID, 
4418f4
             (EXTEN_EXT_VALUE_ENCODER) CERT_EncodeSubjectKeyID);
4418f4
        if (rv)
4418f4
            break;
4418f4
4418f4
    } while (0);
4418f4
    if (arena)
4418f4
        PORT_FreeArena (arena, PR_FALSE);
4418f4
    return (rv);
4418f4
}   
4418f4
4418f4
static SECStatus 
4418f4
AddCrlDistPoint(void *extHandle)
4418f4
{
4418f4
    PRArenaPool *arena = NULL;
4418f4
    CERTCrlDistributionPoints *crlDistPoints = NULL;
4418f4
    CRLDistributionPoint *current;
4418f4
    SECStatus rv = SECSuccess;
4418f4
    int count = 0, intValue;
4418f4
    char buffer[512];
4418f4
4418f4
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
4418f4
    if ( !arena )
4418f4
        return (SECFailure);
4418f4
4418f4
    do {
4418f4
        current = NULL;
4418f4
4418f4
        current = PORT_ArenaZNew(arena, CRLDistributionPoint);
4418f4
        if (current == NULL) {
4418f4
            GEN_BREAK (SECFailure);
4418f4
        }   
4418f4
4418f4
        /* Get the distributionPointName fields - this field is optional */
4418f4
        if (PrintChoicesAndGetAnswer(
4418f4
                "Enter the type of the distribution point name:\n"
4418f4
                "\t1 - Full Name\n\t2 - Relative Name\n\tAny other "
4418f4
                "number to finish\n\t\tChoice: ",
4418f4
                buffer, sizeof(buffer)) == SECFailure) {
4418f4
        GEN_BREAK (SECFailure);
4418f4
    }
4418f4
        intValue = PORT_Atoi (buffer);
4418f4
        switch (intValue) {
4418f4
        case generalName:
4418f4
            current->distPointType = intValue;
4418f4
            current->distPoint.fullName = GetGeneralName (arena);
4418f4
            rv = PORT_GetError();
4418f4
            break;
4418f4
4418f4
        case relativeDistinguishedName: {
4418f4
            CERTName *name;
4418f4
4418f4
            current->distPointType = intValue;
4418f4
            puts ("Enter the relative name: ");
4418f4
            fflush (stdout);
4418f4
            if (Gets_s (buffer, sizeof(buffer)) == NULL) {
4418f4
                GEN_BREAK (SECFailure);
4418f4
            }
4418f4
            /* For simplicity, use CERT_AsciiToName to converse from a string
4418f4
               to NAME, but we only interest in the first RDN */
4418f4
            name = CERT_AsciiToName (buffer);
4418f4
            if (!name) {
4418f4
                GEN_BREAK (SECFailure);
4418f4
            }
4418f4
            rv = CERT_CopyRDN (arena, &current->distPoint.relativeName,
4418f4
                               name->rdns[0]);
4418f4
            CERT_DestroyName (name);
4418f4
            break;
4418f4
          }
4418f4
        }
4418f4
        if (rv != SECSuccess)
4418f4
            break;
4418f4
4418f4
        /* Get the reason flags */
4418f4
        if (PrintChoicesAndGetAnswer(
4418f4
                "\nSelect one of the following for the reason flags\n"
4418f4
                "\t0 - unused\n\t1 - keyCompromise\n"
4418f4
                "\t2 - caCompromise\n\t3 - affiliationChanged\n"
4418f4
                "\t4 - superseded\n\t5 - cessationOfOperation\n"
4418f4
                "\t6 - certificateHold\n"
4418f4
                "\tAny other number to finish\t\tChoice: ",
4418f4
                buffer, sizeof(buffer)) == SECFailure) {
4418f4
            GEN_BREAK(SECFailure);
4418f4
        }
4418f4
        intValue = PORT_Atoi (buffer);
4418f4
        if (intValue == 0) {
4418f4
            /* Checking that zero value of variable 'value'
4418f4
             * corresponds to '0' input made by user */
4418f4
            char *chPtr = strchr(buffer, '0');
4418f4
            if (chPtr == NULL) {
4418f4
                intValue = -1;
4418f4
            }
4418f4
        }
4418f4
        if (intValue >= 0 && intValue <8) {
4418f4
            current->reasons.data = PORT_ArenaAlloc (arena, sizeof(char));
4418f4
            if (current->reasons.data == NULL) {
4418f4
                GEN_BREAK (SECFailure);
4418f4
            }
4418f4
            *current->reasons.data = (char)(0x80 >> intValue);
4418f4
            current->reasons.len = 1;
4418f4
        }
4418f4
        puts ("Enter value for the CRL Issuer name:\n");
4418f4
        current->crlIssuer = GetGeneralName (arena);
4418f4
        if (current->crlIssuer == NULL && (rv = PORT_GetError()) == SECFailure)
4418f4
            break;
4418f4
4418f4
        if (crlDistPoints == NULL) {
4418f4
            crlDistPoints = PORT_ArenaZNew(arena, CERTCrlDistributionPoints);
4418f4
            if (crlDistPoints == NULL) {
4418f4
                GEN_BREAK (SECFailure);
4418f4
            }
4418f4
        }
4418f4
4418f4
        crlDistPoints->distPoints =
4418f4
            PORT_ArenaGrow (arena, crlDistPoints->distPoints,
4418f4
                            sizeof (*crlDistPoints->distPoints) * count,
4418f4
                            sizeof (*crlDistPoints->distPoints) *(count + 1));
4418f4
        if (crlDistPoints->distPoints == NULL) {
4418f4
            GEN_BREAK (SECFailure);
4418f4
        }
4418f4
4418f4
        crlDistPoints->distPoints[count] = current;
4418f4
        ++count;
4418f4
        if (GetYesNo("Enter another value for the CRLDistributionPoint "
4418f4
                      "extension [y/N]?") == 0) {
4418f4
            /* Add null to the end to mark end of data */
4418f4
            crlDistPoints->distPoints =
4418f4
                PORT_ArenaGrow(arena, crlDistPoints->distPoints,
4418f4
               sizeof (*crlDistPoints->distPoints) * count,
4418f4
               sizeof (*crlDistPoints->distPoints) *(count + 1));
4418f4
            crlDistPoints->distPoints[count] = NULL;    
4418f4
            break;
4418f4
        }
4418f4
4418f4
4418f4
    } while (1);
4418f4
    
4418f4
    if (rv == SECSuccess) {
4418f4
        PRBool yesNoAns = GetYesNo ("Is this a critical extension [y/N]?");
4418f4
4418f4
        rv = SECU_EncodeAndAddExtensionValue(arena, extHandle,
4418f4
         crlDistPoints, yesNoAns, SEC_OID_X509_CRL_DIST_POINTS,
4418f4
         (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeCRLDistributionPoints);
4418f4
    }
4418f4
    if (arena)
4418f4
        PORT_FreeArena (arena, PR_FALSE);
4418f4
    return (rv);
4418f4
}
4418f4
4418f4
4418f4
4418f4
static SECStatus 
4418f4
AddPolicyConstraints(void *extHandle)
4418f4
{
4418f4
    CERTCertificatePolicyConstraints *policyConstr;
4418f4
    PRArenaPool *arena = NULL;
4418f4
    SECStatus rv = SECSuccess;
4418f4
    SECItem *item, *dummy;
4418f4
    char buffer[512];
4418f4
    int value;
4418f4
    PRBool yesNoAns;
4418f4
    PRBool skipExt = PR_TRUE;
4418f4
4418f4
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
4418f4
    if ( !arena ) {
4418f4
        SECU_PrintError(progName, "out of memory");
4418f4
        return SECFailure;
4418f4
    }
4418f4
4418f4
    policyConstr = PORT_ArenaZNew(arena, CERTCertificatePolicyConstraints);
4418f4
    if (policyConstr == NULL) {
4418f4
        SECU_PrintError(progName, "out of memory");
4418f4
        goto loser;
4418f4
    }
4418f4
4418f4
    if (PrintChoicesAndGetAnswer("for requireExplicitPolicy enter the number "
4418f4
               "of certs in path\nbefore explicit policy is required\n"
4418f4
               "(press Enter to omit)", buffer, sizeof(buffer)) == SECFailure) {
4418f4
        goto loser;
4418f4
    }
4418f4
4418f4
    if (PORT_Strlen(buffer)) {
4418f4
        value = PORT_Atoi(buffer);
4418f4
    if (value < 0) {
4418f4
            goto loser;
4418f4
        }
4418f4
        item = &policyConstr->explicitPolicySkipCerts;
4418f4
        dummy = SEC_ASN1EncodeInteger(arena, item, value);
4418f4
        if (!dummy) {
4418f4
            goto loser;
4418f4
        }
4418f4
        skipExt = PR_FALSE;
4418f4
    }
4418f4
4418f4
    if (PrintChoicesAndGetAnswer("for inihibitPolicyMapping enter "
4418f4
               "the number of certs in path\n"
4418f4
           "after which policy mapping is not allowed\n"
4418f4
               "(press Enter to omit)", buffer, sizeof(buffer)) == SECFailure) {
4418f4
        goto loser;
4418f4
    }
4418f4
4418f4
    if (PORT_Strlen(buffer)) {
4418f4
        value = PORT_Atoi(buffer);
4418f4
    if (value < 0) {
4418f4
            goto loser;
4418f4
        }
4418f4
        item = &policyConstr->inhibitMappingSkipCerts;
4418f4
        dummy = SEC_ASN1EncodeInteger(arena, item, value);
4418f4
        if (!dummy) {
4418f4
            goto loser;
4418f4
        }
4418f4
        skipExt = PR_FALSE;
4418f4
    }
4418f4
 
4418f4
    
4418f4
    if (!skipExt) {
4418f4
        yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
4418f4
4418f4
        rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, policyConstr,
4418f4
         yesNoAns, SEC_OID_X509_POLICY_CONSTRAINTS,
4418f4
         (EXTEN_EXT_VALUE_ENCODER)CERT_EncodePolicyConstraintsExtension);
4418f4
    } else {
4418f4
        fprintf(stdout, "Policy Constraint extensions must contain "
4418f4
                        "at least one policy field\n");
4418f4
        rv = SECFailure;
4418f4
    }
4418f4
   
4418f4
loser:
4418f4
    if (arena) {
4418f4
        PORT_FreeArena (arena, PR_FALSE);
4418f4
    }
4418f4
    return (rv);
4418f4
}
4418f4
4418f4
4418f4
static SECStatus 
4418f4
AddInhibitAnyPolicy(void *extHandle)
4418f4
{
4418f4
    CERTCertificateInhibitAny certInhibitAny;
4418f4
    PRArenaPool *arena = NULL;
4418f4
    SECStatus rv = SECSuccess;
4418f4
    SECItem *item, *dummy;
4418f4
    char buffer[10];
4418f4
    int value;
4418f4
    PRBool yesNoAns;
4418f4
    
4418f4
4418f4
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
4418f4
    if ( !arena ) {
4418f4
        SECU_PrintError(progName, "out of memory");
4418f4
        return SECFailure;
4418f4
    }
4418f4
4418f4
    if (PrintChoicesAndGetAnswer("Enter the number of certs in the path "
4418f4
                                 "permitted to use anyPolicy.\n"
4418f4
                                 "(press Enter for 0)",
4418f4
                                 buffer, sizeof(buffer)) == SECFailure) {
4418f4
        goto loser;
4418f4
    }
4418f4
4418f4
    item = &certInhibitAny.inhibitAnySkipCerts;
4418f4
    value = PORT_Atoi(buffer);
4418f4
    if (value < 0) {
4418f4
        goto loser;
4418f4
    }
4418f4
    dummy = SEC_ASN1EncodeInteger(arena, item, value);
4418f4
    if (!dummy) {
4418f4
        goto loser;
4418f4
    }
4418f4
    
4418f4
    yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
4418f4
    
4418f4
    rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, &certInhibitAny,
4418f4
         yesNoAns, SEC_OID_X509_INHIBIT_ANY_POLICY,
4418f4
         (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeInhibitAnyExtension);
4418f4
loser:
4418f4
    if (arena) {
4418f4
        PORT_FreeArena (arena, PR_FALSE);
4418f4
    }
4418f4
    return (rv);
4418f4
}
4418f4
4418f4
4418f4
static SECStatus 
4418f4
AddPolicyMappings(void *extHandle)
4418f4
{
4418f4
    CERTPolicyMap **policyMapArr = NULL;
4418f4
    CERTPolicyMap *current;
4418f4
    PRArenaPool *arena = NULL;
4418f4
    SECStatus rv = SECSuccess;
4418f4
    int count = 0;
4418f4
    char buffer[512];
4418f4
    
4418f4
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
4418f4
    if ( !arena ) {
4418f4
        SECU_PrintError(progName, "out of memory");
4418f4
        return SECFailure;
4418f4
    }
4418f4
4418f4
    do {
4418f4
        if (PrintChoicesAndGetAnswer("Enter an Object Identifier (dotted "
4418f4
                                     "decimal format) for Issuer Domain Policy",
4418f4
                                     buffer, sizeof(buffer)) == SECFailure) {
4418f4
            GEN_BREAK (SECFailure);
4418f4
        }
4418f4
4418f4
        current = PORT_ArenaZNew(arena, CERTPolicyMap);
4418f4
        if (current == NULL) {
4418f4
            GEN_BREAK(SECFailure);
4418f4
        }
4418f4
4418f4
        rv = SEC_StringToOID(arena, &current->issuerDomainPolicy, buffer, 0);
4418f4
        if (rv == SECFailure) {
4418f4
            GEN_BREAK(SECFailure);
4418f4
        }
4418f4
4418f4
        if (PrintChoicesAndGetAnswer("Enter an Object Identifier for "
4418f4
                                     "Subject Domain Policy",
4418f4
                                     buffer, sizeof(buffer)) == SECFailure) {
4418f4
            GEN_BREAK (SECFailure);
4418f4
        }
4418f4
4418f4
        rv = SEC_StringToOID(arena, &current->subjectDomainPolicy, buffer, 0);
4418f4
        if (rv == SECFailure) {
4418f4
            GEN_BREAK(SECFailure);
4418f4
        }
4418f4
4418f4
        if (policyMapArr == NULL) {
4418f4
            policyMapArr = PORT_ArenaZNew(arena, CERTPolicyMap *);
4418f4
            if (policyMapArr == NULL) {
4418f4
                GEN_BREAK (SECFailure);
4418f4
            }
4418f4
        }
4418f4
4418f4
        policyMapArr = PORT_ArenaGrow(arena, policyMapArr,
4418f4
                                         sizeof (current) * count,
4418f4
                                         sizeof (current) *(count + 1));
4418f4
        if (policyMapArr == NULL) {
4418f4
            GEN_BREAK (SECFailure);
4418f4
        }
4418f4
    
4418f4
        policyMapArr[count] = current;
4418f4
        ++count;
4418f4
        
4418f4
        if (!GetYesNo("Enter another Policy Mapping [y/N]")) {
4418f4
            /* Add null to the end to mark end of data */
4418f4
            policyMapArr = PORT_ArenaGrow (arena, policyMapArr,
4418f4
                                           sizeof (current) * count,
4418f4
                                           sizeof (current) *(count + 1));
4418f4
            if (policyMapArr == NULL) {
4418f4
                GEN_BREAK (SECFailure);
4418f4
            }
4418f4
            policyMapArr[count] = NULL;        
4418f4
            break;
4418f4
        }
4418f4
4418f4
    } while (1);
4418f4
4418f4
    if (rv == SECSuccess) {
4418f4
        CERTCertificatePolicyMappings mappings;
4418f4
        PRBool yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
4418f4
4418f4
        mappings.arena = arena;
4418f4
        mappings.policyMaps = policyMapArr;
4418f4
        rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, &mappings,
4418f4
         yesNoAns, SEC_OID_X509_POLICY_MAPPINGS,
4418f4
         (EXTEN_EXT_VALUE_ENCODER)CERT_EncodePolicyMappingExtension);
4418f4
    }
4418f4
    if (arena)
4418f4
        PORT_FreeArena (arena, PR_FALSE);
4418f4
    return (rv);
4418f4
}
4418f4
4418f4
enum PoliciQualifierEnum {
4418f4
    cpsPointer = 1,
4418f4
    userNotice = 2
4418f4
};
4418f4
4418f4
static CERTPolicyQualifier **
4418f4
RequestPolicyQualifiers(PRArenaPool *arena, SECItem *policyID)
4418f4
{
4418f4
    CERTPolicyQualifier **policyQualifArr = NULL;
4418f4
    CERTPolicyQualifier *current;
4418f4
    SECStatus rv = SECSuccess;
4418f4
    int count = 0;
4418f4
    char buffer[512];
4418f4
    void *mark;
4418f4
    SECOidData *oid = NULL;
4418f4
    int intValue = 0;
4418f4
    int inCount = 0;
4418f4
4418f4
    PORT_Assert(arena);
4418f4
    mark = PORT_ArenaMark(arena);
4418f4
    do {
4418f4
        current = PORT_ArenaZNew(arena, CERTPolicyQualifier);
4418f4
        if (current == NULL) {
4418f4
            GEN_BREAK(SECFailure);
4418f4
        }
4418f4
4418f4
        /* Get the accessMethod fields */
4418f4
        SECU_PrintObjectID(stdout, policyID,
4418f4
                           "Choose the type of qualifier for policy" , 0);
4418f4
4418f4
        if (PrintChoicesAndGetAnswer(
4418f4
                "\t1 - CPS Pointer qualifier\n"
4418f4
                "\t2 - User notice qualifier\n"
4418f4
                "\tAny other number to finish\n"
4418f4
                "\t\tChoice: ", buffer, sizeof(buffer)) == SECFailure) {
4418f4
            GEN_BREAK (SECFailure);
4418f4
        }
4418f4
        intValue = PORT_Atoi(buffer);
4418f4
        switch (intValue) {
4418f4
        case cpsPointer: {
4418f4
            SECItem input;
4418f4
4418f4
            oid = SECOID_FindOIDByTag(SEC_OID_PKIX_CPS_POINTER_QUALIFIER);
4418f4
            if (PrintChoicesAndGetAnswer("Enter CPS pointer URI: ",
4418f4
                     buffer, sizeof(buffer)) == SECFailure) {
4418f4
                GEN_BREAK (SECFailure);
4418f4
            }
4418f4
            input.len = PORT_Strlen(buffer);
4418f4
            input.data = (void*)PORT_ArenaStrdup(arena, buffer);
4418f4
            if (input.data == NULL ||
4418f4
            SEC_ASN1EncodeItem(arena, &current->qualifierValue, &input,
4418f4
                   SEC_ASN1_GET(SEC_IA5StringTemplate)) == NULL) {
4418f4
                GEN_BREAK (SECFailure);
4418f4
            }
4418f4
            break;
4418f4
        }
4418f4
        case userNotice: {
4418f4
            SECItem **noticeNumArr;
4418f4
            CERTUserNotice *notice = PORT_ArenaZNew(arena, CERTUserNotice);
4418f4
            if (!notice) {
4418f4
                GEN_BREAK(SECFailure);
4418f4
            }
4418f4
            
4418f4
            oid = SECOID_FindOIDByTag(SEC_OID_PKIX_USER_NOTICE_QUALIFIER);
4418f4
4418f4
            if (GetYesNo("\t add a User Notice reference? [y/N]")) {
4418f4
4418f4
                if (PrintChoicesAndGetAnswer("Enter user organization string: ",
4418f4
                 buffer, sizeof(buffer)) == SECFailure) {
4418f4
                    GEN_BREAK (SECFailure);
4418f4
                }
4418f4
4418f4
                notice->noticeReference.organization.type = siAsciiString;
4418f4
                notice->noticeReference.organization.len =
4418f4
                    PORT_Strlen(buffer);
4418f4
                notice->noticeReference.organization.data =
4418f4
                    (void*)PORT_ArenaStrdup(arena, buffer);
4418f4
4418f4
4418f4
                noticeNumArr = PORT_ArenaZNewArray(arena, SECItem *, 2);
4418f4
                if (!noticeNumArr) {
4418f4
                    GEN_BREAK (SECFailure);
4418f4
                }
4418f4
                
4418f4
                do {
4418f4
                    SECItem *noticeNum;
4418f4
                    
4418f4
                    noticeNum = PORT_ArenaZNew(arena, SECItem);
4418f4
                    
4418f4
                    if (PrintChoicesAndGetAnswer(
4418f4
                      "Enter User Notice reference number "
4418f4
                      "(or -1 to quit): ",
4418f4
                                      buffer, sizeof(buffer)) == SECFailure) {
4418f4
                        GEN_BREAK (SECFailure);
4418f4
                    }
4418f4
                    
4418f4
                    intValue = PORT_Atoi(buffer);
4418f4
                    if (noticeNum == NULL) {
4418f4
                        if (intValue < 0) {
4418f4
                            fprintf(stdout, "a noticeReference must have at "
4418f4
                                    "least one reference number\n");
4418f4
                            GEN_BREAK (SECFailure);
4418f4
                        }
4418f4
                    } else {
4418f4
                        if (intValue >= 0) {
4418f4
                            noticeNumArr = PORT_ArenaGrow(arena, noticeNumArr,
4418f4
                          sizeof (current) * inCount,
4418f4
                          sizeof (current) *(inCount + 1));
4418f4
                            if (noticeNumArr == NULL) {
4418f4
                                GEN_BREAK (SECFailure);
4418f4
                            }
4418f4
                        } else {
4418f4
                            break;
4418f4
                        }
4418f4
                    }
4418f4
                    if (!SEC_ASN1EncodeInteger(arena, noticeNum, intValue)) {
4418f4
                        GEN_BREAK (SECFailure);
4418f4
                    }
4418f4
                    noticeNumArr[inCount++] = noticeNum;
4418f4
                    noticeNumArr[inCount] = NULL;
4418f4
                    
4418f4
                } while (1);
4418f4
                if (rv == SECFailure) {
4418f4
                    GEN_BREAK(SECFailure);
4418f4
                }
4418f4
                notice->noticeReference.noticeNumbers = noticeNumArr;
4418f4
                rv = CERT_EncodeNoticeReference(arena, &notice->noticeReference,
4418f4
                                                &notice->derNoticeReference);
4418f4
                if (rv == SECFailure) {
4418f4
                    GEN_BREAK(SECFailure);
4418f4
                }
4418f4
            }
4418f4
            if (GetYesNo("\t EnterUser Notice explicit text? [y/N]")) {
4418f4
                /* Getting only 200 bytes - RFC limitation */
4418f4
                if (PrintChoicesAndGetAnswer(
4418f4
                        "\t", buffer, 200) == SECFailure) {
4418f4
                        GEN_BREAK (SECFailure);
4418f4
                }
4418f4
                notice->displayText.type = siAsciiString;
4418f4
                notice->displayText.len = PORT_Strlen(buffer);
4418f4
                notice->displayText.data = 
4418f4
                                (void*)PORT_ArenaStrdup(arena, buffer);
4418f4
        if (notice->displayText.data == NULL) {
4418f4
            GEN_BREAK(SECFailure);
4418f4
        }
4418f4
            }
4418f4
4418f4
            rv = CERT_EncodeUserNotice(arena, notice, &current->qualifierValue);
4418f4
            if (rv == SECFailure) {
4418f4
                GEN_BREAK(SECFailure);
4418f4
            }
4418f4
4418f4
            break;
4418f4
        }
4418f4
        }
4418f4
        if (rv == SECFailure || oid == NULL ||
4418f4
            SECITEM_CopyItem(arena, &current->qualifierID, &oid->oid) 
4418f4
            == SECFailure) {
4418f4
            GEN_BREAK (SECFailure);
4418f4
        }
4418f4
4418f4
        if (!policyQualifArr) {
4418f4
            policyQualifArr = PORT_ArenaZNew(arena, CERTPolicyQualifier *);
4418f4
        } else {
4418f4
            policyQualifArr = PORT_ArenaGrow (arena, policyQualifArr,
4418f4
                                         sizeof (current) * count,
4418f4
                                         sizeof (current) *(count + 1));
4418f4
        }
4418f4
        if (policyQualifArr == NULL) {
4418f4
            GEN_BREAK (SECFailure);
4418f4
        }
4418f4
    
4418f4
        policyQualifArr[count] = current;
4418f4
        ++count;
4418f4
4418f4
        if (!GetYesNo ("Enter another policy qualifier [y/N]")) {
4418f4
            /* Add null to the end to mark end of data */
4418f4
            policyQualifArr = PORT_ArenaGrow(arena, policyQualifArr,
4418f4
                                              sizeof (current) * count,
4418f4
                                              sizeof (current) *(count + 1));
4418f4
            if (policyQualifArr == NULL) {
4418f4
                GEN_BREAK (SECFailure);
4418f4
            }
4418f4
            policyQualifArr[count] = NULL;        
4418f4
            break;
4418f4
        }
4418f4
4418f4
    } while (1);
4418f4
4418f4
    if (rv != SECSuccess) {
4418f4
        PORT_ArenaRelease (arena, mark);
4418f4
        policyQualifArr = NULL;
4418f4
    }
4418f4
    return (policyQualifArr);
4418f4
}
4418f4
4418f4
static SECStatus 
4418f4
AddCertPolicies(void *extHandle)
4418f4
{
4418f4
    CERTPolicyInfo **certPoliciesArr = NULL;
4418f4
    CERTPolicyInfo *current;
4418f4
    PRArenaPool *arena = NULL;
4418f4
    SECStatus rv = SECSuccess;
4418f4
    int count = 0;
4418f4
    char buffer[512];
4418f4
4418f4
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
4418f4
    if ( !arena ) {
4418f4
        SECU_PrintError(progName, "out of memory");
4418f4
        return SECFailure;
4418f4
    }
4418f4
4418f4
    do {
4418f4
        current = PORT_ArenaZNew(arena, CERTPolicyInfo);
4418f4
        if (current == NULL) {
4418f4
            GEN_BREAK(SECFailure);
4418f4
        }
4418f4
4418f4
        if (PrintChoicesAndGetAnswer("Enter a CertPolicy Object Identifier "
4418f4
                                     "(dotted decimal format)\n"
4418f4
                                     "or \"any\" for AnyPolicy:",
4418f4
                                     buffer, sizeof(buffer)) == SECFailure) {
4418f4
            GEN_BREAK (SECFailure);
4418f4
        }
4418f4
    
4418f4
        if (strncmp(buffer, "any", 3) == 0) {
4418f4
            /* use string version of X509_CERTIFICATE_POLICIES.anyPolicy */
4418f4
            strcpy(buffer, "OID.2.5.29.32.0");
4418f4
        }
4418f4
        rv = SEC_StringToOID(arena, &current->policyID, buffer, 0);
4418f4
4418f4
        if (rv == SECFailure) {
4418f4
            GEN_BREAK(SECFailure);
4418f4
        }
4418f4
        
4418f4
        current->policyQualifiers = 
4418f4
            RequestPolicyQualifiers(arena, &current->policyID); 
4418f4
4418f4
        if (!certPoliciesArr) {
4418f4
            certPoliciesArr = PORT_ArenaZNew(arena, CERTPolicyInfo *);
4418f4
        } else {
4418f4
        certPoliciesArr = PORT_ArenaGrow(arena, certPoliciesArr,
4418f4
                                         sizeof (current) * count,
4418f4
                                         sizeof (current) *(count + 1));
4418f4
        }
4418f4
        if (certPoliciesArr == NULL) {
4418f4
            GEN_BREAK (SECFailure);
4418f4
        }
4418f4
    
4418f4
        certPoliciesArr[count] = current;
4418f4
        ++count;
4418f4
        
4418f4
        if (!GetYesNo ("Enter another PolicyInformation field [y/N]?")) {
4418f4
            /* Add null to the end to mark end of data */
4418f4
            certPoliciesArr = PORT_ArenaGrow(arena, certPoliciesArr,
4418f4
                                              sizeof (current) * count,
4418f4
                                              sizeof (current) *(count + 1));
4418f4
            if (certPoliciesArr == NULL) {
4418f4
                GEN_BREAK (SECFailure);
4418f4
            }
4418f4
            certPoliciesArr[count] = NULL;        
4418f4
            break;
4418f4
        }
4418f4
4418f4
    } while (1);
4418f4
4418f4
    if (rv == SECSuccess) {
4418f4
        CERTCertificatePolicies policies;
4418f4
        PRBool yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
4418f4
4418f4
        policies.arena = arena;
4418f4
        policies.policyInfos = certPoliciesArr;
4418f4
        
4418f4
        rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, &policies,
4418f4
         yesNoAns, SEC_OID_X509_CERTIFICATE_POLICIES,
4418f4
         (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeCertPoliciesExtension);
4418f4
    }
4418f4
    if (arena)
4418f4
    PORT_FreeArena(arena, PR_FALSE);
4418f4
    return (rv);
4418f4
}
4418f4
4418f4
enum AuthInfoAccessTypesEnum {
4418f4
    caIssuers = 1,
4418f4
    ocsp = 2
4418f4
};
4418f4
4418f4
enum SubjInfoAccessTypesEnum {
4418f4
    caRepository = 1,
4418f4
    timeStamping = 2
4418f4
};
4418f4
4418f4
/* Encode and add an AIA or SIA extension */
4418f4
static SECStatus 
4418f4
AddInfoAccess(void *extHandle, PRBool addSIAExt, PRBool isCACert)
4418f4
{
4418f4
    CERTAuthInfoAccess **infoAccArr = NULL;
4418f4
    CERTAuthInfoAccess *current;
4418f4
    PRArenaPool *arena = NULL;
4418f4
    SECStatus rv = SECSuccess;
4418f4
    int count = 0;
4418f4
    char buffer[512];
4418f4
    SECOidData *oid = NULL;
4418f4
    int intValue = 0;
4418f4
4418f4
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
4418f4
    if ( !arena ) {
4418f4
        SECU_PrintError(progName, "out of memory");
4418f4
        return SECFailure;
4418f4
    }
4418f4
4418f4
    do {
4418f4
        current = NULL;
4418f4
        current = PORT_ArenaZNew(arena, CERTAuthInfoAccess);
4418f4
        if (current == NULL) {
4418f4
            GEN_BREAK(SECFailure);
4418f4
        }
4418f4
4418f4
        /* Get the accessMethod fields */
4418f4
        if (addSIAExt) {
4418f4
            if (isCACert) {
4418f4
                puts("Adding \"CA Repository\" access method type for "
4418f4
                    "Subject Information Access extension:\n");
4418f4
                intValue = caRepository;
4418f4
            } else {
4418f4
                puts("Adding \"Time Stamping Services\" access method type for "
4418f4
                    "Subject Information Access extension:\n");
4418f4
                intValue = timeStamping;
4418f4
            }
4418f4
        } else {
4418f4
            PrintChoicesAndGetAnswer("Enter access method type "
4418f4
                "for Authority Information Access extension:\n"
4418f4
                "\t1 - CA Issuers\n\t2 - OCSP\n\tAny"
4418f4
                "other number to finish\n\tChoice",
4418f4
                buffer, sizeof(buffer));
4418f4
            intValue = PORT_Atoi(buffer);
4418f4
        }
4418f4
        if (addSIAExt) {
4418f4
            switch (intValue) {
4418f4
              case caRepository:
4418f4
                  oid = SECOID_FindOIDByTag(SEC_OID_PKIX_CA_REPOSITORY);
4418f4
                  break;
4418f4
                  
4418f4
              case timeStamping:
4418f4
                  oid = SECOID_FindOIDByTag(SEC_OID_PKIX_TIMESTAMPING);
4418f4
                  break;
4418f4
            } 
4418f4
        } else {
4418f4
            switch (intValue) {
4418f4
              case caIssuers:
4418f4
                  oid = SECOID_FindOIDByTag(SEC_OID_PKIX_CA_ISSUERS);
4418f4
                  break;
4418f4
                  
4418f4
              case ocsp:
4418f4
                  oid = SECOID_FindOIDByTag(SEC_OID_PKIX_OCSP);
4418f4
                  break;
4418f4
            } 
4418f4
        }
4418f4
        if (oid == NULL ||
4418f4
            SECITEM_CopyItem(arena, &current->method, &oid->oid) 
4418f4
            == SECFailure) {
4418f4
            GEN_BREAK (SECFailure);
4418f4
        }
4418f4
4418f4
        current->location = GetGeneralName(arena);
4418f4
        if (!current->location) {
4418f4
            GEN_BREAK(SECFailure);
4418f4
        }
4418f4
       
4418f4
        if (infoAccArr == NULL) {
4418f4
            infoAccArr = PORT_ArenaZNew(arena, CERTAuthInfoAccess *);
4418f4
        } else {
4418f4
            infoAccArr = PORT_ArenaGrow(arena, infoAccArr,
4418f4
                                     sizeof (current) * count,
4418f4
                                     sizeof (current) *(count + 1));
4418f4
        }
4418f4
        if (infoAccArr == NULL) {
4418f4
            GEN_BREAK (SECFailure);
4418f4
        }
4418f4
    
4418f4
        infoAccArr[count] = current;
4418f4
        ++count;
4418f4
        
4418f4
        PR_snprintf(buffer, sizeof(buffer), "Add another location to the %s"
4418f4
                    " Information Access extension [y/N]",
4418f4
                    (addSIAExt) ? "Subject" : "Authority");
4418f4
4418f4
        if (GetYesNo (buffer) == 0) {
4418f4
            /* Add null to the end to mark end of data */
4418f4
            infoAccArr = PORT_ArenaGrow(arena, infoAccArr,
4418f4
                                         sizeof (current) * count,
4418f4
                                         sizeof (current) *(count + 1));
4418f4
            if (infoAccArr == NULL) {
4418f4
                GEN_BREAK (SECFailure);
4418f4
            }
4418f4
            infoAccArr[count] = NULL;        
4418f4
            break;
4418f4
        }
4418f4
4418f4
    } while (1);
4418f4
4418f4
    if (rv == SECSuccess) {
4418f4
        int oidIdent = SEC_OID_X509_AUTH_INFO_ACCESS;
4418f4
4418f4
        PRBool yesNoAns = GetYesNo("Is this a critical extension [y/N]?");
4418f4
        
4418f4
        if (addSIAExt) {
4418f4
            oidIdent = SEC_OID_X509_SUBJECT_INFO_ACCESS;
4418f4
        }
4418f4
        rv = SECU_EncodeAndAddExtensionValue(arena, extHandle, infoAccArr,
4418f4
         yesNoAns, oidIdent,
4418f4
         (EXTEN_EXT_VALUE_ENCODER)CERT_EncodeInfoAccessExtension);
4418f4
    }
4418f4
    if (arena)
4418f4
        PORT_FreeArena(arena, PR_FALSE);
4418f4
    return (rv);
4418f4
}
4418f4
4418f4
SECStatus
4418f4
AddExtensions(void *extHandle, const char *emailAddrs, const char *dnsNames,
4418f4
              certutilExtnList extList)
4418f4
{
4418f4
    SECStatus rv = SECSuccess;
4418f4
    char *errstring = NULL;
4418f4
    
4418f4
    do {
4418f4
        /* Add key usage extension */
4418f4
        if (extList[ext_keyUsage]) {
4418f4
            rv = AddKeyUsage(extHandle);
4418f4
            if (rv) {
4418f4
                errstring = "KeyUsage";
4418f4
                break;
4418f4
            }
4418f4
        }
4418f4
4418f4
        /* Add extended key usage extension */
4418f4
        if (extList[ext_extKeyUsage]) {
4418f4
            rv = AddExtKeyUsage(extHandle);
4418f4
            if (rv) {
4418f4
                errstring = "ExtendedKeyUsage";
4418f4
                break;
4418f4
            }
4418f4
        }
4418f4
4418f4
        /* Add basic constraint extension */
4418f4
        if (extList[ext_basicConstraint]) {
4418f4
            rv = AddBasicConstraint(extHandle);
4418f4
            if (rv) {
4418f4
                errstring = "BasicConstraint";
4418f4
                break;
4418f4
            }
4418f4
        }
4418f4
4418f4
        if (extList[ext_authorityKeyID]) {
4418f4
            rv = AddAuthKeyID(extHandle);
4418f4
            if (rv) {
4418f4
                errstring = "AuthorityKeyID";
4418f4
                break;
4418f4
            }
4418f4
        }
4418f4
4418f4
        if (extList[ext_subjectKeyID]) {
4418f4
            rv = AddSubjKeyID(extHandle);
4418f4
            if (rv) {
4418f4
                errstring = "SubjectKeyID";
4418f4
                break;
4418f4
            }
4418f4
        }    
4418f4
4418f4
        if (extList[ext_CRLDistPts]) {
4418f4
            rv = AddCrlDistPoint(extHandle);
4418f4
            if (rv) {
4418f4
                errstring = "CRLDistPoints";
4418f4
                break;
4418f4
            }
4418f4
        }
4418f4
4418f4
        if (extList[ext_NSCertType]) {
4418f4
            rv = AddNscpCertType(extHandle);
4418f4
            if (rv) {
4418f4
                errstring = "NSCertType";
4418f4
                break;
4418f4
            }
4418f4
        }
4418f4
4418f4
        if (extList[ext_authInfoAcc] || extList[ext_subjInfoAcc]) {
4418f4
            rv = AddInfoAccess(extHandle, extList[ext_subjInfoAcc],
4418f4
                           extList[ext_basicConstraint]);
4418f4
            if (rv) {
4418f4
                errstring = "InformationAccess";
4418f4
                break;
4418f4
            }
4418f4
        }
4418f4
4418f4
        if (extList[ext_certPolicies]) {
4418f4
            rv = AddCertPolicies(extHandle);
4418f4
            if (rv) {
4418f4
                errstring = "Policies";
4418f4
                break;
4418f4
            }
4418f4
        }
4418f4
4418f4
        if (extList[ext_policyMappings]) {
4418f4
            rv = AddPolicyMappings(extHandle);
4418f4
            if (rv) {
4418f4
                errstring = "PolicyMappings";
4418f4
                break;
4418f4
            }
4418f4
        }
4418f4
4418f4
        if (extList[ext_policyConstr]) {
4418f4
            rv = AddPolicyConstraints(extHandle);
4418f4
            if (rv) {
4418f4
                errstring = "PolicyConstraints";
4418f4
                break;
4418f4
            }
4418f4
        }
4418f4
4418f4
        if (extList[ext_inhibitAnyPolicy]) {
4418f4
            rv = AddInhibitAnyPolicy(extHandle);
4418f4
            if (rv) {
4418f4
                errstring = "InhibitAnyPolicy";
4418f4
                break;
4418f4
            }
4418f4
        }
4418f4
4418f4
        if (emailAddrs || dnsNames) {
4418f4
            PRArenaPool *arena;
4418f4
            CERTGeneralName *namelist = NULL;
4418f4
            SECItem item = { 0, NULL, 0 };
4418f4
            
4418f4
            arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
4418f4
            if (arena == NULL) {
4418f4
                rv = SECFailure;
4418f4
                break;
4418f4
            }
4418f4
4418f4
            rv = AddEmailSubjectAlt(arena, &namelist, emailAddrs);
4418f4
4418f4
            rv |= AddDNSSubjectAlt(arena, &namelist, dnsNames);
4418f4
4418f4
            if (rv == SECSuccess) {
4418f4
                rv = CERT_EncodeAltNameExtension(arena, namelist, &item);
4418f4
            if (rv == SECSuccess) {
4418f4
                    rv = CERT_AddExtension(extHandle,
4418f4
                                          SEC_OID_X509_SUBJECT_ALT_NAME,
4418f4
                                          &item, PR_FALSE, PR_TRUE);
4418f4
        }
4418f4
            }
4418f4
        PORT_FreeArena(arena, PR_FALSE);
4418f4
        if (rv) {
4418f4
                errstring = "SubjectAltName";
4418f4
                break;
4418f4
        }
4418f4
        }
4418f4
    } while (0);
4418f4
    
4418f4
    if (rv != SECSuccess) {
4418f4
        SECU_PrintError(progName, "Problem creating %s extension", errstring);
4418f4
    }
4418f4
    return rv;
4418f4
}