C: Passwortabfrage im Terminal
Ich beschreibe hier kurz, wie unter Linux in der Konsole ein Passwort abgefragt werden kann, ohne dass die Eingabe des Users im Terminal erscheint.
Hierzu Definitionen im Header-File passphrase.h:
#ifndef PRJ_PASSPHRASE_H #define PRJ_PASSPHRASE_H 1 #if defined(__cplusplus) extern "C" { #endif char * prj_read_passphrase(size_t size); int prj_get_passphrase(size_t count, size_t size, char **passphrase); #if defined(__cplusplus) } #endif #endif /* !PRJ_PASSPHRASE_H */
Daraufhin der eigentliche Code in passphrase.c:
#include <stdlib.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <termios.h> #include "passphrase.h" /* * \brief prj_read_passphrase * * reads from stdin input of user * * \param size maximum length of input * * \return a char array containing input of user */ char * prj_read_passphrase(size_t size) { char password_input[size + 1]; char *password = NULL; int ch, i; for (i = 0; (i < (int) size) && ((ch = getchar()) != EOF) && (ch != '\n') && (ch != '\r'); i++) { if (ch == 127 || ch == 8) { /* DEL or BS */ if (i > 0) i = i - 2; else i = -1; } else if (ch < 33) /* of course no control characters allowed */ i--; else password_input[i] = (char) ch; } password_input[i] = '\0'; /* last given hidden character is broken */ i++; password = (char *) malloc(sizeof(char) * i); memcpy(password, password_input, (size_t) i); memset(password_input, 0, (size_t) (i - 1)); return password; } /* * \brief prj_get_passphrase * * user interface for getting passphrase given by user on terminal * * \param count asking for passphrase one or two times * \param size maximum length of passphrase allowed * \param passphrase on success given passphrase is stored here, otherwise NULL * * \return on technical error -1, otherwise 0 */ int prj_get_passphrase(size_t count, size_t size, char **passphrase) { size_t j, x = 1; char *pass_first = NULL, *pass_second = NULL; size_t len_first = 0, len_second = 0; struct termios oldState, newState; if (tcgetattr(STDIN_FILENO, &oldState) == -1) { printf("\nError: could not hide terminal input!\n"); return -1; } newState = oldState; newState.c_lflag &= ~(ICANON | ECHO); if (tcsetattr(STDIN_FILENO, TCSANOW, &newState) == -1) { printf("\nError: could not hide terminal input!\n"); return -1; } if (count != 1) /* default is asking two times */ count = 2; retry: if (x > 3) /* three chances */ goto failed; if (x > 1) printf("Passphrase mismatch. Please try it again.\n\n"); x++; for (j = 0; j < count; j++) { if (j == 0) { printf("Please enter your passphrase: "); pass_first = prj_read_passphrase(size); } else { printf("Please re-enter your passphrase: "); pass_second = prj_read_passphrase(size); } printf("\n"); } if (pass_first == NULL) goto retry; len_first = strlen(pass_first); if (pass_first != NULL && pass_second != NULL && count == 2) { len_second = strlen(pass_second); if (len_first != len_second) goto retry; if (memcmp(pass_first, pass_second, len_first) != 0) goto retry; } len_first++; *passphrase = (char *) malloc(sizeof(char) * len_first); memcpy(*passphrase, pass_first, len_first); failed: if (tcsetattr(STDIN_FILENO, TCSANOW, &oldState) == -1) { printf("\nError: could not unhide terminal input!\n"); printf("\nPlease try to reset your terminal by typing command 'reset -x'\n"); } if (pass_first != NULL) { memset(pass_first, 0, len_first--); free(pass_first); } if (pass_second != NULL) { memset(pass_second, 0, len_second); free(pass_second); } return 0; }
Jetzt kann die Funktionen prj_get_passphrase() wie in diesem Beispiel verwendet werden (get_passphrase.c):
#include <stdlib.h> #include <string.h> #include <stdio.h> #include "passphrase.h" #define GPG_MAX_PASSPHRASE_LENGTH 100 /* ********************************************************************** */ int main(int argc, char *argv[]) { (void) argc; /* avoid compiler warnings */ (void) argv; char *passphrase = NULL; if (prj_get_passphrase(2, GPG_MAX_PASSPHRASE_LENGTH + 1, &passphrase) != 0) { printf("An error occured. Aborting.\n"); return 1; } if (passphrase == NULL) { printf("An error occured. Aborting.\n"); return 1; } printf("\nYour passphrase: '%s'\n", passphrase); memset(passphrase, 0, strlen(passphrase)); /* overwrite passphrase in memory */ free(passphrase); return 0; }
Danach kann wie gewohnt das Binary mit zum Beispiel gcc erstellt werden:
![]() |
gcc -Wall -Wextra -Werror -o get_passphrase passphrase.c get_passphrase.c |