Set PAM_RHOST item for PAM authentication

The PAM_RHOST item is set to the remote IP address or host name and can
be used by PAM modules.  A pg_hba.conf option is provided to choose
between IP address and resolved host name.

From: Grzegorz Sampolski <grzsmp@gmail.com>
Reviewed-by: Haribabu Kommi <kommi.haribabu@gmail.com>
This commit is contained in:
Peter Eisentraut 2016-04-08 10:45:16 -04:00
parent 4e55b3f033
commit 2f1d2b7a75
4 changed files with 52 additions and 4 deletions

View File

@ -1617,10 +1617,11 @@ host ... ldap ldapurl="ldap://ldap.example.net/dc=example,dc=net?uid?sub"
<literal>password</literal> except that it uses PAM (Pluggable
Authentication Modules) as the authentication mechanism. The
default PAM service name is <literal>postgresql</literal>.
PAM is used only to validate user name/password pairs.
Therefore the user must already exist in the database before PAM
can be used for authentication. For more information about
PAM, please read the <ulink url="http://www.kernel.org/pub/linux/libs/pam/">
PAM is used only to validate user name/password pairs and optionally the
connected remote host name or IP address. Therefore the user must already
exist in the database before PAM can be used for authentication. For more
information about PAM, please read the
<ulink url="http://www.kernel.org/pub/linux/libs/pam/">
<productname>Linux-PAM</> Page</ulink>.
</para>
@ -1635,6 +1636,20 @@ host ... ldap ldapurl="ldap://ldap.example.net/dc=example,dc=net?uid?sub"
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>pam_use_hostname</literal></term>
<listitem>
<para>
Determines whether the remote IP address or the host name is provided
to PAM modules through the <symbol>PAM_RHOST</symbol> item. By
default, the IP address is used. Set this option to 1 to use the
resolved host name instead. Host name resolution can lead to login
delays. (Most PAM configurations don't use this information, so it is
only necessary to consider this setting if a PAM configuration was
specifically created to make use of it.)
</para>
</listitem>
</varlistentry>
</variablelist>
</para>

View File

@ -1739,6 +1739,18 @@ CheckPAMAuth(Port *port, char *user, char *password)
{
int retval;
pam_handle_t *pamh = NULL;
char hostinfo[NI_MAXHOST];
retval = pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
hostinfo, sizeof(hostinfo), NULL, 0,
port->hba->pam_use_hostname ? 0 : NI_NUMERICHOST | NI_NUMERICSERV);
if (retval != 0)
{
ereport(WARNING,
(errmsg_internal("pg_getnameinfo_all() failed: %s",
gai_strerror(retval))));
return STATUS_ERROR;
}
/*
* We can't entirely rely on PAM to pass through appdata --- it appears
@ -1784,6 +1796,17 @@ CheckPAMAuth(Port *port, char *user, char *password)
return STATUS_ERROR;
}
retval = pam_set_item(pamh, PAM_RHOST, hostinfo);
if (retval != PAM_SUCCESS)
{
ereport(LOG,
(errmsg("pam_set_item(PAM_RHOST) failed: %s",
pam_strerror(pamh, retval))));
pam_passwd = NULL;
return STATUS_ERROR;
}
retval = pam_set_item(pamh, PAM_CONV, &pam_passw_conv);
if (retval != PAM_SUCCESS)

View File

@ -1447,6 +1447,15 @@ parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline, int line_num)
REQUIRE_AUTH_OPTION(uaPAM, "pamservice", "pam");
hbaline->pamservice = pstrdup(val);
}
else if (strcmp(name, "pam_use_hostname") == 0)
{
REQUIRE_AUTH_OPTION(uaPAM, "pam_use_hostname", "pam");
if (strcmp(val, "1") == 0)
hbaline->pam_use_hostname = true;
else
hbaline->pam_use_hostname = false;
}
else if (strcmp(name, "ldapurl") == 0)
{
#ifdef LDAP_API_FEATURE_X_OPENLDAP

View File

@ -64,6 +64,7 @@ typedef struct HbaLine
char *usermap;
char *pamservice;
bool pam_use_hostname;
bool ldaptls;
char *ldapserver;
int ldapport;