2 * Routines for ssh packet dissection
4 * Huagang XIE <huagang@intruvert.com>
6 * $Id: packet-ssh.c,v 1.5 2003/01/30 08:11:20 guy Exp $
8 * Ethereal - Network traffic analyzer
9 * By Gerald Combs <gerald@ethereal.com>
10 * Copyright 1998 Gerald Combs
12 * Copied from packet-mysql.c
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 * Note: support SSH v1 and v2 now.
38 #include <epan/packet.h>
39 #include <epan/conversation.h>
41 #include "packet-smb-common.h"
42 #include "packet-tcp.h"
43 #include "reassemble.h"
46 /* get from openssh ssh2.h */
47 #define SSH2_MSG_DISCONNECT 1
48 #define SSH2_MSG_IGNORE 2
49 #define SSH2_MSG_UNIMPLEMENTED 3
50 #define SSH2_MSG_DEBUG 4
51 #define SSH2_MSG_SERVICE_REQUEST 5
52 #define SSH2_MSG_SERVICE_ACCEPT 6
54 /* transport layer: alg negotiation */
56 #define SSH2_MSG_KEXINIT 20
57 #define SSH2_MSG_NEWKEYS 21
59 /* transport layer: kex specific messages, can be reused */
61 #define SSH2_MSG_KEXDH_INIT 30
62 #define SSH2_MSG_KEXDH_REPLY 31
65 #define SSH2_MSG_KEX_DH_GEX_REQUEST_OLD 30
66 #define SSH2_MSG_KEX_DH_GEX_GROUP 31
68 #define SSH2_MSG_KEX_DH_GEX_INIT 32
69 #define SSH2_MSG_KEX_DH_GEX_REPLY 33
70 #define SSH2_MSG_KEX_DH_GEX_REQUEST 34
72 /* SSH Version 1 definition , from openssh ssh1.h */
74 #define SSH_MSG_NONE 0 /* no message */
75 #define SSH_MSG_DISCONNECT 1 /* cause (string) */
76 #define SSH_SMSG_PUBLIC_KEY 2 /* ck,msk,srvk,hostk */
77 #define SSH_CMSG_SESSION_KEY 3 /* key (BIGNUM) */
78 #define SSH_CMSG_USER 4 /* user (string) */
81 #define SSH_VERSION_UNKNOWN 0
82 #define SSH_VERSION_1 1
83 #define SSH_VERSION_2 2
92 struct ssh_flow_data {
97 static GMemChunk *ssh_this_data=NULL;
98 static GMemChunk *ssh_global_data = NULL;
100 static int proto_ssh = -1;
101 static int hf_ssh_packet_length= -1;
102 static int hf_ssh_padding_length= -1;
103 static int hf_ssh_payload= -1;
104 static int hf_ssh_protocol= -1;
105 static int hf_ssh_encrypted_packet= -1;
106 static int hf_ssh_padding_string= -1;
107 static int hf_ssh_mac_string= -1;
108 static int hf_ssh_msg_code = -1;
109 static int hf_ssh_cookie = -1;
110 static int hf_ssh_kex_algorithms = -1;
111 static int hf_ssh_server_host_key_algorithms = -1;
112 static int hf_ssh_encryption_algorithms_client_to_server = -1;
113 static int hf_ssh_encryption_algorithms_server_to_client = -1;
114 static int hf_ssh_mac_algorithms_client_to_server=-1;
115 static int hf_ssh_mac_algorithms_server_to_client=-1;
116 static int hf_ssh_compression_algorithms_client_to_server=-1;
117 static int hf_ssh_compression_algorithms_server_to_client=-1;
118 static int hf_ssh_languages_client_to_server=-1;
119 static int hf_ssh_languages_server_to_client=-1;
120 static int hf_ssh_kex_algorithms_length= -1;
121 static int hf_ssh_server_host_key_algorithms_length= -1;
122 static int hf_ssh_encryption_algorithms_client_to_server_length= -1;
123 static int hf_ssh_encryption_algorithms_server_to_client_length= -1;
124 static int hf_ssh_mac_algorithms_client_to_server_length= -1;
125 static int hf_ssh_mac_algorithms_server_to_client_length= -1;
126 static int hf_ssh_compression_algorithms_client_to_server_length= -1;
127 static int hf_ssh_compression_algorithms_server_to_client_length= -1;
128 static int hf_ssh_languages_client_to_server_length= -1;
129 static int hf_ssh_languages_server_to_client_length= -1;
131 static gint ett_ssh = -1;
132 static gint ett_key_exchange= -1;
133 static gint ett_key_init= -1;
134 static gint ett_ssh1= -1;
135 static gint ett_ssh2= -1;
137 static gboolean ssh_desegment = TRUE;
139 #define TCP_PORT_SSH 22
141 static const value_string ssh2_msg_vals[] = {
142 {SSH2_MSG_DISCONNECT, "Disconnect"},
143 {SSH2_MSG_IGNORE, "Ignore"},
144 {SSH2_MSG_UNIMPLEMENTED, "Unimplemented"},
145 {SSH2_MSG_DEBUG, "Debug"} ,
146 {SSH2_MSG_SERVICE_REQUEST,"Service Request"},
147 {SSH2_MSG_SERVICE_ACCEPT,"Service Accept"},
148 {SSH2_MSG_KEXINIT, "Key Exchange"},
149 {SSH2_MSG_NEWKEYS,"New Keys"},
150 {SSH2_MSG_KEXDH_INIT, "Key Init"},
151 {SSH2_MSG_KEXDH_REPLY,"Key Reply"},
152 {SSH2_MSG_KEX_DH_GEX_INIT,"Diffie-Hellman GEX Init"},
153 {SSH2_MSG_KEX_DH_GEX_REPLY,"Diffie-Hellman GEX Reply"},
154 {SSH2_MSG_KEX_DH_GEX_REQUEST,"Diffie-Hellman GEX Request"},
158 static const value_string ssh1_msg_vals[] = {
159 {SSH_MSG_NONE,"No Message"},
160 {SSH_MSG_DISCONNECT, "Disconnect"},
161 {SSH_SMSG_PUBLIC_KEY,"Public Key"},
162 {SSH_CMSG_SESSION_KEY,"Session Key"},
163 {SSH_CMSG_USER,"User"},
167 static const value_string ssh_opcode_vals[] = {
171 static int ssh_dissect_key_init(tvbuff_t *tvb, int offset, proto_tree *tree);
173 static int ssh_dissect_ssh1(tvbuff_t *tvb, packet_info *pinfo,
174 int offset, proto_tree *tree,int is_response,
175 int number, gboolean *need_desegmentation);
176 static int ssh_dissect_ssh2(tvbuff_t *tvb, packet_info *pinfo,
177 int offset, proto_tree *tree,int is_response,
178 int number, gboolean *need_desegmentation );
179 static int ssh_dissect_key_exchange(tvbuff_t *tvb, packet_info *pinfo,
180 int offset, proto_tree *tree,int is_response,
181 int number, gboolean *need_desegmentation );
182 static int ssh_dissect_protocol(tvbuff_t *tvb, packet_info *pinfo,
183 int offset, proto_tree *tree,int is_response,int *version,
184 gboolean *need_desegmentation);
185 static int ssh_dissect_encrypted_packet(tvbuff_t *tvb, packet_info *pinfo,
186 int offset, proto_tree *tree,int is_response);
187 proto_item * ssh_proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
188 gint start, gint length, gboolean little_endian);
191 ssh_init_protocol(void)
194 g_mem_chunk_destroy(ssh_global_data);
196 g_mem_chunk_destroy(ssh_this_data);
198 ssh_global_data = g_mem_chunk_new("ssh_global_datas",
199 sizeof(struct ssh_flow_data),
200 100* sizeof(struct ssh_flow_data), G_ALLOC_AND_FREE);
201 ssh_this_data = g_mem_chunk_new("ssh_pku_data",
202 sizeof(struct ssh_pdu_data),
203 100* sizeof(struct ssh_pdu_data), G_ALLOC_AND_FREE);
208 dissect_ssh(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
211 proto_tree *ssh_tree = NULL;
213 conversation_t *conversation=NULL;
216 guint this_number,number;
220 gboolean is_response;
222 gboolean need_desegmentation;
225 struct ssh_pdu_data *this_data=NULL;
226 struct ssh_flow_data *global_data=NULL;
229 this_data = p_get_proto_data(pinfo->fd, proto_ssh);
231 conversation = find_conversation(&pinfo->src, &pinfo->dst, pinfo->ptype,
232 pinfo->srcport, pinfo->destport, 0);
235 /* create a new conversation */
236 conversation = conversation_new(&pinfo->src, &pinfo->dst, pinfo->ptype,
237 pinfo->srcport, pinfo->destport, 0);
240 global_data = conversation_get_proto_data(conversation,proto_ssh);
242 global_data = g_mem_chunk_alloc(ssh_global_data);
243 global_data->req_counter=0;
244 global_data->rsp_counter=0;
245 global_data->version=SSH_VERSION_UNKNOWN;
246 conversation_add_proto_data(conversation,proto_ssh,global_data);
250 * end of attaching data
252 if (pinfo->destport == pinfo->match_port) {
255 this_data = g_mem_chunk_alloc(ssh_this_data);
256 this_data->counter = global_data->req_counter++;
257 p_add_proto_data(pinfo->fd, proto_ssh, this_data);
263 this_data = g_mem_chunk_alloc(ssh_global_data);
264 this_data->counter = global_data->rsp_counter++;
265 p_add_proto_data(pinfo->fd, proto_ssh, this_data);
270 ti = proto_tree_add_item(tree, proto_ssh, tvb, offset, -1, FALSE);
271 ssh_tree = proto_item_add_subtree(ti, ett_ssh);
275 version = global_data->version;
277 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
279 case SSH_VERSION_UNKNOWN:
280 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSH");
283 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSHv1");
286 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSHv2");
292 if(this_data->counter != 0 && version == SSH_VERSION_UNKNOWN) {
293 offset = ssh_dissect_encrypted_packet(tvb, pinfo,
294 offset,ssh_tree,is_response);
298 while((remain_length = tvb_reported_length_remaining(tvb,offset))> 0 ) {
299 need_desegmentation = FALSE;
300 last_offset = offset;
301 this_number = this_data->counter+number;
303 if(number > 1 && is_newdata) {
304 /* update the this_data and flow_data */
306 global_data->rsp_counter++;
308 global_data->req_counter++;
313 if(this_number == 0) {
314 offset = ssh_dissect_protocol(tvb, pinfo,
315 offset,ssh_tree, is_response,
316 &version, &need_desegmentation);
318 global_data->version= version;
321 if(version == SSH_VERSION_1) {
322 offset = ssh_dissect_ssh1(tvb, pinfo,
323 offset,ssh_tree,is_response,this_number,
324 &need_desegmentation);
325 } else if(version == SSH_VERSION_2) {
326 offset = ssh_dissect_ssh2(tvb, pinfo,
327 offset,ssh_tree,is_response,this_number,
328 &need_desegmentation);
332 if(need_desegmentation) return;
337 ssh_dissect_ssh2(tvbuff_t *tvb, packet_info *pinfo,
338 int offset, proto_tree *tree,int is_response, int this_number,
339 gboolean *need_desegmentation)
342 proto_item *ssh2_tree=NULL;
345 ti=proto_tree_add_text(tree,tvb,offset,-1,"SSH Version 2");
346 ssh2_tree = proto_item_add_subtree(ti ,ett_ssh2);
349 if((is_response && this_number > 3) || (!is_response && this_number>4)) {
350 offset = ssh_dissect_encrypted_packet(tvb, pinfo,
351 offset,ssh2_tree,is_response);
353 offset = ssh_dissect_key_exchange(tvb,pinfo,
354 offset,ssh2_tree,is_response,this_number,
355 need_desegmentation);
361 ssh_dissect_ssh1(tvbuff_t *tvb, packet_info *pinfo,
362 int offset, proto_tree *tree,int is_response,
363 int number, gboolean *need_desegmentation)
365 guint plen, padding_length,len;
367 guint remain_length=0;
370 proto_item *ssh1_tree =NULL;
373 ti=proto_tree_add_text(tree,tvb,offset,-1,"SSH Version 1");
374 ssh1_tree = proto_item_add_subtree(ti ,ett_ssh1);
377 remain_length = tvb_reported_length_remaining(tvb,offset);
378 if (ssh_desegment && pinfo->can_desegment) {
379 if(remain_length < 4) {
380 pinfo->desegment_offset = offset;
381 pinfo->desegment_len = 4-remain_length;
382 *need_desegmentation = TRUE;
386 plen = tvb_get_ntohl(tvb, offset) ;
387 padding_length = 8 - plen%8;
390 if (ssh_desegment && pinfo->can_desegment) {
391 if(plen+4+padding_length > remain_length ) {
392 pinfo->desegment_offset = offset;
393 pinfo->desegment_len = plen+padding_length - remain_length;
394 *need_desegmentation = TRUE;
399 if (check_col(pinfo->cinfo, COL_INFO)) {
400 col_add_fstr(pinfo->cinfo, COL_INFO, "%s: ",
401 is_response?"Server":"Client");
405 if (ssh1_tree && plen > 0) {
406 proto_tree_add_uint_format(ssh1_tree, hf_ssh_packet_length, tvb,
407 offset, 4, plen,"Overly large length %x",plen);
409 plen = remain_length-4-padding_length;
411 if (ssh1_tree && plen > 0) {
412 proto_tree_add_uint(ssh1_tree, hf_ssh_packet_length, tvb,
420 proto_tree_add_uint(ssh1_tree, hf_ssh_padding_length, tvb,
421 offset, padding_length, padding_length);
423 offset += padding_length;
426 tf=proto_tree_add_text(tree,tvb,offset,-1,"SSH Version 1");
427 ssh1_tree = proto_item_add_subtree(tf ,ett_ssh1);
432 msg_code = tvb_get_guint8(tvb, offset);
434 proto_tree_add_uint_format(ssh1_tree, hf_ssh_msg_code, tvb,
435 offset, 1, msg_code,"Msg code: %s (%u)",
436 val_to_str(msg_code, ssh1_msg_vals, "Unknown (%u)"),
439 if (check_col(pinfo->cinfo, COL_INFO)) {
440 col_append_fstr(pinfo->cinfo, COL_INFO, "%s",
441 val_to_str(msg_code, ssh1_msg_vals, "Unknown (%u)"));
447 if (check_col(pinfo->cinfo, COL_INFO)) {
448 col_append_fstr(pinfo->cinfo, COL_INFO, "Encrypted packet len=%d", len);
453 ssh_proto_tree_add_item(ssh1_tree, hf_ssh_payload,
454 tvb, offset, len, FALSE);
462 ssh_dissect_key_exchange(tvbuff_t *tvb, packet_info *pinfo,
463 int offset, proto_tree *tree,int is_response,int number,
464 gboolean *need_desegmentation)
467 guint8 padding_length;
468 guint remain_length=0;
469 guint last_offset=offset;
473 proto_item *key_ex_tree =NULL;
475 remain_length = tvb_reported_length_remaining(tvb,offset);
476 if (ssh_desegment && pinfo->can_desegment) {
477 if(remain_length < 4) {
478 pinfo->desegment_offset = offset;
479 pinfo->desegment_len = 4-remain_length;
480 *need_desegmentation = TRUE;
484 plen = tvb_get_ntohl(tvb, offset) ;
486 if (ssh_desegment && pinfo->can_desegment) {
487 if(plen +4 > remain_length ) {
488 pinfo->desegment_offset = offset;
489 pinfo->desegment_len = plen+4 - remain_length;
490 *need_desegmentation = TRUE;
495 * Need to check plen > 0x80000000 here
498 if (check_col(pinfo->cinfo, COL_INFO)) {
499 col_add_fstr(pinfo->cinfo, COL_INFO, "%s: ",
500 is_response?"Server":"Client");
505 proto_tree_add_uint_format(tree, hf_ssh_packet_length, tvb,
506 offset, 4, plen,"Overly large number 0x%x",plen);
508 plen = remain_length-4;
511 proto_tree_add_uint(tree, hf_ssh_packet_length, tvb,
517 padding_length = tvb_get_guint8(tvb, offset);
519 proto_tree_add_uint(tree, hf_ssh_padding_length, tvb,
520 offset, 1, padding_length);
525 tf=proto_tree_add_text(tree,tvb,offset,-1,"Key Exchange");
526 key_ex_tree = proto_item_add_subtree(tf ,ett_key_exchange);
529 msg_code = tvb_get_guint8(tvb, offset);
531 proto_tree_add_uint_format(key_ex_tree, hf_ssh_msg_code, tvb,
532 offset, 1, msg_code,"Msg code: %s (%u)",
533 val_to_str(msg_code, ssh2_msg_vals, "Unknown (%u)"),
537 if (check_col(pinfo->cinfo, COL_INFO)) {
538 col_append_fstr(pinfo->cinfo, COL_INFO, "%s",
539 val_to_str(msg_code, ssh2_msg_vals, "Unknown (%u)"));
543 /* 16 bytes cookie */
545 offset = ssh_dissect_key_init(tvb, offset,key_ex_tree);
548 len = plen+4-padding_length-(offset-last_offset);
550 ssh_proto_tree_add_item(key_ex_tree, hf_ssh_payload,
551 tvb, offset, len, FALSE);
557 ssh_proto_tree_add_item(key_ex_tree, hf_ssh_padding_string,
558 tvb, offset, padding_length, FALSE);
560 offset+= padding_length;
562 /* MAC , if there is still bytes, treat it as 16bytes MAC*/
563 if(msg_code == SSH2_MSG_KEX_DH_GEX_REPLY) {
564 len = tvb_reported_length_remaining(tvb,offset);
567 proto_tree_add_item(key_ex_tree, hf_ssh_mac_string,
568 tvb, offset, len , FALSE);
577 ssh_dissect_encrypted_packet(tvbuff_t *tvb, packet_info *pinfo,
578 int offset, proto_tree *tree,int is_response)
582 len = tvb_reported_length_remaining(tvb,offset);
583 if (check_col(pinfo->cinfo, COL_INFO)) {
584 col_add_fstr(pinfo->cinfo, COL_INFO, "Encrypted %s packet len=%d",
585 is_response?"response":"request",len);
588 ssh_proto_tree_add_item(tree, hf_ssh_encrypted_packet,
589 tvb, offset, len, FALSE);
596 ssh_dissect_protocol(tvbuff_t *tvb, packet_info *pinfo,
597 int offset, proto_tree *tree, int is_response, int * version,
598 gboolean *need_desegmentation)
604 * If the first packet do not contain the banner,
605 * it is dump in the middle of a flow or not a ssh at all
607 if(tvb_strncaseeql(tvb,offset,"SSH-",4) != 0 ) {
608 offset = ssh_dissect_encrypted_packet(tvb, pinfo,
609 offset,tree,is_response);
614 if(tvb_strncaseeql(tvb,offset,"SSH-2.",6) == 0 ) {
615 *(version) = SSH_VERSION_2;
616 }else if(tvb_strncaseeql(tvb,offset,"SSH-1.99-",9) == 0 ) {
617 *(version) = SSH_VERSION_2;
618 }else if(tvb_strncaseeql(tvb,offset,"SSH-1.",6) == 0 ) {
619 *(version) = SSH_VERSION_1;
623 remain_length = tvb_reported_length_remaining(tvb,offset);
624 /*linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
626 linelen = tvb_find_guint8(tvb, offset, -1, '\n');
628 if (ssh_desegment && pinfo->can_desegment) {
629 if(remain_length < (guint)(linelen-offset) || linelen == -1 ) {
630 pinfo->desegment_offset = offset;
631 pinfo->desegment_len = linelen-remain_length;
632 *need_desegmentation = TRUE;
637 linelen = remain_length;
639 linelen = linelen - offset;
642 if (check_col(pinfo->cinfo, COL_INFO)) {
643 col_add_fstr(pinfo->cinfo, COL_INFO, "%s Protocol: %s",
644 is_response?"Server":"Client",
645 tvb_format_text(tvb,offset,linelen));
648 ssh_proto_tree_add_item(tree, hf_ssh_protocol,
649 tvb, offset, linelen+1, FALSE);
656 ssh_dissect_key_init(tvbuff_t *tvb, int offset, proto_tree *tree )
661 proto_item *key_init_tree=NULL;
665 tf=proto_tree_add_text(tree,tvb,offset,-1,"Keys");
666 key_init_tree = proto_item_add_subtree(tf ,ett_key_init);
669 proto_tree_add_item(key_init_tree, hf_ssh_cookie,
670 tvb, offset, 16, FALSE);
675 len = tvb_get_ntohl(tvb, offset) ;
677 proto_tree_add_uint(key_init_tree,
678 hf_ssh_kex_algorithms_length ,tvb,offset,4, len);
681 if (key_init_tree ) {
682 ssh_proto_tree_add_item(key_init_tree, hf_ssh_kex_algorithms,
683 tvb, offset, len , FALSE);
687 /* server_host_key_algorithms */
688 len = tvb_get_ntohl(tvb, offset) ;
690 proto_tree_add_uint(key_init_tree,
691 hf_ssh_server_host_key_algorithms_length ,tvb,offset,4, len);
695 ssh_proto_tree_add_item(key_init_tree, hf_ssh_server_host_key_algorithms,
696 tvb, offset, len , FALSE);
700 /* encryption_algorithms_client_to_server */
701 len = tvb_get_ntohl(tvb, offset) ;
703 proto_tree_add_uint(key_init_tree,
704 hf_ssh_encryption_algorithms_client_to_server_length ,tvb,offset,4, len);
707 if (key_init_tree ) {
708 ssh_proto_tree_add_item(key_init_tree, hf_ssh_encryption_algorithms_client_to_server,
709 tvb, offset, len , FALSE);
712 /* encryption_algorithms_server_to_client */
713 len = tvb_get_ntohl(tvb, offset) ;
715 proto_tree_add_uint(key_init_tree,
716 hf_ssh_encryption_algorithms_server_to_client_length ,tvb,offset,4, len);
719 if (key_init_tree ) {
720 ssh_proto_tree_add_item(key_init_tree, hf_ssh_encryption_algorithms_server_to_client,
721 tvb, offset, len , FALSE);
725 /* mac_algorithms_client_to_server */
726 len = tvb_get_ntohl(tvb, offset) ;
728 proto_tree_add_uint(key_init_tree,
729 hf_ssh_mac_algorithms_client_to_server_length ,tvb,offset,4, len);
732 if (key_init_tree ) {
733 ssh_proto_tree_add_item(key_init_tree, hf_ssh_mac_algorithms_client_to_server,
734 tvb, offset, len , FALSE);
738 /* mac_algorithms_server_to_client */
739 len = tvb_get_ntohl(tvb, offset) ;
741 proto_tree_add_uint(key_init_tree,
742 hf_ssh_mac_algorithms_server_to_client_length ,tvb,offset,4, len);
745 if (key_init_tree ) {
746 ssh_proto_tree_add_item(key_init_tree, hf_ssh_mac_algorithms_server_to_client,
747 tvb, offset, len , FALSE);
751 /* compression_algorithms_client_to_server */
752 len = tvb_get_ntohl(tvb, offset) ;
754 proto_tree_add_uint(key_init_tree,
755 hf_ssh_compression_algorithms_client_to_server_length ,tvb,offset,4, len);
758 if (key_init_tree ) {
759 ssh_proto_tree_add_item(key_init_tree, hf_ssh_compression_algorithms_client_to_server,
760 tvb, offset, len , FALSE);
764 /* compression_algorithms_server_to_client */
765 len = tvb_get_ntohl(tvb, offset) ;
767 proto_tree_add_uint(key_init_tree,
768 hf_ssh_compression_algorithms_server_to_client_length ,tvb,offset,4, len);
771 if (key_init_tree ) {
772 ssh_proto_tree_add_item(key_init_tree, hf_ssh_compression_algorithms_server_to_client,
773 tvb, offset, len , FALSE);
777 /* languages_client_to_server */
778 len = tvb_get_ntohl(tvb, offset) ;
780 proto_tree_add_uint(key_init_tree,
781 hf_ssh_languages_client_to_server_length ,tvb,offset,4, len);
784 if (key_init_tree ) {
785 ssh_proto_tree_add_item(key_init_tree, hf_ssh_languages_client_to_server,
786 tvb, offset, len , FALSE);
790 /* languages_server_to_client */
791 len = tvb_get_ntohl(tvb, offset) ;
793 proto_tree_add_uint(key_init_tree,
794 hf_ssh_languages_server_to_client_length ,tvb,offset,4, len);
798 ssh_proto_tree_add_item(key_init_tree, hf_ssh_languages_server_to_client,
799 tvb, offset, len , FALSE);
806 ssh_proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
807 gint start, gint length, gboolean little_endian)
809 if (tree && length <0xffff && length > 0) {
810 return proto_tree_add_item(tree, hfindex, tvb, start, length,little_endian);
816 proto_register_ssh(void)
818 static hf_register_info hf[] = {
819 { &hf_ssh_packet_length,
820 { "Packet Length", "ssh.packet_length",
821 FT_UINT32, BASE_DEC, NULL, 0x0,
822 "SSH packet length", HFILL }},
824 { &hf_ssh_padding_length,
825 { "Padding Length", "ssh.padding_length",
826 FT_UINT8, BASE_DEC, NULL, 0x0,
827 "SSH Packet Number", HFILL }},
830 { "Message Code", "ssh.message_code",
831 FT_UINT8, BASE_DEC, NULL, 0x0,
832 "SSH Message Code", HFILL }},
835 { "Cookie", "ssh.cookie",
836 FT_STRING, BASE_NONE, NULL, 0x0,
837 "SSH Cookie", HFILL }},
840 { &hf_ssh_encrypted_packet,
841 { "Encrypted Packet", "ssh.encrypted_packet",
842 FT_BYTES, BASE_NONE, NULL, 0x0,
843 "SSH Protocol Packet", HFILL }},
846 { "Protocol", "ssh.protocol",
847 FT_STRING, BASE_NONE, NULL, 0x0,
848 "SSH Protocol", HFILL }},
851 { "Payload", "ssh.payload",
852 FT_BYTES, BASE_NONE, NULL, 0x0,
853 "SSH Payload", HFILL }},
855 { &hf_ssh_padding_string,
856 { "Padding String", "ssh.padding_string",
857 FT_STRING, BASE_NONE, NULL, 0x0,
858 "SSH Padding String", HFILL }},
860 { &hf_ssh_mac_string,
861 { "MAC String", "ssh.mac_string",
862 FT_STRING, BASE_NONE, NULL, 0x0,
863 "SSH MAC String", HFILL }},
865 { &hf_ssh_kex_algorithms,
866 { "kex_algorithms string", "ssh.kex_algorithms",
867 FT_STRINGZ, BASE_NONE, NULL, 0x0,
868 "SSH kex_algorithms string", HFILL }},
870 { &hf_ssh_server_host_key_algorithms,
871 { "server_host_key_algorithms string", "ssh.server_host_key_algorithms",
872 FT_STRINGZ, BASE_NONE, NULL, 0x0,
873 "SSH server_host_key_algorithms string", HFILL }},
875 { &hf_ssh_encryption_algorithms_client_to_server,
876 { "encryption_algorithms_client_to_server string", "ssh.encryption_algorithms_client_to_server",
877 FT_STRINGZ, BASE_NONE, NULL, 0x0,
878 "SSH encryption_algorithms_client_to_server string", HFILL }},
880 { &hf_ssh_encryption_algorithms_server_to_client,
881 { "encryption_algorithms_server_to_client string", "ssh.encryption_algorithms_server_to_client",
882 FT_STRINGZ, BASE_NONE, NULL, 0x0,
883 "SSH encryption_algorithms_server_to_client string", HFILL }},
885 { &hf_ssh_mac_algorithms_client_to_server,
886 { "mac_algorithms_client_to_server string", "ssh.mac_algorithms_client_to_server",
887 FT_STRINGZ, BASE_NONE, NULL, 0x0,
888 "SSH mac_algorithms_client_to_server string", HFILL }},
890 { &hf_ssh_mac_algorithms_server_to_client,
891 { "mac_algorithms_server_to_client string", "ssh.mac_algorithms_server_to_client",
892 FT_STRINGZ, BASE_NONE, NULL, 0x0,
893 "SSH mac_algorithms_server_to_client string", HFILL }},
895 { &hf_ssh_compression_algorithms_client_to_server,
896 { "compression_algorithms_client_to_server string", "ssh.compression_algorithms_client_to_server",
897 FT_STRINGZ, BASE_NONE, NULL, 0x0,
898 "SSH compression_algorithms_client_to_server string", HFILL }},
900 { &hf_ssh_compression_algorithms_server_to_client,
901 { "compression_algorithms_server_to_client string", "ssh.compression_algorithms_server_to_client",
902 FT_STRINGZ, BASE_NONE, NULL, 0x0,
903 "SSH compression_algorithms_server_to_client string", HFILL }},
905 { &hf_ssh_languages_client_to_server,
906 { "languages_client_to_server string", "ssh.languages_client_to_server",
907 FT_STRINGZ, BASE_NONE, NULL, 0x0,
908 "SSH languages_client_to_server string", HFILL }},
910 { &hf_ssh_languages_server_to_client,
911 { "languages_server_to_client string", "ssh.languages_server_to_client",
912 FT_STRINGZ, BASE_NONE, NULL, 0x0,
913 "SSH languages_server_to_client string", HFILL }},
915 { &hf_ssh_kex_algorithms_length,
916 { "kex_algorithms length", "ssh.kex_algorithms_length",
917 FT_UINT32, BASE_DEC, NULL, 0x0,
918 "SSH kex_algorithms length", HFILL }},
920 { &hf_ssh_server_host_key_algorithms_length,
921 { "server_host_key_algorithms length", "ssh.server_host_key_algorithms_length",
922 FT_UINT32, BASE_DEC, NULL, 0x0,
923 "SSH server_host_key_algorithms length", HFILL }},
925 { &hf_ssh_encryption_algorithms_client_to_server_length,
926 { "encryption_algorithms_client_to_server length", "ssh.encryption_algorithms_client_to_server_length",
927 FT_UINT32, BASE_DEC, NULL, 0x0,
928 "SSH encryption_algorithms_client_to_server length", HFILL }},
930 { &hf_ssh_encryption_algorithms_server_to_client_length,
931 { "encryption_algorithms_server_to_client length", "ssh.encryption_algorithms_server_to_client_length",
932 FT_UINT32, BASE_DEC, NULL, 0x0,
933 "SSH encryption_algorithms_server_to_client length", HFILL }},
935 { &hf_ssh_mac_algorithms_client_to_server_length,
936 { "mac_algorithms_client_to_server length", "ssh.mac_algorithms_client_to_server_length",
937 FT_UINT32, BASE_DEC, NULL, 0x0,
938 "SSH mac_algorithms_client_to_server length", HFILL }},
940 { &hf_ssh_mac_algorithms_server_to_client_length,
941 { "mac_algorithms_server_to_client length", "ssh.mac_algorithms_server_to_client_length",
942 FT_UINT32, BASE_DEC, NULL, 0x0,
943 "SSH mac_algorithms_server_to_client length", HFILL }},
945 { &hf_ssh_compression_algorithms_client_to_server_length,
946 { "compression_algorithms_client_to_server length", "ssh.compression_algorithms_client_to_server_length",
947 FT_UINT32, BASE_DEC, NULL, 0x0,
948 "SSH compression_algorithms_client_to_server length", HFILL }},
950 { &hf_ssh_compression_algorithms_server_to_client_length,
951 { "compression_algorithms_server_to_client length", "ssh.compression_algorithms_server_to_client_length",
952 FT_UINT32, BASE_DEC, NULL, 0x0,
953 "SSH compression_algorithms_server_to_client length", HFILL }},
955 { &hf_ssh_languages_client_to_server_length,
956 { "languages_client_to_server length", "ssh.languages_client_to_server_length",
957 FT_UINT32, BASE_DEC, NULL, 0x0,
958 "SSH languages_client_to_server length", HFILL }},
960 { &hf_ssh_languages_server_to_client_length,
961 { "languages_server_to_client length", "ssh.languages_server_to_client_length",
962 FT_UINT32, BASE_DEC, NULL, 0x0,
963 "SSH languages_server_to_client length", HFILL }},
967 static gint *ett[] = {
974 module_t *ssh_module;
976 proto_ssh = proto_register_protocol("SSH Protocol",
978 proto_register_field_array(proto_ssh, hf, array_length(hf));
979 proto_register_subtree_array(ett, array_length(ett));
980 register_init_routine(&ssh_init_protocol);
982 ssh_module = prefs_register_protocol(proto_ssh, NULL);
983 prefs_register_bool_preference(ssh_module, "desegment_buffers",
984 "Desegment all SSH buffers spanning multiple TCP segments",
985 "Whether the SSH dissector should desegment all SSH buffers spanning multiple TCP segments",
990 proto_reg_handoff_ssh(void)
992 dissector_handle_t ssh_handle;
994 ssh_handle = create_dissector_handle(dissect_ssh, proto_ssh);
996 dissector_add("tcp.port", TCP_PORT_SSH, ssh_handle);