From b8b34b7b44ee7d932b2a1317232ff15fb72cf1a7 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Sat, 6 Mar 2010 00:45:49 +0000
Subject: [PATCH] When reading pg_hba.conf and similar files, do not treat
 @file as an inclusion 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 | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c
index afc39f45bfe..7718b0be490 100644
--- a/src/backend/libpq/hba.c
+++ b/src/backend/libpq/hba.c
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.200 2010/03/03 20:31:08 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.201 2010/03/06 00:45:49 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -90,6 +90,10 @@ pg_isblank(const char c)
  * double quotes (this allows the inclusion of blanks, but not newlines).
  *
  * The token, if any, is returned at *buf (a buffer of size bufsz).
+ * Also, we set *initial_quote to indicate whether there was quoting before
+ * the first character.  (We use that to prevent "@x" from being treated
+ * as a file inclusion request.  Note that @"x" should be so treated;
+ * we want to allow that to support embedded spaces in file paths.)
  *
  * If successful: store null-terminated token at *buf and return TRUE.
  * If no more tokens on line: set *buf = '\0' and return FALSE.
@@ -104,7 +108,7 @@ pg_isblank(const char c)
  * token.
  */
 static bool
-next_token(FILE *fp, char *buf, int bufsz)
+next_token(FILE *fp, char *buf, int bufsz, bool *initial_quote)
 {
 	int			c;
 	char	   *start_buf = buf;
@@ -113,8 +117,11 @@ next_token(FILE *fp, char *buf, int bufsz)
 	bool		was_quote = false;
 	bool		saw_quote = false;
 
+	/* end_buf reserves two bytes to ensure we can append \n and \0 */
 	Assert(end_buf > start_buf);
 
+	*initial_quote = false;
+
 	/* Move over initial whitespace and commas */
 	while ((c = getc(fp)) != EOF && (pg_isblank(c) || c == ','))
 		;
@@ -173,6 +180,8 @@ next_token(FILE *fp, char *buf, int bufsz)
 		{
 			in_quote = !in_quote;
 			saw_quote = true;
+			if (buf == start_buf)
+				*initial_quote = true;
 		}
 
 		c = getc(fp);
@@ -216,12 +225,13 @@ next_token_expand(const char *filename, FILE *file)
 	char	   *comma_str = pstrdup("");
 	bool		got_something = false;
 	bool		trailing_comma;
+	bool		initial_quote;
 	char	   *incbuf;
 	int			needed;
 
 	do
 	{
-		if (!next_token(file, buf, sizeof(buf)))
+		if (!next_token(file, buf, sizeof(buf), &initial_quote))
 			break;
 
 		got_something = true;
@@ -235,7 +245,7 @@ next_token_expand(const char *filename, 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(filename, buf + 1);
 		else
 			incbuf = pstrdup(buf);
-- 
GitLab