Initial import
[py-rsbac] / rsbac / rc.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 """
21
22 This module provides access to RC type and RC role objects for the
23 RSBAC Python bindings.
24
25 """
26
27 __all__ = []
28
29 def export( o ) :
30     if not isinstance( o , basestring ) :
31         name = o.__name__
32     else :
33         name , o = o , None
34     if name in __all__ :
35         raise ImportError , 'duplicate name %r in module %r' % ( name , __name__ )
36     __all__.append( name )
37     return o
38
39 import new
40 import weakref
41 from ctypes import byref, c_uint32
42
43 from rsbac import headers, lib, transaction
44 from rsbac.errors import Error, raiseIfError
45 from rsbac._utils import aptr, slowButCorrectStringAssignation, fetch
46
47 # Singletons. Obviously bad for MT. But good for performance..
48 g_rcItemValue = headers.rsbac_rc_item_value_t()
49 g_rcItemValueRef = byref( g_rcItemValue )
50
51 g_rcTargetValue = headers.rsbac_rc_target_id_t()
52 g_rcTargetValueRef = byref( g_rcTargetValue )
53
54 g_rcTargetValue2 = headers.rsbac_rc_target_id_t()
55 g_rcTargetValue2Ref = byref( g_rcTargetValue2 )
56
57 g_ttl = headers.rsbac_time_t()
58 g_ttlRef = byref( g_ttl )
59
60 g_rcNameTargetToItem = {
61     headers.T_FD      : headers.RI_type_fd_name ,
62     headers.T_FILE    : headers.RI_type_fd_name ,
63     headers.T_DIR     : headers.RI_type_fd_name ,
64     headers.T_FIFO    : headers.RI_type_fd_name ,
65     headers.T_DEV     : headers.RI_type_dev_name ,
66     headers.T_IPC     : headers.RI_type_ipc_name ,
67     headers.T_USER    : headers.RI_type_user_name ,
68     headers.T_GROUP   : headers.RI_type_group_name ,
69     headers.T_PROCESS : headers.RI_type_process_name ,
70     headers.T_NETDEV  : headers.RI_type_netdev_name ,
71     headers.T_NETTEMP : headers.RI_type_nettemp_name ,
72     headers.T_NETOBJ  : headers.RI_type_netobj_name ,
73     headers.T_SCD     : headers.RI_type_scd_name
74     }
75
76 g_rcCompatibilityTargetToItem = {
77     headers.T_FD      : headers.RI_type_comp_fd ,
78     headers.T_FILE    : headers.RI_type_comp_fd ,
79     headers.T_DIR     : headers.RI_type_comp_fd ,
80     headers.T_FIFO    : headers.RI_type_comp_fd ,
81     headers.T_DEV     : headers.RI_type_comp_dev ,
82     headers.T_IPC     : headers.RI_type_comp_ipc ,
83     headers.T_USER    : headers.RI_type_comp_user ,
84     headers.T_GROUP   : headers.RI_type_comp_group ,
85     headers.T_PROCESS : headers.RI_type_comp_process ,
86     headers.T_NETDEV  : headers.RI_type_comp_netdev ,
87     headers.T_NETTEMP : headers.RI_type_comp_nettemp ,
88     headers.T_NETOBJ  : headers.RI_type_comp_netobj ,
89     headers.T_SCD     : headers.RI_type_comp_scd
90     }
91
92 g_rcTargetToTypeRemove = {
93     headers.T_FD      : headers.RI_type_fd_remove ,
94     headers.T_FILE    : headers.RI_type_fd_remove ,
95     headers.T_DIR     : headers.RI_type_fd_remove ,
96     headers.T_FIFO    : headers.RI_type_fd_remove ,
97     headers.T_DEV     : headers.RI_type_dev_remove ,
98     headers.T_IPC     : headers.RI_type_ipc_remove ,
99     headers.T_USER    : headers.RI_type_user_remove ,
100     headers.T_GROUP   : headers.RI_type_group_remove ,
101     headers.T_PROCESS : headers.RI_type_process_remove ,
102     headers.T_NETDEV  : headers.RI_type_netdev_remove ,
103     headers.T_NETTEMP : headers.RI_type_nettemp_remove ,
104     headers.T_NETOBJ  : headers.RI_type_netobj_remove
105     }
106
107 # RC role specific data
108 _g_role_mod = headers.rsbac_rc_role_id_t( -1 ).value + 1
109 assert _g_role_mod > 0
110 _g_role_max_value = headers.rsbac_rc_role_id_t( -32 ).value
111 def _nrole( n ) :
112     n %= _g_role_mod
113     if n >= _g_role_max_value :
114         return int( n - _g_role_mod )
115     else :
116         return int( n )
117 _g_roles = weakref.WeakValueDictionary()
118 _g_pseudoRoles = {
119     -1 : 'inherit_user' ,
120     -2 : 'inherit_process' ,
121     -3 : 'inherit_parent' ,
122     -4 : 'inherit_up_mixed' ,
123     -5 : 'use_force_role'
124     }
125
126 # RC type specific data
127 _g_type_mod = headers.rsbac_rc_type_id_t( -1 ).value + 1
128 assert _g_type_mod > 0
129 _g_type_max_value = headers.rsbac_rc_type_id_t( -32 ).value
130 def _ntype( n ) :
131     n %= _g_type_mod
132     if n >= _g_type_max_value :
133         return int( n - _g_type_mod )
134     else :
135         return int( n )
136 _g_types = weakref.WeakValueDictionary()
137 _g_pseudoTypes = {
138     -1 : 'inherit_process' ,
139     -2 : 'inherit_parent' ,
140     -3 : 'no_create' ,
141     -4 : 'no_execute' ,
142     -5 : 'use_new_role_def_create' ,
143     -6 : 'no_chown' ,
144     -7 : 'use_fd'
145     }
146
147 @export
148 def copyRole( source , dest ) :
149     """Copy a RC role.
150
151     source -- RC role as integer
152     dest -- RC role as integer
153
154     """
155     raiseIfError( lib.rsbac_rc_copy_role( transaction._t ,
156                                           source , dest ) )
157
158 @export
159 def grant( role , type , requests ) :
160     """Grant 'requests' to 'role' for the given 'type'.
161
162     role -- RC role
163     type -- RC type
164     requests -- RequestVector
165     """
166     rights , ttl = role.typeCompatibility[ type ]
167     rights |= rsbac.RequestVector( requests )
168     role.typeCompatibility[ type ] = rights , ttl
169
170 @export
171 def revoke( role , type , requests ) :
172     """Revoke 'requests' to 'role' for the given 'type'.
173
174     role -- RC Role
175     type -- RC type
176     requests -- RequestVector
177     """
178     rights , ttl = role.typeCompatibility[ type ]
179     rights &= ~rsbac.RequestVector( requests )
180     role.typeCompatibility[ type ] = rights , ttl
181
182 def findUnnamedRole( start = 0 ) :
183     """Find an unnamed role.
184
185     start -- Minimal RC role id to use, as integer.
186
187     Return an integer.
188     """
189     i = start
190     while 1 :
191         try :
192             getRoleName( i )
193         except Error , e :
194             if e[ 0 ] != headers.RSBAC_ENOTFOUND :
195                 raise
196             break
197         i += 1
198     return i
199
200 def findUnnamedRoles( n = 1 , start = 0 ) :
201     """Find a set of unnammed roles.
202
203     n -- Number of unnnamed roles to find.
204     start -- Minimal RC role id to use, as integer.
205
206     Returns a list of integers.
207     """
208     r = []
209     i = start
210     for j in range( n ) :
211         role = findUnnamedRole( i )
212         r.append( role )
213         i = role + 1
214     return r
215
216 @export
217 def newRole( name , start = 0 ) :
218     """Create a new RC role.
219
220     name -- Name for the new RC role.
221
222     Returns a RC Role.
223     """
224     role = findUnnamedRole( start )
225     setRoleName( role , name )
226     return Role( role )
227
228 @export
229 def cloneRole( source , start = 0 ) :
230     """Clone a RC role under another name.
231
232     source -- RC role as integer
233     name -- Name of the new role
234
235     """
236     role = findUnnamedRole( start )
237     copyRole( source , role )
238     return role
239
240 @export
241 def copyType( target , source , dest ) :
242     """Copy a RC type.
243
244     The target specify which type of RC type should be copied.
245
246     target -- RSBAC object type as integer
247     source -- RC type as integer
248     dest -- RC Type as integer
249
250     """
251     raiseIfError( lib.rsbac_rc_copy_type( transaction._t , target ,
252                                           source , dest ) )
253
254 @export
255 def getList( rcTarget , rcId , item ) :
256     """Retrieve a list of RC items (role or type).
257
258     rcTarget -- RT_ROLE, RT_TYPE or None.
259     rcId -- role or target as integer.
260     item -- a value from RI_* defines.
261
262     """
263     # FIXME: I'm assuming that all roles are returned when querying
264     # with RI_name, and that target can be NULL. Is that right?
265     if rcId is None :
266         id = None
267     elif rcTarget == headers.RT_ROLE :
268         g_rcTargetValue.role = rcId
269     elif rcTarget == headers.RT_TYPE :
270         g_rcTargetValue.type = rcId
271     else :
272         raise RuntimeError , 'unexpected rc target %d' % ( rcTarget , )
273     arr = fetch( c_uint32 ,
274                  lambda n , a : lib.rsbac_rc_get_list( transaction._t ,
275                                                        rcTarget , g_rcTargetValueRef ,
276                                                        item , n , a , None ) )
277     return sorted( map( int , arr ) )
278
279 @export
280 def getRoleList( role , item ) :
281     """Retrieve a list of items associated with a role.
282
283     role -- RC role as integer or None
284     item -- a value from RI_* defines.
285
286     """
287     return getList( headers.RT_ROLE , role , item )
288
289 @export
290 def getTypeList( type , item ) :
291     """Retrieve a list of items associated with a type.
292
293     type -- RC type as integer (or None?)
294     item -- a value from RI_* defines.
295
296     """
297     return getList( headers.RT_TYPE , type , item )
298
299 @export
300 def getRoles() :
301     """Retrieve a list of all defined roles (those with a name.)
302
303     """
304     # FIXME: I'm assuming that all roles are returned when querying
305     # with RI_name, and that target can be NULL. Is that correct?
306     return getRoleList( None , headers.RI_name )
307
308 g_scdRcTypes = None
309
310 @export
311 def getTypes( target ) :
312     """Retrieve a list of all defined types (those with a name.)
313
314     target -- RSBAC object type as integer
315
316     """
317     if target == headers.T_SCD :
318         global g_scdRcTypes
319         if g_scdRcTypes is None :
320             r = []
321             for key in dir( headers ) :
322                 if ( key.startswith( 'ST_' ) or key.startswith( 'AST_' ) ) \
323                     and not key.endswith( '_none' ) :
324                     r.append( int( getattr( headers , key ) ) )
325             r.sort()
326             g_scdRcTypes = r
327         return g_scdRcTypes
328     else :
329         if target not in g_rcNameTargetToItem :
330             raise RuntimeError , 'Unexpected target %r' % ( target , )
331         return getTypeList( None , g_rcNameTargetToItem[ target ] )
332
333 @export
334 def changeRole( role , password = None ) :
335     """Change the role of the current process.
336
337     role -- RC role as integer
338     password -- the password as a string or None
339
340     """
341     raiseIfError( lib.rsbac_rc_change_role( role , password ) )
342
343 @export
344 def getCurrentRole() :
345     """Return the role of the current process.
346
347     Returns a RC role as an integer.
348
349     """
350     role = headers.rsbac_rc_role_id_t()
351     raiseIfError( lib.rsbac_rc_get_current_role( byref( role ) ) )
352     return int( role.value )
353
354 @export
355 def getRoleName( role ) :
356     """Get the name of a RC role.
357
358     role -- RC role as integer
359
360     """
361     g_rcTargetValue.role = role
362     raiseIfError( lib.rsbac_rc_get_item( transaction._t , headers.RT_ROLE ,
363                                          g_rcTargetValueRef , None ,
364                                          headers.RI_name , g_rcItemValueRef ,
365                                          None ) )
366     return g_rcItemValue.name
367
368 @export
369 def setRoleName( role , name ) :
370     """Set the name of a RC role.
371
372     role -- RC role as integer
373     name -- the new name as string
374
375     """
376     g_rcTargetValue.role = role
377     slowButCorrectStringAssignation( g_rcItemValue , 'name' , name )
378     raiseIfError( lib.rsbac_rc_set_item( transaction._t , headers.RT_ROLE ,
379                                          g_rcTargetValueRef , None ,
380                                          headers.RI_name , g_rcItemValueRef ,
381                                          0 ) )
382
383 @export
384 def getRoleTypeCompatibility( role , type ) :
385     """Get RC role compatibility with the given type.
386
387     role -- RC role as integer
388     type -- RC type as either a tuple (target,type) or an Object class
389     or instance.
390
391     Returns a tuple (RequestVector,ttl).
392
393     """
394     g_rcTargetValue.role = role
395     target , type = _type( type )
396     g_rcTargetValue2.type = type
397     item = g_rcCompatibilityTargetToItem[ target ]
398     raiseIfError( lib.rsbac_rc_get_item( transaction._t , headers.RT_ROLE ,
399                                          g_rcTargetValueRef , g_rcTargetValue2Ref ,
400                                          item , g_rcItemValueRef ,
401                                          g_ttlRef ) )
402     return RequestVector( g_rcItemValue.rights ) , g_ttl.value
403
404 @export
405 def setRoleTypeCompatibility( role , type , value ) :
406     """Set RC role compatibility with the given type.
407
408     role -- RC role as integer
409     type -- RC type
410     value -- A tuple (RequestVector,ttl) or a RequestVector (implying
411     unlimited TTL.)
412
413     """
414     g_rcTargetValue.role = role
415     target , type = _type( type )
416     g_rcTargetValue2.type = type
417     item = g_rcCompatibilityTargetToItem[ target ]
418     if not isinstance( value , ( tuple , list ) ) :
419         value = ( value , 0 )
420     rights , ttl = value
421     g_rcItemValue.rights = int( rights )
422     raiseIfError( lib.rsbac_rc_set_item( transaction._t , headers.RT_ROLE ,
423                                          g_rcTargetValueRef , g_rcTargetValue2Ref ,
424                                          item , g_rcItemValueRef ,
425                                          ttl ) )
426
427 @export
428 def getRoleDefaultIndividualFdCreateType( role , type ) :
429     """Get RC role default individual FD create type
430
431     role -- RC role as integer
432     type -- RC type
433
434     Returns a Type (FIXME.. Returns an integer, and use Type in the
435     class wrapper instead.)
436
437     """
438     g_rcTargetValue.role = role
439     g_rcTargetValue2.type = int( type ) # FIXME: Check target type
440     raiseIfError( lib.rsbac_rc_get_item( transaction._t , headers.RT_ROLE ,
441                                          g_rcTargetValueRef , g_rcTargetValue2Ref ,
442                                          headers.RI_def_fd_ind_create_type ,
443                                          g_rcItemValueRef , None ) )
444     return Type( headers.T_FD , g_rcItemValue.type_id )
445
446 @export
447 def setRoleDefaultIndividualFdCreateType( role , type1 , type2 ) :
448     """Set RC role default individual FD create type
449
450     role -- RC role as integer
451     type1 -- RC type
452     type2 -- RC type
453
454     """
455     g_rcTargetValue.role = role
456     g_rcTargetValue2.type = int( type1 ) # FIXME: Check target type
457     g_rcItemValue.type_id = int( type2 ) # FIXME: Check target type
458     raiseIfError( lib.rsbac_rc_set_item( transaction._t , headers.RT_ROLE ,
459                                          g_rcTargetValueRef , g_rcTargetValue2Ref ,
460                                          headers.RI_def_fd_ind_create_type ,
461                                          g_rcItemValueRef , 0 ) )
462
463 @export
464 def delRoleDefaultIndividualFdCreateType( role , type ) :
465     """Remove RC role default individidual FD create type setting
466
467     role -- RC role as integer
468     type -- RC type
469     """
470     g_rcTargetValue.role = role
471     g_rcTargetValue2.type = int( type ) # FIXME: Check target type
472     raiseIfError( lib.rsbac_rc_set_item( transaction._t , headers.RT_ROLE ,
473                                          g_rcTargetValueRef , g_rcTargetValue2Ref ,
474                                          headers.RI_def_fd_ind_create_type_remove ,
475                                          None , 0 ) )
476
477 @export
478 def getRoleAdminType( role ) :
479     """Get the RC role admin type.
480
481     role -- RC role as integer
482
483     """
484     g_rcTargetValue.role = role
485     raiseIfError( lib.rsbac_rc_get_item( transaction._t , headers.RT_ROLE ,
486                                          g_rcTargetValueRef , None ,
487                                          headers.RI_admin_type , g_rcItemValueRef ,
488                                          None ) )
489     return g_rcItemValue.admin_type
490
491 @export
492 def setRoleAdminType( role , value ) :
493     """Set the RC role admin type.
494
495     role -- RC role as integer
496     value -- RC role admin type (0 [no admin], 1 [role admin] or 2 [system admin])
497
498     """
499     g_rcTargetValue.role = role
500     g_rcItemValue.admin_type = value
501     raiseIfError( lib.rsbac_rc_set_item( transaction._t , headers.RT_ROLE ,
502                                          g_rcTargetValueRef , None ,
503                                          headers.RI_admin_type , g_rcItemValueRef ,
504                                          0 ) )
505
506 @export
507 def getRoleBootRole( role ) :
508     """Test if the RC role is a boot role.
509
510     role -- RC role as integer
511     """
512     g_rcTargetValue.role = role
513     raiseIfError( lib.rsbac_rc_get_item( transaction._t , headers.RT_ROLE ,
514                                          g_rcTargetValueRef , None ,
515                                          headers.RI_boot_role ,
516                                          g_rcItemValueRef , None ) )
517     return bool( g_rcItemValue.boot_role )
518
519 @export
520 def setRoleBootRole( role , value ) :
521     """Set if the RC role is a boot role.
522
523     role -- RC role as integer
524     value -- boolean
525     """
526     g_rcTargetValue.role = role
527     g_rcItemValue.boot_role = value
528     raiseIfError( lib.rsbac_rc_set_item( transaction._t , headers.RT_ROLE ,
529                                          g_rcTargetValueRef , None ,
530                                          headers.RI_boot_role ,
531                                          g_rcItemValueRef , 0 ) )
532
533 @export
534 def getRoleRequireReauthentication( role ) :
535     """Test if the role requires reauthentication
536
537     role -- RC role as integer
538
539     """
540     g_rcTargetValue.role = role
541     raiseIfError( lib.rsbac_rc_get_item( transaction._t , headers.RT_ROLE ,
542                                          g_rcTargetValueRef , None ,
543                                          headers.RI_req_reauth ,
544                                          g_rcItemValueRef , None ) )
545     return bool( g_rcItemValue.req_reauth )
546
547 @export
548 def setRoleRequireReauthentication( role , value ) :
549     """Set if the role requires reauthentication
550
551     role -- RC role as integer
552     value -- boolean
553
554     """
555     g_rcTargetValue.role = role
556     g_rcItemValue.req_reauth = value
557     raiseIfError( lib.rsbac_rc_set_item( transaction._t , headers.RT_ROLE ,
558                                          g_rcTargetValueRef , None ,
559                                          headers.RI_req_reauth ,
560                                          g_rcItemValueRef , 0 ) )
561
562 @export
563 def removeRole( role ) :
564     """Remove a RC role.
565
566     role -- RC role as integer
567
568     """
569     g_rcTargetValue.role = role
570     raiseIfError( lib.rsbac_rc_set_item( transaction._t , headers.RT_ROLE ,
571                                          g_rcTargetValueRef , None ,
572                                          headers.RI_remove_role , None , 0 ) )
573
574 def makeGetSetRoles( name , item , docGet = None , docSet = None ) :
575     import sys
576     RT_ROLE = headers.RT_ROLE
577     def get( roleA , roleB ) :
578         g_rcTargetValue.role = roleA
579         g_rcTargetValue2.role = roleB
580         raiseIfError( lib.rsbac_rc_get_item( transaction._t , RT_ROLE ,
581                                              g_rcTargetValueRef , g_rcTargetValue2Ref ,
582                                              item , g_rcItemValueRef , g_ttlRef ) )
583         return int( g_ttl.value ) or bool( g_rcItemValue.comp )
584     if docGet is not None :
585         get.__doc__ = docGet + """
586
587         roleA -- RC role as integer
588         roleB -- RC role as integer
589
590         """
591     def set( roleA , roleB , value ) :
592         g_rcTargetValue.role = roleA
593         g_rcTargetValue2.role = roleB
594         if value is True :
595             flag , ttl = True , 0
596         elif not value or value < 1 :
597             flag , ttl = False , 0
598         else :
599             flag , ttl = True , value
600         g_rcItemValue.comp = flag
601         raiseIfError( lib.rsbac_rc_set_item( transaction._t , RT_ROLE ,
602                                              g_rcTargetValueRef , g_rcTargetValue2Ref ,
603                                              item , g_rcItemValueRef , ttl ) )
604     if docSet is not None :
605         set.__doc__ = docSet + """
606
607         roleA -- RC role as integer
608         roleB -- RC role as integer
609         value -- False, True or an integer.
610
611         """
612     def list( role ) :
613         return getList( RT_ROLE , role , item )
614     m = sys.modules[ __name__ ]
615     setattr( m , 'get' + name , get )
616     setattr( m , 'set' + name , set )
617     setattr( m , 'list' + name + 's' , list )
618     __all__.append( 'get' + name )
619     __all__.append( 'set' + name )
620     __all__.append( 'list' + name + 's' )
621
622 makeGetSetRoles( 'RoleCompatibilityRole' , headers.RI_role_comp ,
623                  'Test if the RC role is compatible with another one.' ,
624                  'Set if the RC role is compatible with another one.' )
625
626 makeGetSetRoles( 'RoleAdminRole' , headers.RI_admin_roles ,
627                  None , # FIXME
628                  None ) # FIXME
629
630 makeGetSetRoles( 'RoleAssignRole' , headers.RI_assign_roles ,
631                  None , # FIXME
632                  None ) # FIXME
633
634 # FIXME: dict interface!
635 class RoleTtlDictProxy( object ) :
636     def __init__( self , name , role , get , set , list ) :
637         self.__name = name
638         self.__role = role
639         self.__get = get
640         self.__set = set
641         self.__list = list
642     def __iter__( self ) :
643         return iter( self.__list( self.__role ) )
644     def __contains__( self , role ) :
645         return bool( self.__get( self.__role , role ) )
646     def __getitem__( self , role ) :
647         return self.__get( self.__role , role )
648     def __setitem__( self , role , value ) :
649         # FIXME: __setitem__ = Role( self.role ).setRoleCompatibility?
650         self.__set( self.__role , role , value )
651     def __delitem__( self , role ) :
652         self.__set( self.__role , role , False )
653     def __repr__( self ) :
654         r = []
655         for role in self :
656             value = self.__get( self.__role , role )
657             if value is True :
658                 r.append( str( role ) )
659             elif value is False :
660                 pass
661             else :
662                 r.append( '%s(%ds)' % ( role , value ) )
663         try :
664             name = `getRoleName( self.__role )`
665         except Error , e :
666             if e[ 0 ] != headers.RSBAC_ENOTFOUND :
667                 raise
668             name = 'undefined'
669         return '<%s for RC Role %d (%s): %s>' \
670             % ( self.__name , self.__role , name ,
671                 ', '.join( r ) or 'none' )
672     def keys( self ) :
673         return list( self )
674     def items( self ) :
675         r = []
676         # Be careful with TTL..
677         for role in self :
678             value = self.__get( self.__role , role )
679             if value :
680                 r.append( ( role , value ) )
681         return r
682     def add( self , role ) :
683         self.__set( self.__role , role , True )
684     def discard( self , role ) :
685         self.__set( self.__role , role , False )
686     def clear( self ) :
687         for role in self :
688             self.__set( self.__role , role , False )
689
690 class RoleTypeCompatibility( object ) :
691     def __init__( self , role ) :
692         self.role = role
693     def __getitem__( self , type ) :
694         return getRoleTypeCompatibility( self.role , type )
695     def __setitem__( self , type , value ) :
696         return setRoleTypeCompatibility( self.role , type , value )
697     def __repr__( self ) :
698         return '<RoleTypeCompatibility with RC role %d>' % ( self.role , )
699
700 class DefaultIndividualFdCreateType( object ) :
701     def __init__( self , role ) :
702         self.role = role
703     def __getitem__( self , type ) :
704         return self.role.getDefaultIndividualFdCreateType( type )
705     def get( self , type ) :
706         try :
707             return self[ type ]
708         except Error , e :
709             if e[ 0 ] != headers.RSBAC_ENOTFOUND :
710                 raise
711     def __setitem__( self , type , value ) :
712         self.role.setDefaultIndividualFdCreateType( type , value )
713     def __delitem__( self , type ) :
714         self.role.delDefaultIndividualFdCreateType( type )
715
716 class DefaultTypes( object ) :
717     def __init__( self , role ) :
718         self.role = role
719     def __getitem__( self , action ) :
720         return self.role.getDefaultType( action )
721     def __setitem__( self , action , value ) :
722         self.role.setDefaultType( action , value )
723
724 def _type( t ) :
725     from objects import Scd
726     if isinstance( t , Type ) :
727         return t.target , t.type
728     elif isinstance( t , Scd ) :
729         return t.type , t.id
730     else :
731         return t
732                 
733 class RoleBase( object ) :
734     __slots__ = [ '_role' , '_id' ]
735     def __new__( cls , role ) :
736         role = _nrole( role )
737         instance = _g_roles.get( role )
738         if instance is None :
739             instance = object.__new__( cls )
740             instance.__init_singleton__( role )
741             _g_roles[ role ] = instance
742         return instance
743     def __init_singleton__( self , role ) :
744         self._role = int( role )
745         id = headers.rsbac_rc_target_id_t()
746         id.role = role
747         self._id = byref( id )
748         self.compatibility = \
749             RoleTtlDictProxy( 'RoleCompatibility' , self._role ,
750                               getRoleCompatibilityRole ,
751                               setRoleCompatibilityRole ,
752                               listRoleCompatibilityRoles )
753         self.adminRoles = \
754             RoleTtlDictProxy( 'AdminRoles' , self._role ,
755                               getRoleAdminRole ,
756                               setRoleAdminRole ,
757                               listRoleAdminRoles )
758         self.assignRoles = \
759             RoleTtlDictProxy( 'AssignRoles' , self._role ,
760                               getRoleAssignRole ,
761                               setRoleAssignRole ,
762                               listRoleAssignRoles )
763         self.typeCompatibility = \
764             RoleTypeCompatibility( self._role )
765         self.defaultIndividualFdCreateType = \
766             DefaultIndividualFdCreateType( self._role )
767     def __int__( self ) :
768         return int( self._role )
769     def __long__( self ) :
770         return long( self._role )
771     def __repr__( self ) :
772         if self._role < 0 :
773             return '<RC PseudoRole %d %s>' \
774                 % ( self._role ,
775                     _g_pseudoRoles.get( self._role , 'unknown' ) )
776         else :
777             try :
778                 name = `self.getName()`
779             except Error :
780                 name = 'undefined'
781             return '<RC Role %d %s>' % ( self._role , name )
782     def copyTo( self , dest ) :
783         copyRole( self._role , int( dest ) )
784     def clone( self , name = None ) :
785         role = Role( cloneRole( self._role ) )
786         if name is not None :
787             role.name = name
788         return role
789     #
790     # id
791     #
792     def getId( self ) :
793         return self._role
794     id = property( getId )
795     #
796     # name
797     #
798     def getName( self ) :
799         return getRoleName( self._role )
800     def setName( self , name ) :
801         return setRoleName( self._role , name )
802     name = property( getName , setName )
803     #
804     # role_comp
805     #
806     def getRoleCompatibility( self , role ) :
807         return getRoleRoleCompatibility( self._role , role )
808     def setRoleCompatibility( self , role , value ) :
809         return setRoleRoleCompatibility( self._role , role , value )
810     compatibility = None
811     #
812     # admin_roles
813     #
814     def getAdminRole( self , role ) :
815         return getRoleAdminRole( self._role , role )
816     def setAdminRole( self , role , value ) :
817         return setRoleAdminRole( self._role , role , value )
818     adminRoles = None
819     #
820     # assign_roles
821     #
822     def getAssignRole( self , role ) :
823         return getRoleAssignRole( self._role , role )
824     def setAssignRole( self , role , value ) :
825         return setRoleAssignRole( self._role , role , value )
826     assignRoles = None
827     #
828     # type_comp_*
829     #
830     def getTypeCompatibility( self , type ) :
831         return getRoleTypeCompatibility( self._role , type )
832     def setTypeCompatibility( self , type , value ) :
833         return setRoleTypeCompatibility( self._role , type , value )
834     typeCompatibility = None
835     #
836     # def_fd_ind_create_type
837     #
838     def getDefaultIndividualFdCreateType( self , type ) :
839         return getRoleDefaultIndividualFdCreateType( self._role , type )
840     def setDefaultIndividualFdCreateType( self , type1 , type2 ) :
841         return setRoleDefaultIndividualFdCreateType( self._role , type1 , type2 )
842     def delDefaultIndividualFdCreateType( self , type ) :
843         return delRoleDefaultIndividualFdCreateType( self._role , type )
844     defaultFdType = None
845     #
846     # boot_role
847     #
848     def getBootRole( self ) :
849         return getRoleBootRole( self._role )
850     def setBootRole( self , value ) :
851         return setRoleBootRole( self._role , value )
852     bootRole = property( getBootRole , setBootRole )
853     #
854     # req_reauth
855     #
856     def getRequireReauthentication( self ) :
857         return getRoleRequireReauthentication( self._role )
858     def setRequireReauthentication( self , value ) :
859         return setRoleRequireReauthentication( self._role , value )
860     requireReauthentication = property( getRequireReauthentication ,
861                                         setRequireReauthentication )
862     #
863     # admin_type
864     #
865     def getAdminType( self ) :
866         return getRoleAdminType( self._role )
867     def setAdminType( self , value ) :
868         return setRoleAdminType( self._role , value )
869     adminType = property( getAdminType , setAdminType )
870     #
871     # remove
872     #
873     def delete( self ) :
874         removeRole( self._role )
875
876 def createRoleClass() :
877     attrs = {}
878     def addAttribute( target , name ) :
879         pname = 'default' + ''.join( [ s.capitalize() for s in name.split( '_' ) ] ) + 'Type'
880         cpname = pname[ 0 ].upper() + pname[ 1 : ]
881         #pname = 'def_%s_type' % name
882         item = getattr( headers , 'RI_def_%s_type' % name )
883         def getter( id ) :
884             raiseIfError( lib.rsbac_rc_get_item( 0 , headers.RT_ROLE ,
885                                                  id , None ,
886                                                  item , g_rcItemValueRef ,
887                                                  None ) )
888             return g_rcItemValue.type_id
889         def setter( id , value ) :
890             g_rcItemValue.type_id = value
891             raiseIfError( lib.rsbac_rc_set_item( 0 , headers.RT_ROLE ,
892                                                  id , None ,
893                                                  item , g_rcItemValueRef ,
894                                                  0 ) )
895         def mget( self ) :
896             return Type( target , getter( self._id ) )
897         def mset( self , value ) :
898             return setter( self._id , int( value ) )
899         attrs[ 'getter_' + pname ] = staticmethod( getter )
900         attrs[ 'setter_' + pname ] = staticmethod( setter )
901         #
902         attrs[ 'get' + cpname ] = mget
903         attrs[ 'set' + cpname ] = mset
904         attrs[ pname ] = property( mget , mset )
905     for target , name in (
906         ( headers.T_FD , 'fd_create' ) ,
907         ( headers.T_USER , 'user_create' ) ,
908         ( headers.T_GROUP , 'group_create' ) ,
909         ( headers.T_PROCESS , 'process_create' ) ,
910         ( headers.T_PROCESS , 'process_chown' )  ,
911         ( headers.T_PROCESS , 'process_execute' ) ,
912         ( headers.T_IPC , 'ipc_create' ) ,
913         ( headers.T_FD , 'unixsock_create' ) ) :
914         addAttribute( target , name )
915     return type( 'Role' , ( RoleBase , ) , attrs )
916
917 export( 'Role' )
918 Role = createRoleClass()
919
920 #-----------------------------------------------------------------------------
921
922 @export
923 def getTypeName( type ) :
924     """Get the name of a RC type
925
926     type -- RC type
927
928     """
929     target , type = _type( type )
930     g_rcTargetValue.type = type
931     raiseIfError( lib.rsbac_rc_get_item( transaction._t , headers.RT_TYPE ,
932                                          g_rcTargetValueRef , None ,
933                                          g_rcNameTargetToItem[ target ] ,
934                                          g_rcItemValueRef , None ) )
935     return g_rcItemValue.name
936
937 @export
938 def setTypeName( type , name ) :
939     """Set the name of a RC type
940
941     type -- RC type
942     name -- the new name as string
943
944     """
945     target , type = _type( type )
946     g_rcTargetValue.type = type
947     slowButCorrectStringAssignation( g_rcItemValue , 'name' , name )
948     raiseIfError( lib.rsbac_rc_set_item( transaction._t , headers.RT_TYPE ,
949                                          g_rcTargetValueRef , None ,
950                                          g_rcNameTargetToItem[ target ] ,
951                                          g_rcItemValueRef , 0 ) )
952
953 @export
954 def getTypeNeedSecureDelete( type ) :
955     """Test if the RC type need secure delete.
956
957     type -- RC type
958
959     """
960     target , type = _type( type )
961     g_rcTargetValue.type = type
962     if target != headers.T_FD :
963         raise RuntimeError , 'attribute available for the FD type only'
964     raiseIfError( lib.rsbac_rc_get_item( transaction._t , headers.RT_TYPE ,
965                                          g_rcTargetValueRef , None ,
966                                          headers.RI_type_fd_need_secdel ,
967                                          g_rcItemValueRef , None ) )
968     return bool( g_rcItemValue.need_secdel )
969
970 @export
971 def setTypeNeedSecureDelete( type , value ) :
972     """Set if the RC type need secure delete.
973
974     type -- RC type
975     value - boolean
976
977     """
978     target , type = _type( type )
979     g_rcTargetValue.type = type
980     if target != headers.T_FD :
981         raise RuntimeError , 'attribute available for the FD type only'
982     g_rcItemValue.need_secdel = value
983     raiseIfError( lib.rsbac_rc_set_item( transaction._t , headers.RT_TYPE ,
984                                          g_rcTargetValueRef , None ,
985                                          headers.RI_type_fd_need_secdel ,
986                                          g_rcItemValueRef , 0 ) )
987
988 @export
989 def removeType( type ) :
990     """Remove a RC type.
991
992     type -- RC type
993
994     """
995     target , type = _type( type )
996     g_rcTargetValue.type = type
997     raiseIfError( lib.rsbac_rc_set_item( transaction._t , headers.RT_TYPE ,
998                                          g_rcTargetValueRef , None ,
999                                          g_rcTargetToTypeRemove[ target ] ,
1000                                          None , 0 ) )
1001
1002 class Type( object ) :
1003     def __new__( cls , target , type ) :
1004         if hasattr( target , 'type' ) :
1005             target = target.type
1006         type = _ntype( type )
1007         if type < 0 :
1008             target = None
1009         t = ( target , type )
1010         instance = _g_types.get( t )
1011         if instance is None :
1012             instance = object.__new__( cls )
1013             instance.__init_singleton__( target , type )
1014             _g_types[ t ] = instance
1015         return instance
1016     def __init_singleton__( self , target , type ) :
1017         self.__id = ( target , type )
1018     def __eq__( self , other ) :
1019         if isinstance( other , ( int , long ) ) :
1020             return self.type == _ntype( other )
1021         else :
1022             return ( self is other
1023                      or ( isinstance( other , Type )
1024                           and self.__id == other.__id ) )
1025     def __int__( self ) :
1026         return int( self.__id[ 1 ] )
1027     def __long__( self ) :
1028         return long( self.__id[ 1 ] )
1029     def __repr__( self ) :
1030         target , type = self.__id
1031         if type < 0 :
1032             return '<RC PseudoType [%d] %s>' \
1033                 % ( type ,
1034                     _g_pseudoTypes.get( type , 'unknown' ) , )
1035         else :
1036             try :
1037                 name = `self.getName()`
1038             except Error :
1039                 name = 'undefined'
1040             return '<RC Type [%d:%d] %s>' % ( target , type , name )
1041     #
1042     # target, type
1043     #
1044     target = property( lambda self : self.__id[ 0 ] )
1045     type = property( lambda self : self.__id[ 1 ] )
1046     #
1047     # name
1048     #
1049     def getName( self ) :
1050         return getTypeName( self.__id )
1051     def setName( self , name ) :
1052         return setTypeName( self.__id , name )
1053     name = property( getName , setName )
1054     #
1055     # fd_need_secdel
1056     #
1057     def getNeedSecureDelete( self ) :
1058         return getTypeNeedSecureDelete( self.__id )
1059     def setNeedSecureDelete( self , value ) :
1060         return setTypeNeedSecureDelete( self.__id , value )
1061     needSecureDelete = property( getNeedSecureDelete , setNeedSecureDelete )
1062     #
1063     # delete
1064     #
1065     def delete( self ) :
1066         removeType( self.__id )
1067
1068 pseudoRoles = new.module( 'pseudoRoles' )
1069 for k , v in _g_pseudoRoles.items() :
1070     setattr( pseudoRoles , v , Role( k ) )
1071 pseudoTypes = new.module( 'pseudoTypes' )
1072 for k , v in _g_pseudoTypes.items() :
1073     setattr( pseudoTypes , v , Type( None , k ) )
1074
1075 class RcRoleDict( object ) :
1076     def keys( self ) :
1077         return getRoles()
1078     def items( self ) :
1079         return [ ( id , Role( id ) ) for id in self.keys() ]
1080     def values( self ) :
1081         return [ Role( id ) for id in self.keys() ]
1082     def __iter__( self ) :
1083         return iter( self.keys() )
1084     def __getitem__( self , id ) :
1085         return Role( id )
1086     def __setitem__( self , *args ) :
1087         raise RuntimeError
1088     def __delitem__( self , id ) :
1089         Role( id ).delete()
1090     def __repr__( self ) :
1091         return '{' + ', '.join( [ ': '.join( map( repr , item ) ) for item in self.items() ] ) + '}'
1092
1093 def newType( target , name , start = 0 ) :
1094     i = start
1095     if hasattr( target , 'type' ) :
1096         target = target.type
1097     while 1 :
1098         try :
1099             Type( target , i ).name
1100         except Error , e :
1101             if e[ 0 ] != headers.RSBAC_ENOTFOUND :
1102                 raise
1103             t = Type( target , i )
1104             t.name = name
1105             return t
1106         i += 1
1107
1108 class RcTypeDict( object ) :
1109     def __init__( self , target ) :
1110         self.target = target
1111     def keys( self ) :
1112         return getTypes( self.target )
1113     def items( self ) :
1114         return [ ( id , Type( self.target , id ) ) for id in self.keys() ]
1115     def values( self ) :
1116         return [ Type( self.target , id ) for id in self.keys() ]
1117     def __iter__( self ) :
1118         return iter( self.keys() )
1119     def __getitem__( self , id ) :
1120         return Type( self.target , id )
1121     def __setitem__( self , *args ) :
1122         raise RuntimeError
1123     def __delitem__( self , id ) :
1124         Type( self.target , id ).delete()
1125     def __repr__( self ) :
1126         return '{' + ', '.join( [ ': '.join( map( repr , item ) ) for item in self.items() ] ) + '}'
1127
1128 roles = RcRoleDict()
1129
1130 from rsbac._data import RequestVector
1131
1132 # Local Variables:
1133 # indent-tabs-mode: nil
1134 # python-indent: 4
1135 # End: