]> granicus.if.org Git - postgresql/commitdiff
* make pg_hba authoption be a set of 0 or more name=value pairs
authorMagnus Hagander <magnus@hagander.net>
Thu, 23 Oct 2008 13:31:10 +0000 (13:31 +0000)
committerMagnus Hagander <magnus@hagander.net>
Thu, 23 Oct 2008 13:31:10 +0000 (13:31 +0000)
* 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.

doc/src/sgml/client-auth.sgml
src/backend/libpq/auth.c
src/backend/libpq/hba.c
src/backend/libpq/pg_hba.conf.sample
src/backend/libpq/pg_ident.conf.sample
src/include/libpq/hba.h

index 61f2b1e2e6c85071a9d97fdd9dce3e6ab8a59cad..5a308eb89589eb4b1c5f7bd5bf5dcbd3a0aafcf9 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $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">
  <title>Client Authentication</title>
   <para>
    A record can have one of the seven formats
 <synopsis>
-local      <replaceable>database</replaceable>  <replaceable>user</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-option</replaceable></optional>
-hostssl    <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-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-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-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-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-options</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-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-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-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-options</replaceable></optional>
 </synopsis>
    The meaning of the fields is as follows:
 
@@ -422,11 +422,13 @@ hostnossl  <replaceable>database</replaceable>  <replaceable>user</replaceable>
     </varlistentry>
 
     <varlistentry>
-     <term><replaceable>auth-option</replaceable></term>
+     <term><replaceable>auth-options</replaceable></term>
      <listitem>
       <para>
-       The meaning of this optional field depends on the chosen
-       authentication method.  Details appear below.
+       This field contains zero or more name-value pairs with
+       extra options passed to this authentication method. Details
+       about which options are available for which authentication
+       method appear below.
       </para>
      </listitem>
     </varlistentry>
@@ -534,7 +536,7 @@ host    all         all         0.0.0.0/0             krb5
 # "omicron" that says "bryanh" is allowed to connect as "guest1".
 #
 # 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
 # allow local users to connect only to their own databases (databases
@@ -557,6 +559,92 @@ local   db1,db2,@demodbs  all                         md5
    </example>
  </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">
   <title>Authentication methods</title>
   <para>
@@ -685,7 +773,21 @@ local   db1,db2,@demodbs  all                         md5
     GSSAPI support has to be enabled when <productname>PostgreSQL</> is built;
     see <xref linkend="installation"> for more information.
    </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 id="sspi-auth">
@@ -713,6 +815,20 @@ local   db1,db2,@demodbs  all                         md5
     for details.
    </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 id="kerberos-auth">
@@ -846,6 +962,21 @@ local   db1,db2,@demodbs  all                         md5
     depending on the connection type.
    </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>
     <title>Ident Authentication over TCP/IP</title>
 
@@ -918,83 +1049,6 @@ local   db1,db2,@demodbs  all                         md5
     </para>
     </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 id="auth-ldap">
@@ -1007,49 +1061,84 @@ omicron       bryanh            guest1
    <para>
     This authentication method operates similarly to
     <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
     exist in the database before LDAP can be used for
-    authentication. The server and parameters used are specified
-    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.
+    authentication.
    </para>
+
    <para>
-    The server will bind to the distinguished name specified as
-    <replaceable>base dn</> using the user name supplied by the client.
-    If <replaceable>prefix</> and <replaceable>suffix</> is 
-    specified, it will be prepended and appended to the user name
+    The server will bind to the distinguished name constructed as
+    <replaceable>prefix</> <replaceable>username</> <replaceable>suffix</>.
     before the bind. Typically, the prefix parameter is used to specify
     <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>
+    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 id="auth-pam">
@@ -1063,9 +1152,7 @@ ldap[<replaceable>s</>]://<replaceable>servername</>[:<replaceable>port</>]/<rep
     This authentication method operates similarly to
     <literal>password</literal> except that it uses PAM (Pluggable
     Authentication Modules) as the authentication mechanism. The
