|
|
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, ¤t->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, ¤t->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, ¤t->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, ¤t->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, ¤t->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, ¬ice->noticeReference,
|
|
|
4418f4 |
¬ice->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, ¤t->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, ¤t->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, ¤t->policyID, buffer, 0);
|
|
|
4418f4 |
|
|
|
4418f4 |
if (rv == SECFailure) {
|
|
|
4418f4 |
GEN_BREAK(SECFailure);
|
|
|
4418f4 |
}
|
|
|
4418f4 |
|
|
|
4418f4 |
current->policyQualifiers =
|
|
|
4418f4 |
RequestPolicyQualifiers(arena, ¤t->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, ¤t->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 |
}
|