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.
8296465Sdelphij *
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).
15296465Sdelphij *
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.
22296465Sdelphij *
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 :-).
37296465Sdelphij * 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)"
40296465Sdelphij *
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.
52296465Sdelphij *
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 <sys/stat.h>
6755714Skris#include <openssl/conf.h>
6855714Skris#include <openssl/bio.h>
6955714Skris#include <openssl/err.h>
7055714Skris#include <openssl/bn.h>
7155714Skris#include <openssl/txt_db.h>
7255714Skris#include <openssl/evp.h>
7355714Skris#include <openssl/x509.h>
7455714Skris#include <openssl/x509v3.h>
7555714Skris#include <openssl/objects.h>
76109998Smarkm#include <openssl/ocsp.h>
7755714Skris#include <openssl/pem.h>
7855714Skris
7955714Skris#ifndef W_OK
80296465Sdelphij# ifdef OPENSSL_SYS_VMS
81296465Sdelphij#  if defined(__DECC)
82296465Sdelphij#   include <unistd.h>
83296465Sdelphij#  else
84296465Sdelphij#   include <unixlib.h>
8555714Skris#  endif
86296465Sdelphij# elif !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_NETWARE) && !defined(__TANDEM)
87296465Sdelphij#  include <sys/file.h>
88296465Sdelphij# endif
8955714Skris#endif
9055714Skris
91109998Smarkm#include "apps.h"
92109998Smarkm
9355714Skris#ifndef W_OK
94296465Sdelphij# define F_OK 0
95296465Sdelphij# define X_OK 1
96296465Sdelphij# define W_OK 2
97296465Sdelphij# define R_OK 4
9855714Skris#endif
9955714Skris
10055714Skris#undef PROG
10155714Skris#define PROG ca_main
10255714Skris
103296465Sdelphij#define BASE_SECTION    "ca"
10455714Skris#define CONFIG_FILE "openssl.cnf"
10555714Skris
106296465Sdelphij#define ENV_DEFAULT_CA          "default_ca"
10755714Skris
108296465Sdelphij#define STRING_MASK     "string_mask"
109296465Sdelphij#define UTF8_IN                 "utf8"
110160814Ssimon
111296465Sdelphij#define ENV_DIR                 "dir"
112296465Sdelphij#define ENV_CERTS               "certs"
113296465Sdelphij#define ENV_CRL_DIR             "crl_dir"
114296465Sdelphij#define ENV_CA_DB               "CA_DB"
115296465Sdelphij#define ENV_NEW_CERTS_DIR       "new_certs_dir"
116296465Sdelphij#define ENV_CERTIFICATE         "certificate"
117296465Sdelphij#define ENV_SERIAL              "serial"
118296465Sdelphij#define ENV_CRLNUMBER           "crlnumber"
119296465Sdelphij#define ENV_CRL                 "crl"
120296465Sdelphij#define ENV_PRIVATE_KEY         "private_key"
121296465Sdelphij#define ENV_RANDFILE            "RANDFILE"
122296465Sdelphij#define ENV_DEFAULT_DAYS        "default_days"
123296465Sdelphij#define ENV_DEFAULT_STARTDATE   "default_startdate"
124296465Sdelphij#define ENV_DEFAULT_ENDDATE     "default_enddate"
125296465Sdelphij#define ENV_DEFAULT_CRL_DAYS    "default_crl_days"
126296465Sdelphij#define ENV_DEFAULT_CRL_HOURS   "default_crl_hours"
127296465Sdelphij#define ENV_DEFAULT_MD          "default_md"
128296465Sdelphij#define ENV_DEFAULT_EMAIL_DN    "email_in_dn"
129296465Sdelphij#define ENV_PRESERVE            "preserve"
130296465Sdelphij#define ENV_POLICY              "policy"
131296465Sdelphij#define ENV_EXTENSIONS          "x509_extensions"
132296465Sdelphij#define ENV_CRLEXT              "crl_extensions"
133296465Sdelphij#define ENV_MSIE_HACK           "msie_hack"
134296465Sdelphij#define ENV_NAMEOPT             "name_opt"
135296465Sdelphij#define ENV_CERTOPT             "cert_opt"
136296465Sdelphij#define ENV_EXTCOPY             "copy_extensions"
137296465Sdelphij#define ENV_UNIQUE_SUBJECT      "unique_subject"
13855714Skris
139296465Sdelphij#define ENV_DATABASE            "database"
14055714Skris
141109998Smarkm/* Additional revocation information types */
142109998Smarkm
143296465Sdelphij#define REV_NONE                0 /* No addditional information */
144296465Sdelphij#define REV_CRL_REASON          1 /* Value is CRL reason code */
145296465Sdelphij#define REV_HOLD                2 /* Value is hold instruction */
146296465Sdelphij#define REV_KEY_COMPROMISE      3 /* Value is cert key compromise time */
147296465Sdelphij#define REV_CA_COMPROMISE       4 /* Value is CA key compromise time */
148109998Smarkm
149296465Sdelphijstatic const char *ca_usage[] = {
150296465Sdelphij    "usage: ca args\n",
151296465Sdelphij    "\n",
152296465Sdelphij    " -verbose        - Talk alot while doing things\n",
153296465Sdelphij    " -config file    - A config file\n",
154296465Sdelphij    " -name arg       - The particular CA definition to use\n",
155296465Sdelphij    " -gencrl         - Generate a new CRL\n",
156296465Sdelphij    " -crldays days   - Days is when the next CRL is due\n",
157296465Sdelphij    " -crlhours hours - Hours is when the next CRL is due\n",
158296465Sdelphij    " -startdate YYMMDDHHMMSSZ  - certificate validity notBefore\n",
159296465Sdelphij    " -enddate YYMMDDHHMMSSZ    - certificate validity notAfter (overrides -days)\n",
160296465Sdelphij    " -days arg       - number of days to certify the certificate for\n",
161296465Sdelphij    " -md arg         - md to use, one of md2, md5, sha or sha1\n",
162296465Sdelphij    " -policy arg     - The CA 'policy' to support\n",
163296465Sdelphij    " -keyfile arg    - private key file\n",
164296465Sdelphij    " -keyform arg    - private key file format (PEM or ENGINE)\n",
165296465Sdelphij    " -key arg        - key to decode the private key if it is encrypted\n",
166296465Sdelphij    " -cert file      - The CA certificate\n",
167296465Sdelphij    " -selfsign       - sign a certificate with the key associated with it\n",
168296465Sdelphij    " -in file        - The input PEM encoded certificate request(s)\n",
169296465Sdelphij    " -out file       - Where to put the output file(s)\n",
170296465Sdelphij    " -outdir dir     - Where to put output certificates\n",
171296465Sdelphij    " -infiles ....   - The last argument, requests to process\n",
172296465Sdelphij    " -spkac file     - File contains DN and signed public key and challenge\n",
173296465Sdelphij    " -ss_cert file   - File contains a self signed cert to sign\n",
174296465Sdelphij    " -preserveDN     - Don't re-order the DN\n",
175296465Sdelphij    " -noemailDN      - Don't add the EMAIL field into certificate' subject\n",
176296465Sdelphij    " -batch          - Don't ask questions\n",
177296465Sdelphij    " -msie_hack      - msie modifications to handle all those universal strings\n",
178296465Sdelphij    " -revoke file    - Revoke a certificate (given in file)\n",
179296465Sdelphij    " -subj arg       - Use arg instead of request's subject\n",
180296465Sdelphij    " -utf8           - input characters are UTF8 (default ASCII)\n",
181296465Sdelphij    " -multivalue-rdn - enable support for multivalued RDNs\n",
182296465Sdelphij    " -extensions ..  - Extension section (override value in config file)\n",
183296465Sdelphij    " -extfile file   - Configuration file with X509v3 extentions to add\n",
184296465Sdelphij    " -crlexts ..     - CRL extension section (override value in config file)\n",
185111147Snectar#ifndef OPENSSL_NO_ENGINE
186296465Sdelphij    " -engine e       - use engine e, possibly a hardware device.\n",
187111147Snectar#endif
188296465Sdelphij    " -status serial  - Shows certificate status given the serial number\n",
189296465Sdelphij    " -updatedb       - Updates db for expired certificates\n",
190296465Sdelphij    NULL
19155714Skris};
19255714Skris
19355714Skris#ifdef EFENCE
19455714Skrisextern int EF_PROTECT_FREE;
19555714Skrisextern int EF_PROTECT_BELOW;
19655714Skrisextern int EF_ALIGNMENT;
19755714Skris#endif
19855714Skris
199160814Ssimonstatic void lookup_fail(const char *name, const char *tag);
200296465Sdelphijstatic int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
201296465Sdelphij                   const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy,
202296465Sdelphij                   CA_DB *db, BIGNUM *serial, char *subj,
203296465Sdelphij                   unsigned long chtype, int multirdn, int email_dn,
204296465Sdelphij                   char *startdate, char *enddate, long days, int batch,
205296465Sdelphij                   char *ext_sect, CONF *conf, int verbose,
206296465Sdelphij                   unsigned long certopt, unsigned long nameopt,
207296465Sdelphij                   int default_op, int ext_copy, int selfsign);
208296465Sdelphijstatic int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
209296465Sdelphij                        const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy,
210296465Sdelphij                        CA_DB *db, BIGNUM *serial, char *subj,
211296465Sdelphij                        unsigned long chtype, int multirdn, int email_dn,
212296465Sdelphij                        char *startdate, char *enddate, long days, int batch,
213296465Sdelphij                        char *ext_sect, CONF *conf, int verbose,
214296465Sdelphij                        unsigned long certopt, unsigned long nameopt,
215296465Sdelphij                        int default_op, int ext_copy, ENGINE *e);
216296465Sdelphijstatic int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey,
217296465Sdelphij                         X509 *x509, const EVP_MD *dgst,
218296465Sdelphij                         STACK_OF(CONF_VALUE) *policy, CA_DB *db,
219296465Sdelphij                         BIGNUM *serial, char *subj, unsigned long chtype,
220296465Sdelphij                         int multirdn, int email_dn, char *startdate,
221296465Sdelphij                         char *enddate, long days, char *ext_sect, CONF *conf,
222296465Sdelphij                         int verbose, unsigned long certopt,
223296465Sdelphij                         unsigned long nameopt, int default_op, int ext_copy);
224296465Sdelphijstatic void write_new_certificate(BIO *bp, X509 *x, int output_der,
225296465Sdelphij                                  int notext);
226296465Sdelphijstatic int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
227296465Sdelphij                   const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy,
228296465Sdelphij                   CA_DB *db, BIGNUM *serial, char *subj,
229296465Sdelphij                   unsigned long chtype, int multirdn, int email_dn,
230296465Sdelphij                   char *startdate, char *enddate, long days, int batch,
231296465Sdelphij                   int verbose, X509_REQ *req, char *ext_sect, CONF *conf,
232296465Sdelphij                   unsigned long certopt, unsigned long nameopt,
233296465Sdelphij                   int default_op, int ext_copy, int selfsign);
234127128Snectarstatic int do_revoke(X509 *x509, CA_DB *db, int ext, char *extval);
235127128Snectarstatic int get_certificate_status(const char *ser_status, CA_DB *db);
236127128Snectarstatic int do_updatedb(CA_DB *db);
237205128Ssimonstatic int check_time_format(const char *str);
238109998Smarkmchar *make_revocation_str(int rev_type, char *rev_arg);
239160814Ssimonint make_revoked(X509_REVOKED *rev, const char *str);
240109998Smarkmint old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str);
241296465Sdelphijstatic CONF *conf = NULL;
242296465Sdelphijstatic CONF *extconf = NULL;
243296465Sdelphijstatic char *section = NULL;
24455714Skris
245296465Sdelphijstatic int preserve = 0;
246296465Sdelphijstatic int msie_hack = 0;
24755714Skris
24859191Skrisint MAIN(int, char **);
24959191Skris
25055714Skrisint MAIN(int argc, char **argv)
251296465Sdelphij{
252296465Sdelphij    ENGINE *e = NULL;
253296465Sdelphij    char *key = NULL, *passargin = NULL;
254296465Sdelphij    int create_ser = 0;
255296465Sdelphij    int free_key = 0;
256296465Sdelphij    int total = 0;
257296465Sdelphij    int total_done = 0;
258296465Sdelphij    int badops = 0;
259296465Sdelphij    int ret = 1;
260296465Sdelphij    int email_dn = 1;
261296465Sdelphij    int req = 0;
262296465Sdelphij    int verbose = 0;
263296465Sdelphij    int gencrl = 0;
264296465Sdelphij    int dorevoke = 0;
265296465Sdelphij    int doupdatedb = 0;
266296465Sdelphij    long crldays = 0;
267296465Sdelphij    long crlhours = 0;
268296465Sdelphij    long errorline = -1;
269296465Sdelphij    char *configfile = NULL;
270296465Sdelphij    char *md = NULL;
271296465Sdelphij    char *policy = NULL;
272296465Sdelphij    char *keyfile = NULL;
273296465Sdelphij    char *certfile = NULL;
274296465Sdelphij    int keyform = FORMAT_PEM;
275296465Sdelphij    char *infile = NULL;
276296465Sdelphij    char *spkac_file = NULL;
277296465Sdelphij    char *ss_cert_file = NULL;
278296465Sdelphij    char *ser_status = NULL;
279296465Sdelphij    EVP_PKEY *pkey = NULL;
280296465Sdelphij    int output_der = 0;
281296465Sdelphij    char *outfile = NULL;
282296465Sdelphij    char *outdir = NULL;
283296465Sdelphij    char *serialfile = NULL;
284296465Sdelphij    char *crlnumberfile = NULL;
285296465Sdelphij    char *extensions = NULL;
286296465Sdelphij    char *extfile = NULL;
287296465Sdelphij    char *subj = NULL;
288296465Sdelphij    unsigned long chtype = MBSTRING_ASC;
289296465Sdelphij    int multirdn = 0;
290296465Sdelphij    char *tmp_email_dn = NULL;
291296465Sdelphij    char *crl_ext = NULL;
292296465Sdelphij    int rev_type = REV_NONE;
293296465Sdelphij    char *rev_arg = NULL;
294296465Sdelphij    BIGNUM *serial = NULL;
295296465Sdelphij    BIGNUM *crlnumber = NULL;
296296465Sdelphij    char *startdate = NULL;
297296465Sdelphij    char *enddate = NULL;
298296465Sdelphij    long days = 0;
299296465Sdelphij    int batch = 0;
300296465Sdelphij    int notext = 0;
301296465Sdelphij    unsigned long nameopt = 0, certopt = 0;
302296465Sdelphij    int default_op = 1;
303296465Sdelphij    int ext_copy = EXT_COPY_NONE;
304296465Sdelphij    int selfsign = 0;
305296465Sdelphij    X509 *x509 = NULL, *x509p = NULL;
306296465Sdelphij    X509 *x = NULL;
307296465Sdelphij    BIO *in = NULL, *out = NULL, *Sout = NULL, *Cout = NULL;
308296465Sdelphij    char *dbfile = NULL;
309296465Sdelphij    CA_DB *db = NULL;
310296465Sdelphij    X509_CRL *crl = NULL;
311296465Sdelphij    X509_REVOKED *r = NULL;
312296465Sdelphij    ASN1_TIME *tmptm;
313296465Sdelphij    ASN1_INTEGER *tmpser;
314296465Sdelphij    char *f;
315296465Sdelphij    const char *p, **pp;
316296465Sdelphij    int i, j;
317296465Sdelphij    const EVP_MD *dgst = NULL;
318296465Sdelphij    STACK_OF(CONF_VALUE) *attribs = NULL;
319296465Sdelphij    STACK_OF(X509) *cert_sk = NULL;
32055714Skris#undef BSIZE
32155714Skris#define BSIZE 256
322296465Sdelphij    MS_STATIC char buf[3][BSIZE];
323296465Sdelphij    char *randfile = NULL;
324111147Snectar#ifndef OPENSSL_NO_ENGINE
325296465Sdelphij    char *engine = NULL;
326111147Snectar#endif
327296465Sdelphij    char *tofree = NULL;
328296465Sdelphij    DB_ATTR db_attr;
32955714Skris
33055714Skris#ifdef EFENCE
331296465Sdelphij    EF_PROTECT_FREE = 1;
332296465Sdelphij    EF_PROTECT_BELOW = 1;
333296465Sdelphij    EF_ALIGNMENT = 0;
33455714Skris#endif
33555714Skris
336296465Sdelphij    apps_startup();
33755714Skris
338296465Sdelphij    conf = NULL;
339296465Sdelphij    key = NULL;
340296465Sdelphij    section = NULL;
34155714Skris
342296465Sdelphij    preserve = 0;
343296465Sdelphij    msie_hack = 0;
344296465Sdelphij    if (bio_err == NULL)
345296465Sdelphij        if ((bio_err = BIO_new(BIO_s_file())) != NULL)
346296465Sdelphij            BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
34755714Skris
348296465Sdelphij    argc--;
349296465Sdelphij    argv++;
350296465Sdelphij    while (argc >= 1) {
351296465Sdelphij        if (strcmp(*argv, "-verbose") == 0)
352296465Sdelphij            verbose = 1;
353296465Sdelphij        else if (strcmp(*argv, "-config") == 0) {
354296465Sdelphij            if (--argc < 1)
355296465Sdelphij                goto bad;
356296465Sdelphij            configfile = *(++argv);
357296465Sdelphij        } else if (strcmp(*argv, "-name") == 0) {
358296465Sdelphij            if (--argc < 1)
359296465Sdelphij                goto bad;
360296465Sdelphij            section = *(++argv);
361296465Sdelphij        } else if (strcmp(*argv, "-subj") == 0) {
362296465Sdelphij            if (--argc < 1)
363296465Sdelphij                goto bad;
364296465Sdelphij            subj = *(++argv);
365296465Sdelphij            /* preserve=1; */
366296465Sdelphij        } else if (strcmp(*argv, "-utf8") == 0)
367296465Sdelphij            chtype = MBSTRING_UTF8;
368296465Sdelphij        else if (strcmp(*argv, "-create_serial") == 0)
369296465Sdelphij            create_ser = 1;
370296465Sdelphij        else if (strcmp(*argv, "-multivalue-rdn") == 0)
371296465Sdelphij            multirdn = 1;
372296465Sdelphij        else if (strcmp(*argv, "-startdate") == 0) {
373296465Sdelphij            if (--argc < 1)
374296465Sdelphij                goto bad;
375296465Sdelphij            startdate = *(++argv);
376296465Sdelphij        } else if (strcmp(*argv, "-enddate") == 0) {
377296465Sdelphij            if (--argc < 1)
378296465Sdelphij                goto bad;
379296465Sdelphij            enddate = *(++argv);
380296465Sdelphij        } else if (strcmp(*argv, "-days") == 0) {
381296465Sdelphij            if (--argc < 1)
382296465Sdelphij                goto bad;
383296465Sdelphij            days = atoi(*(++argv));
384296465Sdelphij        } else if (strcmp(*argv, "-md") == 0) {
385296465Sdelphij            if (--argc < 1)
386296465Sdelphij                goto bad;
387296465Sdelphij            md = *(++argv);
388296465Sdelphij        } else if (strcmp(*argv, "-policy") == 0) {
389296465Sdelphij            if (--argc < 1)
390296465Sdelphij                goto bad;
391296465Sdelphij            policy = *(++argv);
392296465Sdelphij        } else if (strcmp(*argv, "-keyfile") == 0) {
393296465Sdelphij            if (--argc < 1)
394296465Sdelphij                goto bad;
395296465Sdelphij            keyfile = *(++argv);
396296465Sdelphij        } else if (strcmp(*argv, "-keyform") == 0) {
397296465Sdelphij            if (--argc < 1)
398296465Sdelphij                goto bad;
399296465Sdelphij            keyform = str2fmt(*(++argv));
400296465Sdelphij        } else if (strcmp(*argv, "-passin") == 0) {
401296465Sdelphij            if (--argc < 1)
402296465Sdelphij                goto bad;
403296465Sdelphij            passargin = *(++argv);
404296465Sdelphij        } else if (strcmp(*argv, "-key") == 0) {
405296465Sdelphij            if (--argc < 1)
406296465Sdelphij                goto bad;
407296465Sdelphij            key = *(++argv);
408296465Sdelphij        } else if (strcmp(*argv, "-cert") == 0) {
409296465Sdelphij            if (--argc < 1)
410296465Sdelphij                goto bad;
411296465Sdelphij            certfile = *(++argv);
412296465Sdelphij        } else if (strcmp(*argv, "-selfsign") == 0)
413296465Sdelphij            selfsign = 1;
414296465Sdelphij        else if (strcmp(*argv, "-in") == 0) {
415296465Sdelphij            if (--argc < 1)
416296465Sdelphij                goto bad;
417296465Sdelphij            infile = *(++argv);
418296465Sdelphij            req = 1;
419296465Sdelphij        } else if (strcmp(*argv, "-out") == 0) {
420296465Sdelphij            if (--argc < 1)
421296465Sdelphij                goto bad;
422296465Sdelphij            outfile = *(++argv);
423296465Sdelphij        } else if (strcmp(*argv, "-outdir") == 0) {
424296465Sdelphij            if (--argc < 1)
425296465Sdelphij                goto bad;
426296465Sdelphij            outdir = *(++argv);
427296465Sdelphij        } else if (strcmp(*argv, "-notext") == 0)
428296465Sdelphij            notext = 1;
429296465Sdelphij        else if (strcmp(*argv, "-batch") == 0)
430296465Sdelphij            batch = 1;
431296465Sdelphij        else if (strcmp(*argv, "-preserveDN") == 0)
432296465Sdelphij            preserve = 1;
433296465Sdelphij        else if (strcmp(*argv, "-noemailDN") == 0)
434296465Sdelphij            email_dn = 0;
435296465Sdelphij        else if (strcmp(*argv, "-gencrl") == 0)
436296465Sdelphij            gencrl = 1;
437296465Sdelphij        else if (strcmp(*argv, "-msie_hack") == 0)
438296465Sdelphij            msie_hack = 1;
439296465Sdelphij        else if (strcmp(*argv, "-crldays") == 0) {
440296465Sdelphij            if (--argc < 1)
441296465Sdelphij                goto bad;
442296465Sdelphij            crldays = atol(*(++argv));
443296465Sdelphij        } else if (strcmp(*argv, "-crlhours") == 0) {
444296465Sdelphij            if (--argc < 1)
445296465Sdelphij                goto bad;
446296465Sdelphij            crlhours = atol(*(++argv));
447296465Sdelphij        } else if (strcmp(*argv, "-infiles") == 0) {
448296465Sdelphij            argc--;
449296465Sdelphij            argv++;
450296465Sdelphij            req = 1;
451296465Sdelphij            break;
452296465Sdelphij        } else if (strcmp(*argv, "-ss_cert") == 0) {
453296465Sdelphij            if (--argc < 1)
454296465Sdelphij                goto bad;
455296465Sdelphij            ss_cert_file = *(++argv);
456296465Sdelphij            req = 1;
457296465Sdelphij        } else if (strcmp(*argv, "-spkac") == 0) {
458296465Sdelphij            if (--argc < 1)
459296465Sdelphij                goto bad;
460296465Sdelphij            spkac_file = *(++argv);
461296465Sdelphij            req = 1;
462296465Sdelphij        } else if (strcmp(*argv, "-revoke") == 0) {
463296465Sdelphij            if (--argc < 1)
464296465Sdelphij                goto bad;
465296465Sdelphij            infile = *(++argv);
466296465Sdelphij            dorevoke = 1;
467296465Sdelphij        } else if (strcmp(*argv, "-extensions") == 0) {
468296465Sdelphij            if (--argc < 1)
469296465Sdelphij                goto bad;
470296465Sdelphij            extensions = *(++argv);
471296465Sdelphij        } else if (strcmp(*argv, "-extfile") == 0) {
472296465Sdelphij            if (--argc < 1)
473296465Sdelphij                goto bad;
474296465Sdelphij            extfile = *(++argv);
475296465Sdelphij        } else if (strcmp(*argv, "-status") == 0) {
476296465Sdelphij            if (--argc < 1)
477296465Sdelphij                goto bad;
478296465Sdelphij            ser_status = *(++argv);
479296465Sdelphij        } else if (strcmp(*argv, "-updatedb") == 0) {
480296465Sdelphij            doupdatedb = 1;
481296465Sdelphij        } else if (strcmp(*argv, "-crlexts") == 0) {
482296465Sdelphij            if (--argc < 1)
483296465Sdelphij                goto bad;
484296465Sdelphij            crl_ext = *(++argv);
485296465Sdelphij        } else if (strcmp(*argv, "-crl_reason") == 0) {
486296465Sdelphij            if (--argc < 1)
487296465Sdelphij                goto bad;
488296465Sdelphij            rev_arg = *(++argv);
489296465Sdelphij            rev_type = REV_CRL_REASON;
490296465Sdelphij        } else if (strcmp(*argv, "-crl_hold") == 0) {
491296465Sdelphij            if (--argc < 1)
492296465Sdelphij                goto bad;
493296465Sdelphij            rev_arg = *(++argv);
494296465Sdelphij            rev_type = REV_HOLD;
495296465Sdelphij        } else if (strcmp(*argv, "-crl_compromise") == 0) {
496296465Sdelphij            if (--argc < 1)
497296465Sdelphij                goto bad;
498296465Sdelphij            rev_arg = *(++argv);
499296465Sdelphij            rev_type = REV_KEY_COMPROMISE;
500296465Sdelphij        } else if (strcmp(*argv, "-crl_CA_compromise") == 0) {
501296465Sdelphij            if (--argc < 1)
502296465Sdelphij                goto bad;
503296465Sdelphij            rev_arg = *(++argv);
504296465Sdelphij            rev_type = REV_CA_COMPROMISE;
505296465Sdelphij        }
506111147Snectar#ifndef OPENSSL_NO_ENGINE
507296465Sdelphij        else if (strcmp(*argv, "-engine") == 0) {
508296465Sdelphij            if (--argc < 1)
509296465Sdelphij                goto bad;
510296465Sdelphij            engine = *(++argv);
511296465Sdelphij        }
512111147Snectar#endif
513296465Sdelphij        else {
514296465Sdelphij bad:
515296465Sdelphij            BIO_printf(bio_err, "unknown option %s\n", *argv);
516296465Sdelphij            badops = 1;
517296465Sdelphij            break;
518296465Sdelphij        }
519296465Sdelphij        argc--;
520296465Sdelphij        argv++;
521296465Sdelphij    }
52255714Skris
523296465Sdelphij    if (badops) {
524296465Sdelphij        for (pp = ca_usage; (*pp != NULL); pp++)
525296465Sdelphij            BIO_printf(bio_err, "%s", *pp);
526296465Sdelphij        goto err;
527296465Sdelphij    }
52855714Skris
529296465Sdelphij    ERR_load_crypto_strings();
53055714Skris
531296465Sdelphij        /*****************************************************************/
532296465Sdelphij    tofree = NULL;
533296465Sdelphij    if (configfile == NULL)
534296465Sdelphij        configfile = getenv("OPENSSL_CONF");
535296465Sdelphij    if (configfile == NULL)
536296465Sdelphij        configfile = getenv("SSLEAY_CONF");
537296465Sdelphij    if (configfile == NULL) {
538296465Sdelphij        const char *s = X509_get_default_cert_area();
539296465Sdelphij        size_t len;
540109998Smarkm
541109998Smarkm#ifdef OPENSSL_SYS_VMS
542296465Sdelphij        len = strlen(s) + sizeof(CONFIG_FILE);
543296465Sdelphij        tofree = OPENSSL_malloc(len);
544296465Sdelphij        strcpy(tofree, s);
54555714Skris#else
546296465Sdelphij        len = strlen(s) + sizeof(CONFIG_FILE) + 1;
547296465Sdelphij        tofree = OPENSSL_malloc(len);
548296465Sdelphij        BUF_strlcpy(tofree, s, len);
549296465Sdelphij        BUF_strlcat(tofree, "/", len);
55055714Skris#endif
551296465Sdelphij        BUF_strlcat(tofree, CONFIG_FILE, len);
552296465Sdelphij        configfile = tofree;
553296465Sdelphij    }
55455714Skris
555296465Sdelphij    BIO_printf(bio_err, "Using configuration from %s\n", configfile);
556296465Sdelphij    conf = NCONF_new(NULL);
557296465Sdelphij    if (NCONF_load(conf, configfile, &errorline) <= 0) {
558296465Sdelphij        if (errorline <= 0)
559296465Sdelphij            BIO_printf(bio_err, "error loading the config file '%s'\n",
560296465Sdelphij                       configfile);
561296465Sdelphij        else
562296465Sdelphij            BIO_printf(bio_err, "error on line %ld of config file '%s'\n",
563296465Sdelphij                       errorline, configfile);
564296465Sdelphij        goto err;
565296465Sdelphij    }
566296465Sdelphij    if (tofree) {
567296465Sdelphij        OPENSSL_free(tofree);
568296465Sdelphij        tofree = NULL;
569296465Sdelphij    }
57055714Skris
571296465Sdelphij    if (!load_config(bio_err, conf))
572296465Sdelphij        goto err;
573109998Smarkm
574142425Snectar#ifndef OPENSSL_NO_ENGINE
575296465Sdelphij    e = setup_engine(bio_err, engine, 0);
576142425Snectar#endif
577142425Snectar
578296465Sdelphij    /* Lets get the config section we are using */
579296465Sdelphij    if (section == NULL) {
580296465Sdelphij        section = NCONF_get_string(conf, BASE_SECTION, ENV_DEFAULT_CA);
581296465Sdelphij        if (section == NULL) {
582296465Sdelphij            lookup_fail(BASE_SECTION, ENV_DEFAULT_CA);
583296465Sdelphij            goto err;
584296465Sdelphij        }
585296465Sdelphij    }
58655714Skris
587296465Sdelphij    if (conf != NULL) {
588296465Sdelphij        p = NCONF_get_string(conf, NULL, "oid_file");
589296465Sdelphij        if (p == NULL)
590296465Sdelphij            ERR_clear_error();
591296465Sdelphij        if (p != NULL) {
592296465Sdelphij            BIO *oid_bio;
59355714Skris
594296465Sdelphij            oid_bio = BIO_new_file(p, "r");
595296465Sdelphij            if (oid_bio == NULL) {
596296465Sdelphij                /*-
597296465Sdelphij                BIO_printf(bio_err,"problems opening %s for extra oid's\n",p);
598296465Sdelphij                ERR_print_errors(bio_err);
599296465Sdelphij                */
600296465Sdelphij                ERR_clear_error();
601296465Sdelphij            } else {
602296465Sdelphij                OBJ_create_objects(oid_bio);
603296465Sdelphij                BIO_free(oid_bio);
604296465Sdelphij            }
605296465Sdelphij        }
606296465Sdelphij        if (!add_oid_section(bio_err, conf)) {
607296465Sdelphij            ERR_print_errors(bio_err);
608296465Sdelphij            goto err;
609296465Sdelphij        }
610296465Sdelphij    }
61155714Skris
612296465Sdelphij    randfile = NCONF_get_string(conf, BASE_SECTION, "RANDFILE");
613296465Sdelphij    if (randfile == NULL)
614296465Sdelphij        ERR_clear_error();
615296465Sdelphij    app_RAND_load_file(randfile, bio_err, 0);
616127128Snectar
617296465Sdelphij    f = NCONF_get_string(conf, section, STRING_MASK);
618296465Sdelphij    if (!f)
619296465Sdelphij        ERR_clear_error();
620160814Ssimon
621296465Sdelphij    if (f && !ASN1_STRING_set_default_mask_asc(f)) {
622296465Sdelphij        BIO_printf(bio_err, "Invalid global string mask setting %s\n", f);
623296465Sdelphij        goto err;
624296465Sdelphij    }
625160814Ssimon
626296465Sdelphij    if (chtype != MBSTRING_UTF8) {
627296465Sdelphij        f = NCONF_get_string(conf, section, UTF8_IN);
628296465Sdelphij        if (!f)
629296465Sdelphij            ERR_clear_error();
630296465Sdelphij        else if (!strcmp(f, "yes"))
631296465Sdelphij            chtype = MBSTRING_UTF8;
632296465Sdelphij    }
633160814Ssimon
634296465Sdelphij    db_attr.unique_subject = 1;
635296465Sdelphij    p = NCONF_get_string(conf, section, ENV_UNIQUE_SUBJECT);
636296465Sdelphij    if (p) {
637127128Snectar#ifdef RL_DEBUG
638296465Sdelphij        BIO_printf(bio_err, "DEBUG: unique_subject = \"%s\"\n", p);
639127128Snectar#endif
640296465Sdelphij        db_attr.unique_subject = parse_yesno(p, 1);
641296465Sdelphij    } else
642296465Sdelphij        ERR_clear_error();
643127128Snectar#ifdef RL_DEBUG
644296465Sdelphij    if (!p)
645296465Sdelphij        BIO_printf(bio_err, "DEBUG: unique_subject undefined\n", p);
646127128Snectar#endif
647127128Snectar#ifdef RL_DEBUG
648296465Sdelphij    BIO_printf(bio_err, "DEBUG: configured unique_subject is %d\n",
649296465Sdelphij               db_attr.unique_subject);
650127128Snectar#endif
65155714Skris
652296465Sdelphij    in = BIO_new(BIO_s_file());
653296465Sdelphij    out = BIO_new(BIO_s_file());
654296465Sdelphij    Sout = BIO_new(BIO_s_file());
655296465Sdelphij    Cout = BIO_new(BIO_s_file());
656296465Sdelphij    if ((in == NULL) || (out == NULL) || (Sout == NULL) || (Cout == NULL)) {
657296465Sdelphij        ERR_print_errors(bio_err);
658296465Sdelphij        goto err;
659296465Sdelphij    }
66055714Skris
661296465Sdelphij        /*****************************************************************/
662296465Sdelphij    /* report status of cert with serial number given on command line */
663296465Sdelphij    if (ser_status) {
664296465Sdelphij        if ((dbfile = NCONF_get_string(conf, section, ENV_DATABASE)) == NULL) {
665296465Sdelphij            lookup_fail(section, ENV_DATABASE);
666296465Sdelphij            goto err;
667296465Sdelphij        }
668296465Sdelphij        db = load_index(dbfile, &db_attr);
669296465Sdelphij        if (db == NULL)
670296465Sdelphij            goto err;
671109998Smarkm
672296465Sdelphij        if (!index_index(db))
673296465Sdelphij            goto err;
674109998Smarkm
675296465Sdelphij        if (get_certificate_status(ser_status, db) != 1)
676296465Sdelphij            BIO_printf(bio_err, "Error verifying serial %s!\n", ser_status);
677296465Sdelphij        goto err;
678296465Sdelphij    }
679109998Smarkm
680296465Sdelphij        /*****************************************************************/
681296465Sdelphij    /* we definitely need a private key, so let's get it */
68255714Skris
683296465Sdelphij    if ((keyfile == NULL) && ((keyfile = NCONF_get_string(conf,
684296465Sdelphij                                                          section,
685296465Sdelphij                                                          ENV_PRIVATE_KEY)) ==
686296465Sdelphij                              NULL)) {
687296465Sdelphij        lookup_fail(section, ENV_PRIVATE_KEY);
688296465Sdelphij        goto err;
689296465Sdelphij    }
690296465Sdelphij    if (!key) {
691296465Sdelphij        free_key = 1;
692296465Sdelphij        if (!app_passwd(bio_err, passargin, NULL, &key, NULL)) {
693296465Sdelphij            BIO_printf(bio_err, "Error getting password\n");
694296465Sdelphij            goto err;
695296465Sdelphij        }
696296465Sdelphij    }
697296465Sdelphij    pkey = load_key(bio_err, keyfile, keyform, 0, key, e, "CA private key");
698296465Sdelphij    if (key)
699296465Sdelphij        OPENSSL_cleanse(key, strlen(key));
700296465Sdelphij    if (pkey == NULL) {
701296465Sdelphij        /* load_key() has already printed an appropriate message */
702296465Sdelphij        goto err;
703296465Sdelphij    }
70455714Skris
705296465Sdelphij        /*****************************************************************/
706296465Sdelphij    /* we need a certificate */
707296465Sdelphij    if (!selfsign || spkac_file || ss_cert_file || gencrl) {
708296465Sdelphij        if ((certfile == NULL)
709296465Sdelphij            && ((certfile = NCONF_get_string(conf,
710296465Sdelphij                                             section,
711296465Sdelphij                                             ENV_CERTIFICATE)) == NULL)) {
712296465Sdelphij            lookup_fail(section, ENV_CERTIFICATE);
713296465Sdelphij            goto err;
714296465Sdelphij        }
715296465Sdelphij        x509 = load_cert(bio_err, certfile, FORMAT_PEM, NULL, e,
716296465Sdelphij                         "CA certificate");
717296465Sdelphij        if (x509 == NULL)
718296465Sdelphij            goto err;
71955714Skris
720296465Sdelphij        if (!X509_check_private_key(x509, pkey)) {
721296465Sdelphij            BIO_printf(bio_err,
722296465Sdelphij                       "CA certificate and CA private key do not match\n");
723296465Sdelphij            goto err;
724296465Sdelphij        }
725296465Sdelphij    }
726296465Sdelphij    if (!selfsign)
727296465Sdelphij        x509p = x509;
72855714Skris
729296465Sdelphij    f = NCONF_get_string(conf, BASE_SECTION, ENV_PRESERVE);
730296465Sdelphij    if (f == NULL)
731296465Sdelphij        ERR_clear_error();
732296465Sdelphij    if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
733296465Sdelphij        preserve = 1;
734296465Sdelphij    f = NCONF_get_string(conf, BASE_SECTION, ENV_MSIE_HACK);
735296465Sdelphij    if (f == NULL)
736296465Sdelphij        ERR_clear_error();
737296465Sdelphij    if ((f != NULL) && ((*f == 'y') || (*f == 'Y')))
738296465Sdelphij        msie_hack = 1;
739109998Smarkm
740296465Sdelphij    f = NCONF_get_string(conf, section, ENV_NAMEOPT);
741109998Smarkm
742296465Sdelphij    if (f) {
743296465Sdelphij        if (!set_name_ex(&nameopt, f)) {
744296465Sdelphij            BIO_printf(bio_err, "Invalid name options: \"%s\"\n", f);
745296465Sdelphij            goto err;
746296465Sdelphij        }
747296465Sdelphij        default_op = 0;
748296465Sdelphij    } else
749296465Sdelphij        ERR_clear_error();
750109998Smarkm
751296465Sdelphij    f = NCONF_get_string(conf, section, ENV_CERTOPT);
752109998Smarkm
753296465Sdelphij    if (f) {
754296465Sdelphij        if (!set_cert_ex(&certopt, f)) {
755296465Sdelphij            BIO_printf(bio_err, "Invalid certificate options: \"%s\"\n", f);
756296465Sdelphij            goto err;
757296465Sdelphij        }
758296465Sdelphij        default_op = 0;
759296465Sdelphij    } else
760296465Sdelphij        ERR_clear_error();
761109998Smarkm
762296465Sdelphij    f = NCONF_get_string(conf, section, ENV_EXTCOPY);
763109998Smarkm
764296465Sdelphij    if (f) {
765296465Sdelphij        if (!set_ext_copy(&ext_copy, f)) {
766296465Sdelphij            BIO_printf(bio_err, "Invalid extension copy option: \"%s\"\n", f);
767296465Sdelphij            goto err;
768296465Sdelphij        }
769296465Sdelphij    } else
770296465Sdelphij        ERR_clear_error();
77155714Skris
772296465Sdelphij        /*****************************************************************/
773296465Sdelphij    /* lookup where to write new certificates */
774296465Sdelphij    if ((outdir == NULL) && (req)) {
775296465Sdelphij        struct stat sb;
776296465Sdelphij
777296465Sdelphij        if ((outdir = NCONF_get_string(conf, section, ENV_NEW_CERTS_DIR))
778296465Sdelphij            == NULL) {
779296465Sdelphij            BIO_printf(bio_err,
780296465Sdelphij                       "there needs to be defined a directory for new certificate to be placed in\n");
781296465Sdelphij            goto err;
782296465Sdelphij        }
783109998Smarkm#ifndef OPENSSL_SYS_VMS
784296465Sdelphij        /*
785296465Sdelphij         * outdir is a directory spec, but access() for VMS demands a
786296465Sdelphij         * filename.  In any case, stat(), below, will catch the problem if
787296465Sdelphij         * outdir is not a directory spec, and the fopen() or open() will
788296465Sdelphij         * catch an error if there is no write access.
789296465Sdelphij         *
790296465Sdelphij         * Presumably, this problem could also be solved by using the DEC C
791296465Sdelphij         * routines to convert the directory syntax to Unixly, and give that
792296465Sdelphij         * to access().  However, time's too short to do that just now.
793296465Sdelphij         */
794296465Sdelphij        if (access(outdir, R_OK | W_OK | X_OK) != 0) {
795296465Sdelphij            BIO_printf(bio_err, "I am unable to access the %s directory\n",
796296465Sdelphij                       outdir);
797296465Sdelphij            perror(outdir);
798296465Sdelphij            goto err;
799296465Sdelphij        }
80059191Skris
801296465Sdelphij        if (stat(outdir, &sb) != 0) {
802296465Sdelphij            BIO_printf(bio_err, "unable to stat(%s)\n", outdir);
803296465Sdelphij            perror(outdir);
804296465Sdelphij            goto err;
805296465Sdelphij        }
806296465Sdelphij# ifdef S_ISDIR
807296465Sdelphij        if (!S_ISDIR(sb.st_mode)) {
808296465Sdelphij            BIO_printf(bio_err, "%s need to be a directory\n", outdir);
809296465Sdelphij            perror(outdir);
810296465Sdelphij            goto err;
811296465Sdelphij        }
812296465Sdelphij# endif
81359191Skris#endif
814296465Sdelphij    }
81555714Skris
816296465Sdelphij        /*****************************************************************/
817296465Sdelphij    /* we need to load the database file */
818296465Sdelphij    if ((dbfile = NCONF_get_string(conf, section, ENV_DATABASE)) == NULL) {
819296465Sdelphij        lookup_fail(section, ENV_DATABASE);
820296465Sdelphij        goto err;
821296465Sdelphij    }
822296465Sdelphij    db = load_index(dbfile, &db_attr);
823296465Sdelphij    if (db == NULL)
824296465Sdelphij        goto err;
82555714Skris
826296465Sdelphij    /* Lets check some fields */
827296465Sdelphij    for (i = 0; i < sk_num(db->db->data); i++) {
828296465Sdelphij        pp = (const char **)sk_value(db->db->data, i);
829296465Sdelphij        if ((pp[DB_type][0] != DB_TYPE_REV) && (pp[DB_rev_date][0] != '\0')) {
830296465Sdelphij            BIO_printf(bio_err,
831296465Sdelphij                       "entry %d: not revoked yet, but has a revocation date\n",
832296465Sdelphij                       i + 1);
833296465Sdelphij            goto err;
834296465Sdelphij        }
835296465Sdelphij        if ((pp[DB_type][0] == DB_TYPE_REV) &&
836296465Sdelphij            !make_revoked(NULL, pp[DB_rev_date])) {
837296465Sdelphij            BIO_printf(bio_err, " in entry %d\n", i + 1);
838296465Sdelphij            goto err;
839296465Sdelphij        }
840296465Sdelphij        if (!check_time_format(pp[DB_exp_date])) {
841296465Sdelphij            BIO_printf(bio_err, "entry %d: invalid expiry date\n", i + 1);
842296465Sdelphij            goto err;
843296465Sdelphij        }
844296465Sdelphij        p = pp[DB_serial];
845296465Sdelphij        j = strlen(p);
846296465Sdelphij        if (*p == '-') {
847296465Sdelphij            p++;
848296465Sdelphij            j--;
849296465Sdelphij        }
850296465Sdelphij        if ((j & 1) || (j < 2)) {
851296465Sdelphij            BIO_printf(bio_err, "entry %d: bad serial number length (%d)\n",
852296465Sdelphij                       i + 1, j);
853296465Sdelphij            goto err;
854296465Sdelphij        }
855296465Sdelphij        while (*p) {
856296465Sdelphij            if (!(((*p >= '0') && (*p <= '9')) ||
857296465Sdelphij                  ((*p >= 'A') && (*p <= 'F')) ||
858296465Sdelphij                  ((*p >= 'a') && (*p <= 'f')))) {
859296465Sdelphij                BIO_printf(bio_err,
860296465Sdelphij                           "entry %d: bad serial number characters, char pos %ld, char is '%c'\n",
861296465Sdelphij                           i + 1, (long)(p - pp[DB_serial]), *p);
862296465Sdelphij                goto err;
863296465Sdelphij            }
864296465Sdelphij            p++;
865296465Sdelphij        }
866296465Sdelphij    }
867296465Sdelphij    if (verbose) {
868296465Sdelphij        BIO_set_fp(out, stdout, BIO_NOCLOSE | BIO_FP_TEXT); /* cannot fail */
869109998Smarkm#ifdef OPENSSL_SYS_VMS
870296465Sdelphij        {
871296465Sdelphij            BIO *tmpbio = BIO_new(BIO_f_linebuffer());
872296465Sdelphij            out = BIO_push(tmpbio, out);
873296465Sdelphij        }
87468651Skris#endif
875296465Sdelphij        TXT_DB_write(out, db->db);
876296465Sdelphij        BIO_printf(bio_err, "%d entries loaded from the database\n",
877296465Sdelphij                   db->db->data->num);
878296465Sdelphij        BIO_printf(bio_err, "generating index\n");
879296465Sdelphij    }
88055714Skris
881296465Sdelphij    if (!index_index(db))
882296465Sdelphij        goto err;
883109998Smarkm
884296465Sdelphij        /*****************************************************************/
885296465Sdelphij    /* Update the db file for expired certificates */
886296465Sdelphij    if (doupdatedb) {
887296465Sdelphij        if (verbose)
888296465Sdelphij            BIO_printf(bio_err, "Updating %s ...\n", dbfile);
889109998Smarkm
890296465Sdelphij        i = do_updatedb(db);
891296465Sdelphij        if (i == -1) {
892296465Sdelphij            BIO_printf(bio_err, "Malloc failure\n");
893296465Sdelphij            goto err;
894296465Sdelphij        } else if (i == 0) {
895296465Sdelphij            if (verbose)
896296465Sdelphij                BIO_printf(bio_err, "No entries found to mark expired\n");
897296465Sdelphij        } else {
898296465Sdelphij            if (!save_index(dbfile, "new", db))
899296465Sdelphij                goto err;
900109998Smarkm
901296465Sdelphij            if (!rotate_index(dbfile, "new", "old"))
902296465Sdelphij                goto err;
903109998Smarkm
904296465Sdelphij            if (verbose)
905296465Sdelphij                BIO_printf(bio_err,
906296465Sdelphij                           "Done. %d entries marked as expired\n", i);
907296465Sdelphij        }
908296465Sdelphij    }
909109998Smarkm
910296465Sdelphij        /*****************************************************************/
911296465Sdelphij    /* Read extentions config file                                   */
912296465Sdelphij    if (extfile) {
913296465Sdelphij        extconf = NCONF_new(NULL);
914296465Sdelphij        if (NCONF_load(extconf, extfile, &errorline) <= 0) {
915296465Sdelphij            if (errorline <= 0)
916296465Sdelphij                BIO_printf(bio_err, "ERROR: loading the config file '%s'\n",
917296465Sdelphij                           extfile);
918296465Sdelphij            else
919296465Sdelphij                BIO_printf(bio_err,
920296465Sdelphij                           "ERROR: on line %ld of config file '%s'\n",
921296465Sdelphij                           errorline, extfile);
922296465Sdelphij            ret = 1;
923296465Sdelphij            goto err;
924296465Sdelphij        }
925296465Sdelphij
926296465Sdelphij        if (verbose)
927296465Sdelphij            BIO_printf(bio_err, "Successfully loaded extensions file %s\n",
928296465Sdelphij                       extfile);
929296465Sdelphij
930296465Sdelphij        /* We can have sections in the ext file */
931296465Sdelphij        if (!extensions
932296465Sdelphij            && !(extensions =
933296465Sdelphij                 NCONF_get_string(extconf, "default", "extensions")))
934296465Sdelphij            extensions = "default";
935296465Sdelphij    }
936296465Sdelphij
937296465Sdelphij        /*****************************************************************/
938296465Sdelphij    if (req || gencrl) {
939296465Sdelphij        if (outfile != NULL) {
940296465Sdelphij            if (BIO_write_filename(Sout, outfile) <= 0) {
941296465Sdelphij                perror(outfile);
942296465Sdelphij                goto err;
943296465Sdelphij            }
944296465Sdelphij        } else {
945296465Sdelphij            BIO_set_fp(Sout, stdout, BIO_NOCLOSE | BIO_FP_TEXT);
946109998Smarkm#ifdef OPENSSL_SYS_VMS
947296465Sdelphij            {
948296465Sdelphij                BIO *tmpbio = BIO_new(BIO_f_linebuffer());
949296465Sdelphij                Sout = BIO_push(tmpbio, Sout);
950296465Sdelphij            }
95168651Skris#endif
952296465Sdelphij        }
953296465Sdelphij    }
95455714Skris
955296465Sdelphij    if ((md == NULL) && ((md = NCONF_get_string(conf,
956296465Sdelphij                                                section,
957296465Sdelphij                                                ENV_DEFAULT_MD)) == NULL)) {
958296465Sdelphij        lookup_fail(section, ENV_DEFAULT_MD);
959296465Sdelphij        goto err;
960296465Sdelphij    }
961160814Ssimon
962296465Sdelphij    if ((dgst = EVP_get_digestbyname(md)) == NULL) {
963296465Sdelphij        BIO_printf(bio_err, "%s is an unsupported message digest type\n", md);
964296465Sdelphij        goto err;
965296465Sdelphij    }
966160814Ssimon
967296465Sdelphij    if (req) {
968296465Sdelphij        if ((email_dn == 1) && ((tmp_email_dn = NCONF_get_string(conf,
969296465Sdelphij                                                                 section,
970296465Sdelphij                                                                 ENV_DEFAULT_EMAIL_DN))
971296465Sdelphij                                != NULL)) {
972296465Sdelphij            if (strcmp(tmp_email_dn, "no") == 0)
973296465Sdelphij                email_dn = 0;
974296465Sdelphij        }
975296465Sdelphij        if (verbose)
976296465Sdelphij            BIO_printf(bio_err, "message digest is %s\n",
977296465Sdelphij                       OBJ_nid2ln(dgst->type));
978296465Sdelphij        if ((policy == NULL) && ((policy = NCONF_get_string(conf,
979296465Sdelphij                                                            section,
980296465Sdelphij                                                            ENV_POLICY)) ==
981296465Sdelphij                                 NULL)) {
982296465Sdelphij            lookup_fail(section, ENV_POLICY);
983296465Sdelphij            goto err;
984296465Sdelphij        }
985296465Sdelphij        if (verbose)
986296465Sdelphij            BIO_printf(bio_err, "policy is %s\n", policy);
98755714Skris
988296465Sdelphij        if ((serialfile = NCONF_get_string(conf, section, ENV_SERIAL))
989296465Sdelphij            == NULL) {
990296465Sdelphij            lookup_fail(section, ENV_SERIAL);
991296465Sdelphij            goto err;
992296465Sdelphij        }
993109998Smarkm
994296465Sdelphij        if (!extconf) {
995296465Sdelphij            /*
996296465Sdelphij             * no '-extfile' option, so we look for extensions in the main
997296465Sdelphij             * configuration file
998296465Sdelphij             */
999296465Sdelphij            if (!extensions) {
1000296465Sdelphij                extensions = NCONF_get_string(conf, section, ENV_EXTENSIONS);
1001296465Sdelphij                if (!extensions)
1002296465Sdelphij                    ERR_clear_error();
1003296465Sdelphij            }
1004296465Sdelphij            if (extensions) {
1005296465Sdelphij                /* Check syntax of file */
1006296465Sdelphij                X509V3_CTX ctx;
1007296465Sdelphij                X509V3_set_ctx_test(&ctx);
1008296465Sdelphij                X509V3_set_nconf(&ctx, conf);
1009296465Sdelphij                if (!X509V3_EXT_add_nconf(conf, &ctx, extensions, NULL)) {
1010296465Sdelphij                    BIO_printf(bio_err,
1011296465Sdelphij                               "Error Loading extension section %s\n",
1012296465Sdelphij                               extensions);
1013296465Sdelphij                    ret = 1;
1014296465Sdelphij                    goto err;
1015296465Sdelphij                }
1016296465Sdelphij            }
1017296465Sdelphij        }
101855714Skris
1019296465Sdelphij        if (startdate == NULL) {
1020296465Sdelphij            startdate = NCONF_get_string(conf, section,
1021296465Sdelphij                                         ENV_DEFAULT_STARTDATE);
1022296465Sdelphij            if (startdate == NULL)
1023296465Sdelphij                ERR_clear_error();
1024296465Sdelphij        }
1025296465Sdelphij        if (startdate && !ASN1_UTCTIME_set_string(NULL, startdate)) {
1026296465Sdelphij            BIO_printf(bio_err,
1027296465Sdelphij                       "start date is invalid, it should be YYMMDDHHMMSSZ\n");
1028296465Sdelphij            goto err;
1029296465Sdelphij        }
1030296465Sdelphij        if (startdate == NULL)
1031296465Sdelphij            startdate = "today";
103255714Skris
1033296465Sdelphij        if (enddate == NULL) {
1034296465Sdelphij            enddate = NCONF_get_string(conf, section, ENV_DEFAULT_ENDDATE);
1035296465Sdelphij            if (enddate == NULL)
1036296465Sdelphij                ERR_clear_error();
1037296465Sdelphij        }
1038296465Sdelphij        if (enddate && !ASN1_UTCTIME_set_string(NULL, enddate)) {
1039296465Sdelphij            BIO_printf(bio_err,
1040296465Sdelphij                       "end date is invalid, it should be YYMMDDHHMMSSZ\n");
1041296465Sdelphij            goto err;
1042296465Sdelphij        }
104355714Skris
1044296465Sdelphij        if (days == 0) {
1045296465Sdelphij            if (!NCONF_get_number(conf, section, ENV_DEFAULT_DAYS, &days))
1046296465Sdelphij                days = 0;
1047296465Sdelphij        }
1048296465Sdelphij        if (!enddate && (days == 0)) {
1049296465Sdelphij            BIO_printf(bio_err,
1050296465Sdelphij                       "cannot lookup how many days to certify for\n");
1051296465Sdelphij            goto err;
1052296465Sdelphij        }
105355714Skris
1054296465Sdelphij        if ((serial = load_serial(serialfile, create_ser, NULL)) == NULL) {
1055296465Sdelphij            BIO_printf(bio_err, "error while loading serial number\n");
1056296465Sdelphij            goto err;
1057296465Sdelphij        }
1058296465Sdelphij        if (verbose) {
1059296465Sdelphij            if (BN_is_zero(serial))
1060296465Sdelphij                BIO_printf(bio_err, "next serial number is 00\n");
1061296465Sdelphij            else {
1062296465Sdelphij                if ((f = BN_bn2hex(serial)) == NULL)
1063296465Sdelphij                    goto err;
1064296465Sdelphij                BIO_printf(bio_err, "next serial number is %s\n", f);
1065296465Sdelphij                OPENSSL_free(f);
1066296465Sdelphij            }
1067296465Sdelphij        }
106855714Skris
1069296465Sdelphij        if ((attribs = NCONF_get_section(conf, policy)) == NULL) {
1070296465Sdelphij            BIO_printf(bio_err, "unable to find 'section' for %s\n", policy);
1071296465Sdelphij            goto err;
1072296465Sdelphij        }
107355714Skris
1074296465Sdelphij        if ((cert_sk = sk_X509_new_null()) == NULL) {
1075296465Sdelphij            BIO_printf(bio_err, "Memory allocation failure\n");
1076296465Sdelphij            goto err;
1077296465Sdelphij        }
1078296465Sdelphij        if (spkac_file != NULL) {
1079296465Sdelphij            total++;
1080296465Sdelphij            j = certify_spkac(&x, spkac_file, pkey, x509, dgst, attribs, db,
1081296465Sdelphij                              serial, subj, chtype, multirdn, email_dn,
1082296465Sdelphij                              startdate, enddate, days, extensions, conf,
1083296465Sdelphij                              verbose, certopt, nameopt, default_op,
1084296465Sdelphij                              ext_copy);
1085296465Sdelphij            if (j < 0)
1086296465Sdelphij                goto err;
1087296465Sdelphij            if (j > 0) {
1088296465Sdelphij                total_done++;
1089296465Sdelphij                BIO_printf(bio_err, "\n");
1090296465Sdelphij                if (!BN_add_word(serial, 1))
1091296465Sdelphij                    goto err;
1092296465Sdelphij                if (!sk_X509_push(cert_sk, x)) {
1093296465Sdelphij                    BIO_printf(bio_err, "Memory allocation failure\n");
1094296465Sdelphij                    goto err;
1095296465Sdelphij                }
1096296465Sdelphij                if (outfile) {
1097296465Sdelphij                    output_der = 1;
1098296465Sdelphij                    batch = 1;
1099296465Sdelphij                }
1100296465Sdelphij            }
1101296465Sdelphij        }
1102296465Sdelphij        if (ss_cert_file != NULL) {
1103296465Sdelphij            total++;
1104296465Sdelphij            j = certify_cert(&x, ss_cert_file, pkey, x509, dgst, attribs,
1105296465Sdelphij                             db, serial, subj, chtype, multirdn, email_dn,
1106296465Sdelphij                             startdate, enddate, days, batch, extensions,
1107296465Sdelphij                             conf, verbose, certopt, nameopt, default_op,
1108296465Sdelphij                             ext_copy, e);
1109296465Sdelphij            if (j < 0)
1110296465Sdelphij                goto err;
1111296465Sdelphij            if (j > 0) {
1112296465Sdelphij                total_done++;
1113296465Sdelphij                BIO_printf(bio_err, "\n");
1114296465Sdelphij                if (!BN_add_word(serial, 1))
1115296465Sdelphij                    goto err;
1116296465Sdelphij                if (!sk_X509_push(cert_sk, x)) {
1117296465Sdelphij                    BIO_printf(bio_err, "Memory allocation failure\n");
1118296465Sdelphij                    goto err;
1119296465Sdelphij                }
1120296465Sdelphij            }
1121296465Sdelphij        }
1122296465Sdelphij        if (infile != NULL) {
1123296465Sdelphij            total++;
1124296465Sdelphij            j = certify(&x, infile, pkey, x509p, dgst, attribs, db,
1125296465Sdelphij                        serial, subj, chtype, multirdn, email_dn, startdate,
1126296465Sdelphij                        enddate, days, batch, extensions, conf, verbose,
1127296465Sdelphij                        certopt, nameopt, default_op, ext_copy, selfsign);
1128296465Sdelphij            if (j < 0)
1129296465Sdelphij                goto err;
1130296465Sdelphij            if (j > 0) {
1131296465Sdelphij                total_done++;
1132296465Sdelphij                BIO_printf(bio_err, "\n");
1133296465Sdelphij                if (!BN_add_word(serial, 1))
1134296465Sdelphij                    goto err;
1135296465Sdelphij                if (!sk_X509_push(cert_sk, x)) {
1136296465Sdelphij                    BIO_printf(bio_err, "Memory allocation failure\n");
1137296465Sdelphij                    goto err;
1138296465Sdelphij                }
1139296465Sdelphij            }
1140296465Sdelphij        }
1141296465Sdelphij        for (i = 0; i < argc; i++) {
1142296465Sdelphij            total++;
1143296465Sdelphij            j = certify(&x, argv[i], pkey, x509p, dgst, attribs, db,
1144296465Sdelphij                        serial, subj, chtype, multirdn, email_dn, startdate,
1145296465Sdelphij                        enddate, days, batch, extensions, conf, verbose,
1146296465Sdelphij                        certopt, nameopt, default_op, ext_copy, selfsign);
1147296465Sdelphij            if (j < 0)
1148296465Sdelphij                goto err;
1149296465Sdelphij            if (j > 0) {
1150296465Sdelphij                total_done++;
1151296465Sdelphij                BIO_printf(bio_err, "\n");
1152296465Sdelphij                if (!BN_add_word(serial, 1))
1153296465Sdelphij                    goto err;
1154296465Sdelphij                if (!sk_X509_push(cert_sk, x)) {
1155296465Sdelphij                    BIO_printf(bio_err, "Memory allocation failure\n");
1156296465Sdelphij                    goto err;
1157296465Sdelphij                }
1158296465Sdelphij            }
1159296465Sdelphij        }
1160296465Sdelphij        /*
1161296465Sdelphij         * we have a stack of newly certified certificates and a data base
1162296465Sdelphij         * and serial number that need updating
1163296465Sdelphij         */
116455714Skris
1165296465Sdelphij        if (sk_X509_num(cert_sk) > 0) {
1166296465Sdelphij            if (!batch) {
1167296465Sdelphij                BIO_printf(bio_err,
1168296465Sdelphij                           "\n%d out of %d certificate requests certified, commit? [y/n]",
1169296465Sdelphij                           total_done, total);
1170296465Sdelphij                (void)BIO_flush(bio_err);
1171296465Sdelphij                buf[0][0] = '\0';
1172296465Sdelphij                if (!fgets(buf[0], 10, stdin)) {
1173296465Sdelphij                    BIO_printf(bio_err,
1174296465Sdelphij                               "CERTIFICATION CANCELED: I/O error\n");
1175296465Sdelphij                    ret = 0;
1176296465Sdelphij                    goto err;
1177296465Sdelphij                }
1178296465Sdelphij                if ((buf[0][0] != 'y') && (buf[0][0] != 'Y')) {
1179296465Sdelphij                    BIO_printf(bio_err, "CERTIFICATION CANCELED\n");
1180296465Sdelphij                    ret = 0;
1181296465Sdelphij                    goto err;
1182296465Sdelphij                }
1183296465Sdelphij            }
118455714Skris
1185296465Sdelphij            BIO_printf(bio_err, "Write out database with %d new entries\n",
1186296465Sdelphij                       sk_X509_num(cert_sk));
118755714Skris
1188296465Sdelphij            if (!save_serial(serialfile, "new", serial, NULL))
1189296465Sdelphij                goto err;
119055714Skris
1191296465Sdelphij            if (!save_index(dbfile, "new", db))
1192296465Sdelphij                goto err;
1193296465Sdelphij        }
119455714Skris
1195296465Sdelphij        if (verbose)
1196296465Sdelphij            BIO_printf(bio_err, "writing new certificates\n");
1197296465Sdelphij        for (i = 0; i < sk_X509_num(cert_sk); i++) {
1198296465Sdelphij            int k;
1199296465Sdelphij            char *n;
120055714Skris
1201296465Sdelphij            x = sk_X509_value(cert_sk, i);
120255714Skris
1203296465Sdelphij            j = x->cert_info->serialNumber->length;
1204296465Sdelphij            p = (const char *)x->cert_info->serialNumber->data;
1205109998Smarkm
1206296465Sdelphij            if (strlen(outdir) >= (size_t)(j ? BSIZE - j * 2 - 6 : BSIZE - 8)) {
1207296465Sdelphij                BIO_printf(bio_err, "certificate file name too long\n");
1208296465Sdelphij                goto err;
1209296465Sdelphij            }
1210296465Sdelphij
1211296465Sdelphij            strcpy(buf[2], outdir);
1212296465Sdelphij
1213109998Smarkm#ifndef OPENSSL_SYS_VMS
1214296465Sdelphij            BUF_strlcat(buf[2], "/", sizeof(buf[2]));
121555714Skris#endif
121655714Skris
1217296465Sdelphij            n = (char *)&(buf[2][strlen(buf[2])]);
1218296465Sdelphij            if (j > 0) {
1219296465Sdelphij                for (k = 0; k < j; k++) {
1220296465Sdelphij                    if (n >= &(buf[2][sizeof(buf[2])]))
1221296465Sdelphij                        break;
1222296465Sdelphij                    BIO_snprintf(n,
1223296465Sdelphij                                 &buf[2][0] + sizeof(buf[2]) - n,
1224296465Sdelphij                                 "%02X", (unsigned char)*(p++));
1225296465Sdelphij                    n += 2;
1226296465Sdelphij                }
1227296465Sdelphij            } else {
1228296465Sdelphij                *(n++) = '0';
1229296465Sdelphij                *(n++) = '0';
1230296465Sdelphij            }
1231296465Sdelphij            *(n++) = '.';
1232296465Sdelphij            *(n++) = 'p';
1233296465Sdelphij            *(n++) = 'e';
1234296465Sdelphij            *(n++) = 'm';
1235296465Sdelphij            *n = '\0';
1236296465Sdelphij            if (verbose)
1237296465Sdelphij                BIO_printf(bio_err, "writing %s\n", buf[2]);
123855714Skris
1239296465Sdelphij            if (BIO_write_filename(Cout, buf[2]) <= 0) {
1240296465Sdelphij                perror(buf[2]);
1241296465Sdelphij                goto err;
1242296465Sdelphij            }
1243296465Sdelphij            write_new_certificate(Cout, x, 0, notext);
1244296465Sdelphij            write_new_certificate(Sout, x, output_der, notext);
1245296465Sdelphij        }
124655714Skris
1247296465Sdelphij        if (sk_X509_num(cert_sk)) {
1248296465Sdelphij            /* Rename the database and the serial file */
1249296465Sdelphij            if (!rotate_serial(serialfile, "new", "old"))
1250296465Sdelphij                goto err;
125155714Skris
1252296465Sdelphij            if (!rotate_index(dbfile, "new", "old"))
1253296465Sdelphij                goto err;
125455714Skris
1255296465Sdelphij            BIO_printf(bio_err, "Data Base Updated\n");
1256296465Sdelphij        }
1257296465Sdelphij    }
125855714Skris
1259296465Sdelphij        /*****************************************************************/
1260296465Sdelphij    if (gencrl) {
1261296465Sdelphij        int crl_v2 = 0;
1262296465Sdelphij        if (!crl_ext) {
1263296465Sdelphij            crl_ext = NCONF_get_string(conf, section, ENV_CRLEXT);
1264296465Sdelphij            if (!crl_ext)
1265296465Sdelphij                ERR_clear_error();
1266296465Sdelphij        }
1267296465Sdelphij        if (crl_ext) {
1268296465Sdelphij            /* Check syntax of file */
1269296465Sdelphij            X509V3_CTX ctx;
1270296465Sdelphij            X509V3_set_ctx_test(&ctx);
1271296465Sdelphij            X509V3_set_nconf(&ctx, conf);
1272296465Sdelphij            if (!X509V3_EXT_add_nconf(conf, &ctx, crl_ext, NULL)) {
1273296465Sdelphij                BIO_printf(bio_err,
1274296465Sdelphij                           "Error Loading CRL extension section %s\n",
1275296465Sdelphij                           crl_ext);
1276296465Sdelphij                ret = 1;
1277296465Sdelphij                goto err;
1278296465Sdelphij            }
1279296465Sdelphij        }
1280127128Snectar
1281296465Sdelphij        if ((crlnumberfile = NCONF_get_string(conf, section, ENV_CRLNUMBER))
1282296465Sdelphij            != NULL)
1283296465Sdelphij            if ((crlnumber = load_serial(crlnumberfile, 0, NULL)) == NULL) {
1284296465Sdelphij                BIO_printf(bio_err, "error while loading CRL number\n");
1285296465Sdelphij                goto err;
1286296465Sdelphij            }
128755714Skris
1288296465Sdelphij        if (!crldays && !crlhours) {
1289296465Sdelphij            if (!NCONF_get_number(conf, section,
1290296465Sdelphij                                  ENV_DEFAULT_CRL_DAYS, &crldays))
1291296465Sdelphij                crldays = 0;
1292296465Sdelphij            if (!NCONF_get_number(conf, section,
1293296465Sdelphij                                  ENV_DEFAULT_CRL_HOURS, &crlhours))
1294296465Sdelphij                crlhours = 0;
1295296465Sdelphij        }
1296296465Sdelphij        if ((crldays == 0) && (crlhours == 0)) {
1297296465Sdelphij            BIO_printf(bio_err,
1298296465Sdelphij                       "cannot lookup how long until the next CRL is issued\n");
1299296465Sdelphij            goto err;
1300296465Sdelphij        }
130155714Skris
1302296465Sdelphij        if (verbose)
1303296465Sdelphij            BIO_printf(bio_err, "making CRL\n");
1304296465Sdelphij        if ((crl = X509_CRL_new()) == NULL)
1305296465Sdelphij            goto err;
1306296465Sdelphij        if (!X509_CRL_set_issuer_name(crl, X509_get_subject_name(x509)))
1307296465Sdelphij            goto err;
130855714Skris
1309296465Sdelphij        tmptm = ASN1_TIME_new();
1310296465Sdelphij        if (!tmptm)
1311296465Sdelphij            goto err;
1312296465Sdelphij        X509_gmtime_adj(tmptm, 0);
1313296465Sdelphij        X509_CRL_set_lastUpdate(crl, tmptm);
1314296465Sdelphij        X509_gmtime_adj(tmptm, (crldays * 24 + crlhours) * 60 * 60);
1315296465Sdelphij        X509_CRL_set_nextUpdate(crl, tmptm);
1316109998Smarkm
1317296465Sdelphij        ASN1_TIME_free(tmptm);
1318109998Smarkm
1319296465Sdelphij        for (i = 0; i < sk_num(db->db->data); i++) {
1320296465Sdelphij            pp = (const char **)sk_value(db->db->data, i);
1321296465Sdelphij            if (pp[DB_type][0] == DB_TYPE_REV) {
1322296465Sdelphij                if ((r = X509_REVOKED_new()) == NULL)
1323296465Sdelphij                    goto err;
1324296465Sdelphij                j = make_revoked(r, pp[DB_rev_date]);
1325296465Sdelphij                if (!j)
1326296465Sdelphij                    goto err;
1327296465Sdelphij                if (j == 2)
1328296465Sdelphij                    crl_v2 = 1;
1329296465Sdelphij                if (!BN_hex2bn(&serial, pp[DB_serial]))
1330296465Sdelphij                    goto err;
1331296465Sdelphij                tmpser = BN_to_ASN1_INTEGER(serial, NULL);
1332296465Sdelphij                BN_free(serial);
1333296465Sdelphij                serial = NULL;
1334296465Sdelphij                if (!tmpser)
1335296465Sdelphij                    goto err;
1336296465Sdelphij                X509_REVOKED_set_serialNumber(r, tmpser);
1337296465Sdelphij                ASN1_INTEGER_free(tmpser);
1338296465Sdelphij                X509_CRL_add0_revoked(crl, r);
1339296465Sdelphij            }
1340296465Sdelphij        }
134155714Skris
1342296465Sdelphij        /*
1343296465Sdelphij         * sort the data so it will be written in serial number order
1344296465Sdelphij         */
1345296465Sdelphij        X509_CRL_sort(crl);
1346296465Sdelphij
1347296465Sdelphij        /* we now have a CRL */
1348296465Sdelphij        if (verbose)
1349296465Sdelphij            BIO_printf(bio_err, "signing CRL\n");
1350160814Ssimon#ifndef OPENSSL_NO_DSA
1351296465Sdelphij        if (pkey->type == EVP_PKEY_DSA)
1352296465Sdelphij            dgst = EVP_dss1();
1353296465Sdelphij        else
135455714Skris#endif
1355160814Ssimon#ifndef OPENSSL_NO_ECDSA
1356296465Sdelphij        if (pkey->type == EVP_PKEY_EC)
1357296465Sdelphij            dgst = EVP_ecdsa();
1358160814Ssimon#endif
135955714Skris
1360296465Sdelphij        /* Add any extensions asked for */
136155714Skris
1362296465Sdelphij        if (crl_ext || crlnumberfile != NULL) {
1363296465Sdelphij            X509V3_CTX crlctx;
1364296465Sdelphij            X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0);
1365296465Sdelphij            X509V3_set_nconf(&crlctx, conf);
136655714Skris
1367296465Sdelphij            if (crl_ext)
1368296465Sdelphij                if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx, crl_ext, crl))
1369296465Sdelphij                    goto err;
1370296465Sdelphij            if (crlnumberfile != NULL) {
1371296465Sdelphij                tmpser = BN_to_ASN1_INTEGER(crlnumber, NULL);
1372296465Sdelphij                if (!tmpser)
1373296465Sdelphij                    goto err;
1374296465Sdelphij                X509_CRL_add1_ext_i2d(crl, NID_crl_number, tmpser, 0, 0);
1375296465Sdelphij                ASN1_INTEGER_free(tmpser);
1376296465Sdelphij                crl_v2 = 1;
1377296465Sdelphij                if (!BN_add_word(crlnumber, 1))
1378296465Sdelphij                    goto err;
1379296465Sdelphij            }
1380296465Sdelphij        }
1381296465Sdelphij        if (crl_ext || crl_v2) {
1382296465Sdelphij            if (!X509_CRL_set_version(crl, 1))
1383296465Sdelphij                goto err;       /* version 2 CRL */
1384296465Sdelphij        }
138555714Skris
1386296465Sdelphij        /* we have a CRL number that need updating */
1387296465Sdelphij        if (crlnumberfile != NULL)
1388296465Sdelphij            if (!save_serial(crlnumberfile, "new", crlnumber, NULL))
1389296465Sdelphij                goto err;
1390127128Snectar
1391296465Sdelphij        if (!X509_CRL_sign(crl, pkey, dgst))
1392296465Sdelphij            goto err;
139355714Skris
1394296465Sdelphij        PEM_write_bio_X509_CRL(Sout, crl);
1395127128Snectar
1396296465Sdelphij        if (crlnumberfile != NULL) /* Rename the crlnumber file */
1397296465Sdelphij            if (!rotate_serial(crlnumberfile, "new", "old"))
1398296465Sdelphij                goto err;
1399127128Snectar
1400296465Sdelphij    }
1401296465Sdelphij        /*****************************************************************/
1402296465Sdelphij    if (dorevoke) {
1403296465Sdelphij        if (infile == NULL) {
1404296465Sdelphij            BIO_printf(bio_err, "no input files\n");
1405296465Sdelphij            goto err;
1406296465Sdelphij        } else {
1407296465Sdelphij            X509 *revcert;
1408296465Sdelphij            revcert = load_cert(bio_err, infile, FORMAT_PEM, NULL, e, infile);
1409296465Sdelphij            if (revcert == NULL)
1410296465Sdelphij                goto err;
1411296465Sdelphij            j = do_revoke(revcert, db, rev_type, rev_arg);
1412296465Sdelphij            if (j <= 0)
1413296465Sdelphij                goto err;
1414296465Sdelphij            X509_free(revcert);
141555714Skris
1416296465Sdelphij            if (!save_index(dbfile, "new", db))
1417296465Sdelphij                goto err;
1418109998Smarkm
1419296465Sdelphij            if (!rotate_index(dbfile, "new", "old"))
1420296465Sdelphij                goto err;
1421127128Snectar
1422296465Sdelphij            BIO_printf(bio_err, "Data Base Updated\n");
1423296465Sdelphij        }
1424296465Sdelphij    }
1425296465Sdelphij        /*****************************************************************/
1426296465Sdelphij    ret = 0;
1427296465Sdelphij err:
1428296465Sdelphij    if (tofree)
1429296465Sdelphij        OPENSSL_free(tofree);
1430296465Sdelphij    BIO_free_all(Cout);
1431296465Sdelphij    BIO_free_all(Sout);
1432296465Sdelphij    BIO_free_all(out);
1433296465Sdelphij    BIO_free_all(in);
143455714Skris
1435296465Sdelphij    if (cert_sk)
1436296465Sdelphij        sk_X509_pop_free(cert_sk, X509_free);
143755714Skris
1438296465Sdelphij    if (ret)
1439296465Sdelphij        ERR_print_errors(bio_err);
1440296465Sdelphij    app_RAND_write_file(randfile, bio_err);
1441296465Sdelphij    if (free_key && key)
1442296465Sdelphij        OPENSSL_free(key);
1443296465Sdelphij    BN_free(serial);
1444296465Sdelphij    free_index(db);
1445296465Sdelphij    EVP_PKEY_free(pkey);
1446296465Sdelphij    if (x509)
1447296465Sdelphij        X509_free(x509);
1448296465Sdelphij    X509_CRL_free(crl);
1449296465Sdelphij    NCONF_free(conf);
1450296465Sdelphij    NCONF_free(extconf);
1451296465Sdelphij    OBJ_cleanup();
1452296465Sdelphij    apps_shutdown();
1453296465Sdelphij    OPENSSL_EXIT(ret);
1454296465Sdelphij}
145555714Skris
1456160814Ssimonstatic void lookup_fail(const char *name, const char *tag)
1457296465Sdelphij{
1458296465Sdelphij    BIO_printf(bio_err, "variable lookup failed for %s::%s\n", name, tag);
1459296465Sdelphij}
146055714Skris
146155714Skrisstatic int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1462296465Sdelphij                   const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy,
1463296465Sdelphij                   CA_DB *db, BIGNUM *serial, char *subj,
1464296465Sdelphij                   unsigned long chtype, int multirdn, int email_dn,
1465296465Sdelphij                   char *startdate, char *enddate, long days, int batch,
1466296465Sdelphij                   char *ext_sect, CONF *lconf, int verbose,
1467296465Sdelphij                   unsigned long certopt, unsigned long nameopt,
1468296465Sdelphij                   int default_op, int ext_copy, int selfsign)
1469296465Sdelphij{
1470296465Sdelphij    X509_REQ *req = NULL;
1471296465Sdelphij    BIO *in = NULL;
1472296465Sdelphij    EVP_PKEY *pktmp = NULL;
1473296465Sdelphij    int ok = -1, i;
147455714Skris
1475296465Sdelphij    in = BIO_new(BIO_s_file());
147655714Skris
1477296465Sdelphij    if (BIO_read_filename(in, infile) <= 0) {
1478296465Sdelphij        perror(infile);
1479296465Sdelphij        goto err;
1480296465Sdelphij    }
1481296465Sdelphij    if ((req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL)) == NULL) {
1482296465Sdelphij        BIO_printf(bio_err, "Error reading certificate request in %s\n",
1483296465Sdelphij                   infile);
1484296465Sdelphij        goto err;
1485296465Sdelphij    }
1486296465Sdelphij    if (verbose)
1487296465Sdelphij        X509_REQ_print(bio_err, req);
148855714Skris
1489296465Sdelphij    BIO_printf(bio_err, "Check that the request matches the signature\n");
149055714Skris
1491296465Sdelphij    if (selfsign && !X509_REQ_check_private_key(req, pkey)) {
1492296465Sdelphij        BIO_printf(bio_err,
1493296465Sdelphij                   "Certificate request and CA private key do not match\n");
1494296465Sdelphij        ok = 0;
1495296465Sdelphij        goto err;
1496296465Sdelphij    }
1497296465Sdelphij    if ((pktmp = X509_REQ_get_pubkey(req)) == NULL) {
1498296465Sdelphij        BIO_printf(bio_err, "error unpacking public key\n");
1499296465Sdelphij        goto err;
1500296465Sdelphij    }
1501296465Sdelphij    i = X509_REQ_verify(req, pktmp);
1502296465Sdelphij    EVP_PKEY_free(pktmp);
1503296465Sdelphij    if (i < 0) {
1504296465Sdelphij        ok = 0;
1505296465Sdelphij        BIO_printf(bio_err, "Signature verification problems....\n");
1506296465Sdelphij        ERR_print_errors(bio_err);
1507296465Sdelphij        goto err;
1508296465Sdelphij    }
1509296465Sdelphij    if (i == 0) {
1510296465Sdelphij        ok = 0;
1511296465Sdelphij        BIO_printf(bio_err,
1512296465Sdelphij                   "Signature did not match the certificate request\n");
1513296465Sdelphij        ERR_print_errors(bio_err);
1514296465Sdelphij        goto err;
1515296465Sdelphij    } else
1516296465Sdelphij        BIO_printf(bio_err, "Signature ok\n");
151755714Skris
1518296465Sdelphij    ok = do_body(xret, pkey, x509, dgst, policy, db, serial, subj, chtype,
1519296465Sdelphij                 multirdn, email_dn, startdate, enddate, days, batch, verbose,
1520296465Sdelphij                 req, ext_sect, lconf, certopt, nameopt, default_op, ext_copy,
1521296465Sdelphij                 selfsign);
152255714Skris
1523296465Sdelphij err:
1524296465Sdelphij    if (req != NULL)
1525296465Sdelphij        X509_REQ_free(req);
1526296465Sdelphij    if (in != NULL)
1527296465Sdelphij        BIO_free(in);
1528296465Sdelphij    return (ok);
1529296465Sdelphij}
153055714Skris
153155714Skrisstatic int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
1532296465Sdelphij                        const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy,
1533296465Sdelphij                        CA_DB *db, BIGNUM *serial, char *subj,
1534296465Sdelphij                        unsigned long chtype, int multirdn, int email_dn,
1535296465Sdelphij                        char *startdate, char *enddate, long days, int batch,
1536296465Sdelphij                        char *ext_sect, CONF *lconf, int verbose,
1537296465Sdelphij                        unsigned long certopt, unsigned long nameopt,
1538296465Sdelphij                        int default_op, int ext_copy, ENGINE *e)
1539296465Sdelphij{
1540296465Sdelphij    X509 *req = NULL;
1541296465Sdelphij    X509_REQ *rreq = NULL;
1542296465Sdelphij    EVP_PKEY *pktmp = NULL;
1543296465Sdelphij    int ok = -1, i;
154455714Skris
1545296465Sdelphij    if ((req =
1546296465Sdelphij         load_cert(bio_err, infile, FORMAT_PEM, NULL, e, infile)) == NULL)
1547296465Sdelphij        goto err;
1548296465Sdelphij    if (verbose)
1549296465Sdelphij        X509_print(bio_err, req);
155055714Skris
1551296465Sdelphij    BIO_printf(bio_err, "Check that the request matches the signature\n");
155255714Skris
1553296465Sdelphij    if ((pktmp = X509_get_pubkey(req)) == NULL) {
1554296465Sdelphij        BIO_printf(bio_err, "error unpacking public key\n");
1555296465Sdelphij        goto err;
1556296465Sdelphij    }
1557296465Sdelphij    i = X509_verify(req, pktmp);
1558296465Sdelphij    EVP_PKEY_free(pktmp);
1559296465Sdelphij    if (i < 0) {
1560296465Sdelphij        ok = 0;
1561296465Sdelphij        BIO_printf(bio_err, "Signature verification problems....\n");
1562296465Sdelphij        goto err;
1563296465Sdelphij    }
1564296465Sdelphij    if (i == 0) {
1565296465Sdelphij        ok = 0;
1566296465Sdelphij        BIO_printf(bio_err, "Signature did not match the certificate\n");
1567296465Sdelphij        goto err;
1568296465Sdelphij    } else
1569296465Sdelphij        BIO_printf(bio_err, "Signature ok\n");
157055714Skris
1571296465Sdelphij    if ((rreq = X509_to_X509_REQ(req, NULL, EVP_md5())) == NULL)
1572296465Sdelphij        goto err;
157355714Skris
1574296465Sdelphij    ok = do_body(xret, pkey, x509, dgst, policy, db, serial, subj, chtype,
1575296465Sdelphij                 multirdn, email_dn, startdate, enddate, days, batch, verbose,
1576296465Sdelphij                 rreq, ext_sect, lconf, certopt, nameopt, default_op,
1577296465Sdelphij                 ext_copy, 0);
157855714Skris
1579296465Sdelphij err:
1580296465Sdelphij    if (rreq != NULL)
1581296465Sdelphij        X509_REQ_free(rreq);
1582296465Sdelphij    if (req != NULL)
1583296465Sdelphij        X509_free(req);
1584296465Sdelphij    return (ok);
1585296465Sdelphij}
158655714Skris
1587296465Sdelphijstatic int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
1588296465Sdelphij                   const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy,
1589296465Sdelphij                   CA_DB *db, BIGNUM *serial, char *subj,
1590296465Sdelphij                   unsigned long chtype, int multirdn, int email_dn,
1591296465Sdelphij                   char *startdate, char *enddate, long days, int batch,
1592296465Sdelphij                   int verbose, X509_REQ *req, char *ext_sect, CONF *lconf,
1593296465Sdelphij                   unsigned long certopt, unsigned long nameopt,
1594296465Sdelphij                   int default_op, int ext_copy, int selfsign)
1595296465Sdelphij{
1596296465Sdelphij    X509_NAME *name = NULL, *CAname = NULL, *subject = NULL, *dn_subject =
1597296465Sdelphij        NULL;
1598296465Sdelphij    ASN1_UTCTIME *tm, *tmptm;
1599296465Sdelphij    ASN1_STRING *str, *str2;
1600296465Sdelphij    ASN1_OBJECT *obj;
1601296465Sdelphij    X509 *ret = NULL;
1602296465Sdelphij    X509_CINF *ci;
1603296465Sdelphij    X509_NAME_ENTRY *ne;
1604296465Sdelphij    X509_NAME_ENTRY *tne, *push;
1605296465Sdelphij    EVP_PKEY *pktmp;
1606296465Sdelphij    int ok = -1, i, j, last, nid;
1607296465Sdelphij    const char *p;
1608296465Sdelphij    CONF_VALUE *cv;
1609296465Sdelphij    char *row[DB_NUMBER], **rrow = NULL, **irow = NULL;
1610296465Sdelphij    char buf[25];
161155714Skris
1612296465Sdelphij    tmptm = ASN1_UTCTIME_new();
1613296465Sdelphij    if (tmptm == NULL) {
1614296465Sdelphij        BIO_printf(bio_err, "malloc error\n");
1615296465Sdelphij        return (0);
1616296465Sdelphij    }
161755714Skris
1618296465Sdelphij    for (i = 0; i < DB_NUMBER; i++)
1619296465Sdelphij        row[i] = NULL;
162055714Skris
1621296465Sdelphij    if (subj) {
1622296465Sdelphij        X509_NAME *n = parse_name(subj, chtype, multirdn);
1623109998Smarkm
1624296465Sdelphij        if (!n) {
1625296465Sdelphij            ERR_print_errors(bio_err);
1626296465Sdelphij            goto err;
1627296465Sdelphij        }
1628296465Sdelphij        X509_REQ_set_subject_name(req, n);
1629296465Sdelphij        req->req_info->enc.modified = 1;
1630296465Sdelphij        X509_NAME_free(n);
1631296465Sdelphij    }
1632109998Smarkm
1633296465Sdelphij    if (default_op)
1634296465Sdelphij        BIO_printf(bio_err,
1635296465Sdelphij                   "The Subject's Distinguished Name is as follows\n");
1636109998Smarkm
1637296465Sdelphij    name = X509_REQ_get_subject_name(req);
1638296465Sdelphij    for (i = 0; i < X509_NAME_entry_count(name); i++) {
1639296465Sdelphij        ne = X509_NAME_get_entry(name, i);
1640296465Sdelphij        str = X509_NAME_ENTRY_get_data(ne);
1641296465Sdelphij        obj = X509_NAME_ENTRY_get_object(ne);
164255714Skris
1643296465Sdelphij        if (msie_hack) {
1644296465Sdelphij            /* assume all type should be strings */
1645296465Sdelphij            nid = OBJ_obj2nid(ne->object);
164655714Skris
1647296465Sdelphij            if (str->type == V_ASN1_UNIVERSALSTRING)
1648296465Sdelphij                ASN1_UNIVERSALSTRING_to_string(str);
164955714Skris
1650296465Sdelphij            if ((str->type == V_ASN1_IA5STRING) &&
1651296465Sdelphij                (nid != NID_pkcs9_emailAddress))
1652296465Sdelphij                str->type = V_ASN1_T61STRING;
165355714Skris
1654296465Sdelphij            if ((nid == NID_pkcs9_emailAddress) &&
1655296465Sdelphij                (str->type == V_ASN1_PRINTABLESTRING))
1656296465Sdelphij                str->type = V_ASN1_IA5STRING;
1657296465Sdelphij        }
165855714Skris
1659296465Sdelphij        /* If no EMAIL is wanted in the subject */
1660296465Sdelphij        if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) && (!email_dn))
1661296465Sdelphij            continue;
166255714Skris
1663296465Sdelphij        /* check some things */
1664296465Sdelphij        if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) &&
1665296465Sdelphij            (str->type != V_ASN1_IA5STRING)) {
1666296465Sdelphij            BIO_printf(bio_err,
1667296465Sdelphij                       "\nemailAddress type needs to be of type IA5STRING\n");
1668296465Sdelphij            goto err;
1669296465Sdelphij        }
1670296465Sdelphij        if ((str->type != V_ASN1_BMPSTRING)
1671296465Sdelphij            && (str->type != V_ASN1_UTF8STRING)) {
1672296465Sdelphij            j = ASN1_PRINTABLE_type(str->data, str->length);
1673296465Sdelphij            if (((j == V_ASN1_T61STRING) &&
1674296465Sdelphij                 (str->type != V_ASN1_T61STRING)) ||
1675296465Sdelphij                ((j == V_ASN1_IA5STRING) &&
1676296465Sdelphij                 (str->type == V_ASN1_PRINTABLESTRING))) {
1677296465Sdelphij                BIO_printf(bio_err,
1678296465Sdelphij                           "\nThe string contains characters that are illegal for the ASN.1 type\n");
1679296465Sdelphij                goto err;
1680296465Sdelphij            }
1681296465Sdelphij        }
1682109998Smarkm
1683296465Sdelphij        if (default_op)
1684296465Sdelphij            old_entry_print(bio_err, obj, str);
1685296465Sdelphij    }
168655714Skris
1687296465Sdelphij    /* Ok, now we check the 'policy' stuff. */
1688296465Sdelphij    if ((subject = X509_NAME_new()) == NULL) {
1689296465Sdelphij        BIO_printf(bio_err, "Memory allocation failure\n");
1690296465Sdelphij        goto err;
1691296465Sdelphij    }
169255714Skris
1693296465Sdelphij    /* take a copy of the issuer name before we mess with it. */
1694296465Sdelphij    if (selfsign)
1695296465Sdelphij        CAname = X509_NAME_dup(name);
1696296465Sdelphij    else
1697296465Sdelphij        CAname = X509_NAME_dup(x509->cert_info->subject);
1698296465Sdelphij    if (CAname == NULL)
1699296465Sdelphij        goto err;
1700296465Sdelphij    str = str2 = NULL;
170155714Skris
1702296465Sdelphij    for (i = 0; i < sk_CONF_VALUE_num(policy); i++) {
1703296465Sdelphij        cv = sk_CONF_VALUE_value(policy, i); /* get the object id */
1704296465Sdelphij        if ((j = OBJ_txt2nid(cv->name)) == NID_undef) {
1705296465Sdelphij            BIO_printf(bio_err,
1706296465Sdelphij                       "%s:unknown object type in 'policy' configuration\n",
1707296465Sdelphij                       cv->name);
1708296465Sdelphij            goto err;
1709296465Sdelphij        }
1710296465Sdelphij        obj = OBJ_nid2obj(j);
171155714Skris
1712296465Sdelphij        last = -1;
1713296465Sdelphij        for (;;) {
1714296465Sdelphij            /* lookup the object in the supplied name list */
1715296465Sdelphij            j = X509_NAME_get_index_by_OBJ(name, obj, last);
1716296465Sdelphij            if (j < 0) {
1717296465Sdelphij                if (last != -1)
1718296465Sdelphij                    break;
1719296465Sdelphij                tne = NULL;
1720296465Sdelphij            } else {
1721296465Sdelphij                tne = X509_NAME_get_entry(name, j);
1722296465Sdelphij            }
1723296465Sdelphij            last = j;
172455714Skris
1725296465Sdelphij            /* depending on the 'policy', decide what to do. */
1726296465Sdelphij            push = NULL;
1727296465Sdelphij            if (strcmp(cv->value, "optional") == 0) {
1728296465Sdelphij                if (tne != NULL)
1729296465Sdelphij                    push = tne;
1730296465Sdelphij            } else if (strcmp(cv->value, "supplied") == 0) {
1731296465Sdelphij                if (tne == NULL) {
1732296465Sdelphij                    BIO_printf(bio_err,
1733296465Sdelphij                               "The %s field needed to be supplied and was missing\n",
1734296465Sdelphij                               cv->name);
1735296465Sdelphij                    goto err;
1736296465Sdelphij                } else
1737296465Sdelphij                    push = tne;
1738296465Sdelphij            } else if (strcmp(cv->value, "match") == 0) {
1739296465Sdelphij                int last2;
174055714Skris
1741296465Sdelphij                if (tne == NULL) {
1742296465Sdelphij                    BIO_printf(bio_err,
1743296465Sdelphij                               "The mandatory %s field was missing\n",
1744296465Sdelphij                               cv->name);
1745296465Sdelphij                    goto err;
1746296465Sdelphij                }
174755714Skris
1748296465Sdelphij                last2 = -1;
174955714Skris
1750296465Sdelphij again2:
1751296465Sdelphij                j = X509_NAME_get_index_by_OBJ(CAname, obj, last2);
1752296465Sdelphij                if ((j < 0) && (last2 == -1)) {
1753296465Sdelphij                    BIO_printf(bio_err,
1754296465Sdelphij                               "The %s field does not exist in the CA certificate,\nthe 'policy' is misconfigured\n",
1755296465Sdelphij                               cv->name);
1756296465Sdelphij                    goto err;
1757296465Sdelphij                }
1758296465Sdelphij                if (j >= 0) {
1759296465Sdelphij                    push = X509_NAME_get_entry(CAname, j);
1760296465Sdelphij                    str = X509_NAME_ENTRY_get_data(tne);
1761296465Sdelphij                    str2 = X509_NAME_ENTRY_get_data(push);
1762296465Sdelphij                    last2 = j;
1763296465Sdelphij                    if (ASN1_STRING_cmp(str, str2) != 0)
1764296465Sdelphij                        goto again2;
1765296465Sdelphij                }
1766296465Sdelphij                if (j < 0) {
1767296465Sdelphij                    BIO_printf(bio_err,
1768296465Sdelphij                               "The %s field needed to be the same in the\nCA certificate (%s) and the request (%s)\n",
1769296465Sdelphij                               cv->name,
1770296465Sdelphij                               ((str2 == NULL) ? "NULL" : (char *)str2->data),
1771296465Sdelphij                               ((str == NULL) ? "NULL" : (char *)str->data));
1772296465Sdelphij                    goto err;
1773296465Sdelphij                }
1774296465Sdelphij            } else {
1775296465Sdelphij                BIO_printf(bio_err,
1776296465Sdelphij                           "%s:invalid type in 'policy' configuration\n",
1777296465Sdelphij                           cv->value);
1778296465Sdelphij                goto err;
1779296465Sdelphij            }
178055714Skris
1781296465Sdelphij            if (push != NULL) {
1782296465Sdelphij                if (!X509_NAME_add_entry(subject, push, -1, 0)) {
1783296465Sdelphij                    if (push != NULL)
1784296465Sdelphij                        X509_NAME_ENTRY_free(push);
1785296465Sdelphij                    BIO_printf(bio_err, "Memory allocation failure\n");
1786296465Sdelphij                    goto err;
1787296465Sdelphij                }
1788296465Sdelphij            }
1789296465Sdelphij            if (j < 0)
1790296465Sdelphij                break;
1791296465Sdelphij        }
1792296465Sdelphij    }
179355714Skris
1794296465Sdelphij    if (preserve) {
1795296465Sdelphij        X509_NAME_free(subject);
1796296465Sdelphij        /* subject=X509_NAME_dup(X509_REQ_get_subject_name(req)); */
1797296465Sdelphij        subject = X509_NAME_dup(name);
1798296465Sdelphij        if (subject == NULL)
1799296465Sdelphij            goto err;
1800296465Sdelphij    }
180155714Skris
1802296465Sdelphij    if (verbose)
1803296465Sdelphij        BIO_printf(bio_err,
1804296465Sdelphij                   "The subject name appears to be ok, checking data base for clashes\n");
180555714Skris
1806296465Sdelphij    /* Build the correct Subject if no e-mail is wanted in the subject */
1807296465Sdelphij    /*
1808296465Sdelphij     * and add it later on because of the method extensions are added
1809296465Sdelphij     * (altName)
1810296465Sdelphij     */
1811109998Smarkm
1812296465Sdelphij    if (email_dn)
1813296465Sdelphij        dn_subject = subject;
1814296465Sdelphij    else {
1815296465Sdelphij        X509_NAME_ENTRY *tmpne;
1816296465Sdelphij        /*
1817296465Sdelphij         * Its best to dup the subject DN and then delete any email addresses
1818296465Sdelphij         * because this retains its structure.
1819296465Sdelphij         */
1820296465Sdelphij        if (!(dn_subject = X509_NAME_dup(subject))) {
1821296465Sdelphij            BIO_printf(bio_err, "Memory allocation failure\n");
1822296465Sdelphij            goto err;
1823296465Sdelphij        }
1824296465Sdelphij        while ((i = X509_NAME_get_index_by_NID(dn_subject,
1825296465Sdelphij                                               NID_pkcs9_emailAddress,
1826296465Sdelphij                                               -1)) >= 0) {
1827296465Sdelphij            tmpne = X509_NAME_get_entry(dn_subject, i);
1828296465Sdelphij            X509_NAME_delete_entry(dn_subject, i);
1829296465Sdelphij            X509_NAME_ENTRY_free(tmpne);
1830296465Sdelphij        }
1831296465Sdelphij    }
183255714Skris
1833296465Sdelphij    if (BN_is_zero(serial))
1834296465Sdelphij        row[DB_serial] = BUF_strdup("00");
1835296465Sdelphij    else
1836296465Sdelphij        row[DB_serial] = BN_bn2hex(serial);
1837296465Sdelphij    if (row[DB_serial] == NULL) {
1838296465Sdelphij        BIO_printf(bio_err, "Memory allocation failure\n");
1839296465Sdelphij        goto err;
1840296465Sdelphij    }
184155714Skris
1842296465Sdelphij    if (db->attributes.unique_subject) {
1843296465Sdelphij        rrow = TXT_DB_get_by_index(db->db, DB_name, row);
1844296465Sdelphij        if (rrow != NULL) {
1845296465Sdelphij            BIO_printf(bio_err,
1846296465Sdelphij                       "ERROR:There is already a certificate for %s\n",
1847296465Sdelphij                       row[DB_name]);
1848296465Sdelphij        }
1849296465Sdelphij    }
1850296465Sdelphij    if (rrow == NULL) {
1851296465Sdelphij        rrow = TXT_DB_get_by_index(db->db, DB_serial, row);
1852296465Sdelphij        if (rrow != NULL) {
1853296465Sdelphij            BIO_printf(bio_err,
1854296465Sdelphij                       "ERROR:Serial number %s has already been issued,\n",
1855296465Sdelphij                       row[DB_serial]);
1856296465Sdelphij            BIO_printf(bio_err,
1857296465Sdelphij                       "      check the database/serial_file for corruption\n");
1858296465Sdelphij        }
1859296465Sdelphij    }
186055714Skris
1861296465Sdelphij    if (rrow != NULL) {
1862296465Sdelphij        BIO_printf(bio_err, "The matching entry has the following details\n");
1863296465Sdelphij        if (rrow[DB_type][0] == 'E')
1864296465Sdelphij            p = "Expired";
1865296465Sdelphij        else if (rrow[DB_type][0] == 'R')
1866296465Sdelphij            p = "Revoked";
1867296465Sdelphij        else if (rrow[DB_type][0] == 'V')
1868296465Sdelphij            p = "Valid";
1869296465Sdelphij        else
1870296465Sdelphij            p = "\ninvalid type, Data base error\n";
1871296465Sdelphij        BIO_printf(bio_err, "Type          :%s\n", p);;
1872296465Sdelphij        if (rrow[DB_type][0] == 'R') {
1873296465Sdelphij            p = rrow[DB_exp_date];
1874296465Sdelphij            if (p == NULL)
1875296465Sdelphij                p = "undef";
1876296465Sdelphij            BIO_printf(bio_err, "Was revoked on:%s\n", p);
1877296465Sdelphij        }
1878296465Sdelphij        p = rrow[DB_exp_date];
1879296465Sdelphij        if (p == NULL)
1880296465Sdelphij            p = "undef";
1881296465Sdelphij        BIO_printf(bio_err, "Expires on    :%s\n", p);
1882296465Sdelphij        p = rrow[DB_serial];
1883296465Sdelphij        if (p == NULL)
1884296465Sdelphij            p = "undef";
1885296465Sdelphij        BIO_printf(bio_err, "Serial Number :%s\n", p);
1886296465Sdelphij        p = rrow[DB_file];
1887296465Sdelphij        if (p == NULL)
1888296465Sdelphij            p = "undef";
1889296465Sdelphij        BIO_printf(bio_err, "File name     :%s\n", p);
1890296465Sdelphij        p = rrow[DB_name];
1891296465Sdelphij        if (p == NULL)
1892296465Sdelphij            p = "undef";
1893296465Sdelphij        BIO_printf(bio_err, "Subject Name  :%s\n", p);
1894296465Sdelphij        ok = -1;                /* This is now a 'bad' error. */
1895296465Sdelphij        goto err;
1896296465Sdelphij    }
189755714Skris
1898296465Sdelphij    /* We are now totally happy, lets make and sign the certificate */
1899296465Sdelphij    if (verbose)
1900296465Sdelphij        BIO_printf(bio_err,
1901296465Sdelphij                   "Everything appears to be ok, creating and signing the certificate\n");
190255714Skris
1903296465Sdelphij    if ((ret = X509_new()) == NULL)
1904296465Sdelphij        goto err;
1905296465Sdelphij    ci = ret->cert_info;
1906296465Sdelphij
190755714Skris#ifdef X509_V3
1908296465Sdelphij    /* Make it an X509 v3 certificate. */
1909296465Sdelphij    if (!X509_set_version(ret, 2))
1910296465Sdelphij        goto err;
191155714Skris#endif
191255714Skris
1913296465Sdelphij    if (BN_to_ASN1_INTEGER(serial, ci->serialNumber) == NULL)
1914296465Sdelphij        goto err;
1915296465Sdelphij    if (selfsign) {
1916296465Sdelphij        if (!X509_set_issuer_name(ret, subject))
1917296465Sdelphij            goto err;
1918296465Sdelphij    } else {
1919296465Sdelphij        if (!X509_set_issuer_name(ret, X509_get_subject_name(x509)))
1920296465Sdelphij            goto err;
1921296465Sdelphij    }
192255714Skris
1923296465Sdelphij    if (strcmp(startdate, "today") == 0)
1924296465Sdelphij        X509_gmtime_adj(X509_get_notBefore(ret), 0);
1925296465Sdelphij    else
1926296465Sdelphij        ASN1_UTCTIME_set_string(X509_get_notBefore(ret), startdate);
192755714Skris
1928296465Sdelphij    if (enddate == NULL)
1929296465Sdelphij        X509_gmtime_adj(X509_get_notAfter(ret), (long)60 * 60 * 24 * days);
1930296465Sdelphij    else
1931296465Sdelphij        ASN1_UTCTIME_set_string(X509_get_notAfter(ret), enddate);
193255714Skris
1933296465Sdelphij    if (!X509_set_subject_name(ret, subject))
1934296465Sdelphij        goto err;
193555714Skris
1936296465Sdelphij    pktmp = X509_REQ_get_pubkey(req);
1937296465Sdelphij    i = X509_set_pubkey(ret, pktmp);
1938296465Sdelphij    EVP_PKEY_free(pktmp);
1939296465Sdelphij    if (!i)
1940296465Sdelphij        goto err;
194155714Skris
1942296465Sdelphij    /* Lets add the extensions, if there are any */
1943296465Sdelphij    if (ext_sect) {
1944296465Sdelphij        X509V3_CTX ctx;
1945296465Sdelphij        if (ci->version == NULL)
1946296465Sdelphij            if ((ci->version = ASN1_INTEGER_new()) == NULL)
1947296465Sdelphij                goto err;
1948296465Sdelphij        ASN1_INTEGER_set(ci->version, 2); /* version 3 certificate */
194955714Skris
1950296465Sdelphij        /*
1951296465Sdelphij         * Free the current entries if any, there should not be any I believe
1952296465Sdelphij         */
1953296465Sdelphij        if (ci->extensions != NULL)
1954296465Sdelphij            sk_X509_EXTENSION_pop_free(ci->extensions, X509_EXTENSION_free);
195555714Skris
1956296465Sdelphij        ci->extensions = NULL;
195755714Skris
1958296465Sdelphij        /* Initialize the context structure */
1959296465Sdelphij        if (selfsign)
1960296465Sdelphij            X509V3_set_ctx(&ctx, ret, ret, req, NULL, 0);
1961296465Sdelphij        else
1962296465Sdelphij            X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0);
196355714Skris
1964296465Sdelphij        if (extconf) {
1965296465Sdelphij            if (verbose)
1966296465Sdelphij                BIO_printf(bio_err, "Extra configuration file found\n");
196755714Skris
1968296465Sdelphij            /* Use the extconf configuration db LHASH */
1969296465Sdelphij            X509V3_set_nconf(&ctx, extconf);
1970109998Smarkm
1971296465Sdelphij            /* Test the structure (needed?) */
1972296465Sdelphij            /* X509V3_set_ctx_test(&ctx); */
1973109998Smarkm
1974296465Sdelphij            /* Adds exts contained in the configuration file */
1975296465Sdelphij            if (!X509V3_EXT_add_nconf(extconf, &ctx, ext_sect, ret)) {
1976296465Sdelphij                BIO_printf(bio_err,
1977296465Sdelphij                           "ERROR: adding extensions in section %s\n",
1978296465Sdelphij                           ext_sect);
1979296465Sdelphij                ERR_print_errors(bio_err);
1980296465Sdelphij                goto err;
1981296465Sdelphij            }
1982296465Sdelphij            if (verbose)
1983296465Sdelphij                BIO_printf(bio_err,
1984296465Sdelphij                           "Successfully added extensions from file.\n");
1985296465Sdelphij        } else if (ext_sect) {
1986296465Sdelphij            /* We found extensions to be set from config file */
1987296465Sdelphij            X509V3_set_nconf(&ctx, lconf);
198855714Skris
1989296465Sdelphij            if (!X509V3_EXT_add_nconf(lconf, &ctx, ext_sect, ret)) {
1990296465Sdelphij                BIO_printf(bio_err,
1991296465Sdelphij                           "ERROR: adding extensions in section %s\n",
1992296465Sdelphij                           ext_sect);
1993296465Sdelphij                ERR_print_errors(bio_err);
1994296465Sdelphij                goto err;
1995296465Sdelphij            }
199655714Skris
1997296465Sdelphij            if (verbose)
1998296465Sdelphij                BIO_printf(bio_err,
1999296465Sdelphij                           "Successfully added extensions from config\n");
2000296465Sdelphij        }
2001296465Sdelphij    }
2002109998Smarkm
2003296465Sdelphij    /* Copy extensions from request (if any) */
2004109998Smarkm
2005296465Sdelphij    if (!copy_extensions(ret, req, ext_copy)) {
2006296465Sdelphij        BIO_printf(bio_err, "ERROR: adding extensions from request\n");
2007296465Sdelphij        ERR_print_errors(bio_err);
2008296465Sdelphij        goto err;
2009296465Sdelphij    }
2010109998Smarkm
2011296465Sdelphij    /* Set the right value for the noemailDN option */
2012296465Sdelphij    if (email_dn == 0) {
2013296465Sdelphij        if (!X509_set_subject_name(ret, dn_subject))
2014296465Sdelphij            goto err;
2015296465Sdelphij    }
2016109998Smarkm
2017296465Sdelphij    if (!default_op) {
2018296465Sdelphij        BIO_printf(bio_err, "Certificate Details:\n");
2019296465Sdelphij        /*
2020296465Sdelphij         * Never print signature details because signature not present
2021296465Sdelphij         */
2022296465Sdelphij        certopt |= X509_FLAG_NO_SIGDUMP | X509_FLAG_NO_SIGNAME;
2023296465Sdelphij        X509_print_ex(bio_err, ret, nameopt, certopt);
2024296465Sdelphij    }
2025109998Smarkm
2026296465Sdelphij    BIO_printf(bio_err, "Certificate is to be certified until ");
2027296465Sdelphij    ASN1_TIME_print(bio_err, X509_get_notAfter(ret));
2028296465Sdelphij    if (days)
2029296465Sdelphij        BIO_printf(bio_err, " (%ld days)", days);
2030296465Sdelphij    BIO_printf(bio_err, "\n");
203155714Skris
2032296465Sdelphij    if (!batch) {
203355714Skris
2034296465Sdelphij        BIO_printf(bio_err, "Sign the certificate? [y/n]:");
2035296465Sdelphij        (void)BIO_flush(bio_err);
2036296465Sdelphij        buf[0] = '\0';
2037296465Sdelphij        if (!fgets(buf, sizeof(buf) - 1, stdin)) {
2038296465Sdelphij            BIO_printf(bio_err,
2039296465Sdelphij                       "CERTIFICATE WILL NOT BE CERTIFIED: I/O error\n");
2040296465Sdelphij            ok = 0;
2041296465Sdelphij            goto err;
2042296465Sdelphij        }
2043296465Sdelphij        if (!((buf[0] == 'y') || (buf[0] == 'Y'))) {
2044296465Sdelphij            BIO_printf(bio_err, "CERTIFICATE WILL NOT BE CERTIFIED\n");
2045296465Sdelphij            ok = 0;
2046296465Sdelphij            goto err;
2047296465Sdelphij        }
2048296465Sdelphij    }
2049109998Smarkm#ifndef OPENSSL_NO_DSA
2050296465Sdelphij    if (pkey->type == EVP_PKEY_DSA)
2051296465Sdelphij        dgst = EVP_dss1();
2052296465Sdelphij    pktmp = X509_get_pubkey(ret);
2053296465Sdelphij    if (EVP_PKEY_missing_parameters(pktmp) &&
2054296465Sdelphij        !EVP_PKEY_missing_parameters(pkey))
2055296465Sdelphij        EVP_PKEY_copy_parameters(pktmp, pkey);
2056296465Sdelphij    EVP_PKEY_free(pktmp);
205755714Skris#endif
2058160814Ssimon#ifndef OPENSSL_NO_ECDSA
2059296465Sdelphij    if (pkey->type == EVP_PKEY_EC)
2060296465Sdelphij        dgst = EVP_ecdsa();
2061296465Sdelphij    pktmp = X509_get_pubkey(ret);
2062296465Sdelphij    if (EVP_PKEY_missing_parameters(pktmp) &&
2063296465Sdelphij        !EVP_PKEY_missing_parameters(pkey))
2064296465Sdelphij        EVP_PKEY_copy_parameters(pktmp, pkey);
2065296465Sdelphij    EVP_PKEY_free(pktmp);
2066160814Ssimon#endif
206755714Skris
2068296465Sdelphij    if (!X509_sign(ret, pkey, dgst))
2069296465Sdelphij        goto err;
2070160814Ssimon
2071296465Sdelphij    /* We now just add it to the database */
2072296465Sdelphij    row[DB_type] = (char *)OPENSSL_malloc(2);
207355714Skris
2074296465Sdelphij    tm = X509_get_notAfter(ret);
2075296465Sdelphij    row[DB_exp_date] = (char *)OPENSSL_malloc(tm->length + 1);
2076296465Sdelphij    memcpy(row[DB_exp_date], tm->data, tm->length);
2077296465Sdelphij    row[DB_exp_date][tm->length] = '\0';
207855714Skris
2079296465Sdelphij    row[DB_rev_date] = NULL;
208055714Skris
2081296465Sdelphij    /* row[DB_serial] done already */
2082296465Sdelphij    row[DB_file] = (char *)OPENSSL_malloc(8);
2083296465Sdelphij    row[DB_name] = X509_NAME_oneline(X509_get_subject_name(ret), NULL, 0);
208455714Skris
2085296465Sdelphij    if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2086296465Sdelphij        (row[DB_file] == NULL) || (row[DB_name] == NULL)) {
2087296465Sdelphij        BIO_printf(bio_err, "Memory allocation failure\n");
2088296465Sdelphij        goto err;
2089296465Sdelphij    }
2090296465Sdelphij    BUF_strlcpy(row[DB_file], "unknown", 8);
2091296465Sdelphij    row[DB_type][0] = 'V';
2092296465Sdelphij    row[DB_type][1] = '\0';
209355714Skris
2094296465Sdelphij    if ((irow =
2095296465Sdelphij         (char **)OPENSSL_malloc(sizeof(char *) * (DB_NUMBER + 1))) == NULL) {
2096296465Sdelphij        BIO_printf(bio_err, "Memory allocation failure\n");
2097296465Sdelphij        goto err;
2098296465Sdelphij    }
209955714Skris
2100296465Sdelphij    for (i = 0; i < DB_NUMBER; i++) {
2101296465Sdelphij        irow[i] = row[i];
2102296465Sdelphij        row[i] = NULL;
2103296465Sdelphij    }
2104296465Sdelphij    irow[DB_NUMBER] = NULL;
210555714Skris
2106296465Sdelphij    if (!TXT_DB_insert(db->db, irow)) {
2107296465Sdelphij        BIO_printf(bio_err, "failed to update database\n");
2108296465Sdelphij        BIO_printf(bio_err, "TXT_DB error number %ld\n", db->db->error);
2109296465Sdelphij        goto err;
2110296465Sdelphij    }
2111296465Sdelphij    ok = 1;
2112296465Sdelphij err:
2113296465Sdelphij    for (i = 0; i < DB_NUMBER; i++)
2114296465Sdelphij        if (row[i] != NULL)
2115296465Sdelphij            OPENSSL_free(row[i]);
211655714Skris
2117296465Sdelphij    if (CAname != NULL)
2118296465Sdelphij        X509_NAME_free(CAname);
2119296465Sdelphij    if (subject != NULL)
2120296465Sdelphij        X509_NAME_free(subject);
2121296465Sdelphij    if ((dn_subject != NULL) && !email_dn)
2122296465Sdelphij        X509_NAME_free(dn_subject);
2123296465Sdelphij    if (tmptm != NULL)
2124296465Sdelphij        ASN1_UTCTIME_free(tmptm);
2125296465Sdelphij    if (ok <= 0) {
2126296465Sdelphij        if (ret != NULL)
2127296465Sdelphij            X509_free(ret);
2128296465Sdelphij        ret = NULL;
2129296465Sdelphij    } else
2130296465Sdelphij        *xret = ret;
2131296465Sdelphij    return (ok);
2132296465Sdelphij}
213355714Skris
2134296465Sdelphijstatic void write_new_certificate(BIO *bp, X509 *x, int output_der,
2135296465Sdelphij                                  int notext)
2136296465Sdelphij{
213755714Skris
2138296465Sdelphij    if (output_der) {
2139296465Sdelphij        (void)i2d_X509_bio(bp, x);
2140296465Sdelphij        return;
2141296465Sdelphij    }
214259191Skris#if 0
2143296465Sdelphij    /* ??? Not needed since X509_print prints all this stuff anyway */
2144296465Sdelphij    f = X509_NAME_oneline(X509_get_issuer_name(x), buf, 256);
2145296465Sdelphij    BIO_printf(bp, "issuer :%s\n", f);
214655714Skris
2147296465Sdelphij    f = X509_NAME_oneline(X509_get_subject_name(x), buf, 256);
2148296465Sdelphij    BIO_printf(bp, "subject:%s\n", f);
214955714Skris
2150296465Sdelphij    BIO_puts(bp, "serial :");
2151296465Sdelphij    i2a_ASN1_INTEGER(bp, x->cert_info->serialNumber);
2152296465Sdelphij    BIO_puts(bp, "\n\n");
215359191Skris#endif
2154296465Sdelphij    if (!notext)
2155296465Sdelphij        X509_print(bp, x);
2156296465Sdelphij    PEM_write_bio_X509(bp, x);
2157296465Sdelphij}
215855714Skris
2159296465Sdelphijstatic int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey,
2160296465Sdelphij                         X509 *x509, const EVP_MD *dgst,
2161296465Sdelphij                         STACK_OF(CONF_VALUE) *policy, CA_DB *db,
2162296465Sdelphij                         BIGNUM *serial, char *subj, unsigned long chtype,
2163296465Sdelphij                         int multirdn, int email_dn, char *startdate,
2164296465Sdelphij                         char *enddate, long days, char *ext_sect,
2165296465Sdelphij                         CONF *lconf, int verbose, unsigned long certopt,
2166296465Sdelphij                         unsigned long nameopt, int default_op, int ext_copy)
2167296465Sdelphij{
2168296465Sdelphij    STACK_OF(CONF_VALUE) *sk = NULL;
2169296465Sdelphij    LHASH *parms = NULL;
2170296465Sdelphij    X509_REQ *req = NULL;
2171296465Sdelphij    CONF_VALUE *cv = NULL;
2172296465Sdelphij    NETSCAPE_SPKI *spki = NULL;
2173296465Sdelphij    X509_REQ_INFO *ri;
2174296465Sdelphij    char *type, *buf;
2175296465Sdelphij    EVP_PKEY *pktmp = NULL;
2176296465Sdelphij    X509_NAME *n = NULL;
2177296465Sdelphij    X509_NAME_ENTRY *ne = NULL;
2178296465Sdelphij    int ok = -1, i, j;
2179296465Sdelphij    long errline;
2180296465Sdelphij    int nid;
218155714Skris
2182296465Sdelphij    /*
2183296465Sdelphij     * Load input file into a hash table.  (This is just an easy
2184296465Sdelphij     * way to read and parse the file, then put it into a convenient
2185296465Sdelphij     * STACK format).
2186296465Sdelphij     */
2187296465Sdelphij    parms = CONF_load(NULL, infile, &errline);
2188296465Sdelphij    if (parms == NULL) {
2189296465Sdelphij        BIO_printf(bio_err, "error on line %ld of %s\n", errline, infile);
2190296465Sdelphij        ERR_print_errors(bio_err);
2191296465Sdelphij        goto err;
2192296465Sdelphij    }
219355714Skris
2194296465Sdelphij    sk = CONF_get_section(parms, "default");
2195296465Sdelphij    if (sk_CONF_VALUE_num(sk) == 0) {
2196296465Sdelphij        BIO_printf(bio_err, "no name/value pairs found in %s\n", infile);
2197296465Sdelphij        CONF_free(parms);
2198296465Sdelphij        goto err;
2199296465Sdelphij    }
220055714Skris
2201296465Sdelphij    /*
2202296465Sdelphij     * Now create a dummy X509 request structure.  We don't actually
2203296465Sdelphij     * have an X509 request, but we have many of the components
2204296465Sdelphij     * (a public key, various DN components).  The idea is that we
2205296465Sdelphij     * put these components into the right X509 request structure
2206296465Sdelphij     * and we can use the same code as if you had a real X509 request.
2207296465Sdelphij     */
2208296465Sdelphij    req = X509_REQ_new();
2209296465Sdelphij    if (req == NULL) {
2210296465Sdelphij        ERR_print_errors(bio_err);
2211296465Sdelphij        goto err;
2212296465Sdelphij    }
221355714Skris
2214296465Sdelphij    /*
2215296465Sdelphij     * Build up the subject name set.
2216296465Sdelphij     */
2217296465Sdelphij    ri = req->req_info;
2218296465Sdelphij    n = ri->subject;
221955714Skris
2220296465Sdelphij    for (i = 0;; i++) {
2221296465Sdelphij        if (sk_CONF_VALUE_num(sk) <= i)
2222296465Sdelphij            break;
222355714Skris
2224296465Sdelphij        cv = sk_CONF_VALUE_value(sk, i);
2225296465Sdelphij        type = cv->name;
2226296465Sdelphij        /*
2227296465Sdelphij         * Skip past any leading X. X: X, etc to allow for multiple instances
2228296465Sdelphij         */
2229296465Sdelphij        for (buf = cv->name; *buf; buf++)
2230296465Sdelphij            if ((*buf == ':') || (*buf == ',') || (*buf == '.')) {
2231296465Sdelphij                buf++;
2232296465Sdelphij                if (*buf)
2233296465Sdelphij                    type = buf;
2234296465Sdelphij                break;
2235296465Sdelphij            }
223659191Skris
2237296465Sdelphij        buf = cv->value;
2238296465Sdelphij        if ((nid = OBJ_txt2nid(type)) == NID_undef) {
2239296465Sdelphij            if (strcmp(type, "SPKAC") == 0) {
2240296465Sdelphij                spki = NETSCAPE_SPKI_b64_decode(cv->value, -1);
2241296465Sdelphij                if (spki == NULL) {
2242296465Sdelphij                    BIO_printf(bio_err,
2243296465Sdelphij                               "unable to load Netscape SPKAC structure\n");
2244296465Sdelphij                    ERR_print_errors(bio_err);
2245296465Sdelphij                    goto err;
2246296465Sdelphij                }
2247296465Sdelphij            }
2248296465Sdelphij            continue;
2249296465Sdelphij        }
225055714Skris
2251296465Sdelphij        if (!X509_NAME_add_entry_by_NID(n, nid, chtype,
2252296465Sdelphij                                        (unsigned char *)buf, -1, -1, 0))
2253296465Sdelphij            goto err;
2254296465Sdelphij    }
2255296465Sdelphij    if (spki == NULL) {
2256296465Sdelphij        BIO_printf(bio_err, "Netscape SPKAC structure not found in %s\n",
2257296465Sdelphij                   infile);
2258296465Sdelphij        goto err;
2259296465Sdelphij    }
226055714Skris
2261296465Sdelphij    /*
2262296465Sdelphij     * Now extract the key from the SPKI structure.
2263296465Sdelphij     */
226455714Skris
2265296465Sdelphij    BIO_printf(bio_err,
2266296465Sdelphij               "Check that the SPKAC request matches the signature\n");
226755714Skris
2268296465Sdelphij    if ((pktmp = NETSCAPE_SPKI_get_pubkey(spki)) == NULL) {
2269296465Sdelphij        BIO_printf(bio_err, "error unpacking SPKAC public key\n");
2270296465Sdelphij        goto err;
2271296465Sdelphij    }
227255714Skris
2273296465Sdelphij    j = NETSCAPE_SPKI_verify(spki, pktmp);
2274296465Sdelphij    if (j <= 0) {
2275296465Sdelphij        BIO_printf(bio_err,
2276296465Sdelphij                   "signature verification failed on SPKAC public key\n");
2277296465Sdelphij        goto err;
2278296465Sdelphij    }
2279296465Sdelphij    BIO_printf(bio_err, "Signature ok\n");
228055714Skris
2281296465Sdelphij    X509_REQ_set_pubkey(req, pktmp);
2282296465Sdelphij    EVP_PKEY_free(pktmp);
2283296465Sdelphij    ok = do_body(xret, pkey, x509, dgst, policy, db, serial, subj, chtype,
2284296465Sdelphij                 multirdn, email_dn, startdate, enddate, days, 1, verbose,
2285296465Sdelphij                 req, ext_sect, lconf, certopt, nameopt, default_op, ext_copy,
2286296465Sdelphij                 0);
2287296465Sdelphij err:
2288296465Sdelphij    if (req != NULL)
2289296465Sdelphij        X509_REQ_free(req);
2290296465Sdelphij    if (parms != NULL)
2291296465Sdelphij        CONF_free(parms);
2292296465Sdelphij    if (spki != NULL)
2293296465Sdelphij        NETSCAPE_SPKI_free(spki);
2294296465Sdelphij    if (ne != NULL)
2295296465Sdelphij        X509_NAME_ENTRY_free(ne);
229655714Skris
2297296465Sdelphij    return (ok);
2298296465Sdelphij}
229955714Skris
2300205128Ssimonstatic int check_time_format(const char *str)
2301296465Sdelphij{
2302296465Sdelphij    ASN1_TIME tm;
230355714Skris
2304296465Sdelphij    tm.data = (unsigned char *)str;
2305296465Sdelphij    tm.length = strlen(str);
2306296465Sdelphij    tm.type = V_ASN1_UTCTIME;
2307296465Sdelphij    if (ASN1_TIME_check(&tm))
2308296465Sdelphij        return 1;
2309296465Sdelphij    tm.type = V_ASN1_GENERALIZEDTIME;
2310296465Sdelphij    return ASN1_TIME_check(&tm);
2311296465Sdelphij}
231255714Skris
2313127128Snectarstatic int do_revoke(X509 *x509, CA_DB *db, int type, char *value)
2314296465Sdelphij{
2315296465Sdelphij    ASN1_UTCTIME *tm = NULL;
2316296465Sdelphij    char *row[DB_NUMBER], **rrow, **irow;
2317296465Sdelphij    char *rev_str = NULL;
2318296465Sdelphij    BIGNUM *bn = NULL;
2319296465Sdelphij    int ok = -1, i;
232055714Skris
2321296465Sdelphij    for (i = 0; i < DB_NUMBER; i++)
2322296465Sdelphij        row[i] = NULL;
2323296465Sdelphij    row[DB_name] = X509_NAME_oneline(X509_get_subject_name(x509), NULL, 0);
2324296465Sdelphij    bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x509), NULL);
2325296465Sdelphij    if (BN_is_zero(bn))
2326296465Sdelphij        row[DB_serial] = BUF_strdup("00");
2327296465Sdelphij    else
2328296465Sdelphij        row[DB_serial] = BN_bn2hex(bn);
2329296465Sdelphij    BN_free(bn);
2330296465Sdelphij    if ((row[DB_name] == NULL) || (row[DB_serial] == NULL)) {
2331296465Sdelphij        BIO_printf(bio_err, "Memory allocation failure\n");
2332296465Sdelphij        goto err;
2333296465Sdelphij    }
2334296465Sdelphij    /*
2335296465Sdelphij     * We have to lookup by serial number because name lookup skips revoked
2336296465Sdelphij     * certs
2337296465Sdelphij     */
2338296465Sdelphij    rrow = TXT_DB_get_by_index(db->db, DB_serial, row);
2339296465Sdelphij    if (rrow == NULL) {
2340296465Sdelphij        BIO_printf(bio_err,
2341296465Sdelphij                   "Adding Entry with serial number %s to DB for %s\n",
2342296465Sdelphij                   row[DB_serial], row[DB_name]);
234355714Skris
2344296465Sdelphij        /* We now just add it to the database */
2345296465Sdelphij        row[DB_type] = (char *)OPENSSL_malloc(2);
234655714Skris
2347296465Sdelphij        tm = X509_get_notAfter(x509);
2348296465Sdelphij        row[DB_exp_date] = (char *)OPENSSL_malloc(tm->length + 1);
2349296465Sdelphij        memcpy(row[DB_exp_date], tm->data, tm->length);
2350296465Sdelphij        row[DB_exp_date][tm->length] = '\0';
235155714Skris
2352296465Sdelphij        row[DB_rev_date] = NULL;
235355714Skris
2354296465Sdelphij        /* row[DB_serial] done already */
2355296465Sdelphij        row[DB_file] = (char *)OPENSSL_malloc(8);
235655714Skris
2357296465Sdelphij        /* row[DB_name] done already */
235855714Skris
2359296465Sdelphij        if ((row[DB_type] == NULL) || (row[DB_exp_date] == NULL) ||
2360296465Sdelphij            (row[DB_file] == NULL)) {
2361296465Sdelphij            BIO_printf(bio_err, "Memory allocation failure\n");
2362296465Sdelphij            goto err;
2363296465Sdelphij        }
2364296465Sdelphij        BUF_strlcpy(row[DB_file], "unknown", 8);
2365296465Sdelphij        row[DB_type][0] = 'V';
2366296465Sdelphij        row[DB_type][1] = '\0';
236755714Skris
2368296465Sdelphij        if ((irow =
2369296465Sdelphij             (char **)OPENSSL_malloc(sizeof(char *) * (DB_NUMBER + 1))) ==
2370296465Sdelphij            NULL) {
2371296465Sdelphij            BIO_printf(bio_err, "Memory allocation failure\n");
2372296465Sdelphij            goto err;
2373296465Sdelphij        }
237455714Skris
2375296465Sdelphij        for (i = 0; i < DB_NUMBER; i++) {
2376296465Sdelphij            irow[i] = row[i];
2377296465Sdelphij            row[i] = NULL;
2378296465Sdelphij        }
2379296465Sdelphij        irow[DB_NUMBER] = NULL;
238055714Skris
2381296465Sdelphij        if (!TXT_DB_insert(db->db, irow)) {
2382296465Sdelphij            BIO_printf(bio_err, "failed to update database\n");
2383296465Sdelphij            BIO_printf(bio_err, "TXT_DB error number %ld\n", db->db->error);
2384296465Sdelphij            goto err;
2385296465Sdelphij        }
238655714Skris
2387296465Sdelphij        /* Revoke Certificate */
2388296465Sdelphij        ok = do_revoke(x509, db, type, value);
238955714Skris
2390296465Sdelphij        goto err;
239155714Skris
2392296465Sdelphij    } else if (index_name_cmp((const char **)row, (const char **)rrow)) {
2393296465Sdelphij        BIO_printf(bio_err, "ERROR:name does not match %s\n", row[DB_name]);
2394296465Sdelphij        goto err;
2395296465Sdelphij    } else if (rrow[DB_type][0] == 'R') {
2396296465Sdelphij        BIO_printf(bio_err, "ERROR:Already revoked, serial number %s\n",
2397296465Sdelphij                   row[DB_serial]);
2398296465Sdelphij        goto err;
2399296465Sdelphij    } else {
2400296465Sdelphij        BIO_printf(bio_err, "Revoking Certificate %s.\n", rrow[DB_serial]);
2401296465Sdelphij        rev_str = make_revocation_str(type, value);
2402296465Sdelphij        if (!rev_str) {
2403296465Sdelphij            BIO_printf(bio_err, "Error in revocation arguments\n");
2404296465Sdelphij            goto err;
2405296465Sdelphij        }
2406296465Sdelphij        rrow[DB_type][0] = 'R';
2407296465Sdelphij        rrow[DB_type][1] = '\0';
2408296465Sdelphij        rrow[DB_rev_date] = rev_str;
2409296465Sdelphij    }
2410296465Sdelphij    ok = 1;
2411296465Sdelphij err:
2412296465Sdelphij    for (i = 0; i < DB_NUMBER; i++) {
2413296465Sdelphij        if (row[i] != NULL)
2414296465Sdelphij            OPENSSL_free(row[i]);
2415296465Sdelphij    }
2416296465Sdelphij    return (ok);
2417296465Sdelphij}
2418109998Smarkm
2419127128Snectarstatic int get_certificate_status(const char *serial, CA_DB *db)
2420296465Sdelphij{
2421296465Sdelphij    char *row[DB_NUMBER], **rrow;
2422296465Sdelphij    int ok = -1, i;
2423109998Smarkm
2424296465Sdelphij    /* Free Resources */
2425296465Sdelphij    for (i = 0; i < DB_NUMBER; i++)
2426296465Sdelphij        row[i] = NULL;
2427109998Smarkm
2428296465Sdelphij    /* Malloc needed char spaces */
2429296465Sdelphij    row[DB_serial] = OPENSSL_malloc(strlen(serial) + 2);
2430296465Sdelphij    if (row[DB_serial] == NULL) {
2431296465Sdelphij        BIO_printf(bio_err, "Malloc failure\n");
2432296465Sdelphij        goto err;
2433296465Sdelphij    }
2434109998Smarkm
2435296465Sdelphij    if (strlen(serial) % 2) {
2436296465Sdelphij        /*
2437296465Sdelphij         * Set the first char to 0
2438296465Sdelphij         */ ;
2439296465Sdelphij        row[DB_serial][0] = '0';
2440109998Smarkm
2441296465Sdelphij        /* Copy String from serial to row[DB_serial] */
2442296465Sdelphij        memcpy(row[DB_serial] + 1, serial, strlen(serial));
2443296465Sdelphij        row[DB_serial][strlen(serial) + 1] = '\0';
2444296465Sdelphij    } else {
2445296465Sdelphij        /* Copy String from serial to row[DB_serial] */
2446296465Sdelphij        memcpy(row[DB_serial], serial, strlen(serial));
2447296465Sdelphij        row[DB_serial][strlen(serial)] = '\0';
2448296465Sdelphij    }
2449109998Smarkm
2450296465Sdelphij    /* Make it Upper Case */
2451296465Sdelphij    for (i = 0; row[DB_serial][i] != '\0'; i++)
2452296465Sdelphij        row[DB_serial][i] = toupper(row[DB_serial][i]);
2453109998Smarkm
2454296465Sdelphij    ok = 1;
2455109998Smarkm
2456296465Sdelphij    /* Search for the certificate */
2457296465Sdelphij    rrow = TXT_DB_get_by_index(db->db, DB_serial, row);
2458296465Sdelphij    if (rrow == NULL) {
2459296465Sdelphij        BIO_printf(bio_err, "Serial %s not present in db.\n", row[DB_serial]);
2460296465Sdelphij        ok = -1;
2461296465Sdelphij        goto err;
2462296465Sdelphij    } else if (rrow[DB_type][0] == 'V') {
2463296465Sdelphij        BIO_printf(bio_err, "%s=Valid (%c)\n",
2464296465Sdelphij                   row[DB_serial], rrow[DB_type][0]);
2465296465Sdelphij        goto err;
2466296465Sdelphij    } else if (rrow[DB_type][0] == 'R') {
2467296465Sdelphij        BIO_printf(bio_err, "%s=Revoked (%c)\n",
2468296465Sdelphij                   row[DB_serial], rrow[DB_type][0]);
2469296465Sdelphij        goto err;
2470296465Sdelphij    } else if (rrow[DB_type][0] == 'E') {
2471296465Sdelphij        BIO_printf(bio_err, "%s=Expired (%c)\n",
2472296465Sdelphij                   row[DB_serial], rrow[DB_type][0]);
2473296465Sdelphij        goto err;
2474296465Sdelphij    } else if (rrow[DB_type][0] == 'S') {
2475296465Sdelphij        BIO_printf(bio_err, "%s=Suspended (%c)\n",
2476296465Sdelphij                   row[DB_serial], rrow[DB_type][0]);
2477296465Sdelphij        goto err;
2478296465Sdelphij    } else {
2479296465Sdelphij        BIO_printf(bio_err, "%s=Unknown (%c).\n",
2480296465Sdelphij                   row[DB_serial], rrow[DB_type][0]);
2481296465Sdelphij        ok = -1;
2482296465Sdelphij    }
2483296465Sdelphij err:
2484296465Sdelphij    for (i = 0; i < DB_NUMBER; i++) {
2485296465Sdelphij        if (row[i] != NULL)
2486296465Sdelphij            OPENSSL_free(row[i]);
2487296465Sdelphij    }
2488296465Sdelphij    return (ok);
2489296465Sdelphij}
2490109998Smarkm
2491296465Sdelphijstatic int do_updatedb(CA_DB *db)
2492296465Sdelphij{
2493296465Sdelphij    ASN1_UTCTIME *a_tm = NULL;
2494296465Sdelphij    int i, cnt = 0;
2495296465Sdelphij    int db_y2k, a_y2k;          /* flags = 1 if y >= 2000 */
2496296465Sdelphij    char **rrow, *a_tm_s;
2497109998Smarkm
2498296465Sdelphij    a_tm = ASN1_UTCTIME_new();
2499109998Smarkm
2500296465Sdelphij    /* get actual time and make a string */
2501296465Sdelphij    a_tm = X509_gmtime_adj(a_tm, 0);
2502296465Sdelphij    a_tm_s = (char *)OPENSSL_malloc(a_tm->length + 1);
2503296465Sdelphij    if (a_tm_s == NULL) {
2504296465Sdelphij        cnt = -1;
2505296465Sdelphij        goto err;
2506296465Sdelphij    }
2507109998Smarkm
2508296465Sdelphij    memcpy(a_tm_s, a_tm->data, a_tm->length);
2509296465Sdelphij    a_tm_s[a_tm->length] = '\0';
2510109998Smarkm
2511296465Sdelphij    if (strncmp(a_tm_s, "49", 2) <= 0)
2512296465Sdelphij        a_y2k = 1;
2513296465Sdelphij    else
2514296465Sdelphij        a_y2k = 0;
2515109998Smarkm
2516296465Sdelphij    for (i = 0; i < sk_num(db->db->data); i++) {
2517296465Sdelphij        rrow = (char **)sk_value(db->db->data, i);
2518109998Smarkm
2519296465Sdelphij        if (rrow[DB_type][0] == 'V') {
2520296465Sdelphij            /* ignore entries that are not valid */
2521296465Sdelphij            if (strncmp(rrow[DB_exp_date], "49", 2) <= 0)
2522296465Sdelphij                db_y2k = 1;
2523296465Sdelphij            else
2524296465Sdelphij                db_y2k = 0;
2525109998Smarkm
2526296465Sdelphij            if (db_y2k == a_y2k) {
2527296465Sdelphij                /* all on the same y2k side */
2528296465Sdelphij                if (strcmp(rrow[DB_exp_date], a_tm_s) <= 0) {
2529296465Sdelphij                    rrow[DB_type][0] = 'E';
2530296465Sdelphij                    rrow[DB_type][1] = '\0';
2531296465Sdelphij                    cnt++;
2532109998Smarkm
2533296465Sdelphij                    BIO_printf(bio_err, "%s=Expired\n", rrow[DB_serial]);
2534296465Sdelphij                }
2535296465Sdelphij            } else if (db_y2k < a_y2k) {
2536296465Sdelphij                rrow[DB_type][0] = 'E';
2537296465Sdelphij                rrow[DB_type][1] = '\0';
2538296465Sdelphij                cnt++;
2539109998Smarkm
2540296465Sdelphij                BIO_printf(bio_err, "%s=Expired\n", rrow[DB_serial]);
2541296465Sdelphij            }
2542109998Smarkm
2543296465Sdelphij        }
2544296465Sdelphij    }
2545109998Smarkm
2546296465Sdelphij err:
2547109998Smarkm
2548296465Sdelphij    ASN1_UTCTIME_free(a_tm);
2549296465Sdelphij    OPENSSL_free(a_tm_s);
2550109998Smarkm
2551296465Sdelphij    return (cnt);
2552296465Sdelphij}
2553296465Sdelphij
2554160814Ssimonstatic const char *crl_reasons[] = {
2555296465Sdelphij    /* CRL reason strings */
2556296465Sdelphij    "unspecified",
2557296465Sdelphij    "keyCompromise",
2558296465Sdelphij    "CACompromise",
2559296465Sdelphij    "affiliationChanged",
2560296465Sdelphij    "superseded",
2561296465Sdelphij    "cessationOfOperation",
2562296465Sdelphij    "certificateHold",
2563296465Sdelphij    "removeFromCRL",
2564296465Sdelphij    /* Additional pseudo reasons */
2565296465Sdelphij    "holdInstruction",
2566296465Sdelphij    "keyTime",
2567296465Sdelphij    "CAkeyTime"
2568109998Smarkm};
2569109998Smarkm
2570109998Smarkm#define NUM_REASONS (sizeof(crl_reasons) / sizeof(char *))
2571109998Smarkm
2572296465Sdelphij/*
2573296465Sdelphij * Given revocation information convert to a DB string. The format of the
2574296465Sdelphij * string is: revtime[,reason,extra]. Where 'revtime' is the revocation time
2575296465Sdelphij * (the current time). 'reason' is the optional CRL reason and 'extra' is any
2576296465Sdelphij * additional argument
2577109998Smarkm */
2578109998Smarkm
2579109998Smarkmchar *make_revocation_str(int rev_type, char *rev_arg)
2580296465Sdelphij{
2581296465Sdelphij    char *other = NULL, *str;
2582296465Sdelphij    const char *reason = NULL;
2583296465Sdelphij    ASN1_OBJECT *otmp;
2584296465Sdelphij    ASN1_UTCTIME *revtm = NULL;
2585296465Sdelphij    int i;
2586296465Sdelphij    switch (rev_type) {
2587296465Sdelphij    case REV_NONE:
2588296465Sdelphij        break;
2589109998Smarkm
2590296465Sdelphij    case REV_CRL_REASON:
2591296465Sdelphij        for (i = 0; i < 8; i++) {
2592296465Sdelphij            if (!strcasecmp(rev_arg, crl_reasons[i])) {
2593296465Sdelphij                reason = crl_reasons[i];
2594296465Sdelphij                break;
2595296465Sdelphij            }
2596296465Sdelphij        }
2597296465Sdelphij        if (reason == NULL) {
2598296465Sdelphij            BIO_printf(bio_err, "Unknown CRL reason %s\n", rev_arg);
2599296465Sdelphij            return NULL;
2600296465Sdelphij        }
2601296465Sdelphij        break;
2602109998Smarkm
2603296465Sdelphij    case REV_HOLD:
2604296465Sdelphij        /* Argument is an OID */
2605109998Smarkm
2606296465Sdelphij        otmp = OBJ_txt2obj(rev_arg, 0);
2607296465Sdelphij        ASN1_OBJECT_free(otmp);
2608109998Smarkm
2609296465Sdelphij        if (otmp == NULL) {
2610296465Sdelphij            BIO_printf(bio_err, "Invalid object identifier %s\n", rev_arg);
2611296465Sdelphij            return NULL;
2612296465Sdelphij        }
2613109998Smarkm
2614296465Sdelphij        reason = "holdInstruction";
2615296465Sdelphij        other = rev_arg;
2616296465Sdelphij        break;
2617109998Smarkm
2618296465Sdelphij    case REV_KEY_COMPROMISE:
2619296465Sdelphij    case REV_CA_COMPROMISE:
2620109998Smarkm
2621296465Sdelphij        /* Argument is the key compromise time  */
2622296465Sdelphij        if (!ASN1_GENERALIZEDTIME_set_string(NULL, rev_arg)) {
2623296465Sdelphij            BIO_printf(bio_err,
2624296465Sdelphij                       "Invalid time format %s. Need YYYYMMDDHHMMSSZ\n",
2625296465Sdelphij                       rev_arg);
2626296465Sdelphij            return NULL;
2627296465Sdelphij        }
2628296465Sdelphij        other = rev_arg;
2629296465Sdelphij        if (rev_type == REV_KEY_COMPROMISE)
2630296465Sdelphij            reason = "keyTime";
2631296465Sdelphij        else
2632296465Sdelphij            reason = "CAkeyTime";
2633109998Smarkm
2634296465Sdelphij        break;
2635109998Smarkm
2636296465Sdelphij    }
2637109998Smarkm
2638296465Sdelphij    revtm = X509_gmtime_adj(NULL, 0);
2639279265Sdelphij
2640296465Sdelphij    if (!revtm)
2641296465Sdelphij        return NULL;
2642109998Smarkm
2643296465Sdelphij    i = revtm->length + 1;
2644109998Smarkm
2645296465Sdelphij    if (reason)
2646296465Sdelphij        i += strlen(reason) + 1;
2647296465Sdelphij    if (other)
2648296465Sdelphij        i += strlen(other) + 1;
2649109998Smarkm
2650296465Sdelphij    str = OPENSSL_malloc(i);
2651109998Smarkm
2652296465Sdelphij    if (!str)
2653296465Sdelphij        return NULL;
2654109998Smarkm
2655296465Sdelphij    BUF_strlcpy(str, (char *)revtm->data, i);
2656296465Sdelphij    if (reason) {
2657296465Sdelphij        BUF_strlcat(str, ",", i);
2658296465Sdelphij        BUF_strlcat(str, reason, i);
2659296465Sdelphij    }
2660296465Sdelphij    if (other) {
2661296465Sdelphij        BUF_strlcat(str, ",", i);
2662296465Sdelphij        BUF_strlcat(str, other, i);
2663296465Sdelphij    }
2664296465Sdelphij    ASN1_UTCTIME_free(revtm);
2665296465Sdelphij    return str;
2666296465Sdelphij}
2667296465Sdelphij
2668296465Sdelphij/*-
2669296465Sdelphij * Convert revocation field to X509_REVOKED entry
2670109998Smarkm * return code:
2671109998Smarkm * 0 error
2672109998Smarkm * 1 OK
2673109998Smarkm * 2 OK and some extensions added (i.e. V2 CRL)
2674109998Smarkm */
2675109998Smarkm
2676160814Ssimonint make_revoked(X509_REVOKED *rev, const char *str)
2677296465Sdelphij{
2678296465Sdelphij    char *tmp = NULL;
2679296465Sdelphij    int reason_code = -1;
2680296465Sdelphij    int i, ret = 0;
2681296465Sdelphij    ASN1_OBJECT *hold = NULL;
2682296465Sdelphij    ASN1_GENERALIZEDTIME *comp_time = NULL;
2683296465Sdelphij    ASN1_ENUMERATED *rtmp = NULL;
2684109998Smarkm
2685296465Sdelphij    ASN1_TIME *revDate = NULL;
2686109998Smarkm
2687296465Sdelphij    i = unpack_revinfo(&revDate, &reason_code, &hold, &comp_time, str);
2688109998Smarkm
2689296465Sdelphij    if (i == 0)
2690296465Sdelphij        goto err;
2691109998Smarkm
2692296465Sdelphij    if (rev && !X509_REVOKED_set_revocationDate(rev, revDate))
2693296465Sdelphij        goto err;
2694109998Smarkm
2695296465Sdelphij    if (rev && (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)) {
2696296465Sdelphij        rtmp = ASN1_ENUMERATED_new();
2697296465Sdelphij        if (!rtmp || !ASN1_ENUMERATED_set(rtmp, reason_code))
2698296465Sdelphij            goto err;
2699296465Sdelphij        if (!X509_REVOKED_add1_ext_i2d(rev, NID_crl_reason, rtmp, 0, 0))
2700296465Sdelphij            goto err;
2701296465Sdelphij    }
2702109998Smarkm
2703296465Sdelphij    if (rev && comp_time) {
2704296465Sdelphij        if (!X509_REVOKED_add1_ext_i2d
2705296465Sdelphij            (rev, NID_invalidity_date, comp_time, 0, 0))
2706296465Sdelphij            goto err;
2707296465Sdelphij    }
2708296465Sdelphij    if (rev && hold) {
2709296465Sdelphij        if (!X509_REVOKED_add1_ext_i2d
2710296465Sdelphij            (rev, NID_hold_instruction_code, hold, 0, 0))
2711296465Sdelphij            goto err;
2712296465Sdelphij    }
2713109998Smarkm
2714296465Sdelphij    if (reason_code != OCSP_REVOKED_STATUS_NOSTATUS)
2715296465Sdelphij        ret = 2;
2716296465Sdelphij    else
2717296465Sdelphij        ret = 1;
2718109998Smarkm
2719296465Sdelphij err:
2720109998Smarkm
2721296465Sdelphij    if (tmp)
2722296465Sdelphij        OPENSSL_free(tmp);
2723296465Sdelphij    ASN1_OBJECT_free(hold);
2724296465Sdelphij    ASN1_GENERALIZEDTIME_free(comp_time);
2725296465Sdelphij    ASN1_ENUMERATED_free(rtmp);
2726296465Sdelphij    ASN1_TIME_free(revDate);
2727109998Smarkm
2728296465Sdelphij    return ret;
2729296465Sdelphij}
2730109998Smarkm
2731109998Smarkmint old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str)
2732296465Sdelphij{
2733296465Sdelphij    char buf[25], *pbuf, *p;
2734296465Sdelphij    int j;
2735296465Sdelphij    j = i2a_ASN1_OBJECT(bp, obj);
2736296465Sdelphij    pbuf = buf;
2737296465Sdelphij    for (j = 22 - j; j > 0; j--)
2738296465Sdelphij        *(pbuf++) = ' ';
2739296465Sdelphij    *(pbuf++) = ':';
2740296465Sdelphij    *(pbuf++) = '\0';
2741296465Sdelphij    BIO_puts(bp, buf);
2742109998Smarkm
2743296465Sdelphij    if (str->type == V_ASN1_PRINTABLESTRING)
2744296465Sdelphij        BIO_printf(bp, "PRINTABLE:'");
2745296465Sdelphij    else if (str->type == V_ASN1_T61STRING)
2746296465Sdelphij        BIO_printf(bp, "T61STRING:'");
2747296465Sdelphij    else if (str->type == V_ASN1_IA5STRING)
2748296465Sdelphij        BIO_printf(bp, "IA5STRING:'");
2749296465Sdelphij    else if (str->type == V_ASN1_UNIVERSALSTRING)
2750296465Sdelphij        BIO_printf(bp, "UNIVERSALSTRING:'");
2751296465Sdelphij    else
2752296465Sdelphij        BIO_printf(bp, "ASN.1 %2d:'", str->type);
2753296465Sdelphij
2754296465Sdelphij    p = (char *)str->data;
2755296465Sdelphij    for (j = str->length; j > 0; j--) {
2756194206Ssimon#ifdef CHARSET_EBCDIC
2757296465Sdelphij        if ((*p >= 0x20) && (*p <= 0x7e))
2758296465Sdelphij            BIO_printf(bp, "%c", os_toebcdic[*p]);
2759194206Ssimon#else
2760296465Sdelphij        if ((*p >= ' ') && (*p <= '~'))
2761296465Sdelphij            BIO_printf(bp, "%c", *p);
2762194206Ssimon#endif
2763296465Sdelphij        else if (*p & 0x80)
2764296465Sdelphij            BIO_printf(bp, "\\0x%02X", *p);
2765296465Sdelphij        else if ((unsigned char)*p == 0xf7)
2766296465Sdelphij            BIO_printf(bp, "^?");
2767194206Ssimon#ifdef CHARSET_EBCDIC
2768296465Sdelphij        else
2769296465Sdelphij            BIO_printf(bp, "^%c", os_toebcdic[*p + 0x40]);
2770194206Ssimon#else
2771296465Sdelphij        else
2772296465Sdelphij            BIO_printf(bp, "^%c", *p + '@');
2773194206Ssimon#endif
2774296465Sdelphij        p++;
2775296465Sdelphij    }
2776296465Sdelphij    BIO_printf(bp, "'\n");
2777296465Sdelphij    return 1;
2778296465Sdelphij}
2779109998Smarkm
2780296465Sdelphijint unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold,
2781296465Sdelphij                   ASN1_GENERALIZEDTIME **pinvtm, const char *str)
2782296465Sdelphij{
2783296465Sdelphij    char *tmp = NULL;
2784296465Sdelphij    char *rtime_str, *reason_str = NULL, *arg_str = NULL, *p;
2785296465Sdelphij    int reason_code = -1;
2786296465Sdelphij    int ret = 0;
2787296465Sdelphij    unsigned int i;
2788296465Sdelphij    ASN1_OBJECT *hold = NULL;
2789296465Sdelphij    ASN1_GENERALIZEDTIME *comp_time = NULL;
2790296465Sdelphij    tmp = BUF_strdup(str);
2791109998Smarkm
2792296465Sdelphij    p = strchr(tmp, ',');
2793109998Smarkm
2794296465Sdelphij    rtime_str = tmp;
2795109998Smarkm
2796296465Sdelphij    if (p) {
2797296465Sdelphij        *p = '\0';
2798296465Sdelphij        p++;
2799296465Sdelphij        reason_str = p;
2800296465Sdelphij        p = strchr(p, ',');
2801296465Sdelphij        if (p) {
2802296465Sdelphij            *p = '\0';
2803296465Sdelphij            arg_str = p + 1;
2804296465Sdelphij        }
2805296465Sdelphij    }
2806109998Smarkm
2807296465Sdelphij    if (prevtm) {
2808296465Sdelphij        *prevtm = ASN1_UTCTIME_new();
2809296465Sdelphij        if (!ASN1_UTCTIME_set_string(*prevtm, rtime_str)) {
2810296465Sdelphij            BIO_printf(bio_err, "invalid revocation date %s\n", rtime_str);
2811296465Sdelphij            goto err;
2812296465Sdelphij        }
2813296465Sdelphij    }
2814296465Sdelphij    if (reason_str) {
2815296465Sdelphij        for (i = 0; i < NUM_REASONS; i++) {
2816296465Sdelphij            if (!strcasecmp(reason_str, crl_reasons[i])) {
2817296465Sdelphij                reason_code = i;
2818296465Sdelphij                break;
2819296465Sdelphij            }
2820296465Sdelphij        }
2821296465Sdelphij        if (reason_code == OCSP_REVOKED_STATUS_NOSTATUS) {
2822296465Sdelphij            BIO_printf(bio_err, "invalid reason code %s\n", reason_str);
2823296465Sdelphij            goto err;
2824296465Sdelphij        }
2825109998Smarkm
2826296465Sdelphij        if (reason_code == 7)
2827296465Sdelphij            reason_code = OCSP_REVOKED_STATUS_REMOVEFROMCRL;
2828296465Sdelphij        else if (reason_code == 8) { /* Hold instruction */
2829296465Sdelphij            if (!arg_str) {
2830296465Sdelphij                BIO_printf(bio_err, "missing hold instruction\n");
2831296465Sdelphij                goto err;
2832296465Sdelphij            }
2833296465Sdelphij            reason_code = OCSP_REVOKED_STATUS_CERTIFICATEHOLD;
2834296465Sdelphij            hold = OBJ_txt2obj(arg_str, 0);
2835109998Smarkm
2836296465Sdelphij            if (!hold) {
2837296465Sdelphij                BIO_printf(bio_err, "invalid object identifier %s\n",
2838296465Sdelphij                           arg_str);
2839296465Sdelphij                goto err;
2840296465Sdelphij            }
2841296465Sdelphij            if (phold)
2842296465Sdelphij                *phold = hold;
2843296465Sdelphij        } else if ((reason_code == 9) || (reason_code == 10)) {
2844296465Sdelphij            if (!arg_str) {
2845296465Sdelphij                BIO_printf(bio_err, "missing compromised time\n");
2846296465Sdelphij                goto err;
2847296465Sdelphij            }
2848296465Sdelphij            comp_time = ASN1_GENERALIZEDTIME_new();
2849296465Sdelphij            if (!ASN1_GENERALIZEDTIME_set_string(comp_time, arg_str)) {
2850296465Sdelphij                BIO_printf(bio_err, "invalid compromised time %s\n", arg_str);
2851296465Sdelphij                goto err;
2852296465Sdelphij            }
2853296465Sdelphij            if (reason_code == 9)
2854296465Sdelphij                reason_code = OCSP_REVOKED_STATUS_KEYCOMPROMISE;
2855296465Sdelphij            else
2856296465Sdelphij                reason_code = OCSP_REVOKED_STATUS_CACOMPROMISE;
2857296465Sdelphij        }
2858296465Sdelphij    }
2859109998Smarkm
2860296465Sdelphij    if (preason)
2861296465Sdelphij        *preason = reason_code;
2862296465Sdelphij    if (pinvtm)
2863296465Sdelphij        *pinvtm = comp_time;
2864296465Sdelphij    else
2865296465Sdelphij        ASN1_GENERALIZEDTIME_free(comp_time);
2866109998Smarkm
2867296465Sdelphij    ret = 1;
2868109998Smarkm
2869296465Sdelphij err:
2870109998Smarkm
2871296465Sdelphij    if (tmp)
2872296465Sdelphij        OPENSSL_free(tmp);
2873296465Sdelphij    if (!phold)
2874296465Sdelphij        ASN1_OBJECT_free(hold);
2875296465Sdelphij    if (!pinvtm)
2876296465Sdelphij        ASN1_GENERALIZEDTIME_free(comp_time);
2877109998Smarkm
2878296465Sdelphij    return ret;
2879296465Sdelphij}
2880