use of org.apache.tomcat.util.net.openssl.OpenSSLConf in project tomcat by apache.
the class TestSSLHostConfig method testSerialization.
@Test
public void testSerialization() throws IOException, ClassNotFoundException {
// Dummy OpenSSL command name/value pair
String name = "foo";
String value = "bar";
// Set up the object
SSLHostConfig sslHostConfig = new SSLHostConfig();
OpenSSLConf openSSLConf = new OpenSSLConf();
OpenSSLConfCmd openSSLConfCmd = new OpenSSLConfCmd();
openSSLConfCmd.setName(name);
openSSLConfCmd.setValue(value);
openSSLConf.addCmd(openSSLConfCmd);
sslHostConfig.setOpenSslConf(openSSLConf);
// Serialize
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(sslHostConfig);
oos.close();
// Deserialize
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
SSLHostConfig output = (SSLHostConfig) ois.readObject();
// Check values
List<OpenSSLConfCmd> commands = output.getOpenSslConf().getCommands();
Assert.assertEquals(1, commands.size());
OpenSSLConfCmd command = commands.get(0);
Assert.assertEquals(name, command.getName());
Assert.assertEquals(value, command.getValue());
}
use of org.apache.tomcat.util.net.openssl.OpenSSLConf in project tomcat by apache.
the class OpenSSLConfSF method storeChildren.
/**
* Store nested OpenSSLConfCmd elements.
* {@inheritDoc}
*/
@Override
public void storeChildren(PrintWriter aWriter, int indent, Object aOpenSSLConf, StoreDescription parentDesc) throws Exception {
if (aOpenSSLConf instanceof OpenSSLConf) {
OpenSSLConf openSslConf = (OpenSSLConf) aOpenSSLConf;
// Store nested <OpenSSLConfCmd> elements
OpenSSLConfCmd[] openSSLConfCmds = openSslConf.getCommands().toArray(new OpenSSLConfCmd[0]);
storeElementArray(aWriter, indent + 2, openSSLConfCmds);
}
}
use of org.apache.tomcat.util.net.openssl.OpenSSLConf in project tomcat by apache.
the class SSLHostConfigSF method storeChildren.
/**
* Store nested SSLHostConfigCertificate elements.
* {@inheritDoc}
*/
@Override
public void storeChildren(PrintWriter aWriter, int indent, Object aSSLHostConfig, StoreDescription parentDesc) throws Exception {
if (aSSLHostConfig instanceof SSLHostConfig) {
SSLHostConfig sslHostConfig = (SSLHostConfig) aSSLHostConfig;
// Store nested <SSLHostConfigCertificate> elements
SSLHostConfigCertificate[] hostConfigsCertificates = sslHostConfig.getCertificates().toArray(new SSLHostConfigCertificate[0]);
// Remove a possible default UNDEFINED certificate
if (hostConfigsCertificates.length > 1) {
ArrayList<SSLHostConfigCertificate> certificates = new ArrayList<>();
for (SSLHostConfigCertificate certificate : hostConfigsCertificates) {
if (Type.UNDEFINED != certificate.getType()) {
certificates.add(certificate);
}
}
hostConfigsCertificates = certificates.toArray(new SSLHostConfigCertificate[0]);
}
storeElementArray(aWriter, indent, hostConfigsCertificates);
// Store nested <OpenSSLConf> element
OpenSSLConf openSslConf = sslHostConfig.getOpenSslConf();
storeElement(aWriter, indent, openSslConf);
}
}
use of org.apache.tomcat.util.net.openssl.OpenSSLConf in project tomcat by apache.
the class OpenSSLContext method init.
/**
* Setup the SSL_CTX.
*
* @param kms Must contain a KeyManager of the type
* {@code OpenSSLKeyManager}
* @param tms Must contain a TrustManager of the type
* {@code X509TrustManager}
* @param sr Is not used for this implementation.
*/
@Override
public synchronized void init(KeyManager[] kms, TrustManager[] tms, SecureRandom sr) {
if (initialized) {
log.warn(sm.getString("openssl.doubleInit"));
return;
}
try {
if (sslHostConfig.getInsecureRenegotiation()) {
SSL_CTX_set_options(state.sslCtx, SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION());
} else {
SSL_CTX_clear_options(state.sslCtx, SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION());
}
// client's)
if (sslHostConfig.getHonorCipherOrder()) {
SSL_CTX_set_options(state.sslCtx, SSL_OP_CIPHER_SERVER_PREFERENCE());
} else {
SSL_CTX_clear_options(state.sslCtx, SSL_OP_CIPHER_SERVER_PREFERENCE());
}
// Disable compression if requested
if (sslHostConfig.getDisableCompression()) {
SSL_CTX_set_options(state.sslCtx, SSL_OP_NO_COMPRESSION());
} else {
SSL_CTX_clear_options(state.sslCtx, SSL_OP_NO_COMPRESSION());
}
// Disable TLS Session Tickets (RFC4507) to protect perfect forward secrecy
if (sslHostConfig.getDisableSessionTickets()) {
SSL_CTX_set_options(state.sslCtx, SSL_OP_NO_TICKET());
} else {
SSL_CTX_clear_options(state.sslCtx, SSL_OP_NO_TICKET());
}
// List the ciphers that the client is permitted to negotiate
if (SSL_CTX_set_cipher_list(state.sslCtx, CLinker.toCString(sslHostConfig.getCiphers(), state.contextScope)) <= 0) {
log.warn(sm.getString("engine.failedCipherSuite", sslHostConfig.getCiphers()));
}
if (certificate.getCertificateFile() == null) {
certificate.setCertificateKeyManager(OpenSSLUtil.chooseKeyManager(kms));
}
addCertificate(certificate);
// Client certificate verification
int value = 0;
switch(sslHostConfig.getCertificateVerification()) {
case NONE:
value = SSL_VERIFY_NONE();
break;
case OPTIONAL:
value = SSL_VERIFY_PEER();
break;
case OPTIONAL_NO_CA:
value = OPTIONAL_NO_CA;
break;
case REQUIRED:
value = SSL_VERIFY_FAIL_IF_NO_PEER_CERT();
break;
}
// SSLContext.setVerify(state.ctx, value, sslHostConfig.getCertificateVerificationDepth());
if (SSL_CTX_set_default_verify_paths(state.sslCtx) > 0) {
var store = SSL_CTX_get_cert_store(state.sslCtx);
X509_STORE_set_flags(store, 0);
}
// Set int verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) callback
MemoryAddress openSSLCallbackVerify = CLinker.getInstance().upcallStub(openSSLCallbackVerifyHandle, openSSLCallbackVerifyFunctionDescriptor, state.contextScope);
// Leave this just in case but in Tomcat this is always set again by the engine
SSL_CTX_set_verify(state.sslCtx, value, openSSLCallbackVerify);
// Trust and certificate verification
var allocator = SegmentAllocator.ofScope(state.contextScope);
if (tms != null) {
// Client certificate verification based on custom trust managers
state.x509TrustManager = chooseTrustManager(tms);
MemoryAddress openSSLCallbackCertVerify = CLinker.getInstance().upcallStub(openSSLCallbackCertVerifyHandle, openSSLCallbackCertVerifyFunctionDescriptor, state.contextScope);
SSL_CTX_set_cert_verify_callback(state.sslCtx, openSSLCallbackCertVerify, state.sslCtx);
// an acceptable certificate
for (X509Certificate caCert : state.x509TrustManager.getAcceptedIssuers()) {
// SSLContext.addClientCACertificateRaw(state.ctx, caCert.getEncoded());
var rawCACertificate = allocator.allocateArray(CLinker.C_CHAR, caCert.getEncoded());
var rawCACertificatePointer = allocator.allocate(CLinker.C_POINTER, rawCACertificate);
var x509CACert = d2i_X509(MemoryAddress.NULL, rawCACertificatePointer, rawCACertificate.byteSize());
if (MemoryAddress.NULL.equals(x509CACert)) {
logLastError(allocator, "openssl.errorLoadingCertificate");
} else if (SSL_CTX_add_client_CA(state.sslCtx, x509CACert) <= 0) {
logLastError(allocator, "openssl.errorAddingCertificate");
} else if (log.isDebugEnabled()) {
log.debug(sm.getString("openssl.addedClientCaCert", caCert.toString()));
}
}
} else {
// Client certificate verification based on trusted CA files and dirs
// SSLContext.setCACertificate(state.ctx,
// SSLHostConfig.adjustRelativePath(sslHostConfig.getCaCertificateFile()),
// SSLHostConfig.adjustRelativePath(sslHostConfig.getCaCertificatePath()));
MemorySegment caCertificateFileNative = sslHostConfig.getCaCertificateFile() != null ? CLinker.toCString(SSLHostConfig.adjustRelativePath(sslHostConfig.getCaCertificateFile()), state.contextScope) : null;
MemorySegment caCertificatePathNative = sslHostConfig.getCaCertificatePath() != null ? CLinker.toCString(SSLHostConfig.adjustRelativePath(sslHostConfig.getCaCertificatePath()), state.contextScope) : null;
if (SSL_CTX_load_verify_locations(state.sslCtx, caCertificateFileNative == null ? MemoryAddress.NULL : caCertificateFileNative, caCertificatePathNative == null ? MemoryAddress.NULL : caCertificatePathNative) <= 0) {
logLastError(allocator, "openssl.errorConfiguringLocations");
} else {
var caCerts = SSL_CTX_get_client_CA_list(state.sslCtx);
if (MemoryAddress.NULL.equals(caCerts)) {
caCerts = SSL_load_client_CA_file(caCertificateFileNative);
if (!MemoryAddress.NULL.equals(caCerts)) {
SSL_CTX_set_client_CA_list(state.sslCtx, caCerts);
}
} else {
if (SSL_add_file_cert_subjects_to_stack(caCerts, caCertificateFileNative) <= 0) {
caCerts = MemoryAddress.NULL;
}
}
if (MemoryAddress.NULL.equals(caCerts)) {
log.warn(sm.getString("openssl.noCACerts"));
}
}
}
if (state.negotiableProtocols != null && state.negotiableProtocols.size() > 0) {
// int openSSLCallbackAlpnSelectProto(MemoryAddress ssl, MemoryAddress out, MemoryAddress outlen,
// MemoryAddress in, int inlen, MemoryAddress arg
MemoryAddress openSSLCallbackAlpnSelectProto = CLinker.getInstance().upcallStub(openSSLCallbackAlpnSelectProtoHandle, openSSLCallbackAlpnSelectProtoFunctionDescriptor, state.contextScope);
SSL_CTX_set_alpn_select_cb(state.sslCtx, openSSLCallbackAlpnSelectProto, state.sslCtx);
// Skip NPN (annoying and likely not useful anymore)
// SSLContext.setNpnProtos(state.ctx, protocolsArray, SSL.SSL_SELECTOR_FAILURE_NO_ADVERTISE);
}
// Apply OpenSSLConfCmd if used
OpenSSLConf openSslConf = sslHostConfig.getOpenSslConf();
if (openSslConf != null && !MemoryAddress.NULL.equals(state.confCtx)) {
// Check OpenSSLConfCmd if used
if (log.isDebugEnabled()) {
log.debug(sm.getString("openssl.checkConf"));
}
try {
if (!checkConf(openSslConf)) {
log.error(sm.getString("openssl.errCheckConf"));
throw new Exception(sm.getString("openssl.errCheckConf"));
}
} catch (Exception e) {
throw new Exception(sm.getString("openssl.errCheckConf"), e);
}
if (log.isDebugEnabled()) {
log.debug(sm.getString("openssl.applyConf"));
}
try {
if (!applyConf(openSslConf)) {
log.error(sm.getString("openssl.errApplyConf"));
throw new SSLException(sm.getString("openssl.errApplyConf"));
}
} catch (Exception e) {
throw new SSLException(sm.getString("openssl.errApplyConf"), e);
}
// Reconfigure the enabled protocols
long opts = SSL_CTX_get_options(state.sslCtx);
List<String> enabled = new ArrayList<>();
// Seems like there is no way to explicitly disable SSLv2Hello
// in OpenSSL so it is always enabled
enabled.add(Constants.SSL_PROTO_SSLv2Hello);
if ((opts & SSL_OP_NO_TLSv1()) == 0) {
enabled.add(Constants.SSL_PROTO_TLSv1);
}
if ((opts & SSL_OP_NO_TLSv1_1()) == 0) {
enabled.add(Constants.SSL_PROTO_TLSv1_1);
}
if ((opts & SSL_OP_NO_TLSv1_2()) == 0) {
enabled.add(Constants.SSL_PROTO_TLSv1_2);
}
if ((opts & SSL_OP_NO_TLSv1_3()) == 0) {
enabled.add(Constants.SSL_PROTO_TLSv1_3);
}
if ((opts & SSL_OP_NO_SSLv2()) == 0) {
enabled.add(Constants.SSL_PROTO_SSLv2);
}
if ((opts & SSL_OP_NO_SSLv3()) == 0) {
enabled.add(Constants.SSL_PROTO_SSLv3);
}
sslHostConfig.setEnabledProtocols(enabled.toArray(new String[0]));
// Reconfigure the enabled ciphers
sslHostConfig.setEnabledCiphers(getCiphers(state.sslCtx));
}
sessionContext = new OpenSSLSessionContext(this);
// If client authentication is being used, OpenSSL requires that
// this is set so always set it in case an app is configured to
// require it
sessionContext.setSessionIdContext(DEFAULT_SESSION_ID_CONTEXT);
sslHostConfig.setOpenSslContext(state.sslCtx.toRawLongValue());
initialized = true;
} catch (Exception e) {
log.warn(sm.getString("openssl.errorSSLCtxInit"), e);
destroy();
}
}
Aggregations