001: /**
002: *
003: * Licensed to the Apache Software Foundation (ASF) under one or more
004: * contributor license agreements. See the NOTICE file distributed with
005: * this work for additional information regarding copyright ownership.
006: * The ASF licenses this file to You under the Apache License, Version 2.0
007: * (the "License"); you may not use this file except in compliance with
008: * the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */package org.apache.openejb.tomcat.catalina;
018:
019: import org.apache.catalina.Realm;
020: import org.apache.catalina.Service;
021: import org.apache.catalina.Engine;
022: import org.apache.catalina.ServerFactory;
023: import org.apache.catalina.Server;
024: import org.apache.openejb.core.security.AbstractSecurityService;
025: import org.apache.openejb.core.CoreDeploymentInfo;
026:
027: import javax.security.auth.Subject;
028: import javax.security.auth.login.LoginException;
029: import java.security.Principal;
030: import java.util.HashSet;
031: import java.util.LinkedHashSet;
032: import java.util.Set;
033: import java.util.LinkedList;
034: import java.util.UUID;
035:
036: public class TomcatSecurityService extends AbstractSecurityService {
037: static protected final ThreadLocal<LinkedList<Subject>> runAsStack = new ThreadLocal<LinkedList<Subject>>() {
038: protected LinkedList<Subject> initialValue() {
039: return new LinkedList<Subject>();
040: }
041: };
042:
043: private Realm defaultRealm;
044:
045: public TomcatSecurityService() {
046: Server server = ServerFactory.getServer();
047: for (Service service : server.findServices()) {
048: if (service.getContainer() instanceof Engine) {
049: Engine engine = (Engine) service.getContainer();
050: if (engine.getRealm() != null) {
051: defaultRealm = engine.getRealm();
052: break;
053: }
054: }
055: }
056: }
057:
058: public UUID login(String realmName, String username, String password)
059: throws LoginException {
060: if (defaultRealm == null) {
061: throw new LoginException("No Tomcat realm available");
062: }
063:
064: Principal principal = defaultRealm.authenticate(username,
065: password);
066: Subject subject = createSubject(defaultRealm, principal);
067: UUID token = registerSubject(subject);
068: return token;
069: }
070:
071: private Subject createSubject(Realm realm, Principal principal) {
072: TomcatUser tomcatUser = new TomcatUser(realm, principal);
073:
074: HashSet<Principal> principals = new HashSet<Principal>();
075: principals.add(tomcatUser);
076:
077: Subject subject = new Subject(true, principals, new HashSet(),
078: new HashSet());
079: return subject;
080: }
081:
082: public Set<String> getLogicalRoles(Principal[] principals,
083: Set<String> logicalRoles) {
084: LinkedHashSet<String> roles = new LinkedHashSet<String>(
085: logicalRoles.size());
086: for (String logicalRole : logicalRoles) {
087: for (Principal principal : principals) {
088: if (principal instanceof TomcatUser) {
089: TomcatUser user = (TomcatUser) principal;
090: if (user.getRealm().hasRole(
091: user.getTomcatPrincipal(), logicalRole)) {
092: roles.add(logicalRole);
093: break;
094: }
095: } else if (principal instanceof RunAsRole) {
096: RunAsRole runAsRole = (RunAsRole) principal;
097: String name = runAsRole.getName();
098: if (logicalRole.equals(name)) {
099: roles.add(logicalRole);
100: }
101: }
102: }
103: }
104: return roles;
105: }
106:
107: public Object enterWebApp(Realm realm, Principal principal,
108: String runAs) {
109: Identity newIdentity = null;
110: if (principal != null) {
111: Subject newSubject = createSubject(realm, principal);
112: newIdentity = new Identity(newSubject, null);
113: }
114:
115: Identity oldIdentity = clientIdentity.get();
116: WebAppState webAppState = new WebAppState(oldIdentity,
117: runAs != null);
118: clientIdentity.set(newIdentity);
119:
120: if (runAs != null) {
121: Subject runAsSubject = createRunAsSubject(runAs);
122: runAsStack.get().addFirst(runAsSubject);
123: }
124:
125: return webAppState;
126: }
127:
128: public void exitWebApp(Object state) {
129: if (state instanceof WebAppState) {
130: WebAppState webAppState = (WebAppState) state;
131: clientIdentity.set(webAppState.oldIdentity);
132: if (webAppState.hadRunAs) {
133: runAsStack.get().removeFirst();
134: }
135: }
136: }
137:
138: protected Subject getRunAsSubject(
139: CoreDeploymentInfo callingDeploymentInfo) {
140: Subject runAsSubject = super
141: .getRunAsSubject(callingDeploymentInfo);
142: if (runAsSubject != null)
143: return runAsSubject;
144:
145: LinkedList<Subject> stack = runAsStack.get();
146: if (stack.isEmpty()) {
147: return null;
148: }
149: return stack.getFirst();
150: }
151:
152: protected Subject createRunAsSubject(String role) {
153: if (role == null)
154: return null;
155:
156: RunAsRole runAsRole = new RunAsRole(role);
157:
158: HashSet<Principal> principals = new HashSet<Principal>();
159: principals.add(runAsRole);
160:
161: return new Subject(true, principals, new HashSet(),
162: new HashSet());
163: }
164:
165: protected static class TomcatUser implements Principal {
166: private final Realm realm;
167: private final Principal tomcatPrincipal;
168:
169: public TomcatUser(Realm realm, Principal tomcatPrincipal) {
170: if (realm == null)
171: throw new NullPointerException("realm is null");
172: if (tomcatPrincipal == null)
173: throw new NullPointerException(
174: "tomcatPrincipal is null");
175: this .realm = realm;
176: this .tomcatPrincipal = tomcatPrincipal;
177: }
178:
179: public Realm getRealm() {
180: return realm;
181: }
182:
183: public Principal getTomcatPrincipal() {
184: return tomcatPrincipal;
185: }
186:
187: public String getName() {
188: return tomcatPrincipal.getName();
189: }
190:
191: public String toString() {
192: return "[TomcatUser: " + tomcatPrincipal + "]";
193: }
194:
195: public boolean equals(Object o) {
196: if (this == o)
197: return true;
198: if (o == null || getClass() != o.getClass())
199: return false;
200:
201: TomcatUser that = (TomcatUser) o;
202:
203: return realm.equals(that.realm)
204: && tomcatPrincipal.equals(that.tomcatPrincipal);
205: }
206:
207: public int hashCode() {
208: int result;
209: result = realm.hashCode();
210: result = 31 * result + tomcatPrincipal.hashCode();
211: return result;
212: }
213: }
214:
215: protected static class RunAsRole implements Principal {
216: private final String name;
217:
218: public RunAsRole(String name) {
219: if (name == null)
220: throw new NullPointerException("name is null");
221: this .name = name;
222: }
223:
224: public String getName() {
225: return name;
226: }
227:
228: public String toString() {
229: return "[RunAsRole: " + name + "]";
230: }
231:
232: public boolean equals(Object o) {
233: if (this == o)
234: return true;
235: if (o == null || getClass() != o.getClass())
236: return false;
237:
238: RunAsRole runAsRole = (RunAsRole) o;
239:
240: return name.equals(runAsRole.name);
241: }
242:
243: public int hashCode() {
244: return name.hashCode();
245: }
246: }
247:
248: private static class WebAppState {
249: private final Identity oldIdentity;
250: private final boolean hadRunAs;
251:
252: public WebAppState(Identity oldIdentity, boolean hadRunAs) {
253: this.oldIdentity = oldIdentity;
254: this.hadRunAs = hadRunAs;
255: }
256: }
257: }
|