]> granicus.if.org Git - pgbouncer/commitdiff
fix reconnects of auth_user dbs after online restart
authorCody Cutrer <cody@instructure.com>
Wed, 28 Aug 2013 02:47:44 +0000 (20:47 -0600)
committerCody Cutrer <cody@instructure.com>
Mon, 7 Oct 2013 21:34:51 +0000 (15:34 -0600)
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

include/client.h
include/objects.h
src/admin.c
src/client.c
src/objects.c
src/takeover.c

index 32535321a0b2ecdee558da34ff4f3418adfe9d92..911e3f152e01713475cb072db880e2166e2d2a0c 100644 (file)
@@ -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);
index 37355650dbb97afef5413c2c86706d8a30e0d821..b4a91a649f6ab6ec3a4dafd1af77a4baff2248c0 100644 (file)
@@ -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);
index 945669a99a675512abe175276a42ae6e4d545a88..cfe7df999216c7613d774930c97d6c45513fe1b3 100644 (file)
@@ -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);
 
index 66bb46e5247c35986f2e022231ee2b5b77d32e3b..d8bc5f2eeb3ea5e818eaf59492dd1f0739efcdad 100644 (file)
@@ -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 */
index 1e718c5756924f487597ed645634b39d83f9c056..fe9865a16369d897b650d41d2dfde7c35a2ce292 100644 (file)
@@ -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)
index e34d74e09384f3725fe235684f468c20523d977a..18a384d26d6130581ed24fa3e780f61951a5158e 100644 (file)
@@ -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