Package com.notnoop.apns.internal

Source Code of com.notnoop.apns.internal.TlsTunnelBuilder

/*
* Copyright 2012, Square, Inc.
* Copyright 2012, Mahmood Ali.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   * Redistributions in binary form must reproduce the above
*     copyright notice, this list of conditions and the following disclaimer
*     in the documentation and/or other materials provided with the
*     distribution.
*   * Neither the name of Mahmood Ali. nor the names of its
*     contributors may be used to endorse or promote products derived from
*     this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.notnoop.apns.internal;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ProtocolException;
import java.net.Proxy;
import java.net.Socket;
import javax.net.ssl.SSLSocketFactory;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import org.apache.commons.httpclient.ConnectMethod;
import org.apache.commons.httpclient.NTCredentials;
import org.apache.commons.httpclient.ProxyClient;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthScope;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Establishes a TLS connection using an HTTP proxy. See <a
* href="http://www.ietf.org/rfc/rfc2817.txt">RFC 2817 5.2</a>. This class does
* not support proxies requiring a "Proxy-Authorization" header.
*/
public final class TlsTunnelBuilder {
   
    private static final Logger logger = LoggerFactory.getLogger(TlsTunnelBuilder.class);
   
    public Socket build(SSLSocketFactory factory, Proxy proxy, String proxyUsername, String proxyPassword, String host, int port)
            throws IOException {
        boolean success = false;
        Socket proxySocket = null;
        try {
            logger.debug("Attempting to use proxy : " + proxy.toString());
            InetSocketAddress proxyAddress = (InetSocketAddress) proxy.address();
            proxySocket = makeTunnel(host, port, proxyUsername, proxyPassword, proxyAddress);

            // Handshake with the origin server.
            if(proxySocket ==  null) {
                throw new ProtocolException("Unable to create tunnel through proxy server.");
            }
            Socket socket = factory.createSocket(proxySocket, host, port, true /* auto close */);
            success = true;
            return socket;
        } finally {
            if (!success) {
                Utilities.close(proxySocket);
            }
        }
    }

    @SuppressFBWarnings(value = "VA_FORMAT_STRING_USES_NEWLINE",
            justification = "use <CR><LF> as according to RFC, not platform-linefeed")
    Socket makeTunnel(String host, int port, String proxyUsername,
            String proxyPassword, InetSocketAddress proxyAddress) throws IOException {
        if(host == null || port < 0 || host.isEmpty() || proxyAddress == null){
            throw new ProtocolException("Incorrect parameters to build tunnel.");  
        }
        logger.debug("Creating socket for Proxy : " + proxyAddress.getAddress() + ":" + proxyAddress.getPort());
        Socket socket;
        try {
            ProxyClient client = new ProxyClient();
            client.getParams().setParameter("http.useragent", "java-apns");
            client.getHostConfiguration().setHost(host, port);
            String proxyHost = proxyAddress.getAddress().toString().substring(0, proxyAddress.getAddress().toString().indexOf("/"));
            client.getHostConfiguration().setProxy(proxyHost, proxyAddress.getPort());
           
       
            ProxyClient.ConnectResponse response = client.connect();
            socket = response.getSocket();
            if (socket == null) {
                ConnectMethod method = response.getConnectMethod();
                // Read the proxy's HTTP response.
                if(method.getStatusLine().toString().matches("HTTP/1\\.\\d 407 Proxy Authentication Required")) {
                    // Proxy server returned 407. We will now try to connect with auth Header
                    if(proxyUsername != null && proxyPassword != null) {
                        socket = AuthenticateProxy(method, client,proxyHost, proxyAddress.getPort(),
                                proxyUsername, proxyPassword);
                    } else {
                        throw new ProtocolException("Socket not created: " + method.getStatusLine());
                    }
                }            
            }
           
        } catch (Exception e) {
            throw new ProtocolException("Error occurred while creating proxy socket : " + e.toString());
        }
        if (socket != null) {
            logger.debug("Socket for proxy created successfully : " + socket.getRemoteSocketAddress().toString());
        }
        return socket;
    }
   
    private Socket AuthenticateProxy(ConnectMethod method, ProxyClient client,
            String proxyHost, int proxyPort,
            String proxyUsername, String proxyPassword) throws IOException {  
        if(method.getProxyAuthState().getAuthScheme().getSchemeName().equalsIgnoreCase("ntlm")) {
            // If Auth scheme is NTLM, set NT credentials with blank host and domain name
            client.getState().setProxyCredentials(new AuthScope(proxyHost, proxyPort),
                            new NTCredentials(proxyUsername, proxyPassword,"",""));
        } else {
            // If Auth scheme is Basic/Digest, set regular Credentials
            client.getState().setProxyCredentials(new AuthScope(proxyHost, proxyPort),
                    new UsernamePasswordCredentials(proxyUsername, proxyPassword));
        }
       
        ProxyClient.ConnectResponse response = client.connect();
        Socket socket = response.getSocket();
       
        if (socket == null) {
            method = response.getConnectMethod();
            throw new ProtocolException("Proxy Authentication failed. Socket not created: "
                    + method.getStatusLine());
        }
        return socket;
    }
   
}
TOP

Related Classes of com.notnoop.apns.internal.TlsTunnelBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.