Line data Source code
1 : /*
2 : * Copyright (C) 2002-2012 Free Software Foundation, Inc.
3 : * Copyright (C) 2017 Red Hat, Inc.
4 : *
5 : * Author: Nikos Mavrogiannopoulos
6 : *
7 : * This file is part of GnuTLS.
8 : *
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.
13 : *
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.
18 : *
19 : * You should have received a copy of the GNU Lesser General Public License
20 : * along with this program. If not, see <https://www.gnu.org/licenses/>
21 : *
22 : */
23 :
24 : #include "gnutls_int.h"
25 : #include "auth.h"
26 : #include "errors.h"
27 : #include "num.h"
28 : #include "str.h"
29 : #include <ext/server_name.h>
30 : #include "hello_ext_lib.h"
31 :
32 : static int _gnutls_server_name_recv_params(gnutls_session_t session,
33 : const uint8_t * data,
34 : size_t data_size);
35 : static int _gnutls_server_name_send_params(gnutls_session_t session,
36 : gnutls_buffer_st * extdata);
37 :
38 : int
39 : _gnutls_server_name_set_raw(gnutls_session_t session,
40 : gnutls_server_name_type_t type,
41 : const void *name, size_t name_length);
42 :
43 : const hello_ext_entry_st ext_mod_server_name = {
44 : .name = "Server Name Indication",
45 : .tls_id = 0,
46 : .gid = GNUTLS_EXTENSION_SERVER_NAME,
47 : .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_CLIENT_HELLO |
48 : GNUTLS_EXT_FLAG_EE | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
49 : .client_parse_point = GNUTLS_EXT_MANDATORY,
50 : .server_parse_point = GNUTLS_EXT_MANDATORY,
51 : .recv_func = _gnutls_server_name_recv_params,
52 : .send_func = _gnutls_server_name_send_params,
53 : .pack_func = _gnutls_hello_ext_default_pack,
54 : .unpack_func = _gnutls_hello_ext_default_unpack,
55 : .deinit_func = _gnutls_hello_ext_default_deinit,
56 : .cannot_be_overriden = 1
57 : };
58 :
59 : /*
60 : * In case of a server: if a NAME_DNS extension type is received then
61 : * it stores into the session the value of NAME_DNS. The server may
62 : * use gnutls_ext_get_server_name(), in order to access it.
63 : *
64 : * In case of a client: If a proper NAME_DNS extension type is found
65 : * in the session then it sends the extension to the peer.
66 : *
67 : */
68 : static int
69 2099 : _gnutls_server_name_recv_params(gnutls_session_t session,
70 : const uint8_t * data, size_t data_size)
71 : {
72 2099 : const unsigned char *p;
73 2099 : uint16_t len, type;
74 2099 : gnutls_datum_t name;
75 :
76 2099 : if (session->security_parameters.entity == GNUTLS_SERVER) {
77 2095 : DECR_LENGTH_RET(data_size, 2, GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
78 2092 : len = _gnutls_read_uint16(data);
79 2092 : if (len == 0)
80 5 : return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
81 :
82 2088 : if (len != data_size) {
83 5 : gnutls_assert();
84 5 : return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
85 : }
86 :
87 2083 : p = data + 2;
88 :
89 2175 : while (data_size > 0) {
90 2148 : DECR_LEN(data_size, 1);
91 2148 : type = *p;
92 2148 : p++;
93 :
94 2148 : DECR_LEN(data_size, 2);
95 2142 : len = _gnutls_read_uint16(p);
96 2142 : p += 2;
97 :
98 2142 : if (len == 0) {
99 5 : _gnutls_handshake_log
100 : ("HSK[%p]: Received server name size of zero\n",
101 : session);
102 6 : return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
103 : }
104 :
105 2137 : DECR_LEN(data_size, len);
106 :
107 2128 : if (type == 0) { /* NAME_DNS */
108 4072 : if (!_gnutls_dnsname_is_valid((char*)p, len)) {
109 530 : _gnutls_handshake_log
110 : ("HSK[%p]: Server name is not acceptable: '%.*s'\n",
111 : session, (int) len, p);
112 533 : return gnutls_assert_val(GNUTLS_E_RECEIVED_DISALLOWED_NAME);
113 : }
114 :
115 1506 : name.data = (void*)p;
116 1506 : name.size = len;
117 :
118 1506 : _gnutls_hello_ext_unset_priv(session, GNUTLS_EXTENSION_SERVER_NAME);
119 1506 : return _gnutls_hello_ext_set_datum(session,
120 : GNUTLS_EXTENSION_SERVER_NAME,
121 : &name);
122 : }
123 92 : p += len;
124 :
125 : }
126 :
127 :
128 : }
129 :
130 : return 0;
131 : }
132 :
133 : /* returns data_size or a negative number on failure
134 : */
135 : static int
136 4875 : _gnutls_server_name_send_params(gnutls_session_t session,
137 : gnutls_buffer_st * extdata)
138 : {
139 4875 : int total_size = 0, ret;
140 4875 : gnutls_datum_t name;
141 :
142 4875 : ret =
143 4875 : _gnutls_hello_ext_get_datum(session, GNUTLS_EXTENSION_SERVER_NAME,
144 : &name);
145 4875 : if (ret < 0)
146 : return 0;
147 :
148 : /* this function sends the client extension data (dnsname)
149 : */
150 1516 : if (session->security_parameters.entity == GNUTLS_CLIENT) {
151 437 : if (name.size == 0)
152 : return 0;
153 :
154 : /* uint8_t + uint16_t + size
155 : */
156 437 : total_size = 2 + 1 + 2 + name.size;
157 :
158 : /* UINT16: write total size of all names
159 : */
160 437 : ret =
161 874 : _gnutls_buffer_append_prefix(extdata, 16,
162 437 : total_size - 2);
163 437 : if (ret < 0)
164 0 : return gnutls_assert_val(ret);
165 :
166 : /* UINT8: type of this extension
167 : * UINT16: size of the first name
168 : * LEN: the actual server name.
169 : */
170 437 : ret =
171 437 : _gnutls_buffer_append_prefix(extdata, 8, 0);
172 437 : if (ret < 0)
173 0 : return gnutls_assert_val(ret);
174 :
175 437 : _gnutls_debug_log("HSK[%p]: sent server name: '%.*s'\n", session, name.size, name.data);
176 :
177 437 : ret =
178 874 : _gnutls_buffer_append_data_prefix
179 : (extdata, 16,
180 437 : name.data, name.size);
181 437 : if (ret < 0)
182 0 : return gnutls_assert_val(ret);
183 : } else {
184 : return 0;
185 : }
186 :
187 : return total_size;
188 : }
189 :
190 : /**
191 : * gnutls_server_name_get:
192 : * @session: is a #gnutls_session_t type.
193 : * @data: will hold the data
194 : * @data_length: will hold the data length. Must hold the maximum size of data.
195 : * @type: will hold the server name indicator type
196 : * @indx: is the index of the server_name
197 : *
198 : * This function will allow you to get the name indication (if any), a
199 : * client has sent. The name indication may be any of the enumeration
200 : * gnutls_server_name_type_t.
201 : *
202 : * If @type is GNUTLS_NAME_DNS, then this function is to be used by
203 : * servers that support virtual hosting, and the data will be a null
204 : * terminated IDNA ACE string (prior to GnuTLS 3.4.0 it was a UTF-8 string).
205 : *
206 : * If @data has not enough size to hold the server name
207 : * GNUTLS_E_SHORT_MEMORY_BUFFER is returned, and @data_length will
208 : * hold the required size.
209 : *
210 : * @indx is used to retrieve more than one server names (if sent by
211 : * the client). The first server name has an index of 0, the second 1
212 : * and so on. If no name with the given index exists
213 : * GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned.
214 : *
215 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, on UTF-8
216 : * decoding error %GNUTLS_E_IDNA_ERROR is returned, otherwise a negative
217 : * error code is returned.
218 : **/
219 : int
220 22859 : gnutls_server_name_get(gnutls_session_t session, void *data,
221 : size_t * data_length,
222 : unsigned int *type, unsigned int indx)
223 : {
224 22859 : char *_data = data;
225 22859 : gnutls_datum_t name;
226 22859 : int ret;
227 :
228 22859 : if (session->security_parameters.entity == GNUTLS_CLIENT) {
229 254 : gnutls_assert();
230 254 : return GNUTLS_E_INVALID_REQUEST;
231 : }
232 :
233 22605 : if (indx != 0)
234 : return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
235 :
236 22603 : ret =
237 22603 : _gnutls_hello_ext_get_datum(session, GNUTLS_EXTENSION_SERVER_NAME, &name);
238 22603 : if (ret < 0) {
239 20691 : gnutls_assert();
240 20691 : return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
241 : }
242 :
243 1912 : if (name.size == 0) {
244 : return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
245 : }
246 :
247 1912 : *type = GNUTLS_NAME_DNS;
248 :
249 1912 : if (*data_length > name.size) { /* greater since we need one extra byte for the null */
250 1847 : *data_length = name.size;
251 1847 : memcpy(data, name.data, *data_length);
252 :
253 : /* null terminate */
254 1847 : _data[(*data_length)] = 0;
255 :
256 : } else {
257 65 : *data_length = name.size + 1;
258 65 : ret = GNUTLS_E_SHORT_MEMORY_BUFFER;
259 65 : goto cleanup;
260 : }
261 :
262 1847 : ret = 0;
263 : cleanup:
264 : return ret;
265 : }
266 :
267 : /* This does not do any conversion not perform any check */
268 : int
269 445 : _gnutls_server_name_set_raw(gnutls_session_t session,
270 : gnutls_server_name_type_t type,
271 : const void *name, size_t name_length)
272 : {
273 445 : int ret;
274 445 : gnutls_datum_t dname;
275 :
276 445 : if (name_length >= MAX_SERVER_NAME_SIZE) {
277 : return GNUTLS_E_INVALID_REQUEST;
278 : }
279 :
280 445 : _gnutls_hello_ext_unset_priv(session, GNUTLS_EXTENSION_SERVER_NAME);
281 :
282 445 : dname.data = (void*)name;
283 445 : dname.size = name_length;
284 :
285 445 : ret = _gnutls_hello_ext_set_datum(session, GNUTLS_EXTENSION_SERVER_NAME, &dname);
286 445 : if (ret < 0)
287 0 : return gnutls_assert_val(ret);
288 :
289 : return 0;
290 : }
291 :
292 : /**
293 : * gnutls_server_name_set:
294 : * @session: is a #gnutls_session_t type.
295 : * @type: specifies the indicator type
296 : * @name: is a string that contains the server name.
297 : * @name_length: holds the length of name excluding the terminating null byte
298 : *
299 : * This function is to be used by clients that want to inform (via a
300 : * TLS extension mechanism) the server of the name they connected to.
301 : * This should be used by clients that connect to servers that do
302 : * virtual hosting.
303 : *
304 : * The value of @name depends on the @type type. In case of
305 : * %GNUTLS_NAME_DNS, a UTF-8 null-terminated domain name string,
306 : * without the trailing dot, is expected.
307 : *
308 : * IPv4 or IPv6 addresses are not permitted to be set by this function.
309 : * If the function is called with a name of @name_length zero it will clear
310 : * all server names set.
311 : *
312 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
313 : * otherwise a negative error code is returned.
314 : **/
315 : int
316 447 : gnutls_server_name_set(gnutls_session_t session,
317 : gnutls_server_name_type_t type,
318 : const void *name, size_t name_length)
319 : {
320 447 : int ret;
321 447 : gnutls_datum_t idn_name = {NULL,0};
322 :
323 447 : if (session->security_parameters.entity == GNUTLS_SERVER) {
324 0 : gnutls_assert();
325 0 : return GNUTLS_E_INVALID_REQUEST;
326 : }
327 :
328 447 : if (name_length == 0) { /* unset extension */
329 5 : _gnutls_hello_ext_unset_priv(session, GNUTLS_EXTENSION_SERVER_NAME);
330 5 : return 0;
331 : }
332 :
333 442 : ret = gnutls_idna_map(name, name_length, &idn_name, 0);
334 442 : if (ret < 0) {
335 0 : _gnutls_debug_log("unable to convert name %s to IDNA2008 format\n", (char*)name);
336 0 : return ret;
337 : }
338 :
339 442 : name = idn_name.data;
340 442 : name_length = idn_name.size;
341 :
342 442 : ret = _gnutls_server_name_set_raw(session, type, name, name_length);
343 442 : gnutls_free(idn_name.data);
344 :
345 442 : return ret;
346 : }
347 :
348 813 : unsigned _gnutls_server_name_matches_resumed(gnutls_session_t session)
349 : {
350 813 : gnutls_datum_t name1, name2;
351 813 : int ret;
352 :
353 813 : ret =
354 813 : _gnutls_hello_ext_get_datum(session,
355 : GNUTLS_EXTENSION_SERVER_NAME,
356 : &name1);
357 813 : if (ret < 0) { /* no server name in this session */
358 747 : name1.data = NULL;
359 747 : name1.size = 0;
360 : }
361 :
362 813 : ret =
363 813 : _gnutls_hello_ext_get_resumed_datum(session,
364 : GNUTLS_EXTENSION_SERVER_NAME,
365 : &name2);
366 813 : if (ret < 0) { /* no server name in this session */
367 747 : name2.data = NULL;
368 747 : name2.size = 0;
369 : }
370 :
371 813 : if (name1.data == NULL || name2.data == NULL) {
372 747 : if (name1.data == name2.data)
373 : return 1;
374 : else
375 0 : return 0;
376 : }
377 :
378 66 : if (name1.size != name2.size)
379 : return 0;
380 :
381 24 : if (memcmp(name1.data, name2.data, name1.size) != 0)
382 0 : return 0;
383 :
384 : return 1;
385 : }
|