Re: pg_hba options parsing

Поиск
Список
Период
Сортировка
От Magnus Hagander
Тема Re: pg_hba options parsing
Дата
Msg-id 48F0DE8B.8030004@hagander.net
обсуждение исходный текст
Ответ на pg_hba options parsing  (Magnus Hagander <magnus@hagander.net>)
Список pgsql-hackers
Magnus Hagander wrote:
> This patch changes the options field of pg_hba.conf to take name/value
> pairs instead of a fixed string. This makes it a lot nicer to deal with
> auth methods that need more than one parameter, such as LDAP.
>
> While at it, it also adds map support to kerberos, gssapi and sspi and
> not just ident - basically all methods where the username comes from an
> outside source (lmk if I missed one).
>
> Also in passing, changes the methods in auth.c to deal with "unsupported
> auth method on this platform" errors the same way for all authentication
> methods.
>
> I intend to build on this patch to support setting some
> Kerberos/GSSAPI/SSPI parameters on a per-connection base, but wanted to
> get the basics in first.
>
> Obviously, documentation still pending. I'm working on that in parallel.
>
>
> So, comments? Both in general, and specifically on if we need to do
> backwards compatible parsing of LDAP options (doing it of all the other
> options would be trivial, but LDAP would be harder)

Updated version of this patch, now with doc changes.

//Magnus

*** a/doc/src/sgml/client-auth.sgml
--- b/doc/src/sgml/client-auth.sgml
***************
*** 96,108 ****
    <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>
  </synopsis>
     The meaning of the fields is as follows:

--- 96,108 ----
    <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-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,432 **** hostnossl  <replaceable>database</replaceable>  <replaceable>user</replaceable>
      </varlistentry>

      <varlistentry>
!      <term><replaceable>auth-option</replaceable></term>
       <listitem>
        <para>
!        The meaning of this optional field depends on the chosen
!        authentication method.  Details appear below.
        </para>
       </listitem>
      </varlistentry>
--- 422,434 ----
      </varlistentry>

      <varlistentry>
!      <term><replaceable>auth-options</replaceable></term>
       <listitem>
        <para>
!        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,540 **** 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

  # If these are the only three lines for local connections, they will
  # allow local users to connect only to their own databases (databases
--- 536,542 ----
  # "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 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,562 **** local   db1,db2,@demodbs  all                         md5
--- 559,650 ----
     </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,691 **** 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>
!
    </sect2>

    <sect2 id="sspi-auth">
--- 773,793 ----
      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,718 **** local   db1,db2,@demodbs  all                         md5
--- 815,834 ----
      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,851 **** local   db1,db2,@demodbs  all                         md5
--- 962,982 ----
      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,1000 **** 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">
--- 1049,1054 ----
***************
*** 1007,1055 **** 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
      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.
     </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
      before the bind. Typically, the prefix parameter is used to specify
      <replaceable>cn=</>, or <replaceable>DOMAIN\</> in an Active
!     Directory environment.
     </para>
!
    </sect2>

    <sect2 id="auth-pam">
--- 1061,1144 ----
     <para>
      This authentication method operates similarly to
      <literal>password</literal> except that it uses LDAP
!     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.
     </para>
+
     <para>
!     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, 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,1071 **** 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>.
      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
--- 1152,1158 ----
      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>.
      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,1080 **** ldap[<replaceable>s</>]://<replaceable>servername</>[:<replaceable>port</>]/<rep
--- 1162,1181 ----
      <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
*** a/src/backend/libpq/auth.c
--- b/src/backend/libpq/auth.c
***************
*** 126,134 **** char       *pg_krb_realm = NULL;
   * MIT Kerberos authentication system - protocol version 5
   *----------------------------------------------------------------
   */
- static int pg_krb5_recvauth(Port *port);
-
  #ifdef KRB5

  #include <krb5.h>
  /* Some old versions of Kerberos do not include <com_err.h> in <krb5.h> */
--- 126,133 ----
   * MIT Kerberos authentication system - protocol version 5
   *----------------------------------------------------------------
   */
  #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,163 **** 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
  #endif /* ENABLE_GSS */


--- 149,162 ----
   * GSSAPI Authentication
   *----------------------------------------------------------------
   */
  #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,176 **** 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 **);
  #endif


--- 164,174 ----
   * SSPI Authentication
   *----------------------------------------------------------------
   */
  #ifdef ENABLE_SSPI
  typedef        SECURITY_STATUS
              (WINAPI * QUERY_SECURITY_CONTEXT_TOKEN_FN) (
                                                         PCtxtHandle, void **);
