Websphere MQ SSL connection using java - java

I've below code which connects to IBM Websphere MQ that doesn't have SSL without issues and able to put/ get messages. But when I try to connect with a MQ with SSL, i'm getting error.
Please note that the patch() method is to disable SSL, which gets executed but isn't disabling SSL.
Rather than this, can you tell me how I can connect to the MQ that has SSL enabled channel.
Note - I've the certificate files like - key.kdb, key.crl, key.rdb, key.sth and few other CA3, CA4.cer files. How do I install them and use it in my code?
import com.ibm.mq.MQEnvironment;
import com.ibm.mq.MQMessage;
import com.ibm.mq.MQPutMessageOptions;
import com.ibm.mq.MQQueue;
import com.ibm.mq.MQQueueManager;
import com.ibm.mq.constants.CMQC;
import com.ibm.mq.*;
import java.io.IOException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Hashtable;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
public class mq1 {
public static String host = "localhost";
public static int port = 1414;
public static String strchannel = "MQ.CHL";
public static String strqueuemanager = "MQMGR";
public static String strqueue = "REQUEST.QUEUE";
#SuppressWarnings("deprecation")
public static void main(String[] args) throws KeyManagementException, NoSuchAlgorithmException {
//call patch() to skip SSL
patch();
int openOptions = CMQC.MQOO_BROWSE | CMQC.MQOO_INQUIRE | CMQC.MQOO_OUTPUT | CMQC.MQOO_INPUT_AS_Q_DEF ;
MQEnvironment.hostname = host;
MQEnvironment.port = port;
MQEnvironment.channel = strchannel;
MQEnvironment.properties.put(CMQC.TRANSPORT_PROPERTY,CMQC.TRANSPORT_MQSERIES);
MQQueueManager qMgr;
try {
qMgr = new MQQueueManager (strqueuemanager);
System.out.println(qMgr);
MQQueue destQueue = qMgr.accessQueue(strqueue, openOptions);
System.out.println("Queue size:" + destQueue.getCurrentDepth());
MQMessage hello_world = new MQMessage();
System.out.println("MQMessage message created");
hello_world.writeUTF("Sending Sample message");
MQPutMessageOptions pmo = new MQPutMessageOptions();
try {
destQueue.put(hello_world,pmo);
destQueue.get(hello_world);
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
int len = hello_world.getDataLength();
System.out.println("Length : " + len);
System.out.println("GET: "+ hello_world.readString(len-1));
destQueue.close();
qMgr.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void patch() throws KeyManagementException, NoSuchAlgorithmException {
System.out.println("Calling SSL patch");
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}
};
System.out.println("trustAllCerts = "+trustAllCerts);
SSLContext sc = SSLContext.getInstance("SSL");
System.out.println("sc before init = "+sc);
sc.init(
null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, javax.net.ssl.SSLSession session) {
return true;
}
};
System.out.println("sc after init= "+sc);
System.out.println("allHostsValid= "+allHostsValid);
// Install the all-trusting host verifier
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
}
}

Easiest way is not to put it in your code at all and instead utilise a Client Channel Definitiin Table (CCDT). Then you can use it without SSL and later change the CCDT to use SSL without needing to change your code at all. This is considered the best practice for client connectivity to IBM MQ.
This will mean you stop using the MQEnvironment class to pass in things like the channel name, hostname etc, and instead use a slightly different MQQueueManager constructor with two parameters, the first is the queue managers name as before, the second is the name of your CCDT file.
You can read more about how to use the CCDT with Java in the official IBM MQ Knowledge Center at the following page which also includes a link to how to create the CCDT file:-
Using a client channel definition table with IBM MQ classes for Java

Related

AD authentication with one LDAP failed but passed with another LDAP

