Update copyright year
[openssl.git] / crypto / x509 / t_x509.c
index 6ef979c4ff67c989037d8429cdc05b32159ef7f4..68b04a565075290e129a394da76c9eb42692b385 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
 #include "crypto/asn1.h"
 #include "crypto/x509.h"
 
+void OSSL_STACK_OF_X509_free(STACK_OF(X509) *certs)
+{
+    sk_X509_pop_free(certs, X509_free);
+}
+
 #ifndef OPENSSL_NO_STDIO
 int X509_print_fp(FILE *fp, X509 *x)
 {
@@ -30,7 +35,7 @@ int X509_print_ex_fp(FILE *fp, X509 *x, unsigned long nmflag,
     int ret;
 
     if ((b = BIO_new(BIO_s_file())) == NULL) {
-        X509err(X509_F_X509_PRINT_EX_FP, ERR_R_BUF_LIB);
+        ERR_raise(ERR_LIB_X509, ERR_R_BUF_LIB);
         return 0;
     }
     BIO_set_fp(b, fp, BIO_NOCLOSE);
@@ -50,9 +55,8 @@ int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags,
 {
     long l;
     int ret = 0, i;
-    char *m = NULL, mlch = ' ';
-    int nmindent = 0;
-    ASN1_INTEGER *bs;
+    char mlch = ' ';
+    int nmindent = 0, printok = 0;
     EVP_PKEY *pkey = NULL;
     const char *neg;
 
@@ -61,8 +65,10 @@ int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags,
         nmindent = 12;
     }
 
-    if (nmflags == X509_FLAG_COMPAT)
+    if (nmflags == X509_FLAG_COMPAT) {
         nmindent = 16;
+        printok = 1;
+    }
 
     if (!(cflag & X509_FLAG_NO_HEADER)) {
         if (BIO_write(bp, "Certificate:\n", 13) <= 0)
@@ -72,7 +78,7 @@ int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags,
     }
     if (!(cflag & X509_FLAG_NO_VERSION)) {
         l = X509_get_version(x);
-        if (l >= 0 && l <= 2) {
+        if (l >= X509_VERSION_1 && l <= X509_VERSION_3) {
             if (BIO_printf(bp, "%8sVersion: %ld (0x%lx)\n", "", l + 1, (unsigned long)l) <= 0)
                 goto err;
         } else {
@@ -81,11 +87,11 @@ int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags,
         }
     }
     if (!(cflag & X509_FLAG_NO_SERIAL)) {
+        const ASN1_INTEGER *bs = X509_get0_serialNumber(x);
 
         if (BIO_write(bp, "        Serial Number:", 22) <= 0)
             goto err;
 
-        bs = X509_get_serialNumber(x);
         if (bs->length <= (int)sizeof(long)) {
                 ERR_set_mark();
                 l = ASN1_INTEGER_get(bs);
@@ -131,7 +137,7 @@ int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags,
         if (BIO_printf(bp, "        Issuer:%c", mlch) <= 0)
             goto err;
         if (X509_NAME_print_ex(bp, X509_get_issuer_name(x), nmindent, nmflags)
-            < 0)
+            < printok)
             goto err;
         if (BIO_write(bp, "\n", 1) <= 0)
             goto err;
@@ -141,11 +147,11 @@ int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags,
             goto err;
         if (BIO_write(bp, "            Not Before: ", 24) <= 0)
             goto err;
-        if (!ASN1_TIME_print(bp, X509_get0_notBefore(x)))
+        if (ossl_asn1_time_print_ex(bp, X509_get0_notBefore(x), ASN1_DTFLGS_RFC822) == 0)
             goto err;
         if (BIO_write(bp, "\n            Not After : ", 25) <= 0)
             goto err;
-        if (!ASN1_TIME_print(bp, X509_get0_notAfter(x)))
+        if (ossl_asn1_time_print_ex(bp, X509_get0_notAfter(x), ASN1_DTFLGS_RFC822) == 0)
             goto err;
         if (BIO_write(bp, "\n", 1) <= 0)
             goto err;
@@ -154,7 +160,7 @@ int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags,
         if (BIO_printf(bp, "        Subject:%c", mlch) <= 0)
             goto err;
         if (X509_NAME_print_ex
-            (bp, X509_get_subject_name(x), nmindent, nmflags) < 0)
+            (bp, X509_get_subject_name(x), nmindent, nmflags) < printok)
             goto err;
         if (BIO_write(bp, "\n", 1) <= 0)
             goto err;
@@ -198,9 +204,10 @@ int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags,
         }
     }
 
-    if (!(cflag & X509_FLAG_NO_EXTENSIONS))
-        X509V3_extensions_print(bp, "X509v3 extensions",
-                                X509_get0_extensions(x), cflag, 8);
+    if (!(cflag & X509_FLAG_NO_EXTENSIONS)
+        && !X509V3_extensions_print(bp, "X509v3 extensions",
+                                    X509_get0_extensions(x), cflag, 8))
+        goto err;
 
     if (!(cflag & X509_FLAG_NO_SIGDUMP)) {
         const X509_ALGOR *sig_alg;
@@ -215,7 +222,6 @@ int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags,
     }
     ret = 1;
  err:
-    OPENSSL_free(m);
     return ret;
 }
 
