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,
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 version
;
100 opaque rnd
[TLS_RANDOM_SIZE
];
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;
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.
133 return GNUTLS_E_UNKNOWN_CIPHER_SUITE
;
141 _gnutls_set_current_version (session
, ver
);
146 /* Read uint16_t cipher_spec_length */
148 sizeOfSuites
= _gnutls_read_uint16 (&data
[pos
]);
151 /* read session id length */
153 session_id_len
= _gnutls_read_uint16 (&data
[pos
]);
156 if (session_id_len
> TLS_MAX_SESSION_ID_SIZE
)
159 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH
;
162 /* read challenge length */
164 challenge
= _gnutls_read_uint16 (&data
[pos
]);
167 if (challenge
< 16 || challenge
> TLS_RANDOM_SIZE
)
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
);
185 /* check if the credentials (username, public key etc.) are ok
187 if (_gnutls_get_kx_cred
189 _gnutls_cipher_suite_get_kx_algo (&session
->security_parameters
.
190 current_cipher_suite
),
191 &err
) == NULL
&& err
!= 0)
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",
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
);
240 DECR_LEN (len
, session_id_len
);
241 ret
= _gnutls_server_restore_session (session
, session_id
, session_id_len
);
245 /* get the new random values */
246 memcpy (session
->internals
.resumed_security_parameters
.
247 server_random
, session
->security_parameters
.server_random
,
249 memcpy (session
->internals
.resumed_security_parameters
.
250 client_random
, session
->security_parameters
.client_random
,
253 session
->internals
.resumed
= RESUME_TRUE
;
258 _gnutls_generate_session_id (session
->security_parameters
.
260 &session
->security_parameters
.
262 session
->internals
.resumed
= RESUME_FALSE
;
265 session
->internals
.compression_method
= GNUTLS_COMP_NULL
;