Is there any method in netty ssl client to know if server requested client certificate after completion of SSL Handshake process - ssl

I have a Netty HTTPS(SSL ENABLED) Client which communicates with both Mutual Authentication enabled servers and Mutual Authentication non-enabled servers.
Following is the code I use to Setup SSL Handler for Client.
TrustManagerFactory tmf= ...// Necessary Trust certs
KeyManagerFactory kmf = ...// Necessary Client certs
SslContext sslContext = SslContextBuilder.forClient().keyManager(kmf).trustManager(tmf).build();
SslHandler sslHandler = sslContex.newHandler(ByteBuffAllocator);
I use the above sslHandler in the pipeline. I know that providing keyManager(kmf) will provide client certificate to server if server requests. Everything works as expected.
MY NEED : I need to know if the Server requested Client certificate or not(ie. Mutual Auth enabled server or not) in SSL Handshake process. I need to know this after completion of Handshake process.

You could provide your own KeyManager implementation (that later calls the actual KeyManager). If getPrivateKey() is called you know that the server has requested the client certificate.

Related

SSL and JKS to TLS 1.2 client side

I am running an old version of jetty that allows SSL TLS v1.0 and v1.1. I want to disable anything other than TLS 1.2 as there are security vulnerabilities with the other implementations.
Currently clients connect to the jetty server using SSL, without any jks file for java clients or any certs or pk12 equivalent for c#/.net clients.
My understanding of jks is that the client and server needs it, which isn't a vulnerability in itself as the alias and servers should not be available in the jks file.
So my question is when I enforce stricter security protocol TLS 1.2 do i need to provide the clients with jks/pk12 or whatever the windows equivalent is? If i dont change the code to allow trustAll etc?
Client(is a request running within jetty server 9.4) server and request code:
System.setProperty("javax.net.ssl.trustStore", "filename");
System.setProperty("java.net.ssl.trustStorePassword", "xyx")
ServletContextHandler context =
ServletContextHandler(ServletContextHandler.SESSIONS);
...
server.setPort(8080);
server.start();
//Then call is via apache server code
CLoseableHttpClient httpClient = HttpClients.createMinimal();
HttpGet httpGet = new HttpGet("https://server:8080/getLogisticsData");
...
httpClient.execute(httpGet), response -> {
//format response
}));

Disabling certificate check in gRPC TLS

