Commit 98723810 authored by Magnus Hagander's avatar Magnus Hagander

Parse pg_hba.conf in postmaster, instead of once in each backend for

each connection. This makes it possible to catch errors in the pg_hba
file when it's being reloaded, instead of silently reloading a broken
file and failing only when a user tries to connect.

This patch also makes the "sameuser" argument to ident authentication
optional.
parent b850cf61
<!-- $PostgreSQL: pgsql/doc/src/sgml/client-auth.sgml,v 1.106 2008/01/05 13:17:00 petere Exp $ --> <!-- $PostgreSQL: pgsql/doc/src/sgml/client-auth.sgml,v 1.107 2008/09/15 12:32:56 mha Exp $ -->
<chapter id="client-authentication"> <chapter id="client-authentication">
<title>Client Authentication</title> <title>Client Authentication</title>
...@@ -509,7 +509,7 @@ host all all 127.0.0.1 255.255.255.255 trust ...@@ -509,7 +509,7 @@ host all all 127.0.0.1 255.255.255.255 trust
# the connection (typically the Unix user name). # the connection (typically the Unix user name).
# #
# TYPE DATABASE USER CIDR-ADDRESS METHOD # TYPE DATABASE USER CIDR-ADDRESS METHOD
host postgres all 192.168.93.0/24 ident sameuser host postgres all 192.168.93.0/24 ident
# Allow a user from host 192.168.12.10 to connect to database # Allow a user from host 192.168.12.10 to connect to database
# "postgres" if the user's password is correctly supplied. # "postgres" if the user's password is correctly supplied.
...@@ -839,8 +839,8 @@ local db1,db2,@demodbs all md5 ...@@ -839,8 +839,8 @@ local db1,db2,@demodbs all md5
<para> <para>
The ident authentication method works by obtaining the client's The ident authentication method works by obtaining the client's
operating system user name, then determining the allowed database operating system user name, then optionally determining the allowed
user names using a map file that lists the permitted database user names using a map file that lists the permitted
corresponding pairs of names. The determination of the client's corresponding pairs of names. The determination of the client's
user name is the security-critical point, and it works differently user name is the security-critical point, and it works differently
depending on the connection type. depending on the connection type.
...@@ -928,15 +928,13 @@ local db1,db2,@demodbs all md5 ...@@ -928,15 +928,13 @@ local db1,db2,@demodbs all md5
allowed to connect as the database user he is requesting to connect allowed to connect as the database user he is requesting to connect
as. This is controlled by the ident map argument that follows the as. This is controlled by the ident map argument that follows the
<literal>ident</> key word in the <filename>pg_hba.conf</filename> <literal>ident</> key word in the <filename>pg_hba.conf</filename>
file. There is a predefined ident map <literal>sameuser</literal>, file. If an ident map is not specified, the database user will be
which allows any operating system user to connect as the database checked with the same name as the operating system user. Other maps
user of the same name (if the latter exists). Other maps must be must be created manually.
created manually.
</para> </para>
<para> <para>
Ident maps other than <literal>sameuser</literal> are defined in the Ident maps are defined in the ident map file, which by default is named
ident map file, which by default is named
<filename>pg_ident.conf</><indexterm><primary>pg_ident.conf</primary></indexterm> <filename>pg_ident.conf</><indexterm><primary>pg_ident.conf</primary></indexterm>
and is stored in the and is stored in the
cluster's data directory. (It is possible to place the map file cluster's data directory. (It is possible to place the map file
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/libpq/auth.c,v 1.167 2008/08/01 11:41:12 mha Exp $ * $PostgreSQL: pgsql/src/backend/libpq/auth.c,v 1.168 2008/09/15 12:32:56 mha Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -211,7 +211,7 @@ auth_failed(Port *port, int status) ...@@ -211,7 +211,7 @@ auth_failed(Port *port, int status)
if (status == STATUS_EOF) if (status == STATUS_EOF)
proc_exit(0); proc_exit(0);
switch (port->auth_method) switch (port->hba->auth_method)
{ {
case uaReject: case uaReject:
errstr = gettext_noop("authentication failed for user \"%s\": host rejected"); errstr = gettext_noop("authentication failed for user \"%s\": host rejected");
...@@ -279,7 +279,7 @@ ClientAuthentication(Port *port) ...@@ -279,7 +279,7 @@ ClientAuthentication(Port *port)
errmsg("missing or erroneous pg_hba.conf file"), errmsg("missing or erroneous pg_hba.conf file"),
errhint("See server log for details."))); errhint("See server log for details.")));
switch (port->auth_method) switch (port->hba->auth_method)
{ {
case uaReject: case uaReject:
...@@ -1761,7 +1761,7 @@ ident_unix(int sock, char *ident_user) ...@@ -1761,7 +1761,7 @@ ident_unix(int sock, char *ident_user)
/* /*
* Determine the username of the initiator of the connection described * Determine the username of the initiator of the connection described
* by "port". Then look in the usermap file under the usermap * by "port". Then look in the usermap file under the usermap
* port->auth_arg and see if that user is equivalent to Postgres user * port->hba->usermap and see if that user is equivalent to Postgres user
* port->user. * port->user.
* *
* Return STATUS_OK if yes, STATUS_ERROR if no match (or couldn't get info). * Return STATUS_OK if yes, STATUS_ERROR if no match (or couldn't get info).
...@@ -1799,7 +1799,7 @@ authident(hbaPort *port) ...@@ -1799,7 +1799,7 @@ authident(hbaPort *port)
(errmsg("Ident protocol identifies remote user as \"%s\"", (errmsg("Ident protocol identifies remote user as \"%s\"",
ident_user))); ident_user)));
if (check_ident_usermap(port->auth_arg, port->user_name, ident_user)) if (check_ident_usermap(port->hba->usermap, port->user_name, ident_user))
return STATUS_OK; return STATUS_OK;
else else
return STATUS_ERROR; return STATUS_ERROR;
...@@ -1913,8 +1913,8 @@ CheckPAMAuth(Port *port, char *user, char *password) ...@@ -1913,8 +1913,8 @@ CheckPAMAuth(Port *port, char *user, char *password)
* not allocated */ * not allocated */
/* Optionally, one can set the service name in pg_hba.conf */ /* Optionally, one can set the service name in pg_hba.conf */
if (port->auth_arg && port->auth_arg[0] != '\0') if (port->hba->auth_arg && port->hba->auth_arg[0] != '\0')
retval = pam_start(port->auth_arg, "pgsql@", retval = pam_start(port->hba->auth_arg, "pgsql@",
&pam_passw_conv, &pamh); &pam_passw_conv, &pamh);
else else
retval = pam_start(PGSQL_PAM_SERVICE, "pgsql@", retval = pam_start(PGSQL_PAM_SERVICE, "pgsql@",
...@@ -2011,7 +2011,7 @@ CheckLDAPAuth(Port *port) ...@@ -2011,7 +2011,7 @@ CheckLDAPAuth(Port *port)
int ldapport = LDAP_PORT; int ldapport = LDAP_PORT;
char fulluser[NAMEDATALEN + 256 + 1]; char fulluser[NAMEDATALEN + 256 + 1];
if (!port->auth_arg || port->auth_arg[0] == '\0') if (!port->hba->auth_arg || port->hba->auth_arg[0] == '\0')
{ {
ereport(LOG, ereport(LOG,
(errmsg("LDAP configuration URL not specified"))); (errmsg("LDAP configuration URL not specified")));
...@@ -2035,13 +2035,13 @@ CheckLDAPAuth(Port *port) ...@@ -2035,13 +2035,13 @@ CheckLDAPAuth(Port *port)
suffix[0] = '\0'; suffix[0] = '\0';
/* ldap, including port number */ /* ldap, including port number */
r = sscanf(port->auth_arg, r = sscanf(port->hba->auth_arg,
"ldap://%127[^:]:%d/%127[^;];%127[^;];%127[^\n]", "ldap://%127[^:]:%d/%127[^;];%127[^;];%127[^\n]",
server, &ldapport, basedn, prefix, suffix); server, &ldapport, basedn, prefix, suffix);
if (r < 3) if (r < 3)
{ {
/* ldaps, including port number */ /* ldaps, including port number */
r = sscanf(port->auth_arg, r = sscanf(port->hba->auth_arg,
"ldaps://%127[^:]:%d/%127[^;];%127[^;];%127[^\n]", "ldaps://%127[^:]:%d/%127[^;];%127[^;];%127[^\n]",
server, &ldapport, basedn, prefix, suffix); server, &ldapport, basedn, prefix, suffix);
if (r >= 3) if (r >= 3)
...@@ -2050,14 +2050,14 @@ CheckLDAPAuth(Port *port) ...@@ -2050,14 +2050,14 @@ CheckLDAPAuth(Port *port)
if (r < 3) if (r < 3)
{ {
/* ldap, no port number */ /* ldap, no port number */
r = sscanf(port->auth_arg, r = sscanf(port->hba->auth_arg,
"ldap://%127[^/]/%127[^;];%127[^;];%127[^\n]", "ldap://%127[^/]/%127[^;];%127[^;];%127[^\n]",
server, basedn, prefix, suffix); server, basedn, prefix, suffix);
} }
if (r < 2) if (r < 2)
{ {
/* ldaps, no port number */ /* ldaps, no port number */
r = sscanf(port->auth_arg, r = sscanf(port->hba->auth_arg,
"ldaps://%127[^/]/%127[^;];%127[^;];%127[^\n]", "ldaps://%127[^/]/%127[^;];%127[^;];%127[^\n]",
server, basedn, prefix, suffix); server, basedn, prefix, suffix);
if (r >= 2) if (r >= 2)
...@@ -2067,7 +2067,7 @@ CheckLDAPAuth(Port *port) ...@@ -2067,7 +2067,7 @@ CheckLDAPAuth(Port *port)
{ {
ereport(LOG, ereport(LOG,
(errmsg("invalid LDAP URL: \"%s\"", (errmsg("invalid LDAP URL: \"%s\"",
port->auth_arg))); port->hba->auth_arg)));
return STATUS_ERROR; return STATUS_ERROR;
} }
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/backend/libpq/crypt.c,v 1.74 2008/01/01 19:45:49 momjian Exp $ * $PostgreSQL: pgsql/src/backend/libpq/crypt.c,v 1.75 2008/09/15 12:32:56 mha Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -54,7 +54,7 @@ md5_crypt_verify(const Port *port, const char *role, char *client_pass) ...@@ -54,7 +54,7 @@ md5_crypt_verify(const Port *port, const char *role, char *client_pass)
return STATUS_ERROR; return STATUS_ERROR;
/* We can't do crypt with MD5 passwords */ /* We can't do crypt with MD5 passwords */
if (isMD5(shadow_pass) && port->auth_method == uaCrypt) if (isMD5(shadow_pass) && port->hba->auth_method == uaCrypt)
{ {
ereport(LOG, ereport(LOG,
(errmsg("cannot use authentication method \"crypt\" because password is MD5-encrypted"))); (errmsg("cannot use authentication method \"crypt\" because password is MD5-encrypted")));
...@@ -65,7 +65,7 @@ md5_crypt_verify(const Port *port, const char *role, char *client_pass) ...@@ -65,7 +65,7 @@ md5_crypt_verify(const Port *port, const char *role, char *client_pass)
* Compare with the encrypted or plain password depending on the * Compare with the encrypted or plain password depending on the
* authentication method being used for this connection. * authentication method being used for this connection.
*/ */
switch (port->auth_method) switch (port->hba->auth_method)
{ {
case uaMD5: case uaMD5:
crypt_pwd = palloc(MD5_PASSWD_LEN + 1); crypt_pwd = palloc(MD5_PASSWD_LEN + 1);
...@@ -155,7 +155,7 @@ md5_crypt_verify(const Port *port, const char *role, char *client_pass) ...@@ -155,7 +155,7 @@ md5_crypt_verify(const Port *port, const char *role, char *client_pass)
} }
} }
if (port->auth_method == uaMD5) if (port->hba->auth_method == uaMD5)
pfree(crypt_pwd); pfree(crypt_pwd);
if (crypt_client_pass != client_pass) if (crypt_client_pass != client_pass)
pfree(crypt_client_pass); pfree(crypt_client_pass);
......
This diff is collapsed.
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
# #
# No map names are defined in the default configuration. If all ident # No map names are defined in the default configuration. If all ident
# user names and PostgreSQL user names are the same, you don't need # user names and PostgreSQL user names are the same, you don't need
# this file. Instead, use the special map name "sameuser" in # this file.
# pg_hba.conf.
# MAPNAME IDENT-USERNAME PG-USERNAME # MAPNAME IDENT-USERNAME PG-USERNAME
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.562 2008/08/25 15:11:01 mha Exp $ * $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.563 2008/09/15 12:32:57 mha Exp $
* *
* NOTES * NOTES
* *
...@@ -888,7 +888,15 @@ PostmasterMain(int argc, char *argv[]) ...@@ -888,7 +888,15 @@ PostmasterMain(int argc, char *argv[])
/* /*
* Load configuration files for client authentication. * Load configuration files for client authentication.
*/ */
load_hba(); if (!load_hba())
{
/*
* It makes no sense continue if we fail to load the HBA file, since
* there is no way to connect to the database in this case.
*/
ereport(FATAL,
(errmsg("could not load pg_hba.conf")));
}
load_ident(); load_ident();
/* /*
...@@ -1927,7 +1935,10 @@ SIGHUP_handler(SIGNAL_ARGS) ...@@ -1927,7 +1935,10 @@ SIGHUP_handler(SIGNAL_ARGS)
signal_child(PgStatPID, SIGHUP); signal_child(PgStatPID, SIGHUP);
/* Reload authentication config files too */ /* Reload authentication config files too */
load_hba(); if (!load_hba())
ereport(WARNING,
(errmsg("pg_hba.conf not reloaded")));
load_ident(); load_ident();
#ifdef EXEC_BACKEND #ifdef EXEC_BACKEND
...@@ -3081,7 +3092,15 @@ BackendInitialize(Port *port) ...@@ -3081,7 +3092,15 @@ BackendInitialize(Port *port)
ALLOCSET_DEFAULT_MAXSIZE); ALLOCSET_DEFAULT_MAXSIZE);
MemoryContextSwitchTo(PostmasterContext); MemoryContextSwitchTo(PostmasterContext);
load_hba(); if (!load_hba())
{
/*
* It makes no sense continue if we fail to load the HBA file, since
* there is no way to connect to the database in this case.
*/
ereport(FATAL,
(errmsg("could not load pg_hba.conf")));
}
load_ident(); load_ident();
load_role(); load_role();
#endif #endif
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* Interface to hba.c * Interface to hba.c
* *
* *
* $PostgreSQL: pgsql/src/include/libpq/hba.h,v 1.48 2008/08/01 09:09:48 mha Exp $ * $PostgreSQL: pgsql/src/include/libpq/hba.h,v 1.49 2008/09/15 12:32:57 mha Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#define HBA_H #define HBA_H
#include "nodes/pg_list.h" #include "nodes/pg_list.h"
#include "libpq/pqcomm.h"
typedef enum UserAuth typedef enum UserAuth
...@@ -33,10 +34,31 @@ typedef enum UserAuth ...@@ -33,10 +34,31 @@ typedef enum UserAuth
#endif #endif
} UserAuth; } UserAuth;
typedef enum ConnType
{
ctLocal,
ctHost,
ctHostSSL,
ctHostNoSSL
} ConnType;
typedef struct
{
int linenumber;
ConnType conntype;
char *database;
char *role;
struct sockaddr_storage addr;
struct sockaddr_storage mask;
UserAuth auth_method;
char *usermap;
char *auth_arg;
} HbaLine;
typedef struct Port hbaPort; typedef struct Port hbaPort;
extern List **get_role_line(const char *role); extern List **get_role_line(const char *role);
extern void load_hba(void); extern bool load_hba(void);
extern void load_ident(void); extern void load_ident(void);
extern void load_role(void); extern void load_role(void);
extern int hba_getauthmethod(hbaPort *port); extern int hba_getauthmethod(hbaPort *port);
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/libpq/libpq-be.h,v 1.66 2008/04/26 22:47:40 tgl Exp $ * $PostgreSQL: pgsql/src/include/libpq/libpq-be.h,v 1.67 2008/09/15 12:32:57 mha Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -121,8 +121,7 @@ typedef struct Port ...@@ -121,8 +121,7 @@ typedef struct Port
/* /*
* Information that needs to be held during the authentication cycle. * Information that needs to be held during the authentication cycle.
*/ */
UserAuth auth_method; HbaLine *hba;
char *auth_arg;
char md5Salt[4]; /* Password salt */ char md5Salt[4]; /* Password salt */
char cryptSalt[2]; /* Password salt */ char cryptSalt[2]; /* Password salt */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment