package at.gv.egovernment.moa.id.util; 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.GeneralSecurityException; import java.util.Hashtable; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import org.apache.axis.components.net.BooleanHolder; import org.apache.axis.components.net.DefaultSocketFactory; import org.apache.axis.components.net.SecureSocketFactory; 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.XMLUtils; import at.gv.egovernment.moa.logging.Logger; /** * Secure socket factory for Axis webs service clients of the MOA-ID component, * which are the MOA-SP calls from MOA-ID Auth, * and the MOA-ID Auth calls from MOA-ID Proxy. *
Use this initialization code:
* // ConnectionParameter connParam = ... get from ConfigurationProvider * AxisSecureSocketFactory.initialize(connParam); *
See the Apache Axis documentation on how to configure this class * as the default secure socket factory to be used by Axis. *
* This code has been copied from JSSESocketFactory, the * method initialize() has been added. * * * @author Paul Ivancsics * @version $Id$ */ public class AxisSecureSocketFactory extends DefaultSocketFactory implements SecureSocketFactory { /** Field sslFactory */ private static SSLSocketFactory sslFactory; /** * Constructor for AxisSecureSocketFactory. * @param attributes ??? */ public AxisSecureSocketFactory(Hashtable attributes) { super(attributes); } /** * Initializes the factory by setting the connection parameters to be used for * setting the secure socket factory, and by setting the system property * axis.socketSecureFactory. * @param connParam ConnectionParameter to derive the * secure socket factory from */ public static void initialize(SSLSocketFactory ssf) throws IOException, GeneralSecurityException { Logger.debug("Initialize AxisSecureSocketFactory"); sslFactory = ssf; } /** * 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 (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 (!replyStr.startsWith("HTTP/1.0 200") && !replyStr.startsWith("HTTP/1.1 200")) { 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")); } return sslSocket; } }