View | Details | Raw Unified | Return to bug 12355
Collapse All | Expand All

(-)modules/ssl/ssl_engine_io.c (+185 lines)
Lines 880-885 Link Here
880
}
880
}
881
881
882
static const char ssl_io_filter[] = "SSL/TLS Filter";
882
static const char ssl_io_filter[] = "SSL/TLS Filter";
883
static const char ssl_io_buffer[] = "SSL/TLS Buffer";
883
884
884
/*
885
/*
885
 *  Close the SSL part of the socket connection
886
 *  Close the SSL part of the socket connection
Lines 1373-1378 Link Here
1373
    return status;
1374
    return status;
1374
}
1375
}
1375
1376
1377
/* 128K maximum buffer size by default. */
1378
#ifndef SSL_MAX_IO_BUFFER
1379
#define SSL_MAX_IO_BUFFER (128 * 1024)
1380
#endif
1381
1382
struct modssl_buffer_ctx {
1383
    apr_bucket_brigade *bb;
1384
    apr_pool_t *pool;
1385
};
1386
1387
int ssl_io_buffer_fill(request_rec *r)
1388
{
1389
    conn_rec *c = r->connection;
1390
    struct modssl_buffer_ctx *ctx;
1391
    apr_bucket_brigade *tempb;
1392
    apr_off_t total = 0; /* total length buffered */
1393
    int eos = 0; /* non-zero once EOS is seen */
1394
    
1395
    /* Create the context which will be passed to the input filter;
1396
     * containing a setaside pool and a brigade which constrain the
1397
     * lifetime of the buffered data. */
1398
    ctx = apr_palloc(r->pool, sizeof *ctx);
1399
    apr_pool_create(&ctx->pool, r->pool);
1400
    ctx->bb = apr_brigade_create(ctx->pool, c->bucket_alloc);
1401
1402
    /* ... and a temporary brigade. */
1403
    tempb = apr_brigade_create(r->pool, c->bucket_alloc);
1404
1405
    ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, "filling buffer");
1406
1407
    do {
1408
        apr_status_t rv;
1409
        apr_bucket *e, *next;
1410
1411
        /* The request body is read from the protocol-level input
1412
         * filters; the buffering filter will reinject it from that
1413
         * level, allowing content/resource filters to run later, if
1414
         * necessary. */
1415
1416
        rv = ap_get_brigade(r->proto_input_filters, tempb, AP_MODE_READBYTES,
1417
                            APR_BLOCK_READ, 8192);
1418
        if (rv) {
1419
            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
1420
                          "could not read request body for SSL buffer");
1421
            return HTTP_INTERNAL_SERVER_ERROR;
1422
        }
1423
        
1424
        /* Iterate through the returned brigade: setaside each bucket
1425
         * into the context's pool and move it into the brigade. */
1426
        for (e = APR_BRIGADE_FIRST(tempb); 
1427
             e != APR_BRIGADE_SENTINEL(tempb) && !eos; e = next) {
1428
            const char *data;
1429
            apr_size_t len;
1430
1431
            next = APR_BUCKET_NEXT(e);
1432
1433
            if (APR_BUCKET_IS_EOS(e)) {
1434
                eos = 1;
1435
            } else if (!APR_BUCKET_IS_METADATA(e)) {
1436
                rv = apr_bucket_read(e, &data, &len, APR_BLOCK_READ);
1437
                if (rv != APR_SUCCESS) {
1438
                    ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
1439
                                  "could not read bucket for SSL buffer");
1440
                    return HTTP_INTERNAL_SERVER_ERROR;
1441
                }
1442
                total += len;
1443
            }
1444
                
1445
            rv = apr_bucket_setaside(e, ctx->pool);
1446
            if (rv != APR_SUCCESS) {
1447
                ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
1448
                              "could not setaside bucket for SSL buffer");
1449
                return HTTP_INTERNAL_SERVER_ERROR;
1450
            }
1451
            
1452
            APR_BUCKET_REMOVE(e);
