/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying FINErmation: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package org.jvnet.glassfish.comms.security.auth.impl;
import com.sun.enterprise.security.factory.SecurityManagerFactory;
import java.util.logging.Logger;
import com.sun.logging.LogDomains;
import java.util.ArrayList;
import com.sun.enterprise.deployment.runtime.web.Servlet;
import com.sun.enterprise.deployment.BundleDescriptor;
import com.sun.enterprise.deployment.Group;
import com.sun.enterprise.deployment.Role;
import com.sun.enterprise.deployment.interfaces.SecurityRoleMapper;
import com.sun.enterprise.deployment.interfaces.SecurityRoleMapperFactory;
import com.sun.enterprise.deployment.interfaces.SecurityRoleMapperFactoryMgr;
import com.sun.enterprise.deployment.runtime.common.PrincipalNameDescriptor;
import com.sun.enterprise.deployment.runtime.common.SecurityRoleMapping;
import com.sun.enterprise.deployment.runtime.web.SunWebApp;
import com.sun.enterprise.security.AppservAccessController;
import com.sun.enterprise.security.SecurityContext;
import com.sun.web.security.WebPrincipal;
import java.security.Principal;
import java.security.PrivilegedExceptionAction;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import javax.security.auth.Subject;
import javax.security.jacc.PolicyConfigurationFactory;
import javax.security.jacc.PolicyContext;
import javax.security.jacc.PolicyContextException;
import org.jvnet.glassfish.comms.deployment.backend.SipBundleDescriptor;
/**
*
* @author K.venugopal@sun.com
*/
public class SipSecurityManager extends SecurityManagerFactory {
// stores the context ids to appnames for standalone web apps
static private Map<String, ArrayList<String>> CONTEXT_IDS =
new HashMap<String, ArrayList<String>>();
static private Map<String, Map<String, SipSecurityManager>> SECURITY_MANAGERS =
new HashMap<String, Map<String, SipSecurityManager>>();
public static Logger logger =
Logger.getLogger(LogDomains.SECURITY_LOGGER);
private SipBundleDescriptor sbd = null;
private String CONTEXT_ID = null;
protected static PolicyConfigurationFactory pcf = null;
private static SecurityRoleMapperFactory factory =
SecurityRoleMapperFactoryMgr.getFactory();
// Create a WebSecurityObject
private SipSecurityManager(SipBundleDescriptor sbd) throws PolicyContextException {
this.sbd = sbd;
this.CONTEXT_ID = getContextID(sbd);
String appname = sbd.getApplication().getRegistrationName();
factory.setAppNameForContext(appname, CONTEXT_ID);
createRoleMapper(CONTEXT_ID);
//initialise(appname);
}
public String getContextID() {
return CONTEXT_ID;
}
public boolean inService() {
boolean inService = false;
try {
inService = getPolicyFactory().inService(CONTEXT_ID);
} catch (PolicyContextException ex) {
logger.log(Level.SEVERE, null, ex);
}
return inService;
}
public static String getContextID(SipBundleDescriptor sbd) {
String cid = null;
if (sbd != null) {
String moduleId = sbd.getUniqueFriendlyId();
cid = sbd.getApplication().getRegistrationName() +
"/sip_" + sbd.getUniqueFriendlyId();
}
return cid;
}
public void createRoleMapper(String name) {
SunWebApp sunSipDesc = sbd.getSipApplication().getSunSipDescriptor();
SecurityRoleMapping[] srmList = sunSipDesc.getSecurityRoleMapping();
//SecurityRoleMapping[] srmList = ((WebBundleDescriptor) descriptor).getSunDescriptor().getSecurityRoleMapping();
// SecurityRoleMapperFactory factory = SecurityRoleMapperFactoryMgr.getFactory();
//super.getDescriptor().getApplication().getRoleMapper().getName();
if (srmList == null) {
return;
}
for (int si = 0; si < srmList.length; si++) {
SecurityRoleMapping srm = srmList[si];
Role role = new Role(srm.getRoleName());
SecurityRoleMapper rm = factory.getRoleMapper(name);
if (rm != null) {
List<PrincipalNameDescriptor> principals = srm.getPrincipalNames();
for (int i = 0; i < principals.size(); i++) {
rm.assignRole(principals.get(i).getPrincipal(), role,
sbd);
}
List<String> groups = srm.getGroupNames();
for (int i = 0; i < groups.size(); i++) {
rm.assignRole(new Group(groups.get(i)), role, sbd);
}
}
}
}
public static void setPolicyContext(final String ctxID) throws Throwable {
String old = PolicyContext.getContextID();
try {
AppservAccessController.doPrivileged(new PrivilegedExceptionAction() {
public java.lang.Object run() throws Exception {
PolicyContext.setContextID(ctxID);
return null;
}
});
} catch (java.security.PrivilegedActionException pae) {
Throwable cause = pae.getCause();
//log exception.
throw cause;
}
}
public static Subject getCurrentSubject() {
SecurityContext secCtx = SecurityContext.getCurrent();
Subject subject = secCtx.getSubject();
return subject;
}
public static void setSecurityContext(Object obj) {
if (obj == null) {
SecurityContext.setCurrent((SecurityContext) obj);
return;
}
if (obj instanceof SecurityContext) {
SecurityContext.setCurrent((SecurityContext) obj);
} else if (obj instanceof WebPrincipal) {
SecurityContext sc = ((WebPrincipal) obj).getSecurityContext();
SecurityContext.setCurrent(sc);
}
}
public static Object getSecurityContext(Principal pc) {
if (pc instanceof WebPrincipal) {
SecurityContext sc = ((WebPrincipal) pc).getSecurityContext();
return sc;
}
return null;
}
public static Object getSecurityContext() {
return SecurityContext.getCurrent();
}
public static Subject getSubject(Principal principal) {
SecurityContext secContext = null;
if (principal != null) {
if (principal instanceof WebPrincipal) {
WebPrincipal wp = (WebPrincipal) principal;
secContext = wp.getSecurityContext();
} else {
secContext = new SecurityContext(principal.getName(), null);
}
}
if (secContext == null) {
secContext = SecurityContext.getDefaultSecurityContext();
}
return secContext.getSubject();
}
public Map<String, String> readRunAs(BundleDescriptor descriptor, Map<String, String> srMap) {
Map runAs = new HashMap<String, String>();
if (descriptor instanceof SipBundleDescriptor) {
SipBundleDescriptor sbd = (SipBundleDescriptor) descriptor;
SunWebApp sunSipDesc = sbd.getSipApplication().getSunSipDescriptor();
Servlet[] servlets = sunSipDesc.getServlet();
if (servlets != null) {
for (int i = 0; i < servlets.length; i++) {
Servlet servlet = servlets[i];
String prinName = servlet.getPrincipalName();
String sn = servlet.getServletName();
runAs.put(sn, prinName);
}
} else {
SecurityRoleMapping[] srmList = sunSipDesc.getSecurityRoleMapping();
//SecurityRoleMapping[] srmList = ((WebBundleDescriptor) descriptor).getSunDescriptor().getSecurityRoleMapping();
// SecurityRoleMapperFactory factory = SecurityRoleMapperFactoryMgr.getFactory();
//super.getDescriptor().getApplication().getRoleMapper().getName();
if (srmList == null) {
return runAs;
}
Iterator<String> itr = srMap.keySet().iterator();
while (itr.hasNext()) {
String servletName = itr.next();
if (!runAs.containsKey(servletName)) {
for (int si = 0; si < srmList.length; si++) {
SecurityRoleMapping srm = srmList[si];
String role = srm.getRoleName();
List<PrincipalNameDescriptor> principals = srm.getPrincipalNames();
if ((srMap.containsValue(role) && principals.size() > 0)) {
Principal principal = principals.get(0).getPrincipal();
runAs.put(servletName, principal.getName());
break;
}
}
}
}
}
}
return runAs;
}
private static synchronized PolicyConfigurationFactory getPolicyFactory()
throws PolicyContextException {
if (pcf == null) {
try {
pcf = PolicyConfigurationFactory.getPolicyConfigurationFactory();
} catch (ClassNotFoundException cnfe) {
logger.severe("jaccfactory.notfound");
throw new PolicyContextException(cnfe);
} catch (PolicyContextException pce) {
logger.severe("jaccfactory.notfound");
throw pce;
}
}
return pcf;
}
public void destroy() throws PolicyContextException {
factory.removeAppNameForContext(CONTEXT_ID);
getPolicyFactory().getPolicyConfiguration(CONTEXT_ID, true);
SipSecurityManager sm = SipSecurityManager.getManager(CONTEXT_ID, null, true);
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "SIPSecurityManager: destroyed" + sm);
printCache();
}
}
public static <T> SipSecurityManager getManager(String ctxId, String name,
boolean remove) {
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "getManager beforeprintcache" + remove);
printCache();
}
SipSecurityManager secManager = getManager(SECURITY_MANAGERS, ctxId, name, remove);
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "getManager after printcache" + remove);
printCache();
}
return secManager;
}
public static <T> ArrayList<SipSecurityManager> getManagers(String ctxId, boolean remove) {
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "getManagers before printcache" + remove);
printCache();
}
ArrayList<SipSecurityManager> list = getManagers(SECURITY_MANAGERS, ctxId, remove);
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "getManagers after printcache" + remove);
printCache();
}
return list;
}
public static <T> ArrayList<SipSecurityManager> getManagersForApp(String appName, boolean remove) {
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "getManagersForApp before printcache" + remove);
printCache();
}
ArrayList<SipSecurityManager> list = getManagersForApp(SECURITY_MANAGERS, CONTEXT_IDS, appName,
remove);
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "getManagersForApp after printcache" + remove);
printCache();
}
return list;
}
public static <T> String[] getContextsForApp(String appName, boolean remove) {
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "getContextsForApp before printcache" + remove);
printCache();
}
String[] ctlist = getContextsForApp(CONTEXT_IDS, appName, remove);
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "getContextsForApp after printcache" + remove);
printCache();
}
return ctlist;
}
public static <T> void addManagerToApp(String ctxId, String name,
String appName, SipSecurityManager manager) {
addManagerToApp(SECURITY_MANAGERS, CONTEXT_IDS, ctxId, name,
appName, manager);
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "addManagerToApp after printcache" + manager);
printCache();
}
}
public static SipSecurityManager createManager(SipBundleDescriptor sbd,
boolean register) {
String ctxId = SipSecurityManager.getContextID(sbd);
SipSecurityManager manager = null;
if (register) {
manager = getManager(ctxId, null, false);
}
if (manager == null || !register) {
try {
manager = new SipSecurityManager(sbd);
if (register) {
String appName = sbd.getApplication().getRegistrationName();
addManagerToApp(ctxId, null, appName, manager);
}
} catch (javax.security.jacc.PolicyContextException e) {
logger.log(Level.FINE, "[SIP-Security] FATAL Exception. Unable to create WebSecurityManager: " + e.getMessage());
throw new RuntimeException(e);
}
}
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "SIPSecurityManager called with" + register);
logger.log(Level.FINE, "SIPSecurityManager " + manager + "returned");
}
return manager;
}
static void printCache() {
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "CONTEXT_IDS :" + CONTEXT_IDS.toString());
logger.log(Level.FINE, "SECURITY_MANAGERS :" + SECURITY_MANAGERS.toString());
}
}
}