View Javadoc

1   /*
2   jGuard is a security framework based on top of jaas (java authentication and authorization security).
3   it is written for web applications, to resolve simply, access control problems.
4   version $Name$
5   http://sourceforge.net/projects/jguard/
6   
7   Copyright (C) 2004  Charles GAY
8   
9   This library is free software; you can redistribute it and/or
10  modify it under the terms of the GNU Lesser General Public
11  License as published by the Free Software Foundation; either
12  version 2.1 of the License, or (at your option) any later version.
13  
14  This library is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  Lesser General Public License for more details.
18  
19  You should have received a copy of the GNU Lesser General Public
20  License along with this library; if not, write to the Free Software
21  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  
23  
24  jGuard project home page:
25  http://sourceforge.net/projects/jguard/
26  
27  */
28  package net.sf.jguard.core.authentication.configuration;
29  
30  import java.util.ArrayList;
31  import java.util.HashMap;
32  import java.util.Iterator;
33  import java.util.List;
34  import java.util.Map;
35  
36  import javax.security.auth.login.AppConfigurationEntry;
37  import javax.security.auth.login.Configuration;
38  
39  import net.sf.jguard.core.CoreConstants;
40  import net.sf.jguard.core.PolicyEnforcementPointOptions;
41  import net.sf.jguard.core.util.XMLUtils;
42  import org.dom4j.Document;
43  import org.dom4j.Element;
44  import org.slf4j.Logger;
45  import org.slf4j.LoggerFactory;
46  
47  
48  /**
49   * utility class to deal with the {@link javax.security.auth.login.Configuration} class.
50   * @author <a href="mailto:diabolo512@users.sourceforge.net">Charles Gay</a>
51   */
52  public class ConfigurationHelper {
53  	 
54  	 private static String scope;
55  	 
56  	 
57  	 private static boolean configurationInstalled = false;
58       private static Logger logger = LoggerFactory.getLogger(ConfigurationHelper.class.getName());
59       private final static String COM_SUN_SECURITY_AUTH_LOGIN_CONFIG_FILE = "com.sun.security.auth.login.ConfigFile";
60  
61      /**
62       * add the required AppConfigurationEntry when no none is configured for the webapp.
63       * @param applicationName
64       * @param authenticationSettings
65       * @param debug
66       */
67      public static void addConfigurationEntryForApplication(JGuardConfiguration configuration,String applicationName,Map authenticationSettings,boolean debug){
68          List webappEntries = buildAppConfigurationEntries(applicationName,authenticationSettings,debug);
69          configuration.addConfigEntriesForApplication(applicationName,webappEntries);
70      }
71  
72  
73      /**
74       * install JGuardConfiguration.
75       * @param includeOldConfiguration include informations contained in the replaced configuration instance
76       * @param includeConfigFromJavaParam
77       * @throws RuntimeException
78       */
79  	public static void installConfiguration(JGuardConfiguration jGuardConf,boolean includeConfigFromJavaParam) throws RuntimeException {
80  		if(!configurationInstalled){
81  			includeConfigFromJavaParam = false;
82  		}
83  			
84  		
85          if(includeConfigFromJavaParam){
86          	//TODO build a Configuration object to include from the configuration file
87          	try {
88  				Class defaultConfigClass = Class.forName(ConfigurationHelper.COM_SUN_SECURITY_AUTH_LOGIN_CONFIG_FILE);
89  				Configuration defaultConfiguration = (Configuration) defaultConfigClass.newInstance();
90  	        	jGuardConf.includeConfiguration(defaultConfiguration);
91  			} catch (ClassNotFoundException e) {
92  				logger.error(ConfigurationHelper.COM_SUN_SECURITY_AUTH_LOGIN_CONFIG_FILE+" class cannot be found "+e.getMessage(),e);
93  			} catch (InstantiationException e) {
94  				logger.error(ConfigurationHelper.COM_SUN_SECURITY_AUTH_LOGIN_CONFIG_FILE+" class cannot be instantiated "+e.getMessage(),e);
95  			} catch (IllegalAccessException e) {
96  				logger.error(ConfigurationHelper.COM_SUN_SECURITY_AUTH_LOGIN_CONFIG_FILE+" class cannot be accessed "+e.getMessage(),e);
97  			}
98  
99          }
100 
101 	}
102 
103 
104     /**
105      * we override the current JVM-scope {@link Configuration} instance, and include it into the
106      * set Jguard's {@link Configuration} instance depending on the includeOldConfiguration flag.
107      * @param includeOldConfiguration
108      * @return
109      * @throws RuntimeException
110      */
111 	private static JGuardConfiguration installWithOldConfig(boolean includeOldConfiguration) throws RuntimeException {
112 		JGuardConfiguration jGuardConf;
113 		Configuration oldConfiguration = null;
114         boolean skipOldConfig = false;
115         try{
116           oldConfiguration = Configuration.getConfiguration();
117           logger.debug(" oldConfiguration="+oldConfiguration.getClass().getName());
118           logger.debug(" oldConfiguration="+oldConfiguration);
119 
120         }catch(SecurityException sex){
121           skipOldConfig = true;
122           logger.debug(" addConfigurationEntryForWebapp() -  exception raised when we try to retrieve the default Configuration instance ");
123           logger.debug(" addConfigurationEntryForWebapp() - "+ sex.getMessage());
124           logger.debug(" jGuard will not include the old Configuration ");
125         }catch(NullPointerException npe){
126             skipOldConfig = true;
127             logger.debug("addConfigurationEntryForWebapp() - a NullPointerException has been raised when the default configuration :no configuration is defined ");
128             logger.debug("addConfigurationEntryForWebapp() - "+ npe.getMessage());
129         }
130 
131         //we override the current Configuration to JGuardConfiguration
132         //only if the current Configuration is not a JGuardConfiguration instance
133         if(oldConfiguration== null ||
134         		(!oldConfiguration.getClass().getName().equals(JGuardConfiguration.class.getName()))){
135 	          jGuardConf = new JGuardConfiguration();
136 	          Configuration.setConfiguration(jGuardConf);
137 	          logger.info(" JGuardConfiguration is set ");
138 	    //it is a JGuardConfiguration but with a class not loaded with this classloader
139         }else if(!oldConfiguration.getClass().equals(JGuardConfiguration.class)
140         		 && oldConfiguration.getClass().getName().equals(JGuardConfiguration.class.getName())){
141         	logger.error(" jGuard_jvm must be placed under the shared libraries directory or on the jvm side, not in the WEB-INF/lib directory of the webapp ");
142         	throw new RuntimeException(" jGuard_jvm must be placed under the shared libraries directory or on the jvm side, not in the WEB-INF/lib directory of the webapp ");
143         }else{
144           jGuardConf = (JGuardConfiguration) Configuration.getConfiguration();
145           logger.debug("configuration="+oldConfiguration.getClass().getName());
146           logger.debug(" JGuardConfiguration is already set ");
147       	  // we don't include the old Configuration
148       	  //because the old Configuration is kept: it's already a jGuardConfiguration
149       	  skipOldConfig = true;
150         }
151 
152         //there is no configuration entries for the webapp
153         if(!skipOldConfig && includeOldConfiguration == true){
154         	logger.info(" jGuard include the old Configuration ");
155            jGuardConf.includeConfiguration(oldConfiguration);
156         }
157 
158         //we should only execute one time this method per webapp
159         configurationInstalled = true;
160         return jGuardConf;
161 	}
162 
163 
164     /**
165      * build the list of AppConfigurationEntry.
166      * @param applicationName
167      * @param authSettings
168      * @param debug
169      * @return list built
170      */
171     public static List buildAppConfigurationEntries(String applicationName,Map authSettings,boolean debug) {
172     	List appConfigurationEntryList = new ArrayList();
173 
174         List loginModules = (List)authSettings.get(CoreConstants.LOGIN_MODULES);
175         if(loginModules==null){
176         	throw new IllegalArgumentException(" no loginModules have been configured for the application="+applicationName);
177         }
178         Iterator itLoginModules = loginModules.iterator();
179         while(itLoginModules.hasNext()){
180                Map loginModuleMap = (Map)itLoginModules.next();
181                String loginModuleClassName = (String)loginModuleMap.get(CoreConstants.NAME);
182                String loginModuleFlag = (String)loginModuleMap.get(CoreConstants.FLAG);
183                AppConfigurationEntry.LoginModuleControlFlag controlFlag;
184                if(loginModuleFlag.equalsIgnoreCase(CoreConstants.REQUIRED)){
185                    controlFlag = AppConfigurationEntry.LoginModuleControlFlag.REQUIRED;
186                }else if(loginModuleFlag.equalsIgnoreCase(CoreConstants.OPTIONAL)){
187                    controlFlag = AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL;
188                }else if(loginModuleFlag.equalsIgnoreCase(CoreConstants.REQUISITE)){
189                    controlFlag = AppConfigurationEntry.LoginModuleControlFlag.REQUISITE;
190                }else if(loginModuleFlag.equalsIgnoreCase(CoreConstants.SUFFICIENT)){
191                    controlFlag = AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT;
192                }else{
193             	   throw new IllegalArgumentException(" invalid loginModuleControlFlag ="+loginModuleFlag+" is neither OPTIONAL,REQUIRED,REQUISITE nor SUFFICIENT ");
194                }
195                Map loginModuleOptions = (Map)loginModuleMap.get(CoreConstants.LOGIN_MODULE_OPTIONS);
196                loginModuleOptions.put(PolicyEnforcementPointOptions.APPLICATION_NAME.getLabel(),applicationName);
197                AppConfigurationEntry entry = new AppConfigurationEntry(loginModuleClassName,controlFlag,loginModuleOptions);
198                appConfigurationEntryList.add(entry);
199         }
200         if(appConfigurationEntryList.size()==0){
201         	throw new IllegalArgumentException(" no loginModules have been configured for the application="+applicationName);
202         }
203         return appConfigurationEntryList;
204     }
205 
206 
207 	public static String getScope() {
208 		return scope;
209 	}
210 
211 
212         /**
213 	 * load a configuration file from a location with an appHomePath prefix.
214 	 * @param configurationLocation
215 	 * @param appHomePath
216 	 * @return
217 	 */
218 	public static Map loadConfiguration(String configurationLocation, String appHomePath){
219 
220 		Document doc = XMLUtils.read(configurationLocation);
221 
222 		//authentication part
223 		Element authentication = doc.getRootElement().element(CoreConstants.AUTHENTICATION);
224 		Map authenticationMap = new HashMap();
225 		authenticationMap.put(CoreConstants.SCOPE, authentication.element(CoreConstants.SCOPE).getTextTrim());
226 		authenticationMap.put(CoreConstants.DEBUG, authentication.element(CoreConstants.DEBUG).getTextTrim());
227 		authenticationMap.put(CoreConstants.INCLUDE_OLD_CONFIG, authentication.element(CoreConstants.INCLUDE_OLD_CONFIG).getTextTrim());
228 		authenticationMap.put(CoreConstants.INCLUDE_CONFIG_FROM_JAVA_PARAM, authentication.element(CoreConstants.INCLUDE_CONFIG_FROM_JAVA_PARAM).getTextTrim());
229 		authenticationMap.put(CoreConstants.INCLUDE_POLICY_FROM_JAVA_PARAM, authentication.element(CoreConstants.INCLUDE_POLICY_FROM_JAVA_PARAM).getTextTrim());
230 		if(authentication.element(CoreConstants.DIGEST_ALGORITHM)!=null){
231 			authenticationMap.put(CoreConstants.DIGEST_ALGORITHM,authentication.element(CoreConstants.DIGEST_ALGORITHM).getTextTrim());
232 		}
233 		if(authentication.element(CoreConstants.SALT)!=null){
234 			authenticationMap.put(CoreConstants.SALT,authentication.element(CoreConstants.SALT).getTextTrim());
235 		}
236 		//loginModules configuration
237 		List loginModuleElementsList = authentication.element(CoreConstants.LOGIN_MODULES).elements(CoreConstants.LOGIN_MODULE);
238 		List loginModules = new ArrayList();
239 		Iterator itLoginModuleElementsList = loginModuleElementsList.iterator();
240 		while(itLoginModuleElementsList.hasNext()){
241 			Element loginModule = (Element)itLoginModuleElementsList.next();
242 
243 			Map loginModuleMap = new HashMap();
244 			loginModuleMap.put(CoreConstants.NAME,loginModule.element(CoreConstants.NAME).getTextTrim());
245 			loginModuleMap.put(CoreConstants.FLAG,loginModule.element(CoreConstants.FLAG).getTextTrim());
246 			Element loginModuleOpts = loginModule.element(CoreConstants.LOGIN_MODULE_OPTIONS);
247 			if(loginModuleOpts!=null){
248 				List loginModuleOptsList = loginModuleOpts.elements(CoreConstants.OPTION);
249 				Iterator itLoginModuleOpts = loginModuleOptsList.iterator();
250 				Map loginModulesOptions = new HashMap();
251 				while (itLoginModuleOpts.hasNext()){
252 					Element option = (Element)itLoginModuleOpts.next();
253 					String name = option.element(CoreConstants.NAME).getTextTrim();
254 					String value = option.element(CoreConstants.VALUE_MARKUP).getTextTrim();
255 					if(CoreConstants.AUTHENTICATION_XML_FILE_LOCATION.equals(name)||CoreConstants.AUTHENTICATION_DATABASE_FILE_LOCATION.equals(name)){
256 						value=appHomePath+value;
257 					}
258 					loginModulesOptions.put(name,value);
259 				}
260 				loginModuleMap.put(CoreConstants.LOGIN_MODULE_OPTIONS, loginModulesOptions);
261 			}else{
262 				//there are no options for the loginmodule
263 				loginModuleMap.put(CoreConstants.LOGIN_MODULE_OPTIONS,new HashMap());
264 			}
265 			loginModules.add(loginModuleMap);
266 		}
267 
268 		authenticationMap.put(CoreConstants.LOGIN_MODULES, loginModules);
269 
270 		//authenticationManager configuration
271 		authenticationMap.put(CoreConstants.AUTHENTICATION_MANAGER, authentication.element(CoreConstants.AUTHENTICATION_MANAGER).getTextTrim());
272 
273 		Map authenticationManagerOptions = new HashMap();
274 		Element authentManagerOptsElement = authentication.element(CoreConstants.AUTHENTICATION_MANAGER_OPTIONS);
275 		List authentManagerOptsList = authentManagerOptsElement.elements(CoreConstants.OPTION);
276 		Iterator authentManagerOpts = authentManagerOptsList.iterator();
277 		while (authentManagerOpts.hasNext()){
278 			Element option = (Element)authentManagerOpts.next();
279 			String name = option.element(CoreConstants.NAME).getTextTrim();
280 			String value = option.element(CoreConstants.VALUE_MARKUP).getTextTrim();
281 			if(CoreConstants.AUTHENTICATION_XML_FILE_LOCATION.equals(name)||CoreConstants.AUTHENTICATION_DATABASE_FILE_LOCATION.equals(name)){
282      	    	value=appHomePath+value;
283      	    }
284 			authenticationManagerOptions.put(name,value);
285 		}
286 
287 		authenticationMap.put(CoreConstants.AUTHENTICATION_MANAGER_OPTIONS, authenticationManagerOptions);
288 
289 		return authenticationMap;
290 	}
291 }