+ static int pg_SSPI_recvauth(Port *port);
  #endif


***************
*** 236,251 **** 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;
--- 234,245 ----
***************
*** 316,333 **** ClientAuthentication(Port *port)
--- 310,339 ----
              }

          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,394 **** ClientAuthentication(Port *port)
              status = recv_and_check_password_packet(port);
              break;

- #ifdef USE_PAM
          case uaPAM:
              pam_port_cludge = port;
              status = CheckPAMAuth(port, port->user_name, "");
!             break;
  #endif   /* USE_PAM */

- #ifdef USE_LDAP
          case uaLDAP:
              status = CheckLDAPAuth(port);
!             break;
  #endif

          case uaTrust:
              status = STATUS_OK;
--- 383,404 ----
              status = recv_and_check_password_packet(port);
              break;

          case uaPAM:
+ #ifdef USE_PAM
              pam_port_cludge = port;
              status = CheckPAMAuth(port, port->user_name, "");
! #else
!             Assert(false);
  #endif   /* USE_PAM */
+             break;

          case uaLDAP:
+ #ifdef USE_LDAP
              status = CheckLDAPAuth(port);
! #else
!             Assert(false);
  #endif
+             break;

          case uaTrust:
              status = STATUS_OK;
***************
*** 713,731 **** 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;

      krb5_free_ticket(pg_krb5_context, ticket);
      krb5_auth_con_free(pg_krb5_context, auth_context);
--- 723,730 ----
          return STATUS_ERROR;
      }

!     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,748 **** 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 */


--- 732,737 ----
***************
*** 1020,1057 **** 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;
!     }

      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 */


--- 1009,1021 ----
          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;
  }
  #endif   /* ENABLE_GSS */


***************
*** 1328,1357 **** 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;
  }
-
- #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 */


--- 1292,1299 ----
       * We have the username (without domain/realm) in accountname, compare to
       * the supplied value. In SSPI, always compare case insensitive.
       */
!     return check_usermap(port->hba->usermap, port->user_name, accountname, true);
  }
  #endif   /* ENABLE_SSPI */


***************
*** 1795,1808 **** 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;
  }


--- 1737,1743 ----
              return STATUS_ERROR;
      }

!     return check_usermap(port->hba->usermap, port->user_name, ident_user, false);
  }


