Ethereal-dev: [Ethereal-dev] patch for SSH Version 1 support

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Huagang Xie <xie@xxxxxxxx>
Date: Mon, 27 Jan 2003 22:08:34 -0800
Hello, 

Here is the patch to support SSH version 1 dissection support, 
it include,
	- added ssh version 1 support
	- fixed desegmentation length checking bug
	- seperated the disection for ssh v2 and v1

Enjoy it,
Huagang

-- 
LIDS secure linux kernel
http://www.lids.org/
1024D/B6EFB028 		4731 2BF7 7735 4DBD 3771  4E24 B53B B60A B6EF B028
Index: packet-ssh.c
===================================================================
RCS file: /cvsroot/ethereal/packet-ssh.c,v
retrieving revision 1.2
diff -u -r1.2 packet-ssh.c
--- packet-ssh.c	27 Jan 2003 19:40:55 -0000	1.2
+++ packet-ssh.c	28 Jan 2003 06:01:16 -0000
@@ -26,7 +26,7 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  *
  *
- * Note:  only support SSHv2 now. 
+ * Note:  support SSH v1 and v2  now. 
  * 
  */
 
@@ -69,6 +69,15 @@
 #define SSH2_MSG_KEX_DH_GEX_REPLY			33
 #define SSH2_MSG_KEX_DH_GEX_REQUEST			34
 
+/* SSH Version 1 definition , from openssh ssh1.h */
+
+#define SSH_MSG_NONE				0	/* no message */
+#define SSH_MSG_DISCONNECT			1	/* cause (string) */
+#define SSH_SMSG_PUBLIC_KEY			2	/* ck,msk,srvk,hostk */
+#define SSH_CMSG_SESSION_KEY			3	/* key (BIGNUM) */
+#define SSH_CMSG_USER				4	/* user (string) */
+
+
 #define SSH_VERSION_UNKNOWN 	0
 #define SSH_VERSION_1		1
 #define SSH_VERSION_2		2
@@ -122,12 +131,13 @@
 static gint ett_ssh = -1;
 static gint ett_key_exchange= -1;
 static gint ett_key_init= -1;
+static gint ett_ssh1= -1;
 
 static gboolean ssh_desegment = TRUE;
 
 #define TCP_PORT_SSH  22 
 
-static const value_string ssh_msg_vals[] = {
+static const value_string ssh2_msg_vals[] = {
 	{SSH2_MSG_DISCONNECT, "Disconnect"},
 	{SSH2_MSG_IGNORE, "Ignore"},
 	{SSH2_MSG_UNIMPLEMENTED, "Unimplemented"},
@@ -144,6 +154,14 @@
   	{ 0,          NULL }
 };
 
+static const value_string ssh1_msg_vals[] = {
+	{SSH_MSG_NONE,"No Message"},
+	{SSH_MSG_DISCONNECT, "Disconnect"},
+	{SSH_SMSG_PUBLIC_KEY,"Public Key"},
+	{SSH_CMSG_SESSION_KEY,"Session Key"},
+	{SSH_CMSG_USER,"User"},
+};
+
 
 static const value_string ssh_opcode_vals[] = {
   { 0,          NULL }
@@ -151,6 +169,12 @@
 
 static int ssh_dissect_key_init(tvbuff_t *tvb, int offset, proto_tree *tree);
 
+static int ssh_dissect_ssh1(tvbuff_t *tvb, packet_info *pinfo,
+		int offset, proto_tree *tree,int is_response,
+		int number, gboolean *need_desegmentation);
+static int ssh_dissect_ssh2(tvbuff_t *tvb, packet_info *pinfo, 
+		int offset, proto_tree *tree,int is_response,
+		int number, gboolean *need_desegmentation );
 static int ssh_dissect_key_exchange(tvbuff_t *tvb, packet_info *pinfo, 
 		int offset, proto_tree *tree,int is_response,
 		int number, gboolean *need_desegmentation );
@@ -262,18 +286,17 @@
 		}
 	}
 
