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;
302 MS_STATIC char buf[3][BSIZE];
321 if ((bio_err=BIO_new(BIO_s_file())) != NULL)
322 BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
328 if (strcmp(*argv,"-verbose") == 0)
330 else if (strcmp(*argv,"-config") == 0)
332 if (--argc < 1) goto bad;
333 configfile= *(++argv);
335 else if (strcmp(*argv,"-name") == 0)
337 if (--argc < 1) goto bad;
340 else if (strcmp(*argv,"-startdate") == 0)
342 if (--argc < 1) goto bad;
343 startdate= *(++argv);
345 else if (strcmp(*argv,"-enddate") == 0)
347 if (--argc < 1) goto bad;
350 else if (strcmp(*argv,"-days") == 0)
352 if (--argc < 1) goto bad;
353 days=atoi(*(++argv));
355 else if (strcmp(*argv,"-md") == 0)
357 if (--argc < 1) goto bad;
360 else if (strcmp(*argv,"-policy") == 0)
362 if (--argc < 1) goto bad;
365 else if (strcmp(*argv,"-keyfile") == 0)
367 if (--argc < 1) goto bad;
370 else if (strcmp(*argv,"-keyform") == 0)
372 if (--argc < 1) goto bad;
373 keyform=str2fmt(*(++argv));
375 else if (strcmp(*argv,"-passin") == 0)
377 if (--argc < 1) goto bad;
378 passargin= *(++argv);
380 else if (strcmp(*argv,"-key") == 0)
382 if (--argc < 1) goto bad;
385 else if (strcmp(*argv,"-cert") == 0)
387 if (--argc < 1) goto bad;
390 else if (strcmp(*argv,"-in") == 0)
392 if (--argc < 1) goto bad;
396 else if (strcmp(*argv,"-out") == 0)
398 if (--argc < 1) goto bad;
401 else if (strcmp(*argv,"-outdir") == 0)
403 if (--argc < 1) goto bad;
406 else if (strcmp(*argv,"-notext") == 0)
408 else if (strcmp(*argv,"-batch") == 0)
410 else if (strcmp(*argv,"-preserveDN") == 0)
412 else if (strcmp(*argv,"-gencrl") == 0)
414 else if (strcmp(*argv,"-msie_hack") == 0)
416 else if (strcmp(*argv,"-crldays") == 0)
418 if (--argc < 1) goto bad;
419 crldays= atol(*(++argv));
421 else if (strcmp(*argv,"-crlhours") == 0)
423 if (--argc < 1) goto bad;
424 crlhours= atol(*(++argv));
426 else if (strcmp(*argv,"-infiles") == 0)
433 else if (strcmp(*argv, "-ss_cert") == 0)
435 if (--argc < 1) goto bad;
436 ss_cert_file = *(++argv);
439 else if (strcmp(*argv, "-spkac") == 0)
441 if (--argc < 1) goto bad;
442 spkac_file = *(++argv);
445 else if (strcmp(*argv,"-revoke") == 0)
447 if (--argc < 1) goto bad;
451 else if (strcmp(*argv,"-extensions") == 0)
453 if (--argc < 1) goto bad;
454 extensions= *(++argv);
456 else if (strcmp(*argv,"-extfile") == 0)
458 if (--argc < 1) goto bad;
461 else if (strcmp(*argv,"-status") == 0)
463 if (--argc < 1) goto bad;
464 ser_status= *(++argv);
466 else if (strcmp(*argv,"-updatedb") == 0)
470 else if (strcmp(*argv,"-crlexts") == 0)
472 if (--argc < 1) goto bad;
475 else if (strcmp(*argv,"-crl_reason") == 0)
477 if (--argc < 1) goto bad;
479 rev_type = REV_CRL_REASON;
481 else if (strcmp(*argv,"-crl_hold") == 0)
483 if (--argc < 1) goto bad;
487 else if (strcmp(*argv,"-crl_compromise") == 0)
489 if (--argc < 1) goto bad;
491 rev_type = REV_KEY_COMPROMISE;
493 else if (strcmp(*argv,"-crl_CA_compromise") == 0)
495 if (--argc < 1) goto bad;
497 rev_type = REV_CA_COMPROMISE;
499 else if (strcmp(*argv,"-engine") == 0)
501 if (--argc < 1) goto bad;
507 BIO_printf(bio_err,"unknown option %s\n",*argv);
517 for (pp=ca_usage; (*pp != NULL); pp++)
518 BIO_printf(bio_err,"%s",*pp);
522 ERR_load_crypto_strings();
526 if ((e = ENGINE_by_id(engine)) == NULL)
528 BIO_printf(bio_err,"invalid engine \"%s\"\n",
532 if (!ENGINE_set_default(e, ENGINE_METHOD_ALL))
534 BIO_printf(bio_err,"can't use that engine\n");
537 BIO_printf(bio_err,"engine \"%s\" set.\n", engine);
538 /* Free our "structural" reference. */
542 /*****************************************************************/
543 if (configfile == NULL) configfile = getenv("OPENSSL_CONF");
544 if (configfile == NULL) configfile = getenv("SSLEAY_CONF");
545 if (configfile == NULL)
547 /* We will just use 'buf[0]' as a temporary buffer. */
549 strncpy(buf[0],X509_get_default_cert_area(),
550 sizeof(buf[0])-1-sizeof(CONFIG_FILE));
552 strncpy(buf[0],X509_get_default_cert_area(),
553 sizeof(buf[0])-2-sizeof(CONFIG_FILE));
556 strcat(buf[0],CONFIG_FILE);
560 BIO_printf(bio_err,"Using configuration from %s\n",configfile);
561 if ((conf=CONF_load(NULL,configfile,&errorline)) == NULL)
564 BIO_printf(bio_err,"error loading the config file '%s'\n",
567 BIO_printf(bio_err,"error on line %ld of config file '%s'\n"
568 ,errorline,configfile);
572 /* Lets get the config section we are using */
575 section=CONF_get_string(conf,BASE_SECTION,ENV_DEFAULT_CA);
578 lookup_fail(BASE_SECTION,ENV_DEFAULT_CA);
585 p=CONF_get_string(conf,NULL,"oid_file");
592 oid_bio=BIO_new_file(p,"r");
596 BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
597 ERR_print_errors(bio_err);
603 OBJ_create_objects(oid_bio);
607 if (!add_oid_section(bio_err,conf))
609 ERR_print_errors(bio_err);
614 randfile = CONF_get_string(conf, BASE_SECTION, "RANDFILE");
615 if (randfile == NULL)
617 app_RAND_load_file(randfile, bio_err, 0);
619 in=BIO_new(BIO_s_file());
620 out=BIO_new(BIO_s_file());
621 Sout=BIO_new(BIO_s_file());
622 Cout=BIO_new(BIO_s_file());
623 if ((in == NULL) || (out == NULL) || (Sout == NULL) || (Cout == NULL))
625 ERR_print_errors(bio_err);
629 /*****************************************************************/
630 /* report status of cert with serial number given on command line */
633 if ((dbfile=CONF_get_string(conf,section,ENV_DATABASE)) == NULL)
635 lookup_fail(section,ENV_DATABASE);
638 if (BIO_read_filename(in,dbfile) <= 0)
641 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
644 db=TXT_DB_read(in,DB_NUMBER);
645 if (db == NULL) goto err;
647 if (!TXT_DB_create_index(db, DB_serial, NULL,
648 LHASH_HASH_FN(index_serial_hash),
649 LHASH_COMP_FN(index_serial_cmp)))
652 "error creating serial number index:(%ld,%ld,%ld)\n",
653 db->error,db->arg1,db->arg2);
657 if (get_certificate_status(ser_status,db) != 1)
658 BIO_printf(bio_err,"Error verifying serial %s!\n",
663 /*****************************************************************/
664 /* we definitely need a public key, so let's get it */
666 if ((keyfile == NULL) && ((keyfile=CONF_get_string(conf,
667 section,ENV_PRIVATE_KEY)) == NULL))
669 lookup_fail(section,ENV_PRIVATE_KEY);
672 if (!key && !app_passwd(bio_err, passargin, NULL, &key, NULL))
674 BIO_printf(bio_err,"Error getting password\n");
677 if (keyform == FORMAT_ENGINE)
681 BIO_printf(bio_err,"no engine specified\n");
684 pkey = ENGINE_load_private_key(e, keyfile, key);
686 else if (keyform == FORMAT_PEM)
688 if (BIO_read_filename(in,keyfile) <= 0)
691 BIO_printf(bio_err,"trying to load CA private key\n");
694 pkey=PEM_read_bio_PrivateKey(in,NULL,NULL,key);
698 BIO_printf(bio_err,"bad input format specified for key file\n");
701 if (key) memset(key,0,strlen(key));
704 BIO_printf(bio_err,"unable to load CA private key\n");
708 /*****************************************************************/
709 /* we need a certificate */
710 if ((certfile == NULL) && ((certfile=CONF_get_string(conf,
711 section,ENV_CERTIFICATE)) == NULL))
713 lookup_fail(section,ENV_CERTIFICATE);
716 if (BIO_read_filename(in,certfile) <= 0)
719 BIO_printf(bio_err,"trying to load CA certificate\n");
722 x509=PEM_read_bio_X509(in,NULL,NULL,NULL);
725 BIO_printf(bio_err,"unable to load CA certificate\n");
729 if (!X509_check_private_key(x509,pkey))
731 BIO_printf(bio_err,"CA certificate and CA private key do not match\n");
735 f=CONF_get_string(conf,BASE_SECTION,ENV_PRESERVE);
738 if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
740 f=CONF_get_string(conf,BASE_SECTION,ENV_MSIE_HACK);
743 if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
746 /*****************************************************************/
747 /* lookup where to write new certificates */
748 if ((outdir == NULL) && (req))
752 if ((outdir=CONF_get_string(conf,section,ENV_NEW_CERTS_DIR))
755 BIO_printf(bio_err,"there needs to be defined a directory for new certificate to be placed in\n");
758 #ifndef VMS /* outdir is a directory spec, but access() for VMS demands a
759 filename. In any case, stat(), below, will catch the problem
760 if outdir is not a directory spec, and the fopen() or open()
761 will catch an error if there is no write access.
763 Presumably, this problem could also be solved by using the DEC
764 C routines to convert the directory syntax to Unixly, and give
765 that to access(). However, time's too short to do that just
768 if (access(outdir,R_OK|W_OK|X_OK) != 0)
770 BIO_printf(bio_err,"I am unable to access the %s directory\n",outdir);
775 if (stat(outdir,&sb) != 0)
777 BIO_printf(bio_err,"unable to stat(%s)\n",outdir);
782 if (!(sb.st_mode & S_IFDIR))
784 BIO_printf(bio_err,"%s need to be a directory\n",outdir);
792 /*****************************************************************/
793 /* we need to load the database file */
794 if ((dbfile=CONF_get_string(conf,section,ENV_DATABASE)) == NULL)
796 lookup_fail(section,ENV_DATABASE);
799 if (BIO_read_filename(in,dbfile) <= 0)
802 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
805 db=TXT_DB_read(in,DB_NUMBER);
806 if (db == NULL) goto err;
808 /* Lets check some fields */
809 for (i=0; i<sk_num(db->data); i++)
811 pp=(char **)sk_value(db->data,i);
812 if ((pp[DB_type][0] != DB_TYPE_REV) &&
813 (pp[DB_rev_date][0] != '\0'))
815 BIO_printf(bio_err,"entry %d: not revoked yet, but has a revocation date\n",i+1);
818 if ((pp[DB_type][0] == DB_TYPE_REV) &&
819 !make_revoked(NULL, pp[DB_rev_date]))
821 BIO_printf(bio_err," in entry %d\n", i+1);
824 if (!check_time_format(pp[DB_exp_date]))
826 BIO_printf(bio_err,"entry %d: invalid expiry date\n",i+1);
836 if ((j&1) || (j < 2))
838 BIO_printf(bio_err,"entry %d: bad serial number length (%d)\n",i+1,j);
843 if (!( ((*p >= '0') && (*p <= '9')) ||
844 ((*p >= 'A') && (*p <= 'F')) ||
845 ((*p >= 'a') && (*p <= 'f'))) )
847 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);
855 BIO_set_fp(out,stdout,BIO_NOCLOSE|BIO_FP_TEXT); /* cannot fail */
858 BIO *tmpbio = BIO_new(BIO_f_linebuffer());
859 out = BIO_push(tmpbio, out);
862 TXT_DB_write(out,db);
863 BIO_printf(bio_err,"%d entries loaded from the database\n",
865 BIO_printf(bio_err,"generating index\n");
868 if (!TXT_DB_create_index(db, DB_serial, NULL,
869 LHASH_HASH_FN(index_serial_hash),
870 LHASH_COMP_FN(index_serial_cmp)))
872 BIO_printf(bio_err,"error creating serial number index:(%ld,%ld,%ld)\n",db->error,db->arg1,db->arg2);
876 if (!TXT_DB_create_index(db, DB_name, index_name_qual,
877 LHASH_HASH_FN(index_name_hash),
878 LHASH_COMP_FN(index_name_cmp)))
880 BIO_printf(bio_err,"error creating name index:(%ld,%ld,%ld)\n",
881 db->error,db->arg1,db->arg2);
885 /*****************************************************************/
886 /* Update the db file for expired certificates */
890 BIO_printf(bio_err, "Updating %s ...\n",
896 BIO_printf(bio_err,"Malloc failure\n");
901 if (verbose) BIO_printf(bio_err,
902 "No entries found to mark expired\n");
906 out = BIO_new(BIO_s_file());
909 ERR_print_errors(bio_err);
913 j = BIO_snprintf(buf[0], sizeof buf[0], "%s.new", dbfile);
914 if (j < 0 || j >= sizeof buf[0])
916 BIO_printf(bio_err, "file name too long\n");
919 if (BIO_write_filename(out,buf[0]) <= 0)
922 BIO_printf(bio_err,"unable to open '%s'\n",
926 j=TXT_DB_write(out,db);
927 if (j <= 0) goto err;
931 j = BIO_snprintf(buf[1], sizeof buf[1], "%s.old", dbfile);
932 if (j < 0 || j >= sizeof buf[1])
934 BIO_printf(bio_err, "file name too long\n");
937 if (rename(dbfile,buf[1]) < 0)
940 "unable to rename %s to %s\n",
945 if (rename(buf[0],dbfile) < 0)
948 "unable to rename %s to %s\n",
951 rename(buf[1],dbfile);
955 if (verbose) BIO_printf(bio_err,
956 "Done. %d entries marked as expired\n",i);
961 /*****************************************************************/
962 /* Read extentions config file */
965 if (!(extconf=CONF_load(NULL,extfile,&errorline)))
968 BIO_printf(bio_err, "ERROR: loading the config file '%s'\n",
971 BIO_printf(bio_err, "ERROR: on line %ld of config file '%s'\n",
978 BIO_printf(bio_err, "Succesfully loaded extensions file %s\n", extfile);
980 /* We can have sections in the ext file */
981 if (!extensions && !(extensions = CONF_get_string(extconf, "default", "extensions")))
982 extensions = "default";
985 /*****************************************************************/
990 if (BIO_write_filename(Sout,outfile) <= 0)
998 BIO_set_fp(Sout,stdout,BIO_NOCLOSE|BIO_FP_TEXT);
1001 BIO *tmpbio = BIO_new(BIO_f_linebuffer());
1002 Sout = BIO_push(tmpbio, Sout);
1010 if ((md == NULL) && ((md=CONF_get_string(conf,
1011 section,ENV_DEFAULT_MD)) == NULL))
1013 lookup_fail(section,ENV_DEFAULT_MD);
1016 if ((dgst=EVP_get_digestbyname(md)) == NULL)
1018 BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
1022 BIO_printf(bio_err,"message digest is %s\n",
1023 OBJ_nid2ln(dgst->type));
1024 if ((policy == NULL) && ((policy=CONF_get_string(conf,
1025 section,ENV_POLICY)) == NULL))
1027 lookup_fail(section,ENV_POLICY);
1031 BIO_printf(bio_err,"policy is %s\n",policy);
1033 if ((serialfile=CONF_get_string(conf,section,ENV_SERIAL))
1036 lookup_fail(section,ENV_SERIAL);
1042 /* no '-extfile' option, so we look for extensions
1043 * in the main configuration file */
1046 extensions=CONF_get_string(conf,section,
1053 /* Check syntax of file */
1055 X509V3_set_ctx_test(&ctx);
1056 X509V3_set_conf_lhash(&ctx, conf);
1057 if (!X509V3_EXT_add_conf(conf, &ctx, extensions,
1061 "Error Loading extension section %s\n",
1069 if (startdate == NULL)
1071 startdate=CONF_get_string(conf,section,
1072 ENV_DEFAULT_STARTDATE);
1073 if (startdate == NULL)
1076 if (startdate && !ASN1_UTCTIME_set_string(NULL,startdate))
1078 BIO_printf(bio_err,"start date is invalid, it should be YYMMDDHHMMSSZ\n");
1081 if (startdate == NULL) startdate="today";
1083 if (enddate == NULL)
1085 enddate=CONF_get_string(conf,section,
1086 ENV_DEFAULT_ENDDATE);
1087 if (enddate == NULL)
1090 if (enddate && !ASN1_UTCTIME_set_string(NULL,enddate))
1092 BIO_printf(bio_err,"end date is invalid, it should be YYMMDDHHMMSSZ\n");
1098 days=(int)CONF_get_number(conf,section,
1101 if (!enddate && (days == 0))
1103 BIO_printf(bio_err,"cannot lookup how many days to certify for\n");
1107 if ((serial=load_serial(serialfile)) == NULL)
1109 BIO_printf(bio_err,"error while loading serial number\n");
1114 if ((f=BN_bn2hex(serial)) == NULL) goto err;
1115 BIO_printf(bio_err,"next serial number is %s\n",f);
1119 if ((attribs=CONF_get_section(conf,policy)) == NULL)
1121 BIO_printf(bio_err,"unable to find 'section' for %s\n",policy);
1125 if ((cert_sk=sk_X509_new_null()) == NULL)
1127 BIO_printf(bio_err,"Memory allocation failure\n");
1130 if (spkac_file != NULL)
1133 j=certify_spkac(&x,spkac_file,pkey,x509,dgst,attribs,db,
1134 serial,startdate,enddate, days,extensions,conf,
1136 if (j < 0) goto err;
1140 BIO_printf(bio_err,"\n");
1141 if (!BN_add_word(serial,1)) goto err;
1142 if (!sk_X509_push(cert_sk,x))
1144 BIO_printf(bio_err,"Memory allocation failure\n");
1154 if (ss_cert_file != NULL)
1157 j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,attribs,
1158 db,serial,startdate,enddate,days,batch,
1159 extensions,conf,verbose);
1160 if (j < 0) goto err;
1164 BIO_printf(bio_err,"\n");
1165 if (!BN_add_word(serial,1)) goto err;
1166 if (!sk_X509_push(cert_sk,x))
1168 BIO_printf(bio_err,"Memory allocation failure\n");
1176 j=certify(&x,infile,pkey,x509,dgst,attribs,db,
1177 serial,startdate,enddate,days,batch,
1178 extensions,conf,verbose);
1179 if (j < 0) goto err;
1183 BIO_printf(bio_err,"\n");
1184 if (!BN_add_word(serial,1)) goto err;
1185 if (!sk_X509_push(cert_sk,x))
1187 BIO_printf(bio_err,"Memory allocation failure\n");
1192 for (i=0; i<argc; i++)
1195 j=certify(&x,argv[i],pkey,x509,dgst,attribs,db,
1196 serial,startdate,enddate,days,batch,
1197 extensions,conf,verbose);
1198 if (j < 0) goto err;
1202 BIO_printf(bio_err,"\n");
1203 if (!BN_add_word(serial,1)) goto err;
1204 if (!sk_X509_push(cert_sk,x))
1206 BIO_printf(bio_err,"Memory allocation failure\n");
1211 /* we have a stack of newly certified certificates
1212 * and a data base and serial number that need
1215 if (sk_X509_num(cert_sk) > 0)
1219 BIO_printf(bio_err,"\n%d out of %d certificate requests certified, commit? [y/n]",total_done,total);
1220 (void)BIO_flush(bio_err);
1222 fgets(buf[0],10,stdin);
1223 if ((buf[0][0] != 'y') && (buf[0][0] != 'Y'))
1225 BIO_printf(bio_err,"CERTIFICATION CANCELED\n");
1231 BIO_printf(bio_err,"Write out database with %d new entries\n",sk_X509_num(cert_sk));
1233 strncpy(buf[0],serialfile,BSIZE-4);
1236 strcat(buf[0],"-new");
1238 strcat(buf[0],".new");
1241 if (!save_serial(buf[0],serial)) goto err;
1243 strncpy(buf[1],dbfile,BSIZE-4);
1246 strcat(buf[1],"-new");
1248 strcat(buf[1],".new");
1251 if (BIO_write_filename(out,buf[1]) <= 0)
1254 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
1257 l=TXT_DB_write(out,db);
1258 if (l <= 0) goto err;
1262 BIO_printf(bio_err,"writing new certificates\n");
1263 for (i=0; i<sk_X509_num(cert_sk); i++)
1268 x=sk_X509_value(cert_sk,i);
1270 j=x->cert_info->serialNumber->length;
1271 p=(char *)x->cert_info->serialNumber->data;
1273 strncpy(buf[2],outdir,BSIZE-(j*2)-6);
1279 n=(unsigned char *)&(buf[2][strlen(buf[2])]);
1284 sprintf((char *)n,"%02X",(unsigned char)*(p++));
1293 *(n++)='.'; *(n++)='p'; *(n++)='e'; *(n++)='m';
1296 BIO_printf(bio_err,"writing %s\n",buf[2]);
1298 if (BIO_write_filename(Cout,buf[2]) <= 0)
1303 write_new_certificate(Cout,x, 0, notext);
1304 write_new_certificate(Sout,x, output_der, notext);
1307 if (sk_X509_num(cert_sk))
1309 /* Rename the database and the serial file */
1310 strncpy(buf[2],serialfile,BSIZE-4);
1313 strcat(buf[2],"-old");
1315 strcat(buf[2],".old");
1322 if (rename(serialfile,buf[2]) < 0)
1324 BIO_printf(bio_err,"unable to rename %s to %s\n",
1329 if (rename(buf[0],serialfile) < 0)
1331 BIO_printf(bio_err,"unable to rename %s to %s\n",
1334 rename(buf[2],serialfile);
1338 strncpy(buf[2],dbfile,BSIZE-4);
1341 strcat(buf[2],"-old");
1343 strcat(buf[2],".old");
1346 if (rename(dbfile,buf[2]) < 0)
1348 BIO_printf(bio_err,"unable to rename %s to %s\n",
1353 if (rename(buf[1],dbfile) < 0)
1355 BIO_printf(bio_err,"unable to rename %s to %s\n",
1358 rename(buf[2],dbfile);
1361 BIO_printf(bio_err,"Data Base Updated\n");
1365 /*****************************************************************/
1371 crl_ext=CONF_get_string(conf,section,ENV_CRLEXT);
1377 /* Check syntax of file */
1379 X509V3_set_ctx_test(&ctx);
1380 X509V3_set_conf_lhash(&ctx, conf);
1381 if (!X509V3_EXT_add_conf(conf, &ctx, crl_ext, NULL))
1384 "Error Loading CRL extension section %s\n",
1391 if (!crldays && !crlhours)
1393 crldays=CONF_get_number(conf,section,
1394 ENV_DEFAULT_CRL_DAYS);
1395 crlhours=CONF_get_number(conf,section,
1396 ENV_DEFAULT_CRL_HOURS);
1398 if ((crldays == 0) && (crlhours == 0))
1400 BIO_printf(bio_err,"cannot lookup how long until the next CRL is issuer\n");
1404 if (verbose) BIO_printf(bio_err,"making CRL\n");
1405 if ((crl=X509_CRL_new()) == NULL) goto err;
1407 X509_NAME_free(ci->issuer);
1408 ci->issuer=X509_NAME_dup(x509->cert_info->subject);
1409 if (ci->issuer == NULL) goto err;
1411 X509_gmtime_adj(ci->lastUpdate,0);
1412 if (ci->nextUpdate == NULL)
1413 ci->nextUpdate=ASN1_UTCTIME_new();
1414 X509_gmtime_adj(ci->nextUpdate,(crldays*24+crlhours)*60*60);
1416 for (i=0; i<sk_num(db->data); i++)
1418 pp=(char **)sk_value(db->data,i);
1419 if (pp[DB_type][0] == DB_TYPE_REV)
1421 if ((r=X509_REVOKED_new()) == NULL) goto err;
1422 j = make_revoked(r, pp[DB_rev_date]);
1424 if (j == 2) crl_v2 = 1;
1425 if (!BN_hex2bn(&serial, pp[DB_serial]))
1427 r->serialNumber = BN_to_ASN1_INTEGER(serial, r->serialNumber);
1430 if (!r->serialNumber)
1432 X509_CRL_add0_revoked(crl,r);
1435 /* sort the data so it will be written in serial
1437 sk_X509_REVOKED_sort(ci->revoked);
1438 for (i=0; i<sk_X509_REVOKED_num(ci->revoked); i++)
1440 r=sk_X509_REVOKED_value(ci->revoked,i);
1444 /* we now have a CRL */
1445 if (verbose) BIO_printf(bio_err,"signing CRL\n");
1448 if ((dgst=EVP_get_digestbyname(md)) == NULL)
1450 BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
1456 #ifndef OPENSSL_NO_DSA
1457 if (pkey->type == EVP_PKEY_DSA)
1464 /* Add any extensions asked for */
1469 if (ci->version == NULL)
1470 if ((ci->version=ASN1_INTEGER_new()) == NULL) goto err;
1471 X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0);
1472 X509V3_set_conf_lhash(&crlctx, conf);
1474 if (!X509V3_EXT_CRL_add_conf(conf, &crlctx,
1475 crl_ext, crl)) goto err;
1477 if (crl_ext || crl_v2)
1479 if (ci->version == NULL)
1480 if ((ci->version=ASN1_INTEGER_new()) == NULL) goto err;
1481 ASN1_INTEGER_set(ci->version,1); /* version 2 CRL */
1484 if (!X509_CRL_sign(crl,pkey,dgst)) goto err;
1486 PEM_write_bio_X509_CRL(Sout,crl);
1488 /*****************************************************************/
1493 BIO_printf(bio_err,"no input files\n");
1499 if (BIO_read_filename(in,infile) <= 0)
1502 BIO_printf(bio_err,"error trying to load '%s' certificate\n",infile);
1505 revcert=PEM_read_bio_X509(in,NULL,NULL,NULL);
1506 if (revcert == NULL)
1508 BIO_printf(bio_err,"unable to load '%s' certificate\n",infile);
1511 j=do_revoke(revcert,db, rev_type, rev_arg);
1512 if (j <= 0) goto err;
1515 strncpy(buf[0],dbfile,BSIZE-4);
1516 strcat(buf[0],".new");
1517 if (BIO_write_filename(out,buf[0]) <= 0)
1520 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
1523 j=TXT_DB_write(out,db);
1524 if (j <= 0) goto err;
1525 strncpy(buf[1],dbfile,BSIZE-4);
1526 strcat(buf[1],".old");
1527 if (rename(dbfile,buf[1]) < 0)
1529 BIO_printf(bio_err,"unable to rename %s to %s\n", dbfile, buf[1]);
1533 if (rename(buf[0],dbfile) < 0)
1535 BIO_printf(bio_err,"unable to rename %s to %s\n", buf[0],dbfile);
1537 rename(buf[1],dbfile);
1540 BIO_printf(bio_err,"Data Base Updated\n");
1543 /*****************************************************************/
1551 sk_X509_pop_free(cert_sk,X509_free);
1553 if (ret) ERR_print_errors(bio_err);
1554 app_RAND_write_file(randfile, bio_err);
1557 EVP_PKEY_free(pkey);
1565 static void lookup_fail(char *name, char *tag)
1567 BIO_printf(bio_err,"variable lookup failed for %s::%s\n",name,tag);
1570 static unsigned long index_serial_hash(const char **a)
1575 while (*n == '0') n++;
1576 return(lh_strhash(n));
1579 static int index_serial_cmp(const char **a, const char **b)
1583 for (aa=a[DB_serial]; *aa == '0'; aa++);
1584 for (bb=b[DB_serial]; *bb == '0'; bb++);
1585 return(strcmp(aa,bb));
1588 static unsigned long index_name_hash(const char **a)
1589 { return(lh_strhash(a[DB_name])); }
1591 static int index_name_qual(char **a)
1592 { return(a[0][0] == 'V'); }
1594 static int index_name_cmp(const char **a, const char **b)
1595 { return(strcmp(a[DB_name],
1598 static BIGNUM *load_serial(char *serialfile)
1602 MS_STATIC char buf[1024];
1603 ASN1_INTEGER *ai=NULL;
1605 if ((in=BIO_new(BIO_s_file())) == NULL)
1607 ERR_print_errors(bio_err);
1611 if (BIO_read_filename(in,serialfile) <= 0)
1616 ai=ASN1_INTEGER_new();
1617 if (ai == NULL) goto err;
1618 if (!a2i_ASN1_INTEGER(in,ai,buf,1024))
1620 BIO_printf(bio_err,"unable to load number from %s\n",
1624 ret=ASN1_INTEGER_to_BN(ai,NULL);
1627 BIO_printf(bio_err,"error converting number from bin to BIGNUM");
1631 if (in != NULL) BIO_free(in);
1632 if (ai != NULL) ASN1_INTEGER_free(ai);
1636 static int save_serial(char *serialfile, BIGNUM *serial)
1640 ASN1_INTEGER *ai=NULL;
1642 out=BIO_new(BIO_s_file());
1645 ERR_print_errors(bio_err);
1648 if (BIO_write_filename(out,serialfile) <= 0)
1654 if ((ai=BN_to_ASN1_INTEGER(serial,NULL)) == NULL)
1656 BIO_printf(bio_err,"error converting serial to ASN.1 format\n");
1659 i2a_ASN1_INTEGER(out,ai);
1663 if (out != NULL) BIO_free_all(out);
1664 if (ai != NULL) ASN1_INTEGER_free(ai);
1668 static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1669 const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
1670 BIGNUM *serial, char *startdate, char *enddate, int days,
1671 int batch, char *ext_sect, LHASH *lconf, int verbose)
1675 EVP_PKEY *pktmp=NULL;
1678 in=BIO_new(BIO_s_file());
1680 if (BIO_read_filename(in,infile) <= 0)
1685 if ((req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL)) == NULL)
1687 BIO_printf(bio_err,"Error reading certificate request in %s\n",
1692 X509_REQ_print(bio_err,req);
1694 BIO_printf(bio_err,"Check that the request matches the signature\n");
1696 if ((pktmp=X509_REQ_get_pubkey(req)) == NULL)
1698 BIO_printf(bio_err,"error unpacking public key\n");
1701 i=X509_REQ_verify(req,pktmp);
1702 EVP_PKEY_free(pktmp);
1706 BIO_printf(bio_err,"Signature verification problems....\n");
1712 BIO_printf(bio_err,"Signature did not match the certificate request\n");
1716 BIO_printf(bio_err,"Signature ok\n");
1718 ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate, enddate,
1719 days,batch,verbose,req,ext_sect,lconf);
1722 if (req != NULL) X509_REQ_free(req);
1723 if (in != NULL) BIO_free(in);
1727 static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1728 const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
1729 BIGNUM *serial, char *startdate, char *enddate, int days,
1730 int batch, char *ext_sect, LHASH *lconf, int verbose)
1733 X509_REQ *rreq=NULL;
1735 EVP_PKEY *pktmp=NULL;
1738 in=BIO_new(BIO_s_file());
1740 if (BIO_read_filename(in,infile) <= 0)
1745 if ((req=PEM_read_bio_X509(in,NULL,NULL,NULL)) == NULL)
1747 BIO_printf(bio_err,"Error reading self signed certificate in %s\n",infile);
1751 X509_print(bio_err,req);
1753 BIO_printf(bio_err,"Check that the request matches the signature\n");
1755 if ((pktmp=X509_get_pubkey(req)) == NULL)
1757 BIO_printf(bio_err,"error unpacking public key\n");
1760 i=X509_verify(req,pktmp);
1761 EVP_PKEY_free(pktmp);
1765 BIO_printf(bio_err,"Signature verification problems....\n");
1771 BIO_printf(bio_err,"Signature did not match the certificate\n");
1775 BIO_printf(bio_err,"Signature ok\n");
1777 if ((rreq=X509_to_X509_REQ(req,NULL,EVP_md5())) == NULL)
1780 ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,enddate,days,
1781 batch,verbose,rreq,ext_sect,lconf);
1784 if (rreq != NULL) X509_REQ_free(rreq);
1785 if (req != NULL) X509_free(req);
1786 if (in != NULL) BIO_free(in);
1790 static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
1791 STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial,
1792 char *startdate, char *enddate, int days, int batch, int verbose,
1793 X509_REQ *req, char *ext_sect, LHASH *lconf)
1795 X509_NAME *name=NULL,*CAname=NULL,*subject=NULL;
1796 ASN1_UTCTIME *tm,*tmptm;
1797 ASN1_STRING *str,*str2;
1801 X509_NAME_ENTRY *ne;
1802 X509_NAME_ENTRY *tne,*push;
1804 int ok= -1,i,j,last,nid;
1807 char *row[DB_NUMBER],**rrow,**irow=NULL;
1810 tmptm=ASN1_UTCTIME_new();
1813 BIO_printf(bio_err,"malloc error\n");
1817 for (i=0; i<DB_NUMBER; i++)
1820 BIO_printf(bio_err,"The Subjects Distinguished Name is as follows\n");
1821 name=X509_REQ_get_subject_name(req);
1822 for (i=0; i<X509_NAME_entry_count(name); i++)
1824 ne=(X509_NAME_ENTRY *)X509_NAME_get_entry(name,i);
1825 obj=X509_NAME_ENTRY_get_object(ne);
1826 j=i2a_ASN1_OBJECT(bio_err,obj);
1827 str=X509_NAME_ENTRY_get_data(ne);
1829 for (j=22-j; j>0; j--)
1833 BIO_puts(bio_err,buf);
1837 /* assume all type should be strings */
1838 nid=OBJ_obj2nid(ne->object);
1840 if (str->type == V_ASN1_UNIVERSALSTRING)
1841 ASN1_UNIVERSALSTRING_to_string(str);
1843 if ((str->type == V_ASN1_IA5STRING) &&
1844 (nid != NID_pkcs9_emailAddress))
1845 str->type=V_ASN1_T61STRING;
1847 if ((nid == NID_pkcs9_emailAddress) &&
1848 (str->type == V_ASN1_PRINTABLESTRING))
1849 str->type=V_ASN1_IA5STRING;
1852 if (str->type == V_ASN1_PRINTABLESTRING)
1853 BIO_printf(bio_err,"PRINTABLE:'");
1854 else if (str->type == V_ASN1_T61STRING)
1855 BIO_printf(bio_err,"T61STRING:'");
1856 else if (str->type == V_ASN1_IA5STRING)
1857 BIO_printf(bio_err,"IA5STRING:'");
1858 else if (str->type == V_ASN1_UNIVERSALSTRING)
1859 BIO_printf(bio_err,"UNIVERSALSTRING:'");
1861 BIO_printf(bio_err,"ASN.1 %2d:'",str->type);
1863 /* check some things */
1864 if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) &&
1865 (str->type != V_ASN1_IA5STRING))
1867 BIO_printf(bio_err,"\nemailAddress type needs to be of type IA5STRING\n");
1870 j=ASN1_PRINTABLE_type(str->data,str->length);
1871 if ( ((j == V_ASN1_T61STRING) &&
1872 (str->type != V_ASN1_T61STRING)) ||
1873 ((j == V_ASN1_IA5STRING) &&
1874 (str->type == V_ASN1_PRINTABLESTRING)))
1876 BIO_printf(bio_err,"\nThe string contains characters that are illegal for the ASN.1 type\n");
1880 p=(char *)str->data;
1881 for (j=str->length; j>0; j--)
1883 if ((*p >= ' ') && (*p <= '~'))
1884 BIO_printf(bio_err,"%c",*p);
1886 BIO_printf(bio_err,"\\0x%02X",*p);
1887 else if ((unsigned char)*p == 0xf7)
1888 BIO_printf(bio_err,"^?");
1889 else BIO_printf(bio_err,"^%c",*p+'@');
1892 BIO_printf(bio_err,"'\n");
1895 /* Ok, now we check the 'policy' stuff. */
1896 if ((subject=X509_NAME_new()) == NULL)
1898 BIO_printf(bio_err,"Memory allocation failure\n");
1902 /* take a copy of the issuer name before we mess with it. */
1903 CAname=X509_NAME_dup(x509->cert_info->subject);
1904 if (CAname == NULL) goto err;
1907 for (i=0; i<sk_CONF_VALUE_num(policy); i++)
1909 cv=sk_CONF_VALUE_value(policy,i); /* get the object id */
1910 if ((j=OBJ_txt2nid(cv->name)) == NID_undef)
1912 BIO_printf(bio_err,"%s:unknown object type in 'policy' configuration\n",cv->name);
1920 /* lookup the object in the supplied name list */
1921 j=X509_NAME_get_index_by_OBJ(name,obj,last);
1924 if (last != -1) break;
1929 tne=X509_NAME_get_entry(name,j);
1933 /* depending on the 'policy', decide what to do. */
1935 if (strcmp(cv->value,"optional") == 0)
1940 else if (strcmp(cv->value,"supplied") == 0)
1944 BIO_printf(bio_err,"The %s field needed to be supplied and was missing\n",cv->name);
1950 else if (strcmp(cv->value,"match") == 0)
1956 BIO_printf(bio_err,"The mandatory %s field was missing\n",cv->name);
1963 j=X509_NAME_get_index_by_OBJ(CAname,obj,last2);
1964 if ((j < 0) && (last2 == -1))
1966 BIO_printf(bio_err,"The %s field does not exist in the CA certificate,\nthe 'policy' is misconfigured\n",cv->name);
1971 push=X509_NAME_get_entry(CAname,j);
1972 str=X509_NAME_ENTRY_get_data(tne);
1973 str2=X509_NAME_ENTRY_get_data(push);
1975 if (ASN1_STRING_cmp(str,str2) != 0)
1980 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));
1986 BIO_printf(bio_err,"%s:invalid type in 'policy' configuration\n",cv->value);
1992 if (!X509_NAME_add_entry(subject,push, -1, 0))
1995 X509_NAME_ENTRY_free(push);
1996 BIO_printf(bio_err,"Memory allocation failure\n");
2006 X509_NAME_free(subject);
2007 subject=X509_NAME_dup(X509_REQ_get_subject_name(req));
2008 if (subject == NULL) goto err;
2012 BIO_printf(bio_err,"The subject name appears to be ok, checking data base for clashes\n");
2014 row[DB_name]=X509_NAME_oneline(subject,NULL,0);
2015 row[DB_serial]=BN_bn2hex(serial);
2016 if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
2018 BIO_printf(bio_err,"Memory allocation failure\n");
2022 rrow=TXT_DB_get_by_index(db,DB_name,row);
2025 BIO_printf(bio_err,"ERROR:There is already a certificate for %s\n",
2030 rrow=TXT_DB_get_by_index(db,DB_serial,row);
2033 BIO_printf(bio_err,"ERROR:Serial number %s has already been issued,\n",
2035 BIO_printf(bio_err," check the database/serial_file for corruption\n");
2042 "The matching entry has the following details\n");
2043 if (rrow[DB_type][0] == 'E')
2045 else if (rrow[DB_type][0] == 'R')
2047 else if (rrow[DB_type][0] == 'V')
2050 p="\ninvalid type, Data base error\n";
2051 BIO_printf(bio_err,"Type :%s\n",p);;
2052 if (rrow[DB_type][0] == 'R')
2054 p=rrow[DB_exp_date]; if (p == NULL) p="undef";
2055 BIO_printf(bio_err,"Was revoked on:%s\n",p);
2057 p=rrow[DB_exp_date]; if (p == NULL) p="undef";
2058 BIO_printf(bio_err,"Expires on :%s\n",p);
2059 p=rrow[DB_serial]; if (p == NULL) p="undef";
2060 BIO_printf(bio_err,"Serial Number :%s\n",p);
2061 p=rrow[DB_file]; if (p == NULL) p="undef";
2062 BIO_printf(bio_err,"File name :%s\n",p);
2063 p=rrow[DB_name]; if (p == NULL) p="undef";
2064 BIO_printf(bio_err,"Subject Name :%s\n",p);
2065 ok= -1; /* This is now a 'bad' error. */
2069 /* We are now totally happy, lets make and sign the certificate */
2071 BIO_printf(bio_err,"Everything appears to be ok, creating and signing the certificate\n");
2073 if ((ret=X509_new()) == NULL) goto err;
2077 /* Make it an X509 v3 certificate. */
2078 if (!X509_set_version(x509,2)) goto err;
2081 if (BN_to_ASN1_INTEGER(serial,ci->serialNumber) == NULL)
2083 if (!X509_set_issuer_name(ret,X509_get_subject_name(x509)))
2086 BIO_printf(bio_err,"Certificate is to be certified until ");
2087 if (strcmp(startdate,"today") == 0)
2088 X509_gmtime_adj(X509_get_notBefore(ret),0);
2089 else ASN1_UTCTIME_set_string(X509_get_notBefore(ret),startdate);
2091 if (enddate == NULL)
2092 X509_gmtime_adj(X509_get_notAfter(ret),(long)60*60*24*days);
2093 else ASN1_UTCTIME_set_string(X509_get_notAfter(ret),enddate);
2095 ASN1_UTCTIME_print(bio_err,X509_get_notAfter(ret));
2096 if (days) BIO_printf(bio_err," (%d days)",days);
2097 BIO_printf(bio_err, "\n");
2099 if (!X509_set_subject_name(ret,subject)) goto err;
2101 pktmp=X509_REQ_get_pubkey(req);
2102 i = X509_set_pubkey(ret,pktmp);
2103 EVP_PKEY_free(pktmp);
2106 /* Lets add the extensions, if there are any */
2110 if (ci->version == NULL)
2111 if ((ci->version=ASN1_INTEGER_new()) == NULL)
2113 ASN1_INTEGER_set(ci->version,2); /* version 3 certificate */
2115 /* Free the current entries if any, there should not
2116 * be any I believe */
2117 if (ci->extensions != NULL)
2118 sk_X509_EXTENSION_pop_free(ci->extensions,
2119 X509_EXTENSION_free);
2121 ci->extensions = NULL;
2123 /* Initialize the context structure */
2124 X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0);
2129 BIO_printf(bio_err, "Extra configuration file found\n");
2131 /* Use the extconf configuration db LHASH */
2132 X509V3_set_conf_lhash(&ctx, extconf);
2134 /* Test the structure (needed?) */
2135 /* X509V3_set_ctx_test(&ctx); */
2137 /* Adds exts contained in the configuration file */
2138 if (!X509V3_EXT_add_conf(extconf, &ctx, ext_sect,ret))
2141 "ERROR: adding extensions in section %s\n",
2143 ERR_print_errors(bio_err);
2147 BIO_printf(bio_err, "Successfully added extensions from file.\n");
2151 /* We found extensions to be set from config file */
2152 X509V3_set_conf_lhash(&ctx, lconf);
2154 if(!X509V3_EXT_add_conf(lconf, &ctx, ext_sect, ret))
2156 BIO_printf(bio_err, "ERROR: adding extensions in section %s\n", ext_sect);
2157 ERR_print_errors(bio_err);
2162 BIO_printf(bio_err, "Successfully added extensions from config\n");
2169 BIO_printf(bio_err,"Sign the certificate? [y/n]:");
2170 (void)BIO_flush(bio_err);
2172 fgets(buf,sizeof(buf)-1,stdin);
2173 if (!((buf[0] == 'y') || (buf[0] == 'Y')))
2175 BIO_printf(bio_err,"CERTIFICATE WILL NOT BE CERTIFIED\n");
2182 #ifndef OPENSSL_NO_DSA
2183 if (pkey->type == EVP_PKEY_DSA) dgst=EVP_dss1();
2184 pktmp=X509_get_pubkey(ret);
2185 if (EVP_PKEY_missing_parameters(pktmp) &&
2186 !EVP_PKEY_missing_parameters(pkey))
2187 EVP_PKEY_copy_parameters(pktmp,pkey);
2188 EVP_PKEY_free(pktmp);
2191 if (!X509_sign(ret,pkey,dgst))
2194 /* We now just add it to the database */
2195 row[DB_type]=(char *)OPENSSL_malloc(2);
2197 tm=X509_get_notAfter(ret);
2198 row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
2199 memcpy(row[DB_exp_date],tm->data,tm->length);
2200 row[DB_exp_date][tm->length]='\0';
2202 row[DB_rev_date]=NULL;
2204 /* row[DB_serial] done already */
2205 row[DB_file]=(char *)OPENSSL_malloc(8);
2206 /* row[DB_name] done already */
2208 if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2209 (row[DB_file] == NULL))
2211 BIO_printf(bio_err,"Memory allocation failure\n");
2214 strcpy(row[DB_file],"unknown");
2215 row[DB_type][0]='V';
2216 row[DB_type][1]='\0';
2218 if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
2220 BIO_printf(bio_err,"Memory allocation failure\n");
2224 for (i=0; i<DB_NUMBER; i++)
2229 irow[DB_NUMBER]=NULL;
2231 if (!TXT_DB_insert(db,irow))
2233 BIO_printf(bio_err,"failed to update database\n");
2234 BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
2239 for (i=0; i<DB_NUMBER; i++)
2240 if (row[i] != NULL) OPENSSL_free(row[i]);
2243 X509_NAME_free(CAname);
2244 if (subject != NULL)
2245 X509_NAME_free(subject);
2247 ASN1_UTCTIME_free(tmptm);
2250 if (ret != NULL) X509_free(ret);
2258 static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext)
2263 (void)i2d_X509_bio(bp,x);
2267 /* ??? Not needed since X509_print prints all this stuff anyway */
2268 f=X509_NAME_oneline(X509_get_issuer_name(x),buf,256);
2269 BIO_printf(bp,"issuer :%s\n",f);
2271 f=X509_NAME_oneline(X509_get_subject_name(x),buf,256);
2272 BIO_printf(bp,"subject:%s\n",f);
2274 BIO_puts(bp,"serial :");
2275 i2a_ASN1_INTEGER(bp,x->cert_info->serialNumber);
2276 BIO_puts(bp,"\n\n");
2278 if (!notext)X509_print(bp,x);
2279 PEM_write_bio_X509(bp,x);
2282 static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
2283 const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
2284 BIGNUM *serial, char *startdate, char *enddate, int days,
2285 char *ext_sect, LHASH *lconf, int verbose)
2287 STACK_OF(CONF_VALUE) *sk=NULL;
2290 CONF_VALUE *cv=NULL;
2291 NETSCAPE_SPKI *spki = NULL;
2294 EVP_PKEY *pktmp=NULL;
2296 X509_NAME_ENTRY *ne=NULL;
2302 * Load input file into a hash table. (This is just an easy
2303 * way to read and parse the file, then put it into a convenient
2306 parms=CONF_load(NULL,infile,&errline);
2309 BIO_printf(bio_err,"error on line %ld of %s\n",errline,infile);
2310 ERR_print_errors(bio_err);
2314 sk=CONF_get_section(parms, "default");
2315 if (sk_CONF_VALUE_num(sk) == 0)
2317 BIO_printf(bio_err, "no name/value pairs found in %s\n", infile);
2323 * Now create a dummy X509 request structure. We don't actually
2324 * have an X509 request, but we have many of the components
2325 * (a public key, various DN components). The idea is that we
2326 * put these components into the right X509 request structure
2327 * and we can use the same code as if you had a real X509 request.
2332 ERR_print_errors(bio_err);
2337 * Build up the subject name set.
2344 if (sk_CONF_VALUE_num(sk) <= i) break;
2346 cv=sk_CONF_VALUE_value(sk,i);
2348 /* Skip past any leading X. X: X, etc to allow for
2349 * multiple instances
2351 for (buf = cv->name; *buf ; buf++)
2352 if ((*buf == ':') || (*buf == ',') || (*buf == '.'))
2355 if (*buf) type = buf;
2360 if ((nid=OBJ_txt2nid(type)) == NID_undef)
2362 if (strcmp(type, "SPKAC") == 0)
2364 spki = NETSCAPE_SPKI_b64_decode(cv->value, -1);
2367 BIO_printf(bio_err,"unable to load Netscape SPKAC structure\n");
2368 ERR_print_errors(bio_err);
2375 j=ASN1_PRINTABLE_type((unsigned char *)buf,-1);
2376 if (fix_data(nid, &j) == 0)
2379 "invalid characters in string %s\n",buf);
2383 if ((ne=X509_NAME_ENTRY_create_by_NID(&ne,nid,j,
2384 (unsigned char *)buf,
2385 strlen(buf))) == NULL)
2388 if (!X509_NAME_add_entry(n,ne,-1, 0)) goto err;
2392 BIO_printf(bio_err,"Netscape SPKAC structure not found in %s\n",
2398 * Now extract the key from the SPKI structure.
2401 BIO_printf(bio_err,"Check that the SPKAC request matches the signature\n");
2403 if ((pktmp=NETSCAPE_SPKI_get_pubkey(spki)) == NULL)
2405 BIO_printf(bio_err,"error unpacking SPKAC public key\n");
2409 j = NETSCAPE_SPKI_verify(spki, pktmp);
2412 BIO_printf(bio_err,"signature verification failed on SPKAC public key\n");
2415 BIO_printf(bio_err,"Signature ok\n");
2417 X509_REQ_set_pubkey(req,pktmp);
2418 EVP_PKEY_free(pktmp);
2419 ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,enddate,
2420 days,1,verbose,req,ext_sect,lconf);
2422 if (req != NULL) X509_REQ_free(req);
2423 if (parms != NULL) CONF_free(parms);
2424 if (spki != NULL) NETSCAPE_SPKI_free(spki);
2425 if (ne != NULL) X509_NAME_ENTRY_free(ne);
2430 static int fix_data(int nid, int *type)
2432 if (nid == NID_pkcs9_emailAddress)
2433 *type=V_ASN1_IA5STRING;
2434 if ((nid == NID_commonName) && (*type == V_ASN1_IA5STRING))
2435 *type=V_ASN1_T61STRING;
2436 if ((nid == NID_pkcs9_challengePassword) && (*type == V_ASN1_IA5STRING))
2437 *type=V_ASN1_T61STRING;
2438 if ((nid == NID_pkcs9_unstructuredName) && (*type == V_ASN1_T61STRING))
2440 if (nid == NID_pkcs9_unstructuredName)
2441 *type=V_ASN1_IA5STRING;
2445 static int check_time_format(char *str)
2449 tm.data=(unsigned char *)str;
2450 tm.length=strlen(str);
2451 tm.type=V_ASN1_UTCTIME;
2452 return(ASN1_UTCTIME_check(&tm));
2455 static int do_revoke(X509 *x509, TXT_DB *db, int type, char *value)
2457 ASN1_UTCTIME *tm=NULL;
2458 char *row[DB_NUMBER],**rrow,**irow;
2459 char *rev_str = NULL;
2463 for (i=0; i<DB_NUMBER; i++)
2465 row[DB_name]=X509_NAME_oneline(X509_get_subject_name(x509),NULL,0);
2466 bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509),NULL);
2467 row[DB_serial]=BN_bn2hex(bn);
2469 if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
2471 BIO_printf(bio_err,"Memory allocation failure\n");
2474 /* We have to lookup by serial number because name lookup
2475 * skips revoked certs
2477 rrow=TXT_DB_get_by_index(db,DB_serial,row);
2480 BIO_printf(bio_err,"Adding Entry to DB for %s\n", row[DB_name]);
2482 /* We now just add it to the database */
2483 row[DB_type]=(char *)OPENSSL_malloc(2);
2485 tm=X509_get_notAfter(x509);
2486 row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
2487 memcpy(row[DB_exp_date],tm->data,tm->length);
2488 row[DB_exp_date][tm->length]='\0';
2490 row[DB_rev_date]=NULL;
2492 /* row[DB_serial] done already */
2493 row[DB_file]=(char *)OPENSSL_malloc(8);
2495 /* row[DB_name] done already */
2497 if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2498 (row[DB_file] == NULL))
2500 BIO_printf(bio_err,"Memory allocation failure\n");
2503 strcpy(row[DB_file],"unknown");
2504 row[DB_type][0]='V';
2505 row[DB_type][1]='\0';
2507 if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
2509 BIO_printf(bio_err,"Memory allocation failure\n");
2513 for (i=0; i<DB_NUMBER; i++)
2518 irow[DB_NUMBER]=NULL;
2520 if (!TXT_DB_insert(db,irow))
2522 BIO_printf(bio_err,"failed to update database\n");
2523 BIO_printf(bio_err,"TXT_DB error number %ld\n",db->error);
2527 /* Revoke Certificate */
2528 ok = do_revoke(x509,db, type, value);
2533 else if (index_name_cmp((const char **)row,(const char **)rrow))
2535 BIO_printf(bio_err,"ERROR:name does not match %s\n",
2539 else if (rrow[DB_type][0]=='R')
2541 BIO_printf(bio_err,"ERROR:Already revoked, serial number %s\n",
2547 BIO_printf(bio_err,"Revoking Certificate %s.\n", rrow[DB_serial]);
2548 rev_str = make_revocation_str(type, value);
2551 BIO_printf(bio_err, "Error in revocation arguments\n");
2554 rrow[DB_type][0]='R';
2555 rrow[DB_type][1]='\0';
2556 rrow[DB_rev_date] = rev_str;
2560 for (i=0; i<DB_NUMBER; i++)
2563 OPENSSL_free(row[i]);
2568 static int get_certificate_status(const char *serial, TXT_DB *db)
2570 char *row[DB_NUMBER],**rrow;
2573 /* Free Resources */
2574 for (i=0; i<DB_NUMBER; i++)
2577 /* Malloc needed char spaces */
2578 row[DB_serial] = OPENSSL_malloc(strlen(serial) + 2);
2579 if (row[DB_serial] == NULL)
2581 BIO_printf(bio_err,"Malloc failure\n");
2585 if (strlen(serial) % 2)
2587 /* Set the first char to 0 */;
2588 row[DB_serial][0]='0';
2590 /* Copy String from serial to row[DB_serial] */
2591 memcpy(row[DB_serial]+1, serial, strlen(serial));
2592 row[DB_serial][strlen(serial)+1]='\0';
2596 /* Copy String from serial to row[DB_serial] */
2597 memcpy(row[DB_serial], serial, strlen(serial));
2598 row[DB_serial][strlen(serial)]='\0';
2601 /* Make it Upper Case */
2602 for (i=0; row[DB_serial][i] != '\0'; i++)
2603 row[DB_serial][i] = toupper(row[DB_serial][i]);
2608 /* Search for the certificate */
2609 rrow=TXT_DB_get_by_index(db,DB_serial,row);
2612 BIO_printf(bio_err,"Serial %s not present in db.\n",
2617 else if (rrow[DB_type][0]=='V')
2619 BIO_printf(bio_err,"%s=Valid (%c)\n",
2620 row[DB_serial], rrow[DB_type][0]);
2623 else if (rrow[DB_type][0]=='R')
2625 BIO_printf(bio_err,"%s=Revoked (%c)\n",
2626 row[DB_serial], rrow[DB_type][0]);
2629 else if (rrow[DB_type][0]=='E')
2631 BIO_printf(bio_err,"%s=Expired (%c)\n",
2632 row[DB_serial], rrow[DB_type][0]);
2635 else if (rrow[DB_type][0]=='S')
2637 BIO_printf(bio_err,"%s=Suspended (%c)\n",
2638 row[DB_serial], rrow[DB_type][0]);
2643 BIO_printf(bio_err,"%s=Unknown (%c).\n",
2644 row[DB_serial], rrow[DB_type][0]);
2648 for (i=0; i<DB_NUMBER; i++)
2651 OPENSSL_free(row[i]);
2656 static int do_updatedb (TXT_DB *db)
2658 ASN1_UTCTIME *a_tm = NULL;
2660 int db_y2k, a_y2k; /* flags = 1 if y >= 2000 */
2661 char **rrow, *a_tm_s;
2663 a_tm = ASN1_UTCTIME_new();
2665 /* get actual time and make a string */
2666 a_tm = X509_gmtime_adj(a_tm, 0);
2667 a_tm_s = (char *) OPENSSL_malloc(a_tm->length+1);
2674 memcpy(a_tm_s, a_tm->data, a_tm->length);
2675 a_tm_s[a_tm->length] = '\0';
2677 if (strncmp(a_tm_s, "49", 2) <= 0)
2682 for (i = 0; i < sk_num(db->data); i++)
2684 rrow = (char **) sk_value(db->data, i);
2686 if (rrow[DB_type][0] == 'V')
2688 /* ignore entries that are not valid */
2689 if (strncmp(rrow[DB_exp_date], "49", 2) <= 0)
2694 if (db_y2k == a_y2k)
2696 /* all on the same y2k side */
2697 if (strcmp(rrow[DB_exp_date], a_tm_s) <= 0)
2699 rrow[DB_type][0] = 'E';
2700 rrow[DB_type][1] = '\0';
2703 BIO_printf(bio_err, "%s=Expired\n",
2707 else if (db_y2k < a_y2k)
2709 rrow[DB_type][0] = 'E';
2710 rrow[DB_type][1] = '\0';
2713 BIO_printf(bio_err, "%s=Expired\n",
2722 ASN1_UTCTIME_free(a_tm);
2723 OPENSSL_free(a_tm_s);
2728 static char *crl_reasons[] = {
2729 /* CRL reason strings */
2733 "affiliationChanged",
2735 "cessationOfOperation",
2738 /* Additional pseudo reasons */
2744 #define NUM_REASONS (sizeof(crl_reasons) / sizeof(char *))
2746 /* Given revocation information convert to a DB string.
2747 * The format of the string is:
2748 * revtime[,reason,extra]. Where 'revtime' is the
2749 * revocation time (the current time). 'reason' is the
2750 * optional CRL reason and 'extra' is any additional
2754 char *make_revocation_str(int rev_type, char *rev_arg)
2756 char *reason = NULL, *other = NULL, *str;
2758 ASN1_UTCTIME *revtm = NULL;
2765 case REV_CRL_REASON:
2766 for (i = 0; i < 8; i++)
2768 if (!strcasecmp(rev_arg, crl_reasons[i]))
2770 reason = crl_reasons[i];
2776 BIO_printf(bio_err, "Unknown CRL reason %s\n", rev_arg);
2782 /* Argument is an OID */
2784 otmp = OBJ_txt2obj(rev_arg, 0);
2785 ASN1_OBJECT_free(otmp);
2789 BIO_printf(bio_err, "Invalid object identifier %s\n", rev_arg);
2793 reason = "holdInstruction";
2797 case REV_KEY_COMPROMISE:
2798 case REV_CA_COMPROMISE:
2800 /* Argument is the key compromise time */
2801 if (!ASN1_GENERALIZEDTIME_set_string(NULL, rev_arg))
2803 BIO_printf(bio_err, "Invalid time format %s. Need YYYYMMDDHHMMSSZ\n", rev_arg);
2807 if (rev_type == REV_KEY_COMPROMISE)
2810 reason = "CAkeyTime";
2816 revtm = X509_gmtime_adj(NULL, 0);
2818 i = revtm->length + 1;
2820 if (reason) i += strlen(reason) + 1;
2821 if (other) i += strlen(other) + 1;
2823 str = OPENSSL_malloc(i);
2825 if (!str) return NULL;
2827 strcpy(str, (char *)revtm->data);
2831 strcat(str, reason);
2838 ASN1_UTCTIME_free(revtm);
2842 /* Convert revocation field to X509_REVOKED entry
2846 * 2 OK and some extensions added (i.e. V2 CRL)
2849 int make_revoked(X509_REVOKED *rev, char *str)
2852 char *rtime_str, *reason_str = NULL, *arg_str = NULL, *p;
2853 int reason_code = -1;
2855 ASN1_OBJECT *hold = NULL;
2856 ASN1_GENERALIZEDTIME *comp_time = NULL;
2857 ASN1_ENUMERATED *rtmp = NULL;
2858 tmp = BUF_strdup(str);
2860 p = strchr(tmp, ',');
2877 if (rev && !ASN1_UTCTIME_set_string(rev->revocationDate, rtime_str))
2879 BIO_printf(bio_err, "invalid revocation date %s\n", rtime_str);
2884 for (i = 0; i < NUM_REASONS; i++)
2886 if(!strcasecmp(reason_str, crl_reasons[i]))
2892 if (reason_code == OCSP_REVOKED_STATUS_NOSTATUS)
2894 BIO_printf(bio_err, "invalid reason code %s\n", reason_str);
2898 if (reason_code == 7)
2899 reason_code = OCSP_REVOKED_STATUS_REMOVEFROMCRL;
2900 else if (reason_code == 8) /* Hold instruction */
2904 BIO_printf(bio_err, "missing hold instruction\n");
2907 reason_code = OCSP_REVOKED_STATUS_CERTIFICATEHOLD;
2908 hold = OBJ_txt2obj(arg_str, 0);
2912 BIO_printf(bio_err, "invalid object identifier %s\n", arg_str);
2916 else if ((reason_code == 9) || (reason_code == 10))
2920 BIO_printf(bio_err, "missing compromised time\n");
2923 comp_time = ASN1_GENERALIZEDTIME_new();
2924 if (!ASN1_GENERALIZEDTIME_set_string(comp_time, arg_str))
2926 BIO_printf(bio_err, "invalid compromised time %s\n", arg_str);
2929 if (reason_code == 9)
2930 reason_code = OCSP_REVOKED_STATUS_KEYCOMPROMISE;
2932 reason_code = OCSP_REVOKED_STATUS_CACOMPROMISE;
2936 if (rev && (reason_code != OCSP_REVOKED_STATUS_NOSTATUS))
2938 rtmp = ASN1_ENUMERATED_new();
2939 if (!rtmp || !ASN1_ENUMERATED_set(rtmp, reason_code))
2941 if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0))
2945 if (rev && comp_time)
2947 if (!X509_REVOKED_add1_ext_i2d(rev, NID_invalidity_date, comp_time, 0, 0))
2952 if (!X509_REVOKED_add1_ext_i2d(rev, NID_hold_instruction_code, hold, 0, 0))
2956 if (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)
2962 if (tmp) OPENSSL_free(tmp);
2963 ASN1_OBJECT_free(hold);
2964 ASN1_GENERALIZEDTIME_free(comp_time);
2965 ASN1_ENUMERATED_free(rtmp);