LCOV - differential code coverage report
Current view: top level - src/backend/libpq - auth.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 38.8 % 896 348 7 37 342 162 33 224 9 82 346 215 7 14
Current Date: 2023-04-08 15:15:32 Functions: 66.7 % 24 16 1 7 16 8 13 3
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * auth.c
       4                 :  *    Routines to handle network authentication
       5                 :  *
       6                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
       7                 :  * Portions Copyright (c) 1994, Regents of the University of California
       8                 :  *
       9                 :  *
      10                 :  * IDENTIFICATION
      11                 :  *    src/backend/libpq/auth.c
      12                 :  *
      13                 :  *-------------------------------------------------------------------------
      14                 :  */
      15                 : 
      16                 : #include "postgres.h"
      17                 : 
      18                 : #include <sys/param.h>
      19                 : #include <sys/select.h>
      20                 : #include <sys/socket.h>
      21                 : #include <netinet/in.h>
      22                 : #include <netdb.h>
      23                 : #include <pwd.h>
      24                 : #include <unistd.h>
      25                 : 
      26                 : #include "commands/user.h"
      27                 : #include "common/ip.h"
      28                 : #include "common/md5.h"
      29                 : #include "libpq/auth.h"
      30                 : #include "libpq/crypt.h"
      31                 : #include "libpq/libpq.h"
      32                 : #include "libpq/pqformat.h"
      33                 : #include "libpq/sasl.h"
      34                 : #include "libpq/scram.h"
      35                 : #include "miscadmin.h"
      36                 : #include "port/pg_bswap.h"
      37                 : #include "postmaster/postmaster.h"
      38                 : #include "replication/walsender.h"
      39                 : #include "storage/ipc.h"
      40                 : #include "utils/guc.h"
      41                 : #include "utils/memutils.h"
      42                 : #include "utils/timestamp.h"
      43                 : 
      44                 : /*----------------------------------------------------------------
      45                 :  * Global authentication functions
      46                 :  *----------------------------------------------------------------
      47                 :  */
      48                 : static void auth_failed(Port *port, int status, const char *logdetail);
      49                 : static char *recv_password_packet(Port *port);
      50                 : static void set_authn_id(Port *port, const char *id);
      51                 : 
      52                 : 
      53                 : /*----------------------------------------------------------------
      54                 :  * Password-based authentication methods (password, md5, and scram-sha-256)
      55                 :  *----------------------------------------------------------------
      56                 :  */
      57                 : static int  CheckPasswordAuth(Port *port, const char **logdetail);
      58                 : static int  CheckPWChallengeAuth(Port *port, const char **logdetail);
      59                 : 
      60                 : static int  CheckMD5Auth(Port *port, char *shadow_pass,
      61                 :                          const char **logdetail);
      62                 : 
      63                 : 
      64                 : /*----------------------------------------------------------------
      65                 :  * Ident authentication
      66                 :  *----------------------------------------------------------------
      67                 :  */
      68                 : /* Max size of username ident server can return (per RFC 1413) */
      69                 : #define IDENT_USERNAME_MAX 512
      70                 : 
      71                 : /* Standard TCP port number for Ident service.  Assigned by IANA */
      72                 : #define IDENT_PORT 113
      73                 : 
      74                 : static int  ident_inet(hbaPort *port);
      75                 : 
      76                 : 
      77                 : /*----------------------------------------------------------------
      78                 :  * Peer authentication
      79                 :  *----------------------------------------------------------------
      80                 :  */
      81                 : static int  auth_peer(hbaPort *port);
      82                 : 
      83                 : 
      84                 : /*----------------------------------------------------------------
      85                 :  * PAM authentication
      86                 :  *----------------------------------------------------------------
      87                 :  */
      88                 : #ifdef USE_PAM
      89                 : #ifdef HAVE_PAM_PAM_APPL_H
      90                 : #include <pam/pam_appl.h>
      91                 : #endif
      92                 : #ifdef HAVE_SECURITY_PAM_APPL_H
      93                 : #include <security/pam_appl.h>
      94                 : #endif
      95                 : 
      96                 : #define PGSQL_PAM_SERVICE "postgresql"    /* Service name passed to PAM */
      97                 : 
      98                 : static int  CheckPAMAuth(Port *port, const char *user, const char *password);
      99                 : static int  pam_passwd_conv_proc(int num_msg, const struct pam_message **msg,
     100                 :                                  struct pam_response **resp, void *appdata_ptr);
     101                 : 
     102                 : static struct pam_conv pam_passw_conv = {
     103                 :     &pam_passwd_conv_proc,
     104                 :     NULL
     105                 : };
     106                 : 
     107                 : static const char *pam_passwd = NULL;   /* Workaround for Solaris 2.6
     108                 :                                          * brokenness */
     109                 : static Port *pam_port_cludge;   /* Workaround for passing "Port *port" into
     110                 :                                  * pam_passwd_conv_proc */
     111                 : static bool pam_no_password;    /* For detecting no-password-given */
     112                 : #endif                          /* USE_PAM */
     113                 : 
     114                 : 
     115                 : /*----------------------------------------------------------------
     116                 :  * BSD authentication
     117                 :  *----------------------------------------------------------------
     118                 :  */
     119                 : #ifdef USE_BSD_AUTH
     120                 : #include <bsd_auth.h>
     121                 : 
     122                 : static int  CheckBSDAuth(Port *port, char *user);
     123                 : #endif                          /* USE_BSD_AUTH */
     124                 : 
     125                 : 
     126                 : /*----------------------------------------------------------------
     127                 :  * LDAP authentication
     128                 :  *----------------------------------------------------------------
     129                 :  */
     130                 : #ifdef USE_LDAP
     131                 : #ifndef WIN32
     132                 : /* We use a deprecated function to keep the codepath the same as win32. */
     133                 : #define LDAP_DEPRECATED 1
     134                 : #include <ldap.h>
     135                 : #else
     136                 : #include <winldap.h>
     137                 : 
     138                 : #endif
     139                 : 
     140                 : static int  CheckLDAPAuth(Port *port);
     141                 : 
     142                 : /* LDAP_OPT_DIAGNOSTIC_MESSAGE is the newer spelling */
     143                 : #ifndef LDAP_OPT_DIAGNOSTIC_MESSAGE
     144                 : #define LDAP_OPT_DIAGNOSTIC_MESSAGE LDAP_OPT_ERROR_STRING
     145                 : #endif
     146                 : 
     147                 : /* Default LDAP password mutator hook, can be overridden by a shared library */
     148                 : static char *dummy_ldap_password_mutator(char *input);
     149                 : auth_password_hook_typ ldap_password_hook = dummy_ldap_password_mutator;
     150                 : 
     151                 : #endif                          /* USE_LDAP */
     152                 : 
     153                 : /*----------------------------------------------------------------
     154                 :  * Cert authentication
     155                 :  *----------------------------------------------------------------
     156                 :  */
     157                 : #ifdef USE_SSL
     158                 : static int  CheckCertAuth(Port *port);
     159                 : #endif
     160                 : 
     161                 : 
     162                 : /*----------------------------------------------------------------
     163                 :  * Kerberos and GSSAPI GUCs
     164                 :  *----------------------------------------------------------------
     165                 :  */
     166                 : char       *pg_krb_server_keyfile;
     167                 : bool        pg_krb_caseins_users;
     168                 : 
     169                 : 
     170                 : /*----------------------------------------------------------------
     171                 :  * GSSAPI Authentication
     172                 :  *----------------------------------------------------------------
     173                 :  */
     174                 : #ifdef ENABLE_GSS
     175                 : #include "libpq/be-gssapi-common.h"
     176                 : 
     177                 : static int  pg_GSS_checkauth(Port *port);
     178                 : static int  pg_GSS_recvauth(Port *port);
     179                 : #endif                          /* ENABLE_GSS */
     180                 : 
     181                 : 
     182                 : /*----------------------------------------------------------------
     183                 :  * SSPI Authentication
     184                 :  *----------------------------------------------------------------
     185                 :  */
     186                 : #ifdef ENABLE_SSPI
     187                 : typedef SECURITY_STATUS
     188                 :             (WINAPI * QUERY_SECURITY_CONTEXT_TOKEN_FN) (PCtxtHandle, void **);
     189                 : static int  pg_SSPI_recvauth(Port *port);
     190                 : static int  pg_SSPI_make_upn(char *accountname,
     191                 :                              size_t accountnamesize,
     192                 :                              char *domainname,
     193                 :                              size_t domainnamesize,
     194                 :                              bool update_accountname);
     195                 : #endif
     196                 : 
     197                 : /*----------------------------------------------------------------
     198                 :  * RADIUS Authentication
     199                 :  *----------------------------------------------------------------
     200                 :  */
     201                 : static int  CheckRADIUSAuth(Port *port);
     202                 : static int  PerformRadiusTransaction(const char *server, const char *secret, const char *portstr, const char *identifier, const char *user_name, const char *passwd);
     203                 : 
     204                 : 
     205                 : /*
     206                 :  * Maximum accepted size of GSS and SSPI authentication tokens.
     207                 :  * We also use this as a limit on ordinary password packet lengths.
     208                 :  *
     209                 :  * Kerberos tickets are usually quite small, but the TGTs issued by Windows
     210                 :  * domain controllers include an authorization field known as the Privilege
     211                 :  * Attribute Certificate (PAC), which contains the user's Windows permissions
     212                 :  * (group memberships etc.). The PAC is copied into all tickets obtained on
     213                 :  * the basis of this TGT (even those issued by Unix realms which the Windows
     214                 :  * realm trusts), and can be several kB in size. The maximum token size
     215                 :  * accepted by Windows systems is determined by the MaxAuthToken Windows
     216                 :  * registry setting. Microsoft recommends that it is not set higher than
     217                 :  * 65535 bytes, so that seems like a reasonable limit for us as well.
     218                 :  */
     219                 : #define PG_MAX_AUTH_TOKEN_LENGTH    65535
     220                 : 
     221                 : /*----------------------------------------------------------------
     222                 :  * Global authentication functions
     223                 :  *----------------------------------------------------------------
     224                 :  */
     225                 : 
     226                 : /*
     227                 :  * This hook allows plugins to get control following client authentication,
     228                 :  * but before the user has been informed about the results.  It could be used
     229                 :  * to record login events, insert a delay after failed authentication, etc.
     230                 :  */
     231                 : ClientAuthentication_hook_type ClientAuthentication_hook = NULL;
     232                 : 
     233                 : /*
     234                 :  * Tell the user the authentication failed, but not (much about) why.
     235                 :  *
     236                 :  * There is a tradeoff here between security concerns and making life
     237                 :  * unnecessarily difficult for legitimate users.  We would not, for example,
     238                 :  * want to report the password we were expecting to receive...
     239                 :  * But it seems useful to report the username and authorization method
     240                 :  * in use, and these are items that must be presumed known to an attacker
     241                 :  * anyway.
     242 ECB             :  * Note that many sorts of failure report additional information in the
     243                 :  * postmaster log, which we hope is only readable by good guys.  In
     244                 :  * particular, if logdetail isn't NULL, we send that string to the log.
     245                 :  */
     246                 : static void
     247 GIC          50 : auth_failed(Port *port, int status, const char *logdetail)
     248                 : {
     249                 :     const char *errstr;
     250                 :     char       *cdetail;
     251              50 :     int         errcode_return = ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION;
     252                 : 
     253                 :     /*
     254                 :      * If we failed due to EOF from client, just quit; there's no point in
     255                 :      * trying to send a message to the client, and not much point in logging
     256                 :      * the failure in the postmaster log.  (Logging the failure might be
     257                 :      * desirable, were it not for the fact that libpq closes the connection
     258 ECB             :      * unceremoniously if challenged for a password when it hasn't got one to
     259                 :      * send.  We'll get a useless log entry for every psql connection under
     260                 :      * password auth, even if it's perfectly successful, if we log STATUS_EOF
     261                 :      * events.)
     262                 :      */
     263 GBC          50 :     if (status == STATUS_EOF)
     264 GIC          21 :         proc_exit(0);
     265 EUB             : 
     266 GBC          29 :     switch (port->hba->auth_method)
     267 ECB             :     {
     268 LBC           0 :         case uaReject:
     269 ECB             :         case uaImplicitReject:
     270 UBC           0 :             errstr = gettext_noop("authentication failed for user \"%s\": host rejected");
     271               0 :             break;
     272 GBC           1 :         case uaTrust:
     273 CBC           1 :             errstr = gettext_noop("\"trust\" authentication failed for user \"%s\"");
     274               1 :             break;
     275 LBC           0 :         case uaIdent:
     276               0 :             errstr = gettext_noop("Ident authentication failed for user \"%s\"");
     277 UIC           0 :             break;
     278 GIC           6 :         case uaPeer:
     279 CBC           6 :             errstr = gettext_noop("Peer authentication failed for user \"%s\"");
     280 GIC           6 :             break;
     281 CBC           5 :         case uaPassword:
     282 ECB             :         case uaMD5:
     283                 :         case uaSCRAM:
     284 CBC           5 :             errstr = gettext_noop("password authentication failed for user \"%s\"");
     285 ECB             :             /* We use it to indicate if a .pgpass password failed. */
     286 GBC           5 :             errcode_return = ERRCODE_INVALID_PASSWORD;
     287               5 :             break;
     288               4 :         case uaGSS:
     289               4 :             errstr = gettext_noop("GSSAPI authentication failed for user \"%s\"");
     290               4 :             break;
     291 UBC           0 :         case uaSSPI:
     292               0 :             errstr = gettext_noop("SSPI authentication failed for user \"%s\"");
     293               0 :             break;
     294               0 :         case uaPAM:
     295 LBC           0 :             errstr = gettext_noop("PAM authentication failed for user \"%s\"");
     296               0 :             break;
     297               0 :         case uaBSD:
     298               0 :             errstr = gettext_noop("BSD authentication failed for user \"%s\"");
     299               0 :             break;
     300 CBC          12 :         case uaLDAP:
     301 GBC          12 :             errstr = gettext_noop("LDAP authentication failed for user \"%s\"");
     302              12 :             break;
     303               1 :         case uaCert:
     304               1 :             errstr = gettext_noop("certificate authentication failed for user \"%s\"");
     305               1 :             break;
     306 UBC           0 :         case uaRADIUS:
     307 UIC           0 :             errstr = gettext_noop("RADIUS authentication failed for user \"%s\"");
     308               0 :             break;
     309 LBC           0 :         default:
     310               0 :             errstr = gettext_noop("authentication failed for user \"%s\": invalid authentication method");
     311               0 :             break;
     312 ECB             :     }
     313                 : 
     314 GNC          29 :     cdetail = psprintf(_("Connection matched %s line %d: \"%s\""),
     315              29 :                        port->hba->sourcefile, port->hba->linenumber,
     316              29 :                        port->hba->rawline);
     317 GIC          29 :     if (logdetail)
     318 CBC           1 :         logdetail = psprintf("%s\n%s", logdetail, cdetail);
     319                 :     else
     320 GIC          28 :         logdetail = cdetail;
     321                 : 
     322              29 :     ereport(FATAL,
     323                 :             (errcode(errcode_return),
     324                 :              errmsg(errstr, port->user_name),
     325                 :              logdetail ? errdetail_log("%s", logdetail) : 0));
     326                 : 
     327                 :     /* doesn't return */
     328                 : }
     329                 : 
     330                 : 
     331                 : /*
     332                 :  * Sets the authenticated identity for the current user.  The provided string
     333                 :  * will be stored into MyClientConnectionInfo, alongside the current HBA
     334                 :  * method in use.  The ID will be logged if log_connections is enabled.
     335                 :  *
     336                 :  * Auth methods should call this routine exactly once, as soon as the user is
     337                 :  * successfully authenticated, even if they have reasons to know that
     338                 :  * authorization will fail later.
     339                 :  *
     340                 :  * The provided string will be copied into TopMemoryContext, to match the
     341                 :  * lifetime of MyClientConnectionInfo, so it is safe to pass a string that is
     342                 :  * managed by an external library.
     343 ECB             :  */
     344                 : static void
     345 CBC         124 : set_authn_id(Port *port, const char *id)
     346                 : {
     347 GIC         124 :     Assert(id);
     348                 : 
     349 GNC         124 :     if (MyClientConnectionInfo.authn_id)
     350                 :     {
     351                 :         /*
     352                 :          * An existing authn_id should never be overwritten; that means two
     353 EUB             :          * authentication providers are fighting (or one is fighting itself).
     354                 :          * Don't leak any authn details to the client, but don't let the
     355                 :          * connection continue, either.
     356                 :          */
     357 UIC           0 :         ereport(FATAL,
     358                 :                 (errmsg("authentication identifier set more than once"),
     359 ECB             :                  errdetail_log("previous identifier: \"%s\"; new identifier: \"%s\"",
     360                 :                                MyClientConnectionInfo.authn_id, id)));
     361                 :     }
     362                 : 
     363 GNC         124 :     MyClientConnectionInfo.authn_id = MemoryContextStrdup(TopMemoryContext, id);
     364             124 :     MyClientConnectionInfo.auth_method = port->hba->auth_method;
     365 ECB             : 
     366 GIC         124 :     if (Log_connections)
     367                 :     {
     368             116 :         ereport(LOG,
     369                 :                 errmsg("connection authenticated: identity=\"%s\" method=%s "
     370                 :                        "(%s:%d)",
     371                 :                        MyClientConnectionInfo.authn_id,
     372                 :                        hba_authname(MyClientConnectionInfo.auth_method),
     373                 :                        port->hba->sourcefile, port->hba->linenumber));
     374                 :     }
     375             124 : }
     376                 : 
     377                 : 
     378                 : /*
     379                 :  * Client authentication starts here.  If there is an error, this
     380                 :  * function does not return and the backend process is terminated.
     381 ECB             :  */
     382                 : void
     383 CBC        8601 : ClientAuthentication(Port *port)
     384 ECB             : {
     385 GIC        8601 :     int         status = STATUS_ERROR;
     386            8601 :     const char *logdetail = NULL;
     387                 : 
     388                 :     /*
     389                 :      * Get the authentication method to use for this frontend/database
     390                 :      * combination.  Note: we do not parse the file at this point; this has
     391                 :      * already been done elsewhere.  hba.c dropped an error message into the
     392 ECB             :      * server logfile if parsing the hba config file failed.
     393                 :      */
     394 CBC        8601 :     hba_getauthmethod(port);
     395                 : 
     396 GIC        8601 :     CHECK_FOR_INTERRUPTS();
     397                 : 
     398                 :     /*
     399                 :      * This is the first point where we have access to the hba record for the
     400                 :      * current connection, so perform any verifications based on the hba
     401 ECB             :      * options field that should be done *before* the authentication here.
     402                 :      */
     403 GIC        8601 :     if (port->hba->clientcert != clientCertOff)
     404 ECB             :     {
     405 EUB             :         /* If we haven't loaded a root certificate store, fail */
     406 GIC          30 :         if (!secure_loaded_verify_locations())
     407 UIC           0 :             ereport(FATAL,
     408                 :                     (errcode(ERRCODE_CONFIG_FILE_ERROR),
     409                 :                      errmsg("client certificates can only be checked if a root certificate store is available")));
     410                 : 
     411                 :         /*
     412                 :          * If we loaded a root certificate store, and if a certificate is
     413                 :          * present on the client, then it has been verified against our root
     414                 :          * certificate store, and the connection would have been aborted
     415 ECB             :          * already if it didn't verify ok.
     416                 :          */
     417 GIC          30 :         if (!port->peer_cert_valid)
     418               2 :             ereport(FATAL,
     419                 :                     (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
     420                 :                      errmsg("connection requires a valid client certificate")));
     421                 :     }
     422                 : 
     423                 :     /*
     424 ECB             :      * Now proceed to do the actual authentication check
     425                 :      */
     426 GBC        8599 :     switch (port->hba->auth_method)
     427                 :     {
     428 UIC           0 :         case uaReject:
     429                 : 
     430                 :             /*
     431                 :              * An explicit "reject" entry in pg_hba.conf.  This report exposes
     432                 :              * the fact that there's an explicit reject entry, which is
     433                 :              * perhaps not so desirable from a security standpoint; but the
     434                 :              * message for an implicit reject could confuse the DBA a lot when
     435                 :              * the true situation is a match to an explicit reject.  And we
     436                 :              * don't want to change the message for an implicit reject.  As
     437                 :              * noted below, the additional information shown here doesn't
     438                 :              * expose anything not known to an attacker.
     439                 :              */
     440                 :             {
     441                 :                 char        hostinfo[NI_MAXHOST];
     442 EUB             :                 const char *encryption_state;
     443                 : 
     444 UIC           0 :                 pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
     445                 :                                    hostinfo, sizeof(hostinfo),
     446                 :                                    NULL, 0,
     447 EUB             :                                    NI_NUMERICHOST);
     448                 : 
     449 UBC           0 :                 encryption_state =
     450                 : #ifdef ENABLE_GSS
     451 UIC           0 :                     (port->gss && port->gss->enc) ? _("GSS encryption") :
     452 EUB             : #endif
     453                 : #ifdef USE_SSL
     454 UBC           0 :                     port->ssl_in_use ? _("SSL encryption") :
     455                 : #endif
     456               0 :                     _("no encryption");
     457 EUB             : 
     458 UIC           0 :                 if (am_walsender && !am_db_walsender)
     459               0 :                     ereport(FATAL,
     460                 :                             (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
     461                 :                     /* translator: last %s describes encryption state */
     462                 :                              errmsg("pg_hba.conf rejects replication connection for host \"%s\", user \"%s\", %s",
     463                 :                                     hostinfo, port->user_name,
     464 EUB             :                                     encryption_state)));
     465                 :                 else
     466 UIC           0 :                     ereport(FATAL,
     467                 :                             (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
     468                 :                     /* translator: last %s describes encryption state */
     469                 :                              errmsg("pg_hba.conf rejects connection for host \"%s\", user \"%s\", database \"%s\", %s",
     470                 :                                     hostinfo, port->user_name,
     471                 :                                     port->database_name,
     472                 :                                     encryption_state)));
     473                 :                 break;
     474 ECB             :             }
     475                 : 
     476 GIC          10 :         case uaImplicitReject:
     477                 : 
     478                 :             /*
     479                 :              * No matching entry, so tell the user we fell through.
     480                 :              *
     481                 :              * NOTE: the extra info reported here is not a security breach,
     482                 :              * because all that info is known at the frontend and must be
     483                 :              * assumed known to bad guys.  We're merely helping out the less
     484                 :              * clueful good guys.
     485                 :              */
     486                 :             {
     487                 :                 char        hostinfo[NI_MAXHOST];
     488 ECB             :                 const char *encryption_state;
     489                 : 
     490 GIC          10 :                 pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
     491                 :                                    hostinfo, sizeof(hostinfo),
     492                 :                                    NULL, 0,
     493 ECB             :                                    NI_NUMERICHOST);
     494                 : 
     495 CBC           8 :                 encryption_state =
     496                 : #ifdef ENABLE_GSS
     497 GIC          10 :                     (port->gss && port->gss->enc) ? _("GSS encryption") :
     498 ECB             : #endif
     499                 : #ifdef USE_SSL
     500 CBC           8 :                     port->ssl_in_use ? _("SSL encryption") :
     501                 : #endif
     502 GIC           8 :                     _("no encryption");
     503                 : 
     504                 : #define HOSTNAME_LOOKUP_DETAIL(port) \
     505                 :                 (port->remote_hostname ? \
     506                 :                  (port->remote_hostname_resolv == +1 ? \
     507                 :                   errdetail_log("Client IP address resolved to \"%s\", forward lookup matches.", \
     508                 :                                 port->remote_hostname) : \
     509                 :                   port->remote_hostname_resolv == 0 ? \
     510                 :                   errdetail_log("Client IP address resolved to \"%s\", forward lookup not checked.", \
     511                 :                                 port->remote_hostname) : \
     512                 :                   port->remote_hostname_resolv == -1 ? \
     513                 :                   errdetail_log("Client IP address resolved to \"%s\", forward lookup does not match.", \
     514                 :                                 port->remote_hostname) : \
     515                 :                   port->remote_hostname_resolv == -2 ? \
     516                 :                   errdetail_log("Could not translate client host name \"%s\" to IP address: %s.", \
     517                 :                                 port->remote_hostname, \
     518                 :                                 gai_strerror(port->remote_hostname_errcode)) : \
     519                 :                   0) \
     520                 :                  : (port->remote_hostname_resolv == -2 ? \
     521                 :                     errdetail_log("Could not resolve client IP address to a host name: %s.", \
     522                 :                                   gai_strerror(port->remote_hostname_errcode)) : \
     523 ECB             :                     0))
     524 EUB             : 
     525 GIC          10 :                 if (am_walsender && !am_db_walsender)
     526 UIC           0 :                     ereport(FATAL,
     527                 :                             (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
     528                 :                     /* translator: last %s describes encryption state */
     529                 :                              errmsg("no pg_hba.conf entry for replication connection from host \"%s\", user \"%s\", %s",
     530                 :                                     hostinfo, port->user_name,
     531                 :                                     encryption_state),
     532 ECB             :                              HOSTNAME_LOOKUP_DETAIL(port)));
     533                 :                 else
     534 GIC          10 :                     ereport(FATAL,
     535                 :                             (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
     536                 :                     /* translator: last %s describes encryption state */
     537                 :                              errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s",
     538                 :                                     hostinfo, port->user_name,
     539                 :                                     port->database_name,
     540                 :                                     encryption_state),
     541                 :                              HOSTNAME_LOOKUP_DETAIL(port)));
     542                 :                 break;
     543 ECB             :             }
     544                 : 
     545 GIC          21 :         case uaGSS:
     546 ECB             : #ifdef ENABLE_GSS
     547                 :             /* We might or might not have the gss workspace already */
     548 CBC          21 :             if (port->gss == NULL)
     549 GIC           6 :                 port->gss = (pg_gssinfo *)
     550 CBC           6 :                     MemoryContextAllocZero(TopMemoryContext,
     551                 :                                            sizeof(pg_gssinfo));
     552 GIC          21 :             port->gss->auth = true;
     553                 : 
     554                 :             /*
     555                 :              * If GSS state was set up while enabling encryption, we can just
     556 ECB             :              * check the client's principal.  Otherwise, ask for it.
     557                 :              */
     558 GIC          21 :             if (port->gss->enc)
     559              15 :                 status = pg_GSS_checkauth(port);
     560 ECB             :             else
     561                 :             {
     562 GIC           6 :                 sendAuthRequest(port, AUTH_REQ_GSS, NULL, 0);
     563               6 :                 status = pg_GSS_recvauth(port);
     564                 :             }
     565                 : #else
     566 ECB             :             Assert(false);
     567                 : #endif
     568 GBC          21 :             break;
     569                 : 
     570 UIC           0 :         case uaSSPI:
     571                 : #ifdef ENABLE_SSPI
     572                 :             if (port->gss == NULL)
     573                 :                 port->gss = (pg_gssinfo *)
     574                 :                     MemoryContextAllocZero(TopMemoryContext,
     575                 :                                            sizeof(pg_gssinfo));
     576                 :             sendAuthRequest(port, AUTH_REQ_SSPI, NULL, 0);
     577 EUB             :             status = pg_SSPI_recvauth(port);
     578                 : #else
     579 UIC           0 :             Assert(false);
     580                 : #endif
     581 ECB             :             break;
     582                 : 
     583 CBC          26 :         case uaPeer:
     584 GIC          26 :             status = auth_peer(port);
     585 GBC          26 :             break;
     586 EUB             : 
     587 UBC           0 :         case uaIdent:
     588 UIC           0 :             status = ident_inet(port);
     589 LBC           0 :             break;
     590                 : 
     591 CBC          50 :         case uaMD5:
     592 ECB             :         case uaSCRAM:
     593 GIC          50 :             status = CheckPWChallengeAuth(port, &logdetail);
     594 CBC          50 :             break;
     595 ECB             : 
     596 CBC          17 :         case uaPassword:
     597 GIC          17 :             status = CheckPasswordAuth(port, &logdetail);
     598 GBC          17 :             break;
     599                 : 
     600 UBC           0 :         case uaPAM:
     601                 : #ifdef USE_PAM
     602 UIC           0 :             status = CheckPAMAuth(port, port->user_name, "");
     603                 : #else
     604 EUB             :             Assert(false);
     605                 : #endif                          /* USE_PAM */
     606 UBC           0 :             break;
     607                 : 
     608 UIC           0 :         case uaBSD:
     609                 : #ifdef USE_BSD_AUTH
     610 EUB             :             status = CheckBSDAuth(port, port->user_name);
     611                 : #else
     612 UIC           0 :             Assert(false);
     613                 : #endif                          /* USE_BSD_AUTH */
     614 ECB             :             break;
     615                 : 
     616 CBC          26 :         case uaLDAP:
     617                 : #ifdef USE_LDAP
     618 GIC          26 :             status = CheckLDAPAuth(port);
     619                 : #else
     620 ECB             :             Assert(false);
     621 EUB             : #endif
     622 GBC          26 :             break;
     623 UBC           0 :         case uaRADIUS:
     624 LBC           0 :             status = CheckRADIUSAuth(port);
     625 UIC           0 :             break;
     626 GIC        8449 :         case uaCert:
     627 ECB             :             /* uaCert will be treated as if clientcert=verify-full (uaTrust) */
     628                 :         case uaTrust:
     629 GIC        8449 :             status = STATUS_OK;
     630            8449 :             break;
     631 ECB             :     }
     632                 : 
     633 GIC        8589 :     if ((status == STATUS_OK && port->hba->clientcert == clientCertFull)
     634            8562 :         || port->hba->auth_method == uaCert)
     635                 :     {
     636                 :         /*
     637                 :          * Make sure we only check the certificate if we use the cert method
     638                 :          * or verify-full option.
     639 ECB             :          */
     640                 : #ifdef USE_SSL
     641 GIC          27 :         status = CheckCertAuth(port);
     642                 : #else
     643                 :         Assert(false);
     644                 : #endif
     645 ECB             :     }
     646 EUB             : 
     647 GIC        8589 :     if (ClientAuthentication_hook)
     648 LBC           0 :         (*ClientAuthentication_hook) (port, status);
     649 ECB             : 
     650 GIC        8589 :     if (status == STATUS_OK)
     651 CBC        8539 :         sendAuthRequest(port, AUTH_REQ_OK, NULL, 0);
     652 ECB             :     else
     653 GIC          50 :         auth_failed(port, status, logdetail);
     654            8539 : }
     655                 : 
     656                 : 
     657                 : /*
     658                 :  * Send an authentication request packet to the frontend.
     659 ECB             :  */
     660                 : void
     661 GIC        8699 : sendAuthRequest(Port *port, AuthRequest areq, const char *extradata, int extralen)
     662                 : {
     663 ECB             :     StringInfoData buf;
     664                 : 
     665 CBC        8699 :     CHECK_FOR_INTERRUPTS();
     666 ECB             : 
     667 CBC        8699 :     pq_beginmessage(&buf, 'R');
     668            8699 :     pq_sendint32(&buf, (int32) areq);
     669 GIC        8699 :     if (extralen > 0)
     670 CBC         111 :         pq_sendbytes(&buf, extradata, extralen);
     671                 : 
     672 GIC        8699 :     pq_endmessage(&buf);
     673                 : 
     674                 :     /*
     675                 :      * Flush message so client will see it, except for AUTH_REQ_OK and
     676                 :      * AUTH_REQ_SASL_FIN, which need not be sent until we are ready for
     677 ECB             :      * queries.
     678                 :      */
     679 GIC        8699 :     if (areq != AUTH_REQ_OK && areq != AUTH_REQ_SASL_FIN)
     680 CBC         134 :         pq_flush();
     681 ECB             : 
     682 GIC        8699 :     CHECK_FOR_INTERRUPTS();
     683            8699 : }
     684                 : 
     685                 : /*
     686                 :  * Collect password response packet from frontend.
     687                 :  *
     688                 :  * Returns NULL if couldn't get password, else palloc'd string.
     689 ECB             :  */
     690                 : static char *
     691 GIC          56 : recv_password_packet(Port *port)
     692                 : {
     693                 :     StringInfoData buf;
     694 ECB             :     int         mtype;
     695                 : 
     696 GIC          56 :     pq_startmsgread();
     697 ECB             : 
     698                 :     /* Expect 'p' message type */
     699 GIC          56 :     mtype = pq_getbyte();
     700              56 :     if (mtype != 'p')
     701                 :     {
     702                 :         /*
     703                 :          * If the client just disconnects without offering a password, don't
     704                 :          * make a log entry.  This is legal per protocol spec and in fact
     705 ECB             :          * commonly done by psql, so complaining just clutters the log.
     706 EUB             :          */
     707 GIC          15 :         if (mtype != EOF)
     708 UIC           0 :             ereport(ERROR,
     709                 :                     (errcode(ERRCODE_PROTOCOL_VIOLATION),
     710 ECB             :                      errmsg("expected password response, got message type %d",
     711                 :                             mtype)));
     712 GIC          15 :         return NULL;            /* EOF or bad message type */
     713 ECB             :     }
     714                 : 
     715 GIC          41 :     initStringInfo(&buf);
     716              41 :     if (pq_getmessage(&buf, PG_MAX_AUTH_TOKEN_LENGTH))  /* receive password */
     717 EUB             :     {
     718                 :         /* EOF - pq_getmessage already logged a suitable message */
     719 UIC           0 :         pfree(buf.data);
     720               0 :         return NULL;
     721                 :     }
     722                 : 
     723                 :     /*
     724                 :      * Apply sanity check: password packet length should agree with length of
     725                 :      * contained string.  Note it is safe to use strlen here because
     726 ECB             :      * StringInfo is guaranteed to have an appended '\0'.
     727 EUB             :      */
     728 GIC          41 :     if (strlen(buf.data) + 1 != buf.len)
     729 UIC           0 :         ereport(ERROR,
     730                 :                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
     731                 :                  errmsg("invalid password packet size")));
     732                 : 
     733                 :     /*
     734                 :      * Don't allow an empty password. Libpq treats an empty password the same
     735                 :      * as no password at all, and won't even try to authenticate. But other
     736                 :      * clients might, so allowing it would be confusing.
     737                 :      *
     738                 :      * Note that this only catches an empty password sent by the client in
     739                 :      * plaintext. There's also a check in CREATE/ALTER USER that prevents an
     740                 :      * empty string from being stored as a user's password in the first place.
     741                 :      * We rely on that for MD5 and SCRAM authentication, but we still need
     742                 :      * this check here, to prevent an empty password from being used with
     743                 :      * authentication methods that check the password against an external
     744 ECB             :      * system, like PAM, LDAP and RADIUS.
     745 EUB             :      */
     746 GIC          41 :     if (buf.len == 1)
     747 UIC           0 :         ereport(ERROR,
     748                 :                 (errcode(ERRCODE_INVALID_PASSWORD),
     749                 :                  errmsg("empty password returned by client")));
     750 ECB             : 
     751                 :     /* Do not echo password to logs, for security. */
     752 GIC          41 :     elog(DEBUG5, "received password packet");
     753                 : 
     754                 :     /*
     755                 :      * Return the received string.  Note we do not attempt to do any
     756                 :      * character-set conversion on it; since we don't yet know the client's
     757 ECB             :      * encoding, there wouldn't be much point.
     758                 :      */
     759 GIC          41 :     return buf.data;
     760                 : }
     761                 : 
     762                 : 
     763                 : /*----------------------------------------------------------------
     764                 :  * Password-based authentication mechanisms
     765                 :  *----------------------------------------------------------------
     766                 :  */
     767                 : 
     768                 : /*
     769                 :  * Plaintext password authentication.
     770 ECB             :  */
     771                 : static int
     772 GIC          17 : CheckPasswordAuth(Port *port, const char **logdetail)
     773                 : {
     774                 :     char       *passwd;
     775                 :     int         result;
     776 ECB             :     char       *shadow_pass;
     777                 : 
     778 CBC          17 :     sendAuthRequest(port, AUTH_REQ_PASSWORD, NULL, 0);
     779 ECB             : 
     780 CBC          17 :     passwd = recv_password_packet(port);
     781 GIC          17 :     if (passwd == NULL)
     782 CBC           7 :         return STATUS_EOF;      /* client wouldn't send password */
     783 ECB             : 
     784 GIC          10 :     shadow_pass = get_role_password(port->user_name, logdetail);
     785 CBC          10 :     if (shadow_pass)
     786                 :     {
     787 GIC          10 :         result = plain_crypt_verify(port->user_name, shadow_pass, passwd,
     788                 :                                     logdetail);
     789 EUB             :     }
     790                 :     else
     791 LBC           0 :         result = STATUS_ERROR;
     792 ECB             : 
     793 CBC          10 :     if (shadow_pass)
     794 GIC          10 :         pfree(shadow_pass);
     795 CBC          10 :     pfree(passwd);
     796 ECB             : 
     797 GIC          10 :     if (result == STATUS_OK)
     798 CBC          10 :         set_authn_id(port, port->user_name);
     799                 : 
     800 GIC          10 :     return result;
     801                 : }
     802                 : 
     803                 : /*
     804                 :  * MD5 and SCRAM authentication.
     805 ECB             :  */
     806                 : static int
     807 GIC          50 : CheckPWChallengeAuth(Port *port, const char **logdetail)
     808                 : {
     809                 :     int         auth_result;
     810                 :     char       *shadow_pass;
     811 ECB             :     PasswordType pwtype;
     812                 : 
     813 GIC          50 :     Assert(port->hba->auth_method == uaSCRAM ||
     814                 :            port->hba->auth_method == uaMD5);
     815 ECB             : 
     816                 :     /* First look up the user's password. */
     817 GIC          50 :     shadow_pass = get_role_password(port->user_name, logdetail);
     818                 : 
     819                 :     /*
     820                 :      * If the user does not exist, or has no password or it's expired, we
     821                 :      * still go through the motions of authentication, to avoid revealing to
     822                 :      * the client that the user didn't exist.  If 'md5' is allowed, we choose
     823                 :      * whether to use 'md5' or 'scram-sha-256' authentication based on current
     824                 :      * password_encryption setting.  The idea is that most genuine users
     825                 :      * probably have a password of that type, and if we pretend that this user
     826 ECB             :      * had a password of that type, too, it "blends in" best.
     827 EUB             :      */
     828 GIC          50 :     if (!shadow_pass)
     829 LBC           0 :         pwtype = Password_encryption;
     830                 :     else
     831 GIC          50 :         pwtype = get_password_type(shadow_pass);
     832                 : 
     833                 :     /*
     834                 :      * If 'md5' authentication is allowed, decide whether to perform 'md5' or
     835                 :      * 'scram-sha-256' authentication based on the type of password the user
     836                 :      * has.  If it's an MD5 hash, we must do MD5 authentication, and if it's a
     837                 :      * SCRAM secret, we must do SCRAM authentication.
     838                 :      *
     839                 :      * If MD5 authentication is not allowed, always use SCRAM.  If the user
     840                 :      * had an MD5 password, CheckSASLAuth() with the SCRAM mechanism will
     841 ECB             :      * fail.
     842                 :      */
     843 GIC          50 :     if (port->hba->auth_method == uaMD5 && pwtype == PASSWORD_TYPE_MD5)
     844 CBC          13 :         auth_result = CheckMD5Auth(port, shadow_pass, logdetail);
     845                 :     else
     846 GIC          37 :         auth_result = CheckSASLAuth(&pg_be_scram_mech, port, shadow_pass,
     847 ECB             :                                     logdetail);
     848                 : 
     849 GIC          50 :     if (shadow_pass)
     850              50 :         pfree(shadow_pass);
     851                 : 
     852                 :     /*
     853                 :      * If get_role_password() returned error, return error, even if the
     854 ECB             :      * authentication succeeded.
     855                 :      */
     856 GBC          50 :     if (!shadow_pass)
     857 EUB             :     {
     858 UIC           0 :         Assert(auth_result != STATUS_OK);
     859               0 :         return STATUS_ERROR;
     860 ECB             :     }
     861                 : 
     862 GIC          50 :     if (auth_result == STATUS_OK)
     863 CBC          32 :         set_authn_id(port, port->user_name);
     864                 : 
     865 GIC          50 :     return auth_result;
     866                 : }
     867 ECB             : 
     868                 : static int
     869 GIC          13 : CheckMD5Auth(Port *port, char *shadow_pass, const char **logdetail)
     870                 : {
     871                 :     char        md5Salt[4];     /* Password salt */
     872                 :     char       *passwd;
     873 ECB             :     int         result;
     874 EUB             : 
     875 GIC          13 :     if (Db_user_namespace)
     876 UIC           0 :         ereport(FATAL,
     877                 :                 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
     878                 :                  errmsg("MD5 authentication is not supported when \"db_user_namespace\" is enabled")));
     879 ECB             : 
     880                 :     /* include the salt to use for computing the response */
     881 GBC          13 :     if (!pg_strong_random(md5Salt, 4))
     882                 :     {
     883 UBC           0 :         ereport(LOG,
     884                 :                 (errmsg("could not generate random MD5 salt")));
     885 UIC           0 :         return STATUS_ERROR;
     886 ECB             :     }
     887                 : 
     888 CBC          13 :     sendAuthRequest(port, AUTH_REQ_MD5, md5Salt, 4);
     889 ECB             : 
     890 CBC          13 :     passwd = recv_password_packet(port);
     891 GIC          13 :     if (passwd == NULL)
     892 CBC           7 :         return STATUS_EOF;      /* client wouldn't send password */
     893 ECB             : 
     894 GIC           6 :     if (shadow_pass)
     895               6 :         result = md5_crypt_verify(port->user_name, shadow_pass, passwd,
     896 EUB             :                                   md5Salt, 4, logdetail);
     897                 :     else
     898 LBC           0 :         result = STATUS_ERROR;
     899                 : 
     900 CBC           6 :     pfree(passwd);
     901                 : 
     902 GIC           6 :     return result;
     903                 : }
     904                 : 
     905                 : 
     906                 : /*----------------------------------------------------------------
     907                 :  * GSSAPI authentication system
     908                 :  *----------------------------------------------------------------
     909                 :  */
     910 ECB             : #ifdef ENABLE_GSS
     911                 : static int
     912 GIC           6 : pg_GSS_recvauth(Port *port)
     913                 : {
     914                 :     OM_uint32   maj_stat,
     915                 :                 min_stat,
     916                 :                 lmin_s,
     917                 :                 gflags;
     918                 :     int         mtype;
     919                 :     StringInfoData buf;
     920                 :     gss_buffer_desc gbuf;
     921                 : 
     922                 :     /*
     923                 :      * Use the configured keytab, if there is one.  Unfortunately, Heimdal
     924 ECB             :      * doesn't support the cred store extensions, so use the env var.
     925                 :      */
     926 CBC           6 :     if (pg_krb_server_keyfile != NULL && pg_krb_server_keyfile[0] != '\0')
     927                 :     {
     928 GIC           6 :         if (setenv("KRB5_KTNAME", pg_krb_server_keyfile, 1) != 0)
     929 EUB             :         {
     930                 :             /* The only likely failure cause is OOM, so use that errcode */
     931 UIC           0 :             ereport(FATAL,
     932                 :                     (errcode(ERRCODE_OUT_OF_MEMORY),
     933                 :                      errmsg("could not set environment: %m")));
     934                 :         }
     935                 :     }
     936                 : 
     937                 :     /*
     938                 :      * We accept any service principal that's present in our keytab. This
     939                 :      * increases interoperability between kerberos implementations that see
     940                 :      * for example case sensitivity differently, while not really opening up
     941 ECB             :      * any vector of attack.
     942                 :      */
     943 GIC           6 :     port->gss->cred = GSS_C_NO_CREDENTIAL;
     944                 : 
     945                 :     /*
     946 ECB             :      * Initialize sequence with an empty context
     947                 :      */
     948 GIC           6 :     port->gss->ctx = GSS_C_NO_CONTEXT;
     949                 : 
     950                 :     /*
     951                 :      * Loop through GSSAPI message exchange. This exchange can consist of
     952                 :      * multiple messages sent in both directions. First message is always from
     953                 :      * the client. All messages from client to server are password packets
     954                 :      * (type 'p').
     955                 :      */
     956 ECB             :     do
     957                 :     {
     958 CBC           6 :         pq_startmsgread();
     959                 : 
     960               6 :         CHECK_FOR_INTERRUPTS();
     961 ECB             : 
     962 GIC           6 :         mtype = pq_getbyte();
     963               6 :         if (mtype != 'p')
     964 ECB             :         {
     965 EUB             :             /* Only log error if client didn't disconnect. */
     966 GIC           2 :             if (mtype != EOF)
     967 UIC           0 :                 ereport(ERROR,
     968                 :                         (errcode(ERRCODE_PROTOCOL_VIOLATION),
     969 ECB             :                          errmsg("expected GSS response, got message type %d",
     970                 :                                 mtype)));
     971 GIC           2 :             return STATUS_ERROR;
     972                 :         }
     973 ECB             : 
     974                 :         /* Get the actual GSS token */
     975 GIC           4 :         initStringInfo(&buf);
     976               4 :         if (pq_getmessage(&buf, PG_MAX_AUTH_TOKEN_LENGTH))
     977 EUB             :         {
     978                 :             /* EOF - pq_getmessage already logged error */
     979 UIC           0 :             pfree(buf.data);
     980               0 :             return STATUS_ERROR;
     981                 :         }
     982 ECB             : 
     983                 :         /* Map to GSSAPI style buffer */
     984 GIC           4 :         gbuf.length = buf.len;
     985 CBC           4 :         gbuf.value = buf.data;
     986                 : 
     987 GIC           4 :         elog(DEBUG4, "processing received GSS token of length %u",
     988 ECB             :              (unsigned int) gbuf.length);
     989                 : 
     990 CBC           4 :         maj_stat = gss_accept_sec_context(&min_stat,
     991 GIC           4 :                                           &port->gss->ctx,
     992               4 :                                           port->gss->cred,
     993 ECB             :                                           &gbuf,
     994                 :                                           GSS_C_NO_CHANNEL_BINDINGS,
     995 CBC           4 :                                           &port->gss->name,
     996                 :                                           NULL,
     997 GIC           4 :                                           &port->gss->outbuf,
     998                 :                                           &gflags,
     999                 :                                           NULL,
    1000                 :                                           NULL);
    1001 ECB             : 
    1002                 :         /* gbuf no longer used */
    1003 CBC           4 :         pfree(buf.data);
    1004                 : 
    1005 GIC           4 :         elog(DEBUG5, "gss_accept_sec_context major: %u, "
    1006                 :              "minor: %u, outlen: %u, outflags: %x",
    1007                 :              maj_stat, min_stat,
    1008 ECB             :              (unsigned int) port->gss->outbuf.length, gflags);
    1009                 : 
    1010 CBC           4 :         CHECK_FOR_INTERRUPTS();
    1011                 : 
    1012 GIC           4 :         if (port->gss->outbuf.length != 0)
    1013                 :         {
    1014                 :             /*
    1015 ECB             :              * Negotiation generated data to be sent to the client.
    1016                 :              */
    1017 GIC           4 :             elog(DEBUG4, "sending GSS response token of length %u",
    1018 ECB             :                  (unsigned int) port->gss->outbuf.length);
    1019                 : 
    1020 GIC           4 :             sendAuthRequest(port, AUTH_REQ_GSS_CONT,
    1021 CBC           4 :                             port->gss->outbuf.value, port->gss->outbuf.length);
    1022                 : 
    1023 GIC           4 :             gss_release_buffer(&lmin_s, &port->gss->outbuf);
    1024 ECB             :         }
    1025                 : 
    1026 GBC           4 :         if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
    1027 EUB             :         {
    1028 UIC           0 :             gss_delete_sec_context(&lmin_s, &port->gss->ctx, GSS_C_NO_BUFFER);
    1029 UBC           0 :             pg_GSS_error(_("accepting GSS security context failed"),
    1030                 :                          maj_stat, min_stat);
    1031 UIC           0 :             return STATUS_ERROR;
    1032 ECB             :         }
    1033 EUB             : 
    1034 GIC           4 :         if (maj_stat == GSS_S_CONTINUE_NEEDED)
    1035 LBC           0 :             elog(DEBUG4, "GSS continue needed");
    1036                 : 
    1037 CBC           4 :     } while (maj_stat == GSS_S_CONTINUE_NEEDED);
    1038                 : 
    1039 GIC           4 :     if (port->gss->cred != GSS_C_NO_CREDENTIAL)
    1040                 :     {
    1041                 :         /*
    1042 EUB             :          * Release service principal credentials
    1043                 :          */
    1044 LBC           0 :         gss_release_cred(&min_stat, &port->gss->cred);
    1045                 :     }
    1046 GIC           4 :     return pg_GSS_checkauth(port);
    1047                 : }
    1048                 : 
    1049                 : /*
    1050                 :  * Check whether the GSSAPI-authenticated user is allowed to connect as the
    1051                 :  * claimed username.
    1052 ECB             :  */
    1053                 : static int
    1054 GIC          19 : pg_GSS_checkauth(Port *port)
    1055                 : {
    1056                 :     int         ret;
    1057                 :     OM_uint32   maj_stat,
    1058                 :                 min_stat,
    1059                 :                 lmin_s;
    1060                 :     gss_buffer_desc gbuf;
    1061                 :     char       *princ;
    1062                 : 
    1063                 :     /*
    1064                 :      * Get the name of the user that authenticated, and compare it to the pg
    1065 ECB             :      * username that was specified for the connection.
    1066                 :      */
    1067 GIC          19 :     maj_stat = gss_display_name(&min_stat, port->gss->name, &gbuf, NULL);
    1068 GBC          19 :     if (maj_stat != GSS_S_COMPLETE)
    1069                 :     {
    1070 UBC           0 :         pg_GSS_error(_("retrieving GSS user name failed"),
    1071                 :                      maj_stat, min_stat);
    1072 UIC           0 :         return STATUS_ERROR;
    1073                 :     }
    1074                 : 
    1075                 :     /*
    1076                 :      * gbuf.value might not be null-terminated, so turn it into a regular
    1077 ECB             :      * null-terminated string.
    1078                 :      */
    1079 CBC          19 :     princ = palloc(gbuf.length + 1);
    1080              19 :     memcpy(princ, gbuf.value, gbuf.length);
    1081 GIC          19 :     princ[gbuf.length] = '\0';
    1082              19 :     gss_release_buffer(&lmin_s, &gbuf);
    1083                 : 
    1084                 :     /*
    1085                 :      * Copy the original name of the authenticated principal into our backend
    1086                 :      * memory for display later.
    1087                 :      *
    1088                 :      * This is also our authenticated identity.  Set it now, rather than
    1089                 :      * waiting for the usermap check below, because authentication has already
    1090 ECB             :      * succeeded and we want the log file to reflect that.
    1091                 :      */
    1092 GIC          19 :     port->gss->princ = MemoryContextStrdup(TopMemoryContext, princ);
    1093              19 :     set_authn_id(port, princ);
    1094                 : 
    1095                 :     /*
    1096 ECB             :      * Split the username at the realm separator
    1097                 :      */
    1098 CBC          19 :     if (strchr(princ, '@'))
    1099                 :     {
    1100 GIC          19 :         char       *cp = strchr(princ, '@');
    1101                 : 
    1102                 :         /*
    1103                 :          * If we are not going to include the realm in the username that is
    1104                 :          * passed to the ident map, destructively modify it here to remove the
    1105 ECB             :          * realm. Then advance past the separator to check the realm.
    1106                 :          */
    1107 CBC          19 :         if (!port->hba->include_realm)
    1108 GIC           1 :             *cp = '\0';
    1109 CBC          19 :         cp++;
    1110                 : 
    1111 GIC          19 :         if (port->hba->krb_realm != NULL && strlen(port->hba->krb_realm))
    1112                 :         {
    1113                 :             /*
    1114 EUB             :              * Match the realm part of the name first
    1115                 :              */
    1116 UIC           0 :             if (pg_krb_caseins_users)
    1117 UBC           0 :                 ret = pg_strcasecmp(port->hba->krb_realm, cp);
    1118                 :             else
    1119               0 :                 ret = strcmp(port->hba->krb_realm, cp);
    1120                 : 
    1121 UIC           0 :             if (ret)
    1122 EUB             :             {
    1123                 :                 /* GSS realm does not match */
    1124 UIC           0 :                 elog(DEBUG2,
    1125 EUB             :                      "GSSAPI realm (%s) and configured realm (%s) don't match",
    1126                 :                      cp, port->hba->krb_realm);
    1127 UIC           0 :                 pfree(princ);
    1128               0 :                 return STATUS_ERROR;
    1129                 :             }
    1130 EUB             :         }
    1131                 :     }
    1132 UBC           0 :     else if (port->hba->krb_realm && strlen(port->hba->krb_realm))
    1133                 :     {
    1134               0 :         elog(DEBUG2,
    1135 EUB             :              "GSSAPI did not return realm but realm matching was requested");
    1136 UIC           0 :         pfree(princ);
    1137               0 :         return STATUS_ERROR;
    1138 ECB             :     }
    1139                 : 
    1140 GIC          19 :     ret = check_usermap(port->hba->usermap, port->user_name, princ,
    1141 ECB             :                         pg_krb_caseins_users);
    1142                 : 
    1143 CBC          19 :     pfree(princ);
    1144                 : 
    1145 GIC          19 :     return ret;
    1146                 : }
    1147                 : #endif                          /* ENABLE_GSS */
    1148                 : 
    1149                 : 
    1150                 : /*----------------------------------------------------------------
    1151                 :  * SSPI authentication system
    1152                 :  *----------------------------------------------------------------
    1153                 :  */
    1154                 : #ifdef ENABLE_SSPI
    1155                 : 
    1156                 : /*
    1157                 :  * Generate an error for SSPI authentication.  The caller should apply
    1158                 :  * _() to errmsg to make it translatable.
    1159                 :  */
    1160                 : static void
    1161                 : pg_SSPI_error(int severity, const char *errmsg, SECURITY_STATUS r)
    1162                 : {
    1163                 :     char        sysmsg[256];
    1164                 : 
    1165                 :     if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS |
    1166                 :                       FORMAT_MESSAGE_FROM_SYSTEM,
    1167                 :                       NULL, r, 0,
    1168                 :                       sysmsg, sizeof(sysmsg), NULL) == 0)
    1169                 :         ereport(severity,
    1170                 :                 (errmsg_internal("%s", errmsg),
    1171                 :                  errdetail_internal("SSPI error %x", (unsigned int) r)));
    1172                 :     else
    1173                 :         ereport(severity,
    1174                 :                 (errmsg_internal("%s", errmsg),
    1175                 :                  errdetail_internal("%s (%x)", sysmsg, (unsigned int) r)));
    1176                 : }
    1177                 : 
    1178                 : static int
    1179                 : pg_SSPI_recvauth(Port *port)
    1180                 : {
    1181                 :     int         mtype;
    1182                 :     StringInfoData buf;
    1183                 :     SECURITY_STATUS r;
    1184                 :     CredHandle  sspicred;
    1185                 :     CtxtHandle *sspictx = NULL,
    1186                 :                 newctx;
    1187                 :     TimeStamp   expiry;
    1188                 :     ULONG       contextattr;
    1189                 :     SecBufferDesc inbuf;
    1190                 :     SecBufferDesc outbuf;
    1191                 :     SecBuffer   OutBuffers[1];
    1192                 :     SecBuffer   InBuffers[1];
    1193                 :     HANDLE      token;
    1194                 :     TOKEN_USER *tokenuser;
    1195                 :     DWORD       retlen;
    1196                 :     char        accountname[MAXPGPATH];
    1197                 :     char        domainname[MAXPGPATH];
    1198                 :     DWORD       accountnamesize = sizeof(accountname);
    1199                 :     DWORD       domainnamesize = sizeof(domainname);
    1200                 :     SID_NAME_USE accountnameuse;
    1201                 :     char       *authn_id;
    1202                 : 
    1203                 :     /*
    1204                 :      * Acquire a handle to the server credentials.
    1205                 :      */
    1206                 :     r = AcquireCredentialsHandle(NULL,
    1207                 :                                  "negotiate",
    1208                 :                                  SECPKG_CRED_INBOUND,
    1209                 :                                  NULL,
    1210                 :                                  NULL,
    1211                 :                                  NULL,
    1212                 :                                  NULL,
    1213                 :                                  &sspicred,
    1214                 :                                  &expiry);
    1215                 :     if (r != SEC_E_OK)
    1216                 :         pg_SSPI_error(ERROR, _("could not acquire SSPI credentials"), r);
    1217                 : 
    1218                 :     /*
    1219                 :      * Loop through SSPI message exchange. This exchange can consist of
    1220                 :      * multiple messages sent in both directions. First message is always from
    1221                 :      * the client. All messages from client to server are password packets
    1222                 :      * (type 'p').
    1223                 :      */
    1224                 :     do
    1225                 :     {
    1226                 :         pq_startmsgread();
    1227                 :         mtype = pq_getbyte();
    1228                 :         if (mtype != 'p')
    1229                 :         {
    1230                 :             if (sspictx != NULL)
    1231                 :             {
    1232                 :                 DeleteSecurityContext(sspictx);
    1233                 :                 free(sspictx);
    1234                 :             }
    1235                 :             FreeCredentialsHandle(&sspicred);
    1236                 : 
    1237                 :             /* Only log error if client didn't disconnect. */
    1238                 :             if (mtype != EOF)
    1239                 :                 ereport(ERROR,
    1240                 :                         (errcode(ERRCODE_PROTOCOL_VIOLATION),
    1241                 :                          errmsg("expected SSPI response, got message type %d",
    1242                 :                                 mtype)));
    1243                 :             return STATUS_ERROR;
    1244                 :         }
    1245                 : 
    1246                 :         /* Get the actual SSPI token */
    1247                 :         initStringInfo(&buf);
    1248                 :         if (pq_getmessage(&buf, PG_MAX_AUTH_TOKEN_LENGTH))
    1249                 :         {
    1250                 :             /* EOF - pq_getmessage already logged error */
    1251                 :             pfree(buf.data);
    1252                 :             if (sspictx != NULL)
    1253                 :             {
    1254                 :                 DeleteSecurityContext(sspictx);
    1255                 :                 free(sspictx);
    1256                 :             }
    1257                 :             FreeCredentialsHandle(&sspicred);
    1258                 :             return STATUS_ERROR;
    1259                 :         }
    1260                 : 
    1261                 :         /* Map to SSPI style buffer */
    1262                 :         inbuf.ulVersion = SECBUFFER_VERSION;
    1263                 :         inbuf.cBuffers = 1;
    1264                 :         inbuf.pBuffers = InBuffers;
    1265                 :         InBuffers[0].pvBuffer = buf.data;
    1266                 :         InBuffers[0].cbBuffer = buf.len;
    1267                 :         InBuffers[0].BufferType = SECBUFFER_TOKEN;
    1268                 : 
    1269                 :         /* Prepare output buffer */
    1270                 :         OutBuffers[0].pvBuffer = NULL;
    1271                 :         OutBuffers[0].BufferType = SECBUFFER_TOKEN;
    1272                 :         OutBuffers[0].cbBuffer = 0;
    1273                 :         outbuf.cBuffers = 1;
    1274                 :         outbuf.pBuffers = OutBuffers;
    1275                 :         outbuf.ulVersion = SECBUFFER_VERSION;
    1276                 : 
    1277                 :         elog(DEBUG4, "processing received SSPI token of length %u",
    1278                 :              (unsigned int) buf.len);
    1279                 : 
    1280                 :         r = AcceptSecurityContext(&sspicred,
    1281                 :                                   sspictx,
    1282                 :                                   &inbuf,
    1283                 :                                   ASC_REQ_ALLOCATE_MEMORY,
    1284                 :                                   SECURITY_NETWORK_DREP,
    1285                 :                                   &newctx,
    1286                 :                                   &outbuf,
    1287                 :                                   &contextattr,
    1288                 :                                   NULL);
    1289                 : 
    1290                 :         /* input buffer no longer used */
    1291                 :         pfree(buf.data);
    1292                 : 
    1293                 :         if (outbuf.cBuffers > 0 && outbuf.pBuffers[0].cbBuffer > 0)
    1294                 :         {
    1295                 :             /*
    1296                 :              * Negotiation generated data to be sent to the client.
    1297                 :              */
    1298                 :             elog(DEBUG4, "sending SSPI response token of length %u",
    1299                 :                  (unsigned int) outbuf.pBuffers[0].cbBuffer);
    1300                 : 
    1301                 :             port->gss->outbuf.length = outbuf.pBuffers[0].cbBuffer;
    1302                 :             port->gss->outbuf.value = outbuf.pBuffers[0].pvBuffer;
    1303                 : 
    1304                 :             sendAuthRequest(port, AUTH_REQ_GSS_CONT,
    1305                 :                             port->gss->outbuf.value, port->gss->outbuf.length);
    1306                 : 
    1307                 :             FreeContextBuffer(outbuf.pBuffers[0].pvBuffer);
    1308                 :         }
    1309                 : 
    1310                 :         if (r != SEC_E_OK && r != SEC_I_CONTINUE_NEEDED)
    1311                 :         {
    1312                 :             if (sspictx != NULL)
    1313                 :             {
    1314                 :                 DeleteSecurityContext(sspictx);
    1315                 :                 free(sspictx);
    1316                 :             }
    1317                 :             FreeCredentialsHandle(&sspicred);
    1318                 :             pg_SSPI_error(ERROR,
    1319                 :                           _("could not accept SSPI security context"), r);
    1320                 :         }
    1321                 : 
    1322                 :         /*
    1323                 :          * Overwrite the current context with the one we just received. If
    1324                 :          * sspictx is NULL it was the first loop and we need to allocate a
    1325                 :          * buffer for it. On subsequent runs, we can just overwrite the buffer
    1326                 :          * contents since the size does not change.
    1327                 :          */
    1328                 :         if (sspictx == NULL)
    1329                 :         {
    1330                 :             sspictx = malloc(sizeof(CtxtHandle));
    1331                 :             if (sspictx == NULL)
    1332                 :                 ereport(ERROR,
    1333                 :                         (errmsg("out of memory")));
    1334                 :         }
    1335                 : 
    1336                 :         memcpy(sspictx, &newctx, sizeof(CtxtHandle));
    1337                 : 
    1338                 :         if (r == SEC_I_CONTINUE_NEEDED)
    1339                 :             elog(DEBUG4, "SSPI continue needed");
    1340                 : 
    1341                 :     } while (r == SEC_I_CONTINUE_NEEDED);
    1342                 : 
    1343                 : 
    1344                 :     /*
    1345                 :      * Release service principal credentials
    1346                 :      */
    1347                 :     FreeCredentialsHandle(&sspicred);
    1348                 : 
    1349                 : 
    1350                 :     /*
    1351                 :      * SEC_E_OK indicates that authentication is now complete.
    1352                 :      *
    1353                 :      * Get the name of the user that authenticated, and compare it to the pg
    1354                 :      * username that was specified for the connection.
    1355                 :      */
    1356                 : 
    1357                 :     r = QuerySecurityContextToken(sspictx, &token);
    1358                 :     if (r != SEC_E_OK)
    1359                 :         pg_SSPI_error(ERROR,
    1360                 :                       _("could not get token from SSPI security context"), r);
    1361                 : 
    1362                 :     /*
    1363                 :      * No longer need the security context, everything from here on uses the
    1364                 :      * token instead.
    1365                 :      */
    1366                 :     DeleteSecurityContext(sspictx);
    1367                 :     free(sspictx);
    1368                 : 
    1369                 :     if (!GetTokenInformation(token, TokenUser, NULL, 0, &retlen) && GetLastError() != 122)
    1370                 :         ereport(ERROR,
    1371                 :                 (errmsg_internal("could not get token information buffer size: error code %lu",
    1372                 :                                  GetLastError())));
    1373                 : 
    1374                 :     tokenuser = malloc(retlen);
    1375                 :     if (tokenuser == NULL)
    1376                 :         ereport(ERROR,
    1377                 :                 (errmsg("out of memory")));
    1378                 : 
    1379                 :     if (!GetTokenInformation(token, TokenUser, tokenuser, retlen, &retlen))
    1380                 :         ereport(ERROR,
    1381                 :                 (errmsg_internal("could not get token information: error code %lu",
    1382                 :                                  GetLastError())));
    1383                 : 
    1384                 :     CloseHandle(token);
    1385                 : 
    1386                 :     if (!LookupAccountSid(NULL, tokenuser->User.Sid, accountname, &accountnamesize,
    1387                 :                           domainname, &domainnamesize, &accountnameuse))
    1388                 :         ereport(ERROR,
    1389                 :                 (errmsg_internal("could not look up account SID: error code %lu",
    1390                 :                                  GetLastError())));
    1391                 : 
    1392                 :     free(tokenuser);
    1393                 : 
    1394                 :     if (!port->hba->compat_realm)
    1395                 :     {
    1396                 :         int         status = pg_SSPI_make_upn(accountname, sizeof(accountname),
    1397                 :                                               domainname, sizeof(domainname),
    1398                 :                                               port->hba->upn_username);
    1399                 : 
    1400                 :         if (status != STATUS_OK)
    1401                 :             /* Error already reported from pg_SSPI_make_upn */
    1402                 :             return status;
    1403                 :     }
    1404                 : 
    1405                 :     /*
    1406                 :      * We have all of the information necessary to construct the authenticated
    1407                 :      * identity.  Set it now, rather than waiting for check_usermap below,
    1408                 :      * because authentication has already succeeded and we want the log file
    1409                 :      * to reflect that.
    1410                 :      */
    1411                 :     if (port->hba->compat_realm)
    1412                 :     {
    1413                 :         /* SAM-compatible format. */
    1414                 :         authn_id = psprintf("%s\\%s", domainname, accountname);
    1415                 :     }
    1416                 :     else
    1417                 :     {
    1418                 :         /* Kerberos principal format. */
    1419                 :         authn_id = psprintf("%s@%s", accountname, domainname);
    1420                 :     }
    1421                 : 
    1422                 :     set_authn_id(port, authn_id);
    1423                 :     pfree(authn_id);
    1424                 : 
    1425                 :     /*
    1426                 :      * Compare realm/domain if requested. In SSPI, always compare case
    1427                 :      * insensitive.
    1428                 :      */
    1429                 :     if (port->hba->krb_realm && strlen(port->hba->krb_realm))
    1430                 :     {
    1431                 :         if (pg_strcasecmp(port->hba->krb_realm, domainname) != 0)
    1432                 :         {
    1433                 :             elog(DEBUG2,
    1434                 :                  "SSPI domain (%s) and configured domain (%s) don't match",
    1435                 :                  domainname, port->hba->krb_realm);
    1436                 : 
    1437                 :             return STATUS_ERROR;
    1438                 :         }
    1439                 :     }
    1440                 : 
    1441                 :     /*
    1442                 :      * We have the username (without domain/realm) in accountname, compare to
    1443                 :      * the supplied value. In SSPI, always compare case insensitive.
    1444                 :      *
    1445                 :      * If set to include realm, append it in <username>@<realm> format.
    1446                 :      */
    1447                 :     if (port->hba->include_realm)
    1448                 :     {
    1449                 :         char       *namebuf;
    1450                 :         int         retval;
    1451                 : 
    1452                 :         namebuf = psprintf("%s@%s", accountname, domainname);
    1453                 :         retval = check_usermap(port->hba->usermap, port->user_name, namebuf, true);
    1454                 :         pfree(namebuf);
    1455                 :         return retval;
    1456                 :     }
    1457                 :     else
    1458                 :         return check_usermap(port->hba->usermap, port->user_name, accountname, true);
    1459                 : }
    1460                 : 
    1461                 : /*
    1462                 :  * Replaces the domainname with the Kerberos realm name,
    1463                 :  * and optionally the accountname with the Kerberos user name.
    1464                 :  */
    1465                 : static int
    1466                 : pg_SSPI_make_upn(char *accountname,
    1467                 :                  size_t accountnamesize,
    1468                 :                  char *domainname,
    1469                 :                  size_t domainnamesize,
    1470                 :                  bool update_accountname)
    1471                 : {
    1472                 :     char       *samname;
    1473                 :     char       *upname = NULL;
    1474                 :     char       *p = NULL;
    1475                 :     ULONG       upnamesize = 0;
    1476                 :     size_t      upnamerealmsize;
    1477                 :     BOOLEAN     res;
    1478                 : 
    1479                 :     /*
    1480                 :      * Build SAM name (DOMAIN\user), then translate to UPN
    1481                 :      * (user@kerberos.realm). The realm name is returned in lower case, but
    1482                 :      * that is fine because in SSPI auth, string comparisons are always
    1483                 :      * case-insensitive.
    1484                 :      */
    1485                 : 
    1486                 :     samname = psprintf("%s\\%s", domainname, accountname);
    1487                 :     res = TranslateName(samname, NameSamCompatible, NameUserPrincipal,
    1488                 :                         NULL, &upnamesize);
    1489                 : 
    1490                 :     if ((!res && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
    1491                 :         || upnamesize == 0)
    1492                 :     {
    1493                 :         pfree(samname);
    1494                 :         ereport(LOG,
    1495                 :                 (errcode(ERRCODE_INVALID_ROLE_SPECIFICATION),
    1496                 :                  errmsg("could not translate name")));
    1497                 :         return STATUS_ERROR;
    1498                 :     }
    1499                 : 
    1500                 :     /* upnamesize includes the terminating NUL. */
    1501                 :     upname = palloc(upnamesize);
    1502                 : 
    1503                 :     res = TranslateName(samname, NameSamCompatible, NameUserPrincipal,
    1504                 :                         upname, &upnamesize);
    1505                 : 
    1506                 :     pfree(samname);
    1507                 :     if (res)
    1508                 :         p = strchr(upname, '@');
    1509                 : 
    1510                 :     if (!res || p == NULL)
    1511                 :     {
    1512                 :         pfree(upname);
    1513                 :         ereport(LOG,
    1514                 :                 (errcode(ERRCODE_INVALID_ROLE_SPECIFICATION),
    1515                 :                  errmsg("could not translate name")));
    1516                 :         return STATUS_ERROR;
    1517                 :     }
    1518                 : 
    1519                 :     /* Length of realm name after the '@', including the NUL. */
    1520                 :     upnamerealmsize = upnamesize - (p - upname + 1);
    1521                 : 
    1522                 :     /* Replace domainname with realm name. */
    1523                 :     if (upnamerealmsize > domainnamesize)
    1524                 :     {
    1525                 :         pfree(upname);
    1526                 :         ereport(LOG,
    1527                 :                 (errcode(ERRCODE_INVALID_ROLE_SPECIFICATION),
    1528                 :                  errmsg("realm name too long")));
    1529                 :         return STATUS_ERROR;
    1530                 :     }
    1531                 : 
    1532                 :     /* Length is now safe. */
    1533                 :     strcpy(domainname, p + 1);
    1534                 : 
    1535                 :     /* Replace account name as well (in case UPN != SAM)? */
    1536                 :     if (update_accountname)
    1537                 :     {
    1538                 :         if ((p - upname + 1) > accountnamesize)
    1539                 :         {
    1540                 :             pfree(upname);
    1541 EUB             :             ereport(LOG,
    1542                 :                     (errcode(ERRCODE_INVALID_ROLE_SPECIFICATION),
    1543                 :                      errmsg("translated account name too long")));
    1544                 :             return STATUS_ERROR;
    1545                 :         }
    1546                 : 
    1547                 :         *p = 0;
    1548                 :         strcpy(accountname, upname);
    1549                 :     }
    1550                 : 
    1551                 :     pfree(upname);
    1552                 :     return STATUS_OK;
    1553                 : }
    1554                 : #endif                          /* ENABLE_SSPI */
    1555                 : 
    1556                 : 
    1557                 : 
    1558                 : /*----------------------------------------------------------------
    1559                 :  * Ident authentication system
    1560                 :  *----------------------------------------------------------------
    1561                 :  */
    1562                 : 
    1563                 : /*
    1564                 :  *  Parse the string "*ident_response" as a response from a query to an Ident
    1565                 :  *  server.  If it's a normal response indicating a user name, return true
    1566                 :  *  and store the user name at *ident_user. If it's anything else,
    1567                 :  *  return false.
    1568                 :  */
    1569                 : static bool
    1570 UBC           0 : interpret_ident_response(const char *ident_response,
    1571                 :                          char *ident_user)
    1572 EUB             : {
    1573 UBC           0 :     const char *cursor = ident_response;    /* Cursor into *ident_response */
    1574 EUB             : 
    1575                 :     /*
    1576                 :      * Ident's response, in the telnet tradition, should end in crlf (\r\n).
    1577                 :      */
    1578 UIC           0 :     if (strlen(ident_response) < 2)
    1579               0 :         return false;
    1580               0 :     else if (ident_response[strlen(ident_response) - 2] != '\r')
    1581               0 :         return false;
    1582                 :     else
    1583                 :     {
    1584 UBC           0 :         while (*cursor != ':' && *cursor != '\r')
    1585               0 :             cursor++;           /* skip port field */
    1586                 : 
    1587 UIC           0 :         if (*cursor != ':')
    1588 UBC           0 :             return false;
    1589                 :         else
    1590 EUB             :         {
    1591                 :             /* We're positioned to colon before response type field */
    1592                 :             char        response_type[80];
    1593                 :             int         i;      /* Index into *response_type */
    1594                 : 
    1595 UIC           0 :             cursor++;           /* Go over colon */
    1596 UBC           0 :             while (pg_isblank(*cursor))
    1597               0 :                 cursor++;       /* skip blanks */
    1598               0 :             i = 0;
    1599 UIC           0 :             while (*cursor != ':' && *cursor != '\r' && !pg_isblank(*cursor) &&
    1600 EUB             :                    i < (int) (sizeof(response_type) - 1))
    1601 UBC           0 :                 response_type[i++] = *cursor++;
    1602               0 :             response_type[i] = '\0';
    1603               0 :             while (pg_isblank(*cursor))
    1604               0 :                 cursor++;       /* skip blanks */
    1605 UIC           0 :             if (strcmp(response_type, "USERID") != 0)
    1606               0 :                 return false;
    1607                 :             else
    1608                 :             {
    1609                 :                 /*
    1610                 :                  * It's a USERID response.  Good.  "cursor" should be pointing
    1611                 :                  * to the colon that precedes the operating system type.
    1612                 :                  */
    1613               0 :                 if (*cursor != ':')
    1614               0 :                     return false;
    1615                 :                 else
    1616                 :                 {
    1617               0 :                     cursor++;   /* Go over colon */
    1618                 :                     /* Skip over operating system field. */
    1619               0 :                     while (*cursor != ':' && *cursor != '\r')
    1620               0 :                         cursor++;
    1621               0 :                     if (*cursor != ':')
    1622 UBC           0 :                         return false;
    1623                 :                     else
    1624 EUB             :                     {
    1625 UBC           0 :                         cursor++;   /* Go over colon */
    1626 UIC           0 :                         while (pg_isblank(*cursor))
    1627               0 :                             cursor++;   /* skip blanks */
    1628                 :                         /* Rest of line is user name.  Copy it over. */
    1629               0 :                         i = 0;
    1630               0 :                         while (*cursor != '\r' && i < IDENT_USERNAME_MAX)
    1631               0 :                             ident_user[i++] = *cursor++;
    1632               0 :                         ident_user[i] = '\0';
    1633               0 :                         return true;
    1634                 :                     }
    1635 EUB             :                 }
    1636                 :             }
    1637                 :         }
    1638                 :     }
    1639                 : }
    1640                 : 
    1641                 : 
    1642                 : /*
    1643                 :  *  Talk to the ident server on "remote_addr" and find out who
    1644                 :  *  owns the tcp connection to "local_addr"
    1645                 :  *  If the username is successfully retrieved, check the usermap.
    1646                 :  *
    1647                 :  *  XXX: Using WaitLatchOrSocket() and doing a CHECK_FOR_INTERRUPTS() if the
    1648                 :  *  latch was set would improve the responsiveness to timeouts/cancellations.
    1649                 :  */
    1650                 : static int
    1651 UIC           0 : ident_inet(hbaPort *port)
    1652 EUB             : {
    1653 UBC           0 :     const SockAddr remote_addr = port->raddr;
    1654               0 :     const SockAddr local_addr = port->laddr;
    1655 EUB             :     char        ident_user[IDENT_USERNAME_MAX + 1];
    1656 UBC           0 :     pgsocket    sock_fd = PGINVALID_SOCKET; /* for talking to Ident server */
    1657 EUB             :     int         rc;             /* Return code from a locally called function */
    1658                 :     bool        ident_return;
    1659                 :     char        remote_addr_s[NI_MAXHOST];
    1660                 :     char        remote_port[NI_MAXSERV];
    1661                 :     char        local_addr_s[NI_MAXHOST];
    1662                 :     char        local_port[NI_MAXSERV];
    1663                 :     char        ident_port[NI_MAXSERV];
    1664                 :     char        ident_query[80];
    1665                 :     char        ident_response[80 + IDENT_USERNAME_MAX];
    1666 UBC           0 :     struct addrinfo *ident_serv = NULL,
    1667 UIC           0 :                *la = NULL,
    1668                 :                 hints;
    1669 EUB             : 
    1670                 :     /*
    1671                 :      * Might look a little weird to first convert it to text and then back to
    1672                 :      * sockaddr, but it's protocol independent.
    1673                 :      */
    1674 UBC           0 :     pg_getnameinfo_all(&remote_addr.addr, remote_addr.salen,
    1675 EUB             :                        remote_addr_s, sizeof(remote_addr_s),
    1676                 :                        remote_port, sizeof(remote_port),
    1677                 :                        NI_NUMERICHOST | NI_NUMERICSERV);
    1678 UBC           0 :     pg_getnameinfo_all(&local_addr.addr, local_addr.salen,
    1679                 :                        local_addr_s, sizeof(local_addr_s),
    1680                 :                        local_port, sizeof(local_port),
    1681 EUB             :                        NI_NUMERICHOST | NI_NUMERICSERV);
    1682                 : 
    1683 UIC           0 :     snprintf(ident_port, sizeof(ident_port), "%d", IDENT_PORT);
    1684               0 :     hints.ai_flags = AI_NUMERICHOST;
    1685 UBC           0 :     hints.ai_family = remote_addr.addr.ss_family;
    1686               0 :     hints.ai_socktype = SOCK_STREAM;
    1687               0 :     hints.ai_protocol = 0;
    1688 UIC           0 :     hints.ai_addrlen = 0;
    1689 UBC           0 :     hints.ai_canonname = NULL;
    1690 UIC           0 :     hints.ai_addr = NULL;
    1691               0 :     hints.ai_next = NULL;
    1692 UBC           0 :     rc = pg_getaddrinfo_all(remote_addr_s, ident_port, &hints, &ident_serv);
    1693               0 :     if (rc || !ident_serv)
    1694                 :     {
    1695                 :         /* we don't expect this to happen */
    1696 UIC           0 :         ident_return = false;
    1697               0 :         goto ident_inet_done;
    1698                 :     }
    1699                 : 
    1700               0 :     hints.ai_flags = AI_NUMERICHOST;
    1701 UBC           0 :     hints.ai_family = local_addr.addr.ss_family;
    1702               0 :     hints.ai_socktype = SOCK_STREAM;
    1703 UIC           0 :     hints.ai_protocol = 0;
    1704 UBC           0 :     hints.ai_addrlen = 0;
    1705 UIC           0 :     hints.ai_canonname = NULL;
    1706               0 :     hints.ai_addr = NULL;
    1707               0 :     hints.ai_next = NULL;
    1708 UBC           0 :     rc = pg_getaddrinfo_all(local_addr_s, NULL, &hints, &la);
    1709               0 :     if (rc || !la)
    1710                 :     {
    1711                 :         /* we don't expect this to happen */
    1712               0 :         ident_return = false;
    1713               0 :         goto ident_inet_done;
    1714 EUB             :     }
    1715                 : 
    1716 UBC           0 :     sock_fd = socket(ident_serv->ai_family, ident_serv->ai_socktype,
    1717 UIC           0 :                      ident_serv->ai_protocol);
    1718               0 :     if (sock_fd == PGINVALID_SOCKET)
    1719                 :     {
    1720 UBC           0 :         ereport(LOG,
    1721 EUB             :                 (errcode_for_socket_access(),
    1722                 :                  errmsg("could not create socket for Ident connection: %m")));
    1723 UIC           0 :         ident_return = false;
    1724               0 :         goto ident_inet_done;
    1725 EUB             :     }
    1726                 : 
    1727                 :     /*
    1728                 :      * Bind to the address which the client originally contacted, otherwise
    1729                 :      * the ident server won't be able to match up the right connection. This
    1730                 :      * is necessary if the PostgreSQL server is running on an IP alias.
    1731                 :      */
    1732 UIC           0 :     rc = bind(sock_fd, la->ai_addr, la->ai_addrlen);
    1733 UBC           0 :     if (rc != 0)
    1734 EUB             :     {
    1735 UIC           0 :         ereport(LOG,
    1736 EUB             :                 (errcode_for_socket_access(),
    1737                 :                  errmsg("could not bind to local address \"%s\": %m",
    1738                 :                         local_addr_s)));
    1739 UIC           0 :         ident_return = false;
    1740               0 :         goto ident_inet_done;
    1741                 :     }
    1742 EUB             : 
    1743 UBC           0 :     rc = connect(sock_fd, ident_serv->ai_addr,
    1744 UIC           0 :                  ident_serv->ai_addrlen);
    1745               0 :     if (rc != 0)
    1746                 :     {
    1747               0 :         ereport(LOG,
    1748 EUB             :                 (errcode_for_socket_access(),
    1749                 :                  errmsg("could not connect to Ident server at address \"%s\", port %s: %m",
    1750                 :                         remote_addr_s, ident_port)));
    1751 UBC           0 :         ident_return = false;
    1752 UIC           0 :         goto ident_inet_done;
    1753 EUB             :     }
    1754                 : 
    1755                 :     /* The query we send to the Ident server */
    1756 UIC           0 :     snprintf(ident_query, sizeof(ident_query), "%s,%s\r\n",
    1757                 :              remote_port, local_port);
    1758                 : 
    1759 EUB             :     /* loop in case send is interrupted */
    1760                 :     do
    1761                 :     {
    1762 UIC           0 :         CHECK_FOR_INTERRUPTS();
    1763 EUB             : 
    1764 UBC           0 :         rc = send(sock_fd, ident_query, strlen(ident_query), 0);
    1765               0 :     } while (rc < 0 && errno == EINTR);
    1766 EUB             : 
    1767 UIC           0 :     if (rc < 0)
    1768                 :     {
    1769               0 :         ereport(LOG,
    1770 EUB             :                 (errcode_for_socket_access(),
    1771                 :                  errmsg("could not send query to Ident server at address \"%s\", port %s: %m",
    1772                 :                         remote_addr_s, ident_port)));
    1773 UBC           0 :         ident_return = false;
    1774               0 :         goto ident_inet_done;
    1775 EUB             :     }
    1776                 : 
    1777                 :     do
    1778                 :     {
    1779 UIC           0 :         CHECK_FOR_INTERRUPTS();
    1780                 : 
    1781               0 :         rc = recv(sock_fd, ident_response, sizeof(ident_response) - 1, 0);
    1782               0 :     } while (rc < 0 && errno == EINTR);
    1783                 : 
    1784               0 :     if (rc < 0)
    1785 EUB             :     {
    1786 UBC           0 :         ereport(LOG,
    1787                 :                 (errcode_for_socket_access(),
    1788 EUB             :                  errmsg("could not receive response from Ident server at address \"%s\", port %s: %m",
    1789                 :                         remote_addr_s, ident_port)));
    1790 UIC           0 :         ident_return = false;
    1791               0 :         goto ident_inet_done;
    1792                 :     }
    1793                 : 
    1794               0 :     ident_response[rc] = '\0';
    1795               0 :     ident_return = interpret_ident_response(ident_response, ident_user);
    1796               0 :     if (!ident_return)
    1797               0 :         ereport(LOG,
    1798                 :                 (errmsg("invalidly formatted response from Ident server: \"%s\"",
    1799                 :                         ident_response)));
    1800                 : 
    1801               0 : ident_inet_done:
    1802               0 :     if (sock_fd != PGINVALID_SOCKET)
    1803               0 :         closesocket(sock_fd);
    1804               0 :     if (ident_serv)
    1805 LBC           0 :         pg_freeaddrinfo_all(remote_addr.addr.ss_family, ident_serv);
    1806 UIC           0 :     if (la)
    1807               0 :         pg_freeaddrinfo_all(local_addr.addr.ss_family, la);
    1808                 : 
    1809               0 :     if (ident_return)
    1810                 :     {
    1811                 :         /*
    1812                 :          * Success!  Store the identity, then check the usermap. Note that
    1813                 :          * setting the authenticated identity is done before checking the
    1814 ECB             :          * usermap, because at this point authentication has succeeded.
    1815                 :          */
    1816 UIC           0 :         set_authn_id(port, ident_user);
    1817 UBC           0 :         return check_usermap(port->hba->usermap, port->user_name, ident_user, false);
    1818 EUB             :     }
    1819 UIC           0 :     return STATUS_ERROR;
    1820                 : }
    1821                 : 
    1822 EUB             : 
    1823                 : /*----------------------------------------------------------------
    1824                 :  * Peer authentication system
    1825                 :  *----------------------------------------------------------------
    1826                 :  */
    1827                 : 
    1828                 : /*
    1829 ECB             :  *  Ask kernel about the credentials of the connecting process,
    1830                 :  *  determine the symbolic name of the corresponding user, and check
    1831                 :  *  if valid per the usermap.
    1832                 :  *
    1833 EUB             :  *  Iff authorized, return STATUS_OK, otherwise return STATUS_ERROR.
    1834                 :  */
    1835                 : static int
    1836 GIC          26 : auth_peer(hbaPort *port)
    1837                 : {
    1838                 :     uid_t       uid;
    1839 EUB             :     gid_t       gid;
    1840                 : #ifndef WIN32
    1841                 :     struct passwd *pw;
    1842                 :     int         ret;
    1843                 : #endif
    1844                 : 
    1845 GIC          26 :     if (getpeereid(port->sock, &uid, &gid) != 0)
    1846                 :     {
    1847 ECB             :         /* Provide special error message if getpeereid is a stub */
    1848 UIC           0 :         if (errno == ENOSYS)
    1849 LBC           0 :             ereport(LOG,
    1850                 :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    1851                 :                      errmsg("peer authentication is not supported on this platform")));
    1852 ECB             :         else
    1853 UIC           0 :             ereport(LOG,
    1854                 :                     (errcode_for_socket_access(),
    1855                 :                      errmsg("could not get peer credentials: %m")));
    1856               0 :         return STATUS_ERROR;
    1857                 :     }
    1858                 : 
    1859                 : #ifndef WIN32
    1860 GIC          26 :     errno = 0;                  /* clear errno before call */
    1861              26 :     pw = getpwuid(uid);
    1862              26 :     if (!pw)
    1863                 :     {
    1864 UIC           0 :         int         save_errno = errno;
    1865                 : 
    1866               0 :         ereport(LOG,
    1867                 :                 (errmsg("could not look up local user ID %ld: %s",
    1868                 :                         (long) uid,
    1869                 :                         save_errno ? strerror(save_errno) : _("user does not exist"))));
    1870               0 :         return STATUS_ERROR;
    1871                 :     }
    1872 EUB             : 
    1873                 :     /*
    1874                 :      * Make a copy of static getpw*() result area; this is our authenticated
    1875                 :      * identity.  Set it before calling check_usermap, because authentication
    1876                 :      * has already succeeded and we want the log file to reflect that.
    1877                 :      */
    1878 GIC          26 :     set_authn_id(port, pw->pw_name);
    1879 EUB             : 
    1880 GNC          26 :     ret = check_usermap(port->hba->usermap, port->user_name,
    1881                 :                         MyClientConnectionInfo.authn_id, false);
    1882                 : 
    1883 GIC          26 :     return ret;
    1884                 : #else
    1885                 :     /* should have failed with ENOSYS above */
    1886                 :     Assert(false);
    1887                 :     return STATUS_ERROR;
    1888 EUB             : #endif
    1889                 : }
    1890                 : 
    1891                 : 
    1892                 : /*----------------------------------------------------------------
    1893                 :  * PAM authentication system
    1894                 :  *----------------------------------------------------------------
    1895                 :  */
    1896                 : #ifdef USE_PAM
    1897                 : 
    1898                 : /*
    1899                 :  * PAM conversation function
    1900                 :  */
    1901                 : 
    1902                 : static int
    1903 UIC           0 : pam_passwd_conv_proc(int num_msg, const struct pam_message **msg,
    1904                 :                      struct pam_response **resp, void *appdata_ptr)
    1905 EUB             : {
    1906                 :     const char *passwd;
    1907                 :     struct pam_response *reply;
    1908                 :     int         i;
    1909                 : 
    1910 UBC           0 :     if (appdata_ptr)
    1911 UIC           0 :         passwd = (char *) appdata_ptr;
    1912 EUB             :     else
    1913                 :     {
    1914                 :         /*
    1915                 :          * Workaround for Solaris 2.6 where the PAM library is broken and does
    1916                 :          * not pass appdata_ptr to the conversation routine
    1917                 :          */
    1918 UIC           0 :         passwd = pam_passwd;
    1919                 :     }
    1920 EUB             : 
    1921 UBC           0 :     *resp = NULL;               /* in case of error exit */
    1922 EUB             : 
    1923 UIC           0 :     if (num_msg <= 0 || num_msg > PAM_MAX_NUM_MSG)
    1924               0 :         return PAM_CONV_ERR;
    1925                 : 
    1926                 :     /*
    1927                 :      * Explicitly not using palloc here - PAM will free this memory in
    1928                 :      * pam_end()
    1929 EUB             :      */
    1930 UBC           0 :     if ((reply = calloc(num_msg, sizeof(struct pam_response))) == NULL)
    1931                 :     {
    1932 UIC           0 :         ereport(LOG,
    1933 EUB             :                 (errcode(ERRCODE_OUT_OF_MEMORY),
    1934                 :                  errmsg("out of memory")));
    1935 UBC           0 :         return PAM_CONV_ERR;
    1936 EUB             :     }
    1937                 : 
    1938 UBC           0 :     for (i = 0; i < num_msg; i++)
    1939                 :     {
    1940 UIC           0 :         switch (msg[i]->msg_style)
    1941                 :         {
    1942               0 :             case PAM_PROMPT_ECHO_OFF:
    1943               0 :                 if (strlen(passwd) == 0)
    1944 EUB             :                 {
    1945                 :                     /*
    1946                 :                      * Password wasn't passed to PAM the first time around -
    1947                 :                      * let's go ask the client to send a password, which we
    1948                 :                      * then stuff into PAM.
    1949                 :                      */
    1950 UIC           0 :                     sendAuthRequest(pam_port_cludge, AUTH_REQ_PASSWORD, NULL, 0);
    1951               0 :                     passwd = recv_password_packet(pam_port_cludge);
    1952               0 :                     if (passwd == NULL)
    1953 EUB             :                     {
    1954                 :                         /*
    1955                 :                          * Client didn't want to send password.  We
    1956                 :                          * intentionally do not log anything about this,
    1957                 :                          * either here or at higher levels.
    1958                 :                          */
    1959 UIC           0 :                         pam_no_password = true;
    1960 UBC           0 :                         goto fail;
    1961                 :                     }
    1962 EUB             :                 }
    1963 UBC           0 :                 if ((reply[i].resp = strdup(passwd)) == NULL)
    1964               0 :                     goto fail;
    1965 UIC           0 :                 reply[i].resp_retcode = PAM_SUCCESS;
    1966 UBC           0 :                 break;
    1967 UIC           0 :             case PAM_ERROR_MSG:
    1968               0 :                 ereport(LOG,
    1969                 :                         (errmsg("error from underlying PAM layer: %s",
    1970                 :                                 msg[i]->msg)));
    1971                 :                 /* FALL THROUGH */
    1972                 :             case PAM_TEXT_INFO:
    1973                 :                 /* we don't bother to log TEXT_INFO messages */
    1974 UBC           0 :                 if ((reply[i].resp = strdup("")) == NULL)
    1975 UIC           0 :                     goto fail;
    1976               0 :                 reply[i].resp_retcode = PAM_SUCCESS;
    1977 UBC           0 :                 break;
    1978 UIC           0 :             default:
    1979               0 :                 ereport(LOG,
    1980                 :                         (errmsg("unsupported PAM conversation %d/\"%s\"",
    1981                 :                                 msg[i]->msg_style,
    1982                 :                                 msg[i]->msg ? msg[i]->msg : "(none)")));
    1983               0 :                 goto fail;
    1984 EUB             :         }
    1985                 :     }
    1986                 : 
    1987 UIC           0 :     *resp = reply;
    1988               0 :     return PAM_SUCCESS;
    1989                 : 
    1990               0 : fail:
    1991                 :     /* free up whatever we allocated */
    1992               0 :     for (i = 0; i < num_msg; i++)
    1993 UNC           0 :         free(reply[i].resp);
    1994 UBC           0 :     free(reply);
    1995 EUB             : 
    1996 UIC           0 :     return PAM_CONV_ERR;
    1997                 : }
    1998 EUB             : 
    1999                 : 
    2000                 : /*
    2001                 :  * Check authentication against PAM.
    2002                 :  */
    2003                 : static int
    2004 UIC           0 : CheckPAMAuth(Port *port, const char *user, const char *password)
    2005                 : {
    2006 EUB             :     int         retval;
    2007 UBC           0 :     pam_handle_t *pamh = NULL;
    2008                 : 
    2009                 :     /*
    2010 EUB             :      * We can't entirely rely on PAM to pass through appdata --- it appears
    2011                 :      * not to work on at least Solaris 2.6.  So use these ugly static
    2012                 :      * variables instead.
    2013                 :      */
    2014 UBC           0 :     pam_passwd = password;
    2015 UIC           0 :     pam_port_cludge = port;
    2016               0 :     pam_no_password = false;
    2017 EUB             : 
    2018                 :     /*
    2019                 :      * Set the application data portion of the conversation struct.  This is
    2020                 :      * later used inside the PAM conversation to pass the password to the
    2021                 :      * authentication module.
    2022                 :      */
    2023 UIC           0 :     pam_passw_conv.appdata_ptr = unconstify(char *, password);  /* from password above,
    2024                 :                                                                  * not allocated */
    2025                 : 
    2026 EUB             :     /* Optionally, one can set the service name in pg_hba.conf */
    2027 UBC           0 :     if (port->hba->pamservice && port->hba->pamservice[0] != '\0')
    2028 UIC           0 :         retval = pam_start(port->hba->pamservice, "pgsql@",
    2029 EUB             :                            &pam_passw_conv, &pamh);
    2030                 :     else
    2031 UBC           0 :         retval = pam_start(PGSQL_PAM_SERVICE, "pgsql@",
    2032                 :                            &pam_passw_conv, &pamh);
    2033                 : 
    2034               0 :     if (retval != PAM_SUCCESS)
    2035                 :     {
    2036               0 :         ereport(LOG,
    2037                 :                 (errmsg("could not create PAM authenticator: %s",
    2038                 :                         pam_strerror(pamh, retval))));
    2039               0 :         pam_passwd = NULL;      /* Unset pam_passwd */
    2040 UIC           0 :         return STATUS_ERROR;
    2041                 :     }
    2042 EUB             : 
    2043 UIC           0 :     retval = pam_set_item(pamh, PAM_USER, user);
    2044 EUB             : 
    2045 UIC           0 :     if (retval != PAM_SUCCESS)
    2046 EUB             :     {
    2047 UIC           0 :         ereport(LOG,
    2048                 :                 (errmsg("pam_set_item(PAM_USER) failed: %s",
    2049 EUB             :                         pam_strerror(pamh, retval))));
    2050 UBC           0 :         pam_passwd = NULL;      /* Unset pam_passwd */
    2051 UIC           0 :         return STATUS_ERROR;
    2052                 :     }
    2053                 : 
    2054 UBC           0 :     if (port->hba->conntype != ctLocal)
    2055                 :     {
    2056 EUB             :         char        hostinfo[NI_MAXHOST];
    2057                 :         int         flags;
    2058                 : 
    2059 UIC           0 :         if (port->hba->pam_use_hostname)
    2060               0 :             flags = 0;
    2061 EUB             :         else
    2062 UBC           0 :             flags = NI_NUMERICHOST | NI_NUMERICSERV;
    2063                 : 
    2064 UIC           0 :         retval = pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
    2065 EUB             :                                     hostinfo, sizeof(hostinfo), NULL, 0,
    2066                 :                                     flags);
    2067 UBC           0 :         if (retval != 0)
    2068                 :         {
    2069 UIC           0 :             ereport(WARNING,
    2070 EUB             :                     (errmsg_internal("pg_getnameinfo_all() failed: %s",
    2071                 :                                      gai_strerror(retval))));
    2072 UIC           0 :             return STATUS_ERROR;
    2073                 :         }
    2074 EUB             : 
    2075 UBC           0 :         retval = pam_set_item(pamh, PAM_RHOST, hostinfo);
    2076                 : 
    2077 UIC           0 :         if (retval != PAM_SUCCESS)
    2078 EUB             :         {
    2079 UIC           0 :             ereport(LOG,
    2080 EUB             :                     (errmsg("pam_set_item(PAM_RHOST) failed: %s",
    2081                 :                             pam_strerror(pamh, retval))));
    2082 UIC           0 :             pam_passwd = NULL;
    2083 UBC           0 :             return STATUS_ERROR;
    2084 EUB             :         }
    2085                 :     }
    2086                 : 
    2087 UBC           0 :     retval = pam_set_item(pamh, PAM_CONV, &pam_passw_conv);
    2088 EUB             : 
    2089 UIC           0 :     if (retval != PAM_SUCCESS)
    2090                 :     {
    2091 UBC           0 :         ereport(LOG,
    2092                 :                 (errmsg("pam_set_item(PAM_CONV) failed: %s",
    2093 EUB             :                         pam_strerror(pamh, retval))));
    2094 UIC           0 :         pam_passwd = NULL;      /* Unset pam_passwd */
    2095 UBC           0 :         return STATUS_ERROR;
    2096                 :     }
    2097                 : 
    2098 UIC           0 :     retval = pam_authenticate(pamh, 0);
    2099                 : 
    2100 UBC           0 :     if (retval != PAM_SUCCESS)
    2101                 :     {
    2102 EUB             :         /* If pam_passwd_conv_proc saw EOF, don't log anything */
    2103 UBC           0 :         if (!pam_no_password)
    2104 UIC           0 :             ereport(LOG,
    2105 EUB             :                     (errmsg("pam_authenticate failed: %s",
    2106                 :                             pam_strerror(pamh, retval))));
    2107 UIC           0 :         pam_passwd = NULL;      /* Unset pam_passwd */
    2108               0 :         return pam_no_password ? STATUS_EOF : STATUS_ERROR;
    2109                 :     }
    2110                 : 
    2111               0 :     retval = pam_acct_mgmt(pamh, 0);
    2112                 : 
    2113               0 :     if (retval != PAM_SUCCESS)
    2114                 :     {
    2115                 :         /* If pam_passwd_conv_proc saw EOF, don't log anything */
    2116               0 :         if (!pam_no_password)
    2117               0 :             ereport(LOG,
    2118                 :                     (errmsg("pam_acct_mgmt failed: %s",
    2119                 :                             pam_strerror(pamh, retval))));
    2120               0 :         pam_passwd = NULL;      /* Unset pam_passwd */
    2121               0 :         return pam_no_password ? STATUS_EOF : STATUS_ERROR;
    2122                 :     }
    2123                 : 
    2124               0 :     retval = pam_end(pamh, retval);
    2125                 : 
    2126               0 :     if (retval != PAM_SUCCESS)
    2127                 :     {
    2128               0 :         ereport(LOG,
    2129                 :                 (errmsg("could not release PAM authenticator: %s",
    2130                 :                         pam_strerror(pamh, retval))));
    2131                 :     }
    2132                 : 
    2133               0 :     pam_passwd = NULL;          /* Unset pam_passwd */
    2134                 : 
    2135               0 :     if (retval == PAM_SUCCESS)
    2136               0 :         set_authn_id(port, user);
    2137                 : 
    2138               0 :     return (retval == PAM_SUCCESS ? STATUS_OK : STATUS_ERROR);
    2139                 : }
    2140                 : #endif                          /* USE_PAM */
    2141                 : 
    2142                 : 
    2143                 : /*----------------------------------------------------------------
    2144                 :  * BSD authentication system
    2145                 :  *----------------------------------------------------------------
    2146                 :  */
    2147                 : #ifdef USE_BSD_AUTH
    2148                 : static int
    2149                 : CheckBSDAuth(Port *port, char *user)
    2150                 : {
    2151                 :     char       *passwd;
    2152                 :     int         retval;
    2153                 : 
    2154                 :     /* Send regular password request to client, and get the response */
    2155                 :     sendAuthRequest(port, AUTH_REQ_PASSWORD, NULL, 0);
    2156                 : 
    2157                 :     passwd = recv_password_packet(port);
    2158                 :     if (passwd == NULL)
    2159 ECB             :         return STATUS_EOF;
    2160                 : 
    2161                 :     /*
    2162                 :      * Ask the BSD auth system to verify password.  Note that auth_userokay
    2163                 :      * will overwrite the password string with zeroes, but it's just a
    2164                 :      * temporary string so we don't care.
    2165                 :      */
    2166                 :     retval = auth_userokay(user, NULL, "auth-postgresql", passwd);
    2167                 : 
    2168                 :     pfree(passwd);
    2169                 : 
    2170                 :     if (!retval)
    2171                 :         return STATUS_ERROR;
    2172                 : 
    2173                 :     set_authn_id(port, user);
    2174                 :     return STATUS_OK;
    2175                 : }
    2176                 : #endif                          /* USE_BSD_AUTH */
    2177                 : 
    2178                 : 
    2179                 : /*----------------------------------------------------------------
    2180                 :  * LDAP authentication system
    2181                 :  *----------------------------------------------------------------
    2182                 :  */
    2183                 : #ifdef USE_LDAP
    2184                 : 
    2185                 : static int  errdetail_for_ldap(LDAP *ldap);
    2186                 : 
    2187                 : /*
    2188                 :  * Initialize a connection to the LDAP server, including setting up
    2189                 :  * TLS if requested.
    2190                 :  */
    2191                 : static int
    2192 GIC          39 : InitializeLDAPConnection(Port *port, LDAP **ldap)
    2193 ECB             : {
    2194                 :     const char *scheme;
    2195 GIC          39 :     int         ldapversion = LDAP_VERSION3;
    2196                 :     int         r;
    2197                 : 
    2198 CBC          39 :     scheme = port->hba->ldapscheme;
    2199 GIC          39 :     if (scheme == NULL)
    2200              24 :         scheme = "ldap";
    2201                 : #ifdef WIN32
    2202                 :     if (strcmp(scheme, "ldaps") == 0)
    2203                 :         *ldap = ldap_sslinit(port->hba->ldapserver, port->hba->ldapport, 1);
    2204                 :     else
    2205 ECB             :         *ldap = ldap_init(port->hba->ldapserver, port->hba->ldapport);
    2206 EUB             :     if (!*ldap)
    2207                 :     {
    2208                 :         ereport(LOG,
    2209                 :                 (errmsg("could not initialize LDAP: error code %d",
    2210                 :                         (int) LdapGetLastError())));
    2211                 : 
    2212                 :         return STATUS_ERROR;
    2213                 :     }
    2214                 : #else
    2215                 : #ifdef HAVE_LDAP_INITIALIZE
    2216                 : 
    2217                 :     /*
    2218                 :      * OpenLDAP provides a non-standard extension ldap_initialize() that takes
    2219                 :      * a list of URIs, allowing us to request "ldaps" instead of "ldap".  It
    2220                 :      * also provides ldap_domain2hostlist() to find LDAP servers automatically
    2221                 :      * using DNS SRV.  They were introduced in the same version, so for now we
    2222                 :      * don't have an extra configure check for the latter.
    2223                 :      */
    2224                 :     {
    2225                 :         StringInfoData uris;
    2226 GIC          39 :         char       *hostlist = NULL;
    2227 EUB             :         char       *p;
    2228                 :         bool        append_port;
    2229                 : 
    2230                 :         /* We'll build a space-separated scheme://hostname:port list here */
    2231 GBC          39 :         initStringInfo(&uris);
    2232                 : 
    2233                 :         /*
    2234                 :          * If pg_hba.conf provided no hostnames, we can ask OpenLDAP to try to
    2235                 :          * find some by extracting a domain name from the base DN and looking
    2236 ECB             :          * up DSN SRV records for _ldap._tcp.<domain>.
    2237                 :          */
    2238 GIC          39 :         if (!port->hba->ldapserver || port->hba->ldapserver[0] == '\0')
    2239 UIC           0 :         {
    2240                 :             char       *domain;
    2241                 : 
    2242                 :             /* ou=blah,dc=foo,dc=bar -> foo.bar */
    2243               0 :             if (ldap_dn2domain(port->hba->ldapbasedn, &domain))
    2244                 :             {
    2245               0 :                 ereport(LOG,
    2246 ECB             :                         (errmsg("could not extract domain name from ldapbasedn")));
    2247 UIC           0 :                 return STATUS_ERROR;
    2248                 :             }
    2249 ECB             : 
    2250                 :             /* Look up a list of LDAP server hosts and port numbers */
    2251 UIC           0 :             if (ldap_domain2hostlist(domain, &hostlist))
    2252                 :             {
    2253 LBC           0 :                 ereport(LOG,
    2254 ECB             :                         (errmsg("LDAP authentication could not find DNS SRV records for \"%s\"",
    2255                 :                                 domain),
    2256                 :                          (errhint("Set an LDAP server name explicitly."))));
    2257 LBC           0 :                 ldap_memfree(domain);
    2258 UIC           0 :                 return STATUS_ERROR;
    2259                 :             }
    2260 LBC           0 :             ldap_memfree(domain);
    2261 ECB             : 
    2262                 :             /* We have a space-separated list of host:port entries */
    2263 LBC           0 :             p = hostlist;
    2264 UIC           0 :             append_port = false;
    2265                 :         }
    2266 ECB             :         else
    2267 EUB             :         {
    2268                 :             /* We have a space-separated list of hosts from pg_hba.conf */
    2269 GIC          39 :             p = port->hba->ldapserver;
    2270 CBC          39 :             append_port = true;
    2271 ECB             :         }
    2272                 : 
    2273                 :         /* Convert the list of host[:port] entries to full URIs */
    2274 EUB             :         do
    2275                 :         {
    2276                 :             size_t      size;
    2277                 : 
    2278                 :             /* Find the span of the next entry */
    2279 GIC          44 :             size = strcspn(p, " ");
    2280                 : 
    2281                 :             /* Append a space separator if this isn't the first URI */
    2282              44 :             if (uris.len > 0)
    2283               5 :                 appendStringInfoChar(&uris, ' ');
    2284                 : 
    2285                 :             /* Append scheme://host:port */
    2286              44 :             appendStringInfoString(&uris, scheme);
    2287              44 :             appendStringInfoString(&uris, "://");
    2288              44 :             appendBinaryStringInfo(&uris, p, size);
    2289              44 :             if (append_port)
    2290              44 :                 appendStringInfo(&uris, ":%d", port->hba->ldapport);
    2291                 : 
    2292                 :             /* Step over this entry and any number of trailing spaces */
    2293              44 :             p += size;
    2294              49 :             while (*p == ' ')
    2295               5 :                 ++p;
    2296              44 :         } while (*p);
    2297                 : 
    2298                 :         /* Free memory from OpenLDAP if we looked up SRV records */
    2299              39 :         if (hostlist)
    2300 LBC           0 :             ldap_memfree(hostlist);
    2301                 : 
    2302 EUB             :         /* Finally, try to connect using the URI list */
    2303 GIC          39 :         r = ldap_initialize(ldap, uris.data);
    2304              39 :         pfree(uris.data);
    2305              39 :         if (r != LDAP_SUCCESS)
    2306 EUB             :         {
    2307 UBC           0 :             ereport(LOG,
    2308                 :                     (errmsg("could not initialize LDAP: %s",
    2309                 :                             ldap_err2string(r))));
    2310 ECB             : 
    2311 UIC           0 :             return STATUS_ERROR;
    2312                 :         }
    2313 ECB             :     }
    2314                 : #else
    2315                 :     if (strcmp(scheme, "ldaps") == 0)
    2316                 :     {
    2317                 :         ereport(LOG,
    2318 EUB             :                 (errmsg("ldaps not supported with this LDAP library")));
    2319                 : 
    2320                 :         return STATUS_ERROR;
    2321                 :     }
    2322                 :     *ldap = ldap_init(port->hba->ldapserver, port->hba->ldapport);
    2323                 :     if (!*ldap)
    2324                 :     {
    2325                 :         ereport(LOG,
    2326                 :                 (errmsg("could not initialize LDAP: %m")));
    2327 ECB             : 
    2328                 :         return STATUS_ERROR;
    2329                 :     }
    2330                 : #endif
    2331                 : #endif
    2332                 : 
    2333 GIC          39 :     if ((r = ldap_set_option(*ldap, LDAP_OPT_PROTOCOL_VERSION, &ldapversion)) != LDAP_SUCCESS)
    2334                 :     {
    2335 UIC           0 :         ereport(LOG,
    2336                 :                 (errmsg("could not set LDAP protocol version: %s",
    2337                 :                         ldap_err2string(r)),
    2338                 :                  errdetail_for_ldap(*ldap)));
    2339               0 :         ldap_unbind(*ldap);
    2340               0 :         return STATUS_ERROR;
    2341                 :     }
    2342                 : 
    2343 GIC          39 :     if (port->hba->ldaptls)
    2344                 :     {
    2345 EUB             : #ifndef WIN32
    2346 GIC           2 :         if ((r = ldap_start_tls_s(*ldap, NULL, NULL)) != LDAP_SUCCESS)
    2347 EUB             : #else
    2348                 :         if ((r = ldap_start_tls_s(*ldap, NULL, NULL, NULL, NULL)) != LDAP_SUCCESS)
    2349                 : #endif
    2350                 :         {
    2351 LBC           0 :             ereport(LOG,
    2352 EUB             :                     (errmsg("could not start LDAP TLS session: %s",
    2353                 :                             ldap_err2string(r)),
    2354                 :                      errdetail_for_ldap(*ldap)));
    2355 UIC           0 :             ldap_unbind(*ldap);
    2356 UBC           0 :             return STATUS_ERROR;
    2357                 :         }
    2358                 :     }
    2359                 : 
    2360 GIC          39 :     return STATUS_OK;
    2361                 : }
    2362                 : 
    2363                 : /* Placeholders recognized by FormatSearchFilter.  For now just one. */
    2364                 : #define LPH_USERNAME "$username"
    2365                 : #define LPH_USERNAME_LEN (sizeof(LPH_USERNAME) - 1)
    2366                 : 
    2367                 : /* Not all LDAP implementations define this. */
    2368                 : #ifndef LDAP_NO_ATTRS
    2369                 : #define LDAP_NO_ATTRS "1.1"
    2370                 : #endif
    2371 ECB             : 
    2372                 : /* Not all LDAP implementations define this. */
    2373                 : #ifndef LDAPS_PORT
    2374                 : #define LDAPS_PORT 636
    2375 EUB             : #endif
    2376                 : 
    2377                 : static char *
    2378 UNC           0 : dummy_ldap_password_mutator(char *input)
    2379                 : {
    2380               0 :     return input;
    2381                 : }
    2382                 : 
    2383 EUB             : /*
    2384                 :  * Return a newly allocated C string copied from "pattern" with all
    2385                 :  * occurrences of the placeholder "$username" replaced with "user_name".
    2386                 :  */
    2387                 : static char *
    2388 CBC           8 : FormatSearchFilter(const char *pattern, const char *user_name)
    2389                 : {
    2390 ECB             :     StringInfoData output;
    2391                 : 
    2392 CBC           8 :     initStringInfo(&output);
    2393 GIC         119 :     while (*pattern != '\0')
    2394 ECB             :     {
    2395 GIC         111 :         if (strncmp(pattern, LPH_USERNAME, LPH_USERNAME_LEN) == 0)
    2396                 :         {
    2397 GBC          13 :             appendStringInfoString(&output, user_name);
    2398              13 :             pattern += LPH_USERNAME_LEN;
    2399                 :         }
    2400                 :         else
    2401 CBC          98 :             appendStringInfoChar(&output, *pattern++);
    2402                 :     }
    2403                 : 
    2404 GIC           8 :     return output.data;
    2405                 : }
    2406                 : 
    2407                 : /*
    2408                 :  * Perform LDAP authentication
    2409                 :  */
    2410 ECB             : static int
    2411 GIC          26 : CheckLDAPAuth(Port *port)
    2412                 : {
    2413                 :     char       *passwd;
    2414                 :     LDAP       *ldap;
    2415                 :     int         r;
    2416                 :     char       *fulluser;
    2417                 :     const char *server_name;
    2418                 : 
    2419                 : #ifdef HAVE_LDAP_INITIALIZE
    2420                 : 
    2421 ECB             :     /*
    2422                 :      * For OpenLDAP, allow empty hostname if we have a basedn.  We'll look for
    2423                 :      * servers with DNS SRV records via OpenLDAP library facilities.
    2424                 :      */
    2425 CBC          26 :     if ((!port->hba->ldapserver || port->hba->ldapserver[0] == '\0') &&
    2426 LBC           0 :         (!port->hba->ldapbasedn || port->hba->ldapbasedn[0] == '\0'))
    2427 ECB             :     {
    2428 UIC           0 :         ereport(LOG,
    2429 EUB             :                 (errmsg("LDAP server not specified, and no ldapbasedn")));
    2430 UIC           0 :         return STATUS_ERROR;
    2431 EUB             :     }
    2432                 : #else
    2433 ECB             :     if (!port->hba->ldapserver || port->hba->ldapserver[0] == '\0')
    2434                 :     {
    2435                 :         ereport(LOG,
    2436                 :                 (errmsg("LDAP server not specified")));
    2437                 :         return STATUS_ERROR;
    2438                 :     }
    2439                 : #endif
    2440                 : 
    2441                 :     /*
    2442                 :      * If we're using SRV records, we don't have a server name so we'll just
    2443                 :      * show an empty string in error messages.
    2444                 :      */
    2445 GIC          26 :     server_name = port->hba->ldapserver ? port->hba->ldapserver : "";
    2446 ECB             : 
    2447 GIC          26 :     if (port->hba->ldapport == 0)
    2448                 :     {
    2449 UIC           0 :         if (port->hba->ldapscheme != NULL &&
    2450               0 :             strcmp(port->hba->ldapscheme, "ldaps") == 0)
    2451               0 :             port->hba->ldapport = LDAPS_PORT;
    2452 ECB             :         else
    2453 LBC           0 :             port->hba->ldapport = LDAP_PORT;
    2454 ECB             :     }
    2455                 : 
    2456 GIC          26 :     sendAuthRequest(port, AUTH_REQ_PASSWORD, NULL, 0);
    2457                 : 
    2458 CBC          26 :     passwd = recv_password_packet(port);
    2459              26 :     if (passwd == NULL)
    2460               1 :         return STATUS_EOF;      /* client wouldn't send password */
    2461 ECB             : 
    2462 GIC          25 :     if (InitializeLDAPConnection(port, &ldap) == STATUS_ERROR)
    2463 ECB             :     {
    2464                 :         /* Error message already sent */
    2465 LBC           0 :         pfree(passwd);
    2466               0 :         return STATUS_ERROR;
    2467 ECB             :     }
    2468                 : 
    2469 GIC          25 :     if (port->hba->ldapbasedn)
    2470                 :     {
    2471                 :         /*
    2472                 :          * First perform an LDAP search to find the DN for the user we are
    2473                 :          * trying to log in as.
    2474 ECB             :          */
    2475                 :         char       *filter;
    2476 EUB             :         LDAPMessage *search_message;
    2477                 :         LDAPMessage *entry;
    2478 GIC          20 :         char       *attributes[] = {LDAP_NO_ATTRS, NULL};
    2479                 :         char       *dn;
    2480 EUB             :         char       *c;
    2481                 :         int         count;
    2482                 : 
    2483                 :         /*
    2484                 :          * Disallow any characters that we would otherwise need to escape,
    2485                 :          * since they aren't really reasonable in a username anyway. Allowing
    2486                 :          * them would make it possible to inject any kind of custom filters in
    2487                 :          * the LDAP filter.
    2488 ECB             :          */
    2489 CBC         144 :         for (c = port->user_name; *c; c++)
    2490                 :         {
    2491             124 :             if (*c == '*' ||
    2492             124 :                 *c == '(' ||
    2493 GIC         124 :                 *c == ')' ||
    2494             124 :                 *c == '\\' ||
    2495             124 :                 *c == '/')
    2496                 :             {
    2497 UBC           0 :                 ereport(LOG,
    2498                 :                         (errmsg("invalid character in user name for LDAP authentication")));
    2499 UIC           0 :                 ldap_unbind(ldap);
    2500               0 :                 pfree(passwd);
    2501 GIC           6 :                 return STATUS_ERROR;
    2502                 :             }
    2503                 :         }
    2504 ECB             : 
    2505                 :         /*
    2506                 :          * Bind with a pre-defined username/password (if available) for
    2507                 :          * searching. If none is specified, this turns into an anonymous bind.
    2508                 :          */
    2509 GIC          38 :         r = ldap_simple_bind_s(ldap,
    2510              20 :                                port->hba->ldapbinddn ? port->hba->ldapbinddn : "",
    2511 GNC          20 :                                port->hba->ldapbindpasswd ? ldap_password_hook(port->hba->ldapbindpasswd) : "");
    2512 CBC          20 :         if (r != LDAP_SUCCESS)
    2513 ECB             :         {
    2514 GIC           3 :             ereport(LOG,
    2515                 :                     (errmsg("could not perform initial LDAP bind for ldapbinddn \"%s\" on server \"%s\": %s",
    2516                 :                             port->hba->ldapbinddn ? port->hba->ldapbinddn : "",
    2517 EUB             :                             server_name,
    2518                 :                             ldap_err2string(r)),
    2519                 :                      errdetail_for_ldap(ldap)));
    2520 GIC           3 :             ldap_unbind(ldap);
    2521               3 :             pfree(passwd);
    2522               3 :             return STATUS_ERROR;
    2523 EUB             :         }
    2524                 : 
    2525                 :         /* Build a custom filter or a single attribute filter? */
    2526 GBC          17 :         if (port->hba->ldapsearchfilter)
    2527               8 :             filter = FormatSearchFilter(port->hba->ldapsearchfilter, port->user_name);
    2528 GIC           9 :         else if (port->hba->ldapsearchattribute)
    2529 CBC           3 :             filter = psprintf("(%s=%s)", port->hba->ldapsearchattribute, port->user_name);
    2530                 :         else
    2531               6 :             filter = psprintf("(uid=%s)", port->user_name);
    2532 ECB             : 
    2533 GNC          17 :         search_message = NULL;
    2534 CBC          17 :         r = ldap_search_s(ldap,
    2535 GIC          17 :                           port->hba->ldapbasedn,
    2536              17 :                           port->hba->ldapscope,
    2537 ECB             :                           filter,
    2538                 :                           attributes,
    2539                 :                           0,
    2540 EUB             :                           &search_message);
    2541                 : 
    2542 GIC          17 :         if (r != LDAP_SUCCESS)
    2543 EUB             :         {
    2544 UBC           0 :             ereport(LOG,
    2545 EUB             :                     (errmsg("could not search LDAP for filter \"%s\" on server \"%s\": %s",
    2546                 :                             filter, server_name, ldap_err2string(r)),
    2547                 :                      errdetail_for_ldap(ldap)));
    2548 UNC           0 :             if (search_message != NULL)
    2549               0 :                 ldap_msgfree(search_message);
    2550 UIC           0 :             ldap_unbind(ldap);
    2551               0 :             pfree(passwd);
    2552               0 :             pfree(filter);
    2553               0 :             return STATUS_ERROR;
    2554 ECB             :         }
    2555                 : 
    2556 GBC          17 :         count = ldap_count_entries(ldap, search_message);
    2557              17 :         if (count != 1)
    2558                 :         {
    2559 GIC           3 :             if (count == 0)
    2560 GBC           3 :                 ereport(LOG,
    2561                 :                         (errmsg("LDAP user \"%s\" does not exist", port->user_name),
    2562                 :                          errdetail("LDAP search for filter \"%s\" on server \"%s\" returned no entries.",
    2563                 :                                    filter, server_name)));
    2564 ECB             :             else
    2565 LBC           0 :                 ereport(LOG,
    2566                 :                         (errmsg("LDAP user \"%s\" is not unique", port->user_name),
    2567 ECB             :                          errdetail_plural("LDAP search for filter \"%s\" on server \"%s\" returned %d entry.",
    2568                 :                                           "LDAP search for filter \"%s\" on server \"%s\" returned %d entries.",
    2569                 :                                           count,
    2570                 :                                           filter, server_name, count)));
    2571                 : 
    2572 GIC           3 :             ldap_unbind(ldap);
    2573 CBC           3 :             pfree(passwd);
    2574 GIC           3 :             pfree(filter);
    2575               3 :             ldap_msgfree(search_message);
    2576               3 :             return STATUS_ERROR;
    2577 ECB             :         }
    2578                 : 
    2579 CBC          14 :         entry = ldap_first_entry(ldap, search_message);
    2580              14 :         dn = ldap_get_dn(ldap, entry);
    2581 GIC          14 :         if (dn == NULL)
    2582                 :         {
    2583                 :             int         error;
    2584 ECB             : 
    2585 UIC           0 :             (void) ldap_get_option(ldap, LDAP_OPT_ERROR_NUMBER, &error);
    2586 LBC           0 :             ereport(LOG,
    2587 ECB             :                     (errmsg("could not get dn for the first entry matching \"%s\" on server \"%s\": %s",
    2588                 :                             filter, server_name,
    2589                 :                             ldap_err2string(error)),
    2590                 :                      errdetail_for_ldap(ldap)));
    2591 UIC           0 :             ldap_unbind(ldap);
    2592               0 :             pfree(passwd);
    2593               0 :             pfree(filter);
    2594               0 :             ldap_msgfree(search_message);
    2595               0 :             return STATUS_ERROR;
    2596                 :         }
    2597 GIC          14 :         fulluser = pstrdup(dn);
    2598 ECB             : 
    2599 GIC          14 :         pfree(filter);
    2600              14 :         ldap_memfree(dn);
    2601              14 :         ldap_msgfree(search_message);
    2602                 : 
    2603 ECB             :         /* Unbind and disconnect from the LDAP server */
    2604 CBC          14 :         r = ldap_unbind_s(ldap);
    2605 GIC          14 :         if (r != LDAP_SUCCESS)
    2606 ECB             :         {
    2607 LBC           0 :             ereport(LOG,
    2608                 :                     (errmsg("could not unbind after searching for user \"%s\" on server \"%s\"",
    2609                 :                             fulluser, server_name)));
    2610               0 :             pfree(passwd);
    2611 UIC           0 :             pfree(fulluser);
    2612               0 :             return STATUS_ERROR;
    2613                 :         }
    2614                 : 
    2615                 :         /*
    2616                 :          * Need to re-initialize the LDAP connection, so that we can bind to
    2617                 :          * it with a different username.
    2618                 :          */
    2619 GIC          14 :         if (InitializeLDAPConnection(port, &ldap) == STATUS_ERROR)
    2620                 :         {
    2621 UIC           0 :             pfree(passwd);
    2622 LBC           0 :             pfree(fulluser);
    2623                 : 
    2624 ECB             :             /* Error message already sent */
    2625 LBC           0 :             return STATUS_ERROR;
    2626                 :         }
    2627 ECB             :     }
    2628                 :     else
    2629 GIC           5 :         fulluser = psprintf("%s%s%s",
    2630 CBC           5 :                             port->hba->ldapprefix ? port->hba->ldapprefix : "",
    2631                 :                             port->user_name,
    2632               5 :                             port->hba->ldapsuffix ? port->hba->ldapsuffix : "");
    2633 ECB             : 
    2634 CBC          19 :     r = ldap_simple_bind_s(ldap, fulluser, passwd);
    2635 ECB             : 
    2636 CBC          19 :     if (r != LDAP_SUCCESS)
    2637                 :     {
    2638 GIC           6 :         ereport(LOG,
    2639                 :                 (errmsg("LDAP login failed for user \"%s\" on server \"%s\": %s",
    2640 ECB             :                         fulluser, server_name, ldap_err2string(r)),
    2641                 :                  errdetail_for_ldap(ldap)));
    2642 GIC           6 :         ldap_unbind(ldap);
    2643 GBC           6 :         pfree(passwd);
    2644 GIC           6 :         pfree(fulluser);
    2645               6 :         return STATUS_ERROR;
    2646 EUB             :     }
    2647                 : 
    2648                 :     /* Save the original bind DN as the authenticated identity. */
    2649 CBC          13 :     set_authn_id(port, fulluser);
    2650                 : 
    2651 GIC          13 :     ldap_unbind(ldap);
    2652              13 :     pfree(passwd);
    2653              13 :     pfree(fulluser);
    2654                 : 
    2655              13 :     return STATUS_OK;
    2656                 : }
    2657                 : 
    2658 ECB             : /*
    2659                 :  * Add a detail error message text to the current error if one can be
    2660                 :  * constructed from the LDAP 'diagnostic message'.
    2661                 :  */
    2662                 : static int
    2663 GIC           9 : errdetail_for_ldap(LDAP *ldap)
    2664 EUB             : {
    2665                 :     char       *message;
    2666                 :     int         rc;
    2667                 : 
    2668 GIC           9 :     rc = ldap_get_option(ldap, LDAP_OPT_DIAGNOSTIC_MESSAGE, &message);
    2669               9 :     if (rc == LDAP_SUCCESS && message != NULL)
    2670 ECB             :     {
    2671 GIC           2 :         errdetail("LDAP diagnostics: %s", message);
    2672               2 :         ldap_memfree(message);
    2673                 :     }
    2674 ECB             : 
    2675 CBC           9 :     return 0;
    2676                 : }
    2677                 : 
    2678                 : #endif                          /* USE_LDAP */
    2679                 : 
    2680                 : 
    2681                 : /*----------------------------------------------------------------
    2682 ECB             :  * SSL client certificate authentication
    2683                 :  *----------------------------------------------------------------
    2684                 :  */
    2685                 : #ifdef USE_SSL
    2686 EUB             : static int
    2687 GBC          27 : CheckCertAuth(Port *port)
    2688                 : {
    2689 GIC          27 :     int         status_check_usermap = STATUS_ERROR;
    2690 GBC          27 :     char       *peer_username = NULL;
    2691 ECB             : 
    2692 CBC          27 :     Assert(port->ssl);
    2693                 : 
    2694                 :     /* select the correct field to compare */
    2695 GIC          27 :     switch (port->hba->clientcertname)
    2696                 :     {
    2697               2 :         case clientCertDN:
    2698 CBC           2 :             peer_username = port->peer_dn;
    2699 GIC           2 :             break;
    2700              25 :         case clientCertCN:
    2701              25 :             peer_username = port->peer_cn;
    2702                 :     }
    2703                 : 
    2704                 :     /* Make sure we have received a username in the certificate */
    2705              27 :     if (peer_username == NULL ||
    2706              27 :         strlen(peer_username) <= 0)
    2707                 :     {
    2708 UIC           0 :         ereport(LOG,
    2709                 :                 (errmsg("certificate authentication failed for user \"%s\": client certificate contains no user name",
    2710                 :                         port->user_name)));
    2711               0 :         return STATUS_ERROR;
    2712                 :     }
    2713                 : 
    2714 GIC          27 :     if (port->hba->auth_method == uaCert)
    2715                 :     {
    2716                 :         /*
    2717                 :          * For cert auth, the client's Subject DN is always our authenticated
    2718                 :          * identity, even if we're only using its CN for authorization.  Set
    2719                 :          * it now, rather than waiting for check_usermap() below, because
    2720                 :          * authentication has already succeeded and we want the log file to
    2721                 :          * reflect that.
    2722                 :          */
    2723              24 :         if (!port->peer_dn)
    2724                 :         {
    2725                 :             /*
    2726                 :              * This should not happen as both peer_dn and peer_cn should be
    2727                 :              * set in this context.
    2728                 :              */
    2729 UIC           0 :             ereport(LOG,
    2730                 :                     (errmsg("certificate authentication failed for user \"%s\": unable to retrieve subject DN",
    2731                 :                             port->user_name)));
    2732               0 :             return STATUS_ERROR;
    2733                 :         }
    2734                 : 
    2735 GIC          24 :         set_authn_id(port, port->peer_dn);
    2736                 :     }
    2737                 : 
    2738                 :     /* Just pass the certificate cn/dn to the usermap check */
    2739              27 :     status_check_usermap = check_usermap(port->hba->usermap, port->user_name, peer_username, false);
    2740              27 :     if (status_check_usermap != STATUS_OK)
    2741                 :     {
    2742                 :         /*
    2743                 :          * If clientcert=verify-full was specified and the authentication
    2744                 :          * method is other than uaCert, log the reason for rejecting the
    2745                 :          * authentication.
    2746                 :          */
    2747               2 :         if (port->hba->clientcert == clientCertFull && port->hba->auth_method != uaCert)
    2748                 :         {
    2749               1 :             switch (port->hba->clientcertname)
    2750                 :             {
    2751 UIC           0 :                 case clientCertDN:
    2752               0 :                     ereport(LOG,
    2753                 :                             (errmsg("certificate validation (clientcert=verify-full) failed for user \"%s\": DN mismatch",
    2754 EUB             :                                     port->user_name)));
    2755 UIC           0 :                     break;
    2756 GIC           1 :                 case clientCertCN:
    2757               1 :                     ereport(LOG,
    2758 EUB             :                             (errmsg("certificate validation (clientcert=verify-full) failed for user \"%s\": CN mismatch",
    2759                 :                                     port->user_name)));
    2760                 :             }
    2761                 :         }
    2762                 :     }
    2763 GIC          27 :     return status_check_usermap;
    2764                 : }
    2765                 : #endif
    2766 EUB             : 
    2767                 : 
    2768                 : /*----------------------------------------------------------------
    2769                 :  * RADIUS authentication
    2770                 :  *----------------------------------------------------------------
    2771                 :  */
    2772                 : 
    2773                 : /*
    2774                 :  * RADIUS authentication is described in RFC2865 (and several others).
    2775                 :  */
    2776                 : 
    2777                 : #define RADIUS_VECTOR_LENGTH 16
    2778                 : #define RADIUS_HEADER_LENGTH 20
    2779                 : #define RADIUS_MAX_PASSWORD_LENGTH 128
    2780                 : 
    2781                 : /* Maximum size of a RADIUS packet we will create or accept */
    2782                 : #define RADIUS_BUFFER_SIZE 1024
    2783                 : 
    2784                 : typedef struct
    2785                 : {
    2786                 :     uint8       attribute;
    2787                 :     uint8       length;
    2788                 :     uint8       data[FLEXIBLE_ARRAY_MEMBER];
    2789                 : } radius_attribute;
    2790                 : 
    2791                 : typedef struct
    2792                 : {
    2793                 :     uint8       code;
    2794                 :     uint8       id;
    2795                 :     uint16      length;
    2796                 :     uint8       vector[RADIUS_VECTOR_LENGTH];
    2797                 :     /* this is a bit longer than strictly necessary: */
    2798                 :     char        pad[RADIUS_BUFFER_SIZE - RADIUS_VECTOR_LENGTH];
    2799                 : } radius_packet;
    2800                 : 
    2801                 : /* RADIUS packet types */
    2802                 : #define RADIUS_ACCESS_REQUEST   1
    2803                 : #define RADIUS_ACCESS_ACCEPT    2
    2804                 : #define RADIUS_ACCESS_REJECT    3
    2805                 : 
    2806                 : /* RADIUS attributes */
    2807                 : #define RADIUS_USER_NAME        1
    2808                 : #define RADIUS_PASSWORD         2
    2809                 : #define RADIUS_SERVICE_TYPE     6
    2810                 : #define RADIUS_NAS_IDENTIFIER   32
    2811                 : 
    2812                 : /* RADIUS service types */
    2813                 : #define RADIUS_AUTHENTICATE_ONLY    8
    2814                 : 
    2815                 : /* Seconds to wait - XXX: should be in a config variable! */
    2816                 : #define RADIUS_TIMEOUT 3
    2817                 : 
    2818                 : static void
    2819 UIC           0 : radius_add_attribute(radius_packet *packet, uint8 type, const unsigned char *data, int len)
    2820                 : {
    2821                 :     radius_attribute *attr;
    2822                 : 
    2823               0 :     if (packet->length + len > RADIUS_BUFFER_SIZE)
    2824 EUB             :     {
    2825                 :         /*
    2826                 :          * With remotely realistic data, this can never happen. But catch it
    2827                 :          * just to make sure we don't overrun a buffer. We'll just skip adding
    2828                 :          * the broken attribute, which will in the end cause authentication to
    2829                 :          * fail.
    2830                 :          */
    2831 UIC           0 :         elog(WARNING,
    2832                 :              "adding attribute code %d with length %d to radius packet would create oversize packet, ignoring",
    2833 EUB             :              type, len);
    2834 UIC           0 :         return;
    2835                 :     }
    2836                 : 
    2837               0 :     attr = (radius_attribute *) ((unsigned char *) packet + packet->length);
    2838               0 :     attr->attribute = type;
    2839               0 :     attr->length = len + 2;      /* total size includes type and length */
    2840               0 :     memcpy(attr->data, data, len);
    2841               0 :     packet->length += attr->length;
    2842 EUB             : }
    2843                 : 
    2844                 : static int
    2845 UIC           0 : CheckRADIUSAuth(Port *port)
    2846 EUB             : {
    2847                 :     char       *passwd;
    2848                 :     ListCell   *server,
    2849                 :                *secrets,
    2850                 :                *radiusports,
    2851                 :                *identifiers;
    2852                 : 
    2853                 :     /* Make sure struct alignment is correct */
    2854                 :     Assert(offsetof(radius_packet, vector) == 4);
    2855                 : 
    2856                 :     /* Verify parameters */
    2857 UNC           0 :     if (port->hba->radiusservers == NIL)
    2858                 :     {
    2859 UIC           0 :         ereport(LOG,
    2860                 :                 (errmsg("RADIUS server not specified")));
    2861 UBC           0 :         return STATUS_ERROR;
    2862 EUB             :     }
    2863                 : 
    2864 UNC           0 :     if (port->hba->radiussecrets == NIL)
    2865 EUB             :     {
    2866 UBC           0 :         ereport(LOG,
    2867                 :                 (errmsg("RADIUS secret not specified")));
    2868 UIC           0 :         return STATUS_ERROR;
    2869                 :     }
    2870 EUB             : 
    2871                 :     /* Send regular password request to client, and get the response */
    2872 UIC           0 :     sendAuthRequest(port, AUTH_REQ_PASSWORD, NULL, 0);
    2873                 : 
    2874               0 :     passwd = recv_password_packet(port);
    2875 UBC           0 :     if (passwd == NULL)
    2876 UIC           0 :         return STATUS_EOF;      /* client wouldn't send password */
    2877                 : 
    2878               0 :     if (strlen(passwd) > RADIUS_MAX_PASSWORD_LENGTH)
    2879 EUB             :     {
    2880 UBC           0 :         ereport(LOG,
    2881 EUB             :                 (errmsg("RADIUS authentication does not support passwords longer than %d characters", RADIUS_MAX_PASSWORD_LENGTH)));
    2882 UBC           0 :         pfree(passwd);
    2883               0 :         return STATUS_ERROR;
    2884                 :     }
    2885                 : 
    2886                 :     /*
    2887                 :      * Loop over and try each server in order.
    2888                 :      */
    2889 UIC           0 :     secrets = list_head(port->hba->radiussecrets);
    2890               0 :     radiusports = list_head(port->hba->radiusports);
    2891               0 :     identifiers = list_head(port->hba->radiusidentifiers);
    2892               0 :     foreach(server, port->hba->radiusservers)
    2893                 :     {
    2894               0 :         int         ret = PerformRadiusTransaction(lfirst(server),
    2895               0 :                                                    lfirst(secrets),
    2896                 :                                                    radiusports ? lfirst(radiusports) : NULL,
    2897                 :                                                    identifiers ? lfirst(identifiers) : NULL,
    2898               0 :                                                    port->user_name,
    2899                 :                                                    passwd);
    2900                 : 
    2901                 :         /*------
    2902                 :          * STATUS_OK = Login OK
    2903                 :          * STATUS_ERROR = Login not OK, but try next server
    2904 EUB             :          * STATUS_EOF = Login not OK, and don't try next server
    2905                 :          *------
    2906                 :          */
    2907 UBC           0 :         if (ret == STATUS_OK)
    2908                 :         {
    2909               0 :             set_authn_id(port, port->user_name);
    2910 EUB             : 
    2911 UBC           0 :             pfree(passwd);
    2912               0 :             return STATUS_OK;
    2913                 :         }
    2914               0 :         else if (ret == STATUS_EOF)
    2915 EUB             :         {
    2916 UIC           0 :             pfree(passwd);
    2917 UBC           0 :             return STATUS_ERROR;
    2918                 :         }
    2919                 : 
    2920 EUB             :         /*
    2921                 :          * secret, port and identifiers either have length 0 (use default),
    2922                 :          * length 1 (use the same everywhere) or the same length as servers.
    2923                 :          * So if the length is >1, we advance one step. In other cases, we
    2924                 :          * don't and will then reuse the correct value.
    2925                 :          */
    2926 UIC           0 :         if (list_length(port->hba->radiussecrets) > 1)
    2927 UBC           0 :             secrets = lnext(port->hba->radiussecrets, secrets);
    2928               0 :         if (list_length(port->hba->radiusports) > 1)
    2929               0 :             radiusports = lnext(port->hba->radiusports, radiusports);
    2930 UIC           0 :         if (list_length(port->hba->radiusidentifiers) > 1)
    2931 UBC           0 :             identifiers = lnext(port->hba->radiusidentifiers, identifiers);
    2932                 :     }
    2933 EUB             : 
    2934                 :     /* No servers left to try, so give up */
    2935 UIC           0 :     pfree(passwd);
    2936 UBC           0 :     return STATUS_ERROR;
    2937 EUB             : }
    2938                 : 
    2939                 : static int
    2940 UIC           0 : PerformRadiusTransaction(const char *server, const char *secret, const char *portstr, const char *identifier, const char *user_name, const char *passwd)
    2941                 : {
    2942                 :     radius_packet radius_send_pack;
    2943                 :     radius_packet radius_recv_pack;
    2944               0 :     radius_packet *packet = &radius_send_pack;
    2945               0 :     radius_packet *receivepacket = &radius_recv_pack;
    2946               0 :     char       *radius_buffer = (char *) &radius_send_pack;
    2947 UBC           0 :     char       *receive_buffer = (char *) &radius_recv_pack;
    2948               0 :     int32       service = pg_hton32(RADIUS_AUTHENTICATE_ONLY);
    2949 EUB             :     uint8      *cryptvector;
    2950                 :     int         encryptedpasswordlen;
    2951                 :     uint8       encryptedpassword[RADIUS_MAX_PASSWORD_LENGTH];
    2952                 :     uint8      *md5trailer;
    2953                 :     int         packetlength;
    2954                 :     pgsocket    sock;
    2955                 : 
    2956                 :     struct sockaddr_in6 localaddr;
    2957                 :     struct sockaddr_in6 remoteaddr;
    2958                 :     struct addrinfo hint;
    2959                 :     struct addrinfo *serveraddrs;
    2960                 :     int         port;
    2961                 :     socklen_t   addrsize;
    2962                 :     fd_set      fdset;
    2963                 :     struct timeval endtime;
    2964                 :     int         i,
    2965                 :                 j,
    2966                 :                 r;
    2967                 : 
    2968                 :     /* Assign default values */
    2969 UIC           0 :     if (portstr == NULL)
    2970               0 :         portstr = "1812";
    2971 UBC           0 :     if (identifier == NULL)
    2972 UIC           0 :         identifier = "postgresql";
    2973 EUB             : 
    2974 UBC           0 :     MemSet(&hint, 0, sizeof(hint));
    2975 UIC           0 :     hint.ai_socktype = SOCK_DGRAM;
    2976 UBC           0 :     hint.ai_family = AF_UNSPEC;
    2977 UIC           0 :     port = atoi(portstr);
    2978                 : 
    2979 UBC           0 :     r = pg_getaddrinfo_all(server, portstr, &hint, &serveraddrs);
    2980 UIC           0 :     if (r || !serveraddrs)
    2981 EUB             :     {
    2982 UIC           0 :         ereport(LOG,
    2983                 :                 (errmsg("could not translate RADIUS server name \"%s\" to address: %s",
    2984 EUB             :                         server, gai_strerror(r))));
    2985 UBC           0 :         if (serveraddrs)
    2986 UIC           0 :             pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
    2987 UBC           0 :         return STATUS_ERROR;
    2988 EUB             :     }
    2989                 :     /* XXX: add support for multiple returned addresses? */
    2990                 : 
    2991                 :     /* Construct RADIUS packet */
    2992 UBC           0 :     packet->code = RADIUS_ACCESS_REQUEST;
    2993               0 :     packet->length = RADIUS_HEADER_LENGTH;
    2994 UIC           0 :     if (!pg_strong_random(packet->vector, RADIUS_VECTOR_LENGTH))
    2995                 :     {
    2996 UBC           0 :         ereport(LOG,
    2997 EUB             :                 (errmsg("could not generate random encryption vector")));
    2998 UBC           0 :         pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
    2999               0 :         return STATUS_ERROR;
    3000 EUB             :     }
    3001 UIC           0 :     packet->id = packet->vector[0];
    3002 UBC           0 :     radius_add_attribute(packet, RADIUS_SERVICE_TYPE, (const unsigned char *) &service, sizeof(service));
    3003 UIC           0 :     radius_add_attribute(packet, RADIUS_USER_NAME, (const unsigned char *) user_name, strlen(user_name));
    3004 UBC           0 :     radius_add_attribute(packet, RADIUS_NAS_IDENTIFIER, (const unsigned char *) identifier, strlen(identifier));
    3005                 : 
    3006 EUB             :     /*
    3007                 :      * RADIUS password attributes are calculated as: e[0] = p[0] XOR
    3008                 :      * MD5(secret + Request Authenticator) for the first group of 16 octets,
    3009                 :      * and then: e[i] = p[i] XOR MD5(secret + e[i-1]) for the following ones
    3010                 :      * (if necessary)
    3011                 :      */
    3012 UIC           0 :     encryptedpasswordlen = ((strlen(passwd) + RADIUS_VECTOR_LENGTH - 1) / RADIUS_VECTOR_LENGTH) * RADIUS_VECTOR_LENGTH;
    3013 UBC           0 :     cryptvector = palloc(strlen(secret) + RADIUS_VECTOR_LENGTH);
    3014               0 :     memcpy(cryptvector, secret, strlen(secret));
    3015                 : 
    3016 EUB             :     /* for the first iteration, we use the Request Authenticator vector */
    3017 UIC           0 :     md5trailer = packet->vector;
    3018 UBC           0 :     for (i = 0; i < encryptedpasswordlen; i += RADIUS_VECTOR_LENGTH)
    3019 EUB             :     {
    3020 UBC           0 :         const char *errstr = NULL;
    3021                 : 
    3022 UIC           0 :         memcpy(cryptvector + strlen(secret), md5trailer, RADIUS_VECTOR_LENGTH);
    3023                 : 
    3024 EUB             :         /*
    3025                 :          * .. and for subsequent iterations the result of the previous XOR
    3026                 :          * (calculated below)
    3027                 :          */
    3028 UIC           0 :         md5trailer = encryptedpassword + i;
    3029                 : 
    3030               0 :         if (!pg_md5_binary(cryptvector, strlen(secret) + RADIUS_VECTOR_LENGTH,
    3031                 :                            encryptedpassword + i, &errstr))
    3032                 :         {
    3033               0 :             ereport(LOG,
    3034                 :                     (errmsg("could not perform MD5 encryption of password: %s",
    3035                 :                             errstr)));
    3036 UBC           0 :             pfree(cryptvector);
    3037               0 :             pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
    3038 UIC           0 :             return STATUS_ERROR;
    3039                 :         }
    3040 EUB             : 
    3041 UIC           0 :         for (j = i; j < i + RADIUS_VECTOR_LENGTH; j++)
    3042                 :         {
    3043               0 :             if (j < strlen(passwd))
    3044 UBC           0 :                 encryptedpassword[j] = passwd[j] ^ encryptedpassword[j];
    3045                 :             else
    3046               0 :                 encryptedpassword[j] = '\0' ^ encryptedpassword[j];
    3047 EUB             :         }
    3048                 :     }
    3049 UIC           0 :     pfree(cryptvector);
    3050 EUB             : 
    3051 UIC           0 :     radius_add_attribute(packet, RADIUS_PASSWORD, encryptedpassword, encryptedpasswordlen);
    3052                 : 
    3053 EUB             :     /* Length needs to be in network order on the wire */
    3054 UBC           0 :     packetlength = packet->length;
    3055 UIC           0 :     packet->length = pg_hton16(packet->length);
    3056 EUB             : 
    3057 UBC           0 :     sock = socket(serveraddrs[0].ai_family, SOCK_DGRAM, 0);
    3058 UIC           0 :     if (sock == PGINVALID_SOCKET)
    3059 EUB             :     {
    3060 UBC           0 :         ereport(LOG,
    3061                 :                 (errmsg("could not create RADIUS socket: %m")));
    3062               0 :         pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
    3063               0 :         return STATUS_ERROR;
    3064                 :     }
    3065 EUB             : 
    3066 UBC           0 :     memset(&localaddr, 0, sizeof(localaddr));
    3067 UIC           0 :     localaddr.sin6_family = serveraddrs[0].ai_family;
    3068 UBC           0 :     localaddr.sin6_addr = in6addr_any;
    3069 UIC           0 :     if (localaddr.sin6_family == AF_INET6)
    3070 UBC           0 :         addrsize = sizeof(struct sockaddr_in6);
    3071 EUB             :     else
    3072 UIC           0 :         addrsize = sizeof(struct sockaddr_in);
    3073 EUB             : 
    3074 UBC           0 :     if (bind(sock, (struct sockaddr *) &localaddr, addrsize))
    3075                 :     {
    3076 UIC           0 :         ereport(LOG,
    3077                 :                 (errmsg("could not bind local RADIUS socket: %m")));
    3078               0 :         closesocket(sock);
    3079               0 :         pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
    3080               0 :         return STATUS_ERROR;
    3081                 :     }
    3082                 : 
    3083               0 :     if (sendto(sock, radius_buffer, packetlength, 0,
    3084               0 :                serveraddrs[0].ai_addr, serveraddrs[0].ai_addrlen) < 0)
    3085                 :     {
    3086               0 :         ereport(LOG,
    3087                 :                 (errmsg("could not send RADIUS packet: %m")));
    3088 UBC           0 :         closesocket(sock);
    3089               0 :         pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
    3090 UIC           0 :         return STATUS_ERROR;
    3091 EUB             :     }
    3092                 : 
    3093                 :     /* Don't need the server address anymore */
    3094 UIC           0 :     pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
    3095 EUB             : 
    3096                 :     /*
    3097                 :      * Figure out at what time we should time out. We can't just use a single
    3098                 :      * call to select() with a timeout, since somebody can be sending invalid
    3099                 :      * packets to our port thus causing us to retry in a loop and never time
    3100                 :      * out.
    3101                 :      *
    3102                 :      * XXX: Using WaitLatchOrSocket() and doing a CHECK_FOR_INTERRUPTS() if
    3103                 :      * the latch was set would improve the responsiveness to
    3104                 :      * timeouts/cancellations.
    3105                 :      */
    3106 UIC           0 :     gettimeofday(&endtime, NULL);
    3107 UBC           0 :     endtime.tv_sec += RADIUS_TIMEOUT;
    3108                 : 
    3109 EUB             :     while (true)
    3110 UIC           0 :     {
    3111 EUB             :         struct timeval timeout;
    3112                 :         struct timeval now;
    3113                 :         int64       timeoutval;
    3114 UBC           0 :         const char *errstr = NULL;
    3115                 : 
    3116               0 :         gettimeofday(&now, NULL);
    3117 UIC           0 :         timeoutval = (endtime.tv_sec * 1000000 + endtime.tv_usec) - (now.tv_sec * 1000000 + now.tv_usec);
    3118               0 :         if (timeoutval <= 0)
    3119 EUB             :         {
    3120 UIC           0 :             ereport(LOG,
    3121                 :                     (errmsg("timeout waiting for RADIUS response from %s",
    3122 EUB             :                             server)));
    3123 UIC           0 :             closesocket(sock);
    3124 UBC           0 :             return STATUS_ERROR;
    3125                 :         }
    3126 UIC           0 :         timeout.tv_sec = timeoutval / 1000000;
    3127 UBC           0 :         timeout.tv_usec = timeoutval % 1000000;
    3128                 : 
    3129 UIC           0 :         FD_ZERO(&fdset);
    3130               0 :         FD_SET(sock, &fdset);
    3131                 : 
    3132               0 :         r = select(sock + 1, &fdset, NULL, NULL, &timeout);
    3133               0 :         if (r < 0)
    3134 EUB             :         {
    3135 UIC           0 :             if (errno == EINTR)
    3136 UBC           0 :                 continue;
    3137 EUB             : 
    3138                 :             /* Anything else is an actual error */
    3139 UIC           0 :             ereport(LOG,
    3140 EUB             :                     (errmsg("could not check status on RADIUS socket: %m")));
    3141 UIC           0 :             closesocket(sock);
    3142 UBC           0 :             return STATUS_ERROR;
    3143 EUB             :         }
    3144 UIC           0 :         if (r == 0)
    3145 EUB             :         {
    3146 UBC           0 :             ereport(LOG,
    3147                 :                     (errmsg("timeout waiting for RADIUS response from %s",
    3148                 :                             server)));
    3149               0 :             closesocket(sock);
    3150 UIC           0 :             return STATUS_ERROR;
    3151                 :         }
    3152 EUB             : 
    3153                 :         /*
    3154                 :          * Attempt to read the response packet, and verify the contents.
    3155                 :          *
    3156                 :          * Any packet that's not actually a RADIUS packet, or otherwise does
    3157                 :          * not validate as an explicit reject, is just ignored and we retry
    3158                 :          * for another packet (until we reach the timeout). This is to avoid
    3159                 :          * the possibility to denial-of-service the login by flooding the
    3160                 :          * server with invalid packets on the port that we're expecting the
    3161                 :          * RADIUS response on.
    3162                 :          */
    3163                 : 
    3164 UIC           0 :         addrsize = sizeof(remoteaddr);
    3165 UBC           0 :         packetlength = recvfrom(sock, receive_buffer, RADIUS_BUFFER_SIZE, 0,
    3166                 :                                 (struct sockaddr *) &remoteaddr, &addrsize);
    3167               0 :         if (packetlength < 0)
    3168 EUB             :         {
    3169 UIC           0 :             ereport(LOG,
    3170 EUB             :                     (errmsg("could not read RADIUS response: %m")));
    3171 UIC           0 :             closesocket(sock);
    3172 UBC           0 :             return STATUS_ERROR;
    3173 EUB             :         }
    3174                 : 
    3175 UIC           0 :         if (remoteaddr.sin6_port != pg_hton16(port))
    3176 EUB             :         {
    3177 UIC           0 :             ereport(LOG,
    3178                 :                     (errmsg("RADIUS response from %s was sent from incorrect port: %d",
    3179                 :                             server, pg_ntoh16(remoteaddr.sin6_port))));
    3180               0 :             continue;
    3181                 :         }
    3182                 : 
    3183               0 :         if (packetlength < RADIUS_HEADER_LENGTH)
    3184                 :         {
    3185               0 :             ereport(LOG,
    3186                 :                     (errmsg("RADIUS response from %s too short: %d", server, packetlength)));
    3187               0 :             continue;
    3188                 :         }
    3189                 : 
    3190               0 :         if (packetlength != pg_ntoh16(receivepacket->length))
    3191                 :         {
    3192               0 :             ereport(LOG,
    3193                 :                     (errmsg("RADIUS response from %s has corrupt length: %d (actual length %d)",
    3194                 :                             server, pg_ntoh16(receivepacket->length), packetlength)));
    3195               0 :             continue;
    3196                 :         }
    3197                 : 
    3198               0 :         if (packet->id != receivepacket->id)
    3199                 :         {
    3200               0 :             ereport(LOG,
    3201                 :                     (errmsg("RADIUS response from %s is to a different request: %d (should be %d)",
    3202                 :                             server, receivepacket->id, packet->id)));
    3203               0 :             continue;
    3204                 :         }
    3205                 : 
    3206                 :         /*
    3207                 :          * Verify the response authenticator, which is calculated as
    3208                 :          * MD5(Code+ID+Length+RequestAuthenticator+Attributes+Secret)
    3209                 :          */
    3210               0 :         cryptvector = palloc(packetlength + strlen(secret));
    3211                 : 
    3212               0 :         memcpy(cryptvector, receivepacket, 4);  /* code+id+length */
    3213               0 :         memcpy(cryptvector + 4, packet->vector, RADIUS_VECTOR_LENGTH);   /* request
    3214                 :                                                                          * authenticator, from
    3215                 :                                                                          * original packet */
    3216               0 :         if (packetlength > RADIUS_HEADER_LENGTH) /* there may be no
    3217                 :                                                      * attributes at all */
    3218               0 :             memcpy(cryptvector + RADIUS_HEADER_LENGTH, receive_buffer + RADIUS_HEADER_LENGTH, packetlength - RADIUS_HEADER_LENGTH);
    3219               0 :         memcpy(cryptvector + packetlength, secret, strlen(secret));
    3220                 : 
    3221               0 :         if (!pg_md5_binary(cryptvector,
    3222               0 :                            packetlength + strlen(secret),
    3223                 :                            encryptedpassword, &errstr))
    3224                 :         {
    3225               0 :             ereport(LOG,
    3226                 :                     (errmsg("could not perform MD5 encryption of received packet: %s",
    3227                 :                             errstr)));
    3228               0 :             pfree(cryptvector);
    3229               0 :             continue;
    3230                 :         }
    3231               0 :         pfree(cryptvector);
    3232                 : 
    3233               0 :         if (memcmp(receivepacket->vector, encryptedpassword, RADIUS_VECTOR_LENGTH) != 0)
    3234                 :         {
    3235               0 :             ereport(LOG,
    3236                 :                     (errmsg("RADIUS response from %s has incorrect MD5 signature",
    3237                 :                             server)));
    3238               0 :             continue;
    3239                 :         }
    3240                 : 
    3241               0 :         if (receivepacket->code == RADIUS_ACCESS_ACCEPT)
    3242                 :         {
    3243               0 :             closesocket(sock);
    3244               0 :             return STATUS_OK;
    3245                 :         }
    3246               0 :         else if (receivepacket->code == RADIUS_ACCESS_REJECT)
    3247                 :         {
    3248               0 :             closesocket(sock);
    3249               0 :             return STATUS_EOF;
    3250                 :         }
    3251                 :         else
    3252                 :         {
    3253               0 :             ereport(LOG,
    3254                 :                     (errmsg("RADIUS response from %s has invalid code (%d) for user \"%s\"",
    3255                 :                             server, receivepacket->code, user_name)));
    3256               0 :             continue;
    3257                 :         }
    3258                 :     }                           /* while (true) */
    3259                 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a