Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 6561372

Browse files
committed
Fix up problems in write_auth_file and parsing of the auth file.
In particular, make hba.c cope with zero-length tokens, which it never did properly before. Also, enforce rolcanlogin.
1 parent 0eaa36a commit 6561372

File tree

4 files changed

+235
-147
lines changed

4 files changed

+235
-147
lines changed

src/backend/commands/user.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
* $PostgreSQL: pgsql/src/backend/commands/user.c,v 1.153 2005/06/28 19:51:22 tgl Exp $
9+
* $PostgreSQL: pgsql/src/backend/commands/user.c,v 1.154 2005/06/28 22:16:44 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -859,6 +859,9 @@ RenameRole(const char *oldname, const char *newname)
859859
ReleaseSysCache(oldtuple);
860860
heap_close(rel, NoLock);
861861

862+
/*
863+
* Set flag to update flat auth file at commit.
864+
*/
862865
auth_file_update_needed();
863866
}
864867

@@ -902,6 +905,11 @@ GrantRole(GrantRoleStmt *stmt)
902905
stmt->grantee_roles, grantee_ids,
903906
stmt->admin_opt);
904907
}
908+
909+
/*
910+
* Set flag to update flat auth file at commit.
911+
*/
912+
auth_file_update_needed();
905913
}
906914

907915
/*

src/backend/libpq/hba.c

Lines changed: 71 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*
1111
*
1212
* 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 $
1414
*
1515
*-------------------------------------------------------------------------
1616
*/
@@ -96,17 +96,23 @@ pg_isblank(const char c)
9696

9797
/*
9898
* 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
107113
* database names specially, by appending a newline to them.
108114
*/
109-
static void
115+
static bool
110116
next_token(FILE *fp, char *buf, int bufsz)
111117
{
112118
int c;
@@ -125,7 +131,7 @@ next_token(FILE *fp, char *buf, int bufsz)
125131
if (c == EOF || c == '\n')
126132
{
127133
*buf = '\0';
128-
return;
134+
return false;
129135
}
130136

131137
/*
@@ -200,32 +206,35 @@ next_token(FILE *fp, char *buf, int bufsz)
200206
*buf++ = '\n';
201207
*buf = '\0';
202208
}
209+
210+
return (saw_quote || buf > start_buf);
203211
}
204212

205213
/*
206214
* Tokenize file and handle file inclusion and comma lists. We have
207215
* to break apart the commas to expand any file names then
208216
* reconstruct with commas.
209217
*
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.
212219
*/
213220
static char *
214221
next_token_expand(const char *filename, FILE *file)
215222
{
216223
char buf[MAX_TOKEN];
217224
char *comma_str = pstrdup("");
225+
bool got_something = false;
218226
bool trailing_comma;
219227
char *incbuf;
220228
int needed;
221229

222230
do
223231
{
224-
next_token(file, buf, sizeof(buf));
225-
if (!buf[0])
232+
if (!next_token(file, buf, sizeof(buf)))
226233
break;
227234

228-
if (buf[strlen(buf) - 1] == ',')
235+
got_something = true;
236+
237+
if (strlen(buf) > 0 && buf[strlen(buf) - 1] == ',')
229238
{
230239
trailing_comma = true;
231240
buf[strlen(buf) - 1] = '\0';
@@ -249,6 +258,12 @@ next_token_expand(const char *filename, FILE *file)
249258
pfree(incbuf);
250259
} while (trailing_comma);
251260

261+
if (!got_something)
262+
{
263+
pfree(comma_str);
264+
return NULL;
265+
}
266+
252267
return comma_str;
253268
}
254269

@@ -402,7 +417,7 @@ tokenize_file(const char *filename, FILE *file,
402417
buf = next_token_expand(filename, file);
403418

404419
/* add token to list, unless we are at EOL or comment start */
405-
if (buf[0])
420+
if (buf)
406421
{
407422
if (current_line == NIL)
408423
{
@@ -423,8 +438,6 @@ tokenize_file(const char *filename, FILE *file,
423438
current_line = NIL;
424439
/* Advance line number whenever we reach EOL */
425440
line_number++;
426-
/* Don't forget to pfree the next_token_expand result */
427-
pfree(buf);
428441
}
429442
}
430443
}
@@ -462,44 +475,58 @@ get_role_line(const char *role)
462475

463476

464477
/*
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.
466482
*/
467483
static bool
468-
check_member(const char *role, const char *member)
484+
is_member(const char *user, const char *role)
469485
{
470486
List **line;
471-
List **line2;
472487
ListCell *line_item;
473488

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" */
476491

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;
479495

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)))))
482503
{
483-
if (strcmp((char *) lfirst(line_item), member) == 0)
504+
if (strcmp((char *) lfirst(line_item), role) == 0)
484505
return true;
485506
}
486507

487508
return false;
488509
}
489510

490511
/*
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.
492517
*/
493518
static bool
494-
check_role(char *role, char *param_str)
519+
check_role(const char *role, char *param_str)
495520
{
496521
char *tok;
497522

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))
499526
{
500527
if (tok[0] == '+')
501528
{
502-
if (check_member(tok + 1, role))
529+
if (is_member(role, tok + 1))
503530
return true;
504531
}
505532
else if (strcmp(tok, role) == 0 ||
@@ -512,13 +539,19 @@ check_role(char *role, char *param_str)
512539

513540
/*
514541
* 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.
515546
*/
516547
static bool
517-
check_db(char *dbname, char *role, char *param_str)
548+
check_db(const char *dbname, const char *role, char *param_str)
518549
{
519550
char *tok;
520551

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))
522555
{
523556
if (strcmp(tok, "all\n") == 0)
524557
return true;
@@ -530,7 +563,7 @@ check_db(char *dbname, char *role, char *param_str)
530563
else if (strcmp(tok, "samegroup\n") == 0 ||
531564
strcmp(tok, "samerole\n") == 0)
532565
{
533-
if (check_member(dbname, role))
566+
if (is_member(role, dbname))
534567
return true;
535568
}
536569
else if (strcmp(tok, dbname) == 0)
@@ -981,8 +1014,7 @@ read_pg_database_line(FILE *fp, char *dbname,
9811014

9821015
if (feof(fp))
9831016
return false;
984-
next_token(fp, buf, sizeof(buf));
985-
if (!buf[0])
1017+
if (!next_token(fp, buf, sizeof(buf)))
9861018
return false;
9871019
if (strlen(buf) >= NAMEDATALEN)
9881020
elog(FATAL, "bad data in flat pg_database file");
@@ -1000,8 +1032,7 @@ read_pg_database_line(FILE *fp, char *dbname,
10001032
if (!isdigit((unsigned char) buf[0]))
10011033
elog(FATAL, "bad data in flat pg_database file");
10021034
/* expect EOL next */
1003-
next_token(fp, buf, sizeof(buf));
1004-
if (buf[0])
1035+
if (next_token(fp, buf, sizeof(buf)))
10051036
elog(FATAL, "bad data in flat pg_database file");
10061037
return true;
10071038
}

0 commit comments

Comments
 (0)