提交 7356381e 编写于 作者: M Magnus Hagander

* make pg_hba authoption be a set of 0 or more name=value pairs

* make LDAP use this instead of the hacky previous method to specify
  the DN to bind as
* make all auth options behave the same when they are not compiled
  into the server
* rename "ident maps" to "user name maps", and support them for all
  auth methods that provide an external username

This makes a backwards incompatible change in the format of pg_hba.conf
for the ident, PAM and LDAP authentication methods.
上级 2675d043
<!-- $PostgreSQL: pgsql/doc/src/sgml/client-auth.sgml,v 1.108 2008/09/15 12:41:54 mha Exp $ --> <!-- $PostgreSQL: pgsql/doc/src/sgml/client-auth.sgml,v 1.109 2008/10/23 13:31:09 mha Exp $ -->
<chapter id="client-authentication"> <chapter id="client-authentication">
<title>Client Authentication</title> <title>Client Authentication</title>
...@@ -96,13 +96,13 @@ ...@@ -96,13 +96,13 @@
<para> <para>
A record can have one of the seven formats A record can have one of the seven formats
<synopsis> <synopsis>
local <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>auth-method</replaceable> <optional><replaceable>auth-option</replaceable></optional> local <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>auth-method</replaceable> <optional><replaceable>auth-options</replaceable></optional>
host <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>CIDR-address</replaceable> <replaceable>auth-method</replaceable> <optional><replaceable>auth-option</replaceable></optional> host <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>CIDR-address</replaceable> <replaceable>auth-method</replaceable> <optional><replaceable>auth-options</replaceable></optional>
hostssl <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>CIDR-address</replaceable> <replaceable>auth-method</replaceable> <optional><replaceable>auth-option</replaceable></optional> hostssl <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>CIDR-address</replaceable> <replaceable>auth-method</replaceable> <optional><replaceable>auth-options</replaceable></optional>
hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>CIDR-address</replaceable> <replaceable>auth-method</replaceable> <optional><replaceable>auth-option</replaceable></optional> hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>CIDR-address</replaceable> <replaceable>auth-method</replaceable> <optional><replaceable>auth-options</replaceable></optional>
host <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>IP-address</replaceable> <replaceable>IP-mask</replaceable> <replaceable>auth-method</replaceable> <optional><replaceable>auth-option</replaceable></optional> host <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>IP-address</replaceable> <replaceable>IP-mask</replaceable> <replaceable>auth-method</replaceable> <optional><replaceable>auth-options</replaceable></optional>
hostssl <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>IP-address</replaceable> <replaceable>IP-mask</replaceable> <replaceable>auth-method</replaceable> <optional><replaceable>auth-option</replaceable></optional> hostssl <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>IP-address</replaceable> <replaceable>IP-mask</replaceable> <replaceable>auth-method</replaceable> <optional><replaceable>auth-options</replaceable></optional>
hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>IP-address</replaceable> <replaceable>IP-mask</replaceable> <replaceable>auth-method</replaceable> <optional><replaceable>auth-option</replaceable></optional> hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>IP-address</replaceable> <replaceable>IP-mask</replaceable> <replaceable>auth-method</replaceable> <optional><replaceable>auth-options</replaceable></optional>
</synopsis> </synopsis>
The meaning of the fields is as follows: The meaning of the fields is as follows:
...@@ -422,11 +422,13 @@ hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable> ...@@ -422,11 +422,13 @@ hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><replaceable>auth-option</replaceable></term> <term><replaceable>auth-options</replaceable></term>
<listitem> <listitem>
<para> <para>
The meaning of this optional field depends on the chosen This field contains zero or more name-value pairs with
authentication method. Details appear below. extra options passed to this authentication method. Details
about which options are available for which authentication
method appear below.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
...@@ -534,7 +536,7 @@ host all all 0.0.0.0/0 krb5 ...@@ -534,7 +536,7 @@ host all all 0.0.0.0/0 krb5
# "omicron" that says "bryanh" is allowed to connect as "guest1". # "omicron" that says "bryanh" is allowed to connect as "guest1".
# #
# TYPE DATABASE USER CIDR-ADDRESS METHOD # TYPE DATABASE USER CIDR-ADDRESS METHOD
host all all 192.168.0.0/16 ident omicron host all all 192.168.0.0/16 ident map=omicron
# If these are the only three lines for local connections, they will # If these are the only three lines for local connections, they will
# allow local users to connect only to their own databases (databases # allow local users to connect only to their own databases (databases
...@@ -557,6 +559,92 @@ local db1,db2,@demodbs all md5 ...@@ -557,6 +559,92 @@ local db1,db2,@demodbs all md5
</example> </example>
</sect1> </sect1>
<sect1 id="auth-username-maps">
<title>Username maps</title>
<indexterm zone="auth-username-maps">
<primary>Username maps</primary>
</indexterm>
<para>
When using an external authentication system like Ident or GSSAPI,
the name of the operating system user that initiated the connection may
not be the same as the database user he is requesting to connect as.
In this case, a user name map can be applied to map the operating system
username to a database user, using the <filename>pg_ident.conf</filename>
file. In order to use username mapping, specify
<literal>map</literal>=<replaceable>map-name</replaceable>
in the options field in <filename>pg_hba.conf</filename>. This option is
supported for all authentication methods that receive external usernames.
Since the <filename>pg_ident.conf</filename> file can contain multiple maps,
the name of the map to be used is specified in the
<replaceable>map-name</replaceable> parameter in <filename>pg_hba.conf</filename>
to indicate which map to use for each individual connection.
</para>
<para>
Ident maps are defined in the ident map file, which by default is named
<filename>pg_ident.conf</><indexterm><primary>pg_ident.conf</primary></indexterm>
and is stored in the
cluster's data directory. (It is possible to place the map file
elsewhere, however; see the <xref linkend="guc-ident-file">
configuration parameter.)
The ident map file contains lines of the general form:
<synopsis>
<replaceable>map-name</> <replaceable>system-username</> <replaceable>database-username</>
</synopsis>
Comments and whitespace are handled in the same way as in
<filename>pg_hba.conf</>. The
<replaceable>map-name</> is an arbitrary name that will be used to
refer to this mapping in <filename>pg_hba.conf</filename>. The other
two fields specify which operating system user is allowed to connect
as which database user. The same <replaceable>map-name</> can be
used repeatedly to specify more user-mappings within a single map.
There is no restriction regarding how many database users a given
operating system user can correspond to, nor vice versa.
</para>
<para>
The <filename>pg_ident.conf</filename> file is read on start-up and
when the main server process receives a
<systemitem>SIGHUP</systemitem><indexterm><primary>SIGHUP</primary></indexterm>
signal. If you edit the file on an
active system, you will need to signal the server
(using <literal>pg_ctl reload</> or <literal>kill -HUP</>) to make it
re-read the file.
</para>
<para>
A <filename>pg_ident.conf</filename> file that could be used in
conjunction with the <filename>pg_hba.conf</> file in <xref
linkend="example-pg-hba.conf"> is shown in <xref
linkend="example-pg-ident.conf">. In this example setup, anyone
logged in to a machine on the 192.168 network that does not have the
Unix user name <literal>bryanh</>, <literal>ann</>, or
<literal>robert</> would not be granted access. Unix user
<literal>robert</> would only be allowed access when he tries to
connect as <productname>PostgreSQL</> user <literal>bob</>, not
as <literal>robert</> or anyone else. <literal>ann</> would
only be allowed to connect as <literal>ann</>. User
<literal>bryanh</> would be allowed to connect as either
<literal>bryanh</> himself or as <literal>guest1</>.
</para>
<example id="example-pg-ident.conf">
<title>An example <filename>pg_ident.conf</> file</title>
<programlisting>
# MAPNAME IDENT-USERNAME PG-USERNAME
omicron bryanh bryanh
omicron ann ann
# bob has user name robert on these machines
omicron robert bob
# bryanh can also connect as guest1
omicron bryanh guest1
</programlisting>
</example>
</sect1>
<sect1 id="auth-methods"> <sect1 id="auth-methods">
<title>Authentication methods</title> <title>Authentication methods</title>
<para> <para>
...@@ -685,7 +773,21 @@ local db1,db2,@demodbs all md5 ...@@ -685,7 +773,21 @@ local db1,db2,@demodbs all md5
GSSAPI support has to be enabled when <productname>PostgreSQL</> is built; GSSAPI support has to be enabled when <productname>PostgreSQL</> is built;
see <xref linkend="installation"> for more information. see <xref linkend="installation"> for more information.
</para> </para>
<para>
The following configuration options are supported for <productname>GSSAPI</productname>:
<variablelist>
<varlistentry>
<term>map</term>
<listitem>
<para>
Allows for mapping between system and database usernames. See
<xref linkend="auth-username-maps"> for details.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</sect2> </sect2>
<sect2 id="sspi-auth"> <sect2 id="sspi-auth">
...@@ -713,6 +815,20 @@ local db1,db2,@demodbs all md5 ...@@ -713,6 +815,20 @@ local db1,db2,@demodbs all md5
for details. for details.
</para> </para>
<para>
The following configuration options are supported for <productname>SSPI</productname>:
<variablelist>
<varlistentry>
<term>map</term>
<listitem>
<para>
Allows for mapping between system and database usernames. See
<xref linkend="auth-username-maps"> for details.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</sect2> </sect2>
<sect2 id="kerberos-auth"> <sect2 id="kerberos-auth">
...@@ -846,6 +962,21 @@ local db1,db2,@demodbs all md5 ...@@ -846,6 +962,21 @@ local db1,db2,@demodbs all md5
depending on the connection type. depending on the connection type.
</para> </para>
<para>
The following configuration options are supported for <productname>GSSAPI</productname>:
<variablelist>
<varlistentry>
<term>map</term>
<listitem>
<para>
Allows for mapping between system and database usernames. See
<xref linkend="auth-username-maps"> for details.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<sect3> <sect3>
<title>Ident Authentication over TCP/IP</title> <title>Ident Authentication over TCP/IP</title>
...@@ -918,83 +1049,6 @@ local db1,db2,@demodbs all md5 ...@@ -918,83 +1049,6 @@ local db1,db2,@demodbs all md5
</para> </para>
</sect3> </sect3>
<sect3 id="auth-ident-maps">
<title>Ident Maps</title>
<para>
When using ident-based authentication, after having determined the
name of the operating system user that initiated the connection,
<productname>PostgreSQL</productname> checks whether that user is
allowed to connect as the database user he is requesting to connect
as. This is controlled by the ident map argument that follows the
<literal>ident</> key word in the <filename>pg_hba.conf</filename>
file. If an ident map is not specified, the database user will be
checked with the same name as the operating system user. Other maps
must be created manually.
</para>
<para>
Ident maps are defined in the ident map file, which by default is named
<filename>pg_ident.conf</><indexterm><primary>pg_ident.conf</primary></indexterm>
and is stored in the
cluster's data directory. (It is possible to place the map file
elsewhere, however; see the <xref linkend="guc-ident-file">
configuration parameter.)
The ident map file contains lines of the general form:
<synopsis>
<replaceable>map-name</> <replaceable>ident-username</> <replaceable>database-username</>
</synopsis>
Comments and whitespace are handled in the same way as in
<filename>pg_hba.conf</>. The
<replaceable>map-name</> is an arbitrary name that will be used to
refer to this mapping in <filename>pg_hba.conf</filename>. The other
two fields specify which operating system user is allowed to connect
as which database user. The same <replaceable>map-name</> can be
used repeatedly to specify more user-mappings within a single map.
There is no restriction regarding how many database users a given
operating system user can correspond to, nor vice versa.
</para>
<para>
The <filename>pg_ident.conf</filename> file is read on start-up and
when the main server process receives a
<systemitem>SIGHUP</systemitem><indexterm><primary>SIGHUP</primary></indexterm>
signal. If you edit the file on an
active system, you will need to signal the server
(using <literal>pg_ctl reload</> or <literal>kill -HUP</>) to make it
re-read the file.
</para>
<para>
A <filename>pg_ident.conf</filename> file that could be used in
conjunction with the <filename>pg_hba.conf</> file in <xref
linkend="example-pg-hba.conf"> is shown in <xref
linkend="example-pg-ident.conf">. In this example setup, anyone
logged in to a machine on the 192.168 network that does not have the
Unix user name <literal>bryanh</>, <literal>ann</>, or
<literal>robert</> would not be granted access. Unix user
<literal>robert</> would only be allowed access when he tries to
connect as <productname>PostgreSQL</> user <literal>bob</>, not
as <literal>robert</> or anyone else. <literal>ann</> would
only be allowed to connect as <literal>ann</>. User
<literal>bryanh</> would be allowed to connect as either
<literal>bryanh</> himself or as <literal>guest1</>.
</para>
<example id="example-pg-ident.conf">
<title>An example <filename>pg_ident.conf</> file</title>
<programlisting>
# MAPNAME IDENT-USERNAME PG-USERNAME
omicron bryanh bryanh
omicron ann ann
# bob has user name robert on these machines
omicron robert bob
# bryanh can also connect as guest1
omicron bryanh guest1
</programlisting>
</example>
</sect3>
</sect2> </sect2>
<sect2 id="auth-ldap"> <sect2 id="auth-ldap">
...@@ -1007,49 +1061,84 @@ omicron bryanh guest1 ...@@ -1007,49 +1061,84 @@ omicron bryanh guest1
<para> <para>
This authentication method operates similarly to This authentication method operates similarly to
<literal>password</literal> except that it uses LDAP <literal>password</literal> except that it uses LDAP
as the authentication method. LDAP is used only to validate as the password verification method. LDAP is used only to validate
the user name/password pairs. Therefore the user must already the user name/password pairs. Therefore the user must already
exist in the database before LDAP can be used for exist in the database before LDAP can be used for
authentication. The server and parameters used are specified authentication.
after the <literal>ldap</> key word in the file
<filename>pg_hba.conf</filename>. The format of this parameter is:
<synopsis>
ldap[<replaceable>s</>]://<replaceable>servername</>[:<replaceable>port</>]/<replaceable>base dn</replaceable>[;<replaceable>prefix</>[;<replaceable>suffix</>]]
</synopsis>
Commas are used to specify multiple items in an <literal>ldap</>
component. However, because unquoted commas are treated as item
separators in <filename>pg_hba.conf</filename>, it is wise to
double-quote the <literal>ldap</> URL to preserve any commas present,
e.g.:
<synopsis>
"ldap://ldap.example.net/dc=example,dc=net;EXAMPLE\"
</synopsis>
</para>
<para>
If <literal>ldaps</> is specified instead of <literal>ldap</>,
TLS encryption will be enabled for the connection. Note that this
will encrypt only the connection between the PostgreSQL server
and the LDAP server. The connection between the client and the
PostgreSQL server is not affected by this setting. To make use of
TLS encryption, you might need to configure the LDAP library prior
to configuring PostgreSQL. Note that encrypted LDAP is available only
if the platform's LDAP library supports it.
</para>
<para>
If no port is specified, the default port as configured in the
LDAP library will be used.
</para> </para>
<para> <para>
The server will bind to the distinguished name specified as The server will bind to the distinguished name constructed as
<replaceable>base dn</> using the user name supplied by the client. <replaceable>prefix</> <replaceable>username</> <replaceable>suffix</>.
If <replaceable>prefix</> and <replaceable>suffix</> is
specified, it will be prepended and appended to the user name
before the bind. Typically, the prefix parameter is used to specify before the bind. Typically, the prefix parameter is used to specify
<replaceable>cn=</>, or <replaceable>DOMAIN\</> in an Active <replaceable>cn=</>, or <replaceable>DOMAIN\</> in an Active
Directory environment. Directory environment, and suffix is used to specify the remaining part
of the DN in a non-Active Directory environment.
</para> </para>
<para>
The following configuration options are supported for LDAP:
<variablelist>
<varlistentry>
<term>ldapserver</term>
<listitem>
<para>
Name or IP of LDAP server to connect to.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>ldapprefix</term>
<listitem>
<para>
String to prepend to the username when building the base DN to
bind as.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>ldapsuffix</term>
<listitem>
<para>
String to append to the username when building the base DN to
bind as.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>ldapport</term>
<listitem>
<para>
Port number on LDAP server to connect to. If no port is specified,
the default port in the LDAP library will be used.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>ldaptls</term>
<listitem>
<para>
Set to 1 to make the connection between PostgreSQL and the
LDAP server use TLS encryption. Note that this only encrypts
the traffic to the LDAP server - the connection to the client
may still be unencrypted unless TLS is used there as well.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<note>
<para>
Since LDAP often uses commas and spaces to separate the different
parts of a DN, it is advised to always use double-quoted parameter
values when configuring LDAP options, such as:
</para>
</note>
<synopsis>
ldapserver=ldap.example.net prefix="cn=" suffix="dc=example, dc=net"
</synopsis>
</sect2> </sect2>
<sect2 id="auth-pam"> <sect2 id="auth-pam">
...@@ -1063,9 +1152,7 @@ ldap[<replaceable>s</>]://<replaceable>servername</>[:<replaceable>port</>]/<rep ...@@ -1063,9 +1152,7 @@ ldap[<replaceable>s</>]://<replaceable>servername</>[:<replaceable>port</>]/<rep
This authentication method operates similarly to This authentication method operates similarly to
<literal>password</literal> except that it uses PAM (Pluggable <literal>password</literal> except that it uses PAM (Pluggable
Authentication Modules) as the authentication mechanism. The Authentication Modules) as the authentication mechanism. The
default PAM service name is <literal>postgresql</literal>. You can default PAM service name is <literal>postgresql</literal>.
optionally supply your own service name after the <literal>pam</>
key word in the file <filename>pg_hba.conf</filename>.
PAM is used only to validate user name/password pairs. PAM is used only to validate user name/password pairs.
Therefore the user must already exist in the database before PAM Therefore the user must already exist in the database before PAM
can be used for authentication. For more information about can be used for authentication. For more information about
...@@ -1075,6 +1162,20 @@ ldap[<replaceable>s</>]://<replaceable>servername</>[:<replaceable>port</>]/<rep ...@@ -1075,6 +1162,20 @@ ldap[<replaceable>s</>]://<replaceable>servername</>[:<replaceable>port</>]/<rep
<systemitem class="osname">Solaris</> PAM Page</ulink>. <systemitem class="osname">Solaris</> PAM Page</ulink>.
</para> </para>
<para>
The following configuration options are supported for PAM:
<variablelist>
<varlistentry>
<term>pamservice</term>
<listitem>
<para>
PAM service name.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<note> <note>
<para> <para>
If PAM is set up to read <filename>/etc/shadow</>, authentication If PAM is set up to read <filename>/etc/shadow</>, authentication
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/libpq/auth.c,v 1.168 2008/09/15 12:32:56 mha Exp $ * $PostgreSQL: pgsql/src/backend/libpq/auth.c,v 1.169 2008/10/23 13:31:10 mha Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -126,9 +126,8 @@ char *pg_krb_realm = NULL; ...@@ -126,9 +126,8 @@ char *pg_krb_realm = NULL;
* MIT Kerberos authentication system - protocol version 5 * MIT Kerberos authentication system - protocol version 5
*---------------------------------------------------------------- *----------------------------------------------------------------
*/ */
static int pg_krb5_recvauth(Port *port);
#ifdef KRB5 #ifdef KRB5
static int pg_krb5_recvauth(Port *port);
#include <krb5.h> #include <krb5.h>
/* Some old versions of Kerberos do not include <com_err.h> in <krb5.h> */ /* Some old versions of Kerberos do not include <com_err.h> in <krb5.h> */
...@@ -150,14 +149,14 @@ static krb5_principal pg_krb5_server; ...@@ -150,14 +149,14 @@ static krb5_principal pg_krb5_server;
* GSSAPI Authentication * GSSAPI Authentication
*---------------------------------------------------------------- *----------------------------------------------------------------
*/ */
static int pg_GSS_recvauth(Port *port);
#ifdef ENABLE_GSS #ifdef ENABLE_GSS
#if defined(HAVE_GSSAPI_H) #if defined(HAVE_GSSAPI_H)
#include <gssapi.h> #include <gssapi.h>
#else #else
#include <gssapi/gssapi.h> #include <gssapi/gssapi.h>
#endif #endif
static int pg_GSS_recvauth(Port *port);
#endif /* ENABLE_GSS */ #endif /* ENABLE_GSS */
...@@ -165,12 +164,11 @@ static int pg_GSS_recvauth(Port *port); ...@@ -165,12 +164,11 @@ static int pg_GSS_recvauth(Port *port);
* SSPI Authentication * SSPI Authentication
*---------------------------------------------------------------- *----------------------------------------------------------------
*/ */
static int pg_SSPI_recvauth(Port *port);
#ifdef ENABLE_SSPI #ifdef ENABLE_SSPI
typedef SECURITY_STATUS typedef SECURITY_STATUS
(WINAPI * QUERY_SECURITY_CONTEXT_TOKEN_FN) ( (WINAPI * QUERY_SECURITY_CONTEXT_TOKEN_FN) (
PCtxtHandle, void **); PCtxtHandle, void **);
static int pg_SSPI_recvauth(Port *port);
#endif #endif
...@@ -236,16 +234,12 @@ auth_failed(Port *port, int status) ...@@ -236,16 +234,12 @@ auth_failed(Port *port, int status)
case uaPassword: case uaPassword:
errstr = gettext_noop("password authentication failed for user \"%s\""); errstr = gettext_noop("password authentication failed for user \"%s\"");
break; break;
#ifdef USE_PAM
case uaPAM: case uaPAM:
errstr = gettext_noop("PAM authentication failed for user \"%s\""); errstr = gettext_noop("PAM authentication failed for user \"%s\"");
break; break;
#endif /* USE_PAM */
#ifdef USE_LDAP
case uaLDAP: case uaLDAP:
errstr = gettext_noop("LDAP authentication failed for user \"%s\""); errstr = gettext_noop("LDAP authentication failed for user \"%s\"");
break; break;
#endif /* USE_LDAP */
default: default:
errstr = gettext_noop("authentication failed for user \"%s\": invalid authentication method"); errstr = gettext_noop("authentication failed for user \"%s\": invalid authentication method");
break; break;
...@@ -316,18 +310,30 @@ ClientAuthentication(Port *port) ...@@ -316,18 +310,30 @@ ClientAuthentication(Port *port)
} }
case uaKrb5: case uaKrb5:
#ifdef KRB5
sendAuthRequest(port, AUTH_REQ_KRB5); sendAuthRequest(port, AUTH_REQ_KRB5);
status = pg_krb5_recvauth(port); status = pg_krb5_recvauth(port);
#else
Assert(false);
#endif
break; break;
case uaGSS: case uaGSS:
#ifdef ENABLE_GSS
sendAuthRequest(port, AUTH_REQ_GSS); sendAuthRequest(port, AUTH_REQ_GSS);
status = pg_GSS_recvauth(port); status = pg_GSS_recvauth(port);
#else
Assert(false);
#endif
break; break;
case uaSSPI: case uaSSPI:
#ifdef ENABLE_SSPI
sendAuthRequest(port, AUTH_REQ_SSPI); sendAuthRequest(port, AUTH_REQ_SSPI);
status = pg_SSPI_recvauth(port); status = pg_SSPI_recvauth(port);
#else
Assert(false);
#endif
break; break;
case uaIdent: case uaIdent:
...@@ -377,18 +383,22 @@ ClientAuthentication(Port *port) ...@@ -377,18 +383,22 @@ ClientAuthentication(Port *port)
status = recv_and_check_password_packet(port); status = recv_and_check_password_packet(port);
break; break;
#ifdef USE_PAM
case uaPAM: case uaPAM:
#ifdef USE_PAM
pam_port_cludge = port; pam_port_cludge = port;
status = CheckPAMAuth(port, port->user_name, ""); status = CheckPAMAuth(port, port->user_name, "");
break; #else
Assert(false);
#endif /* USE_PAM */ #endif /* USE_PAM */
break;
#ifdef USE_LDAP
case uaLDAP: case uaLDAP:
#ifdef USE_LDAP
status = CheckLDAPAuth(port); status = CheckLDAPAuth(port);
break; #else
Assert(false);
#endif #endif
break;
case uaTrust: case uaTrust:
status = STATUS_OK; status = STATUS_OK;
...@@ -713,19 +723,8 @@ pg_krb5_recvauth(Port *port) ...@@ -713,19 +723,8 @@ pg_krb5_recvauth(Port *port)
return STATUS_ERROR; return STATUS_ERROR;
} }
if (pg_krb_caseins_users) ret = check_usermap(port->hba->usermap, port->user_name, kusername,
ret = pg_strncasecmp(port->user_name, kusername, SM_DATABASE_USER); pg_krb_caseins_users);
else
ret = strncmp(port->user_name, kusername, SM_DATABASE_USER);
if (ret)
{
ereport(LOG,
(errmsg("unexpected Kerberos user name received from client (received \"%s\", expected \"%s\")",
port->user_name, kusername)));
ret = STATUS_ERROR;
}
else
ret = STATUS_OK;
krb5_free_ticket(pg_krb5_context, ticket); krb5_free_ticket(pg_krb5_context, ticket);
krb5_auth_con_free(pg_krb5_context, auth_context); krb5_auth_con_free(pg_krb5_context, auth_context);
...@@ -733,16 +732,6 @@ pg_krb5_recvauth(Port *port) ...@@ -733,16 +732,6 @@ pg_krb5_recvauth(Port *port)
return ret; return ret;
} }
#else
static int
pg_krb5_recvauth(Port *port)
{
ereport(LOG,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("Kerberos 5 not implemented on this server")));
return STATUS_ERROR;
}
#endif /* KRB5 */ #endif /* KRB5 */
...@@ -1020,38 +1009,13 @@ pg_GSS_recvauth(Port *port) ...@@ -1020,38 +1009,13 @@ pg_GSS_recvauth(Port *port)
return STATUS_ERROR; return STATUS_ERROR;
} }
if (pg_krb_caseins_users) ret = check_usermap(port->hba->usermap, port->user_name, gbuf.value,
ret = pg_strcasecmp(port->user_name, gbuf.value); pg_krb_caseins_users);
else
ret = strcmp(port->user_name, gbuf.value);
if (ret)
{
/* GSS name and PGUSER are not equivalent */
elog(DEBUG2,
"provided username (%s) and GSSAPI username (%s) don't match",
port->user_name, (char *) gbuf.value);
gss_release_buffer(&lmin_s, &gbuf);
return STATUS_ERROR;
}
gss_release_buffer(&lmin_s, &gbuf); gss_release_buffer(&lmin_s, &gbuf);
return STATUS_OK; return STATUS_OK;
} }
#else /* no ENABLE_GSS */
static int
pg_GSS_recvauth(Port *port)
{
ereport(LOG,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("GSSAPI not implemented on this server")));
return STATUS_ERROR;
}
#endif /* ENABLE_GSS */ #endif /* ENABLE_GSS */
...@@ -1328,30 +1292,8 @@ pg_SSPI_recvauth(Port *port) ...@@ -1328,30 +1292,8 @@ pg_SSPI_recvauth(Port *port)
* We have the username (without domain/realm) in accountname, compare to * We have the username (without domain/realm) in accountname, compare to
* the supplied value. In SSPI, always compare case insensitive. * the supplied value. In SSPI, always compare case insensitive.
*/ */
if (pg_strcasecmp(port->user_name, accountname)) return check_usermap(port->hba->usermap, port->user_name, accountname, true);
{
/* GSS name and PGUSER are not equivalent */
elog(DEBUG2,
"provided username (%s) and SSPI username (%s) don't match",
port->user_name, accountname);
return STATUS_ERROR;
}
return STATUS_OK;
} }
#else /* no ENABLE_SSPI */
static int
pg_SSPI_recvauth(Port *port)
{
ereport(LOG,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("SSPI not implemented on this server")));
return STATUS_ERROR;
}
#endif /* ENABLE_SSPI */ #endif /* ENABLE_SSPI */
...@@ -1795,14 +1737,7 @@ authident(hbaPort *port) ...@@ -1795,14 +1737,7 @@ authident(hbaPort *port)
return STATUS_ERROR; return STATUS_ERROR;
} }
ereport(DEBUG2, return check_usermap(port->hba->usermap, port->user_name, ident_user, false);
(errmsg("Ident protocol identifies remote user as \"%s\"",
ident_user)));
if (check_ident_usermap(port->hba->usermap, port->user_name, ident_user))
return STATUS_OK;
else
return STATUS_ERROR;
} }
...@@ -1913,8 +1848,8 @@ CheckPAMAuth(Port *port, char *user, char *password) ...@@ -1913,8 +1848,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->hba->auth_arg && port->hba->auth_arg[0] != '\0') if (port->hba->pamservice && port->hba->pamservice[0] != '\0')
retval = pam_start(port->hba->auth_arg, "pgsql@", retval = pam_start(port->hba->pamservice, "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@",
...@@ -2000,76 +1935,20 @@ static int ...@@ -2000,76 +1935,20 @@ static int
CheckLDAPAuth(Port *port) CheckLDAPAuth(Port *port)
{ {
char *passwd; char *passwd;
char server[128];
char basedn[128];
char prefix[128];
char suffix[128];
LDAP *ldap; LDAP *ldap;
bool ssl = false;
int r; int r;
int ldapversion = LDAP_VERSION3; int ldapversion = LDAP_VERSION3;
int ldapport = LDAP_PORT;
char fulluser[NAMEDATALEN + 256 + 1]; char fulluser[NAMEDATALEN + 256 + 1];
if (!port->hba->auth_arg || port->hba->auth_arg[0] == '\0') if (!port->hba->ldapserver|| port->hba->ldapserver[0] == '\0')
{ {
ereport(LOG, ereport(LOG,
(errmsg("LDAP configuration URL not specified"))); (errmsg("LDAP server not specified")));
return STATUS_ERROR; return STATUS_ERROR;
} }
/* if (port->hba->ldapport == 0)
* Crack the LDAP url. We do a very trivial parse: port->hba->ldapport = LDAP_PORT;
*
* ldap[s]://<server>[:<port>]/<basedn>[;prefix[;suffix]]
*
* This code originally used "%127s" for the suffix, but that doesn't
* work for embedded whitespace. We know that tokens formed by
* hba.c won't include newlines, so we can use a "not newline" scanset
* instead.
*/
server[0] = '\0';
basedn[0] = '\0';
prefix[0] = '\0';
suffix[0] = '\0';
/* ldap, including port number */
r = sscanf(port->hba->auth_arg,
"ldap://%127[^:]:%d/%127[^;];%127[^;];%127[^\n]",
server, &ldapport, basedn, prefix, suffix);
if (r < 3)
{
/* ldaps, including port number */
r = sscanf(port->hba->auth_arg,
"ldaps://%127[^:]:%d/%127[^;];%127[^;];%127[^\n]",
server, &ldapport, basedn, prefix, suffix);
if (r >= 3)
ssl = true;
}
if (r < 3)
{
/* ldap, no port number */
r = sscanf(port->hba->auth_arg,
"ldap://%127[^/]/%127[^;];%127[^;];%127[^\n]",
server, basedn, prefix, suffix);
}
if (r < 2)
{
/* ldaps, no port number */
r = sscanf(port->hba->auth_arg,
"ldaps://%127[^/]/%127[^;];%127[^;];%127[^\n]",
server, basedn, prefix, suffix);
if (r >= 2)
ssl = true;
}
if (r < 2)
{
ereport(LOG,
(errmsg("invalid LDAP URL: \"%s\"",
port->hba->auth_arg)));
return STATUS_ERROR;
}
sendAuthRequest(port, AUTH_REQ_PASSWORD); sendAuthRequest(port, AUTH_REQ_PASSWORD);
...@@ -2077,7 +1956,7 @@ CheckLDAPAuth(Port *port) ...@@ -2077,7 +1956,7 @@ CheckLDAPAuth(Port *port)
if (passwd == NULL) if (passwd == NULL)
return STATUS_EOF; /* client wouldn't send password */ return STATUS_EOF; /* client wouldn't send password */
ldap = ldap_init(server, ldapport); ldap = ldap_init(port->hba->ldapserver, port->hba->ldapport);
if (!ldap) if (!ldap)
{ {
#ifndef WIN32 #ifndef WIN32
...@@ -2100,7 +1979,7 @@ CheckLDAPAuth(Port *port) ...@@ -2100,7 +1979,7 @@ CheckLDAPAuth(Port *port)
return STATUS_ERROR; return STATUS_ERROR;
} }
if (ssl) if (port->hba->ldaptls)
{ {
#ifndef WIN32 #ifndef WIN32
if ((r = ldap_start_tls_s(ldap, NULL, NULL)) != LDAP_SUCCESS) if ((r = ldap_start_tls_s(ldap, NULL, NULL)) != LDAP_SUCCESS)
...@@ -2155,7 +2034,9 @@ CheckLDAPAuth(Port *port) ...@@ -2155,7 +2034,9 @@ CheckLDAPAuth(Port *port)
} }
snprintf(fulluser, sizeof(fulluser), "%s%s%s", snprintf(fulluser, sizeof(fulluser), "%s%s%s",
prefix, port->user_name, suffix); port->hba->ldapprefix ? port->hba->ldapprefix : "",
port->user_name,
port->hba->ldapsuffix ? port->hba->ldapsuffix : "");
fulluser[sizeof(fulluser) - 1] = '\0'; fulluser[sizeof(fulluser) - 1] = '\0';
r = ldap_simple_bind_s(ldap, fulluser, passwd); r = ldap_simple_bind_s(ldap, fulluser, passwd);
...@@ -2165,7 +2046,7 @@ CheckLDAPAuth(Port *port) ...@@ -2165,7 +2046,7 @@ CheckLDAPAuth(Port *port)
{ {
ereport(LOG, ereport(LOG,
(errmsg("LDAP login failed for user \"%s\" on server \"%s\": error code %d", (errmsg("LDAP login failed for user \"%s\" on server \"%s\": error code %d",
fulluser, server, r))); fulluser, port->hba->ldapserver, r)));
return STATUS_ERROR; return STATUS_ERROR;
} }
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.168 2008/09/15 20:55:04 mha Exp $ * $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.169 2008/10/23 13:31:10 mha Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -564,6 +564,44 @@ check_db(const char *dbname, const char *role, char *param_str) ...@@ -564,6 +564,44 @@ check_db(const char *dbname, const char *role, char *param_str)
} }
/*
* Macros used to check and report on invalid configuration options.
* INVALID_AUTH_OPTION = reports when an option is specified for a method where it's
* not supported.
* REQUIRE_AUTH_OPTION = same as INVALID_AUTH_OPTION, except it also checks if the
* method is actually the one specified. Used as a shortcut when
* the option is only valid for one authentication method.
* MANDATORY_AUTH_ARG = check if a required option is set for an authentication method,
* reporting error if it's not.
*/
#define INVALID_AUTH_OPTION(optname, validmethods) do {\
ereport(LOG, \
(errcode(ERRCODE_CONFIG_FILE_ERROR), \
errmsg("authentication option '%s' is only valid for authentication methods '%s'", \
optname, validmethods), \
errcontext("line %d of configuration file \"%s\"", \
line_num, HbaFileName))); \
goto hba_other_error; \
} while (0);
#define REQUIRE_AUTH_OPTION(methodval, optname, validmethods) do {\
if (parsedline->auth_method != methodval) \
INVALID_AUTH_OPTION("ldaptls", "ldap"); \
} while (0);
#define MANDATORY_AUTH_ARG(argvar, argname, authname) do {\
if (argvar == NULL) {\
ereport(LOG, \
(errcode(ERRCODE_CONFIG_FILE_ERROR), \
errmsg("authentication method '%s' requires argument '%s' to be set", \
authname, argname), \
errcontext("line %d of configuration file \"%s\"", \
line_num, HbaFileName))); \
goto hba_other_error; \
} \
} while (0);
/* /*
* Parse one line in the hba config file and store the result in * Parse one line in the hba config file and store the result in
* a HbaLine structure. * a HbaLine structure.
...@@ -801,38 +839,102 @@ parse_hba_line(List *line, int line_num, HbaLine *parsedline) ...@@ -801,38 +839,102 @@ parse_hba_line(List *line, int line_num, HbaLine *parsedline)
goto hba_other_error; goto hba_other_error;
} }
/* Get the authentication argument token, if any */ /* Parse remaining arguments */
line_item = lnext(line_item); while ((line_item = lnext(line_item)) != NULL)
if (line_item)
{ {
char *c;
token = lfirst(line_item); token = lfirst(line_item);
parsedline->auth_arg= pstrdup(token);
}
/* c = strchr(token, '=');
* Backwards compatible format of ident authentication - support "naked" ident map if (c == NULL)
* 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) * Got something that's not a name=value pair.
*
* XXX: attempt to do some backwards compatible parsing here?
*/
ereport(LOG,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("authentication option not in name=value format: %s", token),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
goto hba_other_error;
}
else
{
*c++ = '\0'; /* token now holds "name", c holds "value" */
if (strcmp(token, "map") == 0)
{
if (parsedline->auth_method != uaIdent &&
parsedline->auth_method != uaKrb5 &&
parsedline->auth_method != uaGSS &&
parsedline->auth_method != uaSSPI)
INVALID_AUTH_OPTION("map", "ident, krb5, gssapi and sspi");
parsedline->usermap = pstrdup(c);
}
else if (strcmp(token, "pamservice") == 0)
{
REQUIRE_AUTH_OPTION(uaPAM, "pamservice", "pam");
parsedline->pamservice = pstrdup(c);
}
else if (strcmp(token, "ldaptls") == 0)
{
REQUIRE_AUTH_OPTION(uaLDAP, "ldaptls", "ldap");
if (strcmp(c, "1") == 0)
parsedline->ldaptls = true;
else
parsedline->ldaptls = false;
}
else if (strcmp(token, "ldapserver") == 0)
{
REQUIRE_AUTH_OPTION(uaLDAP, "ldapserver", "ldap");
parsedline->ldapserver = pstrdup(c);
}
else if (strcmp(token, "ldapport") == 0)
{
REQUIRE_AUTH_OPTION(uaLDAP, "ldapport", "ldap");
parsedline->ldapport = atoi(c);
if (parsedline->ldapport == 0)
{
ereport(LOG,
(errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("invalid ldap port '%s'", c),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
goto hba_other_error;
}
}
else if (strcmp(token, "ldapprefix") == 0)
{ {
/* This is now the default */ REQUIRE_AUTH_OPTION(uaLDAP, "ldapprefix", "ldap");
pfree(parsedline->auth_arg); parsedline->ldapprefix = pstrdup(c);
parsedline->auth_arg = NULL; }
parsedline->usermap = NULL; else if (strcmp(token, "ldapsuffix") == 0)
{
REQUIRE_AUTH_OPTION(uaLDAP, "ldapsuffix", "ldap");
parsedline->ldapsuffix = pstrdup(c);
} }
else else
{ {
/* Specific ident map specified */ ereport(LOG,
parsedline->usermap = parsedline->auth_arg; (errcode(ERRCODE_CONFIG_FILE_ERROR),
parsedline->auth_arg = NULL; errmsg("unknown authentication option name '%s'", token),
errcontext("line %d of configuration file \"%s\"",
line_num, HbaFileName)));
goto hba_other_error;
} }
} }
} }
/*
* Check if the selected authentication method has any mandatory arguments that
* are not set.
*/
if (parsedline->auth_method == uaLDAP)
{
MANDATORY_AUTH_ARG(parsedline->ldapserver, "ldapserver", "ldap");
}
return true; return true;
...@@ -1018,8 +1120,14 @@ free_hba_record(HbaLine *record) ...@@ -1018,8 +1120,14 @@ free_hba_record(HbaLine *record)
pfree(record->database); pfree(record->database);
if (record->role) if (record->role)
pfree(record->role); pfree(record->role);
if (record->auth_arg) if (record->pamservice)
pfree(record->auth_arg); pfree(record->pamservice);
if (record->ldapserver)
pfree(record->ldapserver);
if (record->ldapprefix)
pfree(record->ldapprefix);
if (record->ldapsuffix)
pfree(record->ldapsuffix);
} }
/* /*
...@@ -1150,7 +1258,7 @@ read_pg_database_line(FILE *fp, char *dbname, Oid *dboid, ...@@ -1150,7 +1258,7 @@ read_pg_database_line(FILE *fp, char *dbname, Oid *dboid,
static void static void
parse_ident_usermap(List *line, int line_number, const char *usermap_name, parse_ident_usermap(List *line, int line_number, const char *usermap_name,
const char *pg_role, const char *ident_user, const char *pg_role, const char *ident_user,
bool *found_p, bool *error_p) bool case_insensitive, bool *found_p, bool *error_p)
{ {
ListCell *line_item; ListCell *line_item;
char *token; char *token;
...@@ -1183,10 +1291,20 @@ parse_ident_usermap(List *line, int line_number, const char *usermap_name, ...@@ -1183,10 +1291,20 @@ parse_ident_usermap(List *line, int line_number, const char *usermap_name,
file_pgrole = token; file_pgrole = token;
/* Match? */ /* Match? */
if (strcmp(file_map, usermap_name) == 0 && if (case_insensitive)
strcmp(file_pgrole, pg_role) == 0 && {
strcmp(file_ident_user, ident_user) == 0) if (strcmp(file_map, usermap_name) == 0 &&
*found_p = true; pg_strcasecmp(file_pgrole, pg_role) == 0 &&
pg_strcasecmp(file_ident_user, ident_user) == 0)
*found_p = true;
}
else
{
if (strcmp(file_map, usermap_name) == 0 &&
strcmp(file_pgrole, pg_role) == 0 &&
strcmp(file_ident_user, ident_user) == 0)
*found_p = true;
}
return; return;
...@@ -1210,22 +1328,32 @@ ident_syntax: ...@@ -1210,22 +1328,32 @@ ident_syntax:
* 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.
* *
* Iff authorized, return true. * Iff authorized, return STATUS_OK, otherwise return STATUS_ERROR.
*/ */
bool int
check_ident_usermap(const char *usermap_name, check_usermap(const char *usermap_name,
const char *pg_role, const char *pg_role,
const char *ident_user) const char *auth_user,
bool case_insensitive)
{ {
bool found_entry = false, bool found_entry = false,
error = false; error = false;
if (usermap_name == NULL || usermap_name[0] == '\0') if (usermap_name == NULL || usermap_name[0] == '\0')
{ {
if (strcmp(pg_role, ident_user) == 0) if (case_insensitive)
found_entry = true; {
else if (pg_strcasecmp(pg_role, auth_user) == 0)
found_entry = false; return STATUS_OK;
}
else {
if (strcmp(pg_role, auth_user) == 0)
return STATUS_OK;
}
ereport(LOG,
(errmsg("provided username (%s) and authenticated username (%s) don't match",
auth_user, pg_role)));
return STATUS_ERROR;
} }
else else
{ {
...@@ -1235,13 +1363,20 @@ check_ident_usermap(const char *usermap_name, ...@@ -1235,13 +1363,20 @@ check_ident_usermap(const char *usermap_name,
forboth(line_cell, ident_lines, num_cell, ident_line_nums) forboth(line_cell, ident_lines, num_cell, ident_line_nums)
{ {
parse_ident_usermap(lfirst(line_cell), lfirst_int(num_cell), parse_ident_usermap(lfirst(line_cell), lfirst_int(num_cell),
usermap_name, pg_role, ident_user, usermap_name, pg_role, auth_user, case_insensitive,
&found_entry, &error); &found_entry, &error);
if (found_entry || error) if (found_entry || error)
break; break;
} }
} }
return found_entry; if (!found_entry && !error)
{
ereport(LOG,
(errmsg("no match in usermap for user '%s' authenticated as '%s'",
pg_role, auth_user),
errcontext("usermap '%s'", usermap_name)));
}
return found_entry?STATUS_OK:STATUS_ERROR;
} }
......
...@@ -9,10 +9,10 @@ ...@@ -9,10 +9,10 @@
# are authenticated, which PostgreSQL user names they can use, which # are authenticated, which PostgreSQL user names they can use, which
# databases they can access. Records take one of these forms: # databases they can access. Records take one of these forms:
# #
# local DATABASE USER METHOD [OPTION] # local DATABASE USER METHOD [OPTIONS]
# host DATABASE USER CIDR-ADDRESS METHOD [OPTION] # host DATABASE USER CIDR-ADDRESS METHOD [OPTIONS]
# hostssl DATABASE USER CIDR-ADDRESS METHOD [OPTION] # hostssl DATABASE USER CIDR-ADDRESS METHOD [OPTIONS]
# hostnossl DATABASE USER CIDR-ADDRESS METHOD [OPTION] # hostnossl DATABASE USER CIDR-ADDRESS METHOD [OPTIONS]
# #
# (The uppercase items must be replaced by actual values.) # (The uppercase items must be replaced by actual values.)
# #
...@@ -38,7 +38,10 @@ ...@@ -38,7 +38,10 @@
# "krb5", "ident", "pam" or "ldap". Note that "password" sends passwords # "krb5", "ident", "pam" or "ldap". Note that "password" sends passwords
# in clear text; "md5" is preferred since it sends encrypted passwords. # in clear text; "md5" is preferred since it sends encrypted passwords.
# #
# OPTION is the ident map or the name of the PAM service, depending on METHOD. # OPTIONS are a set of options for the authentication in the format
# NAME=VALUE. The available options depend on the different authentication
# methods - refer to the "Client Authentication" section in the documentation
# for a list of which options are available for which authentication methods.
# #
# Database and user names containing spaces, commas, quotes and other special # Database and user names containing spaces, commas, quotes and other special
# characters must be quoted. Quoting one of the keywords "all", "sameuser" or # characters must be quoted. Quoting one of the keywords "all", "sameuser" or
......
...@@ -5,18 +5,18 @@ ...@@ -5,18 +5,18 @@
# Authentication" for a complete description. A short synopsis # Authentication" for a complete description. A short synopsis
# follows. # follows.
# #
# This file controls PostgreSQL ident-based authentication. It maps # This file controls PostgreSQL username mapping. It maps
# ident user names (typically Unix user names) to their corresponding # external user names to their corresponding
# PostgreSQL user names. Records are of the form: # PostgreSQL user names. Records are of the form:
# #
# MAPNAME IDENT-USERNAME PG-USERNAME # MAPNAME SYSTEM-USERNAME PG-USERNAME
# #
# (The uppercase quantities must be replaced by actual values.) # (The uppercase quantities must be replaced by actual values.)
# #
# MAPNAME is the (otherwise freely chosen) map name that was used in # MAPNAME is the (otherwise freely chosen) map name that was used in
# pg_hba.conf. IDENT-USERNAME is the detected user name of the # pg_hba.conf. SYSTEM-USERNAME is the detected user name of the
# client. PG-USERNAME is the requested PostgreSQL user name. The # client. PG-USERNAME is the requested PostgreSQL user name. The
# existence of a record specifies that IDENT-USERNAME may connect as # existence of a record specifies that SYSTEM-USERNAME may connect as
# PG-USERNAME. Multiple maps may be specified in this file and used # PG-USERNAME. Multiple maps may be specified in this file and used
# by pg_hba.conf. # by pg_hba.conf.
# #
...@@ -28,8 +28,8 @@ ...@@ -28,8 +28,8 @@
# Put your actual configuration here # Put your actual configuration here
# ---------------------------------- # ----------------------------------
# #
# No map names are defined in the default configuration. If all ident # No map names are defined in the default configuration. If all system
# 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. # this file.
# MAPNAME IDENT-USERNAME PG-USERNAME # MAPNAME SYSTEM-USERNAME PG-USERNAME
...@@ -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.49 2008/09/15 12:32:57 mha Exp $ * $PostgreSQL: pgsql/src/include/libpq/hba.h,v 1.50 2008/10/23 13:31:10 mha Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -25,13 +25,9 @@ typedef enum UserAuth ...@@ -25,13 +25,9 @@ typedef enum UserAuth
uaCrypt, uaCrypt,
uaMD5, uaMD5,
uaGSS, uaGSS,
uaSSPI uaSSPI,
#ifdef USE_PAM uaPAM,
,uaPAM uaLDAP
#endif /* USE_PAM */
#ifdef USE_LDAP
,uaLDAP
#endif
} UserAuth; } UserAuth;
typedef enum ConnType typedef enum ConnType
...@@ -51,8 +47,14 @@ typedef struct ...@@ -51,8 +47,14 @@ typedef struct
struct sockaddr_storage addr; struct sockaddr_storage addr;
struct sockaddr_storage mask; struct sockaddr_storage mask;
UserAuth auth_method; UserAuth auth_method;
char *usermap; char *usermap;
char *auth_arg; char *pamservice;
bool ldaptls;
char *ldapserver;
int ldapport;
char *ldapprefix;
char *ldapsuffix;
} HbaLine; } HbaLine;
typedef struct Port hbaPort; typedef struct Port hbaPort;
...@@ -64,8 +66,9 @@ extern void load_role(void); ...@@ -64,8 +66,9 @@ extern void load_role(void);
extern int hba_getauthmethod(hbaPort *port); extern int hba_getauthmethod(hbaPort *port);
extern bool read_pg_database_line(FILE *fp, char *dbname, Oid *dboid, extern bool read_pg_database_line(FILE *fp, char *dbname, Oid *dboid,
Oid *dbtablespace, TransactionId *dbfrozenxid); Oid *dbtablespace, TransactionId *dbfrozenxid);
extern bool check_ident_usermap(const char *usermap_name, extern int check_usermap(const char *usermap_name,
const char *pg_role, const char *ident_user); const char *pg_role, const char *auth_user,
bool case_sensitive);
extern bool pg_isblank(const char c); extern bool pg_isblank(const char c);
#endif /* HBA_H */ #endif /* HBA_H */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册