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

Commit 3f9aec5

Browse files
committed
Flat file cleanup phase 2: make it work for pg_group. The flat group
file now identifies group members by usesysid not name; this avoids needing to depend on SearchSysCache which we can't use during startup. (The old representation was entirely broken anyway, since we did not regenerate the file following RENAME USER.) It's only a 95% solution because if the group membership list is big enough to be toasted out of line, we cannot read it during startup. I think this will do for the moment, until we have time to implement the planned pg_role replacement for pg_group.
1 parent 60b2444 commit 3f9aec5

File tree

3 files changed

+104
-110
lines changed

3 files changed

+104
-110
lines changed

src/backend/libpq/crypt.c

+12-10
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
1010
* Portions Copyright (c) 1994, Regents of the University of California
1111
*
12-
* $PostgreSQL: pgsql/src/backend/libpq/crypt.c,v 1.61 2004/12/31 21:59:50 pgsql Exp $
12+
* $PostgreSQL: pgsql/src/backend/libpq/crypt.c,v 1.62 2005/02/20 04:45:57 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -42,14 +42,18 @@ md5_crypt_verify(const Port *port, const char *user, char *client_pass)
4242
if ((line = get_user_line(user)) == NULL)
4343
return STATUS_ERROR;
4444

45-
/* Skip over username */
46-
token = lnext(list_head(*line));
45+
/* Skip over username and usesysid */
46+
token = list_head(*line);
47+
if (token)
48+
token = lnext(token);
49+
if (token)
50+
token = lnext(token);
4751
if (token)
4852
{
49-
shadow_pass = lfirst(token);
53+
shadow_pass = (char *) lfirst(token);
5054
token = lnext(token);
5155
if (token)
52-
valuntil = lfirst(token);
56+
valuntil = (char *) lfirst(token);
5357
}
5458

5559
if (shadow_pass == NULL || *shadow_pass == '\0')
@@ -142,16 +146,14 @@ md5_crypt_verify(const Port *port, const char *user, char *client_pass)
142146
/*
143147
* Password OK, now check to be sure we are not past valuntil
144148
*/
145-
AbsoluteTime vuntil,
146-
current;
149+
AbsoluteTime vuntil;
147150

148-
if (!valuntil)
151+
if (valuntil == NULL || *valuntil == '\0')
149152
vuntil = INVALID_ABSTIME;
150153
else
151154
vuntil = DatumGetAbsoluteTime(DirectFunctionCall1(abstimein,
152155
CStringGetDatum(valuntil)));
153-
current = GetCurrentAbsoluteTime();
154-
if (vuntil != INVALID_ABSTIME && vuntil < current)
156+
if (vuntil != INVALID_ABSTIME && vuntil < GetCurrentAbsoluteTime())
155157
retval = STATUS_ERROR;
156158
else
157159
retval = STATUS_OK;

src/backend/libpq/hba.c

+16-11
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.138 2005/02/20 02:21:40 tgl Exp $
13+
* $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.139 2005/02/20 04:45:57 tgl Exp $
1414
*
1515
*-------------------------------------------------------------------------
1616
*/
@@ -498,23 +498,28 @@ get_user_line(const char *user)
498498

499499