-	/* we will not decode SSH1 now */
-	if(this_data->counter != 0 && version != SSH_VERSION_2) {
+	if(this_data->counter != 0 && version == SSH_VERSION_UNKNOWN) {
 		offset = ssh_dissect_encrypted_packet(tvb, pinfo,
 			offset,ssh_tree,is_response);
 		return;
 	}
 			
 	while((remain_length = tvb_reported_length_remaining(tvb,offset))> 0 ) {
-
 		need_desegmentation = FALSE;
 		last_offset = offset;
 		this_number = this_data->counter+number;
+
 		if(number > 1 && is_newdata) {
 			/* update the this_data and flow_data */
 			if(is_response) {
@@ -284,29 +307,131 @@
 		}
 				
 		number++;
-	
 		if(this_number == 0)  {
-			offset = ssh_dissect_protocol(tvb, pinfo,offset,ssh_tree,
-					is_response,&version, &need_desegmentation);
+			offset = ssh_dissect_protocol(tvb, pinfo,
+					offset,ssh_tree, is_response,
+					&version, &need_desegmentation);
 			if(!is_response) {
 				global_data->version= version;
 			}
 		} else {
-			/* response, 1, 2 is key_exchange */
-			/* request, 1,2,3,4 is key_exchange */
-			if((is_response && this_number > 3) || (!is_response && this_number>4)) {
-				offset = ssh_dissect_encrypted_packet(tvb, pinfo,
-						offset,ssh_tree,is_response);
-			} else {
-				offset = ssh_dissect_key_exchange(tvb,pinfo,
+			if(version == SSH_VERSION_1) {
+				offset = ssh_dissect_ssh1(tvb, pinfo,
+						offset,ssh_tree,is_response,this_number, 
+						&need_desegmentation);
+			} else if(version == SSH_VERSION_2) {
+				offset = ssh_dissect_ssh2(tvb, pinfo,
 						offset,ssh_tree,is_response,this_number,
 						&need_desegmentation);
 			}
 		}
+
 		if(need_desegmentation) return;
 	}
 }
 
+static int 
+ssh_dissect_ssh2(tvbuff_t *tvb, packet_info *pinfo,
+	       	int offset, proto_tree *tree,int is_response, int this_number,
+		gboolean *need_desegmentation)
+{
+	
+	if((is_response && this_number > 3) || (!is_response && this_number>4)) {
+		offset = ssh_dissect_encrypted_packet(tvb, pinfo,
+				offset,tree,is_response);
+	} else {
+		offset = ssh_dissect_key_exchange(tvb,pinfo,
+			offset,tree,is_response,this_number,
+			need_desegmentation);
+	}
+
+	return offset;
+}
+static int 
+ssh_dissect_ssh1(tvbuff_t *tvb, packet_info *pinfo,
+	       	int offset, proto_tree *tree,int is_response, 
+		int number, gboolean *need_desegmentation)
+{
+	guint 	plen, padding_length,len;
+	guint8 	msg_code;
+	guint	remain_length=0;
+
+	proto_item *tf;
+	proto_item *ssh1_tree =NULL;
+	
+	if (ssh_desegment && pinfo->can_desegment) {
+		remain_length = tvb_reported_length_remaining(tvb,offset);
+		if(remain_length < 4) {
+                	pinfo->desegment_offset = offset;
+                	pinfo->desegment_len = 4-remain_length;
+                	*need_desegmentation = TRUE;
+                	return offset;
+		}
+	}
+	plen = tvb_get_ntohl(tvb, offset) ;
+
+	padding_length  = 8 - plen%8;
+	if (ssh_desegment && pinfo->can_desegment) {
+		if(plen+4+padding_length >  remain_length ) {
+                	pinfo->desegment_offset = offset;
+                	pinfo->desegment_len = plen+padding_length - remain_length;
+                	*need_desegmentation = TRUE;
+                	return offset;
+		}
+	}
+
+	if (check_col(pinfo->cinfo, COL_INFO)) {
+  		col_add_fstr(pinfo->cinfo, COL_INFO, "%s: ", 
+			is_response?"Server":"Client");
+	}
+
+	if (tree) {
+		  proto_tree_add_uint(tree, hf_ssh_packet_length, tvb,
+		    offset, 4, plen);
+	}
+	offset+=4;
+/* padding length */
+
+	if (tree) {
+		  proto_tree_add_uint(tree, hf_ssh_padding_length, tvb,
+		    offset, padding_length, padding_length);
+	}
+	offset += padding_length;
+
+	if(tree) {
+		tf=proto_tree_add_text(tree,tvb,offset,-1,"SSH Version 1");
+		ssh1_tree = proto_item_add_subtree(tf ,ett_ssh1);
+	}
+	/* msg_code */
+	if(number == 1 ) {
+		msg_code = tvb_get_guint8(tvb, offset);
+		if (tree) {
+		  	proto_tree_add_uint_format(ssh1_tree, hf_ssh_msg_code, tvb,
+		    		offset, 1, msg_code,"Msg code: %s (%u)",
+				val_to_str(msg_code, ssh1_msg_vals, "Unknown (%u)"),
+				msg_code);
+		}
+		if (check_col(pinfo->cinfo, COL_INFO)) {
+			col_append_fstr(pinfo->cinfo, COL_INFO, "%s", 
+			val_to_str(msg_code, ssh1_msg_vals, "Unknown (%u)"));
+		}
+		offset += 1;
+		len = plen -1;
+	} else {
+		len = plen;
+		if (check_col(pinfo->cinfo, COL_INFO)) {
+			col_append_fstr(pinfo->cinfo, COL_INFO, "Encrypted packet len %d", len);
+		}
+	}
+	/* payload */
+	if (tree) {
+		proto_tree_add_item(ssh1_tree, hf_ssh_payload,
+		    tvb, offset, len, FALSE);
+	}
+	offset+=len;
+
+	return offset;
+}
 
 static int 
 ssh_dissect_key_exchange(tvbuff_t *tvb, packet_info *pinfo,
@@ -334,7 +459,7 @@
 	plen = tvb_get_ntohl(tvb, offset) ;
 
 	if (ssh_desegment && pinfo->can_desegment) {
-		if(plen < remain_length - 4 ) {
+		if(plen +4 >  remain_length ) {
                 	pinfo->desegment_offset = offset;
                 	pinfo->desegment_len = plen+4 - remain_length;
                 	*need_desegmentation = TRUE;
@@ -369,13 +494,13 @@
 	if (tree) {
 		  proto_tree_add_uint_format(key_ex_tree, hf_ssh_msg_code, tvb,
 		    offset, 1, msg_code,"Msg code: %s (%u)",
-			val_to_str(msg_code, ssh_msg_vals, "Unknown (%u)"),
+			val_to_str(msg_code, ssh2_msg_vals, "Unknown (%u)"),
 			msg_code);
 		    
 	}
 	if (check_col(pinfo->cinfo, COL_INFO)) {
 		col_append_fstr(pinfo->cinfo, COL_INFO, "%s", 
-			val_to_str(msg_code, ssh_msg_vals, "Unknown (%u)"));
+			val_to_str(msg_code, ssh2_msg_vals, "Unknown (%u)"));
 	}
 	offset += 1;
 	
@@ -450,9 +575,11 @@
 	}
 
 	if(!is_response) {
-	       if(tvb_strncaseeql(tvb,offset,"SSH-2.",6) == 0 ) {
+	       	if(tvb_strncaseeql(tvb,offset,"SSH-2.",6) == 0 ) {
+			*(version) = SSH_VERSION_2;
+		}else if(tvb_strncaseeql(tvb,offset,"SSH-1.99-",9) == 0 ) {
 			*(version) = SSH_VERSION_2;
-	       }else if(tvb_strncaseeql(tvb,offset,"SSH-1.",6) == 0 ) {
+	       	}else if(tvb_strncaseeql(tvb,offset,"SSH-1.",6) == 0 ) {
 			*(version) = SSH_VERSION_1;
 	       }
 	}
@@ -788,6 +915,7 @@
   	static gint *ett[] = {
     		&ett_ssh,
 		&ett_key_exchange,
+		&ett_ssh1,
 		&ett_key_init
   	};
   	module_t *ssh_module;

Attachment: pgpey8IAbEe2c.pgp
Description: PGP signature