Commit c2078ecc authored by Rainer Jung's avatar Rainer Jung
Browse files

Merge r833582, r833593, r881222 from trunk:

SECURITY: Partial fix for CVE-2009-3555:

Reject client-initiated renegotiations; this is sufficient to prevent
the attack for any configuration which does not require renegotiation
due to per-directory/per-location access control configuration.

Configuration with per-directory/per-location access control
requirements (such as "SSLVerifyClient require") are still vulnerable
to CVE-2009-3555 with this patch applied (if using OpenSSL != 0.9.8l).

* modules/ssl/ssl_private.h (SSLConnRec): Add reneg_state field.
  (ssl_callback_Info): Renamed from ssl_callback_LogTracingState.

* modules/ssl/ssl_engine_init.c (ssl_init_ctx_callbacks): Install
  the (renamed) info callback unconditionally.

* modules/ssl/ssl_engine_io.c (ssl_filter_ctx_t): Add config pointer
  to SSLConnRec.
  (bio_filter_out_write, bio_filter_in_read): Fail with
  APR_ECONNABORTED if the reneg state is set to RENEG_ABORT.

* modules/ssl/ssl_engine_kernel.c (log_tracing_state): Factored out
  of ssl_callback_LogTracingState.
  (ssl_callback_Info): New function.

Submitted by: jorton, rpluem, rjung
Reviewed by: rjung, rpluem, pgollucci


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.0.x@943879 13f79535-47bb-0310-9956-ffa450edef68
parent f12ccb85
Loading
Loading
Loading
Loading
+8 −0
Changes for CHANGES: 8 added lines, 0 removed lines.
Original line number Diff line number Diff line
                                                         -*- coding: utf-8 -*-
Changes with Apache 2.0.64

  *) SECURITY: CVE-2009-3555 (cve.mitre.org)
     mod_ssl: A partial fix for the TLS renegotiation prefix injection attack
     for OpenSSL versions prior to 0.9.8l; reject any client-initiated
     renegotiations. Any configuration which requires renegotiation for
     per-directory/location access control is still vulnerable, unless using
     OpenSSL 0.9.8l or later.
     [Joe Orton, Ruediger Pluem, Rainer Jung]

  *) SECURITY: CVE-2010-0434 (cve.mitre.org)
     Ensure each subrequest has a shallow copy of headers_in so that the
     parent request headers are not corrupted.  Elimiates a problematic
+0 −10
Changes for STATUS: 0 added lines, 10 removed lines.
Original line number Diff line number Diff line
@@ -124,16 +124,6 @@ PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
    Backport version for 2.0.x of patch:
       http://people.apache.org/~fuankg/diffs/httpd-2.0.x-ap_vhost_iterate_given_conn.diff
    +1: fuankg, wrowe, pgollucci
  * mod_ssl: Partial fix for CVE-2009-3555
    Trunk version of patch:
      http://svn.apache.org/viewvc?rev=833582&view=rev
      http://svn.apache.org/viewvc?rev=833593&view=rev
      http://svn.apache.org/viewvc?rev=881222&view=rev
    Patch in 2.2.x branch:
      http://svn.apache.org/viewvc?rev=833622&view=rev
    Backport version for 2.0.x of patch (Updated with backport of r881222):
      http://people.apache.org/~rjung/patches/cve-2009-3555_httpd_2_0_x-v2.patch
    +1: rjung, rpluem, pgollucci (+1 2.0.64 w/ this)

