2 * Routines for ssh packet dissection
4 * Huagang XIE <huagang@intruvert.com>
5 * Kees Cook <kees@outflux.net>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * Copied from packet-mysql.c
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 * Note: support SSH v1 and v2 now.
32 /* SSH version 2 is defined in:
34 * RFC 4250: The Secure Shell (SSH) Protocol Assigned Numbers
35 * RFC 4251: The Secure Shell (SSH) Protocol Architecture
36 * RFC 4252: The Secure Shell (SSH) Authentication Protocol
37 * RFC 4253: The Secure Shell (SSH) Transport Layer Protocol
38 * RFC 4254: The Secure Shell (SSH) Connection Protocol
40 * SSH versions under 2 were never officially standardized.
42 * Diffie-Hellman Group Exchange is defined in:
44 * RFC 4419: Diffie-Hellman Group Exchange for
45 * the Secure Shell (SSH) Transport Layer Protocol
48 /* "SSH" prefixes are for version 2, whereas "SSH1" is for version 1 */
54 #include <epan/packet.h>
55 #include <epan/exceptions.h>
56 #include <epan/conversation.h>
57 #include <epan/wmem/wmem.h>
58 #include <epan/sctpppids.h>
59 #include <epan/prefs.h>
60 #include <epan/expert.h>
62 #include "packet-tcp.h"
64 void proto_register_ssh(void);
65 void proto_reg_handoff_ssh(void);
67 /* SSH Version 1 definition , from openssh ssh1.h */
68 #define SSH1_MSG_NONE 0 /* no message */
69 #define SSH1_MSG_DISCONNECT 1 /* cause (string) */
70 #define SSH1_SMSG_PUBLIC_KEY 2 /* ck,msk,srvk,hostk */
71 #define SSH1_CMSG_SESSION_KEY 3 /* key (BIGNUM) */
72 #define SSH1_CMSG_USER 4 /* user (string) */
75 #define SSH_VERSION_UNKNOWN 0
76 #define SSH_VERSION_1 1
77 #define SSH_VERSION_2 2
81 struct ssh_peer_data {
84 guint32 frame_version_start;
85 guint32 frame_version_end;
87 guint32 frame_key_start;
88 guint32 frame_key_end;
92 /* For all subsequent proposals,
93 [0] is client-to-server and [1] is server-to-client. */
94 #define CLIENT_TO_SERVER_PROPOSAL 0
95 #define SERVER_TO_CLIENT_PROPOSAL 1
97 gchar* mac_proposals[2];
101 gchar* enc_proposals[2];
104 gchar* comp_proposals[2];
107 gint length_is_plaintext;
110 struct ssh_flow_data {
114 int (*kex_specific_dissector)(guint8 msg_code, tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree);
116 /* [0] is client's, [1] is server's */
117 #define CLIENT_PEER_DATA 0
118 #define SERVER_PEER_DATA 1
119 struct ssh_peer_data peer_data[2];
122 static int proto_ssh = -1;
123 static int hf_ssh_packet_length= -1;
124 static int hf_ssh_packet_length_encrypted= -1;
125 static int hf_ssh_padding_length= -1;
126 static int hf_ssh_payload= -1;
127 static int hf_ssh_protocol= -1;
128 static int hf_ssh_dh_gex_min= -1;
129 static int hf_ssh_dh_gex_nbits= -1;
130 static int hf_ssh_dh_gex_max= -1;
131 static int hf_ssh_encrypted_packet= -1;
132 static int hf_ssh_padding_string= -1;
133 static int hf_ssh_mac_string= -1;
134 static int hf_ssh_msg_code = -1;
135 static int hf_ssh2_msg_code = -1;
136 static int hf_ssh2_kex_dh_msg_code = -1;
137 static int hf_ssh2_kex_dh_gex_msg_code = -1;
138 static int hf_ssh_cookie = -1;
139 static int hf_ssh_mpint_g= -1;
140 static int hf_ssh_mpint_p= -1;
141 static int hf_ssh_mpint_e= -1;
142 static int hf_ssh_mpint_f= -1;
143 static int hf_ssh_mpint_length= -1;
144 static int hf_ssh_kexdh_host_key= -1;
145 static int hf_ssh_kexdh_host_key_length= -1;
146 static int hf_ssh_kexdh_h_sig= -1;
147 static int hf_ssh_kexdh_h_sig_length= -1;
148 static int hf_ssh_kex_algorithms = -1;
149 static int hf_ssh_server_host_key_algorithms = -1;
150 static int hf_ssh_encryption_algorithms_client_to_server = -1;
151 static int hf_ssh_encryption_algorithms_server_to_client = -1;
152 static int hf_ssh_mac_algorithms_client_to_server=-1;
153 static int hf_ssh_mac_algorithms_server_to_client=-1;
154 static int hf_ssh_compression_algorithms_client_to_server=-1;
155 static int hf_ssh_compression_algorithms_server_to_client=-1;
156 static int hf_ssh_languages_client_to_server=-1;
157 static int hf_ssh_languages_server_to_client=-1;
158 static int hf_ssh_kex_algorithms_length= -1;
159 static int hf_ssh_server_host_key_algorithms_length= -1;
160 static int hf_ssh_encryption_algorithms_client_to_server_length= -1;
161 static int hf_ssh_encryption_algorithms_server_to_client_length= -1;
162 static int hf_ssh_mac_algorithms_client_to_server_length= -1;
163 static int hf_ssh_mac_algorithms_server_to_client_length= -1;
164 static int hf_ssh_compression_algorithms_client_to_server_length= -1;
165 static int hf_ssh_compression_algorithms_server_to_client_length= -1;
166 static int hf_ssh_languages_client_to_server_length= -1;
167 static int hf_ssh_languages_server_to_client_length= -1;
168 static int hf_ssh_kex_first_packet_follows = -1;
169 static int hf_ssh_kex_reserved = -1;
171 static gint ett_ssh = -1;
172 static gint ett_key_exchange = -1;
173 static gint ett_key_init = -1;
174 static gint ett_ssh1 = -1;
175 static gint ett_ssh2 = -1;
177 static expert_field ei_ssh_packet_length = EI_INIT;
179 static gboolean ssh_desegment = TRUE;
181 static dissector_handle_t ssh_handle;
183 #define TCP_PORT_SSH 22
184 #define SCTP_PORT_SSH 22
186 /* Message Numbers (from RFC 4250) (1-255) */
188 /* Transport layer protocol: generic (1-19) */
189 #define SSH_MSG_DISCONNECT 1
190 #define SSH_MSG_IGNORE 2
191 #define SSH_MSG_UNIMPLEMENTED 3
192 #define SSH_MSG_DEBUG 4
193 #define SSH_MSG_SERVICE_REQUEST 5
194 #define SSH_MSG_SERVICE_ACCEPT 6
196 /* Transport layer protocol: Algorithm negotiation (20-29) */
197 #define SSH_MSG_KEXINIT 20
198 #define SSH_MSG_NEWKEYS 21
200 /* Transport layer: Key exchange method specific (reusable) (30-49) */
201 #define SSH_MSG_KEXDH_INIT 30
202 #define SSH_MSG_KEXDH_REPLY 31
204 #define SSH_MSG_KEX_DH_GEX_REQUEST_OLD 30
205 #define SSH_MSG_KEX_DH_GEX_GROUP 31
206 #define SSH_MSG_KEX_DH_GEX_INIT 32
207 #define SSH_MSG_KEX_DH_GEX_REPLY 33
208 #define SSH_MSG_KEX_DH_GEX_REQUEST 34
210 /* User authentication protocol: generic (50-59) */
211 #define SSH_MSG_USERAUTH_REQUEST 50
212 #define SSH_MSG_USERAUTH_FAILURE 51
213 #define SSH_MSG_USERAUTH_SUCCESS 52
214 #define SSH_MSG_USERAUTH_BANNER 53
216 /* User authentication protocol: method specific (reusable) (50-79) */
218 /* Connection protocol: generic (80-89) */
219 #define SSH_MSG_GLOBAL_REQUEST 80
220 #define SSH_MSG_REQUEST_SUCCESS 81
221 #define SSH_MSG_REQUEST_FAILURE 82
223 /* Connection protocol: channel related messages (90-127) */
224 #define SSH_MSG_CHANNEL_OPEN 90
225 #define SSH_MSG_CHANNEL_OPEN_CONFIRMATION 91
226 #define SSH_MSG_CHANNEL_OPEN_FAILURE 92
227 #define SSH_MSG_CHANNEL_WINDOW_ADJUST 93
228 #define SSH_MSG_CHANNEL_DATA 94
229 #define SSH_MSG_CHANNEL_EXTENDED_DATA 95
230 #define SSH_MSG_CHANNEL_EOF 96
231 #define SSH_MSG_CHANNEL_CLOSE 97
232 #define SSH_MSG_CHANNEL_REQUEST 98
233 #define SSH_MSG_CHANNEL_SUCCESS 99
234 #define SSH_MSG_CHANNEL_FAILURE 100
236 /* 128-191 reserved for client protocols */
237 /* 192-255 local extensions */
239 static const value_string ssh2_msg_vals[] = {
240 { SSH_MSG_DISCONNECT, "Disconnect" },
241 { SSH_MSG_IGNORE, "Ignore" },
242 { SSH_MSG_UNIMPLEMENTED, "Unimplemented" },
243 { SSH_MSG_DEBUG, "Debug" },
244 { SSH_MSG_SERVICE_REQUEST, "Service Request" },
245 { SSH_MSG_SERVICE_ACCEPT, "Service Accept" },
246 { SSH_MSG_KEXINIT, "Key Exchange Init" },
247 { SSH_MSG_NEWKEYS, "New Keys" },
248 { SSH_MSG_USERAUTH_REQUEST, "User Authentication Request" },
249 { SSH_MSG_USERAUTH_FAILURE, "User Authentication Failure" },
250 { SSH_MSG_USERAUTH_SUCCESS, "User Authentication Success" },
251 { SSH_MSG_USERAUTH_BANNER, "User Authentication Banner" },
252 { SSH_MSG_GLOBAL_REQUEST, "Global Request" },
253 { SSH_MSG_REQUEST_SUCCESS, "Request Success" },
254 { SSH_MSG_REQUEST_FAILURE, "Request Failure" },
255 { SSH_MSG_CHANNEL_OPEN, "Channel Open" },
256 { SSH_MSG_CHANNEL_OPEN_CONFIRMATION, "Channel Open Confirmation" },
257 { SSH_MSG_CHANNEL_OPEN_FAILURE, "Channel Open Failure" },
258 { SSH_MSG_CHANNEL_WINDOW_ADJUST, "Window Adjust" },
259 { SSH_MSG_CHANNEL_DATA, "Channel Data" },
260 { SSH_MSG_CHANNEL_EXTENDED_DATA, "Channel Extended Data" },
261 { SSH_MSG_CHANNEL_EOF, "Channel EOF" },
262 { SSH_MSG_CHANNEL_CLOSE, "Channel Close" },
263 { SSH_MSG_CHANNEL_REQUEST, "Channel Request" },
264 { SSH_MSG_CHANNEL_SUCCESS, "Channel Success" },
265 { SSH_MSG_CHANNEL_FAILURE, "Channel Failure" },
269 static const value_string ssh2_kex_dh_msg_vals[] = {
270 { SSH_MSG_KEXDH_INIT, "Diffie-Hellman Key Exchange Init" },
271 { SSH_MSG_KEXDH_REPLY, "Diffie-Hellman Key Exchange Reply" },
275 static const value_string ssh2_kex_dh_gex_msg_vals[] = {
276 { SSH_MSG_KEX_DH_GEX_REQUEST_OLD, "Diffie-Hellman Group Exchange Request (Old)" },
277 { SSH_MSG_KEX_DH_GEX_GROUP, "Diffie-Hellman Group Exchange Group" },
278 { SSH_MSG_KEX_DH_GEX_INIT, "Diffie-Hellman Group Exchange Init" },
279 { SSH_MSG_KEX_DH_GEX_REPLY, "Diffie-Hellman Group Exchange Reply" },
280 { SSH_MSG_KEX_DH_GEX_REQUEST, "Diffie-Hellman Group Exchange Request" },
284 static const value_string ssh1_msg_vals[] = {
285 {SSH1_MSG_NONE, "No Message"},
286 {SSH1_MSG_DISCONNECT, "Disconnect"},
287 {SSH1_SMSG_PUBLIC_KEY, "Public Key"},
288 {SSH1_CMSG_SESSION_KEY, "Session Key"},
289 {SSH1_CMSG_USER, "User"},
293 static int ssh_dissect_key_init(tvbuff_t *tvb, int offset, proto_tree *tree,
295 struct ssh_flow_data *global_data);
296 static int ssh_dissect_proposal(tvbuff_t *tvb, int offset, proto_tree *tree,
297 int hf_index_length, int hf_index_value, gchar **store);
298 static int ssh_dissect_ssh1(tvbuff_t *tvb, packet_info *pinfo,
299 struct ssh_flow_data *global_data,
300 int offset, proto_tree *tree, int is_response,
301 gboolean *need_desegmentation);
302 static int ssh_dissect_ssh2(tvbuff_t *tvb, packet_info *pinfo,
303 struct ssh_flow_data *global_data,
304 int offset, proto_tree *tree, int is_response,
305 gboolean *need_desegmentation);
306 static int ssh_dissect_key_exchange(tvbuff_t *tvb, packet_info *pinfo,
307 struct ssh_flow_data *global_data,
308 int offset, proto_tree *tree, int is_response,
309 gboolean *need_desegmentation);
310 static int ssh_dissect_kex_dh(guint8 msg_code, tvbuff_t *tvb,
311 packet_info *pinfo, int offset, proto_tree *tree);
312 static int ssh_dissect_kex_dh_gex(guint8 msg_code, tvbuff_t *tvb,
313 packet_info *pinfo, int offset, proto_tree *tree);
314 static int ssh_dissect_protocol(tvbuff_t *tvb, packet_info *pinfo,
315 struct ssh_flow_data *global_data,
316 int offset, proto_tree *tree, int is_response, guint *version,
317 gboolean *need_desegmentation);
318 static int ssh_dissect_encrypted_packet(tvbuff_t *tvb, packet_info *pinfo,
319 struct ssh_peer_data *peer_data,
320 int offset, proto_tree *tree);
321 static void ssh_choose_algo(gchar *client, gchar *server, gchar **result);
322 static void ssh_set_mac_length(struct ssh_peer_data *peer_data);
323 static void ssh_set_kex_specific_dissector(struct ssh_flow_data *global_data);
327 dissect_ssh(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
330 proto_tree *ssh_tree = NULL;
332 conversation_t *conversation;
333 int last_offset, offset = 0;
335 gboolean is_response = (pinfo->destport != pinfo->match_uint),
339 struct ssh_flow_data *global_data=NULL;
340 struct ssh_peer_data *peer_data;
342 conversation = find_or_create_conversation(pinfo);
344 global_data = (struct ssh_flow_data *)conversation_get_proto_data(conversation, proto_ssh);
346 global_data = (struct ssh_flow_data *)wmem_alloc0(wmem_file_scope(), sizeof(struct ssh_flow_data));
347 global_data->version=SSH_VERSION_UNKNOWN;
348 global_data->kex_specific_dissector=ssh_dissect_kex_dh;
349 global_data->peer_data[CLIENT_PEER_DATA].mac_length=-1;
350 global_data->peer_data[SERVER_PEER_DATA].mac_length=-1;
352 conversation_add_proto_data(conversation, proto_ssh, global_data);
355 peer_data = &global_data->peer_data[is_response];
358 ti = proto_tree_add_item(tree, proto_ssh, tvb, offset, -1, ENC_NA);
359 ssh_tree = proto_item_add_subtree(ti, ett_ssh);
362 version = global_data->version;
365 case SSH_VERSION_UNKNOWN:
366 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSH");
369 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSHv1");
372 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSHv2");
377 col_clear(pinfo->cinfo, COL_INFO);
379 while(tvb_reported_length_remaining(tvb, offset)> 0) {
380 gboolean after_version_start = (peer_data->frame_version_start == 0 ||
381 pinfo->fd->num >= peer_data->frame_version_start);
382 gboolean before_version_end = (peer_data->frame_version_end == 0 ||
383 pinfo->fd->num <= peer_data->frame_version_end);
385 need_desegmentation = FALSE;
386 last_offset = offset;
388 peer_data->counter++;
390 if (after_version_start && before_version_end &&
391 (tvb_strncaseeql(tvb, offset, "SSH-", 4) == 0)) {
392 if (peer_data->frame_version_start == 0)
393 peer_data->frame_version_start = pinfo->fd->num;
395 offset = ssh_dissect_protocol(tvb, pinfo,
397 offset, ssh_tree, is_response,
398 &version, &need_desegmentation);
400 if (!need_desegmentation) {
401 peer_data->frame_version_end = pinfo->fd->num;
402 global_data->version = version;
407 case SSH_VERSION_UNKNOWN:
408 offset = ssh_dissect_encrypted_packet(tvb, pinfo,
409 &global_data->peer_data[is_response], offset, ssh_tree);
413 offset = ssh_dissect_ssh1(tvb, pinfo, global_data,
414 offset, ssh_tree, is_response,
415 &need_desegmentation);
419 offset = ssh_dissect_ssh2(tvb, pinfo, global_data,
420 offset, ssh_tree, is_response,
421 &need_desegmentation);
426 if (need_desegmentation)
428 if (offset <= last_offset)
429 THROW(ReportedBoundsError);
432 col_prepend_fstr(pinfo->cinfo, COL_INFO, "%s: ", is_response ? "Server" : "Client");
436 ssh_dissect_ssh2(tvbuff_t *tvb, packet_info *pinfo,
437 struct ssh_flow_data *global_data,
438 int offset, proto_tree *tree, int is_response,
439 gboolean *need_desegmentation)
442 proto_item *ssh2_tree=NULL;
444 struct ssh_peer_data *peer_data = &global_data->peer_data[is_response];
447 wmem_strbuf_t *title=wmem_strbuf_new(wmem_packet_scope(), "SSH Version 2");
449 if (peer_data->enc || peer_data->mac || peer_data->comp) {
450 wmem_strbuf_append_printf(title, " (");
452 wmem_strbuf_append_printf(title, "encryption:%s%s",
454 peer_data->mac || peer_data->comp
457 wmem_strbuf_append_printf(title, "mac:%s%s",
459 peer_data->comp ? " " : "");
461 wmem_strbuf_append_printf(title, "compression:%s",
463 wmem_strbuf_append_printf(title, ")");
466 ti=proto_tree_add_text(tree, tvb, offset, -1, "%s", wmem_strbuf_get_str(title));
467 ssh2_tree = proto_item_add_subtree(ti, ett_ssh2);
470 if ((peer_data->frame_key_start == 0) ||
471 ((peer_data->frame_key_start <= pinfo->fd->num) &&
472 ((peer_data->frame_key_end == 0) || (pinfo->fd->num <= peer_data->frame_key_end)))) {
473 offset = ssh_dissect_key_exchange(tvb, pinfo, global_data,
474 offset, ssh2_tree, is_response,
475 need_desegmentation);
477 offset = ssh_dissect_encrypted_packet(tvb, pinfo,
478 &global_data->peer_data[is_response], offset, ssh2_tree);
484 ssh_dissect_ssh1(tvbuff_t *tvb, packet_info *pinfo,
485 struct ssh_flow_data *global_data,
486 int offset, proto_tree *tree, int is_response,
487 gboolean *need_desegmentation)
489 guint plen, padding_length, len;
494 proto_item *ssh1_tree =NULL;
496 struct ssh_peer_data *peer_data = &global_data->peer_data[is_response];
499 ti=proto_tree_add_text(tree, tvb, offset, -1, "SSH Version 1");
500 ssh1_tree = proto_item_add_subtree(ti, ett_ssh1);
504 * We use "tvb_ensure_length_remaining()" to make sure there
505 * actually *is* data remaining.
507 * This means we're guaranteed that "remain_length" is positive.
509 remain_length = tvb_ensure_length_remaining(tvb, offset);
511 * Can we do reassembly?
513 if (ssh_desegment && pinfo->can_desegment) {
515 * Yes - would an SSH header starting at this offset be split
516 * across segment boundaries?
518 if (remain_length < 4) {
520 * Yes. Tell the TCP dissector where the data for
521 * this message starts in the data it handed us and
522 * that we need "some more data." Don't tell it
523 * exactly how many bytes we need because if/when we
524 * ask for even more (after the header) that will
527 pinfo->desegment_offset = offset;
528 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
529 *need_desegmentation = TRUE;
533 plen = tvb_get_ntohl(tvb, offset) ;
534 padding_length = 8 - plen%8;
537 if (ssh_desegment && pinfo->can_desegment) {
538 if (plen+4+padding_length > remain_length) {
539 pinfo->desegment_offset = offset;
540 pinfo->desegment_len = plen+padding_length - remain_length;
541 *need_desegmentation = TRUE;
546 if (plen >= 0xffff) {
547 if (ssh1_tree && plen > 0) {
548 proto_tree_add_uint_format(ssh1_tree, hf_ssh_packet_length, tvb,
549 offset, 4, plen, "Overly large length %x", plen);
551 plen = remain_length-4-padding_length;
553 if (ssh1_tree && plen > 0) {
554 proto_tree_add_uint(ssh1_tree, hf_ssh_packet_length, tvb,
562 proto_tree_add_uint(ssh1_tree, hf_ssh_padding_length, tvb,
563 offset, padding_length, padding_length);
565 offset += padding_length;
568 if ((peer_data->frame_key_start == 0) ||
569 ((peer_data->frame_key_start >= pinfo->fd->num) && (pinfo->fd->num <= peer_data->frame_key_end))) {
570 msg_code = tvb_get_guint8(tvb, offset);
572 proto_tree_add_item(ssh1_tree, hf_ssh_msg_code, tvb, offset, 1, ENC_NA);
573 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
574 val_to_str(msg_code, ssh1_msg_vals, "Unknown (%u)"));
577 if (!pinfo->fd->flags.visited) {
578 if (peer_data->frame_key_start == 0)
579 peer_data->frame_key_start = pinfo->fd->num;
580 peer_data->frame_key_end = pinfo->fd->num;
584 col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Encrypted packet (len=%d)", len);
588 proto_tree_add_item(ssh1_tree, hf_ssh_payload,
589 tvb, offset, len, ENC_NA);
597 ssh_tree_add_mpint(tvbuff_t *tvb, int offset, proto_tree *tree,
598 int hf_ssh_mpint_selection)
600 guint len = tvb_get_ntohl(tvb, offset);
602 proto_tree_add_uint(tree, hf_ssh_mpint_length, tvb,
607 proto_tree_add_item(tree, hf_ssh_mpint_selection,
608 tvb, offset, len, ENC_NA);
614 ssh_tree_add_string(tvbuff_t *tvb, int offset, proto_tree *tree,
615 int hf_ssh_string, int hf_ssh_string_length)
617 guint len = tvb_get_ntohl(tvb, offset);
619 proto_tree_add_uint(tree, hf_ssh_string_length, tvb,
624 proto_tree_add_item(tree, hf_ssh_string,
625 tvb, offset, len, ENC_NA);
631 ssh_dissect_key_exchange(tvbuff_t *tvb, packet_info *pinfo,
632 struct ssh_flow_data *global_data,
633 int offset, proto_tree *tree, int is_response,
634 gboolean *need_desegmentation)
637 guint8 padding_length;
639 int last_offset=offset;
643 proto_item *key_ex_tree =NULL;
645 struct ssh_peer_data *peer_data = &global_data->peer_data[is_response];
648 * We use "tvb_ensure_length_remaining()" to make sure there
649 * actually *is* data remaining.
651 * This means we're guaranteed that "remain_length" is positive.
653 remain_length = tvb_ensure_length_remaining(tvb, offset);
655 * Can we do reassembly?
657 if (ssh_desegment && pinfo->can_desegment) {
659 * Yes - would an SSH header starting at this offset
660 * be split across segment boundaries?
662 if (remain_length < 4) {
664 * Yes. Tell the TCP dissector where the data for
665 * this message starts in the data it handed us and
666 * that we need "some more data." Don't tell it
667 * exactly how many bytes we need because if/when we
668 * ask for even more (after the header) that will
671 pinfo->desegment_offset = offset;
672 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
673 *need_desegmentation = TRUE;
677 plen = tvb_get_ntohl(tvb, offset) ;
679 if (ssh_desegment && pinfo->can_desegment) {
680 if (plen +4 > remain_length) {
681 pinfo->desegment_offset = offset;
682 pinfo->desegment_len = plen+4 - remain_length;
683 *need_desegmentation = TRUE;
688 * Need to check plen > 0x80000000 here
691 ti = proto_tree_add_uint(tree, hf_ssh_packet_length, tvb,
693 if (plen >= 0xffff) {
694 expert_add_info_format(pinfo, ti, &ei_ssh_packet_length, "Overly large number %d", plen);
695 plen = remain_length-4;
700 padding_length = tvb_get_guint8(tvb, offset);
701 proto_tree_add_uint(tree, hf_ssh_padding_length, tvb, offset, 1, padding_length);
704 tf=proto_tree_add_text(tree, tvb, offset, -1, "Key Exchange");
705 key_ex_tree = proto_item_add_subtree(tf, ett_key_exchange);
708 msg_code = tvb_get_guint8(tvb, offset);
710 if (msg_code >= 30 && msg_code < 40) {
711 offset = global_data->kex_specific_dissector(msg_code, tvb, pinfo, offset, key_ex_tree);
713 proto_tree_add_item(key_ex_tree, hf_ssh2_msg_code, tvb, offset, 1, ENC_NA);
716 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
717 val_to_str(msg_code, ssh2_msg_vals, "Unknown (%u)"));
719 /* 16 bytes cookie */
722 case SSH_MSG_KEXINIT:
723 if ((peer_data->frame_key_start == 0) || (peer_data->frame_key_start == pinfo->fd->num)) {
724 offset = ssh_dissect_key_init(tvb, offset, key_ex_tree, is_response, global_data);
725 peer_data->frame_key_start = pinfo->fd->num;
728 case SSH_MSG_NEWKEYS:
729 if (peer_data->frame_key_end == 0) {
730 peer_data->frame_key_end = pinfo->fd->num;
731 ssh_choose_algo(global_data->peer_data[CLIENT_PEER_DATA].enc_proposals[is_response],
732 global_data->peer_data[SERVER_PEER_DATA].enc_proposals[is_response],
735 /* some ciphers have their own MAC so the "negotiated" one is meaningless */
736 if(peer_data->enc && (0 == strcmp(peer_data->enc, "aes128-gcm@openssh.com") ||
737 0 == strcmp(peer_data->enc, "aes256-gcm@openssh.com"))) {
738 peer_data->mac = wmem_strdup(wmem_file_scope(), (const gchar *)"<implicit>");
739 peer_data->mac_length = 16;
740 peer_data->length_is_plaintext = 1;
742 else if(peer_data->enc && 0 == strcmp(peer_data->enc, "chacha20-poly1305@openssh.com")) {
743 peer_data->mac = wmem_strdup(wmem_file_scope(), (const gchar *)"<implicit>");
744 peer_data->mac_length = 16;
747 ssh_choose_algo(global_data->peer_data[CLIENT_PEER_DATA].mac_proposals[is_response],
748 global_data->peer_data[SERVER_PEER_DATA].mac_proposals[is_response],
750 ssh_set_mac_length(peer_data);
753 ssh_choose_algo(global_data->peer_data[CLIENT_PEER_DATA].comp_proposals[is_response],
754 global_data->peer_data[SERVER_PEER_DATA].comp_proposals[is_response],
761 len = plen+4-padding_length-(offset-last_offset);
762 proto_tree_add_item(key_ex_tree, hf_ssh_payload, tvb, offset, len, ENC_NA);
766 proto_tree_add_item(key_ex_tree, hf_ssh_padding_string, tvb, offset, padding_length, ENC_NA);
767 offset+= padding_length;
772 static int ssh_dissect_kex_dh(guint8 msg_code, tvbuff_t *tvb,
773 packet_info *pinfo, int offset, proto_tree *tree)
775 proto_tree_add_item(tree, hf_ssh2_kex_dh_msg_code, tvb, offset, 1, ENC_NA);
778 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
779 val_to_str(msg_code, ssh2_kex_dh_msg_vals, "Unknown (%u)"));
782 case SSH_MSG_KEXDH_INIT:
783 offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_e);
786 case SSH_MSG_KEXDH_REPLY:
787 offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_kexdh_host_key, hf_ssh_kexdh_host_key_length);
788 offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_f);
789 offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_kexdh_h_sig, hf_ssh_kexdh_h_sig_length);
796 static int ssh_dissect_kex_dh_gex(guint8 msg_code, tvbuff_t *tvb,
797 packet_info *pinfo, int offset, proto_tree *tree)
799 proto_tree_add_item(tree, hf_ssh2_kex_dh_gex_msg_code, tvb, offset, 1, ENC_NA);
802 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
803 val_to_str(msg_code, ssh2_kex_dh_gex_msg_vals, "Unknown (%u)"));
806 case SSH_MSG_KEX_DH_GEX_REQUEST_OLD:
807 proto_tree_add_item(tree, hf_ssh_dh_gex_nbits, tvb, offset, 4, ENC_BIG_ENDIAN);
811 case SSH_MSG_KEX_DH_GEX_GROUP:
812 offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_p);
813 offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_g);
816 case SSH_MSG_KEX_DH_GEX_INIT:
817 offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_e);
820 case SSH_MSG_KEX_DH_GEX_REPLY:
821 offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_kexdh_host_key, hf_ssh_kexdh_host_key_length);
822 offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_f);
823 offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_kexdh_h_sig, hf_ssh_kexdh_h_sig_length);
826 case SSH_MSG_KEX_DH_GEX_REQUEST:
827 proto_tree_add_item(tree, hf_ssh_dh_gex_min, tvb, offset, 4, ENC_BIG_ENDIAN);
829 proto_tree_add_item(tree, hf_ssh_dh_gex_nbits, tvb, offset, 4, ENC_BIG_ENDIAN);
831 proto_tree_add_item(tree, hf_ssh_dh_gex_max, tvb, offset, 4, ENC_BIG_ENDIAN);
840 ssh_dissect_encrypted_packet(tvbuff_t *tvb, packet_info *pinfo,
841 struct ssh_peer_data *peer_data,
842 int offset, proto_tree *tree)
847 len = tvb_reported_length_remaining(tvb, offset);
848 col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Encrypted packet (len=%d)", len);
851 gint encrypted_len = len;
853 if (len > 4 && peer_data->length_is_plaintext) {
854 plen = tvb_get_ntohl(tvb, offset) ;
855 proto_tree_add_uint(tree, hf_ssh_packet_length, tvb, offset, 4, plen);
859 proto_tree_add_item(tree, hf_ssh_packet_length_encrypted, tvb, offset, 4, ENC_NA);
863 if (peer_data->mac_length>0)
864 encrypted_len -= peer_data->mac_length;
866 proto_tree_add_item(tree, hf_ssh_encrypted_packet,
867 tvb, offset+4, encrypted_len, ENC_NA);
869 if (peer_data->mac_length>0)
870 proto_tree_add_item(tree, hf_ssh_mac_string,
871 tvb, offset+4+encrypted_len,
872 peer_data->mac_length, ENC_NA);
879 ssh_dissect_protocol(tvbuff_t *tvb, packet_info *pinfo,
880 struct ssh_flow_data *global_data,
881 int offset, proto_tree *tree, int is_response, guint * version,
882 gboolean *need_desegmentation)
885 gint linelen, protolen;
888 * If the first packet do not contain the banner,
889 * it is dump in the middle of a flow or not a ssh at all
891 if (tvb_strncaseeql(tvb, offset, "SSH-", 4) != 0) {
892 offset = ssh_dissect_encrypted_packet(tvb, pinfo,
893 &global_data->peer_data[is_response], offset, tree);
898 if (tvb_strncaseeql(tvb, offset, "SSH-2.", 6) == 0) {
899 *(version) = SSH_VERSION_2;
900 } else if (tvb_strncaseeql(tvb, offset, "SSH-1.99-", 9) == 0) {
901 *(version) = SSH_VERSION_2;
902 } else if (tvb_strncaseeql(tvb, offset, "SSH-1.", 6) == 0) {
903 *(version) = SSH_VERSION_1;
908 * We use "tvb_ensure_length_remaining()" to make sure there
909 * actually *is* data remaining.
911 * This means we're guaranteed that "remain_length" is positive.
913 remain_length = tvb_ensure_length_remaining(tvb, offset);
914 /*linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
916 linelen = tvb_find_guint8(tvb, offset, -1, '\n');
918 if (ssh_desegment && pinfo->can_desegment) {
919 if (linelen == -1 || remain_length < (guint)linelen-offset) {
920 pinfo->desegment_offset = offset;
921 pinfo->desegment_len = linelen-remain_length;
922 *need_desegmentation = TRUE;
927 /* XXX - reassemble across segment boundaries? */
928 linelen = remain_length;
931 linelen = linelen - offset + 1;
933 if (linelen > 1 && tvb_get_guint8(tvb, offset + linelen - 2) == '\r')
934 protolen = linelen - 2;
936 protolen = linelen - 1;
939 col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Protocol (%s)",
940 tvb_format_text(tvb, offset, protolen));
942 proto_tree_add_item(tree, hf_ssh_protocol,
943 tvb, offset, linelen, ENC_ASCII|ENC_NA);
949 ssh_set_mac_length(struct ssh_peer_data *peer_data)
953 char *mac_name = peer_data->mac;
956 if (!mac_name) return;
957 mac_name = wmem_strdup(NULL, (const gchar *)mac_name);
958 if (!mac_name) return;
960 /* strip trailing "-etm@openssh.com" or "@openssh.com" */
961 strip = strstr(mac_name, "-etm@openssh.com");
963 peer_data->length_is_plaintext = 1;
967 strip = strstr(mac_name, "@openssh.com");
968 if (strip) *strip = '\0';
971 if ((size_str=g_strrstr(mac_name, "-")) && ((size=atoi(size_str+1)))) {
972 peer_data->mac_length = (size > 0) ? size / 8 : 0;
974 else if (strcmp(mac_name, "hmac-sha1") == 0) {
975 peer_data->mac_length = 20;
977 else if (strcmp(mac_name, "hmac-md5") == 0) {
978 peer_data->mac_length = 16;
980 else if (strcmp(mac_name, "hmac-ripemd160") == 0) {
981 peer_data->mac_length = 20;
983 else if (strcmp(mac_name, "none") == 0) {
984 peer_data->mac_length = 0;
987 wmem_free(NULL, mac_name);
990 static void ssh_set_kex_specific_dissector(struct ssh_flow_data *global_data)
992 const char *kex_name = global_data->kex;
994 if (!kex_name) return;
996 if (strcmp(kex_name, "diffie-hellman-group-exchange-sha1") == 0 ||
997 strcmp(kex_name, "diffie-hellman-group-exchange-sha256") == 0)
999 global_data->kex_specific_dissector = ssh_dissect_kex_dh_gex;
1004 ssh_gslist_compare_strings(gconstpointer a, gconstpointer b)
1006 if (a == NULL && b == NULL)
1012 return strcmp((const char*)a, (const char*)b);
1015 /* expects that *result is NULL */
1017 ssh_choose_algo(gchar *client, gchar *server, gchar **result)
1019 gchar **server_strings=NULL;
1020 gchar **client_strings=NULL;
1022 GSList *server_list = NULL;
1024 if (!client || !server || !result || *result)
1027 server_strings = g_strsplit(server, ",", 0);
1028 for (step = server_strings; *step; step++) {
1029 server_list = g_slist_append(server_list, *step);
1032 client_strings = g_strsplit(client, ",", 0);
1033 for (step = client_strings; *step; step++) {
1035 if ((agreed=g_slist_find_custom(server_list, *step, ssh_gslist_compare_strings))) {
1036 *result = wmem_strdup(wmem_file_scope(), (const gchar *)agreed->data);
1041 g_strfreev(client_strings);
1042 g_slist_free(server_list);
1043 g_strfreev(server_strings);
1047 ssh_dissect_key_init(tvbuff_t *tvb, int offset, proto_tree *tree,
1048 int is_response, struct ssh_flow_data *global_data)
1050 int start_offset = offset;
1052 proto_item *tf = NULL;
1053 proto_item *key_init_tree=NULL;
1055 struct ssh_peer_data *peer_data = &global_data->peer_data[is_response];
1058 tf=proto_tree_add_text(tree, tvb, offset, -1, "Algorithms");
1059 key_init_tree = proto_item_add_subtree(tf, ett_key_init);
1060 proto_tree_add_item(key_init_tree, hf_ssh_cookie,
1061 tvb, offset, 16, ENC_NA);
1065 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1066 hf_ssh_kex_algorithms_length, hf_ssh_kex_algorithms,
1067 &peer_data->kex_proposal);
1068 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1069 hf_ssh_server_host_key_algorithms_length,
1070 hf_ssh_server_host_key_algorithms, NULL);
1071 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1072 hf_ssh_encryption_algorithms_client_to_server_length,
1073 hf_ssh_encryption_algorithms_client_to_server,
1074 &peer_data->enc_proposals[CLIENT_TO_SERVER_PROPOSAL]);
1075 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1076 hf_ssh_encryption_algorithms_server_to_client_length,
1077 hf_ssh_encryption_algorithms_server_to_client,
1078 &peer_data->enc_proposals[SERVER_TO_CLIENT_PROPOSAL]);
1079 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1080 hf_ssh_mac_algorithms_client_to_server_length,
1081 hf_ssh_mac_algorithms_client_to_server,
1082 &peer_data->mac_proposals[CLIENT_TO_SERVER_PROPOSAL]);
1083 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1084 hf_ssh_mac_algorithms_server_to_client_length,
1085 hf_ssh_mac_algorithms_server_to_client,
1086 &peer_data->mac_proposals[SERVER_TO_CLIENT_PROPOSAL]);
1087 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1088 hf_ssh_compression_algorithms_client_to_server_length,
1089 hf_ssh_compression_algorithms_client_to_server,
1090 &peer_data->comp_proposals[CLIENT_TO_SERVER_PROPOSAL]);
1091 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1092 hf_ssh_compression_algorithms_server_to_client_length,
1093 hf_ssh_compression_algorithms_server_to_client,
1094 &peer_data->comp_proposals[SERVER_TO_CLIENT_PROPOSAL]);
1095 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1096 hf_ssh_languages_client_to_server_length,
1097 hf_ssh_languages_client_to_server, NULL);
1098 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1099 hf_ssh_languages_server_to_client_length,
1100 hf_ssh_languages_server_to_client, NULL);
1102 proto_tree_add_item(key_init_tree, hf_ssh_kex_first_packet_follows,
1103 tvb, offset, 1, ENC_BIG_ENDIAN);
1106 proto_tree_add_item(key_init_tree, hf_ssh_kex_reserved,
1107 tvb, offset, 4, ENC_NA);
1110 if (global_data->peer_data[CLIENT_PEER_DATA].kex_proposal &&
1111 global_data->peer_data[SERVER_PEER_DATA].kex_proposal &&
1114 /* Note: we're ignoring first_kex_packet_follows. */
1116 global_data->peer_data[CLIENT_PEER_DATA].kex_proposal,
1117 global_data->peer_data[SERVER_PEER_DATA].kex_proposal,
1119 ssh_set_kex_specific_dissector(global_data);
1123 proto_item_set_len(tf, offset-start_offset);
1130 ssh_dissect_proposal(tvbuff_t *tvb, int offset, proto_tree *tree,
1131 int hf_index_length, int hf_index_value, gchar **store)
1133 guint32 len = tvb_get_ntohl(tvb, offset);
1134 proto_tree_add_uint(tree, hf_index_length, tvb, offset, 4, len);
1137 proto_tree_add_item(tree, hf_index_value, tvb, offset, len,
1140 *store = tvb_get_string_enc(wmem_file_scope(), tvb, offset, len, ENC_ASCII);
1148 proto_register_ssh(void)
1150 static hf_register_info hf[] = {
1151 { &hf_ssh_packet_length,
1152 { "Packet Length", "ssh.packet_length",
1153 FT_UINT32, BASE_DEC, NULL, 0x0,
1154 "SSH packet length", HFILL }},
1156 { &hf_ssh_packet_length_encrypted,
1157 { "Packet Length (encrypted)", "ssh.packet_length_encrypted",
1158 FT_BYTES, BASE_NONE, NULL, 0x0,
1159 "SSH packet length (encrypted)", HFILL }},
1161 { &hf_ssh_padding_length,
1162 { "Padding Length", "ssh.padding_length",
1163 FT_UINT8, BASE_DEC, NULL, 0x0,
1164 "SSH Packet Number", HFILL }},
1167 { "Message Code", "ssh.message_code",
1168 FT_UINT8, BASE_DEC, VALS(ssh1_msg_vals), 0x0,
1169 "SSH Message Code", HFILL }},
1171 { &hf_ssh2_msg_code,
1172 { "Message Code", "ssh.message_code",
1173 FT_UINT8, BASE_DEC, VALS(ssh2_msg_vals), 0x0,
1174 "SSH Message Code", HFILL }},
1176 { &hf_ssh2_kex_dh_msg_code,
1177 { "Message Code", "ssh.message_code",
1178 FT_UINT8, BASE_DEC, VALS(ssh2_kex_dh_msg_vals), 0x0,
1179 "SSH Message Code", HFILL }},
1181 { &hf_ssh2_kex_dh_gex_msg_code,
1182 { "Message Code", "ssh.message_code",
1183 FT_UINT8, BASE_DEC, VALS(ssh2_kex_dh_gex_msg_vals), 0x0,
1184 "SSH Message Code", HFILL }},
1187 { "DH base (G)", "ssh.dh.g",
1188 FT_BYTES, BASE_NONE, NULL, 0x0,
1189 "SSH DH base (G)", HFILL }},
1192 { "DH modulus (P)", "ssh.dh.p",
1193 FT_BYTES, BASE_NONE, NULL, 0x0,
1194 "SSH DH modulus (P)", HFILL }},
1197 { "DH client e", "ssh.dh.e",
1198 FT_BYTES, BASE_NONE, NULL, 0x0,
1199 "SSH DH client e", HFILL }},
1202 { "DH server f", "ssh.dh.f",
1203 FT_BYTES, BASE_NONE, NULL, 0x0,
1204 "SSH DH server f", HFILL }},
1206 { &hf_ssh_mpint_length,
1207 { "Multi Precision Integer Length", "ssh.mpint_length",
1208 FT_UINT32, BASE_DEC, NULL, 0x0,
1209 "SSH mpint length", HFILL }},
1211 { &hf_ssh_kexdh_host_key,
1212 { "KEX DH host key", "ssh.kexdh.host_key",
1213 FT_BYTES, BASE_NONE, NULL, 0x0,
1214 "SSH KEX DH host key", HFILL }},
1216 { &hf_ssh_kexdh_h_sig,
1217 { "KEX DH H signature", "ssh.kexdh.h_sig",
1218 FT_BYTES, BASE_NONE, NULL, 0x0,
1219 "SSH KEX DH H signature", HFILL }},
1221 { &hf_ssh_kexdh_host_key_length,
1222 { "KEX DH host key length", "ssh.kexdh.host_key_length",
1223 FT_UINT32, BASE_DEC, NULL, 0x0,
1224 "SSH KEX DH host key length", HFILL }},
1226 { &hf_ssh_kexdh_h_sig_length,
1227 { "KEX DH H signature length", "ssh.kexdh.h_sig_length",
1228 FT_UINT32, BASE_DEC, NULL, 0x0,
1229 "SSH KEX DH H signature length", HFILL }},
1231 { &hf_ssh_encrypted_packet,
1232 { "Encrypted Packet", "ssh.encrypted_packet",
1233 FT_BYTES, BASE_NONE, NULL, 0x0,
1234 "SSH Protocol Packet", HFILL }},
1237 { "Protocol", "ssh.protocol",
1238 FT_STRING, BASE_NONE, NULL, 0x0,
1239 "SSH Protocol", HFILL }},
1242 { "Cookie", "ssh.cookie",
1243 FT_BYTES, BASE_NONE, NULL, 0x0,
1244 "SSH Cookie", HFILL }},
1246 { &hf_ssh_kex_first_packet_follows,
1247 { "KEX First Packet Follows", "ssh.kex.first_packet_follows",
1248 FT_UINT8, BASE_DEC, NULL, 0x0,
1249 "SSH KEX Fist Packet Follows", HFILL }},
1251 { &hf_ssh_kex_reserved,
1252 { "Reserved", "ssh.kex.reserved",
1253 FT_BYTES, BASE_NONE, NULL, 0x0,
1254 "SSH Protocol KEX Reserved", HFILL }},
1256 { &hf_ssh_dh_gex_min,
1257 { "DH GEX Min", "ssh.dh_gex.min",
1258 FT_UINT32, BASE_DEC, NULL, 0x0,
1259 "SSH DH GEX Minimum", HFILL }},
1261 { &hf_ssh_dh_gex_nbits,
1262 { "DH GEX Numbers of Bits", "ssh.dh_gex.nbits",
1263 FT_UINT32, BASE_DEC, NULL, 0x0,
1264 "SSH DH GEX Number of Bits", HFILL }},
1266 { &hf_ssh_dh_gex_max,
1267 { "DH GEX Max", "ssh.dh_gex.max",
1268 FT_UINT32, BASE_DEC, NULL, 0x0,
1269 "SSH DH GEX Maximum", HFILL }},
1272 { "Payload", "ssh.payload",
1273 FT_BYTES, BASE_NONE, NULL, 0x0,
1274 "SSH Payload", HFILL }},
1276 { &hf_ssh_padding_string,
1277 { "Padding String", "ssh.padding_string",
1278 FT_BYTES, BASE_NONE, NULL, 0x0,
1279 "SSH Padding String", HFILL }},
1281 { &hf_ssh_mac_string,
1283 FT_BYTES, BASE_NONE, NULL, 0x0,
1284 "SSH Protocol Packet MAC", HFILL }},
1286 { &hf_ssh_kex_algorithms,
1287 { "kex_algorithms string", "ssh.kex_algorithms",
1288 FT_STRINGZ, BASE_NONE, NULL, 0x0,
1289 "SSH kex_algorithms string", HFILL }},
1291 { &hf_ssh_server_host_key_algorithms,
1292 { "server_host_key_algorithms string", "ssh.server_host_key_algorithms",
1293 FT_STRINGZ, BASE_NONE, NULL, 0x0,
1294 "SSH server_host_key_algorithms string", HFILL }},
1296 { &hf_ssh_encryption_algorithms_client_to_server,
1297 { "encryption_algorithms_client_to_server string", "ssh.encryption_algorithms_client_to_server",
1298 FT_STRINGZ, BASE_NONE, NULL, 0x0,
1299 "SSH encryption_algorithms_client_to_server string", HFILL }},
1301 { &hf_ssh_encryption_algorithms_server_to_client,
1302 { "encryption_algorithms_server_to_client string", "ssh.encryption_algorithms_server_to_client",
1303 FT_STRINGZ, BASE_NONE, NULL, 0x0,
1304 "SSH encryption_algorithms_server_to_client string", HFILL }},
1306 { &hf_ssh_mac_algorithms_client_to_server,
1307 { "mac_algorithms_client_to_server string", "ssh.mac_algorithms_client_to_server",
1308 FT_STRINGZ, BASE_NONE, NULL, 0x0,
1309 "SSH mac_algorithms_client_to_server string", HFILL }},
1311 { &hf_ssh_mac_algorithms_server_to_client,
1312 { "mac_algorithms_server_to_client string", "ssh.mac_algorithms_server_to_client",
1313 FT_STRINGZ, BASE_NONE, NULL, 0x0,
1314 "SSH mac_algorithms_server_to_client string", HFILL }},
1316 { &hf_ssh_compression_algorithms_client_to_server,
1317 { "compression_algorithms_client_to_server string", "ssh.compression_algorithms_client_to_server",
1318 FT_STRINGZ, BASE_NONE, NULL, 0x0,
1319 "SSH compression_algorithms_client_to_server string", HFILL }},
1321 { &hf_ssh_compression_algorithms_server_to_client,
1322 { "compression_algorithms_server_to_client string", "ssh.compression_algorithms_server_to_client",
1323 FT_STRINGZ, BASE_NONE, NULL, 0x0,
1324 "SSH compression_algorithms_server_to_client string", HFILL }},
1326 { &hf_ssh_languages_client_to_server,
1327 { "languages_client_to_server string", "ssh.languages_client_to_server",
1328 FT_STRINGZ, BASE_NONE, NULL, 0x0,
1329 "SSH languages_client_to_server string", HFILL }},
1331 { &hf_ssh_languages_server_to_client,
1332 { "languages_server_to_client string", "ssh.languages_server_to_client",
1333 FT_STRINGZ, BASE_NONE, NULL, 0x0,
1334 "SSH languages_server_to_client string", HFILL }},
1336 { &hf_ssh_kex_algorithms_length,
1337 { "kex_algorithms length", "ssh.kex_algorithms_length",
1338 FT_UINT32, BASE_DEC, NULL, 0x0,
1339 "SSH kex_algorithms length", HFILL }},
1341 { &hf_ssh_server_host_key_algorithms_length,
1342 { "server_host_key_algorithms length", "ssh.server_host_key_algorithms_length",
1343 FT_UINT32, BASE_DEC, NULL, 0x0,
1344 "SSH server_host_key_algorithms length", HFILL }},
1346 { &hf_ssh_encryption_algorithms_client_to_server_length,
1347 { "encryption_algorithms_client_to_server length", "ssh.encryption_algorithms_client_to_server_length",
1348 FT_UINT32, BASE_DEC, NULL, 0x0,
1349 "SSH encryption_algorithms_client_to_server length", HFILL }},
1351 { &hf_ssh_encryption_algorithms_server_to_client_length,
1352 { "encryption_algorithms_server_to_client length", "ssh.encryption_algorithms_server_to_client_length",
1353 FT_UINT32, BASE_DEC, NULL, 0x0,
1354 "SSH encryption_algorithms_server_to_client length", HFILL }},
1356 { &hf_ssh_mac_algorithms_client_to_server_length,
1357 { "mac_algorithms_client_to_server length", "ssh.mac_algorithms_client_to_server_length",
1358 FT_UINT32, BASE_DEC, NULL, 0x0,
1359 "SSH mac_algorithms_client_to_server length", HFILL }},
1361 { &hf_ssh_mac_algorithms_server_to_client_length,
1362 { "mac_algorithms_server_to_client length", "ssh.mac_algorithms_server_to_client_length",
1363 FT_UINT32, BASE_DEC, NULL, 0x0,
1364 "SSH mac_algorithms_server_to_client length", HFILL }},
1366 { &hf_ssh_compression_algorithms_client_to_server_length,
1367 { "compression_algorithms_client_to_server length", "ssh.compression_algorithms_client_to_server_length",
1368 FT_UINT32, BASE_DEC, NULL, 0x0,
1369 "SSH compression_algorithms_client_to_server length", HFILL }},
1371 { &hf_ssh_compression_algorithms_server_to_client_length,
1372 { "compression_algorithms_server_to_client length", "ssh.compression_algorithms_server_to_client_length",
1373 FT_UINT32, BASE_DEC, NULL, 0x0,
1374 "SSH compression_algorithms_server_to_client length", HFILL }},
1376 { &hf_ssh_languages_client_to_server_length,
1377 { "languages_client_to_server length", "ssh.languages_client_to_server_length",
1378 FT_UINT32, BASE_DEC, NULL, 0x0,
1379 "SSH languages_client_to_server length", HFILL }},
1381 { &hf_ssh_languages_server_to_client_length,
1382 { "languages_server_to_client length", "ssh.languages_server_to_client_length",
1383 FT_UINT32, BASE_DEC, NULL, 0x0,
1384 "SSH languages_server_to_client length", HFILL }},
1387 static gint *ett[] = {
1395 static ei_register_info ei[] = {
1396 { &ei_ssh_packet_length, { "ssh.packet_length.error", PI_PROTOCOL, PI_WARN, "Overly large number", EXPFILL }},
1399 module_t *ssh_module;
1400 expert_module_t *expert_ssh;
1402 proto_ssh = proto_register_protocol("SSH Protocol", "SSH", "ssh");
1403 proto_register_field_array(proto_ssh, hf, array_length(hf));
1404 proto_register_subtree_array(ett, array_length(ett));
1405 expert_ssh = expert_register_protocol(proto_ssh);
1406 expert_register_field_array(expert_ssh, ei, array_length(ei));
1408 ssh_module = prefs_register_protocol(proto_ssh, NULL);
1409 prefs_register_bool_preference(ssh_module, "desegment_buffers",
1410 "Reassemble SSH buffers spanning multiple TCP segments",
1411 "Whether the SSH dissector should reassemble SSH buffers spanning multiple TCP segments. "
1412 "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
1415 ssh_handle = register_dissector("ssh", dissect_ssh, proto_ssh);
1419 proto_reg_handoff_ssh(void)
1421 dissector_add_uint("tcp.port", TCP_PORT_SSH, ssh_handle);
1422 dissector_add_uint("sctp.port", SCTP_PORT_SSH, ssh_handle);
1423 dissector_add_uint("sctp.ppi", SSH_PAYLOAD_PROTOCOL_ID, ssh_handle);
1427 * Editor modelines - http://www.wireshark.org/tools/modelines.html
1432 * indent-tabs-mode: t
1435 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1436 * :indentSize=8:tabSize=8:noTabs=false: