KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > geronimo > security > jaas > client > JaasLoginCoordinator


1 /**
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. 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.security.jaas.client;
18
19 import java.util.HashMap JavaDoc;
20 import java.util.Map JavaDoc;
21 import java.util.Set JavaDoc;
22 import javax.management.MalformedObjectNameException JavaDoc;
23 import javax.management.ObjectName JavaDoc;
24 import javax.security.auth.Subject JavaDoc;
25 import javax.security.auth.callback.CallbackHandler JavaDoc;
26 import javax.security.auth.login.FailedLoginException JavaDoc;
27 import javax.security.auth.login.LoginException JavaDoc;
28 import javax.security.auth.spi.LoginModule JavaDoc;
29
30 import org.apache.geronimo.kernel.Kernel;
31 import org.apache.geronimo.kernel.KernelRegistry;
32 import org.apache.geronimo.kernel.GBeanNotFoundException;
33 import org.apache.geronimo.security.jaas.server.JaasSessionId;
34 import org.apache.geronimo.security.jaas.server.JaasLoginModuleConfiguration;
35 import org.apache.geronimo.security.jaas.LoginModuleControlFlag;
36 import org.apache.geronimo.security.jaas.LoginUtils;
37 import org.apache.geronimo.security.jaas.server.JaasLoginServiceMBean;
38 import org.apache.geronimo.security.remoting.jmx.JaasLoginServiceRemotingClient;
39
40
41 /**
42  * A LoginModule implementation which connects to a Geronimo server under
43  * the covers, and uses Geronimo realms to resolve the login. It handles a
44  * mix of client-side and server-side login modules. It treats any client
45  * side module as something it should manage and execute, while a server side
46  * login module would be managed and executed by the Geronimo server.
47  * <p/>
48  * Note that this can actually be run from within a Geronimo server, in which
49  * case the client/server distinction is somewhat less important, and the
50  * communication is optimized by avoiding network traffic.
51  *
52  * @version $Rev: 476049 $ $Date: 2006-11-16 23:35:17 -0500 (Thu, 16 Nov 2006) $
53  */

