diff options
-rw-r--r-- | doc/Makefile.am | 25 | ||||
-rw-r--r-- | doc/manpages/Makefile.am | 12 | ||||
-rw-r--r-- | lib/ext/Makefile.am | 4 | ||||
-rw-r--r-- | lib/ext/status_request.c | 413 | ||||
-rw-r--r-- | lib/ext/status_request.h | 30 | ||||
-rw-r--r-- | lib/gnutls_extensions.c | 6 | ||||
-rw-r--r-- | lib/gnutls_int.h | 1 | ||||
-rw-r--r-- | lib/includes/gnutls/gnutls.h.in | 13 | ||||
-rw-r--r-- | lib/libgnutls.map | 2 | ||||
-rw-r--r-- | src/cli-args.def | 6 | ||||
-rw-r--r-- | src/cli.c | 12 | ||||
-rw-r--r-- | src/serv-args.def | 8 | ||||
-rw-r--r-- | src/serv.c | 30 |
13 files changed, 542 insertions, 20 deletions
diff --git a/doc/Makefile.am b/doc/Makefile.am index 549e680264..b375353087 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -496,6 +496,7 @@ ENUMS += enums/gnutls_sec_param_t ENUMS += enums/gnutls_server_name_type_t ENUMS += enums/gnutls_sign_algorithm_t ENUMS += enums/gnutls_supplemental_data_format_type_t +ENUMS += enums/gnutls_tpmkey_fmt_t ENUMS += enums/gnutls_x509_crt_fmt_t ENUMS += enums/gnutls_x509_subject_alt_name_t @@ -1078,14 +1079,6 @@ FUNCS += functions/gnutls_pk_algorithm_get_name FUNCS += functions/gnutls_pk_algorithm_get_name.short FUNCS += functions/gnutls_pk_bits_to_sec_param FUNCS += functions/gnutls_pk_bits_to_sec_param.short -FUNCS += functions/gnutls_pk_get_id -FUNCS += functions/gnutls_pk_get_id.short -FUNCS += functions/gnutls_pk_get_name -FUNCS += functions/gnutls_pk_get_name.short -FUNCS += functions/gnutls_pk_list -FUNCS += functions/gnutls_pk_list.short -FUNCS += functions/gnutls_pk_to_sign -FUNCS += functions/gnutls_pk_to_sign.short FUNCS += functions/gnutls_pkcs11_add_provider FUNCS += functions/gnutls_pkcs11_add_provider.short FUNCS += functions/gnutls_pkcs11_copy_secret_key @@ -1232,6 +1225,14 @@ FUNCS += functions/gnutls_pkcs7_set_crt FUNCS += functions/gnutls_pkcs7_set_crt.short FUNCS += functions/gnutls_pkcs7_set_crt_raw FUNCS += functions/gnutls_pkcs7_set_crt_raw.short +FUNCS += functions/gnutls_pk_get_id +FUNCS += functions/gnutls_pk_get_id.short +FUNCS += functions/gnutls_pk_get_name +FUNCS += functions/gnutls_pk_get_name.short +FUNCS += functions/gnutls_pk_list +FUNCS += functions/gnutls_pk_list.short +FUNCS += functions/gnutls_pk_to_sign +FUNCS += functions/gnutls_pk_to_sign.short FUNCS += functions/gnutls_prf FUNCS += functions/gnutls_prf.short FUNCS += functions/gnutls_prf_raw @@ -1534,6 +1535,10 @@ FUNCS += functions/gnutls_srp_set_server_credentials_function FUNCS += functions/gnutls_srp_set_server_credentials_function.short FUNCS += functions/gnutls_srp_verifier FUNCS += functions/gnutls_srp_verifier.short +FUNCS += functions/gnutls_status_request_ocsp_client +FUNCS += functions/gnutls_status_request_ocsp_client.short +FUNCS += functions/gnutls_status_request_ocsp_server +FUNCS += functions/gnutls_status_request_ocsp_server.short FUNCS += functions/gnutls_store_commitment FUNCS += functions/gnutls_store_commitment.short FUNCS += functions/gnutls_store_pubkey @@ -1910,10 +1915,10 @@ FUNCS += functions/gnutls_x509_crt_set_pubkey FUNCS += functions/gnutls_x509_crt_set_pubkey.short FUNCS += functions/gnutls_x509_crt_set_serial FUNCS += functions/gnutls_x509_crt_set_serial.short -FUNCS += functions/gnutls_x509_crt_set_subject_alt_name -FUNCS += functions/gnutls_x509_crt_set_subject_alt_name.short FUNCS += functions/gnutls_x509_crt_set_subject_alternative_name FUNCS += functions/gnutls_x509_crt_set_subject_alternative_name.short +FUNCS += functions/gnutls_x509_crt_set_subject_alt_name +FUNCS += functions/gnutls_x509_crt_set_subject_alt_name.short FUNCS += functions/gnutls_x509_crt_set_subject_key_id FUNCS += functions/gnutls_x509_crt_set_subject_key_id.short FUNCS += functions/gnutls_x509_crt_set_version diff --git a/doc/manpages/Makefile.am b/doc/manpages/Makefile.am index ff952ef893..7a9979dc40 100644 --- a/doc/manpages/Makefile.am +++ b/doc/manpages/Makefile.am @@ -367,10 +367,6 @@ APIMANS += gnutls_pem_base64_encode_alloc.3 APIMANS += gnutls_perror.3 APIMANS += gnutls_pk_algorithm_get_name.3 APIMANS += gnutls_pk_bits_to_sec_param.3 -APIMANS += gnutls_pk_get_id.3 -APIMANS += gnutls_pk_get_name.3 -APIMANS += gnutls_pk_list.3 -APIMANS += gnutls_pk_to_sign.3 APIMANS += gnutls_pkcs11_add_provider.3 APIMANS += gnutls_pkcs11_copy_secret_key.3 APIMANS += gnutls_pkcs11_copy_x509_crt.3 @@ -444,6 +440,10 @@ APIMANS += gnutls_pkcs7_set_crl.3 APIMANS += gnutls_pkcs7_set_crl_raw.3 APIMANS += gnutls_pkcs7_set_crt.3 APIMANS += gnutls_pkcs7_set_crt_raw.3 +APIMANS += gnutls_pk_get_id.3 +APIMANS += gnutls_pk_get_name.3 +APIMANS += gnutls_pk_list.3 +APIMANS += gnutls_pk_to_sign.3 APIMANS += gnutls_prf.3 APIMANS += gnutls_prf_raw.3 APIMANS += gnutls_priority_certificate_type_list.3 @@ -595,6 +595,8 @@ APIMANS += gnutls_srp_set_prime_bits.3 APIMANS += gnutls_srp_set_server_credentials_file.3 APIMANS += gnutls_srp_set_server_credentials_function.3 APIMANS += gnutls_srp_verifier.3 +APIMANS += gnutls_status_request_ocsp_client.3 +APIMANS += gnutls_status_request_ocsp_server.3 APIMANS += gnutls_store_commitment.3 APIMANS += gnutls_store_pubkey.3 APIMANS += gnutls_strerror.3 @@ -783,8 +785,8 @@ APIMANS += gnutls_x509_crt_set_proxy.3 APIMANS += gnutls_x509_crt_set_proxy_dn.3 APIMANS += gnutls_x509_crt_set_pubkey.3 APIMANS += gnutls_x509_crt_set_serial.3 -APIMANS += gnutls_x509_crt_set_subject_alt_name.3 APIMANS += gnutls_x509_crt_set_subject_alternative_name.3 +APIMANS += gnutls_x509_crt_set_subject_alt_name.3 APIMANS += gnutls_x509_crt_set_subject_key_id.3 APIMANS += gnutls_x509_crt_set_version.3 APIMANS += gnutls_x509_crt_sign.3 diff --git a/lib/ext/Makefile.am b/lib/ext/Makefile.am index 48a635e902..ca6628e8af 100644 --- a/lib/ext/Makefile.am +++ b/lib/ext/Makefile.am @@ -38,4 +38,6 @@ libgnutls_ext_la_SOURCES = max_record.c cert_type.c \ server_name.c signature.c safe_renegotiation.c \ max_record.h cert_type.h server_name.h srp.h \ session_ticket.h signature.h safe_renegotiation.h \ - session_ticket.c srp.c ecc.c ecc.h heartbeat.c heartbeat.h + session_ticket.c srp.c ecc.c ecc.h heartbeat.c heartbeat.h \ + status_request.h status_request.c + diff --git a/lib/ext/status_request.c b/lib/ext/status_request.c new file mode 100644 index 0000000000..07d6516434 --- /dev/null +++ b/lib/ext/status_request.c @@ -0,0 +1,413 @@ +/* + * Copyright (C) 2012 Free Software Foundation, Inc. + * + * Author: Simon Josefsson + * + * 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 3 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 6066 section 8: + https://tools.ietf.org/html/rfc6066#section-8 +*/ + +#include "gnutls_int.h" +#include "gnutls_errors.h" +#include <gnutls_extensions.h> +#include <ext/status_request.h> + +typedef struct +{ + gnutls_datum_t *responder_id; + size_t responder_id_size; + gnutls_datum_t request_extensions; + int dealloc; + + gnutls_status_request_ocsp_func ocsp_func; + void *ocsp_func_ptr; + + int expect_certificate_status; +} status_request_ext_st; + +/* + From RFC 6066. Client sends: + + struct { + CertificateStatusType status_type; + select (status_type) { + case ocsp: OCSPStatusRequest; + } request; + } CertificateStatusRequest; + + enum { ocsp(1), (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>; +*/ + +static int +client_send (gnutls_session_t session, + gnutls_buffer_st* extdata, + status_request_ext_st *priv) +{ + int ret_len = 1 + 2; + int ret; + size_t i; + + ret = _gnutls_buffer_append_prefix (extdata, 8, 1); + 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_len += 2 + priv->responder_id[i].size; + } + + 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 += 2 + priv->request_extensions.size; + + return ret_len; +} + +static int +server_recv (gnutls_session_t session, + status_request_ext_st *priv, + const uint8_t * data, + size_t size) +{ + size_t i; + + _gnutls_handshake_log ("EXT[%p]: got ocsp\n", session); + + /* minimum message is type (1) + responder_id_list (2) + + request_extension (2) = 5 */ + if (size < 5) + return gnutls_assert_val (GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + /* We ignore non-ocsp CertificateStatusType. The spec is unclear + what should be done. */ + if (data[0] != '\x01') + { + gnutls_assert (); + _gnutls_handshake_log ("EXT[%p]: unknown status_type %d\n", + session, data[0]); + return 0; + } + size--, data++; + + priv->dealloc = 1; + + priv->responder_id_size = _gnutls_read_uint16 (data); + size -= 2, data += 2; + + if (size <= priv->responder_id_size * 2) + return gnutls_assert_val (GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + + priv->responder_id = gnutls_malloc (priv->responder_id_size + * sizeof (*priv->responder_id)); + if (priv->responder_id == NULL) + return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR); + + for (i = 0; i < priv->responder_id_size; i++) + { + size_t l; + + if (size <= 2) + return gnutls_assert_val (GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + l = _gnutls_read_uint16 (data); + size -= 2, data += 2; + + if (size <= l) + return gnutls_assert_val (GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + + priv->responder_id[i].data = gnutls_malloc (l); + if (priv->responder_id[i].data == NULL) + return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR); + + memcpy (priv->responder_id[i].data, data, l); + priv->responder_id[i].size = l; + + size -= l, data += l; + } + + return 0; +} + +/* + 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; + + if (priv->ocsp_func == NULL) + return gnutls_assert_val (GNUTLS_E_SUCCESS); + + ret = priv->ocsp_func (session, priv->ocsp_func_ptr, NULL); + if (ret == GNUTLS_E_NO_CERTIFICATE_STATUS) + return 0; + else if (ret != GNUTLS_E_SUCCESS) + return gnutls_assert_val (ret); + + ret = _gnutls_buffer_append_data (extdata, "", 0); + if (ret < 0) + return gnutls_assert_val (ret); + + priv->expect_certificate_status = 1; + + return 0; +} + +static int +client_recv (gnutls_session_t session, + status_request_ext_st *priv, + const uint8_t * data, + size_t size) +{ + if (size != 0) + return gnutls_assert_val (GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + priv->expect_certificate_status = 1; + + return 0; +} + +static int +_gnutls_status_request_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, + &epriv); + if (ret < 0) /* it is ok not to have it */ + return 0; + + priv = epriv.ptr; + + if (session->security_parameters.entity == GNUTLS_CLIENT) + return client_send (session, extdata, priv); + return server_send (session, extdata, priv); +} + +static int +_gnutls_status_request_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, + &epriv); + if (ret < 0) /* it is ok not to have it */ + return 0; + + priv = epriv.ptr; + + if (session->security_parameters.entity == GNUTLS_CLIENT) + return client_recv (session, priv, data, size); + return server_recv (session, priv, data, size); +} + +/** + * gnutls_status_request_ocsp_client: + * @session: is a #gnutls_session_t structure. + * @responder_id: array with #gnutls_datum_t with DER data of responder id + * @responder_id_size: number of members in @responder_id array + * @request_extensions: a #gnutls_datum_t with DER encoded OCSP extensions + * + * This function is to be used by clients to request OCSP response + * from the server, using the "status_request" TLS extension. Only + * OCSP status type is supported. + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, + * otherwise a negative error code is returned. + **/ +int +gnutls_status_request_ocsp_client (gnutls_session_t session, + gnutls_datum_t *responder_id, + size_t responder_id_size, + gnutls_datum_t *request_extensions) +{ + status_request_ext_st *priv; + extension_priv_data_t epriv; + + if (session->security_parameters.entity == GNUTLS_SERVER) + return gnutls_assert_val (GNUTLS_E_INVALID_REQUEST); + + 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 (request_extensions) + { + priv->request_extensions.data = request_extensions->data; + priv->request_extensions.size = request_extensions->size; + } + + _gnutls_ext_set_session_data (session, + GNUTLS_EXTENSION_STATUS_REQUEST, + epriv); + + return 0; +} + +/** + * gnutls_status_request_ocsp_server: + * @session: is a #gnutls_session_t structure. + * @ocsp_func: function pointer to OCSP status request callback. + * @ptr: opaque pointer passed to callback function + * + * This function is to be used by server to register a callback to + * handle OCSP status requests from the client. The callback will be + * invoked if the client supplied a status-request OCSP extension. + * The callback function prototype is: + * + * typedef int (*gnutls_status_request_ocsp_func) + * (gnutls_session_t session, void *ptr, gnutls_datum_t *ocsp_response); + * + * The callback may be invoked up to two times for each handshake. It + * is called the first time when the client hello requested the status + * request extension. In this case, ocsp_response is NULL. The + * purpose of the first callback invocation is to determine whether + * the server will acknowledge the client's request to use the + * extension. The callback may return + * %GNUTLS_E_NO_CERTIFICATE_STATUS, in which case the server will not + * enable the extension. If the callback returns %GNUTLS_E_SUCCESS, + * the server enable the extension. If the callback returns another + * error code, the handshake will terminate. + * + * If the first call to the callback enabled the extension, there will + * usually be a second phase, with a non-NULL ocsp_response. Now the + * server is ready to send the CertificateStatus, and it expects the + * callback to provide the OCSP response data. The callback can at + * this point return %GNUTLS_E_NO_CERTIFICATE_STATUS to avoid sending + * a CertificateStatus message. If the callback returns + * %GNUTLS_E_SUCCESS the ocsp_response will be sent off to the client. + * If the callback returns an error, the handshake will terminate. + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, + * otherwise a negative error code is returned. + **/ +int +gnutls_status_request_ocsp_server (gnutls_session_t session, + gnutls_status_request_ocsp_func ocsp_func, + void *ptr) +{ + status_request_ext_st *priv; + extension_priv_data_t epriv; + + if (session->security_parameters.entity == GNUTLS_CLIENT) + return gnutls_assert_val (GNUTLS_E_INVALID_REQUEST); + + epriv.ptr = priv = gnutls_calloc (1, sizeof (*priv)); + if (priv == NULL) + return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR); + + priv->ocsp_func = ocsp_func; + priv->ocsp_func_ptr = ptr; + + _gnutls_ext_set_session_data (session, + GNUTLS_EXTENSION_STATUS_REQUEST, + epriv); + + return 0; +} + +static void +_gnutls_status_request_deinit_data (extension_priv_data_t epriv) +{ + status_request_ext_st *priv = epriv.ptr; + size_t i; + + if (priv->dealloc) + { + for (i = 0; i < priv->responder_id_size; i++) + gnutls_free (priv->responder_id[i].data); + gnutls_free (priv->responder_id); + gnutls_free (priv->request_extensions.data); + } + + gnutls_free (priv); +} + +static int +_gnutls_status_request_pack (extension_priv_data_t epriv, + gnutls_buffer_st * ps) +{ + return -1; +} + +static int +_gnutls_status_request_unpack (gnutls_buffer_st * ps, + extension_priv_data_t * _priv) +{ + return -1; +} + +extension_entry_st ext_mod_status_request = { + .name = "STATUS REQUEST", + .type = GNUTLS_EXTENSION_STATUS_REQUEST, + .parse_type = GNUTLS_EXT_TLS, + .recv_func = _gnutls_status_request_recv_params, + .send_func = _gnutls_status_request_send_params, + .pack_func = _gnutls_status_request_pack, + .unpack_func = _gnutls_status_request_unpack, + .deinit_func = _gnutls_status_request_deinit_data +}; diff --git a/lib/ext/status_request.h b/lib/ext/status_request.h new file mode 100644 index 0000000000..dc807f8259 --- /dev/null +++ b/lib/ext/status_request.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2012 Free Software Foundation, Inc. + * + * Author: Simon Josefsson + * + * 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 3 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_H +#define EXT_STATUS_REQUEST_H + +#include <gnutls_extensions.h> + +extern extension_entry_st ext_mod_status_request; + +#endif diff --git a/lib/gnutls_extensions.c b/lib/gnutls_extensions.c index eb07d28621..54797b5ffd 100644 --- a/lib/gnutls_extensions.c +++ b/lib/gnutls_extensions.c @@ -38,6 +38,7 @@ #include <ext/signature.h> #include <ext/safe_renegotiation.h> #include <ext/ecc.h> +#include <ext/status_request.h> #include <gnutls_num.h> @@ -311,10 +312,13 @@ _gnutls_ext_init (void) if (ret != GNUTLS_E_SUCCESS) return ret; - ret = _gnutls_ext_register (&ext_mod_cert_type); + ret = _gnutls_ext_register (&ext_mod_status_request); if (ret != GNUTLS_E_SUCCESS) return ret; + ret = _gnutls_ext_register (&ext_mod_cert_type); + if (ret != GNUTLS_E_SUCCESS) + return ret; ret = _gnutls_ext_register (&ext_mod_server_name); if (ret != GNUTLS_E_SUCCESS) diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index 1949402953..29b7f7b38f 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -254,6 +254,7 @@ typedef enum extensions_t { GNUTLS_EXTENSION_SERVER_NAME = 0, GNUTLS_EXTENSION_MAX_RECORD_SIZE = 1, + GNUTLS_EXTENSION_STATUS_REQUEST = 5, GNUTLS_EXTENSION_CERT_TYPE = 9, GNUTLS_EXTENSION_SUPPORTED_ECC = 10, GNUTLS_EXTENSION_SUPPORTED_ECC_PF = 11, diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in index ef4f1269e7..54fe31fe5e 100644 --- a/lib/includes/gnutls/gnutls.h.in +++ b/lib/includes/gnutls/gnutls.h.in @@ -954,6 +954,17 @@ gnutls_ecc_curve_t gnutls_ecc_curve_get(gnutls_session_t session); int gnutls_key_generate (gnutls_datum_t * key, unsigned int key_size); + /* OCSP status request extension, RFC 6066 */ + typedef int (*gnutls_status_request_ocsp_func) + (gnutls_session_t session, void *ptr, gnutls_datum_t *ocsp_response); + int gnutls_status_request_ocsp_server (gnutls_session_t session, + gnutls_status_request_ocsp_func ocsp_func, + void *ptr); + int gnutls_status_request_ocsp_client (gnutls_session_t session, + gnutls_datum_t *responder_id, + size_t responder_id_size, + gnutls_datum_t *request_extensions); + /* if you just want some defaults, use the following. */ int gnutls_priority_init (gnutls_priority_t * priority_cache, @@ -2030,6 +2041,8 @@ typedef int (*gnutls_pin_callback_t) (void *userdata, int attempt, #define GNUTLS_E_TPM_KEY_NOT_FOUND -333 #define GNUTLS_E_TPM_UNINITIALIZED -334 +#define GNUTLS_E_NO_CERTIFICATE_STATUS -329 + #define GNUTLS_E_UNIMPLEMENTED_FEATURE -1250 diff --git a/lib/libgnutls.map b/lib/libgnutls.map index 8df7823577..8c404facce 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -790,6 +790,8 @@ GNUTLS_3_0_0 { gnutls_pk_to_sign; gnutls_certificate_set_x509_system_trust; gnutls_session_set_premaster; + gnutls_status_request_ocsp_client; + gnutls_status_request_ocsp_server; } GNUTLS_2_12; GNUTLS_3_1_0 { diff --git a/src/cli-args.def b/src/cli-args.def index 1d9bc782dd..17cf85f757 100644 --- a/src/cli-args.def +++ b/src/cli-args.def @@ -56,6 +56,12 @@ flag = { }; flag = { + name = status-request-ocsp; + descrip = "Request OCSP status request"; + doc = "The client will indicate to the server in a TLS extension that it wants a OCSP status request."; +}; + +flag = { name = starttls; value = s; descrip = "Connect, establish a plain session and start TLS."; @@ -68,6 +68,7 @@ int resume, starttls, insecure, rehandshake, udp, mtu; const char *hostname = NULL; const char *service = NULL; int record_max_size; +int status_request_ocsp; int fingerprint; int crlf; unsigned int verbose = 0; @@ -628,6 +629,16 @@ init_tls_session (const char *hostname) if (HAVE_OPT(HEARTBEAT)) gnutls_heartbeat_enable (session, GNUTLS_HB_PEER_ALLOWED_TO_SEND); + /* OCSP status-request TLS extension */ + if (status_request_ocsp > 0 && disable_extensions == 0) + { + if (gnutls_status_request_ocsp_client (session, NULL, 0, NULL) < 0) + { + fprintf (stderr, "Cannot set OCSP status request information.\n"); + exit (1); + } + } + #ifdef ENABLE_SESSION_TICKET if (disable_extensions == 0 && !HAVE_OPT(NOTICKET)t) gnutls_session_ticket_enable_client (session); @@ -1092,6 +1103,7 @@ const char* rest = NULL; } record_max_size = OPT_VALUE_RECORDSIZE; + status_request_ocsp = HAVE_OPT(STATUS_REQUEST_OCSP); fingerprint = HAVE_OPT(FINGERPRINT); if (HAVE_OPT(X509FMTDER)) diff --git a/src/serv-args.def b/src/serv-args.def index e61034e58d..c24e7ebca5 100644 --- a/src/serv-args.def +++ b/src/serv-args.def @@ -228,6 +228,14 @@ flag = { }; flag = { + name = status-response-ocsp; + arg-type = file; + file-exists = yes; + descrip = "OCSP response to send to client"; + doc = "If the client requested an OCSP response, return data from this file to the client."; +}; + +flag = { name = port; value = p; arg-type = number; diff --git a/src/serv.c b/src/serv.c index d3dc35043e..2e9c674726 100644 --- a/src/serv.c +++ b/src/serv.c @@ -81,7 +81,8 @@ const char *x509_ecccertfile = NULL; const char *x509_cafile = NULL; const char *dh_params_file = NULL; const char *x509_crlfile = NULL; -const char *priorities = NULL; +const char * priorities = NULL; +const char * status_response_ocsp = NULL; gnutls_datum_t session_ticket_key; static void tcp_server (const char *name, int port); @@ -329,8 +330,15 @@ generate_rsa_params (void) LIST_DECLARE_INIT (listener_list, listener_item, listener_free); -gnutls_session_t -initialize_session (int dtls) +static int +ocsp_callback (gnutls_session_t session, + void *ptr, + gnutls_datum_t *ocsp_response) +{ + return GNUTLS_E_NO_CERTIFICATE_STATUS; +} + +gnutls_session_t initialize_session (int dtls) { gnutls_session_t session; const char *err; @@ -359,6 +367,19 @@ initialize_session (int dtls) gnutls_session_ticket_enable_server (session, &session_ticket_key); #endif + /* OCSP status-request TLS extension */ + if (status_response_ocsp) + { + if (gnutls_status_request_ocsp_server (session, ocsp_callback, NULL) < 0) + { + fprintf (stderr, "Cannot set OCSP status request callback.\n"); + exit (1); + } + } + + if (noticket == 0) + gnutls_session_ticket_enable_server (session, &session_ticket_key); + if (gnutls_priority_set_direct (session, priorities, &err) < 0) { fprintf (stderr, "Syntax error at: %s\n", err); @@ -1650,6 +1671,9 @@ cmd_parser (int argc, char **argv) if (HAVE_OPT (PSKPASSWD)) psk_passwd = OPT_ARG (PSKPASSWD); + if (HAVE_OPT(STATUS_RESPONSE_OCSP)) + status_response_ocsp = OPT_ARG(STATUS_RESPONSE_OCSP); + } /* session resuming support */ |