Guile: Fix `x509-certificate-dn-oid' and related functions.
[gnutls.git] / lib / ext_server_name.c
blobf9ca429a8023b35112dd73a7bc494e5afc547c15
1 /*
2 * Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation
4 * Author: Nikos Mavroyanopoulos
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,
21 * USA
25 #include "gnutls_int.h"
26 #include "gnutls_auth_int.h"
27 #include "gnutls_errors.h"
28 #include "gnutls_num.h"
29 #include <ext_server_name.h>
31 /*
32 * In case of a server: if a NAME_DNS extension type is received then it stores
33 * into the session the value of NAME_DNS. The server may use gnutls_ext_get_server_name(),
34 * in order to access it.
36 * In case of a client: If a proper NAME_DNS extension type is found in the session then
37 * it sends the extension to the peer.
41 int
42 _gnutls_server_name_recv_params (gnutls_session_t session,
43 const opaque * data, size_t _data_size)
45 int i;
46 const unsigned char *p;
47 uint16_t len, type;
48 ssize_t data_size = _data_size;
49 int server_names = 0;
51 if (session->security_parameters.entity == GNUTLS_SERVER)
53 DECR_LENGTH_RET (data_size, 2, 0);
54 len = _gnutls_read_uint16 (data);
56 if (len != data_size)
58 /* This is unexpected packet length, but
59 * just ignore it, for now.
61 gnutls_assert ();
62 return 0;
65 p = data + 2;
67 /* Count all server_names in the packet. */
68 while (data_size > 0)
70 DECR_LENGTH_RET (data_size, 1, 0);
71 p++;
73 DECR_LEN (data_size, 2);
74 len = _gnutls_read_uint16 (p);
75 p += 2;
77 DECR_LENGTH_RET (data_size, len, 0);
78 server_names++;
80 p += len;
83 session->security_parameters.extensions.server_names_size =
84 server_names;
85 if (server_names == 0)
86 return 0; /* no names found */
88 /* we cannot accept more server names.
90 if (server_names > MAX_SERVER_NAME_EXTENSIONS)
91 server_names = MAX_SERVER_NAME_EXTENSIONS;
93 p = data + 2;
94 for (i = 0; i < server_names; i++)
96 type = *p;
97 p++;
99 len = _gnutls_read_uint16 (p);
100 p += 2;
102 switch (type)
104 case 0: /* NAME_DNS */
105 if (len <= MAX_SERVER_NAME_SIZE)
107 memcpy (session->security_parameters.extensions.
108 server_names[i].name, p, len);
109 session->security_parameters.extensions.
110 server_names[i].name_length = len;
111 session->security_parameters.extensions.
112 server_names[i].type = GNUTLS_NAME_DNS;
113 break;
117 /* move to next record */
118 p += len;
121 return 0;
124 /* returns data_size or a negative number on failure
127 _gnutls_server_name_send_params (gnutls_session_t session,
128 opaque * data, size_t _data_size)
130 uint16_t len;
131 opaque *p;
132 unsigned i;
133 ssize_t data_size = _data_size;
134 int total_size = 0;
136 /* this function sends the client extension data (dnsname)
138 if (session->security_parameters.entity == GNUTLS_CLIENT)
141 if (session->security_parameters.extensions.server_names_size == 0)
142 return 0;
144 /* uint16_t
146 total_size = 2;
147 for (i = 0;
148 i < session->security_parameters.extensions.server_names_size; i++)
150 /* count the total size
152 len =
153 session->security_parameters.extensions.server_names[i].
154 name_length;
156 /* uint8_t + uint16_t + size
158 total_size += 1 + 2 + len;
161 p = data;
163 /* UINT16: write total size of all names
165 DECR_LENGTH_RET (data_size, 2, GNUTLS_E_SHORT_MEMORY_BUFFER);
166 _gnutls_write_uint16 (total_size - 2, p);
167 p += 2;
169 for (i = 0;
170 i < session->security_parameters.extensions.server_names_size; i++)
173 switch (session->security_parameters.extensions.
174 server_names[i].type)
176 case GNUTLS_NAME_DNS:
178 len =
179 session->security_parameters.extensions.
180 server_names[i].name_length;
181 if (len == 0)
182 break;
184 /* UINT8: type of this extension
185 * UINT16: size of the first name
186 * LEN: the actual server name.
188 DECR_LENGTH_RET (data_size, len + 3,
189 GNUTLS_E_SHORT_MEMORY_BUFFER);
191 *p = 0; /* NAME_DNS type */
192 p++;
194 _gnutls_write_uint16 (len, p);
195 p += 2;
197 memcpy (p,
198 session->security_parameters.extensions.
199 server_names[0].name, len);
200 p += len;
201 break;
202 default:
203 gnutls_assert ();
204 return GNUTLS_E_INTERNAL_ERROR;
209 return total_size;
213 * gnutls_server_name_get - Used to get the server name indicator send by a client
214 * @session: is a #gnutls_session_t structure.
215 * @data: will hold the data
216 * @data_length: will hold the data length. Must hold the maximum size of data.
217 * @type: will hold the server name indicator type
218 * @indx: is the index of the server_name
220 * This function will allow you to get the name indication (if any),
221 * a client has sent. The name indication may be any of the enumeration
222 * gnutls_server_name_type_t.
224 * If @type is GNUTLS_NAME_DNS, then this function is to be used by servers
225 * that support virtual hosting, and the data will be a null terminated UTF-8 string.
227 * If @data has not enough size to hold the server name GNUTLS_E_SHORT_MEMORY_BUFFER
228 * is returned, and @data_length will hold the required size.
230 * @index is used to retrieve more than one server names (if sent by the client).
231 * The first server name has an index of 0, the second 1 and so on. If no name with the given
232 * index exists GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned.
236 gnutls_server_name_get (gnutls_session_t session, void *data,
237 size_t * data_length,
238 unsigned int *type, unsigned int indx)
240 char *_data = data;
242 if (session->security_parameters.entity == GNUTLS_CLIENT)
244 gnutls_assert ();
245 return GNUTLS_E_INVALID_REQUEST;
248 if (indx + 1 > session->security_parameters.extensions.server_names_size)
250 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
253 *type = session->security_parameters.extensions.server_names[indx].type;
255 if (*data_length > /* greater since we need one extra byte for the null */
256 session->security_parameters.extensions.server_names[indx].name_length)
258 *data_length =
259 session->security_parameters.extensions.server_names[indx].
260 name_length;
261 memcpy (data,
262 session->security_parameters.extensions.server_names[indx].
263 name, *data_length);
265 if (*type == GNUTLS_NAME_DNS) /* null terminate */
266 _data[(*data_length)] = 0;
269 else
271 *data_length =
272 session->security_parameters.extensions.server_names[indx].
273 name_length;
274 return GNUTLS_E_SHORT_MEMORY_BUFFER;
277 return 0;
281 * gnutls_server_name_set - Used to set a name indicator to be sent as an extension
282 * @session: is a #gnutls_session_t structure.
283 * @type: specifies the indicator type
284 * @name: is a string that contains the server name.
285 * @name_length: holds the length of name
287 * This function is to be used by clients that want to inform
288 * (via a TLS extension mechanism) the server of the name they
289 * connected to. This should be used by clients that connect
290 * to servers that do virtual hosting.
292 * The value of @name depends on the @ind type. In case of GNUTLS_NAME_DNS,
293 * an ASCII or UTF-8 null terminated string, without the trailing dot, is expected.
294 * IPv4 or IPv6 addresses are not permitted.
298 gnutls_server_name_set (gnutls_session_t session,
299 gnutls_server_name_type_t type,
300 const void *name, size_t name_length)
302 int server_names;
304 if (session->security_parameters.entity == GNUTLS_SERVER)
306 gnutls_assert ();
307 return GNUTLS_E_INVALID_REQUEST;
310 if (name_length > MAX_SERVER_NAME_SIZE)
311 return GNUTLS_E_SHORT_MEMORY_BUFFER;
313 server_names =
314 session->security_parameters.extensions.server_names_size + 1;
316 if (server_names > MAX_SERVER_NAME_EXTENSIONS)
317 server_names = MAX_SERVER_NAME_EXTENSIONS;
319 session->security_parameters.extensions.server_names[server_names -
320 1].type = type;
321 memcpy (session->security_parameters.extensions.
322 server_names[server_names - 1].name, name, name_length);
323 session->security_parameters.extensions.server_names[server_names -
324 1].name_length =
325 name_length;
327 session->security_parameters.extensions.server_names_size++;
329 return 0;