1453
            APR_BRIGADE_INSERT_TAIL(ctx->bb, e);
1454
        }
1455
1456
        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, 
1457
                      "total of %" APR_OFF_T_FMT " bytes in buffer, eos=%d",
1458
                      total, eos);
1459
1460
        /* Fail if this exceeds the maximum buffer size. */
1461
        if (total > SSL_MAX_IO_BUFFER) {
1462
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
1463
                          "request body exceeds maximum size for SSL buffer");
1464
            return HTTP_REQUEST_ENTITY_TOO_LARGE;
1465
        }
1466
1467
    } while (!eos);
1468
1469
    apr_brigade_destroy(tempb);
1470
1471
    /* Insert the filter which will supply the buffered data. */
1472
    ap_add_input_filter(ssl_io_buffer, ctx, r, c);
1473
1474
    return 0;
1475
}
1476
1477
/* This input filter supplies the buffered request body to the caller
1478
 * from the brigade stored in f->ctx. */
1479
static apr_status_t ssl_io_filter_buffer(ap_filter_t *f,
1480
                                         apr_bucket_brigade *bb,
1481
                                         ap_input_mode_t mode,
1482
                                         apr_read_type_e block,
1483
                                         apr_off_t bytes)
1484
{
1485
    struct modssl_buffer_ctx *ctx = f->ctx;
1486
    apr_status_t rv;
1487
1488
    ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, f->c,
1489
                  "read from buffered SSL brigade, mode %d, "
1490
                  "%" APR_OFF_T_FMT " bytes",
1491
                  mode, bytes);
1492
1493
    if (mode != AP_MODE_READBYTES && mode != AP_MODE_GETLINE) {
1494
        return APR_ENOTIMPL;
1495
    }
1496
1497
    if (mode == AP_MODE_READBYTES) {
1498
        apr_bucket *e;
1499
1500
        /* Partition the buffered brigade. */
1501
        rv = apr_brigade_partition(ctx->bb, bytes, &e);
1502
        if (rv && rv != APR_INCOMPLETE) {
1503
            ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, f->c,
1504
                          "could not partition buffered SSL brigade");
1505
            ap_remove_input_filter(f);
1506
            return rv;
1507
        }
1508
1509
        /* If the buffered brigade contains less then the requested
1510
         * length, just pass it all back. */
1511
        if (rv == APR_INCOMPLETE) {
1512
            APR_BRIGADE_CONCAT(bb, ctx->bb);
1513
        } else {
1514
            apr_bucket *d = APR_BRIGADE_FIRST(ctx->bb);
1515
1516
            e = APR_BUCKET_PREV(e);
1517
            
1518
            /* Unsplice the partitioned segment and move it into the
1519
             * passed-in brigade; no convenient way to do this with
1520
             * the APR_BRIGADE_* macros. */
1521
            APR_RING_UNSPLICE(d, e, link);
1522
            APR_RING_SPLICE_HEAD(&bb->list, d, e, apr_bucket, link);
1523
1524
            APR_BRIGADE_CHECK_CONSISTENCY(bb);
1525
            APR_BRIGADE_CHECK_CONSISTENCY(ctx->bb);
1526
        }
1527
    }
1528
    else {
1529
        /* Split a line into the passed-in brigade. */
1530
        rv = apr_brigade_split_line(bb, ctx->bb, mode, bytes);
1531
1532
        if (rv) {
1533
            ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, f->c,
1534
                          "could not split line from buffered SSL brigade");
1535
            ap_remove_input_filter(f);
1536
            return rv;
1537
        }
1538
    }
1539
1540
    if (APR_BRIGADE_EMPTY(ctx->bb)) {
1541
        apr_bucket *e = APR_BRIGADE_LAST(bb);
1542
        
1543
        /* Ensure that the brigade is terminated by an EOS if the
1544
         * buffered request body has been entirely consumed. */
1545
        if (e == APR_BRIGADE_SENTINEL(bb) || !APR_BUCKET_IS_EOS(e)) {
1546
            e = apr_bucket_eos_create(f->c->bucket_alloc);
1547
            APR_BRIGADE_INSERT_TAIL(bb, e);
1548
        }
1549
1550
        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, f->c,
1551
                      "buffered SSL brigade now exhausted; removing filter");
