Strengthen X509_STORE_CTX_print_verify_cb() to print expected host etc.
authorDr. David von Oheimb <David.von.Oheimb@siemens.com>
Thu, 30 Apr 2020 17:31:07 +0000 (19:31 +0200)
committerDr. David von Oheimb <David.von.Oheimb@siemens.com>
Tue, 5 May 2020 08:27:28 +0000 (10:27 +0200)
Add X509_VERIFY_PARAM_get0_host(), X509_VERIFY_PARAM_get0_email(),
and X509_VERIFY_PARAM_get1_ip_asc() to support this,
as well as the internal helper function ipaddr_to_asc(), which
is used also for simplifying other IP address output functions.

Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: David von Oheimb <david.von.oheimb@siemens.com>
(Merged from https://github.com/openssl/openssl/pull/11693)

crypto/x509/t_x509.c
crypto/x509/v3_addr.c
crypto/x509/v3_alt.c
crypto/x509/v3_ncons.c
crypto/x509/v3_utl.c
crypto/x509/x509_vpm.c
doc/man3/X509_VERIFY_PARAM_set_flags.pod
include/internal/cryptlib.h
include/openssl/x509_vfy.h
util/libcrypto.num

index e3c21b0..75d688c 100644 (file)
@@ -452,17 +452,46 @@ 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",
+        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");
+        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
@@ -470,9 +499,9 @@ 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));
         }
         X509err(0, X509_R_CERTIFICATE_VERIFICATION_FAILED);
