1 /*-------------------------------------------------------------------------
2  *
3  * fe-auth.c
4  *	   The front-end (client) authorization routines
5  *
6  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  * IDENTIFICATION
10  *	  src/interfaces/libpq/fe-auth.c
11  *
12  *-------------------------------------------------------------------------
13  */
14 
15 /*
16  * INTERFACE ROUTINES
17  *	   frontend (client) routines:
18  *		pg_fe_sendauth			send authentication information
19  *		pg_fe_getauthname		get user's name according to the client side
20  *								of the authentication system
21  */
22 
23 #include "postgres_fe.h"
24 
25 #ifdef WIN32
26 #include "win32.h"
27 #else
28 #include <unistd.h>
29 #include <fcntl.h>
30 #include <sys/param.h>			/* for MAXHOSTNAMELEN on most */
31 #include <sys/socket.h>
32 #ifdef HAVE_SYS_UCRED_H
33 #include <sys/ucred.h>
34 #endif
35 #ifndef  MAXHOSTNAMELEN
36 #include <netdb.h>				/* for MAXHOSTNAMELEN on some */
37 #endif
38 #include <pwd.h>
39 #endif
40 
41 #include "common/md5.h"
42 #include "common/scram-common.h"
43 #include "libpq-fe.h"
44 #include "fe-auth.h"
45 
46 
47 #ifdef ENABLE_GSS
48 /*
49  * GSSAPI authentication system.
50  */
51 
52 #include "fe-gssapi-common.h"
53 
54 /*
55  * Continue GSS authentication with next token as needed.
56  */
57 static int
pg_GSS_continue(PGconn * conn,int payloadlen)58 pg_GSS_continue(PGconn *conn, int payloadlen)
59 {
60 	OM_uint32	maj_stat,
61 				min_stat,
62 				lmin_s;
63 	gss_buffer_desc ginbuf;
64 	gss_buffer_desc goutbuf;
65 
66 	/*
67 	 * On first call, there's no input token. On subsequent calls, read the
68 	 * input token into a GSS buffer.
69 	 */
70 	if (conn->gctx != GSS_C_NO_CONTEXT)
71 	{
72 		ginbuf.length = payloadlen;
73 		ginbuf.value = malloc(payloadlen);
74 		if (!ginbuf.value)
75 		{
76 			printfPQExpBuffer(&conn->errorMessage,
77 							  libpq_gettext("out of memory allocating GSSAPI buffer (%d)\n"),
78 							  payloadlen);
79 			return STATUS_ERROR;
80 		}
81 		if (pqGetnchar(ginbuf.value, payloadlen, conn))
82 		{
83 			/*
84 			 * Shouldn't happen, because the caller should've ensured that the
85 			 * whole message is already in the input buffer.
86 			 */
87 			free(ginbuf.value);
88 			return STATUS_ERROR;
89 		}
90 	}
91 	else
92 	{
93 		ginbuf.length = 0;
94 		ginbuf.value = NULL;
95 	}
96 
97 	maj_stat = gss_init_sec_context(&min_stat,
98 									GSS_C_NO_CREDENTIAL,
99 									&conn->gctx,
100 									conn->gtarg_nam,
101 									GSS_C_NO_OID,
102 									GSS_C_MUTUAL_FLAG,
103 									0,
104 									GSS_C_NO_CHANNEL_BINDINGS,
105 									(ginbuf.value == NULL) ? GSS_C_NO_BUFFER : &ginbuf,
106 									NULL,
107 									&goutbuf,
108 									NULL,
109 									NULL);
110 
111 	if (ginbuf.value)
112 		free(ginbuf.value);
113 
114 	if (goutbuf.length != 0)
115 	{
116 		/*
117 		 * GSS generated data to send to the server. We don't care if it's the
118 		 * first or subsequent packet, just send the same kind of password
119 		 * packet.
120 		 */
121 		if (pqPacketSend(conn, 'p',
122 						 goutbuf.value, goutbuf.length) != STATUS_OK)
123 		{
124 			gss_release_buffer(&lmin_s, &goutbuf);
125 			return STATUS_ERROR;
126 		}
127 	}
128 	gss_release_buffer(&lmin_s, &goutbuf);
129 
130 	if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
131 	{
132 		pg_GSS_error(libpq_gettext("GSSAPI continuation error"),
133 					 conn,
134 					 maj_stat, min_stat);
135 		gss_release_name(&lmin_s, &conn->gtarg_nam);
136 		if (conn->gctx)
137 			gss_delete_sec_context(&lmin_s, &conn->gctx, GSS_C_NO_BUFFER);
138 		return STATUS_ERROR;
139 	}
140 
141 	if (maj_stat == GSS_S_COMPLETE)
142 		gss_release_name(&lmin_s, &conn->gtarg_nam);
143 
144 	return STATUS_OK;
145 }
146 
147 /*
148  * Send initial GSS authentication token
149  */
150 static int
pg_GSS_startup(PGconn * conn,int payloadlen)151 pg_GSS_startup(PGconn *conn, int payloadlen)
152 {
153 	int			ret;
154 	char	   *host = conn->connhost[conn->whichhost].host;
155 
156 	if (!(host && host[0] != '\0'))
157 	{
158 		printfPQExpBuffer(&conn->errorMessage,
159 						  libpq_gettext("host name must be specified\n"));
160 		return STATUS_ERROR;
161 	}
162 
163 	if (conn->gctx)
164 	{
165 		printfPQExpBuffer(&conn->errorMessage,
166 						  libpq_gettext("duplicate GSS authentication request\n"));
167 		return STATUS_ERROR;
168 	}
169 
170 	ret = pg_GSS_load_servicename(conn);
171 	if (ret != STATUS_OK)
172 		return ret;
173 
174 	/*
175 	 * Initial packet is the same as a continuation packet with no initial
176 	 * context.
177 	 */
178 	conn->gctx = GSS_C_NO_CONTEXT;
179 
180 	return pg_GSS_continue(conn, payloadlen);
181 }
182 #endif							/* ENABLE_GSS */
183 
184 
185 #ifdef ENABLE_SSPI
186 /*
187  * SSPI authentication system (Windows only)
188  */
189 
190 static void
pg_SSPI_error(PGconn * conn,const char * mprefix,SECURITY_STATUS r)191 pg_SSPI_error(PGconn *conn, const char *mprefix, SECURITY_STATUS r)
192 {
193 	char		sysmsg[256];
194 
195 	if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS |
196 					  FORMAT_MESSAGE_FROM_SYSTEM,
197 					  NULL, r, 0,
198 					  sysmsg, sizeof(sysmsg), NULL) == 0)
199 		printfPQExpBuffer(&conn->errorMessage, "%s: SSPI error %x\n",
200 						  mprefix, (unsigned int) r);
201 	else
202 		printfPQExpBuffer(&conn->errorMessage, "%s: %s (%x)\n",
203 						  mprefix, sysmsg, (unsigned int) r);
204 }
205 
206 /*
207  * Continue SSPI authentication with next token as needed.
208  */
209 static int
pg_SSPI_continue(PGconn * conn,int payloadlen)210 pg_SSPI_continue(PGconn *conn, int payloadlen)
211 {
212 	SECURITY_STATUS r;
213 	CtxtHandle	newContext;
214 	ULONG		contextAttr;
215 	SecBufferDesc inbuf;
216 	SecBufferDesc outbuf;
217 	SecBuffer	OutBuffers[1];
218 	SecBuffer	InBuffers[1];
219 	char	   *inputbuf = NULL;
220 
221 	if (conn->sspictx != NULL)
222 	{
223 		/*
224 		 * On runs other than the first we have some data to send. Put this
225 		 * data in a SecBuffer type structure.
226 		 */
227 		inputbuf = malloc(payloadlen);
228 		if (!inputbuf)
229 		{
230 			printfPQExpBuffer(&conn->errorMessage,
231 							  libpq_gettext("out of memory allocating SSPI buffer (%d)\n"),
232 							  payloadlen);
233 			return STATUS_ERROR;
234 		}
235 		if (pqGetnchar(inputbuf, payloadlen, conn))
236 		{
237 			/*
238 			 * Shouldn't happen, because the caller should've ensured that the
239 			 * whole message is already in the input buffer.
240 			 */
241 			free(inputbuf);
242 			return STATUS_ERROR;
243 		}
244 
245 		inbuf.ulVersion = SECBUFFER_VERSION;
246 		inbuf.cBuffers = 1;
247 		inbuf.pBuffers = InBuffers;
248 		InBuffers[0].pvBuffer = inputbuf;
249 		InBuffers[0].cbBuffer = payloadlen;
250 		InBuffers[0].BufferType = SECBUFFER_TOKEN;
251 	}
252 
253 	OutBuffers[0].pvBuffer = NULL;
254 	OutBuffers[0].BufferType = SECBUFFER_TOKEN;
255 	OutBuffers[0].cbBuffer = 0;
256 	outbuf.cBuffers = 1;
257 	outbuf.pBuffers = OutBuffers;
258 	outbuf.ulVersion = SECBUFFER_VERSION;
259 
260 	r = InitializeSecurityContext(conn->sspicred,
261 								  conn->sspictx,
262 								  conn->sspitarget,
263 								  ISC_REQ_ALLOCATE_MEMORY,
264 								  0,
265 								  SECURITY_NETWORK_DREP,
266 								  (conn->sspictx == NULL) ? NULL : &inbuf,
267 								  0,
268 								  &newContext,
269 								  &outbuf,
270 								  &contextAttr,
271 								  NULL);
272 
273 	/* we don't need the input anymore */
274 	if (inputbuf)
275 		free(inputbuf);
276 
277 	if (r != SEC_E_OK && r != SEC_I_CONTINUE_NEEDED)
278 	{
279 		pg_SSPI_error(conn, libpq_gettext("SSPI continuation error"), r);
280 
281 		return STATUS_ERROR;
282 	}
283 
284 	if (conn->sspictx == NULL)
285 	{
286 		/* On first run, transfer retrieved context handle */
287 		conn->sspictx = malloc(sizeof(CtxtHandle));
288 		if (conn->sspictx == NULL)
289 		{
290 			printfPQExpBuffer(&conn->errorMessage, libpq_gettext("out of memory\n"));
291 			return STATUS_ERROR;
292 		}
293 		memcpy(conn->sspictx, &newContext, sizeof(CtxtHandle));
294 	}
295 
296 	/*
297 	 * If SSPI returned any data to be sent to the server (as it normally
298 	 * would), send this data as a password packet.
299 	 */
300 	if (outbuf.cBuffers > 0)
301 	{
302 		if (outbuf.cBuffers != 1)
303 		{
304 			/*
305 			 * This should never happen, at least not for Kerberos
306 			 * authentication. Keep check in case it shows up with other
307 			 * authentication methods later.
308 			 */
309 			printfPQExpBuffer(&conn->errorMessage, "SSPI returned invalid number of output buffers\n");
310 			return STATUS_ERROR;
311 		}
312 
313 		/*
314 		 * If the negotiation is complete, there may be zero bytes to send.
315 		 * The server is at this point not expecting any more data, so don't
316 		 * send it.
317 		 */
318 		if (outbuf.pBuffers[0].cbBuffer > 0)
319 		{
320 			if (pqPacketSend(conn, 'p',
321 							 outbuf.pBuffers[0].pvBuffer, outbuf.pBuffers[0].cbBuffer))
322 			{
323 				FreeContextBuffer(outbuf.pBuffers[0].pvBuffer);
324 				return STATUS_ERROR;
325 			}
326 		}
327 		FreeContextBuffer(outbuf.pBuffers[0].pvBuffer);
328 	}
329 
330 	/* Cleanup is handled by the code in freePGconn() */
331 	return STATUS_OK;
332 }
333 
334 /*
335  * Send initial SSPI authentication token.
336  * If use_negotiate is 0, use kerberos authentication package which is
337  * compatible with Unix. If use_negotiate is 1, use the negotiate package
338  * which supports both kerberos and NTLM, but is not compatible with Unix.
339  */
340 static int
pg_SSPI_startup(PGconn * conn,int use_negotiate,int payloadlen)341 pg_SSPI_startup(PGconn *conn, int use_negotiate, int payloadlen)
342 {
343 	SECURITY_STATUS r;
344 	TimeStamp	expire;
345 	char	   *host = conn->connhost[conn->whichhost].host;
346 
347 	if (conn->sspictx)
348 	{
349 		printfPQExpBuffer(&conn->errorMessage,
350 						  libpq_gettext("duplicate SSPI authentication request\n"));
351 		return STATUS_ERROR;
352 	}
353 
354 	/*
355 	 * Retrieve credentials handle
356 	 */
357 	conn->sspicred = malloc(sizeof(CredHandle));
358 	if (conn->sspicred == NULL)
359 	{
360 		printfPQExpBuffer(&conn->errorMessage, libpq_gettext("out of memory\n"));
361 		return STATUS_ERROR;
362 	}
363 
364 	r = AcquireCredentialsHandle(NULL,
365 								 use_negotiate ? "negotiate" : "kerberos",
366 								 SECPKG_CRED_OUTBOUND,
367 								 NULL,
368 								 NULL,
369 								 NULL,
370 								 NULL,
371 								 conn->sspicred,
372 								 &expire);
373 	if (r != SEC_E_OK)
374 	{
375 		pg_SSPI_error(conn, libpq_gettext("could not acquire SSPI credentials"), r);
376 		free(conn->sspicred);
377 		conn->sspicred = NULL;
378 		return STATUS_ERROR;
379 	}
380 
381 	/*
382 	 * Compute target principal name. SSPI has a different format from GSSAPI,
383 	 * but not more complex. We can skip the @REALM part, because Windows will
384 	 * fill that in for us automatically.
385 	 */
386 	if (!(host && host[0] != '\0'))
387 	{
388 		printfPQExpBuffer(&conn->errorMessage,
389 						  libpq_gettext("host name must be specified\n"));
390 		return STATUS_ERROR;
391 	}
392 	conn->sspitarget = malloc(strlen(conn->krbsrvname) + strlen(host) + 2);
393 	if (!conn->sspitarget)
394 	{
395 		printfPQExpBuffer(&conn->errorMessage, libpq_gettext("out of memory\n"));
396 		return STATUS_ERROR;
397 	}
398 	sprintf(conn->sspitarget, "%s/%s", conn->krbsrvname, host);
399 
400 	/*
401 	 * Indicate that we're in SSPI authentication mode to make sure that
402 	 * pg_SSPI_continue is called next time in the negotiation.
403 	 */
404 	conn->usesspi = 1;
405 
406 	return pg_SSPI_continue(conn, payloadlen);
407 }
408 #endif							/* ENABLE_SSPI */
409 
410 /*
411  * Initialize SASL authentication exchange.
412  */
413 static int
pg_SASL_init(PGconn * conn,int payloadlen)414 pg_SASL_init(PGconn *conn, int payloadlen)
415 {
416 	char	   *initialresponse = NULL;
417 	int			initialresponselen;
418 	bool		done;
419 	bool		success;
420 	const char *selected_mechanism;
421 	PQExpBufferData mechanism_buf;
422 	char	   *password;
423 
424 	initPQExpBuffer(&mechanism_buf);
425 
426 	if (conn->sasl_state)
427 	{
428 		printfPQExpBuffer(&conn->errorMessage,
429 						  libpq_gettext("duplicate SASL authentication request\n"));
430 		goto error;
431 	}
432 
433 	/*
434 	 * Parse the list of SASL authentication mechanisms in the
435 	 * AuthenticationSASL message, and select the best mechanism that we
436 	 * support.  SCRAM-SHA-256-PLUS and SCRAM-SHA-256 are the only ones
437 	 * supported at the moment, listed by order of decreasing importance.
438 	 */
439 	selected_mechanism = NULL;
440 	for (;;)
441 	{
442 		if (pqGets(&mechanism_buf, conn))
443 		{
444 			printfPQExpBuffer(&conn->errorMessage,
445 							  "fe_sendauth: invalid authentication request from server: invalid list of authentication mechanisms\n");
446 			goto error;
447 		}
448 		if (PQExpBufferDataBroken(mechanism_buf))
449 			goto oom_error;
450 
451 		/* An empty string indicates end of list */
452 		if (mechanism_buf.data[0] == '\0')
453 			break;
454 
455 		/*
456 		 * Select the mechanism to use.  Pick SCRAM-SHA-256-PLUS over anything
457 		 * else if a channel binding type is set and if the client supports
458 		 * it. Pick SCRAM-SHA-256 if nothing else has already been picked.  If
459 		 * we add more mechanisms, a more refined priority mechanism might
460 		 * become necessary.
461 		 */
462 		if (strcmp(mechanism_buf.data, SCRAM_SHA_256_PLUS_NAME) == 0)
463 		{
464 			if (conn->ssl_in_use)
465 			{
466 				/*
467 				 * The server has offered SCRAM-SHA-256-PLUS, which is only
468 				 * supported by the client if a hash of the peer certificate
469 				 * can be created.
470 				 */
471 #ifdef HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH
472 				selected_mechanism = SCRAM_SHA_256_PLUS_NAME;
473 #endif
474 			}
475 			else
476 			{
477 				/*
478 				 * The server offered SCRAM-SHA-256-PLUS, but the connection
479 				 * is not SSL-encrypted. That's not sane. Perhaps SSL was
480 				 * stripped by a proxy? There's no point in continuing,
481 				 * because the server will reject the connection anyway if we
482 				 * try authenticate without channel binding even though both
483 				 * the client and server supported it. The SCRAM exchange
484 				 * checks for that, to prevent downgrade attacks.
485 				 */
486 				printfPQExpBuffer(&conn->errorMessage,
487 								  libpq_gettext("server offered SCRAM-SHA-256-PLUS authentication over a non-SSL connection\n"));
488 				goto error;
489 			}
490 		}
491 		else if (strcmp(mechanism_buf.data, SCRAM_SHA_256_NAME) == 0 &&
492 				 !selected_mechanism)
493 			selected_mechanism = SCRAM_SHA_256_NAME;
494 	}
495 
496 	if (!selected_mechanism)
497 	{
498 		printfPQExpBuffer(&conn->errorMessage,
499 						  libpq_gettext("none of the server's SASL authentication mechanisms are supported\n"));
500 		goto error;
501 	}
502 
503 	/*
504 	 * Now that the SASL mechanism has been chosen for the exchange,
505 	 * initialize its state information.
506 	 */
507 
508 	/*
509 	 * First, select the password to use for the exchange, complaining if
510 	 * there isn't one.  Currently, all supported SASL mechanisms require a
511 	 * password, so we can just go ahead here without further distinction.
512 	 */
513 	conn->password_needed = true;
514 	password = conn->connhost[conn->whichhost].password;
515 	if (password == NULL)
516 		password = conn->pgpass;
517 	if (password == NULL || password[0] == '\0')
518 	{
519 		printfPQExpBuffer(&conn->errorMessage,
520 						  PQnoPasswordSupplied);
521 		goto error;
522 	}
523 
524 	/*
525 	 * Initialize the SASL state information with all the information gathered
526 	 * during the initial exchange.
527 	 *
528 	 * Note: Only tls-unique is supported for the moment.
529 	 */
530 	conn->sasl_state = pg_fe_scram_init(conn,
531 										password,
532 										selected_mechanism);
533 	if (!conn->sasl_state)
534 		goto oom_error;
535 
536 	/* Get the mechanism-specific Initial Client Response, if any */
537 	pg_fe_scram_exchange(conn->sasl_state,
538 						 NULL, -1,
539 						 &initialresponse, &initialresponselen,
540 						 &done, &success);
541 
542 	if (done && !success)
543 		goto error;
544 
545 	/*
546 	 * Build a SASLInitialResponse message, and send it.
547 	 */
548 	if (pqPutMsgStart('p', true, conn))
549 		goto error;
550 	if (pqPuts(selected_mechanism, conn))
551 		goto error;
552 	if (initialresponse)
553 	{
554 		if (pqPutInt(initialresponselen, 4, conn))
555 			goto error;
556 		if (pqPutnchar(initialresponse, initialresponselen, conn))
557 			goto error;
558 	}
559 	if (pqPutMsgEnd(conn))
560 		goto error;
561 	if (pqFlush(conn))
562 		goto error;
563 
564 	termPQExpBuffer(&mechanism_buf);
565 	if (initialresponse)
566 		free(initialresponse);
567 
568 	return STATUS_OK;
569 
570 error:
571 	termPQExpBuffer(&mechanism_buf);
572 	if (initialresponse)
573 		free(initialresponse);
574 	return STATUS_ERROR;
575 
576 oom_error:
577 	termPQExpBuffer(&mechanism_buf);
578 	if (initialresponse)
579 		free(initialresponse);
580 	printfPQExpBuffer(&conn->errorMessage,
581 					  libpq_gettext("out of memory\n"));
582 	return STATUS_ERROR;
583 }
584 
585 /*
586  * Exchange a message for SASL communication protocol with the backend.
587  * This should be used after calling pg_SASL_init to set up the status of
588  * the protocol.
589  */
590 static int
pg_SASL_continue(PGconn * conn,int payloadlen,bool final)591 pg_SASL_continue(PGconn *conn, int payloadlen, bool final)
592 {
593 	char	   *output;
594 	int			outputlen;
595 	bool		done;
596 	bool		success;
597 	int			res;
598 	char	   *challenge;
599 
600 	/* Read the SASL challenge from the AuthenticationSASLContinue message. */
601 	challenge = malloc(payloadlen + 1);
602 	if (!challenge)
603 	{
604 		printfPQExpBuffer(&conn->errorMessage,
605 						  libpq_gettext("out of memory allocating SASL buffer (%d)\n"),
606 						  payloadlen);
607 		return STATUS_ERROR;
608 	}
609 
610 	if (pqGetnchar(challenge, payloadlen, conn))
611 	{
612 		free(challenge);
613 		return STATUS_ERROR;
614 	}
615 	/* For safety and convenience, ensure the buffer is NULL-terminated. */
616 	challenge[payloadlen] = '\0';
617 
618 	pg_fe_scram_exchange(conn->sasl_state,
619 						 challenge, payloadlen,
620 						 &output, &outputlen,
621 						 &done, &success);
622 	free(challenge);			/* don't need the input anymore */
623 
624 	if (final && !done)
625 	{
626 		if (outputlen != 0)
627 			free(output);
628 
629 		printfPQExpBuffer(&conn->errorMessage,
630 						  libpq_gettext("AuthenticationSASLFinal received from server, but SASL authentication was not completed\n"));
631 		return STATUS_ERROR;
632 	}
633 	if (outputlen != 0)
634 	{
635 		/*
636 		 * Send the SASL response to the server.
637 		 */
638 		res = pqPacketSend(conn, 'p', output, outputlen);
639 		free(output);
640 
641 		if (res != STATUS_OK)
642 			return STATUS_ERROR;
643 	}
644 
645 	if (done && !success)
646 		return STATUS_ERROR;
647 
648 	return STATUS_OK;
649 }
650 
651 /*
652  * Respond to AUTH_REQ_SCM_CREDS challenge.
653  *
654  * Note: this is dead code as of Postgres 9.1, because current backends will
655  * never send this challenge.  But we must keep it as long as libpq needs to
656  * interoperate with pre-9.1 servers.  It is believed to be needed only on
657  * Debian/kFreeBSD (ie, FreeBSD kernel with Linux userland, so that the
658  * getpeereid() function isn't provided by libc).
659  */
660 static int
pg_local_sendauth(PGconn * conn)661 pg_local_sendauth(PGconn *conn)
662 {
663 #ifdef HAVE_STRUCT_CMSGCRED
664 	char		buf;
665 	struct iovec iov;
666 	struct msghdr msg;
667 	struct cmsghdr *cmsg;
668 	union
669 	{
670 		struct cmsghdr hdr;
671 		unsigned char buf[CMSG_SPACE(sizeof(struct cmsgcred))];
672 	}			cmsgbuf;
673 
674 	/*
675 	 * The backend doesn't care what we send here, but it wants exactly one
676 	 * character to force recvmsg() to block and wait for us.
677 	 */
678 	buf = '\0';
679 	iov.iov_base = &buf;
680 	iov.iov_len = 1;
681 
682 	memset(&msg, 0, sizeof(msg));
683 	msg.msg_iov = &iov;
684 	msg.msg_iovlen = 1;
685 
686 	/* We must set up a message that will be filled in by kernel */
687 	memset(&cmsgbuf, 0, sizeof(cmsgbuf));
688 	msg.msg_control = &cmsgbuf.buf;
689 	msg.msg_controllen = sizeof(cmsgbuf.buf);
690 	cmsg = CMSG_FIRSTHDR(&msg);
691 	cmsg->cmsg_len = CMSG_LEN(sizeof(struct cmsgcred));
692 	cmsg->cmsg_level = SOL_SOCKET;
693 	cmsg->cmsg_type = SCM_CREDS;
694 
695 	if (sendmsg(conn->sock, &msg, 0) == -1)
696 	{
697 		char		sebuf[PG_STRERROR_R_BUFLEN];
698 
699 		printfPQExpBuffer(&conn->errorMessage,
700 						  "pg_local_sendauth: sendmsg: %s\n",
701 						  strerror_r(errno, sebuf, sizeof(sebuf)));
702 		return STATUS_ERROR;
703 	}
704 	return STATUS_OK;
705 #else
706 	printfPQExpBuffer(&conn->errorMessage,
707 					  libpq_gettext("SCM_CRED authentication method not supported\n"));
708 	return STATUS_ERROR;
709 #endif
710 }
711 
712 static int
pg_password_sendauth(PGconn * conn,const char * password,AuthRequest areq)713 pg_password_sendauth(PGconn *conn, const char *password, AuthRequest areq)
714 {
715 	int			ret;
716 	char	   *crypt_pwd = NULL;
717 	const char *pwd_to_send;
718 	char		md5Salt[4];
719 
720 	/* Read the salt from the AuthenticationMD5Password message. */
721 	if (areq == AUTH_REQ_MD5)
722 	{
723 		if (pqGetnchar(md5Salt, 4, conn))
724 			return STATUS_ERROR;	/* shouldn't happen */
725 	}
726 
727 	/* Encrypt the password if needed. */
728 
729 	switch (areq)
730 	{
731 		case AUTH_REQ_MD5:
732 			{
733 				char	   *crypt_pwd2;
734 
735 				/* Allocate enough space for two MD5 hashes */
736 				crypt_pwd = malloc(2 * (MD5_PASSWD_LEN + 1));
737 				if (!crypt_pwd)
738 				{
739 					printfPQExpBuffer(&conn->errorMessage,
740 									  libpq_gettext("out of memory\n"));
741 					return STATUS_ERROR;
742 				}
743 
744 				crypt_pwd2 = crypt_pwd + MD5_PASSWD_LEN + 1;
745 				if (!pg_md5_encrypt(password, conn->pguser,
746 									strlen(conn->pguser), crypt_pwd2))
747 				{
748 					free(crypt_pwd);
749 					return STATUS_ERROR;
750 				}
751 				if (!pg_md5_encrypt(crypt_pwd2 + strlen("md5"), md5Salt,
752 									4, crypt_pwd))
753 				{
754 					free(crypt_pwd);
755 					return STATUS_ERROR;
756 				}
757 
758 				pwd_to_send = crypt_pwd;
759 				break;
760 			}
761 		case AUTH_REQ_PASSWORD:
762 			pwd_to_send = password;
763 			break;
764 		default:
765 			return STATUS_ERROR;
766 	}
767 	/* Packet has a message type as of protocol 3.0 */
768 	if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
769 		ret = pqPacketSend(conn, 'p', pwd_to_send, strlen(pwd_to_send) + 1);
770 	else
771 		ret = pqPacketSend(conn, 0, pwd_to_send, strlen(pwd_to_send) + 1);
772 	if (crypt_pwd)
773 		free(crypt_pwd);
774 	return ret;
775 }
776 
777 /*
778  * pg_fe_sendauth
779  *		client demux routine for processing an authentication request
780  *
781  * The server has sent us an authentication challenge (or OK). Send an
782  * appropriate response. The caller has ensured that the whole message is
783  * now in the input buffer, and has already read the type and length of
784  * it. We are responsible for reading any remaining extra data, specific
785  * to the authentication method. 'payloadlen' is the remaining length in
786  * the message.
787  */
788 int
pg_fe_sendauth(AuthRequest areq,int payloadlen,PGconn * conn)789 pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn)
790 {
791 	switch (areq)
792 	{
793 		case AUTH_REQ_OK:
794 			break;
795 
796 		case AUTH_REQ_KRB4:
797 			printfPQExpBuffer(&conn->errorMessage,
798 							  libpq_gettext("Kerberos 4 authentication not supported\n"));
799 			return STATUS_ERROR;
800 
801 		case AUTH_REQ_KRB5:
802 			printfPQExpBuffer(&conn->errorMessage,
803 							  libpq_gettext("Kerberos 5 authentication not supported\n"));
804 			return STATUS_ERROR;
805 
806 #if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
807 		case AUTH_REQ_GSS:
808 #if !defined(ENABLE_SSPI)
809 			/* no native SSPI, so use GSSAPI library for it */
810 		case AUTH_REQ_SSPI:
811 #endif
812 			{
813 				int			r;
814 
815 				pglock_thread();
816 
817 				/*
818 				 * If we have both GSS and SSPI support compiled in, use SSPI
819 				 * support by default. This is overridable by a connection
820 				 * string parameter. Note that when using SSPI we still leave
821 				 * the negotiate parameter off, since we want SSPI to use the
822 				 * GSSAPI kerberos protocol. For actual SSPI negotiate
823 				 * protocol, we use AUTH_REQ_SSPI.
824 				 */
825 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
826 				if (conn->gsslib && (pg_strcasecmp(conn->gsslib, "gssapi") == 0))
827 					r = pg_GSS_startup(conn, payloadlen);
828 				else
829 					r = pg_SSPI_startup(conn, 0, payloadlen);
830 #elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
831 				r = pg_GSS_startup(conn, payloadlen);
832 #elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
833 				r = pg_SSPI_startup(conn, 0, payloadlen);
834 #endif
835 				if (r != STATUS_OK)
836 				{
837 					/* Error message already filled in. */
838 					pgunlock_thread();
839 					return STATUS_ERROR;
840 				}
841 				pgunlock_thread();
842 			}
843 			break;
844 
845 		case AUTH_REQ_GSS_CONT:
846 			{
847 				int			r;
848 
849 				pglock_thread();
850 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
851 				if (conn->usesspi)
852 					r = pg_SSPI_continue(conn, payloadlen);
853 				else
854 					r = pg_GSS_continue(conn, payloadlen);
855 #elif defined(ENABLE_GSS) && !defined(ENABLE_SSPI)
856 				r = pg_GSS_continue(conn, payloadlen);
857 #elif !defined(ENABLE_GSS) && defined(ENABLE_SSPI)
858 				r = pg_SSPI_continue(conn, payloadlen);
859 #endif
860 				if (r != STATUS_OK)
861 				{
862 					/* Error message already filled in. */
863 					pgunlock_thread();
864 					return STATUS_ERROR;
865 				}
866 				pgunlock_thread();
867 			}
868 			break;
869 #else							/* defined(ENABLE_GSS) || defined(ENABLE_SSPI) */
870 			/* No GSSAPI *or* SSPI support */
871 		case AUTH_REQ_GSS:
872 		case AUTH_REQ_GSS_CONT:
873 			printfPQExpBuffer(&conn->errorMessage,
874 							  libpq_gettext("GSSAPI authentication not supported\n"));
875 			return STATUS_ERROR;
876 #endif							/* defined(ENABLE_GSS) || defined(ENABLE_SSPI) */
877 
878 #ifdef ENABLE_SSPI
879 		case AUTH_REQ_SSPI:
880 
881 			/*
882 			 * SSPI has its own startup message so libpq can decide which
883 			 * method to use. Indicate to pg_SSPI_startup that we want SSPI
884 			 * negotiation instead of Kerberos.
885 			 */
886 			pglock_thread();
887 			if (pg_SSPI_startup(conn, 1, payloadlen) != STATUS_OK)
888 			{
889 				/* Error message already filled in. */
890 				pgunlock_thread();
891 				return STATUS_ERROR;
892 			}
893 			pgunlock_thread();
894 			break;
895 #else
896 
897 			/*
898 			 * No SSPI support. However, if we have GSSAPI but not SSPI
899 			 * support, AUTH_REQ_SSPI will have been handled in the codepath
900 			 * for AUTH_REQ_GSS above, so don't duplicate the case label in
901 			 * that case.
902 			 */
903 #if !defined(ENABLE_GSS)
904 		case AUTH_REQ_SSPI:
905 			printfPQExpBuffer(&conn->errorMessage,
906 							  libpq_gettext("SSPI authentication not supported\n"));
907 			return STATUS_ERROR;
908 #endif							/* !define(ENABLE_GSS) */
909 #endif							/* ENABLE_SSPI */
910 
911 
912 		case AUTH_REQ_CRYPT:
913 			printfPQExpBuffer(&conn->errorMessage,
914 							  libpq_gettext("Crypt authentication not supported\n"));
915 			return STATUS_ERROR;
916 
917 		case AUTH_REQ_MD5:
918 		case AUTH_REQ_PASSWORD:
919 			{
920 				char	   *password;
921 
922 				conn->password_needed = true;
923 				password = conn->connhost[conn->whichhost].password;
924 				if (password == NULL)
925 					password = conn->pgpass;
926 				if (password == NULL || password[0] == '\0')
927 				{
928 					printfPQExpBuffer(&conn->errorMessage,
929 									  PQnoPasswordSupplied);
930 					return STATUS_ERROR;
931 				}
932 				if (pg_password_sendauth(conn, password, areq) != STATUS_OK)
933 				{
934 					printfPQExpBuffer(&conn->errorMessage,
935 									  "fe_sendauth: error sending password authentication\n");
936 					return STATUS_ERROR;
937 				}
938 				break;
939 			}
940 
941 		case AUTH_REQ_SASL:
942 
943 			/*
944 			 * The request contains the name (as assigned by IANA) of the
945 			 * authentication mechanism.
946 			 */
947 			if (pg_SASL_init(conn, payloadlen) != STATUS_OK)
948 			{
949 				/* pg_SASL_init already set the error message */
950 				return STATUS_ERROR;
951 			}
952 			break;
953 
954 		case AUTH_REQ_SASL_CONT:
955 		case AUTH_REQ_SASL_FIN:
956 			if (conn->sasl_state == NULL)
957 			{
958 				printfPQExpBuffer(&conn->errorMessage,
959 								  "fe_sendauth: invalid authentication request from server: AUTH_REQ_SASL_CONT without AUTH_REQ_SASL\n");
960 				return STATUS_ERROR;
961 			}
962 			if (pg_SASL_continue(conn, payloadlen,
963 								 (areq == AUTH_REQ_SASL_FIN)) != STATUS_OK)
964 			{
965 				/* Use error message, if set already */
966 				if (conn->errorMessage.len == 0)
967 					printfPQExpBuffer(&conn->errorMessage,
968 									  "fe_sendauth: error in SASL authentication\n");
969 				return STATUS_ERROR;
970 			}
971 			break;
972 
973 		case AUTH_REQ_SCM_CREDS:
974 			if (pg_local_sendauth(conn) != STATUS_OK)
975 				return STATUS_ERROR;
976 			break;
977 
978 		default:
979 			printfPQExpBuffer(&conn->errorMessage,
980 							  libpq_gettext("authentication method %u not supported\n"), areq);
981 			return STATUS_ERROR;
982 	}
983 
984 	return STATUS_OK;
985 }
986 
987 
988 /*
989  * pg_fe_getauthname
990  *
991  * Returns a pointer to malloc'd space containing whatever name the user
992  * has authenticated to the system.  If there is an error, return NULL,
993  * and put a suitable error message in *errorMessage if that's not NULL.
994  */
995 char *
pg_fe_getauthname(PQExpBuffer errorMessage)996 pg_fe_getauthname(PQExpBuffer errorMessage)
997 {
998 	char	   *result = NULL;
999 	const char *name = NULL;
1000 
1001 #ifdef WIN32
1002 	/* Microsoft recommends buffer size of UNLEN+1, where UNLEN = 256 */
1003 	char		username[256 + 1];
1004 	DWORD		namesize = sizeof(username);
1005 #else
1006 	uid_t		user_id = geteuid();
1007 	char		pwdbuf[BUFSIZ];
1008 	struct passwd pwdstr;
1009 	struct passwd *pw = NULL;
1010 	int			pwerr;
1011 #endif
1012 
1013 	/*
1014 	 * Some users are using configure --enable-thread-safety-force, so we
1015 	 * might as well do the locking within our library to protect
1016 	 * pqGetpwuid(). In fact, application developers can use getpwuid() in
1017 	 * their application if they use the locking call we provide, or install
1018 	 * their own locking function using PQregisterThreadLock().
1019 	 */
1020 	pglock_thread();
1021 
1022 #ifdef WIN32
1023 	if (GetUserName(username, &namesize))
1024 		name = username;
1025 	else if (errorMessage)
1026 		printfPQExpBuffer(errorMessage,
1027 						  libpq_gettext("user name lookup failure: error code %lu\n"),
1028 						  GetLastError());
1029 #else
1030 	pwerr = pqGetpwuid(user_id, &pwdstr, pwdbuf, sizeof(pwdbuf), &pw);
1031 	if (pw != NULL)
1032 		name = pw->pw_name;
1033 	else if (errorMessage)
1034 	{
1035 		if (pwerr != 0)
1036 			printfPQExpBuffer(errorMessage,
1037 							  libpq_gettext("could not look up local user ID %d: %s\n"),
1038 							  (int) user_id,
1039 							  strerror_r(pwerr, pwdbuf, sizeof(pwdbuf)));
1040 		else
1041 			printfPQExpBuffer(errorMessage,
1042 							  libpq_gettext("local user with ID %d does not exist\n"),
1043 							  (int) user_id);
1044 	}
1045 #endif
1046 
1047 	if (name)
1048 	{
1049 		result = strdup(name);
1050 		if (result == NULL && errorMessage)
1051 			printfPQExpBuffer(errorMessage,
1052 							  libpq_gettext("out of memory\n"));
1053 	}
1054 
1055 	pgunlock_thread();
1056 
1057 	return result;
1058 }
1059 
1060 
1061 /*
1062  * PQencryptPassword -- exported routine to encrypt a password with MD5
1063  *
1064  * This function is equivalent to calling PQencryptPasswordConn with
1065  * "md5" as the encryption method, except that this doesn't require
1066  * a connection object.  This function is deprecated, use
1067  * PQencryptPasswordConn instead.
1068  */
1069 char *
PQencryptPassword(const char * passwd,const char * user)1070 PQencryptPassword(const char *passwd, const char *user)
1071 {
1072 	char	   *crypt_pwd;
1073 
1074 	crypt_pwd = malloc(MD5_PASSWD_LEN + 1);
1075 	if (!crypt_pwd)
1076 		return NULL;
1077 
1078 	if (!pg_md5_encrypt(passwd, user, strlen(user), crypt_pwd))
1079 	{
1080 		free(crypt_pwd);
1081 		return NULL;
1082 	}
1083 
1084 	return crypt_pwd;
1085 }
1086 
1087 /*
1088  * PQencryptPasswordConn -- exported routine to encrypt a password
1089  *
1090  * This is intended to be used by client applications that wish to send
1091  * commands like ALTER USER joe PASSWORD 'pwd'.  The password need not
1092  * be sent in cleartext if it is encrypted on the client side.  This is
1093  * good because it ensures the cleartext password won't end up in logs,
1094  * pg_stat displays, etc.  We export the function so that clients won't
1095  * be dependent on low-level details like whether the encryption is MD5
1096  * or something else.
1097  *
1098  * Arguments are a connection object, the cleartext password, the SQL
1099  * name of the user it is for, and a string indicating the algorithm to
1100  * use for encrypting the password.  If algorithm is NULL, this queries
1101  * the server for the current 'password_encryption' value.  If you wish
1102  * to avoid that, e.g. to avoid blocking, you can execute
1103  * 'show password_encryption' yourself before calling this function, and
1104  * pass it as the algorithm.
1105  *
1106  * Return value is a malloc'd string.  The client may assume the string
1107  * doesn't contain any special characters that would require escaping.
1108  * On error, an error message is stored in the connection object, and
1109  * returns NULL.
1110  */
1111 char *
PQencryptPasswordConn(PGconn * conn,const char * passwd,const char * user,const char * algorithm)1112 PQencryptPasswordConn(PGconn *conn, const char *passwd, const char *user,
1113 					  const char *algorithm)
1114 {
1115 #define MAX_ALGORITHM_NAME_LEN 50
1116 	char		algobuf[MAX_ALGORITHM_NAME_LEN + 1];
1117 	char	   *crypt_pwd = NULL;
1118 
1119 	if (!conn)
1120 		return NULL;
1121 
1122 	/* If no algorithm was given, ask the server. */
1123 	if (algorithm == NULL)
1124 	{
1125 		PGresult   *res;
1126 		char	   *val;
1127 
1128 		res = PQexec(conn, "show password_encryption");
1129 		if (res == NULL)
1130 		{
1131 			/* PQexec() should've set conn->errorMessage already */
1132 			return NULL;
1133 		}
1134 		if (PQresultStatus(res) != PGRES_TUPLES_OK)
1135 		{
1136 			/* PQexec() should've set conn->errorMessage already */
1137 			PQclear(res);
1138 			return NULL;
1139 		}
1140 		if (PQntuples(res) != 1 || PQnfields(res) != 1)
1141 		{
1142 			PQclear(res);
1143 			printfPQExpBuffer(&conn->errorMessage,
1144 							  libpq_gettext("unexpected shape of result set returned for SHOW\n"));
1145 			return NULL;
1146 		}
1147 		val = PQgetvalue(res, 0, 0);
1148 
1149 		if (strlen(val) > MAX_ALGORITHM_NAME_LEN)
1150 		{
1151 			PQclear(res);
1152 			printfPQExpBuffer(&conn->errorMessage,
1153 							  libpq_gettext("password_encryption value too long\n"));
1154 			return NULL;
1155 		}
1156 		strcpy(algobuf, val);
1157 		PQclear(res);
1158 
1159 		algorithm = algobuf;
1160 	}
1161 
1162 	/*
1163 	 * Also accept "on" and "off" as aliases for "md5", because
1164 	 * password_encryption was a boolean before PostgreSQL 10.  We refuse to
1165 	 * send the password in plaintext even if it was "off".
1166 	 */
1167 	if (strcmp(algorithm, "on") == 0 ||
1168 		strcmp(algorithm, "off") == 0)
1169 		algorithm = "md5";
1170 
1171 	/*
1172 	 * Ok, now we know what algorithm to use
1173 	 */
1174 	if (strcmp(algorithm, "scram-sha-256") == 0)
1175 	{
1176 		crypt_pwd = pg_fe_scram_build_verifier(passwd);
1177 	}
1178 	else if (strcmp(algorithm, "md5") == 0)
1179 	{
1180 		crypt_pwd = malloc(MD5_PASSWD_LEN + 1);
1181 		if (crypt_pwd)
1182 		{
1183 			if (!pg_md5_encrypt(passwd, user, strlen(user), crypt_pwd))
1184 			{
1185 				free(crypt_pwd);
1186 				crypt_pwd = NULL;
1187 			}
1188 		}
1189 	}
1190 	else
1191 	{
1192 		printfPQExpBuffer(&conn->errorMessage,
1193 						  libpq_gettext("unrecognized password encryption algorithm \"%s\"\n"),
1194 						  algorithm);
1195 		return NULL;
1196 	}
1197 
1198 	if (!crypt_pwd)
1199 		printfPQExpBuffer(&conn->errorMessage,
1200 						  libpq_gettext("out of memory\n"));
1201 
1202 	return crypt_pwd;
1203 }
1204