summaryrefslogblamecommitdiffstats
path: root/dozentenmodul/src/main/java/org/openslx/dozmod/util/ProxyConfigurator.java
blob: 8011eaec7750e3a0424a5e599b6986fb36c86a61 (plain) (tree)
1
2
3
4
5
6
7
8
9
                                
 

                           
                              
                       
                               
                                                   
 


                                     
                                    
                                                   
                                              












                                                                    


                                           

                                                  
                                                       
                                              
                             


                                                         

                                            






                         
                                



                                
                                                                                           
        

                                                                                                   


                                 
                                   
                                                                                                                       








                                                                                                
                                               



                                                                                    

                                                                                                   
                               
                 







                                                                                                                        
                                                       

                                                                       
                                                                                                          
                                               




                                                               
                                                              

                                              
                                                              

                                              
                                                               
                                 
                                                                                                             






                                                                           
                                                                                               
                                                   

                                                                               
 



                                                                                         
                                                                


                                                             
                                                                  

                                                           



                                                                         
        


















                                                                                   
                                                                                                               





























                                                                                                               
                                                  




                                                                    
                                                                                
                                                 
                                                                                   

                                                                                                                     
                     
                                                                             






                                                                                                               



























                                                                                                        
        
 
package org.openslx.dozmod.util;

import java.io.IOException;
import java.net.Proxy;
import java.net.ProxySelector;
import java.net.Socket;
import java.text.MessageFormat;
import java.util.concurrent.atomic.AtomicReference;

import org.apache.http.HttpException;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.routing.HttpRoute;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.impl.conn.SystemDefaultRoutePlanner;
import org.apache.http.protocol.HttpContext;
import org.apache.http.ssl.SSLContexts;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.openslx.bwlp.thrift.iface.MasterServer;
import org.openslx.dozmod.App;
import org.openslx.dozmod.authentication.ShibbolethEcp;
import org.openslx.thrifthelper.ThriftManager;
import org.openslx.util.Util;

import com.btr.proxy.search.ProxySearch;
import com.btr.proxy.search.wpad.WpadProxySearchStrategy;
import com.btr.proxy.util.Logger.LogBackEnd;
import com.btr.proxy.util.Logger.LogLevel;

/**
 * Configures the proxy
 * 
 * @author Jonathan Bauer
 */

public class ProxyConfigurator {

	/**
	 * Logger for this class
	 */
	private final static Logger LOGGER = LogManager.getLogger(ProxyConfigurator.class);
	
	private static AtomicReference<CloseableHttpClient> apacheClient = new AtomicReference<>();
	
	/**
	 * Initialization method.
	 */
	public static void init() {
		MasterServer.Client masterClient = ThriftManager.getNewMasterClient(null, App.getMasterServerAddress(),
				App.THRIFT_PORT, 4000);
		if (masterClient != null) {
			try {
				masterClient.ping();
				try {
					masterClient.getInputProtocol().getTransport().close();
					masterClient.getOutputProtocol().getTransport().close();
				} catch (Throwable e) {
				}
			} catch (Exception e) {
				masterClient = null;
			}
		}
		// To be discussed: Let's bail out if the master server is reachable
		if (masterClient != null && testHttpsMaster()) {
			LOGGER.info("Not setting up proxy because master server seems reachable.");
			return;
		}
		
		// Build special HTTP Client Builder for apache and try again
		apacheClient.set(createSlxBuilder().build());
		if (masterClient != null && testHttpsMaster()) {
			LOGGER.info("Not setting up proxy since master server is reachable with custom client builder");
			return;
		}
		
		// first setup the logger of proxy-vole
		com.btr.proxy.util.Logger.setBackend(new LogBackEnd() {

			public void log(Class<?> clazz, LogLevel loglevel, String msg, Object... params) {
				Level priority;
				switch (loglevel) {
				case ERROR:
					priority = Level.ERROR;
					break;
				case WARNING:
					priority = Level.WARN;
					break;
				case INFO:
					priority = Level.INFO;
					break;
				default:
					priority = Level.DEBUG;
				}
				LogManager.getLogger(clazz).log(priority, MessageFormat.format(msg, params));
			}

			public boolean isLogginEnabled(LogLevel logLevel) {
				return true;
			}
		});

		LOGGER.info("Master server not directly reachable; trying to determine proxy");
		// try to find local proxy settings
		ProxySearch proxySearch = ProxySearch.getDefaultProxySearch();
		ProxySelector myProxySelector = proxySearch.getProxySelector();

		if (myProxySelector == null) {
			// didn't work, try WPAD detection
			LOGGER.error("No suitable proxy settings found, trying WPAD...");
			WpadProxySearchStrategy ss = new WpadProxySearchStrategy();
			myProxySelector = ss.getProxySelector();
		}
		// final check to see if WPAD actually worked
		if (myProxySelector != null) {
			ProxySelector.setDefault(myProxySelector);
			LOGGER.debug("Proxy initialised.");
			Util.sleep(10);
		} else {
			LOGGER.error("Could not find a suitable proxy!");
		}
	}
	
