Changeset 16ad0eb in mod_gnutls
- Timestamp:
- Jun 14, 2016, 2:40:13 PM (6 years ago)
- Branches:
- asyncio, debian/master, debian/stretch-backports, master, proxy-ticket, upstream
- Children:
- 82745d1
- Parents:
- 04addef
- Location:
- src
- Files:
-
- 2 added
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Makefile.am
r04addef r16ad0eb 7 7 8 8 mod_gnutls_la_SOURCES = mod_gnutls.c gnutls_io.c gnutls_cache.c \ 9 gnutls_config.c gnutls_hooks.c gnutls_ocsp.c 9 gnutls_config.c gnutls_hooks.c gnutls_ocsp.c gnutls_util.c 10 10 mod_gnutls_la_CFLAGS = -Wall ${MODULE_CFLAGS} 11 11 mod_gnutls_la_LDFLAGS = -module -avoid-version ${MODULE_LIBS} 12 noinst_HEADERS = gnutls_cache.h gnutls_ocsp.h 12 noinst_HEADERS = gnutls_cache.h gnutls_ocsp.h gnutls_util.h 13 13 14 14 apmodpkglib_LTLIBRARIES = mod_gnutls.la -
src/gnutls_ocsp.c
r04addef r16ad0eb 18 18 #include "mod_gnutls.h" 19 19 #include "gnutls_cache.h" 20 #include "gnutls_util.h" 20 21 21 22 #include <apr_escape.h> … … 28 29 APLOG_USE_MODULE(gnutls); 29 30 #endif 31 32 /* maximum supported OCSP response size, 8K should be plenty */ 33 #define OCSP_RESP_SIZE_MAX (8 * 1024) 34 #define OCSP_REQ_TYPE "application/ocsp-request" 35 #define OCSP_RESP_TYPE "application/ocsp-response" 30 36 31 37 … … 84 90 * Returns GNUTLS_E_SUCCESS, or a GnuTLS error code. 85 91 */ 86 int mgs_create_ocsp_request(server_rec *s, gnutls_datum_t *req,92 static int mgs_create_ocsp_request(server_rec *s, gnutls_datum_t *req, 87 93 gnutls_datum_t *nonce) 88 { 89 if (req == NULL || s == NULL) 90 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;91 94 __attribute__((nonnull(1, 2))); 95 static int mgs_create_ocsp_request(server_rec *s, gnutls_datum_t *req, 96 gnutls_datum_t *nonce) 97 { 92 98 mgs_srvconf_rec *sc = (mgs_srvconf_rec *) 93 99 ap_get_module_config(s->module_config, &gnutls_module); … … 168 174 return ret; 169 175 } 176 170 177 171 178 … … 348 355 349 356 357 static apr_status_t do_ocsp_request(apr_pool_t *p, server_rec *s, 358 gnutls_datum_t *request, 359 gnutls_datum_t *response) 360 __attribute__((nonnull)); 361 static apr_status_t do_ocsp_request(apr_pool_t *p, server_rec *s, 362 gnutls_datum_t *request, 363 gnutls_datum_t *response) 364 { 365 mgs_srvconf_rec *sc = (mgs_srvconf_rec *) 366 ap_get_module_config(s->module_config, &gnutls_module); 367 368 if (apr_strnatcmp(sc->ocsp->uri->scheme, "http")) 369 { 370 ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s, 371 "Scheme \"%s\" is not supported for OCSP requests!", 372 sc->ocsp->uri->scheme); 373 return APR_EINVAL; 374 } 375 376 const char* header = http_post_header(p, sc->ocsp->uri, 377 OCSP_REQ_TYPE, OCSP_RESP_TYPE, 378 request->size); 379 ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, s, 380 "OCSP POST header: %s", header); 381 382 /* Find correct port */ 383 apr_port_t port = sc->ocsp->uri->port ? 384 sc->ocsp->uri->port : apr_uri_port_of_scheme(sc->ocsp->uri->scheme); 385 386 apr_sockaddr_t *sa; 387 apr_status_t rv = apr_sockaddr_info_get(&sa, sc->ocsp->uri->hostname, 388 APR_UNSPEC, port, 0, p); 389 if (rv != APR_SUCCESS) 390 { 391 ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, 392 "Address resolution for OCSP responder %s failed.", 393 sc->ocsp->uri->hostinfo); 394 } 395 396 /* There may be multiple answers, try them in order until one 397 * works. */ 398 apr_socket_t *sock; 399 /* TODO: configurable timeout */ 400 apr_interval_time_t timeout = apr_time_from_sec(2); 401 while (sa) 402 { 403 rv = apr_socket_create(&sock, sa->family, SOCK_STREAM, 404 APR_PROTO_TCP, p); 405 if (rv == APR_SUCCESS) 406 { 407 apr_socket_timeout_set(sock, timeout); 408 rv = apr_socket_connect(sock, sa); 409 if (rv == APR_SUCCESS) 410 /* Connected! */ 411 break; 412 apr_socket_close(sock); 413 } 414 sa = sa->next; 415 } 416 /* If the socket is connected, 'sa' points at the matching 417 * address. */ 418 if (sa == NULL) 419 { 420 ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, 421 "Connecting to OCSP responder %s failed.", 422 sc->ocsp->uri->hostinfo); 423 return rv; 424 } 425 426 /* Header is generated locally, so strlen() is safe. */ 427 rv = sock_send_buf(sock, header, strlen(header)); 428 if (rv == APR_SUCCESS) 429 rv = sock_send_buf(sock, (char*) request->data, request->size); 430 /* catches errors from both header and request */ 431 if (rv != APR_SUCCESS) 432 { 433 ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, 434 "Sending OCSP request failed."); 435 goto exit; 436 } 437 438 /* Prepare bucket brigades to read the response header. BBs make 439 * it easy to split the header into lines. */ 440 apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p); 441 apr_bucket_brigade *bb = apr_brigade_create(p, ba); 442 /* will carry split response headers */ 443 apr_bucket_brigade *rh = apr_brigade_create(p, ba); 444 445 APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_socket_create(sock, ba)); 446 /* The first line in the response header must be the status, check 447 * for OK status code. Line looks similar to "HTTP/1.0 200 OK". */ 448 const char *h = read_line(p, bb, rh); 449 const char *code = 0; 450 if (h == NULL 451 || strncmp(h, "HTTP/", 5) 452 || (code = ap_strchr(h, ' ')) == NULL 453 || apr_atoi64(code + 1) != HTTP_OK) 454 { 455 ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, 456 "Invalid HTTP response status from %s: %s", 457 sc->ocsp->uri->hostinfo, h); 458 rv = APR_ECONNRESET; 459 goto exit; 460 } 461 /* Read remaining header lines */ 462 for (h = read_line(p, bb, rh); h != NULL && apr_strnatcmp(h, "") != 0; 463 h = read_line(p, bb, rh)) 464 { 465 ap_log_error(APLOG_MARK, APLOG_TRACE2, APR_SUCCESS, s, 466 "Received header: %s", h); 467 } 468 /* The last header line should be empty (""), NULL indicates an 469 * error. */ 470 if (h == NULL) 471 { 472 ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, 473 "Error while reading HTTP response header from %s", 474 sc->ocsp->uri->hostinfo); 475 rv = APR_ECONNRESET; 476 goto exit; 477 } 478 479 /* Headers have been consumed, the rest of the available data 480 * should be the actual response. */ 481 apr_size_t len = OCSP_RESP_SIZE_MAX; 482 char buf[OCSP_RESP_SIZE_MAX]; 483 /* apr_brigade_pflatten() can allocate directly from the pool, but 484 * the documentation does not describe a way to limit the size of 485 * the buffer, which is necessary here to prevent DoS by endless 486 * response. Use apr_brigade_flatten() to read to a stack pool, 487 * then create a copy to return. */ 488 rv = apr_brigade_flatten(bb, buf, &len); 489 if (rv != APR_SUCCESS) 490 { 491 ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, 492 "Failed to read OCSP response."); 493 goto exit; 494 } 495 496 /* With the length restriction this really should not happen. */ 497 if (__builtin_add_overflow(len, 0, &response->size)) 498 { 499 response->data = NULL; 500 rv = APR_ENOMEM; 501 } 502 else 503 { 504 response->data = apr_pmemdup(p, buf, len); 505 } 506 507 exit: 508 apr_socket_close(sock); 509 return rv; 510 } 511 512 513 350 514 apr_status_t mgs_cache_ocsp_response(server_rec *s) 351 515 { … … 369 533 } 370 534 371 /* TODO: actually send this request to sc->ocsp->uri and parse the372 * received response (including nonce) */373 535 gnutls_datum_t req; 374 536 int ret = mgs_create_ocsp_request(s, &req, NULL); … … 382 544 } 383 545 384 ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, s, 385 "Loading OCSP response from %s", 386 sc->ocsp_response_file); 387 apr_file_t *file; 388 apr_finfo_t finfo; 389 apr_size_t br = 0; 390 rv = apr_file_open(&file, sc->ocsp_response_file, 391 APR_READ | APR_BINARY, APR_OS_DEFAULT, tmp); 546 gnutls_datum_t resp; 547 rv = do_ocsp_request(tmp, s, &req, &resp); 392 548 if (rv != APR_SUCCESS) 393 549 { 550 /* do_ocsp_request() does its own error logging. */ 394 551 apr_pool_destroy(tmp); 395 552 return rv; 396 553 } 397 rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, file); 398 if (rv != APR_SUCCESS) 399 { 400 apr_pool_destroy(tmp); 401 return rv; 402 } 403 404 gnutls_datum_t resp; 405 resp.data = apr_palloc(tmp, finfo.size); 406 rv = apr_file_read_full(file, resp.data, finfo.size, &br); 407 if (rv != APR_SUCCESS) 408 { 409 apr_pool_destroy(tmp); 410 return rv; 411 } 412 apr_file_close(file); 413 /* safe integer type conversion */ 414 if (__builtin_add_overflow(br, 0, &resp.size)) 415 { 416 apr_pool_destroy(tmp); 417 return APR_EINVAL; 418 } 554 /* TODO: check nonce */ 555 556 /* TODO: separate option to enable/disable OCSP stapling, restore 557 * reading response from file for debugging/expert use. */ 419 558 420 559 apr_time_t expiry;
Note: See TracChangeset
for help on using the changeset viewer.