-    default PAM service name is <literal>postgresql</literal>. You can
-    optionally supply your own service name after the <literal>pam</>
-    key word in the file <filename>pg_hba.conf</filename>.
+    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 
@@ -1075,6 +1162,20 @@ ldap[<replaceable>s</>]://<replaceable>servername</>[:<replaceable>port</>]/<rep
     <systemitem class="osname">Solaris</> PAM Page</ulink>.
    </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>
     <para>
      If PAM is set up to read <filename>/etc/shadow</>, authentication
index f01be3b18f01f34019b4cf52c521280752341bb3..865d52fc56ff7e5e91140817ed9ebb5a8b90f177 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * 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;
  * MIT Kerberos authentication system - protocol version 5
  *----------------------------------------------------------------
  */
-static int pg_krb5_recvauth(Port *port);
-
 #ifdef KRB5
+static int pg_krb5_recvauth(Port *port);
 
 #include <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;
  * GSSAPI Authentication
  *----------------------------------------------------------------
  */
-static int pg_GSS_recvauth(Port *port);
-
 #ifdef ENABLE_GSS
 #if defined(HAVE_GSSAPI_H)
 #include <gssapi.h>
 #else
 #include <gssapi/gssapi.h>
 #endif
+
+static int pg_GSS_recvauth(Port *port);
 #endif /* ENABLE_GSS */
 
 
@@ -165,12 +164,11 @@ static int pg_GSS_recvauth(Port *port);
  * SSPI Authentication
  *----------------------------------------------------------------
  */
-static int pg_SSPI_recvauth(Port *port);
-
 #ifdef ENABLE_SSPI
 typedef                SECURITY_STATUS
                        (WINAPI * QUERY_SECURITY_CONTEXT_TOKEN_FN) (
                                                                                                           PCtxtHandle, void **);
+static int pg_SSPI_recvauth(Port *port);
 #endif
 
 
@@ -236,16 +234,12 @@ auth_failed(Port *port, int status)
                case uaPassword:
                        errstr = gettext_noop("password authentication failed for user \"%s\"");
                        break;
-#ifdef USE_PAM
                case uaPAM:
                        errstr = gettext_noop("PAM authentication failed for user \"%s\"");
                        break;
-#endif   /* USE_PAM */
-#ifdef USE_LDAP
                case uaLDAP:
                        errstr = gettext_noop("LDAP authentication failed for user \"%s\"");
                        break;
-#endif   /* USE_LDAP */
                default:
                        errstr = gettext_noop("authentication failed for user \"%s\": invalid authentication method");
                        break;
@@ -316,18 +310,30 @@ ClientAuthentication(Port *port)
                        }
 
                case uaKrb5:
+#ifdef KRB5
                        sendAuthRequest(port, AUTH_REQ_KRB5);
                        status = pg_krb5_recvauth(port);
+#else
+                       Assert(false);
+#endif
                        break;
 
                case uaGSS:
+#ifdef ENABLE_GSS
                        sendAuthRequest(port, AUTH_REQ_GSS);
                        status = pg_GSS_recvauth(port);
+#else
+                       Assert(false);
+#endif
                        break;
 
                case uaSSPI:
+#ifdef ENABLE_SSPI
                        sendAuthRequest(port, AUTH_REQ_SSPI);
                        status = pg_SSPI_recvauth(port);
+#else
+                       Assert(false);
+#endif
                        break;
 
                case uaIdent:
@@ -377,18 +383,22 @@ ClientAuthentication(Port *port)
                        status = recv_and_check_password_packet(port);
                        break;
 
-#ifdef USE_PAM
                case uaPAM:
+#ifdef USE_PAM
                        pam_port_cludge = port;
                        status = CheckPAMAuth(port, port->user_name, "");
-                       break;
+#else
+                       Assert(false);
 #endif   /* USE_PAM */
+                       break;
 
-#ifdef USE_LDAP
                case uaLDAP:
+#ifdef USE_LDAP
                        status = CheckLDAPAuth(port);
-                       break;
+#else
+                       Assert(false);
 #endif
+                       break;
 
                case uaTrust:
                        status = STATUS_OK;
