*** empty log message ***
[gnutls.git] / lib / gnutls_v2_compat.c
blob3f6ab174af6f6c9c6a49178cf2bf1ae7a9407ea6
1 /*
2 * Copyright (C) 2001 Nikos Mavroyanopoulos
4 * This file is part of GNUTLS.
6 * The GNUTLS library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "gnutls_int.h"
23 #include "gnutls_errors.h"
24 #include "gnutls_dh.h"
25 #include "debug.h"
26 #include "gnutls_algorithms.h"
27 #include "gnutls_compress.h"
28 #include "gnutls_cipher.h"
29 #include "gnutls_buffers.h"
30 #include "gnutls_kx.h"
31 #include "gnutls_handshake.h"
32 #include "gnutls_num.h"
33 #include "gnutls_hash_int.h"
34 #include "gnutls_db.h"
35 #include "gnutls_extensions.h"
36 #include "gnutls_random.h"
37 #include "gnutls_auth_int.h"
39 /* This selects the best supported ciphersuite from the ones provided */
40 static int _gnutls_handshake_select_v2_suite(GNUTLS_STATE state, char *data, int datalen)
42 int i, j, ret;
43 char* _data;
44 int _datalen;
46 _data = gnutls_malloc( datalen);
47 if (_data==NULL) {
48 gnutls_assert();
49 return GNUTLS_E_MEMORY_ERROR;
52 _gnutls_handshake_log( "HSK: Parsing a version 2.0 client hello.\n");
54 i = _datalen = 0;
55 for (j = 0; j < datalen; j += 3) {
56 if (data[j] == 0) {
57 memcpy( &_data[i], &data[j+1], 2);
58 i+=2;
59 _datalen+=2;
63 ret = _gnutls_server_select_suite( state, _data, _datalen);
64 gnutls_free(_data);
66 return ret;
71 /* Read a v2 client hello. Some browsers still use that beast!
72 * However they set their version to 3.0 or 3.1.
74 int _gnutls_read_client_hello_v2(GNUTLS_STATE state, opaque * data,
75 int datalen)
77 uint16 session_id_len = 0;
78 int pos = 0;
79 int ret = 0;
80 uint16 sizeOfSuites;
81 GNUTLS_Version version;
82 opaque random[TLS_RANDOM_SIZE];
83 int len = datalen;
84 int err;
85 uint16 challenge;
86 opaque session_id[TLS_MAX_SESSION_ID_SIZE];
87 GNUTLS_Version ver;
89 /* we only want to get here once - only in client hello */
90 state->gnutls_internals.v2_hello = 0;
92 DECR_LEN(len, 2);
94 _gnutls_handshake_log( "HSK: SSL 2.0 Hello: Client's version: %d.%d\n", data[pos],
95 data[pos + 1]);
97 set_adv_version( state, data[pos], data[pos+1]);
99 version = _gnutls_version_get(data[pos], data[pos + 1]);
101 /* if we do not support that version */
102 if (_gnutls_version_is_supported(state, version) == 0) {
103 ver = _gnutls_version_lowest( state);
104 } else {
105 ver = version;
108 if (ver==GNUTLS_VERSION_UNKNOWN || ver > version) {
109 gnutls_assert();
110 return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
113 _gnutls_set_current_version(state, ver);
115 pos += 2;
118 /* Read uint16 cipher_spec_length */
119 DECR_LEN(len, 2);
120 sizeOfSuites = _gnutls_read_uint16( &data[pos]);
121 pos += 2;
123 /* read session id length */
124 DECR_LEN(len, 2);
125 session_id_len = _gnutls_read_uint16( &data[pos]);
126 pos += 2;
128 if (session_id_len > TLS_MAX_SESSION_ID_SIZE) {
129 gnutls_assert();
130 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
133 /* read challenge length */
134 DECR_LEN(len, 2);
135 challenge = _gnutls_read_uint16( &data[pos]);
136 pos += 2;
138 if ( challenge < 16 || challenge > TLS_RANDOM_SIZE) {
139 gnutls_assert();
140 return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
143 /* find an appropriate cipher suite */
145 DECR_LEN(len, sizeOfSuites);
146 ret = _gnutls_handshake_select_v2_suite(state, &data[pos], sizeOfSuites);
148 pos += sizeOfSuites;
149 if (ret < 0) {
150 gnutls_assert();
151 return ret;
154 /* check if the credentials (username, public key etc. are ok)
156 if (_gnutls_get_kx_cred( state->gnutls_key, _gnutls_cipher_suite_get_kx_algo(state->security_parameters.current_cipher_suite), &err) == NULL && err != 0) {
157 gnutls_assert();
158 return GNUTLS_E_INSUFICIENT_CRED;
161 /* set the MOD_AUTH_STRUCT to the appropriate struct
162 * according to the KX algorithm. This is needed since all the
163 * handshake functions are read from there;
165 state->gnutls_internals.auth_struct =
166 _gnutls_kx_auth_struct(_gnutls_cipher_suite_get_kx_algo
167 (state->security_parameters.
168 current_cipher_suite));
169 if (state->gnutls_internals.auth_struct == NULL) {
171 _gnutls_handshake_log(
172 "HSK: SSL 2.0 Hello: Cannot find the appropriate handler for the KX algorithm\n");
174 gnutls_assert();
175 return GNUTLS_E_UNKNOWN_CIPHER_TYPE;
180 /* read random new values -skip session id for now */
181 DECR_LEN(len, session_id_len); /* skip session id for now */
182 memcpy( session_id, &data[pos], session_id_len);
183 pos+=session_id_len;
185 DECR_LEN(len, challenge);
186 memset( random, 0, TLS_RANDOM_SIZE);
188 memcpy( &random[TLS_RANDOM_SIZE-challenge], &data[pos], challenge);
190 _gnutls_set_client_random( state, random);
192 /* generate server random value */
194 _gnutls_create_random( random);
195 _gnutls_set_server_random( state, random);
197 state->security_parameters.timestamp = time(NULL);
200 /* RESUME SESSION */
202 DECR_LEN(len, session_id_len);
203 ret = _gnutls_server_restore_session(state, session_id, session_id_len);
205 if (ret == 0) { /* resumed! */
206 /* get the new random values */
207 memcpy(state->gnutls_internals.resumed_security_parameters.server_random,
208 state->security_parameters.server_random, TLS_RANDOM_SIZE);
209 memcpy(state->gnutls_internals.resumed_security_parameters.client_random,
210 state->security_parameters.client_random, TLS_RANDOM_SIZE);
212 state->gnutls_internals.resumed = RESUME_TRUE;
213 return 0;
214 } else {
215 _gnutls_generate_session_id(state->security_parameters.
216 session_id,
217 &state->security_parameters.
218 session_id_size);
219 state->gnutls_internals.resumed = RESUME_FALSE;
222 state->gnutls_internals.compression_method = GNUTLS_COMP_NULL;
224 return 0;