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_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "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_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, |
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_rerror(APLOG_MARK, APLOG_DEBUG, 0, f->r, |
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_rerror(APLOG_MARK, APLOG_ERR, rv, f->r, |
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_rerror(APLOG_MARK, APLOG_ERR, rv, f->r, |
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_rerror(APLOG_MARK, APLOG_DEBUG, 0, f->r, |
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 |
|