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