View Javadoc

1   /*
2    * $Id: JaasSimpleAuthenticationProvider.java 8467 2007-09-18 11:44:20Z marie.rizzo $
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.umo.lifecycle.InitialisationException;
15  import org.mule.umo.security.UMOAuthentication;
16  import org.mule.umo.security.UMOSecurityContext;
17  import org.mule.umo.security.UMOSecurityContextFactory;
18  import org.mule.umo.security.UMOSecurityProvider;
19  import org.mule.umo.security.UnauthorisedException;
20  import org.mule.umo.security.UnknownAuthenticationTypeException;
21  
22  import java.io.IOException;
23  import java.security.Security;
24  import java.util.HashMap;
25  import java.util.Map;
26  
27  import javax.security.auth.Subject;
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   * 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         LoginContext loginContext;
197         JaasAuthentication auth = (JaasAuthentication)authentication;
198 
199         // Create the Mule Callback Handler
200         MuleCallbackHandler cbh = new MuleCallbackHandler(auth);
201 
202         // Create the LoginContext object, and pass it to the CallbackHandler
203         try
204         {
205             if (auth.getSubject() != null)
206             {
207                 loginContext = new LoginContext(loginContextName,auth.getSubject(), cbh);
208             }
209             else
210             {
211                 loginContext = new LoginContext(loginContextName, cbh);
212             }
213         }
214         catch (LoginException e)
215         {
216             throw new org.mule.umo.security.UnauthorisedException(
217                 CoreMessages.cannotLoadFromClasspath(loginContextName));
218         }
219 
220         // Attempt to login the user
221         try
222         {
223             loginContext.login();
224         }
225         catch (LoginException le)
226         {
227             le.fillInStackTrace();
228             throw new UnauthorisedException(CoreMessages.authFailedForUser(auth.getPrincipal()));
229         }
230 
231         Subject subject = loginContext.getSubject();
232         JaasAuthentication finalAuth = new JaasAuthentication(auth.getPrincipal(), auth.getCredentials(),subject);
233         finalAuth.setAuthenticated(true);
234         
235         return finalAuth;
236     }
237 
238     /**
239      * checks whether the class is supported.
240      * 
241      * @return
242      * @param aClass
243      */
244     public final boolean supports(Class aClass)
245     {
246         return UMOAuthentication.class.isAssignableFrom(aClass);
247     }
248 
249     /**
250      * @throws UnknownAuthenticationTypeException This occurs when the Security
251      *             Factory cannot be created
252      * @return
253      */
254     public final UMOSecurityContext createSecurityContext(UMOAuthentication auth)
255         throws UnknownAuthenticationTypeException
256     {
257         return factory.create(auth);
258     }
259 
260     /**
261      * The initialise method checks whether a jaas configuration file exists. If it
262      * exists, it will call the configureJaas() method to create the context URL of
263      * that file. If such a configuration file is not present, it will then try to
264      * configure jaas programmatically. It also attempts to create the
265      * JaasSecurityContextFactory.
266      * 
267      * @throws InitialisationException
268      */
269     public final void initialise() throws InitialisationException
270     {
271         // configure jaas from properties passed to the provider from the Mule XML
272         // configuration file
273         if (loginConfig == null)
274         {
275             try
276             {
277                 AppConfigurationEntry entry = null;
278                 JaasConfig.init();
279 
280                 HashMap options = new HashMap();
281                 options.put("credentials", credentials);
282 
283                 // if a custom login module is not found, it will use the Default
284                 // Login Module
285                 if (loginModule != null)
286                 {
287                     entry = new AppConfigurationEntry(loginModule,
288                         AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options);
289                 }
290                 else
291                 {
292                     entry = new AppConfigurationEntry(defaultModule,
293                         AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options);
294                 }
295 
296                 JaasConfig.addApplicationConfigEntry(loginContextName, entry);
297             }
298             catch (Exception e)
299             {
300                 throw new InitialisationException(e, this);
301             }
302         }
303         else
304         {
305             // configure jaas from a jaas configuration file
306             try
307             {
308                 configureJaas();
309             }
310             catch (IOException e)
311             {
312                 throw new InitialisationException(e, this);
313             }
314         }
315 
316         // create the Jaas SecurityContext Factory
317         try
318         {
319             factory = new JaasSecurityContextFactory();
320         }
321         catch (Exception e)
322         {
323             throw new InitialisationException(CoreMessages.failedToCreate("JaasProvider"), e);
324         }
325     }
326 
327     /**
328      * The JaasConfig class extends the Jaas Configuration in order to be able to
329      * configure the jaas security programmatically.
330      */
331     public static class JaasConfig extends Configuration
332     {
333 
334         private static Map appConfigEntries = new HashMap();
335         private static JaasConfig jaasConfig;
336 
337         /**
338          * Initializes and sets the Jaas Configuration
339          */
340         public static void init()
341         {
342             jaasConfig = new JaasConfig();
343             Configuration.setConfiguration(jaasConfig);
344         }
345 
346         /**
347          * Returns the Jas Configuration
348          * 
349          * @return jaasConfig
350          */
351         public static JaasConfig getJaasConfig()
352         {
353             return jaasConfig;
354         }
355 
356         /**
357          * Adds the Configuration Entries
358          * 
359          * @param name
360          * @param entry
361          */
362         public static void addApplicationConfigEntry(String name, AppConfigurationEntry entry)
363         {
364             appConfigEntries.put(name, entry);
365         }
366 
367         /**
368          * Gets the configuration entries using the application Name
369          * 
370          * @param applicationName
371          * @return
372          */
373         public final AppConfigurationEntry[] getAppConfigurationEntry(String applicationName)
374         {
375 
376             if (applicationName == null)
377             {
378                 throw new IllegalArgumentException("applicationName passed in was null.");
379             }
380 
381             AppConfigurationEntry entry = (AppConfigurationEntry)appConfigEntries.get(applicationName);
382             if (entry == null)
383             {
384                 return new AppConfigurationEntry[]{};
385             }
386             else
387             {
388                 AppConfigurationEntry e[] = new AppConfigurationEntry[1];
389                 e[0] = entry;
390                 return e;
391             }
392         }
393 
394         public void refresh()
395         {
396             // Nothing to do here
397         }
398     }
399 }