2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
5 * This package is an SSL implementation written
6 * by Eric Young (eay@cryptsoft.com).
7 * The implementation was written so as to conform with Netscapes SSL.
9 * This library is free for commercial and non-commercial use as long as
10 * the following conditions are aheared to. The following conditions
11 * apply to all code found in this distribution, be it the RC4, RSA,
12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
13 * included with this distribution is covered by the same copyright terms
14 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
16 * Copyright remains Eric Young's, and as such any Copyright notices in
17 * the code are not to be removed.
18 * If this package is used in a product, Eric Young should be given attribution
19 * as the author of the parts of the library used.
20 * This can be in the form of a textual message at program startup or
21 * in documentation (online or textual) provided with the package.
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
26 * 1. Redistributions of source code must retain the copyright
27 * notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 * notice, this list of conditions and the following disclaimer in the
30 * documentation and/or other materials provided with the distribution.
31 * 3. All advertising materials mentioning features or use of this software
32 * must display the following acknowledgement:
33 * "This product includes cryptographic software written by
34 * Eric Young (eay@cryptsoft.com)"
35 * The word 'cryptographic' can be left out if the rouines from the library
36 * being used are not cryptographic related :-).
37 * 4. If you include any Windows specific code (or a derivative thereof) from
38 * the apps directory (application code) you must include an acknowledgement:
39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53 * The licence and distribution terms for any publically available version or
54 * derivative of this code cannot be changed. i.e. this code cannot simply be
55 * copied and put under another distribution licence
56 * [including the GNU Public Licence.]
59 /* The PPKI stuff has been donated by Jeff Barber <jeffb@issl.atl.hp.com> */
65 #include <sys/types.h>
68 #include <openssl/conf.h>
69 #include <openssl/bio.h>
70 #include <openssl/err.h>
71 #include <openssl/bn.h>
72 #include <openssl/txt_db.h>
73 #include <openssl/evp.h>
74 #include <openssl/x509.h>
75 #include <openssl/x509v3.h>
76 #include <openssl/objects.h>
77 #include <openssl/ocsp.h>
78 #include <openssl/pem.h>
79 #include <openssl/engine.h>
81 #ifdef OPENSSL_SYS_WINDOWS
82 #define strcasecmp _stricmp
88 # ifdef OPENSSL_SYS_VMS
95 # include <sys/file.h>
109 #define BASE_SECTION "ca"
110 #define CONFIG_FILE "openssl.cnf"
112 #define ENV_DEFAULT_CA "default_ca"
114 #define ENV_DIR "dir"
115 #define ENV_CERTS "certs"
116 #define ENV_CRL_DIR "crl_dir"
117 #define ENV_CA_DB "CA_DB"
118 #define ENV_NEW_CERTS_DIR "new_certs_dir"
119 #define ENV_CERTIFICATE "certificate"
120 #define ENV_SERIAL "serial"
121 #define ENV_CRL "crl"
122 #define ENV_PRIVATE_KEY "private_key"
123 #define ENV_RANDFILE "RANDFILE"
124 #define ENV_DEFAULT_DAYS "default_days"
125 #define ENV_DEFAULT_STARTDATE "default_startdate"
126 #define ENV_DEFAULT_ENDDATE "default_enddate"
127 #define ENV_DEFAULT_CRL_DAYS "default_crl_days"
128 #define ENV_DEFAULT_CRL_HOURS "default_crl_hours"
129 #define ENV_DEFAULT_MD "default_md"
130 #define ENV_PRESERVE "preserve"
131 #define ENV_POLICY "policy"
132 #define ENV_EXTENSIONS "x509_extensions"
133 #define ENV_CRLEXT "crl_extensions"
134 #define ENV_MSIE_HACK "msie_hack"
135 #define ENV_NAMEOPT "name_opt"
136 #define ENV_CERTOPT "cert_opt"
137 #define ENV_EXTCOPY "copy_extensions"
139 #define ENV_DATABASE "database"
142 #define DB_exp_date 1
143 #define DB_rev_date 2
144 #define DB_serial 3 /* index - unique */
146 #define DB_name 5 /* index - unique for active */
149 #define DB_TYPE_REV 'R'
150 #define DB_TYPE_EXP 'E'
151 #define DB_TYPE_VAL 'V'
153 /* Additional revocation information types */
155 #define REV_NONE 0 /* No addditional information */
156 #define REV_CRL_REASON 1 /* Value is CRL reason code */
157 #define REV_HOLD 2 /* Value is hold instruction */
158 #define REV_KEY_COMPROMISE 3 /* Value is cert key compromise time */
159 #define REV_CA_COMPROMISE 4 /* Value is CA key compromise time */
161 static char *ca_usage[]={
164 " -verbose - Talk alot while doing things\n",
165 " -config file - A config file\n",
166 " -name arg - The particular CA definition to use\n",
167 " -gencrl - Generate a new CRL\n",
168 " -crldays days - Days is when the next CRL is due\n",
169 " -crlhours hours - Hours is when the next CRL is due\n",
170 " -startdate YYMMDDHHMMSSZ - certificate validity notBefore\n",
171 " -enddate YYMMDDHHMMSSZ - certificate validity notAfter (overrides -days)\n",
172 " -days arg - number of days to certify the certificate for\n",
173 " -md arg - md to use, one of md2, md5, sha or sha1\n",
174 " -policy arg - The CA 'policy' to support\n",
175 " -keyfile arg - private key file\n",
176 " -keyform arg - private key file format (PEM or ENGINE)\n",
177 " -key arg - key to decode the private key if it is encrypted\n",
178 " -cert file - The CA certificate\n",
179 " -in file - The input PEM encoded certificate request(s)\n",
180 " -out file - Where to put the output file(s)\n",
181 " -outdir dir - Where to put output certificates\n",
182 " -infiles .... - The last argument, requests to process\n",
183 " -spkac file - File contains DN and signed public key and challenge\n",
184 " -ss_cert file - File contains a self signed cert to sign\n",
185 " -preserveDN - Don't re-order the DN\n",
186 " -batch - Don't ask questions\n",
187 " -msie_hack - msie modifications to handle all those universal strings\n",
188 " -revoke file - Revoke a certificate (given in file)\n",
189 " -subj arg - Use arg instead of request's subject\n",
190 " -extensions .. - Extension section (override value in config file)\n",
191 " -extfile file - Configuration file with X509v3 extentions to add\n",
192 " -crlexts .. - CRL extension section (override value in config file)\n",
193 " -engine e - use engine e, possibly a hardware device.\n",
194 " -status serial - Shows certificate status given the serial number\n",
195 " -updatedb - Updates db for expired certificates\n",
200 extern int EF_PROTECT_FREE;
201 extern int EF_PROTECT_BELOW;
202 extern int EF_ALIGNMENT;
205 static void lookup_fail(char *name,char *tag);
206 static unsigned long index_serial_hash(const char **a);
207 static int index_serial_cmp(const char **a, const char **b);
208 static unsigned long index_name_hash(const char **a);
209 static int index_name_qual(char **a);
210 static int index_name_cmp(const char **a,const char **b);
211 static BIGNUM *load_serial(char *serialfile);
212 static int save_serial(char *serialfile, BIGNUM *serial);
213 static int certify(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
214 const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,TXT_DB *db,
215 BIGNUM *serial, char *subj, char *startdate,char *enddate,
216 int days, int batch, char *ext_sect, LHASH *conf,int verbose,
217 unsigned long certopt, unsigned long nameopt, int default_op,
219 static int certify_cert(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
220 const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
221 TXT_DB *db, BIGNUM *serial, char *subj, char *startdate,
222 char *enddate, int days, int batch, char *ext_sect,
223 LHASH *conf,int verbose, unsigned long certopt,
224 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, int days, char *ext_sect,LHASH *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, int days, int batch, int verbose,
236 X509_REQ *req, char *ext_sect, LHASH *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 LHASH *conf=NULL;
248 static LHASH *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;
278 char *configfile=NULL;
283 int keyform=FORMAT_PEM;
285 char *spkac_file=NULL;
286 char *ss_cert_file=NULL;
287 char *ser_status=NULL;
292 char *serialfile=NULL;
293 char *extensions=NULL;
297 int rev_type = REV_NONE;
298 char *rev_arg = NULL;
300 char *startdate=NULL;
305 unsigned long nameopt = 0, certopt = 0;
307 int ext_copy = EXT_COPY_NONE;
310 BIO *in=NULL,*out=NULL,*Sout=NULL,*Cout=NULL;
314 X509_CRL_INFO *ci=NULL;
315 X509_REVOKED *r=NULL;
319 const EVP_MD *dgst=NULL;
320 STACK_OF(CONF_VALUE) *attribs=NULL;
321 STACK_OF(X509) *cert_sk=NULL;
324 MS_STATIC char buf[3][BSIZE];
343 if ((bio_err=BIO_new(BIO_s_file())) != NULL)
344 BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
350 if (strcmp(*argv,"-verbose") == 0)
352 else if (strcmp(*argv,"-config") == 0)
354 if (--argc < 1) goto bad;
355 configfile= *(++argv);
357 else if (strcmp(*argv,"-name") == 0)
359 if (--argc < 1) goto bad;
362 else if (strcmp(*argv,"-subj") == 0)
364 if (--argc < 1) goto bad;
368 else if (strcmp(*argv,"-startdate") == 0)
370 if (--argc < 1) goto bad;
371 startdate= *(++argv);
373 else if (strcmp(*argv,"-enddate") == 0)
375 if (--argc < 1) goto bad;
378 else if (strcmp(*argv,"-days") == 0)
380 if (--argc < 1) goto bad;
381 days=atoi(*(++argv));
383 else if (strcmp(*argv,"-md") == 0)
385 if (--argc < 1) goto bad;
388 else if (strcmp(*argv,"-policy") == 0)
390 if (--argc < 1) goto bad;
393 else if (strcmp(*argv,"-keyfile") == 0)
395 if (--argc < 1) goto bad;
398 else if (strcmp(*argv,"-keyform") == 0)
400 if (--argc < 1) goto bad;
401 keyform=str2fmt(*(++argv));
403 else if (strcmp(*argv,"-passin") == 0)
405 if (--argc < 1) goto bad;
406 passargin= *(++argv);
408 else if (strcmp(*argv,"-key") == 0)
410 if (--argc < 1) goto bad;
413 else if (strcmp(*argv,"-cert") == 0)
415 if (--argc < 1) goto bad;
418 else if (strcmp(*argv,"-in") == 0)
420 if (--argc < 1) goto bad;
424 else if (strcmp(*argv,"-out") == 0)
426 if (--argc < 1) goto bad;
429 else if (strcmp(*argv,"-outdir") == 0)
431 if (--argc < 1) goto bad;
434 else if (strcmp(*argv,"-notext") == 0)
436 else if (strcmp(*argv,"-batch") == 0)
438 else if (strcmp(*argv,"-preserveDN") == 0)
440 else if (strcmp(*argv,"-gencrl") == 0)
442 else if (strcmp(*argv,"-msie_hack") == 0)
444 else if (strcmp(*argv,"-crldays") == 0)
446 if (--argc < 1) goto bad;
447 crldays= atol(*(++argv));
449 else if (strcmp(*argv,"-crlhours") == 0)
451 if (--argc < 1) goto bad;
452 crlhours= atol(*(++argv));
454 else if (strcmp(*argv,"-infiles") == 0)
461 else if (strcmp(*argv, "-ss_cert") == 0)
463 if (--argc < 1) goto bad;
464 ss_cert_file = *(++argv);
467 else if (strcmp(*argv, "-spkac") == 0)
469 if (--argc < 1) goto bad;
470 spkac_file = *(++argv);
473 else if (strcmp(*argv,"-revoke") == 0)
475 if (--argc < 1) goto bad;
479 else if (strcmp(*argv,"-extensions") == 0)
481 if (--argc < 1) goto bad;
482 extensions= *(++argv);
484 else if (strcmp(*argv,"-extfile") == 0)
486 if (--argc < 1) goto bad;
489 else if (strcmp(*argv,"-status") == 0)
491 if (--argc < 1) goto bad;
492 ser_status= *(++argv);
494 else if (strcmp(*argv,"-updatedb") == 0)
498 else if (strcmp(*argv,"-crlexts") == 0)
500 if (--argc < 1) goto bad;
503 else if (strcmp(*argv,"-crl_reason") == 0)
505 if (--argc < 1) goto bad;
507 rev_type = REV_CRL_REASON;
509 else if (strcmp(*argv,"-crl_hold") == 0)
511 if (--argc < 1) goto bad;
515 else if (strcmp(*argv,"-crl_compromise") == 0)
517 if (--argc < 1) goto bad;
519 rev_type = REV_KEY_COMPROMISE;
521 else if (strcmp(*argv,"-crl_CA_compromise") == 0)
523 if (--argc < 1) goto bad;
525 rev_type = REV_CA_COMPROMISE;
527 else if (strcmp(*argv,"-engine") == 0)
529 if (--argc < 1) goto bad;
535 BIO_printf(bio_err,"unknown option %s\n",*argv);
545 for (pp=ca_usage; (*pp != NULL); pp++)
546 BIO_printf(bio_err,"%s",*pp);
550 ERR_load_crypto_strings();
554 if ((e = ENGINE_by_id(engine)) == NULL)
556 BIO_printf(bio_err,"invalid engine \"%s\"\n",
560 if (!ENGINE_set_default(e, ENGINE_METHOD_ALL))
562 BIO_printf(bio_err,"can't use that engine\n");
565 BIO_printf(bio_err,"engine \"%s\" set.\n", engine);
566 /* Free our "structural" reference. */
570 /*****************************************************************/
571 if (configfile == NULL) configfile = getenv("OPENSSL_CONF");
572 if (configfile == NULL) configfile = getenv("SSLEAY_CONF");
573 if (configfile == NULL)
575 /* We will just use 'buf[0]' as a temporary buffer. */
576 #ifdef OPENSSL_SYS_VMS
577 strncpy(buf[0],X509_get_default_cert_area(),
578 sizeof(buf[0])-1-sizeof(CONFIG_FILE));
580 strncpy(buf[0],X509_get_default_cert_area(),
581 sizeof(buf[0])-2-sizeof(CONFIG_FILE));
584 strcat(buf[0],CONFIG_FILE);
588 BIO_printf(bio_err,"Using configuration from %s\n",configfile);
589 if ((conf=CONF_load(NULL,configfile,&errorline)) == NULL)
592 BIO_printf(bio_err,"error loading the config file '%s'\n",
595 BIO_printf(bio_err,"error on line %ld of config file '%s'\n"
596 ,errorline,configfile);
600 /* Lets get the config section we are using */
603 section=CONF_get_string(conf,BASE_SECTION,ENV_DEFAULT_CA);
606 lookup_fail(BASE_SECTION,ENV_DEFAULT_CA);
613 p=CONF_get_string(conf,NULL,"oid_file");
620 oid_bio=BIO_new_file(p,"r");
624 BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
625 ERR_print_errors(bio_err);
631 OBJ_create_objects(oid_bio);
635 if (!add_oid_section(bio_err,conf))
637 ERR_print_errors(bio_err);
642 randfile = CONF_get_string(conf, BASE_SECTION, "RANDFILE");
643 if (randfile == NULL)
645 app_RAND_load_file(randfile, bio_err, 0);
647 in=BIO_new(BIO_s_file());
648 out=BIO_new(BIO_s_file());
649 Sout=BIO_new(BIO_s_file());
650 Cout=BIO_new(BIO_s_file());
651 if ((in == NULL) || (out == NULL) || (Sout == NULL) || (Cout == NULL))
653 ERR_print_errors(bio_err);
657 /*****************************************************************/
658 /* report status of cert with serial number given on command line */
661 if ((dbfile=CONF_get_string(conf,section,ENV_DATABASE)) == NULL)
663 lookup_fail(section,ENV_DATABASE);
666 if (BIO_read_filename(in,dbfile) <= 0)
669 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
672 db=TXT_DB_read(in,DB_NUMBER);
673 if (db == NULL) goto err;
675 if (!TXT_DB_create_index(db, DB_serial, NULL,
676 LHASH_HASH_FN(index_serial_hash),
677 LHASH_COMP_FN(index_serial_cmp)))
680 "error creating serial number index:(%ld,%ld,%ld)\n",
681 db->error,db->arg1,db->arg2);
685 if (get_certificate_status(ser_status,db) != 1)
686 BIO_printf(bio_err,"Error verifying serial %s!\n",
691 /*****************************************************************/
692 /* we definitely need a public key, so let's get it */
694 if ((keyfile == NULL) && ((keyfile=CONF_get_string(conf,
695 section,ENV_PRIVATE_KEY)) == NULL))
697 lookup_fail(section,ENV_PRIVATE_KEY);
700 if (!key && !app_passwd(bio_err, passargin, NULL, &key, NULL))
702 BIO_printf(bio_err,"Error getting password\n");
705 if (keyform == FORMAT_ENGINE)
709 BIO_printf(bio_err,"no engine specified\n");
712 pkey = ENGINE_load_private_key(e, keyfile, key);
714 else if (keyform == FORMAT_PEM)
716 if (BIO_read_filename(in,keyfile) <= 0)
719 BIO_printf(bio_err,"trying to load CA private key\n");
722 pkey=PEM_read_bio_PrivateKey(in,NULL,NULL,key);
726 BIO_printf(bio_err,"bad input format specified for key file\n");
729 if (key) memset(key,0,strlen(key));
732 BIO_printf(bio_err,"unable to load CA private key\n");
736 /*****************************************************************/
737 /* we need a certificate */
738 if ((certfile == NULL) && ((certfile=CONF_get_string(conf,
739 section,ENV_CERTIFICATE)) == NULL))
741 lookup_fail(section,ENV_CERTIFICATE);
744 if (BIO_read_filename(in,certfile) <= 0)
747 BIO_printf(bio_err,"trying to load CA certificate\n");
750 x509=PEM_read_bio_X509(in,NULL,NULL,NULL);
753 BIO_printf(bio_err,"unable to load CA certificate\n");
757 if (!X509_check_private_key(x509,pkey))
759 BIO_printf(bio_err,"CA certificate and CA private key do not match\n");
763 f=CONF_get_string(conf,BASE_SECTION,ENV_PRESERVE);
766 if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
768 f=CONF_get_string(conf,BASE_SECTION,ENV_MSIE_HACK);
771 if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
774 f=CONF_get_string(conf,section,ENV_NAMEOPT);
778 if (!set_name_ex(&nameopt, f))
780 BIO_printf(bio_err, "Invalid name options: \"%s\"\n", f);
788 f=CONF_get_string(conf,section,ENV_CERTOPT);
792 if (!set_cert_ex(&certopt, f))
794 BIO_printf(bio_err, "Invalid certificate options: \"%s\"\n", f);
802 f=CONF_get_string(conf,section,ENV_EXTCOPY);
806 if (!set_ext_copy(&ext_copy, f))
808 BIO_printf(bio_err, "Invalid extension copy option: \"%s\"\n", f);
815 /*****************************************************************/
816 /* lookup where to write new certificates */
817 if ((outdir == NULL) && (req))
821 if ((outdir=CONF_get_string(conf,section,ENV_NEW_CERTS_DIR))
824 BIO_printf(bio_err,"there needs to be defined a directory for new certificate to be placed in\n");
827 #ifndef OPENSSL_SYS_VMS
828 /* outdir is a directory spec, but access() for VMS demands a
829 filename. In any case, stat(), below, will catch the problem
830 if outdir is not a directory spec, and the fopen() or open()
831 will catch an error if there is no write access.
833 Presumably, this problem could also be solved by using the DEC
834 C routines to convert the directory syntax to Unixly, and give
835 that to access(). However, time's too short to do that just
838 if (access(outdir,R_OK|W_OK|X_OK) != 0)
840 BIO_printf(bio_err,"I am unable to access the %s directory\n",outdir);
845 if (stat(outdir,&sb) != 0)
847 BIO_printf(bio_err,"unable to stat(%s)\n",outdir);
852 if (!(sb.st_mode & S_IFDIR))
854 BIO_printf(bio_err,"%s need to be a directory\n",outdir);
862 /*****************************************************************/
863 /* we need to load the database file */
864 if ((dbfile=CONF_get_string(conf,section,ENV_DATABASE)) == NULL)
866 lookup_fail(section,ENV_DATABASE);
869 if (BIO_read_filename(in,dbfile) <= 0)
872 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
875 db=TXT_DB_read(in,DB_NUMBER);
876 if (db == NULL) goto err;
878 /* Lets check some fields */
879 for (i=0; i<sk_num(db->data); i++)
881 pp=(char **)sk_value(db->data,i);
882 if ((pp[DB_type][0] != DB_TYPE_REV) &&
883 (pp[DB_rev_date][0] != '\0'))
885 BIO_printf(bio_err,"entry %d: not revoked yet, but has a revocation date\n",i+1);
888 if ((pp[DB_type][0] == DB_TYPE_REV) &&
889 !make_revoked(NULL, pp[DB_rev_date]))
891 BIO_printf(bio_err," in entry %d\n", i+1);
894 if (!check_time_format(pp[DB_exp_date]))
896 BIO_printf(bio_err,"entry %d: invalid expiry date\n",i+1);
906 if ((j&1) || (j < 2))
908 BIO_printf(bio_err,"entry %d: bad serial number length (%d)\n",i+1,j);
913 if (!( ((*p >= '0') && (*p <= '9')) ||
914 ((*p >= 'A') && (*p <= 'F')) ||
915 ((*p >= 'a') && (*p <= 'f'))) )
917 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);
925 BIO_set_fp(out,stdout,BIO_NOCLOSE|BIO_FP_TEXT); /* cannot fail */
926 #ifdef OPENSSL_SYS_VMS
928 BIO *tmpbio = BIO_new(BIO_f_linebuffer());
929 out = BIO_push(tmpbio, out);
932 TXT_DB_write(out,db);
933 BIO_printf(bio_err,"%d entries loaded from the database\n",
935 BIO_printf(bio_err,"generating index\n");
938 if (!TXT_DB_create_index(db, DB_serial, NULL,
939 LHASH_HASH_FN(index_serial_hash),
940 LHASH_COMP_FN(index_serial_cmp)))
942 BIO_printf(bio_err,"error creating serial number index:(%ld,%ld,%ld)\n",db->error,db->arg1,db->arg2);
946 if (!TXT_DB_create_index(db, DB_name, index_name_qual,
947 LHASH_HASH_FN(index_name_hash),
948 LHASH_COMP_FN(index_name_cmp)))
950 BIO_printf(bio_err,"error creating name index:(%ld,%ld,%ld)\n",
951 db->error,db->arg1,db->arg2);
955 /*****************************************************************/
956 /* Update the db file for expired certificates */
960 BIO_printf(bio_err, "Updating %s ...\n",
966 BIO_printf(bio_err,"Malloc failure\n");
971 if (verbose) BIO_printf(bio_err,
972 "No entries found to mark expired\n");
976 out = BIO_new(BIO_s_file());
979 ERR_print_errors(bio_err);
983 #ifndef OPENSSL_SYS_VMS
984 j = BIO_snprintf(buf[0], sizeof buf[0], "%s.new", dbfile);
986 j = BIO_snprintf(buf[0], sizeof buf[0], "%s-new", dbfile);
988 if (j < 0 || j >= sizeof buf[0])
990 BIO_printf(bio_err, "file name too long\n");
993 if (BIO_write_filename(out,buf[0]) <= 0)
996 BIO_printf(bio_err,"unable to open '%s'\n",
1000 j=TXT_DB_write(out,db);
1001 if (j <= 0) goto err;
1005 #ifndef OPENSSL_SYS_VMS
1006 j = BIO_snprintf(buf[1], sizeof buf[1], "%s.old", dbfile);
1008 j = BIO_snprintf(buf[1], sizeof buf[1], "%s-old", dbfile);
1010 if (j < 0 || j >= sizeof buf[1])
1012 BIO_printf(bio_err, "file name too long\n");
1015 if (rename(dbfile,buf[1]) < 0)
1018 "unable to rename %s to %s\n",
1023 if (rename(buf[0],dbfile) < 0)
1026 "unable to rename %s to %s\n",
1029 rename(buf[1],dbfile);
1033 if (verbose) BIO_printf(bio_err,
1034 "Done. %d entries marked as expired\n",i);
1039 /*****************************************************************/
1040 /* Read extentions config file */
1043 if (!(extconf=CONF_load(NULL,extfile,&errorline)))
1046 BIO_printf(bio_err, "ERROR: loading the config file '%s'\n",
1049 BIO_printf(bio_err, "ERROR: on line %ld of config file '%s'\n",
1056 BIO_printf(bio_err, "Succesfully loaded extensions file %s\n", extfile);
1058 /* We can have sections in the ext file */
1059 if (!extensions && !(extensions = CONF_get_string(extconf, "default", "extensions")))
1060 extensions = "default";
1063 /*****************************************************************/
1066 if (outfile != NULL)
1068 if (BIO_write_filename(Sout,outfile) <= 0)
1076 BIO_set_fp(Sout,stdout,BIO_NOCLOSE|BIO_FP_TEXT);
1077 #ifdef OPENSSL_SYS_VMS
1079 BIO *tmpbio = BIO_new(BIO_f_linebuffer());
1080 Sout = BIO_push(tmpbio, Sout);
1088 if ((md == NULL) && ((md=CONF_get_string(conf,
1089 section,ENV_DEFAULT_MD)) == NULL))
1091 lookup_fail(section,ENV_DEFAULT_MD);
1094 if ((dgst=EVP_get_digestbyname(md)) == NULL)
1096 BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
1100 BIO_printf(bio_err,"message digest is %s\n",
1101 OBJ_nid2ln(dgst->type));
1102 if ((policy == NULL) && ((policy=CONF_get_string(conf,
1103 section,ENV_POLICY)) == NULL))
1105 lookup_fail(section,ENV_POLICY);
1109 BIO_printf(bio_err,"policy is %s\n",policy);
1111 if ((serialfile=CONF_get_string(conf,section,ENV_SERIAL))
1114 lookup_fail(section,ENV_SERIAL);
1120 /* no '-extfile' option, so we look for extensions
1121 * in the main configuration file */
1124 extensions=CONF_get_string(conf,section,
1131 /* Check syntax of file */
1133 X509V3_set_ctx_test(&ctx);
1134 X509V3_set_conf_lhash(&ctx, conf);
1135 if (!X509V3_EXT_add_conf(conf, &ctx, extensions,
1139 "Error Loading extension section %s\n",
1147 if (startdate == NULL)
1149 startdate=CONF_get_string(conf,section,
1150 ENV_DEFAULT_STARTDATE);
1151 if (startdate == NULL)
1154 if (startdate && !ASN1_UTCTIME_set_string(NULL,startdate))
1156 BIO_printf(bio_err,"start date is invalid, it should be YYMMDDHHMMSSZ\n");
1159 if (startdate == NULL) startdate="today";
1161 if (enddate == NULL)
1163 enddate=CONF_get_string(conf,section,
1164 ENV_DEFAULT_ENDDATE);
1165 if (enddate == NULL)
1168 if (enddate && !ASN1_UTCTIME_set_string(NULL,enddate))
1170 BIO_printf(bio_err,"end date is invalid, it should be YYMMDDHHMMSSZ\n");
1176 days=(int)CONF_get_number(conf,section,
1179 if (!enddate && (days == 0))
1181 BIO_printf(bio_err,"cannot lookup how many days to certify for\n");
1185 if ((serial=load_serial(serialfile)) == NULL)
1187 BIO_printf(bio_err,"error while loading serial number\n");
1192 if ((f=BN_bn2hex(serial)) == NULL) goto err;
1193 BIO_printf(bio_err,"next serial number is %s\n",f);
1197 if ((attribs=CONF_get_section(conf,policy)) == NULL)
1199 BIO_printf(bio_err,"unable to find 'section' for %s\n",policy);
1203 if ((cert_sk=sk_X509_new_null()) == NULL)
1205 BIO_printf(bio_err,"Memory allocation failure\n");
1208 if (spkac_file != NULL)
1211 j=certify_spkac(&x,spkac_file,pkey,x509,dgst,attribs,db,
1212 serial,subj,startdate,enddate, days,extensions,conf,
1213 verbose, certopt, nameopt, default_op, ext_copy);
1214 if (j < 0) goto err;
1218 BIO_printf(bio_err,"\n");
1219 if (!BN_add_word(serial,1)) goto err;
1220 if (!sk_X509_push(cert_sk,x))
1222 BIO_printf(bio_err,"Memory allocation failure\n");
1232 if (ss_cert_file != NULL)
1235 j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,attribs,
1236 db,serial,subj,startdate,enddate,days,batch,
1237 extensions,conf,verbose, certopt, nameopt,
1238 default_op, ext_copy);
1239 if (j < 0) goto err;
1243 BIO_printf(bio_err,"\n");
1244 if (!BN_add_word(serial,1)) goto err;
1245 if (!sk_X509_push(cert_sk,x))
1247 BIO_printf(bio_err,"Memory allocation failure\n");
1255 j=certify(&x,infile,pkey,x509,dgst,attribs,db,
1256 serial,subj,startdate,enddate,days,batch,
1257 extensions,conf,verbose, certopt, nameopt,
1258 default_op, ext_copy);
1259 if (j < 0) goto err;
1263 BIO_printf(bio_err,"\n");
1264 if (!BN_add_word(serial,1)) goto err;
1265 if (!sk_X509_push(cert_sk,x))
1267 BIO_printf(bio_err,"Memory allocation failure\n");
1272 for (i=0; i<argc; i++)
1275 j=certify(&x,argv[i],pkey,x509,dgst,attribs,db,
1276 serial,subj,startdate,enddate,days,batch,
1277 extensions,conf,verbose, certopt, nameopt,
1278 default_op, ext_copy);
1279 if (j < 0) goto err;
1283 BIO_printf(bio_err,"\n");
1284 if (!BN_add_word(serial,1)) goto err;
1285 if (!sk_X509_push(cert_sk,x))
1287 BIO_printf(bio_err,"Memory allocation failure\n");
1292 /* we have a stack of newly certified certificates
1293 * and a data base and serial number that need
1296 if (sk_X509_num(cert_sk) > 0)
1300 BIO_printf(bio_err,"\n%d out of %d certificate requests certified, commit? [y/n]",total_done,total);
1301 (void)BIO_flush(bio_err);
1303 fgets(buf[0],10,stdin);
1304 if ((buf[0][0] != 'y') && (buf[0][0] != 'Y'))
1306 BIO_printf(bio_err,"CERTIFICATION CANCELED\n");
1312 BIO_printf(bio_err,"Write out database with %d new entries\n",sk_X509_num(cert_sk));
1314 strncpy(buf[0],serialfile,BSIZE-4);
1316 #ifdef OPENSSL_SYS_VMS
1317 strcat(buf[0],"-new");
1319 strcat(buf[0],".new");
1322 if (!save_serial(buf[0],serial)) goto err;
1324 strncpy(buf[1],dbfile,BSIZE-4);
1326 #ifdef OPENSSL_SYS_VMS
1327 strcat(buf[1],"-new");
1329 strcat(buf[1],".new");
1332 if (BIO_write_filename(out,buf[1]) <= 0)
1335 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
1338 l=TXT_DB_write(out,db);
1339 if (l <= 0) goto err;
1343 BIO_printf(bio_err,"writing new certificates\n");
1344 for (i=0; i<sk_X509_num(cert_sk); i++)
1349 x=sk_X509_value(cert_sk,i);
1351 j=x->cert_info->serialNumber->length;
1352 p=(char *)x->cert_info->serialNumber->data;
1354 strncpy(buf[2],outdir,BSIZE-(j*2)-6);
1356 #ifndef OPENSSL_SYS_VMS
1360 n=(unsigned char *)&(buf[2][strlen(buf[2])]);
1365 sprintf((char *)n,"%02X",(unsigned char)*(p++));
1374 *(n++)='.'; *(n++)='p'; *(n++)='e'; *(n++)='m';
1377 BIO_printf(bio_err,"writing %s\n",buf[2]);
1379 if (BIO_write_filename(Cout,buf[2]) <= 0)
1384 write_new_certificate(Cout,x, 0, notext);
1385 write_new_certificate(Sout,x, output_der, notext);
1388 if (sk_X509_num(cert_sk))
1390 /* Rename the database and the serial file */
1391 strncpy(buf[2],serialfile,BSIZE-4);
1393 #ifdef OPENSSL_SYS_VMS
1394 strcat(buf[2],"-old");
1396 strcat(buf[2],".old");
1403 if (rename(serialfile,buf[2]) < 0)
1405 BIO_printf(bio_err,"unable to rename %s to %s\n",
1410 if (rename(buf[0],serialfile) < 0)
1412 BIO_printf(bio_err,"unable to rename %s to %s\n",
1415 rename(buf[2],serialfile);
1419 strncpy(buf[2],dbfile,BSIZE-4);
1421 #ifdef OPENSSL_SYS_VMS
1422 strcat(buf[2],"-old");
1424 strcat(buf[2],".old");
1427 if (rename(dbfile,buf[2]) < 0)
1429 BIO_printf(bio_err,"unable to rename %s to %s\n",
1434 if (rename(buf[1],dbfile) < 0)
1436 BIO_printf(bio_err,"unable to rename %s to %s\n",
1439 rename(buf[2],dbfile);
1442 BIO_printf(bio_err,"Data Base Updated\n");
1446 /*****************************************************************/
1452 crl_ext=CONF_get_string(conf,section,ENV_CRLEXT);
1458 /* Check syntax of file */
1460 X509V3_set_ctx_test(&ctx);
1461 X509V3_set_conf_lhash(&ctx, conf);
1462 if (!X509V3_EXT_add_conf(conf, &ctx, crl_ext, NULL))
1465 "Error Loading CRL extension section %s\n",
1472 if (!crldays && !crlhours)
1474 crldays=CONF_get_number(conf,section,
1475 ENV_DEFAULT_CRL_DAYS);
1476 crlhours=CONF_get_number(conf,section,
1477 ENV_DEFAULT_CRL_HOURS);
1479 if ((crldays == 0) && (crlhours == 0))
1481 BIO_printf(bio_err,"cannot lookup how long until the next CRL is issuer\n");
1485 if (verbose) BIO_printf(bio_err,"making CRL\n");
1486 if ((crl=X509_CRL_new()) == NULL) goto err;
1488 X509_NAME_free(ci->issuer);
1489 ci->issuer=X509_NAME_dup(x509->cert_info->subject);
1490 if (ci->issuer == NULL) goto err;
1492 X509_gmtime_adj(ci->lastUpdate,0);
1493 if (ci->nextUpdate == NULL)
1494 ci->nextUpdate=ASN1_UTCTIME_new();
1495 X509_gmtime_adj(ci->nextUpdate,(crldays*24+crlhours)*60*60);
1497 for (i=0; i<sk_num(db->data); i++)
1499 pp=(char **)sk_value(db->data,i);
1500 if (pp[DB_type][0] == DB_TYPE_REV)
1502 if ((r=X509_REVOKED_new()) == NULL) goto err;
1503 j = make_revoked(r, pp[DB_rev_date]);
1505 if (j == 2) crl_v2 = 1;
1506 if (!BN_hex2bn(&serial, pp[DB_serial]))
1508 r->serialNumber = BN_to_ASN1_INTEGER(serial, r->serialNumber);
1511 if (!r->serialNumber)
1513 X509_CRL_add0_revoked(crl,r);
1516 /* sort the data so it will be written in serial
1518 sk_X509_REVOKED_sort(ci->revoked);
1519 for (i=0; i<sk_X509_REVOKED_num(ci->revoked); i++)
1521 r=sk_X509_REVOKED_value(ci->revoked,i);
1525 /* we now have a CRL */
1526 if (verbose) BIO_printf(bio_err,"signing CRL\n");
1529 if ((dgst=EVP_get_digestbyname(md)) == NULL)
1531 BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
1537 #ifndef OPENSSL_NO_DSA
1538 if (pkey->type == EVP_PKEY_DSA)
1545 /* Add any extensions asked for */
1550 if (ci->version == NULL)
1551 if ((ci->version=ASN1_INTEGER_new()) == NULL) goto err;
1552 X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0);
1553 X509V3_set_conf_lhash(&crlctx, conf);
1555 if (!X509V3_EXT_CRL_add_conf(conf, &crlctx,
1556 crl_ext, crl)) goto err;
1558 if (crl_ext || crl_v2)
1560 if (ci->version == NULL)
1561 if ((ci->version=ASN1_INTEGER_new()) == NULL) goto err;
1562 ASN1_INTEGER_set(ci->version,1); /* version 2 CRL */
1565 if (!X509_CRL_sign(crl,pkey,dgst)) goto err;
1567 PEM_write_bio_X509_CRL(Sout,crl);
1569 /*****************************************************************/
1574 BIO_printf(bio_err,"no input files\n");
1580 if (BIO_read_filename(in,infile) <= 0)
1583 BIO_printf(bio_err,"error trying to load '%s' certificate\n",infile);
1586 revcert=PEM_read_bio_X509(in,NULL,NULL,NULL);
1587 if (revcert == NULL)
1589 BIO_printf(bio_err,"unable to load '%s' certificate\n",infile);
1592 j=do_revoke(revcert,db, rev_type, rev_arg);
1593 if (j <= 0) goto err;
1596 strncpy(buf[0],dbfile,BSIZE-4);
1597 #ifndef OPENSSL_SYS_VMS
1598 strcat(buf[0],".new");
1600 strcat(buf[0],"-new");
1602 if (BIO_write_filename(out,buf[0]) <= 0)
1605 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
1608 j=TXT_DB_write(out,db);
1609 if (j <= 0) goto err;
1610 strncpy(buf[1],dbfile,BSIZE-4);
1611 #ifndef OPENSSL_SYS_VMS
1612 strcat(buf[1],".old");
1614 strcat(buf[1],"-old");
1616 if (rename(dbfile,buf[1]) < 0)
1618 BIO_printf(bio_err,"unable to rename %s to %s\n", dbfile, buf[1]);
1622 if (rename(buf[0],dbfile) < 0)
1624 BIO_printf(bio_err,"unable to rename %s to %s\n", buf[0],dbfile);
1626 rename(buf[1],dbfile);
1629 BIO_printf(bio_err,"Data Base Updated\n");
1632 /*****************************************************************/
1640 sk_X509_pop_free(cert_sk,X509_free);
1642 if (ret) ERR_print_errors(bio_err);
1643 app_RAND_write_file(randfile, bio_err);
1646 EVP_PKEY_free(pkey);
1654 static void lookup_fail(char *name, char *tag)
1656 BIO_printf(bio_err,"variable lookup failed for %s::%s\n",name,tag);
1659 static unsigned long index_serial_hash(const char **a)
1664 while (*n == '0') n++;
1665 return(lh_strhash(n));
1668 static int index_serial_cmp(const char **a, const char **b)
1672 for (aa=a[DB_serial]; *aa == '0'; aa++);
1673 for (bb=b[DB_serial]; *bb == '0'; bb++);
1674 return(strcmp(aa,bb));
1677 static unsigned long index_name_hash(const char **a)
1678 { return(lh_strhash(a[DB_name])); }
1680 static int index_name_qual(char **a)
1681 { return(a[0][0] == 'V'); }
1683 static int index_name_cmp(const char **a, const char **b)
1684 { return(strcmp(a[DB_name],
1687 static BIGNUM *load_serial(char *serialfile)
1691 MS_STATIC char buf[1024];
1692 ASN1_INTEGER *ai=NULL;
1694 if ((in=BIO_new(BIO_s_file())) == NULL)
1696 ERR_print_errors(bio_err);
1700 if (BIO_read_filename(in,serialfile) <= 0)
1705 ai=ASN1_INTEGER_new();
1706 if (ai == NULL) goto err;
1707 if (!a2i_ASN1_INTEGER(in,ai,buf,1024))
1709 BIO_printf(bio_err,"unable to load number from %s\n",
1713 ret=ASN1_INTEGER_to_BN(ai,NULL);
1716 BIO_printf(bio_err,"error converting number from bin to BIGNUM");
1720 if (in != NULL) BIO_free(in);
1721 if (ai != NULL) ASN1_INTEGER_free(ai);
1725 static int save_serial(char *serialfile, BIGNUM *serial)
1729 ASN1_INTEGER *ai=NULL;
1731 out=BIO_new(BIO_s_file());
1734 ERR_print_errors(bio_err);
1737 if (BIO_write_filename(out,serialfile) <= 0)
1743 if ((ai=BN_to_ASN1_INTEGER(serial,NULL)) == NULL)
1745 BIO_printf(bio_err,"error converting serial to ASN.1 format\n");
1748 i2a_ASN1_INTEGER(out,ai);
1752 if (out != NULL) BIO_free_all(out);
1753 if (ai != NULL) ASN1_INTEGER_free(ai);
1757 static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1758 const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
1759 BIGNUM *serial, char *subj, char *startdate, char *enddate, int days,
1760 int batch, char *ext_sect, LHASH *lconf, int verbose,
1761 unsigned long certopt, unsigned long nameopt, int default_op,
1766 EVP_PKEY *pktmp=NULL;
1769 in=BIO_new(BIO_s_file());
1771 if (BIO_read_filename(in,infile) <= 0)
1776 if ((req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL)) == NULL)
1778 BIO_printf(bio_err,"Error reading certificate request in %s\n",
1783 X509_REQ_print(bio_err,req);
1785 BIO_printf(bio_err,"Check that the request matches the signature\n");
1787 if ((pktmp=X509_REQ_get_pubkey(req)) == NULL)
1789 BIO_printf(bio_err,"error unpacking public key\n");
1792 i=X509_REQ_verify(req,pktmp);
1793 EVP_PKEY_free(pktmp);
1797 BIO_printf(bio_err,"Signature verification problems....\n");
1803 BIO_printf(bio_err,"Signature did not match the certificate request\n");
1807 BIO_printf(bio_err,"Signature ok\n");
1809 ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,startdate, enddate,
1810 days,batch,verbose,req,ext_sect,lconf,
1811 certopt, nameopt, default_op, ext_copy);
1814 if (req != NULL) X509_REQ_free(req);
1815 if (in != NULL) BIO_free(in);
1819 static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1820 const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
1821 BIGNUM *serial, char *subj, char *startdate, char *enddate, int days,
1822 int batch, char *ext_sect, LHASH *lconf, int verbose,
1823 unsigned long certopt, unsigned long nameopt, int default_op,
1827 X509_REQ *rreq=NULL;
1829 EVP_PKEY *pktmp=NULL;
1832 in=BIO_new(BIO_s_file());
1834 if (BIO_read_filename(in,infile) <= 0)
1839 if ((req=PEM_read_bio_X509(in,NULL,NULL,NULL)) == NULL)
1841 BIO_printf(bio_err,"Error reading self signed certificate in %s\n",infile);
1845 X509_print(bio_err,req);
1847 BIO_printf(bio_err,"Check that the request matches the signature\n");
1849 if ((pktmp=X509_get_pubkey(req)) == NULL)
1851 BIO_printf(bio_err,"error unpacking public key\n");
1854 i=X509_verify(req,pktmp);
1855 EVP_PKEY_free(pktmp);
1859 BIO_printf(bio_err,"Signature verification problems....\n");
1865 BIO_printf(bio_err,"Signature did not match the certificate\n");
1869 BIO_printf(bio_err,"Signature ok\n");
1871 if ((rreq=X509_to_X509_REQ(req,NULL,EVP_md5())) == NULL)
1874 ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,startdate,enddate,days,
1875 batch,verbose,rreq,ext_sect,lconf, certopt, nameopt, default_op,
1879 if (rreq != NULL) X509_REQ_free(rreq);
1880 if (req != NULL) X509_free(req);
1881 if (in != NULL) BIO_free(in);
1885 static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
1886 STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial, char *subj,
1887 char *startdate, char *enddate, int days, int batch, int verbose,
1888 X509_REQ *req, char *ext_sect, LHASH *lconf,
1889 unsigned long certopt, unsigned long nameopt, int default_op,
1892 X509_NAME *name=NULL,*CAname=NULL,*subject=NULL;
1893 ASN1_UTCTIME *tm,*tmptm;
1894 ASN1_STRING *str,*str2;
1898 X509_NAME_ENTRY *ne;
1899 X509_NAME_ENTRY *tne,*push;
1901 int ok= -1,i,j,last,nid;
1904 char *row[DB_NUMBER],**rrow,**irow=NULL;
1907 tmptm=ASN1_UTCTIME_new();
1910 BIO_printf(bio_err,"malloc error\n");
1914 for (i=0; i<DB_NUMBER; i++)
1919 X509_NAME *n = do_subject(subj);
1923 ERR_print_errors(bio_err);
1926 X509_REQ_set_subject_name(req,n);
1927 req->req_info->enc.modified = 1;
1932 BIO_printf(bio_err,"The Subject's Distinguished Name is as follows\n");
1933 name=X509_REQ_get_subject_name(req);
1934 for (i=0; i<X509_NAME_entry_count(name); i++)
1936 ne= X509_NAME_get_entry(name,i);
1937 str=X509_NAME_ENTRY_get_data(ne);
1938 obj=X509_NAME_ENTRY_get_object(ne);
1942 /* assume all type should be strings */
1943 nid=OBJ_obj2nid(ne->object);
1945 if (str->type == V_ASN1_UNIVERSALSTRING)
1946 ASN1_UNIVERSALSTRING_to_string(str);
1948 if ((str->type == V_ASN1_IA5STRING) &&
1949 (nid != NID_pkcs9_emailAddress))
1950 str->type=V_ASN1_T61STRING;
1952 if ((nid == NID_pkcs9_emailAddress) &&
1953 (str->type == V_ASN1_PRINTABLESTRING))
1954 str->type=V_ASN1_IA5STRING;
1957 /* check some things */
1958 if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) &&
1959 (str->type != V_ASN1_IA5STRING))
1961 BIO_printf(bio_err,"\nemailAddress type needs to be of type IA5STRING\n");
1964 j=ASN1_PRINTABLE_type(str->data,str->length);
1965 if ( ((j == V_ASN1_T61STRING) &&
1966 (str->type != V_ASN1_T61STRING)) ||
1967 ((j == V_ASN1_IA5STRING) &&
1968 (str->type == V_ASN1_PRINTABLESTRING)))
1970 BIO_printf(bio_err,"\nThe string contains characters that are illegal for the ASN.1 type\n");
1975 old_entry_print(bio_err, obj, str);
1978 /* Ok, now we check the 'policy' stuff. */
1979 if ((subject=X509_NAME_new()) == NULL)
1981 BIO_printf(bio_err,"Memory allocation failure\n");
1985 /* take a copy of the issuer name before we mess with it. */
1986 CAname=X509_NAME_dup(x509->cert_info->subject);
1987 if (CAname == NULL) goto err;
1990 for (i=0; i<sk_CONF_VALUE_num(policy); i++)
1992 cv=sk_CONF_VALUE_value(policy,i); /* get the object id */
1993 if ((j=OBJ_txt2nid(cv->name)) == NID_undef)
1995 BIO_printf(bio_err,"%s:unknown object type in 'policy' configuration\n",cv->name);
2003 /* lookup the object in the supplied name list */
2004 j=X509_NAME_get_index_by_OBJ(name,obj,last);
2007 if (last != -1) break;
2012 tne=X509_NAME_get_entry(name,j);
2016 /* depending on the 'policy', decide what to do. */
2018 if (strcmp(cv->value,"optional") == 0)
2023 else if (strcmp(cv->value,"supplied") == 0)
2027 BIO_printf(bio_err,"The %s field needed to be supplied and was missing\n",cv->name);
2033 else if (strcmp(cv->value,"match") == 0)
2039 BIO_printf(bio_err,"The mandatory %s field was missing\n",cv->name);
2046 j=X509_NAME_get_index_by_OBJ(CAname,obj,last2);
2047 if ((j < 0) && (last2 == -1))
2049 BIO_printf(bio_err,"The %s field does not exist in the CA certificate,\nthe 'policy' is misconfigured\n",cv->name);
2054 push=X509_NAME_get_entry(CAname,j);
2055 str=X509_NAME_ENTRY_get_data(tne);
2056 str2=X509_NAME_ENTRY_get_data(push);
2058 if (ASN1_STRING_cmp(str,str2) != 0)
2063 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));
2069 BIO_printf(bio_err,"%s:invalid type in 'policy' configuration\n",cv->value);
2075 if (!X509_NAME_add_entry(subject,push, -1, 0))
2078 X509_NAME_ENTRY_free(push);
2079 BIO_printf(bio_err,"Memory allocation failure\n");
2089 X509_NAME_free(subject);
2090 subject=X509_NAME_dup(X509_REQ_get_subject_name(req));
2091 if (subject == NULL) goto err;
2095 BIO_printf(bio_err,"The subject name appears to be ok, checking data base for clashes\n");
2097 row[DB_name]=X509_NAME_oneline(subject,NULL,0);
2098 row[DB_serial]=BN_bn2hex(serial);
2099 if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
2101 BIO_printf(bio_err,"Memory allocation failure\n");
2105 rrow=TXT_DB_get_by_index(db,DB_name,row);
2108 BIO_printf(bio_err,"ERROR:There is already a certificate for %s\n",
2113 rrow=TXT_DB_get_by_index(db,DB_serial,row);
2116 BIO_printf(bio_err,"ERROR:Serial number %s has already been issued,\n",
2118 BIO_printf(bio_err," check the database/serial_file for corruption\n");
2125 "The matching entry has the following details\n");
2126 if (rrow[DB_type][0] == 'E')
2128 else if (rrow[DB_type][0] == 'R')
2130 else if (rrow[DB_type][0] == 'V')
2133 p="\ninvalid type, Data base error\n";
2134 BIO_printf(bio_err,"Type :%s\n",p);;
2135 if (rrow[DB_type][0] == 'R')
2137 p=rrow[DB_exp_date]; if (p == NULL) p="undef";
2138 BIO_printf(bio_err,"Was revoked on:%s\n",p);
2140 p=rrow[DB_exp_date]; if (p == NULL) p="undef";
2141 BIO_printf(bio_err,"Expires on :%s\n",p);
2142 p=rrow[DB_serial]; if (p == NULL) p="undef";
2143 BIO_printf(bio_err,"Serial Number :%s\n",p);
2144 p=rrow[DB_file]; if (p == NULL) p="undef";
2145 BIO_printf(bio_err,"File name :%s\n",p);
2146 p=rrow[DB_name]; if (p == NULL) p="undef";
2147 BIO_printf(bio_err,"Subject Name :%s\n",p);
2148 ok= -1; /* This is now a 'bad' error. */
2152 /* We are now totally happy, lets make and sign the certificate */
2154 BIO_printf(bio_err,"Everything appears to be ok, creating and signing the certificate\n");
2156 if ((ret=X509_new()) == NULL) goto err;
2160 /* Make it an X509 v3 certificate. */
2161 if (!X509_set_version(x509,2)) goto err;
2164 if (BN_to_ASN1_INTEGER(serial,ci->serialNumber) == NULL)
2166 if (!X509_set_issuer_name(ret,X509_get_subject_name(x509)))
2169 if (strcmp(startdate,"today") == 0)
2170 X509_gmtime_adj(X509_get_notBefore(ret),0);
2171 else ASN1_UTCTIME_set_string(X509_get_notBefore(ret),startdate);
2173 if (enddate == NULL)
2174 X509_gmtime_adj(X509_get_notAfter(ret),(long)60*60*24*days);
2175 else ASN1_UTCTIME_set_string(X509_get_notAfter(ret),enddate);
2177 if (!X509_set_subject_name(ret,subject)) goto err;
2179 pktmp=X509_REQ_get_pubkey(req);
2180 i = X509_set_pubkey(ret,pktmp);
2181 EVP_PKEY_free(pktmp);
2184 /* Lets add the extensions, if there are any */
2188 if (ci->version == NULL)
2189 if ((ci->version=ASN1_INTEGER_new()) == NULL)
2191 ASN1_INTEGER_set(ci->version,2); /* version 3 certificate */
2193 /* Free the current entries if any, there should not
2194 * be any I believe */
2195 if (ci->extensions != NULL)
2196 sk_X509_EXTENSION_pop_free(ci->extensions,
2197 X509_EXTENSION_free);
2199 ci->extensions = NULL;
2201 /* Initialize the context structure */
2202 X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0);
2207 BIO_printf(bio_err, "Extra configuration file found\n");
2209 /* Use the extconf configuration db LHASH */
2210 X509V3_set_conf_lhash(&ctx, extconf);
2212 /* Test the structure (needed?) */
2213 /* X509V3_set_ctx_test(&ctx); */
2215 /* Adds exts contained in the configuration file */
2216 if (!X509V3_EXT_add_conf(extconf, &ctx, ext_sect,ret))
2219 "ERROR: adding extensions in section %s\n",
2221 ERR_print_errors(bio_err);
2225 BIO_printf(bio_err, "Successfully added extensions from file.\n");
2229 /* We found extensions to be set from config file */
2230 X509V3_set_conf_lhash(&ctx, lconf);
2232 if(!X509V3_EXT_add_conf(lconf, &ctx, ext_sect, ret))
2234 BIO_printf(bio_err, "ERROR: adding extensions in section %s\n", ext_sect);
2235 ERR_print_errors(bio_err);
2240 BIO_printf(bio_err, "Successfully added extensions from config\n");
2244 /* Copy extensions from request (if any) */
2246 if (!copy_extensions(ret, req, ext_copy))
2248 BIO_printf(bio_err, "ERROR: adding extensions from request\n");
2249 ERR_print_errors(bio_err);
2256 BIO_printf(bio_err, "Certificate Details:\n");
2257 /* Never print signature details because signature not present */
2258 certopt |= X509_FLAG_NO_SIGDUMP | X509_FLAG_NO_SIGNAME;
2259 X509_print_ex(bio_err, ret, nameopt, certopt);
2262 BIO_printf(bio_err,"Certificate is to be certified until ");
2263 ASN1_UTCTIME_print(bio_err,X509_get_notAfter(ret));
2264 if (days) BIO_printf(bio_err," (%d days)",days);
2265 BIO_printf(bio_err, "\n");
2270 BIO_printf(bio_err,"Sign the certificate? [y/n]:");
2271 (void)BIO_flush(bio_err);
2273 fgets(buf,sizeof(buf)-1,stdin);
2274 if (!((buf[0] == 'y') || (buf[0] == 'Y')))
2276 BIO_printf(bio_err,"CERTIFICATE WILL NOT BE CERTIFIED\n");
2283 #ifndef OPENSSL_NO_DSA
2284 if (pkey->type == EVP_PKEY_DSA) dgst=EVP_dss1();
2285 pktmp=X509_get_pubkey(ret);
2286 if (EVP_PKEY_missing_parameters(pktmp) &&
2287 !EVP_PKEY_missing_parameters(pkey))
2288 EVP_PKEY_copy_parameters(pktmp,pkey);
2289 EVP_PKEY_free(pktmp);
2292 if (!X509_sign(ret,pkey,dgst))
2295 /* We now just add it to the database */
2296 row[DB_type]=(char *)OPENSSL_malloc(2);
2298 tm=X509_get_notAfter(ret);
2299 row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
2300 memcpy(row[DB_exp_date],tm->data,tm->length);
2301 row[DB_exp_date][tm->length]='\0';
2303 row[DB_rev_date]=NULL;
2305 /* row[DB_serial] done already */
2306 row[DB_file]=(char *)OPENSSL_malloc(8);
2307 /* row[DB_name] done already */
2309 if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2310 (row[DB_file] == NULL))
2312 BIO_printf(bio_err,"Memory allocation failure\n");
2315 strcpy(row[DB_file],"unknown");
2316 row[DB_type][0]='V';
2317 row[DB_type][1]='\0';
2319 if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
2321 BIO_printf(bio_err,"Memory allocation failure\n");
2325 for (i=0; i<DB_NUMBER; i++)
2330 irow[DB_NUMBER]=NULL;
2332 if (!TXT_DB_insert(db,irow))
2334 BIO_printf(bio_err,"failed to update database\n");
2335 BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
2340 for (i=0; i<DB_NUMBER; i++)
2341 if (row[i] != NULL) OPENSSL_free(row[i]);
2344 X509_NAME_free(CAname);
2345 if (subject != NULL)
2346 X509_NAME_free(subject);
2348 ASN1_UTCTIME_free(tmptm);
2351 if (ret != NULL) X509_free(ret);
2359 static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext)
2364 (void)i2d_X509_bio(bp,x);
2368 /* ??? Not needed since X509_print prints all this stuff anyway */
2369 f=X509_NAME_oneline(X509_get_issuer_name(x),buf,256);
2370 BIO_printf(bp,"issuer :%s\n",f);
2372 f=X509_NAME_oneline(X509_get_subject_name(x),buf,256);
2373 BIO_printf(bp,"subject:%s\n",f);
2375 BIO_puts(bp,"serial :");
2376 i2a_ASN1_INTEGER(bp,x->cert_info->serialNumber);
2377 BIO_puts(bp,"\n\n");
2379 if (!notext)X509_print(bp,x);
2380 PEM_write_bio_X509(bp,x);
2383 static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
2384 const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
2385 BIGNUM *serial, char *subj, char *startdate, char *enddate, int days,
2386 char *ext_sect, LHASH *lconf, int verbose, unsigned long certopt,
2387 unsigned long nameopt, int default_op, int ext_copy)
2389 STACK_OF(CONF_VALUE) *sk=NULL;
2392 CONF_VALUE *cv=NULL;
2393 NETSCAPE_SPKI *spki = NULL;
2396 EVP_PKEY *pktmp=NULL;
2398 X509_NAME_ENTRY *ne=NULL;
2404 * Load input file into a hash table. (This is just an easy
2405 * way to read and parse the file, then put it into a convenient
2408 parms=CONF_load(NULL,infile,&errline);
2411 BIO_printf(bio_err,"error on line %ld of %s\n",errline,infile);
2412 ERR_print_errors(bio_err);
2416 sk=CONF_get_section(parms, "default");
2417 if (sk_CONF_VALUE_num(sk) == 0)
2419 BIO_printf(bio_err, "no name/value pairs found in %s\n", infile);
2425 * Now create a dummy X509 request structure. We don't actually
2426 * have an X509 request, but we have many of the components
2427 * (a public key, various DN components). The idea is that we
2428 * put these components into the right X509 request structure
2429 * and we can use the same code as if you had a real X509 request.
2434 ERR_print_errors(bio_err);
2439 * Build up the subject name set.
2446 if (sk_CONF_VALUE_num(sk) <= i) break;
2448 cv=sk_CONF_VALUE_value(sk,i);
2450 /* Skip past any leading X. X: X, etc to allow for
2451 * multiple instances
2453 for (buf = cv->name; *buf ; buf++)
2454 if ((*buf == ':') || (*buf == ',') || (*buf == '.'))
2457 if (*buf) type = buf;
2462 if ((nid=OBJ_txt2nid(type)) == NID_undef)
2464 if (strcmp(type, "SPKAC") == 0)
2466 spki = NETSCAPE_SPKI_b64_decode(cv->value, -1);
2469 BIO_printf(bio_err,"unable to load Netscape SPKAC structure\n");
2470 ERR_print_errors(bio_err);
2477 j=ASN1_PRINTABLE_type((unsigned char *)buf,-1);
2478 if (fix_data(nid, &j) == 0)
2481 "invalid characters in string %s\n",buf);
2485 if ((ne=X509_NAME_ENTRY_create_by_NID(&ne,nid,j,
2486 (unsigned char *)buf,
2487 strlen(buf))) == NULL)
2490 if (!X509_NAME_add_entry(n,ne,-1, 0)) goto err;
2494 BIO_printf(bio_err,"Netscape SPKAC structure not found in %s\n",
2500 * Now extract the key from the SPKI structure.
2503 BIO_printf(bio_err,"Check that the SPKAC request matches the signature\n");
2505 if ((pktmp=NETSCAPE_SPKI_get_pubkey(spki)) == NULL)
2507 BIO_printf(bio_err,"error unpacking SPKAC public key\n");
2511 j = NETSCAPE_SPKI_verify(spki, pktmp);
2514 BIO_printf(bio_err,"signature verification failed on SPKAC public key\n");
2517 BIO_printf(bio_err,"Signature ok\n");
2519 X509_REQ_set_pubkey(req,pktmp);
2520 EVP_PKEY_free(pktmp);
2521 ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,startdate,enddate,
2522 days,1,verbose,req,ext_sect,lconf, certopt, nameopt, default_op,
2525 if (req != NULL) X509_REQ_free(req);
2526 if (parms != NULL) CONF_free(parms);
2527 if (spki != NULL) NETSCAPE_SPKI_free(spki);
2528 if (ne != NULL) X509_NAME_ENTRY_free(ne);
2533 static int fix_data(int nid, int *type)
2535 if (nid == NID_pkcs9_emailAddress)
2536 *type=V_ASN1_IA5STRING;
2537 if ((nid == NID_commonName) && (*type == V_ASN1_IA5STRING))
2538 *type=V_ASN1_T61STRING;
2539 if ((nid == NID_pkcs9_challengePassword) && (*type == V_ASN1_IA5STRING))
2540 *type=V_ASN1_T61STRING;
2541 if ((nid == NID_pkcs9_unstructuredName) && (*type == V_ASN1_T61STRING))
2543 if (nid == NID_pkcs9_unstructuredName)
2544 *type=V_ASN1_IA5STRING;
2548 static int check_time_format(char *str)
2552 tm.data=(unsigned char *)str;
2553 tm.length=strlen(str);
2554 tm.type=V_ASN1_UTCTIME;
2555 return(ASN1_UTCTIME_check(&tm));
2558 static int do_revoke(X509 *x509, TXT_DB *db, int type, char *value)
2560 ASN1_UTCTIME *tm=NULL;
2561 char *row[DB_NUMBER],**rrow,**irow;
2562 char *rev_str = NULL;
2566 for (i=0; i<DB_NUMBER; i++)
2568 row[DB_name]=X509_NAME_oneline(X509_get_subject_name(x509),NULL,0);
2569 bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509),NULL);
2570 row[DB_serial]=BN_bn2hex(bn);
2572 if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
2574 BIO_printf(bio_err,"Memory allocation failure\n");
2577 /* We have to lookup by serial number because name lookup
2578 * skips revoked certs
2580 rrow=TXT_DB_get_by_index(db,DB_serial,row);
2583 BIO_printf(bio_err,"Adding Entry to DB for %s\n", row[DB_name]);
2585 /* We now just add it to the database */
2586 row[DB_type]=(char *)OPENSSL_malloc(2);
2588 tm=X509_get_notAfter(x509);
2589 row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
2590 memcpy(row[DB_exp_date],tm->data,tm->length);
2591 row[DB_exp_date][tm->length]='\0';
2593 row[DB_rev_date]=NULL;
2595 /* row[DB_serial] done already */
2596 row[DB_file]=(char *)OPENSSL_malloc(8);
2598 /* row[DB_name] done already */
2600 if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2601 (row[DB_file] == NULL))
2603 BIO_printf(bio_err,"Memory allocation failure\n");
2606 strcpy(row[DB_file],"unknown");
2607 row[DB_type][0]='V';
2608 row[DB_type][1]='\0';
2610 if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
2612 BIO_printf(bio_err,"Memory allocation failure\n");
2616 for (i=0; i<DB_NUMBER; i++)
2621 irow[DB_NUMBER]=NULL;
2623 if (!TXT_DB_insert(db,irow))
2625 BIO_printf(bio_err,"failed to update database\n");
2626 BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
2630 /* Revoke Certificate */
2631 ok = do_revoke(x509,db, type, value);
2636 else if (index_name_cmp((const char **)row,(const char **)rrow))
2638 BIO_printf(bio_err,"ERROR:name does not match %s\n",
2642 else if (rrow[DB_type][0]=='R')
2644 BIO_printf(bio_err,"ERROR:Already revoked, serial number %s\n",
2650 BIO_printf(bio_err,"Revoking Certificate %s.\n", rrow[DB_serial]);
2651 rev_str = make_revocation_str(type, value);
2654 BIO_printf(bio_err, "Error in revocation arguments\n");
2657 rrow[DB_type][0]='R';
2658 rrow[DB_type][1]='\0';
2659 rrow[DB_rev_date] = rev_str;
2663 for (i=0; i<DB_NUMBER; i++)
2666 OPENSSL_free(row[i]);
2671 static int get_certificate_status(const char *serial, TXT_DB *db)
2673 char *row[DB_NUMBER],**rrow;
2676 /* Free Resources */
2677 for (i=0; i<DB_NUMBER; i++)
2680 /* Malloc needed char spaces */
2681 row[DB_serial] = OPENSSL_malloc(strlen(serial) + 2);
2682 if (row[DB_serial] == NULL)
2684 BIO_printf(bio_err,"Malloc failure\n");
2688 if (strlen(serial) % 2)
2690 /* Set the first char to 0 */;
2691 row[DB_serial][0]='0';
2693 /* Copy String from serial to row[DB_serial] */
2694 memcpy(row[DB_serial]+1, serial, strlen(serial));
2695 row[DB_serial][strlen(serial)+1]='\0';
2699 /* Copy String from serial to row[DB_serial] */
2700 memcpy(row[DB_serial], serial, strlen(serial));
2701 row[DB_serial][strlen(serial)]='\0';
2704 /* Make it Upper Case */
2705 for (i=0; row[DB_serial][i] != '\0'; i++)
2706 row[DB_serial][i] = toupper(row[DB_serial][i]);
2711 /* Search for the certificate */
2712 rrow=TXT_DB_get_by_index(db,DB_serial,row);
2715 BIO_printf(bio_err,"Serial %s not present in db.\n",
2720 else if (rrow[DB_type][0]=='V')
2722 BIO_printf(bio_err,"%s=Valid (%c)\n",
2723 row[DB_serial], rrow[DB_type][0]);
2726 else if (rrow[DB_type][0]=='R')
2728 BIO_printf(bio_err,"%s=Revoked (%c)\n",
2729 row[DB_serial], rrow[DB_type][0]);
2732 else if (rrow[DB_type][0]=='E')
2734 BIO_printf(bio_err,"%s=Expired (%c)\n",
2735 row[DB_serial], rrow[DB_type][0]);
2738 else if (rrow[DB_type][0]=='S')
2740 BIO_printf(bio_err,"%s=Suspended (%c)\n",
2741 row[DB_serial], rrow[DB_type][0]);
2746 BIO_printf(bio_err,"%s=Unknown (%c).\n",
2747 row[DB_serial], rrow[DB_type][0]);
2751 for (i=0; i<DB_NUMBER; i++)
2754 OPENSSL_free(row[i]);
2759 static int do_updatedb (TXT_DB *db)
2761 ASN1_UTCTIME *a_tm = NULL;
2763 int db_y2k, a_y2k; /* flags = 1 if y >= 2000 */
2764 char **rrow, *a_tm_s;
2766 a_tm = ASN1_UTCTIME_new();
2768 /* get actual time and make a string */
2769 a_tm = X509_gmtime_adj(a_tm, 0);
2770 a_tm_s = (char *) OPENSSL_malloc(a_tm->length+1);
2777 memcpy(a_tm_s, a_tm->data, a_tm->length);
2778 a_tm_s[a_tm->length] = '\0';
2780 if (strncmp(a_tm_s, "49", 2) <= 0)
2785 for (i = 0; i < sk_num(db->data); i++)
2787 rrow = (char **) sk_value(db->data, i);
2789 if (rrow[DB_type][0] == 'V')
2791 /* ignore entries that are not valid */
2792 if (strncmp(rrow[DB_exp_date], "49", 2) <= 0)
2797 if (db_y2k == a_y2k)
2799 /* all on the same y2k side */
2800 if (strcmp(rrow[DB_exp_date], a_tm_s) <= 0)
2802 rrow[DB_type][0] = 'E';
2803 rrow[DB_type][1] = '\0';
2806 BIO_printf(bio_err, "%s=Expired\n",
2810 else if (db_y2k < a_y2k)
2812 rrow[DB_type][0] = 'E';
2813 rrow[DB_type][1] = '\0';
2816 BIO_printf(bio_err, "%s=Expired\n",
2825 ASN1_UTCTIME_free(a_tm);
2826 OPENSSL_free(a_tm_s);
2831 static char *crl_reasons[] = {
2832 /* CRL reason strings */
2836 "affiliationChanged",
2838 "cessationOfOperation",
2841 /* Additional pseudo reasons */
2847 #define NUM_REASONS (sizeof(crl_reasons) / sizeof(char *))
2849 /* Given revocation information convert to a DB string.
2850 * The format of the string is:
2851 * revtime[,reason,extra]. Where 'revtime' is the
2852 * revocation time (the current time). 'reason' is the
2853 * optional CRL reason and 'extra' is any additional
2857 char *make_revocation_str(int rev_type, char *rev_arg)
2859 char *reason = NULL, *other = NULL, *str;
2861 ASN1_UTCTIME *revtm = NULL;
2868 case REV_CRL_REASON:
2869 for (i = 0; i < 8; i++)
2871 if (!strcasecmp(rev_arg, crl_reasons[i]))
2873 reason = crl_reasons[i];
2879 BIO_printf(bio_err, "Unknown CRL reason %s\n", rev_arg);
2885 /* Argument is an OID */
2887 otmp = OBJ_txt2obj(rev_arg, 0);
2888 ASN1_OBJECT_free(otmp);
2892 BIO_printf(bio_err, "Invalid object identifier %s\n", rev_arg);
2896 reason = "holdInstruction";
2900 case REV_KEY_COMPROMISE:
2901 case REV_CA_COMPROMISE:
2903 /* Argument is the key compromise time */
2904 if (!ASN1_GENERALIZEDTIME_set_string(NULL, rev_arg))
2906 BIO_printf(bio_err, "Invalid time format %s. Need YYYYMMDDHHMMSSZ\n", rev_arg);
2910 if (rev_type == REV_KEY_COMPROMISE)
2913 reason = "CAkeyTime";
2919 revtm = X509_gmtime_adj(NULL, 0);
2921 i = revtm->length + 1;
2923 if (reason) i += strlen(reason) + 1;
2924 if (other) i += strlen(other) + 1;
2926 str = OPENSSL_malloc(i);
2928 if (!str) return NULL;
2930 strcpy(str, (char *)revtm->data);
2934 strcat(str, reason);
2941 ASN1_UTCTIME_free(revtm);
2945 /* Convert revocation field to X509_REVOKED entry
2949 * 2 OK and some extensions added (i.e. V2 CRL)
2952 int make_revoked(X509_REVOKED *rev, char *str)
2955 char *rtime_str, *reason_str = NULL, *arg_str = NULL, *p;
2956 int reason_code = -1;
2958 ASN1_OBJECT *hold = NULL;
2959 ASN1_GENERALIZEDTIME *comp_time = NULL;
2960 ASN1_ENUMERATED *rtmp = NULL;
2961 tmp = BUF_strdup(str);
2963 p = strchr(tmp, ',');
2980 if (rev && !ASN1_UTCTIME_set_string(rev->revocationDate, rtime_str))
2982 BIO_printf(bio_err, "invalid revocation date %s\n", rtime_str);
2987 for (i = 0; i < NUM_REASONS; i++)
2989 if(!strcasecmp(reason_str, crl_reasons[i]))
2995 if (reason_code == OCSP_REVOKED_STATUS_NOSTATUS)
2997 BIO_printf(bio_err, "invalid reason code %s\n", reason_str);
3001 if (reason_code == 7)
3002 reason_code = OCSP_REVOKED_STATUS_REMOVEFROMCRL;
3003 else if (reason_code == 8) /* Hold instruction */
3007 BIO_printf(bio_err, "missing hold instruction\n");
3010 reason_code = OCSP_REVOKED_STATUS_CERTIFICATEHOLD;
3011 hold = OBJ_txt2obj(arg_str, 0);
3015 BIO_printf(bio_err, "invalid object identifier %s\n", arg_str);
3019 else if ((reason_code == 9) || (reason_code == 10))
3023 BIO_printf(bio_err, "missing compromised time\n");
3026 comp_time = ASN1_GENERALIZEDTIME_new();
3027 if (!ASN1_GENERALIZEDTIME_set_string(comp_time, arg_str))
3029 BIO_printf(bio_err, "invalid compromised time %s\n", arg_str);
3032 if (reason_code == 9)
3033 reason_code = OCSP_REVOKED_STATUS_KEYCOMPROMISE;
3035 reason_code = OCSP_REVOKED_STATUS_CACOMPROMISE;
3039 if (rev && (reason_code != OCSP_REVOKED_STATUS_NOSTATUS))
3041 rtmp = ASN1_ENUMERATED_new();
3042 if (!rtmp || !ASN1_ENUMERATED_set(rtmp, reason_code))
3044 if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0))
3048 if (rev && comp_time)
3050 if (!X509_REVOKED_add1_ext_i2d(rev, NID_invalidity_date, comp_time, 0, 0))
3055 if (!X509_REVOKED_add1_ext_i2d(rev, NID_hold_instruction_code, hold, 0, 0))
3059 if (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)
3065 if (tmp) OPENSSL_free(tmp);
3066 ASN1_OBJECT_free(hold);
3067 ASN1_GENERALIZEDTIME_free(comp_time);
3068 ASN1_ENUMERATED_free(rtmp);
3073 static X509_NAME *do_subject(char *subject)
3075 X509_NAME *n = NULL;
3077 int i, nid, ne_num=0;
3079 char *ne_name = NULL;
3080 char *ne_value = NULL;
3085 char *str_list[256];
3090 n = X509_NAME_new();
3092 tmp = strtok(subject, p[0]);
3093 while((tmp != NULL) && (ne_num < (sizeof str_list/sizeof *str_list)))
3097 while (token[0] == ' ')
3099 str_list[ne_num] = token;
3101 tmp = strtok(NULL, p[0]);
3105 for (i = 0; i < ne_num; i++)
3107 ne_name = strtok(str_list[i], p[1]);
3108 ne_value = strtok(NULL, p[1]);
3110 if ((nid=OBJ_txt2nid(ne_name)) == NID_undef)
3112 BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_name);
3116 if (ne_value == NULL)
3118 BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_name);
3122 if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_ASC, (unsigned char*)ne_value, -1,-1,0))
3133 int old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str)
3135 char buf[25],*pbuf, *p;
3137 j=i2a_ASN1_OBJECT(bp,obj);
3139 for (j=22-j; j>0; j--)
3145 if (str->type == V_ASN1_PRINTABLESTRING)
3146 BIO_printf(bp,"PRINTABLE:'");
3147 else if (str->type == V_ASN1_T61STRING)
3148 BIO_printf(bp,"T61STRING:'");
3149 else if (str->type == V_ASN1_IA5STRING)
3150 BIO_printf(bp,"IA5STRING:'");
3151 else if (str->type == V_ASN1_UNIVERSALSTRING)
3152 BIO_printf(bp,"UNIVERSALSTRING:'");
3154 BIO_printf(bp,"ASN.1 %2d:'",str->type);
3156 p=(char *)str->data;
3157 for (j=str->length; j>0; j--)
3159 if ((*p >= ' ') && (*p <= '~'))
3160 BIO_printf(bp,"%c",*p);
3162 BIO_printf(bp,"\\0x%02X",*p);
3163 else if ((unsigned char)*p == 0xf7)
3164 BIO_printf(bp,"^?");
3165 else BIO_printf(bp,"^%c",*p+'@');
3168 BIO_printf(bp,"'\n");