]> git.8kb.co.uk Git - pgpool-ii/pgpool-ii_2.2.5/blob - pool_auth.c
cd5bf4233e59a54e85229ec10b4a51da79b1f2c3
[pgpool-ii/pgpool-ii_2.2.5] / pool_auth.c
1 /* -*-pgsql-c-*- */
2 /*
3  * $Header: /cvsroot/pgpool/pgpool-II/pool_auth.c,v 1.15.2.2 2009/09/23 02:03:12 t-ishii Exp $
4  *
5  * pgpool: a language independent connection pool server for PostgreSQL
6  * written by Tatsuo Ishii
7  *
8  * Copyright (c) 2003-2008      PgPool Global Development Group
9  *
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.
20  *
21  * pool_auth.c: authenticaton stuff
22  *
23 */
24
25 #include "pool.h"
26
27 #ifdef HAVE_SYS_TYPES_H
28 #include <sys/types.h>
29 #endif
30 #ifdef HAVE_NETINET_IN_H
31 #include <netinet/in.h>
32 #endif
33 #ifdef HAVE_PARAM_H
34 #include <param.h>
35 #endif
36 #include <errno.h>
37 #include <string.h>
38
39 #define AUTHFAIL_ERRORCODE "28000"
40
41 static POOL_STATUS pool_send_auth_ok(POOL_CONNECTION *frontend, int pid, int key, int protoMajor);
42 static int do_clear_text_password(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reauth, int protoMajor);
43 static int do_crypt(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reauth, int protoMajor);
44 static int do_md5(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reauth, int protoMajor);
45
46 /*
47 * do authentication against backend. if success return 0 otherwise non 0.
48 */
49 int pool_do_auth(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *cp)
50 {
51         signed char kind;
52         int pid;
53         int key;
54         int protoMajor;
55         int length;
56         int authkind;
57         int i;
58         StartupPacket *sp;
59
60         protoMajor = MAJOR(cp);
61
62         kind = pool_read_kind(cp);
63         if (kind < 0)
64         {
65                 return -1;
66         }
67
68         /* error response? */
69         if (kind == 'E')
70         {
71                 /* we assume error response at this stage is likely version
72                  * protocol mismatch (v3 frontend vs. v2 backend). So we throw
73                  * a V2 protocol error response in the hope that v3 frontend
74                  * will negotiate again using v2 protocol.
75                  */
76                 pool_log("pool_do_auth: maybe protocol version mismatch (current version %d)", protoMajor);
77                 ErrorResponse(frontend, cp);
78                 return -1;
79         }
80         else if (kind != 'R')
81         {
82                 pool_error("pool_do_auth: expect \"R\" got %c", kind);
83                 return -1;
84         }
85
86         /*
87          * message length (v3 only)
88          */
89         if (protoMajor == PROTO_MAJOR_V3 && pool_read_message_length(cp) < 0)
90         {
91                 pool_error("Failed to read the authentication packet length. \
92 This is likely caused by the inconsistency of auth method among DB nodes. \
93 In this case you can check the previous error messages (hint: length field) \
94 from pool_read_message_length and recheck the pg_hba.conf settings.");
95                 return -1;
96         }
97
98         /*
99          * read authentication request kind.
100          *
101          * 0: authentication ok
102          * 1: kerberos v4
103          * 2: kerberos v5
104          * 3: clear text password
105          * 4: crypt password
106          * 5: md5 password
107          * 6: scm credential
108          *
109          * in replication mode, we only support  kind = 0, 3. this is because to "salt"
110          * cannot be replicated.
111          * in non replication mode, we support kind = 0, 3, 4, 5
112          */
113
114         authkind = pool_read_int(cp);
115         if (authkind < 0)
116         {
117                 pool_error("pool_do_auth: read auth kind failed");
118                 return -1;
119         }
120
121         authkind = ntohl(authkind);
122
123         /* trust? */
124         if (authkind == 0)
125         {
126                 int msglen;
127
128                 pool_write(frontend, "R", 1);
129
130                 if (protoMajor == PROTO_MAJOR_V3)
131                 {
132                         msglen = htonl(8);
133                         pool_write(frontend, &msglen, sizeof(msglen));
134                 }
135
136                 msglen = htonl(0);
137                 if (pool_write_and_flush(frontend, &msglen, sizeof(msglen)) < 0)
138                 {
139                         return -1;
140                 }
141                 MASTER(cp)->auth_kind = 0;
142         }
143
144         /* clear text password authentication? */
145         else if (authkind == 3)
146         {
147                 for (i=0;i<NUM_BACKENDS;i++)
148                 {
149                         if (!VALID_BACKEND(i))
150                                 continue;
151
152                         pool_debug("trying clear text password authentication");
153
154                         authkind = do_clear_text_password(CONNECTION(cp, i), frontend, 0, protoMajor);
155
156                         if (authkind < 0)
157                         {
158                                 pool_error("do_clear_text_password failed in slot %d", i);
159                                 return -1;
160                         }
161                 }
162         }
163
164         /* crypt authentication? */
165         else if (authkind == 4)
166         {
167                 for (i=0;i<NUM_BACKENDS;i++)
168                 {
169                         if (!VALID_BACKEND(i))
170                                 continue;
171
172                         pool_debug("trying crypt authentication");
173
174                         authkind = do_crypt(CONNECTION(cp, i), frontend, 0, protoMajor);
175
176                         if (authkind < 0)
177                         {
178                                 pool_error("do_crypt_text_password failed in slot %d", i);
179                                 return -1;
180                         }
181                 }
182         }
183
184         /* md5 authentication? */
185         else if (authkind == 5)
186         {
187                 if (!RAW_MODE && NUM_BACKENDS > 1)
188                 {
189                         pool_send_error_message(frontend, protoMajor, AUTHFAIL_ERRORCODE,
190                                                                         "MD5 authentication is unsupported in replication, master-slave and parallel modes.",
191                                                                         "",
192                                                                         "check pg_hba.conf",
193                                                                         __FILE__, __LINE__);
194                         return -1;
195                 }
196
197                 for (i=0;i<NUM_BACKENDS;i++)
198                 {
199                         if (!VALID_BACKEND(i))
200                                 continue;
201
202                         pool_debug("trying md5 authentication");
203
204                         authkind = do_md5(CONNECTION(cp, i), frontend, 0, protoMajor);
205
206                         if (authkind < 0)
207                         {
208                                 pool_error("do_md5failed in slot %d", i);
209                                 return -1;
210                         }
211                 }
212         }
213
214         else
215         {
216                 pool_error("pool_do_auth: unsupported auth kind received: %d", authkind);
217                 return -1;
218         }
219
220         if (authkind != 0)
221         {
222                 pool_error("pool_do_auth: backend does not return authentication ok");
223                 return -1;
224         }
225
226         /*
227          * authentication ok. now read pid and secret key from the
228          * backend
229          */
230         for (;;)
231         {
232                 kind = pool_read_kind(cp);
233                 if (kind < 0)
234                 {
235                         pool_error("pool_do_auth: failed to read kind before BackendKeyData");
236                         return -1;
237                 }
238                 else if (kind == 'K')
239                         break;
240
241                 if (protoMajor == PROTO_MAJOR_V3)
242                 {
243                         switch (kind)
244                         {
245                                 case 'S':
246                                         /* process parameter status */
247                                         if (ParameterStatus(frontend, cp) != POOL_CONTINUE)
248                                                 return -1;
249                                         pool_flush(frontend);
250                                         break;
251
252                                 case 'N':
253                                         /* process notice message */
254                                         if (SimpleForwardToFrontend(kind, frontend, cp))
255                                                 return -1;
256                                         pool_flush(frontend);
257                                         break;
258
259                                         /* process error message */
260                                 case 'E':
261                                         SimpleForwardToFrontend(kind, frontend, cp);
262                                         pool_flush(frontend);
263                                         return -1;
264                                         break;
265
266                                 default:
267                                         pool_error("pool_do_auth: unknown response \"%c\" before processing BackendKeyData",
268                                                            kind);
269                                         return -1;
270                                         break;
271                         }
272                 }
273                 else
274                 {
275                         /* V2 case */
276                         switch (kind)
277                         {
278                                 case 'N':
279                                         /* process notice message */
280                                         if (NoticeResponse(frontend, cp) != POOL_CONTINUE)
281                                                 return -1;
282                                         break;
283
284                                         /* process error message */
285                                 case 'E':
286                                         ErrorResponse(frontend, cp);
287                                         return -1;
288                                         break;
289
290                                 default:
291                                         pool_error("pool_do_auth: unknown response \"%c\" before processing V2 BackendKeyData",
292                                                            kind);
293                                         return -1;
294                                         break;
295                         }
296                 }
297         }
298
299         /*
300          * message length (V3 only)
301          */
302         if (protoMajor == PROTO_MAJOR_V3)
303         {
304                 if (kind != 'K')
305                 {
306                         pool_error("pool_do_auth: expect \"K\" got %c", kind);
307                         return -1;
308                 }
309
310                 if ((length = pool_read_message_length(cp)) != 12)
311                 {
312                         pool_error("pool_do_auth: invalid messages length(%d) for BackendKeyData", length);
313                         return -1;
314                 }
315         }
316
317         /*
318          * OK, read pid and secret key
319          */
320         for (i=0;i<NUM_BACKENDS;i++)
321         {
322                 if (VALID_BACKEND(i))
323                 {
324                         /* read pid */
325                         if (pool_read(CONNECTION(cp, i), &pid, sizeof(pid)) < 0)
326                         {
327                                 pool_error("pool_do_auth: failed to read pid in slot %d", i);
328                                 return -1;
329                         }
330
331                         CONNECTION_SLOT(cp, i)->pid = cp->info[i].pid = pid;
332
333                         /* read key */
334                         if (pool_read(CONNECTION(cp, i), &key, sizeof(key)) < 0)
335                         {
336                                 pool_error("pool_do_auth: failed to read key in slot %d", i);
337                                 return -1;
338                         }
339                         CONNECTION_SLOT(cp, i)->key = cp->info[i].key = key;
340
341                 }
342         }
343
344         sp = MASTER_CONNECTION(cp)->sp;
345         cp->info->major = sp->major;
346         cp->info->minor = sp->minor;
347         strncpy(cp->info->database, sp->database, sizeof(cp->info->database) - 1);
348         strncpy(cp->info->user, sp->user, sizeof(cp->info->user) - 1);
349         cp->info->counter = 1;
350
351         return pool_send_auth_ok(frontend, pid, key, protoMajor);
352 }
353
354 /*
355 * do re-authentication for reused connection. if success return 0 otherwise non 0.
356 */
357 int pool_do_reauth(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *cp)
358 {
359         int status;
360         int protoMajor;
361
362         protoMajor = MAJOR(cp);
363
364         switch(MASTER(cp)->auth_kind)
365         {
366                 case 0:
367                         /* trust */
368                         status = 0;
369                         break;
370
371                 case 3:
372                         /* clear text password */
373                         status = do_clear_text_password(MASTER(cp), frontend, 1, protoMajor);
374                         break;
375
376                 case 4:
377                         /* crypt password */
378                         status = do_crypt(MASTER(cp), frontend, 1, protoMajor);
379                         break;
380
381                 case 5:
382                         /* md5 password */
383                         status = do_md5(MASTER(cp), frontend, 1, protoMajor);
384                         break;
385
386                 default:
387                         pool_error("pool_do_reauth: unknown authentication request code %d",
388                                            MASTER(cp)->auth_kind);
389                         return -1;
390         }
391
392         if (status == 0)
393         {
394                 int msglen;
395
396                 pool_write(frontend, "R", 1);
397
398                 if (protoMajor == PROTO_MAJOR_V3)
399                 {
400                         msglen = htonl(8);
401                         pool_write(frontend, &msglen, sizeof(msglen));
402                 }
403
404                 msglen = htonl(0);
405                 if (pool_write_and_flush(frontend, &msglen, sizeof(msglen)) < 0)
406                 {
407                         return -1;
408                 }
409         }
410         else
411         {
412                 pool_debug("pool_do_reauth: authentication failed");
413                 return -1;
414         }
415
416         return (pool_send_auth_ok(frontend, MASTER_CONNECTION(cp)->pid, MASTER_CONNECTION(cp)->key, protoMajor) != POOL_CONTINUE);
417 }
418
419 /*
420 * send authentication ok to frontend. if success return 0 otherwise non 0.
421 */
422 static POOL_STATUS pool_send_auth_ok(POOL_CONNECTION *frontend, int pid, int key, int protoMajor)
423 {
424         char kind;
425         int len;
426
427 #ifdef NOT_USED
428         if (protoMajor == PROTO_MAJOR_V2)
429         {
430                 /* return "Authentication OK" to the frontend */
431                 kind = 'R';
432                 pool_write(frontend, &kind, 1);
433                 len = htonl(0);
434                 if (pool_write_and_flush(frontend, &len, sizeof(len)) < 0)
435                 {
436                         return -1;
437                 }
438         }
439 #endif
440
441         /* send backend key data */
442         kind = 'K';
443         pool_write(frontend, &kind, 1);
444         if (protoMajor == PROTO_MAJOR_V3)
445         {
446                 len = htonl(12);
447                 pool_write(frontend, &len, sizeof(len));
448         }
449
450         pool_debug("pool_send_auth_ok: send pid %d to frontend", ntohl(pid));
451
452         pool_write(frontend, &pid, sizeof(pid));
453         if (pool_write_and_flush(frontend, &key, sizeof(key)) < 0)
454         {
455                 return -1;
456         }
457
458         return 0;
459 }
460
461 /*
462  * perform clear text password authetication
463  */
464 static int do_clear_text_password(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reauth, int protoMajor)
465 {
466         static int size;
467         static char password[MAX_PASSWORD_SIZE];
468         char response;
469         int kind;
470         int len;
471
472         /* master? */
473         if (IS_MASTER_NODE_ID(backend->db_node_id))
474         {
475                 pool_write(frontend, "R", 1);   /* authenticaton */
476                 if (protoMajor == PROTO_MAJOR_V3)
477                 {
478                         len = htonl(8);
479                         pool_write(frontend, &len, sizeof(len));
480                 }
481                 kind = htonl(3);                /* clear text password authentication */
482                 pool_write_and_flush(frontend, &kind, sizeof(kind));    /* indicating clear text password authentication */
483
484                 /* read password packet */
485                 if (protoMajor == PROTO_MAJOR_V2)
486                 {
487                         if (pool_read(frontend, &size, sizeof(size)))
488                         {
489                                 pool_error("do_clear_text_password: failed to read password packet size");
490                                 return -1;
491                         }
492                 }
493                 else
494                 {
495                         char k;
496
497                         if (pool_read(frontend, &k, sizeof(k)))
498                         {
499                                 pool_error("do_clear_text_password: failed to read password packet \"p\"");
500                                 return -1;
501                         }
502                         if (k != 'p')
503                         {
504                                 pool_error("do_clear_text_password: password packet does not start with \"p\"");
505                                 return -1;
506                         }
507                         if (pool_read(frontend, &size, sizeof(size)))
508                         {
509                                 pool_error("do_clear_text_password: failed to read password packet size");
510                                 return -1;
511                         }
512                 }
513
514                 if ((ntohl(size) - 4) > sizeof(password))
515                 {
516                         pool_error("do_clear_text_password: password is too long (size: %d)", ntohl(size) - 4);
517                         return -1;
518                 }
519
520                 if (pool_read(frontend, password, ntohl(size) - 4))
521                 {
522                         pool_error("do_clear_text_password: failed to read password (size: %d)", ntohl(size) - 4);
523                         return -1;
524                 }
525         }
526
527         /* connection reusing? */
528         if (reauth)
529         {
530                 if ((ntohl(size) - 4) != backend->pwd_size)
531                 {
532                         pool_debug("do_clear_text_password; password size does not match in re-authetication");
533                         return -1;
534                 }
535
536                 if (memcmp(password, backend->password, backend->pwd_size) != 0)
537                 {
538                         pool_debug("do_clear_text_password; password does not match in re-authetication");
539                         return -1;
540                 }
541
542                 return 0;
543         }
544
545         /* send password packet to backend */
546         if (protoMajor == PROTO_MAJOR_V3)
547                 pool_write(backend, "p", 1);
548         pool_write(backend, &size, sizeof(size));
549         pool_write_and_flush(backend, password, ntohl(size) -4);
550         if (pool_read(backend, &response, sizeof(response)))
551         {
552                 pool_error("do_clear_text_password: failed to read authentication response");
553                 return -1;
554         }
555
556         if (response != 'R')
557         {
558                 pool_debug("do_clear_text_password: backend does not return R while processing clear text password authentication");
559                 return -1;
560         }
561
562         if (protoMajor == PROTO_MAJOR_V3)
563         {
564                 if (pool_read(backend, &len, sizeof(len)))
565                 {
566                         pool_error("do_clear_text_password: failed to read authentication packet size");
567                         return -1;
568                 }
569
570                 if (ntohl(len) != 8)
571                 {
572                         pool_error("do_clear_text_password: incorrect authentication packet size (%d)", ntohl(len));
573                         return -1;
574                 }
575         }
576
577         /* expect to read "Authentication OK" response. kind should be 0... */
578         if (pool_read(backend, &kind, sizeof(kind)))
579         {
580                 pool_debug("do_clear_text_password: failed to read Authentication OK response");
581                 return -1;
582         }
583
584         /* if authenticated, save info */
585         if (!reauth && kind == 0)
586         {
587                 if (IS_MASTER_NODE_ID(backend->db_node_id))
588                 {
589                         int msglen;
590
591                         pool_write(frontend, "R", 1);
592
593                         if (protoMajor == PROTO_MAJOR_V3)
594                         {
595                                 msglen = htonl(8);
596                                 pool_write(frontend, &msglen, sizeof(msglen));
597                         }
598
599                         msglen = htonl(0);
600                         if (pool_write_and_flush(frontend, &msglen, sizeof(msglen)) < 0)
601                         {
602                                 return -1;
603                         }
604                 }
605
606                 backend->auth_kind = 3;
607                 backend->pwd_size = ntohl(size) - 4;
608                 memcpy(backend->password, password, backend->pwd_size);
609         }
610         return kind;
611 }
612
613 /*
614  * perform crypt authetication
615  */
616 static int do_crypt(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reauth, int protoMajor)
617 {
618         char salt[2];
619         static int size;
620         static char password[MAX_PASSWORD_SIZE];
621         char response;
622         int kind;
623         int len;
624
625         if (!reauth)
626         {
627                 /* read salt */
628                 if (pool_read(backend, salt, sizeof(salt)))
629                 {
630                         pool_error("do_crypt: failed to read salt");
631                         return -1;
632                 }
633         }
634         else
635         {
636                 memcpy(salt, backend->salt, sizeof(salt));
637         }
638
639         /* master? */
640         if (IS_MASTER_NODE_ID(backend->db_node_id))
641         {
642                 pool_write(frontend, "R", 1);   /* authenticaton */
643                 if (protoMajor == PROTO_MAJOR_V3)
644                 {
645                         len = htonl(10);
646                         pool_write(frontend, &len, sizeof(len));
647                 }
648                 kind = htonl(4);                /* crypt authentication */
649                 pool_write(frontend, &kind, sizeof(kind));      /* indicating crypt authentication */
650                 pool_write_and_flush(frontend, salt, sizeof(salt));             /* salt */
651
652                 /* read password packet */
653                 if (protoMajor == PROTO_MAJOR_V2)
654                 {
655                         if (pool_read(frontend, &size, sizeof(size)))
656                         {
657                                 pool_error("do_crypt: failed to read password packet size");
658                                 return -1;
659                         }
660                 }
661                 else
662                 {
663                         char k;
664
665                         if (pool_read(frontend, &k, sizeof(k)))
666                         {
667                                 pool_error("do_crypt_password: failed to read password packet \"p\"");
668                                 return -1;
669                         }
670                         if (k != 'p')
671                         {
672                                 pool_error("do_crypt_password: password packet does not start with \"p\"");
673                                 return -1;
674                         }
675                         if (pool_read(frontend, &size, sizeof(size)))
676                         {
677                                 pool_error("do_crypt_password: failed to read password packet size");
678                                 return -1;
679                         }
680                 }
681
682                 if ((ntohl(size) - 4) > sizeof(password))
683                 {
684                         pool_error("do_crypt: password is too long(size: %d)", ntohl(size) - 4);
685                         return -1;
686                 }
687
688                 if (pool_read(frontend, password, ntohl(size) - 4))
689                 {
690                         pool_error("do_crypt: failed to read password (size: %d)", ntohl(size) - 4);
691                         return -1;
692                 }
693         }
694
695         /* connection reusing? */
696         if (reauth)
697         {
698                 pool_debug("size: %d saved_size: %d", (ntohl(size) - 4), backend->pwd_size);
699                 if ((ntohl(size) - 4) != backend->pwd_size)
700                 {
701                         pool_debug("do_crypt: password size does not match in re-authentication");
702                         return -1;
703                 }
704
705                 if (memcmp(password, backend->password, backend->pwd_size) != 0)
706                 {
707                         pool_debug("do_crypt: password does not match in re-authentication");
708                         return -1;
709                 }
710
711                 return 0;
712         }
713
714         /* send password packet to backend */
715         if (protoMajor == PROTO_MAJOR_V3)
716                 pool_write(backend, "p", 1);
717         pool_write(backend, &size, sizeof(size));
718         pool_write_and_flush(backend, password, ntohl(size) -4);
719         if (pool_read(backend, &response, sizeof(response)))
720         {
721                 pool_error("do_crypt: failed to read authentication response");
722                 return -1;
723         }
724
725         if (response != 'R')
726         {
727                 pool_debug("do_crypt: backend does not return R while processing crypt authentication(%02x) DB node id: %d", response, backend->db_node_id);
728                 return -1;
729         }
730
731         if (protoMajor == PROTO_MAJOR_V3)
732         {
733                 if (pool_read(backend, &len, sizeof(len)))
734                 {
735                         pool_error("do_clear_text_password: failed to read authentication packet size");
736                         return -1;
737                 }
738
739                 if (ntohl(len) != 8)
740                 {
741                         pool_error("do_clear_text_password: incorrect authentication packet size (%d)", ntohl(len));
742                         return -1;
743                 }
744         }
745
746         /* expect to read "Authentication OK" response. kind should be 0... */
747         if (pool_read(backend, &kind, sizeof(kind)))
748         {
749                 pool_debug("do_crypt: failed to read Authentication OK response");
750                 return -1;
751         }
752
753         /* if authenticated, save info */
754         if (!reauth && kind == 0)
755         {
756                 int msglen;
757
758                 pool_write(frontend, "R", 1);
759
760                 if (protoMajor == PROTO_MAJOR_V3)
761                 {
762                         msglen = htonl(8);
763                         pool_write(frontend, &msglen, sizeof(msglen));
764                 }
765
766                 msglen = htonl(0);
767                 if (pool_write_and_flush(frontend, &msglen, sizeof(msglen)) < 0)
768                 {
769                         return -1;
770                 }
771
772                 backend->auth_kind = 4;
773                 backend->pwd_size = ntohl(size) - 4;
774                 memcpy(backend->password, password, backend->pwd_size);
775                 memcpy(backend->salt, salt, sizeof(salt));
776         }
777         return kind;
778 }
779
780 /*
781  * perform MD5 authetication
782  */
783 static int do_md5(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reauth, int protoMajor)
784 {
785         char salt[4];
786         static int size;
787         static char password[MAX_PASSWORD_SIZE];
788         char response;
789         int kind;
790         int len;
791
792         if (!reauth)
793         {
794                 /* read salt */
795                 if (pool_read(backend, salt, sizeof(salt)))
796                 {
797                         pool_error("do_md5: failed to read salt");
798                         return -1;
799                 }
800                 pool_debug("DB node id: %d salt: %hhx%hhx%hhx%hhx", backend->db_node_id,
801                                    salt[0], salt[1], salt[2], salt[3]);
802         }
803         else
804         {
805                 memcpy(salt, backend->salt, sizeof(salt));
806         }
807
808         /* master? */
809         if (IS_MASTER_NODE_ID(backend->db_node_id))
810         {
811                 pool_write(frontend, "R", 1);   /* authenticaton */
812                 if (protoMajor == PROTO_MAJOR_V3)
813                 {
814                         len = htonl(12);
815                         pool_write(frontend, &len, sizeof(len));
816                 }
817                 kind = htonl(5);
818                 pool_write(frontend, &kind, sizeof(kind));      /* indicating MD5 */
819                 pool_write_and_flush(frontend, salt, sizeof(salt));             /* salt */
820
821                 /* read password packet */
822                 if (protoMajor == PROTO_MAJOR_V2)
823                 {
824                         if (pool_read(frontend, &size, sizeof(size)))
825                         {
826                                 pool_error("do_md5: failed to read password packet size");
827                                 return -1;
828                         }
829                 }
830                 else
831                 {
832                         char k;
833
834                         if (pool_read(frontend, &k, sizeof(k)))
835                         {
836                                 pool_error("do_md5_password: failed to read password packet \"p\"");
837                                 return -1;
838                         }
839                         if (k != 'p')
840                         {
841                                 pool_error("do_md5_password: password packet does not start with \"p\"");
842                                 return -1;
843                         }
844                         if (pool_read(frontend, &size, sizeof(size)))
845                         {
846                                 pool_error("do_md5_password: failed to read password packet size");
847                                 return -1;
848                         }
849                 }
850
851                 if ((ntohl(size) - 4) > sizeof(password))
852                 {
853                         pool_error("do_md5: password is too long(size: %d)", ntohl(size) - 4);
854                         return -1;
855                 }
856
857                 if (pool_read(frontend, password, ntohl(size) - 4))
858                 {
859                         pool_error("do_md5: failed to read password (size: %d)", ntohl(size) - 4);
860                         return -1;
861                 }
862         }
863
864         /* connection reusing? */
865         if (reauth)
866         {
867                 if ((ntohl(size) - 4) != backend->pwd_size)
868                 {
869                         pool_debug("do_md5; password size does not match in re-authentication");
870                         return -1;
871                 }
872
873                 if (memcmp(password, backend->password, backend->pwd_size) != 0)
874                 {
875                         pool_debug("do_md5; password does not match in re-authentication");
876                         return -1;
877                 }
878
879                 return 0;
880         }
881
882         /* send password packet to backend */
883         if (protoMajor == PROTO_MAJOR_V3)
884                 pool_write(backend, "p", 1);
885         pool_write(backend, &size, sizeof(size));
886         pool_write_and_flush(backend, password, ntohl(size) -4);
887         if (pool_read(backend, &response, sizeof(response)))
888         {
889                 pool_error("do_md5: failed to read authentication response");
890                 return -1;
891         }
892
893         if (response != 'R')
894         {
895                 pool_debug("do_md5: backend does not return R while processing MD5 authentication %c", response);
896                 return -1;
897         }
898
899         if (protoMajor == PROTO_MAJOR_V3)
900         {
901                 if (pool_read(backend, &len, sizeof(len)))
902                 {
903                         pool_error("do_md5: failed to read authentication packet size");
904                         return -1;
905                 }
906
907                 if (ntohl(len) != 8)
908                 {
909                         pool_error("do_clear_text_password: incorrect authentication packet size (%d)", ntohl(len));
910                         return -1;
911                 }
912         }
913
914         /* expect to read "Authentication OK" response. kind should be 0... */
915         if (pool_read(backend, &kind, sizeof(kind)))
916         {
917                 pool_debug("do_md5: failed to read Authentication OK response");
918                 return -1;
919         }
920
921         /* if authenticated, save info */
922         if (!reauth && kind == 0)
923         {
924                 int msglen;
925
926                 pool_write(frontend, "R", 1);
927
928                 if (protoMajor == PROTO_MAJOR_V3)
929                 {
930                         msglen = htonl(8);
931                         pool_write(frontend, &msglen, sizeof(msglen));
932                 }
933
934                 msglen = htonl(0);
935                 if (pool_write_and_flush(frontend, &msglen, sizeof(msglen)) < 0)
936                 {
937                         return -1;
938                 }
939
940                 backend->auth_kind = 5;
941                 backend->pwd_size = ntohl(size) - 4;
942                 memcpy(backend->password, password, backend->pwd_size);
943                 memcpy(backend->salt, salt, sizeof(salt));
944         }
945         return kind;
946 }
947
948 /*
949  * read message length (V3 only)
950  */
951 int pool_read_message_length(POOL_CONNECTION_POOL *cp)
952 {
953         int status;
954         int length, length0;
955         int i;
956
957         /* read message from master node */
958         status = pool_read(CONNECTION(cp, MASTER_NODE_ID), &length0, sizeof(length0));
959         if (status < 0)
960         {
961                 pool_error("pool_read_message_length: error while reading message length in slot %d", MASTER_NODE_ID);
962                 return -1;
963         }
964         length0 = ntohl(length0);
965         pool_debug("pool_read_message_length: slot: %d length: %d", MASTER_NODE_ID, length0);
966
967         for (i=0;i<NUM_BACKENDS;i++)
968         {
969                 if (!VALID_BACKEND(i) || IS_MASTER_NODE_ID(i))
970                 {
971                         continue;
972                 }
973
974                 status = pool_read(CONNECTION(cp, i), &length, sizeof(length));
975                 if (status < 0)
976                 {
977                         pool_error("pool_read_message_length: error while reading message length in slot %d", i);
978                         return -1;
979                 }
980
981                 length = ntohl(length);
982                 pool_debug("pool_read_message_length: slot: %d length: %d", i, length);
983
984                 if (length != length0)
985                 {
986                         pool_error("pool_read_message_length: message length (%d) in slot %d does not match with slot 0(%d)", length, i, length0);
987                         return -1;
988                 }
989         }
990
991         if (length0 < 0)
992         {
993                 pool_error("pool_read_message_length: invalid message length (%d)", length);
994                 return -1;
995         }
996
997         return length0;
998 }
999
1000 /*
1001  * read message length2 (V3 only)
1002  * unlike pool_read_message_length, this returns an array of message length.
1003  * The array is in the static storage, thus it will be destroyed by subsequent calls.
1004  */
1005 int *pool_read_message_length2(POOL_CONNECTION_POOL *cp)
1006 {
1007         int status;
1008         int length, length0;
1009         int i;
1010         static int length_array[MAX_CONNECTION_SLOTS];
1011
1012         /* read message from master node */
1013         status = pool_read(CONNECTION(cp, MASTER_NODE_ID), &length0, sizeof(length0));
1014         if (status < 0)
1015         {
1016                 pool_error("pool_read_message_length2: error while reading message length in slot %d", MASTER_NODE_ID);
1017                 return NULL;
1018         }
1019
1020         length0 = ntohl(length0);
1021         length_array[MASTER_NODE_ID] = length0;
1022         pool_debug("pool_read_message_length2: master slot: %d length: %d", MASTER_NODE_ID, length0);
1023         for (i=0;i<NUM_BACKENDS;i++)
1024         {
1025                 if (VALID_BACKEND(i) && !IS_MASTER_NODE_ID(i))
1026                 {
1027                         status = pool_read(CONNECTION(cp, i), &length, sizeof(length));
1028                         if (status < 0)
1029                         {
1030                                 pool_error("pool_read_message_length2: error while reading message length in slot %d", i);
1031                                 return NULL;
1032                         }
1033
1034                         length = ntohl(length);
1035                         pool_debug("pool_read_message_length2: master slot: %d length: %d", i, length);
1036
1037                         if (length != length0)
1038                         {
1039                                 pool_log("pool_read_message_length2: message length (%d) in slot %d does not match with slot 0(%d)", length, i, length0);
1040                         }
1041
1042                         if (length < 0)
1043                         {
1044                                 pool_error("pool_read_message_length2: invalid message length (%d)", length);
1045                                 return NULL;
1046                         }
1047
1048                         length_array[i] = length;
1049                 }
1050
1051         }
1052         return &length_array[0];
1053 }
1054
1055 signed char pool_read_kind(POOL_CONNECTION_POOL *cp)
1056 {
1057         int status;
1058         char kind0, kind;
1059         int i;
1060
1061         kind0 = 0;
1062
1063         for (i=0;i<NUM_BACKENDS;i++)
1064         {
1065                 if (!VALID_BACKEND(i))
1066                 {
1067                         continue;
1068                 }
1069
1070                 status = pool_read(CONNECTION(cp, i), &kind, sizeof(kind));
1071                 if (status < 0)
1072                 {
1073                         pool_error("pool_read_kind: error while reading message kind");
1074                         return -1;
1075                 }
1076
1077                 if (IS_MASTER_NODE_ID(i))
1078                 {
1079                         kind0 = kind;
1080                 }
1081                 else
1082                 {
1083                         if (kind != kind0)
1084                         {
1085                                 pool_error("pool_read_kind: kind does not match between master(%x) slot[%d] (%x)",
1086                                                    kind0, i, kind);
1087                                 return -1;
1088                         }
1089                 }
1090         }
1091
1092         return kind;
1093 }
1094
1095 int pool_read_int(POOL_CONNECTION_POOL *cp)
1096 {
1097         int status;
1098         int data0, data;
1099         int i;
1100
1101         data0 = 0;
1102
1103         for (i=0;i<NUM_BACKENDS;i++)
1104         {
1105                 if (!VALID_BACKEND(i))
1106                 {
1107                         continue;
1108                 }
1109
1110                 status = pool_read(CONNECTION(cp, i), &data, sizeof(data));
1111                 if (status < 0)
1112                 {
1113                         pool_error("pool_read_int: error while reading message data");
1114                         return -1;
1115                 }
1116
1117                 if (IS_MASTER_NODE_ID(i))
1118                 {
1119                         data0 = data;
1120                 }
1121                 else
1122                 {
1123                         if (data != data0)
1124                         {
1125                                 pool_error("pool_read_int: data does not match between between master(%x) slot[%d] (%x)",
1126                                                    data0, i, data);
1127                                 return -1;
1128                         }
1129                 }
1130         }
1131
1132         return data;
1133 }