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