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>
89 # include <sys/file.h>
103 #define BASE_SECTION "ca"
104 #define CONFIG_FILE "openssl.cnf"
106 #define ENV_DEFAULT_CA "default_ca"
108 #define ENV_DIR "dir"
109 #define ENV_CERTS "certs"
110 #define ENV_CRL_DIR "crl_dir"
111 #define ENV_CA_DB "CA_DB"
112 #define ENV_NEW_CERTS_DIR "new_certs_dir"
113 #define ENV_CERTIFICATE "certificate"
114 #define ENV_SERIAL "serial"
115 #define ENV_CRL "crl"
116 #define ENV_PRIVATE_KEY "private_key"
117 #define ENV_RANDFILE "RANDFILE"
118 #define ENV_DEFAULT_DAYS "default_days"
119 #define ENV_DEFAULT_STARTDATE "default_startdate"
120 #define ENV_DEFAULT_ENDDATE "default_enddate"
121 #define ENV_DEFAULT_CRL_DAYS "default_crl_days"
122 #define ENV_DEFAULT_CRL_HOURS "default_crl_hours"
123 #define ENV_DEFAULT_MD "default_md"
124 #define ENV_PRESERVE "preserve"
125 #define ENV_POLICY "policy"
126 #define ENV_EXTENSIONS "x509_extensions"
127 #define ENV_CRLEXT "crl_extensions"
128 #define ENV_MSIE_HACK "msie_hack"
130 #define ENV_DATABASE "database"
133 #define DB_exp_date 1
134 #define DB_rev_date 2
135 #define DB_serial 3 /* index - unique */
137 #define DB_name 5 /* index - unique for active */
140 #define DB_TYPE_REV 'R'
141 #define DB_TYPE_EXP 'E'
142 #define DB_TYPE_VAL 'V'
144 /* Additional revocation information types */
146 #define REV_NONE 0 /* No addditional information */
147 #define REV_CRL_REASON 1 /* Value is CRL reason code */
148 #define REV_HOLD 2 /* Value is hold instruction */
149 #define REV_KEY_COMPROMISE 3 /* Value is cert key compromise time */
150 #define REV_CA_COMPROMISE 4 /* Value is CA key compromise time */
152 static char *ca_usage[]={
155 " -verbose - Talk alot while doing things\n",
156 " -config file - A config file\n",
157 " -name arg - The particular CA definition to use\n",
158 " -gencrl - Generate a new CRL\n",
159 " -crldays days - Days is when the next CRL is due\n",
160 " -crlhours hours - Hours is when the next CRL is due\n",
161 " -startdate YYMMDDHHMMSSZ - certificate validity notBefore\n",
162 " -enddate YYMMDDHHMMSSZ - certificate validity notAfter (overrides -days)\n",
163 " -days arg - number of days to certify the certificate for\n",
164 " -md arg - md to use, one of md2, md5, sha or sha1\n",
165 " -policy arg - The CA 'policy' to support\n",
166 " -keyfile arg - private key file\n",
167 " -keyform arg - private key file format (PEM or ENGINE)\n",
168 " -key arg - key to decode the private key if it is encrypted\n",
169 " -cert file - The CA certificate\n",
170 " -in file - The input PEM encoded certificate request(s)\n",
171 " -out file - Where to put the output file(s)\n",
172 " -outdir dir - Where to put output certificates\n",
173 " -infiles .... - The last argument, requests to process\n",
174 " -spkac file - File contains DN and signed public key and challenge\n",
175 " -ss_cert file - File contains a self signed cert to sign\n",
176 " -preserveDN - Don't re-order the DN\n",
177 " -batch - Don't ask questions\n",
178 " -msie_hack - msie modifications to handle all those universal strings\n",
179 " -revoke file - Revoke a certificate (given in file)\n",
180 " -extensions .. - Extension section (override value in config file)\n",
181 " -extfile file - Configuration file with X509v3 extentions to add\n",
182 " -crlexts .. - CRL extension section (override value in config file)\n",
183 " -engine e - use engine e, possibly a hardware device.\n",
184 " -status serial - Shows certificate status given the serial number\n",
185 " -updatedb - Updates db for expired certificates\n",
190 extern int EF_PROTECT_FREE;
191 extern int EF_PROTECT_BELOW;
192 extern int EF_ALIGNMENT;
195 static void lookup_fail(char *name,char *tag);
196 static unsigned long index_serial_hash(const char **a);
197 static int index_serial_cmp(const char **a, const char **b);
198 static unsigned long index_name_hash(const char **a);
199 static int index_name_qual(char **a);
200 static int index_name_cmp(const char **a,const char **b);
201 static BIGNUM *load_serial(char *serialfile);
202 static int save_serial(char *serialfile, BIGNUM *serial);
203 static int certify(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
204 const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,TXT_DB *db,
205 BIGNUM *serial, char *startdate,char *enddate, int days,
206 int batch, char *ext_sect, LHASH *conf,int verbose);
207 static int certify_cert(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
208 const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
209 TXT_DB *db, BIGNUM *serial,char *startdate,
210 char *enddate, int days, int batch, char *ext_sect,
211 LHASH *conf,int verbose);
212 static int certify_spkac(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
213 const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
214 TXT_DB *db, BIGNUM *serial,char *startdate,
215 char *enddate, int days, char *ext_sect,LHASH *conf,
217 static int fix_data(int nid, int *type);
218 static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext);
219 static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
220 STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial,
221 char *startdate, char *enddate, int days, int batch, int verbose,
222 X509_REQ *req, char *ext_sect, LHASH *conf);
223 static int do_revoke(X509 *x509, TXT_DB *db, int ext, char *extval);
224 static int get_certificate_status(const char *ser_status, TXT_DB *db);
225 static int do_updatedb(TXT_DB *db);
226 static int check_time_format(char *str);
227 char *make_revocation_str(int rev_type, char *rev_arg);
228 int make_revoked(X509_REVOKED *rev, char *str);
229 static LHASH *conf=NULL;
230 static LHASH *extconf=NULL;
231 static char *section=NULL;
233 static int preserve=0;
234 static int msie_hack=0;
236 static IMPLEMENT_LHASH_HASH_FN(index_serial_hash,const char **)
237 static IMPLEMENT_LHASH_COMP_FN(index_serial_cmp,const char **)
238 static IMPLEMENT_LHASH_HASH_FN(index_name_hash,const char **)
239 static IMPLEMENT_LHASH_COMP_FN(index_name_cmp,const char **)
242 int MAIN(int, char **);
244 int MAIN(int argc, char **argv)
247 char *key=NULL,*passargin=NULL;
260 char *configfile=NULL;
265 int keyform=FORMAT_PEM;
267 char *spkac_file=NULL;
268 char *ss_cert_file=NULL;
269 char *ser_status=NULL;
274 char *serialfile=NULL;
275 char *extensions=NULL;
278 int rev_type = REV_NONE;
279 char *rev_arg = NULL;
281 char *startdate=NULL;
288 BIO *in=NULL,*out=NULL,*Sout=NULL,*Cout=NULL;
292 X509_CRL_INFO *ci=NULL;
293 X509_REVOKED *r=NULL;
297 const EVP_MD *dgst=NULL;
298 STACK_OF(CONF_VALUE) *attribs=NULL;
299 STACK_OF(X509) *cert_sk=NULL;
303 MS_STATIC char buf[3][BSIZE];
322 if ((bio_err=BIO_new(BIO_s_file())) != NULL)
323 BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
329 if (strcmp(*argv,"-verbose") == 0)
331 else if (strcmp(*argv,"-config") == 0)
333 if (--argc < 1) goto bad;
334 configfile= *(++argv);
336 else if (strcmp(*argv,"-name") == 0)
338 if (--argc < 1) goto bad;
341 else if (strcmp(*argv,"-startdate") == 0)
343 if (--argc < 1) goto bad;
344 startdate= *(++argv);
346 else if (strcmp(*argv,"-enddate") == 0)
348 if (--argc < 1) goto bad;
351 else if (strcmp(*argv,"-days") == 0)
353 if (--argc < 1) goto bad;
354 days=atoi(*(++argv));
356 else if (strcmp(*argv,"-md") == 0)
358 if (--argc < 1) goto bad;
361 else if (strcmp(*argv,"-policy") == 0)
363 if (--argc < 1) goto bad;
366 else if (strcmp(*argv,"-keyfile") == 0)
368 if (--argc < 1) goto bad;
371 else if (strcmp(*argv,"-keyform") == 0)
373 if (--argc < 1) goto bad;
374 keyform=str2fmt(*(++argv));
376 else if (strcmp(*argv,"-passin") == 0)
378 if (--argc < 1) goto bad;
379 passargin= *(++argv);
381 else if (strcmp(*argv,"-key") == 0)
383 if (--argc < 1) goto bad;
386 else if (strcmp(*argv,"-cert") == 0)
388 if (--argc < 1) goto bad;
391 else if (strcmp(*argv,"-in") == 0)
393 if (--argc < 1) goto bad;
397 else if (strcmp(*argv,"-out") == 0)
399 if (--argc < 1) goto bad;
402 else if (strcmp(*argv,"-outdir") == 0)
404 if (--argc < 1) goto bad;
407 else if (strcmp(*argv,"-notext") == 0)
409 else if (strcmp(*argv,"-batch") == 0)
411 else if (strcmp(*argv,"-preserveDN") == 0)
413 else if (strcmp(*argv,"-gencrl") == 0)
415 else if (strcmp(*argv,"-msie_hack") == 0)
417 else if (strcmp(*argv,"-crldays") == 0)
419 if (--argc < 1) goto bad;
420 crldays= atol(*(++argv));
422 else if (strcmp(*argv,"-crlhours") == 0)
424 if (--argc < 1) goto bad;
425 crlhours= atol(*(++argv));
427 else if (strcmp(*argv,"-infiles") == 0)
434 else if (strcmp(*argv, "-ss_cert") == 0)
436 if (--argc < 1) goto bad;
437 ss_cert_file = *(++argv);
440 else if (strcmp(*argv, "-spkac") == 0)
442 if (--argc < 1) goto bad;
443 spkac_file = *(++argv);
446 else if (strcmp(*argv,"-revoke") == 0)
448 if (--argc < 1) goto bad;
452 else if (strcmp(*argv,"-extensions") == 0)
454 if (--argc < 1) goto bad;
455 extensions= *(++argv);
457 else if (strcmp(*argv,"-extfile") == 0)
459 if (--argc < 1) goto bad;
462 else if (strcmp(*argv,"-status") == 0)
464 if (--argc < 1) goto bad;
465 ser_status= *(++argv);
467 else if (strcmp(*argv,"-updatedb") == 0)
471 else if (strcmp(*argv,"-crlexts") == 0)
473 if (--argc < 1) goto bad;
476 else if (strcmp(*argv,"-crl_reason") == 0)
478 if (--argc < 1) goto bad;
480 rev_type = REV_CRL_REASON;
482 else if (strcmp(*argv,"-crl_hold") == 0)
484 if (--argc < 1) goto bad;
488 else if (strcmp(*argv,"-crl_compromise") == 0)
490 if (--argc < 1) goto bad;
492 rev_type = REV_KEY_COMPROMISE;
494 else if (strcmp(*argv,"-crl_CA_compromise") == 0)
496 if (--argc < 1) goto bad;
498 rev_type = REV_CA_COMPROMISE;
500 else if (strcmp(*argv,"-engine") == 0)
502 if (--argc < 1) goto bad;
508 BIO_printf(bio_err,"unknown option %s\n",*argv);
518 for (pp=ca_usage; (*pp != NULL); pp++)
519 BIO_printf(bio_err,"%s",*pp);
523 ERR_load_crypto_strings();
527 if ((e = ENGINE_by_id(engine)) == NULL)
529 BIO_printf(bio_err,"invalid engine \"%s\"\n",
533 if (!ENGINE_set_default(e, ENGINE_METHOD_ALL))
535 BIO_printf(bio_err,"can't use that engine\n");
538 BIO_printf(bio_err,"engine \"%s\" set.\n", engine);
539 /* Free our "structural" reference. */
543 /*****************************************************************/
544 if (configfile == NULL) configfile = getenv("OPENSSL_CONF");
545 if (configfile == NULL) configfile = getenv("SSLEAY_CONF");
546 if (configfile == NULL)
548 /* We will just use 'buf[0]' as a temporary buffer. */
550 strncpy(buf[0],X509_get_default_cert_area(),
551 sizeof(buf[0])-1-sizeof(CONFIG_FILE));
553 strncpy(buf[0],X509_get_default_cert_area(),
554 sizeof(buf[0])-2-sizeof(CONFIG_FILE));
557 strcat(buf[0],CONFIG_FILE);
561 BIO_printf(bio_err,"Using configuration from %s\n",configfile);
562 if ((conf=CONF_load(NULL,configfile,&errorline)) == NULL)
565 BIO_printf(bio_err,"error loading the config file '%s'\n",
568 BIO_printf(bio_err,"error on line %ld of config file '%s'\n"
569 ,errorline,configfile);
573 /* Lets get the config section we are using */
576 section=CONF_get_string(conf,BASE_SECTION,ENV_DEFAULT_CA);
579 lookup_fail(BASE_SECTION,ENV_DEFAULT_CA);
586 p=CONF_get_string(conf,NULL,"oid_file");
593 oid_bio=BIO_new_file(p,"r");
597 BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
598 ERR_print_errors(bio_err);
604 OBJ_create_objects(oid_bio);
608 if (!add_oid_section(bio_err,conf))
610 ERR_print_errors(bio_err);
615 randfile = CONF_get_string(conf, BASE_SECTION, "RANDFILE");
616 if (randfile == NULL)
618 app_RAND_load_file(randfile, bio_err, 0);
620 in=BIO_new(BIO_s_file());
621 out=BIO_new(BIO_s_file());
622 Sout=BIO_new(BIO_s_file());
623 Cout=BIO_new(BIO_s_file());
624 if ((in == NULL) || (out == NULL) || (Sout == NULL) || (Cout == NULL))
626 ERR_print_errors(bio_err);
630 /*****************************************************************/
631 /* report status of cert with serial number given on command line */
634 if ((dbfile=CONF_get_string(conf,section,ENV_DATABASE)) == NULL)
636 lookup_fail(section,ENV_DATABASE);
639 if (BIO_read_filename(in,dbfile) <= 0)
642 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
645 db=TXT_DB_read(in,DB_NUMBER);
646 if (db == NULL) goto err;
648 if (!TXT_DB_create_index(db, DB_serial, NULL,
649 LHASH_HASH_FN(index_serial_hash),
650 LHASH_COMP_FN(index_serial_cmp)))
653 "error creating serial number index:(%ld,%ld,%ld)\n",
654 db->error,db->arg1,db->arg2);
658 if (get_certificate_status(ser_status,db) != 1)
659 BIO_printf(bio_err,"Error verifying serial %s!\n",
664 /*****************************************************************/
665 /* we definitely need a public key, so let's get it */
667 if ((keyfile == NULL) && ((keyfile=CONF_get_string(conf,
668 section,ENV_PRIVATE_KEY)) == NULL))
670 lookup_fail(section,ENV_PRIVATE_KEY);
673 if (!key && !app_passwd(bio_err, passargin, NULL, &key, NULL))
675 BIO_printf(bio_err,"Error getting password\n");
678 if (keyform == FORMAT_ENGINE)
682 BIO_printf(bio_err,"no engine specified\n");
685 pkey = ENGINE_load_private_key(e, keyfile, key);
687 else if (keyform == FORMAT_PEM)
689 if (BIO_read_filename(in,keyfile) <= 0)
692 BIO_printf(bio_err,"trying to load CA private key\n");
695 pkey=PEM_read_bio_PrivateKey(in,NULL,NULL,key);
699 BIO_printf(bio_err,"bad input format specified for key file\n");
702 if (key) memset(key,0,strlen(key));
705 BIO_printf(bio_err,"unable to load CA private key\n");
709 /*****************************************************************/
710 /* we need a certificate */
711 if ((certfile == NULL) && ((certfile=CONF_get_string(conf,
712 section,ENV_CERTIFICATE)) == NULL))
714 lookup_fail(section,ENV_CERTIFICATE);
717 if (BIO_read_filename(in,certfile) <= 0)
720 BIO_printf(bio_err,"trying to load CA certificate\n");
723 x509=PEM_read_bio_X509(in,NULL,NULL,NULL);
726 BIO_printf(bio_err,"unable to load CA certificate\n");
730 if (!X509_check_private_key(x509,pkey))
732 BIO_printf(bio_err,"CA certificate and CA private key do not match\n");
736 f=CONF_get_string(conf,BASE_SECTION,ENV_PRESERVE);
739 if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
741 f=CONF_get_string(conf,BASE_SECTION,ENV_MSIE_HACK);
744 if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
747 /*****************************************************************/
748 /* lookup where to write new certificates */
749 if ((outdir == NULL) && (req))
753 if ((outdir=CONF_get_string(conf,section,ENV_NEW_CERTS_DIR))
756 BIO_printf(bio_err,"there needs to be defined a directory for new certificate to be placed in\n");
759 #ifndef VMS /* outdir is a directory spec, but access() for VMS demands a
760 filename. In any case, stat(), below, will catch the problem
761 if outdir is not a directory spec, and the fopen() or open()
762 will catch an error if there is no write access.
764 Presumably, this problem could also be solved by using the DEC
765 C routines to convert the directory syntax to Unixly, and give
766 that to access(). However, time's too short to do that just
769 if (access(outdir,R_OK|W_OK|X_OK) != 0)
771 BIO_printf(bio_err,"I am unable to access the %s directory\n",outdir);
776 if (stat(outdir,&sb) != 0)
778 BIO_printf(bio_err,"unable to stat(%s)\n",outdir);
783 if (!(sb.st_mode & S_IFDIR))
785 BIO_printf(bio_err,"%s need to be a directory\n",outdir);
793 /*****************************************************************/
794 /* we need to load the database file */
795 if ((dbfile=CONF_get_string(conf,section,ENV_DATABASE)) == NULL)
797 lookup_fail(section,ENV_DATABASE);
800 if (BIO_read_filename(in,dbfile) <= 0)
803 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
806 db=TXT_DB_read(in,DB_NUMBER);
807 if (db == NULL) goto err;
809 /* Lets check some fields */
810 for (i=0; i<sk_num(db->data); i++)
812 pp=(char **)sk_value(db->data,i);
813 if ((pp[DB_type][0] != DB_TYPE_REV) &&
814 (pp[DB_rev_date][0] != '\0'))
816 BIO_printf(bio_err,"entry %d: not revoked yet, but has a revocation date\n",i+1);
819 if ((pp[DB_type][0] == DB_TYPE_REV) &&
820 !make_revoked(NULL, pp[DB_rev_date]))
822 BIO_printf(bio_err," in entry %d\n", i+1);
825 if (!check_time_format(pp[DB_exp_date]))
827 BIO_printf(bio_err,"entry %d: invalid expiry date\n",i+1);
832 if ((j&1) || (j < 2))
834 BIO_printf(bio_err,"entry %d: bad serial number length (%d)\n",i+1,j);
839 if (!( ((*p >= '0') && (*p <= '9')) ||
840 ((*p >= 'A') && (*p <= 'F')) ||
841 ((*p >= 'a') && (*p <= 'f'))) )
843 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);
851 BIO_set_fp(out,stdout,BIO_NOCLOSE|BIO_FP_TEXT); /* cannot fail */
854 BIO *tmpbio = BIO_new(BIO_f_linebuffer());
855 out = BIO_push(tmpbio, out);
858 TXT_DB_write(out,db);
859 BIO_printf(bio_err,"%d entries loaded from the database\n",
861 BIO_printf(bio_err,"generating index\n");
864 if (!TXT_DB_create_index(db, DB_serial, NULL,
865 LHASH_HASH_FN(index_serial_hash),
866 LHASH_COMP_FN(index_serial_cmp)))
868 BIO_printf(bio_err,"error creating serial number index:(%ld,%ld,%ld)\n",db->error,db->arg1,db->arg2);
872 if (!TXT_DB_create_index(db, DB_name, index_name_qual,
873 LHASH_HASH_FN(index_name_hash),
874 LHASH_COMP_FN(index_name_cmp)))
876 BIO_printf(bio_err,"error creating name index:(%ld,%ld,%ld)\n",
877 db->error,db->arg1,db->arg2);
881 /*****************************************************************/
882 /* Update the db file for expired certificates */
886 BIO_printf(bio_err, "Updating %s ...\n",
892 BIO_printf(bio_err,"Malloc failure\n");
897 if (verbose) BIO_printf(bio_err,
898 "No entries found to mark expired\n");
902 out = BIO_new(BIO_s_file());
905 ERR_print_errors(bio_err);
909 j = BIO_snprintf(buf[0], sizeof buf[0], "%s.new", dbfile);
910 if (j < 0 || j >= sizeof buf[0])
912 BIO_printf(bio_err, "file name too long\n");
915 if (BIO_write_filename(out,buf[0]) <= 0)
918 BIO_printf(bio_err,"unable to open '%s'\n",
922 j=TXT_DB_write(out,db);
923 if (j <= 0) goto err;
927 j = BIO_snprintf(buf[1], sizeof buf[1], "%s.old", dbfile);
928 if (j < 0 || j >= sizeof buf[1])
930 BIO_printf(bio_err, "file name too long\n");
933 if (rename(dbfile,buf[1]) < 0)
936 "unable to rename %s to %s\n",
941 if (rename(buf[0],dbfile) < 0)
944 "unable to rename %s to %s\n",
947 rename(buf[1],dbfile);
951 if (verbose) BIO_printf(bio_err,
952 "Done. %d entries marked as expired\n",i);
957 /*****************************************************************/
958 /* Read extentions config file */
961 if (!(extconf=CONF_load(NULL,extfile,&errorline)))
964 BIO_printf(bio_err, "ERROR: loading the config file '%s'\n",
967 BIO_printf(bio_err, "ERROR: on line %ld of config file '%s'\n",
974 BIO_printf(bio_err, "Succesfully loaded extensions file %s\n", extfile);
976 /* We can have sections in the ext file */
977 if (!extensions && !(extensions = CONF_get_string(extconf, "default", "extensions")))
978 extensions = "default";
981 /*****************************************************************/
986 if (BIO_write_filename(Sout,outfile) <= 0)
994 BIO_set_fp(Sout,stdout,BIO_NOCLOSE|BIO_FP_TEXT);
997 BIO *tmpbio = BIO_new(BIO_f_linebuffer());
998 Sout = BIO_push(tmpbio, Sout);
1006 if ((md == NULL) && ((md=CONF_get_string(conf,
1007 section,ENV_DEFAULT_MD)) == NULL))
1009 lookup_fail(section,ENV_DEFAULT_MD);
1012 if ((dgst=EVP_get_digestbyname(md)) == NULL)
1014 BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
1018 BIO_printf(bio_err,"message digest is %s\n",
1019 OBJ_nid2ln(dgst->type));
1020 if ((policy == NULL) && ((policy=CONF_get_string(conf,
1021 section,ENV_POLICY)) == NULL))
1023 lookup_fail(section,ENV_POLICY);
1027 BIO_printf(bio_err,"policy is %s\n",policy);
1029 if ((serialfile=CONF_get_string(conf,section,ENV_SERIAL))
1032 lookup_fail(section,ENV_SERIAL);
1038 /* no '-extfile' option, so we look for extensions
1039 * in the main configuration file */
1042 extensions=CONF_get_string(conf,section,
1049 /* Check syntax of file */
1051 X509V3_set_ctx_test(&ctx);
1052 X509V3_set_conf_lhash(&ctx, conf);
1053 if (!X509V3_EXT_add_conf(conf, &ctx, extensions,
1057 "Error Loading extension section %s\n",
1065 if (startdate == NULL)
1067 startdate=CONF_get_string(conf,section,
1068 ENV_DEFAULT_STARTDATE);
1069 if (startdate == NULL)
1072 if (startdate && !ASN1_UTCTIME_set_string(NULL,startdate))
1074 BIO_printf(bio_err,"start date is invalid, it should be YYMMDDHHMMSSZ\n");
1077 if (startdate == NULL) startdate="today";
1079 if (enddate == NULL)
1081 enddate=CONF_get_string(conf,section,
1082 ENV_DEFAULT_ENDDATE);
1083 if (enddate == NULL)
1086 if (enddate && !ASN1_UTCTIME_set_string(NULL,enddate))
1088 BIO_printf(bio_err,"end date is invalid, it should be YYMMDDHHMMSSZ\n");
1094 days=(int)CONF_get_number(conf,section,
1097 if (!enddate && (days == 0))
1099 BIO_printf(bio_err,"cannot lookup how many days to certify for\n");
1103 if ((serial=load_serial(serialfile)) == NULL)
1105 BIO_printf(bio_err,"error while loading serial number\n");
1110 if ((f=BN_bn2hex(serial)) == NULL) goto err;
1111 BIO_printf(bio_err,"next serial number is %s\n",f);
1115 if ((attribs=CONF_get_section(conf,policy)) == NULL)
1117 BIO_printf(bio_err,"unable to find 'section' for %s\n",policy);
1121 if ((cert_sk=sk_X509_new_null()) == NULL)
1123 BIO_printf(bio_err,"Memory allocation failure\n");
1126 if (spkac_file != NULL)
1129 j=certify_spkac(&x,spkac_file,pkey,x509,dgst,attribs,db,
1130 serial,startdate,enddate, days,extensions,conf,
1132 if (j < 0) goto err;
1136 BIO_printf(bio_err,"\n");
1137 if (!BN_add_word(serial,1)) goto err;
1138 if (!sk_X509_push(cert_sk,x))
1140 BIO_printf(bio_err,"Memory allocation failure\n");
1150 if (ss_cert_file != NULL)
1153 j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,attribs,
1154 db,serial,startdate,enddate,days,batch,
1155 extensions,conf,verbose);
1156 if (j < 0) goto err;
1160 BIO_printf(bio_err,"\n");
1161 if (!BN_add_word(serial,1)) goto err;
1162 if (!sk_X509_push(cert_sk,x))
1164 BIO_printf(bio_err,"Memory allocation failure\n");
1172 j=certify(&x,infile,pkey,x509,dgst,attribs,db,
1173 serial,startdate,enddate,days,batch,
1174 extensions,conf,verbose);
1175 if (j < 0) goto err;
1179 BIO_printf(bio_err,"\n");
1180 if (!BN_add_word(serial,1)) goto err;
1181 if (!sk_X509_push(cert_sk,x))
1183 BIO_printf(bio_err,"Memory allocation failure\n");
1188 for (i=0; i<argc; i++)
1191 j=certify(&x,argv[i],pkey,x509,dgst,attribs,db,
1192 serial,startdate,enddate,days,batch,
1193 extensions,conf,verbose);
1194 if (j < 0) goto err;
1198 BIO_printf(bio_err,"\n");
1199 if (!BN_add_word(serial,1)) goto err;
1200 if (!sk_X509_push(cert_sk,x))
1202 BIO_printf(bio_err,"Memory allocation failure\n");
1207 /* we have a stack of newly certified certificates
1208 * and a data base and serial number that need
1211 if (sk_X509_num(cert_sk) > 0)
1215 BIO_printf(bio_err,"\n%d out of %d certificate requests certified, commit? [y/n]",total_done,total);
1216 (void)BIO_flush(bio_err);
1218 fgets(buf[0],10,stdin);
1219 if ((buf[0][0] != 'y') && (buf[0][0] != 'Y'))
1221 BIO_printf(bio_err,"CERTIFICATION CANCELED\n");
1227 BIO_printf(bio_err,"Write out database with %d new entries\n",sk_X509_num(cert_sk));
1229 strncpy(buf[0],serialfile,BSIZE-4);
1232 strcat(buf[0],"-new");
1234 strcat(buf[0],".new");
1237 if (!save_serial(buf[0],serial)) goto err;
1239 strncpy(buf[1],dbfile,BSIZE-4);
1242 strcat(buf[1],"-new");
1244 strcat(buf[1],".new");
1247 if (BIO_write_filename(out,buf[1]) <= 0)
1250 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
1253 l=TXT_DB_write(out,db);
1254 if (l <= 0) goto err;
1258 BIO_printf(bio_err,"writing new certificates\n");
1259 for (i=0; i<sk_X509_num(cert_sk); i++)
1264 x=sk_X509_value(cert_sk,i);
1266 j=x->cert_info->serialNumber->length;
1267 p=(char *)x->cert_info->serialNumber->data;
1269 strncpy(buf[2],outdir,BSIZE-(j*2)-6);
1275 n=(unsigned char *)&(buf[2][strlen(buf[2])]);
1280 sprintf((char *)n,"%02X",(unsigned char)*(p++));
1289 *(n++)='.'; *(n++)='p'; *(n++)='e'; *(n++)='m';
1292 BIO_printf(bio_err,"writing %s\n",buf[2]);
1294 if (BIO_write_filename(Cout,buf[2]) <= 0)
1299 write_new_certificate(Cout,x, 0, notext);
1300 write_new_certificate(Sout,x, output_der, notext);
1303 if (sk_X509_num(cert_sk))
1305 /* Rename the database and the serial file */
1306 strncpy(buf[2],serialfile,BSIZE-4);
1309 strcat(buf[2],"-old");
1311 strcat(buf[2],".old");
1318 if (rename(serialfile,buf[2]) < 0)
1320 BIO_printf(bio_err,"unable to rename %s to %s\n",
1325 if (rename(buf[0],serialfile) < 0)
1327 BIO_printf(bio_err,"unable to rename %s to %s\n",
1330 rename(buf[2],serialfile);
1334 strncpy(buf[2],dbfile,BSIZE-4);
1337 strcat(buf[2],"-old");
1339 strcat(buf[2],".old");
1342 if (rename(dbfile,buf[2]) < 0)
1344 BIO_printf(bio_err,"unable to rename %s to %s\n",
1349 if (rename(buf[1],dbfile) < 0)
1351 BIO_printf(bio_err,"unable to rename %s to %s\n",
1354 rename(buf[2],dbfile);
1357 BIO_printf(bio_err,"Data Base Updated\n");
1361 /*****************************************************************/
1367 crl_ext=CONF_get_string(conf,section,ENV_CRLEXT);
1373 /* Check syntax of file */
1375 X509V3_set_ctx_test(&ctx);
1376 X509V3_set_conf_lhash(&ctx, conf);
1377 if (!X509V3_EXT_add_conf(conf, &ctx, crl_ext, NULL))
1380 "Error Loading CRL extension section %s\n",
1386 if ((hex=BIO_new(BIO_s_mem())) == NULL) goto err;
1388 if (!crldays && !crlhours)
1390 crldays=CONF_get_number(conf,section,
1391 ENV_DEFAULT_CRL_DAYS);
1392 crlhours=CONF_get_number(conf,section,
1393 ENV_DEFAULT_CRL_HOURS);
1395 if ((crldays == 0) && (crlhours == 0))
1397 BIO_printf(bio_err,"cannot lookup how long until the next CRL is issuer\n");
1401 if (verbose) BIO_printf(bio_err,"making CRL\n");
1402 if ((crl=X509_CRL_new()) == NULL) goto err;
1404 X509_NAME_free(ci->issuer);
1405 ci->issuer=X509_NAME_dup(x509->cert_info->subject);
1406 if (ci->issuer == NULL) goto err;
1408 X509_gmtime_adj(ci->lastUpdate,0);
1409 if (ci->nextUpdate == NULL)
1410 ci->nextUpdate=ASN1_UTCTIME_new();
1411 X509_gmtime_adj(ci->nextUpdate,(crldays*24+crlhours)*60*60);
1413 for (i=0; i<sk_num(db->data); i++)
1415 pp=(char **)sk_value(db->data,i);
1416 if (pp[DB_type][0] == DB_TYPE_REV)
1418 if ((r=X509_REVOKED_new()) == NULL) goto err;
1419 j = make_revoked(r, pp[DB_rev_date]);
1421 if (j == 2) crl_v2 = 1;
1422 (void)BIO_reset(hex);
1423 if (!BIO_puts(hex,pp[DB_serial]))
1425 if (!a2i_ASN1_INTEGER(hex,r->serialNumber,
1426 buf[0],BSIZE)) goto err;
1428 X509_CRL_add0_revoked(crl,r);
1431 /* sort the data so it will be written in serial
1433 sk_X509_REVOKED_sort(ci->revoked);
1434 for (i=0; i<sk_X509_REVOKED_num(ci->revoked); i++)
1436 r=sk_X509_REVOKED_value(ci->revoked,i);
1440 /* we now have a CRL */
1441 if (verbose) BIO_printf(bio_err,"signing CRL\n");
1444 if ((dgst=EVP_get_digestbyname(md)) == NULL)
1446 BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
1453 if (pkey->type == EVP_PKEY_DSA)
1460 /* Add any extensions asked for */
1465 if (ci->version == NULL)
1466 if ((ci->version=ASN1_INTEGER_new()) == NULL) goto err;
1467 X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0);
1468 X509V3_set_conf_lhash(&crlctx, conf);
1470 if (!X509V3_EXT_CRL_add_conf(conf, &crlctx,
1471 crl_ext, crl)) goto err;
1473 if (crl_ext || crl_v2)
1475 if (ci->version == NULL)
1476 if ((ci->version=ASN1_INTEGER_new()) == NULL) goto err;
1477 ASN1_INTEGER_set(ci->version,1); /* version 2 CRL */
1480 if (!X509_CRL_sign(crl,pkey,dgst)) goto err;
1482 PEM_write_bio_X509_CRL(Sout,crl);
1484 /*****************************************************************/
1489 BIO_printf(bio_err,"no input files\n");
1495 if (BIO_read_filename(in,infile) <= 0)
1498 BIO_printf(bio_err,"error trying to load '%s' certificate\n",infile);
1501 revcert=PEM_read_bio_X509(in,NULL,NULL,NULL);
1502 if (revcert == NULL)
1504 BIO_printf(bio_err,"unable to load '%s' certificate\n",infile);
1507 j=do_revoke(revcert,db, rev_type, rev_arg);
1508 if (j <= 0) goto err;
1511 strncpy(buf[0],dbfile,BSIZE-4);
1512 strcat(buf[0],".new");
1513 if (BIO_write_filename(out,buf[0]) <= 0)
1516 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
1519 j=TXT_DB_write(out,db);
1520 if (j <= 0) goto err;
1521 strncpy(buf[1],dbfile,BSIZE-4);
1522 strcat(buf[1],".old");
1523 if (rename(dbfile,buf[1]) < 0)
1525 BIO_printf(bio_err,"unable to rename %s to %s\n", dbfile, buf[1]);
1529 if (rename(buf[0],dbfile) < 0)
1531 BIO_printf(bio_err,"unable to rename %s to %s\n", buf[0],dbfile);
1533 rename(buf[1],dbfile);
1536 BIO_printf(bio_err,"Data Base Updated\n");
1539 /*****************************************************************/
1548 sk_X509_pop_free(cert_sk,X509_free);
1550 if (ret) ERR_print_errors(bio_err);
1551 app_RAND_write_file(randfile, bio_err);
1554 EVP_PKEY_free(pkey);
1562 static void lookup_fail(char *name, char *tag)
1564 BIO_printf(bio_err,"variable lookup failed for %s::%s\n",name,tag);
1567 static unsigned long index_serial_hash(const char **a)
1572 while (*n == '0') n++;
1573 return(lh_strhash(n));
1576 static int index_serial_cmp(const char **a, const char **b)
1580 for (aa=a[DB_serial]; *aa == '0'; aa++);
1581 for (bb=b[DB_serial]; *bb == '0'; bb++);
1582 return(strcmp(aa,bb));
1585 static unsigned long index_name_hash(const char **a)
1586 { return(lh_strhash(a[DB_name])); }
1588 static int index_name_qual(char **a)
1589 { return(a[0][0] == 'V'); }
1591 static int index_name_cmp(const char **a, const char **b)
1592 { return(strcmp(a[DB_name],
1595 static BIGNUM *load_serial(char *serialfile)
1599 MS_STATIC char buf[1024];
1600 ASN1_INTEGER *ai=NULL;
1602 if ((in=BIO_new(BIO_s_file())) == NULL)
1604 ERR_print_errors(bio_err);
1608 if (BIO_read_filename(in,serialfile) <= 0)
1613 ai=ASN1_INTEGER_new();
1614 if (ai == NULL) goto err;
1615 if (!a2i_ASN1_INTEGER(in,ai,buf,1024))
1617 BIO_printf(bio_err,"unable to load number from %s\n",
1621 ret=ASN1_INTEGER_to_BN(ai,NULL);
1624 BIO_printf(bio_err,"error converting number from bin to BIGNUM");
1628 if (in != NULL) BIO_free(in);
1629 if (ai != NULL) ASN1_INTEGER_free(ai);
1633 static int save_serial(char *serialfile, BIGNUM *serial)
1637 ASN1_INTEGER *ai=NULL;
1639 out=BIO_new(BIO_s_file());
1642 ERR_print_errors(bio_err);
1645 if (BIO_write_filename(out,serialfile) <= 0)
1651 if ((ai=BN_to_ASN1_INTEGER(serial,NULL)) == NULL)
1653 BIO_printf(bio_err,"error converting serial to ASN.1 format\n");
1656 i2a_ASN1_INTEGER(out,ai);
1660 if (out != NULL) BIO_free_all(out);
1661 if (ai != NULL) ASN1_INTEGER_free(ai);
1665 static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1666 const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
1667 BIGNUM *serial, char *startdate, char *enddate, int days,
1668 int batch, char *ext_sect, LHASH *lconf, int verbose)
1672 EVP_PKEY *pktmp=NULL;
1675 in=BIO_new(BIO_s_file());
1677 if (BIO_read_filename(in,infile) <= 0)
1682 if ((req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL)) == NULL)
1684 BIO_printf(bio_err,"Error reading certificate request in %s\n",
1689 X509_REQ_print(bio_err,req);
1691 BIO_printf(bio_err,"Check that the request matches the signature\n");
1693 if ((pktmp=X509_REQ_get_pubkey(req)) == NULL)
1695 BIO_printf(bio_err,"error unpacking public key\n");
1698 i=X509_REQ_verify(req,pktmp);
1699 EVP_PKEY_free(pktmp);
1703 BIO_printf(bio_err,"Signature verification problems....\n");
1709 BIO_printf(bio_err,"Signature did not match the certificate request\n");
1713 BIO_printf(bio_err,"Signature ok\n");
1715 ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate, enddate,
1716 days,batch,verbose,req,ext_sect,lconf);
1719 if (req != NULL) X509_REQ_free(req);
1720 if (in != NULL) BIO_free(in);
1724 static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1725 const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
1726 BIGNUM *serial, char *startdate, char *enddate, int days,
1727 int batch, char *ext_sect, LHASH *lconf, int verbose)
1730 X509_REQ *rreq=NULL;
1732 EVP_PKEY *pktmp=NULL;
1735 in=BIO_new(BIO_s_file());
1737 if (BIO_read_filename(in,infile) <= 0)
1742 if ((req=PEM_read_bio_X509(in,NULL,NULL,NULL)) == NULL)
1744 BIO_printf(bio_err,"Error reading self signed certificate in %s\n",infile);
1748 X509_print(bio_err,req);
1750 BIO_printf(bio_err,"Check that the request matches the signature\n");
1752 if ((pktmp=X509_get_pubkey(req)) == NULL)
1754 BIO_printf(bio_err,"error unpacking public key\n");
1757 i=X509_verify(req,pktmp);
1758 EVP_PKEY_free(pktmp);
1762 BIO_printf(bio_err,"Signature verification problems....\n");
1768 BIO_printf(bio_err,"Signature did not match the certificate\n");
1772 BIO_printf(bio_err,"Signature ok\n");
1774 if ((rreq=X509_to_X509_REQ(req,NULL,EVP_md5())) == NULL)
1777 ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,enddate,days,
1778 batch,verbose,rreq,ext_sect,lconf);
1781 if (rreq != NULL) X509_REQ_free(rreq);
1782 if (req != NULL) X509_free(req);
1783 if (in != NULL) BIO_free(in);
1787 static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
1788 STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial,
1789 char *startdate, char *enddate, int days, int batch, int verbose,
1790 X509_REQ *req, char *ext_sect, LHASH *lconf)
1792 X509_NAME *name=NULL,*CAname=NULL,*subject=NULL;
1793 ASN1_UTCTIME *tm,*tmptm;
1794 ASN1_STRING *str,*str2;
1798 X509_NAME_ENTRY *ne;
1799 X509_NAME_ENTRY *tne,*push;
1801 int ok= -1,i,j,last,nid;
1804 char *row[DB_NUMBER],**rrow,**irow=NULL;
1807 tmptm=ASN1_UTCTIME_new();
1810 BIO_printf(bio_err,"malloc error\n");
1814 for (i=0; i<DB_NUMBER; i++)
1817 BIO_printf(bio_err,"The Subjects Distinguished Name is as follows\n");
1818 name=X509_REQ_get_subject_name(req);
1819 for (i=0; i<X509_NAME_entry_count(name); i++)
1821 ne=(X509_NAME_ENTRY *)X509_NAME_get_entry(name,i);
1822 obj=X509_NAME_ENTRY_get_object(ne);
1823 j=i2a_ASN1_OBJECT(bio_err,obj);
1824 str=X509_NAME_ENTRY_get_data(ne);
1826 for (j=22-j; j>0; j--)
1830 BIO_puts(bio_err,buf);
1834 /* assume all type should be strings */
1835 nid=OBJ_obj2nid(ne->object);
1837 if (str->type == V_ASN1_UNIVERSALSTRING)
1838 ASN1_UNIVERSALSTRING_to_string(str);
1840 if ((str->type == V_ASN1_IA5STRING) &&
1841 (nid != NID_pkcs9_emailAddress))
1842 str->type=V_ASN1_T61STRING;
1844 if ((nid == NID_pkcs9_emailAddress) &&
1845 (str->type == V_ASN1_PRINTABLESTRING))
1846 str->type=V_ASN1_IA5STRING;
1849 if (str->type == V_ASN1_PRINTABLESTRING)
1850 BIO_printf(bio_err,"PRINTABLE:'");
1851 else if (str->type == V_ASN1_T61STRING)
1852 BIO_printf(bio_err,"T61STRING:'");
1853 else if (str->type == V_ASN1_IA5STRING)
1854 BIO_printf(bio_err,"IA5STRING:'");
1855 else if (str->type == V_ASN1_UNIVERSALSTRING)
1856 BIO_printf(bio_err,"UNIVERSALSTRING:'");
1858 BIO_printf(bio_err,"ASN.1 %2d:'",str->type);
1860 /* check some things */
1861 if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) &&
1862 (str->type != V_ASN1_IA5STRING))
1864 BIO_printf(bio_err,"\nemailAddress type needs to be of type IA5STRING\n");
1867 j=ASN1_PRINTABLE_type(str->data,str->length);
1868 if ( ((j == V_ASN1_T61STRING) &&
1869 (str->type != V_ASN1_T61STRING)) ||
1870 ((j == V_ASN1_IA5STRING) &&
1871 (str->type == V_ASN1_PRINTABLESTRING)))
1873 BIO_printf(bio_err,"\nThe string contains characters that are illegal for the ASN.1 type\n");
1877 p=(char *)str->data;
1878 for (j=str->length; j>0; j--)
1880 if ((*p >= ' ') && (*p <= '~'))
1881 BIO_printf(bio_err,"%c",*p);
1883 BIO_printf(bio_err,"\\0x%02X",*p);
1884 else if ((unsigned char)*p == 0xf7)
1885 BIO_printf(bio_err,"^?");
1886 else BIO_printf(bio_err,"^%c",*p+'@');
1889 BIO_printf(bio_err,"'\n");
1892 /* Ok, now we check the 'policy' stuff. */
1893 if ((subject=X509_NAME_new()) == NULL)
1895 BIO_printf(bio_err,"Memory allocation failure\n");
1899 /* take a copy of the issuer name before we mess with it. */
1900 CAname=X509_NAME_dup(x509->cert_info->subject);
1901 if (CAname == NULL) goto err;
1904 for (i=0; i<sk_CONF_VALUE_num(policy); i++)
1906 cv=sk_CONF_VALUE_value(policy,i); /* get the object id */
1907 if ((j=OBJ_txt2nid(cv->name)) == NID_undef)
1909 BIO_printf(bio_err,"%s:unknown object type in 'policy' configuration\n",cv->name);
1917 /* lookup the object in the supplied name list */
1918 j=X509_NAME_get_index_by_OBJ(name,obj,last);
1921 if (last != -1) break;
1926 tne=X509_NAME_get_entry(name,j);
1930 /* depending on the 'policy', decide what to do. */
1932 if (strcmp(cv->value,"optional") == 0)
1937 else if (strcmp(cv->value,"supplied") == 0)
1941 BIO_printf(bio_err,"The %s field needed to be supplied and was missing\n",cv->name);
1947 else if (strcmp(cv->value,"match") == 0)
1953 BIO_printf(bio_err,"The mandatory %s field was missing\n",cv->name);
1960 j=X509_NAME_get_index_by_OBJ(CAname,obj,last2);
1961 if ((j < 0) && (last2 == -1))
1963 BIO_printf(bio_err,"The %s field does not exist in the CA certificate,\nthe 'policy' is misconfigured\n",cv->name);
1968 push=X509_NAME_get_entry(CAname,j);
1969 str=X509_NAME_ENTRY_get_data(tne);
1970 str2=X509_NAME_ENTRY_get_data(push);
1972 if (ASN1_STRING_cmp(str,str2) != 0)
1977 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));
1983 BIO_printf(bio_err,"%s:invalid type in 'policy' configuration\n",cv->value);
1989 if (!X509_NAME_add_entry(subject,push, -1, 0))
1992 X509_NAME_ENTRY_free(push);
1993 BIO_printf(bio_err,"Memory allocation failure\n");
2003 X509_NAME_free(subject);
2004 subject=X509_NAME_dup(X509_REQ_get_subject_name(req));
2005 if (subject == NULL) goto err;
2009 BIO_printf(bio_err,"The subject name appears to be ok, checking data base for clashes\n");
2011 row[DB_name]=X509_NAME_oneline(subject,NULL,0);
2012 row[DB_serial]=BN_bn2hex(serial);
2013 if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
2015 BIO_printf(bio_err,"Memory allocation failure\n");
2019 rrow=TXT_DB_get_by_index(db,DB_name,row);
2022 BIO_printf(bio_err,"ERROR:There is already a certificate for %s\n",
2027 rrow=TXT_DB_get_by_index(db,DB_serial,row);
2030 BIO_printf(bio_err,"ERROR:Serial number %s has already been issued,\n",
2032 BIO_printf(bio_err," check the database/serial_file for corruption\n");
2039 "The matching entry has the following details\n");
2040 if (rrow[DB_type][0] == 'E')
2042 else if (rrow[DB_type][0] == 'R')
2044 else if (rrow[DB_type][0] == 'V')
2047 p="\ninvalid type, Data base error\n";
2048 BIO_printf(bio_err,"Type :%s\n",p);;
2049 if (rrow[DB_type][0] == 'R')
2051 p=rrow[DB_exp_date]; if (p == NULL) p="undef";
2052 BIO_printf(bio_err,"Was revoked on:%s\n",p);
2054 p=rrow[DB_exp_date]; if (p == NULL) p="undef";
2055 BIO_printf(bio_err,"Expires on :%s\n",p);
2056 p=rrow[DB_serial]; if (p == NULL) p="undef";
2057 BIO_printf(bio_err,"Serial Number :%s\n",p);
2058 p=rrow[DB_file]; if (p == NULL) p="undef";
2059 BIO_printf(bio_err,"File name :%s\n",p);
2060 p=rrow[DB_name]; if (p == NULL) p="undef";
2061 BIO_printf(bio_err,"Subject Name :%s\n",p);
2062 ok= -1; /* This is now a 'bad' error. */
2066 /* We are now totally happy, lets make and sign the certificate */
2068 BIO_printf(bio_err,"Everything appears to be ok, creating and signing the certificate\n");
2070 if ((ret=X509_new()) == NULL) goto err;
2074 /* Make it an X509 v3 certificate. */
2075 if (!X509_set_version(x509,2)) goto err;
2078 if (BN_to_ASN1_INTEGER(serial,ci->serialNumber) == NULL)
2080 if (!X509_set_issuer_name(ret,X509_get_subject_name(x509)))
2083 BIO_printf(bio_err,"Certificate is to be certified until ");
2084 if (strcmp(startdate,"today") == 0)
2085 X509_gmtime_adj(X509_get_notBefore(ret),0);
2086 else ASN1_UTCTIME_set_string(X509_get_notBefore(ret),startdate);
2088 if (enddate == NULL)
2089 X509_gmtime_adj(X509_get_notAfter(ret),(long)60*60*24*days);
2090 else ASN1_UTCTIME_set_string(X509_get_notAfter(ret),enddate);
2092 ASN1_UTCTIME_print(bio_err,X509_get_notAfter(ret));
2093 if (days) BIO_printf(bio_err," (%d days)",days);
2094 BIO_printf(bio_err, "\n");
2096 if (!X509_set_subject_name(ret,subject)) goto err;
2098 pktmp=X509_REQ_get_pubkey(req);
2099 i = X509_set_pubkey(ret,pktmp);
2100 EVP_PKEY_free(pktmp);
2103 /* Lets add the extensions, if there are any */
2107 if (ci->version == NULL)
2108 if ((ci->version=ASN1_INTEGER_new()) == NULL)
2110 ASN1_INTEGER_set(ci->version,2); /* version 3 certificate */
2112 /* Free the current entries if any, there should not
2113 * be any I believe */
2114 if (ci->extensions != NULL)
2115 sk_X509_EXTENSION_pop_free(ci->extensions,
2116 X509_EXTENSION_free);
2118 ci->extensions = NULL;
2120 /* Initialize the context structure */
2121 X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0);
2126 BIO_printf(bio_err, "Extra configuration file found\n");
2128 /* Use the extconf configuration db LHASH */
2129 X509V3_set_conf_lhash(&ctx, extconf);
2131 /* Test the structure (needed?) */
2132 /* X509V3_set_ctx_test(&ctx); */
2134 /* Adds exts contained in the configuration file */
2135 if (!X509V3_EXT_add_conf(extconf, &ctx, ext_sect,ret))
2138 "ERROR: adding extensions in section %s\n",
2140 ERR_print_errors(bio_err);
2144 BIO_printf(bio_err, "Successfully added extensions from file.\n");
2148 /* We found extensions to be set from config file */
2149 X509V3_set_conf_lhash(&ctx, lconf);
2151 if(!X509V3_EXT_add_conf(lconf, &ctx, ext_sect, ret))
2153 BIO_printf(bio_err, "ERROR: adding extensions in section %s\n", ext_sect);
2154 ERR_print_errors(bio_err);
2159 BIO_printf(bio_err, "Successfully added extensions from config\n");
2166 BIO_printf(bio_err,"Sign the certificate? [y/n]:");
2167 (void)BIO_flush(bio_err);
2169 fgets(buf,sizeof(buf)-1,stdin);
2170 if (!((buf[0] == 'y') || (buf[0] == 'Y')))
2172 BIO_printf(bio_err,"CERTIFICATE WILL NOT BE CERTIFIED\n");
2180 if (pkey->type == EVP_PKEY_DSA) dgst=EVP_dss1();
2181 pktmp=X509_get_pubkey(ret);
2182 if (EVP_PKEY_missing_parameters(pktmp) &&
2183 !EVP_PKEY_missing_parameters(pkey))
2184 EVP_PKEY_copy_parameters(pktmp,pkey);
2185 EVP_PKEY_free(pktmp);
2188 if (!X509_sign(ret,pkey,dgst))
2191 /* We now just add it to the database */
2192 row[DB_type]=(char *)OPENSSL_malloc(2);
2194 tm=X509_get_notAfter(ret);
2195 row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
2196 memcpy(row[DB_exp_date],tm->data,tm->length);
2197 row[DB_exp_date][tm->length]='\0';
2199 row[DB_rev_date]=NULL;
2201 /* row[DB_serial] done already */
2202 row[DB_file]=(char *)OPENSSL_malloc(8);
2203 /* row[DB_name] done already */
2205 if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2206 (row[DB_file] == NULL))
2208 BIO_printf(bio_err,"Memory allocation failure\n");
2211 strcpy(row[DB_file],"unknown");
2212 row[DB_type][0]='V';
2213 row[DB_type][1]='\0';
2215 if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
2217 BIO_printf(bio_err,"Memory allocation failure\n");
2221 for (i=0; i<DB_NUMBER; i++)
2226 irow[DB_NUMBER]=NULL;
2228 if (!TXT_DB_insert(db,irow))
2230 BIO_printf(bio_err,"failed to update database\n");
2231 BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
2236 for (i=0; i<DB_NUMBER; i++)
2237 if (row[i] != NULL) OPENSSL_free(row[i]);
2240 X509_NAME_free(CAname);
2241 if (subject != NULL)
2242 X509_NAME_free(subject);
2244 ASN1_UTCTIME_free(tmptm);
2247 if (ret != NULL) X509_free(ret);
2255 static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext)
2260 (void)i2d_X509_bio(bp,x);
2264 /* ??? Not needed since X509_print prints all this stuff anyway */
2265 f=X509_NAME_oneline(X509_get_issuer_name(x),buf,256);
2266 BIO_printf(bp,"issuer :%s\n",f);
2268 f=X509_NAME_oneline(X509_get_subject_name(x),buf,256);
2269 BIO_printf(bp,"subject:%s\n",f);
2271 BIO_puts(bp,"serial :");
2272 i2a_ASN1_INTEGER(bp,x->cert_info->serialNumber);
2273 BIO_puts(bp,"\n\n");
2275 if (!notext)X509_print(bp,x);
2276 PEM_write_bio_X509(bp,x);
2279 static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
2280 const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
2281 BIGNUM *serial, char *startdate, char *enddate, int days,
2282 char *ext_sect, LHASH *lconf, int verbose)
2284 STACK_OF(CONF_VALUE) *sk=NULL;
2287 CONF_VALUE *cv=NULL;
2288 NETSCAPE_SPKI *spki = NULL;
2291 EVP_PKEY *pktmp=NULL;
2293 X509_NAME_ENTRY *ne=NULL;
2299 * Load input file into a hash table. (This is just an easy
2300 * way to read and parse the file, then put it into a convenient
2303 parms=CONF_load(NULL,infile,&errline);
2306 BIO_printf(bio_err,"error on line %ld of %s\n",errline,infile);
2307 ERR_print_errors(bio_err);
2311 sk=CONF_get_section(parms, "default");
2312 if (sk_CONF_VALUE_num(sk) == 0)
2314 BIO_printf(bio_err, "no name/value pairs found in %s\n", infile);
2320 * Now create a dummy X509 request structure. We don't actually
2321 * have an X509 request, but we have many of the components
2322 * (a public key, various DN components). The idea is that we
2323 * put these components into the right X509 request structure
2324 * and we can use the same code as if you had a real X509 request.
2329 ERR_print_errors(bio_err);
2334 * Build up the subject name set.
2341 if (sk_CONF_VALUE_num(sk) <= i) break;
2343 cv=sk_CONF_VALUE_value(sk,i);
2345 /* Skip past any leading X. X: X, etc to allow for
2346 * multiple instances
2348 for (buf = cv->name; *buf ; buf++)
2349 if ((*buf == ':') || (*buf == ',') || (*buf == '.'))
2352 if (*buf) type = buf;
2357 if ((nid=OBJ_txt2nid(type)) == NID_undef)
2359 if (strcmp(type, "SPKAC") == 0)
2361 spki = NETSCAPE_SPKI_b64_decode(cv->value, -1);
2364 BIO_printf(bio_err,"unable to load Netscape SPKAC structure\n");
2365 ERR_print_errors(bio_err);
2372 j=ASN1_PRINTABLE_type((unsigned char *)buf,-1);
2373 if (fix_data(nid, &j) == 0)
2376 "invalid characters in string %s\n",buf);
2380 if ((ne=X509_NAME_ENTRY_create_by_NID(&ne,nid,j,
2381 (unsigned char *)buf,
2382 strlen(buf))) == NULL)
2385 if (!X509_NAME_add_entry(n,ne,-1, 0)) goto err;
2389 BIO_printf(bio_err,"Netscape SPKAC structure not found in %s\n",
2395 * Now extract the key from the SPKI structure.
2398 BIO_printf(bio_err,"Check that the SPKAC request matches the signature\n");
2400 if ((pktmp=NETSCAPE_SPKI_get_pubkey(spki)) == NULL)
2402 BIO_printf(bio_err,"error unpacking SPKAC public key\n");
2406 j = NETSCAPE_SPKI_verify(spki, pktmp);
2409 BIO_printf(bio_err,"signature verification failed on SPKAC public key\n");
2412 BIO_printf(bio_err,"Signature ok\n");
2414 X509_REQ_set_pubkey(req,pktmp);
2415 EVP_PKEY_free(pktmp);
2416 ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,enddate,
2417 days,1,verbose,req,ext_sect,lconf);
2419 if (req != NULL) X509_REQ_free(req);
2420 if (parms != NULL) CONF_free(parms);
2421 if (spki != NULL) NETSCAPE_SPKI_free(spki);
2422 if (ne != NULL) X509_NAME_ENTRY_free(ne);
2427 static int fix_data(int nid, int *type)
2429 if (nid == NID_pkcs9_emailAddress)
2430 *type=V_ASN1_IA5STRING;
2431 if ((nid == NID_commonName) && (*type == V_ASN1_IA5STRING))
2432 *type=V_ASN1_T61STRING;
2433 if ((nid == NID_pkcs9_challengePassword) && (*type == V_ASN1_IA5STRING))
2434 *type=V_ASN1_T61STRING;
2435 if ((nid == NID_pkcs9_unstructuredName) && (*type == V_ASN1_T61STRING))
2437 if (nid == NID_pkcs9_unstructuredName)
2438 *type=V_ASN1_IA5STRING;
2442 static int check_time_format(char *str)
2446 tm.data=(unsigned char *)str;
2447 tm.length=strlen(str);
2448 tm.type=V_ASN1_UTCTIME;
2449 return(ASN1_UTCTIME_check(&tm));
2452 static int do_revoke(X509 *x509, TXT_DB *db, int type, char *value)
2454 ASN1_UTCTIME *tm=NULL;
2455 char *row[DB_NUMBER],**rrow,**irow;
2456 char *rev_str = NULL;
2460 for (i=0; i<DB_NUMBER; i++)
2462 row[DB_name]=X509_NAME_oneline(X509_get_subject_name(x509),NULL,0);
2463 bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509),NULL);
2464 row[DB_serial]=BN_bn2hex(bn);
2466 if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
2468 BIO_printf(bio_err,"Memory allocation failure\n");
2471 /* We have to lookup by serial number because name lookup
2472 * skips revoked certs
2474 rrow=TXT_DB_get_by_index(db,DB_serial,row);
2477 BIO_printf(bio_err,"Adding Entry to DB for %s\n", row[DB_name]);
2479 /* We now just add it to the database */
2480 row[DB_type]=(char *)OPENSSL_malloc(2);
2482 tm=X509_get_notAfter(x509);
2483 row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
2484 memcpy(row[DB_exp_date],tm->data,tm->length);
2485 row[DB_exp_date][tm->length]='\0';
2487 row[DB_rev_date]=NULL;
2489 /* row[DB_serial] done already */
2490 row[DB_file]=(char *)OPENSSL_malloc(8);
2492 /* row[DB_name] done already */
2494 if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2495 (row[DB_file] == NULL))
2497 BIO_printf(bio_err,"Memory allocation failure\n");
2500 strcpy(row[DB_file],"unknown");
2501 row[DB_type][0]='V';
2502 row[DB_type][1]='\0';
2504 if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
2506 BIO_printf(bio_err,"Memory allocation failure\n");
2510 for (i=0; i<DB_NUMBER; i++)
2515 irow[DB_NUMBER]=NULL;
2517 if (!TXT_DB_insert(db,irow))
2519 BIO_printf(bio_err,"failed to update database\n");
2520 BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
2524 /* Revoke Certificate */
2525 ok = do_revoke(x509,db, type, value);
2530 else if (index_name_cmp((const char **)row,(const char **)rrow))
2532 BIO_printf(bio_err,"ERROR:name does not match %s\n",
2536 else if (rrow[DB_type][0]=='R')
2538 BIO_printf(bio_err,"ERROR:Already revoked, serial number %s\n",
2544 BIO_printf(bio_err,"Revoking Certificate %s.\n", rrow[DB_serial]);
2545 rev_str = make_revocation_str(type, value);
2548 BIO_printf(bio_err, "Error in revocation arguments\n");
2551 rrow[DB_type][0]='R';
2552 rrow[DB_type][1]='\0';
2553 rrow[DB_rev_date] = rev_str;
2557 for (i=0; i<DB_NUMBER; i++)
2560 OPENSSL_free(row[i]);
2565 static int get_certificate_status(const char *serial, TXT_DB *db)
2567 char *row[DB_NUMBER],**rrow;
2570 /* Free Resources */
2571 for (i=0; i<DB_NUMBER; i++)
2574 /* Malloc needed char spaces */
2575 row[DB_serial] = OPENSSL_malloc(strlen(serial) + 2);
2576 if (row[DB_serial] == NULL)
2578 BIO_printf(bio_err,"Malloc failure\n");
2582 if (strlen(serial) % 2)
2584 /* Set the first char to 0 */;
2585 row[DB_serial][0]='0';
2587 /* Copy String from serial to row[DB_serial] */
2588 memcpy(row[DB_serial]+1, serial, strlen(serial));
2589 row[DB_serial][strlen(serial)+1]='\0';
2593 /* Copy String from serial to row[DB_serial] */
2594 memcpy(row[DB_serial], serial, strlen(serial));
2595 row[DB_serial][strlen(serial)]='\0';
2598 /* Make it Upper Case */
2599 for (i=0; row[DB_serial][i] != '\0'; i++)
2600 row[DB_serial][i] = toupper(row[DB_serial][i]);
2605 /* Search for the certificate */
2606 rrow=TXT_DB_get_by_index(db,DB_serial,row);
2609 BIO_printf(bio_err,"Serial %s not present in db.\n",
2614 else if (rrow[DB_type][0]=='V')
2616 BIO_printf(bio_err,"%s=Valid (%c)\n",
2617 row[DB_serial], rrow[DB_type][0]);
2620 else if (rrow[DB_type][0]=='R')
2622 BIO_printf(bio_err,"%s=Revoked (%c)\n",
2623 row[DB_serial], rrow[DB_type][0]);
2626 else if (rrow[DB_type][0]=='E')
2628 BIO_printf(bio_err,"%s=Expired (%c)\n",
2629 row[DB_serial], rrow[DB_type][0]);
2632 else if (rrow[DB_type][0]=='S')
2634 BIO_printf(bio_err,"%s=Suspended (%c)\n",
2635 row[DB_serial], rrow[DB_type][0]);
2640 BIO_printf(bio_err,"%s=Unknown (%c).\n",
2641 row[DB_serial], rrow[DB_type][0]);
2645 for (i=0; i<DB_NUMBER; i++)
2648 OPENSSL_free(row[i]);
2653 static int do_updatedb (TXT_DB *db)
2655 ASN1_UTCTIME *a_tm = NULL;
2657 int db_y2k, a_y2k; /* flags = 1 if y >= 2000 */
2658 char **rrow, *a_tm_s;
2660 a_tm = ASN1_UTCTIME_new();
2662 /* get actual time and make a string */
2663 a_tm = X509_gmtime_adj(a_tm, 0);
2664 a_tm_s = (char *) OPENSSL_malloc(a_tm->length+1);
2671 memcpy(a_tm_s, a_tm->data, a_tm->length);
2672 a_tm_s[a_tm->length] = '\0';
2674 if (strncmp(a_tm_s, "49", 2) <= 0)
2679 for (i = 0; i < sk_num(db->data); i++)
2681 rrow = (char **) sk_value(db->data, i);
2683 if (rrow[DB_type][0] == 'V')
2685 /* ignore entries that are not valid */
2686 if (strncmp(rrow[DB_exp_date], "49", 2) <= 0)
2691 if (db_y2k == a_y2k)
2693 /* all on the same y2k side */
2694 if (strcmp(rrow[DB_exp_date], a_tm_s) <= 0)
2696 rrow[DB_type][0] = 'E';
2697 rrow[DB_type][1] = '\0';
2700 BIO_printf(bio_err, "%s=Expired\n",
2704 else if (db_y2k < a_y2k)
2706 rrow[DB_type][0] = 'E';
2707 rrow[DB_type][1] = '\0';
2710 BIO_printf(bio_err, "%s=Expired\n",
2719 ASN1_UTCTIME_free(a_tm);
2720 OPENSSL_free(a_tm_s);
2725 static char *crl_reasons[] = {
2726 /* CRL reason strings */
2730 "affiliationChanged",
2732 "cessationOfOperation",
2735 /* Additional pseudo reasons */
2741 #define NUM_REASONS (sizeof(crl_reasons) / sizeof(char *))
2743 /* Given revocation information convert to a DB string.
2744 * The format of the string is:
2745 * revtime[,reason,extra]. Where 'revtime' is the
2746 * revocation time (the current time). 'reason' is the
2747 * optional CRL reason and 'extra' is any additional
2751 char *make_revocation_str(int rev_type, char *rev_arg)
2753 char *reason = NULL, *other = NULL, *str;
2755 ASN1_UTCTIME *revtm = NULL;
2762 case REV_CRL_REASON:
2763 for (i = 0; i < 8; i++)
2765 if (!strcasecmp(rev_arg, crl_reasons[i]))
2767 reason = crl_reasons[i];
2773 BIO_printf(bio_err, "Unknown CRL reason %s\n", rev_arg);
2779 /* Argument is an OID */
2781 otmp = OBJ_txt2obj(rev_arg, 0);
2782 ASN1_OBJECT_free(otmp);
2786 BIO_printf(bio_err, "Invalid object identifier %s\n", rev_arg);
2790 reason = "holdInstruction";
2794 case REV_KEY_COMPROMISE:
2795 case REV_CA_COMPROMISE:
2797 /* Argument is the key compromise time */
2798 if (!ASN1_GENERALIZEDTIME_set_string(NULL, rev_arg))
2800 BIO_printf(bio_err, "Invalid time format %s. Need YYYYMMDDHHMMSSZ\n", rev_arg);
2804 if (rev_type == REV_KEY_COMPROMISE)
2807 reason = "CAkeyTime";
2813 revtm = X509_gmtime_adj(NULL, 0);
2815 i = revtm->length + 1;
2817 if (reason) i += strlen(reason) + 1;
2818 if (other) i += strlen(other) + 1;
2820 str = OPENSSL_malloc(i);
2822 if (!str) return NULL;
2824 strcpy(str, (char *)revtm->data);
2828 strcat(str, reason);
2835 ASN1_UTCTIME_free(revtm);
2839 /* Convert revocation field to X509_REVOKED entry
2843 * 2 OK and some extensions added (i.e. V2 CRL)
2846 int make_revoked(X509_REVOKED *rev, char *str)
2849 char *rtime_str, *reason_str = NULL, *arg_str = NULL, *p;
2850 int reason_code = -1;
2852 ASN1_OBJECT *hold = NULL;
2853 ASN1_GENERALIZEDTIME *comp_time = NULL;
2854 ASN1_ENUMERATED *rtmp = NULL;
2855 tmp = BUF_strdup(str);
2857 p = strchr(tmp, ',');
2874 if (rev && !ASN1_UTCTIME_set_string(rev->revocationDate, rtime_str))
2876 BIO_printf(bio_err, "invalid revocation date %s\n", rtime_str);
2881 for (i = 0; i < NUM_REASONS; i++)
2883 if(!strcasecmp(reason_str, crl_reasons[i]))
2889 if (reason_code == OCSP_REVOKED_STATUS_NOSTATUS)
2891 BIO_printf(bio_err, "invalid reason code %s\n", reason_str);
2895 if (reason_code == 7)
2896 reason_code = OCSP_REVOKED_STATUS_REMOVEFROMCRL;
2897 else if (reason_code == 8) /* Hold instruction */
2901 BIO_printf(bio_err, "missing hold instruction\n");
2904 reason_code = OCSP_REVOKED_STATUS_CERTIFICATEHOLD;
2905 hold = OBJ_txt2obj(arg_str, 0);
2909 BIO_printf(bio_err, "invalid object identifier %s\n", arg_str);
2913 else if ((reason_code == 9) || (reason_code == 10))
2917 BIO_printf(bio_err, "missing compromised time\n");
2920 comp_time = ASN1_GENERALIZEDTIME_new();
2921 if (!ASN1_GENERALIZEDTIME_set_string(comp_time, arg_str))
2923 BIO_printf(bio_err, "invalid compromised time %s\n", arg_str);
2926 if (reason_code == 9)
2927 reason_code = OCSP_REVOKED_STATUS_KEYCOMPROMISE;
2929 reason_code = OCSP_REVOKED_STATUS_CACOMPROMISE;
2933 if (rev && (reason_code != OCSP_REVOKED_STATUS_NOSTATUS))
2935 rtmp = ASN1_ENUMERATED_new();
2936 if (!rtmp || !ASN1_ENUMERATED_set(rtmp, reason_code))
2938 if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0))
2942 if (rev && comp_time)
2944 if (!X509_REVOKED_add1_ext_i2d(rev, NID_invalidity_date, comp_time, 0, 0))
2949 if (!X509_REVOKED_add1_ext_i2d(rev, NID_hold_instruction_code, hold, 0, 0))
2953 if (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)
2959 if (tmp) OPENSSL_free(tmp);
2960 ASN1_OBJECT_free(hold);
2961 ASN1_GENERALIZEDTIME_free(comp_time);
2962 ASN1_ENUMERATED_free(rtmp);