diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2015-02-05 05:34:42 +0100 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2015-02-05 05:34:42 +0100 |
commit | d35f4a0d0be674323076aebd26ae648d57562877 (patch) | |
tree | 22afbd0a4f055500e31731b90ea51aee156a40d8 | |
parent | 0853d5ace1cef8bf4235f06e209f16b3de449014 (diff) | |
download | gnutls-ocsp2.tar.gz |
when verifying account for all responses available via RFC6961 status request extensionocsp2
-rw-r--r-- | lib/gnutls_int.h | 3 | ||||
-rw-r--r-- | lib/gnutls_ui.c | 32 | ||||
-rw-r--r-- | lib/gnutls_x509.c | 64 | ||||
-rw-r--r-- | lib/includes/gnutls/gnutls.h.in | 2 |
4 files changed, 70 insertions, 31 deletions
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index 06a7ec9ed3..a2f919ae86 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -996,7 +996,8 @@ typedef struct { unsigned int hb_retrans_timeout_ms; /* the default timeout, in milliseconds */ unsigned int hb_total_timeout_ms; /* the total timeout, in milliseconds */ - bool ocsp_check_ok; /* will be zero if the OCSP response TLS extension + unsigned int ocsp_check_size; /* the size of ocsp_check_ok */ + bool ocsp_check_ok[DEFAULT_MAX_VERIFY_DEPTH]; /* will be zero if the OCSP response TLS extension * check failed (OCSP was old/unrelated or so). */ heartbeat_state_t hb_state; /* for ping */ diff --git a/lib/gnutls_ui.c b/lib/gnutls_ui.c index 910d7b0f2c..c80c98180a 100644 --- a/lib/gnutls_ui.c +++ b/lib/gnutls_ui.c @@ -749,6 +749,13 @@ int gnutls_load_file(const char *filename, gnutls_datum_t * data) * OCSP validity check on the peer's certificate. Should be called after * any of gnutls_certificate_verify_peers*() are called. * + * In case the peer provided multiple certificate status responses + * (e.g., via the RFC6961 extension), you can specify the index of the + * response to check, by using the GNUTLS_OCSP_SR_SET_IDX() macro in flags. + * The available status responses should correspond with the number of certificates + * sent by the server. Otherwise if multiple certificates are available, this + * function will return non-zero if all responses were valid. + * * If the flag %GNUTLS_OCSP_SR_IS_AVAIL is specified, the return * value of the function indicates whether an OCSP status response have * been received (even if invalid). @@ -761,10 +768,17 @@ gnutls_ocsp_status_request_is_checked(gnutls_session_t session, unsigned int flags) { int ret; + int idx = 0, multi = 0; + unsigned i; gnutls_datum_t data; + if ((flags >> 24) != 0) + idx = GNUTLS_OCSP_SR_GET_IDX(flags); + else + multi = 1; + if (flags & GNUTLS_OCSP_SR_IS_AVAIL) { - ret = gnutls_ocsp_status_request_get_multi(session, &data, 0); + ret = gnutls_ocsp_status_request_get_multi(session, &data, idx); if (ret < 0) return gnutls_assert_val(0); @@ -772,7 +786,21 @@ gnutls_ocsp_status_request_is_checked(gnutls_session_t session, return gnutls_assert_val(0); return 1; } - return session->internals.ocsp_check_ok; + + if (multi) { + ret = 0; + for (i=0;i<session->internals.ocsp_check_size;i++) { + if (session->internals.ocsp_check_ok[i] == 0) + return 0; + } + if (session->internals.ocsp_check_size > 0) + return 1; + return 0; + } else { + if (idx > session->internals.ocsp_check_size) + return 0; + return session->internals.ocsp_check_ok[idx]; + } } #define DESC_SIZE 64 diff --git a/lib/gnutls_x509.c b/lib/gnutls_x509.c index 2ada8f303e..520b116054 100644 --- a/lib/gnutls_x509.c +++ b/lib/gnutls_x509.c @@ -60,7 +60,7 @@ /* If the certificate is revoked status will be GNUTLS_CERT_REVOKED. * * Returns: - * Zero on success, a negative error code otherwise. + * Zero on success, one of the OCSP response was ignored, or a negative error code otherwise. */ static int check_ocsp_response(gnutls_session_t session, gnutls_x509_crt_t cert, @@ -157,8 +157,8 @@ check_ocsp_response(gnutls_session_t session, gnutls_x509_crt_t cert, ret = 0; cleanup: - if (check_failed == 0) - session->internals.ocsp_check_ok = 1; + if (check_failed != 0 && ret == 0) + ret = 1; gnutls_ocsp_resp_deinit(resp); @@ -196,10 +196,10 @@ _gnutls_x509_cert_verify_peers(gnutls_session_t session, gnutls_x509_crt_t issuer = NULL; unsigned int ocsp_status = 0; unsigned int verify_flags; - unsigned issuer_deinit = 0; + unsigned issuer_deinit; /* No OCSP check so far */ - session->internals.ocsp_check_ok = 0; + memset(session->internals.ocsp_check_ok, 0, sizeof(session->internals.ocsp_check_ok)); CHECK_AUTH(GNUTLS_CRD_CERTIFICATE, GNUTLS_E_INVALID_REQUEST); @@ -263,32 +263,40 @@ _gnutls_x509_cert_verify_peers(gnutls_session_t session, if (verify_flags & GNUTLS_VERIFY_DISABLE_CRL_CHECKS) goto skip_ocsp; - ret = gnutls_ocsp_status_request_get(session, &resp); - if (ret < 0) - goto skip_ocsp; + session->internals.ocsp_check_size = 0; + i = 0; + while((ret = gnutls_ocsp_status_request_get_multi(session, &resp, i)) >= 0) { + if (resp.size > 0 && peer_certificate_list_size > i) { + if (peer_certificate_list_size > i+1) { + issuer = peer_certificate_list[i+1]; + issuer_deinit = 0; + } else { + ret = + gnutls_x509_trust_list_get_issuer(cred->tlist, + peer_certificate_list[i], + &issuer, GNUTLS_TL_GET_COPY); + if (ret < 0) { + break; + } + issuer_deinit = 1; + } - if (peer_certificate_list_size > 1) { - issuer = peer_certificate_list[1]; - } else { - ret = - gnutls_x509_trust_list_get_issuer(cred->tlist, - peer_certificate_list - [0], &issuer, GNUTLS_TL_GET_COPY); - if (ret < 0) { - goto skip_ocsp; - } - issuer_deinit = 1; - } + ret = + check_ocsp_response(session, peer_certificate_list[i], issuer, + &resp, &ocsp_status); + if (issuer_deinit != 0) + gnutls_x509_crt_deinit(issuer); - ret = - check_ocsp_response(session, peer_certificate_list[0], issuer, - &resp, &ocsp_status); - if (issuer_deinit != 0) - gnutls_x509_crt_deinit(issuer); + if (ret == 0 && i < sizeof(session->internals.ocsp_check_ok)/sizeof(session->internals.ocsp_check_ok[0])) + session->internals.ocsp_check_ok[i] = 1; - if (ret < 0) { - CLEAR_CERTS; - return gnutls_assert_val(ret); + if (ret < 0) { + CLEAR_CERTS; + return gnutls_assert_val(ret); + } + } + i++; + session->internals.ocsp_check_size++; } #endif diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in index f9b0c06318..63cb8bc7a2 100644 --- a/lib/includes/gnutls/gnutls.h.in +++ b/lib/includes/gnutls/gnutls.h.in @@ -1483,6 +1483,8 @@ gnutls_ocsp_status_request_get_multi(gnutls_session_t session, gnutls_datum_t * response, unsigned idx); #define GNUTLS_OCSP_SR_IS_AVAIL 1 +#define GNUTLS_OCSP_SR_SET_IDX(x) ((x+1)<<24) +#define GNUTLS_OCSP_SR_GET_IDX(x) ((x>>24)-1) int gnutls_ocsp_status_request_is_checked(gnutls_session_t session, unsigned int flags); |