From 74dbf6bdf5218bc69bcfe5b936abe06d82246ba1 Mon Sep 17 00:00:00 2001 From: glyn Date: Mon, 2 Nov 2009 20:36:11 +0000 Subject: [PATCH] Attempt to send a proper failure message to frontend when authentication fails rather than "server closed the connection unexpectedly". EDIT: Committed "http://git.postgresql.org/gitweb/?p=pgpool2.git;a=commit;h=810b44217e16767c4206d183d290cee56a5fd5c8" --- pool.h | 15 +++++++++++++++ pool_auth.c | 36 ++++++++++++++++++++++++++++++++++++ pool_process_query.c | 31 ++++++++++++++++++++++++++++++- 3 files changed, 81 insertions(+), 1 deletion(-) diff --git a/pool.h b/pool.h index 674a2b5..6b78b63 100644 --- a/pool.h +++ b/pool.h @@ -523,6 +523,21 @@ extern void pool_send_error_message(POOL_CONNECTION *frontend, int protoMajor, char *hint, char *file, int line); +extern void pool_send_fatal_message(POOL_CONNECTION *frontend, int protoMajor, + char *code, + char *message, + char *detail, + char *hint, + char *file, + int line); +extern void pool_send_severity_message(POOL_CONNECTION *frontend, int protoMajor, + char *code, + char *message, + char *detail, + char *hint, + char *file, + char *severity, + int line); extern void pool_send_readyforquery(POOL_CONNECTION *frontend); extern int send_startup_packet(POOL_CONNECTION_POOL_SLOT *cp); extern void pool_free_startup_packet(StartupPacket *sp); diff --git a/pool_auth.c b/pool_auth.c index cd5bf42..def2ebc 100644 --- a/pool_auth.c +++ b/pool_auth.c @@ -35,14 +35,17 @@ #endif #include #include +#include #define AUTHFAIL_ERRORCODE "28000" static POOL_STATUS pool_send_auth_ok(POOL_CONNECTION *frontend, int pid, int key, int protoMajor); static int do_clear_text_password(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reauth, int protoMajor); +static void pool_send_auth_fail(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *cp); static int do_crypt(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reauth, int protoMajor); static int do_md5(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reauth, int protoMajor); + /* * do authentication against backend. if success return 0 otherwise non 0. */ @@ -136,6 +139,7 @@ from pool_read_message_length and recheck the pg_hba.conf settings."); msglen = htonl(0); if (pool_write_and_flush(frontend, &msglen, sizeof(msglen)) < 0) { + pool_send_auth_fail(frontend, cp); return -1; } MASTER(cp)->auth_kind = 0; @@ -156,6 +160,7 @@ from pool_read_message_length and recheck the pg_hba.conf settings."); if (authkind < 0) { pool_error("do_clear_text_password failed in slot %d", i); + pool_send_auth_fail(frontend, cp); return -1; } } @@ -176,6 +181,7 @@ from pool_read_message_length and recheck the pg_hba.conf settings."); if (authkind < 0) { pool_error("do_crypt_text_password failed in slot %d", i); + pool_send_auth_fail(frontend, cp); return -1; } } @@ -206,6 +212,7 @@ from pool_read_message_length and recheck the pg_hba.conf settings."); if (authkind < 0) { pool_error("do_md5failed in slot %d", i); + pool_send_auth_fail(frontend, cp); return -1; } } @@ -410,12 +417,41 @@ int pool_do_reauth(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *cp) else { pool_debug("pool_do_reauth: authentication failed"); + pool_send_auth_fail(frontend, cp); return -1; } return (pool_send_auth_ok(frontend, MASTER_CONNECTION(cp)->pid, MASTER_CONNECTION(cp)->key, protoMajor) != POOL_CONTINUE); } +/* +* send authentication failure message text to frontend +*/ +static void pool_send_auth_fail(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *cp) +{ + int messagelen; + char *errmessage; + int protoMajor; + + bool send_error_to_frontend = true; + + protoMajor = MAJOR(cp); + + messagelen = strlen(MASTER_CONNECTION(cp)->sp->user) + 100; + if ((errmessage = (char *)malloc(messagelen+1)) == NULL) + { + pool_error("pool_send_auth_fail_failed: malloc failed: %s", strerror(errno)); + child_exit(1); + } + + snprintf(errmessage, messagelen, "password authentication failed for user \"%s\"", + MASTER_CONNECTION(cp)->sp->user); + if (send_error_to_frontend) + pool_send_fatal_message(frontend, protoMajor, "XX000", errmessage, + "", "", __FILE__, __LINE__); + free(errmessage); +} + /* * send authentication ok to frontend. if success return 0 otherwise non 0. */ diff --git a/pool_process_query.c b/pool_process_query.c index 5cf2b69..60901ff 100644 --- a/pool_process_query.c +++ b/pool_process_query.c @@ -2447,6 +2447,35 @@ void pool_send_error_message(POOL_CONNECTION *frontend, int protoMajor, char *hint, char *file, int line) +{ + pool_send_severity_message(frontend, protoMajor, code, message, detail, hint, file, "ERROR", line); +} + +/* + * send fatal message to frontend + */ +void pool_send_fatal_message(POOL_CONNECTION *frontend, int protoMajor, + char *code, + char *message, + char *detail, + char *hint, + char *file, + int line) +{ + pool_send_severity_message(frontend, protoMajor, code, message, detail, hint, file, "FATAL", line); +} + +/* + * send severity message to frontend + */ +void pool_send_severity_message(POOL_CONNECTION *frontend, int protoMajor, + char *code, + char *message, + char *detail, + char *hint, + char *file, + char *severity, + int line) { /* * Buffer length for each message part @@ -2479,7 +2508,7 @@ void pool_send_error_message(POOL_CONNECTION *frontend, int protoMajor, pool_write(frontend, "E", 1); /* error level */ - thislen = snprintf(msgbuf, MAXMSGBUF, "SERROR"); + thislen = snprintf(msgbuf, MAXMSGBUF, "S%s", severity); thislen = Min(thislen, MAXMSGBUF); memcpy(data +len, msgbuf, thislen+1); len += thislen + 1; -- 2.39.2