index 51f5cd8..943423f 100644 (file)
@@ -144,6 +144,7 @@ static int i2r_address(BIO *out,
             return 0;
         BIO_printf(out, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
         break;
+        /* TODO possibly combine with ipaddr_to_asc() */
     case IANA_AFI_IPV6:
         if (!addr_expand(addr, bs, 16, fill))
             return 0;
index 98ff0bc..45f7bac 100644 (file)
@@ -82,10 +82,8 @@ STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method,
                                        GENERAL_NAME *gen,
                                        STACK_OF(CONF_VALUE) *ret)
 {
-    unsigned char *p;
     char othername[300];
-    char oline[256], htmp[5];
-    int i;
+    char oline[256], *tmp;
 
     switch (gen->type) {
     case GEN_OTHERNAME:
@@ -183,26 +181,10 @@ STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method,
         break;
 
     case GEN_IPADD:
-        p = gen->d.ip->data;
-        if (gen->d.ip->length == 4)
-            BIO_snprintf(oline, sizeof(oline), "%d.%d.%d.%d",
-                         p[0], p[1], p[2], p[3]);
-        else if (gen->d.ip->length == 16) {
-            oline[0] = 0;
-            for (i = 0; i < 8; i++) {
-                BIO_snprintf(htmp, sizeof(htmp), "%X", p[0] << 8 | p[1]);
-                p += 2;
-                strcat(oline, htmp);
-                if (i != 7)
-                    strcat(oline, ":");
-            }
-        } else {
-            if (!X509V3_add_value("IP Address", "<invalid>", &ret))
-                return NULL;
-            break;
-        }
-        if (!X509V3_add_value("IP Address", oline, &ret))
-            return NULL;
+        tmp = ipaddr_to_asc(gen->d.ip->data, gen->d.ip->length);
+        if (tmp == NULL || !X509V3_add_value("IP Address", tmp, &ret))
+            ret = NULL;
+        OPENSSL_free(tmp);
         break;
 
     case GEN_RID:
@@ -216,8 +198,8 @@ STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method,
 
 int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen)
 {
-    unsigned char *p;
-    int i, nid;
+    char *tmp;
+    int nid;
 
     switch (gen->type) {
     case GEN_OTHERNAME:
@@ -288,19 +270,11 @@ int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen)
         break;
 
     case GEN_IPADD:
-        p = gen->d.ip->data;
-        if (gen->d.ip->length == 4)
-            BIO_printf(out, "IP Address:%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
-        else if (gen->d.ip->length == 16) {
-            BIO_printf(out, "IP Address");
-            for (i = 0; i < 8; i++) {
-                BIO_printf(out, ":%X", p[0] << 8 | p[1]);
-                p += 2;
-            }
-        } else {
-            BIO_printf(out, "IP Address:<invalid>");
-            break;
-        }
+        tmp = ipaddr_to_asc(gen->d.ip->data, gen->d.ip->length);
+        if (tmp == NULL)
+            return 0;
+        BIO_printf(out, "IP Address:%s", tmp);
+        OPENSSL_free(tmp);
         break;
 
     case GEN_RID:
index 88ad8ba..d7b82b7 100644 (file)
@@ -192,26 +192,17 @@ static int do_i2r_name_constraints(const X509V3_EXT_METHOD *method,
 
 static int print_nc_ipadd(BIO *bp, ASN1_OCTET_STRING *ip)
 {
-    int i, len;
-    unsigned char *p;
-    p = ip->data;
-    len = ip->length;
-    BIO_puts(bp, "IP:");
-    if (len == 8) {
-        BIO_printf(bp, "%d.%d.%d.%d/%d.%d.%d.%d",
-                   p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
-    } else if (len == 32) {
-        for (i = 0; i < 16; i++) {
-            BIO_printf(bp, "%X", p[0] << 8 | p[1]);
-            p += 2;
-            if (i == 7)
-                BIO_puts(bp, "/");
-            else if (i != 15)
-                BIO_puts(bp, ":");
-        }
-    } else
-        BIO_printf(bp, "IP Address:<invalid>");
-    return 1;
+    /* ip->length should be 8 or 32 and len1 == len2 == 4 or len1 == len2 == 16 */
+    int len1 = ip->length >= 16 ? 16 : ip->length >= 4 ? 4 : ip->length;
+    int len2 = ip->length - len1;
+    char *ip1 = ipaddr_to_asc(ip->data, len1);
+    char *ip2 = ipaddr_to_asc(ip->data + len1, len2);
+    int ret = ret = ip1 != NULL && ip2 != NULL
+        && BIO_printf(bp, "IP:%s/%s", ip1, ip2) > 0;
+
+    OPENSSL_free(ip1);
+    OPENSSL_free(ip2);
+    return ret;
 }
 
 #define NAME_CHECK_MAX (1 << 20)
index 4be3953..aefb589 100644 (file)
@@ -31,7 +31,8 @@ static int sk_strcmp(const char *const *a, const char *const *b);
 static STACK_OF(OPENSSL_STRING) *get_email(const X509_NAME *name,
                                            GENERAL_NAMES *gens);
 static void str_free(OPENSSL_STRING str);
-static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, const ASN1_IA5STRING *email);
+static int append_ia5(STACK_OF(OPENSSL_STRING) **sk,
+                      const ASN1_IA5STRING *email);
 
 static int ipv4_from_asc(unsigned char *v4, const char *in);
 static int ipv6_from_asc(unsigned char *v6, const char *in);
@@ -178,6 +179,7 @@ ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, const char *value)
     ASN1_INTEGER *aint;
     int isneg, ishex;
     int ret;
+
     if (value == NULL) {
         X509V3err(X509V3_F_S2I_ASN1_INTEGER, X509V3_R_INVALID_NULL_VALUE);
         return NULL;
@@ -190,14 +192,16 @@ ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, const char *value)
     if (value[0] == '-') {
         value++;
         isneg = 1;
-    } else
+    } else {
         isneg = 0;
+    }
 
     if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X'))) {
         value += 2;
         ishex = 1;
-    } else
+    } else {
         ishex = 0;
+    }
 
     if (ishex)
         ret = BN_hex2bn(&bn, value);
@@ -297,6 +301,7 @@ STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line)
     STACK_OF(CONF_VALUE) *values = NULL;
     char *linebuf;
     int state;
