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