From: glyn <glyn@8kb.co.uk>
Date: Mon, 2 Nov 2009 20:36:11 +0000 (+0000)
Subject: Attempt to send a proper failure message to frontend when authentication
X-Git-Url: https://git.8kb.co.uk/?a=commitdiff_plain;h=refs%2Fheads%2Fmaster;p=pgpool-ii%2Fpgpool-ii_2.2.5

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"
---

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 <errno.h>
 #include <string.h>
+#include <stdlib.h>
 
 #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;