5050#define atoxid (x ) ((TransactionId) strtoul((x), NULL, 10))
5151
5252#define MAX_TOKEN 256
53+ #define MAX_LINE 8192
5354
5455/* callback data for check_network_callback */
5556typedef struct check_network_data
@@ -93,7 +94,7 @@ static MemoryContext parsed_ident_context = NULL;
9394
9495
9596static MemoryContext tokenize_file (const char * filename ,FILE * file ,
96- List * * lines ,List * * line_nums );
97+ List * * lines ,List * * line_nums , List * * raw_lines );
9798static List * tokenize_inc_file (List * tokens ,const char * outer_filename ,
9899const char * inc_filename );
99100static bool parse_hba_auth_opt (char * name ,char * val ,HbaLine * hbaline ,
@@ -111,7 +112,8 @@ pg_isblank(const char c)
111112
112113
113114/*
114- * Grab one token out of fp. Tokens are strings of non-blank
115+ * Grab one token out of the string pointed to by lineptr.
116+ * Tokens are strings of non-blank
115117 * characters bounded by blank characters, commas, beginning of line, and
116118 * end of line. Blank means space or tab. Tokens can be delimited by
117119 * double quotes (this allows the inclusion of blanks, but not newlines).
@@ -134,7 +136,7 @@ pg_isblank(const char c)
134136 * Handle comments.
135137 */
136138static bool
137- next_token (FILE * fp ,char * buf ,int bufsz ,bool * initial_quote ,
139+ next_token (char * * lineptr ,char * buf ,int bufsz ,bool * initial_quote ,
138140bool * terminating_comma )
139141{
140142int c ;
@@ -151,10 +153,10 @@ next_token(FILE *fp, char *buf, int bufsz, bool *initial_quote,
151153* terminating_comma = false;
152154
153155/* Move over initial whitespace and commas */
154- while ((c = getc ( fp )) != EOF && (pg_isblank (c )|| c == ',' ))
156+ while ((c = ( * ( * lineptr ) ++ )) != '\0' && (pg_isblank (c )|| c == ',' ))
155157;
156158
157- if (c == EOF || c == '\n' )
159+ if (c == '\0' || c == '\n' )
158160{
159161* buf = '\0' ;
160162return false;
@@ -164,17 +166,17 @@ next_token(FILE *fp, char *buf, int bufsz, bool *initial_quote,
164166 * Build a token in buf of next characters up to EOF, EOL, unquoted comma,
165167 * or unquoted whitespace.
166168 */
167- while (c != EOF && c != '\n' &&
169+ while (c != '\0' && c != '\n' &&
168170 (!pg_isblank (c )|| in_quote ))
169171{
170172/* skip comments to EOL */
171173if (c == '#' && !in_quote )
172174{
173- while ((c = getc ( fp )) != EOF && c != '\n' )
175+ while ((c = ( * ( * lineptr ) ++ )) != '\0' && c != '\n' )
174176;
175177/* If only comment, consume EOL too; return EOL */
176- if (c != EOF && buf == start_buf )
177- c = getc ( fp ) ;
178+ if (c != '\0' && buf == start_buf )
179+ ( * lineptr ) ++ ;
178180break ;
179181}
180182
@@ -186,7 +188,7 @@ next_token(FILE *fp, char *buf, int bufsz, bool *initial_quote,
186188errmsg ("authentication file token too long, skipping: \"%s\"" ,
187189start_buf )));
188190/* Discard remainder of line */
189- while ((c = getc ( fp )) != EOF && c != '\n' )
191+ while ((c = ( * ( * lineptr ) ++ )) != '\0' && c != '\n' )
190192;
191193break ;
192194}
@@ -215,15 +217,14 @@ next_token(FILE *fp, char *buf, int bufsz, bool *initial_quote,
215217* initial_quote = true;
216218}
217219
218- c = getc ( fp ) ;
220+ c = * ( * lineptr ) ++ ;
219221}
220222
221223/*
222224 * Put back the char right after the token (critical in case it is EOL,
223225 * since we need to detect end-of-line at next call).
224226 */
225- if (c != EOF )
226- ungetc (c ,fp );
227+ (* lineptr )-- ;
227228
228229* buf = '\0' ;
229230
@@ -258,13 +259,13 @@ copy_hba_token(HbaToken *in)
258259
259260
260261/*
261- * Tokenize one HBA field from afile , handling file inclusion and comma lists.
262+ * Tokenize one HBA field from aline , handling file inclusion and comma lists.
262263 *
263264 * The result is a List of HbaToken structs for each individual token,
264265 * or NIL if we reached EOL.
265266 */
266267static List *
267- next_field_expand (const char * filename ,FILE * file )
268+ next_field_expand (const char * filename ,char * * lineptr )
268269{
269270char buf [MAX_TOKEN ];
270271bool trailing_comma ;
@@ -273,7 +274,7 @@ next_field_expand(const char *filename, FILE *file)
273274
274275do
275276{
276- if (!next_token (file ,buf ,sizeof (buf ),& initial_quote ,& trailing_comma ))
277+ if (!next_token (lineptr ,buf ,sizeof (buf ),& initial_quote ,& trailing_comma ))
277278break ;
278279
279280/* Is this referencing a file? */
@@ -335,7 +336,7 @@ tokenize_inc_file(List *tokens,
335336}
336337
337338/* There is possible recursion here if the file contains @ */
338- linecxt = tokenize_file (inc_fullname ,inc_file ,& inc_lines ,& inc_line_nums );
339+ linecxt = tokenize_file (inc_fullname ,inc_file ,& inc_lines ,& inc_line_nums , NULL );
339340
340341FreeFile (inc_file );
341342pfree (inc_fullname );
@@ -364,8 +365,8 @@ tokenize_inc_file(List *tokens,
364365}
365366
366367/*
367- * Tokenize the given file, storing the resulting data intotwo Lists: a
368- * List of lines, and a List of linenumbers .
368+ * Tokenize the given file, storing the resulting data intothree Lists: a
369+ * List of lines,a List of line numbers, and a List ofraw linecontents .
369370 *
370371 * The list of lines is a triple-nested List structure. Each line is a List of
371372 * fields, and each field is a List of HbaTokens.
@@ -377,7 +378,7 @@ tokenize_inc_file(List *tokens,
377378 */
378379static MemoryContext
379380tokenize_file (const char * filename ,FILE * file ,
380- List * * lines ,List * * line_nums )
381+ List * * lines ,List * * line_nums , List * * raw_lines )
381382{
382383List * current_line = NIL ;
383384List * current_field = NIL ;
@@ -396,30 +397,51 @@ tokenize_file(const char *filename, FILE *file,
396397
397398while (!feof (file )&& !ferror (file ))
398399{
399- current_field = next_field_expand (filename ,file );
400+ char rawline [MAX_LINE ];
401+ char * lineptr ;
400402
401- /* add tokens to list, unless we are at EOL or comment start */
402- if (list_length (current_field )> 0 )
403+ if (!fgets (rawline ,sizeof (rawline ),file ))
404+ break ;
405+ if (strlen (rawline )== MAX_LINE - 1 )
406+ /* Line too long! */
407+ ereport (ERROR ,
408+ (errcode (ERRCODE_CONFIG_FILE_ERROR ),
409+ errmsg ("authentication file line too long" ),
410+ errcontext ("line %d of configuration file \"%s\"" ,
411+ line_number ,filename )));
412+
413+ /* Strip trailing linebreak from rawline */
414+ while (rawline [strlen (rawline )- 1 ]== '\n' ||
415+ rawline [strlen (rawline )- 1 ]== '\r' )
416+ rawline [strlen (rawline )- 1 ]= '\0' ;
417+
418+ lineptr = rawline ;
419+ while (strlen (lineptr )> 0 )
403420{
404- if (current_line == NIL )
405- {
406- /* make a new line List, record its line number */
407- current_line = lappend (current_line ,current_field );
408- * lines = lappend (* lines ,current_line );
409- * line_nums = lappend_int (* line_nums ,line_number );
410- }
411- else
421+ current_field = next_field_expand (filename ,& lineptr );
422+
423+ /* add tokens to list, unless we are at EOL or comment start */
424+ if (list_length (current_field )> 0 )
412425{
413- /* append tokens to current line's list */
414- current_line = lappend (current_line ,current_field );
426+ if (current_line == NIL )
427+ {
428+ /* make a new line List, record its line number */
429+ current_line = lappend (current_line ,current_field );
430+ * lines = lappend (* lines ,current_line );
431+ * line_nums = lappend_int (* line_nums ,line_number );
432+ if (raw_lines )
433+ * raw_lines = lappend (* raw_lines ,pstrdup (rawline ));
434+ }
435+ else
436+ {
437+ /* append tokens to current line's list */
438+ current_line = lappend (current_line ,current_field );
439+ }
415440}
416441}
417- else
418- {
419- /* we are at real or logical EOL, so force a new line List */
420- current_line = NIL ;
421- line_number ++ ;
422- }
442+ /* we are at real or logical EOL, so force a new line List */
443+ current_line = NIL ;
444+ line_number ++ ;
423445}
424446
425447MemoryContextSwitchTo (oldcxt );
@@ -815,7 +837,7 @@ check_same_host_or_net(SockAddr *raddr, IPCompareMethod method)
815837 * NULL.
816838 */
817839static HbaLine *
818- parse_hba_line (List * line ,int line_num )
840+ parse_hba_line (List * line ,int line_num , char * raw_line )
819841{
820842char * str ;
821843struct addrinfo * gai_result ;
@@ -831,6 +853,7 @@ parse_hba_line(List *line, int line_num)
831853
832854parsedline = palloc0 (sizeof (HbaLine ));
833855parsedline -> linenumber = line_num ;
856+ parsedline -> rawline = pstrdup (raw_line );
834857
835858/* Check the record type. */
836859field = list_head (line );
@@ -1761,8 +1784,10 @@ load_hba(void)
17611784FILE * file ;
17621785List * hba_lines = NIL ;
17631786List * hba_line_nums = NIL ;
1787+ List * hba_raw_lines = NIL ;
17641788ListCell * line ,
1765- * line_num ;
1789+ * line_num ,
1790+ * raw_line ;
17661791List * new_parsed_lines = NIL ;
17671792bool ok = true;
17681793MemoryContext linecxt ;
@@ -1779,7 +1804,7 @@ load_hba(void)
17791804return false;
17801805}
17811806
1782- linecxt = tokenize_file (HbaFileName ,file ,& hba_lines ,& hba_line_nums );
1807+ linecxt = tokenize_file (HbaFileName ,file ,& hba_lines ,& hba_line_nums , & hba_raw_lines );
17831808FreeFile (file );
17841809
17851810/* Now parse all the lines */
@@ -1789,11 +1814,11 @@ load_hba(void)
17891814ALLOCSET_DEFAULT_MINSIZE ,
17901815ALLOCSET_DEFAULT_MAXSIZE );
17911816oldcxt = MemoryContextSwitchTo (hbacxt );
1792- forboth (line ,hba_lines ,line_num ,hba_line_nums )
1817+ forthree (line ,hba_lines ,line_num ,hba_line_nums , raw_line , hba_raw_lines )
17931818{
17941819HbaLine * newline ;
17951820
1796- if ((newline = parse_hba_line (lfirst (line ),lfirst_int (line_num )))== NULL )
1821+ if ((newline = parse_hba_line (lfirst (line ),lfirst_int (line_num ), lfirst ( raw_line ) ))== NULL )
17971822{
17981823/*
17991824 * Parse error in the file, so indicate there's a problem. NB: a
@@ -2153,7 +2178,7 @@ load_ident(void)
21532178return false;
21542179}
21552180
2156- linecxt = tokenize_file (IdentFileName ,file ,& ident_lines ,& ident_line_nums );
2181+ linecxt = tokenize_file (IdentFileName ,file ,& ident_lines ,& ident_line_nums , NULL );
21572182FreeFile (file );
21582183
21592184/* Now parse all the lines */