1552
        ap_remove_input_filter(f);
1553
    }
1554
1555
    return APR_SUCCESS;
1556
}
1557
1376
static void ssl_io_input_add_filter(ssl_filter_ctx_t *filter_ctx, conn_rec *c,
1558
static void ssl_io_input_add_filter(ssl_filter_ctx_t *filter_ctx, conn_rec *c,
1377
                                    SSL *ssl)
1559
                                    SSL *ssl)
1378
{
1560
{
Lines 1429-1434 Link Here
1429
{
1611
{
1430
    ap_register_input_filter  (ssl_io_filter, ssl_io_filter_input,  NULL, AP_FTYPE_CONNECTION + 5);
1612
    ap_register_input_filter  (ssl_io_filter, ssl_io_filter_input,  NULL, AP_FTYPE_CONNECTION + 5);
1431
    ap_register_output_filter (ssl_io_filter, ssl_io_filter_output, NULL, AP_FTYPE_CONNECTION + 5);
1613
    ap_register_output_filter (ssl_io_filter, ssl_io_filter_output, NULL, AP_FTYPE_CONNECTION + 5);
1614
    
1615
    ap_register_input_filter  (ssl_io_buffer, ssl_io_filter_buffer, NULL, AP_FTYPE_PROTOCOL - 1);
1616
1432
    return;
1617
    return;
1433
}
1618
}
1434
1619
(-)modules/ssl/ssl_engine_kernel.c (-65 / +27 lines)
Lines 490-562 Link Here
490
    }
490
    }
491
#endif /* HAVE_SSL_SET_CERT_STORE */
491
#endif /* HAVE_SSL_SET_CERT_STORE */
492
492
493
    /* 
493
    /* If a renegotiation is now required for this location, and the
494
     * SSL renegotiations in conjunction with HTTP
494
     * request includes a message body (and the client has not
495
     * requests using the POST method are not supported.
495
     * requested a "100 Continue" response), then the client will be
496
     *
496
     * streaming the request body over the wire already.  In that
497
     * Background:
497
     * case, it is not possible to stop and perform a new SSL
498
     *
498
     * handshake immediately; once the SSL library moves to the
499
     * 1. When the client sends a HTTP/HTTPS request, Apache's core code
499
     * "accept" state, it will reject the SSL packets which the client
500
     * reads only the request line ("METHOD /path HTTP/x.y") and the
500
     * is sending for the request body.
501
     * attached MIME headers ("Foo: bar") up to the terminating line ("CR
501
     * 
502
     * LF"). An attached request body (for instance the data of a POST
502
     * To allow authentication to complete in this auth hook, the
503
     * method) is _NOT_ read. Instead it is read by mod_cgi's content
503
     * solution used here is to fill a (bounded) buffer with the
504
     * handler and directly passed to the CGI script.
504
     * request body, and then to reinject that request body later.
505
     *
506
     * 2. mod_ssl supports per-directory re-configuration of SSL parameters.
507
     * This is implemented by performing an SSL renegotiation of the
508
     * re-configured parameters after the request is read, but before the
509
     * response is sent. In more detail: the renegotiation happens after the
510
     * request line and MIME headers were read, but _before_ the attached
511
     * request body is read. The reason simply is that in the HTTP protocol
512
     * usually there is no acknowledgment step between the headers and the
513
     * body (there is the 100-continue feature and the chunking facility
514
     * only), so Apache has no API hook for this step.
515
     *
516
     * 3. the problem now occurs when the client sends a POST request for
517
     * URL /foo via HTTPS the server and the server has SSL parameters
518
     * re-configured on a per-URL basis for /foo. Then mod_ssl has to
519
     * perform an SSL renegotiation after the request was read and before
520
     * the response is sent. But the problem is the pending POST body data
521
     * in the receive buffer of SSL (which Apache still has not read - it's
522
     * pending until mod_cgi sucks it in). When mod_ssl now tries to perform
523
     * the renegotiation the pending data leads to an I/O error.
524
     *
525
     * Solution Idea:
526
     *
527
     * There are only two solutions: Either to simply state that POST
528
     * requests to URLs with SSL re-configurations are not allowed, or to
529
     * renegotiate really after the _complete_ request (i.e. including
530
     * the POST body) was read. Obviously the latter would be preferred,
531
     * but it cannot be done easily inside Apache, because as already
532
     * mentioned, there is no API step between the body reading and the body
533
     * processing. And even when we mod_ssl would hook directly into the
534
     * loop of mod_cgi, we wouldn't solve the problem for other handlers, of
535
     * course. So the only general solution is to suck in the pending data
536
     * of the request body from the OpenSSL BIO into the Apache BUFF. Then
537
     * the renegotiation can be done and after this step Apache can proceed
538
     * processing the request as before.
539
     *
540
     * Solution Implementation:
541
     *
542
     * We cannot simply suck in the data via an SSL_read-based loop because of
543
     * HTTP chunking. Instead we _have_ to use the Apache API for this step which
544
     * is aware of HTTP chunking. So the trick is to suck in the pending request
545
     * data via the Apache API (which uses Apache's BUFF code and in the
546
     * background mod_ssl's I/O glue code) and re-inject it later into the Apache
547
     * BUFF code again. This way the data flows twice through the Apache BUFF, of
548
     * course. But this way the solution doesn't depend on any Apache specifics
549
     * and is fully transparent to Apache modules.
550
     *
551
     * !! BUT ALL THIS IS STILL NOT RE-IMPLEMENTED FOR APACHE 2.0 !!
552
     */
