/*
 * Copyright 2001-2004 The Apache Software Foundation.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.axis.components.net;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.security.cert.Certificate;
import java.security.cert.CertificateParsingException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.regex.Pattern;

import javax.naming.InvalidNameException;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;

import org.apache.axis.utils.Messages;
import org.apache.axis.utils.StringUtils;
import org.apache.axis.utils.XMLUtils;


/**
 * SSL socket factory. It _requires_ a valid RSA key and
 * JSSE. (borrowed code from tomcat)
 * 
 * THIS CODE STILL HAS DEPENDENCIES ON sun.* and com.sun.*
 *
 * @author Davanum Srinivas (dims@yahoo.com)
 */
public class JSSESocketFactory extends DefaultSocketFactory implements SecureSocketFactory {

    // This is a a sorted list, if you insert new elements do it orderdered.
    private final static String[] BAD_COUNTRY_2LDS =
        {"ac", "co", "com", "ed", "edu", "go", "gouv", "gov", "info",
            "lg", "ne", "net", "or", "org"};
    /** Field sslFactory           */
    protected SSLSocketFactory sslFactory = null;

    /**
     * Constructor JSSESocketFactory
     *
     * @param attributes
     */
    public JSSESocketFactory(Hashtable attributes) {
        super(attributes);
    }

    /**
     * Initialize the SSLSocketFactory
     * @throws IOException
     */ 
    protected void initFactory() throws IOException {
        sslFactory = (SSLSocketFactory)SSLSocketFactory.getDefault();
    }
    
    /**
     * creates a secure socket
     *
     * @param host
     * @param port
     * @param otherHeaders
     * @param useFullURL
     *
     * @return Socket
     * @throws Exception
     */
    public Socket create(
            String host, int port, StringBuffer otherHeaders, BooleanHolder useFullURL)
            throws Exception {
        if (sslFactory == null) {
            initFactory();
        }
        if (port == -1) {
            port = 443;
        }

        TransportClientProperties tcp = TransportClientPropertiesFactory.create("https");

        boolean hostInNonProxyList = isHostInNonProxyList(host, tcp.getNonProxyHosts());

        Socket sslSocket = null;
        if (tcp.getProxyHost().length() == 0 || hostInNonProxyList) {
            // direct SSL connection
            sslSocket = sslFactory.createSocket(host, port);
        } else {

            // Default proxy port is 80, even for https
            int tunnelPort = (tcp.getProxyPort().length() != 0)
                             ? Integer.parseInt(tcp.getProxyPort())
                             : 80;
            if (tunnelPort < 0)
                tunnelPort = 80;

            // Create the regular socket connection to the proxy
            Socket tunnel = new Socket(tcp.getProxyHost(), tunnelPort);

            // The tunnel handshake method (condensed and made reflexive)
            OutputStream tunnelOutputStream = tunnel.getOutputStream();
            PrintWriter out = new PrintWriter(
                    new BufferedWriter(new OutputStreamWriter(tunnelOutputStream)));

            // More secure version... engage later?
            // PasswordAuthentication pa =
            // Authenticator.requestPasswordAuthentication(
            // InetAddress.getByName(tunnelHost),
            // tunnelPort, "SOCK", "Proxy","HTTP");
            // if(pa == null){
            // printDebug("No Authenticator set.");
            // }else{
            // printDebug("Using Authenticator.");
            // tunnelUser = pa.getUserName();
            // tunnelPassword = new String(pa.getPassword());
            // }
            out.print("CONNECT " + host + ":" + port + " HTTP/1.0\r\n"
                    + "User-Agent: AxisClient");
            if (tcp.getProxyUser().length() != 0 &&
                tcp.getProxyPassword().length() != 0) {

                // add basic authentication header for the proxy
                String encodedPassword = XMLUtils.base64encode((tcp.getProxyUser()
                        + ":"
                        + tcp.getProxyPassword()).getBytes());

                out.print("\nProxy-Authorization: Basic " + encodedPassword);
            }
            out.print("\nContent-Length: 0");
            out.print("\nPragma: no-cache");
            out.print("\r\n\r\n");
            out.flush();
            InputStream tunnelInputStream = tunnel.getInputStream();

            if (log.isDebugEnabled()) {
                log.debug(Messages.getMessage("isNull00", "tunnelInputStream",
                        "" + (tunnelInputStream
                        == null)));
            }
            String replyStr = "";

            // Make sure to read all the response from the proxy to prevent SSL negotiation failure
            // Response message terminated by two sequential newlines
            int newlinesSeen = 0;
            boolean headerDone = false;    /* Done on first newline */

            while (newlinesSeen < 2) {
                int i = tunnelInputStream.read();

                if (i < 0) {
                    throw new IOException("Unexpected EOF from proxy");
                }
                if (i == '\n') {
                    headerDone = true;
                    ++newlinesSeen;
                } else if (i != '\r') {
                    newlinesSeen = 0;
                    if (!headerDone) {
                        replyStr += String.valueOf((char) i);
                    }
                }
            }
            if (StringUtils.startsWithIgnoreWhitespaces("HTTP/1.0 200", replyStr) &&
                    StringUtils.startsWithIgnoreWhitespaces("HTTP/1.1 200", replyStr)) {
                throw new IOException(Messages.getMessage("cantTunnel00",
                        new String[]{
                            tcp.getProxyHost(),
                            "" + tunnelPort,
                            replyStr}));
            }

            // End of condensed reflective tunnel handshake method
            sslSocket = sslFactory.createSocket(tunnel, host, port, true);
            if (log.isDebugEnabled()) {
                log.debug(Messages.getMessage("setupTunnel00",
                          tcp.getProxyHost(),
                        "" + tunnelPort));
            }
        }

        ((SSLSocket) sslSocket).startHandshake();
        if (log.isDebugEnabled()) {
            log.debug(Messages.getMessage("createdSSL00"));
        }
        verifyHostName(host, (SSLSocket) sslSocket);
        return sslSocket;
    }
    /**
     * Verifies that the given hostname in certicifate is the hostname we are trying to connect to.
     * This resolves CVE-2012-5784 and CVE-2014-3596
     * @param host
     * @param ssl
     * @throws IOException
     */
    
