View Javadoc

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