From the following website, I found codes to perform java AD authentication.
http://java2db.com/jndi-ldap-programming/solution-to-sslhandshakeexception
The followings are the codes:
MySSLSocketFactory.java
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.SecureRandom;
import javax.net.SocketFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
public class MySSLSocketFactory extends SSLSocketFactory {
private SSLSocketFactory socketFactory;
public MySSLSocketFactory() {
try {
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, new TrustManager[]{new DummyTrustmanager()}, new SecureRandom());
socketFactory = ctx.getSocketFactory();
} catch (Exception ex) {
ex.printStackTrace(System.err);
}
}
public static SocketFactory getDefault() {
return new MySSLSocketFactory();
}
#Override
public String[] getDefaultCipherSuites() {
return socketFactory.getDefaultCipherSuites();
}
#Override
public String[] getSupportedCipherSuites() {
return socketFactory.getSupportedCipherSuites();
}
#Override
public Socket createSocket(Socket socket, String string, int num, boolean bool) throws IOException {
return socketFactory.createSocket(socket, string, num, bool);
}
#Override
public Socket createSocket(String string, int num) throws IOException, UnknownHostException {
return socketFactory.createSocket(string, num);
}
#Override
public Socket createSocket(String string, int num, InetAddress netAdd, int i)
throws IOException, UnknownHostException {
return socketFactory.createSocket(string, num, netAdd, i);
}
#Override
public Socket createSocket(InetAddress netAdd, int num) throws IOException {
return socketFactory.createSocket(netAdd, num);
}
#Override
public Socket createSocket(InetAddress netAdd1, int num, InetAddress netAdd2, int i) throws IOException {
return socketFactory.createSocket(netAdd1, num, netAdd2, i);
}
}
DummyTrustmanager.java
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;
public class DummyTrustmanager implements X509TrustManager {
public void checkClientTrusted(X509Certificate[] cert, String string) throws CertificateException
{
}
public void checkServerTrusted(X509Certificate[] cert, String string) throws CertificateException
{
}
public X509Certificate[] getAcceptedIssuers()
{
return new java.security.cert.X509Certificate[0];
}
}
TestAD.java
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
public class TestAD {
public static void main(String[] args) {
try {
//String url = "ldaps://abc.company.com:636";
String url = "ldaps://xyz.group.com:636";
String conntype = "simple";
// String id = "abc#abc.company.com";
String id = "xyz.group.com";
//String password = "abcpassword";
String password = "xyzpassword";
Hashtable<String, String> environment = new Hashtable<String, String>();
environment.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
environment.put(Context.PROVIDER_URL, url);
environment.put("java.naming.ldap.factory.socket", "MySSLSocketFactory");
environment.put(Context.SECURITY_AUTHENTICATION, conntype);
environment.put(Context.SECURITY_PRINCIPAL, id);
environment.put(Context.SECURITY_CREDENTIALS, password);
DirContext ldapContext = new InitialDirContext(environment);
System.out.println("Bind successful");
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
My company has a few subsidiaries, and they have their own LDAPs. When I run TestAD against my company ABC's LDAP, it works fine. But when I run it against the subsidiary XYZ's LDAP, I got the following exception:
javax.naming.CommunicationException: simple bind failed: xyz.group.com:636
[Root exception is javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative DNS name matching xyz.group.com found.]
at com.sun.jndi.ldap.LdapClient.authenticate(LdapClient.java:219)
at com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2791)
at com.sun.jndi.ldap.LdapCtx.<init>(LdapCtx.java:319)
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:192)
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:210)
at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:153)
at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:83)
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:684)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:313)
at javax.naming.InitialContext.init(InitialContext.java:244)
at javax.naming.InitialContext.<init>(InitialContext.java:216)
at javax.naming.directory.InitialDirContext.<init>(InitialDirContext.java:101)
at TestAD.main(TestAD.java:26)
Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative DNS name matching xyz.group.com found.
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1946)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:316)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:310)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1639)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:223)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1037)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:965)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1064)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1367)
at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:931)
at sun.security.ssl.AppInputStream.read(AppInputStream.java:105)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:286)
at java.io.BufferedInputStream.read(BufferedInputStream.java:345)
at com.sun.jndi.ldap.Connection.run(Connection.java:877)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.security.cert.CertificateException: No subject alternative DNS name matching xyz.group.com found.
at sun.security.util.HostnameChecker.matchDNS(HostnameChecker.java:214)
at sun.security.util.HostnameChecker.match(HostnameChecker.java:96)
at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:459)
at sun.security.ssl.AbstractTrustManagerWrapper.checkAdditionalTrust(SSLContextImpl.java:1125)
at sun.security.ssl.AbstractTrustManagerWrapper.checkServerTrusted(SSLContextImpl.java:1092)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1621)
... 12 more
What could be the reason for the failure? I did not import ABC's or XYZ's certificate into my trust store. Why does it work fine for ABC but not for XYZ? Could it be that XYZ is expecting my certificate?
This caused by the endpoint identification algorithms, it checks the host name in your configuration matches the host name in your remote LDAPS TLS server certificate, and that those host names are valid.
Given this error No subject alternative DNS name matching xyz.group.com found, it must be that "xyz.group.com" doesn't match your ldap server certificate, while "abc.company.com" does match.
Java 8u181 brought some changes in core-libs/javax.naming and updated how secure LDAP connections are handled (cf. release note) :
Endpoint identification has been enabled on
LDAPS connections.
To improve the robustness of LDAPS (secure LDAP over TLS) connections,
endpoint identification algorithms have been enabled by default.
Note that there may be situations where some applications that were
previously able to successfully connect to an LDAPS server may no
longer be able to do so. Such applications may, if they deem
appropriate, disable endpoint identification using a new system
property: com.sun.jndi.ldap.object.disableEndpointIdentification.
Define this system property (or set it to true) to disable endpoint
identification algorithms.
Disabling the endpoint identification algorithms is a workaround, the long term solution is to fix the server certificate so that it matches "xyz.group.com" hostname.

