/*
 * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package org.glassfish.enterprise.iiop.impl;

import com.sun.corba.ee.impl.misc.ORBUtility;
import com.sun.corba.ee.spi.transport.Acceptor;
import java.util.Hashtable;
import java.util.Map;
import java.util.logging.Logger;
import javax.net.ssl.SSLContext;
import com.sun.corba.ee.spi.orb.ORB;
import com.sun.corba.ee.spi.misc.ORBConstants;
import com.sun.corba.ee.spi.transport.ORBSocketFactory;
import com.sun.enterprise.config.serverbeans.Config;
import org.glassfish.orb.admin.config.IiopListener;
import org.glassfish.orb.admin.config.IiopService;
import org.glassfish.grizzly.config.dom.Ssl;
import com.sun.logging.LogDomains;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import java.util.logging.Level;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import org.glassfish.api.admin.ProcessEnvironment;
import org.glassfish.api.admin.ProcessEnvironment.ProcessType;
import org.glassfish.internal.api.Globals;
import org.glassfish.security.common.CipherInfo;
import org.glassfish.enterprise.iiop.api.IIOPSSLUtil;
import com.sun.enterprise.security.integration.AppClientSSL;
import org.glassfish.api.admin.ServerEnvironment;


/**
 * This is socket factory used to create either plain sockets or SSL
 * sockets based on the target's policies and the client policies.
 * @author Vivek Nagar
 * @author Shing Wai Chan
 */
public class IIOPSSLSocketFactory implements ORBSocketFactory {

    private static final Logger _logger = LogDomains.getLogger(
        IIOPSSLSocketFactory.class, LogDomains.CORBA_LOGGER);

    private static final String TLS = "TLS";
    private static final String SSL3 = "SSLv3";
    private static final String SSL2 = "SSLv2";
    private static final String SSL = "SSL";
    private static final String SSL_MUTUALAUTH = "SSL_MUTUALAUTH";
    private static final String PERSISTENT_SSL = "PERSISTENT_SSL";

    private static final int BACKLOG = 50;

    //private static SecureRandom sr = null;

    /* this is stored for the Server side of SSL Connections.
     * Note: There will be only a port per iiop listener and a corresponding
     * ctx for that port
     */
    /*
     * @todo provide an interface to the admin, so that whenever a iiop-listener
     * is added / removed, we modify the hashtable,
     */
    private Map portToSSLInfo = new Hashtable();
    /* this is stored for the client side of SSL Connections.
     * Note: There will be only 1 ctx for the client side, as we will reuse the
     * ctx for all SSL connections
     */
    private SSLInfo clientSslInfo = null;

    private ORB orb;

