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