Currently, I have a ngnix server (on port 5001) behind which a gRPC server is running, nginx having TLS enabled. All gRPC clients need to send the request to nginx port which forwards to gRPC server running. Initially for testing had gRPC request using usePlaintext() and it all worked fine, but the end goal is to use TLS. The requirement here is (as this are internal applications), gRPC channel request need not pass certificate but do a "skip certificate" when creating the channel.
After Googling around, I found examples on TLS but all of them does take .cert, .key file. Below is snippet which i tried and it failed at the server end couldn't validate the certificate
(java code)
ManagedChannel channel = NettyChannelBuilder.forAddress(<server IP address>, 5001).sslContext(GrpcSslContexts.forClient().trustManager
(new File(<.cert file>).build())
.build();
Doing some more research, i see Golang has InsecureSkipVerify() using which i can skip ceritifcate check (pls correct me if i am wrong)
tc := credentials.NewTLS(&tls.Config{
InsecureSkipVerify: true,
})
Now how do I accomplish the same in java?
TLS with disabled certificate checking is of questionable usefulness because it can be trivially MITMed and so is not "supported" by gRPC. I highly recommend providing the client with proper root certificates to verify the server.
That said, you can go around gRPC's API to do this by passing Netty's InsecureTrustManagerFactory to SslContextBuilder.trustManager(TrustManagerFactory):
NettyChannelBuilder.forAddress("<server IP address>", 5001)
.sslContext(GrpcSslContexts.forClient()
.trustManager(InsecureTrustManagerFactory.INSTANCE)
.build())
.build();

How to get Remote server untrusted SSL certificate using Apache HTTP Client API

I have a remote server which may or may not be running using a valid SSL cert (using self-signed SSL cert).
We are making connection to remote server, which may fail if remote server is using self-signed SSL cert. So, we want to be able to download/view the remote server cert if our SSL handshake fails.
If I use Apache HTTP Client then I couldn't find a method which could allow me to view remote server certificate (you can do it with HttpsURLConnection but we are trying to avoid using it see this example).
I also looked into Spring RestTemplate, and it didn't provide any option either - I searched on Google and didn't find anything around Spring or Apache HTTP Client.
This should give you pretty much a complete control over the process of trust verification.
SSLContext sslContext = SSLContextBuilder.create()
.loadTrustMaterial((chain, authType) -> {
for (X509Certificate cert: chain) {
System.out.println(cert.getSubjectDN());
}
// Let the standard trust managers decide
// whether or not the cert chain is trusted
return false;
})
.build();
CloseableHttpClient client = HttpClientBuilder.create()
.setSSLContext(sslContext)
.build();

Client certificates with AWS API Gateway

I am trying to implement mutual authentication for the communication between aws api gateway and my server. I want to use the client side certificates that amazon offers for authentication. I know that my server is configured correctly because previously I was using a lambda function and mutual authentication was working.
I have exported the (.PEM) certificate and added it into a truststore. I have configured my Jetty server to use that truststore for authentication. I have set client-auth to :need. I know my server is set up correctly because it was working with with my self-implemented mutual SSL. All I did was change the truststore. When I test my method gateway returns a 200:
{ "message": "Unknown endpoint error."}
Here is an excerpt from the server log files. It appears that the server side handshake completes, but there is an error with the client certificate.
pConnection#3a0a2e84{FILLING} server-side handshake completed
2015-09-28 13:04:29,856 DEBUG [qtp1980278840-19]
o.e.j.i.ChannelEndPoint - flushed 45
SelectChannelEndPoint#2c05eeb2{ec2-xx-xxx-xxx-x.compute-1.amazonaws.com/5x.xxx.xxx.x:43942<->4000,Open,in,out,-,-,0/200000,SslConnection}{io=0,kio=0,kro=1}
2015-09-28 13:04:29,856 DEBUG [qtp1980278840-19]
o.e.j.i.s.SslConnection -
SslConnection#50e2de43{NOT_HANDSHAKING,eio=0/0,di=-1} ->
HttpConnection#3a0a2e84{FILLING} flush exit, consumed 0 2015-09-28
13:04:29,856 DEBUG [qtp1980278840-19] o.e.j.i.s.SslConnection -
SslConnection#50e2de43{NOT_HANDSHAKING,eio=0/-1,di=-1} ->
HttpConnection#3a0a2e84{FILLING} unwrap Status = BUFFER_UNDERFLOW
HandshakeStatus = NOT_HANDSHAKING
I have solved this problem. The server logs I posted are misleading. No handshake occurs because the server certificate I was using was self signed, not signed by a trusted CA. As of 9/28/2015, aws api gateway requires a certificate signed by a trusted certificate authority. Because my cert was self signed, the server (and client) handshakes do not complete. Hopefully this problem will be solved in future versions.

Set up Netty-with TLS handsake with ECC and RSA client certificate auth

I am working on a remote server that uses Netty to perform client authentication with a TLS handshake through the Netty SSLHandler library. This S/O question gives a bit: Set up Netty with 2-way SSL Handsake (client and server certificate)
Now, the question I have about this system is that the Server requires a TrustManager to initialize a SSLContext. From what I observe this uses the SunJSSE provider. Now after setting up this implementation, I got it working with RSA client certs. Now, I am having trouble using ECC client certs as SunJSSE cannot recognize them (I think Java SE 7 include SunEC as a provider. But SunEC is a SunJCE implementation and not a SunJSSE one and thus cannot be used as a provider for TrustManager). So, how do I proceed. I heard Bouncy Castle can recognize these certs, but I still cannot instantiate a TrustManager with BC as the provider.
Edit: Also if there is no way to use TrustManagers, should I do the entire handshake only use BouncyCastle's API's and not netty's libraries? That seems off though.
This is my other S/O question that shows the stack trace: Client ECC SSL Certificate contains "unknown named curve"