+
     /* We are going to modify the line so copy it first */
     linebuf = OPENSSL_strdup(line);
     if (linebuf == NULL) {
@@ -382,6 +387,7 @@ STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line)
 static char *strip_spaces(char *name)
 {
     char *p, *q;
+
     /* Skip over leading spaces */
     p = name;
     while (*p && ossl_isspace(*p))
@@ -407,6 +413,7 @@ int v3_name_cmp(const char *name, const char *cmp)
 {
     int len, ret;
     char c;
+
     len = strlen(cmp);
     if ((ret = strncmp(name, cmp, len)))
         return ret;
@@ -502,9 +509,11 @@ static void str_free(OPENSSL_STRING str)
     OPENSSL_free(str);
 }
 
-static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, const ASN1_IA5STRING *email)
+static int append_ia5(STACK_OF(OPENSSL_STRING) **sk,
+                      const ASN1_IA5STRING *email)
 {
     char *emtmp;
+
     /* First some sanity checks */
     if (email->type != V_ASN1_IA5STRING)
         return 1;
@@ -519,7 +528,7 @@ static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, const ASN1_IA5STRING *email
         return 1;
     emtmp = OPENSSL_strdup((char *)email->data);
     if (emtmp == NULL || !sk_OPENSSL_STRING_push(*sk, emtmp)) {
-        OPENSSL_free(emtmp);    /* free on push failure */
+        OPENSSL_free(emtmp); /* free on push failure */
         X509_email_free(*sk);
         *sk = NULL;
         return 0;
@@ -576,9 +585,10 @@ static int equal_nocase(const unsigned char *pattern, size_t pattern_len,
     skip_prefix(&pattern, &pattern_len, subject_len, flags);
     if (pattern_len != subject_len)
         return 0;
-    while (pattern_len) {
+    while (pattern_len != 0) {
         unsigned char l = *pattern;
         unsigned char r = *subject;
+
         /* The pattern must not contain NUL characters. */
         if (l == 0)
             return 0;
@@ -617,6 +627,7 @@ static int equal_email(const unsigned char *a, size_t a_len,
                        unsigned int unused_flags)
 {
     size_t i = a_len;
+
     if (a_len != b_len)
         return 0;
     /*
@@ -704,6 +715,7 @@ static const unsigned char *valid_star(const unsigned char *p, size_t len,
     size_t i;
     int state = LABEL_START;
     int dots = 0;
+
     for (i = 0; i < len; ++i) {
         /*
          * Locate first and only legal wildcard, either at the start
@@ -745,8 +757,9 @@ static const unsigned char *valid_star(const unsigned char *p, size_t len,
             if ((state & LABEL_START) != 0)
                 return NULL;
             state |= LABEL_HYPHEN;
-        } else
+        } else {
             return NULL;
+        }
     }
 
     /*
@@ -862,6 +875,7 @@ static int do_x509_check(X509 *x, const char *chk, size_t chklen,
         for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
             GENERAL_NAME *gen;
             ASN1_STRING *cstr;
+
             gen = sk_GENERAL_NAME_value(gens, i);
             if (gen->type != check_type)
                 continue;
@@ -961,6 +975,29 @@ int X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags)
     return do_x509_check(x, (char *)ipout, iplen, flags, GEN_IPADD, NULL);
 }
 
+char *ipaddr_to_asc(unsigned char *p, int len)
+{
+    char buf[40], *out;
+
+    switch (len) {
+    case 4: /* IPv4 */
+        BIO_snprintf(buf, sizeof(buf), "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
+        break;
+        /* TODO possibly combine with static i2r_address() in v3_addr.c */
+    case 16: /* IPv6 */
+        for (out = buf; out < buf + 8 * 3; out += 3) {
+            BIO_snprintf(out, 3 + 1, "%X:", p[0] << 8 | p[1]);
+            p += 2;
+        }
+        out[-1] = '\0';
+        break;
+    default:
+        BIO_snprintf(buf, sizeof(buf), "<invalid length=%d>", len);
+        break;
+    }
+    return OPENSSL_strdup(buf);
+}
+
 /*
  * Convert IP addresses both IPv4 and IPv6 into an OCTET STRING compatible
  * with RFC3280.
@@ -1050,6 +1087,7 @@ int a2i_ipadd(unsigned char *ipout, const char *ipasc)
 static int ipv4_from_asc(unsigned char *v4, const char *in)
 {
     int a0, a1, a2, a3;
+
     if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4)
         return 0;
     if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255)
@@ -1076,6 +1114,7 @@ typedef struct {
 static int ipv6_from_asc(unsigned char *v6, const char *in)
 {
     IPV6_STAT v6stat;
+
     v6stat.total = 0;
     v6stat.zero_pos = -1;
     v6stat.zero_cnt = 0;
@@ -1098,21 +1137,19 @@ static int ipv6_from_asc(unsigned char *v6, const char *in)
         if (v6stat.total == 16)
             return 0;
         /* More than three zeroes is an error */
-        if (v6stat.zero_cnt > 3)
+        if (v6stat.zero_cnt > 3) {
             return 0;
         /* Can only have three zeroes if nothing else present */
-        else if (v6stat.zero_cnt == 3) {
+        else if (v6stat.zero_cnt == 3) {
             if (v6stat.total > 0)
                 return 0;
-        }
-        /* Can only have two zeroes if at start or end */
-        else if (v6stat.zero_cnt == 2) {
+        } else if (v6stat.zero_cnt == 2) {
+            /* Can only have two zeroes if at start or end */
             if ((v6stat.zero_pos != 0)
                 && (v6stat.zero_pos != v6stat.total))
                 return 0;
-        } else
+        } else {
             /* Can only have one zero if *not* start or end */
-        {
             if ((v6stat.zero_pos == 0)
                 || (v6stat.zero_pos == v6stat.total))
                 return 0;
@@ -1131,8 +1168,9 @@ static int ipv6_from_asc(unsigned char *v6, const char *in)
             memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total,
                    v6stat.tmp + v6stat.zero_pos,
                    v6stat.total - v6stat.zero_pos);
-    } else
+    } else {
         memcpy(v6, v6stat.tmp, 16);
+    }
 
     return 1;
 }
@@ -1140,6 +1178,7 @@ static int ipv6_from_asc(unsigned char *v6, const char *in)
 static int ipv6_cb(const char *elem, int len, void *usr)
 {
     IPV6_STAT *s = usr;
+
     /* Error if 16 bytes written */
     if (s->total == 16)
         return 0;
@@ -1203,6 +1242,7 @@ int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE) *dn_sk,
     CONF_VALUE *v;
     int i, mval, spec_char, plus_char;
     char *p, *type;
+
     if (!nm)
         return 0;
 
@@ -1217,7 +1257,7 @@ int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE) *dn_sk,
             spec_char = ((*p == ':') || (*p == ',') || (*p == '.'));
 #else
             spec_char = ((*p == os_toascii[':']) || (*p == os_toascii[','])
-                    || (*p == os_toascii['.']));
+                         || (*p == os_toascii['.']));
 #endif
             if (spec_char) {
                 p++;
@@ -1234,8 +1274,9 @@ int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE) *dn_sk,
         if (plus_char) {
             mval = -1;
             type++;
-        } else
+        } else {
             mval = 0;
+        }
         if (!X509_NAME_add_entry_by_txt(nm, type, chtype,
                                         (unsigned char *)v->value, -1, -1,
                                         mval))
index c3af2d3..f87dfd0 100644 (file)
@@ -146,14 +146,14 @@ void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param)
 /* Macro to test if a field should be copied from src to dest */
 
 #define test_x509_verify_param_copy(field, def) \
