LCOV - code coverage report
Current view: top level - lib/util - getpass.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 48 83 57.8 %
Date: 2024-04-21 15:09:00 Functions: 2 2 100.0 %

          Line data    Source code
       1             : /*
       2             :  *  Unix SMB/CIFS implementation.
       3             :  *
       4             :  *  getpass.c - platform independent getpass function.
       5             :  *
       6             :  *  Copyright (c) 2010-2012 Andreas Schneider <asn@samba.org>
       7             :  *
       8             :  *  This program is free software; you can redistribute it and/or modify
       9             :  *  it under the terms of the GNU General Public License as published by
      10             :  *  the Free Software Foundation; either version 3 of the License, or
      11             :  *  (at your option) any later version.
      12             :  *
      13             :  *  This program is distributed in the hope that it will be useful,
      14             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :  *  GNU General Public License for more details.
      17             :  *
      18             :  *  You should have received a copy of the GNU General Public License
      19             :  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
      20             :  */
      21             : 
      22             : #include "includes.h"
      23             : 
      24             : #include "system/filesys.h"
      25             : #include "system/terminal.h"
      26             : 
      27             : #if !defined(SMB_MALLOC)
      28             : #undef malloc
      29             : #define SMB_MALLOC(s) malloc((s))
      30             : #endif
      31             : 
      32             : /**
      33             :  * @internal
      34             :  *
      35             :  * @brief Get the password from the console.
      36             :  *
      37             :  * @param[in]  prompt   The prompt to display.
      38             :  *
      39             :  * @param[in]  buf      The buffer to fill.
      40             :  *
      41             :  * @param[in]  len      The length of the buffer.
      42             :  *
      43             :  * @param[in]  verify   Should the password be verified?
      44             :  *
      45             :  * @return              1 on success, 0 on error.
      46             :  */
      47          80 : static int samba_gets(const char *prompt, char *buf, size_t len, bool verify)
      48             : {
      49           0 :         char *tmp;
      50          80 :         char *ptr = NULL;
      51          80 :         int ok = 0;
      52             : 
      53          80 :         tmp = SMB_MALLOC(len);
      54          80 :         if (tmp == NULL) {
      55           0 :                 return 0;
      56             :         }
      57          80 :         memset(tmp,'\0',len);
      58             : 
      59             :         /* read the password */
      60         158 :         while (!ok) {
      61          80 :                 if (buf[0] != '\0') {
      62           0 :                         fprintf(stdout, "%s[%s] ", prompt, buf);
      63             :                 } else {
      64          80 :                         fprintf(stdout, "%s", prompt);
      65             :                 }
      66          80 :                 fflush(stdout);
      67          80 :                 if (fgets(tmp, len, stdin) == NULL) {
      68           2 :                         free(tmp);
      69           2 :                         return 0;
      70             :                 }
      71             : 
      72          78 :                 if ((ptr = strchr(tmp, '\n'))) {
      73          78 :                         *ptr = '\0';
      74             :                 }
      75          78 :                 fprintf(stdout, "\n");
      76             : 
      77          78 :                 if (*tmp) {
      78          78 :                         strncpy(buf, tmp, len);
      79             :                 }
      80             : 
      81          78 :                 if (verify) {
      82           0 :                         char *key_string;
      83             : 
      84           0 :                         key_string = SMB_MALLOC(len);
      85           0 :                         if (key_string == NULL) {
      86           0 :                                 break;
      87             :                         }
      88           0 :                         memset(key_string, '\0', len);
      89             : 
      90           0 :                         fprintf(stdout, "\nVerifying, please re-enter. %s", prompt);
      91           0 :                         fflush(stdout);
      92           0 :                         if (! fgets(key_string, len, stdin)) {
      93           0 :                                 memset(key_string, '\0', len);
      94           0 :                                 SAFE_FREE(key_string);
      95           0 :                                 clearerr(stdin);
      96           0 :                                 continue;
      97             :                         }
      98           0 :                         if ((ptr = strchr(key_string, '\n'))) {
      99           0 :                                 *ptr = '\0';
     100             :                         }
     101           0 :                         fprintf(stdout, "\n");
     102           0 :                         if (strcmp(buf, key_string)) {
     103           0 :                                 printf("\n\07\07Mismatch - try again\n");
     104           0 :                                 memset(key_string, '\0', len);
     105           0 :                                 SAFE_FREE(key_string);
     106           0 :                                 fflush(stdout);
     107           0 :                                 continue;
     108             :                         }
     109           0 :                         memset(key_string, '\0', len);
     110           0 :                         SAFE_FREE(key_string);
     111             :                 }
     112          78 :                 ok = 1;
     113             :         }
     114          78 :         memset(tmp, '\0', len);
     115          78 :         free(tmp);
     116             : 
     117          78 :         return ok;
     118             : }
     119             : 
     120             : /**
     121             :  * @brief Get a password from the console.
     122             :  *
     123             :  * You should make sure that the buffer is an empty string!
     124             :  *
     125             :  * You can also use this function to ask for a username. Then you can fill the
     126             :  * buffer with the username and it is shows to the users. If the users just
     127             :  * presses enter the buffer will be untouched.
     128             :  *
     129             :  * @code
     130             :  *   char username[128];
     131             :  *
     132             :  *   snprintf(username, sizeof(username), "john");
     133             :  *
     134             :  *   samba_getpass("Username:", username, sizeof(username), 1, 0);
     135             :  * @endcode
     136             :  *
     137             :  * The prompt will look like this:
     138             :  *
     139             :  *   Username: [john]
     140             :  *
     141             :  * If you press enter then john is used as the username, or you can type it in
     142             :  * to change it.
     143             :  *
     144             :  * @param[in]  prompt   The prompt to show to ask for the password.
     145             :  *
     146             :  * @param[out] buf    The buffer the password should be stored. It NEEDS to be
     147             :  *                      empty or filled out.
     148             :  *
     149             :  * @param[in]  len      The length of the buffer.
     150             :  *
     151             :  * @param[in]  echo     Should we echo what you type.
     152             :  *
     153             :  * @param[in]  verify   Should we ask for the password twice.
     154             :  *
     155             :  * @return              0 on success, -1 on error.
     156             :  */
     157          80 : int samba_getpass(const char *prompt,
     158             :                   char *buf,
     159             :                   size_t len,
     160             :                   bool echo,
     161             :                   bool verify)
     162             : {
     163           0 :         struct termios attr;
     164           0 :         struct termios old_attr;
     165          80 :         int ok = 0;
     166          80 :         int fd = -1;
     167             : 
     168             :         /* fgets needs at least len - 1 */
     169          80 :         if (prompt == NULL || buf == NULL || len < 2) {
     170           0 :                 return -1;
     171             :         }
     172             : 
     173          80 :         if (isatty (STDIN_FILENO)) {
     174             : 
     175          46 :                 ZERO_STRUCT(attr);
     176          46 :                 ZERO_STRUCT(old_attr);
     177             : 
     178             :                 /* get local terminal attributes */
     179          46 :                 if (tcgetattr(STDIN_FILENO, &attr) < 0) {
     180           0 :                         perror("tcgetattr");
     181           0 :                         return -1;
     182             :                 }
     183             : 
     184             :                 /* save terminal attributes */
     185          46 :                 memcpy(&old_attr, &attr, sizeof(attr));
     186          46 :                 if((fd = fcntl(0, F_GETFL, 0)) < 0) {
     187           0 :                         perror("fcntl");
     188           0 :                         return -1;
     189             :                 }
     190             : 
     191             :                 /* disable echo */
     192          46 :                 if (!echo) {
     193          46 :                         attr.c_lflag &= ~(ECHO);
     194             :                 }
     195             : 
     196             :                 /* write attributes to terminal */
     197          46 :                 if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &attr) < 0) {
     198           0 :                         perror("tcsetattr");
     199           0 :                         return -1;
     200             :                 }
     201             :         }
     202             : 
     203             :         /* disable nonblocking I/O */
     204          80 :         if (fd & O_NDELAY) {
     205          34 :                 fcntl(0, F_SETFL, fd & ~O_NDELAY);
     206             :         }
     207             : 
     208          80 :         ok = samba_gets(prompt, buf, len, verify);
     209             : 
     210          80 :         if (isatty (STDIN_FILENO)) {
     211             : 
     212             :                 /* reset terminal */
     213          46 :                 tcsetattr(STDIN_FILENO, TCSANOW, &old_attr);
     214             :         }
     215             : 
     216             :         /* close fd */
     217          80 :         if (fd & O_NDELAY) {
     218          34 :                 fcntl(0, F_SETFL, fd);
     219             :         }
     220             : 
     221          80 :         if (!ok) {
     222           2 :                 memset (buf, '\0', len);
     223           2 :                 return -1;
     224             :         }
     225             : 
     226             :         /* force termination */
     227          78 :         buf[len - 1] = '\0';
     228             : 
     229          78 :         return 0;
     230             : }

Generated by: LCOV version 1.14