Как правильно использовать функции fgets () и strncmp ()? - PullRequest
0 голосов
/ 16 июня 2019

Я пытаюсь защитить некоторый код C, используя функции fgets () и strncmp ().Программа работает нормально, однако, если я введу правильный пароль («пароль») более одного раза, он все равно будет указывать правильный пароль.Кроме того, даже при использовании функции fgets () результаты (если они больше, чем 9, указанные в буфере) все равно появляются в выходных данных.Любая помощь будет принята с благодарностью.

#include <stdio.h>
#include <string.h>

int main(void)
{
    char buffer[9];
    int pass = 0;
    char password[] = "password";

    printf("\n Enter your password : \n");
    fgets(buffer, 9, stdin);

    if(strcmp(buffer, password))
    {
        printf ("\n Incorrect Password \n");
    }
    else
    {
        printf ("\n Correct Password \n");
        pass = 1;
    }

    if(pass)
    {
        printf ("\n Root privileges authorized \n");
    }

    return 0;
}

Ответы [ 2 ]

1 голос
/ 16 июня 2019

Проблема с вашим кодом в том, что fgets берет первые 8 символов с входа и игнорирует остальные. Очевидно, что если вы приглашаете пароль, вы не хотите игнорировать любой ввод! Возможно, вы захотите сделать что-то более причудливое, чтобы убедиться, что вы захватили весь ввод.

Мои первые две попытки ответить на этот вопрос были неверными. Спасибо Wildplasser за то, что я держал ноги у огня.

Итак, хакерский ответ: используйте действительно большой буфер. fgets - это, вероятно, ваше простое решение.

В качестве альтернативы, вы можете динамически распределять память, когда входная строка превышает ваш буфер.

Но, просто для удовольствия, вот реализация, которая выводит нас из ловушки "строкового буфера", в которой я не знал, что getchar был.

Для этого я использовал очень красивый комментарий: getchar () и stdin

PS: Хорошо, хорошо, я протестировал на этот раз. Оно работает. На моем Mac.

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <termios.h>

int main(void)
{
    int c, i;
    char buffer[9];
    struct termios tty_opts_default, tty_opts_raw;

    if (!isatty(STDIN_FILENO)) {
      printf("Error: stdin is not a TTY\n");
      return 1;
    }

    /* save tty settings for later. */
    tcgetattr(STDIN_FILENO, &tty_opts_default);

    /* put tty settings into raw mode. */
    cfmakeraw(&tty_opts_raw);
    tcsetattr(STDIN_FILENO, TCSANOW, &tty_opts_raw);

    /* NOW we can grab the input one character at a time. */
    c = getchar();
    while (i < 8 && c != EOF && c != '\n' && c != '\r') {
      /* Since we are collecting a pwd, we might want to enforce other
         password logic here, such as no control characters! */
      putchar('*');
      buffer[i++] = c;
      c = getchar();
    }
    buffer[i] = '\0';

    /* Restore default TTY settings */
    tcsetattr(STDIN_FILENO, TCSANOW, &tty_opts_default);

    /* Report results to user. */
    printf("\nPassword received.\n");
    printf("(It was '%s' -- don't tell anyone! Quick! Hide the terminal!)\n", buffer);

    return 0;
}
0 голосов
/ 16 июня 2019
  • fgets() также читает (CR +) LF и сохраняет его в буфере.
  • Но только , если места достаточно!
  • В противном случае ваш буфер будет содержать первые n-1 символов плюс символ NUL.

    Итак: выделите достаточно большой буфер и уберите CR / LF:


#include <stdio.h>
#include <string.h>

int main(void)
{
    int pass = 0;
    char password[] = "password";
    char buffer[3+ sizeof password];

    printf("\n Enter your password : \n");
    fgets(buffer, sizeof buffer, stdin);
    buffer[strcspn(buffer,"\r\n")]=0;

    if(strcmp(buffer, password))
    {
        printf ("\n Incorrect Password \n");
    }

    else
    {
        printf ("\n Correct Password \n");
        pass = 1;
    }

    if(pass)
    {
        printf ("\n Root privileges authorized \n");
    }

    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...