diff options
author | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2014-06-06 13:56:01 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2015-02-04 10:23:40 +0100 |
commit | 6758c449e2cc034601cf48f533a9f504591d6e25 (patch) | |
tree | 41c31d23b55f890dd1346984ef90abc4793c7ffd | |
parent | 3a33bfb4118f8f35207210def7bae82f51fa56d2 (diff) | |
download | gnutls-6758c449e2cc034601cf48f533a9f504591d6e25.tar.gz |
Added support to read and send the RFC6961 status request.
-rw-r--r-- | lib/ext/Makefile.am | 3 | ||||
-rw-r--r-- | lib/ext/status_request.c | 192 | ||||
-rw-r--r-- | lib/ext/status_request.h | 38 | ||||
-rw-r--r-- | lib/ext/status_request_multi.c | 274 | ||||
-rw-r--r-- | lib/ext/status_request_multi.h | 30 | ||||
-rw-r--r-- | lib/gnutls_extensions.c | 5 | ||||
-rw-r--r-- | lib/gnutls_int.h | 1 | ||||
-rw-r--r-- | lib/includes/gnutls/gnutls.h.in | 18 |
8 files changed, 481 insertions, 80 deletions
diff --git a/lib/ext/Makefile.am b/lib/ext/Makefile.am index 04edf81b91..608447793d 100644 --- a/lib/ext/Makefile.am +++ b/lib/ext/Makefile.am @@ -40,7 +40,8 @@ libgnutls_ext_la_SOURCES = max_record.c cert_type.c \ session_ticket.h signature.h safe_renegotiation.h \ session_ticket.c srp.c ecc.c ecc.h heartbeat.c heartbeat.h \ status_request.h status_request.c dumbfw.c dumbfw.h \ - ext_master_secret.c ext_master_secret.h etm.h etm.c + ext_master_secret.c ext_master_secret.h etm.h etm.c \ + status_request_multi.c status_request_multi.h if ENABLE_ALPN libgnutls_ext_la_SOURCES += alpn.c alpn.h diff --git a/lib/ext/status_request.c b/lib/ext/status_request.c index 8cefc617e0..78f249f145 100644 --- a/lib/ext/status_request.c +++ b/lib/ext/status_request.c @@ -36,15 +36,6 @@ #ifdef ENABLE_OCSP -typedef struct { - gnutls_datum_t *responder_id; - size_t responder_id_size; - gnutls_datum_t request_extensions; - gnutls_datum_t response; - - unsigned int expect_cstatus; -} status_request_ext_st; - /* From RFC 6066. Client sends: @@ -66,7 +57,7 @@ typedef struct { opaque Extensions<0..2^16-1>; */ -static void deinit_responder_id(status_request_ext_st *priv) +void _gnutls_deinit_responder_id(status_request_ext_st *priv) { unsigned i; @@ -127,14 +118,19 @@ client_send(gnutls_session_t session, return ret_len; } -static int -server_recv(gnutls_session_t session, +int +_gnutls_status_request_server_recv(gnutls_session_t session, status_request_ext_st * priv, - const uint8_t * data, size_t size) + const uint8_t * data, size_t size, unsigned v2) { size_t i; ssize_t data_size = size; + if (priv->status_type != 0) { + gnutls_assert(); + return 0; + } + /* minimum message is type (1) + responder_id_list (2) + request_extension (2) = 5 */ if (data_size < 5) @@ -143,12 +139,14 @@ server_recv(gnutls_session_t session, /* We ignore non-ocsp CertificateStatusType. The spec is unclear what should be done. */ - if (data[0] != 0x01) { + if (data[0] != 0x01 && (v2 == 0 && data[0] != 0x02)) { gnutls_assert(); _gnutls_handshake_log("EXT[%p]: unknown status_type %d\n", session, data[0]); return 0; } + priv->status_type = data[0]; + DECR_LEN(data_size, 1); data++; @@ -162,7 +160,7 @@ server_recv(gnutls_session_t session, gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); if (priv->responder_id != NULL) - deinit_responder_id(priv); + _gnutls_deinit_responder_id(priv); priv->responder_id = gnutls_calloc(1, priv->responder_id_size * sizeof(*priv->responder_id)); @@ -218,7 +216,7 @@ server_send(gnutls_session_t session, return gnutls_assert_val(GNUTLS_E_SUCCESS); ret = - cred->ocsp_func(session, cred->ocsp_func_ptr, &priv->response); + cred->ocsp_func(session, cred->ocsp_func_ptr, &priv->raw_resp); if (ret == GNUTLS_E_NO_CERTIFICATE_STATUS) return 0; else if (ret < 0) @@ -227,16 +225,20 @@ server_send(gnutls_session_t session, return GNUTLS_E_INT_RET_0; } -static int -client_recv(gnutls_session_t session, +int +_gnutls_status_request_client_recv(gnutls_session_t session, status_request_ext_st * priv, - const uint8_t * data, size_t size) + const uint8_t * data, size_t size, unsigned v2) { if (size != 0) return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); else { priv->expect_cstatus = 1; + if (v2) + priv->status_type = 0x2; + else + priv->status_type = 0x1; return 0; } } @@ -289,9 +291,9 @@ _gnutls_status_request_recv_params(gnutls_session_t session, priv = epriv.ptr; if (session->security_parameters.entity == GNUTLS_CLIENT) - return client_recv(session, priv, data, size); + return _gnutls_status_request_client_recv(session, priv, data, size, 0); else - return server_recv(session, priv, data, size); + return _gnutls_status_request_server_recv(session, priv, data, size, 0); } /** @@ -339,6 +341,20 @@ gnutls_ocsp_status_request_enable_client(gnutls_session_t session, GNUTLS_EXTENSION_STATUS_REQUEST, epriv); + epriv.ptr = priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + + priv->responder_id = responder_id; + priv->responder_id_size = responder_id_size; + if (extensions) { + priv->request_extensions.data = extensions->data; + priv->request_extensions.size = extensions->size; + } + _gnutls_ext_set_session_data(session, + GNUTLS_EXTENSION_STATUS_REQUEST_V2, + epriv); + return 0; } @@ -361,30 +377,7 @@ int gnutls_ocsp_status_request_get(gnutls_session_t session, gnutls_datum_t * response) { - status_request_ext_st *priv; - extension_priv_data_t epriv; - int ret; - - if (session->security_parameters.entity == GNUTLS_SERVER) - return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); - - ret = _gnutls_ext_get_session_data(session, - GNUTLS_EXTENSION_STATUS_REQUEST, - &epriv); - if (ret < 0) - return gnutls_assert_val(ret); - - priv = epriv.ptr; - - if (priv == NULL || priv->response.data == NULL) - return - gnutls_assert_val - (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); - - response->data = priv->response.data; - response->size = priv->response.size; - - return 0; + return gnutls_ocsp_status_request_get_multi(session, response, 0); } /** @@ -469,33 +462,62 @@ gnutls_certificate_set_ocsp_status_request_file return 0; } -static void _gnutls_status_request_deinit_data(extension_priv_data_t epriv) +void _gnutls_status_request_deinit_data(extension_priv_data_t epriv) { status_request_ext_st *priv = epriv.ptr; if (priv == NULL) return; - deinit_responder_id(priv); + _gnutls_deinit_responder_id(priv); gnutls_free(priv->request_extensions.data); - gnutls_free(priv->response.data); + gnutls_free(priv->raw_resp.data); gnutls_free(priv); } -static int +static +int _gnutls_status_request_decode_raw_resp(status_request_ext_st *priv) +{ + int len = priv->raw_resp.size; + + if (priv->status_type == 0x01) { + priv->responses[0].data = priv->raw_resp.data; + priv->responses[0].size = priv->raw_resp.size; + priv->responses_size = 1; + } else { + uint8_t *data = priv->raw_resp.data; + unsigned i; + + for (i=0;i<MAX_OCSP_RESPONSES;i++) { + if (len == 0) + break; + DECR_LEN(len, 2); + priv->responses[i].size = _gnutls_read_uint16(data); + data += 2; + DECR_LEN(len, priv->responses[i].size); + priv->responses[i].data = data; + data += priv->responses[i].size; + priv->responses_size++; + } + } + return 0; +} + +int _gnutls_status_request_pack(extension_priv_data_t epriv, gnutls_buffer_st * ps) { status_request_ext_st *priv = epriv.ptr; int ret; - BUFFER_APPEND_PFX4(ps, priv->response.data, priv->response.size); + BUFFER_APPEND_NUM(ps, priv->status_type); + BUFFER_APPEND_PFX4(ps, priv->raw_resp.data, priv->raw_resp.size); return 0; } -static int +int _gnutls_status_request_unpack(gnutls_buffer_st * ps, extension_priv_data_t * epriv) { @@ -508,7 +530,13 @@ _gnutls_status_request_unpack(gnutls_buffer_st * ps, return GNUTLS_E_MEMORY_ERROR; } - BUFFER_POP_DATUM(ps, &priv->response); + BUFFER_POP_NUM(ps, priv->status_type); + BUFFER_POP_DATUM(ps, &priv->raw_resp); + ret = _gnutls_status_request_decode_raw_resp(priv); + if (ret < 0) { + gnutls_assert(); + goto error; + } epriv->ptr = priv; @@ -538,6 +566,7 @@ _gnutls_send_server_certificate_status(gnutls_session_t session, int again) mbuffer_st *bufel = NULL; uint8_t *data; int data_size = 0; + uint32_t magic; int ret; status_request_ext_st *priv = NULL; extension_priv_data_t epriv; @@ -550,22 +579,37 @@ _gnutls_send_server_certificate_status(gnutls_session_t session, int again) return 0; priv = epriv.ptr; - if (!priv->response.size) + if (priv->raw_resp.size < 4) return 0; - data_size = priv->response.size + 4; - bufel = - _gnutls_handshake_alloc(session, data_size); - if (!bufel) - return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); - - data = _mbuffer_get_udata_ptr(bufel); - - data[0] = 0x01; - _gnutls_write_uint24(priv->response.size, &data[1]); - memcpy(&data[4], priv->response.data, priv->response.size); - - _gnutls_free_datum(&priv->response); + memcpy(&magic, priv->raw_resp.data, 4); + if (magic == GNUTLS_OCSP_MULTI_MAGIC) { + data_size = priv->raw_resp.size; + bufel = + _gnutls_handshake_alloc(session, data_size); + if (!bufel) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + + data = _mbuffer_get_udata_ptr(bufel); + + data[0] = 0x02; + _gnutls_write_uint24(priv->raw_resp.size-4, &data[1]); + memcpy(&data[4], priv->raw_resp.data+4, priv->raw_resp.size-4); + } else { + data_size = priv->raw_resp.size + 4; + bufel = + _gnutls_handshake_alloc(session, data_size); + if (!bufel) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + + data = _mbuffer_get_udata_ptr(bufel); + + data[0] = 0x01; + _gnutls_write_uint24(priv->raw_resp.size, &data[1]); + memcpy(&data[4], priv->raw_resp.data, priv->raw_resp.size); + } + + _gnutls_free_datum(&priv->raw_resp); } return _gnutls_send_handshake(session, data_size ? bufel : NULL, GNUTLS_HANDSHAKE_CERTIFICATE_STATUS); @@ -611,9 +655,9 @@ int _gnutls_recv_server_certificate_status(gnutls_session_t session) return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); - if (data[0] != 0x01) { + if (data[0] != priv->status_type) { gnutls_assert(); - _gnutls_handshake_log("EXT[%p]: unknown status_type %d\n", + _gnutls_handshake_log("EXT[%p]: unexpected status_type %d\n", session, data[0]); return 0; } @@ -632,9 +676,17 @@ int _gnutls_recv_server_certificate_status(gnutls_session_t session) GNUTLS_E_UNEXPECTED_PACKET_LENGTH; goto error); - ret = _gnutls_set_datum(&priv->response, data, r_size); - if (ret < 0) + ret = _gnutls_set_datum(&priv->raw_resp, data, r_size); + if (ret < 0) { + gnutls_assert(); + goto error; + } + + ret = _gnutls_status_request_decode_raw_resp(priv); + if (ret < 0) { + gnutls_assert(); goto error; + } ret = 0; diff --git a/lib/ext/status_request.h b/lib/ext/status_request.h index cd1aaeea46..82887ba494 100644 --- a/lib/ext/status_request.h +++ b/lib/ext/status_request.h @@ -25,6 +25,22 @@ #include <gnutls_extensions.h> +#define MAX_OCSP_RESPONSES 16 + +typedef struct { + gnutls_datum_t *responder_id; + size_t responder_id_size; + gnutls_datum_t request_extensions; + gnutls_datum_t raw_resp; + + /* read only */ + gnutls_datum_t responses[MAX_OCSP_RESPONSES]; + unsigned int responses_size; + + unsigned int expect_cstatus; + unsigned int status_type; +} status_request_ext_st; + extern extension_entry_st ext_mod_status_request; int @@ -32,4 +48,26 @@ _gnutls_send_server_certificate_status(gnutls_session_t session, int again); int _gnutls_recv_server_certificate_status(gnutls_session_t session); +void _gnutls_deinit_responder_id(status_request_ext_st *priv); + +int +_gnutls_status_request_server_recv(gnutls_session_t session, + status_request_ext_st * priv, + const uint8_t * data, size_t size, unsigned v2); + +int +_gnutls_status_request_client_recv(gnutls_session_t session, + status_request_ext_st * priv, + const uint8_t * data, size_t size, unsigned v2); + +void _gnutls_status_request_deinit_data(extension_priv_data_t epriv); + +int +_gnutls_status_request_pack(extension_priv_data_t epriv, + gnutls_buffer_st * ps); + +int +_gnutls_status_request_unpack(gnutls_buffer_st * ps, + extension_priv_data_t * epriv); + #endif diff --git a/lib/ext/status_request_multi.c b/lib/ext/status_request_multi.c new file mode 100644 index 0000000000..33217e7bd7 --- /dev/null +++ b/lib/ext/status_request_multi.c @@ -0,0 +1,274 @@ +/* + * Copyright (C) 2014 Red Hat, Inc. + * + * Author: Nikos Mavrogiannopoulos + * + * This file is part of GnuTLS. + * + * The GnuTLS is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +/* + Status Request (OCSP) TLS extension. See RFC 6961 + https://tools.ietf.org/html/rfc6961 +*/ + +#include "gnutls_int.h" +#include "gnutls_errors.h" +#include <gnutls_extensions.h> +#include <ext/status_request_multi.h> +#include <ext/status_request.h> +#include <gnutls_mbuffers.h> +#include <gnutls_auth.h> +#include <auth/cert.h> +#include <gnutls_handshake.h> + +#ifdef ENABLE_OCSP + +/* + From RFC 6961. Client sends: + + struct { + CertificateStatusType status_type; + uint16 request_length; -- Length of request field in bytes + select (status_type) { + case ocsp: OCSPStatusRequest; + case ocsp_multi: OCSPStatusRequest; + } request; + } CertificateStatusRequestItemV2; + + enum { ocsp(1), ocsp_multi(2), (255) } CertificateStatusType; + + struct { + ResponderID responder_id_list<0..2^16-1>; + Extensions request_extensions; + } OCSPStatusRequest; + + opaque ResponderID<1..2^16-1>; + opaque Extensions<0..2^16-1>; + + struct { + CertificateStatusRequestItemV2 certificate_status_req_list<1..2^16-1>; + } CertificateStatusRequestListV2; +*/ + +static int +client_send(gnutls_session_t session, + gnutls_buffer_st *extdata, status_request_ext_st *priv) +{ + int ret, ret_len; + unsigned spos; + size_t i; + + spos = extdata->length; + ret = _gnutls_buffer_append_prefix(extdata, 16, 0); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = _gnutls_buffer_append_prefix(extdata, 8, 2); + if (ret < 0) + return gnutls_assert_val(ret); + + ret = + _gnutls_buffer_append_prefix(extdata, 16, + priv->responder_id_size); + if (ret < 0) + return gnutls_assert_val(ret); + + for (i = 0; i < priv->responder_id_size; i++) { + if (priv->responder_id[i].size <= 0) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + ret = _gnutls_buffer_append_data_prefix(extdata, 16, + priv-> + responder_id[i]. + data, + priv-> + responder_id[i]. + size); + if (ret < 0) + return gnutls_assert_val(ret); + } + + ret = _gnutls_buffer_append_data_prefix(extdata, 16, + priv->request_extensions. + data, + priv->request_extensions. + size); + if (ret < 0) + return gnutls_assert_val(ret); + + ret_len = extdata->length - spos; + _gnutls_write_uint16(ret_len-2, &extdata->data[spos]); + + return ret_len; +} + +/* + Servers return a certificate response along with their certificate + by sending a "CertificateStatus" message immediately after the + "Certificate" message (and before any "ServerKeyExchange" or + "CertificateRequest" messages). If a server returns a + "CertificateStatus" message, then the server MUST have included an + extension of type "status_request" with empty "extension_data" in + the extended server hello. +*/ + +static int +server_send(gnutls_session_t session, + gnutls_buffer_st * extdata, status_request_ext_st * priv) +{ + int ret; + gnutls_certificate_credentials_t cred; + + cred = (gnutls_certificate_credentials_t) + _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE); + if (cred == NULL) /* no certificate authentication */ + return gnutls_assert_val(0); + + if (cred->ocsp_func == NULL) + return gnutls_assert_val(GNUTLS_E_SUCCESS); + + ret = + cred->ocsp_func(session, cred->ocsp_func_ptr, &priv->raw_resp); + if (ret == GNUTLS_E_NO_CERTIFICATE_STATUS) + return 0; + else if (ret < 0) + return gnutls_assert_val(ret); + + return GNUTLS_E_INT_RET_0; +} + +static int +_gnutls_status_request_v2_send_params(gnutls_session_t session, + gnutls_buffer_st * extdata) +{ + extension_priv_data_t epriv; + status_request_ext_st *priv; + int ret; + + ret = _gnutls_ext_get_session_data(session, + GNUTLS_EXTENSION_STATUS_REQUEST_V2, + &epriv); + + if (session->security_parameters.entity == GNUTLS_CLIENT) { + if (ret < 0 || epriv.ptr == NULL) /* it is ok not to have it */ + return 0; + priv = epriv.ptr; + + return client_send(session, extdata, priv); + } else { + epriv.ptr = priv = gnutls_calloc(1, sizeof(*priv)); + if (priv == NULL) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + + _gnutls_ext_set_session_data(session, + GNUTLS_EXTENSION_STATUS_REQUEST_V2, + epriv); + + return server_send(session, extdata, priv); + } +} + +static int +_gnutls_status_request_v2_recv_params(gnutls_session_t session, + const uint8_t * data, size_t size) +{ + extension_priv_data_t epriv; + status_request_ext_st *priv; + int ret; + + ret = _gnutls_ext_get_session_data(session, + GNUTLS_EXTENSION_STATUS_REQUEST_V2, + &epriv); + if (ret < 0 || epriv.ptr == NULL) /* it is ok not to have it */ + return 0; + + priv = epriv.ptr; + + if (session->security_parameters.entity == GNUTLS_CLIENT) + return _gnutls_status_request_client_recv(session, priv, data, size, 1); + else + return _gnutls_status_request_server_recv(session, priv, data, size, 1); +} + +/** + * gnutls_ocsp_status_request_get_multi: + * @session: is a #gnutls_session_t structure. + * @response: a #gnutls_datum_t with DER encoded OCSP response + * @idx: the index of the response to retrieve (starting from zero) + * + * This function returns the indexed OCSP status response received + * from the TLS server. The @response should be treated as + * constant. If no OCSP response is available then + * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned. + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, + * otherwise a negative error code is returned. + * + * Since: 3.3.5 + **/ +int +gnutls_ocsp_status_request_get_multi(gnutls_session_t session, + gnutls_datum_t *response, unsigned idx) +{ + status_request_ext_st *priv; + extension_priv_data_t epriv; + int ret; + + if (session->security_parameters.entity == GNUTLS_SERVER) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + ret = _gnutls_ext_get_session_data(session, + GNUTLS_EXTENSION_STATUS_REQUEST_V2, + &epriv); + if (ret < 0) { + ret = _gnutls_ext_get_session_data(session, + GNUTLS_EXTENSION_STATUS_REQUEST, + &epriv); + if (ret < 0) + return gnutls_assert_val(ret); + } + + priv = epriv.ptr; + + if (priv == NULL || idx >= priv->responses_size) + return + gnutls_assert_val + (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); + + if (priv->responses[idx].data == NULL) + return + gnutls_assert_val + (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); + + response->data = priv->responses[idx].data; + response->size = priv->responses[idx].size; + + return 0; +} + +extension_entry_st ext_mod_status_request_v2 = { + .name = "STATUS REQUEST V2", + .type = GNUTLS_EXTENSION_STATUS_REQUEST_V2, + .parse_type = GNUTLS_EXT_TLS, + .recv_func = _gnutls_status_request_v2_recv_params, + .send_func = _gnutls_status_request_v2_send_params, + .pack_func = _gnutls_status_request_pack, + .unpack_func = _gnutls_status_request_unpack, + .deinit_func = _gnutls_status_request_deinit_data +}; + +#endif diff --git a/lib/ext/status_request_multi.h b/lib/ext/status_request_multi.h new file mode 100644 index 0000000000..1826e6772b --- /dev/null +++ b/lib/ext/status_request_multi.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2014 Red Hat, Inc. + * + * Author: Nikos Mavrogiannopoulos + * + * This file is part of GnuTLS. + * + * The GnuTLS is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +#ifndef EXT_STATUS_REQUEST_MULTI_H +#define EXT_STATUS_REQUEST_MULTI_H + +#include <gnutls_extensions.h> + +extern extension_entry_st ext_mod_status_request_v2; + +#endif diff --git a/lib/gnutls_extensions.c b/lib/gnutls_extensions.c index 3c5d45289a..cdc92f4cfd 100644 --- a/lib/gnutls_extensions.c +++ b/lib/gnutls_extensions.c @@ -40,6 +40,7 @@ #include <ext/ecc.h> #include <ext/status_request.h> #include <ext/ext_master_secret.h> +#include <ext/status_request_multi.h> #include <ext/srtp.h> #include <ext/alpn.h> #include <ext/dumbfw.h> @@ -322,6 +323,10 @@ int _gnutls_ext_init(void) return ret; #ifdef ENABLE_OCSP + ret = _gnutls_ext_register(&ext_mod_status_request_v2); + if (ret != GNUTLS_E_SUCCESS) + return ret; + ret = _gnutls_ext_register(&ext_mod_status_request); if (ret != GNUTLS_E_SUCCESS) return ret; diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index ced8fccce9..06a7ec9ed3 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -282,6 +282,7 @@ typedef enum extensions_t { GNUTLS_EXTENSION_SRTP = 14, GNUTLS_EXTENSION_HEARTBEAT = 15, GNUTLS_EXTENSION_ALPN = 16, + GNUTLS_EXTENSION_STATUS_REQUEST_V2 = 17, GNUTLS_EXTENSION_DUMBFW = 21, GNUTLS_EXTENSION_ETM = 22, GNUTLS_EXTENSION_EXT_MASTER_SECRET = 23, diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in index c8e3fc26b0..f9b0c06318 100644 --- a/lib/includes/gnutls/gnutls.h.in +++ b/lib/includes/gnutls/gnutls.h.in @@ -1451,15 +1451,12 @@ int gnutls_certificate_set_x509_crl(gnutls_certificate_credentials_t res, gnutls_x509_crl_t * crl_list, int crl_list_size); -int gnutls_certificate_get_x509_key(gnutls_certificate_credentials_t res, - unsigned index, - gnutls_x509_privkey_t *key); -int gnutls_certificate_get_x509_crt(gnutls_certificate_credentials_t res, - unsigned index, - gnutls_x509_crt_t **crt_list, - unsigned *crt_list_size); - - /* OCSP status request extension, RFC 6066 */ +/* OCSP status request extension, RFC 6066 */ + +/* The magic number that files containing more than a single OCSP + * status response have. */ +#define GNUTLS_OCSP_MULTI_MAGIC 0xcece15ab + typedef int (*gnutls_status_request_ocsp_func) (gnutls_session_t session, void *ptr, gnutls_datum_t * ocsp_response); @@ -1481,6 +1478,9 @@ int gnutls_ocsp_status_request_enable_client(gnutls_session_t session, int gnutls_ocsp_status_request_get(gnutls_session_t session, gnutls_datum_t * response); +int +gnutls_ocsp_status_request_get_multi(gnutls_session_t session, + gnutls_datum_t * response, unsigned idx); #define GNUTLS_OCSP_SR_IS_AVAIL 1 int gnutls_ocsp_status_request_is_checked(gnutls_session_t session, |