Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitfb97d2b

Browse files
committed
Correct permissions-checking bugs associated with ancient decision to
copy PUBLIC access rights into each newly created ACL entry. Insteadtreat each ACL entry as independent flags. Also clean up some uglinessin acl.h API.
1 parentcdd230d commitfb97d2b

File tree

5 files changed

+162
-105
lines changed

5 files changed

+162
-105
lines changed

‎src/backend/catalog/aclchk.c

Lines changed: 134 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.48 2001/05/27 09:59:28 petere Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.49 2001/06/05 19:34:56 tgl Exp $
1212
*
1313
* NOTES
1414
* See acl.h.
@@ -33,8 +33,7 @@
3333
#include"utils/acl.h"
3434
#include"utils/syscache.h"
3535

36-
staticint32aclcheck(char*relname,Acl*acl,AclIdid,
37-
AclIdTypeidtype,AclModemode);
36+
staticint32aclcheck(Acl*acl,AclIdid,AclIdTypeidtype,AclModemode);
3837

3938
/* warning messages, now more explicit. */
4039
/* MUST correspond to the order of the ACLCHK_* result codes in acl.h. */
@@ -192,14 +191,17 @@ get_groname(AclId grosysid)
192191
returnname;
193192
}
194193

194+
/*
195+
* Is user a member of group?
196+
*/
195197
staticbool
196198
in_group(AclIduid,AclIdgid)
197199
{
198200
boolresult= false;
199201
HeapTupletuple;
200202
Datumatt;
201203
boolisNull;
202-
IdList*tmp;
204+
IdList*glist;
203205
AclId*aidp;
204206
inti,
205207
num;
@@ -216,10 +218,10 @@ in_group(AclId uid, AclId gid)
216218
if (!isNull)
217219
{
218220
/* be sure the IdList is not toasted */
219-
tmp=DatumGetIdListP(att);
221+
glist=DatumGetIdListP(att);
220222
/* scan it */
221-
num=IDLIST_NUM(tmp);
222-
aidp=IDLIST_DAT(tmp);
223+
num=IDLIST_NUM(glist);
224+
aidp=IDLIST_DAT(glist);
223225
for (i=0;i<num;++i)
224226
{
225227
if (aidp[i]==uid)
@@ -228,6 +230,9 @@ in_group(AclId uid, AclId gid)
228230
break;
229231
}
230232
}
233+
/* if IdList was toasted, free detoasted copy */
234+
if ((Pointer)glist!=DatumGetPointer(att))
235+
pfree(glist);
231236
}
232237
ReleaseSysCache(tuple);
233238
}
@@ -238,11 +243,15 @@ in_group(AclId uid, AclId gid)
238243

239244
/*
240245
* aclcheck
241-
* Returns 1 if the 'id' of type 'idtype' has ACL entries in 'acl' to satisfy
242-
* any one of the requirements of 'mode'. Returns 0 otherwise.
246+
*
247+
* Returns ACLCHECK_OK if the 'id' of type 'idtype' has ACL entries in 'acl'
248+
* to satisfy any one of the requirements of 'mode'. Returns an appropriate
249+
* ACLCHECK_* error code otherwise.
250+
*
251+
* The ACL list is expected to be sorted in standard order.
243252
*/
244253
staticint32
245-
aclcheck(char*relname,Acl*acl,AclIdid,AclIdTypeidtype,AclModemode)
254+
aclcheck(Acl*acl,AclIdid,AclIdTypeidtype,AclModemode)
246255
{
247256
AclItem*aip,
248257
*aidat;
@@ -255,7 +264,7 @@ aclcheck(char *relname, Acl *acl, AclId id, AclIdType idtype, AclMode mode)
255264
*/
256265
if (!acl)
257266
{
258-
elog(DEBUG,"aclcheck: null ACL, returning1");
267+
elog(DEBUG,"aclcheck: null ACL, returningOK");
259268
returnACLCHECK_OK;
260269
}
261270

@@ -270,15 +279,28 @@ aclcheck(char *relname, Acl *acl, AclId id, AclIdType idtype, AclMode mode)
270279
*/
271280
if (num<1)
272281
{
273-
elog(DEBUG,"aclcheck: zero-length ACL, returning 1");
282+
elog(DEBUG,"aclcheck: zero-length ACL, returning OK");
283+
returnACLCHECK_OK;
284+
}
285+
286+
/*
287+
* "World" rights are applicable regardless of the passed-in ID,
288+
* and since they're much the cheapest to check, check 'em first.
289+
*/
290+
if (aidat->ai_idtype!=ACL_IDTYPE_WORLD)
291+
elog(ERROR,"aclcheck: first entry in ACL is not 'world' entry");
292+
if (aidat->ai_mode&mode)
293+
{
294+
#ifdefACLDEBUG
295+
elog(DEBUG,"aclcheck: using world=%d",aidat->ai_mode);
296+
#endif
274297
returnACLCHECK_OK;
275298
}
276-
Assert(aidat->ai_idtype==ACL_IDTYPE_WORLD);
277299

278300
switch (idtype)
279301
{
280302
caseACL_IDTYPE_UID:
281-
/*Look for exact match to user */
303+
/*See if permission is granted directly to user */
282304
for (i=1,aip=aidat+1;/* skip world entry */
283305
i<num&&aip->ai_idtype==ACL_IDTYPE_UID;
284306
++i,++aip)
@@ -289,7 +311,8 @@ aclcheck(char *relname, Acl *acl, AclId id, AclIdType idtype, AclMode mode)
289311
elog(DEBUG,"aclcheck: found user %u/%d",
290312
aip->ai_id,aip->ai_mode);
291313
#endif
292-
return (aip->ai_mode&mode) ?ACLCHECK_OK :ACLCHECK_NO_PRIV;
314+
if (aip->ai_mode&mode)
315+
returnACLCHECK_OK;
293316
}
294317
}
295318
/* See if he has the permission via any group */
@@ -309,15 +332,13 @@ aclcheck(char *relname, Acl *acl, AclId id, AclIdType idtype, AclMode mode)
309332
}
310333
}
311334
}
312-
/* Else, look to the world entry */
313335
break;
314336
caseACL_IDTYPE_GID:
315337
/* Look for this group ID */
316-
for (i=1,aip=aidat+1;/* skip world entry and
317-
* UIDs */
338+
for (i=1,aip=aidat+1;/* skip world entry */
318339
i<num&&aip->ai_idtype==ACL_IDTYPE_UID;
319340
++i,++aip)
320-
;
341+
/* skip UID entry */;
321342
for (;
322343
i<num&&aip->ai_idtype==ACL_IDTYPE_GID;
323344
++i,++aip)
@@ -328,10 +349,10 @@ aclcheck(char *relname, Acl *acl, AclId id, AclIdType idtype, AclMode mode)
328349
elog(DEBUG,"aclcheck: found group %u/%d",
329350
aip->ai_id,aip->ai_mode);
330351
#endif
331-
return (aip->ai_mode&mode) ?ACLCHECK_OK :ACLCHECK_NO_PRIV;
352+
if (aip->ai_mode&mode)
353+
returnACLCHECK_OK;
332354
}
333355
}
334-
/* Else, look to the world entry */
335356
break;
336357
caseACL_IDTYPE_WORLD:
337358
/* Only check the world entry */
@@ -341,12 +362,15 @@ aclcheck(char *relname, Acl *acl, AclId id, AclIdType idtype, AclMode mode)
341362
break;
342363
}
343364

344-
#ifdefACLDEBUG
345-
elog(DEBUG,"aclcheck: using world=%d",aidat->ai_mode);
346-
#endif
347-
return (aidat->ai_mode&mode) ?ACLCHECK_OK :ACLCHECK_NO_PRIV;
365+
/* If get here, he doesn't have the privilege nohow */
366+
returnACLCHECK_NO_PRIV;
348367
}
349368

369+
/*
370+
* Exported routine for checking a user's access privileges to a table
371+
*
372+
* Returns an ACLCHECK_* result code.
373+
*/
350374
int32
351375
pg_aclcheck(char*relname,Oiduserid,AclModemode)
352376
{
@@ -357,6 +381,9 @@ pg_aclcheck(char *relname, Oid userid, AclMode mode)
357381
boolisNull;
358382
Acl*acl;
359383

384+
/*
385+
* Validate userid, find out if he is superuser
386+
*/
360387
tuple=SearchSysCache(SHADOWSYSID,
361388
ObjectIdGetDatum(userid),
362389
0,0,0);
@@ -371,13 +398,15 @@ pg_aclcheck(char *relname, Oid userid, AclMode mode)
371398
* pg_shadow.usecatupd is set.(This is to let superusers protect
372399
* themselves from themselves.)
373400
*/
374-
if (((mode&ACL_UPDATE)|| (mode&ACL_INSERT)|| (mode&ACL_DELETE))&&
401+
if ((mode&(ACL_INSERT |ACL_UPDATE |ACL_DELETE))&&
375402
!allowSystemTableMods&&IsSystemRelationName(relname)&&
376403
strncmp(relname,"pg_temp.",strlen("pg_temp."))!=0&&
377404
!((Form_pg_shadow)GETSTRUCT(tuple))->usecatupd)
378405
{
406+
#ifdefACLDEBUG
379407
elog(DEBUG,"pg_aclcheck: catalog update to \"%s\": permission denied",
380408
relname);
409+
#endif
381410
ReleaseSysCache(tuple);
382411
returnACLCHECK_NO_PRIV;
383412
}
@@ -416,25 +445,35 @@ pg_aclcheck(char *relname, Oid userid, AclMode mode)
416445

417446
ownerId= ((Form_pg_class)GETSTRUCT(tuple))->relowner;
418447
acl=acldefault(relname,ownerId);
448+
aclDatum= (Datum)0;
419449
}
420450
else
421451
{
422-
/*get a detoasted copy of therel's ACL */
423-
acl=DatumGetAclPCopy(aclDatum);
452+
/*detoastrel's ACL if necessary */
453+
acl=DatumGetAclP(aclDatum);
424454
}
425455

426-
result=aclcheck(relname,acl,userid, (AclIdType)ACL_IDTYPE_UID,mode);
456+
result=aclcheck(acl,userid, (AclIdType)ACL_IDTYPE_UID,mode);
427457

428-
if (acl)
458+
/* if we have a detoasted copy, free it */
459+
if (acl&& (Pointer)acl!=DatumGetPointer(aclDatum))
429460
pfree(acl);
461+
430462
ReleaseSysCache(tuple);
431463

432464
returnresult;
433465
}
434466

435-
int32
467+
/*
468+
* Check ownership of an object identified by name (which will be looked
469+
* up in the system cache identified by cacheid).
470+
*
471+
* Returns true if userid owns the item, or should be allowed to modify
472+
* the item as if he owned it.
473+
*/
474+
bool
436475
pg_ownercheck(Oiduserid,
437-
constchar*value,
476+
constchar*name,
438477
intcacheid)
439478
{
440479
HeapTupletuple;
@@ -459,39 +498,27 @@ pg_ownercheck(Oid userid,
459498
usename);
460499
#endif
461500
ReleaseSysCache(tuple);
462-
return1;
501+
returntrue;
463502
}
464503

465504
ReleaseSysCache(tuple);
466505
/* caution: usename is inaccessible beyond this point... */
467506

