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>
67 #include <openssl/conf.h>
68 #include <openssl/bio.h>
69 #include <openssl/err.h>
70 #include <openssl/bn.h>
71 #include <openssl/txt_db.h>
72 #include <openssl/evp.h>
73 #include <openssl/x509.h>
74 #include <openssl/x509v3.h>
75 #include <openssl/objects.h>
76 #include <openssl/ocsp.h>
77 #include <openssl/pem.h>
80 # ifdef OPENSSL_SYS_VMS
86 # elif !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_NETWARE)
87 # 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_CRLNUMBER "crlnumber"
116 #define ENV_CRL "crl"
117 #define ENV_PRIVATE_KEY "private_key"
118 #define ENV_RANDFILE "RANDFILE"
119 #define ENV_DEFAULT_DAYS "default_days"
120 #define ENV_DEFAULT_STARTDATE "default_startdate"
121 #define ENV_DEFAULT_ENDDATE "default_enddate"
122 #define ENV_DEFAULT_CRL_DAYS "default_crl_days"
123 #define ENV_DEFAULT_CRL_HOURS "default_crl_hours"
124 #define ENV_DEFAULT_MD "default_md"
125 #define ENV_DEFAULT_EMAIL_DN "email_in_dn"
126 #define ENV_PRESERVE "preserve"
127 #define ENV_POLICY "policy"
128 #define ENV_EXTENSIONS "x509_extensions"
129 #define ENV_CRLEXT "crl_extensions"
130 #define ENV_MSIE_HACK "msie_hack"
131 #define ENV_NAMEOPT "name_opt"
132 #define ENV_CERTOPT "cert_opt"
133 #define ENV_EXTCOPY "copy_extensions"
134 #define ENV_UNIQUE_SUBJECT "unique_subject"
136 #define ENV_DATABASE "database"
138 /* Additional revocation information types */
140 #define REV_NONE 0 /* No addditional information */
141 #define REV_CRL_REASON 1 /* Value is CRL reason code */
142 #define REV_HOLD 2 /* Value is hold instruction */
143 #define REV_KEY_COMPROMISE 3 /* Value is cert key compromise time */
144 #define REV_CA_COMPROMISE 4 /* Value is CA key compromise time */
146 static const char *ca_usage[]={
149 " -verbose - Talk alot while doing things\n",
150 " -config file - A config file\n",
151 " -name arg - The particular CA definition to use\n",
152 " -gencrl - Generate a new CRL\n",
153 " -crldays days - Days is when the next CRL is due\n",
154 " -crlhours hours - Hours is when the next CRL is due\n",
155 " -startdate YYMMDDHHMMSSZ - certificate validity notBefore\n",
156 " -enddate YYMMDDHHMMSSZ - certificate validity notAfter (overrides -days)\n",
157 " -days arg - number of days to certify the certificate for\n",
158 " -md arg - md to use, one of md2, md5, sha or sha1\n",
159 " -policy arg - The CA 'policy' to support\n",
160 " -keyfile arg - private key file\n",
161 " -keyform arg - private key file format (PEM or ENGINE)\n",
162 " -key arg - key to decode the private key if it is encrypted\n",
163 " -cert file - The CA certificate\n",
164 " -selfsign - sign a certificate with the key associated with it\n",
165 " -in file - The input PEM encoded certificate request(s)\n",
166 " -out file - Where to put the output file(s)\n",
167 " -outdir dir - Where to put output certificates\n",
168 " -infiles .... - The last argument, requests to process\n",
169 " -spkac file - File contains DN and signed public key and challenge\n",
170 " -ss_cert file - File contains a self signed cert to sign\n",
171 " -preserveDN - Don't re-order the DN\n",
172 " -noemailDN - Don't add the EMAIL field into certificate' subject\n",
173 " -batch - Don't ask questions\n",
174 " -msie_hack - msie modifications to handle all those universal strings\n",
175 " -revoke file - Revoke a certificate (given in file)\n",
176 " -subj arg - Use arg instead of request's subject\n",
177 " -multivalue-rdn - enable support for multivalued RDNs\n",
178 " -extensions .. - Extension section (override value in config file)\n",
179 " -extfile file - Configuration file with X509v3 extentions to add\n",
180 " -crlexts .. - CRL extension section (override value in config file)\n",
181 #ifndef OPENSSL_NO_ENGINE
182 " -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(const char *name, const char *tag);
196 static int certify(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
197 const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,CA_DB *db,
198 BIGNUM *serial, char *subj, int multirdn, int email_dn, char *startdate,
199 char *enddate, long days, int batch, char *ext_sect, CONF *conf,
200 int verbose, unsigned long certopt, unsigned long nameopt,
201 int default_op, int ext_copy, int selfsign);
202 static int certify_cert(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
203 const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
204 CA_DB *db, BIGNUM *serial, char *subj, int multirdn, int email_dn,
205 char *startdate, char *enddate, long days, int batch,
206 char *ext_sect, CONF *conf,int verbose, unsigned long certopt,
207 unsigned long nameopt, int default_op, int ext_copy,
209 static int certify_spkac(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
210 const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
211 CA_DB *db, BIGNUM *serial,char *subj, int multirdn, int email_dn,
212 char *startdate, char *enddate, long days, char *ext_sect,
213 CONF *conf, int verbose, unsigned long certopt,
214 unsigned long nameopt, int default_op, int ext_copy);
215 static int fix_data(int nid, int *type);
216 static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext);
217 static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
218 STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial,char *subj, int multirdn,
219 int email_dn, char *startdate, char *enddate, long days, int batch,
220 int verbose, X509_REQ *req, char *ext_sect, CONF *conf,
221 unsigned long certopt, unsigned long nameopt, int default_op,
222 int ext_copy, int selfsign);
223 static int do_revoke(X509 *x509, CA_DB *db, int ext, char *extval);
224 static int get_certificate_status(const char *ser_status, CA_DB *db);
225 static int do_updatedb(CA_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, const char *str);
229 int old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str);
230 static CONF *conf=NULL;
231 static CONF *extconf=NULL;
232 static char *section=NULL;
234 static int preserve=0;
235 static int msie_hack=0;
238 int MAIN(int, char **);
240 int MAIN(int argc, char **argv)
243 char *key=NULL,*passargin=NULL;
259 char *configfile=NULL;
264 int keyform=FORMAT_PEM;
266 char *spkac_file=NULL;
267 char *ss_cert_file=NULL;
268 char *ser_status=NULL;
273 char *serialfile=NULL;
274 char *crlnumberfile=NULL;
275 char *extensions=NULL;
279 char *tmp_email_dn=NULL;
281 int rev_type = REV_NONE;
282 char *rev_arg = NULL;
284 BIGNUM *crlnumber=NULL;
285 char *startdate=NULL;
290 unsigned long nameopt = 0, certopt = 0;
292 int ext_copy = EXT_COPY_NONE;
294 X509 *x509=NULL, *x509p = NULL;
296 BIO *in=NULL,*out=NULL,*Sout=NULL,*Cout=NULL;
300 X509_REVOKED *r=NULL;
302 ASN1_INTEGER *tmpser;
306 const EVP_MD *dgst=NULL;
307 STACK_OF(CONF_VALUE) *attribs=NULL;
308 STACK_OF(X509) *cert_sk=NULL;
311 MS_STATIC char buf[3][BSIZE];
313 #ifndef OPENSSL_NO_ENGINE
334 if ((bio_err=BIO_new(BIO_s_file())) != NULL)
335 BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
341 if (strcmp(*argv,"-verbose") == 0)
343 else if (strcmp(*argv,"-config") == 0)
345 if (--argc < 1) goto bad;
346 configfile= *(++argv);
348 else if (strcmp(*argv,"-name") == 0)
350 if (--argc < 1) goto bad;
353 else if (strcmp(*argv,"-subj") == 0)
355 if (--argc < 1) goto bad;
359 else if (strcmp(*argv,"-create_serial") == 0)
361 else if (strcmp(*argv,"-multivalue-rdn") == 0)
363 else if (strcmp(*argv,"-startdate") == 0)
365 if (--argc < 1) goto bad;
366 startdate= *(++argv);
368 else if (strcmp(*argv,"-enddate") == 0)
370 if (--argc < 1) goto bad;
373 else if (strcmp(*argv,"-days") == 0)
375 if (--argc < 1) goto bad;
376 days=atoi(*(++argv));
378 else if (strcmp(*argv,"-md") == 0)
380 if (--argc < 1) goto bad;
383 else if (strcmp(*argv,"-policy") == 0)
385 if (--argc < 1) goto bad;
388 else if (strcmp(*argv,"-keyfile") == 0)
390 if (--argc < 1) goto bad;
393 else if (strcmp(*argv,"-keyform") == 0)
395 if (--argc < 1) goto bad;
396 keyform=str2fmt(*(++argv));
398 else if (strcmp(*argv,"-passin") == 0)
400 if (--argc < 1) goto bad;
401 passargin= *(++argv);
403 else if (strcmp(*argv,"-key") == 0)
405 if (--argc < 1) goto bad;
408 else if (strcmp(*argv,"-cert") == 0)
410 if (--argc < 1) goto bad;
413 else if (strcmp(*argv,"-selfsign") == 0)
415 else if (strcmp(*argv,"-in") == 0)
417 if (--argc < 1) goto bad;
421 else if (strcmp(*argv,"-out") == 0)
423 if (--argc < 1) goto bad;
426 else if (strcmp(*argv,"-outdir") == 0)
428 if (--argc < 1) goto bad;
431 else if (strcmp(*argv,"-notext") == 0)
433 else if (strcmp(*argv,"-batch") == 0)
435 else if (strcmp(*argv,"-preserveDN") == 0)
437 else if (strcmp(*argv,"-noemailDN") == 0)
439 else if (strcmp(*argv,"-gencrl") == 0)
441 else if (strcmp(*argv,"-msie_hack") == 0)
443 else if (strcmp(*argv,"-crldays") == 0)
445 if (--argc < 1) goto bad;
446 crldays= atol(*(++argv));
448 else if (strcmp(*argv,"-crlhours") == 0)
450 if (--argc < 1) goto bad;
451 crlhours= atol(*(++argv));
453 else if (strcmp(*argv,"-infiles") == 0)
460 else if (strcmp(*argv, "-ss_cert") == 0)
462 if (--argc < 1) goto bad;
463 ss_cert_file = *(++argv);
466 else if (strcmp(*argv, "-spkac") == 0)
468 if (--argc < 1) goto bad;
469 spkac_file = *(++argv);
472 else if (strcmp(*argv,"-revoke") == 0)
474 if (--argc < 1) goto bad;
478 else if (strcmp(*argv,"-extensions") == 0)
480 if (--argc < 1) goto bad;
481 extensions= *(++argv);
483 else if (strcmp(*argv,"-extfile") == 0)
485 if (--argc < 1) goto bad;
488 else if (strcmp(*argv,"-status") == 0)
490 if (--argc < 1) goto bad;
491 ser_status= *(++argv);
493 else if (strcmp(*argv,"-updatedb") == 0)
497 else if (strcmp(*argv,"-crlexts") == 0)
499 if (--argc < 1) goto bad;
502 else if (strcmp(*argv,"-crl_reason") == 0)
504 if (--argc < 1) goto bad;
506 rev_type = REV_CRL_REASON;
508 else if (strcmp(*argv,"-crl_hold") == 0)
510 if (--argc < 1) goto bad;
514 else if (strcmp(*argv,"-crl_compromise") == 0)
516 if (--argc < 1) goto bad;
518 rev_type = REV_KEY_COMPROMISE;
520 else if (strcmp(*argv,"-crl_CA_compromise") == 0)
522 if (--argc < 1) goto bad;
524 rev_type = REV_CA_COMPROMISE;
526 #ifndef OPENSSL_NO_ENGINE
527 else if (strcmp(*argv,"-engine") == 0)
529 if (--argc < 1) goto bad;
536 BIO_printf(bio_err,"unknown option %s\n",*argv);
546 for (pp=ca_usage; (*pp != NULL); pp++)
547 BIO_printf(bio_err,"%s",*pp);
551 ERR_load_crypto_strings();
553 /*****************************************************************/
555 if (configfile == NULL) configfile = getenv("OPENSSL_CONF");
556 if (configfile == NULL) configfile = getenv("SSLEAY_CONF");
557 if (configfile == NULL)
559 const char *s=X509_get_default_cert_area();
562 #ifdef OPENSSL_SYS_VMS
563 len = strlen(s)+sizeof(CONFIG_FILE);
564 tofree=OPENSSL_malloc(len);
567 len = strlen(s)+sizeof(CONFIG_FILE)+1;
568 tofree=OPENSSL_malloc(len);
569 BUF_strlcpy(tofree,s,len);
570 BUF_strlcat(tofree,"/",len);
572 BUF_strlcat(tofree,CONFIG_FILE,len);
576 BIO_printf(bio_err,"Using configuration from %s\n",configfile);
577 conf = NCONF_new(NULL);
578 if (NCONF_load(conf,configfile,&errorline) <= 0)
581 BIO_printf(bio_err,"error loading the config file '%s'\n",
584 BIO_printf(bio_err,"error on line %ld of config file '%s'\n"
585 ,errorline,configfile);
590 OPENSSL_free(tofree);
594 if (!load_config(bio_err, conf))
597 #ifndef OPENSSL_NO_ENGINE
598 e = setup_engine(bio_err, engine, 0);
601 /* Lets get the config section we are using */
604 section=NCONF_get_string(conf,BASE_SECTION,ENV_DEFAULT_CA);
607 lookup_fail(BASE_SECTION,ENV_DEFAULT_CA);
614 p=NCONF_get_string(conf,NULL,"oid_file");
621 oid_bio=BIO_new_file(p,"r");
625 BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
626 ERR_print_errors(bio_err);
632 OBJ_create_objects(oid_bio);
636 if (!add_oid_section(bio_err,conf))
638 ERR_print_errors(bio_err);
643 randfile = NCONF_get_string(conf, BASE_SECTION, "RANDFILE");
644 if (randfile == NULL)
646 app_RAND_load_file(randfile, bio_err, 0);
648 db_attr.unique_subject = 1;
649 p = NCONF_get_string(conf, section, ENV_UNIQUE_SUBJECT);
653 BIO_printf(bio_err, "DEBUG: unique_subject = \"%s\"\n", p);
655 db_attr.unique_subject = parse_yesno(p,1);
661 BIO_printf(bio_err, "DEBUG: unique_subject undefined\n", p);
664 BIO_printf(bio_err, "DEBUG: configured unique_subject is %d\n",
665 db_attr.unique_subject);
668 in=BIO_new(BIO_s_file());
669 out=BIO_new(BIO_s_file());
670 Sout=BIO_new(BIO_s_file());
671 Cout=BIO_new(BIO_s_file());
672 if ((in == NULL) || (out == NULL) || (Sout == NULL) || (Cout == NULL))
674 ERR_print_errors(bio_err);
678 /*****************************************************************/
679 /* report status of cert with serial number given on command line */
682 if ((dbfile=NCONF_get_string(conf,section,ENV_DATABASE)) == NULL)
684 lookup_fail(section,ENV_DATABASE);
687 db = load_index(dbfile,&db_attr);
688 if (db == NULL) goto err;
690 if (!index_index(db)) goto err;
692 if (get_certificate_status(ser_status,db) != 1)
693 BIO_printf(bio_err,"Error verifying serial %s!\n",
698 /*****************************************************************/
699 /* we definitely need a private key, so let's get it */
701 if ((keyfile == NULL) && ((keyfile=NCONF_get_string(conf,
702 section,ENV_PRIVATE_KEY)) == NULL))
704 lookup_fail(section,ENV_PRIVATE_KEY);
710 if (!app_passwd(bio_err, passargin, NULL, &key, NULL))
712 BIO_printf(bio_err,"Error getting password\n");
716 pkey = load_key(bio_err, keyfile, keyform, 0, key, e,
718 if (key) OPENSSL_cleanse(key,strlen(key));
721 /* load_key() has already printed an appropriate message */
725 /*****************************************************************/
726 /* we need a certificate */
727 if (!selfsign || spkac_file || ss_cert_file || gencrl)
729 if ((certfile == NULL)
730 && ((certfile=NCONF_get_string(conf,
731 section,ENV_CERTIFICATE)) == NULL))
733 lookup_fail(section,ENV_CERTIFICATE);
736 x509=load_cert(bio_err, certfile, FORMAT_PEM, NULL, e,
741 if (!X509_check_private_key(x509,pkey))
743 BIO_printf(bio_err,"CA certificate and CA private key do not match\n");
747 if (!selfsign) x509p = x509;
749 f=NCONF_get_string(conf,BASE_SECTION,ENV_PRESERVE);
752 if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
754 f=NCONF_get_string(conf,BASE_SECTION,ENV_MSIE_HACK);
757 if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
760 f=NCONF_get_string(conf,section,ENV_NAMEOPT);
764 if (!set_name_ex(&nameopt, f))
766 BIO_printf(bio_err, "Invalid name options: \"%s\"\n", f);
774 f=NCONF_get_string(conf,section,ENV_CERTOPT);
778 if (!set_cert_ex(&certopt, f))
780 BIO_printf(bio_err, "Invalid certificate options: \"%s\"\n", f);
788 f=NCONF_get_string(conf,section,ENV_EXTCOPY);
792 if (!set_ext_copy(&ext_copy, f))
794 BIO_printf(bio_err, "Invalid extension copy option: \"%s\"\n", f);
801 /*****************************************************************/
802 /* lookup where to write new certificates */
803 if ((outdir == NULL) && (req))
807 if ((outdir=NCONF_get_string(conf,section,ENV_NEW_CERTS_DIR))
810 BIO_printf(bio_err,"there needs to be defined a directory for new certificate to be placed in\n");
813 #ifndef OPENSSL_SYS_VMS
814 /* outdir is a directory spec, but access() for VMS demands a
815 filename. In any case, stat(), below, will catch the problem
816 if outdir is not a directory spec, and the fopen() or open()
817 will catch an error if there is no write access.
819 Presumably, this problem could also be solved by using the DEC
820 C routines to convert the directory syntax to Unixly, and give
821 that to access(). However, time's too short to do that just
824 if (access(outdir,R_OK|W_OK|X_OK) != 0)
826 BIO_printf(bio_err,"I am unable to access the %s directory\n",outdir);
831 if (stat(outdir,&sb) != 0)
833 BIO_printf(bio_err,"unable to stat(%s)\n",outdir);
838 if (!(sb.st_mode & S_IFDIR))
840 BIO_printf(bio_err,"%s need to be a directory\n",outdir);
848 /*****************************************************************/
849 /* we need to load the database file */
850 if ((dbfile=NCONF_get_string(conf,section,ENV_DATABASE)) == NULL)
852 lookup_fail(section,ENV_DATABASE);
855 db = load_index(dbfile, &db_attr);
856 if (db == NULL) goto err;
858 /* Lets check some fields */
859 for (i=0; i<sk_num(db->db->data); i++)
861 pp=(const char **)sk_value(db->db->data,i);
862 if ((pp[DB_type][0] != DB_TYPE_REV) &&
863 (pp[DB_rev_date][0] != '\0'))
865 BIO_printf(bio_err,"entry %d: not revoked yet, but has a revocation date\n",i+1);
868 if ((pp[DB_type][0] == DB_TYPE_REV) &&
869 !make_revoked(NULL, pp[DB_rev_date]))
871 BIO_printf(bio_err," in entry %d\n", i+1);
874 if (!check_time_format((char *)pp[DB_exp_date]))
876 BIO_printf(bio_err,"entry %d: invalid expiry date\n",i+1);
886 if ((j&1) || (j < 2))
888 BIO_printf(bio_err,"entry %d: bad serial number length (%d)\n",i+1,j);
893 if (!( ((*p >= '0') && (*p <= '9')) ||
894 ((*p >= 'A') && (*p <= 'F')) ||
895 ((*p >= 'a') && (*p <= 'f'))) )
897 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);
905 BIO_set_fp(out,stdout,BIO_NOCLOSE|BIO_FP_TEXT); /* cannot fail */
906 #ifdef OPENSSL_SYS_VMS
908 BIO *tmpbio = BIO_new(BIO_f_linebuffer());
909 out = BIO_push(tmpbio, out);
912 TXT_DB_write(out,db->db);
913 BIO_printf(bio_err,"%d entries loaded from the database\n",
915 BIO_printf(bio_err,"generating index\n");
918 if (!index_index(db)) goto err;
920 /*****************************************************************/
921 /* Update the db file for expired certificates */
925 BIO_printf(bio_err, "Updating %s ...\n",
931 BIO_printf(bio_err,"Malloc failure\n");
936 if (verbose) BIO_printf(bio_err,
937 "No entries found to mark expired\n");
941 if (!save_index(dbfile,"new",db)) goto err;
943 if (!rotate_index(dbfile,"new","old")) goto err;
945 if (verbose) BIO_printf(bio_err,
946 "Done. %d entries marked as expired\n",i);
951 /*****************************************************************/
952 /* Read extentions config file */
955 extconf = NCONF_new(NULL);
956 if (NCONF_load(extconf,extfile,&errorline) <= 0)
959 BIO_printf(bio_err, "ERROR: loading the config file '%s'\n",
962 BIO_printf(bio_err, "ERROR: on line %ld of config file '%s'\n",
969 BIO_printf(bio_err, "Successfully loaded extensions file %s\n", extfile);
971 /* We can have sections in the ext file */
972 if (!extensions && !(extensions = NCONF_get_string(extconf, "default", "extensions")))
973 extensions = "default";
976 /*****************************************************************/
981 if (BIO_write_filename(Sout,outfile) <= 0)
989 BIO_set_fp(Sout,stdout,BIO_NOCLOSE|BIO_FP_TEXT);
990 #ifdef OPENSSL_SYS_VMS
992 BIO *tmpbio = BIO_new(BIO_f_linebuffer());
993 Sout = BIO_push(tmpbio, Sout);
999 if ((md == NULL) && ((md=NCONF_get_string(conf,
1000 section,ENV_DEFAULT_MD)) == NULL))
1002 lookup_fail(section,ENV_DEFAULT_MD);
1006 if ((dgst=EVP_get_digestbyname(md)) == NULL)
1008 BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
1014 if ((email_dn == 1) && ((tmp_email_dn=NCONF_get_string(conf,
1015 section,ENV_DEFAULT_EMAIL_DN)) != NULL ))
1017 if(strcmp(tmp_email_dn,"no") == 0)
1021 BIO_printf(bio_err,"message digest is %s\n",
1022 OBJ_nid2ln(dgst->type));
1023 if ((policy == NULL) && ((policy=NCONF_get_string(conf,
1024 section,ENV_POLICY)) == NULL))
1026 lookup_fail(section,ENV_POLICY);
1030 BIO_printf(bio_err,"policy is %s\n",policy);
1032 if ((serialfile=NCONF_get_string(conf,section,ENV_SERIAL))
1035 lookup_fail(section,ENV_SERIAL);
1041 /* no '-extfile' option, so we look for extensions
1042 * in the main configuration file */
1045 extensions=NCONF_get_string(conf,section,
1052 /* Check syntax of file */
1054 X509V3_set_ctx_test(&ctx);
1055 X509V3_set_nconf(&ctx, conf);
1056 if (!X509V3_EXT_add_nconf(conf, &ctx, extensions,
1060 "Error Loading extension section %s\n",
1068 if (startdate == NULL)
1070 startdate=NCONF_get_string(conf,section,
1071 ENV_DEFAULT_STARTDATE);
1072 if (startdate == NULL)
1075 if (startdate && !ASN1_UTCTIME_set_string(NULL,startdate))
1077 BIO_printf(bio_err,"start date is invalid, it should be YYMMDDHHMMSSZ\n");
1080 if (startdate == NULL) startdate="today";
1082 if (enddate == NULL)
1084 enddate=NCONF_get_string(conf,section,
1085 ENV_DEFAULT_ENDDATE);
1086 if (enddate == NULL)
1089 if (enddate && !ASN1_UTCTIME_set_string(NULL,enddate))
1091 BIO_printf(bio_err,"end date is invalid, it should be YYMMDDHHMMSSZ\n");
1097 if(!NCONF_get_number(conf,section, ENV_DEFAULT_DAYS, &days))
1100 if (!enddate && (days == 0))
1102 BIO_printf(bio_err,"cannot lookup how many days to certify for\n");
1106 if ((serial=load_serial(serialfile, create_ser, NULL)) == NULL)
1108 BIO_printf(bio_err,"error while loading serial number\n");
1113 if (BN_is_zero(serial))
1114 BIO_printf(bio_err,"next serial number is 00\n");
1117 if ((f=BN_bn2hex(serial)) == NULL) goto err;
1118 BIO_printf(bio_err,"next serial number is %s\n",f);
1123 if ((attribs=NCONF_get_section(conf,policy)) == NULL)
1125 BIO_printf(bio_err,"unable to find 'section' for %s\n",policy);
1129 if ((cert_sk=sk_X509_new_null()) == NULL)
1131 BIO_printf(bio_err,"Memory allocation failure\n");
1134 if (spkac_file != NULL)
1137 j=certify_spkac(&x,spkac_file,pkey,x509,dgst,attribs,db,
1138 serial,subj,multirdn,email_dn,startdate,enddate,days,extensions,
1139 conf,verbose,certopt,nameopt,default_op,ext_copy);
1140 if (j < 0) goto err;
1144 BIO_printf(bio_err,"\n");
1145 if (!BN_add_word(serial,1)) goto err;
1146 if (!sk_X509_push(cert_sk,x))
1148 BIO_printf(bio_err,"Memory allocation failure\n");
1158 if (ss_cert_file != NULL)
1161 j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,attribs,
1162 db,serial,subj,multirdn,email_dn,startdate,enddate,days,batch,
1163 extensions,conf,verbose, certopt, nameopt,
1164 default_op, ext_copy, e);
1165 if (j < 0) goto err;
1169 BIO_printf(bio_err,"\n");
1170 if (!BN_add_word(serial,1)) goto err;
1171 if (!sk_X509_push(cert_sk,x))
1173 BIO_printf(bio_err,"Memory allocation failure\n");
1181 j=certify(&x,infile,pkey,x509p,dgst,attribs,db,
1182 serial,subj,multirdn,email_dn,startdate,enddate,days,batch,
1183 extensions,conf,verbose, certopt, nameopt,
1184 default_op, ext_copy, selfsign);
1185 if (j < 0) goto err;
1189 BIO_printf(bio_err,"\n");
1190 if (!BN_add_word(serial,1)) goto err;
1191 if (!sk_X509_push(cert_sk,x))
1193 BIO_printf(bio_err,"Memory allocation failure\n");
1198 for (i=0; i<argc; i++)
1201 j=certify(&x,argv[i],pkey,x509p,dgst,attribs,db,
1202 serial,subj,multirdn,email_dn,startdate,enddate,days,batch,
1203 extensions,conf,verbose, certopt, nameopt,
1204 default_op, ext_copy, selfsign);
1205 if (j < 0) goto err;
1209 BIO_printf(bio_err,"\n");
1210 if (!BN_add_word(serial,1)) goto err;
1211 if (!sk_X509_push(cert_sk,x))
1213 BIO_printf(bio_err,"Memory allocation failure\n");
1218 /* we have a stack of newly certified certificates
1219 * and a data base and serial number that need
1222 if (sk_X509_num(cert_sk) > 0)
1226 BIO_printf(bio_err,"\n%d out of %d certificate requests certified, commit? [y/n]",total_done,total);
1227 (void)BIO_flush(bio_err);
1229 fgets(buf[0],10,stdin);
1230 if ((buf[0][0] != 'y') && (buf[0][0] != 'Y'))
1232 BIO_printf(bio_err,"CERTIFICATION CANCELED\n");
1238 BIO_printf(bio_err,"Write out database with %d new entries\n",sk_X509_num(cert_sk));
1240 if (!save_serial(serialfile,"new",serial,NULL)) goto err;
1242 if (!save_index(dbfile, "new", db)) goto err;
1246 BIO_printf(bio_err,"writing new certificates\n");
1247 for (i=0; i<sk_X509_num(cert_sk); i++)
1252 x=sk_X509_value(cert_sk,i);
1254 j=x->cert_info->serialNumber->length;
1255 p=(const char *)x->cert_info->serialNumber->data;
1257 if(strlen(outdir) >= (size_t)(j ? BSIZE-j*2-6 : BSIZE-8))
1259 BIO_printf(bio_err,"certificate file name too long\n");
1263 strcpy(buf[2],outdir);
1265 #ifndef OPENSSL_SYS_VMS
1266 BUF_strlcat(buf[2],"/",sizeof(buf[2]));
1269 n=(char *)&(buf[2][strlen(buf[2])]);
1274 if (n >= &(buf[2][sizeof(buf[2])]))
1277 &buf[2][0] + sizeof(buf[2]) - n,
1278 "%02X",(unsigned char)*(p++));
1287 *(n++)='.'; *(n++)='p'; *(n++)='e'; *(n++)='m';
1290 BIO_printf(bio_err,"writing %s\n",buf[2]);
1292 if (BIO_write_filename(Cout,buf[2]) <= 0)
1297 write_new_certificate(Cout,x, 0, notext);
1298 write_new_certificate(Sout,x, output_der, notext);
1301 if (sk_X509_num(cert_sk))
1303 /* Rename the database and the serial file */
1304 if (!rotate_serial(serialfile,"new","old")) goto err;
1306 if (!rotate_index(dbfile,"new","old")) goto err;
1308 BIO_printf(bio_err,"Data Base Updated\n");
1312 /*****************************************************************/
1318 crl_ext=NCONF_get_string(conf,section,ENV_CRLEXT);
1324 /* Check syntax of file */
1326 X509V3_set_ctx_test(&ctx);
1327 X509V3_set_nconf(&ctx, conf);
1328 if (!X509V3_EXT_add_nconf(conf, &ctx, crl_ext, NULL))
1331 "Error Loading CRL extension section %s\n",
1338 if ((crlnumberfile=NCONF_get_string(conf,section,ENV_CRLNUMBER))
1340 if ((crlnumber=load_serial(crlnumberfile,0,NULL)) == NULL)
1342 BIO_printf(bio_err,"error while loading CRL number\n");
1346 if (!crldays && !crlhours)
1348 if (!NCONF_get_number(conf,section,
1349 ENV_DEFAULT_CRL_DAYS, &crldays))
1351 if (!NCONF_get_number(conf,section,
1352 ENV_DEFAULT_CRL_HOURS, &crlhours))
1355 if ((crldays == 0) && (crlhours == 0))
1357 BIO_printf(bio_err,"cannot lookup how long until the next CRL is issued\n");
1361 if (verbose) BIO_printf(bio_err,"making CRL\n");
1362 if ((crl=X509_CRL_new()) == NULL) goto err;
1363 if (!X509_CRL_set_issuer_name(crl, X509_get_subject_name(x509))) goto err;
1365 tmptm = ASN1_TIME_new();
1366 if (!tmptm) goto err;
1367 X509_gmtime_adj(tmptm,0);
1368 X509_CRL_set_lastUpdate(crl, tmptm);
1369 X509_gmtime_adj(tmptm,(crldays*24+crlhours)*60*60);
1370 X509_CRL_set_nextUpdate(crl, tmptm);
1372 ASN1_TIME_free(tmptm);
1374 for (i=0; i<sk_num(db->db->data); i++)
1376 pp=(const char **)sk_value(db->db->data,i);
1377 if (pp[DB_type][0] == DB_TYPE_REV)
1379 if ((r=X509_REVOKED_new()) == NULL) goto err;
1380 j = make_revoked(r, pp[DB_rev_date]);
1382 if (j == 2) crl_v2 = 1;
1383 if (!BN_hex2bn(&serial, pp[DB_serial]))
1385 tmpser = BN_to_ASN1_INTEGER(serial, NULL);
1390 X509_REVOKED_set_serialNumber(r, tmpser);
1391 ASN1_INTEGER_free(tmpser);
1392 X509_CRL_add0_revoked(crl,r);
1396 /* sort the data so it will be written in serial
1400 /* we now have a CRL */
1401 if (verbose) BIO_printf(bio_err,"signing CRL\n");
1402 #ifndef OPENSSL_NO_DSA
1403 if (pkey->type == EVP_PKEY_DSA)
1407 #ifndef OPENSSL_NO_ECDSA
1408 if (pkey->type == EVP_PKEY_EC)
1412 /* Add any extensions asked for */
1414 if (crl_ext || crlnumberfile != NULL)
1417 X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0);
1418 X509V3_set_nconf(&crlctx, conf);
1421 if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx,
1422 crl_ext, crl)) goto err;
1423 if (crlnumberfile != NULL)
1425 tmpser = BN_to_ASN1_INTEGER(crlnumber, NULL);
1426 if (!tmpser) goto err;
1427 X509_CRL_add1_ext_i2d(crl,NID_crl_number,tmpser,0,0);
1428 ASN1_INTEGER_free(tmpser);
1430 if (!BN_add_word(crlnumber,1)) goto err;
1433 if (crl_ext || crl_v2)
1435 if (!X509_CRL_set_version(crl, 1))
1436 goto err; /* version 2 CRL */
1440 if (crlnumberfile != NULL) /* we have a CRL number that need updating */
1441 if (!save_serial(crlnumberfile,"new",crlnumber,NULL)) goto err;
1443 if (!X509_CRL_sign(crl,pkey,dgst)) goto err;
1445 PEM_write_bio_X509_CRL(Sout,crl);
1447 if (crlnumberfile != NULL) /* Rename the crlnumber file */
1448 if (!rotate_serial(crlnumberfile,"new","old")) goto err;
1451 /*****************************************************************/
1456 BIO_printf(bio_err,"no input files\n");
1462 revcert=load_cert(bio_err, infile, FORMAT_PEM,
1464 if (revcert == NULL)
1466 j=do_revoke(revcert,db, rev_type, rev_arg);
1467 if (j <= 0) goto err;
1470 if (!save_index(dbfile, "new", db)) goto err;
1472 if (!rotate_index(dbfile, "new", "old")) goto err;
1474 BIO_printf(bio_err,"Data Base Updated\n");
1477 /*****************************************************************/
1481 OPENSSL_free(tofree);
1488 sk_X509_pop_free(cert_sk,X509_free);
1490 if (ret) ERR_print_errors(bio_err);
1491 app_RAND_write_file(randfile, bio_err);
1492 if (free_key && key)
1496 EVP_PKEY_free(pkey);
1497 if (x509) X509_free(x509);
1505 static void lookup_fail(const char *name, const char *tag)
1507 BIO_printf(bio_err,"variable lookup failed for %s::%s\n",name,tag);
1510 static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1511 const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, CA_DB *db,
1512 BIGNUM *serial, char *subj, int multirdn, int email_dn, char *startdate, char *enddate,
1513 long days, int batch, char *ext_sect, CONF *lconf, int verbose,
1514 unsigned long certopt, unsigned long nameopt, int default_op,
1515 int ext_copy, int selfsign)
1519 EVP_PKEY *pktmp=NULL;
1522 in=BIO_new(BIO_s_file());
1524 if (BIO_read_filename(in,infile) <= 0)
1529 if ((req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL)) == NULL)
1531 BIO_printf(bio_err,"Error reading certificate request in %s\n",
1536 X509_REQ_print(bio_err,req);
1538 BIO_printf(bio_err,"Check that the request matches the signature\n");
1540 if (selfsign && !X509_REQ_check_private_key(req,pkey))
1542 BIO_printf(bio_err,"Certificate request and CA private key do not match\n");
1546 if ((pktmp=X509_REQ_get_pubkey(req)) == NULL)
1548 BIO_printf(bio_err,"error unpacking public key\n");
1551 i=X509_REQ_verify(req,pktmp);
1552 EVP_PKEY_free(pktmp);
1556 BIO_printf(bio_err,"Signature verification problems....\n");
1562 BIO_printf(bio_err,"Signature did not match the certificate request\n");
1566 BIO_printf(bio_err,"Signature ok\n");
1568 ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj, multirdn, email_dn,
1569 startdate,enddate,days,batch,verbose,req,ext_sect,lconf,
1570 certopt, nameopt, default_op, ext_copy, selfsign);
1573 if (req != NULL) X509_REQ_free(req);
1574 if (in != NULL) BIO_free(in);
1578 static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1579 const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, CA_DB *db,
1580 BIGNUM *serial, char *subj, int multirdn, int email_dn, char *startdate, char *enddate,
1581 long days, int batch, char *ext_sect, CONF *lconf, int verbose,
1582 unsigned long certopt, unsigned long nameopt, int default_op,
1583 int ext_copy, ENGINE *e)
1586 X509_REQ *rreq=NULL;
1587 EVP_PKEY *pktmp=NULL;
1590 if ((req=load_cert(bio_err, infile, FORMAT_PEM, NULL, e, infile)) == NULL)
1593 X509_print(bio_err,req);
1595 BIO_printf(bio_err,"Check that the request matches the signature\n");
1597 if ((pktmp=X509_get_pubkey(req)) == NULL)
1599 BIO_printf(bio_err,"error unpacking public key\n");
1602 i=X509_verify(req,pktmp);
1603 EVP_PKEY_free(pktmp);
1607 BIO_printf(bio_err,"Signature verification problems....\n");
1613 BIO_printf(bio_err,"Signature did not match the certificate\n");
1617 BIO_printf(bio_err,"Signature ok\n");
1619 if ((rreq=X509_to_X509_REQ(req,NULL,EVP_md5())) == NULL)
1622 ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,multirdn,email_dn,startdate,enddate,
1623 days,batch,verbose,rreq,ext_sect,lconf, certopt, nameopt, default_op,
1627 if (rreq != NULL) X509_REQ_free(rreq);
1628 if (req != NULL) X509_free(req);
1632 static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
1633 STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, char *subj,
1635 int email_dn, char *startdate, char *enddate, long days, int batch,
1636 int verbose, X509_REQ *req, char *ext_sect, CONF *lconf,
1637 unsigned long certopt, unsigned long nameopt, int default_op,
1638 int ext_copy, int selfsign)
1640 X509_NAME *name=NULL,*CAname=NULL,*subject=NULL, *dn_subject=NULL;
1641 ASN1_UTCTIME *tm,*tmptm;
1642 ASN1_STRING *str,*str2;
1646 X509_NAME_ENTRY *ne;
1647 X509_NAME_ENTRY *tne,*push;
1649 int ok= -1,i,j,last,nid;
1652 char *row[DB_NUMBER],**rrow=NULL,**irow=NULL;
1655 tmptm=ASN1_UTCTIME_new();
1658 BIO_printf(bio_err,"malloc error\n");
1662 for (i=0; i<DB_NUMBER; i++)
1667 X509_NAME *n = parse_name(subj, MBSTRING_ASC, multirdn);
1671 ERR_print_errors(bio_err);
1674 X509_REQ_set_subject_name(req,n);
1675 req->req_info->enc.modified = 1;
1680 BIO_printf(bio_err,"The Subject's Distinguished Name is as follows\n");
1682 name=X509_REQ_get_subject_name(req);
1683 for (i=0; i<X509_NAME_entry_count(name); i++)
1685 ne= X509_NAME_get_entry(name,i);
1686 str=X509_NAME_ENTRY_get_data(ne);
1687 obj=X509_NAME_ENTRY_get_object(ne);
1691 /* assume all type should be strings */
1692 nid=OBJ_obj2nid(ne->object);
1694 if (str->type == V_ASN1_UNIVERSALSTRING)
1695 ASN1_UNIVERSALSTRING_to_string(str);
1697 if ((str->type == V_ASN1_IA5STRING) &&
1698 (nid != NID_pkcs9_emailAddress))
1699 str->type=V_ASN1_T61STRING;
1701 if ((nid == NID_pkcs9_emailAddress) &&
1702 (str->type == V_ASN1_PRINTABLESTRING))
1703 str->type=V_ASN1_IA5STRING;
1706 /* If no EMAIL is wanted in the subject */
1707 if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) && (!email_dn))
1710 /* check some things */
1711 if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) &&
1712 (str->type != V_ASN1_IA5STRING))
1714 BIO_printf(bio_err,"\nemailAddress type needs to be of type IA5STRING\n");
1717 if ((str->type != V_ASN1_BMPSTRING) && (str->type != V_ASN1_UTF8STRING))
1719 j=ASN1_PRINTABLE_type(str->data,str->length);
1720 if ( ((j == V_ASN1_T61STRING) &&
1721 (str->type != V_ASN1_T61STRING)) ||
1722 ((j == V_ASN1_IA5STRING) &&
1723 (str->type == V_ASN1_PRINTABLESTRING)))
1725 BIO_printf(bio_err,"\nThe string contains characters that are illegal for the ASN.1 type\n");
1731 old_entry_print(bio_err, obj, str);
1734 /* Ok, now we check the 'policy' stuff. */
1735 if ((subject=X509_NAME_new()) == NULL)
1737 BIO_printf(bio_err,"Memory allocation failure\n");
1741 /* take a copy of the issuer name before we mess with it. */
1743 CAname=X509_NAME_dup(name);
1745 CAname=X509_NAME_dup(x509->cert_info->subject);
1746 if (CAname == NULL) goto err;
1749 for (i=0; i<sk_CONF_VALUE_num(policy); i++)
1751 cv=sk_CONF_VALUE_value(policy,i); /* get the object id */
1752 if ((j=OBJ_txt2nid(cv->name)) == NID_undef)
1754 BIO_printf(bio_err,"%s:unknown object type in 'policy' configuration\n",cv->name);
1762 /* lookup the object in the supplied name list */
1763 j=X509_NAME_get_index_by_OBJ(name,obj,last);
1766 if (last != -1) break;
1771 tne=X509_NAME_get_entry(name,j);
1775 /* depending on the 'policy', decide what to do. */
1777 if (strcmp(cv->value,"optional") == 0)
1782 else if (strcmp(cv->value,"supplied") == 0)
1786 BIO_printf(bio_err,"The %s field needed to be supplied and was missing\n",cv->name);
1792 else if (strcmp(cv->value,"match") == 0)
1798 BIO_printf(bio_err,"The mandatory %s field was missing\n",cv->name);
1805 j=X509_NAME_get_index_by_OBJ(CAname,obj,last2);
1806 if ((j < 0) && (last2 == -1))
1808 BIO_printf(bio_err,"The %s field does not exist in the CA certificate,\nthe 'policy' is misconfigured\n",cv->name);
1813 push=X509_NAME_get_entry(CAname,j);
1814 str=X509_NAME_ENTRY_get_data(tne);
1815 str2=X509_NAME_ENTRY_get_data(push);
1817 if (ASN1_STRING_cmp(str,str2) != 0)
1822 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));
1828 BIO_printf(bio_err,"%s:invalid type in 'policy' configuration\n",cv->value);
1834 if (!X509_NAME_add_entry(subject,push, -1, 0))
1837 X509_NAME_ENTRY_free(push);
1838 BIO_printf(bio_err,"Memory allocation failure\n");
1848 X509_NAME_free(subject);
1849 /* subject=X509_NAME_dup(X509_REQ_get_subject_name(req)); */
1850 subject=X509_NAME_dup(name);
1851 if (subject == NULL) goto err;
1855 BIO_printf(bio_err,"The subject name appears to be ok, checking data base for clashes\n");
1857 /* Build the correct Subject if no e-mail is wanted in the subject */
1858 /* and add it later on because of the method extensions are added (altName) */
1861 dn_subject = subject;
1864 X509_NAME_ENTRY *tmpne;
1865 /* Its best to dup the subject DN and then delete any email
1866 * addresses because this retains its structure.
1868 if (!(dn_subject = X509_NAME_dup(subject)))
1870 BIO_printf(bio_err,"Memory allocation failure\n");
1873 while((i = X509_NAME_get_index_by_NID(dn_subject,
1874 NID_pkcs9_emailAddress, -1)) >= 0)
1876 tmpne = X509_NAME_get_entry(dn_subject, i);
1877 X509_NAME_delete_entry(dn_subject, i);
1878 X509_NAME_ENTRY_free(tmpne);
1882 if (BN_is_zero(serial))
1883 row[DB_serial]=BUF_strdup("00");
1885 row[DB_serial]=BN_bn2hex(serial);
1886 if (row[DB_serial] == NULL)
1888 BIO_printf(bio_err,"Memory allocation failure\n");
1892 if (db->attributes.unique_subject)
1894 rrow=TXT_DB_get_by_index(db->db,DB_name,row);
1898 "ERROR:There is already a certificate for %s\n",
1904 rrow=TXT_DB_get_by_index(db->db,DB_serial,row);
1907 BIO_printf(bio_err,"ERROR:Serial number %s has already been issued,\n",
1909 BIO_printf(bio_err," check the database/serial_file for corruption\n");
1916 "The matching entry has the following details\n");
1917 if (rrow[DB_type][0] == 'E')
1919 else if (rrow[DB_type][0] == 'R')
1921 else if (rrow[DB_type][0] == 'V')
1924 p="\ninvalid type, Data base error\n";
1925 BIO_printf(bio_err,"Type :%s\n",p);;
1926 if (rrow[DB_type][0] == 'R')
1928 p=rrow[DB_exp_date]; if (p == NULL) p="undef";
1929 BIO_printf(bio_err,"Was revoked on:%s\n",p);
1931 p=rrow[DB_exp_date]; if (p == NULL) p="undef";
1932 BIO_printf(bio_err,"Expires on :%s\n",p);
1933 p=rrow[DB_serial]; if (p == NULL) p="undef";
1934 BIO_printf(bio_err,"Serial Number :%s\n",p);
1935 p=rrow[DB_file]; if (p == NULL) p="undef";
1936 BIO_printf(bio_err,"File name :%s\n",p);
1937 p=rrow[DB_name]; if (p == NULL) p="undef";
1938 BIO_printf(bio_err,"Subject Name :%s\n",p);
1939 ok= -1; /* This is now a 'bad' error. */
1943 /* We are now totally happy, lets make and sign the certificate */
1945 BIO_printf(bio_err,"Everything appears to be ok, creating and signing the certificate\n");
1947 if ((ret=X509_new()) == NULL) goto err;
1951 /* Make it an X509 v3 certificate. */
1952 if (!X509_set_version(ret,2)) goto err;
1955 if (BN_to_ASN1_INTEGER(serial,ci->serialNumber) == NULL)
1959 if (!X509_set_issuer_name(ret,subject))
1964 if (!X509_set_issuer_name(ret,X509_get_subject_name(x509)))
1968 if (strcmp(startdate,"today") == 0)
1969 X509_gmtime_adj(X509_get_notBefore(ret),0);
1970 else ASN1_UTCTIME_set_string(X509_get_notBefore(ret),startdate);
1972 if (enddate == NULL)
1973 X509_gmtime_adj(X509_get_notAfter(ret),(long)60*60*24*days);
1974 else ASN1_UTCTIME_set_string(X509_get_notAfter(ret),enddate);
1976 if (!X509_set_subject_name(ret,subject)) goto err;
1978 pktmp=X509_REQ_get_pubkey(req);
1979 i = X509_set_pubkey(ret,pktmp);
1980 EVP_PKEY_free(pktmp);
1983 /* Lets add the extensions, if there are any */
1987 if (ci->version == NULL)
1988 if ((ci->version=ASN1_INTEGER_new()) == NULL)
1990 ASN1_INTEGER_set(ci->version,2); /* version 3 certificate */
1992 /* Free the current entries if any, there should not
1993 * be any I believe */
1994 if (ci->extensions != NULL)
1995 sk_X509_EXTENSION_pop_free(ci->extensions,
1996 X509_EXTENSION_free);
1998 ci->extensions = NULL;
2000 /* Initialize the context structure */
2002 X509V3_set_ctx(&ctx, ret, ret, req, NULL, 0);
2004 X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0);
2009 BIO_printf(bio_err, "Extra configuration file found\n");
2011 /* Use the extconf configuration db LHASH */
2012 X509V3_set_nconf(&ctx, extconf);
2014 /* Test the structure (needed?) */
2015 /* X509V3_set_ctx_test(&ctx); */
2017 /* Adds exts contained in the configuration file */
2018 if (!X509V3_EXT_add_nconf(extconf, &ctx, ext_sect,ret))
2021 "ERROR: adding extensions in section %s\n",
2023 ERR_print_errors(bio_err);
2027 BIO_printf(bio_err, "Successfully added extensions from file.\n");
2031 /* We found extensions to be set from config file */
2032 X509V3_set_nconf(&ctx, lconf);
2034 if(!X509V3_EXT_add_nconf(lconf, &ctx, ext_sect, ret))
2036 BIO_printf(bio_err, "ERROR: adding extensions in section %s\n", ext_sect);
2037 ERR_print_errors(bio_err);
2042 BIO_printf(bio_err, "Successfully added extensions from config\n");
2046 /* Copy extensions from request (if any) */
2048 if (!copy_extensions(ret, req, ext_copy))
2050 BIO_printf(bio_err, "ERROR: adding extensions from request\n");
2051 ERR_print_errors(bio_err);
2055 /* Set the right value for the noemailDN option */
2058 if (!X509_set_subject_name(ret,dn_subject)) goto err;
2063 BIO_printf(bio_err, "Certificate Details:\n");
2064 /* Never print signature details because signature not present */
2065 certopt |= X509_FLAG_NO_SIGDUMP | X509_FLAG_NO_SIGNAME;
2066 X509_print_ex(bio_err, ret, nameopt, certopt);
2069 BIO_printf(bio_err,"Certificate is to be certified until ");
2070 ASN1_UTCTIME_print(bio_err,X509_get_notAfter(ret));
2071 if (days) BIO_printf(bio_err," (%ld days)",days);
2072 BIO_printf(bio_err, "\n");
2077 BIO_printf(bio_err,"Sign the certificate? [y/n]:");
2078 (void)BIO_flush(bio_err);
2080 fgets(buf,sizeof(buf)-1,stdin);
2081 if (!((buf[0] == 'y') || (buf[0] == 'Y')))
2083 BIO_printf(bio_err,"CERTIFICATE WILL NOT BE CERTIFIED\n");
2090 #ifndef OPENSSL_NO_DSA
2091 if (pkey->type == EVP_PKEY_DSA) dgst=EVP_dss1();
2092 pktmp=X509_get_pubkey(ret);
2093 if (EVP_PKEY_missing_parameters(pktmp) &&
2094 !EVP_PKEY_missing_parameters(pkey))
2095 EVP_PKEY_copy_parameters(pktmp,pkey);
2096 EVP_PKEY_free(pktmp);
2098 #ifndef OPENSSL_NO_ECDSA
2099 if (pkey->type == EVP_PKEY_EC)
2101 pktmp = X509_get_pubkey(ret);
2102 if (EVP_PKEY_missing_parameters(pktmp) &&
2103 !EVP_PKEY_missing_parameters(pkey))
2104 EVP_PKEY_copy_parameters(pktmp, pkey);
2105 EVP_PKEY_free(pktmp);
2109 if (!X509_sign(ret,pkey,dgst))
2112 /* We now just add it to the database */
2113 row[DB_type]=(char *)OPENSSL_malloc(2);
2115 tm=X509_get_notAfter(ret);
2116 row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
2117 memcpy(row[DB_exp_date],tm->data,tm->length);
2118 row[DB_exp_date][tm->length]='\0';
2120 row[DB_rev_date]=NULL;
2122 /* row[DB_serial] done already */
2123 row[DB_file]=(char *)OPENSSL_malloc(8);
2124 row[DB_name]=X509_NAME_oneline(X509_get_subject_name(ret),NULL,0);
2126 if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2127 (row[DB_file] == NULL) || (row[DB_name] == NULL))
2129 BIO_printf(bio_err,"Memory allocation failure\n");
2132 BUF_strlcpy(row[DB_file],"unknown",8);
2133 row[DB_type][0]='V';
2134 row[DB_type][1]='\0';
2136 if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
2138 BIO_printf(bio_err,"Memory allocation failure\n");
2142 for (i=0; i<DB_NUMBER; i++)
2147 irow[DB_NUMBER]=NULL;
2149 if (!TXT_DB_insert(db->db,irow))
2151 BIO_printf(bio_err,"failed to update database\n");
2152 BIO_printf(bio_err,"TXT_DB error number %ld\n",db->db->error);
2157 for (i=0; i<DB_NUMBER; i++)
2158 if (row[i] != NULL) OPENSSL_free(row[i]);
2161 X509_NAME_free(CAname);
2162 if (subject != NULL)
2163 X509_NAME_free(subject);
2164 if ((dn_subject != NULL) && !email_dn)
2165 X509_NAME_free(dn_subject);
2167 ASN1_UTCTIME_free(tmptm);
2170 if (ret != NULL) X509_free(ret);
2178 static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext)
2183 (void)i2d_X509_bio(bp,x);
2187 /* ??? Not needed since X509_print prints all this stuff anyway */
2188 f=X509_NAME_oneline(X509_get_issuer_name(x),buf,256);
2189 BIO_printf(bp,"issuer :%s\n",f);
2191 f=X509_NAME_oneline(X509_get_subject_name(x),buf,256);
2192 BIO_printf(bp,"subject:%s\n",f);
2194 BIO_puts(bp,"serial :");
2195 i2a_ASN1_INTEGER(bp,x->cert_info->serialNumber);
2196 BIO_puts(bp,"\n\n");
2198 if (!notext)X509_print(bp,x);
2199 PEM_write_bio_X509(bp,x);
2202 static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
2203 const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, CA_DB *db,
2204 BIGNUM *serial, char *subj, int multirdn, int email_dn, char *startdate, char *enddate,
2205 long days, char *ext_sect, CONF *lconf, int verbose, unsigned long certopt,
2206 unsigned long nameopt, int default_op, int ext_copy)
2208 STACK_OF(CONF_VALUE) *sk=NULL;
2211 CONF_VALUE *cv=NULL;
2212 NETSCAPE_SPKI *spki = NULL;
2215 EVP_PKEY *pktmp=NULL;
2217 X509_NAME_ENTRY *ne=NULL;
2223 * Load input file into a hash table. (This is just an easy
2224 * way to read and parse the file, then put it into a convenient
2227 parms=CONF_load(NULL,infile,&errline);
2230 BIO_printf(bio_err,"error on line %ld of %s\n",errline,infile);
2231 ERR_print_errors(bio_err);
2235 sk=CONF_get_section(parms, "default");
2236 if (sk_CONF_VALUE_num(sk) == 0)
2238 BIO_printf(bio_err, "no name/value pairs found in %s\n", infile);
2244 * Now create a dummy X509 request structure. We don't actually
2245 * have an X509 request, but we have many of the components
2246 * (a public key, various DN components). The idea is that we
2247 * put these components into the right X509 request structure
2248 * and we can use the same code as if you had a real X509 request.
2253 ERR_print_errors(bio_err);
2258 * Build up the subject name set.
2265 if (sk_CONF_VALUE_num(sk) <= i) break;
2267 cv=sk_CONF_VALUE_value(sk,i);
2269 /* Skip past any leading X. X: X, etc to allow for
2270 * multiple instances
2272 for (buf = cv->name; *buf ; buf++)
2273 if ((*buf == ':') || (*buf == ',') || (*buf == '.'))
2276 if (*buf) type = buf;
2281 if ((nid=OBJ_txt2nid(type)) == NID_undef)
2283 if (strcmp(type, "SPKAC") == 0)
2285 spki = NETSCAPE_SPKI_b64_decode(cv->value, -1);
2288 BIO_printf(bio_err,"unable to load Netscape SPKAC structure\n");
2289 ERR_print_errors(bio_err);
2297 if ((nid == NID_pkcs9_emailAddress) && (email_dn == 0))
2301 j=ASN1_PRINTABLE_type((unsigned char *)buf,-1);
2302 if (fix_data(nid, &j) == 0)
2305 "invalid characters in string %s\n",buf);
2309 if ((ne=X509_NAME_ENTRY_create_by_NID(&ne,nid,j,
2310 (unsigned char *)buf,
2311 strlen(buf))) == NULL)
2314 if (!X509_NAME_add_entry(n,ne,-1, 0)) goto err;
2318 BIO_printf(bio_err,"Netscape SPKAC structure not found in %s\n",
2324 * Now extract the key from the SPKI structure.
2327 BIO_printf(bio_err,"Check that the SPKAC request matches the signature\n");
2329 if ((pktmp=NETSCAPE_SPKI_get_pubkey(spki)) == NULL)
2331 BIO_printf(bio_err,"error unpacking SPKAC public key\n");
2335 j = NETSCAPE_SPKI_verify(spki, pktmp);
2338 BIO_printf(bio_err,"signature verification failed on SPKAC public key\n");
2341 BIO_printf(bio_err,"Signature ok\n");
2343 X509_REQ_set_pubkey(req,pktmp);
2344 EVP_PKEY_free(pktmp);
2345 ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,multirdn,email_dn,startdate,enddate,
2346 days,1,verbose,req,ext_sect,lconf, certopt, nameopt, default_op,
2349 if (req != NULL) X509_REQ_free(req);
2350 if (parms != NULL) CONF_free(parms);
2351 if (spki != NULL) NETSCAPE_SPKI_free(spki);
2352 if (ne != NULL) X509_NAME_ENTRY_free(ne);
2357 static int fix_data(int nid, int *type)
2359 if (nid == NID_pkcs9_emailAddress)
2360 *type=V_ASN1_IA5STRING;
2361 if ((nid == NID_commonName) && (*type == V_ASN1_IA5STRING))
2362 *type=V_ASN1_T61STRING;
2363 if ((nid == NID_pkcs9_challengePassword) && (*type == V_ASN1_IA5STRING))
2364 *type=V_ASN1_T61STRING;
2365 if ((nid == NID_pkcs9_unstructuredName) && (*type == V_ASN1_T61STRING))
2367 if (nid == NID_pkcs9_unstructuredName)
2368 *type=V_ASN1_IA5STRING;
2372 static int check_time_format(char *str)
2376 tm.data=(unsigned char *)str;
2377 tm.length=strlen(str);
2378 tm.type=V_ASN1_UTCTIME;
2379 return(ASN1_UTCTIME_check(&tm));
2382 static int do_revoke(X509 *x509, CA_DB *db, int type, char *value)
2384 ASN1_UTCTIME *tm=NULL;
2385 char *row[DB_NUMBER],**rrow,**irow;
2386 char *rev_str = NULL;
2390 for (i=0; i<DB_NUMBER; i++)
2392 row[DB_name]=X509_NAME_oneline(X509_get_subject_name(x509),NULL,0);
2393 bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509),NULL);
2395 row[DB_serial]=BUF_strdup("00");
2397 row[DB_serial]=BN_bn2hex(bn);
2399 if ((row[DB_name] == NULL) || (row[DB_serial] == NULL))
2401 BIO_printf(bio_err,"Memory allocation failure\n");
2404 /* We have to lookup by serial number because name lookup
2405 * skips revoked certs
2407 rrow=TXT_DB_get_by_index(db->db,DB_serial,row);
2410 BIO_printf(bio_err,"Adding Entry with serial number %s to DB for %s\n", row[DB_serial], row[DB_name]);
2412 /* We now just add it to the database */
2413 row[DB_type]=(char *)OPENSSL_malloc(2);
2415 tm=X509_get_notAfter(x509);
2416 row[DB_exp_date]=(char *)OPENSSL_malloc(tm->length+1);
2417 memcpy(row[DB_exp_date],tm->data,tm->length);
2418 row[DB_exp_date][tm->length]='\0';
2420 row[DB_rev_date]=NULL;
2422 /* row[DB_serial] done already */
2423 row[DB_file]=(char *)OPENSSL_malloc(8);
2425 /* row[DB_name] done already */
2427 if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2428 (row[DB_file] == NULL))
2430 BIO_printf(bio_err,"Memory allocation failure\n");
2433 BUF_strlcpy(row[DB_file],"unknown",8);
2434 row[DB_type][0]='V';
2435 row[DB_type][1]='\0';
2437 if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
2439 BIO_printf(bio_err,"Memory allocation failure\n");
2443 for (i=0; i<DB_NUMBER; i++)
2448 irow[DB_NUMBER]=NULL;
2450 if (!TXT_DB_insert(db->db,irow))
2452 BIO_printf(bio_err,"failed to update database\n");
2453 BIO_printf(bio_err,"TXT_DB error number %ld\n",db->db->error);
2457 /* Revoke Certificate */
2458 ok = do_revoke(x509,db, type, value);
2463 else if (index_name_cmp((const char **)row,(const char **)rrow))
2465 BIO_printf(bio_err,"ERROR:name does not match %s\n",
2469 else if (rrow[DB_type][0]=='R')
2471 BIO_printf(bio_err,"ERROR:Already revoked, serial number %s\n",
2477 BIO_printf(bio_err,"Revoking Certificate %s.\n", rrow[DB_serial]);
2478 rev_str = make_revocation_str(type, value);
2481 BIO_printf(bio_err, "Error in revocation arguments\n");
2484 rrow[DB_type][0]='R';
2485 rrow[DB_type][1]='\0';
2486 rrow[DB_rev_date] = rev_str;
2490 for (i=0; i<DB_NUMBER; i++)
2493 OPENSSL_free(row[i]);
2498 static int get_certificate_status(const char *serial, CA_DB *db)
2500 char *row[DB_NUMBER],**rrow;
2503 /* Free Resources */
2504 for (i=0; i<DB_NUMBER; i++)
2507 /* Malloc needed char spaces */
2508 row[DB_serial] = OPENSSL_malloc(strlen(serial) + 2);
2509 if (row[DB_serial] == NULL)
2511 BIO_printf(bio_err,"Malloc failure\n");
2515 if (strlen(serial) % 2)
2517 /* Set the first char to 0 */;
2518 row[DB_serial][0]='0';
2520 /* Copy String from serial to row[DB_serial] */
2521 memcpy(row[DB_serial]+1, serial, strlen(serial));
2522 row[DB_serial][strlen(serial)+1]='\0';
2526 /* Copy String from serial to row[DB_serial] */
2527 memcpy(row[DB_serial], serial, strlen(serial));
2528 row[DB_serial][strlen(serial)]='\0';
2531 /* Make it Upper Case */
2532 for (i=0; row[DB_serial][i] != '\0'; i++)
2533 row[DB_serial][i] = toupper(row[DB_serial][i]);
2538 /* Search for the certificate */
2539 rrow=TXT_DB_get_by_index(db->db,DB_serial,row);
2542 BIO_printf(bio_err,"Serial %s not present in db.\n",
2547 else if (rrow[DB_type][0]=='V')
2549 BIO_printf(bio_err,"%s=Valid (%c)\n",
2550 row[DB_serial], rrow[DB_type][0]);
2553 else if (rrow[DB_type][0]=='R')
2555 BIO_printf(bio_err,"%s=Revoked (%c)\n",
2556 row[DB_serial], rrow[DB_type][0]);
2559 else if (rrow[DB_type][0]=='E')
2561 BIO_printf(bio_err,"%s=Expired (%c)\n",
2562 row[DB_serial], rrow[DB_type][0]);
2565 else if (rrow[DB_type][0]=='S')
2567 BIO_printf(bio_err,"%s=Suspended (%c)\n",
2568 row[DB_serial], rrow[DB_type][0]);
2573 BIO_printf(bio_err,"%s=Unknown (%c).\n",
2574 row[DB_serial], rrow[DB_type][0]);
2578 for (i=0; i<DB_NUMBER; i++)
2581 OPENSSL_free(row[i]);
2586 static int do_updatedb (CA_DB *db)
2588 ASN1_UTCTIME *a_tm = NULL;
2590 int db_y2k, a_y2k; /* flags = 1 if y >= 2000 */
2591 char **rrow, *a_tm_s;
2593 a_tm = ASN1_UTCTIME_new();
2595 /* get actual time and make a string */
2596 a_tm = X509_gmtime_adj(a_tm, 0);
2597 a_tm_s = (char *) OPENSSL_malloc(a_tm->length+1);
2604 memcpy(a_tm_s, a_tm->data, a_tm->length);
2605 a_tm_s[a_tm->length] = '\0';
2607 if (strncmp(a_tm_s, "49", 2) <= 0)
2612 for (i = 0; i < sk_num(db->db->data); i++)
2614 rrow = (char **) sk_value(db->db->data, i);
2616 if (rrow[DB_type][0] == 'V')
2618 /* ignore entries that are not valid */
2619 if (strncmp(rrow[DB_exp_date], "49", 2) <= 0)
2624 if (db_y2k == a_y2k)
2626 /* all on the same y2k side */
2627 if (strcmp(rrow[DB_exp_date], a_tm_s) <= 0)
2629 rrow[DB_type][0] = 'E';
2630 rrow[DB_type][1] = '\0';
2633 BIO_printf(bio_err, "%s=Expired\n",
2637 else if (db_y2k < a_y2k)
2639 rrow[DB_type][0] = 'E';
2640 rrow[DB_type][1] = '\0';
2643 BIO_printf(bio_err, "%s=Expired\n",
2652 ASN1_UTCTIME_free(a_tm);
2653 OPENSSL_free(a_tm_s);
2658 static const char *crl_reasons[] = {
2659 /* CRL reason strings */
2663 "affiliationChanged",
2665 "cessationOfOperation",
2668 /* Additional pseudo reasons */
2674 #define NUM_REASONS (sizeof(crl_reasons) / sizeof(char *))
2676 /* Given revocation information convert to a DB string.
2677 * The format of the string is:
2678 * revtime[,reason,extra]. Where 'revtime' is the
2679 * revocation time (the current time). 'reason' is the
2680 * optional CRL reason and 'extra' is any additional
2684 char *make_revocation_str(int rev_type, char *rev_arg)
2686 char *other = NULL, *str;
2687 const char *reason = NULL;
2689 ASN1_UTCTIME *revtm = NULL;
2696 case REV_CRL_REASON:
2697 for (i = 0; i < 8; i++)
2699 if (!strcasecmp(rev_arg, crl_reasons[i]))
2701 reason = crl_reasons[i];
2707 BIO_printf(bio_err, "Unknown CRL reason %s\n", rev_arg);
2713 /* Argument is an OID */
2715 otmp = OBJ_txt2obj(rev_arg, 0);
2716 ASN1_OBJECT_free(otmp);
2720 BIO_printf(bio_err, "Invalid object identifier %s\n", rev_arg);
2724 reason = "holdInstruction";
2728 case REV_KEY_COMPROMISE:
2729 case REV_CA_COMPROMISE:
2731 /* Argument is the key compromise time */
2732 if (!ASN1_GENERALIZEDTIME_set_string(NULL, rev_arg))
2734 BIO_printf(bio_err, "Invalid time format %s. Need YYYYMMDDHHMMSSZ\n", rev_arg);
2738 if (rev_type == REV_KEY_COMPROMISE)
2741 reason = "CAkeyTime";
2747 revtm = X509_gmtime_adj(NULL, 0);
2749 i = revtm->length + 1;
2751 if (reason) i += strlen(reason) + 1;
2752 if (other) i += strlen(other) + 1;
2754 str = OPENSSL_malloc(i);
2756 if (!str) return NULL;
2758 BUF_strlcpy(str, (char *)revtm->data, i);
2761 BUF_strlcat(str, ",", i);
2762 BUF_strlcat(str, reason, i);
2766 BUF_strlcat(str, ",", i);
2767 BUF_strlcat(str, other, i);
2769 ASN1_UTCTIME_free(revtm);
2773 /* Convert revocation field to X509_REVOKED entry
2777 * 2 OK and some extensions added (i.e. V2 CRL)
2781 int make_revoked(X509_REVOKED *rev, const char *str)
2784 int reason_code = -1;
2786 ASN1_OBJECT *hold = NULL;
2787 ASN1_GENERALIZEDTIME *comp_time = NULL;
2788 ASN1_ENUMERATED *rtmp = NULL;
2790 ASN1_TIME *revDate = NULL;
2792 i = unpack_revinfo(&revDate, &reason_code, &hold, &comp_time, str);
2797 if (rev && !X509_REVOKED_set_revocationDate(rev, revDate))
2800 if (rev && (reason_code != OCSP_REVOKED_STATUS_NOSTATUS))
2802 rtmp = ASN1_ENUMERATED_new();
2803 if (!rtmp || !ASN1_ENUMERATED_set(rtmp, reason_code))
2805 if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0))
2809 if (rev && comp_time)
2811 if (!X509_REVOKED_add1_ext_i2d(rev, NID_invalidity_date, comp_time, 0, 0))
2816 if (!X509_REVOKED_add1_ext_i2d(rev, NID_hold_instruction_code, hold, 0, 0))
2820 if (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)
2826 if (tmp) OPENSSL_free(tmp);
2827 ASN1_OBJECT_free(hold);
2828 ASN1_GENERALIZEDTIME_free(comp_time);
2829 ASN1_ENUMERATED_free(rtmp);
2830 ASN1_TIME_free(revDate);
2835 int old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str)
2837 char buf[25],*pbuf, *p;
2839 j=i2a_ASN1_OBJECT(bp,obj);
2841 for (j=22-j; j>0; j--)
2847 if (str->type == V_ASN1_PRINTABLESTRING)
2848 BIO_printf(bp,"PRINTABLE:'");
2849 else if (str->type == V_ASN1_T61STRING)
2850 BIO_printf(bp,"T61STRING:'");
2851 else if (str->type == V_ASN1_IA5STRING)
2852 BIO_printf(bp,"IA5STRING:'");
2853 else if (str->type == V_ASN1_UNIVERSALSTRING)
2854 BIO_printf(bp,"UNIVERSALSTRING:'");
2856 BIO_printf(bp,"ASN.1 %2d:'",str->type);
2858 p=(char *)str->data;
2859 for (j=str->length; j>0; j--)
2861 if ((*p >= ' ') && (*p <= '~'))
2862 BIO_printf(bp,"%c",*p);
2864 BIO_printf(bp,"\\0x%02X",*p);
2865 else if ((unsigned char)*p == 0xf7)
2866 BIO_printf(bp,"^?");
2867 else BIO_printf(bp,"^%c",*p+'@');
2870 BIO_printf(bp,"'\n");
2874 int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, ASN1_GENERALIZEDTIME **pinvtm, const char *str)
2877 char *rtime_str, *reason_str = NULL, *arg_str = NULL, *p;
2878 int reason_code = -1;
2881 ASN1_OBJECT *hold = NULL;
2882 ASN1_GENERALIZEDTIME *comp_time = NULL;
2883 tmp = BUF_strdup(str);
2885 p = strchr(tmp, ',');
2904 *prevtm = ASN1_UTCTIME_new();
2905 if (!ASN1_UTCTIME_set_string(*prevtm, rtime_str))
2907 BIO_printf(bio_err, "invalid revocation date %s\n", rtime_str);
2913 for (i = 0; i < NUM_REASONS; i++)
2915 if(!strcasecmp(reason_str, crl_reasons[i]))
2921 if (reason_code == OCSP_REVOKED_STATUS_NOSTATUS)
2923 BIO_printf(bio_err, "invalid reason code %s\n", reason_str);
2927 if (reason_code == 7)
2928 reason_code = OCSP_REVOKED_STATUS_REMOVEFROMCRL;
2929 else if (reason_code == 8) /* Hold instruction */
2933 BIO_printf(bio_err, "missing hold instruction\n");
2936 reason_code = OCSP_REVOKED_STATUS_CERTIFICATEHOLD;
2937 hold = OBJ_txt2obj(arg_str, 0);
2941 BIO_printf(bio_err, "invalid object identifier %s\n", arg_str);
2944 if (phold) *phold = hold;
2946 else if ((reason_code == 9) || (reason_code == 10))
2950 BIO_printf(bio_err, "missing compromised time\n");
2953 comp_time = ASN1_GENERALIZEDTIME_new();
2954 if (!ASN1_GENERALIZEDTIME_set_string(comp_time, arg_str))
2956 BIO_printf(bio_err, "invalid compromised time %s\n", arg_str);
2959 if (reason_code == 9)
2960 reason_code = OCSP_REVOKED_STATUS_KEYCOMPROMISE;
2962 reason_code = OCSP_REVOKED_STATUS_CACOMPROMISE;
2966 if (preason) *preason = reason_code;
2967 if (pinvtm) *pinvtm = comp_time;
2968 else ASN1_GENERALIZEDTIME_free(comp_time);
2974 if (tmp) OPENSSL_free(tmp);
2975 if (!phold) ASN1_OBJECT_free(hold);
2976 if (!pinvtm) ASN1_GENERALIZEDTIME_free(comp_time);