Skip to content

Commit c91027d

Browse files
authored
fix: support plaintext PU when AuthPolicy is NONE (#16374)
Change-Id: Ic201a42623151d99369a2692b8e8206a2b281007
1 parent c587ff6 commit c91027d

4 files changed

Lines changed: 159 additions & 19 deletions

File tree

dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyPortUnificationServerHandler.java

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -127,27 +127,29 @@ protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) t
127127
if (providerConnectionConfig != null && canDetectSsl(in)) {
128128
if (isSsl(in)) {
129129
enableSsl(ctx, providerConnectionConfig);
130-
} else {
131-
// check server should load TLS or not
132-
if (providerConnectionConfig.getAuthPolicy() != AuthPolicy.NONE) {
133-
byte[] preface = new byte[in.readableBytes()];
134-
in.readBytes(preface);
135-
LOGGER.error(
136-
CONFIG_SSL_CONNECT_INSECURE,
137-
"client request server without TLS",
138-
"",
139-
String.format(
140-
"Downstream=%s request without TLS preface, but server require it. " + "preface=%s",
141-
ctx.channel().remoteAddress(), Bytes.bytes2hex(preface)));
142-
143-
// Untrusted connection; discard everything and close the connection.
144-
in.clear();
145-
ctx.close();
146-
}
130+
return;
131+
}
132+
// check server should load TLS or not
133+
if (providerConnectionConfig.getAuthPolicy() != AuthPolicy.NONE) {
134+
byte[] preface = new byte[in.readableBytes()];
135+
in.readBytes(preface);
136+
LOGGER.error(
137+
CONFIG_SSL_CONNECT_INSECURE,
138+
"client request server without TLS",
139+
"",
140+
String.format(
141+
"Downstream=%s request without TLS preface, but server require it. " + "preface=%s",
142+
ctx.channel().remoteAddress(), Bytes.bytes2hex(preface)));
143+
144+
// Untrusted connection; discard everything and close the connection.
145+
in.clear();
146+
ctx.close();
147+
return;
147148
}
148-
} else {
149-
detectProtocol(ctx, url, channel, in);
149+
// AuthPolicy.NONE with a non-TLS client: permissive mode, fall through to
150+
// plaintext protocol detection below instead of silently waiting for more data.
150151
}
152+
detectProtocol(ctx, url, channel, in);
151153
}
152154

153155
private void enableSsl(ChannelHandlerContext ctx, ProviderCert providerConnectionConfig) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.dubbo.remoting.transport.netty4;
18+
19+
import org.apache.dubbo.common.URL;
20+
import org.apache.dubbo.remoting.ChannelHandler;
21+
import org.apache.dubbo.remoting.api.ProtocolDetector;
22+
import org.apache.dubbo.remoting.api.WireProtocol;
23+
import org.apache.dubbo.remoting.api.pu.ChannelOperator;
24+
import org.apache.dubbo.remoting.api.ssl.ContextOperator;
25+
import org.apache.dubbo.rpc.model.ApplicationModel;
26+
import org.apache.dubbo.rpc.model.FrameworkModel;
27+
28+
import java.util.Collections;
29+
import java.util.concurrent.atomic.AtomicInteger;
30+
31+
import io.netty.buffer.Unpooled;
32+
import io.netty.channel.embedded.EmbeddedChannel;
33+
import org.junit.jupiter.api.Test;
34+
35+
import static org.junit.jupiter.api.Assertions.assertEquals;
36+
import static org.junit.jupiter.api.Assertions.assertTrue;
37+
import static org.mockito.Mockito.mock;
38+
39+
class NettyPortUnificationServerHandlerTest {
40+
41+
@Test
42+
void shouldDetectPlaintextProtocolWhenAuthPolicyIsNone() {
43+
AtomicInteger detectCount = new AtomicInteger();
44+
FrameworkModel frameworkModel = new FrameworkModel();
45+
try {
46+
ApplicationModel applicationModel = frameworkModel.newApplication();
47+
URL url = URL.valueOf("dubbo://127.0.0.1:20880?codec=default&pu.test.cert=true")
48+
.setScopeModel(applicationModel);
49+
ChannelHandler handler = mock(ChannelHandler.class);
50+
WireProtocol protocol = new CountingWireProtocol(detectCount);
51+
NettyPortUnificationServerHandler puHandler = new NettyPortUnificationServerHandler(
52+
url,
53+
true,
54+
Collections.singletonMap("dubbo", protocol),
55+
handler,
56+
Collections.singletonMap("dubbo", url),
57+
Collections.emptyMap());
58+
EmbeddedChannel channel = new EmbeddedChannel(puHandler);
59+
60+
channel.writeInbound(Unpooled.wrappedBuffer(new byte[] {(byte) 0xda, (byte) 0xbb, 0, 0, 0}));
61+
62+
assertEquals(1, detectCount.get());
63+
assertTrue(channel.isOpen());
64+
channel.finishAndReleaseAll();
65+
} finally {
66+
frameworkModel.destroy();
67+
}
68+
}
69+
70+
private static final class CountingWireProtocol implements WireProtocol {
71+
private final AtomicInteger detectCount;
72+
73+
private CountingWireProtocol(AtomicInteger detectCount) {
74+
this.detectCount = detectCount;
75+
}
76+
77+
@Override
78+
public ProtocolDetector detector() {
79+
return in -> {
80+
detectCount.incrementAndGet();
81+
return ProtocolDetector.Result.needMoreData();
82+
};
83+
}
84+
85+
@Override
86+
public void configServerProtocolHandler(URL url, ChannelOperator operator) {}
87+
88+
@Override
89+
public void configClientPipeline(URL url, ChannelOperator operator, ContextOperator contextOperator) {}
90+
91+
@Override
92+
public void close() {}
93+
}
94+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.dubbo.remoting.transport.netty4;
18+
19+
import org.apache.dubbo.common.URL;
20+
import org.apache.dubbo.common.extension.Activate;
21+
import org.apache.dubbo.common.ssl.AuthPolicy;
22+
import org.apache.dubbo.common.ssl.Cert;
23+
import org.apache.dubbo.common.ssl.CertProvider;
24+
import org.apache.dubbo.common.ssl.ProviderCert;
25+
26+
@Activate(order = -10000)
27+
public class PortUnificationTestCertProvider implements CertProvider {
28+
29+
@Override
30+
public boolean isSupport(URL address) {
31+
return address.getParameter("pu.test.cert", false);
32+
}
33+
34+
@Override
35+
public ProviderCert getProviderConnectionConfig(URL localAddress) {
36+
return new ProviderCert(new byte[0], new byte[0], null, AuthPolicy.NONE);
37+
}
38+
39+
@Override
40+
public Cert getConsumerConnectionConfig(URL remoteAddress) {
41+
return null;
42+
}
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pu-test-cert=org.apache.dubbo.remoting.transport.netty4.PortUnificationTestCertProvider

0 commit comments

Comments
 (0)