    /**
     * Constructs an <code>IIOPSSLSocketFactory</code>
     */
    public IIOPSSLSocketFactory() {
        try {
            ProcessEnvironment penv = null;
            ProcessType processType = null;
            boolean notServerOrACC =  Globals.getDefaultHabitat() == null ? true : false;
            if (!notServerOrACC) {
                penv = Globals.get(ProcessEnvironment.class);
                processType = penv.getProcessType();
            }
            //if (Switch.getSwitch().getContainerType() == Switch.EJBWEB_CONTAINER) {
            if ((processType != null) && (processType.isServer())) {
                // this is the EJB container
                Config conf = Globals.getDefaultHabitat().getService(Config.class,
                    ServerEnvironment.DEFAULT_INSTANCE_NAME);
                IiopService iiopBean =conf.getExtensionByType(IiopService.class);
                List<IiopListener> iiopListeners = iiopBean.getIiopListener();
                for (IiopListener listener : iiopListeners) {
                    Ssl ssl = listener.getSsl();
                    SSLInfo sslInfo = null;
                    boolean securityEnabled = Boolean.valueOf(listener.getSecurityEnabled());

                    if (securityEnabled) {
                        if (ssl != null) {
                            boolean ssl2Enabled = Boolean.valueOf(ssl.getSsl2Enabled());
                            boolean tlsEnabled = Boolean.valueOf(ssl.getTlsEnabled());
                            boolean ssl3Enabled = Boolean.valueOf(ssl.getSsl3Enabled());
                            sslInfo = init(ssl.getCertNickname(),
                                    ssl2Enabled, ssl.getSsl2Ciphers(),
                                    ssl3Enabled, ssl.getSsl3TlsCiphers(),
                                    tlsEnabled);
                        } else {
                            sslInfo = getDefaultSslInfo();
                        }
                        portToSSLInfo.put(Integer.parseInt(listener.getPort()), sslInfo);
                    }
                }

                if (iiopBean.getSslClientConfig() != null &&
                        /*iiopBean.getSslClientConfig().isEnabled()*/
                        iiopBean.getSslClientConfig().getSsl() != null) {
                    Ssl outboundSsl = iiopBean.getSslClientConfig().getSsl();
                    if (outboundSsl != null) {
                        boolean ssl2Enabled = Boolean.valueOf(outboundSsl.getSsl2Enabled());
                        boolean ssl3Enabled = Boolean.valueOf(outboundSsl.getSsl3Enabled());
                        boolean tlsEnabled = Boolean.valueOf(outboundSsl.getTlsEnabled());
                        clientSslInfo = init(outboundSsl.getCertNickname(),
                            ssl2Enabled,
                            outboundSsl.getSsl2Ciphers(),
                            ssl3Enabled,
                            outboundSsl.getSsl3TlsCiphers(),
                            tlsEnabled);
                    }
                }
                if (clientSslInfo == null) {
                    clientSslInfo = getDefaultSslInfo();
                }
            } else {
                if ((processType != null) && (processType == ProcessType.ACC)) {
                    IIOPSSLUtil sslUtil = Globals.getDefaultHabitat().getService(IIOPSSLUtil.class);
                    AppClientSSL clientSsl = (AppClientSSL)sslUtil.getAppClientSSL();
                    if (clientSsl != null) {
                        clientSslInfo = init(clientSsl.getCertNickname(),
                                clientSsl.getSsl2Enabled(), clientSsl.getSsl2Ciphers(),
                                clientSsl.getSsl3Enabled(), clientSsl.getSsl3TlsCiphers(),
                                clientSsl.getTlsEnabled());
                    } else { // include case keystore, truststore jvm option

                        clientSslInfo = getDefaultSslInfo();
                    }
                } else {
                    clientSslInfo = getDefaultSslInfo();
                }
            }
        } catch (Exception e) {
            _logger.log(Level.SEVERE,"iiop.init_exception",e);
            throw new IllegalStateException(e);
        }
    }

    /**
     * Return a default SSLInfo object.
     */
    private SSLInfo getDefaultSslInfo() throws Exception {
       return init(null, false, null, true, null, true);
    }

    /**
     * serveralias/clientalias cannot be set at the same time.
     * this method encapsulates the common code for both the client side and
     * server side to create a SSLContext
     * it is called once for each serveralias and once for each clientalias
     */
    private SSLInfo init(String alias,
            boolean ssl2Enabled, String ssl2Ciphers,
            boolean ssl3Enabled, String ssl3TlsCiphers,
            boolean tlsEnabled) throws Exception {

        String protocol;
        if (tlsEnabled) {
            protocol = TLS;
        } else if (ssl3Enabled) {
            protocol = SSL3;
        } else if (ssl2Enabled) {
            protocol = SSL2;
        } else { // default
            protocol = "SSL";
        }

        String[] ssl3TlsCipherArr = null;
        if (tlsEnabled || ssl3Enabled) {
            ssl3TlsCipherArr = getEnabledCipherSuites(ssl3TlsCiphers,
                    false, ssl3Enabled, tlsEnabled);
        }

        String[] ssl2CipherArr = null;
        if (ssl2Enabled) {
            ssl2CipherArr = getEnabledCipherSuites(ssl2Ciphers,
                    true, false, false);
        }

        SSLContext ctx = SSLContext.getInstance(protocol);
        if (Globals.getDefaultHabitat() != null) {
            IIOPSSLUtil sslUtil = Globals.getDefaultHabitat().getService(IIOPSSLUtil.class);
            KeyManager[] mgrs = sslUtil.getKeyManagers(alias);
            ctx.init(mgrs, sslUtil.getTrustManagers(), sslUtil.getInitializedSecureRandom());
        } else {
            //do nothing
            //ctx.init(mgrs, sslUtil.getTrustManagers(), sslUtil.getInitializedSecureRandom());
        }

        return new SSLInfo(ctx, ssl3TlsCipherArr, ssl2CipherArr);
    }

    //----- implements com.sun.corba.ee.spi.transport.ORBSocketFactory -----

    public void setORB(ORB orb) {
        this.orb = orb;
    }

