2 * Copyright (C) 2001, 2004, 2005, 2006, 2008, 2010 Free Software
5 * Author: Nikos Mavrogiannopoulos
7 * This file is part of GNUTLS.
9 * The GNUTLS library 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.
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.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
26 /* Functions to parse the SSLv2.0 hello message.
29 #include "gnutls_int.h"
30 #include "gnutls_errors.h"
31 #include "gnutls_dh.h"
33 #include "gnutls_algorithms.h"
34 #include "gnutls_compress.h"
35 #include "gnutls_cipher.h"
36 #include "gnutls_buffers.h"
37 #include "gnutls_kx.h"
38 #include "gnutls_handshake.h"
39 #include "gnutls_num.h"
40 #include "gnutls_hash_int.h"
41 #include "gnutls_db.h"
42 #include "gnutls_extensions.h"
43 #include "gnutls_auth.h"
44 #include "gnutls_v2_compat.h"
46 /* This selects the best supported ciphersuite from the ones provided */
48 _gnutls_handshake_select_v2_suite (gnutls_session_t session
,
49 opaque
* data
, int datalen
)
55 _gnutls_handshake_log ("HSK[%p]: Parsing a version 2.0 client hello.\n",
58 _data
= gnutls_malloc (datalen
);
62 return GNUTLS_E_MEMORY_ERROR
;
68 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH
;
72 for (j
= 0; j
< datalen
; j
+= 3)
76 memcpy (&_data
[i
], &data
[j
+ 1], 2);
82 ret
= _gnutls_server_select_suite (session
, _data
, _datalen
);
90 /* Read a v2 client hello. Some browsers still use that beast!
91 * However they set their version to 3.0 or 3.1.
94 _gnutls_read_client_hello_v2 (gnutls_session_t session
, opaque
* data
,
97 uint16_t session_id_len
= 0;
100 uint16_t sizeOfSuites
;
101 gnutls_protocol_t adv_version
;
102 opaque rnd
[GNUTLS_RANDOM_SIZE
];
106 opaque session_id
[TLS_MAX_SESSION_ID_SIZE
];
108 /* we only want to get here once - only in client hello */
109 session
->internals
.v2_hello
= 0;
113 _gnutls_handshake_log
114 ("HSK[%p]: SSL 2.0 Hello: Client's version: %d.%d\n", session
,
115 data
[pos
], data
[pos
+ 1]);
117 set_adv_version (session
, data
[pos
], data
[pos
+ 1]);
119 adv_version
= _gnutls_version_get (data
[pos
], data
[pos
+ 1]);
121 ret
= _gnutls_negotiate_version (session
, adv_version
);
130 /* Read uint16_t cipher_spec_length */
132 sizeOfSuites
= _gnutls_read_uint16 (&data
[pos
]);
135 /* read session id length */
137 session_id_len
= _gnutls_read_uint16 (&data
[pos
]);
140 if (session_id_len
> TLS_MAX_SESSION_ID_SIZE
)
143 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH
;
146 /* read challenge length */
148 challenge
= _gnutls_read_uint16 (&data
[pos
]);
151 if (challenge
< 16 || challenge
> GNUTLS_RANDOM_SIZE
)
154 return GNUTLS_E_UNSUPPORTED_VERSION_PACKET
;
157 /* call the user hello callback
159 ret
= _gnutls_user_hello_func (session
, adv_version
);
166 /* find an appropriate cipher suite */
168 DECR_LEN (len
, sizeOfSuites
);
169 ret
= _gnutls_handshake_select_v2_suite (session
, &data
[pos
], sizeOfSuites
);
178 /* check if the credentials (username, public key etc.) are ok
180 if (_gnutls_get_kx_cred
182 _gnutls_cipher_suite_get_kx_algo (&session
->security_parameters
.
183 current_cipher_suite
), &err
) == NULL
187 return GNUTLS_E_INSUFFICIENT_CREDENTIALS
;
190 /* set the mod_auth_st to the appropriate struct
191 * according to the KX algorithm. This is needed since all the
192 * handshake functions are read from there;
194 session
->internals
.auth_struct
=
195 _gnutls_kx_auth_struct (_gnutls_cipher_suite_get_kx_algo
196 (&session
->security_parameters
.
197 current_cipher_suite
));
198 if (session
->internals
.auth_struct
== NULL
)
201 _gnutls_handshake_log
202 ("HSK[%p]: SSL 2.0 Hello: Cannot find the appropriate handler for the KX algorithm\n",
206 return GNUTLS_E_INTERNAL_ERROR
;
211 /* read random new values -skip session id for now */
212 DECR_LEN (len
, session_id_len
); /* skip session id for now */
213 memcpy (session_id
, &data
[pos
], session_id_len
);
214 pos
+= session_id_len
;
216 DECR_LEN (len
, challenge
);
217 memset (rnd
, 0, GNUTLS_RANDOM_SIZE
);
219 memcpy (&rnd
[GNUTLS_RANDOM_SIZE
- challenge
], &data
[pos
], challenge
);
221 _gnutls_set_client_random (session
, rnd
);
223 /* generate server random value */
225 _gnutls_tls_create_random (rnd
);
226 _gnutls_set_server_random (session
, rnd
);
228 session
->security_parameters
.timestamp
= time (NULL
);
233 DECR_LEN (len
, session_id_len
);
234 ret
= _gnutls_server_restore_session (session
, session_id
, session_id_len
);
238 /* get the new random values */
239 memcpy (session
->internals
.resumed_security_parameters
.server_random
,
240 session
->security_parameters
.server_random
, GNUTLS_RANDOM_SIZE
);
241 memcpy (session
->internals
.resumed_security_parameters
.client_random
,
242 session
->security_parameters
.client_random
, GNUTLS_RANDOM_SIZE
);
244 session
->internals
.resumed
= RESUME_TRUE
;
249 _gnutls_generate_session_id (session
->security_parameters
.session_id
,
250 &session
->security_parameters
.
252 session
->internals
.resumed
= RESUME_FALSE
;
255 session
->internals
.compression_method
= GNUTLS_COMP_NULL
;