Clojure and SSL/x.509 certs quetion - ssl

I need to write a simple program for work that does the following:
read a config file
connect to a bunch of servers
establish a ssl socket
pull info form the server's x509 cert, expire date and hostname for now
email a report when its done
items 3 and 4 are things that I have had bad luck researching/googleing and I do not know java well, at all since 1.2 around 2001

A verbose but throughout guide about the inners of Java Cryptographic Extension is found at Oracles website as well: http://docs.oracle.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html

I found a code snipit that tells me what I need to know about java at http://www.exampledepot.com/egs/javax.net.ssl/GetCert.html
here it is:
try {
// Create the client socket
int port = 443;
String hostname = "hostname";
SSLSocketFactory factory = HttpsURLConnection.getDefaultSSLSocketFactory();
SSLSocket socket = (SSLSocket)factory.createSocket(hostname, port);
// Connect to the server
socket.startHandshake();
// Retrieve the server's certificate chain
java.security.cert.Certificate[] serverCerts =
socket.getSession().getPeerCertificates();
// Close the socket
socket.close();
} catch (SSLPeerUnverifiedException e) {
} catch (IOException e) {
} catch (java.security.cert.CertificateEncodingException e) {
}

Related

Is there a recommended way of establishing an SSLSocket connection to to a peer with a timeout on the handshake process

I have read some answers which do not resolve my question fully e.g. Placing timeout for SSLSocket handshake. This answer requires me to layer a plaintext socket under an SSLSocket which I would rather not do if there is an alternative. The relevant part of my code is as follows (FYI I'm not hardcoding passwords its just for testing):
private static SSLSocket establishConnection(InetAddress ipv4, int port) {
try {
int ksn = Stub.getKeystoreNum();
SecurityUtilities su = new SecurityUtilities("truststore" + ksn + ".jks", "keystore" + ksn + ".jks", "trustcert", "mykey");
KeyStore keystore = su.loadKeyStore("password".toCharArray());
KeyStore truststore = su.loadTrustStore("password".toCharArray());
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KEY_MANAGER);
keyManagerFactory.init(keystore, "password".toCharArray());
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(KEY_MANAGER);
trustManagerFactory.init(truststore);
// specify TLS version e.g. TLSv1.3
SSLContext serverContext = SSLContext.getInstance(TLS_VERSION);
serverContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), SecureRandom.getInstance(RNG_ALGORITHM, RNG_PROVIDER));
// THIS CODE IS MY ATTEMPT AT ESTABLISHING AN SSLSOCKET WITH A TIMEOUT
SSLSocketFactory fact = serverContext.getSocketFactory();
SSLSocket socket = (SSLSocket) fact.createSocket();
socket.connect(new InetSocketAddress(ipv4.getHostAddress(), port), CON_TIMEOUT);
return socket;
} catch (IOException | GeneralSecurityException e) {
System.out.println("tls node connection failed");
}
return null;
}
My code successfully establishes a connection and having tested it with tcpdump I found that it does indeed seem to encrypt the data transmitted with it. However because I have read that it's not possible to create an SSLSocket without having it immediately connect e.g.
return (SSLSocket) fact.createSocket(ipv4.getHostAddress(), port);
and because the connect method is defined in Socket and not SSLSocket I feel I am making some kind of mistake. additionally I have seen multiple examples which utilize the SSLSocket.startHandshake() method is this necessary as I have successfully established connections with the previous line of code alone?
Thanks for any help

How to setup websocket SSL connect using cpprestsdk?

I tried to connect to a websocket server with SSL. But always failed on connection(...).
I am new to cpprestsdk, I can't find doc on how to set SSL information to websocket_client.
websocket_client_config config;
config.set_server_name("wss://host:port/v3/api");
websocket_client client(config);
auto fileStream = std::make_sharedconcurrency::streams::ostream();
pplx::task requestTask = fstream::open_ostream(U("results2.html"))
.then([&](ostream outFile)
{
*fileStream = outFile;
// Create http_client to send the request.
uri wsuri(U("wss://host:port/v3/api"));
client.connect(wsuri).wait();
websocket_outgoing_message msg;
msg.set_utf8_message(obj.serialize());
client.send(msg).wait();
printf("send success: %s\n", obj.serialize().c_str());
return client.receive().get();
})
it throws "Error exception:set_fail_handler: 8: TLS handshake failed".
Documentation for cpprestsdk can be found here
C++ REST SDK WebSocket client. Although this doesn't show all the necessary information related to cpprestsdk it will help you.
And also you can get an SSL test example here. I show a simple websocket client implemented using SSL or wss:// scheme
websocket_client client;
std::string body_str("hello");
try
{
client.connect(U("wss://echo.websocket.org/")).wait();
auto receive_task = client.receive().then([body_str](websocket_incoming_message ret_msg) {
VERIFY_ARE_EQUAL(ret_msg.length(), body_str.length());
auto ret_str = ret_msg.extract_string().get();
VERIFY_ARE_EQUAL(body_str.compare(ret_str), 0);
VERIFY_ARE_EQUAL(ret_msg.message_type(), websocket_message_type::text_message);
});
websocket_outgoing_message msg;
msg.set_utf8_message(body_str);
client.send(msg).wait();
receive_task.wait();
client.close().wait();
}
catch (const websocket_exception& e)
{
if (is_timeout(e.what()))
{
// Since this test depends on an outside server sometimes it sporadically can fail due to timeouts
// especially on our build machines.
return;
}
throw;
}
And further examples here to guide you get it successfully is found here
https://github.com/microsoft/cpprestsdk/wiki/Web-Socket

JSSEHelper does not provide the correct SSLSocketFactory for extablishing secure connection in Websphere 8.0