	private static void verifyHostName(String host, SSLSocket ssl)
			throws IOException {
		if (host == null) {
			throw new IllegalArgumentException("host to verify was null");
		}

		SSLSession session = ssl.getSession();
		if (session == null) {
            // In our experience this only happens under IBM 1.4.x when
            // spurious (unrelated) certificates show up in the server's chain.
            // Hopefully this will unearth the real problem:
			InputStream in = ssl.getInputStream();
			in.available();
            /*
                 If you're looking at the 2 lines of code above because you're
                 running into a problem, you probably have two options:

                    #1.  Clean up the certificate chain that your server
                         is presenting (e.g. edit "/etc/apache2/server.crt" or
                         wherever it is your server's certificate chain is
                         defined).

                                             OR

                    #2.   Upgrade to an IBM 1.5.x or greater JVM, or switch to a
                          non-IBM JVM.
              */

            // If ssl.getInputStream().available() didn't cause an exception,
            // maybe at least now the session is available?
			session = ssl.getSession();
			if (session == null) {
                // If it's still null, probably a startHandshake() will
                // unearth the real problem.
				ssl.startHandshake();

                // Okay, if we still haven't managed to cause an exception,
                // might as well go for the NPE.  Or maybe we're okay now?
				session = ssl.getSession();
			}
		}

		Certificate[] certs = session.getPeerCertificates();
		verifyHostName(host.trim().toLowerCase(Locale.US),  (X509Certificate) certs[0]);
	}
	/**
	 * Extract the names from the certificate and tests host matches one of them
	 * @param host
	 * @param cert
	 * @throws SSLException
	 */

	private static void verifyHostName(final String host, X509Certificate cert)
			throws SSLException {
        // I'm okay with being case-insensitive when comparing the host we used
        // to establish the socket to the hostname in the certificate.
        // Don't trim the CN, though.
        
		String[] cns = getCNs(cert);
		String[] subjectAlts = getDNSSubjectAlts(cert);
		verifyHostName(host, cns, subjectAlts);

	}

	/**
	 * Extract all alternative names from a certificate.
	 * @param cert
	 * @return
	 */
	private static String[] getDNSSubjectAlts(X509Certificate cert) {
		LinkedList subjectAltList = new LinkedList();
		Collection c = null;
		try {
			c = cert.getSubjectAlternativeNames();
		} catch (CertificateParsingException cpe) {
			// Should probably log.debug() this?
			cpe.printStackTrace();
		}
		if (c != null) {
			Iterator it = c.iterator();
			while (it.hasNext()) {
				List list = (List) it.next();
				int type = ((Integer) list.get(0)).intValue();
				// If type is 2, then we've got a dNSName
				if (type == 2) {
					String s = (String) list.get(1);
					subjectAltList.add(s);
				}
			}
		}
		if (!subjectAltList.isEmpty()) {
			String[] subjectAlts = new String[subjectAltList.size()];
			subjectAltList.toArray(subjectAlts);
			return subjectAlts;
		} else {
			return new String[0];
		}
	        
	}
	/**
	 * Verifies
	 * @param host
	 * @param cn
	 * @param subjectAlts
	 * @throws SSLException
	 */

	private static void verifyHostName(final String host, String[] cns, String[] subjectAlts)throws SSLException{
		StringBuffer cnTested = new StringBuffer();

		for (int i = 0; i < subjectAlts.length; i++){
			String name = subjectAlts[i];
			if (name != null) {
				name = name.toLowerCase(Locale.US);
				if (verifyHostName(host, name)){
					return;
				}
				cnTested.append("/").append(name);
			}				
		}
        for (int i = 0; i < cns.length; i++) {
            String cn = cns[i];
            if (cn != null) {
                cn = cn.toLowerCase(Locale.US);
                if (verifyHostName(host, cn)) {
                    return;
                }
                cnTested.append("/").append(cn);
            }
        }
		throw new SSLException("hostname in certificate didn't match: <"
					+ host + "> != <" + cnTested + ">");
	}		
	
