All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.enterprise.iiop.security.SecurityMechanismSelector Maven / Gradle / Ivy

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2010 Oracle and/or its affiliates. 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_1_1.html
 * or packager/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 packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [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 com.sun.enterprise.iiop.security;

import com.sun.corba.ee.org.omg.CSI.ITTAnonymous;
import com.sun.corba.ee.org.omg.CSI.ITTPrincipalName;
import com.sun.corba.ee.org.omg.CSI.ITTX509CertChain;
import com.sun.corba.ee.org.omg.CSI.ITTDistinguishedName;
import com.sun.enterprise.common.iiop.security.AnonCredential;
import com.sun.enterprise.common.iiop.security.GSSUPName;
import com.sun.enterprise.common.iiop.security.SecurityContext;

import java.net.Socket;
import java.util.Set;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;

import java.security.PrivilegedAction;
import java.security.AccessController;
import javax.security.auth.Subject;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
// GSS Related Functionality

import com.sun.enterprise.deployment.EjbDescriptor;
import com.sun.enterprise.deployment.EjbIORConfigurationDescriptor;
import org.omg.CORBA.ORB;
import com.sun.enterprise.security.auth.login.common.PasswordCredential;
import com.sun.enterprise.security.auth.login.common.X509CertificateCredential;

import com.sun.enterprise.util.Utility;
import com.sun.corba.ee.spi.ior.IOR;
import com.sun.corba.ee.spi.ior.iiop.IIOPAddress;
import com.sun.corba.ee.spi.ior.iiop.IIOPProfileTemplate;
import com.sun.corba.ee.spi.transport.SocketInfo;
import com.sun.corba.ee.org.omg.CSIIOP.*;
import org.ietf.jgss.Oid;
import java.util.Enumeration;
import sun.security.x509.X500Name;
import com.sun.enterprise.security.SecurityServicesUtil;
import com.sun.enterprise.security.auth.login.LoginContextDriver;
import com.sun.enterprise.security.auth.login.common.LoginException;
import com.sun.enterprise.security.auth.realm.Realm;
import com.sun.enterprise.security.common.ClientSecurityContext;
import com.sun.enterprise.security.common.SecurityConstants;
import com.sun.enterprise.security.ssl.SSLUtils;
import com.sun.enterprise.util.LocalStringManagerImpl;

import java.util.logging.*;
import com.sun.logging.*;
import java.util.Arrays;
import org.glassfish.api.admin.ProcessEnvironment;
import org.glassfish.api.admin.ProcessEnvironment.ProcessType;
import org.glassfish.api.invocation.ComponentInvocation;
import org.glassfish.enterprise.iiop.api.GlassFishORBHelper;
import org.glassfish.enterprise.iiop.api.ProtocolManager;

import org.jvnet.hk2.annotations.Scoped;
import org.jvnet.hk2.annotations.Service;
import org.jvnet.hk2.component.Habitat;
import org.glassfish.api.invocation.InvocationManager ;
import org.jvnet.hk2.annotations.Inject;
import org.jvnet.hk2.component.PostConstruct;
import org.jvnet.hk2.component.Singleton;


/** 
 * This class is responsible for making various decisions for selecting
 * security information to be sent in the IIOP message based on target
 * configuration and client policies.
 * Note: This class can be called concurrently by multiple client threads.
 * However, none of its methods need to be synchronized because the methods
 * either do not modify state or are idempotent.
 * 
 * @author Nithya Subramanian

 */

@Service
@Scoped(Singleton.class)
public final class SecurityMechanismSelector implements PostConstruct {

    private static final java.util.logging.Logger _logger =
       LogDomains.getLogger(SecurityMechanismSelector.class, LogDomains.SECURITY_LOGGER);

    public static final String CLIENT_CONNECTION_CONTEXT = "ClientConnContext";
    //public static final String SERVER_CONNECTION_CONTEXT = "ServerConnContext";

    private  Set corbaIORDescSet = null;
    private  boolean sslRequired = false;

    // List of hosts trusted by the client for sending passwords to.
    // Also, list of hosts trusted by the server for accepting propagated
    // identities.
    //private static String[] serverTrustedHosts = null;

    private static final LocalStringManagerImpl localStrings =
        new LocalStringManagerImpl(SecServerRequestInterceptor.class);

    // A reference to POAProtocolMgr will be obtained dynamically
    // and set if not null. So set it to null here.
    private  ProtocolManager protocolMgr = null;
    private SSLUtils sslUtils = null;
    private GlassFishORBHelper orbHelper;

    //private CompoundSecMech mechanism = null;
    private ORB orb = null;
    private CSIV2TaggedComponentInfo ctc = null;
    private InvocationManager invMgr = null;
    @Inject
    private Habitat habitat;
    @Inject
    private ProcessEnvironment processEnv;
    /**
     * Read the client and server preferences from the config files.
     */
    public SecurityMechanismSelector() {
    }
    
    public void postConstruct() {
        try {
            orbHelper = Lookups.getGlassFishORBHelper(habitat);
            sslUtils = habitat.getComponent(SSLUtils.class);
            invMgr = habitat.getComponent(InvocationManager.class);
	    // Initialize client security config
	    String s = 
		(orbHelper.getCSIv2Props()).getProperty(GlassFishORBHelper.ORB_SSL_CLIENT_REQUIRED);
	    if ( s != null && s.equals("true") ) {
		sslRequired = true;
	    }

	    // initialize corbaIORDescSet with security config for CORBA objects
	    corbaIORDescSet = new HashSet();
	    EjbIORConfigurationDescriptor iorDesc = 
					    new EjbIORConfigurationDescriptor();
	    EjbIORConfigurationDescriptor iorDesc2 = 
					    new EjbIORConfigurationDescriptor();
	    String serverSslReqd =
                    (orbHelper.getCSIv2Props()).getProperty(GlassFishORBHelper.ORB_SSL_SERVER_REQUIRED);
	    if ( serverSslReqd != null && serverSslReqd.equals("true") ) {
		iorDesc.setIntegrity(EjbIORConfigurationDescriptor.REQUIRED);
		iorDesc.setConfidentiality(
					EjbIORConfigurationDescriptor.REQUIRED);
		iorDesc2.setIntegrity(EjbIORConfigurationDescriptor.REQUIRED);
		iorDesc2.setConfidentiality(
					EjbIORConfigurationDescriptor.REQUIRED);
	    }
	    String clientAuthReq = 
		(orbHelper.getCSIv2Props()).getProperty(GlassFishORBHelper.ORB_CLIENT_AUTH_REQUIRED);
	    if ( clientAuthReq != null && clientAuthReq.equals("true") ) {
		// Need auth either by SSL or username-password.
		// This sets SSL clientauth to required.
		iorDesc.setEstablishTrustInClient(
					EjbIORConfigurationDescriptor.REQUIRED);
		// This sets username-password auth to required.
		iorDesc2.setAuthMethodRequired(true);
		getCorbaIORDescSet().add(iorDesc2);
	    }
	    getCorbaIORDescSet().add(iorDesc);

        } catch(Exception e) {
            _logger.log(Level.SEVERE,"iiop.Exception",e);
        }        
    }

    public ConnectionContext getClientConnectionContext() {
        Hashtable h = ConnectionExecutionContext.getContext();
        ConnectionContext scc = 
            (ConnectionContext) h.get(CLIENT_CONNECTION_CONTEXT);
        return scc;
    }

    public void setClientConnectionContext(ConnectionContext scc) {
        Hashtable h = ConnectionExecutionContext.getContext();
        h.put(CLIENT_CONNECTION_CONTEXT, scc);
    }

    /**
     * This method determines if SSL should be used to connect to the
     * target based on client and target policies. It will return null if
     * SSL should not be used or an SocketInfo containing the SSL port
     * if SSL should be used.
     */
    public SocketInfo getSSLPort(IOR ior, ConnectionContext ctx) 
    {
        SocketInfo info = null;
        CompoundSecMech mechanism = null;
        try {
             mechanism = selectSecurityMechanism(ior);
        } catch(SecurityMechanismException sme) {
            throw new RuntimeException(sme.getMessage());
        }
        ctx.setIOR(ior);
        ctx.setMechanism(mechanism);

        TLS_SEC_TRANS ssl = null;
        if ( mechanism != null ) {
            ssl = getCtc().getSSLInformation(mechanism);
        }

        if (ssl == null) {
            if (isSslRequired()) {
                // Attempt to create SSL connection to host, ORBInitialPort
                IIOPProfileTemplate templ = (IIOPProfileTemplate)
                    ior.getProfile().getTaggedProfileTemplate();
                IIOPAddress addr = templ.getPrimaryAddress();
                info = IORToSocketInfoImpl.createSocketInfo(
		        "SecurityMechanismSelector1",
                        "SSL", addr.getHost(), orbHelper.getORBPort(orbHelper.getORB()));
                return info;
            } else {
                return null;
            }
        }

        int targetRequires = ssl.target_requires;
        int targetSupports = ssl.target_supports;
        
        /*
         * If target requires any of Integrity, Confidentiality or 
         * EstablishTrustInClient, then SSL is used.
         */
        if (isSet(targetRequires, Integrity.value) || 
                isSet(targetRequires, Confidentiality.value) ||
                isSet(targetRequires, EstablishTrustInClient.value)) {
            if (_logger.isLoggable(Level.FINE)) {
                 _logger.log(Level.FINE, "Target requires SSL");
            }
            ctx.setSSLUsed(true);
            String type = "SSL";
            if(isSet(targetRequires, EstablishTrustInClient.value)) {
                type = "SSL_MUTUALAUTH";
                ctx.setSSLClientAuthenticationOccurred(true);
            } 
            short sslport = ssl.addresses[0].port;
            int ssl_port = Utility.shortToInt(sslport);
            String host_name = ssl.addresses[0].host_name;
            
            info = IORToSocketInfoImpl.createSocketInfo(
		    "SecurityMechanismSelector2",
                    type, host_name, ssl_port);

            return info;
        } else if (isSet(targetSupports, Integrity.value) || 
                    isSet(targetSupports, Confidentiality.value) ||
                    isSet(targetSupports, EstablishTrustInClient.value)) {
            if (_logger.isLoggable(Level.FINE)) {
                _logger.log(Level.FINE, "Target supports SSL");
            }

            if ( isSslRequired() ) {
                if (_logger.isLoggable(Level.FINE)) {
                    _logger.log(Level.FINE, "Client is configured to require SSL for the target");
                }

                ctx.setSSLUsed(true);
                short sslport = ssl.addresses[0].port;
                String host_name = ssl.addresses[0].host_name;
                int ssl_port = Utility.shortToInt(sslport);
                info = IORToSocketInfoImpl.createSocketInfo(
		        "SecurityMechanismSelector3",
                        "SSL", host_name, ssl_port);
                return info;
            } else {
                return null;
            }
        } else if ( isSslRequired() ) {
	    throw new RuntimeException("SSL required by client but not supported by server.");
	} else {
	    return null;
	}
    }

    /*
    public String[] getServerTrustedHosts() {
        return serverTrustedHosts;
    }
    
    public void setServerTrustedHosts(String[] val) {
        this.serverTrustedHosts = val;
    }
    */
    
    
    public ORB getOrb() {
        return orb;
    }
    
    public void setOrb(ORB val) {
        this.orb = val;
    }
    
    public synchronized CSIV2TaggedComponentInfo getCtc() {
        if (ctc == null) {
           this.ctc = new CSIV2TaggedComponentInfo(orbHelper.getORB(), habitat); 
        }
        return ctc;
    }
    
    
    public java.util.List getSSLPorts(IOR ior, ConnectionContext ctx) 
    {
        CompoundSecMech mechanism = null;
        try {
            mechanism = selectSecurityMechanism(ior);
        } catch(SecurityMechanismException sme) {
            throw new RuntimeException(sme.getMessage());
        }
        ctx.setIOR(ior);
        ctx.setMechanism(mechanism);

        TLS_SEC_TRANS ssl = null;
        if ( mechanism != null ) {
            ssl = getCtc().getSSLInformation(mechanism);
        }

        if (ssl == null) {
            if (isSslRequired()) {
                // Attempt to create SSL connection to host, ORBInitialPort
                IIOPProfileTemplate templ = (IIOPProfileTemplate)
                    ior.getProfile().getTaggedProfileTemplate();
                IIOPAddress addr = templ.getPrimaryAddress();
                SocketInfo info = IORToSocketInfoImpl.createSocketInfo(
		        "SecurityMechanismSelector1",
                        "SSL", addr.getHost(), orbHelper.getORBPort(orbHelper.getORB()));
                //SocketInfo[] sInfos = new SocketInfo[]{info};
                List sInfos = new ArrayList();
                sInfos.add(info);
                return sInfos;
            } else {
                return null;
            }
        }

        int targetRequires = ssl.target_requires;
        int targetSupports = ssl.target_supports;
        
        /*
         * If target requires any of Integrity, Confidentiality or 
         * EstablishTrustInClient, then SSL is used.
         */
        if (isSet(targetRequires, Integrity.value) || 
                isSet(targetRequires, Confidentiality.value) ||
                isSet(targetRequires, EstablishTrustInClient.value)) {
            if (_logger.isLoggable(Level.FINE)) {
                 _logger.log(Level.FINE, "Target requires SSL");
            }
            ctx.setSSLUsed(true);
            String type = "SSL";
            if(isSet(targetRequires, EstablishTrustInClient.value)) {
                type = "SSL_MUTUALAUTH";
                ctx.setSSLClientAuthenticationOccurred(true);
            } 
            //SocketInfo[] socketInfos = new SocketInfo[ssl.addresses.size];
            List socketInfos = new ArrayList();
            for(int addressIndex =0; addressIndex < ssl.addresses.length; addressIndex++){
                short sslport = ssl.addresses[addressIndex].port;
                int ssl_port = Utility.shortToInt(sslport);
                String host_name = ssl.addresses[addressIndex].host_name;
            
                SocketInfo sInfo = IORToSocketInfoImpl.createSocketInfo(
		    "SecurityMechanismSelector2",
                    type, host_name, ssl_port);
                socketInfos.add(sInfo);
            }
            return socketInfos;
        } else if (isSet(targetSupports, Integrity.value) || 
                    isSet(targetSupports, Confidentiality.value) ||
                    isSet(targetSupports, EstablishTrustInClient.value)) {
            if (_logger.isLoggable(Level.FINE)) {
                _logger.log(Level.FINE, "Target supports SSL");
            }

            if ( isSslRequired() ) {
                if (_logger.isLoggable(Level.FINE)) {
                    _logger.log(Level.FINE, "Client is configured to require SSL for the target");
                }

                ctx.setSSLUsed(true);
                //SocketInfo[] socketInfos = new SocketInfo[ssl.addresses.size];
                List socketInfos = new ArrayList();
                for(int addressIndex =0; addressIndex < ssl.addresses.length; addressIndex++){
                    short sslport = ssl.addresses[addressIndex].port;
                    int ssl_port = Utility.shortToInt(sslport);
                    String host_name = ssl.addresses[addressIndex].host_name;

                    SocketInfo sInfo = IORToSocketInfoImpl.createSocketInfo(
                        "SecurityMechanismSelector3",
                        "SSL", host_name, ssl_port);
                    socketInfos.add(sInfo);
                }
                return socketInfos;                
            } else {
                return null;
            }
        } else if ( isSslRequired() ) {
	    throw new RuntimeException("SSL required by client but not supported by server.");
	} else {
	    return null;
	}
    }


    /**
     * Select the security context to be used by the CSIV2 layer
     * based on whether the current component is an application 
     * client or a web/EJB component.
     */

    public SecurityContext selectSecurityContext(IOR ior)
        throws InvalidIdentityTokenException, 
            InvalidMechanismException, SecurityMechanismException
    {
        SecurityContext context = null;   
	ConnectionContext cc = new ConnectionContext();
        //print CSIv2 mechanism definition in IOR
        if (traceIORs()) {
            _logger.info("\nCSIv2 Mechanism List:" +
                    getSecurityMechanismString(ctc,ior));
	}

        getSSLPort(ior, cc);
        setClientConnectionContext(cc); 

        CompoundSecMech mechanism = cc.getMechanism();
        if(mechanism == null) {
            return null;
        }
        boolean sslUsed = cc.getSSLUsed();
        boolean clientAuthOccurred = cc.getSSLClientAuthenticationOccurred();

        // Standalone client
        if (isNotServerOrACC()) {
            context = getSecurityContextForAppClient(
                    null, sslUsed, clientAuthOccurred, mechanism);
            return context;
        }

        if (_logger.isLoggable(Level.FINE)) {
            _logger.log(Level.FINE, "SSL used:" + sslUsed + " SSL Mutual auth:" + clientAuthOccurred);
        }
        ComponentInvocation ci = null;
        /*// BEGIN IASRI# 4646060
        ci = invMgr.getCurrentInvocation();
        if (ci == null) {
            // END IASRI# 4646060
            return null;
        }
        Object obj = ci.getContainerContext();*/
        if(isACC()) {
            context = getSecurityContextForAppClient(ci, sslUsed, clientAuthOccurred, mechanism);
        } else {
            context = getSecurityContextForWebOrEJB(ci, sslUsed, clientAuthOccurred, mechanism);
        }
        return context;
    }

    /**
     * Create the security context to be used by the CSIV2 layer
     * to marshal in the service context of the IIOP message from an appclient
     * or standalone client.
     * @return the security context.
     */
    public SecurityContext getSecurityContextForAppClient(
                                        ComponentInvocation ci, 
                                        boolean sslUsed,
                                        boolean clientAuthOccurred,
                                        CompoundSecMech mechanism) 
        throws InvalidMechanismException, InvalidIdentityTokenException,
                                            SecurityMechanismException {

        return sendUsernameAndPassword(ci, sslUsed, clientAuthOccurred, mechanism);
    }

    /**
     * Create the security context to be used by the CSIV2 layer
     * to marshal in the service context of the IIOP message from an web
     * component or EJB invoking another EJB.
     * @return the security context.
     */
    public SecurityContext getSecurityContextForWebOrEJB(
                        ComponentInvocation ci, boolean sslUsed,
                        boolean clientAuthOccurred,
                        CompoundSecMech mechanism) 
        throws InvalidMechanismException, InvalidIdentityTokenException, 
                            SecurityMechanismException {

        SecurityContext ctx = null;
        if(!sslUsed) {
	    ctx = propagateIdentity(false, ci, mechanism);
	} else {
	    ctx = propagateIdentity(clientAuthOccurred, ci, mechanism);
	}
	return ctx;
    }

    Object getSSLSocketInfo(Object ior) {
         ConnectionContext ctx = new ConnectionContext();
         List socketInfo = getSSLPorts((com.sun.corba.ee.spi.ior.IOR)ior, ctx);
         setClientConnectionContext(ctx);
         return socketInfo;
    }

    private boolean isMechanismSupported(SAS_ContextSec sas){
        byte[][] mechanisms = sas.supported_naming_mechanisms;
        byte[] mechSupported = GSSUtils.getMechanism();

	if (mechSupported == null) {
	    return false;
	}
        if (mechanisms == null) {
            return false;
        }

        for (int i = 0; i < mechanisms.length; i++) {
            if (Arrays.equals(mechSupported, mechanisms[i])) {
                return true;
            }
        }
        return false;
    }
    
    public boolean isIdentityTypeSupported(SAS_ContextSec sas){
        int ident_token = sas.supported_identity_types;
        // the identity token matches atleast one of the types we support
        int value = ident_token &
            CSIV2TaggedComponentInfo.SUPPORTED_IDENTITY_TOKEN_TYPES;
        if (value != 0)
            return true;
        else 
            return false;
    }

    /**
     * Get the security context to send username and password in the
     * service context.
     * @param whether username/password will be sent over plain IIOP or
     *        over IIOP/SSL.
     * @return the security context.
     * @exception SecurityMechanismException if there was an error.
     */
    private SecurityContext sendUsernameAndPassword(ComponentInvocation ci,
						    boolean sslUsed,
						    boolean clientAuthOccurred,
                                                    CompoundSecMech mechanism) 
                throws SecurityMechanismException {
        SecurityContext ctx = null;
        if(mechanism == null) {
            return null;
        }
        AS_ContextSec asContext = mechanism.as_context_mech;
        if( isSet(asContext.target_requires, EstablishTrustInClient.value)
            || ( isSet(mechanism.target_requires, EstablishTrustInClient.value)
		 && !clientAuthOccurred ) ) {

            ctx = getUsernameAndPassword(ci, mechanism);

            if (_logger.isLoggable(Level.FINE)) {
                _logger.log(Level.FINE, "Sending Username/Password");
            }
        } else {
            return null;
        }
        return ctx;
    }

    /**
     * Get the security context to propagate principal/distinguished name
     * in the service context.
     * @param clientAuth whether SSL client authentication has happened.
     * @return the security context.
     * @exception SecurityMechanismException if there was an error.
     */
    private SecurityContext propagateIdentity(boolean clientAuth,
                                              ComponentInvocation ci,
                                              CompoundSecMech mechanism) 
        throws InvalidIdentityTokenException, InvalidMechanismException, SecurityMechanismException {
            
        SecurityContext ctx = null;
        if(mechanism == null) {
            return null;
        }
        AS_ContextSec asContext = mechanism.as_context_mech;
        SAS_ContextSec sasContext = mechanism.sas_context_mech;
        if (_logger.isLoggable(Level.FINE)) {
            _logger.log(Level.FINE, "SAS CONTEXT's target_requires=" + sasContext.target_requires);
            _logger.log(Level.FINE, "SAS CONTEXT's target_supports=" + sasContext.target_supports);
        }

        if(isSet(asContext.target_requires, EstablishTrustInClient.value)) {
            ctx = getUsernameAndPassword(ci, mechanism);
            if (ctx.authcls == null){ // run as mode cannot send password
                String errmsg =
localStrings.getLocalString("securitymechansimselector.runas_cannot_propagate_username_password",
"Cannot propagate username/password required by target when using run as identity");

            _logger.log(Level.SEVERE,"iiop.runas_error",errmsg);
            throw new SecurityMechanismException (errmsg);
            }
        } else if(isSet(sasContext.target_supports, IdentityAssertion.value) ||
                  isSet(sasContext.target_requires, IdentityAssertion.value)) {
            // called from the client side. thus before getting the identity. check the
            // mechanisms and the identity token supported
            if(!isIdentityTypeSupported(sasContext)){
                String errmsg =
                    localStrings.getLocalString("securitymechanismselector.invalid_identity_type",
                                                "The given identity token is unsupported.");
                throw new InvalidIdentityTokenException(errmsg);
            }
            if (sasContext.target_supports == IdentityAssertion.value){
                if(!isMechanismSupported(sasContext)){
                    String errmsg =
                        localStrings.getLocalString("securitymechanismselector.invalid_mechanism",
                                                    "The given mechanism type is unsupported.");
                _logger.log(Level.SEVERE,"iiop.unsupported_type_error",errmsg);
                throw new InvalidMechanismException(errmsg);
                }
            }

            // propagate principal/certificate/distinguished name
            ctx = getIdentity();
        } else if(isSet(asContext.target_supports, 
                        EstablishTrustInClient.value)) {
            if (clientAuth) {   // client auth done we can send password
                ctx = getUsernameAndPassword(ci, mechanism);
                if (ctx.authcls == null) {
                    return null; // runas mode dont have username/password
                                //  dont really need to send it too
                }
            } else { // not sending anything for unauthenticated client
                return null;
            }
        } else{
            return null;        //  will never come here
        }
        return ctx;
    }


    /**
     * Return whether the server is trusted or not based on configuration
     * information.
     * @return true if the server is trusted.
     */
    /*
    private boolean isServerTrusted() {
        String star = "*";
        // first check if "*" in trusted - then why bother
        // doing all the processing . We trust everything
        // System.out.println (" In server trusted ??"); 
        for (int i = 0; i < serverTrustedHosts.length; i++){
            if (serverTrustedHosts[i].length () == 1) {
                if (serverTrustedHosts[i].equals (star))
                    return true;
            }
        }
        ConnectionContext scc = getClientConnectionContext ();
        if (scc != null){
            Socket skt = scc.getSocket ();
            InetAddress adr = skt.getInetAddress ();
            // System.out.println (" Calling isServerTrusted");
            // System.out.println (" addres "+ adr.toString ()); 
            return isDomainInTrustedList (adr, serverTrustedHosts);
        } 
        return false;

    }
    */

    /**
     * Checks if a given domain is trusted.
     * e.g. domain = 123.203.1.1 is an IP address
     * trusted list = *.com, *.eng
     * should say that the given domain is trusted.
     * @param the InetAddress of the domain to be checked for
     * @param the array of trusted domains
     * @return true - if the given domain is trusted
     */
    /*
    private boolean isDomainInTrustedList (InetAddress inetAddress,
                                           String[] trusted)
        throws SecurityException 
    {
        boolean isTrusted = false;
        String domain = null; 
        String star = "*";
        String dot = ".";
        // lookup and get domain name
        try{
            domain = inetAddress.getHostName ();
        } catch (Exception e){
            _logger.log(Level.SEVERE,"iiop.domain_lookup_failed",inetAddress.getHostAddress ());
            return false;
        }  
        if (_logger.isLoggable(Level.FINE)) {
            _logger.log(Level.FINE, " Verifying if domain address ="+
                 inetAddress.toString () + " is in the Trusted list ");
            _logger.log(Level.FINE, " the domain name is = "+ domain);
        }

        String[] domainTok = TypeUtil.stringToArray (domain, dot);
        // now lets go through the list of trusted domains
        // one at a time
        for (int i=0; i< trusted.length; i++){
            // String to compare with
            String[] toksList = 
                TypeUtil.stringToArray (trusted[i], dot);
            // cannot compare *.eng to *.eng.sun
            if (toksList.length != domainTok.length){
                isTrusted = false;
                continue;
            } else{
                for (int j=toksList.length-1; j>=0 ; j--){
                    // compare com in *.eng.com and abc.eng.com
                    // compare in the reverse order
                    if (toksList[j].equals (domainTok[j])){
                        isTrusted = true;
                    } else {
                        // compare * in abc.*.com and abc.eng.com
                        if (toksList[j].equals (star)){
                            isTrusted = true;
                        }
                        else {
                            // get out and try the next domain
                            isTrusted = false;
                            break;
                        }
                    }
                }
                // We went through one domain and found a match 
                // no need to compare further
                if (isTrusted) 
                    return isTrusted;
            }
        }
        return isTrusted;
    }
    */


    /**
     * Get the username and password either from the JAAS subject or
     * from thread local storage. For appclients if login has'nt happened
     * this method would trigger login and popup a user interface to
     * gather authentication information.
     * @return the security context.
     */
    private SecurityContext getUsernameAndPassword(ComponentInvocation ci, CompoundSecMech mechanism) 
            throws SecurityMechanismException {
        try {
            Subject s = null;
            //if(ci == null) {
            if (isNotServerOrACC()) {
		// Standalone client ... Changed the security context 
		// from which to fetch the subject
                ClientSecurityContext sc = 
                    ClientSecurityContext.getCurrent();
                if(sc == null) {
                    return null;
                }
                s = sc.getSubject();
                if (_logger.isLoggable(Level.FINE)) {
                    _logger.log(Level.FINE, "SUBJECT:" + s);
                }
            } else {
                //Object obj = ci.getContainerContext();
                //if(obj instanceof AppContainer) {
                 if (isACC()) {
		    // get the subject
                    ClientSecurityContext sc = 
                        ClientSecurityContext.getCurrent();
                    if(sc == null) {
			s = LoginContextDriver.doClientLogin(
                                SecurityConstants.USERNAME_PASSWORD,
                                SecurityServicesUtil.getInstance().getCallbackHandler());
                    } else {
                        s = sc.getSubject();
                    }
                } else {
                    // web/ejb
                    s = getSubjectFromSecurityCurrent();
                    // TODO check if username/password is available
                    // if not throw exception
                }
            }
            SecurityContext ctx = new SecurityContext();
            final Subject sub = s;
            ctx.subject = s;
            // determining if run-as has been used
            Set privateCredSet = 
                AccessController.doPrivileged(new PrivilegedAction() {

                public Set run() {
                    return sub.getPrivateCredentials();
                }
            });
            if (privateCredSet.isEmpty()) { // this is runas case dont set
                if (_logger.isLoggable(Level.FINE)) {
                    _logger.log(Level.FINE, "no private credential run as mode");
                }
                ctx.authcls = null; // the auth class
                ctx.identcls = GSSUPName.class;
                
            } else{
                /** lookup the realm name that is required by the server
                 * and set it up in the PasswordCredential class.
                 */
                AS_ContextSec asContext = mechanism.as_context_mech;
                final byte[] target_name = asContext.target_name;
                byte[] _realm = null;
                if (target_name == null || target_name.length == 0) {
                    _realm = Realm.getDefaultRealm().getBytes();
                } else {
                    _realm = GSSUtils.importName(GSSUtils.GSSUP_MECH_OID, target_name);
                }
                final String realm_name = new String(_realm);
                final Iterator it = privateCredSet.iterator();
                for(;it.hasNext();){
                    AccessController.doPrivileged(new PrivilegedAction(){
                        public java.lang.Object run(){
                            PasswordCredential pc = (PasswordCredential) it.next();
                            pc.setRealm(realm_name);
                            return null;
                        }
                    });
                }
                ctx.authcls = PasswordCredential.class;
            }
            return ctx;
        } catch(LoginException le){
            throw le;
        } catch(Exception e) {
            _logger.log(Level.SEVERE,"iiop.user_password_exception",e);
            return null;
        }
    }

    /**
     * Get the principal/distinguished name from thread local storage.
     * @return the security context.
     */
    private SecurityContext getIdentity() 
            throws SecurityMechanismException {
        if (_logger.isLoggable(Level.FINE)) {
            _logger.log(Level.FINE, "Getting PRINCIPAL/DN from TLS");
        }

        SecurityContext ctx = new SecurityContext();
        final SecurityContext sCtx = ctx;
	// get stuff from the SecurityContext class
        com.sun.enterprise.security.SecurityContext scontext = 
            com.sun.enterprise.security.SecurityContext.getCurrent();
        if ((scontext == null) ||
             scontext.didServerGenerateCredentials()){  
            
            // a default guest/guest123 was created
            sCtx.identcls = AnonCredential.class;
            
            AccessController.doPrivileged(new PrivilegedAction() {
                public java.lang.Object run(){
                    // remove all the public and private credentials 
                    Subject sub = new Subject();
                    sCtx.subject = sub; 
                    sCtx.subject.getPublicCredentials().add(new AnonCredential());
                    return null;
                }
            });
            return sCtx;
        }

        Subject s = getSubjectFromSecurityCurrent();
        ctx.subject = s;

        // Figure out the credential class
        final Subject sub = s;
        Set credSet = 
            AccessController.doPrivileged(new PrivilegedAction() {
                public Set run() {
                    return sub.getPrivateCredentials(PasswordCredential.class);
                }
            });
        if(credSet.size() == 1) {
            ctx.identcls = GSSUPName.class;
            final Set cs = credSet;
            Subject subj = AccessController.doPrivileged(new
            PrivilegedAction() {
                public Subject run() {
                    Subject ss = new Subject();
                    Iterator iter = cs.iterator();
                    PasswordCredential pc = (PasswordCredential) iter.next();
                    GSSUPName gssname = new GSSUPName(pc.getUser(), pc.getRealm());
                    ss.getPublicCredentials().add(gssname);
                    return ss;
                }
            });
            ctx.subject = subj;
            return ctx;
        }

        credSet = s.getPublicCredentials();
        if(credSet.size() != 1) {
            _logger.log(Level.SEVERE,"iiop.principal_error");
            return null;
        } else {
            Iterator credIter = credSet.iterator();
            if(credIter.hasNext()) {
                Object o = credIter.next();
                if(o instanceof GSSUPName) {
                    ctx.identcls = GSSUPName.class;
                } else if(o instanceof X500Name) {
                    ctx.identcls = X500Name.class;
                } else {
                    ctx.identcls = X509CertificateCredential.class;
                }
            } else {
        	_logger.log(Level.SEVERE,"iiop.credential_error");
                return null;
            }
        }
        return ctx;
    }

    private Subject getSubjectFromSecurityCurrent() 
            throws SecurityMechanismException {
        com.sun.enterprise.security.SecurityContext sc = null;
        sc = com.sun.enterprise.security.SecurityContext.getCurrent();
        if(sc == null) {
            if(_logger.isLoggable(Level.FINE)) {
        	_logger.log(Level.FINE," SETTING GUEST ---");
            }
            sc = com.sun.enterprise.security.SecurityContext.init();
        }
        if(sc == null) {
            throw new SecurityMechanismException("Could not find " +
                        " security information");
        }
        Subject s = sc.getSubject();
        if(s == null) {
            throw new SecurityMechanismException("Could not find " +
                " subject information in the security context.");
        }
        if (_logger.isLoggable(Level.FINE)) {
            _logger.log(Level.FINE, "Subject in security current:" + s);
        }
        return s;
    }

    public CompoundSecMech selectSecurityMechanism(IOR ior) 
            throws SecurityMechanismException {
        CompoundSecMech[] mechList = getCtc().getSecurityMechanisms(ior);
        CompoundSecMech mech = selectSecurityMechanism(mechList);
        return mech;
    }

    /**
     * Select the security mechanism from the list of compound security
     * mechanisms.
     */
    private CompoundSecMech selectSecurityMechanism(
                CompoundSecMech[] mechList) throws SecurityMechanismException {
        // We should choose from list of compound security mechanisms
        // which are in decreasing preference order. Right now we select
        // the first one.
        if(mechList == null || mechList.length == 0) {
            return null;
        }
        CompoundSecMech mech = null;
        for(int i = 0; i < mechList.length; i++) {
            mech = mechList[i];
            boolean useMech = useMechanism(mech);
            if(useMech) {
                return mech;
            }
        }
        throw new SecurityMechanismException("Cannot use any of the " +
            " target's supported mechanisms");
    }

    private boolean useMechanism(CompoundSecMech mech) {
        boolean val = true;
        TLS_SEC_TRANS tls = getCtc().getSSLInformation(mech);

        if (mech.sas_context_mech.supported_naming_mechanisms.length > 0
                && !isMechanismSupported(mech.sas_context_mech)) {
            return false;
        } else if (mech.as_context_mech.client_authentication_mech.length > 0
                && !isMechanismSupportedAS(mech.as_context_mech)) {
            return false;
        }

        if(tls == null) {
            return true;
        }
        int targetRequires = tls.target_requires;
        if(isSet(targetRequires, EstablishTrustInClient.value)) {
            if(! sslUtils.isKeyAvailable()) {
                val = false;
            }
        }
        return val;
    }
    
    private boolean isMechanismSupportedAS(AS_ContextSec as) {
        byte[] mechanism = as.client_authentication_mech;
        byte[] mechSupported = GSSUtils.getMechanism();

        if (mechSupported == null) {
            return false;
        }
        if (mechanism == null) {
            return false;
        }

        if (Arrays.equals(mechanism,mechSupported)) {
            return true;
        }

        return false;
    }

    // Returns the target_name from PasswordCredential in Subject subj
    // subj must contain a single instance of PasswordCredential.

    private byte[] getTargetName(Subject subj)
    {
  
        byte[] tgt_name = {} ;

        final Subject sub = subj;
        final Set credset = 
            AccessController.doPrivileged(new PrivilegedAction() {
                public Set run() {
                    return sub.getPrivateCredentials(PasswordCredential.class);
                }
            });
        if(credset.size() == 1) {
            tgt_name = AccessController.doPrivileged(new PrivilegedAction() {
                public byte[] run() {
                    Iterator iter = credset.iterator();
                    PasswordCredential pc = (PasswordCredential) iter.next();
                    return pc.getTargetName();
                }
            });
        }
        return tgt_name;
    }

    private boolean evaluate_client_conformance_ssl(
                        EjbIORConfigurationDescriptor iordesc,
                        boolean  ssl_used,
                        X509Certificate[] certchain)
    {
      try {
        if(_logger.isLoggable(Level.FINE)) {
	    _logger.log(Level.FINE,
			"SecurityMechanismSelector.evaluate_client_conformance_ssl->:");
	}
	
        boolean ssl_required  = false;
        boolean ssl_supported = false;
        int ssl_target_requires = 0;
        int ssl_target_supports = 0;

        /*************************************************************************
         * Conformance Matrix:
         *
         * |---------------|---------------------|---------------------|------------|
         * | SSLClientAuth | targetrequires.ETIC | targetSupports.ETIC | Conformant |
         * |---------------|---------------------|---------------------|------------|
         * |     Yes       |          0          |      1              |    Yes     |
         * |     Yes       |          0          |      0              |    No      |
         * |     Yes       |          1          |      X              |    Yes     |
         * |     No        |          0          |      X              |    Yes     |
         * |     No        |          1          |      X              |    No      |
         * |---------------|---------------------|---------------------|------------|
         *
         *************************************************************************/

        // gather the configured SSL security policies.
 
        ssl_target_requires = this.getCtc().getTargetRequires(iordesc);
        ssl_target_supports = this.getCtc().getTargetSupports(iordesc);

        if (    isSet(ssl_target_requires, Integrity.value)
             || isSet(ssl_target_requires, Confidentiality.value)
             || isSet(ssl_target_requires, EstablishTrustInClient.value))
            ssl_required = true;
        else
            ssl_required = false;

        if ( ssl_target_supports != 0)
            ssl_supported = true;
        else
            ssl_supported = false;

        /* Check for conformance for using SSL usage.
         * 
         * a. if SSL was used, then either the target must require or support
         *    SSL. In the latter case, SSL is used because of client policy.
         *
         * b. if SSL was not used, then the target must not require it either.
         *    The target may or may not support SSL (it is irrelevant).
         */
        if(_logger.isLoggable(Level.FINE)) {
	    _logger.log(Level.FINE,
			"SecurityMechanismSelector.evaluate_client_conformance_ssl:"
			+ " " + isSet(ssl_target_requires, Integrity.value)
			+ " " + isSet(ssl_target_requires, Confidentiality.value)
			+ " " + isSet(ssl_target_requires, EstablishTrustInClient.value)
			+ " " + ssl_required
			+ " " + ssl_supported
			+ " " + ssl_used);
	}

        if (ssl_used) {
            if (! (ssl_required || ssl_supported))
                return false;  // security mechanism did not match
        } else {
            if (ssl_required)
                return false;  // security mechanism did not match
        }

        /* Check for conformance for SSL client authentication.
         *
         * a. if client performed SSL client authentication, then the target
         *    must either require or support SSL client authentication. If 
         *    the target only supports, SSL client authentication is used
         *    because of client security policy.
         *
         * b. if SSL client authentication was not used, then the target must
         *    not require SSL client authentcation either. The target may or may 
         *    not support SSL client authentication (it is irrelevant).
         */

        if(_logger.isLoggable(Level.FINE)) {
	    _logger.log(Level.FINE,
			"SecurityMechanismSelector.evaluate_client_conformance_ssl:"
			+ " " + certchain
			+ " " + isSet(ssl_target_requires, EstablishTrustInClient.value)
			+ " " + isSet(ssl_target_supports, EstablishTrustInClient.value));
	}

        if (certchain != null) {
            if ( ! ( isSet(ssl_target_requires, EstablishTrustInClient.value)
                     || isSet(ssl_target_supports, EstablishTrustInClient.value)))
            return false; // security mechanism did not match
        } else {
            if (isSet(ssl_target_requires, EstablishTrustInClient.value))
                return false; // security mechanism did not match
        }

        if(_logger.isLoggable(Level.FINE)) {
	    _logger.log(Level.FINE,
			"SecurityMechanismSelector.evaluate_client_conformance_ssl: true");
	}

        return true ; // mechanism matched
      } finally {
	  if(_logger.isLoggable(Level.FINE)) {
	      _logger.log(Level.FINE,
			  "SecurityMechanismSelector.evaluate_client_conformance_ssl<-:");
	  }
      }
    }

   
   /* Evaluates a client's conformance to a security policies
    * at the client authentication layer.
    *
    * returns true if conformant ; else returns false
    */
    private boolean evaluate_client_conformance_ascontext(
                        SecurityContext ctx,
                        EjbIORConfigurationDescriptor iordesc,
                        String realmName)
    {

        boolean client_authenticated = false;

        // get requirements and supports at the client authentication layer
        AS_ContextSec ascontext = null;
        try {
            ascontext = this.getCtc().createASContextSec(iordesc, realmName);
        } catch (Exception e) {
            _logger.log(Level.SEVERE, "iiop.createcontextsec_exception",e);

            return false;
        }
   
        // ascontext should never be null - perhaps an exception should be raised.
        // for now return false;
        if (ascontext == null)
            return false;
            
        /*************************************************************************
         * Conformance Matrix:
         *
         * |------------|---------------------|---------------------|------------|
         * | ClientAuth | targetrequires.ETIC | targetSupports.ETIC | Conformant |
         * |------------|---------------------|---------------------|------------|
         * |     Yes    |          0          |      1              |    Yes     |
         * |     Yes    |          0          |      0              |    No      |
         * |     Yes    |          1          |      X              |    Yes     |
         * |     No     |          0          |      X              |    Yes     |
         * |     No     |          1          |      X              |    No      |
         * |------------|---------------------|---------------------|------------|
         *
         * Abbreviations: ETIC - EstablishTrusInClient
         * 
         *************************************************************************/

        if  ( (ctx != null) && (ctx.authcls != null) &&  (ctx.subject != null))
            client_authenticated = true;
        else
            client_authenticated = false;

        if (client_authenticated) {
            if ( ! ( isSet(ascontext.target_requires, EstablishTrustInClient.value)
                     || isSet(ascontext.target_supports, EstablishTrustInClient.value))){
            return false; // non conforming client
            }
            // match the target_name from client with the target_name in policy 

            byte [] client_tgtname = getTargetName(ctx.subject);

            if (ascontext.target_name.length != client_tgtname.length){
                return false; // mechanism did not match.
            }            
            for (int i=0; i < ascontext.target_name.length ; i ++)
                if (ascontext.target_name[i] != client_tgtname[i]){
                    return false; // mechanism did not match
                }
        } else { 
            if ( isSet(ascontext.target_requires, EstablishTrustInClient.value)){
                return false;  // no mechanism match.
            }
        }
        return true;
    }

   /* Evaluates a client's conformance to a security policy
    * at the sas context layer. The security policy
    * is derived from the EjbIORConfigurationDescriptor.
    *
    * returns true if conformant ; else returns false
    */
    private boolean evaluate_client_conformance_sascontext(
                        SecurityContext ctx,
                        EjbIORConfigurationDescriptor iordesc)
    {

        boolean caller_propagated = false;

        // get requirements and supports at the sas context layer
        SAS_ContextSec sascontext = null;
        try {
            sascontext = this.getCtc().createSASContextSec(iordesc);
        } catch (Exception e) {
            _logger.log(Level.SEVERE,"iiop.createcontextsec_exception",e);
            return false;
        }
   
        if (sascontext == null)  // this should never be null
            return false;
            
        if  ( (ctx != null) && (ctx.identcls != null) &&  (ctx.subject != null))
            caller_propagated = true;
        else
            caller_propagated = false;

        if (caller_propagated) {
            if ( ! isSet(sascontext.target_supports, IdentityAssertion.value))
                return false; // target does not support IdentityAssertion

            /* There is no need further checking here since SecServerRequestInterceptor
             * code filters out the following:
             * a. IdentityAssertions of types other than those required by level 0 
             *    (for e.g. IdentityExtension)
             * b. unsupported identity types.
             * 
             * The checks are done in SecServerRequestInterceptor rather than here
             * to minimize code changes.
             */
            return true;
        }
        return true; //  either caller was not propagated or mechanism matched.
    }
       
                                                    

    /**
     * Evaluates a client's conformance to the security policies configured
     * on the target.
     * Returns true if conformant to the security policies
     * otherwise return false.
     *
     * Conformance checking is done as follows:
     * First, the object_id is mapped to the set of EjbIORConfigurationDescriptor.
     * Each EjbIORConfigurationDescriptor corresponds to a single CompoundSecMechanism
     * of the CSIv2 spec. A client is considered to be conformant if a
CompoundSecMechanism
     * consistent with the client's actions is found i.e. transport_mech,
as_context_mech
     * and sas_context_mech must all be consistent.
     * 
     */
    private boolean evaluate_client_conformance(SecurityContext   ctx,
                                                byte[]            object_id,
                                                boolean           ssl_used,
                                                X509Certificate[] certchain)
    {
        // Obtain the IOR configuration descriptors for the Ejb using
        // the object_id within the SecurityContext field.

        // if object_id is null then nothing to evaluate. This is a sanity
        // check - for the object_id should never be null.
        
        if (object_id == null)
            return true;

        if (protocolMgr == null)
            protocolMgr = orbHelper.getProtocolManager();

        // Check to make sure protocolMgr is not null. 
        // This could happen during server initialization or if this call
        // is on a callback object in the client VM. 
        if (protocolMgr == null)
            return true;

        EjbDescriptor ejbDesc = protocolMgr.getEjbDescriptor(object_id);

        Set iorDescSet = null;
        if (ejbDesc != null) {
	    iorDescSet = ejbDesc.getIORConfigurationDescriptors();
	}
	else {
	    // Probably a non-EJB CORBA object.
	    // Create a temporary EjbIORConfigurationDescriptor.
	    iorDescSet = getCorbaIORDescSet();
	}

	if(_logger.isLoggable(Level.FINE)) {
	    _logger.log(Level.FINE,
			"SecurityMechanismSelector.evaluate_client_conformance: iorDescSet: " + iorDescSet);
	}

        /* if there are no IORConfigurationDescriptors configured, then
         * no security policy is configured. So consider the client 
         * to be conformant.
         */
        if (iorDescSet.isEmpty())
            return true;

        // go through each EjbIORConfigurationDescriptor trying to find
        // a find a CompoundSecMechanism that matches client's actions.
        boolean checkSkipped = false;
        for (Iterator itr = iorDescSet.iterator(); itr.hasNext();) {
            EjbIORConfigurationDescriptor iorDesc = 
                (EjbIORConfigurationDescriptor) itr.next();
            if(skip_client_conformance(iorDesc)){
		if(_logger.isLoggable(Level.FINE)) {
		    _logger.log(Level.FINE,
				"SecurityMechanismSelector.evaluate_client_conformance: skip_client_conformance");
		}
                checkSkipped = true;
                continue;
            }
            if (! evaluate_client_conformance_ssl(iorDesc, ssl_used, certchain)){
		if(_logger.isLoggable(Level.FINE)) {
		    _logger.log(Level.FINE,
				"SecurityMechanismSelector.evaluate_client_conformance: evaluate_client_conformance_ssl");
		}
                checkSkipped = false;
                continue;
            }
            String realmName = "default";
            if(ejbDesc != null && ejbDesc.getApplication() != null) {
                realmName = ejbDesc.getApplication().getRealm();
            }
            if(realmName == null) {
                realmName = iorDesc.getRealmName();
            }
            if (realmName == null) {
                realmName = "default";
            }
            if ( ! evaluate_client_conformance_ascontext(ctx, iorDesc ,realmName)){
		if(_logger.isLoggable(Level.FINE)) {
		    _logger.log(Level.FINE,
				"SecurityMechanismSelector.evaluate_client_conformance: evaluate_client_conformance_ascontext");
		}
                checkSkipped = false;
                continue;
            }
            if  ( ! evaluate_client_conformance_sascontext(ctx, iorDesc)){
		if(_logger.isLoggable(Level.FINE)) {
		    _logger.log(Level.FINE,
				"SecurityMechanismSelector.evaluate_client_conformance: evaluate_client_conformance_sascontext");
		}
               checkSkipped = false;
               continue;
            }
            return true;  // security policy matched.
        }
        if(checkSkipped)
            return true;
        return false; // No matching security policy found
    }     
     
     /** if ejb requires no security - then skip checking the client-conformance
     */    
    private boolean skip_client_conformance (EjbIORConfigurationDescriptor ior){
        String none = EjbIORConfigurationDescriptor.NONE;
	// sanity check
	if(ior == null){
	   return false;
	}
        // SSL is required and/or supported either
        if(!none.equalsIgnoreCase(ior.getIntegrity())){
            return false;
        }
        if(!none.equalsIgnoreCase(ior.getConfidentiality())){
            return false;
        }
        if(!none.equalsIgnoreCase(ior.getEstablishTrustInClient())){
            return false;
        }
        // Username password is required
        if(ior.isAuthMethodRequired()){
            return false;
        }
        // caller propagation is supported
        if(!none.equalsIgnoreCase(ior.getCallerPropagation())){
            return false;
        }
        return true;
    }
    /**
     * Called by the target to interpret client credentials after validation. 
     */
    public SecurityContext evaluateTrust(SecurityContext ctx, byte[] object_id, Socket socket)
        throws SecurityMechanismException
    {
        SecurityContext ssc = null;

        // ssl_used is true if SSL was used.        
        boolean ssl_used        = false ;

        // X509 Certificicate chain is non null if client has authenticated at
        // the SSL level.

        X509Certificate[] certChain = null ;

        // First gather all the information and then check the 
        // conformance of the client to the security policies.
        // If the test for client conformance passes, then set the
        // security context.
        if ((socket != null) && (socket instanceof SSLSocket)) {
            ssl_used = true; // SSL was used
            // checkif there is a transport principal
            SSLSocket sslSock = (SSLSocket) socket;
            SSLSession sslSession = sslSock.getSession();
            try {
                certChain = (X509Certificate[]) sslSession.getPeerCertificates();
            } catch (Exception e) {
                if (_logger.isLoggable(Level.FINE)) {
                    _logger.log(Level.FINE, "iiop.cannot_get_peercert", e);
                }
            }
        }
        

        // For a local invocation - we don't need to check the security
        // policies. The following condition guarantees the call is local
        // and thus bypassing policy checks.
        
        // XXX: Workaround for non-null connection object ri for local invocation.
        // if (socket == null && ctx == null)
        Long ClientID = ConnectionExecutionContext.readClientThreadID();
        if (ClientID != null && ClientID == Thread.currentThread().getId() && ctx == null)
            return null;

        if ( evaluate_client_conformance(ctx, object_id, ssl_used, certChain) 
                                                                     == false) {
            String msg = "Trust evaluation failed because ";
            msg = msg + "client does not conform to configured security policies";
            throw new SecurityMechanismException(msg);
        }            

        if ( ctx == null ) {
            if ( socket == null || !ssl_used || certChain == null )  {
                // Transport info is null and security context is null.
                // No need to set the anonymous credential here,
                // it will get set if any security operations 
                // (e.g. getCallerPrincipal) are done.
                // Note: if the target object is not an EJB, 
                // no security ctx is needed.
                return null;
            }  else {
                // Set the transport principal in subject and
                // return the X500Name class
                ssc = new SecurityContext();
                X500Name x500Name = (X500Name) certChain[0].getSubjectDN();
                ssc.subject = new Subject();
                ssc.subject.getPublicCredentials().add(x500Name);
                ssc.identcls = X500Name.class;
                ssc.authcls = null;
                return ssc;
            }
        } else {
            ssc = ctx;
        }

        Class authCls = ctx.authcls;
        Class identCls = ctx.identcls;
        
        ssc.authcls = null;
        ssc.identcls = null;

        if (identCls != null)
            ssc.identcls = identCls;
        else if (authCls != null)
            ssc.authcls = authCls;
        else
            ssc.identcls = AnonCredential.class;

        return ssc;
    }

    private static boolean isSet(int val1, int val2) {
        if((val1 & val2) == val2) {
            return true;
        }
        return false;
    }

    private Set getCorbaIORDescSet() {
        return corbaIORDescSet;
    }

    public boolean isSslRequired() {
        return sslRequired;
    }

    private boolean isNotServerOrACC() {
        return processEnv.getProcessType().equals(ProcessType.Other);
    }
    
    private boolean isACC() {
        return processEnv.getProcessType().equals(ProcessType.ACC);
    }

    // property controls IOR tracing by clients]

    private static final String traceIORsProperty =
         "com.sun.enterprise.iiop.security.traceIORS";

    private static final boolean _traceIORs = Boolean.getBoolean
            (traceIORsProperty);

    private static final Hashtable assocOptions;

    static {
        assocOptions = new Hashtable();
    	assocOptions.put(Integer.valueOf(Integrity.value),"Integrity");
	assocOptions.put(Integer.valueOf(Confidentiality.value),"Confidentiality");
	assocOptions.put(Integer.valueOf(EstablishTrustInTarget.value),"EstablishTrustInTarget");
	assocOptions.put(Integer.valueOf(EstablishTrustInClient.value),"EstablishTrustInClient");
	assocOptions.put(Integer.valueOf(IdentityAssertion.value),"IdentityAssertion");
	assocOptions.put(Integer.valueOf(DelegationByClient.value),"DelegationByClient");
    }

    private static final Hashtable identityTokenTypes;

    static {
        identityTokenTypes = new Hashtable();
    	identityTokenTypes.put(Integer.valueOf(ITTAnonymous.value),"Anonymous");
	identityTokenTypes.put(Integer.valueOf(ITTPrincipalName.value),"PrincipalName");
	identityTokenTypes.put(Integer.valueOf(ITTX509CertChain.value),"X509CertChain");
	identityTokenTypes.put(Integer.valueOf(ITTDistinguishedName.value),"DistinguishedName");
    }

    public static boolean traceIORs() {
       return _traceIORs;
    }

    public String getSecurityMechanismString(CSIV2TaggedComponentInfo tCI,
            IOR ior) {
        // need to print out top port value and hosr ior.getProfile().isLocal();
        String typeId = ior.getTypeId();
        CompoundSecMech[] mechList = tCI.getSecurityMechanisms(ior);
        return getSecurityMechanismString(tCI, mechList, typeId);
    }

    public static String getSecurityMechanismString(CSIV2TaggedComponentInfo tCI,
           CompoundSecMech[] list, String name) {
        StringBuffer b = new StringBuffer();
        b.append("\ntypeId: " + name == null ? "null" : name);
        try {
            for (int i = 0; list != null && i < list.length; i++) {
                CompoundSecMech m = list[i];
                b.append("\nCSIv2 CompoundSecMech[" + i + "]\n\tTarget Requires:");
                Enumeration keys = assocOptions.keys();
                while (keys.hasMoreElements()) {
                    Integer j = keys.nextElement();
                    if (isSet(m.target_requires, j.intValue())) {
                        b.append("\n\t\t" + assocOptions.get(j));
                    }
                }

                TLS_SEC_TRANS ssl = tCI.getSSLInformation(m);
                if (ssl != null) {
                    b.append("\n\tTLS_SEC_TRANS\n\t\tTarget Requires:");
                    keys = assocOptions.keys();
                    while (keys.hasMoreElements()) {
                        Integer j = keys.nextElement();
                        if (isSet(ssl.target_requires, j.intValue())) {
                            b.append("\n\t\t\t" + assocOptions.get(j));
                        }
                    }
                    b.append("\n\t\tTarget Supports:");
                    keys = assocOptions.keys();
                    while (keys.hasMoreElements()) {
                        Integer j = keys.nextElement();
                        if (isSet(ssl.target_supports, j.intValue())) {
                            b.append("\n\t\t\t" + assocOptions.get(j));
                        }
                    }
                    TransportAddress[] aList = ssl.addresses;
                    for (int j = 0; j < aList.length; j++) {
                        TransportAddress a = aList[j];
                        b.append("\n\t\tAddress[" + j + "] Host Name: " +
                                a.host_name + " port: " + a.port);
                    }
                }

                AS_ContextSec asContext = m.as_context_mech;
                if (asContext != null) {
                    b.append("\n\tAS_ContextSec\n\t\tTarget Requires:");
                    keys = assocOptions.keys();
                    while (keys.hasMoreElements()) {
                        Integer j = keys.nextElement();
                        if (isSet(asContext.target_requires, j.intValue())) {
                            b.append("\n\t\t\t" + assocOptions.get(j));
                        }
                    }
                    b.append("\n\t\tTarget Supports:");
                    keys = assocOptions.keys();
                    while (keys.hasMoreElements()) {
                        Integer j = keys.nextElement();
                        if (isSet(asContext.target_supports, j.intValue())) {
                            b.append("\n\t\t\t" + assocOptions.get(j));
                        }
                    }
                    try {
                        if (asContext.client_authentication_mech.length > 0) {
                            Oid oid = new Oid(asContext.client_authentication_mech);
                            b.append("\n\t\tclient_auth_mech_OID:" + oid);
                        } else {
                            b.append("\n\t\tclient_auth_mech_OID: undefined");
                        }
                    } catch (Exception e) {
                        b.append("\n\t\tclient_auth_mech_OID: (invalid)" + e.getMessage());
                    } finally {
                        b.append("\n\t\ttarget_name:" + new String(asContext.target_name));
                    }
                }

                SAS_ContextSec sasContext = m.sas_context_mech;
                if (sasContext != null) {
                    b.append("\n\tSAS_ContextSec\n\t\tTarget Requires:");
                    keys = assocOptions.keys();
                    while (keys.hasMoreElements()) {
                        Integer j = keys.nextElement();
                        if (isSet(sasContext.target_requires, j.intValue())) {
                            b.append("\n\t\t\t" + assocOptions.get(j));
                        }
                    }
                    b.append("\n\t\tTarget Supports:");
                    keys = assocOptions.keys();
                    while (keys.hasMoreElements()) {
                        Integer j = keys.nextElement();
                        if (isSet(sasContext.target_supports, j.intValue())) {
                            b.append("\n\t\t\t" + assocOptions.get(j));
                        }
                    }
                    b.append("\n\t\tprivilege authorities:" + Arrays.toString(sasContext.privilege_authorities));
                    byte[][] nameTypes = sasContext.supported_naming_mechanisms;
                    for (int j = 0; j < nameTypes.length; j++) {
                        try {
                            if (nameTypes[j].length > 0) {
                                Oid oid = new Oid(nameTypes[j]);
                                b.append("\n\t\tSupported Naming Mechanim[" + j + "]: " + oid);
                            } else {
                                b.append("\n\t\tSupported Naming Mechanim[" + j + "]:  undefined");
                            }
                        } catch (Exception e) {
                            b.append("\n\t\tSupported Naming Mechanism[" + j + "]: (invalid)" + e.getMessage());
                        }
                    }
                    b.append("\n\t\tsupported Identity Types:");
                    long map = sasContext.supported_identity_types;
                    keys = identityTokenTypes.keys();
                    while (keys.hasMoreElements()) {
                        Integer j = keys.nextElement();
                        if (isSet(sasContext.supported_identity_types, j.intValue())) {
                            b.append("\n\t\t\t" + identityTokenTypes.get(j));
                            map = map - j.intValue();
                        }
                    }
                    if (map > 0) {
                        b.append("\n\t\t\tcustom bits set: " + map);
                    }
                }
            }
            b.append("\n\n");
        } catch ( Exception e) {
            e.printStackTrace();
            return("Unexpected exception during IOR tracing - unset Property: " + traceIORsProperty);
        }
	return b.toString();
    }

}