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