KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > geronimo > security > ContextManager


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
18 package org.apache.geronimo.security;
19
20 import java.io.Serializable JavaDoc;
21 import java.security.AccessControlContext JavaDoc;
22 import java.security.AccessControlException JavaDoc;
23 import java.security.AccessController JavaDoc;
24 import java.security.InvalidKeyException JavaDoc;
25 import java.security.NoSuchAlgorithmException JavaDoc;
26 import java.security.Principal JavaDoc;
27 import java.security.PrivilegedAction JavaDoc;
28 import java.util.Hashtable JavaDoc;
29 import java.util.IdentityHashMap JavaDoc;
30 import java.util.Map JavaDoc;
31 import java.util.Set JavaDoc;
32 import javax.crypto.Mac;
33 import javax.crypto.SecretKey;
34 import javax.crypto.spec.SecretKeySpec;
35 import javax.security.auth.Subject JavaDoc;
36 import javax.security.jacc.EJBRoleRefPermission JavaDoc;
37
38 import org.apache.geronimo.security.realm.providers.GeronimoCallerPrincipal;
39
40
41 /**
42  * @version $Rev: 479880 $ $Date: 2006-11-27 22:45:44 -0500 (Mon, 27 Nov 2006) $
43  */

44 public class ContextManager {
45     private static ThreadLocal JavaDoc currentCallerId = new ThreadLocal JavaDoc();
46     private static final ThreadLocal JavaDoc callers = new ThreadLocal JavaDoc();
47     private static Map JavaDoc subjectContexts = new IdentityHashMap JavaDoc();
48     private static Map JavaDoc subjectIds = new Hashtable JavaDoc();
49     private static long nextSubjectId = System.currentTimeMillis();
50
51     private static SecretKey key;
52     private static String JavaDoc algorithm;
53     private static String JavaDoc password;
54
55     public static final GeronimoSecurityPermission GET_CONTEXT = new GeronimoSecurityPermission("getContext");
56     public static final GeronimoSecurityPermission SET_CONTEXT = new GeronimoSecurityPermission("setContext");
57
58     static {
59         password = "secret";
60         ContextManager.setAlgorithm("HmacSHA1");
61     }
62
63     /**
64      * After a login, the client is left with a relatively empty Subject, while
65      * the Subject used by the server has more important contents. This method
66      * lets a server-side component acting as an authentication client (such
67      * as Tocmat/Jetty) access the fully populated server-side Subject.
68      */

69     public static Subject JavaDoc getServerSideSubject(Subject JavaDoc clientSideSubject) {
70         Set JavaDoc set = clientSideSubject.getPrincipals(IdentificationPrincipal.class);
71         if(set == null || set.size() == 0) {
72             return null;
73         }
74         IdentificationPrincipal idp = (IdentificationPrincipal)set.iterator().next();
75         return getRegisteredSubject(idp.getId());
76     }
77
78     public static void setCurrentCallerId(Serializable JavaDoc id) {
79         SecurityManager JavaDoc sm = System.getSecurityManager();
80         if (sm != null) sm.checkPermission(SET_CONTEXT);
81
82         currentCallerId.set(id);
83     }
84
85     public static Serializable JavaDoc getCurrentCallerId() {
86         SecurityManager JavaDoc sm = System.getSecurityManager();
87         if (sm != null) sm.checkPermission(GET_CONTEXT);
88
89         return (Serializable JavaDoc) currentCallerId.get();
90     }
91
92     public static void setCallers(Subject JavaDoc currentCaller, Subject JavaDoc nextCaller) {
93         SecurityManager JavaDoc sm = System.getSecurityManager();
94         if (sm != null) sm.checkPermission(SET_CONTEXT);
95         assert currentCaller != null;
96         assert nextCaller != null;
97         Callers newCallers = new Callers(currentCaller, nextCaller);
98         callers.set(newCallers);
99     }
100
101     public static void clearCallers() {
102         callers.set(null);
103     }
104
105     public static Callers getCallers() {
106         SecurityManager JavaDoc sm = System.getSecurityManager();
107         if (sm != null) sm.checkPermission(GET_CONTEXT);
108         return (Callers) callers.get();
109     }
110
111     public static Callers setNextCaller(Subject JavaDoc nextCaller) {
112         SecurityManager JavaDoc sm = System.getSecurityManager();
113         if (sm != null) sm.checkPermission(SET_CONTEXT);
114         assert nextCaller != null;
115         Callers oldCallers = (Callers) callers.get();
116         assert oldCallers != null;
117         Callers newCallers = new Callers(oldCallers.getNextCaller(), nextCaller);
118         callers.set(newCallers);
119         return oldCallers;
120     }
121
122     public static Callers pushNextCaller(Subject JavaDoc nextCaller) {
123         SecurityManager JavaDoc sm = System.getSecurityManager();
124         if (sm != null) sm.checkPermission(SET_CONTEXT);
125         Callers oldCallers = (Callers) callers.get();
126         Subject JavaDoc oldNextCaller = oldCallers == null? null: oldCallers.getNextCaller();
127         Subject JavaDoc newNextCaller = nextCaller == null? oldNextCaller : nextCaller;
128         Callers newCallers = new Callers(oldNextCaller, newNextCaller);
129         callers.set(newCallers);
130         return oldCallers;
131     }
132
133     public static void popCallers(Callers oldCallers) {
134         SecurityManager JavaDoc sm = System.getSecurityManager();
135         if (sm != null) sm.checkPermission(SET_CONTEXT);
136         callers.set(oldCallers);
137     }
138
139     public static Subject JavaDoc getCurrentCaller() {
140         SecurityManager JavaDoc sm = System.getSecurityManager();
141         if (sm != null) sm.checkPermission(GET_CONTEXT);
142
143         Callers callers = (Callers) ContextManager.callers.get();
144         return callers == null? null: callers.getCurrentCaller();
145     }
146
147     public static Subject JavaDoc getNextCaller() {
148         SecurityManager JavaDoc sm = System.getSecurityManager();
149         if (sm != null) sm.checkPermission(GET_CONTEXT);
150
151         Callers callers = (Callers) ContextManager.callers.get();
152         return callers == null? null: callers.getNextCaller();
153     }
154
155     public static AccessControlContext JavaDoc getCurrentContext() {
156         SecurityManager JavaDoc sm = System.getSecurityManager();
157         if (sm != null) sm.checkPermission(GET_CONTEXT);
158
159         Callers threadLocalCallers = (Callers) callers.get();
160         assert threadLocalCallers != null : "No current callers";
161         Subject JavaDoc currentSubject = threadLocalCallers.getCurrentCaller();
162         assert currentSubject != null : "No current caller";
163         Context JavaDoc context = (Context JavaDoc) subjectContexts.get(currentSubject);
164
165         assert context != null : "No registered context";
166
167         return context.context;
168     }
169
170     public static Principal JavaDoc getCurrentPrincipal(Subject JavaDoc callerSubject) {
171         SecurityManager JavaDoc sm = System.getSecurityManager();
172         if (sm != null) sm.checkPermission(GET_CONTEXT);
173
174         if (callerSubject == null) {
175             return new Principal JavaDoc() {
176                 public String JavaDoc getName() {
177                     return "";
178                 }
179             };
180         }
181         Context JavaDoc context = (Context JavaDoc) subjectContexts.get(callerSubject);
182
183         assert context != null : "No registered context";
184
185         return context.principal;
186     }
187
188     public static SubjectId getCurrentId() {
189         SecurityManager JavaDoc sm = System.getSecurityManager();
190         if (sm != null) sm.checkPermission(GET_CONTEXT);
191
192         Callers threadLocalCallers = (Callers) callers.get();
193         assert threadLocalCallers != null : "No current callers";
194         Subject JavaDoc currentSubject = threadLocalCallers.getCurrentCaller();
195         assert currentSubject != null : "No current caller";
196         Context JavaDoc context = (Context JavaDoc) subjectContexts.get(currentSubject);
197
198         assert context != null : "No registered context";
199
200         return context.id;
201     }
202
203     public static SubjectId getSubjectId(Subject JavaDoc subject) {
204         SecurityManager JavaDoc sm = System.getSecurityManager();
205         if (sm != null) sm.checkPermission(GET_CONTEXT);
206
207         Context JavaDoc context = (Context JavaDoc) subjectContexts.get(subject);
208
209         return (context != null ? context.id : null);
210     }
211
212     public static boolean isCallerInRole(String JavaDoc EJBName, String JavaDoc role) {
213         if (EJBName == null) throw new IllegalArgumentException JavaDoc("EJBName must not be null");
214         if (role == null) throw new IllegalArgumentException JavaDoc("Role must not be null");
215
216         try {
217             Callers currentCallers = (Callers)callers.get();
218             if (currentCallers == null) {
219                 return false;
220             }
221             Subject JavaDoc currentSubject = currentCallers.getCurrentCaller();
222             if (currentSubject == null) {
223                 return false;
224             }
225
226             Context JavaDoc context = (Context JavaDoc) subjectContexts.get(currentSubject);
227
228             assert context != null : "No registered context";
229
230             context.context.checkPermission(new EJBRoleRefPermission JavaDoc(EJBName, role));
231         } catch (AccessControlException JavaDoc e) {
232             return false;
233         }
234         return true;
235     }
236
237     public static Subject JavaDoc getRegisteredSubject(SubjectId id) {
238         return (Subject JavaDoc) subjectIds.get(id);
239     }
240
241     public static synchronized SubjectId registerSubject(Subject JavaDoc subject) {
242         SecurityManager JavaDoc sm = System.getSecurityManager();
243         if (sm != null) sm.checkPermission(SET_CONTEXT);
244
245         if (subject == null) throw new IllegalArgumentException JavaDoc("Subject must not be null");
246
247         AccessControlContext JavaDoc acc = (AccessControlContext JavaDoc) Subject.doAsPrivileged(subject, new PrivilegedAction JavaDoc() {
248             public Object JavaDoc run() {
249                 return AccessController.getContext();
250             }
251         }, null);
252
253         Context JavaDoc context = new Context JavaDoc();
254         context.subject = subject;
255         context.context = acc;
256         Set JavaDoc principals = subject.getPrincipals((Class JavaDoc)GeronimoCallerPrincipal.class);
257         if (!principals.isEmpty()) {
258             context.principal = (Principal JavaDoc) principals.iterator().next();
259         } else if (!(principals = subject.getPrincipals(PrimaryRealmPrincipal.class)).isEmpty()) {
260             context.principal = (PrimaryRealmPrincipal) principals.iterator().next();
261         } else if (!(principals = subject.getPrincipals(RealmPrincipal.class)).isEmpty()) {
262             context.principal = (RealmPrincipal) principals.iterator().next();
263         } else if (!(principals = subject.getPrincipals()).isEmpty()) {
264             context.principal = (Principal JavaDoc) principals.iterator().next();
265         }
266         Long JavaDoc id = new Long JavaDoc(nextSubjectId++);
267         context.id = new SubjectId(id, hash(id));
268
269         subjectIds.put(context.id, subject);
270         subjectContexts.put(subject, context);
271
272         return context.id;
273     }
274
275     public static synchronized void unregisterSubject(Subject JavaDoc subject) {
276         SecurityManager JavaDoc sm = System.getSecurityManager();
277         if (sm != null) sm.checkPermission(SET_CONTEXT);
278
279         if (subject == null) throw new IllegalArgumentException JavaDoc("Subject must not be null");
280
281         Context JavaDoc context = (Context JavaDoc) subjectContexts.get(subject);
282         if (context == null) return;
283
284         subjectIds.remove(context.id);
285         subjectContexts.remove(subject);
286     }
287
288     /**
289      * Obtain the thread's identifying principal.
290      * <p/>
291      * Clients should use <code>Subject.doAs*</code> to associate a Subject
292      * with the thread's call stack. It is this Subject that will be used for
293      * authentication checks.
294      * <p/>
295      * Return a <code>IdentificationPrincipal</code>. This kind of principal
296      * is inserted into a subject if one uses one of the Geronimo LoginModules.
297      * It is a secure id that identifies the Subject.
298      *
299      * @return the principal that identifies the Subject of this thread.
300      * @see Subject#doAs(javax.security.auth.Subject, java.security.PrivilegedAction)
301      * @see Subject#doAs(javax.security.auth.Subject, java.security.PrivilegedExceptionAction)
302      * @see Subject#doAsPrivileged(javax.security.auth.Subject, java.security.PrivilegedAction, java.security.AccessControlContext)
303      * @see Subject#doAsPrivileged(javax.security.auth.Subject, java.security.PrivilegedExceptionAction, java.security.AccessControlContext)
304      */

305     public static IdentificationPrincipal getThreadPrincipal() {
306         SecurityManager JavaDoc sm = System.getSecurityManager();
307         if (sm != null) sm.checkPermission(GET_CONTEXT);
308
309         Subject JavaDoc subject = Subject.getSubject(AccessController.getContext());
310         if (subject != null) {
311             Set JavaDoc set = subject.getPrincipals(IdentificationPrincipal.class);
312             if (!set.isEmpty()) return (IdentificationPrincipal) set.iterator().next();
313         }
314         return null;
315     }
316
317     public static String JavaDoc getAlgorithm() {
318         SecurityManager JavaDoc sm = System.getSecurityManager();
319         if (sm != null) sm.checkPermission(GET_CONTEXT);
320
321         return algorithm;
322     }
323
324     public static void setAlgorithm(String JavaDoc algorithm) {
325         SecurityManager JavaDoc sm = System.getSecurityManager();
326         if (sm != null) sm.checkPermission(SET_CONTEXT);
327
328         ContextManager.algorithm = algorithm;
329
330         key = new SecretKeySpec(password.getBytes(), algorithm);
331
332         /**
333          * Make sure that we can generate the Mac.
334          */

335         try {
336             Mac mac = Mac.getInstance(algorithm);
337             mac.init(key);
338         } catch (NoSuchAlgorithmException JavaDoc e) {
339             assert false : "Should never have reached here";
340         } catch (InvalidKeyException JavaDoc e) {
341             assert false : "Should never have reached here";
342         }
343     }
344
345     public static String JavaDoc getPassword() {
346         SecurityManager JavaDoc sm = System.getSecurityManager();
347         if (sm != null) sm.checkPermission(GET_CONTEXT);
348
349         return password;
350     }
351
352     public static void setPassword(String JavaDoc password) {
353         SecurityManager JavaDoc sm = System.getSecurityManager();
354         if (sm != null) sm.checkPermission(SET_CONTEXT);
355
356         ContextManager.password = password;
357
358         key = new SecretKeySpec(password.getBytes(), algorithm);
359     }
360
361     private static byte[] hash(Long JavaDoc id) {
362         long n = id.longValue();
363         byte[] bytes = new byte[8];
364         for (int i = 7; i >= 0; i--) {
365             bytes[i] = (byte) (n);
366             n >>>= 8;
367         }
368
369         try {
370             Mac mac = Mac.getInstance(algorithm);
371             mac.init(key);
372             mac.update(bytes);
373
374             return mac.doFinal();
375         } catch (NoSuchAlgorithmException JavaDoc e) {
376         } catch (InvalidKeyException JavaDoc e) {
377         }
378         assert false : "Should never have reached here";
379         return null;
380     }
381
382     private static class Context {
383         SubjectId id;
384         AccessControlContext JavaDoc context;
385         Subject JavaDoc subject;
386         Principal JavaDoc principal;
387     }
388
389 }
390
Popular Tags