2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
5 * This package is an SSL implementation written
6 * by Eric Young (eay@cryptsoft.com).
7 * The implementation was written so as to conform with Netscapes SSL.
9 * This library is free for commercial and non-commercial use as long as
10 * the following conditions are aheared to. The following conditions
11 * apply to all code found in this distribution, be it the RC4, RSA,
12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
13 * included with this distribution is covered by the same copyright terms
14 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
16 * Copyright remains Eric Young's, and as such any Copyright notices in
17 * the code are not to be removed.
18 * If this package is used in a product, Eric Young should be given attribution
19 * as the author of the parts of the library used.
20 * This can be in the form of a textual message at program startup or
21 * in documentation (online or textual) provided with the package.
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
26 * 1. Redistributions of source code must retain the copyright
27 * notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 * notice, this list of conditions and the following disclaimer in the
30 * documentation and/or other materials provided with the distribution.
31 * 3. All advertising materials mentioning features or use of this software
32 * must display the following acknowledgement:
33 * "This product includes cryptographic software written by
34 * Eric Young (eay@cryptsoft.com)"
35 * The word 'cryptographic' can be left out if the rouines from the library
36 * being used are not cryptographic related :-).
37 * 4. If you include any Windows specific code (or a derivative thereof) from
38 * the apps directory (application code) you must include an acknowledgement:
39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53 * The licence and distribution terms for any publically available version or
54 * derivative of this code cannot be changed. i.e. this code cannot simply be
55 * copied and put under another distribution licence
56 * [including the GNU Public Licence.]
59 /* The PPKI stuff has been donated by Jeff Barber <jeffb@issl.atl.hp.com> */
65 #include <sys/types.h>
68 #include <openssl/conf.h>
69 #include <openssl/bio.h>
70 #include <openssl/err.h>
71 #include <openssl/bn.h>
72 #include <openssl/txt_db.h>
73 #include <openssl/evp.h>
74 #include <openssl/x509.h>
75 #include <openssl/x509v3.h>
76 #include <openssl/objects.h>
77 #include <openssl/ocsp.h>
78 #include <openssl/pem.h>
79 #include <openssl/engine.h>
81 #ifdef OPENSSL_SYS_WINDOWS
82 #define strcasecmp _stricmp
88 # ifdef OPENSSL_SYS_VMS
95 # include <sys/file.h>
109 #define BASE_SECTION "ca"
110 #define CONFIG_FILE "openssl.cnf"
112 #define ENV_DEFAULT_CA "default_ca"
114 #define ENV_DIR "dir"
115 #define ENV_CERTS "certs"
116 #define ENV_CRL_DIR "crl_dir"
117 #define ENV_CA_DB "CA_DB"
118 #define ENV_NEW_CERTS_DIR "new_certs_dir"
119 #define ENV_CERTIFICATE "certificate"
120 #define ENV_SERIAL "serial"
121 #define ENV_CRL "crl"
122 #define ENV_PRIVATE_KEY "private_key"
123 #define ENV_RANDFILE "RANDFILE"
124 #define ENV_DEFAULT_DAYS "default_days"
125 #define ENV_DEFAULT_STARTDATE "default_startdate"
126 #define ENV_DEFAULT_ENDDATE "default_enddate"
127 #define ENV_DEFAULT_CRL_DAYS "default_crl_days"
128 #define ENV_DEFAULT_CRL_HOURS "default_crl_hours"
129 #define ENV_DEFAULT_MD "default_md"
130 #define ENV_PRESERVE "preserve"
131 #define ENV_POLICY "policy"
132 #define ENV_EXTENSIONS "x509_extensions"
133 #define ENV_CRLEXT "crl_extensions"
134 #define ENV_MSIE_HACK "msie_hack"
136 #define ENV_DATABASE "database"
139 #define DB_exp_date 1
140 #define DB_rev_date 2
141 #define DB_serial 3 /* index - unique */
143 #define DB_name 5 /* index - unique for active */
146 #define DB_TYPE_REV 'R'
147 #define DB_TYPE_EXP 'E'
148 #define DB_TYPE_VAL 'V'
150 /* Additional revocation information types */
152 #define REV_NONE 0 /* No addditional information */
153 #define REV_CRL_REASON 1 /* Value is CRL reason code */
154 #define REV_HOLD 2 /* Value is hold instruction */
155 #define REV_KEY_COMPROMISE 3 /* Value is cert key compromise time */
156 #define REV_CA_COMPROMISE 4 /* Value is CA key compromise time */
158 static char *ca_usage[]={
161 " -verbose - Talk alot while doing things\n",
162 " -config file - A config file\n",
163 " -name arg - The particular CA definition to use\n",
164 " -gencrl - Generate a new CRL\n",
165 " -crldays days - Days is when the next CRL is due\n",
166 " -crlhours hours - Hours is when the next CRL is due\n",
167 " -startdate YYMMDDHHMMSSZ - certificate validity notBefore\n",
168 " -enddate YYMMDDHHMMSSZ - certificate validity notAfter (overrides -days)\n",
169 " -days arg - number of days to certify the certificate for\n",
170 " -md arg - md to use, one of md2, md5, sha or sha1\n",
171 " -policy arg - The CA 'policy' to support\n",
172 " -keyfile arg - private key file\n",
173 " -keyform arg - private key file format (PEM or ENGINE)\n",
174 " -key arg - key to decode the private key if it is encrypted\n",
175 " -cert file - The CA certificate\n",
176 " -in file - The input PEM encoded certificate request(s)\n",
177 " -out file - Where to put the output file(s)\n",
178 " -outdir dir - Where to put output certificates\n",
179 " -infiles .... - The last argument, requests to process\n",
180 " -spkac file - File contains DN and signed public key and challenge\n",
181 " -ss_cert file - File contains a self signed cert to sign\n",
182 " -preserveDN - Don't re-order the DN\n",
183 " -batch - Don't ask questions\n",
184 " -msie_hack - msie modifications to handle all those universal strings\n",
185 " -revoke file - Revoke a certificate (given in file)\n",
186 " -extensions .. - Extension section (override value in config file)\n",
187 " -extfile file - Configuration file with X509v3 extentions to add\n",
188 " -crlexts .. - CRL extension section (override value in config file)\n",
189 " -engine e - use engine e, possibly a hardware device.\n",
190 " -status serial - Shows certificate status given the serial number\n",
191 " -updatedb - Updates db for expired certificates\n",
196 extern int EF_PROTECT_FREE;
197 extern int EF_PROTECT_BELOW;
198 extern int EF_ALIGNMENT;
201 static void lookup_fail(char *name,char *tag);
202 static unsigned long index_serial_hash(const char **a);
203 static int index_serial_cmp(const char **a, const char **b);
204 static unsigned long index_name_hash(const char **a);
205 static int index_name_qual(char **a);
206 static int index_name_cmp(const char **a,const char **b);
207 static BIGNUM *load_serial(char *serialfile);
208 static int save_serial(char *serialfile, BIGNUM *serial);
209 static int certify(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
210 const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,TXT_DB *db,
211 BIGNUM *serial, char *startdate,char *enddate, int days,
212 int batch, char *ext_sect, LHASH *conf,int verbose);
213 static int certify_cert(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
214 const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
215 TXT_DB *db, BIGNUM *serial,char *startdate,
216 char *enddate, int days, int batch, char *ext_sect,
217 LHASH *conf,int verbose);
218 static int certify_spkac(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
219 const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
220 TXT_DB *db, BIGNUM *serial,char *startdate,
221 char *enddate, int days, char *ext_sect,LHASH *conf,
223 static int fix_data(int nid, int *type);
224 static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext);
225 static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
226 STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial,
227 char *startdate, char *enddate, int days, int batch, int verbose,
228 X509_REQ *req, char *ext_sect, LHASH *conf);
229 static int do_revoke(X509 *x509, TXT_DB *db, int ext, char *extval);
230 static int get_certificate_status(const char *ser_status, TXT_DB *db);
231 static int do_updatedb(TXT_DB *db);
232 static int check_time_format(char *str);
233 char *make_revocation_str(int rev_type, char *rev_arg);
234 int make_revoked(X509_REVOKED *rev, char *str);
235 static LHASH *conf=NULL;
236 static LHASH *extconf=NULL;
237 static char *section=NULL;
239 static int preserve=0;
240 static int msie_hack=0;
242 static IMPLEMENT_LHASH_HASH_FN(index_serial_hash,const char **)
243 static IMPLEMENT_LHASH_COMP_FN(index_serial_cmp,const char **)
244 static IMPLEMENT_LHASH_HASH_FN(index_name_hash,const char **)
245 static IMPLEMENT_LHASH_COMP_FN(index_name_cmp,const char **)
248 int MAIN(int, char **);
250 int MAIN(int argc, char **argv)
253 char *key=NULL,*passargin=NULL;
266 char *configfile=NULL;
271 int keyform=FORMAT_PEM;
273 char *spkac_file=NULL;
274 char *ss_cert_file=NULL;
275 char *ser_status=NULL;
280 char *serialfile=NULL;
281 char *extensions=NULL;
284 int rev_type = REV_NONE;
285 char *rev_arg = NULL;
287 char *startdate=NULL;
294 BIO *in=NULL,*out=NULL,*Sout=NULL,*Cout=NULL;
298 X509_CRL_INFO *ci=NULL;
299 X509_REVOKED *r=NULL;
303 const EVP_MD *dgst=NULL;
304 STACK_OF(CONF_VALUE) *attribs=NULL;
305 STACK_OF(X509) *cert_sk=NULL;
308 MS_STATIC char buf[3][BSIZE];
327 if ((bio_err=BIO_new(BIO_s_file())) != NULL)
328 BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
334 if (strcmp(*argv,"-verbose") == 0)
336 else if (strcmp(*argv,"-config") == 0)
338 if (--argc < 1) goto bad;
339 configfile= *(++argv);
341 else if (strcmp(*argv,"-name") == 0)
343 if (--argc < 1) goto bad;
346 else if (strcmp(*argv,"-startdate") == 0)
348 if (--argc < 1) goto bad;
349 startdate= *(++argv);
351 else if (strcmp(*argv,"-enddate") == 0)
353 if (--argc < 1) goto bad;
356 else if (strcmp(*argv,"-days") == 0)
358 if (--argc < 1) goto bad;
359 days=atoi(*(++argv));
361 else if (strcmp(*argv,"-md") == 0)
363 if (--argc < 1) goto bad;
366 else if (strcmp(*argv,"-policy") == 0)
368 if (--argc < 1) goto bad;
371 else if (strcmp(*argv,"-keyfile") == 0)
373 if (--argc < 1) goto bad;
376 else if (strcmp(*argv,"-keyform") == 0)
378 if (--argc < 1) goto bad;
379 keyform=str2fmt(*(++argv));
381 else if (strcmp(*argv,"-passin") == 0)
383 if (--argc < 1) goto bad;
384 passargin= *(++argv);
386 else if (strcmp(*argv,"-key") == 0)
388 if (--argc < 1) goto bad;
391 else if (strcmp(*argv,"-cert") == 0)
393 if (--argc < 1) goto bad;
396 else if (strcmp(*argv,"-in") == 0)
398 if (--argc < 1) goto bad;
402 else if (strcmp(*argv,"-out") == 0)
404 if (--argc < 1) goto bad;
407 else if (strcmp(*argv,"-outdir") == 0)
409 if (--argc < 1) goto bad;
412 else if (strcmp(*argv,"-notext") == 0)
414 else if (strcmp(*argv,"-batch") == 0)
416 else if (strcmp(*argv,"-preserveDN") == 0)
418 else if (strcmp(*argv,"-gencrl") == 0)
420 else if (strcmp(*argv,"-msie_hack") == 0)
422 else if (strcmp(*argv,"-crldays") == 0)
424 if (--argc < 1) goto bad;
425 crldays= atol(*(++argv));
427 else if (strcmp(*argv,"-crlhours") == 0)
429 if (--argc < 1) goto bad;
430 crlhours= atol(*(++argv));
432 else if (strcmp(*argv,"-infiles") == 0)
439 else if (strcmp(*argv, "-ss_cert") == 0)
441 if (--argc < 1) goto bad;
442 ss_cert_file = *(++argv);
445 else if (strcmp(*argv, "-spkac") == 0)
447 if (--argc < 1) goto bad;
448 spkac_file = *(++argv);
451 else if (strcmp(*argv,"-revoke") == 0)
453 if (--argc < 1) goto bad;
457 else if (strcmp(*argv,"-extensions") == 0)
459 if (--argc < 1) goto bad;
460 extensions= *(++argv);
462 else if (strcmp(*argv,"-extfile") == 0)
464 if (--argc < 1) goto bad;
467 else if (strcmp(*argv,"-status") == 0)
469 if (--argc < 1) goto bad;
470 ser_status= *(++argv);
472 else if (strcmp(*argv,"-updatedb") == 0)
476 else if (strcmp(*argv,"-crlexts") == 0)
478 if (--argc < 1) goto bad;
481 else if (strcmp(*argv,"-crl_reason") == 0)
483 if (--argc < 1) goto bad;
485 rev_type = REV_CRL_REASON;
487 else if (strcmp(*argv,"-crl_hold") == 0)
489 if (--argc < 1) goto bad;
493 else if (strcmp(*argv,"-crl_compromise") == 0)
495 if (--argc < 1) goto bad;
497 rev_type = REV_KEY_COMPROMISE;
499 else if (strcmp(*argv,"-crl_CA_compromise") == 0)
501 if (--argc < 1) goto bad;
503 rev_type = REV_CA_COMPROMISE;
505 else if (strcmp(*argv,"-engine") == 0)
507 if (--argc < 1) goto bad;
513 BIO_printf(bio_err,"unknown option %s\n",*argv);
523 for (pp=ca_usage; (*pp != NULL); pp++)
524 BIO_printf(bio_err,"%s",*pp);
528 ERR_load_crypto_strings();
532 if ((e = ENGINE_by_id(engine)) == NULL)
534 BIO_printf(bio_err,"invalid engine \"%s\"\n",
538 if (!ENGINE_set_default(e, ENGINE_METHOD_ALL))
540 BIO_printf(bio_err,"can't use that engine\n");
543 BIO_printf(bio_err,"engine \"%s\" set.\n", engine);
544 /* Free our "structural" reference. */
548 /*****************************************************************/
549 if (configfile == NULL) configfile = getenv("OPENSSL_CONF");
550 if (configfile == NULL) configfile = getenv("SSLEAY_CONF");
551 if (configfile == NULL)
553 /* We will just use 'buf[0]' as a temporary buffer. */
554 #ifdef OPENSSL_SYS_VMS
555 strncpy(buf[0],X509_get_default_cert_area(),
556 sizeof(buf[0])-1-sizeof(CONFIG_FILE));
558 strncpy(buf[0],X509_get_default_cert_area(),
559 sizeof(buf[0])-2-sizeof(CONFIG_FILE));
562 strcat(buf[0],CONFIG_FILE);
566 BIO_printf(bio_err,"Using configuration from %s\n",configfile);
567 if ((conf=CONF_load(NULL,configfile,&errorline)) == NULL)
570 BIO_printf(bio_err,"error loading the config file '%s'\n",
573 BIO_printf(bio_err,"error on line %ld of config file '%s'\n"
574 ,errorline,configfile);
578 /* Lets get the config section we are using */
581 section=CONF_get_string(conf,BASE_SECTION,ENV_DEFAULT_CA);
584 lookup_fail(BASE_SECTION,ENV_DEFAULT_CA);
591 p=CONF_get_string(conf,NULL,"oid_file");
598 oid_bio=BIO_new_file(p,"r");
602 BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
603 ERR_print_errors(bio_err);
609 OBJ_create_objects(oid_bio);
613 if (!add_oid_section(bio_err,conf))
615 ERR_print_errors(bio_err);
620 randfile = CONF_get_string(conf, BASE_SECTION, "RANDFILE");
621 if (randfile == NULL)
623 app_RAND_load_file(randfile, bio_err, 0);
625 in=BIO_new(BIO_s_file());
626 out=BIO_new(BIO_s_file());
627 Sout=BIO_new(BIO_s_file());
628 Cout=BIO_new(BIO_s_file());
629 if ((in == NULL) || (out == NULL) || (Sout == NULL) || (Cout == NULL))
631 ERR_print_errors(bio_err);
635 /*****************************************************************/
636 /* report status of cert with serial number given on command line */
639 if ((dbfile=CONF_get_string(conf,section,ENV_DATABASE)) == NULL)
641 lookup_fail(section,ENV_DATABASE);
644 if (BIO_read_filename(in,dbfile) <= 0)
647 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
650 db=TXT_DB_read(in,DB_NUMBER);
651 if (db == NULL) goto err;
653 if (!TXT_DB_create_index(db, DB_serial, NULL,
654 LHASH_HASH_FN(index_serial_hash),
655 LHASH_COMP_FN(index_serial_cmp)))
658 "error creating serial number index:(%ld,%ld,%ld)\n",
659 db->error,db->arg1,db->arg2);
663 if (get_certificate_status(ser_status,db) != 1)
664 BIO_printf(bio_err,"Error verifying serial %s!\n",
669 /*****************************************************************/
670 /* we definitely need a public key, so let's get it */
672 if ((keyfile == NULL) && ((keyfile=CONF_get_string(conf,
673 section,ENV_PRIVATE_KEY)) == NULL))
675 lookup_fail(section,ENV_PRIVATE_KEY);
678 if (!key && !app_passwd(bio_err, passargin, NULL, &key, NULL))
680 BIO_printf(bio_err,"Error getting password\n");
683 if (keyform == FORMAT_ENGINE)
687 BIO_printf(bio_err,"no engine specified\n");
690 pkey = ENGINE_load_private_key(e, keyfile, key);
692 else if (keyform == FORMAT_PEM)
694 if (BIO_read_filename(in,keyfile) <= 0)
697 BIO_printf(bio_err,"trying to load CA private key\n");
700 pkey=PEM_read_bio_PrivateKey(in,NULL,NULL,key);
704 BIO_printf(bio_err,"bad input format specified for key file\n");
707 if (key) memset(key,0,strlen(key));
710 BIO_printf(bio_err,"unable to load CA private key\n");
714 /*****************************************************************/
715 /* we need a certificate */
716 if ((certfile == NULL) && ((certfile=CONF_get_string(conf,
717 section,ENV_CERTIFICATE)) == NULL))
719 lookup_fail(section,ENV_CERTIFICATE);
722 if (BIO_read_filename(in,certfile) <= 0)
725 BIO_printf(bio_err,"trying to load CA certificate\n");
728 x509=PEM_read_bio_X509(in,NULL,NULL,NULL);
731 BIO_printf(bio_err,"unable to load CA certificate\n");
735 if (!X509_check_private_key(x509,pkey))
737 BIO_printf(bio_err,"CA certificate and CA private key do not match\n");
741 f=CONF_get_string(conf,BASE_SECTION,ENV_PRESERVE);
744 if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
746 f=CONF_get_string(conf,BASE_SECTION,ENV_MSIE_HACK);
749 if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
752 /*****************************************************************/
753 /* lookup where to write new certificates */
754 if ((outdir == NULL) && (req))
758 if ((outdir=CONF_get_string(conf,section,ENV_NEW_CERTS_DIR))
761 BIO_printf(bio_err,"there needs to be defined a directory for new certificate to be placed in\n");
764 #ifndef OPENSSL_SYS_VMS
765 /* outdir is a directory spec, but access() for VMS demands a
766 filename. In any case, stat(), below, will catch the problem
767 if outdir is not a directory spec, and the fopen() or open()
768 will catch an error if there is no write access.
770 Presumably, this problem could also be solved by using the DEC
771 C routines to convert the directory syntax to Unixly, and give
772 that to access(). However, time's too short to do that just
775 if (access(outdir,R_OK|W_OK|X_OK) != 0)
777 BIO_printf(bio_err,"I am unable to access the %s directory\n",outdir);
782 if (stat(outdir,&sb) != 0)
784 BIO_printf(bio_err,"unable to stat(%s)\n",outdir);
789 if (!(sb.st_mode & S_IFDIR))
791 BIO_printf(bio_err,"%s need to be a directory\n",outdir);
799 /*****************************************************************/
800 /* we need to load the database file */
801 if ((dbfile=CONF_get_string(conf,section,ENV_DATABASE)) == NULL)
803 lookup_fail(section,ENV_DATABASE);
806 if (BIO_read_filename(in,dbfile) <= 0)
809 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
812 db=TXT_DB_read(in,DB_NUMBER);
813 if (db == NULL) goto err;
815 /* Lets check some fields */
816 for (i=0; i<sk_num(db->data); i++)
818 pp=(char **)sk_value(db->data,i);
819 if ((pp[DB_type][0] != DB_TYPE_REV) &&
820 (pp[DB_rev_date][0] != '\0'))
822 BIO_printf(bio_err,"entry %d: not revoked yet, but has a revocation date\n",i+1);
825 if ((pp[DB_type][0] == DB_TYPE_REV) &&
826 !make_revoked(NULL, pp[DB_rev_date]))
828 BIO_printf(bio_err," in entry %d\n", i+1);
831 if (!check_time_format(pp[DB_exp_date]))
833 BIO_printf(bio_err,"entry %d: invalid expiry date\n",i+1);
843 if ((j&1) || (j < 2))
845 BIO_printf(bio_err,"entry %d: bad serial number length (%d)\n",i+1,j);
850 if (!( ((*p >= '0') && (*p <= '9')) ||
851 ((*p >= 'A') && (*p <= 'F')) ||
852 ((*p >= 'a') && (*p <= 'f'))) )
854 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);
862 BIO_set_fp(out,stdout,BIO_NOCLOSE|BIO_FP_TEXT); /* cannot fail */
863 #ifdef OPENSSL_SYS_VMS
865 BIO *tmpbio = BIO_new(BIO_f_linebuffer());
866 out = BIO_push(tmpbio, out);
869 TXT_DB_write(out,db);
870 BIO_printf(bio_err,"%d entries loaded from the database\n",
872 BIO_printf(bio_err,"generating index\n");
875 if (!TXT_DB_create_index(db, DB_serial, NULL,
876 LHASH_HASH_FN(index_serial_hash),
877 LHASH_COMP_FN(index_serial_cmp)))
879 BIO_printf(bio_err,"error creating serial number index:(%ld,%ld,%ld)\n",db->error,db->arg1,db->arg2);
883 if (!TXT_DB_create_index(db, DB_name, index_name_qual,
884 LHASH_HASH_FN(index_name_hash),
885 LHASH_COMP_FN(index_name_cmp)))
887 BIO_printf(bio_err,"error creating name index:(%ld,%ld,%ld)\n",
888 db->error,db->arg1,db->arg2);
892 /*****************************************************************/
893 /* Update the db file for expired certificates */
897 BIO_printf(bio_err, "Updating %s ...\n",
903 BIO_printf(bio_err,"Malloc failure\n");
908 if (verbose) BIO_printf(bio_err,
909 "No entries found to mark expired\n");
913 out = BIO_new(BIO_s_file());
916 ERR_print_errors(bio_err);
920 j = BIO_snprintf(buf[0], sizeof buf[0], "%s.new", dbfile);
921 if (j < 0 || j >= sizeof buf[0])
923 BIO_printf(bio_err, "file name too long\n");
926 if (BIO_write_filename(out,buf[0]) <= 0)
929 BIO_printf(bio_err,"unable to open '%s'\n",
933 j=TXT_DB_write(out,db);
934 if (j <= 0) goto err;
938 j = BIO_snprintf(buf[1], sizeof buf[1], "%s.old", dbfile);
939 if (j < 0 || j >= sizeof buf[1])
941 BIO_printf(bio_err, "file name too long\n");
944 if (rename(dbfile,buf[1]) < 0)
947 "unable to rename %s to %s\n",
952 if (rename(buf[0],dbfile) < 0)
955 "unable to rename %s to %s\n",
958 rename(buf[1],dbfile);
962 if (verbose) BIO_printf(bio_err,
963 "Done. %d entries marked as expired\n",i);
968 /*****************************************************************/
969 /* Read extentions config file */
972 if (!(extconf=CONF_load(NULL,extfile,&errorline)))
975 BIO_printf(bio_err, "ERROR: loading the config file '%s'\n",
978 BIO_printf(bio_err, "ERROR: on line %ld of config file '%s'\n",
985 BIO_printf(bio_err, "Succesfully loaded extensions file %s\n", extfile);
987 /* We can have sections in the ext file */
988 if (!extensions && !(extensions = CONF_get_string(extconf, "default", "extensions")))
989 extensions = "default";
992 /*****************************************************************/
997 if (BIO_write_filename(Sout,outfile) <= 0)
1005 BIO_set_fp(Sout,stdout,BIO_NOCLOSE|BIO_FP_TEXT);
1006 #ifdef OPENSSL_SYS_VMS
1008 BIO *tmpbio = BIO_new(BIO_f_linebuffer());
1009 Sout = BIO_push(tmpbio, Sout);
1017 if ((md == NULL) && ((md=CONF_get_string(conf,
1018 section,ENV_DEFAULT_MD)) == NULL))
1020 lookup_fail(section,ENV_DEFAULT_MD);
1023 if ((dgst=EVP_get_digestbyname(md)) == NULL)
1025 BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
1029 BIO_printf(bio_err,"message digest is %s\n",
1030 OBJ_nid2ln(dgst->type));
1031 if ((policy == NULL) && ((policy=CONF_get_string(conf,
1032 section,ENV_POLICY)) == NULL))
1034 lookup_fail(section,ENV_POLICY);
1038 BIO_printf(bio_err,"policy is %s\n",policy);
1040 if ((serialfile=CONF_get_string(conf,section,ENV_SERIAL))
1043 lookup_fail(section,ENV_SERIAL);
1049 /* no '-extfile' option, so we look for extensions
1050 * in the main configuration file */
1053 extensions=CONF_get_string(conf,section,
1060 /* Check syntax of file */
1062 X509V3_set_ctx_test(&ctx);
1063 X509V3_set_conf_lhash(&ctx, conf);
1064 if (!X509V3_EXT_add_conf(conf, &ctx, extensions,
1068 "Error Loading extension section %s\n",
1076 if (startdate == NULL)
1078 startdate=CONF_get_string(conf,section,
1079 ENV_DEFAULT_STARTDATE);
1080 if (startdate == NULL)
1083 if (startdate && !ASN1_UTCTIME_set_string(NULL,startdate))
1085 BIO_printf(bio_err,"start date is invalid, it should be YYMMDDHHMMSSZ\n");
1088 if (startdate == NULL) startdate="today";
1090 if (enddate == NULL)
1092 enddate=CONF_get_string(conf,section,
1093 ENV_DEFAULT_ENDDATE);
1094 if (enddate == NULL)
1097 if (enddate && !ASN1_UTCTIME_set_string(NULL,enddate))
1099 BIO_printf(bio_err,"end date is invalid, it should be YYMMDDHHMMSSZ\n");
1105 days=(int)CONF_get_number(conf,section,
1108 if (!enddate && (days == 0))
1110 BIO_printf(bio_err,"cannot lookup how many days to certify for\n");
1114 if ((serial=load_serial(serialfile)) == NULL)
1116 BIO_printf(bio_err,"error while loading serial number\n");
1121 if ((f=BN_bn2hex(serial)) == NULL) goto err;
1122 BIO_printf(bio_err,"next serial number is %s\n",f);
1126 if ((attribs=CONF_get_section(conf,policy)) == NULL)
1128 BIO_printf(bio_err,"unable to find 'section' for %s\n",policy);
1132 if ((cert_sk=sk_X509_new_null()) == NULL)
1134 BIO_printf(bio_err,"Memory allocation failure\n");
1137 if (spkac_file != NULL)
1140 j=certify_spkac(&x,spkac_file,pkey,x509,dgst,attribs,db,
1141 serial,startdate,enddate, days,extensions,conf,
1143 if (j < 0) goto err;
1147 BIO_printf(bio_err,"\n");
1148 if (!BN_add_word(serial,1)) goto err;
1149 if (!sk_X509_push(cert_sk,x))
1151 BIO_printf(bio_err,"Memory allocation failure\n");
1161 if (ss_cert_file != NULL)
1164 j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,attribs,
1165 db,serial,startdate,enddate,days,batch,
1166 extensions,conf,verbose);
1167 if (j < 0) goto err;
1171 BIO_printf(bio_err,"\n");
1172 if (!BN_add_word(serial,1)) goto err;
1173 if (!sk_X509_push(cert_sk,x))
1175 BIO_printf(bio_err,"Memory allocation failure\n");
1183 j=certify(&x,infile,pkey,x509,dgst,attribs,db,
1184 serial,startdate,enddate,days,batch,
1185 extensions,conf,verbose);
1186 if (j < 0) goto err;
1190 BIO_printf(bio_err,"\n");
1191 if (!BN_add_word(serial,1)) goto err;
1192 if (!sk_X509_push(cert_sk,x))
1194 BIO_printf(bio_err,"Memory allocation failure\n");
1199 for (i=0; i<argc; i++)
1202 j=certify(&x,argv[i],pkey,x509,dgst,attribs,db,
1203 serial,startdate,enddate,days,batch,
1204 extensions,conf,verbose);
1205 if (j < 0) goto err;
1209 BIO_printf(bio_err,"\n");
1210 if (!BN_add_word(serial,1)) goto err;
1211 if (!sk_X509_push(cert_sk,x))
1213 BIO_printf(bio_err,"Memory allocation failure\n");
1218 /* we have a stack of newly certified certificates
1219 * and a data base and serial number that need
1222 if (sk_X509_num(cert_sk) > 0)
1226 BIO_printf(bio_err,"\n%d out of %d certificate requests certified, commit? [y/n]",total_done,total);
1227 (void)BIO_flush(bio_err);
1229 fgets(buf[0],10,stdin);
1230 if ((buf[0][0] != 'y') && (buf[0][0] != 'Y'))
1232 BIO_printf(bio_err,"CERTIFICATION CANCELED\n");
1238 BIO_printf(bio_err,"Write out database with %d new entries\n",sk_X509_num(cert_sk));
1240 strncpy(buf[0],serialfile,BSIZE-4);
1242 #ifdef OPENSSL_SYS_VMS
1243 strcat(buf[0],"-new");
1245 strcat(buf[0],".new");
1248 if (!save_serial(buf[0],serial)) goto err;
1250 strncpy(buf[1],dbfile,BSIZE-4);
1252 #ifdef OPENSSL_SYS_VMS
1253 strcat(buf[1],"-new");
1255 strcat(buf[1],".new");
1258 if (BIO_write_filename(out,buf[1]) <= 0)
1261 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
1264 l=TXT_DB_write(out,db);
1265 if (l <= 0) goto err;
1269 BIO_printf(bio_err,"writing new certificates\n");
1270 for (i=0; i<sk_X509_num(cert_sk); i++)
1275 x=sk_X509_value(cert_sk,i);
1277 j=x->cert_info->serialNumber->length;
1278 p=(char *)x->cert_info->serialNumber->data;
1280 strncpy(buf[2],outdir,BSIZE-(j*2)-6);
1282 #ifndef OPENSSL_SYS_VMS
1286 n=(unsigned char *)&(buf[2][strlen(buf[2])]);
1291 sprintf((char *)n,"%02X",(unsigned char)*(p++));
1300 *(n++)='.'; *(n++)='p'; *(n++)='e'; *(n++)='m';
1303 BIO_printf(bio_err,"writing %s\n",buf[2]);
1305 if (BIO_write_filename(Cout,buf[2]) <= 0)
1310 write_new_certificate(Cout,x, 0, notext);
1311 write_new_certificate(Sout,x, output_der, notext);
1314 if (sk_X509_num(cert_sk))
1316 /* Rename the database and the serial file */
1317 strncpy(buf[2],serialfile,BSIZE-4);
1319 #ifdef OPENSSL_SYS_VMS
1320 strcat(buf[2],"-old");
1322 strcat(buf[2],".old");
1329 if (rename(serialfile,buf[2]) < 0)
1331 BIO_printf(bio_err,"unable to rename %s to %s\n",
1336 if (rename(buf[0],serialfile) < 0)
1338 BIO_printf(bio_err,"unable to rename %s to %s\n",
1341 rename(buf[2],serialfile);
1345 strncpy(buf[2],dbfile,BSIZE-4);
1347 #ifdef OPENSSL_SYS_VMS
1348 strcat(buf[2],"-old");
1350 strcat(buf[2],".old");
1353 if (rename(dbfile,buf[2]) < 0)
1355 BIO_printf(bio_err,"unable to rename %s to %s\n",
1360 if (rename(buf[1],dbfile) < 0)
1362 BIO_printf(bio_err,"unable to rename %s to %s\n",
1365 rename(buf[2],dbfile);
1368 BIO_printf(bio_err,"Data Base Updated\n");
1372 /*****************************************************************/
1378 crl_ext=CONF_get_string(conf,section,ENV_CRLEXT);
1384 /* Check syntax of file */
1386 X509V3_set_ctx_test(&ctx);
1387 X509V3_set_conf_lhash(&ctx, conf);
1388 if (!X509V3_EXT_add_conf(conf, &ctx, crl_ext, NULL))
1391 "Error Loading CRL extension section %s\n",
1398 if (!crldays && !crlhours)
1400 crldays=CONF_get_number(conf,section,
1401 ENV_DEFAULT_CRL_DAYS);
1402 crlhours=CONF_get_number(conf,section,
1403 ENV_DEFAULT_CRL_HOURS);
1405 if ((crldays == 0) && (crlhours == 0))
1407 BIO_printf(bio_err,"cannot lookup how long until the next CRL is issuer\n");
1411 if (verbose) BIO_printf(bio_err,"making CRL\n");
1412 if ((crl=X509_CRL_new()) == NULL) goto err;
1414 X509_NAME_free(ci->issuer);
1415 ci->issuer=X509_NAME_dup(x509->cert_info->subject);
1416 if (ci->issuer == NULL) goto err;
1418 X509_gmtime_adj(ci->lastUpdate,0);
1419 if (ci->nextUpdate == NULL)
1420 ci->nextUpdate=ASN1_UTCTIME_new();
1421 X509_gmtime_adj(ci->nextUpdate,(crldays*24+crlhours)*60*60);
1423 for (i=0; i<sk_num(db->data); i++)
1425 pp=(char **)sk_value(db->data,i);
1426 if (pp[DB_type][0] == DB_TYPE_REV)
1428 if ((r=X509_REVOKED_new()) == NULL) goto err;
1429 j = make_revoked(r, pp[DB_rev_date]);
1431 if (j == 2) crl_v2 = 1;
1432 if (!BN_hex2bn(&serial, pp[DB_serial]))
1434 r->serialNumber = BN_to_ASN1_INTEGER(serial, r->serialNumber);
1437 if (!r->serialNumber)
1439 X509_CRL_add0_revoked(crl,r);
1442 /* sort the data so it will be written in serial
1444 sk_X509_REVOKED_sort(ci->revoked);
1445 for (i=0; i<sk_X509_REVOKED_num(ci->revoked); i++)
1447 r=sk_X509_REVOKED_value(ci->revoked,i);
1451 /* we now have a CRL */
1452 if (verbose) BIO_printf(bio_err,"signing CRL\n");
1455 if ((dgst=EVP_get_digestbyname(md)) == NULL)
1457 BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
1463 #ifndef OPENSSL_NO_DSA
1464 if (pkey->type == EVP_PKEY_DSA)
1471 /* Add any extensions asked for */
1476 if (ci->version == NULL)
1477 if ((ci->version=ASN1_INTEGER_new()) == NULL) goto err;
1478 X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0);
1479 X509V3_set_conf_lhash(&crlctx, conf);
1481 if (!X509V3_EXT_CRL_add_conf(conf, &crlctx,
1482 crl_ext, crl)) goto err;
1484 if (crl_ext || crl_v2)
1486 if (ci->version == NULL)
1487 if ((ci->version=ASN1_INTEGER_new()) == NULL) goto err;
1488 ASN1_INTEGER_set(ci->version,1); /* version 2 CRL */
1491 if (!X509_CRL_sign(crl,pkey,dgst)) goto err;
1493 PEM_write_bio_X509_CRL(Sout,crl);
1495 /*****************************************************************/
1500 BIO_printf(bio_err,"no input files\n");
1506 if (BIO_read_filename(in,infile) <= 0)
1509 BIO_printf(bio_err,"error trying to load '%s' certificate\n",infile);
1512 revcert=PEM_read_bio_X509(in,NULL,NULL,NULL);
1513 if (revcert == NULL)
1515 BIO_printf(bio_err,"unable to load '%s' certificate\n",infile);
1518 j=do_revoke(revcert,db, rev_type, rev_arg);
1519 if (j <= 0) goto err;
1522 strncpy(buf[0],dbfile,BSIZE-4);
1523 strcat(buf[0],".new");
1524 if (BIO_write_filename(out,buf[0]) <= 0)
1527 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
1530 j=TXT_DB_write(out,db);
1531 if (j <= 0) goto err;
1532 strncpy(buf[1],dbfile,BSIZE-4);
1533 strcat(buf[1],".old");
1534 if (rename(dbfile,buf[1]) < 0)
1536 BIO_printf(bio_err,"unable to rename %s to %s\n", dbfile, buf[1]);
1540 if (rename(buf[0],dbfile) < 0)
1542 BIO_printf(bio_err,"unable to rename %s to %s\n", buf[0],dbfile);
1544 rename(buf[1],dbfile);
1547 BIO_printf(bio_err,"Data Base Updated\n");
1550 /*****************************************************************/
1558 sk_X509_pop_free(cert_sk,X509_free);
1560 if (ret) ERR_print_errors(bio_err);
1561 app_RAND_write_file(randfile, bio_err);
1564 EVP_PKEY_free(pkey);
1572 static void lookup_fail(char *name, char *tag)
1574 BIO_printf(bio_err,"variable lookup failed for %s::%s\n",name,tag);
1577 static unsigned long index_serial_hash(const char **a)
1582 while (*n == '0') n++;
1583 return(lh_strhash(n));
1586 static int index_serial_cmp(const char **a, const char **b)
1590 for (aa=a[DB_serial]; *aa == '0'; aa++);
1591 for (bb=b[DB_serial]; *bb == '0'; bb++);
1592 return(strcmp(aa,bb));
1595 static unsigned long index_name_hash(const char **a)
1596 { return(lh_strhash(a[DB_name])); }
1598 static int index_name_qual(char **a)
1599 { return(a[0][0] == 'V'); }
1601 static int index_name_cmp(const char **a, const char **b)
1602 { return(strcmp(a[DB_name],
1605 static BIGNUM *load_serial(char *serialfile)
1609 MS_STATIC char buf[1024];
1610 ASN1_INTEGER *ai=NULL;
1612 if ((in=BIO_new(BIO_s_file())) == NULL)
1614 ERR_print_errors(bio_err);
1618 if (BIO_read_filename(in,serialfile) <= 0)
1623 ai=ASN1_INTEGER_new();
1624 if (ai == NULL) goto err;
1625 if (!a2i_ASN1_INTEGER(in,ai,buf,1024))
1627 BIO_printf(bio_err,"unable to load number from %s\n",
1631 ret=ASN1_INTEGER_to_BN(ai,NULL);
1634 BIO_printf(bio_err,"error converting number from bin to BIGNUM");
1638 if (in != NULL) BIO_free(in);
1639 if (ai != NULL) ASN1_INTEGER_free(ai);
1643 static int save_serial(char *serialfile, BIGNUM *serial)
1647 ASN1_INTEGER *ai=NULL;
1649 out=BIO_new(BIO_s_file());
1652 ERR_print_errors(bio_err);
1655 if (BIO_write_filename(out,serialfile) <= 0)
1661 if ((ai=BN_to_ASN1_INTEGER(serial,NULL)) == NULL)
1663 BIO_printf(bio_err,"error converting serial to ASN.1 format\n");
1666 i2a_ASN1_INTEGER(out,ai);
1670 if (out != NULL) BIO_free_all(out);
1671 if (ai != NULL) ASN1_INTEGER_free(ai);
1675 static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1676 const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
1677 BIGNUM *serial, char *startdate, char *enddate, int days,
1678 int batch, char *ext_sect, LHASH *lconf, int verbose)
1682 EVP_PKEY *pktmp=NULL;
1685 in=BIO_new(BIO_s_file());
1687 if (BIO_read_filename(in,infile) <= 0)
1692 if ((req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL)) == NULL)
1694 BIO_printf(bio_err,"Error reading certificate request in %s\n",
1699 X509_REQ_print(bio_err,req);
1701 BIO_printf(bio_err,"Check that the request matches the signature\n");
1703 if ((pktmp=X509_REQ_get_pubkey(req)) == NULL)
1705 BIO_printf(bio_err,"error unpacking public key\n");
1708 i=X509_REQ_verify(req,pktmp);
1709 EVP_PKEY_free(pktmp);
1713 BIO_printf(bio_err,"Signature verification problems....\n");
1719 BIO_printf(bio_err,"Signature did not match the certificate request\n");
1723 BIO_printf(bio_err,"Signature ok\n");
1725 ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate, enddate,
1726 days,batch,verbose,req,ext_sect,lconf);
1729 if (req != NULL) X509_REQ_free(req);
1730 if (in != NULL) BIO_free(in);
1734 static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1735 const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
1736 BIGNUM *serial, char *startdate, char *enddate, int days,
1737 int batch, char *ext_sect, LHASH *lconf, int verbose)
1740 X509_REQ *rreq=NULL;
1742 EVP_PKEY *pktmp=NULL;
1745 in=BIO_new(BIO_s_file());
1747 if (BIO_read_filename(in,infile) <= 0)
1752 if ((req=PEM_read_bio_X509(in,NULL,NULL,NULL)) == NULL)
1754 BIO_printf(bio_err,"Error reading self signed certificate in %s\n",infile);
1758 X509_print(bio_err,req);
1760 BIO_printf(bio_err,"Check that the request matches the signature\n");
1762 if ((pktmp=X509_get_pubkey(req)) == NULL)
1764 BIO_printf(bio_err,"error unpacking public key\n");
1767 i=X509_verify(req,pktmp);
1768 EVP_PKEY_free(pktmp);
1772 BIO_printf(bio_err,"Signature verification problems....\n");
1778 BIO_printf(bio_err,"Signature did not match the certificate\n");
1782 BIO_printf(bio_err,"Signature ok\n");
1784 if ((rreq=X509_to_X509_REQ(req,NULL,EVP_md5())) == NULL)
1787 ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,enddate,days,
1788 batch,verbose,rreq,ext_sect,lconf);
1791 if (rreq != NULL) X509_REQ_free(rreq);
1792 if (req != NULL) X509_free(req);
1793 if (in != NULL) BIO_free(in);
1797 static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
1798 STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial,
1799 char *startdate, char *enddate, int days, int batch, int verbose,
1800 X509_REQ *req, char *ext_sect, LHASH *lconf)
1802 X509_NAME *name=NULL,*CAname=NULL,*subject=NULL;
1803 ASN1_UTCTIME *tm,*tmptm;
1804 ASN1_STRING *str,*str2;
1808 X509_NAME_ENTRY *ne;
1809 X509_NAME_ENTRY *tne,*push;
1811 int ok= -1,i,j,last,nid;
1814 char *row[DB_NUMBER],**rrow,**irow=NULL;
1817 tmptm=ASN1_UTCTIME_new();
1820 BIO_printf(bio_err,"malloc error\n");
1824 for (i=0; i<DB_NUMBER; i++)
1827 BIO_printf(bio_err,"The Subjects Distinguished Name is as follows\n");
1828 name=X509_REQ_get_subject_name(req);
1829 for (i=0; i<X509_NAME_entry_count(name); i++)
1831 ne=(X509_NAME_ENTRY *)X509_NAME_get_entry(name,i);
1832 obj=X509_NAME_ENTRY_get_object(ne);
1833 j=i2a_ASN1_OBJECT(bio_err,obj);
1834 str=X509_NAME_ENTRY_get_data(ne);
1836 for (j=22-j; j>0; j--)
1840 BIO_puts(bio_err,buf);
1844 /* assume all type should be strings */
1845 nid=OBJ_obj2nid(ne->object);
1847 if (str->type == V_ASN1_UNIVERSALSTRING)
1848 ASN1_UNIVERSALSTRING_to_string(str);
1850 if ((str->type == V_ASN1_IA5STRING) &&
1851 (nid != NID_pkcs9_emailAddress))
1852 str->type=V_ASN1_T61STRING;
1854 if ((nid == NID_pkcs9_emailAddress) &&
1855 (str->type == V_ASN1_PRINTABLESTRING))
1856 str->type=V_ASN1_IA5STRING;
1859 if (str->type == V_ASN1_PRINTABLESTRING)
1860 BIO_printf(bio_err,"PRINTABLE:'");
1861 else if (str->type == V_ASN1_T61STRING)
1862 BIO_printf(bio_err,"T61STRING:'");
1863 else if (str->type == V_ASN1_IA5STRING)
1864 BIO_printf(bio_err,"IA5STRING:'");
1865 else if (str->type == V_ASN1_UNIVERSALSTRING)
1866 BIO_printf(bio_err,"UNIVERSALSTRING:'");
1868 BIO_printf(bio_err,"ASN.1 %2d:'",str->type);
1870 /* check some things */
1871 if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) &&
1872 (str->type != V_ASN1_IA5STRING))
1874 BIO_printf(bio_err,"\nemailAddress type needs to be of type IA5STRING\n");
1877 j=ASN1_PRINTABLE_type(str->data,str->length);
1878 if ( ((j == V_ASN1_T61STRING) &&
1879 (str->type != V_ASN1_T61STRING)) ||
1880 ((j == V_ASN1_IA5STRING) &&
1881 (str->type == V_ASN1_PRINTABLESTRING)))
1883 BIO_printf(bio_err,"\nThe string contains characters that are illegal for the ASN.1 type\n");
1887 p=(char *)str->data;
1888 for (j=str->length; j>0; j--)
1890 if ((*p >= ' ') && (*p <= '~'))
1891 BIO_printf(bio_err,"%c",*p);
1893 BIO_printf(bio_err,"\\0x%02X",*p);
1894 else if ((unsigned char)*p == 0xf7)
1895 BIO_printf(bio_err,"^?");
1896 else BIO_printf(bio_err,"^%c",*p+'@');
1899 BIO_printf(bio_err,"'\n");
1902 /* Ok, now we check the 'policy' stuff. */
1903 if ((subject=X509_NAME_new()) == NULL)
1905 BIO_printf(bio_err,"Memory allocation failure\n");
1909 /* take a copy of the issuer name before we mess with it. */
1910 CAname=X509_NAME_dup(x509->cert_info->subject);
1911 if (CAname == NULL) goto err;
1914 for (i=0; i<sk_CONF_VALUE_num(policy); i++)
1916 cv=sk_CONF_VALUE_value(policy,i); /* get the object id */
1917 if ((j=OBJ_txt2nid(cv->name)) == NID_undef)
1919 BIO_printf(bio_err,"%s:unknown object type in 'policy' configuration\n",cv->name);
1927 /* lookup the object in the supplied name list */
1928 j=X509_NAME_get_index_by_OBJ(name,obj,last);
1931 if (last != -1) break;
1936 tne=X509_NAME_get_entry(name,j);
1940 /* depending on the 'policy', decide what to do. */
1942 if (strcmp(cv->value,"optional") == 0)
1947 else if (strcmp(cv->value,"supplied") == 0)
1951 BIO_printf(bio_err,"The %s field needed to be supplied and was missing\n",cv->name);
1957 else if (strcmp(cv->value,"match") == 0)
1963 BIO_printf(bio_err,"The mandatory %s field was missing\n",cv->name);
1970 j=X509_NAME_get_index_by_OBJ(CAname,obj,last2);
1971 if ((j < 0) && (last2 == -1))
1973 BIO_printf(bio_err,"The %s field does not exist in the CA certificate,\nthe 'policy' is misconfigured\n",cv->name);
1978 push=X509_NAME_get_entry(CAname,j);
1979 str=X509_NAME_ENTRY_get_data(tne);
1980 str2=X509_NAME_ENTRY_get_data(push);
1982 if (ASN1_STRING_cmp(str,str2) != 0)
1987 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));
1993 BIO_printf(bio_err,"%s:invalid type in 'policy' configuration\n",cv->value);
1999 if (!X509_NAME_add_entry(subject,push, -1, 0))
2002 X509_NAME_ENTRY_free(push);
2003 BIO_printf(bio_err,"Memory allocation failure\n");
2013 X509_NAME_free(subject);
2014 subject=X509_NAME_dup(X509_REQ_get_subject_name(req));
2015 if (subject == NULL) goto err;
2019 BIO_printf(bio_err,"The subject name appears to be ok, checking data base for clashes\n");
2021 row[DB_name]=X509_NAME_oneline(subject,NULL,0);
2022 row[DB_serial]=BN_bn2hex(serial);
2023 if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
2025 BIO_printf(bio_err,"Memory allocation failure\n");
2029 rrow=TXT_DB_get_by_index(db,DB_name,row);
2032 BIO_printf(bio_err,"ERROR:There is already a certificate for %s\n",
2037 rrow=TXT_DB_get_by_index(db,DB_serial,row);
2040 BIO_printf(bio_err,"ERROR:Serial number %s has already been issued,\n",
2042 BIO_printf(bio_err," check the database/serial_file for corruption\n");
2049 "The matching entry has the following details\n");
2050 if (rrow[DB_type][0] == 'E')
2052 else if (rrow[DB_type][0] == 'R')
2054 else if (rrow[DB_type][0] == 'V')
2057 p="\ninvalid type, Data base error\n";
2058 BIO_printf(bio_err,"Type :%s\n",p);;
2059 if (rrow[DB_type][0] == 'R')
2061 p=rrow[DB_exp_date]; if (p == NULL) p="undef";
2062 BIO_printf(bio_err,"Was revoked on:%s\n",p);
2064 p=rrow[DB_exp_date]; if (p == NULL) p="undef";
2065 BIO_printf(bio_err,"Expires on :%s\n",p);
2066 p=rrow[DB_serial]; if (p == NULL) p="undef";
2067 BIO_printf(bio_err,"Serial Number :%s\n",p);
2068 p=rrow[DB_file]; if (p == NULL) p="undef";
2069 BIO_printf(bio_err,"File name :%s\n",p);
2070 p=rrow[DB_name]; if (p == NULL) p="undef";
2071 BIO_printf(bio_err,"Subject Name :%s\n",p);
2072 ok= -1; /* This is now a 'bad' error. */
2076 /* We are now totally happy, lets make and sign the certificate */
2078 BIO_printf(bio_err,"Everything appears to be ok, creating and signing the certificate\n");
2080 if ((ret=X509_new()) == NULL) goto err;
2084 /* Make it an X509 v3 certificate. */
2085 if (!X509_set_version(x509,2)) goto err;
2088 if (BN_to_ASN1_INTEGER(serial,ci->serialNumber) == NULL)
2090 if (!X509_set_issuer_name(ret,X509_get_subject_name(x509)))
2093 BIO_printf(bio_err,"Certificate is to be certified until ");
2094 if (strcmp(startdate,"today") == 0)
2095 X509_gmtime_adj(X509_get_notBefore(ret),0);
2096 else ASN1_UTCTIME_set_string(X509_get_notBefore(ret),startdate);
2098 if (enddate == NULL)
2099 X509_gmtime_adj(X509_get_notAfter(ret),(long)60*60*24*days);
2100 else ASN1_UTCTIME_set_string(X509_get_notAfter(ret),enddate);
2102 ASN1_UTCTIME_print(bio_err,X509_get_notAfter(ret));
2103 if (days) BIO_printf(bio_err," (%d days)",days);
2104 BIO_printf(bio_err, "\n");
2106 if (!X509_set_subject_name(ret,subject)) goto err;
2108 pktmp=X509_REQ_get_pubkey(req);
2109 i = X509_set_pubkey(ret,pktmp);
2110 EVP_PKEY_free(pktmp);
2113 /* Lets add the extensions, if there are any */
2117 if (ci->version == NULL)
2118 if ((ci->version=ASN1_INTEGER_new()) == NULL)
2120 ASN1_INTEGER_set(ci->version,2); /* version 3 certificate */
2122 /* Free the current entries if any, there should not
2123 * be any I believe */
2124 if (ci->extensions != NULL)
2125 sk_X509_EXTENSION_pop_free(ci->extensions,
2126 X509_EXTENSION_free);
2128 ci->extensions = NULL;
2130 /* Initialize the context structure */
2131 X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0);
2136 BIO_printf(bio_err, "Extra configuration file found\n");
2138 /* Use the extconf configuration db LHASH */
2139 X509V3_set_conf_lhash(&ctx, extconf);
2141 /* Test the structure (needed?) */
2142 /* X509V3_set_ctx_test(&ctx); */
2144 /* Adds exts contained in the configuration file */
2145 if (!X509V3_EXT_add_conf(extconf, &ctx, ext_sect,ret))
2148 "ERROR: adding extensions in section %s\n",
2150 ERR_print_errors(bio_err);
2154 BIO_printf(bio_err, "Successfully added extensions from file.\n");
2158 /* We found extensions to be set from config file */
2159 X509V3_set_conf_lhash(&ctx, lconf);
2161 if(!X509V3_EXT_add_conf(lconf, &ctx, ext_sect, ret))
2163 BIO_printf(bio_err, "ERROR: adding extensions in section %s\n", ext_sect);
2164 ERR_print_errors(bio_err);
2169 BIO_printf(bio_err, "Successfully added extensions from config\n");
2176 BIO_printf(bio_err,"Sign the certificate? [y/n]:");
2177 (void)BIO_flush(bio_err);
2179 fgets(buf,sizeof(buf)-1,stdin);
2180 if (!((buf[0] == 'y') || (buf[0] == 'Y')))
2182 BIO_printf(bio_err,"CERTIFICATE WILL NOT BE CERTIFIED\n");
2189 #ifndef OPENSSL_NO_DSA
2190 if (pkey->type == EVP_PKEY_DSA) dgst=EVP_dss1();
2191 pktmp=X509_get_pubkey(ret);
2192 if (EVP_PKEY_missing_parameters(pktmp) &&
2193 !EVP_PKEY_missing_parameters(pkey))
2194 EVP_PKEY_copy_parameters(pktmp,pkey);
2195 EVP_PKEY_free(pktmp);
2198 if (!X509_sign(ret,pkey,dgst))
2201 /* We now just add it to the database */
2202 row[DB_type]=(char *)OPENSSL_malloc(2);
2204 tm=X509_get_notAfter(ret);
2205 row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
2206 memcpy(row[DB_exp_date],tm->data,tm->length);
2207 row[DB_exp_date][tm->length]='\0';
2209 row[DB_rev_date]=NULL;
2211 /* row[DB_serial] done already */
2212 row[DB_file]=(char *)OPENSSL_malloc(8);
2213 /* row[DB_name] done already */
2215 if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2216 (row[DB_file] == NULL))
2218 BIO_printf(bio_err,"Memory allocation failure\n");
2221 strcpy(row[DB_file],"unknown");
2222 row[DB_type][0]='V';
2223 row[DB_type][1]='\0';
2225 if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
2227 BIO_printf(bio_err,"Memory allocation failure\n");
2231 for (i=0; i<DB_NUMBER; i++)
2236 irow[DB_NUMBER]=NULL;
2238 if (!TXT_DB_insert(db,irow))
2240 BIO_printf(bio_err,"failed to update database\n");
2241 BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
2246 for (i=0; i<DB_NUMBER; i++)
2247 if (row[i] != NULL) OPENSSL_free(row[i]);
2250 X509_NAME_free(CAname);
2251 if (subject != NULL)
2252 X509_NAME_free(subject);
2254 ASN1_UTCTIME_free(tmptm);
2257 if (ret != NULL) X509_free(ret);
2265 static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext)
2270 (void)i2d_X509_bio(bp,x);
2274 /* ??? Not needed since X509_print prints all this stuff anyway */
2275 f=X509_NAME_oneline(X509_get_issuer_name(x),buf,256);
2276 BIO_printf(bp,"issuer :%s\n",f);
2278 f=X509_NAME_oneline(X509_get_subject_name(x),buf,256);
2279 BIO_printf(bp,"subject:%s\n",f);
2281 BIO_puts(bp,"serial :");
2282 i2a_ASN1_INTEGER(bp,x->cert_info->serialNumber);
2283 BIO_puts(bp,"\n\n");
2285 if (!notext)X509_print(bp,x);
2286 PEM_write_bio_X509(bp,x);
2289 static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
2290 const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
2291 BIGNUM *serial, char *startdate, char *enddate, int days,
2292 char *ext_sect, LHASH *lconf, int verbose)
2294 STACK_OF(CONF_VALUE) *sk=NULL;
2297 CONF_VALUE *cv=NULL;
2298 NETSCAPE_SPKI *spki = NULL;
2301 EVP_PKEY *pktmp=NULL;
2303 X509_NAME_ENTRY *ne=NULL;
2309 * Load input file into a hash table. (This is just an easy
2310 * way to read and parse the file, then put it into a convenient
2313 parms=CONF_load(NULL,infile,&errline);
2316 BIO_printf(bio_err,"error on line %ld of %s\n",errline,infile);
2317 ERR_print_errors(bio_err);
2321 sk=CONF_get_section(parms, "default");
2322 if (sk_CONF_VALUE_num(sk) == 0)
2324 BIO_printf(bio_err, "no name/value pairs found in %s\n", infile);
2330 * Now create a dummy X509 request structure. We don't actually
2331 * have an X509 request, but we have many of the components
2332 * (a public key, various DN components). The idea is that we
2333 * put these components into the right X509 request structure
2334 * and we can use the same code as if you had a real X509 request.
2339 ERR_print_errors(bio_err);
2344 * Build up the subject name set.
2351 if (sk_CONF_VALUE_num(sk) <= i) break;
2353 cv=sk_CONF_VALUE_value(sk,i);
2355 /* Skip past any leading X. X: X, etc to allow for
2356 * multiple instances
2358 for (buf = cv->name; *buf ; buf++)
2359 if ((*buf == ':') || (*buf == ',') || (*buf == '.'))
2362 if (*buf) type = buf;
2367 if ((nid=OBJ_txt2nid(type)) == NID_undef)
2369 if (strcmp(type, "SPKAC") == 0)
2371 spki = NETSCAPE_SPKI_b64_decode(cv->value, -1);
2374 BIO_printf(bio_err,"unable to load Netscape SPKAC structure\n");
2375 ERR_print_errors(bio_err);
2382 j=ASN1_PRINTABLE_type((unsigned char *)buf,-1);
2383 if (fix_data(nid, &j) == 0)
2386 "invalid characters in string %s\n",buf);
2390 if ((ne=X509_NAME_ENTRY_create_by_NID(&ne,nid,j,
2391 (unsigned char *)buf,
2392 strlen(buf))) == NULL)
2395 if (!X509_NAME_add_entry(n,ne,-1, 0)) goto err;
2399 BIO_printf(bio_err,"Netscape SPKAC structure not found in %s\n",
2405 * Now extract the key from the SPKI structure.
2408 BIO_printf(bio_err,"Check that the SPKAC request matches the signature\n");
2410 if ((pktmp=NETSCAPE_SPKI_get_pubkey(spki)) == NULL)
2412 BIO_printf(bio_err,"error unpacking SPKAC public key\n");
2416 j = NETSCAPE_SPKI_verify(spki, pktmp);
2419 BIO_printf(bio_err,"signature verification failed on SPKAC public key\n");
2422 BIO_printf(bio_err,"Signature ok\n");
2424 X509_REQ_set_pubkey(req,pktmp);
2425 EVP_PKEY_free(pktmp);
2426 ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,enddate,
2427 days,1,verbose,req,ext_sect,lconf);
2429 if (req != NULL) X509_REQ_free(req);
2430 if (parms != NULL) CONF_free(parms);
2431 if (spki != NULL) NETSCAPE_SPKI_free(spki);
2432 if (ne != NULL) X509_NAME_ENTRY_free(ne);
2437 static int fix_data(int nid, int *type)
2439 if (nid == NID_pkcs9_emailAddress)
2440 *type=V_ASN1_IA5STRING;
2441 if ((nid == NID_commonName) && (*type == V_ASN1_IA5STRING))
2442 *type=V_ASN1_T61STRING;
2443 if ((nid == NID_pkcs9_challengePassword) && (*type == V_ASN1_IA5STRING))
2444 *type=V_ASN1_T61STRING;
2445 if ((nid == NID_pkcs9_unstructuredName) && (*type == V_ASN1_T61STRING))
2447 if (nid == NID_pkcs9_unstructuredName)
2448 *type=V_ASN1_IA5STRING;
2452 static int check_time_format(char *str)
2456 tm.data=(unsigned char *)str;
2457 tm.length=strlen(str);
2458 tm.type=V_ASN1_UTCTIME;
2459 return(ASN1_UTCTIME_check(&tm));
2462 static int do_revoke(X509 *x509, TXT_DB *db, int type, char *value)
2464 ASN1_UTCTIME *tm=NULL;
2465 char *row[DB_NUMBER],**rrow,**irow;
2466 char *rev_str = NULL;
2470 for (i=0; i<DB_NUMBER; i++)
2472 row[DB_name]=X509_NAME_oneline(X509_get_subject_name(x509),NULL,0);
2473 bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509),NULL);
2474 row[DB_serial]=BN_bn2hex(bn);
2476 if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
2478 BIO_printf(bio_err,"Memory allocation failure\n");
2481 /* We have to lookup by serial number because name lookup
2482 * skips revoked certs
2484 rrow=TXT_DB_get_by_index(db,DB_serial,row);
2487 BIO_printf(bio_err,"Adding Entry to DB for %s\n", row[DB_name]);
2489 /* We now just add it to the database */
2490 row[DB_type]=(char *)OPENSSL_malloc(2);
2492 tm=X509_get_notAfter(x509);
2493 row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
2494 memcpy(row[DB_exp_date],tm->data,tm->length);
2495 row[DB_exp_date][tm->length]='\0';
2497 row[DB_rev_date]=NULL;
2499 /* row[DB_serial] done already */
2500 row[DB_file]=(char *)OPENSSL_malloc(8);
2502 /* row[DB_name] done already */
2504 if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2505 (row[DB_file] == NULL))
2507 BIO_printf(bio_err,"Memory allocation failure\n");
2510 strcpy(row[DB_file],"unknown");
2511 row[DB_type][0]='V';
2512 row[DB_type][1]='\0';
2514 if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
2516 BIO_printf(bio_err,"Memory allocation failure\n");
2520 for (i=0; i<DB_NUMBER; i++)
2525 irow[DB_NUMBER]=NULL;
2527 if (!TXT_DB_insert(db,irow))
2529 BIO_printf(bio_err,"failed to update database\n");
2530 BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
2534 /* Revoke Certificate */
2535 ok = do_revoke(x509,db, type, value);
2540 else if (index_name_cmp((const char **)row,(const char **)rrow))
2542 BIO_printf(bio_err,"ERROR:name does not match %s\n",
2546 else if (rrow[DB_type][0]=='R')
2548 BIO_printf(bio_err,"ERROR:Already revoked, serial number %s\n",
2554 BIO_printf(bio_err,"Revoking Certificate %s.\n", rrow[DB_serial]);
2555 rev_str = make_revocation_str(type, value);
2558 BIO_printf(bio_err, "Error in revocation arguments\n");
2561 rrow[DB_type][0]='R';
2562 rrow[DB_type][1]='\0';
2563 rrow[DB_rev_date] = rev_str;
2567 for (i=0; i<DB_NUMBER; i++)
2570 OPENSSL_free(row[i]);
2575 static int get_certificate_status(const char *serial, TXT_DB *db)
2577 char *row[DB_NUMBER],**rrow;
2580 /* Free Resources */
2581 for (i=0; i<DB_NUMBER; i++)
2584 /* Malloc needed char spaces */
2585 row[DB_serial] = OPENSSL_malloc(strlen(serial) + 2);
2586 if (row[DB_serial] == NULL)
2588 BIO_printf(bio_err,"Malloc failure\n");
2592 if (strlen(serial) % 2)
2594 /* Set the first char to 0 */;
2595 row[DB_serial][0]='0';
2597 /* Copy String from serial to row[DB_serial] */
2598 memcpy(row[DB_serial]+1, serial, strlen(serial));
2599 row[DB_serial][strlen(serial)+1]='\0';
2603 /* Copy String from serial to row[DB_serial] */
2604 memcpy(row[DB_serial], serial, strlen(serial));
2605 row[DB_serial][strlen(serial)]='\0';
2608 /* Make it Upper Case */
2609 for (i=0; row[DB_serial][i] != '\0'; i++)
2610 row[DB_serial][i] = toupper(row[DB_serial][i]);
2615 /* Search for the certificate */
2616 rrow=TXT_DB_get_by_index(db,DB_serial,row);
2619 BIO_printf(bio_err,"Serial %s not present in db.\n",
2624 else if (rrow[DB_type][0]=='V')
2626 BIO_printf(bio_err,"%s=Valid (%c)\n",
2627 row[DB_serial], rrow[DB_type][0]);
2630 else if (rrow[DB_type][0]=='R')
2632 BIO_printf(bio_err,"%s=Revoked (%c)\n",
2633 row[DB_serial], rrow[DB_type][0]);
2636 else if (rrow[DB_type][0]=='E')
2638 BIO_printf(bio_err,"%s=Expired (%c)\n",
2639 row[DB_serial], rrow[DB_type][0]);
2642 else if (rrow[DB_type][0]=='S')
2644 BIO_printf(bio_err,"%s=Suspended (%c)\n",
2645 row[DB_serial], rrow[DB_type][0]);
2650 BIO_printf(bio_err,"%s=Unknown (%c).\n",
2651 row[DB_serial], rrow[DB_type][0]);
2655 for (i=0; i<DB_NUMBER; i++)
2658 OPENSSL_free(row[i]);
2663 static int do_updatedb (TXT_DB *db)
2665 ASN1_UTCTIME *a_tm = NULL;
2667 int db_y2k, a_y2k; /* flags = 1 if y >= 2000 */
2668 char **rrow, *a_tm_s;
2670 a_tm = ASN1_UTCTIME_new();
2672 /* get actual time and make a string */
2673 a_tm = X509_gmtime_adj(a_tm, 0);
2674 a_tm_s = (char *) OPENSSL_malloc(a_tm->length+1);
2681 memcpy(a_tm_s, a_tm->data, a_tm->length);
2682 a_tm_s[a_tm->length] = '\0';
2684 if (strncmp(a_tm_s, "49", 2) <= 0)
2689 for (i = 0; i < sk_num(db->data); i++)
2691 rrow = (char **) sk_value(db->data, i);
2693 if (rrow[DB_type][0] == 'V')
2695 /* ignore entries that are not valid */
2696 if (strncmp(rrow[DB_exp_date], "49", 2) <= 0)
2701 if (db_y2k == a_y2k)
2703 /* all on the same y2k side */
2704 if (strcmp(rrow[DB_exp_date], a_tm_s) <= 0)
2706 rrow[DB_type][0] = 'E';
2707 rrow[DB_type][1] = '\0';
2710 BIO_printf(bio_err, "%s=Expired\n",
2714 else if (db_y2k < a_y2k)
2716 rrow[DB_type][0] = 'E';
2717 rrow[DB_type][1] = '\0';
2720 BIO_printf(bio_err, "%s=Expired\n",
2729 ASN1_UTCTIME_free(a_tm);
2730 OPENSSL_free(a_tm_s);
2735 static char *crl_reasons[] = {
2736 /* CRL reason strings */
2740 "affiliationChanged",
2742 "cessationOfOperation",
2745 /* Additional pseudo reasons */
2751 #define NUM_REASONS (sizeof(crl_reasons) / sizeof(char *))
2753 /* Given revocation information convert to a DB string.
2754 * The format of the string is:
2755 * revtime[,reason,extra]. Where 'revtime' is the
2756 * revocation time (the current time). 'reason' is the
2757 * optional CRL reason and 'extra' is any additional
2761 char *make_revocation_str(int rev_type, char *rev_arg)
2763 char *reason = NULL, *other = NULL, *str;
2765 ASN1_UTCTIME *revtm = NULL;
2772 case REV_CRL_REASON:
2773 for (i = 0; i < 8; i++)
2775 if (!strcasecmp(rev_arg, crl_reasons[i]))
2777 reason = crl_reasons[i];
2783 BIO_printf(bio_err, "Unknown CRL reason %s\n", rev_arg);
2789 /* Argument is an OID */
2791 otmp = OBJ_txt2obj(rev_arg, 0);
2792 ASN1_OBJECT_free(otmp);
2796 BIO_printf(bio_err, "Invalid object identifier %s\n", rev_arg);
2800 reason = "holdInstruction";
2804 case REV_KEY_COMPROMISE:
2805 case REV_CA_COMPROMISE:
2807 /* Argument is the key compromise time */
2808 if (!ASN1_GENERALIZEDTIME_set_string(NULL, rev_arg))
2810 BIO_printf(bio_err, "Invalid time format %s. Need YYYYMMDDHHMMSSZ\n", rev_arg);
2814 if (rev_type == REV_KEY_COMPROMISE)
2817 reason = "CAkeyTime";
2823 revtm = X509_gmtime_adj(NULL, 0);
2825 i = revtm->length + 1;
2827 if (reason) i += strlen(reason) + 1;
2828 if (other) i += strlen(other) + 1;
2830 str = OPENSSL_malloc(i);
2832 if (!str) return NULL;
2834 strcpy(str, (char *)revtm->data);
2838 strcat(str, reason);
2845 ASN1_UTCTIME_free(revtm);
2849 /* Convert revocation field to X509_REVOKED entry
2853 * 2 OK and some extensions added (i.e. V2 CRL)
2856 int make_revoked(X509_REVOKED *rev, char *str)
2859 char *rtime_str, *reason_str = NULL, *arg_str = NULL, *p;
2860 int reason_code = -1;
2862 ASN1_OBJECT *hold = NULL;
2863 ASN1_GENERALIZEDTIME *comp_time = NULL;
2864 ASN1_ENUMERATED *rtmp = NULL;
2865 tmp = BUF_strdup(str);
2867 p = strchr(tmp, ',');
2884 if (rev && !ASN1_UTCTIME_set_string(rev->revocationDate, rtime_str))
2886 BIO_printf(bio_err, "invalid revocation date %s\n", rtime_str);
2891 for (i = 0; i < NUM_REASONS; i++)
2893 if(!strcasecmp(reason_str, crl_reasons[i]))
2899 if (reason_code == OCSP_REVOKED_STATUS_NOSTATUS)
2901 BIO_printf(bio_err, "invalid reason code %s\n", reason_str);
2905 if (reason_code == 7)
2906 reason_code = OCSP_REVOKED_STATUS_REMOVEFROMCRL;
2907 else if (reason_code == 8) /* Hold instruction */
2911 BIO_printf(bio_err, "missing hold instruction\n");
2914 reason_code = OCSP_REVOKED_STATUS_CERTIFICATEHOLD;
2915 hold = OBJ_txt2obj(arg_str, 0);
2919 BIO_printf(bio_err, "invalid object identifier %s\n", arg_str);
2923 else if ((reason_code == 9) || (reason_code == 10))
2927 BIO_printf(bio_err, "missing compromised time\n");
2930 comp_time = ASN1_GENERALIZEDTIME_new();
2931 if (!ASN1_GENERALIZEDTIME_set_string(comp_time, arg_str))
2933 BIO_printf(bio_err, "invalid compromised time %s\n", arg_str);
2936 if (reason_code == 9)
2937 reason_code = OCSP_REVOKED_STATUS_KEYCOMPROMISE;
2939 reason_code = OCSP_REVOKED_STATUS_CACOMPROMISE;
2943 if (rev && (reason_code != OCSP_REVOKED_STATUS_NOSTATUS))
2945 rtmp = ASN1_ENUMERATED_new();
2946 if (!rtmp || !ASN1_ENUMERATED_set(rtmp, reason_code))
2948 if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0))
2952 if (rev && comp_time)
2954 if (!X509_REVOKED_add1_ext_i2d(rev, NID_invalidity_date, comp_time, 0, 0))
2959 if (!X509_REVOKED_add1_ext_i2d(rev, NID_hold_instruction_code, hold, 0, 0))
2963 if (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)
2969 if (tmp) OPENSSL_free(tmp);
2970 ASN1_OBJECT_free(hold);
2971 ASN1_GENERALIZEDTIME_free(comp_time);
2972 ASN1_ENUMERATED_free(rtmp);