Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting a password in C without using getpass (3)?

Tags:

c

passwords

I could use getpass() to get a password. However, the man page says:

This function is obsolete. Do not use it.

What is the current way to get a password from the user's terminal without echoing it, in a POSIX-compliant way? [Originally I said "portably", but my intention was to avoid using an obsolete function.]

like image 403
Jerry Penner Avatar asked Jul 28 '09 20:07

Jerry Penner


People also ask

Why is Getpass deprecated?

Why is getpass() considered an obsolete function? The getpass() function is not threadsafe because it manipulates global signal state. The getpass() function is scheduled to be withdrawn from a future version of the X/Open CAE Specification. If your C library has the function, then you can use it.

What is Getpass in C?

The getpass() function opens the process's controlling terminal, writes to that device the NULL-terminated string prompt, disables echoing, reads a string of characters up to the next newline character or EOF, restores the terminal state and closes the terminal.

How do I prompt a password in Python?

The getpass() function is used to prompt to users using the string prompt and reads the input from the user as Password. The input read defaults to “Password: ” is returned to the caller as a string.

How does Getpass work Python?

The getpass module in Python yields a platform-independent approach to entering or adding passwords in a command-line program. The getuser() method is used to extract the current logged-in username or login name. In order to return, it checks system environment variables LOGNAME , USER , LNAME and USERNAME .


3 Answers

this should work on linux/macosx, a windows version should use Get/Set ConsoleMode

#include <stdio.h>
#include <stdlib.h>
#include <termios.h>

int
main(int argc, char **argv)
{
    struct termios oflags, nflags;
    char password[64];

    /* disabling echo */
    tcgetattr(fileno(stdin), &oflags);
    nflags = oflags;
    nflags.c_lflag &= ~ECHO;
    nflags.c_lflag |= ECHONL;

    if (tcsetattr(fileno(stdin), TCSANOW, &nflags) != 0) {
        perror("tcsetattr");
        return EXIT_FAILURE;
    }

    printf("password: ");
    fgets(password, sizeof(password), stdin);
    password[strlen(password) - 1] = 0;
    printf("you typed '%s'\n", password);

    /* restore terminal */
    if (tcsetattr(fileno(stdin), TCSANOW, &oflags) != 0) {
        perror("tcsetattr");
        return EXIT_FAILURE;
    }

    return 0;
}
like image 160
dfa Avatar answered Oct 11 '22 18:10

dfa


You could use the ncurses library to read from standard input without echoing the results to the screen. (Call noecho() before getting any input). The library has been around for ages and works on a wide variety of platforms (the windows version can be found here)

like image 41
indy Avatar answered Oct 11 '22 17:10

indy


Even though this is a very old question that has already been answered, here's what I've been using (which is very similar to the accepted answer):

#include <termios.h>
#include <cstdio>

//
// The following is a slightly modifed version taken from:
// http://www.gnu.org/software/libc/manual/html_node/getpass.html
//
ssize_t my_getpass (char *prompt, 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;

    /* Display the prompt */
    if (prompt)
        printf("%s", prompt);

    /* Read the password. */
    nread = getline (lineptr, n, stream);

    /* Remove the carriage return */
    if (nread >= 1 && (*lineptr)[nread - 1] == '\n')
    {
        (*lineptr)[nread-1] = 0;
        nread--;
    }
    printf("\n");

    /* Restore terminal. */
    (void) tcsetattr (fileno (stream), TCSAFLUSH, &_old);

    return nread;
}

//
// Test harness - demonstrate calling my_getpass().
//
int main(int argc, char *argv[])
{
    size_t maxlen = 255;
    char pwd[maxlen];
    char *pPwd = pwd; // <-- haven't figured out how to avoid this.

    int count = my_getpass((char*)"Enter Password: ", &pPwd, &maxlen, stdin);

    printf("Size of password: %d\nPassword in plaintext: %s\n", count, pwd);

    return 0;
}
like image 5
Vanessa Deagan Avatar answered Oct 11 '22 18:10

Vanessa Deagan