Skip to content

Commit

Permalink
Some more plumbing to support multiple certificates per virtual host
Browse files Browse the repository at this point in the history
git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@1686483 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
markt-asf committed Jun 19, 2015
1 parent 1f01e07 commit 5d09ca3
Show file tree
Hide file tree
Showing 11 changed files with 301 additions and 183 deletions.
22 changes: 12 additions & 10 deletions java/org/apache/tomcat/util/net/AbstractJsseEndpoint.java
Expand Up @@ -74,17 +74,19 @@ protected void initialiseSsl() throws Exception {
sslImplementation = SSLImplementation.getInstance(getSslImplementationName());

for (SSLHostConfig sslHostConfig : sslHostConfigs.values()) {
SSLUtil sslUtil = sslImplementation.getSSLUtil(sslHostConfig);

SSLContext sslContext = sslUtil.createSSLContext();
sslContext.init(sslUtil.getKeyManagers(), sslUtil.getTrustManagers(), null);

SSLSessionContext sessionContext = sslContext.getServerSessionContext();
if (sessionContext != null) {
sslUtil.configureSessionContext(sessionContext);
for (SSLHostConfigCertificate certificate : sslHostConfig.getCertificates(true)) {
SSLUtil sslUtil = sslImplementation.getSSLUtil(sslHostConfig, certificate);

SSLContext sslContext = sslUtil.createSSLContext();
sslContext.init(sslUtil.getKeyManagers(), sslUtil.getTrustManagers(), null);

SSLSessionContext sessionContext = sslContext.getServerSessionContext();
if (sessionContext != null) {
sslUtil.configureSessionContext(sessionContext);
}
SSLContextWrapper sslContextWrapper = new SSLContextWrapper(sslContext, sslUtil);
sslHostConfig.setSslContext(sslContextWrapper);
}
SSLContextWrapper sslContextWrapper = new SSLContextWrapper(sslContext, sslUtil);
sslHostConfig.setSslContext(sslContextWrapper);
}
}
}
Expand Down
310 changes: 156 additions & 154 deletions java/org/apache/tomcat/util/net/AprEndpoint.java

Large diffs are not rendered by default.

