|
Packit |
549fdc |
/*
|
|
Packit |
549fdc |
* Copyright (C) 2002-2012 Free Software Foundation, Inc.
|
|
Packit |
549fdc |
* Copyright (C) 2017 Red Hat, Inc.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Author: Nikos Mavrogiannopoulos
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This file is part of GnuTLS.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* The GnuTLS is free software; you can redistribute it and/or
|
|
Packit |
549fdc |
* modify it under the terms of the GNU Lesser General Public License
|
|
Packit |
549fdc |
* as published by the Free Software Foundation; either version 2.1 of
|
|
Packit |
549fdc |
* the License, or (at your option) any later version.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This library is distributed in the hope that it will be useful, but
|
|
Packit |
549fdc |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
549fdc |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
549fdc |
* Lesser General Public License for more details.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* You should have received a copy of the GNU Lesser General Public License
|
|
Packit |
549fdc |
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
#include "gnutls_int.h"
|
|
Packit |
549fdc |
#include "auth.h"
|
|
Packit |
549fdc |
#include "errors.h"
|
|
Packit |
549fdc |
#include "num.h"
|
|
Packit |
549fdc |
#include "str.h"
|
|
Packit |
549fdc |
#include <ext/server_name.h>
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
static int _gnutls_server_name_recv_params(gnutls_session_t session,
|
|
Packit |
549fdc |
const uint8_t * data,
|
|
Packit |
549fdc |
size_t data_size);
|
|
Packit |
549fdc |
static int _gnutls_server_name_send_params(gnutls_session_t session,
|
|
Packit |
549fdc |
gnutls_buffer_st * extdata);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
static int _gnutls_server_name_unpack(gnutls_buffer_st * ps,
|
|
Packit |
549fdc |
gnutls_ext_priv_data_t * _priv);
|
|
Packit |
549fdc |
static int _gnutls_server_name_pack(gnutls_ext_priv_data_t _priv,
|
|
Packit |
549fdc |
gnutls_buffer_st * ps);
|
|
Packit |
549fdc |
static void _gnutls_server_name_deinit_data(gnutls_ext_priv_data_t priv);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
_gnutls_server_name_set_raw(gnutls_session_t session,
|
|
Packit |
549fdc |
gnutls_server_name_type_t type,
|
|
Packit |
549fdc |
const void *name, size_t name_length);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
const extension_entry_st ext_mod_server_name = {
|
|
Packit |
549fdc |
.name = "Server Name Indication",
|
|
Packit |
549fdc |
.type = GNUTLS_EXTENSION_SERVER_NAME,
|
|
Packit |
549fdc |
.parse_type = GNUTLS_EXT_MANDATORY,
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
.recv_func = _gnutls_server_name_recv_params,
|
|
Packit |
549fdc |
.send_func = _gnutls_server_name_send_params,
|
|
Packit |
549fdc |
.pack_func = _gnutls_server_name_pack,
|
|
Packit |
549fdc |
.unpack_func = _gnutls_server_name_unpack,
|
|
Packit |
549fdc |
.deinit_func = _gnutls_server_name_deinit_data,
|
|
Packit |
549fdc |
.cannot_be_overriden = 1
|
|
Packit |
549fdc |
};
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/*
|
|
Packit |
549fdc |
* In case of a server: if a NAME_DNS extension type is received then
|
|
Packit |
549fdc |
* it stores into the session the value of NAME_DNS. The server may
|
|
Packit |
549fdc |
* use gnutls_ext_get_server_name(), in order to access it.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* In case of a client: If a proper NAME_DNS extension type is found
|
|
Packit |
549fdc |
* in the session then it sends the extension to the peer.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
static int
|
|
Packit |
549fdc |
_gnutls_server_name_recv_params(gnutls_session_t session,
|
|
Packit |
549fdc |
const uint8_t * data, size_t _data_size)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
const unsigned char *p;
|
|
Packit |
549fdc |
uint16_t len, type;
|
|
Packit |
549fdc |
ssize_t data_size = _data_size;
|
|
Packit |
549fdc |
server_name_ext_st *priv = NULL;
|
|
Packit |
549fdc |
gnutls_ext_priv_data_t epriv;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (session->security_parameters.entity == GNUTLS_SERVER) {
|
|
Packit |
549fdc |
DECR_LENGTH_RET(data_size, 2, GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
|
|
Packit |
549fdc |
len = _gnutls_read_uint16(data);
|
|
Packit |
549fdc |
if (len == 0)
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (len != data_size) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
p = data + 2;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
while (data_size > 0) {
|
|
Packit |
549fdc |
DECR_LEN(data_size, 1);
|
|
Packit |
549fdc |
type = *p;
|
|
Packit |
549fdc |
p++;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
DECR_LEN(data_size, 2);
|
|
Packit |
549fdc |
len = _gnutls_read_uint16(p);
|
|
Packit |
549fdc |
p += 2;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (len == 0) {
|
|
Packit |
549fdc |
_gnutls_handshake_log
|
|
Packit |
549fdc |
("HSK[%p]: Received server name size of zero\n",
|
|
Packit |
549fdc |
session);
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
DECR_LEN(data_size, len);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (type == 0) { /* NAME_DNS */
|
|
Packit |
549fdc |
if (!_gnutls_dnsname_is_valid((char*)p, len))
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (len < MAX_SERVER_NAME_SIZE) {
|
|
Packit |
549fdc |
priv = gnutls_calloc(1, sizeof(*priv));
|
|
Packit |
549fdc |
if (priv == NULL) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_MEMORY_ERROR;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
memcpy(priv->name, p, len);
|
|
Packit |
549fdc |
priv->name[len] = 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
priv->name_length = len;
|
|
Packit |
549fdc |
priv->type =
|
|
Packit |
549fdc |
GNUTLS_NAME_DNS;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
epriv = priv;
|
|
Packit |
549fdc |
_gnutls_ext_set_session_data(session,
|
|
Packit |
549fdc |
GNUTLS_EXTENSION_SERVER_NAME,
|
|
Packit |
549fdc |
epriv);
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
p += len;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* returns data_size or a negative number on failure
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
static int
|
|
Packit |
549fdc |
_gnutls_server_name_send_params(gnutls_session_t session,
|
|
Packit |
549fdc |
gnutls_buffer_st * extdata)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int total_size = 0, ret;
|
|
Packit |
549fdc |
server_name_ext_st *priv;
|
|
Packit |
549fdc |
gnutls_ext_priv_data_t epriv;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
_gnutls_ext_get_session_data(session,
|
|
Packit |
549fdc |
GNUTLS_EXTENSION_SERVER_NAME,
|
|
Packit |
549fdc |
&epriv);
|
|
Packit |
549fdc |
if (ret < 0)
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* this function sends the client extension data (dnsname)
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
if (session->security_parameters.entity == GNUTLS_CLIENT) {
|
|
Packit |
549fdc |
priv = epriv;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (priv->name_length == 0 || priv->type != GNUTLS_NAME_DNS)
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* uint8_t + uint16_t + size
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
total_size = 2 + 1 + 2 + priv->name_length;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* UINT16: write total size of all names
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
_gnutls_buffer_append_prefix(extdata, 16,
|
|
Packit |
549fdc |
total_size - 2);
|
|
Packit |
549fdc |
if (ret < 0)
|
|
Packit |
549fdc |
return gnutls_assert_val(ret);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* UINT8: type of this extension
|
|
Packit |
549fdc |
* UINT16: size of the first name
|
|
Packit |
549fdc |
* LEN: the actual server name.
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
_gnutls_buffer_append_prefix(extdata, 8, 0);
|
|
Packit |
549fdc |
if (ret < 0)
|
|
Packit |
549fdc |
return gnutls_assert_val(ret);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_gnutls_debug_log("HSK[%p]: sent server name: '%s'\n", session, priv->name);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
_gnutls_buffer_append_data_prefix
|
|
Packit |
549fdc |
(extdata, 16,
|
|
Packit |
549fdc |
priv->name, priv->name_length);
|
|
Packit |
549fdc |
if (ret < 0)
|
|
Packit |
549fdc |
return gnutls_assert_val(ret);
|
|
Packit |
549fdc |
} else {
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return total_size;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_server_name_get:
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type.
|
|
Packit |
549fdc |
* @data: will hold the data
|
|
Packit |
549fdc |
* @data_length: will hold the data length. Must hold the maximum size of data.
|
|
Packit |
549fdc |
* @type: will hold the server name indicator type
|
|
Packit |
549fdc |
* @indx: is the index of the server_name
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function will allow you to get the name indication (if any), a
|
|
Packit |
549fdc |
* client has sent. The name indication may be any of the enumeration
|
|
Packit |
549fdc |
* gnutls_server_name_type_t.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* If @type is GNUTLS_NAME_DNS, then this function is to be used by
|
|
Packit |
549fdc |
* servers that support virtual hosting, and the data will be a null
|
|
Packit |
549fdc |
* terminated IDNA ACE string (prior to GnuTLS 3.4.0 it was a UTF-8 string).
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* If @data has not enough size to hold the server name
|
|
Packit |
549fdc |
* GNUTLS_E_SHORT_MEMORY_BUFFER is returned, and @data_length will
|
|
Packit |
549fdc |
* hold the required size.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* @indx is used to retrieve more than one server names (if sent by
|
|
Packit |
549fdc |
* the client). The first server name has an index of 0, the second 1
|
|
Packit |
549fdc |
* and so on. If no name with the given index exists
|
|
Packit |
549fdc |
* GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, on UTF-8
|
|
Packit |
549fdc |
* decoding error %GNUTLS_E_IDNA_ERROR is returned, otherwise a negative
|
|
Packit |
549fdc |
* error code is returned.
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
gnutls_server_name_get(gnutls_session_t session, void *data,
|
|
Packit |
549fdc |
size_t * data_length,
|
|
Packit |
549fdc |
unsigned int *type, unsigned int indx)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
char *_data = data;
|
|
Packit |
549fdc |
server_name_ext_st *priv;
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
gnutls_ext_priv_data_t epriv;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (session->security_parameters.entity == GNUTLS_CLIENT) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_INVALID_REQUEST;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (indx != 0)
|
|
Packit |
549fdc |
return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
_gnutls_ext_get_session_data(session,
|
|
Packit |
549fdc |
GNUTLS_EXTENSION_SERVER_NAME,
|
|
Packit |
549fdc |
&epriv);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
priv = epriv;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (priv->name_length == 0) {
|
|
Packit |
549fdc |
return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
*type = priv->type;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (*data_length > /* greater since we need one extra byte for the null */
|
|
Packit |
549fdc |
priv->name_length) {
|
|
Packit |
549fdc |
*data_length = priv->name_length;
|
|
Packit |
549fdc |
memcpy(data, priv->name, *data_length);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (*type == GNUTLS_NAME_DNS) /* null terminate */
|
|
Packit |
549fdc |
_data[(*data_length)] = 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
} else {
|
|
Packit |
549fdc |
*data_length = priv->name_length + 1;
|
|
Packit |
549fdc |
ret = GNUTLS_E_SHORT_MEMORY_BUFFER;
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = 0;
|
|
Packit |
549fdc |
cleanup:
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* This does not do any conversion not perform any check */
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
_gnutls_server_name_set_raw(gnutls_session_t session,
|
|
Packit |
549fdc |
gnutls_server_name_type_t type,
|
|
Packit |
549fdc |
const void *name, size_t name_length)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
server_name_ext_st *priv;
|
|
Packit |
549fdc |
gnutls_ext_priv_data_t epriv;
|
|
Packit |
549fdc |
int set = 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (name_length >= MAX_SERVER_NAME_SIZE) {
|
|
Packit |
549fdc |
return GNUTLS_E_INVALID_REQUEST;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
_gnutls_ext_get_session_data(session,
|
|
Packit |
549fdc |
GNUTLS_EXTENSION_SERVER_NAME,
|
|
Packit |
549fdc |
&epriv);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
set = 1;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (set != 0) {
|
|
Packit |
549fdc |
priv = gnutls_calloc(1, sizeof(*priv));
|
|
Packit |
549fdc |
if (priv == NULL) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_MEMORY_ERROR;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
epriv = priv;
|
|
Packit |
549fdc |
} else
|
|
Packit |
549fdc |
priv = epriv;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
priv->type = type;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (name_length > 0) {
|
|
Packit |
549fdc |
memcpy(priv->name, name, name_length);
|
|
Packit |
549fdc |
priv->name[name_length] = 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
priv->name_length = name_length;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (set != 0)
|
|
Packit |
549fdc |
_gnutls_ext_set_session_data(session,
|
|
Packit |
549fdc |
GNUTLS_EXTENSION_SERVER_NAME,
|
|
Packit |
549fdc |
epriv);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_server_name_set:
|
|
Packit |
549fdc |
* @session: is a #gnutls_session_t type.
|
|
Packit |
549fdc |
* @type: specifies the indicator type
|
|
Packit |
549fdc |
* @name: is a string that contains the server name.
|
|
Packit |
549fdc |
* @name_length: holds the length of name excluding the terminating null byte
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function is to be used by clients that want to inform (via a
|
|
Packit |
549fdc |
* TLS extension mechanism) the server of the name they connected to.
|
|
Packit |
549fdc |
* This should be used by clients that connect to servers that do
|
|
Packit |
549fdc |
* virtual hosting.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* The value of @name depends on the @type type. In case of
|
|
Packit |
549fdc |
* %GNUTLS_NAME_DNS, a UTF-8 null-terminated domain name string,
|
|
Packit |
549fdc |
* without the trailing dot, is expected.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* IPv4 or IPv6 addresses are not permitted to be set by this function.
|
|
Packit |
549fdc |
* If the function is called with a name of @name_length zero it will clear
|
|
Packit |
549fdc |
* all server names set.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
|
|
Packit |
549fdc |
* otherwise a negative error code is returned.
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
gnutls_server_name_set(gnutls_session_t session,
|
|
Packit |
549fdc |
gnutls_server_name_type_t type,
|
|
Packit |
549fdc |
const void *name, size_t name_length)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
gnutls_datum_t idn_name = {NULL,0};
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (session->security_parameters.entity == GNUTLS_SERVER) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_INVALID_REQUEST;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (name_length == 0) { /* unset extension */
|
|
Packit |
549fdc |
_gnutls_ext_unset_session_data(session, GNUTLS_EXTENSION_SERVER_NAME);
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = gnutls_idna_map(name, name_length, &idn_name, 0);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
_gnutls_debug_log("unable to convert name %s to IDNA2008 format\n", (char*)name);
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
name = idn_name.data;
|
|
Packit |
549fdc |
name_length = idn_name.size;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = _gnutls_server_name_set_raw(session, type, name, name_length);
|
|
Packit |
549fdc |
gnutls_free(idn_name.data);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
static void _gnutls_server_name_deinit_data(gnutls_ext_priv_data_t priv)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
gnutls_free(priv);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
static int
|
|
Packit |
549fdc |
_gnutls_server_name_pack(gnutls_ext_priv_data_t epriv,
|
|
Packit |
549fdc |
gnutls_buffer_st * ps)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
server_name_ext_st *priv = epriv;
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
BUFFER_APPEND_NUM(ps, priv->type);
|
|
Packit |
549fdc |
BUFFER_APPEND_PFX4(ps, priv->name,
|
|
Packit |
549fdc |
priv->name_length);
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
static int
|
|
Packit |
549fdc |
_gnutls_server_name_unpack(gnutls_buffer_st * ps,
|
|
Packit |
549fdc |
gnutls_ext_priv_data_t * _priv)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
server_name_ext_st *priv;
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
gnutls_ext_priv_data_t epriv;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
priv = gnutls_calloc(1, sizeof(*priv));
|
|
Packit |
549fdc |
if (priv == NULL) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_MEMORY_ERROR;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
BUFFER_POP_NUM(ps, priv->type);
|
|
Packit |
549fdc |
BUFFER_POP_NUM(ps, priv->name_length);
|
|
Packit |
549fdc |
if (priv->name_length >=
|
|
Packit |
549fdc |
sizeof(priv->name)) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_PARSING_ERROR;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
BUFFER_POP(ps, priv->name,
|
|
Packit |
549fdc |
priv->name_length);
|
|
Packit |
549fdc |
priv->name[priv->name_length] = 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
epriv = priv;
|
|
Packit |
549fdc |
*_priv = epriv;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
error:
|
|
Packit |
549fdc |
gnutls_free(priv);
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
unsigned _gnutls_server_name_matches_resumed(gnutls_session_t session)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
server_name_ext_st *priv1, *priv2;
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
gnutls_ext_priv_data_t epriv;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
_gnutls_ext_get_session_data(session,
|
|
Packit |
549fdc |
GNUTLS_EXTENSION_SERVER_NAME,
|
|
Packit |
549fdc |
&epriv);
|
|
Packit |
549fdc |
if (ret < 0) /* no server name in this session */
|
|
Packit |
549fdc |
priv1 = NULL;
|
|
Packit |
549fdc |
else
|
|
Packit |
549fdc |
priv1 = epriv;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
_gnutls_ext_get_resumed_session_data(session,
|
|
Packit |
549fdc |
GNUTLS_EXTENSION_SERVER_NAME,
|
|
Packit |
549fdc |
&epriv);
|
|
Packit |
549fdc |
if (ret < 0) /* no server name in extensions */
|
|
Packit |
549fdc |
priv2 = NULL;
|
|
Packit |
549fdc |
else
|
|
Packit |
549fdc |
priv2 = epriv;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (priv1 == NULL || priv2 == NULL) {
|
|
Packit |
549fdc |
if (priv1 == priv2)
|
|
Packit |
549fdc |
return 1;
|
|
Packit |
549fdc |
else
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (priv1->name_length != priv2->name_length)
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (memcmp(priv1->name, priv2->name, priv1->name_length) != 0)
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 1;
|
|
Packit |
549fdc |
}
|