Creating service provider in WSO2 Identity Server with OAuth facility using Java

I am developing a Java client which creates the service provider dynamically with Inbound Authentication set to OAuth in WSO2 Identity Server. The code goes as follows
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.Map;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.ConfigurationContextFactory;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.axis2.transport.http.HttpTransportProperties;
import org.wso2.carbon.authenticator.proxy.AuthenticationAdminStub;
import org.wso2.carbon.um.ws.api.WSRealmBuilder;
import org.wso2.carbon.um.ws.api.stub.ClaimValue;
import org.wso2.carbon.user.core.UserRealm;
import org.wso2.carbon.user.core.UserStoreManager;
import org.wso2.carbon.identity.application.common.model.xsd.InboundAuthenticationConfig;
import org.wso2.carbon.identity.application.common.model.xsd.InboundAuthenticationRequestConfig;
import org.wso2.carbon.identity.application.common.model.xsd.ServiceProvider;
import org.wso2.carbon.identity.application.mgt.stub.IdentityApplicationManagementServiceStub;
import org.wso2.carbon.identity.oauth.stub.*;
import org.wso2.carbon.identity.oauth.stub.dto.OAuthConsumerAppDTO;
public class IdentityClient {
private final static String SERVER_URL = "https://localhost:9443/services/";
public static void main(String[] args) throws RemoteException, OAuthAdminServiceException {
String appName = "Sample_App_3";
System.setProperty("javax.net.ssl.trustStore", "wso2carbon.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "wso2carbon");
try {
OAuthAdminServiceStub stub = new OAuthAdminServiceStub(null,
SERVER_URL + "OAuthAdminService");
IdentityApplicationManagementServiceStub IAMStub = new IdentityApplicationManagementServiceStub(
null, SERVER_URL + "IdentityApplicationManagementService");
ServiceClient client = stub._getServiceClient();
ServiceClient IAMClient = IAMStub._getServiceClient();
authenticate(client);
OAuthConsumerAppDTO consumerApp = new OAuthConsumerAppDTO();
consumerApp.setApplicationName(appName);
consumerApp.setOAuthVersion("OAuth-2.0");
consumerApp.setCallbackUrl("http://localhost:8080/playground2/oauth2client");
consumerApp.setGrantTypes(
"authorization_code implicit password client_credentials refresh_token "
+ "urn:ietf:params:oauth:grant-type:saml2-bearer iwa:ntlm");
/* OAuthAdminProxy.registerOAuthApplicationData(consumerApp); */
stub.registerOAuthApplicationData(consumerApp);
System.out.println("Application created successfully");
authenticate(IAMClient);
InboundAuthenticationRequestConfig iaReqConfig = new InboundAuthenticationRequestConfig();
iaReqConfig.setInboundAuthKey(stub.getOAuthApplicationDataByAppName(appName)
.getOauthConsumerKey());
iaReqConfig.setInboundAuthType(stub.getOAuthApplicationDataByAppName(appName)
.getOauthConsumerSecret());
InboundAuthenticationRequestConfig[] iaReqConfigList = { iaReqConfig };
InboundAuthenticationConfig ib = new InboundAuthenticationConfig();
ib.setInboundAuthenticationRequestConfigs(iaReqConfigList);
ServiceProvider serviceProvider = new ServiceProvider();
serviceProvider.setApplicationName(
stub.getOAuthApplicationDataByAppName(appName).getApplicationName());
serviceProvider.setInboundAuthenticationConfig(ib);
IAMStub.createApplication(serviceProvider);
System.out.println("Service Provider created");
} catch (Exception e) {
e.printStackTrace();
}
}
public static void authenticate(ServiceClient client) {
Options option = client.getOptions();
HttpTransportProperties.Authenticator auth = new HttpTransportProperties.Authenticator();
auth.setUsername("admin");
auth.setPassword("admin");
auth.setPreemptiveAuthentication(true);
option.setProperty(org.apache.axis2.transport.http.HTTPConstants.AUTHENTICATE, auth);
option.setManageSession(true);
}
}
Once I run this code, the service provider is getting created in the WSO2 Identity Server which I could see in the management console. The OAuth configuration which has been done vis-a-vis the service provider is not showing up and it is empty with just a 'configure' link. Had I understood WSO2 IS properly then I should be getting the consumer key and consumer secret under Inbound Authentication Configuration --> OAuth/OpenID Connect Configuration drop down.
Please help me in what should be done right ?
Try changing your client as bellow,
import java.rmi.RemoteException;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;
import org.apache.axis2.transport.http.HttpTransportProperties;
import org.wso2.carbon.identity.application.common.model.xsd.InboundAuthenticationConfig;
import org.wso2.carbon.identity.application.common.model.xsd.InboundAuthenticationRequestConfig;
import org.wso2.carbon.identity.application.common.model.xsd.Property;
import org.wso2.carbon.identity.application.common.model.xsd.ServiceProvider;
import org.wso2.carbon.identity.application.mgt.stub.IdentityApplicationManagementServiceStub;
import org.wso2.carbon.identity.oauth.stub.OAuthAdminServiceException;
import org.wso2.carbon.identity.oauth.stub.OAuthAdminServiceStub;
import org.wso2.carbon.identity.oauth.stub.dto.OAuthConsumerAppDTO;
public class IdentityClient {
private final static String SERVER_URL = "https://localhost:9443/services/";
public static void main(String[] args) throws RemoteException, OAuthAdminServiceException {
String appName = "Sample_App_5";
String appDescription = "Test description";
System.setProperty("javax.net.ssl.trustStore", "wso2carbon.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "wso2carbon");
try {
OAuthAdminServiceStub stub = new OAuthAdminServiceStub(null,
SERVER_URL + "OAuthAdminService");
IdentityApplicationManagementServiceStub IAMStub = new IdentityApplicationManagementServiceStub(
null, SERVER_URL + "IdentityApplicationManagementService");
ServiceClient client = stub._getServiceClient();
ServiceClient IAMClient = IAMStub._getServiceClient();
authenticate(client);
authenticate(IAMClient);
ServiceProvider serviceProvider = new ServiceProvider();
serviceProvider.setApplicationName(appName);
serviceProvider.setDescription(appDescription);
IAMStub.createApplication(serviceProvider);
OAuthConsumerAppDTO consumerApp = new OAuthConsumerAppDTO();
consumerApp.setApplicationName(appName);
consumerApp.setOAuthVersion("OAuth-2.0");
consumerApp.setCallbackUrl("http://localhost:8080/playground2/oauth2client");
consumerApp.setGrantTypes(
"authorization_code implicit password client_credentials refresh_token "
+ "urn:ietf:params:oauth:grant-type:saml2-bearer iwa:ntlm");
/* OAuthAdminProxy.registerOAuthApplicationData(consumerApp); */
stub.registerOAuthApplicationData(consumerApp);
System.out.println("Application created successfully");
System.out.println(stub.getOAuthApplicationDataByAppName(appName).getOauthConsumerKey());
authenticate(IAMClient);
InboundAuthenticationRequestConfig iaReqConfig = new InboundAuthenticationRequestConfig();
iaReqConfig.setInboundAuthKey(stub.getOAuthApplicationDataByAppName(appName).getOauthConsumerKey());
iaReqConfig.setInboundAuthType("oauth2");
Property property = new Property();
property.setName("oauthConsumerSecret");
property.setValue(stub.getOAuthApplicationDataByAppName(appName).getOauthConsumerSecret());
Property[] properties = { property };
iaReqConfig.setProperties(properties);
InboundAuthenticationRequestConfig[] iaReqConfigList = { iaReqConfig };
InboundAuthenticationConfig ib = new InboundAuthenticationConfig();
ib.setInboundAuthenticationRequestConfigs(iaReqConfigList);
serviceProvider = IAMStub.getApplication(appName);
serviceProvider.setApplicationName(
stub.getOAuthApplicationDataByAppName(appName).getApplicationName());
serviceProvider.setInboundAuthenticationConfig(ib);
IAMStub.updateApplication(serviceProvider);
System.out.println("Service Provider created");
} catch (Exception e) {
e.printStackTrace();
}
}
public static void authenticate(ServiceClient client) {
Options option = client.getOptions();
HttpTransportProperties.Authenticator auth = new HttpTransportProperties.Authenticator();
auth.setUsername("admin");
auth.setPassword("admin");
auth.setPreemptiveAuthentication(true);
option.setProperty(org.apache.axis2.transport.http.HTTPConstants.AUTHENTICATE, auth);
option.setManageSession(true);
}
}
Problem is createApplication does not save the configurations other than the name and the description. You have to call updateApplication to save other application configurations.

Using com.sun.net.httpserver.HttpsServer - how to specify protocol?

I am trying to implement a HTTPS (SSL) server in Java, and I'd like to leverage com.sun.net.httpserver.HttpsServer.
I have been able to cobble together some code from different places that kind of works, but I want to be able to specify which protocols, e.g., SSLv3, TLSv!, etc. that my HTTPS server is willing able to support, but I have not been able to figure out how to do that.
I'm posting the code I have so far, and was wondering if anyone could tell me how I can add the ability to specify the protocols?
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Arrays;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpsServer;
import com.sun.net.httpserver.HttpsConfigurator;
import com.sun.net.httpserver.HttpsParameters;
public class Test {
static private String PROGVERSION = "V1.00";
static private String keystoreFile = "";
static private int listenPort = 0;
public static void main(String[] args) throws Exception {
System.out.println("JavaHttpsServer " + PROGVERSION);
keystoreFile = args[0];
listenPort = Integer.parseInt(args[1]);
System.out.println("keystoreFile=[" + keystoreFile + "]");
System.out.println("listenPort=[" + listenPort + "]");
SSLContext ssl = SSLContext.getInstance("SSLv3");
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
KeyStore store = KeyStore.getInstance(KeyStore.getDefaultType());
//Load the JKS file (located, in this case, at D:\keystore.jks, with password 'test'
//store.load(new FileInputStream("C:\\Users\\Eclipse-workspaces\\Test\\keystore.jks"), "changeit".toCharArray());
store.load(new FileInputStream(keystoreFile), "changeit".toCharArray());
//init the key store, along with the password 'changeit'
kmf.init(store, "changeit".toCharArray());
KeyManager[] keyManagers = new KeyManager[1];
keyManagers = kmf.getKeyManagers();
// Init the trust manager factory
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
// It will reference the same key store as the key managers
tmf.init(store);
TrustManager[] trustManagers = tmf.getTrustManagers();
ssl.init(keyManagers, trustManagers, new SecureRandom());
// Init a configuration with our SSL context
HttpsConfigurator configurator = new HttpsConfigurator(ssl);
//configurator.configure(hparams);
// Create a new HTTPS Server instance, listening on port 8000
HttpsServer server = HttpsServer.create(new InetSocketAddress(listenPort), 0);
server.setHttpsConfigurator(configurator);
server.createContext("/test", new MyHandler());
server.setExecutor(null); // creates a default executor
server.start();
}
static class MyHandler implements HttpHandler {
#Override
public void handle(HttpExchange t) throws IOException {
String x = t.getRemoteAddress().getHostString();
System.out.println("In handle: Request from (getHostString) = [" + x + "]");
x = t.getRequestURI().toASCIIString();
System.out.println("In handle: getRequestURI = [" + x + "]");
if (x.equalsIgnoreCase("/test?stop")) {
System.out.println("In handle: Received request to exit, so will exit now...");
System.exit(0);
}
System.out.println("In handle: About to send response...");
String response = "This is the response";
t.sendResponseHeaders(200, response.length());
OutputStream os = t.getResponseBody();
os.write(response.getBytes());
System.out.println("In handle: Finished sending response...");
os.close();
}
}
}
I am not sure if I understand the question correctly, because your code already shows, how to set the protocol. You provide the protocol in the getInstance() method of SSLContext. In your example you initialize SSLContext with SSLv3. You can use one of the strings described here: https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#SSLContext
To verify, which protocol your server uses, you can use the "s_client" command of OpenSSL: openssl s_client -connect localhost:8443

WSImport over SSL with fake (dev) certificate

Recently I spent couple of hours trying to get WSImport working on web service that is hosted over HTTPS, with fake certificate (dev deployment).
I tried to use windows version of wsimport.exe, from Java 8 jdk.
I specified option -XdisableSSLHostnameVerification, but it kept complaining about wrong certificate.
That is true, certificate is not valid, but in dev environment it should be acceptable.
I did not find easy way to make wsimport to skip certificate check.
Finally I got a solution, using wrapper class.
I think it makes sense to share the solution.
Hope it will save some someone's time for better purposes.
The solution (assuming that java is installed in c:\Program Files\Java\jdk1.8.0_40):
How to compile
"c:\Program Files\Java\jdk1.8.0_40\bin\javac" -cp "c:\Program Files\Java\jdk1.8.0_40\lib\tools.jar" WSImportSSLByPass.java
How to use
"c:\Program Files\Java\jdk1.8.0_40\bin\java" -cp "c:\Program Files\Java\jdk1.8.0_40\lib\tools.jar";. WSImportSSLByPass %wsimport args%
The code
to be put into WSImportSSLByPass.java
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
public class WSImportSSLByPass {
public static void main(String[] args) throws Throwable{
configureBypassSSL();
com.sun.tools.internal.ws.WsImport.main(args);
}
private static void configureBypassSSL() throws NoSuchAlgorithmException,
KeyManagementException {
SSLContext ssl_ctx = SSLContext.getInstance("SSL");
TrustManager[] trust_mgr = get_trust_mgr();
ssl_ctx.init(null, // key manager
trust_mgr, // trust manager
new SecureRandom()); // random number generator
SSLSocketFactory sf = ssl_ctx.getSocketFactory();
HttpsURLConnection.setDefaultSSLSocketFactory(sf);
HttpsURLConnection.setDefaultHostnameVerifier(new DummyHostVerifier());
}
private static TrustManager[] get_trust_mgr() {
TrustManager[] certs = new TrustManager[] { new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String t) {
}
public void checkServerTrusted(X509Certificate[] certs, String t) {
}
} };
return certs;
}
}
class DummyHostVerifier implements HostnameVerifier {
public boolean verify(String name, SSLSession sess) {
return true;
}
}
In case of 2-way ssl handshake, we can modify the WSImportSSLByPass class like this
import com.sun.tools.internal.ws.WsImport;
public class OCBWSImport {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws Throwable {
// TODO code application logic here
//System.setProperty("javax.net.ssl.trustStore", "C:\\Program Files\\Java\\jdk1.8.0_131\\jre\\lib\\security\\cacerts");
//System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
//System.setProperty("javax.net.ssl.keyStoreType", "pkcs12");
//Certificate for 2-way handshake
System.setProperty("javax.net.ssl.keyStore", "D:\\tuanpa\\yourp12file.p12");
System.setProperty("javax.net.ssl.keyStorePassword", "password of p12 file");
//Hostname checking bypass
javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(
new javax.net.ssl.HostnameVerifier() {
public boolean verify(String hostname,
javax.net.ssl.SSLSession sslSession) {
//return hostname.equals("192.168.1.10");
return true;
}
});
WsImport.main(args);
}
}

