Tomcat 6 - Java proxy tunneling failed on Windows - ERROR - 407 - java

I've created a class which deal with HTTP proxy to connect with remote server for web services. Deployed on Tomcat 6, on Windows server 2008 and called in servlet.
It is working perfectly with $CATALINA_HOME\bin\tomcat6.exe, i.e. on cmd.
It couldn't go through proxy with windows service utility, i.e. $CATALINA_HOME\bin\tomcat6w.exe.
Both are reading same configurations, but behaving differently while establishing connection with remote server through proxy.
I've found few way to get proxy settings, as follows:
Proxy Vole utility jar (proxy-vole_20131209.jar).
java.net.useSystemProxies set to true and fetch proxy info.
Reading PAC with Java code (deploy.jar).
Passing constant hostname/IP and port.
All of the above work well with $CATALINA_HOME\bin\tomcat6.exe, other then PAC reading as it fetches private IP instead or public IP (well can ignore for now as long as I know exact hostname and port).
Note: there is no proxy credentials I've found and it is working without it as well from cmd.
But when I try to run it with tomcat windows service utility, i.e. $CATALINA_HOME\bin\tomcat6w.exe it fails to connect remote server and throws exception:
java.io.IOException: Unable to tunnel through proxy. Proxy returns "HTTP/1.1 407 Proxy Authentication Required"
Please find my Class, it retry each case one by one all above mentioned (PAC one skipped).
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.ProxySelector;
import java.net.SocketAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.List;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import com.btr.proxy.search.ProxySearch;
import com.btr.proxy.search.ProxySearch.Strategy;
import com.btr.proxy.util.PlatformUtil;
import com.btr.proxy.util.PlatformUtil.Platform;
import com.sun.deploy.net.proxy.BrowserProxyInfo;
import com.sun.deploy.net.proxy.DummyAutoProxyHandler;
import com.sun.deploy.net.proxy.ProxyConfigException;
import com.sun.deploy.net.proxy.ProxyInfo;
import com.sun.deploy.net.proxy.ProxyType;
public class ProxyPacManager {
public static void main(String args[]) throws Exception{
getProxy();
}
public static Proxy getProxy(){
String almProtocol = Constants.getPropereties().getProperty("dashboard.alm.protocol");
String almHost = Constants.getPropereties().getProperty("dashboard.alm.host");
String almPort = Constants.getPropereties().getProperty("dashboard.alm.port");
String urlStr = almProtocol+almHost+":"+almPort;
Proxy proxy = null;
List<Proxy> proxyList = null;
String successMsg = "Proxy not found.";
try{
System.out.println("Trying to connect through Proxy Vole plugin.");
proxyList = getSSLCertificateAutoProxy(urlStr);
proxy = getProxyTested(proxyList, urlStr);
successMsg="Successfully connected through Proxy Vole plugin.";
} catch(Exception ex){
System.out.println("Proxy Vole plugin didn't work."+ex.getMessage());
try{
System.out.println("Trying to connect through java.net.useSystemProxies Proxy.");
proxyList = getSSLCertificateSysProxy(urlStr);
proxy = getProxyTested(proxyList, urlStr);
successMsg="Successfully connected through java.net.useSystemProxies Proxy.";
} catch(Exception ex1){
System.out.println("java.net.useSystemProxies didn't work."+ex1.getMessage());
try{
/*System.out.println("Trying to connect through PAC Proxy.");
proxyList = getSSLCertificatePACProxy(urlStr);
proxy = getProxyTested(proxyList, urlStr);
successMsg="Successfully connected through PAC Proxy.";*/
throw new Exception("Bypass PAC Proxy for testing.");
}catch(Exception ex2){
System.out.println("PAC Proxy read didn't work."+ex2.getMessage());
try{
System.out.println("Trying to connect through Constant Proxy.");
proxyList = getSSLCertificateConstantProxy();
proxy = getProxyTested(proxyList, urlStr);
successMsg="Successfully connected through Constant Proxy.";
}catch(Exception ex3){
System.out.println("Constant Proxy read didn't work."+ex3.getMessage());
proxyList = new ArrayList<Proxy>();
proxyList.add(Proxy.NO_PROXY);
proxy = getProxyTested(proxyList, urlStr);
successMsg = "Connected with NO_PROXY";
}
}
}
}
System.out.println(successMsg);
return proxy;
}
private static Proxy getProxyTested(List<Proxy> proxyList, String urlStr){
if (proxyList != null && !proxyList.isEmpty()) {
for (Proxy proxy : proxyList) {
SocketAddress address = proxy.address();
if (address instanceof InetSocketAddress) {
System.out.println("Trying to connect through proxy: "+((InetSocketAddress) address).getHostName()+":"+((InetSocketAddress) address).getPort());
try {
URLConnection connection = new URL(urlStr).openConnection(proxy);
connection.connect();
System.out.println("Connected through proxy: "+((InetSocketAddress) address).getHostName()+":"+((InetSocketAddress) address).getPort());
return proxy;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
return null;
}
private static List<Proxy> getSSLCertificateConstantProxy() throws Exception{
setCertificate();
List<Proxy> proxyList = new ArrayList<Proxy>();
String proxyHost = Constants.getPropereties().getProperty("dashboard.alm.proxy.host");
InetAddress hostIp = InetAddress.getByName(proxyHost);
int proxyPort = Integer.parseInt(Constants.getPropereties().getProperty("dashboard.alm.proxy.port"));
//Create your proxy and setup authentication for it.
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(hostIp.getHostAddress(), proxyPort));
//Setup authentication for your proxy.
/*Authenticator.setDefault(new Authenticator() {
#Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("<user>", "<password>".toCharArray());
}
});*/
proxyList.add(proxy);
return proxyList;
}
private static void setCertificate() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, KeyManagementException{
//First, load the key store file
String jksFile = Constants.getPropereties().getProperty("dashboard.alm.certificate");
InputStream trustStream = new FileInputStream(jksFile);
String jksPass = Constants.getPropereties().getProperty("dashboard.alm.certificate.pass");
char[] trustPassword = jksPass.toCharArray();
//Initialize a KeyStore
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(trustStream, trustPassword);
//Initialize TrustManager objects.
TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustFactory.init(trustStore);
TrustManager[] trustManagers = trustFactory.getTrustManagers();
//Create a new SSLContext, load the TrustManager objects into it and set it as default.
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustManagers, null);
SSLContext.setDefault(sslContext);
}
private static ProxyInfo[] getProxyInfo(String urlStr) throws ProxyConfigException, MalformedURLException{
String proxypac = Constants.getPropereties().getProperty("dashboard.alm.proxy.pac");
BrowserProxyInfo b = new BrowserProxyInfo();
/*WDefaultBrowserProxyConfig wd = new WDefaultBrowserProxyConfig();
BrowserProxyInfo b = wd.getBrowserProxyInfo(); */
b.setType(ProxyType.AUTO);
b.setAutoConfigURL(proxypac);
DummyAutoProxyHandler handler = new DummyAutoProxyHandler();
handler.init(b);
URL url = new URL(urlStr);
ProxyInfo[] ps = handler.getProxyInfo(url);
return ps;
}
public static List<Proxy> getSSLCertificateAutoProxy(String urlStr) throws Exception{
setCertificate();
/*ProxySearch proxySearch = ProxySearch.getDefaultProxySearch();*/
ProxySearch proxySearch = new ProxySearch();
proxySearch.setPacCacheSettings(32, 1000*60*5);
if (PlatformUtil.getCurrentPlattform() == Platform.WIN) {
proxySearch.addStrategy(Strategy.IE);
proxySearch.addStrategy(Strategy.FIREFOX);
proxySearch.addStrategy(Strategy.JAVA);
} else if (PlatformUtil.getCurrentPlattform() == Platform.LINUX) {
proxySearch.addStrategy(Strategy.GNOME);
proxySearch.addStrategy(Strategy.KDE);
proxySearch.addStrategy(Strategy.FIREFOX);
} else {
proxySearch.addStrategy(Strategy.OS_DEFAULT);
}
ProxySelector proxySelector = proxySearch.getProxySelector();
/*BufferedProxySelector cachedSelector = new BufferedProxySelector(32, 1000*60*5, proxySelector);*/
ProxySelector.setDefault(proxySelector);
//ProxySelector.setDefault(cachedSelector);
URI home = URI.create(urlStr);
//List<Proxy> proxyList = cachedSelector.select(home);
List<Proxy> proxyList = proxySelector.select(home);
return proxyList;
}
public static List<Proxy> getSSLCertificatePACProxy(String urlStr) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, KeyManagementException, ProxyConfigException{
List<Proxy> proxyList = new ArrayList<Proxy>();
setCertificate();
ProxyInfo[] ps = getProxyInfo(urlStr);
for(ProxyInfo p: ps){
String proxyHost = p.getProxy();
int proxyPort = p.getPort();
//Create your proxy and setup authentication for it.
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort));
//Setup authentication for your proxy.
/*Authenticator.setDefault(new Authenticator() {
#Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("<user>", "<password>".toCharArray());
}
});*/
proxyList.add(proxy);
}
return proxyList;
}
public static List<Proxy> getSSLCertificateSysProxy(String urlStr) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, KeyManagementException, ProxyConfigException, URISyntaxException{
setCertificate();
System.setProperty("java.net.useSystemProxies","true");
List<Proxy> proxyList = ProxySelector.getDefault().select(new URI(urlStr));
return proxyList;
}
}
Failure output of the class,
Trying to connect through java.net.useSystemProxies Proxy.
java.net.useSystemProxies didn't work.null
PAC Proxy read didn't work.Bypass PAC Proxy for testing.
Trying to connect through Constant Proxy.
Trying to connect through proxy: XX.XX.XXX.XX:8080 [Masked for security reasons]
java.io.IOException: Unable to tunnel through proxy. Proxy returns "HTTP/1.1 407 Proxy Authentication Required"
Please help me to get through the proxy with Tomcat 6 windows service utility.
Note: Windows security policy:
Network security: LAN Manager authentication level = Send NTLM response only

