[Red5commits] [2111] validate RTMP handshake received from client (Jira APPSERVER-159)
jbauch
luke at codegent.com
Tue Jun 19 05:20:57 EDT 2007
validate RTMP handshake received from client (Jira APPSERVER-159)
Timestamp: 06/19/07 04:02:11 EST (less than one hour ago)
Change: 2111
Author: jbauch
Files (see diff or trac for details):
doc/trunk/changelog.txt
java/server/trunk/src/org/red5/server/net/protocol/HandshakeFailedException.java
java/server/trunk/src/org/red5/server/net/rtmp/RTMPMinaIoHandler.java
java/server/trunk/src/org/red5/server/net/rtmp/codec/RTMP.java
java/server/trunk/src/org/red5/server/net/rtmp/codec/RTMPProtocolDecoder.java
java/server/trunk/src/org/red5/server/net/rtmpt/RTMPTConnection.java
java/server/trunk/src/org/red5/server/net/rtmpt/RTMPTHandler.java
Trac: http://mirror1.cvsdude.com/trac/osflash/red5/changeset/2111
Index: /java/server/trunk/src/org/red5/server/net/protocol/HandshakeFailedException.java
===================================================================
--- /java/server/trunk/src/org/red5/server/net/protocol/HandshakeFailedException.java (revision 2111)
+++ /java/server/trunk/src/org/red5/server/net/protocol/HandshakeFailedException.java (revision 2111)
@@ -0,0 +1,37 @@
+package org.red5.server.net.protocol;
+
+/*
+ * RED5 Open Source Flash Server - http://www.osflash.org/red5
+ *
+ * Copyright (c) 2006-2007 by respective authors (see below). All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation; either version 2.1 of the License, or (at your option) any later
+ * version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along
+ * with this library; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+public class HandshakeFailedException extends ProtocolException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 8255789603304183796L;
+
+ /**
+ * Create handshake failed exception with given message
+ * @param message
+ */
+ public HandshakeFailedException(String message) {
+ super(message);
+ }
+
+}
Index: /java/server/trunk/src/org/red5/server/net/rtmp/RTMPMinaIoHandler.java
===================================================================
--- /java/server/trunk/src/org/red5/server/net/rtmp/RTMPMinaIoHandler.java (revision 2092)
+++ /java/server/trunk/src/org/red5/server/net/rtmp/RTMPMinaIoHandler.java (revision 2111)
@@ -148,4 +148,5 @@
out.put(in);
out.flip();
+ rtmp.setHandshake(out, 1, Constants.HANDSHAKE_SIZE);
//in.release();
session.write(out);
Index: /java/server/trunk/src/org/red5/server/net/rtmp/codec/RTMP.java
===================================================================
--- /java/server/trunk/src/org/red5/server/net/rtmp/codec/RTMP.java (revision 2004)
+++ /java/server/trunk/src/org/red5/server/net/rtmp/codec/RTMP.java (revision 2111)
@@ -20,7 +20,9 @@
*/
+import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
+import org.apache.mina.common.ByteBuffer;
import org.red5.server.api.IConnection.Encoding;
import org.red5.server.net.protocol.ProtocolState;
@@ -112,4 +114,8 @@
*/
private Encoding encoding = Encoding.AMF0;
+ /**
+ * Handshake as sent to the client.
+ */
+ private byte[] handshake;
/**
@@ -344,3 +350,38 @@
}
+ /**
+ * Store the handshake sent to the client.
+ *
+ * @param data Handshake data
+ * @param length Length of handshake to store
+ */
+ public void setHandshake(ByteBuffer data, int start, int length) {
+ handshake = new byte[length];
+ int old = data.position();
+ data.position(start);
+ data.get(handshake);
+ data.position(old);
+ }
+
+ /**
+ * Check if the handshake reply received from a client contains valid data.
+ *
+ * @param data
+ * @param length
+ * @return
+ */
+ public boolean validateHandshakeReply(ByteBuffer data, int start, int length) {
+ if (handshake == null || length != handshake.length) {
+ return false;
+ }
+
+ byte[] reply = new byte [length];
+ int old = data.position();
+ data.position(start);
+ data.get(reply);
+ data.position(old);
+
+ return Arrays.equals(reply, handshake);
+ }
+
}
Index: /java/server/trunk/src/org/red5/server/net/rtmp/codec/RTMPProtocolDecoder.java
===================================================================
--- /java/server/trunk/src/org/red5/server/net/rtmp/codec/RTMPProtocolDecoder.java (revision 1884)
+++ /java/server/trunk/src/org/red5/server/net/rtmp/codec/RTMPProtocolDecoder.java (revision 2111)
@@ -38,4 +38,5 @@
import org.red5.server.api.Red5;
import org.red5.server.api.IConnection.Encoding;
+import org.red5.server.net.protocol.HandshakeFailedException;
import org.red5.server.net.protocol.ProtocolException;
import org.red5.server.net.protocol.ProtocolState;
@@ -132,4 +133,12 @@
}
}
+ } catch (HandshakeFailedException hfe) {
+ IConnection conn = Red5.getConnectionLocal();
+ if (conn != null) {
+ conn.close();
+ } else {
+ log.error("Handshake validation failed but no current connection!?");
+ }
+ return null;
} catch (ProtocolException pvx) {
log.error("Error decoding buffer", pvx);
@@ -179,4 +188,5 @@
case RTMP.STATE_ERROR:
// attempt to correct error
+ return null;
case RTMP.STATE_CONNECT:
case RTMP.STATE_HANDSHAKE:
@@ -185,4 +195,7 @@
return null;
}
+ } catch (ProtocolException pe) {
+ // Raise to caller unmodified
+ throw pe;
} catch (RuntimeException e) {
log.error("Error in packet at " + start, e);
@@ -230,4 +243,12 @@
return null;
} else {
+ if (!rtmp.validateHandshakeReply(in, 0, HANDSHAKE_SIZE)) {
+ if (log.isDebugEnabled()) {
+ log.debug("Handshake reply validation failed, disconnecting client.");
+ }
+ in.skip(HANDSHAKE_SIZE);
+ rtmp.setState(RTMP.STATE_ERROR);
+ throw new HandshakeFailedException("Handshake validation failed");
+ }
in.skip(HANDSHAKE_SIZE);
rtmp.setState(RTMP.STATE_CONNECTED);
Index: /java/server/trunk/src/org/red5/server/net/rtmpt/RTMPTHandler.java
===================================================================
--- /java/server/trunk/src/org/red5/server/net/rtmpt/RTMPTHandler.java (revision 2035)
+++ /java/server/trunk/src/org/red5/server/net/rtmpt/RTMPTHandler.java (revision 2111)
@@ -96,4 +96,5 @@
out.fill((byte) 0x00, Constants.HANDSHAKE_SIZE);
out.put(in).flip();
+ rtmp.setHandshake(out, 1, Constants.HANDSHAKE_SIZE);
conn.rawWrite(out);
Index: /java/server/trunk/src/org/red5/server/net/rtmpt/RTMPTConnection.java
===================================================================
--- /java/server/trunk/src/org/red5/server/net/rtmpt/RTMPTConnection.java (revision 1970)
+++ /java/server/trunk/src/org/red5/server/net/rtmpt/RTMPTConnection.java (revision 2111)
@@ -28,4 +28,5 @@
import org.apache.commons.logging.LogFactory;
import org.apache.mina.common.ByteBuffer;
+import org.red5.server.api.Red5;
import org.red5.server.net.protocol.SimpleProtocolDecoder;
import org.red5.server.net.protocol.SimpleProtocolEncoder;
@@ -237,4 +238,5 @@
*/
public List decode(ByteBuffer data) {
+ Red5.setConnectionLocal(this);
readBytes += data.limit();
this.buffer.put(data);
Index: /doc/trunk/changelog.txt
===================================================================
--- /doc/trunk/changelog.txt (revision 2106)
+++ /doc/trunk/changelog.txt (revision 2111)
@@ -7,4 +7,6 @@
Red5 0.6.3 (unreleased)
------------------------
+Bugfixes:
+- validate RTMP handshake received from client (Jira APPSERVER-159)
Note:
Diffs are chopped if more than 25k.
This is to get past the limit on the mailing list.
More information about the Red5commits
mailing list