// $Id: UserSecurityCell.java,v 1.4 2006-12-15 10:58:14 tigran Exp $
package dmg.cells.services.login.user ;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.Serializable;
import java.util.Enumeration;
import dmg.cells.nucleus.CellAdapter;
import dmg.cells.nucleus.CellMessage;
import dmg.cells.nucleus.CellNucleus;
import org.dcache.util.Args;
import dmg.util.Authorizable;
import dmg.util.AuthorizedString;
import dmg.util.CommandPanicException;
import dmg.util.CommandSyntaxException;
import dmg.util.CommandThrowableException;
/**
**
*
*
* @author Patrick Fuhrmann
* @version 0.1, 15 Feb 1998
*
*/
public class UserSecurityCell
extends CellAdapter {
private static final Logger _log =
LoggerFactory.getLogger(UserSecurityCell.class);
private final String _cellName ;
private final CellNucleus _nucleus ;
private final Args _args ;
private AclDb _aclDb;
private UserRelationable _userDb;
private UserMetaDb _userMetaDb;
public UserSecurityCell(String name, String argString)
{
super(name, argString);
_cellName = name;
_args = getArgs();
_nucleus = getNucleus();
}
@Override
protected void starting()
{
if (_args.argc() < 1) {
throw new IllegalArgumentException("Usage : ... <dbPath>");
}
File dbBase = new File(_args.argv(0));
_aclDb = new AclDb(new File(dbBase, "acls"));
_userDb = new InMemoryUserRelation(new FileUserRelation(new File(dbBase, "relations")));
_userMetaDb = new UserMetaDb(new File(dbBase, "meta"));
}
@Override
public void messageArrived( CellMessage msg ){
Serializable obj = msg.getMessageObject() ;
Serializable answer;
try{
_log.info( "Message type : "+obj.getClass() ) ;
if( ( obj instanceof Object [] ) &&
( ((Object[])obj).length >= 3 ) &&
( ((Object[])obj)[0].equals("request") ) ){
Object [] request = (Object[])obj ;
String user = request[1] == null ?
"unknown" : (String)request[1] ;
String command = (String)request[2] ;
_log.info('>' + command + "< request from " + user );
//FIXME: refactoring required
try{
if( command.equals( "check-password" ) ) {
answer = acl_check_password(request);
} else {
throw new Exception("Command not found : " + command);
}
}catch( Exception xe ){
throw new Exception( "Problem : "+xe ) ;
}
}else if( obj instanceof AuthorizedString ){
String command = obj.toString() ;
String user = ((Authorizable)obj).getAuthorizedPrincipal() ;
answer = execAuthorizedString( user , command ) ;
}else{
String r = "Illegal message object received from : "+
msg.getSourcePath() ;
_log.warn( r ) ;
throw new Exception( r ) ;
}
}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, ioe ) ;
}
}
private Serializable execAuthorizedString( String user , String command )
throws Exception {
if( user == null || user.isEmpty()) {
throw new
Exception("Not authenticated");
}
if (command.trim().isEmpty()) {
return "";
}
try{
return command( new Args( command + " -auth="+user ) ) ;
}catch( CommandPanicException cte ){
throw (Exception)cte.getTargetException() ;
}catch( CommandThrowableException cte ){
throw (Exception)cte.getTargetException() ;
}
}
///////////////////////////////////////////////////////////////////////////
//
// 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 Serializable
acl_check_password( Object [] request )
{
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] ;
response[5] = true;
return response ;
}
private void checkPermission( String user , String acl )
throws AclPermissionException {
if( user == null ) {
throw new
AclPermissionException("Not authenticated");
}
if( ! user.equals("admin") ){
if( ! _aclDb.check(acl,user,_userDb) ) {
throw new
AclPermissionException("Acl >" + acl + "< negative for " + user);
}
}
}
/////////////////////////////////////////////////////////////
//
// the interpreter
//
public static final String hh_show_all = "<user> exception|null|object|string" ;
public Object ac_show_all_$_1( Args args )throws Exception {
String user = args.getOpt("auth") ;
if( user == null ) {
throw new Exception("Not authenticated");
}
String command = args.argv(0) ;
_log.info( "show all : mode="+command+";user=user") ;
if( command.equals("exception") ) {
throw new
Exception("hallo otto");
}
if( command.equals("null") ) {
return null;
}
if( command.equals("object") ) {
return args;
}
return "Done" ;
}
public static final String hh_check_permission = "<user> <acl>" ;
public Object ac_check_permission_$_2( Args args )
{
try{
checkPermission( args.argv(0) , args.argv(1) ) ;
return true;
}catch( AclPermissionException e ){
return false;
}
}
public static final String hh_create_user = "<userName>" ;
public String ac_create_user_$_1( Args args )throws Exception {
checkPermission( args.getOpt("auth" ) , "user.*.create" ) ;
String user = args.argv(0) ;
_userMetaDb.createUser( user ) ;
return "" ;
}
public static final String hh_create_group = "<groupName>" ;
public String ac_create_group_$_1( Args args )throws Exception {
checkPermission( args.getOpt("auth" ) , "user.*.create" ) ;
String group = args.argv(0) ;
_userMetaDb.createGroup( group ) ;
_userDb.createContainer( group ) ;
_aclDb.createAclItem( "group."+group+".access" ) ;
return "" ;
}
public static final String hh_destroy_principal = "<principalName>" ;
public String ac_destroy_principal_$_1( Args args )throws Exception {
checkPermission( args.getOpt("auth" ) , "user.*.create" ) ;
String user = args.argv(0) ;
Enumeration<String> e = _userDb.getElementsOf(user) ;
if( e.hasMoreElements() ) {
throw new
DatabaseException("Not Empty : " + user);
}
e = _userDb.getParentsOf(user) ;
if( e.hasMoreElements() ) {
throw new
DatabaseException("Still in groups : " + user);
}
_userMetaDb.removePrincipal( user ) ;
try{
_userDb.removeContainer( user ) ;
_aclDb.removeAclItem( "group."+user+".access" ) ;
}catch( Exception ee ){
_log.warn(args + " : " + ee ) ;
//
// not an error
//
// System.err.println(" removeContainer : "+ee ) ;
}
return "" ;
}
public static final String hh_add = "<principalName> to <groupName>" ;
public String ac_add_$_3( Args args )throws Exception {
if( ! args.argv(1).equals("to") ) {
throw new
CommandSyntaxException("keyword 'to' missing");
}
String group = args.argv(2) ;
String princ = args.argv(0) ;
checkPermission( args.getOpt("auth" ) , "group."+group+".access" ) ;
_userDb.addElement(group, princ);
return "" ;
}
public static final String hh_remove = "<principalName> from <groupName>" ;
public String ac_remove_$_3( Args args )throws Exception {
if( ! args.argv(1).equals("from") ) {
throw new
CommandSyntaxException("keyword 'from' missing");
}
String group = args.argv(2) ;
String princ = args.argv(0) ;
checkPermission( args.getOpt("auth" ) , "group."+group+".access" ) ;
_userDb.removeElement(group,princ);
return "" ;
}
public static final String hh_add_access = "[-allowed|-denied] <acl> <principal>" ;
public String ac_add_access_$_2( Args args )throws Exception {
boolean allowed = !args.hasOption("denied") ;
String acl = args.argv(0) ;
String princ = args.argv(1) ;
checkPermission( args.getOpt("auth") , "acl."+acl+".access" ) ;
if( allowed ){
_aclDb.addAllowed( acl , princ ) ;
}else{
_aclDb.addDenied( acl , princ ) ;
}
return "" ;
}
public static final String hh_create_acl = "<aclName>" ;
public String ac_create_acl_$_1( Args args )throws Exception {
checkPermission( args.getOpt("auth") , "super.access" ) ;
_aclDb.createAclItem(args.argv(0));
return "" ;
}
public static final String hh_ls_acl = "<aclName> -resolve" ;
public String ac_ls_acl_$_1( Args args )throws Exception {
if( _aclDb == null ) {
throw new Exception("AclDb not open");
}
boolean resolve = args.hasOption("resolve") ;
AcDictionary dict = _aclDb.getPermissions(args.argv(0),resolve);
Enumeration<String> e = dict.getPrincipals() ;
String inherits = dict.getInheritance() ;
StringBuilder sb = new StringBuilder() ;
if( inherits == null ) {
sb.append("<resolved>\n");
} else {
sb.append("<inherits=").append(inherits).append(">\n");
}
while( e.hasMoreElements() ){
String user = e.nextElement();
sb.append(user).append(" -> ").append(dict.getPermission(user))
.append('\n');
}
return sb.toString() ;
}
}