@@ -228,7 +234,10 @@ int X509_ocspid_print(BIO *bp, X509 *x)
     unsigned char SHA1md[SHA_DIGEST_LENGTH];
     ASN1_BIT_STRING *keybstr;
     const X509_NAME *subj;
+    EVP_MD *md = NULL;
 
+    if (x == NULL || bp == NULL)
+        return 0;
     /*
      * display the hash of the subject as it would appear in OCSP requests
      */
@@ -236,11 +245,16 @@ int X509_ocspid_print(BIO *bp, X509 *x)
         goto err;
     subj = X509_get_subject_name(x);
     derlen = i2d_X509_NAME(subj, NULL);
+    if (derlen <= 0)
+        goto err;
     if ((der = dertmp = OPENSSL_malloc(derlen)) == NULL)
         goto err;
     i2d_X509_NAME(subj, &dertmp);
 
-    if (!EVP_Digest(der, derlen, SHA1md, NULL, EVP_sha1(), NULL))
+    md = EVP_MD_fetch(x->libctx, SN_sha1, x->propq);
+    if (md == NULL)
+        goto err;
+    if (!EVP_Digest(der, derlen, SHA1md, NULL, md, NULL))
         goto err;
     for (i = 0; i < SHA_DIGEST_LENGTH; i++) {
         if (BIO_printf(bp, "%02X", SHA1md[i]) <= 0)
@@ -261,18 +275,19 @@ int X509_ocspid_print(BIO *bp, X509 *x)
         goto err;
 
     if (!EVP_Digest(ASN1_STRING_get0_data(keybstr),
-                    ASN1_STRING_length(keybstr), SHA1md, NULL, EVP_sha1(),
-                    NULL))
+                    ASN1_STRING_length(keybstr), SHA1md, NULL, md, NULL))
         goto err;
     for (i = 0; i < SHA_DIGEST_LENGTH; i++) {
         if (BIO_printf(bp, "%02X", SHA1md[i]) <= 0)
             goto err;
     }
     BIO_printf(bp, "\n");
+    EVP_MD_free(md);
 
     return 1;
  err:
     OPENSSL_free(der);
+    EVP_MD_free(md);
     return 0;
 }
 
@@ -369,9 +384,9 @@ int X509_aux_print(BIO *out, X509 *x, int indent)
         BIO_puts(out, "\n");
     } else
         BIO_printf(out, "%*sNo Rejected Uses.\n", indent, "");
-    alias = X509_alias_get0(x, NULL);
+    alias = X509_alias_get0(x, &i);
     if (alias)
-        BIO_printf(out, "%*sAlias: %s\n", indent, "", alias);
+        BIO_printf(out, "%*sAlias: %.*s\n", indent, "", i, alias);
     keyid = X509_keyid_get0(x, &keyidlen);
     if (keyid) {
         BIO_printf(out, "%*sKey Id: ", indent, "");
@@ -386,7 +401,7 @@ int X509_aux_print(BIO *out, X509 *x, int indent)
  * Helper functions for improving certificate verification error diagnostics
  */
 
-int x509_print_ex_brief(BIO *bio, X509 *cert, unsigned long neg_cflags)
+int ossl_x509_print_ex_brief(BIO *bio, X509 *cert, unsigned long neg_cflags)
 {
     unsigned long flags = ASN1_STRFLGS_RFC2253 | ASN1_STRFLGS_ESC_QUOTE |
         XN_FLAG_SEP_CPLUS_SPC | XN_FLAG_FN_SN;
@@ -413,7 +428,8 @@ int x509_print_ex_brief(BIO *bio, X509 *cert, unsigned long neg_cflags)
     if (X509_cmp_current_time(X509_get0_notAfter(cert)) < 0)
         if (BIO_printf(bio, "        no more valid\n") <= 0)
             return 0;
-    return X509_print_ex(bio, cert, flags, ~(neg_cflags));
+    return X509_print_ex(bio, cert, flags,
+                         ~neg_cflags & ~X509_FLAG_EXTENSIONS_ONLY_KID);
 }
 
 static int print_certs(BIO *bio, const STACK_OF(X509) *certs)
@@ -425,8 +441,15 @@ static int print_certs(BIO *bio, const STACK_OF(X509) *certs)
 
     for (i = 0; i < sk_X509_num(certs); i++) {
         X509 *cert = sk_X509_value(certs, i);
-        if (cert != NULL && !x509_print_ex_brief(bio, cert, 0))
-            return 0;
+
+        if (cert != NULL) {
+            if (!ossl_x509_print_ex_brief(bio, cert, 0))
+                return 0;
+            if (!X509V3_extensions_print(bio, NULL,
+                                         X509_get0_extensions(cert),
+                                         X509_FLAG_EXTENSIONS_ONLY_KID, 8))
+                return 0;
+            }
     }
     return 1;
 }
