2 * Copyright (C) 2002, 2003, 2004, 2005, 2008, 2009, 2010 Free Software
5 * Author: Nikos Mavrogiannopoulos
7 * This file is part of GnuTLS.
9 * The GnuTLS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
26 #include "gnutls_int.h"
27 #include "gnutls_auth.h"
28 #include "gnutls_errors.h"
29 #include "gnutls_num.h"
30 #include <ext_server_name.h>
32 static int _gnutls_server_name_recv_params (gnutls_session_t session,
35 static int _gnutls_server_name_send_params (gnutls_session_t session,
36 opaque * data, size_t);
38 static int _gnutls_server_name_unpack (gnutls_buffer_st * ps,
39 extension_priv_data_t * _priv);
40 static int _gnutls_server_name_pack (extension_priv_data_t _priv,
41 gnutls_buffer_st * ps);
42 static void _gnutls_server_name_deinit_data (extension_priv_data_t priv);
45 extension_entry_st ext_mod_server_name = {
46 .name = "SERVER NAME",
47 .type = GNUTLS_EXTENSION_SERVER_NAME,
48 .parse_type = GNUTLS_EXT_APPLICATION,
50 .recv_func = _gnutls_server_name_recv_params,
51 .send_func = _gnutls_server_name_send_params,
52 .pack_func = _gnutls_server_name_pack,
53 .unpack_func = _gnutls_server_name_unpack,
54 .deinit_func = _gnutls_server_name_deinit_data,
58 * In case of a server: if a NAME_DNS extension type is received then
59 * it stores into the session the value of NAME_DNS. The server may
60 * use gnutls_ext_get_server_name(), in order to access it.
62 * In case of a client: If a proper NAME_DNS extension type is found
63 * in the session then it sends the extension to the peer.
67 _gnutls_server_name_recv_params (gnutls_session_t session,
68 const opaque * data, size_t _data_size)
71 const unsigned char *p;
73 ssize_t data_size = _data_size;
75 server_name_ext_st *priv;
76 extension_priv_data_t epriv;
78 if (session->security_parameters.entity == GNUTLS_SERVER)
80 DECR_LENGTH_RET (data_size, 2, 0);
81 len = _gnutls_read_uint16 (data);
85 /* This is unexpected packet length, but
86 * just ignore it, for now.
94 /* Count all server_names in the packet. */
97 DECR_LENGTH_RET (data_size, 1, 0);
100 DECR_LEN (data_size, 2);
101 len = _gnutls_read_uint16 (p);
106 DECR_LENGTH_RET (data_size, len, 0);
111 _gnutls_handshake_log
112 ("HSK[%p]: Received zero size server name (under attack?)\n",
117 /* we cannot accept more server names.
119 if (server_names > MAX_SERVER_NAME_EXTENSIONS)
121 _gnutls_handshake_log
122 ("HSK[%p]: Too many server names received (under attack?)\n",
124 server_names = MAX_SERVER_NAME_EXTENSIONS;
127 if (server_names == 0)
128 return 0; /* no names found */
130 priv = gnutls_calloc (1, sizeof (*priv));
134 return GNUTLS_E_MEMORY_ERROR;
137 priv->server_names_size = server_names;
140 for (i = 0; i < server_names; i++)
145 len = _gnutls_read_uint16 (p);
150 case 0: /* NAME_DNS */
151 if (len <= MAX_SERVER_NAME_SIZE)
153 memcpy (priv->server_names[i].name, p, len);
154 priv->server_names[i].name_length = len;
155 priv->server_names[i].type = GNUTLS_NAME_DNS;
160 /* move to next record */
165 _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_SERVER_NAME,
173 /* returns data_size or a negative number on failure
176 _gnutls_server_name_send_params (gnutls_session_t session,
177 opaque * data, size_t _data_size)
182 ssize_t data_size = _data_size;
183 int total_size = 0, ret;
184 server_name_ext_st *priv;
185 extension_priv_data_t epriv;
188 _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SERVER_NAME,
194 /* this function sends the client extension data (dnsname)
196 if (session->security_parameters.entity == GNUTLS_CLIENT)
200 if (priv->server_names_size == 0)
206 for (i = 0; i < priv->server_names_size; i++)
208 /* count the total size
210 len = priv->server_names[i].name_length;
212 /* uint8_t + uint16_t + size
214 total_size += 1 + 2 + len;
219 /* UINT16: write total size of all names
221 DECR_LENGTH_RET (data_size, 2, GNUTLS_E_SHORT_MEMORY_BUFFER);
222 _gnutls_write_uint16 (total_size - 2, p);
224 for (i = 0; i < priv->server_names_size; i++)
227 switch (priv->server_names[i].type)
229 case GNUTLS_NAME_DNS:
230 len = priv->server_names[i].name_length;
234 /* UINT8: type of this extension
235 * UINT16: size of the first name
236 * LEN: the actual server name.
238 DECR_LENGTH_RET (data_size, len + 3,
239 GNUTLS_E_SHORT_MEMORY_BUFFER);
241 *p = 0; /* NAME_DNS type */
244 _gnutls_write_uint16 (len, p);
247 memcpy (p, priv->server_names[i].name, len);
252 return GNUTLS_E_INTERNAL_ERROR;
261 * gnutls_server_name_get:
262 * @session: is a #gnutls_session_t structure.
263 * @data: will hold the data
264 * @data_length: will hold the data length. Must hold the maximum size of data.
265 * @type: will hold the server name indicator type
266 * @indx: is the index of the server_name
268 * This function will allow you to get the name indication (if any), a
269 * client has sent. The name indication may be any of the enumeration
270 * gnutls_server_name_type_t.
272 * If @type is GNUTLS_NAME_DNS, then this function is to be used by
273 * servers that support virtual hosting, and the data will be a null
274 * terminated UTF-8 string.
276 * If @data has not enough size to hold the server name
277 * GNUTLS_E_SHORT_MEMORY_BUFFER is returned, and @data_length will
278 * hold the required size.
280 * @index is used to retrieve more than one server names (if sent by
281 * the client). The first server name has an index of 0, the second 1
282 * and so on. If no name with the given index exists
283 * GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned.
285 * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned,
286 * otherwise an error code is returned.
289 gnutls_server_name_get (gnutls_session_t session, void *data,
290 size_t * data_length,
291 unsigned int *type, unsigned int indx)
294 server_name_ext_st *priv;
296 extension_priv_data_t epriv;
298 if (session->security_parameters.entity == GNUTLS_CLIENT)
301 return GNUTLS_E_INVALID_REQUEST;
305 _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SERVER_NAME,
310 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
315 if (indx + 1 > priv->server_names_size)
317 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
320 *type = priv->server_names[indx].type;
322 if (*data_length > /* greater since we need one extra byte for the null */
323 priv->server_names[indx].name_length)
325 *data_length = priv->server_names[indx].name_length;
326 memcpy (data, priv->server_names[indx].name, *data_length);
328 if (*type == GNUTLS_NAME_DNS) /* null terminate */
329 _data[(*data_length)] = 0;
334 *data_length = priv->server_names[indx].name_length;
335 return GNUTLS_E_SHORT_MEMORY_BUFFER;
342 * gnutls_server_name_set:
343 * @session: is a #gnutls_session_t structure.
344 * @type: specifies the indicator type
345 * @name: is a string that contains the server name.
346 * @name_length: holds the length of name
348 * This function is to be used by clients that want to inform (via a
349 * TLS extension mechanism) the server of the name they connected to.
350 * This should be used by clients that connect to servers that do
353 * The value of @name depends on the @type type. In case of
354 * %GNUTLS_NAME_DNS, an ASCII zero-terminated domain name string,
355 * without the trailing dot, is expected. IPv4 or IPv6 addresses are
358 * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned,
359 * otherwise an error code is returned.
362 gnutls_server_name_set (gnutls_session_t session,
363 gnutls_server_name_type_t type,
364 const void *name, size_t name_length)
366 int server_names, ret;
367 server_name_ext_st *priv;
368 extension_priv_data_t epriv;
371 if (session->security_parameters.entity == GNUTLS_SERVER)
374 return GNUTLS_E_INVALID_REQUEST;
377 if (name_length > MAX_SERVER_NAME_SIZE)
378 return GNUTLS_E_SHORT_MEMORY_BUFFER;
381 _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SERVER_NAME,
390 priv = gnutls_calloc (1, sizeof (*priv));
394 return GNUTLS_E_MEMORY_ERROR;
401 server_names = priv->server_names_size + 1;
403 if (server_names > MAX_SERVER_NAME_EXTENSIONS)
404 server_names = MAX_SERVER_NAME_EXTENSIONS;
406 priv->server_names[server_names - 1].type = type;
407 memcpy (priv->server_names[server_names - 1].name, name, name_length);
408 priv->server_names[server_names - 1].name_length = name_length;
410 priv->server_names_size++;
413 _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_SERVER_NAME,
420 _gnutls_server_name_deinit_data (extension_priv_data_t priv)
422 gnutls_free (priv.ptr);
426 _gnutls_server_name_pack (extension_priv_data_t epriv, gnutls_buffer_st * ps)
428 server_name_ext_st *priv = epriv.ptr;
431 BUFFER_APPEND_NUM (ps, priv->server_names_size);
432 for (i = 0; i < priv->server_names_size; i++)
434 BUFFER_APPEND_NUM (ps, priv->server_names[i].type);
435 BUFFER_APPEND_PFX (ps, priv->server_names[i].name,
436 priv->server_names[i].name_length);
442 _gnutls_server_name_unpack (gnutls_buffer_st * ps,
443 extension_priv_data_t * _priv)
445 server_name_ext_st *priv;
447 extension_priv_data_t epriv;
449 priv = gnutls_calloc (1, sizeof (*priv));
453 return GNUTLS_E_MEMORY_ERROR;
456 BUFFER_POP_NUM (ps, priv->server_names_size);
457 for (i = 0; i < priv->server_names_size; i++)
459 BUFFER_POP_NUM (ps, priv->server_names[i].type);
460 BUFFER_POP_NUM (ps, priv->server_names[i].name_length);
461 if (priv->server_names[i].name_length >
462 sizeof (priv->server_names[i].name))
465 return GNUTLS_E_PARSING_ERROR;
467 BUFFER_POP (ps, priv->server_names[i].name,
468 priv->server_names[i].name_length);