-        (to_overwrite || \
-                ((src->field != def) && (to_default || (dest->field == def))))
+    (to_overwrite \
+         || ((src->field != def) && (to_default || (dest->field == def))))
 
 /* Macro to test and copy a field if necessary */
 
 #define x509_verify_param_copy(field, def) \
-        if (test_x509_verify_param_copy(field, def)) \
-                dest->field = src->field
+    if (test_x509_verify_param_copy(field, def)) \
+        dest->field = src->field;
 
 int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest,
                               const X509_VERIFY_PARAM *src)
@@ -243,14 +243,16 @@ int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to,
 static int int_x509_param_set1(char **pdest, size_t *pdestlen,
                                const char *src, size_t srclen)
 {
-    void *tmp;
+    char *tmp;
     if (src) {
         if (srclen == 0)
             srclen = strlen(src);
 
-        tmp = OPENSSL_memdup(src, srclen);
+        tmp = OPENSSL_malloc(srclen + 1);
         if (tmp == NULL)
             return 0;
+        memcpy(tmp, src, srclen);
+        tmp[srclen] = '\0'; /* enforce NUL termination */
     } else {
         tmp = NULL;
         srclen = 0;
@@ -379,6 +381,11 @@ int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param,
     return 1;
 }
 
+char *X509_VERIFY_PARAM_get0_host(X509_VERIFY_PARAM *param, int idx)
+{
+    return sk_OPENSSL_STRING_value(param->hosts, idx);
+}
+
 int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param,
                                 const char *name, size_t namelen)
 {
@@ -425,6 +432,11 @@ void X509_VERIFY_PARAM_move_peername(X509_VERIFY_PARAM *to,
         from->peername = NULL;
 }
 
+char *X509_VERIFY_PARAM_get0_email(X509_VERIFY_PARAM *param)
+{
+    return param->email;
+}
+
 int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param,
                                  const char *email, size_t emaillen)
 {
@@ -432,6 +444,24 @@ int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param,
                                email, emaillen);
 }
 