500500
/*
501-
* Check group for a specific user.
501+
* Does user belong to group?
502502
*/
503503
static bool
504504
check_group(char *group, char *user)
505505
{
506506
List **line;
507+
ListCell *line_item;
508+
char *usesysid;
507509

508-
if ((line = get_group_line(group)) != NULL)
509-
{
510-
ListCell *line_item;
510+
if ((line = get_user_line(user)) == NULL)
511+
return false; /* if user not exist, say "no" */
512+
/* Skip over username to get usesysid */
513+
usesysid = (char *) lsecond(*line);
511514

512-
/* skip over the group name */
513-
for_each_cell(line_item, lnext(list_head(*line)))
514-
{
515-
if (strcmp(lfirst(line_item), user) == 0)
516-
return true;
517-
}
515+
if ((line = get_group_line(group)) == NULL)
516+
return false; /* if group not exist, say "no" */
517+
518+
/* skip over the group name, examine all the member usesysid's */
519+
for_each_cell(line_item, lnext(list_head(*line)))
520+
{
521+
if (strcmp((char *) lfirst(line_item), usesysid) == 0)
522+
return true;
518523
}
519524

520525
return false;

src/backend/utils/init/flatfiles.c

+76-89
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
2323
* Portions Copyright (c) 1994, Regents of the University of California
2424
*
25-
* $PostgreSQL: pgsql/src/backend/utils/init/flatfiles.c,v 1.1 2005/02/20 02:22:00 tgl Exp $
25+
* $PostgreSQL: pgsql/src/backend/utils/init/flatfiles.c,v 1.2 2005/02/20 04:45:59 tgl Exp $
2626
*
2727
*-------------------------------------------------------------------------
2828
*/
@@ -278,7 +278,7 @@ write_database_file(Relation drel)
278278
}
279279

280280
/*
281-
* File format is: "dbname" oid frozenxid
281+
* The file format is: "dbname" oid frozenxid
282282
*
283283
* The xid is not needed for backend startup, but may be of use
284284
* for forensic purposes.
@@ -317,13 +317,6 @@ write_database_file(Relation drel)
317317

318318
/*
319319
* write_group_file: update the flat group file
320-
*
321-
* XXX this will never be able to work during system bootstrap: we don't
322-
* have either TOAST support or SysCache support. Need to redefine both
323-
* the catalog and file contents to fix this completely. In the short term
324-
* we can handle everything except an out-of-line-toasted grolist, if we
325-
* change the flat file definition to store numeric sysids instead of
326-
* user names.
327320
*/
328321
static void
329322
write_group_file(Relation grel)
@@ -335,7 +328,6 @@ write_group_file(Relation grel)
335328
mode_t oumask;
336329
HeapScanDesc scan;
337330
HeapTuple tuple;
338-
TupleDesc dsc = RelationGetDescr(grel);
339331

340332
/*
341333
* Create a temporary filename to be renamed later. This prevents the
@@ -364,22 +356,19 @@ write_group_file(Relation grel)
364356
scan = heap_beginscan(grel, SnapshotSelf, 0, NULL);
365357
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
366358
{
367-
Datum datum,
368-
grolist_datum;
369-
bool isnull;
359+
Form_pg_group grpform = (Form_pg_group) GETSTRUCT(tuple);
360+
HeapTupleHeader tup = tuple->t_data;
361+
char *tp; /* ptr to tuple data */
362+
long off; /* offset in tuple data */
363+
bits8 *bp = tup->t_bits; /* ptr to null bitmask in tuple */
364+
Datum datum;
370365
char *groname;
371366
IdList *grolist_p;
372367
AclId *aidp;
373368
int i,
374369
num;
375-
char *usename;
376-
bool first_user = true;
377370

378-
datum = heap_getattr(tuple, Anum_pg_group_groname, dsc, &isnull);
379-
/* ignore NULL groupnames --- shouldn't happen */
380-
if (isnull)
381-
continue;
382-
groname = NameStr(*DatumGetName(datum));
371+
groname = NameStr(grpform->groname);
383372

384373
/*
385374
* Check for illegal characters in the group name.
@@ -391,57 +380,58 @@ write_group_file(Relation grel)
391380
continue;
392381
}
393382

394-
grolist_datum = heap_getattr(tuple, Anum_pg_group_grolist, dsc, &isnull);
395-
/* Ignore NULL group lists */
396-
if (isnull)
383+
/*
384+
* We can't use heap_getattr() here because during startup we will
385+
* not have any tupdesc for pg_group. Fortunately it's not too
386+
* hard to work around this. grolist is the first possibly-null
387+
* field so we can compute its offset directly.
388+
*/
389+
tp = (char *) tup + tup->t_hoff;
390+
off = offsetof(FormData_pg_group, grolist);
391+
392+
if (HeapTupleHasNulls(tuple) &&
393+
att_isnull(Anum_pg_group_grolist - 1, bp))
394+
{
395+
/* grolist is null, so we can ignore this group */
396+
continue;
397+
}
398+
399+
/* assume grolist is pass-by-ref */
400+
datum = PointerGetDatum(tp + off);
401+
402+
/*
403+
* We can't currently support out-of-line toasted group lists in
404+
* startup mode (the tuptoaster won't work). This sucks, but it
405+
* should be something of a corner case. Live with it until we
406+
* can redesign pg_group.
407+
*
408+
* Detect startup mode by noting whether we got a tupdesc.
409+
*/
410+
if (VARATT_IS_EXTERNAL(DatumGetPointer(datum)) &&
411+
RelationGetDescr(grel) == NULL)
397412
continue;
398413

399414
/* be sure the IdList is not toasted */
400-
grolist_p = DatumGetIdListP(grolist_datum);
415+
grolist_p = DatumGetIdListP(datum);
401416

402-
/* scan grolist */
403-
num = IDLIST_NUM(grolist_p);
417+
/*
418+
* The file format is: "groupname" usesysid1 usesysid2 ...
419+
*
420+
* We ignore groups that have no members.
421+
*/
404422
aidp = IDLIST_DAT(grolist_p);
405-
for (i = 0; i < num; ++i)
423+
num = IDLIST_NUM(grolist_p);
424+
if (num > 0)
406425
{
407-
tuple = SearchSysCache(SHADOWSYSID,
408-
PointerGetDatum(aidp[i]),
409-
0, 0, 0);
410-
if (HeapTupleIsValid(tuple))
411-
{
412-
usename = NameStr(((Form_pg_shadow) GETSTRUCT(tuple))->usename);
413-
414-
/*
415-
* Check for illegal characters in the user name.
416-
*/
417-
if (!name_okay(usename))
418-
{
419-
ereport(LOG,
420-
(errmsg("invalid user name \"%s\"", usename)));
421-
continue;
422-
}
423-
424-
/*
425-
* File format is: "groupname" "user1" "user2" "user3"
426-
*/
427-
if (first_user)
428-
{
429-
fputs_quote(groname, fp);
430-
fputs("\t", fp);
431-
first_user = false;
432-
}
433-
else
434-
fputs(" ", fp);
435-
436-
fputs_quote(usename, fp);
437-
438-
ReleaseSysCache(tuple);
439-
}
440-
}
441-
if (!first_user)
426+
fputs_quote(groname, fp);
427+
fprintf(fp, "\t%u", aidp[0]);
428+
for (i = 1; i < num; ++i)
429+
fprintf(fp, " %u", aidp[i]);
442430
fputs("\n", fp);
431+
}
432+
443433
/* if IdList was toasted, free detoasted copy */
444-
if ((Pointer) grolist_p != DatumGetPointer(grolist_datum))
434+
if ((Pointer) grolist_p != DatumGetPointer(datum))
445435
pfree(grolist_p);
446436
}
447437
heap_endscan(scan);
@@ -517,8 +507,10 @@ write_user_file(Relation urel)
517507
char *usename,
518508
*passwd,
519509
*valuntil;
510+
AclId usesysid;
520511

