powered by Jive Software

RFE: upgrade socket to STARTTLS with custom SSLSocketFactory as alternative


#1

In some use cases I have a custom SSLSocketFactory instead of an SSLContext. This RFE is for the purpose of upgrading to STARTTLS using a custom SSLSocketFactory as an alternative to the (current) SSLContext.

The only time we use getCustomSSLContext() is to get the context to get the factory, therefore it is useful if we could inject the factory directly.

More detailed use case: with smartcards it is easier to create a SSLSocketFactory than a custom SSLContext.

Proposed API

ConnectionConfiguration.Builder

public B setCustomSSLSocketFactory(SSLSocketFactory factory) {
this.customSSLSocketFactory = Objects.requireNonNull(factory, “The SSLSocketFactory must not be null”);
return getThis();
}
etc etc

XMPPTCPConnection.java:

private void proceedTLSReceived() {

SSL factory = this.config.getCustomSSLSocketFactory();
if (factory == null) {
// then set the SSLContext context var
}

Socket plain = socket;
// Secure the plain connection
if (factory != null) {
socket = factory.createSocket(plain,
config.getXMPPServiceDomain().toString(), plain.getPort(), true);
else {
socket = context.getSocketFactory().createSocket(plain,
config.getXMPPServiceDomain().toString(), plain.getPort(), true);
}
}

Happy to do a PR if you think this RFE is workable.


#2

Bumping this

I see that there were several customizations done to the configuration class org.jivesoftware.smack.ConnectionConfiguration to make TLS parameters more configurable but there are still use cases that require access to either SSLSocket or SSLEngine directly such as using a custom SSLSocketFactory or indirectly via javax.net.ssl.SSLParameters.

For example for me being able to connect to a service requiring SNI extension requires access to javax.net.ssl.SSLParameters#setServerNames but the sockets that smack-tcp currently creates are encapsulated and do not have access to the custom socket factory.
Eg. as OP posted in the snippet from library source the custom factory can be specified for initial socket creation but not for upgrade to secure socket.

context.getSocketFactory().createSocket(...)

Will you accept a PR for this? There are several ways to go about it from either most flexible way of allowing a custom SSLSocketFactory to providing a hook that allows custom SSLParameters to be set on a newly created SSLSocket before handshaking.


#3

If I understand you correctly, you want to specify a custom SSLSocketFactory, and propose to extend ConnectionConfiguration by something like setCustomSslSocketFactory(SSLSocketFactory). But are you not already able to just configure a SSLContext which returns your SSLSocketFactory?


#4

@Flow - SSLContext objects are very onerous to subclass; you also need to subclass SSLContextSpi.

SSLContext::getSocketFactory() is final and delegates to SSLContextSpi::engineGetSocketFactory

This relies on looking at the actual implementation in SSLContext.java and relies on undocumented behaviour.

It is much much(+1000) easier to inject a custom SSLSocketFactory


#5

@Flow Thats precisely what I’m asking.

Either explicitly being able to control SSLSocketFactory or SSLSocket or implicitly have the library provide a hook point where SSLParameters on the socket can be adjusted (eg. after creation and application of TLS protocols/ciphers in the config object).
SSLContext customization is important and pretty much takes care of most cases for your users but not all the cases unfortunately.

If you look at the JSSE API you cannot set a factory on the context only get at it and as @rc556677 mentioned its quite onerous but I’d say its pretty much impractical. You can also only get default SSLParameters for sockets from the context but not change them as these can only be set on individual SSLSocket or SSLEngine objects which are encapsulated.

As a reference for SNI control and (other customisations more cases) This is the API required to be called to set up appropriate SNI in my case https://docs.oracle.com/javase/8/docs/api/javax/net/ssl/SSLSocket.html#setSSLParameters-javax.net.ssl.SSLParameters-