+static unsigned char
+*int_X509_VERIFY_PARAM_get0_ip(X509_VERIFY_PARAM *param, size_t *plen)
+{
+    if (param == NULL || param->ip == NULL)
+        return NULL;
+    if (plen != NULL)
+        *plen = param->iplen;
+    return param->ip;
+}
+
+char *X509_VERIFY_PARAM_get1_ip_asc(X509_VERIFY_PARAM *param)
+{
+    size_t iplen;
+    unsigned char *ip = int_X509_VERIFY_PARAM_get0_ip(param, &iplen);
+
+    return  ip == NULL ? NULL : ipaddr_to_asc(ip, iplen);
+}
+
 int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param,
                               const unsigned char *ip, size_t iplen)
 {
index 27e0a73..f34020c 100644 (file)
@@ -10,11 +10,13 @@ X509_VERIFY_PARAM_get_depth, X509_VERIFY_PARAM_set_auth_level,
 X509_VERIFY_PARAM_get_auth_level, X509_VERIFY_PARAM_set_time,
 X509_VERIFY_PARAM_get_time,
 X509_VERIFY_PARAM_add0_policy, X509_VERIFY_PARAM_set1_policies,
+X509_VERIFY_PARAM_get0_host,
 X509_VERIFY_PARAM_set1_host, X509_VERIFY_PARAM_add1_host,
 X509_VERIFY_PARAM_set_hostflags,
 X509_VERIFY_PARAM_get_hostflags,
 X509_VERIFY_PARAM_get0_peername,
-X509_VERIFY_PARAM_set1_email, X509_VERIFY_PARAM_set1_ip,
+X509_VERIFY_PARAM_get0_email, X509_VERIFY_PARAM_set1_email,
+X509_VERIFY_PARAM_set1_ip, X509_VERIFY_PARAM_get1_ip_asc,
 X509_VERIFY_PARAM_set1_ip_asc
 - X509 verification parameters
 
@@ -50,6 +52,7 @@ X509_VERIFY_PARAM_set1_ip_asc
                                        int auth_level);
  int X509_VERIFY_PARAM_get_auth_level(const X509_VERIFY_PARAM *param);
 
+ char *X509_VERIFY_PARAM_get0_host(X509_VERIFY_PARAM *param, int n);
  int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param,
                                  const char *name, size_t namelen);
  int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param,
@@ -58,8 +61,10 @@ X509_VERIFY_PARAM_set1_ip_asc
                                       unsigned int flags);
  unsigned int X509_VERIFY_PARAM_get_hostflags(const X509_VERIFY_PARAM *param);
  char *X509_VERIFY_PARAM_get0_peername(const X509_VERIFY_PARAM *param);
+ char *X509_VERIFY_PARAM_get0_email(X509_VERIFY_PARAM *param);
  int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param,
                                   const char *email, size_t emaillen);
+ char *X509_VERIFY_PARAM_get1_ip_asc(X509_VERIFY_PARAM *param);
  int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param,
                                const unsigned char *ip, size_t iplen);
  int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc);
@@ -128,6 +133,11 @@ Security level 1 requires at least 80-bit-equivalent security and is broadly
 interoperable, though it will, for example, reject MD5 signatures or RSA keys
 shorter than 1024 bits.
 
+X509_VERIFY_PARAM_get0_host() returns the B<n>th expected DNS hostname that has
+been set using X509_VERIFY_PARAM_set1_host() or X509_VERIFY_PARAM_add1_host().
+To obtain all names start with B<n> = 0 and increment B<n> as long as no NULL
+pointer is returned.
+
 X509_VERIFY_PARAM_set1_host() sets the expected DNS hostname to
 B<name> clearing any previously specified hostname.  If
 B<name> is NULL, or empty the list of hostnames is cleared, and
@@ -177,12 +187,17 @@ string is allocated by the library and is no longer valid once the
 associated B<param> argument is freed.  Applications must not free
 the return value.
 
+X509_VERIFY_PARAM_get0_email() returns the expected RFC822 email address.
+
 X509_VERIFY_PARAM_set1_email() sets the expected RFC822 email address to
 B<email>.  If B<email> is NUL-terminated, B<emaillen> may be zero, otherwise
 B<emaillen> must be set to the length of B<email>.  When an email address
 is specified, certificate verification automatically invokes
 L<X509_check_email(3)>.
 