56 changes: 50 additions & 6 deletions java/org/apache/tomcat/util/net/SSLHostConfig.java
Expand Up @@ -63,8 +63,11 @@ public class SSLHostConfig {

// Configuration properties

// Nested
private SSLHostConfigCertificate defaultCertificate = null;
private Set<SSLHostConfigCertificate> certificates = new HashSet<>(4);

// Common
private String certificateKeyPassword = null;
private String certificateRevocationListFile;
private CertificateVerification certificateVerification = CertificateVerification.NONE;
private int certificateVerificationDepth = 10;
Expand Down Expand Up @@ -146,15 +149,56 @@ private void setProperty(String name, Type configType) {
}


// ----------------------------------------- Common configuration properties
// ------------------------------------------- Nested configuration elements

public void setCertificateKeyPassword(String certificateKeyPassword) {
this.certificateKeyPassword = certificateKeyPassword;
private void registerDefaultCertificate() {
if (defaultCertificate == null) {
defaultCertificate =
new SSLHostConfigCertificate(SSLHostConfigCertificate.Type.UNDEFINED);
certificates.add(defaultCertificate);
}
}


public void addCertificate(SSLHostConfigCertificate certificate) {
// Need to make sure that if there is more than one certificate, none of
// them have a type of undefined.
if (certificates.size() == 0) {
certificates.add(certificate);
return;
}

if (certificates.size() == 1 &&
certificates.iterator().next().getType() == SSLHostConfigCertificate.Type.UNDEFINED ||
certificate.getType() == SSLHostConfigCertificate.Type.UNDEFINED) {
// Invalid config
}

certificates.add(certificate);
}


public String getCertificateKeyPassword() {
return certificateKeyPassword;
public Set<SSLHostConfigCertificate> getCertificates() {
return getCertificates(false);
}


public Set<SSLHostConfigCertificate> getCertificates(boolean createDefaultIfEmpty) {
if (certificates.size() == 0 && createDefaultIfEmpty) {
registerDefaultCertificate();
}
return certificates;
}


// ----------------------------------------- Common configuration properties

// TODO: All of these SSL setters can be removed once it is no longer
// necessary to support the old configuration attributes (Tomcat 10?).

public void setCertificateKeyPassword(String certificateKeyPassword) {
registerDefaultCertificate();
defaultCertificate.setCertificateKeyPassword(certificateKeyPassword);
}


Expand Down
56 changes: 56 additions & 0 deletions java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java
@@ -0,0 +1,56 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.tomcat.util.net;


public class SSLHostConfigCertificate {

public static final Type DEFAULT_TYPE = Type.UNDEFINED;

// Common
private final Type type;
private String certificateKeyPassword = null;


public SSLHostConfigCertificate(Type type) {
this.type = type;
}


public Type getType() {
return type;
}


public String getCertificateKeyPassword() {
return certificateKeyPassword;
}


public void setCertificateKeyPassword(String certificateKeyPassword) {
this.certificateKeyPassword = certificateKeyPassword;
}


public static enum Type {
UNDEFINED,
RSA,
DSA,
EC,
DH
}
}
3 changes: 2 additions & 1 deletion java/org/apache/tomcat/util/net/SSLImplementation.java
Expand Up @@ -71,5 +71,6 @@ public static SSLImplementation getInstance(String className)

public abstract SSLSupport getSSLSupport(SSLSession session);

public abstract SSLUtil getSSLUtil(SSLHostConfig sslHostConfig);
public abstract SSLUtil getSSLUtil(SSLHostConfig sslHostConfig,
SSLHostConfigCertificate certificate);
}
5 changes: 3 additions & 2 deletions java/org/apache/tomcat/util/net/jsse/JSSEImplementation.java
Expand Up @@ -19,6 +19,7 @@
import javax.net.ssl.SSLSession;

import org.apache.tomcat.util.net.SSLHostConfig;
import org.apache.tomcat.util.net.SSLHostConfigCertificate;
import org.apache.tomcat.util.net.SSLImplementation;
import org.apache.tomcat.util.net.SSLSupport;
import org.apache.tomcat.util.net.SSLUtil;
Expand Down Expand Up @@ -50,7 +51,7 @@ public SSLSupport getSSLSupport(SSLSession session) {
}

@Override
public SSLUtil getSSLUtil(SSLHostConfig sslHostConfig) {
return new JSSESocketFactory(sslHostConfig);
public SSLUtil getSSLUtil(SSLHostConfig sslHostConfig, SSLHostConfigCertificate certificate) {
return new JSSESocketFactory(sslHostConfig, certificate);
}
}
7 changes: 5 additions & 2 deletions java/org/apache/tomcat/util/net/jsse/JSSESocketFactory.java
Expand Up @@ -56,6 +56,7 @@
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.net.SSLContext;
import org.apache.tomcat.util.net.SSLHostConfig;
import org.apache.tomcat.util.net.SSLHostConfigCertificate;
import org.apache.tomcat.util.net.SSLUtil;
import org.apache.tomcat.util.net.jsse.openssl.OpenSSLCipherConfigurationParser;
import org.apache.tomcat.util.res.StringManager;
Expand All @@ -78,12 +79,14 @@ public class JSSESocketFactory implements SSLUtil {
private static final StringManager sm = StringManager.getManager(JSSESocketFactory.class);

private final SSLHostConfig sslHostConfig;
private final SSLHostConfigCertificate certificate;

private final String[] defaultServerProtocols;


public JSSESocketFactory (SSLHostConfig sslHostConfig) {
public JSSESocketFactory (SSLHostConfig sslHostConfig, SSLHostConfigCertificate certificate) {
this.sslHostConfig = sslHostConfig;
this.certificate = certificate;

SSLContext context;
try {
Expand Down Expand Up @@ -266,7 +269,7 @@ public KeyManager[] getKeyManagers() throws Exception {
String keystorePass = sslHostConfig.getCertificateKeystorePassword();
String keyAlias = sslHostConfig.getCertificateKeyAlias();
String algorithm = sslHostConfig.getKeyManagerAlgorithm();
String keyPass = sslHostConfig.getCertificateKeyPassword();
String keyPass = certificate.getCertificateKeyPassword();
// This has to be here as it can't be moved to SSLHostConfig since the
// defaults vary between JSSE and OpenSSL.
if (keyPass == null) {
Expand Down
8 changes: 6 additions & 2 deletions java/org/apache/tomcat/util/net/openssl/OpenSSLContext.java
Expand Up @@ -55,6 +55,7 @@
import org.apache.tomcat.util.net.AbstractEndpoint;
import org.apache.tomcat.util.net.Constants;
import org.apache.tomcat.util.net.SSLHostConfig;
import org.apache.tomcat.util.net.SSLHostConfigCertificate;
import org.apache.tomcat.util.net.jsse.openssl.OpenSSLCipherConfigurationParser;
import org.apache.tomcat.util.res.StringManager;

Expand All @@ -69,6 +70,7 @@ public class OpenSSLContext implements org.apache.tomcat.util.net.SSLContext {
private static final String defaultProtocol = "TLS";

private final SSLHostConfig sslHostConfig;
private final SSLHostConfigCertificate certificate;
private OpenSSLServerSessionContext sessionContext;

private List<String> ciphers = new ArrayList<>();
Expand Down Expand Up @@ -105,8 +107,10 @@ public void setEnabledProtocol(String protocol) {
}
}

public OpenSSLContext(SSLHostConfig sslHostConfig) throws SSLException {
public OpenSSLContext(SSLHostConfig sslHostConfig, SSLHostConfigCertificate certificate)
throws SSLException {
this.sslHostConfig = sslHostConfig;
this.certificate = certificate;
aprPool = Pool.create(0);
boolean success = false;
try {
Expand Down Expand Up @@ -305,7 +309,7 @@ public synchronized void init(KeyManager[] kms, TrustManager[] tms, SecureRandom
SSLContext.setCertificate(ctx,
SSLHostConfig.adjustRelativePath(sslHostConfig.getCertificateFile()),
SSLHostConfig.adjustRelativePath(sslHostConfig.getCertificateKeyFile()),
sslHostConfig.getCertificateKeyPassword(), SSL.SSL_AIDX_RSA);
certificate.getCertificateKeyPassword(), SSL.SSL_AIDX_RSA);
// Support Client Certificates
SSLContext.setCACertificate(ctx,
SSLHostConfig.adjustRelativePath(sslHostConfig.getCaCertificateFile()),
Expand Down
Expand Up @@ -19,6 +19,7 @@
import javax.net.ssl.SSLSession;

import org.apache.tomcat.util.net.SSLHostConfig;
import org.apache.tomcat.util.net.SSLHostConfigCertificate;
import org.apache.tomcat.util.net.SSLImplementation;
import org.apache.tomcat.util.net.SSLSupport;
import org.apache.tomcat.util.net.SSLUtil;
Expand All @@ -39,8 +40,8 @@ public SSLSupport getSSLSupport(SSLSession session) {
}

@Override
public SSLUtil getSSLUtil(SSLHostConfig sslHostConfig) {
return new OpenSSLUtil(sslHostConfig);
public SSLUtil getSSLUtil(SSLHostConfig sslHostConfig, SSLHostConfigCertificate certificate) {
return new OpenSSLUtil(sslHostConfig, certificate);
}

}
7 changes: 5 additions & 2 deletions java/org/apache/tomcat/util/net/openssl/OpenSSLUtil.java
Expand Up @@ -24,22 +24,25 @@

import org.apache.tomcat.util.net.SSLContext;
import org.apache.tomcat.util.net.SSLHostConfig;
import org.apache.tomcat.util.net.SSLHostConfigCertificate;
import org.apache.tomcat.util.net.SSLUtil;

public class OpenSSLUtil implements SSLUtil {

private final SSLHostConfig sslHostConfig;
private final SSLHostConfigCertificate certificate;

private String[] enabledProtocols = null;
private String[] enabledCiphers = null;

public OpenSSLUtil(SSLHostConfig sslHostConfig) {
public OpenSSLUtil(SSLHostConfig sslHostConfig, SSLHostConfigCertificate certificate) {
this.sslHostConfig = sslHostConfig;
this.certificate = certificate;
}

@Override
public SSLContext createSSLContext() throws Exception {
return new OpenSSLContext(sslHostConfig);
return new OpenSSLContext(sslHostConfig, certificate);
}

@Override
Expand Down
Expand Up @@ -17,6 +17,7 @@
package org.apache.tomcat.util.net.jsse;

import org.apache.tomcat.util.net.SSLHostConfig;
import org.apache.tomcat.util.net.SSLHostConfigCertificate;
import org.apache.tomcat.util.net.SSLUtil;

public class TesterBug50640SslImpl extends JSSEImplementation {
Expand All @@ -26,11 +27,11 @@ public class TesterBug50640SslImpl extends JSSEImplementation {


@Override
public SSLUtil getSSLUtil(SSLHostConfig sslHostConfig) {
public SSLUtil getSSLUtil(SSLHostConfig sslHostConfig, SSLHostConfigCertificate certificate) {
if (sslHostConfig.getProtocols().size() == 1 &&
sslHostConfig.getProtocols().contains(PROPERTY_VALUE)) {
sslHostConfig.setProtocols("TLSv1,TLSv1.1,TLSv1.2");
return super.getSSLUtil(sslHostConfig);
return super.getSSLUtil(sslHostConfig, certificate);
} else {
return null;
}
Expand Down

0 comments on commit 5d09ca3

Please sign in to comment.