Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hide password input on terminal

Tags:

c

linux

I want to mask my password while writing it with *. I use Linux GCC for this code. I know one solution is to use getch() function like this

#include <conio.h>    int main() {     char c,password[10];     int i;     while( (c=getch())!= '\n');{         password[i] = c;         printf("*");         i++;     }     return 1; } 

but the problem is that GCC does not include conio.h file so, getch() is useless for me. Does anyone have a solution?

like image 773
Hit's Avatar asked Jul 28 '11 09:07

Hit's


People also ask

How do I make my Python password not visible?

There are various Python modules that are used to hide the user's inputted password, among them one is maskpass() module. In Python with the help of maskpass() module and base64() module we can hide the password of users with asterisk(*) during input time and then with the help of base64() module it can be encrypted.

Which of the following techniques is used by terminal driver to stop displaying the passwords on console in Linux?

The getpass() function first disables echoing and all processing of terminal special characters (such as the interrupt character, normally Control-C).

How do you make an input invisible in C++?

Use getch() to get the input instead of using cin , so the input will not be shown (quoting wiki): int getch(void) Reads a character directly from the console without buffer, and without echo.

How do I remove a terminal input?

Use either key shortcut: Esc , #


2 Answers

In the Linux world, masking isn't usually done with asterisks, normally echoing is just turned off and the terminal displays blanks E.g. if you use su or log into a virtual terminal etc.

There is a library function to handle getting passwords, it won't mask the password with asterisks but will disable echoing of the password to terminal. I pulled this out of a linux book I have. I believe its part of the posix standard

#include <unistd.h> char *getpass(const char *prompt);  /*Returns pointer to statically allocated input password string on success, or NULL on error*/ 

The getpass() function first disables echoing and all processing of terminal special characters (such as the interrupt character, normally Control-C).

It then prints the string pointed to by prompt, and reads a line of input, returning the null-terminated input string with the trailing newline stripped, as its function result.

A google search for getpass() has a reference to the GNU implementation (should be in most linux distros) and some sample code for implementing your own if need be

http://www.gnu.org/s/hello/manual/libc/getpass.html

Their example for rolling your own:

#include <termios.h> #include <stdio.h>  ssize_t my_getpass (char **lineptr, size_t *n, FILE *stream) {     struct termios old, new;     int nread;      /* Turn echoing off and fail if we can't. */     if (tcgetattr (fileno (stream), &old) != 0)         return -1;     new = old;     new.c_lflag &= ~ECHO;     if (tcsetattr (fileno (stream), TCSAFLUSH, &new) != 0)         return -1;      /* Read the password. */     nread = getline (lineptr, n, stream);      /* Restore terminal. */     (void) tcsetattr (fileno (stream), TCSAFLUSH, &old);      return nread; } 

If need be you could use this as the basis as modify it to display asterisks.

like image 67
matt Avatar answered Oct 11 '22 02:10

matt


Without getch to rely on and avoiding the obsolete getpass, the recommended approach is to disable terminal ECHO through termios use. After a few searches to find a canned flexible password routine, I was surprised that very few for stand-alone use with C. Rather than simply recoding getch with termios c_lflag options, slightly more generalized approach takes just a few additions. Beyond replacing getch any routine should enforce a specified maximum length to prevent overflow, truncate if the user attempt to enter beyond the maximum, and warn if truncation occurs in some manner.

Below, the additions will allow reading from any FILE * input stream, limiting the length to a specified length, provide minimal editing (backspace) ability when taking input, allow the character mask to be specified or disabled completely, and finally return the length of the password entered. A warning was added when the password entered was truncated to the maximum or specified length.

Hopefully it will prove useful to others with this question looking for a similar solution:

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <termios.h>  #define MAXPW 32  /* read a string from fp into pw masking keypress with mask char. getpasswd will read upto sz - 1 chars into pw, null-terminating the resulting string. On success, the number of characters in pw are returned, -1 otherwise. */ ssize_t getpasswd (char **pw, size_t sz, int mask, FILE *fp) {     if (!pw || !sz || !fp) return -1;       /* validate input   */ #ifdef MAXPW     if (sz > MAXPW) sz = MAXPW; #endif      if (*pw == NULL) {              /* reallocate if no address */         void *tmp = realloc (*pw, sz * sizeof **pw);         if (!tmp)             return -1;         memset (tmp, 0, sz);    /* initialize memory to 0   */         *pw =  (char*) tmp;     }      size_t idx = 0;         /* index, number of chars in read   */     int c = 0;      struct termios old_kbd_mode;    /* orig keyboard settings   */     struct termios new_kbd_mode;      if (tcgetattr (0, &old_kbd_mode)) { /* save orig settings   */         fprintf (stderr, "%s() error: tcgetattr failed.\n", __func__);         return -1;     }   /* copy old to new */     memcpy (&new_kbd_mode, &old_kbd_mode, sizeof(struct termios));      new_kbd_mode.c_lflag &= ~(ICANON | ECHO);  /* new kbd flags */     new_kbd_mode.c_cc[VTIME] = 0;     new_kbd_mode.c_cc[VMIN] = 1;     if (tcsetattr (0, TCSANOW, &new_kbd_mode)) {         fprintf (stderr, "%s() error: tcsetattr failed.\n", __func__);         return -1;     }      /* read chars from fp, mask if valid char specified */     while (((c = fgetc (fp)) != '\n' && c != EOF && idx < sz - 1) ||             (idx == sz - 1 && c == 127))     {         if (c != 127) {             if (31 < mask && mask < 127)    /* valid ascii char */                 fputc (mask, stdout);             (*pw)[idx++] = c;         }         else if (idx > 0) {         /* handle backspace (del)   */             if (31 < mask && mask < 127) {                 fputc (0x8, stdout);                 fputc (' ', stdout);                 fputc (0x8, stdout);             }             (*pw)[--idx] = 0;         }     }     (*pw)[idx] = 0; /* null-terminate   */      /* reset original keyboard  */     if (tcsetattr (0, TCSANOW, &old_kbd_mode)) {         fprintf (stderr, "%s() error: tcsetattr failed.\n", __func__);         return -1;     }      if (idx == sz - 1 && c != '\n') /* warn if pw truncated */         fprintf (stderr, " (%s() warning: truncated at %zu chars.)\n",                 __func__, sz - 1);      return idx; /* number of chars in passwd    */ } 

A simple program showing the use would be as follows. If using a static array of character for holding the password, just insure a pointer is passed to the function.

int main (void ) {      char pw[MAXPW] = {0};     char *p = pw;     FILE *fp = stdin;     ssize_t nchr = 0;      printf ( "\n Enter password: ");     nchr = getpasswd (&p, MAXPW, '*', fp);     printf ("\n you entered   : %s  (%zu chars)\n", p, nchr);      printf ( "\n Enter password: ");     nchr = getpasswd (&p, MAXPW, 0, fp);     printf ("\n you entered   : %s  (%zu chars)\n\n", p, nchr);      return 0; } 

Example Output

$ ./bin/getpasswd2   Enter password: ******  you entered   : 123456  (6 chars)   Enter password:  you entered   : abcdef  (6 chars) 
like image 39
David C. Rankin Avatar answered Oct 11 '22 02:10

David C. Rankin