Получение пароля в C без использования getpass (3)?


Я мог бы использовать getpass(), чтобы получить пароль. Однако на главной странице написано:

Эта функция устарела. Не использовать оно.

Каков текущий способ получить пароль от терминала пользователя, не повторяя его, в POSIX-совместимом способе? [Первоначально я сказал "переносно", но мое намерение состояло в том, чтобы избежать использования устаревшей функции.]

5 21

5 ответов:

Это должно работать на Linux/MacOSX она называется, версию Windows должны использовать получить/установить 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;
}

Вы можете использовать библиотекуncurses для чтения из стандартного ввода, не передавая результаты на экран. (Вызовите noecho() перед получением любого ввода). Библиотека существует уже много лет и работает на самых разных платформах (версию для windows можно найти здесь )

Хотя это очень старый вопрос, на который уже был дан ответ, вот что я использую (что очень похоже на принятый ответ):

#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;
}

Согласно документации университета Милуоки он устарел, потому что:

Функция getpass() не является потокобезопасной, поскольку она манипулирует состояние глобального сигнала.

Функцию getpass() планируется изъять из будущей версии спецификации X/Open CAE.

В windows, вероятно, можно использовать api SetConsoleMode, описанный здесь .