From 92536334518011245095c352ec368da96dc421f7 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Wed, 6 Dec 2017 13:51:52 +0100 Subject: ocsp: moved non-extension related functions to ocsp-api.c That keeps ext/status_response.c clear of items that are not related with the extension handling. Signed-off-by: Nikos Mavrogiannopoulos --- lib/Makefile.am | 2 +- lib/ext/status_request.c | 249 ----------------------------------------- lib/ocsp-api.c | 286 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 287 insertions(+), 250 deletions(-) create mode 100644 lib/ocsp-api.c diff --git a/lib/Makefile.am b/lib/Makefile.am index 3b4ae8bda9..16d7cff875 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -80,7 +80,7 @@ COBJECTS = range.c record.c compress.c debug.c cipher.c gthreads.h handshake-tls system-keys.h urls.c urls.h prf.c auto-verify.c dh-session.c \ cert-session.c handshake-checks.c dtls-sw.c dh-primes.c openpgp_compat.c \ crypto-selftests.c crypto-selftests-pk.c secrets.c extv.c extv.h \ - hello_ext_lib.c hello_ext_lib.h + hello_ext_lib.c hello_ext_lib.h ocsp-api.c if WINDOWS COBJECTS += system/keys-win.c diff --git a/lib/ext/status_request.c b/lib/ext/status_request.c index e8dbaa1827..d99aab6a1a 100644 --- a/lib/ext/status_request.c +++ b/lib/ext/status_request.c @@ -296,213 +296,6 @@ gnutls_ocsp_status_request_enable_client(gnutls_session_t session, return 0; } -/** - * gnutls_ocsp_status_request_get: - * @session: is a #gnutls_session_t type. - * @response: a #gnutls_datum_t with DER encoded OCSP response - * - * This function returns the 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.1.3 - **/ -int -gnutls_ocsp_status_request_get(gnutls_session_t session, - gnutls_datum_t * response) -{ - return gnutls_ocsp_status_request_get2(session, 0, response); -} - -/** - * gnutls_ocsp_status_request_get2: - * @session: is a #gnutls_session_t type. - * @idx: the index of peer's certificate - * @response: a #gnutls_datum_t with DER encoded OCSP response - * - * This function returns the OCSP status response received - * from the TLS server for the certificate index provided. - * The index corresponds to certificates as returned by - * gnutls_certificate_get_peers. When index is zero this - * function operates identically to gnutls_ocsp_status_request_get(). - * - * The returned @response should be treated as - * constant. If no OCSP response is available for the - * given index 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.6.xx - **/ -int -gnutls_ocsp_status_request_get2(gnutls_session_t session, - unsigned idx, - gnutls_datum_t * response) -{ - const version_entry_st *ver = get_version(session); - cert_auth_info_t info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE); - - if (!ver->tls13_sem && session->security_parameters.entity == GNUTLS_SERVER) - return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); - - if (info == NULL || info->raw_ocsp_list == NULL || - idx >= info->nocsp || info->raw_ocsp_list[idx].size == 0) - return - gnutls_assert_val - (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); - - response->data = info->raw_ocsp_list[idx].data; - response->size = info->raw_ocsp_list[idx].size; - - return 0; -} - -/** - * gnutls_certificate_set_ocsp_status_request_function: - * @sc: is a #gnutls_certificate_credentials_t type. - * @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 will be invoked if the client requests an OCSP certificate - * status. The callback may return %GNUTLS_E_NO_CERTIFICATE_STATUS, if - * there is no recent OCSP response. If the callback returns %GNUTLS_E_SUCCESS, - * it is expected to have the @ocsp_response field set with a valid (DER-encoded) - * OCSP response. The response must be a value allocated using gnutls_malloc(), - * and will be deinitialized by the caller. - * - * It is possible to set a specific callback for each provided certificate - * using gnutls_certificate_set_ocsp_status_request_function2(). - * - * Since: 3.1.3 - **/ -void -gnutls_certificate_set_ocsp_status_request_function -(gnutls_certificate_credentials_t sc, -gnutls_status_request_ocsp_func ocsp_func, void *ptr) -{ - - sc->glob_ocsp_func = ocsp_func; - sc->glob_ocsp_func_ptr = ptr; -} - -/** - * gnutls_certificate_set_ocsp_status_request_function2: - * @sc: is a #gnutls_certificate_credentials_t type. - * @idx: is a certificate index as returned by gnutls_certificate_set_key() and friends - * @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 - * provide OCSP status requests that correspond to the indexed certificate chain - * 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 will be invoked if the client requests an OCSP certificate - * status. The callback may return %GNUTLS_E_NO_CERTIFICATE_STATUS, if - * there is no recent OCSP response. If the callback returns %GNUTLS_E_SUCCESS, - * it is expected to have the @ocsp_response field set with a valid (DER-encoded) - * OCSP response. The response must be a value allocated using gnutls_malloc(), - * and will be deinitialized by the caller. - * - * Note: the ability to set multiple OCSP responses per credential - * structure via the index @idx was added in version 3.5.6. To keep - * backwards compatibility, it requires using gnutls_certificate_set_flags() - * with the %GNUTLS_CERTIFICATE_API_V2 flag to make the set certificate - * functions return an index usable by this function. - * - * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, - * otherwise a negative error code is returned. - * - * Since: 3.5.5 - **/ -int -gnutls_certificate_set_ocsp_status_request_function2 -(gnutls_certificate_credentials_t sc, unsigned idx, gnutls_status_request_ocsp_func ocsp_func, void *ptr) -{ - if (idx >= sc->ncerts) - return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); - - sc->certs[idx].ocsp_func = ocsp_func; - sc->certs[idx].ocsp_func_ptr = ptr; - - return 0; -} - -static int file_ocsp_func(gnutls_session_t session, void *ptr, - gnutls_datum_t * ocsp_response) -{ - int ret; - const char *file = ptr; - - ret = gnutls_load_file(file, ocsp_response); - if (ret < 0) - return gnutls_assert_val(GNUTLS_E_NO_CERTIFICATE_STATUS); - - return 0; -} - -/** - * gnutls_certificate_set_ocsp_status_request_file: - * @sc: is a credentials structure. - * @response_file: a filename of the OCSP response - * @idx: is a certificate index as returned by gnutls_certificate_set_key() and friends - * - * This function sets the filename of an OCSP response, that will be - * sent to the client if requests an OCSP certificate status for - * the certificate chain specified by @idx. - * - * This is a convenience function which may be inefficient on busy servers since - * the file is opened on every access. Use - * gnutls_certificate_set_ocsp_status_request_function2() to fine-tune - * file accesses. - * - * Note: the ability to set multiple OCSP responses per credential - * structure via the index @idx was added in version 3.5.6. To keep - * backwards compatibility, it requires using gnutls_certificate_set_flags() - * with the %GNUTLS_CERTIFICATE_API_V2 flag to make the set certificate - * functions return an index usable by this function. - * - * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, - * otherwise a negative error code is returned. - * - * Since: 3.1.3 - **/ -int -gnutls_certificate_set_ocsp_status_request_file(gnutls_certificate_credentials_t sc, - const char *response_file, - unsigned idx) -{ - if (idx >= sc->ncerts) - return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); - - gnutls_free(sc->certs[idx].ocsp_response_file); - sc->certs[idx].ocsp_response_file = gnutls_strdup(response_file); - if (sc->certs[idx].ocsp_response_file == NULL) - return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); - - gnutls_certificate_set_ocsp_status_request_function2(sc, idx, file_ocsp_func, sc->certs[idx].ocsp_response_file); - - return 0; -} static void _gnutls_status_request_deinit_data(gnutls_ext_priv_data_t epriv) { @@ -683,46 +476,4 @@ int _gnutls_recv_server_certificate_status(gnutls_session_t session) return ret; } -/** - * gnutls_ocsp_status_request_is_checked: - * @session: is a gnutls session - * @flags: should be zero or %GNUTLS_OCSP_SR_IS_AVAIL - * - * When flags are zero this function returns non-zero if a valid OCSP status - * response was included in the TLS handshake. That is, an OCSP status response - * which is not too old or superseded. It returns zero otherwise. - * - * When the flag %GNUTLS_OCSP_SR_IS_AVAIL is specified, the function - * returns non-zero if an OCSP status response was included in the handshake - * even if it was invalid. Otherwise, if no OCSP status response was included, - * it returns zero. The %GNUTLS_OCSP_SR_IS_AVAIL flag was introduced in GnuTLS 3.4.0. - * - * This is a helper function when needing to decide whether to perform an - * explicit OCSP validity check on the peer's certificate. Should be called after - * any of gnutls_certificate_verify_peers*() are called. - * - * Returns: non zero if the response was valid, or a zero if it wasn't sent, - * or sent and was invalid. - * - * Since: 3.1.4 - **/ -int -gnutls_ocsp_status_request_is_checked(gnutls_session_t session, - unsigned int flags) -{ - int ret; - gnutls_datum_t data; - - if (flags & GNUTLS_OCSP_SR_IS_AVAIL) { - ret = gnutls_ocsp_status_request_get(session, &data); - if (ret < 0) - return gnutls_assert_val(0); - - if (data.data == NULL) - return gnutls_assert_val(0); - return 1; - } - return session->internals.ocsp_check_ok; -} - #endif diff --git a/lib/ocsp-api.c b/lib/ocsp-api.c new file mode 100644 index 0000000000..b7604f789e --- /dev/null +++ b/lib/ocsp-api.c @@ -0,0 +1,286 @@ +/* + * Copyright (C) 2012-2017 Free Software Foundation, Inc. + * Copyright (C) 2017 Red Hat, Inc. + * + * Author: Simon Josefsson, 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 + * + */ + +/* + * Status Request (OCSP) API. + */ + +#include "gnutls_int.h" +#include "errors.h" +#include +#include +#include + +#ifdef ENABLE_OCSP + +/** + * gnutls_ocsp_status_request_get: + * @session: is a #gnutls_session_t type. + * @response: a #gnutls_datum_t with DER encoded OCSP response + * + * This function returns the 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.1.3 + **/ +int +gnutls_ocsp_status_request_get(gnutls_session_t session, + gnutls_datum_t * response) +{ + return gnutls_ocsp_status_request_get2(session, 0, response); +} + +/** + * gnutls_ocsp_status_request_get2: + * @session: is a #gnutls_session_t type. + * @idx: the index of peer's certificate + * @response: a #gnutls_datum_t with DER encoded OCSP response + * + * This function returns the OCSP status response received + * from the TLS server for the certificate index provided. + * The index corresponds to certificates as returned by + * gnutls_certificate_get_peers. When index is zero this + * function operates identically to gnutls_ocsp_status_request_get(). + * + * The returned @response should be treated as + * constant. If no OCSP response is available for the + * given index 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.6.xx + **/ +int +gnutls_ocsp_status_request_get2(gnutls_session_t session, + unsigned idx, + gnutls_datum_t * response) +{ + const version_entry_st *ver = get_version(session); + cert_auth_info_t info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE); + + if (!ver->tls13_sem && session->security_parameters.entity == GNUTLS_SERVER) + return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); + + if (info == NULL || info->raw_ocsp_list == NULL || + info->nocsp <= idx || info->raw_ocsp_list[idx].size == 0) + return + gnutls_assert_val + (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); + + response->data = info->raw_ocsp_list[idx].data; + response->size = info->raw_ocsp_list[idx].size; + + return 0; +} + +/** + * gnutls_certificate_set_ocsp_status_request_function: + * @sc: is a #gnutls_certificate_credentials_t type. + * @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 will be invoked if the client requests an OCSP certificate + * status. The callback may return %GNUTLS_E_NO_CERTIFICATE_STATUS, if + * there is no recent OCSP response. If the callback returns %GNUTLS_E_SUCCESS, + * it is expected to have the @ocsp_response field set with a valid (DER-encoded) + * OCSP response. The response must be a value allocated using gnutls_malloc(), + * and will be deinitialized by the caller. + * + * It is possible to set a specific callback for each provided certificate + * using gnutls_certificate_set_ocsp_status_request_function2(). + * + * Since: 3.1.3 + **/ +void +gnutls_certificate_set_ocsp_status_request_function +(gnutls_certificate_credentials_t sc, +gnutls_status_request_ocsp_func ocsp_func, void *ptr) +{ + + sc->glob_ocsp_func = ocsp_func; + sc->glob_ocsp_func_ptr = ptr; +} + +/** + * gnutls_certificate_set_ocsp_status_request_function2: + * @sc: is a #gnutls_certificate_credentials_t type. + * @idx: is a certificate index as returned by gnutls_certificate_set_key() and friends + * @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 + * provide OCSP status requests that correspond to the indexed certificate chain + * 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 will be invoked if the client requests an OCSP certificate + * status. The callback may return %GNUTLS_E_NO_CERTIFICATE_STATUS, if + * there is no recent OCSP response. If the callback returns %GNUTLS_E_SUCCESS, + * it is expected to have the @ocsp_response field set with a valid (DER-encoded) + * OCSP response. The response must be a value allocated using gnutls_malloc(), + * and will be deinitialized by the caller. + * + * Note: the ability to set multiple OCSP responses per credential + * structure via the index @idx was added in version 3.5.6. To keep + * backwards compatibility, it requires using gnutls_certificate_set_flags() + * with the %GNUTLS_CERTIFICATE_API_V2 flag to make the set certificate + * functions return an index usable by this function. + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, + * otherwise a negative error code is returned. + * + * Since: 3.5.5 + **/ +int +gnutls_certificate_set_ocsp_status_request_function2 +(gnutls_certificate_credentials_t sc, unsigned idx, gnutls_status_request_ocsp_func ocsp_func, void *ptr) +{ + if (idx >= sc->ncerts) + return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); + + sc->certs[idx].ocsp_func = ocsp_func; + sc->certs[idx].ocsp_func_ptr = ptr; + + return 0; +} + +static int file_ocsp_func(gnutls_session_t session, void *ptr, + gnutls_datum_t * ocsp_response) +{ + int ret; + const char *file = ptr; + + ret = gnutls_load_file(file, ocsp_response); + if (ret < 0) + return gnutls_assert_val(GNUTLS_E_NO_CERTIFICATE_STATUS); + + return 0; +} + +/** + * gnutls_certificate_set_ocsp_status_request_file: + * @sc: is a credentials structure. + * @response_file: a filename of the OCSP response + * @idx: is a certificate index as returned by gnutls_certificate_set_key() and friends + * + * This function sets the filename of an OCSP response, that will be + * sent to the client if requests an OCSP certificate status for + * the certificate chain specified by @idx. + * + * This is a convenience function which may be inefficient on busy servers since + * the file is opened on every access. Use + * gnutls_certificate_set_ocsp_status_request_function2() to fine-tune + * file accesses. + * + * Note: the ability to set multiple OCSP responses per credential + * structure via the index @idx was added in version 3.5.6. To keep + * backwards compatibility, it requires using gnutls_certificate_set_flags() + * with the %GNUTLS_CERTIFICATE_API_V2 flag to make the set certificate + * functions return an index usable by this function. + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, + * otherwise a negative error code is returned. + * + * Since: 3.1.3 + **/ +int +gnutls_certificate_set_ocsp_status_request_file(gnutls_certificate_credentials_t sc, + const char *response_file, + unsigned idx) +{ + if (idx >= sc->ncerts) + return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); + + gnutls_free(sc->certs[idx].ocsp_response_file); + sc->certs[idx].ocsp_response_file = gnutls_strdup(response_file); + if (sc->certs[idx].ocsp_response_file == NULL) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + + gnutls_certificate_set_ocsp_status_request_function2(sc, idx, file_ocsp_func, sc->certs[idx].ocsp_response_file); + + return 0; +} + +/** + * gnutls_ocsp_status_request_is_checked: + * @session: is a gnutls session + * @flags: should be zero or %GNUTLS_OCSP_SR_IS_AVAIL + * + * When flags are zero this function returns non-zero if a valid OCSP status + * response was included in the TLS handshake. That is, an OCSP status response + * which is not too old or superseded. It returns zero otherwise. + * + * When the flag %GNUTLS_OCSP_SR_IS_AVAIL is specified, the function + * returns non-zero if an OCSP status response was included in the handshake + * even if it was invalid. Otherwise, if no OCSP status response was included, + * it returns zero. The %GNUTLS_OCSP_SR_IS_AVAIL flag was introduced in GnuTLS 3.4.0. + * + * This is a helper function when needing to decide whether to perform an + * explicit OCSP validity check on the peer's certificate. Should be called after + * any of gnutls_certificate_verify_peers*() are called. + * + * Returns: non zero if the response was valid, or a zero if it wasn't sent, + * or sent and was invalid. + * + * Since: 3.1.4 + **/ +int +gnutls_ocsp_status_request_is_checked(gnutls_session_t session, + unsigned int flags) +{ + int ret; + gnutls_datum_t data; + + if (flags & GNUTLS_OCSP_SR_IS_AVAIL) { + ret = gnutls_ocsp_status_request_get(session, &data); + if (ret < 0) + return gnutls_assert_val(0); + + if (data.data == NULL) + return gnutls_assert_val(0); + return 1; + } + return session->internals.ocsp_check_ok; +} + +#endif -- cgit v1.2.1