Ensure BIO is only used one time
Motivation: Its not safe to reuse a BIO, we need to ensure we only use it once. Modifications: Only use the BIO once. Result: Correctly usage of BIO
This commit is contained in:
parent
4d74bf3984
commit
c1d5066929
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package io.netty.handler.ssl;
|
||||
|
||||
import io.netty.buffer.ByteBufAllocator;
|
||||
import org.apache.tomcat.jni.SSL;
|
||||
|
||||
import javax.net.ssl.SSLException;
|
||||
@ -27,6 +28,10 @@ import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static io.netty.handler.ssl.ReferenceCountedOpenSslContext.freeBio;
|
||||
import static io.netty.handler.ssl.ReferenceCountedOpenSslContext.newBIO;
|
||||
import static io.netty.handler.ssl.ReferenceCountedOpenSslContext.toBIO;
|
||||
|
||||
/**
|
||||
* Manages key material for {@link OpenSslEngine}s and so set the right {@link PrivateKey}s and
|
||||
* {@link X509Certificate}s.
|
||||
@ -88,32 +93,39 @@ class OpenSslKeyMaterialManager {
|
||||
private void setKeyMaterial(long ssl, String alias) throws SSLException {
|
||||
long keyBio = 0;
|
||||
long keyCertChainBio = 0;
|
||||
long keyCertChainBio2 = 0;
|
||||
|
||||
try {
|
||||
// TODO: Should we cache these and so not need to do a memory copy all the time ?
|
||||
PrivateKey key = keyManager.getPrivateKey(alias);
|
||||
X509Certificate[] certificates = keyManager.getCertificateChain(alias);
|
||||
|
||||
if (certificates != null && certificates.length != 0) {
|
||||
keyCertChainBio = OpenSslContext.toBIO(certificates);
|
||||
if (key != null) {
|
||||
keyBio = OpenSslContext.toBIO(key);
|
||||
}
|
||||
SSL.setCertificateBio(ssl, keyCertChainBio, keyBio, password);
|
||||
// Only encode one time
|
||||
PemEncoded encoded = PemX509Certificate.toPEM(ByteBufAllocator.DEFAULT, true, certificates);
|
||||
try {
|
||||
keyCertChainBio = newBIO(encoded.content().retainedSlice());
|
||||
keyCertChainBio2 = newBIO(encoded.content().retainedSlice());
|
||||
|
||||
// We may have more then one cert in the chain so add all of them now.
|
||||
SSL.setCertificateChainBio(ssl, keyCertChainBio, false);
|
||||
if (key != null) {
|
||||
keyBio = toBIO(key);
|
||||
}
|
||||
SSL.setCertificateBio(ssl, keyCertChainBio, keyBio, password);
|
||||
|
||||
// We may have more then one cert in the chain so add all of them now.
|
||||
SSL.setCertificateChainBio(ssl, keyCertChainBio2, false);
|
||||
} finally {
|
||||
encoded.release();
|
||||
}
|
||||
}
|
||||
} catch (SSLException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new SSLException(e);
|
||||
} finally {
|
||||
if (keyBio != 0) {
|
||||
SSL.freeBIO(keyBio);
|
||||
}
|
||||
if (keyCertChainBio != 0) {
|
||||
SSL.freeBIO(keyCertChainBio);
|
||||
}
|
||||
freeBio(keyBio);
|
||||
freeBio(keyCertChainBio);
|
||||
freeBio(keyCertChainBio2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -637,29 +637,43 @@ public abstract class ReferenceCountedOpenSslContext extends SslContext implemen
|
||||
/* Load the certificate file and private key. */
|
||||
long keyBio = 0;
|
||||
long keyCertChainBio = 0;
|
||||
|
||||
long keyCertChainBio2 = 0;
|
||||
PemEncoded encoded = null;
|
||||
try {
|
||||
keyCertChainBio = toBIO(keyCertChain);
|
||||
keyBio = toBIO(key);
|
||||
// Only encode one time
|
||||
encoded = PemX509Certificate.toPEM(ByteBufAllocator.DEFAULT, true, keyCertChain);
|
||||
keyCertChainBio = newBIO(encoded.content().retainedSlice());
|
||||
keyCertChainBio2 = newBIO(encoded.content().retainedSlice());
|
||||
|
||||
if (key != null) {
|
||||
keyBio = toBIO(key);
|
||||
}
|
||||
|
||||
SSLContext.setCertificateBio(
|
||||
ctx, keyCertChainBio, keyBio,
|
||||
keyPassword == null ? StringUtil.EMPTY_STRING : keyPassword);
|
||||
// We may have more then one cert in the chain so add all of them now.
|
||||
SSLContext.setCertificateChainBio(ctx, keyCertChainBio, false);
|
||||
SSLContext.setCertificateChainBio(ctx, keyCertChainBio2, false);
|
||||
} catch (SSLException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new SSLException("failed to set certificate and key", e);
|
||||
} finally {
|
||||
if (keyBio != 0) {
|
||||
SSL.freeBIO(keyBio);
|
||||
}
|
||||
if (keyCertChainBio != 0) {
|
||||
SSL.freeBIO(keyCertChainBio);
|
||||
freeBio(keyBio);
|
||||
freeBio(keyCertChainBio);
|
||||
freeBio(keyCertChainBio2);
|
||||
if (encoded != null) {
|
||||
encoded.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void freeBio(long bio) {
|
||||
if (bio != 0) {
|
||||
SSL.freeBIO(bio);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the pointer to a <a href="https://www.openssl.org/docs/crypto/BIO_get_mem_ptr.html">in-memory BIO</a>
|
||||
* or {@code 0} if the {@code key} is {@code null}. The BIO contains the content of the {@code key}.
|
||||
@ -730,7 +744,7 @@ public abstract class ReferenceCountedOpenSslContext extends SslContext implemen
|
||||
}
|
||||
}
|
||||
|
||||
private static long newBIO(ByteBuf buffer) throws Exception {
|
||||
static long newBIO(ByteBuf buffer) throws Exception {
|
||||
try {
|
||||
long bio = SSL.newMemBIO();
|
||||
int readable = buffer.readableBytes();
|
||||
|
Loading…
Reference in New Issue
Block a user