Please if someone have any solution for the issue let me know, ASAP.
I'll break the code for more understanding:
Get proxy by Proxy vole plugin/jar
public static List<Proxy> getSSLCertificateAutoProxy(String urlStr) throws Exception{
setCertificate();
/*ProxySearch proxySearch = ProxySearch.getDefaultProxySearch();*/
ProxySearch proxySearch = new ProxySearch();
proxySearch.setPacCacheSettings(32, 1000*60*5);
if (PlatformUtil.getCurrentPlattform() == Platform.WIN) {
proxySearch.addStrategy(Strategy.IE);
proxySearch.addStrategy(Strategy.FIREFOX);
proxySearch.addStrategy(Strategy.JAVA);
} else if (PlatformUtil.getCurrentPlattform() == Platform.LINUX) {
proxySearch.addStrategy(Strategy.GNOME);
proxySearch.addStrategy(Strategy.KDE);
proxySearch.addStrategy(Strategy.FIREFOX);
} else {
proxySearch.addStrategy(Strategy.OS_DEFAULT);
}
ProxySelector proxySelector = proxySearch.getProxySelector();
/*BufferedProxySelector cachedSelector = new BufferedProxySelector(32, 1000*60*5, proxySelector);*/
ProxySelector.setDefault(proxySelector);
//ProxySelector.setDefault(cachedSelector);
URI home = URI.create(urlStr);
//List<Proxy> proxyList = cachedSelector.select(home);
List<Proxy> proxyList = proxySelector.select(home);
return proxyList;
}
Get Proxy using java.net.useSystemProxies
public static List<Proxy> getSSLCertificateSysProxy(String urlStr) throws Exception{
setCertificate();
System.setProperty("java.net.useSystemProxies","true");
List<Proxy> proxyList = ProxySelector.getDefault().select(new URI(urlStr));
return proxyList;
}
Get proxy from PAC:
public static List<Proxy> getSSLCertificatePACProxy(String urlStr) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, KeyManagementException, ProxyConfigException{
setCertificate();
List<Proxy> proxyList = new ArrayList<Proxy>();
String proxypac = "<http://mydomain/proxy.pac>";
BrowserProxyInfo b = new BrowserProxyInfo();
/*WDefaultBrowserProxyConfig wd = new WDefaultBrowserProxyConfig();
BrowserProxyInfo b = wd.getBrowserProxyInfo(); */
b.setType(ProxyType.AUTO);
b.setAutoConfigURL(proxypac);
DummyAutoProxyHandler handler = new DummyAutoProxyHandler();
handler.init(b);
URL url = new URL(urlStr);
ProxyInfo[] ps = handler.getProxyInfo(url);
for(ProxyInfo p: ps){
String proxyHost = p.getProxy();
int proxyPort = p.getPort();
//Create your proxy and setup authentication for it.
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort));
//Setup authentication for your proxy.
/*Authenticator.setDefault(new Authenticator() {
#Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("<user>", "<password>".toCharArray());
}
});*/
proxyList.add(proxy);
}
return proxyList;
}
Get proxy by directly passing known proxy hostname and port
private static List<Proxy> getSSLCertificateConstantProxy() throws Exception{
setCertificate();
List<Proxy> proxyList = new ArrayList<Proxy>();
String proxyHost = "<myproxy.hostname>";
InetAddress hostIp = InetAddress.getByName(proxyHost);
int proxyPort = Integer.parseInt("<myProxyPort>"));
//Create your proxy and setup authentication for it.
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(hostIp.getHostAddress(), proxyPort));
//Setup authentication for your proxy.
/*Authenticator.setDefault(new Authenticator() {
#Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("<user>", "<password>".toCharArray());
}
});*/
proxyList.add(proxy);
return proxyList;
}

