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 17:13:01 Functions: 66.7 % 24 16 1 7 16 8 13 3
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 [..60] days: 33.3 % 3 1 2 1
Legend: Lines: hit not hit (120,180] days: 100.0 % 3 3 3
(180,240] days: 55.6 % 9 5 4 5
(240..) days: 38.5 % 881 339 1 37 342 162 33 224 82 346 215
Function coverage date bins:
[..60] days: 0.0 % 1 0 1
(240..) days: 36.4 % 44 16 7 16 8 13

 Age         Owner                  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.
 5364 magnus                    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
  453 michael                   247 GIC          50 : auth_failed(Port *port, int status, const char *logdetail)
                                248                 : {
                                249                 :     const char *errstr;
                                250                 :     char       *cdetail;
 4660 bruce                     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
 5364 magnus                    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                 :      */
 5364 magnus                    263 GBC          50 :     if (status == STATUS_EOF)
 5364 magnus                    264 GIC          21 :         proc_exit(0);
 8352 bruce                     265 EUB             : 
 5319 magnus                    266 GBC          29 :     switch (port->hba->auth_method)
 8053 bruce                     267 ECB             :     {
 5364 magnus                    268 LBC           0 :         case uaReject:
 4736 tgl                       269 ECB             :         case uaImplicitReject:
 5364 magnus                    270 UBC           0 :             errstr = gettext_noop("authentication failed for user \"%s\": host rejected");
                                271               0 :             break;
 5364 magnus                    272 GBC           1 :         case uaTrust:
 5364 magnus                    273 CBC           1 :             errstr = gettext_noop("\"trust\" authentication failed for user \"%s\"");
                                274               1 :             break;
 5364 magnus                    275 LBC           0 :         case uaIdent:
                                276               0 :             errstr = gettext_noop("Ident authentication failed for user \"%s\"");
 5364 magnus                    277 UIC           0 :             break;
 4404 magnus                    278 GIC           6 :         case uaPeer:
 4404 magnus                    279 CBC           6 :             errstr = gettext_noop("Peer authentication failed for user \"%s\"");
 4404 magnus                    280 GIC           6 :             break;
 5364 magnus                    281 CBC           5 :         case uaPassword:
 4701 tgl                       282 ECB             :         case uaMD5:
 2207 heikki.linnakangas        283                 :         case uaSCRAM:
 5364 magnus                    284 CBC           5 :             errstr = gettext_noop("password authentication failed for user \"%s\"");
 4775 bruce                     285 ECB             :             /* We use it to indicate if a .pgpass password failed. */
 4775 bruce                     286 GBC           5 :             errcode_return = ERRCODE_INVALID_PASSWORD;
 5364 magnus                    287               5 :             break;
 4701 tgl                       288               4 :         case uaGSS:
                                289               4 :             errstr = gettext_noop("GSSAPI authentication failed for user \"%s\"");
                                290               4 :             break;
 4701 tgl                       291 UBC           0 :         case uaSSPI:
                                292               0 :             errstr = gettext_noop("SSPI authentication failed for user \"%s\"");
                                293               0 :             break;
 5364 magnus                    294               0 :         case uaPAM:
 5364 magnus                    295 LBC           0 :             errstr = gettext_noop("PAM authentication failed for user \"%s\"");
                                296               0 :             break;
 2557 tgl                       297               0 :         case uaBSD:
                                298               0 :             errstr = gettext_noop("BSD authentication failed for user \"%s\"");
                                299               0 :             break;
 5364 magnus                    300 CBC          12 :         case uaLDAP:
 5364 magnus                    301 GBC          12 :             errstr = gettext_noop("LDAP authentication failed for user \"%s\"");
                                302              12 :             break;
 4701 tgl                       303               1 :         case uaCert:
                                304               1 :             errstr = gettext_noop("certificate authentication failed for user \"%s\"");
                                305               1 :             break;
 4820 magnus                    306 UBC           0 :         case uaRADIUS:
 4820 magnus                    307 UIC           0 :             errstr = gettext_noop("RADIUS authentication failed for user \"%s\"");
                                308               0 :             break;
 5364 magnus                    309 LBC           0 :         default:
                                310               0 :             errstr = gettext_noop("authentication failed for user \"%s\": invalid authentication method");
                                311               0 :             break;
 8053 bruce                     312 ECB             :     }
 9345                           313                 : 
  165 michael                   314 GNC          29 :     cdetail = psprintf(_("Connection matched %s line %d: \"%s\""),
                                315              29 :                        port->hba->sourcefile, port->hba->linenumber,
                                316              29 :                        port->hba->rawline);
 3324 sfrost                    317 GIC          29 :     if (logdetail)
 3324 sfrost                    318 CBC           1 :         logdetail = psprintf("%s\n%s", logdetail, cdetail);
                                319                 :     else
 3324 sfrost                    320 GIC          28 :         logdetail = cdetail;
                                321                 : 
 3359 tgl                       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.
  732 michael                   343 ECB             :  */
                                344                 : static void
  732 michael                   345 CBC         124 : set_authn_id(Port *port, const char *id)
                                346                 : {
  732 michael                   347 GIC         124 :     Assert(id);
                                348                 : 
  228 michael                   349 GNC         124 :     if (MyClientConnectionInfo.authn_id)
                                350                 :     {
                                351                 :         /*
                                352                 :          * An existing authn_id should never be overwritten; that means two
  732 michael                   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                 :          */
  732 michael                   357 UIC           0 :         ereport(FATAL,
                                358                 :                 (errmsg("authentication identifier set more than once"),
  570 peter                     359 ECB             :                  errdetail_log("previous identifier: \"%s\"; new identifier: \"%s\"",
                                360                 :                                MyClientConnectionInfo.authn_id, id)));
                                361                 :     }
  732 michael                   362                 : 
  228 michael                   363 GNC         124 :     MyClientConnectionInfo.authn_id = MemoryContextStrdup(TopMemoryContext, id);
                                364             124 :     MyClientConnectionInfo.auth_method = port->hba->auth_method;
  732 michael                   365 ECB             : 
  732 michael                   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.
 5364 magnus                    381 ECB             :  */
                                382                 : void
 5364 magnus                    383 CBC        8601 : ClientAuthentication(Port *port)
 5364 magnus                    384 ECB             : {
 5364 magnus                    385 GIC        8601 :     int         status = STATUS_ERROR;
  453 michael                   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
 3955 bruce                     392 ECB             :      * server logfile if parsing the hba config file failed.
                                393                 :      */
 4311 alvherre                  394 CBC        8601 :     hba_getauthmethod(port);
                                395                 : 
 4971 tgl                       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
 5050 bruce                     401 ECB             :      * options field that should be done *before* the authentication here.
                                402                 :      */
 1492 magnus                    403 GIC        8601 :     if (port->hba->clientcert != clientCertOff)
 5253 magnus                    404 ECB             :     {
 2288 tgl                       405 EUB             :         /* If we haven't loaded a root certificate store, fail */
 2288 tgl                       406 GIC          30 :         if (!secure_loaded_verify_locations())
 2288 tgl                       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
 5253 magnus                    415 ECB             :          * already if it didn't verify ok.
                                416                 :          */
 3163 heikki.linnakangas        417 GIC          30 :         if (!port->peer_cert_valid)
 5253 magnus                    418               2 :             ereport(FATAL,
                                419                 :                     (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
                                420                 :                      errmsg("connection requires a valid client certificate")));
                                421                 :     }
                                422                 : 
                                423                 :     /*
 5253 magnus                    424 ECB             :      * Now proceed to do the actual authentication check
                                425                 :      */
 5319 magnus                    426 GBC        8599 :     switch (port->hba->auth_method)
                                427                 :     {
 5364 magnus                    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];
  832 tgl                       442 EUB             :                 const char *encryption_state;
                                443                 : 
 4738 simon                     444 UIC           0 :                 pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
                                445                 :                                    hostinfo, sizeof(hostinfo),
                                446                 :                                    NULL, 0,
 4738 simon                     447 EUB             :                                    NI_NUMERICHOST);
                                448                 : 
  832 tgl                       449 UBC           0 :                 encryption_state =
                                450                 : #ifdef ENABLE_GSS
  832 tgl                       451 UIC           0 :                     (port->gss && port->gss->enc) ? _("GSS encryption") :
  832 tgl                       452 EUB             : #endif
                                453                 : #ifdef USE_SSL
  832 tgl                       454 UBC           0 :                     port->ssl_in_use ? _("SSL encryption") :
                                455                 : #endif
                                456               0 :                     _("no encryption");
  832 tgl                       457 EUB             : 
  775 akapila                   458 UIC           0 :                 if (am_walsender && !am_db_walsender)
 4736 tgl                       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,
  832 tgl                       464 EUB             :                                     encryption_state)));
                                465                 :                 else
 4736 tgl                       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;
 4738 simon                     474 ECB             :             }
                                475                 : 
 4738 simon                     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];
  832 tgl                       488 ECB             :                 const char *encryption_state;
                                489                 : 
 5364 magnus                    490 GIC          10 :                 pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
                                491                 :                                    hostinfo, sizeof(hostinfo),
                                492                 :                                    NULL, 0,
 5364 magnus                    493 ECB             :                                    NI_NUMERICHOST);
                                494                 : 
  832 tgl                       495 CBC           8 :                 encryption_state =
                                496                 : #ifdef ENABLE_GSS
  832 tgl                       497 GIC          10 :                     (port->gss && port->gss->enc) ? _("GSS encryption") :
  832 tgl                       498 ECB             : #endif
                                499                 : #ifdef USE_SSL
  832 tgl                       500 CBC           8 :                     port->ssl_in_use ? _("SSL encryption") :
                                501                 : #endif
  832 tgl                       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)) : \
 3294 tgl                       523 ECB             :                     0))
 4270 peter_e                   524 EUB             : 
  775 akapila                   525 GIC          10 :                 if (am_walsender && !am_db_walsender)
 4736 tgl                       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),
 2118 tgl                       532 ECB             :                              HOSTNAME_LOOKUP_DETAIL(port)));
                                533                 :                 else
 4736 tgl                       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;
 5630 magnus                    543 ECB             :             }
                                544                 : 
 5364 magnus                    545 GIC          21 :         case uaGSS:
 5281 magnus                    546 ECB             : #ifdef ENABLE_GSS
  832 tgl                       547                 :             /* We might or might not have the gss workspace already */
  832 tgl                       548 CBC          21 :             if (port->gss == NULL)
  832 tgl                       549 GIC           6 :                 port->gss = (pg_gssinfo *)
  832 tgl                       550 CBC           6 :                     MemoryContextAllocZero(TopMemoryContext,
                                551                 :                                            sizeof(pg_gssinfo));
 1467 sfrost                    552 GIC          21 :             port->gss->auth = true;
                                553                 : 
                                554                 :             /*
                                555                 :              * If GSS state was set up while enabling encryption, we can just
  832 tgl                       556 ECB             :              * check the client's principal.  Otherwise, ask for it.
                                557                 :              */
 1467 sfrost                    558 GIC          21 :             if (port->gss->enc)
                                559              15 :                 status = pg_GSS_checkauth(port);
 1467 sfrost                    560 ECB             :             else
                                561                 :             {
 1467 sfrost                    562 GIC           6 :                 sendAuthRequest(port, AUTH_REQ_GSS, NULL, 0);
                                563               6 :                 status = pg_GSS_recvauth(port);
                                564                 :             }
                                565                 : #else
 5281 magnus                    566 ECB             :             Assert(false);
                                567                 : #endif
 5364 magnus                    568 GBC          21 :             break;
                                569                 : 
 5364 magnus                    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);
 5364 magnus                    577 EUB             :             status = pg_SSPI_recvauth(port);
                                578                 : #else
 5281 magnus                    579 UIC           0 :             Assert(false);
                                580                 : #endif
 5364 magnus                    581 ECB             :             break;
 8352 bruce                     582                 : 
 4404 magnus                    583 CBC          26 :         case uaPeer:
 4404 magnus                    584 GIC          26 :             status = auth_peer(port);
 4404 magnus                    585 GBC          26 :             break;
 4404 magnus                    586 EUB             : 
 4404 magnus                    587 UBC           0 :         case uaIdent:
 4404 magnus                    588 UIC           0 :             status = ident_inet(port);
 5364 magnus                    589 LBC           0 :             break;
                                590                 : 
 5364 magnus                    591 CBC          50 :         case uaMD5:
 2207 heikki.linnakangas        592 ECB             :         case uaSCRAM:
 2207 heikki.linnakangas        593 GIC          50 :             status = CheckPWChallengeAuth(port, &logdetail);
 5364 magnus                    594 CBC          50 :             break;
 5364 magnus                    595 ECB             : 
 5364 magnus                    596 CBC          17 :         case uaPassword:
 2316 heikki.linnakangas        597 GIC          17 :             status = CheckPasswordAuth(port, &logdetail);
 5364 magnus                    598 GBC          17 :             break;
                                599                 : 
 5364 magnus                    600 UBC           0 :         case uaPAM:
                                601                 : #ifdef USE_PAM
 5364 magnus                    602 UIC           0 :             status = CheckPAMAuth(port, port->user_name, "");
                                603                 : #else
 5281 magnus                    604 EUB             :             Assert(false);
                                605                 : #endif                          /* USE_PAM */
 5281 magnus                    606 UBC           0 :             break;
                                607                 : 
 2557 tgl                       608 UIC           0 :         case uaBSD:
                                609                 : #ifdef USE_BSD_AUTH
 2557 tgl                       610 EUB             :             status = CheckBSDAuth(port, port->user_name);
                                611                 : #else
 2557 tgl                       612 UIC           0 :             Assert(false);
                                613                 : #endif                          /* USE_BSD_AUTH */
 2557 tgl                       614 ECB             :             break;
                                615                 : 
 5364 magnus                    616 CBC          26 :         case uaLDAP:
                                617                 : #ifdef USE_LDAP
 5364 magnus                    618 GIC          26 :             status = CheckLDAPAuth(port);
                                619                 : #else
 5281 magnus                    620 ECB             :             Assert(false);
 5253 magnus                    621 EUB             : #endif
 5253 magnus                    622 GBC          26 :             break;
 4820 magnus                    623 UBC           0 :         case uaRADIUS:
 4820 magnus                    624 LBC           0 :             status = CheckRADIUSAuth(port);
 4820 magnus                    625 UIC           0 :             break;
 1492 magnus                    626 GIC        8449 :         case uaCert:
 1492 magnus                    627 ECB             :             /* uaCert will be treated as if clientcert=verify-full (uaTrust) */
 5364                           628                 :         case uaTrust:
 5364 magnus                    629 GIC        8449 :             status = STATUS_OK;
                                630            8449 :             break;
 5364 magnus                    631 ECB             :     }
                                632                 : 
 1492 magnus                    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.
 1492 magnus                    639 ECB             :          */
                                640                 : #ifdef USE_SSL
 1492 magnus                    641 GIC          27 :         status = CheckCertAuth(port);
                                642                 : #else
                                643                 :         Assert(false);
                                644                 : #endif
 1492 magnus                    645 ECB             :     }
 1492 magnus                    646 EUB             : 
 4548 rhaas                     647 GIC        8589 :     if (ClientAuthentication_hook)
 4382 bruce                     648 LBC           0 :         (*ClientAuthentication_hook) (port, status);
 4548 rhaas                     649 ECB             : 
 5364 magnus                    650 GIC        8589 :     if (status == STATUS_OK)
 2425 heikki.linnakangas        651 CBC        8539 :         sendAuthRequest(port, AUTH_REQ_OK, NULL, 0);
 5364 magnus                    652 ECB             :     else
 3359 tgl                       653 GIC          50 :         auth_failed(port, status, logdetail);
 5364 magnus                    654            8539 : }
                                655                 : 
                                656                 : 
                                657                 : /*
                                658                 :  * Send an authentication request packet to the frontend.
 5364 magnus                    659 ECB             :  */
                                660                 : void
 1986 peter_e                   661 GIC        8699 : sendAuthRequest(Port *port, AuthRequest areq, const char *extradata, int extralen)
                                662                 : {
 5364 magnus                    663 ECB             :     StringInfoData buf;
                                664                 : 
 2987 andres                    665 CBC        8699 :     CHECK_FOR_INTERRUPTS();
 2987 andres                    666 ECB             : 
 5364 magnus                    667 CBC        8699 :     pq_beginmessage(&buf, 'R');
 2006 andres                    668            8699 :     pq_sendint32(&buf, (int32) areq);
 2425 heikki.linnakangas        669 GIC        8699 :     if (extralen > 0)
 2425 heikki.linnakangas        670 CBC         111 :         pq_sendbytes(&buf, extradata, extralen);
                                671                 : 
 5364 magnus                    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
 2187 heikki.linnakangas        677 ECB             :      * queries.
 5624 bruce                     678                 :      */
 2187 heikki.linnakangas        679 GIC        8699 :     if (areq != AUTH_REQ_OK && areq != AUTH_REQ_SASL_FIN)
 5364 magnus                    680 CBC         134 :         pq_flush();
 2987 andres                    681 ECB             : 
 2987 andres                    682 GIC        8699 :     CHECK_FOR_INTERRUPTS();
 5752 magnus                    683            8699 : }
                                684                 : 
                                685                 : /*
                                686                 :  * Collect password response packet from frontend.
                                687                 :  *
                                688                 :  * Returns NULL if couldn't get password, else palloc'd string.
 5364 magnus                    689 ECB             :  */
                                690                 : static char *
 5364 magnus                    691 GIC          56 : recv_password_packet(Port *port)
                                692                 : {
                                693                 :     StringInfoData buf;
  766 heikki.linnakangas        694 ECB             :     int         mtype;
                                695                 : 
 2988 heikki.linnakangas        696 GIC          56 :     pq_startmsgread();
 5548 tgl                       697 ECB             : 
  766 heikki.linnakangas        698                 :     /* Expect 'p' message type */
  766 heikki.linnakangas        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
  697 tgl                       705 ECB             :          * commonly done by psql, so complaining just clutters the log.
  766 heikki.linnakangas        706 EUB             :          */
  766 heikki.linnakangas        707 GIC          15 :         if (mtype != EOF)
  766 heikki.linnakangas        708 UIC           0 :             ereport(ERROR,
                                709                 :                     (errcode(ERRCODE_PROTOCOL_VIOLATION),
  766 heikki.linnakangas        710 ECB             :                      errmsg("expected password response, got message type %d",
                                711                 :                             mtype)));
  697 tgl                       712 GIC          15 :         return NULL;            /* EOF or bad message type */
 5364 magnus                    713 ECB             :     }
 5752                           714                 : 
 5364 magnus                    715 GIC          41 :     initStringInfo(&buf);
  711 tgl                       716              41 :     if (pq_getmessage(&buf, PG_MAX_AUTH_TOKEN_LENGTH))  /* receive password */
 5364 magnus                    717 EUB             :     {
                                718                 :         /* EOF - pq_getmessage already logged a suitable message */
 5364 magnus                    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
 5364 magnus                    726 ECB             :      * StringInfo is guaranteed to have an appended '\0'.
 5752 magnus                    727 EUB             :      */
 5364 magnus                    728 GIC          41 :     if (strlen(buf.data) + 1 != buf.len)
 2131 heikki.linnakangas        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
 2071 heikki.linnakangas        744 ECB             :      * system, like PAM, LDAP and RADIUS.
 2071 heikki.linnakangas        745 EUB             :      */
 2071 heikki.linnakangas        746 GIC          41 :     if (buf.len == 1)
 2071 heikki.linnakangas        747 UIC           0 :         ereport(ERROR,
                                748                 :                 (errcode(ERRCODE_INVALID_PASSWORD),
                                749                 :                  errmsg("empty password returned by client")));
 2071 heikki.linnakangas        750 ECB             : 
                                751                 :     /* Do not echo password to logs, for security. */
 2701 peter_e                   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
 5364 magnus                    757 ECB             :      * encoding, there wouldn't be much point.
                                758                 :      */
 5364 magnus                    759 GIC          41 :     return buf.data;
                                760                 : }
                                761                 : 
                                762                 : 
                                763                 : /*----------------------------------------------------------------
                                764                 :  * Password-based authentication mechanisms
                                765                 :  *----------------------------------------------------------------
                                766                 :  */
                                767                 : 
                                768                 : /*
                                769                 :  * Plaintext password authentication.
 2207 heikki.linnakangas        770 ECB             :  */
                                771                 : static int
  453 michael                   772 GIC          17 : CheckPasswordAuth(Port *port, const char **logdetail)
                                773                 : {
                                774                 :     char       *passwd;
                                775                 :     int         result;
 2207 heikki.linnakangas        776 ECB             :     char       *shadow_pass;
                                777                 : 
 2207 heikki.linnakangas        778 CBC          17 :     sendAuthRequest(port, AUTH_REQ_PASSWORD, NULL, 0);
 2316 heikki.linnakangas        779 ECB             : 
 2316 heikki.linnakangas        780 CBC          17 :     passwd = recv_password_packet(port);
 2316 heikki.linnakangas        781 GIC          17 :     if (passwd == NULL)
 2316 heikki.linnakangas        782 CBC           7 :         return STATUS_EOF;      /* client wouldn't send password */
 2316 heikki.linnakangas        783 ECB             : 
 2207 heikki.linnakangas        784 GIC          10 :     shadow_pass = get_role_password(port->user_name, logdetail);
 2207 heikki.linnakangas        785 CBC          10 :     if (shadow_pass)
                                786                 :     {
 2207 heikki.linnakangas        787 GIC          10 :         result = plain_crypt_verify(port->user_name, shadow_pass, passwd,
                                788                 :                                     logdetail);
 2207 heikki.linnakangas        789 EUB             :     }
                                790                 :     else
 2207 heikki.linnakangas        791 LBC           0 :         result = STATUS_ERROR;
 2316 heikki.linnakangas        792 ECB             : 
 2309 heikki.linnakangas        793 CBC          10 :     if (shadow_pass)
 2309 heikki.linnakangas        794 GIC          10 :         pfree(shadow_pass);
 2316 heikki.linnakangas        795 CBC          10 :     pfree(passwd);
 2316 heikki.linnakangas        796 ECB             : 
  732 michael                   797 GIC          10 :     if (result == STATUS_OK)
  732 michael                   798 CBC          10 :         set_authn_id(port, port->user_name);
                                799                 : 
 2316 heikki.linnakangas        800 GIC          10 :     return result;
                                801                 : }
                                802                 : 
                                803                 : /*
                                804                 :  * MD5 and SCRAM authentication.
 5364 magnus                    805 ECB             :  */
                                806                 : static int
  453 michael                   807 GIC          50 : CheckPWChallengeAuth(Port *port, const char **logdetail)
                                808                 : {
                                809                 :     int         auth_result;
                                810                 :     char       *shadow_pass;
 2207 heikki.linnakangas        811 ECB             :     PasswordType pwtype;
                                812                 : 
 2207 heikki.linnakangas        813 GIC          50 :     Assert(port->hba->auth_method == uaSCRAM ||
                                814                 :            port->hba->auth_method == uaMD5);
 2207 heikki.linnakangas        815 ECB             : 
                                816                 :     /* First look up the user's password. */
 2207 heikki.linnakangas        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
 2153 bruce                     826 ECB             :      * had a password of that type, too, it "blends in" best.
 2207 heikki.linnakangas        827 EUB             :      */
 2207 heikki.linnakangas        828 GIC          50 :     if (!shadow_pass)
 2207 heikki.linnakangas        829 LBC           0 :         pwtype = Password_encryption;
                                830                 :     else
 2207 heikki.linnakangas        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
  641 michael                   841 ECB             :      * fail.
 2207 heikki.linnakangas        842                 :      */
 2207 heikki.linnakangas        843 GIC          50 :     if (port->hba->auth_method == uaMD5 && pwtype == PASSWORD_TYPE_MD5)
 2207 heikki.linnakangas        844 CBC          13 :         auth_result = CheckMD5Auth(port, shadow_pass, logdetail);
                                845                 :     else
  641 michael                   846 GIC          37 :         auth_result = CheckSASLAuth(&pg_be_scram_mech, port, shadow_pass,
  641 michael                   847 ECB             :                                     logdetail);
 2207 heikki.linnakangas        848                 : 
 2207 heikki.linnakangas        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
 2207 heikki.linnakangas        854 ECB             :      * authentication succeeded.
                                855                 :      */
 2207 heikki.linnakangas        856 GBC          50 :     if (!shadow_pass)
 2207 heikki.linnakangas        857 EUB             :     {
 2207 heikki.linnakangas        858 UIC           0 :         Assert(auth_result != STATUS_OK);
                                859               0 :         return STATUS_ERROR;
 2207 heikki.linnakangas        860 ECB             :     }
  732 michael                   861                 : 
  732 michael                   862 GIC          50 :     if (auth_result == STATUS_OK)
  732 michael                   863 CBC          32 :         set_authn_id(port, port->user_name);
                                864                 : 
 2207 heikki.linnakangas        865 GIC          50 :     return auth_result;
                                866                 : }
 2316 heikki.linnakangas        867 ECB             : 
                                868                 : static int
  453 michael                   869 GIC          13 : CheckMD5Auth(Port *port, char *shadow_pass, const char **logdetail)
                                870                 : {
                                871                 :     char        md5Salt[4];     /* Password salt */
                                872                 :     char       *passwd;
 5364 magnus                    873 ECB             :     int         result;
 5752 magnus                    874 EUB             : 
 2207 heikki.linnakangas        875 GIC          13 :     if (Db_user_namespace)
 2207 heikki.linnakangas        876 UIC           0 :         ereport(FATAL,
                                877                 :                 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
                                878                 :                  errmsg("MD5 authentication is not supported when \"db_user_namespace\" is enabled")));
 2207 heikki.linnakangas        879 ECB             : 
                                880                 :     /* include the salt to use for computing the response */
 1559 michael                   881 GBC          13 :     if (!pg_strong_random(md5Salt, 4))
                                882                 :     {
 2207 heikki.linnakangas        883 UBC           0 :         ereport(LOG,
                                884                 :                 (errmsg("could not generate random MD5 salt")));
 2207 heikki.linnakangas        885 UIC           0 :         return STATUS_ERROR;
 2207 heikki.linnakangas        886 ECB             :     }
                                887                 : 
 2207 heikki.linnakangas        888 CBC          13 :     sendAuthRequest(port, AUTH_REQ_MD5, md5Salt, 4);
 2316 heikki.linnakangas        889 ECB             : 
 5364 magnus                    890 CBC          13 :     passwd = recv_password_packet(port);
 5364 magnus                    891 GIC          13 :     if (passwd == NULL)
 5364 magnus                    892 CBC           7 :         return STATUS_EOF;      /* client wouldn't send password */
 5752 magnus                    893 ECB             : 
 2309 heikki.linnakangas        894 GIC           6 :     if (shadow_pass)
 2207                           895               6 :         result = md5_crypt_verify(port->user_name, shadow_pass, passwd,
 2207 heikki.linnakangas        896 EUB             :                                   md5Salt, 4, logdetail);
                                897                 :     else
 2207 heikki.linnakangas        898 LBC           0 :         result = STATUS_ERROR;
                                899                 : 
 5364 magnus                    900 CBC           6 :     pfree(passwd);
                                901                 : 
 5364 magnus                    902 GIC           6 :     return result;
                                903                 : }
                                904                 : 
                                905                 : 
                                906                 : /*----------------------------------------------------------------
                                907                 :  * GSSAPI authentication system
                                908                 :  *----------------------------------------------------------------
                                909                 :  */
 5364 magnus                    910 ECB             : #ifdef ENABLE_GSS
                                911                 : static int
 5364 magnus                    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
  830 tgl                       924 ECB             :      * doesn't support the cred store extensions, so use the env var.
                                925                 :      */
  830 tgl                       926 CBC           6 :     if (pg_krb_server_keyfile != NULL && pg_krb_server_keyfile[0] != '\0')
                                927                 :     {
  830 tgl                       928 GIC           6 :         if (setenv("KRB5_KTNAME", pg_krb_server_keyfile, 1) != 0)
 5364 magnus                    929 EUB             :         {
                                930                 :             /* The only likely failure cause is OOM, so use that errcode */
  830 tgl                       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
 5364 magnus                    941 ECB             :      * any vector of attack.
                                942                 :      */
 5364 magnus                    943 GIC           6 :     port->gss->cred = GSS_C_NO_CREDENTIAL;
                                944                 : 
                                945                 :     /*
 5364 magnus                    946 ECB             :      * Initialize sequence with an empty context
                                947                 :      */
 5364 magnus                    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                 :      */
 5364 magnus                    956 ECB             :     do
                                957                 :     {
 2988 heikki.linnakangas        958 CBC           6 :         pq_startmsgread();
                                959                 : 
 2987 andres                    960               6 :         CHECK_FOR_INTERRUPTS();
 2987 andres                    961 ECB             : 
 5364 magnus                    962 GIC           6 :         mtype = pq_getbyte();
                                963               6 :         if (mtype != 'p')
 5364 magnus                    964 ECB             :         {
 5364 magnus                    965 EUB             :             /* Only log error if client didn't disconnect. */
 5364 magnus                    966 GIC           2 :             if (mtype != EOF)
 2131 heikki.linnakangas        967 UIC           0 :                 ereport(ERROR,
                                968                 :                         (errcode(ERRCODE_PROTOCOL_VIOLATION),
 5364 magnus                    969 ECB             :                          errmsg("expected GSS response, got message type %d",
                                970                 :                                 mtype)));
 5364 magnus                    971 GIC           2 :             return STATUS_ERROR;
                                972                 :         }
 5364 magnus                    973 ECB             : 
                                974                 :         /* Get the actual GSS token */
 5364 magnus                    975 GIC           4 :         initStringInfo(&buf);
 4925 heikki.linnakangas        976               4 :         if (pq_getmessage(&buf, PG_MAX_AUTH_TOKEN_LENGTH))
 5364 magnus                    977 EUB             :         {
                                978                 :             /* EOF - pq_getmessage already logged error */
 5364 magnus                    979 UIC           0 :             pfree(buf.data);
                                980               0 :             return STATUS_ERROR;
                                981                 :         }
 5364 magnus                    982 ECB             : 
                                983                 :         /* Map to GSSAPI style buffer */
 5364 magnus                    984 GIC           4 :         gbuf.length = buf.len;
 5364 magnus                    985 CBC           4 :         gbuf.value = buf.data;
                                986                 : 
 1251 tgl                       987 GIC           4 :         elog(DEBUG4, "processing received GSS token of length %u",
 5364 magnus                    988 ECB             :              (unsigned int) gbuf.length);
                                989                 : 
 1165 alvherre                  990 CBC           4 :         maj_stat = gss_accept_sec_context(&min_stat,
 5364 magnus                    991 GIC           4 :                                           &port->gss->ctx,
                                992               4 :                                           port->gss->cred,
 5364 magnus                    993 ECB             :                                           &gbuf,
                                994                 :                                           GSS_C_NO_CHANNEL_BINDINGS,
 5364 magnus                    995 CBC           4 :                                           &port->gss->name,
                                996                 :                                           NULL,
 5364 magnus                    997 GIC           4 :                                           &port->gss->outbuf,
                                998                 :                                           &gflags,
                                999                 :                                           NULL,
                               1000                 :                                           NULL);
 5364 magnus                   1001 ECB             : 
                               1002                 :         /* gbuf no longer used */
 5364 magnus                   1003 CBC           4 :         pfree(buf.data);
                               1004                 : 
  578 peter                    1005 GIC           4 :         elog(DEBUG5, "gss_accept_sec_context major: %u, "
                               1006                 :              "minor: %u, outlen: %u, outflags: %x",
                               1007                 :              maj_stat, min_stat,
 5364 magnus                   1008 ECB             :              (unsigned int) port->gss->outbuf.length, gflags);
                               1009                 : 
 2987 andres                   1010 CBC           4 :         CHECK_FOR_INTERRUPTS();
                               1011                 : 
 5364 magnus                   1012 GIC           4 :         if (port->gss->outbuf.length != 0)
                               1013                 :         {
                               1014                 :             /*
 5364 magnus                   1015 ECB             :              * Negotiation generated data to be sent to the client.
                               1016                 :              */
 5364 magnus                   1017 GIC           4 :             elog(DEBUG4, "sending GSS response token of length %u",
 5364 magnus                   1018 ECB             :                  (unsigned int) port->gss->outbuf.length);
                               1019                 : 
 2425 heikki.linnakangas       1020 GIC           4 :             sendAuthRequest(port, AUTH_REQ_GSS_CONT,
 2118 tgl                      1021 CBC           4 :                             port->gss->outbuf.value, port->gss->outbuf.length);
                               1022                 : 
 5364 magnus                   1023 GIC           4 :             gss_release_buffer(&lmin_s, &port->gss->outbuf);
 5364 magnus                   1024 ECB             :         }
                               1025                 : 
 5364 magnus                   1026 GBC           4 :         if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
 5364 magnus                   1027 EUB             :         {
 5364 magnus                   1028 UIC           0 :             gss_delete_sec_context(&lmin_s, &port->gss->ctx, GSS_C_NO_BUFFER);
  832 tgl                      1029 UBC           0 :             pg_GSS_error(_("accepting GSS security context failed"),
                               1030                 :                          maj_stat, min_stat);
  832 tgl                      1031 UIC           0 :             return STATUS_ERROR;
 5364 magnus                   1032 ECB             :         }
 5364 magnus                   1033 EUB             : 
 5364 magnus                   1034 GIC           4 :         if (maj_stat == GSS_S_CONTINUE_NEEDED)
 5364 magnus                   1035 LBC           0 :             elog(DEBUG4, "GSS continue needed");
                               1036                 : 
 5364 magnus                   1037 CBC           4 :     } while (maj_stat == GSS_S_CONTINUE_NEEDED);
                               1038                 : 
 5364 magnus                   1039 GIC           4 :     if (port->gss->cred != GSS_C_NO_CREDENTIAL)
                               1040                 :     {
                               1041                 :         /*
 5364 magnus                   1042 EUB             :          * Release service principal credentials
                               1043                 :          */
 5364 magnus                   1044 LBC           0 :         gss_release_cred(&min_stat, &port->gss->cred);
                               1045                 :     }
 1467 sfrost                   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.
 1467 sfrost                   1052 ECB             :  */
                               1053                 : static int
 1467 sfrost                   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
 5364 magnus                   1065 ECB             :      * username that was specified for the connection.
                               1066                 :      */
 5364 magnus                   1067 GIC          19 :     maj_stat = gss_display_name(&min_stat, port->gss->name, &gbuf, NULL);
 5364 magnus                   1068 GBC          19 :     if (maj_stat != GSS_S_COMPLETE)
                               1069                 :     {
  832 tgl                      1070 UBC           0 :         pg_GSS_error(_("retrieving GSS user name failed"),
                               1071                 :                      maj_stat, min_stat);
  832 tgl                      1072 UIC           0 :         return STATUS_ERROR;
                               1073                 :     }
                               1074                 : 
                               1075                 :     /*
                               1076                 :      * gbuf.value might not be null-terminated, so turn it into a regular
  655 tgl                      1077 ECB             :      * null-terminated string.
                               1078                 :      */
  655 tgl                      1079 CBC          19 :     princ = palloc(gbuf.length + 1);
                               1080              19 :     memcpy(princ, gbuf.value, gbuf.length);
  655 tgl                      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
  732 michael                  1090 ECB             :      * succeeded and we want the log file to reflect that.
 1467 sfrost                   1091                 :      */
  655 tgl                      1092 GIC          19 :     port->gss->princ = MemoryContextStrdup(TopMemoryContext, princ);
                               1093              19 :     set_authn_id(port, princ);
                               1094                 : 
                               1095                 :     /*
 5364 magnus                   1096 ECB             :      * Split the username at the realm separator
                               1097                 :      */
  655 tgl                      1098 CBC          19 :     if (strchr(princ, '@'))
                               1099                 :     {
  655 tgl                      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
 5050 bruce                    1105 ECB             :          * realm. Then advance past the separator to check the realm.
 5205 magnus                   1106                 :          */
 5205 magnus                   1107 CBC          19 :         if (!port->hba->include_realm)
 5205 magnus                   1108 GIC           1 :             *cp = '\0';
 5364 magnus                   1109 CBC          19 :         cp++;
                               1110                 : 
 5203 magnus                   1111 GIC          19 :         if (port->hba->krb_realm != NULL && strlen(port->hba->krb_realm))
                               1112                 :         {
                               1113                 :             /*
 5364 magnus                   1114 EUB             :              * Match the realm part of the name first
                               1115                 :              */
 5364 magnus                   1116 UIC           0 :             if (pg_krb_caseins_users)
 5203 magnus                   1117 UBC           0 :                 ret = pg_strcasecmp(port->hba->krb_realm, cp);
                               1118                 :             else
                               1119               0 :                 ret = strcmp(port->hba->krb_realm, cp);
                               1120                 : 
 5364 magnus                   1121 UIC           0 :             if (ret)
 5364 magnus                   1122 EUB             :             {
                               1123                 :                 /* GSS realm does not match */
 5364 magnus                   1124 UIC           0 :                 elog(DEBUG2,
 2118 tgl                      1125 EUB             :                      "GSSAPI realm (%s) and configured realm (%s) don't match",
 5203 magnus                   1126                 :                      cp, port->hba->krb_realm);
  655 tgl                      1127 UIC           0 :                 pfree(princ);
 5364 magnus                   1128               0 :                 return STATUS_ERROR;
                               1129                 :             }
 5364 magnus                   1130 EUB             :         }
                               1131                 :     }
 5203 magnus                   1132 UBC           0 :     else if (port->hba->krb_realm && strlen(port->hba->krb_realm))
                               1133                 :     {
 5364                          1134               0 :         elog(DEBUG2,
 5364 magnus                   1135 EUB             :              "GSSAPI did not return realm but realm matching was requested");
  655 tgl                      1136 UIC           0 :         pfree(princ);
 5364 magnus                   1137               0 :         return STATUS_ERROR;
 5364 magnus                   1138 ECB             :     }
                               1139                 : 
  655 tgl                      1140 GIC          19 :     ret = check_usermap(port->hba->usermap, port->user_name, princ,
 5281 magnus                   1141 ECB             :                         pg_krb_caseins_users);
                               1142                 : 
  655 tgl                      1143 CBC          19 :     pfree(princ);
                               1144                 : 
 5065 magnus                   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);
 2557 magnus                   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 */
 5364                          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
 5364 magnus                   1570 UBC           0 : interpret_ident_response(const char *ident_response,
                               1571                 :                          char *ident_user)
 5364 magnus                   1572 EUB             : {
 2118 tgl                      1573 UBC           0 :     const char *cursor = ident_response;    /* Cursor into *ident_response */
 5364 magnus                   1574 EUB             : 
                               1575                 :     /*
                               1576                 :      * Ident's response, in the telnet tradition, should end in crlf (\r\n).
                               1577                 :      */
 5364 magnus                   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                 :     {
 5364 magnus                   1584 UBC           0 :         while (*cursor != ':' && *cursor != '\r')
                               1585               0 :             cursor++;           /* skip port field */
                               1586                 : 
 5364 magnus                   1587 UIC           0 :         if (*cursor != ':')
 5364 magnus                   1588 UBC           0 :             return false;
                               1589                 :         else
 5364 magnus                   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                 : 
 5364 magnus                   1595 UIC           0 :             cursor++;           /* Go over colon */
 5364 magnus                   1596 UBC           0 :             while (pg_isblank(*cursor))
                               1597               0 :                 cursor++;       /* skip blanks */
                               1598               0 :             i = 0;
 5364 magnus                   1599 UIC           0 :             while (*cursor != ':' && *cursor != '\r' && !pg_isblank(*cursor) &&
 5364 magnus                   1600 EUB             :                    i < (int) (sizeof(response_type) - 1))
 5364 magnus                   1601 UBC           0 :                 response_type[i++] = *cursor++;
                               1602               0 :             response_type[i] = '\0';
                               1603               0 :             while (pg_isblank(*cursor))
                               1604               0 :                 cursor++;       /* skip blanks */
 5364 magnus                   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 != ':')
 5364 magnus                   1622 UBC           0 :                         return false;
                               1623                 :                     else
 5364 magnus                   1624 EUB             :                     {
 2118 tgl                      1625 UBC           0 :                         cursor++;   /* Go over colon */
 5364 magnus                   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                 :                     }
 5364 magnus                   1635 EUB             :                 }
                               1636                 :             }
                               1637                 :         }
                               1638                 :     }
                               1639                 : }
                               1640                 : 
                               1641                 : 
                               1642                 : /*
 1350 michael                  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                 :  *
 2987 andres                   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
 4404 magnus                   1651 UIC           0 : ident_inet(hbaPort *port)
 5364 magnus                   1652 EUB             : {
 4404 magnus                   1653 UBC           0 :     const SockAddr remote_addr = port->raddr;
                               1654               0 :     const SockAddr local_addr = port->laddr;
 4404 magnus                   1655 EUB             :     char        ident_user[IDENT_USERNAME_MAX + 1];
 2118 tgl                      1656 UBC           0 :     pgsocket    sock_fd = PGINVALID_SOCKET; /* for talking to Ident server */
 3983 tgl                      1657 EUB             :     int         rc;             /* Return code from a locally called function */
 5364 magnus                   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];
 5364 magnus                   1666 UBC           0 :     struct addrinfo *ident_serv = NULL,
 5364 magnus                   1667 UIC           0 :                *la = NULL,
                               1668                 :                 hints;
 5364 magnus                   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                 :      */
 5364 magnus                   1674 UBC           0 :     pg_getnameinfo_all(&remote_addr.addr, remote_addr.salen,
 5364 magnus                   1675 EUB             :                        remote_addr_s, sizeof(remote_addr_s),
                               1676                 :                        remote_port, sizeof(remote_port),
                               1677                 :                        NI_NUMERICHOST | NI_NUMERICSERV);
 5364 magnus                   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),
 5364 magnus                   1681 EUB             :                        NI_NUMERICHOST | NI_NUMERICSERV);
                               1682                 : 
 5364 magnus                   1683 UIC           0 :     snprintf(ident_port, sizeof(ident_port), "%d", IDENT_PORT);
                               1684               0 :     hints.ai_flags = AI_NUMERICHOST;
 5364 magnus                   1685 UBC           0 :     hints.ai_family = remote_addr.addr.ss_family;
                               1686               0 :     hints.ai_socktype = SOCK_STREAM;
                               1687               0 :     hints.ai_protocol = 0;
 5364 magnus                   1688 UIC           0 :     hints.ai_addrlen = 0;
 5364 magnus                   1689 UBC           0 :     hints.ai_canonname = NULL;
 5364 magnus                   1690 UIC           0 :     hints.ai_addr = NULL;
                               1691               0 :     hints.ai_next = NULL;
 5364 magnus                   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 */
 2979 tgl                      1696 UIC           0 :         ident_return = false;
                               1697               0 :         goto ident_inet_done;
                               1698                 :     }
                               1699                 : 
 5364 magnus                   1700               0 :     hints.ai_flags = AI_NUMERICHOST;
 5364 magnus                   1701 UBC           0 :     hints.ai_family = local_addr.addr.ss_family;
                               1702               0 :     hints.ai_socktype = SOCK_STREAM;
 5364 magnus                   1703 UIC           0 :     hints.ai_protocol = 0;
 5364 magnus                   1704 UBC           0 :     hints.ai_addrlen = 0;
 5364 magnus                   1705 UIC           0 :     hints.ai_canonname = NULL;
                               1706               0 :     hints.ai_addr = NULL;
                               1707               0 :     hints.ai_next = NULL;
 5364 magnus                   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 */
 2979 tgl                      1712               0 :         ident_return = false;
                               1713               0 :         goto ident_inet_done;
 5364 magnus                   1714 EUB             :     }
                               1715                 : 
 5364 magnus                   1716 UBC           0 :     sock_fd = socket(ident_serv->ai_family, ident_serv->ai_socktype,
 5364 magnus                   1717 UIC           0 :                      ident_serv->ai_protocol);
 3280 bruce                    1718               0 :     if (sock_fd == PGINVALID_SOCKET)
                               1719                 :     {
 5364 magnus                   1720 UBC           0 :         ereport(LOG,
 5364 magnus                   1721 EUB             :                 (errcode_for_socket_access(),
                               1722                 :                  errmsg("could not create socket for Ident connection: %m")));
 5364 magnus                   1723 UIC           0 :         ident_return = false;
                               1724               0 :         goto ident_inet_done;
 5364 magnus                   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                 :      */
 5364 magnus                   1732 UIC           0 :     rc = bind(sock_fd, la->ai_addr, la->ai_addrlen);
 5364 magnus                   1733 UBC           0 :     if (rc != 0)
 5364 magnus                   1734 EUB             :     {
 5364 magnus                   1735 UIC           0 :         ereport(LOG,
 5364 magnus                   1736 EUB             :                 (errcode_for_socket_access(),
                               1737                 :                  errmsg("could not bind to local address \"%s\": %m",
                               1738                 :                         local_addr_s)));
 5364 magnus                   1739 UIC           0 :         ident_return = false;
                               1740               0 :         goto ident_inet_done;
                               1741                 :     }
 5364 magnus                   1742 EUB             : 
 5364 magnus                   1743 UBC           0 :     rc = connect(sock_fd, ident_serv->ai_addr,
 5364 magnus                   1744 UIC           0 :                  ident_serv->ai_addrlen);
                               1745               0 :     if (rc != 0)
                               1746                 :     {
                               1747               0 :         ereport(LOG,
 5364 magnus                   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)));
 5364 magnus                   1751 UBC           0 :         ident_return = false;
 5364 magnus                   1752 UIC           0 :         goto ident_inet_done;
 5364 magnus                   1753 EUB             :     }
                               1754                 : 
                               1755                 :     /* The query we send to the Ident server */
 5364 magnus                   1756 UIC           0 :     snprintf(ident_query, sizeof(ident_query), "%s,%s\r\n",
                               1757                 :              remote_port, local_port);
                               1758                 : 
 5364 magnus                   1759 EUB             :     /* loop in case send is interrupted */
                               1760                 :     do
                               1761                 :     {
 2987 andres                   1762 UIC           0 :         CHECK_FOR_INTERRUPTS();
 2987 andres                   1763 EUB             : 
 5364 magnus                   1764 UBC           0 :         rc = send(sock_fd, ident_query, strlen(ident_query), 0);
                               1765               0 :     } while (rc < 0 && errno == EINTR);
 5364 magnus                   1766 EUB             : 
 5364 magnus                   1767 UIC           0 :     if (rc < 0)
                               1768                 :     {
                               1769               0 :         ereport(LOG,
 5364 magnus                   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)));
 5364 magnus                   1773 UBC           0 :         ident_return = false;
                               1774               0 :         goto ident_inet_done;
 5364 magnus                   1775 EUB             :     }
                               1776                 : 
                               1777                 :     do
                               1778                 :     {
 2987 andres                   1779 UIC           0 :         CHECK_FOR_INTERRUPTS();
                               1780                 : 
 5364 magnus                   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)
 5364 magnus                   1785 EUB             :     {
 5364 magnus                   1786 UBC           0 :         ereport(LOG,
                               1787                 :                 (errcode_for_socket_access(),
 5364 magnus                   1788 EUB             :                  errmsg("could not receive response from Ident server at address \"%s\", port %s: %m",
                               1789                 :                         remote_addr_s, ident_port)));
 5364 magnus                   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:
 3280 bruce                    1802               0 :     if (sock_fd != PGINVALID_SOCKET)
 5364 magnus                   1803               0 :         closesocket(sock_fd);
 2979 tgl                      1804               0 :     if (ident_serv)
 2979 tgl                      1805 LBC           0 :         pg_freeaddrinfo_all(remote_addr.addr.ss_family, ident_serv);
 2979 tgl                      1806 UIC           0 :     if (la)
                               1807               0 :         pg_freeaddrinfo_all(local_addr.addr.ss_family, la);
                               1808                 : 
 4404 magnus                   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
  732 michael                  1814 ECB             :          * usermap, because at this point authentication has succeeded.
                               1815                 :          */
  732 michael                  1816 UIC           0 :         set_authn_id(port, ident_user);
 4404 magnus                   1817 UBC           0 :         return check_usermap(port->hba->usermap, port->user_name, ident_user, false);
  732 michael                  1818 EUB             :     }
 4404 magnus                   1819 UIC           0 :     return STATUS_ERROR;
                               1820                 : }
                               1821                 : 
 1257 peter                    1822 EUB             : 
                               1823                 : /*----------------------------------------------------------------
                               1824                 :  * Peer authentication system
                               1825                 :  *----------------------------------------------------------------
                               1826                 :  */
                               1827                 : 
                               1828                 : /*
 4331 tgl                      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                 :  *
 4331 tgl                      1833 EUB             :  *  Iff authorized, return STATUS_OK, otherwise return STATUS_ERROR.
                               1834                 :  */
 4404 magnus                   1835                 : static int
 4404 magnus                   1836 GIC          26 : auth_peer(hbaPort *port)
                               1837                 : {
                               1838                 :     uid_t       uid;
 5364 magnus                   1839 EUB             :     gid_t       gid;
                               1840                 : #ifndef WIN32
                               1841                 :     struct passwd *pw;
                               1842                 :     int         ret;
                               1843                 : #endif
                               1844                 : 
 4403 tgl                      1845 GIC          26 :     if (getpeereid(port->sock, &uid, &gid) != 0)
                               1846                 :     {
 4329 tgl                      1847 ECB             :         /* Provide special error message if getpeereid is a stub */
 4329 tgl                      1848 UIC           0 :         if (errno == ENOSYS)
 4329 tgl                      1849 LBC           0 :             ereport(LOG,
                               1850                 :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                               1851                 :                      errmsg("peer authentication is not supported on this platform")));
 4329 tgl                      1852 ECB             :         else
 4329 tgl                      1853 UIC           0 :             ereport(LOG,
                               1854                 :                     (errcode_for_socket_access(),
                               1855                 :                      errmsg("could not get peer credentials: %m")));
 4404 magnus                   1856               0 :         return STATUS_ERROR;
                               1857                 :     }
                               1858                 : 
                               1859                 : #ifndef WIN32
 3299 bruce                    1860 GIC          26 :     errno = 0;                  /* clear errno before call */
                               1861              26 :     pw = getpwuid(uid);
                               1862              26 :     if (!pw)
                               1863                 :     {
 1784 tgl                      1864 UIC           0 :         int         save_errno = errno;
                               1865                 : 
 3299                          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"))));
 4404 magnus                   1870               0 :         return STATUS_ERROR;
                               1871                 :     }
 5255 peter_e                  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                 :      */
  732 michael                  1878 GIC          26 :     set_authn_id(port, pw->pw_name);
 5364 magnus                   1879 EUB             : 
  228 michael                  1880 GNC          26 :     ret = check_usermap(port->hba->usermap, port->user_name,
                               1881                 :                         MyClientConnectionInfo.authn_id, false);
                               1882                 : 
 1257 peter                    1883 GIC          26 :     return ret;
                               1884                 : #else
                               1885                 :     /* should have failed with ENOSYS above */
                               1886                 :     Assert(false);
                               1887                 :     return STATUS_ERROR;
 1257 peter                    1888 EUB             : #endif
                               1889                 : }
                               1890                 : 
 5364 magnus                   1891                 : 
                               1892                 : /*----------------------------------------------------------------
                               1893                 :  * PAM authentication system
                               1894                 :  *----------------------------------------------------------------
                               1895                 :  */
                               1896                 : #ifdef USE_PAM
                               1897                 : 
                               1898                 : /*
                               1899                 :  * PAM conversation function
 7885 bruce                    1900                 :  */
                               1901                 : 
                               1902                 : static int
 2118 tgl                      1903 UIC           0 : pam_passwd_conv_proc(int num_msg, const struct pam_message **msg,
                               1904                 :                      struct pam_response **resp, void *appdata_ptr)
 7885 bruce                    1905 EUB             : {
                               1906                 :     const char *passwd;
                               1907                 :     struct pam_response *reply;
 4923 tgl                      1908                 :     int         i;
                               1909                 : 
 4923 tgl                      1910 UBC           0 :     if (appdata_ptr)
 4923 tgl                      1911 UIC           0 :         passwd = (char *) appdata_ptr;
 4923 tgl                      1912 EUB             :     else
 7836 bruce                    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                 :          */
 4923 tgl                      1918 UIC           0 :         passwd = pam_passwd;
                               1919                 :     }
 7885 bruce                    1920 EUB             : 
 4923 tgl                      1921 UBC           0 :     *resp = NULL;               /* in case of error exit */
 7675 bruce                    1922 EUB             : 
 4923 tgl                      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()
 7885 bruce                    1929 EUB             :      */
 4923 tgl                      1930 UBC           0 :     if ((reply = calloc(num_msg, sizeof(struct pam_response))) == NULL)
                               1931                 :     {
 7201 tgl                      1932 UIC           0 :         ereport(LOG,
 7201 tgl                      1933 EUB             :                 (errcode(ERRCODE_OUT_OF_MEMORY),
                               1934                 :                  errmsg("out of memory")));
 7836 bruce                    1935 UBC           0 :         return PAM_CONV_ERR;
 7885 bruce                    1936 EUB             :     }
                               1937                 : 
 4923 tgl                      1938 UBC           0 :     for (i = 0; i < num_msg; i++)
                               1939                 :     {
 4923 tgl                      1940 UIC           0 :         switch (msg[i]->msg_style)
                               1941                 :         {
                               1942               0 :             case PAM_PROMPT_ECHO_OFF:
                               1943               0 :                 if (strlen(passwd) == 0)
 4923 tgl                      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                 :                      */
 2425 heikki.linnakangas       1950 UIC           0 :                     sendAuthRequest(pam_port_cludge, AUTH_REQ_PASSWORD, NULL, 0);
 4923 tgl                      1951               0 :                     passwd = recv_password_packet(pam_port_cludge);
                               1952               0 :                     if (passwd == NULL)
 4923 tgl                      1953 EUB             :                     {
                               1954                 :                         /*
                               1955                 :                          * Client didn't want to send password.  We
                               1956                 :                          * intentionally do not log anything about this,
 1251                          1957                 :                          * either here or at higher levels.
 4923                          1958                 :                          */
 1251 tgl                      1959 UIC           0 :                         pam_no_password = true;
 4923 tgl                      1960 UBC           0 :                         goto fail;
                               1961                 :                     }
 4923 tgl                      1962 EUB             :                 }
 4923 tgl                      1963 UBC           0 :                 if ((reply[i].resp = strdup(passwd)) == NULL)
                               1964               0 :                     goto fail;
 4923 tgl                      1965 UIC           0 :                 reply[i].resp_retcode = PAM_SUCCESS;
 4923 tgl                      1966 UBC           0 :                 break;
 4923 tgl                      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 */
 4923 tgl                      1974 UBC           0 :                 if ((reply[i].resp = strdup("")) == NULL)
 4923 tgl                      1975 UIC           0 :                     goto fail;
                               1976               0 :                 reply[i].resp_retcode = PAM_SUCCESS;
 4923 tgl                      1977 UBC           0 :                 break;
 4923 tgl                      1978 UIC           0 :             default:
  856 peter                    1979               0 :                 ereport(LOG,
                               1980                 :                         (errmsg("unsupported PAM conversation %d/\"%s\"",
                               1981                 :                                 msg[i]->msg_style,
                               1982                 :                                 msg[i]->msg ? msg[i]->msg : "(none)")));
 4923 tgl                      1983               0 :                 goto fail;
 4923 tgl                      1984 EUB             :         }
                               1985                 :     }
                               1986                 : 
 4923 tgl                      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++)
  297 peter                    1993 UNC           0 :         free(reply[i].resp);
 4923 tgl                      1994 UBC           0 :     free(reply);
 7885 bruce                    1995 EUB             : 
 4923 tgl                      1996 UIC           0 :     return PAM_CONV_ERR;
                               1997                 : }
 7885 bruce                    1998 EUB             : 
                               1999                 : 
                               2000                 : /*
                               2001                 :  * Check authentication against PAM.
                               2002                 :  */
                               2003                 : static int
 1986 peter_e                  2004 UIC           0 : CheckPAMAuth(Port *port, const char *user, const char *password)
                               2005                 : {
 7836 bruce                    2006 EUB             :     int         retval;
 7885 bruce                    2007 UBC           0 :     pam_handle_t *pamh = NULL;
                               2008                 : 
                               2009                 :     /*
 4923 tgl                      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                 :      */
 7885 bruce                    2014 UBC           0 :     pam_passwd = password;
 4923 tgl                      2015 UIC           0 :     pam_port_cludge = port;
 1251                          2016               0 :     pam_no_password = false;
 7885 bruce                    2017 EUB             : 
 7836                          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                 :      */
 1418 tgl                      2023 UIC           0 :     pam_passw_conv.appdata_ptr = unconstify(char *, password);  /* from password above,
                               2024                 :                                                                  * not allocated */
                               2025                 : 
 7885 bruce                    2026 EUB             :     /* Optionally, one can set the service name in pg_hba.conf */
 5281 magnus                   2027 UBC           0 :     if (port->hba->pamservice && port->hba->pamservice[0] != '\0')
 5281 magnus                   2028 UIC           0 :         retval = pam_start(port->hba->pamservice, "pgsql@",
 7297 tgl                      2029 EUB             :                            &pam_passw_conv, &pamh);
                               2030                 :     else
 7297 tgl                      2031 UBC           0 :         retval = pam_start(PGSQL_PAM_SERVICE, "pgsql@",
                               2032                 :                            &pam_passw_conv, &pamh);
                               2033                 : 
 7836 bruce                    2034               0 :     if (retval != PAM_SUCCESS)
                               2035                 :     {
 7201 tgl                      2036               0 :         ereport(LOG,
                               2037                 :                 (errmsg("could not create PAM authenticator: %s",
                               2038                 :                         pam_strerror(pamh, retval))));
 7836 bruce                    2039               0 :         pam_passwd = NULL;      /* Unset pam_passwd */
 7885 bruce                    2040 UIC           0 :         return STATUS_ERROR;
                               2041                 :     }
 7885 bruce                    2042 EUB             : 
 7713 bruce                    2043 UIC           0 :     retval = pam_set_item(pamh, PAM_USER, user);
 7713 bruce                    2044 EUB             : 
 7713 bruce                    2045 UIC           0 :     if (retval != PAM_SUCCESS)
 7836 bruce                    2046 EUB             :     {
 7201 tgl                      2047 UIC           0 :         ereport(LOG,
                               2048                 :                 (errmsg("pam_set_item(PAM_USER) failed: %s",
 7201 tgl                      2049 EUB             :                         pam_strerror(pamh, retval))));
 7836 bruce                    2050 UBC           0 :         pam_passwd = NULL;      /* Unset pam_passwd */
 7885 bruce                    2051 UIC           0 :         return STATUS_ERROR;
                               2052                 :     }
                               2053                 : 
 1593 tmunro                   2054 UBC           0 :     if (port->hba->conntype != ctLocal)
                               2055                 :     {
 1593 tmunro                   2056 EUB             :         char        hostinfo[NI_MAXHOST];
                               2057                 :         int         flags;
                               2058                 : 
 1593 tmunro                   2059 UIC           0 :         if (port->hba->pam_use_hostname)
                               2060               0 :             flags = 0;
 1593 tmunro                   2061 EUB             :         else
 1593 tmunro                   2062 UBC           0 :             flags = NI_NUMERICHOST | NI_NUMERICSERV;
                               2063                 : 
 1593 tmunro                   2064 UIC           0 :         retval = pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
 1593 tmunro                   2065 EUB             :                                     hostinfo, sizeof(hostinfo), NULL, 0,
                               2066                 :                                     flags);
 1593 tmunro                   2067 UBC           0 :         if (retval != 0)
                               2068                 :         {
 1593 tmunro                   2069 UIC           0 :             ereport(WARNING,
 1593 tmunro                   2070 EUB             :                     (errmsg_internal("pg_getnameinfo_all() failed: %s",
                               2071                 :                                      gai_strerror(retval))));
 1593 tmunro                   2072 UIC           0 :             return STATUS_ERROR;
                               2073                 :         }
 1593 tmunro                   2074 EUB             : 
 1593 tmunro                   2075 UBC           0 :         retval = pam_set_item(pamh, PAM_RHOST, hostinfo);
                               2076                 : 
 1593 tmunro                   2077 UIC           0 :         if (retval != PAM_SUCCESS)
 1593 tmunro                   2078 EUB             :         {
 1593 tmunro                   2079 UIC           0 :             ereport(LOG,
 1593 tmunro                   2080 EUB             :                     (errmsg("pam_set_item(PAM_RHOST) failed: %s",
                               2081                 :                             pam_strerror(pamh, retval))));
 1593 tmunro                   2082 UIC           0 :             pam_passwd = NULL;
 1593 tmunro                   2083 UBC           0 :             return STATUS_ERROR;
 1593 tmunro                   2084 EUB             :         }
                               2085                 :     }
                               2086                 : 
 7713 bruce                    2087 UBC           0 :     retval = pam_set_item(pamh, PAM_CONV, &pam_passw_conv);
 7713 bruce                    2088 EUB             : 
 7713 bruce                    2089 UIC           0 :     if (retval != PAM_SUCCESS)
                               2090                 :     {
 7201 tgl                      2091 UBC           0 :         ereport(LOG,
                               2092                 :                 (errmsg("pam_set_item(PAM_CONV) failed: %s",
 7201 tgl                      2093 EUB             :                         pam_strerror(pamh, retval))));
 7836 bruce                    2094 UIC           0 :         pam_passwd = NULL;      /* Unset pam_passwd */
 7885 bruce                    2095 UBC           0 :         return STATUS_ERROR;
                               2096                 :     }
                               2097                 : 
 7713 bruce                    2098 UIC           0 :     retval = pam_authenticate(pamh, 0);
                               2099                 : 
 7713 bruce                    2100 UBC           0 :     if (retval != PAM_SUCCESS)
                               2101                 :     {
 1251 tgl                      2102 EUB             :         /* If pam_passwd_conv_proc saw EOF, don't log anything */
 1251 tgl                      2103 UBC           0 :         if (!pam_no_password)
 1251 tgl                      2104 UIC           0 :             ereport(LOG,
 1251 tgl                      2105 EUB             :                     (errmsg("pam_authenticate failed: %s",
                               2106                 :                             pam_strerror(pamh, retval))));
 7836 bruce                    2107 UIC           0 :         pam_passwd = NULL;      /* Unset pam_passwd */
 1251 tgl                      2108               0 :         return pam_no_password ? STATUS_EOF : STATUS_ERROR;
                               2109                 :     }
                               2110                 : 
 7713 bruce                    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 */
 1251 tgl                      2116               0 :         if (!pam_no_password)
                               2117               0 :             ereport(LOG,
                               2118                 :                     (errmsg("pam_acct_mgmt failed: %s",
                               2119                 :                             pam_strerror(pamh, retval))));
 7836 bruce                    2120               0 :         pam_passwd = NULL;      /* Unset pam_passwd */
 1251 tgl                      2121               0 :         return pam_no_password ? STATUS_EOF : STATUS_ERROR;
                               2122                 :     }
                               2123                 : 
 7713 bruce                    2124               0 :     retval = pam_end(pamh, retval);
                               2125                 : 
                               2126               0 :     if (retval != PAM_SUCCESS)
                               2127                 :     {
 7201 tgl                      2128               0 :         ereport(LOG,
                               2129                 :                 (errmsg("could not release PAM authenticator: %s",
                               2130                 :                         pam_strerror(pamh, retval))));
                               2131                 :     }
                               2132                 : 
 7522 bruce                    2133               0 :     pam_passwd = NULL;          /* Unset pam_passwd */
                               2134                 : 
  732 michael                  2135               0 :     if (retval == PAM_SUCCESS)
                               2136               0 :         set_authn_id(port, user);
                               2137                 : 
 7713 bruce                    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)
 2557 tgl                      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
 4866 magnus                   2192 GIC          39 : InitializeLDAPConnection(Port *port, LDAP **ldap)
 6243 bruce                    2193 ECB             : {
                               2194                 :     const char *scheme;
 6031 bruce                    2195 GIC          39 :     int         ldapversion = LDAP_VERSION3;
                               2196                 :     int         r;
                               2197                 : 
 1922 peter_e                  2198 CBC          39 :     scheme = port->hba->ldapscheme;
 1922 peter_e                  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
 1921 peter_e                  2205 ECB             :         *ldap = ldap_init(port->hba->ldapserver, port->hba->ldapport);
 4866 magnus                   2206 EUB             :     if (!*ldap)
                               2207                 :     {
                               2208                 :         ereport(LOG,
                               2209                 :                 (errmsg("could not initialize LDAP: error code %d",
 6031 bruce                    2210                 :                         (int) LdapGetLastError())));
                               2211                 : 
                               2212                 :         return STATUS_ERROR;
                               2213                 :     }
 1922 peter_e                  2214                 : #else
                               2215                 : #ifdef HAVE_LDAP_INITIALIZE
                               2216                 : 
                               2217                 :     /*
 1480 tmunro                   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                 :      */
 1922 peter_e                  2224                 :     {
 1480 tmunro                   2225                 :         StringInfoData uris;
 1480 tmunro                   2226 GIC          39 :         char       *hostlist = NULL;
 1480 tmunro                   2227 EUB             :         char       *p;
                               2228                 :         bool        append_port;
                               2229                 : 
                               2230                 :         /* We'll build a space-separated scheme://hostname:port list here */
 1480 tmunro                   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
 1480 tmunro                   2236 ECB             :          * up DSN SRV records for _ldap._tcp.<domain>.
 1608                          2237                 :          */
 1480 tmunro                   2238 GIC          39 :         if (!port->hba->ldapserver || port->hba->ldapserver[0] == '\0')
 1480 tmunro                   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,
 1480 tmunro                   2246 ECB             :                         (errmsg("could not extract domain name from ldapbasedn")));
 1480 tmunro                   2247 UIC           0 :                 return STATUS_ERROR;
                               2248                 :             }
 1480 tmunro                   2249 ECB             : 
                               2250                 :             /* Look up a list of LDAP server hosts and port numbers */
 1480 tmunro                   2251 UIC           0 :             if (ldap_domain2hostlist(domain, &hostlist))
                               2252                 :             {
 1480 tmunro                   2253 LBC           0 :                 ereport(LOG,
 1480 tmunro                   2254 ECB             :                         (errmsg("LDAP authentication could not find DNS SRV records for \"%s\"",
                               2255                 :                                 domain),
                               2256                 :                          (errhint("Set an LDAP server name explicitly."))));
 1480 tmunro                   2257 LBC           0 :                 ldap_memfree(domain);
 1480 tmunro                   2258 UIC           0 :                 return STATUS_ERROR;
                               2259                 :             }
 1480 tmunro                   2260 LBC           0 :             ldap_memfree(domain);
 1480 tmunro                   2261 ECB             : 
                               2262                 :             /* We have a space-separated list of host:port entries */
 1480 tmunro                   2263 LBC           0 :             p = hostlist;
 1480 tmunro                   2264 UIC           0 :             append_port = false;
                               2265                 :         }
 1480 tmunro                   2266 ECB             :         else
 1480 tmunro                   2267 EUB             :         {
                               2268                 :             /* We have a space-separated list of hosts from pg_hba.conf */
 1480 tmunro                   2269 GIC          39 :             p = port->hba->ldapserver;
 1480 tmunro                   2270 CBC          39 :             append_port = true;
 1480 tmunro                   2271 ECB             :         }
                               2272                 : 
                               2273                 :         /* Convert the list of host[:port] entries to full URIs */
 1608 tmunro                   2274 EUB             :         do
                               2275                 :         {
                               2276                 :             size_t      size;
                               2277                 : 
 1480                          2278                 :             /* Find the span of the next entry */
 1480 tmunro                   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)
 1480 tmunro                   2300 LBC           0 :             ldap_memfree(hostlist);
                               2301                 : 
 1480 tmunro                   2302 EUB             :         /* Finally, try to connect using the URI list */
 1480 tmunro                   2303 GIC          39 :         r = ldap_initialize(ldap, uris.data);
                               2304              39 :         pfree(uris.data);
 1922 peter_e                  2305              39 :         if (r != LDAP_SUCCESS)
 1922 peter_e                  2306 EUB             :         {
 1922 peter_e                  2307 UBC           0 :             ereport(LOG,
                               2308                 :                     (errmsg("could not initialize LDAP: %s",
                               2309                 :                             ldap_err2string(r))));
 1922 peter_e                  2310 ECB             : 
 1922 peter_e                  2311 UIC           0 :             return STATUS_ERROR;
                               2312                 :         }
 1922 peter_e                  2313 ECB             :     }
                               2314                 : #else
                               2315                 :     if (strcmp(scheme, "ldaps") == 0)
                               2316                 :     {
                               2317                 :         ereport(LOG,
 1922 peter_e                  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")));
 1922 peter_e                  2327 ECB             : 
                               2328                 :         return STATUS_ERROR;
                               2329                 :     }
                               2330                 : #endif
                               2331                 : #endif
                               2332                 : 
 4866 magnus                   2333 GIC          39 :     if ((r = ldap_set_option(*ldap, LDAP_OPT_PROTOCOL_VERSION, &ldapversion)) != LDAP_SUCCESS)
                               2334                 :     {
 6031 bruce                    2335 UIC           0 :         ereport(LOG,
                               2336                 :                 (errmsg("could not set LDAP protocol version: %s",
                               2337                 :                         ldap_err2string(r)),
                               2338                 :                  errdetail_for_ldap(*ldap)));
 2005 peter_e                  2339               0 :         ldap_unbind(*ldap);
 6031 bruce                    2340               0 :         return STATUS_ERROR;
                               2341                 :     }
                               2342                 : 
 5281 magnus                   2343 GIC          39 :     if (port->hba->ldaptls)
                               2344                 :     {
 6243 bruce                    2345 EUB             : #ifndef WIN32
 4866 magnus                   2346 GIC           2 :         if ((r = ldap_start_tls_s(*ldap, NULL, NULL)) != LDAP_SUCCESS)
 6243 bruce                    2347 EUB             : #else
                               2348                 :         if ((r = ldap_start_tls_s(*ldap, NULL, NULL, NULL, NULL)) != LDAP_SUCCESS)
                               2349                 : #endif
                               2350                 :         {
 6031 bruce                    2351 LBC           0 :             ereport(LOG,
 2005 peter_e                  2352 EUB             :                     (errmsg("could not start LDAP TLS session: %s",
                               2353                 :                             ldap_err2string(r)),
                               2354                 :                      errdetail_for_ldap(*ldap)));
 2005 peter_e                  2355 UIC           0 :             ldap_unbind(*ldap);
 6031 bruce                    2356 UBC           0 :             return STATUS_ERROR;
                               2357                 :         }
                               2358                 :     }
                               2359                 : 
 4866 magnus                   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
 2034 peter_e                  2371 ECB             : 
                               2372                 : /* Not all LDAP implementations define this. */
 1921                          2373                 : #ifndef LDAPS_PORT
                               2374                 : #define LDAPS_PORT 636
 1921 peter_e                  2375 EUB             : #endif
                               2376                 : 
                               2377                 : static char *
   25 andrew                   2378 UNC           0 : dummy_ldap_password_mutator(char *input)
                               2379                 : {
                               2380               0 :     return input;
                               2381                 : }
                               2382                 : 
 2035 peter_e                  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 *
 2035 peter_e                  2388 CBC           8 : FormatSearchFilter(const char *pattern, const char *user_name)
                               2389                 : {
 2035 peter_e                  2390 ECB             :     StringInfoData output;
                               2391                 : 
 2035 peter_e                  2392 CBC           8 :     initStringInfo(&output);
 2035 peter_e                  2393 GIC         119 :     while (*pattern != '\0')
 2035 peter_e                  2394 ECB             :     {
 2035 peter_e                  2395 GIC         111 :         if (strncmp(pattern, LPH_USERNAME, LPH_USERNAME_LEN) == 0)
                               2396                 :         {
 2035 peter_e                  2397 GBC          13 :             appendStringInfoString(&output, user_name);
                               2398              13 :             pattern += LPH_USERNAME_LEN;
                               2399                 :         }
                               2400                 :         else
 2035 peter_e                  2401 CBC          98 :             appendStringInfoChar(&output, *pattern++);
                               2402                 :     }
                               2403                 : 
 2035 peter_e                  2404 GIC           8 :     return output.data;
                               2405                 : }
                               2406                 : 
                               2407                 : /*
                               2408                 :  * Perform LDAP authentication
                               2409                 :  */
 4866 magnus                   2410 ECB             : static int
 4866 magnus                   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                 : 
 1480 tmunro                   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                 :      */
 1480 tmunro                   2425 CBC          26 :     if ((!port->hba->ldapserver || port->hba->ldapserver[0] == '\0') &&
 1480 tmunro                   2426 LBC           0 :         (!port->hba->ldapbasedn || port->hba->ldapbasedn[0] == '\0'))
 1480 tmunro                   2427 ECB             :     {
 1480 tmunro                   2428 UIC           0 :         ereport(LOG,
 1480 tmunro                   2429 EUB             :                 (errmsg("LDAP server not specified, and no ldapbasedn")));
 1480 tmunro                   2430 UIC           0 :         return STATUS_ERROR;
 1480 tmunro                   2431 EUB             :     }
                               2432                 : #else
 4866 magnus                   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                 : 
 1480 tmunro                   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                 :      */
 1480 tmunro                   2445 GIC          26 :     server_name = port->hba->ldapserver ? port->hba->ldapserver : "";
 4866 magnus                   2446 ECB             : 
 4866 magnus                   2447 GIC          26 :     if (port->hba->ldapport == 0)
                               2448                 :     {
 1922 peter_e                  2449 UIC           0 :         if (port->hba->ldapscheme != NULL &&
                               2450               0 :             strcmp(port->hba->ldapscheme, "ldaps") == 0)
                               2451               0 :             port->hba->ldapport = LDAPS_PORT;
 1922 peter_e                  2452 ECB             :         else
 1922 peter_e                  2453 LBC           0 :             port->hba->ldapport = LDAP_PORT;
 1922 peter_e                  2454 ECB             :     }
                               2455                 : 
 2425 heikki.linnakangas       2456 GIC          26 :     sendAuthRequest(port, AUTH_REQ_PASSWORD, NULL, 0);
                               2457                 : 
 4866 magnus                   2458 CBC          26 :     passwd = recv_password_packet(port);
                               2459              26 :     if (passwd == NULL)
                               2460               1 :         return STATUS_EOF;      /* client wouldn't send password */
 4866 magnus                   2461 ECB             : 
 4866 magnus                   2462 GIC          25 :     if (InitializeLDAPConnection(port, &ldap) == STATUS_ERROR)
 2071 heikki.linnakangas       2463 ECB             :     {
                               2464                 :         /* Error message already sent */
 2071 heikki.linnakangas       2465 LBC           0 :         pfree(passwd);
 4866 magnus                   2466               0 :         return STATUS_ERROR;
 2071 heikki.linnakangas       2467 ECB             :     }
 4866 magnus                   2468                 : 
 4866 magnus                   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.
 4866 magnus                   2474 ECB             :          */
                               2475                 :         char       *filter;
 4790 bruce                    2476 EUB             :         LDAPMessage *search_message;
                               2477                 :         LDAPMessage *entry;
 1957 rhaas                    2478 GIC          20 :         char       *attributes[] = {LDAP_NO_ATTRS, NULL};
                               2479                 :         char       *dn;
 4790 bruce                    2480 EUB             :         char       *c;
 3841 peter_e                  2481                 :         int         count;
 4866 magnus                   2482                 : 
                               2483                 :         /*
 4790 bruce                    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.
 4866 magnus                   2488 ECB             :          */
 4866 magnus                   2489 CBC         144 :         for (c = port->user_name; *c; c++)
                               2490                 :         {
                               2491             124 :             if (*c == '*' ||
                               2492             124 :                 *c == '(' ||
 4866 magnus                   2493 GIC         124 :                 *c == ')' ||
                               2494             124 :                 *c == '\\' ||
                               2495             124 :                 *c == '/')
                               2496                 :             {
 4866 magnus                   2497 UBC           0 :                 ereport(LOG,
                               2498                 :                         (errmsg("invalid character in user name for LDAP authentication")));
 2005 peter_e                  2499 UIC           0 :                 ldap_unbind(ldap);
 2071 heikki.linnakangas       2500               0 :                 pfree(passwd);
 4866 magnus                   2501 GIC           6 :                 return STATUS_ERROR;
                               2502                 :             }
                               2503                 :         }
 4866 magnus                   2504 ECB             : 
                               2505                 :         /*
 4790 bruce                    2506                 :          * Bind with a pre-defined username/password (if available) for
                               2507                 :          * searching. If none is specified, this turns into an anonymous bind.
 4866 magnus                   2508                 :          */
 4866 magnus                   2509 GIC          38 :         r = ldap_simple_bind_s(ldap,
 2118 tgl                      2510              20 :                                port->hba->ldapbinddn ? port->hba->ldapbinddn : "",
   25 andrew                   2511 GNC          20 :                                port->hba->ldapbindpasswd ? ldap_password_hook(port->hba->ldapbindpasswd) : "");
 4866 magnus                   2512 CBC          20 :         if (r != LDAP_SUCCESS)
 4866 magnus                   2513 ECB             :         {
 4866 magnus                   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 : "",
 1480 tmunro                   2517 EUB             :                             server_name,
 2005 peter_e                  2518                 :                             ldap_err2string(r)),
                               2519                 :                      errdetail_for_ldap(ldap)));
 2005 peter_e                  2520 GIC           3 :             ldap_unbind(ldap);
 2071 heikki.linnakangas       2521               3 :             pfree(passwd);
 4866 magnus                   2522               3 :             return STATUS_ERROR;
 4866 magnus                   2523 EUB             :         }
                               2524                 : 
 2035 peter_e                  2525                 :         /* Build a custom filter or a single attribute filter? */
 2035 peter_e                  2526 GBC          17 :         if (port->hba->ldapsearchfilter)
                               2527               8 :             filter = FormatSearchFilter(port->hba->ldapsearchfilter, port->user_name);
 2035 peter_e                  2528 GIC           9 :         else if (port->hba->ldapsearchattribute)
 2035 peter_e                  2529 CBC           3 :             filter = psprintf("(%s=%s)", port->hba->ldapsearchattribute, port->user_name);
                               2530                 :         else
                               2531               6 :             filter = psprintf("(uid=%s)", port->user_name);
 4866 magnus                   2532 ECB             : 
  211 michael                  2533 GNC          17 :         search_message = NULL;
 4866 magnus                   2534 CBC          17 :         r = ldap_search_s(ldap,
 4866 magnus                   2535 GIC          17 :                           port->hba->ldapbasedn,
 3779 peter_e                  2536              17 :                           port->hba->ldapscope,
 4866 magnus                   2537 ECB             :                           filter,
                               2538                 :                           attributes,
                               2539                 :                           0,
 4866 magnus                   2540 EUB             :                           &search_message);
                               2541                 : 
 4866 magnus                   2542 GIC          17 :         if (r != LDAP_SUCCESS)
 4866 magnus                   2543 EUB             :         {
 4866 magnus                   2544 UBC           0 :             ereport(LOG,
 3846 peter_e                  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)));
  211 michael                  2548 UNC           0 :             if (search_message != NULL)
                               2549               0 :                 ldap_msgfree(search_message);
 2005 peter_e                  2550 UIC           0 :             ldap_unbind(ldap);
 2071 heikki.linnakangas       2551               0 :             pfree(passwd);
 4866 magnus                   2552               0 :             pfree(filter);
                               2553               0 :             return STATUS_ERROR;
 4866 magnus                   2554 ECB             :         }
                               2555                 : 
 3841 peter_e                  2556 GBC          17 :         count = ldap_count_entries(ldap, search_message);
                               2557              17 :         if (count != 1)
                               2558                 :         {
 3841 peter_e                  2559 GIC           3 :             if (count == 0)
 4866 magnus                   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)));
 4866 magnus                   2564 ECB             :             else
 4866 magnus                   2565 LBC           0 :                 ereport(LOG,
                               2566                 :                         (errmsg("LDAP user \"%s\" is not unique", port->user_name),
 2118 tgl                      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)));
 4866 magnus                   2571                 : 
 2005 peter_e                  2572 GIC           3 :             ldap_unbind(ldap);
 2071 heikki.linnakangas       2573 CBC           3 :             pfree(passwd);
 4866 magnus                   2574 GIC           3 :             pfree(filter);
                               2575               3 :             ldap_msgfree(search_message);
                               2576               3 :             return STATUS_ERROR;
 4866 magnus                   2577 ECB             :         }
                               2578                 : 
 4866 magnus                   2579 CBC          14 :         entry = ldap_first_entry(ldap, search_message);
                               2580              14 :         dn = ldap_get_dn(ldap, entry);
 4866 magnus                   2581 GIC          14 :         if (dn == NULL)
                               2582                 :         {
                               2583                 :             int         error;
 4790 bruce                    2584 ECB             : 
 4790 bruce                    2585 UIC           0 :             (void) ldap_get_option(ldap, LDAP_OPT_ERROR_NUMBER, &error);
 4866 magnus                   2586 LBC           0 :             ereport(LOG,
 4866 magnus                   2587 ECB             :                     (errmsg("could not get dn for the first entry matching \"%s\" on server \"%s\": %s",
 1480 tmunro                   2588                 :                             filter, server_name,
                               2589                 :                             ldap_err2string(error)),
 2005 peter_e                  2590                 :                      errdetail_for_ldap(ldap)));
 2005 peter_e                  2591 UIC           0 :             ldap_unbind(ldap);
 2071 heikki.linnakangas       2592               0 :             pfree(passwd);
 4866 magnus                   2593               0 :             pfree(filter);
                               2594               0 :             ldap_msgfree(search_message);
                               2595               0 :             return STATUS_ERROR;
                               2596                 :         }
 4866 magnus                   2597 GIC          14 :         fulluser = pstrdup(dn);
 4866 magnus                   2598 ECB             : 
 4866 magnus                   2599 GIC          14 :         pfree(filter);
                               2600              14 :         ldap_memfree(dn);
                               2601              14 :         ldap_msgfree(search_message);
                               2602                 : 
 4866 magnus                   2603 ECB             :         /* Unbind and disconnect from the LDAP server */
 4866 magnus                   2604 CBC          14 :         r = ldap_unbind_s(ldap);
 4866 magnus                   2605 GIC          14 :         if (r != LDAP_SUCCESS)
 4866 magnus                   2606 ECB             :         {
 4866 magnus                   2607 LBC           0 :             ereport(LOG,
                               2608                 :                     (errmsg("could not unbind after searching for user \"%s\" on server \"%s\"",
                               2609                 :                             fulluser, server_name)));
 2071 heikki.linnakangas       2610               0 :             pfree(passwd);
 4866 magnus                   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                 :          */
 4866 magnus                   2619 GIC          14 :         if (InitializeLDAPConnection(port, &ldap) == STATUS_ERROR)
                               2620                 :         {
 2071 heikki.linnakangas       2621 UIC           0 :             pfree(passwd);
 4866 magnus                   2622 LBC           0 :             pfree(fulluser);
                               2623                 : 
 4866 magnus                   2624 ECB             :             /* Error message already sent */
 4866 magnus                   2625 LBC           0 :             return STATUS_ERROR;
                               2626                 :         }
 4866 magnus                   2627 ECB             :     }
                               2628                 :     else
 3465 peter_e                  2629 GIC           5 :         fulluser = psprintf("%s%s%s",
 2118 tgl                      2630 CBC           5 :                             port->hba->ldapprefix ? port->hba->ldapprefix : "",
                               2631                 :                             port->user_name,
                               2632               5 :                             port->hba->ldapsuffix ? port->hba->ldapsuffix : "");
 6243 bruce                    2633 ECB             : 
 6031 bruce                    2634 CBC          19 :     r = ldap_simple_bind_s(ldap, fulluser, passwd);
 6243 bruce                    2635 ECB             : 
 6031 bruce                    2636 CBC          19 :     if (r != LDAP_SUCCESS)
                               2637                 :     {
 6031 bruce                    2638 GIC           6 :         ereport(LOG,
                               2639                 :                 (errmsg("LDAP login failed for user \"%s\" on server \"%s\": %s",
 1480 tmunro                   2640 ECB             :                         fulluser, server_name, ldap_err2string(r)),
 2005 peter_e                  2641                 :                  errdetail_for_ldap(ldap)));
 2005 peter_e                  2642 GIC           6 :         ldap_unbind(ldap);
 2071 heikki.linnakangas       2643 GBC           6 :         pfree(passwd);
 4866 magnus                   2644 GIC           6 :         pfree(fulluser);
 6031 bruce                    2645               6 :         return STATUS_ERROR;
 6031 bruce                    2646 EUB             :     }
                               2647                 : 
                               2648                 :     /* Save the original bind DN as the authenticated identity. */
  732 michael                  2649 CBC          13 :     set_authn_id(port, fulluser);
                               2650                 : 
 2005 peter_e                  2651 GIC          13 :     ldap_unbind(ldap);
 2071 heikki.linnakangas       2652              13 :     pfree(passwd);
 4866 magnus                   2653              13 :     pfree(fulluser);
                               2654                 : 
 6031 bruce                    2655              13 :     return STATUS_OK;
                               2656                 : }
                               2657                 : 
 2005 peter_e                  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
 2005 peter_e                  2663 GIC           9 : errdetail_for_ldap(LDAP *ldap)
 2005 peter_e                  2664 EUB             : {
                               2665                 :     char       *message;
                               2666                 :     int         rc;
                               2667                 : 
 2005 peter_e                  2668 GIC           9 :     rc = ldap_get_option(ldap, LDAP_OPT_DIAGNOSTIC_MESSAGE, &message);
                               2669               9 :     if (rc == LDAP_SUCCESS && message != NULL)
 2005 peter_e                  2670 ECB             :     {
 2005 peter_e                  2671 GIC           2 :         errdetail("LDAP diagnostics: %s", message);
                               2672               2 :         ldap_memfree(message);
                               2673                 :     }
 2005 peter_e                  2674 ECB             : 
 2005 peter_e                  2675 CBC           9 :     return 0;
                               2676                 : }
                               2677                 : 
                               2678                 : #endif                          /* USE_LDAP */
                               2679                 : 
                               2680                 : 
                               2681                 : /*----------------------------------------------------------------
 5253 magnus                   2682 ECB             :  * SSL client certificate authentication
                               2683                 :  *----------------------------------------------------------------
                               2684                 :  */
                               2685                 : #ifdef USE_SSL
 5253 magnus                   2686 EUB             : static int
 5253 magnus                   2687 GBC          27 : CheckCertAuth(Port *port)
                               2688                 : {
 1492 magnus                   2689 GIC          27 :     int         status_check_usermap = STATUS_ERROR;
  741 andrew                   2690 GBC          27 :     char       *peer_username = NULL;
 1492 magnus                   2691 ECB             : 
 5253 magnus                   2692 CBC          27 :     Assert(port->ssl);
                               2693                 : 
                               2694                 :     /* select the correct field to compare */
  741 andrew                   2695 GIC          27 :     switch (port->hba->clientcertname)
                               2696                 :     {
                               2697               2 :         case clientCertDN:
  741 andrew                   2698 CBC           2 :             peer_username = port->peer_dn;
  741 andrew                   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                 :     {
 5253 magnus                   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                 : 
  732 michael                  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                 :              */
  732 michael                  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                 : 
  732 michael                  2735 GIC          24 :         set_authn_id(port, port->peer_dn);
                               2736                 :     }
                               2737                 : 
                               2738                 :     /* Just pass the certificate cn/dn to the usermap check */
  741 andrew                   2739              27 :     status_check_usermap = check_usermap(port->hba->usermap, port->user_name, peer_username, false);
 1492 magnus                   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                 :         {
  741 andrew                   2749               1 :             switch (port->hba->clientcertname)
                               2750                 :             {
  741 andrew                   2751 UIC           0 :                 case clientCertDN:
                               2752               0 :                     ereport(LOG,
                               2753                 :                             (errmsg("certificate validation (clientcert=verify-full) failed for user \"%s\": DN mismatch",
  741 andrew                   2754 EUB             :                                     port->user_name)));
  741 andrew                   2755 UIC           0 :                     break;
  741 andrew                   2756 GIC           1 :                 case clientCertCN:
                               2757               1 :                     ereport(LOG,
  741 andrew                   2758 EUB             :                             (errmsg("certificate validation (clientcert=verify-full) failed for user \"%s\": CN mismatch",
                               2759                 :                                     port->user_name)));
                               2760                 :             }
                               2761                 :         }
                               2762                 :     }
 1492 magnus                   2763 GIC          27 :     return status_check_usermap;
                               2764                 : }
                               2765                 : #endif
 4820 magnus                   2766 EUB             : 
                               2767                 : 
                               2768                 : /*----------------------------------------------------------------
                               2769                 :  * RADIUS authentication
                               2770                 :  *----------------------------------------------------------------
                               2771                 :  */
                               2772                 : 
                               2773                 : /*
 2205 tgl                      2774                 :  * RADIUS authentication is described in RFC2865 (and several others).
 4820 magnus                   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;
 4790 bruce                    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];
 4820 magnus                   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
 4820 magnus                   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)
 4820 magnus                   2824 EUB             :     {
                               2825                 :         /*
 4790 bruce                    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.
 4820 magnus                   2830                 :          */
 4820 magnus                   2831 UIC           0 :         elog(WARNING,
                               2832                 :              "adding attribute code %d with length %d to radius packet would create oversize packet, ignoring",
 4820 magnus                   2833 EUB             :              type, len);
 4820 magnus                   2834 UIC           0 :         return;
                               2835                 :     }
                               2836                 : 
 4790 bruce                    2837               0 :     attr = (radius_attribute *) ((unsigned char *) packet + packet->length);
 4820 magnus                   2838               0 :     attr->attribute = type;
 4790 bruce                    2839               0 :     attr->length = len + 2;      /* total size includes type and length */
 4820 magnus                   2840               0 :     memcpy(attr->data, data, len);
                               2841               0 :     packet->length += attr->length;
 4820 magnus                   2842 EUB             : }
                               2843                 : 
                               2844                 : static int
 4820 magnus                   2845 UIC           0 : CheckRADIUSAuth(Port *port)
 4820 magnus                   2846 EUB             : {
 4790 bruce                    2847                 :     char       *passwd;
                               2848                 :     ListCell   *server,
 2209 magnus                   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 */
  235 tgl                      2857 UNC           0 :     if (port->hba->radiusservers == NIL)
                               2858                 :     {
 2209 magnus                   2859 UIC           0 :         ereport(LOG,
                               2860                 :                 (errmsg("RADIUS server not specified")));
 2209 magnus                   2861 UBC           0 :         return STATUS_ERROR;
 2209 magnus                   2862 EUB             :     }
                               2863                 : 
  235 tgl                      2864 UNC           0 :     if (port->hba->radiussecrets == NIL)
 2209 magnus                   2865 EUB             :     {
 2209 magnus                   2866 UBC           0 :         ereport(LOG,
                               2867                 :                 (errmsg("RADIUS secret not specified")));
 2209 magnus                   2868 UIC           0 :         return STATUS_ERROR;
                               2869                 :     }
 2209 magnus                   2870 EUB             : 
                               2871                 :     /* Send regular password request to client, and get the response */
 2209 magnus                   2872 UIC           0 :     sendAuthRequest(port, AUTH_REQ_PASSWORD, NULL, 0);
                               2873                 : 
                               2874               0 :     passwd = recv_password_packet(port);
 2209 magnus                   2875 UBC           0 :     if (passwd == NULL)
 2209 magnus                   2876 UIC           0 :         return STATUS_EOF;      /* client wouldn't send password */
                               2877                 : 
                               2878               0 :     if (strlen(passwd) > RADIUS_MAX_PASSWORD_LENGTH)
 2209 magnus                   2879 EUB             :     {
 2209 magnus                   2880 UBC           0 :         ereport(LOG,
 2209 magnus                   2881 EUB             :                 (errmsg("RADIUS authentication does not support passwords longer than %d characters", RADIUS_MAX_PASSWORD_LENGTH)));
 2071 heikki.linnakangas       2882 UBC           0 :         pfree(passwd);
 2209 magnus                   2883               0 :         return STATUS_ERROR;
                               2884                 :     }
                               2885                 : 
                               2886                 :     /*
                               2887                 :      * Loop over and try each server in order.
                               2888                 :      */
 2209 magnus                   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
 2209 magnus                   2904 EUB             :          * STATUS_EOF = Login not OK, and don't try next server
                               2905                 :          *------
                               2906                 :          */
 2209 magnus                   2907 UBC           0 :         if (ret == STATUS_OK)
                               2908                 :         {
  732 michael                  2909               0 :             set_authn_id(port, port->user_name);
  732 michael                  2910 EUB             : 
 2071 heikki.linnakangas       2911 UBC           0 :             pfree(passwd);
 2209 magnus                   2912               0 :             return STATUS_OK;
                               2913                 :         }
                               2914               0 :         else if (ret == STATUS_EOF)
 2071 heikki.linnakangas       2915 EUB             :         {
 2071 heikki.linnakangas       2916 UIC           0 :             pfree(passwd);
 2209 magnus                   2917 UBC           0 :             return STATUS_ERROR;
                               2918                 :         }
                               2919                 : 
 2209 magnus                   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                 :          */
 2209 magnus                   2926 UIC           0 :         if (list_length(port->hba->radiussecrets) > 1)
 1364 tgl                      2927 UBC           0 :             secrets = lnext(port->hba->radiussecrets, secrets);
 2209 magnus                   2928               0 :         if (list_length(port->hba->radiusports) > 1)
 1364 tgl                      2929               0 :             radiusports = lnext(port->hba->radiusports, radiusports);
 2209 magnus                   2930 UIC           0 :         if (list_length(port->hba->radiusidentifiers) > 1)
 1364 tgl                      2931 UBC           0 :             identifiers = lnext(port->hba->radiusidentifiers, identifiers);
                               2932                 :     }
 2209 magnus                   2933 EUB             : 
                               2934                 :     /* No servers left to try, so give up */
 2071 heikki.linnakangas       2935 UIC           0 :     pfree(passwd);
 2209 magnus                   2936 UBC           0 :     return STATUS_ERROR;
 2209 magnus                   2937 EUB             : }
                               2938                 : 
                               2939                 : static int
 1986 peter_e                  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;
 2205 tgl                      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;
 2205 tgl                      2947 UBC           0 :     char       *receive_buffer = (char *) &radius_recv_pack;
 2016 andres                   2948               0 :     int32       service = pg_hton32(RADIUS_AUTHENTICATE_ONLY);
 4790 bruce                    2949 EUB             :     uint8      *cryptvector;
                               2950                 :     int         encryptedpasswordlen;
                               2951                 :     uint8       encryptedpassword[RADIUS_MAX_PASSWORD_LENGTH];
 2772 magnus                   2952                 :     uint8      *md5trailer;
 4790 bruce                    2953                 :     int         packetlength;
                               2954                 :     pgsocket    sock;
                               2955                 : 
 4814 magnus                   2956                 :     struct sockaddr_in6 localaddr;
                               2957                 :     struct sockaddr_in6 remoteaddr;
 4790 bruce                    2958                 :     struct addrinfo hint;
                               2959                 :     struct addrinfo *serveraddrs;
 2209 magnus                   2960                 :     int         port;
                               2961                 :     socklen_t   addrsize;
                               2962                 :     fd_set      fdset;
 4559                          2963                 :     struct timeval endtime;
                               2964                 :     int         i,
                               2965                 :                 j,
 4790 bruce                    2966                 :                 r;
 4820 magnus                   2967                 : 
 2209                          2968                 :     /* Assign default values */
 2209 magnus                   2969 UIC           0 :     if (portstr == NULL)
                               2970               0 :         portstr = "1812";
 2209 magnus                   2971 UBC           0 :     if (identifier == NULL)
 2209 magnus                   2972 UIC           0 :         identifier = "postgresql";
 4820 magnus                   2973 EUB             : 
 4814 magnus                   2974 UBC           0 :     MemSet(&hint, 0, sizeof(hint));
 4814 magnus                   2975 UIC           0 :     hint.ai_socktype = SOCK_DGRAM;
 4814 magnus                   2976 UBC           0 :     hint.ai_family = AF_UNSPEC;
 2209 magnus                   2977 UIC           0 :     port = atoi(portstr);
                               2978                 : 
 2209 magnus                   2979 UBC           0 :     r = pg_getaddrinfo_all(server, portstr, &hint, &serveraddrs);
 4814 magnus                   2980 UIC           0 :     if (r || !serveraddrs)
 4820 magnus                   2981 EUB             :     {
 4820 magnus                   2982 UIC           0 :         ereport(LOG,
                               2983                 :                 (errmsg("could not translate RADIUS server name \"%s\" to address: %s",
 2209 magnus                   2984 EUB             :                         server, gai_strerror(r))));
 4814 magnus                   2985 UBC           0 :         if (serveraddrs)
 4814 magnus                   2986 UIC           0 :             pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
 4820 magnus                   2987 UBC           0 :         return STATUS_ERROR;
 4820 magnus                   2988 EUB             :     }
                               2989                 :     /* XXX: add support for multiple returned addresses? */
                               2990                 : 
                               2991                 :     /* Construct RADIUS packet */
 4820 magnus                   2992 UBC           0 :     packet->code = RADIUS_ACCESS_REQUEST;
                               2993               0 :     packet->length = RADIUS_HEADER_LENGTH;
 1559 michael                  2994 UIC           0 :     if (!pg_strong_random(packet->vector, RADIUS_VECTOR_LENGTH))
                               2995                 :     {
 4820 magnus                   2996 UBC           0 :         ereport(LOG,
 4820 magnus                   2997 EUB             :                 (errmsg("could not generate random encryption vector")));
 2205 tgl                      2998 UBC           0 :         pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
 4820 magnus                   2999               0 :         return STATUS_ERROR;
 4820 magnus                   3000 EUB             :     }
 4820 magnus                   3001 UIC           0 :     packet->id = packet->vector[0];
 1986 peter_e                  3002 UBC           0 :     radius_add_attribute(packet, RADIUS_SERVICE_TYPE, (const unsigned char *) &service, sizeof(service));
 1986 peter_e                  3003 UIC           0 :     radius_add_attribute(packet, RADIUS_USER_NAME, (const unsigned char *) user_name, strlen(user_name));
 1986 peter_e                  3004 UBC           0 :     radius_add_attribute(packet, RADIUS_NAS_IDENTIFIER, (const unsigned char *) identifier, strlen(identifier));
                               3005                 : 
 4820 magnus                   3006 EUB             :     /*
                               3007                 :      * RADIUS password attributes are calculated as: e[0] = p[0] XOR
 2495 rhaas                    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                 :      */
 2772 magnus                   3012 UIC           0 :     encryptedpasswordlen = ((strlen(passwd) + RADIUS_VECTOR_LENGTH - 1) / RADIUS_VECTOR_LENGTH) * RADIUS_VECTOR_LENGTH;
 2209 magnus                   3013 UBC           0 :     cryptvector = palloc(strlen(secret) + RADIUS_VECTOR_LENGTH);
                               3014               0 :     memcpy(cryptvector, secret, strlen(secret));
                               3015                 : 
 2772 magnus                   3016 EUB             :     /* for the first iteration, we use the Request Authenticator vector */
 2772 magnus                   3017 UIC           0 :     md5trailer = packet->vector;
 2772 magnus                   3018 UBC           0 :     for (i = 0; i < encryptedpasswordlen; i += RADIUS_VECTOR_LENGTH)
 4820 magnus                   3019 EUB             :     {
  453 michael                  3020 UBC           0 :         const char *errstr = NULL;
                               3021                 : 
 2209 magnus                   3022 UIC           0 :         memcpy(cryptvector + strlen(secret), md5trailer, RADIUS_VECTOR_LENGTH);
                               3023                 : 
 2495 rhaas                    3024 EUB             :         /*
                               3025                 :          * .. and for subsequent iterations the result of the previous XOR
                               3026                 :          * (calculated below)
                               3027                 :          */
 2772 magnus                   3028 UIC           0 :         md5trailer = encryptedpassword + i;
                               3029                 : 
  453 michael                  3030               0 :         if (!pg_md5_binary(cryptvector, strlen(secret) + RADIUS_VECTOR_LENGTH,
                               3031                 :                            encryptedpassword + i, &errstr))
                               3032                 :         {
 2772 magnus                   3033               0 :             ereport(LOG,
                               3034                 :                     (errmsg("could not perform MD5 encryption of password: %s",
                               3035                 :                             errstr)));
 2772 magnus                   3036 UBC           0 :             pfree(cryptvector);
 2205 tgl                      3037               0 :             pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
 2772 magnus                   3038 UIC           0 :             return STATUS_ERROR;
                               3039                 :         }
 2772 magnus                   3040 EUB             : 
 2495 rhaas                    3041 UIC           0 :         for (j = i; j < i + RADIUS_VECTOR_LENGTH; j++)
                               3042                 :         {
 2772 magnus                   3043               0 :             if (j < strlen(passwd))
 2772 magnus                   3044 UBC           0 :                 encryptedpassword[j] = passwd[j] ^ encryptedpassword[j];
                               3045                 :             else
                               3046               0 :                 encryptedpassword[j] = '\0' ^ encryptedpassword[j];
 2772 magnus                   3047 EUB             :         }
 4820                          3048                 :     }
 4820 magnus                   3049 UIC           0 :     pfree(cryptvector);
 2772 magnus                   3050 EUB             : 
 2772 magnus                   3051 UIC           0 :     radius_add_attribute(packet, RADIUS_PASSWORD, encryptedpassword, encryptedpasswordlen);
                               3052                 : 
 2205 tgl                      3053 EUB             :     /* Length needs to be in network order on the wire */
 4820 magnus                   3054 UBC           0 :     packetlength = packet->length;
 2016 andres                   3055 UIC           0 :     packet->length = pg_hton16(packet->length);
 4820 magnus                   3056 EUB             : 
 4814 magnus                   3057 UBC           0 :     sock = socket(serveraddrs[0].ai_family, SOCK_DGRAM, 0);
 3280 bruce                    3058 UIC           0 :     if (sock == PGINVALID_SOCKET)
 4820 magnus                   3059 EUB             :     {
 4820 magnus                   3060 UBC           0 :         ereport(LOG,
                               3061                 :                 (errmsg("could not create RADIUS socket: %m")));
 4814                          3062               0 :         pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
 4820                          3063               0 :         return STATUS_ERROR;
                               3064                 :     }
 4820 magnus                   3065 EUB             : 
 4820 magnus                   3066 UBC           0 :     memset(&localaddr, 0, sizeof(localaddr));
 4814 magnus                   3067 UIC           0 :     localaddr.sin6_family = serveraddrs[0].ai_family;
 4814 magnus                   3068 UBC           0 :     localaddr.sin6_addr = in6addr_any;
 4814 magnus                   3069 UIC           0 :     if (localaddr.sin6_family == AF_INET6)
 4814 magnus                   3070 UBC           0 :         addrsize = sizeof(struct sockaddr_in6);
 4814 magnus                   3071 EUB             :     else
 4814 magnus                   3072 UIC           0 :         addrsize = sizeof(struct sockaddr_in);
 2205 tgl                      3073 EUB             : 
 2118 tgl                      3074 UBC           0 :     if (bind(sock, (struct sockaddr *) &localaddr, addrsize))
                               3075                 :     {
 4820 magnus                   3076 UIC           0 :         ereport(LOG,
                               3077                 :                 (errmsg("could not bind local RADIUS socket: %m")));
                               3078               0 :         closesocket(sock);
 4814                          3079               0 :         pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
 4820                          3080               0 :         return STATUS_ERROR;
                               3081                 :     }
                               3082                 : 
                               3083               0 :     if (sendto(sock, radius_buffer, packetlength, 0,
 4814                          3084               0 :                serveraddrs[0].ai_addr, serveraddrs[0].ai_addrlen) < 0)
                               3085                 :     {
 4820                          3086               0 :         ereport(LOG,
                               3087                 :                 (errmsg("could not send RADIUS packet: %m")));
 4820 magnus                   3088 UBC           0 :         closesocket(sock);
 4814                          3089               0 :         pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
 4820 magnus                   3090 UIC           0 :         return STATUS_ERROR;
 4820 magnus                   3091 EUB             :     }
                               3092                 : 
 4814                          3093                 :     /* Don't need the server address anymore */
 4814 magnus                   3094 UIC           0 :     pg_freeaddrinfo_all(hint.ai_family, serveraddrs);
 4814 magnus                   3095 EUB             : 
 4559                          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
 4382 bruce                    3099                 :      * packets to our port thus causing us to retry in a loop and never time
                               3100                 :      * out.
 2987 andres                   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                 :      */
 4559 magnus                   3106 UIC           0 :     gettimeofday(&endtime, NULL);
 4559 magnus                   3107 UBC           0 :     endtime.tv_sec += RADIUS_TIMEOUT;
                               3108                 : 
 4820 magnus                   3109 EUB             :     while (true)
 4820 magnus                   3110 UIC           0 :     {
 4559 magnus                   3111 EUB             :         struct timeval timeout;
                               3112                 :         struct timeval now;
                               3113                 :         int64       timeoutval;
  453 michael                  3114 UBC           0 :         const char *errstr = NULL;
                               3115                 : 
 4559 magnus                   3116               0 :         gettimeofday(&now, NULL);
 4559 magnus                   3117 UIC           0 :         timeoutval = (endtime.tv_sec * 1000000 + endtime.tv_usec) - (now.tv_sec * 1000000 + now.tv_usec);
                               3118               0 :         if (timeoutval <= 0)
 4559 magnus                   3119 EUB             :         {
 4559 magnus                   3120 UIC           0 :             ereport(LOG,
                               3121                 :                     (errmsg("timeout waiting for RADIUS response from %s",
 2209 magnus                   3122 EUB             :                             server)));
 4559 magnus                   3123 UIC           0 :             closesocket(sock);
 4559 magnus                   3124 UBC           0 :             return STATUS_ERROR;
                               3125                 :         }
 4559 magnus                   3126 UIC           0 :         timeout.tv_sec = timeoutval / 1000000;
 4559 magnus                   3127 UBC           0 :         timeout.tv_usec = timeoutval % 1000000;
                               3128                 : 
 4559 magnus                   3129 UIC           0 :         FD_ZERO(&fdset);
                               3130               0 :         FD_SET(sock, &fdset);
                               3131                 : 
 4820                          3132               0 :         r = select(sock + 1, &fdset, NULL, NULL, &timeout);
                               3133               0 :         if (r < 0)
 4820 magnus                   3134 EUB             :         {
 4820 magnus                   3135 UIC           0 :             if (errno == EINTR)
 4820 magnus                   3136 UBC           0 :                 continue;
 4820 magnus                   3137 EUB             : 
                               3138                 :             /* Anything else is an actual error */
 4820 magnus                   3139 UIC           0 :             ereport(LOG,
 4820 magnus                   3140 EUB             :                     (errmsg("could not check status on RADIUS socket: %m")));
 4820 magnus                   3141 UIC           0 :             closesocket(sock);
 4820 magnus                   3142 UBC           0 :             return STATUS_ERROR;
 4820 magnus                   3143 EUB             :         }
 4820 magnus                   3144 UIC           0 :         if (r == 0)
 4820 magnus                   3145 EUB             :         {
 4820 magnus                   3146 UBC           0 :             ereport(LOG,
                               3147                 :                     (errmsg("timeout waiting for RADIUS response from %s",
                               3148                 :                             server)));
                               3149               0 :             closesocket(sock);
 4820 magnus                   3150 UIC           0 :             return STATUS_ERROR;
                               3151                 :         }
 4820 magnus                   3152 EUB             : 
 4559                          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
 4382 bruce                    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.
 4559 magnus                   3162                 :          */
                               3163                 : 
 4559 magnus                   3164 UIC           0 :         addrsize = sizeof(remoteaddr);
 4559 magnus                   3165 UBC           0 :         packetlength = recvfrom(sock, receive_buffer, RADIUS_BUFFER_SIZE, 0,
                               3166                 :                                 (struct sockaddr *) &remoteaddr, &addrsize);
                               3167               0 :         if (packetlength < 0)
 4559 magnus                   3168 EUB             :         {
 4559 magnus                   3169 UIC           0 :             ereport(LOG,
 4559 magnus                   3170 EUB             :                     (errmsg("could not read RADIUS response: %m")));
 2205 tgl                      3171 UIC           0 :             closesocket(sock);
 4559 magnus                   3172 UBC           0 :             return STATUS_ERROR;
 4559 magnus                   3173 EUB             :         }
                               3174                 : 
 2016 andres                   3175 UIC           0 :         if (remoteaddr.sin6_port != pg_hton16(port))
 4559 magnus                   3176 EUB             :         {
 4559 magnus                   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                 : 
 2016 andres                   3190               0 :         if (packetlength != pg_ntoh16(receivepacket->length))
                               3191                 :         {
 4559 magnus                   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                 :          */
 2209                          3210               0 :         cryptvector = palloc(packetlength + strlen(secret));
                               3211                 : 
 4382 bruce                    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 */
 2118 tgl                      3216               0 :         if (packetlength > RADIUS_HEADER_LENGTH) /* there may be no
                               3217                 :                                                      * attributes at all */
 4559 magnus                   3218               0 :             memcpy(cryptvector + RADIUS_HEADER_LENGTH, receive_buffer + RADIUS_HEADER_LENGTH, packetlength - RADIUS_HEADER_LENGTH);
 2209                          3219               0 :         memcpy(cryptvector + packetlength, secret, strlen(secret));
                               3220                 : 
 4559                          3221               0 :         if (!pg_md5_binary(cryptvector,
 2209                          3222               0 :                            packetlength + strlen(secret),
                               3223                 :                            encryptedpassword, &errstr))
                               3224                 :         {
 4559                          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                 :         }
 4820                          3231               0 :         pfree(cryptvector);
                               3232                 : 
 4559                          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);
 2209                          3249               0 :             return STATUS_EOF;
                               3250                 :         }
                               3251                 :         else
                               3252                 :         {
 4559                          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