mirror of
https://github.com/postgres/postgres.git
synced 2025-05-01 01:04:50 +03:00
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.
This commit is contained in:
parent
b850cf61bd
commit
9872381090
@ -1,4 +1,4 @@
|
|||||||
<!-- $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
|
|||||||
# 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
|
|||||||
|
|
||||||
<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
|
|||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
/*
|
/*
|
||||||
* 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)
|
|||||||
(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)
|
|||||||
* 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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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 @@
|
|||||||
* 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)
|
|||||||
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)
|
|||||||
* 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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.166 2008/08/01 09:09:49 mha Exp $
|
* $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.167 2008/09/15 12:32:56 mha Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -41,8 +41,11 @@
|
|||||||
|
|
||||||
#define MAX_TOKEN 256
|
#define MAX_TOKEN 256
|
||||||
|
|
||||||
|
/* pre-parsed content of HBA config file */
|
||||||
|
static List *parsed_hba_lines = NIL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These variables hold the pre-parsed contents of the hba and ident
|
* These variables hold the pre-parsed contents of the ident
|
||||||
* configuration files, as well as the flat auth file.
|
* configuration files, as well as the flat auth file.
|
||||||
* Each is a list of sublists, one sublist for
|
* Each is a list of sublists, one sublist for
|
||||||
* each (non-empty, non-comment) line of the file. Each sublist's
|
* each (non-empty, non-comment) line of the file. Each sublist's
|
||||||
@ -52,10 +55,6 @@
|
|||||||
* one token, since blank lines are not entered in the data structure.
|
* one token, since blank lines are not entered in the data structure.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* pre-parsed content of HBA config file and corresponding line #s */
|
|
||||||
static List *hba_lines = NIL;
|
|
||||||
static List *hba_line_nums = NIL;
|
|
||||||
|
|
||||||
/* pre-parsed content of ident usermap file and corresponding line #s */
|
/* pre-parsed content of ident usermap file and corresponding line #s */
|
||||||
static List *ident_lines = NIL;
|
static List *ident_lines = NIL;
|
||||||
static List *ident_line_nums = NIL;
|
static List *ident_line_nums = NIL;
|
||||||
@ -566,131 +565,29 @@ check_db(const char *dbname, const char *role, char *param_str)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Scan the rest of a host record (after the mask field)
|
* Parse one line in the hba config file and store the result in
|
||||||
* and return the interpretation of it as *userauth_p, *auth_arg_p, and
|
* a HbaLine structure.
|
||||||
* *error_p. *line_item points to the next token of the line, and is
|
|
||||||
* advanced over successfully-read tokens.
|
|
||||||
*/
|
*/
|
||||||
static void
|
static bool
|
||||||
parse_hba_auth(ListCell **line_item, UserAuth *userauth_p,
|
parse_hba_line(List *line, int line_num, HbaLine *parsedline)
|
||||||
char **auth_arg_p, bool *error_p)
|
|
||||||
{
|
{
|
||||||
char *token;
|
char *token;
|
||||||
|
|
||||||
*auth_arg_p = NULL;
|
|
||||||
|
|
||||||
if (!*line_item)
|
|
||||||
{
|
|
||||||
*error_p = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
token = lfirst(*line_item);
|
|
||||||
if (strcmp(token, "trust") == 0)
|
|
||||||
*userauth_p = uaTrust;
|
|
||||||
else if (strcmp(token, "ident") == 0)
|
|
||||||
*userauth_p = uaIdent;
|
|
||||||
else if (strcmp(token, "password") == 0)
|
|
||||||
*userauth_p = uaPassword;
|
|
||||||
else if (strcmp(token, "krb5") == 0)
|
|
||||||
*userauth_p = uaKrb5;
|
|
||||||
else if (strcmp(token, "gss") == 0)
|
|
||||||
*userauth_p = uaGSS;
|
|
||||||
else if (strcmp(token, "sspi") == 0)
|
|
||||||
*userauth_p = uaSSPI;
|
|
||||||
else if (strcmp(token, "reject") == 0)
|
|
||||||
*userauth_p = uaReject;
|
|
||||||
else if (strcmp(token, "md5") == 0)
|
|
||||||
*userauth_p = uaMD5;
|
|
||||||
else if (strcmp(token, "crypt") == 0)
|
|
||||||
*userauth_p = uaCrypt;
|
|
||||||
#ifdef USE_PAM
|
|
||||||
else if (strcmp(token, "pam") == 0)
|
|
||||||
*userauth_p = uaPAM;
|
|
||||||
#endif
|
|
||||||
#ifdef USE_LDAP
|
|
||||||
else if (strcmp(token, "ldap") == 0)
|
|
||||||
*userauth_p = uaLDAP;
|
|
||||||
#endif
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*error_p = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*line_item = lnext(*line_item);
|
|
||||||
|
|
||||||
/* Get the authentication argument token, if any */
|
|
||||||
if (*line_item)
|
|
||||||
{
|
|
||||||
token = lfirst(*line_item);
|
|
||||||
*auth_arg_p = pstrdup(token);
|
|
||||||
*line_item = lnext(*line_item);
|
|
||||||
/* If there is more on the line, it is an error */
|
|
||||||
if (*line_item)
|
|
||||||
*error_p = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Process one line from the hba config file.
|
|
||||||
*
|
|
||||||
* See if it applies to a connection from a host with IP address port->raddr
|
|
||||||
* to a database named port->database. If so, return *found_p true
|
|
||||||
* and fill in the auth arguments into the appropriate port fields.
|
|
||||||
* If not, leave *found_p as it was. If the record has a syntax error,
|
|
||||||
* return *error_p true, after issuing a message to the log. If no error,
|
|
||||||
* leave *error_p as it was.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
parse_hba(List *line, int line_num, hbaPort *port,
|
|
||||||
bool *found_p, bool *error_p)
|
|
||||||
{
|
|
||||||
char *token;
|
|
||||||
char *db;
|
|
||||||
char *role;
|
|
||||||
struct addrinfo *gai_result;
|
struct addrinfo *gai_result;
|
||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
int ret;
|
int ret;
|
||||||
struct sockaddr_storage addr;
|
|
||||||
struct sockaddr_storage mask;
|
|
||||||
char *cidr_slash;
|
char *cidr_slash;
|
||||||
|
char *unsupauth;
|
||||||
ListCell *line_item;
|
ListCell *line_item;
|
||||||
|
|
||||||
line_item = list_head(line);
|
line_item = list_head(line);
|
||||||
|
|
||||||
|
parsedline->linenumber = line_num;
|
||||||
|
|
||||||
/* Check the record type. */
|
/* Check the record type. */
|
||||||
token = lfirst(line_item);
|
token = lfirst(line_item);
|
||||||
if (strcmp(token, "local") == 0)
|
if (strcmp(token, "local") == 0)
|
||||||
{
|
{
|
||||||
/* Get the database. */
|
parsedline->conntype = ctLocal;
|
||||||
line_item = lnext(line_item);
|
|
||||||
if (!line_item)
|
|
||||||
goto hba_syntax;
|
|
||||||
db = lfirst(line_item);
|
|
||||||
|
|
||||||
/* Get the role. */
|
|
||||||
line_item = lnext(line_item);
|
|
||||||
if (!line_item)
|
|
||||||
goto hba_syntax;
|
|
||||||
role = lfirst(line_item);
|
|
||||||
|
|
||||||
line_item = lnext(line_item);
|
|
||||||
if (!line_item)
|
|
||||||
goto hba_syntax;
|
|
||||||
|
|
||||||
/* Read the rest of the line. */
|
|
||||||
parse_hba_auth(&line_item, &port->auth_method,
|
|
||||||
&port->auth_arg, error_p);
|
|
||||||
if (*error_p)
|
|
||||||
goto hba_syntax;
|
|
||||||
|
|
||||||
/* Disallow auth methods that always need TCP/IP sockets to work */
|
|
||||||
if (port->auth_method == uaKrb5)
|
|
||||||
goto hba_syntax;
|
|
||||||
|
|
||||||
/* Does not match if connection isn't AF_UNIX */
|
|
||||||
if (!IS_AF_UNIX(port->raddr.addr.ss_family))
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
else if (strcmp(token, "host") == 0
|
else if (strcmp(token, "host") == 0
|
||||||
|| strcmp(token, "hostssl") == 0
|
|| strcmp(token, "hostssl") == 0
|
||||||
@ -700,14 +597,7 @@ parse_hba(List *line, int line_num, hbaPort *port,
|
|||||||
if (token[4] == 's') /* "hostssl" */
|
if (token[4] == 's') /* "hostssl" */
|
||||||
{
|
{
|
||||||
#ifdef USE_SSL
|
#ifdef USE_SSL
|
||||||
/* Record does not match if we are not on an SSL connection */
|
parsedline->conntype = ctHostSSL;
|
||||||
if (!port->ssl)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Placeholder to require specific SSL level, perhaps? */
|
|
||||||
/* Or a client certificate */
|
|
||||||
|
|
||||||
/* Since we were on SSL, proceed as with normal 'host' mode */
|
|
||||||
#else
|
#else
|
||||||
/* We don't accept this keyword at all if no SSL support */
|
/* We don't accept this keyword at all if no SSL support */
|
||||||
goto hba_syntax;
|
goto hba_syntax;
|
||||||
@ -716,29 +606,37 @@ parse_hba(List *line, int line_num, hbaPort *port,
|
|||||||
#ifdef USE_SSL
|
#ifdef USE_SSL
|
||||||
else if (token[4] == 'n') /* "hostnossl" */
|
else if (token[4] == 'n') /* "hostnossl" */
|
||||||
{
|
{
|
||||||
/* Record does not match if we are on an SSL connection */
|
parsedline->conntype = ctHostNoSSL;
|
||||||
if (port->ssl)
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* "host", or "hostnossl" and SSL support not built in */
|
||||||
|
parsedline->conntype = ctHost;
|
||||||
|
}
|
||||||
|
} /* record type */
|
||||||
|
else
|
||||||
|
goto hba_syntax;
|
||||||
|
|
||||||
/* Get the database. */
|
/* Get the database. */
|
||||||
line_item = lnext(line_item);
|
line_item = lnext(line_item);
|
||||||
if (!line_item)
|
if (!line_item)
|
||||||
goto hba_syntax;
|
goto hba_syntax;
|
||||||
db = lfirst(line_item);
|
parsedline->database = pstrdup(lfirst(line_item));
|
||||||
|
|
||||||
/* Get the role. */
|
/* Get the role. */
|
||||||
line_item = lnext(line_item);
|
line_item = lnext(line_item);
|
||||||
if (!line_item)
|
if (!line_item)
|
||||||
goto hba_syntax;
|
goto hba_syntax;
|
||||||
role = lfirst(line_item);
|
parsedline->role = pstrdup(lfirst(line_item));
|
||||||
|
|
||||||
|
if (parsedline->conntype != ctLocal)
|
||||||
|
{
|
||||||
/* Read the IP address field. (with or without CIDR netmask) */
|
/* Read the IP address field. (with or without CIDR netmask) */
|
||||||
line_item = lnext(line_item);
|
line_item = lnext(line_item);
|
||||||
if (!line_item)
|
if (!line_item)
|
||||||
goto hba_syntax;
|
goto hba_syntax;
|
||||||
token = lfirst(line_item);
|
token = pstrdup(lfirst(line_item));
|
||||||
|
|
||||||
/* Check if it has a CIDR suffix and if so isolate it */
|
/* Check if it has a CIDR suffix and if so isolate it */
|
||||||
cidr_slash = strchr(token, '/');
|
cidr_slash = strchr(token, '/');
|
||||||
@ -760,9 +658,10 @@ parse_hba(List *line, int line_num, hbaPort *port,
|
|||||||
{
|
{
|
||||||
ereport(LOG,
|
ereport(LOG,
|
||||||
(errcode(ERRCODE_CONFIG_FILE_ERROR),
|
(errcode(ERRCODE_CONFIG_FILE_ERROR),
|
||||||
errmsg("invalid IP address \"%s\" in file \"%s\" line %d: %s",
|
errmsg("invalid IP address \"%s\": %s",
|
||||||
token, HbaFileName, line_num,
|
token, gai_strerror(ret)),
|
||||||
gai_strerror(ret))));
|
errdetail("In file \"%s\", line %d",
|
||||||
|
HbaFileName, line_num)));
|
||||||
if (cidr_slash)
|
if (cidr_slash)
|
||||||
*cidr_slash = '/';
|
*cidr_slash = '/';
|
||||||
if (gai_result)
|
if (gai_result)
|
||||||
@ -773,14 +672,14 @@ parse_hba(List *line, int line_num, hbaPort *port,
|
|||||||
if (cidr_slash)
|
if (cidr_slash)
|
||||||
*cidr_slash = '/';
|
*cidr_slash = '/';
|
||||||
|
|
||||||
memcpy(&addr, gai_result->ai_addr, gai_result->ai_addrlen);
|
memcpy(&parsedline->addr, gai_result->ai_addr, gai_result->ai_addrlen);
|
||||||
pg_freeaddrinfo_all(hints.ai_family, gai_result);
|
pg_freeaddrinfo_all(hints.ai_family, gai_result);
|
||||||
|
|
||||||
/* Get the netmask */
|
/* Get the netmask */
|
||||||
if (cidr_slash)
|
if (cidr_slash)
|
||||||
{
|
{
|
||||||
if (pg_sockaddr_cidr_mask(&mask, cidr_slash + 1,
|
if (pg_sockaddr_cidr_mask(&parsedline->mask, cidr_slash + 1,
|
||||||
addr.ss_family) < 0)
|
parsedline->addr.ss_family) < 0)
|
||||||
goto hba_syntax;
|
goto hba_syntax;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -796,18 +695,19 @@ parse_hba(List *line, int line_num, hbaPort *port,
|
|||||||
{
|
{
|
||||||
ereport(LOG,
|
ereport(LOG,
|
||||||
(errcode(ERRCODE_CONFIG_FILE_ERROR),
|
(errcode(ERRCODE_CONFIG_FILE_ERROR),
|
||||||
errmsg("invalid IP mask \"%s\" in file \"%s\" line %d: %s",
|
errmsg("invalid IP mask \"%s\": %s",
|
||||||
token, HbaFileName, line_num,
|
token, gai_strerror(ret)),
|
||||||
gai_strerror(ret))));
|
errdetail("In file \"%s\", line %d",
|
||||||
|
HbaFileName, line_num)));
|
||||||
if (gai_result)
|
if (gai_result)
|
||||||
pg_freeaddrinfo_all(hints.ai_family, gai_result);
|
pg_freeaddrinfo_all(hints.ai_family, gai_result);
|
||||||
goto hba_other_error;
|
goto hba_other_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(&mask, gai_result->ai_addr, gai_result->ai_addrlen);
|
memcpy(&parsedline->mask, gai_result->ai_addr, gai_result->ai_addrlen);
|
||||||
pg_freeaddrinfo_all(hints.ai_family, gai_result);
|
pg_freeaddrinfo_all(hints.ai_family, gai_result);
|
||||||
|
|
||||||
if (addr.ss_family != mask.ss_family)
|
if (parsedline->addr.ss_family != parsedline->mask.ss_family)
|
||||||
{
|
{
|
||||||
ereport(LOG,
|
ereport(LOG,
|
||||||
(errcode(ERRCODE_CONFIG_FILE_ERROR),
|
(errcode(ERRCODE_CONFIG_FILE_ERROR),
|
||||||
@ -816,54 +716,125 @@ parse_hba(List *line, int line_num, hbaPort *port,
|
|||||||
goto hba_other_error;
|
goto hba_other_error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} /* != ctLocal */
|
||||||
|
|
||||||
if (addr.ss_family != port->raddr.addr.ss_family)
|
/* Get the authentication method */
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Wrong address family. We allow only one case: if the file has
|
|
||||||
* IPv4 and the port is IPv6, promote the file address to IPv6 and
|
|
||||||
* try to match that way.
|
|
||||||
*/
|
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
if (addr.ss_family == AF_INET &&
|
|
||||||
port->raddr.addr.ss_family == AF_INET6)
|
|
||||||
{
|
|
||||||
pg_promote_v4_to_v6_addr(&addr);
|
|
||||||
pg_promote_v4_to_v6_mask(&mask);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif /* HAVE_IPV6 */
|
|
||||||
{
|
|
||||||
/* Line doesn't match client port, so ignore it. */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ignore line if client port is not in the matching addr range. */
|
|
||||||
if (!pg_range_sockaddr(&port->raddr.addr, &addr, &mask))
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Read the rest of the line. */
|
|
||||||
line_item = lnext(line_item);
|
line_item = lnext(line_item);
|
||||||
if (!line_item)
|
if (!line_item)
|
||||||
goto hba_syntax;
|
goto hba_syntax;
|
||||||
parse_hba_auth(&line_item, &port->auth_method,
|
token = lfirst(line_item);
|
||||||
&port->auth_arg, error_p);
|
|
||||||
if (*error_p)
|
unsupauth = NULL;
|
||||||
goto hba_syntax;
|
if (strcmp(token, "trust") == 0)
|
||||||
|
parsedline->auth_method = uaTrust;
|
||||||
|
else if (strcmp(token, "ident") == 0)
|
||||||
|
parsedline->auth_method = uaIdent;
|
||||||
|
else if (strcmp(token, "password") == 0)
|
||||||
|
parsedline->auth_method = uaPassword;
|
||||||
|
else if (strcmp(token, "krb5") == 0)
|
||||||
|
#ifdef KRB5
|
||||||
|
parsedline->auth_method = uaKrb5;
|
||||||
|
#else
|
||||||
|
unsupauth = "krb5";
|
||||||
|
#endif
|
||||||
|
else if (strcmp(token, "gss") == 0)
|
||||||
|
#ifdef ENABLE_GSS
|
||||||
|
parsedline->auth_method = uaGSS;
|
||||||
|
#else
|
||||||
|
unsupauth = "gss";
|
||||||
|
#endif
|
||||||
|
else if (strcmp(token, "sspi") == 0)
|
||||||
|
#ifdef ENABLE_SSPI
|
||||||
|
parsedline->auth_method = uaSSPI;
|
||||||
|
#else
|
||||||
|
unsupauth = "sspi";
|
||||||
|
#endif
|
||||||
|
else if (strcmp(token, "reject") == 0)
|
||||||
|
parsedline->auth_method = uaReject;
|
||||||
|
else if (strcmp(token, "md5") == 0)
|
||||||
|
parsedline->auth_method = uaMD5;
|
||||||
|
else if (strcmp(token, "crypt") == 0)
|
||||||
|
parsedline->auth_method = uaCrypt;
|
||||||
|
else if (strcmp(token, "pam") == 0)
|
||||||
|
#ifdef USE_PAM
|
||||||
|
parsedline->auth_method = uaPAM;
|
||||||
|
#else
|
||||||
|
unsupauth = "pam";
|
||||||
|
#endif
|
||||||
|
else if (strcmp(token, "ldap") == 0)
|
||||||
|
#ifdef USE_LDAP
|
||||||
|
parsedline->auth_method = uaLDAP;
|
||||||
|
#else
|
||||||
|
unsupauth = "ldap";
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ereport(LOG,
|
||||||
|
(errcode(ERRCODE_CONFIG_FILE_ERROR),
|
||||||
|
errmsg("invalid authentication method \"%s\"",
|
||||||
|
token),
|
||||||
|
errdetail("In file \"%s\" line %d",
|
||||||
|
HbaFileName, line_num)));
|
||||||
|
goto hba_other_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unsupauth)
|
||||||
|
{
|
||||||
|
ereport(LOG,
|
||||||
|
(errcode(ERRCODE_CONFIG_FILE_ERROR),
|
||||||
|
errmsg("invalid authentication method \"%s\": not supported on this platform",
|
||||||
|
token),
|
||||||
|
errdetail("In file \"%s\" line %d",
|
||||||
|
HbaFileName, line_num)));
|
||||||
|
goto hba_other_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Invalid authentication combinations */
|
||||||
|
if (parsedline->conntype == ctLocal &&
|
||||||
|
parsedline->auth_method == uaKrb5)
|
||||||
|
{
|
||||||
|
ereport(LOG,
|
||||||
|
(errcode(ERRCODE_CONFIG_FILE_ERROR),
|
||||||
|
errmsg("krb5 authentication is not supported on local sockets"),
|
||||||
|
errdetail("In file \"%s\" line %d",
|
||||||
|
HbaFileName, line_num)));
|
||||||
|
goto hba_other_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the authentication argument token, if any */
|
||||||
|
line_item = lnext(line_item);
|
||||||
|
if (line_item)
|
||||||
|
{
|
||||||
|
token = lfirst(line_item);
|
||||||
|
parsedline->auth_arg= pstrdup(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Backwards compatible format of ident authentication - support "naked" ident map
|
||||||
|
* name, as well as "sameuser"/"samerole"
|
||||||
|
*/
|
||||||
|
if (parsedline->auth_method == uaIdent)
|
||||||
|
{
|
||||||
|
if (parsedline->auth_arg && strlen(parsedline->auth_arg))
|
||||||
|
{
|
||||||
|
if (strcmp(parsedline->auth_arg, "sameuser\n") == 0 ||
|
||||||
|
strcmp(parsedline->auth_arg, "samerole\n") == 0)
|
||||||
|
{
|
||||||
|
/* This is now the default */
|
||||||
|
pfree(parsedline->auth_arg);
|
||||||
|
parsedline->auth_arg = NULL;
|
||||||
|
parsedline->usermap = NULL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
goto hba_syntax;
|
{
|
||||||
|
/* Specific ident map specified */
|
||||||
|
parsedline->usermap = parsedline->auth_arg;
|
||||||
|
parsedline->auth_arg = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Does the entry match database and role? */
|
return true;
|
||||||
if (!check_db(port->database_name, port->user_name, db))
|
|
||||||
return;
|
|
||||||
if (!check_role(port->user_name, role))
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Success */
|
|
||||||
*found_p = true;
|
|
||||||
return;
|
|
||||||
|
|
||||||
hba_syntax:
|
hba_syntax:
|
||||||
if (line_item)
|
if (line_item)
|
||||||
@ -880,7 +851,7 @@ hba_syntax:
|
|||||||
|
|
||||||
/* Come here if suitable message already logged */
|
/* Come here if suitable message already logged */
|
||||||
hba_other_error:
|
hba_other_error:
|
||||||
*error_p = true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -891,28 +862,96 @@ hba_other_error:
|
|||||||
static bool
|
static bool
|
||||||
check_hba(hbaPort *port)
|
check_hba(hbaPort *port)
|
||||||
{
|
{
|
||||||
bool found_entry = false;
|
|
||||||
bool error = false;
|
|
||||||
ListCell *line;
|
ListCell *line;
|
||||||
ListCell *line_num;
|
HbaLine *hba;
|
||||||
|
|
||||||
forboth(line, hba_lines, line_num, hba_line_nums)
|
foreach(line, parsed_hba_lines)
|
||||||
{
|
{
|
||||||
parse_hba(lfirst(line), lfirst_int(line_num),
|
hba = (HbaLine *) lfirst(line);
|
||||||
port, &found_entry, &error);
|
|
||||||
if (found_entry || error)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!error)
|
/* Check connection type */
|
||||||
|
if (hba->conntype == ctLocal)
|
||||||
{
|
{
|
||||||
/* If no matching entry was found, synthesize 'reject' entry. */
|
if (!IS_AF_UNIX(port->raddr.addr.ss_family))
|
||||||
if (!found_entry)
|
continue;
|
||||||
port->auth_method = uaReject;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return false;
|
{
|
||||||
|
if (IS_AF_UNIX(port->raddr.addr.ss_family))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Check SSL state */
|
||||||
|
#ifdef USE_SSL
|
||||||
|
if (port->ssl)
|
||||||
|
{
|
||||||
|
/* Connection is SSL, match both "host" and "hostssl" */
|
||||||
|
if (hba->conntype == ctHostNoSSL)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Connection is not SSL, match both "host" and "hostnossl" */
|
||||||
|
if (hba->conntype == ctHostSSL)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/* No SSL support, so reject "hostssl" lines */
|
||||||
|
if (hba->conntype == ctHostSSL)
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Check IP address */
|
||||||
|
if (port->raddr.addr.ss_family == hba->addr.ss_family)
|
||||||
|
{
|
||||||
|
if (!pg_range_sockaddr(&port->raddr.addr, &hba->addr, &hba->mask))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
else if (hba->addr.ss_family == AF_INET &&
|
||||||
|
port->raddr.addr.ss_family == AF_INET6)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Wrong address family. We allow only one case: if the file has
|
||||||
|
* IPv4 and the port is IPv6, promote the file address to IPv6 and
|
||||||
|
* try to match that way.
|
||||||
|
*/
|
||||||
|
struct sockaddr_storage addrcopy, maskcopy;
|
||||||
|
memcpy(&addrcopy, &hba->addr, sizeof(addrcopy));
|
||||||
|
memcpy(&maskcopy, &hba->mask, sizeof(maskcopy));
|
||||||
|
pg_promote_v4_to_v6_addr(&addrcopy);
|
||||||
|
pg_promote_v4_to_v6_mask(&maskcopy);
|
||||||
|
|
||||||
|
if (!pg_range_sockaddr(&port->raddr.addr, &addrcopy, &maskcopy))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_IPV6 */
|
||||||
|
else
|
||||||
|
/* Wrong address family, no IPV6 */
|
||||||
|
continue;
|
||||||
|
} /* != ctLocal */
|
||||||
|
|
||||||
|
/* Check database and role */
|
||||||
|
if (!check_db(port->database_name, port->user_name, hba->database))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!check_role(port->user_name, hba->role))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Found a record that matched! */
|
||||||
|
port->hba = hba;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If no matching entry was found, synthesize 'reject' entry. */
|
||||||
|
hba = palloc0(sizeof(HbaLine));
|
||||||
|
hba->auth_method = uaReject;
|
||||||
|
port->hba = hba;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
/* XXX:
|
||||||
|
* Return false only happens if we have a parsing error, which we can
|
||||||
|
* no longer have (parsing now in postmaster). Consider changing API.
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -967,17 +1006,52 @@ load_role(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Free the contents of a hba record
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
free_hba_record(HbaLine *record)
|
||||||
|
{
|
||||||
|
if (record->database)
|
||||||
|
pfree(record->database);
|
||||||
|
if (record->role)
|
||||||
|
pfree(record->role);
|
||||||
|
if (record->auth_arg)
|
||||||
|
pfree(record->auth_arg);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read the config file and create a List of Lists of tokens in the file.
|
* Free all records on the parsed HBA list
|
||||||
*/
|
*/
|
||||||
void
|
static void
|
||||||
|
clean_hba_list(List *lines)
|
||||||
|
{
|
||||||
|
ListCell *line;
|
||||||
|
|
||||||
|
foreach(line, lines)
|
||||||
|
{
|
||||||
|
HbaLine *parsed = (HbaLine *)lfirst(line);
|
||||||
|
if (parsed)
|
||||||
|
free_hba_record(parsed);
|
||||||
|
}
|
||||||
|
list_free(lines);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read the config file and create a List of HbaLine records for the contents.
|
||||||
|
*
|
||||||
|
* The configuration is read into a temporary list, and if any parse error occurs
|
||||||
|
* the old list is kept in place and false is returned. Only if the whole file
|
||||||
|
* parses Ok is the list replaced, and the function returns true.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
load_hba(void)
|
load_hba(void)
|
||||||
{
|
{
|
||||||
FILE *file;
|
FILE *file;
|
||||||
|
List *hba_lines = NIL;
|
||||||
if (hba_lines || hba_line_nums)
|
List *hba_line_nums = NIL;
|
||||||
free_lines(&hba_lines, &hba_line_nums);
|
ListCell *line, *line_num;
|
||||||
|
List *new_parsed_lines = NIL;
|
||||||
|
|
||||||
file = AllocateFile(HbaFileName, "r");
|
file = AllocateFile(HbaFileName, "r");
|
||||||
/* Failure is fatal since with no HBA entries we can do nothing... */
|
/* Failure is fatal since with no HBA entries we can do nothing... */
|
||||||
@ -989,6 +1063,35 @@ load_hba(void)
|
|||||||
|
|
||||||
tokenize_file(HbaFileName, file, &hba_lines, &hba_line_nums);
|
tokenize_file(HbaFileName, file, &hba_lines, &hba_line_nums);
|
||||||
FreeFile(file);
|
FreeFile(file);
|
||||||
|
|
||||||
|
/* Now parse all the lines */
|
||||||
|
forboth(line, hba_lines, line_num, hba_line_nums)
|
||||||
|
{
|
||||||
|
HbaLine *newline;
|
||||||
|
|
||||||
|
newline = palloc0(sizeof(HbaLine));
|
||||||
|
|
||||||
|
if (!parse_hba_line(lfirst(line), lfirst_int(line_num), newline))
|
||||||
|
{
|
||||||
|
/* Parse error in the file, so bail out */
|
||||||
|
free_hba_record(newline);
|
||||||
|
pfree(newline);
|
||||||
|
clean_hba_list(new_parsed_lines);
|
||||||
|
/* Error has already been reported in the parsing function */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_parsed_lines = lappend(new_parsed_lines, newline);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Loaded new file successfully, replace the one we use */
|
||||||
|
clean_hba_list(parsed_hba_lines);
|
||||||
|
parsed_hba_lines = new_parsed_lines;
|
||||||
|
|
||||||
|
/* Free the temporary lists */
|
||||||
|
free_lines(&hba_lines, &hba_line_nums);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1100,7 +1203,8 @@ ident_syntax:
|
|||||||
* See if the user with ident username "ident_user" is allowed to act
|
* See if the user with ident username "ident_user" is allowed to act
|
||||||
* as Postgres user "pgrole" according to usermap "usermap_name".
|
* as Postgres user "pgrole" according to usermap "usermap_name".
|
||||||
*
|
*
|
||||||
* Special case: For usermap "samerole", don't look in the usermap
|
* Special case: Usermap NULL, equivalent to what was previously called
|
||||||
|
* "sameuser" or "samerole", don't look in the usermap
|
||||||
* file. That's an implied map where "pgrole" must be identical to
|
* file. That's an implied map where "pgrole" must be identical to
|
||||||
* "ident_user" in order to be authorized.
|
* "ident_user" in order to be authorized.
|
||||||
*
|
*
|
||||||
@ -1115,14 +1219,6 @@ check_ident_usermap(const char *usermap_name,
|
|||||||
error = false;
|
error = false;
|
||||||
|
|
||||||
if (usermap_name == NULL || usermap_name[0] == '\0')
|
if (usermap_name == NULL || usermap_name[0] == '\0')
|
||||||
{
|
|
||||||
ereport(LOG,
|
|
||||||
(errcode(ERRCODE_CONFIG_FILE_ERROR),
|
|
||||||
errmsg("cannot use Ident authentication without usermap field")));
|
|
||||||
found_entry = false;
|
|
||||||
}
|
|
||||||
else if (strcmp(usermap_name, "sameuser\n") == 0 ||
|
|
||||||
strcmp(usermap_name, "samerole\n") == 0)
|
|
||||||
{
|
{
|
||||||
if (strcmp(pg_role, ident_user) == 0)
|
if (strcmp(pg_role, ident_user) == 0)
|
||||||
found_entry = true;
|
found_entry = true;
|
||||||
|
@ -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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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[])
|
|||||||
/*
|
/*
|
||||||
* 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)
|
|||||||
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)
|
|||||||
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 @@
|
|||||||
* 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 @@
|
|||||||
#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
|
|||||||
#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 @@
|
|||||||
* 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
|
|||||||
/*
|
/*
|
||||||
* 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 */
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user