Search in sources :

Example 1 with OpenSSLConf

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());
}
Also used : OpenSSLConfCmd(org.apache.tomcat.util.net.openssl.OpenSSLConfCmd) ByteArrayInputStream(java.io.ByteArrayInputStream) OpenSSLConf(org.apache.tomcat.util.net.openssl.OpenSSLConf) ByteArrayOutputStream(java.io.ByteArrayOutputStream) ObjectOutputStream(java.io.ObjectOutputStream) ObjectInputStream(java.io.ObjectInputStream) Test(org.junit.Test)

Example 2 with OpenSSLConf

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);
    }
}
Also used : OpenSSLConfCmd(org.apache.tomcat.util.net.openssl.OpenSSLConfCmd) OpenSSLConf(org.apache.tomcat.util.net.openssl.OpenSSLConf)

Example 3 with OpenSSLConf

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);
    }
}
Also used : SSLHostConfigCertificate(org.apache.tomcat.util.net.SSLHostConfigCertificate) ArrayList(java.util.ArrayList) OpenSSLConf(org.apache.tomcat.util.net.openssl.OpenSSLConf) SSLHostConfig(org.apache.tomcat.util.net.SSLHostConfig)

Example 4 with 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();
    }
}
Also used : ArrayList(java.util.ArrayList) OpenSSLConf(org.apache.tomcat.util.net.openssl.OpenSSLConf) SSLException(javax.net.ssl.SSLException) AbstractEndpoint(org.apache.tomcat.util.net.AbstractEndpoint) X509Certificate(java.security.cert.X509Certificate) MemorySegment(jdk.incubator.foreign.MemorySegment) CertificateException(java.security.cert.CertificateException) SSLException(javax.net.ssl.SSLException) MemoryAddress(jdk.incubator.foreign.MemoryAddress)

Aggregations

OpenSSLConf (org.apache.tomcat.util.net.openssl.OpenSSLConf)4 ArrayList (java.util.ArrayList)2 OpenSSLConfCmd (org.apache.tomcat.util.net.openssl.OpenSSLConfCmd)2 ByteArrayInputStream (java.io.ByteArrayInputStream)1 ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 ObjectInputStream (java.io.ObjectInputStream)1 ObjectOutputStream (java.io.ObjectOutputStream)1 CertificateException (java.security.cert.CertificateException)1 X509Certificate (java.security.cert.X509Certificate)1 SSLException (javax.net.ssl.SSLException)1 MemoryAddress (jdk.incubator.foreign.MemoryAddress)1 MemorySegment (jdk.incubator.foreign.MemorySegment)1 AbstractEndpoint (org.apache.tomcat.util.net.AbstractEndpoint)1 SSLHostConfig (org.apache.tomcat.util.net.SSLHostConfig)1 SSLHostConfigCertificate (org.apache.tomcat.util.net.SSLHostConfigCertificate)1 Test (org.junit.Test)1