View Javadoc

1   /*
2    * $Id: JaasSimpleAuthenticationProvider.java 7976 2007-08-21 14:26:13Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.extras.jaas;
12  
13  import org.mule.config.i18n.CoreMessages;
14  import org.mule.impl.security.MuleAuthentication;
15  import org.mule.umo.lifecycle.InitialisationException;
16  import org.mule.umo.security.UMOAuthentication;
17  import org.mule.umo.security.UMOSecurityContext;
18  import org.mule.umo.security.UMOSecurityContextFactory;
19  import org.mule.umo.security.UMOSecurityProvider;
20  import org.mule.umo.security.UnauthorisedException;
21  import org.mule.umo.security.UnknownAuthenticationTypeException;
22  
23  import java.io.IOException;
24  import java.security.Security;
25  import java.util.HashMap;
26  import java.util.Map;
27  
28  import javax.security.auth.login.AppConfigurationEntry;
29  import javax.security.auth.login.Configuration;
30  import javax.security.auth.login.LoginContext;
31  import javax.security.auth.login.LoginException;
32  
33  /**
34   * @author Marie.Rizzo This is the Provider for Mule's Jaas Security
35   */
36  public class JaasSimpleAuthenticationProvider implements UMOSecurityProvider
37  {
38  
39      private String loginConfig;
40      private String loginContextName;
41      private String credentials;
42      private String loginModule;
43      private String defaultModule = "org.mule.extras.jaas.loginmodule.DefaultLoginModule";
44      private String name;
45      private UMOSecurityContextFactory factory;
46  
47      // ~ Getters and Setters
48      // ================================================================
49  
50      /**
51       * Sets the login Configuration
52       * 
53       * @param loginConfig
54       */
55      public final void setLoginConfig(String loginConfig)
56      {
57          this.loginConfig = loginConfig;
58      }
59  
60      /**
61       * Gets the Login Configuration
62       * 
63       * @return loginConfig
64       */
65      public final String getLoginConfig()
66      {
67          return loginConfig;
68      }
69  
70      /**
71       * Sets the Login Context name
72       * 
73       * @param loginContextName
74       */
75      public final void setLoginContextName(String loginContextName)
76      {
77          this.loginContextName = loginContextName;
78      }
79  
80      /**
81       * Gets the Login Context Name
82       * 
83       * @return loginContextName
84       */
85      public final String getLoginContextName()
86      {
87          return loginContextName;
88      }
89  
90      /**
91       * Gets the user's credentials, i.e. the username and password
92       * 
93       * @return credentials
94       */
95      public final String getCredentials()
96      {
97          return credentials;
98      }
99  
100     /**
101      * Sets the user's credentials.
102      * 
103      * @param credentials
104      */
105     public final void setCredentials(String credentials)
106     {
107         this.credentials = credentials;
108     }
109 
110     /**
111      * Gets the login module name
112      * 
113      * @return loginModule
114      */
115     public final String getLoginModule()
116     {
117         return loginModule;
118     }
119 
120     /**
121      * sets the login module name
122      * 
123      * @param loginModule
124      */
125     public final void setLoginModule(String loginModule)
126     {
127         this.loginModule = loginModule;
128     }
129 
130     /**
131      * @return name
132      */
133     public final String getName()
134     {
135         return name;
136     }
137 
138     /**
139      * @param name
140      */
141     public final void setName(String name)
142     {
143         this.name = name;
144     }
145 
146     // ~ Methods ================================================================
147 
148     /**
149      * @throws IOException The configureJaas method gets the resource path of the
150      *             jaas configuration file and constructs the URL for the login
151      *             configuration.
152      */
153     private void configureJaas() throws IOException
154     {
155 
156         String loginConfigUrl = "file://"
157                                 + org.mule.util.FileUtils.getResourcePath(loginConfig,
158                                     JaasSimpleAuthenticationProvider.class);
159 
160         boolean alreadySet = false;
161 
162         int n = 1;
163         String prefix = "login.config.url.";
164         String existing = null;
165 
166         while ((existing = Security.getProperty(prefix + n)) != null)
167         {
168             alreadySet = existing.equals(loginConfigUrl);
169 
170             if (alreadySet)
171             {
172                 break;
173             }
174             n++;
175         }
176 
177         if (!alreadySet)
178         {
179             String key = prefix + n;
180             Security.setProperty(key, loginConfigUrl);
181         }
182     }
183 
184     /**
185      * The authenticate method first creates the jaas Login Context using the
186      * callback handler and the name of the class or directory to prtect. If the
187      * Login Context is successfully created, it will then attempt to login.
188      * 
189      * @param UMOAuthentication
190      * @return UMOAuthentication
191      * @throws org.mule.umo.security.SecurityException
192      */
193     public final UMOAuthentication authenticate(UMOAuthentication authentication)
194         throws org.mule.umo.security.SecurityException
195     {
196 
197         LoginContext loginContext;
198         MuleAuthentication auth = (MuleAuthentication)authentication;
199 
200         // Create the Mule Callback Handler
201         MuleCallbackHandler cbh = new MuleCallbackHandler(auth);
202 
203         // Create the LoginContext object, and pass it to the CallbackHandler
204         try
205         {
206             loginContext = new LoginContext(loginContextName, cbh);
207         }
208         catch (LoginException e)
209         {
210             throw new org.mule.umo.security.UnauthorisedException(
211                 CoreMessages.cannotLoadFromClasspath(loginContextName));
212         }
213 
214         // Attempt to login the user
215         try
216         {
217             loginContext.login();
218         }
219         catch (LoginException le)
220         {
221             throw new UnauthorisedException(CoreMessages.authFailedForUser(auth.getPrincipal()));
222         }
223 
224         auth.setAuthenticated(true);
225 
226         return auth;
227     }
228 
229     /**
230      * checks whether the class is supported.
231      * 
232      * @return
233      * @param aClass
234      */
235     public final boolean supports(Class aClass)
236     {
237         return UMOAuthentication.class.isAssignableFrom(aClass);
238     }
239 
240     /**
241      * @throws UnknownAuthenticationTypeException This occurs when the Security
242      *             Factory cannot be created
243      * @return
244      */
245     public final UMOSecurityContext createSecurityContext(UMOAuthentication auth)
246         throws UnknownAuthenticationTypeException
247     {
248         return factory.create(auth);
249     }
250 
251     /**
252      * The initialise method checks whether a jaas configuration file exists. If it
253      * exists, it will call the configureJaas() method to create the context URL of
254      * that file. If such a configuration file is not present, it will then try to
255      * configure jaas programmatically. It also attempts to create the
256      * JaasSecurityContextFactory.
257      * 
258      * @throws InitialisationException
259      */
260     public final void initialise() throws InitialisationException
261     {
262         // configure jaas from properties passed to the provider from the Mule XML
263         // configuration file
264         if (loginConfig == null)
265         {
266             try
267             {
268                 AppConfigurationEntry entry = null;
269                 JaasConfig.init();
270 
271                 HashMap options = new HashMap();
272                 options.put("credentials", credentials);
273 
274                 // if a custom login module is not found, it will use the Default
275                 // Login Module
276                 if (loginModule != null)
277                 {
278                     entry = new AppConfigurationEntry(loginModule,
279                         AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options);
280                 }
281                 else
282                 {
283                     entry = new AppConfigurationEntry(defaultModule,
284                         AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options);
285                 }
286 
287                 JaasConfig.addApplicationConfigEntry(loginContextName, entry);
288             }
289             catch (Exception e)
290             {
291                 throw new InitialisationException(e, this);
292             }
293         }
294         else
295         {
296             // configure jaas from a jaas configuration file
297             try
298             {
299                 configureJaas();
300             }
301             catch (IOException e)
302             {
303                 throw new InitialisationException(e, this);
304             }
305         }
306 
307         // create the Jaas SecurityContext Factory
308         try
309         {
310             factory = new JaasSecurityContextFactory();
311         }
312         catch (Exception e)
313         {
314             throw new InitialisationException(CoreMessages.failedToCreate("JaasProvider"), e);
315         }
316     }
317 
318     /**
319      * The JaasConfig class extends the Jaas Configuration in order to be able to
320      * configure the jaas security programmatically.
321      */
322     public static class JaasConfig extends Configuration
323     {
324 
325         private static Map appConfigEntries = new HashMap();
326         private static JaasConfig jaasConfig;
327 
328         /**
329          * Initializes and sets the Jaas Configuration
330          */
331         public static void init()
332         {
333             jaasConfig = new JaasConfig();
334             Configuration.setConfiguration(jaasConfig);
335         }
336 
337         /**
338          * Returns the Jas Configuration
339          * 
340          * @return jaasConfig
341          */
342         public static JaasConfig getJaasConfig()
343         {
344             return jaasConfig;
345         }
346 
347         /**
348          * Adds the Configuration Entries
349          * 
350          * @param name
351          * @param entry
352          */
353         public static void addApplicationConfigEntry(String name, AppConfigurationEntry entry)
354         {
355             appConfigEntries.put(name, entry);
356         }
357 
358         /**
359          * Gets the configuration entries using the application Name
360          * 
361          * @param applicationName
362          * @return
363          */
364         public final AppConfigurationEntry[] getAppConfigurationEntry(String applicationName)
365         {
366 
367             if (applicationName == null)
368             {
369                 throw new IllegalArgumentException("applicationName passed in was null.");
370             }
371 
372             AppConfigurationEntry entry = (AppConfigurationEntry)appConfigEntries.get(applicationName);
373             if (entry == null)
374             {
375                 return new AppConfigurationEntry[]{};
376             }
377             else
378             {
379                 AppConfigurationEntry e[] = new AppConfigurationEntry[1];
380                 e[0] = entry;
381                 return e;
382             }
383         }
384 
385         public void refresh()
386         {
387             // Nothing to do here
388         }
389     }
390 }