tecn603
tecn603

Reputation: 251

Masking the characters of a password in a C program on Linux

I'm trying to create a program that obscures the characters entered when entering the password. But I still have a problem, as soon as I start the program, '*' characters are continuously written up to a segmentation fault. This is the code that I wrote and the behavior of the program after execution:

#include <stdio.h>
#include <curses.h>

#define ENTER 13
#define TAB 9

char pwd[100];

int main(){
    int i = 0;
    char ch;

    printf("Enter your password. Hit ENTER to confirm.\n");
    printf("Password:");

    while(getch() != ENTER){
        ch = getch();
        pwd[i++] = ch;
        printf("* \b");
    }
    if(ch == ENTER || ch == TAB){
        pwd[i] = '\0';
    }

    printf("\n\nPassword:%s\nLength:%d\n\n", pwd, i);
    return 0;
}

enter image description here

Upvotes: 1

Views: 358

Answers (3)

user3629249
user3629249

Reputation: 16540

regarding:

while(getch() != ENTER){
    ch = getch();

this gets 2 characters every pass through the loop. Not what you want. Suggest:

while( ( ch = getch() ) != ENTER ){

To avoid echoing the char when the user enters it: You need to turn echo off then for each char entered by the user, output a masking character, like *

since the array pwd[] is only 100 characters long, need to limit the number of characters the user can enter to 99 (leaves room for the trailing NUL byte) Suggest:

 WINDOW *mainwin;
 mainwin = initscr();   /* start the curses mode with default window */
 clear()    /* clear the default window */
 ...
 raw();     /* stop terminal driver from interpreting key strokes */ 
 cbreak();  /* input chars without waiting for newline */
 
 nodelay( mainwin, true); /* causes getch() to wait for a key rather than returning ERR */
 keypad( mainwin, true ); /* program must handle all meta keys including newline */

 noecho();  /* stop terminal echo while entering password */

 size_t i = 0;
 while( i < (sizeof( pwd ) -1) && ( ch = getch() ) != ENTER )
 {
     pwd[i] = ch;
     i++;

     printw( "*" );
     refresh();
 }

 echo();               /* resume echoing characters on terminal */
 keypad( mainwin, false );      /* stop passing keypad chars to program */
 noraw();              /* terminal driver resumes interpreting key strokes */

 pwd[i] = '\0';        /* NUL terminate the string */   
 ...
 endwin();

The above may be a bit of overkill.

due to several problems, suggest NOT using the C library function: getpass()

if you use the raw() function, then the program will also need to handle backspace (and similar) characters from the user.

Upvotes: 0

Snild Dolkow
Snild Dolkow

Reputation: 6866

Looks like you're getting ERR returned from getch().

That is not equal to ENTER, so the loop is entered and repeated. Eventually, you run out of room in pwd, but continue writing outside it. The segmentation fault means that you tried to write some address that is unwriteable.

You also have a bug in that you call getch() twice per loop, which will give you trouble even after fixing the loop/segfault issue.

Upvotes: 0

Andy
Andy

Reputation: 13597

You are supposed to call initscr(); before you start using any ncurses methods. So, try doing this:

int main(){
    int i = 0;
    char ch;

    initscr();
    // ...

More information.

Upvotes: 2

Related Questions