Skip to content

Commit 563a5e3

Browse files
committed
IGNITE-27554 Add check for serMode
1 parent 97a1829 commit 563a5e3

File tree

3 files changed

+116
-9
lines changed

3 files changed

+116
-9
lines changed

modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoveryIoSession.java

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,16 @@ <T> T readMessage() throws IgniteCheckedException, IOException {
168168

169169
try {
170170
if (MESSAGE_SERIALIZATION != serMode) {
171-
detectSslAlert(serMode, in);
171+
byte[] hdr = new byte[4];
172+
hdr[0] = serMode;
173+
174+
int read = in.readNBytes(hdr, 1, 3);
175+
176+
if (read < 3)
177+
throw new EOFException();
178+
179+
detectSslAlert(hdr);
180+
detectJavaObjectStreamHeader(hdr);
172181

173182
// IOException type is important for ServerImpl. It may search the cause (X.hasCause).
174183
// The connection error processing behavior depends on it.
@@ -307,17 +316,23 @@ private void serializeMessage(Message m, OutputStream out) throws IOException {
307316
* See handling {@code StreamCorruptedException} in {@link #readMessage()}.
308317
* Keeps logic similar to {@link java.io.ObjectInputStream#readStreamHeader}.
309318
*/
310-
private void detectSslAlert(byte firstByte, InputStream in) throws IOException {
311-
byte[] hdr = new byte[4];
312-
hdr[0] = firstByte;
313-
int read = in.readNBytes(hdr, 1, 3);
314-
315-
if (read < 3)
316-
throw new EOFException();
317-
319+
private void detectSslAlert(byte[] hdr) throws IOException {
318320
String hex = String.format("%02x%02x%02x%02x", hdr[0], hdr[1], hdr[2], hdr[3]);
319321

320322
if (hex.matches("15....00"))
321323
throw new StreamCorruptedException("invalid stream header: " + hex);
322324
}
325+
326+
/**
327+
* Detects Java Object Serialization stream header (AC ED 00 05).
328+
* This indicates that the remote node sends discovery messages without leading serMode byte.
329+
*/
330+
private void detectJavaObjectStreamHeader(byte[] hdr) throws IOException {
331+
if ((hdr[0] == (byte)0xAC) && (hdr[1] == (byte)0xED) && (hdr[2] == (byte)0x00) && (hdr[3] == (byte)0x05))
332+
throw new IOException(
333+
"Incompatible discovery protocol: received Java ObjectStream header (AC ED 00 05) where serMode byte is expected. "
334+
+ "Remote node likely uses a discovery message format without serMode. "
335+
+ "All nodes must run compatible Ignite versions."
336+
);
337+
}
323338
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
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+
18+
package org.apache.ignite.spi.discovery.tcp;
19+
20+
import java.io.ByteArrayInputStream;
21+
import java.io.ByteArrayOutputStream;
22+
import java.io.IOException;
23+
import java.io.InputStream;
24+
import java.io.OutputStream;
25+
import java.net.Socket;
26+
import org.apache.ignite.IgniteCheckedException;
27+
import org.apache.ignite.internal.IgniteEx;
28+
import org.apache.ignite.internal.util.typedef.X;
29+
import org.apache.ignite.internal.util.typedef.internal.U;
30+
import org.apache.ignite.spi.discovery.tcp.messages.TcpDiscoveryHandshakeRequest;
31+
import org.apache.ignite.testframework.GridTestUtils;
32+
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
33+
import org.junit.Test;
34+
35+
/** Tests Java serialization header detection in discovery messages. */
36+
public class TcpDiscoveryIoSessionDifferentSerializationTest extends GridCommonAbstractTest {
37+
/** {@inheritDoc} */
38+
@Override protected void afterTest() throws Exception {
39+
stopAllGrids();
40+
}
41+
42+
/** */
43+
@Test
44+
public void testDetectJavaObjectStreamHeader() throws Exception {
45+
IgniteEx grid = startGrid(0);
46+
47+
TcpDiscoverySpi spi = (TcpDiscoverySpi)grid.configuration().getDiscoverySpi();
48+
49+
TcpDiscoveryHandshakeRequest req = new TcpDiscoveryHandshakeRequest();
50+
51+
byte[] bytes = U.marshal(spi.marshaller(), req);
52+
53+
TcpDiscoveryIoSession ses = new TcpDiscoveryIoSession(
54+
new TestSocket(new ByteArrayInputStream(bytes), new ByteArrayOutputStream()),
55+
spi
56+
);
57+
58+
Throwable e = GridTestUtils.assertThrows(log, () -> ses.readMessage(), IgniteCheckedException.class, null);
59+
60+
assertTrue(X.hasCause(e, "Incompatible discovery protocol: received Java ObjectStream header", IOException.class));
61+
}
62+
63+
/** */
64+
private static class TestSocket extends Socket {
65+
/** */
66+
private final InputStream in;
67+
68+
/** */
69+
private final OutputStream out;
70+
71+
/**
72+
* @param in Input stream.
73+
* @param out Output stream.
74+
*/
75+
private TestSocket(InputStream in, OutputStream out) {
76+
this.in = in;
77+
this.out = out;
78+
}
79+
80+
/** {@inheritDoc} */
81+
@Override public InputStream getInputStream() {
82+
return in;
83+
}
84+
85+
/** {@inheritDoc} */
86+
@Override public OutputStream getOutputStream() {
87+
return out;
88+
}
89+
}
90+
}

modules/core/src/test/java/org/apache/ignite/testsuites/IgniteSpiDiscoverySelfTestSuite.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import org.apache.ignite.spi.discovery.tcp.TcpDiscoveryCoordinatorFailureTest;
4848
import org.apache.ignite.spi.discovery.tcp.TcpDiscoveryDeadNodeAddressResolvingTest;
4949
import org.apache.ignite.spi.discovery.tcp.TcpDiscoveryFailedJoinTest;
50+
import org.apache.ignite.spi.discovery.tcp.TcpDiscoveryIoSessionDifferentSerializationTest;
5051
import org.apache.ignite.spi.discovery.tcp.TcpDiscoveryIpFinderCleanerTest;
5152
import org.apache.ignite.spi.discovery.tcp.TcpDiscoveryIpFinderFailureTest;
5253
import org.apache.ignite.spi.discovery.tcp.TcpDiscoveryMetricsWarnLogTest;
@@ -157,6 +158,7 @@
157158
IgniteClientReconnectEventHandlingTest.class,
158159

159160
TcpDiscoveryFailedJoinTest.class,
161+
TcpDiscoveryIoSessionDifferentSerializationTest.class,
160162

161163
// SSL.
162164
TcpDiscoverySslSelfTest.class,

0 commit comments

Comments
 (0)