    /**
     * Create a server socket on the specified InetSocketAddress  based on the
     * type of the server socket (SSL, SSL_MUTUALAUTH, PERSISTENT_SSL or CLEAR_TEXT).
     * @param type type of socket to create.
     * @param  inetSocketAddress the InetSocketAddress
     * @return the server socket on the specified InetSocketAddress
     * @exception IOException if an I/O error occurs during server socket
     * creation
     */
    public ServerSocket createServerSocket(String type, InetSocketAddress inetSocketAddress) throws IOException {
        if (_logger.isLoggable(Level.FINE)) {
            _logger.log(Level.FINE, "Creating server socket for type =" + type
                    + " inetSocketAddress =" + inetSocketAddress);
        }

        if(type.equals(SSL_MUTUALAUTH) || type.equals(SSL) ||
            type.equals(PERSISTENT_SSL)) {
            return createSSLServerSocket(type, inetSocketAddress);
        } else {
                ServerSocket serverSocket = null;
                if (orb.getORBData().acceptorSocketType().equals(
                        ORBConstants.SOCKETCHANNEL)) {
                    ServerSocketChannel serverSocketChannel =
                            ServerSocketChannel.open();
                    serverSocket = serverSocketChannel.socket();
                } else {
                    serverSocket = new ServerSocket();
                }

            serverSocket.bind(inetSocketAddress);
            return serverSocket;

        }
    }

    /**
     * Create a client socket for the specified InetSocketAddress. Creates an SSL
     * socket if the type specified is SSL or SSL_MUTUALAUTH.
     * @param type
     * @param inetSocketAddress
     * @return the socket.
     */
    public Socket createSocket(String type, InetSocketAddress inetSocketAddress)
            throws IOException {

        try {
            String host = inetSocketAddress.getHostName();
            int port = inetSocketAddress.getPort();
            if (_logger.isLoggable(Level.FINE)) {
                _logger.log(Level.FINE, "createSocket(" + type + ", " + host + ", " +port + ")");
            }
            if (type.equals(SSL) || type.equals(SSL_MUTUALAUTH)) {
                return createSSLSocket(host, port);
            } else {
                Socket socket = null;
                if (_logger.isLoggable(Level.FINE)) {
                    _logger.log(Level.FINE, "Creating CLEAR_TEXT socket for:" +port);
                }

                if (orb.getORBData().connectionSocketType().equals(
                    ORBConstants.SOCKETCHANNEL)) {
                    SocketChannel socketChannel = ORBUtility.openSocketChannel(inetSocketAddress);
                    socket = socketChannel.socket();
                } else {
                    socket = new Socket(inetSocketAddress.getHostName(), inetSocketAddress.getPort());
                }

                // Disable Nagle's algorithm (i.e. always send immediately).
                socket.setTcpNoDelay(true);
                return socket;
            }
        } catch ( Exception ex ) {
            if(_logger.isLoggable(Level.FINE)) {
                _logger.log(Level.FINE,"Exception creating socket",ex);
            }
            throw new RuntimeException(ex);
        }
    }

    public void setAcceptedSocketOptions(Acceptor acceptor,
        ServerSocket serverSocket, Socket socket) {
        if (_logger.isLoggable(Level.FINE)) {
            _logger.log(Level.FINE, "setAcceptedSocketOptions: " + acceptor + " " + serverSocket + " " + socket);
        }
        // Disable Nagle's algorithm (i.e., always send immediately).
        try {
            socket.setTcpNoDelay(true);
        } catch (SocketException ex) {
            throw new RuntimeException(ex);
        }
    }

    //----- END implements com.sun.corba.ee.spi.transport.ORBSocketFactory -----

