From: Cody Cutrer Date: Wed, 28 Aug 2013 02:47:44 +0000 (-0600) Subject: fix reconnects of auth_user dbs after online restart X-Git-Tag: pgbouncer_1_6_rc1~21^2~2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e21c127a8dbfeab21cacdb3647d8ae058deeb488;p=pgbouncer fix reconnects of auth_user dbs after online restart if the user was a dynamic user, the only way the bouncer knows the password was from a new client connection. if an existing client starts a transaction before a new client connects, it will not know the correct password. so pass that info along in the online restart data. note that this is backwards compatible - old bouncers just won't send the password, and it's stuck until the client tries to connect --- diff --git a/include/client.h b/include/client.h index 3253532..911e3f1 100644 --- a/include/client.h +++ b/include/client.h @@ -17,5 +17,5 @@ */ bool client_proto(SBuf *sbuf, SBufEvent evtype, struct MBuf *pkt) _MUSTCHECK; -bool set_pool(PgSocket *client, const char *dbname, const char *username, bool takeover) _MUSTCHECK; +bool set_pool(PgSocket *client, const char *dbname, const char *username, const char *password, bool takeover) _MUSTCHECK; bool handle_auth_response(PgSocket *client, PktHdr *pkt); diff --git a/include/objects.h b/include/objects.h index 3735565..b4a91a6 100644 --- a/include/objects.h +++ b/include/objects.h @@ -53,10 +53,12 @@ void forward_cancel_request(PgSocket *server); void launch_new_connection(PgPool *pool); bool use_client_socket(int fd, PgAddr *addr, const char *dbname, const char *username, uint64_t ckey, int oldfd, int linkfd, - const char *client_end, const char *std_string, const char *datestyle, const char *timezone) + const char *client_end, const char *std_string, const char *datestyle, const char *timezone, + const char *password) _MUSTCHECK; bool use_server_socket(int fd, PgAddr *addr, const char *dbname, const char *username, uint64_t ckey, int oldfd, int linkfd, - const char *client_end, const char *std_string, const char *datestyle, const char *timezone) + const char *client_end, const char *std_string, const char *datestyle, const char *timezone, + const char *password) _MUSTCHECK; void activate_client(PgSocket *client); diff --git a/src/admin.c b/src/admin.c index 945669a..cfe7df9 100644 --- a/src/admin.c +++ b/src/admin.c @@ -244,7 +244,8 @@ static bool send_one_fd(PgSocket *admin, const char *client_enc, const char *std_strings, const char *datestyle, - const char *timezone) + const char *timezone, + const char *password) { struct msghdr msg; struct cmsghdr *cmsg; @@ -254,9 +255,10 @@ static bool send_one_fd(PgSocket *admin, struct PktBuf *pkt = pktbuf_temp(); - pktbuf_write_DataRow(pkt, "issssiqissss", + pktbuf_write_DataRow(pkt, "issssiqisssss", fd, task, user, db, addr, port, ckey, link, - client_enc, std_strings, datestyle, timezone); + client_enc, std_strings, datestyle, timezone, + password); if (pkt->failed) return false; iovec.iov_base = pkt->buf; @@ -306,11 +308,14 @@ static bool show_one_fd(PgSocket *admin, PgSocket *sk) const struct PStr *datestyle = v->var_list[VDateStyle]; const struct PStr *timezone = v->var_list[VTimeZone]; char addrbuf[PGADDR_BUF]; + const char *password = NULL; mbuf_init_fixed_reader(&tmp, sk->cancel_key, 8); if (!mbuf_get_uint64be(&tmp, &ckey)) return false; + if (sk->pool->db->auth_user && sk->auth_user && !find_user(sk->auth_user->name)) + password = sk->auth_user->passwd; return send_one_fd(admin, sbuf_socket(&sk->sbuf), is_server_socket(sk) ? "server" : "client", @@ -323,7 +328,8 @@ static bool show_one_fd(PgSocket *admin, PgSocket *sk) client_encoding ? client_encoding->str : NULL, std_strings ? std_strings->str : NULL, datestyle ? datestyle->str : NULL, - timezone ? timezone->str : NULL); + timezone ? timezone->str : NULL, + password); } static bool show_pooler_cb(void *arg, int fd, const PgAddr *a) @@ -332,7 +338,7 @@ static bool show_pooler_cb(void *arg, int fd, const PgAddr *a) return send_one_fd(arg, fd, "pooler", NULL, NULL, pga_ntop(a, buf, sizeof(buf)), pga_port(a), 0, 0, - NULL, NULL, NULL, NULL); + NULL, NULL, NULL, NULL, NULL); } /* send a row with sendmsg, optionally attaching a fd */ @@ -384,6 +390,7 @@ static bool admin_show_fds(PgSocket *admin, const char *arg) * Dangerous to show to everybody: * - can lock pooler as code flips async option * - show cancel keys for all users + * - shows passwords (md5) for dynamic users */ if (!admin->admin_user) return admin_error(admin, "admin access needed"); @@ -397,13 +404,13 @@ static bool admin_show_fds(PgSocket *admin, const char *arg) /* * send resultset */ - SEND_RowDescription(res, admin, "issssiqissss", + SEND_RowDescription(res, admin, "issssiqisssss", "fd", "task", "user", "database", "addr", "port", "cancel", "link", "client_encoding", "std_strings", - "datestyle", "timezone"); + "datestyle", "timezone", "password"); if (res) res = show_pooler_fds(admin); diff --git a/src/client.c b/src/client.c index 66bb46e..d8bc5f2 100644 --- a/src/client.c +++ b/src/client.c @@ -157,7 +157,7 @@ static bool finish_set_pool(PgSocket *client, bool takeover) return true; } -bool set_pool(PgSocket *client, const char *dbname, const char *username, bool takeover) +bool set_pool(PgSocket *client, const char *dbname, const char *username, const char *password, bool takeover) { /* find database */ client->db = find_database(dbname); @@ -199,7 +199,7 @@ bool set_pool(PgSocket *client, const char *dbname, const char *username, bool t client->auth_user = find_user(username); if (!client->auth_user && client->db->auth_user) { if (takeover) { - client->auth_user = add_db_user(client->db, username, ""); + client->auth_user = add_db_user(client->db, username, password); return finish_set_pool(client, takeover); } start_auth_request(client, username); @@ -350,7 +350,7 @@ static bool decide_startup_pool(PgSocket *client, PktHdr *pkt) } /* find pool */ - return set_pool(client, dbname, username, false); + return set_pool(client, dbname, username, "", false); } /* decide on packets of client in login phase */ diff --git a/src/objects.c b/src/objects.c index 1e718c5..fe9865a 100644 --- a/src/objects.c +++ b/src/objects.c @@ -1188,7 +1188,8 @@ bool use_client_socket(int fd, PgAddr *addr, const char *dbname, const char *username, uint64_t ckey, int oldfd, int linkfd, const char *client_enc, const char *std_string, - const char *datestyle, const char *timezone) + const char *datestyle, const char *timezone, + const char *password) { PgSocket *client; PktBuf tmp; @@ -1198,7 +1199,7 @@ bool use_client_socket(int fd, PgAddr *addr, return false; client->suspended = 1; - if (!set_pool(client, dbname, username, true)) + if (!set_pool(client, dbname, username, password, true)) return false; change_client_state(client, CL_ACTIVE); @@ -1223,7 +1224,8 @@ bool use_server_socket(int fd, PgAddr *addr, const char *dbname, const char *username, uint64_t ckey, int oldfd, int linkfd, const char *client_enc, const char *std_string, - const char *datestyle, const char *timezone) + const char *datestyle, const char *timezone, + const char *password) { PgDatabase *db = find_database(dbname); PgUser *user; @@ -1244,7 +1246,7 @@ bool use_server_socket(int fd, PgAddr *addr, else user = find_user(username); if (!user && db->auth_user) - user = add_db_user(db, username, ""); + user = add_db_user(db, username, password); pool = get_pool(db, user); if (!pool) diff --git a/src/takeover.c b/src/takeover.c index e34d74e..18a384d 100644 --- a/src/takeover.c +++ b/src/takeover.c @@ -79,7 +79,7 @@ static void takeover_load_fd(struct MBuf *pkt, const struct cmsghdr *cmsg) { int fd; char *task, *saddr, *user, *db; - char *client_enc, *std_string, *datestyle, *timezone; + char *client_enc, *std_string, *datestyle, *timezone, *password; int oldfd, port, linkfd; int got; uint64_t ckey; @@ -99,9 +99,10 @@ static void takeover_load_fd(struct MBuf *pkt, const struct cmsghdr *cmsg) fatal("broken fd packet"); /* parse row contents */ - got = scan_text_result(pkt, "issssiqissss", &oldfd, &task, &user, &db, + got = scan_text_result(pkt, "issssiqisssss", &oldfd, &task, &user, &db, &saddr, &port, &ckey, &linkfd, - &client_enc, &std_string, &datestyle, &timezone); + &client_enc, &std_string, &datestyle, &timezone, + &password); if (got < 0 || task == NULL || saddr == NULL) fatal("NULL data from old process"); @@ -110,6 +111,9 @@ static void takeover_load_fd(struct MBuf *pkt, const struct cmsghdr *cmsg) user ? user : "NULL", db ? db : "NULL", client_enc ? client_enc : "NULL"); + if (!password) + password = ""; + /* fill address */ if (strcmp(saddr, "unix") == 0) { pga_set(&addr, AF_UNIX, cf_listen_port); @@ -121,10 +125,12 @@ static void takeover_load_fd(struct MBuf *pkt, const struct cmsghdr *cmsg) /* decide what to do with it */ if (strcmp(task, "client") == 0) res = use_client_socket(fd, &addr, db, user, ckey, oldfd, linkfd, - client_enc, std_string, datestyle, timezone); + client_enc, std_string, datestyle, timezone, + password); else if (strcmp(task, "server") == 0) res = use_server_socket(fd, &addr, db, user, ckey, oldfd, linkfd, - client_enc, std_string, datestyle, timezone); + client_enc, std_string, datestyle, timezone, + password); else if (strcmp(task, "pooler") == 0) res = use_pooler_socket(fd, pga_is_unix(&addr)); else