155714Skris/* apps/ca.c */
255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
355714Skris * All rights reserved.
455714Skris *
555714Skris * This package is an SSL implementation written
655714Skris * by Eric Young (eay@cryptsoft.com).
755714Skris * The implementation was written so as to conform with Netscapes SSL.
8296341Sdelphij *
955714Skris * This library is free for commercial and non-commercial use as long as
1055714Skris * the following conditions are aheared to.  The following conditions
1155714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1255714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1355714Skris * included with this distribution is covered by the same copyright terms
1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15296341Sdelphij *
1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1755714Skris * the code are not to be removed.
1855714Skris * If this package is used in a product, Eric Young should be given attribution
1955714Skris * as the author of the parts of the library used.
2055714Skris * This can be in the form of a textual message at program startup or
2155714Skris * in documentation (online or textual) provided with the package.
22296341Sdelphij *
2355714Skris * Redistribution and use in source and binary forms, with or without
2455714Skris * modification, are permitted provided that the following conditions
2555714Skris * are met:
2655714Skris * 1. Redistributions of source code must retain the copyright
2755714Skris *    notice, this list of conditions and the following disclaimer.
2855714Skris * 2. Redistributions in binary form must reproduce the above copyright
2955714Skris *    notice, this list of conditions and the following disclaimer in the
3055714Skris *    documentation and/or other materials provided with the distribution.
3155714Skris * 3. All advertising materials mentioning features or use of this software
3255714Skris *    must display the following acknowledgement:
3355714Skris *    "This product includes cryptographic software written by
3455714Skris *     Eric Young (eay@cryptsoft.com)"
3555714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3655714Skris *    being used are not cryptographic related :-).
37296341Sdelphij * 4. If you include any Windows specific code (or a derivative thereof) from
3855714Skris *    the apps directory (application code) you must include an acknowledgement:
3955714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40296341Sdelphij *
4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4455714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5155714Skris * SUCH DAMAGE.
52296341Sdelphij *
5355714Skris * The licence and distribution terms for any publically available version or
5455714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5555714Skris * copied and put under another distribution licence
5655714Skris * [including the GNU Public Licence.]
5755714Skris */
5855714Skris
5955714Skris/* The PPKI stuff has been donated by Jeff Barber <jeffb@issl.atl.hp.com> */
6055714Skris
6155714Skris#include <stdio.h>
6255714Skris#include <stdlib.h>
6355714Skris#include <string.h>
64109998Smarkm#include <ctype.h>
6555714Skris#include <sys/types.h>
6655714Skris#include <openssl/conf.h>
6755714Skris#include <openssl/bio.h>
6855714Skris#include <openssl/err.h>
6955714Skris#include <openssl/bn.h>
7055714Skris#include <openssl/txt_db.h>
7155714Skris#include <openssl/evp.h>
7255714Skris#include <openssl/x509.h>
7355714Skris#include <openssl/x509v3.h>
7455714Skris#include <openssl/objects.h>
75109998Smarkm#include <openssl/ocsp.h>
7655714Skris#include <openssl/pem.h>
7755714Skris
7855714Skris#ifndef W_OK
79296341Sdelphij# ifdef OPENSSL_SYS_VMS
80296341Sdelphij#  if defined(__DECC)
81296341Sdelphij#   include <unistd.h>
82296341Sdelphij#  else
83296341Sdelphij#   include <unixlib.h>
8455714Skris#  endif
85296341Sdelphij# elif !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_NETWARE)
86296341Sdelphij#  include <sys/file.h>
87296341Sdelphij# endif
8855714Skris#endif
8955714Skris
90109998Smarkm#include "apps.h"
91109998Smarkm
9255714Skris#ifndef W_OK
93296341Sdelphij# define F_OK 0
94296341Sdelphij# define X_OK 1
95296341Sdelphij# define W_OK 2
96296341Sdelphij# define R_OK 4
9755714Skris#endif
9855714Skris
9955714Skris#undef PROG
10055714Skris#define PROG ca_main
10155714Skris
102296341Sdelphij#define BASE_SECTION    "ca"
10355714Skris#define CONFIG_FILE "openssl.cnf"
10455714Skris
105296341Sdelphij#define ENV_DEFAULT_CA          "default_ca"
10655714Skris
107296341Sdelphij#define STRING_MASK     "string_mask"
108296341Sdelphij#define UTF8_IN                 "utf8"
109160814Ssimon
110296341Sdelphij#define ENV_DIR                 "dir"
111296341Sdelphij#define ENV_CERTS               "certs"
112296341Sdelphij#define ENV_CRL_DIR             "crl_dir"
113296341Sdelphij#define ENV_CA_DB               "CA_DB"
114296341Sdelphij#define ENV_NEW_CERTS_DIR       "new_certs_dir"
115296341Sdelphij#define ENV_CERTIFICATE         "certificate"
116296341Sdelphij#define ENV_SERIAL              "serial"
117296341Sdelphij#define ENV_CRLNUMBER           "crlnumber"
118296341Sdelphij#define ENV_CRL                 "crl"
119296341Sdelphij#define ENV_PRIVATE_KEY         "private_key"
120296341Sdelphij#define ENV_RANDFILE            "RANDFILE"
121296341Sdelphij#define ENV_DEFAULT_DAYS        "default_days"
122296341Sdelphij#define ENV_DEFAULT_STARTDATE   "default_startdate"
123296341Sdelphij#define ENV_DEFAULT_ENDDATE     "default_enddate"
124296341Sdelphij#define ENV_DEFAULT_CRL_DAYS    "default_crl_days"
125296341Sdelphij#define ENV_DEFAULT_CRL_HOURS   "default_crl_hours"
126296341Sdelphij#define ENV_DEFAULT_MD          "default_md"
127296341Sdelphij#define ENV_DEFAULT_EMAIL_DN    "email_in_dn"
128296341Sdelphij#define ENV_PRESERVE            "preserve"
129296341Sdelphij#define ENV_POLICY              "policy"
130296341Sdelphij#define ENV_EXTENSIONS          "x509_extensions"
131296341Sdelphij#define ENV_CRLEXT              "crl_extensions"
132296341Sdelphij#define ENV_MSIE_HACK           "msie_hack"
133296341Sdelphij#define ENV_NAMEOPT             "name_opt"
134296341Sdelphij#define ENV_CERTOPT             "cert_opt"
135296341Sdelphij#define ENV_EXTCOPY             "copy_extensions"
136296341Sdelphij#define ENV_UNIQUE_SUBJECT      "unique_subject"
13755714Skris
138296341Sdelphij#define ENV_DATABASE            "database"
13955714Skris
140109998Smarkm/* Additional revocation information types */
141109998Smarkm
142296341Sdelphij#define REV_NONE                0 /* No addditional information */
143296341Sdelphij#define REV_CRL_REASON          1 /* Value is CRL reason code */
144296341Sdelphij#define REV_HOLD                2 /* Value is hold instruction */
145296341Sdelphij#define REV_KEY_COMPROMISE      3 /* Value is cert key compromise time */
146296341Sdelphij#define REV_CA_COMPROMISE       4 /* Value is CA key compromise time */
147109998Smarkm
148296341Sdelphijstatic const char *ca_usage[] = {
149296341Sdelphij    "usage: ca args\n",
150296341Sdelphij    "\n",
151296341Sdelphij    " -verbose        - Talk alot while doing things\n",
152296341Sdelphij    " -config file    - A config file\n",
153296341Sdelphij    " -name arg       - The particular CA definition to use\n",
154296341Sdelphij    " -gencrl         - Generate a new CRL\n",
155296341Sdelphij    " -crldays days   - Days is when the next CRL is due\n",
156296341Sdelphij    " -crlhours hours - Hours is when the next CRL is due\n",
157296341Sdelphij    " -startdate YYMMDDHHMMSSZ  - certificate validity notBefore\n",
158296341Sdelphij    " -enddate YYMMDDHHMMSSZ    - certificate validity notAfter (overrides -days)\n",
159296341Sdelphij    " -days arg       - number of days to certify the certificate for\n",
160296341Sdelphij    " -md arg         - md to use, one of md2, md5, sha or sha1\n",
161296341Sdelphij    " -policy arg     - The CA 'policy' to support\n",
162296341Sdelphij    " -keyfile arg    - private key file\n",
163296341Sdelphij    " -keyform arg    - private key file format (PEM or ENGINE)\n",
164296341Sdelphij    " -key arg        - key to decode the private key if it is encrypted\n",
165296341Sdelphij    " -cert file      - The CA certificate\n",
166296341Sdelphij    " -selfsign       - sign a certificate with the key associated with it\n",
167296341Sdelphij    " -in file        - The input PEM encoded certificate request(s)\n",
168296341Sdelphij    " -out file       - Where to put the output file(s)\n",
169296341Sdelphij    " -outdir dir     - Where to put output certificates\n",
170296341Sdelphij    " -infiles ....   - The last argument, requests to process\n",
171296341Sdelphij    " -spkac file     - File contains DN and signed public key and challenge\n",
172296341Sdelphij    " -ss_cert file   - File contains a self signed cert to sign\n",
173296341Sdelphij    " -preserveDN     - Don't re-order the DN\n",
174296341Sdelphij    " -noemailDN      - Don't add the EMAIL field into certificate' subject\n",
175296341Sdelphij    " -batch          - Don't ask questions\n",
176296341Sdelphij    " -msie_hack      - msie modifications to handle all those universal strings\n",
177296341Sdelphij    " -revoke file    - Revoke a certificate (given in file)\n",
178296341Sdelphij    " -subj arg       - Use arg instead of request's subject\n",
179296341Sdelphij    " -utf8           - input characters are UTF8 (default ASCII)\n",
180296341Sdelphij    " -multivalue-rdn - enable support for multivalued RDNs\n",
181296341Sdelphij    " -extensions ..  - Extension section (override value in config file)\n",
182296341Sdelphij    " -extfile file   - Configuration file with X509v3 extentions to add\n",
183296341Sdelphij    " -crlexts ..     - CRL extension section (override value in config file)\n",
184111147Snectar#ifndef OPENSSL_NO_ENGINE
185296341Sdelphij    " -engine e       - use engine e, possibly a hardware device.\n",
186111147Snectar#endif
187296341Sdelphij    " -status serial  - Shows certificate status given the serial number\n",
188296341Sdelphij    " -updatedb       - Updates db for expired certificates\n",
189296341Sdelphij    NULL
19055714Skris};
19155714Skris
19255714Skris#ifdef EFENCE
19355714Skrisextern int EF_PROTECT_FREE;
19455714Skrisextern int EF_PROTECT_BELOW;
19555714Skrisextern int EF_ALIGNMENT;
19655714Skris#endif
19755714Skris
198160814Ssimonstatic void lookup_fail(const char *name, const char *tag);
199296341Sdelphijstatic int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
200296341Sdelphij                   const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
201296341Sdelphij                   STACK_OF(CONF_VALUE) *policy, CA_DB *db,
202296341Sdelphij                   BIGNUM *serial, char *subj, unsigned long chtype,
203296341Sdelphij                   int multirdn, int email_dn, char *startdate, char *enddate,
204296341Sdelphij                   long days, int batch, char *ext_sect, CONF *conf,
205296341Sdelphij                   int verbose, unsigned long certopt, unsigned long nameopt,
206296341Sdelphij                   int default_op, int ext_copy, int selfsign);
207296341Sdelphijstatic int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
208296341Sdelphij                        const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
209296341Sdelphij                        STACK_OF(CONF_VALUE) *policy, CA_DB *db,
210296341Sdelphij                        BIGNUM *serial, char *subj, unsigned long chtype,
211296341Sdelphij                        int multirdn, int email_dn, char *startdate,
212296341Sdelphij                        char *enddate, long days, int batch, char *ext_sect,
213296341Sdelphij                        CONF *conf, int verbose, unsigned long certopt,
214296341Sdelphij                        unsigned long nameopt, int default_op, int ext_copy,
215296341Sdelphij                        ENGINE *e);
216296341Sdelphijstatic int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey,
217296341Sdelphij                         X509 *x509, const EVP_MD *dgst,
218296341Sdelphij                         STACK_OF(OPENSSL_STRING) *sigopts,
219296341Sdelphij                         STACK_OF(CONF_VALUE) *policy, CA_DB *db,
220296341Sdelphij                         BIGNUM *serial, char *subj, unsigned long chtype,
221296341Sdelphij                         int multirdn, int email_dn, char *startdate,
222296341Sdelphij                         char *enddate, long days, char *ext_sect, CONF *conf,
223296341Sdelphij                         int verbose, unsigned long certopt,
224296341Sdelphij                         unsigned long nameopt, int default_op, int ext_copy);
225296341Sdelphijstatic void write_new_certificate(BIO *bp, X509 *x, int output_der,
226296341Sdelphij                                  int notext);
227296341Sdelphijstatic int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
228296341Sdelphij                   const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
229296341Sdelphij                   STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial,
230296341Sdelphij                   char *subj, unsigned long chtype, int multirdn,
231296341Sdelphij                   int email_dn, char *startdate, char *enddate, long days,
232296341Sdelphij                   int batch, int verbose, X509_REQ *req, char *ext_sect,
233296341Sdelphij                   CONF *conf, unsigned long certopt, unsigned long nameopt,
234296341Sdelphij                   int default_op, int ext_copy, int selfsign);
235127128Snectarstatic int do_revoke(X509 *x509, CA_DB *db, int ext, char *extval);
236127128Snectarstatic int get_certificate_status(const char *ser_status, CA_DB *db);
237127128Snectarstatic int do_updatedb(CA_DB *db);
238205128Ssimonstatic int check_time_format(const char *str);
239109998Smarkmchar *make_revocation_str(int rev_type, char *rev_arg);
240160814Ssimonint make_revoked(X509_REVOKED *rev, const char *str);
241109998Smarkmint old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str);
242296341Sdelphijstatic CONF *conf = NULL;
243296341Sdelphijstatic CONF *extconf = NULL;
244296341Sdelphijstatic char *section = NULL;
24555714Skris
246296341Sdelphijstatic int preserve = 0;
247296341Sdelphijstatic int msie_hack = 0;
24855714Skris
24959191Skrisint MAIN(int, char **);
25059191Skris
25155714Skrisint MAIN(int argc, char **argv)
252296341Sdelphij{
253296341Sdelphij    ENGINE *e = NULL;
254296341Sdelphij    char *key = NULL, *passargin = NULL;
255296341Sdelphij    int create_ser = 0;
256296341Sdelphij    int free_key = 0;
257296341Sdelphij    int total = 0;
258296341Sdelphij    int total_done = 0;
259296341Sdelphij    int badops = 0;
260296341Sdelphij    int ret = 1;
261296341Sdelphij    int email_dn = 1;
262296341Sdelphij    int req = 0;
263296341Sdelphij    int verbose = 0;
264296341Sdelphij    int gencrl = 0;
265296341Sdelphij    int dorevoke = 0;
266296341Sdelphij    int doupdatedb = 0;
267296341Sdelphij    long crldays = 0;
268296341Sdelphij    long crlhours = 0;
269296341Sdelphij    long crlsec = 0;
270296341Sdelphij    long errorline = -1;
271296341Sdelphij    char *configfile = NULL;
272296341Sdelphij    char *md = NULL;
273296341Sdelphij    char *policy = NULL;
274296341Sdelphij    char *keyfile = NULL;
275296341Sdelphij    char *certfile = NULL;
276296341Sdelphij    int keyform = FORMAT_PEM;
277296341Sdelphij    char *infile = NULL;
278296341Sdelphij    char *spkac_file = NULL;
279296341Sdelphij    char *ss_cert_file = NULL;
280296341Sdelphij    char *ser_status = NULL;
281296341Sdelphij    EVP_PKEY *pkey = NULL;
282296341Sdelphij    int output_der = 0;
283296341Sdelphij    char *outfile = NULL;
284296341Sdelphij    char *outdir = NULL;
285296341Sdelphij    char *serialfile = NULL;
286296341Sdelphij    char *crlnumberfile = NULL;
287296341Sdelphij    char *extensions = NULL;
288296341Sdelphij    char *extfile = NULL;
289296341Sdelphij    char *subj = NULL;
290296341Sdelphij    unsigned long chtype = MBSTRING_ASC;
291296341Sdelphij    int multirdn = 0;
292296341Sdelphij    char *tmp_email_dn = NULL;
293296341Sdelphij    char *crl_ext = NULL;
294296341Sdelphij    int rev_type = REV_NONE;
295296341Sdelphij    char *rev_arg = NULL;
296296341Sdelphij    BIGNUM *serial = NULL;
297296341Sdelphij    BIGNUM *crlnumber = NULL;
298296341Sdelphij    char *startdate = NULL;
299296341Sdelphij    char *enddate = NULL;
300296341Sdelphij    long days = 0;
301296341Sdelphij    int batch = 0;
302296341Sdelphij    int notext = 0;
303296341Sdelphij    unsigned long nameopt = 0, certopt = 0;
304296341Sdelphij    int default_op = 1;
305296341Sdelphij    int ext_copy = EXT_COPY_NONE;
306296341Sdelphij    int selfsign = 0;
307296341Sdelphij    X509 *x509 = NULL, *x509p = NULL;
308296341Sdelphij    X509 *x = NULL;
309296341Sdelphij    BIO *in = NULL, *out = NULL, *Sout = NULL, *Cout = NULL;
310296341Sdelphij    char *dbfile = NULL;
311296341Sdelphij    CA_DB *db = NULL;
312296341Sdelphij    X509_CRL *crl = NULL;
313296341Sdelphij    X509_REVOKED *r = NULL;
314296341Sdelphij    ASN1_TIME *tmptm;
315296341Sdelphij    ASN1_INTEGER *tmpser;
316296341Sdelphij    char *f;
317296341Sdelphij    const char *p;
318296341Sdelphij    char *const *pp;
319296341Sdelphij    int i, j;
320296341Sdelphij    const EVP_MD *dgst = NULL;
321296341Sdelphij    STACK_OF(CONF_VALUE) *attribs = NULL;
322296341Sdelphij    STACK_OF(X509) *cert_sk = NULL;
323296341Sdelphij    STACK_OF(OPENSSL_STRING) *sigopts = NULL;
32455714Skris#undef BSIZE
32555714Skris#define BSIZE 256
326296341Sdelphij    MS_STATIC char buf[3][BSIZE];
327296341Sdelphij    char *randfile = NULL;
328111147Snectar#ifndef OPENSSL_NO_ENGINE
329296341Sdelphij    char *engine = NULL;
330111147Snectar#endif
331296341Sdelphij    char *tofree = NULL;
332296341Sdelphij    DB_ATTR db_attr;
33355714Skris
33455714Skris#ifdef EFENCE
335296341Sdelphij    EF_PROTECT_FREE = 1;
336296341Sdelphij    EF_PROTECT_BELOW = 1;
337296341Sdelphij    EF_ALIGNMENT = 0;
33855714Skris#endif
33955714Skris
340296341Sdelphij    apps_startup();
34155714Skris
342296341Sdelphij    conf = NULL;
343296341Sdelphij    key = NULL;
344296341Sdelphij    section = NULL;
34555714Skris
346296341Sdelphij    preserve = 0;
347296341Sdelphij    msie_hack = 0;
348296341Sdelphij    if (bio_err == NULL)
349296341Sdelphij        if ((bio_err = BIO_new(BIO_s_file())) != NULL)
350296341Sdelphij            BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
35155714Skris
352296341Sdelphij    argc--;
353296341Sdelphij    argv++;
354296341Sdelphij    while (argc >= 1) {
355296341Sdelphij        if (strcmp(*argv, "-verbose") == 0)
356296341Sdelphij            verbose = 1;
357296341Sdelphij        else if (strcmp(*argv, "-config") == 0) {
358296341Sdelphij            if (--argc < 1)
359296341Sdelphij                goto bad;
360296341Sdelphij            configfile = *(++argv);
361296341Sdelphij        } else if (strcmp(*argv, "-name") == 0) {
362296341Sdelphij            if (--argc < 1)
363296341Sdelphij                goto bad;
364296341Sdelphij            section = *(++argv);
365296341Sdelphij        } else if (strcmp(*argv, "-subj") == 0) {
366296341Sdelphij            if (--argc < 1)
367296341Sdelphij                goto bad;
368296341Sdelphij            subj = *(++argv);
369296341Sdelphij            /* preserve=1; */
370296341Sdelphij        } else if (strcmp(*argv, "-utf8") == 0)
371296341Sdelphij            chtype = MBSTRING_UTF8;
372296341Sdelphij        else if (strcmp(*argv, "-create_serial") == 0)
373296341Sdelphij            create_ser = 1;
374296341Sdelphij        else if (strcmp(*argv, "-multivalue-rdn") == 0)
375296341Sdelphij            multirdn = 1;
376296341Sdelphij        else if (strcmp(*argv, "-startdate") == 0) {
377296341Sdelphij            if (--argc < 1)
378296341Sdelphij                goto bad;
379296341Sdelphij            startdate = *(++argv);
380296341Sdelphij        } else if (strcmp(*argv, "-enddate") == 0) {
381296341Sdelphij            if (--argc < 1)
382296341Sdelphij                goto bad;
383296341Sdelphij            enddate = *(++argv);
384296341Sdelphij        } else if (strcmp(*argv, "-days") == 0) {
385296341Sdelphij            if (--argc < 1)
386296341Sdelphij                goto bad;
387296341Sdelphij            days = atoi(*(++argv));
388296341Sdelphij        } else if (strcmp(*argv, "-md") == 0) {
389296341Sdelphij            if (--argc < 1)
390296341Sdelphij                goto bad;
391296341Sdelphij            md = *(++argv);
392296341Sdelphij        } else if (strcmp(*argv, "-policy") == 0) {
393296341Sdelphij            if (--argc < 1)
394296341Sdelphij                goto bad;
395296341Sdelphij            policy = *(++argv);
396296341Sdelphij        } else if (strcmp(*argv, "-keyfile") == 0) {
397296341Sdelphij            if (--argc < 1)
398296341Sdelphij                goto bad;
399296341Sdelphij            keyfile = *(++argv);
400296341Sdelphij        } else if (strcmp(*argv, "-keyform") == 0) {
401296341Sdelphij            if (--argc < 1)
402296341Sdelphij                goto bad;
403296341Sdelphij            keyform = str2fmt(*(++argv));
404296341Sdelphij        } else if (strcmp(*argv, "-passin") == 0) {
405296341Sdelphij            if (--argc < 1)
406296341Sdelphij                goto bad;
407296341Sdelphij            passargin = *(++argv);
408296341Sdelphij        } else if (strcmp(*argv, "-key") == 0) {
409296341Sdelphij            if (--argc < 1)
410296341Sdelphij                goto bad;
411296341Sdelphij            key = *(++argv);
412296341Sdelphij        } else if (strcmp(*argv, "-cert") == 0) {
413296341Sdelphij            if (--argc < 1)
414296341Sdelphij                goto bad;
415296341Sdelphij            certfile = *(++argv);
416296341Sdelphij        } else if (strcmp(*argv, "-selfsign") == 0)
417296341Sdelphij            selfsign = 1;
418296341Sdelphij        else if (strcmp(*argv, "-in") == 0) {
419296341Sdelphij            if (--argc < 1)
420296341Sdelphij                goto bad;
421296341Sdelphij            infile = *(++argv);
422296341Sdelphij            req = 1;
423296341Sdelphij        } else if (strcmp(*argv, "-out") == 0) {
424296341Sdelphij            if (--argc < 1)
425296341Sdelphij                goto bad;
426296341Sdelphij            outfile = *(++argv);
427296341Sdelphij        } else if (strcmp(*argv, "-outdir") == 0) {
428296341Sdelphij            if (--argc < 1)
429296341Sdelphij                goto bad;
430296341Sdelphij            outdir = *(++argv);
431296341Sdelphij        } else if (strcmp(*argv, "-sigopt") == 0) {
432296341Sdelphij            if (--argc < 1)
433296341Sdelphij                goto bad;
434296341Sdelphij            if (!sigopts)
435296341Sdelphij                sigopts = sk_OPENSSL_STRING_new_null();
436296341Sdelphij            if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv)))
437296341Sdelphij                goto bad;
438296341Sdelphij        } else if (strcmp(*argv, "-notext") == 0)
439296341Sdelphij            notext = 1;
440296341Sdelphij        else if (strcmp(*argv, "-batch") == 0)
441296341Sdelphij            batch = 1;
442296341Sdelphij        else if (strcmp(*argv, "-preserveDN") == 0)
443296341Sdelphij            preserve = 1;
444296341Sdelphij        else if (strcmp(*argv, "-noemailDN") == 0)
445296341Sdelphij            email_dn = 0;
446296341Sdelphij        else if (strcmp(*argv, "-gencrl") == 0)
447296341Sdelphij            gencrl = 1;
448296341Sdelphij        else if (strcmp(*argv, "-msie_hack") == 0)
449296341Sdelphij            msie_hack = 1;
450296341Sdelphij        else if (strcmp(*argv, "-crldays") == 0) {
451296341Sdelphij            if (--argc < 1)
452296341Sdelphij                goto bad;
453296341Sdelphij            crldays = atol(*(++argv));
454296341Sdelphij        } else if (strcmp(*argv, "-crlhours") == 0) {
455296341Sdelphij            if (--argc < 1)
456296341Sdelphij                goto bad;
457296341Sdelphij            crlhours = atol(*(++argv));
458296341Sdelphij        } else if (strcmp(*argv, "-crlsec") == 0) {
459296341Sdelphij            if (--argc < 1)
460296341Sdelphij                goto bad;
461296341Sdelphij            crlsec = atol(*(++argv));
462296341Sdelphij        } else if (strcmp(*argv, "-infiles") == 0) {
463296341Sdelphij            argc--;
464296341Sdelphij            argv++;
465296341Sdelphij            req = 1;
466296341Sdelphij            break;
467296341Sdelphij        } else if (strcmp(*argv, "-ss_cert") == 0) {
468296341Sdelphij            if (--argc < 1)
469296341Sdelphij                goto bad;
470296341Sdelphij            ss_cert_file = *(++argv);
471296341Sdelphij            req = 1;
472296341Sdelphij        } else if (strcmp(*argv, "-spkac") == 0) {
473296341Sdelphij            if (--argc < 1)
474296341Sdelphij                goto bad;
475296341Sdelphij            spkac_file = *(++argv);
476296341Sdelphij            req = 1;
477296341Sdelphij        } else if (strcmp(*argv, "-revoke") == 0) {
478296341Sdelphij            if (--argc < 1)
479296341Sdelphij                goto bad;
480296341Sdelphij            infile = *(++argv);
481296341Sdelphij            dorevoke = 1;
482296341Sdelphij        } else if (strcmp(*argv, "-extensions") == 0) {
483296341Sdelphij            if (--argc < 1)
484296341Sdelphij                goto bad;
485296341Sdelphij            extensions = *(++argv);
486296341Sdelphij        } else if (strcmp(*argv, "-extfile") == 0) {
487296341Sdelphij            if (--argc < 1)
488296341Sdelphij                goto bad;
489296341Sdelphij            extfile = *(++argv);
490296341Sdelphij        } else if (strcmp(*argv, "-status") == 0) {
491296341Sdelphij            if (--argc < 1)
492296341Sdelphij                goto bad;
493296341Sdelphij            ser_status = *(++argv);
494296341Sdelphij        } else if (strcmp(*argv, "-updatedb") == 0) {
495296341Sdelphij            doupdatedb = 1;
496296341Sdelphij        } else if (strcmp(*argv, "-crlexts") == 0) {
497296341Sdelphij            if (--argc < 1)
498296341Sdelphij                goto bad;
499296341Sdelphij            crl_ext = *(++argv);
500296341Sdelphij        } else if (strcmp(*argv, "-crl_reason") == 0) {
501296341Sdelphij            if (--argc < 1)
502296341Sdelphij                goto bad;
503296341Sdelphij            rev_arg = *(++argv);
504296341Sdelphij            rev_type = REV_CRL_REASON;
505296341Sdelphij        } else if (strcmp(*argv, "-crl_hold") == 0) {
506296341Sdelphij            if (--argc < 1)
507296341Sdelphij                goto bad;
508296341Sdelphij            rev_arg = *(++argv);
509296341Sdelphij            rev_type = REV_HOLD;
510296341Sdelphij        } else if (strcmp(*argv, "-crl_compromise") == 0) {
511296341Sdelphij            if (--argc < 1)
512296341Sdelphij                goto bad;
513296341Sdelphij            rev_arg = *(++argv);
514296341Sdelphij            rev_type = REV_KEY_COMPROMISE;
515296341Sdelphij        } else if (strcmp(*argv, "-crl_CA_compromise") == 0) {
516296341Sdelphij            if (--argc < 1)
517296341Sdelphij                goto bad;
518296341Sdelphij            rev_arg = *(++argv);
519296341Sdelphij            rev_type = REV_CA_COMPROMISE;
520296341Sdelphij        }
521111147Snectar#ifndef OPENSSL_NO_ENGINE
522296341Sdelphij        else if (strcmp(*argv, "-engine") == 0) {
523296341Sdelphij            if (--argc < 1)
524296341Sdelphij                goto bad;
525296341Sdelphij            engine = *(++argv);
526296341Sdelphij        }
527111147Snectar#endif
528296341Sdelphij        else {
529296341Sdelphij bad:
530296341Sdelphij            BIO_printf(bio_err, "unknown option %s\n", *argv);
531296341Sdelphij            badops = 1;
532296341Sdelphij            break;
533296341Sdelphij        }
534296341Sdelphij        argc--;
535296341Sdelphij        argv++;
536296341Sdelphij    }
53755714Skris
538296341Sdelphij    if (badops) {
539296341Sdelphij        const char **pp2;
540238405Sjkim
541296341Sdelphij        for (pp2 = ca_usage; (*pp2 != NULL); pp2++)
542296341Sdelphij            BIO_printf(bio_err, "%s", *pp2);
543296341Sdelphij        goto err;
544296341Sdelphij    }
54555714Skris
546296341Sdelphij    ERR_load_crypto_strings();
54755714Skris
548296341Sdelphij        /*****************************************************************/
549296341Sdelphij    tofree = NULL;
550296341Sdelphij    if (configfile == NULL)
551296341Sdelphij        configfile = getenv("OPENSSL_CONF");
552296341Sdelphij    if (configfile == NULL)
553296341Sdelphij        configfile = getenv("SSLEAY_CONF");
554296341Sdelphij    if (configfile == NULL) {
555296341Sdelphij        const char *s = X509_get_default_cert_area();
556296341Sdelphij        size_t len;
557109998Smarkm
558109998Smarkm#ifdef OPENSSL_SYS_VMS
559296341Sdelphij        len = strlen(s) + sizeof(CONFIG_FILE);
560296341Sdelphij        tofree = OPENSSL_malloc(len);
561296341Sdelphij        if (!tofree) {
562296341Sdelphij            BIO_printf(bio_err, "Out of memory\n");
563296341Sdelphij            goto err;
564296341Sdelphij        }
565296341Sdelphij        strcpy(tofree, s);
56655714Skris#else
567296341Sdelphij        len = strlen(s) + sizeof(CONFIG_FILE) + 1;
568296341Sdelphij        tofree = OPENSSL_malloc(len);
569296341Sdelphij        if (!tofree) {
570296341Sdelphij            BIO_printf(bio_err, "Out of memory\n");
571296341Sdelphij            goto err;
572296341Sdelphij        }
573296341Sdelphij        BUF_strlcpy(tofree, s, len);
574296341Sdelphij        BUF_strlcat(tofree, "/", len);
57555714Skris#endif
576296341Sdelphij        BUF_strlcat(tofree, CONFIG_FILE, len);
577296341Sdelphij        configfile = tofree;
578296341Sdelphij    }
57955714Skris
580296341Sdelphij    BIO_printf(bio_err, "Using configuration from %s\n", configfile);
581296341Sdelphij    conf = NCONF_new(NULL);
582296341Sdelphij    if (NCONF_load(conf, configfile, &errorline) <= 0) {
583296341Sdelphij        if (errorline <= 0)
584296341Sdelphij            BIO_printf(bio_err, "error loading the config file '%s'\n",
585296341Sdelphij                       configfile);
586296341Sdelphij        else
587296341Sdelphij            BIO_printf(bio_err, "error on line %ld of config file '%s'\n",
588296341Sdelphij                       errorline, configfile);
589296341Sdelphij        goto err;
590296341Sdelphij    }
591296341Sdelphij    if (tofree) {
592296341Sdelphij        OPENSSL_free(tofree);
593296341Sdelphij        tofree = NULL;
594296341Sdelphij    }
59555714Skris
596296341Sdelphij    if (!load_config(bio_err, conf))
597296341Sdelphij        goto err;
598109998Smarkm
599142425Snectar#ifndef OPENSSL_NO_ENGINE
600296341Sdelphij    e = setup_engine(bio_err, engine, 0);
601142425Snectar#endif
602142425Snectar
603296341Sdelphij    /* Lets get the config section we are using */
604296341Sdelphij    if (section == NULL) {
605296341Sdelphij        section = NCONF_get_string(conf, BASE_SECTION, ENV_DEFAULT_CA);
606296341Sdelphij        if (section == NULL) {
607296341Sdelphij            lookup_fail(BASE_SECTION, ENV_DEFAULT_CA);
608296341Sdelphij            goto err;
609296341Sdelphij        }
610296341Sdelphij    }
61155714Skris
612296341Sdelphij    if (conf != NULL) {
613296341Sdelphij        p = NCONF_get_string(conf, NULL, "oid_file");
614296341Sdelphij        if (p == NULL)
615296341Sdelphij            ERR_clear_error();
616296341Sdelphij        if (p != NULL) {
617296341Sdelphij            BIO *oid_bio;
61855714Skris
619296341Sdelphij            oid_bio = BIO_new_file(p, "r");
620296341Sdelphij            if (oid_bio == NULL) {
621296341Sdelphij                /*-
622296341Sdelphij                BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
623296341Sdelphij                ERR_print_errors(bio_err);
624296341Sdelphij                */
625296341Sdelphij                ERR_clear_error();
626296341Sdelphij            } else {
627296341Sdelphij                OBJ_create_objects(oid_bio);
628296341Sdelphij                BIO_free(oid_bio);
629296341Sdelphij            }
630296341Sdelphij        }
631296341Sdelphij        if (!add_oid_section(bio_err, conf)) {
632296341Sdelphij            ERR_print_errors(bio_err);
633296341Sdelphij            goto err;
634296341Sdelphij        }
635296341Sdelphij    }
63655714Skris
637296341Sdelphij    randfile = NCONF_get_string(conf, BASE_SECTION, "RANDFILE");
638296341Sdelphij    if (randfile == NULL)
639296341Sdelphij        ERR_clear_error();
640296341Sdelphij    app_RAND_load_file(randfile, bio_err, 0);
641127128Snectar
642296341Sdelphij    f = NCONF_get_string(conf, section, STRING_MASK);
643296341Sdelphij    if (!f)
644296341Sdelphij        ERR_clear_error();
645160814Ssimon
646296341Sdelphij    if (f && !ASN1_STRING_set_default_mask_asc(f)) {
647296341Sdelphij        BIO_printf(bio_err, "Invalid global string mask setting %s\n", f);
648296341Sdelphij        goto err;
649296341Sdelphij    }
650160814Ssimon
651296341Sdelphij    if (chtype != MBSTRING_UTF8) {
652296341Sdelphij        f = NCONF_get_string(conf, section, UTF8_IN);
653296341Sdelphij        if (!f)
654296341Sdelphij            ERR_clear_error();
655296341Sdelphij        else if (!strcmp(f, "yes"))
656296341Sdelphij            chtype = MBSTRING_UTF8;
657296341Sdelphij    }
658160814Ssimon
659296341Sdelphij    db_attr.unique_subject = 1;
660296341Sdelphij    p = NCONF_get_string(conf, section, ENV_UNIQUE_SUBJECT);
661296341Sdelphij    if (p) {
662127128Snectar#ifdef RL_DEBUG
663296341Sdelphij        BIO_printf(bio_err, "DEBUG: unique_subject = \"%s\"\n", p);
664127128Snectar#endif
665296341Sdelphij        db_attr.unique_subject = parse_yesno(p, 1);
666296341Sdelphij    } else
667296341Sdelphij        ERR_clear_error();
668127128Snectar#ifdef RL_DEBUG
669296341Sdelphij    if (!p)
670296341Sdelphij        BIO_printf(bio_err, "DEBUG: unique_subject undefined\n");
671127128Snectar#endif
672127128Snectar#ifdef RL_DEBUG
673296341Sdelphij    BIO_printf(bio_err, "DEBUG: configured unique_subject is %d\n",
674296341Sdelphij               db_attr.unique_subject);
675127128Snectar#endif
67655714Skris
677296341Sdelphij    in = BIO_new(BIO_s_file());
678296341Sdelphij    out = BIO_new(BIO_s_file());
679296341Sdelphij    Sout = BIO_new(BIO_s_file());
680296341Sdelphij    Cout = BIO_new(BIO_s_file());
681296341Sdelphij    if ((in == NULL) || (out == NULL) || (Sout == NULL) || (Cout == NULL)) {
682296341Sdelphij        ERR_print_errors(bio_err);
683296341Sdelphij        goto err;
684296341Sdelphij    }
68555714Skris
686296341Sdelphij        /*****************************************************************/
687296341Sdelphij    /* report status of cert with serial number given on command line */
688296341Sdelphij    if (ser_status) {
689296341Sdelphij        if ((dbfile = NCONF_get_string(conf, section, ENV_DATABASE)) == NULL) {
690296341Sdelphij            lookup_fail(section, ENV_DATABASE);
691296341Sdelphij            goto err;
692296341Sdelphij        }
693296341Sdelphij        db = load_index(dbfile, &db_attr);
694296341Sdelphij        if (db == NULL)
695296341Sdelphij            goto err;
696109998Smarkm
697296341Sdelphij        if (!index_index(db))
698296341Sdelphij            goto err;
699109998Smarkm
700296341Sdelphij        if (get_certificate_status(ser_status, db) != 1)
701296341Sdelphij            BIO_printf(bio_err, "Error verifying serial %s!\n", ser_status);
702296341Sdelphij        goto err;
703296341Sdelphij    }
704109998Smarkm
705296341Sdelphij        /*****************************************************************/
706296341Sdelphij    /* we definitely need a private key, so let's get it */
70755714Skris
708296341Sdelphij    if ((keyfile == NULL) && ((keyfile = NCONF_get_string(conf,
709296341Sdelphij                                                          section,
710296341Sdelphij                                                          ENV_PRIVATE_KEY)) ==
711296341Sdelphij                              NULL)) {
712296341Sdelphij        lookup_fail(section, ENV_PRIVATE_KEY);
713296341Sdelphij        goto err;
714296341Sdelphij    }
715296341Sdelphij    if (!key) {
716296341Sdelphij        free_key = 1;
717296341Sdelphij        if (!app_passwd(bio_err, passargin, NULL, &key, NULL)) {
718296341Sdelphij            BIO_printf(bio_err, "Error getting password\n");
719296341Sdelphij            goto err;
720296341Sdelphij        }
721296341Sdelphij    }
722296341Sdelphij    pkey = load_key(bio_err, keyfile, keyform, 0, key, e, "CA private key");
723296341Sdelphij    if (key)
724296341Sdelphij        OPENSSL_cleanse(key, strlen(key));
725296341Sdelphij    if (pkey == NULL) {
726296341Sdelphij        /* load_key() has already printed an appropriate message */
727296341Sdelphij        goto err;
728296341Sdelphij    }
72955714Skris
730296341Sdelphij        /*****************************************************************/
731296341Sdelphij    /* we need a certificate */
732296341Sdelphij    if (!selfsign || spkac_file || ss_cert_file || gencrl) {
733296341Sdelphij        if ((certfile == NULL)
734296341Sdelphij            && ((certfile = NCONF_get_string(conf,
735296341Sdelphij                                             section,
736296341Sdelphij                                             ENV_CERTIFICATE)) == NULL)) {
737296341Sdelphij            lookup_fail(section, ENV_CERTIFICATE);
738296341Sdelphij            goto err;
739296341Sdelphij        }
740296341Sdelphij        x509 = load_cert(bio_err, certfile, FORMAT_PEM, NULL, e,
741296341Sdelphij                         "CA certificate");
742296341Sdelphij        if (x509 == NULL)
743296341Sdelphij            goto err;
74455714Skris
745296341Sdelphij        if (!X509_check_private_key(x509, pkey)) {
746296341Sdelphij            BIO_printf(bio_err,
747296341Sdelphij                       "CA certificate and CA private key do not match\n");
748296341Sdelphij            goto err;
749296341Sdelphij        }
750296341Sdelphij    }
751296341Sdelphij    if (!selfsign)
752296341Sdelphij        x509p = x509;
75355714Skris
754296341Sdelphij    f = NCONF_get_string(conf, BASE_SECTION, ENV_PRESERVE);
755296341Sdelphij    if (f == NULL)
756296341Sdelphij        ERR_clear_error();
757296341Sdelphij    if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
758296341Sdelphij        preserve = 1;
759296341Sdelphij    f = NCONF_get_string(conf, BASE_SECTION, ENV_MSIE_HACK);
760296341Sdelphij    if (f == NULL)
761296341Sdelphij        ERR_clear_error();
762296341Sdelphij    if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
763296341Sdelphij        msie_hack = 1;
764109998Smarkm
765296341Sdelphij    f = NCONF_get_string(conf, section, ENV_NAMEOPT);
766109998Smarkm
767296341Sdelphij    if (f) {
768296341Sdelphij        if (!set_name_ex(&nameopt, f)) {
769296341Sdelphij            BIO_printf(bio_err, "Invalid name options: \"%s\"\n", f);
770296341Sdelphij            goto err;
771296341Sdelphij        }
772296341Sdelphij        default_op = 0;
773296341Sdelphij    } else
774296341Sdelphij        ERR_clear_error();
775109998Smarkm
776296341Sdelphij    f = NCONF_get_string(conf, section, ENV_CERTOPT);
777109998Smarkm
778296341Sdelphij    if (f) {
779296341Sdelphij        if (!set_cert_ex(&certopt, f)) {
780296341Sdelphij            BIO_printf(bio_err, "Invalid certificate options: \"%s\"\n", f);
781296341Sdelphij            goto err;
782296341Sdelphij        }
783296341Sdelphij        default_op = 0;
784296341Sdelphij    } else
785296341Sdelphij        ERR_clear_error();
786109998Smarkm
787296341Sdelphij    f = NCONF_get_string(conf, section, ENV_EXTCOPY);
788109998Smarkm
789296341Sdelphij    if (f) {
790296341Sdelphij        if (!set_ext_copy(&ext_copy, f)) {
791296341Sdelphij            BIO_printf(bio_err, "Invalid extension copy option: \"%s\"\n", f);
792296341Sdelphij            goto err;
793296341Sdelphij        }
794296341Sdelphij    } else
795296341Sdelphij        ERR_clear_error();
79655714Skris
797296341Sdelphij        /*****************************************************************/
798296341Sdelphij    /* lookup where to write new certificates */
799296341Sdelphij    if ((outdir == NULL) && (req)) {
800296341Sdelphij
801296341Sdelphij        if ((outdir = NCONF_get_string(conf, section, ENV_NEW_CERTS_DIR))
802296341Sdelphij            == NULL) {
803296341Sdelphij            BIO_printf(bio_err,
804296341Sdelphij                       "there needs to be defined a directory for new certificate to be placed in\n");
805296341Sdelphij            goto err;
806296341Sdelphij        }
807109998Smarkm#ifndef OPENSSL_SYS_VMS
808296341Sdelphij        /*
809296341Sdelphij         * outdir is a directory spec, but access() for VMS demands a
810296341Sdelphij         * filename.  In any case, stat(), below, will catch the problem if
811296341Sdelphij         * outdir is not a directory spec, and the fopen() or open() will
812296341Sdelphij         * catch an error if there is no write access.
813296341Sdelphij         *
814296341Sdelphij         * Presumably, this problem could also be solved by using the DEC C
815296341Sdelphij         * routines to convert the directory syntax to Unixly, and give that
816296341Sdelphij         * to access().  However, time's too short to do that just now.
817296341Sdelphij         */
818296341Sdelphij# ifndef _WIN32
819296341Sdelphij        if (access(outdir, R_OK | W_OK | X_OK) != 0)
820296341Sdelphij# else
821296341Sdelphij        if (_access(outdir, R_OK | W_OK | X_OK) != 0)
822296341Sdelphij# endif
823296341Sdelphij        {
824296341Sdelphij            BIO_printf(bio_err, "I am unable to access the %s directory\n",
825296341Sdelphij                       outdir);
826296341Sdelphij            perror(outdir);
827296341Sdelphij            goto err;
828296341Sdelphij        }
82959191Skris
830296341Sdelphij        if (app_isdir(outdir) <= 0) {
831296341Sdelphij            BIO_printf(bio_err, "%s need to be a directory\n", outdir);
832296341Sdelphij            perror(outdir);
833296341Sdelphij            goto err;
834296341Sdelphij        }
835238405Sjkim#endif
836296341Sdelphij    }
83755714Skris
838296341Sdelphij        /*****************************************************************/
839296341Sdelphij    /* we need to load the database file */
840296341Sdelphij    if ((dbfile = NCONF_get_string(conf, section, ENV_DATABASE)) == NULL) {
841296341Sdelphij        lookup_fail(section, ENV_DATABASE);
842296341Sdelphij        goto err;
843296341Sdelphij    }
844296341Sdelphij    db = load_index(dbfile, &db_attr);
845296341Sdelphij    if (db == NULL)
846296341Sdelphij        goto err;
84755714Skris
848296341Sdelphij    /* Lets check some fields */
849296341Sdelphij    for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
850296341Sdelphij        pp = sk_OPENSSL_PSTRING_value(db->db->data, i);
851296341Sdelphij        if ((pp[DB_type][0] != DB_TYPE_REV) && (pp[DB_rev_date][0] != '\0')) {
852296341Sdelphij            BIO_printf(bio_err,
853296341Sdelphij                       "entry %d: not revoked yet, but has a revocation date\n",
854296341Sdelphij                       i + 1);
855296341Sdelphij            goto err;
856296341Sdelphij        }
857296341Sdelphij        if ((pp[DB_type][0] == DB_TYPE_REV) &&
858296341Sdelphij            !make_revoked(NULL, pp[DB_rev_date])) {
859296341Sdelphij            BIO_printf(bio_err, " in entry %d\n", i + 1);
860296341Sdelphij            goto err;
861296341Sdelphij        }
862296341Sdelphij        if (!check_time_format((char *)pp[DB_exp_date])) {
863296341Sdelphij            BIO_printf(bio_err, "entry %d: invalid expiry date\n", i + 1);
864296341Sdelphij            goto err;
865296341Sdelphij        }
866296341Sdelphij        p = pp[DB_serial];
867296341Sdelphij        j = strlen(p);
868296341Sdelphij        if (*p == '-') {
869296341Sdelphij            p++;
870296341Sdelphij            j--;
871296341Sdelphij        }
872296341Sdelphij        if ((j & 1) || (j < 2)) {
873296341Sdelphij            BIO_printf(bio_err, "entry %d: bad serial number length (%d)\n",
874296341Sdelphij                       i + 1, j);
875296341Sdelphij            goto err;
876296341Sdelphij        }
877296341Sdelphij        while (*p) {
878296341Sdelphij            if (!(((*p >= '0') && (*p <= '9')) ||
879296341Sdelphij                  ((*p >= 'A') && (*p <= 'F')) ||
880296341Sdelphij                  ((*p >= 'a') && (*p <= 'f')))) {
881296341Sdelphij                BIO_printf(bio_err,
882296341Sdelphij                           "entry %d: bad serial number characters, char pos %ld, char is '%c'\n",
883296341Sdelphij                           i + 1, (long)(p - pp[DB_serial]), *p);
884296341Sdelphij                goto err;
885296341Sdelphij            }
886296341Sdelphij            p++;
887296341Sdelphij        }
888296341Sdelphij    }
889296341Sdelphij    if (verbose) {
890296341Sdelphij        BIO_set_fp(out, stdout, BIO_NOCLOSE | BIO_FP_TEXT); /* cannot fail */
891109998Smarkm#ifdef OPENSSL_SYS_VMS
892296341Sdelphij        {
893296341Sdelphij            BIO *tmpbio = BIO_new(BIO_f_linebuffer());
894296341Sdelphij            out = BIO_push(tmpbio, out);
895296341Sdelphij        }
89668651Skris#endif
897296341Sdelphij        TXT_DB_write(out, db->db);
898296341Sdelphij        BIO_printf(bio_err, "%d entries loaded from the database\n",
899296341Sdelphij                   sk_OPENSSL_PSTRING_num(db->db->data));
900296341Sdelphij        BIO_printf(bio_err, "generating index\n");
901296341Sdelphij    }
90255714Skris
903296341Sdelphij    if (!index_index(db))
904296341Sdelphij        goto err;
905109998Smarkm
906296341Sdelphij        /*****************************************************************/
907296341Sdelphij    /* Update the db file for expired certificates */
908296341Sdelphij    if (doupdatedb) {
909296341Sdelphij        if (verbose)
910296341Sdelphij            BIO_printf(bio_err, "Updating %s ...\n", dbfile);
911109998Smarkm
912296341Sdelphij        i = do_updatedb(db);
913296341Sdelphij        if (i == -1) {
914296341Sdelphij            BIO_printf(bio_err, "Malloc failure\n");
915296341Sdelphij            goto err;
916296341Sdelphij        } else if (i == 0) {
917296341Sdelphij            if (verbose)
918296341Sdelphij                BIO_printf(bio_err, "No entries found to mark expired\n");
919296341Sdelphij        } else {
920296341Sdelphij            if (!save_index(dbfile, "new", db))
921296341Sdelphij                goto err;
922109998Smarkm
923296341Sdelphij            if (!rotate_index(dbfile, "new", "old"))
924296341Sdelphij                goto err;
925109998Smarkm
926296341Sdelphij            if (verbose)
927296341Sdelphij                BIO_printf(bio_err,
928296341Sdelphij                           "Done. %d entries marked as expired\n", i);
929296341Sdelphij        }
930296341Sdelphij    }
931109998Smarkm
932296341Sdelphij        /*****************************************************************/
933296341Sdelphij    /* Read extentions config file                                   */
934296341Sdelphij    if (extfile) {
935296341Sdelphij        extconf = NCONF_new(NULL);
936296341Sdelphij        if (NCONF_load(extconf, extfile, &errorline) <= 0) {
937296341Sdelphij            if (errorline <= 0)
938296341Sdelphij                BIO_printf(bio_err, "ERROR: loading the config file '%s'\n",
939296341Sdelphij                           extfile);
940296341Sdelphij            else
941296341Sdelphij                BIO_printf(bio_err,
942296341Sdelphij                           "ERROR: on line %ld of config file '%s'\n",
943296341Sdelphij                           errorline, extfile);
944296341Sdelphij            ret = 1;
945296341Sdelphij            goto err;
946296341Sdelphij        }
947296341Sdelphij
948296341Sdelphij        if (verbose)
949296341Sdelphij            BIO_printf(bio_err, "Successfully loaded extensions file %s\n",
950296341Sdelphij                       extfile);
951296341Sdelphij
952296341Sdelphij        /* We can have sections in the ext file */
953296341Sdelphij        if (!extensions
954296341Sdelphij            && !(extensions =
955296341Sdelphij                 NCONF_get_string(extconf, "default", "extensions")))
956296341Sdelphij            extensions = "default";
957296341Sdelphij    }
958296341Sdelphij
959296341Sdelphij        /*****************************************************************/
960296341Sdelphij    if (req || gencrl) {
961296341Sdelphij        if (outfile != NULL) {
962296341Sdelphij            if (BIO_write_filename(Sout, outfile) <= 0) {
963296341Sdelphij                perror(outfile);
964296341Sdelphij                goto err;
965296341Sdelphij            }
966296341Sdelphij        } else {
967296341Sdelphij            BIO_set_fp(Sout, stdout, BIO_NOCLOSE | BIO_FP_TEXT);
968109998Smarkm#ifdef OPENSSL_SYS_VMS
969296341Sdelphij            {
970296341Sdelphij                BIO *tmpbio = BIO_new(BIO_f_linebuffer());
971296341Sdelphij                Sout = BIO_push(tmpbio, Sout);
972296341Sdelphij            }
97368651Skris#endif
974296341Sdelphij        }
975296341Sdelphij    }
97655714Skris
977296341Sdelphij    if ((md == NULL) && ((md = NCONF_get_string(conf,
978296341Sdelphij                                                section,
979296341Sdelphij                                                ENV_DEFAULT_MD)) == NULL)) {
980296341Sdelphij        lookup_fail(section, ENV_DEFAULT_MD);
981296341Sdelphij        goto err;
982296341Sdelphij    }
983160814Ssimon
984296341Sdelphij    if (!strcmp(md, "default")) {
985296341Sdelphij        int def_nid;
986296341Sdelphij        if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) <= 0) {
987296341Sdelphij            BIO_puts(bio_err, "no default digest\n");
988296341Sdelphij            goto err;
989296341Sdelphij        }
990296341Sdelphij        md = (char *)OBJ_nid2sn(def_nid);
991296341Sdelphij    }
992238405Sjkim
993296341Sdelphij    if ((dgst = EVP_get_digestbyname(md)) == NULL) {
994296341Sdelphij        BIO_printf(bio_err, "%s is an unsupported message digest type\n", md);
995296341Sdelphij        goto err;
996296341Sdelphij    }
997160814Ssimon
998296341Sdelphij    if (req) {
999296341Sdelphij        if ((email_dn == 1) && ((tmp_email_dn = NCONF_get_string(conf,
1000296341Sdelphij                                                                 section,
1001296341Sdelphij                                                                 ENV_DEFAULT_EMAIL_DN))
1002296341Sdelphij                                != NULL)) {
1003296341Sdelphij            if (strcmp(tmp_email_dn, "no") == 0)
1004296341Sdelphij                email_dn = 0;
1005296341Sdelphij        }
1006296341Sdelphij        if (verbose)
1007296341Sdelphij            BIO_printf(bio_err, "message digest is %s\n",
1008296341Sdelphij                       OBJ_nid2ln(dgst->type));
1009296341Sdelphij        if ((policy == NULL) && ((policy = NCONF_get_string(conf,
1010296341Sdelphij                                                            section,
1011296341Sdelphij                                                            ENV_POLICY)) ==
1012296341Sdelphij                                 NULL)) {
1013296341Sdelphij            lookup_fail(section, ENV_POLICY);
1014296341Sdelphij            goto err;
1015296341Sdelphij        }
1016296341Sdelphij        if (verbose)
1017296341Sdelphij            BIO_printf(bio_err, "policy is %s\n", policy);
101855714Skris
1019296341Sdelphij        if ((serialfile = NCONF_get_string(conf, section, ENV_SERIAL))
1020296341Sdelphij            == NULL) {
1021296341Sdelphij            lookup_fail(section, ENV_SERIAL);
1022296341Sdelphij            goto err;
1023296341Sdelphij        }
1024109998Smarkm
1025296341Sdelphij        if (!extconf) {
1026296341Sdelphij            /*
1027296341Sdelphij             * no '-extfile' option, so we look for extensions in the main
1028296341Sdelphij             * configuration file
1029296341Sdelphij             */
1030296341Sdelphij            if (!extensions) {
1031296341Sdelphij                extensions = NCONF_get_string(conf, section, ENV_EXTENSIONS);
1032296341Sdelphij                if (!extensions)
1033296341Sdelphij                    ERR_clear_error();
1034296341Sdelphij            }
1035296341Sdelphij            if (extensions) {
1036296341Sdelphij                /* Check syntax of file */
1037296341Sdelphij                X509V3_CTX ctx;
1038296341Sdelphij                X509V3_set_ctx_test(&ctx);
1039296341Sdelphij                X509V3_set_nconf(&ctx, conf);
1040296341Sdelphij                if (!X509V3_EXT_add_nconf(conf, &ctx, extensions, NULL)) {
1041296341Sdelphij                    BIO_printf(bio_err,
1042296341Sdelphij                               "Error Loading extension section %s\n",
1043296341Sdelphij                               extensions);
1044296341Sdelphij                    ret = 1;
1045296341Sdelphij                    goto err;
1046296341Sdelphij                }
1047296341Sdelphij            }
1048296341Sdelphij        }
104955714Skris
1050296341Sdelphij        if (startdate == NULL) {
1051296341Sdelphij            startdate = NCONF_get_string(conf, section,
1052296341Sdelphij                                         ENV_DEFAULT_STARTDATE);
1053296341Sdelphij            if (startdate == NULL)
1054296341Sdelphij                ERR_clear_error();
1055296341Sdelphij        }
1056296341Sdelphij        if (startdate && !ASN1_TIME_set_string(NULL, startdate)) {
1057296341Sdelphij            BIO_printf(bio_err,
1058296341Sdelphij                       "start date is invalid, it should be YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ\n");
1059296341Sdelphij            goto err;
1060296341Sdelphij        }
1061296341Sdelphij        if (startdate == NULL)
1062296341Sdelphij            startdate = "today";
106355714Skris
1064296341Sdelphij        if (enddate == NULL) {
1065296341Sdelphij            enddate = NCONF_get_string(conf, section, ENV_DEFAULT_ENDDATE);
1066296341Sdelphij            if (enddate == NULL)
1067296341Sdelphij                ERR_clear_error();
1068296341Sdelphij        }
1069296341Sdelphij        if (enddate && !ASN1_TIME_set_string(NULL, enddate)) {
1070296341Sdelphij            BIO_printf(bio_err,
1071296341Sdelphij                       "end date is invalid, it should be YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ\n");
1072296341Sdelphij            goto err;
1073296341Sdelphij        }
107455714Skris
1075296341Sdelphij        if (days == 0) {
1076296341Sdelphij            if (!NCONF_get_number(conf, section, ENV_DEFAULT_DAYS, &days))
1077296341Sdelphij                days = 0;
1078296341Sdelphij        }
1079296341Sdelphij        if (!enddate && (days == 0)) {
1080296341Sdelphij            BIO_printf(bio_err,
1081296341Sdelphij                       "cannot lookup how many days to certify for\n");
1082296341Sdelphij            goto err;
1083296341Sdelphij        }
108455714Skris
1085296341Sdelphij        if ((serial = load_serial(serialfile, create_ser, NULL)) == NULL) {
1086296341Sdelphij            BIO_printf(bio_err, "error while loading serial number\n");
1087296341Sdelphij            goto err;
1088296341Sdelphij        }
1089296341Sdelphij        if (verbose) {
1090296341Sdelphij            if (BN_is_zero(serial))
1091296341Sdelphij                BIO_printf(bio_err, "next serial number is 00\n");
1092296341Sdelphij            else {
1093296341Sdelphij                if ((f = BN_bn2hex(serial)) == NULL)
1094296341Sdelphij                    goto err;
1095296341Sdelphij                BIO_printf(bio_err, "next serial number is %s\n", f);
1096296341Sdelphij                OPENSSL_free(f);
1097296341Sdelphij            }
1098296341Sdelphij        }
109955714Skris
1100296341Sdelphij        if ((attribs = NCONF_get_section(conf, policy)) == NULL) {
1101296341Sdelphij            BIO_printf(bio_err, "unable to find 'section' for %s\n", policy);
1102296341Sdelphij            goto err;
1103296341Sdelphij        }
110455714Skris
1105296341Sdelphij        if ((cert_sk = sk_X509_new_null()) == NULL) {
1106296341Sdelphij            BIO_printf(bio_err, "Memory allocation failure\n");
1107296341Sdelphij            goto err;
1108296341Sdelphij        }
1109296341Sdelphij        if (spkac_file != NULL) {
1110296341Sdelphij            total++;
1111296341Sdelphij            j = certify_spkac(&x, spkac_file, pkey, x509, dgst, sigopts,
1112296341Sdelphij                              attribs, db, serial, subj, chtype, multirdn,
1113296341Sdelphij                              email_dn, startdate, enddate, days, extensions,
1114296341Sdelphij                              conf, verbose, certopt, nameopt, default_op,
1115296341Sdelphij                              ext_copy);
1116296341Sdelphij            if (j < 0)
1117296341Sdelphij                goto err;
1118296341Sdelphij            if (j > 0) {
1119296341Sdelphij                total_done++;
1120296341Sdelphij                BIO_printf(bio_err, "\n");
1121296341Sdelphij                if (!BN_add_word(serial, 1))
1122296341Sdelphij                    goto err;
1123296341Sdelphij                if (!sk_X509_push(cert_sk, x)) {
1124296341Sdelphij                    BIO_printf(bio_err, "Memory allocation failure\n");
1125296341Sdelphij                    goto err;
1126296341Sdelphij                }
1127296341Sdelphij                if (outfile) {
1128296341Sdelphij                    output_der = 1;
1129296341Sdelphij                    batch = 1;
1130296341Sdelphij                }
1131296341Sdelphij            }
1132296341Sdelphij        }
1133296341Sdelphij        if (ss_cert_file != NULL) {
1134296341Sdelphij            total++;
1135296341Sdelphij            j = certify_cert(&x, ss_cert_file, pkey, x509, dgst, sigopts,
1136296341Sdelphij                             attribs,
1137296341Sdelphij                             db, serial, subj, chtype, multirdn, email_dn,
1138296341Sdelphij                             startdate, enddate, days, batch, extensions,
1139296341Sdelphij                             conf, verbose, certopt, nameopt, default_op,
1140296341Sdelphij                             ext_copy, e);
1141296341Sdelphij            if (j < 0)
1142296341Sdelphij                goto err;
1143296341Sdelphij            if (j > 0) {
1144296341Sdelphij                total_done++;
1145296341Sdelphij                BIO_printf(bio_err, "\n");
1146296341Sdelphij                if (!BN_add_word(serial, 1))
1147296341Sdelphij                    goto err;
1148296341Sdelphij                if (!sk_X509_push(cert_sk, x)) {
1149296341Sdelphij                    BIO_printf(bio_err, "Memory allocation failure\n");
1150296341Sdelphij                    goto err;
1151296341Sdelphij                }
1152296341Sdelphij            }
1153296341Sdelphij        }
1154296341Sdelphij        if (infile != NULL) {
1155296341Sdelphij            total++;
1156296341Sdelphij            j = certify(&x, infile, pkey, x509p, dgst, sigopts, attribs, db,
1157296341Sdelphij                        serial, subj, chtype, multirdn, email_dn, startdate,
1158296341Sdelphij                        enddate, days, batch, extensions, conf, verbose,
1159296341Sdelphij                        certopt, nameopt, default_op, ext_copy, selfsign);
1160296341Sdelphij            if (j < 0)
1161296341Sdelphij                goto err;
1162296341Sdelphij            if (j > 0) {
1163296341Sdelphij                total_done++;
1164296341Sdelphij                BIO_printf(bio_err, "\n");
1165296341Sdelphij                if (!BN_add_word(serial, 1))
1166296341Sdelphij                    goto err;
1167296341Sdelphij                if (!sk_X509_push(cert_sk, x)) {
1168296341Sdelphij                    BIO_printf(bio_err, "Memory allocation failure\n");
1169296341Sdelphij                    goto err;
1170296341Sdelphij                }
1171296341Sdelphij            }
1172296341Sdelphij        }
1173296341Sdelphij        for (i = 0; i < argc; i++) {
1174296341Sdelphij            total++;
1175296341Sdelphij            j = certify(&x, argv[i], pkey, x509p, dgst, sigopts, attribs, db,
1176296341Sdelphij                        serial, subj, chtype, multirdn, email_dn, startdate,
1177296341Sdelphij                        enddate, days, batch, extensions, conf, verbose,
1178296341Sdelphij                        certopt, nameopt, default_op, ext_copy, selfsign);
1179296341Sdelphij            if (j < 0)
1180296341Sdelphij                goto err;
1181296341Sdelphij            if (j > 0) {
1182296341Sdelphij                total_done++;
1183296341Sdelphij                BIO_printf(bio_err, "\n");
1184296341Sdelphij                if (!BN_add_word(serial, 1))
1185296341Sdelphij                    goto err;
1186296341Sdelphij                if (!sk_X509_push(cert_sk, x)) {
1187296341Sdelphij                    BIO_printf(bio_err, "Memory allocation failure\n");
1188296341Sdelphij                    goto err;
1189296341Sdelphij                }
1190296341Sdelphij            }
1191296341Sdelphij        }
1192296341Sdelphij        /*
1193296341Sdelphij         * we have a stack of newly certified certificates and a data base
1194296341Sdelphij         * and serial number that need updating
1195296341Sdelphij         */
119655714Skris
1197296341Sdelphij        if (sk_X509_num(cert_sk) > 0) {
1198296341Sdelphij            if (!batch) {
1199296341Sdelphij                BIO_printf(bio_err,
1200296341Sdelphij                           "\n%d out of %d certificate requests certified, commit? [y/n]",
1201296341Sdelphij                           total_done, total);
1202296341Sdelphij                (void)BIO_flush(bio_err);
1203296341Sdelphij                buf[0][0] = '\0';
1204296341Sdelphij                if (!fgets(buf[0], 10, stdin)) {
1205296341Sdelphij                    BIO_printf(bio_err,
1206296341Sdelphij                               "CERTIFICATION CANCELED: I/O error\n");
1207296341Sdelphij                    ret = 0;
1208296341Sdelphij                    goto err;
1209296341Sdelphij                }
1210296341Sdelphij                if ((buf[0][0] != 'y') && (buf[0][0] != 'Y')) {
1211296341Sdelphij                    BIO_printf(bio_err, "CERTIFICATION CANCELED\n");
1212296341Sdelphij                    ret = 0;
1213296341Sdelphij                    goto err;
1214296341Sdelphij                }
1215296341Sdelphij            }
121655714Skris
1217296341Sdelphij            BIO_printf(bio_err, "Write out database with %d new entries\n",
1218296341Sdelphij                       sk_X509_num(cert_sk));
121955714Skris
1220296341Sdelphij            if (!save_serial(serialfile, "new", serial, NULL))
1221296341Sdelphij                goto err;
122255714Skris
1223296341Sdelphij            if (!save_index(dbfile, "new", db))
1224296341Sdelphij                goto err;
1225296341Sdelphij        }
122655714Skris
1227296341Sdelphij        if (verbose)
1228296341Sdelphij            BIO_printf(bio_err, "writing new certificates\n");
1229296341Sdelphij        for (i = 0; i < sk_X509_num(cert_sk); i++) {
1230296341Sdelphij            int k;
1231296341Sdelphij            char *n;
123255714Skris
1233296341Sdelphij            x = sk_X509_value(cert_sk, i);
123455714Skris
1235296341Sdelphij            j = x->cert_info->serialNumber->length;
1236296341Sdelphij            p = (const char *)x->cert_info->serialNumber->data;
1237109998Smarkm
1238296341Sdelphij            if (strlen(outdir) >= (size_t)(j ? BSIZE - j * 2 - 6 : BSIZE - 8)) {
1239296341Sdelphij                BIO_printf(bio_err, "certificate file name too long\n");
1240296341Sdelphij                goto err;
1241296341Sdelphij            }
1242296341Sdelphij
1243296341Sdelphij            strcpy(buf[2], outdir);
1244296341Sdelphij
1245109998Smarkm#ifndef OPENSSL_SYS_VMS
1246296341Sdelphij            BUF_strlcat(buf[2], "/", sizeof(buf[2]));
124755714Skris#endif
124855714Skris
1249296341Sdelphij            n = (char *)&(buf[2][strlen(buf[2])]);
1250296341Sdelphij            if (j > 0) {
1251296341Sdelphij                for (k = 0; k < j; k++) {
1252296341Sdelphij                    if (n >= &(buf[2][sizeof(buf[2])]))
1253296341Sdelphij                        break;
1254296341Sdelphij                    BIO_snprintf(n,
1255296341Sdelphij                                 &buf[2][0] + sizeof(buf[2]) - n,
1256296341Sdelphij                                 "%02X", (unsigned char)*(p++));
1257296341Sdelphij                    n += 2;
1258296341Sdelphij                }
1259296341Sdelphij            } else {
1260296341Sdelphij                *(n++) = '0';
1261296341Sdelphij                *(n++) = '0';
1262296341Sdelphij            }
1263296341Sdelphij            *(n++) = '.';
1264296341Sdelphij            *(n++) = 'p';
1265296341Sdelphij            *(n++) = 'e';
1266296341Sdelphij            *(n++) = 'm';
1267296341Sdelphij            *n = '\0';
1268296341Sdelphij            if (verbose)
1269296341Sdelphij                BIO_printf(bio_err, "writing %s\n", buf[2]);
127055714Skris
1271296341Sdelphij            if (BIO_write_filename(Cout, buf[2]) <= 0) {
1272296341Sdelphij                perror(buf[2]);
1273296341Sdelphij                goto err;
1274296341Sdelphij            }
1275296341Sdelphij            write_new_certificate(Cout, x, 0, notext);
1276296341Sdelphij            write_new_certificate(Sout, x, output_der, notext);
1277296341Sdelphij        }
127855714Skris
1279296341Sdelphij        if (sk_X509_num(cert_sk)) {
1280296341Sdelphij            /* Rename the database and the serial file */
1281296341Sdelphij            if (!rotate_serial(serialfile, "new", "old"))
1282296341Sdelphij                goto err;
128355714Skris
1284296341Sdelphij            if (!rotate_index(dbfile, "new", "old"))
1285296341Sdelphij                goto err;
128655714Skris
1287296341Sdelphij            BIO_printf(bio_err, "Data Base Updated\n");
1288296341Sdelphij        }
1289296341Sdelphij    }
129055714Skris
1291296341Sdelphij        /*****************************************************************/
1292296341Sdelphij    if (gencrl) {
1293296341Sdelphij        int crl_v2 = 0;
1294296341Sdelphij        if (!crl_ext) {
1295296341Sdelphij            crl_ext = NCONF_get_string(conf, section, ENV_CRLEXT);
1296296341Sdelphij            if (!crl_ext)
1297296341Sdelphij                ERR_clear_error();
1298296341Sdelphij        }
1299296341Sdelphij        if (crl_ext) {
1300296341Sdelphij            /* Check syntax of file */
1301296341Sdelphij            X509V3_CTX ctx;
1302296341Sdelphij            X509V3_set_ctx_test(&ctx);
1303296341Sdelphij            X509V3_set_nconf(&ctx, conf);
1304296341Sdelphij            if (!X509V3_EXT_add_nconf(conf, &ctx, crl_ext, NULL)) {
1305296341Sdelphij                BIO_printf(bio_err,
1306296341Sdelphij                           "Error Loading CRL extension section %s\n",
1307296341Sdelphij                           crl_ext);
1308296341Sdelphij                ret = 1;
1309296341Sdelphij                goto err;
1310296341Sdelphij            }
1311296341Sdelphij        }
1312127128Snectar
1313296341Sdelphij        if ((crlnumberfile = NCONF_get_string(conf, section, ENV_CRLNUMBER))
1314296341Sdelphij            != NULL)
1315296341Sdelphij            if ((crlnumber = load_serial(crlnumberfile, 0, NULL)) == NULL) {
1316296341Sdelphij                BIO_printf(bio_err, "error while loading CRL number\n");
1317296341Sdelphij                goto err;
1318296341Sdelphij            }
131955714Skris
1320296341Sdelphij        if (!crldays && !crlhours && !crlsec) {
1321296341Sdelphij            if (!NCONF_get_number(conf, section,
1322296341Sdelphij                                  ENV_DEFAULT_CRL_DAYS, &crldays))
1323296341Sdelphij                crldays = 0;
1324296341Sdelphij            if (!NCONF_get_number(conf, section,
1325296341Sdelphij                                  ENV_DEFAULT_CRL_HOURS, &crlhours))
1326296341Sdelphij                crlhours = 0;
1327296341Sdelphij            ERR_clear_error();
1328296341Sdelphij        }
1329296341Sdelphij        if ((crldays == 0) && (crlhours == 0) && (crlsec == 0)) {
1330296341Sdelphij            BIO_printf(bio_err,
1331296341Sdelphij                       "cannot lookup how long until the next CRL is issued\n");
1332296341Sdelphij            goto err;
1333296341Sdelphij        }
133455714Skris
1335296341Sdelphij        if (verbose)
1336296341Sdelphij            BIO_printf(bio_err, "making CRL\n");
1337296341Sdelphij        if ((crl = X509_CRL_new()) == NULL)
1338296341Sdelphij            goto err;
1339296341Sdelphij        if (!X509_CRL_set_issuer_name(crl, X509_get_subject_name(x509)))
1340296341Sdelphij            goto err;
134155714Skris
1342296341Sdelphij        tmptm = ASN1_TIME_new();
1343296341Sdelphij        if (!tmptm)
1344296341Sdelphij            goto err;
1345296341Sdelphij        X509_gmtime_adj(tmptm, 0);
1346296341Sdelphij        X509_CRL_set_lastUpdate(crl, tmptm);
1347296341Sdelphij        if (!X509_time_adj_ex(tmptm, crldays, crlhours * 60 * 60 + crlsec,
1348296341Sdelphij                              NULL)) {
1349296341Sdelphij            BIO_puts(bio_err, "error setting CRL nextUpdate\n");
1350296341Sdelphij            goto err;
1351296341Sdelphij        }
1352296341Sdelphij        X509_CRL_set_nextUpdate(crl, tmptm);
1353109998Smarkm
1354296341Sdelphij        ASN1_TIME_free(tmptm);
1355109998Smarkm
1356296341Sdelphij        for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
1357296341Sdelphij            pp = sk_OPENSSL_PSTRING_value(db->db->data, i);
1358296341Sdelphij            if (pp[DB_type][0] == DB_TYPE_REV) {
1359296341Sdelphij                if ((r = X509_REVOKED_new()) == NULL)
1360296341Sdelphij                    goto err;
1361296341Sdelphij                j = make_revoked(r, pp[DB_rev_date]);
1362296341Sdelphij                if (!j)
1363296341Sdelphij                    goto err;
1364296341Sdelphij                if (j == 2)
1365296341Sdelphij                    crl_v2 = 1;
1366296341Sdelphij                if (!BN_hex2bn(&serial, pp[DB_serial]))
1367296341Sdelphij                    goto err;
1368296341Sdelphij                tmpser = BN_to_ASN1_INTEGER(serial, NULL);
1369296341Sdelphij                BN_free(serial);
1370296341Sdelphij                serial = NULL;
1371296341Sdelphij                if (!tmpser)
1372296341Sdelphij                    goto err;
1373296341Sdelphij                X509_REVOKED_set_serialNumber(r, tmpser);
1374296341Sdelphij                ASN1_INTEGER_free(tmpser);
1375296341Sdelphij                X509_CRL_add0_revoked(crl, r);
1376296341Sdelphij            }
1377296341Sdelphij        }
137855714Skris
1379296341Sdelphij        /*
1380296341Sdelphij         * sort the data so it will be written in serial number order
1381296341Sdelphij         */
1382296341Sdelphij        X509_CRL_sort(crl);
138355714Skris
1384296341Sdelphij        /* we now have a CRL */
1385296341Sdelphij        if (verbose)
1386296341Sdelphij            BIO_printf(bio_err, "signing CRL\n");
138755714Skris
1388296341Sdelphij        /* Add any extensions asked for */
138955714Skris
1390296341Sdelphij        if (crl_ext || crlnumberfile != NULL) {
1391296341Sdelphij            X509V3_CTX crlctx;
1392296341Sdelphij            X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0);
1393296341Sdelphij            X509V3_set_nconf(&crlctx, conf);
139455714Skris
1395296341Sdelphij            if (crl_ext)
1396296341Sdelphij                if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx, crl_ext, crl))
1397296341Sdelphij                    goto err;
1398296341Sdelphij            if (crlnumberfile != NULL) {
1399296341Sdelphij                tmpser = BN_to_ASN1_INTEGER(crlnumber, NULL);
1400296341Sdelphij                if (!tmpser)
1401296341Sdelphij                    goto err;
1402296341Sdelphij                X509_CRL_add1_ext_i2d(crl, NID_crl_number, tmpser, 0, 0);
1403296341Sdelphij                ASN1_INTEGER_free(tmpser);
1404296341Sdelphij                crl_v2 = 1;
1405296341Sdelphij                if (!BN_add_word(crlnumber, 1))
1406296341Sdelphij                    goto err;
1407296341Sdelphij            }
1408296341Sdelphij        }
1409296341Sdelphij        if (crl_ext || crl_v2) {
1410296341Sdelphij            if (!X509_CRL_set_version(crl, 1))
1411296341Sdelphij                goto err;       /* version 2 CRL */
1412296341Sdelphij        }
1413127128Snectar
1414296341Sdelphij        /* we have a CRL number that need updating */
1415296341Sdelphij        if (crlnumberfile != NULL)
1416296341Sdelphij            if (!save_serial(crlnumberfile, "new", crlnumber, NULL))
1417296341Sdelphij                goto err;
141855714Skris
1419296341Sdelphij        if (crlnumber) {
1420296341Sdelphij            BN_free(crlnumber);
1421296341Sdelphij            crlnumber = NULL;
1422296341Sdelphij        }
1423238405Sjkim
1424296341Sdelphij        if (!do_X509_CRL_sign(bio_err, crl, pkey, dgst, sigopts))
1425296341Sdelphij            goto err;
1426127128Snectar
1427296341Sdelphij        PEM_write_bio_X509_CRL(Sout, crl);
1428127128Snectar
1429296341Sdelphij        if (crlnumberfile != NULL) /* Rename the crlnumber file */
1430296341Sdelphij            if (!rotate_serial(crlnumberfile, "new", "old"))
1431296341Sdelphij                goto err;
143255714Skris
1433296341Sdelphij    }
1434296341Sdelphij        /*****************************************************************/
1435296341Sdelphij    if (dorevoke) {
1436296341Sdelphij        if (infile == NULL) {
1437296341Sdelphij            BIO_printf(bio_err, "no input files\n");
1438296341Sdelphij            goto err;
1439296341Sdelphij        } else {
1440296341Sdelphij            X509 *revcert;
1441296341Sdelphij            revcert = load_cert(bio_err, infile, FORMAT_PEM, NULL, e, infile);
1442296341Sdelphij            if (revcert == NULL)
1443296341Sdelphij                goto err;
1444296341Sdelphij            j = do_revoke(revcert, db, rev_type, rev_arg);
1445296341Sdelphij            if (j <= 0)
1446296341Sdelphij                goto err;
1447296341Sdelphij            X509_free(revcert);
1448109998Smarkm
1449296341Sdelphij            if (!save_index(dbfile, "new", db))
1450296341Sdelphij                goto err;
1451127128Snectar
1452296341Sdelphij            if (!rotate_index(dbfile, "new", "old"))
1453296341Sdelphij                goto err;
145455714Skris
1455296341Sdelphij            BIO_printf(bio_err, "Data Base Updated\n");
1456296341Sdelphij        }
1457296341Sdelphij    }
1458296341Sdelphij        /*****************************************************************/
1459296341Sdelphij    ret = 0;
1460296341Sdelphij err:
1461296341Sdelphij    if (tofree)
1462296341Sdelphij        OPENSSL_free(tofree);
1463296341Sdelphij    BIO_free_all(Cout);
1464296341Sdelphij    BIO_free_all(Sout);
1465296341Sdelphij    BIO_free_all(out);
1466296341Sdelphij    BIO_free_all(in);
146755714Skris
1468296341Sdelphij    if (cert_sk)
1469296341Sdelphij        sk_X509_pop_free(cert_sk, X509_free);
147055714Skris
1471296341Sdelphij    if (ret)
1472296341Sdelphij        ERR_print_errors(bio_err);
1473296341Sdelphij    app_RAND_write_file(randfile, bio_err);
1474296341Sdelphij    if (free_key && key)
1475296341Sdelphij        OPENSSL_free(key);
1476296341Sdelphij    BN_free(serial);
1477296341Sdelphij    BN_free(crlnumber);
1478296341Sdelphij    free_index(db);
1479296341Sdelphij    if (sigopts)
1480296341Sdelphij        sk_OPENSSL_STRING_free(sigopts);
1481296341Sdelphij    EVP_PKEY_free(pkey);
1482296341Sdelphij    if (x509)
1483296341Sdelphij        X509_free(x509);
1484296341Sdelphij    X509_CRL_free(crl);
1485296341Sdelphij    NCONF_free(conf);
1486296341Sdelphij    NCONF_free(extconf);
1487296341Sdelphij    OBJ_cleanup();
1488296341Sdelphij    apps_shutdown();
1489296341Sdelphij    OPENSSL_EXIT(ret);
1490296341Sdelphij}
1491296341Sdelphij
1492160814Ssimonstatic void lookup_fail(const char *name, const char *tag)
1493296341Sdelphij{
1494296341Sdelphij    BIO_printf(bio_err, "variable lookup failed for %s::%s\n", name, tag);
1495296341Sdelphij}
149655714Skris
149755714Skrisstatic int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1498296341Sdelphij                   const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
1499296341Sdelphij                   STACK_OF(CONF_VALUE) *policy, CA_DB *db,
1500296341Sdelphij                   BIGNUM *serial, char *subj, unsigned long chtype,
1501296341Sdelphij                   int multirdn, int email_dn, char *startdate, char *enddate,
1502296341Sdelphij                   long days, int batch, char *ext_sect, CONF *lconf,
1503296341Sdelphij                   int verbose, unsigned long certopt, unsigned long nameopt,
1504296341Sdelphij                   int default_op, int ext_copy, int selfsign)
1505296341Sdelphij{
1506296341Sdelphij    X509_REQ *req = NULL;
1507296341Sdelphij    BIO *in = NULL;
1508296341Sdelphij    EVP_PKEY *pktmp = NULL;
1509296341Sdelphij    int ok = -1, i;
151055714Skris
1511296341Sdelphij    in = BIO_new(BIO_s_file());
151255714Skris
1513296341Sdelphij    if (BIO_read_filename(in, infile) <= 0) {
1514296341Sdelphij        perror(infile);
1515296341Sdelphij        goto err;
1516296341Sdelphij    }
1517296341Sdelphij    if ((req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL)) == NULL) {
1518296341Sdelphij        BIO_printf(bio_err, "Error reading certificate request in %s\n",
1519296341Sdelphij                   infile);
1520296341Sdelphij        goto err;
1521296341Sdelphij    }
1522296341Sdelphij    if (verbose)
1523296341Sdelphij        X509_REQ_print(bio_err, req);
152455714Skris
1525296341Sdelphij    BIO_printf(bio_err, "Check that the request matches the signature\n");
152655714Skris
1527296341Sdelphij    if (selfsign && !X509_REQ_check_private_key(req, pkey)) {
1528296341Sdelphij        BIO_printf(bio_err,
1529296341Sdelphij                   "Certificate request and CA private key do not match\n");
1530296341Sdelphij        ok = 0;
1531296341Sdelphij        goto err;
1532296341Sdelphij    }
1533296341Sdelphij    if ((pktmp = X509_REQ_get_pubkey(req)) == NULL) {
1534296341Sdelphij        BIO_printf(bio_err, "error unpacking public key\n");
1535296341Sdelphij        goto err;
1536296341Sdelphij    }
1537296341Sdelphij    i = X509_REQ_verify(req, pktmp);
1538296341Sdelphij    EVP_PKEY_free(pktmp);
1539296341Sdelphij    if (i < 0) {
1540296341Sdelphij        ok = 0;
1541296341Sdelphij        BIO_printf(bio_err, "Signature verification problems....\n");
1542296341Sdelphij        ERR_print_errors(bio_err);
1543296341Sdelphij        goto err;
1544296341Sdelphij    }
1545296341Sdelphij    if (i == 0) {
1546296341Sdelphij        ok = 0;
1547296341Sdelphij        BIO_printf(bio_err,
1548296341Sdelphij                   "Signature did not match the certificate request\n");
1549296341Sdelphij        ERR_print_errors(bio_err);
1550296341Sdelphij        goto err;
1551296341Sdelphij    } else
1552296341Sdelphij        BIO_printf(bio_err, "Signature ok\n");
155355714Skris
1554296341Sdelphij    ok = do_body(xret, pkey, x509, dgst, sigopts, policy, db, serial, subj,
1555296341Sdelphij                 chtype, multirdn, email_dn, startdate, enddate, days, batch,
1556296341Sdelphij                 verbose, req, ext_sect, lconf, certopt, nameopt, default_op,
1557296341Sdelphij                 ext_copy, selfsign);
155855714Skris
1559296341Sdelphij err:
1560296341Sdelphij    if (req != NULL)
1561296341Sdelphij        X509_REQ_free(req);
1562296341Sdelphij    if (in != NULL)
1563296341Sdelphij        BIO_free(in);
1564296341Sdelphij    return (ok);
1565296341Sdelphij}
156655714Skris
156755714Skrisstatic int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1568296341Sdelphij                        const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
1569296341Sdelphij                        STACK_OF(CONF_VALUE) *policy, CA_DB *db,
1570296341Sdelphij                        BIGNUM *serial, char *subj, unsigned long chtype,
1571296341Sdelphij                        int multirdn, int email_dn, char *startdate,
1572296341Sdelphij                        char *enddate, long days, int batch, char *ext_sect,
1573296341Sdelphij                        CONF *lconf, int verbose, unsigned long certopt,
1574296341Sdelphij                        unsigned long nameopt, int default_op, int ext_copy,
1575296341Sdelphij                        ENGINE *e)
1576296341Sdelphij{
1577296341Sdelphij    X509 *req = NULL;
1578296341Sdelphij    X509_REQ *rreq = NULL;
1579296341Sdelphij    EVP_PKEY *pktmp = NULL;
1580296341Sdelphij    int ok = -1, i;
158155714Skris
1582296341Sdelphij    if ((req =
1583296341Sdelphij         load_cert(bio_err, infile, FORMAT_PEM, NULL, e, infile)) == NULL)
1584296341Sdelphij        goto err;
1585296341Sdelphij    if (verbose)
1586296341Sdelphij        X509_print(bio_err, req);
158755714Skris
1588296341Sdelphij    BIO_printf(bio_err, "Check that the request matches the signature\n");
158955714Skris
1590296341Sdelphij    if ((pktmp = X509_get_pubkey(req)) == NULL) {
1591296341Sdelphij        BIO_printf(bio_err, "error unpacking public key\n");
1592296341Sdelphij        goto err;
1593296341Sdelphij    }
1594296341Sdelphij    i = X509_verify(req, pktmp);
1595296341Sdelphij    EVP_PKEY_free(pktmp);
1596296341Sdelphij    if (i < 0) {
1597296341Sdelphij        ok = 0;
1598296341Sdelphij        BIO_printf(bio_err, "Signature verification problems....\n");
1599296341Sdelphij        goto err;
1600296341Sdelphij    }
1601296341Sdelphij    if (i == 0) {
1602296341Sdelphij        ok = 0;
1603296341Sdelphij        BIO_printf(bio_err, "Signature did not match the certificate\n");
1604296341Sdelphij        goto err;
1605296341Sdelphij    } else
1606296341Sdelphij        BIO_printf(bio_err, "Signature ok\n");
160755714Skris
1608296341Sdelphij    if ((rreq = X509_to_X509_REQ(req, NULL, EVP_md5())) == NULL)
1609296341Sdelphij        goto err;
161055714Skris
1611296341Sdelphij    ok = do_body(xret, pkey, x509, dgst, sigopts, policy, db, serial, subj,
1612296341Sdelphij                 chtype, multirdn, email_dn, startdate, enddate, days, batch,
1613296341Sdelphij                 verbose, rreq, ext_sect, lconf, certopt, nameopt, default_op,
1614296341Sdelphij                 ext_copy, 0);
161555714Skris
1616296341Sdelphij err:
1617296341Sdelphij    if (rreq != NULL)
1618296341Sdelphij        X509_REQ_free(rreq);
1619296341Sdelphij    if (req != NULL)
1620296341Sdelphij        X509_free(req);
1621296341Sdelphij    return (ok);
1622296341Sdelphij}
162355714Skris
1624296341Sdelphijstatic int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
1625296341Sdelphij                   const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts,
1626296341Sdelphij                   STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial,
1627296341Sdelphij                   char *subj, unsigned long chtype, int multirdn,
1628296341Sdelphij                   int email_dn, char *startdate, char *enddate, long days,
1629296341Sdelphij                   int batch, int verbose, X509_REQ *req, char *ext_sect,
1630296341Sdelphij                   CONF *lconf, unsigned long certopt, unsigned long nameopt,
1631296341Sdelphij                   int default_op, int ext_copy, int selfsign)
1632296341Sdelphij{
1633296341Sdelphij    X509_NAME *name = NULL, *CAname = NULL, *subject = NULL, *dn_subject =
1634296341Sdelphij        NULL;
1635296341Sdelphij    ASN1_UTCTIME *tm, *tmptm;
1636296341Sdelphij    ASN1_STRING *str, *str2;
1637296341Sdelphij    ASN1_OBJECT *obj;
1638296341Sdelphij    X509 *ret = NULL;
1639296341Sdelphij    X509_CINF *ci;
1640296341Sdelphij    X509_NAME_ENTRY *ne;
1641296341Sdelphij    X509_NAME_ENTRY *tne, *push;
1642296341Sdelphij    EVP_PKEY *pktmp;
1643296341Sdelphij    int ok = -1, i, j, last, nid;
1644296341Sdelphij    const char *p;
1645296341Sdelphij    CONF_VALUE *cv;
1646296341Sdelphij    OPENSSL_STRING row[DB_NUMBER];
1647296341Sdelphij    OPENSSL_STRING *irow = NULL;
1648296341Sdelphij    OPENSSL_STRING *rrow = NULL;
1649296341Sdelphij    char buf[25];
165055714Skris
1651296341Sdelphij    tmptm = ASN1_UTCTIME_new();
1652296341Sdelphij    if (tmptm == NULL) {
1653296341Sdelphij        BIO_printf(bio_err, "malloc error\n");
1654296341Sdelphij        return (0);
1655296341Sdelphij    }
165655714Skris
1657296341Sdelphij    for (i = 0; i < DB_NUMBER; i++)
1658296341Sdelphij        row[i] = NULL;
165955714Skris
1660296341Sdelphij    if (subj) {
1661296341Sdelphij        X509_NAME *n = parse_name(subj, chtype, multirdn);
1662109998Smarkm
1663296341Sdelphij        if (!n) {
1664296341Sdelphij            ERR_print_errors(bio_err);
1665296341Sdelphij            goto err;
1666296341Sdelphij        }
1667296341Sdelphij        X509_REQ_set_subject_name(req, n);
1668296341Sdelphij        req->req_info->enc.modified = 1;
1669296341Sdelphij        X509_NAME_free(n);
1670296341Sdelphij    }
1671109998Smarkm
1672296341Sdelphij    if (default_op)
1673296341Sdelphij        BIO_printf(bio_err,
1674296341Sdelphij                   "The Subject's Distinguished Name is as follows\n");
1675109998Smarkm
1676296341Sdelphij    name = X509_REQ_get_subject_name(req);
1677296341Sdelphij    for (i = 0; i < X509_NAME_entry_count(name); i++) {
1678296341Sdelphij        ne = X509_NAME_get_entry(name, i);
1679296341Sdelphij        str = X509_NAME_ENTRY_get_data(ne);
1680296341Sdelphij        obj = X509_NAME_ENTRY_get_object(ne);
168155714Skris
1682296341Sdelphij        if (msie_hack) {
1683296341Sdelphij            /* assume all type should be strings */
1684296341Sdelphij            nid = OBJ_obj2nid(ne->object);
168555714Skris
1686296341Sdelphij            if (str->type == V_ASN1_UNIVERSALSTRING)
1687296341Sdelphij                ASN1_UNIVERSALSTRING_to_string(str);
168855714Skris
1689296341Sdelphij            if ((str->type == V_ASN1_IA5STRING) &&
1690296341Sdelphij                (nid != NID_pkcs9_emailAddress))
1691296341Sdelphij                str->type = V_ASN1_T61STRING;
169255714Skris
1693296341Sdelphij            if ((nid == NID_pkcs9_emailAddress) &&
1694296341Sdelphij                (str->type == V_ASN1_PRINTABLESTRING))
1695296341Sdelphij                str->type = V_ASN1_IA5STRING;
1696296341Sdelphij        }
169755714Skris
1698296341Sdelphij        /* If no EMAIL is wanted in the subject */
1699296341Sdelphij        if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) && (!email_dn))
1700296341Sdelphij            continue;
170155714Skris
1702296341Sdelphij        /* check some things */
1703296341Sdelphij        if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) &&
1704296341Sdelphij            (str->type != V_ASN1_IA5STRING)) {
1705296341Sdelphij            BIO_printf(bio_err,
1706296341Sdelphij                       "\nemailAddress type needs to be of type IA5STRING\n");
1707296341Sdelphij            goto err;
1708296341Sdelphij        }
1709296341Sdelphij        if ((str->type != V_ASN1_BMPSTRING)
1710296341Sdelphij            && (str->type != V_ASN1_UTF8STRING)) {
1711296341Sdelphij            j = ASN1_PRINTABLE_type(str->data, str->length);
1712296341Sdelphij            if (((j == V_ASN1_T61STRING) &&
1713296341Sdelphij                 (str->type != V_ASN1_T61STRING)) ||
1714296341Sdelphij                ((j == V_ASN1_IA5STRING) &&
1715296341Sdelphij                 (str->type == V_ASN1_PRINTABLESTRING))) {
1716296341Sdelphij                BIO_printf(bio_err,
1717296341Sdelphij                           "\nThe string contains characters that are illegal for the ASN.1 type\n");
1718296341Sdelphij                goto err;
1719296341Sdelphij            }
1720296341Sdelphij        }
1721109998Smarkm
1722296341Sdelphij        if (default_op)
1723296341Sdelphij            old_entry_print(bio_err, obj, str);
1724296341Sdelphij    }
172555714Skris
1726296341Sdelphij    /* Ok, now we check the 'policy' stuff. */
1727296341Sdelphij    if ((subject = X509_NAME_new()) == NULL) {
1728296341Sdelphij        BIO_printf(bio_err, "Memory allocation failure\n");
1729296341Sdelphij        goto err;
1730296341Sdelphij    }
173155714Skris
1732296341Sdelphij    /* take a copy of the issuer name before we mess with it. */
1733296341Sdelphij    if (selfsign)
1734296341Sdelphij        CAname = X509_NAME_dup(name);
1735296341Sdelphij    else
1736296341Sdelphij        CAname = X509_NAME_dup(x509->cert_info->subject);
1737296341Sdelphij    if (CAname == NULL)
1738296341Sdelphij        goto err;
1739296341Sdelphij    str = str2 = NULL;
174055714Skris
1741296341Sdelphij    for (i = 0; i < sk_CONF_VALUE_num(policy); i++) {
1742296341Sdelphij        cv = sk_CONF_VALUE_value(policy, i); /* get the object id */
1743296341Sdelphij        if ((j = OBJ_txt2nid(cv->name)) == NID_undef) {
1744296341Sdelphij            BIO_printf(bio_err,
1745296341Sdelphij                       "%s:unknown object type in 'policy' configuration\n",
1746296341Sdelphij                       cv->name);
1747296341Sdelphij            goto err;
1748296341Sdelphij        }
1749296341Sdelphij        obj = OBJ_nid2obj(j);
175055714Skris
1751296341Sdelphij        last = -1;
1752296341Sdelphij        for (;;) {
1753296341Sdelphij            /* lookup the object in the supplied name list */
1754296341Sdelphij            j = X509_NAME_get_index_by_OBJ(name, obj, last);
1755296341Sdelphij            if (j < 0) {
1756296341Sdelphij                if (last != -1)
1757296341Sdelphij                    break;
1758296341Sdelphij                tne = NULL;
1759296341Sdelphij            } else {
1760296341Sdelphij                tne = X509_NAME_get_entry(name, j);
1761296341Sdelphij            }
1762296341Sdelphij            last = j;
176355714Skris
1764296341Sdelphij            /* depending on the 'policy', decide what to do. */
1765296341Sdelphij            push = NULL;
1766296341Sdelphij            if (strcmp(cv->value, "optional") == 0) {
1767296341Sdelphij                if (tne != NULL)
1768296341Sdelphij                    push = tne;
1769296341Sdelphij            } else if (strcmp(cv->value, "supplied") == 0) {
1770296341Sdelphij                if (tne == NULL) {
1771296341Sdelphij                    BIO_printf(bio_err,
1772296341Sdelphij                               "The %s field needed to be supplied and was missing\n",
1773296341Sdelphij                               cv->name);
1774296341Sdelphij                    goto err;
1775296341Sdelphij                } else
1776296341Sdelphij                    push = tne;
1777296341Sdelphij            } else if (strcmp(cv->value, "match") == 0) {
1778296341Sdelphij                int last2;
177955714Skris
1780296341Sdelphij                if (tne == NULL) {
1781296341Sdelphij                    BIO_printf(bio_err,
1782296341Sdelphij                               "The mandatory %s field was missing\n",
1783296341Sdelphij                               cv->name);
1784296341Sdelphij                    goto err;
1785296341Sdelphij                }
178655714Skris
1787296341Sdelphij                last2 = -1;
178855714Skris
1789296341Sdelphij again2:
1790296341Sdelphij                j = X509_NAME_get_index_by_OBJ(CAname, obj, last2);
1791296341Sdelphij                if ((j < 0) && (last2 == -1)) {
1792296341Sdelphij                    BIO_printf(bio_err,
1793296341Sdelphij                               "The %s field does not exist in the CA certificate,\nthe 'policy' is misconfigured\n",
1794296341Sdelphij                               cv->name);
1795296341Sdelphij                    goto err;
1796296341Sdelphij                }
1797296341Sdelphij                if (j >= 0) {
1798296341Sdelphij                    push = X509_NAME_get_entry(CAname, j);
1799296341Sdelphij                    str = X509_NAME_ENTRY_get_data(tne);
1800296341Sdelphij                    str2 = X509_NAME_ENTRY_get_data(push);
1801296341Sdelphij                    last2 = j;
1802296341Sdelphij                    if (ASN1_STRING_cmp(str, str2) != 0)
1803296341Sdelphij                        goto again2;
1804296341Sdelphij                }
1805296341Sdelphij                if (j < 0) {
1806296341Sdelphij                    BIO_printf(bio_err,
1807296341Sdelphij                               "The %s field needed to be the same in the\nCA certificate (%s) and the request (%s)\n",
1808296341Sdelphij                               cv->name,
1809296341Sdelphij                               ((str2 == NULL) ? "NULL" : (char *)str2->data),
1810296341Sdelphij                               ((str == NULL) ? "NULL" : (char *)str->data));
1811296341Sdelphij                    goto err;
1812296341Sdelphij                }
1813296341Sdelphij            } else {
1814296341Sdelphij                BIO_printf(bio_err,
1815296341Sdelphij                           "%s:invalid type in 'policy' configuration\n",
1816296341Sdelphij                           cv->value);
1817296341Sdelphij                goto err;
1818296341Sdelphij            }
181955714Skris
1820296341Sdelphij            if (push != NULL) {
1821296341Sdelphij                if (!X509_NAME_add_entry(subject, push, -1, 0)) {
1822296341Sdelphij                    if (push != NULL)
1823296341Sdelphij                        X509_NAME_ENTRY_free(push);
1824296341Sdelphij                    BIO_printf(bio_err, "Memory allocation failure\n");
1825296341Sdelphij                    goto err;
1826296341Sdelphij                }
1827296341Sdelphij            }
1828296341Sdelphij            if (j < 0)
1829296341Sdelphij                break;
1830296341Sdelphij        }
1831296341Sdelphij    }
183255714Skris
1833296341Sdelphij    if (preserve) {
1834296341Sdelphij        X509_NAME_free(subject);
1835296341Sdelphij        /* subject=X509_NAME_dup(X509_REQ_get_subject_name(req)); */
1836296341Sdelphij        subject = X509_NAME_dup(name);
1837296341Sdelphij        if (subject == NULL)
1838296341Sdelphij            goto err;
1839296341Sdelphij    }
184055714Skris
1841296341Sdelphij    if (verbose)
1842296341Sdelphij        BIO_printf(bio_err,
1843296341Sdelphij                   "The subject name appears to be ok, checking data base for clashes\n");
184455714Skris
1845296341Sdelphij    /* Build the correct Subject if no e-mail is wanted in the subject */
1846296341Sdelphij    /*
1847296341Sdelphij     * and add it later on because of the method extensions are added
1848296341Sdelphij     * (altName)
1849296341Sdelphij     */
1850109998Smarkm
1851296341Sdelphij    if (email_dn)
1852296341Sdelphij        dn_subject = subject;
1853296341Sdelphij    else {
1854296341Sdelphij        X509_NAME_ENTRY *tmpne;
1855296341Sdelphij        /*
1856296341Sdelphij         * Its best to dup the subject DN and then delete any email addresses
1857296341Sdelphij         * because this retains its structure.
1858296341Sdelphij         */
1859296341Sdelphij        if (!(dn_subject = X509_NAME_dup(subject))) {
1860296341Sdelphij            BIO_printf(bio_err, "Memory allocation failure\n");
1861296341Sdelphij            goto err;
1862296341Sdelphij        }
1863296341Sdelphij        while ((i = X509_NAME_get_index_by_NID(dn_subject,
1864296341Sdelphij                                               NID_pkcs9_emailAddress,
1865296341Sdelphij                                               -1)) >= 0) {
1866296341Sdelphij            tmpne = X509_NAME_get_entry(dn_subject, i);
1867296341Sdelphij            X509_NAME_delete_entry(dn_subject, i);
1868296341Sdelphij            X509_NAME_ENTRY_free(tmpne);
1869296341Sdelphij        }
1870296341Sdelphij    }
187155714Skris
1872296341Sdelphij    if (BN_is_zero(serial))
1873296341Sdelphij        row[DB_serial] = BUF_strdup("00");
1874296341Sdelphij    else
1875296341Sdelphij        row[DB_serial] = BN_bn2hex(serial);
1876296341Sdelphij    if (row[DB_serial] == NULL) {
1877296341Sdelphij        BIO_printf(bio_err, "Memory allocation failure\n");
1878296341Sdelphij        goto err;
1879296341Sdelphij    }
1880238405Sjkim
1881296341Sdelphij    if (db->attributes.unique_subject) {
1882296341Sdelphij        OPENSSL_STRING *crow = row;
188355714Skris
1884296341Sdelphij        rrow = TXT_DB_get_by_index(db->db, DB_name, crow);
1885296341Sdelphij        if (rrow != NULL) {
1886296341Sdelphij            BIO_printf(bio_err,
1887296341Sdelphij                       "ERROR:There is already a certificate for %s\n",
1888296341Sdelphij                       row[DB_name]);
1889296341Sdelphij        }
1890296341Sdelphij    }
1891296341Sdelphij    if (rrow == NULL) {
1892296341Sdelphij        rrow = TXT_DB_get_by_index(db->db, DB_serial, row);
1893296341Sdelphij        if (rrow != NULL) {
1894296341Sdelphij            BIO_printf(bio_err,
1895296341Sdelphij                       "ERROR:Serial number %s has already been issued,\n",
1896296341Sdelphij                       row[DB_serial]);
1897296341Sdelphij            BIO_printf(bio_err,
1898296341Sdelphij                       "      check the database/serial_file for corruption\n");
1899296341Sdelphij        }
1900296341Sdelphij    }
190155714Skris
1902296341Sdelphij    if (rrow != NULL) {
1903296341Sdelphij        BIO_printf(bio_err, "The matching entry has the following details\n");
1904296341Sdelphij        if (rrow[DB_type][0] == 'E')
1905296341Sdelphij            p = "Expired";
1906296341Sdelphij        else if (rrow[DB_type][0] == 'R')
1907296341Sdelphij            p = "Revoked";
1908296341Sdelphij        else if (rrow[DB_type][0] == 'V')
1909296341Sdelphij            p = "Valid";
1910296341Sdelphij        else
1911296341Sdelphij            p = "\ninvalid type, Data base error\n";
1912296341Sdelphij        BIO_printf(bio_err, "Type          :%s\n", p);;
1913296341Sdelphij        if (rrow[DB_type][0] == 'R') {
1914296341Sdelphij            p = rrow[DB_exp_date];
1915296341Sdelphij            if (p == NULL)
1916296341Sdelphij                p = "undef";
1917296341Sdelphij            BIO_printf(bio_err, "Was revoked on:%s\n", p);
1918296341Sdelphij        }
1919296341Sdelphij        p = rrow[DB_exp_date];
1920296341Sdelphij        if (p == NULL)
1921296341Sdelphij            p = "undef";
1922296341Sdelphij        BIO_printf(bio_err, "Expires on    :%s\n", p);
1923296341Sdelphij        p = rrow[DB_serial];
1924296341Sdelphij        if (p == NULL)
1925296341Sdelphij            p = "undef";
1926296341Sdelphij        BIO_printf(bio_err, "Serial Number :%s\n", p);
1927296341Sdelphij        p = rrow[DB_file];
1928296341Sdelphij        if (p == NULL)
1929296341Sdelphij            p = "undef";
1930296341Sdelphij        BIO_printf(bio_err, "File name     :%s\n", p);
1931296341Sdelphij        p = rrow[DB_name];
1932296341Sdelphij        if (p == NULL)
1933296341Sdelphij            p = "undef";
1934296341Sdelphij        BIO_printf(bio_err, "Subject Name  :%s\n", p);
1935296341Sdelphij        ok = -1;                /* This is now a 'bad' error. */
1936296341Sdelphij        goto err;
1937296341Sdelphij    }
193855714Skris
1939296341Sdelphij    /* We are now totally happy, lets make and sign the certificate */
1940296341Sdelphij    if (verbose)
1941296341Sdelphij        BIO_printf(bio_err,
1942296341Sdelphij                   "Everything appears to be ok, creating and signing the certificate\n");
194355714Skris
1944296341Sdelphij    if ((ret = X509_new()) == NULL)
1945296341Sdelphij        goto err;
1946296341Sdelphij    ci = ret->cert_info;
1947296341Sdelphij
194855714Skris#ifdef X509_V3
1949296341Sdelphij    /* Make it an X509 v3 certificate. */
1950296341Sdelphij    if (!X509_set_version(ret, 2))
1951296341Sdelphij        goto err;
195255714Skris#endif
195355714Skris
1954296341Sdelphij    if (BN_to_ASN1_INTEGER(serial, ci->serialNumber) == NULL)
1955296341Sdelphij        goto err;
1956296341Sdelphij    if (selfsign) {
1957296341Sdelphij        if (!X509_set_issuer_name(ret, subject))
1958296341Sdelphij            goto err;
1959296341Sdelphij    } else {
1960296341Sdelphij        if (!X509_set_issuer_name(ret, X509_get_subject_name(x509)))
1961296341Sdelphij            goto err;
1962296341Sdelphij    }
196355714Skris
1964296341Sdelphij    if (strcmp(startdate, "today") == 0)
1965296341Sdelphij        X509_gmtime_adj(X509_get_notBefore(ret), 0);
1966296341Sdelphij    else
1967296341Sdelphij        ASN1_TIME_set_string(X509_get_notBefore(ret), startdate);
196855714Skris
1969296341Sdelphij    if (enddate == NULL)
1970296341Sdelphij        X509_time_adj_ex(X509_get_notAfter(ret), days, 0, NULL);
1971296341Sdelphij    else
1972296341Sdelphij        ASN1_TIME_set_string(X509_get_notAfter(ret), enddate);
197355714Skris
1974296341Sdelphij    if (!X509_set_subject_name(ret, subject))
1975296341Sdelphij        goto err;
197655714Skris
1977296341Sdelphij    pktmp = X509_REQ_get_pubkey(req);
1978296341Sdelphij    i = X509_set_pubkey(ret, pktmp);
1979296341Sdelphij    EVP_PKEY_free(pktmp);
1980296341Sdelphij    if (!i)
1981296341Sdelphij        goto err;
198255714Skris
1983296341Sdelphij    /* Lets add the extensions, if there are any */
1984296341Sdelphij    if (ext_sect) {
1985296341Sdelphij        X509V3_CTX ctx;
1986296341Sdelphij        if (ci->version == NULL)
1987296341Sdelphij            if ((ci->version = ASN1_INTEGER_new()) == NULL)
1988296341Sdelphij                goto err;
1989296341Sdelphij        ASN1_INTEGER_set(ci->version, 2); /* version 3 certificate */
199055714Skris
1991296341Sdelphij        /*
1992296341Sdelphij         * Free the current entries if any, there should not be any I believe
1993296341Sdelphij         */
1994296341Sdelphij        if (ci->extensions != NULL)
1995296341Sdelphij            sk_X509_EXTENSION_pop_free(ci->extensions, X509_EXTENSION_free);
199655714Skris
1997296341Sdelphij        ci->extensions = NULL;
199855714Skris
1999296341Sdelphij        /* Initialize the context structure */
2000296341Sdelphij        if (selfsign)
2001296341Sdelphij            X509V3_set_ctx(&ctx, ret, ret, req, NULL, 0);
2002296341Sdelphij        else
2003296341Sdelphij            X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0);
200455714Skris
2005296341Sdelphij        if (extconf) {
2006296341Sdelphij            if (verbose)
2007296341Sdelphij                BIO_printf(bio_err, "Extra configuration file found\n");
200855714Skris
2009296341Sdelphij            /* Use the extconf configuration db LHASH */
2010296341Sdelphij            X509V3_set_nconf(&ctx, extconf);
2011109998Smarkm
2012296341Sdelphij            /* Test the structure (needed?) */
2013296341Sdelphij            /* X509V3_set_ctx_test(&ctx); */
2014109998Smarkm
2015296341Sdelphij            /* Adds exts contained in the configuration file */
2016296341Sdelphij            if (!X509V3_EXT_add_nconf(extconf, &ctx, ext_sect, ret)) {
2017296341Sdelphij                BIO_printf(bio_err,
2018296341Sdelphij                           "ERROR: adding extensions in section %s\n",
2019296341Sdelphij                           ext_sect);
2020296341Sdelphij                ERR_print_errors(bio_err);
2021296341Sdelphij                goto err;
2022296341Sdelphij            }
2023296341Sdelphij            if (verbose)
2024296341Sdelphij                BIO_printf(bio_err,
2025296341Sdelphij                           "Successfully added extensions from file.\n");
2026296341Sdelphij        } else if (ext_sect) {
2027296341Sdelphij            /* We found extensions to be set from config file */
2028296341Sdelphij            X509V3_set_nconf(&ctx, lconf);
202955714Skris
2030296341Sdelphij            if (!X509V3_EXT_add_nconf(lconf, &ctx, ext_sect, ret)) {
2031296341Sdelphij                BIO_printf(bio_err,
2032296341Sdelphij                           "ERROR: adding extensions in section %s\n",
2033296341Sdelphij                           ext_sect);
2034296341Sdelphij                ERR_print_errors(bio_err);
2035296341Sdelphij                goto err;
2036296341Sdelphij            }
203755714Skris
2038296341Sdelphij            if (verbose)
2039296341Sdelphij                BIO_printf(bio_err,
2040296341Sdelphij                           "Successfully added extensions from config\n");
2041296341Sdelphij        }
2042296341Sdelphij    }
2043109998Smarkm
2044296341Sdelphij    /* Copy extensions from request (if any) */
2045109998Smarkm
2046296341Sdelphij    if (!copy_extensions(ret, req, ext_copy)) {
2047296341Sdelphij        BIO_printf(bio_err, "ERROR: adding extensions from request\n");
2048296341Sdelphij        ERR_print_errors(bio_err);
2049296341Sdelphij        goto err;
2050296341Sdelphij    }
2051109998Smarkm
2052296341Sdelphij    /* Set the right value for the noemailDN option */
2053296341Sdelphij    if (email_dn == 0) {
2054296341Sdelphij        if (!X509_set_subject_name(ret, dn_subject))
2055296341Sdelphij            goto err;
2056296341Sdelphij    }
2057109998Smarkm
2058296341Sdelphij    if (!default_op) {
2059296341Sdelphij        BIO_printf(bio_err, "Certificate Details:\n");
2060296341Sdelphij        /*
2061296341Sdelphij         * Never print signature details because signature not present
2062296341Sdelphij         */
2063296341Sdelphij        certopt |= X509_FLAG_NO_SIGDUMP | X509_FLAG_NO_SIGNAME;
2064296341Sdelphij        X509_print_ex(bio_err, ret, nameopt, certopt);
2065296341Sdelphij    }
2066109998Smarkm
2067296341Sdelphij    BIO_printf(bio_err, "Certificate is to be certified until ");
2068296341Sdelphij    ASN1_TIME_print(bio_err, X509_get_notAfter(ret));
2069296341Sdelphij    if (days)
2070296341Sdelphij        BIO_printf(bio_err, " (%ld days)", days);
2071296341Sdelphij    BIO_printf(bio_err, "\n");
207255714Skris
2073296341Sdelphij    if (!batch) {
207455714Skris
2075296341Sdelphij        BIO_printf(bio_err, "Sign the certificate? [y/n]:");
2076296341Sdelphij        (void)BIO_flush(bio_err);
2077296341Sdelphij        buf[0] = '\0';
2078296341Sdelphij        if (!fgets(buf, sizeof(buf) - 1, stdin)) {
2079296341Sdelphij            BIO_printf(bio_err,
2080296341Sdelphij                       "CERTIFICATE WILL NOT BE CERTIFIED: I/O error\n");
2081296341Sdelphij            ok = 0;
2082296341Sdelphij            goto err;
2083296341Sdelphij        }
2084296341Sdelphij        if (!((buf[0] == 'y') || (buf[0] == 'Y'))) {
2085296341Sdelphij            BIO_printf(bio_err, "CERTIFICATE WILL NOT BE CERTIFIED\n");
2086296341Sdelphij            ok = 0;
2087296341Sdelphij            goto err;
2088296341Sdelphij        }
2089296341Sdelphij    }
209055714Skris
2091296341Sdelphij    pktmp = X509_get_pubkey(ret);
2092296341Sdelphij    if (EVP_PKEY_missing_parameters(pktmp) &&
2093296341Sdelphij        !EVP_PKEY_missing_parameters(pkey))
2094296341Sdelphij        EVP_PKEY_copy_parameters(pktmp, pkey);
2095296341Sdelphij    EVP_PKEY_free(pktmp);
209655714Skris
2097296341Sdelphij    if (!do_X509_sign(bio_err, ret, pkey, dgst, sigopts))
2098296341Sdelphij        goto err;
209955714Skris
2100296341Sdelphij    /* We now just add it to the database */
2101296341Sdelphij    row[DB_type] = (char *)OPENSSL_malloc(2);
210255714Skris
2103296341Sdelphij    tm = X509_get_notAfter(ret);
2104296341Sdelphij    row[DB_exp_date] = (char *)OPENSSL_malloc(tm->length + 1);
2105296341Sdelphij    memcpy(row[DB_exp_date], tm->data, tm->length);
2106296341Sdelphij    row[DB_exp_date][tm->length] = '\0';
210755714Skris
2108296341Sdelphij    row[DB_rev_date] = NULL;
210955714Skris
2110296341Sdelphij    /* row[DB_serial] done already */
2111296341Sdelphij    row[DB_file] = (char *)OPENSSL_malloc(8);
2112296341Sdelphij    row[DB_name] = X509_NAME_oneline(X509_get_subject_name(ret), NULL, 0);
211355714Skris
2114296341Sdelphij    if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2115296341Sdelphij        (row[DB_file] == NULL) || (row[DB_name] == NULL)) {
2116296341Sdelphij        BIO_printf(bio_err, "Memory allocation failure\n");
2117296341Sdelphij        goto err;
2118296341Sdelphij    }
2119296341Sdelphij    BUF_strlcpy(row[DB_file], "unknown", 8);
2120296341Sdelphij    row[DB_type][0] = 'V';
2121296341Sdelphij    row[DB_type][1] = '\0';
212255714Skris
2123296341Sdelphij    if ((irow =
2124296341Sdelphij         (char **)OPENSSL_malloc(sizeof(char *) * (DB_NUMBER + 1))) == NULL) {
2125296341Sdelphij        BIO_printf(bio_err, "Memory allocation failure\n");
2126296341Sdelphij        goto err;
2127296341Sdelphij    }
212855714Skris
2129296341Sdelphij    for (i = 0; i < DB_NUMBER; i++) {
2130296341Sdelphij        irow[i] = row[i];
2131296341Sdelphij        row[i] = NULL;
2132296341Sdelphij    }
2133296341Sdelphij    irow[DB_NUMBER] = NULL;
213455714Skris
2135296341Sdelphij    if (!TXT_DB_insert(db->db, irow)) {
2136296341Sdelphij        BIO_printf(bio_err, "failed to update database\n");
2137296341Sdelphij        BIO_printf(bio_err, "TXT_DB error number %ld\n", db->db->error);
2138296341Sdelphij        goto err;
2139296341Sdelphij    }
2140296341Sdelphij    ok = 1;
2141296341Sdelphij err:
2142296341Sdelphij    for (i = 0; i < DB_NUMBER; i++)
2143296341Sdelphij        if (row[i] != NULL)
2144296341Sdelphij            OPENSSL_free(row[i]);
214555714Skris
2146296341Sdelphij    if (CAname != NULL)
2147296341Sdelphij        X509_NAME_free(CAname);
2148296341Sdelphij    if (subject != NULL)
2149296341Sdelphij        X509_NAME_free(subject);
2150296341Sdelphij    if ((dn_subject != NULL) && !email_dn)
2151296341Sdelphij        X509_NAME_free(dn_subject);
2152296341Sdelphij    if (tmptm != NULL)
2153296341Sdelphij        ASN1_UTCTIME_free(tmptm);
2154296341Sdelphij    if (ok <= 0) {
2155296341Sdelphij        if (ret != NULL)
2156296341Sdelphij            X509_free(ret);
2157296341Sdelphij        ret = NULL;
2158296341Sdelphij    } else
2159296341Sdelphij        *xret = ret;
2160296341Sdelphij    return (ok);
2161296341Sdelphij}
2162296341Sdelphij
2163296341Sdelphijstatic void write_new_certificate(BIO *bp, X509 *x, int output_der,
2164296341Sdelphij                                  int notext)
2165296341Sdelphij{
2166296341Sdelphij
2167296341Sdelphij    if (output_der) {
2168296341Sdelphij        (void)i2d_X509_bio(bp, x);
2169296341Sdelphij        return;
2170296341Sdelphij    }
217159191Skris#if 0
2172296341Sdelphij    /* ??? Not needed since X509_print prints all this stuff anyway */
2173296341Sdelphij    f = X509_NAME_oneline(X509_get_issuer_name(x), buf, 256);
2174296341Sdelphij    BIO_printf(bp, "issuer :%s\n", f);
217555714Skris
2176296341Sdelphij    f = X509_NAME_oneline(X509_get_subject_name(x), buf, 256);
2177296341Sdelphij    BIO_printf(bp, "subject:%s\n", f);
217855714Skris
2179296341Sdelphij    BIO_puts(bp, "serial :");
2180296341Sdelphij    i2a_ASN1_INTEGER(bp, x->cert_info->serialNumber);
2181296341Sdelphij    BIO_puts(bp, "\n\n");
218259191Skris#endif
2183296341Sdelphij    if (!notext)
2184296341Sdelphij        X509_print(bp, x);
2185296341Sdelphij    PEM_write_bio_X509(bp, x);
2186296341Sdelphij}
218755714Skris
2188296341Sdelphijstatic int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey,
2189296341Sdelphij                         X509 *x509, const EVP_MD *dgst,
2190296341Sdelphij                         STACK_OF(OPENSSL_STRING) *sigopts,
2191296341Sdelphij                         STACK_OF(CONF_VALUE) *policy, CA_DB *db,
2192296341Sdelphij                         BIGNUM *serial, char *subj, unsigned long chtype,
2193296341Sdelphij                         int multirdn, int email_dn, char *startdate,
2194296341Sdelphij                         char *enddate, long days, char *ext_sect,
2195296341Sdelphij                         CONF *lconf, int verbose, unsigned long certopt,
2196296341Sdelphij                         unsigned long nameopt, int default_op, int ext_copy)
2197296341Sdelphij{
2198296341Sdelphij    STACK_OF(CONF_VALUE) *sk = NULL;
2199296341Sdelphij    LHASH_OF(CONF_VALUE) *parms = NULL;
2200296341Sdelphij    X509_REQ *req = NULL;
2201296341Sdelphij    CONF_VALUE *cv = NULL;
2202296341Sdelphij    NETSCAPE_SPKI *spki = NULL;
2203296341Sdelphij    X509_REQ_INFO *ri;
2204296341Sdelphij    char *type, *buf;
2205296341Sdelphij    EVP_PKEY *pktmp = NULL;
2206296341Sdelphij    X509_NAME *n = NULL;
2207296341Sdelphij    X509_NAME_ENTRY *ne = NULL;
2208296341Sdelphij    int ok = -1, i, j;
2209296341Sdelphij    long errline;
2210296341Sdelphij    int nid;
221155714Skris
2212296341Sdelphij    /*
2213296341Sdelphij     * Load input file into a hash table.  (This is just an easy
2214296341Sdelphij     * way to read and parse the file, then put it into a convenient
2215296341Sdelphij     * STACK format).
2216296341Sdelphij     */
2217296341Sdelphij    parms = CONF_load(NULL, infile, &errline);
2218296341Sdelphij    if (parms == NULL) {
2219296341Sdelphij        BIO_printf(bio_err, "error on line %ld of %s\n", errline, infile);
2220296341Sdelphij        ERR_print_errors(bio_err);
2221296341Sdelphij        goto err;
2222296341Sdelphij    }
222355714Skris
2224296341Sdelphij    sk = CONF_get_section(parms, "default");
2225296341Sdelphij    if (sk_CONF_VALUE_num(sk) == 0) {
2226296341Sdelphij        BIO_printf(bio_err, "no name/value pairs found in %s\n", infile);
2227296341Sdelphij        CONF_free(parms);
2228296341Sdelphij        goto err;
2229296341Sdelphij    }
223055714Skris
2231296341Sdelphij    /*
2232296341Sdelphij     * Now create a dummy X509 request structure.  We don't actually
2233296341Sdelphij     * have an X509 request, but we have many of the components
2234296341Sdelphij     * (a public key, various DN components).  The idea is that we
2235296341Sdelphij     * put these components into the right X509 request structure
2236296341Sdelphij     * and we can use the same code as if you had a real X509 request.
2237296341Sdelphij     */
2238296341Sdelphij    req = X509_REQ_new();
2239296341Sdelphij    if (req == NULL) {
2240296341Sdelphij        ERR_print_errors(bio_err);
2241296341Sdelphij        goto err;
2242296341Sdelphij    }
224355714Skris
2244296341Sdelphij    /*
2245296341Sdelphij     * Build up the subject name set.
2246296341Sdelphij     */
2247296341Sdelphij    ri = req->req_info;
2248296341Sdelphij    n = ri->subject;
224955714Skris
2250296341Sdelphij    for (i = 0;; i++) {
2251296341Sdelphij        if (sk_CONF_VALUE_num(sk) <= i)
2252296341Sdelphij            break;
225355714Skris
2254296341Sdelphij        cv = sk_CONF_VALUE_value(sk, i);
2255296341Sdelphij        type = cv->name;
2256296341Sdelphij        /*
2257296341Sdelphij         * Skip past any leading X. X: X, etc to allow for multiple instances
2258296341Sdelphij         */
2259296341Sdelphij        for (buf = cv->name; *buf; buf++)
2260296341Sdelphij            if ((*buf == ':') || (*buf == ',') || (*buf == '.')) {
2261296341Sdelphij                buf++;
2262296341Sdelphij                if (*buf)
2263296341Sdelphij                    type = buf;
2264296341Sdelphij                break;
2265296341Sdelphij            }
226659191Skris
2267296341Sdelphij        buf = cv->value;
2268296341Sdelphij        if ((nid = OBJ_txt2nid(type)) == NID_undef) {
2269296341Sdelphij            if (strcmp(type, "SPKAC") == 0) {
2270296341Sdelphij                spki = NETSCAPE_SPKI_b64_decode(cv->value, -1);
2271296341Sdelphij                if (spki == NULL) {
2272296341Sdelphij                    BIO_printf(bio_err,
2273296341Sdelphij                               "unable to load Netscape SPKAC structure\n");
2274296341Sdelphij                    ERR_print_errors(bio_err);
2275296341Sdelphij                    goto err;
2276296341Sdelphij                }
2277296341Sdelphij            }
2278296341Sdelphij            continue;
2279296341Sdelphij        }
228055714Skris
2281296341Sdelphij        if (!X509_NAME_add_entry_by_NID(n, nid, chtype,
2282296341Sdelphij                                        (unsigned char *)buf, -1, -1, 0))
2283296341Sdelphij            goto err;
2284296341Sdelphij    }
2285296341Sdelphij    if (spki == NULL) {
2286296341Sdelphij        BIO_printf(bio_err, "Netscape SPKAC structure not found in %s\n",
2287296341Sdelphij                   infile);
2288296341Sdelphij        goto err;
2289296341Sdelphij    }
229055714Skris
2291296341Sdelphij    /*
2292296341Sdelphij     * Now extract the key from the SPKI structure.
2293296341Sdelphij     */
229455714Skris
2295296341Sdelphij    BIO_printf(bio_err,
2296296341Sdelphij               "Check that the SPKAC request matches the signature\n");
229755714Skris
2298296341Sdelphij    if ((pktmp = NETSCAPE_SPKI_get_pubkey(spki)) == NULL) {
2299296341Sdelphij        BIO_printf(bio_err, "error unpacking SPKAC public key\n");
2300296341Sdelphij        goto err;
2301296341Sdelphij    }
230255714Skris
2303296341Sdelphij    j = NETSCAPE_SPKI_verify(spki, pktmp);
2304296341Sdelphij    if (j <= 0) {
2305296341Sdelphij        BIO_printf(bio_err,
2306296341Sdelphij                   "signature verification failed on SPKAC public key\n");
2307296341Sdelphij        goto err;
2308296341Sdelphij    }
2309296341Sdelphij    BIO_printf(bio_err, "Signature ok\n");
231055714Skris
2311296341Sdelphij    X509_REQ_set_pubkey(req, pktmp);
2312296341Sdelphij    EVP_PKEY_free(pktmp);
2313296341Sdelphij    ok = do_body(xret, pkey, x509, dgst, sigopts, policy, db, serial, subj,
2314296341Sdelphij                 chtype, multirdn, email_dn, startdate, enddate, days, 1,
2315296341Sdelphij                 verbose, req, ext_sect, lconf, certopt, nameopt, default_op,
2316296341Sdelphij                 ext_copy, 0);
2317296341Sdelphij err:
2318296341Sdelphij    if (req != NULL)
2319296341Sdelphij        X509_REQ_free(req);
2320296341Sdelphij    if (parms != NULL)
2321296341Sdelphij        CONF_free(parms);
2322296341Sdelphij    if (spki != NULL)
2323296341Sdelphij        NETSCAPE_SPKI_free(spki);
2324296341Sdelphij    if (ne != NULL)
2325296341Sdelphij        X509_NAME_ENTRY_free(ne);
232655714Skris
2327296341Sdelphij    return (ok);
2328296341Sdelphij}
232955714Skris
2330205128Ssimonstatic int check_time_format(const char *str)
2331296341Sdelphij{
2332296341Sdelphij    return ASN1_TIME_set_string(NULL, str);
2333296341Sdelphij}
233455714Skris
2335127128Snectarstatic int do_revoke(X509 *x509, CA_DB *db, int type, char *value)
2336296341Sdelphij{
2337296341Sdelphij    ASN1_UTCTIME *tm = NULL;
2338296341Sdelphij    char *row[DB_NUMBER], **rrow, **irow;
2339296341Sdelphij    char *rev_str = NULL;
2340296341Sdelphij    BIGNUM *bn = NULL;
2341296341Sdelphij    int ok = -1, i;
234255714Skris
2343296341Sdelphij    for (i = 0; i < DB_NUMBER; i++)
2344296341Sdelphij        row[i] = NULL;
2345296341Sdelphij    row[DB_name] = X509_NAME_oneline(X509_get_subject_name(x509), NULL, 0);
2346296341Sdelphij    bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509), NULL);
2347296341Sdelphij    if (!bn)
2348296341Sdelphij        goto err;
2349296341Sdelphij    if (BN_is_zero(bn))
2350296341Sdelphij        row[DB_serial] = BUF_strdup("00");
2351296341Sdelphij    else
2352296341Sdelphij        row[DB_serial] = BN_bn2hex(bn);
2353296341Sdelphij    BN_free(bn);
2354296341Sdelphij    if ((row[DB_name] == NULL) || (row[DB_serial] == NULL)) {
2355296341Sdelphij        BIO_printf(bio_err, "Memory allocation failure\n");
2356296341Sdelphij        goto err;
2357296341Sdelphij    }
2358296341Sdelphij    /*
2359296341Sdelphij     * We have to lookup by serial number because name lookup skips revoked
2360296341Sdelphij     * certs
2361296341Sdelphij     */
2362296341Sdelphij    rrow = TXT_DB_get_by_index(db->db, DB_serial, row);
2363296341Sdelphij    if (rrow == NULL) {
2364296341Sdelphij        BIO_printf(bio_err,
2365296341Sdelphij                   "Adding Entry with serial number %s to DB for %s\n",
2366296341Sdelphij                   row[DB_serial], row[DB_name]);
236755714Skris
2368296341Sdelphij        /* We now just add it to the database */
2369296341Sdelphij        row[DB_type] = (char *)OPENSSL_malloc(2);
237055714Skris
2371296341Sdelphij        tm = X509_get_notAfter(x509);
2372296341Sdelphij        row[DB_exp_date] = (char *)OPENSSL_malloc(tm->length + 1);
2373296341Sdelphij        memcpy(row[DB_exp_date], tm->data, tm->length);
2374296341Sdelphij        row[DB_exp_date][tm->length] = '\0';
237555714Skris
2376296341Sdelphij        row[DB_rev_date] = NULL;
237755714Skris
2378296341Sdelphij        /* row[DB_serial] done already */
2379296341Sdelphij        row[DB_file] = (char *)OPENSSL_malloc(8);
238055714Skris
2381296341Sdelphij        /* row[DB_name] done already */
238255714Skris
2383296341Sdelphij        if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2384296341Sdelphij            (row[DB_file] == NULL)) {
2385296341Sdelphij            BIO_printf(bio_err, "Memory allocation failure\n");
2386296341Sdelphij            goto err;
2387296341Sdelphij        }
2388296341Sdelphij        BUF_strlcpy(row[DB_file], "unknown", 8);
2389296341Sdelphij        row[DB_type][0] = 'V';
2390296341Sdelphij        row[DB_type][1] = '\0';
239155714Skris
2392296341Sdelphij        if ((irow =
2393296341Sdelphij             (char **)OPENSSL_malloc(sizeof(char *) * (DB_NUMBER + 1))) ==
2394296341Sdelphij            NULL) {
2395296341Sdelphij            BIO_printf(bio_err, "Memory allocation failure\n");
2396296341Sdelphij            goto err;
2397296341Sdelphij        }
239855714Skris
2399296341Sdelphij        for (i = 0; i < DB_NUMBER; i++) {
2400296341Sdelphij            irow[i] = row[i];
2401296341Sdelphij            row[i] = NULL;
2402296341Sdelphij        }
2403296341Sdelphij        irow[DB_NUMBER] = NULL;
240455714Skris
2405296341Sdelphij        if (!TXT_DB_insert(db->db, irow)) {
2406296341Sdelphij            BIO_printf(bio_err, "failed to update database\n");
2407296341Sdelphij            BIO_printf(bio_err, "TXT_DB error number %ld\n", db->db->error);
2408296341Sdelphij            goto err;
2409296341Sdelphij        }
241055714Skris
2411296341Sdelphij        /* Revoke Certificate */
2412296341Sdelphij        ok = do_revoke(x509, db, type, value);
241355714Skris
2414296341Sdelphij        goto err;
241555714Skris
2416296341Sdelphij    } else if (index_name_cmp_noconst(row, rrow)) {
2417296341Sdelphij        BIO_printf(bio_err, "ERROR:name does not match %s\n", row[DB_name]);
2418296341Sdelphij        goto err;
2419296341Sdelphij    } else if (rrow[DB_type][0] == 'R') {
2420296341Sdelphij        BIO_printf(bio_err, "ERROR:Already revoked, serial number %s\n",
2421296341Sdelphij                   row[DB_serial]);
2422296341Sdelphij        goto err;
2423296341Sdelphij    } else {
2424296341Sdelphij        BIO_printf(bio_err, "Revoking Certificate %s.\n", rrow[DB_serial]);
2425296341Sdelphij        rev_str = make_revocation_str(type, value);
2426296341Sdelphij        if (!rev_str) {
2427296341Sdelphij            BIO_printf(bio_err, "Error in revocation arguments\n");
2428296341Sdelphij            goto err;
2429296341Sdelphij        }
2430296341Sdelphij        rrow[DB_type][0] = 'R';
2431296341Sdelphij        rrow[DB_type][1] = '\0';
2432296341Sdelphij        rrow[DB_rev_date] = rev_str;
2433296341Sdelphij    }
2434296341Sdelphij    ok = 1;
2435296341Sdelphij err:
2436296341Sdelphij    for (i = 0; i < DB_NUMBER; i++) {
2437296341Sdelphij        if (row[i] != NULL)
2438296341Sdelphij            OPENSSL_free(row[i]);
2439296341Sdelphij    }
2440296341Sdelphij    return (ok);
2441296341Sdelphij}
2442109998Smarkm
2443127128Snectarstatic int get_certificate_status(const char *serial, CA_DB *db)
2444296341Sdelphij{
2445296341Sdelphij    char *row[DB_NUMBER], **rrow;
2446296341Sdelphij    int ok = -1, i;
2447109998Smarkm
2448296341Sdelphij    /* Free Resources */
2449296341Sdelphij    for (i = 0; i < DB_NUMBER; i++)
2450296341Sdelphij        row[i] = NULL;
2451109998Smarkm
2452296341Sdelphij    /* Malloc needed char spaces */
2453296341Sdelphij    row[DB_serial] = OPENSSL_malloc(strlen(serial) + 2);
2454296341Sdelphij    if (row[DB_serial] == NULL) {
2455296341Sdelphij        BIO_printf(bio_err, "Malloc failure\n");
2456296341Sdelphij        goto err;
2457296341Sdelphij    }
2458109998Smarkm
2459296341Sdelphij    if (strlen(serial) % 2) {
2460296341Sdelphij        /*
2461296341Sdelphij         * Set the first char to 0
2462296341Sdelphij         */ ;
2463296341Sdelphij        row[DB_serial][0] = '0';
2464109998Smarkm
2465296341Sdelphij        /* Copy String from serial to row[DB_serial] */
2466296341Sdelphij        memcpy(row[DB_serial] + 1, serial, strlen(serial));
2467296341Sdelphij        row[DB_serial][strlen(serial) + 1] = '\0';
2468296341Sdelphij    } else {
2469296341Sdelphij        /* Copy String from serial to row[DB_serial] */
2470296341Sdelphij        memcpy(row[DB_serial], serial, strlen(serial));
2471296341Sdelphij        row[DB_serial][strlen(serial)] = '\0';
2472296341Sdelphij    }
2473109998Smarkm
2474296341Sdelphij    /* Make it Upper Case */
2475296341Sdelphij    for (i = 0; row[DB_serial][i] != '\0'; i++)
2476296341Sdelphij        row[DB_serial][i] = toupper((unsigned char)row[DB_serial][i]);
2477109998Smarkm
2478296341Sdelphij    ok = 1;
2479109998Smarkm
2480296341Sdelphij    /* Search for the certificate */
2481296341Sdelphij    rrow = TXT_DB_get_by_index(db->db, DB_serial, row);
2482296341Sdelphij    if (rrow == NULL) {
2483296341Sdelphij        BIO_printf(bio_err, "Serial %s not present in db.\n", row[DB_serial]);
2484296341Sdelphij        ok = -1;
2485296341Sdelphij        goto err;
2486296341Sdelphij    } else if (rrow[DB_type][0] == 'V') {
2487296341Sdelphij        BIO_printf(bio_err, "%s=Valid (%c)\n",
2488296341Sdelphij                   row[DB_serial], rrow[DB_type][0]);
2489296341Sdelphij        goto err;
2490296341Sdelphij    } else if (rrow[DB_type][0] == 'R') {
2491296341Sdelphij        BIO_printf(bio_err, "%s=Revoked (%c)\n",
2492296341Sdelphij                   row[DB_serial], rrow[DB_type][0]);
2493296341Sdelphij        goto err;
2494296341Sdelphij    } else if (rrow[DB_type][0] == 'E') {
2495296341Sdelphij        BIO_printf(bio_err, "%s=Expired (%c)\n",
2496296341Sdelphij                   row[DB_serial], rrow[DB_type][0]);
2497296341Sdelphij        goto err;
2498296341Sdelphij    } else if (rrow[DB_type][0] == 'S') {
2499296341Sdelphij        BIO_printf(bio_err, "%s=Suspended (%c)\n",
2500296341Sdelphij                   row[DB_serial], rrow[DB_type][0]);
2501296341Sdelphij        goto err;
2502296341Sdelphij    } else {
2503296341Sdelphij        BIO_printf(bio_err, "%s=Unknown (%c).\n",
2504296341Sdelphij                   row[DB_serial], rrow[DB_type][0]);
2505296341Sdelphij        ok = -1;
2506296341Sdelphij    }
2507296341Sdelphij err:
2508296341Sdelphij    for (i = 0; i < DB_NUMBER; i++) {
2509296341Sdelphij        if (row[i] != NULL)
2510296341Sdelphij            OPENSSL_free(row[i]);
2511296341Sdelphij    }
2512296341Sdelphij    return (ok);
2513296341Sdelphij}
2514109998Smarkm
2515296341Sdelphijstatic int do_updatedb(CA_DB *db)
2516296341Sdelphij{
2517296341Sdelphij    ASN1_UTCTIME *a_tm = NULL;
2518296341Sdelphij    int i, cnt = 0;
2519296341Sdelphij    int db_y2k, a_y2k;          /* flags = 1 if y >= 2000 */
2520296341Sdelphij    char **rrow, *a_tm_s;
2521109998Smarkm
2522296341Sdelphij    a_tm = ASN1_UTCTIME_new();
2523109998Smarkm
2524296341Sdelphij    /* get actual time and make a string */
2525296341Sdelphij    a_tm = X509_gmtime_adj(a_tm, 0);
2526296341Sdelphij    a_tm_s = (char *)OPENSSL_malloc(a_tm->length + 1);
2527296341Sdelphij    if (a_tm_s == NULL) {
2528296341Sdelphij        cnt = -1;
2529296341Sdelphij        goto err;
2530296341Sdelphij    }
2531109998Smarkm
2532296341Sdelphij    memcpy(a_tm_s, a_tm->data, a_tm->length);
2533296341Sdelphij    a_tm_s[a_tm->length] = '\0';
2534109998Smarkm
2535296341Sdelphij    if (strncmp(a_tm_s, "49", 2) <= 0)
2536296341Sdelphij        a_y2k = 1;
2537296341Sdelphij    else
2538296341Sdelphij        a_y2k = 0;
2539109998Smarkm
2540296341Sdelphij    for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) {
2541296341Sdelphij        rrow = sk_OPENSSL_PSTRING_value(db->db->data, i);
2542109998Smarkm
2543296341Sdelphij        if (rrow[DB_type][0] == 'V') {
2544296341Sdelphij            /* ignore entries that are not valid */
2545296341Sdelphij            if (strncmp(rrow[DB_exp_date], "49", 2) <= 0)
2546296341Sdelphij                db_y2k = 1;
2547296341Sdelphij            else
2548296341Sdelphij                db_y2k = 0;
2549109998Smarkm
2550296341Sdelphij            if (db_y2k == a_y2k) {
2551296341Sdelphij                /* all on the same y2k side */
2552296341Sdelphij                if (strcmp(rrow[DB_exp_date], a_tm_s) <= 0) {
2553296341Sdelphij                    rrow[DB_type][0] = 'E';
2554296341Sdelphij                    rrow[DB_type][1] = '\0';
2555296341Sdelphij                    cnt++;
2556109998Smarkm
2557296341Sdelphij                    BIO_printf(bio_err, "%s=Expired\n", rrow[DB_serial]);
2558296341Sdelphij                }
2559296341Sdelphij            } else if (db_y2k < a_y2k) {
2560296341Sdelphij                rrow[DB_type][0] = 'E';
2561296341Sdelphij                rrow[DB_type][1] = '\0';
2562296341Sdelphij                cnt++;
2563109998Smarkm
2564296341Sdelphij                BIO_printf(bio_err, "%s=Expired\n", rrow[DB_serial]);
2565296341Sdelphij            }
2566109998Smarkm
2567296341Sdelphij        }
2568296341Sdelphij    }
2569109998Smarkm
2570296341Sdelphij err:
2571109998Smarkm
2572296341Sdelphij    ASN1_UTCTIME_free(a_tm);
2573296341Sdelphij    OPENSSL_free(a_tm_s);
2574109998Smarkm
2575296341Sdelphij    return (cnt);
2576296341Sdelphij}
2577296341Sdelphij
2578160814Ssimonstatic const char *crl_reasons[] = {
2579296341Sdelphij    /* CRL reason strings */
2580296341Sdelphij    "unspecified",
2581296341Sdelphij    "keyCompromise",
2582296341Sdelphij    "CACompromise",
2583296341Sdelphij    "affiliationChanged",
2584296341Sdelphij    "superseded",
2585296341Sdelphij    "cessationOfOperation",
2586296341Sdelphij    "certificateHold",
2587296341Sdelphij    "removeFromCRL",
2588296341Sdelphij    /* Additional pseudo reasons */
2589296341Sdelphij    "holdInstruction",
2590296341Sdelphij    "keyTime",
2591296341Sdelphij    "CAkeyTime"
2592109998Smarkm};
2593109998Smarkm
2594109998Smarkm#define NUM_REASONS (sizeof(crl_reasons) / sizeof(char *))
2595109998Smarkm
2596296341Sdelphij/*
2597296341Sdelphij * Given revocation information convert to a DB string. The format of the
2598296341Sdelphij * string is: revtime[,reason,extra]. Where 'revtime' is the revocation time
2599296341Sdelphij * (the current time). 'reason' is the optional CRL reason and 'extra' is any
2600296341Sdelphij * additional argument
2601109998Smarkm */
2602109998Smarkm
2603109998Smarkmchar *make_revocation_str(int rev_type, char *rev_arg)
2604296341Sdelphij{
2605296341Sdelphij    char *other = NULL, *str;
2606296341Sdelphij    const char *reason = NULL;
2607296341Sdelphij    ASN1_OBJECT *otmp;
2608296341Sdelphij    ASN1_UTCTIME *revtm = NULL;
2609296341Sdelphij    int i;
2610296341Sdelphij    switch (rev_type) {
2611296341Sdelphij    case REV_NONE:
2612296341Sdelphij        break;
2613109998Smarkm
2614296341Sdelphij    case REV_CRL_REASON:
2615296341Sdelphij        for (i = 0; i < 8; i++) {
2616296341Sdelphij            if (!strcasecmp(rev_arg, crl_reasons[i])) {
2617296341Sdelphij                reason = crl_reasons[i];
2618296341Sdelphij                break;
2619296341Sdelphij            }
2620296341Sdelphij        }
2621296341Sdelphij        if (reason == NULL) {
2622296341Sdelphij            BIO_printf(bio_err, "Unknown CRL reason %s\n", rev_arg);
2623296341Sdelphij            return NULL;
2624296341Sdelphij        }
2625296341Sdelphij        break;
2626109998Smarkm
2627296341Sdelphij    case REV_HOLD:
2628296341Sdelphij        /* Argument is an OID */
2629109998Smarkm
2630296341Sdelphij        otmp = OBJ_txt2obj(rev_arg, 0);
2631296341Sdelphij        ASN1_OBJECT_free(otmp);
2632109998Smarkm
2633296341Sdelphij        if (otmp == NULL) {
2634296341Sdelphij            BIO_printf(bio_err, "Invalid object identifier %s\n", rev_arg);
2635296341Sdelphij            return NULL;
2636296341Sdelphij        }
2637109998Smarkm
2638296341Sdelphij        reason = "holdInstruction";
2639296341Sdelphij        other = rev_arg;
2640296341Sdelphij        break;
2641109998Smarkm
2642296341Sdelphij    case REV_KEY_COMPROMISE:
2643296341Sdelphij    case REV_CA_COMPROMISE:
2644109998Smarkm
2645296341Sdelphij        /* Argument is the key compromise time  */
2646296341Sdelphij        if (!ASN1_GENERALIZEDTIME_set_string(NULL, rev_arg)) {
2647296341Sdelphij            BIO_printf(bio_err,
2648296341Sdelphij                       "Invalid time format %s. Need YYYYMMDDHHMMSSZ\n",
2649296341Sdelphij                       rev_arg);
2650296341Sdelphij            return NULL;
2651296341Sdelphij        }
2652296341Sdelphij        other = rev_arg;
2653296341Sdelphij        if (rev_type == REV_KEY_COMPROMISE)
2654296341Sdelphij            reason = "keyTime";
2655296341Sdelphij        else
2656296341Sdelphij            reason = "CAkeyTime";
2657109998Smarkm
2658296341Sdelphij        break;
2659109998Smarkm
2660296341Sdelphij    }
2661109998Smarkm
2662296341Sdelphij    revtm = X509_gmtime_adj(NULL, 0);
2663269686Sjkim
2664296341Sdelphij    if (!revtm)
2665296341Sdelphij        return NULL;
2666109998Smarkm
2667296341Sdelphij    i = revtm->length + 1;
2668109998Smarkm
2669296341Sdelphij    if (reason)
2670296341Sdelphij        i += strlen(reason) + 1;
2671296341Sdelphij    if (other)
2672296341Sdelphij        i += strlen(other) + 1;
2673109998Smarkm
2674296341Sdelphij    str = OPENSSL_malloc(i);
2675109998Smarkm
2676296341Sdelphij    if (!str)
2677296341Sdelphij        return NULL;
2678109998Smarkm
2679296341Sdelphij    BUF_strlcpy(str, (char *)revtm->data, i);
2680296341Sdelphij    if (reason) {
2681296341Sdelphij        BUF_strlcat(str, ",", i);
2682296341Sdelphij        BUF_strlcat(str, reason, i);
2683296341Sdelphij    }
2684296341Sdelphij    if (other) {
2685296341Sdelphij        BUF_strlcat(str, ",", i);
2686296341Sdelphij        BUF_strlcat(str, other, i);
2687296341Sdelphij    }
2688296341Sdelphij    ASN1_UTCTIME_free(revtm);
2689296341Sdelphij    return str;
2690296341Sdelphij}
2691296341Sdelphij
2692296341Sdelphij/*-
2693296341Sdelphij * Convert revocation field to X509_REVOKED entry
2694109998Smarkm * return code:
2695109998Smarkm * 0 error
2696109998Smarkm * 1 OK
2697109998Smarkm * 2 OK and some extensions added (i.e. V2 CRL)
2698109998Smarkm */
2699109998Smarkm
2700160814Ssimonint make_revoked(X509_REVOKED *rev, const char *str)
2701296341Sdelphij{
2702296341Sdelphij    char *tmp = NULL;
2703296341Sdelphij    int reason_code = -1;
2704296341Sdelphij    int i, ret = 0;
2705296341Sdelphij    ASN1_OBJECT *hold = NULL;
2706296341Sdelphij    ASN1_GENERALIZEDTIME *comp_time = NULL;
2707296341Sdelphij    ASN1_ENUMERATED *rtmp = NULL;
2708109998Smarkm
2709296341Sdelphij    ASN1_TIME *revDate = NULL;
2710109998Smarkm
2711296341Sdelphij    i = unpack_revinfo(&revDate, &reason_code, &hold, &comp_time, str);
2712109998Smarkm
2713296341Sdelphij    if (i == 0)
2714296341Sdelphij        goto err;
2715109998Smarkm
2716296341Sdelphij    if (rev && !X509_REVOKED_set_revocationDate(rev, revDate))
2717296341Sdelphij        goto err;
2718109998Smarkm
2719296341Sdelphij    if (rev && (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)) {
2720296341Sdelphij        rtmp = ASN1_ENUMERATED_new();
2721296341Sdelphij        if (!rtmp || !ASN1_ENUMERATED_set(rtmp, reason_code))
2722296341Sdelphij            goto err;
2723296341Sdelphij        if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0))
2724296341Sdelphij            goto err;
2725296341Sdelphij    }
2726109998Smarkm
2727296341Sdelphij    if (rev && comp_time) {
2728296341Sdelphij        if (!X509_REVOKED_add1_ext_i2d
2729296341Sdelphij            (rev, NID_invalidity_date, comp_time, 0, 0))
2730296341Sdelphij            goto err;
2731296341Sdelphij    }
2732296341Sdelphij    if (rev && hold) {
2733296341Sdelphij        if (!X509_REVOKED_add1_ext_i2d
2734296341Sdelphij            (rev, NID_hold_instruction_code, hold, 0, 0))
2735296341Sdelphij            goto err;
2736296341Sdelphij    }
2737109998Smarkm
2738296341Sdelphij    if (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)
2739296341Sdelphij        ret = 2;
2740296341Sdelphij    else
2741296341Sdelphij        ret = 1;
2742109998Smarkm
2743296341Sdelphij err:
2744109998Smarkm
2745296341Sdelphij    if (tmp)
2746296341Sdelphij        OPENSSL_free(tmp);
2747296341Sdelphij    ASN1_OBJECT_free(hold);
2748296341Sdelphij    ASN1_GENERALIZEDTIME_free(comp_time);
2749296341Sdelphij    ASN1_ENUMERATED_free(rtmp);
2750296341Sdelphij    ASN1_TIME_free(revDate);
2751109998Smarkm
2752296341Sdelphij    return ret;
2753296341Sdelphij}
2754109998Smarkm
2755109998Smarkmint old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str)
2756296341Sdelphij{
2757296341Sdelphij    char buf[25], *pbuf, *p;
2758296341Sdelphij    int j;
2759296341Sdelphij    j = i2a_ASN1_OBJECT(bp, obj);
2760296341Sdelphij    pbuf = buf;
2761296341Sdelphij    for (j = 22 - j; j > 0; j--)
2762296341Sdelphij        *(pbuf++) = ' ';
2763296341Sdelphij    *(pbuf++) = ':';
2764296341Sdelphij    *(pbuf++) = '\0';
2765296341Sdelphij    BIO_puts(bp, buf);
2766109998Smarkm
2767296341Sdelphij    if (str->type == V_ASN1_PRINTABLESTRING)
2768296341Sdelphij        BIO_printf(bp, "PRINTABLE:'");
2769296341Sdelphij    else if (str->type == V_ASN1_T61STRING)
2770296341Sdelphij        BIO_printf(bp, "T61STRING:'");
2771296341Sdelphij    else if (str->type == V_ASN1_IA5STRING)
2772296341Sdelphij        BIO_printf(bp, "IA5STRING:'");
2773296341Sdelphij    else if (str->type == V_ASN1_UNIVERSALSTRING)
2774296341Sdelphij        BIO_printf(bp, "UNIVERSALSTRING:'");
2775296341Sdelphij    else
2776296341Sdelphij        BIO_printf(bp, "ASN.1 %2d:'", str->type);
2777109998Smarkm
2778296341Sdelphij    p = (char *)str->data;
2779296341Sdelphij    for (j = str->length; j > 0; j--) {
2780296341Sdelphij        if ((*p >= ' ') && (*p <= '~'))
2781296341Sdelphij            BIO_printf(bp, "%c", *p);
2782296341Sdelphij        else if (*p & 0x80)
2783296341Sdelphij            BIO_printf(bp, "\\0x%02X", *p);
2784296341Sdelphij        else if ((unsigned char)*p == 0xf7)
2785296341Sdelphij            BIO_printf(bp, "^?");
2786296341Sdelphij        else
2787296341Sdelphij            BIO_printf(bp, "^%c", *p + '@');
2788296341Sdelphij        p++;
2789296341Sdelphij    }
2790296341Sdelphij    BIO_printf(bp, "'\n");
2791296341Sdelphij    return 1;
2792296341Sdelphij}
2793109998Smarkm
2794296341Sdelphijint unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold,
2795296341Sdelphij                   ASN1_GENERALIZEDTIME **pinvtm, const char *str)
2796296341Sdelphij{
2797296341Sdelphij    char *tmp = NULL;
2798296341Sdelphij    char *rtime_str, *reason_str = NULL, *arg_str = NULL, *p;
2799296341Sdelphij    int reason_code = -1;
2800296341Sdelphij    int ret = 0;
2801296341Sdelphij    unsigned int i;
2802296341Sdelphij    ASN1_OBJECT *hold = NULL;
2803296341Sdelphij    ASN1_GENERALIZEDTIME *comp_time = NULL;
2804296341Sdelphij    tmp = BUF_strdup(str);
2805109998Smarkm
2806296341Sdelphij    if (!tmp) {
2807296341Sdelphij        BIO_printf(bio_err, "memory allocation failure\n");
2808296341Sdelphij        goto err;
2809296341Sdelphij    }
2810109998Smarkm
2811296341Sdelphij    p = strchr(tmp, ',');
2812109998Smarkm
2813296341Sdelphij    rtime_str = tmp;
2814109998Smarkm
2815296341Sdelphij    if (p) {
2816296341Sdelphij        *p = '\0';
2817296341Sdelphij        p++;
2818296341Sdelphij        reason_str = p;
2819296341Sdelphij        p = strchr(p, ',');
2820296341Sdelphij        if (p) {
2821296341Sdelphij            *p = '\0';
2822296341Sdelphij            arg_str = p + 1;
2823296341Sdelphij        }
2824296341Sdelphij    }
2825109998Smarkm
2826296341Sdelphij    if (prevtm) {
2827296341Sdelphij        *prevtm = ASN1_UTCTIME_new();
2828296341Sdelphij        if (!*prevtm) {
2829296341Sdelphij            BIO_printf(bio_err, "memory allocation failure\n");
2830296341Sdelphij            goto err;
2831296341Sdelphij        }
2832296341Sdelphij        if (!ASN1_UTCTIME_set_string(*prevtm, rtime_str)) {
2833296341Sdelphij            BIO_printf(bio_err, "invalid revocation date %s\n", rtime_str);
2834296341Sdelphij            goto err;
2835296341Sdelphij        }
2836296341Sdelphij    }
2837296341Sdelphij    if (reason_str) {
2838296341Sdelphij        for (i = 0; i < NUM_REASONS; i++) {
2839296341Sdelphij            if (!strcasecmp(reason_str, crl_reasons[i])) {
2840296341Sdelphij                reason_code = i;
2841296341Sdelphij                break;
2842296341Sdelphij            }
2843296341Sdelphij        }
2844296341Sdelphij        if (reason_code == OCSP_REVOKED_STATUS_NOSTATUS) {
2845296341Sdelphij            BIO_printf(bio_err, "invalid reason code %s\n", reason_str);
2846296341Sdelphij            goto err;
2847296341Sdelphij        }
2848109998Smarkm
2849296341Sdelphij        if (reason_code == 7)
2850296341Sdelphij            reason_code = OCSP_REVOKED_STATUS_REMOVEFROMCRL;
2851296341Sdelphij        else if (reason_code == 8) { /* Hold instruction */
2852296341Sdelphij            if (!arg_str) {
2853296341Sdelphij                BIO_printf(bio_err, "missing hold instruction\n");
2854296341Sdelphij                goto err;
2855296341Sdelphij            }
2856296341Sdelphij            reason_code = OCSP_REVOKED_STATUS_CERTIFICATEHOLD;
2857296341Sdelphij            hold = OBJ_txt2obj(arg_str, 0);
2858109998Smarkm
2859296341Sdelphij            if (!hold) {
2860296341Sdelphij                BIO_printf(bio_err, "invalid object identifier %s\n",
2861296341Sdelphij                           arg_str);
2862296341Sdelphij                goto err;
2863296341Sdelphij            }
2864296341Sdelphij            if (phold)
2865296341Sdelphij                *phold = hold;
2866296341Sdelphij        } else if ((reason_code == 9) || (reason_code == 10)) {
2867296341Sdelphij            if (!arg_str) {
2868296341Sdelphij                BIO_printf(bio_err, "missing compromised time\n");
2869296341Sdelphij                goto err;
2870296341Sdelphij            }
2871296341Sdelphij            comp_time = ASN1_GENERALIZEDTIME_new();
2872296341Sdelphij            if (!comp_time) {
2873296341Sdelphij                BIO_printf(bio_err, "memory allocation failure\n");
2874296341Sdelphij                goto err;
2875296341Sdelphij            }
2876296341Sdelphij            if (!ASN1_GENERALIZEDTIME_set_string(comp_time, arg_str)) {
2877296341Sdelphij                BIO_printf(bio_err, "invalid compromised time %s\n", arg_str);
2878296341Sdelphij                goto err;
2879296341Sdelphij            }
2880296341Sdelphij            if (reason_code == 9)
2881296341Sdelphij                reason_code = OCSP_REVOKED_STATUS_KEYCOMPROMISE;
2882296341Sdelphij            else
2883296341Sdelphij                reason_code = OCSP_REVOKED_STATUS_CACOMPROMISE;
2884296341Sdelphij        }
2885296341Sdelphij    }
2886109998Smarkm
2887296341Sdelphij    if (preason)
2888296341Sdelphij        *preason = reason_code;
2889296341Sdelphij    if (pinvtm)
2890296341Sdelphij        *pinvtm = comp_time;
2891296341Sdelphij    else
2892296341Sdelphij        ASN1_GENERALIZEDTIME_free(comp_time);
2893109998Smarkm
2894296341Sdelphij    ret = 1;
2895109998Smarkm
2896296341Sdelphij err:
2897296341Sdelphij
2898296341Sdelphij    if (tmp)
2899296341Sdelphij        OPENSSL_free(tmp);
2900296341Sdelphij    if (!phold)
2901296341Sdelphij        ASN1_OBJECT_free(hold);
2902296341Sdelphij    if (!pinvtm)
2903296341Sdelphij        ASN1_GENERALIZEDTIME_free(comp_time);
2904296341Sdelphij
2905296341Sdelphij    return ret;
2906296341Sdelphij}
2907