I was working with 8.0 version of Websphere application server. I was trying to get SSLSocketFactory from JSSEHelper. Although
I have successfuly got the SSLSocketFactory
I have successfuly got the SSLSocket from SSLSocketFactory
I have successfuly established the secure connection,
but cipher suites provided in ClientHello message corresponded neither to
CellDefault SSL Settings/NodeDefault SSL Settings/NodeDefaultnor
nor to my own custom SSL configuration.
The solution to this problem was to avoid retrieving SSLSocketFactory from JSSEHelper. Instead of using JSSEHelper, I should use static method getDefault() from SSLSocketFactory class in whis way:
public SSLSocket getSslSocket(Properties sslProps) {
SSLSocketFactory factory = SSLSocketFactory.getDefault();
SSLSocket socket = null;
try {
socket = (SSLSocket) factory.createSocket();
} catch (IOException e) {
e.printStackTrace();
}
return socket;
}
More details can be found here:
Could anybody please clarify why this statement:
slSocketFactory = jsseHelper.getSSLSocketFactory(sslMap, sslProps)
returns incorrect 'SSL socket factory' while this statement
SSLSocketFactory.getDefault()
returns the correct one?
Moreover, in what case should I use factory retrieved from these statements respectively?
SSLSocketFactory.getDefault();
jsseHelper.getSSLSocketFactory(sslMap, sslProps)
getSSLSocketFactory(java.lang.String sslAliasName, java.util.Map connectionInfo, SSLConfigChangeListener listener)
Thank you very much
Although it is not intuitive, statement:
SSLSocketFactory factory = SSLSocketFactory.getDefault();
returns the WebSphere custom SSLSocketFactory.
Then you can enforce SSL-configuration on thread in this way:
Properties sslProperties = getProperties();
jsseHelper.setSSLPropertiesOnThread(sslProperties);
SSLSocket socket = getSslSocket();
CommonIO.writeToSocket(socket, "127.0.0.1", 1234);
jsseHelper.setSSLPropertiesOnThread(null);
Although JSSEHelper.getSSLSocketFactory(sslMap, sslConfig_XYZ) returns also factory but their sockets ignore cipher suites encapsulated in SSL-configuration sslConfig_XYZ.
On the other hand, if you want to enforce only
protocol
keystore
truststore
this method:
JSSEHelper.getSSLSocketFactory(sslMap, sslConfig_XYZ)
is sufficient enough.

HTTP Client with https

What is the best way to process HTTP GET Method with SSL using HTTP Components HTTPClient 4 Project?
what is the best way to parametrized certification info? properties file? reload method to Daemon Service?
HttpClient httpClient = new DefaultHttpClient();
String url = "https://xxx.190.2.45/index.jsp";
HttpGet get = new HttpGet(url);
try {
//TODO
HTTPHelper.addSSLSupport(httpClient);
HttpResponse response = httpClient.execute(get);
BasicResponseHandler responseHandler = new BasicResponseHandler();
String responseString = responseHandler.handleResponse(response);
} catch (ClientProtocolException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
You'll need to enable the SSL support, see the tutorial for more information
I'm under the impression that you're using a self-signed certificate for the server. What you probably should do is look at getting openssl, generate yourself a CA & server certificate. Put the CA certificate (not the private key) in a "trust store" and configure the socket factory.
If you need more detail on how to do this, just comment on this and I'll flesh out some more. I've had great success with simple local projects!

How can I get the Client Certificate in Netty Handler to identify user?

I am successfully running Netty with 2-way SSL (see Set up Netty with 2-way SSL Handsake (client and server certificate)).
However, in some of my handlers, I need to know about the user who is using the application. I find that I can't figure out how to get information like the user certificate DN in my handlers.
I would think it would be available in the ChannelHandlerContext somewhere but it is not. Any suggestions?
I know the SSLEngine has access to it somewhere, but I don't see anything about obtaining access in the SSLEngine public API. I know it has access in the handshake operation.... but how do I get it?
The SSLEngine can be fetched through the Pipline/ChannelHandlerContext
ChannelHandlerContext ctx = ...
SslHandler sslhandler = (SslHandler) ctx.channel().pipeline().get("ssl");
sslhandler.engine().getSession().getPeerCertificateChain()[0].getSubjectDN());
This allows you to get the certificates in the Handler Objects. Pay attention, that the SSL-Handshake needs to be finished when you do this. Otherwise you will get a
javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
exception. To avoid this, you can listen for a userEvent (in our case HandshakeCompletionEvent) in the handler, which could look the following:
#Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
logger.info("userEventTriggered: {0}, Class: {1}", evt.toString(), evt.getClass());
if (evt instanceof HandshakeCompletionEvent) {
fetchCertificate(ctx);
}
}
SSLEngine.getSession().getPeerCertificateChain(). The zeroth entry is the peer's own certificate.
I used the following codes to get the client certificate and certificate's issuer. I hope it helps.
SslHandler sslHandler = (SslHandler) ctx.channel().pipeline().get("ssl");
X509Certificate issuer = convert(sslHandler.engine().getSession().getPeerCertificateChain()[sslHandler.engine().getSession().getPeerCertificateChain().length -1]);
System.out.println("issuer: " + issuer);
public static java.security.cert.X509Certificate convert(javax.security.cert.X509Certificate cert) {
try {
byte[] encoded = cert.getEncoded();
ByteArrayInputStream bis = new ByteArrayInputStream(encoded);
java.security.cert.CertificateFactory cf
= java.security.cert.CertificateFactory.getInstance("X.509");
return (java.security.cert.X509Certificate)cf.generateCertificate(bis);
} catch (java.security.cert.CertificateEncodingException e) {
} catch (javax.security.cert.CertificateEncodingException e) {
} catch (java.security.cert.CertificateException e) {
}
return null;
}