ca.c revision 55714
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> 6455714Skris#include <sys/types.h> 6555714Skris#include <sys/stat.h> 6655714Skris#include "apps.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> 7655714Skris#include <openssl/pem.h> 7755714Skris 7855714Skris#ifndef W_OK 7955714Skris# ifdef VMS 8055714Skris# if defined(__DECC) 8155714Skris# include <unistd.h> 8255714Skris# else 8355714Skris# include <unixlib.h> 8455714Skris# endif 8555714Skris# else 8655714Skris# include <sys/file.h> 8755714Skris# endif 8855714Skris#endif 8955714Skris 9055714Skris#ifndef W_OK 9155714Skris# define F_OK 0 9255714Skris# define X_OK 1 9355714Skris# define W_OK 2 9455714Skris# define R_OK 4 9555714Skris#endif 9655714Skris 9755714Skris#undef PROG 9855714Skris#define PROG ca_main 9955714Skris 10055714Skris#define BASE_SECTION "ca" 10155714Skris#define CONFIG_FILE "openssl.cnf" 10255714Skris 10355714Skris#define ENV_DEFAULT_CA "default_ca" 10455714Skris 10555714Skris#define ENV_DIR "dir" 10655714Skris#define ENV_CERTS "certs" 10755714Skris#define ENV_CRL_DIR "crl_dir" 10855714Skris#define ENV_CA_DB "CA_DB" 10955714Skris#define ENV_NEW_CERTS_DIR "new_certs_dir" 11055714Skris#define ENV_CERTIFICATE "certificate" 11155714Skris#define ENV_SERIAL "serial" 11255714Skris#define ENV_CRL "crl" 11355714Skris#define ENV_PRIVATE_KEY "private_key" 11455714Skris#define ENV_RANDFILE "RANDFILE" 11555714Skris#define ENV_DEFAULT_DAYS "default_days" 11655714Skris#define ENV_DEFAULT_STARTDATE "default_startdate" 11755714Skris#define ENV_DEFAULT_ENDDATE "default_enddate" 11855714Skris#define ENV_DEFAULT_CRL_DAYS "default_crl_days" 11955714Skris#define ENV_DEFAULT_CRL_HOURS "default_crl_hours" 12055714Skris#define ENV_DEFAULT_MD "default_md" 12155714Skris#define ENV_PRESERVE "preserve" 12255714Skris#define ENV_POLICY "policy" 12355714Skris#define ENV_EXTENSIONS "x509_extensions" 12455714Skris#define ENV_CRLEXT "crl_extensions" 12555714Skris#define ENV_MSIE_HACK "msie_hack" 12655714Skris 12755714Skris#define ENV_DATABASE "database" 12855714Skris 12955714Skris#define DB_type 0 13055714Skris#define DB_exp_date 1 13155714Skris#define DB_rev_date 2 13255714Skris#define DB_serial 3 /* index - unique */ 13355714Skris#define DB_file 4 13455714Skris#define DB_name 5 /* index - unique for active */ 13555714Skris#define DB_NUMBER 6 13655714Skris 13755714Skris#define DB_TYPE_REV 'R' 13855714Skris#define DB_TYPE_EXP 'E' 13955714Skris#define DB_TYPE_VAL 'V' 14055714Skris 14155714Skrisstatic char *ca_usage[]={ 14255714Skris"usage: ca args\n", 14355714Skris"\n", 14455714Skris" -verbose - Talk alot while doing things\n", 14555714Skris" -config file - A config file\n", 14655714Skris" -name arg - The particular CA definition to use\n", 14755714Skris" -gencrl - Generate a new CRL\n", 14855714Skris" -crldays days - Days is when the next CRL is due\n", 14955714Skris" -crlhours hours - Hours is when the next CRL is due\n", 15055714Skris" -days arg - number of days to certify the certificate for\n", 15155714Skris" -md arg - md to use, one of md2, md5, sha or sha1\n", 15255714Skris" -policy arg - The CA 'policy' to support\n", 15355714Skris" -keyfile arg - PEM private key file\n", 15455714Skris" -key arg - key to decode the private key if it is encrypted\n", 15555714Skris" -cert file - The CA certificate\n", 15655714Skris" -in file - The input PEM encoded certificate request(s)\n", 15755714Skris" -out file - Where to put the output file(s)\n", 15855714Skris" -outdir dir - Where to put output certificates\n", 15955714Skris" -infiles .... - The last argument, requests to process\n", 16055714Skris" -spkac file - File contains DN and signed public key and challenge\n", 16155714Skris" -ss_cert file - File contains a self signed cert to sign\n", 16255714Skris" -preserveDN - Don't re-order the DN\n", 16355714Skris" -batch - Don't ask questions\n", 16455714Skris" -msie_hack - msie modifications to handle all those universal strings\n", 16555714Skris" -revoke file - Revoke a certificate (given in file)\n", 16655714SkrisNULL 16755714Skris}; 16855714Skris 16955714Skris#ifdef EFENCE 17055714Skrisextern int EF_PROTECT_FREE; 17155714Skrisextern int EF_PROTECT_BELOW; 17255714Skrisextern int EF_ALIGNMENT; 17355714Skris#endif 17455714Skris 17555714Skrisstatic int add_oid_section(LHASH *conf); 17655714Skrisstatic void lookup_fail(char *name,char *tag); 17755714Skrisstatic int MS_CALLBACK key_callback(char *buf,int len,int verify,void *u); 17855714Skrisstatic unsigned long index_serial_hash(char **a); 17955714Skrisstatic int index_serial_cmp(char **a, char **b); 18055714Skrisstatic unsigned long index_name_hash(char **a); 18155714Skrisstatic int index_name_qual(char **a); 18255714Skrisstatic int index_name_cmp(char **a,char **b); 18355714Skrisstatic BIGNUM *load_serial(char *serialfile); 18455714Skrisstatic int save_serial(char *serialfile, BIGNUM *serial); 18555714Skrisstatic int certify(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509, 18655714Skris const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,TXT_DB *db, 18755714Skris BIGNUM *serial, char *startdate,char *enddate, int days, 18855714Skris int batch, char *ext_sect, LHASH *conf,int verbose); 18955714Skrisstatic int certify_cert(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509, 19055714Skris const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy, 19155714Skris TXT_DB *db, BIGNUM *serial,char *startdate, 19255714Skris char *enddate, int days, int batch, char *ext_sect, 19355714Skris LHASH *conf,int verbose); 19455714Skrisstatic int certify_spkac(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509, 19555714Skris const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy, 19655714Skris TXT_DB *db, BIGNUM *serial,char *startdate, 19755714Skris char *enddate, int days, char *ext_sect,LHASH *conf, 19855714Skris int verbose); 19955714Skrisstatic int fix_data(int nid, int *type); 20055714Skrisstatic void write_new_certificate(BIO *bp, X509 *x, int output_der); 20155714Skrisstatic int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, 20255714Skris STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial, 20355714Skris char *startdate, char *enddate, int days, int batch, int verbose, 20455714Skris X509_REQ *req, char *ext_sect, LHASH *conf); 20555714Skrisstatic int do_revoke(X509 *x509, TXT_DB *db); 20655714Skrisstatic int check_time_format(char *str); 20755714Skrisstatic LHASH *conf; 20855714Skrisstatic char *key=NULL; 20955714Skrisstatic char *section=NULL; 21055714Skris 21155714Skrisstatic int preserve=0; 21255714Skrisstatic int msie_hack=0; 21355714Skris 21455714Skrisint MAIN(int argc, char **argv) 21555714Skris { 21655714Skris int total=0; 21755714Skris int total_done=0; 21855714Skris int badops=0; 21955714Skris int ret=1; 22055714Skris int req=0; 22155714Skris int verbose=0; 22255714Skris int gencrl=0; 22355714Skris int dorevoke=0; 22455714Skris long crldays=0; 22555714Skris long crlhours=0; 22655714Skris long errorline= -1; 22755714Skris char *configfile=NULL; 22855714Skris char *md=NULL; 22955714Skris char *policy=NULL; 23055714Skris char *keyfile=NULL; 23155714Skris char *certfile=NULL; 23255714Skris char *infile=NULL; 23355714Skris char *spkac_file=NULL; 23455714Skris char *ss_cert_file=NULL; 23555714Skris EVP_PKEY *pkey=NULL; 23655714Skris int output_der = 0; 23755714Skris char *outfile=NULL; 23855714Skris char *outdir=NULL; 23955714Skris char *serialfile=NULL; 24055714Skris char *extensions=NULL; 24155714Skris char *crl_ext=NULL; 24255714Skris BIGNUM *serial=NULL; 24355714Skris char *startdate=NULL; 24455714Skris char *enddate=NULL; 24555714Skris int days=0; 24655714Skris int batch=0; 24755714Skris X509 *x509=NULL; 24855714Skris X509 *x=NULL; 24955714Skris BIO *in=NULL,*out=NULL,*Sout=NULL,*Cout=NULL; 25055714Skris char *dbfile=NULL; 25155714Skris TXT_DB *db=NULL; 25255714Skris X509_CRL *crl=NULL; 25355714Skris X509_CRL_INFO *ci=NULL; 25455714Skris X509_REVOKED *r=NULL; 25555714Skris char **pp,*p,*f; 25655714Skris int i,j; 25755714Skris long l; 25855714Skris const EVP_MD *dgst=NULL; 25955714Skris STACK_OF(CONF_VALUE) *attribs=NULL; 26055714Skris STACK *cert_sk=NULL; 26155714Skris BIO *hex=NULL; 26255714Skris#undef BSIZE 26355714Skris#define BSIZE 256 26455714Skris MS_STATIC char buf[3][BSIZE]; 26555714Skris 26655714Skris#ifdef EFENCE 26755714SkrisEF_PROTECT_FREE=1; 26855714SkrisEF_PROTECT_BELOW=1; 26955714SkrisEF_ALIGNMENT=0; 27055714Skris#endif 27155714Skris 27255714Skris apps_startup(); 27355714Skris 27455714Skris X509V3_add_standard_extensions(); 27555714Skris 27655714Skris preserve=0; 27755714Skris if (bio_err == NULL) 27855714Skris if ((bio_err=BIO_new(BIO_s_file())) != NULL) 27955714Skris BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT); 28055714Skris 28155714Skris argc--; 28255714Skris argv++; 28355714Skris while (argc >= 1) 28455714Skris { 28555714Skris if (strcmp(*argv,"-verbose") == 0) 28655714Skris verbose=1; 28755714Skris else if (strcmp(*argv,"-config") == 0) 28855714Skris { 28955714Skris if (--argc < 1) goto bad; 29055714Skris configfile= *(++argv); 29155714Skris } 29255714Skris else if (strcmp(*argv,"-name") == 0) 29355714Skris { 29455714Skris if (--argc < 1) goto bad; 29555714Skris section= *(++argv); 29655714Skris } 29755714Skris else if (strcmp(*argv,"-startdate") == 0) 29855714Skris { 29955714Skris if (--argc < 1) goto bad; 30055714Skris startdate= *(++argv); 30155714Skris } 30255714Skris else if (strcmp(*argv,"-enddate") == 0) 30355714Skris { 30455714Skris if (--argc < 1) goto bad; 30555714Skris enddate= *(++argv); 30655714Skris } 30755714Skris else if (strcmp(*argv,"-days") == 0) 30855714Skris { 30955714Skris if (--argc < 1) goto bad; 31055714Skris days=atoi(*(++argv)); 31155714Skris } 31255714Skris else if (strcmp(*argv,"-md") == 0) 31355714Skris { 31455714Skris if (--argc < 1) goto bad; 31555714Skris md= *(++argv); 31655714Skris } 31755714Skris else if (strcmp(*argv,"-policy") == 0) 31855714Skris { 31955714Skris if (--argc < 1) goto bad; 32055714Skris policy= *(++argv); 32155714Skris } 32255714Skris else if (strcmp(*argv,"-keyfile") == 0) 32355714Skris { 32455714Skris if (--argc < 1) goto bad; 32555714Skris keyfile= *(++argv); 32655714Skris } 32755714Skris else if (strcmp(*argv,"-key") == 0) 32855714Skris { 32955714Skris if (--argc < 1) goto bad; 33055714Skris key= *(++argv); 33155714Skris } 33255714Skris else if (strcmp(*argv,"-cert") == 0) 33355714Skris { 33455714Skris if (--argc < 1) goto bad; 33555714Skris certfile= *(++argv); 33655714Skris } 33755714Skris else if (strcmp(*argv,"-in") == 0) 33855714Skris { 33955714Skris if (--argc < 1) goto bad; 34055714Skris infile= *(++argv); 34155714Skris req=1; 34255714Skris } 34355714Skris else if (strcmp(*argv,"-out") == 0) 34455714Skris { 34555714Skris if (--argc < 1) goto bad; 34655714Skris outfile= *(++argv); 34755714Skris } 34855714Skris else if (strcmp(*argv,"-outdir") == 0) 34955714Skris { 35055714Skris if (--argc < 1) goto bad; 35155714Skris outdir= *(++argv); 35255714Skris } 35355714Skris else if (strcmp(*argv,"-batch") == 0) 35455714Skris batch=1; 35555714Skris else if (strcmp(*argv,"-preserveDN") == 0) 35655714Skris preserve=1; 35755714Skris else if (strcmp(*argv,"-gencrl") == 0) 35855714Skris gencrl=1; 35955714Skris else if (strcmp(*argv,"-msie_hack") == 0) 36055714Skris msie_hack=1; 36155714Skris else if (strcmp(*argv,"-crldays") == 0) 36255714Skris { 36355714Skris if (--argc < 1) goto bad; 36455714Skris crldays= atol(*(++argv)); 36555714Skris } 36655714Skris else if (strcmp(*argv,"-crlhours") == 0) 36755714Skris { 36855714Skris if (--argc < 1) goto bad; 36955714Skris crlhours= atol(*(++argv)); 37055714Skris } 37155714Skris else if (strcmp(*argv,"-infiles") == 0) 37255714Skris { 37355714Skris argc--; 37455714Skris argv++; 37555714Skris req=1; 37655714Skris break; 37755714Skris } 37855714Skris else if (strcmp(*argv, "-ss_cert") == 0) 37955714Skris { 38055714Skris if (--argc < 1) goto bad; 38155714Skris ss_cert_file = *(++argv); 38255714Skris req=1; 38355714Skris } 38455714Skris else if (strcmp(*argv, "-spkac") == 0) 38555714Skris { 38655714Skris if (--argc < 1) goto bad; 38755714Skris spkac_file = *(++argv); 38855714Skris req=1; 38955714Skris } 39055714Skris else if (strcmp(*argv,"-revoke") == 0) 39155714Skris { 39255714Skris if (--argc < 1) goto bad; 39355714Skris infile= *(++argv); 39455714Skris dorevoke=1; 39555714Skris } 39655714Skris else 39755714Skris { 39855714Skrisbad: 39955714Skris BIO_printf(bio_err,"unknown option %s\n",*argv); 40055714Skris badops=1; 40155714Skris break; 40255714Skris } 40355714Skris argc--; 40455714Skris argv++; 40555714Skris } 40655714Skris 40755714Skris if (badops) 40855714Skris { 40955714Skris for (pp=ca_usage; (*pp != NULL); pp++) 41055714Skris BIO_printf(bio_err,*pp); 41155714Skris goto err; 41255714Skris } 41355714Skris 41455714Skris ERR_load_crypto_strings(); 41555714Skris 41655714Skris /*****************************************************************/ 41755714Skris if (configfile == NULL) configfile = getenv("OPENSSL_CONF"); 41855714Skris if (configfile == NULL) configfile = getenv("SSLEAY_CONF"); 41955714Skris if (configfile == NULL) 42055714Skris { 42155714Skris /* We will just use 'buf[0]' as a temporary buffer. */ 42255714Skris#ifdef VMS 42355714Skris strncpy(buf[0],X509_get_default_cert_area(), 42455714Skris sizeof(buf[0])-1-sizeof(CONFIG_FILE)); 42555714Skris#else 42655714Skris strncpy(buf[0],X509_get_default_cert_area(), 42755714Skris sizeof(buf[0])-2-sizeof(CONFIG_FILE)); 42855714Skris strcat(buf[0],"/"); 42955714Skris#endif 43055714Skris strcat(buf[0],CONFIG_FILE); 43155714Skris configfile=buf[0]; 43255714Skris } 43355714Skris 43455714Skris BIO_printf(bio_err,"Using configuration from %s\n",configfile); 43555714Skris if ((conf=CONF_load(NULL,configfile,&errorline)) == NULL) 43655714Skris { 43755714Skris if (errorline <= 0) 43855714Skris BIO_printf(bio_err,"error loading the config file '%s'\n", 43955714Skris configfile); 44055714Skris else 44155714Skris BIO_printf(bio_err,"error on line %ld of config file '%s'\n" 44255714Skris ,errorline,configfile); 44355714Skris goto err; 44455714Skris } 44555714Skris 44655714Skris /* Lets get the config section we are using */ 44755714Skris if (section == NULL) 44855714Skris { 44955714Skris section=CONF_get_string(conf,BASE_SECTION,ENV_DEFAULT_CA); 45055714Skris if (section == NULL) 45155714Skris { 45255714Skris lookup_fail(BASE_SECTION,ENV_DEFAULT_CA); 45355714Skris goto err; 45455714Skris } 45555714Skris } 45655714Skris 45755714Skris if (conf != NULL) 45855714Skris { 45955714Skris p=CONF_get_string(conf,NULL,"oid_file"); 46055714Skris if (p != NULL) 46155714Skris { 46255714Skris BIO *oid_bio; 46355714Skris 46455714Skris oid_bio=BIO_new_file(p,"r"); 46555714Skris if (oid_bio == NULL) 46655714Skris { 46755714Skris /* 46855714Skris BIO_printf(bio_err,"problems opening %s for extra oid's\n",p); 46955714Skris ERR_print_errors(bio_err); 47055714Skris */ 47155714Skris ERR_clear_error(); 47255714Skris } 47355714Skris else 47455714Skris { 47555714Skris OBJ_create_objects(oid_bio); 47655714Skris BIO_free(oid_bio); 47755714Skris } 47855714Skris } 47955714Skris } 48055714Skris if(!add_oid_section(conf)) { 48155714Skris ERR_print_errors(bio_err); 48255714Skris goto err; 48355714Skris } 48455714Skris 48555714Skris in=BIO_new(BIO_s_file()); 48655714Skris out=BIO_new(BIO_s_file()); 48755714Skris Sout=BIO_new(BIO_s_file()); 48855714Skris Cout=BIO_new(BIO_s_file()); 48955714Skris if ((in == NULL) || (out == NULL) || (Sout == NULL) || (Cout == NULL)) 49055714Skris { 49155714Skris ERR_print_errors(bio_err); 49255714Skris goto err; 49355714Skris } 49455714Skris 49555714Skris /*****************************************************************/ 49655714Skris /* we definitly need an public key, so lets get it */ 49755714Skris 49855714Skris if ((keyfile == NULL) && ((keyfile=CONF_get_string(conf, 49955714Skris section,ENV_PRIVATE_KEY)) == NULL)) 50055714Skris { 50155714Skris lookup_fail(section,ENV_PRIVATE_KEY); 50255714Skris goto err; 50355714Skris } 50455714Skris if (BIO_read_filename(in,keyfile) <= 0) 50555714Skris { 50655714Skris perror(keyfile); 50755714Skris BIO_printf(bio_err,"trying to load CA private key\n"); 50855714Skris goto err; 50955714Skris } 51055714Skris if (key == NULL) 51155714Skris pkey=PEM_read_bio_PrivateKey(in,NULL,NULL,NULL); 51255714Skris else 51355714Skris { 51455714Skris pkey=PEM_read_bio_PrivateKey(in,NULL,key_callback,NULL); 51555714Skris memset(key,0,strlen(key)); 51655714Skris } 51755714Skris if (pkey == NULL) 51855714Skris { 51955714Skris BIO_printf(bio_err,"unable to load CA private key\n"); 52055714Skris goto err; 52155714Skris } 52255714Skris 52355714Skris /*****************************************************************/ 52455714Skris /* we need a certificate */ 52555714Skris if ((certfile == NULL) && ((certfile=CONF_get_string(conf, 52655714Skris section,ENV_CERTIFICATE)) == NULL)) 52755714Skris { 52855714Skris lookup_fail(section,ENV_CERTIFICATE); 52955714Skris goto err; 53055714Skris } 53155714Skris if (BIO_read_filename(in,certfile) <= 0) 53255714Skris { 53355714Skris perror(certfile); 53455714Skris BIO_printf(bio_err,"trying to load CA certificate\n"); 53555714Skris goto err; 53655714Skris } 53755714Skris x509=PEM_read_bio_X509(in,NULL,NULL,NULL); 53855714Skris if (x509 == NULL) 53955714Skris { 54055714Skris BIO_printf(bio_err,"unable to load CA certificate\n"); 54155714Skris goto err; 54255714Skris } 54355714Skris 54455714Skris if (!X509_check_private_key(x509,pkey)) 54555714Skris { 54655714Skris BIO_printf(bio_err,"CA certificate and CA private key do not match\n"); 54755714Skris goto err; 54855714Skris } 54955714Skris 55055714Skris f=CONF_get_string(conf,BASE_SECTION,ENV_PRESERVE); 55155714Skris if ((f != NULL) && ((*f == 'y') || (*f == 'Y'))) 55255714Skris preserve=1; 55355714Skris f=CONF_get_string(conf,BASE_SECTION,ENV_MSIE_HACK); 55455714Skris if ((f != NULL) && ((*f == 'y') || (*f == 'Y'))) 55555714Skris msie_hack=1; 55655714Skris 55755714Skris /*****************************************************************/ 55855714Skris /* lookup where to write new certificates */ 55955714Skris if ((outdir == NULL) && (req)) 56055714Skris { 56155714Skris struct stat sb; 56255714Skris 56355714Skris if ((outdir=CONF_get_string(conf,section,ENV_NEW_CERTS_DIR)) 56455714Skris == NULL) 56555714Skris { 56655714Skris BIO_printf(bio_err,"there needs to be defined a directory for new certificate to be placed in\n"); 56755714Skris goto err; 56855714Skris } 56955714Skris#ifdef VMS 57055714Skris /* For technical reasons, VMS misbehaves with X_OK */ 57155714Skris if (access(outdir,R_OK|W_OK) != 0) 57255714Skris#else 57355714Skris if (access(outdir,R_OK|W_OK|X_OK) != 0) 57455714Skris#endif 57555714Skris { 57655714Skris BIO_printf(bio_err,"I am unable to acces the %s directory\n",outdir); 57755714Skris perror(outdir); 57855714Skris goto err; 57955714Skris } 58055714Skris 58155714Skris if (stat(outdir,&sb) != 0) 58255714Skris { 58355714Skris BIO_printf(bio_err,"unable to stat(%s)\n",outdir); 58455714Skris perror(outdir); 58555714Skris goto err; 58655714Skris } 58755714Skris if (!(sb.st_mode & S_IFDIR)) 58855714Skris { 58955714Skris BIO_printf(bio_err,"%s need to be a directory\n",outdir); 59055714Skris perror(outdir); 59155714Skris goto err; 59255714Skris } 59355714Skris } 59455714Skris 59555714Skris /*****************************************************************/ 59655714Skris /* we need to load the database file */ 59755714Skris if ((dbfile=CONF_get_string(conf,section,ENV_DATABASE)) == NULL) 59855714Skris { 59955714Skris lookup_fail(section,ENV_DATABASE); 60055714Skris goto err; 60155714Skris } 60255714Skris if (BIO_read_filename(in,dbfile) <= 0) 60355714Skris { 60455714Skris perror(dbfile); 60555714Skris BIO_printf(bio_err,"unable to open '%s'\n",dbfile); 60655714Skris goto err; 60755714Skris } 60855714Skris db=TXT_DB_read(in,DB_NUMBER); 60955714Skris if (db == NULL) goto err; 61055714Skris 61155714Skris /* Lets check some fields */ 61255714Skris for (i=0; i<sk_num(db->data); i++) 61355714Skris { 61455714Skris pp=(char **)sk_value(db->data,i); 61555714Skris if ((pp[DB_type][0] != DB_TYPE_REV) && 61655714Skris (pp[DB_rev_date][0] != '\0')) 61755714Skris { 61855714Skris BIO_printf(bio_err,"entry %d: not revoked yet, but has a revocation date\n",i+1); 61955714Skris goto err; 62055714Skris } 62155714Skris if ((pp[DB_type][0] == DB_TYPE_REV) && 62255714Skris !check_time_format(pp[DB_rev_date])) 62355714Skris { 62455714Skris BIO_printf(bio_err,"entry %d: invalid revocation date\n", 62555714Skris i+1); 62655714Skris goto err; 62755714Skris } 62855714Skris if (!check_time_format(pp[DB_exp_date])) 62955714Skris { 63055714Skris BIO_printf(bio_err,"entry %d: invalid expiry date\n",i+1); 63155714Skris goto err; 63255714Skris } 63355714Skris p=pp[DB_serial]; 63455714Skris j=strlen(p); 63555714Skris if ((j&1) || (j < 2)) 63655714Skris { 63755714Skris BIO_printf(bio_err,"entry %d: bad serial number length (%d)\n",i+1,j); 63855714Skris goto err; 63955714Skris } 64055714Skris while (*p) 64155714Skris { 64255714Skris if (!( ((*p >= '0') && (*p <= '9')) || 64355714Skris ((*p >= 'A') && (*p <= 'F')) || 64455714Skris ((*p >= 'a') && (*p <= 'f'))) ) 64555714Skris { 64655714Skris 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); 64755714Skris goto err; 64855714Skris } 64955714Skris p++; 65055714Skris } 65155714Skris } 65255714Skris if (verbose) 65355714Skris { 65455714Skris BIO_set_fp(out,stdout,BIO_NOCLOSE|BIO_FP_TEXT); /* cannot fail */ 65555714Skris TXT_DB_write(out,db); 65655714Skris BIO_printf(bio_err,"%d entries loaded from the database\n", 65755714Skris db->data->num); 65855714Skris BIO_printf(bio_err,"generating indexs\n"); 65955714Skris } 66055714Skris 66155714Skris if (!TXT_DB_create_index(db,DB_serial,NULL,index_serial_hash, 66255714Skris index_serial_cmp)) 66355714Skris { 66455714Skris BIO_printf(bio_err,"error creating serial number index:(%ld,%ld,%ld)\n",db->error,db->arg1,db->arg2); 66555714Skris goto err; 66655714Skris } 66755714Skris 66855714Skris if (!TXT_DB_create_index(db,DB_name,index_name_qual,index_name_hash, 66955714Skris index_name_cmp)) 67055714Skris { 67155714Skris BIO_printf(bio_err,"error creating name index:(%ld,%ld,%ld)\n", 67255714Skris db->error,db->arg1,db->arg2); 67355714Skris goto err; 67455714Skris } 67555714Skris 67655714Skris /*****************************************************************/ 67755714Skris if (req || gencrl) 67855714Skris { 67955714Skris if (outfile != NULL) 68055714Skris { 68155714Skris 68255714Skris if (BIO_write_filename(Sout,outfile) <= 0) 68355714Skris { 68455714Skris perror(outfile); 68555714Skris goto err; 68655714Skris } 68755714Skris } 68855714Skris else 68955714Skris BIO_set_fp(Sout,stdout,BIO_NOCLOSE|BIO_FP_TEXT); 69055714Skris } 69155714Skris 69255714Skris if (req) 69355714Skris { 69455714Skris if ((md == NULL) && ((md=CONF_get_string(conf, 69555714Skris section,ENV_DEFAULT_MD)) == NULL)) 69655714Skris { 69755714Skris lookup_fail(section,ENV_DEFAULT_MD); 69855714Skris goto err; 69955714Skris } 70055714Skris if ((dgst=EVP_get_digestbyname(md)) == NULL) 70155714Skris { 70255714Skris BIO_printf(bio_err,"%s is an unsupported message digest type\n",md); 70355714Skris goto err; 70455714Skris } 70555714Skris if (verbose) 70655714Skris BIO_printf(bio_err,"message digest is %s\n", 70755714Skris OBJ_nid2ln(dgst->type)); 70855714Skris if ((policy == NULL) && ((policy=CONF_get_string(conf, 70955714Skris section,ENV_POLICY)) == NULL)) 71055714Skris { 71155714Skris lookup_fail(section,ENV_POLICY); 71255714Skris goto err; 71355714Skris } 71455714Skris if (verbose) 71555714Skris BIO_printf(bio_err,"policy is %s\n",policy); 71655714Skris 71755714Skris if ((serialfile=CONF_get_string(conf,section,ENV_SERIAL)) 71855714Skris == NULL) 71955714Skris { 72055714Skris lookup_fail(section,ENV_SERIAL); 72155714Skris goto err; 72255714Skris } 72355714Skris 72455714Skris extensions=CONF_get_string(conf,section,ENV_EXTENSIONS); 72555714Skris if(extensions) { 72655714Skris /* Check syntax of file */ 72755714Skris X509V3_CTX ctx; 72855714Skris X509V3_set_ctx_test(&ctx); 72955714Skris X509V3_set_conf_lhash(&ctx, conf); 73055714Skris if(!X509V3_EXT_add_conf(conf, &ctx, extensions, NULL)) { 73155714Skris BIO_printf(bio_err, 73255714Skris "Error Loading extension section %s\n", 73355714Skris extensions); 73455714Skris ret = 1; 73555714Skris goto err; 73655714Skris } 73755714Skris } 73855714Skris 73955714Skris if (startdate == NULL) 74055714Skris { 74155714Skris startdate=CONF_get_string(conf,section, 74255714Skris ENV_DEFAULT_STARTDATE); 74355714Skris } 74455714Skris if (startdate && !ASN1_UTCTIME_set_string(NULL,startdate)) 74555714Skris { 74655714Skris BIO_printf(bio_err,"start date is invalid, it should be YYMMDDHHMMSSZ\n"); 74755714Skris goto err; 74855714Skris } 74955714Skris if (startdate == NULL) startdate="today"; 75055714Skris 75155714Skris if (enddate == NULL) 75255714Skris { 75355714Skris enddate=CONF_get_string(conf,section, 75455714Skris ENV_DEFAULT_ENDDATE); 75555714Skris } 75655714Skris if (enddate && !ASN1_UTCTIME_set_string(NULL,enddate)) 75755714Skris { 75855714Skris BIO_printf(bio_err,"end date is invalid, it should be YYMMDDHHMMSSZ\n"); 75955714Skris goto err; 76055714Skris } 76155714Skris 76255714Skris if (days == 0) 76355714Skris { 76455714Skris days=(int)CONF_get_number(conf,section, 76555714Skris ENV_DEFAULT_DAYS); 76655714Skris } 76755714Skris if (!enddate && (days == 0)) 76855714Skris { 76955714Skris BIO_printf(bio_err,"cannot lookup how many days to certify for\n"); 77055714Skris goto err; 77155714Skris } 77255714Skris 77355714Skris if ((serial=load_serial(serialfile)) == NULL) 77455714Skris { 77555714Skris BIO_printf(bio_err,"error while loading serial number\n"); 77655714Skris goto err; 77755714Skris } 77855714Skris if (verbose) 77955714Skris { 78055714Skris if ((f=BN_bn2hex(serial)) == NULL) goto err; 78155714Skris BIO_printf(bio_err,"next serial number is %s\n",f); 78255714Skris Free(f); 78355714Skris } 78455714Skris 78555714Skris if ((attribs=CONF_get_section(conf,policy)) == NULL) 78655714Skris { 78755714Skris BIO_printf(bio_err,"unable to find 'section' for %s\n",policy); 78855714Skris goto err; 78955714Skris } 79055714Skris 79155714Skris if ((cert_sk=sk_new_null()) == NULL) 79255714Skris { 79355714Skris BIO_printf(bio_err,"Malloc failure\n"); 79455714Skris goto err; 79555714Skris } 79655714Skris if (spkac_file != NULL) 79755714Skris { 79855714Skris total++; 79955714Skris j=certify_spkac(&x,spkac_file,pkey,x509,dgst,attribs,db, 80055714Skris serial,startdate,enddate, days,extensions,conf, 80155714Skris verbose); 80255714Skris if (j < 0) goto err; 80355714Skris if (j > 0) 80455714Skris { 80555714Skris total_done++; 80655714Skris BIO_printf(bio_err,"\n"); 80755714Skris if (!BN_add_word(serial,1)) goto err; 80855714Skris if (!sk_push(cert_sk,(char *)x)) 80955714Skris { 81055714Skris BIO_printf(bio_err,"Malloc failure\n"); 81155714Skris goto err; 81255714Skris } 81355714Skris if (outfile) 81455714Skris { 81555714Skris output_der = 1; 81655714Skris batch = 1; 81755714Skris } 81855714Skris } 81955714Skris } 82055714Skris if (ss_cert_file != NULL) 82155714Skris { 82255714Skris total++; 82355714Skris j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,attribs, 82455714Skris db,serial,startdate,enddate,days,batch, 82555714Skris extensions,conf,verbose); 82655714Skris if (j < 0) goto err; 82755714Skris if (j > 0) 82855714Skris { 82955714Skris total_done++; 83055714Skris BIO_printf(bio_err,"\n"); 83155714Skris if (!BN_add_word(serial,1)) goto err; 83255714Skris if (!sk_push(cert_sk,(char *)x)) 83355714Skris { 83455714Skris BIO_printf(bio_err,"Malloc failure\n"); 83555714Skris goto err; 83655714Skris } 83755714Skris } 83855714Skris } 83955714Skris if (infile != NULL) 84055714Skris { 84155714Skris total++; 84255714Skris j=certify(&x,infile,pkey,x509,dgst,attribs,db, 84355714Skris serial,startdate,enddate,days,batch, 84455714Skris extensions,conf,verbose); 84555714Skris if (j < 0) goto err; 84655714Skris if (j > 0) 84755714Skris { 84855714Skris total_done++; 84955714Skris BIO_printf(bio_err,"\n"); 85055714Skris if (!BN_add_word(serial,1)) goto err; 85155714Skris if (!sk_push(cert_sk,(char *)x)) 85255714Skris { 85355714Skris BIO_printf(bio_err,"Malloc failure\n"); 85455714Skris goto err; 85555714Skris } 85655714Skris } 85755714Skris } 85855714Skris for (i=0; i<argc; i++) 85955714Skris { 86055714Skris total++; 86155714Skris j=certify(&x,argv[i],pkey,x509,dgst,attribs,db, 86255714Skris serial,startdate,enddate,days,batch, 86355714Skris extensions,conf,verbose); 86455714Skris if (j < 0) goto err; 86555714Skris if (j > 0) 86655714Skris { 86755714Skris total_done++; 86855714Skris BIO_printf(bio_err,"\n"); 86955714Skris if (!BN_add_word(serial,1)) goto err; 87055714Skris if (!sk_push(cert_sk,(char *)x)) 87155714Skris { 87255714Skris BIO_printf(bio_err,"Malloc failure\n"); 87355714Skris goto err; 87455714Skris } 87555714Skris } 87655714Skris } 87755714Skris /* we have a stack of newly certified certificates 87855714Skris * and a data base and serial number that need 87955714Skris * updating */ 88055714Skris 88155714Skris if (sk_num(cert_sk) > 0) 88255714Skris { 88355714Skris if (!batch) 88455714Skris { 88555714Skris BIO_printf(bio_err,"\n%d out of %d certificate requests certified, commit? [y/n]",total_done,total); 88655714Skris (void)BIO_flush(bio_err); 88755714Skris buf[0][0]='\0'; 88855714Skris fgets(buf[0],10,stdin); 88955714Skris if ((buf[0][0] != 'y') && (buf[0][0] != 'Y')) 89055714Skris { 89155714Skris BIO_printf(bio_err,"CERTIFICATION CANCELED\n"); 89255714Skris ret=0; 89355714Skris goto err; 89455714Skris } 89555714Skris } 89655714Skris 89755714Skris BIO_printf(bio_err,"Write out database with %d new entries\n",sk_num(cert_sk)); 89855714Skris 89955714Skris strncpy(buf[0],serialfile,BSIZE-4); 90055714Skris 90155714Skris#ifdef VMS 90255714Skris strcat(buf[0],"-new"); 90355714Skris#else 90455714Skris strcat(buf[0],".new"); 90555714Skris#endif 90655714Skris 90755714Skris if (!save_serial(buf[0],serial)) goto err; 90855714Skris 90955714Skris strncpy(buf[1],dbfile,BSIZE-4); 91055714Skris 91155714Skris#ifdef VMS 91255714Skris strcat(buf[1],"-new"); 91355714Skris#else 91455714Skris strcat(buf[1],".new"); 91555714Skris#endif 91655714Skris 91755714Skris if (BIO_write_filename(out,buf[1]) <= 0) 91855714Skris { 91955714Skris perror(dbfile); 92055714Skris BIO_printf(bio_err,"unable to open '%s'\n",dbfile); 92155714Skris goto err; 92255714Skris } 92355714Skris l=TXT_DB_write(out,db); 92455714Skris if (l <= 0) goto err; 92555714Skris } 92655714Skris 92755714Skris if (verbose) 92855714Skris BIO_printf(bio_err,"writing new certificates\n"); 92955714Skris for (i=0; i<sk_num(cert_sk); i++) 93055714Skris { 93155714Skris int k; 93255714Skris unsigned char *n; 93355714Skris 93455714Skris x=(X509 *)sk_value(cert_sk,i); 93555714Skris 93655714Skris j=x->cert_info->serialNumber->length; 93755714Skris p=(char *)x->cert_info->serialNumber->data; 93855714Skris 93955714Skris strncpy(buf[2],outdir,BSIZE-(j*2)-6); 94055714Skris 94155714Skris#ifndef VMS 94255714Skris strcat(buf[2],"/"); 94355714Skris#endif 94455714Skris 94555714Skris n=(unsigned char *)&(buf[2][strlen(buf[2])]); 94655714Skris if (j > 0) 94755714Skris { 94855714Skris for (k=0; k<j; k++) 94955714Skris { 95055714Skris sprintf((char *)n,"%02X",(unsigned char)*(p++)); 95155714Skris n+=2; 95255714Skris } 95355714Skris } 95455714Skris else 95555714Skris { 95655714Skris *(n++)='0'; 95755714Skris *(n++)='0'; 95855714Skris } 95955714Skris *(n++)='.'; *(n++)='p'; *(n++)='e'; *(n++)='m'; 96055714Skris *n='\0'; 96155714Skris if (verbose) 96255714Skris BIO_printf(bio_err,"writing %s\n",buf[2]); 96355714Skris 96455714Skris if (BIO_write_filename(Cout,buf[2]) <= 0) 96555714Skris { 96655714Skris perror(buf[2]); 96755714Skris goto err; 96855714Skris } 96955714Skris write_new_certificate(Cout,x, 0); 97055714Skris write_new_certificate(Sout,x, output_der); 97155714Skris } 97255714Skris 97355714Skris if (sk_num(cert_sk)) 97455714Skris { 97555714Skris /* Rename the database and the serial file */ 97655714Skris strncpy(buf[2],serialfile,BSIZE-4); 97755714Skris 97855714Skris#ifdef VMS 97955714Skris strcat(buf[2],"-old"); 98055714Skris#else 98155714Skris strcat(buf[2],".old"); 98255714Skris#endif 98355714Skris 98455714Skris BIO_free(in); 98555714Skris BIO_free(out); 98655714Skris in=NULL; 98755714Skris out=NULL; 98855714Skris if (rename(serialfile,buf[2]) < 0) 98955714Skris { 99055714Skris BIO_printf(bio_err,"unabel to rename %s to %s\n", 99155714Skris serialfile,buf[2]); 99255714Skris perror("reason"); 99355714Skris goto err; 99455714Skris } 99555714Skris if (rename(buf[0],serialfile) < 0) 99655714Skris { 99755714Skris BIO_printf(bio_err,"unabel to rename %s to %s\n", 99855714Skris buf[0],serialfile); 99955714Skris perror("reason"); 100055714Skris rename(buf[2],serialfile); 100155714Skris goto err; 100255714Skris } 100355714Skris 100455714Skris strncpy(buf[2],dbfile,BSIZE-4); 100555714Skris 100655714Skris#ifdef VMS 100755714Skris strcat(buf[2],"-old"); 100855714Skris#else 100955714Skris strcat(buf[2],".old"); 101055714Skris#endif 101155714Skris 101255714Skris if (rename(dbfile,buf[2]) < 0) 101355714Skris { 101455714Skris BIO_printf(bio_err,"unabel to rename %s to %s\n", 101555714Skris dbfile,buf[2]); 101655714Skris perror("reason"); 101755714Skris goto err; 101855714Skris } 101955714Skris if (rename(buf[1],dbfile) < 0) 102055714Skris { 102155714Skris BIO_printf(bio_err,"unabel to rename %s to %s\n", 102255714Skris buf[1],dbfile); 102355714Skris perror("reason"); 102455714Skris rename(buf[2],dbfile); 102555714Skris goto err; 102655714Skris } 102755714Skris BIO_printf(bio_err,"Data Base Updated\n"); 102855714Skris } 102955714Skris } 103055714Skris 103155714Skris /*****************************************************************/ 103255714Skris if (gencrl) 103355714Skris { 103455714Skris crl_ext=CONF_get_string(conf,section,ENV_CRLEXT); 103555714Skris if(crl_ext) { 103655714Skris /* Check syntax of file */ 103755714Skris X509V3_CTX ctx; 103855714Skris X509V3_set_ctx_test(&ctx); 103955714Skris X509V3_set_conf_lhash(&ctx, conf); 104055714Skris if(!X509V3_EXT_add_conf(conf, &ctx, crl_ext, NULL)) { 104155714Skris BIO_printf(bio_err, 104255714Skris "Error Loading CRL extension section %s\n", 104355714Skris crl_ext); 104455714Skris ret = 1; 104555714Skris goto err; 104655714Skris } 104755714Skris } 104855714Skris if ((hex=BIO_new(BIO_s_mem())) == NULL) goto err; 104955714Skris 105055714Skris if (!crldays && !crlhours) 105155714Skris { 105255714Skris crldays=CONF_get_number(conf,section, 105355714Skris ENV_DEFAULT_CRL_DAYS); 105455714Skris crlhours=CONF_get_number(conf,section, 105555714Skris ENV_DEFAULT_CRL_HOURS); 105655714Skris } 105755714Skris if ((crldays == 0) && (crlhours == 0)) 105855714Skris { 105955714Skris BIO_printf(bio_err,"cannot lookup how long until the next CRL is issuer\n"); 106055714Skris goto err; 106155714Skris } 106255714Skris 106355714Skris if (verbose) BIO_printf(bio_err,"making CRL\n"); 106455714Skris if ((crl=X509_CRL_new()) == NULL) goto err; 106555714Skris ci=crl->crl; 106655714Skris X509_NAME_free(ci->issuer); 106755714Skris ci->issuer=X509_NAME_dup(x509->cert_info->subject); 106855714Skris if (ci->issuer == NULL) goto err; 106955714Skris 107055714Skris X509_gmtime_adj(ci->lastUpdate,0); 107155714Skris if (ci->nextUpdate == NULL) 107255714Skris ci->nextUpdate=ASN1_UTCTIME_new(); 107355714Skris X509_gmtime_adj(ci->nextUpdate,(crldays*24+crlhours)*60*60); 107455714Skris 107555714Skris for (i=0; i<sk_num(db->data); i++) 107655714Skris { 107755714Skris pp=(char **)sk_value(db->data,i); 107855714Skris if (pp[DB_type][0] == DB_TYPE_REV) 107955714Skris { 108055714Skris if ((r=X509_REVOKED_new()) == NULL) goto err; 108155714Skris ASN1_STRING_set((ASN1_STRING *) 108255714Skris r->revocationDate, 108355714Skris (unsigned char *)pp[DB_rev_date], 108455714Skris strlen(pp[DB_rev_date])); 108555714Skris /* strcpy(r->revocationDate,pp[DB_rev_date]);*/ 108655714Skris 108755714Skris (void)BIO_reset(hex); 108855714Skris if (!BIO_puts(hex,pp[DB_serial])) 108955714Skris goto err; 109055714Skris if (!a2i_ASN1_INTEGER(hex,r->serialNumber, 109155714Skris buf[0],BSIZE)) goto err; 109255714Skris 109355714Skris sk_X509_REVOKED_push(ci->revoked,r); 109455714Skris } 109555714Skris } 109655714Skris /* sort the data so it will be written in serial 109755714Skris * number order */ 109855714Skris sk_X509_REVOKED_sort(ci->revoked); 109955714Skris for (i=0; i<sk_X509_REVOKED_num(ci->revoked); i++) 110055714Skris { 110155714Skris r=sk_X509_REVOKED_value(ci->revoked,i); 110255714Skris r->sequence=i; 110355714Skris } 110455714Skris 110555714Skris /* we now have a CRL */ 110655714Skris if (verbose) BIO_printf(bio_err,"signing CRL\n"); 110755714Skris if (md != NULL) 110855714Skris { 110955714Skris if ((dgst=EVP_get_digestbyname(md)) == NULL) 111055714Skris { 111155714Skris BIO_printf(bio_err,"%s is an unsupported message digest type\n",md); 111255714Skris goto err; 111355714Skris } 111455714Skris } 111555714Skris else 111655714Skris { 111755714Skris#ifndef NO_DSA 111855714Skris if (pkey->type == EVP_PKEY_DSA) 111955714Skris dgst=EVP_dss1(); 112055714Skris else 112155714Skris#endif 112255714Skris dgst=EVP_md5(); 112355714Skris } 112455714Skris 112555714Skris /* Add any extensions asked for */ 112655714Skris 112755714Skris if(crl_ext) { 112855714Skris X509V3_CTX crlctx; 112955714Skris if (ci->version == NULL) 113055714Skris if ((ci->version=ASN1_INTEGER_new()) == NULL) goto err; 113155714Skris ASN1_INTEGER_set(ci->version,1); /* version 2 CRL */ 113255714Skris X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0); 113355714Skris X509V3_set_conf_lhash(&crlctx, conf); 113455714Skris 113555714Skris if(!X509V3_EXT_CRL_add_conf(conf, &crlctx, 113655714Skris crl_ext, crl)) goto err; 113755714Skris } 113855714Skris 113955714Skris if (!X509_CRL_sign(crl,pkey,dgst)) goto err; 114055714Skris 114155714Skris PEM_write_bio_X509_CRL(Sout,crl); 114255714Skris } 114355714Skris /*****************************************************************/ 114455714Skris if (dorevoke) 114555714Skris { 114655714Skris in=BIO_new(BIO_s_file()); 114755714Skris out=BIO_new(BIO_s_file()); 114855714Skris if ((in == NULL) || (out == NULL)) 114955714Skris { 115055714Skris ERR_print_errors(bio_err); 115155714Skris goto err; 115255714Skris } 115355714Skris if (infile == NULL) 115455714Skris { 115555714Skris BIO_printf(bio_err,"no input files\n"); 115655714Skris goto err; 115755714Skris } 115855714Skris else 115955714Skris { 116055714Skris if (BIO_read_filename(in,infile) <= 0) 116155714Skris { 116255714Skris perror(infile); 116355714Skris BIO_printf(bio_err,"error trying to load '%s' certificate\n",infile); 116455714Skris goto err; 116555714Skris } 116655714Skris x509=PEM_read_bio_X509(in,NULL,NULL,NULL); 116755714Skris if (x509 == NULL) 116855714Skris { 116955714Skris BIO_printf(bio_err,"unable to load '%s' certificate\n",infile); 117055714Skris goto err; 117155714Skris } 117255714Skris j=do_revoke(x509,db); 117355714Skris 117455714Skris strncpy(buf[0],dbfile,BSIZE-4); 117555714Skris strcat(buf[0],".new"); 117655714Skris if (BIO_write_filename(out,buf[0]) <= 0) 117755714Skris { 117855714Skris perror(dbfile); 117955714Skris BIO_printf(bio_err,"unable to open '%s'\n",dbfile); 118055714Skris goto err; 118155714Skris } 118255714Skris j=TXT_DB_write(out,db); 118355714Skris if (j <= 0) goto err; 118455714Skris BIO_free(in); 118555714Skris BIO_free(out); 118655714Skris in=NULL; 118755714Skris out=NULL; 118855714Skris strncpy(buf[1],dbfile,BSIZE-4); 118955714Skris strcat(buf[1],".old"); 119055714Skris if (rename(dbfile,buf[1]) < 0) 119155714Skris { 119255714Skris BIO_printf(bio_err,"unable to rename %s to %s\n", dbfile, buf[1]); 119355714Skris perror("reason"); 119455714Skris goto err; 119555714Skris } 119655714Skris if (rename(buf[0],dbfile) < 0) 119755714Skris { 119855714Skris BIO_printf(bio_err,"unable to rename %s to %s\n", buf[0],dbfile); 119955714Skris perror("reason"); 120055714Skris rename(buf[1],dbfile); 120155714Skris goto err; 120255714Skris } 120355714Skris BIO_printf(bio_err,"Data Base Updated\n"); 120455714Skris } 120555714Skris } 120655714Skris /*****************************************************************/ 120755714Skris ret=0; 120855714Skriserr: 120955714Skris BIO_free(hex); 121055714Skris BIO_free(Cout); 121155714Skris BIO_free(Sout); 121255714Skris BIO_free(out); 121355714Skris BIO_free(in); 121455714Skris 121555714Skris sk_pop_free(cert_sk,X509_free); 121655714Skris 121755714Skris if (ret) ERR_print_errors(bio_err); 121855714Skris BN_free(serial); 121955714Skris TXT_DB_free(db); 122055714Skris EVP_PKEY_free(pkey); 122155714Skris X509_free(x509); 122255714Skris X509_CRL_free(crl); 122355714Skris CONF_free(conf); 122455714Skris X509V3_EXT_cleanup(); 122555714Skris OBJ_cleanup(); 122655714Skris EXIT(ret); 122755714Skris } 122855714Skris 122955714Skrisstatic void lookup_fail(char *name, char *tag) 123055714Skris { 123155714Skris BIO_printf(bio_err,"variable lookup failed for %s::%s\n",name,tag); 123255714Skris } 123355714Skris 123455714Skrisstatic int MS_CALLBACK key_callback(char *buf, int len, int verify, void *u) 123555714Skris { 123655714Skris int i; 123755714Skris 123855714Skris if (key == NULL) return(0); 123955714Skris i=strlen(key); 124055714Skris i=(i > len)?len:i; 124155714Skris memcpy(buf,key,i); 124255714Skris return(i); 124355714Skris } 124455714Skris 124555714Skrisstatic unsigned long index_serial_hash(char **a) 124655714Skris { 124755714Skris char *n; 124855714Skris 124955714Skris n=a[DB_serial]; 125055714Skris while (*n == '0') n++; 125155714Skris return(lh_strhash(n)); 125255714Skris } 125355714Skris 125455714Skrisstatic int index_serial_cmp(char **a, char **b) 125555714Skris { 125655714Skris char *aa,*bb; 125755714Skris 125855714Skris for (aa=a[DB_serial]; *aa == '0'; aa++); 125955714Skris for (bb=b[DB_serial]; *bb == '0'; bb++); 126055714Skris return(strcmp(aa,bb)); 126155714Skris } 126255714Skris 126355714Skrisstatic unsigned long index_name_hash(char **a) 126455714Skris { return(lh_strhash(a[DB_name])); } 126555714Skris 126655714Skrisstatic int index_name_qual(char **a) 126755714Skris { return(a[0][0] == 'V'); } 126855714Skris 126955714Skrisstatic int index_name_cmp(char **a, char **b) 127055714Skris { return(strcmp(a[DB_name], 127155714Skris b[DB_name])); } 127255714Skris 127355714Skrisstatic BIGNUM *load_serial(char *serialfile) 127455714Skris { 127555714Skris BIO *in=NULL; 127655714Skris BIGNUM *ret=NULL; 127755714Skris MS_STATIC char buf[1024]; 127855714Skris ASN1_INTEGER *ai=NULL; 127955714Skris 128055714Skris if ((in=BIO_new(BIO_s_file())) == NULL) 128155714Skris { 128255714Skris ERR_print_errors(bio_err); 128355714Skris goto err; 128455714Skris } 128555714Skris 128655714Skris if (BIO_read_filename(in,serialfile) <= 0) 128755714Skris { 128855714Skris perror(serialfile); 128955714Skris goto err; 129055714Skris } 129155714Skris ai=ASN1_INTEGER_new(); 129255714Skris if (ai == NULL) goto err; 129355714Skris if (!a2i_ASN1_INTEGER(in,ai,buf,1024)) 129455714Skris { 129555714Skris BIO_printf(bio_err,"unable to load number from %s\n", 129655714Skris serialfile); 129755714Skris goto err; 129855714Skris } 129955714Skris ret=ASN1_INTEGER_to_BN(ai,NULL); 130055714Skris if (ret == NULL) 130155714Skris { 130255714Skris BIO_printf(bio_err,"error converting number from bin to BIGNUM"); 130355714Skris goto err; 130455714Skris } 130555714Skriserr: 130655714Skris if (in != NULL) BIO_free(in); 130755714Skris if (ai != NULL) ASN1_INTEGER_free(ai); 130855714Skris return(ret); 130955714Skris } 131055714Skris 131155714Skrisstatic int save_serial(char *serialfile, BIGNUM *serial) 131255714Skris { 131355714Skris BIO *out; 131455714Skris int ret=0; 131555714Skris ASN1_INTEGER *ai=NULL; 131655714Skris 131755714Skris out=BIO_new(BIO_s_file()); 131855714Skris if (out == NULL) 131955714Skris { 132055714Skris ERR_print_errors(bio_err); 132155714Skris goto err; 132255714Skris } 132355714Skris if (BIO_write_filename(out,serialfile) <= 0) 132455714Skris { 132555714Skris perror(serialfile); 132655714Skris goto err; 132755714Skris } 132855714Skris 132955714Skris if ((ai=BN_to_ASN1_INTEGER(serial,NULL)) == NULL) 133055714Skris { 133155714Skris BIO_printf(bio_err,"error converting serial to ASN.1 format\n"); 133255714Skris goto err; 133355714Skris } 133455714Skris i2a_ASN1_INTEGER(out,ai); 133555714Skris BIO_puts(out,"\n"); 133655714Skris ret=1; 133755714Skriserr: 133855714Skris if (out != NULL) BIO_free(out); 133955714Skris if (ai != NULL) ASN1_INTEGER_free(ai); 134055714Skris return(ret); 134155714Skris } 134255714Skris 134355714Skrisstatic int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, 134455714Skris const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db, 134555714Skris BIGNUM *serial, char *startdate, char *enddate, int days, 134655714Skris int batch, char *ext_sect, LHASH *lconf, int verbose) 134755714Skris { 134855714Skris X509_REQ *req=NULL; 134955714Skris BIO *in=NULL; 135055714Skris EVP_PKEY *pktmp=NULL; 135155714Skris int ok= -1,i; 135255714Skris 135355714Skris in=BIO_new(BIO_s_file()); 135455714Skris 135555714Skris if (BIO_read_filename(in,infile) <= 0) 135655714Skris { 135755714Skris perror(infile); 135855714Skris goto err; 135955714Skris } 136055714Skris if ((req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL)) == NULL) 136155714Skris { 136255714Skris BIO_printf(bio_err,"Error reading certificate request in %s\n", 136355714Skris infile); 136455714Skris goto err; 136555714Skris } 136655714Skris if (verbose) 136755714Skris X509_REQ_print(bio_err,req); 136855714Skris 136955714Skris BIO_printf(bio_err,"Check that the request matches the signature\n"); 137055714Skris 137155714Skris if ((pktmp=X509_REQ_get_pubkey(req)) == NULL) 137255714Skris { 137355714Skris BIO_printf(bio_err,"error unpacking public key\n"); 137455714Skris goto err; 137555714Skris } 137655714Skris i=X509_REQ_verify(req,pktmp); 137755714Skris EVP_PKEY_free(pktmp); 137855714Skris if (i < 0) 137955714Skris { 138055714Skris ok=0; 138155714Skris BIO_printf(bio_err,"Signature verification problems....\n"); 138255714Skris goto err; 138355714Skris } 138455714Skris if (i == 0) 138555714Skris { 138655714Skris ok=0; 138755714Skris BIO_printf(bio_err,"Signature did not match the certificate request\n"); 138855714Skris goto err; 138955714Skris } 139055714Skris else 139155714Skris BIO_printf(bio_err,"Signature ok\n"); 139255714Skris 139355714Skris ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate, enddate, 139455714Skris days,batch,verbose,req,ext_sect,lconf); 139555714Skris 139655714Skriserr: 139755714Skris if (req != NULL) X509_REQ_free(req); 139855714Skris if (in != NULL) BIO_free(in); 139955714Skris return(ok); 140055714Skris } 140155714Skris 140255714Skrisstatic int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, 140355714Skris const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db, 140455714Skris BIGNUM *serial, char *startdate, char *enddate, int days, 140555714Skris int batch, char *ext_sect, LHASH *lconf, int verbose) 140655714Skris { 140755714Skris X509 *req=NULL; 140855714Skris X509_REQ *rreq=NULL; 140955714Skris BIO *in=NULL; 141055714Skris EVP_PKEY *pktmp=NULL; 141155714Skris int ok= -1,i; 141255714Skris 141355714Skris in=BIO_new(BIO_s_file()); 141455714Skris 141555714Skris if (BIO_read_filename(in,infile) <= 0) 141655714Skris { 141755714Skris perror(infile); 141855714Skris goto err; 141955714Skris } 142055714Skris if ((req=PEM_read_bio_X509(in,NULL,NULL,NULL)) == NULL) 142155714Skris { 142255714Skris BIO_printf(bio_err,"Error reading self signed certificate in %s\n",infile); 142355714Skris goto err; 142455714Skris } 142555714Skris if (verbose) 142655714Skris X509_print(bio_err,req); 142755714Skris 142855714Skris BIO_printf(bio_err,"Check that the request matches the signature\n"); 142955714Skris 143055714Skris if ((pktmp=X509_get_pubkey(req)) == NULL) 143155714Skris { 143255714Skris BIO_printf(bio_err,"error unpacking public key\n"); 143355714Skris goto err; 143455714Skris } 143555714Skris i=X509_verify(req,pktmp); 143655714Skris EVP_PKEY_free(pktmp); 143755714Skris if (i < 0) 143855714Skris { 143955714Skris ok=0; 144055714Skris BIO_printf(bio_err,"Signature verification problems....\n"); 144155714Skris goto err; 144255714Skris } 144355714Skris if (i == 0) 144455714Skris { 144555714Skris ok=0; 144655714Skris BIO_printf(bio_err,"Signature did not match the certificate\n"); 144755714Skris goto err; 144855714Skris } 144955714Skris else 145055714Skris BIO_printf(bio_err,"Signature ok\n"); 145155714Skris 145255714Skris if ((rreq=X509_to_X509_REQ(req,NULL,EVP_md5())) == NULL) 145355714Skris goto err; 145455714Skris 145555714Skris ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,enddate,days, 145655714Skris batch,verbose,rreq,ext_sect,lconf); 145755714Skris 145855714Skriserr: 145955714Skris if (rreq != NULL) X509_REQ_free(rreq); 146055714Skris if (req != NULL) X509_free(req); 146155714Skris if (in != NULL) BIO_free(in); 146255714Skris return(ok); 146355714Skris } 146455714Skris 146555714Skrisstatic int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, 146655714Skris STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial, 146755714Skris char *startdate, char *enddate, int days, int batch, int verbose, 146855714Skris X509_REQ *req, char *ext_sect, LHASH *lconf) 146955714Skris { 147055714Skris X509_NAME *name=NULL,*CAname=NULL,*subject=NULL; 147155714Skris ASN1_UTCTIME *tm,*tmptm; 147255714Skris ASN1_STRING *str,*str2; 147355714Skris ASN1_OBJECT *obj; 147455714Skris X509 *ret=NULL; 147555714Skris X509_CINF *ci; 147655714Skris X509_NAME_ENTRY *ne; 147755714Skris X509_NAME_ENTRY *tne,*push; 147855714Skris EVP_PKEY *pktmp; 147955714Skris int ok= -1,i,j,last,nid; 148055714Skris char *p; 148155714Skris CONF_VALUE *cv; 148255714Skris char *row[DB_NUMBER],**rrow,**irow=NULL; 148355714Skris char buf[25],*pbuf; 148455714Skris 148555714Skris tmptm=ASN1_UTCTIME_new(); 148655714Skris if (tmptm == NULL) 148755714Skris { 148855714Skris BIO_printf(bio_err,"malloc error\n"); 148955714Skris return(0); 149055714Skris } 149155714Skris 149255714Skris for (i=0; i<DB_NUMBER; i++) 149355714Skris row[i]=NULL; 149455714Skris 149555714Skris BIO_printf(bio_err,"The Subjects Distinguished Name is as follows\n"); 149655714Skris name=X509_REQ_get_subject_name(req); 149755714Skris for (i=0; i<X509_NAME_entry_count(name); i++) 149855714Skris { 149955714Skris ne=(X509_NAME_ENTRY *)X509_NAME_get_entry(name,i); 150055714Skris obj=X509_NAME_ENTRY_get_object(ne); 150155714Skris j=i2a_ASN1_OBJECT(bio_err,obj); 150255714Skris str=X509_NAME_ENTRY_get_data(ne); 150355714Skris pbuf=buf; 150455714Skris for (j=22-j; j>0; j--) 150555714Skris *(pbuf++)=' '; 150655714Skris *(pbuf++)=':'; 150755714Skris *(pbuf++)='\0'; 150855714Skris BIO_puts(bio_err,buf); 150955714Skris 151055714Skris if (msie_hack) 151155714Skris { 151255714Skris /* assume all type should be strings */ 151355714Skris nid=OBJ_obj2nid(ne->object); 151455714Skris 151555714Skris if (str->type == V_ASN1_UNIVERSALSTRING) 151655714Skris ASN1_UNIVERSALSTRING_to_string(str); 151755714Skris 151855714Skris if ((str->type == V_ASN1_IA5STRING) && 151955714Skris (nid != NID_pkcs9_emailAddress)) 152055714Skris str->type=V_ASN1_T61STRING; 152155714Skris 152255714Skris if ((nid == NID_pkcs9_emailAddress) && 152355714Skris (str->type == V_ASN1_PRINTABLESTRING)) 152455714Skris str->type=V_ASN1_IA5STRING; 152555714Skris } 152655714Skris 152755714Skris if (str->type == V_ASN1_PRINTABLESTRING) 152855714Skris BIO_printf(bio_err,"PRINTABLE:'"); 152955714Skris else if (str->type == V_ASN1_T61STRING) 153055714Skris BIO_printf(bio_err,"T61STRING:'"); 153155714Skris else if (str->type == V_ASN1_IA5STRING) 153255714Skris BIO_printf(bio_err,"IA5STRING:'"); 153355714Skris else if (str->type == V_ASN1_UNIVERSALSTRING) 153455714Skris BIO_printf(bio_err,"UNIVERSALSTRING:'"); 153555714Skris else 153655714Skris BIO_printf(bio_err,"ASN.1 %2d:'",str->type); 153755714Skris 153855714Skris /* check some things */ 153955714Skris if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) && 154055714Skris (str->type != V_ASN1_IA5STRING)) 154155714Skris { 154255714Skris BIO_printf(bio_err,"\nemailAddress type needs to be of type IA5STRING\n"); 154355714Skris goto err; 154455714Skris } 154555714Skris j=ASN1_PRINTABLE_type(str->data,str->length); 154655714Skris if ( ((j == V_ASN1_T61STRING) && 154755714Skris (str->type != V_ASN1_T61STRING)) || 154855714Skris ((j == V_ASN1_IA5STRING) && 154955714Skris (str->type == V_ASN1_PRINTABLESTRING))) 155055714Skris { 155155714Skris BIO_printf(bio_err,"\nThe string contains characters that are illegal for the ASN.1 type\n"); 155255714Skris goto err; 155355714Skris } 155455714Skris 155555714Skris p=(char *)str->data; 155655714Skris for (j=str->length; j>0; j--) 155755714Skris { 155855714Skris if ((*p >= ' ') && (*p <= '~')) 155955714Skris BIO_printf(bio_err,"%c",*p); 156055714Skris else if (*p & 0x80) 156155714Skris BIO_printf(bio_err,"\\0x%02X",*p); 156255714Skris else if ((unsigned char)*p == 0xf7) 156355714Skris BIO_printf(bio_err,"^?"); 156455714Skris else BIO_printf(bio_err,"^%c",*p+'@'); 156555714Skris p++; 156655714Skris } 156755714Skris BIO_printf(bio_err,"'\n"); 156855714Skris } 156955714Skris 157055714Skris /* Ok, now we check the 'policy' stuff. */ 157155714Skris if ((subject=X509_NAME_new()) == NULL) 157255714Skris { 157355714Skris BIO_printf(bio_err,"Malloc failure\n"); 157455714Skris goto err; 157555714Skris } 157655714Skris 157755714Skris /* take a copy of the issuer name before we mess with it. */ 157855714Skris CAname=X509_NAME_dup(x509->cert_info->subject); 157955714Skris if (CAname == NULL) goto err; 158055714Skris str=str2=NULL; 158155714Skris 158255714Skris for (i=0; i<sk_CONF_VALUE_num(policy); i++) 158355714Skris { 158455714Skris cv=sk_CONF_VALUE_value(policy,i); /* get the object id */ 158555714Skris if ((j=OBJ_txt2nid(cv->name)) == NID_undef) 158655714Skris { 158755714Skris BIO_printf(bio_err,"%s:unknown object type in 'policy' configuration\n",cv->name); 158855714Skris goto err; 158955714Skris } 159055714Skris obj=OBJ_nid2obj(j); 159155714Skris 159255714Skris last= -1; 159355714Skris for (;;) 159455714Skris { 159555714Skris /* lookup the object in the supplied name list */ 159655714Skris j=X509_NAME_get_index_by_OBJ(name,obj,last); 159755714Skris if (j < 0) 159855714Skris { 159955714Skris if (last != -1) break; 160055714Skris tne=NULL; 160155714Skris } 160255714Skris else 160355714Skris { 160455714Skris tne=X509_NAME_get_entry(name,j); 160555714Skris } 160655714Skris last=j; 160755714Skris 160855714Skris /* depending on the 'policy', decide what to do. */ 160955714Skris push=NULL; 161055714Skris if (strcmp(cv->value,"optional") == 0) 161155714Skris { 161255714Skris if (tne != NULL) 161355714Skris push=tne; 161455714Skris } 161555714Skris else if (strcmp(cv->value,"supplied") == 0) 161655714Skris { 161755714Skris if (tne == NULL) 161855714Skris { 161955714Skris BIO_printf(bio_err,"The %s field needed to be supplied and was missing\n",cv->name); 162055714Skris goto err; 162155714Skris } 162255714Skris else 162355714Skris push=tne; 162455714Skris } 162555714Skris else if (strcmp(cv->value,"match") == 0) 162655714Skris { 162755714Skris int last2; 162855714Skris 162955714Skris if (tne == NULL) 163055714Skris { 163155714Skris BIO_printf(bio_err,"The mandatory %s field was missing\n",cv->name); 163255714Skris goto err; 163355714Skris } 163455714Skris 163555714Skris last2= -1; 163655714Skris 163755714Skrisagain2: 163855714Skris j=X509_NAME_get_index_by_OBJ(CAname,obj,last2); 163955714Skris if ((j < 0) && (last2 == -1)) 164055714Skris { 164155714Skris BIO_printf(bio_err,"The %s field does not exist in the CA certificate,\nthe 'policy' is misconfigured\n",cv->name); 164255714Skris goto err; 164355714Skris } 164455714Skris if (j >= 0) 164555714Skris { 164655714Skris push=X509_NAME_get_entry(CAname,j); 164755714Skris str=X509_NAME_ENTRY_get_data(tne); 164855714Skris str2=X509_NAME_ENTRY_get_data(push); 164955714Skris last2=j; 165055714Skris if (ASN1_STRING_cmp(str,str2) != 0) 165155714Skris goto again2; 165255714Skris } 165355714Skris if (j < 0) 165455714Skris { 165555714Skris BIO_printf(bio_err,"The %s field needed to be the same in the\nCA certificate (%s) and the request (%s)\n",cv->name,((str == NULL)?"NULL":(char *)str->data),((str2 == NULL)?"NULL":(char *)str2->data)); 165655714Skris goto err; 165755714Skris } 165855714Skris } 165955714Skris else 166055714Skris { 166155714Skris BIO_printf(bio_err,"%s:invalid type in 'policy' configuration\n",cv->value); 166255714Skris goto err; 166355714Skris } 166455714Skris 166555714Skris if (push != NULL) 166655714Skris { 166755714Skris if (!X509_NAME_add_entry(subject,push, 166855714Skris X509_NAME_entry_count(subject),0)) 166955714Skris { 167055714Skris if (push != NULL) 167155714Skris X509_NAME_ENTRY_free(push); 167255714Skris BIO_printf(bio_err,"Malloc failure\n"); 167355714Skris goto err; 167455714Skris } 167555714Skris } 167655714Skris if (j < 0) break; 167755714Skris } 167855714Skris } 167955714Skris 168055714Skris if (preserve) 168155714Skris { 168255714Skris X509_NAME_free(subject); 168355714Skris subject=X509_NAME_dup(X509_REQ_get_subject_name(req)); 168455714Skris if (subject == NULL) goto err; 168555714Skris } 168655714Skris 168755714Skris if (verbose) 168855714Skris BIO_printf(bio_err,"The subject name apears to be ok, checking data base for clashes\n"); 168955714Skris 169055714Skris row[DB_name]=X509_NAME_oneline(subject,NULL,0); 169155714Skris row[DB_serial]=BN_bn2hex(serial); 169255714Skris if ((row[DB_name] == NULL) || (row[DB_serial] == NULL)) 169355714Skris { 169455714Skris BIO_printf(bio_err,"Malloc failure\n"); 169555714Skris goto err; 169655714Skris } 169755714Skris 169855714Skris rrow=TXT_DB_get_by_index(db,DB_name,row); 169955714Skris if (rrow != NULL) 170055714Skris { 170155714Skris BIO_printf(bio_err,"ERROR:There is already a certificate for %s\n", 170255714Skris row[DB_name]); 170355714Skris } 170455714Skris else 170555714Skris { 170655714Skris rrow=TXT_DB_get_by_index(db,DB_serial,row); 170755714Skris if (rrow != NULL) 170855714Skris { 170955714Skris BIO_printf(bio_err,"ERROR:Serial number %s has already been issued,\n", 171055714Skris row[DB_serial]); 171155714Skris BIO_printf(bio_err," check the database/serial_file for corruption\n"); 171255714Skris } 171355714Skris } 171455714Skris 171555714Skris if (rrow != NULL) 171655714Skris { 171755714Skris BIO_printf(bio_err, 171855714Skris "The matching entry has the following details\n"); 171955714Skris if (rrow[DB_type][0] == 'E') 172055714Skris p="Expired"; 172155714Skris else if (rrow[DB_type][0] == 'R') 172255714Skris p="Revoked"; 172355714Skris else if (rrow[DB_type][0] == 'V') 172455714Skris p="Valid"; 172555714Skris else 172655714Skris p="\ninvalid type, Data base error\n"; 172755714Skris BIO_printf(bio_err,"Type :%s\n",p);; 172855714Skris if (rrow[DB_type][0] == 'R') 172955714Skris { 173055714Skris p=rrow[DB_exp_date]; if (p == NULL) p="undef"; 173155714Skris BIO_printf(bio_err,"Was revoked on:%s\n",p); 173255714Skris } 173355714Skris p=rrow[DB_exp_date]; if (p == NULL) p="undef"; 173455714Skris BIO_printf(bio_err,"Expires on :%s\n",p); 173555714Skris p=rrow[DB_serial]; if (p == NULL) p="undef"; 173655714Skris BIO_printf(bio_err,"Serial Number :%s\n",p); 173755714Skris p=rrow[DB_file]; if (p == NULL) p="undef"; 173855714Skris BIO_printf(bio_err,"File name :%s\n",p); 173955714Skris p=rrow[DB_name]; if (p == NULL) p="undef"; 174055714Skris BIO_printf(bio_err,"Subject Name :%s\n",p); 174155714Skris ok= -1; /* This is now a 'bad' error. */ 174255714Skris goto err; 174355714Skris } 174455714Skris 174555714Skris /* We are now totaly happy, lets make and sign the certificate */ 174655714Skris if (verbose) 174755714Skris BIO_printf(bio_err,"Everything appears to be ok, creating and signing the certificate\n"); 174855714Skris 174955714Skris if ((ret=X509_new()) == NULL) goto err; 175055714Skris ci=ret->cert_info; 175155714Skris 175255714Skris#ifdef X509_V3 175355714Skris /* Make it an X509 v3 certificate. */ 175455714Skris if (!X509_set_version(x509,2)) goto err; 175555714Skris#endif 175655714Skris 175755714Skris if (BN_to_ASN1_INTEGER(serial,ci->serialNumber) == NULL) 175855714Skris goto err; 175955714Skris if (!X509_set_issuer_name(ret,X509_get_subject_name(x509))) 176055714Skris goto err; 176155714Skris 176255714Skris BIO_printf(bio_err,"Certificate is to be certified until "); 176355714Skris if (strcmp(startdate,"today") == 0) 176455714Skris X509_gmtime_adj(X509_get_notBefore(ret),0); 176555714Skris else ASN1_UTCTIME_set_string(X509_get_notBefore(ret),startdate); 176655714Skris 176755714Skris if (enddate == NULL) 176855714Skris X509_gmtime_adj(X509_get_notAfter(ret),(long)60*60*24*days); 176955714Skris else ASN1_UTCTIME_set_string(X509_get_notAfter(ret),enddate); 177055714Skris 177155714Skris ASN1_UTCTIME_print(bio_err,X509_get_notAfter(ret)); 177255714Skris if(days) BIO_printf(bio_err," (%d days)",days); 177355714Skris BIO_printf(bio_err, "\n"); 177455714Skris 177555714Skris if (!X509_set_subject_name(ret,subject)) goto err; 177655714Skris 177755714Skris pktmp=X509_REQ_get_pubkey(req); 177855714Skris i = X509_set_pubkey(ret,pktmp); 177955714Skris EVP_PKEY_free(pktmp); 178055714Skris if (!i) goto err; 178155714Skris 178255714Skris /* Lets add the extensions, if there are any */ 178355714Skris if (ext_sect) 178455714Skris { 178555714Skris X509V3_CTX ctx; 178655714Skris if (ci->version == NULL) 178755714Skris if ((ci->version=ASN1_INTEGER_new()) == NULL) 178855714Skris goto err; 178955714Skris ASN1_INTEGER_set(ci->version,2); /* version 3 certificate */ 179055714Skris 179155714Skris /* Free the current entries if any, there should not 179255714Skris * be any I belive */ 179355714Skris if (ci->extensions != NULL) 179455714Skris sk_X509_EXTENSION_pop_free(ci->extensions, 179555714Skris X509_EXTENSION_free); 179655714Skris 179755714Skris ci->extensions = NULL; 179855714Skris 179955714Skris X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0); 180055714Skris X509V3_set_conf_lhash(&ctx, lconf); 180155714Skris 180255714Skris if(!X509V3_EXT_add_conf(lconf, &ctx, ext_sect, ret)) goto err; 180355714Skris 180455714Skris } 180555714Skris 180655714Skris 180755714Skris if (!batch) 180855714Skris { 180955714Skris BIO_printf(bio_err,"Sign the certificate? [y/n]:"); 181055714Skris (void)BIO_flush(bio_err); 181155714Skris buf[0]='\0'; 181255714Skris fgets(buf,sizeof(buf)-1,stdin); 181355714Skris if (!((buf[0] == 'y') || (buf[0] == 'Y'))) 181455714Skris { 181555714Skris BIO_printf(bio_err,"CERTIFICATE WILL NOT BE CERTIFIED\n"); 181655714Skris ok=0; 181755714Skris goto err; 181855714Skris } 181955714Skris } 182055714Skris 182155714Skris 182255714Skris#ifndef NO_DSA 182355714Skris if (pkey->type == EVP_PKEY_DSA) dgst=EVP_dss1(); 182455714Skris pktmp=X509_get_pubkey(ret); 182555714Skris if (EVP_PKEY_missing_parameters(pktmp) && 182655714Skris !EVP_PKEY_missing_parameters(pkey)) 182755714Skris EVP_PKEY_copy_parameters(pktmp,pkey); 182855714Skris EVP_PKEY_free(pktmp); 182955714Skris#endif 183055714Skris 183155714Skris if (!X509_sign(ret,pkey,dgst)) 183255714Skris goto err; 183355714Skris 183455714Skris /* We now just add it to the database */ 183555714Skris row[DB_type]=(char *)Malloc(2); 183655714Skris 183755714Skris tm=X509_get_notAfter(ret); 183855714Skris row[DB_exp_date]=(char *)Malloc(tm->length+1); 183955714Skris memcpy(row[DB_exp_date],tm->data,tm->length); 184055714Skris row[DB_exp_date][tm->length]='\0'; 184155714Skris 184255714Skris row[DB_rev_date]=NULL; 184355714Skris 184455714Skris /* row[DB_serial] done already */ 184555714Skris row[DB_file]=(char *)Malloc(8); 184655714Skris /* row[DB_name] done already */ 184755714Skris 184855714Skris if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) || 184955714Skris (row[DB_file] == NULL)) 185055714Skris { 185155714Skris BIO_printf(bio_err,"Malloc failure\n"); 185255714Skris goto err; 185355714Skris } 185455714Skris strcpy(row[DB_file],"unknown"); 185555714Skris row[DB_type][0]='V'; 185655714Skris row[DB_type][1]='\0'; 185755714Skris 185855714Skris if ((irow=(char **)Malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL) 185955714Skris { 186055714Skris BIO_printf(bio_err,"Malloc failure\n"); 186155714Skris goto err; 186255714Skris } 186355714Skris 186455714Skris for (i=0; i<DB_NUMBER; i++) 186555714Skris { 186655714Skris irow[i]=row[i]; 186755714Skris row[i]=NULL; 186855714Skris } 186955714Skris irow[DB_NUMBER]=NULL; 187055714Skris 187155714Skris if (!TXT_DB_insert(db,irow)) 187255714Skris { 187355714Skris BIO_printf(bio_err,"failed to update database\n"); 187455714Skris BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error); 187555714Skris goto err; 187655714Skris } 187755714Skris ok=1; 187855714Skriserr: 187955714Skris for (i=0; i<DB_NUMBER; i++) 188055714Skris if (row[i] != NULL) Free(row[i]); 188155714Skris 188255714Skris if (CAname != NULL) 188355714Skris X509_NAME_free(CAname); 188455714Skris if (subject != NULL) 188555714Skris X509_NAME_free(subject); 188655714Skris if (ok <= 0) 188755714Skris { 188855714Skris if (ret != NULL) X509_free(ret); 188955714Skris ret=NULL; 189055714Skris } 189155714Skris else 189255714Skris *xret=ret; 189355714Skris return(ok); 189455714Skris } 189555714Skris 189655714Skrisstatic void write_new_certificate(BIO *bp, X509 *x, int output_der) 189755714Skris { 189855714Skris char *f; 189955714Skris char buf[256]; 190055714Skris 190155714Skris if (output_der) 190255714Skris { 190355714Skris (void)i2d_X509_bio(bp,x); 190455714Skris return; 190555714Skris } 190655714Skris 190755714Skris f=X509_NAME_oneline(X509_get_issuer_name(x),buf,256); 190855714Skris BIO_printf(bp,"issuer :%s\n",f); 190955714Skris 191055714Skris f=X509_NAME_oneline(X509_get_subject_name(x),buf,256); 191155714Skris BIO_printf(bp,"subject:%s\n",f); 191255714Skris 191355714Skris BIO_puts(bp,"serial :"); 191455714Skris i2a_ASN1_INTEGER(bp,x->cert_info->serialNumber); 191555714Skris BIO_puts(bp,"\n\n"); 191655714Skris X509_print(bp,x); 191755714Skris BIO_puts(bp,"\n"); 191855714Skris PEM_write_bio_X509(bp,x); 191955714Skris BIO_puts(bp,"\n"); 192055714Skris } 192155714Skris 192255714Skrisstatic int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, 192355714Skris const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db, 192455714Skris BIGNUM *serial, char *startdate, char *enddate, int days, 192555714Skris char *ext_sect, LHASH *lconf, int verbose) 192655714Skris { 192755714Skris STACK_OF(CONF_VALUE) *sk=NULL; 192855714Skris LHASH *parms=NULL; 192955714Skris X509_REQ *req=NULL; 193055714Skris CONF_VALUE *cv=NULL; 193155714Skris NETSCAPE_SPKI *spki = NULL; 193255714Skris unsigned char *spki_der = NULL,*p; 193355714Skris X509_REQ_INFO *ri; 193455714Skris char *type,*buf; 193555714Skris EVP_PKEY *pktmp=NULL; 193655714Skris X509_NAME *n=NULL; 193755714Skris X509_NAME_ENTRY *ne=NULL; 193855714Skris int ok= -1,i,j; 193955714Skris long errline; 194055714Skris int nid; 194155714Skris 194255714Skris /* 194355714Skris * Load input file into a hash table. (This is just an easy 194455714Skris * way to read and parse the file, then put it into a convenient 194555714Skris * STACK format). 194655714Skris */ 194755714Skris parms=CONF_load(NULL,infile,&errline); 194855714Skris if (parms == NULL) 194955714Skris { 195055714Skris BIO_printf(bio_err,"error on line %ld of %s\n",errline,infile); 195155714Skris ERR_print_errors(bio_err); 195255714Skris goto err; 195355714Skris } 195455714Skris 195555714Skris sk=CONF_get_section(parms, "default"); 195655714Skris if (sk_CONF_VALUE_num(sk) == 0) 195755714Skris { 195855714Skris BIO_printf(bio_err, "no name/value pairs found in %s\n", infile); 195955714Skris CONF_free(parms); 196055714Skris goto err; 196155714Skris } 196255714Skris 196355714Skris /* 196455714Skris * Now create a dummy X509 request structure. We don't actually 196555714Skris * have an X509 request, but we have many of the components 196655714Skris * (a public key, various DN components). The idea is that we 196755714Skris * put these components into the right X509 request structure 196855714Skris * and we can use the same code as if you had a real X509 request. 196955714Skris */ 197055714Skris req=X509_REQ_new(); 197155714Skris if (req == NULL) 197255714Skris { 197355714Skris ERR_print_errors(bio_err); 197455714Skris goto err; 197555714Skris } 197655714Skris 197755714Skris /* 197855714Skris * Build up the subject name set. 197955714Skris */ 198055714Skris ri=req->req_info; 198155714Skris n = ri->subject; 198255714Skris 198355714Skris for (i = 0; ; i++) 198455714Skris { 198555714Skris if (sk_CONF_VALUE_num(sk) <= i) break; 198655714Skris 198755714Skris cv=sk_CONF_VALUE_value(sk,i); 198855714Skris type=cv->name; 198955714Skris buf=cv->value; 199055714Skris 199155714Skris if ((nid=OBJ_txt2nid(type)) == NID_undef) 199255714Skris { 199355714Skris if (strcmp(type, "SPKAC") == 0) 199455714Skris { 199555714Skris spki_der=(unsigned char *)Malloc( 199655714Skris strlen(cv->value)+1); 199755714Skris if (spki_der == NULL) 199855714Skris { 199955714Skris BIO_printf(bio_err,"Malloc failure\n"); 200055714Skris goto err; 200155714Skris } 200255714Skris j = EVP_DecodeBlock(spki_der, (unsigned char *)cv->value, 200355714Skris strlen(cv->value)); 200455714Skris if (j <= 0) 200555714Skris { 200655714Skris BIO_printf(bio_err, "Can't b64 decode SPKAC structure\n"); 200755714Skris goto err; 200855714Skris } 200955714Skris 201055714Skris p=spki_der; 201155714Skris spki = d2i_NETSCAPE_SPKI(&spki, &p, j); 201255714Skris Free(spki_der); 201355714Skris spki_der = NULL; 201455714Skris if (spki == NULL) 201555714Skris { 201655714Skris BIO_printf(bio_err,"unable to load Netscape SPKAC structure\n"); 201755714Skris ERR_print_errors(bio_err); 201855714Skris goto err; 201955714Skris } 202055714Skris } 202155714Skris continue; 202255714Skris } 202355714Skris 202455714Skris j=ASN1_PRINTABLE_type((unsigned char *)buf,-1); 202555714Skris if (fix_data(nid, &j) == 0) 202655714Skris { 202755714Skris BIO_printf(bio_err, 202855714Skris "invalid characters in string %s\n",buf); 202955714Skris goto err; 203055714Skris } 203155714Skris 203255714Skris if ((ne=X509_NAME_ENTRY_create_by_NID(&ne,nid,j, 203355714Skris (unsigned char *)buf, 203455714Skris strlen(buf))) == NULL) 203555714Skris goto err; 203655714Skris 203755714Skris if (!X509_NAME_add_entry(n,ne,X509_NAME_entry_count(n),0)) 203855714Skris goto err; 203955714Skris } 204055714Skris if (spki == NULL) 204155714Skris { 204255714Skris BIO_printf(bio_err,"Netscape SPKAC structure not found in %s\n", 204355714Skris infile); 204455714Skris goto err; 204555714Skris } 204655714Skris 204755714Skris /* 204855714Skris * Now extract the key from the SPKI structure. 204955714Skris */ 205055714Skris 205155714Skris BIO_printf(bio_err,"Check that the SPKAC request matches the signature\n"); 205255714Skris 205355714Skris if ((pktmp=X509_PUBKEY_get(spki->spkac->pubkey)) == NULL) 205455714Skris { 205555714Skris BIO_printf(bio_err,"error unpacking SPKAC public key\n"); 205655714Skris goto err; 205755714Skris } 205855714Skris 205955714Skris j = NETSCAPE_SPKI_verify(spki, pktmp); 206055714Skris if (j <= 0) 206155714Skris { 206255714Skris BIO_printf(bio_err,"signature verification failed on SPKAC public key\n"); 206355714Skris goto err; 206455714Skris } 206555714Skris BIO_printf(bio_err,"Signature ok\n"); 206655714Skris 206755714Skris X509_REQ_set_pubkey(req,pktmp); 206855714Skris EVP_PKEY_free(pktmp); 206955714Skris ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,enddate, 207055714Skris days,1,verbose,req,ext_sect,lconf); 207155714Skriserr: 207255714Skris if (req != NULL) X509_REQ_free(req); 207355714Skris if (parms != NULL) CONF_free(parms); 207455714Skris if (spki_der != NULL) Free(spki_der); 207555714Skris if (spki != NULL) NETSCAPE_SPKI_free(spki); 207655714Skris if (ne != NULL) X509_NAME_ENTRY_free(ne); 207755714Skris 207855714Skris return(ok); 207955714Skris } 208055714Skris 208155714Skrisstatic int fix_data(int nid, int *type) 208255714Skris { 208355714Skris if (nid == NID_pkcs9_emailAddress) 208455714Skris *type=V_ASN1_IA5STRING; 208555714Skris if ((nid == NID_commonName) && (*type == V_ASN1_IA5STRING)) 208655714Skris *type=V_ASN1_T61STRING; 208755714Skris if ((nid == NID_pkcs9_challengePassword) && (*type == V_ASN1_IA5STRING)) 208855714Skris *type=V_ASN1_T61STRING; 208955714Skris if ((nid == NID_pkcs9_unstructuredName) && (*type == V_ASN1_T61STRING)) 209055714Skris return(0); 209155714Skris if (nid == NID_pkcs9_unstructuredName) 209255714Skris *type=V_ASN1_IA5STRING; 209355714Skris return(1); 209455714Skris } 209555714Skris 209655714Skrisstatic int check_time_format(char *str) 209755714Skris { 209855714Skris ASN1_UTCTIME tm; 209955714Skris 210055714Skris tm.data=(unsigned char *)str; 210155714Skris tm.length=strlen(str); 210255714Skris tm.type=V_ASN1_UTCTIME; 210355714Skris return(ASN1_UTCTIME_check(&tm)); 210455714Skris } 210555714Skris 210655714Skrisstatic int add_oid_section(LHASH *hconf) 210755714Skris{ 210855714Skris char *p; 210955714Skris STACK_OF(CONF_VALUE) *sktmp; 211055714Skris CONF_VALUE *cnf; 211155714Skris int i; 211255714Skris if(!(p=CONF_get_string(hconf,NULL,"oid_section"))) return 1; 211355714Skris if(!(sktmp = CONF_get_section(hconf, p))) { 211455714Skris BIO_printf(bio_err, "problem loading oid section %s\n", p); 211555714Skris return 0; 211655714Skris } 211755714Skris for(i = 0; i < sk_CONF_VALUE_num(sktmp); i++) { 211855714Skris cnf = sk_CONF_VALUE_value(sktmp, i); 211955714Skris if(OBJ_create(cnf->value, cnf->name, cnf->name) == NID_undef) { 212055714Skris BIO_printf(bio_err, "problem creating object %s=%s\n", 212155714Skris cnf->name, cnf->value); 212255714Skris return 0; 212355714Skris } 212455714Skris } 212555714Skris return 1; 212655714Skris} 212755714Skris 212855714Skrisstatic int do_revoke(X509 *x509, TXT_DB *db) 212955714Skris{ 213055714Skris ASN1_UTCTIME *tm=NULL; 213155714Skris char *row[DB_NUMBER],**rrow,**irow; 213255714Skris int ok=-1,i; 213355714Skris 213455714Skris for (i=0; i<DB_NUMBER; i++) 213555714Skris row[i]=NULL; 213655714Skris row[DB_name]=X509_NAME_oneline(x509->cert_info->subject,NULL,0); 213755714Skris row[DB_serial]=BN_bn2hex(ASN1_INTEGER_to_BN(x509->cert_info->serialNumber,NULL)); 213855714Skris if ((row[DB_name] == NULL) || (row[DB_serial] == NULL)) 213955714Skris { 214055714Skris BIO_printf(bio_err,"Malloc failure\n"); 214155714Skris goto err; 214255714Skris } 214355714Skris rrow=TXT_DB_get_by_index(db,DB_name,row); 214455714Skris if (rrow == NULL) 214555714Skris { 214655714Skris BIO_printf(bio_err,"Adding Entry to DB for %s\n", row[DB_name]); 214755714Skris 214855714Skris /* We now just add it to the database */ 214955714Skris row[DB_type]=(char *)Malloc(2); 215055714Skris 215155714Skris tm=X509_get_notAfter(x509); 215255714Skris row[DB_exp_date]=(char *)Malloc(tm->length+1); 215355714Skris memcpy(row[DB_exp_date],tm->data,tm->length); 215455714Skris row[DB_exp_date][tm->length]='\0'; 215555714Skris 215655714Skris row[DB_rev_date]=NULL; 215755714Skris 215855714Skris /* row[DB_serial] done already */ 215955714Skris row[DB_file]=(char *)Malloc(8); 216055714Skris 216155714Skris /* row[DB_name] done already */ 216255714Skris 216355714Skris if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) || 216455714Skris (row[DB_file] == NULL)) 216555714Skris { 216655714Skris BIO_printf(bio_err,"Malloc failure\n"); 216755714Skris goto err; 216855714Skris } 216955714Skris strcpy(row[DB_file],"unknown"); 217055714Skris row[DB_type][0]='V'; 217155714Skris row[DB_type][1]='\0'; 217255714Skris 217355714Skris if ((irow=(char **)Malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL) 217455714Skris { 217555714Skris BIO_printf(bio_err,"Malloc failure\n"); 217655714Skris goto err; 217755714Skris } 217855714Skris 217955714Skris for (i=0; i<DB_NUMBER; i++) 218055714Skris { 218155714Skris irow[i]=row[i]; 218255714Skris row[i]=NULL; 218355714Skris } 218455714Skris irow[DB_NUMBER]=NULL; 218555714Skris 218655714Skris if (!TXT_DB_insert(db,irow)) 218755714Skris { 218855714Skris BIO_printf(bio_err,"failed to update database\n"); 218955714Skris BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error); 219055714Skris goto err; 219155714Skris } 219255714Skris 219355714Skris /* Revoke Certificate */ 219455714Skris do_revoke(x509,db); 219555714Skris 219655714Skris ok=1; 219755714Skris goto err; 219855714Skris 219955714Skris } 220055714Skris else if (index_serial_cmp(row,rrow)) 220155714Skris { 220255714Skris BIO_printf(bio_err,"ERROR:no same serial number %s\n", 220355714Skris row[DB_serial]); 220455714Skris goto err; 220555714Skris } 220655714Skris else if (rrow[DB_type][0]=='R') 220755714Skris { 220855714Skris BIO_printf(bio_err,"ERROR:Already revoked, serial number %s\n", 220955714Skris row[DB_serial]); 221055714Skris goto err; 221155714Skris } 221255714Skris else 221355714Skris { 221455714Skris BIO_printf(bio_err,"Revoking Certificate %s.\n", rrow[DB_serial]); 221555714Skris tm=X509_gmtime_adj(tm,0); 221655714Skris rrow[DB_type][0]='R'; 221755714Skris rrow[DB_type][1]='\0'; 221855714Skris rrow[DB_rev_date]=(char *)Malloc(tm->length+1); 221955714Skris memcpy(rrow[DB_rev_date],tm->data,tm->length); 222055714Skris rrow[DB_rev_date][tm->length]='\0'; 222155714Skris } 222255714Skris ok=1; 222355714Skriserr: 222455714Skris for (i=0; i<DB_NUMBER; i++) 222555714Skris { 222655714Skris if (row[i] != NULL) 222755714Skris Free(row[i]); 222855714Skris } 222955714Skris ASN1_UTCTIME_free(tm); 223055714Skris return(ok); 223155714Skris} 223255714Skris 2233