Related

javax.net.ssl.SSLException: unexpected_message

We're trying to make secure http communication between client an server.
The server provided the certificates, we took them, install them and we start running, the point is to exchange an exact number of messages simultaneously between the client and server consecutively, the problem that's driving us crazy is that between the requests, at SSLHANDSHAKE we get randomly the exception javax.net.ssl.SSLException: Received fatal alert: unexpected_message exactly at ServerHello handshake phase, and i don't know how or why this is happening while it keeps working fine for 98% of the other requests.
it crashes at step 2.
Transporter.java : This is the class responsible for sending and receiving the data.
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.security.KeyStore;
import java.util.ResourceBundle;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
public class Transporter {
private static ResourceBundle resource = ResourceBundle.getBundle("resourece_00");
private static final String keystore = resource.getString("server_keystore");
private static final String truststore = resource.getString("server_truststore");
private static final String keypass = resource.getString("server_keystore_pwd");
private static final String trustpass = resource.getString("server_truststore_pwd");
// secure channel variables
private static SSLSocketFactory sslSocketFactory = null;
public Transporter() {
// setupSocketFactory();
}
static {
try {
String protocol = "TLS";
String type = "JKS";
String algorithm = KeyManagerFactory.getDefaultAlgorithm();
String trustAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
// create and initialize an SSLContext object
SSLContext sslContext = SSLContext.getInstance(protocol);
sslContext.init(getKeyManagers(type, algorithm), getTrustManagers(type, trustAlgorithm), null);
// obtain the SSLSocketFactory from the SSLContext
sslSocketFactory = sslContext.getSocketFactory();
} catch (Exception e) {
e.printStackTrace();
}
}
private static KeyStore getStore(String type, String filename, String pwd) throws Exception {
KeyStore ks = KeyStore.getInstance(type);
InputStream istream = null;
try {
File ksfile = new File(filename);
istream = new FileInputStream(ksfile);
ks.load(istream, pwd != null ? pwd.toCharArray() : null);
} finally {
if (istream != null) {
istream.close();
}
}
return ks;
}
private static KeyManager[] getKeyManagers(String type, String algorithm) throws Exception {
KeyStore ks = getStore(type, keystore, keypass);
KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm);
kmf.init(ks, keypass.toCharArray());
return kmf.getKeyManagers();
}
private static TrustManager[] getTrustManagers(String type, String algorithm) throws Exception {
KeyStore ts = getStore(type, truststore, trustpass);
TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
tmf.init(ts);
return tmf.getTrustManagers();
}
public String sendToVD(String msg, String urll, Long timeOut) {
byte[] bytes = msg.getBytes();
HttpsURLConnection sconn = null;
URL url = null;
OutputStream out = null;
BufferedReader read = null;
String recu = null;
try {
url = new URL(urll);
sconn = (HttpsURLConnection) url.openConnection();
sconn.setHostnameVerifier(new HostnameVerifier() {
public boolean verify(String hostname, SSLSession sslSession) {
return true;
}
});
sconn.setSSLSocketFactory(sslSocketFactory);
// sconn.setReadTimeout((timeOut.intValue()) * 1000);// set timeout
sconn.setRequestMethod("POST");
sconn.addRequestProperty("Content-Length", "" + bytes.length);
sconn.setRequestProperty("Content-Type", "application/xml; charset=utf-8");
sconn.setDoOutput(true);
sconn.setDoInput(true);
// send POST data
// This is the crash location
out = sconn.getOutputStream();
// OutputStreamWriter osw = new OutputStreamWriter(out, "UTF-8");
out.write(bytes);
out.flush();
// logger.info("flush!!!!!!!!!!!!!");
// out.close();
read = new BufferedReader(new InputStreamReader(sconn.getInputStream()));
String query = null;
recu = read.readLine();
while ((query = read.readLine()) != null) {
recu += query;
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (ProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
// close all connections here
if (out != null)
out.close();
if (read != null)
read.close();
if (sconn != null)
sconn.disconnect();
} catch (Exception ce) {
}
}
return recu;
}
}
The function sendToVD() does the main work of the exchange between the client and the server.
At Client-End :
A web application with JSF managing the front layer, spring managing the beans life cycle, the communication entry to the client is assured by Servlets.
The client is deployed in a RedHat Linux machine, all TLS_VERSIONS are enbaled, JDK_8.
At Server-Side: i can't post the detailed information about the target URL for security measures, but it follows the following pattern https://ip:port/path, and it supports TLS_v1.2.
Hope you can help me out.

