b19d6e
diff --git a/docs/manual/mod/mod_ssl.html.en b/docs/manual/mod/mod_ssl.html.en
b19d6e
index 98540cd..4580f1c 100644
b19d6e
--- a/docs/manual/mod/mod_ssl.html.en
b19d6e
+++ b/docs/manual/mod/mod_ssl.html.en
b19d6e
@@ -197,6 +197,12 @@ the SSLOptions directiv
b19d6e
 first (or only) attribute of any DN is added only under a non-suffixed
b19d6e
 name; i.e. no _0 suffixed entries are added.

b19d6e
 
b19d6e
+

The _RAW suffix may now be added to mod_ssl DN variable names

b19d6e
+(such as SSL_CLIENT_I_O_RAW). When this suffix is used, conversion
b19d6e
+of certificate name attributes to UTF-8 is omitted. This allows variable
b19d6e
+lookups and comparisons for certificates with incorrectly tagged name
b19d6e
+attributes.

b19d6e
+
b19d6e
 

The format of the *_DN variables has changed in Apache HTTPD

b19d6e
 2.3.11. See the LegacyDNStringFormat option for
b19d6e
 SSLOptions for details.

b19d6e
@@ -861,7 +867,7 @@ SSLEngine on
b19d6e
 </VirtualHost>
b19d6e
 
b19d6e
 
b19d6e
-

In Apache 2.1 and later, SSLEngine can be set to

b19d6e
+

In httpd 2.2.0 and later, SSLEngine can be set to

b19d6e
 optional. This enables support for
b19d6e
 RFC 2817, Upgrading to TLS
b19d6e
 Within HTTP/1.1. At this time no web browsers support RFC 2817.

b19d6e
diff --git a/modules/ssl/ssl_engine_vars.c b/modules/ssl/ssl_engine_vars.c
b19d6e
index 2b7c9ba..e25a6d4 100644
b19d6e
--- a/modules/ssl/ssl_engine_vars.c
b19d6e
+++ b/modules/ssl/ssl_engine_vars.c
b19d6e
@@ -41,7 +41,7 @@
b19d6e
 
b19d6e
 static char *ssl_var_lookup_ssl(apr_pool_t *p, conn_rec *c, request_rec *r, char *var);
b19d6e
 static char *ssl_var_lookup_ssl_cert(apr_pool_t *p, request_rec *r, X509 *xs, char *var);
b19d6e
-static char *ssl_var_lookup_ssl_cert_dn(apr_pool_t *p, X509_NAME *xsname, char *var);
b19d6e
+static char *ssl_var_lookup_ssl_cert_dn(apr_pool_t *p, X509_NAME *xsname, const char *var);
b19d6e
 static char *ssl_var_lookup_ssl_cert_san(apr_pool_t *p, X509 *xs, char *var);
b19d6e
 static char *ssl_var_lookup_ssl_cert_valid(apr_pool_t *p, ASN1_TIME *tm);
b19d6e
 static char *ssl_var_lookup_ssl_cert_remain(apr_pool_t *p, ASN1_TIME *tm);
b19d6e
@@ -562,15 +562,23 @@ static const struct {
b19d6e
     { NULL,    0,                          0 }
b19d6e
 };
b19d6e
 
b19d6e
-static char *ssl_var_lookup_ssl_cert_dn(apr_pool_t *p, X509_NAME *xsname, char *var)
b19d6e
+static char *ssl_var_lookup_ssl_cert_dn(apr_pool_t *p, X509_NAME *xsname,
b19d6e
+                                        const char *var)
b19d6e
 {
b19d6e
-    char *result, *ptr;
b19d6e
+    const char *ptr;
b19d6e
+    char *result;
b19d6e
     X509_NAME_ENTRY *xsne;
b19d6e
-    int i, j, n, idx = 0;
b19d6e
+    int i, j, n, idx = 0, raw = 0;
b19d6e
     apr_size_t varlen;
b19d6e
 
b19d6e
+    ptr = ap_strrchr_c(var, '_');
b19d6e
+    if (ptr && ptr > var && strcmp(ptr + 1, "RAW") == 0) {
b19d6e
+        var = apr_pstrmemdup(p, var, ptr - var);
b19d6e
+        raw = 1;
b19d6e
+    }
b19d6e
+
b19d6e
     /* if an _N suffix is used, find the Nth attribute of given name */
b19d6e
-    ptr = strchr(var, '_');
b19d6e
+    ptr = ap_strchr_c(var, '_');
b19d6e
     if (ptr != NULL && strspn(ptr + 1, "0123456789") == strlen(ptr + 1)) {
b19d6e
         idx = atoi(ptr + 1);
b19d6e
         varlen = ptr - var;
b19d6e
@@ -592,7 +600,7 @@ static char *ssl_var_lookup_ssl_cert_dn(apr_pool_t *p, X509_NAME *xsname, char *
b19d6e
                 n =OBJ_obj2nid((ASN1_OBJECT *)X509_NAME_ENTRY_get_object(xsne));
b19d6e
 
b19d6e
                 if (n == ssl_var_lookup_ssl_cert_dn_rec[i].nid && idx-- == 0) {
b19d6e
-                    result = SSL_X509_NAME_ENTRY_to_string(p, xsne);
b19d6e
+                    result = SSL_X509_NAME_ENTRY_to_string(p, xsne, raw);
b19d6e
                     break;
b19d6e
                 }
b19d6e
             }
b19d6e
@@ -897,7 +905,7 @@ static void extract_dn(apr_table_t *t, apr_hash_t *nids, const char *pfx,
b19d6e
                  apr_hash_set(count, &nid, sizeof nid, dup);
b19d6e
                  key = apr_pstrcat(p, pfx, tag, NULL);
b19d6e
              }
b19d6e
-             value = SSL_X509_NAME_ENTRY_to_string(p, xsne);
b19d6e
+             value = SSL_X509_NAME_ENTRY_to_string(p, xsne, 0);
b19d6e
              apr_table_setn(t, key, value);
b19d6e
          }
b19d6e
     }
b19d6e
diff --git a/modules/ssl/ssl_util_ssl.c b/modules/ssl/ssl_util_ssl.c
b19d6e
index 09a9877..fbd701f 100644
b19d6e
--- a/modules/ssl/ssl_util_ssl.c
b19d6e
+++ b/modules/ssl/ssl_util_ssl.c
b19d6e
@@ -236,18 +236,21 @@ BOOL SSL_X509_getBC(X509 *cert, int *ca, int *pathlen)
b19d6e
     return TRUE;
b19d6e
 }
b19d6e
 
