From 282e77e18488033438276f17db2c1ba76efc16cc Mon Sep 17 00:00:00 2001 From: Umar Hayat Date: Thu, 5 Mar 2020 01:24:33 +0500 Subject: [PATCH] Add support for an user/password input file to pg_md5 A new --input-file option added in pg_md5. Using this option, pg_md5 will parse the user name:password pairs from provide file and it will add user names and md5 hashed password values in pool_passwd file. This is usefull in scenarios where user cannot use password prompt or avoid providing password as command paramater ( due to security risks ) --- doc/src/sgml/ref/pg_md5.sgml | 27 +++++++++ src/tools/pgmd5/pg_md5.c | 127 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 152 insertions(+), 2 deletions(-) diff --git a/doc/src/sgml/ref/pg_md5.sgml b/doc/src/sgml/ref/pg_md5.sgml index b02c24f..a121ac7 100644 --- a/doc/src/sgml/ref/pg_md5.sgml +++ b/doc/src/sgml/ref/pg_md5.sgml @@ -86,6 +86,16 @@ Pgpool-II documentation + + + + + + Specifies file containing user name and password pairs. + + + + @@ -118,6 +128,23 @@ Pgpool-II documentation $ cat /path/to/pool_passwd username:md55a231fcdb710d73268c4f44283487ba2 + + To avoid password prompt or password in command parameter, + pg_md5 can read user name:password pairs from file. + It will add all user names and md5 hashed password to + authentication file. + + $ cat users.txt + username1:secretpassword1 + username2:secretpassword1 + + $ pg_md5 -m -f /path/to/pgpool.conf -i users.txt + + $ cat /path/to/pool_passwd + username1:md533314126ba0b187df1e37f5ce6a489a8 + username2:md58ae92c6e1d6a48d80e2583fe715e2b36 + + To just display the md5 hashed string, not adding an entry to , pass a string concatenating password and user name. For example, if password is "password" and user name is "user", the output would be: diff --git a/src/tools/pgmd5/pg_md5.c b/src/tools/pgmd5/pg_md5.c index cf37e89..e79b981 100644 --- a/src/tools/pgmd5/pg_md5.c +++ b/src/tools/pgmd5/pg_md5.c @@ -39,13 +39,16 @@ #endif #include #include +#include /* Maximum number of characters allowed for input. */ #define MAX_INPUT_SIZE MAX_USER_NAME_LEN +#define MAX_BUFFER_SIZE MAX_INPUT_SIZE + 1 + MAX_INPUT_SIZE static void print_usage(const char prog[], int exit_code); static void set_tio_attr(int enable); static void update_pool_passwd(char *conf_file, char *username, char *password); +static void update_pool_passwd_from_file(char *conf_file, char *input_file, bool md5auth); int main(int argc, char *argv[]) @@ -53,11 +56,13 @@ main(int argc, char *argv[]) #define PRINT_USAGE(exit_code) print_usage(argv[0], exit_code) char conf_file[POOLMAXPATHLEN + 1]; + char input_file[POOLMAXPATHLEN + 1]; char username[MAX_INPUT_SIZE + 1]; int opt; int optindex; bool md5auth = false; bool prompt = false; + bool use_input_file = false; static struct option long_options[] = { {"help", no_argument, NULL, 'h'}, @@ -65,6 +70,7 @@ main(int argc, char *argv[]) {"md5auth", no_argument, NULL, 'm'}, {"username", required_argument, NULL, 'u'}, {"config-file", required_argument, NULL, 'f'}, + {"input-file", required_argument, NULL, 'i'}, {NULL, 0, NULL, 0} }; @@ -76,7 +82,7 @@ main(int argc, char *argv[]) */ memset(username, 0, MAX_INPUT_SIZE + 1); - while ((opt = getopt_long(argc, argv, "hpmf:u:", long_options, &optindex)) != -1) + while ((opt = getopt_long(argc, argv, "hpmf:i:u:", long_options, &optindex)) != -1) { switch (opt) { @@ -96,6 +102,15 @@ main(int argc, char *argv[]) strlcpy(conf_file, optarg, sizeof(conf_file)); break; + case 'i': /* specify users password input file */ + if (!optarg) + { + PRINT_USAGE(EXIT_SUCCESS); + } + strlcpy(input_file, optarg, sizeof(input_file)); + use_input_file = true; + break; + case 'u': if (!optarg) { @@ -115,6 +130,12 @@ main(int argc, char *argv[]) break; } } + /* Use input file */ + if (use_input_file) + { + update_pool_passwd_from_file(conf_file, input_file, md5auth); + return EXIT_SUCCESS; + } /* Prompt for password. */ if (prompt) @@ -190,6 +211,107 @@ main(int argc, char *argv[]) } static void +update_pool_passwd_from_file(char *conf_file, char *input_file, bool md5auth) +{ + FILE *fp; + struct stat stat_buf; + + char buf[MAX_BUFFER_SIZE + 1]; + char username[MAX_INPUT_SIZE + 1]; + char password[MAX_INPUT_SIZE + 1]; + char md5[MD5_PASSWD_LEN + 1]; + char *pch; + int len; + int line_count; + + if (strlen(input_file) == 0) + { + fprintf(stderr, "input_file is emptry\n\n"); + exit(EXIT_FAILURE); + } + + if (stat(input_file, &stat_buf) != 0) + { + fprintf(stderr, "input_file \"%s\" cannot be opened. Check file permissions\n\n", input_file); + exit(EXIT_FAILURE); + } + + if (!S_ISREG(stat_buf.st_mode)) + { + fprintf(stderr, "input_file \"%s\" is not a plain file\n\n", input_file); + exit(EXIT_FAILURE); + } + + fp = fopen(input_file, "r"); + if (fp == NULL) + { + fprintf(stderr, "input_file \"%s\" cannot be opened\n\n", input_file); + exit(EXIT_FAILURE); + } + + line_count = 0; + while (!feof(fp) && !ferror(fp)) + { + line_count++; + + memset(buf, 0, MAX_BUFFER_SIZE + 1); + memset(username, 0, MAX_INPUT_SIZE + 1); + memset(password, 0, MAX_INPUT_SIZE + 1); + + if (fgets(buf, sizeof(buf), fp) == NULL) + break; + fprintf(stdout, "LINE#%02d: ", line_count); + len = strlen(buf); + if (len == 0 || *buf == '\n') + { + fprintf(stdout, "BLANK LINE\n"); + continue; + } + + /* Remove trailing newline */ + if (buf[len - 1] == '\n') + buf[len - 1] = 0; + + /* Split username and passwords */ + pch = buf; + while( pch && pch != buf + len && *pch != ':') + pch++; + if (*pch == ':') + pch++; + + if (!strlen(pch)) + { + fprintf(stdout, "Invalid username:password pair\n"); + continue; + } + + if( (pch-buf) > sizeof(username)) + { + fprintf(stdout, "Input exceeds maximum username length!\n"); + continue; + } + strncpy(username, buf, pch-buf-1); + + if (strlen(pch) >= sizeof(password)) + { + fprintf(stdout, "Input exceeds maximum password length given:%d max allowed:%d!\n", (int)strlen(pch), MAX_PGPASS_LEN); + continue; + } + strncpy(password, pch, strlen(pch)); + + fprintf(stdout, "USER: <%s>\n", username); + if(md5auth) + update_pool_passwd(conf_file, username, password); + else + { + pool_md5_hash(password, strlen(password), md5); + printf("%s\n", md5); + } + } + fclose(fp); +} + +static void update_pool_passwd(char *conf_file, char *username, char *password) { struct passwd *pw; @@ -250,12 +372,13 @@ print_usage(const char prog[], int exit_code) --username, -u USER When producing a md5 authentication password,\n\ create the pool_passwd entry for USER.\n\ --config-file, -f CONFIG-FILE Specify pgpool.conf.\n\ + --input-file, -i INPUT-FILE Specify file containing username and password pairs.\n\ --help, -h This help menu.\n\ \n\ Warning: At most %d characters are allowed for input.\n\ Warning: Plain password argument is deprecated for security concerns\n\ and kept for compatibility. Please prefer using password\n\ - prompt.\n", + prompt or input file method.\n", prog, prog, MAX_INPUT_SIZE); exit(exit_code); -- 2.8.1