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