Remove the X_OK define, it is unused.
[openssl.git] / apps / ca.c
index 030f8b1d3d6e9bbfd80c700854e862c998c5d366..976f6bb5f00c8416d4a383e00219fb64e72cb2fa 100644 (file)
--- a/apps/ca.c
+++ b/apps/ca.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
 
 #ifndef W_OK
 # ifdef OPENSSL_SYS_VMS
-#  if defined(__DECC)
-#   include <unistd.h>
-#  else
-#   include <unixlib.h>
-#  endif
+#  include <unistd.h>
 # elif !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_WINDOWS)
 #  include <sys/file.h>
 # endif
@@ -42,7 +38,6 @@
 
 #ifndef W_OK
 # define F_OK 0
-# define X_OK 1
 # define W_OK 2
 # define R_OK 4
 #endif
@@ -66,6 +61,7 @@
 #define ENV_NEW_CERTS_DIR       "new_certs_dir"
 #define ENV_CERTIFICATE         "certificate"
 #define ENV_SERIAL              "serial"
+#define ENV_RAND_SERIAL         "rand_serial"
 #define ENV_CRLNUMBER           "crlnumber"
 #define ENV_PRIVATE_KEY         "private_key"
 #define ENV_DEFAULT_DAYS        "default_days"
@@ -157,6 +153,8 @@ typedef enum OPTION_choice {
     OPT_GENCRL, OPT_MSIE_HACK, OPT_CRLDAYS, OPT_CRLHOURS, OPT_CRLSEC,
     OPT_INFILES, OPT_SS_CERT, OPT_SPKAC, OPT_REVOKE, OPT_VALID,
     OPT_EXTENSIONS, OPT_EXTFILE, OPT_STATUS, OPT_UPDATEDB, OPT_CRLEXTS,
+    OPT_RAND_SERIAL,
+    OPT_R_ENUM,
     /* Do not change the order here; see related case statements below */
     OPT_CRL_REASON, OPT_CRL_HOLD, OPT_CRL_COMPROMISE, OPT_CRL_CA_COMPROMISE
 } OPTION_CHOICE;
@@ -170,6 +168,8 @@ const OPTIONS ca_options[] = {
     {"utf8", OPT_UTF8, '-', "Input characters are UTF8 (default ASCII)"},
     {"create_serial", OPT_CREATE_SERIAL, '-',
      "If reading serial fails, create a new random serial"},
+    {"rand_serial", OPT_RAND_SERIAL, '-',
+     "Always create a random serial; do not store it"},
     {"multivalue-rdn", OPT_MULTIVALUE_RDN, '-',
      "Enable support for multivalued RDNs"},
     {"startdate", OPT_STARTDATE, 's', "Cert notBefore, YYMMDDHHMMSSZ"},
@@ -221,6 +221,7 @@ const OPTIONS ca_options[] = {
      "sets compromise time to val and the revocation reason to keyCompromise"},
     {"crl_CA_compromise", OPT_CRL_CA_COMPROMISE, 's',
      "sets compromise time to val and the revocation reason to CACompromise"},
+    OPT_R_OPTIONS,
 #ifndef OPENSSL_NO_ENGINE
     {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
 #endif
@@ -251,7 +252,7 @@ int ca_main(int argc, char **argv)
     char *outdir = NULL, *outfile = NULL, *rev_arg = NULL, *ser_status = NULL;
     const char *serialfile = NULL, *subj = NULL;
     char *prog, *startdate = NULL, *enddate = NULL;
-    char *dbfile = NULL, *f, *randfile = NULL;
+    char *dbfile = NULL, *f;
     char new_cert[CERT_MAX + 1];
     char tmp[10 + 1] = "\0";
     char *const *pp;
@@ -260,9 +261,9 @@ int ca_main(int argc, char **argv)
     int batch = 0, default_op = 1, doupdatedb = 0, ext_copy = EXT_COPY_NONE;
     int keyformat = FORMAT_PEM, multirdn = 0, notext = 0, output_der = 0;
     int ret = 1, email_dn = 1, req = 0, verbose = 0, gencrl = 0, dorevoke = 0;
-    int i, j, selfsign = 0;
+    int rand_ser = 0, i, j, selfsign = 0;
     long crldays = 0, crlhours = 0, crlsec = 0, days = 0;
-    unsigned long chtype = MBSTRING_ASC, nameopt = 0, certopt = 0;
+    unsigned long chtype = MBSTRING_ASC, certopt = 0;
     X509 *x509 = NULL, *x509p = NULL, *x = NULL;
     REVINFO_TYPE rev_type = REV_NONE;
     X509_REVOKED *r = NULL;
@@ -305,6 +306,9 @@ opthelp:
         case OPT_UTF8:
             chtype = MBSTRING_UTF8;
             break;
+        case OPT_RAND_SERIAL:
+            rand_ser = 1;
+            break;
         case OPT_CREATE_SERIAL:
             create_ser = 1;
             break;
@@ -336,6 +340,10 @@ opthelp:
         case OPT_PASSIN:
             passinarg = opt_arg();
             break;
+        case OPT_R_CASES:
+            if (!opt_rand(o))
+                goto end;
+            break;
         case OPT_KEY:
             key = opt_arg();
             break;
@@ -469,23 +477,20 @@ end_of_options:
         }
     }
 
