|
Packit Service |
4684c1 |
/*
|
|
Packit Service |
4684c1 |
* Copyright (C) 2001-2018 Free Software Foundation, Inc.
|
|
Packit Service |
4684c1 |
* Copyright (C) 2015-2018 Red Hat, Inc.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Author: Nikos Mavrogiannopoulos, Simon Josefsson
|
|
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 |
/* Functions that relate to the TLS hello extension parsing.
|
|
Packit Service |
4684c1 |
* Hello extensions are packets appended in the TLS hello packet, and
|
|
Packit Service |
4684c1 |
* allow for extra functionality.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#include "gnutls_int.h"
|
|
Packit Service |
4684c1 |
#include "hello_ext.h"
|
|
Packit Service |
4684c1 |
#include "errors.h"
|
|
Packit Service |
4684c1 |
#include "ext/max_record.h"
|
|
Packit Service |
4684c1 |
#include <ext/server_name.h>
|
|
Packit Service |
4684c1 |
#include <ext/srp.h>
|
|
Packit Service |
4684c1 |
#include <ext/heartbeat.h>
|
|
Packit Service |
4684c1 |
#include <ext/session_ticket.h>
|
|
Packit Service |
4684c1 |
#include <ext/safe_renegotiation.h>
|
|
Packit Service |
4684c1 |
#include <ext/signature.h>
|
|
Packit Service |
4684c1 |
#include <ext/safe_renegotiation.h>
|
|
Packit Service |
4684c1 |
#include "ext/supported_groups.h"
|
|
Packit Service |
4684c1 |
#include "ext/ec_point_formats.h"
|
|
Packit Service |
4684c1 |
#include <ext/status_request.h>
|
|
Packit Service |
4684c1 |
#include <ext/ext_master_secret.h>
|
|
Packit Service |
4684c1 |
#include <ext/supported_versions.h>
|
|
Packit Service |
4684c1 |
#include <ext/post_handshake.h>
|
|
Packit Service |
4684c1 |
#include <ext/srtp.h>
|
|
Packit Service |
4684c1 |
#include <ext/alpn.h>
|
|
Packit Service |
4684c1 |
#include <ext/dumbfw.h>
|
|
Packit Service |
4684c1 |
#include <ext/key_share.h>
|
|
Packit Service |
4684c1 |
#include <ext/pre_shared_key.h>
|
|
Packit Service |
4684c1 |
#include <ext/psk_ke_modes.h>
|
|
Packit Service |
4684c1 |
#include <ext/etm.h>
|
|
Packit Service |
4684c1 |
#include <ext/cookie.h>
|
|
Packit Service |
4684c1 |
#include <ext/early_data.h>
|
|
Packit Service |
4684c1 |
#include <ext/record_size_limit.h>
|
|
Packit Service |
4684c1 |
#include "extv.h"
|
|
Packit Service |
4684c1 |
#include <num.h>
|
|
Packit Service |
4684c1 |
#include <ext/client_cert_type.h>
|
|
Packit Service |
4684c1 |
#include <ext/server_cert_type.h>
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static void
|
|
Packit Service |
4684c1 |
unset_ext_data(gnutls_session_t session, const struct hello_ext_entry_st *, unsigned idx);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static void unset_resumed_ext_data(gnutls_session_t session, const struct hello_ext_entry_st *, unsigned idx);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static hello_ext_entry_st const *extfunc[MAX_EXT_TYPES+1] = {
|
|
Packit Service |
4684c1 |
[GNUTLS_EXTENSION_EXT_MASTER_SECRET] = &ext_mod_ext_master_secret,
|
|
Packit Service |
4684c1 |
[GNUTLS_EXTENSION_SUPPORTED_VERSIONS] = &ext_mod_supported_versions,
|
|
Packit Service |
4684c1 |
[GNUTLS_EXTENSION_POST_HANDSHAKE] = &ext_mod_post_handshake,
|
|
Packit Service |
4684c1 |
[GNUTLS_EXTENSION_ETM] = &ext_mod_etm,
|
|
Packit Service |
4684c1 |
#ifdef ENABLE_OCSP
|
|
Packit Service |
4684c1 |
[GNUTLS_EXTENSION_STATUS_REQUEST] = &ext_mod_status_request,
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
[GNUTLS_EXTENSION_SERVER_NAME] = &ext_mod_server_name,
|
|
Packit Service |
4684c1 |
[GNUTLS_EXTENSION_SAFE_RENEGOTIATION] = &ext_mod_sr,
|
|
Packit Service |
4684c1 |
#ifdef ENABLE_SRP
|
|
Packit Service |
4684c1 |
[GNUTLS_EXTENSION_SRP] = &ext_mod_srp,
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
#ifdef ENABLE_HEARTBEAT
|
|
Packit Service |
4684c1 |
[GNUTLS_EXTENSION_HEARTBEAT] = &ext_mod_heartbeat,
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
[GNUTLS_EXTENSION_SESSION_TICKET] = &ext_mod_session_ticket,
|
|
Packit Service |
4684c1 |
[GNUTLS_EXTENSION_CLIENT_CERT_TYPE] = &ext_mod_client_cert_type,
|
|
Packit Service |
4684c1 |
[GNUTLS_EXTENSION_SERVER_CERT_TYPE] = &ext_mod_server_cert_type,
|
|
Packit Service |
4684c1 |
[GNUTLS_EXTENSION_SUPPORTED_GROUPS] = &ext_mod_supported_groups,
|
|
Packit Service |
4684c1 |
[GNUTLS_EXTENSION_SUPPORTED_EC_POINT_FORMATS] = &ext_mod_supported_ec_point_formats,
|
|
Packit Service |
4684c1 |
[GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS] = &ext_mod_sig,
|
|
Packit Service |
4684c1 |
[GNUTLS_EXTENSION_KEY_SHARE] = &ext_mod_key_share,
|
|
Packit Service |
4684c1 |
[GNUTLS_EXTENSION_COOKIE] = &ext_mod_cookie,
|
|
Packit Service |
4684c1 |
[GNUTLS_EXTENSION_EARLY_DATA] = &ext_mod_early_data,
|
|
Packit Service |
4684c1 |
#ifdef ENABLE_DTLS_SRTP
|
|
Packit Service |
4684c1 |
[GNUTLS_EXTENSION_SRTP] = &ext_mod_srtp,
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
#ifdef ENABLE_ALPN
|
|
Packit Service |
4684c1 |
[GNUTLS_EXTENSION_ALPN] = &ext_mod_alpn,
|
|
Packit Service |
4684c1 |
#endif
|
|
Packit Service |
4684c1 |
[GNUTLS_EXTENSION_RECORD_SIZE_LIMIT] = &ext_mod_record_size_limit,
|
|
Packit Service |
4684c1 |
[GNUTLS_EXTENSION_MAX_RECORD_SIZE] = &ext_mod_max_record_size,
|
|
Packit Service |
4684c1 |
[GNUTLS_EXTENSION_PSK_KE_MODES] = &ext_mod_psk_ke_modes,
|
|
Packit Service |
4684c1 |
[GNUTLS_EXTENSION_PRE_SHARED_KEY] = &ext_mod_pre_shared_key,
|
|
Packit Service |
4684c1 |
/* This must be the last extension registered.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
[GNUTLS_EXTENSION_DUMBFW] = &ext_mod_dumbfw,
|
|
Packit Service |
4684c1 |
};
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static const hello_ext_entry_st *
|
|
Packit Service |
4684c1 |
gid_to_ext_entry(gnutls_session_t session, extensions_t id)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
unsigned i;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
assert(id < MAX_EXT_TYPES);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
for (i=0;i<session->internals.rexts_size;i++) {
|
|
Packit Service |
4684c1 |
if (session->internals.rexts[i].gid == id) {
|
|
Packit Service |
4684c1 |
return &session->internals.rexts[i];
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return extfunc[id];
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static const hello_ext_entry_st *
|
|
Packit Service |
4684c1 |
tls_id_to_ext_entry(gnutls_session_t session, uint16_t tls_id, gnutls_ext_parse_type_t parse_point)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
unsigned i;
|
|
Packit Service |
4684c1 |
const hello_ext_entry_st *e;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
for (i=0;i<session->internals.rexts_size;i++) {
|
|
Packit Service |
4684c1 |
if (session->internals.rexts[i].tls_id == tls_id) {
|
|
Packit Service |
4684c1 |
e = &session->internals.rexts[i];
|
|
Packit Service |
4684c1 |
goto done;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
for (i = 0; i < MAX_EXT_TYPES; i++) {
|
|
Packit Service |
4684c1 |
if (!extfunc[i])
|
|
Packit Service |
4684c1 |
continue;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (extfunc[i]->tls_id == tls_id) {
|
|
Packit Service |
4684c1 |
e = extfunc[i];
|
|
Packit Service |
4684c1 |
goto done;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return NULL;
|
|
Packit Service |
4684c1 |
done:
|
|
Packit Service |
4684c1 |
if (parse_point == GNUTLS_EXT_ANY || (IS_SERVER(session) && e->server_parse_point == parse_point) ||
|
|
Packit Service |
4684c1 |
(!IS_SERVER(session) && e->client_parse_point == parse_point)) {
|
|
Packit Service |
4684c1 |
return e;
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
return NULL;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_ext_get_name:
|
|
Packit Service |
4684c1 |
* @ext: is a TLS extension numeric ID
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Convert a TLS extension numeric ID to a printable string.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: a pointer to a string that contains the name of the
|
|
Packit Service |
4684c1 |
* specified cipher, or %NULL.
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
const char *gnutls_ext_get_name(unsigned int ext)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
size_t i;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
for (i = 0; i < MAX_EXT_TYPES; i++) {
|
|
Packit Service |
4684c1 |
if (!extfunc[i])
|
|
Packit Service |
4684c1 |
continue;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (extfunc[i]->tls_id == ext)
|
|
Packit Service |
4684c1 |
return extfunc[i]->name;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return NULL;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Returns %GNUTLS_EXTENSION_INVALID on error
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
static unsigned tls_id_to_gid(gnutls_session_t session, unsigned tls_id)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
unsigned i;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
for (i=0; i < session->internals.rexts_size; i++) {
|
|
Packit Service |
4684c1 |
if (session->internals.rexts[i].tls_id == tls_id)
|
|
Packit Service |
4684c1 |
return session->internals.rexts[i].gid;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
for (i = 0; i < MAX_EXT_TYPES; i++) {
|
|
Packit Service |
4684c1 |
if (!extfunc[i])
|
|
Packit Service |
4684c1 |
continue;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (extfunc[i]->tls_id == tls_id)
|
|
Packit Service |
4684c1 |
return extfunc[i]->gid;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return GNUTLS_EXTENSION_INVALID;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
typedef struct hello_ext_ctx_st {
|
|
Packit Service |
4684c1 |
gnutls_session_t session;
|
|
Packit Service |
4684c1 |
gnutls_ext_flags_t msg;
|
|
Packit Service |
4684c1 |
gnutls_ext_parse_type_t parse_point;
|
|
Packit Service |
4684c1 |
const hello_ext_entry_st *ext; /* used during send */
|
|
Packit Service |
4684c1 |
unsigned seen_pre_shared_key;
|
|
Packit Service |
4684c1 |
} hello_ext_ctx_st;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static
|
|
Packit Service |
4684c1 |
int hello_ext_parse(void *_ctx, unsigned tls_id, const uint8_t *data, unsigned data_size)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
hello_ext_ctx_st *ctx = _ctx;
|
|
Packit Service |
4684c1 |
gnutls_session_t session = ctx->session;
|
|
Packit Service |
4684c1 |
const hello_ext_entry_st *ext;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (tls_id == PRE_SHARED_KEY_TLS_ID) {
|
|
Packit Service |
4684c1 |
ctx->seen_pre_shared_key = 1;
|
|
Packit Service |
4684c1 |
} else if (ctx->seen_pre_shared_key && session->security_parameters.entity == GNUTLS_SERVER) {
|
|
Packit Service |
4684c1 |
/* the pre-shared key extension must always be the last one,
|
|
Packit Service |
4684c1 |
* draft-ietf-tls-tls13-28: 4.2.11 */
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ext = tls_id_to_ext_entry(session, tls_id, ctx->parse_point);
|
|
Packit Service |
4684c1 |
if (ext == NULL || ext->recv_func == NULL) {
|
|
Packit Service |
4684c1 |
goto ignore;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* we do not hard fail when extensions defined for TLS are used for
|
|
Packit Service |
4684c1 |
* DTLS and vice-versa. They may extend their role in the future. */
|
|
Packit Service |
4684c1 |
if (IS_DTLS(session)) {
|
|
Packit Service |
4684c1 |
if (!(ext->validity & GNUTLS_EXT_FLAG_DTLS)) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto ignore;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
if (!(ext->validity & GNUTLS_EXT_FLAG_TLS)) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto ignore;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (session->security_parameters.entity == GNUTLS_CLIENT) {
|
|
Packit Service |
4684c1 |
if (!(ext->validity & GNUTLS_EXT_FLAG_IGNORE_CLIENT_REQUEST) &&
|
|
Packit Service |
4684c1 |
!_gnutls_hello_ext_is_present(session, ext->gid)) {
|
|
Packit Service |
4684c1 |
_gnutls_debug_log("EXT[%p]: Received unexpected extension '%s/%d'\n", session,
|
|
Packit Service |
4684c1 |
ext->name, (int)tls_id);
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if ((ext->validity & ctx->msg) == 0) {
|
|
Packit Service |
4684c1 |
_gnutls_debug_log("EXT[%p]: Received unexpected extension (%s/%d) for '%s'\n", session,
|
|
Packit Service |
4684c1 |
ext->name, (int)tls_id,
|
|
Packit Service |
4684c1 |
ext_msg_validity_to_str(ctx->msg));
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (session->security_parameters.entity == GNUTLS_SERVER) {
|
|
Packit Service |
4684c1 |
ret = _gnutls_hello_ext_save(session, ext->gid, 1);
|
|
Packit Service |
4684c1 |
if (ret == 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_handshake_log
|
|
Packit Service |
4684c1 |
("EXT[%p]: Parsing extension '%s/%d' (%d bytes)\n",
|
|
Packit Service |
4684c1 |
session, ext->name, (int)tls_id,
|
|
Packit Service |
4684c1 |
data_size);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_ext_set_msg(session, ctx->msg);
|
|
Packit Service |
4684c1 |
if ((ret = ext->recv_func(session, data, data_size)) < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ignore:
|
|
Packit Service |
4684c1 |
if (ext) {
|
|
Packit Service |
4684c1 |
_gnutls_handshake_log
|
|
Packit Service |
4684c1 |
("EXT[%p]: Ignoring extension '%s/%d'\n", session,
|
|
Packit Service |
4684c1 |
ext->name, (int)tls_id);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
_gnutls_parse_hello_extensions(gnutls_session_t session,
|
|
Packit Service |
4684c1 |
gnutls_ext_flags_t msg,
|
|
Packit Service |
4684c1 |
gnutls_ext_parse_type_t parse_point,
|
|
Packit Service |
4684c1 |
const uint8_t * data, int data_size)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
hello_ext_ctx_st ctx;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
msg &= GNUTLS_EXT_FLAG_SET_ONLY_FLAGS_MASK;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ctx.session = session;
|
|
Packit Service |
4684c1 |
ctx.msg = msg;
|
|
Packit Service |
4684c1 |
ctx.parse_point = parse_point;
|
|
Packit Service |
4684c1 |
ctx.seen_pre_shared_key = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_extv_parse(&ctx, hello_ext_parse, data, data_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 |
static
|
|
Packit Service |
4684c1 |
int hello_ext_send(void *_ctx, gnutls_buffer_st *buf)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
hello_ext_ctx_st *ctx = _ctx;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
const hello_ext_entry_st *p = ctx->ext;
|
|
Packit Service |
4684c1 |
gnutls_session_t session = ctx->session;
|
|
Packit Service |
4684c1 |
int appended;
|
|
Packit Service |
4684c1 |
size_t size_prev;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (unlikely(p->send_func == NULL))
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (ctx->parse_point != GNUTLS_EXT_ANY &&
|
|
Packit Service |
4684c1 |
((IS_SERVER(session) && p->server_parse_point != ctx->parse_point) ||
|
|
Packit Service |
4684c1 |
(!IS_SERVER(session) && p->client_parse_point != ctx->parse_point))) {
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (IS_DTLS(session)) {
|
|
Packit Service |
4684c1 |
if (!(p->validity & GNUTLS_EXT_FLAG_DTLS)) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto skip;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
if (!(p->validity & GNUTLS_EXT_FLAG_TLS)) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
goto skip;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if ((ctx->msg & p->validity) == 0) {
|
|
Packit Service |
4684c1 |
goto skip;
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
_gnutls_handshake_log("EXT[%p]: Preparing extension (%s/%d) for '%s'\n", session,
|
|
Packit Service |
4684c1 |
p->name, (int)p->tls_id,
|
|
Packit Service |
4684c1 |
ext_msg_validity_to_str(ctx->msg));
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* ensure we don't send something twice (i.e, overridden extensions in
|
|
Packit Service |
4684c1 |
* client), and ensure we are sending only what we received in server. */
|
|
Packit Service |
4684c1 |
ret = _gnutls_hello_ext_is_present(session, p->gid);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (session->security_parameters.entity == GNUTLS_SERVER) {
|
|
Packit Service |
4684c1 |
/* if client didn't advertise and the override flag is not present */
|
|
Packit Service |
4684c1 |
if (!(p->validity & GNUTLS_EXT_FLAG_IGNORE_CLIENT_REQUEST) && ret == 0)
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
} else {
|
|
Packit Service |
4684c1 |
if (ret != 0) /* already sent */
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
size_prev = buf->length;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_ext_set_msg(session, ctx->msg);
|
|
Packit Service |
4684c1 |
ret = p->send_func(session, buf);
|
|
Packit Service |
4684c1 |
if (ret < 0 && ret != GNUTLS_E_INT_RET_0) {
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
appended = buf->length - size_prev;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* add this extension to the extension list, to know which extensions
|
|
Packit Service |
4684c1 |
* to expect.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
if ((appended > 0 || ret == GNUTLS_E_INT_RET_0) &&
|
|
Packit Service |
4684c1 |
session->security_parameters.entity == GNUTLS_CLIENT) {
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_hello_ext_save(session, p->gid, 0);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
skip:
|
|
Packit Service |
4684c1 |
_gnutls_handshake_log("EXT[%p]: Not sending extension (%s/%d) for '%s'\n", session,
|
|
Packit Service |
4684c1 |
p->name, (int)p->tls_id,
|
|
Packit Service |
4684c1 |
ext_msg_validity_to_str(ctx->msg));
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
_gnutls_gen_hello_extensions(gnutls_session_t session,
|
|
Packit Service |
4684c1 |
gnutls_buffer_st * buf,
|
|
Packit Service |
4684c1 |
gnutls_ext_flags_t msg,
|
|
Packit Service |
4684c1 |
gnutls_ext_parse_type_t parse_point)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int pos, ret;
|
|
Packit Service |
4684c1 |
size_t i;
|
|
Packit Service |
4684c1 |
hello_ext_ctx_st ctx;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
msg &= GNUTLS_EXT_FLAG_SET_ONLY_FLAGS_MASK;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ctx.session = session;
|
|
Packit Service |
4684c1 |
ctx.msg = msg;
|
|
Packit Service |
4684c1 |
ctx.parse_point = parse_point;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_extv_append_init(buf);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
pos = ret;
|
|
Packit Service |
4684c1 |
_gnutls_ext_set_extensions_offset(session, pos);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
for (i=0; i < session->internals.rexts_size; i++) {
|
|
Packit Service |
4684c1 |
ctx.ext = &session->internals.rexts[i];
|
|
Packit Service |
4684c1 |
ret = _gnutls_extv_append(buf, session->internals.rexts[i].tls_id,
|
|
Packit Service |
4684c1 |
&ctx, hello_ext_send);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (ret > 0)
|
|
Packit Service |
4684c1 |
_gnutls_handshake_log
|
|
Packit Service |
4684c1 |
("EXT[%p]: Sending extension %s/%d (%d bytes)\n",
|
|
Packit Service |
4684c1 |
session, ctx.ext->name, (int)ctx.ext->tls_id, ret-4);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* hello_ext_send() ensures we don't send duplicates, in case
|
|
Packit Service |
4684c1 |
* of overridden extensions */
|
|
Packit Service |
4684c1 |
for (i = 0; i < MAX_EXT_TYPES; i++) {
|
|
Packit Service |
4684c1 |
if (!extfunc[i])
|
|
Packit Service |
4684c1 |
continue;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ctx.ext = extfunc[i];
|
|
Packit Service |
4684c1 |
ret = _gnutls_extv_append(buf, extfunc[i]->tls_id,
|
|
Packit Service |
4684c1 |
&ctx, hello_ext_send);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (ret > 0)
|
|
Packit Service |
4684c1 |
_gnutls_handshake_log
|
|
Packit Service |
4684c1 |
("EXT[%p]: Sending extension %s/%d (%d bytes)\n",
|
|
Packit Service |
4684c1 |
session, ctx.ext->name, (int)ctx.ext->tls_id, ret-4);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = _gnutls_extv_append_final(buf, pos, !(msg & GNUTLS_EXT_FLAG_EE));
|
|
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 |
/* Global deinit and init of global extensions */
|
|
Packit Service |
4684c1 |
int _gnutls_hello_ext_init(void)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
return GNUTLS_E_SUCCESS;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
void _gnutls_hello_ext_deinit(void)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
unsigned i;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
for (i = 0; i < MAX_EXT_TYPES; i++) {
|
|
Packit Service |
4684c1 |
if (!extfunc[i])
|
|
Packit Service |
4684c1 |
continue;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (extfunc[i]->free_struct != 0) {
|
|
Packit Service |
4684c1 |
gnutls_free(((hello_ext_entry_st *)extfunc[i])->name);
|
|
Packit Service |
4684c1 |
gnutls_free(extfunc[i]);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Packing of extension data (for use in resumption) */
|
|
Packit Service |
4684c1 |
static int pack_extension(gnutls_session_t session, const hello_ext_entry_st *extp,
|
|
Packit Service |
4684c1 |
gnutls_buffer_st *packed)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
int size_offset;
|
|
Packit Service |
4684c1 |
int cur_size;
|
|
Packit Service |
4684c1 |
gnutls_ext_priv_data_t data;
|
|
Packit Service |
4684c1 |
int rval = 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret =
|
|
Packit Service |
4684c1 |
_gnutls_hello_ext_get_priv(session, extp->gid,
|
|
Packit Service |
4684c1 |
&data);
|
|
Packit Service |
4684c1 |
if (ret >= 0 && extp->pack_func != NULL) {
|
|
Packit Service |
4684c1 |
BUFFER_APPEND_NUM(packed, extp->gid);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
size_offset = packed->length;
|
|
Packit Service |
4684c1 |
BUFFER_APPEND_NUM(packed, 0);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cur_size = packed->length;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = extp->pack_func(data, packed);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
rval = 1;
|
|
Packit Service |
4684c1 |
/* write the actual size */
|
|
Packit Service |
4684c1 |
_gnutls_write_uint32(packed->length - cur_size,
|
|
Packit Service |
4684c1 |
packed->data + size_offset);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return rval;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
int _gnutls_hello_ext_pack(gnutls_session_t session, gnutls_buffer_st *packed)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
unsigned int i;
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
int total_exts_pos;
|
|
Packit Service |
4684c1 |
int n_exts = 0;
|
|
Packit Service |
4684c1 |
const struct hello_ext_entry_st *ext;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
total_exts_pos = packed->length;
|
|
Packit Service |
4684c1 |
BUFFER_APPEND_NUM(packed, 0);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
for (i = 0; i <= GNUTLS_EXTENSION_MAX_VALUE; i++) {
|
|
Packit Service |
4684c1 |
if (session->internals.used_exts & ((ext_track_t)1 << i)) {
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ext = gid_to_ext_entry(session, i);
|
|
Packit Service |
4684c1 |
if (ext == NULL)
|
|
Packit Service |
4684c1 |
continue;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = pack_extension(session, ext, packed);
|
|
Packit Service |
4684c1 |
if (ret < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (ret > 0)
|
|
Packit Service |
4684c1 |
n_exts++;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_write_uint32(n_exts, packed->data + total_exts_pos);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
int _gnutls_ext_set_full_client_hello(gnutls_session_t session,
|
|
Packit Service |
4684c1 |
handshake_buffer_st *recv_buf)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int ret;
|
|
Packit Service |
4684c1 |
gnutls_buffer_st *buf = &session->internals.full_client_hello;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_buffer_clear(buf);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if ((ret = _gnutls_buffer_append_prefix(buf, 8, recv_buf->htype)) < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
if ((ret = _gnutls_buffer_append_prefix(buf, 24, recv_buf->data.length)) < 0)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(ret);
|
|
Packit Service |
4684c1 |
if ((ret = _gnutls_buffer_append_data(buf, recv_buf->data.data, recv_buf->data.length)) < 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 |
unsigned _gnutls_ext_get_full_client_hello(gnutls_session_t session,
|
|
Packit Service |
4684c1 |
gnutls_datum_t *d)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
gnutls_buffer_st *buf = &session->internals.full_client_hello;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (!buf->length)
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
d->data = buf->data;
|
|
Packit Service |
4684c1 |
d->size = buf->length;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static void
|
|
Packit Service |
4684c1 |
_gnutls_ext_set_resumed_session_data(gnutls_session_t session,
|
|
Packit Service |
4684c1 |
extensions_t id,
|
|
Packit Service |
4684c1 |
gnutls_ext_priv_data_t data)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
const struct hello_ext_entry_st *ext;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* If this happens we need to increase the max */
|
|
Packit Service |
4684c1 |
assert(id < MAX_EXT_TYPES);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ext = gid_to_ext_entry(session, id);
|
|
Packit Service |
4684c1 |
assert(ext != NULL);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (session->internals.ext_data[id].resumed_set != 0)
|
|
Packit Service |
4684c1 |
unset_resumed_ext_data(session, ext, id);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
session->internals.ext_data[id].resumed_priv = data;
|
|
Packit Service |
4684c1 |
session->internals.ext_data[id].resumed_set = 1;
|
|
Packit Service |
4684c1 |
return;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
int _gnutls_hello_ext_unpack(gnutls_session_t session, gnutls_buffer_st * packed)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int i, ret;
|
|
Packit Service |
4684c1 |
gnutls_ext_priv_data_t data;
|
|
Packit Service |
4684c1 |
int max_exts = 0;
|
|
Packit Service |
4684c1 |
extensions_t id;
|
|
Packit Service |
4684c1 |
int size_for_id, cur_pos;
|
|
Packit Service |
4684c1 |
const struct hello_ext_entry_st *ext;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
BUFFER_POP_NUM(packed, max_exts);
|
|
Packit Service |
4684c1 |
for (i = 0; i < max_exts; i++) {
|
|
Packit Service |
4684c1 |
BUFFER_POP_NUM(packed, id);
|
|
Packit Service |
4684c1 |
BUFFER_POP_NUM(packed, size_for_id);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
cur_pos = packed->length;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ext = gid_to_ext_entry(session, id);
|
|
Packit Service |
4684c1 |
if (ext == NULL || ext->unpack_func == NULL) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return GNUTLS_E_PARSING_ERROR;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ret = ext->unpack_func(packed, &data);
|
|
Packit Service |
4684c1 |
if (ret < 0) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* verify that unpack read the correct bytes */
|
|
Packit Service |
4684c1 |
cur_pos = cur_pos - packed->length;
|
|
Packit Service |
4684c1 |
if (cur_pos /* read length */ != size_for_id) {
|
|
Packit Service |
4684c1 |
gnutls_assert();
|
|
Packit Service |
4684c1 |
return GNUTLS_E_PARSING_ERROR;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_ext_set_resumed_session_data(session, id, data);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
error:
|
|
Packit Service |
4684c1 |
return ret;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static void
|
|
Packit Service |
4684c1 |
unset_ext_data(gnutls_session_t session, const struct hello_ext_entry_st *ext, unsigned idx)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
if (session->internals.ext_data[idx].set == 0)
|
|
Packit Service |
4684c1 |
return;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (ext && ext->deinit_func && session->internals.ext_data[idx].priv != NULL)
|
|
Packit Service |
4684c1 |
ext->deinit_func(session->internals.ext_data[idx].priv);
|
|
Packit Service |
4684c1 |
session->internals.ext_data[idx].set = 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
void
|
|
Packit Service |
4684c1 |
_gnutls_hello_ext_unset_priv(gnutls_session_t session,
|
|
Packit Service |
4684c1 |
extensions_t id)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
const struct hello_ext_entry_st *ext;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ext = gid_to_ext_entry(session, id);
|
|
Packit Service |
4684c1 |
if (ext)
|
|
Packit Service |
4684c1 |
unset_ext_data(session, ext, id);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static void unset_resumed_ext_data(gnutls_session_t session, const struct hello_ext_entry_st *ext, unsigned idx)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
if (session->internals.ext_data[idx].resumed_set == 0)
|
|
Packit Service |
4684c1 |
return;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (ext && ext->deinit_func && session->internals.ext_data[idx].resumed_priv) {
|
|
Packit Service |
4684c1 |
ext->deinit_func(session->internals.ext_data[idx].resumed_priv);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
session->internals.ext_data[idx].resumed_set = 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Deinitializes all data that are associated with TLS extensions.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
void _gnutls_hello_ext_priv_deinit(gnutls_session_t session)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
unsigned int i;
|
|
Packit Service |
4684c1 |
const struct hello_ext_entry_st *ext;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
for (i = 0; i < MAX_EXT_TYPES; i++) {
|
|
Packit Service |
4684c1 |
if (!session->internals.ext_data[i].set && !session->internals.ext_data[i].resumed_set)
|
|
Packit Service |
4684c1 |
continue;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ext = gid_to_ext_entry(session, i);
|
|
Packit Service |
4684c1 |
if (ext) {
|
|
Packit Service |
4684c1 |
unset_ext_data(session, ext, i);
|
|
Packit Service |
4684c1 |
unset_resumed_ext_data(session, ext, i);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* This function allows an extension to store data in the current session
|
|
Packit Service |
4684c1 |
* and retrieve them later on. We use functions instead of a pointer to a
|
|
Packit Service |
4684c1 |
* private pointer, to allow API additions by individual extensions.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
void
|
|
Packit Service |
4684c1 |
_gnutls_hello_ext_set_priv(gnutls_session_t session, extensions_t id,
|
|
Packit Service |
4684c1 |
gnutls_ext_priv_data_t data)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
const struct hello_ext_entry_st *ext;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
assert(id < MAX_EXT_TYPES);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ext = gid_to_ext_entry(session, id);
|
|
Packit Service |
4684c1 |
assert(ext != NULL);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (session->internals.ext_data[id].set != 0) {
|
|
Packit Service |
4684c1 |
unset_ext_data(session, ext, id);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
session->internals.ext_data[id].priv = data;
|
|
Packit Service |
4684c1 |
session->internals.ext_data[id].set = 1;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
_gnutls_hello_ext_get_priv(gnutls_session_t session,
|
|
Packit Service |
4684c1 |
extensions_t id, gnutls_ext_priv_data_t * data)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
if (session->internals.ext_data[id].set != 0) {
|
|
Packit Service |
4684c1 |
*data =
|
|
Packit Service |
4684c1 |
session->internals.ext_data[id].priv;
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
_gnutls_hello_ext_get_resumed_priv(gnutls_session_t session,
|
|
Packit Service |
4684c1 |
extensions_t id,
|
|
Packit Service |
4684c1 |
gnutls_ext_priv_data_t * data)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
if (session->internals.ext_data[id].resumed_set != 0) {
|
|
Packit Service |
4684c1 |
*data =
|
|
Packit Service |
4684c1 |
session->internals.ext_data[id].resumed_priv;
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return GNUTLS_E_INVALID_REQUEST;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_ext_register:
|
|
Packit Service |
4684c1 |
* @name: the name of the extension to register
|
|
Packit Service |
4684c1 |
* @id: the numeric TLS id of the extension
|
|
Packit Service |
4684c1 |
* @parse_point: the parse type of the extension (see gnutls_ext_parse_type_t)
|
|
Packit Service |
4684c1 |
* @recv_func: a function to receive the data
|
|
Packit Service |
4684c1 |
* @send_func: a function to send the data
|
|
Packit Service |
4684c1 |
* @deinit_func: a function deinitialize any private data
|
|
Packit Service |
4684c1 |
* @pack_func: a function which serializes the extension's private data (used on session packing for resumption)
|
|
Packit Service |
4684c1 |
* @unpack_func: a function which will deserialize the extension's private data
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will register a new extension type. The extension will remain
|
|
Packit Service |
4684c1 |
* registered until gnutls_global_deinit() is called. If the extension type
|
|
Packit Service |
4684c1 |
* is already registered then %GNUTLS_E_ALREADY_REGISTERED will be returned.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Each registered extension can store temporary data into the gnutls_session_t
|
|
Packit Service |
4684c1 |
* structure using gnutls_ext_set_data(), and they can be retrieved using
|
|
Packit Service |
4684c1 |
* gnutls_ext_get_data().
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Any extensions registered with this function are valid for the client
|
|
Packit Service |
4684c1 |
* and TLS1.2 server hello (or encrypted extensions for TLS1.3).
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function is not thread safe.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Since: 3.4.0
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
gnutls_ext_register(const char *name, int id, gnutls_ext_parse_type_t parse_point,
|
|
Packit Service |
4684c1 |
gnutls_ext_recv_func recv_func, gnutls_ext_send_func send_func,
|
|
Packit Service |
4684c1 |
gnutls_ext_deinit_data_func deinit_func, gnutls_ext_pack_func pack_func,
|
|
Packit Service |
4684c1 |
gnutls_ext_unpack_func unpack_func)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
hello_ext_entry_st *tmp_mod;
|
|
Packit Service |
4684c1 |
unsigned i;
|
|
Packit Service |
4684c1 |
unsigned gid = GNUTLS_EXTENSION_MAX+1;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
for (i = 0; i < MAX_EXT_TYPES; i++) {
|
|
Packit Service |
4684c1 |
if (!extfunc[i])
|
|
Packit Service |
4684c1 |
continue;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (extfunc[i]->tls_id == id)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_ALREADY_REGISTERED);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (extfunc[i]->gid >= gid)
|
|
Packit Service |
4684c1 |
gid = extfunc[i]->gid + 1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (gid > GNUTLS_EXTENSION_MAX_VALUE || gid >= sizeof(extfunc)/sizeof(extfunc[0]))
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
tmp_mod = gnutls_calloc(1, sizeof(*tmp_mod));
|
|
Packit Service |
4684c1 |
if (tmp_mod == NULL)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
tmp_mod->name = gnutls_strdup(name);
|
|
Packit Service |
4684c1 |
tmp_mod->free_struct = 1;
|
|
Packit Service |
4684c1 |
tmp_mod->tls_id = id;
|
|
Packit Service |
4684c1 |
tmp_mod->gid = gid;
|
|
Packit Service |
4684c1 |
tmp_mod->client_parse_point = parse_point;
|
|
Packit Service |
4684c1 |
tmp_mod->server_parse_point = parse_point;
|
|
Packit Service |
4684c1 |
tmp_mod->recv_func = recv_func;
|
|
Packit Service |
4684c1 |
tmp_mod->send_func = send_func;
|
|
Packit Service |
4684c1 |
tmp_mod->deinit_func = deinit_func;
|
|
Packit Service |
4684c1 |
tmp_mod->pack_func = pack_func;
|
|
Packit Service |
4684c1 |
tmp_mod->unpack_func = unpack_func;
|
|
Packit Service |
4684c1 |
tmp_mod->validity = GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO |
|
|
Packit Service |
4684c1 |
GNUTLS_EXT_FLAG_EE | GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_TLS;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
assert(extfunc[gid] == NULL);
|
|
Packit Service |
4684c1 |
extfunc[gid] = tmp_mod;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#define VALIDITY_MASK (GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO | \
|
|
Packit Service |
4684c1 |
GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO | \
|
|
Packit Service |
4684c1 |
GNUTLS_EXT_FLAG_EE | GNUTLS_EXT_FLAG_HRR)
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_session_ext_register:
|
|
Packit Service |
4684c1 |
* @session: the session for which this extension will be set
|
|
Packit Service |
4684c1 |
* @name: the name of the extension to register
|
|
Packit Service |
4684c1 |
* @id: the numeric id of the extension
|
|
Packit Service |
4684c1 |
* @parse_point: the parse type of the extension (see gnutls_ext_parse_type_t)
|
|
Packit Service |
4684c1 |
* @recv_func: a function to receive the data
|
|
Packit Service |
4684c1 |
* @send_func: a function to send the data
|
|
Packit Service |
4684c1 |
* @deinit_func: a function deinitialize any private data
|
|
Packit Service |
4684c1 |
* @pack_func: a function which serializes the extension's private data (used on session packing for resumption)
|
|
Packit Service |
4684c1 |
* @unpack_func: a function which will deserialize the extension's private data
|
|
Packit Service |
4684c1 |
* @flags: must be zero or flags from %gnutls_ext_flags_t
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function will register a new extension type. The extension will be
|
|
Packit Service |
4684c1 |
* only usable within the registered session. If the extension type
|
|
Packit Service |
4684c1 |
* is already registered then %GNUTLS_E_ALREADY_REGISTERED will be returned,
|
|
Packit Service |
4684c1 |
* unless the flag %GNUTLS_EXT_FLAG_OVERRIDE_INTERNAL is specified. The latter
|
|
Packit Service |
4684c1 |
* flag when specified can be used to override certain extensions introduced
|
|
Packit Service |
4684c1 |
* after 3.6.0. It is expected to be used by applications which handle
|
|
Packit Service |
4684c1 |
* custom extensions that are not currently supported in GnuTLS, but direct
|
|
Packit Service |
4684c1 |
* support for them may be added in the future.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Each registered extension can store temporary data into the gnutls_session_t
|
|
Packit Service |
4684c1 |
* structure using gnutls_ext_set_data(), and they can be retrieved using
|
|
Packit Service |
4684c1 |
* gnutls_ext_get_data().
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* The validity of the extension registered can be given by the appropriate flags
|
|
Packit Service |
4684c1 |
* of %gnutls_ext_flags_t. If no validity is given, then the registered extension
|
|
Packit Service |
4684c1 |
* will be valid for client and TLS1.2 server hello (or encrypted extensions for TLS1.3).
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Since: 3.5.5
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
gnutls_session_ext_register(gnutls_session_t session,
|
|
Packit Service |
4684c1 |
const char *name, int id, gnutls_ext_parse_type_t parse_point,
|
|
Packit Service |
4684c1 |
gnutls_ext_recv_func recv_func, gnutls_ext_send_func send_func,
|
|
Packit Service |
4684c1 |
gnutls_ext_deinit_data_func deinit_func, gnutls_ext_pack_func pack_func,
|
|
Packit Service |
4684c1 |
gnutls_ext_unpack_func unpack_func, unsigned flags)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
hello_ext_entry_st tmp_mod;
|
|
Packit Service |
4684c1 |
hello_ext_entry_st *exts;
|
|
Packit Service |
4684c1 |
unsigned i;
|
|
Packit Service |
4684c1 |
unsigned gid = GNUTLS_EXTENSION_MAX+1;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* reject handling any extensions which modify the TLS handshake
|
|
Packit Service |
4684c1 |
* in any way, or are mapped to an exported API. */
|
|
Packit Service |
4684c1 |
for (i = 0; i < GNUTLS_EXTENSION_MAX; i++) {
|
|
Packit Service |
4684c1 |
if (!extfunc[i])
|
|
Packit Service |
4684c1 |
continue;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (extfunc[i]->tls_id == id) {
|
|
Packit Service |
4684c1 |
if (!(flags & GNUTLS_EXT_FLAG_OVERRIDE_INTERNAL)) {
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_ALREADY_REGISTERED);
|
|
Packit Service |
4684c1 |
} else if (extfunc[i]->cannot_be_overriden) {
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_ALREADY_REGISTERED);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (extfunc[i]->gid >= gid)
|
|
Packit Service |
4684c1 |
gid = extfunc[i]->gid + 1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
for (i=0;i<session->internals.rexts_size;i++) {
|
|
Packit Service |
4684c1 |
if (session->internals.rexts[i].tls_id == id) {
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_ALREADY_REGISTERED);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (session->internals.rexts[i].gid >= gid)
|
|
Packit Service |
4684c1 |
gid = session->internals.rexts[i].gid + 1;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (gid > GNUTLS_EXTENSION_MAX_VALUE)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
memset(&tmp_mod, 0, sizeof(hello_ext_entry_st));
|
|
Packit Service |
4684c1 |
tmp_mod.name = gnutls_strdup(name);
|
|
Packit Service |
4684c1 |
tmp_mod.free_struct = 1;
|
|
Packit Service |
4684c1 |
tmp_mod.tls_id = id;
|
|
Packit Service |
4684c1 |
tmp_mod.gid = gid;
|
|
Packit Service |
4684c1 |
tmp_mod.client_parse_point = parse_point;
|
|
Packit Service |
4684c1 |
tmp_mod.server_parse_point = parse_point;
|
|
Packit Service |
4684c1 |
tmp_mod.recv_func = recv_func;
|
|
Packit Service |
4684c1 |
tmp_mod.send_func = send_func;
|
|
Packit Service |
4684c1 |
tmp_mod.deinit_func = deinit_func;
|
|
Packit Service |
4684c1 |
tmp_mod.pack_func = pack_func;
|
|
Packit Service |
4684c1 |
tmp_mod.unpack_func = unpack_func;
|
|
Packit Service |
4684c1 |
tmp_mod.validity = flags;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if ((tmp_mod.validity & VALIDITY_MASK) == 0) {
|
|
Packit Service |
4684c1 |
tmp_mod.validity = GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO |
|
|
Packit Service |
4684c1 |
GNUTLS_EXT_FLAG_EE;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if ((tmp_mod.validity & (GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_TLS)) == 0) {
|
|
Packit Service |
4684c1 |
if (IS_DTLS(session))
|
|
Packit Service |
4684c1 |
tmp_mod.validity |= GNUTLS_EXT_FLAG_DTLS;
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
tmp_mod.validity |= GNUTLS_EXT_FLAG_TLS;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
exts = gnutls_realloc(session->internals.rexts, (session->internals.rexts_size+1)*sizeof(*exts));
|
|
Packit Service |
4684c1 |
if (exts == NULL) {
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
session->internals.rexts = exts;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
memcpy(&session->internals.rexts[session->internals.rexts_size], &tmp_mod, sizeof(hello_ext_entry_st));
|
|
Packit Service |
4684c1 |
session->internals.rexts_size++;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_ext_set_data:
|
|
Packit Service |
4684c1 |
* @session: a #gnutls_session_t opaque pointer
|
|
Packit Service |
4684c1 |
* @tls_id: the numeric id of the extension
|
|
Packit Service |
4684c1 |
* @data: the private data to set
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function allows an extension handler to store data in the current session
|
|
Packit Service |
4684c1 |
* and retrieve them later on. The set data will be deallocated using
|
|
Packit Service |
4684c1 |
* the gnutls_ext_deinit_data_func.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Since: 3.4.0
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
void
|
|
Packit Service |
4684c1 |
gnutls_ext_set_data(gnutls_session_t session, unsigned tls_id,
|
|
Packit Service |
4684c1 |
gnutls_ext_priv_data_t data)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
unsigned id = tls_id_to_gid(session, tls_id);
|
|
Packit Service |
4684c1 |
if (id == GNUTLS_EXTENSION_INVALID)
|
|
Packit Service |
4684c1 |
return;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
_gnutls_hello_ext_set_priv(session, id, data);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_ext_get_data:
|
|
Packit Service |
4684c1 |
* @session: a #gnutls_session_t opaque pointer
|
|
Packit Service |
4684c1 |
* @tls_id: the numeric id of the extension
|
|
Packit Service |
4684c1 |
* @data: a pointer to the private data to retrieve
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function retrieves any data previously stored with gnutls_ext_set_data().
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Since: 3.4.0
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
gnutls_ext_get_data(gnutls_session_t session,
|
|
Packit Service |
4684c1 |
unsigned tls_id, gnutls_ext_priv_data_t *data)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
unsigned id = tls_id_to_gid(session, tls_id);
|
|
Packit Service |
4684c1 |
if (id == GNUTLS_EXTENSION_INVALID)
|
|
Packit Service |
4684c1 |
return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return _gnutls_hello_ext_get_priv(session, id, data);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_ext_get_current_msg:
|
|
Packit Service |
4684c1 |
* @session: a #gnutls_session_t opaque pointer
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* This function allows an extension handler to obtain the message
|
|
Packit Service |
4684c1 |
* this extension is being called from. The returned value is a single
|
|
Packit Service |
4684c1 |
* entry of the %gnutls_ext_flags_t enumeration. That is, if an
|
|
Packit Service |
4684c1 |
* extension was registered with the %GNUTLS_EXT_FLAG_HRR and
|
|
Packit Service |
4684c1 |
* %GNUTLS_EXT_FLAG_EE flags, the value when called during parsing of the
|
|
Packit Service |
4684c1 |
* encrypted extensions message will be %GNUTLS_EXT_FLAG_EE.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* If not called under an extension handler, its value is undefined.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Since: 3.6.3
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
unsigned gnutls_ext_get_current_msg(gnutls_session_t session)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
return _gnutls_ext_get_msg(session);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/**
|
|
Packit Service |
4684c1 |
* gnutls_ext_get_name2:
|
|
Packit Service |
4684c1 |
* @session: a #gnutls_session_t opaque pointer
|
|
Packit Service |
4684c1 |
* @tls_id: is a TLS extension numeric ID
|
|
Packit Service |
4684c1 |
* @parse_point: the parse type of the extension
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Convert a TLS extension numeric ID to a printable string.
|
|
Packit Service |
4684c1 |
*
|
|
Packit Service |
4684c1 |
* Returns: a pointer to a string that contains the name of the
|
|
Packit Service |
4684c1 |
* specified cipher, or %NULL.
|
|
Packit Service |
4684c1 |
**/
|
|
Packit Service |
4684c1 |
const char *gnutls_ext_get_name2(gnutls_session_t session, unsigned int tls_id,
|
|
Packit Service |
4684c1 |
gnutls_ext_parse_type_t parse_point)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
const struct hello_ext_entry_st *ext;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ext = tls_id_to_ext_entry(session, tls_id, parse_point);
|
|
Packit Service |
4684c1 |
if (ext)
|
|
Packit Service |
4684c1 |
return ext->name;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return NULL;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|