corrected copyright notices
[gnutls.git] / lib / ext / server_name.c
blobde5fbe5dee608a281059931b52640543b0ad0f2e
1 /*
2 * Copyright (C) 2002-2012 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
8 * The GnuTLS is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 3 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
23 #include "gnutls_int.h"
24 #include "gnutls_auth.h"
25 #include "gnutls_errors.h"
26 #include "gnutls_num.h"
27 #include <ext/server_name.h>
29 static int _gnutls_server_name_recv_params (gnutls_session_t session,
30 const uint8_t * data,
31 size_t data_size);
32 static int _gnutls_server_name_send_params (gnutls_session_t session,
33 gnutls_buffer_st* extdata);
35 static int _gnutls_server_name_unpack (gnutls_buffer_st * ps,
36 extension_priv_data_t * _priv);
37 static int _gnutls_server_name_pack (extension_priv_data_t _priv,
38 gnutls_buffer_st * ps);
39 static void _gnutls_server_name_deinit_data (extension_priv_data_t priv);
42 extension_entry_st ext_mod_server_name = {
43 .name = "SERVER NAME",
44 .type = GNUTLS_EXTENSION_SERVER_NAME,
45 .parse_type = GNUTLS_EXT_APPLICATION,
47 .recv_func = _gnutls_server_name_recv_params,
48 .send_func = _gnutls_server_name_send_params,
49 .pack_func = _gnutls_server_name_pack,
50 .unpack_func = _gnutls_server_name_unpack,
51 .deinit_func = _gnutls_server_name_deinit_data,
55 * In case of a server: if a NAME_DNS extension type is received then
56 * it stores into the session the value of NAME_DNS. The server may
57 * use gnutls_ext_get_server_name(), in order to access it.
59 * In case of a client: If a proper NAME_DNS extension type is found
60 * in the session then it sends the extension to the peer.
63 static int
64 _gnutls_server_name_recv_params (gnutls_session_t session,
65 const uint8_t * data, size_t _data_size)
67 int i;
68 const unsigned char *p;
69 uint16_t len, type;
70 ssize_t data_size = _data_size;
71 int server_names = 0;
72 server_name_ext_st *priv;
73 extension_priv_data_t epriv;
75 if (session->security_parameters.entity == GNUTLS_SERVER)
77 DECR_LENGTH_RET (data_size, 2, 0);
78 len = _gnutls_read_uint16 (data);
80 if (len != data_size)
82 /* This is unexpected packet length, but
83 * just ignore it, for now.
85 gnutls_assert ();
86 return 0;
89 p = data + 2;
91 /* Count all server_names in the packet. */
92 while (data_size > 0)
94 DECR_LENGTH_RET (data_size, 1, 0);
95 p++;
97 DECR_LEN (data_size, 2);
98 len = _gnutls_read_uint16 (p);
99 p += 2;
101 if (len > 0)
103 DECR_LENGTH_RET (data_size, len, 0);
104 server_names++;
105 p += len;
107 else
108 _gnutls_handshake_log
109 ("HSK[%p]: Received (0) size server name (under attack?)\n",
110 session);
114 /* we cannot accept more server names.
116 if (server_names > MAX_SERVER_NAME_EXTENSIONS)
118 _gnutls_handshake_log
119 ("HSK[%p]: Too many server names received (under attack?)\n",
120 session);
121 server_names = MAX_SERVER_NAME_EXTENSIONS;
124 if (server_names == 0)
125 return 0; /* no names found */
127 priv = gnutls_calloc (1, sizeof (*priv));
128 if (priv == NULL)
130 gnutls_assert ();
131 return GNUTLS_E_MEMORY_ERROR;
134 priv->server_names_size = server_names;
136 p = data + 2;
137 for (i = 0; i < server_names; i++)
139 type = *p;
140 p++;
142 len = _gnutls_read_uint16 (p);
143 p += 2;
145 switch (type)
147 case 0: /* NAME_DNS */
148 if (len <= MAX_SERVER_NAME_SIZE)
150 memcpy (priv->server_names[i].name, p, len);
151 priv->server_names[i].name_length = len;
152 priv->server_names[i].type = GNUTLS_NAME_DNS;
153 break;
157 /* move to next record */
158 p += len;
161 epriv.ptr = priv;
162 _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_SERVER_NAME,
163 epriv);
167 return 0;
170 /* returns data_size or a negative number on failure
172 static int
173 _gnutls_server_name_send_params (gnutls_session_t session,
174 gnutls_buffer_st* extdata)
176 uint16_t len;
177 unsigned i;
178 int total_size = 0, ret;
179 server_name_ext_st *priv;
180 extension_priv_data_t epriv;
182 ret =
183 _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SERVER_NAME,
184 &epriv);
185 if (ret < 0)
186 return 0;
189 /* this function sends the client extension data (dnsname)
191 if (session->security_parameters.entity == GNUTLS_CLIENT)
193 priv = epriv.ptr;
195 if (priv->server_names_size == 0)
196 return 0;
198 /* uint16_t
200 total_size = 2;
201 for (i = 0; i < priv->server_names_size; i++)
203 /* count the total size
205 len = priv->server_names[i].name_length;
207 /* uint8_t + uint16_t + size
209 total_size += 1 + 2 + len;
212 /* UINT16: write total size of all names
214 ret = _gnutls_buffer_append_prefix(extdata, 16, total_size - 2);
215 if (ret < 0)
216 return gnutls_assert_val(ret);
218 for (i = 0; i < priv->server_names_size; i++)
221 switch (priv->server_names[i].type)
223 case GNUTLS_NAME_DNS:
224 len = priv->server_names[i].name_length;
225 if (len == 0)
226 break;
228 /* UINT8: type of this extension
229 * UINT16: size of the first name
230 * LEN: the actual server name.
232 ret = _gnutls_buffer_append_prefix(extdata, 8, 0);
233 if (ret < 0)
234 return gnutls_assert_val(ret);
236 ret = _gnutls_buffer_append_data_prefix(extdata, 16, priv->server_names[i].name, len);
237 if (ret < 0)
238 return gnutls_assert_val(ret);
240 break;
241 default:
242 gnutls_assert ();
243 return GNUTLS_E_INTERNAL_ERROR;
248 return total_size;
252 * gnutls_server_name_get:
253 * @session: is a #gnutls_session_t structure.
254 * @data: will hold the data
255 * @data_length: will hold the data length. Must hold the maximum size of data.
256 * @type: will hold the server name indicator type
257 * @indx: is the index of the server_name
259 * This function will allow you to get the name indication (if any), a
260 * client has sent. The name indication may be any of the enumeration
261 * gnutls_server_name_type_t.
263 * If @type is GNUTLS_NAME_DNS, then this function is to be used by
264 * servers that support virtual hosting, and the data will be a null
265 * terminated UTF-8 string.
267 * If @data has not enough size to hold the server name
268 * GNUTLS_E_SHORT_MEMORY_BUFFER is returned, and @data_length will
269 * hold the required size.
271 * @index is used to retrieve more than one server names (if sent by
272 * the client). The first server name has an index of 0, the second 1
273 * and so on. If no name with the given index exists
274 * GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned.
276 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
277 * otherwise a negative error code is returned.
280 gnutls_server_name_get (gnutls_session_t session, void *data,
281 size_t * data_length,
282 unsigned int *type, unsigned int indx)
284 char *_data = data;
285 server_name_ext_st *priv;
286 int ret;
287 extension_priv_data_t epriv;
289 if (session->security_parameters.entity == GNUTLS_CLIENT)
291 gnutls_assert ();
292 return GNUTLS_E_INVALID_REQUEST;
295 ret =
296 _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SERVER_NAME,
297 &epriv);
298 if (ret < 0)
300 gnutls_assert ();
301 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
304 priv = epriv.ptr;
306 if (indx + 1 > priv->server_names_size)
308 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
311 *type = priv->server_names[indx].type;
313 if (*data_length > /* greater since we need one extra byte for the null */
314 priv->server_names[indx].name_length)
316 *data_length = priv->server_names[indx].name_length;
317 memcpy (data, priv->server_names[indx].name, *data_length);
319 if (*type == GNUTLS_NAME_DNS) /* null terminate */
320 _data[(*data_length)] = 0;
323 else
325 *data_length = priv->server_names[indx].name_length + 1;
326 return GNUTLS_E_SHORT_MEMORY_BUFFER;
329 return 0;
333 * gnutls_server_name_set:
334 * @session: is a #gnutls_session_t structure.
335 * @type: specifies the indicator type
336 * @name: is a string that contains the server name.
337 * @name_length: holds the length of name
339 * This function is to be used by clients that want to inform (via a
340 * TLS extension mechanism) the server of the name they connected to.
341 * This should be used by clients that connect to servers that do
342 * virtual hosting.
344 * The value of @name depends on the @type type. In case of
345 * %GNUTLS_NAME_DNS, an ASCII (0)-terminated domain name string,
346 * without the trailing dot, is expected. IPv4 or IPv6 addresses are
347 * not permitted.
349 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
350 * otherwise a negative error code is returned.
353 gnutls_server_name_set (gnutls_session_t session,
354 gnutls_server_name_type_t type,
355 const void *name, size_t name_length)
357 int server_names, ret;
358 server_name_ext_st *priv;
359 extension_priv_data_t epriv;
360 int set = 0;
362 if (session->security_parameters.entity == GNUTLS_SERVER)
364 gnutls_assert ();
365 return GNUTLS_E_INVALID_REQUEST;
368 if (name_length > MAX_SERVER_NAME_SIZE)
369 return GNUTLS_E_SHORT_MEMORY_BUFFER;
371 ret =
372 _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SERVER_NAME,
373 &epriv);
374 if (ret < 0)
376 set = 1;
379 if (set != 0)
381 priv = gnutls_calloc (1, sizeof (*priv));
382 if (priv == NULL)
384 gnutls_assert ();
385 return GNUTLS_E_MEMORY_ERROR;
387 epriv.ptr = priv;
389 else
390 priv = epriv.ptr;
392 server_names = priv->server_names_size + 1;
394 if (server_names > MAX_SERVER_NAME_EXTENSIONS)
395 server_names = MAX_SERVER_NAME_EXTENSIONS;
397 priv->server_names[server_names - 1].type = type;
398 memcpy (priv->server_names[server_names - 1].name, name, name_length);
399 priv->server_names[server_names - 1].name_length = name_length;
401 priv->server_names_size = server_names;
403 if (set != 0)
404 _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_SERVER_NAME,
405 epriv);
407 return 0;
410 static void
411 _gnutls_server_name_deinit_data (extension_priv_data_t priv)
413 gnutls_free (priv.ptr);
416 static int
417 _gnutls_server_name_pack (extension_priv_data_t epriv, gnutls_buffer_st * ps)
419 server_name_ext_st *priv = epriv.ptr;
420 unsigned int i;
421 int ret;
423 BUFFER_APPEND_NUM (ps, priv->server_names_size);
424 for (i = 0; i < priv->server_names_size; i++)
426 BUFFER_APPEND_NUM (ps, priv->server_names[i].type);
427 BUFFER_APPEND_PFX4 (ps, priv->server_names[i].name,
428 priv->server_names[i].name_length);
430 return 0;
433 static int
434 _gnutls_server_name_unpack (gnutls_buffer_st * ps,
435 extension_priv_data_t * _priv)
437 server_name_ext_st *priv;
438 unsigned int i;
439 int ret;
440 extension_priv_data_t epriv;
442 priv = gnutls_calloc (1, sizeof (*priv));
443 if (priv == NULL)
445 gnutls_assert ();
446 return GNUTLS_E_MEMORY_ERROR;
449 BUFFER_POP_NUM (ps, priv->server_names_size);
450 for (i = 0; i < priv->server_names_size; i++)
452 BUFFER_POP_NUM (ps, priv->server_names[i].type);
453 BUFFER_POP_NUM (ps, priv->server_names[i].name_length);
454 if (priv->server_names[i].name_length >
455 sizeof (priv->server_names[i].name))
457 gnutls_assert ();
458 return GNUTLS_E_PARSING_ERROR;
460 BUFFER_POP (ps, priv->server_names[i].name,
461 priv->server_names[i].name_length);
464 epriv.ptr = priv;
465 *_priv = epriv;
467 return 0;
469 error:
470 gnutls_free (priv);
471 return ret;