468507
tuple=SearchSysCache(cacheid,
469-
PointerGetDatum(value),
508+
PointerGetDatum(name),
470509
0,0,0);
471510
switch (cacheid)
472511
{
473-
caseOPEROID:
474-
if (!HeapTupleIsValid(tuple))
475-
elog(ERROR,"pg_ownercheck: operator %ld not found",
476-
PointerGetDatum(value));
477-
owner_id= ((Form_pg_operator)GETSTRUCT(tuple))->oprowner;
478-
break;
479-
casePROCNAME:
480-
if (!HeapTupleIsValid(tuple))
481-
elog(ERROR,"pg_ownercheck: function \"%s\" not found",
482-
value);
483-
owner_id= ((Form_pg_proc)GETSTRUCT(tuple))->proowner;
484-
break;
485512
caseRELNAME:
486513
if (!HeapTupleIsValid(tuple))
487514
elog(ERROR,"pg_ownercheck: class \"%s\" not found",
488-
value);
515+
name);
489516
owner_id= ((Form_pg_class)GETSTRUCT(tuple))->relowner;
490517
break;
491518
caseTYPENAME:
492519
if (!HeapTupleIsValid(tuple))
493520
elog(ERROR,"pg_ownercheck: type \"%s\" not found",
494-
value);
521+
name);
495522
owner_id= ((Form_pg_type)GETSTRUCT(tuple))->typowner;
496523
break;
497524
default:
@@ -505,7 +532,58 @@ pg_ownercheck(Oid userid,
505532
returnuserid==owner_id;
506533
}
507534

508-
int32
535+
/*
536+
* Ownership check for an operator (specified by OID).
537+
*/
538+
bool
539+
pg_oper_ownercheck(Oiduserid,Oidoprid)
540+
{
541+
HeapTupletuple;
542+
AclIdowner_id;
543+
char*usename;
544+
545+
tuple=SearchSysCache(SHADOWSYSID,
546+
ObjectIdGetDatum(userid),
547+
0,0,0);
548+
if (!HeapTupleIsValid(tuple))
549+
elog(ERROR,"pg_oper_ownercheck: invalid user id %u",
550+
(unsigned)userid);
551+
usename=NameStr(((Form_pg_shadow)GETSTRUCT(tuple))->usename);
552+
553+
/*
554+
* Superusers bypass all permission-checking.
555+
*/
556+
if (((Form_pg_shadow)GETSTRUCT(tuple))->usesuper)
557+
{
558+
#ifdefACLDEBUG
559+
elog(DEBUG,"pg_ownercheck: user \"%s\" is superuser",
560+
usename);
561+
#endif
562+
ReleaseSysCache(tuple);
563+
return true;
564+
}
565+
566+
ReleaseSysCache(tuple);
567+
/* caution: usename is inaccessible beyond this point... */
568+
569+
tuple=SearchSysCache(OPEROID,
570+
ObjectIdGetDatum(oprid),
571+
0,0,0);
572+
if (!HeapTupleIsValid(tuple))
573+
elog(ERROR,"pg_ownercheck: operator %u not found",
574+
oprid);
575+
576+
owner_id= ((Form_pg_operator)GETSTRUCT(tuple))->oprowner;
577+
578+
ReleaseSysCache(tuple);
579+
580+
returnuserid==owner_id;
581+
}
582+
583+
/*
584+
* Ownership check for a function (specified by name and argument types).
585+
*/
586+
bool
509587
pg_func_ownercheck(Oiduserid,
510588
char*funcname,
511589
intnargs,
@@ -533,7 +611,7 @@ pg_func_ownercheck(Oid userid,
533611
usename);
534612
#endif
535613
ReleaseSysCache(tuple);
536-
return1;
614+
returntrue;
537615
}
538616

539617
ReleaseSysCache(tuple);
@@ -554,7 +632,11 @@ pg_func_ownercheck(Oid userid,
554632
returnuserid==owner_id;
555633
}
556634

557-
int32
635+
/*
636+
* Ownership check for an aggregate function (specified by name and
637+
* argument type).
638+
*/
639+
bool
558640
pg_aggr_ownercheck(Oiduserid,
559641
char*aggname,
560642
OidbasetypeID)
@@ -581,7 +663,7 @@ pg_aggr_ownercheck(Oid userid,
581663
usename);
582664
#endif
583665
ReleaseSysCache(tuple);
584-
return1;
666+
returntrue;
585667
}
586668

587669
ReleaseSysCache(tuple);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp