mirror of
https://github.com/postgres/postgres.git
synced 2025-07-30 11:03:19 +03:00
Improve error messages when a connection is rejected.
This commit is contained in:
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.34 1999/03/14 16:06:42 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.35 1999/04/16 04:59:03 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -390,13 +390,53 @@ pg_passwordv0_recvauth(void *arg, PacketLen len, void *pkt)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Tell the user the authentication failed, but not why.
|
* Tell the user the authentication failed, but not (much about) why.
|
||||||
|
*
|
||||||
|
* There is a tradeoff here between security concerns and making life
|
||||||
|
* unnecessarily difficult for legitimate users. We would not, for example,
|
||||||
|
* want to report the password we were expecting to receive...
|
||||||
|
* But it seems useful to report the username and authorization method
|
||||||
|
* in use, and these are items that must be presumed known to an attacker
|
||||||
|
* anyway.
|
||||||
|
* Note that many sorts of failure report additional information in the
|
||||||
|
* postmaster log, which we hope is only readable by good guys.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
auth_failed(Port *port)
|
auth_failed(Port *port)
|
||||||
{
|
{
|
||||||
PacketSendError(&port->pktInfo, "User authentication failed");
|
char buffer[512];
|
||||||
|
const char *authmethod = "Unknown auth method:";
|
||||||
|
|
||||||
|
switch (port->auth_method)
|
||||||
|
{
|
||||||
|
case uaReject:
|
||||||
|
authmethod = "Rejected host:";
|
||||||
|
break;
|
||||||
|
case uaKrb4:
|
||||||
|
authmethod = "Kerberos4";
|
||||||
|
break;
|
||||||
|
case uaKrb5:
|
||||||
|
authmethod = "Kerberos5";
|
||||||
|
break;
|
||||||
|
case uaTrust:
|
||||||
|
authmethod = "Trusted";
|
||||||
|
break;
|
||||||
|
case uaIdent:
|
||||||
|
authmethod = "IDENT";
|
||||||
|
break;
|
||||||
|
case uaPassword:
|
||||||
|
authmethod = "Password";
|
||||||
|
break;
|
||||||
|
case uaCrypt:
|
||||||
|
authmethod = "Password";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(buffer, "%s authentication failed for user '%s'",
|
||||||
|
authmethod, port->user);
|
||||||
|
|
||||||
|
PacketSendError(&port->pktInfo, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -409,12 +449,15 @@ be_recvauth(Port *port)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the authentication method to use for this frontend/database
|
* Get the authentication method to use for this frontend/database
|
||||||
* combination.
|
* combination. Note: a failure return indicates a problem with
|
||||||
|
* the hba config file, not with the request. hba.c should have
|
||||||
|
* dropped an error message into the postmaster logfile if it failed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (hba_getauthmethod(&port->raddr, port->user, port->database,
|
if (hba_getauthmethod(&port->raddr, port->user, port->database,
|
||||||
port->auth_arg, &port->auth_method) != STATUS_OK)
|
port->auth_arg, &port->auth_method) != STATUS_OK)
|
||||||
PacketSendError(&port->pktInfo, "Missing or mis-configured pg_hba.conf file");
|
PacketSendError(&port->pktInfo,
|
||||||
|
"Missing or erroneous pg_hba.conf file, see postmaster log for details");
|
||||||
|
|
||||||
else if (PG_PROTOCOL_MAJOR(port->proto) == 0)
|
else if (PG_PROTOCOL_MAJOR(port->proto) == 0)
|
||||||
{
|
{
|
||||||
@ -425,20 +468,39 @@ be_recvauth(Port *port)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AuthRequest areq;
|
|
||||||
PacketDoneProc auth_handler;
|
|
||||||
|
|
||||||
/* Keep the compiler quiet. */
|
|
||||||
|
|
||||||
areq = AUTH_REQ_OK;
|
|
||||||
|
|
||||||
/* Handle new style authentication. */
|
/* Handle new style authentication. */
|
||||||
|
|
||||||
auth_handler = NULL;
|
AuthRequest areq = AUTH_REQ_OK;
|
||||||
|
PacketDoneProc auth_handler = NULL;
|
||||||
|
|
||||||
switch (port->auth_method)
|
switch (port->auth_method)
|
||||||
{
|
{
|
||||||
case uaReject:
|
case uaReject:
|
||||||
|
/*
|
||||||
|
* This could have come from an explicit "reject" entry
|
||||||
|
* in pg_hba.conf, but more likely it means there was no
|
||||||
|
* matching entry. Take pity on the poor user and issue
|
||||||
|
* a helpful error message. NOTE: this is not a security
|
||||||
|
* breach, because all the info reported here is known
|
||||||
|
* at the frontend and must be assumed known to bad guys.
|
||||||
|
* We're merely helping out the less clueful good guys.
|
||||||
|
* NOTE 2: libpq-be.h defines the maximum error message
|
||||||
|
* length as 99 characters. It probably wouldn't hurt
|
||||||
|
* anything to increase it, but there might be some
|
||||||
|
* client out there that will fail. So, be terse.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
char buffer[512];
|
||||||
|
const char *hostinfo = "localhost";
|
||||||
|
|
||||||
|
if (port->raddr.sa.sa_family == AF_INET)
|
||||||
|
hostinfo = inet_ntoa(port->raddr.in.sin_addr);
|
||||||
|
sprintf(buffer,
|
||||||
|
"No pg_hba.conf entry for host %s, user %s, database %s",
|
||||||
|
hostinfo, port->user, port->database);
|
||||||
|
PacketSendError(&port->pktInfo, buffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case uaKrb4:
|
case uaKrb4:
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
* wherein you authenticate a user by seeing what IP address the system
|
* wherein you authenticate a user by seeing what IP address the system
|
||||||
* says he comes from and possibly using ident).
|
* says he comes from and possibly using ident).
|
||||||
*
|
*
|
||||||
* $Id: hba.c,v 1.39 1999/02/13 23:15:43 momjian Exp $
|
* $Id: hba.c,v 1.40 1999/04/16 04:59:03 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -298,55 +298,42 @@ syntax:
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
process_open_config_file(FILE *file, SockAddr *raddr, const char *user,
|
process_open_config_file(FILE *file, SockAddr *raddr, const char *user,
|
||||||
const char *database, bool *host_ok_p,
|
const char *database, bool *hba_ok_p,
|
||||||
UserAuth *userauth_p, char *auth_arg)
|
UserAuth *userauth_p, char *auth_arg)
|
||||||
{
|
{
|
||||||
/*---------------------------------------------------------------------------
|
/*---------------------------------------------------------------------------
|
||||||
This function does the same thing as find_hba_entry, only with
|
This function does the same thing as find_hba_entry, only with
|
||||||
the config file already open on stream descriptor "file".
|
the config file already open on stream descriptor "file".
|
||||||
----------------------------------------------------------------------------*/
|
----------------------------------------------------------------------------*/
|
||||||
bool found_entry;
|
bool found_entry = false; /* found an applicable entry? */
|
||||||
|
bool error = false; /* found an erroneous entry? */
|
||||||
|
bool eof = false; /* end of hba file */
|
||||||
|
|
||||||
/* We've processed a record that applies to our connection */
|
|
||||||
bool error;
|
|
||||||
|
|
||||||
/* Said record has invalid syntax. */
|
|
||||||
bool eof; /* We've reached the end of the file we're
|
|
||||||
* reading */
|
|
||||||
|
|
||||||
found_entry = false; /* initial value */
|
|
||||||
error = false; /* initial value */
|
|
||||||
eof = false; /* initial value */
|
|
||||||
while (!eof && !found_entry && !error)
|
while (!eof && !found_entry && !error)
|
||||||
{
|
{
|
||||||
/* Process a line from the config file */
|
/* Process a line from the config file */
|
||||||
|
int c = getc(file);
|
||||||
int c; /* a character read from the file */
|
|
||||||
|
|
||||||
c = getc(file);
|
|
||||||
ungetc(c, file);
|
|
||||||
if (c == EOF)
|
if (c == EOF)
|
||||||
eof = true;
|
eof = true;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
ungetc(c, file);
|
||||||
if (c == '#')
|
if (c == '#')
|
||||||
read_through_eol(file);
|
read_through_eol(file);
|
||||||
else
|
else
|
||||||
{
|
|
||||||
process_hba_record(file, raddr, user, database,
|
process_hba_record(file, raddr, user, database,
|
||||||
&found_entry, &error, userauth_p, auth_arg);
|
&found_entry, &error, userauth_p, auth_arg);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!error)
|
if (!error)
|
||||||
{
|
{
|
||||||
/* If no entry was found then force a rejection. */
|
/* If no matching entry was found, synthesize 'reject' entry. */
|
||||||
|
|
||||||
if (!found_entry)
|
if (!found_entry)
|
||||||
*userauth_p = uaReject;
|
*userauth_p = uaReject;
|
||||||
|
|
||||||
*host_ok_p = true;
|
*hba_ok_p = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -354,25 +341,23 @@ process_open_config_file(FILE *file, SockAddr *raddr, const char *user,
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
find_hba_entry(SockAddr *raddr, const char *user, const char *database,
|
find_hba_entry(SockAddr *raddr, const char *user, const char *database,
|
||||||
bool *host_ok_p, UserAuth *userauth_p, char *auth_arg)
|
bool *hba_ok_p, UserAuth *userauth_p, char *auth_arg)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Read the config file and find an entry that allows connection from
|
* Read the config file and find an entry that allows connection from
|
||||||
* host "*raddr" to database "database". If found, return *host_ok_p == true
|
* host "raddr", user "user", to database "database". If found,
|
||||||
* and *userauth_p and *auth_arg representing the contents of that entry.
|
* return *hba_ok_p = true and *userauth_p and *auth_arg representing
|
||||||
|
* the contents of that entry. If there is no matching entry, we
|
||||||
|
* set *hba_ok_p = true, *userauth_p = uaReject.
|
||||||
*
|
*
|
||||||
* When a record has invalid syntax, we either ignore it or reject the
|
* If the config file is unreadable or contains invalid syntax, we
|
||||||
* connection (depending on where it's invalid). No message or anything.
|
* issue a diagnostic message to stderr (ie, the postmaster log file)
|
||||||
* We need to fix that some day.
|
* and return without changing *hba_ok_p.
|
||||||
*
|
|
||||||
* If we don't find or can't access the config file, we issue an error
|
|
||||||
* message and deny the connection.
|
|
||||||
*
|
*
|
||||||
* If we find a file by the old name of the config file (pg_hba), we issue
|
* If we find a file by the old name of the config file (pg_hba), we issue
|
||||||
* an error message because it probably needs to be converted. He didn't
|
* an error message because it probably needs to be converted. He didn't
|
||||||
* follow directions and just installed his old hba file in the new database
|
* follow directions and just installed his old hba file in the new database
|
||||||
* system.
|
* system.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int fd,
|
int fd,
|
||||||
@ -431,14 +416,13 @@ find_hba_entry(SockAddr *raddr, const char *user, const char *database,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
process_open_config_file(file, raddr, user, database, host_ok_p,
|
process_open_config_file(file, raddr, user, database, hba_ok_p,
|
||||||
userauth_p, auth_arg);
|
userauth_p, auth_arg);
|
||||||
FreeFile(file);
|
FreeFile(file);
|
||||||
}
|
}
|
||||||
pfree(conf_file);
|
pfree(conf_file);
|
||||||
}
|
}
|
||||||
pfree(old_conf_file);
|
pfree(old_conf_file);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1079,20 +1063,21 @@ GetCharSetByHost(char *TableName, int host, const char *DataDir)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern int
|
int
|
||||||
hba_getauthmethod(SockAddr *raddr, char *user, char *database,
|
hba_getauthmethod(SockAddr *raddr, char *user, char *database,
|
||||||
char *auth_arg, UserAuth *auth_method)
|
char *auth_arg, UserAuth *auth_method)
|
||||||
{
|
{
|
||||||
/*---------------------------------------------------------------------------
|
/*---------------------------------------------------------------------------
|
||||||
Determine what authentication method should be used when accessing database
|
Determine what authentication method should be used when accessing database
|
||||||
"database" from frontend "raddr". Return the method, an optional argument,
|
"database" from frontend "raddr", user "user". Return the method,
|
||||||
and STATUS_OK.
|
an optional argument, and STATUS_OK.
|
||||||
|
Note that STATUS_ERROR indicates a problem with the hba config file.
|
||||||
|
If the file is OK but does not contain any entry matching the request,
|
||||||
|
we return STATUS_OK and method = uaReject.
|
||||||
----------------------------------------------------------------------------*/
|
----------------------------------------------------------------------------*/
|
||||||
bool host_ok;
|
bool hba_ok = false;
|
||||||
|
|
||||||
host_ok = false;
|
find_hba_entry(raddr, user, database, &hba_ok, auth_method, auth_arg);
|
||||||
|
|
||||||
find_hba_entry(raddr, user, database, &host_ok, auth_method, auth_arg);
|
return hba_ok ? STATUS_OK : STATUS_ERROR;
|
||||||
|
|
||||||
return host_ok ? STATUS_OK : STATUS_ERROR;
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user