Validating the PCP packet length
authorMuhammad Usama <m.usama@gmail.com>
Tue, 29 Mar 2016 20:30:33 +0000 (01:30 +0500)
committerMuhammad Usama <m.usama@gmail.com>
Tue, 29 Mar 2016 20:30:33 +0000 (01:30 +0500)
Without the validation check, a malformed PCP packet can crash the PCP child
and/or can run the server out of memory by sending the packet with a
very large data size.

pcp/pcp.c
pcp/pcp.h
pcp_child.c

index e6b1f1eb8dd9a80abf1ac7acad0b4b18463477db..6c29b01022b532a45f1e3dd67a73b1f1adb14e9d 100644 (file)
--- a/pcp/pcp.c
+++ b/pcp/pcp.c
@@ -8,7 +8,7 @@
  * pgpool: a language independent connection pool server for PostgreSQL 
  * written by Tatsuo Ishii
  *
- * Copyright (c) 2003-2014     PgPool Global Development Group
+ * Copyright (c) 2003-2016     PgPool Global Development Group
  *
  * Permission to use, copy, modify, and distribute this software and
  * its documentation for any purpose and without fee is hereby
@@ -192,6 +192,12 @@ pcp_authorize(char *username, char *password)
        char encrypt_buf[(MD5_PASSWD_LEN+1)*2];
        char md5[MD5_PASSWD_LEN+1];
 
+       if (strlen(username) >= MAX_USER_PASSWD_LEN)
+       {
+               fprintf(stderr, "ERROR: PCP authorization failed. username too long.\n");
+               return -1;
+       }
+
        /* request salt */
        pcp_write(pc, "M", 1);
        wsize = htonl(sizeof(int));
index 364f12c06d7214f67cace234cd266ff3ea51aca5..18beadf1c95cdd59ee7a15c054c5e584e5f3fe40 100644 (file)
--- a/pcp/pcp.h
+++ b/pcp/pcp.h
@@ -4,7 +4,7 @@
  * pgpool: a language independent connection pool server for PostgreSQL 
  * written by Tatsuo Ishii
  *
- * Copyright (c) 2003-2008     PgPool Global Development Group
+ * Copyright (c) 2003-2016     PgPool Global Development Group
  *
  * Permission to use, copy, modify, and distribute this software and
  * its documentation for any purpose and without fee is hereby
 #include "watchdog/watchdog.h"
 
 #define MAX_USER_PASSWD_LEN    128
+/* The largest PCP packet a PCP frontend can send is
+ * the user authentication packet, and the maximum size
+ * of the pcp authentication packet can be
+ * MAX_USER_PASSWD_LEN + MAX_USER_PASSWD_LEN + SIZE OF INT */
+#define MAX_PCP_PACKET_LENGTH  260
 
 typedef enum {
        UNKNOWNERR = 1,         /* shouldn't happen */
index d30f02e7bbd4f94808a4008969e95698746d7ce8..2bc1a2c9310e6b79f018dc6c954f6a19dc1aa512 100644 (file)
@@ -5,7 +5,7 @@
  * pgpool: a language independent connection pool server for PostgreSQL
  * written by Tatsuo Ishii
  *
- * Copyright (c) 2003-2011     PgPool Global Development Group
+ * Copyright (c) 2003-2016     PgPool Global Development Group
  *
  * Permission to use, copy, modify, and distribute this software and
  * its documentation for any purpose and without fee is hereby
@@ -59,7 +59,6 @@
 #include "watchdog/wd_ext.h"
 
 #define MAX_FILE_LINE_LEN    512
-#define MAX_USER_PASSWD_LEN  128
 
 extern void pcp_set_timeout(long sec);
 volatile sig_atomic_t pcp_exit_request; /* non 0 means SIGTERM(smart shutdown) or SIGINT(fast shutdown) has arrived */
@@ -179,6 +178,13 @@ pcp_do_child(int unix_fd, int inet_fd, char *pcp_conf_file)
                }
 
                rsize = ntohl(rsize);
+
+               if (rsize <= 0 || rsize >= MAX_PCP_PACKET_LENGTH)
+               {
+                       pool_error("pcp_child: incorrect packet length (%d)", rsize);
+                       exit(1);
+               }
+
                if ((rsize - sizeof(int)) > 0)
                {
                        buf = (char *)malloc(rsize - sizeof(int));