@@ -713,19 +723,8 @@ pg_krb5_recvauth(Port *port)
                return STATUS_ERROR;
        }
 
-       if (pg_krb_caseins_users)
-               ret = pg_strncasecmp(port->user_name, kusername, SM_DATABASE_USER);
-       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;
+       ret = check_usermap(port->hba->usermap, port->user_name, kusername,
+                                               pg_krb_caseins_users);
 
        krb5_free_ticket(pg_krb5_context, ticket);
        krb5_auth_con_free(pg_krb5_context, auth_context);
@@ -733,16 +732,6 @@ pg_krb5_recvauth(Port *port)
 
        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 */
 
 
@@ -1020,38 +1009,13 @@ pg_GSS_recvauth(Port *port)
                return STATUS_ERROR;
        }
 
-       if (pg_krb_caseins_users)
-               ret = pg_strcasecmp(port->user_name, gbuf.value);
-       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;
-       }
+       ret = check_usermap(port->hba->usermap, port->user_name, gbuf.value,
+                                               pg_krb_caseins_users);
 
        gss_release_buffer(&lmin_s, &gbuf);
 
        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 */
 
 
@@ -1328,30 +1292,8 @@ pg_SSPI_recvauth(Port *port)
         * We have the username (without domain/realm) in accountname, compare to
         * the supplied value. In SSPI, always compare case insensitive.
         */
-       if (pg_strcasecmp(port->user_name, accountname))
-       {
-               /* 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;
+       return check_usermap(port->hba->usermap, port->user_name, accountname, true);
 }
-
-#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 */
 
 
@@ -1795,14 +1737,7 @@ authident(hbaPort *port)
                        return STATUS_ERROR;
        }
 
-       ereport(DEBUG2,
-                       (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;
+       return check_usermap(port->hba->usermap, port->user_name, ident_user, false);
 }
 
 
@@ -1913,8 +1848,8 @@ CheckPAMAuth(Port *port, char *user, char *password)
                                                                                                                 * not allocated */
 
        /* Optionally, one can set the service name in pg_hba.conf */
-       if (port->hba->auth_arg && port->hba->auth_arg[0] != '\0')
-               retval = pam_start(port->hba->auth_arg, "pgsql@",
+       if (port->hba->pamservice && port->hba->pamservice[0] != '\0')
+               retval = pam_start(port->hba->pamservice, "pgsql@",
                                                   &pam_passw_conv, &pamh);
        else
                retval = pam_start(PGSQL_PAM_SERVICE, "pgsql@",
@@ -2000,76 +1935,20 @@ static int
 CheckLDAPAuth(Port *port)
 {
        char       *passwd;
-       char            server[128];
-       char            basedn[128];
-       char            prefix[128];
-       char            suffix[128];
        LDAP       *ldap;
-       bool            ssl = false;
        int                     r;
        int                     ldapversion = LDAP_VERSION3;
-       int                     ldapport = LDAP_PORT;
        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,
-                               (errmsg("LDAP configuration URL not specified")));
+                               (errmsg("LDAP server not specified")));
                return STATUS_ERROR;
        }
 
-       /*
-        * Crack the LDAP url. We do a very trivial parse:
-        *
-        * 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;
-       }
+       if (port->hba->ldapport == 0)
+               port->hba->ldapport = LDAP_PORT;
 
        sendAuthRequest(port, AUTH_REQ_PASSWORD);
 
@@ -2077,7 +1956,7 @@ CheckLDAPAuth(Port *port)
        if (passwd == NULL)
                return STATUS_EOF;              /* client wouldn't send password */
 
-       ldap = ldap_init(server, ldapport);
+       ldap = ldap_init(port->hba->ldapserver, port->hba->ldapport);
        if (!ldap)
        {
 #ifndef WIN32
@@ -2100,7 +1979,7 @@ CheckLDAPAuth(Port *port)
                return STATUS_ERROR;
        }
 
-       if (ssl)
+       if (port->hba->ldaptls)
        {
 #ifndef WIN32
                if ((r = ldap_start_tls_s(ldap, NULL, NULL)) != LDAP_SUCCESS)
@@ -2155,7 +2034,9 @@ CheckLDAPAuth(Port *port)
        }
 
        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';
 
        r = ldap_simple_bind_s(ldap, fulluser, passwd);
@@ -2165,7 +2046,7 @@ CheckLDAPAuth(Port *port)
        {
                ereport(LOG,
                                (errmsg("LDAP login failed for user \"%s\" on server \"%s\": error code %d",
-                                               fulluser, server, r)));
+                                               fulluser, port->hba->ldapserver, r)));
                return STATUS_ERROR;
        }
 
