HACK: 2nd try to match RowsetProperties
[wireshark-wip.git] / epan / dissectors / packet-ssh.c
blobc650721e114889bd522b27cb691beda0a90f71e0
1 /* packet-ssh.c
2 * Routines for ssh packet dissection
4 * Huagang XIE <huagang@intruvert.com>
5 * Kees Cook <kees@outflux.net>
7 * $Id$
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * Copied from packet-mysql.c
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 * Note: support SSH v1 and v2 now.
34 /* SSH version 2 is defined in:
36 * RFC 4250: The Secure Shell (SSH) Protocol Assigned Numbers
37 * RFC 4251: The Secure Shell (SSH) Protocol Architecture
38 * RFC 4252: The Secure Shell (SSH) Authentication Protocol
39 * RFC 4253: The Secure Shell (SSH) Transport Layer Protocol
40 * RFC 4254: The Secure Shell (SSH) Connection Protocol
42 * SSH versions under 2 were never officially standardized.
44 * Diffie-Hellman Group Exchange is defined in:
46 * RFC 4419: Diffie-Hellman Group Exchange for
47 * the Secure Shell (SSH) Transport Layer Protocol
50 /* "SSH" prefixes are for version 2, whereas "SSH1" is for version 1 */
52 #include "config.h"
54 #include <glib.h>
56 #include <epan/packet.h>
57 #include <epan/exceptions.h>
58 #include <epan/conversation.h>
59 #include <epan/wmem/wmem.h>
60 #include <epan/sctpppids.h>
61 #include <epan/prefs.h>
62 #include <epan/expert.h>
64 #include "packet-tcp.h"
66 /* SSH Version 1 definition , from openssh ssh1.h */
67 #define SSH1_MSG_NONE 0 /* no message */
68 #define SSH1_MSG_DISCONNECT 1 /* cause (string) */
69 #define SSH1_SMSG_PUBLIC_KEY 2 /* ck,msk,srvk,hostk */
70 #define SSH1_CMSG_SESSION_KEY 3 /* key (BIGNUM) */
71 #define SSH1_CMSG_USER 4 /* user (string) */
74 #define SSH_VERSION_UNKNOWN 0
75 #define SSH_VERSION_1 1
76 #define SSH_VERSION_2 2
78 /* proto data */
80 struct ssh_peer_data {
81 guint counter;
83 guint32 frame_version_start;
84 guint32 frame_version_end;
86 guint32 frame_key_start;
87 guint32 frame_key_end;
89 gchar* kex_proposal;
91 /* For all subsequent proposals,
92 [0] is client-to-server and [1] is server-to-client. */
93 #define CLIENT_TO_SERVER_PROPOSAL 0
94 #define SERVER_TO_CLIENT_PROPOSAL 1
96 gchar* mac_proposals[2];
97 gchar* mac;
98 gint mac_length;
100 gchar* enc_proposals[2];
101 gchar* enc;
103 gchar* comp_proposals[2];
104 gchar* comp;
107 struct ssh_flow_data {
108 guint version;
110 gchar* kex;
111 int (*kex_specific_dissector)(guint8 msg_code, tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree);
113 /* [0] is client's, [1] is server's */
114 #define CLIENT_PEER_DATA 0
115 #define SERVER_PEER_DATA 1
116 struct ssh_peer_data peer_data[2];
119 static int proto_ssh = -1;
120 static int hf_ssh_packet_length= -1;
121 static int hf_ssh_padding_length= -1;
122 static int hf_ssh_payload= -1;
123 static int hf_ssh_protocol= -1;
124 static int hf_ssh_dh_gex_min= -1;
125 static int hf_ssh_dh_gex_nbits= -1;
126 static int hf_ssh_dh_gex_max= -1;
127 static int hf_ssh_encrypted_packet= -1;
128 static int hf_ssh_padding_string= -1;
129 static int hf_ssh_mac_string= -1;
130 static int hf_ssh_msg_code = -1;
131 static int hf_ssh2_msg_code = -1;
132 static int hf_ssh2_kex_dh_msg_code = -1;
133 static int hf_ssh2_kex_dh_gex_msg_code = -1;
134 static int hf_ssh_cookie = -1;
135 static int hf_ssh_mpint_g= -1;
136 static int hf_ssh_mpint_p= -1;
137 static int hf_ssh_mpint_e= -1;
138 static int hf_ssh_mpint_f= -1;
139 static int hf_ssh_mpint_length= -1;
140 static int hf_ssh_kexdh_host_key= -1;
141 static int hf_ssh_kexdh_host_key_length= -1;
142 static int hf_ssh_kexdh_h_sig= -1;
143 static int hf_ssh_kexdh_h_sig_length= -1;
144 static int hf_ssh_kex_algorithms = -1;
145 static int hf_ssh_server_host_key_algorithms = -1;
146 static int hf_ssh_encryption_algorithms_client_to_server = -1;
147 static int hf_ssh_encryption_algorithms_server_to_client = -1;
148 static int hf_ssh_mac_algorithms_client_to_server=-1;
149 static int hf_ssh_mac_algorithms_server_to_client=-1;
150 static int hf_ssh_compression_algorithms_client_to_server=-1;
151 static int hf_ssh_compression_algorithms_server_to_client=-1;
152 static int hf_ssh_languages_client_to_server=-1;
153 static int hf_ssh_languages_server_to_client=-1;
154 static int hf_ssh_kex_algorithms_length= -1;
155 static int hf_ssh_server_host_key_algorithms_length= -1;
156 static int hf_ssh_encryption_algorithms_client_to_server_length= -1;
157 static int hf_ssh_encryption_algorithms_server_to_client_length= -1;
158 static int hf_ssh_mac_algorithms_client_to_server_length= -1;
159 static int hf_ssh_mac_algorithms_server_to_client_length= -1;
160 static int hf_ssh_compression_algorithms_client_to_server_length= -1;
161 static int hf_ssh_compression_algorithms_server_to_client_length= -1;
162 static int hf_ssh_languages_client_to_server_length= -1;
163 static int hf_ssh_languages_server_to_client_length= -1;
164 static int hf_ssh_kex_first_packet_follows = -1;
165 static int hf_ssh_kex_reserved = -1;
167 static gint ett_ssh = -1;
168 static gint ett_key_exchange = -1;
169 static gint ett_key_init = -1;
170 static gint ett_ssh1 = -1;
171 static gint ett_ssh2 = -1;
173 static expert_field ei_ssh_packet_length = EI_INIT;
175 static gboolean ssh_desegment = TRUE;
177 #define TCP_PORT_SSH 22
178 #define SCTP_PORT_SSH 22
180 /* Message Numbers (from RFC 4250) (1-255) */
182 /* Transport layer protocol: generic (1-19) */
183 #define SSH_MSG_DISCONNECT 1
184 #define SSH_MSG_IGNORE 2
185 #define SSH_MSG_UNIMPLEMENTED 3
186 #define SSH_MSG_DEBUG 4
187 #define SSH_MSG_SERVICE_REQUEST 5
188 #define SSH_MSG_SERVICE_ACCEPT 6
190 /* Transport layer protocol: Algorithm negotiation (20-29) */
191 #define SSH_MSG_KEXINIT 20
192 #define SSH_MSG_NEWKEYS 21
194 /* Transport layer: Key exchange method specific (reusable) (30-49) */
195 #define SSH_MSG_KEXDH_INIT 30
196 #define SSH_MSG_KEXDH_REPLY 31
198 #define SSH_MSG_KEX_DH_GEX_REQUEST_OLD 30
199 #define SSH_MSG_KEX_DH_GEX_GROUP 31
200 #define SSH_MSG_KEX_DH_GEX_INIT 32
201 #define SSH_MSG_KEX_DH_GEX_REPLY 33
202 #define SSH_MSG_KEX_DH_GEX_REQUEST 34
204 /* User authentication protocol: generic (50-59) */
205 #define SSH_MSG_USERAUTH_REQUEST 50
206 #define SSH_MSG_USERAUTH_FAILURE 51
207 #define SSH_MSG_USERAUTH_SUCCESS 52
208 #define SSH_MSG_USERAUTH_BANNER 53
210 /* User authentication protocol: method specific (reusable) (50-79) */
212 /* Connection protocol: generic (80-89) */
213 #define SSH_MSG_GLOBAL_REQUEST 80
214 #define SSH_MSG_REQUEST_SUCCESS 81
215 #define SSH_MSG_REQUEST_FAILURE 82
217 /* Connection protocol: channel related messages (90-127) */
218 #define SSH_MSG_CHANNEL_OPEN 90
219 #define SSH_MSG_CHANNEL_OPEN_CONFIRMATION 91
220 #define SSH_MSG_CHANNEL_OPEN_FAILURE 92
221 #define SSH_MSG_CHANNEL_WINDOW_ADJUST 93
222 #define SSH_MSG_CHANNEL_DATA 94
223 #define SSH_MSG_CHANNEL_EXTENDED_DATA 95
224 #define SSH_MSG_CHANNEL_EOF 96
225 #define SSH_MSG_CHANNEL_CLOSE 97
226 #define SSH_MSG_CHANNEL_REQUEST 98
227 #define SSH_MSG_CHANNEL_SUCCESS 99
228 #define SSH_MSG_CHANNEL_FAILURE 100
230 /* 128-191 reserved for client protocols */
231 /* 192-255 local extensions */
233 static const value_string ssh2_msg_vals[] = {
234 { SSH_MSG_DISCONNECT, "Disconnect" },
235 { SSH_MSG_IGNORE, "Ignore" },
236 { SSH_MSG_UNIMPLEMENTED, "Unimplemented" },
237 { SSH_MSG_DEBUG, "Debug" },
238 { SSH_MSG_SERVICE_REQUEST, "Service Request" },
239 { SSH_MSG_SERVICE_ACCEPT, "Service Accept" },
240 { SSH_MSG_KEXINIT, "Key Exchange Init" },
241 { SSH_MSG_NEWKEYS, "New Keys" },
242 { SSH_MSG_USERAUTH_REQUEST, "User Authentication Request" },
243 { SSH_MSG_USERAUTH_FAILURE, "User Authentication Failure" },
244 { SSH_MSG_USERAUTH_SUCCESS, "User Authentication Success" },
245 { SSH_MSG_USERAUTH_BANNER, "User Authentication Banner" },
246 { SSH_MSG_GLOBAL_REQUEST, "Global Request" },
247 { SSH_MSG_REQUEST_SUCCESS, "Request Success" },
248 { SSH_MSG_REQUEST_FAILURE, "Request Failure" },
249 { SSH_MSG_CHANNEL_OPEN, "Channel Open" },
250 { SSH_MSG_CHANNEL_OPEN_CONFIRMATION, "Channel Open Confirmation" },
251 { SSH_MSG_CHANNEL_OPEN_FAILURE, "Channel Open Failure" },
252 { SSH_MSG_CHANNEL_WINDOW_ADJUST, "Window Adjust" },
253 { SSH_MSG_CHANNEL_DATA, "Channel Data" },
254 { SSH_MSG_CHANNEL_EXTENDED_DATA, "Channel Extended Data" },
255 { SSH_MSG_CHANNEL_EOF, "Channel EOF" },
256 { SSH_MSG_CHANNEL_CLOSE, "Channel Close" },
257 { SSH_MSG_CHANNEL_REQUEST, "Channel Request" },
258 { SSH_MSG_CHANNEL_SUCCESS, "Channel Success" },
259 { SSH_MSG_CHANNEL_FAILURE, "Channel Failure" },
260 { 0, NULL }
263 static const value_string ssh2_kex_dh_msg_vals[] = {
264 { SSH_MSG_KEXDH_INIT, "Diffie-Hellman Key Exchange Init" },
265 { SSH_MSG_KEXDH_REPLY, "Diffie-Hellman Key Exchange Reply" },
266 { 0, NULL }
269 static const value_string ssh2_kex_dh_gex_msg_vals[] = {
270 { SSH_MSG_KEX_DH_GEX_REQUEST_OLD, "Diffie-Hellman Group Exchange Request (Old)" },
271 { SSH_MSG_KEX_DH_GEX_GROUP, "Diffie-Hellman Group Exchange Group" },
272 { SSH_MSG_KEX_DH_GEX_INIT, "Diffie-Hellman Group Exchange Init" },
273 { SSH_MSG_KEX_DH_GEX_REPLY, "Diffie-Hellman Group Exchange Reply" },
274 { SSH_MSG_KEX_DH_GEX_REQUEST, "Diffie-Hellman Group Exchange Request" },
275 { 0, NULL }
278 static const value_string ssh1_msg_vals[] = {
279 {SSH1_MSG_NONE, "No Message"},
280 {SSH1_MSG_DISCONNECT, "Disconnect"},
281 {SSH1_SMSG_PUBLIC_KEY, "Public Key"},
282 {SSH1_CMSG_SESSION_KEY, "Session Key"},
283 {SSH1_CMSG_USER, "User"},
284 {0, NULL}
287 static int ssh_dissect_key_init(tvbuff_t *tvb, int offset, proto_tree *tree,
288 int is_response,
289 struct ssh_flow_data *global_data);
290 static int ssh_dissect_proposal(tvbuff_t *tvb, int offset, proto_tree *tree,
291 int hf_index_length, int hf_index_value, gchar **store);
292 static int ssh_dissect_ssh1(tvbuff_t *tvb, packet_info *pinfo,
293 struct ssh_flow_data *global_data,
294 int offset, proto_tree *tree, int is_response,
295 gboolean *need_desegmentation);
296 static int ssh_dissect_ssh2(tvbuff_t *tvb, packet_info *pinfo,
297 struct ssh_flow_data *global_data,
298 int offset, proto_tree *tree, int is_response,
299 gboolean *need_desegmentation);
300 static int ssh_dissect_key_exchange(tvbuff_t *tvb, packet_info *pinfo,
301 struct ssh_flow_data *global_data,
302 int offset, proto_tree *tree, int is_response,
303 gboolean *need_desegmentation);
304 static int ssh_dissect_kex_dh(guint8 msg_code, tvbuff_t *tvb,
305 packet_info *pinfo, int offset, proto_tree *tree);
306 static int ssh_dissect_kex_dh_gex(guint8 msg_code, tvbuff_t *tvb,
307 packet_info *pinfo, int offset, proto_tree *tree);
308 static int ssh_dissect_protocol(tvbuff_t *tvb, packet_info *pinfo,
309 struct ssh_flow_data *global_data,
310 int offset, proto_tree *tree, int is_response, guint *version,
311 gboolean *need_desegmentation);
312 static int ssh_dissect_encrypted_packet(tvbuff_t *tvb, packet_info *pinfo,
313 struct ssh_peer_data *peer_data,
314 int offset, proto_tree *tree);
315 static proto_item *ssh_proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
316 gint start, gint length, guint encoding);
317 static void ssh_choose_algo(gchar *client, gchar *server, gchar **result);
318 static void ssh_set_mac_length(struct ssh_peer_data *peer_data);
319 static void ssh_set_kex_specific_dissector(struct ssh_flow_data *global_data);
322 static void
323 dissect_ssh(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
326 proto_tree *ssh_tree = NULL;
327 proto_item *ti;
328 conversation_t *conversation;
329 int last_offset, offset = 0;
331 gboolean is_response = (pinfo->destport != pinfo->match_uint),
332 need_desegmentation;
333 guint version;
335 struct ssh_flow_data *global_data=NULL;
336 struct ssh_peer_data *peer_data;
338 conversation = find_or_create_conversation(pinfo);
340 global_data = (struct ssh_flow_data *)conversation_get_proto_data(conversation, proto_ssh);
341 if (!global_data) {
342 global_data = (struct ssh_flow_data *)wmem_alloc0(wmem_file_scope(), sizeof(struct ssh_flow_data));
343 global_data->version=SSH_VERSION_UNKNOWN;
344 global_data->kex_specific_dissector=ssh_dissect_kex_dh;
345 global_data->peer_data[CLIENT_PEER_DATA].mac_length=-1;
346 global_data->peer_data[SERVER_PEER_DATA].mac_length=-1;
348 conversation_add_proto_data(conversation, proto_ssh, global_data);
351 peer_data = &global_data->peer_data[is_response];
353 if (tree) {
354 ti = proto_tree_add_item(tree, proto_ssh, tvb, offset, -1, ENC_NA);
355 ssh_tree = proto_item_add_subtree(ti, ett_ssh);
358 version = global_data->version;
360 switch(version) {
361 case SSH_VERSION_UNKNOWN:
362 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSH");
363 break;
364 case SSH_VERSION_1:
365 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSHv1");
366 break;
367 case SSH_VERSION_2:
368 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSHv2");
369 break;
373 col_clear(pinfo->cinfo, COL_INFO);
375 while(tvb_reported_length_remaining(tvb, offset)> 0) {
376 gboolean after_version_start = (peer_data->frame_version_start == 0 ||
377 pinfo->fd->num >= peer_data->frame_version_start);
378 gboolean before_version_end = (peer_data->frame_version_end == 0 ||
379 pinfo->fd->num <= peer_data->frame_version_end);
381 need_desegmentation = FALSE;
382 last_offset = offset;
384 peer_data->counter++;
386 if (after_version_start && before_version_end &&
387 (tvb_strncaseeql(tvb, offset, "SSH-", 4) == 0)) {
388 if (peer_data->frame_version_start == 0)
389 peer_data->frame_version_start = pinfo->fd->num;
391 offset = ssh_dissect_protocol(tvb, pinfo,
392 global_data,
393 offset, ssh_tree, is_response,
394 &version, &need_desegmentation);
396 if (!need_desegmentation) {
397 peer_data->frame_version_end = pinfo->fd->num;
398 global_data->version = version;
400 } else {
401 switch(version) {
403 case SSH_VERSION_UNKNOWN:
404 offset = ssh_dissect_encrypted_packet(tvb, pinfo,
405 &global_data->peer_data[is_response], offset, ssh_tree);
406 break;
408 case SSH_VERSION_1:
409 offset = ssh_dissect_ssh1(tvb, pinfo, global_data,
410 offset, ssh_tree, is_response,
411 &need_desegmentation);
412 break;
414 case SSH_VERSION_2:
415 offset = ssh_dissect_ssh2(tvb, pinfo, global_data,
416 offset, ssh_tree, is_response,
417 &need_desegmentation);
418 break;
422 if (need_desegmentation)
423 return;
424 if (offset <= last_offset)
425 THROW(ReportedBoundsError);
428 col_prepend_fstr(pinfo->cinfo, COL_INFO, "%s: ", is_response ? "Server" : "Client");
431 static int
432 ssh_dissect_ssh2(tvbuff_t *tvb, packet_info *pinfo,
433 struct ssh_flow_data *global_data,
434 int offset, proto_tree *tree, int is_response,
435 gboolean *need_desegmentation)
437 proto_item *ti;
438 proto_item *ssh2_tree=NULL;
440 struct ssh_peer_data *peer_data = &global_data->peer_data[is_response];
442 if (tree) {
443 wmem_strbuf_t *title=wmem_strbuf_new(wmem_packet_scope(), "SSH Version 2");
445 if (peer_data->enc || peer_data->mac || peer_data->comp) {
446 wmem_strbuf_append_printf(title, " (");
447 if (peer_data->enc)
448 wmem_strbuf_append_printf(title, "encryption:%s%s",
449 peer_data->enc,
450 peer_data->mac || peer_data->comp
451 ? " " : "");
452 if (peer_data->mac)
453 wmem_strbuf_append_printf(title, "mac:%s%s",
454 peer_data->mac,
455 peer_data->comp ? " " : "");
456 if (peer_data->comp)
457 wmem_strbuf_append_printf(title, "compression:%s",
458 peer_data->comp);
459 wmem_strbuf_append_printf(title, ")");
462 ti=proto_tree_add_text(tree, tvb, offset, -1, "%s", wmem_strbuf_get_str(title));
463 ssh2_tree = proto_item_add_subtree(ti, ett_ssh2);
466 if ((peer_data->frame_key_start == 0) ||
467 ((peer_data->frame_key_start <= pinfo->fd->num) &&
468 ((peer_data->frame_key_end == 0) || (pinfo->fd->num <= peer_data->frame_key_end)))) {
469 offset = ssh_dissect_key_exchange(tvb, pinfo, global_data,
470 offset, ssh2_tree, is_response,
471 need_desegmentation);
472 } else {
473 offset = ssh_dissect_encrypted_packet(tvb, pinfo,
474 &global_data->peer_data[is_response], offset, ssh2_tree);
477 return offset;
479 static int
480 ssh_dissect_ssh1(tvbuff_t *tvb, packet_info *pinfo,
481 struct ssh_flow_data *global_data,
482 int offset, proto_tree *tree, int is_response,
483 gboolean *need_desegmentation)
485 guint plen, padding_length, len;
486 guint8 msg_code;
487 guint remain_length;
489 proto_item *ti;
490 proto_item *ssh1_tree =NULL;
492 struct ssh_peer_data *peer_data = &global_data->peer_data[is_response];
494 if (tree) {
495 ti=proto_tree_add_text(tree, tvb, offset, -1, "SSH Version 1");
496 ssh1_tree = proto_item_add_subtree(ti, ett_ssh1);
500 * We use "tvb_ensure_length_remaining()" to make sure there
501 * actually *is* data remaining.
503 * This means we're guaranteed that "remain_length" is positive.
505 remain_length = tvb_ensure_length_remaining(tvb, offset);
507 * Can we do reassembly?
509 if (ssh_desegment && pinfo->can_desegment) {
511 * Yes - would an SSH header starting at this offset be split
512 * across segment boundaries?
514 if (remain_length < 4) {
516 * Yes. Tell the TCP dissector where the data for
517 * this message starts in the data it handed us and
518 * that we need "some more data." Don't tell it
519 * exactly how many bytes we need because if/when we
520 * ask for even more (after the header) that will
521 * break reassembly.
523 pinfo->desegment_offset = offset;
524 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
525 *need_desegmentation = TRUE;
526 return offset;
529 plen = tvb_get_ntohl(tvb, offset) ;
530 padding_length = 8 - plen%8;
533 if (ssh_desegment && pinfo->can_desegment) {
534 if (plen+4+padding_length > remain_length) {
535 pinfo->desegment_offset = offset;
536 pinfo->desegment_len = plen+padding_length - remain_length;
537 *need_desegmentation = TRUE;
538 return offset;
542 if (plen >= 0xffff) {
543 if (ssh1_tree && plen > 0) {
544 proto_tree_add_uint_format(ssh1_tree, hf_ssh_packet_length, tvb,
545 offset, 4, plen, "Overly large length %x", plen);
547 plen = remain_length-4-padding_length;
548 } else {
549 if (ssh1_tree && plen > 0) {
550 proto_tree_add_uint(ssh1_tree, hf_ssh_packet_length, tvb,
551 offset, 4, plen);
554 offset+=4;
555 /* padding length */
557 if (tree) {
558 proto_tree_add_uint(ssh1_tree, hf_ssh_padding_length, tvb,
559 offset, padding_length, padding_length);
561 offset += padding_length;
563 /* msg_code */
564 if ((peer_data->frame_key_start == 0) ||
565 ((peer_data->frame_key_start >= pinfo->fd->num) && (pinfo->fd->num <= peer_data->frame_key_end))) {
566 msg_code = tvb_get_guint8(tvb, offset);
568 proto_tree_add_item(ssh1_tree, hf_ssh_msg_code, tvb, offset, 1, ENC_NA);
569 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
570 val_to_str(msg_code, ssh1_msg_vals, "Unknown (%u)"));
571 offset += 1;
572 len = plen -1;
573 if (!pinfo->fd->flags.visited) {
574 if (peer_data->frame_key_start == 0)
575 peer_data->frame_key_start = pinfo->fd->num;
576 peer_data->frame_key_end = pinfo->fd->num;
578 } else {
579 len = plen;
580 col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Encrypted packet (len=%d)", len);
582 /* payload */
583 if (ssh1_tree) {
584 ssh_proto_tree_add_item(ssh1_tree, hf_ssh_payload,
585 tvb, offset, len, ENC_NA);
587 offset+=len;
589 return offset;
592 static int
593 ssh_tree_add_mpint(tvbuff_t *tvb, int offset, proto_tree *tree,
594 int hf_ssh_mpint_selection)
596 guint len = tvb_get_ntohl(tvb, offset);
597 if (tree) {
598 proto_tree_add_uint(tree, hf_ssh_mpint_length, tvb,
599 offset, 4, len);
601 offset+=4;
602 if (tree) {
603 ssh_proto_tree_add_item(tree, hf_ssh_mpint_selection,
604 tvb, offset, len, ENC_NA);
606 return 4+len;
609 static int
610 ssh_tree_add_string(tvbuff_t *tvb, int offset, proto_tree *tree,
611 int hf_ssh_string, int hf_ssh_string_length)
613 guint len = tvb_get_ntohl(tvb, offset);
614 if (tree) {
615 proto_tree_add_uint(tree, hf_ssh_string_length, tvb,
616 offset, 4, len);
618 offset+=4;
619 if (tree) {
620 ssh_proto_tree_add_item(tree, hf_ssh_string,
621 tvb, offset, len, ENC_NA);
623 return 4+len;
626 static int
627 ssh_dissect_key_exchange(tvbuff_t *tvb, packet_info *pinfo,
628 struct ssh_flow_data *global_data,
629 int offset, proto_tree *tree, int is_response,
630 gboolean *need_desegmentation)
632 guint plen, len;
633 guint8 padding_length;
634 guint remain_length;
635 int last_offset=offset;
636 guint msg_code;
638 proto_item *tf, *ti;
639 proto_item *key_ex_tree =NULL;
641 struct ssh_peer_data *peer_data = &global_data->peer_data[is_response];
644 * We use "tvb_ensure_length_remaining()" to make sure there
645 * actually *is* data remaining.
647 * This means we're guaranteed that "remain_length" is positive.
649 remain_length = tvb_ensure_length_remaining(tvb, offset);
651 * Can we do reassembly?
653 if (ssh_desegment && pinfo->can_desegment) {
655 * Yes - would an SSH header starting at this offset
656 * be split across segment boundaries?
658 if (remain_length < 4) {
660 * Yes. Tell the TCP dissector where the data for
661 * this message starts in the data it handed us and
662 * that we need "some more data." Don't tell it
663 * exactly how many bytes we need because if/when we
664 * ask for even more (after the header) that will
665 * break reassembly.
667 pinfo->desegment_offset = offset;
668 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
669 *need_desegmentation = TRUE;
670 return offset;
673 plen = tvb_get_ntohl(tvb, offset) ;
675 if (ssh_desegment && pinfo->can_desegment) {
676 if (plen +4 > remain_length) {
677 pinfo->desegment_offset = offset;
678 pinfo->desegment_len = plen+4 - remain_length;
679 *need_desegmentation = TRUE;
680 return offset;
684 * Need to check plen > 0x80000000 here
687 ti = proto_tree_add_uint(tree, hf_ssh_packet_length, tvb,
688 offset, 4, plen);
689 if (plen >= 0xffff) {
690 expert_add_info_format(pinfo, ti, &ei_ssh_packet_length, "Overly large number %d", plen);
691 plen = remain_length-4;
693 offset+=4;
695 /* padding length */
696 padding_length = tvb_get_guint8(tvb, offset);
697 proto_tree_add_uint(tree, hf_ssh_padding_length, tvb, offset, 1, padding_length);
698 offset += 1;
700 tf=proto_tree_add_text(tree, tvb, offset, -1, "Key Exchange");
701 key_ex_tree = proto_item_add_subtree(tf, ett_key_exchange);
703 /* msg_code */
704 msg_code = tvb_get_guint8(tvb, offset);
706 if (msg_code >= 30 && msg_code < 40) {
707 offset = global_data->kex_specific_dissector(msg_code, tvb, pinfo, offset, key_ex_tree);
708 } else {
709 proto_tree_add_item(key_ex_tree, hf_ssh2_msg_code, tvb, offset, 1, ENC_NA);
710 offset += 1;
712 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
713 val_to_str(msg_code, ssh2_msg_vals, "Unknown (%u)"));
715 /* 16 bytes cookie */
716 switch(msg_code)
718 case SSH_MSG_KEXINIT:
719 if ((peer_data->frame_key_start == 0) || (peer_data->frame_key_start == pinfo->fd->num)) {
720 offset = ssh_dissect_key_init(tvb, offset, key_ex_tree, is_response, global_data);
721 peer_data->frame_key_start = pinfo->fd->num;
723 break;
724 case SSH_MSG_NEWKEYS:
725 if (peer_data->frame_key_end == 0) {
726 peer_data->frame_key_end = pinfo->fd->num;
727 ssh_choose_algo(global_data->peer_data[CLIENT_PEER_DATA].mac_proposals[is_response],
728 global_data->peer_data[SERVER_PEER_DATA].mac_proposals[is_response],
729 &peer_data->mac);
730 ssh_set_mac_length(peer_data);
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],
733 &peer_data->enc);
734 ssh_choose_algo(global_data->peer_data[CLIENT_PEER_DATA].comp_proposals[is_response],
735 global_data->peer_data[SERVER_PEER_DATA].comp_proposals[is_response],
736 &peer_data->comp);
738 break;
742 len = plen+4-padding_length-(offset-last_offset);
743 ssh_proto_tree_add_item(key_ex_tree, hf_ssh_payload, tvb, offset, len, ENC_NA);
744 offset +=len;
746 /* padding */
747 ssh_proto_tree_add_item(key_ex_tree, hf_ssh_padding_string, tvb, offset, padding_length, ENC_NA);
748 offset+= padding_length;
750 return offset;
753 static int ssh_dissect_kex_dh(guint8 msg_code, tvbuff_t *tvb,
754 packet_info *pinfo, int offset, proto_tree *tree)
756 proto_tree_add_item(tree, hf_ssh2_kex_dh_msg_code, tvb, offset, 1, ENC_NA);
757 offset += 1;
759 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
760 val_to_str(msg_code, ssh2_kex_dh_msg_vals, "Unknown (%u)"));
762 switch (msg_code) {
763 case SSH_MSG_KEXDH_INIT:
764 offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_e);
765 break;
767 case SSH_MSG_KEXDH_REPLY:
768 offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_kexdh_host_key, hf_ssh_kexdh_host_key_length);
769 offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_f);
770 offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_kexdh_h_sig, hf_ssh_kexdh_h_sig_length);
771 break;
774 return offset;
777 static int ssh_dissect_kex_dh_gex(guint8 msg_code, tvbuff_t *tvb,
778 packet_info *pinfo, int offset, proto_tree *tree)
780 proto_tree_add_item(tree, hf_ssh2_kex_dh_gex_msg_code, tvb, offset, 1, ENC_NA);
781 offset += 1;
783 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
784 val_to_str(msg_code, ssh2_kex_dh_gex_msg_vals, "Unknown (%u)"));
786 switch (msg_code) {
787 case SSH_MSG_KEX_DH_GEX_REQUEST_OLD:
788 ssh_proto_tree_add_item(tree, hf_ssh_dh_gex_nbits, tvb, offset, 4, ENC_BIG_ENDIAN);
789 offset += 4;
790 break;
792 case SSH_MSG_KEX_DH_GEX_GROUP:
793 offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_p);
794 offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_g);
795 break;
797 case SSH_MSG_KEX_DH_GEX_INIT:
798 offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_e);
799 break;
801 case SSH_MSG_KEX_DH_GEX_REPLY:
802 offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_kexdh_host_key, hf_ssh_kexdh_host_key_length);
803 offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_mpint_f);
804 offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_kexdh_h_sig, hf_ssh_kexdh_h_sig_length);
805 break;
807 case SSH_MSG_KEX_DH_GEX_REQUEST:
808 ssh_proto_tree_add_item(tree, hf_ssh_dh_gex_min, tvb, offset, 4, ENC_BIG_ENDIAN);
809 offset += 4;
810 ssh_proto_tree_add_item(tree, hf_ssh_dh_gex_nbits, tvb, offset, 4, ENC_BIG_ENDIAN);
811 offset += 4;
812 ssh_proto_tree_add_item(tree, hf_ssh_dh_gex_max, tvb, offset, 4, ENC_BIG_ENDIAN);
813 offset += 4;
814 break;
817 return offset;
820 static int
821 ssh_dissect_encrypted_packet(tvbuff_t *tvb, packet_info *pinfo,
822 struct ssh_peer_data *peer_data,
823 int offset, proto_tree *tree)
825 gint len;
827 len = tvb_reported_length_remaining(tvb, offset);
828 col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Encrypted packet (len=%d)", len);
830 if (tree) {
831 gint encrypted_len = len;
833 if (peer_data->mac_length>0)
834 encrypted_len -= peer_data->mac_length;
836 ssh_proto_tree_add_item(tree, hf_ssh_encrypted_packet,
837 tvb, offset, encrypted_len, ENC_NA);
839 if (peer_data->mac_length>0)
840 ssh_proto_tree_add_item(tree, hf_ssh_mac_string,
841 tvb, offset+encrypted_len,
842 peer_data->mac_length, ENC_NA);
844 offset+=len;
845 return offset;
848 static int
849 ssh_dissect_protocol(tvbuff_t *tvb, packet_info *pinfo,
850 struct ssh_flow_data *global_data,
851 int offset, proto_tree *tree, int is_response, guint * version,
852 gboolean *need_desegmentation)
854 guint remain_length;
855 gint linelen, protolen;
858 * If the first packet do not contain the banner,
859 * it is dump in the middle of a flow or not a ssh at all
861 if (tvb_strncaseeql(tvb, offset, "SSH-", 4) != 0) {
862 offset = ssh_dissect_encrypted_packet(tvb, pinfo,
863 &global_data->peer_data[is_response], offset, tree);
864 return offset;
867 if (!is_response) {
868 if (tvb_strncaseeql(tvb, offset, "SSH-2.", 6) == 0) {
869 *(version) = SSH_VERSION_2;
870 } else if (tvb_strncaseeql(tvb, offset, "SSH-1.99-", 9) == 0) {
871 *(version) = SSH_VERSION_2;
872 } else if (tvb_strncaseeql(tvb, offset, "SSH-1.", 6) == 0) {
873 *(version) = SSH_VERSION_1;
878 * We use "tvb_ensure_length_remaining()" to make sure there
879 * actually *is* data remaining.
881 * This means we're guaranteed that "remain_length" is positive.
883 remain_length = tvb_ensure_length_remaining(tvb, offset);
884 /*linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
886 linelen = tvb_find_guint8(tvb, offset, -1, '\n');
888 if (ssh_desegment && pinfo->can_desegment) {
889 if (linelen == -1 || remain_length < (guint)linelen-offset) {
890 pinfo->desegment_offset = offset;
891 pinfo->desegment_len = linelen-remain_length;
892 *need_desegmentation = TRUE;
893 return offset;
896 if (linelen == -1) {
897 /* XXX - reassemble across segment boundaries? */
898 linelen = remain_length;
899 protolen = linelen;
900 } else {
901 linelen = linelen - offset + 1;
903 if (linelen > 1 && tvb_get_guint8(tvb, offset + linelen - 2) == '\r')
904 protolen = linelen - 2;
905 else
906 protolen = linelen - 1;
909 col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Protocol (%s)",
910 tvb_format_text(tvb, offset, protolen));
912 ssh_proto_tree_add_item(tree, hf_ssh_protocol,
913 tvb, offset, linelen, ENC_ASCII|ENC_NA);
914 offset+=linelen;
915 return offset;
918 static void
919 ssh_set_mac_length(struct ssh_peer_data *peer_data)
921 char *size_str;
922 guint size=0;
924 char *mac_name = peer_data->mac;
926 if (!mac_name) return;
928 if ((size_str=g_strrstr(mac_name, "-")) && ((size=atoi(size_str+1)))) {
929 peer_data->mac_length = size;
931 else if (strcmp(mac_name, "hmac-sha1") == 0) {
932 peer_data->mac_length = 20;
934 else if (strcmp(mac_name, "hmac-md5") == 0) {
935 peer_data->mac_length = 12;
937 else if (strcmp(mac_name, "none") == 0) {
938 peer_data->mac_length = 0;
942 static void ssh_set_kex_specific_dissector(struct ssh_flow_data *global_data)
944 const char *kex_name = global_data->kex;
946 if (!kex_name) return;
948 if (strcmp(kex_name, "diffie-hellman-group-exchange-sha1") == 0 ||
949 strcmp(kex_name, "diffie-hellman-group-exchange-sha256") == 0)
951 global_data->kex_specific_dissector = ssh_dissect_kex_dh_gex;
955 static gint
956 ssh_gslist_compare_strings(gconstpointer a, gconstpointer b)
958 if (a == NULL && b == NULL)
959 return 0;
960 if (a == NULL)
961 return -1;
962 if (b == NULL)
963 return 1;
964 return strcmp((const char*)a, (const char*)b);
967 /* expects that *result is NULL */
968 static void
969 ssh_choose_algo(gchar *client, gchar *server, gchar **result)
971 gchar **server_strings=NULL;
972 gchar **client_strings=NULL;
973 gchar **step;
974 GSList *server_list = NULL;
976 if (!client || !server || !result || *result)
977 return;
979 server_strings = g_strsplit(server, ",", 0);
980 for (step = server_strings; *step; step++) {
981 server_list = g_slist_append(server_list, *step);
984 client_strings = g_strsplit(client, ",", 0);
985 for (step = client_strings; *step; step++) {
986 GSList *agreed;
987 if ((agreed=g_slist_find_custom(server_list, *step, ssh_gslist_compare_strings))) {
988 *result = wmem_strdup(wmem_file_scope(), (const gchar *)agreed->data);
989 break;
993 g_strfreev(client_strings);
994 g_slist_free(server_list);
995 g_strfreev(server_strings);
998 static int
999 ssh_dissect_key_init(tvbuff_t *tvb, int offset, proto_tree *tree,
1000 int is_response, struct ssh_flow_data *global_data)
1002 int start_offset = offset;
1004 proto_item *tf = NULL;
1005 proto_item *key_init_tree=NULL;
1007 struct ssh_peer_data *peer_data = &global_data->peer_data[is_response];
1009 if (tree) {
1010 tf=proto_tree_add_text(tree, tvb, offset, -1, "Algorithms");
1011 key_init_tree = proto_item_add_subtree(tf, ett_key_init);
1012 proto_tree_add_item(key_init_tree, hf_ssh_cookie,
1013 tvb, offset, 16, ENC_NA);
1015 offset += 16;
1017 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1018 hf_ssh_kex_algorithms_length, hf_ssh_kex_algorithms,
1019 &peer_data->kex_proposal);
1020 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1021 hf_ssh_server_host_key_algorithms_length,
1022 hf_ssh_server_host_key_algorithms, NULL);
1023 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1024 hf_ssh_encryption_algorithms_client_to_server_length,
1025 hf_ssh_encryption_algorithms_client_to_server,
1026 &peer_data->enc_proposals[CLIENT_TO_SERVER_PROPOSAL]);
1027 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1028 hf_ssh_encryption_algorithms_server_to_client_length,
1029 hf_ssh_encryption_algorithms_server_to_client,
1030 &peer_data->enc_proposals[SERVER_TO_CLIENT_PROPOSAL]);
1031 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1032 hf_ssh_mac_algorithms_client_to_server_length,
1033 hf_ssh_mac_algorithms_client_to_server,
1034 &peer_data->mac_proposals[CLIENT_TO_SERVER_PROPOSAL]);
1035 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1036 hf_ssh_mac_algorithms_server_to_client_length,
1037 hf_ssh_mac_algorithms_server_to_client,
1038 &peer_data->mac_proposals[SERVER_TO_CLIENT_PROPOSAL]);
1039 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1040 hf_ssh_compression_algorithms_client_to_server_length,
1041 hf_ssh_compression_algorithms_client_to_server,
1042 &peer_data->comp_proposals[CLIENT_TO_SERVER_PROPOSAL]);
1043 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1044 hf_ssh_compression_algorithms_server_to_client_length,
1045 hf_ssh_compression_algorithms_server_to_client,
1046 &peer_data->comp_proposals[SERVER_TO_CLIENT_PROPOSAL]);
1047 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1048 hf_ssh_languages_client_to_server_length,
1049 hf_ssh_languages_client_to_server, NULL);
1050 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1051 hf_ssh_languages_server_to_client_length,
1052 hf_ssh_languages_server_to_client, NULL);
1054 ssh_proto_tree_add_item(key_init_tree, hf_ssh_kex_first_packet_follows,
1055 tvb, offset, 1, ENC_BIG_ENDIAN);
1056 offset+=1;
1058 ssh_proto_tree_add_item(key_init_tree, hf_ssh_kex_reserved,
1059 tvb, offset, 4, ENC_NA);
1060 offset+=4;
1062 if (global_data->peer_data[CLIENT_PEER_DATA].kex_proposal &&
1063 global_data->peer_data[SERVER_PEER_DATA].kex_proposal &&
1064 !global_data->kex)
1066 /* Note: we're ignoring first_kex_packet_follows. */
1067 ssh_choose_algo(
1068 global_data->peer_data[CLIENT_PEER_DATA].kex_proposal,
1069 global_data->peer_data[SERVER_PEER_DATA].kex_proposal,
1070 &global_data->kex);
1071 ssh_set_kex_specific_dissector(global_data);
1074 if (tf != NULL) {
1075 proto_item_set_len(tf, offset-start_offset);
1078 return offset;
1081 static int
1082 ssh_dissect_proposal(tvbuff_t *tvb, int offset, proto_tree *tree,
1083 int hf_index_length, int hf_index_value, gchar **store)
1085 guint32 len = tvb_get_ntohl(tvb, offset);
1086 proto_tree_add_uint(tree, hf_index_length, tvb, offset, 4, len);
1087 offset += 4;
1089 ssh_proto_tree_add_item(tree, hf_index_value, tvb, offset, len,
1090 ENC_ASCII);
1091 if (store)
1092 *store = tvb_get_string(wmem_file_scope(), tvb, offset, len);
1093 offset += len;
1095 return offset;
1098 static proto_item *
1099 ssh_proto_tree_add_item(proto_tree *tree, int hfindex, tvbuff_t *tvb,
1100 gint start, gint length, guint encoding)
1102 if (tree && length <0xffff && length > 0) {
1103 return proto_tree_add_item(tree, hfindex, tvb, start, length, encoding);
1105 return NULL;
1108 void
1109 proto_register_ssh(void)
1111 static hf_register_info hf[] = {
1112 { &hf_ssh_packet_length,
1113 { "Packet Length", "ssh.packet_length",
1114 FT_UINT32, BASE_DEC, NULL, 0x0,
1115 "SSH packet length", HFILL }},
1117 { &hf_ssh_padding_length,
1118 { "Padding Length", "ssh.padding_length",
1119 FT_UINT8, BASE_DEC, NULL, 0x0,
1120 "SSH Packet Number", HFILL }},
1122 { &hf_ssh_msg_code,
1123 { "Message Code", "ssh.message_code",
1124 FT_UINT8, BASE_DEC, VALS(ssh1_msg_vals), 0x0,
1125 "SSH Message Code", HFILL }},
1127 { &hf_ssh2_msg_code,
1128 { "Message Code", "ssh.message_code",
1129 FT_UINT8, BASE_DEC, VALS(ssh2_msg_vals), 0x0,
1130 "SSH Message Code", HFILL }},
1132 { &hf_ssh2_kex_dh_msg_code,
1133 { "Message Code", "ssh.message_code",
1134 FT_UINT8, BASE_DEC, VALS(ssh2_kex_dh_msg_vals), 0x0,
1135 "SSH Message Code", HFILL }},
1137 { &hf_ssh2_kex_dh_gex_msg_code,
1138 { "Message Code", "ssh.message_code",
1139 FT_UINT8, BASE_DEC, VALS(ssh2_kex_dh_gex_msg_vals), 0x0,
1140 "SSH Message Code", HFILL }},
1142 { &hf_ssh_mpint_g,
1143 { "DH base (G)", "ssh.dh.g",
1144 FT_BYTES, BASE_NONE, NULL, 0x0,
1145 "SSH DH base (G)", HFILL }},
1147 { &hf_ssh_mpint_p,
1148 { "DH modulus (P)", "ssh.dh.p",
1149 FT_BYTES, BASE_NONE, NULL, 0x0,
1150 "SSH DH modulus (P)", HFILL }},
1152 { &hf_ssh_mpint_e,
1153 { "DH client e", "ssh.dh.e",
1154 FT_BYTES, BASE_NONE, NULL, 0x0,
1155 "SSH DH client e", HFILL }},
1157 { &hf_ssh_mpint_f,
1158 { "DH server f", "ssh.dh.f",
1159 FT_BYTES, BASE_NONE, NULL, 0x0,
1160 "SSH DH server f", HFILL }},
1162 { &hf_ssh_mpint_length,
1163 { "Multi Precision Integer Length", "ssh.mpint_length",
1164 FT_UINT32, BASE_DEC, NULL, 0x0,
1165 "SSH mpint length", HFILL }},
1167 { &hf_ssh_kexdh_host_key,
1168 { "KEX DH host key", "ssh.kexdh.host_key",
1169 FT_BYTES, BASE_NONE, NULL, 0x0,
1170 "SSH KEX DH host key", HFILL }},
1172 { &hf_ssh_kexdh_h_sig,
1173 { "KEX DH H signature", "ssh.kexdh.h_sig",
1174 FT_BYTES, BASE_NONE, NULL, 0x0,
1175 "SSH KEX DH H signature", HFILL }},
1177 { &hf_ssh_kexdh_host_key_length,
1178 { "KEX DH host key length", "ssh.kexdh.host_key_length",
1179 FT_UINT32, BASE_DEC, NULL, 0x0,
1180 "SSH KEX DH host key length", HFILL }},
1182 { &hf_ssh_kexdh_h_sig_length,
1183 { "KEX DH H signature length", "ssh.kexdh.h_sig_length",
1184 FT_UINT32, BASE_DEC, NULL, 0x0,
1185 "SSH KEX DH H signature length", HFILL }},
1187 { &hf_ssh_encrypted_packet,
1188 { "Encrypted Packet", "ssh.encrypted_packet",
1189 FT_BYTES, BASE_NONE, NULL, 0x0,
1190 "SSH Protocol Packet", HFILL }},
1192 { &hf_ssh_protocol,
1193 { "Protocol", "ssh.protocol",
1194 FT_STRING, BASE_NONE, NULL, 0x0,
1195 "SSH Protocol", HFILL }},
1197 { &hf_ssh_cookie,
1198 { "Cookie", "ssh.cookie",
1199 FT_BYTES, BASE_NONE, NULL, 0x0,
1200 "SSH Cookie", HFILL }},
1202 { &hf_ssh_kex_first_packet_follows,
1203 { "KEX First Packet Follows", "ssh.kex.first_packet_follows",
1204 FT_UINT8, BASE_DEC, NULL, 0x0,
1205 "SSH KEX Fist Packet Follows", HFILL }},
1207 { &hf_ssh_kex_reserved,
1208 { "Reserved", "ssh.kex.reserved",
1209 FT_BYTES, BASE_NONE, NULL, 0x0,
1210 "SSH Protocol KEX Reserved", HFILL }},
1212 { &hf_ssh_dh_gex_min,
1213 { "DH GEX Min", "ssh.dh_gex.min",
1214 FT_UINT32, BASE_DEC, NULL, 0x0,
1215 "SSH DH GEX Minimum", HFILL }},
1217 { &hf_ssh_dh_gex_nbits,
1218 { "DH GEX Numbers of Bits", "ssh.dh_gex.nbits",
1219 FT_UINT32, BASE_DEC, NULL, 0x0,
1220 "SSH DH GEX Number of Bits", HFILL }},
1222 { &hf_ssh_dh_gex_max,
1223 { "DH GEX Max", "ssh.dh_gex.max",
1224 FT_UINT32, BASE_DEC, NULL, 0x0,
1225 "SSH DH GEX Maximum", HFILL }},
1227 { &hf_ssh_payload,
1228 { "Payload", "ssh.payload",
1229 FT_BYTES, BASE_NONE, NULL, 0x0,
1230 "SSH Payload", HFILL }},
1232 { &hf_ssh_padding_string,
1233 { "Padding String", "ssh.padding_string",
1234 FT_BYTES, BASE_NONE, NULL, 0x0,
1235 "SSH Padding String", HFILL }},
1237 { &hf_ssh_mac_string,
1238 { "MAC", "ssh.mac",
1239 FT_BYTES, BASE_NONE, NULL, 0x0,
1240 "SSH Protocol Packet MAC", HFILL }},
1242 { &hf_ssh_kex_algorithms,
1243 { "kex_algorithms string", "ssh.kex_algorithms",
1244 FT_STRINGZ, BASE_NONE, NULL, 0x0,
1245 "SSH kex_algorithms string", HFILL }},
1247 { &hf_ssh_server_host_key_algorithms,
1248 { "server_host_key_algorithms string", "ssh.server_host_key_algorithms",
1249 FT_STRINGZ, BASE_NONE, NULL, 0x0,
1250 "SSH server_host_key_algorithms string", HFILL }},
1252 { &hf_ssh_encryption_algorithms_client_to_server,
1253 { "encryption_algorithms_client_to_server string", "ssh.encryption_algorithms_client_to_server",
1254 FT_STRINGZ, BASE_NONE, NULL, 0x0,
1255 "SSH encryption_algorithms_client_to_server string", HFILL }},
1257 { &hf_ssh_encryption_algorithms_server_to_client,
1258 { "encryption_algorithms_server_to_client string", "ssh.encryption_algorithms_server_to_client",
1259 FT_STRINGZ, BASE_NONE, NULL, 0x0,
1260 "SSH encryption_algorithms_server_to_client string", HFILL }},
1262 { &hf_ssh_mac_algorithms_client_to_server,
1263 { "mac_algorithms_client_to_server string", "ssh.mac_algorithms_client_to_server",
1264 FT_STRINGZ, BASE_NONE, NULL, 0x0,
1265 "SSH mac_algorithms_client_to_server string", HFILL }},
1267 { &hf_ssh_mac_algorithms_server_to_client,
1268 { "mac_algorithms_server_to_client string", "ssh.mac_algorithms_server_to_client",
1269 FT_STRINGZ, BASE_NONE, NULL, 0x0,
1270 "SSH mac_algorithms_server_to_client string", HFILL }},
1272 { &hf_ssh_compression_algorithms_client_to_server,
1273 { "compression_algorithms_client_to_server string", "ssh.compression_algorithms_client_to_server",
1274 FT_STRINGZ, BASE_NONE, NULL, 0x0,
1275 "SSH compression_algorithms_client_to_server string", HFILL }},
1277 { &hf_ssh_compression_algorithms_server_to_client,
1278 { "compression_algorithms_server_to_client string", "ssh.compression_algorithms_server_to_client",
1279 FT_STRINGZ, BASE_NONE, NULL, 0x0,
1280 "SSH compression_algorithms_server_to_client string", HFILL }},
1282 { &hf_ssh_languages_client_to_server,
1283 { "languages_client_to_server string", "ssh.languages_client_to_server",
1284 FT_STRINGZ, BASE_NONE, NULL, 0x0,
1285 "SSH languages_client_to_server string", HFILL }},
1287 { &hf_ssh_languages_server_to_client,
1288 { "languages_server_to_client string", "ssh.languages_server_to_client",
1289 FT_STRINGZ, BASE_NONE, NULL, 0x0,
1290 "SSH languages_server_to_client string", HFILL }},
1292 { &hf_ssh_kex_algorithms_length,
1293 { "kex_algorithms length", "ssh.kex_algorithms_length",
1294 FT_UINT32, BASE_DEC, NULL, 0x0,
1295 "SSH kex_algorithms length", HFILL }},
1297 { &hf_ssh_server_host_key_algorithms_length,
1298 { "server_host_key_algorithms length", "ssh.server_host_key_algorithms_length",
1299 FT_UINT32, BASE_DEC, NULL, 0x0,
1300 "SSH server_host_key_algorithms length", HFILL }},
1302 { &hf_ssh_encryption_algorithms_client_to_server_length,
1303 { "encryption_algorithms_client_to_server length", "ssh.encryption_algorithms_client_to_server_length",
1304 FT_UINT32, BASE_DEC, NULL, 0x0,
1305 "SSH encryption_algorithms_client_to_server length", HFILL }},
1307 { &hf_ssh_encryption_algorithms_server_to_client_length,
1308 { "encryption_algorithms_server_to_client length", "ssh.encryption_algorithms_server_to_client_length",
1309 FT_UINT32, BASE_DEC, NULL, 0x0,
1310 "SSH encryption_algorithms_server_to_client length", HFILL }},
1312 { &hf_ssh_mac_algorithms_client_to_server_length,
1313 { "mac_algorithms_client_to_server length", "ssh.mac_algorithms_client_to_server_length",
1314 FT_UINT32, BASE_DEC, NULL, 0x0,
1315 "SSH mac_algorithms_client_to_server length", HFILL }},
1317 { &hf_ssh_mac_algorithms_server_to_client_length,
1318 { "mac_algorithms_server_to_client length", "ssh.mac_algorithms_server_to_client_length",
1319 FT_UINT32, BASE_DEC, NULL, 0x0,
1320 "SSH mac_algorithms_server_to_client length", HFILL }},
1322 { &hf_ssh_compression_algorithms_client_to_server_length,
1323 { "compression_algorithms_client_to_server length", "ssh.compression_algorithms_client_to_server_length",
1324 FT_UINT32, BASE_DEC, NULL, 0x0,
1325 "SSH compression_algorithms_client_to_server length", HFILL }},
1327 { &hf_ssh_compression_algorithms_server_to_client_length,
1328 { "compression_algorithms_server_to_client length", "ssh.compression_algorithms_server_to_client_length",
1329 FT_UINT32, BASE_DEC, NULL, 0x0,
1330 "SSH compression_algorithms_server_to_client length", HFILL }},
1332 { &hf_ssh_languages_client_to_server_length,
1333 { "languages_client_to_server length", "ssh.languages_client_to_server_length",
1334 FT_UINT32, BASE_DEC, NULL, 0x0,
1335 "SSH languages_client_to_server length", HFILL }},
1337 { &hf_ssh_languages_server_to_client_length,
1338 { "languages_server_to_client length", "ssh.languages_server_to_client_length",
1339 FT_UINT32, BASE_DEC, NULL, 0x0,
1340 "SSH languages_server_to_client length", HFILL }},
1343 static gint *ett[] = {
1344 &ett_ssh,
1345 &ett_key_exchange,
1346 &ett_ssh1,
1347 &ett_ssh2,
1348 &ett_key_init
1351 static ei_register_info ei[] = {
1352 { &ei_ssh_packet_length, { "ssh.packet_length.error", PI_PROTOCOL, PI_WARN, "Overly large number", EXPFILL }},
1355 module_t *ssh_module;
1356 expert_module_t *expert_ssh;
1358 proto_ssh = proto_register_protocol("SSH Protocol", "SSH", "ssh");
1359 proto_register_field_array(proto_ssh, hf, array_length(hf));
1360 proto_register_subtree_array(ett, array_length(ett));
1361 expert_ssh = expert_register_protocol(proto_ssh);
1362 expert_register_field_array(expert_ssh, ei, array_length(ei));
1364 ssh_module = prefs_register_protocol(proto_ssh, NULL);
1365 prefs_register_bool_preference(ssh_module, "desegment_buffers",
1366 "Reassemble SSH buffers spanning multiple TCP segments",
1367 "Whether the SSH dissector should reassemble SSH buffers spanning multiple TCP segments. "
1368 "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
1369 &ssh_desegment);
1372 void
1373 proto_reg_handoff_ssh(void)
1375 dissector_handle_t ssh_handle;
1377 ssh_handle = create_dissector_handle(dissect_ssh, proto_ssh);
1379 dissector_add_uint("tcp.port", TCP_PORT_SSH, ssh_handle);
1380 dissector_add_uint("sctp.port", SCTP_PORT_SSH, ssh_handle);
1381 dissector_add_uint("sctp.ppi", SSH_PAYLOAD_PROTOCOL_ID, ssh_handle);