1 /* packet-ssh.c
2 * Routines for ssh packet dissection
3 *
4 * Huagang XIE <huagang@intruvert.com>
5 * Kees Cook <kees@outflux.net>
6 *
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
10 *
11 * Copied from packet-mysql.c
12 *
13 * SPDX-License-Identifier: GPL-2.0-or-later
14 *
15 *
16 * Note: support SSH v1 and v2 now.
17 *
18 */
19
20 /* SSH version 2 is defined in:
21 *
22 * RFC 4250: The Secure Shell (SSH) Protocol Assigned Numbers
23 * RFC 4251: The Secure Shell (SSH) Protocol Architecture
24 * RFC 4252: The Secure Shell (SSH) Authentication Protocol
25 * RFC 4253: The Secure Shell (SSH) Transport Layer Protocol
26 * RFC 4254: The Secure Shell (SSH) Connection Protocol
27 *
28 * SSH versions under 2 were never officially standardized.
29 *
30 * Diffie-Hellman Group Exchange is defined in:
31 *
32 * RFC 4419: Diffie-Hellman Group Exchange for
33 * the Secure Shell (SSH) Transport Layer Protocol
34 */
35
36 /* "SSH" prefixes are for version 2, whereas "SSH1" is for version 1 */
37
38 #include "config.h"
39
40 #include <errno.h>
41
42 #include <epan/packet.h>
43 #include <epan/exceptions.h>
44 #include <epan/sctpppids.h>
45 #include <epan/prefs.h>
46 #include <epan/expert.h>
47 #include <wsutil/strtoi.h>
48 #include <wsutil/file_util.h>
49 #include <wsutil/filesystem.h>
50 #include <wsutil/wsgcrypt.h>
51 #include <wsutil/curve25519.h>
52 #include <wsutil/wslog.h>
53
54 #include "packet-tcp.h"
55
56 void proto_register_ssh(void);
57 void proto_reg_handoff_ssh(void);
58
59 /* SSH Version 1 definition , from openssh ssh1.h */
60 #define SSH1_MSG_NONE 0 /* no message */
61 #define SSH1_MSG_DISCONNECT 1 /* cause (string) */
62 #define SSH1_SMSG_PUBLIC_KEY 2 /* ck,msk,srvk,hostk */
63 #define SSH1_CMSG_SESSION_KEY 3 /* key (BIGNUM) */
64 #define SSH1_CMSG_USER 4 /* user (string) */
65
66
67 #define SSH_VERSION_UNKNOWN 0
68 #define SSH_VERSION_1 1
69 #define SSH_VERSION_2 2
70
71 /* proto data */
72
73 #if GCRYPT_VERSION_NUMBER >= 0x010700 /* 1.7.0 */
74 #define SSH_DECRYPTION_SUPPORTED
75 #endif
76
77 #ifdef SSH_DECRYPTION_SUPPORTED
78 typedef struct {
79 guint8 *data;
80 guint length;
81 } ssh_kex_key;
82
83 typedef struct {
84 guint8 *data;
85 guint length;
86 guint8 type;
87 } ssh_kex_pub_key;
88
89 typedef struct {
90 guint8 *data;
91 guint length;
92 } ssh_enc_key;
93
94 #define SSH_KEX_CURVE25519 1
95 #endif
96
97 struct ssh_peer_data {
98 guint counter;
99
100 guint32 frame_version_start;
101 guint32 frame_version_end;
102
103 guint32 frame_key_start;
104 guint32 frame_key_end;
105 int frame_key_end_offset;
106
107 gchar* kex_proposal;
108
109 /* For all subsequent proposals,
110 [0] is client-to-server and [1] is server-to-client. */
111 #define CLIENT_TO_SERVER_PROPOSAL 0
112 #define SERVER_TO_CLIENT_PROPOSAL 1
113
114 gchar* mac_proposals[2];
115 gchar* mac;
116 gint mac_length;
117
118 gchar* enc_proposals[2];
119 gchar* enc;
120
121 gchar* comp_proposals[2];
122 gchar* comp;
123
124 gint length_is_plaintext;
125 };
126
127 struct ssh_flow_data {
128 guint version;
129
130 gchar* kex;
131 int (*kex_specific_dissector)(guint8 msg_code, tvbuff_t *tvb,
132 packet_info *pinfo, int offset, proto_tree *tree,
133 struct ssh_flow_data *global_data);
134
135 /* [0] is client's, [1] is server's */
136 #define CLIENT_PEER_DATA 0
137 #define SERVER_PEER_DATA 1
138 struct ssh_peer_data peer_data[2];
139
140 #ifdef SSH_DECRYPTION_SUPPORTED
141 gchar *session_id;
142 guint session_id_length;
143 ssh_kex_pub_key *kex_e;
144 wmem_array_t *kex_hash_buffer;
145 #endif
146 };
147
148 static int proto_ssh = -1;
149
150 /* Version exchange */
151 static int hf_ssh_protocol = -1;
152
153 /* Framing */
154 static int hf_ssh_packet_length = -1;
155 static int hf_ssh_packet_length_encrypted = -1;
156 static int hf_ssh_padding_length = -1;
157 static int hf_ssh_payload = -1;
158 static int hf_ssh_encrypted_packet = -1;
159 static int hf_ssh_padding_string = -1;
160 static int hf_ssh_mac_string = -1;
161 static int hf_ssh_direction = -1;
162
163 /* Message codes */
164 static int hf_ssh_msg_code = -1;
165 static int hf_ssh2_msg_code = -1;
166 static int hf_ssh2_kex_dh_msg_code = -1;
167 static int hf_ssh2_kex_dh_gex_msg_code = -1;
168 static int hf_ssh2_kex_ecdh_msg_code = -1;
169
170 /* Algorithm negotiation */
171 static int hf_ssh_cookie = -1;
172 static int hf_ssh_kex_algorithms = -1;
173 static int hf_ssh_server_host_key_algorithms = -1;
174 static int hf_ssh_encryption_algorithms_client_to_server = -1;
175 static int hf_ssh_encryption_algorithms_server_to_client = -1;
176 static int hf_ssh_mac_algorithms_client_to_server = -1;
177 static int hf_ssh_mac_algorithms_server_to_client = -1;
178 static int hf_ssh_compression_algorithms_client_to_server = -1;
179 static int hf_ssh_compression_algorithms_server_to_client = -1;
180 static int hf_ssh_languages_client_to_server = -1;
181 static int hf_ssh_languages_server_to_client = -1;
182 static int hf_ssh_kex_algorithms_length = -1;
183 static int hf_ssh_server_host_key_algorithms_length = -1;
184 static int hf_ssh_encryption_algorithms_client_to_server_length = -1;
185 static int hf_ssh_encryption_algorithms_server_to_client_length = -1;
186 static int hf_ssh_mac_algorithms_client_to_server_length = -1;
187 static int hf_ssh_mac_algorithms_server_to_client_length = -1;
188 static int hf_ssh_compression_algorithms_client_to_server_length = -1;
189 static int hf_ssh_compression_algorithms_server_to_client_length = -1;
190 static int hf_ssh_languages_client_to_server_length = -1;
191 static int hf_ssh_languages_server_to_client_length = -1;
192 static int hf_ssh_first_kex_packet_follows = -1;
193 static int hf_ssh_kex_reserved = -1;
194 static int hf_ssh_kex_hassh_algo = -1;
195 static int hf_ssh_kex_hassh = -1;
196 static int hf_ssh_kex_hasshserver_algo = -1;
197 static int hf_ssh_kex_hasshserver = -1;
198
199 /* Key exchange common elements */
200 static int hf_ssh_hostkey_length = -1;
201 static int hf_ssh_hostkey_type_length = -1;
202 static int hf_ssh_hostkey_type = -1;
203 static int hf_ssh_hostkey_data = -1;
204 static int hf_ssh_hostkey_rsa_n = -1;
205 static int hf_ssh_hostkey_rsa_e = -1;
206 static int hf_ssh_hostkey_dsa_p = -1;
207 static int hf_ssh_hostkey_dsa_q = -1;
208 static int hf_ssh_hostkey_dsa_g = -1;
209 static int hf_ssh_hostkey_dsa_y = -1;
210 static int hf_ssh_hostkey_ecdsa_curve_id = -1;
211 static int hf_ssh_hostkey_ecdsa_curve_id_length = -1;
212 static int hf_ssh_hostkey_ecdsa_q = -1;
213 static int hf_ssh_hostkey_ecdsa_q_length = -1;
214 static int hf_ssh_hostkey_eddsa_key = -1;
215 static int hf_ssh_hostkey_eddsa_key_length = -1;
216
217 static int hf_ssh_kex_h_sig = -1;
218 static int hf_ssh_kex_h_sig_length = -1;
219
220 /* Key exchange: Diffie-Hellman */
221 static int hf_ssh_dh_e = -1;
222 static int hf_ssh_dh_f = -1;
223
224 /* Key exchange: Diffie-Hellman Group Exchange */
225 static int hf_ssh_dh_gex_min = -1;
226 static int hf_ssh_dh_gex_nbits = -1;
227 static int hf_ssh_dh_gex_max = -1;
228 static int hf_ssh_dh_gex_p = -1;
229 static int hf_ssh_dh_gex_g = -1;
230
231 /* Key exchange: Elliptic Curve Diffie-Hellman */
232 static int hf_ssh_ecdh_q_c = -1;
233 static int hf_ssh_ecdh_q_c_length = -1;
234 static int hf_ssh_ecdh_q_s = -1;
235 static int hf_ssh_ecdh_q_s_length = -1;
236
237 /* Miscellaneous */
238 static int hf_ssh_mpint_length = -1;
239
240 static gint ett_ssh = -1;
241 static gint ett_key_exchange = -1;
242 static gint ett_key_exchange_host_key = -1;
243 static gint ett_key_init = -1;
244 static gint ett_ssh1 = -1;
245 static gint ett_ssh2 = -1;
246
247 static expert_field ei_ssh_packet_length = EI_INIT;
248
249 static gboolean ssh_desegment = TRUE;
250
251 static dissector_handle_t ssh_handle;
252
253 #ifdef SSH_DECRYPTION_SUPPORTED
254 static const char *pref_keylog_file;
255 static FILE *ssh_keylog_file;
256 static wmem_map_t *ssh_kex_keys;
257 #endif
258
259 // 29418/tcp: Gerrit Code Review
260 #define TCP_RANGE_SSH "22,29418"
261 #define SCTP_PORT_SSH 22
262
263 /* Message Numbers (from RFC 4250) (1-255) */
264
265 /* Transport layer protocol: generic (1-19) */
266 #define SSH_MSG_DISCONNECT 1
267 #define SSH_MSG_IGNORE 2
268 #define SSH_MSG_UNIMPLEMENTED 3
269 #define SSH_MSG_DEBUG 4
270 #define SSH_MSG_SERVICE_REQUEST 5
271 #define SSH_MSG_SERVICE_ACCEPT 6
272
273 /* Transport layer protocol: Algorithm negotiation (20-29) */
274 #define SSH_MSG_KEXINIT 20
275 #define SSH_MSG_NEWKEYS 21
276
277 /* Transport layer: Key exchange method specific (reusable) (30-49) */
278 #define SSH_MSG_KEXDH_INIT 30
279 #define SSH_MSG_KEXDH_REPLY 31
280
281 #define SSH_MSG_KEX_DH_GEX_REQUEST_OLD 30
282 #define SSH_MSG_KEX_DH_GEX_GROUP 31
283 #define SSH_MSG_KEX_DH_GEX_INIT 32
284 #define SSH_MSG_KEX_DH_GEX_REPLY 33
285 #define SSH_MSG_KEX_DH_GEX_REQUEST 34
286
287 #define SSH_MSG_KEX_ECDH_INIT 30
288 #define SSH_MSG_KEX_ECDH_REPLY 31
289
290 /* User authentication protocol: generic (50-59) */
291 #define SSH_MSG_USERAUTH_REQUEST 50
292 #define SSH_MSG_USERAUTH_FAILURE 51
293 #define SSH_MSG_USERAUTH_SUCCESS 52
294 #define SSH_MSG_USERAUTH_BANNER 53
295
296 /* User authentication protocol: method specific (reusable) (50-79) */
297
298 /* Connection protocol: generic (80-89) */
299 #define SSH_MSG_GLOBAL_REQUEST 80
300 #define SSH_MSG_REQUEST_SUCCESS 81
301 #define SSH_MSG_REQUEST_FAILURE 82
302
303 /* Connection protocol: channel related messages (90-127) */
304 #define SSH_MSG_CHANNEL_OPEN 90
305 #define SSH_MSG_CHANNEL_OPEN_CONFIRMATION 91
306 #define SSH_MSG_CHANNEL_OPEN_FAILURE 92
307 #define SSH_MSG_CHANNEL_WINDOW_ADJUST 93
308 #define SSH_MSG_CHANNEL_DATA 94
309 #define SSH_MSG_CHANNEL_EXTENDED_DATA 95
310 #define SSH_MSG_CHANNEL_EOF 96
311 #define SSH_MSG_CHANNEL_CLOSE 97
312 #define SSH_MSG_CHANNEL_REQUEST 98
313 #define SSH_MSG_CHANNEL_SUCCESS 99
314 #define SSH_MSG_CHANNEL_FAILURE 100
315
316 /* 128-191 reserved for client protocols */
317 /* 192-255 local extensions */
318
319 static const value_string ssh_direction_vals[] = {
320 { CLIENT_TO_SERVER_PROPOSAL, "client-to-server" },
321 { SERVER_TO_CLIENT_PROPOSAL, "server-to-client" },
322 { 0, NULL }
323 };
324
325 static const value_string ssh2_msg_vals[] = {
326 { SSH_MSG_DISCONNECT, "Disconnect" },
327 { SSH_MSG_IGNORE, "Ignore" },
328 { SSH_MSG_UNIMPLEMENTED, "Unimplemented" },
329 { SSH_MSG_DEBUG, "Debug" },
330 { SSH_MSG_SERVICE_REQUEST, "Service Request" },
331 { SSH_MSG_SERVICE_ACCEPT, "Service Accept" },
332 { SSH_MSG_KEXINIT, "Key Exchange Init" },
333 { SSH_MSG_NEWKEYS, "New Keys" },
334 { SSH_MSG_USERAUTH_REQUEST, "User Authentication Request" },
335 { SSH_MSG_USERAUTH_FAILURE, "User Authentication Failure" },
336 { SSH_MSG_USERAUTH_SUCCESS, "User Authentication Success" },
337 { SSH_MSG_USERAUTH_BANNER, "User Authentication Banner" },
338 { SSH_MSG_GLOBAL_REQUEST, "Global Request" },
339 { SSH_MSG_REQUEST_SUCCESS, "Request Success" },
340 { SSH_MSG_REQUEST_FAILURE, "Request Failure" },
341 { SSH_MSG_CHANNEL_OPEN, "Channel Open" },
342 { SSH_MSG_CHANNEL_OPEN_CONFIRMATION, "Channel Open Confirmation" },
343 { SSH_MSG_CHANNEL_OPEN_FAILURE, "Channel Open Failure" },
344 { SSH_MSG_CHANNEL_WINDOW_ADJUST, "Window Adjust" },
345 { SSH_MSG_CHANNEL_DATA, "Channel Data" },
346 { SSH_MSG_CHANNEL_EXTENDED_DATA, "Channel Extended Data" },
347 { SSH_MSG_CHANNEL_EOF, "Channel EOF" },
348 { SSH_MSG_CHANNEL_CLOSE, "Channel Close" },
349 { SSH_MSG_CHANNEL_REQUEST, "Channel Request" },
350 { SSH_MSG_CHANNEL_SUCCESS, "Channel Success" },
351 { SSH_MSG_CHANNEL_FAILURE, "Channel Failure" },
352 { 0, NULL }
353 };
354
355 static const value_string ssh2_kex_dh_msg_vals[] = {
356 { SSH_MSG_KEXDH_INIT, "Diffie-Hellman Key Exchange Init" },
357 { SSH_MSG_KEXDH_REPLY, "Diffie-Hellman Key Exchange Reply" },
358 { 0, NULL }
359 };
360
361 static const value_string ssh2_kex_dh_gex_msg_vals[] = {
362 { SSH_MSG_KEX_DH_GEX_REQUEST_OLD, "Diffie-Hellman Group Exchange Request (Old)" },
363 { SSH_MSG_KEX_DH_GEX_GROUP, "Diffie-Hellman Group Exchange Group" },
364 { SSH_MSG_KEX_DH_GEX_INIT, "Diffie-Hellman Group Exchange Init" },
365 { SSH_MSG_KEX_DH_GEX_REPLY, "Diffie-Hellman Group Exchange Reply" },
366 { SSH_MSG_KEX_DH_GEX_REQUEST, "Diffie-Hellman Group Exchange Request" },
367 { 0, NULL }
368 };
369
370 static const value_string ssh2_kex_ecdh_msg_vals[] = {
371 { SSH_MSG_KEX_ECDH_INIT, "Elliptic Curve Diffie-Hellman Key Exchange Init" },
372 { SSH_MSG_KEX_ECDH_REPLY, "Elliptic Curve Diffie-Hellman Key Exchange Reply" },
373 { 0, NULL }
374 };
375
376 static const value_string ssh1_msg_vals[] = {
377 {SSH1_MSG_NONE, "No Message"},
378 {SSH1_MSG_DISCONNECT, "Disconnect"},
379 {SSH1_SMSG_PUBLIC_KEY, "Public Key"},
380 {SSH1_CMSG_SESSION_KEY, "Session Key"},
381 {SSH1_CMSG_USER, "User"},
382 {0, NULL}
383 };
384
385 static int ssh_dissect_key_init(tvbuff_t *tvb, int offset, proto_tree *tree,
386 int is_response,
387 struct ssh_flow_data *global_data);
388 static int ssh_dissect_proposal(tvbuff_t *tvb, int offset, proto_tree *tree,
389 int hf_index_length, int hf_index_value, char **store);
390 static int ssh_dissect_ssh1(tvbuff_t *tvb, packet_info *pinfo,
391 struct ssh_flow_data *global_data,
392 int offset, proto_tree *tree, int is_response,
393 gboolean *need_desegmentation);
394 static int ssh_dissect_ssh2(tvbuff_t *tvb, packet_info *pinfo,
395 struct ssh_flow_data *global_data,
396 int offset, proto_tree *tree, int is_response,
397 gboolean *need_desegmentation);
398 static int ssh_dissect_key_exchange(tvbuff_t *tvb, packet_info *pinfo,
399 struct ssh_flow_data *global_data,
400 int offset, proto_tree *tree, int is_response,
401 gboolean *need_desegmentation);
402 static int ssh_dissect_kex_dh(guint8 msg_code, tvbuff_t *tvb,
403 packet_info *pinfo, int offset, proto_tree *tree,
404 struct ssh_flow_data *global_data);
405 static int ssh_dissect_kex_dh_gex(guint8 msg_code, tvbuff_t *tvb,
406 packet_info *pinfo, int offset, proto_tree *tree,
407 struct ssh_flow_data *global_data);
408 static int ssh_dissect_kex_ecdh(guint8 msg_code, tvbuff_t *tvb,
409 packet_info *pinfo, int offset, proto_tree *tree,
410 struct ssh_flow_data *global_data);
411 static int ssh_dissect_protocol(tvbuff_t *tvb, packet_info *pinfo,
412 struct ssh_flow_data *global_data,
413 int offset, proto_tree *tree, int is_response, guint *version,
414 gboolean *need_desegmentation);
415 static int ssh_dissect_encrypted_packet(tvbuff_t *tvb, packet_info *pinfo,
416 struct ssh_peer_data *peer_data,
417 int offset, proto_tree *tree);
418 static void ssh_choose_algo(gchar *client, gchar *server, gchar **result);
419 static void ssh_set_mac_length(struct ssh_peer_data *peer_data);
420 static void ssh_set_kex_specific_dissector(struct ssh_flow_data *global_data);
421
422 #ifdef SSH_DECRYPTION_SUPPORTED
423 static void ssh_keylog_read_file(void);
424 static void ssh_keylog_process_line(char *line);
425 static void ssh_keylog_reset(void);
426 static void ssh_keylog_add_keys(guint8 *priv, guint priv_length,
427 gchar *type_string);
428 static ssh_kex_key *ssh_kex_make_key(guint8 *data, guint length);
429 static ssh_kex_pub_key *ssh_kex_make_pub_key(guint8 *data, guint length,
430 gchar type);
431 static void ssh_read_e(tvbuff_t *tvb, int offset,
432 struct ssh_flow_data *global_data);
433 static void ssh_keylog_compute_hash(tvbuff_t *tvb, int offset,
434 struct ssh_flow_data *global_data);
435 static ssh_kex_key *ssh_kex_shared_secret(ssh_kex_pub_key *pub, ssh_kex_key *priv);
436 static void ssh_hash_buffer_put_string(wmem_array_t *buffer, const gchar *string,
437 guint len);
438 static gchar *ssh_string(const gchar *string, guint len);
439 static void ssh_derive_symmetric_keys(ssh_kex_key *shared_secret,
440 gchar *exchange_hash, guint hash_length,
441 struct ssh_flow_data *global_data);
442 static void ssh_derive_symmetric_key(ssh_kex_key *shared_secret,
443 gchar *exchange_hash, guint hash_length, gchar id,
444 ssh_enc_key *result_key, struct ssh_flow_data *global_data);
445 #endif
446
447 static int
dissect_ssh(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)448 dissect_ssh(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
449 {
450 proto_tree *ssh_tree;
451 proto_item *ti;
452 conversation_t *conversation;
453 int last_offset, offset = 0;
454
455 gboolean is_response = (pinfo->destport != pinfo->match_uint),
456 need_desegmentation;
457 guint version;
458
459 struct ssh_flow_data *global_data = NULL;
460 struct ssh_peer_data *peer_data;
461
462 conversation = find_or_create_conversation(pinfo);
463
464 global_data = (struct ssh_flow_data *)conversation_get_proto_data(conversation, proto_ssh);
465 if (!global_data) {
466 global_data = wmem_new0(wmem_file_scope(), struct ssh_flow_data);
467 global_data->version = SSH_VERSION_UNKNOWN;
468 global_data->kex_specific_dissector = ssh_dissect_kex_dh;
469 global_data->peer_data[CLIENT_PEER_DATA].mac_length = -1;
470 global_data->peer_data[SERVER_PEER_DATA].mac_length = -1;
471 #ifdef SSH_DECRYPTION_SUPPORTED
472 global_data->kex_hash_buffer = wmem_array_new(wmem_file_scope(), 1);
473 #endif
474
475 conversation_add_proto_data(conversation, proto_ssh, global_data);
476 }
477
478 peer_data = &global_data->peer_data[is_response];
479
480 ti = proto_tree_add_item(tree, proto_ssh, tvb, offset, -1, ENC_NA);
481 ssh_tree = proto_item_add_subtree(ti, ett_ssh);
482
483 version = global_data->version;
484
485 switch(version) {
486 case SSH_VERSION_UNKNOWN:
487 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSH");
488 break;
489 case SSH_VERSION_1:
490 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSHv1");
491 break;
492 case SSH_VERSION_2:
493 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSHv2");
494 break;
495
496 }
497
498 col_clear(pinfo->cinfo, COL_INFO);
499
500 while(tvb_reported_length_remaining(tvb, offset)> 0) {
501 gboolean after_version_start = (peer_data->frame_version_start == 0 ||
502 pinfo->num >= peer_data->frame_version_start);
503 gboolean before_version_end = (peer_data->frame_version_end == 0 ||
504 pinfo->num <= peer_data->frame_version_end);
505
506 need_desegmentation = FALSE;
507 last_offset = offset;
508
509 peer_data->counter++;
510
511 if (after_version_start && before_version_end &&
512 (tvb_strncaseeql(tvb, offset, "SSH-", 4) == 0)) {
513 if (peer_data->frame_version_start == 0)
514 peer_data->frame_version_start = pinfo->num;
515
516 offset = ssh_dissect_protocol(tvb, pinfo,
517 global_data,
518 offset, ssh_tree, is_response,
519 &version, &need_desegmentation);
520
521 if (!need_desegmentation) {
522 peer_data->frame_version_end = pinfo->num;
523 global_data->version = version;
524 }
525 } else {
526 switch(version) {
527
528 case SSH_VERSION_UNKNOWN:
529 offset = ssh_dissect_encrypted_packet(tvb, pinfo,
530 &global_data->peer_data[is_response], offset, ssh_tree);
531 break;
532
533 case SSH_VERSION_1:
534 offset = ssh_dissect_ssh1(tvb, pinfo, global_data,
535 offset, ssh_tree, is_response,
536 &need_desegmentation);
537 break;
538
539 case SSH_VERSION_2:
540 offset = ssh_dissect_ssh2(tvb, pinfo, global_data,
541 offset, ssh_tree, is_response,
542 &need_desegmentation);
543 break;
544 }
545 }
546
547 if (need_desegmentation)
548 return tvb_captured_length(tvb);
549 if (offset <= last_offset) {
550 /* XXX - add an expert info in the function
551 that decrements offset */
552 break;
553 }
554 }
555
556 col_prepend_fstr(pinfo->cinfo, COL_INFO, "%s: ", is_response ? "Server" : "Client");
557 ti = proto_tree_add_boolean_format_value(ssh_tree, hf_ssh_direction, tvb, 0, 0, is_response, "%s",
558 try_val_to_str(is_response, ssh_direction_vals));
559 proto_item_set_generated(ti);
560 return tvb_captured_length(tvb);
561 }
562
563 static int
ssh_dissect_ssh2(tvbuff_t * tvb,packet_info * pinfo,struct ssh_flow_data * global_data,int offset,proto_tree * tree,int is_response,gboolean * need_desegmentation)564 ssh_dissect_ssh2(tvbuff_t *tvb, packet_info *pinfo,
565 struct ssh_flow_data *global_data,
566 int offset, proto_tree *tree, int is_response,
567 gboolean *need_desegmentation)
568 {
569 proto_item *ssh2_tree = NULL;
570 int last_offset = offset;
571
572 struct ssh_peer_data *peer_data = &global_data->peer_data[is_response];
573
574 if (tree) {
575 wmem_strbuf_t *title = wmem_strbuf_new(wmem_packet_scope(), "SSH Version 2");
576
577 if (peer_data->enc || peer_data->mac || peer_data->comp) {
578 wmem_strbuf_append_printf(title, " (");
579 if (peer_data->enc)
580 wmem_strbuf_append_printf(title, "encryption:%s%s",
581 peer_data->enc,
582 peer_data->mac || peer_data->comp
583 ? " " : "");
584 if (peer_data->mac)
585 wmem_strbuf_append_printf(title, "mac:%s%s",
586 peer_data->mac,
587 peer_data->comp ? " " : "");
588 if (peer_data->comp)
589 wmem_strbuf_append_printf(title, "compression:%s",
590 peer_data->comp);
591 wmem_strbuf_append_printf(title, ")");
592 }
593
594 ssh2_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_ssh2, NULL, wmem_strbuf_get_str(title));
595 }
596
597 if ((peer_data->frame_key_start == 0) ||
598 ((peer_data->frame_key_start <= pinfo->num) &&
599 ((peer_data->frame_key_end == 0) || (pinfo->num < peer_data->frame_key_end) ||
600 ((pinfo->num == peer_data->frame_key_end) && (offset < peer_data->frame_key_end_offset))))) {
601 offset = ssh_dissect_key_exchange(tvb, pinfo, global_data,
602 offset, ssh2_tree, is_response,
603 need_desegmentation);
604 } else {
605 offset = ssh_dissect_encrypted_packet(tvb, pinfo,
606 &global_data->peer_data[is_response], offset, ssh2_tree);
607 }
608
609 if (ssh2_tree) {
610 proto_item_set_len(ssh2_tree, offset - last_offset);
611 }
612
613 return offset;
614 }
615 static int
ssh_dissect_ssh1(tvbuff_t * tvb,packet_info * pinfo,struct ssh_flow_data * global_data,int offset,proto_tree * tree,int is_response,gboolean * need_desegmentation)616 ssh_dissect_ssh1(tvbuff_t *tvb, packet_info *pinfo,
617 struct ssh_flow_data *global_data,
618 int offset, proto_tree *tree, int is_response,
619 gboolean *need_desegmentation)
620 {
621 guint plen, padding_length, len;
622 guint8 msg_code;
623 guint remain_length;
624
625 proto_item *ssh1_tree;
626
627 struct ssh_peer_data *peer_data = &global_data->peer_data[is_response];
628
629 ssh1_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_ssh1, NULL, "SSH Version 1");
630
631 /*
632 * We use "tvb_ensure_captured_length_remaining()" to make sure there
633 * actually *is* data remaining.
634 *
635 * This means we're guaranteed that "remain_length" is positive.
636 */
637 remain_length = tvb_ensure_captured_length_remaining(tvb, offset);
638 /*
639 * Can we do reassembly?
640 */
641 if (ssh_desegment && pinfo->can_desegment) {
642 /*
643 * Yes - would an SSH header starting at this offset be split
644 * across segment boundaries?
645 */
646 if (remain_length < 4) {
647 /*
648 * Yes. Tell the TCP dissector where the data for
649 * this message starts in the data it handed us and
650 * that we need "some more data." Don't tell it
651 * exactly how many bytes we need because if/when we
652 * ask for even more (after the header) that will
653 * break reassembly.
654 */
655 pinfo->desegment_offset = offset;
656 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
657 *need_desegmentation = TRUE;
658 return offset;
659 }
660 }
661 plen = tvb_get_ntohl(tvb, offset) ;
662 padding_length = 8 - plen%8;
663
664
665 if (ssh_desegment && pinfo->can_desegment) {
666 if (plen+4+padding_length > remain_length) {
667 pinfo->desegment_offset = offset;
668 pinfo->desegment_len = plen+padding_length - remain_length;
669 *need_desegmentation = TRUE;
670 return offset;
671 }
672 }
673
674 if (plen >= 0xffff) {
675 if (ssh1_tree && plen > 0) {
676 proto_tree_add_uint_format(ssh1_tree, hf_ssh_packet_length, tvb,
677 offset, 4, plen, "Overly large length %x", plen);
678 }
679 plen = remain_length-4-padding_length;
680 } else {
681 if (ssh1_tree && plen > 0) {
682 proto_tree_add_uint(ssh1_tree, hf_ssh_packet_length, tvb,
683 offset, 4, plen);
684 }
685 }
686 offset+=4;
687 /* padding length */
688
689 proto_tree_add_uint(ssh1_tree, hf_ssh_padding_length, tvb,
690 offset, padding_length, padding_length);
691 offset += padding_length;
692
693 /* msg_code */
694 if ((peer_data->frame_key_start == 0) ||
695 ((peer_data->frame_key_start >= pinfo->num) && (pinfo->num <= peer_data->frame_key_end))) {
696 msg_code = tvb_get_guint8(tvb, offset);
697
698 proto_tree_add_item(ssh1_tree, hf_ssh_msg_code, tvb, offset, 1, ENC_BIG_ENDIAN);
699 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
700 val_to_str(msg_code, ssh1_msg_vals, "Unknown (%u)"));
701 offset += 1;
702 len = plen -1;
703 if (!pinfo->fd->visited) {
704 if (peer_data->frame_key_start == 0)
705 peer_data->frame_key_start = pinfo->num;
706 peer_data->frame_key_end = pinfo->num;
707 }
708 } else {
709 len = plen;
710 col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Encrypted packet (len=%d)", len);
711 }
712 /* payload */
713 if (ssh1_tree) {
714 proto_tree_add_item(ssh1_tree, hf_ssh_payload,
715 tvb, offset, len, ENC_NA);
716 }
717 offset += len;
718
719 return offset;
720 }
721
722 static int
ssh_tree_add_mpint(tvbuff_t * tvb,int offset,proto_tree * tree,int hf_ssh_mpint_selection)723 ssh_tree_add_mpint(tvbuff_t *tvb, int offset, proto_tree *tree,
724 int hf_ssh_mpint_selection)
725 {
726 guint len = tvb_get_ntohl(tvb, offset);
727 proto_tree_add_uint(tree, hf_ssh_mpint_length, tvb,
728 offset, 4, len);
729 offset+=4;
730 proto_tree_add_item(tree, hf_ssh_mpint_selection,
731 tvb, offset, len, ENC_NA);
732 return 4+len;
733 }
734
735 static int
ssh_tree_add_string(tvbuff_t * tvb,int offset,proto_tree * tree,int hf_ssh_string,int hf_ssh_string_length)736 ssh_tree_add_string(tvbuff_t *tvb, int offset, proto_tree *tree,
737 int hf_ssh_string, int hf_ssh_string_length)
738 {
739 guint len = tvb_get_ntohl(tvb, offset);
740 proto_tree_add_uint(tree, hf_ssh_string_length, tvb,
741 offset, 4, len);
742 offset+=4;
743 proto_tree_add_item(tree, hf_ssh_string,
744 tvb, offset, len, ENC_NA);
745 return 4+len;
746 }
747
748 static guint
ssh_tree_add_hostkey(tvbuff_t * tvb,int offset,proto_tree * parent_tree,const char * tree_name,int ett_idx,struct ssh_flow_data * global_data)749 ssh_tree_add_hostkey(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
750 const char *tree_name, int ett_idx,
751 struct ssh_flow_data *global_data)
752 {
753 proto_tree *tree = NULL;
754 int last_offset;
755 int remaining_len;
756 guint key_len, type_len;
757 char* key_type;
758 gchar *tree_title;
759
760 last_offset = offset;
761
762 key_len = tvb_get_ntohl(tvb, offset);
763 offset += 4;
764
765 /* Read the key type before creating the tree so we can append it as info. */
766 type_len = tvb_get_ntohl(tvb, offset);
767 offset += 4;
768 key_type = (char *) tvb_get_string_enc(wmem_packet_scope(), tvb, offset, type_len, ENC_ASCII|ENC_NA);
769
770 tree_title = wmem_strdup_printf(wmem_packet_scope(), "%s (type: %s)", tree_name, key_type);
771 tree = proto_tree_add_subtree(parent_tree, tvb, last_offset, key_len + 4, ett_idx, NULL,
772 tree_title);
773
774 proto_tree_add_uint(tree, hf_ssh_hostkey_length, tvb, last_offset, 4, key_len);
775
776 // server host key (K_S / Q)
777 #ifdef SSH_DECRYPTION_SUPPORTED
778 gchar *data = (gchar *)tvb_memdup(wmem_packet_scope(), tvb, last_offset + 4, key_len);
779 ssh_hash_buffer_put_string(global_data->kex_hash_buffer, data, key_len);
780 #else
781 // ignore unused parameter complaint
782 (void)global_data;
783 #endif
784
785 last_offset += 4;
786 proto_tree_add_uint(tree, hf_ssh_hostkey_type_length, tvb, last_offset, 4, type_len);
787 proto_tree_add_string(tree, hf_ssh_hostkey_type, tvb, offset, type_len, key_type);
788 offset += type_len;
789
790 if (0 == strcmp(key_type, "ssh-rsa")) {
791 offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_hostkey_rsa_e);
792 ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_hostkey_rsa_n);
793 } else if (0 == strcmp(key_type, "ssh-dss")) {
794 offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_hostkey_dsa_p);
795 offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_hostkey_dsa_q);
796 offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_hostkey_dsa_g);
797 ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_hostkey_dsa_y);
798 } else if (g_str_has_prefix(key_type, "ecdsa-sha2-")) {
799 offset += ssh_tree_add_string(tvb, offset, tree,
800 hf_ssh_hostkey_ecdsa_curve_id, hf_ssh_hostkey_ecdsa_curve_id_length);
801 ssh_tree_add_string(tvb, offset, tree,
802 hf_ssh_hostkey_ecdsa_q, hf_ssh_hostkey_ecdsa_q_length);
803 } else if (g_str_has_prefix(key_type, "ssh-ed")) {
804 ssh_tree_add_string(tvb, offset, tree,
805 hf_ssh_hostkey_eddsa_key, hf_ssh_hostkey_eddsa_key_length);
806 } else {
807 remaining_len = key_len - (type_len + 4);
808 proto_tree_add_item(tree, hf_ssh_hostkey_data, tvb, offset, remaining_len, ENC_NA);
809 }
810
811 return 4+key_len;
812 }
813
814 static int
ssh_dissect_key_exchange(tvbuff_t * tvb,packet_info * pinfo,struct ssh_flow_data * global_data,int offset,proto_tree * tree,int is_response,gboolean * need_desegmentation)815 ssh_dissect_key_exchange(tvbuff_t *tvb, packet_info *pinfo,
816 struct ssh_flow_data *global_data,
817 int offset, proto_tree *tree, int is_response,
818 gboolean *need_desegmentation)
819 {
820 guint plen, len;
821 guint8 padding_length;
822 guint remain_length;
823 int last_offset = offset;
824 guint msg_code;
825
826 proto_item *ti;
827 proto_item *key_ex_tree = NULL;
828 const gchar *key_ex_title = "Key Exchange";
829
830 struct ssh_peer_data *peer_data = &global_data->peer_data[is_response];
831
832 /*
833 * We use "tvb_ensure_captured_length_remaining()" to make sure there
834 * actually *is* data remaining.
835 *
836 * This means we're guaranteed that "remain_length" is positive.
837 */
838 remain_length = tvb_ensure_captured_length_remaining(tvb, offset);
839 /*
840 * Can we do reassembly?
841 */
842 if (ssh_desegment && pinfo->can_desegment) {
843 /*
844 * Yes - would an SSH header starting at this offset
845 * be split across segment boundaries?
846 */
847 if (remain_length < 4) {
848 /*
849 * Yes. Tell the TCP dissector where the data for
850 * this message starts in the data it handed us and
851 * that we need "some more data." Don't tell it
852 * exactly how many bytes we need because if/when we
853 * ask for even more (after the header) that will
854 * break reassembly.
855 */
856 pinfo->desegment_offset = offset;
857 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
858 *need_desegmentation = TRUE;
859 return offset;
860 }
861 }
862 plen = tvb_get_ntohl(tvb, offset) ;
863
864 if (ssh_desegment && pinfo->can_desegment) {
865 if (plen +4 > remain_length) {
866 pinfo->desegment_offset = offset;
867 pinfo->desegment_len = plen+4 - remain_length;
868 *need_desegmentation = TRUE;
869 return offset;
870 }
871 }
872 /*
873 * Need to check plen > 0x80000000 here
874 */
875
876 ti = proto_tree_add_uint(tree, hf_ssh_packet_length, tvb,
877 offset, 4, plen);
878 if (plen >= 0xffff) {
879 expert_add_info_format(pinfo, ti, &ei_ssh_packet_length, "Overly large number %d", plen);
880 plen = remain_length-4;
881 }
882 offset+=4;
883
884 /* padding length */
885 padding_length = tvb_get_guint8(tvb, offset);
886 proto_tree_add_uint(tree, hf_ssh_padding_length, tvb, offset, 1, padding_length);
887 offset += 1;
888
889 if (global_data->kex)
890 key_ex_title = wmem_strdup_printf(wmem_packet_scope(), "%s (method:%s)", key_ex_title, global_data->kex);
891 key_ex_tree = proto_tree_add_subtree(tree, tvb, offset, plen-1, ett_key_exchange, NULL, key_ex_title);
892
893 /* msg_code */
894 msg_code = tvb_get_guint8(tvb, offset);
895
896 if (msg_code >= 30 && msg_code < 40) {
897 offset = global_data->kex_specific_dissector(msg_code, tvb, pinfo,
898 offset, key_ex_tree, global_data);
899 } else {
900 proto_tree_add_item(key_ex_tree, hf_ssh2_msg_code, tvb, offset, 1, ENC_BIG_ENDIAN);
901 offset += 1;
902
903 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
904 val_to_str(msg_code, ssh2_msg_vals, "Unknown (%u)"));
905
906 /* 16 bytes cookie */
907 switch(msg_code)
908 {
909 case SSH_MSG_KEXINIT:
910 if ((peer_data->frame_key_start == 0) || (peer_data->frame_key_start == pinfo->num)) {
911 offset = ssh_dissect_key_init(tvb, offset, key_ex_tree, is_response, global_data);
912 peer_data->frame_key_start = pinfo->num;
913 }
914 break;
915 case SSH_MSG_NEWKEYS:
916 if (peer_data->frame_key_end == 0) {
917 peer_data->frame_key_end = pinfo->num;
918 peer_data->frame_key_end_offset = offset;
919 ssh_choose_algo(global_data->peer_data[CLIENT_PEER_DATA].enc_proposals[is_response],
920 global_data->peer_data[SERVER_PEER_DATA].enc_proposals[is_response],
921 &peer_data->enc);
922
923 /* some ciphers have their own MAC so the "negotiated" one is meaningless */
924 if(peer_data->enc && (0 == strcmp(peer_data->enc, "aes128-gcm@openssh.com") ||
925 0 == strcmp(peer_data->enc, "aes256-gcm@openssh.com"))) {
926 peer_data->mac = wmem_strdup(wmem_file_scope(), (const gchar *)"<implicit>");
927 peer_data->mac_length = 16;
928 peer_data->length_is_plaintext = 1;
929 }
930 else if(peer_data->enc && 0 == strcmp(peer_data->enc, "chacha20-poly1305@openssh.com")) {
931 peer_data->mac = wmem_strdup(wmem_file_scope(), (const gchar *)"<implicit>");
932 peer_data->mac_length = 16;
933 }
934 else {
935 ssh_choose_algo(global_data->peer_data[CLIENT_PEER_DATA].mac_proposals[is_response],
936 global_data->peer_data[SERVER_PEER_DATA].mac_proposals[is_response],
937 &peer_data->mac);
938 ssh_set_mac_length(peer_data);
939 }
940
941 ssh_choose_algo(global_data->peer_data[CLIENT_PEER_DATA].comp_proposals[is_response],
942 global_data->peer_data[SERVER_PEER_DATA].comp_proposals[is_response],
943 &peer_data->comp);
944 }
945 break;
946 }
947 }
948
949 len = plen+4-padding_length-(offset-last_offset);
950 if (len > 0) {
951 proto_tree_add_item(key_ex_tree, hf_ssh_payload, tvb, offset, len, ENC_NA);
952 }
953 offset += len;
954
955 /* padding */
956 proto_tree_add_item(tree, hf_ssh_padding_string, tvb, offset, padding_length, ENC_NA);
957 offset+= padding_length;
958
959 return offset;
960 }
961
ssh_dissect_kex_dh(guint8 msg_code,tvbuff_t * tvb,packet_info * pinfo,int offset,proto_tree * tree,struct ssh_flow_data * global_data)962 static int ssh_dissect_kex_dh(guint8 msg_code, tvbuff_t *tvb,
963 packet_info *pinfo, int offset, proto_tree *tree,
964 struct ssh_flow_data *global_data)
965 {
966 proto_tree_add_item(tree, hf_ssh2_kex_dh_msg_code, tvb, offset, 1, ENC_BIG_ENDIAN);
967 offset += 1;
968
969 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
970 val_to_str(msg_code, ssh2_kex_dh_msg_vals, "Unknown (%u)"));
971
972 switch (msg_code) {
973 case SSH_MSG_KEXDH_INIT:
974 #ifdef SSH_DECRYPTION_SUPPORTED
975 // e (client ephemeral key public part)
976 ssh_read_e(tvb, offset, global_data);
977 #endif
978
979 offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_dh_e);
980 break;
981
982 case SSH_MSG_KEXDH_REPLY:
983 offset += ssh_tree_add_hostkey(tvb, offset, tree, "KEX host key",
984 ett_key_exchange_host_key, global_data);
985
986 #ifdef SSH_DECRYPTION_SUPPORTED
987 // f (server ephemeral key public part), K_S (host key)
988 ssh_keylog_compute_hash(tvb, offset, global_data);
989 #endif
990
991 offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_dh_f);
992 offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_kex_h_sig, hf_ssh_kex_h_sig_length);
993 break;
994 }
995
996 return offset;
997 }
998
ssh_dissect_kex_dh_gex(guint8 msg_code,tvbuff_t * tvb,packet_info * pinfo,int offset,proto_tree * tree,struct ssh_flow_data * global_data)999 static int ssh_dissect_kex_dh_gex(guint8 msg_code, tvbuff_t *tvb,
1000 packet_info *pinfo, int offset, proto_tree *tree,
1001 struct ssh_flow_data *global_data)
1002 {
1003 proto_tree_add_item(tree, hf_ssh2_kex_dh_gex_msg_code, tvb, offset, 1, ENC_BIG_ENDIAN);
1004 offset += 1;
1005
1006 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
1007 val_to_str(msg_code, ssh2_kex_dh_gex_msg_vals, "Unknown (%u)"));
1008
1009 switch (msg_code) {
1010 case SSH_MSG_KEX_DH_GEX_REQUEST_OLD:
1011 proto_tree_add_item(tree, hf_ssh_dh_gex_nbits, tvb, offset, 4, ENC_BIG_ENDIAN);
1012 offset += 4;
1013 break;
1014
1015 case SSH_MSG_KEX_DH_GEX_GROUP:
1016 offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_dh_gex_p);
1017 offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_dh_gex_g);
1018 break;
1019
1020 case SSH_MSG_KEX_DH_GEX_INIT:
1021 // TODO allow decryption with this key exchange method
1022 offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_dh_e);
1023 break;
1024
1025 case SSH_MSG_KEX_DH_GEX_REPLY:
1026 offset += ssh_tree_add_hostkey(tvb, offset, tree, "KEX host key",
1027 ett_key_exchange_host_key, global_data);
1028 offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_dh_f);
1029 offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_kex_h_sig, hf_ssh_kex_h_sig_length);
1030 break;
1031
1032 case SSH_MSG_KEX_DH_GEX_REQUEST:
1033 proto_tree_add_item(tree, hf_ssh_dh_gex_min, tvb, offset, 4, ENC_BIG_ENDIAN);
1034 offset += 4;
1035 proto_tree_add_item(tree, hf_ssh_dh_gex_nbits, tvb, offset, 4, ENC_BIG_ENDIAN);
1036 offset += 4;
1037 proto_tree_add_item(tree, hf_ssh_dh_gex_max, tvb, offset, 4, ENC_BIG_ENDIAN);
1038 offset += 4;
1039 break;
1040 }
1041
1042 return offset;
1043 }
1044
1045 static int
ssh_dissect_kex_ecdh(guint8 msg_code,tvbuff_t * tvb,packet_info * pinfo,int offset,proto_tree * tree,struct ssh_flow_data * global_data)1046 ssh_dissect_kex_ecdh(guint8 msg_code, tvbuff_t *tvb,
1047 packet_info *pinfo, int offset, proto_tree *tree,
1048 struct ssh_flow_data *global_data)
1049 {
1050 proto_tree_add_item(tree, hf_ssh2_kex_ecdh_msg_code, tvb, offset, 1, ENC_BIG_ENDIAN);
1051 offset += 1;
1052
1053 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
1054 val_to_str(msg_code, ssh2_kex_ecdh_msg_vals, "Unknown (%u)"));
1055
1056 switch (msg_code) {
1057 case SSH_MSG_KEX_ECDH_INIT:
1058 #ifdef SSH_DECRYPTION_SUPPORTED
1059 ssh_read_e(tvb, offset, global_data);
1060 #endif
1061
1062 offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_ecdh_q_c, hf_ssh_ecdh_q_c_length);
1063 break;
1064
1065 case SSH_MSG_KEX_ECDH_REPLY:
1066 offset += ssh_tree_add_hostkey(tvb, offset, tree, "KEX host key",
1067 ett_key_exchange_host_key, global_data);
1068
1069 #ifdef SSH_DECRYPTION_SUPPORTED
1070 ssh_keylog_compute_hash(tvb, offset, global_data);
1071 #endif
1072
1073 offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_ecdh_q_s, hf_ssh_ecdh_q_s_length);
1074 offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_kex_h_sig, hf_ssh_kex_h_sig_length);
1075 break;
1076 }
1077
1078 return offset;
1079 }
1080
1081 static int
ssh_dissect_encrypted_packet(tvbuff_t * tvb,packet_info * pinfo,struct ssh_peer_data * peer_data,int offset,proto_tree * tree)1082 ssh_dissect_encrypted_packet(tvbuff_t *tvb, packet_info *pinfo,
1083 struct ssh_peer_data *peer_data,
1084 int offset, proto_tree *tree)
1085 {
1086 gint len;
1087 guint plen;
1088
1089 len = tvb_reported_length_remaining(tvb, offset);
1090 col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Encrypted packet (len=%d)", len);
1091
1092 if (tree) {
1093 gint encrypted_len = len;
1094
1095 if (len > 4 && peer_data->length_is_plaintext) {
1096 plen = tvb_get_ntohl(tvb, offset) ;
1097 proto_tree_add_uint(tree, hf_ssh_packet_length, tvb, offset, 4, plen);
1098 encrypted_len -= 4;
1099 }
1100 else if (len > 4) {
1101 proto_tree_add_item(tree, hf_ssh_packet_length_encrypted, tvb, offset, 4, ENC_NA);
1102 encrypted_len -= 4;
1103 }
1104
1105 if (peer_data->mac_length>0)
1106 encrypted_len -= peer_data->mac_length;
1107
1108 proto_tree_add_item(tree, hf_ssh_encrypted_packet,
1109 tvb, offset+4, encrypted_len, ENC_NA);
1110
1111 if (peer_data->mac_length>0)
1112 proto_tree_add_item(tree, hf_ssh_mac_string,
1113 tvb, offset+4+encrypted_len,
1114 peer_data->mac_length, ENC_NA);
1115 }
1116 offset += len;
1117 return offset;
1118 }
1119
1120 static int
ssh_dissect_protocol(tvbuff_t * tvb,packet_info * pinfo,struct ssh_flow_data * global_data,int offset,proto_tree * tree,int is_response,guint * version,gboolean * need_desegmentation)1121 ssh_dissect_protocol(tvbuff_t *tvb, packet_info *pinfo,
1122 struct ssh_flow_data *global_data,
1123 int offset, proto_tree *tree, int is_response, guint * version,
1124 gboolean *need_desegmentation)
1125 {
1126 guint remain_length;
1127 gint linelen, protolen;
1128
1129 /*
1130 * If the first packet do not contain the banner,
1131 * it is dump in the middle of a flow or not a ssh at all
1132 */
1133 if (tvb_strncaseeql(tvb, offset, "SSH-", 4) != 0) {
1134 offset = ssh_dissect_encrypted_packet(tvb, pinfo,
1135 &global_data->peer_data[is_response], offset, tree);
1136 return offset;
1137 }
1138
1139 if (!is_response) {
1140 if (tvb_strncaseeql(tvb, offset, "SSH-2.", 6) == 0) {
1141 *(version) = SSH_VERSION_2;
1142 } else if (tvb_strncaseeql(tvb, offset, "SSH-1.99-", 9) == 0) {
1143 *(version) = SSH_VERSION_2;
1144 } else if (tvb_strncaseeql(tvb, offset, "SSH-1.", 6) == 0) {
1145 *(version) = SSH_VERSION_1;
1146 }
1147 }
1148
1149 /*
1150 * We use "tvb_ensure_captured_length_remaining()" to make sure there
1151 * actually *is* data remaining.
1152 *
1153 * This means we're guaranteed that "remain_length" is positive.
1154 */
1155 remain_length = tvb_ensure_captured_length_remaining(tvb, offset);
1156 /*linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
1157 */
1158 linelen = tvb_find_guint8(tvb, offset, -1, '\n');
1159
1160 if (ssh_desegment && pinfo->can_desegment) {
1161 if (linelen == -1 || remain_length < (guint)linelen-offset) {
1162 pinfo->desegment_offset = offset;
1163 pinfo->desegment_len = linelen-remain_length;
1164 *need_desegmentation = TRUE;
1165 return offset;
1166 }
1167 }
1168 if (linelen == -1) {
1169 /* XXX - reassemble across segment boundaries? */
1170 linelen = remain_length;
1171 protolen = linelen;
1172 } else {
1173 linelen = linelen - offset + 1;
1174
1175 if (linelen > 1 && tvb_get_guint8(tvb, offset + linelen - 2) == '\r')
1176 protolen = linelen - 2;
1177 else
1178 protolen = linelen - 1;
1179 }
1180
1181 col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Protocol (%s)",
1182 tvb_format_text(pinfo->pool, tvb, offset, protolen));
1183
1184 // V_C / V_S (client and server identification strings) RFC4253 4.2
1185 // format: SSH-protoversion-softwareversion SP comments [CR LF not incl.]
1186 #ifdef SSH_DECRYPTION_SUPPORTED
1187 gchar *data = (gchar *)tvb_memdup(wmem_packet_scope(), tvb, offset, protolen);
1188 ssh_hash_buffer_put_string(global_data->kex_hash_buffer, data, protolen);
1189 #endif
1190
1191 proto_tree_add_item(tree, hf_ssh_protocol,
1192 tvb, offset, protolen, ENC_ASCII|ENC_NA);
1193 offset += linelen;
1194 return offset;
1195 }
1196
1197 static void
ssh_set_mac_length(struct ssh_peer_data * peer_data)1198 ssh_set_mac_length(struct ssh_peer_data *peer_data)
1199 {
1200 char *size_str;
1201 guint32 size = 0;
1202 char *mac_name = peer_data->mac;
1203 char *strip;
1204
1205 if (!mac_name)
1206 return;
1207
1208 /* wmem_strdup() never returns NULL */
1209 mac_name = wmem_strdup(NULL, (const gchar *)mac_name);
1210
1211 /* strip trailing "-etm@openssh.com" or "@openssh.com" */
1212 strip = strstr(mac_name, "-etm@openssh.com");
1213 if (strip) {
1214 peer_data->length_is_plaintext = 1;
1215 *strip = '\0';
1216 }
1217 else {
1218 strip = strstr(mac_name, "@openssh.com");
1219 if (strip) *strip = '\0';
1220 }
1221
1222 size_str = g_strrstr(mac_name, "-");
1223 if (size_str && ws_strtou32(size_str + 1, NULL, &size) && size > 0 && size % 8 == 0) {
1224 peer_data->mac_length = size / 8;
1225 }
1226 else if (strcmp(mac_name, "hmac-sha1") == 0) {
1227 peer_data->mac_length = 20;
1228 }
1229 else if (strcmp(mac_name, "hmac-md5") == 0) {
1230 peer_data->mac_length = 16;
1231 }
1232 else if (strcmp(mac_name, "hmac-ripemd160") == 0) {
1233 peer_data->mac_length = 20;
1234 }
1235 else if (strcmp(mac_name, "none") == 0) {
1236 peer_data->mac_length = 0;
1237 }
1238
1239 wmem_free(NULL, mac_name);
1240 }
1241
ssh_set_kex_specific_dissector(struct ssh_flow_data * global_data)1242 static void ssh_set_kex_specific_dissector(struct ssh_flow_data *global_data)
1243 {
1244 const char *kex_name = global_data->kex;
1245
1246 if (!kex_name) return;
1247
1248 if (strcmp(kex_name, "diffie-hellman-group-exchange-sha1") == 0 ||
1249 strcmp(kex_name, "diffie-hellman-group-exchange-sha256") == 0)
1250 {
1251 global_data->kex_specific_dissector = ssh_dissect_kex_dh_gex;
1252 }
1253 else if (g_str_has_prefix(kex_name, "ecdh-sha2-") ||
1254 strcmp(kex_name, "curve25519-sha256@libssh.org") == 0 ||
1255 strcmp(kex_name, "curve25519-sha256") == 0 ||
1256 strcmp(kex_name, "curve448-sha512") == 0)
1257 {
1258 global_data->kex_specific_dissector = ssh_dissect_kex_ecdh;
1259 }
1260 }
1261
1262 static gint
ssh_gslist_compare_strings(gconstpointer a,gconstpointer b)1263 ssh_gslist_compare_strings(gconstpointer a, gconstpointer b)
1264 {
1265 if (a == NULL && b == NULL)
1266 return 0;
1267 if (a == NULL)
1268 return -1;
1269 if (b == NULL)
1270 return 1;
1271 return strcmp((const char*)a, (const char*)b);
1272 }
1273
1274 /* expects that *result is NULL */
1275 static void
ssh_choose_algo(gchar * client,gchar * server,gchar ** result)1276 ssh_choose_algo(gchar *client, gchar *server, gchar **result)
1277 {
1278 gchar **server_strings = NULL;
1279 gchar **client_strings = NULL;
1280 gchar **step;
1281 GSList *server_list = NULL;
1282
1283 if (!client || !server || !result || *result)
1284 return;
1285
1286 server_strings = g_strsplit(server, ",", 0);
1287 for (step = server_strings; *step; step++) {
1288 server_list = g_slist_append(server_list, *step);
1289 }
1290
1291 client_strings = g_strsplit(client, ",", 0);
1292 for (step = client_strings; *step; step++) {
1293 GSList *agreed;
1294 if ((agreed = g_slist_find_custom(server_list, *step, ssh_gslist_compare_strings))) {
1295 *result = wmem_strdup(wmem_file_scope(), (const gchar *)agreed->data);
1296 break;
1297 }
1298 }
1299
1300 g_strfreev(client_strings);
1301 g_slist_free(server_list);
1302 g_strfreev(server_strings);
1303 }
1304
1305 static int
ssh_dissect_key_init(tvbuff_t * tvb,int offset,proto_tree * tree,int is_response,struct ssh_flow_data * global_data)1306 ssh_dissect_key_init(tvbuff_t *tvb, int offset, proto_tree *tree,
1307 int is_response, struct ssh_flow_data *global_data)
1308 {
1309 int start_offset = offset;
1310 int payload_length;
1311 wmem_strbuf_t *hassh_algo;
1312 gchar *hassh;
1313
1314 proto_item *tf, *ti;
1315 proto_tree *key_init_tree;
1316
1317 struct ssh_peer_data *peer_data = &global_data->peer_data[is_response];
1318
1319 key_init_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_key_init, &tf, "Algorithms");
1320 proto_tree_add_item(key_init_tree, hf_ssh_cookie,
1321 tvb, offset, 16, ENC_NA);
1322 offset += 16;
1323
1324 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1325 hf_ssh_kex_algorithms_length, hf_ssh_kex_algorithms,
1326 &peer_data->kex_proposal);
1327 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1328 hf_ssh_server_host_key_algorithms_length,
1329 hf_ssh_server_host_key_algorithms, NULL);
1330 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1331 hf_ssh_encryption_algorithms_client_to_server_length,
1332 hf_ssh_encryption_algorithms_client_to_server,
1333 &peer_data->enc_proposals[CLIENT_TO_SERVER_PROPOSAL]);
1334 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1335 hf_ssh_encryption_algorithms_server_to_client_length,
1336 hf_ssh_encryption_algorithms_server_to_client,
1337 &peer_data->enc_proposals[SERVER_TO_CLIENT_PROPOSAL]);
1338 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1339 hf_ssh_mac_algorithms_client_to_server_length,
1340 hf_ssh_mac_algorithms_client_to_server,
1341 &peer_data->mac_proposals[CLIENT_TO_SERVER_PROPOSAL]);
1342 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1343 hf_ssh_mac_algorithms_server_to_client_length,
1344 hf_ssh_mac_algorithms_server_to_client,
1345 &peer_data->mac_proposals[SERVER_TO_CLIENT_PROPOSAL]);
1346 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1347 hf_ssh_compression_algorithms_client_to_server_length,
1348 hf_ssh_compression_algorithms_client_to_server,
1349 &peer_data->comp_proposals[CLIENT_TO_SERVER_PROPOSAL]);
1350 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1351 hf_ssh_compression_algorithms_server_to_client_length,
1352 hf_ssh_compression_algorithms_server_to_client,
1353 &peer_data->comp_proposals[SERVER_TO_CLIENT_PROPOSAL]);
1354 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1355 hf_ssh_languages_client_to_server_length,
1356 hf_ssh_languages_client_to_server, NULL);
1357 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
1358 hf_ssh_languages_server_to_client_length,
1359 hf_ssh_languages_server_to_client, NULL);
1360
1361 proto_tree_add_item(key_init_tree, hf_ssh_first_kex_packet_follows,
1362 tvb, offset, 1, ENC_BIG_ENDIAN);
1363 offset+=1;
1364
1365 proto_tree_add_item(key_init_tree, hf_ssh_kex_reserved,
1366 tvb, offset, 4, ENC_NA);
1367 offset+=4;
1368
1369 hassh_algo = wmem_strbuf_new(wmem_packet_scope(), "");
1370 if(!is_response) {
1371 wmem_strbuf_append_printf(hassh_algo, "%s;%s;%s;%s", peer_data->kex_proposal, peer_data->enc_proposals[CLIENT_TO_SERVER_PROPOSAL],
1372 peer_data->mac_proposals[CLIENT_TO_SERVER_PROPOSAL], peer_data->comp_proposals[CLIENT_TO_SERVER_PROPOSAL]);
1373 hassh = g_compute_checksum_for_string(G_CHECKSUM_MD5, wmem_strbuf_get_str(hassh_algo), wmem_strbuf_get_len(hassh_algo));
1374 ti = proto_tree_add_string(key_init_tree, hf_ssh_kex_hassh_algo, tvb, offset, 0, wmem_strbuf_get_str(hassh_algo));
1375 proto_item_set_generated(ti);
1376 ti = proto_tree_add_string(key_init_tree, hf_ssh_kex_hassh, tvb, offset, 0, hassh);
1377 proto_item_set_generated(ti);
1378 g_free(hassh);
1379 } else {
1380 wmem_strbuf_append_printf(hassh_algo, "%s;%s;%s;%s", peer_data->kex_proposal, peer_data->enc_proposals[SERVER_TO_CLIENT_PROPOSAL],
1381 peer_data->mac_proposals[SERVER_TO_CLIENT_PROPOSAL], peer_data->comp_proposals[SERVER_TO_CLIENT_PROPOSAL]);
1382 hassh = g_compute_checksum_for_string(G_CHECKSUM_MD5, wmem_strbuf_get_str(hassh_algo), wmem_strbuf_get_len(hassh_algo));
1383 ti = proto_tree_add_string(key_init_tree, hf_ssh_kex_hasshserver_algo, tvb, offset, 0, wmem_strbuf_get_str(hassh_algo));
1384 proto_item_set_generated(ti);
1385 ti = proto_tree_add_string(key_init_tree, hf_ssh_kex_hasshserver, tvb, offset, 0, hassh);
1386 proto_item_set_generated(ti);
1387 g_free(hassh);
1388 }
1389
1390 if (global_data->peer_data[CLIENT_PEER_DATA].kex_proposal &&
1391 global_data->peer_data[SERVER_PEER_DATA].kex_proposal &&
1392 !global_data->kex)
1393 {
1394 /* Note: we're ignoring first_kex_packet_follows. */
1395 ssh_choose_algo(
1396 global_data->peer_data[CLIENT_PEER_DATA].kex_proposal,
1397 global_data->peer_data[SERVER_PEER_DATA].kex_proposal,
1398 &global_data->kex);
1399 ssh_set_kex_specific_dissector(global_data);
1400 }
1401
1402 payload_length = offset - start_offset;
1403
1404 if (tf != NULL) {
1405 proto_item_set_len(tf, payload_length);
1406 }
1407
1408 #ifdef SSH_DECRYPTION_SUPPORTED
1409 // I_C / I_S (client and server SSH_MSG_KEXINIT payload) RFC4253 4.2
1410 gchar *data = (gchar *)wmem_alloc(wmem_packet_scope(), payload_length + 1);
1411 tvb_memcpy(tvb, data + 1, start_offset, payload_length);
1412 data[0] = SSH_MSG_KEXINIT;
1413 ssh_hash_buffer_put_string(global_data->kex_hash_buffer, data,
1414 payload_length + 1);
1415 #endif
1416
1417 return offset;
1418 }
1419
1420 static int
ssh_dissect_proposal(tvbuff_t * tvb,int offset,proto_tree * tree,int hf_index_length,int hf_index_value,char ** store)1421 ssh_dissect_proposal(tvbuff_t *tvb, int offset, proto_tree *tree,
1422 int hf_index_length, int hf_index_value, char **store)
1423 {
1424 guint32 len = tvb_get_ntohl(tvb, offset);
1425 proto_tree_add_uint(tree, hf_index_length, tvb, offset, 4, len);
1426 offset += 4;
1427
1428 proto_tree_add_item(tree, hf_index_value, tvb, offset, len,
1429 ENC_ASCII);
1430 if (store)
1431 *store = (char *) tvb_get_string_enc(wmem_file_scope(), tvb, offset, len, ENC_ASCII);
1432 offset += len;
1433
1434 return offset;
1435 }
1436
1437 #ifdef SSH_DECRYPTION_SUPPORTED
1438 static void
ssh_keylog_read_file(void)1439 ssh_keylog_read_file(void)
1440 {
1441 if (!pref_keylog_file || !*pref_keylog_file) {
1442 ws_debug("no keylog file preference set");
1443 return;
1444 }
1445
1446 if (ssh_keylog_file && file_needs_reopen(ws_fileno(ssh_keylog_file),
1447 pref_keylog_file)) {
1448 ssh_keylog_reset();
1449 }
1450
1451 if (!ssh_keylog_file) {
1452 ssh_keylog_file = ws_fopen(pref_keylog_file, "r");
1453 if (!ssh_keylog_file) {
1454 ws_debug("ssh: failed to open key log file %s: %s",
1455 pref_keylog_file, g_strerror(errno));
1456 return;
1457 }
1458 }
1459
1460 /* File format: each line follows the format "<type> <key>".
1461 * For available <type>s, see below. <key> is the hex-encoded key (64
1462 * characters).
1463 *
1464 * Example:
1465 * curve25519 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF
1466 */
1467 for (;;) {
1468 char buf[512];
1469
1470 if (!fgets(buf, sizeof(buf), ssh_keylog_file)) {
1471 if (ferror(ssh_keylog_file)) {
1472 ws_debug("Error while reading %s, closing it.", pref_keylog_file);
1473 ssh_keylog_reset();
1474 }
1475 break;
1476 }
1477
1478 ssh_keylog_process_line(buf);
1479 }
1480 }
1481
1482 static void
ssh_keylog_process_line(char * line)1483 ssh_keylog_process_line(char *line)
1484 {
1485 ws_debug("ssh: process line: %s", line);
1486
1487 gchar **split = g_strsplit(line, " ", 2);
1488 gchar *key, *value;
1489 int key_len;
1490
1491 if (g_strv_length(split) != 2) {
1492 ws_debug("ssh keylog: invalid format");
1493 g_strfreev(split);
1494 return;
1495 }
1496
1497 key = split[0];
1498 value = split[1];
1499
1500 if (!strcmp(key, "curve25519")) {
1501 key_len = 32;
1502 } else {
1503 ws_debug("ssh: key exchange method not supported");
1504 g_strfreev(split);
1505 return;
1506 }
1507
1508 gchar hexbyte[3] = {0, 0, 0};
1509 guint8 c;
1510 guint8 *converted = g_new(guint8, key_len);
1511
1512 for (int i = 0; i < key_len; i ++) {
1513 hexbyte[0] = value[i * 2];
1514 hexbyte[1] = value[i * 2 + 1];
1515
1516 if (!ws_hexstrtou8(hexbyte, NULL, &c)) {
1517 ws_debug("ssh: can't process key, invalid hex number: %s", hexbyte);
1518 g_free(converted);
1519 g_strfreev(split);
1520 return;
1521 }
1522
1523 converted[i] = c;
1524 }
1525
1526 ssh_keylog_add_keys(converted, key_len, key);
1527 g_free(converted);
1528 g_strfreev(split);
1529 }
1530
1531 static void
ssh_keylog_reset(void)1532 ssh_keylog_reset(void)
1533 {
1534 if (ssh_keylog_file) {
1535 fclose(ssh_keylog_file);
1536 ssh_keylog_file = NULL;
1537 }
1538 }
1539
1540 static guint
ssh_kex_type(char * type)1541 ssh_kex_type(char *type)
1542 {
1543 if (type && g_str_has_prefix(type, "curve25519")) {
1544 return SSH_KEX_CURVE25519;
1545 }
1546
1547 return 0;
1548 }
1549
1550 static void
ssh_keylog_add_keys(guint8 * priv,guint priv_length,gchar * type_string)1551 ssh_keylog_add_keys(guint8 *priv, guint priv_length, gchar *type_string)
1552 {
1553 guint type = ssh_kex_type(type_string);
1554 ssh_kex_pub_key *pub = ssh_kex_make_pub_key(NULL, priv_length, type);
1555
1556 if (SSH_KEX_CURVE25519 == type) {
1557 if (crypto_scalarmult_curve25519_base(pub->data, priv)) {
1558 ws_debug("cannot compute curve25519 public key");
1559 return;
1560 }
1561 } else {
1562 ws_debug("key type %s not supported", type_string);
1563 return;
1564 }
1565
1566 if (!wmem_map_contains(ssh_kex_keys, pub)) {
1567 ssh_kex_key *value = ssh_kex_make_key(NULL, priv_length);
1568 if (!value) {
1569 ws_debug("invalid key length %u", priv_length);
1570 return;
1571 }
1572 memcpy(value->data, priv, priv_length);
1573 wmem_map_insert(ssh_kex_keys, pub, value);
1574 }
1575 }
1576
1577 // This was the largest valid value I (gcc) could find.
1578 // https://github.com/openssh/openssh-portable/blob/0a4a5571ada76b1b012bec9cf6ad1203fc19ec8d/sshkey.c#L1589
1579 #define MAX_SSH_KEY_BYTES 16384
1580 static ssh_kex_key *
ssh_kex_make_key(guint8 * data,guint length)1581 ssh_kex_make_key(guint8 *data, guint length)
1582 {
1583 if (length >= MAX_SSH_KEY_BYTES) {
1584 return NULL;
1585 }
1586
1587 ssh_kex_key *key = wmem_new0(wmem_file_scope(), ssh_kex_key);
1588 key->data = (guint8 *)wmem_alloc0(wmem_file_scope(), length);
1589
1590 if (data) {
1591 memcpy(key->data, data, length);
1592 }
1593
1594 key->length = length;
1595 return key;
1596 }
1597
1598 static ssh_kex_pub_key *
ssh_kex_make_pub_key(guint8 * data,guint length,gchar type)1599 ssh_kex_make_pub_key(guint8 *data, guint length, gchar type)
1600 {
1601 if (length >= MAX_SSH_KEY_BYTES) {
1602 return NULL;
1603 }
1604
1605 ssh_kex_pub_key *key = wmem_new0(wmem_file_scope(), ssh_kex_pub_key);
1606 key->data = (guint8 *)wmem_alloc0(wmem_file_scope(), length);
1607
1608 if (data) {
1609 memcpy(key->data, data, length);
1610 }
1611
1612 key->length = length;
1613 key->type = type;
1614 return key;
1615 }
1616
1617 static void
ssh_read_e(tvbuff_t * tvb,int offset,struct ssh_flow_data * global_data)1618 ssh_read_e(tvbuff_t *tvb, int offset, struct ssh_flow_data *global_data)
1619 {
1620 // store the client's public part (e) for later usage
1621 guint length = tvb_get_ntohl(tvb, offset);
1622 guint type = ssh_kex_type(global_data->kex);
1623 ssh_kex_pub_key *kex = ssh_kex_make_pub_key(NULL, length, type);
1624 if (!kex) {
1625 ws_debug("invalid key length %u", length);
1626 return;
1627 }
1628 global_data->kex_e = kex;
1629 tvb_memcpy(tvb, global_data->kex_e->data, offset + 4, length);
1630 }
1631
1632 static void
ssh_keylog_compute_hash(tvbuff_t * tvb,int offset,struct ssh_flow_data * global_data)1633 ssh_keylog_compute_hash(tvbuff_t *tvb, int offset,
1634 struct ssh_flow_data *global_data)
1635 {
1636 /*
1637 * This computation is defined differently for each key exchange method:
1638 * https://tools.ietf.org/html/rfc4253#page-23
1639 * https://tools.ietf.org/html/rfc5656#page-8
1640 * https://tools.ietf.org/html/rfc4419#page-4
1641 * All key exchange methods:
1642 * https://www.iana.org/assignments/ssh-parameters/ssh-parameters.xhtml#ssh-parameters-16
1643 */
1644 if (global_data->kex_hash_buffer == NULL) {
1645 return;
1646 }
1647
1648 gcry_md_hd_t hd;
1649 ssh_kex_key *secret, *priv;
1650 ssh_kex_pub_key kex_f;
1651 int length;
1652 // TODO support other key exchange algorithms than curve25519-sha256
1653 guint hash_len = 32;
1654
1655 ssh_keylog_read_file();
1656
1657 if (global_data->kex_e == NULL) {
1658 return;
1659 }
1660
1661 length = tvb_get_ntohl(tvb, offset);
1662 kex_f.length = length;
1663 kex_f.data = (gchar *)tvb_memdup(wmem_packet_scope(), tvb, offset + 4, length);
1664 kex_f.type = global_data->kex_e->type;
1665 priv = (ssh_kex_key *)wmem_map_lookup(ssh_kex_keys, global_data->kex_e);
1666
1667 if (!priv) {
1668 priv = (ssh_kex_key *)wmem_map_lookup(ssh_kex_keys, &kex_f);
1669
1670 if (!priv) {
1671 ws_debug("ssh decryption: private key not available");
1672 return;
1673
1674 // we have the server's private key
1675 } else {
1676 secret = ssh_kex_shared_secret(global_data->kex_e, priv);
1677 }
1678
1679 // we have the client's private key
1680 } else {
1681 secret = ssh_kex_shared_secret(&kex_f, priv);
1682 }
1683
1684 if (!secret) {
1685 return;
1686 }
1687
1688 ssh_hash_buffer_put_string(global_data->kex_hash_buffer,
1689 global_data->kex_e->data, length);
1690 ssh_hash_buffer_put_string(global_data->kex_hash_buffer, kex_f.data, length);
1691
1692 // shared secret data needs to be written as an mpint, and we need it later
1693 if (secret->data[0] & 0x80) {
1694 gchar *tmp = (gchar *)wmem_alloc0(wmem_packet_scope(), length + 1);
1695 memcpy(tmp + 1, secret->data, length);
1696 tmp[0] = 0;
1697 secret->data = tmp;
1698 secret->length = length + 1;
1699 ssh_hash_buffer_put_string(global_data->kex_hash_buffer, secret->data,
1700 length + 1);
1701 } else
1702 ssh_hash_buffer_put_string(global_data->kex_hash_buffer, secret->data,
1703 length);
1704
1705 gchar *exchange_hash = (gchar *)wmem_alloc0(wmem_file_scope(), hash_len);
1706 gcry_md_open(&hd, GCRY_MD_SHA256, 0);
1707 gcry_md_write(hd, wmem_array_get_raw(global_data->kex_hash_buffer),
1708 wmem_array_get_count(global_data->kex_hash_buffer));
1709 memcpy(exchange_hash, gcry_md_read(hd, 0), hash_len);
1710 gcry_md_close(hd);
1711 global_data->kex_hash_buffer = NULL;
1712 ssh_derive_symmetric_keys(secret, exchange_hash, hash_len, global_data);
1713 }
1714
1715 // the purpose of this function is to deal with all different kex methods
1716 static ssh_kex_key *
ssh_kex_shared_secret(ssh_kex_pub_key * pub,ssh_kex_key * priv)1717 ssh_kex_shared_secret(ssh_kex_pub_key *pub, ssh_kex_key *priv)
1718 {
1719 ssh_kex_key *secret = ssh_kex_make_key(NULL, pub->length);
1720 if (!secret) {
1721 ws_debug("invalid key length %u", pub->length);
1722 return NULL;
1723 }
1724
1725 if (crypto_scalarmult_curve25519(secret->data, priv->data, pub->data)) {
1726 ws_debug("curve25519: can't compute shared secret");
1727 return NULL;
1728 }
1729
1730 return secret;
1731 }
1732
1733 static gchar *
ssh_string(const gchar * string,guint length)1734 ssh_string(const gchar *string, guint length)
1735 {
1736 gchar *ssh_string = (gchar *)wmem_alloc(wmem_packet_scope(), length + 4);
1737 ssh_string[0] = (length >> 24) & 0xff;
1738 ssh_string[1] = (length >> 16) & 0xff;
1739 ssh_string[2] = (length >> 8) & 0xff;
1740 ssh_string[3] = length & 0xff;
1741 memcpy(ssh_string + 4, string, length);
1742 return ssh_string;
1743 }
1744
1745 static void
ssh_hash_buffer_put_string(wmem_array_t * buffer,const gchar * string,guint length)1746 ssh_hash_buffer_put_string(wmem_array_t *buffer, const gchar *string,
1747 guint length)
1748 {
1749 if (!buffer) {
1750 return;
1751 }
1752
1753 gchar *string_with_length = ssh_string(string, length);
1754 wmem_array_append(buffer, string_with_length, length + 4);
1755 }
1756
ssh_derive_symmetric_keys(ssh_kex_key * secret,gchar * exchange_hash,guint hash_length,struct ssh_flow_data * global_data)1757 static void ssh_derive_symmetric_keys(ssh_kex_key *secret, gchar *exchange_hash,
1758 guint hash_length, struct ssh_flow_data *global_data)
1759 {
1760 ssh_enc_key keys[6];
1761
1762 if (!global_data->session_id) {
1763 global_data->session_id = exchange_hash;
1764 global_data->session_id_length = hash_length;
1765 }
1766
1767 for (int i = 0; i < 6; i ++) {
1768 ssh_derive_symmetric_key(secret, exchange_hash, hash_length,
1769 'A' + i, &keys[i], global_data);
1770 }
1771 }
1772
ssh_derive_symmetric_key(ssh_kex_key * secret,gchar * exchange_hash,guint hash_length,gchar id,ssh_enc_key * result_key,struct ssh_flow_data * global_data)1773 static void ssh_derive_symmetric_key(ssh_kex_key *secret, gchar *exchange_hash,
1774 guint hash_length, gchar id, ssh_enc_key *result_key,
1775 struct ssh_flow_data *global_data)
1776 {
1777 gcry_md_hd_t hd;
1778 guint len = gcry_md_get_algo_dlen(GCRY_MD_SHA256);
1779
1780 // required size of key depends on cipher used. chacha20 wants 64 bytes
1781 guint need = 64;
1782 result_key->data = (guchar *)wmem_alloc(wmem_file_scope(), need);
1783
1784 gchar *secret_with_length = ssh_string(secret->data, secret->length);
1785
1786 if (gcry_md_open(&hd, GCRY_MD_SHA256, 0) == 0) {
1787 gcry_md_write(hd, secret_with_length, secret->length + 4);
1788 gcry_md_write(hd, exchange_hash, hash_length);
1789 gcry_md_putc(hd, id);
1790 gcry_md_write(hd, global_data->session_id, hash_length);
1791 memcpy(result_key->data, gcry_md_read(hd, 0), len);
1792 gcry_md_close(hd);
1793 }
1794
1795 // expand key
1796 for (guint have = len; have < need; have += len) {
1797 if (gcry_md_open(&hd, GCRY_MD_SHA256, 0) == 0) {
1798 gcry_md_write(hd, secret_with_length, secret->length + 4);
1799 gcry_md_write(hd, exchange_hash, hash_length);
1800 gcry_md_write(hd, result_key->data, len);
1801 guint add_length = MIN(len, need - have);
1802 memcpy(result_key->data+have, gcry_md_read(hd, 0), add_length);
1803 gcry_md_close(hd);
1804 }
1805 }
1806
1807 result_key->length = need;
1808 }
1809
1810 static guint
ssh_kex_pub_key_hash(gconstpointer v1)1811 ssh_kex_pub_key_hash(gconstpointer v1)
1812 {
1813 const ssh_kex_pub_key *key1 = (const ssh_kex_pub_key *)v1;
1814 return wmem_strong_hash(key1->data, key1->length);
1815 }
1816
1817 static gboolean
ssh_kex_pub_key_equal(gconstpointer v1,gconstpointer v2)1818 ssh_kex_pub_key_equal(gconstpointer v1, gconstpointer v2)
1819 {
1820 const ssh_kex_pub_key *key1 = (const ssh_kex_pub_key *)v1;
1821 const ssh_kex_pub_key *key2 = (const ssh_kex_pub_key *)v2;
1822 return key1->type == key2->type && key1->length == key2->length &&
1823 !memcmp(key1->data, key2->data, key1->length);
1824 }
1825 #endif /* SSH_DECRYPTION_SUPPORTED */
1826
1827 void
proto_register_ssh(void)1828 proto_register_ssh(void)
1829 {
1830 static hf_register_info hf[] = {
1831 { &hf_ssh_protocol,
1832 { "Protocol", "ssh.protocol",
1833 FT_STRING, BASE_NONE, NULL, 0x0,
1834 NULL, HFILL }},
1835
1836 { &hf_ssh_packet_length,
1837 { "Packet Length", "ssh.packet_length",
1838 FT_UINT32, BASE_DEC, NULL, 0x0,
1839 NULL, HFILL }},
1840
1841 { &hf_ssh_packet_length_encrypted,
1842 { "Packet Length (encrypted)", "ssh.packet_length_encrypted",
1843 FT_BYTES, BASE_NONE, NULL, 0x0,
1844 NULL, HFILL }},
1845
1846 { &hf_ssh_padding_length,
1847 { "Padding Length", "ssh.padding_length",
1848 FT_UINT8, BASE_DEC, NULL, 0x0,
1849 NULL, HFILL }},
1850
1851 { &hf_ssh_payload,
1852 { "Payload", "ssh.payload",
1853 FT_BYTES, BASE_NONE, NULL, 0x0,
1854 NULL, HFILL }},
1855
1856 { &hf_ssh_encrypted_packet,
1857 { "Encrypted Packet", "ssh.encrypted_packet",
1858 FT_BYTES, BASE_NONE, NULL, 0x0,
1859 NULL, HFILL }},
1860
1861 { &hf_ssh_padding_string,
1862 { "Padding String", "ssh.padding_string",
1863 FT_BYTES, BASE_NONE, NULL, 0x0,
1864 NULL, HFILL }},
1865
1866 { &hf_ssh_mac_string,
1867 { "MAC", "ssh.mac",
1868 FT_BYTES, BASE_NONE, NULL, 0x0,
1869 "Message authentication code", HFILL }},
1870
1871 { &hf_ssh_direction,
1872 { "Direction", "ssh.direction",
1873 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1874 "Message direction", HFILL }},
1875
1876 { &hf_ssh_msg_code,
1877 { "Message Code", "ssh.message_code",
1878 FT_UINT8, BASE_DEC, VALS(ssh1_msg_vals), 0x0,
1879 NULL, HFILL }},
1880
1881 { &hf_ssh2_msg_code,
1882 { "Message Code", "ssh.message_code",
1883 FT_UINT8, BASE_DEC, VALS(ssh2_msg_vals), 0x0,
1884 NULL, HFILL }},
1885
1886 { &hf_ssh2_kex_dh_msg_code,
1887 { "Message Code", "ssh.message_code",
1888 FT_UINT8, BASE_DEC, VALS(ssh2_kex_dh_msg_vals), 0x0,
1889 NULL, HFILL }},
1890
1891 { &hf_ssh2_kex_dh_gex_msg_code,
1892 { "Message Code", "ssh.message_code",
1893 FT_UINT8, BASE_DEC, VALS(ssh2_kex_dh_gex_msg_vals), 0x0,
1894 NULL, HFILL }},
1895
1896 { &hf_ssh2_kex_ecdh_msg_code,
1897 { "Message Code", "ssh.message_code",
1898 FT_UINT8, BASE_DEC, VALS(ssh2_kex_ecdh_msg_vals), 0x0,
1899 NULL, HFILL }},
1900
1901 { &hf_ssh_cookie,
1902 { "Cookie", "ssh.cookie",
1903 FT_BYTES, BASE_NONE, NULL, 0x0,
1904 NULL, HFILL }},
1905
1906 { &hf_ssh_kex_algorithms,
1907 { "kex_algorithms string", "ssh.kex_algorithms",
1908 FT_STRING, BASE_NONE, NULL, 0x0,
1909 NULL, HFILL }},
1910
1911 { &hf_ssh_server_host_key_algorithms,
1912 { "server_host_key_algorithms string", "ssh.server_host_key_algorithms",
1913 FT_STRING, BASE_NONE, NULL, 0x0,
1914 NULL, HFILL }},
1915
1916 { &hf_ssh_encryption_algorithms_client_to_server,
1917 { "encryption_algorithms_client_to_server string", "ssh.encryption_algorithms_client_to_server",
1918 FT_STRING, BASE_NONE, NULL, 0x0,
1919 NULL, HFILL }},
1920
1921 { &hf_ssh_encryption_algorithms_server_to_client,
1922 { "encryption_algorithms_server_to_client string", "ssh.encryption_algorithms_server_to_client",
1923 FT_STRING, BASE_NONE, NULL, 0x0,
1924 NULL, HFILL }},
1925
1926 { &hf_ssh_mac_algorithms_client_to_server,
1927 { "mac_algorithms_client_to_server string", "ssh.mac_algorithms_client_to_server",
1928 FT_STRING, BASE_NONE, NULL, 0x0,
1929 NULL, HFILL }},
1930
1931 { &hf_ssh_mac_algorithms_server_to_client,
1932 { "mac_algorithms_server_to_client string", "ssh.mac_algorithms_server_to_client",
1933 FT_STRING, BASE_NONE, NULL, 0x0,
1934 NULL, HFILL }},
1935
1936 { &hf_ssh_compression_algorithms_client_to_server,
1937 { "compression_algorithms_client_to_server string", "ssh.compression_algorithms_client_to_server",
1938 FT_STRING, BASE_NONE, NULL, 0x0,
1939 NULL, HFILL }},
1940
1941 { &hf_ssh_compression_algorithms_server_to_client,
1942 { "compression_algorithms_server_to_client string", "ssh.compression_algorithms_server_to_client",
1943 FT_STRING, BASE_NONE, NULL, 0x0,
1944 NULL, HFILL }},
1945
1946 { &hf_ssh_languages_client_to_server,
1947 { "languages_client_to_server string", "ssh.languages_client_to_server",
1948 FT_STRING, BASE_NONE, NULL, 0x0,
1949 NULL, HFILL }},
1950
1951 { &hf_ssh_languages_server_to_client,
1952 { "languages_server_to_client string", "ssh.languages_server_to_client",
1953 FT_STRING, BASE_NONE, NULL, 0x0,
1954 NULL, HFILL }},
1955
1956 { &hf_ssh_kex_algorithms_length,
1957 { "kex_algorithms length", "ssh.kex_algorithms_length",
1958 FT_UINT32, BASE_DEC, NULL, 0x0,
1959 NULL, HFILL }},
1960
1961 { &hf_ssh_server_host_key_algorithms_length,
1962 { "server_host_key_algorithms length", "ssh.server_host_key_algorithms_length",
1963 FT_UINT32, BASE_DEC, NULL, 0x0,
1964 NULL, HFILL }},
1965
1966 { &hf_ssh_encryption_algorithms_client_to_server_length,
1967 { "encryption_algorithms_client_to_server length", "ssh.encryption_algorithms_client_to_server_length",
1968 FT_UINT32, BASE_DEC, NULL, 0x0,
1969 NULL, HFILL }},
1970
1971 { &hf_ssh_encryption_algorithms_server_to_client_length,
1972 { "encryption_algorithms_server_to_client length", "ssh.encryption_algorithms_server_to_client_length",
1973 FT_UINT32, BASE_DEC, NULL, 0x0,
1974 NULL, HFILL }},
1975
1976 { &hf_ssh_mac_algorithms_client_to_server_length,
1977 { "mac_algorithms_client_to_server length", "ssh.mac_algorithms_client_to_server_length",
1978 FT_UINT32, BASE_DEC, NULL, 0x0,
1979 NULL, HFILL }},
1980
1981 { &hf_ssh_mac_algorithms_server_to_client_length,
1982 { "mac_algorithms_server_to_client length", "ssh.mac_algorithms_server_to_client_length",
1983 FT_UINT32, BASE_DEC, NULL, 0x0,
1984 NULL, HFILL }},
1985
1986 { &hf_ssh_compression_algorithms_client_to_server_length,
1987 { "compression_algorithms_client_to_server length", "ssh.compression_algorithms_client_to_server_length",
1988 FT_UINT32, BASE_DEC, NULL, 0x0,
1989 NULL, HFILL }},
1990
1991 { &hf_ssh_compression_algorithms_server_to_client_length,
1992 { "compression_algorithms_server_to_client length", "ssh.compression_algorithms_server_to_client_length",
1993 FT_UINT32, BASE_DEC, NULL, 0x0,
1994 NULL, HFILL }},
1995
1996 { &hf_ssh_languages_client_to_server_length,
1997 { "languages_client_to_server length", "ssh.languages_client_to_server_length",
1998 FT_UINT32, BASE_DEC, NULL, 0x0,
1999 NULL, HFILL }},
2000
2001 { &hf_ssh_languages_server_to_client_length,
2002 { "languages_server_to_client length", "ssh.languages_server_to_client_length",
2003 FT_UINT32, BASE_DEC, NULL, 0x0,
2004 NULL, HFILL }},
2005
2006 { &hf_ssh_first_kex_packet_follows,
2007 { "First KEX Packet Follows", "ssh.first_kex_packet_follows",
2008 FT_UINT8, BASE_DEC, NULL, 0x0,
2009 NULL, HFILL }},
2010
2011 { &hf_ssh_kex_reserved,
2012 { "Reserved", "ssh.kex.reserved",
2013 FT_BYTES, BASE_NONE, NULL, 0x0,
2014 NULL, HFILL }},
2015
2016 { &hf_ssh_kex_hassh_algo,
2017 { "hasshAlgorithms", "ssh.kex.hassh_algorithms",
2018 FT_STRING, BASE_NONE, NULL, 0x0,
2019 NULL, HFILL }},
2020
2021 { &hf_ssh_kex_hassh,
2022 { "hassh", "ssh.kex.hassh",
2023 FT_STRING, BASE_NONE, NULL, 0x0,
2024 NULL, HFILL }},
2025
2026 { &hf_ssh_kex_hasshserver_algo,
2027 { "hasshServerAlgorithms", "ssh.kex.hasshserver_algorithms",
2028 FT_STRING, BASE_NONE, NULL, 0x0,
2029 NULL, HFILL }},
2030
2031 { &hf_ssh_kex_hasshserver,
2032 { "hasshServer", "ssh.kex.hasshserver",
2033 FT_STRING, BASE_NONE, NULL, 0x0,
2034 NULL, HFILL }},
2035
2036 { &hf_ssh_hostkey_length,
2037 { "Host key length", "ssh.host_key.length",
2038 FT_UINT32, BASE_DEC, NULL, 0x0,
2039 NULL, HFILL }},
2040
2041 { &hf_ssh_hostkey_type_length,
2042 { "Host key type length", "ssh.host_key.type_length",
2043 FT_UINT32, BASE_DEC, NULL, 0x0,
2044 NULL, HFILL }},
2045
2046 { &hf_ssh_hostkey_type,
2047 { "Host key type", "ssh.host_key.type",
2048 FT_STRING, BASE_NONE, NULL, 0x0,
2049 NULL, HFILL }},
2050
2051 { &hf_ssh_hostkey_data,
2052 { "Host key data", "ssh.host_key.data",
2053 FT_BYTES, BASE_NONE, NULL, 0x0,
2054 NULL, HFILL }},
2055
2056 { &hf_ssh_hostkey_rsa_n,
2057 { "RSA modulus (N)", "ssh.host_key.rsa.n",
2058 FT_BYTES, BASE_NONE, NULL, 0x0,
2059 NULL, HFILL }},
2060
2061 { &hf_ssh_hostkey_rsa_e,
2062 { "RSA public exponent (e)", "ssh.host_key.rsa.e",
2063 FT_BYTES, BASE_NONE, NULL, 0x0,
2064 NULL, HFILL }},
2065
2066 { &hf_ssh_hostkey_dsa_p,
2067 { "DSA prime modulus (p)", "ssh.host_key.dsa.p",
2068 FT_BYTES, BASE_NONE, NULL, 0x0,
2069 NULL, HFILL }},
2070
2071 { &hf_ssh_hostkey_dsa_q,
2072 { "DSA prime divisor (q)", "ssh.host_key.dsa.q",
2073 FT_BYTES, BASE_NONE, NULL, 0x0,
2074 NULL, HFILL }},
2075
2076 { &hf_ssh_hostkey_dsa_g,
2077 { "DSA subgroup generator (g)", "ssh.host_key.dsa.g",
2078 FT_BYTES, BASE_NONE, NULL, 0x0,
2079 NULL, HFILL }},
2080
2081 { &hf_ssh_hostkey_dsa_y,
2082 { "DSA public key (y)", "ssh.host_key.dsa.y",
2083 FT_BYTES, BASE_NONE, NULL, 0x0,
2084 NULL, HFILL }},
2085
2086 { &hf_ssh_hostkey_ecdsa_curve_id,
2087 { "ECDSA elliptic curve identifier", "ssh.host_key.ecdsa.id",
2088 FT_STRING, BASE_NONE, NULL, 0x0,
2089 NULL, HFILL }},
2090
2091 { &hf_ssh_hostkey_ecdsa_curve_id_length,
2092 { "ECDSA elliptic curve identifier length", "ssh.host_key.ecdsa.id_length",
2093 FT_UINT32, BASE_DEC, NULL, 0x0,
2094 NULL, HFILL }},
2095
2096 { &hf_ssh_hostkey_ecdsa_q,
2097 { "ECDSA public key (Q)", "ssh.host_key.ecdsa.q",
2098 FT_BYTES, BASE_NONE, NULL, 0x0,
2099 NULL, HFILL }},
2100
2101 { &hf_ssh_hostkey_ecdsa_q_length,
2102 { "ECDSA public key length", "ssh.host_key.ecdsa.q_length",
2103 FT_UINT32, BASE_DEC, NULL, 0x0,
2104 NULL, HFILL }},
2105
2106 { &hf_ssh_hostkey_eddsa_key,
2107 { "EdDSA public key", "ssh.host_key.eddsa.key",
2108 FT_BYTES, BASE_NONE, NULL, 0x0,
2109 NULL, HFILL }},
2110
2111 { &hf_ssh_hostkey_eddsa_key_length,
2112 { "EdDSA public key length", "ssh.host_key.eddsa.key_length",
2113 FT_UINT32, BASE_DEC, NULL, 0x0,
2114 NULL, HFILL }},
2115
2116 { &hf_ssh_kex_h_sig,
2117 { "KEX H signature", "ssh.kex.h_sig",
2118 FT_BYTES, BASE_NONE, NULL, 0x0,
2119 NULL, HFILL }},
2120
2121 { &hf_ssh_kex_h_sig_length,
2122 { "KEX H signature length", "ssh.kex.h_sig_length",
2123 FT_UINT32, BASE_DEC, NULL, 0x0,
2124 NULL, HFILL }},
2125
2126 { &hf_ssh_dh_e,
2127 { "DH client e", "ssh.dh.e",
2128 FT_BYTES, BASE_NONE, NULL, 0x0,
2129 NULL, HFILL }},
2130
2131 { &hf_ssh_dh_f,
2132 { "DH server f", "ssh.dh.f",
2133 FT_BYTES, BASE_NONE, NULL, 0x0,
2134 NULL, HFILL }},
2135
2136 { &hf_ssh_dh_gex_min,
2137 { "DH GEX Min", "ssh.dh_gex.min",
2138 FT_UINT32, BASE_DEC, NULL, 0x0,
2139 "Minimal acceptable group size", HFILL }},
2140
2141 { &hf_ssh_dh_gex_nbits,
2142 { "DH GEX Number of Bits", "ssh.dh_gex.nbits",
2143 FT_UINT32, BASE_DEC, NULL, 0x0,
2144 "Preferred group size", HFILL }},
2145
2146 { &hf_ssh_dh_gex_max,
2147 { "DH GEX Max", "ssh.dh_gex.max",
2148 FT_UINT32, BASE_DEC, NULL, 0x0,
2149 "Maximal acceptable group size", HFILL }},
2150
2151 { &hf_ssh_dh_gex_p,
2152 { "DH GEX modulus (P)", "ssh.dh_gex.p",
2153 FT_BYTES, BASE_NONE, NULL, 0x0,
2154 NULL, HFILL }},
2155
2156 { &hf_ssh_dh_gex_g,
2157 { "DH GEX base (G)", "ssh.dh_gex.g",
2158 FT_BYTES, BASE_NONE, NULL, 0x0,
2159 NULL, HFILL }},
2160
2161 { &hf_ssh_ecdh_q_c,
2162 { "ECDH client's ephemeral public key (Q_C)", "ssh.ecdh.q_c",
2163 FT_BYTES, BASE_NONE, NULL, 0x0,
2164 NULL, HFILL }},
2165
2166 { &hf_ssh_ecdh_q_c_length,
2167 { "ECDH client's ephemeral public key length", "ssh.ecdh.q_c_length",
2168 FT_UINT32, BASE_DEC, NULL, 0x0,
2169 NULL, HFILL }},
2170
2171 { &hf_ssh_ecdh_q_s,
2172 { "ECDH server's ephemeral public key (Q_S)", "ssh.ecdh.q_s",
2173 FT_BYTES, BASE_NONE, NULL, 0x0,
2174 NULL, HFILL }},
2175
2176 { &hf_ssh_ecdh_q_s_length,
2177 { "ECDH server's ephemeral public key length", "ssh.ecdh.q_s_length",
2178 FT_UINT32, BASE_DEC, NULL, 0x0,
2179 NULL, HFILL }},
2180
2181 { &hf_ssh_mpint_length,
2182 { "Multi Precision Integer Length", "ssh.mpint_length",
2183 FT_UINT32, BASE_DEC, NULL, 0x0,
2184 NULL, HFILL }},
2185 };
2186
2187 static gint *ett[] = {
2188 &ett_ssh,
2189 &ett_key_exchange,
2190 &ett_key_exchange_host_key,
2191 &ett_ssh1,
2192 &ett_ssh2,
2193 &ett_key_init
2194 };
2195
2196 static ei_register_info ei[] = {
2197 { &ei_ssh_packet_length, { "ssh.packet_length.error", PI_PROTOCOL, PI_WARN, "Overly large number", EXPFILL }},
2198 };
2199
2200 module_t *ssh_module;
2201 expert_module_t *expert_ssh;
2202
2203 proto_ssh = proto_register_protocol("SSH Protocol", "SSH", "ssh");
2204 proto_register_field_array(proto_ssh, hf, array_length(hf));
2205 proto_register_subtree_array(ett, array_length(ett));
2206 expert_ssh = expert_register_protocol(proto_ssh);
2207 expert_register_field_array(expert_ssh, ei, array_length(ei));
2208
2209 ssh_module = prefs_register_protocol(proto_ssh, NULL);
2210 prefs_register_bool_preference(ssh_module, "desegment_buffers",
2211 "Reassemble SSH buffers spanning multiple TCP segments",
2212 "Whether the SSH dissector should reassemble SSH buffers spanning multiple TCP segments. "
2213 "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
2214 &ssh_desegment);
2215
2216 #ifdef SSH_DECRYPTION_SUPPORTED
2217 prefs_register_filename_preference(ssh_module, "keylog_file", "Key log filename",
2218 "The path to the file which contains a list of key exchange secrets in the following format:\n"
2219 "\"<key-type> <hex-encoded-key>\" (without quotes or leading spaces).\n"
2220 "<key-type> is one of: curve25519. ",
2221 &pref_keylog_file, FALSE);
2222
2223 ssh_kex_keys = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(),
2224 ssh_kex_pub_key_hash, ssh_kex_pub_key_equal);
2225 #endif
2226
2227 ssh_handle = register_dissector("ssh", dissect_ssh, proto_ssh);
2228 }
2229
2230 void
proto_reg_handoff_ssh(void)2231 proto_reg_handoff_ssh(void)
2232 {
2233 dissector_add_uint_range_with_preference("tcp.port", TCP_RANGE_SSH, ssh_handle);
2234 dissector_add_uint("sctp.port", SCTP_PORT_SSH, ssh_handle);
2235 dissector_add_uint("sctp.ppi", SSH_PAYLOAD_PROTOCOL_ID, ssh_handle);
2236 }
2237
2238 /*
2239 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2240 *
2241 * Local variables:
2242 * c-basic-offset: 4
2243 * tab-width: 8
2244 * indent-tabs-mode: nil
2245 * End:
2246 *
2247 * vi: set shiftwidth=4 tabstop=8 expandtab:
2248 * :indentSize=4:tabSize=8:noTabs=true:
2249 */
2250