databases are configured to log in as specific user. Additionally, the console
database allows any user to log in as admin.
+==== auth_query ====
+
+Query to load user's password from db.
+
+Default: SELECT usename, passwd FROM pg_shadow WHERE usename=$1
+
==== pool_mode ====
Specifies when a server connection can be reused by other clients.
extern int cf_auth_type;
extern char *cf_auth_file;
+extern char *cf_auth_query;
extern char *cf_pidfile;
void pktbuf_write_generic(PktBuf *buf, int type, const char *fmt, ...);
void pktbuf_write_RowDescription(PktBuf *buf, const char *tupdesc, ...);
void pktbuf_write_DataRow(PktBuf *buf, const char *tupdesc, ...);
+void pktbuf_write_ExtQuery(PktBuf *buf, const char *query, int nargs, ...);
/*
* Shortcuts for actual packets.
static void start_auth_request(PgSocket *client, const char *username)
{
int res;
- char quoted_username[64], query[128];
+ PktBuf *buf;
client->auth_user = client->db->auth_user;
/* have to fetch user info from db */
}
client->link->ready = 0;
- pg_quote_literal(quoted_username, username, sizeof(quoted_username));
- snprintf(query, sizeof(query), "SELECT usename, passwd FROM pg_shadow WHERE usename=%s", quoted_username);
- SEND_generic(res, client->link, 'Q', "s", query);
+ res = 0;
+ buf = pktbuf_dynamic(512);
+ if (buf) {
+ pktbuf_write_ExtQuery(buf, cf_auth_query, 1, username);
+ res = pktbuf_send_immediate(buf, client->link);
+ pktbuf_free(buf);
+ /*
+ * Should do instead:
+ * res = pktbuf_send_queued(buf, client->link);
+ * but that needs better integration with SBuf.
+ */
+ }
if (!res)
disconnect_server(client->link, false, "unable to send login query");
}
break;
case 'C': /* CommandComplete */
break;
+ case '1': /* ParseComplete */
+ break;
+ case '2': /* BindComplete */
+ break;
case 'Z': /* ReadyForQuery */
sbuf_prepare_skip(&client->link->sbuf, pkt->len);
if (!client->auth_user) {
int cf_auth_type = AUTH_MD5;
char *cf_auth_file;
+char *cf_auth_query;
int cf_max_client_conn;
int cf_default_pool_size;
#endif
CF_ABS("auth_type", CF_LOOKUP(auth_type_map), cf_auth_type, 0, "md5"),
CF_ABS("auth_file", CF_STR, cf_auth_file, 0, "unconfigured_file"),
+CF_ABS("auth_query", CF_STR, cf_auth_query, 0, "SELECT usename, passwd FROM pg_shadow WHERE usename=$1"),
CF_ABS("pool_mode", CF_LOOKUP(pool_mode_map), cf_pool_mode, 0, "session"),
CF_ABS("max_client_conn", CF_INT, cf_max_client_conn, 0, "100"),
CF_ABS("default_pool_size", CF_INT, cf_default_pool_size, 0, "20"),
pktbuf_finish_packet(buf);
}
+/*
+ * Send Parse+Bind+Execute with string parameters.
+ */
+void pktbuf_write_ExtQuery(PktBuf *buf, const char *query, int nargs, ...)
+{
+ va_list ap;
+ const char *val;
+ int len, i;
+
+ /* Parse */
+ pktbuf_write_generic(buf, 'P', "csh", 0, query, 0);
+
+ /* Bind */
+ pktbuf_start_packet(buf, 'B');
+ pktbuf_put_char(buf, 0); /* portal name */
+ pktbuf_put_char(buf, 0); /* query name */
+ pktbuf_put_uint16(buf, 0); /* number of parameter format codes */
+ pktbuf_put_uint16(buf, nargs); /* number of parameter values */
+
+ va_start(ap, nargs);
+ for (i = 0; i < nargs; i++) {
+ val = va_arg(ap, char *);
+ len = strlen(val);
+ pktbuf_put_uint32(buf, len);
+ pktbuf_put_bytes(buf, val, len);
+ }
+ va_end(ap);
+
+ pktbuf_put_uint16(buf, 0); /* number of result-column format codes */
+ pktbuf_finish_packet(buf);
+
+ /* Describe */
+ pktbuf_write_generic(buf, 'D', "cc", 'P', 0);
+
+ /* Execute */
+ pktbuf_write_generic(buf, 'E', "ci", 0, 0);
+
+ /* Sync */
+ pktbuf_write_generic(buf, 'S', "");
+}
+