10
10
*
11
11
*
12
12
* IDENTIFICATION
13
- * $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.143 2005/06/28 05:08:56 tgl Exp $
13
+ * $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.144 2005/06/28 22:16:45 tgl Exp $
14
14
*
15
15
*-------------------------------------------------------------------------
16
16
*/
@@ -96,17 +96,23 @@ pg_isblank(const char c)
96
96
97
97
/*
98
98
* Grab one token out of fp. Tokens are strings of non-blank
99
- * characters bounded by blank characters, beginning of line, and
100
- * end of line. Blank means space or tab. Return the token as
101
- * *buf. Leave file positioned at the character immediately after the
102
- * token or EOF, whichever comes first. If no more tokens on line,
103
- * return empty string as *buf and position the file to the beginning
104
- * of the next line or EOF, whichever comes first. Allow spaces in
105
- * quoted strings. Terminate on unquoted commas. Handle
106
- * comments. Treat unquoted keywords that might be role names or
99
+ * characters bounded by blank characters, commas, beginning of line, and
100
+ * end of line. Blank means space or tab. Tokens can be delimited by
101
+ * double quotes (and usually are, in current usage).
102
+ *
103
+ * The token, if any, is returned at *buf (a buffer of size bufsz).
104
+ *
105
+ * If successful: store null-terminated token at *buf and return TRUE.
106
+ * If no more tokens on line: set *buf = '\0' and return FALSE.
107
+ *
108
+ * Leave file positioned at the character immediately after the token or EOF,
109
+ * whichever comes first. If no more tokens on line, position the file to the
110
+ * beginning of the next line or EOF, whichever comes first.
111
+ *
112
+ * Handle comments. Treat unquoted keywords that might be role names or
107
113
* database names specially, by appending a newline to them.
108
114
*/
109
- static void
115
+ static bool
110
116
next_token (FILE * fp , char * buf , int bufsz )
111
117
{
112
118
int c ;
@@ -125,7 +131,7 @@ next_token(FILE *fp, char *buf, int bufsz)
125
131
if (c == EOF || c == '\n' )
126
132
{
127
133
* buf = '\0' ;
128
- return ;
134
+ return false ;
129
135
}
130
136
131
137
/*
@@ -200,32 +206,35 @@ next_token(FILE *fp, char *buf, int bufsz)
200
206
* buf ++ = '\n' ;
201
207
* buf = '\0' ;
202
208
}
209
+
210
+ return (saw_quote || buf > start_buf );
203
211
}
204
212
205
213
/*
206
214
* Tokenize file and handle file inclusion and comma lists. We have
207
215
* to break apart the commas to expand any file names then
208
216
* reconstruct with commas.
209
217
*
210
- * The result is always a palloc'd string. If it's zero-length then
211
- * we have reached EOL.
218
+ * The result is a palloc'd string, or NULL if we have reached EOL.
212
219
*/
213
220
static char *
214
221
next_token_expand (const char * filename , FILE * file )
215
222
{
216
223
char buf [MAX_TOKEN ];
217
224
char * comma_str = pstrdup ("" );
225
+ bool got_something = false;
218
226
bool trailing_comma ;
219
227
char * incbuf ;
220
228
int needed ;
221
229
222
230
do
223
231
{
224
- next_token (file , buf , sizeof (buf ));
225
- if (!buf [0 ])
232
+ if (!next_token (file , buf , sizeof (buf )))
226
233
break ;
227
234
228
- if (buf [strlen (buf ) - 1 ] == ',' )
235
+ got_something = true;
236
+
237
+ if (strlen (buf ) > 0 && buf [strlen (buf ) - 1 ] == ',' )
229
238
{
230
239
trailing_comma = true;
231
240
buf [strlen (buf ) - 1 ] = '\0' ;
@@ -249,6 +258,12 @@ next_token_expand(const char *filename, FILE *file)
249
258
pfree (incbuf );
250
259
} while (trailing_comma );
251
260
261
+ if (!got_something )
262
+ {
263
+ pfree (comma_str );
264
+ return NULL ;
265
+ }
266
+
252
267
return comma_str ;
253
268
}
254
269
@@ -402,7 +417,7 @@ tokenize_file(const char *filename, FILE *file,
402
417
buf = next_token_expand (filename , file );
403
418
404
419
/* add token to list, unless we are at EOL or comment start */
405
- if (buf [ 0 ] )
420
+ if (buf )
406
421
{
407
422
if (current_line == NIL )
408
423
{
@@ -423,8 +438,6 @@ tokenize_file(const char *filename, FILE *file,
423
438
current_line = NIL ;
424
439
/* Advance line number whenever we reach EOL */
425
440
line_number ++ ;
426
- /* Don't forget to pfree the next_token_expand result */
427
- pfree (buf );
428
441
}
429
442
}
430
443
}
@@ -462,44 +475,58 @@ get_role_line(const char *role)
462
475
463
476
464
477
/*
465
- * Does member belong to role?
478
+ * Does user belong to role?
479
+ *
480
+ * user is always the name given as the attempted login identifier.
481
+ * We check to see if it is a member of the specified role name.
466
482
*/
467
483
static bool
468
- check_member (const char * role , const char * member )
484
+ is_member (const char * user , const char * role )
469
485
{
470
486
List * * line ;
471
- List * * line2 ;
472
487
ListCell * line_item ;
473
488
474
- if ((line = get_role_line (member )) == NULL )
475
- return false; /* if member not exist, say "no" */
489
+ if ((line = get_role_line (user )) == NULL )
490
+ return false; /* if user not exist, say "no" */
476
491
477
- if ((line2 = get_role_line (role )) == NULL )
478
- return false; /* if role not exist, say "no" */
492
+ /* A user always belongs to its own role */
493
+ if (strcmp (user , role ) == 0 )
494
+ return true;
479
495
480
- /* skip over the role name, password, valuntil, examine all the members */
481
- for_each_cell (line_item , lfourth (* line2 ))
496
+ /*
497
+ * skip over the role name, password, valuntil, examine all the
498
+ * membership entries
499
+ */
500
+ if (list_length (* line ) < 4 )
501
+ return false;
502
+ for_each_cell (line_item , lnext (lnext (lnext (list_head (* line )))))
482
503
{
483
- if (strcmp ((char * ) lfirst (line_item ), member ) == 0 )
504
+ if (strcmp ((char * ) lfirst (line_item ), role ) == 0 )
484
505
return true;
485
506
}
486
507
487
508
return false;
488
509
}
489
510
490
511
/*
491
- * Check comma member list for a specific role, handle role names.
512
+ * Check comma-separated list for a match to role, allowing group names.
513
+ *
514
+ * NB: param_str is destructively modified! In current usage, this is
515
+ * okay only because this code is run after forking off from the postmaster,
516
+ * and so it doesn't matter that we clobber the stored hba info.
492
517
*/
493
518
static bool
494
- check_role (char * role , char * param_str )
519
+ check_role (const char * role , char * param_str )
495
520
{
496
521
char * tok ;
497
522
498
- for (tok = strtok (param_str , MULTI_VALUE_SEP ); tok != NULL ; tok = strtok (NULL , MULTI_VALUE_SEP ))
523
+ for (tok = strtok (param_str , MULTI_VALUE_SEP );
524
+ tok != NULL ;
525
+ tok = strtok (NULL , MULTI_VALUE_SEP ))
499
526
{
500
527
if (tok [0 ] == '+' )
501
528
{
502
- if (check_member ( tok + 1 , role ))
529
+ if (is_member ( role , tok + 1 ))
503
530
return true;
504
531
}
505
532
else if (strcmp (tok , role ) == 0 ||
@@ -512,13 +539,19 @@ check_role(char *role, char *param_str)
512
539
513
540
/*
514
541
* Check to see if db/role combination matches param string.
542
+ *
543
+ * NB: param_str is destructively modified! In current usage, this is
544
+ * okay only because this code is run after forking off from the postmaster,
545
+ * and so it doesn't matter that we clobber the stored hba info.
515
546
*/
516
547
static bool
517
- check_db (char * dbname , char * role , char * param_str )
548
+ check_db (const char * dbname , const char * role , char * param_str )
518
549
{
519
550
char * tok ;
520
551
521
- for (tok = strtok (param_str , MULTI_VALUE_SEP ); tok != NULL ; tok = strtok (NULL , MULTI_VALUE_SEP ))
552
+ for (tok = strtok (param_str , MULTI_VALUE_SEP );
553
+ tok != NULL ;
554
+ tok = strtok (NULL , MULTI_VALUE_SEP ))
522
555
{
523
556
if (strcmp (tok , "all\n" ) == 0 )
524
557
return true;
@@ -530,7 +563,7 @@ check_db(char *dbname, char *role, char *param_str)
530
563
else if (strcmp (tok , "samegroup\n" ) == 0 ||
531
564
strcmp (tok , "samerole\n" ) == 0 )
532
565
{
533
- if (check_member ( dbname , role ))
566
+ if (is_member ( role , dbname ))
534
567
return true;
535
568
}
536
569
else if (strcmp (tok , dbname ) == 0 )
@@ -981,8 +1014,7 @@ read_pg_database_line(FILE *fp, char *dbname,
981
1014
982
1015
if (feof (fp ))
983
1016
return false;
984
- next_token (fp , buf , sizeof (buf ));
985
- if (!buf [0 ])
1017
+ if (!next_token (fp , buf , sizeof (buf )))
986
1018
return false;
987
1019
if (strlen (buf ) >= NAMEDATALEN )
988
1020
elog (FATAL , "bad data in flat pg_database file" );
@@ -1000,8 +1032,7 @@ read_pg_database_line(FILE *fp, char *dbname,
1000
1032
if (!isdigit ((unsigned char ) buf [0 ]))
1001
1033
elog (FATAL , "bad data in flat pg_database file" );
1002
1034
/* expect EOL next */
1003
- next_token (fp , buf , sizeof (buf ));
1004
- if (buf [0 ])
1035
+ if (next_token (fp , buf , sizeof (buf )))
1005
1036
elog (FATAL , "bad data in flat pg_database file" );
1006
1037
return true;
1007
1038
}
0 commit comments