Main Page | Packages | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages

AuthenticatingMBeanServer.java

00001 /**
00002  * C-JDBC: Clustered JDBC.
00003  * Copyright (C) 2002-2004 French National Institute For Research In Computer
00004  * Science And Control (INRIA).
00005  * Contact: c-jdbc@objectweb.org
00006  * 
00007  * This library is free software; you can redistribute it and/or modify it
00008  * under the terms of the GNU Lesser General Public License as published by the
00009  * Free Software Foundation; either version 2.1 of the License, or any later
00010  * version.
00011  * 
00012  * This library is distributed in the hope that it will be useful, but WITHOUT
00013  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
00015  * for more details.
00016  * 
00017  * You should have received a copy of the GNU Lesser General Public License
00018  * along with this library; if not, write to the Free Software Foundation,
00019  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00020  *
00021  * Initial developer(s): Marc Wick.
00022  * Contributor(s): ______________________.
00023  */
00024 
00025 package org.objectweb.cjdbc.controller.jmx;
00026 
00027 import java.util.ArrayList;
00028 import java.util.Arrays;
00029 import java.util.Iterator;
00030 import java.util.List;
00031 import java.util.Set;
00032 
00033 import javax.management.InstanceNotFoundException;
00034 import javax.management.MBeanException;
00035 import javax.management.MBeanServer;
00036 import javax.management.ObjectName;
00037 import javax.management.ReflectionException;
00038 import javax.security.auth.Subject;
00039 
00040 import org.objectweb.cjdbc.common.jmx.JmxConstants;
00041 import org.objectweb.cjdbc.common.log.Trace;
00042 import org.objectweb.cjdbc.common.users.AbstractDatabaseUser;
00043 
00044 /**
00045  * An MBeanServer authenticating all invoke() requests.
00046  * 
00047  * @author <a href="mailto:marc.wick@monte-bre.ch">Marc Wick </a>
00048  * @author <a href="mailto:nicolas.modrzyk@inrialpes.fr">Nicolas Modrzyk </a>
00049  * @version 1.0
00050  */
00051 public class AuthenticatingMBeanServer extends ChainedMBeanServer
00052 {
00053 
00054   /** Logger instance */
00055   static Trace logger = Trace
00056                           .getLogger("org.objectweb.cjdbc.controller.jmx.AuthenticatingMBeanServer");
00057 
00058   /**
00059    * Overridden just to make it public
00060    * <p>
00061    * 
00062    * @see org.objectweb.cjdbc.controller.jmx.ChainedMBeanServer#setMBeanServer(javax.management.MBeanServer)
00063    */
00064   public void setMBeanServer(MBeanServer server)
00065   {
00066     super.setMBeanServer(server);
00067   }
00068 
00069   /**
00070    * @see javax.management.MBeanServerConnection#invoke(javax.management.ObjectName,
00071    *             java.lang.String, java.lang.Object[], java.lang.String[])
00072    */
00073   public Object invoke(ObjectName name, String operationName, Object[] params,
00074       String[] signature) throws InstanceNotFoundException, MBeanException,
00075       ReflectionException
00076   {
00077     if (JmxConstants.mbeanNeedAuthentication(name)
00078         && (operationName.equalsIgnoreCase("checkAdminAuthentication") == false))
00079     {
00080       // we have to check all methods that access a virtual database
00081       // except
00082       // authentication
00083       boolean authenticationOk = false;
00084       String username = null;
00085       String password = null;
00086 
00087       Subject subject = Subject.getSubject(java.security.AccessController
00088           .getContext());
00089       if (subject == null || subject.getPrincipals().size() == 0)
00090       {
00091         username = (String) params[0];
00092         password = (String) params[1];
00093         authenticationOk = authenticate(name, username, password);
00094         if (!authenticationOk)
00095           throw new MBeanException(new Exception(
00096               "Authentication failed (username,password) invalid"));
00097 
00098         if (logger.isDebugEnabled())
00099           logger
00100               .debug("Authentication with username and password was successfull");
00101 
00102         // we have to strip the username and password from the params
00103         // and args
00104         return super.invoke(name, operationName, cleanO(params),
00105             cleanS(signature));
00106       }
00107       else
00108       {
00109         Set principals = subject.getPrincipals(AbstractDatabaseUser.class);
00110         for (Iterator it = principals.iterator(); it.hasNext();)
00111         {
00112           AbstractDatabaseUser user = (AbstractDatabaseUser) it.next();
00113           username = user.getName();
00114           password = user.getPassword();
00115           authenticationOk = authenticate(name, username, password);
00116           if (authenticationOk)
00117             break;
00118         }
00119 
00120         if (principals.size() == 0 && logger.isDebugEnabled())
00121           throw new MBeanException(new Exception(
00122               "Authentication failed : no principal"));
00123 
00124         if (!authenticationOk)
00125           throw new MBeanException(new Exception(
00126               "Authentication failed : principal invalid"));
00127         if (logger.isDebugEnabled())
00128           logger.debug("Authentication with principal was successfull");
00129         return super.invoke(name, operationName, params, signature);
00130       }
00131     }
00132     else
00133     {
00134       if (logger.isDebugEnabled())
00135         logger.debug("no authentication required");
00136 
00137       return super.invoke(name, operationName, params, signature);
00138     }
00139   }
00140 
00141   private boolean authenticate(ObjectName name, String username, String password)
00142   {
00143     try
00144     {
00145       boolean vdb = name.toString().indexOf(
00146           JmxConstants.CJDBC_TYPE_VIRTUALDATABASE) != -1;
00147       if (vdb)
00148         return ((Boolean) invoke(name, "checkAdminAuthentication",
00149             new Object[]{username, password}, new String[]{"java.lang.String",
00150                 "java.lang.String"})).booleanValue();
00151       else
00152       {
00153         boolean backend = name.toString().indexOf(
00154             JmxConstants.CJDBC_TYPE_BACKEND) != -1;
00155         if (backend)
00156         {
00157           // Check with the owning database if the password is right
00158           ObjectName vdbName = JmxConstants
00159               .getVirtualDbObjectNameFromBackend(name);
00160           return ((Boolean) invoke(vdbName, "checkAdminAuthentication",
00161               new Object[]{username, password}, new String[]{
00162                   "java.lang.String", "java.lang.String"})).booleanValue();
00163         }
00164         else
00165           // No further check ...
00166           return true;
00167       }
00168     }
00169     catch (Exception e)
00170     {
00171       if (logger.isDebugEnabled())
00172       {
00173         logger.debug("authentication failed with exception ", e);
00174       }
00175       return false;
00176     }
00177   }
00178 
00179   private static Object[] cleanO(Object[] params)
00180   {
00181     List o = Arrays.asList(params);
00182     o = o.subList(2, o.size());
00183     return (new ArrayList(o).toArray());
00184   }
00185 
00186   private static String[] cleanS(String[] params)
00187   {
00188     List o = Arrays.asList(params);
00189     o = o.subList(2, o.size());
00190     String[] s = new String[o.size()];
00191     return (String[]) new ArrayList(o).toArray(s);
00192   }
00193 }

Generated on Mon Apr 11 22:01:29 2005 for C-JDBC by  doxygen 1.3.9.1