521512
usename = NameStr(pwform->usename);
513+
usesysid = pwform->usesysid;
522514

523515
/*
524516
* We can't use heap_getattr() here because during startup we will
@@ -532,30 +524,26 @@ write_user_file(Relation urel)
532524
if (HeapTupleHasNulls(tuple) &&
533525
att_isnull(Anum_pg_shadow_passwd - 1, bp))
534526
{
535-
/*
536-
* It can be argued that people having a null password shouldn't
537-
* be allowed to connect under password authentication, because
538-
* they need to have a password set up first. If you think
539-
* assuming an empty password in that case is better, change this
540-
* logic to look something like the code for valuntil.
541-
*/
542-
continue;
527+
/* passwd is null, emit as an empty string */
528+
passwd = pstrdup("");
543529
}
530+
else
531+
{
532+
/* assume passwd is pass-by-ref */
533+
datum = PointerGetDatum(tp + off);
544534

545-
/* assume passwd is pass-by-ref */
546-
datum = PointerGetDatum(tp + off);
547-
548-
/*
549-
* The password probably shouldn't ever be out-of-line toasted;
550-
* if it is, ignore it, since we can't handle that in startup mode.
551-
*/
552-
if (VARATT_IS_EXTERNAL(DatumGetPointer(datum)))
553-
continue;
554-
555-
passwd = DatumGetCString(DirectFunctionCall1(textout, datum));
535+
/*
536+
* The password probably shouldn't ever be out-of-line toasted;
537+
* if it is, ignore it, since we can't handle that in startup mode.
538+
*/
539+
if (VARATT_IS_EXTERNAL(DatumGetPointer(datum)))
540+
passwd = pstrdup("");
541+
else
542+
passwd = DatumGetCString(DirectFunctionCall1(textout, datum));
556543

557-
/* assume passwd has attlen -1 */
558-
off = att_addlength(off, -1, tp + off);
544+
/* assume passwd has attlen -1 */
545+
off = att_addlength(off, -1, tp + off);
546+
}
559547

560548
if (HeapTupleHasNulls(tuple) &&
561549
att_isnull(Anum_pg_shadow_valuntil - 1, bp))
@@ -588,8 +576,11 @@ write_user_file(Relation urel)
588576
continue;
589577
}
590578

579+
/*
580+
* The file format is: "usename" usesysid "passwd" "valuntil"
581+
*/
591582
fputs_quote(usename, fp);
592-
fputs(" ", fp);
583+
fprintf(fp, " %u ", usesysid);
593584
fputs_quote(passwd, fp);
594585
fputs(" ", fp);
595586
fputs_quote(valuntil, fp);
@@ -664,17 +655,13 @@ BuildFlatFiles(bool database_only)
664655

665656
if (!database_only)
666657
{
667-
#ifdef NOT_YET
668-
/* XXX doesn't work yet for reasons stated above */
669-
670658
/* hard-wired path to pg_group */
671659
rnode.spcNode = GLOBALTABLESPACE_OID;
672660
rnode.dbNode = 0;
673661
rnode.relNode = RelOid_pg_group;
674662

675663
rel = XLogOpenRelation(true, 0, rnode);
676664
write_group_file(rel);
677-
#endif
678665

679666
/* hard-wired path to pg_shadow */
680667
rnode.spcNode = GLOBALTABLESPACE_OID;

0 commit comments

Comments
 (0)