debug ssl connection issues using GRPC Java client and NodeJS server

I am trying to connect a Java client to a NodeJS server using GRPC on a mac OS. I am consistently getting ssl handshake issues though I can connect with a sample JS client to the NodeJS server using the same certificates. Any thoughts on how to debug this further:
server logs:
chttp2_server.c:123] Handshaking failed: {"created":"#1489747510.536841000","description":"Handshake read failed","file":"../src/core/lib/security/transport/security_handshaker.c","file_line":238,"referenced_errors":[{"created":"#1489747510.536836000","description":"Socket closed","fd":27,"file":"../src/core/lib/iomgr/tcp_posix.c","file_line":249,"target_address":"ipv4:127.0.0.1:61964"}]}
client
public class Connection implements IConnection {
private static final Logger log = LogManager.getLogger(Connection.class.getName());
private final String host;
private final int port;
public Connection(String host, int port) {
this.host = host;
this.port = port;
}
/*public ManagedChannelBuilder getInsecure() {
return ManagedChannelBuilder.forAddress(host, port)
.usePlaintext(true);
}*/
public ManagedChannelBuilder getSecure() {
ManagedChannelBuilder<?> channelBuilder = null;
Optional<SslContext> optional = getSslContext();
if (optional.isPresent()) {
final SslContext sslContext = optional.get();
log.info("building channel for connection");
channelBuilder = NettyChannelBuilder.forAddress(host, port)
.overrideAuthority("localhost")
.negotiationType(NegotiationType.TLS)
.usePlaintext(false)
.sslContext(sslContext);
}
return channelBuilder;
}
private Optional<SslContext> getSslContext() {
SslContext sslContext = null;
Optional<ICertificateRepository> optional = getCertificates();
if (optional.isPresent()) {
final ICertificateRepository certificateRepo = optional.get();
final File publicCert = certificateRepo.getPublicCert();
final File clientCert = certificateRepo.getClientCert();
final File clientKey = certificateRepo.getClientKey();
try {
java.security.Security.addProvider(
new org.bouncycastle.jce.provider.BouncyCastleProvider()
);
log.info("attempting to create the ssl context");
sslContext = GrpcSslContexts.forClient()
.startTls(true)
.sslProvider(defaultSslProvider())
.trustManager(publicCert)
.keyManager(clientCert, clientKey)
.ciphers(null) //testing
.build();
} catch (SSLException se) {
log.error("ssl exception before connection attempt {}", se);
}
}
Optional<SslContext> sslOptional = Optional.ofNullable(sslContext);
return sslOptional;
}
private Optional<ICertificateRepository> getCertificates() {
ICertificateRepository certificateRepo = null;
try {
certificateRepo = new CertificateRepository();
log.info("path: {} | {} | {}", certificateRepo.getPublicCert().getAbsolutePath(),
certificateRepo.getPublicCert().exists(), certificateRepo.getPublicCert().isFile());
log.info("clientCert: {} | {}", certificateRepo.getClientCert().getAbsolutePath(),
certificateRepo.getClientCert().exists());
log.info("clientKey: {} | {}", certificateRepo.getClientKey().getAbsolutePath(),
certificateRepo.getClientKey().exists());
} catch (Exception fe) {
log.error("unable to read SSL certificates in keys directory");
}
Optional<ICertificateRepository> optional = Optional.ofNullable(certificateRepo);
return optional;
}
private static SslProvider defaultSslProvider() {
log.info("is OpenSsl available: {}", OpenSsl.isAvailable());
return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK;
}
}
the certificate file locations are correct and the cert repository is created as:
public CertificateRepository() {
final ClassLoader classLoader = getClass().getClassLoader();
try {
this.publicCert = new File(classLoader.getResource(
new StringBuilder(MonetagoProps.BASE_DIR_FOR_CERTS)
.append(TestProps.CERT_NAME)
.toString()).getFile());
this.clientCert = new File(classLoader.getResource(
new StringBuilder(MonetagoProps.BASE_DIR_FOR_CERTS)
.append(MonetagoProps.CLIENT_CERT_NAME)
.toString()).getFile());
this.clientKey = new File(classLoader.getResource(
new StringBuilder(TestProps.BASE_DIR_FOR_CERTS)
.append(TestProps.CLIENT_KEY_NAME)
.toString()).getFile());
} catch (Exception fe) {
log.error("unable to read ssl certificate files for testConnection");
throw new IllegalStateException("unable to read ssl certificate files for test Connection");
}
}
I simply commented out the usePlaintext(false) call on the channel builder and was able to establish the SSL connection with the server.
channelBuilder = NettyChannelBuilder.forAddress(host, port)
.overrideAuthority("localhost")
.negotiationType(NegotiationType.TLS)
**//.usePlaintext(false)**
.sslContext(sslContext);

