View Javadoc

1   /*
2    * $Id: JaasSimpleAuthenticationProvider.java 19191 2010-08-25 21:05:23Z tcarlson $
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 
215         return finalAuth;
216     }
217 
218     /**
219      * The initialise method checks whether a jaas configuration file exists. If it
220      * exists, it will call the configureJaas() method to create the context URL of
221      * that file. If such a configuration file is not present, it will then try to
222      * configure jaas programmatically. It also attempts to create the
223      * JaasSecurityContextFactory.
224      *
225      * @throws InitialisationException
226      */
227     protected void doInitialise() throws InitialisationException
228     {
229         // configure jaas from properties passed to the provider from the Mule XML
230         // configuration file
231         if (loginConfig == null)
232         {
233             try
234             {
235                 AppConfigurationEntry entry = null;
236                 JaasConfig.init();
237 
238                 HashMap options = new HashMap();
239                 options.put("credentials", credentials);
240 
241                 // if a custom login module is not found, it will use the Default
242                 // Login Module
243                 if (loginModule != null)
244                 {
245                     entry = new AppConfigurationEntry(loginModule,
246                             AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options);
247                 }
248                 else
249                 {
250                     entry = new AppConfigurationEntry(defaultModule,
251                             AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options);
252                 }
253 
254                 JaasConfig.addApplicationConfigEntry(loginContextName, entry);
255             }
256             catch (Exception e)
257             {
258                 throw new InitialisationException(e, this);
259             }
260         }
261         else
262         {
263             // configure jaas from a jaas configuration file
264             try
265             {
266                 configureJaas();
267             }
268             catch (IOException e)
269             {
270                 throw new InitialisationException(e, this);
271             }
272         }
273     }
274 
275     /**
276      * The JaasConfig class extends the Jaas Configuration in order to be able to
277      * configure the jaas security programmatically.
278      */
279     public static class JaasConfig extends Configuration
280     {
281 
282         private static Map appConfigEntries = new HashMap();
283         private static JaasConfig jaasConfig;
284 
285         /** Initializes and sets the Jaas Configuration */
286         public static void init()
287         {
288             jaasConfig = new JaasConfig();
289             Configuration.setConfiguration(jaasConfig);
290         }
291 
292         /**
293          * Returns the Jas Configuration
294          *
295          * @return jaasConfig
296          */
297         public static JaasConfig getJaasConfig()
298         {
299             return jaasConfig;
300         }
301 
302         /**
303          * Adds the Configuration Entries
304          *
305          * @param name
306          * @param entry
307          */
308         public static void addApplicationConfigEntry(String name, AppConfigurationEntry entry)
309         {
310             appConfigEntries.put(name, entry);
311         }
312 
313         /**
314          * Gets the configuration entries using the application Name
315          *
316          * @param applicationName
317          */
318         public final AppConfigurationEntry[] getAppConfigurationEntry(String applicationName)
319         {
320 
321             if (applicationName == null)
322             {
323                 throw new IllegalArgumentException("applicationName passed in was null.");
324             }
325 
326             AppConfigurationEntry entry = (AppConfigurationEntry) appConfigEntries.get(applicationName);
327             if (entry == null)
328             {
329                 return new AppConfigurationEntry[]{};
330             }
331             else
332             {
333                 AppConfigurationEntry e[] = new AppConfigurationEntry[1];
334                 e[0] = entry;
335                 return e;
336             }
337         }
338 
339         public void refresh()
340         {
341             // Nothing to do here
342         }
343     }
344 }