View Javadoc

1   /*
2    * $Id: JaasSimpleAuthenticationProvider.java 11517 2008-03-31 21:34:19Z 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.module.jaas;
12  
13  import org.mule.api.lifecycle.InitialisationException;
14  import org.mule.api.security.Authentication;
15  import org.mule.api.security.SecurityContext;
16  import org.mule.api.security.SecurityContextFactory;
17  import org.mule.api.security.SecurityProvider;
18  import org.mule.api.security.UnauthorisedException;
19  import org.mule.api.security.UnknownAuthenticationTypeException;
20  import org.mule.config.i18n.CoreMessages;
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 SecurityProvider
37  {
38  
39      private String loginConfig;
40      private String loginContextName;
41      private String credentials;
42      private String loginModule;
43      private String defaultModule = "org.mule.module.jaas.loginmodule.DefaultLoginModule";
44      private String name;
45      private SecurityContextFactory 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     /** @return name */
131     public final String getName()
132     {
133         return name;
134     }
135 
136     /** @param name  */
137     public final void setName(String name)
138     {
139         this.name = name;
140     }
141 
142     // ~ Methods ================================================================
143 
144     /**
145      * @throws IOException The configureJaas method gets the resource path of the
146      *                     jaas configuration file and constructs the URL for the login
147      *                     configuration.
148      */
149     private void configureJaas() throws IOException
150     {
151 
152         String loginConfigUrl = "file://"
153                 + org.mule.util.FileUtils.getResourcePath(loginConfig,
154                 JaasSimpleAuthenticationProvider.class);
155 
156         boolean alreadySet = false;
157 
158         int n = 1;
159         String prefix = "login.config.url.";
160         String existing = null;
161 
162         while ((existing = Security.getProperty(prefix + n)) != null)
163         {
164             alreadySet = existing.equals(loginConfigUrl);
165 
166             if (alreadySet)
167             {
168                 break;
169             }
170             n++;
171         }
172 
173         if (!alreadySet)
174         {
175             String key = prefix + n;
176             Security.setProperty(key, loginConfigUrl);
177         }
178     }
179 
180     /**
181      * The authenticate method first creates the jaas Login Context using the
182      * callback handler and the name of the class or directory to prtect. If the
183      * Login Context is successfully created, it will then attempt to login.
184      *
185      * @return Authentication
186      * @throws org.mule.api.security.SecurityException
187      *
188      */
189     public final Authentication authenticate(Authentication authentication)
190             throws org.mule.api.security.SecurityException
191     {
192         LoginContext loginContext;
193         JaasAuthentication auth = (JaasAuthentication)authentication;
194 
195         // Create the Mule Callback Handler
196         MuleCallbackHandler cbh = new MuleCallbackHandler(auth);
197 
198         // Create the LoginContext object, and pass it to the CallbackHandler
199         try
200         {
201             if (auth.getSubject() != null)
202             {
203                 loginContext = new LoginContext(loginContextName,auth.getSubject(), cbh);
204             }
205             else
206             {
207                 loginContext = new LoginContext(loginContextName, cbh);
208             }
209         }
210         catch (LoginException e)
211         {
212             throw new org.mule.api.security.UnauthorisedException(
213                     CoreMessages.cannotLoadFromClasspath(loginContextName));
214         }
215 
216         // Attempt to login the user
217         try
218         {
219             loginContext.login();
220         }
221         catch (LoginException le)
222         {
223             le.fillInStackTrace();
224             throw new UnauthorisedException(CoreMessages.authFailedForUser(auth.getPrincipal()));
225         }
226 
227         Subject subject = loginContext.getSubject();
228         JaasAuthentication finalAuth = new JaasAuthentication(auth.getPrincipal(), auth.getCredentials(),subject);
229         finalAuth.setAuthenticated(true);
230 
231         return finalAuth;
232     }
233 
234     /**
235      * checks whether the class is supported.
236      *
237      * @param aClass
238      * @return
239      */
240     public final boolean supports(Class aClass)
241     {
242         return Authentication.class.isAssignableFrom(aClass);
243     }
244 
245     /**
246      * @return
247      * @throws UnknownAuthenticationTypeException
248      *          This occurs when the Security
249      *          Factory cannot be created
250      */
251     public final SecurityContext createSecurityContext(Authentication auth)
252             throws UnknownAuthenticationTypeException
253     {
254         return factory.create(auth);
255     }
256 
257     /**
258      * The initialise method checks whether a jaas configuration file exists. If it
259      * exists, it will call the configureJaas() method to create the context URL of
260      * that file. If such a configuration file is not present, it will then try to
261      * configure jaas programmatically. It also attempts to create the
262      * JaasSecurityContextFactory.
263      *
264      * @throws InitialisationException
265      */
266     public final void initialise() throws InitialisationException
267     {
268         // configure jaas from properties passed to the provider from the Mule XML
269         // configuration file
270         if (loginConfig == null)
271         {
272             try
273             {
274                 AppConfigurationEntry entry = null;
275                 JaasConfig.init();
276 
277                 HashMap options = new HashMap();
278                 options.put("credentials", credentials);
279 
280                 // if a custom login module is not found, it will use the Default
281                 // Login Module
282                 if (loginModule != null)
283                 {
284                     entry = new AppConfigurationEntry(loginModule,
285                             AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options);
286                 }
287                 else
288                 {
289                     entry = new AppConfigurationEntry(defaultModule,
290                             AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options);
291                 }
292 
293                 JaasConfig.addApplicationConfigEntry(loginContextName, entry);
294             }
295             catch (Exception e)
296             {
297                 throw new InitialisationException(e, this);
298             }
299         }
300         else
301         {
302             // configure jaas from a jaas configuration file
303             try
304             {
305                 configureJaas();
306             }
307             catch (IOException e)
308             {
309                 throw new InitialisationException(e, this);
310             }
311         }
312 
313         // create the Jaas SecurityContext Factory
314         try
315         {
316             factory = new JaasSecurityContextFactory();
317         }
318         catch (Exception e)
319         {
320             throw new InitialisationException(CoreMessages.failedToCreate("JaasProvider"), e, this);
321         }
322     }
323 
324     /**
325      * The JaasConfig class extends the Jaas Configuration in order to be able to
326      * configure the jaas security programmatically.
327      */
328     public static class JaasConfig extends Configuration
329     {
330 
331         private static Map appConfigEntries = new HashMap();
332         private static JaasConfig jaasConfig;
333 
334         /** Initializes and sets the Jaas Configuration */
335         public static void init()
336         {
337             jaasConfig = new JaasConfig();
338             Configuration.setConfiguration(jaasConfig);
339         }
340 
341         /**
342          * Returns the Jas Configuration
343          *
344          * @return jaasConfig
345          */
346         public static JaasConfig getJaasConfig()
347         {
348             return jaasConfig;
349         }
350 
351         /**
352          * Adds the Configuration Entries
353          *
354          * @param name
355          * @param entry
356          */
357         public static void addApplicationConfigEntry(String name, AppConfigurationEntry entry)
358         {
359             appConfigEntries.put(name, entry);
360         }
361 
362         /**
363          * Gets the configuration entries using the application Name
364          *
365          * @param applicationName
366          * @return
367          */
368         public final AppConfigurationEntry[] getAppConfigurationEntry(String applicationName)
369         {
370 
371             if (applicationName == null)
372             {
373                 throw new IllegalArgumentException("applicationName passed in was null.");
374             }
375 
376             AppConfigurationEntry entry = (AppConfigurationEntry) appConfigEntries.get(applicationName);
377             if (entry == null)
378             {
379                 return new AppConfigurationEntry[]{};
380             }
381             else
382             {
383                 AppConfigurationEntry e[] = new AppConfigurationEntry[1];
384                 e[0] = entry;
385                 return e;
386             }
387         }
388 
389         public void refresh()
390         {
391             // Nothing to do here
392         }
393     }
394 }