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>
80 #ifdef OPENSSL_SYS_WINDOWS
81 #define strcasecmp _stricmp
87 # ifdef OPENSSL_SYS_VMS
94 # include <sys/file.h>
108 #define BASE_SECTION "ca"
109 #define CONFIG_FILE "openssl.cnf"
111 #define ENV_DEFAULT_CA "default_ca"
113 #define ENV_DIR "dir"
114 #define ENV_CERTS "certs"
115 #define ENV_CRL_DIR "crl_dir"
116 #define ENV_CA_DB "CA_DB"
117 #define ENV_NEW_CERTS_DIR "new_certs_dir"
118 #define ENV_CERTIFICATE "certificate"
119 #define ENV_SERIAL "serial"
120 #define ENV_CRL "crl"
121 #define ENV_PRIVATE_KEY "private_key"
122 #define ENV_RANDFILE "RANDFILE"
123 #define ENV_DEFAULT_DAYS "default_days"
124 #define ENV_DEFAULT_STARTDATE "default_startdate"
125 #define ENV_DEFAULT_ENDDATE "default_enddate"
126 #define ENV_DEFAULT_CRL_DAYS "default_crl_days"
127 #define ENV_DEFAULT_CRL_HOURS "default_crl_hours"
128 #define ENV_DEFAULT_MD "default_md"
129 #define ENV_PRESERVE "preserve"
130 #define ENV_POLICY "policy"
131 #define ENV_EXTENSIONS "x509_extensions"
132 #define ENV_CRLEXT "crl_extensions"
133 #define ENV_MSIE_HACK "msie_hack"
134 #define ENV_NAMEOPT "name_opt"
135 #define ENV_CERTOPT "cert_opt"
136 #define ENV_EXTCOPY "copy_extensions"
138 #define ENV_DATABASE "database"
141 #define DB_exp_date 1
142 #define DB_rev_date 2
143 #define DB_serial 3 /* index - unique */
145 #define DB_name 5 /* index - unique for active */
148 #define DB_TYPE_REV 'R'
149 #define DB_TYPE_EXP 'E'
150 #define DB_TYPE_VAL 'V'
152 /* Additional revocation information types */
154 #define REV_NONE 0 /* No addditional information */
155 #define REV_CRL_REASON 1 /* Value is CRL reason code */
156 #define REV_HOLD 2 /* Value is hold instruction */
157 #define REV_KEY_COMPROMISE 3 /* Value is cert key compromise time */
158 #define REV_CA_COMPROMISE 4 /* Value is CA key compromise time */
160 static char *ca_usage[]={
163 " -verbose - Talk alot while doing things\n",
164 " -config file - A config file\n",
165 " -name arg - The particular CA definition to use\n",
166 " -gencrl - Generate a new CRL\n",
167 " -crldays days - Days is when the next CRL is due\n",
168 " -crlhours hours - Hours is when the next CRL is due\n",
169 " -startdate YYMMDDHHMMSSZ - certificate validity notBefore\n",
170 " -enddate YYMMDDHHMMSSZ - certificate validity notAfter (overrides -days)\n",
171 " -days arg - number of days to certify the certificate for\n",
172 " -md arg - md to use, one of md2, md5, sha or sha1\n",
173 " -policy arg - The CA 'policy' to support\n",
174 " -keyfile arg - private key file\n",
175 " -keyform arg - private key file format (PEM or ENGINE)\n",
176 " -key arg - key to decode the private key if it is encrypted\n",
177 " -cert file - The CA certificate\n",
178 " -in file - The input PEM encoded certificate request(s)\n",
179 " -out file - Where to put the output file(s)\n",
180 " -outdir dir - Where to put output certificates\n",
181 " -infiles .... - The last argument, requests to process\n",
182 " -spkac file - File contains DN and signed public key and challenge\n",
183 " -ss_cert file - File contains a self signed cert to sign\n",
184 " -preserveDN - Don't re-order the DN\n",
185 " -batch - Don't ask questions\n",
186 " -msie_hack - msie modifications to handle all those universal strings\n",
187 " -revoke file - Revoke a certificate (given in file)\n",
188 " -subj arg - Use arg instead of request's subject\n",
189 " -extensions .. - Extension section (override value in config file)\n",
190 " -extfile file - Configuration file with X509v3 extentions to add\n",
191 " -crlexts .. - CRL extension section (override value in config file)\n",
192 " -engine e - use engine e, possibly a hardware device.\n",
193 " -status serial - Shows certificate status given the serial number\n",
194 " -updatedb - Updates db for expired certificates\n",
199 extern int EF_PROTECT_FREE;
200 extern int EF_PROTECT_BELOW;
201 extern int EF_ALIGNMENT;
204 static void lookup_fail(char *name,char *tag);
205 static unsigned long index_serial_hash(const char **a);
206 static int index_serial_cmp(const char **a, const char **b);
207 static unsigned long index_name_hash(const char **a);
208 static int index_name_qual(char **a);
209 static int index_name_cmp(const char **a,const char **b);
210 static BIGNUM *load_serial(char *serialfile);
211 static int save_serial(char *serialfile, BIGNUM *serial);
212 static int certify(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
213 const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,TXT_DB *db,
214 BIGNUM *serial, char *subj, char *startdate,char *enddate,
215 long days, int batch, char *ext_sect, CONF *conf,int verbose,
216 unsigned long certopt, unsigned long nameopt, int default_op,
218 static int certify_cert(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 *subj, char *startdate,
221 char *enddate, long days, int batch, char *ext_sect,
222 CONF *conf,int verbose, unsigned long certopt,
223 unsigned long nameopt, int default_op, int ext_copy,
225 static int certify_spkac(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
226 const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
227 TXT_DB *db, BIGNUM *serial,char *subj, char *startdate,
228 char *enddate, long days, char *ext_sect,CONF *conf,
229 int verbose, unsigned long certopt, unsigned long nameopt,
230 int default_op, int ext_copy);
231 static int fix_data(int nid, int *type);
232 static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext);
233 static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
234 STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial,char *subj,
235 char *startdate, char *enddate, long days, int batch, int verbose,
236 X509_REQ *req, char *ext_sect, CONF *conf,
237 unsigned long certopt, unsigned long nameopt, int default_op,
239 static X509_NAME *do_subject(char *subject);
240 static int do_revoke(X509 *x509, TXT_DB *db, int ext, char *extval);
241 static int get_certificate_status(const char *ser_status, TXT_DB *db);
242 static int do_updatedb(TXT_DB *db);
243 static int check_time_format(char *str);
244 char *make_revocation_str(int rev_type, char *rev_arg);
245 int make_revoked(X509_REVOKED *rev, char *str);
246 int old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str);
247 static CONF *conf=NULL;
248 static CONF *extconf=NULL;
249 static char *section=NULL;
251 static int preserve=0;
252 static int msie_hack=0;
254 static IMPLEMENT_LHASH_HASH_FN(index_serial_hash,const char **)
255 static IMPLEMENT_LHASH_COMP_FN(index_serial_cmp,const char **)
256 static IMPLEMENT_LHASH_HASH_FN(index_name_hash,const char **)
257 static IMPLEMENT_LHASH_COMP_FN(index_name_cmp,const char **)
260 int MAIN(int, char **);
262 int MAIN(int argc, char **argv)
265 char *key=NULL,*passargin=NULL;
279 char *configfile=NULL;
284 int keyform=FORMAT_PEM;
286 char *spkac_file=NULL;
287 char *ss_cert_file=NULL;
288 char *ser_status=NULL;
293 char *serialfile=NULL;
294 char *extensions=NULL;
298 int rev_type = REV_NONE;
299 char *rev_arg = NULL;
301 char *startdate=NULL;
306 unsigned long nameopt = 0, certopt = 0;
308 int ext_copy = EXT_COPY_NONE;
311 BIO *in=NULL,*out=NULL,*Sout=NULL,*Cout=NULL;
315 X509_REVOKED *r=NULL;
317 ASN1_INTEGER *tmpser;
321 const EVP_MD *dgst=NULL;
322 STACK_OF(CONF_VALUE) *attribs=NULL;
323 STACK_OF(X509) *cert_sk=NULL;
326 MS_STATIC char buf[3][BSIZE];
345 if ((bio_err=BIO_new(BIO_s_file())) != NULL)
346 BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
352 if (strcmp(*argv,"-verbose") == 0)
354 else if (strcmp(*argv,"-config") == 0)
356 if (--argc < 1) goto bad;
357 configfile= *(++argv);
359 else if (strcmp(*argv,"-name") == 0)
361 if (--argc < 1) goto bad;
364 else if (strcmp(*argv,"-subj") == 0)
366 if (--argc < 1) goto bad;
370 else if (strcmp(*argv,"-startdate") == 0)
372 if (--argc < 1) goto bad;
373 startdate= *(++argv);
375 else if (strcmp(*argv,"-enddate") == 0)
377 if (--argc < 1) goto bad;
380 else if (strcmp(*argv,"-days") == 0)
382 if (--argc < 1) goto bad;
383 days=atoi(*(++argv));
385 else if (strcmp(*argv,"-md") == 0)
387 if (--argc < 1) goto bad;
390 else if (strcmp(*argv,"-policy") == 0)
392 if (--argc < 1) goto bad;
395 else if (strcmp(*argv,"-keyfile") == 0)
397 if (--argc < 1) goto bad;
400 else if (strcmp(*argv,"-keyform") == 0)
402 if (--argc < 1) goto bad;
403 keyform=str2fmt(*(++argv));
405 else if (strcmp(*argv,"-passin") == 0)
407 if (--argc < 1) goto bad;
408 passargin= *(++argv);
410 else if (strcmp(*argv,"-key") == 0)
412 if (--argc < 1) goto bad;
415 else if (strcmp(*argv,"-cert") == 0)
417 if (--argc < 1) goto bad;
420 else if (strcmp(*argv,"-in") == 0)
422 if (--argc < 1) goto bad;
426 else if (strcmp(*argv,"-out") == 0)
428 if (--argc < 1) goto bad;
431 else if (strcmp(*argv,"-outdir") == 0)
433 if (--argc < 1) goto bad;
436 else if (strcmp(*argv,"-notext") == 0)
438 else if (strcmp(*argv,"-batch") == 0)
440 else if (strcmp(*argv,"-preserveDN") == 0)
442 else if (strcmp(*argv,"-gencrl") == 0)
444 else if (strcmp(*argv,"-msie_hack") == 0)
446 else if (strcmp(*argv,"-crldays") == 0)
448 if (--argc < 1) goto bad;
449 crldays= atol(*(++argv));
451 else if (strcmp(*argv,"-crlhours") == 0)
453 if (--argc < 1) goto bad;
454 crlhours= atol(*(++argv));
456 else if (strcmp(*argv,"-infiles") == 0)
463 else if (strcmp(*argv, "-ss_cert") == 0)
465 if (--argc < 1) goto bad;
466 ss_cert_file = *(++argv);
469 else if (strcmp(*argv, "-spkac") == 0)
471 if (--argc < 1) goto bad;
472 spkac_file = *(++argv);
475 else if (strcmp(*argv,"-revoke") == 0)
477 if (--argc < 1) goto bad;
481 else if (strcmp(*argv,"-extensions") == 0)
483 if (--argc < 1) goto bad;
484 extensions= *(++argv);
486 else if (strcmp(*argv,"-extfile") == 0)
488 if (--argc < 1) goto bad;
491 else if (strcmp(*argv,"-status") == 0)
493 if (--argc < 1) goto bad;
494 ser_status= *(++argv);
496 else if (strcmp(*argv,"-updatedb") == 0)
500 else if (strcmp(*argv,"-crlexts") == 0)
502 if (--argc < 1) goto bad;
505 else if (strcmp(*argv,"-crl_reason") == 0)
507 if (--argc < 1) goto bad;
509 rev_type = REV_CRL_REASON;
511 else if (strcmp(*argv,"-crl_hold") == 0)
513 if (--argc < 1) goto bad;
517 else if (strcmp(*argv,"-crl_compromise") == 0)
519 if (--argc < 1) goto bad;
521 rev_type = REV_KEY_COMPROMISE;
523 else if (strcmp(*argv,"-crl_CA_compromise") == 0)
525 if (--argc < 1) goto bad;
527 rev_type = REV_CA_COMPROMISE;
529 else if (strcmp(*argv,"-engine") == 0)
531 if (--argc < 1) goto bad;
537 BIO_printf(bio_err,"unknown option %s\n",*argv);
547 for (pp=ca_usage; (*pp != NULL); pp++)
548 BIO_printf(bio_err,"%s",*pp);
552 ERR_load_crypto_strings();
554 e = setup_engine(bio_err, engine, 0);
556 /*****************************************************************/
557 if (configfile == NULL) configfile = getenv("OPENSSL_CONF");
558 if (configfile == NULL) configfile = getenv("SSLEAY_CONF");
559 if (configfile == NULL)
561 /* We will just use 'buf[0]' as a temporary buffer. */
562 #ifdef OPENSSL_SYS_VMS
563 strncpy(buf[0],X509_get_default_cert_area(),
564 sizeof(buf[0])-1-sizeof(CONFIG_FILE));
566 strncpy(buf[0],X509_get_default_cert_area(),
567 sizeof(buf[0])-2-sizeof(CONFIG_FILE));
570 strcat(buf[0],CONFIG_FILE);
574 BIO_printf(bio_err,"Using configuration from %s\n",configfile);
575 conf = NCONF_new(NULL);
576 if (NCONF_load(conf,configfile,&errorline) <= 0)
579 BIO_printf(bio_err,"error loading the config file '%s'\n",
582 BIO_printf(bio_err,"error on line %ld of config file '%s'\n"
583 ,errorline,configfile);
587 /* Lets get the config section we are using */
590 section=NCONF_get_string(conf,BASE_SECTION,ENV_DEFAULT_CA);
593 lookup_fail(BASE_SECTION,ENV_DEFAULT_CA);
600 p=NCONF_get_string(conf,NULL,"oid_file");
607 oid_bio=BIO_new_file(p,"r");
611 BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
612 ERR_print_errors(bio_err);
618 OBJ_create_objects(oid_bio);
622 if (!add_oid_section(bio_err,conf))
624 ERR_print_errors(bio_err);
629 randfile = NCONF_get_string(conf, BASE_SECTION, "RANDFILE");
630 if (randfile == NULL)
632 app_RAND_load_file(randfile, bio_err, 0);
634 in=BIO_new(BIO_s_file());
635 out=BIO_new(BIO_s_file());
636 Sout=BIO_new(BIO_s_file());
637 Cout=BIO_new(BIO_s_file());
638 if ((in == NULL) || (out == NULL) || (Sout == NULL) || (Cout == NULL))
640 ERR_print_errors(bio_err);
644 /*****************************************************************/
645 /* report status of cert with serial number given on command line */
648 if ((dbfile=NCONF_get_string(conf,section,ENV_DATABASE)) == NULL)
650 lookup_fail(section,ENV_DATABASE);
653 if (BIO_read_filename(in,dbfile) <= 0)
656 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
659 db=TXT_DB_read(in,DB_NUMBER);
660 if (db == NULL) goto err;
662 if (!make_serial_index(db))
665 if (get_certificate_status(ser_status,db) != 1)
666 BIO_printf(bio_err,"Error verifying serial %s!\n",
671 /*****************************************************************/
672 /* we definitely need a public key, so let's get it */
674 if ((keyfile == NULL) && ((keyfile=NCONF_get_string(conf,
675 section,ENV_PRIVATE_KEY)) == NULL))
677 lookup_fail(section,ENV_PRIVATE_KEY);
683 if (!app_passwd(bio_err, passargin, NULL, &key, NULL))
685 BIO_printf(bio_err,"Error getting password\n");
689 pkey = load_key(bio_err, keyfile, keyform, key, e,
691 if (key) memset(key,0,strlen(key));
694 /* load_key() has already printed an appropriate message */
698 /*****************************************************************/
699 /* we need a certificate */
700 if ((certfile == NULL) && ((certfile=NCONF_get_string(conf,
701 section,ENV_CERTIFICATE)) == NULL))
703 lookup_fail(section,ENV_CERTIFICATE);
706 x509=load_cert(bio_err, certfile, FORMAT_PEM, NULL, e,
711 if (!X509_check_private_key(x509,pkey))
713 BIO_printf(bio_err,"CA certificate and CA private key do not match\n");
717 f=NCONF_get_string(conf,BASE_SECTION,ENV_PRESERVE);
720 if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
722 f=NCONF_get_string(conf,BASE_SECTION,ENV_MSIE_HACK);
725 if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
728 f=NCONF_get_string(conf,section,ENV_NAMEOPT);
732 if (!set_name_ex(&nameopt, f))
734 BIO_printf(bio_err, "Invalid name options: \"%s\"\n", f);
742 f=NCONF_get_string(conf,section,ENV_CERTOPT);
746 if (!set_cert_ex(&certopt, f))
748 BIO_printf(bio_err, "Invalid certificate options: \"%s\"\n", f);
756 f=NCONF_get_string(conf,section,ENV_EXTCOPY);
760 if (!set_ext_copy(&ext_copy, f))
762 BIO_printf(bio_err, "Invalid extension copy option: \"%s\"\n", f);
769 /*****************************************************************/
770 /* lookup where to write new certificates */
771 if ((outdir == NULL) && (req))
775 if ((outdir=NCONF_get_string(conf,section,ENV_NEW_CERTS_DIR))
778 BIO_printf(bio_err,"there needs to be defined a directory for new certificate to be placed in\n");
781 #ifndef OPENSSL_SYS_VMS
782 /* outdir is a directory spec, but access() for VMS demands a
783 filename. In any case, stat(), below, will catch the problem
784 if outdir is not a directory spec, and the fopen() or open()
785 will catch an error if there is no write access.
787 Presumably, this problem could also be solved by using the DEC
788 C routines to convert the directory syntax to Unixly, and give
789 that to access(). However, time's too short to do that just
792 if (access(outdir,R_OK|W_OK|X_OK) != 0)
794 BIO_printf(bio_err,"I am unable to access the %s directory\n",outdir);
799 if (stat(outdir,&sb) != 0)
801 BIO_printf(bio_err,"unable to stat(%s)\n",outdir);
806 if (!(sb.st_mode & S_IFDIR))
808 BIO_printf(bio_err,"%s need to be a directory\n",outdir);
816 /*****************************************************************/
817 /* we need to load the database file */
818 if ((dbfile=NCONF_get_string(conf,section,ENV_DATABASE)) == NULL)
820 lookup_fail(section,ENV_DATABASE);
823 if (BIO_read_filename(in,dbfile) <= 0)
826 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
829 db=TXT_DB_read(in,DB_NUMBER);
830 if (db == NULL) goto err;
832 /* Lets check some fields */
833 for (i=0; i<sk_num(db->data); i++)
835 pp=(char **)sk_value(db->data,i);
836 if ((pp[DB_type][0] != DB_TYPE_REV) &&
837 (pp[DB_rev_date][0] != '\0'))
839 BIO_printf(bio_err,"entry %d: not revoked yet, but has a revocation date\n",i+1);
842 if ((pp[DB_type][0] == DB_TYPE_REV) &&
843 !make_revoked(NULL, pp[DB_rev_date]))
845 BIO_printf(bio_err," in entry %d\n", i+1);
848 if (!check_time_format(pp[DB_exp_date]))
850 BIO_printf(bio_err,"entry %d: invalid expiry date\n",i+1);
860 if ((j&1) || (j < 2))
862 BIO_printf(bio_err,"entry %d: bad serial number length (%d)\n",i+1,j);
867 if (!( ((*p >= '0') && (*p <= '9')) ||
868 ((*p >= 'A') && (*p <= 'F')) ||
869 ((*p >= 'a') && (*p <= 'f'))) )
871 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);
879 BIO_set_fp(out,stdout,BIO_NOCLOSE|BIO_FP_TEXT); /* cannot fail */
880 #ifdef OPENSSL_SYS_VMS
882 BIO *tmpbio = BIO_new(BIO_f_linebuffer());
883 out = BIO_push(tmpbio, out);
886 TXT_DB_write(out,db);
887 BIO_printf(bio_err,"%d entries loaded from the database\n",
889 BIO_printf(bio_err,"generating index\n");
892 if (!make_serial_index(db))
895 if (!TXT_DB_create_index(db, DB_name, index_name_qual,
896 LHASH_HASH_FN(index_name_hash),
897 LHASH_COMP_FN(index_name_cmp)))
899 BIO_printf(bio_err,"error creating name index:(%ld,%ld,%ld)\n",
900 db->error,db->arg1,db->arg2);
904 /*****************************************************************/
905 /* Update the db file for expired certificates */
909 BIO_printf(bio_err, "Updating %s ...\n",
915 BIO_printf(bio_err,"Malloc failure\n");
920 if (verbose) BIO_printf(bio_err,
921 "No entries found to mark expired\n");
925 out = BIO_new(BIO_s_file());
928 ERR_print_errors(bio_err);
932 #ifndef OPENSSL_SYS_VMS
933 j = BIO_snprintf(buf[0], sizeof buf[0], "%s.new", dbfile);
935 j = BIO_snprintf(buf[0], sizeof buf[0], "%s-new", dbfile);
937 if (j < 0 || j >= sizeof buf[0])
939 BIO_printf(bio_err, "file name too long\n");
942 if (BIO_write_filename(out,buf[0]) <= 0)
945 BIO_printf(bio_err,"unable to open '%s'\n",
949 j=TXT_DB_write(out,db);
950 if (j <= 0) goto err;
954 #ifndef OPENSSL_SYS_VMS
955 j = BIO_snprintf(buf[1], sizeof buf[1], "%s.old", dbfile);
957 j = BIO_snprintf(buf[1], sizeof buf[1], "%s-old", dbfile);
959 if (j < 0 || j >= sizeof buf[1])
961 BIO_printf(bio_err, "file name too long\n");
964 if (rename(dbfile,buf[1]) < 0)
967 "unable to rename %s to %s\n",
972 if (rename(buf[0],dbfile) < 0)
975 "unable to rename %s to %s\n",
978 rename(buf[1],dbfile);
982 if (verbose) BIO_printf(bio_err,
983 "Done. %d entries marked as expired\n",i);
988 /*****************************************************************/
989 /* Read extentions config file */
992 extconf = NCONF_new(NULL);
993 if (NCONF_load(extconf,extfile,&errorline) <= 0)
996 BIO_printf(bio_err, "ERROR: loading the config file '%s'\n",
999 BIO_printf(bio_err, "ERROR: on line %ld of config file '%s'\n",
1006 BIO_printf(bio_err, "Succesfully loaded extensions file %s\n", extfile);
1008 /* We can have sections in the ext file */
1009 if (!extensions && !(extensions = NCONF_get_string(extconf, "default", "extensions")))
1010 extensions = "default";
1013 /*****************************************************************/
1016 if (outfile != NULL)
1018 if (BIO_write_filename(Sout,outfile) <= 0)
1026 BIO_set_fp(Sout,stdout,BIO_NOCLOSE|BIO_FP_TEXT);
1027 #ifdef OPENSSL_SYS_VMS
1029 BIO *tmpbio = BIO_new(BIO_f_linebuffer());
1030 Sout = BIO_push(tmpbio, Sout);
1038 if ((md == NULL) && ((md=NCONF_get_string(conf,
1039 section,ENV_DEFAULT_MD)) == NULL))
1041 lookup_fail(section,ENV_DEFAULT_MD);
1044 if ((dgst=EVP_get_digestbyname(md)) == NULL)
1046 BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
1050 BIO_printf(bio_err,"message digest is %s\n",
1051 OBJ_nid2ln(dgst->type));
1052 if ((policy == NULL) && ((policy=NCONF_get_string(conf,
1053 section,ENV_POLICY)) == NULL))
1055 lookup_fail(section,ENV_POLICY);
1059 BIO_printf(bio_err,"policy is %s\n",policy);
1061 if ((serialfile=NCONF_get_string(conf,section,ENV_SERIAL))
1064 lookup_fail(section,ENV_SERIAL);
1070 /* no '-extfile' option, so we look for extensions
1071 * in the main configuration file */
1074 extensions=NCONF_get_string(conf,section,
1081 /* Check syntax of file */
1083 X509V3_set_ctx_test(&ctx);
1084 X509V3_set_nconf(&ctx, conf);
1085 if (!X509V3_EXT_add_nconf(conf, &ctx, extensions,
1089 "Error Loading extension section %s\n",
1097 if (startdate == NULL)
1099 startdate=NCONF_get_string(conf,section,
1100 ENV_DEFAULT_STARTDATE);
1101 if (startdate == NULL)
1104 if (startdate && !ASN1_UTCTIME_set_string(NULL,startdate))
1106 BIO_printf(bio_err,"start date is invalid, it should be YYMMDDHHMMSSZ\n");
1109 if (startdate == NULL) startdate="today";
1111 if (enddate == NULL)
1113 enddate=NCONF_get_string(conf,section,
1114 ENV_DEFAULT_ENDDATE);
1115 if (enddate == NULL)
1118 if (enddate && !ASN1_UTCTIME_set_string(NULL,enddate))
1120 BIO_printf(bio_err,"end date is invalid, it should be YYMMDDHHMMSSZ\n");
1126 if(!NCONF_get_number(conf,section, ENV_DEFAULT_DAYS, &days))
1129 if (!enddate && (days == 0))
1131 BIO_printf(bio_err,"cannot lookup how many days to certify for\n");
1135 if ((serial=load_serial(serialfile)) == NULL)
1137 BIO_printf(bio_err,"error while loading serial number\n");
1142 if ((f=BN_bn2hex(serial)) == NULL) goto err;
1143 BIO_printf(bio_err,"next serial number is %s\n",f);
1147 if ((attribs=NCONF_get_section(conf,policy)) == NULL)
1149 BIO_printf(bio_err,"unable to find 'section' for %s\n",policy);
1153 if ((cert_sk=sk_X509_new_null()) == NULL)
1155 BIO_printf(bio_err,"Memory allocation failure\n");
1158 if (spkac_file != NULL)
1161 j=certify_spkac(&x,spkac_file,pkey,x509,dgst,attribs,db,
1162 serial,subj,startdate,enddate, days,extensions,conf,
1163 verbose, certopt, nameopt, default_op, ext_copy);
1164 if (j < 0) goto err;
1168 BIO_printf(bio_err,"\n");
1169 if (!BN_add_word(serial,1)) goto err;
1170 if (!sk_X509_push(cert_sk,x))
1172 BIO_printf(bio_err,"Memory allocation failure\n");
1182 if (ss_cert_file != NULL)
1185 j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,attribs,
1186 db,serial,subj,startdate,enddate,days,batch,
1187 extensions,conf,verbose, certopt, nameopt,
1188 default_op, ext_copy, e);
1189 if (j < 0) goto err;
1193 BIO_printf(bio_err,"\n");
1194 if (!BN_add_word(serial,1)) goto err;
1195 if (!sk_X509_push(cert_sk,x))
1197 BIO_printf(bio_err,"Memory allocation failure\n");
1205 j=certify(&x,infile,pkey,x509,dgst,attribs,db,
1206 serial,subj,startdate,enddate,days,batch,
1207 extensions,conf,verbose, certopt, nameopt,
1208 default_op, ext_copy);
1209 if (j < 0) goto err;
1213 BIO_printf(bio_err,"\n");
1214 if (!BN_add_word(serial,1)) goto err;
1215 if (!sk_X509_push(cert_sk,x))
1217 BIO_printf(bio_err,"Memory allocation failure\n");
1222 for (i=0; i<argc; i++)
1225 j=certify(&x,argv[i],pkey,x509,dgst,attribs,db,
1226 serial,subj,startdate,enddate,days,batch,
1227 extensions,conf,verbose, certopt, nameopt,
1228 default_op, ext_copy);
1229 if (j < 0) goto err;
1233 BIO_printf(bio_err,"\n");
1234 if (!BN_add_word(serial,1)) goto err;
1235 if (!sk_X509_push(cert_sk,x))
1237 BIO_printf(bio_err,"Memory allocation failure\n");
1242 /* we have a stack of newly certified certificates
1243 * and a data base and serial number that need
1246 if (sk_X509_num(cert_sk) > 0)
1250 BIO_printf(bio_err,"\n%d out of %d certificate requests certified, commit? [y/n]",total_done,total);
1251 (void)BIO_flush(bio_err);
1253 fgets(buf[0],10,stdin);
1254 if ((buf[0][0] != 'y') && (buf[0][0] != 'Y'))
1256 BIO_printf(bio_err,"CERTIFICATION CANCELED\n");
1262 BIO_printf(bio_err,"Write out database with %d new entries\n",sk_X509_num(cert_sk));
1264 strncpy(buf[0],serialfile,BSIZE-4);
1266 #ifdef OPENSSL_SYS_VMS
1267 strcat(buf[0],"-new");
1269 strcat(buf[0],".new");
1272 if (!save_serial(buf[0],serial)) goto err;
1274 strncpy(buf[1],dbfile,BSIZE-4);
1276 #ifdef OPENSSL_SYS_VMS
1277 strcat(buf[1],"-new");
1279 strcat(buf[1],".new");
1282 if (BIO_write_filename(out,buf[1]) <= 0)
1285 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
1288 l=TXT_DB_write(out,db);
1289 if (l <= 0) goto err;
1293 BIO_printf(bio_err,"writing new certificates\n");
1294 for (i=0; i<sk_X509_num(cert_sk); i++)
1299 x=sk_X509_value(cert_sk,i);
1301 j=x->cert_info->serialNumber->length;
1302 p=(char *)x->cert_info->serialNumber->data;
1304 strncpy(buf[2],outdir,BSIZE-(j*2)-6);
1306 #ifndef OPENSSL_SYS_VMS
1310 n=(unsigned char *)&(buf[2][strlen(buf[2])]);
1315 sprintf((char *)n,"%02X",(unsigned char)*(p++));
1324 *(n++)='.'; *(n++)='p'; *(n++)='e'; *(n++)='m';
1327 BIO_printf(bio_err,"writing %s\n",buf[2]);
1329 if (BIO_write_filename(Cout,buf[2]) <= 0)
1334 write_new_certificate(Cout,x, 0, notext);
1335 write_new_certificate(Sout,x, output_der, notext);
1338 if (sk_X509_num(cert_sk))
1340 /* Rename the database and the serial file */
1341 strncpy(buf[2],serialfile,BSIZE-4);
1343 #ifdef OPENSSL_SYS_VMS
1344 strcat(buf[2],"-old");
1346 strcat(buf[2],".old");
1353 if (rename(serialfile,buf[2]) < 0)
1355 BIO_printf(bio_err,"unable to rename %s to %s\n",
1360 if (rename(buf[0],serialfile) < 0)
1362 BIO_printf(bio_err,"unable to rename %s to %s\n",
1365 rename(buf[2],serialfile);
1369 strncpy(buf[2],dbfile,BSIZE-4);
1371 #ifdef OPENSSL_SYS_VMS
1372 strcat(buf[2],"-old");
1374 strcat(buf[2],".old");
1377 if (rename(dbfile,buf[2]) < 0)
1379 BIO_printf(bio_err,"unable to rename %s to %s\n",
1384 if (rename(buf[1],dbfile) < 0)
1386 BIO_printf(bio_err,"unable to rename %s to %s\n",
1389 rename(buf[2],dbfile);
1392 BIO_printf(bio_err,"Data Base Updated\n");
1396 /*****************************************************************/
1402 crl_ext=NCONF_get_string(conf,section,ENV_CRLEXT);
1408 /* Check syntax of file */
1410 X509V3_set_ctx_test(&ctx);
1411 X509V3_set_nconf(&ctx, conf);
1412 if (!X509V3_EXT_add_nconf(conf, &ctx, crl_ext, NULL))
1415 "Error Loading CRL extension section %s\n",
1422 if (!crldays && !crlhours)
1424 if (!NCONF_get_number(conf,section,
1425 ENV_DEFAULT_CRL_DAYS, &crldays))
1427 if (!NCONF_get_number(conf,section,
1428 ENV_DEFAULT_CRL_HOURS, &crlhours))
1431 if ((crldays == 0) && (crlhours == 0))
1433 BIO_printf(bio_err,"cannot lookup how long until the next CRL is issuer\n");
1437 if (verbose) BIO_printf(bio_err,"making CRL\n");
1438 if ((crl=X509_CRL_new()) == NULL) goto err;
1439 if (!X509_CRL_set_issuer_name(crl, X509_get_issuer_name(x509))) goto err;
1441 tmptm = ASN1_TIME_new();
1442 if (!tmptm) goto err;
1443 X509_gmtime_adj(tmptm,0);
1444 X509_CRL_set_lastUpdate(crl, tmptm);
1445 X509_gmtime_adj(tmptm,(crldays*24+crlhours)*60*60);
1446 X509_CRL_set_nextUpdate(crl, tmptm);
1448 ASN1_TIME_free(tmptm);
1450 for (i=0; i<sk_num(db->data); i++)
1452 pp=(char **)sk_value(db->data,i);
1453 if (pp[DB_type][0] == DB_TYPE_REV)
1455 if ((r=X509_REVOKED_new()) == NULL) goto err;
1456 j = make_revoked(r, pp[DB_rev_date]);
1458 if (j == 2) crl_v2 = 1;
1459 if (!BN_hex2bn(&serial, pp[DB_serial]))
1461 tmpser = BN_to_ASN1_INTEGER(serial, NULL);
1466 X509_REVOKED_set_serialNumber(r, tmpser);
1467 ASN1_INTEGER_free(tmpser);
1468 X509_CRL_add0_revoked(crl,r);
1472 /* sort the data so it will be written in serial
1476 /* we now have a CRL */
1477 if (verbose) BIO_printf(bio_err,"signing CRL\n");
1480 if ((dgst=EVP_get_digestbyname(md)) == NULL)
1482 BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
1488 #ifndef OPENSSL_NO_DSA
1489 if (pkey->type == EVP_PKEY_DSA)
1496 /* Add any extensions asked for */
1501 X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0);
1502 X509V3_set_nconf(&crlctx, conf);
1504 if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx,
1505 crl_ext, crl)) goto err;
1507 if (crl_ext || crl_v2)
1509 if (!X509_CRL_set_version(crl, 1))
1510 goto err; /* version 2 CRL */
1513 if (!X509_CRL_sign(crl,pkey,dgst)) goto err;
1515 PEM_write_bio_X509_CRL(Sout,crl);
1517 /*****************************************************************/
1522 BIO_printf(bio_err,"no input files\n");
1528 revcert=load_cert(bio_err, infile, FORMAT_PEM,
1530 if (revcert == NULL)
1532 j=do_revoke(revcert,db, rev_type, rev_arg);
1533 if (j <= 0) goto err;
1536 strncpy(buf[0],dbfile,BSIZE-4);
1537 #ifndef OPENSSL_SYS_VMS
1538 strcat(buf[0],".new");
1540 strcat(buf[0],"-new");
1542 if (BIO_write_filename(out,buf[0]) <= 0)
1545 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
1548 j=TXT_DB_write(out,db);
1549 if (j <= 0) goto err;
1550 strncpy(buf[1],dbfile,BSIZE-4);
1551 #ifndef OPENSSL_SYS_VMS
1552 strcat(buf[1],".old");
1554 strcat(buf[1],"-old");
1556 if (rename(dbfile,buf[1]) < 0)
1558 BIO_printf(bio_err,"unable to rename %s to %s\n", dbfile, buf[1]);
1562 if (rename(buf[0],dbfile) < 0)
1564 BIO_printf(bio_err,"unable to rename %s to %s\n", buf[0],dbfile);
1566 rename(buf[1],dbfile);
1569 BIO_printf(bio_err,"Data Base Updated\n");
1572 /*****************************************************************/
1580 sk_X509_pop_free(cert_sk,X509_free);
1582 if (ret) ERR_print_errors(bio_err);
1583 app_RAND_write_file(randfile, bio_err);
1588 EVP_PKEY_free(pkey);
1597 static void lookup_fail(char *name, char *tag)
1599 BIO_printf(bio_err,"variable lookup failed for %s::%s\n",name,tag);
1602 static unsigned long index_serial_hash(const char **a)
1607 while (*n == '0') n++;
1608 return(lh_strhash(n));
1611 static int index_serial_cmp(const char **a, const char **b)
1615 for (aa=a[DB_serial]; *aa == '0'; aa++);
1616 for (bb=b[DB_serial]; *bb == '0'; bb++);
1617 return(strcmp(aa,bb));
1620 static unsigned long index_name_hash(const char **a)
1621 { return(lh_strhash(a[DB_name])); }
1623 static int index_name_qual(char **a)
1624 { return(a[0][0] == 'V'); }
1626 static int index_name_cmp(const char **a, const char **b)
1627 { return(strcmp(a[DB_name],
1630 static BIGNUM *load_serial(char *serialfile)
1634 MS_STATIC char buf[1024];
1635 ASN1_INTEGER *ai=NULL;
1637 if ((in=BIO_new(BIO_s_file())) == NULL)
1639 ERR_print_errors(bio_err);
1643 if (BIO_read_filename(in,serialfile) <= 0)
1648 ai=ASN1_INTEGER_new();
1649 if (ai == NULL) goto err;
1650 if (!a2i_ASN1_INTEGER(in,ai,buf,1024))
1652 BIO_printf(bio_err,"unable to load number from %s\n",
1656 ret=ASN1_INTEGER_to_BN(ai,NULL);
1659 BIO_printf(bio_err,"error converting number from bin to BIGNUM");
1663 if (in != NULL) BIO_free(in);
1664 if (ai != NULL) ASN1_INTEGER_free(ai);
1668 static int save_serial(char *serialfile, BIGNUM *serial)
1672 ASN1_INTEGER *ai=NULL;
1674 out=BIO_new(BIO_s_file());
1677 ERR_print_errors(bio_err);
1680 if (BIO_write_filename(out,serialfile) <= 0)
1686 if ((ai=BN_to_ASN1_INTEGER(serial,NULL)) == NULL)
1688 BIO_printf(bio_err,"error converting serial to ASN.1 format\n");
1691 i2a_ASN1_INTEGER(out,ai);
1695 if (out != NULL) BIO_free_all(out);
1696 if (ai != NULL) ASN1_INTEGER_free(ai);
1700 static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1701 const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
1702 BIGNUM *serial, char *subj, char *startdate, char *enddate, long days,
1703 int batch, char *ext_sect, CONF *lconf, int verbose,
1704 unsigned long certopt, unsigned long nameopt, int default_op,
1709 EVP_PKEY *pktmp=NULL;
1712 in=BIO_new(BIO_s_file());
1714 if (BIO_read_filename(in,infile) <= 0)
1719 if ((req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL)) == NULL)
1721 BIO_printf(bio_err,"Error reading certificate request in %s\n",
1726 X509_REQ_print(bio_err,req);
1728 BIO_printf(bio_err,"Check that the request matches the signature\n");
1730 if ((pktmp=X509_REQ_get_pubkey(req)) == NULL)
1732 BIO_printf(bio_err,"error unpacking public key\n");
1735 i=X509_REQ_verify(req,pktmp);
1736 EVP_PKEY_free(pktmp);
1740 BIO_printf(bio_err,"Signature verification problems....\n");
1746 BIO_printf(bio_err,"Signature did not match the certificate request\n");
1750 BIO_printf(bio_err,"Signature ok\n");
1752 ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,startdate, enddate,
1753 days,batch,verbose,req,ext_sect,lconf,
1754 certopt, nameopt, default_op, ext_copy);
1757 if (req != NULL) X509_REQ_free(req);
1758 if (in != NULL) BIO_free(in);
1762 static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1763 const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
1764 BIGNUM *serial, char *subj, char *startdate, char *enddate, long days,
1765 int batch, char *ext_sect, CONF *lconf, int verbose,
1766 unsigned long certopt, unsigned long nameopt, int default_op,
1767 int ext_copy, ENGINE *e)
1770 X509_REQ *rreq=NULL;
1771 EVP_PKEY *pktmp=NULL;
1774 if ((req=load_cert(bio_err, infile, FORMAT_PEM, NULL, e, infile)) == NULL)
1777 X509_print(bio_err,req);
1779 BIO_printf(bio_err,"Check that the request matches the signature\n");
1781 if ((pktmp=X509_get_pubkey(req)) == NULL)
1783 BIO_printf(bio_err,"error unpacking public key\n");
1786 i=X509_verify(req,pktmp);
1787 EVP_PKEY_free(pktmp);
1791 BIO_printf(bio_err,"Signature verification problems....\n");
1797 BIO_printf(bio_err,"Signature did not match the certificate\n");
1801 BIO_printf(bio_err,"Signature ok\n");
1803 if ((rreq=X509_to_X509_REQ(req,NULL,EVP_md5())) == NULL)
1806 ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,startdate,enddate,days,
1807 batch,verbose,rreq,ext_sect,lconf, certopt, nameopt, default_op,
1811 if (rreq != NULL) X509_REQ_free(rreq);
1812 if (req != NULL) X509_free(req);
1816 static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
1817 STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial, char *subj,
1818 char *startdate, char *enddate, long days, int batch, int verbose,
1819 X509_REQ *req, char *ext_sect, CONF *lconf,
1820 unsigned long certopt, unsigned long nameopt, int default_op,
1823 X509_NAME *name=NULL,*CAname=NULL,*subject=NULL;
1824 ASN1_UTCTIME *tm,*tmptm;
1825 ASN1_STRING *str,*str2;
1829 X509_NAME_ENTRY *ne;
1830 X509_NAME_ENTRY *tne,*push;
1832 int ok= -1,i,j,last,nid;
1835 char *row[DB_NUMBER],**rrow,**irow=NULL;
1838 tmptm=ASN1_UTCTIME_new();
1841 BIO_printf(bio_err,"malloc error\n");
1845 for (i=0; i<DB_NUMBER; i++)
1850 X509_NAME *n = do_subject(subj);
1854 ERR_print_errors(bio_err);
1857 X509_REQ_set_subject_name(req,n);
1858 req->req_info->enc.modified = 1;
1863 BIO_printf(bio_err,"The Subject's Distinguished Name is as follows\n");
1864 name=X509_REQ_get_subject_name(req);
1865 for (i=0; i<X509_NAME_entry_count(name); i++)
1867 ne= X509_NAME_get_entry(name,i);
1868 str=X509_NAME_ENTRY_get_data(ne);
1869 obj=X509_NAME_ENTRY_get_object(ne);
1873 /* assume all type should be strings */
1874 nid=OBJ_obj2nid(ne->object);
1876 if (str->type == V_ASN1_UNIVERSALSTRING)
1877 ASN1_UNIVERSALSTRING_to_string(str);
1879 if ((str->type == V_ASN1_IA5STRING) &&
1880 (nid != NID_pkcs9_emailAddress))
1881 str->type=V_ASN1_T61STRING;
1883 if ((nid == NID_pkcs9_emailAddress) &&
1884 (str->type == V_ASN1_PRINTABLESTRING))
1885 str->type=V_ASN1_IA5STRING;
1888 /* check some things */
1889 if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) &&
1890 (str->type != V_ASN1_IA5STRING))
1892 BIO_printf(bio_err,"\nemailAddress type needs to be of type IA5STRING\n");
1895 j=ASN1_PRINTABLE_type(str->data,str->length);
1896 if ( ((j == V_ASN1_T61STRING) &&
1897 (str->type != V_ASN1_T61STRING)) ||
1898 ((j == V_ASN1_IA5STRING) &&
1899 (str->type == V_ASN1_PRINTABLESTRING)))
1901 BIO_printf(bio_err,"\nThe string contains characters that are illegal for the ASN.1 type\n");
1906 old_entry_print(bio_err, obj, str);
1909 /* Ok, now we check the 'policy' stuff. */
1910 if ((subject=X509_NAME_new()) == NULL)
1912 BIO_printf(bio_err,"Memory allocation failure\n");
1916 /* take a copy of the issuer name before we mess with it. */
1917 CAname=X509_NAME_dup(x509->cert_info->subject);
1918 if (CAname == NULL) goto err;
1921 for (i=0; i<sk_CONF_VALUE_num(policy); i++)
1923 cv=sk_CONF_VALUE_value(policy,i); /* get the object id */
1924 if ((j=OBJ_txt2nid(cv->name)) == NID_undef)
1926 BIO_printf(bio_err,"%s:unknown object type in 'policy' configuration\n",cv->name);
1934 /* lookup the object in the supplied name list */
1935 j=X509_NAME_get_index_by_OBJ(name,obj,last);
1938 if (last != -1) break;
1943 tne=X509_NAME_get_entry(name,j);
1947 /* depending on the 'policy', decide what to do. */
1949 if (strcmp(cv->value,"optional") == 0)
1954 else if (strcmp(cv->value,"supplied") == 0)
1958 BIO_printf(bio_err,"The %s field needed to be supplied and was missing\n",cv->name);
1964 else if (strcmp(cv->value,"match") == 0)
1970 BIO_printf(bio_err,"The mandatory %s field was missing\n",cv->name);
1977 j=X509_NAME_get_index_by_OBJ(CAname,obj,last2);
1978 if ((j < 0) && (last2 == -1))
1980 BIO_printf(bio_err,"The %s field does not exist in the CA certificate,\nthe 'policy' is misconfigured\n",cv->name);
1985 push=X509_NAME_get_entry(CAname,j);
1986 str=X509_NAME_ENTRY_get_data(tne);
1987 str2=X509_NAME_ENTRY_get_data(push);
1989 if (ASN1_STRING_cmp(str,str2) != 0)
1994 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));
2000 BIO_printf(bio_err,"%s:invalid type in 'policy' configuration\n",cv->value);
2006 if (!X509_NAME_add_entry(subject,push, -1, 0))
2009 X509_NAME_ENTRY_free(push);
2010 BIO_printf(bio_err,"Memory allocation failure\n");
2020 X509_NAME_free(subject);
2021 subject=X509_NAME_dup(X509_REQ_get_subject_name(req));
2022 if (subject == NULL) goto err;
2026 BIO_printf(bio_err,"The subject name appears to be ok, checking data base for clashes\n");
2028 row[DB_name]=X509_NAME_oneline(subject,NULL,0);
2029 row[DB_serial]=BN_bn2hex(serial);
2030 if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
2032 BIO_printf(bio_err,"Memory allocation failure\n");
2036 rrow=TXT_DB_get_by_index(db,DB_name,row);
2039 BIO_printf(bio_err,"ERROR:There is already a certificate for %s\n",
2044 rrow=TXT_DB_get_by_index(db,DB_serial,row);
2047 BIO_printf(bio_err,"ERROR:Serial number %s has already been issued,\n",
2049 BIO_printf(bio_err," check the database/serial_file for corruption\n");
2056 "The matching entry has the following details\n");
2057 if (rrow[DB_type][0] == 'E')
2059 else if (rrow[DB_type][0] == 'R')
2061 else if (rrow[DB_type][0] == 'V')
2064 p="\ninvalid type, Data base error\n";
2065 BIO_printf(bio_err,"Type :%s\n",p);;
2066 if (rrow[DB_type][0] == 'R')
2068 p=rrow[DB_exp_date]; if (p == NULL) p="undef";
2069 BIO_printf(bio_err,"Was revoked on:%s\n",p);
2071 p=rrow[DB_exp_date]; if (p == NULL) p="undef";
2072 BIO_printf(bio_err,"Expires on :%s\n",p);
2073 p=rrow[DB_serial]; if (p == NULL) p="undef";
2074 BIO_printf(bio_err,"Serial Number :%s\n",p);
2075 p=rrow[DB_file]; if (p == NULL) p="undef";
2076 BIO_printf(bio_err,"File name :%s\n",p);
2077 p=rrow[DB_name]; if (p == NULL) p="undef";
2078 BIO_printf(bio_err,"Subject Name :%s\n",p);
2079 ok= -1; /* This is now a 'bad' error. */
2083 /* We are now totally happy, lets make and sign the certificate */
2085 BIO_printf(bio_err,"Everything appears to be ok, creating and signing the certificate\n");
2087 if ((ret=X509_new()) == NULL) goto err;
2091 /* Make it an X509 v3 certificate. */
2092 if (!X509_set_version(x509,2)) goto err;
2095 if (BN_to_ASN1_INTEGER(serial,ci->serialNumber) == NULL)
2097 if (!X509_set_issuer_name(ret,X509_get_subject_name(x509)))
2100 if (strcmp(startdate,"today") == 0)
2101 X509_gmtime_adj(X509_get_notBefore(ret),0);
2102 else ASN1_UTCTIME_set_string(X509_get_notBefore(ret),startdate);
2104 if (enddate == NULL)
2105 X509_gmtime_adj(X509_get_notAfter(ret),(long)60*60*24*days);
2106 else ASN1_UTCTIME_set_string(X509_get_notAfter(ret),enddate);
2108 if (!X509_set_subject_name(ret,subject)) goto err;
2110 pktmp=X509_REQ_get_pubkey(req);
2111 i = X509_set_pubkey(ret,pktmp);
2112 EVP_PKEY_free(pktmp);
2115 /* Lets add the extensions, if there are any */
2119 if (ci->version == NULL)
2120 if ((ci->version=ASN1_INTEGER_new()) == NULL)
2122 ASN1_INTEGER_set(ci->version,2); /* version 3 certificate */
2124 /* Free the current entries if any, there should not
2125 * be any I believe */
2126 if (ci->extensions != NULL)
2127 sk_X509_EXTENSION_pop_free(ci->extensions,
2128 X509_EXTENSION_free);
2130 ci->extensions = NULL;
2132 /* Initialize the context structure */
2133 X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0);
2138 BIO_printf(bio_err, "Extra configuration file found\n");
2140 /* Use the extconf configuration db LHASH */
2141 X509V3_set_nconf(&ctx, extconf);
2143 /* Test the structure (needed?) */
2144 /* X509V3_set_ctx_test(&ctx); */
2146 /* Adds exts contained in the configuration file */
2147 if (!X509V3_EXT_add_nconf(extconf, &ctx, ext_sect,ret))
2150 "ERROR: adding extensions in section %s\n",
2152 ERR_print_errors(bio_err);
2156 BIO_printf(bio_err, "Successfully added extensions from file.\n");
2160 /* We found extensions to be set from config file */
2161 X509V3_set_nconf(&ctx, lconf);
2163 if(!X509V3_EXT_add_nconf(lconf, &ctx, ext_sect, ret))
2165 BIO_printf(bio_err, "ERROR: adding extensions in section %s\n", ext_sect);
2166 ERR_print_errors(bio_err);
2171 BIO_printf(bio_err, "Successfully added extensions from config\n");
2175 /* Copy extensions from request (if any) */
2177 if (!copy_extensions(ret, req, ext_copy))
2179 BIO_printf(bio_err, "ERROR: adding extensions from request\n");
2180 ERR_print_errors(bio_err);
2187 BIO_printf(bio_err, "Certificate Details:\n");
2188 /* Never print signature details because signature not present */
2189 certopt |= X509_FLAG_NO_SIGDUMP | X509_FLAG_NO_SIGNAME;
2190 X509_print_ex(bio_err, ret, nameopt, certopt);
2193 BIO_printf(bio_err,"Certificate is to be certified until ");
2194 ASN1_UTCTIME_print(bio_err,X509_get_notAfter(ret));
2195 if (days) BIO_printf(bio_err," (%d days)",days);
2196 BIO_printf(bio_err, "\n");
2201 BIO_printf(bio_err,"Sign the certificate? [y/n]:");
2202 (void)BIO_flush(bio_err);
2204 fgets(buf,sizeof(buf)-1,stdin);
2205 if (!((buf[0] == 'y') || (buf[0] == 'Y')))
2207 BIO_printf(bio_err,"CERTIFICATE WILL NOT BE CERTIFIED\n");
2214 #ifndef OPENSSL_NO_DSA
2215 if (pkey->type == EVP_PKEY_DSA) dgst=EVP_dss1();
2216 pktmp=X509_get_pubkey(ret);
2217 if (EVP_PKEY_missing_parameters(pktmp) &&
2218 !EVP_PKEY_missing_parameters(pkey))
2219 EVP_PKEY_copy_parameters(pktmp,pkey);
2220 EVP_PKEY_free(pktmp);
2223 if (!X509_sign(ret,pkey,dgst))
2226 /* We now just add it to the database */
2227 row[DB_type]=(char *)OPENSSL_malloc(2);
2229 tm=X509_get_notAfter(ret);
2230 row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
2231 memcpy(row[DB_exp_date],tm->data,tm->length);
2232 row[DB_exp_date][tm->length]='\0';
2234 row[DB_rev_date]=NULL;
2236 /* row[DB_serial] done already */
2237 row[DB_file]=(char *)OPENSSL_malloc(8);
2238 /* row[DB_name] done already */
2240 if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2241 (row[DB_file] == NULL))
2243 BIO_printf(bio_err,"Memory allocation failure\n");
2246 strcpy(row[DB_file],"unknown");
2247 row[DB_type][0]='V';
2248 row[DB_type][1]='\0';
2250 if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
2252 BIO_printf(bio_err,"Memory allocation failure\n");
2256 for (i=0; i<DB_NUMBER; i++)
2261 irow[DB_NUMBER]=NULL;
2263 if (!TXT_DB_insert(db,irow))
2265 BIO_printf(bio_err,"failed to update database\n");
2266 BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
2271 for (i=0; i<DB_NUMBER; i++)
2272 if (row[i] != NULL) OPENSSL_free(row[i]);
2275 X509_NAME_free(CAname);
2276 if (subject != NULL)
2277 X509_NAME_free(subject);
2279 ASN1_UTCTIME_free(tmptm);
2282 if (ret != NULL) X509_free(ret);
2290 static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext)
2295 (void)i2d_X509_bio(bp,x);
2299 /* ??? Not needed since X509_print prints all this stuff anyway */
2300 f=X509_NAME_oneline(X509_get_issuer_name(x),buf,256);
2301 BIO_printf(bp,"issuer :%s\n",f);
2303 f=X509_NAME_oneline(X509_get_subject_name(x),buf,256);
2304 BIO_printf(bp,"subject:%s\n",f);
2306 BIO_puts(bp,"serial :");
2307 i2a_ASN1_INTEGER(bp,x->cert_info->serialNumber);
2308 BIO_puts(bp,"\n\n");
2310 if (!notext)X509_print(bp,x);
2311 PEM_write_bio_X509(bp,x);
2314 static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
2315 const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
2316 BIGNUM *serial, char *subj, char *startdate, char *enddate, long days,
2317 char *ext_sect, CONF *lconf, int verbose, unsigned long certopt,
2318 unsigned long nameopt, int default_op, int ext_copy)
2320 STACK_OF(CONF_VALUE) *sk=NULL;
2323 CONF_VALUE *cv=NULL;
2324 NETSCAPE_SPKI *spki = NULL;
2327 EVP_PKEY *pktmp=NULL;
2329 X509_NAME_ENTRY *ne=NULL;
2335 * Load input file into a hash table. (This is just an easy
2336 * way to read and parse the file, then put it into a convenient
2339 parms=CONF_load(NULL,infile,&errline);
2342 BIO_printf(bio_err,"error on line %ld of %s\n",errline,infile);
2343 ERR_print_errors(bio_err);
2347 sk=CONF_get_section(parms, "default");
2348 if (sk_CONF_VALUE_num(sk) == 0)
2350 BIO_printf(bio_err, "no name/value pairs found in %s\n", infile);
2356 * Now create a dummy X509 request structure. We don't actually
2357 * have an X509 request, but we have many of the components
2358 * (a public key, various DN components). The idea is that we
2359 * put these components into the right X509 request structure
2360 * and we can use the same code as if you had a real X509 request.
2365 ERR_print_errors(bio_err);
2370 * Build up the subject name set.
2377 if (sk_CONF_VALUE_num(sk) <= i) break;
2379 cv=sk_CONF_VALUE_value(sk,i);
2381 /* Skip past any leading X. X: X, etc to allow for
2382 * multiple instances
2384 for (buf = cv->name; *buf ; buf++)
2385 if ((*buf == ':') || (*buf == ',') || (*buf == '.'))
2388 if (*buf) type = buf;
2393 if ((nid=OBJ_txt2nid(type)) == NID_undef)
2395 if (strcmp(type, "SPKAC") == 0)
2397 spki = NETSCAPE_SPKI_b64_decode(cv->value, -1);
2400 BIO_printf(bio_err,"unable to load Netscape SPKAC structure\n");
2401 ERR_print_errors(bio_err);
2408 j=ASN1_PRINTABLE_type((unsigned char *)buf,-1);
2409 if (fix_data(nid, &j) == 0)
2412 "invalid characters in string %s\n",buf);
2416 if ((ne=X509_NAME_ENTRY_create_by_NID(&ne,nid,j,
2417 (unsigned char *)buf,
2418 strlen(buf))) == NULL)
2421 if (!X509_NAME_add_entry(n,ne,-1, 0)) goto err;
2425 BIO_printf(bio_err,"Netscape SPKAC structure not found in %s\n",
2431 * Now extract the key from the SPKI structure.
2434 BIO_printf(bio_err,"Check that the SPKAC request matches the signature\n");
2436 if ((pktmp=NETSCAPE_SPKI_get_pubkey(spki)) == NULL)
2438 BIO_printf(bio_err,"error unpacking SPKAC public key\n");
2442 j = NETSCAPE_SPKI_verify(spki, pktmp);
2445 BIO_printf(bio_err,"signature verification failed on SPKAC public key\n");
2448 BIO_printf(bio_err,"Signature ok\n");
2450 X509_REQ_set_pubkey(req,pktmp);
2451 EVP_PKEY_free(pktmp);
2452 ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,startdate,enddate,
2453 days,1,verbose,req,ext_sect,lconf, certopt, nameopt, default_op,
2456 if (req != NULL) X509_REQ_free(req);
2457 if (parms != NULL) CONF_free(parms);
2458 if (spki != NULL) NETSCAPE_SPKI_free(spki);
2459 if (ne != NULL) X509_NAME_ENTRY_free(ne);
2464 static int fix_data(int nid, int *type)
2466 if (nid == NID_pkcs9_emailAddress)
2467 *type=V_ASN1_IA5STRING;
2468 if ((nid == NID_commonName) && (*type == V_ASN1_IA5STRING))
2469 *type=V_ASN1_T61STRING;
2470 if ((nid == NID_pkcs9_challengePassword) && (*type == V_ASN1_IA5STRING))
2471 *type=V_ASN1_T61STRING;
2472 if ((nid == NID_pkcs9_unstructuredName) && (*type == V_ASN1_T61STRING))
2474 if (nid == NID_pkcs9_unstructuredName)
2475 *type=V_ASN1_IA5STRING;
2479 static int check_time_format(char *str)
2483 tm.data=(unsigned char *)str;
2484 tm.length=strlen(str);
2485 tm.type=V_ASN1_UTCTIME;
2486 return(ASN1_UTCTIME_check(&tm));
2489 static int do_revoke(X509 *x509, TXT_DB *db, int type, char *value)
2491 ASN1_UTCTIME *tm=NULL;
2492 char *row[DB_NUMBER],**rrow,**irow;
2493 char *rev_str = NULL;
2497 for (i=0; i<DB_NUMBER; i++)
2499 row[DB_name]=X509_NAME_oneline(X509_get_subject_name(x509),NULL,0);
2500 bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509),NULL);
2501 row[DB_serial]=BN_bn2hex(bn);
2503 if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
2505 BIO_printf(bio_err,"Memory allocation failure\n");
2508 /* We have to lookup by serial number because name lookup
2509 * skips revoked certs
2511 rrow=TXT_DB_get_by_index(db,DB_serial,row);
2514 BIO_printf(bio_err,"Adding Entry to DB for %s\n", row[DB_name]);
2516 /* We now just add it to the database */
2517 row[DB_type]=(char *)OPENSSL_malloc(2);
2519 tm=X509_get_notAfter(x509);
2520 row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
2521 memcpy(row[DB_exp_date],tm->data,tm->length);
2522 row[DB_exp_date][tm->length]='\0';
2524 row[DB_rev_date]=NULL;
2526 /* row[DB_serial] done already */
2527 row[DB_file]=(char *)OPENSSL_malloc(8);
2529 /* row[DB_name] done already */
2531 if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2532 (row[DB_file] == NULL))
2534 BIO_printf(bio_err,"Memory allocation failure\n");
2537 strcpy(row[DB_file],"unknown");
2538 row[DB_type][0]='V';
2539 row[DB_type][1]='\0';
2541 if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
2543 BIO_printf(bio_err,"Memory allocation failure\n");
2547 for (i=0; i<DB_NUMBER; i++)
2552 irow[DB_NUMBER]=NULL;
2554 if (!TXT_DB_insert(db,irow))
2556 BIO_printf(bio_err,"failed to update database\n");
2557 BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
2561 /* Revoke Certificate */
2562 ok = do_revoke(x509,db, type, value);
2567 else if (index_name_cmp((const char **)row,(const char **)rrow))
2569 BIO_printf(bio_err,"ERROR:name does not match %s\n",
2573 else if (rrow[DB_type][0]=='R')
2575 BIO_printf(bio_err,"ERROR:Already revoked, serial number %s\n",
2581 BIO_printf(bio_err,"Revoking Certificate %s.\n", rrow[DB_serial]);
2582 rev_str = make_revocation_str(type, value);
2585 BIO_printf(bio_err, "Error in revocation arguments\n");
2588 rrow[DB_type][0]='R';
2589 rrow[DB_type][1]='\0';
2590 rrow[DB_rev_date] = rev_str;
2594 for (i=0; i<DB_NUMBER; i++)
2597 OPENSSL_free(row[i]);
2602 static int get_certificate_status(const char *serial, TXT_DB *db)
2604 char *row[DB_NUMBER],**rrow;
2607 /* Free Resources */
2608 for (i=0; i<DB_NUMBER; i++)
2611 /* Malloc needed char spaces */
2612 row[DB_serial] = OPENSSL_malloc(strlen(serial) + 2);
2613 if (row[DB_serial] == NULL)
2615 BIO_printf(bio_err,"Malloc failure\n");
2619 if (strlen(serial) % 2)
2621 /* Set the first char to 0 */;
2622 row[DB_serial][0]='0';
2624 /* Copy String from serial to row[DB_serial] */
2625 memcpy(row[DB_serial]+1, serial, strlen(serial));
2626 row[DB_serial][strlen(serial)+1]='\0';
2630 /* Copy String from serial to row[DB_serial] */
2631 memcpy(row[DB_serial], serial, strlen(serial));
2632 row[DB_serial][strlen(serial)]='\0';
2635 /* Make it Upper Case */
2636 for (i=0; row[DB_serial][i] != '\0'; i++)
2637 row[DB_serial][i] = toupper(row[DB_serial][i]);
2642 /* Search for the certificate */
2643 rrow=TXT_DB_get_by_index(db,DB_serial,row);
2646 BIO_printf(bio_err,"Serial %s not present in db.\n",
2651 else if (rrow[DB_type][0]=='V')
2653 BIO_printf(bio_err,"%s=Valid (%c)\n",
2654 row[DB_serial], rrow[DB_type][0]);
2657 else if (rrow[DB_type][0]=='R')
2659 BIO_printf(bio_err,"%s=Revoked (%c)\n",
2660 row[DB_serial], rrow[DB_type][0]);
2663 else if (rrow[DB_type][0]=='E')
2665 BIO_printf(bio_err,"%s=Expired (%c)\n",
2666 row[DB_serial], rrow[DB_type][0]);
2669 else if (rrow[DB_type][0]=='S')
2671 BIO_printf(bio_err,"%s=Suspended (%c)\n",
2672 row[DB_serial], rrow[DB_type][0]);
2677 BIO_printf(bio_err,"%s=Unknown (%c).\n",
2678 row[DB_serial], rrow[DB_type][0]);
2682 for (i=0; i<DB_NUMBER; i++)
2685 OPENSSL_free(row[i]);
2690 static int do_updatedb (TXT_DB *db)
2692 ASN1_UTCTIME *a_tm = NULL;
2694 int db_y2k, a_y2k; /* flags = 1 if y >= 2000 */
2695 char **rrow, *a_tm_s;
2697 a_tm = ASN1_UTCTIME_new();
2699 /* get actual time and make a string */
2700 a_tm = X509_gmtime_adj(a_tm, 0);
2701 a_tm_s = (char *) OPENSSL_malloc(a_tm->length+1);
2708 memcpy(a_tm_s, a_tm->data, a_tm->length);
2709 a_tm_s[a_tm->length] = '\0';
2711 if (strncmp(a_tm_s, "49", 2) <= 0)
2716 for (i = 0; i < sk_num(db->data); i++)
2718 rrow = (char **) sk_value(db->data, i);
2720 if (rrow[DB_type][0] == 'V')
2722 /* ignore entries that are not valid */
2723 if (strncmp(rrow[DB_exp_date], "49", 2) <= 0)
2728 if (db_y2k == a_y2k)
2730 /* all on the same y2k side */
2731 if (strcmp(rrow[DB_exp_date], a_tm_s) <= 0)
2733 rrow[DB_type][0] = 'E';
2734 rrow[DB_type][1] = '\0';
2737 BIO_printf(bio_err, "%s=Expired\n",
2741 else if (db_y2k < a_y2k)
2743 rrow[DB_type][0] = 'E';
2744 rrow[DB_type][1] = '\0';
2747 BIO_printf(bio_err, "%s=Expired\n",
2756 ASN1_UTCTIME_free(a_tm);
2757 OPENSSL_free(a_tm_s);
2762 static char *crl_reasons[] = {
2763 /* CRL reason strings */
2767 "affiliationChanged",
2769 "cessationOfOperation",
2772 /* Additional pseudo reasons */
2778 #define NUM_REASONS (sizeof(crl_reasons) / sizeof(char *))
2780 /* Given revocation information convert to a DB string.
2781 * The format of the string is:
2782 * revtime[,reason,extra]. Where 'revtime' is the
2783 * revocation time (the current time). 'reason' is the
2784 * optional CRL reason and 'extra' is any additional
2788 char *make_revocation_str(int rev_type, char *rev_arg)
2790 char *reason = NULL, *other = NULL, *str;
2792 ASN1_UTCTIME *revtm = NULL;
2799 case REV_CRL_REASON:
2800 for (i = 0; i < 8; i++)
2802 if (!strcasecmp(rev_arg, crl_reasons[i]))
2804 reason = crl_reasons[i];
2810 BIO_printf(bio_err, "Unknown CRL reason %s\n", rev_arg);
2816 /* Argument is an OID */
2818 otmp = OBJ_txt2obj(rev_arg, 0);
2819 ASN1_OBJECT_free(otmp);
2823 BIO_printf(bio_err, "Invalid object identifier %s\n", rev_arg);
2827 reason = "holdInstruction";
2831 case REV_KEY_COMPROMISE:
2832 case REV_CA_COMPROMISE:
2834 /* Argument is the key compromise time */
2835 if (!ASN1_GENERALIZEDTIME_set_string(NULL, rev_arg))
2837 BIO_printf(bio_err, "Invalid time format %s. Need YYYYMMDDHHMMSSZ\n", rev_arg);
2841 if (rev_type == REV_KEY_COMPROMISE)
2844 reason = "CAkeyTime";
2850 revtm = X509_gmtime_adj(NULL, 0);
2852 i = revtm->length + 1;
2854 if (reason) i += strlen(reason) + 1;
2855 if (other) i += strlen(other) + 1;
2857 str = OPENSSL_malloc(i);
2859 if (!str) return NULL;
2861 strcpy(str, (char *)revtm->data);
2865 strcat(str, reason);
2872 ASN1_UTCTIME_free(revtm);
2876 /* Convert revocation field to X509_REVOKED entry
2880 * 2 OK and some extensions added (i.e. V2 CRL)
2884 int make_revoked(X509_REVOKED *rev, char *str)
2887 int reason_code = -1;
2889 ASN1_OBJECT *hold = NULL;
2890 ASN1_GENERALIZEDTIME *comp_time = NULL;
2891 ASN1_ENUMERATED *rtmp = NULL;
2893 ASN1_TIME *revDate = NULL;
2895 i = unpack_revinfo(&revDate, &reason_code, &hold, &comp_time, str);
2900 if (rev && !X509_REVOKED_set_revocationDate(rev, revDate))
2903 if (rev && (reason_code != OCSP_REVOKED_STATUS_NOSTATUS))
2905 rtmp = ASN1_ENUMERATED_new();
2906 if (!rtmp || !ASN1_ENUMERATED_set(rtmp, reason_code))
2908 if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0))
2912 if (rev && comp_time)
2914 if (!X509_REVOKED_add1_ext_i2d(rev, NID_invalidity_date, comp_time, 0, 0))
2919 if (!X509_REVOKED_add1_ext_i2d(rev, NID_hold_instruction_code, hold, 0, 0))
2923 if (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)
2929 if (tmp) OPENSSL_free(tmp);
2930 ASN1_OBJECT_free(hold);
2931 ASN1_GENERALIZEDTIME_free(comp_time);
2932 ASN1_ENUMERATED_free(rtmp);
2933 ASN1_TIME_free(revDate);
2938 static X509_NAME *do_subject(char *subject)
2940 X509_NAME *n = NULL;
2942 int i, nid, ne_num=0;
2944 char *ne_name = NULL;
2945 char *ne_value = NULL;
2950 char *str_list[256];
2955 n = X509_NAME_new();
2957 tmp = strtok(subject, p[0]);
2958 while((tmp != NULL) && (ne_num < (sizeof str_list/sizeof *str_list)))
2962 while (token[0] == ' ')
2964 str_list[ne_num] = token;
2966 tmp = strtok(NULL, p[0]);
2970 for (i = 0; i < ne_num; i++)
2972 ne_name = strtok(str_list[i], p[1]);
2973 ne_value = strtok(NULL, p[1]);
2975 if ((nid=OBJ_txt2nid(ne_name)) == NID_undef)
2977 BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_name);
2981 if (ne_value == NULL)
2983 BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_name);
2987 if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_ASC, (unsigned char*)ne_value, -1,-1,0))
2998 int old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str)
3000 char buf[25],*pbuf, *p;
3002 j=i2a_ASN1_OBJECT(bp,obj);
3004 for (j=22-j; j>0; j--)
3010 if (str->type == V_ASN1_PRINTABLESTRING)
3011 BIO_printf(bp,"PRINTABLE:'");
3012 else if (str->type == V_ASN1_T61STRING)
3013 BIO_printf(bp,"T61STRING:'");
3014 else if (str->type == V_ASN1_IA5STRING)
3015 BIO_printf(bp,"IA5STRING:'");
3016 else if (str->type == V_ASN1_UNIVERSALSTRING)
3017 BIO_printf(bp,"UNIVERSALSTRING:'");
3019 BIO_printf(bp,"ASN.1 %2d:'",str->type);
3021 p=(char *)str->data;
3022 for (j=str->length; j>0; j--)
3024 if ((*p >= ' ') && (*p <= '~'))
3025 BIO_printf(bp,"%c",*p);
3027 BIO_printf(bp,"\\0x%02X",*p);
3028 else if ((unsigned char)*p == 0xf7)
3029 BIO_printf(bp,"^?");
3030 else BIO_printf(bp,"^%c",*p+'@');
3033 BIO_printf(bp,"'\n");
3037 int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, ASN1_GENERALIZEDTIME **pinvtm, char *str)
3040 char *rtime_str, *reason_str = NULL, *arg_str = NULL, *p;
3041 int reason_code = -1;
3043 ASN1_OBJECT *hold = NULL;
3044 ASN1_GENERALIZEDTIME *comp_time = NULL;
3045 tmp = BUF_strdup(str);
3047 p = strchr(tmp, ',');
3066 *prevtm = ASN1_UTCTIME_new();
3067 if (!ASN1_UTCTIME_set_string(*prevtm, rtime_str))
3069 BIO_printf(bio_err, "invalid revocation date %s\n", rtime_str);
3075 for (i = 0; i < NUM_REASONS; i++)
3077 if(!strcasecmp(reason_str, crl_reasons[i]))
3083 if (reason_code == OCSP_REVOKED_STATUS_NOSTATUS)
3085 BIO_printf(bio_err, "invalid reason code %s\n", reason_str);
3089 if (reason_code == 7)
3090 reason_code = OCSP_REVOKED_STATUS_REMOVEFROMCRL;
3091 else if (reason_code == 8) /* Hold instruction */
3095 BIO_printf(bio_err, "missing hold instruction\n");
3098 reason_code = OCSP_REVOKED_STATUS_CERTIFICATEHOLD;
3099 hold = OBJ_txt2obj(arg_str, 0);
3103 BIO_printf(bio_err, "invalid object identifier %s\n", arg_str);
3106 if (phold) *phold = hold;
3108 else if ((reason_code == 9) || (reason_code == 10))
3112 BIO_printf(bio_err, "missing compromised time\n");
3115 comp_time = ASN1_GENERALIZEDTIME_new();
3116 if (!ASN1_GENERALIZEDTIME_set_string(comp_time, arg_str))
3118 BIO_printf(bio_err, "invalid compromised time %s\n", arg_str);
3121 if (reason_code == 9)
3122 reason_code = OCSP_REVOKED_STATUS_KEYCOMPROMISE;
3124 reason_code = OCSP_REVOKED_STATUS_CACOMPROMISE;
3128 if (preason) *preason = reason_code;
3129 if (pinvtm) *pinvtm = comp_time;
3130 else ASN1_GENERALIZEDTIME_free(comp_time);
3136 if (tmp) OPENSSL_free(tmp);
3137 if (!phold) ASN1_OBJECT_free(hold);
3138 if (!pinvtm) ASN1_GENERALIZEDTIME_free(comp_time);
3143 int make_serial_index(TXT_DB *db)
3145 if (!TXT_DB_create_index(db, DB_serial, NULL,
3146 LHASH_HASH_FN(index_serial_hash),
3147 LHASH_COMP_FN(index_serial_cmp)))
3150 "error creating serial number index:(%ld,%ld,%ld)\n",
3151 db->error,db->arg1,db->arg2);