Skip to content

Commit

Permalink
When authentication fails, report to frontend proper error messages,
Browse files Browse the repository at this point in the history
rather than unhelpfull "server closed the connection unexpectedly"
message. Patch provided by Glyn Astill with minor tweak by Tatsuo Ishii.
  • Loading branch information
t-ishii committed Nov 3, 2009
1 parent c735b31 commit d6f3a13
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 16 deletions.
17 changes: 16 additions & 1 deletion pool.h
@@ -1,7 +1,7 @@
/* -*-pgsql-c-*- */
/*
*
* $Header: /cvsroot/pgpool/pgpool-II/pool.h,v 1.36.2.6 2009/10/29 12:58:46 t-ishii Exp $
* $Header: /cvsroot/pgpool/pgpool-II/pool.h,v 1.36.2.7 2009/11/03 01:57:00 t-ishii Exp $
*
* pgpool: a language independent connection pool server for PostgreSQL
* written by Tatsuo Ishii
Expand Down Expand Up @@ -564,6 +564,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);
Expand Down
61 changes: 48 additions & 13 deletions pool_auth.c
@@ -1,11 +1,11 @@
/* -*-pgsql-c-*- */
/*
* $Header: /cvsroot/pgpool/pgpool-II/pool_auth.c,v 1.15.2.2 2009/09/23 02:03:12 t-ishii Exp $
* $Header: /cvsroot/pgpool/pgpool-II/pool_auth.c,v 1.15.2.3 2009/11/03 01:57:00 t-ishii Exp $
*
* pgpool: a language independent connection pool server for PostgreSQL
* written by Tatsuo Ishii
*
* Copyright (c) 2003-2008 PgPool Global Development Group
* Copyright (c) 2003-2009 PgPool Global Development Group
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby
Expand Down Expand Up @@ -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.
*/
Expand Down Expand Up @@ -155,7 +158,8 @@ 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_debug("do_clear_text_password failed in slot %d", i);
pool_send_auth_fail(frontend, cp);
return -1;
}
}
Expand All @@ -175,7 +179,8 @@ 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_debug("do_crypt_text_password failed in slot %d", i);
pool_send_auth_fail(frontend, cp);
return -1;
}
}
Expand Down Expand Up @@ -205,7 +210,8 @@ from pool_read_message_length and recheck the pg_hba.conf settings.");

if (authkind < 0)
{
pool_error("do_md5failed in slot %d", i);
pool_debug("do_md5failed in slot %d", i);
pool_send_auth_fail(frontend, cp);
return -1;
}
}
Expand All @@ -219,7 +225,7 @@ from pool_read_message_length and recheck the pg_hba.conf settings.");

if (authkind != 0)
{
pool_error("pool_do_auth: backend does not return authentication ok");
pool_error("pool_do_auth: unknown authentication response from backend %d", authkind);
return -1;
}

Expand Down Expand Up @@ -410,12 +416,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.
*/
Expand Down Expand Up @@ -486,7 +521,7 @@ static int do_clear_text_password(POOL_CONNECTION *backend, POOL_CONNECTION *fro
{
if (pool_read(frontend, &size, sizeof(size)))
{
pool_error("do_clear_text_password: failed to read password packet size");
pool_debug("do_clear_text_password: failed to read password packet size");
return -1;
}
}
Expand All @@ -496,7 +531,7 @@ static int do_clear_text_password(POOL_CONNECTION *backend, POOL_CONNECTION *fro

if (pool_read(frontend, &k, sizeof(k)))
{
pool_error("do_clear_text_password: failed to read password packet \"p\"");
pool_debug("do_clear_text_password: failed to read password packet \"p\"");
return -1;
}
if (k != 'p')
Expand Down Expand Up @@ -664,7 +699,7 @@ static int do_crypt(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int rea

if (pool_read(frontend, &k, sizeof(k)))
{
pool_error("do_crypt_password: failed to read password packet \"p\"");
pool_debug("do_crypt_password: failed to read password packet \"p\"");
return -1;
}
if (k != 'p')
Expand Down Expand Up @@ -732,13 +767,13 @@ static int do_crypt(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int rea
{
if (pool_read(backend, &len, sizeof(len)))
{
pool_error("do_clear_text_password: failed to read authentication packet size");
pool_error("do_crypt: failed to read authentication packet size");
return -1;
}

if (ntohl(len) != 8)
{
pool_error("do_clear_text_password: incorrect authentication packet size (%d)", ntohl(len));
pool_error("do_crypt: incorrect authentication packet size (%d)", ntohl(len));
return -1;
}
}
Expand Down Expand Up @@ -833,7 +868,7 @@ static int do_md5(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reaut

if (pool_read(frontend, &k, sizeof(k)))
{
pool_error("do_md5_password: failed to read password packet \"p\"");
pool_debug("do_md5_password: failed to read password packet \"p\"");
return -1;
}
if (k != 'p')
Expand Down Expand Up @@ -906,7 +941,7 @@ static int do_md5(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reaut

if (ntohl(len) != 8)
{
pool_error("do_clear_text_password: incorrect authentication packet size (%d)", ntohl(len));
pool_error("do_md5: incorrect authentication packet size (%d)", ntohl(len));
return -1;
}
}
Expand Down
33 changes: 31 additions & 2 deletions pool_process_query.c
@@ -1,6 +1,6 @@
/* -*-pgsql-c-*- */
/*
* $Header: /cvsroot/pgpool/pgpool-II/pool_process_query.c,v 1.141.2.25 2009/10/29 12:58:46 t-ishii Exp $
* $Header: /cvsroot/pgpool/pgpool-II/pool_process_query.c,v 1.141.2.26 2009/11/03 01:57:00 t-ishii Exp $
*
* pgpool: a language independent connection pool server for PostgreSQL
* written by Tatsuo Ishii
Expand Down Expand Up @@ -2446,6 +2446,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
Expand Down Expand Up @@ -2478,7 +2507,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;
Expand Down

0 comments on commit d6f3a13

Please sign in to comment.