diff options
| author | beck <> | 2016-11-02 15:18:42 +0000 |
|---|---|---|
| committer | beck <> | 2016-11-02 15:18:42 +0000 |
| commit | 5418ce1f48164f4ba5618463049fa69568460f4f (patch) | |
| tree | d759e28afc9aedffba6861487c1680a3f8e3331d /src | |
| parent | cc11de9530a463cf1046e63cc0a8b635aa93cdae (diff) | |
| download | openbsd-5418ce1f48164f4ba5618463049fa69568460f4f.tar.gz openbsd-5418ce1f48164f4ba5618463049fa69568460f4f.tar.bz2 openbsd-5418ce1f48164f4ba5618463049fa69568460f4f.zip | |
Add OCSP client side support to libtls.
- Provide access to certificate OCSP URL
- Provide ability to check a raw OCSP reply against an
established TLS ctx
- Check and validate OCSP stapling info in the TLS handshake
if a stapled OCSP response is provided.`
Add example code to show OCSP URL and stapled info
into netcat.
ok jsing@
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/libtls/Makefile | 3 | ||||
| -rw-r--r-- | src/lib/libtls/tls.c | 7 | ||||
| -rw-r--r-- | src/lib/libtls/tls.h | 37 | ||||
| -rw-r--r-- | src/lib/libtls/tls_client.c | 12 | ||||
| -rw-r--r-- | src/lib/libtls/tls_init.3 | 121 | ||||
| -rw-r--r-- | src/lib/libtls/tls_internal.h | 33 | ||||
| -rw-r--r-- | src/lib/libtls/tls_ocsp.c | 399 | ||||
| -rw-r--r-- | src/usr.bin/nc/netcat.c | 38 |
8 files changed, 641 insertions, 9 deletions
diff --git a/src/lib/libtls/Makefile b/src/lib/libtls/Makefile index 245b1def6e..f90c57d53f 100644 --- a/src/lib/libtls/Makefile +++ b/src/lib/libtls/Makefile | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | # $OpenBSD: Makefile,v 1.25 2016/09/19 03:25:22 bcook Exp $ | 1 | # $OpenBSD: Makefile,v 1.26 2016/11/02 15:18:42 beck Exp $ |
| 2 | 2 | ||
| 3 | CFLAGS+= -Wall -Werror -Wimplicit | 3 | CFLAGS+= -Wall -Werror -Wimplicit |
| 4 | CFLAGS+= -DLIBRESSL_INTERNAL | 4 | CFLAGS+= -DLIBRESSL_INTERNAL |
| @@ -20,6 +20,7 @@ SRCS= tls.c \ | |||
| 20 | tls_peer.c \ | 20 | tls_peer.c \ |
| 21 | tls_server.c \ | 21 | tls_server.c \ |
| 22 | tls_util.c \ | 22 | tls_util.c \ |
| 23 | tls_ocsp.c \ | ||
| 23 | tls_verify.c | 24 | tls_verify.c |
| 24 | 25 | ||
| 25 | MAN= tls_init.3 | 26 | MAN= tls_init.3 |
diff --git a/src/lib/libtls/tls.c b/src/lib/libtls/tls.c index 00564edb3c..cccdb00531 100644 --- a/src/lib/libtls/tls.c +++ b/src/lib/libtls/tls.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: tls.c,v 1.49 2016/09/04 12:26:43 bcook Exp $ */ | 1 | /* $OpenBSD: tls.c,v 1.50 2016/11/02 15:18:42 beck Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> |
| 4 | * | 4 | * |
| @@ -419,6 +419,9 @@ tls_reset(struct tls *ctx) | |||
| 419 | tls_conninfo_free(ctx->conninfo); | 419 | tls_conninfo_free(ctx->conninfo); |
| 420 | ctx->conninfo = NULL; | 420 | ctx->conninfo = NULL; |
| 421 | 421 | ||
| 422 | tls_ocsp_ctx_free(ctx->ocsp_ctx); | ||
| 423 | ctx->ocsp_ctx = NULL; | ||
| 424 | |||
| 422 | for (sni = ctx->sni_ctx; sni != NULL; sni = nsni) { | 425 | for (sni = ctx->sni_ctx; sni != NULL; sni = nsni) { |
| 423 | nsni = sni->next; | 426 | nsni = sni->next; |
| 424 | tls_sni_ctx_free(sni); | 427 | tls_sni_ctx_free(sni); |
| @@ -499,6 +502,8 @@ tls_handshake(struct tls *ctx) | |||
| 499 | ctx->ssl_peer_cert = SSL_get_peer_certificate(ctx->ssl_conn); | 502 | ctx->ssl_peer_cert = SSL_get_peer_certificate(ctx->ssl_conn); |
| 500 | if (tls_conninfo_populate(ctx) == -1) | 503 | if (tls_conninfo_populate(ctx) == -1) |
| 501 | rv = -1; | 504 | rv = -1; |
| 505 | if (ctx->ocsp_ctx == NULL) | ||
| 506 | ctx->ocsp_ctx = tls_ocsp_setup_from_peer(ctx); | ||
| 502 | } | 507 | } |
| 503 | out: | 508 | out: |
| 504 | /* Prevent callers from performing incorrect error handling */ | 509 | /* Prevent callers from performing incorrect error handling */ |
diff --git a/src/lib/libtls/tls.h b/src/lib/libtls/tls.h index 6cc3d0d6f8..3929cb848e 100644 --- a/src/lib/libtls/tls.h +++ b/src/lib/libtls/tls.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: tls.h,v 1.38 2016/09/13 13:40:58 tedu Exp $ */ | 1 | /* $OpenBSD: tls.h,v 1.39 2016/11/02 15:18:42 beck Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> |
| 4 | * | 4 | * |
| @@ -41,6 +41,31 @@ extern "C" { | |||
| 41 | #define TLS_WANT_POLLIN -2 | 41 | #define TLS_WANT_POLLIN -2 |
| 42 | #define TLS_WANT_POLLOUT -3 | 42 | #define TLS_WANT_POLLOUT -3 |
| 43 | 43 | ||
| 44 | /* RFC 6960 Section 2.3 */ | ||
| 45 | #define TLS_OCSP_RESPONSE_SUCCESSFUL 0 | ||
| 46 | #define TLS_OCSP_RESPONSE_MALFORMED 1 | ||
| 47 | #define TLS_OCSP_RESPONSE_INTERNALERROR 2 | ||
| 48 | #define TLS_OCSP_RESPONSE_TRYLATER 3 | ||
| 49 | #define TLS_OCSP_RESPONSE_SIGREQUIRED 4 | ||
| 50 | #define TLS_OCSP_RESPONSE_UNAUTHORIZED 5 | ||
| 51 | |||
| 52 | /* RFC 6960 Section 2.2 */ | ||
| 53 | #define TLS_OCSP_CERT_GOOD 0 | ||
| 54 | #define TLS_OCSP_CERT_REVOKED 1 | ||
| 55 | #define TLS_OCSP_CERT_UNKNOWN 2 | ||
| 56 | |||
| 57 | /* RFC 5280 Section 5.3.1 */ | ||
| 58 | #define TLS_CRL_REASON_UNSPECIFIED 0 | ||
| 59 | #define TLS_CRL_REASON_KEY_COMPROMISE 1 | ||
| 60 | #define TLS_CRL_REASON_CA_COMPROMISE 2 | ||
| 61 | #define TLS_CRL_REASON_AFFILIATION_CHANGED 3 | ||
| 62 | #define TLS_CRL_REASON_SUPERSEDED 4 | ||
| 63 | #define TLS_CRL_REASON_CESSATION_OF_OPERATION 5 | ||
| 64 | #define TLS_CRL_REASON_CERTIFICATE_HOLD 6 | ||
| 65 | #define TLS_CRL_REASON_REMOVE_FROM_CRL 8 | ||
| 66 | #define TLS_CRL_REASON_PRIVILEGE_WITHDRAWN 9 | ||
| 67 | #define TLS_CRL_REASON_AA_COMPROMISE 10 | ||
| 68 | |||
| 44 | struct tls; | 69 | struct tls; |
| 45 | struct tls_config; | 70 | struct tls_config; |
| 46 | 71 | ||
| @@ -138,6 +163,16 @@ const char *tls_conn_version(struct tls *_ctx); | |||
| 138 | 163 | ||
| 139 | uint8_t *tls_load_file(const char *_file, size_t *_len, char *_password); | 164 | uint8_t *tls_load_file(const char *_file, size_t *_len, char *_password); |
| 140 | 165 | ||
| 166 | int tls_ocsp_process_response(struct tls *_ctx, const unsigned char *_response, size_t _size); | ||
| 167 | int tls_peer_ocsp_cert_status(struct tls *_ctx); | ||
| 168 | int tls_peer_ocsp_crl_reason(struct tls *_ctx); | ||
| 169 | time_t tls_peer_ocsp_next_update(struct tls *_ctx); | ||
| 170 | int tls_peer_ocsp_response_status(struct tls *_ctx); | ||
| 171 | const char *tls_peer_ocsp_result(struct tls *_ctx); | ||
| 172 | time_t tls_peer_ocsp_revocation_time(struct tls *_ctx); | ||
| 173 | time_t tls_peer_ocsp_this_update(struct tls *_ctx); | ||
| 174 | const char *tls_peer_ocsp_url(struct tls *_ctx); | ||
| 175 | |||
| 141 | #ifdef __cplusplus | 176 | #ifdef __cplusplus |
| 142 | } | 177 | } |
| 143 | #endif | 178 | #endif |
diff --git a/src/lib/libtls/tls_client.c b/src/lib/libtls/tls_client.c index a1bceb7d97..84f4e91740 100644 --- a/src/lib/libtls/tls_client.c +++ b/src/lib/libtls/tls_client.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: tls_client.c,v 1.36 2016/09/04 13:20:56 jsing Exp $ */ | 1 | /* $OpenBSD: tls_client.c,v 1.37 2016/11/02 15:18:42 beck Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> | 3 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> |
| 4 | * | 4 | * |
| @@ -200,6 +200,11 @@ tls_connect_common(struct tls *ctx, const char *servername) | |||
| 200 | SSL_VERIFY_PEER) == -1)) | 200 | SSL_VERIFY_PEER) == -1)) |
| 201 | goto err; | 201 | goto err; |
| 202 | 202 | ||
| 203 | if (SSL_CTX_set_tlsext_status_cb(ctx->ssl_ctx, tls_ocsp_verify_cb) != 1) { | ||
| 204 | tls_set_errorx(ctx, "ssl OCSP verification setup failure"); | ||
| 205 | goto err; | ||
| 206 | } | ||
| 207 | |||
| 203 | if ((ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) { | 208 | if ((ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) { |
| 204 | tls_set_errorx(ctx, "ssl connection failure"); | 209 | tls_set_errorx(ctx, "ssl connection failure"); |
| 205 | goto err; | 210 | goto err; |
| @@ -210,6 +215,11 @@ tls_connect_common(struct tls *ctx, const char *servername) | |||
| 210 | goto err; | 215 | goto err; |
| 211 | } | 216 | } |
| 212 | 217 | ||
| 218 | if (SSL_set_tlsext_status_type(ctx->ssl_conn, TLSEXT_STATUSTYPE_ocsp) != 1) { | ||
| 219 | tls_set_errorx(ctx, "ssl OCSP extension setup failure"); | ||
| 220 | goto err; | ||
| 221 | } | ||
| 222 | |||
| 213 | /* | 223 | /* |
| 214 | * RFC4366 (SNI): Literal IPv4 and IPv6 addresses are not | 224 | * RFC4366 (SNI): Literal IPv4 and IPv6 addresses are not |
| 215 | * permitted in "HostName". | 225 | * permitted in "HostName". |
diff --git a/src/lib/libtls/tls_init.3 b/src/lib/libtls/tls_init.3 index 6059c3f8a0..2f6ca3d802 100644 --- a/src/lib/libtls/tls_init.3 +++ b/src/lib/libtls/tls_init.3 | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | .\" $OpenBSD: tls_init.3,v 1.72 2016/09/13 13:40:58 tedu Exp $ | 1 | .\" $OpenBSD: tls_init.3,v 1.73 2016/11/02 15:18:42 beck Exp $ |
| 2 | .\" | 2 | .\" |
| 3 | .\" Copyright (c) 2014 Ted Unangst <tedu@openbsd.org> | 3 | .\" Copyright (c) 2014 Ted Unangst <tedu@openbsd.org> |
| 4 | .\" | 4 | .\" |
| @@ -14,7 +14,7 @@ | |||
| 14 | .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | 14 | .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
| 15 | .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 15 | .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| 16 | .\" | 16 | .\" |
| 17 | .Dd $Mdocdate: September 13 2016 $ | 17 | .Dd $Mdocdate: November 2 2016 $ |
| 18 | .Dt TLS_INIT 3 | 18 | .Dt TLS_INIT 3 |
| 19 | .Os | 19 | .Os |
| 20 | .Sh NAME | 20 | .Sh NAME |
| @@ -50,6 +50,7 @@ | |||
| 50 | .Nm tls_config_verify , | 50 | .Nm tls_config_verify , |
| 51 | .Nm tls_config_verify_client , | 51 | .Nm tls_config_verify_client , |
| 52 | .Nm tls_config_verify_client_optional , | 52 | .Nm tls_config_verify_client_optional , |
| 53 | .Nm tls_ocsp_process_response, | ||
| 53 | .Nm tls_peer_cert_provided , | 54 | .Nm tls_peer_cert_provided , |
| 54 | .Nm tls_peer_cert_contains_name , | 55 | .Nm tls_peer_cert_contains_name , |
| 55 | .Nm tls_peer_cert_issuer , | 56 | .Nm tls_peer_cert_issuer , |
| @@ -57,6 +58,14 @@ | |||
| 57 | .Nm tls_peer_cert_hash , | 58 | .Nm tls_peer_cert_hash , |
| 58 | .Nm tls_peer_cert_notbefore , | 59 | .Nm tls_peer_cert_notbefore , |
| 59 | .Nm tls_peer_cert_notafter , | 60 | .Nm tls_peer_cert_notafter , |
| 61 | .Nm tls_peer_ocsp_cert_status, | ||
| 62 | .Nm tls_peer_ocsp_crl_reason, | ||
| 63 | .Nm tls_peer_ocsp_next_update, | ||
| 64 | .Nm tls_peer_ocsp_response_status, | ||
| 65 | .Nm tls_peer_ocsp_result_msg, | ||
| 66 | .Nm tls_peer_ocsp_revocation_time, | ||
| 67 | .Nm tls_peer_ocsp_this_update, | ||
| 68 | .Nm tls_peer_ocsp_url, | ||
| 60 | .Nm tls_conn_alpn_selected , | 69 | .Nm tls_conn_alpn_selected , |
| 61 | .Nm tls_conn_cipher , | 70 | .Nm tls_conn_cipher , |
| 62 | .Nm tls_conn_servername , | 71 | .Nm tls_conn_servername , |
| @@ -160,6 +169,24 @@ | |||
| 160 | .Fn tls_peer_cert_notbefore "struct tls *ctx" | 169 | .Fn tls_peer_cert_notbefore "struct tls *ctx" |
| 161 | .Ft "time_t" | 170 | .Ft "time_t" |
| 162 | .Fn tls_peer_cert_notafter "struct tls *ctx" | 171 | .Fn tls_peer_cert_notafter "struct tls *ctx" |
| 172 | .Ft "int" | ||
| 173 | .Fn tls_ocsp_process_response "struct tls *ctx" "const unsigned char *response" "size_t size" | ||
| 174 | .Ft "int" | ||
| 175 | .Fn tls_peer_ocsp_cert_status "struct tls *ctx" | ||
| 176 | .Ft "int" | ||
| 177 | .Fn tls_peer_ocsp_crl_reason "struct tls *ctx" | ||
| 178 | .Ft time_t | ||
| 179 | .Fn tls_peer_ocsp_next_update "struct tls *ctx" | ||
| 180 | .Ft "int" | ||
| 181 | .Fn tls_peer_ocsp_response_status "struct tls *ctx" | ||
| 182 | .Ft "const char *" | ||
| 183 | .Fn tls_peer_ocsp_result_msg "struct tls *ctx" | ||
| 184 | .Ft "time_t" | ||
| 185 | .Fn tls_peer_ocsp_revocation_time "struct tls *ctx" | ||
| 186 | .Ft "time_t" | ||
| 187 | .Fn tls_peer_ocsp_this_update" struct tls *ctx" | ||
| 188 | .Ft "const char *" | ||
| 189 | .Fn tls_peer_ocsp_url "struct tls *ctx" | ||
| 163 | .Ft "const char *" | 190 | .Ft "const char *" |
| 164 | .Fn tls_conn_alpn_selected "struct tls *ctx" | 191 | .Fn tls_conn_alpn_selected "struct tls *ctx" |
| 165 | .Ft "const char *" | 192 | .Ft "const char *" |
| @@ -513,6 +540,53 @@ the peer certificate from | |||
| 513 | returns the time corresponding to the end of the validity period of | 540 | returns the time corresponding to the end of the validity period of |
| 514 | the peer certificate from | 541 | the peer certificate from |
| 515 | .Ar ctx . | 542 | .Ar ctx . |
| 543 | .Ed | ||
| 544 | .It | ||
| 545 | .Fn tls_ocsp_process_response | ||
| 546 | processes a raw ocsp response in | ||
| 547 | .Ar response | ||
| 548 | of size | ||
| 549 | .Ar size | ||
| 550 | to check the revocation status of the peer certificate from | ||
| 551 | .Ar ctx . | ||
| 552 | A successful return code of 0 indicates that the certificate has not been revoked. | ||
| 553 | .Ed | ||
| 554 | .It | ||
| 555 | .Fn tls_peer_ocsp_url | ||
| 556 | returns the URL for OCSP validation of the peer certificate from | ||
| 557 | .Ar ctx | ||
| 558 | .El | ||
| 559 | .Pp | ||
| 560 | The following functions return informaiton about the peer certificate from | ||
| 561 | .Ar ctx | ||
| 562 | tha was obtained by validating a stapled OCSP response during the handshake, or | ||
| 563 | via a previous call to | ||
| 564 | .Xr tls_ocsp_process_response | ||
| 565 | .Bl -bullet -offset four | ||
| 566 | .It | ||
| 567 | .Fn tls_peer_ocsp_cert_status | ||
| 568 | returns the OCSP certificate status code as per RFC 6960 section 2.2 | ||
| 569 | .Ed | ||
| 570 | .It | ||
| 571 | .Fn tls_peer_ocsp_crl_reason | ||
| 572 | returns the OCSP certificate revocation reason status code as per RFC 5280 | ||
| 573 | section 5.3.1 | ||
| 574 | .Ed | ||
| 575 | .It | ||
| 576 | .Fn tls_peer_ocsp_next_update | ||
| 577 | returns the OCSP next update time | ||
| 578 | .Ed | ||
| 579 | .It | ||
| 580 | .Fn tls_peer_ocsp_response_status | ||
| 581 | returns the OCSP response status as per RFC 6960 section 2.3 | ||
| 582 | .Ed | ||
| 583 | .It | ||
| 584 | .Fn tls_peer_ocsp_revocation_time | ||
| 585 | returns the OCSP revocation time | ||
| 586 | .Ed | ||
| 587 | .It | ||
| 588 | .Fn tls_peer_ocsp_this_update | ||
| 589 | returns the OCSP this update time | ||
| 516 | .El | 590 | .El |
| 517 | .Pp | 591 | .Pp |
| 518 | The following are TLS related utility functions: | 592 | The following are TLS related utility functions: |
| @@ -616,16 +690,57 @@ The | |||
| 616 | and | 690 | and |
| 617 | .Fn tls_peer_cert_contains_name | 691 | .Fn tls_peer_cert_contains_name |
| 618 | functions return 1 if the check succeeds, and 0 if it does not. | 692 | functions return 1 if the check succeeds, and 0 if it does not. |
| 693 | .Pp | ||
| 619 | Functions that return a | 694 | Functions that return a |
| 620 | .Vt time_t | 695 | .Vt time_t |
| 621 | will return a time in epoch-seconds on success, and -1 on error. | 696 | will return a time in epoch-seconds on success, and -1 on error. |
| 697 | .Pp | ||
| 622 | Functions that return a | 698 | Functions that return a |
| 623 | .Vt ssize_t | 699 | .Vt ssize_t |
| 624 | will return a size on success, and -1 on error. | 700 | will return a size on success, and -1 on error. |
| 701 | .Pp | ||
| 702 | The | ||
| 703 | .Fn tls_peer_ocsp_response_status | ||
| 704 | function returns one of | ||
| 705 | .Ar TLS_OCSP_RESPONSE_SUCCESSFUL , | ||
| 706 | .Ar TLS_OCSP_RESPONSE_MALFORMED , | ||
| 707 | .Ar TLS_OCSP_RESPONSE_INTERNALERROR , | ||
| 708 | .Ar TLS_OCSP_RESPONSE_TRYLATER , | ||
| 709 | .Ar TLS_OCSP_RESPONSE_SIGREQUIRED , | ||
| 710 | or | ||
| 711 | .AR TLS_OCSP_RESPONSE_UNAUTHORIZED | ||
| 712 | on success, and -1 on error. | ||
| 713 | .Pp | ||
| 714 | The | ||
| 715 | .Fn tls_peer_ocsp_cert_status | ||
| 716 | function returns one of | ||
| 717 | .Ar TLS_OCSP_CERT_GOOD , | ||
| 718 | .Ar TLS_OCSP_CERT_REVOKED , | ||
| 719 | or | ||
| 720 | .Ar TLS_OCSP_CERT_UNKNOWN | ||
| 721 | on success, and -1 on error. | ||
| 722 | .Pp | ||
| 723 | The | ||
| 724 | .Fn tls_peer_ocsp_crl_reason | ||
| 725 | function returns one of | ||
| 726 | .Ar TLS_CRL_REASON_UNSPECIFIED , | ||
| 727 | .Ar TLS_CRL_REASON_KEY_COMPROMISE , | ||
| 728 | .Ar TLS_CRL_REASON_CA_COMPROMISE , | ||
| 729 | .Ar TLS_CRL_REASON_AFFILIATION_CHANGED , | ||
| 730 | .Ar TLS_CRL_REASON_SUPERSEDED , | ||
| 731 | .Ar TLS_CRL_REASON_CESSATION_OF_OPERATION , | ||
| 732 | .Ar TLS_CRL_REASON_CERTIFICATE_HOLD , | ||
| 733 | .Ar TLS_CRL_REASON_REMOVE_FROM_CRL , | ||
| 734 | .Ar TLS_CRL_REASON_PRIVILEGE_WITHDRAWN , | ||
| 735 | or | ||
| 736 | .Ar TLS_CRL_REASON_AA_COMPROMISE | ||
| 737 | on success, and -1 on error. | ||
| 738 | .Pp | ||
| 625 | All other functions that return | 739 | All other functions that return |
| 626 | .Vt int | 740 | .Vt int |
| 627 | will return 0 on success and -1 on error. | 741 | will return 0 on success and -1 on error. |
| 628 | Functions that return a pointer will return NULL on error, which indicates an | 742 | .Pp |
| 743 | Functions that return a pointer will return NULL on error or an | ||
| 629 | out of memory condition. | 744 | out of memory condition. |
| 630 | .Pp | 745 | .Pp |
| 631 | The | 746 | The |
diff --git a/src/lib/libtls/tls_internal.h b/src/lib/libtls/tls_internal.h index c272038055..df35db37f2 100644 --- a/src/lib/libtls/tls_internal.h +++ b/src/lib/libtls/tls_internal.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: tls_internal.h,v 1.43 2016/09/04 12:26:43 bcook Exp $ */ | 1 | /* $OpenBSD: tls_internal.h,v 1.44 2016/11/02 15:18:42 beck Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2014 Jeremie Courreges-Anglas <jca@openbsd.org> | 3 | * Copyright (c) 2014 Jeremie Courreges-Anglas <jca@openbsd.org> |
| 4 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> | 4 | * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> |
| @@ -92,6 +92,31 @@ struct tls_conninfo { | |||
| 92 | #define TLS_EOF_NO_CLOSE_NOTIFY (1 << 0) | 92 | #define TLS_EOF_NO_CLOSE_NOTIFY (1 << 0) |
| 93 | #define TLS_HANDSHAKE_COMPLETE (1 << 1) | 93 | #define TLS_HANDSHAKE_COMPLETE (1 << 1) |
| 94 | 94 | ||
| 95 | struct tls_ocsp_result { | ||
| 96 | const char *result_msg; | ||
| 97 | int response_status; | ||
| 98 | int cert_status; | ||
| 99 | int crl_reason; | ||
| 100 | time_t this_update; | ||
| 101 | time_t next_update; | ||
| 102 | time_t revocation_time; | ||
| 103 | }; | ||
| 104 | |||
| 105 | struct tls_ocsp_ctx { | ||
| 106 | /* responder location */ | ||
| 107 | char *ocsp_url; | ||
| 108 | |||
| 109 | /* request blob */ | ||
| 110 | uint8_t *request_data; | ||
| 111 | size_t request_size; | ||
| 112 | |||
| 113 | /* cert data, this struct does not own these */ | ||
| 114 | X509 *main_cert; | ||
| 115 | STACK_OF(X509) *extra_certs; | ||
| 116 | |||
| 117 | struct tls_ocsp_result *ocsp_result; | ||
| 118 | }; | ||
| 119 | |||
| 95 | struct tls_sni_ctx { | 120 | struct tls_sni_ctx { |
| 96 | struct tls_sni_ctx *next; | 121 | struct tls_sni_ctx *next; |
| 97 | 122 | ||
| @@ -118,6 +143,8 @@ struct tls { | |||
| 118 | 143 | ||
| 119 | struct tls_conninfo *conninfo; | 144 | struct tls_conninfo *conninfo; |
| 120 | 145 | ||
| 146 | struct tls_ocsp_ctx *ocsp_ctx; | ||
| 147 | |||
| 121 | tls_read_cb read_cb; | 148 | tls_read_cb read_cb; |
| 122 | tls_write_cb write_cb; | 149 | tls_write_cb write_cb; |
| 123 | void *cb_arg; | 150 | void *cb_arg; |
| @@ -172,6 +199,10 @@ int tls_ssl_error(struct tls *ctx, SSL *ssl_conn, int ssl_ret, | |||
| 172 | int tls_conninfo_populate(struct tls *ctx); | 199 | int tls_conninfo_populate(struct tls *ctx); |
| 173 | void tls_conninfo_free(struct tls_conninfo *conninfo); | 200 | void tls_conninfo_free(struct tls_conninfo *conninfo); |
| 174 | 201 | ||
| 202 | int tls_ocsp_verify_cb(SSL *ssl, void *arg); | ||
| 203 | void tls_ocsp_ctx_free(struct tls_ocsp_ctx *ctx); | ||
| 204 | struct tls_ocsp_ctx *tls_ocsp_setup_from_peer(struct tls *ctx); | ||
| 205 | |||
| 175 | int asn1_time_parse(const char *, size_t, struct tm *, int); | 206 | int asn1_time_parse(const char *, size_t, struct tm *, int); |
| 176 | 207 | ||
| 177 | #endif /* HEADER_TLS_INTERNAL_H */ | 208 | #endif /* HEADER_TLS_INTERNAL_H */ |
diff --git a/src/lib/libtls/tls_ocsp.c b/src/lib/libtls/tls_ocsp.c new file mode 100644 index 0000000000..113ab0dd3d --- /dev/null +++ b/src/lib/libtls/tls_ocsp.c | |||
| @@ -0,0 +1,399 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2015 Marko Kreen <markokr@gmail.com> | ||
| 3 | * Copyright (c) 2016 Bob Beck <beck@openbsd.org> | ||
| 4 | * | ||
| 5 | * Permission to use, copy, modify, and distribute this software for any | ||
| 6 | * purpose with or without fee is hereby granted, provided that the above | ||
| 7 | * copyright notice and this permission notice appear in all copies. | ||
| 8 | * | ||
| 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
| 12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
| 14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
| 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <sys/types.h> | ||
| 19 | |||
| 20 | #include <arpa/inet.h> | ||
| 21 | #include <netinet/in.h> | ||
| 22 | |||
| 23 | #include <openssl/err.h> | ||
| 24 | #include <openssl/ocsp.h> | ||
| 25 | #include <openssl/x509.h> | ||
| 26 | |||
| 27 | #include <tls.h> | ||
| 28 | #include "tls_internal.h" | ||
| 29 | |||
| 30 | #define MAXAGE_SEC (14*24*60*60) | ||
| 31 | #define JITTER_SEC (60) | ||
| 32 | |||
| 33 | /* | ||
| 34 | * State for request. | ||
| 35 | */ | ||
| 36 | |||
| 37 | static struct tls_ocsp_ctx * | ||
| 38 | tls_ocsp_ctx_new(void) | ||
| 39 | { | ||
| 40 | return (calloc(1, sizeof(struct tls_ocsp_ctx))); | ||
| 41 | } | ||
| 42 | |||
| 43 | void | ||
| 44 | tls_ocsp_ctx_free(struct tls_ocsp_ctx *ocsp_ctx) | ||
| 45 | { | ||
| 46 | if (ocsp_ctx == NULL) | ||
| 47 | return; | ||
| 48 | |||
| 49 | free(ocsp_ctx->ocsp_result); | ||
| 50 | ocsp_ctx->ocsp_result = NULL; | ||
| 51 | free(ocsp_ctx->ocsp_url); | ||
| 52 | ocsp_ctx->ocsp_url = NULL; | ||
| 53 | free(ocsp_ctx->request_data); | ||
| 54 | ocsp_ctx->request_data = NULL; | ||
| 55 | free(ocsp_ctx); | ||
| 56 | } | ||
| 57 | |||
| 58 | static int | ||
| 59 | tls_ocsp_asn1_parse_time(struct tls *ctx, ASN1_GENERALIZEDTIME *gt, time_t *time) | ||
| 60 | { | ||
| 61 | struct tm tm; | ||
| 62 | |||
| 63 | if (gt == NULL) | ||
| 64 | return -1; | ||
| 65 | /* RFC 6960 specifies that all times in OCSP must be GENERALIZEDTIME */ | ||
| 66 | if (asn1_time_parse(gt->data, gt->length, &tm, | ||
| 67 | V_ASN1_GENERALIZEDTIME) == -1) | ||
| 68 | return -1; | ||
| 69 | if ((*time = timegm(&tm)) == -1) | ||
| 70 | return -1; | ||
| 71 | return 0; | ||
| 72 | } | ||
| 73 | |||
| 74 | static int | ||
| 75 | tls_ocsp_fill_info(struct tls *ctx, int response_status, int cert_status, | ||
| 76 | int crl_reason, ASN1_GENERALIZEDTIME *revtime, | ||
| 77 | ASN1_GENERALIZEDTIME *thisupd, ASN1_GENERALIZEDTIME *nextupd) | ||
| 78 | { | ||
| 79 | struct tls_ocsp_result *info = NULL; | ||
| 80 | |||
| 81 | free(ctx->ocsp_ctx->ocsp_result); | ||
| 82 | ctx->ocsp_ctx->ocsp_result = NULL; | ||
| 83 | |||
| 84 | if ((info = calloc(1, sizeof (struct tls_ocsp_result))) == NULL) { | ||
| 85 | tls_set_error(ctx, "calloc"); | ||
| 86 | return -1; | ||
| 87 | } | ||
| 88 | info->response_status = response_status; | ||
| 89 | info->cert_status = cert_status; | ||
| 90 | info->crl_reason = crl_reason; | ||
| 91 | if (info->response_status != OCSP_RESPONSE_STATUS_SUCCESSFUL) { | ||
| 92 | info->result_msg = | ||
| 93 | OCSP_response_status_str(info->response_status); | ||
| 94 | } else if (info->cert_status != V_OCSP_CERTSTATUS_REVOKED) { | ||
| 95 | info->result_msg = OCSP_cert_status_str(info->cert_status); | ||
| 96 | } else { | ||
| 97 | info->result_msg = OCSP_crl_reason_str(info->crl_reason); | ||
| 98 | } | ||
| 99 | info->revocation_time = info->this_update = info->next_update = -1; | ||
| 100 | if (revtime != NULL && | ||
| 101 | tls_ocsp_asn1_parse_time(ctx, revtime, &info->revocation_time) != 0) { | ||
| 102 | tls_set_error(ctx, | ||
| 103 | "unable to parse revocation time in OCSP reply"); | ||
| 104 | goto error; | ||
| 105 | } | ||
| 106 | if (thisupd != NULL && | ||
| 107 | tls_ocsp_asn1_parse_time(ctx, thisupd, &info->this_update) != 0) { | ||
| 108 | tls_set_error(ctx, | ||
| 109 | "unable to parse this update time in OCSP reply"); | ||
| 110 | goto error; | ||
| 111 | } | ||
| 112 | if (nextupd != NULL && | ||
| 113 | tls_ocsp_asn1_parse_time(ctx, nextupd, &info->next_update) != 0) { | ||
| 114 | tls_set_error(ctx, | ||
| 115 | "unable to parse next update time in OCSP reply"); | ||
| 116 | goto error; | ||
| 117 | } | ||
| 118 | ctx->ocsp_ctx->ocsp_result = info; | ||
| 119 | return 0; | ||
| 120 | error: | ||
| 121 | free(info); | ||
| 122 | return -1; | ||
| 123 | } | ||
| 124 | |||
| 125 | static OCSP_CERTID * | ||
| 126 | tls_ocsp_get_certid(X509 *main_cert, STACK_OF(X509) *extra_certs, | ||
| 127 | SSL_CTX *ssl_ctx) | ||
| 128 | { | ||
| 129 | X509_NAME *issuer_name; | ||
| 130 | X509 *issuer; | ||
| 131 | X509_STORE_CTX storectx; | ||
| 132 | X509_OBJECT tmpobj; | ||
| 133 | OCSP_CERTID *cid = NULL; | ||
| 134 | X509_STORE *store; | ||
| 135 | |||
| 136 | if ((issuer_name = X509_get_issuer_name(main_cert)) == NULL) | ||
| 137 | return NULL; | ||
| 138 | |||
| 139 | if (extra_certs != NULL) { | ||
| 140 | issuer = X509_find_by_subject(extra_certs, issuer_name); | ||
| 141 | if (issuer != NULL) | ||
| 142 | return OCSP_cert_to_id(NULL, main_cert, issuer); | ||
| 143 | } | ||
| 144 | |||
| 145 | if ((store = SSL_CTX_get_cert_store(ssl_ctx)) == NULL) | ||
| 146 | return NULL; | ||
| 147 | if (X509_STORE_CTX_init(&storectx, store, main_cert, extra_certs) != 1) | ||
| 148 | return NULL; | ||
| 149 | if (X509_STORE_get_by_subject(&storectx, X509_LU_X509, issuer_name, | ||
| 150 | &tmpobj) == 1) { | ||
| 151 | cid = OCSP_cert_to_id(NULL, main_cert, tmpobj.data.x509); | ||
| 152 | X509_OBJECT_free_contents(&tmpobj); | ||
| 153 | } | ||
| 154 | X509_STORE_CTX_cleanup(&storectx); | ||
| 155 | return cid; | ||
| 156 | } | ||
| 157 | |||
| 158 | struct tls_ocsp_ctx * | ||
| 159 | tls_ocsp_setup_from_peer(struct tls *ctx) | ||
| 160 | { | ||
| 161 | struct tls_ocsp_ctx *ocsp_ctx = NULL; | ||
| 162 | STACK_OF(OPENSSL_STRING) *ocsp_urls = NULL; | ||
| 163 | |||
| 164 | if ((ocsp_ctx = tls_ocsp_ctx_new()) == NULL) | ||
| 165 | goto failed; | ||
| 166 | |||
| 167 | /* steal state from ctx struct */ | ||
| 168 | ocsp_ctx->main_cert = SSL_get_peer_certificate(ctx->ssl_conn); | ||
| 169 | ocsp_ctx->extra_certs = SSL_get_peer_cert_chain(ctx->ssl_conn); | ||
| 170 | if (ocsp_ctx->main_cert == NULL) { | ||
| 171 | tls_set_errorx(ctx, "no peer certificate for OCSP"); | ||
| 172 | goto failed; | ||
| 173 | } | ||
| 174 | |||
| 175 | ocsp_urls = X509_get1_ocsp(ocsp_ctx->main_cert); | ||
| 176 | if (ocsp_urls == NULL) | ||
| 177 | goto failed; | ||
| 178 | ocsp_ctx->ocsp_url = strdup(sk_OPENSSL_STRING_value(ocsp_urls, 0)); | ||
| 179 | if (ocsp_ctx->ocsp_url == NULL) { | ||
| 180 | tls_set_errorx(ctx, "out of memory"); | ||
| 181 | goto failed; | ||
| 182 | } | ||
| 183 | |||
| 184 | X509_email_free(ocsp_urls); | ||
| 185 | return ocsp_ctx; | ||
| 186 | |||
| 187 | failed: | ||
| 188 | tls_ocsp_ctx_free(ocsp_ctx); | ||
| 189 | X509_email_free(ocsp_urls); | ||
| 190 | return NULL; | ||
| 191 | } | ||
| 192 | |||
| 193 | static int | ||
| 194 | tls_ocsp_verify_response(struct tls *ctx, OCSP_RESPONSE *resp) | ||
| 195 | { | ||
| 196 | OCSP_BASICRESP *br = NULL; | ||
| 197 | ASN1_GENERALIZEDTIME *revtime = NULL, *thisupd = NULL, *nextupd = NULL; | ||
| 198 | OCSP_CERTID *cid = NULL; | ||
| 199 | STACK_OF(X509) *combined = NULL; | ||
| 200 | int response_status=0, cert_status=0, crl_reason=0; | ||
| 201 | int ret = -1; | ||
| 202 | unsigned long flags; | ||
| 203 | |||
| 204 | if ((br = OCSP_response_get1_basic(resp)) == NULL) { | ||
| 205 | tls_set_errorx(ctx, "cannot load ocsp reply"); | ||
| 206 | goto error; | ||
| 207 | } | ||
| 208 | |||
| 209 | /* | ||
| 210 | * Skip validation of 'extra_certs' as this should be done | ||
| 211 | * already as part of main handshake. | ||
| 212 | */ | ||
| 213 | flags = OCSP_TRUSTOTHER; | ||
| 214 | |||
| 215 | /* now verify */ | ||
| 216 | if (OCSP_basic_verify(br, ctx->ocsp_ctx->extra_certs, | ||
| 217 | SSL_CTX_get_cert_store(ctx->ssl_ctx), flags) != 1) { | ||
| 218 | tls_set_error(ctx, "ocsp verify failed"); | ||
| 219 | goto error; | ||
| 220 | } | ||
| 221 | |||
| 222 | /* signature OK, look inside */ | ||
| 223 | response_status = OCSP_response_status(resp); | ||
| 224 | if (response_status != OCSP_RESPONSE_STATUS_SUCCESSFUL) { | ||
| 225 | tls_set_errorx(ctx, "ocsp verify failed: response - %s", | ||
| 226 | OCSP_response_status_str(response_status)); | ||
| 227 | goto error; | ||
| 228 | } | ||
| 229 | |||
| 230 | cid = tls_ocsp_get_certid(ctx->ocsp_ctx->main_cert, | ||
| 231 | ctx->ocsp_ctx->extra_certs, ctx->ssl_ctx); | ||
| 232 | if (cid == NULL) { | ||
| 233 | tls_set_errorx(ctx, "ocsp verify failed: no issuer cert"); | ||
| 234 | goto error; | ||
| 235 | } | ||
| 236 | |||
| 237 | if (OCSP_resp_find_status(br, cid, &cert_status, &crl_reason, | ||
| 238 | &revtime, &thisupd, &nextupd) != 1) { | ||
| 239 | tls_set_errorx(ctx, "ocsp verify failed: no result for cert"); | ||
| 240 | goto error; | ||
| 241 | } | ||
| 242 | |||
| 243 | if (OCSP_check_validity(thisupd, nextupd, JITTER_SEC, | ||
| 244 | MAXAGE_SEC) != 1) { | ||
| 245 | tls_set_errorx(ctx, | ||
| 246 | "ocsp verify failed: ocsp response not current"); | ||
| 247 | goto error; | ||
| 248 | } | ||
| 249 | |||
| 250 | if (tls_ocsp_fill_info(ctx, response_status, cert_status, | ||
| 251 | crl_reason, revtime, thisupd, nextupd) != 0) | ||
| 252 | goto error; | ||
| 253 | |||
| 254 | /* finally can look at status */ | ||
| 255 | if (cert_status != V_OCSP_CERTSTATUS_GOOD && cert_status != | ||
| 256 | V_OCSP_CERTSTATUS_UNKNOWN) { | ||
| 257 | tls_set_errorx(ctx, "ocsp verify failed: revoked cert - %s", | ||
| 258 | OCSP_crl_reason_str(crl_reason)); | ||
| 259 | goto error; | ||
| 260 | } | ||
| 261 | |||
| 262 | ret = 0; | ||
| 263 | |||
| 264 | error: | ||
| 265 | sk_X509_free(combined); | ||
| 266 | OCSP_CERTID_free(cid); | ||
| 267 | OCSP_BASICRESP_free(br); | ||
| 268 | return ret; | ||
| 269 | } | ||
| 270 | |||
| 271 | /* TLS handshake verification callback for stapled requests */ | ||
| 272 | int | ||
| 273 | tls_ocsp_verify_cb(SSL *ssl, void *arg) | ||
| 274 | { | ||
| 275 | const unsigned char *raw = NULL; | ||
| 276 | int size, res = -1; | ||
| 277 | struct tls *ctx; | ||
| 278 | |||
| 279 | if ((ctx = SSL_get_app_data(ssl)) == NULL) | ||
| 280 | return -1; | ||
| 281 | |||
| 282 | size = SSL_get_tlsext_status_ocsp_resp(ssl, &raw); | ||
| 283 | if (size <= 0) | ||
| 284 | return 1; | ||
| 285 | |||
| 286 | tls_ocsp_ctx_free(ctx->ocsp_ctx); | ||
| 287 | ctx->ocsp_ctx = tls_ocsp_setup_from_peer(ctx); | ||
| 288 | if (ctx->ocsp_ctx != NULL) | ||
| 289 | res = tls_ocsp_process_response(ctx, raw, size); | ||
| 290 | |||
| 291 | return (res == 0) ? 1 : 0; | ||
| 292 | } | ||
| 293 | |||
| 294 | /* | ||
| 295 | * Public API | ||
| 296 | */ | ||
| 297 | |||
| 298 | /* Retrieve OSCP URL from peer certificate, if present */ | ||
| 299 | const char * | ||
| 300 | tls_peer_ocsp_url(struct tls *ctx) | ||
| 301 | { | ||
| 302 | if (ctx->ocsp_ctx == NULL) | ||
| 303 | return NULL; | ||
| 304 | return ctx->ocsp_ctx->ocsp_url; | ||
| 305 | } | ||
| 306 | |||
| 307 | const char * | ||
| 308 | tls_peer_ocsp_result(struct tls *ctx) | ||
| 309 | { | ||
| 310 | if (ctx->ocsp_ctx == NULL) | ||
| 311 | return NULL; | ||
| 312 | if (ctx->ocsp_ctx->ocsp_result == NULL) | ||
| 313 | return NULL; | ||
| 314 | return ctx->ocsp_ctx->ocsp_result->result_msg; | ||
| 315 | } | ||
| 316 | |||
| 317 | int | ||
| 318 | tls_peer_ocsp_response_status(struct tls *ctx) | ||
| 319 | { | ||
| 320 | if (ctx->ocsp_ctx == NULL) | ||
| 321 | return -1; | ||
| 322 | if (ctx->ocsp_ctx->ocsp_result == NULL) | ||
| 323 | return -1; | ||
| 324 | return ctx->ocsp_ctx->ocsp_result->response_status; | ||
| 325 | } | ||
| 326 | |||
| 327 | int | ||
| 328 | tls_peer_ocsp_cert_status(struct tls *ctx) | ||
| 329 | { | ||
| 330 | if (ctx->ocsp_ctx == NULL) | ||
| 331 | return -1; | ||
| 332 | if (ctx->ocsp_ctx->ocsp_result == NULL) | ||
| 333 | return -1; | ||
| 334 | return ctx->ocsp_ctx->ocsp_result->cert_status; | ||
| 335 | } | ||
| 336 | |||
| 337 | int | ||
| 338 | tls_peer_ocsp_crl_reason(struct tls *ctx) | ||
| 339 | { | ||
| 340 | if (ctx->ocsp_ctx == NULL) | ||
| 341 | return -1; | ||
| 342 | if (ctx->ocsp_ctx->ocsp_result == NULL) | ||
| 343 | return -1; | ||
| 344 | return ctx->ocsp_ctx->ocsp_result->crl_reason; | ||
| 345 | } | ||
| 346 | |||
| 347 | time_t | ||
| 348 | tls_peer_ocsp_this_update(struct tls *ctx) | ||
| 349 | { | ||
| 350 | if (ctx->ocsp_ctx == NULL) | ||
| 351 | return -1; | ||
| 352 | if (ctx->ocsp_ctx->ocsp_result == NULL) | ||
| 353 | return -1; | ||
| 354 | return ctx->ocsp_ctx->ocsp_result->this_update; | ||
| 355 | } | ||
| 356 | |||
| 357 | time_t | ||
| 358 | tls_peer_ocsp_next_update(struct tls *ctx) | ||
| 359 | { | ||
| 360 | if (ctx->ocsp_ctx == NULL) | ||
| 361 | return -1; | ||
| 362 | if (ctx->ocsp_ctx->ocsp_result == NULL) | ||
| 363 | return -1; | ||
| 364 | return ctx->ocsp_ctx->ocsp_result->next_update; | ||
| 365 | } | ||
| 366 | |||
| 367 | time_t | ||
| 368 | tls_peer_ocsp_revocation_time(struct tls *ctx) | ||
| 369 | { | ||
| 370 | if (ctx->ocsp_ctx == NULL) | ||
| 371 | return -1; | ||
| 372 | if (ctx->ocsp_ctx->ocsp_result == NULL) | ||
| 373 | return -1; | ||
| 374 | return ctx->ocsp_ctx->ocsp_result->revocation_time; | ||
| 375 | } | ||
| 376 | |||
| 377 | /* | ||
| 378 | * Process a raw OCSP response from an OCSP server request. | ||
| 379 | * OCSP details can then be retrieved with tls_peer_ocsp_* functions. | ||
| 380 | * returns 0 if certificate ok, -1 otherwise. | ||
| 381 | */ | ||
| 382 | int | ||
| 383 | tls_ocsp_process_response(struct tls *ctx, const unsigned char *response, | ||
| 384 | size_t size) | ||
| 385 | { | ||
| 386 | int ret; | ||
| 387 | OCSP_RESPONSE *resp; | ||
| 388 | |||
| 389 | resp = d2i_OCSP_RESPONSE(NULL, &response, size); | ||
| 390 | if (resp == NULL) { | ||
| 391 | tls_ocsp_ctx_free(ctx->ocsp_ctx); | ||
| 392 | ctx->ocsp_ctx = NULL; | ||
| 393 | tls_set_error(ctx, "unable to parse OCSP response"); | ||
| 394 | return -1; | ||
| 395 | } | ||
| 396 | ret = tls_ocsp_verify_response(ctx, resp); | ||
| 397 | OCSP_RESPONSE_free(resp); | ||
| 398 | return ret; | ||
| 399 | } | ||
diff --git a/src/usr.bin/nc/netcat.c b/src/usr.bin/nc/netcat.c index 3af7d50374..64e77a8b52 100644 --- a/src/usr.bin/nc/netcat.c +++ b/src/usr.bin/nc/netcat.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: netcat.c,v 1.163 2016/09/03 17:35:34 bcook Exp $ */ | 1 | /* $OpenBSD: netcat.c,v 1.164 2016/11/02 15:18:42 beck Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2001 Eric Jackson <ericj@monkey.org> | 3 | * Copyright (c) 2001 Eric Jackson <ericj@monkey.org> |
| 4 | * Copyright (c) 2015 Bob Beck. All rights reserved. | 4 | * Copyright (c) 2015 Bob Beck. All rights reserved. |
| @@ -1518,6 +1518,8 @@ void | |||
| 1518 | report_tls(struct tls * tls_ctx, char * host, char *tls_expectname) | 1518 | report_tls(struct tls * tls_ctx, char * host, char *tls_expectname) |
| 1519 | { | 1519 | { |
| 1520 | time_t t; | 1520 | time_t t; |
| 1521 | const char *ocsp_url; | ||
| 1522 | |||
| 1521 | fprintf(stderr, "TLS handshake negotiated %s/%s with host %s\n", | 1523 | fprintf(stderr, "TLS handshake negotiated %s/%s with host %s\n", |
| 1522 | tls_conn_version(tls_ctx), tls_conn_cipher(tls_ctx), host); | 1524 | tls_conn_version(tls_ctx), tls_conn_cipher(tls_ctx), host); |
| 1523 | fprintf(stderr, "Peer name: %s\n", | 1525 | fprintf(stderr, "Peer name: %s\n", |
| @@ -1535,6 +1537,40 @@ report_tls(struct tls * tls_ctx, char * host, char *tls_expectname) | |||
| 1535 | if (tls_peer_cert_hash(tls_ctx)) | 1537 | if (tls_peer_cert_hash(tls_ctx)) |
| 1536 | fprintf(stderr, "Cert Hash: %s\n", | 1538 | fprintf(stderr, "Cert Hash: %s\n", |
| 1537 | tls_peer_cert_hash(tls_ctx)); | 1539 | tls_peer_cert_hash(tls_ctx)); |
| 1540 | ocsp_url = tls_peer_ocsp_url(tls_ctx); | ||
| 1541 | fprintf(stderr, "OCSP URL: %s\n", ocsp_url == NULL ? "" : ocsp_url); | ||
| 1542 | fprintf(stderr, "OCSP Stapling:"); | ||
| 1543 | switch (tls_peer_ocsp_response_status(tls_ctx)) { | ||
| 1544 | case TLS_OCSP_RESPONSE_SUCCESSFUL: | ||
| 1545 | fprintf(stderr, " %s\n", | ||
| 1546 | tls_peer_ocsp_result(tls_ctx) == NULL ? "" : | ||
| 1547 | tls_peer_ocsp_result(tls_ctx)); | ||
| 1548 | fprintf(stderr, | ||
| 1549 | " response_status=%d cert_status=%d crl_reason=%d\n", | ||
| 1550 | tls_peer_ocsp_response_status(tls_ctx), | ||
| 1551 | tls_peer_ocsp_cert_status(tls_ctx), | ||
| 1552 | tls_peer_ocsp_crl_reason(tls_ctx)); | ||
| 1553 | t = tls_peer_ocsp_this_update(tls_ctx); | ||
| 1554 | fprintf(stderr, " this update: %s", | ||
| 1555 | t != -1 ? ctime(&t) : "\n"); | ||
| 1556 | t = tls_peer_ocsp_next_update(tls_ctx); | ||
| 1557 | fprintf(stderr, " next update: %s", | ||
| 1558 | t != -1 ? ctime(&t) : "\n"); | ||
| 1559 | t = tls_peer_ocsp_revocation_time(tls_ctx); | ||
| 1560 | fprintf(stderr, " revocation: %s", | ||
| 1561 | t != -1 ? ctime(&t) : "\n"); | ||
| 1562 | break; | ||
| 1563 | case -1: | ||
| 1564 | fprintf(stderr, "\n"); | ||
| 1565 | break; | ||
| 1566 | default: | ||
| 1567 | fprintf(stderr, " failure - response_status %d (%s)\n", | ||
| 1568 | tls_peer_ocsp_response_status(tls_ctx), | ||
| 1569 | tls_peer_ocsp_result(tls_ctx) == NULL ? "" : | ||
| 1570 | tls_peer_ocsp_result(tls_ctx)); | ||
| 1571 | break; | ||
| 1572 | |||
| 1573 | } | ||
| 1538 | } | 1574 | } |
| 1539 | 1575 | ||
| 1540 | void | 1576 | void |
