add OSSL_STACK_OF_X509_free() for commonly used pattern
[openssl.git] / apps / lib / apps.c
index 43c01401e8d75763a3197c98dae328b99b8b24f8..88c4f7b97ae23e58e12610d7942710e65b4321b4 100644 (file)
@@ -197,7 +197,7 @@ int set_nameopt(const char *arg)
 
 unsigned long get_nameopt(void)
 {
-    return (nmflag_set) ? nmflag : XN_FLAG_ONELINE;
+    return (nmflag_set) ? nmflag : XN_FLAG_SEP_CPLUS_SPC | ASN1_STRFLGS_UTF8_CONVERT;
 }
 
 void dump_cert_text(BIO *out, X509 *x)
@@ -260,21 +260,21 @@ static char *app_get_pass(const char *arg, int keepbio)
     int i;
 
     /* PASS_SOURCE_SIZE_MAX = max number of chars before ':' in below strings */
-    if (strncmp(arg, "pass:", 5) == 0)
-        return OPENSSL_strdup(arg + 5);
-    if (strncmp(arg, "env:", 4) == 0) {
-        tmp = getenv(arg + 4);
+    if (CHECK_AND_SKIP_PREFIX(arg, "pass:"))
+        return OPENSSL_strdup(arg);
+    if (CHECK_AND_SKIP_PREFIX(arg, "env:")) {
+        tmp = getenv(arg);
         if (tmp == NULL) {
-            BIO_printf(bio_err, "No environment variable %s\n", arg + 4);
+            BIO_printf(bio_err, "No environment variable %s\n", arg);
             return NULL;
         }
         return OPENSSL_strdup(tmp);
     }
     if (!keepbio || pwdbio == NULL) {
-        if (strncmp(arg, "file:", 5) == 0) {
-            pwdbio = BIO_new_file(arg + 5, "r");
+        if (CHECK_AND_SKIP_PREFIX(arg, "file:")) {
+            pwdbio = BIO_new_file(arg, "r");
             if (pwdbio == NULL) {
-                BIO_printf(bio_err, "Can't open file %s\n", arg + 5);
+                BIO_printf(bio_err, "Can't open file %s\n", arg);
                 return NULL;
             }
 #if !defined(_WIN32)
@@ -286,13 +286,13 @@ static char *app_get_pass(const char *arg, int keepbio)
              * on real Windows descriptors, such as those obtained
              * with CreateFile.
              */
-        } else if (strncmp(arg, "fd:", 3) == 0) {
+        } else if (CHECK_AND_SKIP_PREFIX(arg, "fd:")) {
             BIO *btmp;
-            i = atoi(arg + 3);
+            i = atoi(arg);
             if (i >= 0)
                 pwdbio = BIO_new_fd(i, BIO_NOCLOSE);
             if ((i < 0) || !pwdbio) {
-                BIO_printf(bio_err, "Can't access file descriptor %s\n", arg + 3);
+                BIO_printf(bio_err, "Can't access file descriptor %s\n", arg);
                 return NULL;
             }
             /*
@@ -450,10 +450,8 @@ CONF *app_load_config_modules(const char *configfile)
     return conf;
 }
 
-#define IS_HTTP(uri) ((uri) != NULL \
-        && strncmp(uri, OSSL_HTTP_PREFIX, strlen(OSSL_HTTP_PREFIX)) == 0)
-#define IS_HTTPS(uri) ((uri) != NULL \
-        && strncmp(uri, OSSL_HTTPS_PREFIX, strlen(OSSL_HTTPS_PREFIX)) == 0)
+#define IS_HTTP(uri) ((uri) != NULL  && HAS_PREFIX(uri, OSSL_HTTP_PREFIX))
+#define IS_HTTPS(uri) ((uri) != NULL && HAS_PREFIX(uri, OSSL_HTTPS_PREFIX))
 
 X509 *load_cert_pass(const char *uri, int format, int maybe_stdin,
                      const char *pass, const char *desc)
@@ -682,8 +680,8 @@ int load_cert_certs(const char *uri,
     int ret = 0;
     char *pass_string;
 
-    if (exclude_http && (strncasecmp(uri, "http://", 7) == 0
-                         || strncasecmp(uri, "https://", 8) == 0)) {
+    if (exclude_http && (HAS_CASE_PREFIX(uri, "http://")
+                         || HAS_CASE_PREFIX(uri, "https://"))) {
         BIO_printf(bio_err, "error: HTTP retrieval not allowed for %s\n", desc);
         return ret;
     }
@@ -698,7 +696,7 @@ int load_cert_certs(const char *uri,
             warn_cert(uri, *pcert, 0, vpm);
         warn_certs(uri, *pcerts, 1, vpm);
     } else {
-        sk_X509_pop_free(*pcerts, X509_free);
+        OSSL_STACK_OF_X509_free(*pcerts);
         *pcerts = NULL;
     }
     return ret;
@@ -723,7 +721,7 @@ STACK_OF(X509) *load_certs_multifile(char *files, const char *pass,
         if (!X509_add_certs(result, certs,
                             X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP))
             goto oom;
-        sk_X509_pop_free(certs, X509_free);
+        OSSL_STACK_OF_X509_free(certs);
         certs = NULL;
         files = next;
     }
@@ -732,8 +730,8 @@ STACK_OF(X509) *load_certs_multifile(char *files, const char *pass,
  oom:
     BIO_printf(bio_err, "out of memory\n");
  err:
-    sk_X509_pop_free(certs, X509_free);
-    sk_X509_pop_free(result, X509_free);
+    OSSL_STACK_OF_X509_free(certs);
+    OSSL_STACK_OF_X509_free(result);
     return NULL;
 }
 
@@ -774,7 +772,7 @@ X509_STORE *load_certstore(char *input, const char *pass, const char *desc,
             return NULL;
         }
         ok = (store = sk_X509_to_store(store, certs)) != NULL;
-        sk_X509_pop_free(certs, X509_free);
+        OSSL_STACK_OF_X509_free(certs);
         certs = NULL;
         if (!ok)
             return NULL;
@@ -796,7 +794,7 @@ int load_certs(const char *uri, int maybe_stdin, STACK_OF(X509) **certs,
                                   NULL, NULL, certs, NULL, NULL);
 
     if (!ret && was_NULL) {
-        sk_X509_pop_free(*certs, X509_free);
+        OSSL_STACK_OF_X509_free(*certs);
         *certs = NULL;
     }
     return ret;
@@ -823,7 +821,7 @@ int load_crls(const char *uri, STACK_OF(X509_CRL) **crls,
 
 static const char *format2string(int format)
 {
-    switch(format) {
+    switch (format) {
     case FORMAT_PEM:
         return "PEM";
     case FORMAT_ASN1:
@@ -1942,7 +1940,7 @@ X509_NAME *parse_name(const char *cp, int chtype, int canmulti,
             ERR_print_errors(bio_err);
             BIO_printf(bio_err,
                        "%s: Error adding %s name attribute \"/%s=%s\"\n",
-                       opt_getprog(), desc, typestr ,valstr);
+                       opt_getprog(), desc, typestrvalstr);
             goto err;
         }
     }
@@ -2106,29 +2104,43 @@ unsigned char *next_protos_parse(size_t *outlen, const char *in)
     return out;
 }
 
-void print_cert_checks(BIO *bio, X509 *x,
+int check_cert_attributes(BIO *bio, X509 *x,
                        const char *checkhost,
-                       const char *checkemail, const char *checkip)
+                       const char *checkemail, const char *checkip, int print)
 {
+    int valid_host = 0;
+    int valid_mail = 0;
+    int valid_ip = 0;
+    int ret = 1;
+
     if (x == NULL)
-        return;
-    if (checkhost) {
-        BIO_printf(bio, "Hostname %s does%s match certificate\n",
-                   checkhost,
-                   X509_check_host(x, checkhost, 0, 0, NULL) == 1
-                       ? "" : " NOT");
+        return 0;
+
+    if (checkhost != NULL) {
+        valid_host = X509_check_host(x, checkhost, 0, 0, NULL);
+        if (print)
+            BIO_printf(bio, "Hostname %s does%s match certificate\n",
+                       checkhost, valid_host == 1 ? "" : " NOT");
+        ret = ret && valid_host;
     }
 
-    if (checkemail) {
-        BIO_printf(bio, "Email %s does%s match certificate\n",
-                   checkemail, X509_check_email(x, checkemail, 0, 0)
-                   ? "" : " NOT");
+    if (checkemail != NULL) {
+        valid_mail = X509_check_email(x, checkemail, 0, 0);
+        if (print)
+            BIO_printf(bio, "Email %s does%s match certificate\n",
+                       checkemail, valid_mail ? "" : " NOT");
+        ret = ret && valid_mail;
     }
 
-    if (checkip) {
-        BIO_printf(bio, "IP %s does%s match certificate\n",
-                   checkip, X509_check_ip_asc(x, checkip, 0) ? "" : " NOT");
+    if (checkip != NULL) {
+        valid_ip   =  X509_check_ip_asc(x, checkip, 0);
+        if (print)
+            BIO_printf(bio, "IP %s does%s match certificate\n",
+                       checkip,  valid_ip ? "" : " NOT");
+        ret = ret && valid_ip;
     }
+
+    return ret;
 }
 
 static int do_pkey_ctx_init(EVP_PKEY_CTX *pkctx, STACK_OF(OPENSSL_STRING) *opts)
@@ -2224,8 +2236,8 @@ static int adapt_keyid_ext(X509 *cert, X509V3_CTX *ext_ctx,
     idx = X509v3_get_ext_by_OBJ(exts, X509_EXTENSION_get_object(new_ext), -1);
     if (idx >= 0) {
         X509_EXTENSION *found_ext = X509v3_get_ext(exts, idx);
-        ASN1_OCTET_STRING *data = X509_EXTENSION_get_data(found_ext);
-        int disabled = ASN1_STRING_length(data) <= 2; /* config said "none" */
+        ASN1_OCTET_STRING *encoded = X509_EXTENSION_get_data(found_ext);
+        int disabled = ASN1_STRING_length(encoded) <= 2; /* indicating "none" */
 
         if (disabled) {
             X509_delete_ext(cert, idx);
@@ -2239,6 +2251,16 @@ static int adapt_keyid_ext(X509 *cert, X509V3_CTX *ext_ctx,
     return rv;
 }
 
+int cert_matches_key(const X509 *cert, const EVP_PKEY *pkey)
+{
+    int match;
+
+    ERR_set_mark();
+    match = X509_check_private_key(cert, pkey);
+    ERR_pop_to_mark();
+    return match;
+}
+
 /* Ensure RFC 5280 compliance, adapt keyIDs as needed, and sign the cert info */
 int do_X509_sign(X509 *cert, EVP_PKEY *pkey, const char *md,
                  STACK_OF(OPENSSL_STRING) *sigopts, X509V3_CTX *ext_ctx)
@@ -2254,16 +2276,14 @@ int do_X509_sign(X509 *cert, EVP_PKEY *pkey, const char *md,
             goto end;
 
         /*
-         * Add default SKID before such that default AKID can make use of it
+         * Add default SKID before AKID such that AKID can make use of it
          * in case the certificate is self-signed
          */
         /* Prevent X509_V_ERR_MISSING_SUBJECT_KEY_IDENTIFIER */
         if (!adapt_keyid_ext(cert, ext_ctx, "subjectKeyIdentifier", "hash", 1))
             goto end;
         /* Prevent X509_V_ERR_MISSING_AUTHORITY_KEY_IDENTIFIER */
-        ERR_set_mark();
-        self_sign = X509_check_private_key(cert, pkey);
-        ERR_pop_to_mark();
+        self_sign = cert_matches_key(cert, pkey);
         if (!adapt_keyid_ext(cert, ext_ctx, "authorityKeyIdentifier",
                              "keyid, issuer", !self_sign))
             goto end;
@@ -2302,23 +2322,35 @@ int do_X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const char *md,
     return rv;
 }
 
+/*
+ * do_X509_verify returns 1 if the signature is valid,
+ * 0 if the signature check fails, or -1 if error occurs.
+ */
 int do_X509_verify(X509 *x, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *vfyopts)
 {
     int rv = 0;
 
     if (do_x509_init(x, vfyopts) > 0)
-        rv = (X509_verify(x, pkey) > 0);
+        rv = X509_verify(x, pkey);
+    else
+        rv = -1;
     return rv;
 }
 
+/*
+ * do_X509_REQ_verify returns 1 if the signature is valid,
+ * 0 if the signature check fails, or -1 if error occurs.
+ */
 int do_X509_REQ_verify(X509_REQ *x, EVP_PKEY *pkey,
                        STACK_OF(OPENSSL_STRING) *vfyopts)
 {
     int rv = 0;
 
     if (do_x509_req_init(x, vfyopts) > 0)
-        rv = (X509_REQ_verify_ex(x, pkey,
-                                 app_get0_libctx(), app_get0_propq()) > 0);
+        rv = X509_REQ_verify_ex(x, pkey,
+                                 app_get0_libctx(), app_get0_propq());
+    else
+        rv = -1;
     return rv;
 }
 
@@ -2845,9 +2877,9 @@ int raw_write_stdout(const void *buf, int siz)
 #   include <floss.h(floss_write)>
 #  endif
 # endif
-int raw_write_stdout(const void *buf,int siz)
+int raw_write_stdout(const void *buf, int siz)
 {
-       return write(fileno(stdout),(void*)buf,siz);
+       return write(fileno(stdout), (void*)buf, siz);
 }
 #else
 # if defined(__TANDEM)