-    randfile = NCONF_get_string(conf, BASE_SECTION, "RANDFILE");
-    if (randfile == NULL)
-        ERR_clear_error();
-    app_RAND_load_file(randfile, 0);
+    app_RAND_load_conf(conf, BASE_SECTION);
 
     f = NCONF_get_string(conf, section, STRING_MASK);
-    if (!f)
+    if (f == NULL)
         ERR_clear_error();
 
-    if (f && !ASN1_STRING_set_default_mask_asc(f)) {
+    if (f != NULL && !ASN1_STRING_set_default_mask_asc(f)) {
         BIO_printf(bio_err, "Invalid global string mask setting %s\n", f);
         goto end;
     }
 
     if (chtype != MBSTRING_UTF8) {
         f = NCONF_get_string(conf, section, UTF8_IN);
-        if (!f)
+        if (f == NULL)
             ERR_clear_error();
         else if (strcmp(f, "yes") == 0)
             chtype = MBSTRING_UTF8;
@@ -493,9 +498,9 @@ end_of_options:
 
     db_attr.unique_subject = 1;
     p = NCONF_get_string(conf, section, ENV_UNIQUE_SUBJECT);
-    if (p) {
+    if (p != NULL)
         db_attr.unique_subject = parse_yesno(p, 1);
-    else
+    else
         ERR_clear_error();
 
     /*****************************************************************/
@@ -524,7 +529,7 @@ end_of_options:
         && (keyfile = lookup_conf(conf, section, ENV_PRIVATE_KEY)) == NULL)
         goto end;
 
-    if (!key) {
+    if (key == NULL) {
         free_key = 1;
         if (!app_passwd(passinarg, NULL, &key, NULL)) {
             BIO_printf(bio_err, "Error getting password\n");
@@ -532,12 +537,11 @@ end_of_options:
         }
     }
     pkey = load_key(keyfile, keyformat, 0, key, e, "CA private key");
-    if (key)
+    if (key != NULL)
         OPENSSL_cleanse(key, strlen(key));
-    if (pkey == NULL) {
+    if (pkey == NULL)
         /* load_key() has already printed an appropriate message */
         goto end;
-    }
 
     /*****************************************************************/
     /* we need a certificate */
@@ -572,37 +576,36 @@ end_of_options:
 
     f = NCONF_get_string(conf, section, ENV_NAMEOPT);
 
-    if (f) {
-        if (!set_name_ex(&nameopt, f)) {
+    if (f != NULL) {
+        if (!set_nameopt(f)) {
             BIO_printf(bio_err, "Invalid name options: \"%s\"\n", f);
             goto end;
         }
         default_op = 0;
-    } else {
-        nameopt = XN_FLAG_ONELINE;
-        ERR_clear_error();
     }
 
     f = NCONF_get_string(conf, section, ENV_CERTOPT);
 
-    if (f) {
+    if (f != NULL) {
         if (!set_cert_ex(&certopt, f)) {
             BIO_printf(bio_err, "Invalid certificate options: \"%s\"\n", f);
             goto end;
         }
         default_op = 0;
-    } else
+    } else {
         ERR_clear_error();
+    }
 
     f = NCONF_get_string(conf, section, ENV_EXTCOPY);
 
-    if (f) {
+    if (f != NULL) {
         if (!set_ext_copy(&ext_copy, f)) {
             BIO_printf(bio_err, "Invalid extension copy option: \"%s\"\n", f);
             goto end;
         }
-    } else
+    } else {
         ERR_clear_error();
+    }
 
     /*****************************************************************/
     /* lookup where to write new certificates */
@@ -777,21 +780,25 @@ end_of_options:
         if (verbose)
             BIO_printf(bio_err, "policy is %s\n", policy);
 
-        serialfile = lookup_conf(conf, section, ENV_SERIAL);
-        if (serialfile == NULL)
-            goto end;
+        if (NCONF_get_string(conf, section, ENV_RAND_SERIAL) != NULL) {
+            rand_ser = 1;
+        } else {
+            serialfile = lookup_conf(conf, section, ENV_SERIAL);
+            if (serialfile == NULL)
+                goto end;
+        }
 
-        if (!extconf) {
+        if (extconf == NULL) {
             /*
              * no '-extfile' option, so we look for extensions in the main
              * configuration file
              */
-            if (!extensions) {
+            if (extensions == NULL) {
                 extensions = NCONF_get_string(conf, section, ENV_EXTENSIONS);
-                if (!extensions)
+                if (extensions == NULL)
                     ERR_clear_error();
             }
-            if (extensions) {
+            if (extensions != NULL) {
                 /* Check syntax of file */
                 X509V3_CTX ctx;
                 X509V3_set_ctx_test(&ctx);
@@ -812,7 +819,7 @@ end_of_options:
             if (startdate == NULL)
                 ERR_clear_error();
         }
-        if (startdate && !ASN1_TIME_set_string(NULL, startdate)) {
+        if (startdate != NULL && !ASN1_TIME_set_string_X509(NULL, startdate)) {
             BIO_printf(bio_err,
                        "start date is invalid, it should be YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ\n");
             goto end;
@@ -825,7 +832,7 @@ end_of_options:
             if (enddate == NULL)
                 ERR_clear_error();
         }
-        if (enddate && !ASN1_TIME_set_string(NULL, enddate)) {
+        if (enddate != NULL && !ASN1_TIME_set_string_X509(NULL, enddate)) {
             BIO_printf(bio_err,
                        "end date is invalid, it should be YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ\n");
             goto end;
@@ -835,24 +842,31 @@ end_of_options:
             if (!NCONF_get_number(conf, section, ENV_DEFAULT_DAYS, &days))
                 days = 0;
         }
-        if (!enddate && (days == 0)) {
+        if (enddate == NULL && (days == 0)) {
             BIO_printf(bio_err,
                        "cannot lookup how many days to certify for\n");
             goto end;
         }
 
-        if ((serial = load_serial(serialfile, create_ser, NULL)) == NULL) {
-            BIO_printf(bio_err, "error while loading serial number\n");
-            goto end;
-        }
-        if (verbose) {
-            if (BN_is_zero(serial))
-                BIO_printf(bio_err, "next serial number is 00\n");
-            else {
-                if ((f = BN_bn2hex(serial)) == NULL)
-                    goto end;
-                BIO_printf(bio_err, "next serial number is %s\n", f);
-                OPENSSL_free(f);
+        if (rand_ser) {
+            if ((serial = BN_new()) == NULL || !rand_serial(serial, NULL)) {
+                BIO_printf(bio_err, "error generating serial number\n");
+                goto end;
+            }
+        } else {
+            if ((serial = load_serial(serialfile, create_ser, NULL)) == NULL) {
+                BIO_printf(bio_err, "error while loading serial number\n");
+                goto end;
+            }
+            if (verbose) {
+                if (BN_is_zero(serial)) {
+                    BIO_printf(bio_err, "next serial number is 00\n");
+                } else {
+                    if ((f = BN_bn2hex(serial)) == NULL)
+                        goto end;
+                    BIO_printf(bio_err, "next serial number is %s\n", f);
+                    OPENSSL_free(f);
+                }
             }
         }
 
@@ -870,7 +884,7 @@ end_of_options:
             j = certify_spkac(&x, spkac_file, pkey, x509, dgst, sigopts,
                               attribs, db, serial, subj, chtype, multirdn,
                               email_dn, startdate, enddate, days, extensions,
-                              conf, verbose, certopt, nameopt, default_op,
+                              conf, verbose, certopt, get_nameopt(), default_op,
                               ext_copy);
             if (j < 0)
                 goto end;
@@ -895,7 +909,7 @@ end_of_options:
                              attribs,
                              db, serial, subj, chtype, multirdn, email_dn,
                              startdate, enddate, days, batch, extensions,
-                             conf, verbose, certopt, nameopt, default_op,
+                             conf, verbose, certopt, get_nameopt(), default_op,
                              ext_copy);
             if (j < 0)
                 goto end;
@@ -915,7 +929,7 @@ end_of_options:
             j = certify(&x, infile, pkey, x509p, dgst, sigopts, attribs, db,
                         serial, subj, chtype, multirdn, email_dn, startdate,
                         enddate, days, batch, extensions, conf, verbose,
-                        certopt, nameopt, default_op, ext_copy, selfsign);
+                        certopt, get_nameopt(), default_op, ext_copy, selfsign);
             if (j < 0)
                 goto end;
             if (j > 0) {
@@ -934,7 +948,7 @@ end_of_options:
             j = certify(&x, argv[i], pkey, x509p, dgst, sigopts, attribs, db,
                         serial, subj, chtype, multirdn, email_dn, startdate,
                         enddate, days, batch, extensions, conf, verbose,
-                        certopt, nameopt, default_op, ext_copy, selfsign);
+                        certopt, get_nameopt(), default_op, ext_copy, selfsign);
             if (j < 0)
                 goto end;
             if (j > 0) {
@@ -976,7 +990,8 @@ end_of_options:
             BIO_printf(bio_err, "Write out database with %d new entries\n",
                        sk_X509_num(cert_sk));
 
-            if (!save_serial(serialfile, "new", serial, NULL))
+            if (!rand_ser
+                    && !save_serial(serialfile, "new", serial, NULL))
                 goto end;
 
             if (!save_index(dbfile, "new", db))
@@ -1052,12 +1067,12 @@ end_of_options:
     /*****************************************************************/
     if (gencrl) {
         int crl_v2 = 0;
-        if (!crl_ext) {
+        if (crl_ext == NULL) {
             crl_ext = NCONF_get_string(conf, section, ENV_CRLEXT);
-            if (!crl_ext)
+            if (crl_ext == NULL)
                 ERR_clear_error();
         }
-        if (crl_ext) {
+        if (crl_ext != NULL) {
             /* Check syntax of file */
             X509V3_CTX ctx;
             X509V3_set_ctx_test(&ctx);
@@ -1148,12 +1163,12 @@ end_of_options:
 
         /* Add any extensions asked for */
 
-        if (crl_ext || crlnumberfile != NULL) {
+        if (crl_ext != NULL || crlnumberfile != NULL) {
             X509V3_CTX crlctx;
             X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0);
             X509V3_set_nconf(&crlctx, conf);
 
-            if (crl_ext)
+            if (crl_ext != NULL)
                 if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx, crl_ext, crl))
                     goto end;
             if (crlnumberfile != NULL) {
@@ -1167,14 +1182,15 @@ end_of_options:
                     goto end;
             }
         }
-        if (crl_ext || crl_v2) {
+        if (crl_ext != NULL || crl_v2) {
             if (!X509_CRL_set_version(crl, 1))
                 goto end;       /* version 2 CRL */
         }
 
         /* we have a CRL number that need updating */
         if (crlnumberfile != NULL)
-            if (!save_serial(crlnumberfile, "new", crlnumber, NULL))
+            if (!rand_ser
+                    && !save_serial(crlnumberfile, "new", crlnumber, NULL))
                 goto end;
 
         BN_free(crlnumber);
@@ -1216,17 +1232,16 @@ end_of_options:
             BIO_printf(bio_err, "Data Base Updated\n");
         }
     }
-    /*****************************************************************/
     ret = 0;
+
  end:
+    if (ret)
+        ERR_print_errors(bio_err);
     BIO_free_all(Sout);
     BIO_free_all(out);
     BIO_free_all(in);
     sk_X509_pop_free(cert_sk, X509_free);
 
-    if (ret)
-        ERR_print_errors(bio_err);
-    app_RAND_write_file(randfile);
     if (free_key)
         OPENSSL_free(key);
     BN_free(serial);
@@ -1276,7 +1291,7 @@ static int certify(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509,
         goto end;
     }
     if (verbose)
-        X509_REQ_print(bio_err, req);
+        X509_REQ_print_ex(bio_err, req, nameopt, X509_FLAG_COMPAT);
 
     BIO_printf(bio_err, "Check that the request matches the signature\n");
 
@@ -1304,8 +1319,9 @@ static int certify(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509,
                    "Signature did not match the certificate request\n");
         ERR_print_errors(bio_err);
         goto end;
-    } else
+    } else {
         BIO_printf(bio_err, "Signature ok\n");
+    }
 
     ok = do_body(xret, pkey, x509, dgst, sigopts, policy, db, serial, subj,
                  chtype, multirdn, email_dn, startdate, enddate, days, batch,
@@ -1353,8 +1369,9 @@ static int certify_cert(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x
         ok = 0;
         BIO_printf(bio_err, "Signature did not match the certificate\n");
         goto end;
-    } else
+    } else {
         BIO_printf(bio_err, "Signature ok\n");
+    }
 
     if ((rreq = X509_to_X509_REQ(req, NULL, NULL)) == NULL)
         goto end;
@@ -1509,8 +1526,9 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
                                "The %s field needed to be supplied and was missing\n",
                                cv->name);
                     goto end;
-                } else
+                } else {
                     push = tne;
+                }
             } else if (strcmp(cv->value, "match") == 0) {
                 int last2;
 
@@ -1580,14 +1598,14 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
         BIO_printf(bio_err,
                    "The subject name appears to be ok, checking data base for clashes\n");
 
-    /* 
+    /*
      * Build the correct Subject if no e-mail is wanted in the subject.
      * And add it later on because of the method extensions are added (altName)
      */
 
-    if (email_dn)
+    if (email_dn) {
         dn_subject = subject;
-    else {
+    else {
         X509_NAME_ENTRY *tmpne;
         /*
          * Its best to dup the subject DN and then delete any email addresses
@@ -1725,7 +1743,7 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
         else
             X509V3_set_ctx(&ctx, x509, ret, req, NULL, 0);
 
-        if (extconf) {
+        if (extconf != NULL) {
             if (verbose)
                 BIO_printf(bio_err, "Extra configuration file found\n");
 
@@ -1836,10 +1854,8 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
     }
 
     irow = app_malloc(sizeof(*irow) * (DB_NUMBER + 1), "row space");
-    for (i = 0; i < DB_NUMBER; i++) {
+    for (i = 0; i < DB_NUMBER; i++)
         irow[i] = row[i];
-        row[i] = NULL;
-    }
     irow[DB_NUMBER] = NULL;
 
     if (!TXT_DB_insert(db->db, irow)) {
@@ -1847,10 +1863,14 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509,
         BIO_printf(bio_err, "TXT_DB error number %ld\n", db->db->error);
         goto end;
     }
+    irow = NULL;
     ok = 1;
  end:
-    for (i = 0; i < DB_NUMBER; i++)
-        OPENSSL_free(row[i]);
+    if (irow != NULL) {
+        for (i = 0; i < DB_NUMBER; i++)
+            OPENSSL_free(row[i]);
+        OPENSSL_free(irow);
+    }
 
     X509_NAME_free(CAname);
     X509_NAME_free(subject);
@@ -2060,19 +2080,26 @@ static int do_revoke(X509 *x509, CA_DB *db, REVINFO_TYPE rev_type,
         row[DB_rev_date] = NULL;
         row[DB_file] = OPENSSL_strdup("unknown");
 
+        if (row[DB_type] == NULL || row[DB_file] == NULL) {
+            BIO_printf(bio_err, "Memory allocation failure\n");
+            goto end;
+        }
+
         irow = app_malloc(sizeof(*irow) * (DB_NUMBER + 1), "row ptr");
-        for (i = 0; i < DB_NUMBER; i++) {
+        for (i = 0; i < DB_NUMBER; i++)
             irow[i] = row[i];
-            row[i] = NULL;
-        }
         irow[DB_NUMBER] = NULL;
 
         if (!TXT_DB_insert(db->db, irow)) {
             BIO_printf(bio_err, "failed to update database\n");
             BIO_printf(bio_err, "TXT_DB error number %ld\n", db->db->error);
+            OPENSSL_free(irow);
             goto end;
         }
 
+        for (i = 0; i < DB_NUMBER; i++)
+            row[i] = NULL;
+
         /* Revoke Certificate */
         if (rev_type == REV_VALID)
             ok = 1;
@@ -2106,9 +2133,8 @@ static int do_revoke(X509 *x509, CA_DB *db, REVINFO_TYPE rev_type,
     }
     ok = 1;
  end:
-    for (i = 0; i < DB_NUMBER; i++) {
+    for (i = 0; i < DB_NUMBER; i++)
         OPENSSL_free(row[i]);
-    }
     return (ok);
 }
 
@@ -2128,7 +2154,7 @@ static int get_certificate_status(const char *serial, CA_DB *db)
     if (serial_len % 2) {
         /*
          * Set the first char to 0
-         */ ;
+         */
         row[DB_serial][0] = '0';
 
         /* Copy String from serial to row[DB_serial] */
@@ -2141,8 +2167,7 @@ static int get_certificate_status(const char *serial, CA_DB *db)
     }
 
     /* Make it Upper Case */
-    for (i = 0; row[DB_serial][i] != '\0'; i++)
-        row[DB_serial][i] = toupper((unsigned char)row[DB_serial][i]);
+    make_uppercase(row[DB_serial]);
 
     ok = 1;
 
@@ -2505,9 +2530,9 @@ int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold,
             goto end;
         }
 
-        if (reason_code == 7)
+        if (reason_code == 7) {
             reason_code = OCSP_REVOKED_STATUS_REMOVEFROMCRL;
-        else if (reason_code == 8) { /* Hold instruction */
+        else if (reason_code == 8) { /* Hold instruction */
             if (!arg_str) {
                 BIO_printf(bio_err, "missing hold instruction\n");
                 goto end;