pgpool2.git / summary / log / commit / refs
commit 2f3cbd4e411f7c5d32ee916d764643cea27c93f5
Author: Tatsuo Ishii <ishii at sraoss.co.jp>
Date: Thu Dec 16 08:42:36 2010 +0000
Fix do_md5(). If raw mode or number of backend is 1, pgpool child segfaults.
patch contributed by Rob Shepherd, slight editing by Tatsuo Ishii.
Fix read_password_packet(). Guard against invalid password lenghth.
Fix send_password_packet(). password string in a password packet must be
a "string" message type, which must has a null termination. Otherwise
you will see "invalid passoword packet size" error message in backend.
pool_auth.c | 70 +++++++++++++++++++++++++++++++++++++++----------------------
1 file changed, 45 insertions(+), 25 deletions(-)
diff --git a/pool_auth.c b/pool_auth.c
index f9bf93d74..2d93d12fc 100644
--- a/pool_auth.c
+++ b/pool_auth.c
@@ -48,7 +48,7 @@ static void pool_send_auth_fail(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL
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 read_password_packet(POOL_CONNECTION *frontend, int protoMajor, char *password, int *pwdSize);
static int send_password_packet(POOL_CONNECTION *backend, int protoMajor, char *password);
static int send_auth_ok(POOL_CONNECTION *frontend, int protoMajor);
@@ -833,7 +833,7 @@ static int do_md5(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reaut
char encbuf[POOL_PASSWD_LEN+1];
char *pool_passwd = NULL;
- if (!RAW_MODE && NUM_BACKENDS > 1)
+ if (NUM_BACKENDS > 1)
{
/* Read password entry from pool_passwd */
pool_passwd = pool_get_passwd(frontend->username);
@@ -855,7 +855,7 @@ static int do_md5(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reaut
}
/* Read password packet */
- if (read_password_packet(frontend, protoMajor, password))
+ if (read_password_packet(frontend, protoMajor, password, &size))
{
pool_error("do_md5: read_password_packet failed");
return -1;
@@ -914,23 +914,24 @@ static int do_md5(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reaut
}
return kind;
}
- else
+
+ /*
+ * Followings are NUM_BACKEND == 1 case.
+ */
+ if (!reauth)
{
- if (!reauth)
- {
- /* read salt */
- if (pool_read(backend, salt, sizeof(salt)))
- {
- 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
+ /* read salt */
+ if (pool_read(backend, salt, sizeof(salt)))
{
- memcpy(salt, backend->salt, sizeof(salt));
+ 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));
}
/* master? */
@@ -944,7 +945,7 @@ static int do_md5(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reaut
}
/* Read password packet */
- if (read_password_packet(frontend, protoMajor, password))
+ if (read_password_packet(frontend, protoMajor, password, &size))
{
pool_error("do_md5: read_password_packet failed");
return -1;
@@ -954,7 +955,7 @@ static int do_md5(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reaut
/* connection reusing? */
if (reauth)
{
- if ((ntohl(size) - 4) != backend->pwd_size)
+ if (size != backend->pwd_size)
{
pool_debug("do_md5; password size does not match in re-authentication");
return -1;
@@ -986,7 +987,7 @@ static int do_md5(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reaut
}
backend->auth_kind = 5;
- backend->pwd_size = ntohl(size) - 4;
+ backend->pwd_size = size;
memcpy(backend->password, password, backend->pwd_size);
memcpy(backend->salt, salt, sizeof(salt));
}
@@ -1017,7 +1018,7 @@ static int send_md5auth_request(POOL_CONNECTION *frontend, int protoMajor, char
/*
* Read password packet from frontend
*/
-static int read_password_packet(POOL_CONNECTION *frontend, int protoMajor, char *password)
+static int read_password_packet(POOL_CONNECTION *frontend, int protoMajor, char *password, int *pwdSize)
{
int size;
@@ -1051,11 +1052,30 @@ static int read_password_packet(POOL_CONNECTION *frontend, int protoMajor, char
}
}
- if (pool_read(frontend, password, ntohl(size) - 4))
+ *pwdSize = ntohl(size) - 4;
+ if (*pwdSize > MAX_PASSWORD_SIZE)
{
- pool_error("read_password_packet: failed to read password (size: %d)", ntohl(size) - 4);
+ pool_error("read_password_packet: too long password string (size: %d)", *pwdSize);
+ /*
+ * We do not read to throw away packet here. Since it is possible that
+ * it's a denial of service attack.
+ */
return -1;
}
+ else if (*pwdSize <= 0)
+ {
+ pool_error("read_password_packet: invalid password string size (size: %d)", *pwdSize);
+ return -1;
+ }
+
+ if (pool_read(frontend, password, *pwdSize))
+ {
+ pool_error("read_password_packet: failed to read password (size: %d)", *pwdSize);
+ return -1;
+ }
+
+ password[*pwdSize] = '\0';
+
return 0;
}
@@ -1075,9 +1095,9 @@ static int send_password_packet(POOL_CONNECTION *backend, int protoMajor, char *
/* Send password packet to backend */
if (protoMajor == PROTO_MAJOR_V3)
pool_write(backend, "p", 1);
- size = htonl(sizeof(size) + strlen(password));
+ size = htonl(sizeof(size) + strlen(password)+1);
pool_write(backend, &size, sizeof(size));
- pool_write_and_flush(backend, password, strlen(password));
+ pool_write_and_flush(backend, password, strlen(password)+1);
if (pool_read(backend, &response, sizeof(response)))
{
[parent: ae1b7cc12916]