    /**
     * Create an SSL server socket at the specified InetSocketAddress. If the type
     * is SSL_MUTUALAUTH then SSL client authentication is requested.
     */
    private ServerSocket createSSLServerSocket(String type, InetSocketAddress inetSocketAddress) throws IOException {
        if (inetSocketAddress == null) {
            throw new IOException(getFormatMessage("iiop.invalid_sslserverport", new Object[] {null}));
        }
        int port = inetSocketAddress.getPort();
        Integer iport = Integer.valueOf(port);
        SSLInfo sslInfo = (SSLInfo)portToSSLInfo.get(iport);
        if (sslInfo == null) {
            throw new IOException(getFormatMessage("iiop.invalid_sslserverport", new Object[] {iport}));
        }
        SSLServerSocketFactory ssf = sslInfo.getContext().getServerSocketFactory();
        String[] ssl3TlsCiphers = sslInfo.getSsl3TlsCiphers();
        String[] ssl2Ciphers = sslInfo.getSsl2Ciphers();
        String[] ciphers = null;
        if (ssl3TlsCiphers != null || ssl2Ciphers != null) {
            String[] socketCiphers = ssf.getDefaultCipherSuites();
            ciphers = mergeCiphers(socketCiphers, ssl3TlsCiphers, ssl2Ciphers);
        }

        String cs[] = null;

        if (_logger.isLoggable(Level.FINE)) {
            cs = ssf.getSupportedCipherSuites();
            for (int i = 0; i < cs.length; ++i) {
                _logger.log(Level.FINE, "Cipher Suite: " + cs[i]);
            }
        }
        ServerSocket ss = null;
        try {
            // bugfix for 6349541
            // specify the ip address to bind to, 50 is the default used
            // by the ssf implementation when only the port is specified
            ss = ssf.createServerSocket(port, BACKLOG, inetSocketAddress.getAddress());
            if (ciphers != null) {
                ((SSLServerSocket) ss).setEnabledCipherSuites(ciphers);
            }
        } catch (IOException e) {
            _logger.log(Level.SEVERE, "iiop.createsocket_exception", new Object[] {type, String.valueOf(port)});
            _logger.log(Level.SEVERE, "", e);
            throw e;
        }

        try {
            if (type.equals(SSL_MUTUALAUTH)) {
                _logger.log(Level.FINE, "Setting Mutual auth");
                ((SSLServerSocket) ss).setNeedClientAuth(true);
            }
        } catch (Exception e) {
            _logger.log(Level.SEVERE, "iiop.cipher_exception", e);
            throw new IOException(e.getMessage());
        }
        if (_logger.isLoggable(Level.FINE)) {
            _logger.log(Level.FINE, "Created server socket:" + ss);
        }
        return ss;
    }

    /**
     * Create an SSL socket at the specified host and port.
     * @param host
     * @param port
     * @return the socket.
     */
    private Socket createSSLSocket(String host, int port) throws IOException {
        SSLSocket socket = null;
        SSLSocketFactory factory = null;
        try {
            // get socketfactory+sanity check
            // clientSslInfo is never null
            factory = clientSslInfo.getContext().getSocketFactory();

            if(_logger.isLoggable(Level.FINE)) {
                  _logger.log(Level.FINE,"Creating SSL Socket for host:" + host +" port:" + port);
            }
            String[] ssl3TlsCiphers = clientSslInfo.getSsl3TlsCiphers();
            String[] ssl2Ciphers = clientSslInfo.getSsl2Ciphers();
            String[] clientCiphers = null;
            if (ssl3TlsCiphers != null || ssl2Ciphers != null) {
                String[] socketCiphers = factory.getDefaultCipherSuites();
                clientCiphers = mergeCiphers(socketCiphers, ssl3TlsCiphers, ssl2Ciphers);
            }

            socket = (SSLSocket)factory.createSocket(host, port);
            if (clientCiphers != null) {
                socket.setEnabledCipherSuites(clientCiphers);
            }
        } catch (Exception e) {
            if(_logger.isLoggable(Level.FINE)) {
                _logger.log(Level.FINE, "iiop.createsocket_exception",
                new Object[] { host, String.valueOf(port) });
                _logger.log(Level.FINE, "", e);
            }
            IOException e2 = new IOException("Error opening SSL socket to host=" + host + " port=" + port);
            e2.initCause(e);
            throw e2;
        }
        return socket;
    }

    /**
     * This API return an array of String listing the enabled cipher suites.
     * Input is the cipherSuiteStr from xml which a space separated list
     * ciphers with a prefix '+' indicating enabled, '-' indicating disabled.
     * If no cipher is enabled, then it returns an empty array.
     * If no cipher is specified, then all are enabled and it returns null.
     * @param cipherSuiteStr cipherSuiteStr from xml
     * @param ssl2Enabled
     * @param ssl3Enabled
     * @param tlsEnabled
     * @return an array of enabled Ciphers
     */
    private String[] getEnabledCipherSuites(String cipherSuiteStr,
            boolean ssl2Enabled, boolean ssl3Enabled, boolean tlsEnabled) {
        String[] cipherArr = null;
        if (cipherSuiteStr != null && cipherSuiteStr.length() > 0) {
            ArrayList cipherList = new ArrayList();
            StringTokenizer tokens = new StringTokenizer(cipherSuiteStr, ",");
            while (tokens.hasMoreTokens()) {
                String cipherAction = tokens.nextToken();
                if (cipherAction.startsWith("+")) {
                    String cipher = cipherAction.substring(1);
                    CipherInfo cipherInfo = CipherInfo.getCipherInfo(cipher);
                    if (cipherInfo != null && isValidProtocolCipher(cipherInfo, ssl2Enabled, ssl3Enabled, tlsEnabled)) {
                        cipherList.add(cipherInfo.getCipherName());
                    } else {
                        throw new IllegalStateException(getFormatMessage("iiop.unknown_cipher", new Object[] {cipher}));
                    }
                } else if (cipherAction.startsWith("-")) {
                    String cipher = cipherAction.substring(1);
                    CipherInfo cipherInfo = CipherInfo.getCipherInfo(cipher);
                    if (cipherInfo == null
                        || !isValidProtocolCipher(cipherInfo, ssl2Enabled, ssl3Enabled, tlsEnabled)) {
                        throw new IllegalStateException(getFormatMessage("iiop.unknown_cipher", new Object[] {cipher}));
                    }
                } else if (cipherAction.trim().length() > 0) {
                    throw new IllegalStateException(
                        getFormatMessage("iiop.invalid_cipheraction", new Object[] {cipherAction}));
                }
            }

            cipherArr = (String[]) cipherList.toArray(new String[cipherList.size()]);
        }
        return cipherArr;
    }

