From: Stefan Fritsch
Date: Sat, 1 Jan 2011 23:56:24 +0000 (+0000)
Subject: Change the format of the SSL_{CLIENT,SERVER}_{I,S}_DN variables
X-Git-Tag: 2.3.11~289
X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7403827278ff4dc120b59f83c5237050a922ecd2;p=thirdparty%2Fapache%2Fhttpd.git
Change the format of the SSL_{CLIENT,SERVER}_{I,S}_DN variables
to be RFC 2253 compatible, convert non-ASCII characters to UTF8, and
escape other special characters with backslashes. The old format can
still be used with the LegacyDNStringFormat argument to SSLOptions.
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1054323 13f79535-47bb-0310-9956-ffa450edef68
---
diff --git a/CHANGES b/CHANGES
index c6821771094..8d25db4e6d0 100644
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,11 @@
Changes with Apache 2.3.11
+ *) mod_ssl: Change the format of the SSL_{CLIENT,SERVER}_{I,S}_DN variables
+ to be RFC 2253 compatible, convert non-ASCII characters to UTF8, and
+ escape other special characters with backslashes. The old format can
+ still be used with the LegacyDNStringFormat argument to SSLOptions.
+
*) core, mod_rewrite: Make the REQUEST_SCHEME variable available to
scripts and mod_rewrite. [Stefan Fritsch]
diff --git a/docs/manual/mod/mod_ssl.xml b/docs/manual/mod/mod_ssl.xml
index 13f0a969ea7..4cbb1ba2663 100644
--- a/docs/manual/mod/mod_ssl.xml
+++ b/docs/manual/mod/mod_ssl.xml
@@ -106,6 +106,10 @@ attribute. For example, where the server certificate subject DN
included two OU fields, SSL_SERVER_S_DN_OU_0
and
SSL_SERVER_S_DN_OU_1
could be used to reference each.
+The format of the *_DN variables has changed in Apache HTTPD
+2.3.11. See the LegacyDNStringFormat
option for
+SSLOptions for details.
+
SSL_CLIENT_V_REMAIN
is only available in version 2.1
and later.
@@ -1181,6 +1185,21 @@ The available options are:
checks sometimes maybe not what the user expects, so enable this on a
per-directory basis only, please.
+LegacyDNStringFormat
+
+ This option influences how values of the
+ SSL_{CLIENT,SERVER}_{I,S}_DN
variables are formatted. Since
+ version 2.3.11, Apache HTTPD uses a RFC 2253 compatible format by
+ default. This uses commas as delimiters between the attributes, allows the
+ use of non-ASCII characters (which are converted to UTF8), escapes
+ various special characters with backslashes, and sorts the attributes
+ with the "C" attribute last.
+
+ If LegacyDNStringFormat
is set, the old format will be
+ used which sorts the "C" attribute first, uses slashes as separators, and
+ does not handle non-ASCII and special characters in any consistent way.
+
+
Example
SSLOptions +FakeBasicAuth -StrictRequire
diff --git a/docs/manual/upgrading.xml b/docs/manual/upgrading.xml
index a5f385da7ed..e2ce3f77397 100644
--- a/docs/manual/upgrading.xml
+++ b/docs/manual/upgrading.xml
@@ -236,6 +236,12 @@
mod_auto_index: will now extract titles and
display descriptions for .xhtml files, which were previously
ignored.
+
+ mod_ssl: The default format of the *_DN
+ variables has changed. The old format can still be used with the new
+ LegacyDNStringFormat
argument to SSLOptions.
+
htpasswd now uses MD5 hash by default on
all platforms.
diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c
index 4bccfe72d6b..029d3d77c53 100644
--- a/modules/ssl/ssl_engine_config.c
+++ b/modules/ssl/ssl_engine_config.c
@@ -1107,6 +1107,9 @@ const char *ssl_cmd_SSLOptions(cmd_parms *cmd,
else if (strcEQ(w, "OptRenegotiate")) {
opt = SSL_OPT_OPTRENEGOTIATE;
}
+ else if (strcEQ(w, "LegacyDNStringFormat")) {
+ opt = SSL_OPT_LEGACYDNFORMAT;
+ }
else {
return apr_pstrcat(cmd->pool,
"SSLOptions: Illegal option '", w, "'",
diff --git a/modules/ssl/ssl_engine_vars.c b/modules/ssl/ssl_engine_vars.c
index d5cf63ba32a..a8c0aef41f0 100644
--- a/modules/ssl/ssl_engine_vars.c
+++ b/modules/ssl/ssl_engine_vars.c
@@ -39,8 +39,8 @@
** _________________________________________________________________
*/
-static char *ssl_var_lookup_ssl(apr_pool_t *p, conn_rec *c, char *var);
-static char *ssl_var_lookup_ssl_cert(apr_pool_t *p, X509 *xs, char *var);
+static char *ssl_var_lookup_ssl(apr_pool_t *p, conn_rec *c, 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_valid(apr_pool_t *p, ASN1_UTCTIME *tm);
static char *ssl_var_lookup_ssl_cert_remain(apr_pool_t *p, ASN1_UTCTIME *tm);
@@ -73,7 +73,7 @@ static apr_array_header_t *expr_peer_ext_list_fn(ap_expr_eval_ctx_t *ctx,
static const char *expr_var_fn(ap_expr_eval_ctx_t *ctx, const void *data)
{
char *var = (char *)data;
- return ssl_var_lookup_ssl(ctx->p, ctx->c, var);
+ return ssl_var_lookup_ssl(ctx->p, ctx->c, ctx->r, var);
}
static int ssl_expr_lookup(ap_expr_lookup_parms *parms)
@@ -241,7 +241,7 @@ char *ssl_var_lookup(apr_pool_t *p, server_rec *s, conn_rec *c, request_rec *r,
SSLConnRec *sslconn = myConnConfig(c);
if (strlen(var) > 4 && strcEQn(var, "SSL_", 4)
&& sslconn && sslconn->ssl)
- result = ssl_var_lookup_ssl(p, c, var+4);
+ result = ssl_var_lookup_ssl(p, c, r, var+4);
else if (strcEQ(var, "REMOTE_ADDR"))
result = c->remote_ip;
else if (strcEQ(var, "HTTPS")) {
@@ -313,7 +313,8 @@ char *ssl_var_lookup(apr_pool_t *p, server_rec *s, conn_rec *c, request_rec *r,
return (char *)result;
}
-static char *ssl_var_lookup_ssl(apr_pool_t *p, conn_rec *c, char *var)
+static char *ssl_var_lookup_ssl(apr_pool_t *p, conn_rec *c, request_rec *r,
+ char *var)
{
SSLConnRec *sslconn = myConnConfig(c);
char *result;
@@ -358,13 +359,17 @@ static char *ssl_var_lookup_ssl(apr_pool_t *p, conn_rec *c, char *var)
}
else if (ssl != NULL && strlen(var) > 7 && strcEQn(var, "CLIENT_", 7)) {
if ((xs = SSL_get_peer_certificate(ssl)) != NULL) {
- result = ssl_var_lookup_ssl_cert(p, xs, var+7);
+ result = ssl_var_lookup_ssl_cert(p, r, xs, var+7);
X509_free(xs);
}
}
else if (ssl != NULL && strlen(var) > 7 && strcEQn(var, "SERVER_", 7)) {
- if ((xs = SSL_get_certificate(ssl)) != NULL)
- result = ssl_var_lookup_ssl_cert(p, xs, var+7);
+ if ((xs = SSL_get_certificate(ssl)) != NULL) {
+ result = ssl_var_lookup_ssl_cert(p, r, xs, var+7);
+ /* SSL_get_certificate is different from SSL_get_peer_certificate.
+ * No need to X509_free(xs).
+ */
+ }
}
else if (ssl != NULL && strcEQ(var, "COMPRESS_METHOD")) {
result = ssl_var_lookup_ssl_compress_meth(ssl);
@@ -386,13 +391,44 @@ static char *ssl_var_lookup_ssl(apr_pool_t *p, conn_rec *c, char *var)
return result;
}
-static char *ssl_var_lookup_ssl_cert(apr_pool_t *p, X509 *xs, char *var)
+static char *ssl_var_lookup_ssl_cert_dn_oneline(apr_pool_t *p, request_rec *r,
+ X509_NAME *xsname)
+{
+ char *result;
+ SSLDirConfigRec *dc;
+ int legacy_format = 0;
+ if (r) {
+ dc = myDirConfig(r);
+ legacy_format = dc->nOptions & SSL_OPT_LEGACYDNFORMAT;
+ }
+ if (legacy_format) {
+ char *cp = X509_NAME_oneline(xsname, NULL, 0);
+ result = apr_pstrdup(p, cp);
+ modssl_free(cp);
+ }
+ else {
+ BIO* bio;
+ int n;
+ unsigned long flags = XN_FLAG_RFC2253 & ~ASN1_STRFLGS_ESC_MSB;
+ if ((bio = BIO_new(BIO_s_mem())) == NULL)
+ return NULL;
+ X509_NAME_print_ex(bio, xsname, 0, flags);
+ n = BIO_pending(bio);
+ result = apr_palloc(p, n+1);
+ n = BIO_read(bio, result, n);
+ result[n] = NUL;
+ BIO_free(bio);
+ }
+ return result;
+}
+
+static char *ssl_var_lookup_ssl_cert(apr_pool_t *p, request_rec *r, X509 *xs,
+ char *var)
{
char *result;
BOOL resdup;
X509_NAME *xsname;
int nid;
- char *cp;
result = NULL;
resdup = TRUE;
@@ -414,27 +450,23 @@ static char *ssl_var_lookup_ssl_cert(apr_pool_t *p, X509 *xs, char *var)
result = ssl_var_lookup_ssl_cert_remain(p, X509_get_notAfter(xs));
resdup = FALSE;
}
- else if (strcEQ(var, "S_DN")) {
- xsname = X509_get_subject_name(xs);
- cp = X509_NAME_oneline(xsname, NULL, 0);
- result = apr_pstrdup(p, cp);
- modssl_free(cp);
- resdup = FALSE;
- }
- else if (strlen(var) > 5 && strcEQn(var, "S_DN_", 5)) {
- xsname = X509_get_subject_name(xs);
- result = ssl_var_lookup_ssl_cert_dn(p, xsname, var+5);
- resdup = FALSE;
- }
- else if (strcEQ(var, "I_DN")) {
- xsname = X509_get_issuer_name(xs);
- cp = X509_NAME_oneline(xsname, NULL, 0);
- result = apr_pstrdup(p, cp);
- modssl_free(cp);
+ else if (*var && strcEQ(var+1, "_DN")) {
+ if (*var == 'S')
+ xsname = X509_get_subject_name(xs);
+ else if (*var == 'I')
+ xsname = X509_get_issuer_name(xs);
+ else
+ return NULL;
+ result = ssl_var_lookup_ssl_cert_dn_oneline(p, r, xsname);
resdup = FALSE;
}
- else if (strlen(var) > 5 && strcEQn(var, "I_DN_", 5)) {
- xsname = X509_get_issuer_name(xs);
+ else if (strlen(var) > 5 && strcEQn(var+1, "_DN_", 4)) {
+ if (*var == 'S')
+ xsname = X509_get_subject_name(xs);
+ else if (*var == 'I')
+ xsname = X509_get_issuer_name(xs);
+ else
+ return NULL;
result = ssl_var_lookup_ssl_cert_dn(p, xsname, var+5);
resdup = FALSE;
}
@@ -516,13 +548,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) {
- unsigned char *data = X509_NAME_ENTRY_get_data_ptr(xsne);
- /* cast needed from unsigned char to char */
- result = apr_pstrmemdup(p, (char *)data,
- X509_NAME_ENTRY_get_data_len(xsne));
-#if APR_CHARSET_EBCDIC
- ap_xlate_proto_from_ascii(result, X509_NAME_ENTRY_get_data_len(xsne));
-#endif /* APR_CHARSET_EBCDIC */
+ result = SSL_X509_NAME_ENTRY_to_string(p, xsne);
break;
}
}
@@ -759,7 +785,6 @@ static void extract_dn(apr_table_t *t, apr_hash_t *nids, const char *pfx,
tag = apr_hash_get(nids, &nid, sizeof nid);
if (tag) {
- unsigned char *data = X509_NAME_ENTRY_get_data_ptr(xsne);
const char *key;
int *dup;
char *value;
@@ -776,13 +801,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);
}
-
- /* cast needed from 'unsigned char *' to 'char *' */
- value = apr_pstrmemdup(p, (char *)data,
- X509_NAME_ENTRY_get_data_len(xsne));
-#if APR_CHARSET_EBCDIC
- ap_xlate_proto_from_ascii(value, X509_NAME_ENTRY_get_data_len(xsne));
-#endif /* APR_CHARSET_EBCDIC */
+ value = SSL_X509_NAME_ENTRY_to_string(p, xsne);
apr_table_setn(t, key, value);
}
}
diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h
index ae344a141d1..d8d0cd27b78 100644
--- a/modules/ssl/ssl_private.h
+++ b/modules/ssl/ssl_private.h
@@ -230,7 +230,7 @@ typedef int ssl_algo_t;
#define SSL_OPT_FAKEBASICAUTH (1<<4)
#define SSL_OPT_STRICTREQUIRE (1<<5)
#define SSL_OPT_OPTRENEGOTIATE (1<<6)
-#define SSL_OPT_ALL (SSL_OPT_STDENVVARS|SSL_OPT_EXPORTCERTDATA|SSL_OPT_FAKEBASICAUTH|SSL_OPT_STRICTREQUIRE|SSL_OPT_OPTRENEGOTIATE)
+#define SSL_OPT_LEGACYDNFORMAT (1<<7)
typedef int ssl_opt_t;
/**
diff --git a/modules/ssl/ssl_util_ssl.c b/modules/ssl/ssl_util_ssl.c
index f44c707fa31..722ab01f6ca 100644
--- a/modules/ssl/ssl_util_ssl.c
+++ b/modules/ssl/ssl_util_ssl.c
@@ -344,14 +344,32 @@ BOOL SSL_X509_getBC(X509 *cert, int *ca, int *pathlen)
#endif
}
+/* convert a NAME_ENTRY to UTF8 string */
+char *SSL_X509_NAME_ENTRY_to_string(apr_pool_t *p, X509_NAME_ENTRY *xsne)
+{
+ char *result = NULL;
+ BIO* bio;
+ int len;
+
+ if ((bio = BIO_new(BIO_s_mem())) == NULL)
+ return NULL;
+ ASN1_STRING_print_ex(bio, X509_NAME_ENTRY_get_data(xsne),
+ ASN1_STRFLGS_ESC_CTRL|ASN1_STRFLGS_UTF8_CONVERT);
+ len = BIO_pending(bio);
+ result = apr_palloc(p, len+1);
+ len = BIO_read(bio, result, len);
+ result[len] = NUL;
+ BIO_free(bio);
+ ap_xlate_proto_from_ascii(value, len);
+ return result;
+}
+
/* retrieve subject CommonName of certificate */
BOOL SSL_X509_getCN(apr_pool_t *p, X509 *xs, char **cppCN)
{
X509_NAME *xsn;
X509_NAME_ENTRY *xsne;
int i, nid;
- unsigned char *data_ptr;
- int data_len;
xsn = X509_get_subject_name(xs);
for (i = 0; i < sk_X509_NAME_ENTRY_num((STACK_OF(X509_NAME_ENTRY) *)
@@ -360,12 +378,7 @@ BOOL SSL_X509_getCN(apr_pool_t *p, X509 *xs, char **cppCN)
X509_NAME_get_entries(xsn), i);
nid = OBJ_obj2nid((ASN1_OBJECT *)X509_NAME_ENTRY_get_object(xsne));
if (nid == NID_commonName) {
- data_ptr = X509_NAME_ENTRY_get_data_ptr(xsne);
- data_len = X509_NAME_ENTRY_get_data_len(xsne);
- *cppCN = apr_palloc(p, data_len+1);
- apr_cpystrn(*cppCN, (char *)data_ptr, data_len+1);
- (*cppCN)[data_len] = NUL;
- ap_xlate_proto_from_ascii(*cppCN, data_len);
+ *cppCN = SSL_X509_NAME_ENTRY_to_string(p, xsne);
return TRUE;
}
}
diff --git a/modules/ssl/ssl_util_ssl.h b/modules/ssl/ssl_util_ssl.h
index 04bcbdc2787..cabfb27c918 100644
--- a/modules/ssl/ssl_util_ssl.h
+++ b/modules/ssl/ssl_util_ssl.h
@@ -85,6 +85,7 @@ int SSL_X509_STORE_lookup(X509_STORE *, int, X509_NAME *, X509_OBJECT *)
char *SSL_make_ciphersuite(apr_pool_t *, SSL *);
BOOL SSL_X509_isSGC(X509 *);
BOOL SSL_X509_getBC(X509 *, int *, int *);
+char *SSL_X509_NAME_ENTRY_to_string(apr_pool_t *p, X509_NAME_ENTRY *xsne);
BOOL SSL_X509_getCN(apr_pool_t *, X509 *, char **);
BOOL SSL_X509_INFO_load_file(apr_pool_t *, STACK_OF(X509_INFO) *, const char *);
BOOL SSL_X509_INFO_load_path(apr_pool_t *, STACK_OF(X509_INFO) *, const char *);