How to implement TLS V1.1 and V1.2 in my android studio application?

I've already bought a SSL certificated in my hosting, but i don't know how to implement in my java code side (using Android Studio).
This is my TLSSocketFactory.java (I copied this class from another page and I put it in my java code)
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
public class TLSSocketFactory extends SSLSocketFactory {
private SSLSocketFactory internalSSLSocketFactory;
public TLSSocketFactory() throws KeyManagementException, NoSuchAlgorithmException {
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, null, null);
internalSSLSocketFactory = context.getSocketFactory();
}
#Override
public String[] getDefaultCipherSuites() {
return internalSSLSocketFactory.getDefaultCipherSuites();
}
#Override
public String[] getSupportedCipherSuites() {
return internalSSLSocketFactory.getSupportedCipherSuites();
}
#Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose));
}
#Override
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port));
}
#Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port, localHost, localPort));
}
#Override
public Socket createSocket(InetAddress host, int port) throws IOException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port));
}
#Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort));
}
private Socket enableTLSOnSocket(Socket socket) {
if(socket != null && (socket instanceof SSLSocket)) {
((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.1", "TLSv1.2"});
}
return socket;
}
}
And this is my methods to use get and post:
GET method:
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.nio.charset.Charset;
public class JSONParser {
public static JSONObject readJsonFromUrl(String url) throws IOException, JSONException {
InputStream is = new URL(url).openStream();
try {
BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
String jsonText = readAll(rd);
return new JSONObject(jsonText);
} finally {
is.close();
}
}
private static String readAll(Reader rd) throws IOException {
StringBuilder sb = new StringBuilder();
int cp;
while ((cp = rd.read()) != -1) {
sb.append((char) cp);
}
return sb.toString();
}
}
POST method:
public String performPostCall(String requestURL, HashMap<String, String> postDataParams) {
URL url;
StringBuffer response = new StringBuffer();
try {
url = new URL(requestURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(15000);
conn.setConnectTimeout(15000);
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(os, "UTF-8"));
writer.write(getPostDataString(postDataParams));
writer.flush();
writer.close();
os.close();
int responseCode=conn.getResponseCode();
if (responseCode == HttpsURLConnection.HTTP_OK) {
String line;
BufferedReader br=new BufferedReader(new InputStreamReader(conn.getInputStream()));
while ((line=br.readLine()) != null) {
response.append(line);
}
br.close();
}
else {
response.append("");
}
} catch (Exception e) {
e.printStackTrace();
}
return response.toString();
}
private String getPostDataString(HashMap<String, String> params) throws UnsupportedEncodingException {
StringBuilder result = new StringBuilder();
boolean first = true;
for(Map.Entry<String, String> entry : params.entrySet()){
if (first)
first = false;
else
result.append("&");
result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
result.append("=");
result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
}
return result.toString();
}
1. question N° 1: how can I mix my intance of TLSSocketFactory with my POST and GET request? Sorry for my noob question.
2. question N° 2: Have I make something in my web services? Or just getting my web services with the certificate is ok?
Thanks!
If your URL starts with https:// the returned connection is an HttpsUrlConnection on which you can set the used socket factory before connecting to the server:
TLSSocketFactory myTlsSocketFactory = new TLSSocketFactory();
...
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(myTlsSocketFactory);
You don't need a TLSSocketFactory, Android uses Apache Commons Http Client to manage that for you, see (Android - Sending HTTPS Get Request)
If you bought a certificate from a valid entity, that means the Certificate Chain is valid, to which you should not have any problems.
I recommend reading this
UPDATE I recommend using this library for HTTP Requests

How do I do TLS with BouncyCastle?

Does anybody know about examples of TLS with BouncyCastle? I was surprised by the lack of them on Internet. If there are really none, let's collect them as answers.
This is a very basic example, with server-only authentication and self-signed cert. The code is based on BC 1.49, mostly leightweight API:
ServerSocket serverSocket = new ServerSocket(SERVER_PORT);
final KeyPair keyPair = ...
final Certificate bcCert = new Certificate(new org.spongycastle.asn1.x509.Certificate[] {
new X509V3CertificateStrategy().selfSignedCertificateHolder(keyPair).toASN1Structure()});
while (true) {
Socket socket = serverSocket.accept();
TlsServerProtocol tlsServerProtocol = new TlsServerProtocol(
socket.getInputStream(), socket.getOutputStream(), secureRandom);
tlsServerProtocol.accept(new DefaultTlsServer() {
protected TlsSignerCredentials getRSASignerCredentials() throws IOException {
return tlsSignerCredentials(context);
}
});
new PrintStream(tlsServerProtocol.getOutputStream()).println("Hello TLS");
}
where
private TlsSignerCredentials tlsSignerCredentials(TlsContext context) throws IOException {
return new DefaultTlsSignerCredentials(context, bcCert,
PrivateKeyFactory.createKey(keyPair.getPrivate().getEncoded()));
}
This is the client code:
Socket socket = new Socket(<server IP>, SERVER_PORT);
TlsClientProtocol tlsClientProtocol = new TlsClientProtocol(
socket.getInputStream(), socket.getOutputStream());
tlsClientProtocol.connect(new DefaultTlsClient() {
public TlsAuthentication getAuthentication() throws IOException {
return new ServerOnlyTlsAuthentication() {
public void notifyServerCertificate(Certificate serverCertificate) throws IOException {
validateCertificate(serverCertificate);
}
};
}
});
String message = new BufferedReader(
new InputStreamReader(tlsClientProtocol.getInputStream())).readLine();
You need to use the input and output stream from tlsClient/ServerProtocol to read and write encrypted data (e.g. tlsClientProtocol.getInputStream()). Otherwise, if you used e.g. socket.getOutputStream(), you would just write unencrypted data.
How to implement validateCertificate? I am using self-signed certificates. This means I just look them up in the key-store without any certificate chains. This is how I create the key store:
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, password);
X509Certificate certificate = ...;
keyStore.setCertificateEntry(alias, certificate);
And this is the validation:
private void validateCertificate(org.spongycastle.crypto.tls.Certificate cert) throws IOException, CertificateException, KeyStoreException {
byte[] encoded = cert.getCertificateList()[0].getEncoded();
java.security.cert.Certificate jsCert =
CertificateFactory.getInstance("X.509").generateCertificate(new ByteArrayInputStream(encoded));
String alias = keyStore.getCertificateAlias(jsCert);
if(alias == null) {
throw new IllegalArgumentException("Unknown cert " + jsCert);
}
}
What is rather confusing, are the three different Certificate classes. You have to convert between them as shown above.
Scenario: Our production server is using JDK1.6. However customer server is upgraded to only communicate in TLS 1.2. SSL Communication between both servers is broken. But we cannot simply upgrade JDK6 to 8 (which is supporting TLS 1.2 by default) because this will cause other libraries compatibility issue.
The following sample code uses jdk1.6.0_45 and bcprov-jdk15on-153.jar (Bouncy Castle SIGNED JAR FILES) to connect to any server using TLS.
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.Socket;
import org.bouncycastle.crypto.tls.CertificateRequest;
import org.bouncycastle.crypto.tls.DefaultTlsClient;
import org.bouncycastle.crypto.tls.TlsAuthentication;
import org.bouncycastle.crypto.tls.TlsClientProtocol;
import org.bouncycastle.crypto.tls.TlsCredentials;
public class TestHttpClient {
// Reference: http://boredwookie.net/index.php/blog/how-to-use-bouncy-castle-lightweight-api-s-tlsclient/
// bcprov-jdk15on-153.tar\src\org\bouncycastle\crypto\tls\test\TlsClientTest.java
public static void main(String[] args) throws Exception {
java.security.SecureRandom secureRandom = new java.security.SecureRandom();
Socket socket = new Socket(java.net.InetAddress.getByName("www.google.com"), 443);
TlsClientProtocol protocol = new TlsClientProtocol(socket.getInputStream(), socket.getOutputStream(),secureRandom);
DefaultTlsClient client = new DefaultTlsClient() {
public TlsAuthentication getAuthentication() throws IOException {
TlsAuthentication auth = new TlsAuthentication() {
// Capture the server certificate information!
public void notifyServerCertificate(org.bouncycastle.crypto.tls.Certificate serverCertificate) throws IOException {
}
public TlsCredentials getClientCredentials(CertificateRequest certificateRequest) throws IOException {
return null;
}
};
return auth;
}
};
protocol.connect(client);
java.io.OutputStream output = protocol.getOutputStream();
output.write("GET / HTTP/1.1\r\n".getBytes("UTF-8"));
output.write("Host: www.google.com\r\n".getBytes("UTF-8"));
output.write("Connection: close\r\n".getBytes("UTF-8")); // So the server will close socket immediately.
output.write("\r\n".getBytes("UTF-8")); // HTTP1.1 requirement: last line must be empty line.
output.flush();
java.io.InputStream input = protocol.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
String line;
while ((line = reader.readLine()) != null)
{
System.out.println(line);
}
}
}
Sample output shows that JDK 6 can obtain the server page in TLS, rather than some SSL Exception:
HTTP/1.1 302 Found
Cache-Control: private
Content-Type: text/html; charset=UTF-8
Location: https://www.google.com.sg/?gfe_rd=cr&ei=WRgeVovGEOTH8Afcx4XYAw
Content-Length: 263
Date: Wed, 14 Oct 2015 08:54:49 GMT
Server: GFE/2.0
Alternate-Protocol: 443:quic,p=1
Alt-Svc: quic="www.google.com:443"; p="1"; ma=600,quic=":443"; p="1"; ma=600
Connection: close
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>302 Moved</TITLE></HEAD><BODY>
<H1>302 Moved</H1>
The document has moved
here.
</BODY></HTML>
One more example, built on top of the server-only auth answer: TLS with self-signed certs with client authentication (I am showing just the changed parts). This is the server part:
tlsServerProtocol.accept(new DefaultTlsServer() {
protected TlsSignerCredentials getRSASignerCredentials() throws IOException {
return tlsSignerCredentials(context);
}
public void notifyClientCertificate(Certificate clientCertificate) throws IOException {
validateCertificate(clientCertificate);
}
public CertificateRequest getCertificateRequest() {
return new CertificateRequest(new short[] { ClientCertificateType.rsa_sign }, new Vector<Object>());
}
});
And this is the client part:
tlsClientProtocol.connect(new DefaultTlsClient() {
public TlsAuthentication getAuthentication() throws IOException {
return new TlsAuthentication() {
public void notifyServerCertificate(Certificate serverCertificate) throws IOException {
validateCertificate(serverCertificate);
}
public TlsCredentials getClientCredentials(CertificateRequest certificateRequest) throws IOException {
return tlsSignerCredentials(context);
}
};
}
});

