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> */
66 #include <sys/types.h>
69 #include <openssl/conf.h>
70 #include <openssl/bio.h>
71 #include <openssl/err.h>
72 #include <openssl/bn.h>
73 #include <openssl/txt_db.h>
74 #include <openssl/evp.h>
75 #include <openssl/x509.h>
76 #include <openssl/x509v3.h>
77 #include <openssl/objects.h>
78 #include <openssl/ocsp.h>
79 #include <openssl/pem.h>
80 #include <openssl/engine.h>
83 # ifdef OPENSSL_SYS_VMS
90 # include <sys/file.h>
104 #define BASE_SECTION "ca"
105 #define CONFIG_FILE "openssl.cnf"
107 #define ENV_DEFAULT_CA "default_ca"
109 #define ENV_DIR "dir"
110 #define ENV_CERTS "certs"
111 #define ENV_CRL_DIR "crl_dir"
112 #define ENV_CA_DB "CA_DB"
113 #define ENV_NEW_CERTS_DIR "new_certs_dir"
114 #define ENV_CERTIFICATE "certificate"
115 #define ENV_SERIAL "serial"
116 #define ENV_CRL "crl"
117 #define ENV_PRIVATE_KEY "private_key"
118 #define ENV_RANDFILE "RANDFILE"
119 #define ENV_DEFAULT_DAYS "default_days"
120 #define ENV_DEFAULT_STARTDATE "default_startdate"
121 #define ENV_DEFAULT_ENDDATE "default_enddate"
122 #define ENV_DEFAULT_CRL_DAYS "default_crl_days"
123 #define ENV_DEFAULT_CRL_HOURS "default_crl_hours"
124 #define ENV_DEFAULT_MD "default_md"
125 #define ENV_PRESERVE "preserve"
126 #define ENV_POLICY "policy"
127 #define ENV_EXTENSIONS "x509_extensions"
128 #define ENV_CRLEXT "crl_extensions"
129 #define ENV_MSIE_HACK "msie_hack"
131 #define ENV_DATABASE "database"
134 #define DB_exp_date 1
135 #define DB_rev_date 2
136 #define DB_serial 3 /* index - unique */
138 #define DB_name 5 /* index - unique for active */
141 #define DB_TYPE_REV 'R'
142 #define DB_TYPE_EXP 'E'
143 #define DB_TYPE_VAL 'V'
145 /* Additional revocation information types */
147 #define REV_NONE 0 /* No addditional information */
148 #define REV_CRL_REASON 1 /* Value is CRL reason code */
149 #define REV_HOLD 2 /* Value is hold instruction */
150 #define REV_KEY_COMPROMISE 3 /* Value is cert key compromise time */
151 #define REV_CA_COMPROMISE 4 /* Value is CA key compromise time */
153 static char *ca_usage[]={
156 " -verbose - Talk alot while doing things\n",
157 " -config file - A config file\n",
158 " -name arg - The particular CA definition to use\n",
159 " -gencrl - Generate a new CRL\n",
160 " -crldays days - Days is when the next CRL is due\n",
161 " -crlhours hours - Hours is when the next CRL is due\n",
162 " -startdate YYMMDDHHMMSSZ - certificate validity notBefore\n",
163 " -enddate YYMMDDHHMMSSZ - certificate validity notAfter (overrides -days)\n",
164 " -days arg - number of days to certify the certificate for\n",
165 " -md arg - md to use, one of md2, md5, sha or sha1\n",
166 " -policy arg - The CA 'policy' to support\n",
167 " -keyfile arg - private key file\n",
168 " -keyform arg - private key file format (PEM or ENGINE)\n",
169 " -key arg - key to decode the private key if it is encrypted\n",
170 " -cert file - The CA certificate\n",
171 " -in file - The input PEM encoded certificate request(s)\n",
172 " -out file - Where to put the output file(s)\n",
173 " -outdir dir - Where to put output certificates\n",
174 " -infiles .... - The last argument, requests to process\n",
175 " -spkac file - File contains DN and signed public key and challenge\n",
176 " -ss_cert file - File contains a self signed cert to sign\n",
177 " -preserveDN - Don't re-order the DN\n",
178 " -batch - Don't ask questions\n",
179 " -msie_hack - msie modifications to handle all those universal strings\n",
180 " -revoke file - Revoke a certificate (given in file)\n",
181 " -extensions .. - Extension section (override value in config file)\n",
182 " -extfile file - Configuration file with X509v3 extentions to add\n",
183 " -crlexts .. - CRL extension section (override value in config file)\n",
184 " -engine e - use engine e, possibly a hardware device.\n",
185 " -status serial - Shows certificate status given the serial number\n",
186 " -updatedb - Updates db for expired certificates\n",
191 extern int EF_PROTECT_FREE;
192 extern int EF_PROTECT_BELOW;
193 extern int EF_ALIGNMENT;
196 static void lookup_fail(char *name,char *tag);
197 static unsigned long index_serial_hash(const char **a);
198 static int index_serial_cmp(const char **a, const char **b);
199 static unsigned long index_name_hash(const char **a);
200 static int index_name_qual(char **a);
201 static int index_name_cmp(const char **a,const char **b);
202 static BIGNUM *load_serial(char *serialfile);
203 static int save_serial(char *serialfile, BIGNUM *serial);
204 static int certify(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
205 const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,TXT_DB *db,
206 BIGNUM *serial, char *startdate,char *enddate, int days,
207 int batch, char *ext_sect, LHASH *conf,int verbose);
208 static int certify_cert(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
209 const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
210 TXT_DB *db, BIGNUM *serial,char *startdate,
211 char *enddate, int days, int batch, char *ext_sect,
212 LHASH *conf,int verbose);
213 static int certify_spkac(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, char *ext_sect,LHASH *conf,
218 static int fix_data(int nid, int *type);
219 static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext);
220 static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
221 STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial,
222 char *startdate, char *enddate, int days, int batch, int verbose,
223 X509_REQ *req, char *ext_sect, LHASH *conf);
224 static int do_revoke(X509 *x509, TXT_DB *db, int ext, char *extval);
225 static int get_certificate_status(const char *ser_status, TXT_DB *db);
226 static int do_updatedb(TXT_DB *db);
227 static int check_time_format(char *str);
228 char *make_revocation_str(int rev_type, char *rev_arg);
229 int make_revoked(X509_REVOKED *rev, char *str);
230 static LHASH *conf=NULL;
231 static LHASH *extconf=NULL;
232 static char *section=NULL;
234 static int preserve=0;
235 static int msie_hack=0;
237 static IMPLEMENT_LHASH_HASH_FN(index_serial_hash,const char **)
238 static IMPLEMENT_LHASH_COMP_FN(index_serial_cmp,const char **)
239 static IMPLEMENT_LHASH_HASH_FN(index_name_hash,const char **)
240 static IMPLEMENT_LHASH_COMP_FN(index_name_cmp,const char **)
243 int MAIN(int, char **);
245 int MAIN(int argc, char **argv)
248 char *key=NULL,*passargin=NULL;
261 char *configfile=NULL;
266 int keyform=FORMAT_PEM;
268 char *spkac_file=NULL;
269 char *ss_cert_file=NULL;
270 char *ser_status=NULL;
275 char *serialfile=NULL;
276 char *extensions=NULL;
279 int rev_type = REV_NONE;
280 char *rev_arg = NULL;
282 char *startdate=NULL;
289 BIO *in=NULL,*out=NULL,*Sout=NULL,*Cout=NULL;
293 X509_CRL_INFO *ci=NULL;
294 X509_REVOKED *r=NULL;
298 const EVP_MD *dgst=NULL;
299 STACK_OF(CONF_VALUE) *attribs=NULL;
300 STACK_OF(X509) *cert_sk=NULL;
303 MS_STATIC char buf[3][BSIZE];
322 if ((bio_err=BIO_new(BIO_s_file())) != NULL)
323 BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
329 if (strcmp(*argv,"-verbose") == 0)
331 else if (strcmp(*argv,"-config") == 0)
333 if (--argc < 1) goto bad;
334 configfile= *(++argv);
336 else if (strcmp(*argv,"-name") == 0)
338 if (--argc < 1) goto bad;
341 else if (strcmp(*argv,"-startdate") == 0)
343 if (--argc < 1) goto bad;
344 startdate= *(++argv);
346 else if (strcmp(*argv,"-enddate") == 0)
348 if (--argc < 1) goto bad;
351 else if (strcmp(*argv,"-days") == 0)
353 if (--argc < 1) goto bad;
354 days=atoi(*(++argv));
356 else if (strcmp(*argv,"-md") == 0)
358 if (--argc < 1) goto bad;
361 else if (strcmp(*argv,"-policy") == 0)
363 if (--argc < 1) goto bad;
366 else if (strcmp(*argv,"-keyfile") == 0)
368 if (--argc < 1) goto bad;
371 else if (strcmp(*argv,"-keyform") == 0)
373 if (--argc < 1) goto bad;
374 keyform=str2fmt(*(++argv));
376 else if (strcmp(*argv,"-passin") == 0)
378 if (--argc < 1) goto bad;
379 passargin= *(++argv);
381 else if (strcmp(*argv,"-key") == 0)
383 if (--argc < 1) goto bad;
386 else if (strcmp(*argv,"-cert") == 0)
388 if (--argc < 1) goto bad;
391 else if (strcmp(*argv,"-in") == 0)
393 if (--argc < 1) goto bad;
397 else if (strcmp(*argv,"-out") == 0)
399 if (--argc < 1) goto bad;
402 else if (strcmp(*argv,"-outdir") == 0)
404 if (--argc < 1) goto bad;
407 else if (strcmp(*argv,"-notext") == 0)
409 else if (strcmp(*argv,"-batch") == 0)
411 else if (strcmp(*argv,"-preserveDN") == 0)
413 else if (strcmp(*argv,"-gencrl") == 0)
415 else if (strcmp(*argv,"-msie_hack") == 0)
417 else if (strcmp(*argv,"-crldays") == 0)
419 if (--argc < 1) goto bad;
420 crldays= atol(*(++argv));
422 else if (strcmp(*argv,"-crlhours") == 0)
424 if (--argc < 1) goto bad;
425 crlhours= atol(*(++argv));
427 else if (strcmp(*argv,"-infiles") == 0)
434 else if (strcmp(*argv, "-ss_cert") == 0)
436 if (--argc < 1) goto bad;
437 ss_cert_file = *(++argv);
440 else if (strcmp(*argv, "-spkac") == 0)
442 if (--argc < 1) goto bad;
443 spkac_file = *(++argv);
446 else if (strcmp(*argv,"-revoke") == 0)
448 if (--argc < 1) goto bad;
452 else if (strcmp(*argv,"-extensions") == 0)
454 if (--argc < 1) goto bad;
455 extensions= *(++argv);
457 else if (strcmp(*argv,"-extfile") == 0)
459 if (--argc < 1) goto bad;
462 else if (strcmp(*argv,"-status") == 0)
464 if (--argc < 1) goto bad;
465 ser_status= *(++argv);
467 else if (strcmp(*argv,"-updatedb") == 0)
471 else if (strcmp(*argv,"-crlexts") == 0)
473 if (--argc < 1) goto bad;
476 else if (strcmp(*argv,"-crl_reason") == 0)
478 if (--argc < 1) goto bad;
480 rev_type = REV_CRL_REASON;
482 else if (strcmp(*argv,"-crl_hold") == 0)
484 if (--argc < 1) goto bad;
488 else if (strcmp(*argv,"-crl_compromise") == 0)
490 if (--argc < 1) goto bad;
492 rev_type = REV_KEY_COMPROMISE;
494 else if (strcmp(*argv,"-crl_CA_compromise") == 0)
496 if (--argc < 1) goto bad;
498 rev_type = REV_CA_COMPROMISE;
500 else if (strcmp(*argv,"-engine") == 0)
502 if (--argc < 1) goto bad;
508 BIO_printf(bio_err,"unknown option %s\n",*argv);
518 for (pp=ca_usage; (*pp != NULL); pp++)
519 BIO_printf(bio_err,"%s",*pp);
523 ERR_load_crypto_strings();
527 if ((e = ENGINE_by_id(engine)) == NULL)
529 BIO_printf(bio_err,"invalid engine \"%s\"\n",
533 if (!ENGINE_set_default(e, ENGINE_METHOD_ALL))
535 BIO_printf(bio_err,"can't use that engine\n");
538 BIO_printf(bio_err,"engine \"%s\" set.\n", engine);
539 /* Free our "structural" reference. */
543 /*****************************************************************/
544 if (configfile == NULL) configfile = getenv("OPENSSL_CONF");
545 if (configfile == NULL) configfile = getenv("SSLEAY_CONF");
546 if (configfile == NULL)
548 /* We will just use 'buf[0]' as a temporary buffer. */
549 #ifdef OPENSSL_SYS_VMS
550 strncpy(buf[0],X509_get_default_cert_area(),
551 sizeof(buf[0])-1-sizeof(CONFIG_FILE));
553 strncpy(buf[0],X509_get_default_cert_area(),
554 sizeof(buf[0])-2-sizeof(CONFIG_FILE));
557 strcat(buf[0],CONFIG_FILE);
561 BIO_printf(bio_err,"Using configuration from %s\n",configfile);
562 if ((conf=CONF_load(NULL,configfile,&errorline)) == NULL)
565 BIO_printf(bio_err,"error loading the config file '%s'\n",
568 BIO_printf(bio_err,"error on line %ld of config file '%s'\n"
569 ,errorline,configfile);
573 /* Lets get the config section we are using */
576 section=CONF_get_string(conf,BASE_SECTION,ENV_DEFAULT_CA);
579 lookup_fail(BASE_SECTION,ENV_DEFAULT_CA);
586 p=CONF_get_string(conf,NULL,"oid_file");
593 oid_bio=BIO_new_file(p,"r");
597 BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
598 ERR_print_errors(bio_err);
604 OBJ_create_objects(oid_bio);
608 if (!add_oid_section(bio_err,conf))
610 ERR_print_errors(bio_err);
615 randfile = CONF_get_string(conf, BASE_SECTION, "RANDFILE");
616 if (randfile == NULL)
618 app_RAND_load_file(randfile, bio_err, 0);
620 in=BIO_new(BIO_s_file());
621 out=BIO_new(BIO_s_file());
622 Sout=BIO_new(BIO_s_file());
623 Cout=BIO_new(BIO_s_file());
624 if ((in == NULL) || (out == NULL) || (Sout == NULL) || (Cout == NULL))
626 ERR_print_errors(bio_err);
630 /*****************************************************************/
631 /* report status of cert with serial number given on command line */
634 if ((dbfile=CONF_get_string(conf,section,ENV_DATABASE)) == NULL)
636 lookup_fail(section,ENV_DATABASE);
639 if (BIO_read_filename(in,dbfile) <= 0)
642 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
645 db=TXT_DB_read(in,DB_NUMBER);
646 if (db == NULL) goto err;
648 if (!TXT_DB_create_index(db, DB_serial, NULL,
649 LHASH_HASH_FN(index_serial_hash),
650 LHASH_COMP_FN(index_serial_cmp)))
653 "error creating serial number index:(%ld,%ld,%ld)\n",
654 db->error,db->arg1,db->arg2);
658 if (get_certificate_status(ser_status,db) != 1)
659 BIO_printf(bio_err,"Error verifying serial %s!\n",
664 /*****************************************************************/
665 /* we definitely need a public key, so let's get it */
667 if ((keyfile == NULL) && ((keyfile=CONF_get_string(conf,
668 section,ENV_PRIVATE_KEY)) == NULL))
670 lookup_fail(section,ENV_PRIVATE_KEY);
673 if (!key && !app_passwd(bio_err, passargin, NULL, &key, NULL))
675 BIO_printf(bio_err,"Error getting password\n");
678 if (keyform == FORMAT_ENGINE)
682 BIO_printf(bio_err,"no engine specified\n");
685 pkey = ENGINE_load_private_key(e, keyfile, key);
687 else if (keyform == FORMAT_PEM)
689 if (BIO_read_filename(in,keyfile) <= 0)
692 BIO_printf(bio_err,"trying to load CA private key\n");
695 pkey=PEM_read_bio_PrivateKey(in,NULL,NULL,key);
699 BIO_printf(bio_err,"bad input format specified for key file\n");
702 if (key) memset(key,0,strlen(key));
705 BIO_printf(bio_err,"unable to load CA private key\n");
709 /*****************************************************************/
710 /* we need a certificate */
711 if ((certfile == NULL) && ((certfile=CONF_get_string(conf,
712 section,ENV_CERTIFICATE)) == NULL))
714 lookup_fail(section,ENV_CERTIFICATE);
717 if (BIO_read_filename(in,certfile) <= 0)
720 BIO_printf(bio_err,"trying to load CA certificate\n");
723 x509=PEM_read_bio_X509(in,NULL,NULL,NULL);
726 BIO_printf(bio_err,"unable to load CA certificate\n");
730 if (!X509_check_private_key(x509,pkey))
732 BIO_printf(bio_err,"CA certificate and CA private key do not match\n");
736 f=CONF_get_string(conf,BASE_SECTION,ENV_PRESERVE);
739 if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
741 f=CONF_get_string(conf,BASE_SECTION,ENV_MSIE_HACK);
744 if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
747 /*****************************************************************/
748 /* lookup where to write new certificates */
749 if ((outdir == NULL) && (req))
753 if ((outdir=CONF_get_string(conf,section,ENV_NEW_CERTS_DIR))
756 BIO_printf(bio_err,"there needs to be defined a directory for new certificate to be placed in\n");
759 #ifndef OPENSSL_SYS_VMS
760 /* outdir is a directory spec, but access() for VMS demands a
761 filename. In any case, stat(), below, will catch the problem
762 if outdir is not a directory spec, and the fopen() or open()
763 will catch an error if there is no write access.
765 Presumably, this problem could also be solved by using the DEC
766 C routines to convert the directory syntax to Unixly, and give
767 that to access(). However, time's too short to do that just
770 if (access(outdir,R_OK|W_OK|X_OK) != 0)
772 BIO_printf(bio_err,"I am unable to access the %s directory\n",outdir);
777 if (stat(outdir,&sb) != 0)
779 BIO_printf(bio_err,"unable to stat(%s)\n",outdir);
784 if (!(sb.st_mode & S_IFDIR))
786 BIO_printf(bio_err,"%s need to be a directory\n",outdir);
794 /*****************************************************************/
795 /* we need to load the database file */
796 if ((dbfile=CONF_get_string(conf,section,ENV_DATABASE)) == NULL)
798 lookup_fail(section,ENV_DATABASE);
801 if (BIO_read_filename(in,dbfile) <= 0)
804 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
807 db=TXT_DB_read(in,DB_NUMBER);
808 if (db == NULL) goto err;
810 /* Lets check some fields */
811 for (i=0; i<sk_num(db->data); i++)
813 pp=(char **)sk_value(db->data,i);
814 if ((pp[DB_type][0] != DB_TYPE_REV) &&
815 (pp[DB_rev_date][0] != '\0'))
817 BIO_printf(bio_err,"entry %d: not revoked yet, but has a revocation date\n",i+1);
820 if ((pp[DB_type][0] == DB_TYPE_REV) &&
821 !make_revoked(NULL, pp[DB_rev_date]))
823 BIO_printf(bio_err," in entry %d\n", i+1);
826 if (!check_time_format(pp[DB_exp_date]))
828 BIO_printf(bio_err,"entry %d: invalid expiry date\n",i+1);
838 if ((j&1) || (j < 2))
840 BIO_printf(bio_err,"entry %d: bad serial number length (%d)\n",i+1,j);
845 if (!( ((*p >= '0') && (*p <= '9')) ||
846 ((*p >= 'A') && (*p <= 'F')) ||
847 ((*p >= 'a') && (*p <= 'f'))) )
849 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);
857 BIO_set_fp(out,stdout,BIO_NOCLOSE|BIO_FP_TEXT); /* cannot fail */
858 #ifdef OPENSSL_SYS_VMS
860 BIO *tmpbio = BIO_new(BIO_f_linebuffer());
861 out = BIO_push(tmpbio, out);
864 TXT_DB_write(out,db);
865 BIO_printf(bio_err,"%d entries loaded from the database\n",
867 BIO_printf(bio_err,"generating index\n");
870 if (!TXT_DB_create_index(db, DB_serial, NULL,
871 LHASH_HASH_FN(index_serial_hash),
872 LHASH_COMP_FN(index_serial_cmp)))
874 BIO_printf(bio_err,"error creating serial number index:(%ld,%ld,%ld)\n",db->error,db->arg1,db->arg2);
878 if (!TXT_DB_create_index(db, DB_name, index_name_qual,
879 LHASH_HASH_FN(index_name_hash),
880 LHASH_COMP_FN(index_name_cmp)))
882 BIO_printf(bio_err,"error creating name index:(%ld,%ld,%ld)\n",
883 db->error,db->arg1,db->arg2);
887 /*****************************************************************/
888 /* Update the db file for expired certificates */
892 BIO_printf(bio_err, "Updating %s ...\n",
898 BIO_printf(bio_err,"Malloc failure\n");
903 if (verbose) BIO_printf(bio_err,
904 "No entries found to mark expired\n");
908 out = BIO_new(BIO_s_file());
911 ERR_print_errors(bio_err);
915 j = BIO_snprintf(buf[0], sizeof buf[0], "%s.new", dbfile);
916 if (j < 0 || j >= sizeof buf[0])
918 BIO_printf(bio_err, "file name too long\n");
921 if (BIO_write_filename(out,buf[0]) <= 0)
924 BIO_printf(bio_err,"unable to open '%s'\n",
928 j=TXT_DB_write(out,db);
929 if (j <= 0) goto err;
933 j = BIO_snprintf(buf[1], sizeof buf[1], "%s.old", dbfile);
934 if (j < 0 || j >= sizeof buf[1])
936 BIO_printf(bio_err, "file name too long\n");
939 if (rename(dbfile,buf[1]) < 0)
942 "unable to rename %s to %s\n",
947 if (rename(buf[0],dbfile) < 0)
950 "unable to rename %s to %s\n",
953 rename(buf[1],dbfile);
957 if (verbose) BIO_printf(bio_err,
958 "Done. %d entries marked as expired\n",i);
963 /*****************************************************************/
964 /* Read extentions config file */
967 if (!(extconf=CONF_load(NULL,extfile,&errorline)))
970 BIO_printf(bio_err, "ERROR: loading the config file '%s'\n",
973 BIO_printf(bio_err, "ERROR: on line %ld of config file '%s'\n",
980 BIO_printf(bio_err, "Succesfully loaded extensions file %s\n", extfile);
982 /* We can have sections in the ext file */
983 if (!extensions && !(extensions = CONF_get_string(extconf, "default", "extensions")))
984 extensions = "default";
987 /*****************************************************************/
992 if (BIO_write_filename(Sout,outfile) <= 0)
1000 BIO_set_fp(Sout,stdout,BIO_NOCLOSE|BIO_FP_TEXT);
1001 #ifdef OPENSSL_SYS_VMS
1003 BIO *tmpbio = BIO_new(BIO_f_linebuffer());
1004 Sout = BIO_push(tmpbio, Sout);
1012 if ((md == NULL) && ((md=CONF_get_string(conf,
1013 section,ENV_DEFAULT_MD)) == NULL))
1015 lookup_fail(section,ENV_DEFAULT_MD);
1018 if ((dgst=EVP_get_digestbyname(md)) == NULL)
1020 BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
1024 BIO_printf(bio_err,"message digest is %s\n",
1025 OBJ_nid2ln(dgst->type));
1026 if ((policy == NULL) && ((policy=CONF_get_string(conf,
1027 section,ENV_POLICY)) == NULL))
1029 lookup_fail(section,ENV_POLICY);
1033 BIO_printf(bio_err,"policy is %s\n",policy);
1035 if ((serialfile=CONF_get_string(conf,section,ENV_SERIAL))
1038 lookup_fail(section,ENV_SERIAL);
1044 /* no '-extfile' option, so we look for extensions
1045 * in the main configuration file */
1048 extensions=CONF_get_string(conf,section,
1055 /* Check syntax of file */
1057 X509V3_set_ctx_test(&ctx);
1058 X509V3_set_conf_lhash(&ctx, conf);
1059 if (!X509V3_EXT_add_conf(conf, &ctx, extensions,
1063 "Error Loading extension section %s\n",
1071 if (startdate == NULL)
1073 startdate=CONF_get_string(conf,section,
1074 ENV_DEFAULT_STARTDATE);
1075 if (startdate == NULL)
1078 if (startdate && !ASN1_UTCTIME_set_string(NULL,startdate))
1080 BIO_printf(bio_err,"start date is invalid, it should be YYMMDDHHMMSSZ\n");
1083 if (startdate == NULL) startdate="today";
1085 if (enddate == NULL)
1087 enddate=CONF_get_string(conf,section,
1088 ENV_DEFAULT_ENDDATE);
1089 if (enddate == NULL)
1092 if (enddate && !ASN1_UTCTIME_set_string(NULL,enddate))
1094 BIO_printf(bio_err,"end date is invalid, it should be YYMMDDHHMMSSZ\n");
1100 days=(int)CONF_get_number(conf,section,
1103 if (!enddate && (days == 0))
1105 BIO_printf(bio_err,"cannot lookup how many days to certify for\n");
1109 if ((serial=load_serial(serialfile)) == NULL)
1111 BIO_printf(bio_err,"error while loading serial number\n");
1116 if ((f=BN_bn2hex(serial)) == NULL) goto err;
1117 BIO_printf(bio_err,"next serial number is %s\n",f);
1121 if ((attribs=CONF_get_section(conf,policy)) == NULL)
1123 BIO_printf(bio_err,"unable to find 'section' for %s\n",policy);
1127 if ((cert_sk=sk_X509_new_null()) == NULL)
1129 BIO_printf(bio_err,"Memory allocation failure\n");
1132 if (spkac_file != NULL)
1135 j=certify_spkac(&x,spkac_file,pkey,x509,dgst,attribs,db,
1136 serial,startdate,enddate, days,extensions,conf,
1138 if (j < 0) goto err;
1142 BIO_printf(bio_err,"\n");
1143 if (!BN_add_word(serial,1)) goto err;
1144 if (!sk_X509_push(cert_sk,x))
1146 BIO_printf(bio_err,"Memory allocation failure\n");
1156 if (ss_cert_file != NULL)
1159 j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,attribs,
1160 db,serial,startdate,enddate,days,batch,
1161 extensions,conf,verbose);
1162 if (j < 0) goto err;
1166 BIO_printf(bio_err,"\n");
1167 if (!BN_add_word(serial,1)) goto err;
1168 if (!sk_X509_push(cert_sk,x))
1170 BIO_printf(bio_err,"Memory allocation failure\n");
1178 j=certify(&x,infile,pkey,x509,dgst,attribs,db,
1179 serial,startdate,enddate,days,batch,
1180 extensions,conf,verbose);
1181 if (j < 0) goto err;
1185 BIO_printf(bio_err,"\n");
1186 if (!BN_add_word(serial,1)) goto err;
1187 if (!sk_X509_push(cert_sk,x))
1189 BIO_printf(bio_err,"Memory allocation failure\n");
1194 for (i=0; i<argc; i++)
1197 j=certify(&x,argv[i],pkey,x509,dgst,attribs,db,
1198 serial,startdate,enddate,days,batch,
1199 extensions,conf,verbose);
1200 if (j < 0) goto err;
1204 BIO_printf(bio_err,"\n");
1205 if (!BN_add_word(serial,1)) goto err;
1206 if (!sk_X509_push(cert_sk,x))
1208 BIO_printf(bio_err,"Memory allocation failure\n");
1213 /* we have a stack of newly certified certificates
1214 * and a data base and serial number that need
1217 if (sk_X509_num(cert_sk) > 0)
1221 BIO_printf(bio_err,"\n%d out of %d certificate requests certified, commit? [y/n]",total_done,total);
1222 (void)BIO_flush(bio_err);
1224 fgets(buf[0],10,stdin);
1225 if ((buf[0][0] != 'y') && (buf[0][0] != 'Y'))
1227 BIO_printf(bio_err,"CERTIFICATION CANCELED\n");
1233 BIO_printf(bio_err,"Write out database with %d new entries\n",sk_X509_num(cert_sk));
1235 strncpy(buf[0],serialfile,BSIZE-4);
1237 #ifdef OPENSSL_SYS_VMS
1238 strcat(buf[0],"-new");
1240 strcat(buf[0],".new");
1243 if (!save_serial(buf[0],serial)) goto err;
1245 strncpy(buf[1],dbfile,BSIZE-4);
1247 #ifdef OPENSSL_SYS_VMS
1248 strcat(buf[1],"-new");
1250 strcat(buf[1],".new");
1253 if (BIO_write_filename(out,buf[1]) <= 0)
1256 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
1259 l=TXT_DB_write(out,db);
1260 if (l <= 0) goto err;
1264 BIO_printf(bio_err,"writing new certificates\n");
1265 for (i=0; i<sk_X509_num(cert_sk); i++)
1270 x=sk_X509_value(cert_sk,i);
1272 j=x->cert_info->serialNumber->length;
1273 p=(char *)x->cert_info->serialNumber->data;
1275 strncpy(buf[2],outdir,BSIZE-(j*2)-6);
1277 #ifndef OPENSSL_SYS_VMS
1281 n=(unsigned char *)&(buf[2][strlen(buf[2])]);
1286 sprintf((char *)n,"%02X",(unsigned char)*(p++));
1295 *(n++)='.'; *(n++)='p'; *(n++)='e'; *(n++)='m';
1298 BIO_printf(bio_err,"writing %s\n",buf[2]);
1300 if (BIO_write_filename(Cout,buf[2]) <= 0)
1305 write_new_certificate(Cout,x, 0, notext);
1306 write_new_certificate(Sout,x, output_der, notext);
1309 if (sk_X509_num(cert_sk))
1311 /* Rename the database and the serial file */
1312 strncpy(buf[2],serialfile,BSIZE-4);
1314 #ifdef OPENSSL_SYS_VMS
1315 strcat(buf[2],"-old");
1317 strcat(buf[2],".old");
1324 if (rename(serialfile,buf[2]) < 0)
1326 BIO_printf(bio_err,"unable to rename %s to %s\n",
1331 if (rename(buf[0],serialfile) < 0)
1333 BIO_printf(bio_err,"unable to rename %s to %s\n",
1336 rename(buf[2],serialfile);
1340 strncpy(buf[2],dbfile,BSIZE-4);
1342 #ifdef OPENSSL_SYS_VMS
1343 strcat(buf[2],"-old");
1345 strcat(buf[2],".old");
1348 if (rename(dbfile,buf[2]) < 0)
1350 BIO_printf(bio_err,"unable to rename %s to %s\n",
1355 if (rename(buf[1],dbfile) < 0)
1357 BIO_printf(bio_err,"unable to rename %s to %s\n",
1360 rename(buf[2],dbfile);
1363 BIO_printf(bio_err,"Data Base Updated\n");
1367 /*****************************************************************/
1373 crl_ext=CONF_get_string(conf,section,ENV_CRLEXT);
1379 /* Check syntax of file */
1381 X509V3_set_ctx_test(&ctx);
1382 X509V3_set_conf_lhash(&ctx, conf);
1383 if (!X509V3_EXT_add_conf(conf, &ctx, crl_ext, NULL))
1386 "Error Loading CRL extension section %s\n",
1393 if (!crldays && !crlhours)
1395 crldays=CONF_get_number(conf,section,
1396 ENV_DEFAULT_CRL_DAYS);
1397 crlhours=CONF_get_number(conf,section,
1398 ENV_DEFAULT_CRL_HOURS);
1400 if ((crldays == 0) && (crlhours == 0))
1402 BIO_printf(bio_err,"cannot lookup how long until the next CRL is issuer\n");
1406 if (verbose) BIO_printf(bio_err,"making CRL\n");
1407 if ((crl=X509_CRL_new()) == NULL) goto err;
1409 X509_NAME_free(ci->issuer);
1410 ci->issuer=X509_NAME_dup(x509->cert_info->subject);
1411 if (ci->issuer == NULL) goto err;
1413 X509_gmtime_adj(ci->lastUpdate,0);
1414 if (ci->nextUpdate == NULL)
1415 ci->nextUpdate=ASN1_UTCTIME_new();
1416 X509_gmtime_adj(ci->nextUpdate,(crldays*24+crlhours)*60*60);
1418 for (i=0; i<sk_num(db->data); i++)
1420 pp=(char **)sk_value(db->data,i);
1421 if (pp[DB_type][0] == DB_TYPE_REV)
1423 if ((r=X509_REVOKED_new()) == NULL) goto err;
1424 j = make_revoked(r, pp[DB_rev_date]);
1426 if (j == 2) crl_v2 = 1;
1427 if (!BN_hex2bn(&serial, pp[DB_serial]))
1429 r->serialNumber = BN_to_ASN1_INTEGER(serial, r->serialNumber);
1432 if (!r->serialNumber)
1434 X509_CRL_add0_revoked(crl,r);
1437 /* sort the data so it will be written in serial
1439 sk_X509_REVOKED_sort(ci->revoked);
1440 for (i=0; i<sk_X509_REVOKED_num(ci->revoked); i++)
1442 r=sk_X509_REVOKED_value(ci->revoked,i);
1446 /* we now have a CRL */
1447 if (verbose) BIO_printf(bio_err,"signing CRL\n");
1450 if ((dgst=EVP_get_digestbyname(md)) == NULL)
1452 BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
1458 #ifndef OPENSSL_NO_DSA
1459 if (pkey->type == EVP_PKEY_DSA)
1466 /* Add any extensions asked for */
1471 if (ci->version == NULL)
1472 if ((ci->version=ASN1_INTEGER_new()) == NULL) goto err;
1473 X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0);
1474 X509V3_set_conf_lhash(&crlctx, conf);
1476 if (!X509V3_EXT_CRL_add_conf(conf, &crlctx,
1477 crl_ext, crl)) goto err;
1479 if (crl_ext || crl_v2)
1481 if (ci->version == NULL)
1482 if ((ci->version=ASN1_INTEGER_new()) == NULL) goto err;
1483 ASN1_INTEGER_set(ci->version,1); /* version 2 CRL */
1486 if (!X509_CRL_sign(crl,pkey,dgst)) goto err;
1488 PEM_write_bio_X509_CRL(Sout,crl);
1490 /*****************************************************************/
1495 BIO_printf(bio_err,"no input files\n");
1501 if (BIO_read_filename(in,infile) <= 0)
1504 BIO_printf(bio_err,"error trying to load '%s' certificate\n",infile);
1507 revcert=PEM_read_bio_X509(in,NULL,NULL,NULL);
1508 if (revcert == NULL)
1510 BIO_printf(bio_err,"unable to load '%s' certificate\n",infile);
1513 j=do_revoke(revcert,db, rev_type, rev_arg);
1514 if (j <= 0) goto err;
1517 strncpy(buf[0],dbfile,BSIZE-4);
1518 strcat(buf[0],".new");
1519 if (BIO_write_filename(out,buf[0]) <= 0)
1522 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
1525 j=TXT_DB_write(out,db);
1526 if (j <= 0) goto err;
1527 strncpy(buf[1],dbfile,BSIZE-4);
1528 strcat(buf[1],".old");
1529 if (rename(dbfile,buf[1]) < 0)
1531 BIO_printf(bio_err,"unable to rename %s to %s\n", dbfile, buf[1]);
1535 if (rename(buf[0],dbfile) < 0)
1537 BIO_printf(bio_err,"unable to rename %s to %s\n", buf[0],dbfile);
1539 rename(buf[1],dbfile);
1542 BIO_printf(bio_err,"Data Base Updated\n");
1545 /*****************************************************************/
1553 sk_X509_pop_free(cert_sk,X509_free);
1555 if (ret) ERR_print_errors(bio_err);
1556 app_RAND_write_file(randfile, bio_err);
1559 EVP_PKEY_free(pkey);
1567 static void lookup_fail(char *name, char *tag)
1569 BIO_printf(bio_err,"variable lookup failed for %s::%s\n",name,tag);
1572 static unsigned long index_serial_hash(const char **a)
1577 while (*n == '0') n++;
1578 return(lh_strhash(n));
1581 static int index_serial_cmp(const char **a, const char **b)
1585 for (aa=a[DB_serial]; *aa == '0'; aa++);
1586 for (bb=b[DB_serial]; *bb == '0'; bb++);
1587 return(strcmp(aa,bb));
1590 static unsigned long index_name_hash(const char **a)
1591 { return(lh_strhash(a[DB_name])); }
1593 static int index_name_qual(char **a)
1594 { return(a[0][0] == 'V'); }
1596 static int index_name_cmp(const char **a, const char **b)
1597 { return(strcmp(a[DB_name],
1600 static BIGNUM *load_serial(char *serialfile)
1604 MS_STATIC char buf[1024];
1605 ASN1_INTEGER *ai=NULL;
1607 if ((in=BIO_new(BIO_s_file())) == NULL)
1609 ERR_print_errors(bio_err);
1613 if (BIO_read_filename(in,serialfile) <= 0)
1618 ai=ASN1_INTEGER_new();
1619 if (ai == NULL) goto err;
1620 if (!a2i_ASN1_INTEGER(in,ai,buf,1024))
1622 BIO_printf(bio_err,"unable to load number from %s\n",
1626 ret=ASN1_INTEGER_to_BN(ai,NULL);
1629 BIO_printf(bio_err,"error converting number from bin to BIGNUM");
1633 if (in != NULL) BIO_free(in);
1634 if (ai != NULL) ASN1_INTEGER_free(ai);
1638 static int save_serial(char *serialfile, BIGNUM *serial)
1642 ASN1_INTEGER *ai=NULL;
1644 out=BIO_new(BIO_s_file());
1647 ERR_print_errors(bio_err);
1650 if (BIO_write_filename(out,serialfile) <= 0)
1656 if ((ai=BN_to_ASN1_INTEGER(serial,NULL)) == NULL)
1658 BIO_printf(bio_err,"error converting serial to ASN.1 format\n");
1661 i2a_ASN1_INTEGER(out,ai);
1665 if (out != NULL) BIO_free_all(out);
1666 if (ai != NULL) ASN1_INTEGER_free(ai);
1670 static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1671 const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
1672 BIGNUM *serial, char *startdate, char *enddate, int days,
1673 int batch, char *ext_sect, LHASH *lconf, int verbose)
1677 EVP_PKEY *pktmp=NULL;
1680 in=BIO_new(BIO_s_file());
1682 if (BIO_read_filename(in,infile) <= 0)
1687 if ((req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL)) == NULL)
1689 BIO_printf(bio_err,"Error reading certificate request in %s\n",
1694 X509_REQ_print(bio_err,req);
1696 BIO_printf(bio_err,"Check that the request matches the signature\n");
1698 if ((pktmp=X509_REQ_get_pubkey(req)) == NULL)
1700 BIO_printf(bio_err,"error unpacking public key\n");
1703 i=X509_REQ_verify(req,pktmp);
1704 EVP_PKEY_free(pktmp);
1708 BIO_printf(bio_err,"Signature verification problems....\n");
1714 BIO_printf(bio_err,"Signature did not match the certificate request\n");
1718 BIO_printf(bio_err,"Signature ok\n");
1720 ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate, enddate,
1721 days,batch,verbose,req,ext_sect,lconf);
1724 if (req != NULL) X509_REQ_free(req);
1725 if (in != NULL) BIO_free(in);
1729 static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1730 const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
1731 BIGNUM *serial, char *startdate, char *enddate, int days,
1732 int batch, char *ext_sect, LHASH *lconf, int verbose)
1735 X509_REQ *rreq=NULL;
1737 EVP_PKEY *pktmp=NULL;
1740 in=BIO_new(BIO_s_file());
1742 if (BIO_read_filename(in,infile) <= 0)
1747 if ((req=PEM_read_bio_X509(in,NULL,NULL,NULL)) == NULL)
1749 BIO_printf(bio_err,"Error reading self signed certificate in %s\n",infile);
1753 X509_print(bio_err,req);
1755 BIO_printf(bio_err,"Check that the request matches the signature\n");
1757 if ((pktmp=X509_get_pubkey(req)) == NULL)
1759 BIO_printf(bio_err,"error unpacking public key\n");
1762 i=X509_verify(req,pktmp);
1763 EVP_PKEY_free(pktmp);
1767 BIO_printf(bio_err,"Signature verification problems....\n");
1773 BIO_printf(bio_err,"Signature did not match the certificate\n");
1777 BIO_printf(bio_err,"Signature ok\n");
1779 if ((rreq=X509_to_X509_REQ(req,NULL,EVP_md5())) == NULL)
1782 ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,enddate,days,
1783 batch,verbose,rreq,ext_sect,lconf);
1786 if (rreq != NULL) X509_REQ_free(rreq);
1787 if (req != NULL) X509_free(req);
1788 if (in != NULL) BIO_free(in);
1792 static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
1793 STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial,
1794 char *startdate, char *enddate, int days, int batch, int verbose,
1795 X509_REQ *req, char *ext_sect, LHASH *lconf)
1797 X509_NAME *name=NULL,*CAname=NULL,*subject=NULL;
1798 ASN1_UTCTIME *tm,*tmptm;
1799 ASN1_STRING *str,*str2;
1803 X509_NAME_ENTRY *ne;
1804 X509_NAME_ENTRY *tne,*push;
1806 int ok= -1,i,j,last,nid;
1809 char *row[DB_NUMBER],**rrow,**irow=NULL;
1812 tmptm=ASN1_UTCTIME_new();
1815 BIO_printf(bio_err,"malloc error\n");
1819 for (i=0; i<DB_NUMBER; i++)
1822 BIO_printf(bio_err,"The Subjects Distinguished Name is as follows\n");
1823 name=X509_REQ_get_subject_name(req);
1824 for (i=0; i<X509_NAME_entry_count(name); i++)
1826 ne=(X509_NAME_ENTRY *)X509_NAME_get_entry(name,i);
1827 obj=X509_NAME_ENTRY_get_object(ne);
1828 j=i2a_ASN1_OBJECT(bio_err,obj);
1829 str=X509_NAME_ENTRY_get_data(ne);
1831 for (j=22-j; j>0; j--)
1835 BIO_puts(bio_err,buf);
1839 /* assume all type should be strings */
1840 nid=OBJ_obj2nid(ne->object);
1842 if (str->type == V_ASN1_UNIVERSALSTRING)
1843 ASN1_UNIVERSALSTRING_to_string(str);
1845 if ((str->type == V_ASN1_IA5STRING) &&
1846 (nid != NID_pkcs9_emailAddress))
1847 str->type=V_ASN1_T61STRING;
1849 if ((nid == NID_pkcs9_emailAddress) &&
1850 (str->type == V_ASN1_PRINTABLESTRING))
1851 str->type=V_ASN1_IA5STRING;
1854 if (str->type == V_ASN1_PRINTABLESTRING)
1855 BIO_printf(bio_err,"PRINTABLE:'");
1856 else if (str->type == V_ASN1_T61STRING)
1857 BIO_printf(bio_err,"T61STRING:'");
1858 else if (str->type == V_ASN1_IA5STRING)
1859 BIO_printf(bio_err,"IA5STRING:'");
1860 else if (str->type == V_ASN1_UNIVERSALSTRING)
1861 BIO_printf(bio_err,"UNIVERSALSTRING:'");
1863 BIO_printf(bio_err,"ASN.1 %2d:'",str->type);
1865 /* check some things */
1866 if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) &&
1867 (str->type != V_ASN1_IA5STRING))
1869 BIO_printf(bio_err,"\nemailAddress type needs to be of type IA5STRING\n");
1872 j=ASN1_PRINTABLE_type(str->data,str->length);
1873 if ( ((j == V_ASN1_T61STRING) &&
1874 (str->type != V_ASN1_T61STRING)) ||
1875 ((j == V_ASN1_IA5STRING) &&
1876 (str->type == V_ASN1_PRINTABLESTRING)))
1878 BIO_printf(bio_err,"\nThe string contains characters that are illegal for the ASN.1 type\n");
1882 p=(char *)str->data;
1883 for (j=str->length; j>0; j--)
1885 if ((*p >= ' ') && (*p <= '~'))
1886 BIO_printf(bio_err,"%c",*p);
1888 BIO_printf(bio_err,"\\0x%02X",*p);
1889 else if ((unsigned char)*p == 0xf7)
1890 BIO_printf(bio_err,"^?");
1891 else BIO_printf(bio_err,"^%c",*p+'@');
1894 BIO_printf(bio_err,"'\n");
1897 /* Ok, now we check the 'policy' stuff. */
1898 if ((subject=X509_NAME_new()) == NULL)
1900 BIO_printf(bio_err,"Memory allocation failure\n");
1904 /* take a copy of the issuer name before we mess with it. */
1905 CAname=X509_NAME_dup(x509->cert_info->subject);
1906 if (CAname == NULL) goto err;
1909 for (i=0; i<sk_CONF_VALUE_num(policy); i++)
1911 cv=sk_CONF_VALUE_value(policy,i); /* get the object id */
1912 if ((j=OBJ_txt2nid(cv->name)) == NID_undef)
1914 BIO_printf(bio_err,"%s:unknown object type in 'policy' configuration\n",cv->name);
1922 /* lookup the object in the supplied name list */
1923 j=X509_NAME_get_index_by_OBJ(name,obj,last);
1926 if (last != -1) break;
1931 tne=X509_NAME_get_entry(name,j);
1935 /* depending on the 'policy', decide what to do. */
1937 if (strcmp(cv->value,"optional") == 0)
1942 else if (strcmp(cv->value,"supplied") == 0)
1946 BIO_printf(bio_err,"The %s field needed to be supplied and was missing\n",cv->name);
1952 else if (strcmp(cv->value,"match") == 0)
1958 BIO_printf(bio_err,"The mandatory %s field was missing\n",cv->name);
1965 j=X509_NAME_get_index_by_OBJ(CAname,obj,last2);
1966 if ((j < 0) && (last2 == -1))
1968 BIO_printf(bio_err,"The %s field does not exist in the CA certificate,\nthe 'policy' is misconfigured\n",cv->name);
1973 push=X509_NAME_get_entry(CAname,j);
1974 str=X509_NAME_ENTRY_get_data(tne);
1975 str2=X509_NAME_ENTRY_get_data(push);
1977 if (ASN1_STRING_cmp(str,str2) != 0)
1982 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));
1988 BIO_printf(bio_err,"%s:invalid type in 'policy' configuration\n",cv->value);
1994 if (!X509_NAME_add_entry(subject,push, -1, 0))
1997 X509_NAME_ENTRY_free(push);
1998 BIO_printf(bio_err,"Memory allocation failure\n");
2008 X509_NAME_free(subject);
2009 subject=X509_NAME_dup(X509_REQ_get_subject_name(req));
2010 if (subject == NULL) goto err;
2014 BIO_printf(bio_err,"The subject name appears to be ok, checking data base for clashes\n");
2016 row[DB_name]=X509_NAME_oneline(subject,NULL,0);
2017 row[DB_serial]=BN_bn2hex(serial);
2018 if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
2020 BIO_printf(bio_err,"Memory allocation failure\n");
2024 rrow=TXT_DB_get_by_index(db,DB_name,row);
2027 BIO_printf(bio_err,"ERROR:There is already a certificate for %s\n",
2032 rrow=TXT_DB_get_by_index(db,DB_serial,row);
2035 BIO_printf(bio_err,"ERROR:Serial number %s has already been issued,\n",
2037 BIO_printf(bio_err," check the database/serial_file for corruption\n");
2044 "The matching entry has the following details\n");
2045 if (rrow[DB_type][0] == 'E')
2047 else if (rrow[DB_type][0] == 'R')
2049 else if (rrow[DB_type][0] == 'V')
2052 p="\ninvalid type, Data base error\n";
2053 BIO_printf(bio_err,"Type :%s\n",p);;
2054 if (rrow[DB_type][0] == 'R')
2056 p=rrow[DB_exp_date]; if (p == NULL) p="undef";
2057 BIO_printf(bio_err,"Was revoked on:%s\n",p);
2059 p=rrow[DB_exp_date]; if (p == NULL) p="undef";
2060 BIO_printf(bio_err,"Expires on :%s\n",p);
2061 p=rrow[DB_serial]; if (p == NULL) p="undef";
2062 BIO_printf(bio_err,"Serial Number :%s\n",p);
2063 p=rrow[DB_file]; if (p == NULL) p="undef";
2064 BIO_printf(bio_err,"File name :%s\n",p);
2065 p=rrow[DB_name]; if (p == NULL) p="undef";
2066 BIO_printf(bio_err,"Subject Name :%s\n",p);
2067 ok= -1; /* This is now a 'bad' error. */
2071 /* We are now totally happy, lets make and sign the certificate */
2073 BIO_printf(bio_err,"Everything appears to be ok, creating and signing the certificate\n");
2075 if ((ret=X509_new()) == NULL) goto err;
2079 /* Make it an X509 v3 certificate. */
2080 if (!X509_set_version(x509,2)) goto err;
2083 if (BN_to_ASN1_INTEGER(serial,ci->serialNumber) == NULL)
2085 if (!X509_set_issuer_name(ret,X509_get_subject_name(x509)))
2088 BIO_printf(bio_err,"Certificate is to be certified until ");
2089 if (strcmp(startdate,"today") == 0)
2090 X509_gmtime_adj(X509_get_notBefore(ret),0);
2091 else ASN1_UTCTIME_set_string(X509_get_notBefore(ret),startdate);
2093 if (enddate == NULL)
2094 X509_gmtime_adj(X509_get_notAfter(ret),(long)60*60*24*days);
2095 else ASN1_UTCTIME_set_string(X509_get_notAfter(ret),enddate);
2097 ASN1_UTCTIME_print(bio_err,X509_get_notAfter(ret));
2098 if (days) BIO_printf(bio_err," (%d days)",days);
2099 BIO_printf(bio_err, "\n");
2101 if (!X509_set_subject_name(ret,subject)) goto err;
2103 pktmp=X509_REQ_get_pubkey(req);
2104 i = X509_set_pubkey(ret,pktmp);
2105 EVP_PKEY_free(pktmp);
2108 /* Lets add the extensions, if there are any */
2112 if (ci->version == NULL)
2113 if ((ci->version=ASN1_INTEGER_new()) == NULL)
2115 ASN1_INTEGER_set(ci->version,2); /* version 3 certificate */
2117 /* Free the current entries if any, there should not
2118 * be any I believe */
2119 if (ci->extensions != NULL)
2120 sk_X509_EXTENSION_pop_free(ci->extensions,
2121 X509_EXTENSION_free);
2123 ci->extensions = NULL;
2125 /* Initialize the context structure */
2126 X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0);
2131 BIO_printf(bio_err, "Extra configuration file found\n");
2133 /* Use the extconf configuration db LHASH */
2134 X509V3_set_conf_lhash(&ctx, extconf);
2136 /* Test the structure (needed?) */
2137 /* X509V3_set_ctx_test(&ctx); */
2139 /* Adds exts contained in the configuration file */
2140 if (!X509V3_EXT_add_conf(extconf, &ctx, ext_sect,ret))
2143 "ERROR: adding extensions in section %s\n",
2145 ERR_print_errors(bio_err);
2149 BIO_printf(bio_err, "Successfully added extensions from file.\n");
2153 /* We found extensions to be set from config file */
2154 X509V3_set_conf_lhash(&ctx, lconf);
2156 if(!X509V3_EXT_add_conf(lconf, &ctx, ext_sect, ret))
2158 BIO_printf(bio_err, "ERROR: adding extensions in section %s\n", ext_sect);
2159 ERR_print_errors(bio_err);
2164 BIO_printf(bio_err, "Successfully added extensions from config\n");
2171 BIO_printf(bio_err,"Sign the certificate? [y/n]:");
2172 (void)BIO_flush(bio_err);
2174 fgets(buf,sizeof(buf)-1,stdin);
2175 if (!((buf[0] == 'y') || (buf[0] == 'Y')))
2177 BIO_printf(bio_err,"CERTIFICATE WILL NOT BE CERTIFIED\n");
2184 #ifndef OPENSSL_NO_DSA
2185 if (pkey->type == EVP_PKEY_DSA) dgst=EVP_dss1();
2186 pktmp=X509_get_pubkey(ret);
2187 if (EVP_PKEY_missing_parameters(pktmp) &&
2188 !EVP_PKEY_missing_parameters(pkey))
2189 EVP_PKEY_copy_parameters(pktmp,pkey);
2190 EVP_PKEY_free(pktmp);
2193 if (!X509_sign(ret,pkey,dgst))
2196 /* We now just add it to the database */
2197 row[DB_type]=(char *)OPENSSL_malloc(2);
2199 tm=X509_get_notAfter(ret);
2200 row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
2201 memcpy(row[DB_exp_date],tm->data,tm->length);
2202 row[DB_exp_date][tm->length]='\0';
2204 row[DB_rev_date]=NULL;
2206 /* row[DB_serial] done already */
2207 row[DB_file]=(char *)OPENSSL_malloc(8);
2208 /* row[DB_name] done already */
2210 if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2211 (row[DB_file] == NULL))
2213 BIO_printf(bio_err,"Memory allocation failure\n");
2216 strcpy(row[DB_file],"unknown");
2217 row[DB_type][0]='V';
2218 row[DB_type][1]='\0';
2220 if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
2222 BIO_printf(bio_err,"Memory allocation failure\n");
2226 for (i=0; i<DB_NUMBER; i++)
2231 irow[DB_NUMBER]=NULL;
2233 if (!TXT_DB_insert(db,irow))
2235 BIO_printf(bio_err,"failed to update database\n");
2236 BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
2241 for (i=0; i<DB_NUMBER; i++)
2242 if (row[i] != NULL) OPENSSL_free(row[i]);
2245 X509_NAME_free(CAname);
2246 if (subject != NULL)
2247 X509_NAME_free(subject);
2249 ASN1_UTCTIME_free(tmptm);
2252 if (ret != NULL) X509_free(ret);
2260 static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext)
2265 (void)i2d_X509_bio(bp,x);
2269 /* ??? Not needed since X509_print prints all this stuff anyway */
2270 f=X509_NAME_oneline(X509_get_issuer_name(x),buf,256);
2271 BIO_printf(bp,"issuer :%s\n",f);
2273 f=X509_NAME_oneline(X509_get_subject_name(x),buf,256);
2274 BIO_printf(bp,"subject:%s\n",f);
2276 BIO_puts(bp,"serial :");
2277 i2a_ASN1_INTEGER(bp,x->cert_info->serialNumber);
2278 BIO_puts(bp,"\n\n");
2280 if (!notext)X509_print(bp,x);
2281 PEM_write_bio_X509(bp,x);
2284 static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
2285 const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
2286 BIGNUM *serial, char *startdate, char *enddate, int days,
2287 char *ext_sect, LHASH *lconf, int verbose)
2289 STACK_OF(CONF_VALUE) *sk=NULL;
2292 CONF_VALUE *cv=NULL;
2293 NETSCAPE_SPKI *spki = NULL;
2296 EVP_PKEY *pktmp=NULL;
2298 X509_NAME_ENTRY *ne=NULL;
2304 * Load input file into a hash table. (This is just an easy
2305 * way to read and parse the file, then put it into a convenient
2308 parms=CONF_load(NULL,infile,&errline);
2311 BIO_printf(bio_err,"error on line %ld of %s\n",errline,infile);
2312 ERR_print_errors(bio_err);
2316 sk=CONF_get_section(parms, "default");
2317 if (sk_CONF_VALUE_num(sk) == 0)
2319 BIO_printf(bio_err, "no name/value pairs found in %s\n", infile);
2325 * Now create a dummy X509 request structure. We don't actually
2326 * have an X509 request, but we have many of the components
2327 * (a public key, various DN components). The idea is that we
2328 * put these components into the right X509 request structure
2329 * and we can use the same code as if you had a real X509 request.
2334 ERR_print_errors(bio_err);
2339 * Build up the subject name set.
2346 if (sk_CONF_VALUE_num(sk) <= i) break;
2348 cv=sk_CONF_VALUE_value(sk,i);
2350 /* Skip past any leading X. X: X, etc to allow for
2351 * multiple instances
2353 for (buf = cv->name; *buf ; buf++)
2354 if ((*buf == ':') || (*buf == ',') || (*buf == '.'))
2357 if (*buf) type = buf;
2362 if ((nid=OBJ_txt2nid(type)) == NID_undef)
2364 if (strcmp(type, "SPKAC") == 0)
2366 spki = NETSCAPE_SPKI_b64_decode(cv->value, -1);
2369 BIO_printf(bio_err,"unable to load Netscape SPKAC structure\n");
2370 ERR_print_errors(bio_err);
2377 j=ASN1_PRINTABLE_type((unsigned char *)buf,-1);
2378 if (fix_data(nid, &j) == 0)
2381 "invalid characters in string %s\n",buf);
2385 if ((ne=X509_NAME_ENTRY_create_by_NID(&ne,nid,j,
2386 (unsigned char *)buf,
2387 strlen(buf))) == NULL)
2390 if (!X509_NAME_add_entry(n,ne,-1, 0)) goto err;
2394 BIO_printf(bio_err,"Netscape SPKAC structure not found in %s\n",
2400 * Now extract the key from the SPKI structure.
2403 BIO_printf(bio_err,"Check that the SPKAC request matches the signature\n");
2405 if ((pktmp=NETSCAPE_SPKI_get_pubkey(spki)) == NULL)
2407 BIO_printf(bio_err,"error unpacking SPKAC public key\n");
2411 j = NETSCAPE_SPKI_verify(spki, pktmp);
2414 BIO_printf(bio_err,"signature verification failed on SPKAC public key\n");
2417 BIO_printf(bio_err,"Signature ok\n");
2419 X509_REQ_set_pubkey(req,pktmp);
2420 EVP_PKEY_free(pktmp);
2421 ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,enddate,
2422 days,1,verbose,req,ext_sect,lconf);
2424 if (req != NULL) X509_REQ_free(req);
2425 if (parms != NULL) CONF_free(parms);
2426 if (spki != NULL) NETSCAPE_SPKI_free(spki);
2427 if (ne != NULL) X509_NAME_ENTRY_free(ne);
2432 static int fix_data(int nid, int *type)
2434 if (nid == NID_pkcs9_emailAddress)
2435 *type=V_ASN1_IA5STRING;
2436 if ((nid == NID_commonName) && (*type == V_ASN1_IA5STRING))
2437 *type=V_ASN1_T61STRING;
2438 if ((nid == NID_pkcs9_challengePassword) && (*type == V_ASN1_IA5STRING))
2439 *type=V_ASN1_T61STRING;
2440 if ((nid == NID_pkcs9_unstructuredName) && (*type == V_ASN1_T61STRING))
2442 if (nid == NID_pkcs9_unstructuredName)
2443 *type=V_ASN1_IA5STRING;
2447 static int check_time_format(char *str)
2451 tm.data=(unsigned char *)str;
2452 tm.length=strlen(str);
2453 tm.type=V_ASN1_UTCTIME;
2454 return(ASN1_UTCTIME_check(&tm));
2457 static int do_revoke(X509 *x509, TXT_DB *db, int type, char *value)
2459 ASN1_UTCTIME *tm=NULL;
2460 char *row[DB_NUMBER],**rrow,**irow;
2461 char *rev_str = NULL;
2465 for (i=0; i<DB_NUMBER; i++)
2467 row[DB_name]=X509_NAME_oneline(X509_get_subject_name(x509),NULL,0);
2468 bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509),NULL);
2469 row[DB_serial]=BN_bn2hex(bn);
2471 if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
2473 BIO_printf(bio_err,"Memory allocation failure\n");
2476 /* We have to lookup by serial number because name lookup
2477 * skips revoked certs
2479 rrow=TXT_DB_get_by_index(db,DB_serial,row);
2482 BIO_printf(bio_err,"Adding Entry to DB for %s\n", row[DB_name]);
2484 /* We now just add it to the database */
2485 row[DB_type]=(char *)OPENSSL_malloc(2);
2487 tm=X509_get_notAfter(x509);
2488 row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
2489 memcpy(row[DB_exp_date],tm->data,tm->length);
2490 row[DB_exp_date][tm->length]='\0';
2492 row[DB_rev_date]=NULL;
2494 /* row[DB_serial] done already */
2495 row[DB_file]=(char *)OPENSSL_malloc(8);
2497 /* row[DB_name] done already */
2499 if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2500 (row[DB_file] == NULL))
2502 BIO_printf(bio_err,"Memory allocation failure\n");
2505 strcpy(row[DB_file],"unknown");
2506 row[DB_type][0]='V';
2507 row[DB_type][1]='\0';
2509 if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
2511 BIO_printf(bio_err,"Memory allocation failure\n");
2515 for (i=0; i<DB_NUMBER; i++)
2520 irow[DB_NUMBER]=NULL;
2522 if (!TXT_DB_insert(db,irow))
2524 BIO_printf(bio_err,"failed to update database\n");
2525 BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
2529 /* Revoke Certificate */
2530 ok = do_revoke(x509,db, type, value);
2535 else if (index_name_cmp((const char **)row,(const char **)rrow))
2537 BIO_printf(bio_err,"ERROR:name does not match %s\n",
2541 else if (rrow[DB_type][0]=='R')
2543 BIO_printf(bio_err,"ERROR:Already revoked, serial number %s\n",
2549 BIO_printf(bio_err,"Revoking Certificate %s.\n", rrow[DB_serial]);
2550 rev_str = make_revocation_str(type, value);
2553 BIO_printf(bio_err, "Error in revocation arguments\n");
2556 rrow[DB_type][0]='R';
2557 rrow[DB_type][1]='\0';
2558 rrow[DB_rev_date] = rev_str;
2562 for (i=0; i<DB_NUMBER; i++)
2565 OPENSSL_free(row[i]);
2570 static int get_certificate_status(const char *serial, TXT_DB *db)
2572 char *row[DB_NUMBER],**rrow;
2575 /* Free Resources */
2576 for (i=0; i<DB_NUMBER; i++)
2579 /* Malloc needed char spaces */
2580 row[DB_serial] = OPENSSL_malloc(strlen(serial) + 2);
2581 if (row[DB_serial] == NULL)
2583 BIO_printf(bio_err,"Malloc failure\n");
2587 if (strlen(serial) % 2)
2589 /* Set the first char to 0 */;
2590 row[DB_serial][0]='0';
2592 /* Copy String from serial to row[DB_serial] */
2593 memcpy(row[DB_serial]+1, serial, strlen(serial));
2594 row[DB_serial][strlen(serial)+1]='\0';
2598 /* Copy String from serial to row[DB_serial] */
2599 memcpy(row[DB_serial], serial, strlen(serial));
2600 row[DB_serial][strlen(serial)]='\0';
2603 /* Make it Upper Case */
2604 for (i=0; row[DB_serial][i] != '\0'; i++)
2605 row[DB_serial][i] = toupper(row[DB_serial][i]);
2610 /* Search for the certificate */
2611 rrow=TXT_DB_get_by_index(db,DB_serial,row);
2614 BIO_printf(bio_err,"Serial %s not present in db.\n",
2619 else if (rrow[DB_type][0]=='V')
2621 BIO_printf(bio_err,"%s=Valid (%c)\n",
2622 row[DB_serial], rrow[DB_type][0]);
2625 else if (rrow[DB_type][0]=='R')
2627 BIO_printf(bio_err,"%s=Revoked (%c)\n",
2628 row[DB_serial], rrow[DB_type][0]);
2631 else if (rrow[DB_type][0]=='E')
2633 BIO_printf(bio_err,"%s=Expired (%c)\n",
2634 row[DB_serial], rrow[DB_type][0]);
2637 else if (rrow[DB_type][0]=='S')
2639 BIO_printf(bio_err,"%s=Suspended (%c)\n",
2640 row[DB_serial], rrow[DB_type][0]);
2645 BIO_printf(bio_err,"%s=Unknown (%c).\n",
2646 row[DB_serial], rrow[DB_type][0]);
2650 for (i=0; i<DB_NUMBER; i++)
2653 OPENSSL_free(row[i]);
2658 static int do_updatedb (TXT_DB *db)
2660 ASN1_UTCTIME *a_tm = NULL;
2662 int db_y2k, a_y2k; /* flags = 1 if y >= 2000 */
2663 char **rrow, *a_tm_s;
2665 a_tm = ASN1_UTCTIME_new();
2667 /* get actual time and make a string */
2668 a_tm = X509_gmtime_adj(a_tm, 0);
2669 a_tm_s = (char *) OPENSSL_malloc(a_tm->length+1);
2676 memcpy(a_tm_s, a_tm->data, a_tm->length);
2677 a_tm_s[a_tm->length] = '\0';
2679 if (strncmp(a_tm_s, "49", 2) <= 0)
2684 for (i = 0; i < sk_num(db->data); i++)
2686 rrow = (char **) sk_value(db->data, i);
2688 if (rrow[DB_type][0] == 'V')
2690 /* ignore entries that are not valid */
2691 if (strncmp(rrow[DB_exp_date], "49", 2) <= 0)
2696 if (db_y2k == a_y2k)
2698 /* all on the same y2k side */
2699 if (strcmp(rrow[DB_exp_date], a_tm_s) <= 0)
2701 rrow[DB_type][0] = 'E';
2702 rrow[DB_type][1] = '\0';
2705 BIO_printf(bio_err, "%s=Expired\n",
2709 else if (db_y2k < a_y2k)
2711 rrow[DB_type][0] = 'E';
2712 rrow[DB_type][1] = '\0';
2715 BIO_printf(bio_err, "%s=Expired\n",
2724 ASN1_UTCTIME_free(a_tm);
2725 OPENSSL_free(a_tm_s);
2730 static char *crl_reasons[] = {
2731 /* CRL reason strings */
2735 "affiliationChanged",
2737 "cessationOfOperation",
2740 /* Additional pseudo reasons */
2746 #define NUM_REASONS (sizeof(crl_reasons) / sizeof(char *))
2748 /* Given revocation information convert to a DB string.
2749 * The format of the string is:
2750 * revtime[,reason,extra]. Where 'revtime' is the
2751 * revocation time (the current time). 'reason' is the
2752 * optional CRL reason and 'extra' is any additional
2756 char *make_revocation_str(int rev_type, char *rev_arg)
2758 char *reason = NULL, *other = NULL, *str;
2760 ASN1_UTCTIME *revtm = NULL;
2767 case REV_CRL_REASON:
2768 for (i = 0; i < 8; i++)
2770 if (!strcasecmp(rev_arg, crl_reasons[i]))
2772 reason = crl_reasons[i];
2778 BIO_printf(bio_err, "Unknown CRL reason %s\n", rev_arg);
2784 /* Argument is an OID */
2786 otmp = OBJ_txt2obj(rev_arg, 0);
2787 ASN1_OBJECT_free(otmp);
2791 BIO_printf(bio_err, "Invalid object identifier %s\n", rev_arg);
2795 reason = "holdInstruction";
2799 case REV_KEY_COMPROMISE:
2800 case REV_CA_COMPROMISE:
2802 /* Argument is the key compromise time */
2803 if (!ASN1_GENERALIZEDTIME_set_string(NULL, rev_arg))
2805 BIO_printf(bio_err, "Invalid time format %s. Need YYYYMMDDHHMMSSZ\n", rev_arg);
2809 if (rev_type == REV_KEY_COMPROMISE)
2812 reason = "CAkeyTime";
2818 revtm = X509_gmtime_adj(NULL, 0);
2820 i = revtm->length + 1;
2822 if (reason) i += strlen(reason) + 1;
2823 if (other) i += strlen(other) + 1;
2825 str = OPENSSL_malloc(i);
2827 if (!str) return NULL;
2829 strcpy(str, (char *)revtm->data);
2833 strcat(str, reason);
2840 ASN1_UTCTIME_free(revtm);
2844 /* Convert revocation field to X509_REVOKED entry
2848 * 2 OK and some extensions added (i.e. V2 CRL)
2851 int make_revoked(X509_REVOKED *rev, char *str)
2854 char *rtime_str, *reason_str = NULL, *arg_str = NULL, *p;
2855 int reason_code = -1;
2857 ASN1_OBJECT *hold = NULL;
2858 ASN1_GENERALIZEDTIME *comp_time = NULL;
2859 ASN1_ENUMERATED *rtmp = NULL;
2860 tmp = BUF_strdup(str);
2862 p = strchr(tmp, ',');
2879 if (rev && !ASN1_UTCTIME_set_string(rev->revocationDate, rtime_str))
2881 BIO_printf(bio_err, "invalid revocation date %s\n", rtime_str);
2886 for (i = 0; i < NUM_REASONS; i++)
2888 if(!strcasecmp(reason_str, crl_reasons[i]))
2894 if (reason_code == OCSP_REVOKED_STATUS_NOSTATUS)
2896 BIO_printf(bio_err, "invalid reason code %s\n", reason_str);
2900 if (reason_code == 7)
2901 reason_code = OCSP_REVOKED_STATUS_REMOVEFROMCRL;
2902 else if (reason_code == 8) /* Hold instruction */
2906 BIO_printf(bio_err, "missing hold instruction\n");
2909 reason_code = OCSP_REVOKED_STATUS_CERTIFICATEHOLD;
2910 hold = OBJ_txt2obj(arg_str, 0);
2914 BIO_printf(bio_err, "invalid object identifier %s\n", arg_str);
2918 else if ((reason_code == 9) || (reason_code == 10))
2922 BIO_printf(bio_err, "missing compromised time\n");
2925 comp_time = ASN1_GENERALIZEDTIME_new();
2926 if (!ASN1_GENERALIZEDTIME_set_string(comp_time, arg_str))
2928 BIO_printf(bio_err, "invalid compromised time %s\n", arg_str);
2931 if (reason_code == 9)
2932 reason_code = OCSP_REVOKED_STATUS_KEYCOMPROMISE;
2934 reason_code = OCSP_REVOKED_STATUS_CACOMPROMISE;
2938 if (rev && (reason_code != OCSP_REVOKED_STATUS_NOSTATUS))
2940 rtmp = ASN1_ENUMERATED_new();
2941 if (!rtmp || !ASN1_ENUMERATED_set(rtmp, reason_code))
2943 if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0))
2947 if (rev && comp_time)
2949 if (!X509_REVOKED_add1_ext_i2d(rev, NID_invalidity_date, comp_time, 0, 0))
2954 if (!X509_REVOKED_add1_ext_i2d(rev, NID_hold_instruction_code, hold, 0, 0))
2958 if (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)
2964 if (tmp) OPENSSL_free(tmp);
2965 ASN1_OBJECT_free(hold);
2966 ASN1_GENERALIZEDTIME_free(comp_time);
2967 ASN1_ENUMERATED_free(rtmp);