Coverage Report

Created: 2023-03-26 07:33

/src/gnutls/lib/sslv2_compat.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2001-2012 Free Software Foundation, Inc.
3
 *
4
 * Author: Nikos Mavrogiannopoulos
5
 *
6
 * This file is part of GnuTLS.
7
 *
8
 * The GnuTLS 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.
12
 *
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.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
20
 *
21
 */
22
23
/* Functions to parse the SSLv2.0 hello message.
24
 */
25
26
#include "gnutls_int.h"
27
#include "errors.h"
28
#include "dh.h"
29
#include "debug.h"
30
#include "algorithms.h"
31
#include "cipher.h"
32
#include "buffers.h"
33
#include "kx.h"
34
#include "handshake.h"
35
#include "num.h"
36
#include "hash_int.h"
37
#include "db.h"
38
#include "hello_ext.h"
39
#include "auth.h"
40
#include "sslv2_compat.h"
41
#include "constate.h"
42
43
#ifdef ENABLE_SSL2
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
          uint8_t * data, unsigned int datalen)
48
0
{
49
0
  unsigned int i, j;
50
0
  int ret;
51
0
  uint8_t *_data;
52
0
  int _datalen;
53
54
0
  _gnutls_handshake_log
55
0
      ("HSK[%p]: Parsing a version 2.0 client hello.\n", session);
56
57
0
  if (datalen % 3 != 0) {
58
0
    gnutls_assert();
59
0
    return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
60
0
  }
61
62
0
  _data = gnutls_malloc(datalen);
63
0
  if (_data == NULL) {
64
0
    gnutls_assert();
65
0
    return GNUTLS_E_MEMORY_ERROR;
66
0
  }
67
68
0
  i = _datalen = 0;
69
0
  for (j = 0; j < datalen; j += 3) {
70
0
    if (data[j] == 0) {
71
0
      memcpy(&_data[i], &data[j + 1], 2);
72
0
      i += 2;
73
0
      _datalen += 2;
74
0
    }
75
0
  }
76
77
0
  ret = _gnutls_server_select_suite(session, _data, _datalen, 0);
78
0
  gnutls_free(_data);
79
80
0
  return ret;
81
82
0
}
83
84
/* Read a v2 client hello. Some browsers still use that beast!
85
 * However they set their version to 3.0 or 3.1.
86
 */
87
int
88
_gnutls_read_client_hello_v2(gnutls_session_t session, uint8_t * data,
89
           unsigned int len)
90
0
{
91
0
  uint16_t session_id_len = 0;
92
0
  int pos = 0;
93
0
  int ret = 0, sret = 0;
94
0
  uint16_t sizeOfSuites;
95
0
  uint8_t rnd[GNUTLS_RANDOM_SIZE], major, minor;
96
0
  int neg_version;
97
0
  const version_entry_st *vers;
98
0
  uint16_t challenge;
99
0
  uint8_t session_id[GNUTLS_MAX_SESSION_ID_SIZE];
100
101
0
  DECR_LEN(len, 2);
102
103
0
  _gnutls_handshake_log
104
0
      ("HSK[%p]: SSL 2.0 Hello: Client's version: %d.%d\n", session,
105
0
       data[pos], data[pos + 1]);
106
107
0
  major = data[pos];
108
0
  minor = data[pos + 1];
109
0
  set_adv_version(session, major, minor);
110
111
0
  ret = _gnutls_negotiate_version(session, major, minor, 0);
112
0
  if (ret < 0) {
113
0
    gnutls_assert();
114
0
    return ret;
115
0
  }
116
117
0
  vers = get_version(session);
118
0
  if (vers == NULL)
119
0
    return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
120
121
0
  neg_version = vers->id;
122
123
0
  pos += 2;
124
125
  /* Read uint16_t cipher_spec_length */
126
0
  DECR_LEN(len, 2);
127
0
  sizeOfSuites = _gnutls_read_uint16(&data[pos]);
128
0
  pos += 2;
129
130
  /* read session id length */
131
0
  DECR_LEN(len, 2);
132
0
  session_id_len = _gnutls_read_uint16(&data[pos]);
133
0
  pos += 2;
134
135
0
  if (session_id_len > GNUTLS_MAX_SESSION_ID_SIZE) {
136
0
    gnutls_assert();
137
0
    return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
138
0
  }
139
140
  /* read challenge length */
141
0
  DECR_LEN(len, 2);
142
0
  challenge = _gnutls_read_uint16(&data[pos]);
143
0
  pos += 2;
144
145
0
  if (challenge < 16 || challenge > GNUTLS_RANDOM_SIZE) {
146
0
    gnutls_assert();
147
0
    return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
148
0
  }
149
150
  /* call the user hello callback
151
   */
152
0
  ret = _gnutls_user_hello_func(session, major, minor);
153
0
  if (ret < 0) {
154
0
    if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) {
155
0
      sret = GNUTLS_E_INT_RET_0;
156
0
    } else {
157
0
      gnutls_assert();
158
0
      return ret;
159
0
    }
160
0
  }
