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
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
93 }
94 }
95 }
96 }
97 }
98 }