From: Joe Orton <jorton@apache.org> Date: Fri, 9 Mar 2018 07:55:27 +0000 (+0000) Subject: Merge r1811976 from trunk: X-Git-Tag: 2.4.32~11 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ea5c40d2273a1379bf42ac8d702ff97ca50c734c;p=apache Merge r1811976 from trunk: Add optional _RAW suffix to SSL_*_DN_xx attribute names, allowing users to convert an attribute value without conversion to UTF-8. (A public CA has issued certs with attributes tagged as the wrong ASN.1 string types.) * modules/ssl/ssl_util_ssl.c (asn1_string_convert): Rename from asn1_string_to_utf8; add raw argument. Reimplement _to_utf8 as macro. (modssl_X509_NAME_ENTRY_to_string): Add raw argument. * modules/ssl/ssl_engine_vars.c (ssl_var_lookup_ssl_cert_dn): Use raw string conversion if _RAW suffix is present in DN component. Submitted by: jorton Reviewed by: jorton, jim, ylavic git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1826300 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 88f7db9e3b..f056fa3a9d 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,9 @@ -*- coding: utf-8 -*- Changes with Apache 2.4.32 + *) mod_ssl: Support SSL DN raw variable extraction without conversion + to UTF-8, using _RAW suffix on variable names. [Joe Orton] + *) ab: Fix send length calculation for the non-blocking connect case introduced in 2.4.30. [Joe Orton] diff --git a/docs/manual/mod/mod_ssl.xml b/docs/manual/mod/mod_ssl.xml index 86287a4df9..a2a41042b7 100644 --- a/docs/manual/mod/mod_ssl.xml +++ b/docs/manual/mod/mod_ssl.xml @@ -109,7 +109,7 @@ compatibility variables.</p> </table> <p><em>x509</em> specifies a component of an X.509 DN; one of -<code>C,ST,L,O,OU,CN,T,I,G,S,D,UID,Email</code>. In Apache 2.1 and +<code>C,ST,L,O,OU,CN,T,I,G,S,D,UID,Email</code>. In httpd 2.2.0 and later, <em>x509</em> may also include a numeric <code>_n</code> suffix. If the DN in question contains multiple attributes of the same name, this suffix is used as a zero-based index to select a @@ -125,6 +125,12 @@ the <directive module="mod_ssl">SSLOptions</directive> directive, the first (or only) attribute of any DN is added only under a non-suffixed name; i.e. no <code>_0</code> suffixed entries are added.</p> +<p>In httpd 2.4.32 and later, an optional <em>_RAW</em> suffix may be +added to <em>x509</em> in a DN component, to suppress conversion of +the attribute value to UTF-8. This must be placed after the index +suffix (if any). For example, <code>SSL_SERVER_S_DN_OU_RAW</code> or +<code>SSL_SERVER_S_DN_OU_0_RAW</code> could be used.</p> + <p>The format of the <em>*_DN</em> variables has changed in Apache HTTPD 2.3.11. See the <code>LegacyDNStringFormat</code> option for <directive module="mod_ssl">SSLOptions</directive> for details.</p> diff --git a/modules/ssl/ssl_engine_vars.c b/modules/ssl/ssl_engine_vars.c index 8ce40efac9..a28d4dd751 100644 --- a/modules/ssl/ssl_engine_vars.c +++ b/modules/ssl/ssl_engine_vars.c @@ -41,7 +41,7 @@ static char *ssl_var_lookup_ssl(apr_pool_t *p, SSLConnRec *sslconn, request_rec *r, char *var); static char *ssl_var_lookup_ssl_cert(apr_pool_t *p, request_rec *r, X509 *xs, char *var); -static char *ssl_var_lookup_ssl_cert_dn(apr_pool_t *p, X509_NAME *xsname, char *var); +static char *ssl_var_lookup_ssl_cert_dn(apr_pool_t *p, X509_NAME *xsname, const char *var); static char *ssl_var_lookup_ssl_cert_san(apr_pool_t *p, X509 *xs, char *var); static char *ssl_var_lookup_ssl_cert_valid(apr_pool_t *p, ASN1_TIME *tm); static char *ssl_var_lookup_ssl_cert_remain(apr_pool_t *p, ASN1_TIME *tm); @@ -588,15 +588,23 @@ static const struct { { NULL, 0, 0 } }; -static char *ssl_var_lookup_ssl_cert_dn(apr_pool_t *p, X509_NAME *xsname, char *var) +static char *ssl_var_lookup_ssl_cert_dn(apr_pool_t *p, X509_NAME *xsname, + const char *var) { - char *result, *ptr; + const char *ptr; + char *result; X509_NAME_ENTRY *xsne; - int i, j, n, idx = 0; + int i, j, n, idx = 0, raw = 0; apr_size_t varlen; + ptr = ap_strrchr_c(var, '_'); + if (ptr && ptr > var && strcmp(ptr + 1, "RAW") == 0) { + var = apr_pstrmemdup(p, var, ptr - var); + raw = 1; + } + /* if an _N suffix is used, find the Nth attribute of given name */ - ptr = strchr(var, '_'); + ptr = ap_strchr_c(var, '_'); if (ptr != NULL && strspn(ptr + 1, "0123456789") == strlen(ptr + 1)) { idx = atoi(ptr + 1); varlen = ptr - var; @@ -615,7 +623,7 @@ static char *ssl_var_lookup_ssl_cert_dn(apr_pool_t *p, X509_NAME *xsname, char * n =OBJ_obj2nid((ASN1_OBJECT *)X509_NAME_ENTRY_get_object(xsne)); if (n == ssl_var_lookup_ssl_cert_dn_rec[i].nid && idx-- == 0) { - result = modssl_X509_NAME_ENTRY_to_string(p, xsne); + result = modssl_X509_NAME_ENTRY_to_string(p, xsne, raw); break; } } @@ -947,7 +955,7 @@ static void extract_dn(apr_table_t *t, apr_hash_t *nids, const char *pfx, apr_hash_set(count, &nid, sizeof nid, dup); key = apr_pstrcat(p, pfx, tag, NULL); } - value = modssl_X509_NAME_ENTRY_to_string(p, xsne); + value = modssl_X509_NAME_ENTRY_to_string(p, xsne, 0); apr_table_setn(t, key, value); } } diff --git a/modules/ssl/ssl_util_ssl.c b/modules/ssl/ssl_util_ssl.c index e22dd7d694..b7f0eca173 100644 --- a/modules/ssl/ssl_util_ssl.c +++ b/modules/ssl/ssl_util_ssl.c @@ -217,18 +217,21 @@ BOOL modssl_X509_getBC(X509 *cert, int *ca, int *pathlen) return TRUE; } -/* convert an ASN.1 string to a UTF-8 string (escaping control characters) */ -static char *asn1_string_to_utf8(apr_pool_t *p, ASN1_STRING *asn1str) +/* Convert ASN.1 string to a pool-allocated char * string, escaping + * control characters. If raw is zero, convert to UTF-8, otherwise + * unchanged from the character set. */ +static char *asn1_string_convert(apr_pool_t *p, ASN1_STRING *asn1str, int raw) { char *result = NULL; BIO *bio; - int len; + int len, flags = ASN1_STRFLGS_ESC_CTRL; if ((bio = BIO_new(BIO_s_mem())) == NULL) return NULL; - ASN1_STRING_print_ex(bio, asn1str, ASN1_STRFLGS_ESC_CTRL| - ASN1_STRFLGS_UTF8_CONVERT); + if (!raw) flags |= ASN1_STRFLGS_UTF8_CONVERT; + + ASN1_STRING_print_ex(bio, asn1str, flags); len = BIO_pending(bio); if (len > 0) { result = apr_palloc(p, len+1); @@ -239,10 +242,13 @@ static char *asn1_string_to_utf8(apr_pool_t *p, ASN1_STRING *asn1str) return result; } +#define asn1_string_to_utf8(p, a) asn1_string_convert(p, a, 0) + /* convert a NAME_ENTRY to UTF8 string */ -char *modssl_X509_NAME_ENTRY_to_string(apr_pool_t *p, X509_NAME_ENTRY *xsne) +char *modssl_X509_NAME_ENTRY_to_string(apr_pool_t *p, X509_NAME_ENTRY *xsne, + int raw) { - char *result = asn1_string_to_utf8(p, X509_NAME_ENTRY_get_data(xsne)); + char *result = asn1_string_convert(p, X509_NAME_ENTRY_get_data(xsne), raw); ap_xlate_proto_from_ascii(result, len); return result; } @@ -395,7 +401,7 @@ static BOOL getIDs(apr_pool_t *p, X509 *x509, apr_array_header_t **ids) subj = X509_get_subject_name(x509); while ((i = X509_NAME_get_index_by_NID(subj, NID_commonName, i)) != -1) { APR_ARRAY_PUSH(*ids, const char *) = - modssl_X509_NAME_ENTRY_to_string(p, X509_NAME_get_entry(subj, i)); + modssl_X509_NAME_ENTRY_to_string(p, X509_NAME_get_entry(subj, i), 0); } return apr_is_empty_array(*ids) ? FALSE : TRUE; diff --git a/modules/ssl/ssl_util_ssl.h b/modules/ssl/ssl_util_ssl.h index 5c6c8b6853..c67dacff3d 100644 --- a/modules/ssl/ssl_util_ssl.h +++ b/modules/ssl/ssl_util_ssl.h @@ -68,7 +68,8 @@ EVP_PKEY *modssl_read_privatekey(const char *, EVP_PKEY **, pem_password_cb *, EVP_PKEY *modssl_read_encrypted_pkey(const char *, EVP_PKEY **, const char *, apr_size_t); int modssl_smart_shutdown(SSL *ssl); BOOL modssl_X509_getBC(X509 *, int *, int *); -char *modssl_X509_NAME_ENTRY_to_string(apr_pool_t *p, X509_NAME_ENTRY *xsne); +char *modssl_X509_NAME_ENTRY_to_string(apr_pool_t *p, X509_NAME_ENTRY *xsne, + int raw); char *modssl_X509_NAME_to_string(apr_pool_t *, X509_NAME *, int); BOOL modssl_X509_getSAN(apr_pool_t *, X509 *, int, const char *, int, apr_array_header_t **); BOOL modssl_X509_match_name(apr_pool_t *, X509 *, const char *, BOOL, server_rec *);