2 * Copyright (C) 2001, 2004, 2005, 2006 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 /* Functions to parse the SSLv2.0 hello message.
28 #include "gnutls_int.h"
29 #include "gnutls_errors.h"
30 #include "gnutls_dh.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 */
46 _gnutls_handshake_select_v2_suite (gnutls_session_t session
,
47 opaque
* data
, int datalen
)
53 _gnutls_handshake_log ("HSK[%x]: Parsing a version 2.0 client hello.\n",
56 _data
= gnutls_malloc (datalen
);
60 return GNUTLS_E_MEMORY_ERROR
;
66 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH
;
70 for (j
= 0; j
< datalen
; j
+= 3)
74 memcpy (&_data
[i
], &data
[j
+ 1], 2);
80 ret
= _gnutls_server_select_suite (session
, _data
, _datalen
);
88 /* Read a v2 client hello. Some browsers still use that beast!
89 * However they set their version to 3.0 or 3.1.
92 _gnutls_read_client_hello_v2 (gnutls_session_t session
, opaque
* data
,
95 uint16_t session_id_len
= 0;
98 uint16_t sizeOfSuites
;
99 gnutls_protocol_t adv_version
;
100 opaque rnd
[TLS_RANDOM_SIZE
];
104 opaque session_id
[TLS_MAX_SESSION_ID_SIZE
];
106 /* we only want to get here once - only in client hello */
107 session
->internals
.v2_hello
= 0;
111 _gnutls_handshake_log
112 ("HSK[%x]: SSL 2.0 Hello: Client's version: %d.%d\n", session
,
113 data
[pos
], data
[pos
+ 1]);
115 set_adv_version (session
, data
[pos
], data
[pos
+ 1]);
117 adv_version
= _gnutls_version_get (data
[pos
], data
[pos
+ 1]);
119 ret
= _gnutls_negotiate_version( session
, adv_version
);
128 /* Read uint16_t cipher_spec_length */
130 sizeOfSuites
= _gnutls_read_uint16 (&data
[pos
]);
133 /* read session id length */
135 session_id_len
= _gnutls_read_uint16 (&data
[pos
]);
138 if (session_id_len
> TLS_MAX_SESSION_ID_SIZE
)
141 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH
;
144 /* read challenge length */
146 challenge
= _gnutls_read_uint16 (&data
[pos
]);
149 if (challenge
< 16 || challenge
> TLS_RANDOM_SIZE
)
152 return GNUTLS_E_UNSUPPORTED_VERSION_PACKET
;
155 /* call the user hello callback
157 ret
= _gnutls_user_hello_func( session
, adv_version
);
164 /* find an appropriate cipher suite */
166 DECR_LEN (len
, sizeOfSuites
);
167 ret
= _gnutls_handshake_select_v2_suite (session
, &data
[pos
], sizeOfSuites
);
176 /* check if the credentials (username, public key etc.) are ok
178 if (_gnutls_get_kx_cred
180 _gnutls_cipher_suite_get_kx_algo (&session
->security_parameters
.
181 current_cipher_suite
),
182 &err
) == NULL
&& err
!= 0)
185 return GNUTLS_E_INSUFFICIENT_CREDENTIALS
;
188 /* set the mod_auth_st to the appropriate struct
189 * according to the KX algorithm. This is needed since all the
190 * handshake functions are read from there;
192 session
->internals
.auth_struct
=
193 _gnutls_kx_auth_struct (_gnutls_cipher_suite_get_kx_algo
194 (&session
->security_parameters
.
195 current_cipher_suite
));
196 if (session
->internals
.auth_struct
== NULL
)
199 _gnutls_handshake_log
200 ("HSK[%x]: SSL 2.0 Hello: Cannot find the appropriate handler for the KX algorithm\n",
204 return GNUTLS_E_INTERNAL_ERROR
;
209 /* read random new values -skip session id for now */
210 DECR_LEN (len
, session_id_len
); /* skip session id for now */
211 memcpy (session_id
, &data
[pos
], session_id_len
);
212 pos
+= session_id_len
;
214 DECR_LEN (len
, challenge
);
215 memset (rnd
, 0, TLS_RANDOM_SIZE
);
217 memcpy (&rnd
[TLS_RANDOM_SIZE
- challenge
], &data
[pos
], challenge
);
219 _gnutls_set_client_random (session
, rnd
);
221 /* generate server random value */
223 _gnutls_tls_create_random (rnd
);
224 _gnutls_set_server_random (session
, rnd
);
226 session
->security_parameters
.timestamp
= time (NULL
);
231 DECR_LEN (len
, session_id_len
);
232 ret
= _gnutls_server_restore_session (session
, session_id
, session_id_len
);
236 /* get the new random values */
237 memcpy (session
->internals
.resumed_security_parameters
.
238 server_random
, session
->security_parameters
.server_random
,
240 memcpy (session
->internals
.resumed_security_parameters
.
241 client_random
, session
->security_parameters
.client_random
,
244 session
->internals
.resumed
= RESUME_TRUE
;
249 _gnutls_generate_session_id (session
->security_parameters
.
251 &session
->security_parameters
.
253 session
->internals
.resumed
= RESUME_FALSE
;
256 session
->internals
.compression_method
= GNUTLS_COMP_NULL
;