Return-Path: Delivered-To: apmail-geronimo-scm-archive@www.apache.org Received: (qmail 4614 invoked from network); 9 May 2007 15:28:04 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 9 May 2007 15:28:03 -0000 Received: (qmail 75606 invoked by uid 500); 9 May 2007 15:28:09 -0000 Delivered-To: apmail-geronimo-scm-archive@geronimo.apache.org Received: (qmail 75545 invoked by uid 500); 9 May 2007 15:28:09 -0000 Mailing-List: contact scm-help@geronimo.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: List-Post: Reply-To: dev@geronimo.apache.org List-Id: Delivered-To: mailing list scm@geronimo.apache.org Received: (qmail 75534 invoked by uid 99); 9 May 2007 15:28:09 -0000 Received: from herse.apache.org (HELO herse.apache.org) (140.211.11.133) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 09 May 2007 08:28:09 -0700 X-ASF-Spam-Status: No, hits=-99.5 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 09 May 2007 08:28:01 -0700 Received: by eris.apache.org (Postfix, from userid 65534) id 6382C1A9838; Wed, 9 May 2007 08:27:41 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r536566 - in /geronimo/server/trunk/modules: geronimo-tomcat6-builder/src/main/java/org/apache/geronimo/tomcat/deployment/ geronimo-tomcat6/src/main/java/org/apache/geronimo/tomcat/ geronimo-tomcat6/src/main/java/org/apache/geronimo/tomcat/... Date: Wed, 09 May 2007 15:27:41 -0000 To: scm@geronimo.apache.org From: pmcmahan@apache.org X-Mailer: svnmailer-1.1.0 Message-Id: <20070509152741.6382C1A9838@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: pmcmahan Date: Wed May 9 08:27:40 2007 New Revision: 536566 URL: http://svn.apache.org/viewvc?view=rev&rev=536566 Log: GERONIMO-3146 run-as support for servlets in the tomcat container Added: geronimo/server/trunk/modules/geronimo-tomcat6/src/main/java/org/apache/geronimo/tomcat/listener/RunAsInstanceListener.java Modified: geronimo/server/trunk/modules/geronimo-tomcat6-builder/src/main/java/org/apache/geronimo/tomcat/deployment/TomcatModuleBuilder.java geronimo/server/trunk/modules/geronimo-tomcat6/src/main/java/org/apache/geronimo/tomcat/GeronimoStandardContext.java geronimo/server/trunk/modules/geronimo-tomcat6/src/main/java/org/apache/geronimo/tomcat/util/SecurityHolder.java Modified: geronimo/server/trunk/modules/geronimo-tomcat6-builder/src/main/java/org/apache/geronimo/tomcat/deployment/TomcatModuleBuilder.java URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-tomcat6-builder/src/main/java/org/apache/geronimo/tomcat/deployment/TomcatModuleBuilder.java?view=diff&rev=536566&r1=536565&r2=536566 ============================================================================== --- geronimo/server/trunk/modules/geronimo-tomcat6-builder/src/main/java/org/apache/geronimo/tomcat/deployment/TomcatModuleBuilder.java (original) +++ geronimo/server/trunk/modules/geronimo-tomcat6-builder/src/main/java/org/apache/geronimo/tomcat/deployment/TomcatModuleBuilder.java Wed May 9 08:27:40 2007 @@ -417,6 +417,7 @@ SecurityHolder securityHolder = new SecurityHolder(); securityHolder.setSecurityRealm(tomcatWebApp.getSecurityRealmName().trim()); + securityHolder.setRoleDesignates(((SecurityConfiguration) earContext.getSecurityConfiguration()).getRoleDesignates()); /** * TODO - go back to commented version when possible. Modified: geronimo/server/trunk/modules/geronimo-tomcat6/src/main/java/org/apache/geronimo/tomcat/GeronimoStandardContext.java URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-tomcat6/src/main/java/org/apache/geronimo/tomcat/GeronimoStandardContext.java?view=diff&rev=536566&r1=536565&r2=536566 ============================================================================== --- geronimo/server/trunk/modules/geronimo-tomcat6/src/main/java/org/apache/geronimo/tomcat/GeronimoStandardContext.java (original) +++ geronimo/server/trunk/modules/geronimo-tomcat6/src/main/java/org/apache/geronimo/tomcat/GeronimoStandardContext.java Wed May 9 08:27:40 2007 @@ -50,6 +50,7 @@ import org.apache.geronimo.tomcat.interceptor.InstanceContextBeforeAfter; import org.apache.geronimo.tomcat.interceptor.PolicyContextBeforeAfter; import org.apache.geronimo.tomcat.interceptor.UserTransactionBeforeAfter; +import org.apache.geronimo.tomcat.listener.RunAsInstanceListener; import org.apache.geronimo.tomcat.util.SecurityHolder; import org.apache.geronimo.tomcat.valve.DefaultSubjectValve; import org.apache.geronimo.tomcat.valve.GeronimoBeforeAfterValve; @@ -70,6 +71,8 @@ private BeforeAfter beforeAfter = null; private int contextCount = 0; + + private Map roleDesignates = null; public void setContextProperties(TomcatContext ctx) throws DeploymentException { @@ -112,6 +115,10 @@ //Set a PolicyContext BeforeAfter SecurityHolder securityHolder = ctx.getSecurityHolder(); if (securityHolder != null) { + + // save the role designates for mapping servlets to their run-as roles + roleDesignates = securityHolder.getRoleDesignates(); + if (securityHolder.getPolicyContextID() != null) { PolicyContext.setContextID(securityHolder.getPolicyContextID()); @@ -173,6 +180,11 @@ //Set the Dispatch listener this.addInstanceListener("org.apache.geronimo.tomcat.listener.DispatchListener"); + + //Set the run-as listener. listeners must be added before start() is called + if (roleDesignates != null) { + this.addInstanceListener(RunAsInstanceListener.class.getName()); + } } public synchronized void start() throws LifecycleException { @@ -185,6 +197,17 @@ Valve defaultSubjectValve = new DefaultSubjectValve(defaultSubject); addValve(defaultSubjectValve); + + // if a servlet uses run-as then make sure role desgnates have been provided + if (hasRunAsServlet()) { + if (roleDesignates == null) { + throw new GeronimoSecurityException("web.xml or annotation specifies a run-as role but deployment descriptor does not provide a designated-run-as prinicpal for the role"); + } + } else { + // optimization + this.removeInstanceListener(RunAsInstanceListener.class.getName()); + } + } catch (IOException e) { if (e.getCause() instanceof LifecycleException) { throw (LifecycleException) e.getCause(); @@ -347,4 +370,32 @@ return contextCount; } + /** + * Determine if the context has at least one servlet that specifies a run-as role + * @return true if at least one servlet specifies a run-as role, false otherwise + */ + protected boolean hasRunAsServlet() { + for (Container servlet : findChildren()) { + if (servlet instanceof Wrapper) { + if (((Wrapper)servlet).getRunAs() != null) { + return true; + } + } + } + return false; + } + + /** + * Get the Subject for the designated Principal of a servlet's run as role + * @return Subject containing designated Prinicpal for the servlet's run-as role, if specified. otherwise null. + */ + public Subject getRoleDesignate(String servletName) { + Subject roleDesignate = null; + Wrapper servlet = (Wrapper)findChild(servletName); + if (servlet!=null && roleDesignates!=null) { + String roleName = servlet.getRunAs(); + roleDesignate = roleDesignates.get(roleName); + } + return roleDesignate; + } } Added: geronimo/server/trunk/modules/geronimo-tomcat6/src/main/java/org/apache/geronimo/tomcat/listener/RunAsInstanceListener.java URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-tomcat6/src/main/java/org/apache/geronimo/tomcat/listener/RunAsInstanceListener.java?view=auto&rev=536566 ============================================================================== --- geronimo/server/trunk/modules/geronimo-tomcat6/src/main/java/org/apache/geronimo/tomcat/listener/RunAsInstanceListener.java (added) +++ geronimo/server/trunk/modules/geronimo-tomcat6/src/main/java/org/apache/geronimo/tomcat/listener/RunAsInstanceListener.java Wed May 9 08:27:40 2007 @@ -0,0 +1,60 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.geronimo.tomcat.listener; + +import javax.security.auth.Subject; +import javax.servlet.Servlet; +import javax.servlet.ServletConfig; + +import org.apache.catalina.Container; +import org.apache.catalina.InstanceEvent; +import org.apache.catalina.InstanceListener; +import org.apache.geronimo.security.Callers; +import org.apache.geronimo.security.ContextManager; +import org.apache.geronimo.tomcat.GeronimoStandardContext; + +public class RunAsInstanceListener implements InstanceListener { + + private static final ThreadLocal threadLocal = new ThreadLocal(); + + public void instanceEvent(InstanceEvent event) { + + if (event.getType().equals(InstanceEvent.BEFORE_SERVICE_EVENT)) { + Container parent = event.getWrapper().getParent(); + if (parent instanceof GeronimoStandardContext) { + GeronimoStandardContext context = (GeronimoStandardContext)parent; + Servlet servlet = event.getServlet(); + ServletConfig config = servlet.getServletConfig(); + String servletName = config.getServletName(); + Subject runAsSubject = context.getRoleDesignate(servletName); + if (runAsSubject != null) { + Callers oldCallers = ContextManager.getCallers(); + ContextManager.registerSubject(runAsSubject); + ContextManager.pushNextCaller(runAsSubject); + threadLocal.set(oldCallers); + } + } + } + + else if (event.getType().equals(InstanceEvent.AFTER_SERVICE_EVENT)) { + Callers oldCallers = threadLocal.get(); + if (oldCallers!=null) { + ContextManager.popCallers(oldCallers); + } + } + } +} Modified: geronimo/server/trunk/modules/geronimo-tomcat6/src/main/java/org/apache/geronimo/tomcat/util/SecurityHolder.java URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-tomcat6/src/main/java/org/apache/geronimo/tomcat/util/SecurityHolder.java?view=diff&rev=536566&r1=536565&r2=536566 ============================================================================== --- geronimo/server/trunk/modules/geronimo-tomcat6/src/main/java/org/apache/geronimo/tomcat/util/SecurityHolder.java (original) +++ geronimo/server/trunk/modules/geronimo-tomcat6/src/main/java/org/apache/geronimo/tomcat/util/SecurityHolder.java Wed May 9 08:27:40 2007 @@ -18,6 +18,10 @@ import java.io.Serializable; import java.security.PermissionCollection; +import java.util.Map; + +import javax.security.auth.Subject; + import org.apache.geronimo.security.deploy.DefaultPrincipal; public class SecurityHolder implements Serializable @@ -31,6 +35,7 @@ private PermissionCollection excluded; private String securityRealm; private boolean security; + private Map roleDesignates; public SecurityHolder() { @@ -40,6 +45,7 @@ excluded = null; securityRealm = null; security = false; + roleDesignates = null; } public String getSecurityRealm() { @@ -96,6 +102,14 @@ public void setSecurity(boolean security) { this.security = security; + } + + public Map getRoleDesignates() { + return roleDesignates; + } + + public void setRoleDesignates(Map roleDesignates) { + this.roleDesignates = roleDesignates; } }