// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package com.netscape.cmscore.authorization; import java.util.Arrays; import java.util.Enumeration; import java.util.Hashtable; import java.util.List; import java.util.Vector; import org.apache.commons.codec.binary.StringUtils; import com.netscape.certsrv.apps.CMS; import com.netscape.certsrv.authentication.IAuthToken; import com.netscape.certsrv.authorization.AuthzManagerProxy; import com.netscape.certsrv.authorization.AuthzMgrPlugin; import com.netscape.certsrv.authorization.AuthzToken; import com.netscape.certsrv.authorization.EAuthzAccessDenied; import com.netscape.certsrv.authorization.EAuthzException; import com.netscape.certsrv.authorization.EAuthzMgrNotFound; import com.netscape.certsrv.authorization.EAuthzMgrPluginNotFound; import com.netscape.certsrv.authorization.EAuthzUnknownRealm; import com.netscape.certsrv.authorization.IAuthzManager; import com.netscape.certsrv.authorization.IAuthzSubsystem; import com.netscape.certsrv.base.EBaseException; import com.netscape.certsrv.base.IConfigStore; import com.netscape.certsrv.base.ISubsystem; import com.netscape.certsrv.logging.ILogger; import com.netscape.cmscore.util.Debug; /** * Default authorization subsystem *