    /**
     * Return an array of merged ciphers.
     * @param enableCiphers  ciphers enabled by socket factory
     * @param ssl3TlsCiphers
     * @param ssl2Ciphers
     */
    private String[] mergeCiphers(String[] enableCiphers,
            String[] ssl3TlsCiphers, String[] ssl2Ciphers) {

        if (ssl3TlsCiphers == null && ssl2Ciphers == null) {
            return null;
        }

        int eSize = (enableCiphers != null)? enableCiphers.length : 0;

        if (_logger.isLoggable(Level.FINE)) {
            StringBuffer buf = new StringBuffer("Default socket ciphers: ");
            for (int i = 0; i < eSize; i++) {
                buf.append(enableCiphers[i] + ", ");
            }
            _logger.log(Level.FINE, buf.toString());
        }

        ArrayList cList = new ArrayList();
        if (ssl3TlsCiphers != null) {
            for (int i = 0; i < ssl3TlsCiphers.length; i++) {
                cList.add(ssl3TlsCiphers[i]);
            }
        } else {
            for (int i = 0; i < eSize; i++) {
                String cipher = enableCiphers[i];
                CipherInfo cInfo = CipherInfo.getCipherInfo(cipher);
                if (cInfo != null && (cInfo.isTLS() || cInfo.isSSL3())) {
                    cList.add(cipher);
                }
            }
        }

        if (ssl2Ciphers != null) {
            for (int i = 0; i < ssl2Ciphers.length; i++) {
                cList.add(ssl2Ciphers[i]);
            }
        } else {
            for (int i = 0; i < eSize; i++) {
                String cipher = enableCiphers[i];
                CipherInfo cInfo = CipherInfo.getCipherInfo(cipher);
                if (cInfo != null && cInfo.isSSL2()) {
                    cList.add(cipher);
                }
            }
        }

        if (_logger.isLoggable(Level.FINE)) {
            _logger.log(Level.FINE, "Merged socket ciphers: " + cList);
        }

        return (String[]) cList.toArray(new String[cList.size()]);
    }

    /**
     * Check whether given cipherInfo belongs to given protocol.
     * @param cipherInfo
     * @param ssl2Enabled
     * @param ssl3Enabled
     * @param tlsEnabled
     */
    private boolean isValidProtocolCipher(CipherInfo cipherInfo,
            boolean ssl2Enabled, boolean ssl3Enabled, boolean tlsEnabled) {
        return (tlsEnabled && cipherInfo.isTLS() ||
                ssl3Enabled && cipherInfo.isSSL3() ||
                ssl2Enabled && cipherInfo.isSSL2());
    }

    /**
     * This API get the format string from resource bundle of _logger.
     * @param key the key of the message
     * @param params the parameter array of Object
     * @return the format String for _logger
     */
    private String getFormatMessage(String key, Object[] params) {
        return MessageFormat.format(_logger.getResourceBundle().getString(key), params);
    }

    class SSLInfo {
        private SSLContext ctx;
        private String[] ssl3TlsCiphers = null;
        private String[] ssl2Ciphers = null;

        SSLInfo(SSLContext ctx, String[] ssl3TlsCiphers, String[] ssl2Ciphers) {
            this.ctx = ctx;
            this.ssl3TlsCiphers = ssl3TlsCiphers;
            this.ssl2Ciphers = ssl2Ciphers;
        }

        SSLContext getContext() {
            return ctx;
        }

        String[] getSsl3TlsCiphers() {
            return ssl3TlsCiphers;
        }

        String[] getSsl2Ciphers() {
            return ssl2Ciphers;
        }
    }
}
