Update gnulib files.
[gnutls.git] / lib / ext_server_name.c
blob4ed7aecf4ba57654af614d177c344d223c96ef48
1 /*
2 * Copyright (C) 2002, 2003, 2004, 2005, 2008, 2009, 2010 Free Software
3 * Foundation, Inc.
5 * Author: Nikos Mavrogiannopoulos
7 * This file is part of GNUTLS.
9 * The GNUTLS library 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,
22 * USA
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>
33 * In case of a server: if a NAME_DNS extension type is received then
34 * it stores into the session the value of NAME_DNS. The server may
35 * use gnutls_ext_get_server_name(), in order to access it.
37 * In case of a client: If a proper NAME_DNS extension type is found
38 * in the session then it sends the extension to the peer.
42 int
43 _gnutls_server_name_recv_params (gnutls_session_t session,
44 const opaque * data, size_t _data_size)
46 int i;
47 const unsigned char *p;
48 uint16_t len, type;
49 ssize_t data_size = _data_size;
50 int server_names = 0;
52 if (session->security_parameters.entity == GNUTLS_SERVER)
54 DECR_LENGTH_RET (data_size, 2, 0);
55 len = _gnutls_read_uint16 (data);
57 if (len != data_size)
59 /* This is unexpected packet length, but
60 * just ignore it, for now.
62 gnutls_assert ();
63 return 0;
66 p = data + 2;
68 /* Count all server_names in the packet. */
69 while (data_size > 0)
71 DECR_LENGTH_RET (data_size, 1, 0);
72 p++;
74 DECR_LEN (data_size, 2);
75 len = _gnutls_read_uint16 (p);
76 p += 2;
78 if (len > 0)
80 DECR_LENGTH_RET (data_size, len, 0);
81 server_names++;
82 p += len;
84 else
85 _gnutls_handshake_log
86 ("HSK[%p]: Received zero size server name (under attack?)\n",
87 session);
91 /* we cannot accept more server names.
93 if (server_names > MAX_SERVER_NAME_EXTENSIONS)
95 _gnutls_handshake_log
96 ("HSK[%p]: Too many server names received (under attack?)\n",
97 session);
98 server_names = MAX_SERVER_NAME_EXTENSIONS;
101 session->security_parameters.extensions.server_names_size =
102 server_names;
103 if (server_names == 0)
104 return 0; /* no names found */
107 p = data + 2;
108 for (i = 0; i < server_names; i++)
110 type = *p;
111 p++;
113 len = _gnutls_read_uint16 (p);
114 p += 2;
116 switch (type)
118 case 0: /* NAME_DNS */
119 if (len <= MAX_SERVER_NAME_SIZE)
121 memcpy (session->security_parameters.
122 extensions.server_names[i].name, p, len);
123 session->security_parameters.extensions.server_names[i].
124 name_length = len;
125 session->security_parameters.extensions.server_names[i].
126 type = GNUTLS_NAME_DNS;
127 break;
131 /* move to next record */
132 p += len;
135 return 0;
138 /* returns data_size or a negative number on failure
141 _gnutls_server_name_send_params (gnutls_session_t session,
142 opaque * data, size_t _data_size)
144 uint16_t len;
145 opaque *p;
146 unsigned i;
147 ssize_t data_size = _data_size;
148 int total_size = 0;
150 /* this function sends the client extension data (dnsname)
152 if (session->security_parameters.entity == GNUTLS_CLIENT)
155 if (session->security_parameters.extensions.server_names_size == 0)
156 return 0;
158 /* uint16_t
160 total_size = 2;
161 for (i = 0;
162 i < session->security_parameters.extensions.server_names_size; i++)
164 /* count the total size
166 len =
167 session->security_parameters.extensions.
168 server_names[i].name_length;
170 /* uint8_t + uint16_t + size
172 total_size += 1 + 2 + len;
175 p = data;
177 /* UINT16: write total size of all names
179 DECR_LENGTH_RET (data_size, 2, GNUTLS_E_SHORT_MEMORY_BUFFER);
180 _gnutls_write_uint16 (total_size - 2, p);
181 p += 2;
183 for (i = 0;
184 i < session->security_parameters.extensions.server_names_size; i++)
187 switch (session->security_parameters.extensions.server_names[i].
188 type)
190 case GNUTLS_NAME_DNS:
192 len =
193 session->security_parameters.extensions.server_names[i].
194 name_length;
195 if (len == 0)
196 break;
198 /* UINT8: type of this extension
199 * UINT16: size of the first name
200 * LEN: the actual server name.
202 DECR_LENGTH_RET (data_size, len + 3,
203 GNUTLS_E_SHORT_MEMORY_BUFFER);
205 *p = 0; /* NAME_DNS type */
206 p++;
208 _gnutls_write_uint16 (len, p);
209 p += 2;
211 memcpy (p,
212 session->security_parameters.extensions.server_names[i].
213 name, len);
214 p += len;
215 break;
216 default:
217 gnutls_assert ();
218 return GNUTLS_E_INTERNAL_ERROR;
223 return total_size;
227 * gnutls_server_name_get:
228 * @session: is a #gnutls_session_t structure.
229 * @data: will hold the data
230 * @data_length: will hold the data length. Must hold the maximum size of data.
231 * @type: will hold the server name indicator type
232 * @indx: is the index of the server_name
234 * This function will allow you to get the name indication (if any), a
235 * client has sent. The name indication may be any of the enumeration
236 * gnutls_server_name_type_t.
238 * If @type is GNUTLS_NAME_DNS, then this function is to be used by
239 * servers that support virtual hosting, and the data will be a null
240 * terminated UTF-8 string.
242 * If @data has not enough size to hold the server name
243 * GNUTLS_E_SHORT_MEMORY_BUFFER is returned, and @data_length will
244 * hold the required size.
246 * @index is used to retrieve more than one server names (if sent by
247 * the client). The first server name has an index of 0, the second 1
248 * and so on. If no name with the given index exists
249 * GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned.
251 * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned,
252 * otherwise an error code is returned.
255 gnutls_server_name_get (gnutls_session_t session, void *data,
256 size_t * data_length,
257 unsigned int *type, unsigned int indx)
259 char *_data = data;
261 if (session->security_parameters.entity == GNUTLS_CLIENT)
263 gnutls_assert ();
264 return GNUTLS_E_INVALID_REQUEST;
267 if (indx + 1 > session->security_parameters.extensions.server_names_size)
269 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
272 *type = session->security_parameters.extensions.server_names[indx].type;
274 if (*data_length > /* greater since we need one extra byte for the null */
275 session->security_parameters.extensions.server_names[indx].name_length)
277 *data_length =
278 session->security_parameters.extensions.
279 server_names[indx].name_length;
280 memcpy (data,
281 session->security_parameters.extensions.server_names[indx].name,
282 *data_length);
284 if (*type == GNUTLS_NAME_DNS) /* null terminate */
285 _data[(*data_length)] = 0;
288 else
290 *data_length =
291 session->security_parameters.extensions.
292 server_names[indx].name_length;
293 return GNUTLS_E_SHORT_MEMORY_BUFFER;
296 return 0;
300 * gnutls_server_name_set:
301 * @session: is a #gnutls_session_t structure.
302 * @type: specifies the indicator type
303 * @name: is a string that contains the server name.
304 * @name_length: holds the length of name
306 * This function is to be used by clients that want to inform (via a
307 * TLS extension mechanism) the server of the name they connected to.
308 * This should be used by clients that connect to servers that do
309 * virtual hosting.
311 * The value of @name depends on the @type type. In case of
312 * %GNUTLS_NAME_DNS, an ASCII zero-terminated domain name string,
313 * without the trailing dot, is expected. IPv4 or IPv6 addresses are
314 * not permitted.
316 * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned,
317 * otherwise an error code is returned.
320 gnutls_server_name_set (gnutls_session_t session,
321 gnutls_server_name_type_t type,
322 const void *name, size_t name_length)
324 int server_names;
326 if (session->security_parameters.entity == GNUTLS_SERVER)
328 gnutls_assert ();
329 return GNUTLS_E_INVALID_REQUEST;
332 if (name_length > MAX_SERVER_NAME_SIZE)
333 return GNUTLS_E_SHORT_MEMORY_BUFFER;
335 server_names =
336 session->security_parameters.extensions.server_names_size + 1;
338 if (server_names > MAX_SERVER_NAME_EXTENSIONS)
339 server_names = MAX_SERVER_NAME_EXTENSIONS;
341 session->security_parameters.extensions.server_names
342 [server_names - 1].type = type;
343 memcpy (session->security_parameters.
344 extensions.server_names[server_names - 1].name, name, name_length);
345 session->security_parameters.extensions.server_names[server_names -
346 1].name_length =
347 name_length;
349 session->security_parameters.extensions.server_names_size++;
351 return 0;