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

com.sun.enterprise.iiop.security.SecurityContextUtil 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.spi.ior.IOR;
import com.sun.corba.ee.spi.presentation.rmi.StubAdapter;
import com.sun.enterprise.common.iiop.security.SecurityContext;
import com.sun.enterprise.security.CORBAObjectPermission;
import com.sun.enterprise.security.auth.login.LoginContextDriver;
import com.sun.logging.LogDomains;
import java.net.Socket;

import java.security.Principal;
import java.security.ProtectionDomain;
import java.security.CodeSource;
import java.security.Policy;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.logging.Level;
import java.util.Set;
import javax.security.auth.Subject;
import org.glassfish.enterprise.iiop.api.GlassFishORBHelper;
import org.glassfish.enterprise.iiop.api.ProtocolManager;
import org.jvnet.hk2.annotations.Inject;
import org.jvnet.hk2.annotations.Scoped;
import org.jvnet.hk2.annotations.Service;
import org.jvnet.hk2.component.PostConstruct;
import org.jvnet.hk2.component.Singleton;


/** 
 * This class provides has the helper methods to deal with
 * the SecurityContext .This represents the SecurityServiceImpl of V2
 * @author Nithya Subramanian
 */

@Service
@Scoped(Singleton.class)
public class SecurityContextUtil implements PostConstruct {
    
    public static final int STATUS_PASSED = 0;
    public static final int STATUS_FAILED = 1;
    public static final int STATUS_RETRY = 2;
    
    private static java.util.logging.Logger _logger =
            LogDomains.getLogger(SecurityContextUtil.class, LogDomains.SECURITY_LOGGER);
   
    private static String IS_A = "_is_a";
    private Policy policy;
    
    @Inject
    private GlassFishORBHelper orbHelper;

    @Inject
    private SecurityMechanismSelector sms;
    
    public SecurityContextUtil() {
    
    }

    public void postConstruct() {
        policy = Policy.getPolicy();
    }
    /**
     * This is called by the CSIv2 interceptor on the client before
     * sending the IIOP message.
     * @param the effective_target field of the PortableInterceptor
     * ClientRequestInfo object.
     * @return a SecurityContext which is marshalled into the IIOP msg
     * by the CSIv2 interceptor.
     */
    public SecurityContext getSecurityContext(
            org.omg.CORBA.Object effective_target)
            throws InvalidMechanismException, InvalidIdentityTokenException {
        SecurityContext context = null;
        assert(orbHelper != null);
        IOR ior =  ((com.sun.corba.ee.spi.orb.ORB)orbHelper.getORB()).getIOR(effective_target, false);
        if (StubAdapter.isStub(effective_target)) {
            if (StubAdapter.isLocal(effective_target)) {
                // XXX: Workaround for non-null connection object ri for local invocation.
                ConnectionExecutionContext.setClientThreadID(Thread.currentThread().getId());
                return null;
            }
        }

        try {
            context = sms.selectSecurityContext(ior);
        } catch (InvalidMechanismException ime) { // let this pass ahead
            _logger.log(Level.SEVERE, "iiop.invalidmechanism_exception", ime);
            throw new InvalidMechanismException(ime.getMessage());
        } catch (InvalidIdentityTokenException iite) {
            _logger.log(Level.SEVERE, "iiop.invalididtoken_exception", iite);
            throw new InvalidIdentityTokenException(iite.getMessage());
        // let this pass ahead
        } catch (SecurityMechanismException sme) {
            _logger.log(Level.SEVERE, "iiop.secmechanism_exception", sme);
            throw new RuntimeException(sme.getMessage());
        }
        return context;
    }

    /**
     * This is called by the CSIv2 interceptor on the client after
     * a reply is received.
     * @param the reply status from the call. The reply status field
     * could indicate an authentication retry.
     * The following is the mapping of PI status to the reply_status field
     * PortableInterceptor::SUCCESSFUL -> STATUS_PASSED
     * PortableInterceptor::SYSTEM_EXCEPTION -> STATUS_FAILED
     * PortableInterceptor::USER_EXCEPTION -> STATUS_PASSED
     * PortableInterceptor::LOCATION_FORWARD -> STATUS_RETRY
     * PortableInterceptor::TRANSPORT_RETRY -> STATUS_RETRY
     * @param the effective_target field of the PI ClientRequestInfo object.
     */
    public static void receivedReply(int reply_status,
            org.omg.CORBA.Object effective_target) {
        if (reply_status == STATUS_FAILED) {
            if (_logger.isLoggable(Level.FINE)) {
                _logger.log(Level.FINE, "Failed status");
            }
            // what kind of exception should we throw? 
            throw new RuntimeException("Target did not accept security context");
        } else if (reply_status == STATUS_RETRY) {
            if (_logger.isLoggable(Level.FINE)) {
                _logger.log(Level.FINE, "Retry status");
            }
        } else {
            if (_logger.isLoggable(Level.FINE)) {
                _logger.log(Level.FINE, "Passed status");
            }
        }
    }

