3 # py-rsbac - RSBAC Python bindings
4 # Copyright (C) 2006 Frederic Jolliton <pyrsbac@tuxee.net>
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.
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.
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
25 if not isinstance( o , basestring ) :
30 raise ImportError , 'duplicate name %r in module %r' % ( name , __name__ )
31 __all__.append( name )
34 from ctypes import byref
36 from rsbac import lib, headers, transaction
37 from rsbac._utils import stringToByteArray, aptr, slowButCorrectStringAssignation
38 from rsbac._utils import fetch, intToTtl, ttlToInt
39 from rsbac.errors import Error, raiseIfError
41 g_umModData = headers.rsbac_um_mod_data_t()
42 g_umModDataRef = byref( g_umModData )
44 # Duplicated in transaction.py
51 def auth( user , password ) :
54 user -- username as string
55 password -- password as string
58 if isinstance( user , ( int , long ) ) :
59 raiseIfError( lib.rsbac_um_auth_uid( user , password ) )
61 raiseIfError( lib.rsbac_um_auth_name( user , password ) )
63 def _makeDefaultUserEntry() :
64 userEntry = headers.rsbac_um_user_entry_t()
65 for field , value in [
69 ( 'homedir' , '/home' ) ,
70 ( 'shell' , '/bin/sh' ) ,
72 slowButCorrectStringAssignation( userEntry , field , value )
73 userEntry.group = 65534
74 userEntry.lastchange = 100000
75 userEntry.minchange = 0
76 userEntry.maxchange = 365
77 userEntry.warnchange = 10
78 userEntry.inactive = 3
79 userEntry.expire = 100000
82 def _makeDefaultGroupEntry() :
83 groupEntry = headers.rsbac_um_group_entry_t()
85 setattr( groupEntry , 'pass' , '' ) # because 'pass' is a keyword
89 def addUser( name , uid = None , password = None , ttl = None ) :
90 """Add a user to the UM module.
92 name -- username as string
93 uid -- None or a prefered UID as integer
94 password -- None or a default password as string
95 ttl -- None or an integer
97 Returns the UID of the newly created user.
102 ttl = ttlToInt( ttl )
103 userEntry = _makeDefaultUserEntry()
104 slowButCorrectStringAssignation( userEntry , 'name' , name )
105 raiseIfError( lib.rsbac_um_add_user( transaction._t , uid ,
106 byref( userEntry ) , password ,
108 # Let's hope that there are no race conditions at this point.
109 return getUid( name )
112 def addGroup( name , gid = None , password = None , ttl = None ) :
113 """Add a group to the UM module.
115 name -- group name as string
116 gid -- None or a prefered GID as integer
117 password -- None or a default password as string
118 ttl -- None or an integer
123 ttl = ttlToInt( ttl )
124 groupEntry = _makeDefaultGroupEntry()
125 slowButCorrectStringAssignation( groupEntry , 'name' , name )
126 raiseIfError( lib.rsbac_um_add_group( transaction._t , gid ,
127 byref( groupEntry ) , password ,
129 # Let's hope that there are no race conditions at this point.
130 return getGid( name )
133 def addToGroups( uid , gid , ttl = None ) :
134 """Add an UM user to an UM group.
136 uid -- UID as integer
137 gid -- GID as integer
138 ttl -- None or an integer
141 ttl = ttlToInt( ttl )
142 raiseIfError( lib.rsbac_um_add_gm( transaction._t , uid , gid , ttl ) )
145 def removeUser( uid ) :
146 """Remove an UM user.
148 uid -- UID as integer
151 raiseIfError( lib.rsbac_um_remove_user( transaction._t , uid ) )
154 def removeGroup( gid ) :
155 """Remove an UM group.
157 gid -- GID as integer
160 raiseIfError( lib.rsbac_um_remove_group( transaction._t , gid ) )
163 def removeFromGroups( uid , gid ) :
164 """Remove an UM user from an UM group.
166 uid -- UID as integer
167 gid -- GID as integer
170 raiseIfError( lib.rsbac_um_remove_gm( transaction._t , uid , gid ) )
173 def userExists( uid ) :
174 """Test if an UM user exists.
176 uid -- UID as integer
181 return bool( raiseIfError( lib.rsbac_um_user_exists( transaction._t , uid ) ) )
184 def groupExists( gid ) :
185 """Test if an UM group exists.
187 gid -- GID as integer
192 return bool( raiseIfError( lib.rsbac_um_group_exists( transaction._t , gid ) ) )
195 def getNextUser( uid = None ) :
196 """Get the user following the one given in argument.
198 uid -- None (to get the first user) or an UID as integer
200 Returns an UID as integer.
205 value = headers.rsbac_uid_t()
206 raiseIfError( lib.rsbac_um_get_next_user( transaction._t , uid , byref( value ) ) )
207 return int( value.value )
211 """Get the list of all UM users.
213 Returns a list of UID.
216 arr = fetch( headers.rsbac_uid_t ,
217 lambda n , a : lib.rsbac_um_get_user_list( transaction._t , a , n ) )
218 return sorted( map( int , arr ) )
221 def getGroupsList( uid ) :
222 """Get the extra groups to which an UM user belong.
224 uid -- an UID as integer
226 Returns a list of GID.
229 arr = fetch( headers.rsbac_gid_t ,
230 lambda n , a : lib.rsbac_um_get_gm_list( transaction._t , uid , a , n ) )
231 return sorted( map( int , arr ) )
234 def getGroupsUserList( gid ) :
235 """Get the users which are in an extra group.
237 gid -- GID as integer
239 Returns a list of UID.
242 arr = fetch( headers.rsbac_uid_t ,
243 lambda n , a : lib.rsbac_um_get_gm_user_list( transaction._t , gid , a , n ) )
244 return sorted( map( int , arr ) )
248 """Get the list of all UM groups.
250 Returns a list of GID.
253 arr = fetch( headers.rsbac_gid_t ,
254 lambda n , a : lib.rsbac_um_get_group_list( transaction._t , a , n ) )
255 return sorted( map( int , arr ) )
259 """Get the UID from the username.
261 name -- username as string
263 Returns the UID as integer.
266 value = headers.rsbac_uid_t()
267 raiseIfError( lib.rsbac_um_get_uid( transaction._t , name , byref( value ) ) )
268 return int( value.value )
272 """Get the GID from the group name.
274 name -- group name as string
277 value = headers.rsbac_gid_t()
278 raiseIfError( lib.rsbac_um_get_gid( transaction._t , name , byref( value ) ) )
279 return int( value.value )
282 def getUserName( uid ) :
283 """Get the name of an UM user.
285 uid -- UID as integer
287 Returns the username as string.
290 raiseIfError( lib.rsbac_um_get_user_item( transaction._t , uid ,
293 return g_umModData.string
296 def setUserName( uid , name ) :
297 """Set the name of an UM user.
299 uid -- UID as integer
300 name -- username as string
303 g_umModData.string = name
304 raiseIfError( lib.rsbac_um_mod_user( transaction._t , uid ,
309 def getUserHashedPassword( uid ) :
310 """Get the user hashed password.
312 uid -- UID as integer
314 Returns the hashed password.
317 raiseIfError( lib.rsbac_um_get_user_item( transaction._t , uid ,
320 return g_umModData.string
323 def setUserHashedPassword( uid , password ) :
324 """Set the user hashed password.
326 uid -- UID as integer
327 password -- hashed password as string
330 slowButCorrectStringAssignation( g_umModData , 'string' , password )
331 raiseIfError( lib.rsbac_um_mod_user( transaction._t , uid ,
332 headers.UM_cryptpass ,
336 def setUserPassword( uid , password ) :
337 """Set the user password.
339 uid -- UID as integer
340 password -- password as string
343 slowButCorrectStringAssignation( g_umModData , 'string' , password )
344 raiseIfError( lib.rsbac_um_mod_user( transaction._t , uid ,
349 def getUserFullname( uid ) :
350 """Get the full name of an UM user.
352 uid -- UID as integer
354 Returns the full name as string.
357 data = headers.rsbac_um_mod_data_t()
358 raiseIfError( lib.rsbac_um_get_user_item( transaction._t , uid ,
359 headers.UM_fullname ,
361 return g_umModData.string
364 def setUserFullname( uid , name ) :
365 """Set the full name of an UM user.
367 uid -- UID as integer
368 name -- full name as string
371 slowButCorrectStringAssignation( g_umModData , 'string' , name )
372 raiseIfError( lib.rsbac_um_mod_user( transaction._t , uid ,
373 headers.UM_fullname ,
377 def getUserHomeDirectory( uid ) :
378 """Get the home directory of an UM user.
380 uid -- UID as integer
382 Returns the home directory as string.
385 raiseIfError( lib.rsbac_um_get_user_item( transaction._t , uid ,
388 return g_umModData.string
391 def setUserHomeDirectory( uid , directory ) :
392 """Set the home directory of an UM user.
394 uid -- UID as integer
395 directory -- directory as string
398 data = headers.rsbac_um_mod_data_t()
399 slowButCorrectStringAssignation( g_umModData , 'string' , directory )
400 raiseIfError( lib.rsbac_um_mod_user( transaction._t , uid ,
405 def getUserShell( uid ) :
406 """Get the shell of an UM user.
408 uid -- UID as integer
410 Returns the shell path as string.
413 raiseIfError( lib.rsbac_um_get_user_item( transaction._t , uid ,
416 return g_umModData.string
419 def setUserShell( uid , shell ) :
420 """Set the shell of an UM user.
422 uid -- UID as integer
423 shell -- shell path as string
426 slowButCorrectStringAssignation( g_umModData , 'string' , shell )
427 raiseIfError( lib.rsbac_um_mod_user( transaction._t , uid ,
432 def getUserGroup( uid ) :
433 """Get the group of an UM user.
435 uid -- UID as integer
437 Returns the GID as integer.
440 raiseIfError( lib.rsbac_um_get_user_item( transaction._t , uid ,
443 return int( g_umModData.group )
446 def setUserGroup( uid , group ) :
447 """Set the group of an UM user.
449 uid -- UID as integer
450 group -- GID as integer
453 g_umModData.group = int( group )
454 raiseIfError( lib.rsbac_um_mod_user( transaction._t , uid ,
459 def getUserTtl( uid ) :
460 """Get the TTL of an UM user.
462 uid -- UID as integer
464 Returns either None (no TTL) or a non-negative integer.
467 raiseIfError( lib.rsbac_um_get_user_item( transaction._t , uid ,
470 return intToTtl( g_umModData.ttl )
473 def setUserTtl( uid , ttl ) :
474 """Set the TTL of an UM user.
476 uid -- UID as integer
477 ttl -- None or an integer.
480 g_umModData.ttl = ttl
481 raiseIfError( lib.rsbac_um_mod_user( transaction._t , uid ,
486 def updateUserPassword( uid , old , new ) :
487 """Update the password of an UM user.
489 uid -- UID as integer
490 old -- previous password as string
491 new -- new password as string
494 raiseIfError( lib.rsbac_um_set_pass( uid , old , new ) )
497 def updateUserPasswordByName( name , old , new ) :
498 """Update the password of an UM user.
500 name -- username as string
501 old -- previous password as string
502 new -- new password as string
505 raiseIfError( lib.rsbac_um_set_pass( name , old , new ) )
508 def checkAccount( uid ) :
509 """Check an UM user account.
511 Check if an account password is still valid and have not
512 expired. If not, an exception is thrown.
514 uid -- UID as integer
517 raiseIfError( lib.rsbac_um_check_account( uid ) )
520 def checkAccountByName( name ) :
521 """Check an UM user account.
523 Check if an account password is still valid and have not
524 expired. If not, an exception is thrown.
526 name -- username as string
529 raiseIfError( lib.rsbac_um_check_account_name( name ) )
532 def getGroupName( gid ) :
533 """Get the name of an UM group.
535 gid -- GID as integer
537 Returns the group name as string.
540 raiseIfError( lib.rsbac_um_get_group_item( transaction._t , gid ,
543 return g_umModData.string
546 def setGroupName( gid , name ) :
547 """Set the name of an UM group.
549 gid -- GID as integer
550 name -- group name as string
553 slowButCorrectStringAssignation( g_umModData , 'string' , name )
554 raiseIfError( lib.rsbac_um_mod_group( transaction._t , gid ,
559 def getGroupHashedPassword( gid ) :
560 """Get the hashed password of an UM group.
562 gid -- GID as integer
564 Returns the hashed password as string.
567 raiseIfError( lib.rsbac_um_get_group_item( transaction._t , self.id ,
570 return g_umModData.string
573 def setGroupHashedPassword( gid , password ) :
574 """Set the hashed password of an UM group.
576 gid -- GID as integer
577 password -- hashed password as string
580 slowButCorrectStringAssignation( g_umModData , 'string' , password )
581 raiseIfError( lib.rsbac_um_mod_group( transaction._t , gid ,
582 headers.UM_cryptpass ,
586 def setGroupPassword( gid , password ) :
587 """Set the password of an UM group.
589 gid -- GID as integer
590 passowrd -- password as string
593 raiseIfError( lib.rsbac_um_set_group_pass( gid , password ) )
596 def setGroupPasswordItem( gid , password ) :
597 """Set the password of an UM group.
599 gid -- GID as integer
600 password -- password as string
603 slowButCorrectStringAssignation( g_umModData , 'string' , password )
604 raiseIfError( lib.rsbac_um_mod_group( transaction._t , gid ,
609 def getGroupTtl( gid ) :
610 """Get the TTL of an UM group
612 gid -- GID as integer
614 Returns None or a positive integer.
617 raiseIfError( lib.rsbac_um_get_group_item( transaction._t , gid ,
620 return intToTtl( g_umModData.ttl )
623 def setGroupTtl( gid , ttl ) :
624 """Set the TTL of an UM group
626 gid -- GID as integer
627 ttl -- None or an integer.
630 g_umModData.ttl = ttl
631 raiseIfError( lib.rsbac_um_mod_group( transaction._t , gid ,
636 class UserGroups( object ) :
637 def __init__( self , uid ) :
639 def __iter__( self ) :
640 return iter( getGroupsList( self._uid ) )
641 def __repr__( self ) :
642 return '<Groups for user %d: %s>' % ( self._uid , list( self ) or 'none' )
643 def add( self , gid , ttl = None ) :
644 addToGroups( self._uid , gid , ttl )
645 def discard( self , gid ) :
646 removeFromGroups( self._uid , gid )
648 map( self.discard , self )
650 class UserBase( object ) :
651 def __init__( self , uid ) :
653 self.groups = UserGroups( self.id )
654 def __int__( self ) :
655 return int( self.id )
656 def __long__( self ) :
657 return long( self.id )
658 def __repr__( self ) :
660 name = `self.getName()`
662 if e[ 0 ] != headers.RSBAC_ENOTFOUND :
672 if e[ 0 ] != headers.RSBAC_ENOTFOUND :
675 return '<UM User [%d]%s %s>' % ( self.id , ttl , name )
679 def getName( self ) :
680 return getUserName( self.id )
681 def setName( self , name ) :
683 return setUserName( self.id , name )
687 addUser( name , self.id )
688 name = property( getName , setName )
692 # UT: get(UM_pass) == set(UM_pass)?
693 def getHashedPassword( self ) :
694 return getUserHashedPassword( self.id )
695 def setHashedPassword( self , password ) :
696 return setUserHashedPassword( self.id , password )
697 hashedPassword = property( getHashedPassword , setHashedPassword )
701 def setPassword( self , password ) :
702 return setUserPassword( self.id , password )
703 password = property( fset = setPassword )
707 def getFullname( self ) :
708 return getUserFullname( self.id )
709 def setFullname( self , name ) :
710 return setUserFullname( self.id , name )
711 fullname = property( getFullname , setFullname )
715 def getHomeDirectory( self ) :
716 return getUserHomeDirectory( self.id )
717 def setHomeDirectory( self , directory ) :
718 return setUserHomeDirectory( self.id , directory )
719 homeDirectory = property( getHomeDirectory , setHomeDirectory )
723 def getShell( self ) :
724 return getUserShell( self.id )
725 def setShell( self , shell ) :
726 return setUserShell( self.id , shell )
727 shell = property( getShell , setShell )
731 def getGroup( self ) :
732 return Group( getUserGroup( self.id ) )
733 def setGroup( self , gid ) :
734 return setUserGroup( self.id , int( gid ) )
735 group = property( getGroup , setGroup )
740 return intToTtl( getUserTtl( self.id ) )
741 def setTtl( self , ttl ) :
742 return setUserTtl( self.id , ttlToInt( ttl ) )
743 ttl = property( getTtl , setTtl )
751 def getExists( self ) :
752 return userExists( self.id )
753 exists = property( getExists )
757 def updatePassword( self , old , new ) :
758 updateUserPassword( self.id , old , new )
760 removeUser( self.id )
762 def buildUserClass() :
764 def addDaysField( name ) :
765 cname = name[ 0 ].upper() + name[ 1 : ]
766 item = getattr( headers , 'UM_' + name.lower() )
768 raiseIfError( lib.rsbac_um_get_user_item( transaction._t , self.id ,
771 return g_umModData.days
772 def set( self , value ) :
773 g_umModData.days = value
774 raiseIfError( lib.rsbac_um_mod_user( transaction._t , self.id ,
777 attrs[ 'get' + cname ] = get
778 attrs[ 'set' + cname ] = set
779 attrs[ name ] = property( get , set )
780 for name in 'lastChange' , 'minChange' , 'maxChange' , 'warnChange' , 'inactive' , 'expire' :
782 return type( 'User' , ( UserBase , ) , attrs )
784 User = buildUserClass()
786 class Group( object ) :
787 def __init__( self , gid ) :
789 def __int__( self ) :
790 return int( self.id )
791 def __long__( self ) :
792 return long( self.id )
793 def __repr__( self ) :
795 name = `self.getName()`
797 if e[ 0 ] != headers.RSBAC_ENOTFOUND :
807 if e[ 0 ] != headers.RSBAC_ENOTFOUND :
810 return '<UM Group [%d]%s %s>' % ( self.id , ttl , name )
814 def getName( self ) :
815 return getGroupName( self.id )
816 def setName( self , name ) :
817 return setGroupName( self.id , name )
818 name = property( getName , setName )
822 def getHashedPassword( self ) :
823 return getGroupHashedPassword( self.id )
824 def setHashedPassword( self , password ) :
825 return setGroupHashedPassword( self.id , password )
826 hashedPassword = property( getHashedPassword , setHashedPassword )
830 def setPassword( self , password ) :
831 return setGroupPassword( self.id , password )
832 password = property( fset = setPassword )
837 return intToTtl( getGroupTtl( self.id ) )
838 def setTtl( self , ttl ) :
839 return setGroupTtl( self.id , ttlToInt( ttl ) )
840 ttl = property( getTtl , setTtl )
844 def getMembers( self ) :
845 return tuple( [ User( uid ) for uid in getUserList()
846 if getUserGroup( uid ) == self.id ] )
847 members = property( getMembers )
851 def getExtraMembers( self ) :
852 return tuple( map( User , getGroupsUserList( self.id ) ) )
853 extraMembers = property( getExtraMembers )
857 def getExists( self ) :
858 return groupExists( self.id )
859 exists = property( getExists )
863 def updatePassword( self , password ) :
864 setGroupPassword( self.id , password )
866 removeGroup( self.id )
868 class UmUserDict( object ) :
869 def __iter__( self ) :
870 return iter( getUserList() )
871 def __delitem__( self , uid ) :
873 def __getitem__( self , uid ) :
875 def __repr__( self ) :
876 return '{' + ', '.join( [ ': '.join( map( repr , item ) ) for item in self.items() ] ) + '}'
880 return map( User , self.keys() )
882 return [ ( uid , User( uid ) ) for uid in self.keys() ]
884 map( self.__delitem__ , self )
888 class UmGroupDict( object ) :
889 def __iter__( self ) :
890 return iter( getGroupList() )
891 def __delitem__( self , gid ) :
893 def __getitem__( self , gid ) :
895 def __repr__( self ) :
896 return '{' + ', '.join( [ ': '.join( map( repr , item ) ) for item in self.items() ] ) + '}'
898 return getGroupList()
900 return map( Group , self.keys() )
902 return [ ( gid , Group( gid ) ) for gid in self.keys() ]
904 map( self.__delitem__ , self )
906 groups = UmGroupDict()
909 # indent-tabs-mode: nil