LCOV - code coverage report
Current view: top level - builds/gnutls/coverage/gnutls-git/lib/ext - server_name.c (source / functions) Hit Total Coverage
Test: GnuTLS-3.6.14 Code Coverage Lines: 117 127 92.1 %
Date: 2020-10-30 04:50:48 Functions: 6 6 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2002-2012 Free Software Foundation, Inc.
       3             :  * Copyright (C) 2017 Red Hat, Inc.
       4             :  *
       5             :  * Author: Nikos Mavrogiannopoulos
       6             :  *
       7             :  * This file is part of GnuTLS.
       8             :  *
       9             :  * The GnuTLS 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.
      13             :  *
      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.
      18             :  *
      19             :  * You should have received a copy of the GNU Lesser General Public License
      20             :  * along with this program.  If not, see <https://www.gnu.org/licenses/>
      21             :  *
      22             :  */
      23             : 
      24             : #include "gnutls_int.h"
      25             : #include "auth.h"
      26             : #include "errors.h"
      27             : #include "num.h"
      28             : #include "str.h"
      29             : #include <ext/server_name.h>
      30             : #include "hello_ext_lib.h"
      31             : 
      32             : static int _gnutls_server_name_recv_params(gnutls_session_t session,
      33             :                                            const uint8_t * data,
      34             :                                            size_t data_size);
      35             : static int _gnutls_server_name_send_params(gnutls_session_t session,
      36             :                                            gnutls_buffer_st * extdata);
      37             : 
      38             : int
      39             : _gnutls_server_name_set_raw(gnutls_session_t session,
      40             :                             gnutls_server_name_type_t type,
      41             :                             const void *name, size_t name_length);
      42             : 
      43             : const hello_ext_entry_st ext_mod_server_name = {
      44             :         .name = "Server Name Indication",
      45             :         .tls_id = 0,
      46             :         .gid = GNUTLS_EXTENSION_SERVER_NAME,
      47             :         .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_DTLS | GNUTLS_EXT_FLAG_CLIENT_HELLO |
      48             :                     GNUTLS_EXT_FLAG_EE | GNUTLS_EXT_FLAG_TLS12_SERVER_HELLO,
      49             :         .client_parse_point = GNUTLS_EXT_MANDATORY,
      50             :         .server_parse_point = GNUTLS_EXT_MANDATORY,
      51             :         .recv_func = _gnutls_server_name_recv_params,
      52             :         .send_func = _gnutls_server_name_send_params,
      53             :         .pack_func = _gnutls_hello_ext_default_pack,
      54             :         .unpack_func = _gnutls_hello_ext_default_unpack,
      55             :         .deinit_func = _gnutls_hello_ext_default_deinit,
      56             :         .cannot_be_overriden = 1
      57             : };
      58             : 
      59             : /*
      60             :  * In case of a server: if a NAME_DNS extension type is received then
      61             :  * it stores into the session the value of NAME_DNS. The server may
      62             :  * use gnutls_ext_get_server_name(), in order to access it.
      63             :  *
      64             :  * In case of a client: If a proper NAME_DNS extension type is found
      65             :  * in the session then it sends the extension to the peer.
      66             :  *
      67             :  */
      68             : static int
      69        2099 : _gnutls_server_name_recv_params(gnutls_session_t session,
      70             :                                 const uint8_t * data, size_t data_size)
      71             : {
      72        2099 :         const unsigned char *p;
      73        2099 :         uint16_t len, type;
      74        2099 :         gnutls_datum_t name;
      75             : 
      76        2099 :         if (session->security_parameters.entity == GNUTLS_SERVER) {
      77        2095 :                 DECR_LENGTH_RET(data_size, 2, GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
      78        2092 :                 len = _gnutls_read_uint16(data);
      79        2092 :                 if (len == 0)
      80           5 :                         return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
      81             : 
      82        2088 :                 if (len != data_size) {
      83           5 :                         gnutls_assert();
      84           5 :                         return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
      85             :                 }
      86             : 
      87        2083 :                 p = data + 2;
      88             : 
      89        2175 :                 while (data_size > 0) {
      90        2148 :                         DECR_LEN(data_size, 1);
      91        2148 :                         type = *p;
      92        2148 :                         p++;
      93             : 
      94        2148 :                         DECR_LEN(data_size, 2);
      95        2142 :                         len = _gnutls_read_uint16(p);
      96        2142 :                         p += 2;
      97             : 
      98        2142 :                         if (len == 0) {
      99           5 :                                 _gnutls_handshake_log
     100             :                                     ("HSK[%p]: Received server name size of zero\n",
     101             :                                      session);
     102           6 :                                 return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
     103             :                         }
     104             : 
     105        2137 :                         DECR_LEN(data_size, len);
     106             : 
     107        2128 :                         if (type == 0) { /* NAME_DNS */
     108        4072 :                                 if (!_gnutls_dnsname_is_valid((char*)p, len)) {
     109         530 :                                         _gnutls_handshake_log
     110             :                                             ("HSK[%p]: Server name is not acceptable: '%.*s'\n",
     111             :                                              session, (int) len, p);
     112         533 :                                         return gnutls_assert_val(GNUTLS_E_RECEIVED_DISALLOWED_NAME);
     113             :                                 }
     114             : 
     115        1506 :                                 name.data = (void*)p;
     116        1506 :                                 name.size = len;
     117             : 
     118        1506 :                                 _gnutls_hello_ext_unset_priv(session, GNUTLS_EXTENSION_SERVER_NAME);
     119        1506 :                                 return _gnutls_hello_ext_set_datum(session,
     120             :                                              GNUTLS_EXTENSION_SERVER_NAME,
     121             :                                              &name);
     122             :                         }
     123          92 :                         p += len;
     124             : 
     125             :                 }
     126             : 
     127             : 
     128             :         }
     129             : 
     130             :         return 0;
     131             : }
     132             : 
     133             : /* returns data_size or a negative number on failure
     134             :  */
     135             : static int
     136        4875 : _gnutls_server_name_send_params(gnutls_session_t session,
     137             :                                 gnutls_buffer_st * extdata)
     138             : {
     139        4875 :         int total_size = 0, ret;
     140        4875 :         gnutls_datum_t name;
     141             : 
     142        4875 :         ret =
     143        4875 :             _gnutls_hello_ext_get_datum(session, GNUTLS_EXTENSION_SERVER_NAME,
     144             :                                         &name);
     145        4875 :         if (ret < 0)
     146             :                 return 0;
     147             : 
     148             :         /* this function sends the client extension data (dnsname)
     149             :          */
     150        1516 :         if (session->security_parameters.entity == GNUTLS_CLIENT) {
     151         437 :                 if (name.size == 0)
     152             :                         return 0;
     153             : 
     154             :                 /* uint8_t + uint16_t + size
     155             :                  */
     156         437 :                 total_size = 2 + 1 + 2 + name.size;
     157             : 
     158             :                 /* UINT16: write total size of all names
     159             :                  */
     160         437 :                 ret =
     161         874 :                     _gnutls_buffer_append_prefix(extdata, 16,
     162         437 :                                                  total_size - 2);
     163         437 :                 if (ret < 0)
     164           0 :                         return gnutls_assert_val(ret);
     165             : 
     166             :                 /* UINT8: type of this extension
     167             :                  * UINT16: size of the first name
     168             :                  * LEN: the actual server name.
     169             :                  */
     170         437 :                 ret =
     171         437 :                     _gnutls_buffer_append_prefix(extdata, 8, 0);
     172         437 :                 if (ret < 0)
     173           0 :                         return gnutls_assert_val(ret);
     174             : 
     175         437 :                 _gnutls_debug_log("HSK[%p]: sent server name: '%.*s'\n", session, name.size, name.data);
     176             : 
     177         437 :                 ret =
     178         874 :                     _gnutls_buffer_append_data_prefix
     179             :                             (extdata, 16,
     180         437 :                              name.data, name.size);
     181         437 :                 if (ret < 0)
     182           0 :                         return gnutls_assert_val(ret);
     183             :         } else {
     184             :                 return 0;
     185             :         }
     186             : 
     187             :         return total_size;
     188             : }
     189             : 
     190             : /**
     191             :  * gnutls_server_name_get:
     192             :  * @session: is a #gnutls_session_t type.
     193             :  * @data: will hold the data
     194             :  * @data_length: will hold the data length. Must hold the maximum size of data.
     195             :  * @type: will hold the server name indicator type
     196             :  * @indx: is the index of the server_name
     197             :  *
     198             :  * This function will allow you to get the name indication (if any), a
     199             :  * client has sent.  The name indication may be any of the enumeration
     200             :  * gnutls_server_name_type_t.
     201             :  *
     202             :  * If @type is GNUTLS_NAME_DNS, then this function is to be used by
     203             :  * servers that support virtual hosting, and the data will be a null
     204             :  * terminated IDNA ACE string (prior to GnuTLS 3.4.0 it was a UTF-8 string).
     205             :  *
     206             :  * If @data has not enough size to hold the server name
     207             :  * GNUTLS_E_SHORT_MEMORY_BUFFER is returned, and @data_length will
     208             :  * hold the required size.
     209             :  *
     210             :  * @indx is used to retrieve more than one server names (if sent by
     211             :  * the client).  The first server name has an index of 0, the second 1
     212             :  * and so on.  If no name with the given index exists
     213             :  * GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned.
     214             :  *
     215             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, on UTF-8
     216             :  *  decoding error %GNUTLS_E_IDNA_ERROR is returned, otherwise a negative
     217             :  *  error code is returned.
     218             :  **/
     219             : int
     220       22859 : gnutls_server_name_get(gnutls_session_t session, void *data,
     221             :                        size_t * data_length,
     222             :                        unsigned int *type, unsigned int indx)
     223             : {
     224       22859 :         char *_data = data;
     225       22859 :         gnutls_datum_t name;
     226       22859 :         int ret;
     227             : 
     228       22859 :         if (session->security_parameters.entity == GNUTLS_CLIENT) {
     229         254 :                 gnutls_assert();
     230         254 :                 return GNUTLS_E_INVALID_REQUEST;
     231             :         }
     232             : 
     233       22605 :         if (indx != 0)
     234             :                 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
     235             : 
     236       22603 :         ret =
     237       22603 :             _gnutls_hello_ext_get_datum(session, GNUTLS_EXTENSION_SERVER_NAME, &name);
     238       22603 :         if (ret < 0) {
     239       20691 :                 gnutls_assert();
     240       20691 :                 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
     241             :         }
     242             : 
     243        1912 :         if (name.size == 0) {
     244             :                 return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
     245             :         }
     246             : 
     247        1912 :         *type = GNUTLS_NAME_DNS;
     248             : 
     249        1912 :         if (*data_length > name.size) { /* greater since we need one extra byte for the null */
     250        1847 :                 *data_length = name.size;
     251        1847 :                 memcpy(data, name.data, *data_length);
     252             : 
     253             :                 /* null terminate */
     254        1847 :                 _data[(*data_length)] = 0;
     255             : 
     256             :         } else {
     257          65 :                 *data_length = name.size + 1;
     258          65 :                 ret = GNUTLS_E_SHORT_MEMORY_BUFFER;
     259          65 :                 goto cleanup;
     260             :         }
     261             : 
     262        1847 :         ret = 0;
     263             :  cleanup:
     264             :         return ret;
     265             : }
     266             : 
     267             : /* This does not do any conversion not perform any check */
     268             : int
     269         445 : _gnutls_server_name_set_raw(gnutls_session_t session,
     270             :                             gnutls_server_name_type_t type,
     271             :                             const void *name, size_t name_length)
     272             : {
     273         445 :         int ret;
     274         445 :         gnutls_datum_t dname;
     275             : 
     276         445 :         if (name_length >= MAX_SERVER_NAME_SIZE) {
     277             :                 return GNUTLS_E_INVALID_REQUEST;
     278             :         }
     279             : 
     280         445 :         _gnutls_hello_ext_unset_priv(session, GNUTLS_EXTENSION_SERVER_NAME);
     281             : 
     282         445 :         dname.data = (void*)name;
     283         445 :         dname.size = name_length;
     284             : 
     285         445 :         ret = _gnutls_hello_ext_set_datum(session, GNUTLS_EXTENSION_SERVER_NAME, &dname);
     286         445 :         if (ret < 0)
     287           0 :                 return gnutls_assert_val(ret);
     288             : 
     289             :         return 0;
     290             : }
     291             : 
     292             : /**
     293             :  * gnutls_server_name_set:
     294             :  * @session: is a #gnutls_session_t type.
     295             :  * @type: specifies the indicator type
     296             :  * @name: is a string that contains the server name.
     297             :  * @name_length: holds the length of name excluding the terminating null byte
     298             :  *
     299             :  * This function is to be used by clients that want to inform (via a
     300             :  * TLS extension mechanism) the server of the name they connected to.
     301             :  * This should be used by clients that connect to servers that do
     302             :  * virtual hosting.
     303             :  *
     304             :  * The value of @name depends on the @type type.  In case of
     305             :  * %GNUTLS_NAME_DNS, a UTF-8 null-terminated domain name string,
     306             :  * without the trailing dot, is expected.
     307             :  *
     308             :  * IPv4 or IPv6 addresses are not permitted to be set by this function.
     309             :  * If the function is called with a name of @name_length zero it will clear
     310             :  * all server names set.
     311             :  *
     312             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
     313             :  *   otherwise a negative error code is returned.
     314             :  **/
     315             : int
     316         447 : gnutls_server_name_set(gnutls_session_t session,
     317             :                        gnutls_server_name_type_t type,
     318             :                        const void *name, size_t name_length)
     319             : {
     320         447 :         int ret;
     321         447 :         gnutls_datum_t idn_name = {NULL,0};
     322             : 
     323         447 :         if (session->security_parameters.entity == GNUTLS_SERVER) {
     324           0 :                 gnutls_assert();
     325           0 :                 return GNUTLS_E_INVALID_REQUEST;
     326             :         }
     327             : 
     328         447 :         if (name_length == 0) { /* unset extension */
     329           5 :                 _gnutls_hello_ext_unset_priv(session, GNUTLS_EXTENSION_SERVER_NAME);
     330           5 :                 return 0;
     331             :         }
     332             : 
     333         442 :         ret = gnutls_idna_map(name, name_length, &idn_name, 0);
     334         442 :         if (ret < 0) {
     335           0 :                  _gnutls_debug_log("unable to convert name %s to IDNA2008 format\n", (char*)name);
     336           0 :                  return ret;
     337             :         }
     338             : 
     339         442 :         name = idn_name.data;
     340         442 :         name_length = idn_name.size;
     341             : 
     342         442 :         ret = _gnutls_server_name_set_raw(session, type, name, name_length);
     343         442 :         gnutls_free(idn_name.data);
     344             : 
     345         442 :         return ret;
     346             : }
     347             : 
     348         813 : unsigned _gnutls_server_name_matches_resumed(gnutls_session_t session)
     349             : {
     350         813 :         gnutls_datum_t name1, name2;
     351         813 :         int ret;
     352             : 
     353         813 :         ret =
     354         813 :             _gnutls_hello_ext_get_datum(session,
     355             :                                         GNUTLS_EXTENSION_SERVER_NAME,
     356             :                                         &name1);
     357         813 :         if (ret < 0) { /* no server name in this session */
     358         747 :                 name1.data = NULL;
     359         747 :                 name1.size = 0;
     360             :         }
     361             : 
     362         813 :         ret =
     363         813 :             _gnutls_hello_ext_get_resumed_datum(session,
     364             :                                                 GNUTLS_EXTENSION_SERVER_NAME,
     365             :                                                 &name2);
     366         813 :         if (ret < 0) { /* no server name in this session */
     367         747 :                 name2.data = NULL;
     368         747 :                 name2.size = 0;
     369             :         }
     370             : 
     371         813 :         if (name1.data == NULL || name2.data == NULL) {
     372         747 :                 if (name1.data == name2.data)
     373             :                         return 1;
     374             :                 else
     375           0 :                         return 0;
     376             :         }
     377             : 
     378          66 :         if (name1.size != name2.size)
     379             :                 return 0;
     380             : 
     381          24 :         if (memcmp(name1.data, name2.data, name1.size) != 0)
     382           0 :                 return 0;
     383             : 
     384             :         return 1;
     385             : }

Generated by: LCOV version 1.14