001: /**
002: * JOnAS: Java(TM) Open Application Server
003: * Copyright (C) 1999-2005 Bull S.A.
004: * Contact: jonas-team@objectweb.org
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
019: * USA
020: *
021: * --------------------------------------------------------------------------
022: * $Id: SecurityContext.java 9905 2007-01-05 12:34:30Z benoitf $
023: * --------------------------------------------------------------------------
024: */package org.objectweb.security.context;
025:
026: import java.io.Serializable;
027: import java.security.Principal;
028: import java.util.ArrayList;
029: import java.util.Collections;
030: import java.util.Iterator;
031: import java.util.List;
032:
033: import org.objectweb.jonas.security.jacc.JPolicyUserRoleMapping;
034:
035: /**
036: * Implementation of the JOnAS Security Context CAUTION: Don't forget to modify
037: * the Marshalling class of this package used for IIOP protocol
038: * @author Jeff Mesnil (initial developer)
039: * @author Florent Benoit
040: */
041:
042: public class SecurityContext implements Serializable {
043:
044: /**
045: * Name of the principal
046: */
047: private String principalName = null;
048:
049: /**
050: * List of roles of the principal
051: */
052: private final String[] roles;
053:
054: /**
055: * run-as stack It uses ArrayList instead of java.util.Stack class This is
056: * for use ArrayList and not Vector as Stack implementation
057: */
058: private List runAsRoleStack = null;
059:
060: /**
061: * This stack is used for defining the principal identity for runAs
062: */
063: private List runAsPrincipalStack = null;
064:
065: /**
066: * This stack is used for defining the roles of the principal identity for
067: * runAs
068: */
069: private List runAsPrincipalRolesStack = null;
070:
071: /**
072: * Signature.
073: */
074: private byte[] signedData = null;
075:
076: /**
077: * Constructor SecurityContext use the default principal name
078: */
079: public SecurityContext() {
080: this ("ANONYMOUS");
081: }
082:
083: /**
084: * Constructor SecurityContext
085: * @param principalName principal name
086: * @param roles the roles of the principal
087: */
088: public SecurityContext(String principalName, String[] roles) {
089: this .principalName = principalName;
090: this .roles = roles;
091: }
092:
093: /**
094: * Constructor SecurityContext
095: * @param principalName principal name
096: * @param arrayRoles the list of the roles of the principal
097: */
098: public SecurityContext(String principalName, List arrayRoles) {
099: this (principalName, arrayRoles, null, null, null);
100: }
101:
102: /**
103: * Constructor SecurityContext
104: * @param principalName principal name
105: * @param arrayRoles the list of the roles of the principal
106: * @param arrayRunas the RunAs stack
107: * @param arrayRunasPrincipal the RunAs stack for principal of runAs
108: * @param arrayRunasPrincipalRoles the RunAs stack for roles of the principal
109: *
110: */
111: protected SecurityContext(String principalName, List arrayRoles,
112: List arrayRunas, List arrayRunasPrincipal,
113: List arrayRunasPrincipalRoles) {
114: this .principalName = principalName;
115: String[] overridedRoles = JPolicyUserRoleMapping
116: .getGlobalMappingForPrincipal(principalName);
117: if (overridedRoles != null) {
118: this .roles = overridedRoles;
119: } else {
120: if (arrayRoles != null) {
121: //Convert list into array
122: String[] r = new String[arrayRoles.size()];
123: r = (String[]) arrayRoles.toArray(r);
124: this .roles = r;
125: } else {
126: this .roles = null;
127: }
128: }
129:
130: this .runAsRoleStack = arrayRunas;
131: this .runAsPrincipalStack = arrayRunasPrincipal;
132: this .runAsPrincipalRolesStack = arrayRunasPrincipalRoles;
133: }
134:
135: /**
136: * Constructor SecurityContext
137: * @param principalName principal name
138: */
139: public SecurityContext(String principalName) {
140: this .principalName = principalName;
141: this .roles = new String[] { "JOnAS" };
142: }
143:
144: /**
145: * Method getCallerPrincipal
146: * @param inRunAs is the caller is in a runAs case in RunAs mode this
147: * function must return the caller of the bean and not the run as
148: * identity (EJB 2.1 chapter21.2.5.1)
149: * @return the Principal in the Security Context
150: */
151: public Principal getCallerPrincipal(boolean inRunAs) {
152: return new InternalPrincipal(inRunAs);
153: }
154:
155: /**
156: * Gets the signature.
157: * @return signature
158: */
159: public byte[] getSignature() {
160: return signedData;
161: }
162:
163: /**
164: * Sets the signature.
165: * @param signedData the given data of the signature.
166: */
167: public void setSignature(final byte[] signedData) {
168: this .signedData = signedData;
169: }
170:
171: /**
172: * Return the roles of the principal
173: * @param inRunAs caller is in run-as bean ?
174: * @return roles of this principal
175: */
176: public String[] getCallerPrincipalRoles(boolean inRunAs) {
177: String[] runAsRoles = null;
178: if (inRunAs) {
179: runAsRoles = peekLastRunAsPrincipalRoles();
180: } else {
181: runAsRoles = peekRunAsPrincipalRoles();
182: }
183: if (runAsRoles != null) {
184: return runAsRoles;
185: } else {
186: return roles;
187: }
188: }
189:
190: /**
191: * Push : Pushes run-as items at the top of this stack.
192: * @param role the role to add on top of the stack
193: * @param principalName the name of the principal to add on top of the
194: * stack.
195: * @param roles list of roles of this principal.
196: */
197: public synchronized void pushRunAs(String role,
198: String principalName, String[] roles) {
199: getRunAsRoleStack().add(role);
200: getRunAsPrincipalStack().add(principalName);
201: getRunAsPrincipalRolesStack().add(roles);
202: }
203:
204: /**
205: * Pop : Removes the object at the top of the run-as stack
206: */
207: public synchronized void popRunAs() {
208: if (!getRunAsRoleStack().isEmpty()) {
209: getRunAsRoleStack().remove(getRunAsRoleStack().size() - 1);
210: }
211: if (!getRunAsPrincipalStack().isEmpty()) {
212: getRunAsPrincipalStack().remove(
213: getRunAsPrincipalStack().size() - 1);
214: }
215: if (!getRunAsPrincipalRolesStack().isEmpty()) {
216: getRunAsPrincipalRolesStack().remove(
217: getRunAsPrincipalRolesStack().size() - 1);
218: }
219: }
220:
221: /**
222: * Peek : Looks at the object at the top of this stack without removing it
223: * from the stack.
224: * @return the role at the top of the stack
225: */
226: public synchronized String peekRunAsRole() {
227: if (getRunAsRoleStack().isEmpty()) {
228: return null;
229: } else {
230: return (String) getRunAsRoleStack().get(
231: getRunAsRoleStack().size() - 1);
232: }
233: }
234:
235: /**
236: * Peek : Looks at the object at the top of this stack without removing it
237: * from the stack.
238: * @return the principal at the top of the stack
239: */
240: public synchronized String peekRunAsPrincipal() {
241: if (getRunAsPrincipalStack().isEmpty()) {
242: return null;
243: } else {
244: return (String) getRunAsPrincipalStack().get(
245: getRunAsPrincipalStack().size() - 1);
246: }
247: }
248:
249: /**
250: * Peek : Looks at the object at the top of this stack without removing it
251: * from the stack.
252: * @return the principal at the top of the stack
253: */
254: public synchronized String peekLastRunAsPrincipal() {
255: if (getRunAsPrincipalStack().size() < 2) {
256: return null;
257: } else {
258: return (String) getRunAsPrincipalStack().get(
259: getRunAsPrincipalStack().size() - 2);
260: }
261: }
262:
263: /**
264: * Peek : Looks at the object at the top of this stack without removing it
265: * from the stack.
266: * @return the principal at the top of the stack
267: */
268: public synchronized String[] peekRunAsPrincipalRoles() {
269: if (getRunAsPrincipalRolesStack().isEmpty()) {
270: return null;
271: } else {
272: return (String[]) getRunAsPrincipalRolesStack().get(
273: getRunAsPrincipalRolesStack().size() - 1);
274: }
275: }
276:
277: /**
278: * Peek : Looks at the object at the top of this stack without removing it
279: * from the stack.
280: * @return the principal at the top of the stack
281: */
282: public synchronized String[] peekLastRunAsPrincipalRoles() {
283: if (getRunAsPrincipalRolesStack().size() < 2) {
284: return null;
285: } else {
286: return (String[]) getRunAsPrincipalRolesStack().get(
287: getRunAsPrincipalRolesStack().size() - 2);
288: }
289: }
290:
291: /**
292: * Gets the stack which manages the run-as
293: * @return the stack which manages the run-as
294: */
295: public synchronized List getRunAsRoleStack() {
296: if (runAsRoleStack == null) {
297: runAsRoleStack = Collections
298: .synchronizedList(new ArrayList());
299: }
300: return runAsRoleStack;
301: }
302:
303: /**
304: * Gets the stack which manages the roles of the current run-as principal
305: * @return the stack which manages the roles of the current run-as principal
306: */
307: public synchronized List getRunAsPrincipalRolesStack() {
308: if (runAsPrincipalRolesStack == null) {
309: runAsPrincipalRolesStack = Collections
310: .synchronizedList(new ArrayList());
311: }
312: return runAsPrincipalRolesStack;
313: }
314:
315: /**
316: * Gets the stack which manages the run-as principal
317: * @return the stack which manages the run-as principal
318: */
319: public synchronized List getRunAsPrincipalStack() {
320: if (runAsPrincipalStack == null) {
321: runAsPrincipalStack = Collections
322: .synchronizedList(new ArrayList());
323: }
324: return runAsPrincipalStack;
325: }
326:
327: /**
328: * Method toString
329: * @return String a string representation of the object
330: */
331: public String toString() {
332: String txt = "principal : name = " + principalName + "\n";
333: if (roles != null) {
334: for (int i = 0; i < roles.length; i++) {
335: txt += "role[" + i + "] = " + roles[i] + "\n";
336: }
337: }
338: if (runAsRoleStack != null) {
339: Iterator iRunas = runAsRoleStack.iterator();
340: int i = 0;
341: while (iRunas.hasNext()) {
342: txt += "runas[" + i + "] = " + ((String) iRunas.next())
343: + "\n";
344: }
345: }
346: return txt;
347: }
348:
349: /**
350: * @param runningRunAs bean is currently running with run-as enabled
351: * @return the principal name.
352: */
353: protected String getPrincipalName(boolean runningRunAs) {
354: String principal = null;
355: if (runningRunAs) {
356: principal = peekLastRunAsPrincipal();
357: } else {
358: principal = peekRunAsPrincipal();
359: }
360: if (principal != null) {
361: return principal;
362: } else {
363: return principalName;
364: }
365: }
366:
367: /**
368: * @return the principal Name.
369: */
370: public String getPrincipalName() {
371: return principalName;
372: }
373:
374: /**
375: * @return the roles.
376: */
377: public String[] getRoles() {
378: return roles;
379: }
380:
381: /**
382: * @author Florent Benoit Defines an implementation of the Principal object
383: */
384: class InternalPrincipal implements Principal {
385:
386: /**
387: * When building principal name, use right principal name. This is
388: * possible by knowing the bean making the call is in a run-as bean or
389: * not.
390: */
391: private boolean inRunAs = false;
392:
393: /**
394: * Constructor
395: * @param inRunAs caller is in run-as bean ?
396: */
397: public InternalPrincipal(boolean inRunAs) {
398: super ();
399: this .inRunAs = inRunAs;
400:
401: }
402:
403: /**
404: * @return name of this principal
405: */
406: public String getName() {
407: return getPrincipalName(inRunAs);
408: }
409:
410: /**
411: * @param o the object to compare
412: * @return true if the given principal has the same name than ours
413: */
414: public boolean equals(Object o) {
415: if (o instanceof Principal) {
416: return getPrincipalName(inRunAs).equals(
417: ((Principal) o).getName());
418: }
419: return false;
420: }
421:
422: /**
423: * Hashcode for this principal
424: * @return hashcode of the principal name
425: */
426: public int hashCode() {
427: return getPrincipalName(inRunAs).hashCode();
428: }
429:
430: /**
431: * Display this object
432: * @return string representing this object
433: */
434: public String toString() {
435: return "name = " + getPrincipalName(inRunAs);
436: }
437: }
438:
439: }
|