54 public class JaasLoginCoordinator implements LoginModule JavaDoc {
55     public final static String JavaDoc OPTION_HOST = "host";
56     public final static String JavaDoc OPTION_PORT = "port";
57     public final static String JavaDoc OPTION_KERNEL = "kernel";
58     public final static String JavaDoc OPTION_REALM = "realm";
59     public final static String JavaDoc OPTION_SERVICENAME = "serviceName";
60     public final static String JavaDoc OPTION_SERVICE_INSTANCE = "serviceInstance";
61     private String JavaDoc serverHost;
62     private int serverPort;
63     private String JavaDoc realmName;
64     private String JavaDoc kernelName;
65     private ObjectName JavaDoc serviceName;
66     private JaasLoginServiceMBean service;
67     private CallbackHandler JavaDoc handler;
68     private Subject JavaDoc subject;
69     private JaasSessionId sessionHandle;
70     private LoginModuleProxy[] proxies;
71     private final Map JavaDoc sharedState = new HashMap JavaDoc();
72
73
74     public void initialize(Subject JavaDoc subject, CallbackHandler JavaDoc callbackHandler, Map JavaDoc sharedState, Map JavaDoc options) {
75         serverHost = (String JavaDoc) options.get(OPTION_HOST);
76         Object JavaDoc port = options.get(OPTION_PORT);
77         if (port != null) {
78             serverPort = Integer.parseInt((String JavaDoc) port);
79         }
80         realmName = (String JavaDoc) options.get(OPTION_REALM);
81         kernelName = (String JavaDoc) options.get(OPTION_KERNEL);
82         try {
83             String JavaDoc s = (String JavaDoc) options.get(OPTION_SERVICENAME);
84             serviceName = s != null ? new ObjectName JavaDoc(s) : null;
85         } catch (MalformedObjectNameException JavaDoc e) {
86             throw new IllegalArgumentException JavaDoc("option " + OPTION_SERVICENAME + "is not a valid ObjectName: " + options.get(OPTION_SERVICENAME));
87         }
88         if (port != null || kernelName != null) {
89             service = connect();
90         } else {
91             //primarily for testing without a kernel
92
service = (JaasLoginServiceMBean) options.get(OPTION_SERVICE_INSTANCE);
93         }
94         handler = callbackHandler;
95         if (subject == null) {
96             this.subject = new Subject JavaDoc();
97         } else {
98             this.subject = subject;
99         }
100     }
101
102     public boolean login() throws LoginException JavaDoc {
103         sessionHandle = service.connectToRealm(realmName);
104         JaasLoginModuleConfiguration[] config = service.getLoginConfiguration(sessionHandle);
105         proxies = new LoginModuleProxy[config.length];
106
107         for (int i = 0; i < proxies.length; i++) {
108             if (config[i].isServerSide()) {
109                 proxies[i] = new ServerLoginProxy(config[i].getFlag(), subject, i, service, sessionHandle);
110             } else {
111                 LoginModule JavaDoc source = config[i].getLoginModule(JaasLoginCoordinator.class.getClassLoader());
112                 if (config[i].isWrapPrincipals()) {
113                     proxies[i] = new WrappingClientLoginModuleProxy(config[i].getFlag(), subject, source, config[i].getLoginDomainName(), realmName);
114                 } else {
115                     proxies[i] = new ClientLoginModuleProxy(config[i].getFlag(), subject, source);
116                 }
117             }
118             proxies[i].initialize(subject, handler, sharedState, config[i].getOptions());
119             syncSharedState();
120         }
121         boolean result = performLogin();
122         if(result) {
123             return true;
124         } else {
125             // login() method should throw LoginException incase of failure
126
throw new FailedLoginException JavaDoc();
127         }
128     }
129
130     public boolean commit() throws LoginException JavaDoc {
131         for (int i = 0; i < proxies.length; i++) {
132             proxies[i].commit();
133             syncSharedState();
134             syncPrincipals();
135         }
136         subject.getPrincipals().add(service.loginSucceeded(sessionHandle));
137         return true;
138     }
139
140     public boolean abort() throws LoginException JavaDoc {
141         try {
142             for (int i = 0; i < proxies.length; i++) {
143                 proxies[i].abort();
144                 syncSharedState();
145             }
146         } finally {
147             service.loginFailed(sessionHandle);
148         }
149         clear();
150         return true;
151     }
152
153     public boolean logout() throws LoginException JavaDoc {
154         try {
155             for (int i = 0; i < proxies.length; i++) {
156                 proxies[i].logout();
157                 syncSharedState();
158             }
159         } finally {
160             service.logout(sessionHandle);
161         }
162         clear();
163         return true;
164     }
165
166     private void clear() {
167         service = null;
168         serverHost = null;
169         serverPort = 0;
170         realmName = null;
171         kernelName = null;
172         service = null;
173         handler = null;
174         subject = null;
175         sessionHandle = null;
176         proxies = null;
177     }
178
179     private JaasLoginServiceMBean connect() {
180         if (serverHost != null && serverPort > 0) {
181             return JaasLoginServiceRemotingClient.create(serverHost, serverPort);
182         } else {
183             Kernel kernel = KernelRegistry.getKernel(kernelName);
184             try {
185                 return (JaasLoginServiceMBean) kernel.getGBean(serviceName);
186             } catch (GBeanNotFoundException e) {
187                 IllegalStateException JavaDoc illegalStateException = new IllegalStateException JavaDoc();
188                 illegalStateException.initCause(e);
189                 throw illegalStateException;
190             }
191         }
192     }
193
194     /**
195      * See http://java.sun.com/j2se/1.4.2/docs/api/javax/security/auth/login/Configuration.html
196      *
197      * @return
198      * @throws LoginException
199      */

200     private boolean performLogin() throws LoginException JavaDoc {
201         Boolean JavaDoc success = null;
202         Boolean JavaDoc backup = null;
203
204         for (int i = 0; i < proxies.length; i++) {
205             LoginModuleProxy proxy = proxies[i];
206             boolean result;
207             try {
208                 result = proxy.login();
209             } catch(LoginException JavaDoc e) {
210                 result = false; // login() method throws LoginException incase of failure
211
}
212             syncSharedState();
213
214             if (proxy.getControlFlag() == LoginModuleControlFlag.REQUIRED) {
215                 if (success == null || success.booleanValue()) {
216                     success = result ? Boolean.TRUE : Boolean.FALSE;
217                 }
218             } else if (proxy.getControlFlag() == LoginModuleControlFlag.REQUISITE) {
219                 if (!result) {
220                     return false;
221                 } else if (success == null) {
222                     success = Boolean.TRUE;
223                 }
224             } else if (proxy.getControlFlag() == LoginModuleControlFlag.SUFFICIENT) {
225                 if (result && (success == null || success.booleanValue())) {
226                     return true;
227                 }
228             } else if (proxy.getControlFlag() == LoginModuleControlFlag.OPTIONAL) {
229                 if (backup == null || backup.booleanValue()) {
230                     backup = result ? Boolean.TRUE : Boolean.FALSE;
231                 }
232             }
233         }
234         // all required and requisite modules succeeded, or at least one required module failed
235
if (success != null) {
236             return success.booleanValue();
237         }
238         // no required or requisite modules, no sufficient modules succeeded, fall back to optional modules
239
if (backup != null) {
240             return backup.booleanValue();
241         }
242         // perhaps only a sufficient module, and it failed
243
return false;
244     }
245
246     private void syncSharedState() throws LoginException JavaDoc {
247         Map JavaDoc map = service.syncShareState(sessionHandle, LoginUtils.getSerializableCopy(sharedState));
248         sharedState.putAll(map);
249     }
250
251     private void syncPrincipals() throws LoginException JavaDoc {
252         Set JavaDoc principals = service.syncPrincipals(sessionHandle, subject.getPrincipals());
253         subject.getPrincipals().addAll(principals);
254     }
255 }
256
Popular Tags