Coverage Report

Created: 2026-10-16 06:48

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