View Javadoc

1   /**
2    *
3    * Copyright 2004 The Apache Software Foundation
4    *
5    *  Licensed under the Apache License, Version 2.0 (the "License");
6    *  you may not use this file except in compliance with the License.
7    *  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   */
17  package org.apache.geronimo.jmxremoting;
18  
19  import java.util.Map;
20  import java.util.Collections;
21  import java.util.HashMap;
22  import javax.management.remote.JMXAuthenticator;
23  import javax.management.remote.JMXConnectionNotification;
24  import javax.management.NotificationListener;
25  import javax.management.Notification;
26  import javax.security.auth.Subject;
27  import javax.security.auth.login.LoginContext;
28  import javax.security.auth.login.LoginException;
29  
30  /**
31   * JMX Authenticator that checks the Credentials by logging in via JAAS.
32   *
33   * @version $Rev: 355877 $ $Date: 2005-12-10 18:48:27 -0800 (Sat, 10 Dec 2005) $
34   */
35  public class Authenticator implements JMXAuthenticator, NotificationListener {
36      private final String configName;
37      private final ClassLoader cl;
38      private ThreadLocal threadContext = new ThreadLocal();
39      private Map contextMap = Collections.synchronizedMap(new HashMap());
40  
41      /**
42       * Constructor indicating which JAAS Application Configuration Entry to use.
43       * @param configName the JAAS config name
44       */
45      public Authenticator(String configName, ClassLoader cl) {
46          this.configName = configName;
47          this.cl = cl;
48      }
49  
50      public Subject authenticate(Object o) throws SecurityException {
51          if (o instanceof String[] == false) {
52              throw new IllegalArgumentException("Expected String[2], got " + o == null ? null : o.getClass().getName());
53          }
54          String[] params = (String[]) o;
55          if (params.length != 2) {
56              throw new IllegalArgumentException("Expected String[2] but length was " + params.length);
57          }
58  
59          Thread thread = Thread.currentThread();
60          ClassLoader oldCL = thread.getContextClassLoader();
61          Credentials credentials = new Credentials(params[0], params[1]);
62          try {
63              thread.setContextClassLoader(cl);
64              LoginContext context = new LoginContext(configName, credentials);
65              context.login();
66              threadContext.set(context);
67              return context.getSubject();
68          } catch (LoginException e) {
69              // do not propogate cause - we don't know what information is may contain
70              throw new SecurityException("Invalid login");
71          } finally {
72              credentials.clear();
73              thread.setContextClassLoader(oldCL);
74          }
75      }
76  
77      public void handleNotification(Notification notification, Object o) {
78          if (notification instanceof JMXConnectionNotification) {
79              JMXConnectionNotification cxNotification = (JMXConnectionNotification) notification;
80              String type = cxNotification.getType();
81              String connectionId = cxNotification.getConnectionId();
82              if (JMXConnectionNotification.OPENED.equals(type)) {
83                  LoginContext context = (LoginContext) threadContext.get();
84                  threadContext.set(null);
85                  contextMap.put(connectionId, context);
86              } else {
87                  LoginContext context = (LoginContext) contextMap.remove(connectionId);
88                  if (context != null) {
89                      try {
90                          context.logout();
91                      } catch (LoginException e) {
92                          //nothing we can do here...
93                      }
94                  }
95              }
96          }
97      }
98  }