From 027811cdbe058d5cb83054e1a4de3eae63b69eb0 Mon Sep 17 00:00:00 2001 From: Artur Zakirov Date: Wed, 28 Feb 2024 15:29:38 +0100 Subject: [PATCH 1/3] Quote passwords in a connection string --- bin/pgut/pgut-fe.c | 4 ++-- bin/pgut/pgut.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bin/pgut/pgut-fe.c b/bin/pgut/pgut-fe.c index 8633ddac..1120226d 100644 --- a/bin/pgut/pgut-fe.c +++ b/bin/pgut/pgut-fe.c @@ -62,7 +62,7 @@ setup_workers(int num_workers) if (username && username[0]) appendStringInfo(&buf, "user=%s ", username); if (password && password[0]) - appendStringInfo(&buf, "password=%s ", password); + appendStringInfo(&buf, "password='%s' ", password); if (workers.conns == NULL) { @@ -168,7 +168,7 @@ reconnect(int elevel) if (username && username[0]) appendStringInfo(&buf, "user=%s ", username); if (password && password[0]) - appendStringInfo(&buf, "password=%s ", password); + appendStringInfo(&buf, "password='%s' ", password); connection = pgut_connect(buf.data, prompt_password, elevel); conn2 = pgut_connect(buf.data, prompt_password, elevel); diff --git a/bin/pgut/pgut.c b/bin/pgut/pgut.c index c4cfbab5..23a4594f 100644 --- a/bin/pgut/pgut.c +++ b/bin/pgut/pgut.c @@ -506,7 +506,7 @@ pgut_connect(const char *info, YesNo prompt, int elevel) passwd = prompt_for_password(); initStringInfo(&add_pass); appendStringInfoString(&add_pass, info); - appendStringInfo(&add_pass, " password=%s ", passwd); + appendStringInfo(&add_pass, " password='%s' ", passwd); } else { @@ -557,7 +557,7 @@ pgut_connect(const char *info, YesNo prompt, int elevel) else initStringInfo(&add_pass); appendStringInfoString(&add_pass, info); - appendStringInfo(&add_pass, " password=%s ", passwd); + appendStringInfo(&add_pass, " password='%s' ", passwd); continue; } From 135df8b6a6a3b145439315b18539e583cf9fec5c Mon Sep 17 00:00:00 2001 From: Artur Zakirov Date: Thu, 11 Apr 2024 15:08:58 +0200 Subject: [PATCH 2/3] Use `PQconnectdbParams()` instead of `PQconnectdb()` --- bin/pgut/pgut-fe.c | 49 ++++++++++++++++++++----------------- bin/pgut/pgut.c | 61 ++++++++++++++++++++++------------------------ bin/pgut/pgut.h | 4 ++- 3 files changed, 58 insertions(+), 56 deletions(-) diff --git a/bin/pgut/pgut-fe.c b/bin/pgut/pgut-fe.c index 1120226d..15e9821c 100644 --- a/bin/pgut/pgut-fe.c +++ b/bin/pgut/pgut-fe.c @@ -44,7 +44,6 @@ static bool parse_pair(const char buffer[], char key[], char value[]); void setup_workers(int num_workers) { - StringInfoData buf; int i; PGconn *conn; @@ -52,17 +51,23 @@ setup_workers(int num_workers) if (num_workers > 1 && num_workers > workers.num_workers) { - initStringInfo(&buf); - if (dbname && dbname[0]) - appendStringInfo(&buf, "dbname=%s ", dbname); - if (host && host[0]) - appendStringInfo(&buf, "host=%s ", host); - if (port && port[0]) - appendStringInfo(&buf, "port=%s ", port); - if (username && username[0]) - appendStringInfo(&buf, "user=%s ", username); - if (password && password[0]) - appendStringInfo(&buf, "password='%s' ", password); +#define PARAMS_ARRAY_SIZE 6 + + const char *keywords[PARAMS_ARRAY_SIZE]; + const char *values[PARAMS_ARRAY_SIZE]; + + keywords[0] = "host"; + values[0] = host; + keywords[1] = "port"; + values[1] = port; + keywords[2] = "user"; + values[2] = username; + keywords[3] = "password"; + values[3] = password; + keywords[4] = "dbname"; + values[4] = dbname; + keywords[5] = NULL; + values[5] = NULL; if (workers.conns == NULL) { @@ -86,11 +91,11 @@ setup_workers(int num_workers) * XXX: could use PQconnectStart() and PQconnectPoll() to * open these connections in non-blocking manner. */ - conn = PQconnectdb(buf.data); - if (PQstatus(conn) == CONNECTION_OK) - { - workers.conns[i] = conn; - } + conn = PQconnectdbParams(keywords, values, true); + if (PQstatus(conn) == CONNECTION_OK) + { + workers.conns[i] = conn; + } else { elog(WARNING, "Unable to set up worker conn #%d: %s", i, @@ -113,10 +118,8 @@ setup_workers(int num_workers) /* In case we bailed out of setting up all workers, record * how many successful worker conns we actually have. */ - workers.num_workers = i; - - termStringInfo(&buf); - } + workers.num_workers = i; + } } /* Disconnect all our worker conns. */ @@ -170,8 +173,8 @@ reconnect(int elevel) if (password && password[0]) appendStringInfo(&buf, "password='%s' ", password); - connection = pgut_connect(buf.data, prompt_password, elevel); - conn2 = pgut_connect(buf.data, prompt_password, elevel); + connection = pgut_connect(dbname, host, port, username, password, prompt_password, elevel); + conn2 = pgut_connect(dbname, host, port, username, password, prompt_password, elevel); /* update password */ if (connection) diff --git a/bin/pgut/pgut.c b/bin/pgut/pgut.c index 23a4594f..db72a978 100644 --- a/bin/pgut/pgut.c +++ b/bin/pgut/pgut.c @@ -496,34 +496,40 @@ prompt_for_password(void) PGconn * -pgut_connect(const char *info, YesNo prompt, int elevel) +pgut_connect(const char *dbname, const char *host, const char *port, + const char *username, const char *password, + YesNo prompt, int elevel) { - char *passwd; - StringInfoData add_pass; + char *new_password = NULL; if (prompt == YES) - { - passwd = prompt_for_password(); - initStringInfo(&add_pass); - appendStringInfoString(&add_pass, info); - appendStringInfo(&add_pass, " password='%s' ", passwd); - } - else - { - passwd = NULL; - add_pass.data = NULL; - } + new_password = prompt_for_password(); /* Start the connection. Loop until we have a password if requested by backend. */ for (;;) { +#define PARAMS_ARRAY_SIZE 6 + + const char *keywords[PARAMS_ARRAY_SIZE]; + const char *values[PARAMS_ARRAY_SIZE]; PGconn *conn; + CHECK_FOR_INTERRUPTS(); - if (!passwd) - conn = PQconnectdb(info); - else - conn = PQconnectdb(add_pass.data); + keywords[0] = "host"; + values[0] = host; + keywords[1] = "port"; + values[1] = port; + keywords[2] = "user"; + values[2] = username; + keywords[3] = "password"; + values[3] = (new_password != NULL) ? new_password : password; + keywords[4] = "dbname"; + values[4] = dbname; + keywords[5] = NULL; + values[5] = NULL; + + conn = PQconnectdbParams(keywords, values, true); if (PQstatus(conn) == CONNECTION_OK) { @@ -538,9 +544,7 @@ pgut_connect(const char *info, YesNo prompt, int elevel) pgut_connections = c; pgut_conn_unlock(); - if (add_pass.data != NULL) - termStringInfo(&add_pass); - free(passwd); + free(new_password); /* Hardcode a search path to avoid injections into public or pg_temp */ pgut_command(conn, "SET search_path TO pg_catalog, pg_temp, public", 0, NULL); @@ -548,22 +552,15 @@ pgut_connect(const char *info, YesNo prompt, int elevel) return conn; } - if (conn && PQconnectionNeedsPassword(conn) && !passwd && prompt != NO) + if (conn && PQconnectionNeedsPassword(conn) && !new_password && prompt != NO) { PQfinish(conn); - passwd = prompt_for_password(); - if (add_pass.data != NULL) - resetStringInfo(&add_pass); - else - initStringInfo(&add_pass); - appendStringInfoString(&add_pass, info); - appendStringInfo(&add_pass, " password='%s' ", passwd); + new_password = prompt_for_password(); + continue; } - if (add_pass.data != NULL) - termStringInfo(&add_pass); - free(passwd); + free(new_password); ereport(elevel, (errcode(E_PG_CONNECT), diff --git a/bin/pgut/pgut.h b/bin/pgut/pgut.h index 9253855b..24895c98 100644 --- a/bin/pgut/pgut.h +++ b/bin/pgut/pgut.h @@ -61,7 +61,9 @@ extern void pgut_putenv(const char *key, const char *value); /* * Database connections */ -extern PGconn *pgut_connect(const char *info, YesNo prompt, int elevel); +extern PGconn *pgut_connect(const char *dbname, const char *host, const char *port, + const char *username, const char *password, + YesNo prompt, int elevel); extern void pgut_disconnect(PGconn *conn); extern void pgut_disconnect_all(void); extern PGresult *pgut_execute(PGconn* conn, const char *query, int nParams, const char **params); From 733adbcf44ab2985387f0b8c06344c62e309fa18 Mon Sep 17 00:00:00 2001 From: Artur Zakirov Date: Thu, 11 Apr 2024 16:03:54 +0200 Subject: [PATCH 3/3] Delete unnecessary StringInfo --- bin/pgut/pgut-fe.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/bin/pgut/pgut-fe.c b/bin/pgut/pgut-fe.c index 15e9821c..b47b1bbf 100644 --- a/bin/pgut/pgut-fe.c +++ b/bin/pgut/pgut-fe.c @@ -157,21 +157,9 @@ void disconnect_workers(void) void reconnect(int elevel) { - StringInfoData buf; char *new_password; disconnect(); - initStringInfo(&buf); - if (dbname && dbname[0]) - appendStringInfo(&buf, "dbname=%s ", dbname); - if (host && host[0]) - appendStringInfo(&buf, "host=%s ", host); - if (port && port[0]) - appendStringInfo(&buf, "port=%s ", port); - if (username && username[0]) - appendStringInfo(&buf, "user=%s ", username); - if (password && password[0]) - appendStringInfo(&buf, "password='%s' ", password); connection = pgut_connect(dbname, host, port, username, password, prompt_password, elevel); conn2 = pgut_connect(dbname, host, port, username, password, prompt_password, elevel); @@ -187,8 +175,6 @@ reconnect(int elevel) password = pgut_strdup(new_password); } } - - termStringInfo(&buf); } void