use of org.apache.ignite.internal.processors.rest.client.message.GridClientHandshakeRequest in project ignite by apache.
the class TcpRestUnmarshalVulnerabilityTest method attack.
/**
* @param data Data.
*/
private void attack(byte[] data) throws IOException {
InetAddress addr = InetAddress.getByName(host);
try (Socket sock = new Socket(addr, port);
OutputStream os = new BufferedOutputStream(sock.getOutputStream())) {
// Handshake request.
os.write(IGNITE_HANDSHAKE_FLAG);
GridClientHandshakeRequest req = new GridClientHandshakeRequest();
req.marshallerId(GridClientJdkMarshaller.ID);
os.write(req.rawBytes());
os.flush();
// Handshake response
InputStream is = new BufferedInputStream(sock.getInputStream());
// Read handshake response.
is.read(new byte[146]);
int len = data.length + 40;
// Package type.
os.write(IGNITE_REQ_FLAG);
// Package length.
os.write((byte) (len >> 24));
os.write((byte) (len >> 16));
os.write((byte) (len >> 8));
os.write((byte) (len));
// Stream header.
os.write(new byte[40]);
// Exploit.
os.write(data);
os.flush();
}
}
use of org.apache.ignite.internal.processors.rest.client.message.GridClientHandshakeRequest in project ignite by apache.
the class GridTcpRouterNioListenerAdapter method onMessage.
/**
* {@inheritDoc}
*/
@SuppressWarnings("TypeMayBeWeakened")
@Override
public void onMessage(final GridNioSession ses, final GridClientMessage msg) {
if (msg instanceof GridRouterRequest) {
GridRouterRequest routerMsg = (GridRouterRequest) msg;
final UUID clientId = routerMsg.clientId();
final long reqId = routerMsg.requestId();
try {
client.forwardMessage(routerMsg, routerMsg.destinationId(), ses.<Byte>meta(MARSHALLER_ID.ordinal())).listen(new GridClientFutureListener() {
@Override
public void onDone(GridClientFuture fut) {
try {
GridRouterResponse res = (GridRouterResponse) fut.get();
// Restoring original request id, because it was overwritten by the client.
res.requestId(reqId);
ses.send(res);
} catch (GridClientException e) {
ses.send(makeFailureResponse(e, clientId, reqId));
}
}
});
} catch (GridClientException e) {
ses.send(makeFailureResponse(e, clientId, reqId));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
U.warn(log, "Message forwarding was interrupted (will ignore last message): " + e.getMessage());
}
} else if (msg instanceof GridClientHandshakeRequest) {
GridClientHandshakeRequest hs = (GridClientHandshakeRequest) msg;
short ver = hs.version();
if (!SUPP_VERS.contains(ver)) {
U.error(log, "Client protocol version is not supported [ses=" + ses + ", ver=" + ver + ", supported=" + SUPP_VERS + ']');
ses.close();
} else {
byte marshId = hs.marshallerId();
GridClientMarshaller marsh = marshMap.get(marshId);
if (marsh == null) {
U.error(log, "Client marshaller ID is invalid. Note that .NET and C++ clients " + "are supported only in enterprise edition [ses=" + ses + ", marshId=" + marshId + ']');
ses.close();
} else {
ses.addMeta(MARSHALLER_ID.ordinal(), marshId);
ses.addMeta(MARSHALLER.ordinal(), marsh);
ses.send(GridClientHandshakeResponse.OK);
}
}
} else if (msg instanceof GridClientPingPacket)
ses.send(GridClientPingPacket.PING_MESSAGE);
else
throw new IllegalArgumentException("Unsupported input message: " + msg);
}
use of org.apache.ignite.internal.processors.rest.client.message.GridClientHandshakeRequest in project ignite by apache.
the class TcpRestParserSelfTest method testParseClientHandshake.
/**
* Tests correct parsing of client handshake packets.
*
* @throws Exception If failed.
*/
@Test
public void testParseClientHandshake() throws Exception {
for (int splitPos = 1; splitPos < 5; splitPos++) {
log.info("Checking split position: " + splitPos);
ByteBuffer tmp = clientHandshakePacket();
ByteBuffer[] split = split(tmp, splitPos);
GridNioSession ses = new MockNioSession();
ses.addMeta(MARSHALLER.ordinal(), new GridClientOptimizedMarshaller());
GridTcpRestParser parser = new GridTcpRestParser(false);
Collection<GridClientMessage> lst = new ArrayList<>(1);
for (ByteBuffer buf : split) {
GridClientMessage r;
while (buf.hasRemaining() && (r = parser.decode(ses, buf)) != null) lst.add(r);
assertTrue("Parser has left unparsed bytes.", buf.remaining() == 0);
}
assertEquals(1, lst.size());
GridClientHandshakeRequest req = (GridClientHandshakeRequest) F.first(lst);
assertNotNull(req);
assertEquals(U.bytesToShort(new byte[] { 5, 0 }, 0), req.version());
}
}
use of org.apache.ignite.internal.processors.rest.client.message.GridClientHandshakeRequest in project ignite by apache.
the class GridTcpRestNioListener method onMessage.
/**
* {@inheritDoc}
*/
@Override
public void onMessage(final GridNioSession ses, final GridClientMessage msg) {
if (msg instanceof GridMemcachedMessage)
memcachedLsnr.onMessage(ses, (GridMemcachedMessage) msg);
else if (msg instanceof GridRedisMessage)
redisLsnr.onMessage(ses, (GridRedisMessage) msg);
else if (msg instanceof GridClientPingPacket)
ses.send(msg);
else if (msg instanceof GridClientHandshakeRequest) {
GridClientHandshakeRequest hs = (GridClientHandshakeRequest) msg;
short ver = hs.version();
if (!SUPP_VERS.contains(ver)) {
U.error(log, "Client protocol version is not supported [ses=" + ses + ", ver=" + ver + ", supported=" + SUPP_VERS + ']');
onSessionClosed(ses);
} else {
byte marshId = hs.marshallerId();
if (marshMapLatch.getCount() > 0) {
try {
U.await(marshMapLatch);
} catch (IgniteInterruptedCheckedException e) {
U.error(log, "Marshaller is not initialized.", e);
onSessionClosed(ses);
return;
}
}
GridClientMarshaller marsh = marshMap.get(marshId);
if (marsh == null) {
U.error(log, "Client marshaller ID is invalid. Note that .NET and C++ clients " + "are supported only in enterprise edition [ses=" + ses + ", marshId=" + marshId + ']');
onSessionClosed(ses);
} else {
ses.addMeta(MARSHALLER.ordinal(), marsh);
ses.send(GridClientHandshakeResponse.OK);
}
}
} else {
final GridRestRequest req = createRestRequest(ses, msg);
if (req != null) {
IgniteInternalFuture<GridRestResponse> taskFut = hnd.handleAsync(req);
if (isInterruptible(msg))
addFutureToSession(ses, taskFut);
taskFut.listen(new CI1<IgniteInternalFuture<GridRestResponse>>() {
@Override
public void apply(IgniteInternalFuture<GridRestResponse> fut) {
removeFutureFromSession(ses, taskFut);
GridClientResponse res = new GridClientResponse();
res.requestId(msg.requestId());
res.clientId(msg.clientId());
try {
GridRestResponse restRes = fut.get();
res.sessionToken(restRes.sessionTokenBytes());
res.successStatus(restRes.getSuccessStatus());
res.errorMessage(restRes.getError());
Object o = restRes.getResponse();
// In case of metrics a little adjustment is needed.
if (o instanceof GridCacheRestMetrics)
o = ((GridCacheRestMetrics) o).map();
res.result(o);
} catch (IgniteCheckedException e) {
U.error(log, "Failed to process client request: " + msg, e);
res.successStatus(GridClientResponse.STATUS_FAILED);
res.errorMessage("Failed to process client request: " + e.getMessage());
}
GridNioFuture<?> sf = ses.send(res);
// Check if send failed.
sf.listen(new CI1<IgniteInternalFuture<?>>() {
@Override
public void apply(IgniteInternalFuture<?> fut) {
try {
fut.get();
} catch (IgniteCheckedException e) {
U.error(log, "Failed to process client request [ses=" + ses + ", msg=" + msg + ']', e);
}
}
});
}
});
} else
U.error(log, "Failed to process client request (unknown packet type) [ses=" + ses + ", msg=" + msg + ']');
}
}
use of org.apache.ignite.internal.processors.rest.client.message.GridClientHandshakeRequest in project ignite by apache.
the class GridTcpRestParser method parseHandshake.
/**
* Parses a client handshake, checking a client version and
* reading the marshaller protocol ID.
*
* @param buf Message bytes.
* @param state Parser state.
* @return True if a hint was parsed, false if still need more bytes to parse.
*/
@Nullable
private GridClientMessage parseHandshake(ByteBuffer buf, ParserState state) {
assert state.packetType() == GridClientPacketType.IGNITE_HANDSHAKE;
int idx = state.index();
GridClientHandshakeRequest packet = (GridClientHandshakeRequest) state.packet();
if (packet == null) {
packet = new GridClientHandshakeRequest();
state.packet(packet);
}
int rem = buf.remaining();
if (rem > 0) {
// Buffer to read data to.
byte[] bbuf = new byte[5];
// Number of bytes to read.
int nRead = Math.min(rem, bbuf.length);
// Batch read from buffer.
buf.get(bbuf, 0, nRead);
// Number of available bytes.
int nAvailable = nRead;
if (idx < 4) {
// Need to read version bytes.
// Number of version bytes available in buffer.
int len = Math.min(nRead, 4 - idx);
packet.putBytes(bbuf, idx, len);
idx += len;
state.index(idx);
nAvailable -= len;
}
assert idx <= 4 : "Wrong idx: " + idx;
assert nAvailable == 0 || nAvailable == 1 : "Wrong nav: " + nAvailable;
if (idx == 4 && nAvailable > 0)
return packet;
}
// Wait for more data.
return null;
}
Aggregations