2 * Routines for ssh packet dissection
4 * Huagang XIE <huagang@intruvert.com>
5 * Kees Cook <kees@outflux.net>
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 */
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
80 struct ssh_peer_data
{
83 guint32 frame_version_start
;
84 guint32 frame_version_end
;
86 guint32 frame_key_start
;
87 guint32 frame_key_end
;
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];
100 gchar
* enc_proposals
[2];
103 gchar
* comp_proposals
[2];
107 struct ssh_flow_data
{
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" },
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" },
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" },
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"},
287 static int ssh_dissect_key_init(tvbuff_t
*tvb
, int offset
, proto_tree
*tree
,
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
);
323 dissect_ssh(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
326 proto_tree
*ssh_tree
= NULL
;
328 conversation_t
*conversation
;
329 int last_offset
, offset
= 0;
331 gboolean is_response
= (pinfo
->destport
!= pinfo
->match_uint
),
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
);
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
];
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
;
361 case SSH_VERSION_UNKNOWN
:
362 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "SSH");
365 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "SSHv1");
368 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "SSHv2");
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
,
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
;
403 case SSH_VERSION_UNKNOWN
:
404 offset
= ssh_dissect_encrypted_packet(tvb
, pinfo
,
405 &global_data
->peer_data
[is_response
], offset
, ssh_tree
);
409 offset
= ssh_dissect_ssh1(tvb
, pinfo
, global_data
,
410 offset
, ssh_tree
, is_response
,
411 &need_desegmentation
);
415 offset
= ssh_dissect_ssh2(tvb
, pinfo
, global_data
,
416 offset
, ssh_tree
, is_response
,
417 &need_desegmentation
);
422 if (need_desegmentation
)
424 if (offset
<= last_offset
)
425 THROW(ReportedBoundsError
);
428 col_prepend_fstr(pinfo
->cinfo
, COL_INFO
, "%s: ", is_response
? "Server" : "Client");
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
)
438 proto_item
*ssh2_tree
=NULL
;
440 struct ssh_peer_data
*peer_data
= &global_data
->peer_data
[is_response
];
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
, " (");
448 wmem_strbuf_append_printf(title
, "encryption:%s%s",
450 peer_data
->mac
|| peer_data
->comp
453 wmem_strbuf_append_printf(title
, "mac:%s%s",
455 peer_data
->comp
? " " : "");
457 wmem_strbuf_append_printf(title
, "compression:%s",
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
);
473 offset
= ssh_dissect_encrypted_packet(tvb
, pinfo
,
474 &global_data
->peer_data
[is_response
], offset
, ssh2_tree
);
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
;
490 proto_item
*ssh1_tree
=NULL
;
492 struct ssh_peer_data
*peer_data
= &global_data
->peer_data
[is_response
];
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
523 pinfo
->desegment_offset
= offset
;
524 pinfo
->desegment_len
= DESEGMENT_ONE_MORE_SEGMENT
;
525 *need_desegmentation
= TRUE
;
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
;
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
;
549 if (ssh1_tree
&& plen
> 0) {
550 proto_tree_add_uint(ssh1_tree
, hf_ssh_packet_length
, tvb
,
558 proto_tree_add_uint(ssh1_tree
, hf_ssh_padding_length
, tvb
,
559 offset
, padding_length
, padding_length
);
561 offset
+= padding_length
;
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)"));
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
;
580 col_append_sep_fstr(pinfo
->cinfo
, COL_INFO
, NULL
, "Encrypted packet (len=%d)", len
);
584 ssh_proto_tree_add_item(ssh1_tree
, hf_ssh_payload
,
585 tvb
, offset
, len
, ENC_NA
);
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
);
598 proto_tree_add_uint(tree
, hf_ssh_mpint_length
, tvb
,
603 ssh_proto_tree_add_item(tree
, hf_ssh_mpint_selection
,
604 tvb
, offset
, len
, ENC_NA
);
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
);
615 proto_tree_add_uint(tree
, hf_ssh_string_length
, tvb
,
620 ssh_proto_tree_add_item(tree
, hf_ssh_string
,
621 tvb
, offset
, len
, ENC_NA
);
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
)
633 guint8 padding_length
;
635 int last_offset
=offset
;
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
667 pinfo
->desegment_offset
= offset
;
668 pinfo
->desegment_len
= DESEGMENT_ONE_MORE_SEGMENT
;
669 *need_desegmentation
= TRUE
;
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
;
684 * Need to check plen > 0x80000000 here
687 ti
= proto_tree_add_uint(tree
, hf_ssh_packet_length
, tvb
,
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;
696 padding_length
= tvb_get_guint8(tvb
, offset
);
697 proto_tree_add_uint(tree
, hf_ssh_padding_length
, tvb
, offset
, 1, padding_length
);
700 tf
=proto_tree_add_text(tree
, tvb
, offset
, -1, "Key Exchange");
701 key_ex_tree
= proto_item_add_subtree(tf
, ett_key_exchange
);
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
);
709 proto_tree_add_item(key_ex_tree
, hf_ssh2_msg_code
, tvb
, offset
, 1, ENC_NA
);
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 */
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
;
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
],
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
],
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
],
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
);
747 ssh_proto_tree_add_item(key_ex_tree
, hf_ssh_padding_string
, tvb
, offset
, padding_length
, ENC_NA
);
748 offset
+= padding_length
;
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
);
759 col_append_sep_str(pinfo
->cinfo
, COL_INFO
, NULL
,
760 val_to_str(msg_code
, ssh2_kex_dh_msg_vals
, "Unknown (%u)"));
763 case SSH_MSG_KEXDH_INIT
:
764 offset
+= ssh_tree_add_mpint(tvb
, offset
, tree
, hf_ssh_mpint_e
);
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
);
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
);
783 col_append_sep_str(pinfo
->cinfo
, COL_INFO
, NULL
,
784 val_to_str(msg_code
, ssh2_kex_dh_gex_msg_vals
, "Unknown (%u)"));
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
);
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
);
797 case SSH_MSG_KEX_DH_GEX_INIT
:
798 offset
+= ssh_tree_add_mpint(tvb
, offset
, tree
, hf_ssh_mpint_e
);
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
);
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
);
810 ssh_proto_tree_add_item(tree
, hf_ssh_dh_gex_nbits
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
812 ssh_proto_tree_add_item(tree
, hf_ssh_dh_gex_max
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
821 ssh_dissect_encrypted_packet(tvbuff_t
*tvb
, packet_info
*pinfo
,
822 struct ssh_peer_data
*peer_data
,
823 int offset
, proto_tree
*tree
)
827 len
= tvb_reported_length_remaining(tvb
, offset
);
828 col_append_sep_fstr(pinfo
->cinfo
, COL_INFO
, NULL
, "Encrypted packet (len=%d)", len
);
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
);
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
)
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
);
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
;
897 /* XXX - reassemble across segment boundaries? */
898 linelen
= remain_length
;
901 linelen
= linelen
- offset
+ 1;
903 if (linelen
> 1 && tvb_get_guint8(tvb
, offset
+ linelen
- 2) == '\r')
904 protolen
= linelen
- 2;
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
);
919 ssh_set_mac_length(struct ssh_peer_data
*peer_data
)
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
;
956 ssh_gslist_compare_strings(gconstpointer a
, gconstpointer b
)
958 if (a
== NULL
&& b
== NULL
)
964 return strcmp((const char*)a
, (const char*)b
);
967 /* expects that *result is NULL */
969 ssh_choose_algo(gchar
*client
, gchar
*server
, gchar
**result
)
971 gchar
**server_strings
=NULL
;
972 gchar
**client_strings
=NULL
;
974 GSList
*server_list
= NULL
;
976 if (!client
|| !server
|| !result
|| *result
)
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
++) {
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
);
993 g_strfreev(client_strings
);
994 g_slist_free(server_list
);
995 g_strfreev(server_strings
);
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
];
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
);
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
);
1058 ssh_proto_tree_add_item(key_init_tree
, hf_ssh_kex_reserved
,
1059 tvb
, offset
, 4, ENC_NA
);
1062 if (global_data
->peer_data
[CLIENT_PEER_DATA
].kex_proposal
&&
1063 global_data
->peer_data
[SERVER_PEER_DATA
].kex_proposal
&&
1066 /* Note: we're ignoring first_kex_packet_follows. */
1068 global_data
->peer_data
[CLIENT_PEER_DATA
].kex_proposal
,
1069 global_data
->peer_data
[SERVER_PEER_DATA
].kex_proposal
,
1071 ssh_set_kex_specific_dissector(global_data
);
1075 proto_item_set_len(tf
, offset
-start_offset
);
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
);
1089 ssh_proto_tree_add_item(tree
, hf_index_value
, tvb
, offset
, len
,
1092 *store
= tvb_get_string(wmem_file_scope(), tvb
, offset
, len
);
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
);
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
}},
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
}},
1143 { "DH base (G)", "ssh.dh.g",
1144 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1145 "SSH DH base (G)", HFILL
}},
1148 { "DH modulus (P)", "ssh.dh.p",
1149 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1150 "SSH DH modulus (P)", HFILL
}},
1153 { "DH client e", "ssh.dh.e",
1154 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1155 "SSH DH client e", HFILL
}},
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
}},
1193 { "Protocol", "ssh.protocol",
1194 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1195 "SSH Protocol", HFILL
}},
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
}},
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
,
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
[] = {
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.",
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
);