package dmg.cells.services.login ; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.io.Serializable; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import dmg.cells.nucleus.CellAdapter; import dmg.cells.nucleus.CellMessage; import dmg.cells.nucleus.CellNucleus; import dmg.util.cdb.CdbLockable; import org.dcache.util.Args; /** ** * * * @author Patrick Fuhrmann * @version 0.1, 15 Feb 1998 * */ public class UserMgrCell extends CellAdapter { private static final Logger _log = LoggerFactory.getLogger(UserMgrCell.class); private String _cellName ; private CellNucleus _nucleus ; private UserDb _userDb ; private Args _args ; private static final String [] __root_priv = { "create-user:user:*" , "create-group:user:*" , "add-user:user:*" , "add-group:user:*" , "remove-user:user:*" , "destroy-user:user:*" , "remove-group:user:*" , "destroy-group:user:*" , "modify-user:user:*" , "modify-group:user:*" , "add-allowed:user:*" , "remove-allowed:user:*" , "add-denied:user:*" , "remove-denied:user:*" , } ; public UserMgrCell(String name, String argString) { super(name, argString); _cellName = name; _args = getArgs(); } @Override protected void starting() throws Exception { if (_args.argc() < 1) { throw new IllegalArgumentException("Usage : ... <dbPath>"); } try { _userDb = new UserDb(new File(_args.argv(0)), false); } catch (Exception eee) { _userDb = new UserDb(new File(_args.argv(0)), true); // // not really necessary, because 'root' is trusted // anyway. // createRootUser(_userDb); } } private void createRootUser( UserDb db )throws Exception { UserHandle user = db.createUser( "root" ) ; user.open( CdbLockable.WRITE ) ; for (String a__root_priv : __root_priv) { user.addAllowed(a__root_priv); } user.setPassword( "elch" ) ; user.close( CdbLockable.COMMIT ) ; } private static final Class<?>[] __argListDef = { UserPrivileges.class , Object[].class } ; @Override public void messageArrived( CellMessage msg ){ Serializable obj = msg.getMessageObject() ; Serializable answer; try{ _log.info( "Message : "+obj.getClass() ) ; if( ( ! ( obj instanceof Object [] ) ) || ( ((Object[])obj).length < 3 ) || ( !((Object[])obj)[0].equals("request") ) ){ String r = "Illegal message object received from : "+ msg.getSourcePath() ; _log.warn( r ) ; throw new Exception( r ) ; } Object [] request = (Object[])obj ; String user = request[1] == null ? "unknown" : (String)request[1] ; String command = (String)request[2] ; UserPrivileges priv = _userDb.getUserPrivileges( user ) ; _log.info('>' + command + "< request from " + user ) ; try{ command = createMethodName( command ) ; Method m = this.getClass().getDeclaredMethod( command , __argListDef ) ; Object [] a = new Object[2] ; a[0] = priv ; a[1] = request ; answer = (Serializable) m.invoke( this , a ) ; }catch( InvocationTargetException ite ){ throw (Exception)ite.getTargetException() ; }catch( Exception xe ){ throw new Exception( "Command not found : "+ request[2]) ; } }catch(Exception iex ){ answer = iex ; } if( answer instanceof Object [] ) { ((Object[]) answer)[0] = "response"; } msg.revertDirection() ; msg.setMessageObject( answer ) ; try{ sendMessage( msg ) ; }catch( RuntimeException ioe ){ _log.warn( "Can't send acl_response : "+ioe ) ; } } private String createMethodName( String com ){ char c ; StringBuilder sb = new StringBuilder() ; sb.append( "acl_" ) ; for( int i = 0 ; i < com.length() ; i ++ ){ c = com.charAt(i) ; sb.append( c == '-' ? '_' : c ) ; } return sb.toString() ; } /////////////////////////////////////////////////////////////////////////// // // r[0] : request // r[1] : <anything> // r[2] : check-password // r[3] : <user> // r[4] : <password>[plainText] // // checks : nothing // // response // // r[0] : response // r[1] : <user> // r[2] : check-password // r[3] : <user> // r[4] : <password>[plainText] // r[5] : Boolean(true/false) // private Object acl_check_password( UserPrivileges priv , Object [] request ) throws Exception { if( request.length < 5 ) { throw new IllegalArgumentException( "Not enough arguments for 'check-password'"); } Object [] response = new Object[6] ; System.arraycopy(request, 0, response, 0, 5); response[1] = request[3] ; String userName = (String)request[3] ; UserHandle user = _userDb.getUserByName( userName ) ; user.open( CdbLockable.READ ) ; String password ; try{ password = user.getPassword() ; }catch(Exception e ){ user.close( CdbLockable.ABORT ) ; throw e ; } user.close( CdbLockable.COMMIT ) ; response[5] = password.equals(request[4]); return response ; } /////////////////////////////////////////////////////////////////////////// // // r[0] : request // r[1] : <anything> // r[2] : check-acl // r[3] : <user> // r[4] : <action> // r[5] : <class> // r[6] : <instance> // // checks : nothing // // response // // r[0] : response // r[1] : <user> // r[2] : check-acl // r[3] : <user> // r[4] : <action> // r[5] : <class> // r[6] : <instance> // r[7] : Boolean(true/false) // private Object acl_check_acl( UserPrivileges priv , Object [] request ) throws Exception { if( request.length < 7 ) { throw new IllegalArgumentException( "Not enough arguments for 'check-acl'"); } Object [] response = new Object[8] ; System.arraycopy(request, 0, response, 0, 7); response[1] = request[3] ; String userName = (String)request[3] ; UserPrivileges privToCheck = _userDb.getUserPrivileges( userName ) ; String p = request[4] + ":" + request[5] + ":" + request[6]; response[7] = privToCheck.isAllowed(p); return response ; } /////////////////////////////////////////////////////////////////////////// // // r[0] : request // r[1] : <user> // r[2] : create-group // r[3] : <newUser> // // checks : create-user:user:* // private Object acl_create_user( UserPrivileges priv , Object [] request ) throws Exception { if( ! priv.isAllowed( "create-user:user:*" ) ) { throw new Exception("Operation not allowed for " + priv.getUserName()); } if( request.length < 4 ) { throw new IllegalArgumentException("Not enough arguments for 'create-user'"); } _userDb.createUser( (String)request[3] ) ; return request ; } /////////////////////////////////////////////////////////////////////////// // // r[0] : request // r[1] : <user> // r[2] : get-user-attr // r[3] : <user> // // checks : nothing // private Object acl_get_user_attr( UserPrivileges priv , Object [] request ) throws Exception { if( request.length < 4 ) { throw new IllegalArgumentException("Not enough arguments for 'get-user-attr'"); } UserHandle user = _userDb.getUserByName( request[3].toString() ) ; user.open( CdbLockable.READ ) ; String eMail = user.getEmail() ; user.close( CdbLockable.COMMIT ) ; String [] p = new String[2] ; p[0] = "e-mail" ; p[1] = eMail ; Object [] answer = new Object[5] ; System.arraycopy( request , 0 , answer , 0 , 4 ) ; answer[4] = new Object[1] ; ((Object[])answer[4])[0] = p ; return answer ; } /////////////////////////////////////////////////////////////////////////// // // r[0] : request // r[1] : <user> // r[2] : set-user-attr // r[3] : <user> // r[4] -> array of ( String [2] ( key , value ) ) // // checks : nothing // private Object acl_set_user_attr( UserPrivileges priv , Object [] request ) throws Exception { if( request.length < 5 ) { throw new IllegalArgumentException("Not enough arguments for 'set-user-attr'"); } if( ! ( request[4] instanceof Object [] ) ) { throw new IllegalArgumentException("Illegal request format 'set-user-attr'"); } // // does the user exists ? // UserHandle user = _userDb.getUserByName( request[3].toString() ) ; // // is the requestor allowed to do the operation ? // if( ( ! priv.isAllowed( "set-password:user:*" ) ) && ( ! priv.getUserName().equals( request[3].toString() ) ) ) { throw new Exception("Operation not allowed for " + priv.getUserName()); } Object [] array = (Object[])request[4] ; for( int i = 0 ; i < array.length ; i++ ){ if( array[i] instanceof String [] ){ String [] pair = (String [])array[i] ; if( pair[0].equals("e-mail") ){ user.open( CdbLockable.WRITE ) ; user.setEmail( pair[1] ) ; user.close( CdbLockable.COMMIT ) ; }else{ pair[1] = "" ; } }else{ array[i] = null ; } } return request ; } /////////////////////////////////////////////////////////////////////////// // // r[0] : request // r[1] : <user> // r[2] : create-group // r[3] : <newGroup> // // checks : create-group:user:<newGroup> // private Object acl_create_group( UserPrivileges priv , Object [] request ) throws Exception { if( request.length < 4 ) { throw new IllegalArgumentException("Not enough arguments for 'create-group'"); } String groupName = (String)request[3] ; if( ! priv.isAllowed( "create-group:user:"+groupName ) ) { throw new Exception("Operation not allowed for " + priv.getUserName()); } _userDb.createGroup( groupName ) ; return request ; } /////////////////////////////////////////////////////////////////////////// // // r[0] : request // r[1] : <user> // r[2] : set-password // r[3] : <user> // r[4] : <password/plaintext> // // checks : set-password:user:* // private Object acl_set_password( UserPrivileges priv , Object [] request ) throws Exception { if( request.length < 5 ) { throw new IllegalArgumentException("Not enough arguments for 'set-password'"); } String userName = (String)request[3] ; if( ( ! priv.isAllowed( "set-password:user:*" ) ) && ( ! priv.getUserName().equals( userName ) ) ) { throw new Exception("Operation not allowed for " + priv.getUserName()); } UserHandle user = _userDb.getUserByName( userName ) ; user.open( CdbLockable.WRITE ) ; user.setPassword( (String)request[4] ) ; user.close( CdbLockable.COMMIT ) ; return request ; } /////////////////////////////////////////////////////////////////////////// // // r[0] : request // r[1] : <user> // r[2] : add-allowed // r[3] : <user/group> // r[4] : <privilege> // // checks : add-allowed:user:* ; for users // checks : add-allowed:user:<group>[.*] ; for groups // private Object acl_add_allowed( UserPrivileges priv , Object [] request ) throws Exception { if( request.length < 5 ) { throw new IllegalArgumentException("Not enough arguments for 'add-allowed'"); } String userName = (String)request[3] ; UserHandle user = _userDb.getUserByName( userName ) ; boolean isGroup ; user.open( CdbLockable.READ ) ; try{ isGroup = user.isGroup() ; } finally{ user.close( CdbLockable.COMMIT ) ; } String p ; if( isGroup ){ p = "add-allowed:user:"+userName ; if( ! priv.isAllowed( p ) ){ _log.info('>' + p + "< denied for " + priv.getUserName() ) ; throw new Exception( "Operation not allowed for "+priv.getUserName() ) ; } }else{ p = "add-allowed:user:*"; if( ! priv.isAllowed( p ) ){ _log.info('>' + p + "< denied for " + priv.getUserName() ) ; throw new Exception( "Operation not allowed for "+priv.getUserName() ) ; } } user.open( CdbLockable.WRITE ) ; try{ user.addAllowed( (String)request[4] ) ; }catch(Exception e ){ user.close( CdbLockable.ABORT ) ; throw e ; } user.close( CdbLockable.COMMIT ) ; return request ; } }