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

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2005-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 for operating in an PSK passwd file are included here */
      24             : 
      25             : #include "gnutls_int.h"
      26             : 
      27             : #include "x509_b64.h"
      28             : #include "errors.h"
      29             : #include <auth/psk_passwd.h>
      30             : #include <auth/psk.h>
      31             : #include "auth.h"
      32             : #include "dh.h"
      33             : #include "debug.h"
      34             : #include <str.h>
      35             : #include <datum.h>
      36             : #include <num.h>
      37             : #include <random.h>
      38             : 
      39             : 
      40             : /* this function parses passwd.psk file. Format is:
      41             :  * string(username):hex(passwd)
      42             :  */
      43        3073 : static int pwd_put_values(gnutls_datum_t * psk, char *str)
      44             : {
      45        3073 :         char *p;
      46        3073 :         int len, ret;
      47        3073 :         gnutls_datum_t tmp;
      48             : 
      49        3073 :         p = strchr(str, ':');
      50        3073 :         if (p == NULL) {
      51           0 :                 gnutls_assert();
      52           0 :                 return GNUTLS_E_SRP_PWD_PARSING_ERROR;
      53             :         }
      54             : 
      55        3073 :         *p = '\0';
      56        3073 :         p++;
      57             : 
      58             :         /* skip username
      59             :          */
      60             : 
      61             :         /* read the key
      62             :          */
      63        3073 :         len = strlen(p);
      64        3073 :         if (p[len - 1] == '\n' || p[len - 1] == ' ')
      65        3073 :                 len--;
      66             : 
      67        3073 :         tmp.data = (void*)p;
      68        3073 :         tmp.size = len;
      69        3073 :         ret = gnutls_hex_decode2(&tmp, psk);
      70        3073 :         if (ret < 0) {
      71         130 :                 gnutls_assert();
      72         130 :                 return ret;
      73             :         }
      74             : 
      75             :         return 0;
      76             : }
      77             : 
      78       10163 : static bool username_matches(const gnutls_datum_t *username,
      79             :                              const char *line, size_t line_size)
      80             : {
      81       10163 :         int retval;
      82       10163 :         unsigned i;
      83       10163 :         gnutls_datum_t hexline, hex_username = { NULL, 0 };
      84             : 
      85             :         /*
      86             :          * Guard against weird behavior - we don't check 'line',
      87             :          * as it's returned by getline(), which will never return NULL
      88             :          * if successful.
      89             :          */
      90       10163 :         if (username->data == NULL)
      91             :                 return false;
      92             : 
      93       10163 :         if (line_size == 0)
      94           0 :                 return (username->size == 0);
      95             : 
      96             :         /* move to first ':' */
      97             :         i = 0;
      98       68510 :         while ((i < line_size) && (line[i] != '\0')
      99       68510 :                && (line[i] != ':')) {
     100       58347 :                 i++;
     101             :         }
     102             : 
     103             :         /* if format is in hex, e.g. #FAFAFA */
     104       10163 :         if (line[0] == '#' && line_size > 1) {
     105        4580 :                 hexline.data = (void *) &line[1];
     106        4580 :                 hexline.size = i - 1;
     107             : 
     108        4580 :                 if (gnutls_hex_decode2(&hexline, &hex_username) < 0)
     109           0 :                         return gnutls_assert_val(0);
     110             : 
     111        4580 :                 if (hex_username.size == username->size)
     112        2788 :                         retval = memcmp(username->data, hex_username.data, username->size);
     113             :                 else
     114             :                         retval = -1;
     115             : 
     116        4580 :                 _gnutls_free_datum(&hex_username);
     117             :         } else {
     118        5583 :                 retval = strncmp((const char *) username->data, line, MAX(i, username->size));
     119             :         }
     120             : 
     121       10163 :         return (retval == 0);
     122             : }
     123             : 
     124             : 
     125             : /* Randomizes the given password entry. It actually sets a random password. 
     126             :  * Returns 0 on success.
     127             :  */
     128         136 : static int _randomize_psk(gnutls_datum_t * psk)
     129             : {
     130         136 :         int ret;
     131             : 
     132         136 :         psk->data = gnutls_malloc(16);
     133         136 :         if (psk->data == NULL) {
     134           0 :                 gnutls_assert();
     135           0 :                 return GNUTLS_E_MEMORY_ERROR;
     136             :         }
     137             : 
     138         136 :         psk->size = 16;
     139             : 
     140         136 :         ret = gnutls_rnd(GNUTLS_RND_NONCE, (char *) psk->data, 16);
     141         136 :         if (ret < 0) {
     142           0 :                 gnutls_assert();
     143           0 :                 return ret;
     144             :         }
     145             : 
     146             :         return 0;
     147             : }
     148             : 
     149             : /* Returns the PSK key of the given user. 
     150             :  * If the user doesn't exist a random password is returned instead.
     151             :  */
     152             : int
     153        3868 : _gnutls_psk_pwd_find_entry(gnutls_session_t session,
     154             :                            const char *username, uint16_t username_len,
     155             :                            gnutls_datum_t * psk)
     156             : {
     157        3868 :         gnutls_psk_server_credentials_t cred;
     158        3868 :         FILE *fp;
     159        3868 :         char *line = NULL;
     160        3868 :         size_t line_size = 0;
     161        3868 :         int ret;
     162        3868 :         gnutls_datum_t username_datum = {
     163             :                 .data = (unsigned char *) username,
     164             :                 .size = username_len
     165             :         };
     166             : 
     167        3868 :         cred = (gnutls_psk_server_credentials_t)
     168        3868 :             _gnutls_get_cred(session, GNUTLS_CRD_PSK);
     169        3868 :         if (cred == NULL) {
     170           0 :                 gnutls_assert();
     171           0 :                 return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
     172             :         }
     173             : 
     174             :         /* if the callback which sends the parameters is
     175             :          * set, use it.
     176             :          */
     177        3868 :         if (cred->pwd_callback != NULL) {
     178         659 :                 ret = cred->pwd_callback(session, &username_datum, psk);
     179             : 
     180         659 :                 if (ret == 1) { /* the user does not exist */
     181           0 :                         ret = _randomize_psk(psk);
     182           0 :                         if (ret < 0) {
     183           0 :                                 gnutls_assert();
     184           0 :                                 return ret;
     185             :                         }
     186             :                         return 0;
     187             :                 }
     188             : 
     189         659 :                 if (ret < 0) {
     190           0 :                         gnutls_assert();
     191           0 :                         return GNUTLS_E_SRP_PWD_ERROR;
     192             :                 }
     193             : 
     194             :                 return 0;
     195             :         }
     196             : 
     197             :         /* The callback was not set. Proceed.
     198             :          */
     199        3209 :         if (cred->password_file == NULL) {
     200           0 :                 gnutls_assert();
     201           0 :                 return GNUTLS_E_SRP_PWD_ERROR;
     202             :         }
     203             : 
     204             :         /* Open the selected password file.
     205             :          */
     206        3209 :         fp = fopen(cred->password_file, "re");
     207        3209 :         if (fp == NULL) {
     208           0 :                 gnutls_assert();
     209           0 :                 return GNUTLS_E_SRP_PWD_ERROR;
     210             :         }
     211             : 
     212       10299 :         while (getline(&line, &line_size, fp) > 0) {
     213       10163 :                 if (username_matches(&username_datum, line, line_size)) {
     214        3073 :                         ret = pwd_put_values(psk, line);
     215        3073 :                         if (ret < 0) {
     216         130 :                                 gnutls_assert();
     217         130 :                                 ret = GNUTLS_E_SRP_PWD_ERROR;
     218         130 :                                 goto cleanup;
     219             :                         }
     220        2943 :                         ret = 0;
     221        2943 :                         goto cleanup;
     222             :                 }
     223             :         }
     224             : 
     225             :         /* user was not found. Fake him. 
     226             :          */
     227         136 :         ret = _randomize_psk(psk);
     228         136 :         if (ret < 0) {
     229           0 :                 goto cleanup;
     230             :         }
     231             : 
     232             :         ret = 0;
     233        3209 : cleanup:
     234        3209 :         if (fp != NULL)
     235        3209 :                 fclose(fp);
     236             : 
     237        3209 :         zeroize_key(line, line_size);
     238        3209 :         free(line);
     239             : 
     240        3209 :         return ret;
     241             : 
     242             : }
     243             : 
     244             : /* returns the username and they key for the PSK session.
     245             :  * Free is non (0) if they have to be freed.
     246             :  */
     247         617 : int _gnutls_find_psk_key(gnutls_session_t session,
     248             :                          gnutls_psk_client_credentials_t cred,
     249             :                          gnutls_datum_t * username, gnutls_datum_t * key,
     250             :                          int *free)
     251             : {
     252         617 :         int ret;
     253             : 
     254         617 :         *free = 0;
     255             : 
     256         617 :         if (cred->username.data != NULL && cred->key.data != NULL) {
     257         616 :                 username->data = cred->username.data;
     258         616 :                 username->size = cred->username.size;
     259         616 :                 key->data = cred->key.data;
     260         616 :                 key->size = cred->key.size;
     261           1 :         } else if (cred->get_function != NULL) {
     262           1 :                 ret = cred->get_function(session, username, key);
     263             : 
     264           1 :                 if (ret)
     265           0 :                         return gnutls_assert_val(ret);
     266             : 
     267           1 :                 *free = 1;
     268             :         } else
     269           0 :                 return
     270           0 :                     gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
     271             : 
     272             :         return 0;
     273             : }

Generated by: LCOV version 1.14