mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	Fix a read of uninitialized memory in next_token() of hba.c, spotted via
valgrind: a buffer passed to strncmp() had to be NUL-terminated. Original report and patch from Dennis Bjorkland, some cleanup by Andrew Dunstan, and finally some editorializing from Neil Conway.
This commit is contained in:
		@@ -10,7 +10,7 @@
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * IDENTIFICATION
 | 
					 * IDENTIFICATION
 | 
				
			||||||
 *	  $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.119 2003/12/25 03:44:04 momjian Exp $
 | 
					 *	  $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.120 2004/02/02 16:58:30 neilc Exp $
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *-------------------------------------------------------------------------
 | 
					 *-------------------------------------------------------------------------
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@@ -37,12 +37,23 @@
 | 
				
			|||||||
#include "storage/fd.h"
 | 
					#include "storage/fd.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define IDENT_USERNAME_MAX 512
 | 
					 | 
				
			||||||
/* Max size of username ident server can return */
 | 
					/* Max size of username ident server can return */
 | 
				
			||||||
 | 
					#define IDENT_USERNAME_MAX 512
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Standard TCP port number for Ident service.  Assigned by IANA */
 | 
				
			||||||
 | 
					#define IDENT_PORT 113
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Name of the config file  */
 | 
				
			||||||
 | 
					#define CONF_FILE "pg_hba.conf"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Name of the usermap file */
 | 
				
			||||||
 | 
					#define USERMAP_FILE "pg_ident.conf"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* This is used to separate values in multi-valued column strings */
 | 
					/* This is used to separate values in multi-valued column strings */
 | 
				
			||||||
#define MULTI_VALUE_SEP "\001"
 | 
					#define MULTI_VALUE_SEP "\001"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MAX_TOKEN	256
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * These variables hold the pre-parsed contents of the hba and ident
 | 
					 * These variables hold the pre-parsed contents of the hba and ident
 | 
				
			||||||
 * configuration files.  Each is a list of sublists, one sublist for
 | 
					 * configuration files.  Each is a list of sublists, one sublist for
 | 
				
			||||||
@@ -80,19 +91,19 @@ pg_isblank(const char c)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 *	 Grab one token out of fp. Tokens are strings of non-blank
 | 
					 * Grab one token out of fp. Tokens are strings of non-blank
 | 
				
			||||||
 *	 characters bounded by blank characters, beginning of line, and
 | 
					 * characters bounded by blank characters, beginning of line, and
 | 
				
			||||||
 *	 end of line. Blank means space or tab. Return the token as
 | 
					 * end of line. Blank means space or tab. Return the token as
 | 
				
			||||||
 *	 *buf. Leave file positioned to character immediately after the
 | 
					 * *buf. Leave file positioned at the character immediately after the
 | 
				
			||||||
 *	 token or EOF, whichever comes first. If no more tokens on line,
 | 
					 * token or EOF, whichever comes first. If no more tokens on line,
 | 
				
			||||||
 *	 return null string as *buf and position file to beginning of
 | 
					 * return empty string as *buf and position the file to the beginning
 | 
				
			||||||
 *	 next line or EOF, whichever comes first. Allow spaces in quoted
 | 
					 * of the next line or EOF, whichever comes first. Allow spaces in
 | 
				
			||||||
 *	 strings. Terminate on unquoted commas. Handle comments. Treat
 | 
					 * quoted strings. Terminate on unquoted commas. Handle
 | 
				
			||||||
 *   unquoted keywords that might be user names or database names 
 | 
					 * comments. Treat unquoted keywords that might be user names or
 | 
				
			||||||
 *   specially, by appending a newline to them.
 | 
					 * database names specially, by appending a newline to them.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void
 | 
					static void
 | 
				
			||||||
next_token(FILE *fp, char *buf, const int bufsz)
 | 
					next_token(FILE *fp, char *buf, int bufsz)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int			c;
 | 
						int			c;
 | 
				
			||||||
	char	   *start_buf = buf;
 | 
						char	   *start_buf = buf;
 | 
				
			||||||
