Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TLS with SNI in Java clients

There is an ongoing discussion on the security and trust working group for NHIN Direct regarding the IP-to-domain mapping problem that is created with traditional SSL. If an HISP (as defined by NHIN Direct) wants to host thousands of NHIN Direct "Health Domains" for providers, then it will an "artificially inflated cost" to have to purchase an IP for each of those domains.

Because Apache and OpenSSL have recently released TLS with support for the SNI extension, it is possible to use SNI as a solution to this problem on the server side. However, if we decide that we will allow server implementations of the NHINDirect transport layer to support TLS+SNI, then we must require that all clients support SNI too. OpenSSL based clients should do this by default and one could always us stunnel to implement an TLS+SNI aware client to proxy if your given programming language SSL implementation does not support SNI. It appears that native Java applications using OpenJDK do not yet support SNI, but I cannot get a straight answer out of that project. I know that there are OpenSSL Java libraries available but I have no idea if that would be considered viable.

Can you give me a "state of the art" summary of where TLS+SNI support is for Java clients? I need a Java implementers perspective on this.

like image 967
ftrotter Avatar asked May 10 '10 16:05

ftrotter


People also ask

Does TLS 1.2 support SNI?

SNI (server name indication) works with TLS 1.2, but rejected by server on TLS 1.0. Save this question.

What is the use of SNI in TLS?

Server Name Indication (SNI) is an extension to the TLS protocol. It allows a client or browser to indicate which hostname it is trying to connect to at the start of the TLS handshake. This allows the server to present multiple certificates on the same IP address and port number.

What is SNI in Java?

The SNI extension is a feature that extends the SSL/TLS protocols to indicate what server name the client is attempting to connect to during handshaking. Servers can use server name indication information to decide whether specific SSLSocket or SSLEngine instances should accept a connection.

Is SNI in client hello?

Specifically, SNI includes the hostname in the Client Hello message, or the very first step of a TLS handshake.


2 Answers

JavaSE 7 has SNI Support in JSSE.

http://docs.oracle.com/javase/7/docs/technotes/guides/security/enhancements-7.html

Note, there seems to be a problem with it, as you can read here:

SSL handshake alert: unrecognized_name error since upgrade to Java 1.7.0

like image 129
3 revs Avatar answered Sep 29 '22 08:09

3 revs


it is also possible to patch with some lines the orig Sun JDK (bootclasspath) to get Server SNI working.

Class: sun.security.ssl.ServerHandshaker

Add Field

    /** Use for SNI */
    private ServerNameExtension serverNameExtension = null;

Patch Method clientHello (add these lines)

    /* Use for SNI */
    this.serverNameExtension = (ServerNameExtension)mesg.extensions.get(ExtensionType.EXT_SERVER_NAME);

Patch Method setupPrivateKeyAndChain (change)

    if (this.conn != null) { alias = km.chooseServerAlias(algorithm      , null, this.conn);
    } else                 { alias = km.chooseEngineServerAlias(algorithm, null, this.engine); }

to

    final Principal[] principals = (this.serverNameExtension == null) ? null : this.serverNameExtension.getHostnamePrincipals();
    if (this.conn != null) { alias = km.chooseServerAlias(algorithm      , principals, this.conn);
    } else                 { alias = km.chooseEngineServerAlias(algorithm, principals, this.engine); }

Add to Class sun.security.ssl.ServerNameExtension

static final class ServerNamePrincipal implements Principal {
    private final String name;
    ServerNamePrincipal(final String name) { this.name = name; }
    @Override public String getName() { return this.name; }
    @Override public String toString() { return this.name; }
}

public Principal[] getHostnamePrincipals() {
    final List<Principal> principals = new LinkedList<>();
    for(final ServerName name : this.names) {
        if(name.type == NAME_HOST_NAME) { principals.add(new ServerNamePrincipal(name.hostname)); }
    }
    return principals.toArray(new Principal[principals.size()]);
}
like image 35
SkateScout Avatar answered Sep 29 '22 07:09

SkateScout