Header And Logo

PostgreSQL
| The world's most advanced open source database.

Typedefs | Functions | Variables

auth.h File Reference

#include "libpq/libpq-be.h"
Include dependency graph for auth.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Typedefs

typedef void(* ClientAuthentication_hook_type )(Port *, int)

Functions

void ClientAuthentication (Port *port)

Variables

char * pg_krb_server_keyfile
char * pg_krb_srvnam
bool pg_krb_caseins_users
char * pg_krb_server_hostname
char * pg_krb_realm
PGDLLIMPORT
ClientAuthentication_hook_type 
ClientAuthentication_hook

Typedef Documentation

typedef void(* ClientAuthentication_hook_type)(Port *, int)

Definition at line 28 of file auth.h.


Function Documentation

void ClientAuthentication ( Port port  ) 

Definition at line 319 of file auth.c.

References _, SockAddr::addr, am_walsender, Assert, auth_failed(), HbaLine::auth_method, AUTH_REQ_GSS, AUTH_REQ_KRB5, AUTH_REQ_MD5, AUTH_REQ_OK, AUTH_REQ_PASSWORD, AUTH_REQ_SSPI, CHECK_FOR_INTERRUPTS, CheckRADIUSAuth(), ClientAuthentication_hook, HbaLine::clientcert, Port::database_name, Db_user_namespace, ereport, errcode(), errmsg(), FATAL, Port::hba, hba_getauthmethod(), HOSTNAME_LOOKUP_DETAIL, ident_inet(), ImmediateInterruptOK, NI_NUMERICHOST, NULL, pg_getnameinfo_all(), Port::raddr, recv_and_check_password_packet(), SockAddr::salen, sendAuthRequest(), status(), STATUS_OK, uaCert, uaGSS, uaIdent, uaImplicitReject, uaKrb5, uaLDAP, uaMD5, uaPAM, uaPassword, uaPeer, uaRADIUS, uaReject, uaSSPI, uaTrust, and Port::user_name.

Referenced by PerformAuthentication().

