I have to access the webservice with 2 way authentication. Below is my approach.
Created MyCustomSSLSocketFactory class.
Loaded TrustManagers
Loaded Keystore Managers
Created SSL Context and SSL socket factory as below.
I call this class method just before calling webservice method.
Then i have done as below:-
AxisProperties.setProperty("axis.socketSecureFactory",
"com.elipva.zephyr.twofa.util.MyCustomSSLSocketFactory");
Security.setProperty("ssl.SocketFactory.provider",
"com.elipva.zephyr.twofa.util.MyCustomSSLSocketFactory");
SSLContext context = SSLContext.getInstance(protocolVersion);
context.init(keyManagers, trustManagers, null);
SSLSocketFactory socketFactory = context.getSocketFactory();
URL url = new URL(urlString);
URLConnection connection = url.openConnection();
if (connection instanceof HttpsURLConnection) {
((HttpsURLConnection) connection)
.setSSLSocketFactory(sslSocketFactory);
connection.connect();
}
when i access the webservice it gives me below error.
org.apache.axis2.AxisFault: Unconnected sockets not implemented
at org.apache.axis2.AxisFault.makeFault(AxisFault.java:430)
at org.apache.axis2.transport.http.HTTPSender.sendViaPost(HTTPSender.java:203)
at org.apache.axis2.transport.http.HTTPSender.send(HTTPSender.java:76)
at org.apache.axis2.transport.http.CommonsHTTPTransportSender.writeMessageWithCommons(CommonsHTTPTransportSender.java:400)
at org.apache.axis2.transport.http.CommonsHTTPTransportSender.invoke(CommonsHTTPTransportSender.java:225)
at org.apache.axis2.engine.AxisEngine.send(AxisEngine.java:435)
at org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisOperation.java:402)
at org.apache.axis2.description.OutInAxisOperationClient.executeImpl(OutInAxisOperation.java:229)
at org.apache.axis2.client.OperationClient.execute(OperationClient.java:165)
Please let me know if i am missing anything.
Issue got resolved, simply imported certificates in cacerts file.
I think it could be this Java bug - http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6771432
Note that this is supposedly fixed in java 1.6.0_u14
Related
I use SSLSocket for my android app
and according to this post SSLSocket doesn't perform host name verification
here
and I didn't see any exception while using IP instead of domain and everything works fine
so can I use IP or any other domain for connection?
I have got the cert from letsencrypt for one domain and I wonder that I can use it for any domain or IP with SSLSocket!
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, nulls, null);
SocketFactory sslsocketfactory = sc.getSocketFactory();
SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket(host, 443);
sslsocket.setSoTimeout(5000);
sslsocket.startHandshake();
The answer is on your link:
Your app needs to do its own hostname verification, preferably by calling
getDefaultHostnameVerifier() with the expected hostname. Further,
beware that HostnameVerifier.verify() doesn't throw an exception on
error but instead returns a boolean result that you must explicitly
check.
"I wonder that I can use it for any domain or IP with SSLSocket!"
No, you will not be able to do that, the cert of the connection must be in your client's truststore, and we can expect that the different domains use different certificates :)
Please see this How should I do hostname validation when using JSSE? link.
I'm putting together a soap client to call a thirdparty soap service. I'm having issues connecting with Java. It works fine with SoapUI. This is the first time I've set up a keystore within the app. All the code I have found is the same and pretty simple but I can't figure out why the java version isn't working.. I'm using a TLS pfx file provided by the company whose service I'm trying to connect too.
I'm getting a 403 back from the server.. Here is the code
URL wsdlLocation = new URL(SECURE_INTEGRATION_WSDL);
ObjectFactory ofactory = new ObjectFactory();
HttpsURLConnection httpsConnection = (HttpsURLConnection)wsdlLocation.openConnection();
char[] password = CLIENT_KEYSTORE_PASSWORD.toCharArray();
//load keystore
FileInputStream is = new FileInputStream(new File(CLIENT_KEYSTORE_PATH));
final KeyStore keystore = KeyStore.getInstance("PKCS12");
keystore.load(is, password);
is.close();
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(keystore, password);
//set the ssl context
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(kmf.getKeyManagers(), null,
new java.security.SecureRandom());
httpsConnection.setSSLSocketFactory(sc.getSocketFactory());
SecureIntegrationServicesImap client = new SecureIntegrationServicesImap(wsdlLocation);
SesMessage message = ofactory.createSesMessage();
ReceiveRequest r = ofactory.createReceiveRequest();
r.setEmail(ofactory.createReceiveRequestEmail("<email ommitted>"));
ArrayOfMessageSummary messages = client.getWSHttpBindingSecureIntegrationServiceImap().getMessageList(r);
log.info(messages.getMessageSummary().size());
Any help with what I'm wrong is greatly appreciated..
Not sure if it matters but the server is a .NET platform
Here is the stacktrace I'm getting
javax.xml.ws.WebServiceException: Failed to access the WSDL at: https://<host omitted>/TS?wsdl. It failed with:
Server returned HTTP response code: 403 for URL: https://<host omitted>/TS?wsdl.
at com.sun.xml.ws.wsdl.parser.RuntimeWSDLParser.tryWithMex(RuntimeWSDLParser.java:265)
at com.sun.xml.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:246)
at com.sun.xml.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:209)
at com.sun.xml.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:178)
at com.sun.xml.ws.client.WSServiceDelegate.parseWSDL(WSServiceDelegate.java:363)
at com.sun.xml.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:321)
at com.sun.xml.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:230)
at com.sun.xml.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:211)
at com.sun.xml.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:207)
at com.sun.xml.ws.spi.ProviderImpl.createServiceDelegate(ProviderImpl.java:114)
at javax.xml.ws.Service.<init>(Service.java:77)
at org.tempuri.SecureIntegrationServicesImap.<init>(SecureIntegrationServicesImap.java:50)
at com.wiredinformatics.utils.SecureExchange.main(SecureExchange.java:127) Caused by: java.io.IOException: Server returned HTTP response code: 403 for URL: https://host omitted/TS?wsdl
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1876)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1474)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
at java.net.URL.openStream(URL.java:1045)
at com.sun.xml.ws.wsdl.parser.RuntimeWSDLParser.createReader(RuntimeWSDLParser.java:999)
at com.sun.xml.ws.wsdl.parser.RuntimeWSDLParser.resolveWSDL(RuntimeWSDLParser.java:400)
at com.sun.xml.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:231)
... 11 more
It sounds like you're using TLS based client authentication. Based on the code you posted I suspect the issue is that you're not using httpsConnection anywhere after you initialize it. Therefore it's not trying to use your client certificate as you were expecting but is instead using the default request context settings.
Assuming you're using JAX-WS you should be able to use the solution outlined in this answer to bind your certificate to your request context (instead of initializing your own HttpsURLConnection):
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
I'm working on an application that processes food orders and we send the requests via HttpsURLConnection to a php function that has been ssl certified. The problem I'm having is that it rejects the handshake sometimes and not others. I was wondering if anyone could explain to me why it would reject it one time and not another.
javax.net.ssl.SSLProtocolException: SSL handshake aborted:
ssl=0x56cbe008: Failure in SSL library, usually a protocol error
error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:744
0x52eb6d74:0x00000000)
javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted:
ssl=0x56cbe008: Failure in SSL library, usually a protocol error
error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:744
0x52eb6d74:0x00000000)
url = new URL(request.endpointUri);
Log.d(LOG_TAG, "Opening connection to " + request.endpointUri);
conn = (HttpsURLConnection)url.openConnection();
//setup the connection
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("charset", "UTF-8");
conn.setDoInput(true);
conn.setDoOutput(true);
//setup the parameters
Uri.Builder params = new Uri.Builder();
String paramString;
params.appendQueryParameter("cctoken", request.token.getId());
params.appendQueryParameter("amt", Integer.toString(request.order.amount));
params.appendQueryParameter("email", request.order.customerEmail);
params.appendQueryParameter("order", request.order.details);
paramString = params.build().getEncodedQuery();
conn.setFixedLengthStreamingMode(paramString.getBytes("UTF-8").length);
Log.d(LOG_TAG, "Compiled query into: " + paramString);
//write the POST request params
OutputStream os = conn.getOutputStream();
BufferedWriter streamWriter = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
streamWriter.write(paramString);
streamWriter.flush();
streamWriter.close();
os.close();
//read the response
int responseCode = conn.getResponseCode();
InputStream is;
The line given for failure is when it attempts to collect the output.
OutputStream os = conn.getOutputStream();
SSL handshake errors which only happen sometimes are often related to server side problems, so your code is not of much help here. Possible causes at the server side are multiple servers with different configuration (some work, some don't), timeouts which might be caused by too much load, server side crashes. There might also be some erratic middleware involved (firewalls) or if the connection is unreliable from start it will also affect the SSL handshake.
Thus don't look too much at your code but look at the server and the network. If in doubt try another client and if this one shows a more stable behavior look into the differences in the connection and SSL handshake (i.e. packet captures).
This problem could be due to self signed certificate of server to which you are sending request. You have to do something like this:
`// Load CAs from an InputStream
// (could be from a resource or ByteArrayInputStream or ...)
CertificateFactory cf = CertificateFactory.getInstance("X.509");
// From https://www.washington.edu/itconnect/security/ca/load-der.crt
InputStream caInput = new BufferedInputStream(new FileInputStream("load- der.crt"));
Certificate ca;
try {
ca = cf.generateCertificate(caInput);
System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
} finally {
caInput.close();
}
// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
// Create an SSLContext that uses our TrustManager
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
//Tell the URLConnection to use a SocketFactory from our SSLContext
URL url = new URL("https://certs.cac.washington.edu/CAtest/");
HttpsURLConnection urlConnection =
(HttpsURLConnection)url.openConnection();
urlConnection.setSSLSocketFactory(context.getSocketFactory());
InputStream in = urlConnection.getInputStream();
copyInputStreamToOutputStream(in, System.out);`
Found it here
Related Issue: Client and server don't support a common encryption protocol
If the error message says something like:
error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version (external/openssl/ssl/s23_clnt.c:741 0x8d92d990:0x00000000)
(Note that is says 'tlsv1' after 'GET_SERVER_HELLO:' rather than 'sslv3') This is a faint clue that the problem could be with the version of encryption needed. If the client is old, it may only support sslv2 or sslv3. An up to date server may support TLS1.2 and does not support the older (perhaps depracated ssl versions. The opposite may be true as well, with the server supporting only the old and the client only the new.
I ran into this problem with an old Android Jelly Bean client that doesn't support TLS1.2, by default, for HttpsUrlConnection. By creating a TLSSocketFactory and X509TrustManager, and calling setSSLSocketFactory() I could get the old version of Android to use TLS1.2, which made the server happy. Navneet Krishna wrote a good description of how to do this in: https://medium.com/#krisnavneet/how-to-solve-sslhandshakeexception-in-android-ssl23-get-server-hello-tlsv1-alert-protocol-13b457c724ef
I have got a server with self-signed certificate. I've imported it with a keytool on my computer and use
-Djavax.net.ssl.trustStore=blabla
compile argument. When I try to run the following code:
SSLSocketFactory factory = HttpsURLConnection.getDefaultSSLSocketFactory();
SSLSocket socket = (SSLSocket) factory.createSocket("MY_URL_DIGITS", 443);
OutputStream os = socket.getOutputStream();
os.write("Test request \n".getBytes());
os.flush();
os.close();
Everything goes alright and I can see the "Test request" on the server. However, when I run:
URL url = new URL("https://MY_URL_DIGITS");
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
OutputStream os = con.getOutputStream();
os.write("Test request \n".getBytes());
os.flush();
os.close();
I've got the
javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names present
So what is the principal difference between these two snippets?
SSLSocket by default only checks whether you trust the certificate. HttpsURLConnection checks whether you trust the certificate and also checks whether the certificate says it is coming from the same place you actually navigated to. For your HttpsURLConnection to succeed, the certificate would have to specify a subject alternative name (SAN) that was the same as the server you are conecting to. In this case the SAN would need to be "dns:MY_URL_DIGITS", where the "dns" part says you are specifying a host name rather than an IP address.
If you need additional information on how to create a certificate with a subject alternative name, see:
how to add subject alernative name to ssl certs?
The difference is that HTTPS adds a step, which can be seen in the HostnameVerifier interface. It is trying to match the hostname being connected to with the hostname in the SubjectDN or alternative names.
I have the java code like this :
URL url = new URL(endPoint);
String encoding = Base64.encodeBase64String(this.key.getBytes());
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
which is opening a ssl connection. Lets say the endPoint does uses a self-singed certificate and act as a original website. Is it possible to prevent these sort of things in the java code?
Thanks in advance.
By default, the SSL implementation in Java checks against a list of trusted certification authorities, which is included in the Java VM. Unless you extend the default trust store, specify a different trust store at run time or provide your own implementation of a TrustManager and/or HostnameVerifier, you will not be able to make an SSL connection to a server with a self-signed certificate.
If you for some reason need access to the server certificates after you have established the connection, you can get these from an HttpsURLConnection like this:
URL url = new URL("https://www.google.com");
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.connect();
for(Certificate crt : conn.getServerCertificates()) {
System.out.println(crt);
}