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 1997-2007 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 information: "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 com.sun.enterprise.iiop.security;

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 sun.security.x509.X500Name;
import com.sun.enterprise.security.SecurityServicesUtil;
import com.sun.enterprise.security.auth.login.LoginContextDriver;
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 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.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;
    
    /**
     * Read the client and server preferences from the config files.
     */
    public SecurityMechanismSelector() {
    }
    
    public void postConstruct() {
        try {
            
            Habitat habitat = SecurityServicesUtil.getInstance().getHabitat();
            orbHelper = habitat.getComponent(GlassFishORBHelper.class);
            sslUtils = habitat.getComponent(SSLUtils.class);
            invMgr = habitat.getComponent(InvocationManager.class);
	    // Initialize client security config
	    String s = 
		(String)(orbHelper.getCSIv2Props()).get(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 = (String)(orbHelper.getCSIv2Props()).get(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 = 
		(String)(orbHelper.getCSIv2Props()).get(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 static ServerConnectionContext getServerConnectionContext() {
        Hashtable h = ConnectionExecutionContext.getContext();
        ServerConnectionContext scc = 
            (ServerConnectionContext) h.get(SERVER_CONNECTION_CONTEXT);
        return scc;
    }

    public static void setServerConnectionContext(ServerConnectionContext scc) {
        Hashtable h = ConnectionExecutionContext.getContext();
        h.put(SERVER_CONNECTION_CONTEXT, scc);
    }

    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()); 
        }
        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();
        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 (SecurityServicesUtil.getInstance().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(SecurityServicesUtil.getInstance().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;
    }

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

	if (mechSupported == null) {
	    return false;
	}
        if (mechanisms[0].length != mechSupported.length)
            return false;
        for (int i=0; i:");
	}
	
        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)
    {

        boolean client_authenticated = false;

        // get requirements and supports at the client authentication layer
        AS_ContextSec ascontext = null;
        try {
            ascontext = this.getCtc().createASContextSec(iordesc);
        } 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;
            }
            if ( ! evaluate_client_conformance_ascontext(ctx, iorDesc)){
		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 = ior.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)
        throws SecurityMechanismException
    {
        SecurityContext ssc = null;
        Socket socket = 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.

        ServerConnectionContext scc = getServerConnectionContext();

        if(scc != null) {
            socket = scc.getSocket();
            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.
        if (socket == null && 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.subject = ctx.subject;

        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 boolean isSet(int val1, int val2) {
        if((val1 & val2) == val2) {
            return true;
        }
        return false;
    }

    public Set getCorbaIORDescSet() {
        return corbaIORDescSet;
    }

    public boolean isSslRequired() {
        return sslRequired;
    }

    
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy