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