1 /* -*-pgsql-c-*- */
2 /*
3  * pgpool: a language independent connection pool server for PostgreSQL
4  * written by Tatsuo Ishii
5  *
6  * Copyright (c) 2003-2020	PgPool Global Development Group
7  *
8  * Permission to use, copy, modify, and distribute this software and
9  * its documentation for any purpose and without fee is hereby
10  * granted, provided that the above copyright notice appear in all
11  * copies and that both that copyright notice and this permission
12  * notice appear in supporting documentation, and that the name of the
13  * author not be used in advertising or publicity pertaining to
14  * distribution of the software without specific, written prior
15  * permission. The author makes no representations about the
16  * suitability of this software for any purpose.  It is provided "as
17  * is" without express or implied warranty.
18  *
19  * pool_auth.c: authentication stuff
20  *
21 */
22 
23 #include "pool.h"
24 #include "context/pool_session_context.h"
25 #include "utils/pool_stream.h"
26 #include "pool_config.h"
27 #include "auth/pool_hba.h"
28 #include "auth/pool_passwd.h"
29 #include "auth/scram.h"
30 #include "utils/elog.h"
31 #include "utils/palloc.h"
32 #include "utils/memutils.h"
33 #include "auth/md5.h"
34 
35 #ifdef HAVE_CRYPT_H
36 #include <crypt.h>
37 #endif
38 
39 #ifdef HAVE_SYS_TYPES_H
40 #include <sys/types.h>
41 #endif
42 #ifdef HAVE_NETINET_IN_H
43 #include <netinet/in.h>
44 #endif
45 #ifdef HAVE_PARAM_H
46 #include <param.h>
47 #endif
48 #ifdef USE_SSL
49 #include <openssl/rand.h>
50 #endif
51 
52 #include <errno.h>
53 #include <string.h>
54 #include <stdlib.h>
55 
56 #define AUTHFAIL_ERRORCODE "28000"
57 #define MAX_SASL_PAYLOAD_LEN 1024
58 
59 
60 static POOL_STATUS pool_send_backend_key_data(POOL_CONNECTION * frontend, int pid, int key, int protoMajor);
61 static int	do_clear_text_password(POOL_CONNECTION * backend, POOL_CONNECTION * frontend, int reauth, int protoMajor);
62 static void pool_send_auth_fail(POOL_CONNECTION * frontend, POOL_CONNECTION_POOL * cp);
63 static int	do_crypt(POOL_CONNECTION * backend, POOL_CONNECTION * frontend, int reauth, int protoMajor);
64 static int do_md5(POOL_CONNECTION * backend, POOL_CONNECTION * frontend, int reauth, int protoMajor,
65 	   char *storedPassword, PasswordType passwordType);
66 static int	do_md5_single_backend(POOL_CONNECTION * backend, POOL_CONNECTION * frontend, int reauth, int protoMajor);
67 static void send_md5auth_request(POOL_CONNECTION * frontend, int protoMajor, char *salt);
68 static int	read_password_packet(POOL_CONNECTION * frontend, int protoMajor, char *password, int *pwdSize);
69 static int	send_password_packet(POOL_CONNECTION * backend, int protoMajor, char *password);
70 static int	send_auth_ok(POOL_CONNECTION * frontend, int protoMajor);
71 static void sendAuthRequest(POOL_CONNECTION * frontend, int protoMajor, int32 auth_req_type, char *extradata, int extralen);
72 static long PostmasterRandom(void);
73 
74 static int	pg_SASL_continue(POOL_CONNECTION * backend, char *payload, int payloadlen, void *sasl_state, bool final);
75 static void *pg_SASL_init(POOL_CONNECTION * backend, char *payload, int payloadlen, char *username, char *storedPassword);
76 static bool do_SCRAM(POOL_CONNECTION * frontend, POOL_CONNECTION * backend, int protoMajor, int message_length,
77 		 char *username, char *storedPassword, PasswordType passwordType);
78 static void authenticate_frontend_md5(POOL_CONNECTION * backend, POOL_CONNECTION * frontend, int reauth, int protoMajor);
79 static void authenticate_frontend_cert(POOL_CONNECTION * frontend);
80 static void authenticate_frontend_SCRAM(POOL_CONNECTION * backend, POOL_CONNECTION * frontend, int reauth);
81 static void authenticate_frontend_clear_text(POOL_CONNECTION * frontend);
82 static bool get_auth_password(POOL_CONNECTION * backend, POOL_CONNECTION * frontend, int reauth,
83 				  char **password, PasswordType *passwordType);
84 
85 /*
86  * Do authentication. Assuming the only caller is
87  * make_persistent_db_connection().
88  */
89 void
connection_do_auth(POOL_CONNECTION_POOL_SLOT * cp,char * password)90 connection_do_auth(POOL_CONNECTION_POOL_SLOT * cp, char *password)
91 {
92 	char		kind;
93 	int			length;
94 	int			auth_kind;
95 	char		state;
96 	char	   *p;
97 	int			pid,
98 				key;
99 	bool		keydata_done;
100 
101 	/*
102 	 * read kind expecting 'R' packet (authentication response)
103 	 */
104 	pool_read_with_error(cp->con, &kind, sizeof(kind),
105 						 "authentication message response type");
106 
107 	if (kind != 'R')
108 	{
109 		char	   *msg;
110 		int			sts = 0;
111 
112 		if (kind == 'E' || kind == 'N')
113 		{
114 			sts = pool_extract_error_message(false, cp->con, cp->sp->major, false, &msg);
115 		}
116 
117 		if (sts == 1)			/* succeeded in extracting error/notice
118 								 * message */
119 		{
120 			ereport(ERROR,
121 					(errmsg("failed to authenticate"),
122 					 errdetail("%s", msg)));
123 			pfree(msg);
124 		}
125 		ereport(ERROR,
126 				(errmsg("failed to authenticate"),
127 				 errdetail("invalid authentication message response type, Expecting 'R' and received '%c'", kind)));
128 	}
129 
130 	/* read message length */
131 	pool_read_with_error(cp->con, &length, sizeof(length),
132 						 "authentication message response length");
133 
134 	length = ntohl(length);
135 
136 	/* read auth kind */
137 	pool_read_with_error(cp->con, &auth_kind, sizeof(auth_kind),
138 						 "authentication method from response");
139 	auth_kind = ntohl(auth_kind);
140 	ereport(DEBUG1,
141 			(errmsg("authenticate kind = %d", auth_kind)));
142 
143 	if (auth_kind == AUTH_REQ_OK)	/* trust authentication? */
144 	{
145 		cp->con->auth_kind = AUTH_REQ_OK;
146 	}
147 	else if (auth_kind == AUTH_REQ_PASSWORD)	/* clear text password? */
148 	{
149 		kind = send_password_packet(cp->con, PROTO_MAJOR_V3, password);
150 		if (kind != AUTH_REQ_OK)
151 			ereport(ERROR,
152 					(errmsg("password authentication failed for user:%s", cp->sp->user),
153 					 errdetail("backend replied with invalid kind")));
154 
155 		cp->con->auth_kind = AUTH_REQ_OK;
156 	}
157 	else if (auth_kind == AUTH_REQ_CRYPT)	/* crypt password? */
158 	{
159 		char		salt[3];
160 		char	   *crypt_password;
161 
162 		pool_read_with_error(cp->con, &salt, 2, "crypt salt");
163 		salt[2] = '\0';
164 
165 		crypt_password = crypt(password, salt);
166 		if (crypt_password == NULL)
167 			ereport(ERROR,
168 					(errmsg("crypt authentication failed for user:%s", cp->sp->user),
169 					 errdetail("failed to encrypt the password")));
170 
171 		/* Send password packet to backend and receive auth response */
172 		kind = send_password_packet(cp->con, PROTO_MAJOR_V3, crypt_password);
173 		if (kind != AUTH_REQ_OK)
174 			ereport(ERROR,
175 					(errmsg("crypt authentication failed for user:%s", cp->sp->user),
176 					 errdetail("backend replied with invalid kind")));
177 
178 		cp->con->auth_kind = AUTH_REQ_OK;
179 	}
180 	else if (auth_kind == AUTH_REQ_MD5) /* md5 password? */
181 	{
182 		char		salt[4];
183 		char	   *buf,
184 				   *buf1;
185 
186 		pool_read_with_error(cp->con, &salt, sizeof(salt), "authentication md5 salt");
187 
188 		buf = palloc0(2 * (MD5_PASSWD_LEN + 4));	/* hash + "md5" + '\0' */
189 
190 		/* build md5 password */
191 		buf1 = buf + MD5_PASSWD_LEN + 4;
192 		pool_md5_encrypt(password, cp->sp->user, strlen(cp->sp->user), buf1);
193 		pool_md5_encrypt(buf1, salt, 4, buf + 3);
194 		memcpy(buf, "md5", 3);
195 
196 		/* Send password packet to backend and receive auth response */
197 		kind = send_password_packet(cp->con, PROTO_MAJOR_V3, buf);
198 		pfree(buf);
199 		if (kind != AUTH_REQ_OK)
200 			ereport(ERROR,
201 					(errmsg("md5 authentication failed for user:%s", cp->sp->user),
202 					 errdetail("backend replied with invalid kind")));
203 
204 		cp->con->auth_kind = AUTH_REQ_OK;
205 	}
206 	else if (auth_kind == AUTH_REQ_SASL)
207 	{
208 		if (do_SCRAM(NULL, cp->con, PROTO_MAJOR_V3, length, cp->sp->user, password, PASSWORD_TYPE_PLAINTEXT) == false)
209 		{
210 			ereport(ERROR,
211 					(errmsg("failed to authenticate with backend"),
212 					 errdetail("SCRAM authentication failed for user:%s", cp->sp->user)));
213 		}
214 		ereport(DEBUG1,
215 				(errmsg("SCRAM authentication successful for user:%s", cp->sp->user)));
216 		cp->con->auth_kind = AUTH_REQ_OK;
217 	}
218 	else
219 	{
220 		ereport(ERROR,
221 				(errmsg("failed to authenticate"),
222 				 errdetail("auth kind %d is not yet supported", auth_kind)));
223 	}
224 
225 	/*
226 	 * Read backend key data and wait until Ready for query arriving or error
227 	 * happens.
228 	 */
229 
230 	keydata_done = false;
231 
232 	for (;;)
233 	{
234 		pool_read_with_error(cp->con, &kind, sizeof(kind),
235 							 "authentication message kind");
236 
237 		switch (kind)
238 		{
239 			case 'K':			/* backend key data */
240 				keydata_done = true;
241 				ereport(DEBUG1,
242 						(errmsg("authenticate backend: key data received")));
243 
244 				/* read message length */
245 				pool_read_with_error(cp->con, &length, sizeof(length), "message length for authentication kind 'K'");
246 				if (ntohl(length) != 12)
247 				{
248 					ereport(ERROR,
249 							(errmsg("failed to authenticate"),
250 							 errdetail("invalid backend key data length. received %d bytes when expecting 12 bytes"
251 									   ,ntohl(length))));
252 				}
253 
254 				/* read pid */
255 				pool_read_with_error(cp->con, &pid, sizeof(pid), "pid for authentication kind 'K'");
256 				cp->pid = pid;
257 
258 				/* read key */
259 				pool_read_with_error(cp->con, &key, sizeof(key),
260 									 "key for authentication kind 'K'");
261 				cp->key = key;
262 				break;
263 
264 			case 'Z':			/* Ready for query */
265 				/* read message length */
266 				pool_read_with_error(cp->con, &length, sizeof(length),
267 									 "message length for authentication kind 'Z'");
268 				length = ntohl(length);
269 
270 				/* read transaction state */
271 				pool_read_with_error(cp->con, &state, sizeof(state),
272 									 "transaction state  for authentication kind 'Z'");
273 
274 				ereport(DEBUG1,
275 						(errmsg("authenticate backend: transaction state: %c", state)));
276 
277 				cp->con->tstate = state;
278 
279 				if (!keydata_done)
280 				{
281 					ereport(ERROR,
282 							(errmsg("failed to authenticate"),
283 							 errdetail("ready for query arrived before receiving keydata")));
284 				}
285 				return;
286 				break;
287 
288 			case 'S':			/* parameter status */
289 			case 'N':			/* notice response */
290 			case 'E':			/* error response */
291 				/* Just throw away data */
292 				pool_read_with_error(cp->con, &length, sizeof(length),
293 									 "backend message length");
294 
295 				length = ntohl(length);
296 				length -= 4;
297 
298 				p = pool_read2(cp->con, length);
299 				if (p == NULL)
300 					ereport(ERROR,
301 							(errmsg("failed to authenticate"),
302 							 errdetail("unable to read data from socket")));
303 
304 				break;
305 
306 			default:
307 				ereport(ERROR,
308 						(errmsg("failed to authenticate"),
309 						 errdetail("unknown authentication message response received '%c'", kind)));
310 				break;
311 		}
312 	}
313 	ereport(ERROR,
314 			(errmsg("failed to authenticate")));
315 }
316 
317 /*
318  * After sending the start up packet to the backend, do the
319  * authentication against backend. if success return 0 otherwise non
320  * 0.
321 */
322 int
pool_do_auth(POOL_CONNECTION * frontend,POOL_CONNECTION_POOL * cp)323 pool_do_auth(POOL_CONNECTION * frontend, POOL_CONNECTION_POOL * cp)
324 {
325 	signed char kind;
326 	int			pid;
327 	int			key;
328 	int			protoMajor;
329 	int			length;
330 	int			authkind;
331 	int			i;
332 	int			message_length = 0;
333 	StartupPacket *sp;
334 
335 
336 	protoMajor = MASTER_CONNECTION(cp)->sp->major;
337 
338 	kind = pool_read_kind(cp);
339 	if (kind < 0)
340 		ereport(ERROR,
341 				(errmsg("invalid authentication packet from backend"),
342 				 errdetail("failed to get response kind")));
343 
344 	/* error response? */
345 	if (kind == 'E')
346 	{
347 		/*
348 		 * we assume error response at this stage is likely version protocol
349 		 * mismatch (v3 frontend vs. v2 backend). So we throw a V2 protocol
350 		 * error response in the hope that v3 frontend will negotiate again
351 		 * using v2 protocol.
352 		 */
353 
354 		ErrorResponse(frontend, cp);
355 
356 		ereport(ERROR,
357 				(errmsg("backend authentication failed"),
358 				 errdetail("backend response with kind \'E\' when expecting \'R\'"),
359 				 errhint("This issue can be caused by version mismatch (current version %d)", protoMajor)));
360 	}
361 	else if (kind != 'R')
362 		ereport(ERROR,
363 				(errmsg("backend authentication failed"),
364 				 errdetail("backend response with kind \'%c\' when expecting \'R\'", kind)));
365 
366 	/*
367 	 * message length (v3 only)
368 	 */
369 	if (protoMajor == PROTO_MAJOR_V3)
370 	{
371 		message_length = pool_read_message_length(cp);
372 		if (message_length <= 0)
373 			ereport(ERROR,
374 					(errmsg("invalid authentication packet from backend"),
375 					 errdetail("failed to get the authentication packet length"),
376 					 errhint("This is likely caused by the inconsistency of auth method among DB nodes. \
377 								Please check the previous error messages (hint: length field) \
378 								from pool_read_message_length and recheck the pg_hba.conf settings.")));
379 	}
380 
381 	/*-------------------------------------------------------------------------
382 	 * read authentication request kind.
383 	 *
384 	 * 0: authentication ok
385 	 * 1: kerberos v4
386 	 * 2: kerberos v5
387 	 * 3: clear text password
388 	 * 4: crypt password
389 	 * 5: md5 password
390 	 * 6: scm credential
391 	 *
392 	 * in replication mode, we only support  kind = 0, 3. this is because "salt"
393 	 * cannot be replicated.
394 	 * in non replication mode, we support kind = 0, 3, 4, 5
395 	 *-------------------------------------------------------------------------
396 	 */
397 
398 	authkind = pool_read_int(cp);
399 	if (authkind < 0)
400 		ereport(ERROR,
401 				(errmsg("invalid authentication packet from backend"),
402 				 errdetail("failed to get auth kind")));
403 
404 	authkind = ntohl(authkind);
405 
406 	ereport(DEBUG1,
407 			(errmsg("authentication backend"),
408 			 errdetail("auth kind:%d", authkind)));
409 	/* trust? */
410 	if (authkind == AUTH_REQ_OK)
411 	{
412 		int			msglen;
413 
414 		pool_write(frontend, "R", 1);
415 
416 		if (protoMajor == PROTO_MAJOR_V3)
417 		{
418 			msglen = htonl(8);
419 			pool_write(frontend, &msglen, sizeof(msglen));
420 		}
421 
422 		msglen = htonl(0);
423 		pool_write_and_flush(frontend, &msglen, sizeof(msglen));
424 		MASTER(cp)->auth_kind = AUTH_REQ_OK;
425 	}
426 
427 	/* clear text password authentication? */
428 	else if (authkind == AUTH_REQ_PASSWORD)
429 	{
430 		for (i = 0; i < NUM_BACKENDS; i++)
431 		{
432 			if (!VALID_BACKEND(i))
433 				continue;
434 
435 			ereport(DEBUG1,
436 					(errmsg("authentication backend"),
437 					 errdetail("trying clear text password authentication")));
438 
439 			authkind = do_clear_text_password(CONNECTION(cp, i), frontend, 0, protoMajor);
440 
441 			if (authkind < 0)
442 			{
443 				ereport(DEBUG1,
444 						(errmsg("authentication backend"),
445 						 errdetail("clear text password failed in slot %d", i)));
446 				pool_send_auth_fail(frontend, cp);
447 				ereport(ERROR,
448 						(errmsg("failed to authenticate with backend"),
449 						 errdetail("do_clear_text_password failed in slot %d", i)));
450 			}
451 		}
452 	}
453 
454 	/* crypt authentication? */
455 	else if (authkind == AUTH_REQ_CRYPT)
456 	{
457 		for (i = 0; i < NUM_BACKENDS; i++)
458 		{
459 			if (!VALID_BACKEND(i))
460 				continue;
461 
462 			ereport(DEBUG1,
463 					(errmsg("authentication backend"),
464 					 errdetail("trying crypt authentication")));
465 
466 			authkind = do_crypt(CONNECTION(cp, i), frontend, 0, protoMajor);
467 
468 			if (authkind < 0)
469 			{
470 				pool_send_auth_fail(frontend, cp);
471 				ereport(ERROR,
472 						(errmsg("failed to authenticate with backend"),
473 						 errdetail("do_crypt_text_password failed in slot %d", i)));
474 			}
475 		}
476 	}
477 
478 	/* md5 authentication? */
479 	else if (authkind == AUTH_REQ_MD5)
480 	{
481 		char	   *password = NULL;
482 		PasswordType passwordType = PASSWORD_TYPE_UNKNOWN;
483 
484 		/*
485 		 * check if we can use md5 authentication.
486 		 */
487 		if (!RAW_MODE && NUM_BACKENDS > 1)
488 		{
489 			if (get_auth_password(MASTER(cp), frontend, 0,
490 								  &password, &passwordType) == false)
491 			{
492 				/*
493 				 * We do not have any passeord, we can still get the password
494 				 * from client using plain text authentication if it is
495 				 * allowed by user
496 				 */
497 				if (frontend->pool_hba == NULL && pool_config->allow_clear_text_frontend_auth)
498 				{
499 					ereport(LOG,
500 							(errmsg("using clear text authentication with frontend"),
501 							 errdetail("backend will still use md5 auth"),
502 							 errhint("you can disable this behavior by setting allow_clear_text_frontend_auth to off")));
503 					authenticate_frontend_clear_text(frontend);
504 					/* now check again if we have a password now */
505 					if (get_auth_password(MASTER(cp), frontend, 0,
506 										  &password, &passwordType) == false)
507 					{
508 						ereport(ERROR,
509 								(errmsg("failed to authenticate with backend using md5"),
510 								 errdetail("unable to get the password")));
511 					}
512 				}
513 			}
514 			/* we have a password to use, validate the password type */
515 			if (passwordType != PASSWORD_TYPE_PLAINTEXT && passwordType != PASSWORD_TYPE_MD5
516 				&& passwordType != PASSWORD_TYPE_AES)
517 			{
518 				ereport(ERROR,
519 						(errmsg("failed to authenticate with backend using md5"),
520 						 errdetail("valid password not found")));
521 			}
522 		}
523 
524 		for (i = 0; i < NUM_BACKENDS; i++)
525 		{
526 			if (!VALID_BACKEND(i))
527 				continue;
528 
529 			ereport(DEBUG1,
530 					(errmsg("authentication backend: %d", i),
531 					 errdetail("trying md5 authentication")));
532 
533 			authkind = do_md5(CONNECTION(cp, i), frontend, 0, protoMajor, password, passwordType);
534 
535 			if (authkind < 0)
536 			{
537 				pool_send_auth_fail(frontend, cp);
538 				ereport(ERROR,
539 						(errmsg("failed to authenticate with backend"),
540 						 errdetail("MD5 authentication failed in slot [%d].", i)));
541 			}
542 		}
543 	}
544 
545 	/* SCRAM authentication? */
546 	else if (authkind == AUTH_REQ_SASL)
547 	{
548 		char	   *password;
549 		PasswordType passwordType = PASSWORD_TYPE_UNKNOWN;
550 
551 		if (get_auth_password(MASTER(cp), frontend, 0,
552 							  &password, &passwordType) == false)
553 		{
554 			/*
555 			 * We do not have any password, we can still get the password from
556 			 * client using plain text authentication if it is allowed by user
557 			 */
558 			if (frontend->pool_hba == NULL && pool_config->allow_clear_text_frontend_auth)
559 			{
560 				ereport(LOG,
561 						(errmsg("using clear text authentication with frontend"),
562 						 errdetail("backend will still use SCRAM auth"),
563 						 errhint("you can disable this behavior by setting allow_clear_text_frontend_auth to off")));
564 				authenticate_frontend_clear_text(frontend);
565 				/* now check again if we have a password now */
566 				if (get_auth_password(MASTER(cp), frontend, 0,
567 									  &password, &passwordType) == false)
568 				{
569 					ereport(ERROR,
570 							(errmsg("failed to authenticate with backend using SCRAM"),
571 							 errdetail("unable to get the password")));
572 				}
573 			}
574 		}
575 
576 		/*
577 		 * if we have encrypted password, Decrypt it before going any further
578 		 */
579 		if (passwordType == PASSWORD_TYPE_AES)
580 		{
581 			password = get_decrypted_password(password);
582 			if (password == NULL)
583 				ereport(ERROR,
584 						(errmsg("SCRAM authentication failed"),
585 						 errdetail("unable to decrypt password from pool_passwd"),
586 						 errhint("verify the valid pool_key exists")));
587 			/* we have converted the password to plain text */
588 			passwordType = PASSWORD_TYPE_PLAINTEXT;
589 		}
590 
591 		/* we have a password to use, validate the password type */
592 		if (passwordType != PASSWORD_TYPE_PLAINTEXT)
593 		{
594 			ereport(ERROR,
595 					(errmsg("failed to authenticate with backend using SCRAM"),
596 					 errdetail("valid password not found")));
597 		}
598 
599 		for (i = 0; i < NUM_BACKENDS; i++)
600 		{
601 			if (!VALID_BACKEND(i))
602 				continue;
603 
604 			ereport(DEBUG1,
605 					(errmsg("authentication backend %d", i),
606 					 errdetail("trying SCRAM authentication")));
607 
608 			if (do_SCRAM(frontend, CONNECTION(cp, i), protoMajor, message_length, frontend->username, password, passwordType) == false)
609 			{
610 				pool_send_auth_fail(frontend, cp);
611 				ereport(ERROR,
612 						(errmsg("failed to authenticate with backend"),
613 						 errdetail("SCRAM authentication failed in slot [%d].", i)));
614 			}
615 			ereport(DEBUG1,
616 					(errmsg("SCRAM authentication successful for backend %d", i)));
617 
618 		}
619 
620 		send_auth_ok(frontend, protoMajor);
621 		authkind = 0;
622 	}
623 
624 	else
625 	{
626 		ereport(ERROR,
627 				(errmsg("failed to authenticate with backend"),
628 				 errdetail("unsupported auth kind received from backend: authkind:%d", authkind)));
629 	}
630 
631 	if (authkind != 0)
632 		ereport(ERROR,
633 				(errmsg("failed to authenticate with backend"),
634 				 errdetail("invalid auth kind received from backend: authkind:%d", authkind)));
635 
636 	/*
637 	 * authentication ok. now read pid and secret key from the backend
638 	 */
639 	for (;;)
640 	{
641 		char	   *message = NULL;
642 
643 		kind = pool_read_kind(cp);
644 
645 		if (kind < 0)
646 		{
647 			ereport(ERROR,
648 					(errmsg("authentication failed from backend"),
649 					 errdetail("failed to read kind before BackendKeyData")));
650 		}
651 		else if (kind == 'K')
652 			break;
653 
654 		if (protoMajor == PROTO_MAJOR_V3)
655 		{
656 			switch (kind)
657 			{
658 				case 'S':
659 					/* process parameter status */
660 					if (ParameterStatus(frontend, cp) != POOL_CONTINUE)
661 						return -1;
662 					pool_flush(frontend);
663 					break;
664 
665 				case 'N':
666 					if (pool_extract_error_message(false, MASTER(cp), protoMajor, true, &message) == 1)
667 					{
668 						ereport(NOTICE,
669 								(errmsg("notice from backend"),
670 								 errdetail("BACKEND NOTICE: \"%s\"", message)));
671 						pfree(message);
672 					}
673 					/* process notice message */
674 					if (SimpleForwardToFrontend(kind, frontend, cp))
675 						ereport(ERROR,
676 								(errmsg("authentication failed"),
677 								 errdetail("failed to forward message to frontend")));
678 					pool_flush(frontend);
679 					break;
680 
681 					/* process error message */
682 				case 'E':
683 
684 					if (pool_extract_error_message(false, MASTER(cp), protoMajor, true, &message) == 1)
685 					{
686 						ereport(LOG,
687 								(errmsg("backend throws an error message"),
688 								 errdetail("%s", message)));
689 					}
690 
691 					SimpleForwardToFrontend(kind, frontend, cp);
692 
693 					pool_flush(frontend);
694 
695 					ereport(ERROR,
696 							(errmsg("authentication failed, backend node replied with an error"),
697 							 errdetail("SERVER ERROR:\"%s\"", message ? message : "could not extract backend message")));
698 
699 					if (message)
700 						pfree(message);
701 					break;
702 
703 				default:
704 					ereport(ERROR,
705 							(errmsg("authentication failed"),
706 							 errdetail("unknown response \"%c\" before processing BackendKeyData", kind)));
707 					break;
708 			}
709 		}
710 		else
711 		{
712 			/* V2 case */
713 			switch (kind)
714 			{
715 				case 'N':
716 					/* process notice message */
717 					NoticeResponse(frontend, cp);
718 					break;
719 
720 					/* process error message */
721 				case 'E':
722 					ErrorResponse(frontend, cp);
723 					/* fallthrough */
724 				default:
725 					ereport(ERROR,
726 							(errmsg("authentication failed"),
727 							 errdetail("invalid response \"%c\" before processing BackendKeyData", kind)));
728 					break;
729 			}
730 		}
731 	}
732 
733 	/*
734 	 * message length (V3 only)
735 	 */
736 	if (protoMajor == PROTO_MAJOR_V3)
737 	{
738 		if ((length = pool_read_message_length(cp)) != 12)
739 		{
740 			ereport(ERROR,
741 					(errmsg("authentication failed"),
742 					 errdetail("invalid messages length(%d) for BackendKeyData", length)));
743 		}
744 	}
745 
746 	/*
747 	 * OK, read pid and secret key
748 	 */
749 	sp = MASTER_CONNECTION(cp)->sp;
750 	pid = -1;
751 
752 	for (i = 0; i < NUM_BACKENDS; i++)
753 	{
754 		if (VALID_BACKEND(i))
755 		{
756 			/* read pid */
757 			if (pool_read(CONNECTION(cp, i), &pid, sizeof(pid)) < 0)
758 			{
759 				ereport(ERROR,
760 						(errmsg("authentication failed"),
761 						 errdetail("failed to read pid in slot %d", i)));
762 			}
763 			ereport(DEBUG1,
764 					(errmsg("authentication backend"),
765 					 errdetail("cp->info[i]:%p pid:%u", &cp->info[i], ntohl(pid))));
766 
767 			CONNECTION_SLOT(cp, i)->pid = cp->info[i].pid = pid;
768 
769 			/* read key */
770 			if (pool_read(CONNECTION(cp, i), &key, sizeof(key)) < 0)
771 			{
772 				ereport(ERROR,
773 						(errmsg("authentication failed"),
774 						 errdetail("failed to read key in slot %d", i)));
775 			}
776 			CONNECTION_SLOT(cp, i)->key = cp->info[i].key = key;
777 
778 			cp->info[i].major = sp->major;
779 			cp->info[i].minor = sp->minor;
780 			strlcpy(cp->info[i].database, sp->database, sizeof(cp->info[i].database));
781 			strlcpy(cp->info[i].user, sp->user, sizeof(cp->info[i].user));
782 			cp->info[i].counter = 1;
783 			CONNECTION(cp, i)->con_info = &cp->info[i];
784 			cp->info[i].swallow_termination = 0;
785 		}
786 	}
787 
788 	if (pid == -1)
789 	{
790 		ereport(ERROR,
791 				(errmsg("authentication failed"),
792 				 errdetail("pool_do_auth: all backends are down")));
793 	}
794 	if (pool_send_backend_key_data(frontend, pid, key, protoMajor))
795 		ereport(ERROR,
796 				(errmsg("authentication failed"),
797 				 errdetail("failed to send backend data to frontend")));
798 	return 0;
799 }
800 
801 /*
802 * do re-authentication for reused connection. if success return 0 otherwise throws ereport.
803 */
804 int
pool_do_reauth(POOL_CONNECTION * frontend,POOL_CONNECTION_POOL * cp)805 pool_do_reauth(POOL_CONNECTION * frontend, POOL_CONNECTION_POOL * cp)
806 {
807 	int			protoMajor;
808 	int			msglen;
809 
810 	protoMajor = MAJOR(cp);
811 
812 	/*
813 	 * if hba is enabled we would already have passed authentication
814 	 */
815 	if (!frontend->frontend_authenticated)
816 	{
817 		switch (MASTER(cp)->auth_kind)
818 		{
819 			case AUTH_REQ_OK:
820 				/* trust */
821 				break;
822 
823 			case AUTH_REQ_PASSWORD:
824 				/* clear text password */
825 				do_clear_text_password(MASTER(cp), frontend, 1, protoMajor);
826 				break;
827 
828 			case AUTH_REQ_CRYPT:
829 				/* crypt password */
830 				do_crypt(MASTER(cp), frontend, 1, protoMajor);
831 				break;
832 
833 			case AUTH_REQ_MD5:
834 				/* md5 password */
835 				authenticate_frontend_md5(MASTER(cp), frontend, 1, protoMajor);
836 				break;
837 			case AUTH_REQ_SASL:
838 				/* SCRAM */
839 				authenticate_frontend_SCRAM(MASTER(cp), frontend, 1);
840 				break;
841 			default:
842 				ereport(ERROR,
843 						(errmsg("authentication failed"),
844 						 errdetail("unknown authentication request code %d", MASTER(cp)->auth_kind)));
845 		}
846 	}
847 
848 	pool_write(frontend, "R", 1);
849 
850 	if (protoMajor == PROTO_MAJOR_V3)
851 	{
852 		msglen = htonl(8);
853 		pool_write(frontend, &msglen, sizeof(msglen));
854 	}
855 
856 	msglen = htonl(0);
857 	pool_write_and_flush(frontend, &msglen, sizeof(msglen));
858 	pool_send_backend_key_data(frontend, MASTER_CONNECTION(cp)->pid, MASTER_CONNECTION(cp)->key, protoMajor);
859 	return 0;
860 }
861 
862 /*
863 * send authentication failure message text to frontend
864 */
865 static void
pool_send_auth_fail(POOL_CONNECTION * frontend,POOL_CONNECTION_POOL * cp)866 pool_send_auth_fail(POOL_CONNECTION * frontend, POOL_CONNECTION_POOL * cp)
867 {
868 	int			messagelen;
869 	char	   *errmessage;
870 	int			protoMajor;
871 
872 	bool		send_error_to_frontend = true;
873 
874 	protoMajor = MAJOR(cp);
875 
876 	messagelen = strlen(MASTER_CONNECTION(cp)->sp->user) + 100;
877 	errmessage = (char *) palloc(messagelen + 1);
878 
879 	snprintf(errmessage, messagelen, "password authentication failed for user \"%s\"",
880 			 MASTER_CONNECTION(cp)->sp->user);
881 	if (send_error_to_frontend)
882 		pool_send_fatal_message(frontend, protoMajor, "XX000", errmessage,
883 								"", "", __FILE__, __LINE__);
884 	pfree(errmessage);
885 }
886 
887 /*
888  * Send backend key data to frontend. if success return 0 otherwise non 0.
889  */
pool_send_backend_key_data(POOL_CONNECTION * frontend,int pid,int key,int protoMajor)890 static POOL_STATUS pool_send_backend_key_data(POOL_CONNECTION * frontend, int pid, int key, int protoMajor)
891 {
892 	char		kind;
893 	int			len;
894 
895 	/* Send backend key data */
896 	kind = 'K';
897 	pool_write(frontend, &kind, 1);
898 	if (protoMajor == PROTO_MAJOR_V3)
899 	{
900 		len = htonl(12);
901 		pool_write(frontend, &len, sizeof(len));
902 	}
903 	ereport(DEBUG1,
904 			(errmsg("sending backend key data"),
905 			 errdetail("send pid %d to frontend", ntohl(pid))));
906 
907 	pool_write(frontend, &pid, sizeof(pid));
908 	pool_write_and_flush(frontend, &key, sizeof(key));
909 
910 	return 0;
911 }
912 
913 static void
authenticate_frontend_clear_text(POOL_CONNECTION * frontend)914 authenticate_frontend_clear_text(POOL_CONNECTION * frontend)
915 {
916 	static int	size;
917 	char		password[MAX_PASSWORD_SIZE];
918 	char		userPassword[MAX_PASSWORD_SIZE];
919 	char	   *storedPassword = NULL;
920 	char	   *userPwd = NULL;
921 
922 	sendAuthRequest(frontend, frontend->protoVersion, AUTH_REQ_PASSWORD, NULL, 0);
923 
924 	/* Read password packet */
925 	read_password_packet(frontend, frontend->protoVersion, password, &size);
926 
927 	/* save the password in frontend */
928 	frontend->auth_kind = AUTH_REQ_PASSWORD;
929 	frontend->pwd_size = size;
930 	memcpy(frontend->password, password, frontend->pwd_size);
931 	frontend->password[size] = 0;	/* Null terminate the password string */
932 	frontend->passwordType = PASSWORD_TYPE_PLAINTEXT;
933 
934 	if (!frontend->passwordMapping)
935 	{
936 		/*
937 		 * if the password is not present in pool_passwd just bail out from
938 		 * here
939 		 */
940 		return;
941 	}
942 
943 	storedPassword = frontend->passwordMapping->pgpoolUser.password;
944 	userPwd = password;
945 
946 	/*
947 	 * If we have md5 password stored in pool_passwd, convert the user
948 	 * supplied password to md5 for comparison
949 	 */
950 	if (frontend->passwordMapping->pgpoolUser.passwordType == PASSWORD_TYPE_MD5)
951 	{
952 		pg_md5_encrypt(password,
953 					   frontend->username,
954 					   strlen(frontend->username), userPassword);
955 		userPwd = userPassword;
956 		size = strlen(userPwd);
957 	}
958 	else if (frontend->passwordMapping->pgpoolUser.passwordType == PASSWORD_TYPE_AES)
959 	{
960 		/*
961 		 * decrypt the stored AES password for comparing it
962 		 */
963 		storedPassword = get_decrypted_password(storedPassword);
964 		if (storedPassword == NULL)
965 			ereport(ERROR,
966 					(errmsg("clear text authentication failed"),
967 					 errdetail("unable to decrypt password from pool_passwd"),
968 					 errhint("verify the valid pool_key exists")));
969 	}
970 	else if (frontend->passwordMapping->pgpoolUser.passwordType == PASSWORD_TYPE_TEXT_PREFIXED)
971 	{
972 		storedPassword = frontend->passwordMapping->pgpoolUser.password + strlen(PASSWORD_TEXT_PREFIX);
973 	}
974 	else if (frontend->passwordMapping->pgpoolUser.passwordType != PASSWORD_TYPE_PLAINTEXT)
975 	{
976 		ereport(ERROR,
977 				(errmsg("clear text authentication failed"),
978 				 errdetail("password type stored in pool_passwd can't be used for clear text authentication")));
979 	}
980 
981 	if (memcmp(userPwd, storedPassword, size))
982 	{
983 		/* Password does not match */
984 		ereport(ERROR,
985 				(errmsg("clear text authentication failed"),
986 				 errdetail("password does not match")));
987 	}
988 	ereport(DEBUG1,
989 			(errmsg("clear text authentication successful with frontend")));
990 
991 	if (frontend->passwordMapping->pgpoolUser.passwordType == PASSWORD_TYPE_AES)
992 		pfree(storedPassword);
993 
994 	frontend->frontend_authenticated = true;
995 }
996 
997 /*
998  * perform clear text password authentication
999  */
1000 static int
do_clear_text_password(POOL_CONNECTION * backend,POOL_CONNECTION * frontend,int reauth,int protoMajor)1001 do_clear_text_password(POOL_CONNECTION * backend, POOL_CONNECTION * frontend, int reauth, int protoMajor)
1002 {
1003 	static int	size;
1004 	char	   *pwd = NULL;
1005 	int			kind;
1006 	PasswordType passwordType = PASSWORD_TYPE_UNKNOWN;
1007 
1008 	if (reauth && frontend->frontend_authenticated)
1009 	{
1010 		/* frontend and backend are both authenticated already */
1011 		return 0;
1012 	}
1013 
1014 	if (get_auth_password(backend, frontend, reauth, &pwd, &passwordType) == false)
1015 	{
1016 		/*
1017 		 * We do not have any passeord, we can still get the password
1018 		 * from client using plain text authentication if it is
1019 		 * allowed by user
1020 		 */
1021 
1022 		if (frontend->pool_hba == NULL ||
1023 			frontend->pool_hba->auth_method == uaPassword ||
1024 			pool_config->allow_clear_text_frontend_auth )
1025 		{
1026 			ereport(DEBUG1,
1027 				(errmsg("using clear text authentication with frontend"),
1028 					 errdetail("backend is using password authentication")));
1029 
1030 			authenticate_frontend_clear_text(frontend);
1031 
1032 			/* now check again if we have a password now */
1033 
1034 			if (get_auth_password(backend, frontend, reauth, &pwd, &passwordType) == false)
1035 			{
1036 				ereport(FATAL,
1037 						(return_code(2),
1038 							errmsg("clear text password authentication failed"),
1039 							errdetail("unable to get the password for user: \"%s\"", frontend->username)));
1040 			}
1041 		}
1042 	}
1043 
1044 	if (passwordType == PASSWORD_TYPE_AES)
1045 	{
1046 		/*
1047 		 * decrypt the stored AES password for comparing it
1048 		 */
1049 		pwd = get_decrypted_password(pwd);
1050 		if (pwd == NULL)
1051 			ereport(ERROR,
1052 					(errmsg("clear text password authentication failed"),
1053 					 errdetail("unable to decrypt password from pool_passwd"),
1054 					 errhint("verify the valid pool_key exists")));
1055 		/* we have converted the password to plain text */
1056 		passwordType = PASSWORD_TYPE_PLAINTEXT;
1057 	}
1058 
1059 	if (pwd == NULL || passwordType != PASSWORD_TYPE_PLAINTEXT)
1060 	{
1061 		/* If we still do not have a password. we can't proceed */
1062 		ereport(ERROR,
1063 				(errmsg("clear text password authentication failed"),
1064 				 errdetail("unable to get the password")));
1065 		return 0;
1066 	}
1067 
1068 	size = strlen(pwd);
1069 
1070 	/* connection reusing? */
1071 	if (reauth)
1072 	{
1073 		if (size != backend->pwd_size)
1074 			ereport(ERROR,
1075 					(errmsg("clear text password authentication failed"),
1076 					 errdetail("password size does not match")));
1077 
1078 		if (memcmp(pwd, backend->password, backend->pwd_size) != 0)
1079 			ereport(ERROR,
1080 					(errmsg("clear text password authentication failed"),
1081 					 errdetail("password does not match")));
1082 
1083 		return 0;
1084 	}
1085 
1086 	kind = send_password_packet(backend, protoMajor, pwd);
1087 
1088 	/* if authenticated, save info */
1089 	if (kind == AUTH_REQ_OK)
1090 	{
1091 		if (IS_MASTER_NODE_ID(backend->db_node_id))
1092 		{
1093 			send_auth_ok(frontend, protoMajor);
1094 		}
1095 
1096 		backend->auth_kind = AUTH_REQ_PASSWORD;
1097 		backend->pwd_size = size;
1098 		memcpy(backend->password, pwd, backend->pwd_size);
1099 		backend->passwordType = PASSWORD_TYPE_PLAINTEXT;
1100 	}
1101 	return kind;
1102 }
1103 
1104 /*
1105  * perform crypt authentication
1106  */
1107 static int
do_crypt(POOL_CONNECTION * backend,POOL_CONNECTION * frontend,int reauth,int protoMajor)1108 do_crypt(POOL_CONNECTION * backend, POOL_CONNECTION * frontend, int reauth, int protoMajor)
1109 {
1110 	char		salt[2];
1111 	static int	size;
1112 	static char password[MAX_PASSWORD_SIZE];
1113 	char		response;
1114 	int			kind;
1115 	int			len;
1116 
1117 	if (!reauth)
1118 	{
1119 		/* read salt */
1120 		pool_read(backend, salt, sizeof(salt));
1121 	}
1122 	else
1123 	{
1124 		memcpy(salt, backend->salt, sizeof(salt));
1125 	}
1126 
1127 	/* master? */
1128 	if (IS_MASTER_NODE_ID(backend->db_node_id))
1129 	{
1130 		pool_write(frontend, "R", 1);	/* authentication */
1131 		if (protoMajor == PROTO_MAJOR_V3)
1132 		{
1133 			len = htonl(10);
1134 			pool_write(frontend, &len, sizeof(len));
1135 		}
1136 		kind = htonl(4);		/* crypt authentication */
1137 		pool_write(frontend, &kind, sizeof(kind));	/* indicating crypt
1138 													 * authentication */
1139 		pool_write_and_flush(frontend, salt, sizeof(salt)); /* salt */
1140 
1141 		/* read password packet */
1142 		if (protoMajor == PROTO_MAJOR_V2)
1143 		{
1144 			pool_read(frontend, &size, sizeof(size));
1145 		}
1146 		else
1147 		{
1148 			char		k;
1149 
1150 			pool_read(frontend, &k, sizeof(k));
1151 			if (k != 'p')
1152 			{
1153 				ereport(ERROR,
1154 						(errmsg("crypt authentication failed"),
1155 						 errdetail("invalid password packet. Packet does not starts with \"p\"")));
1156 			}
1157 			pool_read(frontend, &size, sizeof(size));
1158 		}
1159 
1160 		if ((ntohl(size) - 4) > sizeof(password))
1161 		{
1162 			ereport(ERROR,
1163 					(errmsg("crypt authentication failed"),
1164 					 errdetail("password is too long, password size is %d", ntohl(size) - 4)));
1165 		}
1166 
1167 		pool_read(frontend, password, ntohl(size) - 4);
1168 	}
1169 
1170 	/* connection reusing? */
1171 	if (reauth)
1172 	{
1173 		ereport(DEBUG1,
1174 				(errmsg("performing crypt authentication"),
1175 				 errdetail("size: %d saved_size: %d", (ntohl(size) - 4), backend->pwd_size)));
1176 
1177 		if ((ntohl(size) - 4) != backend->pwd_size)
1178 			ereport(ERROR,
1179 					(errmsg("crypt authentication failed"),
1180 					 errdetail("password size does not match")));
1181 
1182 
1183 		if (memcmp(password, backend->password, backend->pwd_size) != 0)
1184 			ereport(ERROR,
1185 					(errmsg("crypt authentication failed"),
1186 					 errdetail("password does not match")));
1187 
1188 		return 0;
1189 	}
1190 
1191 	/* send password packet to backend */
1192 	if (protoMajor == PROTO_MAJOR_V3)
1193 		pool_write(backend, "p", 1);
1194 	pool_write(backend, &size, sizeof(size));
1195 	pool_write_and_flush(backend, password, ntohl(size) - 4);
1196 	pool_read(backend, &response, sizeof(response));
1197 
1198 	if (response != 'R')
1199 	{
1200 		if (response == 'E')	/* Backend has thrown an error instead */
1201 		{
1202 			char	   *message = NULL;
1203 
1204 			if (pool_extract_error_message(false, backend, protoMajor, false, &message) == 1)
1205 			{
1206 				ereport(ERROR,
1207 						(errmsg("crypt authentication failed"),
1208 						 errdetail("%s", message ? message : "backend throws authentication error")));
1209 			}
1210 			if (message)
1211 				pfree(message);
1212 		}
1213 		ereport(ERROR,
1214 				(errmsg("crypt authentication failed"),
1215 				 errdetail("invalid packet from backend. backend does not return R while processing clear text password authentication")));
1216 	}
1217 
1218 	if (protoMajor == PROTO_MAJOR_V3)
1219 	{
1220 		pool_read(backend, &len, sizeof(len));
1221 
1222 		if (ntohl(len) != 8)
1223 			ereport(ERROR,
1224 					(errmsg("crypt authentication failed"),
1225 					 errdetail("invalid packet from backend. incorrect authentication packet size (%d)", ntohl(len))));
1226 	}
1227 
1228 	/* expect to read "Authentication OK" response. kind should be 0... */
1229 	pool_read(backend, &kind, sizeof(kind));
1230 
1231 	/* if authenticated, save info */
1232 	if (kind == 0)
1233 	{
1234 		int			msglen;
1235 
1236 		pool_write(frontend, "R", 1);
1237 
1238 		if (protoMajor == PROTO_MAJOR_V3)
1239 		{
1240 			msglen = htonl(8);
1241 			pool_write(frontend, &msglen, sizeof(msglen));
1242 		}
1243 
1244 		msglen = htonl(0);
1245 		pool_write_and_flush(frontend, &msglen, sizeof(msglen));
1246 
1247 		backend->auth_kind = 4;
1248 		backend->pwd_size = ntohl(size) - 4;
1249 		memcpy(backend->password, password, backend->pwd_size);
1250 		memcpy(backend->salt, salt, sizeof(salt));
1251 	}
1252 	return kind;
1253 }
1254 
1255 /*
1256  * Do the SCRAM authentication with the frontend using the stored
1257  * password in the pool_passwd file.
1258  */
1259 static void
authenticate_frontend_SCRAM(POOL_CONNECTION * backend,POOL_CONNECTION * frontend,int reauth)1260 authenticate_frontend_SCRAM(POOL_CONNECTION * backend, POOL_CONNECTION * frontend, int reauth)
1261 {
1262 	void	   *scram_opaq;
1263 	char	   *output = NULL;
1264 	int			outputlen = 0;
1265 	char	   *input;
1266 	int			inputlen;
1267 	int			result;
1268 	bool		initial;
1269 	char	   *logdetail = NULL;
1270 	char	   *shadow_pass;
1271 
1272 	PasswordType storedPasswordType = PASSWORD_TYPE_UNKNOWN;
1273 	char	   *storedPassword = NULL;
1274 
1275 	if (get_auth_password(backend, frontend, reauth,&storedPassword, &storedPasswordType) == false)
1276 	{
1277 		ereport(FATAL,
1278 				(return_code(2),
1279 				 errmsg("SCRAM authentication failed"),
1280 				 errdetail("pool_passwd file does not contain an entry for \"%s\"", frontend->username)));
1281 	}
1282 
1283 	if (storedPasswordType == PASSWORD_TYPE_AES)
1284 	{
1285 		/*
1286 		 * decrypt the stored AES password for comparing it
1287 		 */
1288 		storedPassword = get_decrypted_password(storedPassword);
1289 		if (storedPassword == NULL)
1290 			ereport(ERROR,
1291 					(errmsg("SCRAM authentication failed"),
1292 					 errdetail("unable to decrypt password from pool_passwd"),
1293 					 errhint("verify the valid pool_key exists")));
1294 		/* we have converted the password to plain text */
1295 		storedPasswordType = PASSWORD_TYPE_PLAINTEXT;
1296 	}
1297 
1298 	if (storedPasswordType != PASSWORD_TYPE_PLAINTEXT)
1299 	{
1300 		ereport(ERROR,
1301 				(errmsg("SCRAM authentication failed"),
1302 				 errdetail("username \"%s\" has invalid password type", frontend->username)));
1303 	}
1304 
1305 	shadow_pass = pg_be_scram_build_verifier(storedPassword);
1306 	if (!shadow_pass)
1307 		ereport(ERROR,
1308 				(errmsg("authentication failed"),
1309 				 errdetail("faild to build the scram verifier")));
1310 
1311 	/*
1312 	 * SASL auth is not supported for protocol versions before 3, because it
1313 	 * relies on the overall message length word to determine the SASL payload
1314 	 * size in AuthenticationSASLContinue and PasswordMessage messages.  (We
1315 	 * used to have a hard rule that protocol messages must be parsable
1316 	 * without relying on the length word, but we hardly care about older
1317 	 * protocol version anymore.)
1318 	 */
1319 	if (frontend->protoVersion < PROTO_MAJOR_V3)
1320 		ereport(FATAL,
1321 				(errmsg("SASL authentication is not supported in protocol version 2")));
1322 
1323 	/*
1324 	 * Send the SASL authentication request to user.  It includes the list of
1325 	 * authentication mechanisms (which is trivial, because we only support
1326 	 * SCRAM-SHA-256 at the moment).  The extra "\0" is for an empty string to
1327 	 * terminate the list.
1328 	 */
1329 
1330 	sendAuthRequest(frontend, frontend->protoVersion, AUTH_REQ_SASL, SCRAM_SHA_256_NAME "\0",
1331 					strlen(SCRAM_SHA_256_NAME) + 2);
1332 
1333 	/*
1334 	 * Initialize the status tracker for message exchanges.
1335 	 *
1336 	 * If the user doesn't exist, or doesn't have a valid password, or it's
1337 	 * expired, we still go through the motions of SASL authentication, but
1338 	 * tell the authentication method that the authentication is "doomed".
1339 	 * That is, it's going to fail, no matter what.
1340 	 *
1341 	 * This is because we don't want to reveal to an attacker what usernames
1342 	 * are valid, nor which users have a valid password.
1343 	 */
1344 	scram_opaq = pg_be_scram_init(frontend->username, shadow_pass);
1345 
1346 	/*
1347 	 * Loop through SASL message exchange.  This exchange can consist of
1348 	 * multiple messages sent in both directions.  First message is always
1349 	 * from the client.  All messages from client to server are password
1350 	 * packets (type 'p').
1351 	 */
1352 	initial = true;
1353 	do
1354 	{
1355 		static int	size;
1356 		static char data[MAX_PASSWORD_SIZE];
1357 
1358 		/* Read password packet */
1359 		read_password_packet(frontend, frontend->protoVersion, data, &size);
1360 
1361 		ereport(DEBUG4,
1362 				(errmsg("Processing received SASL response of length %d", size)));
1363 
1364 		/*
1365 		 * The first SASLInitialResponse message is different from the others.
1366 		 * It indicates which SASL mechanism the client selected, and contains
1367 		 * an optional Initial Client Response payload.  The subsequent
1368 		 * SASLResponse messages contain just the SASL payload.
1369 		 */
1370 		if (initial)
1371 		{
1372 			const char *selected_mech;
1373 			char	   *ptr = data;
1374 
1375 			/*
1376 			 * We only support SCRAM-SHA-256 at the moment, so anything else
1377 			 * is an error.
1378 			 */
1379 			selected_mech = data;
1380 			if (strcmp(selected_mech, SCRAM_SHA_256_NAME) != 0)
1381 			{
1382 				ereport(ERROR,
1383 						(errmsg("client selected an invalid SASL authentication mechanism")));
1384 			}
1385 			/* get the length of trailing optional data */
1386 			ptr += strlen(selected_mech) + 1;
1387 			memcpy(&inputlen, ptr, sizeof(int));
1388 			inputlen = ntohl(inputlen);
1389 			if (inputlen == -1)
1390 				input = NULL;
1391 			else
1392 				input = ptr + 4;
1393 
1394 			initial = false;
1395 		}
1396 		else
1397 		{
1398 			inputlen = size;
1399 			input = data;
1400 		}
1401 		Assert(input == NULL || input[inputlen] == '\0');
1402 
1403 		/*
1404 		 * we pass 'logdetail' as NULL when doing a mock authentication,
1405 		 * because we should already have a better error message in that case
1406 		 */
1407 		result = pg_be_scram_exchange(scram_opaq, input, inputlen,
1408 									  &output, &outputlen,
1409 									  &logdetail);
1410 
1411 		/* input buffer no longer used */
1412 
1413 		if (output)
1414 		{
1415 			/*
1416 			 * Negotiation generated data to be sent to the client.
1417 			 */
1418 			ereport(DEBUG4,
1419 					(errmsg("sending SASL challenge of length %u", outputlen)));
1420 
1421 			if (result == SASL_EXCHANGE_SUCCESS)
1422 				sendAuthRequest(frontend, frontend->protoVersion, AUTH_REQ_SASL_FIN, output, outputlen);
1423 			else
1424 				sendAuthRequest(frontend, frontend->protoVersion, AUTH_REQ_SASL_CONT, output, outputlen);
1425 
1426 			pfree(output);
1427 		}
1428 	} while (result == SASL_EXCHANGE_CONTINUE);
1429 
1430 	/* Oops, Something bad happened */
1431 	if (result != SASL_EXCHANGE_SUCCESS)
1432 	{
1433 		ereport(ERROR,
1434 				(errmsg("authentication failed"),
1435 				 errdetail("username \"%s\" or password does not exist in backend", frontend->username)));
1436 	}
1437 	frontend->frontend_authenticated = true;
1438 }
1439 
1440 void
authenticate_frontend(POOL_CONNECTION * frontend)1441 authenticate_frontend(POOL_CONNECTION * frontend)
1442 {
1443 	switch (frontend->pool_hba->auth_method)
1444 	{
1445 		case uaMD5:
1446 			authenticate_frontend_md5(NULL, frontend, 0, frontend->protoVersion);
1447 			break;
1448 		case uaCert:
1449 			authenticate_frontend_cert(frontend);
1450 			break;
1451 		case uaSCRAM:
1452 			authenticate_frontend_SCRAM(NULL, frontend, 0);
1453 			break;
1454 		case uaPassword:
1455 			authenticate_frontend_clear_text(frontend);
1456 			break;
1457 		case uaImplicitReject:
1458 		case uaReject:
1459 			ereport(ERROR,
1460 					(errmsg("authentication with pgpool failed for user \"%s\" rejected", frontend->username)));
1461 			break;
1462 		case uaTrust:
1463 			frontend->frontend_authenticated = true;
1464 			break;
1465 #ifdef USE_PAM
1466 		case uaPAM:
1467 			break;
1468 #endif							/* USE_PAM */
1469 
1470 	}
1471 }
1472 
1473 #ifdef USE_SSL
1474 static void
authenticate_frontend_cert(POOL_CONNECTION * frontend)1475 authenticate_frontend_cert(POOL_CONNECTION * frontend)
1476 {
1477 	if (frontend->client_cert_loaded == true && frontend->cert_cn)
1478 	{
1479 		ereport(DEBUG1,
1480 				(errmsg("connecting user is \"%s\" and ssl certificate CN is \"%s\"", frontend->username, frontend->cert_cn)));
1481 		if (strcasecmp(frontend->username, frontend->cert_cn) == 0)
1482 		{
1483 			frontend->frontend_authenticated = true;
1484 			ereport(LOG,
1485 					(errmsg("SSL certificate authentication for user \"%s\" with Pgpool-II is successful", frontend->username)));
1486 			return;
1487 		}
1488 		else
1489 		{
1490 			frontend->frontend_authenticated = false;
1491 			ereport(LOG,
1492 					(errmsg("SSL certificate authentication for user \"%s\" failed", frontend->username)));
1493 		}
1494 	}
1495 	ereport(ERROR,
1496 			(errmsg("CERT authentication failed"),
1497 			 errdetail("no valid certificate presented")));
1498 
1499 }
1500 #else
1501 static void
authenticate_frontend_cert(POOL_CONNECTION * frontend)1502 authenticate_frontend_cert(POOL_CONNECTION * frontend)
1503 {
1504 	ereport(ERROR,
1505 			(errmsg("CERT authentication failed"),
1506 			 errdetail("CERT authentication is not supported without SSL")));
1507 }
1508 #endif
1509 
1510 static void
authenticate_frontend_md5(POOL_CONNECTION * backend,POOL_CONNECTION * frontend,int reauth,int protoMajor)1511 authenticate_frontend_md5(POOL_CONNECTION * backend, POOL_CONNECTION * frontend, int reauth, int protoMajor)
1512 {
1513 	char		salt[4];
1514 	static int	size;
1515 	char		password[MAX_PASSWORD_SIZE];
1516 	char		userPassword[MAX_PASSWORD_SIZE];
1517 	char		encbuf[POOL_PASSWD_LEN + 1];
1518 	char	   *md5;
1519 
1520 	PasswordType storedPasswordType = PASSWORD_TYPE_UNKNOWN;
1521 	char	   *storedPassword = NULL;
1522 
1523 	if (RAW_MODE || NUM_BACKENDS == 1)
1524 	{
1525 		if (backend)
1526 			do_md5_single_backend(backend, frontend, reauth, protoMajor);
1527 		return;					/* This will be handled later */
1528 	}
1529 
1530 	if (get_auth_password(backend, frontend, reauth,&storedPassword, &storedPasswordType) == false)
1531 	{
1532 		ereport(FATAL,
1533 				(return_code(2),
1534 				 errmsg("md5 authentication failed"),
1535 				 errdetail("pool_passwd file does not contain an entry for \"%s\"", frontend->username)));
1536 	}
1537 
1538 	pool_random_salt(salt);
1539 	send_md5auth_request(frontend, frontend->protoVersion, salt);
1540 
1541 	/* Read password packet */
1542 	read_password_packet(frontend, frontend->protoVersion, password, &size);
1543 
1544 	/* If we have clear text password stored in pool_passwd, convert it to md5 */
1545 	if (storedPasswordType == PASSWORD_TYPE_PLAINTEXT || storedPasswordType == PASSWORD_TYPE_AES)
1546 	{
1547 		char	   *pwd;
1548 
1549 		if (storedPasswordType == PASSWORD_TYPE_AES)
1550 		{
1551 			pwd = get_decrypted_password(storedPassword);
1552 			if (pwd == NULL)
1553 				ereport(ERROR,
1554 						(errmsg("md5 authentication failed"),
1555 						 errdetail("unable to decrypt password from pool_passwd"),
1556 						 errhint("verify the valid pool_key exists")));
1557 		}
1558 		else
1559 		{
1560 			pwd = storedPassword;
1561 		}
1562 		pg_md5_encrypt(pwd,
1563 					   frontend->username,
1564 					   strlen(frontend->username), userPassword);
1565 
1566 		if (storedPasswordType == PASSWORD_TYPE_AES)
1567 			pfree(pwd);
1568 
1569 		md5 = userPassword;
1570 	}
1571 	else if (storedPasswordType == PASSWORD_TYPE_MD5)
1572 	{
1573 		md5 = storedPassword;
1574 	}
1575 	else
1576 	{
1577 		ereport(FATAL,
1578 				(return_code(2),
1579 				 errmsg("md5 authentication failed"),
1580 				 errdetail("unable to get the password for \"%s\"", frontend->username)));
1581 	}
1582 
1583 	/* Check the password using my salt + pool_passwd */
1584 	pg_md5_encrypt(md5 + strlen("md5"), salt, sizeof(salt), encbuf);
1585 	if (strcmp(password, encbuf))
1586 	{
1587 		/* Password does not match */
1588 		ereport(ERROR,
1589 				(errmsg("md5 authentication failed"),
1590 				 errdetail("password does not match")));
1591 	}
1592 	ereport(DEBUG1,
1593 			(errmsg("md5 authentication successful with frontend")));
1594 
1595 	frontend->frontend_authenticated = true;
1596 }
1597 
1598 /*
1599  * perform MD5 authentication
1600  */
1601 static int
do_md5_single_backend(POOL_CONNECTION * backend,POOL_CONNECTION * frontend,int reauth,int protoMajor)1602 do_md5_single_backend(POOL_CONNECTION * backend, POOL_CONNECTION * frontend, int reauth, int protoMajor)
1603 {
1604 	char		salt[4];
1605 	static int	size;
1606 	static char password[MAX_PASSWORD_SIZE];
1607 	int			kind;
1608 
1609 	if (!reauth)
1610 	{
1611 		/* read salt from backend */
1612 		pool_read(backend, salt, sizeof(salt));
1613 		ereport(DEBUG1,
1614 				(errmsg("performing md5 authentication"),
1615 				 errdetail("DB node id: %d salt: %hhx%hhx%hhx%hhx", backend->db_node_id,
1616 						   salt[0], salt[1], salt[2], salt[3])));
1617 	}
1618 	else
1619 	{
1620 		/* Use the saved salt */
1621 		memcpy(salt, backend->salt, sizeof(salt));
1622 	}
1623 
1624 	/* Send md5 auth request to frontend */
1625 	send_md5auth_request(frontend, protoMajor, salt);
1626 
1627 	/* Read password packet */
1628 	read_password_packet(frontend, protoMajor, password, &size);
1629 
1630 	/* connection reusing? compare it with saved password */
1631 	if (reauth)
1632 	{
1633 		if (backend->passwordType != PASSWORD_TYPE_MD5)
1634 			ereport(ERROR,
1635 					(errmsg("md5 authentication failed"),
1636 					 errdetail("invalid password type")));
1637 
1638 		if (size != backend->pwd_size)
1639 			ereport(ERROR,
1640 					(errmsg("md5 authentication failed"),
1641 					 errdetail("password does not match")));
1642 
1643 		if (memcmp(password, backend->password, backend->pwd_size) != 0)
1644 			ereport(ERROR,
1645 					(errmsg("md5 authentication failed"),
1646 					 errdetail("password does not match")));
1647 		return 0;
1648 	}
1649 	else
1650 	{
1651 		/* Send password packet to backend and receive auth response */
1652 		kind = send_password_packet(backend, protoMajor, password);
1653 		if (kind < 0)
1654 			ereport(ERROR,
1655 					(errmsg("md5 authentication failed"),
1656 					 errdetail("backend replied with invalid kind")));
1657 
1658 		/* If authenticated, reply back to frontend and save info */
1659 		if (kind == AUTH_REQ_OK)
1660 		{
1661 			send_auth_ok(frontend, protoMajor);
1662 			backend->passwordType = PASSWORD_TYPE_MD5;
1663 			backend->auth_kind = AUTH_REQ_MD5;
1664 			backend->pwd_size = size;
1665 			memcpy(backend->password, password, backend->pwd_size);
1666 			memcpy(backend->salt, salt, sizeof(salt));
1667 		}
1668 	}
1669 	return kind;
1670 }
1671 
1672 static bool
get_auth_password(POOL_CONNECTION * backend,POOL_CONNECTION * frontend,int reauth,char ** password,PasswordType * passwordType)1673 get_auth_password(POOL_CONNECTION * backend, POOL_CONNECTION * frontend, int reauth,
1674 				  char **password, PasswordType *passwordType)
1675 {
1676 	/* First preference is to use the pool_passwd file */
1677 	if (frontend->passwordMapping == NULL)
1678 		frontend->passwordMapping = pool_get_user_credentials(frontend->username);
1679 
1680 	if (frontend->passwordMapping == NULL)
1681 	{
1682 		/*
1683 		 * check if we have password stored in the frontend connection. that
1684 		 * could come by using the clear text auth
1685 		 */
1686 		if (frontend->pwd_size > 0 && frontend->passwordType == PASSWORD_TYPE_PLAINTEXT)
1687 		{
1688 			*password = frontend->password;
1689 			*passwordType = frontend->passwordType;
1690 			return true;
1691 		}
1692 		else if (reauth && backend && backend->pwd_size > 0)
1693 		{
1694 			*password = backend->password;
1695 			*passwordType = backend->passwordType;
1696 			return true;
1697 		}
1698 	}
1699 	else
1700 	{
1701 		if (frontend->passwordMapping->pgpoolUser.passwordType == PASSWORD_TYPE_TEXT_PREFIXED)
1702 		{
1703 			/* convert the TEXT prefixed password to plain text password */
1704 			*passwordType = PASSWORD_TYPE_PLAINTEXT;
1705 			*password = frontend->passwordMapping->pgpoolUser.password + strlen(PASSWORD_TEXT_PREFIX);
1706 		}
1707 		else
1708 		{
1709 			*password = frontend->passwordMapping->pgpoolUser.password;
1710 			*passwordType = frontend->passwordMapping->pgpoolUser.passwordType;
1711 		}
1712 		return true;
1713 	}
1714 	return false;
1715 }
1716 
1717 /*
1718  * perform MD5 authentication
1719  */
1720 static int
do_md5(POOL_CONNECTION * backend,POOL_CONNECTION * frontend,int reauth,int protoMajor,char * storedPassword,PasswordType passwordType)1721 do_md5(POOL_CONNECTION * backend, POOL_CONNECTION * frontend, int reauth, int protoMajor,
1722 	   char *storedPassword, PasswordType passwordType)
1723 {
1724 	char		salt[4];
1725 	static char userPassword[MAX_PASSWORD_SIZE];
1726 	int			kind;
1727 	bool		password_decrypted = false;
1728 	char		encbuf[POOL_PASSWD_LEN + 1];
1729 	char	   *pool_passwd = NULL;
1730 
1731 	if (RAW_MODE || NUM_BACKENDS == 1)
1732 		return do_md5_single_backend(backend, frontend, reauth, protoMajor);
1733 
1734 	if (passwordType == PASSWORD_TYPE_AES)
1735 	{
1736 		/*
1737 		 * decrypt the stored AES password for comparing it
1738 		 */
1739 		storedPassword = get_decrypted_password(storedPassword);
1740 		if (storedPassword == NULL)
1741 			ereport(ERROR,
1742 					(errmsg("md5 authentication failed"),
1743 					 errdetail("unable to decrypt password from pool_passwd"),
1744 					 errhint("verify the valid pool_key exists")));
1745 		/* we have converted the password to plain text */
1746 		passwordType = PASSWORD_TYPE_PLAINTEXT;
1747 		password_decrypted = true;
1748 	}
1749 	if (passwordType == PASSWORD_TYPE_PLAINTEXT)
1750 	{
1751 		pg_md5_encrypt(storedPassword,
1752 					   frontend->username,
1753 					   strlen(frontend->username), userPassword);
1754 		pool_passwd = userPassword;
1755 	}
1756 	else if (passwordType == PASSWORD_TYPE_MD5)
1757 	{
1758 		pool_passwd = storedPassword;
1759 	}
1760 	else
1761 	{
1762 		ereport(ERROR,
1763 				(errmsg("md5 authentication failed"),
1764 				 errdetail("unable to get the password")));
1765 	}
1766 
1767 	/* master? */
1768 	if (IS_MASTER_NODE_ID(backend->db_node_id) && frontend->frontend_authenticated == false)
1769 	{
1770 		/*
1771 		 * If frontend is not authenticated and do it it first. but if we have
1772 		 * already received the password from frontend using the clear text
1773 		 * auth, we may not need to authenticate it
1774 		 */
1775 		if (pool_config->allow_clear_text_frontend_auth &&
1776 			frontend->auth_kind == AUTH_REQ_PASSWORD &&
1777 			frontend->pwd_size > 0 &&
1778 			frontend->passwordType == PASSWORD_TYPE_PLAINTEXT)
1779 		{
1780 			ereport(DEBUG2,
1781 					(errmsg("MD5 authentication using the password from frontend")));
1782 			/* save this password in backend for the re-auth */
1783 			backend->pwd_size = frontend->pwd_size;
1784 			memcpy(backend->password, frontend->password, frontend->pwd_size);
1785 			backend->password[backend->pwd_size] = 0;	/* null terminate */
1786 			backend->passwordType = frontend->passwordType;
1787 		}
1788 		else
1789 		{
1790 			authenticate_frontend_md5(backend, frontend, reauth, protoMajor);
1791 		}
1792 	}
1793 
1794 	if (!reauth)
1795 	{
1796 		/*
1797 		 * now authenticate the backend
1798 		 */
1799 
1800 		/* Read salt */
1801 		pool_read(backend, salt, sizeof(salt));
1802 
1803 		ereport(DEBUG2,
1804 				(errmsg("performing md5 authentication"),
1805 				 errdetail("DB node id: %d salt: %hhx%hhx%hhx%hhx", backend->db_node_id,
1806 						   salt[0], salt[1], salt[2], salt[3])));
1807 
1808 		/* Encrypt password in pool_passwd using the salt */
1809 		pg_md5_encrypt(pool_passwd + strlen("md5"), salt, sizeof(salt), encbuf);
1810 
1811 		/* Send password packet to backend and receive auth response */
1812 		kind = send_password_packet(backend, protoMajor, encbuf);
1813 		if (kind < 0)
1814 			ereport(ERROR,
1815 					(errmsg("md5 authentication failed"),
1816 					 errdetail("backend replied with invalid kind")));
1817 	}
1818 
1819 	if (!reauth && kind == 0)
1820 	{
1821 		if (IS_MASTER_NODE_ID(backend->db_node_id))
1822 		{
1823 			/* Send auth ok to frontend */
1824 			send_auth_ok(frontend, protoMajor);
1825 		}
1826 
1827 		/* Save the auth info */
1828 		backend->auth_kind = AUTH_REQ_MD5;
1829 	}
1830 
1831 	if (password_decrypted && storedPassword)
1832 		pfree(storedPassword);
1833 
1834 	return 0;
1835 }
1836 
1837 /*
1838  * Send an authentication request packet to the frontend.
1839  */
1840 static void
sendAuthRequest(POOL_CONNECTION * frontend,int protoMajor,int32 auth_req_type,char * extradata,int extralen)1841 sendAuthRequest(POOL_CONNECTION * frontend, int protoMajor, int32 auth_req_type, char *extradata, int extralen)
1842 {
1843 	int			kind = htonl(auth_req_type);
1844 
1845 	pool_write(frontend, "R", 1);	/* authentication */
1846 	if (protoMajor == PROTO_MAJOR_V3)
1847 	{
1848 		int			len = 8 + extralen;
1849 
1850 		len = htonl(len);
1851 		pool_write(frontend, &len, sizeof(len));
1852 	}
1853 	pool_write(frontend, &kind, sizeof(kind));
1854 	if (extralen > 0)
1855 		pool_write_and_flush(frontend, extradata, extralen);
1856 	else
1857 		pool_flush(frontend);
1858 }
1859 
1860 /*
1861  * Send md5 authentication request packet to frontend
1862  */
1863 static void
send_md5auth_request(POOL_CONNECTION * frontend,int protoMajor,char * salt)1864 send_md5auth_request(POOL_CONNECTION * frontend, int protoMajor, char *salt)
1865 {
1866 	sendAuthRequest(frontend, protoMajor, AUTH_REQ_MD5, salt, 4);
1867 }
1868 
1869 
1870 /*
1871  * Read password packet from frontend
1872  */
1873 static int
read_password_packet(POOL_CONNECTION * frontend,int protoMajor,char * password,int * pwdSize)1874 read_password_packet(POOL_CONNECTION * frontend, int protoMajor, char *password, int *pwdSize)
1875 {
1876 	int			size;
1877 
1878 	/* Read password packet */
1879 	if (protoMajor == PROTO_MAJOR_V2)
1880 	{
1881 		pool_read(frontend, &size, sizeof(size));
1882 	}
1883 	else
1884 	{
1885 		char		k;
1886 
1887 		pool_read(frontend, &k, sizeof(k));
1888 		if (k != 'p')
1889 			ereport(ERROR,
1890 					(errmsg("authentication failed"),
1891 					 errdetail("invalid authentication packet. password packet does not start with \"p\"")));
1892 
1893 		pool_read(frontend, &size, sizeof(size));
1894 	}
1895 
1896 	*pwdSize = ntohl(size) - 4;
1897 	if (*pwdSize > MAX_PASSWORD_SIZE)
1898 	{
1899 		ereport(ERROR,
1900 				(errmsg("authentication failed"),
1901 				 errdetail("invalid authentication packet. password is too long. password length is %d", *pwdSize)));
1902 
1903 		/*
1904 		 * We do not read to throw away packet here. Since it is possible that
1905 		 * it's a denial of service attack.
1906 		 */
1907 	}
1908 	else if (*pwdSize <= 0)
1909 		ereport(ERROR,
1910 				(errmsg("authentication failed"),
1911 				 errdetail("invalid authentication packet. invalid password length. password length is %d", *pwdSize)));
1912 
1913 	pool_read(frontend, password, *pwdSize);
1914 
1915 	password[*pwdSize] = '\0';
1916 
1917 	return 0;
1918 }
1919 
1920 /*
1921  * Send password packet to backend and receive authentication response
1922  * packet.  Return value is the last field of authentication
1923  * response. If it's 0, authentication was successful.
1924  * "password" must be null-terminated.
1925  */
1926 static int
send_password_packet(POOL_CONNECTION * backend,int protoMajor,char * password)1927 send_password_packet(POOL_CONNECTION * backend, int protoMajor, char *password)
1928 {
1929 	int			size;
1930 	int			len;
1931 	int			kind;
1932 	char		response;
1933 
1934 	/* Send password packet to backend */
1935 	if (protoMajor == PROTO_MAJOR_V3)
1936 		pool_write(backend, "p", 1);
1937 	size = htonl(sizeof(size) + strlen(password) + 1);
1938 	pool_write(backend, &size, sizeof(size));
1939 	pool_write_and_flush(backend, password, strlen(password) + 1);
1940 
1941 	pool_read(backend, &response, sizeof(response));
1942 
1943 	if (response != 'R')
1944 	{
1945 		if (response == 'E')	/* Backend has thrown an error instead */
1946 		{
1947 			char	   *message = NULL;
1948 
1949 			if (pool_extract_error_message(false, backend, protoMajor, false, &message) == 1)
1950 			{
1951 				ereport(ERROR,
1952 						(errmsg("authentication failed"),
1953 						 errdetail("%s", message ? message : "backend throws authentication error")));
1954 			}
1955 			if (message)
1956 				pfree(message);
1957 		}
1958 		ereport(ERROR,
1959 				(errmsg("authentication failed"),
1960 				 errdetail("invalid backend response. Response does not replied with \"R\"")));
1961 	}
1962 
1963 	if (protoMajor == PROTO_MAJOR_V3)
1964 	{
1965 		pool_read(backend, &len, sizeof(len));
1966 
1967 		if (ntohl(len) != 8)
1968 			ereport(ERROR,
1969 					(errmsg("authentication failed"),
1970 					 errdetail("invalid authentication packet. incorrect authentication packet size (%d)", ntohl(len))));
1971 	}
1972 
1973 	/* Expect to read "Authentication OK" response. kind should be 0... */
1974 	pool_read(backend, &kind, sizeof(kind));
1975 
1976 	return kind;
1977 }
1978 
1979 /*
1980  * Send auth ok to frontend
1981  */
1982 static int
send_auth_ok(POOL_CONNECTION * frontend,int protoMajor)1983 send_auth_ok(POOL_CONNECTION * frontend, int protoMajor)
1984 {
1985 	int			msglen;
1986 
1987 	pool_write(frontend, "R", 1);
1988 
1989 	if (protoMajor == PROTO_MAJOR_V3)
1990 	{
1991 		msglen = htonl(8);
1992 		pool_write(frontend, &msglen, sizeof(msglen));
1993 	}
1994 
1995 	msglen = htonl(0);
1996 	pool_write_and_flush(frontend, &msglen, sizeof(msglen));
1997 	return 0;
1998 }
1999 
2000 /*
2001  * read message length (V3 only)
2002  */
2003 int
pool_read_message_length(POOL_CONNECTION_POOL * cp)2004 pool_read_message_length(POOL_CONNECTION_POOL * cp)
2005 {
2006 	int			length,
2007 				length0;
2008 	int			i;
2009 
2010 	/* read message from master node */
2011 	pool_read(CONNECTION(cp, MASTER_NODE_ID), &length0, sizeof(length0));
2012 	length0 = ntohl(length0);
2013 
2014 	ereport(DEBUG5,
2015 			(errmsg("reading message length"),
2016 			 errdetail("slot: %d length: %d", MASTER_NODE_ID, length0)));
2017 
2018 	for (i = 0; i < NUM_BACKENDS; i++)
2019 	{
2020 		if (!VALID_BACKEND(i) || IS_MASTER_NODE_ID(i))
2021 		{
2022 			continue;
2023 		}
2024 
2025 		pool_read(CONNECTION(cp, i), &length, sizeof(length));
2026 
2027 		length = ntohl(length);
2028 		ereport(DEBUG5,
2029 				(errmsg("reading message length"),
2030 				 errdetail("slot: %d length: %d", i, length)));
2031 
2032 		if (length != length0)
2033 		{
2034 			ereport(LOG,
2035 					(errmsg("unable to read message length"),
2036 					 errdetail("message length (%d) in slot %d does not match with slot 0(%d)", length, i, length0)));
2037 			return -1;
2038 		}
2039 
2040 	}
2041 
2042 	if (length0 < 0)
2043 		ereport(ERROR,
2044 				(errmsg("unable to read message length"),
2045 				 errdetail("invalid message length (%d)", length)));
2046 
2047 	return length0;
2048 }
2049 
2050 /*
2051  * read message length2 (V3 only)
2052  * unlike pool_read_message_length, this returns an array of message length.
2053  * The array is in the static storage, thus it will be destroyed by subsequent calls.
2054  */
2055 int *
pool_read_message_length2(POOL_CONNECTION_POOL * cp)2056 pool_read_message_length2(POOL_CONNECTION_POOL * cp)
2057 {
2058 	int			length,
2059 				length0;
2060 	int			i;
2061 	static int	length_array[MAX_CONNECTION_SLOTS];
2062 
2063 	/* read message from master node */
2064 	pool_read(CONNECTION(cp, MASTER_NODE_ID), &length0, sizeof(length0));
2065 
2066 	length0 = ntohl(length0);
2067 	length_array[MASTER_NODE_ID] = length0;
2068 	ereport(DEBUG5,
2069 			(errmsg("reading message length"),
2070 			 errdetail("master slot: %d length: %d", MASTER_NODE_ID, length0)));
2071 
2072 	for (i = 0; i < NUM_BACKENDS; i++)
2073 	{
2074 		if (VALID_BACKEND(i) && !IS_MASTER_NODE_ID(i))
2075 		{
2076 			pool_read(CONNECTION(cp, i), &length, sizeof(length));
2077 
2078 			length = ntohl(length);
2079 			ereport(DEBUG5,
2080 					(errmsg("reading message length"),
2081 					 errdetail("master slot: %d length: %d", i, length)));
2082 
2083 			if (length != length0)
2084 			{
2085 				ereport(LOG,
2086 						(errmsg("reading message length"),
2087 						 errdetail("message length (%d) in slot %d does not match with slot 0(%d)", length, i, length0)));
2088 			}
2089 
2090 			if (length < 0)
2091 			{
2092 				ereport(ERROR,
2093 						(errmsg("unable to read message length"),
2094 						 errdetail("invalid message length (%d)", length)));
2095 			}
2096 
2097 			length_array[i] = length;
2098 		}
2099 
2100 	}
2101 	return &length_array[0];
2102 }
2103 
2104 signed char
pool_read_kind(POOL_CONNECTION_POOL * cp)2105 pool_read_kind(POOL_CONNECTION_POOL * cp)
2106 {
2107 	char		kind0,
2108 				kind;
2109 	int			i;
2110 
2111 	kind = -1;
2112 	kind0 = 0;
2113 
2114 	for (i = 0; i < NUM_BACKENDS; i++)
2115 	{
2116 		if (!VALID_BACKEND(i))
2117 		{
2118 			continue;
2119 		}
2120 
2121 		pool_read(CONNECTION(cp, i), &kind, sizeof(kind));
2122 
2123 		if (IS_MASTER_NODE_ID(i))
2124 		{
2125 			kind0 = kind;
2126 		}
2127 		else
2128 		{
2129 			if (kind != kind0)
2130 			{
2131 				char	   *message;
2132 
2133 				if (kind0 == 'E')
2134 				{
2135 					if (pool_extract_error_message(false, MASTER(cp), MAJOR(cp), true, &message) == 1)
2136 					{
2137 						ereport(LOG,
2138 								(errmsg("pool_read_kind: error message from master backend:%s", message)));
2139 						pfree(message);
2140 					}
2141 				}
2142 				else if (kind == 'E')
2143 				{
2144 					if (pool_extract_error_message(false, CONNECTION(cp, i), MAJOR(cp), true, &message) == 1)
2145 					{
2146 						ereport(LOG,
2147 								(errmsg("pool_read_kind: error message from %d th backend:%s", i, message)));
2148 						pfree(message);
2149 					}
2150 				}
2151 				ereport(ERROR,
2152 						(errmsg("unable to read message kind"),
2153 						 errdetail("kind does not match between master(%x) slot[%d] (%x)", kind0, i, kind)));
2154 			}
2155 		}
2156 	}
2157 
2158 	return kind;
2159 }
2160 
2161 int
pool_read_int(POOL_CONNECTION_POOL * cp)2162 pool_read_int(POOL_CONNECTION_POOL * cp)
2163 {
2164 	int			data0,
2165 				data;
2166 	int			i;
2167 
2168 	data = -1;
2169 	data0 = 0;
2170 
2171 	for (i = 0; i < NUM_BACKENDS; i++)
2172 	{
2173 		if (!VALID_BACKEND(i))
2174 		{
2175 			continue;
2176 		}
2177 		pool_read(CONNECTION(cp, i), &data, sizeof(data));
2178 		if (IS_MASTER_NODE_ID(i))
2179 		{
2180 			data0 = data;
2181 		}
2182 		else
2183 		{
2184 			if (data != data0)
2185 			{
2186 				ereport(ERROR,
2187 						(errmsg("unable to read int value"),
2188 						 errdetail("data does not match between between master(%x) slot[%d] (%x)", data0, i, data)));
2189 
2190 			}
2191 		}
2192 	}
2193 	return data;
2194 }
2195 
2196 void
pool_random(void * buf,size_t len)2197 pool_random(void *buf, size_t len)
2198 {
2199 	int			ret = 0;
2200 #ifdef USE_SSL
2201 	ret = RAND_bytes(buf, len);
2202 #endif
2203 	/* if RND_bytes fails or not present use the old technique */
2204 	if (ret == 0)
2205 	{
2206 		int			i;
2207 		char	   *ptr = buf;
2208 
2209 		for (i = 0; i < len; i++)
2210 		{
2211 			long		rand = PostmasterRandom();
2212 
2213 			ptr[i] = (rand % 255) + 1;
2214 		}
2215 	}
2216 }
2217 
2218 /*
2219  *  pool_random_salt
2220  */
2221 void
pool_random_salt(char * md5Salt)2222 pool_random_salt(char *md5Salt)
2223 {
2224 	pool_random(md5Salt, 4);
2225 }
2226 
2227 /*
2228  * PostmasterRandom
2229  */
2230 static long
PostmasterRandom(void)2231 PostmasterRandom(void)
2232 {
2233 	extern struct timeval random_start_time;
2234 	static unsigned int random_seed = 0;
2235 
2236 	/*
2237 	 * Select a random seed at the time of first receiving a request.
2238 	 */
2239 	if (random_seed == 0)
2240 	{
2241 		do
2242 		{
2243 			struct timeval random_stop_time;
2244 
2245 			gettimeofday(&random_stop_time, NULL);
2246 
2247 			/*
2248 			 * We are not sure how much precision is in tv_usec, so we swap
2249 			 * the high and low 16 bits of 'random_stop_time' and XOR them
2250 			 * with 'random_start_time'. On the off chance that the result is
2251 			 * 0, we loop until it isn't.
2252 			 */
2253 			random_seed = random_start_time.tv_usec ^
2254 				((random_stop_time.tv_usec << 16) |
2255 				 ((random_stop_time.tv_usec >> 16) & 0xffff));
2256 		}
2257 		while (random_seed == 0);
2258 
2259 		srandom(random_seed);
2260 	}
2261 
2262 	return random();
2263 }
2264 
2265 
2266 static bool
do_SCRAM(POOL_CONNECTION * frontend,POOL_CONNECTION * backend,int protoMajor,int message_length,char * username,char * storedPassword,PasswordType passwordType)2267 do_SCRAM(POOL_CONNECTION * frontend, POOL_CONNECTION * backend, int protoMajor, int message_length,
2268 		 char *username, char *storedPassword, PasswordType passwordType)
2269 {
2270 	/* read the packet first */
2271 	void	   *sasl_state = NULL;
2272 	int			payload_len = message_length - 4 - 4;
2273 	int			auth_kind = AUTH_REQ_SASL;
2274 	char		payload[MAX_SASL_PAYLOAD_LEN];
2275 
2276 	if (passwordType != PASSWORD_TYPE_PLAINTEXT)
2277 	{
2278 		ereport(ERROR,
2279 				(errmsg("SCRAM authentication failed"),
2280 				 errdetail("invalid password type")));
2281 	}
2282 	if (storedPassword == NULL)
2283 	{
2284 		ereport(ERROR,
2285 				(errmsg("SCRAM authentication failed"),
2286 				 errdetail("password not found")));
2287 	}
2288 
2289 	/* master? */
2290 	if (frontend && IS_MASTER_NODE_ID(backend->db_node_id) && frontend->frontend_authenticated == false)
2291 	{
2292 		/*
2293 		 * If frontend is not authenticated and do it it first. but if we have
2294 		 * already received the password from frontend using the clear text
2295 		 * auth, we may not need to authenticate it
2296 		 */
2297 		if (pool_config->allow_clear_text_frontend_auth &&
2298 			frontend->auth_kind == AUTH_REQ_PASSWORD &&
2299 			frontend->pwd_size > 0 &&
2300 			frontend->passwordType == PASSWORD_TYPE_PLAINTEXT)
2301 		{
2302 			ereport(DEBUG2,
2303 					(errmsg("SCRAM authentication using the password from frontend")));
2304 			/* save this password in backend for the re-auth */
2305 			backend->pwd_size = frontend->pwd_size;
2306 			memcpy(backend->password, frontend->password, frontend->pwd_size);
2307 			backend->password[backend->pwd_size] = 0;	/* null terminate */
2308 			backend->passwordType = frontend->passwordType;
2309 		}
2310 		else
2311 		{
2312 			authenticate_frontend_SCRAM(backend, frontend, 0);
2313 		}
2314 	}
2315 
2316 	for (;;)
2317 	{
2318 		char		kind;
2319 		int			len;
2320 
2321 		/*
2322 		 * at this point we have already read kind, message length and
2323 		 * authkind
2324 		 */
2325 		if (payload_len > MAX_SASL_PAYLOAD_LEN)
2326 			ereport(ERROR,
2327 					(errmsg("invalid authentication data too big")));
2328 
2329 		pool_read(backend, payload, payload_len);
2330 
2331 		switch (auth_kind)
2332 		{
2333 			case AUTH_REQ_OK:
2334 				/* Save the auth info in backend */
2335 				backend->auth_kind = AUTH_REQ_SASL;
2336 				if (sasl_state)
2337 					pg_fe_scram_free(sasl_state);
2338 				return true;
2339 				break;
2340 			case AUTH_REQ_SASL:
2341 
2342 				/*
2343 				 * The request contains the name (as assigned by IANA) of the
2344 				 * authentication mechanism.
2345 				 */
2346 				sasl_state = pg_SASL_init(backend, payload, payload_len, username, storedPassword);
2347 				if (!sasl_state)
2348 				{
2349 					ereport(ERROR,
2350 							(errmsg("invalid authentication request from server")));
2351 					return false;
2352 				}
2353 				break;
2354 
2355 			case AUTH_REQ_SASL_CONT:
2356 			case AUTH_REQ_SASL_FIN:
2357 				if (sasl_state == NULL)
2358 				{
2359 					ereport(ERROR,
2360 							(errmsg("invalid authentication request from server: AUTH_REQ_SASL_CONT without AUTH_REQ_SASL")));
2361 					return false;
2362 				}
2363 				if (pg_SASL_continue(backend, payload, payload_len, sasl_state, (auth_kind == AUTH_REQ_SASL_FIN)) != 0)
2364 				{
2365 					/* Use error message, if set already */
2366 					ereport(ERROR,
2367 							(errmsg("error in SASL authentication")));
2368 
2369 				}
2370 				break;
2371 			default:
2372 				ereport(ERROR,
2373 						(errmsg("invalid authentication request from server: unknown auth kind %d", auth_kind)));
2374 		}
2375 		/* Read next backend */
2376 		pool_read(backend, &kind, sizeof(kind));
2377 		pool_read(backend, &len, sizeof(len));
2378 		if (kind != 'R')
2379 			ereport(ERROR,
2380 					(errmsg("backend authentication failed"),
2381 					 errdetail("backend response with kind \'%c\' when expecting \'R\'", kind)));
2382 		message_length = ntohl(len);
2383 		if (message_length < 8)
2384 			ereport(ERROR,
2385 					(errmsg("backend authentication failed"),
2386 					 errdetail("backend response with no data ")));
2387 
2388 		pool_read(backend, &auth_kind, sizeof(auth_kind));
2389 		auth_kind = ntohl(auth_kind);
2390 		payload_len = message_length - 4 - 4;
2391 	}
2392 	return false;
2393 }
2394 
2395 static void *
pg_SASL_init(POOL_CONNECTION * backend,char * payload,int payloadlen,char * username,char * storedPassword)2396 pg_SASL_init(POOL_CONNECTION * backend, char *payload, int payloadlen, char *username, char *storedPassword)
2397 {
2398 	char	   *initialresponse = NULL;
2399 	int			initialresponselen;
2400 	bool		done;
2401 	bool		success;
2402 	const char *selected_mechanism;
2403 	char	   *mechanism_buf = payload;
2404 	void	   *sasl_state = NULL;
2405 	int			size;
2406 	int			send_msg_len;
2407 
2408 	/*
2409 	 * Parse the list of SASL authentication mechanisms in the
2410 	 * AuthenticationSASL message, and select the best mechanism that we
2411 	 * support.  (Only SCRAM-SHA-256 is supported at the moment.)
2412 	 */
2413 	selected_mechanism = NULL;
2414 	for (;;)
2415 	{
2416 		/* An empty string indicates end of list */
2417 		if (mechanism_buf[0] == '\0')
2418 			break;
2419 
2420 		/*
2421 		 * If we have already selected a mechanism, just skip through the rest
2422 		 * of the list.
2423 		 */
2424 		if (selected_mechanism)
2425 			continue;
2426 
2427 		/*
2428 		 * Do we support this mechanism?
2429 		 */
2430 		if (strcmp(mechanism_buf, SCRAM_SHA_256_NAME) == 0)
2431 		{
2432 			/*
2433 			 * This is the password which we need to send to the PG backend
2434 			 * for authentication. It is stored in the file
2435 			 */
2436 			if (storedPassword == NULL || storedPassword[0] == '\0')
2437 			{
2438 				ereport(ERROR,
2439 						(errmsg("password not found")));
2440 			}
2441 
2442 			sasl_state = pg_fe_scram_init(username, storedPassword);
2443 			if (!sasl_state)
2444 				ereport(ERROR,
2445 						(errmsg("SASL authentication error\n")));
2446 			selected_mechanism = SCRAM_SHA_256_NAME;
2447 		}
2448 		mechanism_buf += strlen(mechanism_buf) + 1;
2449 	}
2450 
2451 	if (!selected_mechanism)
2452 	{
2453 		ereport(ERROR,
2454 				(errmsg("none of the server's SASL authentication mechanisms are supported\n")));
2455 	}
2456 
2457 	/* Get the mechanism-specific Initial Client Response, if any */
2458 	pg_fe_scram_exchange(sasl_state,
2459 						 NULL, -1,
2460 						 &initialresponse, &initialresponselen,
2461 						 &done, &success);
2462 
2463 	if (done && !success)
2464 		ereport(ERROR,
2465 				(errmsg("SASL authentication error")));
2466 
2467 	send_msg_len = strlen(selected_mechanism) + 1;
2468 	if (initialresponse)
2469 	{
2470 		send_msg_len += 4;
2471 		send_msg_len += initialresponselen;
2472 	}
2473 
2474 	size = htonl(send_msg_len + 4);
2475 
2476 	pool_write(backend, "p", 1);
2477 	pool_write(backend, &size, sizeof(size));
2478 	pool_write(backend, (void *) selected_mechanism, strlen(selected_mechanism) + 1);
2479 	if (initialresponse)
2480 	{
2481 		size = htonl(initialresponselen);
2482 		pool_write(backend, &size, sizeof(size));
2483 		pool_write(backend, initialresponse, initialresponselen);
2484 	}
2485 	pool_flush(backend);
2486 
2487 	if (initialresponse)
2488 		pfree(initialresponse);
2489 
2490 	return sasl_state;
2491 }
2492 
2493 /*
2494  * Exchange a message for SASL communication protocol with the backend.
2495  * This should be used after calling pg_SASL_init to set up the status of
2496  * the protocol.
2497  */
2498 static int
pg_SASL_continue(POOL_CONNECTION * backend,char * payload,int payloadlen,void * sasl_state,bool final)2499 pg_SASL_continue(POOL_CONNECTION * backend, char *payload, int payloadlen, void *sasl_state, bool final)
2500 {
2501 	char	   *output;
2502 	int			outputlen;
2503 	bool		done;
2504 	bool		success;
2505 	char	   *challenge;
2506 
2507 	/* Read the SASL challenge from the AuthenticationSASLContinue message. */
2508 	challenge = palloc(payloadlen + 1);
2509 	memcpy(challenge, payload, payloadlen);
2510 	challenge[payloadlen] = '\0';
2511 
2512 	/* For safety and convenience, ensure the buffer is NULL-terminated. */
2513 
2514 	pg_fe_scram_exchange(sasl_state,
2515 						 challenge, payloadlen,
2516 						 &output, &outputlen,
2517 						 &done, &success);
2518 	pfree(challenge);			/* don't need the input anymore */
2519 
2520 	if (final && !done)
2521 	{
2522 		if (outputlen != 0)
2523 			pfree(output);
2524 
2525 		ereport(ERROR,
2526 				(errmsg("AuthenticationSASLFinal received from server, but SASL authentication was not completed")));
2527 		return -1;
2528 	}
2529 	if (outputlen != 0)
2530 	{
2531 		/*
2532 		 * Send the SASL response to the server.
2533 		 */
2534 		int			size = htonl(outputlen + 4);
2535 
2536 		pool_write(backend, "p", 1);
2537 		pool_write(backend, &size, sizeof(size));
2538 		pool_write_and_flush(backend, output, outputlen);
2539 		pfree(output);
2540 
2541 		return 0;
2542 	}
2543 
2544 	if (done && !success)
2545 		return -1;
2546 
2547 	return 0;
2548 }
2549