index 6917e5c927ab92399b7050fa0a009a22c99f82c2..ddb7fc5696451618a643693f14ae7aea3ee85a9d 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * 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)
 }
 
 
+/*
+ * 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
  * a HbaLine structure.
@@ -801,38 +839,102 @@ parse_hba_line(List *line, int line_num, HbaLine *parsedline)
                goto hba_other_error;
        }
 
-       /* Get the authentication argument token, if any */
-       line_item = lnext(line_item);
-       if (line_item)
+       /* Parse remaining arguments */
+       while ((line_item = lnext(line_item)) != NULL)
        {
+               char *c;
+
                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))
+               c = strchr(token, '=');
+               if (c == NULL)
                {
-                       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 */
-                               pfree(parsedline->auth_arg);
-                               parsedline->auth_arg = NULL;
-                               parsedline->usermap = NULL;
+                               REQUIRE_AUTH_OPTION(uaLDAP, "ldapprefix", "ldap");
+                               parsedline->ldapprefix = pstrdup(c);
+                       }
+                       else if (strcmp(token, "ldapsuffix") == 0)
+                       {
+                               REQUIRE_AUTH_OPTION(uaLDAP, "ldapsuffix", "ldap");
+                               parsedline->ldapsuffix = pstrdup(c);
                        }
                        else
                        {
-                               /* Specific ident map specified */
-                               parsedline->usermap = parsedline->auth_arg;
-                               parsedline->auth_arg = NULL;
+                               ereport(LOG,
+                                               (errcode(ERRCODE_CONFIG_FILE_ERROR),
+                                                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;
 
@@ -1018,8 +1120,14 @@ free_hba_record(HbaLine *record)
                pfree(record->database);
        if (record->role)
                pfree(record->role);
-       if (record->auth_arg)
-               pfree(record->auth_arg);
+       if (record->pamservice)
+               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,
 static void
 parse_ident_usermap(List *line, int line_number, const char *usermap_name,
                                        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;
        char       *token;
@@ -1183,10 +1291,20 @@ parse_ident_usermap(List *line, int line_number, const char *usermap_name,
        file_pgrole = token;
 
        /* Match? */
-       if (strcmp(file_map, usermap_name) == 0 &&
-               strcmp(file_pgrole, pg_role) == 0 &&
-               strcmp(file_ident_user, ident_user) == 0)
-               *found_p = true;
+       if (case_insensitive)
+       {
+               if (strcmp(file_map, usermap_name) == 0 &&
+                       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;
 
@@ -1210,22 +1328,32 @@ ident_syntax:
  *     file.  That's an implied map where "pgrole" must be identical to
  *     "ident_user" in order to be authorized.
  *
- *     Iff authorized, return true.
+ *     Iff authorized, return STATUS_OK, otherwise return STATUS_ERROR.
  */
-bool
-check_ident_usermap(const char *usermap_name,
+int
+check_usermap(const char *usermap_name,
                                        const char *pg_role,
-                                       const char *ident_user)
+                                       const char *auth_user,
+                                       bool case_insensitive)
 {
        bool            found_entry = false,
                                error = false;
 
        if (usermap_name == NULL || usermap_name[0] == '\0')
        {
-               if (strcmp(pg_role, ident_user) == 0)
-                       found_entry = true;
-               else
-                       found_entry = false;
+               if (case_insensitive)
+               {
+                       if (pg_strcasecmp(pg_role, auth_user) == 0)
+                               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
        {
@@ -1235,13 +1363,20 @@ check_ident_usermap(const char *usermap_name,
                forboth(line_cell, ident_lines, num_cell, ident_line_nums)
                {
                        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);
                        if (found_entry || error)
                                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;
 }
 
 
index 1447a8c4bef5512cd29091d80f28617723b462e4..c84d955e1b1374f1f6a01cddca0b76584a33c3b6 100644 (file)
@@ -9,10 +9,10 @@
 # are authenticated, which PostgreSQL user names they can use, which
 # databases they can access.  Records take one of these forms:
 #
-# local      DATABASE  USER  METHOD  [OPTION]
-# host       DATABASE  USER  CIDR-ADDRESS  METHOD  [OPTION]
-# hostssl    DATABASE  USER  CIDR-ADDRESS  METHOD  [OPTION]
-# hostnossl  DATABASE  USER  CIDR-ADDRESS  METHOD  [OPTION]
+# local      DATABASE  USER  METHOD  [OPTIONS]
+# host       DATABASE  USER  CIDR-ADDRESS  METHOD  [OPTIONS]
+# hostssl    DATABASE  USER  CIDR-ADDRESS  METHOD  [OPTIONS]
+# hostnossl  DATABASE  USER  CIDR-ADDRESS  METHOD  [OPTIONS]
 #
 # (The uppercase items must be replaced by actual values.)
 #
 # "krb5", "ident", "pam" or "ldap".  Note that "password" sends 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
 # characters must be quoted. Quoting one of the keywords "all", "sameuser" or
index 6f0de64910b9362919ef24024620c171caad4dd0..4471d56e13e76766e73a1dccc20ffe96e733273c 100644 (file)
@@ -5,18 +5,18 @@
 # Authentication" for a complete description.  A short synopsis
 # follows.
 #
-# This file controls PostgreSQL ident-based authentication. It maps
-# ident user names (typically Unix user names) to their corresponding
+# This file controls PostgreSQL username mapping. It maps
+# external user names to their corresponding
 # 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.)
 #
 # 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
-# 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
 # by pg_hba.conf.
 #
@@ -28,8 +28,8 @@
 # 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
 # this file.
 
-# MAPNAME     IDENT-USERNAME    PG-USERNAME
+# MAPNAME     SYSTEM-USERNAME    PG-USERNAME
index 3af7db9e626fed86498ef0b87f6747a7d1eb6c8c..54ecc560d81027db58997400fdb93e6e4fa9228d 100644 (file)
@@ -4,7 +4,7 @@
  *       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
        uaCrypt,
        uaMD5,
        uaGSS,
-       uaSSPI
-#ifdef USE_PAM
-       ,uaPAM
-#endif   /* USE_PAM */
-#ifdef USE_LDAP
-       ,uaLDAP
-#endif
+       uaSSPI,
+       uaPAM,
+       uaLDAP
 } UserAuth;
 
 typedef enum ConnType
@@ -51,8 +47,14 @@ typedef struct
        struct sockaddr_storage addr;
        struct sockaddr_storage mask;
        UserAuth        auth_method;
+
        char       *usermap;
-       char       *auth_arg;
+       char       *pamservice;
+       bool            ldaptls;
+       char       *ldapserver;
+       int                     ldapport;
+       char       *ldapprefix;
+       char       *ldapsuffix;
 } HbaLine;
 
 typedef struct Port hbaPort;
@@ -64,8 +66,9 @@ extern void load_role(void);
 extern int     hba_getauthmethod(hbaPort *port);
 extern bool read_pg_database_line(FILE *fp, char *dbname, Oid *dboid,
                                          Oid *dbtablespace, TransactionId *dbfrozenxid);
-extern bool check_ident_usermap(const char *usermap_name,
-                                         const char *pg_role, const char *ident_user);
+extern int  check_usermap(const char *usermap_name,
+                                         const char *pg_role, const char *auth_user,
+                                         bool case_sensitive);
 extern bool pg_isblank(const char c);
 
 #endif   /* HBA_H */