2 * Routines for ssh packet dissection
4 * Huagang XIE <huagang@intruvert.com>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
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>
40 #include <epan/emem.h>
42 #include "packet-tcp.h"
43 #include <epan/reassemble.h>
44 #include <epan/prefs.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 {
98 static int proto_ssh = -1;
99 static int hf_ssh_packet_length= -1;
100 static int hf_ssh_padding_length= -1;
101 static int hf_ssh_payload= -1;
102 static int hf_ssh_protocol= -1;
103 static int hf_ssh_encrypted_packet= -1;
104 static int hf_ssh_padding_string= -1;
105 static int hf_ssh_mac_string= -1;
106 static int hf_ssh_msg_code = -1;
107 static int hf_ssh_cookie = -1;
108 static int hf_ssh_kex_algorithms = -1;
109 static int hf_ssh_server_host_key_algorithms = -1;
110 static int hf_ssh_encryption_algorithms_client_to_server = -1;
111 static int hf_ssh_encryption_algorithms_server_to_client = -1;
112 static int hf_ssh_mac_algorithms_client_to_server=-1;
113 static int hf_ssh_mac_algorithms_server_to_client=-1;
114 static int hf_ssh_compression_algorithms_client_to_server=-1;
115 static int hf_ssh_compression_algorithms_server_to_client=-1;
116 static int hf_ssh_languages_client_to_server=-1;
117 static int hf_ssh_languages_server_to_client=-1;
118 static int hf_ssh_kex_algorithms_length= -1;
119 static int hf_ssh_server_host_key_algorithms_length= -1;
120 static int hf_ssh_encryption_algorithms_client_to_server_length= -1;
121 static int hf_ssh_encryption_algorithms_server_to_client_length= -1;
122 static int hf_ssh_mac_algorithms_client_to_server_length= -1;
123 static int hf_ssh_mac_algorithms_server_to_client_length= -1;
124 static int hf_ssh_compression_algorithms_client_to_server_length= -1;
125 static int hf_ssh_compression_algorithms_server_to_client_length= -1;
126 static int hf_ssh_languages_client_to_server_length= -1;
127 static int hf_ssh_languages_server_to_client_length= -1;
129 static gint ett_ssh = -1;
130 static gint ett_key_exchange= -1;
131 static gint ett_key_init= -1;
132 static gint ett_ssh1= -1;
133 static gint ett_ssh2= -1;
135 static gboolean ssh_desegment = TRUE;
137 #define TCP_PORT_SSH 22
139 static const value_string ssh2_msg_vals[] = {
140 {SSH2_MSG_DISCONNECT, "Disconnect"},
141 {SSH2_MSG_IGNORE, "Ignore"},
142 {SSH2_MSG_UNIMPLEMENTED, "Unimplemented"},
143 {SSH2_MSG_DEBUG, "Debug"},
144 {SSH2_MSG_SERVICE_REQUEST, "Service Request"},
145 {SSH2_MSG_SERVICE_ACCEPT, "Service Accept"},
146 {SSH2_MSG_KEXINIT, "Key Exchange Init"},
147 {SSH2_MSG_NEWKEYS, "New Keys"},
148 {SSH2_MSG_KEXDH_INIT, "Diffie-Hellman Key Exchange Init"},
149 {SSH2_MSG_KEXDH_REPLY, "Diffie-Hellman Key Exchange Reply"},
150 {SSH2_MSG_KEX_DH_GEX_INIT, "Diffie-Hellman GEX Init"},
151 {SSH2_MSG_KEX_DH_GEX_REPLY, "Diffie-Hellman GEX Reply"},
152 {SSH2_MSG_KEX_DH_GEX_REQUEST, "Diffie-Hellman GEX Request"},
156 static const value_string ssh1_msg_vals[] = {
157 {SSH_MSG_NONE,"No Message"},
158 {SSH_MSG_DISCONNECT, "Disconnect"},
159 {SSH_SMSG_PUBLIC_KEY,"Public Key"},
160 {SSH_CMSG_SESSION_KEY,"Session Key"},
161 {SSH_CMSG_USER,"User"},
166 static const value_string ssh_opcode_vals[] = {
170 static int ssh_dissect_key_init(tvbuff_t *tvb, int offset, proto_tree *tree);
172 static int ssh_dissect_ssh1(tvbuff_t *tvb, packet_info *pinfo,
173 int offset, proto_tree *tree,int is_response,
174 int number, gboolean *need_desegmentation);
175 static int ssh_dissect_ssh2(tvbuff_t *tvb, packet_info *pinfo,
176 int offset, proto_tree *tree,int is_response,
177 int number, gboolean *need_desegmentation );
178 static int ssh_dissect_key_exchange(tvbuff_t *tvb, packet_info *pinfo,
179 int offset, proto_tree *tree,int is_response,
180 int number, gboolean *need_desegmentation );
181 static int ssh_dissect_protocol(tvbuff_t *tvb, packet_info *pinfo,
182 int offset, proto_tree *tree,int is_response,int *version,
183 gboolean *need_desegmentation);
184 static int ssh_dissect_encrypted_packet(tvbuff_t *tvb, packet_info *pinfo,
185 int offset, proto_tree *tree,int is_response);
186 proto_item * ssh_proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
187 gint start, gint length, gboolean little_endian);
191 dissect_ssh(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
194 proto_tree *ssh_tree = NULL;
196 conversation_t *conversation=NULL;
199 guint this_number,number;
203 gboolean is_response;
205 gboolean need_desegmentation;
208 struct ssh_pdu_data *this_data=NULL;
209 struct ssh_flow_data *global_data=NULL;
212 this_data = p_get_proto_data(pinfo->fd, proto_ssh);
214 conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
215 pinfo->srcport, pinfo->destport, 0);
218 /* create a new conversation */
219 conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
220 pinfo->srcport, pinfo->destport, 0);
223 global_data = conversation_get_proto_data(conversation,proto_ssh);
225 global_data = se_alloc(sizeof(struct ssh_flow_data));
226 global_data->req_counter=0;
227 global_data->rsp_counter=0;
228 global_data->version=SSH_VERSION_UNKNOWN;
229 conversation_add_proto_data(conversation,proto_ssh,global_data);
233 * end of attaching data
235 if (pinfo->destport == pinfo->match_port) {
238 this_data = se_alloc(sizeof(struct ssh_pdu_data));
239 this_data->counter = global_data->req_counter++;
240 p_add_proto_data(pinfo->fd, proto_ssh, this_data);
246 this_data = se_alloc(sizeof(struct ssh_flow_data));
247 this_data->counter = global_data->rsp_counter++;
248 p_add_proto_data(pinfo->fd, proto_ssh, this_data);
253 ti = proto_tree_add_item(tree, proto_ssh, tvb, offset, -1, FALSE);
254 ssh_tree = proto_item_add_subtree(ti, ett_ssh);
258 version = global_data->version;
260 if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
262 case SSH_VERSION_UNKNOWN:
263 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSH");
266 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSHv1");
269 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSHv2");
275 if(this_data->counter != 0 && version == SSH_VERSION_UNKNOWN) {
276 offset = ssh_dissect_encrypted_packet(tvb, pinfo,
277 offset,ssh_tree,is_response);
281 while((remain_length = tvb_reported_length_remaining(tvb,offset))> 0 ) {
282 need_desegmentation = FALSE;
283 last_offset = offset;
284 this_number = this_data->counter+number;
286 if(number > 1 && is_newdata) {
287 /* update the this_data and flow_data */
289 global_data->rsp_counter++;
291 global_data->req_counter++;
296 if(this_number == 0) {
297 offset = ssh_dissect_protocol(tvb, pinfo,
298 offset,ssh_tree, is_response,
299 &version, &need_desegmentation);
301 global_data->version= version;
306 case SSH_VERSION_UNKNOWN:
308 * We use "tvb_ensure_length_remaining()"
309 * to make sure there actually *is* data
312 * This means we're guaranteed that
313 * "remain_length" is positive.
315 remain_length = tvb_ensure_length_remaining(tvb,
317 proto_tree_add_text(ssh_tree, tvb, offset,
319 "Unknown SSH version data");
320 offset += remain_length;
324 offset = ssh_dissect_ssh1(tvb, pinfo,
325 offset,ssh_tree,is_response,this_number,
326 &need_desegmentation);
330 offset = ssh_dissect_ssh2(tvb, pinfo,
331 offset,ssh_tree,is_response,this_number,
332 &need_desegmentation);
337 if(offset <= last_offset)
338 THROW(ReportedBoundsError);
339 if(need_desegmentation) return;
344 ssh_dissect_ssh2(tvbuff_t *tvb, packet_info *pinfo,
345 int offset, proto_tree *tree,int is_response, int this_number,
346 gboolean *need_desegmentation)
349 proto_item *ssh2_tree=NULL;
352 ti=proto_tree_add_text(tree,tvb,offset,-1,"SSH Version 2");
353 ssh2_tree = proto_item_add_subtree(ti ,ett_ssh2);
356 if((is_response && this_number > 3) || (!is_response && this_number>4)) {
357 offset = ssh_dissect_encrypted_packet(tvb, pinfo,
358 offset,ssh2_tree,is_response);
360 offset = ssh_dissect_key_exchange(tvb,pinfo,
361 offset,ssh2_tree,is_response,this_number,
362 need_desegmentation);
368 ssh_dissect_ssh1(tvbuff_t *tvb, packet_info *pinfo,
369 int offset, proto_tree *tree,int is_response,
370 int number, gboolean *need_desegmentation)
372 guint plen, padding_length,len;
377 proto_item *ssh1_tree =NULL;
380 ti=proto_tree_add_text(tree,tvb,offset,-1,"SSH Version 1");
381 ssh1_tree = proto_item_add_subtree(ti ,ett_ssh1);
385 * We use "tvb_ensure_length_remaining()" to make sure there
386 * actually *is* data remaining.
388 * This means we're guaranteed that "remain_length" is positive.
390 remain_length = tvb_ensure_length_remaining(tvb,offset);
391 if (ssh_desegment && pinfo->can_desegment) {
392 if(remain_length < 4) {
393 pinfo->desegment_offset = offset;
394 pinfo->desegment_len = 4-remain_length;
395 *need_desegmentation = TRUE;
399 plen = tvb_get_ntohl(tvb, offset) ;
400 padding_length = 8 - plen%8;
403 if (ssh_desegment && pinfo->can_desegment) {
404 if(plen+4+padding_length > remain_length ) {
405 pinfo->desegment_offset = offset;
406 pinfo->desegment_len = plen+padding_length - remain_length;
407 *need_desegmentation = TRUE;
412 if (check_col(pinfo->cinfo, COL_INFO)) {
413 col_add_fstr(pinfo->cinfo, COL_INFO, "%s: ",
414 is_response?"Server":"Client");
418 if (ssh1_tree && plen > 0) {
419 proto_tree_add_uint_format(ssh1_tree, hf_ssh_packet_length, tvb,
420 offset, 4, plen,"Overly large length %x",plen);
422 plen = remain_length-4-padding_length;
424 if (ssh1_tree && plen > 0) {
425 proto_tree_add_uint(ssh1_tree, hf_ssh_packet_length, tvb,
433 proto_tree_add_uint(ssh1_tree, hf_ssh_padding_length, tvb,
434 offset, padding_length, padding_length);
436 offset += padding_length;
439 tf=proto_tree_add_text(tree,tvb,offset,-1,"SSH Version 1");
440 ssh1_tree = proto_item_add_subtree(tf ,ett_ssh1);
445 msg_code = tvb_get_guint8(tvb, offset);
447 proto_tree_add_uint_format(ssh1_tree, hf_ssh_msg_code, tvb,
448 offset, 1, msg_code,"Msg code: %s (%u)",
449 val_to_str(msg_code, ssh1_msg_vals, "Unknown (%u)"),
452 if (check_col(pinfo->cinfo, COL_INFO)) {
453 col_append_fstr(pinfo->cinfo, COL_INFO, "%s",
454 val_to_str(msg_code, ssh1_msg_vals, "Unknown (%u)"));
460 if (check_col(pinfo->cinfo, COL_INFO)) {
461 col_append_fstr(pinfo->cinfo, COL_INFO, "Encrypted packet len=%d", len);
466 ssh_proto_tree_add_item(ssh1_tree, hf_ssh_payload,
467 tvb, offset, len, FALSE);
475 ssh_dissect_key_exchange(tvbuff_t *tvb, packet_info *pinfo,
476 int offset, proto_tree *tree,int is_response,int number,
477 gboolean *need_desegmentation)
480 guint8 padding_length;
482 int last_offset=offset;
486 proto_item *key_ex_tree =NULL;
489 * We use "tvb_ensure_length_remaining()" to make sure there
490 * actually *is* data remaining.
492 * This means we're guaranteed that "remain_length" is positive.
494 remain_length = tvb_ensure_length_remaining(tvb,offset);
495 if (ssh_desegment && pinfo->can_desegment) {
496 if(remain_length < 4) {
497 pinfo->desegment_offset = offset;
498 pinfo->desegment_len = 4-remain_length;
499 *need_desegmentation = TRUE;
503 plen = tvb_get_ntohl(tvb, offset) ;
505 if (ssh_desegment && pinfo->can_desegment) {
506 if(plen +4 > remain_length ) {
507 pinfo->desegment_offset = offset;
508 pinfo->desegment_len = plen+4 - remain_length;
509 *need_desegmentation = TRUE;
514 * Need to check plen > 0x80000000 here
517 if (check_col(pinfo->cinfo, COL_INFO)) {
518 col_add_fstr(pinfo->cinfo, COL_INFO, "%s: ",
519 is_response?"Server":"Client");
524 proto_tree_add_uint_format(tree, hf_ssh_packet_length, tvb,
525 offset, 4, plen,"Overly large number 0x%x",plen);
527 plen = remain_length-4;
530 proto_tree_add_uint(tree, hf_ssh_packet_length, tvb,
536 padding_length = tvb_get_guint8(tvb, offset);
538 proto_tree_add_uint(tree, hf_ssh_padding_length, tvb,
539 offset, 1, padding_length);
544 tf=proto_tree_add_text(tree,tvb,offset,-1,"Key Exchange");
545 key_ex_tree = proto_item_add_subtree(tf ,ett_key_exchange);
548 msg_code = tvb_get_guint8(tvb, offset);
550 proto_tree_add_uint_format(key_ex_tree, hf_ssh_msg_code, tvb,
551 offset, 1, msg_code,"Msg code: %s (%u)",
552 val_to_str(msg_code, ssh2_msg_vals, "Unknown (%u)"),
556 if (check_col(pinfo->cinfo, COL_INFO)) {
557 col_append_fstr(pinfo->cinfo, COL_INFO, "%s",
558 val_to_str(msg_code, ssh2_msg_vals, "Unknown (%u)"));
562 /* 16 bytes cookie */
564 offset = ssh_dissect_key_init(tvb, offset,key_ex_tree);
567 len = plen+4-padding_length-(offset-last_offset);
569 ssh_proto_tree_add_item(key_ex_tree, hf_ssh_payload,
570 tvb, offset, len, FALSE);
576 ssh_proto_tree_add_item(key_ex_tree, hf_ssh_padding_string,
577 tvb, offset, padding_length, FALSE);
579 offset+= padding_length;
581 /* MAC , if there is still bytes, treat it as 16bytes MAC*/
582 if(msg_code == SSH2_MSG_KEX_DH_GEX_REPLY) {
583 len = tvb_reported_length_remaining(tvb,offset);
586 proto_tree_add_item(key_ex_tree, hf_ssh_mac_string,
587 tvb, offset, len , FALSE);
596 ssh_dissect_encrypted_packet(tvbuff_t *tvb, packet_info *pinfo,
597 int offset, proto_tree *tree,int is_response)
601 len = tvb_reported_length_remaining(tvb,offset);
602 if (check_col(pinfo->cinfo, COL_INFO)) {
603 col_add_fstr(pinfo->cinfo, COL_INFO, "Encrypted %s packet len=%d",
604 is_response?"response":"request",len);
607 ssh_proto_tree_add_item(tree, hf_ssh_encrypted_packet,
608 tvb, offset, len, FALSE);
615 ssh_dissect_protocol(tvbuff_t *tvb, packet_info *pinfo,
616 int offset, proto_tree *tree, int is_response, int * version,
617 gboolean *need_desegmentation)
620 gint linelen, protolen;
623 * If the first packet do not contain the banner,
624 * it is dump in the middle of a flow or not a ssh at all
626 if(tvb_strncaseeql(tvb,offset,"SSH-",4) != 0 ) {
627 offset = ssh_dissect_encrypted_packet(tvb, pinfo,
628 offset,tree,is_response);
633 if(tvb_strncaseeql(tvb,offset,"SSH-2.",6) == 0 ) {
634 *(version) = SSH_VERSION_2;
635 }else if(tvb_strncaseeql(tvb,offset,"SSH-1.99-",9) == 0 ) {
636 *(version) = SSH_VERSION_2;
637 }else if(tvb_strncaseeql(tvb,offset,"SSH-1.",6) == 0 ) {
638 *(version) = SSH_VERSION_1;
643 * We use "tvb_ensure_length_remaining()" to make sure there
644 * actually *is* data remaining.
646 * This means we're guaranteed that "remain_length" is positive.
648 remain_length = tvb_ensure_length_remaining(tvb,offset);
649 /*linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
651 linelen = tvb_find_guint8(tvb, offset, -1, '\n');
653 if (ssh_desegment && pinfo->can_desegment) {
654 if(linelen == -1 || remain_length < (guint)linelen-offset ) {
655 pinfo->desegment_offset = offset;
656 pinfo->desegment_len = linelen-remain_length;
657 *need_desegmentation = TRUE;
662 /* XXX - reassemble across segment boundaries? */
663 linelen = remain_length;
666 linelen = linelen - offset + 1;
667 protolen = linelen - 1;
670 if (check_col(pinfo->cinfo, COL_INFO)) {
671 col_add_fstr(pinfo->cinfo, COL_INFO, "%s Protocol: %s",
672 is_response?"Server":"Client",
673 tvb_format_text(tvb,offset,protolen));
676 ssh_proto_tree_add_item(tree, hf_ssh_protocol,
677 tvb, offset, linelen, FALSE);
683 #define SSH_PROPOSAL(item)\
684 { &hf_ssh_ ## item, &hf_ssh_ ## item ## _length }
688 } ssh_proposals[] = {
689 SSH_PROPOSAL(kex_algorithms),
690 SSH_PROPOSAL(server_host_key_algorithms),
691 SSH_PROPOSAL(encryption_algorithms_client_to_server),
692 SSH_PROPOSAL(encryption_algorithms_server_to_client),
693 SSH_PROPOSAL(mac_algorithms_client_to_server),
694 SSH_PROPOSAL(mac_algorithms_server_to_client),
695 SSH_PROPOSAL(compression_algorithms_client_to_server),
696 SSH_PROPOSAL(compression_algorithms_server_to_client),
697 SSH_PROPOSAL(languages_client_to_server),
698 SSH_PROPOSAL(languages_server_to_client),
703 ssh_dissect_key_init(tvbuff_t *tvb, int offset, proto_tree *tree )
709 proto_item *key_init_tree=NULL;
712 tf=proto_tree_add_text(tree,tvb,offset,-1,"Algorithms");
713 key_init_tree = proto_item_add_subtree(tf, ett_key_init);
714 proto_tree_add_item(key_init_tree, hf_ssh_cookie,
715 tvb, offset, 16, FALSE);
719 for (i = 0; ssh_proposals[i].value; i++) {
720 len = tvb_get_ntohl(tvb, offset);
722 proto_tree_add_uint(key_init_tree,
723 *ssh_proposals[i].length, tvb, offset, 4, len);
727 ssh_proto_tree_add_item(key_init_tree,
728 *ssh_proposals[i].value, tvb, offset, len, FALSE);
735 ssh_proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
736 gint start, gint length, gboolean little_endian)
738 if (tree && length <0xffff && length > 0) {
739 return proto_tree_add_item(tree, hfindex, tvb, start, length,little_endian);
745 proto_register_ssh(void)
747 static hf_register_info hf[] = {
748 { &hf_ssh_packet_length,
749 { "Packet Length", "ssh.packet_length",
750 FT_UINT32, BASE_DEC, NULL, 0x0,
751 "SSH packet length", HFILL }},
753 { &hf_ssh_padding_length,
754 { "Padding Length", "ssh.padding_length",
755 FT_UINT8, BASE_DEC, NULL, 0x0,
756 "SSH Packet Number", HFILL }},
759 { "Message Code", "ssh.message_code",
760 FT_UINT8, BASE_DEC, NULL, 0x0,
761 "SSH Message Code", HFILL }},
764 { "Cookie", "ssh.cookie",
765 FT_BYTES, BASE_NONE, NULL, 0x0,
766 "SSH Cookie", HFILL }},
768 { &hf_ssh_encrypted_packet,
769 { "Encrypted Packet", "ssh.encrypted_packet",
770 FT_BYTES, BASE_NONE, NULL, 0x0,
771 "SSH Protocol Packet", HFILL }},
774 { "Protocol", "ssh.protocol",
775 FT_STRING, BASE_NONE, NULL, 0x0,
776 "SSH Protocol", HFILL }},
779 { "Payload", "ssh.payload",
780 FT_BYTES, BASE_NONE, NULL, 0x0,
781 "SSH Payload", HFILL }},
783 { &hf_ssh_padding_string,
784 { "Padding String", "ssh.padding_string",
785 FT_STRING, BASE_NONE, NULL, 0x0,
786 "SSH Padding String", HFILL }},
788 { &hf_ssh_mac_string,
789 { "MAC String", "ssh.mac_string",
790 FT_STRING, BASE_NONE, NULL, 0x0,
791 "SSH MAC String", HFILL }},
793 { &hf_ssh_kex_algorithms,
794 { "kex_algorithms string", "ssh.kex_algorithms",
795 FT_STRINGZ, BASE_NONE, NULL, 0x0,
796 "SSH kex_algorithms string", HFILL }},
798 { &hf_ssh_server_host_key_algorithms,
799 { "server_host_key_algorithms string", "ssh.server_host_key_algorithms",
800 FT_STRINGZ, BASE_NONE, NULL, 0x0,
801 "SSH server_host_key_algorithms string", HFILL }},
803 { &hf_ssh_encryption_algorithms_client_to_server,
804 { "encryption_algorithms_client_to_server string", "ssh.encryption_algorithms_client_to_server",
805 FT_STRINGZ, BASE_NONE, NULL, 0x0,
806 "SSH encryption_algorithms_client_to_server string", HFILL }},
808 { &hf_ssh_encryption_algorithms_server_to_client,
809 { "encryption_algorithms_server_to_client string", "ssh.encryption_algorithms_server_to_client",
810 FT_STRINGZ, BASE_NONE, NULL, 0x0,
811 "SSH encryption_algorithms_server_to_client string", HFILL }},
813 { &hf_ssh_mac_algorithms_client_to_server,
814 { "mac_algorithms_client_to_server string", "ssh.mac_algorithms_client_to_server",
815 FT_STRINGZ, BASE_NONE, NULL, 0x0,
816 "SSH mac_algorithms_client_to_server string", HFILL }},
818 { &hf_ssh_mac_algorithms_server_to_client,
819 { "mac_algorithms_server_to_client string", "ssh.mac_algorithms_server_to_client",
820 FT_STRINGZ, BASE_NONE, NULL, 0x0,
821 "SSH mac_algorithms_server_to_client string", HFILL }},
823 { &hf_ssh_compression_algorithms_client_to_server,
824 { "compression_algorithms_client_to_server string", "ssh.compression_algorithms_client_to_server",
825 FT_STRINGZ, BASE_NONE, NULL, 0x0,
826 "SSH compression_algorithms_client_to_server string", HFILL }},
828 { &hf_ssh_compression_algorithms_server_to_client,
829 { "compression_algorithms_server_to_client string", "ssh.compression_algorithms_server_to_client",
830 FT_STRINGZ, BASE_NONE, NULL, 0x0,
831 "SSH compression_algorithms_server_to_client string", HFILL }},
833 { &hf_ssh_languages_client_to_server,
834 { "languages_client_to_server string", "ssh.languages_client_to_server",
835 FT_STRINGZ, BASE_NONE, NULL, 0x0,
836 "SSH languages_client_to_server string", HFILL }},
838 { &hf_ssh_languages_server_to_client,
839 { "languages_server_to_client string", "ssh.languages_server_to_client",
840 FT_STRINGZ, BASE_NONE, NULL, 0x0,
841 "SSH languages_server_to_client string", HFILL }},
843 { &hf_ssh_kex_algorithms_length,
844 { "kex_algorithms length", "ssh.kex_algorithms_length",
845 FT_UINT32, BASE_DEC, NULL, 0x0,
846 "SSH kex_algorithms length", HFILL }},
848 { &hf_ssh_server_host_key_algorithms_length,
849 { "server_host_key_algorithms length", "ssh.server_host_key_algorithms_length",
850 FT_UINT32, BASE_DEC, NULL, 0x0,
851 "SSH server_host_key_algorithms length", HFILL }},
853 { &hf_ssh_encryption_algorithms_client_to_server_length,
854 { "encryption_algorithms_client_to_server length", "ssh.encryption_algorithms_client_to_server_length",
855 FT_UINT32, BASE_DEC, NULL, 0x0,
856 "SSH encryption_algorithms_client_to_server length", HFILL }},
858 { &hf_ssh_encryption_algorithms_server_to_client_length,
859 { "encryption_algorithms_server_to_client length", "ssh.encryption_algorithms_server_to_client_length",
860 FT_UINT32, BASE_DEC, NULL, 0x0,
861 "SSH encryption_algorithms_server_to_client length", HFILL }},
863 { &hf_ssh_mac_algorithms_client_to_server_length,
864 { "mac_algorithms_client_to_server length", "ssh.mac_algorithms_client_to_server_length",
865 FT_UINT32, BASE_DEC, NULL, 0x0,
866 "SSH mac_algorithms_client_to_server length", HFILL }},
868 { &hf_ssh_mac_algorithms_server_to_client_length,
869 { "mac_algorithms_server_to_client length", "ssh.mac_algorithms_server_to_client_length",
870 FT_UINT32, BASE_DEC, NULL, 0x0,
871 "SSH mac_algorithms_server_to_client length", HFILL }},
873 { &hf_ssh_compression_algorithms_client_to_server_length,
874 { "compression_algorithms_client_to_server length", "ssh.compression_algorithms_client_to_server_length",
875 FT_UINT32, BASE_DEC, NULL, 0x0,
876 "SSH compression_algorithms_client_to_server length", HFILL }},
878 { &hf_ssh_compression_algorithms_server_to_client_length,
879 { "compression_algorithms_server_to_client length", "ssh.compression_algorithms_server_to_client_length",
880 FT_UINT32, BASE_DEC, NULL, 0x0,
881 "SSH compression_algorithms_server_to_client length", HFILL }},
883 { &hf_ssh_languages_client_to_server_length,
884 { "languages_client_to_server length", "ssh.languages_client_to_server_length",
885 FT_UINT32, BASE_DEC, NULL, 0x0,
886 "SSH languages_client_to_server length", HFILL }},
888 { &hf_ssh_languages_server_to_client_length,
889 { "languages_server_to_client length", "ssh.languages_server_to_client_length",
890 FT_UINT32, BASE_DEC, NULL, 0x0,
891 "SSH languages_server_to_client length", HFILL }},
895 static gint *ett[] = {
902 module_t *ssh_module;
904 proto_ssh = proto_register_protocol("SSH Protocol",
906 proto_register_field_array(proto_ssh, hf, array_length(hf));
907 proto_register_subtree_array(ett, array_length(ett));
909 ssh_module = prefs_register_protocol(proto_ssh, NULL);
910 prefs_register_bool_preference(ssh_module, "desegment_buffers",
911 "Reassemble SSH buffers spanning multiple TCP segments",
912 "Whether the SSH dissector should reassemble SSH buffers spanning multiple TCP segments. "
913 "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
918 proto_reg_handoff_ssh(void)
920 dissector_handle_t ssh_handle;
922 ssh_handle = create_dissector_handle(dissect_ssh, proto_ssh);
924 dissector_add("tcp.port", TCP_PORT_SSH, ssh_handle);