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:
Norman Maurer 2016-08-11 09:08:16 +02:00
parent 4d74bf3984
commit c1d5066929
2 changed files with 49 additions and 23 deletions

View File

@ -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);
}
}

View File

@ -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();