2 * Copyright (C) 2002, 2003, 2004, 2005, 2008, 2009 Free Software Foundation
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GNUTLS.
8 * The GNUTLS library 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 2.1 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
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
25 #include "gnutls_int.h"
26 #include "gnutls_auth.h"
27 #include "gnutls_errors.h"
28 #include "gnutls_num.h"
29 #include <ext_server_name.h>
32 * In case of a server: if a NAME_DNS extension type is received then
33 * it stores into the session the value of NAME_DNS. The server may
34 * use gnutls_ext_get_server_name(), in order to access it.
36 * In case of a client: If a proper NAME_DNS extension type is found
37 * in the session then it sends the extension to the peer.
42 _gnutls_server_name_recv_params (gnutls_session_t session
,
43 const opaque
* data
, size_t _data_size
)
46 const unsigned char *p
;
48 ssize_t data_size
= _data_size
;
51 if (session
->security_parameters
.entity
== GNUTLS_SERVER
)
53 DECR_LENGTH_RET (data_size
, 2, 0);
54 len
= _gnutls_read_uint16 (data
);
58 /* This is unexpected packet length, but
59 * just ignore it, for now.
67 /* Count all server_names in the packet. */
70 DECR_LENGTH_RET (data_size
, 1, 0);
73 DECR_LEN (data_size
, 2);
74 len
= _gnutls_read_uint16 (p
);
79 DECR_LENGTH_RET (data_size
, len
, 0);
85 ("HSK[%p]: Received zero size server name (under attack?)\n",
90 /* we cannot accept more server names.
92 if (server_names
> MAX_SERVER_NAME_EXTENSIONS
)
95 ("HSK[%p]: Too many server names received (under attack?)\n",
97 server_names
= MAX_SERVER_NAME_EXTENSIONS
;
100 session
->security_parameters
.extensions
.server_names_size
=
102 if (server_names
== 0)
103 return 0; /* no names found */
107 for (i
= 0; i
< server_names
; i
++)
112 len
= _gnutls_read_uint16 (p
);
117 case 0: /* NAME_DNS */
118 if (len
<= MAX_SERVER_NAME_SIZE
)
120 memcpy (session
->security_parameters
.extensions
.
121 server_names
[i
].name
, p
, len
);
122 session
->security_parameters
.extensions
.
123 server_names
[i
].name_length
= len
;
124 session
->security_parameters
.extensions
.
125 server_names
[i
].type
= GNUTLS_NAME_DNS
;
130 /* move to next record */
137 /* returns data_size or a negative number on failure
140 _gnutls_server_name_send_params (gnutls_session_t session
,
141 opaque
* data
, size_t _data_size
)
146 ssize_t data_size
= _data_size
;
149 /* this function sends the client extension data (dnsname)
151 if (session
->security_parameters
.entity
== GNUTLS_CLIENT
)
154 if (session
->security_parameters
.extensions
.server_names_size
== 0)
161 i
< session
->security_parameters
.extensions
.server_names_size
; i
++)
163 /* count the total size
166 session
->security_parameters
.extensions
.server_names
[i
].
169 /* uint8_t + uint16_t + size
171 total_size
+= 1 + 2 + len
;
176 /* UINT16: write total size of all names
178 DECR_LENGTH_RET (data_size
, 2, GNUTLS_E_SHORT_MEMORY_BUFFER
);
179 _gnutls_write_uint16 (total_size
- 2, p
);
183 i
< session
->security_parameters
.extensions
.server_names_size
; i
++)
186 switch (session
->security_parameters
.extensions
.
187 server_names
[i
].type
)
189 case GNUTLS_NAME_DNS
:
192 session
->security_parameters
.extensions
.
193 server_names
[i
].name_length
;
197 /* UINT8: type of this extension
198 * UINT16: size of the first name
199 * LEN: the actual server name.
201 DECR_LENGTH_RET (data_size
, len
+ 3,
202 GNUTLS_E_SHORT_MEMORY_BUFFER
);
204 *p
= 0; /* NAME_DNS type */
207 _gnutls_write_uint16 (len
, p
);
211 session
->security_parameters
.extensions
.
212 server_names
[i
].name
, len
);
217 return GNUTLS_E_INTERNAL_ERROR
;
226 * gnutls_server_name_get - Used to get the server name indicator send by a client
227 * @session: is a #gnutls_session_t structure.
228 * @data: will hold the data
229 * @data_length: will hold the data length. Must hold the maximum size of data.
230 * @type: will hold the server name indicator type
231 * @indx: is the index of the server_name
233 * This function will allow you to get the name indication (if any), a
234 * client has sent. The name indication may be any of the enumeration
235 * gnutls_server_name_type_t.
237 * If @type is GNUTLS_NAME_DNS, then this function is to be used by
238 * servers that support virtual hosting, and the data will be a null
239 * terminated UTF-8 string.
241 * If @data has not enough size to hold the server name
242 * GNUTLS_E_SHORT_MEMORY_BUFFER is returned, and @data_length will
243 * hold the required size.
245 * @index is used to retrieve more than one server names (if sent by
246 * the client). The first server name has an index of 0, the second 1
247 * and so on. If no name with the given index exists
248 * GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned.
250 * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned,
251 * otherwise an error code is returned.
254 gnutls_server_name_get (gnutls_session_t session
, void *data
,
255 size_t * data_length
,
256 unsigned int *type
, unsigned int indx
)
260 if (session
->security_parameters
.entity
== GNUTLS_CLIENT
)
263 return GNUTLS_E_INVALID_REQUEST
;
266 if (indx
+ 1 > session
->security_parameters
.extensions
.server_names_size
)
268 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
;
271 *type
= session
->security_parameters
.extensions
.server_names
[indx
].type
;
273 if (*data_length
> /* greater since we need one extra byte for the null */
274 session
->security_parameters
.extensions
.server_names
[indx
].name_length
)
277 session
->security_parameters
.extensions
.server_names
[indx
].
280 session
->security_parameters
.extensions
.server_names
[indx
].name
,
283 if (*type
== GNUTLS_NAME_DNS
) /* null terminate */
284 _data
[(*data_length
)] = 0;
290 session
->security_parameters
.extensions
.server_names
[indx
].
292 return GNUTLS_E_SHORT_MEMORY_BUFFER
;
299 * gnutls_server_name_set - set a name indicator to be sent as an extension
300 * @session: is a #gnutls_session_t structure.
301 * @type: specifies the indicator type
302 * @name: is a string that contains the server name.
303 * @name_length: holds the length of name
305 * This function is to be used by clients that want to inform (via a
306 * TLS extension mechanism) the server of the name they connected to.
307 * This should be used by clients that connect to servers that do
310 * The value of @name depends on the @ind type. In case of
311 * GNUTLS_NAME_DNS, an ASCII or UTF-8 null terminated string, without
312 * the trailing dot, is expected. IPv4 or IPv6 addresses are not
315 * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned,
316 * otherwise an error code is returned.
319 gnutls_server_name_set (gnutls_session_t session
,
320 gnutls_server_name_type_t type
,
321 const void *name
, size_t name_length
)
325 if (session
->security_parameters
.entity
== GNUTLS_SERVER
)
328 return GNUTLS_E_INVALID_REQUEST
;
331 if (name_length
> MAX_SERVER_NAME_SIZE
)
332 return GNUTLS_E_SHORT_MEMORY_BUFFER
;
334 server_names
= session
->security_parameters
.extensions
.server_names_size
+ 1;
336 if (server_names
> MAX_SERVER_NAME_EXTENSIONS
)
337 server_names
= MAX_SERVER_NAME_EXTENSIONS
;
339 session
->security_parameters
.extensions
.server_names
340 [server_names
- 1].type
= type
;
341 memcpy (session
->security_parameters
.extensions
.
342 server_names
[server_names
- 1].name
, name
, name_length
);
343 session
->security_parameters
.extensions
.server_names
344 [server_names
- 1].name_length
= name_length
;
346 session
->security_parameters
.extensions
.server_names_size
++;