161
162
  /* find an appropriate cipher suite */
163
164
0
  DECR_LEN(len, sizeOfSuites);
165
0
  ret =
166
0
      _gnutls_handshake_select_v2_suite(session, &data[pos],
167
0
                sizeOfSuites);
168
169
0
  pos += sizeOfSuites;
170
0
  if (ret < 0) {
171
0
    gnutls_assert();
172
0
    return ret;
173
0
  }
174
175
  /* check if the credentials (username, public key etc.) are ok
176
   */
177
0
  if (_gnutls_get_kx_cred
178
0
      (session, session->security_parameters.cs->kx_algorithm) == NULL) {
179
0
    gnutls_assert();
180
0
    return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
181
0
  }
182
183
  /* set the mod_auth_st to the appropriate struct
184
   * according to the KX algorithm. This is needed since all the
185
   * handshake functions are read from there;
186
   */
187
0
  session->internals.auth_struct =
188
0
      _gnutls_kx_auth_struct(session->security_parameters.
189
0
           cs->kx_algorithm);
190
0
  if (session->internals.auth_struct == NULL) {
191
192
0
    _gnutls_handshake_log
193
0
        ("HSK[%p]: SSL 2.0 Hello: Cannot find the appropriate handler for the KX algorithm\n",
194
0
         session);
195
196
0
    gnutls_assert();
197
0
    return GNUTLS_E_INTERNAL_ERROR;
198
0
  }
199
200
  /* read random new values -skip session id for now */
201
0
  DECR_LEN(len, session_id_len); /* skip session id for now */
202
0
  memcpy(session_id, &data[pos], session_id_len);
203
0
  pos += session_id_len;
204
205
0
  DECR_LEN(len, challenge);
206
0
  memset(rnd, 0, GNUTLS_RANDOM_SIZE);
207
208
0
  memcpy(&rnd[GNUTLS_RANDOM_SIZE - challenge], &data[pos], challenge);
209
210
0
  _gnutls_set_client_random(session, rnd);
211
212
  /* generate server random value */
213
0
  ret = _gnutls_gen_server_random(session, neg_version);
214
0
  if (ret < 0)
215
0
    return gnutls_assert_val(ret);
216
217
0
  session->security_parameters.timestamp = gnutls_time(NULL);
218
219
  /* RESUME SESSION */
220
221
0
  DECR_LEN(len, session_id_len);
222
0
  ret =
223
0
      _gnutls_server_restore_session(session, session_id, session_id_len);
224
225
0
  if (ret == 0) {   /* resumed! */
226
    /* get the new random values */
227
0
    memcpy(session->internals.resumed_security_parameters.
228
0
           server_random,
229
0
           session->security_parameters.server_random,
230
0
           GNUTLS_RANDOM_SIZE);
231
0
    memcpy(session->internals.resumed_security_parameters.
232
0
           client_random,
233
0
           session->security_parameters.client_random,
234
0
           GNUTLS_RANDOM_SIZE);
235
236
0
    session->internals.resumed = true;
237
0
    return 0;
238
0
  } else {
239
0
    ret =
240
0
        _gnutls_generate_session_id(session->
241
0
            security_parameters.session_id,
242
0
            &session->
243
0
            security_parameters.session_id_size);
244
0
    if (ret < 0)
245
0
      return gnutls_assert_val(ret);
246
247
0
    session->internals.resumed = false;
248
0
  }
249
250
0
  return sret;
251
0
}
252
#endif