]> granicus.if.org Git - apache/commitdiff
Add optional _RAW suffix to SSL_*_DN_xx attribute names, allowing
authorJoe Orton <jorton@apache.org>
Thu, 12 Oct 2017 15:11:50 +0000 (15:11 +0000)
committerJoe Orton <jorton@apache.org>
Thu, 12 Oct 2017 15:11:50 +0000 (15:11 +0000)
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.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1811976 13f79535-47bb-0310-9956-ffa450edef68

docs/manual/mod/mod_ssl.xml
modules/ssl/ssl_engine_vars.c
modules/ssl/ssl_util_ssl.c
modules/ssl/ssl_util_ssl.h

index 7b8b8134ddfc67d60c3706c19ed0b6bfe32e5529..c13db2c655f9b209c5563846389d417219eccd58 100644 (file)
@@ -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.5.0 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>
index 77cb028e63aa464b5938442a6dd5b562c7159103..f5822374e270b321b7520c2d13f550acc89710a1 100644 (file)
@@ -41,7 +41,7 @@
 
 static char *ssl_var_lookup_ssl(apr_pool_t *p, const 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);
@@ -662,15 +662,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;
@@ -689,7 +697,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;
                 }
             }
@@ -1023,7 +1031,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);
          }
     }
index e22dd7d6946d411da54147a383a330d97a265efd..b7f0eca173523e9898c25f349ae38254de4a1e90 100644 (file)
@@ -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;
index 5c6c8b6853101dac3ab6a6d50ef346958ec2649b..c67dacff3d84fea7ba80fc42594ca04c657b2bc1 100644 (file)
@@ -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 *);