Skip to content

Commit

Permalink
Allow user provided SSLContext instances on SSLHostConfigCertificate
Browse files Browse the repository at this point in the history
Based on pull request #673 provided by Hakan Altındağ
#673
  • Loading branch information
markt-asf committed Feb 7, 2024
1 parent d5fd9d4 commit b0df981
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 14 deletions.
4 changes: 3 additions & 1 deletion java/org/apache/tomcat/util/net/AbstractEndpoint.java
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,8 @@ protected void destroySsl() throws Exception {
protected void releaseSSLContext(SSLHostConfig sslHostConfig) {
for (SSLHostConfigCertificate certificate : sslHostConfig.getCertificates(true)) {
if (certificate.getSslContext() != null) {
SSLContext sslContext = certificate.getSslContext();
// Only release the SSLContext if we generated it.
SSLContext sslContext = certificate.getSslContextGenerated();
if (sslContext != null) {
sslContext.destroy();
}
Expand Down Expand Up @@ -1317,6 +1318,7 @@ protected abstract SocketProcessorBase<S> createSocketProcessor(

public abstract void bind() throws Exception;
public abstract void unbind() throws Exception;

public abstract void startInternal() throws Exception;
public abstract void stopInternal() throws Exception;

Expand Down
22 changes: 15 additions & 7 deletions java/org/apache/tomcat/util/net/AbstractJsseEndpoint.java
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,18 @@ protected void createSSLContext(SSLHostConfig sslHostConfig) throws IllegalArgum
sslHostConfig.setEnabledCiphers(sslUtil.getEnabledCiphers());
}

SSLContext sslContext;
try {
sslContext = sslUtil.createSSLContext(negotiableProtocols);
} catch (Exception e) {
throw new IllegalArgumentException(e.getMessage(), e);
SSLContext sslContext = certificate.getSslContext();
// Generate the SSLContext from configuration unless (e.g. embedded) an SSLContext has been provided.
if (sslContext == null) {
try {
sslContext = sslUtil.createSSLContext(negotiableProtocols);
} catch (Exception e) {
throw new IllegalArgumentException(e.getMessage(), e);
}

certificate.setSslContextGenerated(sslContext);
}

certificate.setSslContext(sslContext);
logCertificate(certificate);
}
}
Expand Down Expand Up @@ -251,7 +255,11 @@ private void testServerCipherSuitesOrderSupport() {
public void unbind() throws Exception {
for (SSLHostConfig sslHostConfig : sslHostConfigs.values()) {
for (SSLHostConfigCertificate certificate : sslHostConfig.getCertificates(true)) {
certificate.setSslContext(null);
/*
* Only remove any generated SSLContext. If the SSLContext was provided it is left in place in case the
* endpoint is re-started.
*/
certificate.setSslContextGenerated(null);
}
}
}
Expand Down
29 changes: 23 additions & 6 deletions java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,14 @@ public class SSLHostConfigCertificate implements Serializable {
// Internal
private ObjectName oname;

// OpenSSL can handle multiple certs in a single config so the reference to
// the context is at the virtual host level. JSSE can't so the reference is
// held here on the certificate.
private transient volatile SSLContext sslContext;
/*
* OpenSSL can handle multiple certs in a single config so the reference to the context is at the virtual host
* level. JSSE can't so the reference is held here on the certificate. Typically, the SSLContext is generated from
* the configuration but, particularly in embedded scenarios, it can be provided directly.
*/
private transient volatile SSLContext sslContextProvided;
private transient volatile SSLContext sslContextGenerated;


// Common
private final SSLHostConfig sslHostConfig;
Expand Down Expand Up @@ -90,12 +94,25 @@ public SSLHostConfigCertificate(SSLHostConfig sslHostConfig, Type type) {


public SSLContext getSslContext() {
return sslContext;
if (sslContextProvided != null) {
return sslContextProvided;
}
return sslContextGenerated;
}


public void setSslContext(SSLContext sslContext) {
this.sslContext = sslContext;
this.sslContextProvided = sslContext;
}


public SSLContext getSslContextGenerated() {
return sslContextGenerated;
}


void setSslContextGenerated(SSLContext sslContext) {
this.sslContextGenerated = sslContext;
}


Expand Down
5 changes: 5 additions & 0 deletions webapps/docs/changelog.xml
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,11 @@
operations from debug level to trace. In particular, most of the
HTTP/2 debug logging has been changed to trace level. (remm)
</fix>
<fix>
Add support for user provided <code>SSLContext</code> instances
configured on <code>SSLHostConfigCertificate</code> instances. Based on
pull request <pr>673</pr> provided by Hakan Altındağ. (markt)
</fix>
</changelog>
</subsection>
<subsection name="Jasper">
Expand Down

0 comments on commit b0df981

Please sign in to comment.