505
     */
553
    if (renegotiate && !renegotiate_quick && (r->method_number == M_POST)) {
506
    if (renegotiate && !renegotiate_quick
554
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
507
        && (apr_table_get(r->headers_in, "transfer-encoding")
555
                     "SSL Re-negotiation in conjunction "
508
            || (apr_table_get(r->headers_in, "content-length")
556
                     "with POST method not supported! "
509
                && strcmp(apr_table_get(r->headers_in, "content-length"), "0")))
557
                     "hint: try SSLOptions +OptRenegotiate");
510
        && !r->expecting_100) {
511
        int rv;
558
512
559
        return HTTP_METHOD_NOT_ALLOWED;
513
        /* Fill the I/O buffer with the request body if possible. */
514
        rv = ssl_io_buffer_fill(r);
515
516
        if (rv) {
517
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
518
                          "could not buffer message body to allow "
519
                          "SSL renegotiation to proceed");
520
            return rv;
521
        }
560
    }
522
    }
561
523
562
    /*
524
    /*
(-)modules/ssl/mod_ssl.h (+4 lines)
Lines 683-688 Link Here
683
void         ssl_io_filter_register(apr_pool_t *);
683
void         ssl_io_filter_register(apr_pool_t *);
684
long         ssl_io_data_cb(BIO *, int, MODSSL_BIO_CB_ARG_TYPE *, int, long, long);
684
long         ssl_io_data_cb(BIO *, int, MODSSL_BIO_CB_ARG_TYPE *, int, long, long);
685
685
686
/* ssl_io_buffer_fill fills the setaside buffering of the HTTP request
687
  * to allow an SSL renegotiation to take place. */
688
int          ssl_io_buffer_fill(request_rec *r);
689
686
/*  PRNG  */
690
/*  PRNG  */
687
int          ssl_rand_seed(server_rec *, apr_pool_t *, ssl_rsctx_t, char *);
691
int          ssl_rand_seed(server_rec *, apr_pool_t *, ssl_rsctx_t, char *);
688
692

Return to bug 12355