b19d6e
-/* convert an ASN.1 string to a UTF-8 string (escaping control characters) */
b19d6e
-char *SSL_ASN1_STRING_to_utf8(apr_pool_t *p, ASN1_STRING *asn1str)
b19d6e
+/* Convert ASN.1 string to a pool-allocated char * string, escaping
b19d6e
+ * control characters.  If raw is zero, convert to UTF-8, otherwise
b19d6e
+ * unchanged from the character set. */
b19d6e
+char *SSL_ASN1_STRING_convert(apr_pool_t *p, ASN1_STRING *asn1str, int raw)
b19d6e
 {
b19d6e
     char *result = NULL;
b19d6e
     BIO *bio;
b19d6e
-    int len;
b19d6e
+    int len, flags = ASN1_STRFLGS_ESC_CTRL;
b19d6e
 
b19d6e
     if ((bio = BIO_new(BIO_s_mem())) == NULL)
b19d6e
         return NULL;
b19d6e
 
b19d6e
-    ASN1_STRING_print_ex(bio, asn1str, ASN1_STRFLGS_ESC_CTRL|
b19d6e
-                                       ASN1_STRFLGS_UTF8_CONVERT);
b19d6e
+    if (!raw) flags |= ASN1_STRFLGS_UTF8_CONVERT;
b19d6e
+
b19d6e
+    ASN1_STRING_print_ex(bio, asn1str, flags);
b19d6e
     len = BIO_pending(bio);
b19d6e
     if (len > 0) {
b19d6e
         result = apr_palloc(p, len+1);
b19d6e
@@ -258,10 +261,13 @@ char *SSL_ASN1_STRING_to_utf8(apr_pool_t *p, ASN1_STRING *asn1str)
b19d6e
     return result;
b19d6e
 }
b19d6e
 
b19d6e
+#define SSL_ASN1_STRING_to_utf8(p, a) SSL_ASN1_STRING_convert(p, a, 0)
b19d6e
+
b19d6e
 /* convert a NAME_ENTRY to UTF8 string */
b19d6e
-char *SSL_X509_NAME_ENTRY_to_string(apr_pool_t *p, X509_NAME_ENTRY *xsne)
b19d6e
+char *SSL_X509_NAME_ENTRY_to_string(apr_pool_t *p, X509_NAME_ENTRY *xsne,
b19d6e
+                                    int raw) 
b19d6e
 {
b19d6e
-    char *result = SSL_ASN1_STRING_to_utf8(p, X509_NAME_ENTRY_get_data(xsne));
b19d6e
+    char *result = SSL_ASN1_STRING_convert(p, X509_NAME_ENTRY_get_data(xsne), raw);
b19d6e
     ap_xlate_proto_from_ascii(result, len);
b19d6e
     return result;
b19d6e
 }
b19d6e
@@ -414,7 +420,7 @@ BOOL SSL_X509_getIDs(apr_pool_t *p, X509 *x509, apr_array_header_t **ids)
b19d6e
     subj = X509_get_subject_name(x509);
b19d6e
     while ((i = X509_NAME_get_index_by_NID(subj, NID_commonName, i)) != -1) {
b19d6e
         APR_ARRAY_PUSH(*ids, const char *) = 
b19d6e
-            SSL_X509_NAME_ENTRY_to_string(p, X509_NAME_get_entry(subj, i));
b19d6e
+            SSL_X509_NAME_ENTRY_to_string(p, X509_NAME_get_entry(subj, i), 0);
b19d6e
     }
b19d6e
 
b19d6e
     return apr_is_empty_array(*ids) ? FALSE : TRUE;
b19d6e
diff --git a/modules/ssl/ssl_util_ssl.h b/modules/ssl/ssl_util_ssl.h
b19d6e
index be07ab7..611957e 100644
b19d6e
--- a/modules/ssl/ssl_util_ssl.h
b19d6e
+++ b/modules/ssl/ssl_util_ssl.h
b19d6e
@@ -65,8 +65,8 @@ EVP_PKEY   *SSL_read_PrivateKey(char *, EVP_PKEY **, pem_password_cb *, void *);
b19d6e
 int         SSL_smart_shutdown(SSL *ssl);
b19d6e
 BOOL        SSL_X509_isSGC(X509 *);
b19d6e
 BOOL        SSL_X509_getBC(X509 *, int *, int *);
b19d6e
-char       *SSL_ASN1_STRING_to_utf8(apr_pool_t *, ASN1_STRING *);
b19d6e
-char       *SSL_X509_NAME_ENTRY_to_string(apr_pool_t *p, X509_NAME_ENTRY *xsne);
b19d6e
+char       *SSL_ASN1_STRING_to_utf8(apr_pool_t *, ASN1_STRING *, int raw);
b19d6e
+char       *SSL_X509_NAME_ENTRY_to_string(apr_pool_t *p, X509_NAME_ENTRY *xsne, int raw);
b19d6e
 char       *SSL_X509_NAME_to_string(apr_pool_t *, X509_NAME *, int);
b19d6e
 BOOL        SSL_X509_getSAN(apr_pool_t *, X509 *, int, const char *, int, apr_array_header_t **);
b19d6e
 BOOL        SSL_X509_getIDs(apr_pool_t *, X509 *, apr_array_header_t **);