in netty-handler-ssl, drop conscrypt because of https://github.com/google/conscrypt/issues/838, move bouncycastle to separate subproject
This commit is contained in:
parent
3d532a821f
commit
07c6dd718a
90 changed files with 1138 additions and 1916 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -12,5 +12,3 @@
|
|||
.DS_Store
|
||||
*.iml
|
||||
*~
|
||||
*.key
|
||||
*.crt
|
||||
|
|
|
@ -11,6 +11,8 @@ module org.xbib.io.netty.channel {
|
|||
exports io.netty.channel.oio;
|
||||
exports io.netty.channel.pool;
|
||||
exports io.netty.channel.socket;
|
||||
exports io.netty.channel.socket.nio;
|
||||
exports io.netty.channel.socket.oio;
|
||||
uses ChannelInitializerExtension;
|
||||
requires org.xbib.io.netty.buffer;
|
||||
requires org.xbib.io.netty.resolver;
|
||||
|
|
|
@ -3,6 +3,7 @@ dependencies {
|
|||
testImplementation testLibs.gson
|
||||
testImplementation testLibs.assertj
|
||||
testImplementation testLibs.mockito.core
|
||||
testImplementation project(':netty-handler-ssl-bouncycastle')
|
||||
testRuntimeOnly project(path: ':netty-tcnative-boringssl-static', configuration: osdetector.classifier)
|
||||
testRuntimeOnly libs.brotli4j.native."${osdetector.os}"."${osdetector.arch.replace('_','')}"
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ import io.netty.handler.ssl.SslHandshakeCompletionEvent;
|
|||
import io.netty.handler.ssl.SslProvider;
|
||||
import io.netty.handler.ssl.SupportedCipherSuiteFilter;
|
||||
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
|
||||
import io.netty.handler.ssl.util.SelfSignedCertificate;
|
||||
import io.netty.handler.ssl.bouncycastle.SelfSignedCertificate;
|
||||
import io.netty.util.CharsetUtil;
|
||||
import io.netty.util.NetUtil;
|
||||
import io.netty.util.ReferenceCountUtil;
|
||||
|
|
|
@ -3,4 +3,5 @@ dependencies {
|
|||
api project(':netty-handler-codec-quic')
|
||||
testImplementation testLibs.assertj
|
||||
testImplementation testLibs.mockito.core
|
||||
testImplementation project(':netty-handler-ssl-bouncycastle')
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ import io.netty.handler.codec.http.HttpUtil;
|
|||
import io.netty.handler.codec.http.HttpVersion;
|
||||
import io.netty.handler.codec.http.LastHttpContent;
|
||||
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
|
||||
import io.netty.handler.ssl.util.SelfSignedCertificate;
|
||||
import io.netty.handler.ssl.bouncycastle.SelfSignedCertificate;
|
||||
import io.netty.handler.codec.quic.InsecureQuicTokenHandler;
|
||||
import io.netty.handler.codec.quic.QuicChannel;
|
||||
import io.netty.handler.codec.quic.QuicSslContextBuilder;
|
||||
|
|
|
@ -23,7 +23,7 @@ import io.netty.channel.ChannelHandlerContext;
|
|||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.nio.NioDatagramChannel;
|
||||
import io.netty.handler.ssl.util.SelfSignedCertificate;
|
||||
import io.netty.handler.ssl.bouncycastle.SelfSignedCertificate;
|
||||
import io.netty.handler.codec.quic.InsecureQuicTokenHandler;
|
||||
import io.netty.handler.codec.quic.QuicChannel;
|
||||
import io.netty.handler.codec.quic.QuicSslContext;
|
||||
|
|
|
@ -23,7 +23,7 @@ import io.netty.channel.ChannelHandlerContext;
|
|||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.nio.NioDatagramChannel;
|
||||
import io.netty.handler.ssl.util.SelfSignedCertificate;
|
||||
import io.netty.handler.ssl.bouncycastle.SelfSignedCertificate;
|
||||
import io.netty.handler.codec.http3.DefaultHttp3DataFrame;
|
||||
import io.netty.handler.codec.http3.DefaultHttp3HeadersFrame;
|
||||
import io.netty.handler.codec.http3.Http3;
|
||||
|
|
18
netty-handler-codec-http3/src/test/resources/cert.crt
Normal file
18
netty-handler-codec-http3/src/test/resources/cert.crt
Normal file
|
@ -0,0 +1,18 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIC7TCCAdUCFDuGBhl3l5Z++VCLkvaav4yteBonMA0GCSqGSIb3DQEBCwUAMEUx
|
||||
CzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRl
|
||||
cm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMjAwMzIzMTYwNzU0WhcNNDcwODA5MTYw
|
||||
NzU0WjAhMQswCQYDVQQGEwJHQjESMBAGA1UEAwwJcXVpYy50ZWNoMIIBIjANBgkq
|
||||
hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz5bOL7LD9kiIagcVrZqZ13ZcR0KhMuzs
|
||||
brqULbZKyqC+uBRgINxYJ7LPnJ4LPYuCt/nAaQ7CLXfKgzAMFu8eIK6UEvZA6+7b
|
||||
20E4rvOpPbTB/T4JbYZNQKyM9AEwr6j0P6vFgrWT7aBzhkmiqEe5vv/7ZOEGb+Ab
|
||||
+cvMeszfBbk93nyzKdNaUuh95x7/p0Ow315np2PRuoT0QQnA9zE/9eZ3Jah3cNZn
|
||||
NuQ6BDHlkegzTV5JhYYblRo/pmt2E9E0ha+NWsRLf3ZJUYhkYR3UqMltEKuLglCO
|
||||
VWBbPmKd4IZUNIotpKMVQSVb9agNBF49hH9iBhN3fBm7Hp8KBpjJLwIDAQABMA0G
|
||||
CSqGSIb3DQEBCwUAA4IBAQCo/Rn4spa5XFk0cCoKypP27DxePkGD9rQZk/CY4inV
|
||||
JV16anZ1pr9yfO61+m3fRKTZq7yxtHRDWxDdROHx9LqV1dXLAmh1ecV9Kn6/796O
|
||||
EHsOcVB0Lfi9Ili7//oUqlhGNploRuQbgWAXU+Eo1xJRWIXeedhzBSgEOMaQk3Zn
|
||||
TdYFhP0/Ao/fEdI4VULv1A43ztnZIB2KXWgUQoFT32woL47eWge8LxxVmmH3STtz
|
||||
nNcGnYxIorCQemDHDzMrvxRWgHxkpFGGqAhkFFyCmhKFPglKwt+yVTx26T8tShID
|
||||
ISMj0rgVMptmtWKJfzNCvFG52gsuO4w3yGdjgjRRrBDm
|
||||
-----END CERTIFICATE-----
|
28
netty-handler-codec-http3/src/test/resources/cert.key
Normal file
28
netty-handler-codec-http3/src/test/resources/cert.key
Normal file
|
@ -0,0 +1,28 @@
|
|||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDPls4vssP2SIhq
|
||||
BxWtmpnXdlxHQqEy7OxuupQttkrKoL64FGAg3Fgnss+cngs9i4K3+cBpDsItd8qD
|
||||
MAwW7x4grpQS9kDr7tvbQTiu86k9tMH9Pglthk1ArIz0ATCvqPQ/q8WCtZPtoHOG
|
||||
SaKoR7m+//tk4QZv4Bv5y8x6zN8FuT3efLMp01pS6H3nHv+nQ7DfXmenY9G6hPRB
|
||||
CcD3MT/15nclqHdw1mc25DoEMeWR6DNNXkmFhhuVGj+ma3YT0TSFr41axEt/dklR
|
||||
iGRhHdSoyW0Qq4uCUI5VYFs+Yp3ghlQ0ii2koxVBJVv1qA0EXj2Ef2IGE3d8Gbse
|
||||
nwoGmMkvAgMBAAECggEBAMtFkpUmablKgTnBwjqCvs47OlUVK6AgW8x5qwuwC0Cr
|
||||
ctXyLcc/vJry/1UPdVZIvDHGv+Cf8Qhw2r7nV49FiqzaBmki9aOR+3uRPB4kvr6L
|
||||
t8Fw8+5pqlAAJu3wFGqN+M44N2mswDPaAAWpKTu7MGmVY+f+aT03qG1MYOiGoISK
|
||||
gP6DHiinddD38spM2muyCUyFZk9a+aBEfaQzZoU3gc0yB6R/qBOWZ7NIoIUMicku
|
||||
Zf3L6/06uunyZp+ueR83j1YWbg3JoYKlGAuQtDRF709+MQrim8lKTnfuHiBeZKYZ
|
||||
GNLSo7lGjrp6ccSyfXmlA36hSfdlrWtZJ4+utZShftECgYEA+NNOFNa1BLfDw3ot
|
||||
a6L4W6FE45B32bLbnBdg8foyEYrwzHLPFCbws1Z60pNr7NaCHDIMiKVOXvKQa78d
|
||||
qdWuPUVJ83uVs9GI8tAo00RAvBn6ut9yaaLa8mIv6ZpfU20IgE5sDjB7IBY9tTVd
|
||||
EDyJcDuKQXzQ48qmEw86wINQMd0CgYEA1ZMdt7yLnpDiYa6M/BuKjp7PWKcRlzVM
|
||||
BcCEYHA4LJ6xEOH4y9DEx2y5ljwOcXgJhXAfAyGQr7s1xiP/nXurqfmdP8u7bawp
|
||||
VwuWJ8Vv0ZXITaU0isezG2Dpnseuion3qSraWlmWUlWLVVgKETZmk7cF7VIXa0NT
|
||||
LFREdObI5HsCgYBUbm8KRyi5Zxm4VNbgtTYM8ZYMmdLxPe2i85PjyAABT+IRncuC
|
||||
jQwT7n5Swc9XWBpiMuFp5J3JPgmfZgRMwsMS61YClqbfk3Qi4FtaBMjqiu43Rubt
|
||||
zWL56DNV0xoRlufRkcq8rdq5spJR0L+5aLFCMhHh0taW1QaxZPOMq4IkyQKBgQC3
|
||||
GetubGzewqPyzuz77ri5URm+jW0dT4ofnE9hRpRCXMK9EJ52TkOGHYZ2cIKJcTno
|
||||
dpl/27Tpk/ykJJSu9SnVDbVszkOf4OuIPty6uCAHdPxG5Q3ItTCulkVz5QmUqHf1
|
||||
RlHxB8FCUSilQFdRLmx+03h3X9vID+4soQoXlwxAJQKBgE5SQpN+TG5V+E4zHgNd
|
||||
6cy6gA5dGDJ0KbsgxJwlKTFA9nIcs2ssBxLY9U4x75EGuqpeVNmq6xwwmPtBs0rp
|
||||
M3W4zdFrZQ3BneFRW7WbSBbsUSprkJW/p4GXa17GzGUq/MDXlGhNlApP1nknzFvE
|
||||
xGaH0/H/TZxpLCogVP9npUkj
|
||||
-----END PRIVATE KEY-----
|
|
@ -1,4 +0,0 @@
|
|||
dependencies {
|
||||
api project(':netty-handler-codec')
|
||||
implementation libs.protobuf
|
||||
}
|
|
@ -1,133 +0,0 @@
|
|||
/*
|
||||
* Copyright 2015 The Netty Project
|
||||
*
|
||||
* The Netty Project 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:
|
||||
*
|
||||
* https://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 io.netty.handler.codec.protobuf;
|
||||
|
||||
import com.google.protobuf.ExtensionRegistry;
|
||||
import com.google.protobuf.ExtensionRegistryLite;
|
||||
import com.google.protobuf.Message;
|
||||
import com.google.protobuf.MessageLite;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufUtil;
|
||||
import io.netty.channel.ChannelHandler.Sharable;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
|
||||
import io.netty.handler.codec.LengthFieldPrepender;
|
||||
import io.netty.handler.codec.MessageToMessageDecoder;
|
||||
import io.netty.util.internal.ObjectUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Decodes a received {@link ByteBuf} into a
|
||||
* <a href="https://github.com/google/protobuf">Google Protocol Buffers</a>
|
||||
* {@link Message} and {@link MessageLite}. Please note that this decoder must
|
||||
* be used with a proper {@link ByteToMessageDecoder} such as {@link ProtobufVarint32FrameDecoder}
|
||||
* or {@link LengthFieldBasedFrameDecoder} if you are using a stream-based
|
||||
* transport such as TCP/IP. A typical setup for TCP/IP would be:
|
||||
* <pre>
|
||||
* {@link ChannelPipeline} pipeline = ...;
|
||||
*
|
||||
* // Decoders
|
||||
* pipeline.addLast("frameDecoder",
|
||||
* new {@link LengthFieldBasedFrameDecoder}(1048576, 0, 4, 0, 4));
|
||||
* pipeline.addLast("protobufDecoder",
|
||||
* new {@link ProtobufDecoder}(MyMessage.getDefaultInstance()));
|
||||
*
|
||||
* // Encoder
|
||||
* pipeline.addLast("frameEncoder", new {@link LengthFieldPrepender}(4));
|
||||
* pipeline.addLast("protobufEncoder", new {@link ProtobufEncoder}());
|
||||
* </pre>
|
||||
* and then you can use a {@code MyMessage} instead of a {@link ByteBuf}
|
||||
* as a message:
|
||||
* <pre>
|
||||
* void channelRead({@link ChannelHandlerContext} ctx, Object msg) {
|
||||
* MyMessage req = (MyMessage) msg;
|
||||
* MyMessage res = MyMessage.newBuilder().setText(
|
||||
* "Did you say '" + req.getText() + "'?").build();
|
||||
* ch.write(res);
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
@Sharable
|
||||
public class ProtobufDecoder extends MessageToMessageDecoder<ByteBuf> {
|
||||
|
||||
private static final boolean HAS_PARSER;
|
||||
|
||||
static {
|
||||
boolean hasParser = false;
|
||||
try {
|
||||
// MessageLite.getParserForType() is not available until protobuf 2.5.0.
|
||||
MessageLite.class.getDeclaredMethod("getParserForType");
|
||||
hasParser = true;
|
||||
} catch (Throwable t) {
|
||||
// Ignore
|
||||
}
|
||||
|
||||
HAS_PARSER = hasParser;
|
||||
}
|
||||
|
||||
private final MessageLite prototype;
|
||||
private final ExtensionRegistryLite extensionRegistry;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*/
|
||||
public ProtobufDecoder(MessageLite prototype) {
|
||||
this(prototype, null);
|
||||
}
|
||||
|
||||
public ProtobufDecoder(MessageLite prototype, ExtensionRegistry extensionRegistry) {
|
||||
this(prototype, (ExtensionRegistryLite) extensionRegistry);
|
||||
}
|
||||
|
||||
public ProtobufDecoder(MessageLite prototype, ExtensionRegistryLite extensionRegistry) {
|
||||
this.prototype = ObjectUtil.checkNotNull(prototype, "prototype").getDefaultInstanceForType();
|
||||
this.extensionRegistry = extensionRegistry;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out)
|
||||
throws Exception {
|
||||
final byte[] array;
|
||||
final int offset;
|
||||
final int length = msg.readableBytes();
|
||||
if (msg.hasArray()) {
|
||||
array = msg.array();
|
||||
offset = msg.arrayOffset() + msg.readerIndex();
|
||||
} else {
|
||||
array = ByteBufUtil.getBytes(msg, msg.readerIndex(), length, false);
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
if (extensionRegistry == null) {
|
||||
if (HAS_PARSER) {
|
||||
out.add(prototype.getParserForType().parseFrom(array, offset, length));
|
||||
} else {
|
||||
out.add(prototype.newBuilderForType().mergeFrom(array, offset, length).build());
|
||||
}
|
||||
} else {
|
||||
if (HAS_PARSER) {
|
||||
out.add(prototype.getParserForType().parseFrom(
|
||||
array, offset, length, extensionRegistry));
|
||||
} else {
|
||||
out.add(prototype.newBuilderForType().mergeFrom(
|
||||
array, offset, length, extensionRegistry).build());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
/*
|
||||
* Copyright 2015 The Netty Project
|
||||
*
|
||||
* The Netty Project 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:
|
||||
*
|
||||
* https://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 io.netty.handler.codec.protobuf;
|
||||
|
||||
import com.google.protobuf.Message;
|
||||
import com.google.protobuf.MessageLite;
|
||||
import com.google.protobuf.MessageLiteOrBuilder;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandler.Sharable;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
|
||||
import io.netty.handler.codec.LengthFieldPrepender;
|
||||
import io.netty.handler.codec.MessageToMessageEncoder;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static io.netty.buffer.Unpooled.*;
|
||||
|
||||
/**
|
||||
* Encodes the requested <a href="https://github.com/google/protobuf">Google
|
||||
* Protocol Buffers</a> {@link Message} and {@link MessageLite} into a
|
||||
* {@link ByteBuf}. A typical setup for TCP/IP would be:
|
||||
* <pre>
|
||||
* {@link ChannelPipeline} pipeline = ...;
|
||||
*
|
||||
* // Decoders
|
||||
* pipeline.addLast("frameDecoder",
|
||||
* new {@link LengthFieldBasedFrameDecoder}(1048576, 0, 4, 0, 4));
|
||||
* pipeline.addLast("protobufDecoder",
|
||||
* new {@link ProtobufDecoder}(MyMessage.getDefaultInstance()));
|
||||
*
|
||||
* // Encoder
|
||||
* pipeline.addLast("frameEncoder", new {@link LengthFieldPrepender}(4));
|
||||
* pipeline.addLast("protobufEncoder", new {@link ProtobufEncoder}());
|
||||
* </pre>
|
||||
* and then you can use a {@code MyMessage} instead of a {@link ByteBuf}
|
||||
* as a message:
|
||||
* <pre>
|
||||
* void channelRead({@link ChannelHandlerContext} ctx, Object msg) {
|
||||
* MyMessage req = (MyMessage) msg;
|
||||
* MyMessage res = MyMessage.newBuilder().setText(
|
||||
* "Did you say '" + req.getText() + "'?").build();
|
||||
* ch.write(res);
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
@Sharable
|
||||
public class ProtobufEncoder extends MessageToMessageEncoder<MessageLiteOrBuilder> {
|
||||
@Override
|
||||
protected void encode(ChannelHandlerContext ctx, MessageLiteOrBuilder msg, List<Object> out)
|
||||
throws Exception {
|
||||
if (msg instanceof MessageLite) {
|
||||
out.add(wrappedBuffer(((MessageLite) msg).toByteArray()));
|
||||
return;
|
||||
}
|
||||
if (msg instanceof MessageLite.Builder) {
|
||||
out.add(wrappedBuffer(((MessageLite.Builder) msg).build().toByteArray()));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,119 +0,0 @@
|
|||
/*
|
||||
* Copyright 2015 The Netty Project
|
||||
*
|
||||
* The Netty Project 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:
|
||||
*
|
||||
* https://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 io.netty.handler.codec.protobuf;
|
||||
|
||||
import com.google.protobuf.CodedInputStream;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import io.netty.handler.codec.CorruptedFrameException;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A decoder that splits the received {@link ByteBuf}s dynamically by the
|
||||
* value of the Google Protocol Buffers
|
||||
* <a href="https://developers.google.com/protocol-buffers/docs/encoding#varints">Base
|
||||
* 128 Varints</a> integer length field in the message. For example:
|
||||
* <pre>
|
||||
* BEFORE DECODE (302 bytes) AFTER DECODE (300 bytes)
|
||||
* +--------+---------------+ +---------------+
|
||||
* | Length | Protobuf Data |----->| Protobuf Data |
|
||||
* | 0xAC02 | (300 bytes) | | (300 bytes) |
|
||||
* +--------+---------------+ +---------------+
|
||||
* </pre>
|
||||
*
|
||||
* @see CodedInputStream
|
||||
*/
|
||||
public class ProtobufVarint32FrameDecoder extends ByteToMessageDecoder {
|
||||
|
||||
// TODO maxFrameLength + safe skip + fail-fast option
|
||||
// (just like LengthFieldBasedFrameDecoder)
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out)
|
||||
throws Exception {
|
||||
in.markReaderIndex();
|
||||
int preIndex = in.readerIndex();
|
||||
int length = readRawVarint32(in);
|
||||
if (preIndex == in.readerIndex()) {
|
||||
return;
|
||||
}
|
||||
if (length < 0) {
|
||||
throw new CorruptedFrameException("negative length: " + length);
|
||||
}
|
||||
|
||||
if (in.readableBytes() < length) {
|
||||
in.resetReaderIndex();
|
||||
} else {
|
||||
out.add(in.readRetainedSlice(length));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads variable length 32bit int from buffer
|
||||
*
|
||||
* @return decoded int if buffers readerIndex has been forwarded else nonsense value
|
||||
*/
|
||||
private static int readRawVarint32(ByteBuf buffer) {
|
||||
if (!buffer.isReadable()) {
|
||||
return 0;
|
||||
}
|
||||
buffer.markReaderIndex();
|
||||
byte tmp = buffer.readByte();
|
||||
if (tmp >= 0) {
|
||||
return tmp;
|
||||
} else {
|
||||
int result = tmp & 127;
|
||||
if (!buffer.isReadable()) {
|
||||
buffer.resetReaderIndex();
|
||||
return 0;
|
||||
}
|
||||
if ((tmp = buffer.readByte()) >= 0) {
|
||||
result |= tmp << 7;
|
||||
} else {
|
||||
result |= (tmp & 127) << 7;
|
||||
if (!buffer.isReadable()) {
|
||||
buffer.resetReaderIndex();
|
||||
return 0;
|
||||
}
|
||||
if ((tmp = buffer.readByte()) >= 0) {
|
||||
result |= tmp << 14;
|
||||
} else {
|
||||
result |= (tmp & 127) << 14;
|
||||
if (!buffer.isReadable()) {
|
||||
buffer.resetReaderIndex();
|
||||
return 0;
|
||||
}
|
||||
if ((tmp = buffer.readByte()) >= 0) {
|
||||
result |= tmp << 21;
|
||||
} else {
|
||||
result |= (tmp & 127) << 21;
|
||||
if (!buffer.isReadable()) {
|
||||
buffer.resetReaderIndex();
|
||||
return 0;
|
||||
}
|
||||
result |= (tmp = buffer.readByte()) << 28;
|
||||
if (tmp < 0) {
|
||||
throw new CorruptedFrameException("malformed varint.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
/*
|
||||
* Copyright 2015 The Netty Project
|
||||
*
|
||||
* The Netty Project 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:
|
||||
*
|
||||
* https://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 io.netty.handler.codec.protobuf;
|
||||
|
||||
import com.google.protobuf.CodedOutputStream;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandler.Sharable;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
|
||||
/**
|
||||
* An encoder that prepends the Google Protocol Buffers
|
||||
* <a href="https://developers.google.com/protocol-buffers/docs/encoding?csw=1#varints">Base
|
||||
* 128 Varints</a> integer length field. For example:
|
||||
* <pre>
|
||||
* BEFORE ENCODE (300 bytes) AFTER ENCODE (302 bytes)
|
||||
* +---------------+ +--------+---------------+
|
||||
* | Protobuf Data |-------------->| Length | Protobuf Data |
|
||||
* | (300 bytes) | | 0xAC02 | (300 bytes) |
|
||||
* +---------------+ +--------+---------------+
|
||||
* </pre> *
|
||||
*
|
||||
* @see CodedOutputStream
|
||||
*/
|
||||
@Sharable
|
||||
public class ProtobufVarint32LengthFieldPrepender extends MessageToByteEncoder<ByteBuf> {
|
||||
|
||||
@Override
|
||||
protected void encode(
|
||||
ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out) throws Exception {
|
||||
int bodyLen = msg.readableBytes();
|
||||
int headerLen = computeRawVarint32Size(bodyLen);
|
||||
out.ensureWritable(headerLen + bodyLen);
|
||||
writeRawVarint32(out, bodyLen);
|
||||
out.writeBytes(msg, msg.readerIndex(), bodyLen);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes protobuf varint32 to (@link ByteBuf).
|
||||
* @param out to be written to
|
||||
* @param value to be written
|
||||
*/
|
||||
static void writeRawVarint32(ByteBuf out, int value) {
|
||||
while (true) {
|
||||
if ((value & ~0x7F) == 0) {
|
||||
out.writeByte(value);
|
||||
return;
|
||||
} else {
|
||||
out.writeByte((value & 0x7F) | 0x80);
|
||||
value >>>= 7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes size of protobuf varint32 after encoding.
|
||||
* @param value which is to be encoded.
|
||||
* @return size of value encoded as protobuf varint32.
|
||||
*/
|
||||
static int computeRawVarint32Size(final int value) {
|
||||
if ((value & (0xffffffff << 7)) == 0) {
|
||||
return 1;
|
||||
}
|
||||
if ((value & (0xffffffff << 14)) == 0) {
|
||||
return 2;
|
||||
}
|
||||
if ((value & (0xffffffff << 21)) == 0) {
|
||||
return 3;
|
||||
}
|
||||
if ((value & (0xffffffff << 28)) == 0) {
|
||||
return 4;
|
||||
}
|
||||
return 5;
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
/*
|
||||
* Copyright 2012 The Netty Project
|
||||
*
|
||||
* The Netty Project 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:
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Encoder and decoder which transform a
|
||||
* <a href="https://github.com/google/protobuf">Google Protocol Buffers</a>
|
||||
* {@link com.google.protobuf.Message} into a
|
||||
* {@link io.netty.buffer.ByteBuf} and vice versa.
|
||||
*/
|
||||
package io.netty.handler.codec.protobuf;
|
|
@ -1,8 +0,0 @@
|
|||
module org.xbib.io.netty.handler.codec.protobuf {
|
||||
exports io.netty.handler.codec.protobuf;
|
||||
requires org.xbib.io.netty.buffer;
|
||||
requires org.xbib.io.netty.channel;
|
||||
requires org.xbib.io.netty.util;
|
||||
requires org.xbib.io.netty.handler.codec;
|
||||
requires com.google.protobuf;
|
||||
}
|
|
@ -3,6 +3,7 @@ module org.xbib.io.netty.handler.codec {
|
|||
exports io.netty.handler.codec.base64;
|
||||
exports io.netty.handler.codec.bytes;
|
||||
exports io.netty.handler.codec.json;
|
||||
exports io.netty.handler.codec.serialization;
|
||||
exports io.netty.handler.codec.string;
|
||||
exports io.netty.handler.codec.xml;
|
||||
requires org.xbib.io.netty.buffer;
|
||||
|
|
7
netty-handler-ssl-bouncycastle/build.gradle
Normal file
7
netty-handler-ssl-bouncycastle/build.gradle
Normal file
|
@ -0,0 +1,7 @@
|
|||
dependencies {
|
||||
api project(':netty-buffer')
|
||||
api project(':netty-handler-codec')
|
||||
api project(':netty-handler-ssl')
|
||||
api project(':netty-util')
|
||||
implementation libs.bouncycastle
|
||||
}
|
|
@ -13,12 +13,14 @@
|
|||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package io.netty.handler.ssl;
|
||||
package io.netty.handler.ssl.bouncycastle;
|
||||
|
||||
import io.netty.handler.ssl.PrivateKeyProvider;
|
||||
import io.netty.util.CharsetUtil;
|
||||
import io.netty.util.internal.logging.InternalLogger;
|
||||
import io.netty.util.internal.logging.InternalLoggerFactory;
|
||||
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.bouncycastle.openssl.PEMDecryptorProvider;
|
||||
import org.bouncycastle.openssl.PEMEncryptedKeyPair;
|
||||
import org.bouncycastle.openssl.PEMKeyPair;
|
||||
|
@ -37,60 +39,16 @@ import java.io.FileReader;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.Provider;
|
||||
|
||||
final class BouncyCastlePemReader {
|
||||
private static final String BC_PROVIDER = "org.bouncycastle.jce.provider.BouncyCastleProvider";
|
||||
private static final String BC_PEMPARSER = "org.bouncycastle.openssl.PEMParser";
|
||||
public final class BouncyCastlePemReader implements PrivateKeyProvider {
|
||||
|
||||
private static final InternalLogger logger = InternalLoggerFactory.getInstance(BouncyCastlePemReader.class);
|
||||
|
||||
private static volatile Throwable unavailabilityCause;
|
||||
private static volatile Provider bcProvider;
|
||||
private static volatile boolean attemptedLoading;
|
||||
private static final Provider bcProvider = new BouncyCastleProvider();
|
||||
|
||||
public static boolean hasAttemptedLoading() {
|
||||
return attemptedLoading;
|
||||
}
|
||||
|
||||
public static boolean isAvailable() {
|
||||
if (!hasAttemptedLoading()) {
|
||||
tryLoading();
|
||||
}
|
||||
return unavailabilityCause == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the cause if unavailable. {@code null} if available.
|
||||
*/
|
||||
public static Throwable unavailabilityCause() {
|
||||
return unavailabilityCause;
|
||||
}
|
||||
|
||||
private static void tryLoading() {
|
||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
||||
@Override
|
||||
public Void run() {
|
||||
try {
|
||||
ClassLoader classLoader = getClass().getClassLoader();
|
||||
// Check for bcprov-jdk15on:
|
||||
Class<Provider> bcProviderClass =
|
||||
(Class<Provider>) Class.forName(BC_PROVIDER, true, classLoader);
|
||||
// Check for bcpkix-jdk15on:
|
||||
Class.forName(BC_PEMPARSER, true, classLoader);
|
||||
bcProvider = bcProviderClass.getConstructor().newInstance();
|
||||
logger.debug("Bouncy Castle provider available");
|
||||
attemptedLoading = true;
|
||||
} catch (Throwable e) {
|
||||
logger.debug("Cannot load Bouncy Castle provider", e);
|
||||
unavailabilityCause = e;
|
||||
attemptedLoading = true;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
public BouncyCastlePemReader() {
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -101,13 +59,7 @@ final class BouncyCastlePemReader {
|
|||
* {@code null} if it's not password-protected.
|
||||
* @return generated {@link PrivateKey}.
|
||||
*/
|
||||
public static PrivateKey getPrivateKey(InputStream keyInputStream, String keyPassword) {
|
||||
if (!isAvailable()) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Bouncy castle provider is unavailable.", unavailabilityCause());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public PrivateKey getPrivateKey(InputStream keyInputStream, String keyPassword) {
|
||||
try {
|
||||
PEMParser parser = newParser(keyInputStream);
|
||||
return getPrivateKey(parser, keyPassword);
|
||||
|
@ -125,13 +77,7 @@ final class BouncyCastlePemReader {
|
|||
* {@code null} if it's not password-protected.
|
||||
* @return generated {@link PrivateKey}.
|
||||
*/
|
||||
public static PrivateKey getPrivateKey(File keyFile, String keyPassword) {
|
||||
if (!isAvailable()) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Bouncy castle provider is unavailable.", unavailabilityCause());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public PrivateKey getPrivateKey(File keyFile, String keyPassword) {
|
||||
try {
|
||||
PEMParser parser = newParser(keyFile);
|
||||
return getPrivateKey(parser, keyPassword);
|
||||
|
@ -218,6 +164,4 @@ final class BouncyCastlePemReader {
|
|||
private static PEMParser newParser(InputStream keyInputStream) {
|
||||
return new PEMParser(new InputStreamReader(keyInputStream, CharsetUtil.US_ASCII));
|
||||
}
|
||||
|
||||
private BouncyCastlePemReader() { }
|
||||
}
|
|
@ -14,7 +14,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
package io.netty.handler.ssl.util;
|
||||
package io.netty.handler.ssl.bouncycastle;
|
||||
|
||||
import org.bouncycastle.asn1.x500.X500Name;
|
||||
import org.bouncycastle.cert.X509CertificateHolder;
|
||||
|
@ -33,8 +33,6 @@ import java.security.SecureRandom;
|
|||
import java.security.cert.X509Certificate;
|
||||
import java.util.Date;
|
||||
|
||||
import static io.netty.handler.ssl.util.SelfSignedCertificate.newSelfSignedCertificate;
|
||||
|
||||
/**
|
||||
* Generates a self-signed certificate using <a href="https://www.bouncycastle.org/">Bouncy Castle</a>.
|
||||
*/
|
||||
|
@ -57,7 +55,7 @@ final class BouncyCastleSelfSignedCertGenerator {
|
|||
X509Certificate cert = new JcaX509CertificateConverter().setProvider(PROVIDER).getCertificate(certHolder);
|
||||
cert.verify(keypair.getPublic());
|
||||
|
||||
return newSelfSignedCertificate(fqdn, key, cert);
|
||||
return SelfSignedCertificate.newSelfSignedCertificate(fqdn, key, cert);
|
||||
}
|
||||
|
||||
private BouncyCastleSelfSignedCertGenerator() { }
|
|
@ -14,7 +14,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
package io.netty.handler.ssl.util;
|
||||
package io.netty.handler.ssl.bouncycastle;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
|
@ -14,7 +14,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
package io.netty.handler.ssl.util;
|
||||
package io.netty.handler.ssl.bouncycastle;
|
||||
|
||||
import io.netty.util.internal.PlatformDependent;
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
import io.netty.handler.ssl.PrivateKeyProvider;
|
||||
import io.netty.handler.ssl.bouncycastle.BouncyCastlePemReader;
|
||||
|
||||
module org.xbib.io.netty.handler.ssl.bouncycastle {
|
||||
exports io.netty.handler.ssl.bouncycastle;
|
||||
requires org.xbib.io.netty.buffer;
|
||||
requires org.xbib.io.netty.handler.codec;
|
||||
requires org.xbib.io.netty.handler.ssl;
|
||||
requires org.xbib.io.netty.util;
|
||||
requires org.bouncycastle.pkix;
|
||||
requires org.bouncycastle.provider;
|
||||
provides PrivateKeyProvider with BouncyCastlePemReader;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
io.netty.handler.ssl.bouncycastle.BouncyCastlePemReader
|
|
@ -13,7 +13,7 @@
|
|||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package io.netty.handler.ssl.util;
|
||||
package io.netty.handler.ssl.bouncycastle;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.function.Executable;
|
|
@ -5,11 +5,10 @@ dependencies {
|
|||
api project(':netty-handler-codec')
|
||||
api project(':netty-internal-tcnative')
|
||||
api project(':netty-channel-unix')
|
||||
implementation libs.bouncycastle
|
||||
implementation libs.conscrypt
|
||||
testImplementation testLibs.mockito.core
|
||||
testImplementation testLibs.assertj
|
||||
testImplementation project(':netty-handler')
|
||||
testImplementation project(':netty-handler-ssl-bouncycastle')
|
||||
testImplementation (testLibs.amazonCorrettoCrypt) {
|
||||
artifact {
|
||||
classifier = osdetector.classifier
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
*/
|
||||
package io.netty.handler.ssl;
|
||||
|
||||
import io.netty.util.internal.logging.InternalLogger;
|
||||
import io.netty.util.internal.logging.InternalLoggerFactory;
|
||||
import java.security.Provider;
|
||||
import javax.net.ssl.SSLEngine;
|
||||
|
||||
/**
|
||||
|
@ -22,8 +25,18 @@ import javax.net.ssl.SSLEngine;
|
|||
*/
|
||||
final class BouncyCastle {
|
||||
|
||||
private static final InternalLogger logger = InternalLoggerFactory.getInstance(BouncyCastle.class);
|
||||
|
||||
private static final boolean BOUNCY_CASTLE_ON_CLASSPATH;
|
||||
|
||||
private static final String BC_PROVIDER = "org.bouncycastle.jce.provider.BouncyCastleProvider";
|
||||
|
||||
private static final String BC_PEMPARSER = "org.bouncycastle.openssl.PEMParser";
|
||||
|
||||
private static volatile Throwable unavailabilityCause;
|
||||
private static volatile boolean attemptedLoading;
|
||||
|
||||
|
||||
static {
|
||||
boolean bcOnClasspath = false;
|
||||
try {
|
||||
|
@ -38,7 +51,7 @@ final class BouncyCastle {
|
|||
/**
|
||||
* Indicates whether or not BouncyCastle is available on the current system.
|
||||
*/
|
||||
static boolean isAvailable() {
|
||||
public static boolean isAvailable() {
|
||||
return BOUNCY_CASTLE_ON_CLASSPATH;
|
||||
}
|
||||
|
||||
|
@ -49,6 +62,40 @@ final class BouncyCastle {
|
|||
return engine.getClass().getPackage().getName().startsWith("org.bouncycastle.jsse.provider");
|
||||
}
|
||||
|
||||
public static boolean isPemParserAvailable() {
|
||||
if (!hasAttemptedLoading()) {
|
||||
tryLoading();
|
||||
}
|
||||
return unavailabilityCause == null;
|
||||
}
|
||||
|
||||
public static boolean hasAttemptedLoading() {
|
||||
return attemptedLoading;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the cause if unavailable. {@code null} if available.
|
||||
*/
|
||||
public static Throwable unavailabilityCause() {
|
||||
return unavailabilityCause;
|
||||
}
|
||||
|
||||
private static void tryLoading() {
|
||||
try {
|
||||
ClassLoader classLoader = BouncyCastle.class.getClassLoader();
|
||||
// Check for bcprov-jdk15on:
|
||||
Class<Provider> bcProviderClass = (Class<Provider>) Class.forName(BC_PROVIDER, true, classLoader);
|
||||
// Check for bcpkix-jdk15on:
|
||||
Class.forName(BC_PEMPARSER, true, classLoader);
|
||||
logger.debug("Bouncy Castle provider available");
|
||||
attemptedLoading = true;
|
||||
} catch (Throwable e) {
|
||||
logger.debug("Cannot load Bouncy Castle provider", e);
|
||||
unavailabilityCause = e;
|
||||
attemptedLoading = true;
|
||||
}
|
||||
}
|
||||
|
||||
private BouncyCastle() {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
* Copyright 2021 The Netty Project
|
||||
*
|
||||
* The Netty Project 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:
|
||||
*
|
||||
* https://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 io.netty.handler.ssl;
|
||||
|
||||
import io.netty.util.internal.SuppressJava6Requirement;
|
||||
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import java.util.List;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
@SuppressJava6Requirement(reason = "Usage guarded by java version check")
|
||||
final class BouncyCastleAlpnSslEngine extends JdkAlpnSslEngine {
|
||||
|
||||
BouncyCastleAlpnSslEngine(SSLEngine engine,
|
||||
@SuppressWarnings("deprecation") JdkApplicationProtocolNegotiator applicationNegotiator,
|
||||
boolean isServer) {
|
||||
super(engine, applicationNegotiator, isServer,
|
||||
new BiConsumer<SSLEngine, AlpnSelector>() {
|
||||
@Override
|
||||
public void accept(SSLEngine e, AlpnSelector s) {
|
||||
BouncyCastleAlpnSslUtils.setHandshakeApplicationProtocolSelector(e, s);
|
||||
}
|
||||
},
|
||||
new BiConsumer<SSLEngine, List<String>>() {
|
||||
@Override
|
||||
public void accept(SSLEngine e, List<String> p) {
|
||||
BouncyCastleAlpnSslUtils.setApplicationProtocols(e, p);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public String getApplicationProtocol() {
|
||||
return BouncyCastleAlpnSslUtils.getApplicationProtocol(getWrappedEngine());
|
||||
}
|
||||
|
||||
public String getHandshakeApplicationProtocol() {
|
||||
return BouncyCastleAlpnSslUtils.getHandshakeApplicationProtocol(getWrappedEngine());
|
||||
}
|
||||
|
||||
public void setHandshakeApplicationProtocolSelector(BiFunction<SSLEngine, List<String>, String> selector) {
|
||||
BouncyCastleAlpnSslUtils.setHandshakeApplicationProtocolSelector(getWrappedEngine(), selector);
|
||||
}
|
||||
|
||||
public BiFunction<SSLEngine, List<String>, String> getHandshakeApplicationProtocolSelector() {
|
||||
return BouncyCastleAlpnSslUtils.getHandshakeApplicationProtocolSelector(getWrappedEngine());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,259 +0,0 @@
|
|||
/*
|
||||
* Copyright 2021 The Netty Project
|
||||
*
|
||||
* The Netty Project 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:
|
||||
*
|
||||
* https://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 io.netty.handler.ssl;
|
||||
|
||||
|
||||
import io.netty.util.internal.EmptyArrays;
|
||||
import io.netty.util.internal.PlatformDependent;
|
||||
import io.netty.util.internal.SuppressJava6Requirement;
|
||||
import io.netty.util.internal.logging.InternalLogger;
|
||||
import io.netty.util.internal.logging.InternalLoggerFactory;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import static io.netty.handler.ssl.SslUtils.getSSLContext;
|
||||
|
||||
@SuppressJava6Requirement(reason = "Usage guarded by java version check")
|
||||
final class BouncyCastleAlpnSslUtils {
|
||||
private static final InternalLogger logger = InternalLoggerFactory.getInstance(BouncyCastleAlpnSslUtils.class);
|
||||
private static final Method SET_PARAMETERS;
|
||||
private static final Method GET_PARAMETERS;
|
||||
private static final Method SET_APPLICATION_PROTOCOLS;
|
||||
private static final Method GET_APPLICATION_PROTOCOL;
|
||||
private static final Method GET_HANDSHAKE_APPLICATION_PROTOCOL;
|
||||
private static final Method SET_HANDSHAKE_APPLICATION_PROTOCOL_SELECTOR;
|
||||
private static final Method GET_HANDSHAKE_APPLICATION_PROTOCOL_SELECTOR;
|
||||
private static final Class BC_APPLICATION_PROTOCOL_SELECTOR;
|
||||
private static final Method BC_APPLICATION_PROTOCOL_SELECTOR_SELECT;
|
||||
|
||||
static {
|
||||
Class bcSslEngine;
|
||||
Method getParameters;
|
||||
Method setParameters;
|
||||
Method setApplicationProtocols;
|
||||
Method getApplicationProtocol;
|
||||
Method getHandshakeApplicationProtocol;
|
||||
Method setHandshakeApplicationProtocolSelector;
|
||||
Method getHandshakeApplicationProtocolSelector;
|
||||
Method bcApplicationProtocolSelectorSelect;
|
||||
Class bcApplicationProtocolSelector;
|
||||
|
||||
try {
|
||||
bcSslEngine = Class.forName("org.bouncycastle.jsse.BCSSLEngine");
|
||||
final Class testBCSslEngine = bcSslEngine;
|
||||
|
||||
bcApplicationProtocolSelector =
|
||||
Class.forName("org.bouncycastle.jsse.BCApplicationProtocolSelector");
|
||||
|
||||
final Class testBCApplicationProtocolSelector = bcApplicationProtocolSelector;
|
||||
|
||||
bcApplicationProtocolSelectorSelect = AccessController.doPrivileged(
|
||||
new PrivilegedExceptionAction<Method>() {
|
||||
@Override
|
||||
public Method run() throws Exception {
|
||||
return testBCApplicationProtocolSelector.getMethod("select", Object.class, List.class);
|
||||
}
|
||||
});
|
||||
|
||||
SSLContext context = getSSLContext("BCJSSE");
|
||||
SSLEngine engine = context.createSSLEngine();
|
||||
|
||||
getParameters = AccessController.doPrivileged(new PrivilegedExceptionAction<Method>() {
|
||||
@Override
|
||||
public Method run() throws Exception {
|
||||
return testBCSslEngine.getMethod("getParameters");
|
||||
}
|
||||
});
|
||||
|
||||
final Object bcSslParameters = getParameters.invoke(engine);
|
||||
final Class<?> bCSslParametersClass = bcSslParameters.getClass();
|
||||
|
||||
setParameters = AccessController.doPrivileged(new PrivilegedExceptionAction<Method>() {
|
||||
@Override
|
||||
public Method run() throws Exception {
|
||||
return testBCSslEngine.getMethod("setParameters", bCSslParametersClass);
|
||||
}
|
||||
});
|
||||
setParameters.invoke(engine, bcSslParameters);
|
||||
|
||||
setApplicationProtocols = AccessController.doPrivileged(new PrivilegedExceptionAction<Method>() {
|
||||
@Override
|
||||
public Method run() throws Exception {
|
||||
return bCSslParametersClass.getMethod("setApplicationProtocols", String[].class);
|
||||
}
|
||||
});
|
||||
setApplicationProtocols.invoke(bcSslParameters, new Object[]{EmptyArrays.EMPTY_STRINGS});
|
||||
|
||||
getApplicationProtocol = AccessController.doPrivileged(new PrivilegedExceptionAction<Method>() {
|
||||
@Override
|
||||
public Method run() throws Exception {
|
||||
return testBCSslEngine.getMethod("getApplicationProtocol");
|
||||
}
|
||||
});
|
||||
getApplicationProtocol.invoke(engine);
|
||||
|
||||
getHandshakeApplicationProtocol = AccessController.doPrivileged(new PrivilegedExceptionAction<Method>() {
|
||||
@Override
|
||||
public Method run() throws Exception {
|
||||
return testBCSslEngine.getMethod("getHandshakeApplicationProtocol");
|
||||
}
|
||||
});
|
||||
getHandshakeApplicationProtocol.invoke(engine);
|
||||
|
||||
setHandshakeApplicationProtocolSelector =
|
||||
AccessController.doPrivileged(new PrivilegedExceptionAction<Method>() {
|
||||
@Override
|
||||
public Method run() throws Exception {
|
||||
return testBCSslEngine.getMethod("setBCHandshakeApplicationProtocolSelector",
|
||||
testBCApplicationProtocolSelector);
|
||||
}
|
||||
});
|
||||
|
||||
getHandshakeApplicationProtocolSelector =
|
||||
AccessController.doPrivileged(new PrivilegedExceptionAction<Method>() {
|
||||
@Override
|
||||
public Method run() throws Exception {
|
||||
return testBCSslEngine.getMethod("getBCHandshakeApplicationProtocolSelector");
|
||||
}
|
||||
});
|
||||
getHandshakeApplicationProtocolSelector.invoke(engine);
|
||||
|
||||
} catch (Throwable t) {
|
||||
logger.error("Unable to initialize BouncyCastleAlpnSslUtils.", t);
|
||||
setParameters = null;
|
||||
getParameters = null;
|
||||
setApplicationProtocols = null;
|
||||
getApplicationProtocol = null;
|
||||
getHandshakeApplicationProtocol = null;
|
||||
setHandshakeApplicationProtocolSelector = null;
|
||||
getHandshakeApplicationProtocolSelector = null;
|
||||
bcApplicationProtocolSelectorSelect = null;
|
||||
bcApplicationProtocolSelector = null;
|
||||
}
|
||||
SET_PARAMETERS = setParameters;
|
||||
GET_PARAMETERS = getParameters;
|
||||
SET_APPLICATION_PROTOCOLS = setApplicationProtocols;
|
||||
GET_APPLICATION_PROTOCOL = getApplicationProtocol;
|
||||
GET_HANDSHAKE_APPLICATION_PROTOCOL = getHandshakeApplicationProtocol;
|
||||
SET_HANDSHAKE_APPLICATION_PROTOCOL_SELECTOR = setHandshakeApplicationProtocolSelector;
|
||||
GET_HANDSHAKE_APPLICATION_PROTOCOL_SELECTOR = getHandshakeApplicationProtocolSelector;
|
||||
BC_APPLICATION_PROTOCOL_SELECTOR_SELECT = bcApplicationProtocolSelectorSelect;
|
||||
BC_APPLICATION_PROTOCOL_SELECTOR = bcApplicationProtocolSelector;
|
||||
}
|
||||
|
||||
private BouncyCastleAlpnSslUtils() {
|
||||
}
|
||||
|
||||
static String getApplicationProtocol(SSLEngine sslEngine) {
|
||||
try {
|
||||
return (String) GET_APPLICATION_PROTOCOL.invoke(sslEngine);
|
||||
} catch (UnsupportedOperationException ex) {
|
||||
throw ex;
|
||||
} catch (Exception ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
static void setApplicationProtocols(SSLEngine engine, List<String> supportedProtocols) {
|
||||
String[] protocolArray = supportedProtocols.toArray(EmptyArrays.EMPTY_STRINGS);
|
||||
try {
|
||||
Object bcSslParameters = GET_PARAMETERS.invoke(engine);
|
||||
SET_APPLICATION_PROTOCOLS.invoke(bcSslParameters, new Object[]{protocolArray});
|
||||
SET_PARAMETERS.invoke(engine, bcSslParameters);
|
||||
} catch (UnsupportedOperationException ex) {
|
||||
throw ex;
|
||||
} catch (Exception ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
if (PlatformDependent.javaVersion() >= 9) {
|
||||
JdkAlpnSslUtils.setApplicationProtocols(engine, supportedProtocols);
|
||||
}
|
||||
}
|
||||
|
||||
static String getHandshakeApplicationProtocol(SSLEngine sslEngine) {
|
||||
try {
|
||||
return (String) GET_HANDSHAKE_APPLICATION_PROTOCOL.invoke(sslEngine);
|
||||
} catch (UnsupportedOperationException ex) {
|
||||
throw ex;
|
||||
} catch (Exception ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
static void setHandshakeApplicationProtocolSelector(
|
||||
SSLEngine engine, final BiFunction<SSLEngine, List<String>, String> selector) {
|
||||
try {
|
||||
Object selectorProxyInstance = Proxy.newProxyInstance(
|
||||
BouncyCastleAlpnSslUtils.class.getClassLoader(),
|
||||
new Class[]{BC_APPLICATION_PROTOCOL_SELECTOR},
|
||||
|