    /**
     * This is called by the CSIv2 interceptor on the server after
     * receiving the IIOP message. If authentication fails a FAILED status
     * is returned. If a FAILED status is returned the CSIV2 interceptor will
     * marshall the MessageError service context and throw the NO_PERMISSION
     * exception.
     * @param the SecurityContext which arrived in the IIOP message.
     * @return the status
     */
    public int setSecurityContext(SecurityContext context, byte[] object_id,
            String method, Socket socket) {
        if (_logger.isLoggable(Level.FINE)) {
            _logger.log(Level.FINE, "ABOUT TO EVALUATE TRUST");
        }

        try {
            // First check if the client sent the credentials
            // as required by the object's CSIv2 policy.
            // evaluateTrust will throw an exception if client did not
            // conform to security policy.
            SecurityContext ssc = sms.evaluateTrust(context, object_id, socket);

            Class cls = null;
            Subject s = null;
            if (ssc == null) {
                return STATUS_PASSED;
            } else {
                if (ssc.authcls != null) {
                    cls = ssc.authcls;
                } else {
                    cls = ssc.identcls;
                }
                s = ssc.subject;
            }

            // Authenticate the client. An Exception is thrown if login fails.
            // SecurityContext is set on current thread if login succeeds.
            authenticate(s, cls);

            // Authorize the client for non-EJB objects.
            // Auth for EJB objects is done in BaseContainer.preInvoke().
            if (authorizeCORBA(object_id, method)) {
                return STATUS_PASSED;
            } else {
                return STATUS_FAILED;
            }
        } catch (Exception e) {
            if (!method.equals(IS_A)) {
                if (_logger.isLoggable(Level.FINE)) {
                    _logger.log(Level.FINE, "iiop.authenticate_exception", e.toString());
                }
                if (_logger.isLoggable(Level.FINE)) {
                    _logger.log(Level.FINE, "Authentication Exception", e);
                }
            }
            return STATUS_FAILED;
        }
    }


    // return true if authorization succeeds, false otherwise.
    private boolean authorizeCORBA(byte[] object_id, String method)
            throws Exception {

        // Check if target is an EJB
        ProtocolManager 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;
        }
        if (protocolMgr.getEjbDescriptor(object_id) != null) {
            return true; // an EJB object

        }
        CORBAObjectPermission perm = new CORBAObjectPermission("*", method);

        // Create a ProtectionDomain for principal on current thread.
        com.sun.enterprise.security.SecurityContext sc =
                com.sun.enterprise.security.SecurityContext.getCurrent();
        Set principalSet = sc.getPrincipalSet();
        Principal[] principals = (principalSet == null ? null : (Principal[]) principalSet.toArray(new Principal[0]));
        CodeSource cs = new CodeSource(new java.net.URL("file://"),
                (java.security.cert.Certificate[]) null);
        ProtectionDomain prdm = new ProtectionDomain(cs, null, null, principals);

        // Check if policy gives principal the permissions
        boolean result = policy.implies(prdm, perm);

        if (_logger.isLoggable(Level.FINE)) {
            _logger.log(Level.FINE, "CORBA Object permission evaluation result=" + result + " for method=" + method);
        }
        return result;
    }

    /**
     * This is called by the CSIv2 interceptor on the server before
     * sending the reply.
     * @param the SecurityContext which arrived in the IIOP message.
     */
    public void sendingReply(SecurityContext context) {
        // NO OP
    }

    /**
     * This is called on the server to unset the security context 
     * this is introduced to prevent the re-use of the thread
     * security context on re-use of the thread.
     */
    public static void unsetSecurityContext(boolean isLocal) {
        // logout method from LoginContext not called 
        // as we dont want to unset the appcontainer context
        if (!isLocal) {
            com.sun.enterprise.security.SecurityContext.setCurrent(null);
        }
    }

    /**
     * Authenticate the user with the specified subject and
     * credential class.
     */
    private void authenticate(Subject s, Class cls)
            throws SecurityMechanismException {
        // authenticate
        try {
            final Subject fs = s;
            final Class cl = cls;
            AccessController.doPrivileged(new PrivilegedAction() {

                public java.lang.Object run() {
                    LoginContextDriver.login(fs, cl);
                    return null;
                }
            });
        } catch (Exception e) {
            if (_logger.isLoggable(Level.SEVERE)) {
                _logger.log(Level.SEVERE, "iiop.login_exception", e.toString());
            }
            if (_logger.isLoggable(Level.FINE)) {
                _logger.log(Level.FINE, "Login Exception", e);
            }
            throw new SecurityMechanismException("Cannot login user:" +
                    e.getMessage());
        }
    }

  
}






© 2015 - 2024 Weber Informatics LLC | Privacy Policy