|
Packit Service |
4684c1 |
/*
|
|
Packit Service |
4684c1 |
* Copyright (C) 2012-2017 Free Software Foundation, Inc.
|
|
Packit Service |
4684c1 |
* Copyright (C) 2017 Red Hat, Inc.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Author: Simon Josefsson, Nikos Mavrogiannopoulos
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This file is part of GnuTLS.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* The GnuTLS is free software; you can redistribute it and/or
|
|
Packit Service |
4684c1 |
* modify it under the terms of the GNU Lesser General Public License
|
|
Packit Service |
4684c1 |
* as published by the Free Software Foundation; either version 2.1 of
|
|
Packit Service |
4684c1 |
* the License, or (at your option) any later version.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This library is distributed in the hope that it will be useful, but
|
|
Packit Service |
4684c1 |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
4684c1 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit Service |
4684c1 |
* Lesser General Public License for more details.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* You should have received a copy of the GNU Lesser General Public License
|
|
Packit Service |
4684c1 |
* along with this program. If not, see <https://www.gnu.org/licenses/>
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/*
|
|
Packit Service |
4684c1 |
Status Request (OCSP) TLS extension. See RFC 6066 section 8:
|
|
Packit Service |
4684c1 |
https://tools.ietf.org/html/rfc6066#section-8
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#include "gnutls_int.h"
|
|
Packit Service |
4684c1 |
#include "errors.h"
|
|
Packit Service |
4684c1 |
#include <hello_ext.h>
|
|
Packit Service |
4684c1 |
#include <ext/status_request.h>
|
|
Packit Service |
4684c1 |
#include <mbuffers.h>
|
|
Packit Service |
4684c1 |
#include <auth.h>
|
|
Packit Service |
4684c1 |
#include <auth/cert.h>
|
|
Packit Service |
4684c1 |
#include <handshake.h>
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#ifdef ENABLE_OCSP
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
typedef struct {
|
|
Packit Service |
4684c1 |
/* server response */
|
|
Packit Service |
4684c1 |
gnutls_datum_t sresp;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
unsigned int expect_cstatus;
|
|
Packit Service |
4684c1 |
} status_request_ext_st;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/*
|
|
Packit Service |
4684c1 |
From RFC 6066. Client sends:
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
struct {
|
|
Packit Service |
4684c1 |
CertificateStatusType status_type;
|
|
Packit Service |
4684c1 |
select (status_type) {
|
|
Packit Service |
4684c1 |
case ocsp: OCSPStatusRequest;
|
|
Packit Service |
4684c1 |
} request;
|
|
Packit Service |
4684c1 |
} CertificateStatusRequest;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
enum { ocsp(1), (255) } CertificateStatusType;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
struct {
|
|
Packit Service |
4684c1 |
ResponderID responder_id_list<0..2^16-1>;
|
|
Packit Service |
4684c1 |
Extensions request_extensions;
|
|
Packit Service |
4684c1 |
} OCSPStatusRequest;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
opaque ResponderID<1..2^16-1>;
|
|
Packit Service |
4684c1 |
opaque Extensions<0..2^16-1>;
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int
|
|
Packit Service |
4684c1 |
client_send(gnutls_session_t session,
|
|
Packit Service |
4684c1 |
gnutls_buffer_st * extdata, status_request_ext_st * priv)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
const uint8_t data[5] = "\x01\x00\x00\x00\x00";
|
|
Packit Service |
4684c1 |
const int len = 5;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* We do not support setting either ResponderID or Extensions */
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_buffer_append_data(extdata, data, len);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
session->internals.hsk_flags |= HSK_OCSP_REQUESTED;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return len;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int
|
|
Packit Service |
4684c1 |
server_recv(gnutls_session_t session,
|
|
Packit Service |
4684c1 |
const uint8_t * data, size_t data_size)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
unsigned rid_bytes = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* minimum message is type (1) + responder_id_list (2) +
|
|
Packit Service |
4684c1 |
request_extension (2) = 5 */
|
|
Packit Service |
4684c1 |
if (data_size < 5)
|
|
Packit Service |
4684c1 |
return
|
|
Packit Service |
4684c1 |
gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* We ignore non-ocsp CertificateStatusType. The spec is unclear
|
|
Packit Service |
4684c1 |
what should be done. */
|
|
Packit Service |
4684c1 |
if (data[0] != 0x01) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
_gnutls_handshake_log("EXT[%p]: unknown status_type %d\n",
|
|
Packit Service |
4684c1 |
session, data[0]);
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
DECR_LEN(data_size, 1);
|
|
Packit Service |
4684c1 |
data++;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
rid_bytes = _gnutls_read_uint16(data);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
DECR_LEN(data_size, 2);
|
|
Packit Service |
4684c1 |
/*data += 2;*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* sanity check only, we don't use any of the data below */
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (data_size < rid_bytes)
|
|
Packit Service |
4684c1 |
return
|
|
Packit Service |
4684c1 |
gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_handshake_log("EXT[%p]: OCSP status was requested\n", session);
|
|
Packit Service |
4684c1 |
session->internals.hsk_flags |= HSK_OCSP_REQUESTED;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int
|
|
Packit Service |
4684c1 |
client_recv(gnutls_session_t session,
|
|
Packit Service |
4684c1 |
status_request_ext_st * priv,
|
|
Packit Service |
4684c1 |
const uint8_t * data, size_t size)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
if (size != 0)
|
|
Packit Service |
4684c1 |
return
|
|
Packit Service |
4684c1 |
gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
|
|
Packit Service |
4684c1 |
else {
|
|
Packit Service |
4684c1 |
priv->expect_cstatus = 1;
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/*
|
|
Packit Service |
4684c1 |
* Servers return a certificate response along with their certificate
|
|
Packit Service |
4684c1 |
* by sending a "CertificateStatus" message immediately after the
|
|
Packit Service |
4684c1 |
* "Certificate" message (and before any "ServerKeyExchange" or
|
|
Packit Service |
4684c1 |
* "CertificateRequest" messages). If a server returns a
|
|
Packit Service |
4684c1 |
* "CertificateStatus" message, then the server MUST have included an
|
|
Packit Service |
4684c1 |
* extension of type "status_request" with empty "extension_data" in
|
|
Packit Service |
4684c1 |
* the extended server hello.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* According to the description above, as a server we could simply
|
|
Packit Service |
4684c1 |
* return GNUTLS_E_INT_RET_0 on this function. In that case we would
|
|
Packit Service |
4684c1 |
* only need to use the callbacks at the time we need to send the data,
|
|
Packit Service |
4684c1 |
* and skip the status response packet if no such data are there.
|
|
Packit Service |
4684c1 |
* However, that behavior would break gnutls 3.3.x which expects the status
|
|
Packit Service |
4684c1 |
* response to be always send if the extension is present.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Instead we ensure that this extension is parsed after the CS/certificate
|
|
Packit Service |
4684c1 |
* are selected (with the _GNUTLS_EXT_TLS_POST_CS type), and we discover
|
|
Packit Service |
4684c1 |
* (or not) the response to send early.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
static int
|
|
Packit Service |
4684c1 |
server_send(gnutls_session_t session,
|
|
Packit Service |
4684c1 |
gnutls_buffer_st * extdata, status_request_ext_st * priv)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
gnutls_certificate_credentials_t cred;
|
|
Packit Service |
4684c1 |
gnutls_status_request_ocsp_func func;
|
|
Packit Service |
4684c1 |
void *func_ptr;
|
|
Packit Service |
4684c1 |
const version_entry_st *ver = get_version(session);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cred = (gnutls_certificate_credentials_t)
|
|
Packit Service |
4684c1 |
_gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE);
|
|
Packit Service |
4684c1 |
if (cred == NULL) /* no certificate authentication */
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* no need to set sresp; responses are send during certificate sending and
|
|
Packit Service |
4684c1 |
* no response is required from server side. */
|
|
Packit Service |
4684c1 |
if (ver && ver->multi_ocsp)
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Under TLS1.2 we obtain the response at this point in order to respond
|
|
Packit Service |
4684c1 |
* appropriately (empty extension vs no response) */
|
|
Packit Service |
4684c1 |
if (session->internals.selected_ocsp_length > 0) {
|
|
Packit Service |
4684c1 |
if (session->internals.selected_ocsp[0].response.data) {
|
|
Packit Service |
4684c1 |
if (session->internals.selected_ocsp[0].exptime != 0 &&
|
|
Packit Service |
4684c1 |
(gnutls_time(0) >= session->internals.selected_ocsp[0].exptime)) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_set_datum(&priv->sresp,
|
|
Packit Service |
4684c1 |
session->internals.selected_ocsp[0].response.data,
|
|
Packit Service |
4684c1 |
session->internals.selected_ocsp[0].response.size);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
return GNUTLS_E_INT_RET_0;
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
} else if (session->internals.selected_ocsp_func) {
|
|
Packit Service |
4684c1 |
func = session->internals.selected_ocsp_func;
|
|
Packit Service |
4684c1 |
func_ptr = session->internals.selected_ocsp_func_ptr;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (func == NULL)
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = func(session, func_ptr, &priv->sresp);
|
|
Packit Service |
4684c1 |
if (ret == GNUTLS_E_NO_CERTIFICATE_STATUS)
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
else if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return GNUTLS_E_INT_RET_0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int
|
|
Packit Service |
4684c1 |
_gnutls_status_request_send_params(gnutls_session_t session,
|
|
Packit Service |
4684c1 |
gnutls_buffer_st * extdata)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
gnutls_ext_priv_data_t epriv;
|
|
Packit Service |
4684c1 |
status_request_ext_st *priv;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Do not bother sending the OCSP status request extension
|
|
Packit Service |
4684c1 |
* if we are not using certificate authentication */
|
|
Packit Service |
4684c1 |
if (_gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE) == NULL)
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (session->security_parameters.entity == GNUTLS_CLIENT) {
|
|
Packit Service |
4684c1 |
ret = _gnutls_hello_ext_get_priv(session,
|
|
Packit Service |
4684c1 |
GNUTLS_EXTENSION_STATUS_REQUEST,
|
|
Packit Service |
4684c1 |
&epriv);
|
|
Packit Service |
4684c1 |
if (ret < 0 || epriv == NULL) /* it is ok not to have it */
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
priv = epriv;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return client_send(session, extdata, priv);
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
epriv = priv = gnutls_calloc(1, sizeof(*priv));
|
|
Packit Service |
4684c1 |
if (priv == NULL)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_hello_ext_set_priv(session,
|
|
Packit Service |
4684c1 |
GNUTLS_EXTENSION_STATUS_REQUEST,
|
|
Packit Service |
4684c1 |
epriv);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return server_send(session, extdata, priv);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int
|
|
Packit Service |
4684c1 |
_gnutls_status_request_recv_params(gnutls_session_t session,
|
|
Packit Service |
4684c1 |
const uint8_t * data, size_t size)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
gnutls_ext_priv_data_t epriv;
|
|
Packit Service |
4684c1 |
status_request_ext_st *priv;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (session->security_parameters.entity == GNUTLS_CLIENT) {
|
|
Packit Service |
4684c1 |
ret = _gnutls_hello_ext_get_priv(session,
|
|
Packit Service |
4684c1 |
GNUTLS_EXTENSION_STATUS_REQUEST,
|
|
Packit Service |
4684c1 |
&epriv);
|
|
Packit Service |
4684c1 |
if (ret < 0 || epriv == NULL) /* it is ok not to have it */
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
priv = epriv;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return client_recv(session, priv, data, size);
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
return server_recv(session, data, size);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_ocsp_status_request_enable_client:
|
|
Packit Service |
4684c1 |
* @session: is a #gnutls_session_t type.
|
|
Packit Service |
4684c1 |
* @responder_id: ignored, must be %NULL
|
|
Packit Service |
4684c1 |
* @responder_id_size: ignored, must be zero
|
|
Packit Service |
4684c1 |
* @extensions: ignored, must be %NULL
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function is to be used by clients to request OCSP response
|
|
Packit Service |
4684c1 |
* from the server, using the "status_request" TLS extension. Only
|
|
Packit Service |
4684c1 |
* OCSP status type is supported.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Previous versions of GnuTLS supported setting @responder_id and
|
|
Packit Service |
4684c1 |
* @extensions fields, but due to the difficult semantics of the
|
|
Packit Service |
4684c1 |
* parameter usage, and other issues, this support was removed
|
|
Packit Service |
4684c1 |
* since 3.6.0 and these parameters must be set to %NULL.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
|
|
Packit Service |
4684c1 |
* otherwise a negative error code is returned.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Since: 3.1.3
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
gnutls_ocsp_status_request_enable_client(gnutls_session_t session,
|
|
Packit Service |
4684c1 |
gnutls_datum_t * responder_id,
|
|
Packit Service |
4684c1 |
size_t responder_id_size,
|
|
Packit Service |
4684c1 |
gnutls_datum_t * extensions)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
status_request_ext_st *priv;
|
|
Packit Service |
4684c1 |
gnutls_ext_priv_data_t epriv;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (session->security_parameters.entity == GNUTLS_SERVER)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
epriv = priv = gnutls_calloc(1, sizeof(*priv));
|
|
Packit Service |
4684c1 |
if (priv == NULL)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_hello_ext_set_priv(session,
|
|
Packit Service |
4684c1 |
GNUTLS_EXTENSION_STATUS_REQUEST,
|
|
Packit Service |
4684c1 |
epriv);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static void _gnutls_status_request_deinit_data(gnutls_ext_priv_data_t epriv)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
status_request_ext_st *priv = epriv;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (priv == NULL)
|
|
Packit Service |
4684c1 |
return;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
gnutls_free(priv->sresp.data);
|
|
Packit Service |
4684c1 |
gnutls_free(priv);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
const hello_ext_entry_st ext_mod_status_request = {
|
|
Packit Service |
4684c1 |
.name = "OCSP Status Request",
|
|
Packit Service |
4684c1 |
.tls_id = STATUS_REQUEST_TLS_ID,
|
|
Packit Service |
4684c1 |
.gid = GNUTLS_EXTENSION_STATUS_REQUEST,
|
|
Packit Service |
4684c1 |
.validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_CLIENT_HELLO |
|
|
Packit Service |
4684c1 |
GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
|
|
Packit Service |
4684c1 |
.client_parse_point = _GNUTLS_EXT_TLS_POST_CS,
|
|
Packit Service |
4684c1 |
.server_parse_point = _GNUTLS_EXT_TLS_POST_CS,
|
|
Packit Service |
4684c1 |
.recv_func = _gnutls_status_request_recv_params,
|
|
Packit Service |
4684c1 |
.send_func = _gnutls_status_request_send_params,
|
|
Packit Service |
4684c1 |
.deinit_func = _gnutls_status_request_deinit_data,
|
|
Packit Service |
4684c1 |
.cannot_be_overriden = 1
|
|
Packit Service |
4684c1 |
};
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Functions to be called from handshake */
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
_gnutls_send_server_certificate_status(gnutls_session_t session, int again)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
mbuffer_st *bufel = NULL;
|
|
Packit Service |
4684c1 |
uint8_t *data;
|
|
Packit Service |
4684c1 |
int data_size = 0;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
gnutls_ext_priv_data_t epriv;
|
|
Packit Service |
4684c1 |
status_request_ext_st *priv;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (!(session->internals.hsk_flags & HSK_OCSP_REQUESTED))
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (again == 0) {
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
_gnutls_hello_ext_get_priv(session,
|
|
Packit Service |
4684c1 |
GNUTLS_EXTENSION_STATUS_REQUEST,
|
|
Packit Service |
4684c1 |
&epriv);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
priv = epriv;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (!priv->sresp.size)
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
data_size = priv->sresp.size + 4;
|
|
Packit Service |
4684c1 |
bufel =
|
|
Packit Service |
4684c1 |
_gnutls_handshake_alloc(session, data_size);
|
|
Packit Service |
4684c1 |
if (!bufel) {
|
|
Packit Service |
4684c1 |
_gnutls_free_datum(&priv->sresp);
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
data = _mbuffer_get_udata_ptr(bufel);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
data[0] = 0x01;
|
|
Packit Service |
4684c1 |
_gnutls_write_uint24(priv->sresp.size, &data[1]);
|
|
Packit Service |
4684c1 |
memcpy(&data[4], priv->sresp.data, priv->sresp.size);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_free_datum(&priv->sresp);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
return _gnutls_send_handshake(session, data_size ? bufel : NULL,
|
|
Packit Service |
4684c1 |
GNUTLS_HANDSHAKE_CERTIFICATE_STATUS);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
int _gnutls_parse_ocsp_response(gnutls_session_t session, const uint8_t *data, ssize_t data_size, gnutls_datum_t *resp)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
ssize_t r_size;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
resp->data = 0;
|
|
Packit Service |
4684c1 |
resp->size = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* minimum message is type (1) + response (3) + data */
|
|
Packit Service |
4684c1 |
if (data_size < 4)
|
|
Packit Service |
4684c1 |
return
|
|
Packit Service |
4684c1 |
gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (data[0] != 0x01) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
_gnutls_handshake_log("EXT[%p]: unknown status_type %d\n",
|
|
Packit Service |
4684c1 |
session, data[0]);
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
DECR_LENGTH_RET(data_size, 1,
|
|
Packit Service |
4684c1 |
GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
|
|
Packit Service |
4684c1 |
data++;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
DECR_LENGTH_RET(data_size, 3,
|
|
Packit Service |
4684c1 |
GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
r_size = _gnutls_read_uint24(data);
|
|
Packit Service |
4684c1 |
data += 3;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
DECR_LENGTH_RET(data_size, r_size,
|
|
Packit Service |
4684c1 |
GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (r_size < 1)
|
|
Packit Service |
4684c1 |
return
|
|
Packit Service |
4684c1 |
gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_set_datum(resp, data, r_size);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
int _gnutls_recv_server_certificate_status(gnutls_session_t session)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
uint8_t *data;
|
|
Packit Service |
4684c1 |
ssize_t data_size;
|
|
Packit Service |
4684c1 |
gnutls_buffer_st buf;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
gnutls_datum_t resp;
|
|
Packit Service |
4684c1 |
status_request_ext_st *priv = NULL;
|
|
Packit Service |
4684c1 |
gnutls_ext_priv_data_t epriv;
|
|
Packit Service |
4684c1 |
cert_auth_info_t info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (info == NULL)
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
_gnutls_hello_ext_get_priv(session,
|
|
Packit Service |
4684c1 |
GNUTLS_EXTENSION_STATUS_REQUEST,
|
|
Packit Service |
4684c1 |
&epriv);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
priv = epriv;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (!priv->expect_cstatus)
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_recv_handshake(session,
|
|
Packit Service |
4684c1 |
GNUTLS_HANDSHAKE_CERTIFICATE_STATUS,
|
|
Packit Service |
4684c1 |
1, &buf;;
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val_fatal(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
priv->expect_cstatus = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
data = buf.data;
|
|
Packit Service |
4684c1 |
data_size = buf.length;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (data_size == 0) {
|
|
Packit Service |
4684c1 |
ret = 0;
|
|
Packit Service |
4684c1 |
goto error;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_parse_ocsp_response(session, data, data_size, &resp);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto error;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (resp.data && resp.size > 0) {
|
|
Packit Service |
4684c1 |
info->raw_ocsp_list = gnutls_malloc(sizeof(gnutls_datum_t));
|
|
Packit Service |
4684c1 |
if (info->raw_ocsp_list == NULL) {
|
|
Packit Service |
4684c1 |
ret = GNUTLS_E_MEMORY_ERROR;
|
|
Packit Service |
4684c1 |
goto error;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
info->raw_ocsp_list[0].data = resp.data;
|
|
Packit Service |
4684c1 |
info->raw_ocsp_list[0].size = resp.size;
|
|
Packit Service |
4684c1 |
info->nocsp = 1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
error:
|
|
Packit Service |
4684c1 |
_gnutls_buffer_clear(&buf;;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#endif
|