When reading pg_hba.conf and similar files, do not treat @file as an inclusion
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 6 Mar 2010 00:46:27 +0000 (00:46 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 6 Mar 2010 00:46:27 +0000 (00:46 +0000)
unless (1) the @ isn't quoted and (2) the filename isn't empty.  This guards
against unexpectedly treating usernames or other strings in "flat files"
as inclusion requests, as seen in a recent trouble report from Ed L.
The empty-filename case would be guaranteed to misbehave anyway, because our
subsequent path-munging behavior results in trying to read the directory
containing the current input file.

I think this might finally explain the report at
http://archives.postgresql.org/pgsql-bugs/2004-05/msg00132.php
of a crash after printing "authentication file token too long, skipping",
since I was able to duplicate that message (though not a crash) on a
platform where stdio doesn't refuse to read directories.  We never got
far in investigating that problem, but now I'm suspicious that the trigger
condition was an @ in the flat password file.

Back-patch to all active branches since the problem can be demonstrated in all
branches except HEAD.  The test case, creating a user named "@", doesn't cause
a problem in HEAD since we got rid of the flat password file.  Nonetheless it
seems like a good idea to not consider quoted @ as a file inclusion spec,
so I changed HEAD too.

src/backend/libpq/hba.c
src/include/libpq/hba.h

index 89368aea218afa6e112702bea70d5c09ca8483b7..4a4cbba87c4f4e7a3b242914e3d49377f328dbad 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.116.2.5 2010/03/03 20:31:50 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.116.2.6 2010/03/06 00:46:27 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -89,8 +89,8 @@ pg_isblank(const char c)
  *  next line or EOF, whichever comes first. Allow spaces in quoted
  *  strings. Terminate on unquoted commas. Handle comments.
  */
-void
-next_token(FILE *fp, char *buf, const int bufsz)
+static void
+next_token(FILE *fp, char *buf, int bufsz, bool *initial_quote)
 {
    int         c;
    char       *start_buf = buf;
@@ -98,6 +98,8 @@ next_token(FILE *fp, char *buf, const int bufsz)
    bool        in_quote = false;
    bool        was_quote = false;
 
+   *initial_quote = false;
+
    /* Move over initial whitespace and commas */
    while ((c = getc(fp)) != EOF && (pg_isblank(c) || c == ','))
        ;
@@ -149,7 +151,11 @@ next_token(FILE *fp, char *buf, const int bufsz)
                was_quote = false;
 
            if (c == '"')
+           {
                in_quote = !in_quote;
+               if (buf == start_buf)
+                   *initial_quote = true;
+           }
 
            c = getc(fp);
        }
@@ -178,12 +184,13 @@ next_token_expand(FILE *file)
    char        buf[MAX_TOKEN];
    char       *comma_str = pstrdup("");
    bool        trailing_comma;
+   bool        initial_quote;
    char       *incbuf;
    int         needed;
 
    do
    {
-       next_token(file, buf, sizeof(buf));
+       next_token(file, buf, sizeof(buf), &initial_quote);
        if (!*buf)
            break;
 
@@ -196,7 +203,7 @@ next_token_expand(FILE *file)
            trailing_comma = false;
 
        /* Is this referencing a file? */
-       if (buf[0] == '@')
+       if (!initial_quote && buf[0] == '@' && buf[1] != '\0')
            incbuf = tokenize_inc_file(buf + 1);
        else
            incbuf = pstrdup(buf);
index 9a7e355ff3f6ce61b66c198777de6e2fb5e37c65..b350348195c4ebd0d89d10a1afa11950c7f3efee 100644 (file)
@@ -4,7 +4,7 @@
  *   Interface to hba.c
  *
  *
- * $Id: hba.h,v 1.33 2003/04/17 22:26:01 tgl Exp $
+ * $Id: hba.h,v 1.33.4.1 2010/03/06 00:46:27 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -45,7 +45,6 @@ typedef struct Port hbaPort;
 
 #define MAX_TOKEN  256
 
-extern void next_token(FILE *fp, char *buf, const int bufsz);
 extern List **get_user_line(const char *user);
 extern void load_hba(void);
 extern void load_ident(void);