pgpool2.git / summary / log / commit / refs
commit 49ab80f15eb435d5df88633e6dd9d2c40c6d7c4d
Author: Tatsuo Ishii <ishii at sraoss.co.jp>
Date: Sun Jun 27 13:02:57 2010 +0000
Implement md5 authentication using pool_passwd.
Still need to rewrite documents and pgpool.config samples.
Makefile.am | 16 ++-
Makefile.in | 34 ++++--
main.c | 18 ++-
md5.c | 41 ++++++-
pcp/md5.c | 41 ++++++-
pcp_child.c | 17 ---
pg_md5.c | 80 ++++++++++++-
pool.h | 6 +
pool_auth.c | 353 +++++++++++++++++++++++++++++++++++++++++----------------
pool_config.c | 37 ++++++
pool_config.h | 1 +
pool_config.l | 37 ++++++
pool_globals.c | 27 +++++
pool_hba.c | 31 ++++-
pool_type.h | 4 +-
15 files changed, 601 insertions(+), 142 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 5592ed02b..a377e272f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -16,10 +16,20 @@ pgpool_SOURCES = pool.h pool_type.h version.h pgpool.conf.sample \
pool_lobj.c pool_lobj.h \
pool_process_context.c pool_process_context.h \
pool_session_context.c pool_session_context.h \
- pool_query_context.c pool_query_context.h \
- pool_worker_child.c
+ pool_query_context.c pool_query_context.h \
+ pool_worker_child.c \
+ pool_passwd.c pool_passwd.h \
+ pool_globals.c
-pg_md5_SOURCES = pg_md5.c md5.c md5.h
+pgpool_DEFS = -DPGPOOL_MAIN
+
+pg_md5_SOURCES = pg_md5.c md5.c md5.h \
+ pool.h \
+ pool_config.l pool_config.h \
+ pool_error.c \
+ pool_signal.h pool_signal.c \
+ pool_passwd.c pool_passwd.h \
+ pool_globals.c
DEFS = @DEFS@ \
-DDEFAULT_CONFIGDIR=\"$(sysconfdir)\"
diff --git a/Makefile.in b/Makefile.in
index 0fa9cdc0d..1b39e4f45 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -60,7 +60,10 @@ am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man8dir)" \
"$(DESTDIR)$(pkgdatadir)" "$(DESTDIR)$(sysconfdir)"
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
PROGRAMS = $(bin_PROGRAMS)
-am_pg_md5_OBJECTS = pg_md5.$(OBJEXT) md5.$(OBJEXT)
+am_pg_md5_OBJECTS = pg_md5.$(OBJEXT) md5.$(OBJEXT) \
+ pool_config.$(OBJEXT) pool_error.$(OBJEXT) \
+ pool_signal.$(OBJEXT) pool_passwd.$(OBJEXT) \
+ pool_globals.$(OBJEXT)
pg_md5_OBJECTS = $(am_pg_md5_OBJECTS)
pg_md5_LDADD = $(LDADD)
am_pgpool_OBJECTS = main.$(OBJEXT) child.$(OBJEXT) pool_auth.$(OBJEXT) \
@@ -77,7 +80,8 @@ am_pgpool_OBJECTS = main.$(OBJEXT) child.$(OBJEXT) pool_auth.$(OBJEXT) \
pool_timestamp.$(OBJEXT) pool_proto2.$(OBJEXT) \
pool_proto_modules.$(OBJEXT) pool_lobj.$(OBJEXT) \
pool_process_context.$(OBJEXT) pool_session_context.$(OBJEXT) \
- pool_query_context.$(OBJEXT) pool_worker_child.$(OBJEXT)
+ pool_query_context.$(OBJEXT) pool_worker_child.$(OBJEXT) \
+ pool_passwd.$(OBJEXT) pool_globals.$(OBJEXT)
pgpool_OBJECTS = $(am_pgpool_OBJECTS)
pgpool_DEPENDENCIES = parser/libsql-parser.a pcp/libpcp.la \
parser/nodes.o
@@ -94,6 +98,7 @@ LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
LEXCOMPILE = $(LEX) $(LFLAGS) $(AM_LFLAGS)
LTLEXCOMPILE = $(LIBTOOL) --mode=compile $(LEX) $(LFLAGS) $(AM_LFLAGS)
+YLWRAP = $(top_srcdir)/ylwrap
SOURCES = $(pg_md5_SOURCES) $(pgpool_SOURCES)
DIST_SOURCES = $(pg_md5_SOURCES) $(pgpool_SOURCES)
RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
@@ -251,12 +256,23 @@ pgpool_SOURCES = pool.h pool_type.h version.h pgpool.conf.sample \
pool_lobj.c pool_lobj.h \
pool_process_context.c pool_process_context.h \
pool_session_context.c pool_session_context.h \
-< pool_query_context.c pool_query_context.h \
- pool_worker_child.c
+ pool_query_context.c pool_query_context.h \
+ pool_worker_child.c \
+ pool_passwd.c pool_passwd.h \
+ pool_globals.c
+
+pgpool_DEFS = -DPGPOOL_MAIN
+pg_md5_SOURCES = pg_md5.c md5.c md5.h \
+ pool.h \
+ pool_config.l pool_config.h \
+ pool_error.c \
+ pool_signal.h pool_signal.c \
+ pool_passwd.c pool_passwd.h \
+ pool_globals.c
-pg_md5_SOURCES = pg_md5.c md5.c md5.h
sysconf_DATA = pgpool.conf.sample pcp.conf.sample pool_hba.conf.sample \
- pgpool.conf.sample-replication pgpool.conf.sample-master-slave
+ pgpool.conf.sample-replication pgpool.conf.sample-master-slave \
+ pgpool.conf.sample-stream
pkgdata_DATA = sql/system_db.sql sample/pgpool.pam
AM_CPPFLAGS = -D_GNU_SOURCE -I @PGSQL_INCLUDE_DIR@
@@ -409,10 +425,12 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool_config.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool_connection_pool.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool_error.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool_globals.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool_hba.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool_ip.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool_lobj.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool_params.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool_passwd.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool_path.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool_process_context.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool_process_query.Po@am__quote@
@@ -459,9 +477,7 @@ distclean-compile:
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
.l.c:
- $(LEXCOMPILE) $<
- sed '/^#/ s|$(LEX_OUTPUT_ROOT)\.c|$@|' $(LEX_OUTPUT_ROOT).c >$@
- rm -f $(LEX_OUTPUT_ROOT).c
+ $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE)
mostlyclean-libtool:
-rm -f *.lo
diff --git a/main.c b/main.c
index 7d2452c48..81e97cb49 100644
--- a/main.c
+++ b/main.c
@@ -49,10 +49,12 @@
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif
+#include <libgen.h>
#include "version.h"
#include "parser/pool_memory.h"
#include "parser/pool_string.h"
+#include "pool_passwd.h"
/*
* Process pending signal actions.
@@ -141,9 +143,6 @@ static int switching = 0; /* non 0 if I'm fail overing or degenerating */
static int clear_cache = 0; /* non 0 if clear chache option (-c) is given */
static int not_detach = 0; /* non 0 if non detach option (-n) is given */
-int debug = 0; /* non 0 if debug option is given (-d). pcp only */
-
-pid_t mypid; /* pgpool parent process id */
long int weight_master; /* normalized weight of master (0-RAND_MAX range) */
@@ -161,7 +160,6 @@ static volatile sig_atomic_t wakeup_request = 0;
static int pipe_fds[2]; /* for delivering signals */
int my_proc_id;
-bool run_as_pcp_child;
static BackendStatusRecord backend_rec; /* Backend status record */
@@ -304,6 +302,18 @@ int main(int argc, char **argv)
exit(1);
}
+ /*
+ * Locate pool_passwd
+ */
+ if (strcmp("", pool_config->pool_passwd))
+ {
+ char pool_passwd[POOLMAXPATHLEN+1];
+
+ snprintf(pool_passwd, sizeof(pool_passwd), "%s/%s",
+ dirname(conf_file), pool_config->pool_passwd);
+ pool_init_pool_passwd(pool_passwd);
+ }
+
/*
* Override debug level
*/
diff --git a/md5.c b/md5.c
index ee887aa46..827e74cca 100644
--- a/md5.c
+++ b/md5.c
@@ -24,11 +24,13 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
-
+#include "pool.h"
#include "md5.h"
+#ifdef NOT_USED
typedef unsigned char uint8; /* == 8 bits */
typedef unsigned int uint32; /* == 32 bits */
+#endif
#define S11 7
#define S12 12
@@ -403,3 +405,40 @@ pool_md5_encrypt(const char *passwd, const char *salt, size_t salt_len,
return ret;
}
+
+/*
+ * Computes MD5 checksum of "passwd" (a null-terminated string) followed
+ * by "salt" (which need not be null-terminated).
+ *
+ * Output format is "md5" followed by a 32-hex-digit MD5 checksum.
+ * Hence, the output buffer "buf" must be at least 36 bytes long.
+ *
+ * Returns TRUE if okay, FALSE on error (out of memory).
+ */
+bool
+pg_md5_encrypt(const char *passwd, const char *salt, size_t salt_len,
+ char *buf)
+{
+ size_t passwd_len = strlen(passwd);
+
+ /* +1 here is just to avoid risk of unportable malloc(0) */
+ char *crypt_buf = malloc(passwd_len + salt_len + 1);
+ bool ret;
+
+ if (!crypt_buf)
+ return false;
+
+ /*
+ * Place salt at the end because it may be known by users trying to crack
+ * the MD5 output.
+ */
+ memcpy(crypt_buf, passwd, passwd_len);
+ memcpy(crypt_buf + passwd_len, salt, salt_len);
+
+ strcpy(buf, "md5");
+ ret = pool_md5_hash(crypt_buf, passwd_len + salt_len, buf + 3);
+
+ free(crypt_buf);
+
+ return ret;
+}
diff --git a/pcp/md5.c b/pcp/md5.c
index ee887aa46..827e74cca 100644
--- a/pcp/md5.c
+++ b/pcp/md5.c
@@ -24,11 +24,13 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
-
+#include "pool.h"
#include "md5.h"
+#ifdef NOT_USED
typedef unsigned char uint8; /* == 8 bits */
typedef unsigned int uint32; /* == 32 bits */
+#endif
#define S11 7
#define S12 12
@@ -403,3 +405,40 @@ pool_md5_encrypt(const char *passwd, const char *salt, size_t salt_len,
return ret;
}
+
+/*
+ * Computes MD5 checksum of "passwd" (a null-terminated string) followed
+ * by "salt" (which need not be null-terminated).
+ *
+ * Output format is "md5" followed by a 32-hex-digit MD5 checksum.
+ * Hence, the output buffer "buf" must be at least 36 bytes long.
+ *
+ * Returns TRUE if okay, FALSE on error (out of memory).
+ */
+bool
+pg_md5_encrypt(const char *passwd, const char *salt, size_t salt_len,
+ char *buf)
+{
+ size_t passwd_len = strlen(passwd);
+
+ /* +1 here is just to avoid risk of unportable malloc(0) */
+ char *crypt_buf = malloc(passwd_len + salt_len + 1);
+ bool ret;
+
+ if (!crypt_buf)
+ return false;
+
+ /*
+ * Place salt at the end because it may be known by users trying to crack
+ * the MD5 output.
+ */
+ memcpy(crypt_buf, passwd, passwd_len);
+ memcpy(crypt_buf + passwd_len, salt, salt_len);
+
+ strcpy(buf, "md5");
+ ret = pool_md5_hash(crypt_buf, passwd_len + salt_len, buf + 3);
+
+ free(crypt_buf);
+
+ return ret;
+}
diff --git a/pcp_child.c b/pcp_child.c
index 3d8f23ac9..508931e5f 100644
--- a/pcp_child.c
+++ b/pcp_child.c
@@ -65,7 +65,6 @@ static RETSIGTYPE die(int sig);
static PCP_CONNECTION *pcp_do_accept(int unix_fd, int inet_fd);
static void unset_nonblock(int fd);
static int user_authenticate(char *buf, char *passwd_file, char *salt, int salt_len);
-static void pool_random_salt(char *md5Salt);
static RETSIGTYPE wakeup_handler(int sig);
static RETSIGTYPE reload_config_handler(int sig);
@@ -1052,22 +1051,6 @@ user_authenticate(char *buf, char *passwd_file, char *salt, int salt_len)
return 0;
}
-/*
- * pool_random_salt
- */
-static void pool_random_salt(char *md5Salt)
-{
- long rand = random();
-
- md5Salt[0] = (rand % 255) + 1;
- rand = random();
- md5Salt[1] = (rand % 255) + 1;
- rand = random();
- md5Salt[2] = (rand % 255) + 1;
- rand = random();
- md5Salt[3] = (rand % 255) + 1;
-}
-
/* SIGHUP handler */
static RETSIGTYPE reload_config_handler(int sig)
{
diff --git a/pg_md5.c b/pg_md5.c
index b71f25713..3e88aab44 100644
--- a/pg_md5.c
+++ b/pg_md5.c
@@ -23,6 +23,7 @@
*/
#include "pool.h"
#include "pool_config.h"
+#include "pool_passwd.h"
#include "md5.h"
#include <stdio.h>
@@ -34,6 +35,8 @@
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif
+#include <pwd.h>
+#include <libgen.h>
/* Maximum number of characters allowed for input. */
#define MAX_INPUT_SIZE 32
@@ -46,6 +49,8 @@ main(int argc, char *argv[])
{
#define PRINT_USAGE(exit_code) print_usage(argv[0], exit_code)
+ char conf_file[POOLMAXPATHLEN+1];
+ char pool_passwd[POOLMAXPATHLEN+1];
int opt;
int optindex;
bool md5auth = false;
@@ -55,10 +60,14 @@ main(int argc, char *argv[])
{"help", no_argument, NULL, 'h'},
{"prompt", no_argument, NULL, 'p'},
{"md5auth", no_argument, NULL, 'm'},
+ {"md5auth", no_argument, NULL, 'm'},
+ {"config-file", required_argument, NULL, 'f'},
{NULL, 0, NULL, 0}
};
- while ((opt = getopt_long(argc, argv, "h:p:m", long_options, &optindex)) != -1)
+ snprintf(conf_file, sizeof(conf_file), "%s/%s", DEFAULT_CONFIGDIR, POOL_CONF_FILE_NAME);
+
+ while ((opt = getopt_long(argc, argv, "hpmf:", long_options, &optindex)) != -1)
{
switch (opt)
{
@@ -70,6 +79,14 @@ main(int argc, char *argv[])
md5auth = true;
break;
+ case 'f': /* specify configuration file */
+ if (!optarg)
+ {
+ PRINT_USAGE(EXIT_SUCCESS);
+ }
+ strncpy(conf_file, optarg, sizeof(conf_file));
+ break;
+
default:
PRINT_USAGE(EXIT_SUCCESS);
break;
@@ -104,14 +121,35 @@ main(int argc, char *argv[])
len--;
}
- pool_md5_hash(buf, len, md5);
+ if (md5auth)
+ {
+ struct passwd *pw;
+
+ if (pool_init_config())
+ {
+ fprintf(stderr, "pool_init_config() failed\n\n");
+ PRINT_USAGE(EXIT_FAILURE);
+ }
+
+ pw = getpwuid(geteuid());
+ if (!pw)
+ {
+ fprintf(stderr, "getpwuid() failed\n\n");
+ exit(EXIT_FAILURE);
+ }
+ pool_md5_encrypt(buf, pw->pw_name, strlen(pw->pw_name), md5);
+ }
+ else
+ {
+ pool_md5_hash(buf, len, md5);
+ }
printf("\n%s\n", md5);
}
/* Read password from argv. */
else
{
- char md5[MD5_PASSWD_LEN+1];
+ char md5[POOL_PASSWD_LEN+1];
int len;
if (optind >= argc)
@@ -127,7 +165,41 @@ main(int argc, char *argv[])
PRINT_USAGE(EXIT_FAILURE);
}
- pool_md5_hash(argv[optind], len, md5);
+ if (md5auth)
+ {
+ struct passwd *pw;
+
+ if (pool_init_config())
+ {
+ fprintf(stderr, "pool_init_config() failed\n\n");
+ PRINT_USAGE(EXIT_FAILURE);
+ }
+ if (pool_get_config(conf_file, INIT_CONFIG))
+ {
+ fprintf(stderr, "Unable to get configuration. Exiting...");
+ PRINT_USAGE(EXIT_FAILURE);
+ }
+
+ snprintf(pool_passwd, sizeof(pool_passwd), "%s/%s",
+ dirname(conf_file), pool_config->pool_passwd);
+ pool_init_pool_passwd(pool_passwd);
+
+ pw = getpwuid(geteuid());
+ if (!pw)
+ {
+ fprintf(stderr, "getpwuid() failed\n\n");
+ exit(EXIT_FAILURE);
+ }
+ pg_md5_encrypt(argv[optind], pw->pw_name, strlen(pw->pw_name), md5);
+ pool_create_passwdent(pw->pw_name, md5);
+ fprintf(stderr, "%s\n", pool_get_passwd(pw->pw_name));
+ pool_finish_pool_passwd();
+ }
+ else
+ {
+ pool_md5_hash(argv[optind], len, md5);
+ }
+
printf("%s\n", md5);
}
diff --git a/pool.h b/pool.h
index 564c0dd57..835ec628f 100644
--- a/pool.h
+++ b/pool.h
@@ -562,10 +562,16 @@ extern POOL_STATUS do_query(POOL_CONNECTION *backend, char *query, POOL_SELECT_R
extern void free_select_result(POOL_SELECT_RESULT *result);
extern int compare(const void *p1, const void *p2);
+/* pool_auth.c */
+extern void pool_random_salt(char *md5Salt);
+
/* main.c */
extern void pool_sleep(unsigned int second);
/* pool_worker_child.c */
void do_worker_child(void);
+/* md5.c */
+bool pg_md5_encrypt(const char *passwd, const char *salt, size_t salt_len, char *buf);
+
#endif /* POOL_H */
diff --git a/pool_auth.c b/pool_auth.c
index 3bd16196b..e067c233a 100644
--- a/pool_auth.c
+++ b/pool_auth.c
@@ -25,6 +25,7 @@
#include "pool.h"
#include "pool_stream.h"
#include "pool_config.h"
+#include "pool_passwd.h"
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
@@ -41,15 +42,20 @@
#define AUTHFAIL_ERRORCODE "28000"
-static POOL_STATUS pool_send_auth_ok(POOL_CONNECTION *frontend, int pid, int key, int protoMajor);
+static POOL_STATUS pool_send_backend_key_data(POOL_CONNECTION *frontend, int pid, int key, int protoMajor);
static int do_clear_text_password(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reauth, int protoMajor);
static void pool_send_auth_fail(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *cp);
static int do_crypt(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reauth, int protoMajor);
static int do_md5(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reauth, int protoMajor);
-
+static int send_md5auth_request(POOL_CONNECTION *frontend, int protoMajor, char *salt);
+static int read_password_packet(POOL_CONNECTION *frontend, int protoMajor, char *password);
+static int send_password_packet(POOL_CONNECTION *backend, int protoMajor, char *password);
+static int send_auth_ok(POOL_CONNECTION *frontend, int protoMajor);
/*
-* do authentication against backend. if success return 0 otherwise non 0.
+ * After sending the start up packet to the backend, do the
+ * authentication against backend. if success return 0 otherwise non
+ * 0.
*/
int pool_do_auth(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *cp)
{
@@ -111,7 +117,7 @@ from pool_read_message_length and recheck the pg_hba.conf settings.");
* 5: md5 password
* 6: scm credential
*
- * in replication mode, we only support kind = 0, 3. this is because to "salt"
+ * in replication mode, we only support kind = 0, 3. this is because "salt"
* cannot be replicated.
* in non replication mode, we support kind = 0, 3, 4, 5
*/
@@ -191,7 +197,10 @@ from pool_read_message_length and recheck the pg_hba.conf settings.");
/* md5 authentication? */
else if (authkind == 5)
{
- if (!RAW_MODE && NUM_BACKENDS > 1)
+ /* If MD5 auth is not active in pool_hba.conf, it cannot be
+ * used with other than raw mode.
+ */
+ if (frontend->auth_method != uaMD5 && !RAW_MODE && NUM_BACKENDS > 1)
{
pool_send_error_message(frontend, protoMajor, AUTHFAIL_ERRORCODE,
"MD5 authentication is unsupported in replication, master-slave and parallel modes.",
@@ -356,7 +365,7 @@ from pool_read_message_length and recheck the pg_hba.conf settings.");
strncpy(cp->info->user, sp->user, sizeof(cp->info->user) - 1);
cp->info->counter = 1;
- return pool_send_auth_ok(frontend, pid, key, protoMajor);
+ return pool_send_backend_key_data(frontend, pid, key, protoMajor);
}
/*
@@ -422,7 +431,7 @@ int pool_do_reauth(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *cp)
return -1;
}
- return (pool_send_auth_ok(frontend, MASTER_CONNECTION(cp)->pid, MASTER_CONNECTION(cp)->key, protoMajor) != POOL_CONTINUE);
+ return (pool_send_backend_key_data(frontend, MASTER_CONNECTION(cp)->pid, MASTER_CONNECTION(cp)->key, protoMajor) != POOL_CONTINUE);
}
/*
@@ -454,28 +463,14 @@ static void pool_send_auth_fail(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL
}
/*
-* send authentication ok to frontend. if success return 0 otherwise non 0.
+* Send backend key data to frontend. if success return 0 otherwise non 0.
*/
-static POOL_STATUS pool_send_auth_ok(POOL_CONNECTION *frontend, int pid, int key, int protoMajor)
+static POOL_STATUS pool_send_backend_key_data(POOL_CONNECTION *frontend, int pid, int key, int protoMajor)
{
char kind;
int len;
-#ifdef NOT_USED
- if (protoMajor == PROTO_MAJOR_V2)
- {
- /* return "Authentication OK" to the frontend */
- kind = 'R';
- pool_write(frontend, &kind, 1);
- len = htonl(0);
- if (pool_write_and_flush(frontend, &len, sizeof(len)) < 0)
- {
- return -1;
- }
- }
-#endif
-
- /* send backend key data */
+ /* Send backend key data */
kind = 'K';
pool_write(frontend, &kind, 1);
if (protoMajor == PROTO_MAJOR_V3)
@@ -822,78 +817,123 @@ static int do_md5(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reaut
char salt[4];
static int size;
static char password[MAX_PASSWORD_SIZE];
- char response;
int kind;
- int len;
+ char encbuf[POOL_PASSWD_LEN+1];
+ char *pool_passwd;
- if (!reauth)
+ if (!RAW_MODE && NUM_BACKENDS > 1)
{
- /* read salt */
- if (pool_read(backend, salt, sizeof(salt)))
+ /* master? */
+ if (IS_MASTER_NODE_ID(backend->db_node_id))
{
- pool_error("do_md5: failed to read salt");
- return -1;
- }
- pool_debug("DB node id: %d salt: %hhx%hhx%hhx%hhx", backend->db_node_id,
- salt[0], salt[1], salt[2], salt[3]);
- }
- else
- {
- memcpy(salt, backend->salt, sizeof(salt));
- }
+ /* Send md5 auth request to frontend with my own salt */
+ pool_random_salt(salt);
+ if (send_md5auth_request(frontend, protoMajor, salt))
+ {
+ pool_error("do_md5: send_md5auth_request failed");
+ return -1;
+ }
- /* master? */
- if (IS_MASTER_NODE_ID(backend->db_node_id))
- {
- pool_write(frontend, "R", 1); /* authenticaton */
- if (protoMajor == PROTO_MAJOR_V3)
- {
- len = htonl(12);
- pool_write(frontend, &len, sizeof(len));
- }
- kind = htonl(5);
- pool_write(frontend, &kind, sizeof(kind)); /* indicating MD5 */
- pool_write_and_flush(frontend, salt, sizeof(salt)); /* salt */
+ /* Read password packet */
+ if (read_password_packet(frontend, protoMajor, password))
+ {
+ pool_error("do_md5: read_password_packet failed");
+ return -1;
+ }
- /* read password packet */
- if (protoMajor == PROTO_MAJOR_V2)
- {
- if (pool_read(frontend, &size, sizeof(size)))
+ /* Check the password using my salt + pool_passwd */
+ pool_passwd = pool_get_passwd(frontend->username);
+ if (!pool_passwd)
{
- pool_error("do_md5: failed to read password packet size");
+ pool_debug("do_md5: %s does not exist in pool_passwd", frontend->username);
+ return -1;
+ }
+
+ pg_md5_encrypt(pool_passwd+strlen("md5"), salt, sizeof(salt), encbuf);
+ if (strcmp(password, encbuf))
+ {
+ /* Password does not match */
+ pool_debug("password does not match: frontend:%s pgpool:%s", password, encbuf);
return -1;
}
}
- else
- {
- char k;
+ kind = 0;
- if (pool_read(frontend, &k, sizeof(k)))
+ if (!reauth)
+ {
+ /*
+ * If ok, authenticate against backends using pool_passwd
+ */
+ /* Read salt */
+ if (pool_read(backend, salt, sizeof(salt)))
{
- pool_debug("do_md5_password: failed to read password packet \"p\"");
+ pool_error("do_md5: failed to read salt");
return -1;
}
- if (k != 'p')
+ pool_debug("DB node id: %d salt: %hhx%hhx%hhx%hhx", backend->db_node_id,
+ salt[0], salt[1], salt[2], salt[3]);
+
+ /* Encrypt password in pool_passwd using the salt */
+ pg_md5_encrypt(pool_passwd+strlen("md5"), salt, sizeof(salt), encbuf);
+
+ /* Send password packet to backend and receive auth response */
+ kind = send_password_packet(backend, protoMajor, encbuf);
+ if (kind < 0)
{
- pool_error("do_md5_password: password packet does not start with \"p\"");
return -1;
}
- if (pool_read(frontend, &size, sizeof(size)))
+ }
+
+ if (!reauth && kind == 0)
+ {
+ if (IS_MASTER_NODE_ID(backend->db_node_id))
+ {
+ /* Send auth ok to frontend */
+ if (send_auth_ok(frontend, protoMajor) < 0)
+ {
+ pool_error("do_md5: send_auth_ok failed");
+ return -1;
+ }
+ }
+
+ /* Save the auth info */
+ backend->auth_kind = 5;
+ }
+ return kind;
+ }
+ else
+ {
+ if (!reauth)
+ {
+ /* read salt */
+ if (pool_read(backend, salt, sizeof(salt)))
{
- pool_error("do_md5_password: failed to read password packet size");
+ pool_error("do_md5: failed to read salt");
return -1;
}
+ pool_debug("DB node id: %d salt: %hhx%hhx%hhx%hhx", backend->db_node_id,
+ salt[0], salt[1], salt[2], salt[3]);
+ }
+ else
+ {
+ memcpy(salt, backend->salt, sizeof(salt));
}
+ }
- if ((ntohl(size) - 4) > sizeof(password))
+ /* master? */
+ if (IS_MASTER_NODE_ID(backend->db_node_id))
+ {
+ /* Send md5 auth request to frontend */
+ if (send_md5auth_request(frontend, protoMajor, salt))
{
- pool_error("do_md5: password is too long(size: %d)", ntohl(size) - 4);
+ pool_error("do_md5: send_md5auth_request failed");
return -1;
}
- if (pool_read(frontend, password, ntohl(size) - 4))
+ /* Read password packet */
+ if (read_password_packet(frontend, protoMajor, password))
{
- pool_error("do_md5: failed to read password (size: %d)", ntohl(size) - 4);
+ pool_error("do_md5: read_password_packet failed");
return -1;
}
}
@@ -916,20 +956,124 @@ static int do_md5(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reaut
return 0;
}
- /* send password packet to backend */
+ /* Send password packet to backend and receive auth response */
+ kind = send_password_packet(backend, protoMajor, password);
+ if (kind < 0)
+ {
+ return -1;
+ }
+
+ /* If authenticated, reply back to frontend and save info */
+ if (!reauth && kind == 0)
+ {
+ if (send_auth_ok(frontend, protoMajor) < 0)
+ {
+ pool_error("do_md5: send_auth_ok failed");
+ return -1;
+ }
+
+ backend->auth_kind = 5;
+ backend->pwd_size = ntohl(size) - 4;
+ memcpy(backend->password, password, backend->pwd_size);
+ memcpy(backend->salt, salt, sizeof(salt));
+ }
+ return kind;
+}
+
+/*
+ * Send md5 authentication request packet to frontend
+ */
+static int send_md5auth_request(POOL_CONNECTION *frontend, int protoMajor, char *salt)
+{
+ int len;
+ int kind;
+
+ pool_write(frontend, "R", 1); /* authenticaton */
+ if (protoMajor == PROTO_MAJOR_V3)
+ {
+ len = htonl(12);
+ pool_write(frontend, &len, sizeof(len));
+ }
+ kind = htonl(5);
+ pool_write(frontend, &kind, sizeof(kind)); /* indicating MD5 */
+ pool_write_and_flush(frontend, salt, 4); /* salt */
+
+ return 0;
+}
+
+/*
+ * Read password packet from frontend
+ */
+static int read_password_packet(POOL_CONNECTION *frontend, int protoMajor, char *password)
+{
+ int size;
+
+ /* Read password packet */
+ if (protoMajor == PROTO_MAJOR_V2)
+ {
+ if (pool_read(frontend, &size, sizeof(size)))
+ {
+ pool_error("read_password_packet: failed to read password packet size");
+ return -1;
+ }
+ }
+ else
+ {
+ char k;
+
+ if (pool_read(frontend, &k, sizeof(k)))
+ {
+ pool_debug("read_password_packet_password: failed to read password packet \"p\"");
+ return -1;
+ }
+ if (k != 'p')
+ {
+ pool_error("read_password_packet_password: password packet does not start with \"p\"");
+ return -1;
+ }
+ if (pool_read(frontend, &size, sizeof(size)))
+ {
+ pool_error("read_password_packet_password: failed to read password packet size");
+ return -1;
+ }
+ }
+
+ if (pool_read(frontend, password, ntohl(size) - 4))
+ {
+ pool_error("read_password_packet: failed to read password (size: %d)", ntohl(size) - 4);
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Send password packet to backend and receive authentication response
+ * packet. Return value is the last field of authentication
+ * response. If it's 0, authentication was successfull.
+ */
+static int send_password_packet(POOL_CONNECTION *backend, int protoMajor, char *password)
+{
+ int size;
+ int len;
+ int kind;
+ char response;
+
+ /* Send password packet to backend */
if (protoMajor == PROTO_MAJOR_V3)
pool_write(backend, "p", 1);
+ size = htonl(sizeof(size) + strlen(password));
pool_write(backend, &size, sizeof(size));
- pool_write_and_flush(backend, password, ntohl(size) -4);
+ pool_write_and_flush(backend, password, strlen(password));
+
if (pool_read(backend, &response, sizeof(response)))
{
- pool_error("do_md5: failed to read authentication response");
+ pool_error("send_password_packet: failed to read authentication response");
return -1;
}
if (response != 'R')
{
- pool_debug("do_md5: backend does not return R while processing MD5 authentication %c", response);
+ pool_debug("send_password_packet: backend does not return R");
return -1;
}
@@ -937,49 +1081,48 @@ static int do_md5(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reaut
{
if (pool_read(backend, &len, sizeof(len)))
{
- pool_error("do_md5: failed to read authentication packet size");
+ pool_error("send_password_packet: failed to read authentication packet size");
return -1;
}
if (ntohl(len) != 8)
{
- pool_error("do_md5: incorrect authentication packet size (%d)", ntohl(len));
+ pool_error("send_password_packet: incorrect authentication packet size (%d)", ntohl(len));
return -1;
}
}
- /* expect to read "Authentication OK" response. kind should be 0... */
+ /* Expect to read "Authentication OK" response. kind should be 0... */
if (pool_read(backend, &kind, sizeof(kind)))
{
- pool_debug("do_md5: failed to read Authentication OK response");
+ pool_debug("send_password_packet: failed to read Authentication OK response");
return -1;
}
- /* if authenticated, save info */
- if (!reauth && kind == 0)
- {
- int msglen;
+ return kind;
+}
- pool_write(frontend, "R", 1);
+/*
+ * Send auth ok to frontend
+ */
+static int send_auth_ok(POOL_CONNECTION *frontend, int protoMajor)
+{
+ int msglen;
- if (protoMajor == PROTO_MAJOR_V3)
- {
- msglen = htonl(8);
- pool_write(frontend, &msglen, sizeof(msglen));
- }
+ pool_write(frontend, "R", 1);
- msglen = htonl(0);
- if (pool_write_and_flush(frontend, &msglen, sizeof(msglen)) < 0)
- {
- return -1;
- }
+ if (protoMajor == PROTO_MAJOR_V3)
+ {
+ msglen = htonl(8);
+ pool_write(frontend, &msglen, sizeof(msglen));
+ }
- backend->auth_kind = 5;
- backend->pwd_size = ntohl(size) - 4;
- memcpy(backend->password, password, backend->pwd_size);
- memcpy(backend->salt, salt, sizeof(salt));
+ msglen = htonl(0);
+ if (pool_write_and_flush(frontend, &msglen, sizeof(msglen)) < 0)
+ {
+ return -1;
}
- return kind;
+ return 0;
}
/*
@@ -1168,3 +1311,19 @@ int pool_read_int(POOL_CONNECTION_POOL *cp)
return data;
}
+
+/*
+ * pool_random_salt
+ */
+void pool_random_salt(char *md5Salt)
+{
+ long rand = random();
+
+ md5Salt[0] = (rand % 255) + 1;
+ rand = random();
+ md5Salt[1] = (rand % 255) + 1;
+ rand = random();
+ md5Salt[2] = (rand % 255) + 1;
+ rand = random();
+ md5Salt[3] = (rand % 255) + 1;
+}
diff --git a/pool_config.c b/pool_config.c
index 5daca5d14..e8b16950f 100644
--- a/pool_config.c
+++ b/pool_config.c
@@ -1838,12 +1838,21 @@ int pool_init_config(void)
memset(pool_config, 0, sizeof(POOL_CONFIG));
+#ifdef PGPOOL_MAIN
pool_config->backend_desc = pool_shared_memory_create(sizeof(BackendDesc));
if (pool_config->backend_desc == NULL)
{
pool_error("failed to allocate pool_config->backend_desc");
return -1;
}
+#else
+ pool_config->backend_desc = malloc(sizeof(BackendDesc));
+ if (pool_config->backend_desc == NULL)
+ {
+ pool_error("failed to allocate pool_config->backend_desc");
+ return -1;
+ }
+#endif
/* set hardcoded default values */
pool_config->listen_addresses = "localhost";
@@ -1867,6 +1876,7 @@ int pool_init_config(void)
pool_config->log_connections = 0;
pool_config->log_hostname = 0;
pool_config->enable_pool_hba = 0;
+ pool_config->pool_passwd = "pool_passwd";
pool_config->replication_mode = 0;
pool_config->load_balance_mode = 0;
@@ -2250,6 +2260,25 @@ int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context)
}
pool_config->enable_pool_hba = v;
}
+ else if (!strcmp(key, "pool_passwd") && CHECK_CONTEXT(INIT_CONFIG, context))
+ {
+ char *str;
+
+ if (token != POOL_STRING && token != POOL_UNQUOTED_STRING && token != POOL_KEY)
+ {
+ PARSE_ERROR();
+ fclose(fd);
+ return(-1);
+ }
+ str = extract_string(yytext, token);
+ if (str == NULL)
+ {
+ fclose(fd);
+ return(-1);
+ }
+ pool_config->pool_passwd = str;
+ }
+
else if (!strcmp(key, "backend_socket_dir") && CHECK_CONTEXT(INIT_CONFIG, context))
{
char *str;
@@ -3188,12 +3217,17 @@ int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context)
}
memset(system_db_info, 0, sizeof(*system_db_info));
+#ifdef PGPOOL_MAIN
system_db_info->system_db_status = pool_shared_memory_create(sizeof(BACKEND_STATUS));
+#else
+ system_db_info->system_db_status = malloc(sizeof(BACKEND_STATUS));
+#endif
if (system_db_info->system_db_status == NULL)
{
pool_error("failed to allocate system_db_info->system_db_status");
return -1;
}
+
*system_db_info->system_db_status = CON_CONNECT_WAIT; /* which is the same as SYSDB_STATUS = CON_CONNECT_WAIT */
info = malloc(sizeof(SystemDBInfo));
@@ -3213,8 +3247,10 @@ int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context)
info->dist_def_num = 0;
info->dist_def_slot = NULL;
+#ifdef PGPOOL_MAIN
if (pool_config->parallel_mode)
{
+
dist_num = pool_memset_system_db_info(info);
if(dist_num < 0)
{
@@ -3237,6 +3273,7 @@ int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context)
}
}
SYSDB_STATUS = CON_UP;
+#endif
}
return 0;
diff --git a/pool_config.h b/pool_config.h
index 92fbeb714..3f0d65543 100644
--- a/pool_config.h
+++ b/pool_config.h
@@ -58,6 +58,7 @@ typedef struct {
int log_connections; /* 0:false, 1:true - logs incoming connections */
int log_hostname; /* 0:false, 1:true - resolve hostname */
int enable_pool_hba; /* 0:false, 1:true - enables pool_hba.conf file authentication */
+ char *pool_passwd; /* pool_passwd file name. "" disables pool_passwd */
int load_balance_mode; /* load balance mode */
diff --git a/pool_config.l b/pool_config.l
index 972e3230b..d76e0a355 100644
--- a/pool_config.l
+++ b/pool_config.l
@@ -113,12 +113,21 @@ int pool_init_config(void)
memset(pool_config, 0, sizeof(POOL_CONFIG));
+#ifdef PGPOOL_MAIN
pool_config->backend_desc = pool_shared_memory_create(sizeof(BackendDesc));
if (pool_config->backend_desc == NULL)
{
pool_error("failed to allocate pool_config->backend_desc");
return -1;
}
+#else
+ pool_config->backend_desc = malloc(sizeof(BackendDesc));
+ if (pool_config->backend_desc == NULL)
+ {
+ pool_error("failed to allocate pool_config->backend_desc");
+ return -1;
+ }
+#endif
/* set hardcoded default values */
pool_config->listen_addresses = "localhost";
@@ -142,6 +151,7 @@ int pool_init_config(void)
pool_config->log_connections = 0;
pool_config->log_hostname = 0;
pool_config->enable_pool_hba = 0;
+ pool_config->pool_passwd = "pool_passwd";
pool_config->replication_mode = 0;
pool_config->load_balance_mode = 0;
@@ -525,6 +535,25 @@ int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context)
}
pool_config->enable_pool_hba = v;
}
+ else if (!strcmp(key, "pool_passwd") && CHECK_CONTEXT(INIT_CONFIG, context))
+ {
+ char *str;
+
+ if (token != POOL_STRING && token != POOL_UNQUOTED_STRING && token != POOL_KEY)
+ {
+ PARSE_ERROR();
+ fclose(fd);
+ return(-1);
+ }
+ str = extract_string(yytext, token);
+ if (str == NULL)
+ {
+ fclose(fd);
+ return(-1);
+ }
+ pool_config->pool_passwd = str;
+ }
+
else if (!strcmp(key, "backend_socket_dir") && CHECK_CONTEXT(INIT_CONFIG, context))
{
char *str;
@@ -1463,12 +1492,17 @@ int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context)
}
memset(system_db_info, 0, sizeof(*system_db_info));
+#ifdef PGPOOL_MAIN
system_db_info->system_db_status = pool_shared_memory_create(sizeof(BACKEND_STATUS));
+#else
+ system_db_info->system_db_status = malloc(sizeof(BACKEND_STATUS));
+#endif
if (system_db_info->system_db_status == NULL)
{
pool_error("failed to allocate system_db_info->system_db_status");
return -1;
}
+
*system_db_info->system_db_status = CON_CONNECT_WAIT; /* which is the same as SYSDB_STATUS = CON_CONNECT_WAIT */
info = malloc(sizeof(SystemDBInfo));
@@ -1488,8 +1522,10 @@ int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context)
info->dist_def_num = 0;
info->dist_def_slot = NULL;
+#ifdef PGPOOL_MAIN
if (pool_config->parallel_mode)
{
+
dist_num = pool_memset_system_db_info(info);
if(dist_num < 0)
{
@@ -1512,6 +1548,7 @@ int pool_get_config(char *confpath, POOL_CONFIG_CONTEXT context)
}
}
SYSDB_STATUS = CON_UP;
+#endif
}
return 0;
diff --git a/pool_globals.c b/pool_globals.c
new file mode 100644
index 000000000..2ff50f7a3
--- /dev/null
+++ b/pool_globals.c
@@ -0,0 +1,27 @@
+/* -*-pgsql-c-*- */
+/*
+ * $Header$
+ *
+ * pgpool: a language independent connection pool server for PostgreSQL
+ * written by Tatsuo Ishii
+ *
+ * Copyright (c) 2003-2010 PgPool Global Development Group
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of the
+ * author not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. The author makes no representations about the
+ * suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * Global varibles. Should be eventually removed.
+ */
+#include "pool.h"
+
+int debug = 0; /* non 0 if debug option is given (-d). pcp only */
+pid_t mypid; /* pgpool parent process id */
+bool run_as_pcp_child;
diff --git a/pool_hba.c b/pool_hba.c
index 16e23e8a8..909c6c9ea 100644
--- a/pool_hba.c
+++ b/pool_hba.c
@@ -62,6 +62,7 @@ static char *tokenize_inc_file(const char *outer_filename, const char *inc_filen
static bool pg_isblank(const char c);
static void next_token(FILE *fp, char *buf, int bufsz);
static char * next_token_expand(const char *filename, FILE *file);
+static POOL_STATUS CheckMd5Auth(POOL_CONNECTION *frontend);
#ifdef USE_PAM
#ifdef HAVE_PAM_PAM_APPL_H
@@ -217,8 +218,9 @@ void ClientAuthentication(POOL_CONNECTION *frontend)
/* case uaIdent: */
/* break; */
-/* case uaMD5: */
-/* break; */
+ case uaMD5:
+ status = CheckMd5Auth(frontend);
+ break;
/* case uaCrypt: */
/* break; */
@@ -389,7 +391,12 @@ static void auth_failed(POOL_CONNECTION *frontend)
/* "Ident authentication with pgpool failed for user \"%s\"", */
/* frontend->username); */
/* break; */
-/* case uaMD5: */
+ case uaMD5:
+ snprintf(errmessage, messagelen,
+ "\"MD5\" authentication with pgpool failed for user \"%s\"",
+ frontend->username);
+ break;
+
/* case uaCrypt: */
/* case uaPassword: */
/* snprintf(errmessage, messagelen, */
@@ -793,9 +800,9 @@ static void parse_hba_auth(ListCell **line_item, UserAuth *userauth_p,
*/
else if (strcmp(token, "reject") == 0)
*userauth_p = uaReject;
- /*
else if (strcmp(token, "md5") == 0)
*userauth_p = uaMD5;
+ /*
else if (strcmp(token, "crypt") == 0)
*userauth_p = uaCrypt;
*/
@@ -1436,3 +1443,19 @@ static POOL_STATUS CheckPAMAuth(POOL_CONNECTION *frontend, char *user, char *pas
}
#endif /* USE_PAM */
+
+static POOL_STATUS CheckMd5Auth(POOL_CONNECTION *frontend)
+{
+ POOL_STATUS status;
+
+ /* Look for the entry in pool_passwd */
+
+ /* Not found. authentication failed */
+ /* return POOL_ERROR;*/
+
+ /*
+ * If found, save the password.
+ * Actual authentication will be performed later.
+ */
+ return POOL_CONTINUE;
+}
diff --git a/pool_type.h b/pool_type.h
index 368d3b4af..80571df11 100644
--- a/pool_type.h
+++ b/pool_type.h
@@ -254,11 +254,11 @@ typedef enum UserAuth
uaReject,
/* uaKrb4, */
/* uaKrb5, */
- uaTrust
+ uaTrust,
/* uaIdent, */
/* uaPassword, */
/* uaCrypt, */
- /* uaMD5 */
+ uaMD5
#ifdef USE_PAM
,uaPAM
#endif /* USE_PAM */
[parent: cf0799d7d24a]