HTTPS POST using HttpClient API opening 2 sockets

After a lot of R&D and googling, not able to troubleshoot my problem.
Environment Setup
Web Server (Tomcat 6.0.20) --> Proxy Server (Windows Server 2007) --> Thirdy part host
We have application, which does online payment transaction, after completion of this transaction, we want to send status of transaction to third party server. So posting data to third part server from our web server is opening 2 sockets for one transaction at proxy server, but when we check at web server it has created only one socket. SO why 2 socket at proxy server.
Below is my sample code
import javax.net.ssl.*;
import javax.net.SocketFactory;
import java.net.*;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.util.Hashtable;
import java.math.BigInteger;
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.protocol.*;
public class HTTPPostDemo {
private String privateKey;
private String host;
private int port;
private String userName;
private Header[] headers = null;
public class MySSLSocketFactory implements SecureProtocolSocketFactory {
private TrustManager[] getTrustManager() {
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
}
};
return trustAllCerts;
}
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
TrustManager[] trustAllCerts = getTrustManager();
try {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
SocketFactory socketFactory = HttpsURLConnection.getDefaultSSLSocketFactory();
return socketFactory.createSocket(host, port);
} catch (Exception ex) {
throw new UnknownHostException("Problems to connect " + host + ex.toString());
}
}
public Socket createSocket(Socket socket, String host, int port, boolean flag) throws IOException, UnknownHostException {
TrustManager[] trustAllCerts = getTrustManager();
try {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
SocketFactory socketFactory = HttpsURLConnection.getDefaultSSLSocketFactory();
return socketFactory.createSocket(host, port);
} catch (Exception ex) {
throw new UnknownHostException("Problems to connect " + host + ex.toString());
}
}
public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort) throws IOException, UnknownHostException {
TrustManager[] trustAllCerts = getTrustManager();
try {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
SocketFactory socketFactory = HttpsURLConnection.getDefaultSSLSocketFactory();
return socketFactory.createSocket(host, port, clientHost, clientPort);
} catch (Exception ex) {
throw new UnknownHostException("Problems to connect " + host + ex.toString());
}
}
}
public SslClient(String host, int port, String userName, String privateKey) {
this.host = host;
this.port = port;
this.userName = userName;
this.privateKey = privateKey;
}
protected String md5Sum(String str) {
String sum = new String();
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
sum = String.format("%032x", new BigInteger(1, md5.digest(str.getBytes())));
} catch (Exception ex) {
}
return sum;
}
public String getSignature(String xml) {
return md5Sum(md5Sum(xml + privateKey) + privateKey);
}
public String sendRequest(String xml) throws Exception {
HttpClient client = new HttpClient();
client.setConnectionTimeout(60000);
client.setTimeout(60000);
String response = new String();
String portStr = String.valueOf(port);
Protocol.registerProtocol("https", new Protocol("https", new MySSLSocketFactory(), port));
String signature = getSignature(xml);
String uri = "https://" + host + ":" + portStr + "/";
PostMethod postRequest = new PostMethod(uri);
postRequest.addRequestHeader("Content-Length", String.valueOf(xml.length()));
postRequest.addRequestHeader("Content-Type", "text/xml");
postRequest.addRequestHeader("X-Signature", signature);
postRequest.addRequestHeader("X-Username", userName);
postRequest.setRequestBody(xml);
System.out.println("Sending https request....." + postRequest.toString());
try {
client.executeMethod(postRequest);
} catch (Exception ex) {
throw new TaskExecuteException("Sending post got exception ", ex);
}
response = postRequest.getResponseBodyAsString();
headers = postRequest.getRequestHeaders();
return response;
}
public String getPrivateKey() {
return privateKey;
}
public void setPrivateKey(String privateKey) {
this.privateKey = privateKey;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Header[] getHeaders() {
return headers;
}
public void setHeaders(Header[] headers) {
this.headers = headers;
}
public static void main(String[] args) {
String privateKey = "your_private_key";
String userName = "your_user_name";
String host = "demo.site.net";
int port = 55443;
String xml =
"<?xml version='1.0' encoding='UTF-8' standalone='no' ?>"
+ "<!DOCTYPE OPS_envelope SYSTEM 'ops.dtd'>"
+ "<OPS_envelope>"
+ "<header>"
+ "<version>0.9</version>"
+ "<msg_id>2.21765911726198</msg_id>"
+ "<msg_type>standard</msg_type>"
+ "</header>"
+ "<body>"
+ "<data_block>"
+ "<dt_assoc>"
+ "<item key='attributes'>"
+ "<dt_assoc>"
+ "<item key='domain'>test-1061911771844.com</item>"
+ "<item key='pre-reg'>0</item>"
+ "</dt_assoc>"
+ "</item>"
+ "<item key='object'>DOMAIN</item>"
+ "<item key='action'>LOOKUP</item>"
+ "<item key='protocol'>XCP</item>"
+ "</dt_assoc>"
+ "</data_block>"
+ "</body>"
+ "</OPS_envelope>";
SslClient sslclient = new SslClient(host, port, userName, privateKey);
try {
String response = sslclient.sendRequest(xml);
System.out.println("\nResponse is:\n" + response);
} catch (Exception e) {
e.printStackTrace();
}
}
}
As in a day we are processing 10,000 + transactions, so number of socket at proxy are getting increased, so after 2-3 days, we need to do hard reboot of web server to free all the open sockets with proxy server.
Does HTTPClient, opens one socket for SSL Handshake and another for actual data post ? I don't think so. Then it should be at Web server and not at Proxy Server
For checking sockets and open ports at web server we are using netstat command.
For checking sockets and open ports at proxy server we are using proxy tool
when we check at web server it has created only one socket.
Because there is only one inbound connection to it.
SO why 2 socket at proxy server.
Because you are connecting to two different servers via the proxy server?
number of socket at proxy are getting increased, so after 2-3 days, we need to do hard reboot of web server to free all the open sockets with proxy server.
That doesn't make sense. It's the proxy server that has the dual connections, not the web server. You said that above. If the web server is running out of sockets, somebody isn't closing their connections correctly: the client, the proxy server, or the web server. Possibly your socket factory needs to override equals() and maybe hashCode() too, to enable whatever connection pooling HttpClient may do, I'm not an expert on that.
BUT your TrustManager is radically insecure. If you have this deployed in production, you have already committed a major security breach. This is currently a much bigger problem that running out of sockets every few days.
When socket ports run out, transaction timeouts occur. The solution to this problem is to tune the TIMEWAIT-related Windows registry parameters:
TcpTimedWaitDelay
MaxUserPort
StrictTimeWaitSeqCheck
The TIMEWAIT-related Windows registry parameters control how long a socket port remains unavailable after it is closed and how many ports are available for use.
By setting these windows registry parameters, I have solved this problem, but don't know, weather it is a correct solution to implement or not.

Categories

Resources