Thread

Commits

  1. Don't set PAM_RHOST for Unix sockets.

  2. Set PAM_RHOST item for PAM authentication

  1. BUG #15520: PAM authentication + domain socket -> DNS query for symbolic hostname [local]

    The Post Office <noreply@postgresql.org> — 2018-11-24T10:45:54Z

    The following bug has been logged on the website:
    
    Bug reference:      15520
    Logged by:          Albert Schabhuetl
    Email address:      albert_schabhuetl@yahoo.de
    PostgreSQL version: 10.4
    Operating system:   RHEL 7.4
    Description:        
    
    When PAM authentication is configured for local connections via domain
    socket,
    during authentication the backend process sends out a DNS query 
    for the following symbolic hostname: [local]
    
    This is unnecessary as it is not intended that this hostname will ever
    resolve to a valid IP address,
    and depending on how DNS queries are answered in the actual system it can
    cause authentication delays.
    
    Theory why this happens:
    
    Since this commit
    https://github.com/postgres/postgres/commit/2f1d2b7a75fecad25295cb3f453503eb6a176d4f#diff-f5a9c53142c3595fe47ebf5146457c6b
    during PAM authenticaion the functions
    	pg_getnameinfo_all
    	pam_set_item
    are called, in order to support the PAM configuration option
    "pam_use_hostname".
    
    In the case of a TCP connection and pam_use_hostname = 0,
    	pg_getnameinfo_all still calls the library function
    	getnameinfo
    but with flags = 0 to achieve "do nothing" behaviour.
    
    In the case of a domain socket connection,
    regardless of pam_use_hostname,
    	pg_getnameinfo_all calls 
    	getnameinfo_unix,
    which ignores the flags parameter and invariably
    sets the hostname to a symbolic text - [local] in our case.
    
    When subsequently the PAM library function 
    	pam_set_item
    is called, it gets the symbolic hostname [local]
    and probably it is this function which sends the DNS request for this
    hostname.
    
    
  2. Re: BUG #15520: PAM authentication + domain socket -> DNS query for symbolic hostname [local]

    Thomas Munro <thomas.munro@enterprisedb.com> — 2018-11-24T11:57:37Z

    On Sat, Nov 24, 2018 at 11:46 PM PG Bug reporting form
    <noreply@postgresql.org> wrote:
    > The following bug has been logged on the website:
    >
    > Bug reference:      15520
    > Logged by:          Albert Schabhuetl
    > Email address:      albert_schabhuetl@yahoo.de
    > PostgreSQL version: 10.4
    > Operating system:   RHEL 7.4
    > Description:
    >
    > When PAM authentication is configured for local connections via domain
    > socket,
    > during authentication the backend process sends out a DNS query
    > for the following symbolic hostname: [local]
    >
    > This is unnecessary as it is not intended that this hostname will ever
    > resolve to a valid IP address,
    > and depending on how DNS queries are answered in the actual system it can
    > cause authentication delays.
    >
    > Theory why this happens:
    >
    > Since this commit
    > https://github.com/postgres/postgres/commit/2f1d2b7a75fecad25295cb3f453503eb6a176d4f#diff-f5a9c53142c3595fe47ebf5146457c6b
    > during PAM authenticaion the functions
    >         pg_getnameinfo_all
    >         pam_set_item
    > are called, in order to support the PAM configuration option
    > "pam_use_hostname".
    >
    > In the case of a TCP connection and pam_use_hostname = 0,
    >         pg_getnameinfo_all still calls the library function
    >         getnameinfo
    > but with flags = 0 to achieve "do nothing" behaviour.
    >
    > In the case of a domain socket connection,
    > regardless of pam_use_hostname,
    >         pg_getnameinfo_all calls
    >         getnameinfo_unix,
    > which ignores the flags parameter and invariably
    > sets the hostname to a symbolic text - [local] in our case.
    >
    > When subsequently the PAM library function
    >         pam_set_item
    > is called, it gets the symbolic hostname [local]
    > and probably it is this function which sends the DNS request for this
    > hostname.
    
    Right, with a debugger I could see Linux PAM calling libaudit.so code
    that tries to resolve the hostname:
    
    #0  __GI_getaddrinfo (name=0x55b97d269d80 "[local]", service=0x0,
    hints=0x7ffee7011730, pai=0x7ffee7011728) at
    ../sysdeps/posix/getaddrinfo.c:2295
    #1  0x00007f5f4038822a in ?? () from /lib/x86_64-linux-gnu/libaudit.so.1
    #2  0x00007f5f40388bb1 in audit_log_acct_message () from
    /lib/x86_64-linux-gnu/libaudit.so.1
    #3  0x00007f5f41060410 in ?? () from /lib/x86_64-linux-gnu/libpam.so.0
    #4  0x00007f5f41060555 in ?? () from /lib/x86_64-linux-gnu/libpam.so.0
    #5  0x000055b97b07d29b in CheckPAMAuth (password=0x55b97b4ae7fe "",
    user=0x55b97d1d8fd8 "munro", port=0x55b97d1ff590) at auth.c:2249
    
    It seems we shouldn't be passing a bogus hostname in PAM_RHOST.
    
    -- 
    Thomas Munro
    http://www.enterprisedb.com
    
    
    
  3. Re: BUG #15520: PAM authentication + domain socket -> DNS query for symbolic hostname [local]

    Thomas Munro <thomas.munro@enterprisedb.com> — 2018-11-24T21:57:22Z

    On Sun, Nov 25, 2018 at 12:57 AM Thomas Munro
    <thomas.munro@enterprisedb.com> wrote:
    > It seems we shouldn't be passing a bogus hostname in PAM_RHOST.
    
    I wonder if we should simply not set PAM_RHOST for Unix sockets, since
    (in the words of the Linux PAM man page) "[i]n some applications,
    PAM_RHOST may be NULL", or set it to the hostname of the local
    machine, since in a general sense it is "the hostname of the machine
    from which the PAM_RUSER entity is requesting service" (Linux PAM) and
    "[t]he name of the applicant's host" (OpenPAM).  The latter doesn't
    seem great because it means that a PAM module loses the ability to
    distinguish this case from the IP case, so I think the former is
    probably better.  I haven't managed to find anything explicit about
    the expected value of PAM_RHOST for Unix sockets in either the Linux
    PAM or OpenPAM projects.
    
    I wonder if anyone out there has come to rely on the value "[local]"
    that PostgreSQL generates for this case (ie in a custom PAM module or
    script executed with pam_exec.so), and would get upset if we changed
    it.  Seems pretty unlikely.
    
    The comments for pg_getnameinfo_all() could probably do with a mention
    of the special value written to "node" for Unix sockets.
    
    Some relevant code:
    
    We can see that linux-audit only starts trying to resolve host if you
    didn't also pass in an address:
    
    https://github.com/linux-audit/audit-userspace/blob/e42602b7b246ae62e7a12e9cd91f0ac37b1b1968/lib/audit_logging.c#L456
    
    We can also see that linux-pam always passes NULL as an address:
    
    https://github.com/linux-pam/linux-pam/blob/955b3e2f100205be2db4358e9c812de2ae453b8e/libpam/pam_audit.c#L41
    
    -- 
    Thomas Munro
    http://www.enterprisedb.com
    
    
    
  4. Re: BUG #15520: PAM authentication + domain socket -> DNS query for symbolic hostname [local]

    Albert Schabhuetl <albert_schabhuetl@yahoo.de> — 2018-11-25T20:09:42Z

     NULL vs hostname for PAM_RHOST:
    My understanding is that the purpose of the PAM configuration parameter pam_use_hostname is to avoid the adverse effects of DNS queries if set to 0. Thus if pam_use_hostname is 0, PAM_RHOST shall be NULL for domain socket connections, just like it is the case for TCP connections.
    >I wonder if anyone out there has come to rely on the value "[local]"I vote for changing it, and documenting it in the release notes.
    regards,Albert
        Am Samstag, 24. November 2018, 22:58:01 MEZ hat Thomas Munro <thomas.munro@enterprisedb.com> Folgendes geschrieben:  
     
     On Sun, Nov 25, 2018 at 12:57 AM Thomas Munro
    <thomas.munro@enterprisedb.com> wrote:
    > It seems we shouldn't be passing a bogus hostname in PAM_RHOST.
    
    I wonder if we should simply not set PAM_RHOST for Unix sockets, since
    (in the words of the Linux PAM man page) "[i]n some applications,
    PAM_RHOST may be NULL", or set it to the hostname of the local
    machine, since in a general sense it is "the hostname of the machine
    from which the PAM_RUSER entity is requesting service" (Linux PAM) and
    "[t]he name of the applicant's host" (OpenPAM).  The latter doesn't
    seem great because it means that a PAM module loses the ability to
    distinguish this case from the IP case, so I think the former is
    probably better.  I haven't managed to find anything explicit about
    the expected value of PAM_RHOST for Unix sockets in either the Linux
    PAM or OpenPAM projects.
    
    I wonder if anyone out there has come to rely on the value "[local]"
    that PostgreSQL generates for this case (ie in a custom PAM module or
    script executed with pam_exec.so), and would get upset if we changed
    it.  Seems pretty unlikely.
    
    The comments for pg_getnameinfo_all() could probably do with a mention
    of the special value written to "node" for Unix sockets.
    
    Some relevant code:
    
    We can see that linux-audit only starts trying to resolve host if you
    didn't also pass in an address:
    
    https://github.com/linux-audit/audit-userspace/blob/e42602b7b246ae62e7a12e9cd91f0ac37b1b1968/lib/audit_logging.c#L456
    
    We can also see that linux-pam always passes NULL as an address:
    
    https://github.com/linux-pam/linux-pam/blob/955b3e2f100205be2db4358e9c812de2ae453b8e/libpam/pam_audit.c#L41
    
    -- 
    Thomas Munro
    http://www.enterprisedb.com
      
  5. Re: BUG #15520: PAM authentication + domain socket -> DNS query for symbolic hostname [local]

    Thomas Munro <thomas.munro@enterprisedb.com> — 2018-11-25T22:30:06Z

    On Mon, Nov 26, 2018 at 9:10 AM Albert Schabhuetl
    <albert_schabhuetl@yahoo.de> wrote:
    > NULL vs hostname for PAM_RHOST:
    >
    > My understanding is that the purpose of the PAM configuration parameter pam_use_hostname is to avoid the adverse effects of DNS queries if set to 0. Thus if pam_use_hostname is 0, PAM_RHOST shall be NULL for domain socket connections, just like it is the case for TCP connections.
    
    It doesn't set it to NULL for TCP connections.  It tells PostgreSQL
    not to bother resolving the name to an address.  We can't do much
    about it if your PAM implementation decides to resolve it anyway.  I
    suppose we could have an option not to set it at all, even for TCP.
    But the main thing that I think we need to change here to address your
    complaint is the Unix socket case, because we're passing a
    non-hostname in a context that expects a hostname, which is silly and
    generates entirely bogus DNS lookups.
    
    Here's a test:
    
    In pg_hba.conf I put these lines:
    local   all             all                                     pam
    pamservice="foo"
    host    all             all             127.0.0.1/32            pam
    pamservice="foo"
    
    In /etc/pam.d/foo I put these lines:
    auth optional pam_exec.so /tmp/spy_script.sh
    auth required pam_permit.so
    
    In /tmp/spy_script.sh I put these lines, and made it executable:
    #!/bin/bash
    echo "PAM_USER=$PAM_USER, PAM_RHOST=$PAM_RHOST" > /tmp/spy_script.out
    
    $ psql -h localhost postgres munro
    -> PAM_USER=munro, PAM_RHOST=127.0.0.1
    $ psql postgres munro
    -> PAM_USER=munro, PAM_RHOST=[local]
    
    Now in pg_hba.conf I add pam_use_hostname=1 to the end of both lines...
    
    $ psql -h localhost postgres munro
    -> PAM_USER=munro, PAM_RHOST=localhost
    $ psql postgres munro
    -> PAM_USER=munro, PAM_RHOST=[local]
    
    > >I wonder if anyone out there has come to rely on the value "[local]"
    >
    > I vote for changing it, and documenting it in the release notes.
    
    Yeah.  Here is a draft patch to change that.  Test output:
    
    $ psql -h localhost postgres munro
    PAM_USER=munro, PAM_RHOST=localhost
    $ psql postgres munro
    PAM_USER=munro, PAM_RHOST=
    
    -- 
    Thomas Munro
    http://www.enterprisedb.com
    
  6. Re: BUG #15520: PAM authentication + domain socket -> DNS query for symbolic hostname [local]

    Peter Eisentraut <peter.eisentraut@2ndquadrant.com> — 2018-11-26T14:02:12Z

    On 25/11/2018 23:30, Thomas Munro wrote:
    >>> I wonder if anyone out there has come to rely on the value "[local]"
    >> I vote for changing it, and documenting it in the release notes.
    > Yeah.  Here is a draft patch to change that.  Test output:
    > 
    > $ psql -h localhost postgres munro
    > PAM_USER=munro, PAM_RHOST=localhost
    > $ psql postgres munro
    > PAM_USER=munro, PAM_RHOST=
    
    I think this is the right thing to do.
    
    About your patch, if we're not going to set PAM_RHOST, then we should
    also avoid the call to pg_getnameinfo_all() earlier in CheckPAMAuth().
    Look at the original patch linked earlier in the thread; we just need to
    put if statements around both of those hunks.
    
    -- 
    Peter Eisentraut              http://www.2ndQuadrant.com/
    PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
    
    
    
  7. Re: BUG #15520: PAM authentication + domain socket -> DNS query for symbolic hostname [local]

    Thomas Munro <thomas.munro@enterprisedb.com> — 2018-11-27T00:39:01Z

    On Tue, Nov 27, 2018 at 3:02 AM Peter Eisentraut
    <peter.eisentraut@2ndquadrant.com> wrote:
    > On 25/11/2018 23:30, Thomas Munro wrote:
    > >>> I wonder if anyone out there has come to rely on the value "[local]"
    > >> I vote for changing it, and documenting it in the release notes.
    > > Yeah.  Here is a draft patch to change that.  Test output:
    > >
    > > $ psql -h localhost postgres munro
    > > PAM_USER=munro, PAM_RHOST=localhost
    > > $ psql postgres munro
    > > PAM_USER=munro, PAM_RHOST=
    >
    > I think this is the right thing to do.
    >
    > About your patch, if we're not going to set PAM_RHOST, then we should
    > also avoid the call to pg_getnameinfo_all() earlier in CheckPAMAuth().
    > Look at the original patch linked earlier in the thread; we just need to
    > put if statements around both of those hunks.
    
    Thanks for the review.  Right.  Here's a new version that moves both
    things under the same if, and refactors a long line to fit in passing.
    
    I wondered whether we could write
    src/test/authentication/t/003_pam.pl, but it seems hard to do without
    underhand tricks.  Both open source PAM implementations really want to
    read their configuration from /etc.
    
    -- 
    Thomas Munro
    http://www.enterprisedb.com
    
  8. Re: BUG #15520: PAM authentication + domain socket -> DNS query for symbolic hostname [local]

    Thomas Munro <thomas.munro@enterprisedb.com> — 2018-11-28T02:03:58Z

    On Tue, Nov 27, 2018 at 1:39 PM Thomas Munro
    <thomas.munro@enterprisedb.com> wrote:
    > On Tue, Nov 27, 2018 at 3:02 AM Peter Eisentraut
    > <peter.eisentraut@2ndquadrant.com> wrote:
    > > On 25/11/2018 23:30, Thomas Munro wrote:
    > > > $ psql -h localhost postgres munro
    > > > PAM_USER=munro, PAM_RHOST=localhost
    > > > $ psql postgres munro
    > > > PAM_USER=munro, PAM_RHOST=
    > >
    > > I think this is the right thing to do.
    > >
    > > About your patch, if we're not going to set PAM_RHOST, then we should
    > > also avoid the call to pg_getnameinfo_all() earlier in CheckPAMAuth().
    > > Look at the original patch linked earlier in the thread; we just need to
    > > put if statements around both of those hunks.
    >
    > Thanks for the review.  Right.  Here's a new version that moves both
    > things under the same if, and refactors a long line to fit in passing.
    
    Pushed, and back-patched to 9.6.  I wondered whether a documentation
    change was warranted, but the special "[local]" value wasn't
    documented in the first place, and it shouldn't really surprise anyone
    that there is no remote host information for a local connection.  A
    release note about the change seems sufficient.
    
    Thanks for the report.
    
    -- 
    Thomas Munro
    http://www.enterprisedb.com