* * @author cfu * @version $Revision$, $Date$ */ public class AuthzSubsystem implements IAuthzSubsystem { public static final String ID = "authz"; public Hashtable mAuthzMgrPlugins = new Hashtable(); public Hashtable mAuthzMgrInsts = new Hashtable(); private String mId = "authz"; private IConfigStore mConfig = null; private ILogger mLogger = null; // singleton enforcement private static AuthzSubsystem mInstance = new AuthzSubsystem(); public static synchronized AuthzSubsystem getInstance() { return mInstance; } // end singleton enforcement. private AuthzSubsystem() { } /** * Initializes the authorization subsystem from the config store. * Load Authorization manager plugins, create and initialize * initialize authorization manager instances. * * @param owner The owner of this module. * @param config The configuration store. */ public void init(ISubsystem owner, IConfigStore config) throws EBaseException { try { mLogger = CMS.getLogger(); mConfig = config; // get authz manager plugins. IConfigStore c = config.getSubStore(PROP_IMPL); Enumeration mImpls = c.getSubStoreNames(); while (mImpls.hasMoreElements()) { String id = mImpls.nextElement(); String pluginPath = c.getString(id + "." + PROP_CLASS); AuthzMgrPlugin plugin = new AuthzMgrPlugin(id, pluginPath); mAuthzMgrPlugins.put(id, plugin); } if (Debug.ON) { Debug.trace("loaded authz plugins"); } // get authz manager instances. c = config.getSubStore(PROP_INSTANCE); Enumeration instances = c.getSubStoreNames(); while (instances.hasMoreElements()) { String insName = instances.nextElement(); String implName = c.getString(insName + "." + PROP_PLUGIN); AuthzMgrPlugin plugin = mAuthzMgrPlugins.get(implName); if (plugin == null) { log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTHZ_PLUGIN_NOT_FOUND", implName)); throw new EAuthzMgrPluginNotFound(CMS.getUserMessage("CMS_AUTHORIZATION_AUTHZMGR_PLUGIN_NOT_FOUND", implName)); } else { CMS.debug( CMS.getLogMessage("CMSCORE_AUTHZ_PLUGIN_FOUND", implName)); } String className = plugin.getClassPath(); boolean isEnable = false; // Instantiate and init the authorization manager. IAuthzManager authzMgrInst = null; try { authzMgrInst = (IAuthzManager) Class.forName(className).newInstance(); IConfigStore authzMgrConfig = c.getSubStore(insName); authzMgrInst.init(insName, implName, authzMgrConfig); isEnable = true; log(ILogger.LL_INFO, CMS.getLogMessage("CMSCORE_AUTHZ_INSTANCE_ADDED", insName)); } catch (ClassNotFoundException e) { String errMsg = "AuthzSubsystem:: init()-" + e.toString(); log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", errMsg)); throw new EAuthzException(CMS.getUserMessage("CMS_AUTHORIZATION_LOAD_CLASS_FAIL", className)); } catch (IllegalAccessException e) { String errMsg = "AuthzSubsystem:: init()-" + e.toString(); log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", errMsg)); throw new EAuthzException(CMS.getUserMessage("CMS_AUTHORIZATION_LOAD_CLASS_FAIL", className)); } catch (InstantiationException e) { String errMsg = "AuthzSubsystem: init()-" + e.toString(); log(ILogger.LL_FAILURE, CMS.getLogMessage("OPERATION_ERROR", errMsg)); throw new EAuthzException(CMS.getUserMessage("CMS_AUTHORIZATION_LOAD_CLASS_FAIL", className)); } catch (EBaseException e) { log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTHZ_PLUGIN_INIT_FAILED", insName, e.toString())); // it is mis-configurated. This give // administrator another chance to // fix the problem via console CMS.debug(e); } catch (Throwable e) { log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTHZ_PLUGIN_INIT_FAILED", insName, e.toString())); // Skip the authorization instance if // it is mis-configurated. This give // administrator another chance to // fix the problem via console CMS.debug(e); } // add manager instance to list. mAuthzMgrInsts.put(insName, new AuthzManagerProxy(isEnable, authzMgrInst)); if (Debug.ON) { Debug.trace("loaded authz instance " + insName + " impl " + implName); } } } catch (EBaseException ee) { if (CMS.isPreOpMode()) return; throw ee; } log(ILogger.LL_INFO, CMS.getLogMessage("INIT_DONE", getId())); } /** * authMgrzAccessInit is for servlets who want to initialize their * own authorization information before full operation. It is supposed * to be called during the init() method of a servlet. * * @param authzMgrName The authorization manager name * @param accessInfo the access information to be initialized. currently it's acl string in the format specified in * the authorization manager */ public void authzMgrAccessInit(String authzMgrInstName, String accessInfo) throws EAuthzMgrNotFound, EBaseException { AuthzManagerProxy proxy = mAuthzMgrInsts.get(authzMgrInstName); if (proxy == null) { throw new EAuthzMgrNotFound(CMS.getUserMessage("CMS_AUTHORIZATION_AUTHZMGR_NOT_FOUND", authzMgrInstName)); } if (!proxy.isEnable()) { throw new EAuthzMgrNotFound(CMS.getUserMessage("CMS_AUTHORIZATION_AUTHZMGR_NOT_FOUND", authzMgrInstName)); } IAuthzManager authzMgrInst = proxy.getAuthzManager(); if (authzMgrInst == null) { throw new EAuthzMgrNotFound(CMS.getUserMessage("CMS_AUTHORIZATION_AUTHZMGR_NOT_FOUND", authzMgrInstName)); } authzMgrInst.accessInit(accessInfo); } /** * Authorization to the named authorization manager instance * * @param authzMgrName The authorization manager name * @param authToken the authentication token associated with a user * @param resource the resource protected by the authorization system * @param operation the operation for resource protected by the authoriz * n system * @exception EBaseException If an error occurs during authorization. * @return a authorization token. */ public AuthzToken authorize( String authzMgrInstName, IAuthToken authToken, String resource, String operation, String realm) throws EAuthzMgrNotFound, EBaseException { AuthzManagerProxy proxy = mAuthzMgrInsts.get(authzMgrInstName); if (proxy == null) { throw new EAuthzMgrNotFound(CMS.getUserMessage("CMS_AUTHORIZATION_AUTHZMGR_NOT_FOUND", authzMgrInstName)); } if (!proxy.isEnable()) { throw new EAuthzMgrNotFound(CMS.getUserMessage("CMS_AUTHORIZATION_AUTHZMGR_NOT_FOUND", authzMgrInstName)); } IAuthzManager authzMgrInst = proxy.getAuthzManager(); if (authzMgrInst == null) { throw new EAuthzMgrNotFound(CMS.getUserMessage("CMS_AUTHORIZATION_AUTHZMGR_NOT_FOUND", authzMgrInstName)); } if ((realm != null) && (resource != null)) { resource = realm + "." + resource; } return (authzMgrInst.authorize(authToken, resource, operation)); } @Override public AuthzToken authorize(String authzMgrName, IAuthToken authToken, String resource, String operation) throws EBaseException { return authorize(authzMgrName, authToken, resource, operation, null); } @Override public AuthzToken authorize( String authzMgrInstName, IAuthToken authToken, String exp) throws EAuthzMgrNotFound, EBaseException { AuthzManagerProxy proxy = mAuthzMgrInsts.get(authzMgrInstName); if (proxy == null) { throw new EAuthzMgrNotFound(CMS.getUserMessage("CMS_AUTHORIZATION_AUTHZMGR_NOT_FOUND", authzMgrInstName)); } if (!proxy.isEnable()) { throw new EAuthzMgrNotFound(CMS.getUserMessage("CMS_AUTHORIZATION_AUTHZMGR_NOT_FOUND", authzMgrInstName)); } IAuthzManager authzMgrInst = proxy.getAuthzManager(); if (authzMgrInst == null) { throw new EAuthzMgrNotFound(CMS.getUserMessage("CMS_AUTHORIZATION_AUTHZMGR_NOT_FOUND", authzMgrInstName)); } return (authzMgrInst.authorize(authToken, exp)); } /** * Gets configuration parameters for the given * authorization manager plugin. * * @param implName Name of the authorization plugin. * @return Hashtable of required parameters. */ public String[] getConfigParams(String implName) throws EAuthzMgrPluginNotFound, EBaseException { // is this a registered implname? AuthzMgrPlugin plugin = mAuthzMgrPlugins.get(implName); if (plugin == null) { log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTHZ_PLUGIN_NOT_FOUND", implName)); throw new EAuthzMgrPluginNotFound(CMS.getUserMessage("CMS_AUTHORIZATION_AUTHZMGR_PLUGIN_NOT_FOUND", implName)); } // a temporary instance IAuthzManager authzMgrInst = null; String className = plugin.getClassPath(); try { authzMgrInst = (IAuthzManager) Class.forName(className).newInstance(); return (authzMgrInst.getConfigParams()); } catch (InstantiationException e) { log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTHZ_PLUGIN_NOT_CREATED", e.toString())); throw new EAuthzException(CMS.getUserMessage("CMS_AUTHORIZATION_LOAD_CLASS_FAIL", className)); } catch (ClassNotFoundException e) { log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTHZ_PLUGIN_NOT_CREATED", e.toString())); throw new EAuthzException(CMS.getUserMessage("CMS_AUTHORIZATION_LOAD_CLASS_FAIL", className)); } catch (IllegalAccessException e) { log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTHZ_PLUGIN_NOT_CREATED", e.toString())); throw new EAuthzException(CMS.getUserMessage("CMS_AUTHORIZATION_LOAD_CLASS_FAIL", className)); } } /** * Add an authorization manager instance. * * @param name name of the authorization manager instance * @param authzMgr the authorization manager instance to be added */ public void add(String name, IAuthzManager authzMgrInst) { mAuthzMgrInsts.put(name, new AuthzManagerProxy(true, authzMgrInst)); } /* * Removes a authorization manager instance. * @param name name of the authorization manager */ public void delete(String name) { mAuthzMgrInsts.remove(name); } /** * Gets the authorization manager instance of the specified name. * * @param name name of the authorization manager instance * @return the named authorization manager instance */ public IAuthzManager get(String name) { AuthzManagerProxy proxy = mAuthzMgrInsts.get(name); if (proxy == null) return null; return proxy.getAuthzManager(); } /** * Enumerate all authorization manager instances. */ public Enumeration getAuthzManagers() { Vector inst = new Vector(); Enumeration e = mAuthzMgrInsts.keys(); while (e.hasMoreElements()) { IAuthzManager p = get(e.nextElement()); if (p != null) { inst.addElement(p); } } return (inst.elements()); } /** * Enumerate all registered authorization manager plugins. */ public Enumeration getAuthzManagerPlugins() { return (mAuthzMgrPlugins.elements()); } /** * retrieve a single authz manager plugin by name */ public AuthzMgrPlugin getAuthzManagerPluginImpl(String name) { return mAuthzMgrPlugins.get(name); } /** * Retrieve a single authz manager instance */ /* getconfigparams above should be recoded to use this func */ public IAuthzManager getAuthzManagerPlugin(String name) { AuthzMgrPlugin plugin = mAuthzMgrPlugins.get(name); String classpath = plugin.getClassPath(); IAuthzManager authzMgrInst = null; try { authzMgrInst = (IAuthzManager) Class.forName(classpath).newInstance(); return (authzMgrInst); } catch (Exception e) { log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_AUTHZ_PLUGIN_NOT_CREATED", e.toString())); return null; } } /** * Retrieves id (name) of this subsystem. * * @return name of the authorization subsystem */ public String getId() { return (mId); } /** * Sets id string to this subsystem. *

* Use with caution. Should not do it when sharing with others * * @param id name to be applied to an authorization sybsystem */ public void setId(String id) throws EBaseException { mId = id; } /** * registers the administration servlet with the administration subsystem. */ public void startup() throws EBaseException { //remove the log since it's already logged from S_ADMIN //String infoMsg = "Authz subsystem administration Servlet registered"; //log(ILogger.LL_INFO, infoMsg); } /** * shuts down authorization managers one by one. *

*/ public void shutdown() { for (AuthzManagerProxy proxy : mAuthzMgrInsts.values()) { IAuthzManager mgr = proxy.getAuthzManager(); //String infoMsg = // "Shutting down authz manager instance " + mgr.getName(); //log(ILogger.LL_INFO, infoMsg); if (mgr != null) mgr.shutdown(); } mAuthzMgrPlugins.clear(); mAuthzMgrInsts.clear(); } public Hashtable getPlugins() { return mAuthzMgrPlugins; } public Hashtable getInstances() { return mAuthzMgrInsts; } /** * Returns the root configuration storage of this system. *

* * @return configuration store of this subsystem */ public IConfigStore getConfigStore() { return mConfig; } /** * gets the named authorization manager * * @param name of the authorization manager * @return the named authorization manager */ public IAuthzManager getAuthzManager(String name) { return get(name); } /** * logs an entry in the log file. */ public void log(int level, String msg) { if (mLogger == null) return; mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_AUTHORIZATION, level, msg); } @Override public void checkRealm(String realm, IAuthToken authToken, String owner, String resource, String operation) throws EBaseException { // if no realm entry, SUCCESS by default if (realm == null) return; // if record owner == requester, SUCCESS if ((owner != null) && owner.equals(authToken.getInString(IAuthToken.USER_ID))) return; String mgrName = getAuthzManagerByRealm(realm); if (mgrName == null) { throw new EAuthzUnknownRealm("Realm not found"); } AuthzToken authzToken = authorize(mgrName, authToken, resource, operation, realm); if (authzToken == null) { throw new EAuthzAccessDenied("Not authorized by ACL realm"); } } public String getAuthzManagerByRealm(String realm) throws EBaseException { for (AuthzManagerProxy proxy : mAuthzMgrInsts.values()) { IAuthzManager mgr = proxy.getAuthzManager(); if (mgr != null) { IConfigStore cfg = mgr.getConfigStore(); String mgrRealmString = cfg.getString(PROP_REALM, null); if (mgrRealmString == null) continue; List mgrRealms = Arrays.asList(mgrRealmString.split(",")); for (String mgrRealm : mgrRealms) { if (StringUtils.equals(mgrRealm, realm)) return mgr.getName(); } } } return null; } }