@@ -437,7 +460,7 @@ static int print_store_certs(BIO *bio, X509_STORE *store)
         STACK_OF(X509) *certs = X509_STORE_get1_all_certs(store);
         int ret = print_certs(bio, certs);
 
-        sk_X509_pop_free(certs, X509_free);
+        OSSL_STACK_OF_X509_free(certs);
         return ret;
     } else {
         return BIO_printf(bio, "    (no trusted store)\n") >= 0;
@@ -449,17 +472,48 @@ int X509_STORE_CTX_print_verify_cb(int ok, X509_STORE_CTX *ctx)
 {
     if (ok == 0 && ctx != NULL) {
         int cert_error = X509_STORE_CTX_get_error(ctx);
-        int depth = X509_STORE_CTX_get_error_depth(ctx);
-        X509 *cert = X509_STORE_CTX_get_current_cert(ctx);
         BIO *bio = BIO_new(BIO_s_mem()); /* may be NULL */
 
-        BIO_printf(bio, "%s at depth=%d error=%d (%s)\n",
+        if (bio == NULL)
+            return 0;
+        BIO_printf(bio, "%s at depth = %d error = %d (%s)\n",
                    X509_STORE_CTX_get0_parent_ctx(ctx) != NULL
-                   ? "CRL path validation" : "certificate verification",
-                   depth, cert_error,
-                   X509_verify_cert_error_string(cert_error));
-        BIO_printf(bio, "failure for:\n");
-        x509_print_ex_brief(bio, cert, X509_FLAG_NO_EXTENSIONS);
+                   ? "CRL path validation"
+                   : "Certificate verification",
+                   X509_STORE_CTX_get_error_depth(ctx),
+                   cert_error, X509_verify_cert_error_string(cert_error));
+        {
+            X509_STORE *ts = X509_STORE_CTX_get0_store(ctx);
+            X509_VERIFY_PARAM *vpm = X509_STORE_get0_param(ts);
+            char *str;
+            int idx = 0;
+
+            switch (cert_error) {
+            case X509_V_ERR_HOSTNAME_MISMATCH:
+                BIO_printf(bio, "Expected hostname(s) = ");
+                while ((str = X509_VERIFY_PARAM_get0_host(vpm, idx++)) != NULL)
+                    BIO_printf(bio, "%s%s", idx == 1 ? "" : ", ", str);
+                BIO_printf(bio, "\n");
+                break;
+            case X509_V_ERR_EMAIL_MISMATCH:
+                str = X509_VERIFY_PARAM_get0_email(vpm);
+                if (str != NULL)
+                    BIO_printf(bio, "Expected email address = %s\n", str);
+                break;
+            case X509_V_ERR_IP_ADDRESS_MISMATCH:
+                str = X509_VERIFY_PARAM_get1_ip_asc(vpm);
+                if (str != NULL)
+                    BIO_printf(bio, "Expected IP address = %s\n", str);
+                OPENSSL_free(str);
+                break;
+            default:
+                break;
+            }
+        }
+
+        BIO_printf(bio, "Failure for:\n");
+        ossl_x509_print_ex_brief(bio, X509_STORE_CTX_get_current_cert(ctx),
+                                 X509_FLAG_NO_EXTENSIONS);
         if (cert_error == X509_V_ERR_CERT_UNTRUSTED
                 || cert_error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
                 || cert_error == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN
@@ -467,21 +521,15 @@ int X509_STORE_CTX_print_verify_cb(int ok, X509_STORE_CTX *ctx)
                 || cert_error == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
                 || cert_error == X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER
                 || cert_error == X509_V_ERR_STORE_LOOKUP) {
-            BIO_printf(bio, "non-trusted certs:\n");
+            BIO_printf(bio, "Non-trusted certs:\n");
             print_certs(bio, X509_STORE_CTX_get0_untrusted(ctx));
-            BIO_printf(bio, "certs in trust store:\n");
+            BIO_printf(bio, "Certs in trust store:\n");
             print_store_certs(bio, X509_STORE_CTX_get0_store(ctx));
         }
-        CMPerr(0, X509_R_CERTIFICATE_VERIFICATION_FAILED);
+        ERR_raise(ERR_LIB_X509, X509_R_CERTIFICATE_VERIFICATION_FAILED);
         ERR_add_error_mem_bio("\n", bio);
         BIO_free(bio);
     }
 
-    /*
-     * TODO we could check policies here too, e.g.:
-     * if (cert_error == X509_V_OK && ok == 2)
-     *     policies_print(NULL, ctx);
-     */
-
     return ok;
 }