+X509_VERIFY_PARAM_get1_ip_asc() returns the expected IP address as a string.
+The caller is responsible for freeing it.
+
 X509_VERIFY_PARAM_set1_ip() sets the expected IP address to B<ip>.
 The B<ip> argument is in binary format, in network byte-order and
 B<iplen> must be set to 4 for IPv4 and 16 for IPv6.  When an IP
@@ -205,6 +220,10 @@ X509_VERIFY_PARAM_set1_email(), X509_VERIFY_PARAM_set1_ip() and
 X509_VERIFY_PARAM_set1_ip_asc() return 1 for success and 0 for
 failure.
 
+X509_VERIFY_PARAM_get0_host(), X509_VERIFY_PARAM_get0_email(), and
+X509_VERIFY_PARAM_get1_ip_asc(), return the string pointers pecified above
+or NULL if the respective value has not been set or on error.
+
 X509_VERIFY_PARAM_get_flags() returns the current verification flags.
 
 X509_VERIFY_PARAM_get_hostflags() returns any current host flags.
@@ -374,6 +393,9 @@ and has no effect.
 
 The X509_VERIFY_PARAM_get_hostflags() function was added in OpenSSL 1.1.0i.
 
+The X509_VERIFY_PARAM_get0_host(), X509_VERIFY_PARAM_get0_email(),
+and X509_VERIFY_PARAM_get1_ip_asc() functions were added in OpenSSL 3.0.
+
 =head1 COPYRIGHT
 
 Copyright 2009-2020 The OpenSSL Project Authors. All Rights Reserved.
index 615cd21..03f1478 100644 (file)
@@ -238,5 +238,6 @@ static ossl_inline void ossl_sleep(unsigned long millis)
 
 char *sk_ASN1_UTF8STRING2text(STACK_OF(ASN1_UTF8STRING) *text, const char *sep,
                               size_t max_len);
+char *ipaddr_to_asc(unsigned char *p, int len);
 
 #endif
index 84b076a..92aed08 100644 (file)
@@ -585,6 +585,7 @@ int X509_VERIFY_PARAM_set_inh_flags(X509_VERIFY_PARAM *param,
                                     uint32_t flags);
 uint32_t X509_VERIFY_PARAM_get_inh_flags(const X509_VERIFY_PARAM *param);
 
+char *X509_VERIFY_PARAM_get0_host(X509_VERIFY_PARAM *param, int idx);
 int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param,
                                 const char *name, size_t namelen);
 int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param,
@@ -594,8 +595,10 @@ void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param,
 unsigned int X509_VERIFY_PARAM_get_hostflags(const X509_VERIFY_PARAM *param);
 char *X509_VERIFY_PARAM_get0_peername(const X509_VERIFY_PARAM *param);
 void X509_VERIFY_PARAM_move_peername(X509_VERIFY_PARAM *, X509_VERIFY_PARAM *);
+char *X509_VERIFY_PARAM_get0_email(X509_VERIFY_PARAM *param);
 int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param,
                                  const char *email, size_t emaillen);
+char *X509_VERIFY_PARAM_get1_ip_asc(X509_VERIFY_PARAM *param);
 int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param,
                               const unsigned char *ip, size_t iplen);
 int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param,
index 82ae2e7..32942a5 100644 (file)
@@ -5072,6 +5072,9 @@ EVP_PKEY_CTX_set_dh_paramgen_generator  ? 3_0_0   EXIST::FUNCTION:DH
 EVP_PKEY_CTX_set_dh_nid                 ?      3_0_0   EXIST::FUNCTION:DH
 EVP_PKEY_CTX_set_dh_rfc5114             ?      3_0_0   EXIST::FUNCTION:DH
 EVP_PKEY_CTX_set_dhx_rfc5114            ?      3_0_0   EXIST::FUNCTION:DH
+X509_VERIFY_PARAM_get0_host             ?      3_0_0   EXIST::FUNCTION:
+X509_VERIFY_PARAM_get0_email            ?      3_0_0   EXIST::FUNCTION:
+X509_VERIFY_PARAM_get1_ip_asc           ?      3_0_0   EXIST::FUNCTION:
 X509_verify_ex                          ?      3_0_0   EXIST::FUNCTION:
 X509_REQ_verify_ex                      ?      3_0_0   EXIST::FUNCTION:
 X509_ALGOR_copy                         ?      3_0_0   EXIST::FUNCTION: