e5ec318de94435f60fb82c2e9f71765928daf713
[py-rsbac] / rsbac / acl.py
1 # -*- coding:utf-8 -*-
2
3 # py-rsbac - RSBAC Python bindings
4 # Copyright (C) 2006  Frederic Jolliton <pyrsbac@tuxee.net>
5
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
20 __all__ = [ 'Group' , 'groups' ]
21
22 def export( o ) :
23     if not isinstance( o , basestring ) :
24         name = o.__name__
25     else :
26         name , o = o , None
27     if name in __all__ :
28         raise ImportError , 'duplicate name %r in module %r' % ( name , __name__ )
29     __all__.append( name )
30     return o
31
32 from ctypes import byref, pointer
33
34 from rsbac import headers, lib, transaction
35 from rsbac._data import AclRequestVector
36 from rsbac.errors import raiseIfError, Error
37 from rsbac._utils import fetch, intToTtl, ttlToInt
38
39 g_aclSyscallArg = headers.rsbac_acl_syscall_arg_t()
40 g_aclSyscallArgRef = byref( g_aclSyscallArg )
41
42 g_aclSyscallByNameArg = headers.rsbac_acl_syscall_n_arg_t()
43 g_aclSyscallByNameArgRef = byref( g_aclSyscallByNameArg )
44
45 # for acl_remove_user
46 g_targetId = headers.rsbac_target_id_t()
47
48 def _acl_preset( target , tid , subjectType , subjectId , rights , ttl ) :
49     g_aclSyscallArg.target = target
50     g_aclSyscallArg.tid = tid
51     g_aclSyscallArg.subj_type = subjectType
52     g_aclSyscallArg.subj_id = subjectId
53     g_aclSyscallArg.rights = rights
54     g_aclSyscallArg.ttl = ttl
55     return g_aclSyscallArgRef
56
57 def _acl_preset_n( target , name , subjectType , subjectId , rights , ttl ) :
58     g_aclSyscallByNameArg.target = target
59     g_aclSyscallByNameArg.name = name
60     g_aclSyscallByNameArg.subj_type = subjectType
61     g_aclSyscallByNameArg.subj_id = subjectId
62     g_aclSyscallByNameArg.rights = rights
63     g_aclSyscallByNameArg.ttl = ttl
64     return g_aclSyscallByNameArgRef
65
66 def _to_acl_subject( object ) :
67     from rsbac.objects import User
68     if isinstance( object , Role ) :
69         return headers.ACLS_ROLE , object._role
70     elif isinstance( object , User ) :
71         return headers.ACLS_USER , object.uid
72     elif isinstance( object , Group ) :
73         return headers.ACLS_GROUP , object._id
74     else :
75         raise RuntimeError , 'unexpected ACL subject of type %r' % ( object.__class__ , )
76
77 def _from_acl_subject( type , id ) :
78     if type == headers.ACLS_USER :
79         return User( id )
80     elif type == headers.ACLS_ROLE :
81         return Role( id )
82     elif type == headers.ACLS_GROUP :
83         return Group( id )
84     else :
85         raise RuntimeError , 'unexpected subject type %r' % ( type , )
86
87 #
88 # set_acl_entry
89 #
90
91 def setAclEntryById( target , subject , rights , ttl = None ) :
92     st , si = _to_acl_subject( subject )
93     raiseIfError( lib.rsbac_acl( transaction._t ,
94                                  headers.ACLC_set_acl_entry ,
95                                  _acl_preset( target.type , target._id._obj ,
96                                               st , si ,
97                                               int( rights ) , ttlToInt( ttl ) ) ) )
98
99 def setAclEntryByName( target , subject , rights , ttl = None ) :
100     st , si = _to_acl_subject( subject )
101     raiseIfError( lib.rsbac_acl_n( transaction._t ,
102                                    headers.ACLC_set_acl_entry ,
103                                    _acl_preset_n( target.type , target._id ,
104                                                   st , si ,
105                                                   int( rights ) , ttlToInt( ttl ) ) ) )
106
107 #
108 # remove_acl_entry
109 #
110
111 def removeAclEntryById( target , subject ) :
112     st , si = _to_acl_subject( subject )
113     raiseIfError( lib.rsbac_acl( transaction._t ,
114                                  headers.ACLC_remove_acl_entry ,
115                                  _acl_preset( target.type , target._id._obj ,
116                                               st , si ,
117                                               0 , 0 ) ) )
118
119 def removeAclEntryByName( target , subject ) :
120     st , si = _to_acl_subject( subject )
121     raiseIfError( lib.rsbac_acl_n( transaction._t ,
122                                    headers.ACLC_remove_acl_entry ,
123                                    _acl_preset_n( target.type , target._id ,
124                                                   st , si ,
125                                                   0 , 0 ) ) )
126
127 #
128 # remove_acl
129 #
130
131 def removeAclById( target ) :
132     raiseIfError( lib.rsbac_acl( transaction._t ,
133                                  headers.ACLC_remove_acl ,
134                                  _acl_preset( target.type , target._id._obj ,
135                                               0 , 0 , 0 , 0 ) ) )
136
137 def removeAclByName( target ) :
138     raiseIfError( lib.rsbac_acl_n( transaction._t ,
139                                    headers.ACLC_remove_acl ,
140                                    _acl_preset_n( target.type , target._id ,
141                                                   0 , 0 , 0 , 0 ) ) )
142
143 # add_to_acl_entry
144 # remove_from_acl_entry
145
146 #
147 # set_mask
148 #
149
150 def setAclMaskById( target , mask ) :
151     raiseIfError( lib.rsbac_acl( transaction._t ,
152                                  headers.ACLC_remove_acl ,
153                                  _acl_preset( target.type , target._id._obj ,
154                                               0 , 0 ,
155                                               mask , 0 ) ) )
156
157 def setAclMaskByName( target , mask ) :
158     raiseIfError( lib.rsbac_acl_n( transaction._t ,
159                                    headers.ACLC_remove_acl ,
160                                    _acl_preset_n( target.type , target._id ,
161                                                   0 , 0 ,
162                                                   mask , 0 ) ) )
163
164 #
165 # remove_user
166 #
167
168 @export
169 def aclRemoveUser( user ) :
170     """Remove user from all groups and all ACLs.
171
172     user -- UID as integer
173
174     """
175     g_targetId.user = user
176     raiseIfError( lib.rsbac_acl( transaction._t ,
177                                  headers.ACLC_remove_user ,
178                                  _acl_preset( headers.T_USER , g_targetId ,
179                                               0 , 0 , 0 , 0 ) ) )
180
181 #
182 # get_acl_rights
183 #
184
185 def getAclRightsById( target , subject , effective = False ) :
186     st , si = _to_acl_subject( subject )
187     rights = headers.rsbac_acl_rights_vector_t()
188     raiseIfError( lib.rsbac_acl_get_rights( transaction._t ,
189                                             _acl_preset( target.type , target._id._obj ,
190                                                          st , si ,
191                                                          0 , 0 ) ,
192                                             byref( rights ) ,
193                                             effective ) )
194     return AclRequestVector( rights.value )
195
196 def getAclRightsByName( target , subject , effective = False ) :
197     st , si = _to_acl_subject( subject )
198     rights = headers.rsbac_acl_rights_vector_t()
199     raiseIfError( lib.rsbac_acl_get_rights_n( transaction._t ,
200                                               _acl_preset_n( target.type , target._id ,
201                                                              st , si ,
202                                                              0 , 0 ) ,
203                                               byref( rights ) ,
204                                               effective ) )
205     return AclRequestVector( rights.value )
206
207 #
208 # acl_get_tlist
209 #
210
211 def _unpackAclTlist( entries , ttls ) :
212     return [ ( _from_acl_subject( entry.subj_type , entry.subj_id ) ,
213                AclRequestVector( entry.rights ) ,
214                intToTtl( ttl ) )
215              for entry , ttl in zip( entries , ttls ) ]
216
217 def getAclTargetListById( target ) :
218     arrs = fetch( ( headers.rsbac_acl_entry_t ,
219                     headers.rsbac_time_t ) ,
220                   lambda n , a , b : lib.rsbac_acl_get_tlist( transaction._t ,
221                                                               target.type ,
222                                                               target._id._obj ,
223                                                               a , b , n ) ,
224                   32 )
225     return _unpackAclTlist( *arrs )
226
227 def getAclTargetListByName( target ) :
228     arrs = fetch( ( headers.rsbac_acl_entry_t ,
229                     headers.rsbac_time_t ) ,
230                   lambda n , a , b : lib.rsbac_acl_get_tlist_n( transaction._t ,
231                                                                 target.type ,
232                                                                 target._id ,
233                                                                 a , b , n ) ,
234                   32 )
235     return _unpackAclTlist( *arrs )
236
237 #
238 # acl_get_mask
239 #
240
241 def getAclMaskById( target ) :
242     rights = headers.rsbac_acl_rights_vector_t()
243     raiseIfError( lib.rsbac_acl_get_mask( transaction._t ,
244                                           target.type , target._id._obj ,
245                                           byref( rights ) ) )
246     return AclRequestVector( rights.value )
247
248 def getAclMaskByName( target ) :
249     rights = headers.rsbac_acl_rights_vector_t()
250     raiseIfError( lib.rsbac_acl_get_mask_n( transaction._t ,
251                                             target.type , target._id ,
252                                             byref( rights ) ) )
253     return AclRequestVector( rights.value )
254
255 #
256 # dispatchers
257 #
258
259 @export
260 def setAclEntry( target , subject , rights , ttl = None ) :
261     """Set an ACL entry for a target-subject couple.
262
263     target -- Object
264     subject -- either an instance of objects.User, acl.Group or rc.Role.
265     rights -- AclRequestVector
266     ttl -- None or a positive integer
267
268     """
269     if target._byName :
270         return setAclEntryByName( target , subject , rights , ttl )
271     else :
272         return setAclEntryById( target , subject , rights , ttl )
273
274 @export
275 def removeAclEntry( target , subject ) :
276     """Remove an ACL entry.
277
278     target -- Object
279     subject -- either an instance of objects.User, acl.Group or rc.Role.
280
281     """
282     if target._byName :
283         return removeAclEntryByName( target , subject )
284     else :
285         return removeAclEntryById( target , subject )
286
287 @export
288 def removeAcl( target ) :
289     """Remove all ACL entries on a target.
290
291     target -- Object
292
293     """
294     if target._byName :
295         return removeAclByName( target )
296     else :
297         return removeAclById( target )
298
299 @export
300 def setAclMask( target , mask ) :
301     """Set ACL mask on a target.
302
303     target -- Object
304     mask -- AclRequestVector
305
306     """
307     if target._byName :
308         return setAclMaskByName( target , mask )
309     else :
310         return setAclMaskById( target , mask )
311
312 @export
313 def getAclRights( target , subject , effective = False ) :
314     """Get ACL rights for a target-subject couple.
315
316     target -- Object
317     subject -- either an instance of objects.User, acl.Group or rc.Role.
318     effective -- True to retrieve effective rights, False otherwise.
319
320     Returns an AclRequestVector.
321
322     """
323     if target._byName :
324         return getAclRightsByName( target , subject , effective )
325     else :
326         return getAclRightsById( target , subject , effective )
327
328 @export
329 def getAclMask( target ) :
330     """Get ACL mask for a target.
331
332     target -- Object
333
334     Returns an AclRequestVector.
335
336     """
337     if target._byName :
338         return getAclMaskByName( target , mask )
339     else :
340         return getAclMaskById( target , mask )
341
342 @export
343 def getAclTargetList( target ) :
344     """Get all ACL entries for a target.
345
346     target -- Object
347
348     Returns a list of 3-tuple (Object, AclRequestVector, ttl).
349
350     """
351     if target._byName :
352         return getAclTargetListByName( target )
353     else :
354         return getAclTargetListById( target )
355
356 class AclBase( object ) :
357     __slots__ = ( 'target' , )
358     def __init__( self , target ) :
359         object.__init__( self )
360         self.target = target
361     def __len__( self ) :
362         return len( self._list() )
363     def __iter__( self ) :
364         return iter( self.keys() )
365     def __repr__( self ) :
366         return '<ACL for %s: %d entries>' % ( repr( self.target ).strip( '<>' ) , len( self ) )
367     def keys( self ) :
368         return [ e[ 0 ] for e in self._list() ]
369     def values( self ) :
370         return [ ( e[ 1 ] , e[ 2 ] ) for e in self._list() ]
371     def items( self ) :
372         return [ ( e[ 0 ] , ( e[ 1 ] , e[ 2 ] ) ) for e in self._list() ]
373
374 class AclById( AclBase ) :
375     __slots__ = ()
376     def _list( self ) :
377         return getAclTargetListById( self.target )
378     def __getitem__( self , subject ) :
379         # FIXME: temporary solution. Waiting for an O(1) way to get
380         # (right,TTL) couple.
381         for k , v in self.items() :
382             if k == subject :
383                 return v
384         #return AclRequestVector() , None
385         raise RuntimeError
386     def __setitem__( self , subject , value ) :
387         if not isinstance( value , tuple ) :
388             value = value , None
389         rights , ttl = value
390         setAclEntryById( self.target , subject , rights , ttl )
391     def __delitem__( self , subject ) :
392         removeAclEntryById( self.target , subject )
393     # def update( self ) : pass
394     def clear( self ) :
395         # FIXME: temporary solution. Should sys_rsbac_remove_acl
396         # handle T_PROCESS instead?
397         if isinstance( self.target , Process ) :
398             map( self.__delitem__ , self )
399         else :
400             removeAclById( self.target )
401
402 class AclByName( AclBase ) :
403     __slots__ = ()
404     def _list( self ) :
405         return getAclTargetListByName( self.target )
406     def __iter__( self ) :
407         return ( n[ 0 ] for n in self.__list() )
408     def __getitem__( self , subject ) :
409         # FIXME: temporary solution. Waiting for an O(1) way to get
410         # (right,TTL) couple.
411         for k , v in self.items() :
412             if k == subject :
413                 return v
414         #return RequestVector() , None
415         raise RuntimeError
416     def __setitem__( self , subject , value ) :
417         if not isinstance( value , tuple ) :
418             value = value , None
419         rights , ttl = value
420         setAclEntryByName( self.target , subject , rights , ttl )
421     def __delitem__( self , subject ) :
422         removeAclEntryByName( self.target , subject )
423     def clear( self ) :
424         removeAclByName( self.target )
425
426 #--[ Group ]------------------------------------------------------------------
427
428 @export
429 def addGroup( name , type = headers.ACLG_PRIVATE , id = None ) :
430     """Add an ACL group.
431
432     type -- type of group (either ACLG_GLOBAL or ACLG_PRIVATE)
433     name -- group name as string
434     id -- a positive integer or None (automatic ID)
435
436     Returns the ID of the new group.
437
438     """
439     if id is None :
440         id = 0
441     id_ = headers.rsbac_acl_group_id_t()
442     id_.value = id
443     arg = headers.rsbac_acl_group_syscall_arg_t()
444     arg.add_group.type = type
445     arg.add_group.name = name
446     arg.add_group.group_id_p = pointer( id_ )
447     raiseIfError( lib.rsbac_acl_group( transaction._t ,
448                                        headers.ACLGS_add_group ,
449                                        byref( arg ) ) )
450     return int( id_.value )
451
452 @export
453 def addGlobalGroup( name , id = None ) :
454     """Add an global ACL group.
455
456     name -- group name as string
457     id -- a positive integer or None (automatic ID)
458
459     Returns the ID of the new group.
460
461     """
462     return addGroup( name , headers.ACLG_GLOBAL , id )
463
464 @export
465 def addPrivateGroup( name , id = None ) :
466     """Add an private ACL group.
467
468     name -- group name as string
469     id -- a positive integer or None (automatic ID)
470
471     Returns the ID of the new group.
472
473     """
474     return addGroup( name , headers.ACLG_PRIVATE , id )
475
476 @export
477 def changeGroup( id , owner , type , name ) :
478     """Change ACL group attributes.
479
480     Change the owner, type and name of an existing ACL group.
481
482     id -- ACL group as integer
483     owner -- user as integer
484     type -- either headers.ACLG_PRIVATE or headers.ACLG_GLOBAL
485     name -- group name
486
487     """
488     arg = headers.rsbac_acl_group_syscall_arg_t()
489     arg.change_group.id = id
490     arg.change_group.owner = owner
491     arg.change_group.type = type
492     arg.change_group.name = name
493     raiseIfError( lib.rsbac_acl_group( transaction._t ,
494                                        headers.ACLGS_change_group ,
495                                        byref( arg ) ) )
496
497 @export
498 def removeGroup( id ) :
499     """Remove an ACL group.
500
501     id -- ACL group as integer
502
503     """
504     arg = headers.rsbac_acl_group_syscall_arg_t()
505     arg.remove_group.id = id
506     raiseIfError( lib.rsbac_acl_group( transaction._t ,
507                                        headers.ACLGS_remove_group ,
508                                        byref( arg ) ) )
509
510 def _unpackEntry( entry ) :
511     return int( entry.id ) , int( entry.owner ) , int( entry.type ) , entry.name
512
513 @export
514 def getGroupEntry( id ) :
515     """Get group entry attributes.
516
517     id -- ACL group as integer
518
519     Returns a tuple with 4 attributes: id, owner, type and name.
520
521     """
522     entry = headers.rsbac_acl_group_entry_t()
523     arg = headers.rsbac_acl_group_syscall_arg_t()
524     arg.get_group_entry.id = id
525     arg.get_group_entry.entry_p = pointer( entry )
526     raiseIfError( lib.rsbac_acl_group( transaction._t ,
527                                        headers.ACLGS_get_group_entry ,
528                                        byref( arg ) ) )
529     return _unpackEntry( entry )
530
531 def _listGroups( includeGlobal , arr , n ) :
532     arg = headers.rsbac_acl_group_syscall_arg_t()
533     arg.list_groups.include_global = includeGlobal
534     arg.list_groups.group_entry_array = arr
535     arg.list_groups.maxnum = n
536     return raiseIfError( lib.rsbac_acl_group( transaction._t ,
537                                               headers.ACLGS_list_groups ,
538                                               byref( arg ) ) )
539
540 # FIXME: Other groups may be viewed/changed while not listed by
541 # _listGroups (the groups belonging to other users.)
542 @export
543 def getGroupList( includeGlobal = False ) :
544     """Get the list of ACL groups.
545
546     includeGlobal -- boolean. If True, include global groups.
547
548     Returns list of group ID.
549
550     """
551     arr = fetch( headers.rsbac_acl_group_entry_t ,
552                  lambda n , a : _listGroups( includeGlobal , a , n ) ,
553                  32 )
554     return map( _unpackEntry , arr )
555
556 @export
557 def addGroupMember( group , user , ttl = None ) :
558     """Add a member to an ACL group.
559
560     group -- ACL group as integer
561     user -- user as integer
562     ttl -- None or a positive integer
563
564     """
565     arg = headers.rsbac_acl_group_syscall_arg_t()
566     arg.add_member.group = int( group )
567     arg.add_member.user = int( user )
568     arg.add_member.ttl = ttlToInt( ttl )
569     return raiseIfError( lib.rsbac_acl_group( transaction._t ,
570                                               headers.ACLGS_add_member ,
571                                               byref( arg ) ) )
572
573 @export
574 def removeGroupMember( group , user ) :
575     """Remove a member from an ACL group.
576
577     group -- ACL group as integer
578     user -- user as integer
579
580     """
581     arg = headers.rsbac_acl_group_syscall_arg_t()
582     arg.remove_member.group = int( group )
583     arg.remove_member.user = int( user )
584     return raiseIfError( lib.rsbac_acl_group( transaction._t ,
585                                               headers.ACLGS_remove_member ,
586                                               byref( arg ) ) )
587
588 def _getUserGroups( user , groups , ttls , n ) :
589     arg = headers.rsbac_acl_group_syscall_arg_t()
590     arg.get_user_groups.user = user
591     arg.get_user_groups.group_array = groups
592     arg.get_user_groups.ttl_array = ttls
593     arg.get_user_groups.maxnum = n
594     return raiseIfError( lib.rsbac_acl_group( transaction._t ,
595                                               headers.ACLGS_get_user_groups ,
596                                               byref( arg ) ) )
597
598 @export
599 def getUserGroups( uid ) :
600     """Get the ACL groups to which a user belong.
601
602     uid -- user as integer
603
604     Returns a list of pair (id,ttl).
605
606     """
607     arrs = fetch( ( headers.rsbac_acl_group_id_t ,
608                     headers.rsbac_time_t ) ,
609                   lambda n , a , b : _getUserGroups( uid , a , b , n ) ,
610                   32 )
611     return [ ( int( a ) , int( b ) ) for a , b in zip( *arrs ) ]
612
613 def _getGroupMembers( group , users , ttls , n ) :
614     arg = headers.rsbac_acl_group_syscall_arg_t()
615     arg.get_group_members.group = group
616     arg.get_group_members.user_array = users
617     arg.get_group_members.ttl_array = ttls
618     arg.get_group_members.maxnum = n
619     return raiseIfError( lib.rsbac_acl_group( transaction._t ,
620                                               headers.ACLGS_get_group_members ,
621                                               byref( arg ) ) )
622
623 @export
624 def getGroupMembers( id ) :
625     """Get the members of the given ACL group.
626
627     id -- ACL group
628
629     Returns a list of pair (uid,ttl).
630
631     """
632     arrs = fetch( ( headers.rsbac_uid_t ,
633                     headers.rsbac_time_t ) ,
634                   lambda n , a , b : _getGroupMembers( id , a , b , n ) ,
635                   32 )
636     return [ ( int( a ) , intToTtl( b ) ) for a , b in zip( *arrs ) ]
637
638 class AclGroupMembersTtlDictProxy( object ) :
639     __slots__ = ( '__group' , )
640     def __init__( self , id ) :
641         self.__group = id
642     def __getitem__( self , user ) :
643         for uid , ttl in getGroupMembers( self.__group ) :
644             if uid == user :
645                 if ttl is None :
646                     ttl = True
647                 return ttl
648         return False
649     def __setitem__( self , user , value ) :
650         addGroupMember( self.__group , user , value )
651     def __iter__( self ) :
652         return ( n[ 0 ] for n in getGroupMembers( self.__group ) )
653     def __repr__( self ) :
654         r = []
655         for user , ttl in getGroupMembers( self.__group ) :
656             if ttl is None :
657                 r.append( str( user ) )
658             else :
659                 r.append( '%s(%ds)' % ( user , ttl ) )
660         return '<Members for ACL group %d: %s>' \
661             % ( self.__group , ', '.join( r ) or 'none' )
662     def add( self , user , ttl = None ) :
663         addGroupMember( self.__group , user , ttl )
664     def discard( self , user ) :
665         removeGroupMember( self.__group , user )
666     def clear( self ) :
667         map( self.discard , self )
668
669 # FIXME: Add a note about settings (not settable individually
670 # normally)
671 class Group( object ) :
672     __slots__ = ( '_id' , 'members' )
673     def __init__( self , id ) :
674         self._id = id
675         self.members = AclGroupMembersTtlDictProxy( id )
676     def __repr__( self ) :
677         try :
678             entry = getGroupEntry( self._id )
679             assert entry[ 2 ] in ( headers.ACLG_GLOBAL , headers.ACLG_PRIVATE )
680             desc = '%r %s' % \
681                 ( entry[ 3 ] ,
682                   ( 'PRIVATE' , 'GLOBAL' )[ entry[ 2 ] == headers.ACLG_GLOBAL ] )
683         except Error , e :
684             if e[ 0 ] != headers.RSBAC_ENOTFOUND :
685                 raise
686             desc = 'undefined'
687         return '<ACL Group [%d] %s>' % ( self._id , desc )
688     #
689     # owner
690     #
691     def getOwner( self ) :
692         return User( getGroupEntry( self._id )[ 1 ] )
693     def setOwner( self , value ) :
694         entry = getGroupEntry( self._id )
695         changeGroup( self._id , int( value ) , entry[ 2 ] , entry[ 3 ] )
696     owner = property( getOwner , setOwner )
697     #
698     # private (not really a boolean, but let's say it is)
699     #
700     def getPrivate( self ) :
701         entry = getGroupEntry( self._id )
702         type = entry[ 2 ]
703         assert type in ( headers.ACLG_GLOBAL , headers.ACLG_PRIVATE )
704         return type == headers.ACLG_PRIVATE
705     def setPrivate( self , value ) :
706         entry = getGroupEntry( self._id )
707         if value :
708             value = headers.ACLG_PRIVATE
709         else :
710             value = headers.ACLG_GLOBAL
711         changeGroup( self._id , entry[ 1 ] , value , entry[ 3 ] )
712     private = property( getPrivate , setPrivate )
713     #
714     # name
715     #
716     def getName( self ) :
717         return getGroupEntry( self._id )[ 3 ]
718     def setName( self , value ) :
719         entry = getGroupEntry( self._id )
720         changeGroup( self._id , entry[ 1 ] , entry[ 2 ] , value )
721     name = property( getName , setName )
722
723 class GroupDict( object ) :
724     __slots__ = ()
725     def __iter__( self ) :
726         return ( item[ 0 ] for item in getGroupList( True ) )
727     def __getitem__( self , id ) :
728         return Group( id )
729     def __delitem__( self , id ) :
730         return removeGroup( id )
731     def __repr__( self ) :
732         return '{' + ', '.join( '%s: %s' % ( a , b ) for a , b in self.items() ) + '}'
733     def keys( self ) :
734         return list( self )
735     def values( self ) :
736         return map( Group , self )
737     def items( self ) :
738         return [ ( group , Group( group ) ) for group in self ]
739
740 groups = GroupDict()
741
742 from rsbac.rc import Role
743 from rsbac.objects import User, Process
744
745 # Local Variables:
746 # indent-tabs-mode: nil
747 # python-indent: 4
748 # End: