httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Bill Barker" <wbar...@wilshire.com>
Subject Re: mod_ssl, SSL_CLIENT_CERT_CHAIN, mod_proxy_ajp and full chain of client certificates
Date Sun, 05 Oct 2008 22:59:20 GMT
Yes, while mod_jk has an option to send the cert chain (added a little over 
18 months ago by mturk), no Tomcat connector has an option to read it.  As a 
result, Tomcat will read the end certificate and ignore the rest of the 
chain.

This is because the AJP/1.3 protocol was created back in the days of 
Servlet-2.2 (corresponding to Tomcat 3.x) and back then only the end 
certificate was exposed by the Servlet-API.

Mladen's patch to mod_jk is simplier than this one, so I would prefer it to 
this one.  But I have no voting rights on this list :).

"Bruno Harbulot" <Bruno.Harbulot@manchester.ac.uk> wrote in message 
news:gbt26i$9p2$1@ger.gmane.org...
> Hello,
>
> I'm trying to use mod_proxy_ajp instead of mod_jk, but I'd like to be
> able to pass the whole client certificate chain, instead of only the end
> certificate. The servlet specification allows for a chain of
> certificates to be presented and this is indeed possible with mod_jk,
> using "JkOptions +ForwardSSLCertChain".
>
> This doesn't seem to be possible using mod_proxy_ajp, which uses the
> content of the SSL_CLIENT_CERT variable only.
>
> I thought I would be able to pass the chain using mod_headers.
> Unfortunately, there doesn't seem to be a mod_ssl variable that
> represents the whole chain. There is a set of variables called
> SSL_CLIENT_CERT_CHAIN_n (where n is an integer), but they have to be
> named individually.
>
> I'm attaching the patch I've written to provide a variable called
> SSL_CLIENT_CERT_CHAIN, which is the concatenation of all the
> certificates in the chain, in PEM format. (It also sets
> SSL_CLIENT_CERT_CHAIN_0 when there's no chain available but just one
> certificate.)
>
> A few tests with mod_headers "RequestHeader set X-ClientCertChain
> %{SSL_CLIENT_CERT_CHAIN}s" seem to indicate that it works.
>
> However, I've also tried to modify mod_proxy_ajp to send the whole
> chain, but this doesn't work:
>
> --- a/modules/proxy/ajp.h
> +++ b/modules/proxy/ajp.h
> @@ -60,7 +60,7 @@
>
>  /* The following environment variables match mod_ssl! */
>  #define AJP13_HTTPS_INDICATOR           "HTTPS"
> -#define AJP13_SSL_CLIENT_CERT_INDICATOR "SSL_CLIENT_CERT"
> +#define AJP13_SSL_CLIENT_CERT_INDICATOR "SSL_CLIENT_CERT_CHAIN"
>  #define AJP13_SSL_CIPHER_INDICATOR      "SSL_CIPHER"
>  #define AJP13_SSL_SESSION_INDICATOR     "SSL_SESSION_ID"
>  #define AJP13_SSL_KEY_SIZE_INDICATOR    "SSL_CIPHER_USEKEYSIZE"
>
> This patch has been made against the svn trunk, rev 695234.
>
>
> I'm aware that my knowledge of the Apache Httpd code is limited, so this
> patch is likely to need improvements (there's obviously something wrong
> since my modification to mod_proxy_ajp doesn't work).
> I'd appreciate any comments and suggestions.
>
>
> Best wishes,
>
> Bruno.
>


--------------------------------------------------------------------------------


> diff --git a/modules/ssl/ssl_engine_kernel.c 
> b/modules/ssl/ssl_engine_kernel.c
> index e938d05..894bef8 100644
> --- a/modules/ssl/ssl_engine_kernel.c
> +++ b/modules/ssl/ssl_engine_kernel.c
> @@ -1157,6 +1157,11 @@ int ssl_hook_Fixup(request_rec *r)
>                     apr_table_setn(env, var, val);
>                 }
>             }
> +        } else {
> +            val = ssl_var_lookup(r->pool, r->server, r->connection,
> +                                 r, "SSL_CLIENT_CERT");
> +
> +            apr_table_setn(env, "SSL_CLIENT_CERT_CHAIN_0", val);
>         }
>     }
>
> diff --git a/modules/ssl/ssl_engine_vars.c b/modules/ssl/ssl_engine_vars.c
> index 3d688cd..e191ddd 100644
> --- a/modules/ssl/ssl_engine_vars.c
> +++ b/modules/ssl/ssl_engine_vars.c
> @@ -46,6 +46,7 @@ static char *ssl_var_lookup_ssl_cert_remain(apr_pool_t 
> *p, ASN1_UTCTIME *tm);
> static char *ssl_var_lookup_ssl_cert_serial(apr_pool_t *p, X509 *xs);
> static char *ssl_var_lookup_ssl_cert_chain(apr_pool_t *p, STACK_OF(X509) 
> *sk, char *var);
> static char *ssl_var_lookup_ssl_cert_PEM(apr_pool_t *p, X509 *xs);
> +static char *ssl_var_lookup_ssl_cert_chain_PEM(apr_pool_t *p, 
> STACK_OF(X509) *sk);
> static char *ssl_var_lookup_ssl_cert_verify(apr_pool_t *p, conn_rec *c);
> static char *ssl_var_lookup_ssl_cipher(apr_pool_t *p, conn_rec *c, char 
> *var);
> static void  ssl_var_lookup_ssl_cipher_bits(SSL *ssl, int *usekeysize, int 
> *algkeysize);
> @@ -300,6 +301,10 @@ static char *ssl_var_lookup_ssl(apr_pool_t *p, 
> conn_rec *c, char *var)
>     else if (ssl != NULL && strlen(var) >= 6 && strcEQn(var, "CIPHER",
6)) 
> {
>         result = ssl_var_lookup_ssl_cipher(p, c, var+6);
>     }
> +    else if (ssl != NULL && strcEQ(var, "CLIENT_CERT_CHAIN")) {
> +        sk = SSL_get_peer_cert_chain(ssl);
> +        result = ssl_var_lookup_ssl_cert_chain(p, sk, NULL);
> +    }
>     else if (ssl != NULL && strlen(var) > 18 && strcEQn(var, 
> "CLIENT_CERT_CHAIN_", 18)) {
>         sk = SSL_get_peer_cert_chain(ssl);
>         result = ssl_var_lookup_ssl_cert_chain(p, sk, var+18);
> @@ -550,13 +555,18 @@ static char 
> *ssl_var_lookup_ssl_cert_chain(apr_pool_t *p, STACK_OF(X509) *sk, ch
>
>     result = NULL;
>
> -    if (strspn(var, "0123456789") == strlen(var)) {
> -        n = atoi(var);
> -        if (n < sk_X509_num(sk)) {
> -            xs = sk_X509_value(sk, n);
> -            result = ssl_var_lookup_ssl_cert_PEM(p, xs);
> +    if (var != NULL) {
> +        if (strspn(var, "0123456789") == strlen(var)) {
> +            n = atoi(var);
> +            if (n < sk_X509_num(sk)) {
> +                xs = sk_X509_value(sk, n);
> +                result = ssl_var_lookup_ssl_cert_PEM(p, xs);
> +            }
>         }
>     }
> +    else {
> +        result = ssl_var_lookup_ssl_cert_chain_PEM(p, sk);
> +    }
>
>     return result;
> }
> @@ -578,6 +588,28 @@ static char *ssl_var_lookup_ssl_cert_PEM(apr_pool_t 
> *p, X509 *xs)
>     return result;
> }
>
> +static char *ssl_var_lookup_ssl_cert_chain_PEM(apr_pool_t *p, 
> STACK_OF(X509) *sk)
> +{
> +    char *result;
> +    BIO *bio;
> +    X509 *xs;
> +    int n;
> +    int i;
> +
> +    if ((bio = BIO_new(BIO_s_mem())) == NULL)
> +        return NULL;
> +    for (i=0; i < sk_X509_num(sk); i++) {
> +        xs = sk_X509_value(sk, i);
> +        PEM_write_bio_X509(bio, xs);
> +    }
> +    n = BIO_pending(bio);
> +    result = apr_pcalloc(p, n+1);
> +    n = BIO_read(bio, result, n);
> +    result[n] = NUL;
> +    BIO_free(bio);
> +    return result;
> +}
> +
> static char *ssl_var_lookup_ssl_cert_verify(apr_pool_t *p, conn_rec *c)
> {
>     SSLConnRec *sslconn = myConnConfig(c);
> 




Mime
View raw message