diff options
author | Stefan Fritsch <sf@apache.org> | 2011-01-01 23:56:24 +0000 |
---|---|---|
committer | Stefan Fritsch <sf@apache.org> | 2011-01-01 23:56:24 +0000 |
commit | 7403827278ff4dc120b59f83c5237050a922ecd2 (patch) | |
tree | 830013733bbb1c49439b4d29d0717660354d97ee | |
parent | 01755ffe635ad69bfb74871b4bdc36e228bfeb5a (diff) | |
download | httpd-7403827278ff4dc120b59f83c5237050a922ecd2.tar.gz |
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
-rw-r--r-- | CHANGES | 5 | ||||
-rw-r--r-- | docs/manual/mod/mod_ssl.xml | 19 | ||||
-rw-r--r-- | docs/manual/upgrading.xml | 6 | ||||
-rw-r--r-- | modules/ssl/ssl_engine_config.c | 3 | ||||
-rw-r--r-- | modules/ssl/ssl_engine_vars.c | 107 | ||||
-rw-r--r-- | modules/ssl/ssl_private.h | 2 | ||||
-rw-r--r-- | modules/ssl/ssl_util_ssl.c | 29 | ||||
-rw-r--r-- | modules/ssl/ssl_util_ssl.h | 1 |
8 files changed, 119 insertions, 53 deletions
@@ -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 13f0a969ea..4cbb1ba266 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, <code>SSL_SERVER_S_DN_OU_0</code> and <code>SSL_SERVER_S_DN_OU_1</code> could be used to reference each.</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> + <p><code>SSL_CLIENT_V_REMAIN</code> is only available in version 2.1 and later.</p> @@ -1181,6 +1185,21 @@ The available <em>option</em>s are:</p> checks sometimes maybe not what the user expects, so enable this on a per-directory basis only, please.</p> </li> +<li><code>LegacyDNStringFormat</code> + <p> + This option influences how values of the + <code>SSL_{CLIENT,SERVER}_{I,S}_DN</code> 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.</p> + + <p>If <code>LegacyDNStringFormat</code> 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. + </p> +</li> </ul> <example><title>Example</title> SSLOptions +FakeBasicAuth -StrictRequire<br /> diff --git a/docs/manual/upgrading.xml b/docs/manual/upgrading.xml index a5f385da7e..e2ce3f7739 100644 --- a/docs/manual/upgrading.xml +++ b/docs/manual/upgrading.xml @@ -236,6 +236,12 @@ <li><module>mod_auto_index</module>: will now extract titles and display descriptions for .xhtml files, which were previously ignored.</li> + + <li><module>mod_ssl</module>: The default format of the <code>*_DN</code> + variables has changed. The old format can still be used with the new + <code>LegacyDNStringFormat</code> argument to <directive + module="mod_ssl">SSLOptions</directive>.</li> + <li><program>htpasswd</program> now uses MD5 hash by default on all platforms.</li> diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c index 4bccfe72d6..029d3d77c5 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 d5cf63ba32..a8c0aef41f 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 ae344a141d..d8d0cd27b7 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 f44c707fa3..722ab01f6c 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 04bcbdc278..cabfb27c91 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 *); |