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