From 4192f2d85a8946cbbe890217ee740d33c04f3761 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Tue, 11 Dec 2007 02:31:49 +0000 Subject: [PATCH] Remove the -P options of oid2name and pgbench, as they are security hazards. Instead teach these programs to prompt for a password when necessary, just like all our other programs. I did not bother to invent -W switches for them, since the return on investment seems so low. --- contrib/oid2name/oid2name.c | 67 +++++++++++++++++++++------------- contrib/pgbench/pgbench.c | 72 ++++++++++++++++++++++--------------- doc/src/sgml/oid2name.sgml | 8 +---- doc/src/sgml/pgbench.sgml | 7 +--- 4 files changed, 88 insertions(+), 66 deletions(-) diff --git a/contrib/oid2name/oid2name.c b/contrib/oid2name/oid2name.c index 3577979887..86c2ead377 100644 --- a/contrib/oid2name/oid2name.c +++ b/contrib/oid2name/oid2name.c @@ -4,7 +4,8 @@ * * Originally by * B. Palmer, bpalmer@crimelabs.net 1-17-2001 - * $PostgreSQL: pgsql/contrib/oid2name/oid2name.c,v 1.32 2007/07/25 22:16:17 tgl Exp $ + * + * $PostgreSQL: pgsql/contrib/oid2name/oid2name.c,v 1.33 2007/12/11 02:31:49 tgl Exp $ */ #include "postgres_fe.h" @@ -43,7 +44,6 @@ struct options char *hostname; char *port; char *username; - char *password; }; /* function prototypes */ @@ -76,10 +76,9 @@ get_opts(int argc, char **argv, struct options * my_opts) my_opts->hostname = NULL; my_opts->port = NULL; my_opts->username = NULL; - my_opts->password = NULL; /* get opts */ - while ((c = getopt(argc, argv, "H:p:U:P:d:t:o:f:qSxish?")) != -1) + while ((c = getopt(argc, argv, "H:p:U:d:t:o:f:qSxish?")) != -1) { switch (c) { @@ -123,11 +122,6 @@ get_opts(int argc, char **argv, struct options * my_opts) my_opts->username = mystrdup(optarg); break; - /* password */ - case 'P': - my_opts->password = mystrdup(optarg); - break; - /* display system tables */ case 'S': my_opts->systables = true; @@ -166,8 +160,6 @@ get_opts(int argc, char **argv, struct options * my_opts) " -H host connect to remote host\n" " -p port host port to connect to\n" " -U username username to connect with\n" - " -P password password for username\n" - " (see also $PGPASSWORD and ~/.pgpass)\n" ); exit(1); break; @@ -275,22 +267,49 @@ PGconn * sql_conn(struct options * my_opts) { PGconn *conn; + char *password = NULL; + bool new_pass; - /* login */ - conn = PQsetdbLogin(my_opts->hostname, - my_opts->port, - NULL, /* options */ - NULL, /* tty */ - my_opts->dbname, - my_opts->username, - my_opts->password); - - /* deal with errors */ - if (PQstatus(conn) != CONNECTION_OK) + /* + * Start the connection. Loop until we have a password if requested by + * backend. + */ + do { - fprintf(stderr, "%s: connection to database '%s' failed.\n", "oid2name", my_opts->dbname); - fprintf(stderr, "%s", PQerrorMessage(conn)); + new_pass = false; + conn = PQsetdbLogin(my_opts->hostname, + my_opts->port, + NULL, /* options */ + NULL, /* tty */ + my_opts->dbname, + my_opts->username, + password); + if (!conn) + { + fprintf(stderr, "%s: could not connect to database %s\n", + "oid2name", my_opts->dbname); + exit(1); + } + if (PQstatus(conn) == CONNECTION_BAD && + PQconnectionNeedsPassword(conn) && + password == NULL && + !feof(stdin)) + { + PQfinish(conn); + password = simple_prompt("Password: ", 100, false); + new_pass = true; + } + } while (new_pass); + + if (password) + free(password); + + /* check to see that the backend connection was successfully made */ + if (PQstatus(conn) == CONNECTION_BAD) + { + fprintf(stderr, "%s: could not connect to database %s: %s", + "oid2name", my_opts->dbname, PQerrorMessage(conn)); PQfinish(conn); exit(1); } diff --git a/contrib/pgbench/pgbench.c b/contrib/pgbench/pgbench.c index 5fe48b96a3..ce35bd3dff 100644 --- a/contrib/pgbench/pgbench.c +++ b/contrib/pgbench/pgbench.c @@ -1,5 +1,5 @@ /* - * $PostgreSQL: pgsql/contrib/pgbench/pgbench.c,v 1.74 2007/11/15 21:14:31 momjian Exp $ + * $PostgreSQL: pgsql/contrib/pgbench/pgbench.c,v 1.75 2007/12/11 02:31:49 tgl Exp $ * * pgbench: a simple benchmark program for PostgreSQL * written by Tatsuo Ishii @@ -94,7 +94,6 @@ char *pgport = ""; char *pgoptions = NULL; char *pgtty = NULL; char *login = NULL; -char *pwd = NULL; char *dbName; /* variable definitions */ @@ -188,8 +187,8 @@ static char *select_only = { static void usage(void) { - fprintf(stderr, "usage: pgbench [-h hostname][-p port][-c nclients][-t ntransactions][-s scaling_factor][-D varname=value][-n][-C][-v][-S][-N][-f filename][-l][-U login][-P password][-d][dbname]\n"); - fprintf(stderr, "(initialize mode): pgbench -i [-h hostname][-p port][-s scaling_factor] [-F fillfactor] [-U login][-P password][-d][dbname]\n"); + fprintf(stderr, "usage: pgbench [-h hostname][-p port][-c nclients][-t ntransactions][-s scaling_factor][-D varname=value][-n][-C][-v][-S][-N][-f filename][-l][-U login][-d][dbname]\n"); + fprintf(stderr, "(initialize mode): pgbench -i [-h hostname][-p port][-s scaling_factor] [-F fillfactor] [-U login][-d][dbname]\n"); } /* random number generator */ @@ -218,32 +217,50 @@ executeStatement(PGconn *con, const char *sql) static PGconn * doConnect(void) { - PGconn *con; + PGconn *conn; + static char *password = NULL; + bool new_pass; - con = PQsetdbLogin(pghost, pgport, pgoptions, pgtty, dbName, - login, pwd); - if (con == NULL) + /* + * Start the connection. Loop until we have a password if requested by + * backend. + */ + do { - fprintf(stderr, "Connection to database '%s' failed.\n", dbName); - fprintf(stderr, "Memory allocatin problem?\n"); - return (NULL); + new_pass = false; + + conn = PQsetdbLogin(pghost, pgport, pgoptions, pgtty, dbName, + login, password); + if (!conn) + { + fprintf(stderr, "Connection to database \"%s\" failed\n", + dbName); + return NULL; + } + + if (PQstatus(conn) == CONNECTION_BAD && + PQconnectionNeedsPassword(conn) && + password == NULL && + !feof(stdin)) + { + PQfinish(conn); + password = simple_prompt("Password: ", 100, false); + new_pass = true; + } + } while (new_pass); + + /* check to see that the backend connection was successfully made */ + if (PQstatus(conn) == CONNECTION_BAD) + { + fprintf(stderr, "Connection to database \"%s\" failed:\n%s", + dbName, PQerrorMessage(conn)); + PQfinish(conn); + return NULL; } - if (PQstatus(con) == CONNECTION_BAD) - { - fprintf(stderr, "Connection to database '%s' failed.\n", dbName); + executeStatement(conn, "SET search_path = public"); - if (PQerrorMessage(con)) - fprintf(stderr, "%s", PQerrorMessage(con)); - else - fprintf(stderr, "No explanation from the backend\n"); - - return (NULL); - } - - executeStatement(con, "SET search_path = public"); - - return (con); + return conn; } /* throw away response from backend */ @@ -1258,7 +1275,7 @@ main(int argc, char **argv) memset(state, 0, sizeof(*state)); - while ((c = getopt(argc, argv, "ih:nvp:dc:t:s:U:P:CNSlf:D:F:")) != -1) + while ((c = getopt(argc, argv, "ih:nvp:dc:t:s:U:CNSlf:D:F:")) != -1) { switch (c) { @@ -1333,9 +1350,6 @@ main(int argc, char **argv) case 'U': login = optarg; break; - case 'P': - pwd = optarg; - break; case 'l': use_log = true; break; diff --git a/doc/src/sgml/oid2name.sgml b/doc/src/sgml/oid2name.sgml index eb91827c7b..d2ab3f4c22 100644 --- a/doc/src/sgml/oid2name.sgml +++ b/doc/src/sgml/oid2name.sgml @@ -1,4 +1,4 @@ - + oid2name @@ -110,12 +110,6 @@ -U username username to connect as - - - -P password - password (deprecated — putting this on the command line - is a security hazard) - diff --git a/doc/src/sgml/pgbench.sgml b/doc/src/sgml/pgbench.sgml index be089f8836..61d159e6d8 100644 --- a/doc/src/sgml/pgbench.sgml +++ b/doc/src/sgml/pgbench.sgml @@ -1,4 +1,4 @@ - + pgbench @@ -282,11 +282,6 @@ pgbench options dbname -U login username to connect as - - -P password - password (deprecated — putting this on the command line - is a security hazard) -