	/**
	 * Get the HttpClient to be used with apache
	 * httpclient.
	 *
	 * @return client
	 */
	public static CloseableHttpClient getClient() {
		CloseableHttpClient inst = apacheClient.get();
		if (inst != null)
			return inst;
		inst = createShortTimeoutBuilder().build();
		apacheClient.compareAndSet(null, inst);
		return inst;
	}

	private static SSLConnectionSocketFactory createSslFactory() {
		// TODO: Geht nich
		for (String proto : new String[] { "TLSv1.2", "TLSv1.1", "TLS" }) {
		try {
			return new SSLConnectionSocketFactory(SSLContexts.custom().setProtocol(proto).build());
		} catch (Exception e) {
			LOGGER.warn(proto + " not available", e);
		}
		}
		return SSLConnectionSocketFactory.getSystemSocketFactory();
	}

	private static HttpClientBuilder createShortTimeoutBuilder() {
		HttpClientBuilder builder = HttpClientBuilder.create().setSSLSocketFactory(createSslFactory());
		builder.setDefaultSocketConfig(SocketConfig.custom().setSoTimeout(8000).build());
		PoolingHttpClientConnectionManager pm = new PoolingHttpClientConnectionManager();
		pm.setDefaultMaxPerRoute(4);
		builder.setConnectionManager(pm);
		return builder;
	}

	private static HttpClientBuilder createSlxBuilder() {
		HttpClientBuilder builder = HttpClientBuilder.create();
		builder.setRoutePlanner(new SlxRoutePlanner(null));
		builder.setDefaultSocketConfig(SocketConfig.custom().setSoTimeout(8000).build());
		Registry<ConnectionSocketFactory> csf = RegistryBuilder.<ConnectionSocketFactory> create()
				.register("http", new SlxSocketFactory())
				.register("https", createSslFactory())
				.build();
		PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(csf);
		cm.setDefaultMaxPerRoute(4);
		builder.setConnectionManager(cm);
		return builder;
	}

	private static boolean testHttpsMaster() {
		RequestConfig requestConfig = RequestConfig.custom()
				.setConnectionRequestTimeout(3000)
				.setConnectTimeout(3000)
				.setSocketTimeout(3000)
				.build();
		HttpGet httpGet = new HttpGet(ShibbolethEcp.BWLP_SP.toString());
		httpGet.setConfig(requestConfig);
		httpGet.setHeader("Accept", "text/html, application/vnd.paos+xml");
		httpGet.setHeader("PAOS",
				"ver=\"urn:liberty:paos:2003-08\";\"urn:oasis:names:tc:SAML:2.0:profiles:SSO:ecp\"");
		try {
			HttpResponse response = getClient().execute(httpGet);
			LOGGER.debug("Master server replies with " + response.getStatusLine().getStatusCode());
			return response.getStatusLine().getStatusCode() == 200;
		} catch (Exception e) {
			LOGGER.debug("Cannot reach master server via HTTPS", e);
			return false;
		}
	}

	private static class SlxSocketFactory extends PlainConnectionSocketFactory {
		@Override
		public Socket createSocket(HttpContext context) throws IOException {
			Object obj = context.getAttribute("openslx.l7proxy");
			if (obj instanceof HttpRoute) {
				HttpRoute route = (HttpRoute) obj;
				if (route != null && route.getProxyHost() != null) {
					return new Socket(Proxy.NO_PROXY);
				}
			}
			return new Socket();
		}
	}

	private static class SlxRoutePlanner extends SystemDefaultRoutePlanner {
		public SlxRoutePlanner(ProxySelector proxySelector) {
			super(proxySelector);
		}

		@Override
		public HttpRoute determineRoute(HttpHost host, HttpRequest request, HttpContext context)
				throws HttpException {
			HttpRoute route = super.determineRoute(host, request, context);
			context.setAttribute("openslx.l7proxy", route);
			return route;
		}
	}
	
}