From 1c6ddd721a938c98f0fd4404c4414b072b85e66b Mon Sep 17 00:00:00 2001 From: Umar Hayat Date: Wed, 4 Mar 2020 10:51:12 +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:password pairs from provide file and it will add user names and md5 hashed password values, in form user:md5xxxxxx, in pool_passwd file. This is usefull in scenarios where user can't your 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 | 101 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 127 insertions(+), 1 deletion(-) 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..08fa078 100644 --- a/src/tools/pgmd5/pg_md5.c +++ b/src/tools/pgmd5/pg_md5.c @@ -39,6 +39,7 @@ #endif #include #include +#include /* Maximum number of characters allowed for input. */ #define MAX_INPUT_SIZE MAX_USER_NAME_LEN @@ -46,6 +47,7 @@ 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); int main(int argc, char *argv[]) @@ -53,11 +55,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 +69,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 +81,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, "hpmfi:u:", long_options, &optindex)) != -1) { switch (opt) { @@ -96,6 +101,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 +129,12 @@ main(int argc, char *argv[]) break; } } + /* Use input file */ + if (use_input_file) + { + update_pool_passwd_from_file(conf_file, input_file); + return EXIT_SUCCESS; + } /* Prompt for password. */ if (prompt) @@ -190,6 +210,84 @@ main(int argc, char *argv[]) } static void +update_pool_passwd_from_file(char *conf_file, char *input_file) +{ + FILE *fp; + struct stat stat_buf; + + char buf[MAX_INPUT_SIZE + 1]; + char username[MAX_INPUT_SIZE + 1]; + char password[MAX_INPUT_SIZE + 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_INPUT_SIZE + 1); + memset(username, 0, MAX_INPUT_SIZE + 1); + memset(password, 0, MAX_INPUT_SIZE + 1); + + if (fgets(buf, sizeof(buf), fp) == NULL) + break; + + len = strlen(buf); + if (len == 0 || *buf == '\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 (!strlen(pch)) + { + fprintf(stderr, "invalid username:password pair at line:%d\n", line_count); + continue; + } + strncpy(username, buf, pch-buf); + strncpy(password, pch+1, strlen(pch+1)); + + update_pool_passwd(conf_file, username, password); + } + + fclose(fp); +} + +static void update_pool_passwd(char *conf_file, char *username, char *password) { struct passwd *pw; @@ -250,6 +348,7 @@ 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\ -- 2.8.1