***************
*** 1913,1920 **** 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@",
                             &pam_passw_conv, &pamh);
      else
          retval = pam_start(PGSQL_PAM_SERVICE, "pgsql@",
--- 1848,1855 ----
                                                           * not allocated */

      /* Optionally, one can set the service name in pg_hba.conf */
!     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,2075 **** 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')
      {
          ereport(LOG,
!                 (errmsg("LDAP configuration URL 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;
!     }

      sendAuthRequest(port, AUTH_REQ_PASSWORD);

--- 1935,1954 ----
  CheckLDAPAuth(Port *port)
  {
      char       *passwd;
      LDAP       *ldap;
      int            r;
      int            ldapversion = LDAP_VERSION3;
      char        fulluser[NAMEDATALEN + 256 + 1];

!     if (!port->hba->ldapserver|| port->hba->ldapserver[0] == '\0')
      {
          ereport(LOG,
!                 (errmsg("LDAP server not specified")));
          return STATUS_ERROR;
      }

!     if (port->hba->ldapport == 0)
!         port->hba->ldapport = LDAP_PORT;

      sendAuthRequest(port, AUTH_REQ_PASSWORD);

***************
*** 2077,2083 **** CheckLDAPAuth(Port *port)
      if (passwd == NULL)
          return STATUS_EOF;        /* client wouldn't send password */

!     ldap = ldap_init(server, ldapport);
      if (!ldap)
      {
  #ifndef WIN32
--- 1956,1962 ----
      if (passwd == NULL)
          return STATUS_EOF;        /* client wouldn't send password */

!     ldap = ldap_init(port->hba->ldapserver, port->hba->ldapport);
      if (!ldap)
      {
  #ifndef WIN32
***************
*** 2100,2106 **** CheckLDAPAuth(Port *port)
          return STATUS_ERROR;
      }

!     if (ssl)
      {
  #ifndef WIN32
          if ((r = ldap_start_tls_s(ldap, NULL, NULL)) != LDAP_SUCCESS)
--- 1979,1985 ----
          return STATUS_ERROR;
      }

!     if (port->hba->ldaptls)
      {
  #ifndef WIN32
          if ((r = ldap_start_tls_s(ldap, NULL, NULL)) != LDAP_SUCCESS)
***************
*** 2155,2161 **** CheckLDAPAuth(Port *port)
      }

      snprintf(fulluser, sizeof(fulluser), "%s%s%s",
!              prefix, port->user_name, suffix);
      fulluser[sizeof(fulluser) - 1] = '\0';

      r = ldap_simple_bind_s(ldap, fulluser, passwd);
--- 2034,2042 ----
      }

      snprintf(fulluser, sizeof(fulluser), "%s%s%s",
!              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,2171 **** CheckLDAPAuth(Port *port)
      {
          ereport(LOG,
                  (errmsg("LDAP login failed for user \"%s\" on server \"%s\": error code %d",
!                         fulluser, server, r)));
          return STATUS_ERROR;
      }

--- 2046,2052 ----
      {
          ereport(LOG,
                  (errmsg("LDAP login failed for user \"%s\" on server \"%s\": error code %d",
!                         fulluser, port->hba->ldapserver, r)));
          return STATUS_ERROR;
      }

*** a/src/backend/libpq/hba.c
--- b/src/backend/libpq/hba.c
***************
*** 565,570 **** check_db(const char *dbname, const char *role, char *param_str)
--- 565,606 ----


  /*
+  * 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) \
+     if (parsedline->auth_method != methodval) \
+         INVALID_AUTH_OPTION("ldaptls", "ldap")
+
+ #define MANDATORY_AUTH_ARG(argvar, argname, authname) \
+ 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,838 **** 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)
      {
          token = lfirst(line_item);
-         parsedline->auth_arg= pstrdup(token);
-     }

!     /*
!      * Backwards compatible format of ident authentication - support "naked" ident map
!      * name, as well as "sameuser"/"samerole"
!      */
!     if (parsedline->auth_method == uaIdent)
!     {
!         if (parsedline->auth_arg && strlen(parsedline->auth_arg))
          {
!             if (strcmp(parsedline->auth_arg, "sameuser\n") == 0 ||
!                 strcmp(parsedline->auth_arg, "samerole\n") == 0)
              {
!                 /* This is now the default */
!                 pfree(parsedline->auth_arg);
!                 parsedline->auth_arg = NULL;
!                 parsedline->usermap = NULL;
              }
              else
              {
!                 /* Specific ident map specified */
!                 parsedline->usermap = parsedline->auth_arg;
!                 parsedline->auth_arg = NULL;
              }
          }
      }

      return true;

--- 837,938 ----
          goto hba_other_error;
      }

!     /* Parse remaining arguments */
!     while ((line_item = lnext(line_item)) != NULL)
      {
+         char *c;
+
          token = lfirst(line_item);

!         c = strchr(token, '=');
!         if (c == NULL)
          {
!             /*
!              * 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)
              {
!                 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
              {
!                 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,1025 **** free_hba_record(HbaLine *record)
          pfree(record->database);
      if (record->role)
          pfree(record->role);
!     if (record->auth_arg)
!         pfree(record->auth_arg);
  }

  /*
--- 1118,1131 ----
          pfree(record->database);
      if (record->role)
          pfree(record->role);
!     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,1156 **** 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)
  {
      ListCell   *line_item;
      char       *token;
--- 1256,1262 ----
  static void
  parse_ident_usermap(List *line, int line_number, const char *usermap_name,
                      const char *pg_role, const char *ident_user,
!                     bool case_insensitive, bool *found_p, bool *error_p)
  {
      ListCell   *line_item;
      char       *token;
***************
*** 1183,1192 **** 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;

      return;

--- 1289,1308 ----
      file_pgrole = token;

      /* Match? */
!     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,1231 **** 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.
   */
! bool
! check_ident_usermap(const char *usermap_name,
                      const char *pg_role,
!                     const char *ident_user)
  {
      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;
      }
      else
      {
--- 1326,1357 ----
   *    file.  That's an implied map where "pgrole" must be identical to
   *    "ident_user" in order to be authorized.
   *
!  *    Iff authorized, return STATUS_OK, otherwise return STATUS_ERROR.
   */
! int
! check_usermap(const char *usermap_name,
                      const char *pg_role,
!                     const char *auth_user,
!                     bool case_insensitive)
  {
      bool        found_entry = false,
                  error = false;

      if (usermap_name == NULL || usermap_name[0] == '\0')
      {
!         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,1247 **** 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,
                                  &found_entry, &error);
              if (found_entry || error)
                  break;
          }
      }
!     return found_entry;
  }


--- 1361,1380 ----
          forboth(line_cell, ident_lines, num_cell, ident_line_nums)
          {
              parse_ident_usermap(lfirst(line_cell), lfirst_int(num_cell),
!                                 usermap_name, pg_role, auth_user, case_insensitive,
                                  &found_entry, &error);
              if (found_entry || error)
                  break;
          }
      }
!     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;
  }


*** a/src/backend/libpq/pg_hba.conf.sample
--- b/src/backend/libpq/pg_hba.conf.sample
***************
*** 9,18 ****
  # 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]
  #
  # (The uppercase items must be replaced by actual values.)
  #
--- 9,18 ----
  # are authenticated, which PostgreSQL user names they can use, which
  # databases they can access.  Records take one of these forms:
  #
! # 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.)
  #
***************
*** 38,44 ****
  # "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.
  #
  # Database and user names containing spaces, commas, quotes and other special
  # characters must be quoted. Quoting one of the keywords "all", "sameuser" or
--- 38,47 ----
  # "krb5", "ident", "pam" or "ldap".  Note that "password" sends passwords
  # in clear text; "md5" is preferred since it sends encrypted passwords.
  #
! # 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
*** a/src/backend/libpq/pg_ident.conf.sample
--- b/src/backend/libpq/pg_ident.conf.sample
***************
*** 5,22 ****
  # 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
  # PostgreSQL user names.  Records are of the form:
  #
! # MAPNAME  IDENT-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
  # client.  PG-USERNAME is the requested PostgreSQL user name.  The
! # existence of a record specifies that IDENT-USERNAME may connect as
  # PG-USERNAME.  Multiple maps may be specified in this file and used
  # by pg_hba.conf.
  #
--- 5,22 ----
  # Authentication" for a complete description.  A short synopsis
  # follows.
  #
! # This file controls PostgreSQL username mapping. It maps
! # external user names to their corresponding
  # PostgreSQL user names.  Records are of the form:
  #
! # 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.  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 SYSTEM-USERNAME may connect as
  # PG-USERNAME.  Multiple maps may be specified in this file and used
  # by pg_hba.conf.
  #
***************
*** 28,35 ****
  # Put your actual configuration here
  # ----------------------------------
  #
! # No map names are defined in the default configuration.  If all ident
  # user names and PostgreSQL user names are the same, you don't need
  # this file.

! # MAPNAME     IDENT-USERNAME    PG-USERNAME
--- 28,35 ----
  # Put your actual configuration here
  # ----------------------------------
  #
! # 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     SYSTEM-USERNAME    PG-USERNAME
*** a/src/include/libpq/hba.h
--- b/src/include/libpq/hba.h
***************
*** 25,37 **** typedef enum UserAuth
      uaCrypt,
      uaMD5,
      uaGSS,
!     uaSSPI
! #ifdef USE_PAM
!     ,uaPAM
! #endif   /* USE_PAM */
! #ifdef USE_LDAP
!     ,uaLDAP
! #endif
  } UserAuth;

  typedef enum ConnType
--- 25,33 ----
      uaCrypt,
      uaMD5,
      uaGSS,
!     uaSSPI,
!     uaPAM,
!     uaLDAP
  } UserAuth;

  typedef enum ConnType
***************
*** 51,58 **** typedef struct
      struct sockaddr_storage addr;
      struct sockaddr_storage mask;
      UserAuth    auth_method;
      char       *usermap;
!     char       *auth_arg;
  } HbaLine;

  typedef struct Port hbaPort;
--- 47,60 ----
      struct sockaddr_storage addr;
      struct sockaddr_storage mask;
      UserAuth    auth_method;
+
      char       *usermap;
!     char       *pamservice;
!     bool        ldaptls;
!     char       *ldapserver;
!     int            ldapport;
!     char       *ldapprefix;
!     char       *ldapsuffix;
  } HbaLine;

  typedef struct Port hbaPort;
***************
*** 64,71 **** 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 bool pg_isblank(const char c);

  #endif   /* HBA_H */
--- 66,74 ----
  extern int    hba_getauthmethod(hbaPort *port);
  extern bool read_pg_database_line(FILE *fp, char *dbname, Oid *dboid,
                        Oid *dbtablespace, TransactionId *dbfrozenxid);
! 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 */

В списке pgsql-hackers по дате отправления:

Предыдущее
От: dpage@pgadmin.org
Дата:
Сообщение: Re: About postgresql8.3.3 build in MS VS2005
Следующее
От: "Pavel Stehule"
Дата:
Сообщение: Re: Contrib, schema, and load_module