ca.c revision 279265
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 <sys/stat.h> 6755714Skris#include <openssl/conf.h> 6855714Skris#include <openssl/bio.h> 6955714Skris#include <openssl/err.h> 7055714Skris#include <openssl/bn.h> 7155714Skris#include <openssl/txt_db.h> 7255714Skris#include <openssl/evp.h> 7355714Skris#include <openssl/x509.h> 7455714Skris#include <openssl/x509v3.h> 7555714Skris#include <openssl/objects.h> 76109998Smarkm#include <openssl/ocsp.h> 7755714Skris#include <openssl/pem.h> 7855714Skris 7955714Skris#ifndef W_OK 80109998Smarkm# ifdef OPENSSL_SYS_VMS 8155714Skris# if defined(__DECC) 8255714Skris# include <unistd.h> 8355714Skris# else 8455714Skris# include <unixlib.h> 8555714Skris# endif 86194206Ssimon# elif !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_NETWARE) && !defined(__TANDEM) 8755714Skris# include <sys/file.h> 8855714Skris# endif 8955714Skris#endif 9055714Skris 91109998Smarkm#include "apps.h" 92109998Smarkm 9355714Skris#ifndef W_OK 9455714Skris# define F_OK 0 9555714Skris# define X_OK 1 9655714Skris# define W_OK 2 9755714Skris# define R_OK 4 9855714Skris#endif 9955714Skris 10055714Skris#undef PROG 10155714Skris#define PROG ca_main 10255714Skris 10355714Skris#define BASE_SECTION "ca" 10455714Skris#define CONFIG_FILE "openssl.cnf" 10555714Skris 10655714Skris#define ENV_DEFAULT_CA "default_ca" 10755714Skris 108160814Ssimon#define STRING_MASK "string_mask" 109160814Ssimon#define UTF8_IN "utf8" 110160814Ssimon 11155714Skris#define ENV_DIR "dir" 11255714Skris#define ENV_CERTS "certs" 11355714Skris#define ENV_CRL_DIR "crl_dir" 11455714Skris#define ENV_CA_DB "CA_DB" 11555714Skris#define ENV_NEW_CERTS_DIR "new_certs_dir" 11655714Skris#define ENV_CERTIFICATE "certificate" 11755714Skris#define ENV_SERIAL "serial" 118127128Snectar#define ENV_CRLNUMBER "crlnumber" 11955714Skris#define ENV_CRL "crl" 12055714Skris#define ENV_PRIVATE_KEY "private_key" 12155714Skris#define ENV_RANDFILE "RANDFILE" 12255714Skris#define ENV_DEFAULT_DAYS "default_days" 12355714Skris#define ENV_DEFAULT_STARTDATE "default_startdate" 12455714Skris#define ENV_DEFAULT_ENDDATE "default_enddate" 12555714Skris#define ENV_DEFAULT_CRL_DAYS "default_crl_days" 12655714Skris#define ENV_DEFAULT_CRL_HOURS "default_crl_hours" 12755714Skris#define ENV_DEFAULT_MD "default_md" 128109998Smarkm#define ENV_DEFAULT_EMAIL_DN "email_in_dn" 12955714Skris#define ENV_PRESERVE "preserve" 13055714Skris#define ENV_POLICY "policy" 13155714Skris#define ENV_EXTENSIONS "x509_extensions" 13255714Skris#define ENV_CRLEXT "crl_extensions" 13355714Skris#define ENV_MSIE_HACK "msie_hack" 134109998Smarkm#define ENV_NAMEOPT "name_opt" 135109998Smarkm#define ENV_CERTOPT "cert_opt" 136109998Smarkm#define ENV_EXTCOPY "copy_extensions" 137160814Ssimon#define ENV_UNIQUE_SUBJECT "unique_subject" 13855714Skris 13955714Skris#define ENV_DATABASE "database" 14055714Skris 141109998Smarkm/* Additional revocation information types */ 142109998Smarkm 143109998Smarkm#define REV_NONE 0 /* No addditional information */ 144109998Smarkm#define REV_CRL_REASON 1 /* Value is CRL reason code */ 145109998Smarkm#define REV_HOLD 2 /* Value is hold instruction */ 146109998Smarkm#define REV_KEY_COMPROMISE 3 /* Value is cert key compromise time */ 147109998Smarkm#define REV_CA_COMPROMISE 4 /* Value is CA key compromise time */ 148109998Smarkm 149160814Ssimonstatic const char *ca_usage[]={ 15055714Skris"usage: ca args\n", 15155714Skris"\n", 15255714Skris" -verbose - Talk alot while doing things\n", 15355714Skris" -config file - A config file\n", 15455714Skris" -name arg - The particular CA definition to use\n", 15555714Skris" -gencrl - Generate a new CRL\n", 15655714Skris" -crldays days - Days is when the next CRL is due\n", 15755714Skris" -crlhours hours - Hours is when the next CRL is due\n", 15859191Skris" -startdate YYMMDDHHMMSSZ - certificate validity notBefore\n", 15959191Skris" -enddate YYMMDDHHMMSSZ - certificate validity notAfter (overrides -days)\n", 16055714Skris" -days arg - number of days to certify the certificate for\n", 16155714Skris" -md arg - md to use, one of md2, md5, sha or sha1\n", 16255714Skris" -policy arg - The CA 'policy' to support\n", 163109998Smarkm" -keyfile arg - private key file\n", 164109998Smarkm" -keyform arg - private key file format (PEM or ENGINE)\n", 16555714Skris" -key arg - key to decode the private key if it is encrypted\n", 16655714Skris" -cert file - The CA certificate\n", 167160814Ssimon" -selfsign - sign a certificate with the key associated with it\n", 16855714Skris" -in file - The input PEM encoded certificate request(s)\n", 16955714Skris" -out file - Where to put the output file(s)\n", 17055714Skris" -outdir dir - Where to put output certificates\n", 17155714Skris" -infiles .... - The last argument, requests to process\n", 17255714Skris" -spkac file - File contains DN and signed public key and challenge\n", 17355714Skris" -ss_cert file - File contains a self signed cert to sign\n", 17455714Skris" -preserveDN - Don't re-order the DN\n", 175109998Smarkm" -noemailDN - Don't add the EMAIL field into certificate' subject\n", 17655714Skris" -batch - Don't ask questions\n", 17755714Skris" -msie_hack - msie modifications to handle all those universal strings\n", 17855714Skris" -revoke file - Revoke a certificate (given in file)\n", 179109998Smarkm" -subj arg - Use arg instead of request's subject\n", 180160814Ssimon" -utf8 - input characters are UTF8 (default ASCII)\n", 181160814Ssimon" -multivalue-rdn - enable support for multivalued RDNs\n", 18259191Skris" -extensions .. - Extension section (override value in config file)\n", 183109998Smarkm" -extfile file - Configuration file with X509v3 extentions to add\n", 18459191Skris" -crlexts .. - CRL extension section (override value in config file)\n", 185111147Snectar#ifndef OPENSSL_NO_ENGINE 186109998Smarkm" -engine e - use engine e, possibly a hardware device.\n", 187111147Snectar#endif 188109998Smarkm" -status serial - Shows certificate status given the serial number\n", 189109998Smarkm" -updatedb - Updates db for expired certificates\n", 19055714SkrisNULL 19155714Skris}; 19255714Skris 19355714Skris#ifdef EFENCE 19455714Skrisextern int EF_PROTECT_FREE; 19555714Skrisextern int EF_PROTECT_BELOW; 19655714Skrisextern int EF_ALIGNMENT; 19755714Skris#endif 19855714Skris 199160814Ssimonstatic void lookup_fail(const char *name, const char *tag); 20055714Skrisstatic int certify(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509, 201127128Snectar const EVP_MD *dgst,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, 20755714Skris const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy, 208160814Ssimon CA_DB *db, BIGNUM *serial, char *subj,unsigned long chtype, int multirdn, int email_dn, 209109998Smarkm char *startdate, char *enddate, long days, int batch, 210109998Smarkm char *ext_sect, CONF *conf,int verbose, unsigned long certopt, 211109998Smarkm unsigned long nameopt, int default_op, int ext_copy, 212109998Smarkm ENGINE *e); 21355714Skrisstatic int certify_spkac(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509, 21455714Skris const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy, 215160814Ssimon CA_DB *db, BIGNUM *serial,char *subj,unsigned long chtype, int multirdn, int email_dn, 216109998Smarkm char *startdate, char *enddate, long days, char *ext_sect, 217109998Smarkm CONF *conf, int verbose, unsigned long certopt, 218109998Smarkm unsigned long nameopt, int default_op, int ext_copy); 21959191Skrisstatic void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext); 22055714Skrisstatic int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, 221160814Ssimon STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial,char *subj,unsigned long chtype, int multirdn, 222109998Smarkm int email_dn, char *startdate, char *enddate, long days, int batch, 223109998Smarkm int verbose, X509_REQ *req, char *ext_sect, CONF *conf, 224109998Smarkm unsigned long certopt, unsigned long nameopt, int default_op, 225160814Ssimon int ext_copy, int selfsign); 226127128Snectarstatic int do_revoke(X509 *x509, CA_DB *db, int ext, char *extval); 227127128Snectarstatic int get_certificate_status(const char *ser_status, CA_DB *db); 228127128Snectarstatic int do_updatedb(CA_DB *db); 229205128Ssimonstatic int check_time_format(const char *str); 230109998Smarkmchar *make_revocation_str(int rev_type, char *rev_arg); 231160814Ssimonint make_revoked(X509_REVOKED *rev, const char *str); 232109998Smarkmint old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str); 233109998Smarkmstatic CONF *conf=NULL; 234109998Smarkmstatic CONF *extconf=NULL; 23555714Skrisstatic char *section=NULL; 23655714Skris 23755714Skrisstatic int preserve=0; 23855714Skrisstatic int msie_hack=0; 23955714Skris 240109998Smarkm 24159191Skrisint MAIN(int, char **); 24259191Skris 24355714Skrisint MAIN(int argc, char **argv) 24455714Skris { 245109998Smarkm ENGINE *e = NULL; 24668651Skris char *key=NULL,*passargin=NULL; 247142425Snectar int create_ser = 0; 248109998Smarkm int free_key = 0; 24955714Skris int total=0; 25055714Skris int total_done=0; 25155714Skris int badops=0; 25255714Skris int ret=1; 253109998Smarkm int email_dn=1; 25455714Skris int req=0; 25555714Skris int verbose=0; 25655714Skris int gencrl=0; 25755714Skris int dorevoke=0; 258109998Smarkm int doupdatedb=0; 25955714Skris long crldays=0; 26055714Skris long crlhours=0; 26155714Skris long errorline= -1; 26255714Skris char *configfile=NULL; 26355714Skris char *md=NULL; 26455714Skris char *policy=NULL; 26555714Skris char *keyfile=NULL; 26655714Skris char *certfile=NULL; 267109998Smarkm int keyform=FORMAT_PEM; 26855714Skris char *infile=NULL; 26955714Skris char *spkac_file=NULL; 27055714Skris char *ss_cert_file=NULL; 271109998Smarkm char *ser_status=NULL; 27255714Skris EVP_PKEY *pkey=NULL; 27355714Skris int output_der = 0; 27455714Skris char *outfile=NULL; 27555714Skris char *outdir=NULL; 27655714Skris char *serialfile=NULL; 277127128Snectar char *crlnumberfile=NULL; 27855714Skris char *extensions=NULL; 279109998Smarkm char *extfile=NULL; 280109998Smarkm char *subj=NULL; 281160814Ssimon unsigned long chtype = MBSTRING_ASC; 282160814Ssimon int multirdn = 0; 283109998Smarkm char *tmp_email_dn=NULL; 28455714Skris char *crl_ext=NULL; 285109998Smarkm int rev_type = REV_NONE; 286109998Smarkm char *rev_arg = NULL; 28755714Skris BIGNUM *serial=NULL; 288127128Snectar BIGNUM *crlnumber=NULL; 28955714Skris char *startdate=NULL; 29055714Skris char *enddate=NULL; 291109998Smarkm long days=0; 29255714Skris int batch=0; 29359191Skris int notext=0; 294109998Smarkm unsigned long nameopt = 0, certopt = 0; 295109998Smarkm int default_op = 1; 296109998Smarkm int ext_copy = EXT_COPY_NONE; 297160814Ssimon int selfsign = 0; 298160814Ssimon X509 *x509=NULL, *x509p = NULL; 29955714Skris X509 *x=NULL; 30055714Skris BIO *in=NULL,*out=NULL,*Sout=NULL,*Cout=NULL; 30155714Skris char *dbfile=NULL; 302127128Snectar CA_DB *db=NULL; 30355714Skris X509_CRL *crl=NULL; 30455714Skris X509_REVOKED *r=NULL; 305109998Smarkm ASN1_TIME *tmptm; 306109998Smarkm ASN1_INTEGER *tmpser; 307160814Ssimon char *f; 308160814Ssimon const char *p, **pp; 30955714Skris int i,j; 31055714Skris const EVP_MD *dgst=NULL; 31155714Skris STACK_OF(CONF_VALUE) *attribs=NULL; 31268651Skris STACK_OF(X509) *cert_sk=NULL; 31355714Skris#undef BSIZE 31455714Skris#define BSIZE 256 31555714Skris MS_STATIC char buf[3][BSIZE]; 31659191Skris char *randfile=NULL; 317111147Snectar#ifndef OPENSSL_NO_ENGINE 318109998Smarkm char *engine = NULL; 319111147Snectar#endif 320109998Smarkm char *tofree=NULL; 321127128Snectar DB_ATTR db_attr; 32255714Skris 32355714Skris#ifdef EFENCE 32455714SkrisEF_PROTECT_FREE=1; 32555714SkrisEF_PROTECT_BELOW=1; 32655714SkrisEF_ALIGNMENT=0; 32755714Skris#endif 32855714Skris 32955714Skris apps_startup(); 33055714Skris 33159191Skris conf = NULL; 33259191Skris key = NULL; 33359191Skris section = NULL; 33455714Skris 33555714Skris preserve=0; 33659191Skris msie_hack=0; 33755714Skris if (bio_err == NULL) 33855714Skris if ((bio_err=BIO_new(BIO_s_file())) != NULL) 33955714Skris BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT); 34055714Skris 34155714Skris argc--; 34255714Skris argv++; 34355714Skris while (argc >= 1) 34455714Skris { 34555714Skris if (strcmp(*argv,"-verbose") == 0) 34655714Skris verbose=1; 34755714Skris else if (strcmp(*argv,"-config") == 0) 34855714Skris { 34955714Skris if (--argc < 1) goto bad; 35055714Skris configfile= *(++argv); 35155714Skris } 35255714Skris else if (strcmp(*argv,"-name") == 0) 35355714Skris { 35455714Skris if (--argc < 1) goto bad; 35555714Skris section= *(++argv); 35655714Skris } 357109998Smarkm else if (strcmp(*argv,"-subj") == 0) 358109998Smarkm { 359109998Smarkm if (--argc < 1) goto bad; 360109998Smarkm subj= *(++argv); 361109998Smarkm /* preserve=1; */ 362109998Smarkm } 363160814Ssimon else if (strcmp(*argv,"-utf8") == 0) 364160814Ssimon chtype = MBSTRING_UTF8; 365160814Ssimon else if (strcmp(*argv,"-create_serial") == 0) 366160814Ssimon create_ser = 1; 367160814Ssimon else if (strcmp(*argv,"-multivalue-rdn") == 0) 368160814Ssimon multirdn=1; 36955714Skris else if (strcmp(*argv,"-startdate") == 0) 37055714Skris { 37155714Skris if (--argc < 1) goto bad; 37255714Skris startdate= *(++argv); 37355714Skris } 37455714Skris else if (strcmp(*argv,"-enddate") == 0) 37555714Skris { 37655714Skris if (--argc < 1) goto bad; 37755714Skris enddate= *(++argv); 37855714Skris } 37955714Skris else if (strcmp(*argv,"-days") == 0) 38055714Skris { 38155714Skris if (--argc < 1) goto bad; 38255714Skris days=atoi(*(++argv)); 38355714Skris } 38455714Skris else if (strcmp(*argv,"-md") == 0) 38555714Skris { 38655714Skris if (--argc < 1) goto bad; 38755714Skris md= *(++argv); 38855714Skris } 38955714Skris else if (strcmp(*argv,"-policy") == 0) 39055714Skris { 39155714Skris if (--argc < 1) goto bad; 39255714Skris policy= *(++argv); 39355714Skris } 39455714Skris else if (strcmp(*argv,"-keyfile") == 0) 39555714Skris { 39655714Skris if (--argc < 1) goto bad; 39755714Skris keyfile= *(++argv); 39855714Skris } 399109998Smarkm else if (strcmp(*argv,"-keyform") == 0) 400109998Smarkm { 401109998Smarkm if (--argc < 1) goto bad; 402109998Smarkm keyform=str2fmt(*(++argv)); 403109998Smarkm } 40468651Skris else if (strcmp(*argv,"-passin") == 0) 40568651Skris { 40668651Skris if (--argc < 1) goto bad; 40768651Skris passargin= *(++argv); 40868651Skris } 40955714Skris else if (strcmp(*argv,"-key") == 0) 41055714Skris { 41155714Skris if (--argc < 1) goto bad; 41255714Skris key= *(++argv); 41355714Skris } 41455714Skris else if (strcmp(*argv,"-cert") == 0) 41555714Skris { 41655714Skris if (--argc < 1) goto bad; 41755714Skris certfile= *(++argv); 41855714Skris } 419160814Ssimon else if (strcmp(*argv,"-selfsign") == 0) 420160814Ssimon selfsign=1; 42155714Skris else if (strcmp(*argv,"-in") == 0) 42255714Skris { 42355714Skris if (--argc < 1) goto bad; 42455714Skris infile= *(++argv); 42555714Skris req=1; 42655714Skris } 42755714Skris else if (strcmp(*argv,"-out") == 0) 42855714Skris { 42955714Skris if (--argc < 1) goto bad; 43055714Skris outfile= *(++argv); 43155714Skris } 43255714Skris else if (strcmp(*argv,"-outdir") == 0) 43355714Skris { 43455714Skris if (--argc < 1) goto bad; 43555714Skris outdir= *(++argv); 43655714Skris } 43759191Skris else if (strcmp(*argv,"-notext") == 0) 43859191Skris notext=1; 43955714Skris else if (strcmp(*argv,"-batch") == 0) 44055714Skris batch=1; 44155714Skris else if (strcmp(*argv,"-preserveDN") == 0) 44255714Skris preserve=1; 443109998Smarkm else if (strcmp(*argv,"-noemailDN") == 0) 444109998Smarkm email_dn=0; 44555714Skris else if (strcmp(*argv,"-gencrl") == 0) 44655714Skris gencrl=1; 44755714Skris else if (strcmp(*argv,"-msie_hack") == 0) 44855714Skris msie_hack=1; 44955714Skris else if (strcmp(*argv,"-crldays") == 0) 45055714Skris { 45155714Skris if (--argc < 1) goto bad; 45255714Skris crldays= atol(*(++argv)); 45355714Skris } 45455714Skris else if (strcmp(*argv,"-crlhours") == 0) 45555714Skris { 45655714Skris if (--argc < 1) goto bad; 45755714Skris crlhours= atol(*(++argv)); 45855714Skris } 45955714Skris else if (strcmp(*argv,"-infiles") == 0) 46055714Skris { 46155714Skris argc--; 46255714Skris argv++; 46355714Skris req=1; 46455714Skris break; 46555714Skris } 46655714Skris else if (strcmp(*argv, "-ss_cert") == 0) 46755714Skris { 46855714Skris if (--argc < 1) goto bad; 46955714Skris ss_cert_file = *(++argv); 47055714Skris req=1; 47155714Skris } 47255714Skris else if (strcmp(*argv, "-spkac") == 0) 47355714Skris { 47455714Skris if (--argc < 1) goto bad; 47555714Skris spkac_file = *(++argv); 47655714Skris req=1; 47755714Skris } 47855714Skris else if (strcmp(*argv,"-revoke") == 0) 47955714Skris { 48055714Skris if (--argc < 1) goto bad; 48155714Skris infile= *(++argv); 48255714Skris dorevoke=1; 48355714Skris } 48459191Skris else if (strcmp(*argv,"-extensions") == 0) 48559191Skris { 48659191Skris if (--argc < 1) goto bad; 48759191Skris extensions= *(++argv); 48859191Skris } 489109998Smarkm else if (strcmp(*argv,"-extfile") == 0) 490109998Smarkm { 491109998Smarkm if (--argc < 1) goto bad; 492109998Smarkm extfile= *(++argv); 493109998Smarkm } 494109998Smarkm else if (strcmp(*argv,"-status") == 0) 495109998Smarkm { 496109998Smarkm if (--argc < 1) goto bad; 497109998Smarkm ser_status= *(++argv); 498109998Smarkm } 499109998Smarkm else if (strcmp(*argv,"-updatedb") == 0) 500109998Smarkm { 501109998Smarkm doupdatedb=1; 502109998Smarkm } 50359191Skris else if (strcmp(*argv,"-crlexts") == 0) 50459191Skris { 50559191Skris if (--argc < 1) goto bad; 50659191Skris crl_ext= *(++argv); 50759191Skris } 508109998Smarkm else if (strcmp(*argv,"-crl_reason") == 0) 509109998Smarkm { 510109998Smarkm if (--argc < 1) goto bad; 511109998Smarkm rev_arg = *(++argv); 512109998Smarkm rev_type = REV_CRL_REASON; 513109998Smarkm } 514109998Smarkm else if (strcmp(*argv,"-crl_hold") == 0) 515109998Smarkm { 516109998Smarkm if (--argc < 1) goto bad; 517109998Smarkm rev_arg = *(++argv); 518109998Smarkm rev_type = REV_HOLD; 519109998Smarkm } 520109998Smarkm else if (strcmp(*argv,"-crl_compromise") == 0) 521109998Smarkm { 522109998Smarkm if (--argc < 1) goto bad; 523109998Smarkm rev_arg = *(++argv); 524109998Smarkm rev_type = REV_KEY_COMPROMISE; 525109998Smarkm } 526109998Smarkm else if (strcmp(*argv,"-crl_CA_compromise") == 0) 527109998Smarkm { 528109998Smarkm if (--argc < 1) goto bad; 529109998Smarkm rev_arg = *(++argv); 530109998Smarkm rev_type = REV_CA_COMPROMISE; 531109998Smarkm } 532111147Snectar#ifndef OPENSSL_NO_ENGINE 533109998Smarkm else if (strcmp(*argv,"-engine") == 0) 534109998Smarkm { 535109998Smarkm if (--argc < 1) goto bad; 536109998Smarkm engine= *(++argv); 537109998Smarkm } 538111147Snectar#endif 53955714Skris else 54055714Skris { 54155714Skrisbad: 54255714Skris BIO_printf(bio_err,"unknown option %s\n",*argv); 54355714Skris badops=1; 54455714Skris break; 54555714Skris } 54655714Skris argc--; 54755714Skris argv++; 54855714Skris } 54955714Skris 55055714Skris if (badops) 55155714Skris { 55255714Skris for (pp=ca_usage; (*pp != NULL); pp++) 553109998Smarkm BIO_printf(bio_err,"%s",*pp); 55455714Skris goto err; 55555714Skris } 55655714Skris 55755714Skris ERR_load_crypto_strings(); 55855714Skris 55955714Skris /*****************************************************************/ 560109998Smarkm tofree=NULL; 56155714Skris if (configfile == NULL) configfile = getenv("OPENSSL_CONF"); 56255714Skris if (configfile == NULL) configfile = getenv("SSLEAY_CONF"); 56355714Skris if (configfile == NULL) 56455714Skris { 565109998Smarkm const char *s=X509_get_default_cert_area(); 566127128Snectar size_t len; 567109998Smarkm 568109998Smarkm#ifdef OPENSSL_SYS_VMS 569127128Snectar len = strlen(s)+sizeof(CONFIG_FILE); 570127128Snectar tofree=OPENSSL_malloc(len); 571109998Smarkm strcpy(tofree,s); 57255714Skris#else 573127128Snectar len = strlen(s)+sizeof(CONFIG_FILE)+1; 574127128Snectar tofree=OPENSSL_malloc(len); 575127128Snectar BUF_strlcpy(tofree,s,len); 576127128Snectar BUF_strlcat(tofree,"/",len); 57755714Skris#endif 578127128Snectar BUF_strlcat(tofree,CONFIG_FILE,len); 579109998Smarkm configfile=tofree; 58055714Skris } 58155714Skris 58255714Skris BIO_printf(bio_err,"Using configuration from %s\n",configfile); 583109998Smarkm conf = NCONF_new(NULL); 584109998Smarkm if (NCONF_load(conf,configfile,&errorline) <= 0) 58555714Skris { 58655714Skris if (errorline <= 0) 58755714Skris BIO_printf(bio_err,"error loading the config file '%s'\n", 58855714Skris configfile); 58955714Skris else 59055714Skris BIO_printf(bio_err,"error on line %ld of config file '%s'\n" 59155714Skris ,errorline,configfile); 59255714Skris goto err; 59355714Skris } 594109998Smarkm if(tofree) 595111147Snectar { 596109998Smarkm OPENSSL_free(tofree); 597111147Snectar tofree = NULL; 598111147Snectar } 59955714Skris 600109998Smarkm if (!load_config(bio_err, conf)) 601109998Smarkm goto err; 602109998Smarkm 603142425Snectar#ifndef OPENSSL_NO_ENGINE 604142425Snectar e = setup_engine(bio_err, engine, 0); 605142425Snectar#endif 606142425Snectar 60755714Skris /* Lets get the config section we are using */ 60855714Skris if (section == NULL) 60955714Skris { 610109998Smarkm section=NCONF_get_string(conf,BASE_SECTION,ENV_DEFAULT_CA); 61155714Skris if (section == NULL) 61255714Skris { 61355714Skris lookup_fail(BASE_SECTION,ENV_DEFAULT_CA); 61455714Skris goto err; 61555714Skris } 61655714Skris } 61755714Skris 61855714Skris if (conf != NULL) 61955714Skris { 620109998Smarkm p=NCONF_get_string(conf,NULL,"oid_file"); 621109998Smarkm if (p == NULL) 622109998Smarkm ERR_clear_error(); 62355714Skris if (p != NULL) 62455714Skris { 62555714Skris BIO *oid_bio; 62655714Skris 62755714Skris oid_bio=BIO_new_file(p,"r"); 62855714Skris if (oid_bio == NULL) 62955714Skris { 63055714Skris /* 63155714Skris BIO_printf(bio_err,"problems opening %s for extra oid's\n",p); 63255714Skris ERR_print_errors(bio_err); 63355714Skris */ 63455714Skris ERR_clear_error(); 63555714Skris } 63655714Skris else 63755714Skris { 63855714Skris OBJ_create_objects(oid_bio); 63955714Skris BIO_free(oid_bio); 64055714Skris } 64155714Skris } 642109998Smarkm if (!add_oid_section(bio_err,conf)) 64359191Skris { 64455714Skris ERR_print_errors(bio_err); 64555714Skris goto err; 64659191Skris } 64755714Skris } 64855714Skris 649109998Smarkm randfile = NCONF_get_string(conf, BASE_SECTION, "RANDFILE"); 650109998Smarkm if (randfile == NULL) 651109998Smarkm ERR_clear_error(); 65259191Skris app_RAND_load_file(randfile, bio_err, 0); 653127128Snectar 654160814Ssimon f = NCONF_get_string(conf, section, STRING_MASK); 655160814Ssimon if (!f) 656160814Ssimon ERR_clear_error(); 657160814Ssimon 658160814Ssimon if(f && !ASN1_STRING_set_default_mask_asc(f)) { 659160814Ssimon BIO_printf(bio_err, "Invalid global string mask setting %s\n", f); 660160814Ssimon goto err; 661160814Ssimon } 662160814Ssimon 663160814Ssimon if (chtype != MBSTRING_UTF8){ 664160814Ssimon f = NCONF_get_string(conf, section, UTF8_IN); 665160814Ssimon if (!f) 666160814Ssimon ERR_clear_error(); 667160814Ssimon else if (!strcmp(f, "yes")) 668160814Ssimon chtype = MBSTRING_UTF8; 669160814Ssimon } 670160814Ssimon 671127128Snectar db_attr.unique_subject = 1; 672160814Ssimon p = NCONF_get_string(conf, section, ENV_UNIQUE_SUBJECT); 673127128Snectar if (p) 674127128Snectar { 675127128Snectar#ifdef RL_DEBUG 676127128Snectar BIO_printf(bio_err, "DEBUG: unique_subject = \"%s\"\n", p); 677127128Snectar#endif 678160814Ssimon db_attr.unique_subject = parse_yesno(p,1); 679127128Snectar } 680142425Snectar else 681142425Snectar ERR_clear_error(); 682127128Snectar#ifdef RL_DEBUG 683142425Snectar if (!p) 684127128Snectar BIO_printf(bio_err, "DEBUG: unique_subject undefined\n", p); 685127128Snectar#endif 686127128Snectar#ifdef RL_DEBUG 687127128Snectar BIO_printf(bio_err, "DEBUG: configured unique_subject is %d\n", 688127128Snectar db_attr.unique_subject); 689127128Snectar#endif 69059191Skris 69155714Skris in=BIO_new(BIO_s_file()); 69255714Skris out=BIO_new(BIO_s_file()); 69355714Skris Sout=BIO_new(BIO_s_file()); 69455714Skris Cout=BIO_new(BIO_s_file()); 69555714Skris if ((in == NULL) || (out == NULL) || (Sout == NULL) || (Cout == NULL)) 69655714Skris { 69755714Skris ERR_print_errors(bio_err); 69855714Skris goto err; 69955714Skris } 70055714Skris 70155714Skris /*****************************************************************/ 702109998Smarkm /* report status of cert with serial number given on command line */ 703109998Smarkm if (ser_status) 704109998Smarkm { 705109998Smarkm if ((dbfile=NCONF_get_string(conf,section,ENV_DATABASE)) == NULL) 706109998Smarkm { 707109998Smarkm lookup_fail(section,ENV_DATABASE); 708109998Smarkm goto err; 709109998Smarkm } 710127128Snectar db = load_index(dbfile,&db_attr); 711109998Smarkm if (db == NULL) goto err; 71255714Skris 713127128Snectar if (!index_index(db)) goto err; 714109998Smarkm 715109998Smarkm if (get_certificate_status(ser_status,db) != 1) 716109998Smarkm BIO_printf(bio_err,"Error verifying serial %s!\n", 717109998Smarkm ser_status); 718109998Smarkm goto err; 719109998Smarkm } 720109998Smarkm 721109998Smarkm /*****************************************************************/ 722160814Ssimon /* we definitely need a private key, so let's get it */ 723109998Smarkm 724109998Smarkm if ((keyfile == NULL) && ((keyfile=NCONF_get_string(conf, 72555714Skris section,ENV_PRIVATE_KEY)) == NULL)) 72655714Skris { 72755714Skris lookup_fail(section,ENV_PRIVATE_KEY); 72855714Skris goto err; 72955714Skris } 730109998Smarkm if (!key) 73168651Skris { 732109998Smarkm free_key = 1; 733109998Smarkm if (!app_passwd(bio_err, passargin, NULL, &key, NULL)) 734109998Smarkm { 735109998Smarkm BIO_printf(bio_err,"Error getting password\n"); 736109998Smarkm goto err; 737109998Smarkm } 73868651Skris } 739109998Smarkm pkey = load_key(bio_err, keyfile, keyform, 0, key, e, 740109998Smarkm "CA private key"); 741109998Smarkm if (key) OPENSSL_cleanse(key,strlen(key)); 74255714Skris if (pkey == NULL) 74355714Skris { 744109998Smarkm /* load_key() has already printed an appropriate message */ 74555714Skris goto err; 74655714Skris } 74755714Skris 74855714Skris /*****************************************************************/ 74955714Skris /* we need a certificate */ 750160814Ssimon if (!selfsign || spkac_file || ss_cert_file || gencrl) 75155714Skris { 752160814Ssimon if ((certfile == NULL) 753160814Ssimon && ((certfile=NCONF_get_string(conf, 754160814Ssimon section,ENV_CERTIFICATE)) == NULL)) 755160814Ssimon { 756160814Ssimon lookup_fail(section,ENV_CERTIFICATE); 757160814Ssimon goto err; 758160814Ssimon } 759160814Ssimon x509=load_cert(bio_err, certfile, FORMAT_PEM, NULL, e, 760160814Ssimon "CA certificate"); 761160814Ssimon if (x509 == NULL) 762160814Ssimon goto err; 76355714Skris 764160814Ssimon if (!X509_check_private_key(x509,pkey)) 765160814Ssimon { 766160814Ssimon BIO_printf(bio_err,"CA certificate and CA private key do not match\n"); 767160814Ssimon goto err; 768160814Ssimon } 76955714Skris } 770160814Ssimon if (!selfsign) x509p = x509; 77155714Skris 772109998Smarkm f=NCONF_get_string(conf,BASE_SECTION,ENV_PRESERVE); 773109998Smarkm if (f == NULL) 774109998Smarkm ERR_clear_error(); 77555714Skris if ((f != NULL) && ((*f == 'y') || (*f == 'Y'))) 77655714Skris preserve=1; 777109998Smarkm f=NCONF_get_string(conf,BASE_SECTION,ENV_MSIE_HACK); 778109998Smarkm if (f == NULL) 779109998Smarkm ERR_clear_error(); 78055714Skris if ((f != NULL) && ((*f == 'y') || (*f == 'Y'))) 78155714Skris msie_hack=1; 78255714Skris 783109998Smarkm f=NCONF_get_string(conf,section,ENV_NAMEOPT); 784109998Smarkm 785109998Smarkm if (f) 786109998Smarkm { 787109998Smarkm if (!set_name_ex(&nameopt, f)) 788109998Smarkm { 789109998Smarkm BIO_printf(bio_err, "Invalid name options: \"%s\"\n", f); 790109998Smarkm goto err; 791109998Smarkm } 792109998Smarkm default_op = 0; 793109998Smarkm } 794109998Smarkm else 795109998Smarkm ERR_clear_error(); 796109998Smarkm 797109998Smarkm f=NCONF_get_string(conf,section,ENV_CERTOPT); 798109998Smarkm 799109998Smarkm if (f) 800109998Smarkm { 801109998Smarkm if (!set_cert_ex(&certopt, f)) 802109998Smarkm { 803109998Smarkm BIO_printf(bio_err, "Invalid certificate options: \"%s\"\n", f); 804109998Smarkm goto err; 805109998Smarkm } 806109998Smarkm default_op = 0; 807109998Smarkm } 808109998Smarkm else 809109998Smarkm ERR_clear_error(); 810109998Smarkm 811109998Smarkm f=NCONF_get_string(conf,section,ENV_EXTCOPY); 812109998Smarkm 813109998Smarkm if (f) 814109998Smarkm { 815109998Smarkm if (!set_ext_copy(&ext_copy, f)) 816109998Smarkm { 817109998Smarkm BIO_printf(bio_err, "Invalid extension copy option: \"%s\"\n", f); 818109998Smarkm goto err; 819109998Smarkm } 820109998Smarkm } 821109998Smarkm else 822109998Smarkm ERR_clear_error(); 823109998Smarkm 82455714Skris /*****************************************************************/ 82555714Skris /* lookup where to write new certificates */ 82655714Skris if ((outdir == NULL) && (req)) 82755714Skris { 82855714Skris struct stat sb; 82955714Skris 830109998Smarkm if ((outdir=NCONF_get_string(conf,section,ENV_NEW_CERTS_DIR)) 83155714Skris == NULL) 83255714Skris { 83355714Skris BIO_printf(bio_err,"there needs to be defined a directory for new certificate to be placed in\n"); 83455714Skris goto err; 83555714Skris } 836109998Smarkm#ifndef OPENSSL_SYS_VMS 837109998Smarkm /* outdir is a directory spec, but access() for VMS demands a 83859191Skris filename. In any case, stat(), below, will catch the problem 83959191Skris if outdir is not a directory spec, and the fopen() or open() 84059191Skris will catch an error if there is no write access. 84159191Skris 84259191Skris Presumably, this problem could also be solved by using the DEC 84359191Skris C routines to convert the directory syntax to Unixly, and give 84459191Skris that to access(). However, time's too short to do that just 84559191Skris now. 846109998Smarkm */ 84755714Skris if (access(outdir,R_OK|W_OK|X_OK) != 0) 84855714Skris { 84959191Skris BIO_printf(bio_err,"I am unable to access the %s directory\n",outdir); 85055714Skris perror(outdir); 85155714Skris goto err; 85255714Skris } 85355714Skris 85455714Skris if (stat(outdir,&sb) != 0) 85555714Skris { 85655714Skris BIO_printf(bio_err,"unable to stat(%s)\n",outdir); 85755714Skris perror(outdir); 85855714Skris goto err; 85955714Skris } 860205128Ssimon#ifdef S_ISDIR 861205128Ssimon if (!S_ISDIR(sb.st_mode)) 86255714Skris { 86355714Skris BIO_printf(bio_err,"%s need to be a directory\n",outdir); 86455714Skris perror(outdir); 86555714Skris goto err; 86655714Skris } 86759191Skris#endif 86859191Skris#endif 86955714Skris } 87055714Skris 87155714Skris /*****************************************************************/ 87255714Skris /* we need to load the database file */ 873109998Smarkm if ((dbfile=NCONF_get_string(conf,section,ENV_DATABASE)) == NULL) 87455714Skris { 87555714Skris lookup_fail(section,ENV_DATABASE); 87655714Skris goto err; 87755714Skris } 878127128Snectar db = load_index(dbfile, &db_attr); 87955714Skris if (db == NULL) goto err; 88055714Skris 88155714Skris /* Lets check some fields */ 882127128Snectar for (i=0; i<sk_num(db->db->data); i++) 88355714Skris { 884160814Ssimon pp=(const char **)sk_value(db->db->data,i); 88555714Skris if ((pp[DB_type][0] != DB_TYPE_REV) && 88655714Skris (pp[DB_rev_date][0] != '\0')) 88755714Skris { 88855714Skris BIO_printf(bio_err,"entry %d: not revoked yet, but has a revocation date\n",i+1); 88955714Skris goto err; 89055714Skris } 89155714Skris if ((pp[DB_type][0] == DB_TYPE_REV) && 892109998Smarkm !make_revoked(NULL, pp[DB_rev_date])) 89355714Skris { 894109998Smarkm BIO_printf(bio_err," in entry %d\n", i+1); 89555714Skris goto err; 89655714Skris } 897205128Ssimon if (!check_time_format(pp[DB_exp_date])) 89855714Skris { 89955714Skris BIO_printf(bio_err,"entry %d: invalid expiry date\n",i+1); 90055714Skris goto err; 90155714Skris } 90255714Skris p=pp[DB_serial]; 90355714Skris j=strlen(p); 904109998Smarkm if (*p == '-') 905109998Smarkm { 906109998Smarkm p++; 907109998Smarkm j--; 908109998Smarkm } 90955714Skris if ((j&1) || (j < 2)) 91055714Skris { 91155714Skris BIO_printf(bio_err,"entry %d: bad serial number length (%d)\n",i+1,j); 91255714Skris goto err; 91355714Skris } 91455714Skris while (*p) 91555714Skris { 91655714Skris if (!( ((*p >= '0') && (*p <= '9')) || 91755714Skris ((*p >= 'A') && (*p <= 'F')) || 91855714Skris ((*p >= 'a') && (*p <= 'f'))) ) 91955714Skris { 92055714Skris 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); 92155714Skris goto err; 92255714Skris } 92355714Skris p++; 92455714Skris } 92555714Skris } 92655714Skris if (verbose) 92755714Skris { 92855714Skris BIO_set_fp(out,stdout,BIO_NOCLOSE|BIO_FP_TEXT); /* cannot fail */ 929109998Smarkm#ifdef OPENSSL_SYS_VMS 93068651Skris { 93168651Skris BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 93268651Skris out = BIO_push(tmpbio, out); 93368651Skris } 93468651Skris#endif 935127128Snectar TXT_DB_write(out,db->db); 93655714Skris BIO_printf(bio_err,"%d entries loaded from the database\n", 937127128Snectar db->db->data->num); 93859191Skris BIO_printf(bio_err,"generating index\n"); 93955714Skris } 94055714Skris 941127128Snectar if (!index_index(db)) goto err; 94255714Skris 94355714Skris /*****************************************************************/ 944109998Smarkm /* Update the db file for expired certificates */ 945109998Smarkm if (doupdatedb) 946109998Smarkm { 947109998Smarkm if (verbose) 948109998Smarkm BIO_printf(bio_err, "Updating %s ...\n", 949109998Smarkm dbfile); 950109998Smarkm 951109998Smarkm i = do_updatedb(db); 952109998Smarkm if (i == -1) 953109998Smarkm { 954109998Smarkm BIO_printf(bio_err,"Malloc failure\n"); 955109998Smarkm goto err; 956109998Smarkm } 957109998Smarkm else if (i == 0) 958109998Smarkm { 959109998Smarkm if (verbose) BIO_printf(bio_err, 960109998Smarkm "No entries found to mark expired\n"); 961109998Smarkm } 962109998Smarkm else 963109998Smarkm { 964127128Snectar if (!save_index(dbfile,"new",db)) goto err; 965109998Smarkm 966127128Snectar if (!rotate_index(dbfile,"new","old")) goto err; 967127128Snectar 968109998Smarkm if (verbose) BIO_printf(bio_err, 969109998Smarkm "Done. %d entries marked as expired\n",i); 970109998Smarkm } 971109998Smarkm } 972109998Smarkm 973109998Smarkm /*****************************************************************/ 974109998Smarkm /* Read extentions config file */ 975109998Smarkm if (extfile) 976109998Smarkm { 977109998Smarkm extconf = NCONF_new(NULL); 978109998Smarkm if (NCONF_load(extconf,extfile,&errorline) <= 0) 979109998Smarkm { 980109998Smarkm if (errorline <= 0) 981109998Smarkm BIO_printf(bio_err, "ERROR: loading the config file '%s'\n", 982109998Smarkm extfile); 983109998Smarkm else 984109998Smarkm BIO_printf(bio_err, "ERROR: on line %ld of config file '%s'\n", 985109998Smarkm errorline,extfile); 986109998Smarkm ret = 1; 987109998Smarkm goto err; 988109998Smarkm } 989109998Smarkm 990109998Smarkm if (verbose) 991109998Smarkm BIO_printf(bio_err, "Successfully loaded extensions file %s\n", extfile); 992109998Smarkm 993109998Smarkm /* We can have sections in the ext file */ 994109998Smarkm if (!extensions && !(extensions = NCONF_get_string(extconf, "default", "extensions"))) 995109998Smarkm extensions = "default"; 996109998Smarkm } 997109998Smarkm 998109998Smarkm /*****************************************************************/ 99955714Skris if (req || gencrl) 100055714Skris { 100155714Skris if (outfile != NULL) 100255714Skris { 100355714Skris if (BIO_write_filename(Sout,outfile) <= 0) 100455714Skris { 100555714Skris perror(outfile); 100655714Skris goto err; 100755714Skris } 100855714Skris } 100955714Skris else 101068651Skris { 101155714Skris BIO_set_fp(Sout,stdout,BIO_NOCLOSE|BIO_FP_TEXT); 1012109998Smarkm#ifdef OPENSSL_SYS_VMS 101368651Skris { 101468651Skris BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 101568651Skris Sout = BIO_push(tmpbio, Sout); 101668651Skris } 101768651Skris#endif 101868651Skris } 101955714Skris } 102055714Skris 1021160814Ssimon if ((md == NULL) && ((md=NCONF_get_string(conf, 1022160814Ssimon section,ENV_DEFAULT_MD)) == NULL)) 1023160814Ssimon { 1024160814Ssimon lookup_fail(section,ENV_DEFAULT_MD); 1025160814Ssimon goto err; 1026160814Ssimon } 1027160814Ssimon 1028160814Ssimon if ((dgst=EVP_get_digestbyname(md)) == NULL) 1029160814Ssimon { 1030160814Ssimon BIO_printf(bio_err,"%s is an unsupported message digest type\n",md); 1031160814Ssimon goto err; 1032160814Ssimon } 1033160814Ssimon 103455714Skris if (req) 103555714Skris { 1036109998Smarkm if ((email_dn == 1) && ((tmp_email_dn=NCONF_get_string(conf, 1037109998Smarkm section,ENV_DEFAULT_EMAIL_DN)) != NULL )) 1038109998Smarkm { 1039109998Smarkm if(strcmp(tmp_email_dn,"no") == 0) 1040109998Smarkm email_dn=0; 1041109998Smarkm } 104255714Skris if (verbose) 104355714Skris BIO_printf(bio_err,"message digest is %s\n", 104455714Skris OBJ_nid2ln(dgst->type)); 1045109998Smarkm if ((policy == NULL) && ((policy=NCONF_get_string(conf, 104655714Skris section,ENV_POLICY)) == NULL)) 104755714Skris { 104855714Skris lookup_fail(section,ENV_POLICY); 104955714Skris goto err; 105055714Skris } 105155714Skris if (verbose) 105255714Skris BIO_printf(bio_err,"policy is %s\n",policy); 105355714Skris 1054109998Smarkm if ((serialfile=NCONF_get_string(conf,section,ENV_SERIAL)) 105555714Skris == NULL) 105655714Skris { 105755714Skris lookup_fail(section,ENV_SERIAL); 105855714Skris goto err; 105955714Skris } 1060109998Smarkm 1061109998Smarkm if (!extconf) 1062109998Smarkm { 1063109998Smarkm /* no '-extfile' option, so we look for extensions 1064109998Smarkm * in the main configuration file */ 1065109998Smarkm if (!extensions) 1066109998Smarkm { 1067109998Smarkm extensions=NCONF_get_string(conf,section, 1068109998Smarkm ENV_EXTENSIONS); 1069109998Smarkm if (!extensions) 1070109998Smarkm ERR_clear_error(); 1071109998Smarkm } 1072109998Smarkm if (extensions) 1073109998Smarkm { 1074109998Smarkm /* Check syntax of file */ 1075109998Smarkm X509V3_CTX ctx; 1076109998Smarkm X509V3_set_ctx_test(&ctx); 1077109998Smarkm X509V3_set_nconf(&ctx, conf); 1078109998Smarkm if (!X509V3_EXT_add_nconf(conf, &ctx, extensions, 1079109998Smarkm NULL)) 1080109998Smarkm { 1081109998Smarkm BIO_printf(bio_err, 1082109998Smarkm "Error Loading extension section %s\n", 108355714Skris extensions); 1084109998Smarkm ret = 1; 1085109998Smarkm goto err; 1086109998Smarkm } 1087109998Smarkm } 108855714Skris } 108955714Skris 109055714Skris if (startdate == NULL) 109155714Skris { 1092109998Smarkm startdate=NCONF_get_string(conf,section, 109355714Skris ENV_DEFAULT_STARTDATE); 1094109998Smarkm if (startdate == NULL) 1095109998Smarkm ERR_clear_error(); 109655714Skris } 109755714Skris if (startdate && !ASN1_UTCTIME_set_string(NULL,startdate)) 109855714Skris { 109955714Skris BIO_printf(bio_err,"start date is invalid, it should be YYMMDDHHMMSSZ\n"); 110055714Skris goto err; 110155714Skris } 110255714Skris if (startdate == NULL) startdate="today"; 110355714Skris 110455714Skris if (enddate == NULL) 110555714Skris { 1106109998Smarkm enddate=NCONF_get_string(conf,section, 110755714Skris ENV_DEFAULT_ENDDATE); 1108109998Smarkm if (enddate == NULL) 1109109998Smarkm ERR_clear_error(); 111055714Skris } 111155714Skris if (enddate && !ASN1_UTCTIME_set_string(NULL,enddate)) 111255714Skris { 111355714Skris BIO_printf(bio_err,"end date is invalid, it should be YYMMDDHHMMSSZ\n"); 111455714Skris goto err; 111555714Skris } 111655714Skris 111755714Skris if (days == 0) 111855714Skris { 1119109998Smarkm if(!NCONF_get_number(conf,section, ENV_DEFAULT_DAYS, &days)) 1120109998Smarkm days = 0; 112155714Skris } 112255714Skris if (!enddate && (days == 0)) 112355714Skris { 112455714Skris BIO_printf(bio_err,"cannot lookup how many days to certify for\n"); 112555714Skris goto err; 112655714Skris } 112755714Skris 1128142425Snectar if ((serial=load_serial(serialfile, create_ser, NULL)) == NULL) 112955714Skris { 113055714Skris BIO_printf(bio_err,"error while loading serial number\n"); 113155714Skris goto err; 113255714Skris } 113355714Skris if (verbose) 113455714Skris { 1135109998Smarkm if (BN_is_zero(serial)) 1136109998Smarkm BIO_printf(bio_err,"next serial number is 00\n"); 1137109998Smarkm else 1138109998Smarkm { 1139109998Smarkm if ((f=BN_bn2hex(serial)) == NULL) goto err; 1140109998Smarkm BIO_printf(bio_err,"next serial number is %s\n",f); 1141109998Smarkm OPENSSL_free(f); 1142109998Smarkm } 114355714Skris } 114455714Skris 1145109998Smarkm if ((attribs=NCONF_get_section(conf,policy)) == NULL) 114655714Skris { 114755714Skris BIO_printf(bio_err,"unable to find 'section' for %s\n",policy); 114855714Skris goto err; 114955714Skris } 115055714Skris 115168651Skris if ((cert_sk=sk_X509_new_null()) == NULL) 115255714Skris { 115368651Skris BIO_printf(bio_err,"Memory allocation failure\n"); 115455714Skris goto err; 115555714Skris } 115655714Skris if (spkac_file != NULL) 115755714Skris { 115855714Skris total++; 115955714Skris j=certify_spkac(&x,spkac_file,pkey,x509,dgst,attribs,db, 1160160814Ssimon serial,subj,chtype,multirdn,email_dn,startdate,enddate,days,extensions, 1161109998Smarkm conf,verbose,certopt,nameopt,default_op,ext_copy); 116255714Skris if (j < 0) goto err; 116355714Skris if (j > 0) 116455714Skris { 116555714Skris total_done++; 116655714Skris BIO_printf(bio_err,"\n"); 116755714Skris if (!BN_add_word(serial,1)) goto err; 116868651Skris if (!sk_X509_push(cert_sk,x)) 116955714Skris { 117068651Skris BIO_printf(bio_err,"Memory allocation failure\n"); 117155714Skris goto err; 117255714Skris } 117355714Skris if (outfile) 117455714Skris { 117555714Skris output_der = 1; 117655714Skris batch = 1; 117755714Skris } 117855714Skris } 117955714Skris } 118055714Skris if (ss_cert_file != NULL) 118155714Skris { 118255714Skris total++; 118355714Skris j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,attribs, 1184160814Ssimon db,serial,subj,chtype,multirdn,email_dn,startdate,enddate,days,batch, 1185109998Smarkm extensions,conf,verbose, certopt, nameopt, 1186109998Smarkm default_op, ext_copy, e); 118755714Skris if (j < 0) goto err; 118855714Skris if (j > 0) 118955714Skris { 119055714Skris total_done++; 119155714Skris BIO_printf(bio_err,"\n"); 119255714Skris if (!BN_add_word(serial,1)) goto err; 119368651Skris if (!sk_X509_push(cert_sk,x)) 119455714Skris { 119568651Skris BIO_printf(bio_err,"Memory allocation failure\n"); 119655714Skris goto err; 119755714Skris } 119855714Skris } 119955714Skris } 120055714Skris if (infile != NULL) 120155714Skris { 120255714Skris total++; 1203160814Ssimon j=certify(&x,infile,pkey,x509p,dgst,attribs,db, 1204160814Ssimon serial,subj,chtype,multirdn,email_dn,startdate,enddate,days,batch, 1205109998Smarkm extensions,conf,verbose, certopt, nameopt, 1206160814Ssimon default_op, ext_copy, selfsign); 120755714Skris if (j < 0) goto err; 120855714Skris if (j > 0) 120955714Skris { 121055714Skris total_done++; 121155714Skris BIO_printf(bio_err,"\n"); 121255714Skris if (!BN_add_word(serial,1)) goto err; 121368651Skris if (!sk_X509_push(cert_sk,x)) 121455714Skris { 121568651Skris BIO_printf(bio_err,"Memory allocation failure\n"); 121655714Skris goto err; 121755714Skris } 121855714Skris } 121955714Skris } 122055714Skris for (i=0; i<argc; i++) 122155714Skris { 122255714Skris total++; 1223160814Ssimon j=certify(&x,argv[i],pkey,x509p,dgst,attribs,db, 1224160814Ssimon serial,subj,chtype,multirdn,email_dn,startdate,enddate,days,batch, 1225109998Smarkm extensions,conf,verbose, certopt, nameopt, 1226160814Ssimon default_op, ext_copy, selfsign); 122755714Skris if (j < 0) goto err; 122855714Skris if (j > 0) 122955714Skris { 123055714Skris total_done++; 123155714Skris BIO_printf(bio_err,"\n"); 123255714Skris if (!BN_add_word(serial,1)) goto err; 123368651Skris if (!sk_X509_push(cert_sk,x)) 123455714Skris { 123568651Skris BIO_printf(bio_err,"Memory allocation failure\n"); 123655714Skris goto err; 123755714Skris } 123855714Skris } 123955714Skris } 124055714Skris /* we have a stack of newly certified certificates 124155714Skris * and a data base and serial number that need 124255714Skris * updating */ 124355714Skris 124468651Skris if (sk_X509_num(cert_sk) > 0) 124555714Skris { 124655714Skris if (!batch) 124755714Skris { 124855714Skris BIO_printf(bio_err,"\n%d out of %d certificate requests certified, commit? [y/n]",total_done,total); 124955714Skris (void)BIO_flush(bio_err); 125055714Skris buf[0][0]='\0'; 1251205128Ssimon if (!fgets(buf[0],10,stdin)) 1252205128Ssimon { 1253205128Ssimon BIO_printf(bio_err,"CERTIFICATION CANCELED: I/O error\n"); 1254205128Ssimon ret=0; 1255205128Ssimon goto err; 1256205128Ssimon } 125755714Skris if ((buf[0][0] != 'y') && (buf[0][0] != 'Y')) 125855714Skris { 125955714Skris BIO_printf(bio_err,"CERTIFICATION CANCELED\n"); 126055714Skris ret=0; 126155714Skris goto err; 126255714Skris } 126355714Skris } 126455714Skris 126568651Skris BIO_printf(bio_err,"Write out database with %d new entries\n",sk_X509_num(cert_sk)); 126655714Skris 1267127128Snectar if (!save_serial(serialfile,"new",serial,NULL)) goto err; 126855714Skris 1269127128Snectar if (!save_index(dbfile, "new", db)) goto err; 127055714Skris } 127155714Skris 127255714Skris if (verbose) 127355714Skris BIO_printf(bio_err,"writing new certificates\n"); 127468651Skris for (i=0; i<sk_X509_num(cert_sk); i++) 127555714Skris { 127655714Skris int k; 1277127128Snectar char *n; 127855714Skris 127968651Skris x=sk_X509_value(cert_sk,i); 128055714Skris 128155714Skris j=x->cert_info->serialNumber->length; 1282160814Ssimon p=(const char *)x->cert_info->serialNumber->data; 128355714Skris 1284109998Smarkm if(strlen(outdir) >= (size_t)(j ? BSIZE-j*2-6 : BSIZE-8)) 1285109998Smarkm { 1286109998Smarkm BIO_printf(bio_err,"certificate file name too long\n"); 1287109998Smarkm goto err; 1288109998Smarkm } 128955714Skris 1290109998Smarkm strcpy(buf[2],outdir); 1291109998Smarkm 1292109998Smarkm#ifndef OPENSSL_SYS_VMS 1293127128Snectar BUF_strlcat(buf[2],"/",sizeof(buf[2])); 129455714Skris#endif 129555714Skris 1296127128Snectar n=(char *)&(buf[2][strlen(buf[2])]); 129755714Skris if (j > 0) 129855714Skris { 129955714Skris for (k=0; k<j; k++) 130055714Skris { 1301127128Snectar if (n >= &(buf[2][sizeof(buf[2])])) 1302127128Snectar break; 1303127128Snectar BIO_snprintf(n, 1304127128Snectar &buf[2][0] + sizeof(buf[2]) - n, 1305127128Snectar "%02X",(unsigned char)*(p++)); 130655714Skris n+=2; 130755714Skris } 130855714Skris } 130955714Skris else 131055714Skris { 131155714Skris *(n++)='0'; 131255714Skris *(n++)='0'; 131355714Skris } 131455714Skris *(n++)='.'; *(n++)='p'; *(n++)='e'; *(n++)='m'; 131555714Skris *n='\0'; 131655714Skris if (verbose) 131755714Skris BIO_printf(bio_err,"writing %s\n",buf[2]); 131855714Skris 131955714Skris if (BIO_write_filename(Cout,buf[2]) <= 0) 132055714Skris { 132155714Skris perror(buf[2]); 132255714Skris goto err; 132355714Skris } 132459191Skris write_new_certificate(Cout,x, 0, notext); 132559191Skris write_new_certificate(Sout,x, output_der, notext); 132655714Skris } 132755714Skris 132868651Skris if (sk_X509_num(cert_sk)) 132955714Skris { 133055714Skris /* Rename the database and the serial file */ 1331127128Snectar if (!rotate_serial(serialfile,"new","old")) goto err; 133255714Skris 1333127128Snectar if (!rotate_index(dbfile,"new","old")) goto err; 133455714Skris 133555714Skris BIO_printf(bio_err,"Data Base Updated\n"); 133655714Skris } 133755714Skris } 133855714Skris 133955714Skris /*****************************************************************/ 134055714Skris if (gencrl) 134155714Skris { 1342109998Smarkm int crl_v2 = 0; 1343109998Smarkm if (!crl_ext) 1344109998Smarkm { 1345109998Smarkm crl_ext=NCONF_get_string(conf,section,ENV_CRLEXT); 1346109998Smarkm if (!crl_ext) 1347109998Smarkm ERR_clear_error(); 1348109998Smarkm } 1349109998Smarkm if (crl_ext) 1350109998Smarkm { 135155714Skris /* Check syntax of file */ 135255714Skris X509V3_CTX ctx; 135355714Skris X509V3_set_ctx_test(&ctx); 1354109998Smarkm X509V3_set_nconf(&ctx, conf); 1355109998Smarkm if (!X509V3_EXT_add_nconf(conf, &ctx, crl_ext, NULL)) 1356109998Smarkm { 135755714Skris BIO_printf(bio_err, 135855714Skris "Error Loading CRL extension section %s\n", 135955714Skris crl_ext); 136055714Skris ret = 1; 136155714Skris goto err; 1362109998Smarkm } 136355714Skris } 136455714Skris 1365127128Snectar if ((crlnumberfile=NCONF_get_string(conf,section,ENV_CRLNUMBER)) 1366127128Snectar != NULL) 1367127128Snectar if ((crlnumber=load_serial(crlnumberfile,0,NULL)) == NULL) 1368127128Snectar { 1369127128Snectar BIO_printf(bio_err,"error while loading CRL number\n"); 1370127128Snectar goto err; 1371127128Snectar } 1372127128Snectar 137355714Skris if (!crldays && !crlhours) 137455714Skris { 1375109998Smarkm if (!NCONF_get_number(conf,section, 1376109998Smarkm ENV_DEFAULT_CRL_DAYS, &crldays)) 1377109998Smarkm crldays = 0; 1378109998Smarkm if (!NCONF_get_number(conf,section, 1379109998Smarkm ENV_DEFAULT_CRL_HOURS, &crlhours)) 1380109998Smarkm crlhours = 0; 138155714Skris } 138255714Skris if ((crldays == 0) && (crlhours == 0)) 138355714Skris { 1384100936Snectar BIO_printf(bio_err,"cannot lookup how long until the next CRL is issued\n"); 138555714Skris goto err; 138655714Skris } 138755714Skris 138855714Skris if (verbose) BIO_printf(bio_err,"making CRL\n"); 138955714Skris if ((crl=X509_CRL_new()) == NULL) goto err; 1390109998Smarkm if (!X509_CRL_set_issuer_name(crl, X509_get_subject_name(x509))) goto err; 139155714Skris 1392109998Smarkm tmptm = ASN1_TIME_new(); 1393109998Smarkm if (!tmptm) goto err; 1394109998Smarkm X509_gmtime_adj(tmptm,0); 1395109998Smarkm X509_CRL_set_lastUpdate(crl, tmptm); 1396109998Smarkm X509_gmtime_adj(tmptm,(crldays*24+crlhours)*60*60); 1397109998Smarkm X509_CRL_set_nextUpdate(crl, tmptm); 139855714Skris 1399109998Smarkm ASN1_TIME_free(tmptm); 1400109998Smarkm 1401127128Snectar for (i=0; i<sk_num(db->db->data); i++) 140255714Skris { 1403160814Ssimon pp=(const char **)sk_value(db->db->data,i); 140455714Skris if (pp[DB_type][0] == DB_TYPE_REV) 140555714Skris { 140655714Skris if ((r=X509_REVOKED_new()) == NULL) goto err; 1407109998Smarkm j = make_revoked(r, pp[DB_rev_date]); 1408109998Smarkm if (!j) goto err; 1409109998Smarkm if (j == 2) crl_v2 = 1; 1410109998Smarkm if (!BN_hex2bn(&serial, pp[DB_serial])) 141155714Skris goto err; 1412109998Smarkm tmpser = BN_to_ASN1_INTEGER(serial, NULL); 1413109998Smarkm BN_free(serial); 1414109998Smarkm serial = NULL; 1415109998Smarkm if (!tmpser) 1416109998Smarkm goto err; 1417109998Smarkm X509_REVOKED_set_serialNumber(r, tmpser); 1418109998Smarkm ASN1_INTEGER_free(tmpser); 1419109998Smarkm X509_CRL_add0_revoked(crl,r); 142055714Skris } 142155714Skris } 1422109998Smarkm 142355714Skris /* sort the data so it will be written in serial 142455714Skris * number order */ 1425109998Smarkm X509_CRL_sort(crl); 142655714Skris 142755714Skris /* we now have a CRL */ 142855714Skris if (verbose) BIO_printf(bio_err,"signing CRL\n"); 1429160814Ssimon#ifndef OPENSSL_NO_DSA 1430160814Ssimon if (pkey->type == EVP_PKEY_DSA) 1431160814Ssimon dgst=EVP_dss1(); 143255714Skris else 143355714Skris#endif 1434160814Ssimon#ifndef OPENSSL_NO_ECDSA 1435160814Ssimon if (pkey->type == EVP_PKEY_EC) 1436160814Ssimon dgst=EVP_ecdsa(); 1437160814Ssimon#endif 143855714Skris 143955714Skris /* Add any extensions asked for */ 144055714Skris 1441127128Snectar if (crl_ext || crlnumberfile != NULL) 1442109998Smarkm { 1443109998Smarkm X509V3_CTX crlctx; 1444109998Smarkm X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0); 1445109998Smarkm X509V3_set_nconf(&crlctx, conf); 144655714Skris 1447127128Snectar if (crl_ext) 1448127128Snectar if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx, 1449127128Snectar crl_ext, crl)) goto err; 1450127128Snectar if (crlnumberfile != NULL) 1451127128Snectar { 1452127128Snectar tmpser = BN_to_ASN1_INTEGER(crlnumber, NULL); 1453127128Snectar if (!tmpser) goto err; 1454127128Snectar X509_CRL_add1_ext_i2d(crl,NID_crl_number,tmpser,0,0); 1455127128Snectar ASN1_INTEGER_free(tmpser); 1456127128Snectar crl_v2 = 1; 1457127128Snectar if (!BN_add_word(crlnumber,1)) goto err; 1458127128Snectar } 1459109998Smarkm } 1460109998Smarkm if (crl_ext || crl_v2) 1461109998Smarkm { 1462109998Smarkm if (!X509_CRL_set_version(crl, 1)) 1463109998Smarkm goto err; /* version 2 CRL */ 1464109998Smarkm } 146555714Skris 1466127128Snectar 1467127128Snectar if (crlnumberfile != NULL) /* we have a CRL number that need updating */ 1468127128Snectar if (!save_serial(crlnumberfile,"new",crlnumber,NULL)) goto err; 1469127128Snectar 147055714Skris if (!X509_CRL_sign(crl,pkey,dgst)) goto err; 147155714Skris 147255714Skris PEM_write_bio_X509_CRL(Sout,crl); 1473127128Snectar 1474127128Snectar if (crlnumberfile != NULL) /* Rename the crlnumber file */ 1475127128Snectar if (!rotate_serial(crlnumberfile,"new","old")) goto err; 1476127128Snectar 147755714Skris } 147855714Skris /*****************************************************************/ 147955714Skris if (dorevoke) 148055714Skris { 148155714Skris if (infile == NULL) 148255714Skris { 148355714Skris BIO_printf(bio_err,"no input files\n"); 148455714Skris goto err; 148555714Skris } 148655714Skris else 148755714Skris { 148859191Skris X509 *revcert; 1489109998Smarkm revcert=load_cert(bio_err, infile, FORMAT_PEM, 1490109998Smarkm NULL, e, infile); 149159191Skris if (revcert == NULL) 149255714Skris goto err; 1493109998Smarkm j=do_revoke(revcert,db, rev_type, rev_arg); 149459191Skris if (j <= 0) goto err; 149559191Skris X509_free(revcert); 149655714Skris 1497127128Snectar if (!save_index(dbfile, "new", db)) goto err; 1498109998Smarkm 1499127128Snectar if (!rotate_index(dbfile, "new", "old")) goto err; 1500127128Snectar 150155714Skris BIO_printf(bio_err,"Data Base Updated\n"); 150255714Skris } 150355714Skris } 150455714Skris /*****************************************************************/ 150555714Skris ret=0; 150655714Skriserr: 1507109998Smarkm if(tofree) 1508109998Smarkm OPENSSL_free(tofree); 150968651Skris BIO_free_all(Cout); 151068651Skris BIO_free_all(Sout); 151168651Skris BIO_free_all(out); 1512109998Smarkm BIO_free_all(in); 151355714Skris 1514111147Snectar if (cert_sk) 1515111147Snectar sk_X509_pop_free(cert_sk,X509_free); 151655714Skris 151755714Skris if (ret) ERR_print_errors(bio_err); 151859191Skris app_RAND_write_file(randfile, bio_err); 1519111147Snectar if (free_key && key) 1520109998Smarkm OPENSSL_free(key); 152155714Skris BN_free(serial); 1522127128Snectar free_index(db); 152355714Skris EVP_PKEY_free(pkey); 1524160814Ssimon if (x509) X509_free(x509); 152555714Skris X509_CRL_free(crl); 1526109998Smarkm NCONF_free(conf); 1527167612Ssimon NCONF_free(extconf); 152855714Skris OBJ_cleanup(); 1529109998Smarkm apps_shutdown(); 1530109998Smarkm OPENSSL_EXIT(ret); 153155714Skris } 153255714Skris 1533160814Ssimonstatic void lookup_fail(const char *name, const char *tag) 153455714Skris { 153555714Skris BIO_printf(bio_err,"variable lookup failed for %s::%s\n",name,tag); 153655714Skris } 153755714Skris 153855714Skrisstatic int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, 1539127128Snectar const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, CA_DB *db, 1540160814Ssimon BIGNUM *serial, char *subj,unsigned long chtype, int multirdn, int email_dn, char *startdate, char *enddate, 1541109998Smarkm long days, int batch, char *ext_sect, CONF *lconf, int verbose, 1542109998Smarkm unsigned long certopt, unsigned long nameopt, int default_op, 1543160814Ssimon int ext_copy, int selfsign) 154455714Skris { 154555714Skris X509_REQ *req=NULL; 154655714Skris BIO *in=NULL; 154755714Skris EVP_PKEY *pktmp=NULL; 154855714Skris int ok= -1,i; 154955714Skris 155055714Skris in=BIO_new(BIO_s_file()); 155155714Skris 155255714Skris if (BIO_read_filename(in,infile) <= 0) 155355714Skris { 155455714Skris perror(infile); 155555714Skris goto err; 155655714Skris } 155755714Skris if ((req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL)) == NULL) 155855714Skris { 155955714Skris BIO_printf(bio_err,"Error reading certificate request in %s\n", 156055714Skris infile); 156155714Skris goto err; 156255714Skris } 156355714Skris if (verbose) 156455714Skris X509_REQ_print(bio_err,req); 156555714Skris 156655714Skris BIO_printf(bio_err,"Check that the request matches the signature\n"); 156755714Skris 1568160814Ssimon if (selfsign && !X509_REQ_check_private_key(req,pkey)) 1569160814Ssimon { 1570160814Ssimon BIO_printf(bio_err,"Certificate request and CA private key do not match\n"); 1571160814Ssimon ok=0; 1572160814Ssimon goto err; 1573160814Ssimon } 157455714Skris if ((pktmp=X509_REQ_get_pubkey(req)) == NULL) 157555714Skris { 157655714Skris BIO_printf(bio_err,"error unpacking public key\n"); 157755714Skris goto err; 157855714Skris } 157955714Skris i=X509_REQ_verify(req,pktmp); 158055714Skris EVP_PKEY_free(pktmp); 158155714Skris if (i < 0) 158255714Skris { 158355714Skris ok=0; 158455714Skris BIO_printf(bio_err,"Signature verification problems....\n"); 1585279265Sdelphij ERR_print_errors(bio_err); 158655714Skris goto err; 158755714Skris } 158855714Skris if (i == 0) 158955714Skris { 159055714Skris ok=0; 159155714Skris BIO_printf(bio_err,"Signature did not match the certificate request\n"); 1592279265Sdelphij ERR_print_errors(bio_err); 159355714Skris goto err; 159455714Skris } 159555714Skris else 159655714Skris BIO_printf(bio_err,"Signature ok\n"); 159755714Skris 1598160814Ssimon ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,chtype,multirdn, email_dn, 1599109998Smarkm startdate,enddate,days,batch,verbose,req,ext_sect,lconf, 1600160814Ssimon certopt, nameopt, default_op, ext_copy, selfsign); 160155714Skris 160255714Skriserr: 160355714Skris if (req != NULL) X509_REQ_free(req); 160455714Skris if (in != NULL) BIO_free(in); 160555714Skris return(ok); 160655714Skris } 160755714Skris 160855714Skrisstatic int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, 1609127128Snectar const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, CA_DB *db, 1610160814Ssimon BIGNUM *serial, char *subj, unsigned long chtype, int multirdn, int email_dn, char *startdate, char *enddate, 1611109998Smarkm long days, int batch, char *ext_sect, CONF *lconf, int verbose, 1612109998Smarkm unsigned long certopt, unsigned long nameopt, int default_op, 1613109998Smarkm int ext_copy, ENGINE *e) 161455714Skris { 161555714Skris X509 *req=NULL; 161655714Skris X509_REQ *rreq=NULL; 161755714Skris EVP_PKEY *pktmp=NULL; 161855714Skris int ok= -1,i; 161955714Skris 1620109998Smarkm if ((req=load_cert(bio_err, infile, FORMAT_PEM, NULL, e, infile)) == NULL) 162155714Skris goto err; 162255714Skris if (verbose) 162355714Skris X509_print(bio_err,req); 162455714Skris 162555714Skris BIO_printf(bio_err,"Check that the request matches the signature\n"); 162655714Skris 162755714Skris if ((pktmp=X509_get_pubkey(req)) == NULL) 162855714Skris { 162955714Skris BIO_printf(bio_err,"error unpacking public key\n"); 163055714Skris goto err; 163155714Skris } 163255714Skris i=X509_verify(req,pktmp); 163355714Skris EVP_PKEY_free(pktmp); 163455714Skris if (i < 0) 163555714Skris { 163655714Skris ok=0; 163755714Skris BIO_printf(bio_err,"Signature verification problems....\n"); 163855714Skris goto err; 163955714Skris } 164055714Skris if (i == 0) 164155714Skris { 164255714Skris ok=0; 164355714Skris BIO_printf(bio_err,"Signature did not match the certificate\n"); 164455714Skris goto err; 164555714Skris } 164655714Skris else 164755714Skris BIO_printf(bio_err,"Signature ok\n"); 164855714Skris 164955714Skris if ((rreq=X509_to_X509_REQ(req,NULL,EVP_md5())) == NULL) 165055714Skris goto err; 165155714Skris 1652160814Ssimon ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,chtype,multirdn,email_dn,startdate,enddate, 1653109998Smarkm days,batch,verbose,rreq,ext_sect,lconf, certopt, nameopt, default_op, 1654160814Ssimon ext_copy, 0); 165555714Skris 165655714Skriserr: 165755714Skris if (rreq != NULL) X509_REQ_free(rreq); 165855714Skris if (req != NULL) X509_free(req); 165955714Skris return(ok); 166055714Skris } 166155714Skris 166255714Skrisstatic int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, 1663127128Snectar STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, char *subj, 1664160814Ssimon unsigned long chtype, int multirdn, 1665109998Smarkm int email_dn, char *startdate, char *enddate, long days, int batch, 1666109998Smarkm int verbose, X509_REQ *req, char *ext_sect, CONF *lconf, 1667109998Smarkm unsigned long certopt, unsigned long nameopt, int default_op, 1668160814Ssimon int ext_copy, int selfsign) 166955714Skris { 1670109998Smarkm X509_NAME *name=NULL,*CAname=NULL,*subject=NULL, *dn_subject=NULL; 167155714Skris ASN1_UTCTIME *tm,*tmptm; 167255714Skris ASN1_STRING *str,*str2; 167355714Skris ASN1_OBJECT *obj; 167455714Skris X509 *ret=NULL; 167555714Skris X509_CINF *ci; 167655714Skris X509_NAME_ENTRY *ne; 167755714Skris X509_NAME_ENTRY *tne,*push; 167855714Skris EVP_PKEY *pktmp; 167955714Skris int ok= -1,i,j,last,nid; 1680160814Ssimon const char *p; 168155714Skris CONF_VALUE *cv; 1682127128Snectar char *row[DB_NUMBER],**rrow=NULL,**irow=NULL; 1683109998Smarkm char buf[25]; 168455714Skris 168555714Skris tmptm=ASN1_UTCTIME_new(); 168655714Skris if (tmptm == NULL) 168755714Skris { 168855714Skris BIO_printf(bio_err,"malloc error\n"); 168955714Skris return(0); 169055714Skris } 169155714Skris 169255714Skris for (i=0; i<DB_NUMBER; i++) 169355714Skris row[i]=NULL; 169455714Skris 1695109998Smarkm if (subj) 1696109998Smarkm { 1697160814Ssimon X509_NAME *n = parse_name(subj, chtype, multirdn); 1698109998Smarkm 1699109998Smarkm if (!n) 1700109998Smarkm { 1701109998Smarkm ERR_print_errors(bio_err); 1702109998Smarkm goto err; 1703109998Smarkm } 1704109998Smarkm X509_REQ_set_subject_name(req,n); 1705109998Smarkm req->req_info->enc.modified = 1; 1706109998Smarkm X509_NAME_free(n); 1707109998Smarkm } 1708109998Smarkm 1709109998Smarkm if (default_op) 1710109998Smarkm BIO_printf(bio_err,"The Subject's Distinguished Name is as follows\n"); 1711109998Smarkm 171255714Skris name=X509_REQ_get_subject_name(req); 171355714Skris for (i=0; i<X509_NAME_entry_count(name); i++) 171455714Skris { 1715109998Smarkm ne= X509_NAME_get_entry(name,i); 1716109998Smarkm str=X509_NAME_ENTRY_get_data(ne); 171755714Skris obj=X509_NAME_ENTRY_get_object(ne); 171855714Skris 171955714Skris if (msie_hack) 172055714Skris { 172155714Skris /* assume all type should be strings */ 172255714Skris nid=OBJ_obj2nid(ne->object); 172355714Skris 172455714Skris if (str->type == V_ASN1_UNIVERSALSTRING) 172555714Skris ASN1_UNIVERSALSTRING_to_string(str); 172655714Skris 172755714Skris if ((str->type == V_ASN1_IA5STRING) && 172855714Skris (nid != NID_pkcs9_emailAddress)) 172955714Skris str->type=V_ASN1_T61STRING; 173055714Skris 173155714Skris if ((nid == NID_pkcs9_emailAddress) && 173255714Skris (str->type == V_ASN1_PRINTABLESTRING)) 173355714Skris str->type=V_ASN1_IA5STRING; 173455714Skris } 173555714Skris 1736109998Smarkm /* If no EMAIL is wanted in the subject */ 1737109998Smarkm if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) && (!email_dn)) 1738109998Smarkm continue; 173955714Skris 174055714Skris /* check some things */ 174155714Skris if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) && 174255714Skris (str->type != V_ASN1_IA5STRING)) 174355714Skris { 174455714Skris BIO_printf(bio_err,"\nemailAddress type needs to be of type IA5STRING\n"); 174555714Skris goto err; 174655714Skris } 1747109998Smarkm if ((str->type != V_ASN1_BMPSTRING) && (str->type != V_ASN1_UTF8STRING)) 174855714Skris { 1749109998Smarkm j=ASN1_PRINTABLE_type(str->data,str->length); 1750109998Smarkm if ( ((j == V_ASN1_T61STRING) && 1751109998Smarkm (str->type != V_ASN1_T61STRING)) || 1752109998Smarkm ((j == V_ASN1_IA5STRING) && 1753109998Smarkm (str->type == V_ASN1_PRINTABLESTRING))) 1754109998Smarkm { 1755109998Smarkm BIO_printf(bio_err,"\nThe string contains characters that are illegal for the ASN.1 type\n"); 1756109998Smarkm goto err; 1757109998Smarkm } 175855714Skris } 1759109998Smarkm 1760109998Smarkm if (default_op) 1761109998Smarkm old_entry_print(bio_err, obj, str); 176255714Skris } 176355714Skris 176455714Skris /* Ok, now we check the 'policy' stuff. */ 176555714Skris if ((subject=X509_NAME_new()) == NULL) 176655714Skris { 176768651Skris BIO_printf(bio_err,"Memory allocation failure\n"); 176855714Skris goto err; 176955714Skris } 177055714Skris 177155714Skris /* take a copy of the issuer name before we mess with it. */ 1772160814Ssimon if (selfsign) 1773160814Ssimon CAname=X509_NAME_dup(name); 1774160814Ssimon else 1775160814Ssimon CAname=X509_NAME_dup(x509->cert_info->subject); 177655714Skris if (CAname == NULL) goto err; 177755714Skris str=str2=NULL; 177855714Skris 177955714Skris for (i=0; i<sk_CONF_VALUE_num(policy); i++) 178055714Skris { 178155714Skris cv=sk_CONF_VALUE_value(policy,i); /* get the object id */ 178255714Skris if ((j=OBJ_txt2nid(cv->name)) == NID_undef) 178355714Skris { 178455714Skris BIO_printf(bio_err,"%s:unknown object type in 'policy' configuration\n",cv->name); 178555714Skris goto err; 178655714Skris } 178755714Skris obj=OBJ_nid2obj(j); 178855714Skris 178955714Skris last= -1; 179055714Skris for (;;) 179155714Skris { 179255714Skris /* lookup the object in the supplied name list */ 179355714Skris j=X509_NAME_get_index_by_OBJ(name,obj,last); 179455714Skris if (j < 0) 179555714Skris { 179655714Skris if (last != -1) break; 179755714Skris tne=NULL; 179855714Skris } 179955714Skris else 180055714Skris { 180155714Skris tne=X509_NAME_get_entry(name,j); 180255714Skris } 180355714Skris last=j; 180455714Skris 180555714Skris /* depending on the 'policy', decide what to do. */ 180655714Skris push=NULL; 180755714Skris if (strcmp(cv->value,"optional") == 0) 180855714Skris { 180955714Skris if (tne != NULL) 181055714Skris push=tne; 181155714Skris } 181255714Skris else if (strcmp(cv->value,"supplied") == 0) 181355714Skris { 181455714Skris if (tne == NULL) 181555714Skris { 181655714Skris BIO_printf(bio_err,"The %s field needed to be supplied and was missing\n",cv->name); 181755714Skris goto err; 181855714Skris } 181955714Skris else 182055714Skris push=tne; 182155714Skris } 182255714Skris else if (strcmp(cv->value,"match") == 0) 182355714Skris { 182455714Skris int last2; 182555714Skris 182655714Skris if (tne == NULL) 182755714Skris { 182855714Skris BIO_printf(bio_err,"The mandatory %s field was missing\n",cv->name); 182955714Skris goto err; 183055714Skris } 183155714Skris 183255714Skris last2= -1; 183355714Skris 183455714Skrisagain2: 183555714Skris j=X509_NAME_get_index_by_OBJ(CAname,obj,last2); 183655714Skris if ((j < 0) && (last2 == -1)) 183755714Skris { 183855714Skris BIO_printf(bio_err,"The %s field does not exist in the CA certificate,\nthe 'policy' is misconfigured\n",cv->name); 183955714Skris goto err; 184055714Skris } 184155714Skris if (j >= 0) 184255714Skris { 184355714Skris push=X509_NAME_get_entry(CAname,j); 184455714Skris str=X509_NAME_ENTRY_get_data(tne); 184555714Skris str2=X509_NAME_ENTRY_get_data(push); 184655714Skris last2=j; 184755714Skris if (ASN1_STRING_cmp(str,str2) != 0) 184855714Skris goto again2; 184955714Skris } 185055714Skris if (j < 0) 185155714Skris { 185259191Skris 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)); 185355714Skris goto err; 185455714Skris } 185555714Skris } 185655714Skris else 185755714Skris { 185855714Skris BIO_printf(bio_err,"%s:invalid type in 'policy' configuration\n",cv->value); 185955714Skris goto err; 186055714Skris } 186155714Skris 186255714Skris if (push != NULL) 186355714Skris { 186459191Skris if (!X509_NAME_add_entry(subject,push, -1, 0)) 186555714Skris { 186655714Skris if (push != NULL) 186755714Skris X509_NAME_ENTRY_free(push); 186868651Skris BIO_printf(bio_err,"Memory allocation failure\n"); 186955714Skris goto err; 187055714Skris } 187155714Skris } 187255714Skris if (j < 0) break; 187355714Skris } 187455714Skris } 187555714Skris 187655714Skris if (preserve) 187755714Skris { 187855714Skris X509_NAME_free(subject); 1879109998Smarkm /* subject=X509_NAME_dup(X509_REQ_get_subject_name(req)); */ 1880109998Smarkm subject=X509_NAME_dup(name); 188155714Skris if (subject == NULL) goto err; 188255714Skris } 188355714Skris 188455714Skris if (verbose) 188559191Skris BIO_printf(bio_err,"The subject name appears to be ok, checking data base for clashes\n"); 188655714Skris 1887109998Smarkm /* Build the correct Subject if no e-mail is wanted in the subject */ 1888109998Smarkm /* and add it later on because of the method extensions are added (altName) */ 1889109998Smarkm 1890109998Smarkm if (email_dn) 1891109998Smarkm dn_subject = subject; 1892109998Smarkm else 189355714Skris { 1894109998Smarkm X509_NAME_ENTRY *tmpne; 1895109998Smarkm /* Its best to dup the subject DN and then delete any email 1896109998Smarkm * addresses because this retains its structure. 1897109998Smarkm */ 1898109998Smarkm if (!(dn_subject = X509_NAME_dup(subject))) 1899109998Smarkm { 1900109998Smarkm BIO_printf(bio_err,"Memory allocation failure\n"); 1901109998Smarkm goto err; 1902109998Smarkm } 1903109998Smarkm while((i = X509_NAME_get_index_by_NID(dn_subject, 1904109998Smarkm NID_pkcs9_emailAddress, -1)) >= 0) 1905109998Smarkm { 1906109998Smarkm tmpne = X509_NAME_get_entry(dn_subject, i); 1907109998Smarkm X509_NAME_delete_entry(dn_subject, i); 1908109998Smarkm X509_NAME_ENTRY_free(tmpne); 1909109998Smarkm } 1910109998Smarkm } 1911109998Smarkm 1912109998Smarkm if (BN_is_zero(serial)) 1913109998Smarkm row[DB_serial]=BUF_strdup("00"); 1914109998Smarkm else 1915109998Smarkm row[DB_serial]=BN_bn2hex(serial); 1916109998Smarkm if (row[DB_serial] == NULL) 1917109998Smarkm { 191868651Skris BIO_printf(bio_err,"Memory allocation failure\n"); 191955714Skris goto err; 192055714Skris } 192155714Skris 1922127128Snectar if (db->attributes.unique_subject) 192355714Skris { 1924127128Snectar rrow=TXT_DB_get_by_index(db->db,DB_name,row); 1925127128Snectar if (rrow != NULL) 1926127128Snectar { 1927127128Snectar BIO_printf(bio_err, 1928127128Snectar "ERROR:There is already a certificate for %s\n", 1929127128Snectar row[DB_name]); 1930127128Snectar } 193155714Skris } 1932127128Snectar if (rrow == NULL) 193355714Skris { 1934127128Snectar rrow=TXT_DB_get_by_index(db->db,DB_serial,row); 193555714Skris if (rrow != NULL) 193655714Skris { 193755714Skris BIO_printf(bio_err,"ERROR:Serial number %s has already been issued,\n", 193855714Skris row[DB_serial]); 193955714Skris BIO_printf(bio_err," check the database/serial_file for corruption\n"); 194055714Skris } 194155714Skris } 194255714Skris 194355714Skris if (rrow != NULL) 194455714Skris { 194555714Skris BIO_printf(bio_err, 194655714Skris "The matching entry has the following details\n"); 194755714Skris if (rrow[DB_type][0] == 'E') 194855714Skris p="Expired"; 194955714Skris else if (rrow[DB_type][0] == 'R') 195055714Skris p="Revoked"; 195155714Skris else if (rrow[DB_type][0] == 'V') 195255714Skris p="Valid"; 195355714Skris else 195455714Skris p="\ninvalid type, Data base error\n"; 195555714Skris BIO_printf(bio_err,"Type :%s\n",p);; 195655714Skris if (rrow[DB_type][0] == 'R') 195755714Skris { 195855714Skris p=rrow[DB_exp_date]; if (p == NULL) p="undef"; 195955714Skris BIO_printf(bio_err,"Was revoked on:%s\n",p); 196055714Skris } 196155714Skris p=rrow[DB_exp_date]; if (p == NULL) p="undef"; 196255714Skris BIO_printf(bio_err,"Expires on :%s\n",p); 196355714Skris p=rrow[DB_serial]; if (p == NULL) p="undef"; 196455714Skris BIO_printf(bio_err,"Serial Number :%s\n",p); 196555714Skris p=rrow[DB_file]; if (p == NULL) p="undef"; 196655714Skris BIO_printf(bio_err,"File name :%s\n",p); 196755714Skris p=rrow[DB_name]; if (p == NULL) p="undef"; 196855714Skris BIO_printf(bio_err,"Subject Name :%s\n",p); 196955714Skris ok= -1; /* This is now a 'bad' error. */ 197055714Skris goto err; 197155714Skris } 197255714Skris 197359191Skris /* We are now totally happy, lets make and sign the certificate */ 197455714Skris if (verbose) 197555714Skris BIO_printf(bio_err,"Everything appears to be ok, creating and signing the certificate\n"); 197655714Skris 197755714Skris if ((ret=X509_new()) == NULL) goto err; 197855714Skris ci=ret->cert_info; 197955714Skris 198055714Skris#ifdef X509_V3 198155714Skris /* Make it an X509 v3 certificate. */ 1982120631Snectar if (!X509_set_version(ret,2)) goto err; 198355714Skris#endif 198455714Skris 198555714Skris if (BN_to_ASN1_INTEGER(serial,ci->serialNumber) == NULL) 198655714Skris goto err; 1987160814Ssimon if (selfsign) 1988160814Ssimon { 1989160814Ssimon if (!X509_set_issuer_name(ret,subject)) 1990160814Ssimon goto err; 1991160814Ssimon } 1992160814Ssimon else 1993160814Ssimon { 1994160814Ssimon if (!X509_set_issuer_name(ret,X509_get_subject_name(x509))) 1995160814Ssimon goto err; 1996160814Ssimon } 199755714Skris 199855714Skris if (strcmp(startdate,"today") == 0) 199955714Skris X509_gmtime_adj(X509_get_notBefore(ret),0); 200055714Skris else ASN1_UTCTIME_set_string(X509_get_notBefore(ret),startdate); 200155714Skris 200255714Skris if (enddate == NULL) 200355714Skris X509_gmtime_adj(X509_get_notAfter(ret),(long)60*60*24*days); 200455714Skris else ASN1_UTCTIME_set_string(X509_get_notAfter(ret),enddate); 200555714Skris 200655714Skris if (!X509_set_subject_name(ret,subject)) goto err; 200755714Skris 200855714Skris pktmp=X509_REQ_get_pubkey(req); 200955714Skris i = X509_set_pubkey(ret,pktmp); 201055714Skris EVP_PKEY_free(pktmp); 201155714Skris if (!i) goto err; 201255714Skris 201355714Skris /* Lets add the extensions, if there are any */ 201455714Skris if (ext_sect) 201555714Skris { 201655714Skris X509V3_CTX ctx; 201755714Skris if (ci->version == NULL) 201855714Skris if ((ci->version=ASN1_INTEGER_new()) == NULL) 201955714Skris goto err; 202055714Skris ASN1_INTEGER_set(ci->version,2); /* version 3 certificate */ 202155714Skris 202255714Skris /* Free the current entries if any, there should not 202359191Skris * be any I believe */ 202455714Skris if (ci->extensions != NULL) 202555714Skris sk_X509_EXTENSION_pop_free(ci->extensions, 202655714Skris X509_EXTENSION_free); 202755714Skris 202855714Skris ci->extensions = NULL; 202955714Skris 2030109998Smarkm /* Initialize the context structure */ 2031160814Ssimon if (selfsign) 2032160814Ssimon X509V3_set_ctx(&ctx, ret, ret, req, NULL, 0); 2033160814Ssimon else 2034160814Ssimon X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0); 203555714Skris 2036109998Smarkm if (extconf) 2037109998Smarkm { 2038109998Smarkm if (verbose) 2039109998Smarkm BIO_printf(bio_err, "Extra configuration file found\n"); 2040109998Smarkm 2041109998Smarkm /* Use the extconf configuration db LHASH */ 2042109998Smarkm X509V3_set_nconf(&ctx, extconf); 2043109998Smarkm 2044109998Smarkm /* Test the structure (needed?) */ 2045109998Smarkm /* X509V3_set_ctx_test(&ctx); */ 204655714Skris 2047109998Smarkm /* Adds exts contained in the configuration file */ 2048109998Smarkm if (!X509V3_EXT_add_nconf(extconf, &ctx, ext_sect,ret)) 2049109998Smarkm { 2050109998Smarkm BIO_printf(bio_err, 2051109998Smarkm "ERROR: adding extensions in section %s\n", 2052109998Smarkm ext_sect); 2053109998Smarkm ERR_print_errors(bio_err); 2054109998Smarkm goto err; 2055109998Smarkm } 2056109998Smarkm if (verbose) 2057109998Smarkm BIO_printf(bio_err, "Successfully added extensions from file.\n"); 2058109998Smarkm } 2059109998Smarkm else if (ext_sect) 2060109998Smarkm { 2061109998Smarkm /* We found extensions to be set from config file */ 2062109998Smarkm X509V3_set_nconf(&ctx, lconf); 2063109998Smarkm 2064109998Smarkm if(!X509V3_EXT_add_nconf(lconf, &ctx, ext_sect, ret)) 2065109998Smarkm { 2066109998Smarkm BIO_printf(bio_err, "ERROR: adding extensions in section %s\n", ext_sect); 2067109998Smarkm ERR_print_errors(bio_err); 2068109998Smarkm goto err; 2069109998Smarkm } 2070109998Smarkm 2071109998Smarkm if (verbose) 2072109998Smarkm BIO_printf(bio_err, "Successfully added extensions from config\n"); 2073109998Smarkm } 207455714Skris } 207555714Skris 2076109998Smarkm /* Copy extensions from request (if any) */ 207755714Skris 2078109998Smarkm if (!copy_extensions(ret, req, ext_copy)) 2079109998Smarkm { 2080109998Smarkm BIO_printf(bio_err, "ERROR: adding extensions from request\n"); 2081109998Smarkm ERR_print_errors(bio_err); 2082109998Smarkm goto err; 2083109998Smarkm } 2084109998Smarkm 2085109998Smarkm /* Set the right value for the noemailDN option */ 2086109998Smarkm if( email_dn == 0 ) 2087109998Smarkm { 2088109998Smarkm if (!X509_set_subject_name(ret,dn_subject)) goto err; 2089109998Smarkm } 2090109998Smarkm 2091109998Smarkm if (!default_op) 2092109998Smarkm { 2093109998Smarkm BIO_printf(bio_err, "Certificate Details:\n"); 2094109998Smarkm /* Never print signature details because signature not present */ 2095109998Smarkm certopt |= X509_FLAG_NO_SIGDUMP | X509_FLAG_NO_SIGNAME; 2096109998Smarkm X509_print_ex(bio_err, ret, nameopt, certopt); 2097109998Smarkm } 2098109998Smarkm 2099109998Smarkm BIO_printf(bio_err,"Certificate is to be certified until "); 2100205128Ssimon ASN1_TIME_print(bio_err,X509_get_notAfter(ret)); 2101160814Ssimon if (days) BIO_printf(bio_err," (%ld days)",days); 2102109998Smarkm BIO_printf(bio_err, "\n"); 2103109998Smarkm 210455714Skris if (!batch) 210555714Skris { 2106109998Smarkm 210755714Skris BIO_printf(bio_err,"Sign the certificate? [y/n]:"); 210855714Skris (void)BIO_flush(bio_err); 210955714Skris buf[0]='\0'; 2110205128Ssimon if (!fgets(buf,sizeof(buf)-1,stdin)) 2111205128Ssimon { 2112205128Ssimon BIO_printf(bio_err,"CERTIFICATE WILL NOT BE CERTIFIED: I/O error\n"); 2113205128Ssimon ok=0; 2114205128Ssimon goto err; 2115205128Ssimon } 211655714Skris if (!((buf[0] == 'y') || (buf[0] == 'Y'))) 211755714Skris { 211855714Skris BIO_printf(bio_err,"CERTIFICATE WILL NOT BE CERTIFIED\n"); 211955714Skris ok=0; 212055714Skris goto err; 212155714Skris } 212255714Skris } 212355714Skris 212455714Skris 2125109998Smarkm#ifndef OPENSSL_NO_DSA 212655714Skris if (pkey->type == EVP_PKEY_DSA) dgst=EVP_dss1(); 212755714Skris pktmp=X509_get_pubkey(ret); 212855714Skris if (EVP_PKEY_missing_parameters(pktmp) && 212955714Skris !EVP_PKEY_missing_parameters(pkey)) 213055714Skris EVP_PKEY_copy_parameters(pktmp,pkey); 213155714Skris EVP_PKEY_free(pktmp); 213255714Skris#endif 2133160814Ssimon#ifndef OPENSSL_NO_ECDSA 2134160814Ssimon if (pkey->type == EVP_PKEY_EC) 2135160814Ssimon dgst = EVP_ecdsa(); 2136160814Ssimon pktmp = X509_get_pubkey(ret); 2137160814Ssimon if (EVP_PKEY_missing_parameters(pktmp) && 2138160814Ssimon !EVP_PKEY_missing_parameters(pkey)) 2139160814Ssimon EVP_PKEY_copy_parameters(pktmp, pkey); 2140160814Ssimon EVP_PKEY_free(pktmp); 2141160814Ssimon#endif 214255714Skris 2143160814Ssimon 214455714Skris if (!X509_sign(ret,pkey,dgst)) 214555714Skris goto err; 214655714Skris 214755714Skris /* We now just add it to the database */ 214868651Skris row[DB_type]=(char *)OPENSSL_malloc(2); 214955714Skris 215055714Skris tm=X509_get_notAfter(ret); 215168651Skris row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1); 215255714Skris memcpy(row[DB_exp_date],tm->data,tm->length); 215355714Skris row[DB_exp_date][tm->length]='\0'; 215455714Skris 215555714Skris row[DB_rev_date]=NULL; 215655714Skris 215755714Skris /* row[DB_serial] done already */ 215868651Skris row[DB_file]=(char *)OPENSSL_malloc(8); 2159109998Smarkm row[DB_name]=X509_NAME_oneline(X509_get_subject_name(ret),NULL,0); 216055714Skris 216155714Skris if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) || 2162109998Smarkm (row[DB_file] == NULL) || (row[DB_name] == NULL)) 216355714Skris { 216468651Skris BIO_printf(bio_err,"Memory allocation failure\n"); 216555714Skris goto err; 216655714Skris } 2167127128Snectar BUF_strlcpy(row[DB_file],"unknown",8); 216855714Skris row[DB_type][0]='V'; 216955714Skris row[DB_type][1]='\0'; 217055714Skris 217168651Skris if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL) 217255714Skris { 217368651Skris BIO_printf(bio_err,"Memory allocation failure\n"); 217455714Skris goto err; 217555714Skris } 217655714Skris 217755714Skris for (i=0; i<DB_NUMBER; i++) 217855714Skris { 217955714Skris irow[i]=row[i]; 218055714Skris row[i]=NULL; 218155714Skris } 218255714Skris irow[DB_NUMBER]=NULL; 218355714Skris 2184127128Snectar if (!TXT_DB_insert(db->db,irow)) 218555714Skris { 218655714Skris BIO_printf(bio_err,"failed to update database\n"); 2187127128Snectar BIO_printf(bio_err,"TXT_DB error number %ld\n",db->db->error); 218855714Skris goto err; 218955714Skris } 219055714Skris ok=1; 219155714Skriserr: 219255714Skris for (i=0; i<DB_NUMBER; i++) 219368651Skris if (row[i] != NULL) OPENSSL_free(row[i]); 219455714Skris 219555714Skris if (CAname != NULL) 219655714Skris X509_NAME_free(CAname); 219755714Skris if (subject != NULL) 219855714Skris X509_NAME_free(subject); 2199109998Smarkm if ((dn_subject != NULL) && !email_dn) 2200109998Smarkm X509_NAME_free(dn_subject); 220159191Skris if (tmptm != NULL) 220259191Skris ASN1_UTCTIME_free(tmptm); 220355714Skris if (ok <= 0) 220455714Skris { 220555714Skris if (ret != NULL) X509_free(ret); 220655714Skris ret=NULL; 220755714Skris } 220855714Skris else 220955714Skris *xret=ret; 221055714Skris return(ok); 221155714Skris } 221255714Skris 221359191Skrisstatic void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext) 221455714Skris { 221555714Skris 221655714Skris if (output_der) 221755714Skris { 221855714Skris (void)i2d_X509_bio(bp,x); 221955714Skris return; 222055714Skris } 222159191Skris#if 0 222259191Skris /* ??? Not needed since X509_print prints all this stuff anyway */ 222355714Skris f=X509_NAME_oneline(X509_get_issuer_name(x),buf,256); 222455714Skris BIO_printf(bp,"issuer :%s\n",f); 222555714Skris 222655714Skris f=X509_NAME_oneline(X509_get_subject_name(x),buf,256); 222755714Skris BIO_printf(bp,"subject:%s\n",f); 222855714Skris 222955714Skris BIO_puts(bp,"serial :"); 223055714Skris i2a_ASN1_INTEGER(bp,x->cert_info->serialNumber); 223155714Skris BIO_puts(bp,"\n\n"); 223259191Skris#endif 2233109998Smarkm if (!notext)X509_print(bp,x); 223455714Skris PEM_write_bio_X509(bp,x); 223555714Skris } 223655714Skris 223755714Skrisstatic int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, 2238127128Snectar const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, CA_DB *db, 2239160814Ssimon BIGNUM *serial, char *subj,unsigned long chtype, int multirdn, int email_dn, char *startdate, char *enddate, 2240109998Smarkm long days, char *ext_sect, CONF *lconf, int verbose, unsigned long certopt, 2241109998Smarkm unsigned long nameopt, int default_op, int ext_copy) 224255714Skris { 224355714Skris STACK_OF(CONF_VALUE) *sk=NULL; 224455714Skris LHASH *parms=NULL; 224555714Skris X509_REQ *req=NULL; 224655714Skris CONF_VALUE *cv=NULL; 224755714Skris NETSCAPE_SPKI *spki = NULL; 224855714Skris X509_REQ_INFO *ri; 224955714Skris char *type,*buf; 225055714Skris EVP_PKEY *pktmp=NULL; 225155714Skris X509_NAME *n=NULL; 225255714Skris X509_NAME_ENTRY *ne=NULL; 225355714Skris int ok= -1,i,j; 225455714Skris long errline; 225555714Skris int nid; 225655714Skris 225755714Skris /* 225855714Skris * Load input file into a hash table. (This is just an easy 225955714Skris * way to read and parse the file, then put it into a convenient 226055714Skris * STACK format). 226155714Skris */ 226255714Skris parms=CONF_load(NULL,infile,&errline); 226355714Skris if (parms == NULL) 226455714Skris { 226555714Skris BIO_printf(bio_err,"error on line %ld of %s\n",errline,infile); 226655714Skris ERR_print_errors(bio_err); 226755714Skris goto err; 226855714Skris } 226955714Skris 227055714Skris sk=CONF_get_section(parms, "default"); 227155714Skris if (sk_CONF_VALUE_num(sk) == 0) 227255714Skris { 227355714Skris BIO_printf(bio_err, "no name/value pairs found in %s\n", infile); 227455714Skris CONF_free(parms); 227555714Skris goto err; 227655714Skris } 227755714Skris 227855714Skris /* 227955714Skris * Now create a dummy X509 request structure. We don't actually 228055714Skris * have an X509 request, but we have many of the components 228155714Skris * (a public key, various DN components). The idea is that we 228255714Skris * put these components into the right X509 request structure 228355714Skris * and we can use the same code as if you had a real X509 request. 228455714Skris */ 228555714Skris req=X509_REQ_new(); 228655714Skris if (req == NULL) 228755714Skris { 228855714Skris ERR_print_errors(bio_err); 228955714Skris goto err; 229055714Skris } 229155714Skris 229255714Skris /* 229355714Skris * Build up the subject name set. 229455714Skris */ 229555714Skris ri=req->req_info; 229655714Skris n = ri->subject; 229755714Skris 229855714Skris for (i = 0; ; i++) 229955714Skris { 230055714Skris if (sk_CONF_VALUE_num(sk) <= i) break; 230155714Skris 230255714Skris cv=sk_CONF_VALUE_value(sk,i); 230355714Skris type=cv->name; 230459191Skris /* Skip past any leading X. X: X, etc to allow for 230559191Skris * multiple instances 230659191Skris */ 2307109998Smarkm for (buf = cv->name; *buf ; buf++) 2308109998Smarkm if ((*buf == ':') || (*buf == ',') || (*buf == '.')) 2309109998Smarkm { 2310109998Smarkm buf++; 2311109998Smarkm if (*buf) type = buf; 2312109998Smarkm break; 2313109998Smarkm } 231459191Skris 231555714Skris buf=cv->value; 231655714Skris if ((nid=OBJ_txt2nid(type)) == NID_undef) 231755714Skris { 231855714Skris if (strcmp(type, "SPKAC") == 0) 231955714Skris { 232059191Skris spki = NETSCAPE_SPKI_b64_decode(cv->value, -1); 232155714Skris if (spki == NULL) 232255714Skris { 232355714Skris BIO_printf(bio_err,"unable to load Netscape SPKAC structure\n"); 232455714Skris ERR_print_errors(bio_err); 232555714Skris goto err; 232655714Skris } 232755714Skris } 232855714Skris continue; 232955714Skris } 233055714Skris 2331205128Ssimon if (!X509_NAME_add_entry_by_NID(n, nid, chtype, 2332205128Ssimon (unsigned char *)buf, -1, -1, 0)) 233355714Skris goto err; 233455714Skris } 233555714Skris if (spki == NULL) 233655714Skris { 233755714Skris BIO_printf(bio_err,"Netscape SPKAC structure not found in %s\n", 233855714Skris infile); 233955714Skris goto err; 234055714Skris } 234155714Skris 234255714Skris /* 234355714Skris * Now extract the key from the SPKI structure. 234455714Skris */ 234555714Skris 234655714Skris BIO_printf(bio_err,"Check that the SPKAC request matches the signature\n"); 234755714Skris 234859191Skris if ((pktmp=NETSCAPE_SPKI_get_pubkey(spki)) == NULL) 234955714Skris { 235055714Skris BIO_printf(bio_err,"error unpacking SPKAC public key\n"); 235155714Skris goto err; 235255714Skris } 235355714Skris 235455714Skris j = NETSCAPE_SPKI_verify(spki, pktmp); 235555714Skris if (j <= 0) 235655714Skris { 235755714Skris BIO_printf(bio_err,"signature verification failed on SPKAC public key\n"); 235855714Skris goto err; 235955714Skris } 236055714Skris BIO_printf(bio_err,"Signature ok\n"); 236155714Skris 236255714Skris X509_REQ_set_pubkey(req,pktmp); 236355714Skris EVP_PKEY_free(pktmp); 2364160814Ssimon ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,chtype,multirdn,email_dn,startdate,enddate, 2365109998Smarkm days,1,verbose,req,ext_sect,lconf, certopt, nameopt, default_op, 2366160814Ssimon ext_copy, 0); 236755714Skriserr: 236855714Skris if (req != NULL) X509_REQ_free(req); 236955714Skris if (parms != NULL) CONF_free(parms); 237055714Skris if (spki != NULL) NETSCAPE_SPKI_free(spki); 237155714Skris if (ne != NULL) X509_NAME_ENTRY_free(ne); 237255714Skris 237355714Skris return(ok); 237455714Skris } 237555714Skris 2376205128Ssimonstatic int check_time_format(const char *str) 237755714Skris { 2378205128Ssimon ASN1_TIME tm; 237955714Skris 238055714Skris tm.data=(unsigned char *)str; 238155714Skris tm.length=strlen(str); 238255714Skris tm.type=V_ASN1_UTCTIME; 2383205128Ssimon if (ASN1_TIME_check(&tm)) 2384205128Ssimon return 1; 2385205128Ssimon tm.type=V_ASN1_GENERALIZEDTIME; 2386205128Ssimon return ASN1_TIME_check(&tm); 238755714Skris } 238855714Skris 2389127128Snectarstatic int do_revoke(X509 *x509, CA_DB *db, int type, char *value) 2390109998Smarkm { 2391109998Smarkm ASN1_UTCTIME *tm=NULL; 239255714Skris char *row[DB_NUMBER],**rrow,**irow; 2393109998Smarkm char *rev_str = NULL; 239459191Skris BIGNUM *bn = NULL; 239555714Skris int ok=-1,i; 239655714Skris 239755714Skris for (i=0; i<DB_NUMBER; i++) 239855714Skris row[i]=NULL; 239959191Skris row[DB_name]=X509_NAME_oneline(X509_get_subject_name(x509),NULL,0); 240059191Skris bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509),NULL); 2401109998Smarkm if (BN_is_zero(bn)) 2402109998Smarkm row[DB_serial]=BUF_strdup("00"); 2403109998Smarkm else 2404109998Smarkm row[DB_serial]=BN_bn2hex(bn); 240559191Skris BN_free(bn); 240655714Skris if ((row[DB_name] == NULL) || (row[DB_serial] == NULL)) 240755714Skris { 240868651Skris BIO_printf(bio_err,"Memory allocation failure\n"); 240955714Skris goto err; 241055714Skris } 241159191Skris /* We have to lookup by serial number because name lookup 241259191Skris * skips revoked certs 241359191Skris */ 2414127128Snectar rrow=TXT_DB_get_by_index(db->db,DB_serial,row); 241555714Skris if (rrow == NULL) 241655714Skris { 2417127128Snectar BIO_printf(bio_err,"Adding Entry with serial number %s to DB for %s\n", row[DB_serial], row[DB_name]); 241855714Skris 241955714Skris /* We now just add it to the database */ 242068651Skris row[DB_type]=(char *)OPENSSL_malloc(2); 242155714Skris 242255714Skris tm=X509_get_notAfter(x509); 242368651Skris row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1); 242455714Skris memcpy(row[DB_exp_date],tm->data,tm->length); 242555714Skris row[DB_exp_date][tm->length]='\0'; 242655714Skris 242755714Skris row[DB_rev_date]=NULL; 242855714Skris 242955714Skris /* row[DB_serial] done already */ 243068651Skris row[DB_file]=(char *)OPENSSL_malloc(8); 243155714Skris 243255714Skris /* row[DB_name] done already */ 243355714Skris 243455714Skris if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) || 243555714Skris (row[DB_file] == NULL)) 243655714Skris { 243768651Skris BIO_printf(bio_err,"Memory allocation failure\n"); 243855714Skris goto err; 243955714Skris } 2440127128Snectar BUF_strlcpy(row[DB_file],"unknown",8); 244155714Skris row[DB_type][0]='V'; 244255714Skris row[DB_type][1]='\0'; 244355714Skris 244468651Skris if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL) 244555714Skris { 244668651Skris BIO_printf(bio_err,"Memory allocation failure\n"); 244755714Skris goto err; 244855714Skris } 244955714Skris 245055714Skris for (i=0; i<DB_NUMBER; i++) 245155714Skris { 245255714Skris irow[i]=row[i]; 245355714Skris row[i]=NULL; 245455714Skris } 245555714Skris irow[DB_NUMBER]=NULL; 245655714Skris 2457127128Snectar if (!TXT_DB_insert(db->db,irow)) 245855714Skris { 245955714Skris BIO_printf(bio_err,"failed to update database\n"); 2460127128Snectar BIO_printf(bio_err,"TXT_DB error number %ld\n",db->db->error); 246155714Skris goto err; 246255714Skris } 246355714Skris 246455714Skris /* Revoke Certificate */ 2465109998Smarkm ok = do_revoke(x509,db, type, value); 246655714Skris 246755714Skris goto err; 246855714Skris 246955714Skris } 2470109998Smarkm else if (index_name_cmp((const char **)row,(const char **)rrow)) 247155714Skris { 247259191Skris BIO_printf(bio_err,"ERROR:name does not match %s\n", 247359191Skris row[DB_name]); 247455714Skris goto err; 247555714Skris } 247655714Skris else if (rrow[DB_type][0]=='R') 247755714Skris { 247855714Skris BIO_printf(bio_err,"ERROR:Already revoked, serial number %s\n", 247955714Skris row[DB_serial]); 248055714Skris goto err; 248155714Skris } 248255714Skris else 248355714Skris { 248455714Skris BIO_printf(bio_err,"Revoking Certificate %s.\n", rrow[DB_serial]); 2485109998Smarkm rev_str = make_revocation_str(type, value); 2486109998Smarkm if (!rev_str) 2487109998Smarkm { 2488109998Smarkm BIO_printf(bio_err, "Error in revocation arguments\n"); 2489109998Smarkm goto err; 2490109998Smarkm } 249155714Skris rrow[DB_type][0]='R'; 249255714Skris rrow[DB_type][1]='\0'; 2493109998Smarkm rrow[DB_rev_date] = rev_str; 249455714Skris } 249555714Skris ok=1; 249655714Skriserr: 249755714Skris for (i=0; i<DB_NUMBER; i++) 249855714Skris { 249955714Skris if (row[i] != NULL) 250068651Skris OPENSSL_free(row[i]); 250155714Skris } 250255714Skris return(ok); 2503109998Smarkm } 2504109998Smarkm 2505127128Snectarstatic int get_certificate_status(const char *serial, CA_DB *db) 2506109998Smarkm { 2507109998Smarkm char *row[DB_NUMBER],**rrow; 2508109998Smarkm int ok=-1,i; 2509109998Smarkm 2510109998Smarkm /* Free Resources */ 2511109998Smarkm for (i=0; i<DB_NUMBER; i++) 2512109998Smarkm row[i]=NULL; 2513109998Smarkm 2514109998Smarkm /* Malloc needed char spaces */ 2515109998Smarkm row[DB_serial] = OPENSSL_malloc(strlen(serial) + 2); 2516109998Smarkm if (row[DB_serial] == NULL) 2517109998Smarkm { 2518109998Smarkm BIO_printf(bio_err,"Malloc failure\n"); 2519109998Smarkm goto err; 2520109998Smarkm } 2521109998Smarkm 2522109998Smarkm if (strlen(serial) % 2) 2523109998Smarkm { 2524109998Smarkm /* Set the first char to 0 */; 2525109998Smarkm row[DB_serial][0]='0'; 2526109998Smarkm 2527109998Smarkm /* Copy String from serial to row[DB_serial] */ 2528109998Smarkm memcpy(row[DB_serial]+1, serial, strlen(serial)); 2529109998Smarkm row[DB_serial][strlen(serial)+1]='\0'; 2530109998Smarkm } 2531109998Smarkm else 2532109998Smarkm { 2533109998Smarkm /* Copy String from serial to row[DB_serial] */ 2534109998Smarkm memcpy(row[DB_serial], serial, strlen(serial)); 2535109998Smarkm row[DB_serial][strlen(serial)]='\0'; 2536109998Smarkm } 2537109998Smarkm 2538109998Smarkm /* Make it Upper Case */ 2539109998Smarkm for (i=0; row[DB_serial][i] != '\0'; i++) 2540109998Smarkm row[DB_serial][i] = toupper(row[DB_serial][i]); 2541109998Smarkm 2542109998Smarkm 2543109998Smarkm ok=1; 2544109998Smarkm 2545109998Smarkm /* Search for the certificate */ 2546127128Snectar rrow=TXT_DB_get_by_index(db->db,DB_serial,row); 2547109998Smarkm if (rrow == NULL) 2548109998Smarkm { 2549109998Smarkm BIO_printf(bio_err,"Serial %s not present in db.\n", 2550109998Smarkm row[DB_serial]); 2551109998Smarkm ok=-1; 2552109998Smarkm goto err; 2553109998Smarkm } 2554109998Smarkm else if (rrow[DB_type][0]=='V') 2555109998Smarkm { 2556109998Smarkm BIO_printf(bio_err,"%s=Valid (%c)\n", 2557109998Smarkm row[DB_serial], rrow[DB_type][0]); 2558109998Smarkm goto err; 2559109998Smarkm } 2560109998Smarkm else if (rrow[DB_type][0]=='R') 2561109998Smarkm { 2562109998Smarkm BIO_printf(bio_err,"%s=Revoked (%c)\n", 2563109998Smarkm row[DB_serial], rrow[DB_type][0]); 2564109998Smarkm goto err; 2565109998Smarkm } 2566109998Smarkm else if (rrow[DB_type][0]=='E') 2567109998Smarkm { 2568109998Smarkm BIO_printf(bio_err,"%s=Expired (%c)\n", 2569109998Smarkm row[DB_serial], rrow[DB_type][0]); 2570109998Smarkm goto err; 2571109998Smarkm } 2572109998Smarkm else if (rrow[DB_type][0]=='S') 2573109998Smarkm { 2574109998Smarkm BIO_printf(bio_err,"%s=Suspended (%c)\n", 2575109998Smarkm row[DB_serial], rrow[DB_type][0]); 2576109998Smarkm goto err; 2577109998Smarkm } 2578109998Smarkm else 2579109998Smarkm { 2580109998Smarkm BIO_printf(bio_err,"%s=Unknown (%c).\n", 2581109998Smarkm row[DB_serial], rrow[DB_type][0]); 2582109998Smarkm ok=-1; 2583109998Smarkm } 2584109998Smarkmerr: 2585109998Smarkm for (i=0; i<DB_NUMBER; i++) 2586109998Smarkm { 2587109998Smarkm if (row[i] != NULL) 2588109998Smarkm OPENSSL_free(row[i]); 2589109998Smarkm } 2590109998Smarkm return(ok); 2591109998Smarkm } 2592109998Smarkm 2593127128Snectarstatic int do_updatedb (CA_DB *db) 2594109998Smarkm { 2595109998Smarkm ASN1_UTCTIME *a_tm = NULL; 2596109998Smarkm int i, cnt = 0; 2597109998Smarkm int db_y2k, a_y2k; /* flags = 1 if y >= 2000 */ 2598109998Smarkm char **rrow, *a_tm_s; 2599109998Smarkm 2600109998Smarkm a_tm = ASN1_UTCTIME_new(); 2601109998Smarkm 2602109998Smarkm /* get actual time and make a string */ 2603109998Smarkm a_tm = X509_gmtime_adj(a_tm, 0); 2604109998Smarkm a_tm_s = (char *) OPENSSL_malloc(a_tm->length+1); 2605109998Smarkm if (a_tm_s == NULL) 2606109998Smarkm { 2607109998Smarkm cnt = -1; 2608109998Smarkm goto err; 2609109998Smarkm } 2610109998Smarkm 2611109998Smarkm memcpy(a_tm_s, a_tm->data, a_tm->length); 2612109998Smarkm a_tm_s[a_tm->length] = '\0'; 2613109998Smarkm 2614109998Smarkm if (strncmp(a_tm_s, "49", 2) <= 0) 2615109998Smarkm a_y2k = 1; 2616109998Smarkm else 2617109998Smarkm a_y2k = 0; 2618109998Smarkm 2619127128Snectar for (i = 0; i < sk_num(db->db->data); i++) 2620109998Smarkm { 2621127128Snectar rrow = (char **) sk_value(db->db->data, i); 2622109998Smarkm 2623109998Smarkm if (rrow[DB_type][0] == 'V') 2624109998Smarkm { 2625109998Smarkm /* ignore entries that are not valid */ 2626109998Smarkm if (strncmp(rrow[DB_exp_date], "49", 2) <= 0) 2627109998Smarkm db_y2k = 1; 2628109998Smarkm else 2629109998Smarkm db_y2k = 0; 2630109998Smarkm 2631109998Smarkm if (db_y2k == a_y2k) 2632109998Smarkm { 2633109998Smarkm /* all on the same y2k side */ 2634109998Smarkm if (strcmp(rrow[DB_exp_date], a_tm_s) <= 0) 2635109998Smarkm { 2636109998Smarkm rrow[DB_type][0] = 'E'; 2637109998Smarkm rrow[DB_type][1] = '\0'; 2638109998Smarkm cnt++; 2639109998Smarkm 2640109998Smarkm BIO_printf(bio_err, "%s=Expired\n", 2641109998Smarkm rrow[DB_serial]); 2642109998Smarkm } 2643109998Smarkm } 2644109998Smarkm else if (db_y2k < a_y2k) 2645109998Smarkm { 2646109998Smarkm rrow[DB_type][0] = 'E'; 2647109998Smarkm rrow[DB_type][1] = '\0'; 2648109998Smarkm cnt++; 2649109998Smarkm 2650109998Smarkm BIO_printf(bio_err, "%s=Expired\n", 2651109998Smarkm rrow[DB_serial]); 2652109998Smarkm } 2653109998Smarkm 2654109998Smarkm } 2655109998Smarkm } 2656109998Smarkm 2657109998Smarkmerr: 2658109998Smarkm 2659109998Smarkm ASN1_UTCTIME_free(a_tm); 2660109998Smarkm OPENSSL_free(a_tm_s); 2661109998Smarkm 2662109998Smarkm return (cnt); 2663109998Smarkm } 2664109998Smarkm 2665160814Ssimonstatic const char *crl_reasons[] = { 2666109998Smarkm /* CRL reason strings */ 2667109998Smarkm "unspecified", 2668109998Smarkm "keyCompromise", 2669109998Smarkm "CACompromise", 2670109998Smarkm "affiliationChanged", 2671109998Smarkm "superseded", 2672109998Smarkm "cessationOfOperation", 2673109998Smarkm "certificateHold", 2674109998Smarkm "removeFromCRL", 2675109998Smarkm /* Additional pseudo reasons */ 2676109998Smarkm "holdInstruction", 2677109998Smarkm "keyTime", 2678109998Smarkm "CAkeyTime" 2679109998Smarkm}; 2680109998Smarkm 2681109998Smarkm#define NUM_REASONS (sizeof(crl_reasons) / sizeof(char *)) 2682109998Smarkm 2683109998Smarkm/* Given revocation information convert to a DB string. 2684109998Smarkm * The format of the string is: 2685109998Smarkm * revtime[,reason,extra]. Where 'revtime' is the 2686109998Smarkm * revocation time (the current time). 'reason' is the 2687109998Smarkm * optional CRL reason and 'extra' is any additional 2688109998Smarkm * argument 2689109998Smarkm */ 2690109998Smarkm 2691109998Smarkmchar *make_revocation_str(int rev_type, char *rev_arg) 2692109998Smarkm { 2693160814Ssimon char *other = NULL, *str; 2694160814Ssimon const char *reason = NULL; 2695109998Smarkm ASN1_OBJECT *otmp; 2696109998Smarkm ASN1_UTCTIME *revtm = NULL; 2697109998Smarkm int i; 2698109998Smarkm switch (rev_type) 2699109998Smarkm { 2700109998Smarkm case REV_NONE: 2701109998Smarkm break; 2702109998Smarkm 2703109998Smarkm case REV_CRL_REASON: 2704109998Smarkm for (i = 0; i < 8; i++) 2705109998Smarkm { 2706109998Smarkm if (!strcasecmp(rev_arg, crl_reasons[i])) 2707109998Smarkm { 2708109998Smarkm reason = crl_reasons[i]; 2709109998Smarkm break; 2710109998Smarkm } 2711109998Smarkm } 2712109998Smarkm if (reason == NULL) 2713109998Smarkm { 2714109998Smarkm BIO_printf(bio_err, "Unknown CRL reason %s\n", rev_arg); 2715109998Smarkm return NULL; 2716109998Smarkm } 2717109998Smarkm break; 2718109998Smarkm 2719109998Smarkm case REV_HOLD: 2720109998Smarkm /* Argument is an OID */ 2721109998Smarkm 2722109998Smarkm otmp = OBJ_txt2obj(rev_arg, 0); 2723109998Smarkm ASN1_OBJECT_free(otmp); 2724109998Smarkm 2725109998Smarkm if (otmp == NULL) 2726109998Smarkm { 2727109998Smarkm BIO_printf(bio_err, "Invalid object identifier %s\n", rev_arg); 2728109998Smarkm return NULL; 2729109998Smarkm } 2730109998Smarkm 2731109998Smarkm reason = "holdInstruction"; 2732109998Smarkm other = rev_arg; 2733109998Smarkm break; 2734109998Smarkm 2735109998Smarkm case REV_KEY_COMPROMISE: 2736109998Smarkm case REV_CA_COMPROMISE: 2737109998Smarkm 2738109998Smarkm /* Argument is the key compromise time */ 2739109998Smarkm if (!ASN1_GENERALIZEDTIME_set_string(NULL, rev_arg)) 2740109998Smarkm { 2741109998Smarkm BIO_printf(bio_err, "Invalid time format %s. Need YYYYMMDDHHMMSSZ\n", rev_arg); 2742109998Smarkm return NULL; 2743109998Smarkm } 2744109998Smarkm other = rev_arg; 2745109998Smarkm if (rev_type == REV_KEY_COMPROMISE) 2746109998Smarkm reason = "keyTime"; 2747109998Smarkm else 2748109998Smarkm reason = "CAkeyTime"; 2749109998Smarkm 2750109998Smarkm break; 2751109998Smarkm 2752109998Smarkm } 2753109998Smarkm 2754109998Smarkm revtm = X509_gmtime_adj(NULL, 0); 2755109998Smarkm 2756279265Sdelphij if (!revtm) 2757279265Sdelphij return NULL; 2758279265Sdelphij 2759109998Smarkm i = revtm->length + 1; 2760109998Smarkm 2761109998Smarkm if (reason) i += strlen(reason) + 1; 2762109998Smarkm if (other) i += strlen(other) + 1; 2763109998Smarkm 2764109998Smarkm str = OPENSSL_malloc(i); 2765109998Smarkm 2766109998Smarkm if (!str) return NULL; 2767109998Smarkm 2768127128Snectar BUF_strlcpy(str, (char *)revtm->data, i); 2769109998Smarkm if (reason) 2770109998Smarkm { 2771127128Snectar BUF_strlcat(str, ",", i); 2772127128Snectar BUF_strlcat(str, reason, i); 2773109998Smarkm } 2774109998Smarkm if (other) 2775109998Smarkm { 2776127128Snectar BUF_strlcat(str, ",", i); 2777127128Snectar BUF_strlcat(str, other, i); 2778109998Smarkm } 2779109998Smarkm ASN1_UTCTIME_free(revtm); 2780109998Smarkm return str; 2781109998Smarkm } 2782109998Smarkm 2783109998Smarkm/* Convert revocation field to X509_REVOKED entry 2784109998Smarkm * return code: 2785109998Smarkm * 0 error 2786109998Smarkm * 1 OK 2787109998Smarkm * 2 OK and some extensions added (i.e. V2 CRL) 2788109998Smarkm */ 2789109998Smarkm 2790109998Smarkm 2791160814Ssimonint make_revoked(X509_REVOKED *rev, const char *str) 2792109998Smarkm { 2793109998Smarkm char *tmp = NULL; 2794109998Smarkm int reason_code = -1; 2795109998Smarkm int i, ret = 0; 2796109998Smarkm ASN1_OBJECT *hold = NULL; 2797109998Smarkm ASN1_GENERALIZEDTIME *comp_time = NULL; 2798109998Smarkm ASN1_ENUMERATED *rtmp = NULL; 2799109998Smarkm 2800109998Smarkm ASN1_TIME *revDate = NULL; 2801109998Smarkm 2802109998Smarkm i = unpack_revinfo(&revDate, &reason_code, &hold, &comp_time, str); 2803109998Smarkm 2804109998Smarkm if (i == 0) 2805109998Smarkm goto err; 2806109998Smarkm 2807109998Smarkm if (rev && !X509_REVOKED_set_revocationDate(rev, revDate)) 2808109998Smarkm goto err; 2809109998Smarkm 2810109998Smarkm if (rev && (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)) 2811109998Smarkm { 2812109998Smarkm rtmp = ASN1_ENUMERATED_new(); 2813109998Smarkm if (!rtmp || !ASN1_ENUMERATED_set(rtmp, reason_code)) 2814109998Smarkm goto err; 2815109998Smarkm if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0)) 2816109998Smarkm goto err; 2817109998Smarkm } 2818109998Smarkm 2819109998Smarkm if (rev && comp_time) 2820109998Smarkm { 2821109998Smarkm if (!X509_REVOKED_add1_ext_i2d(rev, NID_invalidity_date, comp_time, 0, 0)) 2822109998Smarkm goto err; 2823109998Smarkm } 2824109998Smarkm if (rev && hold) 2825109998Smarkm { 2826109998Smarkm if (!X509_REVOKED_add1_ext_i2d(rev, NID_hold_instruction_code, hold, 0, 0)) 2827109998Smarkm goto err; 2828109998Smarkm } 2829109998Smarkm 2830109998Smarkm if (reason_code != OCSP_REVOKED_STATUS_NOSTATUS) 2831109998Smarkm ret = 2; 2832109998Smarkm else ret = 1; 2833109998Smarkm 2834109998Smarkm err: 2835109998Smarkm 2836109998Smarkm if (tmp) OPENSSL_free(tmp); 2837109998Smarkm ASN1_OBJECT_free(hold); 2838109998Smarkm ASN1_GENERALIZEDTIME_free(comp_time); 2839109998Smarkm ASN1_ENUMERATED_free(rtmp); 2840109998Smarkm ASN1_TIME_free(revDate); 2841109998Smarkm 2842109998Smarkm return ret; 2843109998Smarkm } 2844109998Smarkm 2845109998Smarkmint old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str) 2846109998Smarkm { 2847109998Smarkm char buf[25],*pbuf, *p; 2848109998Smarkm int j; 2849109998Smarkm j=i2a_ASN1_OBJECT(bp,obj); 2850109998Smarkm pbuf=buf; 2851109998Smarkm for (j=22-j; j>0; j--) 2852109998Smarkm *(pbuf++)=' '; 2853109998Smarkm *(pbuf++)=':'; 2854109998Smarkm *(pbuf++)='\0'; 2855109998Smarkm BIO_puts(bp,buf); 2856109998Smarkm 2857109998Smarkm if (str->type == V_ASN1_PRINTABLESTRING) 2858109998Smarkm BIO_printf(bp,"PRINTABLE:'"); 2859109998Smarkm else if (str->type == V_ASN1_T61STRING) 2860109998Smarkm BIO_printf(bp,"T61STRING:'"); 2861109998Smarkm else if (str->type == V_ASN1_IA5STRING) 2862109998Smarkm BIO_printf(bp,"IA5STRING:'"); 2863109998Smarkm else if (str->type == V_ASN1_UNIVERSALSTRING) 2864109998Smarkm BIO_printf(bp,"UNIVERSALSTRING:'"); 2865109998Smarkm else 2866109998Smarkm BIO_printf(bp,"ASN.1 %2d:'",str->type); 2867109998Smarkm 2868109998Smarkm p=(char *)str->data; 2869109998Smarkm for (j=str->length; j>0; j--) 2870109998Smarkm { 2871194206Ssimon#ifdef CHARSET_EBCDIC 2872194206Ssimon if ((*p >= 0x20) && (*p <= 0x7e)) 2873194206Ssimon BIO_printf(bp,"%c",os_toebcdic[*p]); 2874194206Ssimon#else 2875109998Smarkm if ((*p >= ' ') && (*p <= '~')) 2876109998Smarkm BIO_printf(bp,"%c",*p); 2877194206Ssimon#endif 2878109998Smarkm else if (*p & 0x80) 2879109998Smarkm BIO_printf(bp,"\\0x%02X",*p); 2880109998Smarkm else if ((unsigned char)*p == 0xf7) 2881109998Smarkm BIO_printf(bp,"^?"); 2882194206Ssimon#ifdef CHARSET_EBCDIC 2883194206Ssimon else BIO_printf(bp,"^%c",os_toebcdic[*p+0x40]); 2884194206Ssimon#else 2885109998Smarkm else BIO_printf(bp,"^%c",*p+'@'); 2886194206Ssimon#endif 2887109998Smarkm p++; 2888109998Smarkm } 2889109998Smarkm BIO_printf(bp,"'\n"); 2890109998Smarkm return 1; 2891109998Smarkm } 2892109998Smarkm 2893160814Ssimonint unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, ASN1_GENERALIZEDTIME **pinvtm, const char *str) 2894109998Smarkm { 2895109998Smarkm char *tmp = NULL; 2896109998Smarkm char *rtime_str, *reason_str = NULL, *arg_str = NULL, *p; 2897109998Smarkm int reason_code = -1; 2898160814Ssimon int ret = 0; 2899160814Ssimon unsigned int i; 2900109998Smarkm ASN1_OBJECT *hold = NULL; 2901109998Smarkm ASN1_GENERALIZEDTIME *comp_time = NULL; 2902109998Smarkm tmp = BUF_strdup(str); 2903109998Smarkm 2904109998Smarkm p = strchr(tmp, ','); 2905109998Smarkm 2906109998Smarkm rtime_str = tmp; 2907109998Smarkm 2908109998Smarkm if (p) 2909109998Smarkm { 2910109998Smarkm *p = '\0'; 2911109998Smarkm p++; 2912109998Smarkm reason_str = p; 2913109998Smarkm p = strchr(p, ','); 2914109998Smarkm if (p) 2915109998Smarkm { 2916109998Smarkm *p = '\0'; 2917109998Smarkm arg_str = p + 1; 2918109998Smarkm } 2919109998Smarkm } 2920109998Smarkm 2921109998Smarkm if (prevtm) 2922109998Smarkm { 2923109998Smarkm *prevtm = ASN1_UTCTIME_new(); 2924109998Smarkm if (!ASN1_UTCTIME_set_string(*prevtm, rtime_str)) 2925109998Smarkm { 2926109998Smarkm BIO_printf(bio_err, "invalid revocation date %s\n", rtime_str); 2927109998Smarkm goto err; 2928109998Smarkm } 2929109998Smarkm } 2930109998Smarkm if (reason_str) 2931109998Smarkm { 2932109998Smarkm for (i = 0; i < NUM_REASONS; i++) 2933109998Smarkm { 2934109998Smarkm if(!strcasecmp(reason_str, crl_reasons[i])) 2935109998Smarkm { 2936109998Smarkm reason_code = i; 2937109998Smarkm break; 2938109998Smarkm } 2939109998Smarkm } 2940109998Smarkm if (reason_code == OCSP_REVOKED_STATUS_NOSTATUS) 2941109998Smarkm { 2942109998Smarkm BIO_printf(bio_err, "invalid reason code %s\n", reason_str); 2943109998Smarkm goto err; 2944109998Smarkm } 2945109998Smarkm 2946109998Smarkm if (reason_code == 7) 2947109998Smarkm reason_code = OCSP_REVOKED_STATUS_REMOVEFROMCRL; 2948109998Smarkm else if (reason_code == 8) /* Hold instruction */ 2949109998Smarkm { 2950109998Smarkm if (!arg_str) 2951109998Smarkm { 2952109998Smarkm BIO_printf(bio_err, "missing hold instruction\n"); 2953109998Smarkm goto err; 2954109998Smarkm } 2955109998Smarkm reason_code = OCSP_REVOKED_STATUS_CERTIFICATEHOLD; 2956109998Smarkm hold = OBJ_txt2obj(arg_str, 0); 2957109998Smarkm 2958109998Smarkm if (!hold) 2959109998Smarkm { 2960109998Smarkm BIO_printf(bio_err, "invalid object identifier %s\n", arg_str); 2961109998Smarkm goto err; 2962109998Smarkm } 2963109998Smarkm if (phold) *phold = hold; 2964109998Smarkm } 2965109998Smarkm else if ((reason_code == 9) || (reason_code == 10)) 2966109998Smarkm { 2967109998Smarkm if (!arg_str) 2968109998Smarkm { 2969109998Smarkm BIO_printf(bio_err, "missing compromised time\n"); 2970109998Smarkm goto err; 2971109998Smarkm } 2972109998Smarkm comp_time = ASN1_GENERALIZEDTIME_new(); 2973109998Smarkm if (!ASN1_GENERALIZEDTIME_set_string(comp_time, arg_str)) 2974109998Smarkm { 2975109998Smarkm BIO_printf(bio_err, "invalid compromised time %s\n", arg_str); 2976109998Smarkm goto err; 2977109998Smarkm } 2978109998Smarkm if (reason_code == 9) 2979109998Smarkm reason_code = OCSP_REVOKED_STATUS_KEYCOMPROMISE; 2980109998Smarkm else 2981109998Smarkm reason_code = OCSP_REVOKED_STATUS_CACOMPROMISE; 2982109998Smarkm } 2983109998Smarkm } 2984109998Smarkm 2985109998Smarkm if (preason) *preason = reason_code; 2986109998Smarkm if (pinvtm) *pinvtm = comp_time; 2987109998Smarkm else ASN1_GENERALIZEDTIME_free(comp_time); 2988109998Smarkm 2989109998Smarkm ret = 1; 2990109998Smarkm 2991109998Smarkm err: 2992109998Smarkm 2993109998Smarkm if (tmp) OPENSSL_free(tmp); 2994109998Smarkm if (!phold) ASN1_OBJECT_free(hold); 2995109998Smarkm if (!pinvtm) ASN1_GENERALIZEDTIME_free(comp_time); 2996109998Smarkm 2997109998Smarkm return ret; 2998109998Smarkm } 2999