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;
011:
012: import org.mmbase.util.ResourceLoader;
013: import org.mmbase.util.ResourceWatcher;
014:
015: import org.mmbase.util.logging.Logger;
016: import org.mmbase.util.logging.Logging;
017: import org.mmbase.util.xml.DocumentReader;
018:
019: /**
020: * This class is the main class of the security system. It loads the authentication
021: * and authorization classes if needed, and they can be requested from this manager.
022: * @javadoc
023: * @author Eduard Witteveen
024: * @version $Id: MMBaseCopConfig.java,v 1.30 2007/07/26 22:04:23 michiel Exp $
025: */
026: public class MMBaseCopConfig {
027: private static final Logger log = Logging
028: .getLoggerInstance(MMBaseCopConfig.class);
029:
030: public static final ResourceLoader securityLoader = ResourceLoader
031: .getConfigurationRoot().getChildResourceLoader("security");
032:
033: /** looks if the files have been changed */
034: protected ResourceWatcher watcher;
035:
036: /** our current authentication class */
037: private Authentication authentication;
038:
039: /** our current authorization class */
040: private Authorization authorization;
041:
042: private ActionRepository actions;
043:
044: /** if the securitymanager is configured to functionate */
045: private boolean active = false;
046:
047: /** the shared secret used by this system */
048: private String sharedSecret = null;
049:
050: /** the shared secret used by this system */
051: private MMBaseCop cop;
052:
053: /** the class that watches if we have to reload...*/
054: private class SecurityConfigWatcher extends ResourceWatcher {
055: private MMBaseCop cop;
056:
057: public SecurityConfigWatcher(MMBaseCop cop) {
058: super (securityLoader);
059: if (cop == null)
060: throw new RuntimeException("MMBase cop was null");
061: // log.debug("Starting the file watcher");
062: this .cop = cop;
063: }
064:
065: public void onChange(String s) {
066: try {
067: cop.reload();
068: } catch (Exception e) {
069: log.error(e);
070: log.error(Logging.stackTrace(e));
071: }
072: }
073: }
074:
075: /** Public ID of the Builder DTD version 1.0 */
076: public static final String PUBLIC_ID_SECURITY_1_0 = "-//MMBase//DTD security config 1.0//EN";
077: private static final String PUBLIC_ID_SECURITY_1_0_FAULT = "//MMBase - security//";
078:
079: /** DTD resource filename of the Builder DTD version 1.0 */
080: public static final String DTD_SECURITY_1_0 = "security_1_0.dtd";
081:
082: static {
083: org.mmbase.util.XMLEntityResolver.registerPublicID(
084: PUBLIC_ID_SECURITY_1_0, DTD_SECURITY_1_0,
085: MMBaseCopConfig.class);
086: org.mmbase.util.XMLEntityResolver.registerPublicID(
087: PUBLIC_ID_SECURITY_1_0_FAULT, DTD_SECURITY_1_0,
088: MMBaseCopConfig.class);
089: }
090:
091: /**
092: * The constructor, will load the classes for authorization and authentication
093: * with their config files, as specied in the xml from configUrl
094: * @exception java.io.IOException When reading the file failed
095: * @exception .. When XML not validates.
096: * @exception org.mmbase.security.SecurityException When the class could not be loaded
097: *
098: * @param mmbaseCop The MMBaseCop for which this is a configurator
099: */
100: MMBaseCopConfig(MMBaseCop mmbaseCop) throws java.io.IOException,
101: NoSuchMethodException, SecurityException {
102:
103: java.net.URL config = securityLoader
104: .getResource("security.xml");
105: log.info("using: '" + config
106: + "' as configuration file for security");
107:
108: watcher = new SecurityConfigWatcher(mmbaseCop);
109: watcher.add("security.xml");
110: watcher.start();
111:
112: cop = mmbaseCop;
113:
114: }
115:
116: /**
117: * @since MMBase-1.8
118: */
119: void load() throws java.io.IOException {
120: DocumentReader reader = new DocumentReader(securityLoader
121: .getInputSource("security.xml"), this .getClass());
122:
123: // are we active ?
124: String sActive = reader.getElementAttributeValue(reader
125: .getElementByPath("security"), "active");
126: if (sActive.equalsIgnoreCase("true")) {
127: log.debug("SecurityManager will be active");
128: active = true;
129: } else if (sActive.equalsIgnoreCase("false")) {
130: log.debug("SecurityManager will NOT be active");
131: active = false;
132: } else {
133: throw new SecurityException(
134: "security attribute 'active' must have the value 'true' or 'false'");
135: }
136:
137: // load the sharedSecret
138: sharedSecret = reader.getElementValue(reader
139: .getElementByPath("security.sharedsecret"));
140:
141: if (active) {
142:
143: // first instantiate authentication and authorization, during load they can check each others class then.
144:
145: org.w3c.dom.Element entry = reader
146: .getElementByPath("security.authentication");
147: String authenticationClass = reader
148: .getElementAttributeValue(entry, "class");
149: String authenticationUrl = reader.getElementAttributeValue(
150: entry, "url");
151: authentication = getAuthentication(authenticationClass);
152:
153: // load the key
154: String key = reader.getElementValue(reader
155: .getElementByPath("security.key"));
156: if (key != null && !key.equals("")) {
157: try {
158: long k = Long.parseLong(key);
159: authentication.key = k;
160: } catch (NumberFormatException nfe) {
161: log.error("Could not format '" + key
162: + "', defaulting to " + authentication.key);
163: }
164: }
165:
166: entry = reader.getElementByPath("security.authorization");
167: String authorizationClass = reader
168: .getElementAttributeValue(entry, "class");
169: String authorizationUrl = reader.getElementAttributeValue(
170: entry, "url");
171: authorization = getAuthorization(authorizationClass);
172:
173: if (log.isDebugEnabled()) {
174: log.debug("Loading class:"
175: + authentication.getClass().getName()
176: + " with config:" + authenticationUrl
177: + " for Authentication");
178: }
179: authentication.load(cop, watcher, authenticationUrl);
180:
181: if (log.isDebugEnabled()) {
182: log.debug("Using class:"
183: + authorization.getClass().getName()
184: + " with config:" + authorizationUrl
185: + " for Authorization");
186: }
187: authorization.load(cop, watcher, authorizationUrl);
188:
189: entry = reader.getElementByPath("security.actions");
190: if (entry != null) {
191: String actionsClass = reader.getElementAttributeValue(
192: entry, "class");
193: String actionsUrl = reader.getElementAttributeValue(
194: entry, "url");
195: actions = getActions(actionsClass);
196: actions.load(cop, watcher, actionsUrl);
197: } else {
198: actions = new MemoryActionRepository();
199: actions.load(cop, watcher, null);
200: }
201:
202: } else {
203: // we dont use security...
204: authentication = new NoAuthentication();
205: authentication.load(cop, watcher, null);
206: authorization = new NoAuthorization();
207: authorization.load(cop, watcher, null);
208: actions = new MemoryActionRepository();
209: actions.load(cop, watcher, null);
210: log.debug("Retrieved dummy security classes");
211: }
212: }
213:
214: /**
215: * Returns the authentication class, which should be used.
216: * @return The authentication class which should be used.
217: */
218: public Authentication getAuthentication() {
219: return authentication;
220: }
221:
222: /**
223: * Returns the authorization class, which should be used.
224: * @return The authorization class which should be used.
225: */
226: public Authorization getAuthorization() {
227: return authorization;
228: }
229:
230: public ActionRepository getActionRepository() {
231: return actions;
232: }
233:
234: /**
235: * Returns the authorization class, which should be used(for optimizations)
236: * @return <code>true</code>When the SecurityManager should
237: * be used.
238: * <code>false</code>When not.
239: */
240: public boolean getActive() {
241: return active;
242: }
243:
244: /**
245: * checks if the received shared secret is equals to your own shared secret
246: * @param received shared secret
247: * @return true if received shared secret equals your own shared secret
248: * @return false if received shared secret not equals your own shared secret
249: */
250: public boolean checkSharedSecret(String received) {
251: if (sharedSecret != null) {
252: if (sharedSecret.equals(received)) {
253: return true;
254: } else {
255: log.error("the shared " + sharedSecret + "!="
256: + received + " secrets don't match.");
257: }
258: }
259: return false;
260: }
261:
262: /**
263: * get the shared Secret
264: * @return the shared Secret
265: */
266: public String getSharedSecret() {
267: return sharedSecret;
268: }
269:
270: private Authentication getAuthentication(String className)
271: throws SecurityException {
272: Authentication result;
273: try {
274: Class classType = Class.forName(className);
275: Object o = classType.newInstance();
276: result = (Authentication) o;
277: log.debug("Setting manager of " + result + " to " + cop);
278: result.manager = cop;
279: } catch (ClassNotFoundException cnfe) {
280: throw new SecurityException(cnfe);
281: } catch (IllegalAccessException iae) {
282: throw new SecurityException(iae);
283: } catch (InstantiationException ie) {
284: throw new SecurityException(ie);
285: }
286: return result;
287: }
288:
289: private Authorization getAuthorization(String className)
290: throws SecurityException {
291:
292: Authorization result;
293: try {
294: Class classType = Class.forName(className);
295: Object o = classType.newInstance();
296: result = (Authorization) o;
297: log.debug("Setting manager of " + result + " to " + cop);
298: result.manager = cop;
299: } catch (java.lang.ClassNotFoundException cnfe) {
300: log.debug("", cnfe);
301: throw new SecurityException(cnfe.toString());
302: } catch (java.lang.IllegalAccessException iae) {
303: log.debug("", iae);
304: throw new SecurityException(iae.toString());
305: } catch (java.lang.InstantiationException ie) {
306: log.debug("", ie);
307: throw new SecurityException(ie.toString());
308: }
309: return result;
310: }
311:
312: private ActionRepository getActions(String className)
313: throws SecurityException {
314:
315: ActionRepository result;
316: try {
317: Class classType = Class.forName(className);
318: Object o = classType.newInstance();
319: result = (ActionRepository) o;
320: log.debug("Setting manager of " + result + " to " + cop);
321: result.manager = cop;
322: } catch (java.lang.ClassNotFoundException cnfe) {
323: log.debug("", cnfe);
324: throw new SecurityException(cnfe.toString());
325: } catch (java.lang.IllegalAccessException iae) {
326: log.debug("", iae);
327: throw new SecurityException(iae.toString());
328: } catch (java.lang.InstantiationException ie) {
329: log.debug("", ie);
330: throw new SecurityException(ie.toString());
331: }
332: return result;
333: }
334: }
|