3 * $Header: /cvsroot/pgpool/pgpool-II/pool_auth.c,v 1.15.2.2 2009/09/23 02:03:12 t-ishii Exp $
5 * pgpool: a language independent connection pool server for PostgreSQL
6 * written by Tatsuo Ishii
8 * Copyright (c) 2003-2008 PgPool Global Development Group
10 * Permission to use, copy, modify, and distribute this software and
11 * its documentation for any purpose and without fee is hereby
12 * granted, provided that the above copyright notice appear in all
13 * copies and that both that copyright notice and this permission
14 * notice appear in supporting documentation, and that the name of the
15 * author not be used in advertising or publicity pertaining to
16 * distribution of the software without specific, written prior
17 * permission. The author makes no representations about the
18 * suitability of this software for any purpose. It is provided "as
19 * is" without express or implied warranty.
21 * pool_auth.c: authenticaton stuff
27 #ifdef HAVE_SYS_TYPES_H
28 #include <sys/types.h>
30 #ifdef HAVE_NETINET_IN_H
31 #include <netinet/in.h>
40 #define AUTHFAIL_ERRORCODE "28000"
42 static POOL_STATUS pool_send_auth_ok(POOL_CONNECTION *frontend, int pid, int key, int protoMajor);
43 static int do_clear_text_password(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reauth, int protoMajor);
44 static void pool_send_auth_fail(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *cp);
45 static int do_crypt(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reauth, int protoMajor);
46 static int do_md5(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reauth, int protoMajor);
50 * do authentication against backend. if success return 0 otherwise non 0.
52 int pool_do_auth(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *cp)
63 protoMajor = MAJOR(cp);
65 kind = pool_read_kind(cp);
74 /* we assume error response at this stage is likely version
75 * protocol mismatch (v3 frontend vs. v2 backend). So we throw
76 * a V2 protocol error response in the hope that v3 frontend
77 * will negotiate again using v2 protocol.
79 pool_log("pool_do_auth: maybe protocol version mismatch (current version %d)", protoMajor);
80 ErrorResponse(frontend, cp);
85 pool_error("pool_do_auth: expect \"R\" got %c", kind);
90 * message length (v3 only)
92 if (protoMajor == PROTO_MAJOR_V3 && pool_read_message_length(cp) < 0)
94 pool_error("Failed to read the authentication packet length. \
95 This is likely caused by the inconsistency of auth method among DB nodes. \
96 In this case you can check the previous error messages (hint: length field) \
97 from pool_read_message_length and recheck the pg_hba.conf settings.");
102 * read authentication request kind.
104 * 0: authentication ok
107 * 3: clear text password
112 * in replication mode, we only support kind = 0, 3. this is because to "salt"
113 * cannot be replicated.
114 * in non replication mode, we support kind = 0, 3, 4, 5
117 authkind = pool_read_int(cp);
120 pool_error("pool_do_auth: read auth kind failed");
124 authkind = ntohl(authkind);
131 pool_write(frontend, "R", 1);
133 if (protoMajor == PROTO_MAJOR_V3)
136 pool_write(frontend, &msglen, sizeof(msglen));
140 if (pool_write_and_flush(frontend, &msglen, sizeof(msglen)) < 0)
142 pool_send_auth_fail(frontend, cp);
145 MASTER(cp)->auth_kind = 0;
148 /* clear text password authentication? */
149 else if (authkind == 3)
151 for (i=0;i<NUM_BACKENDS;i++)
153 if (!VALID_BACKEND(i))
156 pool_debug("trying clear text password authentication");
158 authkind = do_clear_text_password(CONNECTION(cp, i), frontend, 0, protoMajor);
162 pool_error("do_clear_text_password failed in slot %d", i);
163 pool_send_auth_fail(frontend, cp);
169 /* crypt authentication? */
170 else if (authkind == 4)
172 for (i=0;i<NUM_BACKENDS;i++)
174 if (!VALID_BACKEND(i))
177 pool_debug("trying crypt authentication");
179 authkind = do_crypt(CONNECTION(cp, i), frontend, 0, protoMajor);
183 pool_error("do_crypt_text_password failed in slot %d", i);
184 pool_send_auth_fail(frontend, cp);
190 /* md5 authentication? */
191 else if (authkind == 5)
193 if (!RAW_MODE && NUM_BACKENDS > 1)
195 pool_send_error_message(frontend, protoMajor, AUTHFAIL_ERRORCODE,
196 "MD5 authentication is unsupported in replication, master-slave and parallel modes.",
203 for (i=0;i<NUM_BACKENDS;i++)
205 if (!VALID_BACKEND(i))
208 pool_debug("trying md5 authentication");
210 authkind = do_md5(CONNECTION(cp, i), frontend, 0, protoMajor);
214 pool_error("do_md5failed in slot %d", i);
215 pool_send_auth_fail(frontend, cp);
223 pool_error("pool_do_auth: unsupported auth kind received: %d", authkind);
229 pool_error("pool_do_auth: backend does not return authentication ok");
234 * authentication ok. now read pid and secret key from the
239 kind = pool_read_kind(cp);
242 pool_error("pool_do_auth: failed to read kind before BackendKeyData");
245 else if (kind == 'K')
248 if (protoMajor == PROTO_MAJOR_V3)
253 /* process parameter status */
254 if (ParameterStatus(frontend, cp) != POOL_CONTINUE)
256 pool_flush(frontend);
260 /* process notice message */
261 if (SimpleForwardToFrontend(kind, frontend, cp))
263 pool_flush(frontend);
266 /* process error message */
268 SimpleForwardToFrontend(kind, frontend, cp);
269 pool_flush(frontend);
274 pool_error("pool_do_auth: unknown response \"%c\" before processing BackendKeyData",
286 /* process notice message */
287 if (NoticeResponse(frontend, cp) != POOL_CONTINUE)
291 /* process error message */
293 ErrorResponse(frontend, cp);
298 pool_error("pool_do_auth: unknown response \"%c\" before processing V2 BackendKeyData",
307 * message length (V3 only)
309 if (protoMajor == PROTO_MAJOR_V3)
313 pool_error("pool_do_auth: expect \"K\" got %c", kind);
317 if ((length = pool_read_message_length(cp)) != 12)
319 pool_error("pool_do_auth: invalid messages length(%d) for BackendKeyData", length);
325 * OK, read pid and secret key
327 for (i=0;i<NUM_BACKENDS;i++)
329 if (VALID_BACKEND(i))
332 if (pool_read(CONNECTION(cp, i), &pid, sizeof(pid)) < 0)
334 pool_error("pool_do_auth: failed to read pid in slot %d", i);
338 CONNECTION_SLOT(cp, i)->pid = cp->info[i].pid = pid;
341 if (pool_read(CONNECTION(cp, i), &key, sizeof(key)) < 0)
343 pool_error("pool_do_auth: failed to read key in slot %d", i);
346 CONNECTION_SLOT(cp, i)->key = cp->info[i].key = key;
351 sp = MASTER_CONNECTION(cp)->sp;
352 cp->info->major = sp->major;
353 cp->info->minor = sp->minor;
354 strncpy(cp->info->database, sp->database, sizeof(cp->info->database) - 1);
355 strncpy(cp->info->user, sp->user, sizeof(cp->info->user) - 1);
356 cp->info->counter = 1;
358 return pool_send_auth_ok(frontend, pid, key, protoMajor);
362 * do re-authentication for reused connection. if success return 0 otherwise non 0.
364 int pool_do_reauth(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *cp)
369 protoMajor = MAJOR(cp);
371 switch(MASTER(cp)->auth_kind)
379 /* clear text password */
380 status = do_clear_text_password(MASTER(cp), frontend, 1, protoMajor);
385 status = do_crypt(MASTER(cp), frontend, 1, protoMajor);
390 status = do_md5(MASTER(cp), frontend, 1, protoMajor);
394 pool_error("pool_do_reauth: unknown authentication request code %d",
395 MASTER(cp)->auth_kind);
403 pool_write(frontend, "R", 1);
405 if (protoMajor == PROTO_MAJOR_V3)
408 pool_write(frontend, &msglen, sizeof(msglen));
412 if (pool_write_and_flush(frontend, &msglen, sizeof(msglen)) < 0)
419 pool_debug("pool_do_reauth: authentication failed");
420 pool_send_auth_fail(frontend, cp);
424 return (pool_send_auth_ok(frontend, MASTER_CONNECTION(cp)->pid, MASTER_CONNECTION(cp)->key, protoMajor) != POOL_CONTINUE);
428 * send authentication failure message text to frontend
430 static void pool_send_auth_fail(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *cp)
436 bool send_error_to_frontend = true;
438 protoMajor = MAJOR(cp);
440 messagelen = strlen(MASTER_CONNECTION(cp)->sp->user) + 100;
441 if ((errmessage = (char *)malloc(messagelen+1)) == NULL)
443 pool_error("pool_send_auth_fail_failed: malloc failed: %s", strerror(errno));
447 snprintf(errmessage, messagelen, "password authentication failed for user \"%s\"",
448 MASTER_CONNECTION(cp)->sp->user);
449 if (send_error_to_frontend)
450 pool_send_fatal_message(frontend, protoMajor, "XX000", errmessage,
451 "", "", __FILE__, __LINE__);
456 * send authentication ok to frontend. if success return 0 otherwise non 0.
458 static POOL_STATUS pool_send_auth_ok(POOL_CONNECTION *frontend, int pid, int key, int protoMajor)
464 if (protoMajor == PROTO_MAJOR_V2)
466 /* return "Authentication OK" to the frontend */
468 pool_write(frontend, &kind, 1);
470 if (pool_write_and_flush(frontend, &len, sizeof(len)) < 0)
477 /* send backend key data */
479 pool_write(frontend, &kind, 1);
480 if (protoMajor == PROTO_MAJOR_V3)
483 pool_write(frontend, &len, sizeof(len));
486 pool_debug("pool_send_auth_ok: send pid %d to frontend", ntohl(pid));
488 pool_write(frontend, &pid, sizeof(pid));
489 if (pool_write_and_flush(frontend, &key, sizeof(key)) < 0)
498 * perform clear text password authetication
500 static int do_clear_text_password(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reauth, int protoMajor)
503 static char password[MAX_PASSWORD_SIZE];
509 if (IS_MASTER_NODE_ID(backend->db_node_id))
511 pool_write(frontend, "R", 1); /* authenticaton */
512 if (protoMajor == PROTO_MAJOR_V3)
515 pool_write(frontend, &len, sizeof(len));
517 kind = htonl(3); /* clear text password authentication */
518 pool_write_and_flush(frontend, &kind, sizeof(kind)); /* indicating clear text password authentication */
520 /* read password packet */
521 if (protoMajor == PROTO_MAJOR_V2)
523 if (pool_read(frontend, &size, sizeof(size)))
525 pool_error("do_clear_text_password: failed to read password packet size");
533 if (pool_read(frontend, &k, sizeof(k)))
535 pool_error("do_clear_text_password: failed to read password packet \"p\"");
540 pool_error("do_clear_text_password: password packet does not start with \"p\"");
543 if (pool_read(frontend, &size, sizeof(size)))
545 pool_error("do_clear_text_password: failed to read password packet size");
550 if ((ntohl(size) - 4) > sizeof(password))
552 pool_error("do_clear_text_password: password is too long (size: %d)", ntohl(size) - 4);
556 if (pool_read(frontend, password, ntohl(size) - 4))
558 pool_error("do_clear_text_password: failed to read password (size: %d)", ntohl(size) - 4);
563 /* connection reusing? */
566 if ((ntohl(size) - 4) != backend->pwd_size)
568 pool_debug("do_clear_text_password; password size does not match in re-authetication");
572 if (memcmp(password, backend->password, backend->pwd_size) != 0)
574 pool_debug("do_clear_text_password; password does not match in re-authetication");
581 /* send password packet to backend */
582 if (protoMajor == PROTO_MAJOR_V3)
583 pool_write(backend, "p", 1);
584 pool_write(backend, &size, sizeof(size));
585 pool_write_and_flush(backend, password, ntohl(size) -4);
586 if (pool_read(backend, &response, sizeof(response)))
588 pool_error("do_clear_text_password: failed to read authentication response");
594 pool_debug("do_clear_text_password: backend does not return R while processing clear text password authentication");
598 if (protoMajor == PROTO_MAJOR_V3)
600 if (pool_read(backend, &len, sizeof(len)))
602 pool_error("do_clear_text_password: failed to read authentication packet size");
608 pool_error("do_clear_text_password: incorrect authentication packet size (%d)", ntohl(len));
613 /* expect to read "Authentication OK" response. kind should be 0... */
614 if (pool_read(backend, &kind, sizeof(kind)))
616 pool_debug("do_clear_text_password: failed to read Authentication OK response");
620 /* if authenticated, save info */
621 if (!reauth && kind == 0)
623 if (IS_MASTER_NODE_ID(backend->db_node_id))
627 pool_write(frontend, "R", 1);
629 if (protoMajor == PROTO_MAJOR_V3)
632 pool_write(frontend, &msglen, sizeof(msglen));
636 if (pool_write_and_flush(frontend, &msglen, sizeof(msglen)) < 0)
642 backend->auth_kind = 3;
643 backend->pwd_size = ntohl(size) - 4;
644 memcpy(backend->password, password, backend->pwd_size);
650 * perform crypt authetication
652 static int do_crypt(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reauth, int protoMajor)
656 static char password[MAX_PASSWORD_SIZE];
664 if (pool_read(backend, salt, sizeof(salt)))
666 pool_error("do_crypt: failed to read salt");
672 memcpy(salt, backend->salt, sizeof(salt));
676 if (IS_MASTER_NODE_ID(backend->db_node_id))
678 pool_write(frontend, "R", 1); /* authenticaton */
679 if (protoMajor == PROTO_MAJOR_V3)
682 pool_write(frontend, &len, sizeof(len));
684 kind = htonl(4); /* crypt authentication */
685 pool_write(frontend, &kind, sizeof(kind)); /* indicating crypt authentication */
686 pool_write_and_flush(frontend, salt, sizeof(salt)); /* salt */
688 /* read password packet */
689 if (protoMajor == PROTO_MAJOR_V2)
691 if (pool_read(frontend, &size, sizeof(size)))
693 pool_error("do_crypt: failed to read password packet size");
701 if (pool_read(frontend, &k, sizeof(k)))
703 pool_error("do_crypt_password: failed to read password packet \"p\"");
708 pool_error("do_crypt_password: password packet does not start with \"p\"");
711 if (pool_read(frontend, &size, sizeof(size)))
713 pool_error("do_crypt_password: failed to read password packet size");
718 if ((ntohl(size) - 4) > sizeof(password))
720 pool_error("do_crypt: password is too long(size: %d)", ntohl(size) - 4);
724 if (pool_read(frontend, password, ntohl(size) - 4))
726 pool_error("do_crypt: failed to read password (size: %d)", ntohl(size) - 4);
731 /* connection reusing? */
734 pool_debug("size: %d saved_size: %d", (ntohl(size) - 4), backend->pwd_size);
735 if ((ntohl(size) - 4) != backend->pwd_size)
737 pool_debug("do_crypt: password size does not match in re-authentication");
741 if (memcmp(password, backend->password, backend->pwd_size) != 0)
743 pool_debug("do_crypt: password does not match in re-authentication");
750 /* send password packet to backend */
751 if (protoMajor == PROTO_MAJOR_V3)
752 pool_write(backend, "p", 1);
753 pool_write(backend, &size, sizeof(size));
754 pool_write_and_flush(backend, password, ntohl(size) -4);
755 if (pool_read(backend, &response, sizeof(response)))
757 pool_error("do_crypt: failed to read authentication response");
763 pool_debug("do_crypt: backend does not return R while processing crypt authentication(%02x) DB node id: %d", response, backend->db_node_id);
767 if (protoMajor == PROTO_MAJOR_V3)
769 if (pool_read(backend, &len, sizeof(len)))
771 pool_error("do_clear_text_password: failed to read authentication packet size");
777 pool_error("do_clear_text_password: incorrect authentication packet size (%d)", ntohl(len));
782 /* expect to read "Authentication OK" response. kind should be 0... */
783 if (pool_read(backend, &kind, sizeof(kind)))
785 pool_debug("do_crypt: failed to read Authentication OK response");
789 /* if authenticated, save info */
790 if (!reauth && kind == 0)
794 pool_write(frontend, "R", 1);
796 if (protoMajor == PROTO_MAJOR_V3)
799 pool_write(frontend, &msglen, sizeof(msglen));
803 if (pool_write_and_flush(frontend, &msglen, sizeof(msglen)) < 0)
808 backend->auth_kind = 4;
809 backend->pwd_size = ntohl(size) - 4;
810 memcpy(backend->password, password, backend->pwd_size);
811 memcpy(backend->salt, salt, sizeof(salt));
817 * perform MD5 authetication
819 static int do_md5(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reauth, int protoMajor)
823 static char password[MAX_PASSWORD_SIZE];
831 if (pool_read(backend, salt, sizeof(salt)))
833 pool_error("do_md5: failed to read salt");
836 pool_debug("DB node id: %d salt: %hhx%hhx%hhx%hhx", backend->db_node_id,
837 salt[0], salt[1], salt[2], salt[3]);
841 memcpy(salt, backend->salt, sizeof(salt));
845 if (IS_MASTER_NODE_ID(backend->db_node_id))
847 pool_write(frontend, "R", 1); /* authenticaton */
848 if (protoMajor == PROTO_MAJOR_V3)
851 pool_write(frontend, &len, sizeof(len));
854 pool_write(frontend, &kind, sizeof(kind)); /* indicating MD5 */
855 pool_write_and_flush(frontend, salt, sizeof(salt)); /* salt */
857 /* read password packet */
858 if (protoMajor == PROTO_MAJOR_V2)
860 if (pool_read(frontend, &size, sizeof(size)))
862 pool_error("do_md5: failed to read password packet size");
870 if (pool_read(frontend, &k, sizeof(k)))
872 pool_error("do_md5_password: failed to read password packet \"p\"");
877 pool_error("do_md5_password: password packet does not start with \"p\"");
880 if (pool_read(frontend, &size, sizeof(size)))
882 pool_error("do_md5_password: failed to read password packet size");
887 if ((ntohl(size) - 4) > sizeof(password))
889 pool_error("do_md5: password is too long(size: %d)", ntohl(size) - 4);
893 if (pool_read(frontend, password, ntohl(size) - 4))
895 pool_error("do_md5: failed to read password (size: %d)", ntohl(size) - 4);
900 /* connection reusing? */
903 if ((ntohl(size) - 4) != backend->pwd_size)
905 pool_debug("do_md5; password size does not match in re-authentication");
909 if (memcmp(password, backend->password, backend->pwd_size) != 0)
911 pool_debug("do_md5; password does not match in re-authentication");
918 /* send password packet to backend */
919 if (protoMajor == PROTO_MAJOR_V3)
920 pool_write(backend, "p", 1);
921 pool_write(backend, &size, sizeof(size));
922 pool_write_and_flush(backend, password, ntohl(size) -4);
923 if (pool_read(backend, &response, sizeof(response)))
925 pool_error("do_md5: failed to read authentication response");
931 pool_debug("do_md5: backend does not return R while processing MD5 authentication %c", response);
935 if (protoMajor == PROTO_MAJOR_V3)
937 if (pool_read(backend, &len, sizeof(len)))
939 pool_error("do_md5: failed to read authentication packet size");
945 pool_error("do_clear_text_password: incorrect authentication packet size (%d)", ntohl(len));
950 /* expect to read "Authentication OK" response. kind should be 0... */
951 if (pool_read(backend, &kind, sizeof(kind)))
953 pool_debug("do_md5: failed to read Authentication OK response");
957 /* if authenticated, save info */
958 if (!reauth && kind == 0)
962 pool_write(frontend, "R", 1);
964 if (protoMajor == PROTO_MAJOR_V3)
967 pool_write(frontend, &msglen, sizeof(msglen));
971 if (pool_write_and_flush(frontend, &msglen, sizeof(msglen)) < 0)
976 backend->auth_kind = 5;
977 backend->pwd_size = ntohl(size) - 4;
978 memcpy(backend->password, password, backend->pwd_size);
979 memcpy(backend->salt, salt, sizeof(salt));
985 * read message length (V3 only)
987 int pool_read_message_length(POOL_CONNECTION_POOL *cp)
993 /* read message from master node */
994 status = pool_read(CONNECTION(cp, MASTER_NODE_ID), &length0, sizeof(length0));
997 pool_error("pool_read_message_length: error while reading message length in slot %d", MASTER_NODE_ID);
1000 length0 = ntohl(length0);
1001 pool_debug("pool_read_message_length: slot: %d length: %d", MASTER_NODE_ID, length0);
1003 for (i=0;i<NUM_BACKENDS;i++)
1005 if (!VALID_BACKEND(i) || IS_MASTER_NODE_ID(i))
1010 status = pool_read(CONNECTION(cp, i), &length, sizeof(length));
1013 pool_error("pool_read_message_length: error while reading message length in slot %d", i);
1017 length = ntohl(length);
1018 pool_debug("pool_read_message_length: slot: %d length: %d", i, length);
1020 if (length != length0)
1022 pool_error("pool_read_message_length: message length (%d) in slot %d does not match with slot 0(%d)", length, i, length0);
1029 pool_error("pool_read_message_length: invalid message length (%d)", length);
1037 * read message length2 (V3 only)
1038 * unlike pool_read_message_length, this returns an array of message length.
1039 * The array is in the static storage, thus it will be destroyed by subsequent calls.
1041 int *pool_read_message_length2(POOL_CONNECTION_POOL *cp)
1044 int length, length0;
1046 static int length_array[MAX_CONNECTION_SLOTS];
1048 /* read message from master node */
1049 status = pool_read(CONNECTION(cp, MASTER_NODE_ID), &length0, sizeof(length0));
1052 pool_error("pool_read_message_length2: error while reading message length in slot %d", MASTER_NODE_ID);
1056 length0 = ntohl(length0);
1057 length_array[MASTER_NODE_ID] = length0;
1058 pool_debug("pool_read_message_length2: master slot: %d length: %d", MASTER_NODE_ID, length0);
1059 for (i=0;i<NUM_BACKENDS;i++)
1061 if (VALID_BACKEND(i) && !IS_MASTER_NODE_ID(i))
1063 status = pool_read(CONNECTION(cp, i), &length, sizeof(length));
1066 pool_error("pool_read_message_length2: error while reading message length in slot %d", i);
1070 length = ntohl(length);
1071 pool_debug("pool_read_message_length2: master slot: %d length: %d", i, length);
1073 if (length != length0)
1075 pool_log("pool_read_message_length2: message length (%d) in slot %d does not match with slot 0(%d)", length, i, length0);
1080 pool_error("pool_read_message_length2: invalid message length (%d)", length);
1084 length_array[i] = length;
1088 return &length_array[0];
1091 signed char pool_read_kind(POOL_CONNECTION_POOL *cp)
1099 for (i=0;i<NUM_BACKENDS;i++)
1101 if (!VALID_BACKEND(i))
1106 status = pool_read(CONNECTION(cp, i), &kind, sizeof(kind));
1109 pool_error("pool_read_kind: error while reading message kind");
1113 if (IS_MASTER_NODE_ID(i))
1121 pool_error("pool_read_kind: kind does not match between master(%x) slot[%d] (%x)",
1131 int pool_read_int(POOL_CONNECTION_POOL *cp)
1139 for (i=0;i<NUM_BACKENDS;i++)
1141 if (!VALID_BACKEND(i))
1146 status = pool_read(CONNECTION(cp, i), &data, sizeof(data));
1149 pool_error("pool_read_int: error while reading message data");
1153 if (IS_MASTER_NODE_ID(i))
1161 pool_error("pool_read_int: data does not match between between master(%x) slot[%d] (%x)",