Add.
[gnutls.git] / lib / gnutls_v2_compat.c
blob26fcec7091094a1c79de7bd1b1f1af8ba55a4ac7
1 /*
2 * Copyright (C) 2001, 2004, 2005, 2006 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 /* Functions to parse the SSLv2.0 hello message.
28 #include "gnutls_int.h"
29 #include "gnutls_errors.h"
30 #include "gnutls_dh.h"
31 #include "debug.h"
32 #include "gnutls_algorithms.h"
33 #include "gnutls_compress.h"
34 #include "gnutls_cipher.h"
35 #include "gnutls_buffers.h"
36 #include "gnutls_kx.h"
37 #include "gnutls_handshake.h"
38 #include "gnutls_num.h"
39 #include "gnutls_hash_int.h"
40 #include "gnutls_db.h"
41 #include "gnutls_extensions.h"
42 #include "gnutls_auth_int.h"
44 /* This selects the best supported ciphersuite from the ones provided */
45 static int
46 _gnutls_handshake_select_v2_suite (gnutls_session_t session,
47 opaque * data, int datalen)
49 int i, j, ret;
50 opaque *_data;
51 int _datalen;
53 _gnutls_handshake_log ("HSK[%x]: Parsing a version 2.0 client hello.\n",
54 session);
56 _data = gnutls_malloc (datalen);
57 if (_data == NULL)
59 gnutls_assert ();
60 return GNUTLS_E_MEMORY_ERROR;
63 if (datalen % 3 != 0)
65 gnutls_assert ();
66 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
69 i = _datalen = 0;
70 for (j = 0; j < datalen; j += 3)
72 if (data[j] == 0)
74 memcpy (&_data[i], &data[j + 1], 2);
75 i += 2;
76 _datalen += 2;
80 ret = _gnutls_server_select_suite (session, _data, _datalen);
81 gnutls_free (_data);
83 return ret;
88 /* Read a v2 client hello. Some browsers still use that beast!
89 * However they set their version to 3.0 or 3.1.
91 int
92 _gnutls_read_client_hello_v2 (gnutls_session_t session, opaque * data,
93 int datalen)
95 uint16_t session_id_len = 0;
96 int pos = 0;
97 int ret = 0;
98 uint16_t sizeOfSuites;
99 gnutls_protocol_t version;
100 opaque rnd[TLS_RANDOM_SIZE];
101 int len = datalen;
102 int err;
103 uint16_t challenge;
104 opaque session_id[TLS_MAX_SESSION_ID_SIZE];
105 gnutls_protocol_t ver;
107 /* we only want to get here once - only in client hello */
108 session->internals.v2_hello = 0;
110 DECR_LEN (len, 2);
112 _gnutls_handshake_log
113 ("HSK[%x]: SSL 2.0 Hello: Client's version: %d.%d\n", session,
114 data[pos], data[pos + 1]);
116 set_adv_version (session, data[pos], data[pos + 1]);
118 version = _gnutls_version_get (data[pos], data[pos + 1]);
120 /* if we do not support that version
122 if (_gnutls_version_is_supported (session, version) == 0)
124 /* If he requested something we do not support
125 * then we send him the highest we support.
127 ver = _gnutls_version_max (session);
128 if (ver == GNUTLS_VERSION_UNKNOWN)
130 /* this check is not really needed.
132 gnutls_assert ();
133 return GNUTLS_E_UNKNOWN_CIPHER_SUITE;
136 else
138 ver = version;
141 _gnutls_set_current_version (session, ver);
143 pos += 2;
146 /* Read uint16_t cipher_spec_length */
147 DECR_LEN (len, 2);
148 sizeOfSuites = _gnutls_read_uint16 (&data[pos]);
149 pos += 2;
151 /* read session id length */
152 DECR_LEN (len, 2);
153 session_id_len = _gnutls_read_uint16 (&data[pos]);
154 pos += 2;
156 if (session_id_len > TLS_MAX_SESSION_ID_SIZE)
158 gnutls_assert ();
159 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
162 /* read challenge length */
163 DECR_LEN (len, 2);
164 challenge = _gnutls_read_uint16 (&data[pos]);
165 pos += 2;
167 if (challenge < 16 || challenge > TLS_RANDOM_SIZE)
169 gnutls_assert ();
170 return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
173 /* find an appropriate cipher suite */
175 DECR_LEN (len, sizeOfSuites);
176 ret = _gnutls_handshake_select_v2_suite (session, &data[pos], sizeOfSuites);
178 pos += sizeOfSuites;
179 if (ret < 0)
181 gnutls_assert ();
182 return ret;
185 /* check if the credentials (username, public key etc.) are ok
187 if (_gnutls_get_kx_cred
188 (session,
189 _gnutls_cipher_suite_get_kx_algo (&session->security_parameters.
190 current_cipher_suite),
191 &err) == NULL && err != 0)
193 gnutls_assert ();
194 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
197 /* set the mod_auth_st to the appropriate struct
198 * according to the KX algorithm. This is needed since all the
199 * handshake functions are read from there;
201 session->internals.auth_struct =
202 _gnutls_kx_auth_struct (_gnutls_cipher_suite_get_kx_algo
203 (&session->security_parameters.
204 current_cipher_suite));
205 if (session->internals.auth_struct == NULL)
208 _gnutls_handshake_log
209 ("HSK[%x]: SSL 2.0 Hello: Cannot find the appropriate handler for the KX algorithm\n",
210 session);
212 gnutls_assert ();
213 return GNUTLS_E_INTERNAL_ERROR;
218 /* read random new values -skip session id for now */
219 DECR_LEN (len, session_id_len); /* skip session id for now */
220 memcpy (session_id, &data[pos], session_id_len);
221 pos += session_id_len;
223 DECR_LEN (len, challenge);
224 memset (rnd, 0, TLS_RANDOM_SIZE);
226 memcpy (&rnd[TLS_RANDOM_SIZE - challenge], &data[pos], challenge);
228 _gnutls_set_client_random (session, rnd);
230 /* generate server random value */
232 _gnutls_tls_create_random (rnd);
233 _gnutls_set_server_random (session, rnd);
235 session->security_parameters.timestamp = time (NULL);
238 /* RESUME SESSION */
240 DECR_LEN (len, session_id_len);
241 ret = _gnutls_server_restore_session (session, session_id, session_id_len);
243 if (ret == 0)
244 { /* resumed! */
245 /* get the new random values */
246 memcpy (session->internals.resumed_security_parameters.
247 server_random, session->security_parameters.server_random,
248 TLS_RANDOM_SIZE);
249 memcpy (session->internals.resumed_security_parameters.
250 client_random, session->security_parameters.client_random,
251 TLS_RANDOM_SIZE);
253 session->internals.resumed = RESUME_TRUE;
254 return 0;
256 else
258 _gnutls_generate_session_id (session->security_parameters.
259 session_id,
260 &session->security_parameters.
261 session_id_size);
262 session->internals.resumed = RESUME_FALSE;
265 session->internals.compression_method = GNUTLS_COMP_NULL;
267 return 0;