Fixing javax.net.ssl.SSLPeerUnverifiedException: No peer certificate

I am developing an android app that has to communicate with server over https with self signed certificate (SSL/TLS1.2). I am also using Volley.
I am following this tutorial. Saved the .crt file, created key.bks in raw directory with keytool -importcert -v -trustcacerts -file "cert.crt" -alias IntermediateCA -keystore "key.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "bcprov-jdk16-146.jar" -storetype BKS -storepass blabla
and so on.
When I am sending data to server, Response.ErrorListener() receives No peer certificate error.
Tried to send my json with Postman (of course, had to add the certificate) -worked fine.
Manually installed the certificate on my android device - worked fine
How can I make it work?
I fought a lot with this problem.
It appeared that the server I was sending to has a virtual host (hosted on GAE). On Android 5.0 this issue is solved, but bellow Android 5.0 you have to add SNI support yourself.
Here is an explanation of this problem http://blog.dev001.net/post/67082904181/android-using-sni-and-tlsv1-2-with-apache.
So to make my code work I had to change SslSocketFactory class from the tutorial. It did the magic.
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.GeneralSecurityException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.params.HttpParams;
import android.annotation.TargetApi;
import android.net.SSLCertificateSocketFactory;
import android.os.Build;
class SslSocketFactory extends SSLSocketFactory {
InputStream mkeyStore;
String mkeyStorePassword;
public SslSocketFactory(InputStream keyStore, String keyStorePassword) throws KeyManagementException, UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException{
super(null);
mkeyStore=keyStore;
mkeyStorePassword=keyStorePassword;
}
#Override
public Socket connectSocket(Socket s, String host, int port, InetAddress localAddress, int localPort, HttpParams params) throws IOException {
return null;
}
#Override
public Socket createSocket() throws IOException {
return null;
}
#Override
public boolean isSecure(Socket s) throws IllegalArgumentException {
if (s instanceof SSLSocket) {
return ((SSLSocket) s).isConnected();
}
return false;
}
#TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
#Override
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
SSLSocket sslSocket = null;
if (autoClose) {
socket.close();
}
SSLCertificateSocketFactory sslSocketFactory = (SSLCertificateSocketFactory) SSLCertificateSocketFactory.getDefault(0, null);
try {
sslSocketFactory.setTrustManagers(new TrustManager[] { new SsX509TrustManager( mkeyStore, mkeyStorePassword) });
} catch (GeneralSecurityException e1) {
e1.printStackTrace();
}
sslSocket = (SSLSocket) sslSocketFactory.createSocket(InetAddress.getByName(host), port);
sslSocket.setEnabledProtocols(sslSocket.getSupportedProtocols());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
sslSocketFactory.setHostname(sslSocket, host);
} else {
try {
java.lang.reflect.Method setHostnameMethod = sslSocket.getClass().getMethod("setHostname", String.class);
setHostnameMethod.invoke(sslSocket, host);
} catch (Exception e) {
}
}
return sslSocket;
}
}

Categories

Resources