3 * $Header: /cvsroot/pgpool/pgpool-II/pcp_child.c,v 1.11.2.1 2009/08/22 04:19:49 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 * pcp_child.c: PCP child process main
26 #include <sys/types.h>
27 #include <sys/socket.h>
28 #include <netinet/in.h>
30 #include <arpa/inet.h>
32 #ifdef HAVE_NETINET_TCP_H
33 #include <netinet/tcp.h>
35 #ifdef HAVE_SYS_SELECT_H
36 #include <sys/select.h>
53 #include "pcp/pcp_stream.h"
57 #define MAX_FILE_LINE_LEN 512
58 #define MAX_USER_PASSWD_LEN 128
60 extern void pcp_set_timeout(long sec);
61 static int exit_request; /* non 0 means SIGTERM(smart shutdown) or SIGINT(fast shutdown) has arrived */
63 static RETSIGTYPE die(int sig);
64 static PCP_CONNECTION *pcp_do_accept(int unix_fd, int inet_fd);
65 static void unset_nonblock(int fd);
66 static int user_authenticate(char *buf, char *passwd_file, char *salt, int salt_len);
67 static void pool_random_salt(char *md5Salt);
68 static RETSIGTYPE wakeup_handler(int sig);
69 static RETSIGTYPE reload_config_handler(int sig);
74 static volatile sig_atomic_t pcp_got_sighup = 0;
75 volatile sig_atomic_t pcp_wakeup_request = 0;
78 pcp_do_child(int unix_fd, int inet_fd, char *pcp_conf_file)
80 PCP_CONNECTION *frontend = NULL;
81 int authenticated = 0;
82 struct timeval uptime;
90 pool_debug("I am PCP %d", getpid());
92 /* Identify myself via ps */
93 init_ps_display("", "", "", "");
95 gettimeofday(&uptime, NULL);
96 srandom((unsigned int) (getpid() ^ uptime.tv_usec));
98 /* set pcp_read() timeout */
99 pcp_set_timeout(pool_config->pcp_timeout);
101 /* set up signal handlers */
102 signal(SIGTERM, die);
104 signal(SIGHUP, reload_config_handler);
105 signal(SIGQUIT, die);
106 signal(SIGCHLD, SIG_DFL);
107 signal(SIGUSR1, SIG_DFL);
108 signal(SIGUSR2, wakeup_handler);
109 signal(SIGPIPE, SIG_IGN);
110 signal(SIGALRM, SIG_IGN);
116 if (frontend == NULL)
118 frontend = pcp_do_accept(unix_fd, inet_fd);
119 if (frontend == NULL)
122 unset_nonblock(frontend->fd);
125 /* read a PCP packet */
126 if (pcp_read(frontend, &tos, 1))
128 if (errorcode == TIMEOUTERR)
130 pool_debug("pcp_child: pcp_read() has timed out");
132 pcp_close(frontend); frontend = NULL;
133 free(buf); buf = NULL;
136 pool_error("pcp_child: pcp_read() failed. reason: %s", strerror(errno));
139 if (pcp_read(frontend, &rsize, sizeof(int)))
141 if (errorcode == TIMEOUTERR)
143 pool_debug("pcp_child: pcp_read() has timed out");
145 pcp_close(frontend); frontend = NULL;
146 free(buf); buf = NULL;
149 pool_error("pcp_child: pcp_read() failed. reason: %s", strerror(errno));
153 rsize = ntohl(rsize);
154 if ((rsize - sizeof(int)) > 0)
156 buf = (char *)malloc(rsize - sizeof(int));
159 pool_error("pcp_child: malloc() failed. reason: %s", strerror(errno));
162 if (pcp_read(frontend, buf, rsize - sizeof(int)))
164 if (errorcode == TIMEOUTERR)
166 pool_debug("pcp_child: pcp_read() has timed out");
168 pcp_close(frontend); frontend = NULL;
169 free(buf); buf = NULL;
172 pool_error("pcp_child: pcp_read() failed. reason: %s", strerror(errno));
177 /* is this connection authenticated? if not disconnect immediately*/
178 if ((! authenticated) && (tos != 'R' && tos != 'M'))
180 pool_debug("pcp_child: connection not authorized");
185 pool_signal(SIGALRM, SIG_IGN);
189 /* process a request */
190 pool_debug("pcp_child: received PCP packet type of service '%c'", tos);
192 set_ps_display("PCP: processing a request", false);
196 case 'R': /* authentication */
202 authenticated = user_authenticate(buf, pcp_conf_file, salt, 4);
204 if (!random_salt || !authenticated)
206 char code[] = "AuthenticationFailed";
207 char mesg[] = "username and/or password do not match";
208 pcp_write(frontend, "r", 1);
209 wsize = htonl(sizeof(code) + sizeof(mesg) + sizeof(int));
210 pcp_write(frontend, &wsize, sizeof(int));
211 pcp_write(frontend, code, sizeof(code));
212 pcp_write(frontend, mesg, sizeof(mesg));
213 if (pcp_flush(frontend) < 0)
215 pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
219 pool_error("pcp_child: authentication failed");
226 char code[] = "AuthenticationOK";
227 pcp_write(frontend, "r", 1);
228 wsize = htonl(sizeof(code) + sizeof(int));
229 pcp_write(frontend, &wsize, sizeof(int));
230 pcp_write(frontend, code, sizeof(code));
231 if (pcp_flush(frontend) < 0)
233 pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
238 pool_debug("pcp_child: authentication OK");
243 case 'M': /* md5 salt */
247 pool_random_salt(salt);
250 pcp_write(frontend, "m", 1);
251 wsize = htonl(sizeof(int) + 4);
252 pcp_write(frontend, &wsize, sizeof(int));
253 pcp_write(frontend, salt, 4);
254 if (pcp_flush(frontend) < 0)
256 pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
260 pool_debug("pcp_child: salt sent to the client");
264 case 'L': /* node count */
267 int node_count = pool_get_node_count();
269 char code[] = "CommandComplete";
272 snprintf(mesg, sizeof(mesg), "%d", node_count);
274 pcp_write(frontend, "l", 1);
275 wsize = htonl(sizeof(code) +
278 pcp_write(frontend, &wsize, sizeof(int));
279 pcp_write(frontend, code, sizeof(code));
280 pcp_write(frontend, mesg, strlen(mesg)+1);
281 if (pcp_flush(frontend) < 0)
283 pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
287 pool_debug("pcp_child: %d node(s) found", node_count);
290 case 'I': /* node info */
295 BackendInfo *bi = NULL;
298 bi = pool_get_node_info(node_id);
301 char code[] = "Invalid Node ID";
303 pcp_write(frontend, "e", 1);
304 wsize = htonl(sizeof(code) + sizeof(int));
305 pcp_write(frontend, &wsize, sizeof(int));
306 pcp_write(frontend, code, sizeof(code));
307 if (pcp_flush(frontend) < 0)
309 pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
313 pool_debug("pcp_child: invalid node ID");
317 char code[] = "CommandComplete";
322 snprintf(port_str, sizeof(port_str), "%d", bi->backend_port);
323 snprintf(status, sizeof(status), "%d", bi->backend_status);
324 snprintf(weight_str, sizeof(weight_str), "%f", bi->backend_weight);
326 pcp_write(frontend, "i", 1);
327 wsize = htonl(sizeof(code) +
328 strlen(bi->backend_hostname)+1 +
331 strlen(weight_str)+1 +
333 pcp_write(frontend, &wsize, sizeof(int));
334 pcp_write(frontend, code, sizeof(code));
335 pcp_write(frontend, bi->backend_hostname, strlen(bi->backend_hostname)+1);
336 pcp_write(frontend, port_str, strlen(port_str)+1);
337 pcp_write(frontend, status, strlen(status)+1);
338 pcp_write(frontend, weight_str, strlen(weight_str)+1);
339 if (pcp_flush(frontend) < 0)
341 pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
345 pool_debug("pcp_child: retrieved node information from shared memory");
350 case 'N': /* process count */
354 char process_count_str[16];
355 int *process_list = NULL;
356 char code[] = "CommandComplete";
359 int total_port_len = 0;
361 process_list = pool_get_process_list(&process_count);
363 mesg = (char *)malloc(6*process_count); /* port# is at most 5 characters long (MAX:65535) */
366 pool_error("pcp_child: malloc() failed. reason: %s", strerror(errno));
370 snprintf(process_count_str, sizeof(process_count_str), "%d", process_count);
372 for (i = 0; i < process_count; i++)
375 snprintf(port, sizeof(port), "%d", process_list[i]);
376 snprintf(mesg+total_port_len, strlen(port)+1, "%s", port);
377 total_port_len += strlen(port)+1;
380 pcp_write(frontend, "n", 1);
381 wsize = htonl(sizeof(code) +
382 strlen(process_count_str)+1 +
385 pcp_write(frontend, &wsize, sizeof(int));
386 pcp_write(frontend, code, sizeof(code));
387 pcp_write(frontend, process_count_str, strlen(process_count_str)+1);
388 pcp_write(frontend, mesg, total_port_len);
389 if (pcp_flush(frontend) < 0)
391 pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
398 pool_debug("pcp_child: %d process(es) found", process_count);
402 case 'P': /* process info */
407 ProcessInfo *pi = NULL;
410 pi = pool_get_process_info(proc_id);
414 char code[] = "InvalidProcessID";
416 pcp_write(frontend, "e", 1);
417 wsize = htonl(sizeof(code) + sizeof(int));
418 pcp_write(frontend, &wsize, sizeof(int));
419 pcp_write(frontend, code, sizeof(code));
420 if (pcp_flush(frontend) < 0)
422 pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
426 pool_debug("pcp_child: invalid process ID");
430 /* First, send array size of connection_info */
431 char arr_code[] = "ArraySize";
432 char con_info_size[16];
433 /* Finally, indicate that all data is sent */
434 char fin_code[] = "CommandComplete";
436 snprintf(con_info_size, sizeof(con_info_size), "%d", pool_config->max_pool);
438 pcp_write(frontend, "p", 1);
439 wsize = htonl(sizeof(arr_code) +
440 strlen(con_info_size)+1 +
442 pcp_write(frontend, &wsize, sizeof(int));
443 pcp_write(frontend, arr_code, sizeof(arr_code));
444 pcp_write(frontend, con_info_size, strlen(con_info_size)+1);
445 if (pcp_flush(frontend) < 0)
447 pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
451 /* Second, send process information for all connection_info */
453 for (i = 0; i < pool_config->max_pool; i++)
455 char code[] = "ProcessInfo";
456 char proc_start_time[20];
457 char proc_create_time[20];
458 char majorversion[5];
459 char minorversion[5];
460 char pool_counter[16];
462 snprintf(proc_start_time, sizeof(proc_start_time), "%ld", pi->start_time);
463 snprintf(proc_create_time, sizeof(proc_create_time), "%ld", pi->connection_info[i].create_time);
464 snprintf(majorversion, sizeof(majorversion), "%d", pi->connection_info[i].major);
465 snprintf(minorversion, sizeof(minorversion), "%d", pi->connection_info[i].minor);
466 snprintf(pool_counter, sizeof(pool_counter), "%d", pi->connection_info[i].counter);
468 pcp_write(frontend, "p", 1);
469 wsize = htonl(sizeof(code) +
470 strlen(pi->connection_info[i].database)+1 +
471 strlen(pi->connection_info[i].user)+1 +
472 strlen(proc_start_time)+1 +
473 strlen(proc_create_time)+1 +
474 strlen(majorversion)+1 +
475 strlen(minorversion)+1 +
476 strlen(pool_counter)+1 +
478 pcp_write(frontend, &wsize, sizeof(int));
479 pcp_write(frontend, code, sizeof(code));
480 pcp_write(frontend, pi->connection_info[i].database, strlen(pi->connection_info[i].database)+1);
481 pcp_write(frontend, pi->connection_info[i].user, strlen(pi->connection_info[i].user)+1);
482 pcp_write(frontend, proc_start_time, strlen(proc_start_time)+1);
483 pcp_write(frontend, proc_create_time, strlen(proc_create_time)+1);
484 pcp_write(frontend, majorversion, strlen(majorversion)+1);
485 pcp_write(frontend, minorversion, strlen(minorversion)+1);
486 pcp_write(frontend, pool_counter, strlen(pool_counter)+1);
487 if (pcp_flush(frontend) < 0)
489 pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
494 pcp_write(frontend, "p", 1);
495 wsize = htonl(sizeof(fin_code) +
497 pcp_write(frontend, &wsize, sizeof(int));
498 pcp_write(frontend, fin_code, sizeof(fin_code));
499 if (pcp_flush(frontend) < 0)
501 pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
505 pool_debug("pcp_child: retrieved process information from shared memory");
510 case 'S': /* SystemDB info */
514 SystemDBInfo *si = NULL;
515 si = pool_get_system_db_info();
517 /* since PCP clients can only see SystemDBInfo, set system_db_status from the shared memory */
518 si->system_db_status = SYSDB_STATUS;
522 char code[] = "SystemDBNotDefined";
524 pcp_write(frontend, "e", 1);
525 wsize = htonl(sizeof(code) + sizeof(int));
526 pcp_write(frontend, &wsize, sizeof(int));
527 pcp_write(frontend, code, sizeof(code));
528 if (pcp_flush(frontend) < 0)
530 pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
536 /* first, send systemDB information */
537 char code[] = "SystemDBInfo";
540 char dist_def_num[16];
541 /* finally, indicate that all data is sent */
542 char fin_code[] = "CommandComplete";
544 snprintf(port, sizeof(port), "%d", si->port);
545 snprintf(status, sizeof(status), "%d", si->system_db_status);
546 snprintf(dist_def_num, sizeof(dist_def_num), "%d", si->dist_def_num);
548 pcp_write(frontend, "s", 1);
549 wsize = htonl(sizeof(code) +
550 strlen(si->hostname)+1 +
553 strlen(si->password)+1 +
554 strlen(si->schema_name)+1 +
555 strlen(si->database_name)+1 +
556 strlen(dist_def_num)+1 +
559 pcp_write(frontend, &wsize, sizeof(int));
560 pcp_write(frontend, code, sizeof(code));
561 pcp_write(frontend, si->hostname, strlen(si->hostname)+1);
562 pcp_write(frontend, port, strlen(port)+1);
563 pcp_write(frontend, si->user, strlen(si->user)+1);
564 pcp_write(frontend, si->password, strlen(si->password)+1);
565 pcp_write(frontend, si->schema_name, strlen(si->schema_name)+1);
566 pcp_write(frontend, si->database_name, strlen(si->database_name)+1);
567 pcp_write(frontend, dist_def_num, strlen(dist_def_num)+1);
568 pcp_write(frontend, status, strlen(status)+1);
569 if (pcp_flush(frontend) < 0)
571 pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
575 /* second, send DistDefInfo if any */
576 if (si->dist_def_num > 0)
578 char dist_code[] = "DistDefInfo";
580 int col_list_total_len;
581 int type_list_total_len;
582 char *col_list = NULL;
583 char *type_list = NULL;
585 int type_list_offset;
589 for (i = 0; i < si->dist_def_num; i++)
591 ddi = &si->dist_def_slot[i];
592 snprintf(col_num, sizeof(col_num), "%d", ddi->col_num);
594 col_list_total_len = type_list_total_len = 0;
595 for (j = 0; j < ddi->col_num; j++)
597 col_list_total_len += strlen(ddi->col_list[j]) + 1;
598 type_list_total_len += strlen(ddi->type_list[j]) + 1;
601 col_list = (char *)malloc(col_list_total_len);
602 type_list = (char *)malloc(type_list_total_len);
603 if (col_list == NULL || type_list == NULL)
605 pool_error("pcp_child: malloc() failed. reason: %s", strerror(errno));
609 col_list_offset = type_list_offset = 0;
610 for (j = 0; j < ddi->col_num; j++)
612 snprintf(col_list + col_list_offset, strlen(ddi->col_list[j])+1,
613 "%s", ddi->col_list[j]);
614 snprintf(type_list + type_list_offset, strlen(ddi->type_list[j])+1,
615 "%s", ddi->type_list[j]);
616 col_list_offset += strlen(ddi->col_list[j]) + 1;
617 type_list_offset += strlen(ddi->type_list[j]) + 1;
620 pcp_write(frontend, "s", 1);
621 wsize = htonl(sizeof(dist_code) +
622 strlen(ddi->dbname)+1 +
623 strlen(ddi->schema_name)+1 +
624 strlen(ddi->table_name)+1 +
625 strlen(ddi->dist_key_col_name)+1 +
628 type_list_total_len +
629 strlen(ddi->dist_def_func)+1 +
631 pcp_write(frontend, &wsize, sizeof(int));
632 pcp_write(frontend, dist_code, sizeof(dist_code));
633 pcp_write(frontend, ddi->dbname, strlen(ddi->dbname)+1);
634 pcp_write(frontend, ddi->schema_name, strlen(ddi->schema_name)+1);
635 pcp_write(frontend, ddi->table_name, strlen(ddi->table_name)+1);
636 pcp_write(frontend, ddi->dist_key_col_name, strlen(ddi->dist_key_col_name)+1);
637 pcp_write(frontend, col_num, strlen(col_num)+1);
638 pcp_write(frontend, col_list, col_list_total_len);
639 pcp_write(frontend, type_list, type_list_total_len);
640 pcp_write(frontend, ddi->dist_def_func, strlen(ddi->dist_def_func)+1);
641 if (pcp_flush(frontend) < 0)
643 pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
652 pcp_write(frontend, "s", 1);
653 wsize = htonl(sizeof(fin_code) +
655 pcp_write(frontend, &wsize, sizeof(int));
656 pcp_write(frontend, fin_code, sizeof(fin_code));
657 if (pcp_flush(frontend) < 0)
659 pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
663 pool_debug("pcp_child: retrieved SystemDB information from shared memory");
668 case 'D': /* detach node */
672 char code[] = "CommandComplete";
675 pool_debug("pcp_child: detaching Node ID %d", node_id);
676 notice_backend_error(node_id);
678 pcp_write(frontend, "d", 1);
679 wsize = htonl(sizeof(code) + sizeof(int));
680 pcp_write(frontend, &wsize, sizeof(int));
681 pcp_write(frontend, code, sizeof(code));
682 if (pcp_flush(frontend) < 0)
684 pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
690 case 'C': /* attach node */
694 char code[] = "CommandComplete";
697 pool_debug("pcp_child: attaching Node ID %d", node_id);
698 send_failback_request(node_id);
700 pcp_write(frontend, "c", 1);
701 wsize = htonl(sizeof(code) + sizeof(int));
702 pcp_write(frontend, &wsize, sizeof(int));
703 pcp_write(frontend, code, sizeof(code));
704 if (pcp_flush(frontend) < 0)
706 pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
715 pid_t ppid = getppid();
719 pool_debug("pcp_child: sending SIGTERM to the parent process(%d)", ppid);
722 else if (mode == 'f')
724 pool_debug("pcp_child: sending SIGINT to the parent process(%d)", ppid);
727 else if (mode == 'i')
729 pool_debug("pcp_child: sending SIGQUIT to the parent process(%d)", ppid);
734 pool_debug("pcp_child: invalid shutdown mode %c", mode);
740 case 'O': /* recovery request */
744 char code[] = "CommandComplete";
749 int len = strlen("recovery request is accepted only in replication mode. ") + 1;
750 pcp_write(frontend, "e", 1);
751 wsize = htonl(sizeof(int) + len);
752 pcp_write(frontend, &wsize, sizeof(int));
753 pcp_write(frontend, "recovery request is accepted only in replication mode. ", len);
757 pool_debug("pcp_child: start online recovery");
760 r = start_recovery(node_id);
763 if (r == 0) /* success */
765 pcp_write(frontend, "c", 1);
766 wsize = htonl(sizeof(code) + sizeof(int));
767 pcp_write(frontend, &wsize, sizeof(int));
768 pcp_write(frontend, code, sizeof(code));
772 int len = strlen("recovery failed") + 1;
773 pcp_write(frontend, "e", 1);
774 wsize = htonl(sizeof(int) + len);
775 pcp_write(frontend, &wsize, sizeof(int));
776 pcp_write(frontend, "recovery failed", len);
779 if (pcp_flush(frontend) < 0)
781 pool_error("pcp_child: pcp_flush() failed. reason: %s", strerror(errno));
788 pool_debug("pcp_child: stop online recovery");
791 case 'X': /* disconnect */
792 pool_debug("pcp_child: client disconnecting. close connection");
799 pool_error("pcp_child: unknown packet type %c received", tos);
806 /* seems ok. cancel idle check timer */
807 pool_signal(SIGALRM, SIG_IGN);
818 pool_debug("PCP child receives shutdown request signal %d", sig);
822 case SIGTERM: /* smart shutdown */
823 case SIGINT: /* fast shutdown */
824 case SIGQUIT: /* immediate shutdown */
831 /* send_frontend_exits(); */
837 wakeup_handler(int sig)
839 pcp_wakeup_request = 1;
842 static PCP_CONNECTION *
843 pcp_do_accept(int unix_fd, int inet_fd)
845 PCP_CONNECTION *pc = NULL;
850 struct sockaddr addr;
856 set_ps_display("PCP: wait for connection request", false);
859 FD_SET(unix_fd, &readmask);
861 FD_SET(inet_fd, &readmask);
863 fds = select(Max(unix_fd, inet_fd)+1, &readmask, NULL, NULL, NULL);
867 if (errno == EAGAIN || errno == EINTR)
870 pool_error("pcp_child: select() failed. reason: %s", strerror(errno));
874 if (FD_ISSET(unix_fd, &readmask))
879 if (FD_ISSET(inet_fd, &readmask))
885 addrlen = sizeof(addr);
887 afd = accept(fd, &addr, &addrlen);
891 * "Resource temporarily unavailable" (EAGAIN or EWOULDBLOCK)
892 * can be silently ignored.
894 if (errno != EAGAIN && errno != EWOULDBLOCK)
895 pool_error("pcp_child: accept() failed. reason: %s", strerror(errno));
901 pool_get_config(get_config_file_name(), RELOAD_CONFIG);
905 pool_debug("I am PCP %d accept fd %d", getpid(), afd);
911 if (setsockopt(afd, IPPROTO_TCP, TCP_NODELAY,
915 pool_error("pcp_child: setsockopt() failed: %s", strerror(errno));
919 if (setsockopt(afd, SOL_SOCKET, SO_KEEPALIVE,
923 pool_error("pcp_child: setsockopt() failed: %s", strerror(errno));
929 if ((pc = pcp_open(afd)) == NULL)
938 * unset non-block flag
941 unset_nonblock(int fd)
945 /* set fd to non-blocking */
946 var = fcntl(fd, F_GETFL, 0);
949 pool_error("pcp_child: fcntl failed. %s", strerror(errno));
952 if (fcntl(fd, F_SETFL, var & ~O_NONBLOCK) == -1)
954 pool_error("pcp_child: fcntl failed. %s", strerror(errno));
960 * see if received username and password matches with one in the file
963 user_authenticate(char *buf, char *passwd_file, char *salt, int salt_len)
966 char packet_username[MAX_USER_PASSWD_LEN+1];
967 char packet_password[MAX_USER_PASSWD_LEN+1];
968 char encrypt_buf[(MD5_PASSWD_LEN+1)*2];
969 char file_username[MAX_USER_PASSWD_LEN+1];
970 char file_password[MD5_PASSWD_LEN+1];
972 static char line[MAX_FILE_LINE_LEN+1];
975 /* strcpy() should be OK, but use strncpy() to be extra careful */
976 strncpy(packet_username, buf, MAX_USER_PASSWD_LEN);
977 index = (char *) memchr(buf, '\0', MAX_USER_PASSWD_LEN) + 1;
980 pool_debug("pcp_child: error while reading authentication packet");
983 strncpy(packet_password, index, MAX_USER_PASSWD_LEN);
985 fp = fopen(passwd_file, "r");
988 pool_error("pcp_child: could not open %s. reason: %s", passwd_file, strerror(errno));
992 /* for now, I don't care if duplicate username exists in the config file */
993 while ((fgets(line, MAX_FILE_LINE_LEN, fp)) != NULL)
1003 while (line[i] != ':')
1006 if (++i > MAX_USER_PASSWD_LEN)
1008 pool_error("pcp_child: user name in %s exceeds %d", passwd_file, MAX_USER_PASSWD_LEN);
1013 memcpy(file_username, line, len);
1014 file_username[len] = '\0';
1016 if (strcmp(packet_username, file_username) != 0)
1021 while (line[i] != '\n' && line[i] != '\0')
1024 if (++i > MAX_USER_PASSWD_LEN)
1026 pool_error("pcp_child: password in %s exceeds %d", passwd_file, MAX_USER_PASSWD_LEN);
1032 memcpy(file_password, line+strlen(file_username)+1, len);
1033 file_password[len] = '\0';
1035 pool_md5_encrypt(file_password, file_username, strlen(file_username),
1036 encrypt_buf + MD5_PASSWD_LEN + 1);
1037 encrypt_buf[(MD5_PASSWD_LEN+1)*2-1] = '\0';
1039 pool_md5_encrypt(encrypt_buf+MD5_PASSWD_LEN+1, salt, salt_len,
1041 encrypt_buf[MD5_PASSWD_LEN] = '\0';
1043 if (strcmp(encrypt_buf, packet_password) == 0)
1057 static void pool_random_salt(char *md5Salt)
1059 long rand = random();
1061 md5Salt[0] = (rand % 255) + 1;
1063 md5Salt[1] = (rand % 255) + 1;
1065 md5Salt[2] = (rand % 255) + 1;
1067 md5Salt[3] = (rand % 255) + 1;
1070 /* SIGHUP handler */
1071 static RETSIGTYPE reload_config_handler(int sig)