{
    int         status = STATUS_ERROR;

    /*
     * Get the authentication method to use for this frontend/database
     * combination.  Note: we do not parse the file at this point; this has
     * already been done elsewhere.  hba.c dropped an error message into the
     * server logfile if parsing the hba config file failed.
     */
    hba_getauthmethod(port);

    /*
     * Enable immediate response to SIGTERM/SIGINT/timeout interrupts. (We
     * don't want this during hba_getauthmethod() because it might have to do
     * database access, eg for role membership checks.)
     */
    ImmediateInterruptOK = true;
    /* And don't forget to detect one that already arrived */
    CHECK_FOR_INTERRUPTS();

    /*
     * This is the first point where we have access to the hba record for the
     * current connection, so perform any verifications based on the hba
     * options field that should be done *before* the authentication here.
     */
    if (port->hba->clientcert)
    {
        /*
         * When we parse pg_hba.conf, we have already made sure that we have
         * been able to load a certificate store. Thus, if a certificate is
         * present on the client, it has been verified against our root
         * certificate store, and the connection would have been aborted
         * already if it didn't verify ok.
         */
#ifdef USE_SSL
        if (!port->peer)
        {
            ereport(FATAL,
                    (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
                  errmsg("connection requires a valid client certificate")));
        }
#else

        /*
         * hba.c makes sure hba->clientcert can't be set unless OpenSSL is
         * present.
         */
        Assert(false);
#endif
    }

    /*
     * Now proceed to do the actual authentication check
     */
    switch (port->hba->auth_method)
    {
        case uaReject:

            /*
             * An explicit "reject" entry in pg_hba.conf.  This report exposes
             * the fact that there's an explicit reject entry, which is
             * perhaps not so desirable from a security standpoint; but the
             * message for an implicit reject could confuse the DBA a lot when
             * the true situation is a match to an explicit reject.  And we
             * don't want to change the message for an implicit reject.  As
             * noted below, the additional information shown here doesn't
             * expose anything not known to an attacker.
             */
            {
                char        hostinfo[NI_MAXHOST];

                pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
                                   hostinfo, sizeof(hostinfo),
                                   NULL, 0,
                                   NI_NUMERICHOST);

                if (am_walsender)
                {
#ifdef USE_SSL
                    ereport(FATAL,
                       (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
                        errmsg("pg_hba.conf rejects replication connection for host \"%s\", user \"%s\", %s",
                               hostinfo, port->user_name,
                               port->ssl ? _("SSL on") : _("SSL off"))));
#else
                    ereport(FATAL,
                       (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
                        errmsg("pg_hba.conf rejects replication connection for host \"%s\", user \"%s\"",
                               hostinfo, port->user_name)));
#endif
                }
                else
                {
#ifdef USE_SSL
                    ereport(FATAL,
                       (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
                        errmsg("pg_hba.conf rejects connection for host \"%s\", user \"%s\", database \"%s\", %s",
                               hostinfo, port->user_name,
                               port->database_name,
                               port->ssl ? _("SSL on") : _("SSL off"))));
#else
                    ereport(FATAL,
                       (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
                        errmsg("pg_hba.conf rejects connection for host \"%s\", user \"%s\", database \"%s\"",
                               hostinfo, port->user_name,
                               port->database_name)));
#endif
                }
                break;
            }

        case uaImplicitReject:

            /*
             * No matching entry, so tell the user we fell through.
             *
             * NOTE: the extra info reported here is not a security breach,
             * because all that info is known at the frontend and must be
             * assumed known to bad guys.  We're merely helping out the less
             * clueful good guys.
             */
            {
                char        hostinfo[NI_MAXHOST];

                pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
                                   hostinfo, sizeof(hostinfo),
                                   NULL, 0,
                                   NI_NUMERICHOST);

#define HOSTNAME_LOOKUP_DETAIL(port) \
                (port->remote_hostname                \
                 ? (port->remote_hostname_resolv == +1                  \
                    ? errdetail_log("Client IP address resolved to \"%s\", forward lookup matches.", port->remote_hostname) \
                    : (port->remote_hostname_resolv == 0                \
                       ? errdetail_log("Client IP address resolved to \"%s\", forward lookup not checked.", port->remote_hostname) \
                       : (port->remote_hostname_resolv == -1            \
                          ? errdetail_log("Client IP address resolved to \"%s\", forward lookup does not match.", port->remote_hostname) \
                          : 0)))                                        \
                 : 0)

                if (am_walsender)
                {
#ifdef USE_SSL
                    ereport(FATAL,
                       (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
                        errmsg("no pg_hba.conf entry for replication connection from host \"%s\", user \"%s\", %s",
                               hostinfo, port->user_name,
                               port->ssl ? _("SSL on") : _("SSL off")),
                        HOSTNAME_LOOKUP_DETAIL(port)));
#else
                    ereport(FATAL,
                       (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
                        errmsg("no pg_hba.conf entry for replication connection from host \"%s\", user \"%s\"",
                               hostinfo, port->user_name),
                        HOSTNAME_LOOKUP_DETAIL(port)));
#endif
                }
                else
                {
#ifdef USE_SSL
                    ereport(FATAL,
                       (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
                        errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s",
                               hostinfo, port->user_name,
                               port->database_name,
                               port->ssl ? _("SSL on") : _("SSL off")),
                        HOSTNAME_LOOKUP_DETAIL(port)));
#else
                    ereport(FATAL,
                       (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
                        errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\"",
                               hostinfo, port->user_name,
                               port->database_name),
                        HOSTNAME_LOOKUP_DETAIL(port)));
#endif
                }
                break;
            }

        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 uaPeer:
#ifdef HAVE_UNIX_SOCKETS
            status = auth_peer(port);
#else
            Assert(false);
#endif
            break;

        case uaIdent:
            status = ident_inet(port);
            break;

        case uaMD5:
            if (Db_user_namespace)
                ereport(FATAL,
                        (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
                         errmsg("MD5 authentication is not supported when \"db_user_namespace\" is enabled")));
            sendAuthRequest(port, AUTH_REQ_MD5);
            status = recv_and_check_password_packet(port);
            break;

        case uaPassword:
            sendAuthRequest(port, AUTH_REQ_PASSWORD);
            status = recv_and_check_password_packet(port);
            break;

        case uaPAM:
#ifdef USE_PAM
            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 uaCert:
#ifdef USE_SSL
            status = CheckCertAuth(port);
#else
            Assert(false);
#endif
            break;
        case uaRADIUS:
            status = CheckRADIUSAuth(port);
            break;
        case uaTrust:
            status = STATUS_OK;
            break;
    }

    if (ClientAuthentication_hook)
        (*ClientAuthentication_hook) (port, status);

    if (status == STATUS_OK)
        sendAuthRequest(port, AUTH_REQ_OK);
    else
        auth_failed(port, status);

    /* Done with authentication, so we should turn off immediate interrupts */
    ImmediateInterruptOK = false;
}


Variable Documentation

Definition at line 220 of file auth.c.

Referenced by _PG_init(), ClientAuthentication(), and sepgsql_init_client_label().

Definition at line 132 of file auth.c.

char* pg_krb_realm

Definition at line 130 of file auth.c.

Definition at line 131 of file auth.c.