From cee5807debf3f49ed520ed8cfe648e9254ac62a1 Mon Sep 17 00:00:00 2001 From: Franck Joncourt Date: Sat, 18 May 2013 10:54:44 +0200 Subject: [PATCH] First draft to be able to use stdin as an input for submitting fwknop key. mrash/fwknop#74 --- client/cmd_opts.h | 4 + client/config_init.c | 7 ++ client/fwknop.c | 12 +-- client/fwknop_common.h | 1 + client/getpasswd.c | 184 ++++++++++++++++++++++++----------------- client/getpasswd.h | 2 +- 6 files changed, 126 insertions(+), 84 deletions(-) diff --git a/client/cmd_opts.h b/client/cmd_opts.h index bd121951..68e0a720 100644 --- a/client/cmd_opts.h +++ b/client/cmd_opts.h @@ -58,6 +58,8 @@ enum { KEY_RIJNDAEL_BASE64, KEY_HMAC_BASE64, KEY_HMAC, + FD_SET_STDIN, + FD_SET, /* Put GPG-related items below the following line */ GPG_ENCRYPTION = 0x200, GPG_RECIP_KEY, @@ -88,6 +90,7 @@ static struct option cmd_opts[] = {"destination", 1, NULL, 'D'}, {"save-args-file", 1, NULL, 'E'}, {"encryption-mode", 1, NULL, ENCRYPTION_MODE}, + {"fd", 1, NULL, FD_SET}, {"fw-timeout", 1, NULL, 'f'}, {"gpg-encryption", 0, NULL, 'g'}, {"gpg-recipient-key", 1, NULL, GPG_RECIP_KEY }, @@ -125,6 +128,7 @@ static struct option cmd_opts[] = {"show-last", 0, NULL, SHOW_LAST_ARGS}, {"source-ip", 0, NULL, 's'}, {"source-port", 1, NULL, 'S'}, + {"stdin", 0, NULL, FD_SET_STDIN}, {"test", 0, NULL, 'T'}, {"time-offset-plus", 1, NULL, TIME_OFFSET_PLUS}, {"time-offset-minus", 1, NULL, TIME_OFFSET_MINUS}, diff --git a/client/config_init.c b/client/config_init.c index b2b736f8..220d24ec 100644 --- a/client/config_init.c +++ b/client/config_init.c @@ -1380,6 +1380,7 @@ set_defaults(fko_cli_options_t *options) options->spa_icmp_type = ICMP_ECHOREPLY; /* only used in '-P icmp' mode */ options->spa_icmp_code = 0; /* only used in '-P icmp' mode */ + options->input_fd = NULL; return; } @@ -1767,6 +1768,12 @@ config_init(fko_cli_options_t *options, int argc, char **argv) case FORCE_SAVE_RC_STANZA: options->force_save_rc_stanza = 1; break; + case FD_SET_STDIN: + options->input_fd = stdin; + break; + case FD_SET: + options->input_fd = stdin; + break; default: usage(); exit(EXIT_FAILURE); diff --git a/client/fwknop.c b/client/fwknop.c index 7e22c2c7..eb4c2f72 100644 --- a/client/fwknop.c +++ b/client/fwknop.c @@ -1168,7 +1168,7 @@ get_keys(fko_ctx_t ctx, fko_cli_options_t *options, { if(crypt_op == CRYPT_OP_DECRYPT) { - key_tmp = getpasswd("Enter passphrase for secret key: "); + key_tmp = getpasswd("Enter passphrase for secret key: ", options->input_fd); if(key_tmp == NULL) { log_msg(LOG_VERBOSITY_ERROR, "[*] getpasswd() key error."); @@ -1179,7 +1179,7 @@ get_keys(fko_ctx_t ctx, fko_cli_options_t *options, } else if(strlen(options->gpg_signer_key)) { - key_tmp = getpasswd("Enter passphrase for signing: "); + key_tmp = getpasswd("Enter passphrase for signing: ", options->input_fd); if(key_tmp == NULL) { log_msg(LOG_VERBOSITY_ERROR, "[*] getpasswd() key error."); @@ -1192,11 +1192,11 @@ get_keys(fko_ctx_t ctx, fko_cli_options_t *options, else { if(crypt_op == CRYPT_OP_ENCRYPT) - key_tmp = getpasswd("Enter encryption key: "); + key_tmp = getpasswd("Enter encryption key: ", options->input_fd); else if(crypt_op == CRYPT_OP_DECRYPT) - key_tmp = getpasswd("Enter decryption key: "); + key_tmp = getpasswd("Enter decryption key: ", options->input_fd); else - key_tmp = getpasswd("Enter key: "); + key_tmp = getpasswd("Enter key: ", options->input_fd); if(key_tmp == NULL) { @@ -1240,7 +1240,7 @@ get_keys(fko_ctx_t ctx, fko_cli_options_t *options, } else { - hmac_key_tmp = getpasswd("Enter HMAC key: "); + hmac_key_tmp = getpasswd("Enter HMAC key: ", options->input_fd); if(hmac_key_tmp == NULL) { diff --git a/client/fwknop_common.h b/client/fwknop_common.h index e2261fd4..90bb02f1 100644 --- a/client/fwknop_common.h +++ b/client/fwknop_common.h @@ -161,6 +161,7 @@ typedef struct fko_cli_options unsigned char save_rc_stanza; unsigned char force_save_rc_stanza; + FILE* input_fd; //char config_file[MAX_PATH_LEN]; } fko_cli_options_t; diff --git a/client/getpasswd.c b/client/getpasswd.c index 81e9a5ac..dc31d6cf 100644 --- a/client/getpasswd.c +++ b/client/getpasswd.c @@ -40,107 +40,135 @@ #include "fwknop_common.h" #include "getpasswd.h" -#define MAX_PASS_LEN 128 ///< Maximum number of chars an encryption key or a password can contain +#define PW_BUFSIZE 128 /*!< Maximum number of chars an encryption key or a password can contain */ -#define PW_BREAK_CHAR 0x03 ///< Ascii code for the Ctrl-C char -#define PW_BS_CHAR 0x08 ///< Ascii code for the backspace char -#define PW_LF_CHAR 0x0A ///< Ascii code for the \n char -#define PW_CR_CHAR 0x0D ///< Ascii code for the \r char -#define PW_CLEAR_CHAR 0x15 ///< Ascii code for the Ctrl-U char +/* TODO Wrong BS char 0x08 insteaf od 0x7F */ +#define PW_BREAK_CHAR 0x03 /*!< Ascii code for the Ctrl-C char */ +#define PW_BS_CHAR 0x08 /*!< Ascii code for the backspace char */ +#define PW_LF_CHAR 0x0A /*!< Ascii code for the \n char */ +#define PW_CR_CHAR 0x0D /*!< Ascii code for the \r char */ +#define PW_CLEAR_CHAR 0x15 /*!< Ascii code for the Ctrl-U char */ + +#define ARRAY_FIRST_ELT_ADR(t) &((t)[0]) /*!< Macro to get the first element of an array */ +#define ARRAY_LAST_ELT_ADR(t) &((t)[sizeof(t)-1]) /*!< Macro to get the last element of an array */ /** - * Function for accepting password input from users + * @brief Read a password from a file descriptor + * + * @param fd File descriptor to read the password from + * + * @return The password buffer or NULL if not set + */ +static char * +read_passwd_from_fd(FILE *fd) +{ + static char password[PW_BUFSIZE] = {0}; + int c; + char *ptr; + + /* TODO check fd validity */ + ptr = ARRAY_FIRST_ELT_ADR(password); + +#ifdef WIN32 + while((c = _getch()) != PW_CR_CHAR) +#else + while( ((c = getc(fd)) != EOF) && (c != PW_LF_CHAR) && (c != PW_BREAK_CHAR) ) +#endif + { + /* Handle a backspace without backing up too far. */ + if (c == PW_BS_CHAR) + { + if (ptr != ARRAY_FIRST_ELT_ADR(password)) + ptr--; + } + + /* Handle a Ctrl-U to clear the password entry and start over */ + else if (c == PW_CLEAR_CHAR) + ptr = ARRAY_FIRST_ELT_ADR(password); + + /* Fill in the password buffer until it reach the last -1 char. + * The last char is used to NULL terminate the string. */ + else if (ptr < ARRAY_LAST_ELT_ADR(password)) + { + *ptr++ = c; + } + + /* Discard char */ + else; + } + + /* A CTRL-C char has been detected, we discard the password */ + if (c == PW_BREAK_CHAR) + password[0] = '\0'; + + /* Otherwise we NULL terminate the string here. Overflows are handled + * previously, so we can add the char without worrying */ + else + *ptr = '\0'; + + return password; +} + +/** + * @brief Function for accepting password input from users * * The functions reads chars from the terminal and store them in a buffer of chars. * + * @param prompt String displayed on the terminal to prompt the user for a password + * or an encryption key + * @param fp File descriptor to use as terminal + * * @return NULL if a problem occured or the user killed the terminal (Ctrl-C)\n * otherwise the password - empty password is accepted. */ char* -getpasswd( - const char *prompt) ///< String displayed on the terminal to prompt the user for a password or an encryption key +getpasswd(const char *prompt, FILE *fp) { - static char pwbuf[MAX_KEY_LEN + 1] = {0}; - char *ptr; - int c; - + char *ptr; + #ifndef WIN32 - FILE *fp; sigset_t sig, old_sig; struct termios ts, old_ts; - if((fp = fopen(ctermid(NULL), "r+")) == NULL) - return(NULL); + if (fp == NULL) + { + if((fp = fopen(ctermid(NULL), "r+")) == NULL) + return(NULL); - setbuf(fp, NULL); + setbuf(fp, NULL); - /* Setup blocks for SIGINT and SIGTSTP and save the original signal - * mask. - */ - sigemptyset(&sig); - sigaddset(&sig, SIGINT); - sigaddset(&sig, SIGTSTP); - sigprocmask(SIG_BLOCK, &sig, &old_sig); + /* Setup blocks for SIGINT and SIGTSTP and save the original signal + * mask. + */ + sigemptyset(&sig); + sigaddset(&sig, SIGINT); + sigaddset(&sig, SIGTSTP); + sigprocmask(SIG_BLOCK, &sig, &old_sig); - /* - * Save current tty state for later restoration after we : - * - disable echo of characters to the tty - * - disable signal generation - * - disable cannonical mode (input read line by line mode) - */ - tcgetattr(fileno(fp), &ts); - old_ts = ts; - ts.c_lflag &= ~(ECHO | ICANON | ISIG); - tcsetattr(fileno(fp), TCSAFLUSH, &ts); + /* + * Save current tty state for later restoration after we : + * - disable echo of characters to the tty + * - disable signal generation + * - disable cannonical mode (input read line by line mode) + */ + tcgetattr(fileno(fp), &ts); + old_ts = ts; + ts.c_lflag &= ~(ECHO | ICANON | ISIG); + tcsetattr(fileno(fp), TCSAFLUSH, &ts); - fputs(prompt, fp); -#endif - - /* Read in the password. - */ - ptr = pwbuf; - -#ifdef WIN32 - _cputs(prompt); - while((c = _getch()) != PW_CR_CHAR) + fputs(prompt, fp); + } #else - while( ((c = getc(fp)) != EOF) && (c != PW_LF_CHAR) && (c != PW_BREAK_CHAR) ) + _cputs(prompt); #endif - { - /* Handle a backspace without backing up too far. - */ - if (c == PW_BS_CHAR) - { - if (ptr != pwbuf) - ptr--; - } - /* Handle a Ctrl-U to clear the password entry and start over - */ - else if (c == PW_CLEAR_CHAR) - ptr = pwbuf; - - /* Store data in the buffer and check for a possible overflow - */ - else if (ptr < &pwbuf[MAX_PASS_LEN]) - *ptr++ = c; - } - - /* If a Ctrl-C char has been detected we set an error - */ - if (c == PW_BREAK_CHAR) - ptr = NULL; - - /* Otherwise we make the password as a NULL terminated string and point - * to the start of the password in order to be returned by the function. - */ - else - { - *ptr = '\0'; - ptr = pwbuf; - } + /* Read the password */ + ptr = read_passwd_from_fd(fp); #ifndef WIN32 + + if (fp != stdin) + { /* we can go ahead and echo out a newline. */ putc(PW_LF_CHAR, fp); @@ -151,6 +179,7 @@ getpasswd( sigprocmask(SIG_BLOCK, &old_sig, NULL); fclose(fp); + } #else /* In Windows, it would be a CR-LF */ @@ -158,6 +187,7 @@ getpasswd( _putch(PW_LF_CHAR); #endif + printf("PAssword = %s\n",ptr); return (ptr); } diff --git a/client/getpasswd.h b/client/getpasswd.h index dc4c7f80..a185c137 100644 --- a/client/getpasswd.h +++ b/client/getpasswd.h @@ -33,7 +33,7 @@ /* Prototypes */ -char* getpasswd(const char *prompt); +char* getpasswd(const char *prompt, FILE* fp); /* This can be used to acquire an encryption key or HMAC key */