@@ -101,88 +112,89 @@ next_token(FILE *fp, char *buf, const int bufsz)
 | 
				
			|||||||
	bool		was_quote = false;
 | 
						bool		was_quote = false;
 | 
				
			||||||
	bool        saw_quote = false;
 | 
						bool        saw_quote = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Assert(end_buf > start_buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Move over initial whitespace and commas */
 | 
						/* Move over initial whitespace and commas */
 | 
				
			||||||
	while ((c = getc(fp)) != EOF && (pg_isblank(c) || c == ','))
 | 
						while ((c = getc(fp)) != EOF && (pg_isblank(c) || c == ','))
 | 
				
			||||||
		;
 | 
							;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (c != EOF && c != '\n')
 | 
						if (c == EOF || c == '\n')
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		/*
 | 
							*buf = '\0';
 | 
				
			||||||
		 * Build a token in buf of next characters up to EOF, EOL,
 | 
							return;
 | 
				
			||||||
		 * unquoted comma, or unquoted whitespace.
 | 
						}
 | 
				
			||||||
		 */
 | 
					
 | 
				
			||||||
		while (c != EOF && c != '\n' &&
 | 
						/*
 | 
				
			||||||
			   (!pg_isblank(c) || in_quote == true))
 | 
						 * Build a token in buf of next characters up to EOF, EOL,
 | 
				
			||||||
 | 
						 * unquoted comma, or unquoted whitespace.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						while (c != EOF && c != '\n' &&
 | 
				
			||||||
 | 
							   (!pg_isblank(c) || in_quote == true))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							/* skip comments to EOL */
 | 
				
			||||||
 | 
							if (c == '#' && !in_quote)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			/* skip comments to EOL */
 | 
								while ((c = getc(fp)) != EOF && c != '\n')
 | 
				
			||||||
			if (c == '#' && !in_quote)
 | 
									;
 | 
				
			||||||
			{
 | 
								/* If only comment, consume EOL too; return EOL */
 | 
				
			||||||
				while ((c = getc(fp)) != EOF && c != '\n')
 | 
								if (c != EOF && buf == start_buf)
 | 
				
			||||||
					;
 | 
									c = getc(fp);
 | 
				
			||||||
				/* If only comment, consume EOL too; return EOL */
 | 
								break;
 | 
				
			||||||
				if (c != EOF && buf == start_buf)
 | 
					 | 
				
			||||||
					c = getc(fp);
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (buf >= end_buf)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				ereport(LOG,
 | 
					 | 
				
			||||||
						(errcode(ERRCODE_CONFIG_FILE_ERROR),
 | 
					 | 
				
			||||||
						 errmsg("authentication file token too long, skipping: \"%s\"",
 | 
					 | 
				
			||||||
								buf)));
 | 
					 | 
				
			||||||
				/* Discard remainder of line */
 | 
					 | 
				
			||||||
				while ((c = getc(fp)) != EOF && c != '\n')
 | 
					 | 
				
			||||||
					;
 | 
					 | 
				
			||||||
				buf[0] = '\0';
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (c != '"' || (c == '"' && was_quote))
 | 
					 | 
				
			||||||
				*buf++ = c;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			/* We pass back the comma so the caller knows there is more */
 | 
					 | 
				
			||||||
			if ((pg_isblank(c) || c == ',') && !in_quote)
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			/* Literal double-quote is two double-quotes */
 | 
					 | 
				
			||||||
			if (in_quote && c == '"')
 | 
					 | 
				
			||||||
				was_quote = !was_quote;
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
				was_quote = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (c == '"')
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				in_quote = !in_quote;
 | 
					 | 
				
			||||||
				saw_quote = true;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			c = getc(fp);
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/*
 | 
							if (buf >= end_buf)
 | 
				
			||||||
		 * Put back the char right after the token (critical in case it is
 | 
							{
 | 
				
			||||||
		 * EOL, since we need to detect end-of-line at next call).
 | 
								ereport(LOG,
 | 
				
			||||||
		 */
 | 
										(errcode(ERRCODE_CONFIG_FILE_ERROR),
 | 
				
			||||||
		if (c != EOF)
 | 
										 errmsg("authentication file token too long, skipping: \"%s\"",
 | 
				
			||||||
			ungetc(c, fp);
 | 
												buf)));
 | 
				
			||||||
 | 
								/* Discard remainder of line */
 | 
				
			||||||
 | 
								while ((c = getc(fp)) != EOF && c != '\n')
 | 
				
			||||||
 | 
									;
 | 
				
			||||||
 | 
								buf[0] = '\0';
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (c != '"' || (c == '"' && was_quote))
 | 
				
			||||||
 | 
								*buf++ = c;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* We pass back the comma so the caller knows there is more */
 | 
				
			||||||
 | 
							if ((pg_isblank(c) || c == ',') && !in_quote)
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Literal double-quote is two double-quotes */
 | 
				
			||||||
 | 
							if (in_quote && c == '"')
 | 
				
			||||||
 | 
								was_quote = !was_quote;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								was_quote = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (c == '"')
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								in_quote = !in_quote;
 | 
				
			||||||
 | 
								saw_quote = true;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							c = getc(fp);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
	if ( !saw_quote && 
 | 
						 * Put back the char right after the token (critical in case it is
 | 
				
			||||||
	     (
 | 
						 * EOL, since we need to detect end-of-line at next call).
 | 
				
			||||||
			 strncmp(start_buf,"all",3) == 0  ||
 | 
						 */
 | 
				
			||||||
			 strncmp(start_buf,"sameuser",8) == 0  ||
 | 
						if (c != EOF)
 | 
				
			||||||
			 strncmp(start_buf,"samegroup",9) == 0 
 | 
							ungetc(c, fp);
 | 
				
			||||||
		 )
 | 
					 | 
				
			||||||
		)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		/* append newline to a magical keyword */
 | 
					 | 
				
			||||||
		*buf++ = '\n';
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	*buf = '\0';
 | 
						*buf = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!saw_quote && 
 | 
				
			||||||
 | 
						     (strcmp(start_buf, "all") == 0 ||
 | 
				
			||||||
 | 
							  strcmp(start_buf, "sameuser") == 0 ||
 | 
				
			||||||
 | 
							  strcmp(start_buf, "samegroup") == 0))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							/* append newline to a magical keyword */
 | 
				
			||||||
 | 
							*buf++ = '\n';
 | 
				
			||||||
 | 
							*buf = '\0';
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,7 @@
 | 
				
			|||||||
 *	  Interface to hba.c
 | 
					 *	  Interface to hba.c
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * $PostgreSQL: pgsql/src/include/libpq/hba.h,v 1.34 2003/11/29 22:41:03 pgsql Exp $
 | 
					 * $PostgreSQL: pgsql/src/include/libpq/hba.h,v 1.35 2004/02/02 16:58:30 neilc Exp $
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *-------------------------------------------------------------------------
 | 
					 *-------------------------------------------------------------------------
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@@ -17,15 +17,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "nodes/pg_list.h"
 | 
					#include "nodes/pg_list.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CONF_FILE "pg_hba.conf"
 | 
					 | 
				
			||||||
 /* Name of the config file  */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define USERMAP_FILE "pg_ident.conf"
 | 
					 | 
				
			||||||
 /* Name of the usermap file */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define IDENT_PORT 113
 | 
					 | 
				
			||||||
 /* Standard TCP port number for Ident service.  Assigned by IANA */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef enum UserAuth
 | 
					typedef enum UserAuth
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	uaReject,
 | 
						uaReject,
 | 
				
			||||||
@@ -43,9 +34,6 @@ typedef enum UserAuth
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
typedef struct Port hbaPort;
 | 
					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 List **get_user_line(const char *user);
 | 
				
			||||||
extern void load_hba(void);
 | 
					extern void load_hba(void);
 | 
				
			||||||
extern void load_ident(void);
 | 
					extern void load_ident(void);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user