org.wildfly.security.ssl.SSLConnection Maven / Gradle / Ivy
Go to download
This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including
all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and
JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up
with different versions on classes on the class path).
/*
* JBoss, Home of Professional Open Source.
* Copyright 2017 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.wildfly.security.ssl;
import static org.wildfly.security.ssl.TLSServerEndPointChannelBinding.*;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import org.wildfly.common.Assert;
import org.wildfly.security.auth.callback.ChannelBindingCallback;
/**
* An SSL connection of some sort.
*
* @author David M. Lloyd
*/
public abstract class SSLConnection {
SSLConnection() {
}
/**
* Get the SSL session associated with this connection.
*
* @return the SSL session associated with this connection, or {@code null} if there is none
*/
public abstract SSLSession getSession();
/**
* Get the client-mode flag for this connection.
*
* @return the client-mode flag for this connection
*/
public abstract boolean isClientMode();
/**
* Get the channel binding of the given type from this connection. If the data is not present or the type is not
* supported, {@code null} is returned.
*
* @return the channel binding of the given type from this connection, or {@code null} if it is not supported
*/
public byte[] getChannelBinding(String bindingType) {
// in JDK 10 and later (presumably), this method will be made abstract and the concrete impls will delegate directly to JSSE
final boolean clientMode = isClientMode();
switch (bindingType) {
case TLS_SERVER_ENDPOINT: {
final X509Certificate serverCert;
final SSLSession session = getSession();
if (session == null) {
return null;
}
if (clientMode) {
Certificate[] peerCertificates;
try {
peerCertificates = session.getPeerCertificates();
} catch (SSLPeerUnverifiedException e) {
peerCertificates = null;
}
serverCert = peerCertificates != null && peerCertificates.length > 0 ? (X509Certificate) peerCertificates[0] : null;
} else {
final Certificate[] localCertificates = session.getLocalCertificates();
serverCert = localCertificates != null && localCertificates.length > 0 ? (X509Certificate) localCertificates[0] : null;
}
try {
return getChannelBindingData(serverCert);
} catch (NoSuchAlgorithmException | CertificateEncodingException e) {
return null;
}
}
default: {
return null;
}
}
}
/**
* Populate the given channel binding callback with any channel binding data that might be present on this
* connection. If no channel binding seems to be supported, then the callback will be left unpopulated.
*
* @param callback the binding callback to populate (must not be {@code null})
*/
public void handleChannelBindingCallback(final ChannelBindingCallback callback) {
Assert.checkNotNullParam("callback", callback);
byte[] bindingData = getChannelBinding("tls-unique");
if (bindingData != null) {
callback.setBindingType("tls-unique");
callback.setBindingData(bindingData);
} else {
bindingData = getChannelBinding(TLS_SERVER_ENDPOINT);
if (bindingData != null) {
callback.setBindingType(TLS_SERVER_ENDPOINT);
callback.setBindingData(bindingData);
}
}
}
/**
* Create a {@code SSLConnection} for the given SSL engine.
*
* @param engine the SSL engine (must not be {@code null})
* @return the SSL connection (not {@code null})
*/
public static SSLConnection forEngine(SSLEngine engine) {
Assert.checkNotNullParam("engine", engine);
return new SSLConnection() {
public SSLSession getSession() {
return engine.getSession();
}
public boolean isClientMode() {
return engine.getUseClientMode();
}
};
}
/**
* Create a {@code SSLConnection} for the given SSL socket.
*
* @param socket the SSL socket (must not be {@code null})
* @return the SSL connection (not {@code null})
*/
public static SSLConnection forSocket(SSLSocket socket) {
Assert.checkNotNullParam("socket", socket);
return new SSLConnection() {
public SSLSession getSession() {
return socket.getSession();
}
public boolean isClientMode() {
return socket.getUseClientMode();
}
};
}
/**
* Create a {@code SSLConnection} for the given SSL socket. Since no connection information will be
* available in this case, not all channel binding modes will be supported.
*
* @param session the SSL session (must not be {@code null})
* @param clientMode {@code true} if the session is client-side, {@code false} if it is server-side
* @return the SSL connection (not {@code null})
*/
public static SSLConnection forSession(SSLSession session, boolean clientMode) {
Assert.checkNotNullParam("session", session);
return new SSLConnection() {
public SSLSession getSession() {
return session;
}
public boolean isClientMode() {
return clientMode;
}
};
}
}