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

org.ferris.axis.components.net.MySecureSocketFactory Maven / Gradle / Ivy

package org.ferris.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.InetAddress;
import java.net.Socket;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.util.Enumeration;
import java.util.Hashtable;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;

import org.apache.axis.components.net.BooleanHolder;
import org.apache.axis.components.net.DefaultHTTPSTransportClientProperties;
import org.apache.axis.components.net.TransportClientProperties;
import org.apache.axis.components.net.TransportClientPropertiesFactory;
import org.apache.axis.utils.Messages;
import org.apache.axis.utils.StringUtils;
import org.apache.axis.utils.XMLUtils;
import org.apache.log4j.Logger;

public class MySecureSocketFactory implements org.apache.axis.components.net.SecureSocketFactory {

    private Logger log = Logger.getLogger(getClass());
    private SSLSocketFactory factory;

    public static void main(String[] args)
            throws Exception {
        new MySecureSocketFactory(new Hashtable());
    }

    public MySecureSocketFactory(Hashtable table)
            throws Exception {
        // This url gives an example of how to create a 
        // factory which will accept any certificate, which means
        // connecting to a custom keystore is not neccessary.
        //
        // http://exampledepot.com/egs/javax.net.ssl/TrustAll.html?l=rel
        //
        log.info("Get default type");
        String defaultType = KeyStore.getDefaultType();
        log.info(String.format("defaultType=\"%s\"", defaultType));

        log.info(String.format("Get KeyStore instance"));
        KeyStore ks = KeyStore.getInstance(defaultType);

        String keystore = "/FerrisKeystore";
        log.info(String.format("Get class path resource \"%s\"", keystore));
        InputStream is = this.getClass().getResourceAsStream(keystore);
        if (is == null) {
            throw new RuntimeException(
                    String.format("The class path resource \"%s\" is not found!", keystore));
        }

        log.info(String.format("Create char[]"));
        char[] password = new char[]{'t', 'o', 'm', 'c', 'a', 't'};

        log.info(String.format("Load KeyStore"));
        ks.load(is, password);

        log.info(String.format("Loop over KeyStore aliases..."));
        for (Enumeration enu = ks.aliases(); enu.hasMoreElements();) {
            log.info(String.format("Alias=\"%s\"", String.valueOf(enu.nextElement())));
        }

        log.info(String.format("Get KeyManagerFactory instance"));
        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
        log.info(String.format("Init KeyManagerFactory"));
        kmf.init(ks, password);

        log.info(String.format("Get TrustManagerFactory instance"));
        TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
        log.info(String.format("Init TrustManagerFactory"));
        tmf.init(ks);

        log.info(String.format("Get SSLContext instance"));
        SSLContext context = SSLContext.getInstance("SSL");
        log.info(String.format("Init SSLContext"));
        context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());

        log.info(String.format("Get SocketFactory"));
        factory = context.getSocketFactory();
    }

//    @Override
//	public Socket create(
//			  String host
//			, int port
//			, StringBuffer otherHeaders
//			, BooleanHolder useFullUrl
//	) throws Exception 
//	{
//		log.info(
//			String.format(
//				"ENTER: create(%s, %d, %s, %s)"
//				, host
//				, port
//				, (otherHeaders == null) ? "null" : otherHeaders.toString()
//				, (useFullUrl == null) ? "null" : useFullUrl.value
//		    )
//		);
//		port = (port == -1) ? 443 : port;		
//		return factory.createSocket(host, port);                
//	}
    
    private boolean directSSLConnection(TransportClientProperties tcp) {
        return tcp.getProxyHost() == null || tcp.getProxyHost().length() == 0;
    }
    
    private static final int DEFAULT_SSL_PORT = 443;
    private static final int DEFAULT_PROXY_PORT = 7777;
    /**
     * Copied from AXIS source code, original
     *
     * @author Davanum Srinivas ([email protected]) THIS CODE STILL HAS
     * DEPENDENCIES ON sun.* and com.sun.*
     */
    public Socket create(final String host, final int thePort, final StringBuffer otherHeaders, final BooleanHolder useFullURL)
            throws Exception {

        int port = (thePort == -1) ? DEFAULT_SSL_PORT : thePort;

//        boolean hostInNonProxyList = false;
        TransportClientProperties tcp = TransportClientPropertiesFactory.create("https");

//        if (tcp instanceof DefaultHTTPSTransportClientProperties) {
//            hostInNonProxyList = ((DefaultHTTPSTransportClientProperties) tcp).getNonProxyHosts().contains("host");
//        }
//        boolean hostInNonProxyList = super.isHostInNonPxyList(host, tcp.getNonProxyHosts());

        Socket sslSocket;
        if (directSSLConnection(tcp)) {
            sslSocket = factory.createSocket(host, port);    
        } else {
            int tunnelPort = (tcp.getProxyPort().length() != 0)
                    ? Integer.parseInt(tcp.getProxyPort())
                    : DEFAULT_PROXY_PORT;
            if (tunnelPort < 0) {
                tunnelPort = DEFAULT_PROXY_PORT;
            }


            // Create the regular socket connection to the proxy
            //Socket l = new Socket(new InetAddressImpl(tcp.getProxyHost()), tunnelPort);
            Socket tunnel = new Socket(InetAddress.getByName(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();

            
            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 = factory.createSocket(tunnel, host, port, true);

            log.debug(Messages.getMessage("setupTunnel00", tcp.getProxyHost(), "" + tunnelPort));

        }

        ((SSLSocket) sslSocket).startHandshake();
        log.debug(Messages.getMessage("createdSSL00"));
        
        return sslSocket;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy