88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.41 2000/10/02 04:49:28 tgl Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.42 2000/11/03 19:02:18 tgl Exp $
1212 *
1313 * NOTES
1414 * See acl.h.
@@ -185,41 +185,40 @@ get_groname(AclId grosysid)
185185static bool
186186in_group (AclId uid ,AclId gid )
187187{
188- Relation relation ;
189188HeapTuple tuple ;
190- Acl * tmp ;
189+ Datum att ;
190+ bool isNull ;
191+ IdList * tmp ;
192+ AclId * aidp ;
191193int i ,
192194num ;
193- AclId * aidp ;
194- bool found = false;
195195
196- relation = heap_openr (GroupRelationName ,RowExclusiveLock );
197196tuple = SearchSysCacheTuple (GROSYSID ,
198197ObjectIdGetDatum (gid ),
1991980 ,0 ,0 );
200- if (HeapTupleIsValid (tuple )&&
201- !heap_attisnull (tuple ,Anum_pg_group_grolist ))
199+ if (HeapTupleIsValid (tuple ))
202200{
203- tmp = (IdList * )heap_getattr (tuple ,
204- Anum_pg_group_grolist ,
205- RelationGetDescr (relation ),
206- (bool * )NULL );
207- /* be sure the IdList is not toasted */
208- tmp = DatumGetIdListP (PointerGetDatum (tmp ));
209- /* XXX make me a function */
210- num = IDLIST_NUM (tmp );
211- aidp = IDLIST_DAT (tmp );
212- for (i = 0 ;i < num ;++ i )
213- if (aidp [i ]== uid )
201+ att = SysCacheGetAttr (GROSYSID ,
202+ tuple ,
203+ Anum_pg_group_grolist ,
204+ & isNull );
205+ if (!isNull )
206+ {
207+ /* be sure the IdList is not toasted */
208+ tmp = DatumGetIdListP (att );
209+ /* scan it */
210+ num = IDLIST_NUM (tmp );
211+ aidp = IDLIST_DAT (tmp );
212+ for (i = 0 ;i < num ;++ i )
214213{
215- found = true;
216- break ;
214+ if ( aidp [ i ] == uid )
215+ return true ;
217216}
217+ }
218218}
219219else
220- elog (NOTICE ,"in_group: group %d not found" ,gid );
221- heap_close (relation ,RowExclusiveLock );
222- return found ;
220+ elog (NOTICE ,"in_group: group %u not found" ,gid );
221+ return false;
223222}
224223
225224/*
@@ -230,11 +229,10 @@ in_group(AclId uid, AclId gid)
230229static int32
231230aclcheck (char * relname ,Acl * acl ,AclId id ,AclIdType idtype ,AclMode mode )
232231{
233- unsigned i ;
234232AclItem * aip ,
235233* aidat ;
236- unsigned num ,
237- found_group ;
234+ int i ,
235+ num ;
238236
239237/*
240238 * If ACL is null, default to "OK" --- this should not happen,
@@ -252,52 +250,54 @@ aclcheck(char *relname, Acl *acl, AclId id, AclIdType idtype, AclMode mode)
252250/*
253251 * We'll treat the empty ACL like that, too, although this is more
254252 * like an error (i.e., you manually blew away your ACL array) -- the
255- * system never creates an empty ACL.
253+ * system never creates an empty ACL, since there must always be
254+ * a "world" entry in the first slot.
256255 */
257256if (num < 1 )
258257{
259258elog (DEBUG ,"aclcheck: zero-length ACL, returning 1" );
260259return ACLCHECK_OK ;
261260}
261+ Assert (aidat -> ai_idtype == ACL_IDTYPE_WORLD );
262262
263263switch (idtype )
264264{
265265case ACL_IDTYPE_UID :
266+ /* Look for exact match to user */
266267for (i = 1 ,aip = aidat + 1 ;/* skip world entry */
267268i < num && aip -> ai_idtype == ACL_IDTYPE_UID ;
268269++ i ,++ aip )
269270{
270271if (aip -> ai_id == id )
271272{
272273#ifdef ACLDEBUG_TRACE
273- elog (DEBUG ,"aclcheck: found%d /%d" ,
274+ elog (DEBUG ,"aclcheck: founduser %u /%d" ,
274275aip -> ai_id ,aip -> ai_mode );
275276#endif
276277return (aip -> ai_mode & mode ) ?ACLCHECK_OK :ACLCHECK_NO_PRIV ;
277278}
278279}
279- for (found_group = 0 ;
280+ /* See if he has the permission via any group */
281+ for (;
280282i < num && aip -> ai_idtype == ACL_IDTYPE_GID ;
281283++ i ,++ aip )
282284{
283- if (in_group ( id , aip -> ai_id ) )
285+ if (aip -> ai_mode & mode )
284286{
285- if (aip -> ai_mode & mode )
287+ if (in_group ( id , aip -> ai_id ) )
286288{
287- found_group = 1 ;
288- break ;
289- }
290- }
291- }
292- if (found_group )
293- {
294289#ifdef ACLDEBUG_TRACE
295- elog (DEBUG ,"aclcheck: all groups ok" );
290+ elog (DEBUG ,"aclcheck: found group %u/%d" ,
291+ aip -> ai_id ,aip -> ai_mode );
296292#endif
297- return ACLCHECK_OK ;
293+ return ACLCHECK_OK ;
294+ }
295+ }
298296}
297+ /* Else, look to the world entry */
299298break ;
300299case ACL_IDTYPE_GID :
300+ /* Look for this group ID */
301301for (i = 1 ,aip = aidat + 1 ;/* skip world entry and
302302 * UIDs */
303303i < num && aip -> ai_idtype == ACL_IDTYPE_UID ;
@@ -310,14 +310,16 @@ aclcheck(char *relname, Acl *acl, AclId id, AclIdType idtype, AclMode mode)
310310if (aip -> ai_id == id )
311311{
312312#ifdef ACLDEBUG_TRACE
313- elog (DEBUG ,"aclcheck: found%d /%d" ,
313+ elog (DEBUG ,"aclcheck: foundgroup %u /%d" ,
314314aip -> ai_id ,aip -> ai_mode );
315315#endif
316316return (aip -> ai_mode & mode ) ?ACLCHECK_OK :ACLCHECK_NO_PRIV ;
317317}
318318}
319+ /* Else, look to the world entry */
319320break ;
320321case ACL_IDTYPE_WORLD :
322+ /* Only check the world entry */
321323break ;
322324default :
323325elog (ERROR ,"aclcheck: bogus ACL id type: %d" ,idtype );