[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