155714Skris/* apps/ca.c */ 255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 355714Skris * All rights reserved. 455714Skris * 555714Skris * This package is an SSL implementation written 655714Skris * by Eric Young (eay@cryptsoft.com). 755714Skris * The implementation was written so as to conform with Netscapes SSL. 855714Skris * 955714Skris * This library is free for commercial and non-commercial use as long as 1055714Skris * the following conditions are aheared to. The following conditions 1155714Skris * apply to all code found in this distribution, be it the RC4, RSA, 1255714Skris * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1355714Skris * included with this distribution is covered by the same copyright terms 1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com). 1555714Skris * 1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in 1755714Skris * the code are not to be removed. 1855714Skris * If this package is used in a product, Eric Young should be given attribution 1955714Skris * as the author of the parts of the library used. 2055714Skris * This can be in the form of a textual message at program startup or 2155714Skris * in documentation (online or textual) provided with the package. 2255714Skris * 2355714Skris * Redistribution and use in source and binary forms, with or without 2455714Skris * modification, are permitted provided that the following conditions 2555714Skris * are met: 2655714Skris * 1. Redistributions of source code must retain the copyright 2755714Skris * notice, this list of conditions and the following disclaimer. 2855714Skris * 2. Redistributions in binary form must reproduce the above copyright 2955714Skris * notice, this list of conditions and the following disclaimer in the 3055714Skris * documentation and/or other materials provided with the distribution. 3155714Skris * 3. All advertising materials mentioning features or use of this software 3255714Skris * must display the following acknowledgement: 3355714Skris * "This product includes cryptographic software written by 3455714Skris * Eric Young (eay@cryptsoft.com)" 3555714Skris * The word 'cryptographic' can be left out if the rouines from the library 3655714Skris * being used are not cryptographic related :-). 3755714Skris * 4. If you include any Windows specific code (or a derivative thereof) from 3855714Skris * the apps directory (application code) you must include an acknowledgement: 3955714Skris * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 4055714Skris * 4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4455714Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5155714Skris * SUCH DAMAGE. 5255714Skris * 5355714Skris * The licence and distribution terms for any publically available version or 5455714Skris * derivative of this code cannot be changed. i.e. this code cannot simply be 5555714Skris * copied and put under another distribution licence 5655714Skris * [including the GNU Public Licence.] 5755714Skris */ 5855714Skris 5955714Skris/* The PPKI stuff has been donated by Jeff Barber <jeffb@issl.atl.hp.com> */ 6055714Skris 6155714Skris#include <stdio.h> 6255714Skris#include <stdlib.h> 6355714Skris#include <string.h> 64109998Smarkm#include <ctype.h> 6555714Skris#include <sys/types.h> 6655714Skris#include <openssl/conf.h> 6755714Skris#include <openssl/bio.h> 6855714Skris#include <openssl/err.h> 6955714Skris#include <openssl/bn.h> 7055714Skris#include <openssl/txt_db.h> 7155714Skris#include <openssl/evp.h> 7255714Skris#include <openssl/x509.h> 7355714Skris#include <openssl/x509v3.h> 7455714Skris#include <openssl/objects.h> 75109998Smarkm#include <openssl/ocsp.h> 7655714Skris#include <openssl/pem.h> 7755714Skris 7855714Skris#ifndef W_OK 79109998Smarkm# ifdef OPENSSL_SYS_VMS 8055714Skris# if defined(__DECC) 8155714Skris# include <unistd.h> 8255714Skris# else 8355714Skris# include <unixlib.h> 8455714Skris# endif 85238405Sjkim# elif !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_NETWARE) 8655714Skris# include <sys/file.h> 8755714Skris# endif 8855714Skris#endif 8955714Skris 90109998Smarkm#include "apps.h" 91109998Smarkm 9255714Skris#ifndef W_OK 9355714Skris# define F_OK 0 9455714Skris# define X_OK 1 9555714Skris# define W_OK 2 9655714Skris# define R_OK 4 9755714Skris#endif 9855714Skris 9955714Skris#undef PROG 10055714Skris#define PROG ca_main 10155714Skris 10255714Skris#define BASE_SECTION "ca" 10355714Skris#define CONFIG_FILE "openssl.cnf" 10455714Skris 10555714Skris#define ENV_DEFAULT_CA "default_ca" 10655714Skris 107160814Ssimon#define STRING_MASK "string_mask" 108160814Ssimon#define UTF8_IN "utf8" 109160814Ssimon 11055714Skris#define ENV_DIR "dir" 11155714Skris#define ENV_CERTS "certs" 11255714Skris#define ENV_CRL_DIR "crl_dir" 11355714Skris#define ENV_CA_DB "CA_DB" 11455714Skris#define ENV_NEW_CERTS_DIR "new_certs_dir" 11555714Skris#define ENV_CERTIFICATE "certificate" 11655714Skris#define ENV_SERIAL "serial" 117127128Snectar#define ENV_CRLNUMBER "crlnumber" 11855714Skris#define ENV_CRL "crl" 11955714Skris#define ENV_PRIVATE_KEY "private_key" 12055714Skris#define ENV_RANDFILE "RANDFILE" 12155714Skris#define ENV_DEFAULT_DAYS "default_days" 12255714Skris#define ENV_DEFAULT_STARTDATE "default_startdate" 12355714Skris#define ENV_DEFAULT_ENDDATE "default_enddate" 12455714Skris#define ENV_DEFAULT_CRL_DAYS "default_crl_days" 12555714Skris#define ENV_DEFAULT_CRL_HOURS "default_crl_hours" 12655714Skris#define ENV_DEFAULT_MD "default_md" 127109998Smarkm#define ENV_DEFAULT_EMAIL_DN "email_in_dn" 12855714Skris#define ENV_PRESERVE "preserve" 12955714Skris#define ENV_POLICY "policy" 13055714Skris#define ENV_EXTENSIONS "x509_extensions" 13155714Skris#define ENV_CRLEXT "crl_extensions" 13255714Skris#define ENV_MSIE_HACK "msie_hack" 133109998Smarkm#define ENV_NAMEOPT "name_opt" 134109998Smarkm#define ENV_CERTOPT "cert_opt" 135109998Smarkm#define ENV_EXTCOPY "copy_extensions" 136160814Ssimon#define ENV_UNIQUE_SUBJECT "unique_subject" 13755714Skris 13855714Skris#define ENV_DATABASE "database" 13955714Skris 140109998Smarkm/* Additional revocation information types */ 141109998Smarkm 142109998Smarkm#define REV_NONE 0 /* No addditional information */ 143109998Smarkm#define REV_CRL_REASON 1 /* Value is CRL reason code */ 144109998Smarkm#define REV_HOLD 2 /* Value is hold instruction */ 145109998Smarkm#define REV_KEY_COMPROMISE 3 /* Value is cert key compromise time */ 146109998Smarkm#define REV_CA_COMPROMISE 4 /* Value is CA key compromise time */ 147109998Smarkm 148160814Ssimonstatic const char *ca_usage[]={ 14955714Skris"usage: ca args\n", 15055714Skris"\n", 15155714Skris" -verbose - Talk alot while doing things\n", 15255714Skris" -config file - A config file\n", 15355714Skris" -name arg - The particular CA definition to use\n", 15455714Skris" -gencrl - Generate a new CRL\n", 15555714Skris" -crldays days - Days is when the next CRL is due\n", 15655714Skris" -crlhours hours - Hours is when the next CRL is due\n", 15759191Skris" -startdate YYMMDDHHMMSSZ - certificate validity notBefore\n", 15859191Skris" -enddate YYMMDDHHMMSSZ - certificate validity notAfter (overrides -days)\n", 15955714Skris" -days arg - number of days to certify the certificate for\n", 16055714Skris" -md arg - md to use, one of md2, md5, sha or sha1\n", 16155714Skris" -policy arg - The CA 'policy' to support\n", 162109998Smarkm" -keyfile arg - private key file\n", 163109998Smarkm" -keyform arg - private key file format (PEM or ENGINE)\n", 16455714Skris" -key arg - key to decode the private key if it is encrypted\n", 16555714Skris" -cert file - The CA certificate\n", 166160814Ssimon" -selfsign - sign a certificate with the key associated with it\n", 16755714Skris" -in file - The input PEM encoded certificate request(s)\n", 16855714Skris" -out file - Where to put the output file(s)\n", 16955714Skris" -outdir dir - Where to put output certificates\n", 17055714Skris" -infiles .... - The last argument, requests to process\n", 17155714Skris" -spkac file - File contains DN and signed public key and challenge\n", 17255714Skris" -ss_cert file - File contains a self signed cert to sign\n", 17355714Skris" -preserveDN - Don't re-order the DN\n", 174109998Smarkm" -noemailDN - Don't add the EMAIL field into certificate' subject\n", 17555714Skris" -batch - Don't ask questions\n", 17655714Skris" -msie_hack - msie modifications to handle all those universal strings\n", 17755714Skris" -revoke file - Revoke a certificate (given in file)\n", 178109998Smarkm" -subj arg - Use arg instead of request's subject\n", 179160814Ssimon" -utf8 - input characters are UTF8 (default ASCII)\n", 180160814Ssimon" -multivalue-rdn - enable support for multivalued RDNs\n", 18159191Skris" -extensions .. - Extension section (override value in config file)\n", 182109998Smarkm" -extfile file - Configuration file with X509v3 extentions to add\n", 18359191Skris" -crlexts .. - CRL extension section (override value in config file)\n", 184111147Snectar#ifndef OPENSSL_NO_ENGINE 185109998Smarkm" -engine e - use engine e, possibly a hardware device.\n", 186111147Snectar#endif 187109998Smarkm" -status serial - Shows certificate status given the serial number\n", 188109998Smarkm" -updatedb - Updates db for expired certificates\n", 18955714SkrisNULL 19055714Skris}; 19155714Skris 19255714Skris#ifdef EFENCE 19355714Skrisextern int EF_PROTECT_FREE; 19455714Skrisextern int EF_PROTECT_BELOW; 19555714Skrisextern int EF_ALIGNMENT; 19655714Skris#endif 19755714Skris 198160814Ssimonstatic void lookup_fail(const char *name, const char *tag); 19955714Skrisstatic int certify(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509, 200238405Sjkim const EVP_MD *dgst,STACK_OF(OPENSSL_STRING) *sigopts, 201238405Sjkim STACK_OF(CONF_VALUE) *policy,CA_DB *db, 202160814Ssimon BIGNUM *serial, char *subj,unsigned long chtype, int multirdn, int email_dn, char *startdate, 203109998Smarkm char *enddate, long days, int batch, char *ext_sect, CONF *conf, 204109998Smarkm int verbose, unsigned long certopt, unsigned long nameopt, 205160814Ssimon int default_op, int ext_copy, int selfsign); 20655714Skrisstatic int certify_cert(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509, 207238405Sjkim const EVP_MD *dgst,STACK_OF(OPENSSL_STRING) *sigopts, 208238405Sjkim STACK_OF(CONF_VALUE) *policy, 209160814Ssimon CA_DB *db, BIGNUM *serial, char *subj,unsigned long chtype, int multirdn, int email_dn, 210109998Smarkm char *startdate, char *enddate, long days, int batch, 211109998Smarkm char *ext_sect, CONF *conf,int verbose, unsigned long certopt, 212109998Smarkm unsigned long nameopt, int default_op, int ext_copy, 213109998Smarkm ENGINE *e); 21455714Skrisstatic int certify_spkac(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509, 215238405Sjkim const EVP_MD *dgst,STACK_OF(OPENSSL_STRING) *sigopts, 216238405Sjkim STACK_OF(CONF_VALUE) *policy, 217160814Ssimon CA_DB *db, BIGNUM *serial,char *subj,unsigned long chtype, int multirdn, int email_dn, 218109998Smarkm char *startdate, char *enddate, long days, char *ext_sect, 219109998Smarkm CONF *conf, int verbose, unsigned long certopt, 220109998Smarkm unsigned long nameopt, int default_op, int ext_copy); 22159191Skrisstatic void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext); 22255714Skrisstatic int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, 223238405Sjkim STACK_OF(OPENSSL_STRING) *sigopts, 224160814Ssimon STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial,char *subj,unsigned long chtype, int multirdn, 225109998Smarkm int email_dn, char *startdate, char *enddate, long days, int batch, 226109998Smarkm int verbose, X509_REQ *req, char *ext_sect, CONF *conf, 227109998Smarkm unsigned long certopt, unsigned long nameopt, int default_op, 228160814Ssimon int ext_copy, int selfsign); 229127128Snectarstatic int do_revoke(X509 *x509, CA_DB *db, int ext, char *extval); 230127128Snectarstatic int get_certificate_status(const char *ser_status, CA_DB *db); 231127128Snectarstatic int do_updatedb(CA_DB *db); 232205128Ssimonstatic int check_time_format(const char *str); 233109998Smarkmchar *make_revocation_str(int rev_type, char *rev_arg); 234160814Ssimonint make_revoked(X509_REVOKED *rev, const char *str); 235109998Smarkmint old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str); 236109998Smarkmstatic CONF *conf=NULL; 237109998Smarkmstatic CONF *extconf=NULL; 23855714Skrisstatic char *section=NULL; 23955714Skris 24055714Skrisstatic int preserve=0; 24155714Skrisstatic int msie_hack=0; 24255714Skris 243109998Smarkm 24459191Skrisint MAIN(int, char **); 24559191Skris 24655714Skrisint MAIN(int argc, char **argv) 24755714Skris { 248109998Smarkm ENGINE *e = NULL; 24968651Skris char *key=NULL,*passargin=NULL; 250142425Snectar int create_ser = 0; 251109998Smarkm int free_key = 0; 25255714Skris int total=0; 25355714Skris int total_done=0; 25455714Skris int badops=0; 25555714Skris int ret=1; 256109998Smarkm int email_dn=1; 25755714Skris int req=0; 25855714Skris int verbose=0; 25955714Skris int gencrl=0; 26055714Skris int dorevoke=0; 261109998Smarkm int doupdatedb=0; 26255714Skris long crldays=0; 26355714Skris long crlhours=0; 264238405Sjkim long crlsec=0; 26555714Skris long errorline= -1; 26655714Skris char *configfile=NULL; 26755714Skris char *md=NULL; 26855714Skris char *policy=NULL; 26955714Skris char *keyfile=NULL; 27055714Skris char *certfile=NULL; 271109998Smarkm int keyform=FORMAT_PEM; 27255714Skris char *infile=NULL; 27355714Skris char *spkac_file=NULL; 27455714Skris char *ss_cert_file=NULL; 275109998Smarkm char *ser_status=NULL; 27655714Skris EVP_PKEY *pkey=NULL; 27755714Skris int output_der = 0; 27855714Skris char *outfile=NULL; 27955714Skris char *outdir=NULL; 28055714Skris char *serialfile=NULL; 281127128Snectar char *crlnumberfile=NULL; 28255714Skris char *extensions=NULL; 283109998Smarkm char *extfile=NULL; 284109998Smarkm char *subj=NULL; 285160814Ssimon unsigned long chtype = MBSTRING_ASC; 286160814Ssimon int multirdn = 0; 287109998Smarkm char *tmp_email_dn=NULL; 28855714Skris char *crl_ext=NULL; 289109998Smarkm int rev_type = REV_NONE; 290109998Smarkm char *rev_arg = NULL; 29155714Skris BIGNUM *serial=NULL; 292127128Snectar BIGNUM *crlnumber=NULL; 29355714Skris char *startdate=NULL; 29455714Skris char *enddate=NULL; 295109998Smarkm long days=0; 29655714Skris int batch=0; 29759191Skris int notext=0; 298109998Smarkm unsigned long nameopt = 0, certopt = 0; 299109998Smarkm int default_op = 1; 300109998Smarkm int ext_copy = EXT_COPY_NONE; 301160814Ssimon int selfsign = 0; 302160814Ssimon X509 *x509=NULL, *x509p = NULL; 30355714Skris X509 *x=NULL; 30455714Skris BIO *in=NULL,*out=NULL,*Sout=NULL,*Cout=NULL; 30555714Skris char *dbfile=NULL; 306127128Snectar CA_DB *db=NULL; 30755714Skris X509_CRL *crl=NULL; 30855714Skris X509_REVOKED *r=NULL; 309109998Smarkm ASN1_TIME *tmptm; 310109998Smarkm ASN1_INTEGER *tmpser; 311160814Ssimon char *f; 312238405Sjkim const char *p; 313238405Sjkim char * const *pp; 31455714Skris int i,j; 31555714Skris const EVP_MD *dgst=NULL; 31655714Skris STACK_OF(CONF_VALUE) *attribs=NULL; 31768651Skris STACK_OF(X509) *cert_sk=NULL; 318238405Sjkim STACK_OF(OPENSSL_STRING) *sigopts = NULL; 31955714Skris#undef BSIZE 32055714Skris#define BSIZE 256 32155714Skris MS_STATIC char buf[3][BSIZE]; 32259191Skris char *randfile=NULL; 323111147Snectar#ifndef OPENSSL_NO_ENGINE 324109998Smarkm char *engine = NULL; 325111147Snectar#endif 326109998Smarkm char *tofree=NULL; 327127128Snectar DB_ATTR db_attr; 32855714Skris 32955714Skris#ifdef EFENCE 33055714SkrisEF_PROTECT_FREE=1; 33155714SkrisEF_PROTECT_BELOW=1; 33255714SkrisEF_ALIGNMENT=0; 33355714Skris#endif 33455714Skris 33555714Skris apps_startup(); 33655714Skris 33759191Skris conf = NULL; 33859191Skris key = NULL; 33959191Skris section = NULL; 34055714Skris 34155714Skris preserve=0; 34259191Skris msie_hack=0; 34355714Skris if (bio_err == NULL) 34455714Skris if ((bio_err=BIO_new(BIO_s_file())) != NULL) 34555714Skris BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT); 34655714Skris 34755714Skris argc--; 34855714Skris argv++; 34955714Skris while (argc >= 1) 35055714Skris { 35155714Skris if (strcmp(*argv,"-verbose") == 0) 35255714Skris verbose=1; 35355714Skris else if (strcmp(*argv,"-config") == 0) 35455714Skris { 35555714Skris if (--argc < 1) goto bad; 35655714Skris configfile= *(++argv); 35755714Skris } 35855714Skris else if (strcmp(*argv,"-name") == 0) 35955714Skris { 36055714Skris if (--argc < 1) goto bad; 36155714Skris section= *(++argv); 36255714Skris } 363109998Smarkm else if (strcmp(*argv,"-subj") == 0) 364109998Smarkm { 365109998Smarkm if (--argc < 1) goto bad; 366109998Smarkm subj= *(++argv); 367109998Smarkm /* preserve=1; */ 368109998Smarkm } 369160814Ssimon else if (strcmp(*argv,"-utf8") == 0) 370160814Ssimon chtype = MBSTRING_UTF8; 371160814Ssimon else if (strcmp(*argv,"-create_serial") == 0) 372160814Ssimon create_ser = 1; 373160814Ssimon else if (strcmp(*argv,"-multivalue-rdn") == 0) 374160814Ssimon multirdn=1; 37555714Skris else if (strcmp(*argv,"-startdate") == 0) 37655714Skris { 37755714Skris if (--argc < 1) goto bad; 37855714Skris startdate= *(++argv); 37955714Skris } 38055714Skris else if (strcmp(*argv,"-enddate") == 0) 38155714Skris { 38255714Skris if (--argc < 1) goto bad; 38355714Skris enddate= *(++argv); 38455714Skris } 38555714Skris else if (strcmp(*argv,"-days") == 0) 38655714Skris { 38755714Skris if (--argc < 1) goto bad; 38855714Skris days=atoi(*(++argv)); 38955714Skris } 39055714Skris else if (strcmp(*argv,"-md") == 0) 39155714Skris { 39255714Skris if (--argc < 1) goto bad; 39355714Skris md= *(++argv); 39455714Skris } 39555714Skris else if (strcmp(*argv,"-policy") == 0) 39655714Skris { 39755714Skris if (--argc < 1) goto bad; 39855714Skris policy= *(++argv); 39955714Skris } 40055714Skris else if (strcmp(*argv,"-keyfile") == 0) 40155714Skris { 40255714Skris if (--argc < 1) goto bad; 40355714Skris keyfile= *(++argv); 40455714Skris } 405109998Smarkm else if (strcmp(*argv,"-keyform") == 0) 406109998Smarkm { 407109998Smarkm if (--argc < 1) goto bad; 408109998Smarkm keyform=str2fmt(*(++argv)); 409109998Smarkm } 41068651Skris else if (strcmp(*argv,"-passin") == 0) 41168651Skris { 41268651Skris if (--argc < 1) goto bad; 41368651Skris passargin= *(++argv); 41468651Skris } 41555714Skris else if (strcmp(*argv,"-key") == 0) 41655714Skris { 41755714Skris if (--argc < 1) goto bad; 41855714Skris key= *(++argv); 41955714Skris } 42055714Skris else if (strcmp(*argv,"-cert") == 0) 42155714Skris { 42255714Skris if (--argc < 1) goto bad; 42355714Skris certfile= *(++argv); 42455714Skris } 425160814Ssimon else if (strcmp(*argv,"-selfsign") == 0) 426160814Ssimon selfsign=1; 42755714Skris else if (strcmp(*argv,"-in") == 0) 42855714Skris { 42955714Skris if (--argc < 1) goto bad; 43055714Skris infile= *(++argv); 43155714Skris req=1; 43255714Skris } 43355714Skris else if (strcmp(*argv,"-out") == 0) 43455714Skris { 43555714Skris if (--argc < 1) goto bad; 43655714Skris outfile= *(++argv); 43755714Skris } 43855714Skris else if (strcmp(*argv,"-outdir") == 0) 43955714Skris { 44055714Skris if (--argc < 1) goto bad; 44155714Skris outdir= *(++argv); 44255714Skris } 443238405Sjkim else if (strcmp(*argv,"-sigopt") == 0) 444238405Sjkim { 445238405Sjkim if (--argc < 1) 446238405Sjkim goto bad; 447238405Sjkim if (!sigopts) 448238405Sjkim sigopts = sk_OPENSSL_STRING_new_null(); 449238405Sjkim if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv))) 450238405Sjkim goto bad; 451238405Sjkim } 45259191Skris else if (strcmp(*argv,"-notext") == 0) 45359191Skris notext=1; 45455714Skris else if (strcmp(*argv,"-batch") == 0) 45555714Skris batch=1; 45655714Skris else if (strcmp(*argv,"-preserveDN") == 0) 45755714Skris preserve=1; 458109998Smarkm else if (strcmp(*argv,"-noemailDN") == 0) 459109998Smarkm email_dn=0; 46055714Skris else if (strcmp(*argv,"-gencrl") == 0) 46155714Skris gencrl=1; 46255714Skris else if (strcmp(*argv,"-msie_hack") == 0) 46355714Skris msie_hack=1; 46455714Skris else if (strcmp(*argv,"-crldays") == 0) 46555714Skris { 46655714Skris if (--argc < 1) goto bad; 46755714Skris crldays= atol(*(++argv)); 46855714Skris } 46955714Skris else if (strcmp(*argv,"-crlhours") == 0) 47055714Skris { 47155714Skris if (--argc < 1) goto bad; 47255714Skris crlhours= atol(*(++argv)); 47355714Skris } 474238405Sjkim else if (strcmp(*argv,"-crlsec") == 0) 475238405Sjkim { 476238405Sjkim if (--argc < 1) goto bad; 477238405Sjkim crlsec = atol(*(++argv)); 478238405Sjkim } 47955714Skris else if (strcmp(*argv,"-infiles") == 0) 48055714Skris { 48155714Skris argc--; 48255714Skris argv++; 48355714Skris req=1; 48455714Skris break; 48555714Skris } 48655714Skris else if (strcmp(*argv, "-ss_cert") == 0) 48755714Skris { 48855714Skris if (--argc < 1) goto bad; 48955714Skris ss_cert_file = *(++argv); 49055714Skris req=1; 49155714Skris } 49255714Skris else if (strcmp(*argv, "-spkac") == 0) 49355714Skris { 49455714Skris if (--argc < 1) goto bad; 49555714Skris spkac_file = *(++argv); 49655714Skris req=1; 49755714Skris } 49855714Skris else if (strcmp(*argv,"-revoke") == 0) 49955714Skris { 50055714Skris if (--argc < 1) goto bad; 50155714Skris infile= *(++argv); 50255714Skris dorevoke=1; 50355714Skris } 50459191Skris else if (strcmp(*argv,"-extensions") == 0) 50559191Skris { 50659191Skris if (--argc < 1) goto bad; 50759191Skris extensions= *(++argv); 50859191Skris } 509109998Smarkm else if (strcmp(*argv,"-extfile") == 0) 510109998Smarkm { 511109998Smarkm if (--argc < 1) goto bad; 512109998Smarkm extfile= *(++argv); 513109998Smarkm } 514109998Smarkm else if (strcmp(*argv,"-status") == 0) 515109998Smarkm { 516109998Smarkm if (--argc < 1) goto bad; 517109998Smarkm ser_status= *(++argv); 518109998Smarkm } 519109998Smarkm else if (strcmp(*argv,"-updatedb") == 0) 520109998Smarkm { 521109998Smarkm doupdatedb=1; 522109998Smarkm } 52359191Skris else if (strcmp(*argv,"-crlexts") == 0) 52459191Skris { 52559191Skris if (--argc < 1) goto bad; 52659191Skris crl_ext= *(++argv); 52759191Skris } 528109998Smarkm else if (strcmp(*argv,"-crl_reason") == 0) 529109998Smarkm { 530109998Smarkm if (--argc < 1) goto bad; 531109998Smarkm rev_arg = *(++argv); 532109998Smarkm rev_type = REV_CRL_REASON; 533109998Smarkm } 534109998Smarkm else if (strcmp(*argv,"-crl_hold") == 0) 535109998Smarkm { 536109998Smarkm if (--argc < 1) goto bad; 537109998Smarkm rev_arg = *(++argv); 538109998Smarkm rev_type = REV_HOLD; 539109998Smarkm } 540109998Smarkm else if (strcmp(*argv,"-crl_compromise") == 0) 541109998Smarkm { 542109998Smarkm if (--argc < 1) goto bad; 543109998Smarkm rev_arg = *(++argv); 544109998Smarkm rev_type = REV_KEY_COMPROMISE; 545109998Smarkm } 546109998Smarkm else if (strcmp(*argv,"-crl_CA_compromise") == 0) 547109998Smarkm { 548109998Smarkm if (--argc < 1) goto bad; 549109998Smarkm rev_arg = *(++argv); 550109998Smarkm rev_type = REV_CA_COMPROMISE; 551109998Smarkm } 552111147Snectar#ifndef OPENSSL_NO_ENGINE 553109998Smarkm else if (strcmp(*argv,"-engine") == 0) 554109998Smarkm { 555109998Smarkm if (--argc < 1) goto bad; 556109998Smarkm engine= *(++argv); 557109998Smarkm } 558111147Snectar#endif 55955714Skris else 56055714Skris { 56155714Skrisbad: 56255714Skris BIO_printf(bio_err,"unknown option %s\n",*argv); 56355714Skris badops=1; 56455714Skris break; 56555714Skris } 56655714Skris argc--; 56755714Skris argv++; 56855714Skris } 56955714Skris 57055714Skris if (badops) 57155714Skris { 572238405Sjkim const char **pp2; 573238405Sjkim 574238405Sjkim for (pp2=ca_usage; (*pp2 != NULL); pp2++) 575238405Sjkim BIO_printf(bio_err,"%s",*pp2); 57655714Skris goto err; 57755714Skris } 57855714Skris 57955714Skris ERR_load_crypto_strings(); 58055714Skris 58155714Skris /*****************************************************************/ 582109998Smarkm tofree=NULL; 58355714Skris if (configfile == NULL) configfile = getenv("OPENSSL_CONF"); 58455714Skris if (configfile == NULL) configfile = getenv("SSLEAY_CONF"); 58555714Skris if (configfile == NULL) 58655714Skris { 587109998Smarkm const char *s=X509_get_default_cert_area(); 588127128Snectar size_t len; 589109998Smarkm 590109998Smarkm#ifdef OPENSSL_SYS_VMS 591127128Snectar len = strlen(s)+sizeof(CONFIG_FILE); 592127128Snectar tofree=OPENSSL_malloc(len); 593109998Smarkm strcpy(tofree,s); 59455714Skris#else 595127128Snectar len = strlen(s)+sizeof(CONFIG_FILE)+1; 596127128Snectar tofree=OPENSSL_malloc(len); 597127128Snectar BUF_strlcpy(tofree,s,len); 598127128Snectar BUF_strlcat(tofree,"/",len); 59955714Skris#endif 600127128Snectar BUF_strlcat(tofree,CONFIG_FILE,len); 601109998Smarkm configfile=tofree; 60255714Skris } 60355714Skris 60455714Skris BIO_printf(bio_err,"Using configuration from %s\n",configfile); 605109998Smarkm conf = NCONF_new(NULL); 606109998Smarkm if (NCONF_load(conf,configfile,&errorline) <= 0) 60755714Skris { 60855714Skris if (errorline <= 0) 60955714Skris BIO_printf(bio_err,"error loading the config file '%s'\n", 61055714Skris configfile); 61155714Skris else 61255714Skris BIO_printf(bio_err,"error on line %ld of config file '%s'\n" 61355714Skris ,errorline,configfile); 61455714Skris goto err; 61555714Skris } 616109998Smarkm if(tofree) 617111147Snectar { 618109998Smarkm OPENSSL_free(tofree); 619111147Snectar tofree = NULL; 620111147Snectar } 62155714Skris 622109998Smarkm if (!load_config(bio_err, conf)) 623109998Smarkm goto err; 624109998Smarkm 625142425Snectar#ifndef OPENSSL_NO_ENGINE 626142425Snectar e = setup_engine(bio_err, engine, 0); 627142425Snectar#endif 628142425Snectar 62955714Skris /* Lets get the config section we are using */ 63055714Skris if (section == NULL) 63155714Skris { 632109998Smarkm section=NCONF_get_string(conf,BASE_SECTION,ENV_DEFAULT_CA); 63355714Skris if (section == NULL) 63455714Skris { 63555714Skris lookup_fail(BASE_SECTION,ENV_DEFAULT_CA); 63655714Skris goto err; 63755714Skris } 63855714Skris } 63955714Skris 64055714Skris if (conf != NULL) 64155714Skris { 642109998Smarkm p=NCONF_get_string(conf,NULL,"oid_file"); 643109998Smarkm if (p == NULL) 644109998Smarkm ERR_clear_error(); 64555714Skris if (p != NULL) 64655714Skris { 64755714Skris BIO *oid_bio; 64855714Skris 64955714Skris oid_bio=BIO_new_file(p,"r"); 65055714Skris if (oid_bio == NULL) 65155714Skris { 65255714Skris /* 65355714Skris BIO_printf(bio_err,"problems opening %s for extra oid's\n",p); 65455714Skris ERR_print_errors(bio_err); 65555714Skris */ 65655714Skris ERR_clear_error(); 65755714Skris } 65855714Skris else 65955714Skris { 66055714Skris OBJ_create_objects(oid_bio); 66155714Skris BIO_free(oid_bio); 66255714Skris } 66355714Skris } 664109998Smarkm if (!add_oid_section(bio_err,conf)) 66559191Skris { 66655714Skris ERR_print_errors(bio_err); 66755714Skris goto err; 66859191Skris } 66955714Skris } 67055714Skris 671109998Smarkm randfile = NCONF_get_string(conf, BASE_SECTION, "RANDFILE"); 672109998Smarkm if (randfile == NULL) 673109998Smarkm ERR_clear_error(); 67459191Skris app_RAND_load_file(randfile, bio_err, 0); 675127128Snectar 676160814Ssimon f = NCONF_get_string(conf, section, STRING_MASK); 677160814Ssimon if (!f) 678160814Ssimon ERR_clear_error(); 679160814Ssimon 680160814Ssimon if(f && !ASN1_STRING_set_default_mask_asc(f)) { 681160814Ssimon BIO_printf(bio_err, "Invalid global string mask setting %s\n", f); 682160814Ssimon goto err; 683160814Ssimon } 684160814Ssimon 685160814Ssimon if (chtype != MBSTRING_UTF8){ 686160814Ssimon f = NCONF_get_string(conf, section, UTF8_IN); 687160814Ssimon if (!f) 688160814Ssimon ERR_clear_error(); 689160814Ssimon else if (!strcmp(f, "yes")) 690160814Ssimon chtype = MBSTRING_UTF8; 691160814Ssimon } 692160814Ssimon 693127128Snectar db_attr.unique_subject = 1; 694160814Ssimon p = NCONF_get_string(conf, section, ENV_UNIQUE_SUBJECT); 695127128Snectar if (p) 696127128Snectar { 697127128Snectar#ifdef RL_DEBUG 698127128Snectar BIO_printf(bio_err, "DEBUG: unique_subject = \"%s\"\n", p); 699127128Snectar#endif 700160814Ssimon db_attr.unique_subject = parse_yesno(p,1); 701127128Snectar } 702142425Snectar else 703142425Snectar ERR_clear_error(); 704127128Snectar#ifdef RL_DEBUG 705142425Snectar if (!p) 706279264Sdelphij BIO_printf(bio_err, "DEBUG: unique_subject undefined\n"); 707127128Snectar#endif 708127128Snectar#ifdef RL_DEBUG 709127128Snectar BIO_printf(bio_err, "DEBUG: configured unique_subject is %d\n", 710127128Snectar db_attr.unique_subject); 711127128Snectar#endif 71259191Skris 71355714Skris in=BIO_new(BIO_s_file()); 71455714Skris out=BIO_new(BIO_s_file()); 71555714Skris Sout=BIO_new(BIO_s_file()); 71655714Skris Cout=BIO_new(BIO_s_file()); 71755714Skris if ((in == NULL) || (out == NULL) || (Sout == NULL) || (Cout == NULL)) 71855714Skris { 71955714Skris ERR_print_errors(bio_err); 72055714Skris goto err; 72155714Skris } 72255714Skris 72355714Skris /*****************************************************************/ 724109998Smarkm /* report status of cert with serial number given on command line */ 725109998Smarkm if (ser_status) 726109998Smarkm { 727109998Smarkm if ((dbfile=NCONF_get_string(conf,section,ENV_DATABASE)) == NULL) 728109998Smarkm { 729109998Smarkm lookup_fail(section,ENV_DATABASE); 730109998Smarkm goto err; 731109998Smarkm } 732127128Snectar db = load_index(dbfile,&db_attr); 733109998Smarkm if (db == NULL) goto err; 73455714Skris 735127128Snectar if (!index_index(db)) goto err; 736109998Smarkm 737109998Smarkm if (get_certificate_status(ser_status,db) != 1) 738109998Smarkm BIO_printf(bio_err,"Error verifying serial %s!\n", 739109998Smarkm ser_status); 740109998Smarkm goto err; 741109998Smarkm } 742109998Smarkm 743109998Smarkm /*****************************************************************/ 744160814Ssimon /* we definitely need a private key, so let's get it */ 745109998Smarkm 746109998Smarkm if ((keyfile == NULL) && ((keyfile=NCONF_get_string(conf, 74755714Skris section,ENV_PRIVATE_KEY)) == NULL)) 74855714Skris { 74955714Skris lookup_fail(section,ENV_PRIVATE_KEY); 75055714Skris goto err; 75155714Skris } 752109998Smarkm if (!key) 75368651Skris { 754109998Smarkm free_key = 1; 755109998Smarkm if (!app_passwd(bio_err, passargin, NULL, &key, NULL)) 756109998Smarkm { 757109998Smarkm BIO_printf(bio_err,"Error getting password\n"); 758109998Smarkm goto err; 759109998Smarkm } 76068651Skris } 761109998Smarkm pkey = load_key(bio_err, keyfile, keyform, 0, key, e, 762109998Smarkm "CA private key"); 763109998Smarkm if (key) OPENSSL_cleanse(key,strlen(key)); 76455714Skris if (pkey == NULL) 76555714Skris { 766109998Smarkm /* load_key() has already printed an appropriate message */ 76755714Skris goto err; 76855714Skris } 76955714Skris 77055714Skris /*****************************************************************/ 77155714Skris /* we need a certificate */ 772160814Ssimon if (!selfsign || spkac_file || ss_cert_file || gencrl) 77355714Skris { 774160814Ssimon if ((certfile == NULL) 775160814Ssimon && ((certfile=NCONF_get_string(conf, 776160814Ssimon section,ENV_CERTIFICATE)) == NULL)) 777160814Ssimon { 778160814Ssimon lookup_fail(section,ENV_CERTIFICATE); 779160814Ssimon goto err; 780160814Ssimon } 781160814Ssimon x509=load_cert(bio_err, certfile, FORMAT_PEM, NULL, e, 782160814Ssimon "CA certificate"); 783160814Ssimon if (x509 == NULL) 784160814Ssimon goto err; 78555714Skris 786160814Ssimon if (!X509_check_private_key(x509,pkey)) 787160814Ssimon { 788160814Ssimon BIO_printf(bio_err,"CA certificate and CA private key do not match\n"); 789160814Ssimon goto err; 790160814Ssimon } 79155714Skris } 792160814Ssimon if (!selfsign) x509p = x509; 79355714Skris 794109998Smarkm f=NCONF_get_string(conf,BASE_SECTION,ENV_PRESERVE); 795109998Smarkm if (f == NULL) 796109998Smarkm ERR_clear_error(); 79755714Skris if ((f != NULL) && ((*f == 'y') || (*f == 'Y'))) 79855714Skris preserve=1; 799109998Smarkm f=NCONF_get_string(conf,BASE_SECTION,ENV_MSIE_HACK); 800109998Smarkm if (f == NULL) 801109998Smarkm ERR_clear_error(); 80255714Skris if ((f != NULL) && ((*f == 'y') || (*f == 'Y'))) 80355714Skris msie_hack=1; 80455714Skris 805109998Smarkm f=NCONF_get_string(conf,section,ENV_NAMEOPT); 806109998Smarkm 807109998Smarkm if (f) 808109998Smarkm { 809109998Smarkm if (!set_name_ex(&nameopt, f)) 810109998Smarkm { 811109998Smarkm BIO_printf(bio_err, "Invalid name options: \"%s\"\n", f); 812109998Smarkm goto err; 813109998Smarkm } 814109998Smarkm default_op = 0; 815109998Smarkm } 816109998Smarkm else 817109998Smarkm ERR_clear_error(); 818109998Smarkm 819109998Smarkm f=NCONF_get_string(conf,section,ENV_CERTOPT); 820109998Smarkm 821109998Smarkm if (f) 822109998Smarkm { 823109998Smarkm if (!set_cert_ex(&certopt, f)) 824109998Smarkm { 825109998Smarkm BIO_printf(bio_err, "Invalid certificate options: \"%s\"\n", f); 826109998Smarkm goto err; 827109998Smarkm } 828109998Smarkm default_op = 0; 829109998Smarkm } 830109998Smarkm else 831109998Smarkm ERR_clear_error(); 832109998Smarkm 833109998Smarkm f=NCONF_get_string(conf,section,ENV_EXTCOPY); 834109998Smarkm 835109998Smarkm if (f) 836109998Smarkm { 837109998Smarkm if (!set_ext_copy(&ext_copy, f)) 838109998Smarkm { 839109998Smarkm BIO_printf(bio_err, "Invalid extension copy option: \"%s\"\n", f); 840109998Smarkm goto err; 841109998Smarkm } 842109998Smarkm } 843109998Smarkm else 844109998Smarkm ERR_clear_error(); 845109998Smarkm 84655714Skris /*****************************************************************/ 84755714Skris /* lookup where to write new certificates */ 84855714Skris if ((outdir == NULL) && (req)) 84955714Skris { 85055714Skris 851109998Smarkm if ((outdir=NCONF_get_string(conf,section,ENV_NEW_CERTS_DIR)) 85255714Skris == NULL) 85355714Skris { 85455714Skris BIO_printf(bio_err,"there needs to be defined a directory for new certificate to be placed in\n"); 85555714Skris goto err; 85655714Skris } 857109998Smarkm#ifndef OPENSSL_SYS_VMS 858109998Smarkm /* outdir is a directory spec, but access() for VMS demands a 85959191Skris filename. In any case, stat(), below, will catch the problem 86059191Skris if outdir is not a directory spec, and the fopen() or open() 86159191Skris will catch an error if there is no write access. 86259191Skris 86359191Skris Presumably, this problem could also be solved by using the DEC 86459191Skris C routines to convert the directory syntax to Unixly, and give 86559191Skris that to access(). However, time's too short to do that just 86659191Skris now. 867109998Smarkm */ 868238405Sjkim#ifndef _WIN32 86955714Skris if (access(outdir,R_OK|W_OK|X_OK) != 0) 870238405Sjkim#else 871238405Sjkim if (_access(outdir,R_OK|W_OK|X_OK) != 0) 872238405Sjkim#endif 87355714Skris { 87459191Skris BIO_printf(bio_err,"I am unable to access the %s directory\n",outdir); 87555714Skris perror(outdir); 87655714Skris goto err; 87755714Skris } 87855714Skris 879238405Sjkim if (app_isdir(outdir)<=0) 88055714Skris { 88155714Skris BIO_printf(bio_err,"%s need to be a directory\n",outdir); 88255714Skris perror(outdir); 88355714Skris goto err; 88455714Skris } 88559191Skris#endif 88655714Skris } 88755714Skris 88855714Skris /*****************************************************************/ 88955714Skris /* we need to load the database file */ 890109998Smarkm if ((dbfile=NCONF_get_string(conf,section,ENV_DATABASE)) == NULL) 89155714Skris { 89255714Skris lookup_fail(section,ENV_DATABASE); 89355714Skris goto err; 89455714Skris } 895127128Snectar db = load_index(dbfile, &db_attr); 89655714Skris if (db == NULL) goto err; 89755714Skris 89855714Skris /* Lets check some fields */ 899238405Sjkim for (i=0; i<sk_OPENSSL_PSTRING_num(db->db->data); i++) 90055714Skris { 901238405Sjkim pp=sk_OPENSSL_PSTRING_value(db->db->data,i); 90255714Skris if ((pp[DB_type][0] != DB_TYPE_REV) && 90355714Skris (pp[DB_rev_date][0] != '\0')) 90455714Skris { 90555714Skris BIO_printf(bio_err,"entry %d: not revoked yet, but has a revocation date\n",i+1); 90655714Skris goto err; 90755714Skris } 90855714Skris if ((pp[DB_type][0] == DB_TYPE_REV) && 909109998Smarkm !make_revoked(NULL, pp[DB_rev_date])) 91055714Skris { 911109998Smarkm BIO_printf(bio_err," in entry %d\n", i+1); 91255714Skris goto err; 91355714Skris } 914238405Sjkim if (!check_time_format((char *)pp[DB_exp_date])) 91555714Skris { 91655714Skris BIO_printf(bio_err,"entry %d: invalid expiry date\n",i+1); 91755714Skris goto err; 91855714Skris } 91955714Skris p=pp[DB_serial]; 92055714Skris j=strlen(p); 921109998Smarkm if (*p == '-') 922109998Smarkm { 923109998Smarkm p++; 924109998Smarkm j--; 925109998Smarkm } 92655714Skris if ((j&1) || (j < 2)) 92755714Skris { 92855714Skris BIO_printf(bio_err,"entry %d: bad serial number length (%d)\n",i+1,j); 92955714Skris goto err; 93055714Skris } 93155714Skris while (*p) 93255714Skris { 93355714Skris if (!( ((*p >= '0') && (*p <= '9')) || 93455714Skris ((*p >= 'A') && (*p <= 'F')) || 93555714Skris ((*p >= 'a') && (*p <= 'f'))) ) 93655714Skris { 93755714Skris BIO_printf(bio_err,"entry %d: bad serial number characters, char pos %ld, char is '%c'\n",i+1,(long)(p-pp[DB_serial]),*p); 93855714Skris goto err; 93955714Skris } 94055714Skris p++; 94155714Skris } 94255714Skris } 94355714Skris if (verbose) 94455714Skris { 94555714Skris BIO_set_fp(out,stdout,BIO_NOCLOSE|BIO_FP_TEXT); /* cannot fail */ 946109998Smarkm#ifdef OPENSSL_SYS_VMS 94768651Skris { 94868651Skris BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 94968651Skris out = BIO_push(tmpbio, out); 95068651Skris } 95168651Skris#endif 952127128Snectar TXT_DB_write(out,db->db); 95355714Skris BIO_printf(bio_err,"%d entries loaded from the database\n", 954238405Sjkim sk_OPENSSL_PSTRING_num(db->db->data)); 95559191Skris BIO_printf(bio_err,"generating index\n"); 95655714Skris } 95755714Skris 958127128Snectar if (!index_index(db)) goto err; 95955714Skris 96055714Skris /*****************************************************************/ 961109998Smarkm /* Update the db file for expired certificates */ 962109998Smarkm if (doupdatedb) 963109998Smarkm { 964109998Smarkm if (verbose) 965109998Smarkm BIO_printf(bio_err, "Updating %s ...\n", 966109998Smarkm dbfile); 967109998Smarkm 968109998Smarkm i = do_updatedb(db); 969109998Smarkm if (i == -1) 970109998Smarkm { 971109998Smarkm BIO_printf(bio_err,"Malloc failure\n"); 972109998Smarkm goto err; 973109998Smarkm } 974109998Smarkm else if (i == 0) 975109998Smarkm { 976109998Smarkm if (verbose) BIO_printf(bio_err, 977109998Smarkm "No entries found to mark expired\n"); 978109998Smarkm } 979109998Smarkm else 980109998Smarkm { 981127128Snectar if (!save_index(dbfile,"new",db)) goto err; 982109998Smarkm 983127128Snectar if (!rotate_index(dbfile,"new","old")) goto err; 984127128Snectar 985109998Smarkm if (verbose) BIO_printf(bio_err, 986109998Smarkm "Done. %d entries marked as expired\n",i); 987109998Smarkm } 988109998Smarkm } 989109998Smarkm 990109998Smarkm /*****************************************************************/ 991109998Smarkm /* Read extentions config file */ 992109998Smarkm if (extfile) 993109998Smarkm { 994109998Smarkm extconf = NCONF_new(NULL); 995109998Smarkm if (NCONF_load(extconf,extfile,&errorline) <= 0) 996109998Smarkm { 997109998Smarkm if (errorline <= 0) 998109998Smarkm BIO_printf(bio_err, "ERROR: loading the config file '%s'\n", 999109998Smarkm extfile); 1000109998Smarkm else 1001109998Smarkm BIO_printf(bio_err, "ERROR: on line %ld of config file '%s'\n", 1002109998Smarkm errorline,extfile); 1003109998Smarkm ret = 1; 1004109998Smarkm goto err; 1005109998Smarkm } 1006109998Smarkm 1007109998Smarkm if (verbose) 1008109998Smarkm BIO_printf(bio_err, "Successfully loaded extensions file %s\n", extfile); 1009109998Smarkm 1010109998Smarkm /* We can have sections in the ext file */ 1011109998Smarkm if (!extensions && !(extensions = NCONF_get_string(extconf, "default", "extensions"))) 1012109998Smarkm extensions = "default"; 1013109998Smarkm } 1014109998Smarkm 1015109998Smarkm /*****************************************************************/ 101655714Skris if (req || gencrl) 101755714Skris { 101855714Skris if (outfile != NULL) 101955714Skris { 102055714Skris if (BIO_write_filename(Sout,outfile) <= 0) 102155714Skris { 102255714Skris perror(outfile); 102355714Skris goto err; 102455714Skris } 102555714Skris } 102655714Skris else 102768651Skris { 102855714Skris BIO_set_fp(Sout,stdout,BIO_NOCLOSE|BIO_FP_TEXT); 1029109998Smarkm#ifdef OPENSSL_SYS_VMS 103068651Skris { 103168651Skris BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 103268651Skris Sout = BIO_push(tmpbio, Sout); 103368651Skris } 103468651Skris#endif 103568651Skris } 103655714Skris } 103755714Skris 1038160814Ssimon if ((md == NULL) && ((md=NCONF_get_string(conf, 1039160814Ssimon section,ENV_DEFAULT_MD)) == NULL)) 1040160814Ssimon { 1041160814Ssimon lookup_fail(section,ENV_DEFAULT_MD); 1042160814Ssimon goto err; 1043160814Ssimon } 1044160814Ssimon 1045238405Sjkim if (!strcmp(md, "default")) 1046238405Sjkim { 1047238405Sjkim int def_nid; 1048238405Sjkim if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) <= 0) 1049238405Sjkim { 1050238405Sjkim BIO_puts(bio_err,"no default digest\n"); 1051238405Sjkim goto err; 1052238405Sjkim } 1053238405Sjkim md = (char *)OBJ_nid2sn(def_nid); 1054238405Sjkim } 1055238405Sjkim 1056160814Ssimon if ((dgst=EVP_get_digestbyname(md)) == NULL) 1057160814Ssimon { 1058160814Ssimon BIO_printf(bio_err,"%s is an unsupported message digest type\n",md); 1059160814Ssimon goto err; 1060160814Ssimon } 1061160814Ssimon 106255714Skris if (req) 106355714Skris { 1064109998Smarkm if ((email_dn == 1) && ((tmp_email_dn=NCONF_get_string(conf, 1065109998Smarkm section,ENV_DEFAULT_EMAIL_DN)) != NULL )) 1066109998Smarkm { 1067109998Smarkm if(strcmp(tmp_email_dn,"no") == 0) 1068109998Smarkm email_dn=0; 1069109998Smarkm } 107055714Skris if (verbose) 107155714Skris BIO_printf(bio_err,"message digest is %s\n", 107255714Skris OBJ_nid2ln(dgst->type)); 1073109998Smarkm if ((policy == NULL) && ((policy=NCONF_get_string(conf, 107455714Skris section,ENV_POLICY)) == NULL)) 107555714Skris { 107655714Skris lookup_fail(section,ENV_POLICY); 107755714Skris goto err; 107855714Skris } 107955714Skris if (verbose) 108055714Skris BIO_printf(bio_err,"policy is %s\n",policy); 108155714Skris 1082109998Smarkm if ((serialfile=NCONF_get_string(conf,section,ENV_SERIAL)) 108355714Skris == NULL) 108455714Skris { 108555714Skris lookup_fail(section,ENV_SERIAL); 108655714Skris goto err; 108755714Skris } 1088109998Smarkm 1089109998Smarkm if (!extconf) 1090109998Smarkm { 1091109998Smarkm /* no '-extfile' option, so we look for extensions 1092109998Smarkm * in the main configuration file */ 1093109998Smarkm if (!extensions) 1094109998Smarkm { 1095109998Smarkm extensions=NCONF_get_string(conf,section, 1096109998Smarkm ENV_EXTENSIONS); 1097109998Smarkm if (!extensions) 1098109998Smarkm ERR_clear_error(); 1099109998Smarkm } 1100109998Smarkm if (extensions) 1101109998Smarkm { 1102109998Smarkm /* Check syntax of file */ 1103109998Smarkm X509V3_CTX ctx; 1104109998Smarkm X509V3_set_ctx_test(&ctx); 1105109998Smarkm X509V3_set_nconf(&ctx, conf); 1106109998Smarkm if (!X509V3_EXT_add_nconf(conf, &ctx, extensions, 1107109998Smarkm NULL)) 1108109998Smarkm { 1109109998Smarkm BIO_printf(bio_err, 1110109998Smarkm "Error Loading extension section %s\n", 111155714Skris extensions); 1112109998Smarkm ret = 1; 1113109998Smarkm goto err; 1114109998Smarkm } 1115109998Smarkm } 111655714Skris } 111755714Skris 111855714Skris if (startdate == NULL) 111955714Skris { 1120109998Smarkm startdate=NCONF_get_string(conf,section, 112155714Skris ENV_DEFAULT_STARTDATE); 1122109998Smarkm if (startdate == NULL) 1123109998Smarkm ERR_clear_error(); 112455714Skris } 1125238405Sjkim if (startdate && !ASN1_TIME_set_string(NULL, startdate)) 112655714Skris { 1127238405Sjkim BIO_printf(bio_err,"start date is invalid, it should be YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ\n"); 112855714Skris goto err; 112955714Skris } 113055714Skris if (startdate == NULL) startdate="today"; 113155714Skris 113255714Skris if (enddate == NULL) 113355714Skris { 1134109998Smarkm enddate=NCONF_get_string(conf,section, 113555714Skris ENV_DEFAULT_ENDDATE); 1136109998Smarkm if (enddate == NULL) 1137109998Smarkm ERR_clear_error(); 113855714Skris } 1139238405Sjkim if (enddate && !ASN1_TIME_set_string(NULL, enddate)) 114055714Skris { 1141238405Sjkim BIO_printf(bio_err,"end date is invalid, it should be YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ\n"); 114255714Skris goto err; 114355714Skris } 114455714Skris 114555714Skris if (days == 0) 114655714Skris { 1147109998Smarkm if(!NCONF_get_number(conf,section, ENV_DEFAULT_DAYS, &days)) 1148109998Smarkm days = 0; 114955714Skris } 115055714Skris if (!enddate && (days == 0)) 115155714Skris { 115255714Skris BIO_printf(bio_err,"cannot lookup how many days to certify for\n"); 115355714Skris goto err; 115455714Skris } 115555714Skris 1156142425Snectar if ((serial=load_serial(serialfile, create_ser, NULL)) == NULL) 115755714Skris { 115855714Skris BIO_printf(bio_err,"error while loading serial number\n"); 115955714Skris goto err; 116055714Skris } 116155714Skris if (verbose) 116255714Skris { 1163109998Smarkm if (BN_is_zero(serial)) 1164109998Smarkm BIO_printf(bio_err,"next serial number is 00\n"); 1165109998Smarkm else 1166109998Smarkm { 1167109998Smarkm if ((f=BN_bn2hex(serial)) == NULL) goto err; 1168109998Smarkm BIO_printf(bio_err,"next serial number is %s\n",f); 1169109998Smarkm OPENSSL_free(f); 1170109998Smarkm } 117155714Skris } 117255714Skris 1173109998Smarkm if ((attribs=NCONF_get_section(conf,policy)) == NULL) 117455714Skris { 117555714Skris BIO_printf(bio_err,"unable to find 'section' for %s\n",policy); 117655714Skris goto err; 117755714Skris } 117855714Skris 117968651Skris if ((cert_sk=sk_X509_new_null()) == NULL) 118055714Skris { 118168651Skris BIO_printf(bio_err,"Memory allocation failure\n"); 118255714Skris goto err; 118355714Skris } 118455714Skris if (spkac_file != NULL) 118555714Skris { 118655714Skris total++; 1187238405Sjkim j=certify_spkac(&x,spkac_file,pkey,x509,dgst,sigopts, 1188238405Sjkim attribs,db, serial,subj,chtype,multirdn, 1189238405Sjkim email_dn,startdate,enddate,days,extensions, 1190109998Smarkm conf,verbose,certopt,nameopt,default_op,ext_copy); 119155714Skris if (j < 0) goto err; 119255714Skris if (j > 0) 119355714Skris { 119455714Skris total_done++; 119555714Skris BIO_printf(bio_err,"\n"); 119655714Skris if (!BN_add_word(serial,1)) goto err; 119768651Skris if (!sk_X509_push(cert_sk,x)) 119855714Skris { 119968651Skris BIO_printf(bio_err,"Memory allocation failure\n"); 120055714Skris goto err; 120155714Skris } 120255714Skris if (outfile) 120355714Skris { 120455714Skris output_der = 1; 120555714Skris batch = 1; 120655714Skris } 120755714Skris } 120855714Skris } 120955714Skris if (ss_cert_file != NULL) 121055714Skris { 121155714Skris total++; 1212238405Sjkim j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,sigopts, 1213238405Sjkim attribs, 1214160814Ssimon db,serial,subj,chtype,multirdn,email_dn,startdate,enddate,days,batch, 1215109998Smarkm extensions,conf,verbose, certopt, nameopt, 1216109998Smarkm default_op, ext_copy, e); 121755714Skris if (j < 0) goto err; 121855714Skris if (j > 0) 121955714Skris { 122055714Skris total_done++; 122155714Skris BIO_printf(bio_err,"\n"); 122255714Skris if (!BN_add_word(serial,1)) goto err; 122368651Skris if (!sk_X509_push(cert_sk,x)) 122455714Skris { 122568651Skris BIO_printf(bio_err,"Memory allocation failure\n"); 122655714Skris goto err; 122755714Skris } 122855714Skris } 122955714Skris } 123055714Skris if (infile != NULL) 123155714Skris { 123255714Skris total++; 1233238405Sjkim j=certify(&x,infile,pkey,x509p,dgst,sigopts, attribs,db, 1234160814Ssimon serial,subj,chtype,multirdn,email_dn,startdate,enddate,days,batch, 1235109998Smarkm extensions,conf,verbose, certopt, nameopt, 1236160814Ssimon default_op, ext_copy, selfsign); 123755714Skris if (j < 0) goto err; 123855714Skris if (j > 0) 123955714Skris { 124055714Skris total_done++; 124155714Skris BIO_printf(bio_err,"\n"); 124255714Skris if (!BN_add_word(serial,1)) goto err; 124368651Skris if (!sk_X509_push(cert_sk,x)) 124455714Skris { 124568651Skris BIO_printf(bio_err,"Memory allocation failure\n"); 124655714Skris goto err; 124755714Skris } 124855714Skris } 124955714Skris } 125055714Skris for (i=0; i<argc; i++) 125155714Skris { 125255714Skris total++; 1253238405Sjkim j=certify(&x,argv[i],pkey,x509p,dgst,sigopts,attribs,db, 1254160814Ssimon serial,subj,chtype,multirdn,email_dn,startdate,enddate,days,batch, 1255109998Smarkm extensions,conf,verbose, certopt, nameopt, 1256160814Ssimon default_op, ext_copy, selfsign); 125755714Skris if (j < 0) goto err; 125855714Skris if (j > 0) 125955714Skris { 126055714Skris total_done++; 126155714Skris BIO_printf(bio_err,"\n"); 126255714Skris if (!BN_add_word(serial,1)) goto err; 126368651Skris if (!sk_X509_push(cert_sk,x)) 126455714Skris { 126568651Skris BIO_printf(bio_err,"Memory allocation failure\n"); 126655714Skris goto err; 126755714Skris } 126855714Skris } 126955714Skris } 127055714Skris /* we have a stack of newly certified certificates 127155714Skris * and a data base and serial number that need 127255714Skris * updating */ 127355714Skris 127468651Skris if (sk_X509_num(cert_sk) > 0) 127555714Skris { 127655714Skris if (!batch) 127755714Skris { 127855714Skris BIO_printf(bio_err,"\n%d out of %d certificate requests certified, commit? [y/n]",total_done,total); 127955714Skris (void)BIO_flush(bio_err); 128055714Skris buf[0][0]='\0'; 1281205128Ssimon if (!fgets(buf[0],10,stdin)) 1282205128Ssimon { 1283205128Ssimon BIO_printf(bio_err,"CERTIFICATION CANCELED: I/O error\n"); 1284205128Ssimon ret=0; 1285205128Ssimon goto err; 1286205128Ssimon } 128755714Skris if ((buf[0][0] != 'y') && (buf[0][0] != 'Y')) 128855714Skris { 128955714Skris BIO_printf(bio_err,"CERTIFICATION CANCELED\n"); 129055714Skris ret=0; 129155714Skris goto err; 129255714Skris } 129355714Skris } 129455714Skris 129568651Skris BIO_printf(bio_err,"Write out database with %d new entries\n",sk_X509_num(cert_sk)); 129655714Skris 1297127128Snectar if (!save_serial(serialfile,"new",serial,NULL)) goto err; 129855714Skris 1299127128Snectar if (!save_index(dbfile, "new", db)) goto err; 130055714Skris } 130155714Skris 130255714Skris if (verbose) 130355714Skris BIO_printf(bio_err,"writing new certificates\n"); 130468651Skris for (i=0; i<sk_X509_num(cert_sk); i++) 130555714Skris { 130655714Skris int k; 1307127128Snectar char *n; 130855714Skris 130968651Skris x=sk_X509_value(cert_sk,i); 131055714Skris 131155714Skris j=x->cert_info->serialNumber->length; 1312160814Ssimon p=(const char *)x->cert_info->serialNumber->data; 131355714Skris 1314109998Smarkm if(strlen(outdir) >= (size_t)(j ? BSIZE-j*2-6 : BSIZE-8)) 1315109998Smarkm { 1316109998Smarkm BIO_printf(bio_err,"certificate file name too long\n"); 1317109998Smarkm goto err; 1318109998Smarkm } 131955714Skris 1320109998Smarkm strcpy(buf[2],outdir); 1321109998Smarkm 1322109998Smarkm#ifndef OPENSSL_SYS_VMS 1323127128Snectar BUF_strlcat(buf[2],"/",sizeof(buf[2])); 132455714Skris#endif 132555714Skris 1326127128Snectar n=(char *)&(buf[2][strlen(buf[2])]); 132755714Skris if (j > 0) 132855714Skris { 132955714Skris for (k=0; k<j; k++) 133055714Skris { 1331127128Snectar if (n >= &(buf[2][sizeof(buf[2])])) 1332127128Snectar break; 1333127128Snectar BIO_snprintf(n, 1334127128Snectar &buf[2][0] + sizeof(buf[2]) - n, 1335127128Snectar "%02X",(unsigned char)*(p++)); 133655714Skris n+=2; 133755714Skris } 133855714Skris } 133955714Skris else 134055714Skris { 134155714Skris *(n++)='0'; 134255714Skris *(n++)='0'; 134355714Skris } 134455714Skris *(n++)='.'; *(n++)='p'; *(n++)='e'; *(n++)='m'; 134555714Skris *n='\0'; 134655714Skris if (verbose) 134755714Skris BIO_printf(bio_err,"writing %s\n",buf[2]); 134855714Skris 134955714Skris if (BIO_write_filename(Cout,buf[2]) <= 0) 135055714Skris { 135155714Skris perror(buf[2]); 135255714Skris goto err; 135355714Skris } 135459191Skris write_new_certificate(Cout,x, 0, notext); 135559191Skris write_new_certificate(Sout,x, output_der, notext); 135655714Skris } 135755714Skris 135868651Skris if (sk_X509_num(cert_sk)) 135955714Skris { 136055714Skris /* Rename the database and the serial file */ 1361127128Snectar if (!rotate_serial(serialfile,"new","old")) goto err; 136255714Skris 1363127128Snectar if (!rotate_index(dbfile,"new","old")) goto err; 136455714Skris 136555714Skris BIO_printf(bio_err,"Data Base Updated\n"); 136655714Skris } 136755714Skris } 136855714Skris 136955714Skris /*****************************************************************/ 137055714Skris if (gencrl) 137155714Skris { 1372109998Smarkm int crl_v2 = 0; 1373109998Smarkm if (!crl_ext) 1374109998Smarkm { 1375109998Smarkm crl_ext=NCONF_get_string(conf,section,ENV_CRLEXT); 1376109998Smarkm if (!crl_ext) 1377109998Smarkm ERR_clear_error(); 1378109998Smarkm } 1379109998Smarkm if (crl_ext) 1380109998Smarkm { 138155714Skris /* Check syntax of file */ 138255714Skris X509V3_CTX ctx; 138355714Skris X509V3_set_ctx_test(&ctx); 1384109998Smarkm X509V3_set_nconf(&ctx, conf); 1385109998Smarkm if (!X509V3_EXT_add_nconf(conf, &ctx, crl_ext, NULL)) 1386109998Smarkm { 138755714Skris BIO_printf(bio_err, 138855714Skris "Error Loading CRL extension section %s\n", 138955714Skris crl_ext); 139055714Skris ret = 1; 139155714Skris goto err; 1392109998Smarkm } 139355714Skris } 139455714Skris 1395127128Snectar if ((crlnumberfile=NCONF_get_string(conf,section,ENV_CRLNUMBER)) 1396127128Snectar != NULL) 1397127128Snectar if ((crlnumber=load_serial(crlnumberfile,0,NULL)) == NULL) 1398127128Snectar { 1399127128Snectar BIO_printf(bio_err,"error while loading CRL number\n"); 1400127128Snectar goto err; 1401127128Snectar } 1402127128Snectar 1403238405Sjkim if (!crldays && !crlhours && !crlsec) 140455714Skris { 1405109998Smarkm if (!NCONF_get_number(conf,section, 1406109998Smarkm ENV_DEFAULT_CRL_DAYS, &crldays)) 1407109998Smarkm crldays = 0; 1408109998Smarkm if (!NCONF_get_number(conf,section, 1409109998Smarkm ENV_DEFAULT_CRL_HOURS, &crlhours)) 1410109998Smarkm crlhours = 0; 1411246772Sjkim ERR_clear_error(); 141255714Skris } 1413238405Sjkim if ((crldays == 0) && (crlhours == 0) && (crlsec == 0)) 141455714Skris { 1415100936Snectar BIO_printf(bio_err,"cannot lookup how long until the next CRL is issued\n"); 141655714Skris goto err; 141755714Skris } 141855714Skris 141955714Skris if (verbose) BIO_printf(bio_err,"making CRL\n"); 142055714Skris if ((crl=X509_CRL_new()) == NULL) goto err; 1421109998Smarkm if (!X509_CRL_set_issuer_name(crl, X509_get_subject_name(x509))) goto err; 142255714Skris 1423109998Smarkm tmptm = ASN1_TIME_new(); 1424109998Smarkm if (!tmptm) goto err; 1425109998Smarkm X509_gmtime_adj(tmptm,0); 1426109998Smarkm X509_CRL_set_lastUpdate(crl, tmptm); 1427238405Sjkim if (!X509_time_adj_ex(tmptm, crldays, crlhours*60*60 + crlsec, 1428238405Sjkim NULL)) 1429238405Sjkim { 1430238405Sjkim BIO_puts(bio_err, "error setting CRL nextUpdate\n"); 1431238405Sjkim goto err; 1432238405Sjkim } 1433109998Smarkm X509_CRL_set_nextUpdate(crl, tmptm); 143455714Skris 1435109998Smarkm ASN1_TIME_free(tmptm); 1436109998Smarkm 1437238405Sjkim for (i=0; i<sk_OPENSSL_PSTRING_num(db->db->data); i++) 143855714Skris { 1439238405Sjkim pp=sk_OPENSSL_PSTRING_value(db->db->data,i); 144055714Skris if (pp[DB_type][0] == DB_TYPE_REV) 144155714Skris { 144255714Skris if ((r=X509_REVOKED_new()) == NULL) goto err; 1443109998Smarkm j = make_revoked(r, pp[DB_rev_date]); 1444109998Smarkm if (!j) goto err; 1445109998Smarkm if (j == 2) crl_v2 = 1; 1446109998Smarkm if (!BN_hex2bn(&serial, pp[DB_serial])) 144755714Skris goto err; 1448109998Smarkm tmpser = BN_to_ASN1_INTEGER(serial, NULL); 1449109998Smarkm BN_free(serial); 1450109998Smarkm serial = NULL; 1451109998Smarkm if (!tmpser) 1452109998Smarkm goto err; 1453109998Smarkm X509_REVOKED_set_serialNumber(r, tmpser); 1454109998Smarkm ASN1_INTEGER_free(tmpser); 1455109998Smarkm X509_CRL_add0_revoked(crl,r); 145655714Skris } 145755714Skris } 1458109998Smarkm 145955714Skris /* sort the data so it will be written in serial 146055714Skris * number order */ 1461109998Smarkm X509_CRL_sort(crl); 146255714Skris 146355714Skris /* we now have a CRL */ 146455714Skris if (verbose) BIO_printf(bio_err,"signing CRL\n"); 146555714Skris 146655714Skris /* Add any extensions asked for */ 146755714Skris 1468127128Snectar if (crl_ext || crlnumberfile != NULL) 1469109998Smarkm { 1470109998Smarkm X509V3_CTX crlctx; 1471109998Smarkm X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0); 1472109998Smarkm X509V3_set_nconf(&crlctx, conf); 147355714Skris 1474127128Snectar if (crl_ext) 1475127128Snectar if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx, 1476127128Snectar crl_ext, crl)) goto err; 1477127128Snectar if (crlnumberfile != NULL) 1478127128Snectar { 1479127128Snectar tmpser = BN_to_ASN1_INTEGER(crlnumber, NULL); 1480127128Snectar if (!tmpser) goto err; 1481127128Snectar X509_CRL_add1_ext_i2d(crl,NID_crl_number,tmpser,0,0); 1482127128Snectar ASN1_INTEGER_free(tmpser); 1483127128Snectar crl_v2 = 1; 1484127128Snectar if (!BN_add_word(crlnumber,1)) goto err; 1485127128Snectar } 1486109998Smarkm } 1487109998Smarkm if (crl_ext || crl_v2) 1488109998Smarkm { 1489109998Smarkm if (!X509_CRL_set_version(crl, 1)) 1490109998Smarkm goto err; /* version 2 CRL */ 1491109998Smarkm } 149255714Skris 1493127128Snectar 1494127128Snectar if (crlnumberfile != NULL) /* we have a CRL number that need updating */ 1495127128Snectar if (!save_serial(crlnumberfile,"new",crlnumber,NULL)) goto err; 1496127128Snectar 1497238405Sjkim if (crlnumber) 1498238405Sjkim { 1499238405Sjkim BN_free(crlnumber); 1500238405Sjkim crlnumber = NULL; 1501238405Sjkim } 150255714Skris 1503238405Sjkim if (!do_X509_CRL_sign(bio_err,crl,pkey,dgst,sigopts)) goto err; 1504238405Sjkim 150555714Skris PEM_write_bio_X509_CRL(Sout,crl); 1506127128Snectar 1507127128Snectar if (crlnumberfile != NULL) /* Rename the crlnumber file */ 1508127128Snectar if (!rotate_serial(crlnumberfile,"new","old")) goto err; 1509127128Snectar 151055714Skris } 151155714Skris /*****************************************************************/ 151255714Skris if (dorevoke) 151355714Skris { 151455714Skris if (infile == NULL) 151555714Skris { 151655714Skris BIO_printf(bio_err,"no input files\n"); 151755714Skris goto err; 151855714Skris } 151955714Skris else 152055714Skris { 152159191Skris X509 *revcert; 1522109998Smarkm revcert=load_cert(bio_err, infile, FORMAT_PEM, 1523109998Smarkm NULL, e, infile); 152459191Skris if (revcert == NULL) 152555714Skris goto err; 1526109998Smarkm j=do_revoke(revcert,db, rev_type, rev_arg); 152759191Skris if (j <= 0) goto err; 152859191Skris X509_free(revcert); 152955714Skris 1530127128Snectar if (!save_index(dbfile, "new", db)) goto err; 1531109998Smarkm 1532127128Snectar if (!rotate_index(dbfile, "new", "old")) goto err; 1533127128Snectar 153455714Skris BIO_printf(bio_err,"Data Base Updated\n"); 153555714Skris } 153655714Skris } 153755714Skris /*****************************************************************/ 153855714Skris ret=0; 153955714Skriserr: 1540109998Smarkm if(tofree) 1541109998Smarkm OPENSSL_free(tofree); 154268651Skris BIO_free_all(Cout); 154368651Skris BIO_free_all(Sout); 154468651Skris BIO_free_all(out); 1545109998Smarkm BIO_free_all(in); 154655714Skris 1547111147Snectar if (cert_sk) 1548111147Snectar sk_X509_pop_free(cert_sk,X509_free); 154955714Skris 155055714Skris if (ret) ERR_print_errors(bio_err); 155159191Skris app_RAND_write_file(randfile, bio_err); 1552111147Snectar if (free_key && key) 1553109998Smarkm OPENSSL_free(key); 155455714Skris BN_free(serial); 1555238405Sjkim BN_free(crlnumber); 1556127128Snectar free_index(db); 1557238405Sjkim if (sigopts) 1558238405Sjkim sk_OPENSSL_STRING_free(sigopts); 155955714Skris EVP_PKEY_free(pkey); 1560160814Ssimon if (x509) X509_free(x509); 156155714Skris X509_CRL_free(crl); 1562109998Smarkm NCONF_free(conf); 1563167612Ssimon NCONF_free(extconf); 156455714Skris OBJ_cleanup(); 1565109998Smarkm apps_shutdown(); 1566109998Smarkm OPENSSL_EXIT(ret); 156755714Skris } 156855714Skris 1569160814Ssimonstatic void lookup_fail(const char *name, const char *tag) 157055714Skris { 157155714Skris BIO_printf(bio_err,"variable lookup failed for %s::%s\n",name,tag); 157255714Skris } 157355714Skris 157455714Skrisstatic int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, 1575238405Sjkim const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, 1576238405Sjkim STACK_OF(CONF_VALUE) *policy, CA_DB *db, 1577238405Sjkim BIGNUM *serial, char *subj,unsigned long chtype, int multirdn, 1578238405Sjkim int email_dn, char *startdate, char *enddate, 1579109998Smarkm long days, int batch, char *ext_sect, CONF *lconf, int verbose, 1580109998Smarkm unsigned long certopt, unsigned long nameopt, int default_op, 1581160814Ssimon int ext_copy, int selfsign) 158255714Skris { 158355714Skris X509_REQ *req=NULL; 158455714Skris BIO *in=NULL; 158555714Skris EVP_PKEY *pktmp=NULL; 158655714Skris int ok= -1,i; 158755714Skris 158855714Skris in=BIO_new(BIO_s_file()); 158955714Skris 159055714Skris if (BIO_read_filename(in,infile) <= 0) 159155714Skris { 159255714Skris perror(infile); 159355714Skris goto err; 159455714Skris } 159555714Skris if ((req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL)) == NULL) 159655714Skris { 159755714Skris BIO_printf(bio_err,"Error reading certificate request in %s\n", 159855714Skris infile); 159955714Skris goto err; 160055714Skris } 160155714Skris if (verbose) 160255714Skris X509_REQ_print(bio_err,req); 160355714Skris 160455714Skris BIO_printf(bio_err,"Check that the request matches the signature\n"); 160555714Skris 1606160814Ssimon if (selfsign && !X509_REQ_check_private_key(req,pkey)) 1607160814Ssimon { 1608160814Ssimon BIO_printf(bio_err,"Certificate request and CA private key do not match\n"); 1609160814Ssimon ok=0; 1610160814Ssimon goto err; 1611160814Ssimon } 161255714Skris if ((pktmp=X509_REQ_get_pubkey(req)) == NULL) 161355714Skris { 161455714Skris BIO_printf(bio_err,"error unpacking public key\n"); 161555714Skris goto err; 161655714Skris } 161755714Skris i=X509_REQ_verify(req,pktmp); 161855714Skris EVP_PKEY_free(pktmp); 161955714Skris if (i < 0) 162055714Skris { 162155714Skris ok=0; 162255714Skris BIO_printf(bio_err,"Signature verification problems....\n"); 1623279264Sdelphij ERR_print_errors(bio_err); 162455714Skris goto err; 162555714Skris } 162655714Skris if (i == 0) 162755714Skris { 162855714Skris ok=0; 162955714Skris BIO_printf(bio_err,"Signature did not match the certificate request\n"); 1630279264Sdelphij ERR_print_errors(bio_err); 163155714Skris goto err; 163255714Skris } 163355714Skris else 163455714Skris BIO_printf(bio_err,"Signature ok\n"); 163555714Skris 1636238405Sjkim ok=do_body(xret,pkey,x509,dgst,sigopts, policy,db,serial,subj,chtype, 1637238405Sjkim multirdn, email_dn, 1638109998Smarkm startdate,enddate,days,batch,verbose,req,ext_sect,lconf, 1639160814Ssimon certopt, nameopt, default_op, ext_copy, selfsign); 164055714Skris 164155714Skriserr: 164255714Skris if (req != NULL) X509_REQ_free(req); 164355714Skris if (in != NULL) BIO_free(in); 164455714Skris return(ok); 164555714Skris } 164655714Skris 164755714Skrisstatic int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, 1648238405Sjkim const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, 1649238405Sjkim STACK_OF(CONF_VALUE) *policy, CA_DB *db, 1650160814Ssimon BIGNUM *serial, char *subj, unsigned long chtype, int multirdn, int email_dn, char *startdate, char *enddate, 1651109998Smarkm long days, int batch, char *ext_sect, CONF *lconf, int verbose, 1652109998Smarkm unsigned long certopt, unsigned long nameopt, int default_op, 1653109998Smarkm int ext_copy, ENGINE *e) 165455714Skris { 165555714Skris X509 *req=NULL; 165655714Skris X509_REQ *rreq=NULL; 165755714Skris EVP_PKEY *pktmp=NULL; 165855714Skris int ok= -1,i; 165955714Skris 1660109998Smarkm if ((req=load_cert(bio_err, infile, FORMAT_PEM, NULL, e, infile)) == NULL) 166155714Skris goto err; 166255714Skris if (verbose) 166355714Skris X509_print(bio_err,req); 166455714Skris 166555714Skris BIO_printf(bio_err,"Check that the request matches the signature\n"); 166655714Skris 166755714Skris if ((pktmp=X509_get_pubkey(req)) == NULL) 166855714Skris { 166955714Skris BIO_printf(bio_err,"error unpacking public key\n"); 167055714Skris goto err; 167155714Skris } 167255714Skris i=X509_verify(req,pktmp); 167355714Skris EVP_PKEY_free(pktmp); 167455714Skris if (i < 0) 167555714Skris { 167655714Skris ok=0; 167755714Skris BIO_printf(bio_err,"Signature verification problems....\n"); 167855714Skris goto err; 167955714Skris } 168055714Skris if (i == 0) 168155714Skris { 168255714Skris ok=0; 168355714Skris BIO_printf(bio_err,"Signature did not match the certificate\n"); 168455714Skris goto err; 168555714Skris } 168655714Skris else 168755714Skris BIO_printf(bio_err,"Signature ok\n"); 168855714Skris 168955714Skris if ((rreq=X509_to_X509_REQ(req,NULL,EVP_md5())) == NULL) 169055714Skris goto err; 169155714Skris 1692238405Sjkim ok=do_body(xret,pkey,x509,dgst,sigopts,policy,db,serial,subj,chtype,multirdn,email_dn,startdate,enddate, 1693109998Smarkm days,batch,verbose,rreq,ext_sect,lconf, certopt, nameopt, default_op, 1694160814Ssimon ext_copy, 0); 169555714Skris 169655714Skriserr: 169755714Skris if (rreq != NULL) X509_REQ_free(rreq); 169855714Skris if (req != NULL) X509_free(req); 169955714Skris return(ok); 170055714Skris } 170155714Skris 170255714Skrisstatic int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, 1703238405Sjkim STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy, 1704238405Sjkim CA_DB *db, BIGNUM *serial, char *subj, 1705160814Ssimon unsigned long chtype, int multirdn, 1706109998Smarkm int email_dn, char *startdate, char *enddate, long days, int batch, 1707109998Smarkm int verbose, X509_REQ *req, char *ext_sect, CONF *lconf, 1708109998Smarkm unsigned long certopt, unsigned long nameopt, int default_op, 1709160814Ssimon int ext_copy, int selfsign) 171055714Skris { 1711109998Smarkm X509_NAME *name=NULL,*CAname=NULL,*subject=NULL, *dn_subject=NULL; 171255714Skris ASN1_UTCTIME *tm,*tmptm; 171355714Skris ASN1_STRING *str,*str2; 171455714Skris ASN1_OBJECT *obj; 171555714Skris X509 *ret=NULL; 171655714Skris X509_CINF *ci; 171755714Skris X509_NAME_ENTRY *ne; 171855714Skris X509_NAME_ENTRY *tne,*push; 171955714Skris EVP_PKEY *pktmp; 172055714Skris int ok= -1,i,j,last,nid; 1721160814Ssimon const char *p; 172255714Skris CONF_VALUE *cv; 1723238405Sjkim OPENSSL_STRING row[DB_NUMBER]; 1724238405Sjkim OPENSSL_STRING *irow=NULL; 1725238405Sjkim OPENSSL_STRING *rrow=NULL; 1726109998Smarkm char buf[25]; 172755714Skris 172855714Skris tmptm=ASN1_UTCTIME_new(); 172955714Skris if (tmptm == NULL) 173055714Skris { 173155714Skris BIO_printf(bio_err,"malloc error\n"); 173255714Skris return(0); 173355714Skris } 173455714Skris 173555714Skris for (i=0; i<DB_NUMBER; i++) 173655714Skris row[i]=NULL; 173755714Skris 1738109998Smarkm if (subj) 1739109998Smarkm { 1740160814Ssimon X509_NAME *n = parse_name(subj, chtype, multirdn); 1741109998Smarkm 1742109998Smarkm if (!n) 1743109998Smarkm { 1744109998Smarkm ERR_print_errors(bio_err); 1745109998Smarkm goto err; 1746109998Smarkm } 1747109998Smarkm X509_REQ_set_subject_name(req,n); 1748109998Smarkm req->req_info->enc.modified = 1; 1749109998Smarkm X509_NAME_free(n); 1750109998Smarkm } 1751109998Smarkm 1752109998Smarkm if (default_op) 1753109998Smarkm BIO_printf(bio_err,"The Subject's Distinguished Name is as follows\n"); 1754109998Smarkm 175555714Skris name=X509_REQ_get_subject_name(req); 175655714Skris for (i=0; i<X509_NAME_entry_count(name); i++) 175755714Skris { 1758109998Smarkm ne= X509_NAME_get_entry(name,i); 1759109998Smarkm str=X509_NAME_ENTRY_get_data(ne); 176055714Skris obj=X509_NAME_ENTRY_get_object(ne); 176155714Skris 176255714Skris if (msie_hack) 176355714Skris { 176455714Skris /* assume all type should be strings */ 176555714Skris nid=OBJ_obj2nid(ne->object); 176655714Skris 176755714Skris if (str->type == V_ASN1_UNIVERSALSTRING) 176855714Skris ASN1_UNIVERSALSTRING_to_string(str); 176955714Skris 177055714Skris if ((str->type == V_ASN1_IA5STRING) && 177155714Skris (nid != NID_pkcs9_emailAddress)) 177255714Skris str->type=V_ASN1_T61STRING; 177355714Skris 177455714Skris if ((nid == NID_pkcs9_emailAddress) && 177555714Skris (str->type == V_ASN1_PRINTABLESTRING)) 177655714Skris str->type=V_ASN1_IA5STRING; 177755714Skris } 177855714Skris 1779109998Smarkm /* If no EMAIL is wanted in the subject */ 1780109998Smarkm if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) && (!email_dn)) 1781109998Smarkm continue; 178255714Skris 178355714Skris /* check some things */ 178455714Skris if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) && 178555714Skris (str->type != V_ASN1_IA5STRING)) 178655714Skris { 178755714Skris BIO_printf(bio_err,"\nemailAddress type needs to be of type IA5STRING\n"); 178855714Skris goto err; 178955714Skris } 1790109998Smarkm if ((str->type != V_ASN1_BMPSTRING) && (str->type != V_ASN1_UTF8STRING)) 179155714Skris { 1792109998Smarkm j=ASN1_PRINTABLE_type(str->data,str->length); 1793109998Smarkm if ( ((j == V_ASN1_T61STRING) && 1794109998Smarkm (str->type != V_ASN1_T61STRING)) || 1795109998Smarkm ((j == V_ASN1_IA5STRING) && 1796109998Smarkm (str->type == V_ASN1_PRINTABLESTRING))) 1797109998Smarkm { 1798109998Smarkm BIO_printf(bio_err,"\nThe string contains characters that are illegal for the ASN.1 type\n"); 1799109998Smarkm goto err; 1800109998Smarkm } 180155714Skris } 1802109998Smarkm 1803109998Smarkm if (default_op) 1804109998Smarkm old_entry_print(bio_err, obj, str); 180555714Skris } 180655714Skris 180755714Skris /* Ok, now we check the 'policy' stuff. */ 180855714Skris if ((subject=X509_NAME_new()) == NULL) 180955714Skris { 181068651Skris BIO_printf(bio_err,"Memory allocation failure\n"); 181155714Skris goto err; 181255714Skris } 181355714Skris 181455714Skris /* take a copy of the issuer name before we mess with it. */ 1815160814Ssimon if (selfsign) 1816160814Ssimon CAname=X509_NAME_dup(name); 1817160814Ssimon else 1818160814Ssimon CAname=X509_NAME_dup(x509->cert_info->subject); 181955714Skris if (CAname == NULL) goto err; 182055714Skris str=str2=NULL; 182155714Skris 182255714Skris for (i=0; i<sk_CONF_VALUE_num(policy); i++) 182355714Skris { 182455714Skris cv=sk_CONF_VALUE_value(policy,i); /* get the object id */ 182555714Skris if ((j=OBJ_txt2nid(cv->name)) == NID_undef) 182655714Skris { 182755714Skris BIO_printf(bio_err,"%s:unknown object type in 'policy' configuration\n",cv->name); 182855714Skris goto err; 182955714Skris } 183055714Skris obj=OBJ_nid2obj(j); 183155714Skris 183255714Skris last= -1; 183355714Skris for (;;) 183455714Skris { 183555714Skris /* lookup the object in the supplied name list */ 183655714Skris j=X509_NAME_get_index_by_OBJ(name,obj,last); 183755714Skris if (j < 0) 183855714Skris { 183955714Skris if (last != -1) break; 184055714Skris tne=NULL; 184155714Skris } 184255714Skris else 184355714Skris { 184455714Skris tne=X509_NAME_get_entry(name,j); 184555714Skris } 184655714Skris last=j; 184755714Skris 184855714Skris /* depending on the 'policy', decide what to do. */ 184955714Skris push=NULL; 185055714Skris if (strcmp(cv->value,"optional") == 0) 185155714Skris { 185255714Skris if (tne != NULL) 185355714Skris push=tne; 185455714Skris } 185555714Skris else if (strcmp(cv->value,"supplied") == 0) 185655714Skris { 185755714Skris if (tne == NULL) 185855714Skris { 185955714Skris BIO_printf(bio_err,"The %s field needed to be supplied and was missing\n",cv->name); 186055714Skris goto err; 186155714Skris } 186255714Skris else 186355714Skris push=tne; 186455714Skris } 186555714Skris else if (strcmp(cv->value,"match") == 0) 186655714Skris { 186755714Skris int last2; 186855714Skris 186955714Skris if (tne == NULL) 187055714Skris { 187155714Skris BIO_printf(bio_err,"The mandatory %s field was missing\n",cv->name); 187255714Skris goto err; 187355714Skris } 187455714Skris 187555714Skris last2= -1; 187655714Skris 187755714Skrisagain2: 187855714Skris j=X509_NAME_get_index_by_OBJ(CAname,obj,last2); 187955714Skris if ((j < 0) && (last2 == -1)) 188055714Skris { 188155714Skris BIO_printf(bio_err,"The %s field does not exist in the CA certificate,\nthe 'policy' is misconfigured\n",cv->name); 188255714Skris goto err; 188355714Skris } 188455714Skris if (j >= 0) 188555714Skris { 188655714Skris push=X509_NAME_get_entry(CAname,j); 188755714Skris str=X509_NAME_ENTRY_get_data(tne); 188855714Skris str2=X509_NAME_ENTRY_get_data(push); 188955714Skris last2=j; 189055714Skris if (ASN1_STRING_cmp(str,str2) != 0) 189155714Skris goto again2; 189255714Skris } 189355714Skris if (j < 0) 189455714Skris { 189559191Skris BIO_printf(bio_err,"The %s field needed to be the same in the\nCA certificate (%s) and the request (%s)\n",cv->name,((str2 == NULL)?"NULL":(char *)str2->data),((str == NULL)?"NULL":(char *)str->data)); 189655714Skris goto err; 189755714Skris } 189855714Skris } 189955714Skris else 190055714Skris { 190155714Skris BIO_printf(bio_err,"%s:invalid type in 'policy' configuration\n",cv->value); 190255714Skris goto err; 190355714Skris } 190455714Skris 190555714Skris if (push != NULL) 190655714Skris { 190759191Skris if (!X509_NAME_add_entry(subject,push, -1, 0)) 190855714Skris { 190955714Skris if (push != NULL) 191055714Skris X509_NAME_ENTRY_free(push); 191168651Skris BIO_printf(bio_err,"Memory allocation failure\n"); 191255714Skris goto err; 191355714Skris } 191455714Skris } 191555714Skris if (j < 0) break; 191655714Skris } 191755714Skris } 191855714Skris 191955714Skris if (preserve) 192055714Skris { 192155714Skris X509_NAME_free(subject); 1922109998Smarkm /* subject=X509_NAME_dup(X509_REQ_get_subject_name(req)); */ 1923109998Smarkm subject=X509_NAME_dup(name); 192455714Skris if (subject == NULL) goto err; 192555714Skris } 192655714Skris 192755714Skris if (verbose) 192859191Skris BIO_printf(bio_err,"The subject name appears to be ok, checking data base for clashes\n"); 192955714Skris 1930109998Smarkm /* Build the correct Subject if no e-mail is wanted in the subject */ 1931109998Smarkm /* and add it later on because of the method extensions are added (altName) */ 1932109998Smarkm 1933109998Smarkm if (email_dn) 1934109998Smarkm dn_subject = subject; 1935109998Smarkm else 193655714Skris { 1937109998Smarkm X509_NAME_ENTRY *tmpne; 1938109998Smarkm /* Its best to dup the subject DN and then delete any email 1939109998Smarkm * addresses because this retains its structure. 1940109998Smarkm */ 1941109998Smarkm if (!(dn_subject = X509_NAME_dup(subject))) 1942109998Smarkm { 1943109998Smarkm BIO_printf(bio_err,"Memory allocation failure\n"); 1944109998Smarkm goto err; 1945109998Smarkm } 1946109998Smarkm while((i = X509_NAME_get_index_by_NID(dn_subject, 1947109998Smarkm NID_pkcs9_emailAddress, -1)) >= 0) 1948109998Smarkm { 1949109998Smarkm tmpne = X509_NAME_get_entry(dn_subject, i); 1950109998Smarkm X509_NAME_delete_entry(dn_subject, i); 1951109998Smarkm X509_NAME_ENTRY_free(tmpne); 1952109998Smarkm } 1953109998Smarkm } 1954109998Smarkm 1955109998Smarkm if (BN_is_zero(serial)) 1956109998Smarkm row[DB_serial]=BUF_strdup("00"); 1957109998Smarkm else 1958109998Smarkm row[DB_serial]=BN_bn2hex(serial); 1959109998Smarkm if (row[DB_serial] == NULL) 1960109998Smarkm { 196168651Skris BIO_printf(bio_err,"Memory allocation failure\n"); 196255714Skris goto err; 196355714Skris } 196455714Skris 1965127128Snectar if (db->attributes.unique_subject) 196655714Skris { 1967238405Sjkim OPENSSL_STRING *crow=row; 1968238405Sjkim 1969238405Sjkim rrow=TXT_DB_get_by_index(db->db,DB_name,crow); 1970127128Snectar if (rrow != NULL) 1971127128Snectar { 1972127128Snectar BIO_printf(bio_err, 1973127128Snectar "ERROR:There is already a certificate for %s\n", 1974127128Snectar row[DB_name]); 1975127128Snectar } 197655714Skris } 1977127128Snectar if (rrow == NULL) 197855714Skris { 1979127128Snectar rrow=TXT_DB_get_by_index(db->db,DB_serial,row); 198055714Skris if (rrow != NULL) 198155714Skris { 198255714Skris BIO_printf(bio_err,"ERROR:Serial number %s has already been issued,\n", 198355714Skris row[DB_serial]); 198455714Skris BIO_printf(bio_err," check the database/serial_file for corruption\n"); 198555714Skris } 198655714Skris } 198755714Skris 198855714Skris if (rrow != NULL) 198955714Skris { 199055714Skris BIO_printf(bio_err, 199155714Skris "The matching entry has the following details\n"); 199255714Skris if (rrow[DB_type][0] == 'E') 199355714Skris p="Expired"; 199455714Skris else if (rrow[DB_type][0] == 'R') 199555714Skris p="Revoked"; 199655714Skris else if (rrow[DB_type][0] == 'V') 199755714Skris p="Valid"; 199855714Skris else 199955714Skris p="\ninvalid type, Data base error\n"; 200055714Skris BIO_printf(bio_err,"Type :%s\n",p);; 200155714Skris if (rrow[DB_type][0] == 'R') 200255714Skris { 200355714Skris p=rrow[DB_exp_date]; if (p == NULL) p="undef"; 200455714Skris BIO_printf(bio_err,"Was revoked on:%s\n",p); 200555714Skris } 200655714Skris p=rrow[DB_exp_date]; if (p == NULL) p="undef"; 200755714Skris BIO_printf(bio_err,"Expires on :%s\n",p); 200855714Skris p=rrow[DB_serial]; if (p == NULL) p="undef"; 200955714Skris BIO_printf(bio_err,"Serial Number :%s\n",p); 201055714Skris p=rrow[DB_file]; if (p == NULL) p="undef"; 201155714Skris BIO_printf(bio_err,"File name :%s\n",p); 201255714Skris p=rrow[DB_name]; if (p == NULL) p="undef"; 201355714Skris BIO_printf(bio_err,"Subject Name :%s\n",p); 201455714Skris ok= -1; /* This is now a 'bad' error. */ 201555714Skris goto err; 201655714Skris } 201755714Skris 201859191Skris /* We are now totally happy, lets make and sign the certificate */ 201955714Skris if (verbose) 202055714Skris BIO_printf(bio_err,"Everything appears to be ok, creating and signing the certificate\n"); 202155714Skris 202255714Skris if ((ret=X509_new()) == NULL) goto err; 202355714Skris ci=ret->cert_info; 202455714Skris 202555714Skris#ifdef X509_V3 202655714Skris /* Make it an X509 v3 certificate. */ 2027120631Snectar if (!X509_set_version(ret,2)) goto err; 202855714Skris#endif 202955714Skris 203055714Skris if (BN_to_ASN1_INTEGER(serial,ci->serialNumber) == NULL) 203155714Skris goto err; 2032160814Ssimon if (selfsign) 2033160814Ssimon { 2034160814Ssimon if (!X509_set_issuer_name(ret,subject)) 2035160814Ssimon goto err; 2036160814Ssimon } 2037160814Ssimon else 2038160814Ssimon { 2039160814Ssimon if (!X509_set_issuer_name(ret,X509_get_subject_name(x509))) 2040160814Ssimon goto err; 2041160814Ssimon } 204255714Skris 204355714Skris if (strcmp(startdate,"today") == 0) 204455714Skris X509_gmtime_adj(X509_get_notBefore(ret),0); 2045238405Sjkim else ASN1_TIME_set_string(X509_get_notBefore(ret),startdate); 204655714Skris 204755714Skris if (enddate == NULL) 2048238405Sjkim X509_time_adj_ex(X509_get_notAfter(ret),days, 0, NULL); 2049238405Sjkim else ASN1_TIME_set_string(X509_get_notAfter(ret),enddate); 205055714Skris 205155714Skris if (!X509_set_subject_name(ret,subject)) goto err; 205255714Skris 205355714Skris pktmp=X509_REQ_get_pubkey(req); 205455714Skris i = X509_set_pubkey(ret,pktmp); 205555714Skris EVP_PKEY_free(pktmp); 205655714Skris if (!i) goto err; 205755714Skris 205855714Skris /* Lets add the extensions, if there are any */ 205955714Skris if (ext_sect) 206055714Skris { 206155714Skris X509V3_CTX ctx; 206255714Skris if (ci->version == NULL) 206355714Skris if ((ci->version=ASN1_INTEGER_new()) == NULL) 206455714Skris goto err; 206555714Skris ASN1_INTEGER_set(ci->version,2); /* version 3 certificate */ 206655714Skris 206755714Skris /* Free the current entries if any, there should not 206859191Skris * be any I believe */ 206955714Skris if (ci->extensions != NULL) 207055714Skris sk_X509_EXTENSION_pop_free(ci->extensions, 207155714Skris X509_EXTENSION_free); 207255714Skris 207355714Skris ci->extensions = NULL; 207455714Skris 2075109998Smarkm /* Initialize the context structure */ 2076160814Ssimon if (selfsign) 2077160814Ssimon X509V3_set_ctx(&ctx, ret, ret, req, NULL, 0); 2078160814Ssimon else 2079160814Ssimon X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0); 208055714Skris 2081109998Smarkm if (extconf) 2082109998Smarkm { 2083109998Smarkm if (verbose) 2084109998Smarkm BIO_printf(bio_err, "Extra configuration file found\n"); 2085109998Smarkm 2086109998Smarkm /* Use the extconf configuration db LHASH */ 2087109998Smarkm X509V3_set_nconf(&ctx, extconf); 2088109998Smarkm 2089109998Smarkm /* Test the structure (needed?) */ 2090109998Smarkm /* X509V3_set_ctx_test(&ctx); */ 209155714Skris 2092109998Smarkm /* Adds exts contained in the configuration file */ 2093109998Smarkm if (!X509V3_EXT_add_nconf(extconf, &ctx, ext_sect,ret)) 2094109998Smarkm { 2095109998Smarkm BIO_printf(bio_err, 2096109998Smarkm "ERROR: adding extensions in section %s\n", 2097109998Smarkm ext_sect); 2098109998Smarkm ERR_print_errors(bio_err); 2099109998Smarkm goto err; 2100109998Smarkm } 2101109998Smarkm if (verbose) 2102109998Smarkm BIO_printf(bio_err, "Successfully added extensions from file.\n"); 2103109998Smarkm } 2104109998Smarkm else if (ext_sect) 2105109998Smarkm { 2106109998Smarkm /* We found extensions to be set from config file */ 2107109998Smarkm X509V3_set_nconf(&ctx, lconf); 2108109998Smarkm 2109109998Smarkm if(!X509V3_EXT_add_nconf(lconf, &ctx, ext_sect, ret)) 2110109998Smarkm { 2111109998Smarkm BIO_printf(bio_err, "ERROR: adding extensions in section %s\n", ext_sect); 2112109998Smarkm ERR_print_errors(bio_err); 2113109998Smarkm goto err; 2114109998Smarkm } 2115109998Smarkm 2116109998Smarkm if (verbose) 2117109998Smarkm BIO_printf(bio_err, "Successfully added extensions from config\n"); 2118109998Smarkm } 211955714Skris } 212055714Skris 2121109998Smarkm /* Copy extensions from request (if any) */ 212255714Skris 2123109998Smarkm if (!copy_extensions(ret, req, ext_copy)) 2124109998Smarkm { 2125109998Smarkm BIO_printf(bio_err, "ERROR: adding extensions from request\n"); 2126109998Smarkm ERR_print_errors(bio_err); 2127109998Smarkm goto err; 2128109998Smarkm } 2129109998Smarkm 2130109998Smarkm /* Set the right value for the noemailDN option */ 2131109998Smarkm if( email_dn == 0 ) 2132109998Smarkm { 2133109998Smarkm if (!X509_set_subject_name(ret,dn_subject)) goto err; 2134109998Smarkm } 2135109998Smarkm 2136109998Smarkm if (!default_op) 2137109998Smarkm { 2138109998Smarkm BIO_printf(bio_err, "Certificate Details:\n"); 2139109998Smarkm /* Never print signature details because signature not present */ 2140109998Smarkm certopt |= X509_FLAG_NO_SIGDUMP | X509_FLAG_NO_SIGNAME; 2141109998Smarkm X509_print_ex(bio_err, ret, nameopt, certopt); 2142109998Smarkm } 2143109998Smarkm 2144109998Smarkm BIO_printf(bio_err,"Certificate is to be certified until "); 2145205128Ssimon ASN1_TIME_print(bio_err,X509_get_notAfter(ret)); 2146160814Ssimon if (days) BIO_printf(bio_err," (%ld days)",days); 2147109998Smarkm BIO_printf(bio_err, "\n"); 2148109998Smarkm 214955714Skris if (!batch) 215055714Skris { 2151109998Smarkm 215255714Skris BIO_printf(bio_err,"Sign the certificate? [y/n]:"); 215355714Skris (void)BIO_flush(bio_err); 215455714Skris buf[0]='\0'; 2155205128Ssimon if (!fgets(buf,sizeof(buf)-1,stdin)) 2156205128Ssimon { 2157205128Ssimon BIO_printf(bio_err,"CERTIFICATE WILL NOT BE CERTIFIED: I/O error\n"); 2158205128Ssimon ok=0; 2159205128Ssimon goto err; 2160205128Ssimon } 216155714Skris if (!((buf[0] == 'y') || (buf[0] == 'Y'))) 216255714Skris { 216355714Skris BIO_printf(bio_err,"CERTIFICATE WILL NOT BE CERTIFIED\n"); 216455714Skris ok=0; 216555714Skris goto err; 216655714Skris } 216755714Skris } 216855714Skris 216955714Skris pktmp=X509_get_pubkey(ret); 217055714Skris if (EVP_PKEY_missing_parameters(pktmp) && 217155714Skris !EVP_PKEY_missing_parameters(pkey)) 217255714Skris EVP_PKEY_copy_parameters(pktmp,pkey); 217355714Skris EVP_PKEY_free(pktmp); 217455714Skris 2175238405Sjkim if (!do_X509_sign(bio_err, ret,pkey,dgst, sigopts)) 217655714Skris goto err; 217755714Skris 217855714Skris /* We now just add it to the database */ 217968651Skris row[DB_type]=(char *)OPENSSL_malloc(2); 218055714Skris 218155714Skris tm=X509_get_notAfter(ret); 218268651Skris row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1); 218355714Skris memcpy(row[DB_exp_date],tm->data,tm->length); 218455714Skris row[DB_exp_date][tm->length]='\0'; 218555714Skris 218655714Skris row[DB_rev_date]=NULL; 218755714Skris 218855714Skris /* row[DB_serial] done already */ 218968651Skris row[DB_file]=(char *)OPENSSL_malloc(8); 2190109998Smarkm row[DB_name]=X509_NAME_oneline(X509_get_subject_name(ret),NULL,0); 219155714Skris 219255714Skris if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) || 2193109998Smarkm (row[DB_file] == NULL) || (row[DB_name] == NULL)) 219455714Skris { 219568651Skris BIO_printf(bio_err,"Memory allocation failure\n"); 219655714Skris goto err; 219755714Skris } 2198127128Snectar BUF_strlcpy(row[DB_file],"unknown",8); 219955714Skris row[DB_type][0]='V'; 220055714Skris row[DB_type][1]='\0'; 220155714Skris 220268651Skris if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL) 220355714Skris { 220468651Skris BIO_printf(bio_err,"Memory allocation failure\n"); 220555714Skris goto err; 220655714Skris } 220755714Skris 220855714Skris for (i=0; i<DB_NUMBER; i++) 220955714Skris { 221055714Skris irow[i]=row[i]; 221155714Skris row[i]=NULL; 221255714Skris } 221355714Skris irow[DB_NUMBER]=NULL; 221455714Skris 2215127128Snectar if (!TXT_DB_insert(db->db,irow)) 221655714Skris { 221755714Skris BIO_printf(bio_err,"failed to update database\n"); 2218127128Snectar BIO_printf(bio_err,"TXT_DB error number %ld\n",db->db->error); 221955714Skris goto err; 222055714Skris } 222155714Skris ok=1; 222255714Skriserr: 222355714Skris for (i=0; i<DB_NUMBER; i++) 222468651Skris if (row[i] != NULL) OPENSSL_free(row[i]); 222555714Skris 222655714Skris if (CAname != NULL) 222755714Skris X509_NAME_free(CAname); 222855714Skris if (subject != NULL) 222955714Skris X509_NAME_free(subject); 2230109998Smarkm if ((dn_subject != NULL) && !email_dn) 2231109998Smarkm X509_NAME_free(dn_subject); 223259191Skris if (tmptm != NULL) 223359191Skris ASN1_UTCTIME_free(tmptm); 223455714Skris if (ok <= 0) 223555714Skris { 223655714Skris if (ret != NULL) X509_free(ret); 223755714Skris ret=NULL; 223855714Skris } 223955714Skris else 224055714Skris *xret=ret; 224155714Skris return(ok); 224255714Skris } 224355714Skris 224459191Skrisstatic void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext) 224555714Skris { 224655714Skris 224755714Skris if (output_der) 224855714Skris { 224955714Skris (void)i2d_X509_bio(bp,x); 225055714Skris return; 225155714Skris } 225259191Skris#if 0 225359191Skris /* ??? Not needed since X509_print prints all this stuff anyway */ 225455714Skris f=X509_NAME_oneline(X509_get_issuer_name(x),buf,256); 225555714Skris BIO_printf(bp,"issuer :%s\n",f); 225655714Skris 225755714Skris f=X509_NAME_oneline(X509_get_subject_name(x),buf,256); 225855714Skris BIO_printf(bp,"subject:%s\n",f); 225955714Skris 226055714Skris BIO_puts(bp,"serial :"); 226155714Skris i2a_ASN1_INTEGER(bp,x->cert_info->serialNumber); 226255714Skris BIO_puts(bp,"\n\n"); 226359191Skris#endif 2264109998Smarkm if (!notext)X509_print(bp,x); 226555714Skris PEM_write_bio_X509(bp,x); 226655714Skris } 226755714Skris 226855714Skrisstatic int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, 2269238405Sjkim const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, 2270238405Sjkim STACK_OF(CONF_VALUE) *policy, CA_DB *db, 2271160814Ssimon BIGNUM *serial, char *subj,unsigned long chtype, int multirdn, int email_dn, char *startdate, char *enddate, 2272109998Smarkm long days, char *ext_sect, CONF *lconf, int verbose, unsigned long certopt, 2273109998Smarkm unsigned long nameopt, int default_op, int ext_copy) 227455714Skris { 227555714Skris STACK_OF(CONF_VALUE) *sk=NULL; 2276238405Sjkim LHASH_OF(CONF_VALUE) *parms=NULL; 227755714Skris X509_REQ *req=NULL; 227855714Skris CONF_VALUE *cv=NULL; 227955714Skris NETSCAPE_SPKI *spki = NULL; 228055714Skris X509_REQ_INFO *ri; 228155714Skris char *type,*buf; 228255714Skris EVP_PKEY *pktmp=NULL; 228355714Skris X509_NAME *n=NULL; 228455714Skris X509_NAME_ENTRY *ne=NULL; 228555714Skris int ok= -1,i,j; 228655714Skris long errline; 228755714Skris int nid; 228855714Skris 228955714Skris /* 229055714Skris * Load input file into a hash table. (This is just an easy 229155714Skris * way to read and parse the file, then put it into a convenient 229255714Skris * STACK format). 229355714Skris */ 229455714Skris parms=CONF_load(NULL,infile,&errline); 229555714Skris if (parms == NULL) 229655714Skris { 229755714Skris BIO_printf(bio_err,"error on line %ld of %s\n",errline,infile); 229855714Skris ERR_print_errors(bio_err); 229955714Skris goto err; 230055714Skris } 230155714Skris 230255714Skris sk=CONF_get_section(parms, "default"); 230355714Skris if (sk_CONF_VALUE_num(sk) == 0) 230455714Skris { 230555714Skris BIO_printf(bio_err, "no name/value pairs found in %s\n", infile); 230655714Skris CONF_free(parms); 230755714Skris goto err; 230855714Skris } 230955714Skris 231055714Skris /* 231155714Skris * Now create a dummy X509 request structure. We don't actually 231255714Skris * have an X509 request, but we have many of the components 231355714Skris * (a public key, various DN components). The idea is that we 231455714Skris * put these components into the right X509 request structure 231555714Skris * and we can use the same code as if you had a real X509 request. 231655714Skris */ 231755714Skris req=X509_REQ_new(); 231855714Skris if (req == NULL) 231955714Skris { 232055714Skris ERR_print_errors(bio_err); 232155714Skris goto err; 232255714Skris } 232355714Skris 232455714Skris /* 232555714Skris * Build up the subject name set. 232655714Skris */ 232755714Skris ri=req->req_info; 232855714Skris n = ri->subject; 232955714Skris 233055714Skris for (i = 0; ; i++) 233155714Skris { 233255714Skris if (sk_CONF_VALUE_num(sk) <= i) break; 233355714Skris 233455714Skris cv=sk_CONF_VALUE_value(sk,i); 233555714Skris type=cv->name; 233659191Skris /* Skip past any leading X. X: X, etc to allow for 233759191Skris * multiple instances 233859191Skris */ 2339109998Smarkm for (buf = cv->name; *buf ; buf++) 2340109998Smarkm if ((*buf == ':') || (*buf == ',') || (*buf == '.')) 2341109998Smarkm { 2342109998Smarkm buf++; 2343109998Smarkm if (*buf) type = buf; 2344109998Smarkm break; 2345109998Smarkm } 234659191Skris 234755714Skris buf=cv->value; 234855714Skris if ((nid=OBJ_txt2nid(type)) == NID_undef) 234955714Skris { 235055714Skris if (strcmp(type, "SPKAC") == 0) 235155714Skris { 235259191Skris spki = NETSCAPE_SPKI_b64_decode(cv->value, -1); 235355714Skris if (spki == NULL) 235455714Skris { 235555714Skris BIO_printf(bio_err,"unable to load Netscape SPKAC structure\n"); 235655714Skris ERR_print_errors(bio_err); 235755714Skris goto err; 235855714Skris } 235955714Skris } 236055714Skris continue; 236155714Skris } 236255714Skris 2363205128Ssimon if (!X509_NAME_add_entry_by_NID(n, nid, chtype, 2364205128Ssimon (unsigned char *)buf, -1, -1, 0)) 236555714Skris goto err; 236655714Skris } 236755714Skris if (spki == NULL) 236855714Skris { 236955714Skris BIO_printf(bio_err,"Netscape SPKAC structure not found in %s\n", 237055714Skris infile); 237155714Skris goto err; 237255714Skris } 237355714Skris 237455714Skris /* 237555714Skris * Now extract the key from the SPKI structure. 237655714Skris */ 237755714Skris 237855714Skris BIO_printf(bio_err,"Check that the SPKAC request matches the signature\n"); 237955714Skris 238059191Skris if ((pktmp=NETSCAPE_SPKI_get_pubkey(spki)) == NULL) 238155714Skris { 238255714Skris BIO_printf(bio_err,"error unpacking SPKAC public key\n"); 238355714Skris goto err; 238455714Skris } 238555714Skris 238655714Skris j = NETSCAPE_SPKI_verify(spki, pktmp); 238755714Skris if (j <= 0) 238855714Skris { 238955714Skris BIO_printf(bio_err,"signature verification failed on SPKAC public key\n"); 239055714Skris goto err; 239155714Skris } 239255714Skris BIO_printf(bio_err,"Signature ok\n"); 239355714Skris 239455714Skris X509_REQ_set_pubkey(req,pktmp); 239555714Skris EVP_PKEY_free(pktmp); 2396238405Sjkim ok=do_body(xret,pkey,x509,dgst,sigopts,policy,db,serial,subj,chtype, 2397238405Sjkim multirdn,email_dn,startdate,enddate, days,1,verbose,req, 2398238405Sjkim ext_sect,lconf, certopt, nameopt, default_op, ext_copy, 0); 239955714Skriserr: 240055714Skris if (req != NULL) X509_REQ_free(req); 240155714Skris if (parms != NULL) CONF_free(parms); 240255714Skris if (spki != NULL) NETSCAPE_SPKI_free(spki); 240355714Skris if (ne != NULL) X509_NAME_ENTRY_free(ne); 240455714Skris 240555714Skris return(ok); 240655714Skris } 240755714Skris 2408205128Ssimonstatic int check_time_format(const char *str) 240955714Skris { 2410238405Sjkim return ASN1_TIME_set_string(NULL, str); 241155714Skris } 241255714Skris 2413127128Snectarstatic int do_revoke(X509 *x509, CA_DB *db, int type, char *value) 2414109998Smarkm { 2415109998Smarkm ASN1_UTCTIME *tm=NULL; 241655714Skris char *row[DB_NUMBER],**rrow,**irow; 2417109998Smarkm char *rev_str = NULL; 241859191Skris BIGNUM *bn = NULL; 241955714Skris int ok=-1,i; 242055714Skris 242155714Skris for (i=0; i<DB_NUMBER; i++) 242255714Skris row[i]=NULL; 242359191Skris row[DB_name]=X509_NAME_oneline(X509_get_subject_name(x509),NULL,0); 242459191Skris bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509),NULL); 2425238405Sjkim if (!bn) 2426238405Sjkim goto err; 2427109998Smarkm if (BN_is_zero(bn)) 2428109998Smarkm row[DB_serial]=BUF_strdup("00"); 2429109998Smarkm else 2430109998Smarkm row[DB_serial]=BN_bn2hex(bn); 243159191Skris BN_free(bn); 243255714Skris if ((row[DB_name] == NULL) || (row[DB_serial] == NULL)) 243355714Skris { 243468651Skris BIO_printf(bio_err,"Memory allocation failure\n"); 243555714Skris goto err; 243655714Skris } 243759191Skris /* We have to lookup by serial number because name lookup 243859191Skris * skips revoked certs 243959191Skris */ 2440127128Snectar rrow=TXT_DB_get_by_index(db->db,DB_serial,row); 244155714Skris if (rrow == NULL) 244255714Skris { 2443127128Snectar BIO_printf(bio_err,"Adding Entry with serial number %s to DB for %s\n", row[DB_serial], row[DB_name]); 244455714Skris 244555714Skris /* We now just add it to the database */ 244668651Skris row[DB_type]=(char *)OPENSSL_malloc(2); 244755714Skris 244855714Skris tm=X509_get_notAfter(x509); 244968651Skris row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1); 245055714Skris memcpy(row[DB_exp_date],tm->data,tm->length); 245155714Skris row[DB_exp_date][tm->length]='\0'; 245255714Skris 245355714Skris row[DB_rev_date]=NULL; 245455714Skris 245555714Skris /* row[DB_serial] done already */ 245668651Skris row[DB_file]=(char *)OPENSSL_malloc(8); 245755714Skris 245855714Skris /* row[DB_name] done already */ 245955714Skris 246055714Skris if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) || 246155714Skris (row[DB_file] == NULL)) 246255714Skris { 246368651Skris BIO_printf(bio_err,"Memory allocation failure\n"); 246455714Skris goto err; 246555714Skris } 2466127128Snectar BUF_strlcpy(row[DB_file],"unknown",8); 246755714Skris row[DB_type][0]='V'; 246855714Skris row[DB_type][1]='\0'; 246955714Skris 247068651Skris if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL) 247155714Skris { 247268651Skris BIO_printf(bio_err,"Memory allocation failure\n"); 247355714Skris goto err; 247455714Skris } 247555714Skris 247655714Skris for (i=0; i<DB_NUMBER; i++) 247755714Skris { 247855714Skris irow[i]=row[i]; 247955714Skris row[i]=NULL; 248055714Skris } 248155714Skris irow[DB_NUMBER]=NULL; 248255714Skris 2483127128Snectar if (!TXT_DB_insert(db->db,irow)) 248455714Skris { 248555714Skris BIO_printf(bio_err,"failed to update database\n"); 2486127128Snectar BIO_printf(bio_err,"TXT_DB error number %ld\n",db->db->error); 248755714Skris goto err; 248855714Skris } 248955714Skris 249055714Skris /* Revoke Certificate */ 2491109998Smarkm ok = do_revoke(x509,db, type, value); 249255714Skris 249355714Skris goto err; 249455714Skris 249555714Skris } 2496238405Sjkim else if (index_name_cmp_noconst(row, rrow)) 249755714Skris { 249859191Skris BIO_printf(bio_err,"ERROR:name does not match %s\n", 249959191Skris row[DB_name]); 250055714Skris goto err; 250155714Skris } 250255714Skris else if (rrow[DB_type][0]=='R') 250355714Skris { 250455714Skris BIO_printf(bio_err,"ERROR:Already revoked, serial number %s\n", 250555714Skris row[DB_serial]); 250655714Skris goto err; 250755714Skris } 250855714Skris else 250955714Skris { 251055714Skris BIO_printf(bio_err,"Revoking Certificate %s.\n", rrow[DB_serial]); 2511109998Smarkm rev_str = make_revocation_str(type, value); 2512109998Smarkm if (!rev_str) 2513109998Smarkm { 2514109998Smarkm BIO_printf(bio_err, "Error in revocation arguments\n"); 2515109998Smarkm goto err; 2516109998Smarkm } 251755714Skris rrow[DB_type][0]='R'; 251855714Skris rrow[DB_type][1]='\0'; 2519109998Smarkm rrow[DB_rev_date] = rev_str; 252055714Skris } 252155714Skris ok=1; 252255714Skriserr: 252355714Skris for (i=0; i<DB_NUMBER; i++) 252455714Skris { 252555714Skris if (row[i] != NULL) 252668651Skris OPENSSL_free(row[i]); 252755714Skris } 252855714Skris return(ok); 2529109998Smarkm } 2530109998Smarkm 2531127128Snectarstatic int get_certificate_status(const char *serial, CA_DB *db) 2532109998Smarkm { 2533109998Smarkm char *row[DB_NUMBER],**rrow; 2534109998Smarkm int ok=-1,i; 2535109998Smarkm 2536109998Smarkm /* Free Resources */ 2537109998Smarkm for (i=0; i<DB_NUMBER; i++) 2538109998Smarkm row[i]=NULL; 2539109998Smarkm 2540109998Smarkm /* Malloc needed char spaces */ 2541109998Smarkm row[DB_serial] = OPENSSL_malloc(strlen(serial) + 2); 2542109998Smarkm if (row[DB_serial] == NULL) 2543109998Smarkm { 2544109998Smarkm BIO_printf(bio_err,"Malloc failure\n"); 2545109998Smarkm goto err; 2546109998Smarkm } 2547109998Smarkm 2548109998Smarkm if (strlen(serial) % 2) 2549109998Smarkm { 2550109998Smarkm /* Set the first char to 0 */; 2551109998Smarkm row[DB_serial][0]='0'; 2552109998Smarkm 2553109998Smarkm /* Copy String from serial to row[DB_serial] */ 2554109998Smarkm memcpy(row[DB_serial]+1, serial, strlen(serial)); 2555109998Smarkm row[DB_serial][strlen(serial)+1]='\0'; 2556109998Smarkm } 2557109998Smarkm else 2558109998Smarkm { 2559109998Smarkm /* Copy String from serial to row[DB_serial] */ 2560109998Smarkm memcpy(row[DB_serial], serial, strlen(serial)); 2561109998Smarkm row[DB_serial][strlen(serial)]='\0'; 2562109998Smarkm } 2563109998Smarkm 2564109998Smarkm /* Make it Upper Case */ 2565109998Smarkm for (i=0; row[DB_serial][i] != '\0'; i++) 2566238405Sjkim row[DB_serial][i] = toupper((unsigned char)row[DB_serial][i]); 2567109998Smarkm 2568109998Smarkm 2569109998Smarkm ok=1; 2570109998Smarkm 2571109998Smarkm /* Search for the certificate */ 2572127128Snectar rrow=TXT_DB_get_by_index(db->db,DB_serial,row); 2573109998Smarkm if (rrow == NULL) 2574109998Smarkm { 2575109998Smarkm BIO_printf(bio_err,"Serial %s not present in db.\n", 2576109998Smarkm row[DB_serial]); 2577109998Smarkm ok=-1; 2578109998Smarkm goto err; 2579109998Smarkm } 2580109998Smarkm else if (rrow[DB_type][0]=='V') 2581109998Smarkm { 2582109998Smarkm BIO_printf(bio_err,"%s=Valid (%c)\n", 2583109998Smarkm row[DB_serial], rrow[DB_type][0]); 2584109998Smarkm goto err; 2585109998Smarkm } 2586109998Smarkm else if (rrow[DB_type][0]=='R') 2587109998Smarkm { 2588109998Smarkm BIO_printf(bio_err,"%s=Revoked (%c)\n", 2589109998Smarkm row[DB_serial], rrow[DB_type][0]); 2590109998Smarkm goto err; 2591109998Smarkm } 2592109998Smarkm else if (rrow[DB_type][0]=='E') 2593109998Smarkm { 2594109998Smarkm BIO_printf(bio_err,"%s=Expired (%c)\n", 2595109998Smarkm row[DB_serial], rrow[DB_type][0]); 2596109998Smarkm goto err; 2597109998Smarkm } 2598109998Smarkm else if (rrow[DB_type][0]=='S') 2599109998Smarkm { 2600109998Smarkm BIO_printf(bio_err,"%s=Suspended (%c)\n", 2601109998Smarkm row[DB_serial], rrow[DB_type][0]); 2602109998Smarkm goto err; 2603109998Smarkm } 2604109998Smarkm else 2605109998Smarkm { 2606109998Smarkm BIO_printf(bio_err,"%s=Unknown (%c).\n", 2607109998Smarkm row[DB_serial], rrow[DB_type][0]); 2608109998Smarkm ok=-1; 2609109998Smarkm } 2610109998Smarkmerr: 2611109998Smarkm for (i=0; i<DB_NUMBER; i++) 2612109998Smarkm { 2613109998Smarkm if (row[i] != NULL) 2614109998Smarkm OPENSSL_free(row[i]); 2615109998Smarkm } 2616109998Smarkm return(ok); 2617109998Smarkm } 2618109998Smarkm 2619127128Snectarstatic int do_updatedb (CA_DB *db) 2620109998Smarkm { 2621109998Smarkm ASN1_UTCTIME *a_tm = NULL; 2622109998Smarkm int i, cnt = 0; 2623109998Smarkm int db_y2k, a_y2k; /* flags = 1 if y >= 2000 */ 2624109998Smarkm char **rrow, *a_tm_s; 2625109998Smarkm 2626109998Smarkm a_tm = ASN1_UTCTIME_new(); 2627109998Smarkm 2628109998Smarkm /* get actual time and make a string */ 2629109998Smarkm a_tm = X509_gmtime_adj(a_tm, 0); 2630109998Smarkm a_tm_s = (char *) OPENSSL_malloc(a_tm->length+1); 2631109998Smarkm if (a_tm_s == NULL) 2632109998Smarkm { 2633109998Smarkm cnt = -1; 2634109998Smarkm goto err; 2635109998Smarkm } 2636109998Smarkm 2637109998Smarkm memcpy(a_tm_s, a_tm->data, a_tm->length); 2638109998Smarkm a_tm_s[a_tm->length] = '\0'; 2639109998Smarkm 2640109998Smarkm if (strncmp(a_tm_s, "49", 2) <= 0) 2641109998Smarkm a_y2k = 1; 2642109998Smarkm else 2643109998Smarkm a_y2k = 0; 2644109998Smarkm 2645238405Sjkim for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) 2646109998Smarkm { 2647238405Sjkim rrow = sk_OPENSSL_PSTRING_value(db->db->data, i); 2648109998Smarkm 2649109998Smarkm if (rrow[DB_type][0] == 'V') 2650109998Smarkm { 2651109998Smarkm /* ignore entries that are not valid */ 2652109998Smarkm if (strncmp(rrow[DB_exp_date], "49", 2) <= 0) 2653109998Smarkm db_y2k = 1; 2654109998Smarkm else 2655109998Smarkm db_y2k = 0; 2656109998Smarkm 2657109998Smarkm if (db_y2k == a_y2k) 2658109998Smarkm { 2659109998Smarkm /* all on the same y2k side */ 2660109998Smarkm if (strcmp(rrow[DB_exp_date], a_tm_s) <= 0) 2661109998Smarkm { 2662109998Smarkm rrow[DB_type][0] = 'E'; 2663109998Smarkm rrow[DB_type][1] = '\0'; 2664109998Smarkm cnt++; 2665109998Smarkm 2666109998Smarkm BIO_printf(bio_err, "%s=Expired\n", 2667109998Smarkm rrow[DB_serial]); 2668109998Smarkm } 2669109998Smarkm } 2670109998Smarkm else if (db_y2k < a_y2k) 2671109998Smarkm { 2672109998Smarkm rrow[DB_type][0] = 'E'; 2673109998Smarkm rrow[DB_type][1] = '\0'; 2674109998Smarkm cnt++; 2675109998Smarkm 2676109998Smarkm BIO_printf(bio_err, "%s=Expired\n", 2677109998Smarkm rrow[DB_serial]); 2678109998Smarkm } 2679109998Smarkm 2680109998Smarkm } 2681109998Smarkm } 2682109998Smarkm 2683109998Smarkmerr: 2684109998Smarkm 2685109998Smarkm ASN1_UTCTIME_free(a_tm); 2686109998Smarkm OPENSSL_free(a_tm_s); 2687109998Smarkm 2688109998Smarkm return (cnt); 2689109998Smarkm } 2690109998Smarkm 2691160814Ssimonstatic const char *crl_reasons[] = { 2692109998Smarkm /* CRL reason strings */ 2693109998Smarkm "unspecified", 2694109998Smarkm "keyCompromise", 2695109998Smarkm "CACompromise", 2696109998Smarkm "affiliationChanged", 2697109998Smarkm "superseded", 2698109998Smarkm "cessationOfOperation", 2699109998Smarkm "certificateHold", 2700109998Smarkm "removeFromCRL", 2701109998Smarkm /* Additional pseudo reasons */ 2702109998Smarkm "holdInstruction", 2703109998Smarkm "keyTime", 2704109998Smarkm "CAkeyTime" 2705109998Smarkm}; 2706109998Smarkm 2707109998Smarkm#define NUM_REASONS (sizeof(crl_reasons) / sizeof(char *)) 2708109998Smarkm 2709109998Smarkm/* Given revocation information convert to a DB string. 2710109998Smarkm * The format of the string is: 2711109998Smarkm * revtime[,reason,extra]. Where 'revtime' is the 2712109998Smarkm * revocation time (the current time). 'reason' is the 2713109998Smarkm * optional CRL reason and 'extra' is any additional 2714109998Smarkm * argument 2715109998Smarkm */ 2716109998Smarkm 2717109998Smarkmchar *make_revocation_str(int rev_type, char *rev_arg) 2718109998Smarkm { 2719160814Ssimon char *other = NULL, *str; 2720160814Ssimon const char *reason = NULL; 2721109998Smarkm ASN1_OBJECT *otmp; 2722109998Smarkm ASN1_UTCTIME *revtm = NULL; 2723109998Smarkm int i; 2724109998Smarkm switch (rev_type) 2725109998Smarkm { 2726109998Smarkm case REV_NONE: 2727109998Smarkm break; 2728109998Smarkm 2729109998Smarkm case REV_CRL_REASON: 2730109998Smarkm for (i = 0; i < 8; i++) 2731109998Smarkm { 2732109998Smarkm if (!strcasecmp(rev_arg, crl_reasons[i])) 2733109998Smarkm { 2734109998Smarkm reason = crl_reasons[i]; 2735109998Smarkm break; 2736109998Smarkm } 2737109998Smarkm } 2738109998Smarkm if (reason == NULL) 2739109998Smarkm { 2740109998Smarkm BIO_printf(bio_err, "Unknown CRL reason %s\n", rev_arg); 2741109998Smarkm return NULL; 2742109998Smarkm } 2743109998Smarkm break; 2744109998Smarkm 2745109998Smarkm case REV_HOLD: 2746109998Smarkm /* Argument is an OID */ 2747109998Smarkm 2748109998Smarkm otmp = OBJ_txt2obj(rev_arg, 0); 2749109998Smarkm ASN1_OBJECT_free(otmp); 2750109998Smarkm 2751109998Smarkm if (otmp == NULL) 2752109998Smarkm { 2753109998Smarkm BIO_printf(bio_err, "Invalid object identifier %s\n", rev_arg); 2754109998Smarkm return NULL; 2755109998Smarkm } 2756109998Smarkm 2757109998Smarkm reason = "holdInstruction"; 2758109998Smarkm other = rev_arg; 2759109998Smarkm break; 2760109998Smarkm 2761109998Smarkm case REV_KEY_COMPROMISE: 2762109998Smarkm case REV_CA_COMPROMISE: 2763109998Smarkm 2764109998Smarkm /* Argument is the key compromise time */ 2765109998Smarkm if (!ASN1_GENERALIZEDTIME_set_string(NULL, rev_arg)) 2766109998Smarkm { 2767109998Smarkm BIO_printf(bio_err, "Invalid time format %s. Need YYYYMMDDHHMMSSZ\n", rev_arg); 2768109998Smarkm return NULL; 2769109998Smarkm } 2770109998Smarkm other = rev_arg; 2771109998Smarkm if (rev_type == REV_KEY_COMPROMISE) 2772109998Smarkm reason = "keyTime"; 2773109998Smarkm else 2774109998Smarkm reason = "CAkeyTime"; 2775109998Smarkm 2776109998Smarkm break; 2777109998Smarkm 2778109998Smarkm } 2779109998Smarkm 2780109998Smarkm revtm = X509_gmtime_adj(NULL, 0); 2781109998Smarkm 2782279264Sdelphij if (!revtm) 2783279264Sdelphij return NULL; 2784279264Sdelphij 2785109998Smarkm i = revtm->length + 1; 2786109998Smarkm 2787109998Smarkm if (reason) i += strlen(reason) + 1; 2788109998Smarkm if (other) i += strlen(other) + 1; 2789109998Smarkm 2790109998Smarkm str = OPENSSL_malloc(i); 2791109998Smarkm 2792109998Smarkm if (!str) return NULL; 2793109998Smarkm 2794127128Snectar BUF_strlcpy(str, (char *)revtm->data, i); 2795109998Smarkm if (reason) 2796109998Smarkm { 2797127128Snectar BUF_strlcat(str, ",", i); 2798127128Snectar BUF_strlcat(str, reason, i); 2799109998Smarkm } 2800109998Smarkm if (other) 2801109998Smarkm { 2802127128Snectar BUF_strlcat(str, ",", i); 2803127128Snectar BUF_strlcat(str, other, i); 2804109998Smarkm } 2805109998Smarkm ASN1_UTCTIME_free(revtm); 2806109998Smarkm return str; 2807109998Smarkm } 2808109998Smarkm 2809109998Smarkm/* Convert revocation field to X509_REVOKED entry 2810109998Smarkm * return code: 2811109998Smarkm * 0 error 2812109998Smarkm * 1 OK 2813109998Smarkm * 2 OK and some extensions added (i.e. V2 CRL) 2814109998Smarkm */ 2815109998Smarkm 2816109998Smarkm 2817160814Ssimonint make_revoked(X509_REVOKED *rev, const char *str) 2818109998Smarkm { 2819109998Smarkm char *tmp = NULL; 2820109998Smarkm int reason_code = -1; 2821109998Smarkm int i, ret = 0; 2822109998Smarkm ASN1_OBJECT *hold = NULL; 2823109998Smarkm ASN1_GENERALIZEDTIME *comp_time = NULL; 2824109998Smarkm ASN1_ENUMERATED *rtmp = NULL; 2825109998Smarkm 2826109998Smarkm ASN1_TIME *revDate = NULL; 2827109998Smarkm 2828109998Smarkm i = unpack_revinfo(&revDate, &reason_code, &hold, &comp_time, str); 2829109998Smarkm 2830109998Smarkm if (i == 0) 2831109998Smarkm goto err; 2832109998Smarkm 2833109998Smarkm if (rev && !X509_REVOKED_set_revocationDate(rev, revDate)) 2834109998Smarkm goto err; 2835109998Smarkm 2836109998Smarkm if (rev && (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)) 2837109998Smarkm { 2838109998Smarkm rtmp = ASN1_ENUMERATED_new(); 2839109998Smarkm if (!rtmp || !ASN1_ENUMERATED_set(rtmp, reason_code)) 2840109998Smarkm goto err; 2841109998Smarkm if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0)) 2842109998Smarkm goto err; 2843109998Smarkm } 2844109998Smarkm 2845109998Smarkm if (rev && comp_time) 2846109998Smarkm { 2847109998Smarkm if (!X509_REVOKED_add1_ext_i2d(rev, NID_invalidity_date, comp_time, 0, 0)) 2848109998Smarkm goto err; 2849109998Smarkm } 2850109998Smarkm if (rev && hold) 2851109998Smarkm { 2852109998Smarkm if (!X509_REVOKED_add1_ext_i2d(rev, NID_hold_instruction_code, hold, 0, 0)) 2853109998Smarkm goto err; 2854109998Smarkm } 2855109998Smarkm 2856109998Smarkm if (reason_code != OCSP_REVOKED_STATUS_NOSTATUS) 2857109998Smarkm ret = 2; 2858109998Smarkm else ret = 1; 2859109998Smarkm 2860109998Smarkm err: 2861109998Smarkm 2862109998Smarkm if (tmp) OPENSSL_free(tmp); 2863109998Smarkm ASN1_OBJECT_free(hold); 2864109998Smarkm ASN1_GENERALIZEDTIME_free(comp_time); 2865109998Smarkm ASN1_ENUMERATED_free(rtmp); 2866109998Smarkm ASN1_TIME_free(revDate); 2867109998Smarkm 2868109998Smarkm return ret; 2869109998Smarkm } 2870109998Smarkm 2871109998Smarkmint old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str) 2872109998Smarkm { 2873109998Smarkm char buf[25],*pbuf, *p; 2874109998Smarkm int j; 2875109998Smarkm j=i2a_ASN1_OBJECT(bp,obj); 2876109998Smarkm pbuf=buf; 2877109998Smarkm for (j=22-j; j>0; j--) 2878109998Smarkm *(pbuf++)=' '; 2879109998Smarkm *(pbuf++)=':'; 2880109998Smarkm *(pbuf++)='\0'; 2881109998Smarkm BIO_puts(bp,buf); 2882109998Smarkm 2883109998Smarkm if (str->type == V_ASN1_PRINTABLESTRING) 2884109998Smarkm BIO_printf(bp,"PRINTABLE:'"); 2885109998Smarkm else if (str->type == V_ASN1_T61STRING) 2886109998Smarkm BIO_printf(bp,"T61STRING:'"); 2887109998Smarkm else if (str->type == V_ASN1_IA5STRING) 2888109998Smarkm BIO_printf(bp,"IA5STRING:'"); 2889109998Smarkm else if (str->type == V_ASN1_UNIVERSALSTRING) 2890109998Smarkm BIO_printf(bp,"UNIVERSALSTRING:'"); 2891109998Smarkm else 2892109998Smarkm BIO_printf(bp,"ASN.1 %2d:'",str->type); 2893109998Smarkm 2894109998Smarkm p=(char *)str->data; 2895109998Smarkm for (j=str->length; j>0; j--) 2896109998Smarkm { 2897109998Smarkm if ((*p >= ' ') && (*p <= '~')) 2898109998Smarkm BIO_printf(bp,"%c",*p); 2899109998Smarkm else if (*p & 0x80) 2900109998Smarkm BIO_printf(bp,"\\0x%02X",*p); 2901109998Smarkm else if ((unsigned char)*p == 0xf7) 2902109998Smarkm BIO_printf(bp,"^?"); 2903109998Smarkm else BIO_printf(bp,"^%c",*p+'@'); 2904109998Smarkm p++; 2905109998Smarkm } 2906109998Smarkm BIO_printf(bp,"'\n"); 2907109998Smarkm return 1; 2908109998Smarkm } 2909109998Smarkm 2910160814Ssimonint unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, ASN1_GENERALIZEDTIME **pinvtm, const char *str) 2911109998Smarkm { 2912109998Smarkm char *tmp = NULL; 2913109998Smarkm char *rtime_str, *reason_str = NULL, *arg_str = NULL, *p; 2914109998Smarkm int reason_code = -1; 2915160814Ssimon int ret = 0; 2916160814Ssimon unsigned int i; 2917109998Smarkm ASN1_OBJECT *hold = NULL; 2918109998Smarkm ASN1_GENERALIZEDTIME *comp_time = NULL; 2919109998Smarkm tmp = BUF_strdup(str); 2920109998Smarkm 2921109998Smarkm p = strchr(tmp, ','); 2922109998Smarkm 2923109998Smarkm rtime_str = tmp; 2924109998Smarkm 2925109998Smarkm if (p) 2926109998Smarkm { 2927109998Smarkm *p = '\0'; 2928109998Smarkm p++; 2929109998Smarkm reason_str = p; 2930109998Smarkm p = strchr(p, ','); 2931109998Smarkm if (p) 2932109998Smarkm { 2933109998Smarkm *p = '\0'; 2934109998Smarkm arg_str = p + 1; 2935109998Smarkm } 2936109998Smarkm } 2937109998Smarkm 2938109998Smarkm if (prevtm) 2939109998Smarkm { 2940109998Smarkm *prevtm = ASN1_UTCTIME_new(); 2941109998Smarkm if (!ASN1_UTCTIME_set_string(*prevtm, rtime_str)) 2942109998Smarkm { 2943109998Smarkm BIO_printf(bio_err, "invalid revocation date %s\n", rtime_str); 2944109998Smarkm goto err; 2945109998Smarkm } 2946109998Smarkm } 2947109998Smarkm if (reason_str) 2948109998Smarkm { 2949109998Smarkm for (i = 0; i < NUM_REASONS; i++) 2950109998Smarkm { 2951109998Smarkm if(!strcasecmp(reason_str, crl_reasons[i])) 2952109998Smarkm { 2953109998Smarkm reason_code = i; 2954109998Smarkm break; 2955109998Smarkm } 2956109998Smarkm } 2957109998Smarkm if (reason_code == OCSP_REVOKED_STATUS_NOSTATUS) 2958109998Smarkm { 2959109998Smarkm BIO_printf(bio_err, "invalid reason code %s\n", reason_str); 2960109998Smarkm goto err; 2961109998Smarkm } 2962109998Smarkm 2963109998Smarkm if (reason_code == 7) 2964109998Smarkm reason_code = OCSP_REVOKED_STATUS_REMOVEFROMCRL; 2965109998Smarkm else if (reason_code == 8) /* Hold instruction */ 2966109998Smarkm { 2967109998Smarkm if (!arg_str) 2968109998Smarkm { 2969109998Smarkm BIO_printf(bio_err, "missing hold instruction\n"); 2970109998Smarkm goto err; 2971109998Smarkm } 2972109998Smarkm reason_code = OCSP_REVOKED_STATUS_CERTIFICATEHOLD; 2973109998Smarkm hold = OBJ_txt2obj(arg_str, 0); 2974109998Smarkm 2975109998Smarkm if (!hold) 2976109998Smarkm { 2977109998Smarkm BIO_printf(bio_err, "invalid object identifier %s\n", arg_str); 2978109998Smarkm goto err; 2979109998Smarkm } 2980109998Smarkm if (phold) *phold = hold; 2981109998Smarkm } 2982109998Smarkm else if ((reason_code == 9) || (reason_code == 10)) 2983109998Smarkm { 2984109998Smarkm if (!arg_str) 2985109998Smarkm { 2986109998Smarkm BIO_printf(bio_err, "missing compromised time\n"); 2987109998Smarkm goto err; 2988109998Smarkm } 2989109998Smarkm comp_time = ASN1_GENERALIZEDTIME_new(); 2990109998Smarkm if (!ASN1_GENERALIZEDTIME_set_string(comp_time, arg_str)) 2991109998Smarkm { 2992109998Smarkm BIO_printf(bio_err, "invalid compromised time %s\n", arg_str); 2993109998Smarkm goto err; 2994109998Smarkm } 2995109998Smarkm if (reason_code == 9) 2996109998Smarkm reason_code = OCSP_REVOKED_STATUS_KEYCOMPROMISE; 2997109998Smarkm else 2998109998Smarkm reason_code = OCSP_REVOKED_STATUS_CACOMPROMISE; 2999109998Smarkm } 3000109998Smarkm } 3001109998Smarkm 3002109998Smarkm if (preason) *preason = reason_code; 3003109998Smarkm if (pinvtm) *pinvtm = comp_time; 3004109998Smarkm else ASN1_GENERALIZEDTIME_free(comp_time); 3005109998Smarkm 3006109998Smarkm ret = 1; 3007109998Smarkm 3008109998Smarkm err: 3009109998Smarkm 3010109998Smarkm if (tmp) OPENSSL_free(tmp); 3011109998Smarkm if (!phold) ASN1_OBJECT_free(hold); 3012109998Smarkm if (!pinvtm) ASN1_GENERALIZEDTIME_free(comp_time); 3013109998Smarkm 3014109998Smarkm return ret; 3015109998Smarkm } 3016