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