LCOV - code coverage report
Current view: top level - builds/gnutls/coverage/gnutls-git/lib - sslv2_compat.c (source / functions) Hit Total Coverage
Test: GnuTLS-3.6.14 Code Coverage Lines: 90 109 82.6 %
Date: 2020-10-30 04:50:48 Functions: 2 2 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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         676 : _gnutls_handshake_select_v2_suite(gnutls_session_t session,
      47             :                                   uint8_t * data, unsigned int datalen)
      48             : {
      49         676 :         unsigned int i, j;
      50         676 :         int ret;
      51         676 :         uint8_t *_data;
      52         676 :         int _datalen;
      53             : 
      54         676 :         _gnutls_handshake_log
      55             :             ("HSK[%p]: Parsing a version 2.0 client hello.\n", session);
      56             : 
      57         676 :         if (datalen % 3 != 0) {
      58           3 :                 gnutls_assert();
      59           3 :                 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
      60             :         }
      61             : 
      62         673 :         _data = gnutls_malloc(datalen);
      63         673 :         if (_data == NULL) {
      64           0 :                 gnutls_assert();
      65           0 :                 return GNUTLS_E_MEMORY_ERROR;
      66             :         }
      67             : 
      68             :         i = _datalen = 0;
      69        7494 :         for (j = 0; j < datalen; j += 3) {
      70        6821 :                 if (data[j] == 0) {
      71        4923 :                         memcpy(&_data[i], &data[j + 1], 2);
      72        4923 :                         i += 2;
      73        4923 :                         _datalen += 2;
      74             :                 }
      75             :         }
      76             : 
      77         673 :         ret = _gnutls_server_select_suite(session, _data, _datalen, 0);
      78         673 :         gnutls_free(_data);
      79             : 
      80         673 :         return ret;
      81             : 
      82             : }
      83             : 
      84             : 
      85             : /* Read a v2 client hello. Some browsers still use that beast!
      86             :  * However they set their version to 3.0 or 3.1.
      87             :  */
      88             : int
      89         735 : _gnutls_read_client_hello_v2(gnutls_session_t session, uint8_t * data,
      90             :                              unsigned int len)
      91             : {
      92         735 :         uint16_t session_id_len = 0;
      93         735 :         int pos = 0;
      94         735 :         int ret = 0, sret = 0;
      95         735 :         uint16_t sizeOfSuites;
      96         735 :         uint8_t rnd[GNUTLS_RANDOM_SIZE], major, minor;
      97         735 :         int neg_version;
      98         735 :         const version_entry_st *vers;
      99         735 :         uint16_t challenge;
     100         735 :         uint8_t session_id[GNUTLS_MAX_SESSION_ID_SIZE];
     101             : 
     102         735 :         DECR_LEN(len, 2);
     103             : 
     104         735 :         _gnutls_handshake_log
     105             :             ("HSK[%p]: SSL 2.0 Hello: Client's version: %d.%d\n", session,
     106             :              data[pos], data[pos + 1]);
     107             : 
     108         735 :         major = data[pos];
     109         735 :         minor = data[pos + 1];
     110         735 :         set_adv_version(session, major, minor);
     111             : 
     112         735 :         ret = _gnutls_negotiate_version(session, major, minor, 0);
     113         735 :         if (ret < 0) {
     114          39 :                 gnutls_assert();
     115          39 :                 return ret;
     116             :         }
     117             : 
     118         696 :         vers = get_version(session);
     119         696 :         if (vers == NULL)
     120           0 :                 return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_VERSION_PACKET);
     121             : 
     122         696 :         neg_version = vers->id;
     123             : 
     124         696 :         pos += 2;
     125             : 
     126             :         /* Read uint16_t cipher_spec_length */
     127         696 :         DECR_LEN(len, 2);
     128         693 :         sizeOfSuites = _gnutls_read_uint16(&data[pos]);
     129         693 :         pos += 2;
     130             : 
     131             :         /* read session id length */
     132         693 :         DECR_LEN(len, 2);
     133         689 :         session_id_len = _gnutls_read_uint16(&data[pos]);
     134         689 :         pos += 2;
     135             : 
     136         689 :         if (session_id_len > GNUTLS_MAX_SESSION_ID_SIZE) {
     137           3 :                 gnutls_assert();
     138           3 :                 return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
     139             :         }
     140             : 
     141             :         /* read challenge length */
     142         686 :         DECR_LEN(len, 2);
     143         683 :         challenge = _gnutls_read_uint16(&data[pos]);
     144         683 :         pos += 2;
     145             : 
     146         683 :         if (challenge < 16 || challenge > GNUTLS_RANDOM_SIZE) {
     147           4 :                 gnutls_assert();
     148           4 :                 return GNUTLS_E_UNSUPPORTED_VERSION_PACKET;
     149             :         }
     150             : 
     151             :         /* call the user hello callback
     152             :          */
     153         679 :         ret = _gnutls_user_hello_func(session, major, minor);
     154         679 :         if (ret < 0) {
     155           0 :                 if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) {
     156             :                         sret = GNUTLS_E_INT_RET_0;
     157             :                 } else {
     158           0 :                         gnutls_assert();
     159           0 :                         return ret;
     160             :                 }
     161             :         }
     162             : 
     163             :         /* find an appropriate cipher suite */
     164             : 
     165         679 :         DECR_LEN(len, sizeOfSuites);
     166         676 :         ret =
     167         676 :             _gnutls_handshake_select_v2_suite(session, &data[pos],
     168             :                                               sizeOfSuites);
     169             : 
     170         676 :         pos += sizeOfSuites;
     171         676 :         if (ret < 0) {
     172         146 :                 gnutls_assert();
     173         146 :                 return ret;
     174             :         }
     175             : 
     176             :         /* check if the credentials (username, public key etc.) are ok
     177             :          */
     178         530 :         if (_gnutls_get_kx_cred
     179             :             (session,
     180         530 :              session->security_parameters.cs->kx_algorithm) == NULL) {
     181           0 :                 gnutls_assert();
     182           0 :                 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
     183             :         }
     184             : 
     185             :         /* set the mod_auth_st to the appropriate struct
     186             :          * according to the KX algorithm. This is needed since all the
     187             :          * handshake functions are read from there;
     188             :          */
     189        1060 :         session->internals.auth_struct =
     190         530 :             _gnutls_kx_auth_struct(session->security_parameters.
     191             :                                     cs->kx_algorithm);
     192         530 :         if (session->internals.auth_struct == NULL) {
     193             : 
     194           0 :                 _gnutls_handshake_log
     195             :                     ("HSK[%p]: SSL 2.0 Hello: Cannot find the appropriate handler for the KX algorithm\n",
     196             :                      session);
     197             : 
     198           0 :                 gnutls_assert();
     199           0 :                 return GNUTLS_E_INTERNAL_ERROR;
     200             :         }
     201             : 
     202             :         /* read random new values -skip session id for now */
     203         530 :         DECR_LEN(len, session_id_len);  /* skip session id for now */
     204         527 :         memcpy(session_id, &data[pos], session_id_len);
     205         527 :         pos += session_id_len;
     206             : 
     207         527 :         DECR_LEN(len, challenge);
     208         521 :         memset(rnd, 0, GNUTLS_RANDOM_SIZE);
     209             : 
     210         521 :         memcpy(&rnd[GNUTLS_RANDOM_SIZE - challenge], &data[pos],
     211             :                challenge);
     212             : 
     213         521 :         _gnutls_set_client_random(session, rnd);
     214             : 
     215             :         /* generate server random value */
     216         521 :         ret = _gnutls_gen_server_random(session, neg_version);
     217         521 :         if (ret < 0)
     218           0 :                 return gnutls_assert_val(ret);
     219             : 
     220         521 :         session->security_parameters.timestamp = gnutls_time(NULL);
     221             : 
     222             : 
     223             :         /* RESUME SESSION */
     224             : 
     225         521 :         DECR_LEN(len, session_id_len);
     226         518 :         ret =
     227         518 :             _gnutls_server_restore_session(session, session_id,
     228             :                                            session_id_len);
     229             : 
     230         518 :         if (ret == 0) {         /* resumed! */
     231             :                 /* get the new random values */
     232           0 :                 memcpy(session->internals.resumed_security_parameters.
     233             :                        server_random,
     234           0 :                        session->security_parameters.server_random,
     235             :                        GNUTLS_RANDOM_SIZE);
     236           0 :                 memcpy(session->internals.resumed_security_parameters.
     237             :                        client_random,
     238           0 :                        session->security_parameters.client_random,
     239             :                        GNUTLS_RANDOM_SIZE);
     240             : 
     241           0 :                 session->internals.resumed = RESUME_TRUE;
     242           0 :                 return 0;
     243             :         } else {
     244        1036 :                 ret = _gnutls_generate_session_id(
     245         518 :                         session->security_parameters.session_id,
     246             :                         &session->security_parameters.session_id_size);
     247         518 :                 if (ret < 0)
     248           0 :                         return gnutls_assert_val(ret);
     249             : 
     250         518 :                 session->internals.resumed = RESUME_FALSE;
     251             :         }
     252             : 
     253         518 :         return sret;
     254             : }
     255             : #endif

Generated by: LCOV version 1.14