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

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2001-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 "errors.h"
      26             : #include "auth.h"
      27             : #include "auth.h"
      28             : #include "algorithms.h"
      29             : #include <auth/cert.h>
      30             : #include <auth/psk.h>
      31             : #include <auth/anon.h>
      32             : #include <datum.h>
      33             : 
      34             : /* The functions here are used in order for authentication algorithms
      35             :  * to be able to retrieve the needed credentials eg public and private
      36             :  * key etc.
      37             :  */
      38             : 
      39             : /**
      40             :  * gnutls_credentials_clear:
      41             :  * @session: is a #gnutls_session_t type.
      42             :  *
      43             :  * Clears all the credentials previously set in this session.
      44             :  **/
      45       23002 : void gnutls_credentials_clear(gnutls_session_t session)
      46             : {
      47       23002 :         if (session->key.cred) {     /* beginning of the list */
      48             :                 auth_cred_st *ccred, *ncred;
      49             :                 ccred = session->key.cred;
      50       59642 :                 while (ccred != NULL) {
      51       36679 :                         ncred = ccred->next;
      52       36679 :                         gnutls_free(ccred);
      53       36679 :                         ccred = ncred;
      54             :                 }
      55       22963 :                 session->key.cred = NULL;
      56             :         }
      57       23002 : }
      58             : 
      59             : /* 
      60             :  * This creates a linked list of the form:
      61             :  * { algorithm, credentials, pointer to next }
      62             :  */
      63             : /**
      64             :  * gnutls_credentials_set:
      65             :  * @session: is a #gnutls_session_t type.
      66             :  * @type: is the type of the credentials
      67             :  * @cred: the credentials to set
      68             :  *
      69             :  * Sets the needed credentials for the specified type.  E.g. username,
      70             :  * password - or public and private keys etc.  The @cred parameter is
      71             :  * a structure that depends on the specified type and on the current
      72             :  * session (client or server).
      73             :  *
      74             :  * In order to minimize memory usage, and share credentials between
      75             :  * several threads gnutls keeps a pointer to cred, and not the whole
      76             :  * cred structure.  Thus you will have to keep the structure allocated
      77             :  * until you call gnutls_deinit().
      78             :  *
      79             :  * For %GNUTLS_CRD_ANON, @cred should be
      80             :  * #gnutls_anon_client_credentials_t in case of a client.  In case of
      81             :  * a server it should be #gnutls_anon_server_credentials_t.
      82             :  *
      83             :  * For %GNUTLS_CRD_SRP, @cred should be #gnutls_srp_client_credentials_t
      84             :  * in case of a client, and #gnutls_srp_server_credentials_t, in case
      85             :  * of a server.
      86             :  *
      87             :  * For %GNUTLS_CRD_CERTIFICATE, @cred should be
      88             :  * #gnutls_certificate_credentials_t.
      89             :  *
      90             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
      91             :  *   otherwise a negative error code is returned.
      92             :  **/
      93             : int
      94       36868 : gnutls_credentials_set(gnutls_session_t session,
      95             :                        gnutls_credentials_type_t type, void *cred)
      96             : {
      97       36868 :         auth_cred_st *ccred = NULL, *pcred = NULL;
      98       36868 :         int exists = 0;
      99             : 
     100       36868 :         if (session->key.cred == NULL) {     /* beginning of the list */
     101             : 
     102       23056 :                 session->key.cred = gnutls_malloc(sizeof(auth_cred_st));
     103       23056 :                 if (session->key.cred == NULL)
     104             :                         return GNUTLS_E_MEMORY_ERROR;
     105             : 
     106             :                 /* copy credentials locally */
     107       23056 :                 session->key.cred->credentials = cred;
     108             : 
     109       23056 :                 session->key.cred->next = NULL;
     110       23056 :                 session->key.cred->algorithm = type;
     111             :         } else {
     112             :                 ccred = session->key.cred;
     113       28457 :                 while (ccred != NULL) {
     114       14661 :                         if (ccred->algorithm == type) {
     115             :                                 exists = 1;
     116             :                                 break;
     117             :                         }
     118       14645 :                         pcred = ccred;
     119       14645 :                         ccred = ccred->next;
     120             :                 }
     121             :                 /* After this, pcred is not null.
     122             :                  */
     123             : 
     124       13812 :                 if (exists == 0) {      /* new entry */
     125       13796 :                         pcred->next = gnutls_malloc(sizeof(auth_cred_st));
     126       13796 :                         if (pcred->next == NULL)
     127             :                                 return GNUTLS_E_MEMORY_ERROR;
     128             : 
     129       13796 :                         ccred = pcred->next;
     130             : 
     131             :                         /* copy credentials locally */
     132       13796 :                         ccred->credentials = cred;
     133             : 
     134       13796 :                         ccred->next = NULL;
     135       13796 :                         ccred->algorithm = type;
     136             :                 } else {        /* modify existing entry */
     137          16 :                         ccred->credentials = cred;
     138             :                 }
     139             :         }
     140             : 
     141             :         /* sanity tests */
     142       36868 :         if (type == GNUTLS_CRD_CERTIFICATE) {
     143       17439 :                 gnutls_certificate_credentials_t c = cred;
     144       17439 :                 unsigned i;
     145       17439 :                 bool allow_tls13 = 0;
     146       17439 :                 unsigned key_usage;
     147             : 
     148       17439 :                 if (c != NULL && c->ncerts != 0) {
     149       14686 :                         for (i = 0; i < c->ncerts; i++) {
     150       14674 :                                 key_usage = get_key_usage(session, c->certs[i].cert_list[0].pubkey);
     151       14668 :                                 if (key_usage == 0 || (key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE)) {
     152             :                                         allow_tls13 = 1;
     153             :                                         break;
     154             :                                 }
     155             :                         }
     156             : 
     157       14662 :                         if (session->security_parameters.entity == GNUTLS_SERVER &&
     158       14534 :                             !c->tls13_ok)
     159             :                                 allow_tls13 = 0;
     160             : 
     161       14556 :                         if (!allow_tls13) {
     162             :                                 /* to prevent the server random indicate TLS1.3 support */
     163         117 :                                 session->internals.flags |= INT_FLAG_NO_TLS13;
     164             :                         }
     165             :                 }
     166             :         }
     167             : 
     168             :         return 0;
     169             : }
     170             : 
     171             : /**
     172             :  * gnutls_credentials_get:
     173             :  * @session: is a #gnutls_session_t type.
     174             :  * @type: is the type of the credentials to return
     175             :  * @cred: will contain the credentials.
     176             :  *
     177             :  * Returns the previously provided credentials structures.
     178             :  *
     179             :  * For %GNUTLS_CRD_ANON, @cred will be
     180             :  * #gnutls_anon_client_credentials_t in case of a client.  In case of
     181             :  * a server it should be #gnutls_anon_server_credentials_t.
     182             :  *
     183             :  * For %GNUTLS_CRD_SRP, @cred will be #gnutls_srp_client_credentials_t
     184             :  * in case of a client, and #gnutls_srp_server_credentials_t, in case
     185             :  * of a server.
     186             :  *
     187             :  * For %GNUTLS_CRD_CERTIFICATE, @cred will be
     188             :  * #gnutls_certificate_credentials_t.
     189             :  *
     190             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
     191             :  *   otherwise a negative error code is returned.
     192             :  *
     193             :  * Since: 3.3.3
     194             :  **/
     195             : int
     196           7 : gnutls_credentials_get(gnutls_session_t session,
     197             :                        gnutls_credentials_type_t type, void **cred)
     198             : {
     199           7 :         const void *_cred;
     200             : 
     201           7 :         _cred = _gnutls_get_cred(session, type);
     202           7 :         if (_cred == NULL)
     203           0 :                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
     204             : 
     205           7 :         if (cred)
     206           7 :                 *cred = (void*)_cred;
     207             : 
     208             :         return 0;
     209             : }
     210             : 
     211             : /**
     212             :  * gnutls_auth_get_type:
     213             :  * @session: is a #gnutls_session_t type.
     214             :  *
     215             :  * Returns type of credentials for the current authentication schema.
     216             :  * The returned information is to be used to distinguish the function used
     217             :  * to access authentication data.
     218             :  *
     219             :  * Eg. for CERTIFICATE ciphersuites (key exchange algorithms:
     220             :  * %GNUTLS_KX_RSA, %GNUTLS_KX_DHE_RSA), the same function are to be
     221             :  * used to access the authentication data.
     222             :  *
     223             :  * Note that on resumed sessions, this function returns the schema
     224             :  * used in the original session authentication.
     225             :  *
     226             :  * Returns: The type of credentials for the current authentication
     227             :  *   schema, a #gnutls_credentials_type_t type.
     228             :  **/
     229       52384 : gnutls_credentials_type_t gnutls_auth_get_type(gnutls_session_t session)
     230             : {
     231       52384 :         if (session->security_parameters.entity == GNUTLS_SERVER)
     232       49320 :                 return gnutls_auth_client_get_type(session);
     233             :         else
     234        3064 :                 return gnutls_auth_server_get_type(session);
     235             : }
     236             : 
     237             : /**
     238             :  * gnutls_auth_server_get_type:
     239             :  * @session: is a #gnutls_session_t type.
     240             :  *
     241             :  * Returns the type of credentials that were used for server authentication.
     242             :  * The returned information is to be used to distinguish the function used
     243             :  * to access authentication data.
     244             :  *
     245             :  * Note that on resumed sessions, this function returns the schema
     246             :  * used in the original session authentication.
     247             :  *
     248             :  * Returns: The type of credentials for the server authentication
     249             :  *   schema, a #gnutls_credentials_type_t type.
     250             :  **/
     251             : gnutls_credentials_type_t
     252        8909 : gnutls_auth_server_get_type(gnutls_session_t session)
     253             : {
     254        8909 :         return session->security_parameters.server_auth_type;
     255             : }
     256             : 
     257             : /**
     258             :  * gnutls_auth_client_get_type:
     259             :  * @session: is a #gnutls_session_t type.
     260             :  *
     261             :  * Returns the type of credentials that were used for client authentication.
     262             :  * The returned information is to be used to distinguish the function used
     263             :  * to access authentication data.
     264             :  *
     265             :  * Note that on resumed sessions, this function returns the schema
     266             :  * used in the original session authentication.
     267             :  *
     268             :  * Returns: The type of credentials for the client authentication
     269             :  *   schema, a #gnutls_credentials_type_t type.
     270             :  **/
     271             : gnutls_credentials_type_t
     272       58407 : gnutls_auth_client_get_type(gnutls_session_t session)
     273             : {
     274       58407 :         return session->security_parameters.client_auth_type;
     275             : }
     276             : 
     277             : 
     278             : /* 
     279             :  * This returns a pointer to the linked list. Don't
     280             :  * free that!!!
     281             :  */
     282       12850 : const void *_gnutls_get_kx_cred(gnutls_session_t session,
     283             :                                 gnutls_kx_algorithm_t algo)
     284             : {
     285       12850 :         int server =
     286       12850 :             session->security_parameters.entity == GNUTLS_SERVER ? 1 : 0;
     287             : 
     288       12850 :         return _gnutls_get_cred(session,
     289             :                                 _gnutls_map_kx_get_cred(algo, server));
     290             : }
     291             : 
     292      203847 : const void *_gnutls_get_cred(gnutls_session_t session,
     293             :                              gnutls_credentials_type_t type)
     294             : {
     295      203847 :         auth_cred_st *ccred;
     296      203847 :         gnutls_key_st *key = &session->key;
     297             : 
     298      203847 :         ccred = key->cred;
     299      314095 :         while (ccred != NULL) {
     300      283024 :                 if (ccred->algorithm == type) {
     301             :                         break;
     302             :                 }
     303      110248 :                 ccred = ccred->next;
     304             :         }
     305      203847 :         if (ccred == NULL)
     306             :                 return NULL;
     307             : 
     308      172776 :         return ccred->credentials;
     309             : }
     310             : 
     311             : /*-
     312             :  * _gnutls_free_auth_info - Frees the auth info structure
     313             :  * @session: is a #gnutls_session_t type.
     314             :  *
     315             :  * This function frees the auth info structure and sets it to
     316             :  * null. It must be called since some structures contain malloced
     317             :  * elements.
     318             :  -*/
     319       23021 : void _gnutls_free_auth_info(gnutls_session_t session)
     320             : {
     321       23021 :         dh_info_st *dh_info;
     322             : 
     323       23021 :         if (session == NULL) {
     324           0 :                 gnutls_assert();
     325           0 :                 return;
     326             :         }
     327             : 
     328       23021 :         switch (session->key.auth_info_type) {
     329             :         case GNUTLS_CRD_SRP:
     330             :                 break;
     331             : #ifdef ENABLE_ANON
     332             :         case GNUTLS_CRD_ANON:
     333             :                 {
     334        1002 :                         anon_auth_info_t info =
     335       14536 :                             _gnutls_get_auth_info(session, GNUTLS_CRD_ANON);
     336             : 
     337        1002 :                         if (info == NULL)
     338             :                                 break;
     339             : 
     340        1002 :                         dh_info = &info->dh;
     341        1002 :                         _gnutls_free_dh_info(dh_info);
     342             :                 }
     343        1002 :                 break;
     344             : #endif
     345             :         case GNUTLS_CRD_PSK:
     346             :                 {
     347        4419 :                         psk_auth_info_t info =
     348       17953 :                             _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
     349             : 
     350        4419 :                         if (info == NULL)
     351             :                                 break;
     352             : 
     353             : #ifdef ENABLE_DHE
     354        4419 :                         dh_info = &info->dh;
     355        4419 :                         _gnutls_free_dh_info(dh_info);
     356             : #endif
     357             :                 }
     358        4419 :                 break;
     359             :         case GNUTLS_CRD_CERTIFICATE:
     360             :                 {
     361        7943 :                         unsigned int i;
     362        7943 :                         cert_auth_info_t info =
     363       21477 :                             _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
     364             : 
     365        7943 :                         if (info == NULL)
     366             :                                 break;
     367             : 
     368        7943 :                         dh_info = &info->dh;
     369       11343 :                         for (i = 0; i < info->ncerts; i++) {
     370        6800 :                                 _gnutls_free_datum(&info->raw_certificate_list[i]);
     371             :                         }
     372             : 
     373        8798 :                         for (i = 0; i < info->nocsp; i++) {
     374        1710 :                                 _gnutls_free_datum(&info->raw_ocsp_list[i]);
     375             :                         }
     376             : 
     377        7943 :                         gnutls_free(info->raw_certificate_list);
     378        7943 :                         gnutls_free(info->raw_ocsp_list);
     379        7943 :                         info->ncerts = 0;
     380        7943 :                         info->nocsp = 0;
     381             : 
     382             : #ifdef ENABLE_DHE
     383        7943 :                         _gnutls_free_dh_info(dh_info);
     384             : #endif
     385             :                 }
     386             : 
     387             : 
     388        7943 :                 break;
     389             :         default:
     390             :                 return;
     391             : 
     392             :         }
     393             : 
     394       13534 :         gnutls_free(session->key.auth_info);
     395       13534 :         session->key.auth_info_size = 0;
     396       13534 :         session->key.auth_info_type = 0;
     397             : 
     398             : }
     399             : 
     400             : /* This function will create the auth info structure in the key
     401             :  * structure if needed.
     402             :  *
     403             :  * If allow change is !=0 then this will allow changing the auth
     404             :  * info structure to a different type.
     405             :  */
     406             : int
     407       16101 : _gnutls_auth_info_init(gnutls_session_t session,
     408             :                       gnutls_credentials_type_t type, int size,
     409             :                       int allow_change)
     410             : {
     411       16101 :         if (session->key.auth_info == NULL) {
     412       13594 :                 session->key.auth_info = gnutls_calloc(1, size);
     413       13594 :                 if (session->key.auth_info == NULL) {
     414           0 :                         gnutls_assert();
     415           0 :                         return GNUTLS_E_MEMORY_ERROR;
     416             :                 }
     417       13594 :                 session->key.auth_info_type = type;
     418       13594 :                 session->key.auth_info_size = size;
     419             :         } else {
     420        2507 :                 if (allow_change == 0) {
     421             :                         /* If the credentials for the current authentication scheme,
     422             :                          * are not the one we want to set, then it's an error.
     423             :                          * This may happen if a rehandshake is performed an the
     424             :                          * ciphersuite which is negotiated has different authentication
     425             :                          * schema.
     426             :                          */
     427         424 :                         if (type != session->key.auth_info_type) {
     428           0 :                                 gnutls_assert();
     429           0 :                                 return GNUTLS_E_INVALID_REQUEST;
     430             :                         }
     431             :                 } else {
     432             :                         /* The new behaviour: Here we reallocate the auth info structure
     433             :                          * in order to be able to negotiate different authentication
     434             :                          * types. Ie. perform an auth_anon and then authenticate again using a
     435             :                          * certificate (in order to prevent revealing the certificate's contents,
     436             :                          * to passive eavesdropers.
     437             :                          */
     438        2083 :                         if (type != session->key.auth_info_type) {
     439             : 
     440          15 :                                 _gnutls_free_auth_info(session);
     441             : 
     442          15 :                                 session->key.auth_info = calloc(1, size);
     443          15 :                                 if (session->key.auth_info == NULL) {
     444           0 :                                         gnutls_assert();
     445           0 :                                         return GNUTLS_E_MEMORY_ERROR;
     446             :                                 }
     447             : 
     448          15 :                                 session->key.auth_info_type = type;
     449          15 :                                 session->key.auth_info_size = size;
     450             :                         }
     451             :                 }
     452             :         }
     453             :         return 0;
     454             : }

Generated by: LCOV version 1.14