001: /*
002:
003: This software is OSI Certified Open Source Software.
004: OSI Certified is a certification mark of the Open Source Initiative.
005:
006: The license (Mozilla version 1.0) can be read at the MMBase site.
007: See http://www.MMBase.org/license
008:
009: */
010: package org.mmbase.security.implementation.context;
011:
012: import org.mmbase.security.*;
013: import org.mmbase.security.SecurityException;
014:
015: import java.util.*;
016:
017: import org.w3c.dom.*;
018: import org.xml.sax.InputSource;
019:
020: import javax.xml.xpath.*;
021:
022: import org.mmbase.util.logging.Logger;
023: import org.mmbase.util.logging.Logging;
024:
025: /**
026: * Authentication based on a XML-configuration file. The XML file contains besides users, groups and
027: * contexts (used for ContextAuthorization).
028: *
029: * @author Eduard Witteveen
030: * @version $Id: ContextAuthentication.java,v 1.27 2008/01/10 14:12:24 michiel Exp $
031: * @see ContextAuthorization
032: */
033: public class ContextAuthentication extends Authentication {
034: private static final Logger log = Logging
035: .getLoggerInstance(ContextAuthentication.class);
036: private Map<String, ContextLoginModule> loginModules = new LinkedHashMap<String, ContextLoginModule>();
037: private Document document;
038:
039: /** Public ID of the Builder DTD version 1.0 */
040: public static final String PUBLIC_ID_SECURITY_CONTEXT_CONFIG_1_0 = "-//MMBase//DTD security context config 1.0//EN";
041: public static final String PUBLIC_ID_SECURITY_CONTEXT_CONFIG_1_1 = "-//MMBase//DTD security context config 1.1//EN";
042: public static final String PUBLIC_ID_SECURITY_CONTEXT_CONFIG_1_2 = "-//MMBase//DTD security context config 1.2//EN";
043:
044: /** DTD resource filename of the Builder DTD version 1.0 */
045: public static final String DTD_SECURITY_CONTEXT_CONFIG_1_0 = "securitycontextconfig_1_0.dtd";
046: public static final String DTD_SECURITY_CONTEXT_CONFIG_1_1 = "securitycontextconfig_1_1.dtd";
047: public static final String DTD_SECURITY_CONTEXT_CONFIG_1_2 = "securitycontextconfig_1_2.dtd";
048:
049: static {
050: org.mmbase.util.XMLEntityResolver.registerPublicID(
051: PUBLIC_ID_SECURITY_CONTEXT_CONFIG_1_0,
052: DTD_SECURITY_CONTEXT_CONFIG_1_0, MMBaseCopConfig.class);
053: org.mmbase.util.XMLEntityResolver.registerPublicID(
054: PUBLIC_ID_SECURITY_CONTEXT_CONFIG_1_1,
055: DTD_SECURITY_CONTEXT_CONFIG_1_1, MMBaseCopConfig.class);
056: org.mmbase.util.XMLEntityResolver.registerPublicID(
057: PUBLIC_ID_SECURITY_CONTEXT_CONFIG_1_2,
058: DTD_SECURITY_CONTEXT_CONFIG_1_2, MMBaseCopConfig.class);
059: }
060:
061: public ContextAuthentication() {
062: }
063:
064: protected void load() {
065: if (log.isDebugEnabled()) {
066: log.debug("using: '" + configResource
067: + "' as config file for context-authentication");
068: }
069:
070: try {
071: InputSource in = MMBaseCopConfig.securityLoader
072: .getInputSource(configResource);
073: document = org.mmbase.util.XMLBasicReader
074: .getDocumentBuilder(this .getClass()).parse(in);
075: } catch (org.xml.sax.SAXException se) {
076: String message = "error loading configfile :'"
077: + configResource + "'(" + se + "->"
078: + se.getMessage() + "(" + se.getMessage() + "))";
079: throw new SecurityException(message, se);
080: } catch (java.io.IOException ioe) {
081: throw new SecurityException("error loading configfile :'"
082: + configResource + "'(" + ioe + ")", ioe);
083: }
084: if (log.isDebugEnabled()) {
085: log.debug("loaded: '" + configResource
086: + "' as config file for authentication");
087: log.debug("going to load the modules...");
088: }
089:
090: // do the xpath query...
091: String xpath = "/contextconfig/loginmodules/module";
092: if (log.isDebugEnabled())
093: log.debug("going to execute the query:" + xpath);
094:
095: XPathFactory xf = XPathFactory.newInstance();
096: NodeList found;
097: try {
098: found = (NodeList) xf.newXPath().evaluate(xpath, document,
099: XPathConstants.NODESET);
100: } catch (XPathExpressionException xe) {
101: throw new SecurityException("error executing query: '"
102: + xpath + "' ", xe);
103: }
104: // we now have a list of login modules.. process them all, and load them...
105: for (int i = 0; i < found.getLength(); i++) {
106: Node contains = found.item(i);
107: NamedNodeMap nnm = contains.getAttributes();
108: String moduleName = nnm.getNamedItem("name").getNodeValue();
109: String className = nnm.getNamedItem("class").getNodeValue();
110:
111: log.debug("going to try to load module with the name '"
112: + moduleName + "' with class: " + className);
113: ContextLoginModule module;
114: try {
115: Class moduleClass = Class.forName(className);
116: module = (ContextLoginModule) moduleClass.newInstance();
117: } catch (Exception e) {
118: String msg = "could not load module with the name: '"
119: + moduleName + "' with class: " + className;
120: throw new SecurityException(msg, e);
121: }
122: module.load(document, getKey(), moduleName, manager);
123: log.info("loaded module with the name: '" + moduleName
124: + "' with class: " + className);
125: loginModules.put(moduleName, module);
126: }
127:
128: if (!loginModules.containsKey("class")) {
129: ContextLoginModule classModule = new ClassLogin();
130: log
131: .info("The class login module was not configured. It is needed sometimes. Now loading module with the name 'class' with class: "
132: + classModule.getClass());
133: classModule.load(document, getKey(), "class", manager);
134: loginModules.put("class", classModule);
135: }
136:
137: log.debug("done loading the modules...");
138: }
139:
140: public UserContext login(String moduleName,
141: Map<String, Object> loginInfo, Object[] parameters)
142: throws SecurityException {
143: // look if we can find our login module...
144: if (!loginModules.containsKey(moduleName)) {
145: throw new UnknownAuthenticationMethodException(
146: "could not load module with name: '" + moduleName
147: + "'");
148: }
149: ContextLoginModule module = loginModules.get(moduleName);
150: // and we do the login...
151: UserContext user = module.login(loginInfo, parameters);
152: if (log.isServiceEnabled()) {
153: if (user == null) {
154: log.debug("login on module with name '" + moduleName
155: + "' failed");
156: } else {
157: if (user.getRank().getInt() > Rank.ANONYMOUS_INT) {
158: log.debug("login on module with name '"
159: + moduleName
160: + "' was succesfull for user with id: '"
161: + user.getIdentifier() + "'");
162: }
163: }
164: }
165: return user;
166: }
167:
168: /**
169: * this method does nothing..
170: */
171: public boolean isValid(UserContext userContext)
172: throws SecurityException {
173: if (getKey() == ((ContextUserContext) userContext).getKey())
174: return true;
175: if (log.isDebugEnabled()) {
176: log.debug("not valid because " + getKey() + " != "
177: + ((ContextUserContext) userContext).getKey());
178: }
179: return false;
180: }
181:
182: public String[] getTypes() {
183: return loginModules.keySet().toArray(new String[] {});
184: }
185: }
|