summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2015-02-05 05:34:42 +0100
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2015-02-05 05:34:42 +0100
commitd35f4a0d0be674323076aebd26ae648d57562877 (patch)
tree22afbd0a4f055500e31731b90ea51aee156a40d8
parent0853d5ace1cef8bf4235f06e209f16b3de449014 (diff)
downloadgnutls-ocsp2.tar.gz
when verifying account for all responses available via RFC6961 status request extensionocsp2
-rw-r--r--lib/gnutls_int.h3
-rw-r--r--lib/gnutls_ui.c32
-rw-r--r--lib/gnutls_x509.c64
-rw-r--r--lib/includes/gnutls/gnutls.h.in2
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);