	private static boolean verifyHostName(final String host, final String cn){
		if (doWildCard(cn) && !isIPAddress(host)) {
			return matchesWildCard(cn, host);
		} 
		return host.equalsIgnoreCase(cn);
	}
    private static boolean doWildCard(String cn) {
		// Contains a wildcard
		// wildcard in the first block
    	// not an ipaddress (ip addres must explicitily be equal)
    	// not using 2nd level common tld : ex: not for *.co.uk
    	String parts[] = cn.split("\\.");
    	return parts.length >= 3 &&
    			parts[0].endsWith("*") &&
    			acceptableCountryWildcard(cn) &&
    			!isIPAddress(cn);
    }

	private static final Pattern IPV4_PATTERN =
			Pattern.compile("^(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}$");

	private static final Pattern IPV6_STD_PATTERN = 
			Pattern.compile("^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$");

	private static final Pattern IPV6_HEX_COMPRESSED_PATTERN = 
			Pattern.compile("^((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)::((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)$");


	private static boolean isIPAddress(final String hostname) {
		return hostname != null
				&& (
						IPV4_PATTERN.matcher(hostname).matches()
						|| IPV6_STD_PATTERN.matcher(hostname).matches() 
						|| IPV6_HEX_COMPRESSED_PATTERN.matcher(hostname).matches()
		);

	}

	private static boolean acceptableCountryWildcard(final String cn) {
		// The CN better have at least two dots if it wants wildcard action,
		// but can't be [*.co.uk] or [*.co.jp] or [*.org.uk], etc...
		// The [*.co.uk] problem is an interesting one. Should we just
		// hope that CA's would never foolishly allow such a
		// certificate to happen?
    	
		String[] parts = cn.split("\\.");
		// Only checks for 3 levels, with country code of 2 letters.
		if (parts.length > 3 || parts[parts.length - 1].length() != 2) {
			return true;
		}
		String countryCode = parts[parts.length - 2];
		return Arrays.binarySearch(BAD_COUNTRY_2LDS, countryCode) < 0;
	}

	private static boolean matchesWildCard(final String cn,
			final String hostName) {
		String parts[] = cn.split("\\.");
		boolean match = false;
		String firstpart = parts[0];
		if (firstpart.length() > 1) {
			// server∗
			// e.g. server
			String prefix =  firstpart.substring(0, firstpart.length() - 1);
			// skipwildcard part from cn
			String suffix = cn.substring(firstpart.length()); 
			// skip wildcard part from host
			String hostSuffix = hostName.substring(prefix.length());			
			match = hostName.startsWith(prefix) && hostSuffix.endsWith(suffix);
		} else {
			match = hostName.endsWith(cn.substring(1));
		}
		if (match) {
			// I f we ’ r e i n s t r i c t mode ,
			// [ ∗.foo.com] is not allowed to match [a.b.foo.com]
			match = countDots(hostName) == countDots(cn);
		}
		return match;
	}

	private static int countDots(final String data) {
		int dots = 0;
		for (int i = 0; i < data.length(); i++) {
			if (data.charAt(i) == '.') {
				dots += 1;
			}
		}
		return dots;
	}


	private static String[] getCNs(X509Certificate cert) {
          // Note:  toString() seems to do a better job than getName()
          //
          // For example, getName() gives me this:
          // 1.2.840.113549.1.9.1=#16166a756c6975736461766965734063756362632e636f6d
          //
          // whereas toString() gives me this:
          // EMAILADDRESS=juliusdavies@cucbc.com        
		String subjectPrincipal = cert.getSubjectX500Principal().toString();
		
		return getCNs(subjectPrincipal);

	}
	private static String[] getCNs(String subjectPrincipal) {
        if (subjectPrincipal == null) {
            return null;
        }
        final List cns = new ArrayList();
        try {
            final LdapName subjectDN = new LdapName(subjectPrincipal);
            final List rdns = subjectDN.getRdns();
            for (int i = rdns.size() - 1; i >= 0; i--) {
                final Rdn rds = (Rdn) rdns.get(i);
                final Attributes attributes = rds.toAttributes();
                final Attribute cn = attributes.get("cn");
                if (cn != null) {
                    try {
                        final Object value = cn.get();
                        if (value != null) {
                            cns.add(value.toString());
                        }
                    }
                    catch (NamingException ignore) {}
                }
            }
        }
        catch (InvalidNameException ignore) { }
        return cns.isEmpty() ? null : (String[]) cns.toArray(new String[ cns.size() ]);
	}

}