PATCHES PROPOSED TO BACKPORT FROM TRUNK:
  [ please place SVN revisions from trunk here, so it is easy to
+14 −1
Changes for modules/ssl/mod_ssl.h: 14 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -389,6 +389,19 @@ typedef struct {
    int is_proxy;
    int disabled;
    int non_ssl_request;

    /* Track the handshake/renegotiation state for the connection so
     * that all client-initiated renegotiations can be rejected, as a
     * partial fix for CVE-2009-3555. */
    enum {
        RENEG_INIT = 0, /* Before initial handshake */
        RENEG_REJECT, /* After initial handshake; any client-initiated
                       * renegotiation should be rejected */
        RENEG_ALLOW, /* A server-initated renegotiation is taking
                      * place (as dictated by configuration) */
        RENEG_ABORT /* Renegotiation initiated by client, abort the
                     * connection */
    } reneg_state;
} SSLConnRec;

typedef struct {
@@ -585,7 +598,7 @@ int ssl_callback_proxy_cert(SSL *ssl, MODSSL_CLIENT_CERT_CB_ARG_TYPE **
int          ssl_callback_NewSessionCacheEntry(SSL *, SSL_SESSION *);
SSL_SESSION *ssl_callback_GetSessionCacheEntry(SSL *, unsigned char *, int, int *);
void         ssl_callback_DelSessionCacheEntry(SSL_CTX *, SSL_SESSION *);
void         ssl_callback_LogTracingState(MODSSL_INFO_CB_ARG_TYPE, int, int);
void         ssl_callback_Info(MODSSL_INFO_CB_ARG_TYPE, int, int);

/*  Session Cache Support  */
void         ssl_scache_init(server_rec *, apr_pool_t *);
+1 −4
Changes for modules/ssl/ssl_engine_init.c: 1 added line, 4 removed lines.
Original line number Diff line number Diff line
@@ -464,10 +464,7 @@ static void ssl_init_ctx_callbacks(server_rec *s,
    SSL_CTX_set_tmp_rsa_callback(ctx, ssl_callback_TmpRSA);
    SSL_CTX_set_tmp_dh_callback(ctx,  ssl_callback_TmpDH);

    if (s->loglevel >= APLOG_DEBUG) {
        /* this callback only logs if LogLevel >= info */
        SSL_CTX_set_info_callback(ctx, ssl_callback_LogTracingState);
    }
    SSL_CTX_set_info_callback(ctx, ssl_callback_Info);
}

static void ssl_init_ctx_verify(server_rec *s,
+15 −0
Changes for modules/ssl/ssl_engine_io.c: 15 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -102,6 +102,7 @@ typedef struct {
    ap_filter_t        *pInputFilter;
    ap_filter_t        *pOutputFilter;
    int                nobuffer; /* non-zero to prevent buffering */
    SSLConnRec         *config;
} ssl_filter_ctx_t;

typedef struct {
@@ -193,6 +194,12 @@ static int bio_filter_out_write(BIO *bio, const char *in, int inl)
{
    bio_filter_out_ctx_t *outctx = (bio_filter_out_ctx_t *)(bio->ptr);
    
    /* Abort early if the client has initiated a renegotiation. */
    if (outctx->filter_ctx->config->reneg_state == RENEG_ABORT) {
        outctx->rc = APR_ECONNABORTED;
        return -1;
    }
    
    /* when handshaking we'll have a small number of bytes.
     * max size SSL will pass us here is about 16k.
     * (16413 bytes to be exact)
@@ -465,6 +472,12 @@ static int bio_filter_in_read(BIO *bio, char *in, int inlen)
    if (!in)
        return 0;

    /* Abort early if the client has initiated a renegotiation. */
    if (inctx->filter_ctx->config->reneg_state == RENEG_ABORT) {
        inctx->rc = APR_ECONNABORTED;
        return -1;
    }

    /* XXX: flush here only required for SSLv2;
     * OpenSSL calls BIO_flush() at the appropriate times for
     * the other protocols.
@@ -1585,6 +1598,8 @@ void ssl_io_filter_init(conn_rec *c, SSL *ssl)

    filter_ctx = apr_palloc(c->pool, sizeof(ssl_filter_ctx_t));

    filter_ctx->config          = myConnConfig(c);

    filter_ctx->nobuffer        = 0;
    filter_ctx->pOutputFilter   = ap_add_output_filter(ssl_io_filter,
                                                   filter_ctx, NULL, c);
Loading