Coverage Report

Created: 2026-03-30 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-ssh.c
Line
Count
Source
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
0
#define WS_LOG_DOMAIN "packet-ssh"
40
/* Start with WIRESHARK_LOG_DOMAINS=packet-ssh and WIRESHARK_LOG_LEVEL=debug to see messages. */
41
42
// Define this to get hex dumps more similar to what you get in openssh. If not defined, dumps look more like what you get with other dissectors.
43
#define OPENSSH_STYLE
44
45
#include <errno.h>
46
47
#include <epan/packet.h>
48
#include <epan/exceptions.h>
49
#include <epan/prefs.h>
50
#include <epan/expert.h>
51
#include <epan/proto_data.h>
52
#include <epan/tfs.h>
53
#include <epan/unit_strings.h>
54
#include <wsutil/strtoi.h>
55
#include <wsutil/to_str.h>
56
#include <wsutil/file_util.h>
57
#include <wsutil/filesystem.h>
58
#include <wsutil/wsgcrypt.h>
59
#include <wsutil/curve25519.h>
60
#include <wsutil/pint.h>
61
#include <wsutil/str_util.h>
62
#include <wsutil/wslog.h>
63
#include <epan/secrets.h>
64
#include <wiretap/secrets-types.h>
65
66
#if defined(HAVE_LIBGNUTLS)
67
#include <gnutls/abstract.h>
68
#endif
69
70
#include "packet-tcp.h"
71
#include "packet-sctp.h"
72
73
void proto_register_ssh(void);
74
void proto_reg_handoff_ssh(void);
75
76
/* SSH Version 1 definition , from openssh ssh1.h */
77
#define SSH1_MSG_NONE           0   /* no message */
78
#define SSH1_MSG_DISCONNECT     1   /* cause (string) */
79
#define SSH1_SMSG_PUBLIC_KEY    2   /* ck,msk,srvk,hostk */
80
#define SSH1_CMSG_SESSION_KEY   3   /* key (BIGNUM) */
81
#define SSH1_CMSG_USER          4   /* user (string) */
82
83
84
75
#define SSH_VERSION_UNKNOWN     0
85
0
#define SSH_VERSION_1           1
86
0
#define SSH_VERSION_2           2
87
88
/* proto data */
89
90
typedef struct {
91
    uint8_t *data;
92
    unsigned   length;
93
} ssh_bignum;
94
95
0
#define SSH_KEX_CURVE25519 0x00010000
96
0
#define SSH_KEX_DH_GEX     0x00020000
97
0
#define SSH_KEX_DH_GROUP1  0x00030001
98
0
#define SSH_KEX_DH_GROUP14 0x00030014
99
0
#define SSH_KEX_DH_GROUP16 0x00030016
100
0
#define SSH_KEX_DH_GROUP18 0x00030018
101
0
#define SSH_KEX_SNTRUP761X25519 0x00040000
102
0
#define SSH_KEX_MLKEM768X25519 0x00050000
103
104
0
#define SSH_KEX_HASH_SHA1   1
105
0
#define SSH_KEX_HASH_SHA256 2
106
0
#define SSH_KEX_HASH_SHA512 4
107
108
0
#define DIGEST_MAX_SIZE 48
109
110
/* The maximum SSH packet_length accepted. If the packet_length field after
111
 * attempted decryption is larger than this, the packet will be assumed to
112
 * have failed decryption (possibly due to being continuation data).
113
 * (This could be made a preference.)
114
 */
115
0
#define SSH_MAX_PACKET_LEN 32768
116
117
typedef struct _ssh_message_info_t {
118
    uint32_t sequence_number;
119
    unsigned char *plain_data;     /**< Decrypted data. */
120
    unsigned   data_len;       /**< Length of decrypted data. */
121
    int     id;             /**< Identifies the exact message within a frame
122
                                 (there can be multiple records in a frame). */
123
    uint32_t byte_seq;
124
    uint32_t next_byte_seq;
125
    struct _ssh_message_info_t* next;
126
    uint8_t calc_mac[DIGEST_MAX_SIZE];
127
} ssh_message_info_t;
128
129
typedef struct {
130
    bool from_server;
131
    ssh_message_info_t * messages;
132
} ssh_packet_info_t;
133
134
typedef struct _ssh_channel_info_t {
135
    uint32_t byte_seq;
136
    uint16_t flags;
137
    wmem_tree_t *multisegment_pdus;
138
    dissector_handle_t handle;
139
} ssh_channel_info_t;
140
141
struct ssh_peer_data {
142
    unsigned   counter;
143
144
    uint32_t frame_version_start;
145
    uint32_t frame_version_end;
146
147
    uint32_t frame_key_start;
148
    uint32_t frame_key_end;
149
    int frame_key_end_offset;
150
151
    char*  kex_proposal;
152
153
    /* For all subsequent proposals,
154
       [0] is client-to-server and [1] is server-to-client. */
155
0
#define CLIENT_TO_SERVER_PROPOSAL 0
156
0
#define SERVER_TO_CLIENT_PROPOSAL 1
157
158
    char*  mac_proposals[2];
159
    char*  mac;
160
    int     mac_length;
161
162
    char*  enc_proposals[2];
163
    char*  enc;
164
165
    char*  comp_proposals[2];
166
    char*  comp;
167
168
    int     length_is_plaintext;
169
170
    // see libgcrypt source, gcrypt.h:gcry_cipher_algos
171
    unsigned         cipher_id;
172
    unsigned         mac_id;
173
    // chacha20 needs two cipher handles
174
    gcry_cipher_hd_t cipher, cipher_2;
175
    unsigned         sequence_number;
176
    ssh_bignum      *bn_cookie;
177
    uint8_t          iv[12];
178
    uint8_t          hmac_iv[DIGEST_MAX_SIZE];
179
    unsigned         hmac_iv_len;
180
181
    unsigned int     rekey_trigger_frame;  // for storing new KEXINIT frame value when REKEY
182
    bool             rekey_pending;  // trace REKEY
183
    uint8_t          plain0[16];
184
    bool             plain0_valid;
185
186
    wmem_map_t      *channel_info; /**< Map of sender channel numbers to recipient numbers. */
187
    wmem_map_t      *channel_handles; /**< Map of recipient channel numbers to subdissector handles. */
188
    struct ssh_flow_data * global_data;
189
};
190
191
struct ssh_flow_data {
192
    unsigned   version;
193
194
    /* The address/port of the server */
195
    address srv_addr;
196
    unsigned srv_port;
197
198
    char*  kex;
199
    int   (*kex_specific_dissector)(uint8_t msg_code, tvbuff_t *tvb,
200
            packet_info *pinfo, int offset, proto_tree *tree,
201
            struct ssh_flow_data *global_data);
202
203
    /* [0] is client's, [1] is server's */
204
92
#define CLIENT_PEER_DATA 0
205
92
#define SERVER_PEER_DATA 1
206
    struct ssh_peer_data peer_data[2];
207
208
    const uint8_t   *session_id;
209
    unsigned        session_id_length;
210
    ssh_bignum      *kex_e;
211
    ssh_bignum      *kex_f;
212
    ssh_bignum      *kex_gex_p;                 // Group modulo
213
    ssh_bignum      *kex_gex_g;                 // Group generator
214
    ssh_bignum      *secret;
215
    wmem_array_t    *kex_client_version;
216
    wmem_array_t    *kex_server_version;
217
    wmem_array_t    *kex_client_key_exchange_init;
218
    wmem_array_t    *kex_server_key_exchange_init;
219
    wmem_array_t    *kex_server_host_key_blob;
220
    wmem_array_t    *kex_gex_bits_min;
221
    wmem_array_t    *kex_gex_bits_req;
222
    wmem_array_t    *kex_gex_bits_max;
223
    wmem_array_t    *kex_shared_secret;
224
    bool            do_decrypt;
225
    bool            ext_ping_openssh_offered;
226
    bool            ext_kex_strict;
227
    ssh_bignum      new_keys[6];
228
    uint8_t          *pqkem_ciphertext;
229
    uint32_t         pqkem_ciphertext_len;
230
    uint8_t          *curve25519_pub;
231
    uint32_t         curve25519_pub_len;
232
    // storing PQ dissected keys
233
    uint8_t *kex_e_pq;  // binary material => no bignum (not traditional DH integer / not math ready)
234
    uint8_t *kex_f_pq;  // binary material => no bignum (not traditional DH integer / not math ready)
235
    uint32_t kex_e_pq_len;
236
    uint32_t kex_f_pq_len;
237
};
238
239
typedef struct {
240
    char *type;                     // "PRIVATE_KEY" or "SHARED_SECRET"
241
    ssh_bignum *key_material;       // Either private key or shared secret
242
} ssh_key_map_entry_t;
243
244
static GHashTable * ssh_master_key_map;
245
246
static int proto_ssh;
247
248
/* Version exchange */
249
static int hf_ssh_protocol;
250
251
/* Framing */
252
static int hf_ssh_packet_length;
253
static int hf_ssh_packet_length_encrypted;
254
static int hf_ssh_padding_length;
255
static int hf_ssh_payload;
256
static int hf_ssh_encrypted_packet;
257
static int hf_ssh_padding_string;
258
static int hf_ssh_mac_string;
259
static int hf_ssh_mac_status;
260
static int hf_ssh_seq_num;
261
static int hf_ssh_direction;
262
263
/* Message codes */
264
static int hf_ssh_msg_code;
265
static int hf_ssh2_msg_code;
266
static int hf_ssh2_kex_dh_msg_code;
267
static int hf_ssh2_kex_dh_gex_msg_code;
268
static int hf_ssh2_kex_ecdh_msg_code;
269
static int hf_ssh2_kex_hybrid_msg_code;
270
static int hf_ssh2_ext_ping_msg_code;
271
272
/* Algorithm negotiation */
273
static int hf_ssh_cookie;
274
static int hf_ssh_kex_algorithms;
275
static int hf_ssh_server_host_key_algorithms;
276
static int hf_ssh_encryption_algorithms_client_to_server;
277
static int hf_ssh_encryption_algorithms_server_to_client;
278
static int hf_ssh_mac_algorithms_client_to_server;
279
static int hf_ssh_mac_algorithms_server_to_client;
280
static int hf_ssh_compression_algorithms_client_to_server;
281
static int hf_ssh_compression_algorithms_server_to_client;
282
static int hf_ssh_languages_client_to_server;
283
static int hf_ssh_languages_server_to_client;
284
static int hf_ssh_kex_algorithms_length;
285
static int hf_ssh_server_host_key_algorithms_length;
286
static int hf_ssh_encryption_algorithms_client_to_server_length;
287
static int hf_ssh_encryption_algorithms_server_to_client_length;
288
static int hf_ssh_mac_algorithms_client_to_server_length;
289
static int hf_ssh_mac_algorithms_server_to_client_length;
290
static int hf_ssh_compression_algorithms_client_to_server_length;
291
static int hf_ssh_compression_algorithms_server_to_client_length;
292
static int hf_ssh_languages_client_to_server_length;
293
static int hf_ssh_languages_server_to_client_length;
294
static int hf_ssh_first_kex_packet_follows;
295
static int hf_ssh_kex_reserved;
296
static int hf_ssh_kex_hassh_algo;
297
static int hf_ssh_kex_hassh;
298
static int hf_ssh_kex_hasshserver_algo;
299
static int hf_ssh_kex_hasshserver;
300
301
/* Key exchange common elements */
302
static int hf_ssh_hostkey_length;
303
static int hf_ssh_hostkey_type_length;
304
static int hf_ssh_hostkey_type;
305
static int hf_ssh_hostkey_data;
306
static int hf_ssh_hostkey_rsa_n;
307
static int hf_ssh_hostkey_rsa_e;
308
static int hf_ssh_hostkey_dsa_p;
309
static int hf_ssh_hostkey_dsa_q;
310
static int hf_ssh_hostkey_dsa_g;
311
static int hf_ssh_hostkey_dsa_y;
312
static int hf_ssh_hostkey_ecdsa_curve_id;
313
static int hf_ssh_hostkey_ecdsa_curve_id_length;
314
static int hf_ssh_hostkey_ecdsa_q;
315
static int hf_ssh_hostkey_ecdsa_q_length;
316
static int hf_ssh_hostkey_eddsa_key;
317
static int hf_ssh_hostkey_eddsa_key_length;
318
static int hf_ssh_hostsig_length;
319
static int hf_ssh_hostsig_type_length;
320
static int hf_ssh_hostsig_type;
321
static int hf_ssh_hostsig_rsa;
322
static int hf_ssh_hostsig_dsa;
323
static int hf_ssh_hostsig_data_length;
324
static int hf_ssh_hostsig_data;
325
326
/* Key exchange: Diffie-Hellman */
327
static int hf_ssh_dh_e;
328
static int hf_ssh_dh_f;
329
330
/* Key exchange: Diffie-Hellman Group Exchange */
331
static int hf_ssh_dh_gex_min;
332
static int hf_ssh_dh_gex_nbits;
333
static int hf_ssh_dh_gex_max;
334
static int hf_ssh_dh_gex_p;
335
static int hf_ssh_dh_gex_g;
336
337
/* Key exchange: Elliptic Curve Diffie-Hellman */
338
static int hf_ssh_ecdh_q_c;
339
static int hf_ssh_ecdh_q_c_length;
340
static int hf_ssh_ecdh_q_s;
341
static int hf_ssh_ecdh_q_s_length;
342
343
/* Key exchange: Post-Quantum Hybrid KEM */
344
static int hf_ssh_hybrid_blob_client;      // client's full PQ blob
345
static int hf_ssh_hybrid_blob_client_len;
346
static int hf_ssh_hybrid_blob_server;      // server's full PQ blob
347
static int hf_ssh_hybrid_blob_server_len;
348
static int hf_ssh_pq_kem_client;           // client's PQ public key
349
static int hf_ssh_pq_kem_server;           // server's PQ response
350
351
/* Extension negotiation */
352
static int hf_ssh_ext_count;
353
static int hf_ssh_ext_name_length;
354
static int hf_ssh_ext_name;
355
static int hf_ssh_ext_value_length;
356
static int hf_ssh_ext_value;
357
static int hf_ssh_ext_server_sig_algs_algorithms;
358
static int hf_ssh_ext_delay_compression_algorithms_client_to_server_length;
359
static int hf_ssh_ext_delay_compression_algorithms_client_to_server;
360
static int hf_ssh_ext_delay_compression_algorithms_server_to_client_length;
361
static int hf_ssh_ext_delay_compression_algorithms_server_to_client;
362
static int hf_ssh_ext_no_flow_control_value;
363
static int hf_ssh_ext_elevation_value;
364
static int hf_ssh_ext_prop_publickey_algorithms_algorithms;
365
366
/* Miscellaneous */
367
static int hf_ssh_mpint_length;
368
369
static int hf_ssh_ignore_data_length;
370
static int hf_ssh_ignore_data;
371
static int hf_ssh_debug_always_display;
372
static int hf_ssh_debug_message_length;
373
static int hf_ssh_debug_message;
374
static int hf_ssh_service_name_length;
375
static int hf_ssh_service_name;
376
static int hf_ssh_userauth_user_name_length;
377
static int hf_ssh_userauth_user_name;
378
static int hf_ssh_userauth_change_password;
379
static int hf_ssh_userauth_service_name_length;
380
static int hf_ssh_userauth_service_name;
381
static int hf_ssh_userauth_method_name_length;
382
static int hf_ssh_userauth_method_name;
383
static int hf_ssh_userauth_have_signature;
384
static int hf_ssh_userauth_password_length;
385
static int hf_ssh_userauth_password;
386
static int hf_ssh_userauth_new_password_length;
387
static int hf_ssh_userauth_new_password;
388
static int hf_ssh_auth_failure_list_length;
389
static int hf_ssh_auth_failure_list;
390
static int hf_ssh_userauth_partial_success;
391
static int hf_ssh_userauth_pka_name_len;
392
static int hf_ssh_userauth_pka_name;
393
static int hf_ssh_pk_blob_name_length;
394
static int hf_ssh_pk_blob_name;
395
static int hf_ssh_blob_length;
396
static int hf_ssh_signature_length;
397
static int hf_ssh_pk_sig_blob_name_length;
398
static int hf_ssh_pk_sig_blob_name;
399
static int hf_ssh_connection_type_name_len;
400
static int hf_ssh_connection_type_name;
401
static int hf_ssh_connection_sender_channel;
402
static int hf_ssh_connection_recipient_channel;
403
static int hf_ssh_connection_initial_window;
404
static int hf_ssh_connection_maximum_packet_size;
405
static int hf_ssh_global_request_name_len;
406
static int hf_ssh_global_request_name;
407
static int hf_ssh_global_request_want_reply;
408
static int hf_ssh_global_request_hostkeys_array_len;
409
static int hf_ssh_channel_request_name_len;
410
static int hf_ssh_channel_request_name;
411
static int hf_ssh_channel_request_want_reply;
412
static int hf_ssh_subsystem_name_len;
413
static int hf_ssh_subsystem_name;
414
static int hf_ssh_exec_cmd;
415
static int hf_ssh_env_name;
416
static int hf_ssh_env_value;
417
static int hf_ssh_pty_term;
418
static int hf_ssh_pty_term_width_char;
419
static int hf_ssh_pty_term_height_row;
420
static int hf_ssh_pty_term_width_pixel;
421
static int hf_ssh_pty_term_height_pixel;
422
static int hf_ssh_pty_term_modes_len;
423
static int hf_ssh_pty_term_modes;
424
static int hf_ssh_pty_term_mode;
425
static int hf_ssh_pty_term_mode_opcode;
426
static int hf_ssh_pty_term_mode_vintr;
427
static int hf_ssh_pty_term_mode_vquit;
428
static int hf_ssh_pty_term_mode_verase;
429
static int hf_ssh_pty_term_mode_vkill;
430
static int hf_ssh_pty_term_mode_veof;
431
static int hf_ssh_pty_term_mode_veol;
432
static int hf_ssh_pty_term_mode_veol2;
433
static int hf_ssh_pty_term_mode_vstart;
434
static int hf_ssh_pty_term_mode_vstop;
435
static int hf_ssh_pty_term_mode_vsusp;
436
static int hf_ssh_pty_term_mode_vdsusp;
437
static int hf_ssh_pty_term_mode_vreprint;
438
static int hf_ssh_pty_term_mode_vwerase;
439
static int hf_ssh_pty_term_mode_vlnext;
440
static int hf_ssh_pty_term_mode_vflush;
441
static int hf_ssh_pty_term_mode_vswtch;
442
static int hf_ssh_pty_term_mode_vstatus;
443
static int hf_ssh_pty_term_mode_vdiscard;
444
static int hf_ssh_pty_term_mode_ignpar;
445
static int hf_ssh_pty_term_mode_parmrk;
446
static int hf_ssh_pty_term_mode_inpck;
447
static int hf_ssh_pty_term_mode_istrip;
448
static int hf_ssh_pty_term_mode_inlcr;
449
static int hf_ssh_pty_term_mode_igncr;
450
static int hf_ssh_pty_term_mode_icrnl;
451
static int hf_ssh_pty_term_mode_iuclc;
452
static int hf_ssh_pty_term_mode_ixon;
453
static int hf_ssh_pty_term_mode_ixany;
454
static int hf_ssh_pty_term_mode_ixoff;
455
static int hf_ssh_pty_term_mode_imaxbel;
456
static int hf_ssh_pty_term_mode_iutf8;
457
static int hf_ssh_pty_term_mode_isig;
458
static int hf_ssh_pty_term_mode_icanon;
459
static int hf_ssh_pty_term_mode_xcase;
460
static int hf_ssh_pty_term_mode_echo;
461
static int hf_ssh_pty_term_mode_echoe;
462
static int hf_ssh_pty_term_mode_echok;
463
static int hf_ssh_pty_term_mode_echonl;
464
static int hf_ssh_pty_term_mode_noflsh;
465
static int hf_ssh_pty_term_mode_tostop;
466
static int hf_ssh_pty_term_mode_iexten;
467
static int hf_ssh_pty_term_mode_echoctl;
468
static int hf_ssh_pty_term_mode_echoke;
469
static int hf_ssh_pty_term_mode_pendin;
470
static int hf_ssh_pty_term_mode_opost;
471
static int hf_ssh_pty_term_mode_olcuc;
472
static int hf_ssh_pty_term_mode_onlcr;
473
static int hf_ssh_pty_term_mode_ocrnl;
474
static int hf_ssh_pty_term_mode_onocr;
475
static int hf_ssh_pty_term_mode_onlret;
476
static int hf_ssh_pty_term_mode_cs7;
477
static int hf_ssh_pty_term_mode_cs8;
478
static int hf_ssh_pty_term_mode_parenb;
479
static int hf_ssh_pty_term_mode_parodd;
480
static int hf_ssh_pty_term_mode_ispeed;
481
static int hf_ssh_pty_term_mode_ospeed;
482
static int hf_ssh_pty_term_mode_value;
483
static int hf_ssh_channel_window_adjust;
484
static int hf_ssh_channel_data_len;
485
static int hf_ssh_channel_data_type_code;
486
static int hf_ssh_exit_status;
487
static int hf_ssh_disconnect_reason;
488
static int hf_ssh_disconnect_description_length;
489
static int hf_ssh_disconnect_description;
490
static int hf_ssh_lang_tag_length;
491
static int hf_ssh_lang_tag;
492
static int hf_ssh_ping_data_length;
493
static int hf_ssh_ping_data;
494
static int hf_ssh_pong_data_length;
495
static int hf_ssh_pong_data;
496
497
static int hf_ssh_blob;
498
static int hf_ssh_blob_e;
499
static int hf_ssh_blob_n;
500
static int hf_ssh_blob_dsa_p;
501
static int hf_ssh_blob_dsa_q;
502
static int hf_ssh_blob_dsa_g;
503
static int hf_ssh_blob_dsa_y;
504
static int hf_ssh_blob_ecdsa_curve_id;
505
static int hf_ssh_blob_ecdsa_curve_id_length;
506
static int hf_ssh_blob_ecdsa_q;
507
static int hf_ssh_blob_ecdsa_q_length;
508
static int hf_ssh_blob_eddsa_key;
509
static int hf_ssh_blob_eddsa_key_length;
510
static int hf_ssh_blob_data;
511
512
static int hf_ssh_pk_sig_s_length;
513
static int hf_ssh_pk_sig_s;
514
515
static int hf_ssh_reassembled_in;
516
static int hf_ssh_reassembled_length;
517
static int hf_ssh_reassembled_data;
518
static int hf_ssh_segments;
519
static int hf_ssh_segment;
520
static int hf_ssh_segment_overlap;
521
static int hf_ssh_segment_overlap_conflict;
522
static int hf_ssh_segment_multiple_tails;
523
static int hf_ssh_segment_too_long_fragment;
524
static int hf_ssh_segment_error;
525
static int hf_ssh_segment_count;
526
static int hf_ssh_segment_data;
527
528
static int ett_ssh;
529
static int ett_key_exchange;
530
static int ett_key_exchange_host_key;
531
static int ett_key_exchange_host_sig;
532
static int ett_extension;
533
static int ett_userauth_pk_blob;
534
static int ett_userauth_pk_signature;
535
static int ett_term_modes;
536
static int ett_term_mode;
537
static int ett_key_init;
538
static int ett_ssh1;
539
static int ett_ssh2;
540
static int ett_ssh_segments;
541
static int ett_ssh_segment;
542
static int ett_ssh_pqhybrid_client;
543
static int ett_ssh_pqhybrid_server;
544
545
static expert_field ei_ssh_packet_length;
546
static expert_field ei_ssh_padding_length;
547
static expert_field ei_ssh_packet_decode;
548
static expert_field ei_ssh_channel_number;
549
static expert_field ei_ssh_invalid_keylen;
550
static expert_field ei_ssh_mac_bad;
551
static expert_field ei_ssh2_kex_hybrid_msg_code;
552
static expert_field ei_ssh2_kex_hybrid_msg_code_unknown;
553
554
static bool ssh_desegment = true;
555
static bool ssh_ignore_mac_failed;
556
557
static dissector_handle_t ssh_handle;
558
static dissector_handle_t sftp_handle;
559
static dissector_handle_t data_text_lines_handle;
560
561
static const char   *pref_keylog_file;
562
static FILE         *ssh_keylog_file;
563
564
static reassembly_table ssh_reassembly_table;
565
566
static const fragment_items ssh_segment_items = {
567
    &ett_ssh_segment,
568
    &ett_ssh_segments,
569
    &hf_ssh_segments,
570
    &hf_ssh_segment,
571
    &hf_ssh_segment_overlap,
572
    &hf_ssh_segment_overlap_conflict,
573
    &hf_ssh_segment_multiple_tails,
574
    &hf_ssh_segment_too_long_fragment,
575
    &hf_ssh_segment_error,
576
    &hf_ssh_segment_count,
577
    &hf_ssh_reassembled_in,
578
    &hf_ssh_reassembled_length,
579
    &hf_ssh_reassembled_data,
580
    "Segments"
581
};
582
583
#define SSH_DECRYPT_DEBUG
584
585
#ifdef SSH_DECRYPT_DEBUG
586
static const char *ssh_debug_file_name;
587
#endif
588
589
14
#define TCP_RANGE_SSH  "22"
590
14
#define SCTP_PORT_SSH 22
591
592
/* Message Numbers (from RFC 4250) (1-255) */
593
594
/* Transport layer protocol: generic (1-19) */
595
0
#define SSH_MSG_DISCONNECT          1
596
0
#define SSH_MSG_IGNORE              2
597
#define SSH_MSG_UNIMPLEMENTED       3
598
0
#define SSH_MSG_DEBUG               4
599
0
#define SSH_MSG_SERVICE_REQUEST     5
600
0
#define SSH_MSG_SERVICE_ACCEPT      6
601
0
#define SSH_MSG_EXT_INFO            7
602
#define SSH_MSG_NEWCOMPRESS         8
603
604
/* Transport layer protocol: Algorithm negotiation (20-29) */
605
0
#define SSH_MSG_KEXINIT             20
606
0
#define SSH_MSG_NEWKEYS             21
607
608
/* Transport layer: Key exchange method specific (reusable) (30-49) */
609
0
#define SSH_MSG_KEXDH_INIT          30
610
0
#define SSH_MSG_KEXDH_REPLY         31
611
612
0
#define SSH_MSG_KEX_DH_GEX_REQUEST_OLD  30
613
0
#define SSH_MSG_KEX_DH_GEX_GROUP        31
614
0
#define SSH_MSG_KEX_DH_GEX_INIT         32
615
0
#define SSH_MSG_KEX_DH_GEX_REPLY        33
616
0
#define SSH_MSG_KEX_DH_GEX_REQUEST      34
617
618
0
#define SSH_MSG_KEX_ECDH_INIT       30
619
0
#define SSH_MSG_KEX_ECDH_REPLY      31
620
621
0
#define SSH_MSG_KEX_HYBRID_INIT     30
622
0
#define SSH_MSG_KEX_HYBRID_REPLY    31
623
624
/* User authentication protocol: generic (50-59) */
625
0
#define SSH_MSG_USERAUTH_REQUEST    50
626
0
#define SSH_MSG_USERAUTH_FAILURE    51
627
#define SSH_MSG_USERAUTH_SUCCESS    52
628
#define SSH_MSG_USERAUTH_BANNER     53
629
630
/* User authentication protocol: method specific (reusable) (50-79) */
631
0
#define SSH_MSG_USERAUTH_PK_OK      60
632
633
/* Connection protocol: generic (80-89) */
634
0
#define SSH_MSG_GLOBAL_REQUEST          80
635
#define SSH_MSG_REQUEST_SUCCESS         81
636
#define SSH_MSG_REQUEST_FAILURE         82
637
638
/* Connection protocol: channel related messages (90-127) */
639
0
#define SSH_MSG_CHANNEL_OPEN                90
640
0
#define SSH_MSG_CHANNEL_OPEN_CONFIRMATION   91
641
#define SSH_MSG_CHANNEL_OPEN_FAILURE        92
642
0
#define SSH_MSG_CHANNEL_WINDOW_ADJUST       93
643
0
#define SSH_MSG_CHANNEL_DATA                94
644
0
#define SSH_MSG_CHANNEL_EXTENDED_DATA       95
645
0
#define SSH_MSG_CHANNEL_EOF                 96
646
0
#define SSH_MSG_CHANNEL_CLOSE               97
647
0
#define SSH_MSG_CHANNEL_REQUEST             98
648
0
#define SSH_MSG_CHANNEL_SUCCESS             99
649
#define SSH_MSG_CHANNEL_FAILURE             100
650
651
/* 128-191 reserved for client protocols */
652
/* 192-255 local extensions */
653
0
#define SSH_MSG_PING                        192
654
0
#define SSH_MSG_PONG                        193
655
656
0
#define CIPHER_AES128_CTR               0x00010001
657
0
#define CIPHER_AES192_CTR               0x00010003
658
0
#define CIPHER_AES256_CTR               0x00010004
659
0
#define CIPHER_AES128_CBC               0x00020001
660
0
#define CIPHER_AES192_CBC               0x00020002
661
0
#define CIPHER_AES256_CBC               0x00020004
662
0
#define CIPHER_AES128_GCM               0x00040001
663
//#define CIPHER_AES192_GCM               0x00040002        -- does not exist
664
0
#define CIPHER_AES256_GCM               0x00040004
665
// DO NOT USE 0x00040000 (used by SSH_KEX_SNTRUP761X25519)
666
44
#define CIPHER_NULL                     0x00080000
667
668
0
#define CIPHER_MAC_SHA2_256             0x00020001
669
670
#define SSH_EXTENDED_DATA_STDERR    1
671
672
0
#define SSH_TTY_OP_END      0
673
0
#define SSH_TTY_OP_VINTR    1
674
0
#define SSH_TTY_OP_VQUIT    2
675
0
#define SSH_TTY_OP_VERASE   3
676
0
#define SSH_TTY_OP_VKILL    4
677
0
#define SSH_TTY_OP_VEOF     5
678
0
#define SSH_TTY_OP_VEOL     6
679
0
#define SSH_TTY_OP_VEOL2    7
680
0
#define SSH_TTY_OP_VSTART   8
681
0
#define SSH_TTY_OP_VSTOP    9
682
0
#define SSH_TTY_OP_VSUSP    10
683
0
#define SSH_TTY_OP_VDSUSP   11
684
0
#define SSH_TTY_OP_VREPRINT 12
685
0
#define SSH_TTY_OP_VWERASE  13
686
0
#define SSH_TTY_OP_VLNEXT   14
687
0
#define SSH_TTY_OP_VFLUSH   15
688
0
#define SSH_TTY_OP_VSWTCH   16
689
0
#define SSH_TTY_OP_VSTATUS  17
690
0
#define SSH_TTY_OP_VDISCARD 18
691
0
#define SSH_TTY_OP_IGNPAR   30
692
0
#define SSH_TTY_OP_PARMRK   31
693
0
#define SSH_TTY_OP_INPCK    32
694
0
#define SSH_TTY_OP_ISTRIP   33
695
0
#define SSH_TTY_OP_INLCR    34
696
0
#define SSH_TTY_OP_IGNCR    35
697
0
#define SSH_TTY_OP_ICRNL    36
698
0
#define SSH_TTY_OP_IUCLC    37
699
0
#define SSH_TTY_OP_IXON     38
700
0
#define SSH_TTY_OP_IXANY    39
701
0
#define SSH_TTY_OP_IXOFF    40
702
0
#define SSH_TTY_OP_IMAXBEL  41
703
0
#define SSH_TTY_OP_IUTF8    42
704
0
#define SSH_TTY_OP_ISIG     50
705
0
#define SSH_TTY_OP_ICANON   51
706
0
#define SSH_TTY_OP_XCASE    52
707
0
#define SSH_TTY_OP_ECHO     53
708
0
#define SSH_TTY_OP_ECHOE    54
709
0
#define SSH_TTY_OP_ECHOK    55
710
0
#define SSH_TTY_OP_ECHONL   56
711
0
#define SSH_TTY_OP_NOFLSH   57
712
0
#define SSH_TTY_OP_TOSTOP   58
713
0
#define SSH_TTY_OP_IEXTEN   59
714
0
#define SSH_TTY_OP_ECHOCTL  60
715
0
#define SSH_TTY_OP_ECHOKE   61
716
0
#define SSH_TTY_OP_PENDIN   62
717
0
#define SSH_TTY_OP_OPOST    70
718
0
#define SSH_TTY_OP_OLCUC    71
719
0
#define SSH_TTY_OP_ONLCR    72
720
0
#define SSH_TTY_OP_OCRNL    73
721
0
#define SSH_TTY_OP_ONOCR    74
722
0
#define SSH_TTY_OP_ONLRET   75
723
0
#define SSH_TTY_OP_CS7      90
724
0
#define SSH_TTY_OP_CS8      91
725
0
#define SSH_TTY_OP_PARENB   92
726
0
#define SSH_TTY_OP_PARODD   93
727
0
#define SSH_TTY_OP_ISPEED   128
728
0
#define SSH_TTY_OP_OSPEED   129
729
730
static const value_string ssh2_msg_vals[] = {
731
    { SSH_MSG_DISCONNECT,                "Disconnect" },
732
    { SSH_MSG_IGNORE,                    "Ignore" },
733
    { SSH_MSG_UNIMPLEMENTED,             "Unimplemented" },
734
    { SSH_MSG_DEBUG,                     "Debug" },
735
    { SSH_MSG_SERVICE_REQUEST,           "Service Request" },
736
    { SSH_MSG_SERVICE_ACCEPT,            "Service Accept" },
737
    { SSH_MSG_EXT_INFO,                  "Extension Information" },
738
    { SSH_MSG_NEWCOMPRESS,               "New Compression" },
739
    { SSH_MSG_KEXINIT,                   "Key Exchange Init" },
740
    { SSH_MSG_NEWKEYS,                   "New Keys" },
741
    { SSH_MSG_USERAUTH_REQUEST,          "User Authentication Request" },
742
    { SSH_MSG_USERAUTH_FAILURE,          "User Authentication Failure" },
743
    { SSH_MSG_USERAUTH_SUCCESS,          "User Authentication Success" },
744
    { SSH_MSG_USERAUTH_BANNER,           "User Authentication Banner" },
745
    { SSH_MSG_GLOBAL_REQUEST,            "Global Request" },
746
    { SSH_MSG_REQUEST_SUCCESS,           "Request Success" },
747
    { SSH_MSG_REQUEST_FAILURE,           "Request Failure" },
748
    { SSH_MSG_CHANNEL_OPEN,              "Channel Open" },
749
    { SSH_MSG_CHANNEL_OPEN_CONFIRMATION, "Channel Open Confirmation" },
750
    { SSH_MSG_CHANNEL_OPEN_FAILURE,      "Channel Open Failure" },
751
    { SSH_MSG_CHANNEL_WINDOW_ADJUST,     "Window Adjust" },
752
    { SSH_MSG_CHANNEL_DATA,              "Channel Data" },
753
    { SSH_MSG_CHANNEL_EXTENDED_DATA,     "Channel Extended Data" },
754
    { SSH_MSG_CHANNEL_EOF,               "Channel EOF" },
755
    { SSH_MSG_CHANNEL_CLOSE,             "Channel Close" },
756
    { SSH_MSG_CHANNEL_REQUEST,           "Channel Request" },
757
    { SSH_MSG_CHANNEL_SUCCESS,           "Channel Success" },
758
    { SSH_MSG_CHANNEL_FAILURE,           "Channel Failure" },
759
    { SSH_MSG_USERAUTH_PK_OK,            "Public Key algorithm accepted" },
760
    { 0, NULL }
761
};
762
763
static const value_string ssh2_kex_dh_msg_vals[] = {
764
    { SSH_MSG_KEXDH_INIT,                "Diffie-Hellman Key Exchange Init" },
765
    { SSH_MSG_KEXDH_REPLY,               "Diffie-Hellman Key Exchange Reply" },
766
    { 0, NULL }
767
};
768
769
static const value_string ssh2_kex_dh_gex_msg_vals[] = {
770
    { SSH_MSG_KEX_DH_GEX_REQUEST_OLD,    "Diffie-Hellman Group Exchange Request (Old)" },
771
    { SSH_MSG_KEX_DH_GEX_GROUP,          "Diffie-Hellman Group Exchange Group" },
772
    { SSH_MSG_KEX_DH_GEX_INIT,           "Diffie-Hellman Group Exchange Init" },
773
    { SSH_MSG_KEX_DH_GEX_REPLY,          "Diffie-Hellman Group Exchange Reply" },
774
    { SSH_MSG_KEX_DH_GEX_REQUEST,        "Diffie-Hellman Group Exchange Request" },
775
    { 0, NULL }
776
};
777
778
static const value_string ssh2_kex_ecdh_msg_vals[] = {
779
    { SSH_MSG_KEX_ECDH_INIT,             "Elliptic Curve Diffie-Hellman Key Exchange Init" },
780
    { SSH_MSG_KEX_ECDH_REPLY,            "Elliptic Curve Diffie-Hellman Key Exchange Reply" },
781
    { 0, NULL }
782
};
783
784
static const value_string ssh2_kex_hybrid_msg_vals[] = {
785
    { SSH_MSG_KEX_HYBRID_INIT,           "PQ/T Hybrid Key Exchange Init" },
786
    { SSH_MSG_KEX_HYBRID_REPLY,          "PQ/T Hybrid Key Exchange Reply" },
787
    { 0, NULL }
788
};
789
790
static const value_string ssh2_ext_ping_msg_vals[] = {
791
    { SSH_MSG_PING,                     "Ping" },
792
    { SSH_MSG_PONG,                     "Pong" },
793
    { 0, NULL }
794
};
795
796
static const value_string ssh1_msg_vals[] = {
797
    {SSH1_MSG_NONE,                      "No Message"},
798
    {SSH1_MSG_DISCONNECT,                "Disconnect"},
799
    {SSH1_SMSG_PUBLIC_KEY,               "Public Key"},
800
    {SSH1_CMSG_SESSION_KEY,              "Session Key"},
801
    {SSH1_CMSG_USER,                     "User"},
802
    {0, NULL}
803
};
804
805
static const value_string ssh_channel_data_type_code_vals[] = {
806
    { SSH_EXTENDED_DATA_STDERR, "Standard Error" },
807
    { 0, NULL }
808
};
809
810
static const value_string ssh_tty_op_vals[] = {
811
    { SSH_TTY_OP_END,       "TTY_OP_END" }, // [RFC4250]
812
    { SSH_TTY_OP_VINTR,     "VINTR" }, // [RFC4254],Section 8
813
    { SSH_TTY_OP_VQUIT,     "VQUIT" }, // [RFC4254],Section 8
814
    { SSH_TTY_OP_VERASE,    "VERASE" }, // [RFC4254],Section 8
815
    { SSH_TTY_OP_VKILL,     "VKILL" }, // [RFC4254], Section 8
816
    { SSH_TTY_OP_VEOF,      "VEOF" }, // [RFC4254],Section 8
817
    { SSH_TTY_OP_VEOL,      "VEOL" }, // [RFC4254],Section 8
818
    { SSH_TTY_OP_VEOL2,     "VEOL2" }, // [RFC4254], Section 8
819
    { SSH_TTY_OP_VSTART,    "VSTART" }, // [RFC4254],Section 8
820
    { SSH_TTY_OP_VSTOP,     "VSTOP" }, // [RFC4254], Section 8
821
    { SSH_TTY_OP_VSUSP,     "VSUSP" }, // [RFC4254], Section 8
822
    { SSH_TTY_OP_VDSUSP,    "VDSUSP" }, // [RFC4254], Section 8
823
    { SSH_TTY_OP_VREPRINT,  "VREPRINT" }, // [RFC4254], Section 8
824
    { SSH_TTY_OP_VWERASE,   "VWERASE" }, // [RFC4254], Section 8
825
    { SSH_TTY_OP_VLNEXT,    "VLNEXT" }, // [RFC4254],Section 8
826
    { SSH_TTY_OP_VFLUSH,    "VFLUSH" }, // [RFC4254], Section 8
827
    { SSH_TTY_OP_VSWTCH,    "VSWTCH" }, // [RFC4254], Section 8
828
    { SSH_TTY_OP_VSTATUS,   "VSTATUS" }, // [RFC4254],Section 8
829
    { SSH_TTY_OP_VDISCARD,  "VDISCARD" }, // [RFC4254], Section 8
830
    { SSH_TTY_OP_IGNPAR,    "IGNPAR" }, // [RFC4254],Section 8
831
    { SSH_TTY_OP_PARMRK,    "PARMRK" }, // [RFC4254], Section 8
832
    { SSH_TTY_OP_INPCK,     "INPCK" }, // [RFC4254], Section 8
833
    { SSH_TTY_OP_ISTRIP,    "ISTRIP" }, // [RFC4254], Section 8
834
    { SSH_TTY_OP_INLCR,     "INLCR" }, // [RFC4254], Section 8
835
    { SSH_TTY_OP_IGNCR,     "IGNCR" }, // [RFC4254], Section 8
836
    { SSH_TTY_OP_ICRNL,     "ICRNL" }, // [RFC4254], Section 8
837
    { SSH_TTY_OP_IUCLC,     "IUCLC" }, // [RFC4254],Section 8
838
    { SSH_TTY_OP_IXON,      "IXON" }, // [RFC4254], Section 8
839
    { SSH_TTY_OP_IXANY,     "IXANY" }, // [RFC4254], Section 8
840
    { SSH_TTY_OP_IXOFF,     "IXOFF" }, // [RFC4254], Section 8
841
    { SSH_TTY_OP_IMAXBEL,   "IMAXBEL" }, // [RFC4254], Section 8
842
    { SSH_TTY_OP_IUTF8,     "IUTF8" }, // [RFC8160],
843
    { SSH_TTY_OP_ISIG,      "ISIG" }, // [RFC4254], Section 8
844
    { SSH_TTY_OP_ICANON,    "ICANON" }, // [RFC4254], Section 8
845
    { SSH_TTY_OP_XCASE,     "XCASE" }, // [RFC4254],Section 8
846
    { SSH_TTY_OP_ECHO,      "ECHO" }, // [RFC4254], Section 8
847
    { SSH_TTY_OP_ECHOE,     "ECHOE" }, // [RFC4254], Section 8
848
    { SSH_TTY_OP_ECHOK,     "ECHOK" }, // [RFC4254], Section 8
849
    { SSH_TTY_OP_ECHONL,    "ECHONL" }, // [RFC4254], Section 8
850
    { SSH_TTY_OP_NOFLSH,    "NOFLSH" }, // [RFC4254],Section 8
851
    { SSH_TTY_OP_TOSTOP,    "TOSTOP" }, // [RFC4254], Section 8
852
    { SSH_TTY_OP_IEXTEN,    "IEXTEN" }, // [RFC4254], Section 8
853
    { SSH_TTY_OP_ECHOCTL,   "ECHOCTL" }, // [RFC4254], Section 8
854
    { SSH_TTY_OP_ECHOKE,    "ECHOKE" }, // [RFC4254], Section 8
855
    { SSH_TTY_OP_PENDIN,    "PENDIN" }, // [RFC4254], Section 8
856
    { SSH_TTY_OP_OPOST,     "OPOST" }, // [RFC4254], Section 8
857
    { SSH_TTY_OP_OLCUC,     "OLCUC" }, // [RFC4254], Section 8
858
    { SSH_TTY_OP_ONLCR,     "ONLCR" }, // [RFC4254], Section 8
859
    { SSH_TTY_OP_OCRNL,     "OCRNL" }, // [RFC4254],Section 8
860
    { SSH_TTY_OP_ONOCR,     "ONOCR" }, // [RFC4254],Section 8
861
    { SSH_TTY_OP_ONLRET,    "ONLRET" }, // [RFC4254],Section 8
862
    { SSH_TTY_OP_CS7,       "CS7" }, // [RFC4254], Section 8
863
    { SSH_TTY_OP_CS8,       "CS8" }, // [RFC4254], Section 8
864
    { SSH_TTY_OP_PARENB,    "PARENB" }, // [RFC4254], Section 8
865
    { SSH_TTY_OP_PARODD,    "PARODD" }, // [RFC4254], Section 8
866
    { SSH_TTY_OP_ISPEED,    "TTY_OP_ISPEED" }, // [RFC4254],Section 8
867
    { SSH_TTY_OP_OSPEED,    "TTY_OP_OSPEED" }, // [RFC4254],Section 8
868
    { 0, NULL }
869
};
870
871
static int ssh_dissect_key_init(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree,
872
        int is_response,
873
        struct ssh_flow_data *global_data);
874
static int ssh_dissect_proposal(tvbuff_t *tvb, int offset, proto_tree *tree,
875
        int hf_index_length, int hf_index_value, char **store);
876
static int ssh_dissect_ssh1(tvbuff_t *tvb, packet_info *pinfo,
877
        struct ssh_flow_data *global_data,
878
        int offset, proto_tree *tree, int is_response,
879
        bool *need_desegmentation);
880
static int ssh_dissect_ssh2(tvbuff_t *tvb, packet_info *pinfo,
881
        struct ssh_flow_data *global_data,
882
        int offset, proto_tree *tree, int is_response,
883
        bool *need_desegmentation);
884
static int ssh_dissect_key_exchange(tvbuff_t *tvb, packet_info *pinfo,
885
        struct ssh_flow_data *global_data,
886
        int offset, proto_tree *tree, int is_response,
887
        bool *need_desegmentation);
888
static int ssh_dissect_kex_dh(uint8_t msg_code, tvbuff_t *tvb,
889
        packet_info *pinfo, int offset, proto_tree *tree,
890
        struct ssh_flow_data *global_data);
891
static int ssh_dissect_kex_dh_gex(uint8_t msg_code, tvbuff_t *tvb,
892
        packet_info *pinfo, int offset, proto_tree *tree,
893
        struct ssh_flow_data *global_data);
894
static int ssh_dissect_kex_ecdh(uint8_t msg_code, tvbuff_t *tvb,
895
        packet_info *pinfo, int offset, proto_tree *tree,
896
        struct ssh_flow_data *global_data);
897
static int ssh_dissect_kex_pq_hybrid(uint8_t msg_code, tvbuff_t *tvb,
898
        packet_info *pinfo, int offset, proto_tree *tree,
899
        struct ssh_flow_data *global_data);
900
static int  // add support of client PQ hybrid key (e)
901
ssh_read_e_pq(tvbuff_t *tvb, int offset, struct ssh_flow_data *global_data);
902
static int  // add support of server PQ hybrid key (f)
903
ssh_read_f_pq(tvbuff_t *tvb, int offset, struct ssh_flow_data *global_data);
904
static int ssh_dissect_protocol(tvbuff_t *tvb, packet_info *pinfo,
905
        struct ssh_flow_data *global_data,
906
        unsigned offset, proto_tree *tree, int is_response, unsigned *version,
907
        bool *need_desegmentation);
908
static int ssh_try_dissect_encrypted_packet(tvbuff_t *tvb, packet_info *pinfo,
909
        struct ssh_peer_data *peer_data, int offset, proto_tree *tree);
910
static int ssh_dissect_encrypted_packet(tvbuff_t *tvb, packet_info *pinfo,
911
        struct ssh_peer_data *peer_data,
912
        int offset, proto_tree *tree);
913
static bool ssh_choose_algo(char *client, char *server, char **result);
914
static void ssh_set_mac_length(struct ssh_peer_data *peer_data);
915
static void ssh_set_kex_specific_dissector(struct ssh_flow_data *global_data);
916
917
static void ssh_keylog_read_file(void);
918
static void ssh_keylog_process_line(const char *line);
919
static void ssh_keylog_process_lines(const uint8_t *data, unsigned datalen);
920
static void ssh_keylog_reset(void);
921
static ssh_bignum *ssh_kex_make_bignum(const uint8_t *data, unsigned length);
922
static bool ssh_read_e(tvbuff_t *tvb, int offset,
923
        struct ssh_flow_data *global_data);
924
static bool ssh_read_f(tvbuff_t *tvb, int offset,
925
        struct ssh_flow_data *global_data);
926
static ssh_bignum * ssh_read_mpint(tvbuff_t *tvb, int offset);
927
static void ssh_keylog_hash_write_secret(struct ssh_flow_data *global_data, wmem_allocator_t* tmp_allocator);
928
static ssh_bignum *ssh_kex_shared_secret(int kex_type, ssh_bignum *pub, ssh_bignum *priv, ssh_bignum *modulo);
929
static void ssh_hash_buffer_put_string(wmem_array_t *buffer, const uint8_t *string,
930
        unsigned len);
931
static void ssh_hash_buffer_put_uint32(wmem_array_t *buffer, unsigned val);
932
static char *ssh_string(wmem_allocator_t* allocator, const uint8_t *string, unsigned len);
933
static void ssh_derive_symmetric_keys(ssh_bignum *shared_secret,
934
        uint8_t *exchange_hash, unsigned hash_length,
935
        struct ssh_flow_data *global_data);
936
static void ssh_derive_symmetric_key(ssh_bignum *shared_secret,
937
        const uint8_t *exchange_hash, unsigned hash_length, char id,
938
        ssh_bignum *result_key, struct ssh_flow_data *global_data, unsigned we_need);
939
940
static void ssh_choose_enc_mac(struct ssh_flow_data *global_data);
941
static void ssh_decryption_set_cipher_id(struct ssh_peer_data *peer);
942
static void ssh_decryption_setup_cipher(struct ssh_peer_data *peer,
943
        ssh_bignum *iv, ssh_bignum *key);
944
static void ssh_decryption_set_mac_id(struct ssh_peer_data *peer);
945
static void ssh_decryption_setup_mac(struct ssh_peer_data *peer,
946
        ssh_bignum *iv);
947
static ssh_packet_info_t* ssh_get_packet_info(packet_info *pinfo, bool is_response);
948
static ssh_message_info_t* ssh_get_message(packet_info *pinfo, int record_id);
949
static unsigned ssh_decrypt_packet(tvbuff_t *tvb, packet_info *pinfo,
950
        struct ssh_peer_data *peer_data, int offset);
951
static bool ssh_decrypt_chacha20(gcry_cipher_hd_t hd, uint32_t seqnr,
952
        uint32_t counter, const unsigned char *ctext, unsigned ctext_len,
953
        unsigned char *plain, unsigned plain_len);
954
static int ssh_dissect_decrypted_packet(tvbuff_t *tvb, packet_info *pinfo,
955
        struct ssh_peer_data *peer_data, proto_tree *tree,
956
        ssh_message_info_t *message);
957
static int ssh_dissect_transport_generic(tvbuff_t *packet_tvb, packet_info *pinfo,
958
        int offset, struct ssh_peer_data *peer_data, proto_item *msg_type_tree, unsigned msg_code);
959
static int ssh_dissect_rfc8308_extension(tvbuff_t *packet_tvb, packet_info *pinfo,
960
        int offset, struct ssh_peer_data *peer_data, proto_item *msg_type_tree);
961
static int ssh_dissect_userauth_generic(tvbuff_t *packet_tvb, packet_info *pinfo,
962
        int offset, proto_item *msg_type_tree, unsigned msg_code);
963
static int ssh_dissect_userauth_specific(tvbuff_t *packet_tvb, packet_info *pinfo,
964
        int offset, proto_item *msg_type_tree, unsigned msg_code);
965
static int ssh_dissect_connection_specific(tvbuff_t *packet_tvb, packet_info *pinfo,
966
        struct ssh_peer_data *peer_data, int offset, proto_item *msg_type_tree,
967
        unsigned msg_code, ssh_message_info_t *message);
968
static int ssh_dissect_connection_generic(tvbuff_t *packet_tvb, packet_info *pinfo,
969
        int offset, proto_item *msg_type_tree, unsigned msg_code);
970
static int ssh_dissect_local_extension(tvbuff_t *packet_tvb, packet_info *pinfo,
971
        int offset, struct ssh_peer_data *peer_data, proto_item *msg_type_tree, unsigned msg_code);
972
static int ssh_dissect_public_key_blob(tvbuff_t *tvb, packet_info *pinfo,
973
        proto_item *msg_type_tree);
974
static int ssh_dissect_public_key_signature(tvbuff_t *packet_tvb, packet_info *pinfo,
975
        int offset, proto_item *msg_type_tree);
976
977
static void create_channel(struct ssh_peer_data *peer_data, uint32_t recipient_channel, uint32_t sender_channel);
978
static ssh_channel_info_t* get_channel_info_for_channel(struct ssh_peer_data *peer_data, uint32_t recipient_channel);
979
static void set_subdissector_for_channel(struct ssh_peer_data *peer_data, uint32_t recipient_channel, const char* subsystem_name);
980
981
14
#define SSH_DEBUG_USE_STDERR "-"
982
983
#ifdef SSH_DECRYPT_DEBUG
984
static void
985
ssh_debug_printf(const char* fmt,...) G_GNUC_PRINTF(1,2);
986
static void
987
ssh_print_data(const char* name, const unsigned char* data, size_t len);
988
static void
989
ssh_set_debug(const char* name);
990
static void
991
ssh_debug_flush(void);
992
#else
993
994
/* No debug: nullify debug operation*/
995
static inline void G_GNUC_PRINTF(1,2)
996
ssh_debug_printf(const char* fmt _U_,...)
997
{
998
}
999
#define ssh_print_data(a, b, c)
1000
#define ssh_print_string(a, b)
1001
#define ssh_set_debug(name)
1002
#define ssh_debug_flush()
1003
1004
#endif /* SSH_DECRYPT_DEBUG */
1005
1006
static void
1007
ssh_set_server(struct ssh_flow_data *global_data, address *addr, uint32_t port)
1008
23
{
1009
23
    copy_address_wmem(wmem_file_scope(), &global_data->srv_addr, addr);
1010
23
    global_data->srv_port = port;
1011
23
}
1012
1013
static bool
1014
ssh_packet_from_server(struct ssh_flow_data *session, const packet_info *pinfo)
1015
30
{
1016
30
    bool ret;
1017
30
    if (session && session->srv_addr.type != AT_NONE) {
1018
26
        ret = (session->srv_port == pinfo->srcport) &&
1019
8
              addresses_equal(&session->srv_addr, &pinfo->src);
1020
26
    } else {
1021
4
        ret = (pinfo->match_uint == pinfo->srcport);
1022
4
    }
1023
1024
30
    ssh_debug_printf("packet_from_server: is from server - %s\n", (ret)?"TRUE":"FALSE");
1025
30
    return ret;
1026
30
}
1027
1028
static bool
1029
0
ssh_peer_data_from_server(struct ssh_peer_data* peer_data) {
1030
0
    return &peer_data->global_data->peer_data[SERVER_PEER_DATA] == peer_data;
1031
0
}
1032
1033
static int
1034
dissect_ssh(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1035
30
{
1036
30
    proto_tree  *ssh_tree;
1037
30
    proto_item  *ti;
1038
30
    conversation_t *conversation;
1039
30
    int         last_offset, offset = 0;
1040
1041
30
    bool        is_response,
1042
30
                need_desegmentation;
1043
30
    unsigned    version;
1044
1045
30
    struct ssh_flow_data *global_data = NULL;
1046
30
    struct ssh_peer_data *peer_data;
1047
1048
30
    ssh_debug_printf("\ndissect_ssh enter frame #%u (%s)\n", pinfo->num, (pinfo->fd->visited)?"already visited":"first time");
1049
1050
30
    conversation = find_or_create_conversation(pinfo);
1051
1052
30
    global_data = (struct ssh_flow_data *)conversation_get_proto_data(conversation, proto_ssh);
1053
30
    if (!global_data) {
1054
23
        global_data = wmem_new0(wmem_file_scope(), struct ssh_flow_data);
1055
23
        global_data->version = SSH_VERSION_UNKNOWN;
1056
23
        global_data->kex_specific_dissector = ssh_dissect_kex_dh;
1057
23
        global_data->peer_data[CLIENT_PEER_DATA].mac_length = -1;
1058
23
        global_data->peer_data[SERVER_PEER_DATA].mac_length = -1;
1059
23
        global_data->peer_data[CLIENT_PEER_DATA].sequence_number = 0;
1060
23
        global_data->peer_data[SERVER_PEER_DATA].sequence_number = 0;
1061
23
        global_data->peer_data[CLIENT_PEER_DATA].bn_cookie = NULL;
1062
23
        global_data->peer_data[SERVER_PEER_DATA].bn_cookie = NULL;
1063
23
        global_data->peer_data[CLIENT_PEER_DATA].global_data = global_data;
1064
23
        global_data->peer_data[SERVER_PEER_DATA].global_data = global_data;
1065
23
        global_data->kex_client_version = wmem_array_new(wmem_file_scope(), 1);
1066
23
        global_data->kex_server_version = wmem_array_new(wmem_file_scope(), 1);
1067
23
        global_data->kex_client_key_exchange_init = wmem_array_new(wmem_file_scope(), 1);
1068
23
        global_data->kex_server_key_exchange_init = wmem_array_new(wmem_file_scope(), 1);
1069
23
        global_data->kex_server_host_key_blob = wmem_array_new(wmem_file_scope(), 1);
1070
23
        global_data->kex_gex_bits_min = wmem_array_new(wmem_file_scope(), 1);
1071
23
        global_data->kex_gex_bits_req = wmem_array_new(wmem_file_scope(), 1);
1072
23
        global_data->kex_gex_bits_max = wmem_array_new(wmem_file_scope(), 1);
1073
23
        global_data->kex_shared_secret = wmem_array_new(wmem_file_scope(), 1);
1074
23
        global_data->do_decrypt      = true;
1075
23
        global_data->ext_ping_openssh_offered = false;
1076
1077
        /* We expect to get the client message first. If this is from an
1078
         * an assigned server port, call it the server, otherwise call it
1079
         * the client.
1080
         * XXX - We don't unambiguously know which side is the server and
1081
         * which the client until the KEX specific _INIT and _REPLY messages;
1082
         * we ought to be able to handle the cases where the version string or
1083
         * KEXINIT messages are out of order or where the client version string
1084
         * is missing. */
1085
23
        if (pinfo->match_uint == pinfo->srcport) {
1086
4
            ssh_set_server(global_data, &pinfo->src, pinfo->srcport);
1087
19
        } else {
1088
19
            ssh_set_server(global_data, &pinfo->dst, pinfo->destport);
1089
19
        }
1090
1091
23
        conversation_add_proto_data(conversation, proto_ssh, global_data);
1092
23
    }
1093
1094
30
    is_response = ssh_packet_from_server(global_data, pinfo);
1095
30
    peer_data = &global_data->peer_data[is_response];
1096
1097
30
    ti = proto_tree_add_item(tree, proto_ssh, tvb, offset, -1, ENC_NA);
1098
30
    ssh_tree = proto_item_add_subtree(ti, ett_ssh);
1099
1100
30
    version = global_data->version;
1101
1102
30
    switch(version) {
1103
30
    case SSH_VERSION_UNKNOWN:
1104
30
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSH");
1105
30
        break;
1106
0
    case SSH_VERSION_1:
1107
0
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSHv1");
1108
0
        break;
1109
0
    case SSH_VERSION_2:
1110
0
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSHv2");
1111
0
        break;
1112
1113
30
    }
1114
1115
30
    col_clear(pinfo->cinfo, COL_INFO);
1116
1117
64
    while(tvb_reported_length_remaining(tvb, offset)> 0) {
1118
37
        bool after_version_start = (peer_data->frame_version_start == 0 ||
1119
12
            pinfo->num >= peer_data->frame_version_start);
1120
37
        bool before_version_end = (peer_data->frame_version_end == 0 ||
1121
12
            pinfo->num <= peer_data->frame_version_end);
1122
1123
37
        need_desegmentation = false;
1124
37
        last_offset = offset;
1125
1126
37
        peer_data->counter++;
1127
1128
37
        if (after_version_start && before_version_end &&
1129
34
              (tvb_strncaseeql(tvb, offset, "SSH-", 4) == 0)) {
1130
15
            if (peer_data->frame_version_start == 0)
1131
14
                peer_data->frame_version_start = pinfo->num;
1132
1133
15
            offset = ssh_dissect_protocol(tvb, pinfo,
1134
15
                    global_data,
1135
15
                    offset, ssh_tree, is_response,
1136
15
                    &version, &need_desegmentation);
1137
1138
15
            if (!need_desegmentation) {
1139
15
                peer_data->frame_version_end = pinfo->num;
1140
15
                global_data->version = version;
1141
15
            }
1142
22
        } else {
1143
22
            switch(version) {
1144
1145
22
            case SSH_VERSION_UNKNOWN:
1146
22
                offset = ssh_try_dissect_encrypted_packet(tvb, pinfo,
1147
22
                        &global_data->peer_data[is_response], offset, ssh_tree);
1148
22
                break;
1149
1150
0
            case SSH_VERSION_1:
1151
0
                offset = ssh_dissect_ssh1(tvb, pinfo, global_data,
1152
0
                        offset, ssh_tree, is_response,
1153
0
                        &need_desegmentation);
1154
0
                break;
1155
1156
0
            case SSH_VERSION_2:
1157
0
                offset = ssh_dissect_ssh2(tvb, pinfo, global_data,
1158
0
                        offset, ssh_tree, is_response,
1159
0
                        &need_desegmentation);
1160
0
                break;
1161
22
            }
1162
22
        }
1163
1164
34
        if (need_desegmentation)
1165
0
            return tvb_captured_length(tvb);
1166
34
        if (offset <= last_offset) {
1167
            /* XXX - add an expert info in the function
1168
               that decrements offset */
1169
0
            break;
1170
0
        }
1171
34
    }
1172
1173
27
    col_prepend_fstr(pinfo->cinfo, COL_INFO, "%s: ", is_response ? "Server" : "Client");
1174
27
    ti = proto_tree_add_boolean(ssh_tree, hf_ssh_direction, tvb, 0, 0, is_response);
1175
27
    proto_item_set_generated(ti);
1176
1177
27
    ssh_debug_flush();
1178
1179
27
    return tvb_captured_length(tvb);
1180
30
}
1181
1182
static bool
1183
dissect_ssh_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1184
2.21k
{
1185
2.21k
    conversation_t *conversation;
1186
1187
2.21k
    if (tvb_strneql(tvb, 0, "SSH-", 4) != 0) {
1188
2.20k
        return false;
1189
2.20k
    }
1190
1191
14
    conversation = find_or_create_conversation(pinfo);
1192
14
    conversation_set_dissector(conversation, ssh_handle);
1193
1194
14
    dissect_ssh(tvb, pinfo, tree, data);
1195
1196
14
    return true;
1197
2.21k
}
1198
1199
static int
1200
ssh_dissect_ssh2(tvbuff_t *tvb, packet_info *pinfo,
1201
        struct ssh_flow_data *global_data,
1202
        int offset, proto_tree *tree, int is_response,
1203
        bool *need_desegmentation)
1204
0
{
1205
0
    proto_item *ssh2_tree = NULL;
1206
0
    int remain_length;
1207
1208
0
    struct ssh_peer_data *peer_data = &global_data->peer_data[is_response];
1209
1210
0
    remain_length = tvb_captured_length_remaining(tvb, offset);
1211
1212
0
    if (PINFO_FD_VISITED(pinfo)) {
1213
0
        ws_debug("SSH: SECOND PASS frame %u", pinfo->num);
1214
0
    }else{
1215
0
        ws_debug("SSH: FIRST PASS frame %u", pinfo->num);
1216
0
    }
1217
1218
0
    while(remain_length>0){
1219
0
        int last_offset = offset;
1220
0
        if (tree) {
1221
0
            wmem_strbuf_t *title = wmem_strbuf_new(pinfo->pool, "SSH Version 2");
1222
1223
0
            if (peer_data->enc || peer_data->mac || peer_data->comp) {
1224
0
                wmem_strbuf_append_printf(title, " (");
1225
0
                if (peer_data->enc)
1226
0
                    wmem_strbuf_append_printf(title, "encryption:%s%s",
1227
0
                        peer_data->enc,
1228
0
                        peer_data->mac || peer_data->comp
1229
0
                            ? " " : "");
1230
0
                if (peer_data->mac)
1231
0
                    wmem_strbuf_append_printf(title, "mac:%s%s",
1232
0
                        peer_data->mac,
1233
0
                        peer_data->comp ? " " : "");
1234
0
                if (peer_data->comp)
1235
0
                    wmem_strbuf_append_printf(title, "compression:%s",
1236
0
                        peer_data->comp);
1237
0
                wmem_strbuf_append_printf(title, ")");
1238
0
            }
1239
1240
0
            ssh2_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_ssh2, NULL, wmem_strbuf_get_str(title));
1241
0
        }
1242
0
        ws_noisy("....ssh_dissect_ssh2[%c]: frame_key_start=%d, pinfo->num=%d, frame_key_end=%d, offset=%d, frame_key_end_offset=%d ", is_response==SERVER_PEER_DATA?'S':'C', peer_data->frame_key_start, pinfo->num, peer_data->frame_key_end, offset, peer_data->frame_key_end_offset);
1243
0
        if ((peer_data->frame_key_start == 0) ||
1244
0
            ((peer_data->frame_key_start <= pinfo->num) &&
1245
0
            ((peer_data->frame_key_end == 0) || (pinfo->num < peer_data->frame_key_end) ||
1246
0
                    ((pinfo->num == peer_data->frame_key_end) && (offset < peer_data->frame_key_end_offset))))) {
1247
0
            offset = ssh_dissect_key_exchange(tvb, pinfo, global_data,
1248
0
                offset, ssh2_tree, is_response,
1249
0
                need_desegmentation);
1250
1251
0
            if (!*need_desegmentation) {
1252
0
                ssh_get_packet_info(pinfo, is_response);
1253
0
            }else{
1254
0
                break;
1255
0
            }
1256
0
        } else {
1257
0
            if(!*need_desegmentation){
1258
0
                offset = ssh_try_dissect_encrypted_packet(tvb, pinfo,
1259
0
                        &global_data->peer_data[is_response], offset, ssh2_tree);
1260
0
                if (pinfo->desegment_len) {
1261
0
                    break;
1262
0
                }
1263
0
            }else{
1264
0
                break;
1265
0
            }
1266
0
        }
1267
1268
0
        if (ssh2_tree) {
1269
0
            proto_item_set_len(ssh2_tree, offset - last_offset);
1270
0
        }
1271
1272
0
        remain_length = tvb_captured_length_remaining(tvb, offset);
1273
0
    }
1274
1275
0
    return offset;
1276
0
}
1277
static int
1278
ssh_dissect_ssh1(tvbuff_t *tvb, packet_info *pinfo,
1279
        struct ssh_flow_data *global_data,
1280
        int offset, proto_tree *tree, int is_response,
1281
        bool *need_desegmentation)
1282
0
{
1283
0
    unsigned   plen, padding_length, len;
1284
0
    uint8_t msg_code;
1285
0
    unsigned   remain_length;
1286
1287
0
    proto_item *ssh1_tree;
1288
1289
0
    struct ssh_peer_data *peer_data = &global_data->peer_data[is_response];
1290
1291
0
    ssh1_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_ssh1, NULL, "SSH Version 1");
1292
1293
    /*
1294
     * We use "tvb_ensure_captured_length_remaining()" to make sure there
1295
     * actually *is* data remaining.
1296
     *
1297
     * This means we're guaranteed that "remain_length" is positive.
1298
     */
1299
0
    remain_length = tvb_ensure_captured_length_remaining(tvb, offset);
1300
    /*
1301
     * Can we do reassembly?
1302
     */
1303
0
    if (ssh_desegment && pinfo->can_desegment) {
1304
        /*
1305
         * Yes - would an SSH header starting at this offset be split
1306
         * across segment boundaries?
1307
         */
1308
0
        if (remain_length < 4) {
1309
            /*
1310
             * Yes.  Tell the TCP dissector where the data for
1311
             * this message starts in the data it handed us and
1312
             * that we need "some more data."  Don't tell it
1313
             * exactly how many bytes we need because if/when we
1314
             * ask for even more (after the header) that will
1315
             * break reassembly.
1316
             */
1317
0
            pinfo->desegment_offset = offset;
1318
0
            pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
1319
0
            *need_desegmentation = true;
1320
0
            return offset;
1321
0
        }
1322
0
    }
1323
0
    plen = tvb_get_ntohl(tvb, offset) ;
1324
1325
    /*
1326
     * Amount of random padding.
1327
     *
1328
     * This is between 1 and 8; if the length is a multiple of 8,
1329
     * there are 8 bytes of padding, not 1 byte.
1330
     *
1331
     * That means this calculation is correct; do not use either
1332
     * WS_ROUNDUP_8() or WS_PADDING_TO_8() here.
1333
     */
1334
0
    padding_length  = 8 - plen%8;
1335
1336
1337
0
    if (ssh_desegment && pinfo->can_desegment) {
1338
0
        if (plen+4+padding_length >  remain_length) {
1339
0
            pinfo->desegment_offset = offset;
1340
0
            pinfo->desegment_len = plen+padding_length - remain_length;
1341
0
            *need_desegmentation = true;
1342
0
            return offset;
1343
0
        }
1344
0
    }
1345
1346
0
    if (plen >= SSH_MAX_PACKET_LEN) {
1347
0
        if (ssh1_tree && plen > 0) {
1348
0
              proto_tree_add_uint_format(ssh1_tree, hf_ssh_packet_length, tvb,
1349
0
                offset, 4, plen, "Overly large length %x", plen);
1350
0
        }
1351
0
        plen = remain_length-4-padding_length;
1352
0
    } else {
1353
0
        if (ssh1_tree && plen > 0) {
1354
0
              proto_tree_add_uint(ssh1_tree, hf_ssh_packet_length, tvb,
1355
0
                offset, 4, plen);
1356
0
        }
1357
0
    }
1358
0
    offset+=4;
1359
    /* padding length */
1360
1361
0
    proto_tree_add_uint(ssh1_tree, hf_ssh_padding_length, tvb,
1362
0
            offset, padding_length, padding_length);
1363
0
    offset += padding_length;
1364
1365
    /* msg_code */
1366
0
    if ((peer_data->frame_key_start == 0) ||
1367
0
        ((peer_data->frame_key_start >= pinfo->num) && (pinfo->num <= peer_data->frame_key_end))) {
1368
1369
0
        proto_tree_add_item_ret_uint8(ssh1_tree, hf_ssh_msg_code, tvb, offset, 1, ENC_BIG_ENDIAN, &msg_code);
1370
0
        col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
1371
0
            val_to_str(pinfo->pool, msg_code, ssh1_msg_vals, "Unknown (%u)"));
1372
0
        offset += 1;
1373
0
        len = plen -1;
1374
0
        if (!pinfo->fd->visited) {
1375
0
            if (peer_data->frame_key_start == 0)
1376
0
                peer_data->frame_key_start = pinfo->num;
1377
0
            peer_data->frame_key_end = pinfo->num;
1378
0
        }
1379
0
    } else {
1380
0
        len = plen;
1381
0
        col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Encrypted packet (len=%d)", len);
1382
0
    }
1383
    /* payload */
1384
0
    if (ssh1_tree) {
1385
0
        proto_tree_add_item(ssh1_tree, hf_ssh_payload,
1386
0
            tvb, offset, len, ENC_NA);
1387
0
    }
1388
0
    offset += len;
1389
1390
0
    return offset;
1391
0
}
1392
1393
static int
1394
ssh_tree_add_mpint(tvbuff_t *tvb, int offset, proto_tree *tree,
1395
    int hf_ssh_mpint_selection)
1396
0
{
1397
0
    unsigned len = tvb_get_ntohl(tvb, offset);
1398
0
    proto_tree_add_uint(tree, hf_ssh_mpint_length, tvb,
1399
0
            offset, 4, len);
1400
0
    offset+=4;
1401
0
    proto_tree_add_item(tree, hf_ssh_mpint_selection,
1402
0
            tvb, offset, len, ENC_NA);
1403
0
    return 4+len;
1404
0
}
1405
1406
static int
1407
ssh_tree_add_string(tvbuff_t *tvb, int offset, proto_tree *tree,
1408
    int hf_ssh_string, int hf_ssh_string_length)
1409
0
{
1410
0
    unsigned len = tvb_get_ntohl(tvb, offset);
1411
0
    proto_tree_add_uint(tree, hf_ssh_string_length, tvb,
1412
0
            offset, 4, len);
1413
0
    offset+=4;
1414
0
    proto_tree_add_item(tree, hf_ssh_string,
1415
0
            tvb, offset, len, ENC_NA);
1416
0
    return 4+len;
1417
0
}
1418
1419
static unsigned
1420
ssh_tree_add_hostkey(tvbuff_t *tvb, packet_info* pinfo, int offset, proto_tree *parent_tree,
1421
                     const char *tree_name, int ett_idx,
1422
                     struct ssh_flow_data *global_data)
1423
0
{
1424
0
    proto_tree *tree = NULL;
1425
0
    proto_item *ti;
1426
0
    int last_offset;
1427
0
    int remaining_len;
1428
0
    unsigned key_len, type_len;
1429
0
    char* key_type;
1430
0
    char *tree_title;
1431
1432
0
    last_offset = offset;
1433
1434
0
    key_len = tvb_get_ntohl(tvb, offset);
1435
0
    offset += 4;
1436
1437
    /* Read the key type before creating the tree so we can append it as info. */
1438
0
    type_len = tvb_get_ntohl(tvb, offset);
1439
0
    offset += 4;
1440
0
    key_type = (char *) tvb_get_string_enc(pinfo->pool, tvb, offset, type_len, ENC_ASCII|ENC_NA);
1441
1442
0
    tree_title = wmem_strdup_printf(pinfo->pool, "%s (type: %s)", tree_name, key_type);
1443
0
    tree = proto_tree_add_subtree(parent_tree, tvb, last_offset, key_len + 4, ett_idx, NULL,
1444
0
                                  tree_title);
1445
1446
0
    ti = proto_tree_add_uint(tree, hf_ssh_hostkey_length, tvb, last_offset, 4, key_len);
1447
1448
    // server host key (K_S / Q)
1449
0
    uint8_t *data = (uint8_t *)tvb_memdup(pinfo->pool, tvb, last_offset + 4, key_len);
1450
0
    if (global_data) {
1451
        // Reset array while REKEY: sanitize server host key blob
1452
0
        global_data->kex_server_host_key_blob = wmem_array_new(wmem_file_scope(), 1);
1453
0
        ssh_hash_buffer_put_string(global_data->kex_server_host_key_blob, data, key_len);
1454
0
    }
1455
1456
0
    last_offset += 4;
1457
0
    proto_tree_add_uint(tree, hf_ssh_hostkey_type_length, tvb, last_offset, 4, type_len);
1458
0
    proto_tree_add_string(tree, hf_ssh_hostkey_type, tvb, offset, type_len, key_type);
1459
0
    offset += type_len;
1460
1461
0
    if (0 == strcmp(key_type, "ssh-rsa")) {
1462
0
        offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_hostkey_rsa_e);
1463
0
        offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_hostkey_rsa_n);
1464
0
    } else if (0 == strcmp(key_type, "ssh-dss")) {
1465
0
        offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_hostkey_dsa_p);
1466
0
        offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_hostkey_dsa_q);
1467
0
        offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_hostkey_dsa_g);
1468
0
        offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_hostkey_dsa_y);
1469
0
    } else if (g_str_has_prefix(key_type, "ecdsa-sha2-")) {
1470
0
        offset += ssh_tree_add_string(tvb, offset, tree,
1471
0
                                      hf_ssh_hostkey_ecdsa_curve_id, hf_ssh_hostkey_ecdsa_curve_id_length);
1472
0
        offset += ssh_tree_add_string(tvb, offset, tree,
1473
0
                            hf_ssh_hostkey_ecdsa_q, hf_ssh_hostkey_ecdsa_q_length);
1474
0
    } else if (g_str_has_prefix(key_type, "ssh-ed")) {
1475
0
        offset += ssh_tree_add_string(tvb, offset, tree,
1476
0
                            hf_ssh_hostkey_eddsa_key, hf_ssh_hostkey_eddsa_key_length);
1477
0
    } else {
1478
0
        remaining_len = key_len - (type_len + 4);
1479
0
        proto_tree_add_item(tree, hf_ssh_hostkey_data, tvb, offset, remaining_len, ENC_NA);
1480
0
        offset += remaining_len;
1481
0
    }
1482
1483
0
    if (last_offset + (int)key_len != offset) {
1484
0
        expert_add_info_format(pinfo, ti, &ei_ssh_packet_decode, "Decoded %d bytes, but hostkey length is %d bytes", offset - last_offset, key_len);
1485
0
    }
1486
0
    return 4+key_len;
1487
0
}
1488
1489
static unsigned
1490
ssh_tree_add_hostsignature(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *parent_tree,
1491
                     const char *tree_name, int ett_idx,
1492
                     struct ssh_flow_data *global_data)
1493
0
{
1494
0
    (void)global_data;
1495
0
    proto_tree *tree = NULL;
1496
0
    proto_item* ti = NULL;
1497
0
    int last_offset;
1498
0
    int offset0 = offset;
1499
0
    unsigned sig_len, type_len, data_len;
1500
0
    const char* sig_type;
1501
0
    char *tree_title;
1502
1503
0
    last_offset = offset;
1504
1505
0
    sig_len = tvb_get_ntohl(tvb, offset);
1506
0
    offset += 4;
1507
1508
    /* Read the signature type before creating the tree so we can append it as info. */
1509
0
    type_len = tvb_get_ntohl(tvb, offset);
1510
0
    offset += 4;
1511
0
    sig_type = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset, type_len, ENC_ASCII|ENC_NA);
1512
1513
0
    tree_title = wmem_strdup_printf(pinfo->pool, "%s (type: %s)", tree_name, sig_type);
1514
0
    tree = proto_tree_add_subtree(parent_tree, tvb, last_offset, sig_len + 4, ett_idx, NULL,
1515
0
                                  tree_title);
1516
1517
0
    ti = proto_tree_add_uint(tree, hf_ssh_hostsig_length, tvb, last_offset, 4, sig_len);
1518
1519
0
    last_offset += 4;
1520
0
    proto_tree_add_uint(tree, hf_ssh_hostsig_type_length, tvb, last_offset, 4, type_len);
1521
0
    proto_tree_add_string(tree, hf_ssh_hostsig_type, tvb, offset, type_len, sig_type);
1522
0
    offset += type_len;
1523
1524
0
    if (0 == strcmp(sig_type, "ssh-rsa")) {
1525
0
        offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_hostsig_rsa);
1526
0
    } else if (0 == strcmp(sig_type, "ssh-dss")) {
1527
0
        offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_hostsig_dsa);
1528
//    } else if (g_str_has_prefix(sig_type, "ecdsa-sha2-")) {
1529
//        offset += ssh_tree_add_string(tvb, offset, tree,
1530
//                                      hf_ssh_hostkey_ecdsa_curve_id, hf_ssh_hostkey_ecdsa_curve_id_length);
1531
//        ssh_tree_add_string(tvb, offset, tree,
1532
//                            hf_ssh_hostkey_ecdsa_q, hf_ssh_hostkey_ecdsa_q_length);
1533
//    } else if (g_str_has_prefix(sig_type, "ssh-ed")) {
1534
//        ssh_tree_add_string(tvb, offset, tree,
1535
//                            hf_ssh_hostkey_eddsa_key, hf_ssh_hostkey_eddsa_key_length);
1536
0
    } else {
1537
0
        proto_tree_add_item_ret_uint(tree, hf_ssh_hostsig_data_length, tvb, offset, 4, ENC_BIG_ENDIAN, &data_len);
1538
0
        offset += 4;
1539
0
        proto_tree_add_item(tree, hf_ssh_hostsig_data, tvb, offset, data_len, ENC_NA);
1540
0
        offset += data_len;
1541
0
    }
1542
1543
0
    if(offset-offset0!=(int)(4+sig_len)){
1544
0
        expert_add_info_format(pinfo, ti, &ei_ssh_packet_decode, "Decoded %d bytes, but packet length is %d bytes", offset-offset0, sig_len);
1545
0
    }
1546
1547
0
    return 4+sig_len;
1548
0
}
1549
1550
static int
1551
ssh_dissect_key_exchange(tvbuff_t *tvb, packet_info *pinfo,
1552
        struct ssh_flow_data *global_data,
1553
        int offset, proto_tree *tree, int is_response,
1554
        bool *need_desegmentation)
1555
0
{
1556
0
    unsigned   plen, len;
1557
0
    uint8_t padding_length;
1558
0
    unsigned   remain_length;
1559
0
    int     last_offset = offset;
1560
0
    unsigned   msg_code;
1561
1562
0
    proto_item *ti;
1563
0
    proto_item *key_ex_tree = NULL;
1564
0
    const char *key_ex_title = "Key Exchange";
1565
1566
0
    struct ssh_peer_data *peer_data = &global_data->peer_data[is_response];
1567
1568
0
    if (PINFO_FD_VISITED(pinfo)) {
1569
0
        ws_debug("SSH: SECOND PASS dissecting keys -for Wireshark UI- frame %u", pinfo->num);
1570
0
    }
1571
    /* This is after the identification string (Protocol Version Exchange)
1572
     * but before the first key exchange has completed, so we expect the SSH
1573
     * packets to be unencrypted, and to contain KEX related messages.
1574
     *
1575
     * XXX - Without the "strict kex" extension, other messages are allowed;
1576
     * most don't make sense (SSH_MSG_IGNORE and SSH_MSG_DEBUG might), but we
1577
     * could dissect them and add them to the tree.
1578
     *
1579
     * XXX - Could we combine this with ssh_dissect_decrypted_packet, with a
1580
     * flag to indicate whether we're before the initial key exchange?
1581
     */
1582
1583
    /*
1584
     * We use "tvb_ensure_captured_length_remaining()" to make sure there
1585
     * actually *is* data remaining.
1586
     *
1587
     * This means we're guaranteed that "remain_length" is positive.
1588
     */
1589
0
    remain_length = tvb_ensure_captured_length_remaining(tvb, offset);
1590
    /*
1591
     * Can we do reassembly?
1592
     */
1593
0
    if (ssh_desegment && pinfo->can_desegment) {
1594
        /*
1595
         * Yes - would an SSH header starting at this offset
1596
         * be split across segment boundaries?
1597
         */
1598
0
        if (remain_length < 4) {
1599
            /*
1600
             * Yes.  Tell the TCP dissector where the data for
1601
             * this message starts in the data it handed us and
1602
             * that we need "some more data."  Don't tell it
1603
             * exactly how many bytes we need because if/when we
1604
             * ask for even more (after the header) that will
1605
             * break reassembly.
1606
             */
1607
0
            pinfo->desegment_offset = offset;
1608
0
            pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
1609
0
            *need_desegmentation = true;
1610
0
            return offset;
1611
0
        }
1612
0
    }
1613
0
    plen = tvb_get_ntohl(tvb, offset) ;
1614
1615
0
    if (ssh_desegment && pinfo->can_desegment) {
1616
0
        if (plen +4 >  remain_length) {
1617
0
            pinfo->desegment_offset = offset;
1618
0
            pinfo->desegment_len = plen+4 - remain_length;
1619
0
            *need_desegmentation = true;
1620
0
            return offset;
1621
0
        }
1622
0
    }
1623
    /*
1624
     * Need to check plen > 0x80000000 here
1625
     */
1626
1627
0
    ti = proto_tree_add_uint(tree, hf_ssh_packet_length, tvb,
1628
0
                    offset, 4, plen);
1629
0
    if (plen >= SSH_MAX_PACKET_LEN) {
1630
0
        expert_add_info_format(pinfo, ti, &ei_ssh_packet_length, "Overly large number %d", plen);
1631
0
        plen = remain_length-4;
1632
1633
        /* XXX - Mark as Continuation Data and return without incrementing?
1634
         * Or do so *before* using this length to desegment? */
1635
0
    }
1636
0
    offset+=4;
1637
1638
0
    ssh_packet_info_t *packet = ssh_get_packet_info(pinfo, is_response);
1639
1640
0
    int record_id = tvb_raw_offset(tvb)+offset;
1641
0
    ssh_message_info_t *message;
1642
0
    message = ssh_get_message(pinfo, record_id);
1643
0
    if (!message) {
1644
0
        message = wmem_new0(wmem_file_scope(), ssh_message_info_t);
1645
0
        message->sequence_number = peer_data->sequence_number++;
1646
0
        message->id = record_id;
1647
        /* No data, and no MAC, as is this is before encryption starts. */
1648
0
        message->next = NULL;
1649
0
        ssh_debug_printf("%s->sequence_number++ > %d\n", is_response?"server":"client", peer_data->sequence_number);
1650
1651
0
        ssh_message_info_t **pmessage = &packet->messages;
1652
0
        while(*pmessage){
1653
0
            pmessage = &(*pmessage)->next;
1654
0
        }
1655
0
        *pmessage = message;
1656
0
    }
1657
1658
    /* padding length */
1659
0
    padding_length = tvb_get_uint8(tvb, offset);
1660
0
    proto_tree_add_uint(tree, hf_ssh_padding_length, tvb, offset, 1, padding_length);
1661
0
    offset += 1;
1662
1663
0
    if (global_data->kex)
1664
0
        key_ex_title = wmem_strdup_printf(pinfo->pool, "%s (method:%s)", key_ex_title, global_data->kex);
1665
0
    key_ex_tree = proto_tree_add_subtree(tree, tvb, offset, plen-1, ett_key_exchange, NULL, key_ex_title);
1666
1667
    /* msg_code */
1668
0
    msg_code = tvb_get_uint8(tvb, offset);
1669
1670
0
    if (msg_code >= 30 && msg_code < 40) {
1671
0
        offset = global_data->kex_specific_dissector(msg_code, tvb, pinfo,
1672
0
                offset, key_ex_tree, global_data);
1673
0
    } else {
1674
0
        proto_tree_add_item(key_ex_tree, hf_ssh2_msg_code, tvb, offset, 1, ENC_BIG_ENDIAN);
1675
0
        offset += 1;
1676
1677
0
        col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
1678
0
            val_to_str(pinfo->pool, msg_code, ssh2_msg_vals, "Unknown (%u)"));
1679
1680
        /* 16 bytes cookie  */
1681
0
        switch(msg_code)
1682
0
        {
1683
0
        case SSH_MSG_KEXINIT:
1684
0
            offset = ssh_dissect_key_init(tvb, pinfo, offset, key_ex_tree, is_response, global_data);
1685
0
            if ((peer_data->frame_key_start == 0) && (!PINFO_FD_VISITED(pinfo))) {
1686
0
                peer_data->frame_key_start = pinfo->num;
1687
0
            }
1688
0
            break;
1689
0
        case SSH_MSG_NEWKEYS:
1690
0
            if (peer_data->frame_key_end == 0) {
1691
0
                peer_data->frame_key_end = pinfo->num;
1692
0
                peer_data->frame_key_end_offset = offset;
1693
1694
0
                if (!PINFO_FD_VISITED(pinfo)) {
1695
                    /* "After sending or receiving a SSH2_MSG_NEWKEYS message,
1696
                     * reset the packet sequence number to zero. This behaviour
1697
                     * persists for the duration of the connection (i.e. not
1698
                     * just the first SSH2_MSG_NEWKEYS) */
1699
0
                    if (global_data->ext_kex_strict) {
1700
0
                        peer_data->sequence_number = 0;
1701
0
                        ssh_debug_printf("%s->sequence_number reset to 0 (Strict KEX)\n", is_response?"server":"client");
1702
0
                    }
1703
0
                }
1704
1705
                // the client sent SSH_MSG_NEWKEYS
1706
0
                if (!is_response) {
1707
0
                    ssh_debug_printf("Activating new keys for CLIENT => SERVER\n");
1708
0
                    ssh_decryption_setup_cipher(&global_data->peer_data[CLIENT_PEER_DATA], &global_data->new_keys[0], &global_data->new_keys[2]);
1709
0
                    ssh_decryption_setup_mac(&global_data->peer_data[CLIENT_PEER_DATA], &global_data->new_keys[4]);
1710
0
                }else{
1711
0
                    ssh_debug_printf("Activating new keys for SERVER => CLIENT\n");
1712
0
                    ssh_decryption_setup_cipher(&global_data->peer_data[SERVER_PEER_DATA], &global_data->new_keys[1], &global_data->new_keys[3]);
1713
0
                    ssh_decryption_setup_mac(&global_data->peer_data[SERVER_PEER_DATA], &global_data->new_keys[5]);
1714
0
                }
1715
0
            }
1716
0
            break;
1717
0
        }
1718
0
    }
1719
1720
0
    len = plen+4-padding_length-(offset-last_offset);
1721
0
    if (len > 0) {
1722
0
        proto_tree_add_item(key_ex_tree, hf_ssh_payload, tvb, offset, len, ENC_NA);
1723
0
    }
1724
0
    offset += len;
1725
1726
    /* padding */
1727
0
    proto_tree_add_item(tree, hf_ssh_padding_string, tvb, offset, padding_length, ENC_NA);
1728
0
    offset+= padding_length;
1729
0
    ti = proto_tree_add_uint(tree, hf_ssh_seq_num, tvb, offset, 0, message->sequence_number);
1730
0
    proto_item_set_generated(ti);
1731
1732
0
    return offset;
1733
0
}
1734
1735
static int ssh_dissect_kex_dh(uint8_t msg_code, tvbuff_t *tvb,
1736
        packet_info *pinfo, int offset, proto_tree *tree,
1737
        struct ssh_flow_data *global_data)
1738
0
{
1739
0
    proto_tree_add_item(tree, hf_ssh2_kex_dh_msg_code, tvb, offset, 1, ENC_BIG_ENDIAN);
1740
0
    offset += 1;
1741
1742
0
    col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
1743
0
        val_to_str(pinfo->pool, msg_code, ssh2_kex_dh_msg_vals, "Unknown (%u)"));
1744
1745
0
    switch (msg_code) {
1746
0
    case SSH_MSG_KEXDH_INIT:
1747
        // e (client ephemeral key public part)
1748
0
        if (!ssh_read_e(tvb, offset, global_data)) {
1749
0
            proto_tree_add_expert_format(tree, pinfo, &ei_ssh_invalid_keylen, tvb, offset, 2,
1750
0
                "Invalid key length: %u", tvb_get_ntohl(tvb, offset));
1751
0
        }
1752
1753
0
        offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_dh_e);
1754
0
        break;
1755
1756
0
    case SSH_MSG_KEXDH_REPLY:
1757
0
        offset += ssh_tree_add_hostkey(tvb, pinfo, offset, tree, "KEX host key",
1758
0
                ett_key_exchange_host_key, global_data);
1759
1760
        // f (server ephemeral key public part), K_S (host key)
1761
0
        if (!ssh_read_f(tvb, offset, global_data)) {
1762
0
            proto_tree_add_expert_format(tree, pinfo, &ei_ssh_invalid_keylen, tvb, offset, 2,
1763
0
                "Invalid key length: %u", tvb_get_ntohl(tvb, offset));
1764
0
        }
1765
0
        ssh_choose_enc_mac(global_data);
1766
0
        ssh_keylog_hash_write_secret(global_data, pinfo->pool);
1767
1768
0
        offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_dh_f);
1769
0
        offset += ssh_tree_add_hostsignature(tvb, pinfo, offset, tree, "KEX host signature",
1770
0
                ett_key_exchange_host_sig, global_data);
1771
0
        break;
1772
0
    }
1773
1774
0
    return offset;
1775
0
}
1776
1777
static int ssh_dissect_kex_dh_gex(uint8_t msg_code, tvbuff_t *tvb,
1778
        packet_info *pinfo, int offset, proto_tree *tree,
1779
        struct ssh_flow_data *global_data)
1780
0
{
1781
0
    proto_tree_add_item(tree, hf_ssh2_kex_dh_gex_msg_code, tvb, offset, 1, ENC_BIG_ENDIAN);
1782
0
    offset += 1;
1783
1784
0
    col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
1785
0
        val_to_str(pinfo->pool, msg_code, ssh2_kex_dh_gex_msg_vals, "Unknown (%u)"));
1786
1787
0
    switch (msg_code) {
1788
0
    case SSH_MSG_KEX_DH_GEX_REQUEST_OLD:
1789
0
        proto_tree_add_item(tree, hf_ssh_dh_gex_nbits, tvb, offset, 4, ENC_BIG_ENDIAN);
1790
0
        offset += 4;
1791
0
        break;
1792
1793
0
    case SSH_MSG_KEX_DH_GEX_GROUP:
1794
        // p (Group modulo)
1795
0
        global_data->kex_gex_p = ssh_read_mpint(tvb, offset);
1796
0
        offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_dh_gex_p);
1797
        // g (Group generator)
1798
0
        global_data->kex_gex_g = ssh_read_mpint(tvb, offset);
1799
0
        offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_dh_gex_g);
1800
0
        break;
1801
1802
0
    case SSH_MSG_KEX_DH_GEX_INIT:
1803
        // e (Client public key)
1804
0
        if (!ssh_read_e(tvb, offset, global_data)) {
1805
0
            proto_tree_add_expert_format(tree, pinfo, &ei_ssh_invalid_keylen, tvb, offset, 2,
1806
0
                "Invalid key length: %u", tvb_get_ntohl(tvb, offset));
1807
0
        }
1808
0
        offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_dh_e);
1809
0
        break;
1810
1811
0
    case SSH_MSG_KEX_DH_GEX_REPLY:
1812
0
        offset += ssh_tree_add_hostkey(tvb, pinfo, offset, tree, "KEX host key",
1813
0
                ett_key_exchange_host_key, global_data);
1814
0
        if (!PINFO_FD_VISITED(pinfo)) {
1815
0
            ssh_read_f(tvb, offset, global_data);
1816
            // f (server ephemeral key public part), K_S (host key)
1817
0
            ssh_choose_enc_mac(global_data);
1818
0
            ssh_keylog_hash_write_secret(global_data, pinfo->pool);
1819
0
        }
1820
0
        offset += ssh_tree_add_mpint(tvb, offset, tree, hf_ssh_dh_f);
1821
0
        offset += ssh_tree_add_hostsignature(tvb, pinfo, offset, tree, "KEX host signature",
1822
0
                ett_key_exchange_host_sig, global_data);
1823
0
        break;
1824
1825
0
    case SSH_MSG_KEX_DH_GEX_REQUEST:{
1826
1827
0
        if (!PINFO_FD_VISITED(pinfo)) {
1828
0
            ssh_hash_buffer_put_uint32(global_data->kex_gex_bits_min, tvb_get_ntohl(tvb, offset));
1829
0
        }
1830
0
        proto_tree_add_item(tree, hf_ssh_dh_gex_min, tvb, offset, 4, ENC_BIG_ENDIAN);
1831
0
        offset += 4;
1832
0
        if (!PINFO_FD_VISITED(pinfo)) {
1833
0
            ssh_hash_buffer_put_uint32(global_data->kex_gex_bits_req, tvb_get_ntohl(tvb, offset));
1834
0
        }
1835
0
        proto_tree_add_item(tree, hf_ssh_dh_gex_nbits, tvb, offset, 4, ENC_BIG_ENDIAN);
1836
0
        offset += 4;
1837
0
        if (!PINFO_FD_VISITED(pinfo)) {
1838
0
            ssh_hash_buffer_put_uint32(global_data->kex_gex_bits_max, tvb_get_ntohl(tvb, offset));
1839
0
        }
1840
0
        proto_tree_add_item(tree, hf_ssh_dh_gex_max, tvb, offset, 4, ENC_BIG_ENDIAN);
1841
0
        offset += 4;
1842
0
        break;
1843
0
        }
1844
0
    }
1845
1846
0
    return offset;
1847
0
}
1848
1849
static int
1850
ssh_dissect_kex_ecdh(uint8_t msg_code, tvbuff_t *tvb,
1851
        packet_info *pinfo, int offset, proto_tree *tree,
1852
        struct ssh_flow_data *global_data)
1853
0
{
1854
0
    proto_tree_add_item(tree, hf_ssh2_kex_ecdh_msg_code, tvb, offset, 1, ENC_BIG_ENDIAN);
1855
0
    offset += 1;
1856
1857
0
    col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
1858
0
        val_to_str(pinfo->pool, msg_code, ssh2_kex_ecdh_msg_vals, "Unknown (%u)"));
1859
1860
0
    switch (msg_code) {
1861
0
    case SSH_MSG_KEX_ECDH_INIT:
1862
0
        if (!ssh_read_e(tvb, offset, global_data)) {
1863
0
            proto_tree_add_expert_format(tree, pinfo, &ei_ssh_invalid_keylen, tvb, offset, 2,
1864
0
                "Invalid key length: %u", tvb_get_ntohl(tvb, offset));
1865
0
        }
1866
1867
0
        offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_ecdh_q_c, hf_ssh_ecdh_q_c_length);
1868
0
        break;
1869
1870
0
    case SSH_MSG_KEX_ECDH_REPLY:
1871
0
        offset += ssh_tree_add_hostkey(tvb, pinfo, offset, tree, "KEX host key",
1872
0
                ett_key_exchange_host_key, global_data);
1873
1874
0
        if (!ssh_read_f(tvb, offset, global_data)){
1875
0
            proto_tree_add_expert_format(tree, pinfo, &ei_ssh_invalid_keylen, tvb, offset, 2,
1876
0
                "Invalid key length: %u", tvb_get_ntohl(tvb, offset));
1877
0
        }
1878
1879
0
        ssh_choose_enc_mac(global_data);
1880
0
        ssh_keylog_hash_write_secret(global_data, pinfo->pool);
1881
1882
0
        offset += ssh_tree_add_string(tvb, offset, tree, hf_ssh_ecdh_q_s, hf_ssh_ecdh_q_s_length);
1883
0
        offset += ssh_tree_add_hostsignature(tvb, pinfo, offset, tree, "KEX host signature",
1884
0
                ett_key_exchange_host_sig, global_data);
1885
0
        break;
1886
0
    }
1887
1888
0
    return offset;
1889
0
}
1890
1891
    /*
1892
     * === Hybrid KEX Dissection Strategy for Post-Quantum algorithms ===
1893
     *
1894
     * This 3 functions:
1895
     *
1896
     *   - ssh_dissect_kex_pq_hybrid()
1897
     *   - ssh_read_e_pq()
1898
     *   - ssh_read_f_pq()
1899
     *
1900
     * handles the dissection of server key exchange payloads for the
1901
     * post-quantum hybrid key exchange method:
1902
     *   - sntrup761x25519-sha512
1903
     *   - mlkem768x25519-sha256
1904
     *   - mlkem768nistp256-sha256
1905
     *   - mlkem1024nistp384-sha384
1906
     *
1907
     * /!\ Rationale for implementation approach:
1908
     *
1909
     * SSH encodes the server's ephemeral key (`Q_S`) as a single SSH `string`
1910
     * which contains both the post-quantum KEM ciphertext (from sntrup761 / mlkem768
1911
     * / mlkem1024) and the traditional (Curve25519 / nistp256 / nistp384) public key.
1912
     * Therefore, we parse one string
1913
     *
1914
     *   sntrup761x25519:
1915
     *   - PQ client keyshare:   1158 bytes
1916
     *   - PQ server ciphertext: 1039 bytes
1917
     *   - Curve25519 pubkey:    32 bytes
1918
     *
1919
     *   mlkem768x25519:
1920
     *   - PQ client keyshare:   1184 bytes
1921
     *   - PQ server ciphertext: 1088 bytes
1922
     *   - Curve25519 pubkey:    32 bytes
1923
     *
1924
     *   mlkem768nistp256:
1925
     *   - PQ client keyshare:   1184 bytes
1926
     *   - PQ server ciphertext: 1088 bytes
1927
     *   - nistp256 pubkey:      65 bytes
1928
     *
1929
     *   mlkem1024nistp384:
1930
     *   - PQ client keyshare:   1568 bytes
1931
     *   - PQ server ciphertext: 1568 bytes
1932
     *   - nistp384 pubkey:      97 bytes
1933
     *
1934
     *
1935
     * This matches how OpenSSH serializes the hybrid key material, and allows Wireshark
1936
     * to compute the correct key exchange hash and derive session keys accurately.
1937
     *
1938
     * /!\ This design is necessary for live decryption support in Wireshark and TShark.
1939
     *
1940
     * References:
1941
     *   - RFC 4253: The SSH Transport Layer Protocol
1942
     *     - Section 6: string encoding format
1943
     *     - Section 7.2: Key derivation
1944
     *   - RFC 8731: Secure Shell (SSH) Key Exchange Method using Curve25519
1945
     *   - Internet-Draft on sntrup761x25519-sha512
1946
     *     - https://datatracker.ietf.org/doc/draft-ietf-sshm-ntruprime-ssh/
1947
     *   - Internet-Draft on mlkem768x25519-sha256
1948
     *     - https://datatracker.ietf.org/doc/draft-ietf-sshm-mlkem-hybrid-kex/
1949
     *   - OpenSSH Hybrid KEM Implementation (sntrup761x25519-sha512 / mlkem768x25519-sha256)
1950
     *     - https://github.com/openssh/openssh-portable/blob/master/kexc25519.c
1951
     *     - https://github.com/openssh/openssh-portable/blob/master/kexsntrup761x25519.c
1952
     *     - https://github.com/openssh/openssh-portable/blob/master/kexmlkem768x25519.c
1953
     *   - AsyncSSH Hybrid KEM Implementation (sntrup761x25519-sha512 / mlkem768x25519-sha256 / mlkem768nistp256-sha256 / mlkem1024nistp384-sha384)
1954
     *     - https://github.com/ronf/asyncssh/blob/develop/asyncssh/kex_dh.py
1955
     *
1956
     */
1957
1958
static int
1959
ssh_dissect_kex_pq_hybrid(uint8_t msg_code, tvbuff_t *tvb,
1960
        packet_info *pinfo, int offset, proto_tree *tree,
1961
        struct ssh_flow_data *global_data)
1962
0
{
1963
    //    SSH PACKET STRUCTURE RFC4253 (e.g. packet of 1228 bytes payload)
1964
    //    [00 00 04 cc]                       → ssh payload blob length field in tcp packet (e.g. 1228=0x04cc): 4 bytes
1965
    //    [1228 bytes of SSH PAYLOAD BLOB]    → ssh payload blob field: 1228 bytes
1966
1967
    // Add the message code byte (first field in packet) to the GUI tree.
1968
0
    proto_tree_add_item(tree, hf_ssh2_kex_hybrid_msg_code, tvb, offset, 1, ENC_BIG_ENDIAN);
1969
0
    offset += 1;  // Move offset past the msg_code byte.
1970
1971
    // Add a descriptive string to Wireshark's "Info" column.
1972
0
    col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
1973
0
        val_to_str(pinfo->pool, msg_code, ssh2_kex_hybrid_msg_vals, "Unknown (%u)"));
1974
1975
0
    const char *kex_name = global_data->kex;
1976
1977
0
    if (msg_code == SSH_MSG_KEX_HYBRID_INIT) {
1978
        // Print warning when PQ hybrid KEM is detected in KEX
1979
        // This implementation currently rely on SHARED_SECRET only and do not work with PRIVATE_KEY
1980
0
        if (!PINFO_FD_VISITED(pinfo)) {
1981
0
            ws_warning("POST-QUANTUM KEX_HYBRID detected: KEX = %s", kex_name);
1982
0
            ws_warning("SHARED_SECRET decryption is supported - PRIVATE_KEY decryption is not supported");
1983
0
        }
1984
        // Print noisy debug info
1985
0
        ws_noisy(">>> HYBRID KEM: msg_code = %u, offset = %d, kex = %s", msg_code, offset, kex_name);
1986
0
        }
1987
1988
0
    switch (msg_code) {
1989
1990
    // Client Key Exchange INIT
1991
0
    case SSH_MSG_KEX_HYBRID_INIT: {
1992
1993
        //    SNTRUP761X25519: RFC4253 SSH "string" (binary-encoded structure)
1994
        //    [00 00 04 a6]                       → length = 1190 (0x04a6)
1995
        //    [1158 bytes PQ blob]                → sntrup761 encapsulated client key
1996
        //    [32 bytes of X25519 pubkey]         → ephemeral X25519 public key
1997
1998
        //    MLKEM768X25519: RFC4253 SSH "string" (binary-encoded structure)
1999
        //    [00 00 04 c0]                       → length = 1216 (0x04c0)
2000
        //    [1184 bytes PQ blob]                → mlkem768 encapsulated client key
2001
        //    [32 bytes of X25519 pubkey]         → ephemeral X25519 public key
2002
2003
        //    MLKEM768NISTP256: RFC4253 SSH "string" (binary-encoded structure)
2004
        //    [00 00 04 e1]                       → length = 1249 (0x04e1)
2005
        //    [1184 bytes PQ blob]                → mlkem768 encapsulated client key
2006
        //    [65 bytes of nistp256 pubkey]       → ephemeral nistp256 public key
2007
2008
        //    MLKEM1024NISTP384: RFC4253 SSH "string" (binary-encoded structure)
2009
        //    [00 00 06 81]                       → length = 1665 (0x0681)
2010
        //    [1568 bytes PQ blob]                → mlkem1024 encapsulated client key
2011
        //    [97 bytes of nistp384 pubkey]       → ephemeral nistp384 public key
2012
2013
0
        ws_debug("CLIENT INIT follow offset pointer - absolute offset: %d", offset); // debug trace offset
2014
0
        int new_offset_client = ssh_read_e_pq(tvb, offset, global_data);
2015
0
        if (new_offset_client < 0) {
2016
0
            uint32_t bad_len = tvb_get_ntohl(tvb, offset);
2017
0
            proto_tree_add_expert_format(tree, pinfo, &ei_ssh_invalid_keylen, tvb, offset, 4,
2018
0
                "Invalid PQ client key length: %u", bad_len);
2019
0
            ws_debug("ExpertInfo: Invalid PQ client key length at offset %d: %u", offset, bad_len);
2020
2021
0
            return offset + 4;
2022
0
            ws_debug("CLIENT INIT validate PQ client key length - offset: %d", offset); // debug trace offset
2023
0
        }
2024
2025
        // PQ-hybrid KEMs cannot use ssh_add_tree_string => manual dissection
2026
        // Get PQ blob size
2027
0
        proto_tree *pq_tree = NULL;
2028
0
        uint32_t hybrid_len;
2029
2030
        // Add a subtree for dissecting PQ blob
2031
0
        proto_tree_add_item_ret_uint(tree, hf_ssh_hybrid_blob_client_len, tvb, offset, 4, ENC_BIG_ENDIAN, &hybrid_len); //  add blob length
2032
0
        ws_debug("CLIENT INIT PQ blob length - pq_len: %d", hybrid_len); // debug trace pq_len
2033
0
        offset += 4;  // shift length field
2034
0
        pq_tree = proto_tree_add_subtree(tree, tvb, offset, hybrid_len, ett_ssh_pqhybrid_client, NULL, "Hybrid Key Exchange Blob Client");
2035
0
        ws_debug("CLIENT INIT add PQ Hybrid subtree - offset: %d", offset); // debug trace offset
2036
2037
        // Make a new tvb for just the PQ hybrid blob string contents
2038
0
        tvbuff_t *string_tvb = tvb_new_subset_length(tvb, offset, hybrid_len);
2039
2040
0
        uint32_t pq_len;
2041
0
        uint32_t t_len;
2042
0
        if (strcmp(kex_name, "sntrup761x25519-sha512") == 0) {
2043
0
            pq_len = 1158;
2044
0
            t_len = 32;
2045
0
        } else if (strcmp(kex_name, "mlkem768x25519-sha256") == 0) {
2046
0
            pq_len = 1184;
2047
0
            t_len = 32;
2048
0
        } else if (strcmp(kex_name, "mlkem768nistp256-sha256") == 0) {
2049
0
            pq_len = 1184;
2050
0
            t_len = 65;
2051
0
        } else if (strcmp(kex_name, "mlkem1024nistp384-sha384") == 0) {
2052
0
            pq_len = 1568;
2053
0
            t_len = 97;
2054
0
        } else {
2055
0
            DISSECTOR_ASSERT_NOT_REACHED();
2056
0
            break;
2057
0
        }
2058
2059
0
        if (pq_len + t_len != hybrid_len) {
2060
0
            proto_tree_add_expert_format(tree, pinfo, &ei_ssh_invalid_keylen, tvb, offset, 4,
2061
0
                "Invalid PQ hybrid client key length for %s: %u does not match %u + %u",
2062
0
                kex_name, hybrid_len, pq_len, t_len);
2063
0
        } else {
2064
            // Now dissect string inside the blob and add PQ server response and ECDH Q_S to GUI subtree
2065
0
            proto_tree_add_item(pq_tree, hf_ssh_pq_kem_client, string_tvb, 0, pq_len, ENC_NA);
2066
0
            proto_tree_add_item(pq_tree, hf_ssh_ecdh_q_c, string_tvb, pq_len, t_len, ENC_NA);
2067
0
        }
2068
2069
        // retrieve offset from read_f_pq() to shift blob length and consume packet
2070
0
        offset = new_offset_client;
2071
0
        ws_debug("CLIENT INIT shift PQ blob - offset: %d", offset); // debug trace offset
2072
0
        break;
2073
0
        }
2074
2075
    // Server Reply Message
2076
0
    case SSH_MSG_KEX_HYBRID_REPLY: {
2077
2078
        //    SNTRUP761X25519: RFC4253 SSH "string" (binary-encoded structure)
2079
        //    [00 00 00 33]                       → host key structure length = 51
2080
        //    [00 00 00 0b]                       → host key alg length = 11
2081
        //    [73 73 68 2d 65 64 32 35 35 31 39]  → "ssh-ed25519"
2082
        //    [00 00 00 20]                       → host key length = 32
2083
        //    [32 bytes of public key]            → public key
2084
        //    [00 00 04 2f]                       → PQ blob length = 1071 (0x042f)
2085
        //    [1071 bytes PQ blob]                → PQ blob (1039 sntrup761 + 32 x25519)
2086
        //    [00 00 00 53]                       → signature structure length = 83
2087
        //    [00 00 00 0b]                       → signature alg length
2088
        //    [73 73 68 2d 65 64 32 35 35 31 39]  → "ssh-ed25519"
2089
        //    [00 00 00 40]                       → signature length
2090
        //    [40 bytes signature]                → server signature
2091
2092
        //    MLKEM768X25519: RFC4253 SSH "string" (binary-encoded structure)
2093
        //    [00 00 00 33]                       → host key structure length = 51
2094
        //    [00 00 00 0b]                       → host key alg length = 11
2095
        //    [73 73 68 2d 65 64 32 35 35 31 39]  → "ssh-ed25519"
2096
        //    [00 00 00 20]                       → host key length = 32
2097
        //    [32 bytes of public key]            → public key
2098
        //    [00 00 04 60]                       → PQ blob length = 1120 (0x0460)
2099
        //    [1120 bytes PQ blob]                → PQ blob (1088 mlkem768 + 32 x25519)
2100
        //    [00 00 00 53]                       → signature structure length = 83
2101
        //    [00 00 00 0b]                       → signature alg length
2102
        //    [73 73 68 2d 65 64 32 35 35 31 39]  → "ssh-ed25519"
2103
        //    [00 00 00 40]                       → signature length
2104
        //    [40 bytes signature]                → server signature
2105
2106
        //    MLKEM768NISTP256: RFC4253 SSH "string" (binary-encoded structure)
2107
        //    [00 00 00 33]                       → host key structure length = 51
2108
        //    [00 00 00 0b]                       → host key alg length = 11
2109
        //    [73 73 68 2d 65 64 32 35 35 31 39]  → "ssh-ed25519"
2110
        //    [00 00 00 20]                       → host key length = 32
2111
        //    [32 bytes of public key]            → public key
2112
        //    [00 00 04 81]                       → PQ blob length = 1153 (0x0481)
2113
        //    [1153 bytes PQ blob]                → PQ blob (1088 mlkem768 + 65 nistp256)
2114
        //    [00 00 00 53]                       → signature structure length = 83
2115
        //    [00 00 00 0b]                       → signature alg length
2116
        //    [73 73 68 2d 65 64 32 35 35 31 39]  → "ssh-ed25519"
2117
        //    [00 00 00 40]                       → signature length
2118
        //    [40 bytes signature]                → server signature
2119
2120
        //    MLKEM1024NISTP384: RFC4253 SSH "string" (binary-encoded structure)
2121
        //    [00 00 00 33]                       → host key structure length = 51
2122
        //    [00 00 00 0b]                       → host key alg length = 11
2123
        //    [73 73 68 2d 65 64 32 35 35 31 39]  → "ssh-ed25519"
2124
        //    [00 00 00 20]                       → host key length = 32
2125
        //    [32 bytes of public key]            → public key
2126
        //    [00 00 06 81]                       → PQ blob length = 1665 (0x0681)
2127
        //    [1665 bytes PQ blob]                → PQ blob (1568 mlkem1024 + 97 nistp384)
2128
        //    [00 00 00 53]                       → signature structure length = 83
2129
        //    [00 00 00 0b]                       → signature alg length
2130
        //    [73 73 68 2d 65 64 32 35 35 31 39]  → "ssh-ed25519"
2131
        //    [00 00 00 40]                       → signature length
2132
        //    [40 bytes signature]                → server signature
2133
2134
0
        ws_debug("SERVER REPLY follow offset pointer - absolute offset: %d", offset); // debug trace offset
2135
2136
        // Add the host key used to sign the key exchange to the GUI tree.
2137
0
        offset += ssh_tree_add_hostkey(tvb, pinfo, offset, tree, "KEX host key", ett_key_exchange_host_key, global_data);
2138
2139
0
        ws_debug("SERVER REPLY add hostkey tree - offset: %d", offset); // debug trace offset
2140
2141
0
        int new_offset_server = ssh_read_f_pq(tvb, offset, global_data);
2142
0
        if (new_offset_server < 0) {
2143
0
            uint32_t bad_len = tvb_get_ntohl(tvb, offset);
2144
0
            proto_tree_add_expert_format(tree, pinfo, &ei_ssh_invalid_keylen, tvb, offset, 4,
2145
0
                "Invalid PQ server key length: %u", bad_len);
2146
0
            ws_debug("ExpertInfo: Invalid PQ server key length at offset %d: %u", offset, bad_len);
2147
2148
0
            return offset + 4;
2149
0
            ws_debug("SERVER REPLY validate PQ server key length - offset: %d", offset); // debug trace offset
2150
0
        }
2151
2152
        // Select encryption and MAC based on negotiated algorithms.
2153
0
        ssh_choose_enc_mac(global_data);
2154
2155
        // Write session secrets to keylog file (if enabled).
2156
0
        ssh_keylog_hash_write_secret(global_data, pinfo->pool);
2157
2158
        // PQ-hybrid KEMs cannot use ssh_add_tree_string => manual dissection
2159
        // Get PQ blob size
2160
0
        proto_tree *pq_tree = NULL;
2161
0
        uint32_t hybrid_len = tvb_get_ntohl(tvb, offset);
2162
0
        ws_debug("SERVER REPLY PQ blob length - hybrid_len: %d", hybrid_len); // debug trace hybrid_len
2163
2164
        // Add a subtree for dissecting PQ blob
2165
0
        proto_tree_add_item(tree, hf_ssh_hybrid_blob_server_len, tvb, offset, 4, ENC_BIG_ENDIAN); //  add blob length
2166
0
        offset += 4;  // shift length field
2167
0
        pq_tree = proto_tree_add_subtree(tree, tvb, offset, hybrid_len, ett_ssh_pqhybrid_server, NULL, "Hybrid Key Exchange Blob Server");
2168
0
        ws_debug("SERVER REPLY add PQ Hybrid subtree - offset: %d", offset); // debug trace offset
2169
2170
        // Make a new tvb for just the PQ hybrid blob string contents
2171
0
        tvbuff_t *string_tvb = tvb_new_subset_length(tvb, offset, hybrid_len);
2172
2173
0
        uint32_t pq_len;
2174
0
        uint32_t t_len;
2175
0
        if (strcmp(kex_name, "sntrup761x25519-sha512") == 0) {
2176
0
            pq_len = 1039;
2177
0
            t_len = 32;
2178
0
        } else if (strcmp(kex_name, "mlkem768x25519-sha256") == 0) {
2179
0
            pq_len = 1088;
2180
0
            t_len = 32;
2181
0
        } else if (strcmp(kex_name, "mlkem768nistp256-sha256") == 0) {
2182
0
            pq_len = 1088;
2183
0
            t_len = 65;
2184
0
        } else if (strcmp(kex_name, "mlkem1024nistp384-sha384") == 0) {
2185
0
            pq_len = 1568;
2186
0
            t_len = 97;
2187
0
        } else {
2188
0
            DISSECTOR_ASSERT_NOT_REACHED();
2189
0
            break;
2190
0
        }
2191
2192
0
        if (pq_len + t_len != hybrid_len) {
2193
0
            proto_tree_add_expert_format(tree, pinfo, &ei_ssh_invalid_keylen, tvb, offset, 4,
2194
0
                "Invalid PQ hybrid server key length for %s: %u does not match %u + %u",
2195
0
                kex_name, hybrid_len, pq_len, t_len);
2196
0
        } else {
2197
            // Now dissect string inside the blob and add PQ server response and ECDH Q_S to GUI subtree
2198
0
            proto_tree_add_item(pq_tree, hf_ssh_pq_kem_server, string_tvb, 0, pq_len, ENC_NA);
2199
0
            proto_tree_add_item(pq_tree, hf_ssh_ecdh_q_s, string_tvb, pq_len, t_len, ENC_NA);
2200
0
        }
2201
2202
        // retrieve offset from read_f_pq() to shift blob length
2203
0
        offset = new_offset_server;
2204
0
        ws_debug("SERVER REPLY shift PQ blob - offset: %d", offset); // debug trace offset
2205
2206
        // Add the host's digital signature to the GUI tree
2207
0
        offset += ssh_tree_add_hostsignature(tvb, pinfo, offset, tree, "KEX host signature",
2208
0
                ett_key_exchange_host_sig, global_data);
2209
0
        ws_debug("SERVER REPLY add signature tree - offset: %d", offset); // debug trace offset
2210
0
        break;
2211
0
        }
2212
0
    }
2213
2214
0
    if (msg_code == SSH_MSG_KEX_HYBRID_INIT) {
2215
0
        ws_debug("OUT PQ HYBRID KEX - CLIENT INIT track offset: %d", offset); // debug trace offset
2216
0
    } else if (msg_code == SSH_MSG_KEX_HYBRID_REPLY) {
2217
0
        ws_debug("OUT PQ HYBRID KEX - SERVER REPLY track offset: %d", offset); // debug trace offset
2218
0
    } else {
2219
0
        ws_debug("OUT PQ HYBRID KEX - track offset: %d", offset); // debug trace offset
2220
0
    }
2221
2222
0
    return offset; // Final offset after packet is processed by ssh_dissect_kex_pq_hybrid()
2223
0
}
2224
2225
static ssh_message_info_t*
2226
ssh_get_message(packet_info *pinfo, int record_id)
2227
0
{
2228
0
    ssh_packet_info_t *packet = (ssh_packet_info_t *)p_get_proto_data(
2229
0
            wmem_file_scope(), pinfo, proto_ssh, 0);
2230
2231
0
    if (!packet) {
2232
0
        return NULL;
2233
0
    }
2234
2235
0
    ssh_message_info_t *message = NULL;
2236
0
    for (message = packet->messages; message; message = message->next) {
2237
0
        ws_noisy("%u:looking for message %d now %d", pinfo->num, record_id, message->id);
2238
0
        if (message->id == record_id) {
2239
0
            return message;
2240
0
        }
2241
0
    }
2242
2243
0
    return NULL;
2244
0
}
2245
2246
static int
2247
ssh_try_dissect_encrypted_packet(tvbuff_t *tvb, packet_info *pinfo,
2248
        struct ssh_peer_data *peer_data, int offset, proto_tree *tree)
2249
22
{
2250
22
    bool can_decrypt = peer_data->cipher != NULL || peer_data->cipher_id == CIPHER_NULL;
2251
22
    ssh_message_info_t *message = NULL;
2252
2253
22
    if (can_decrypt) {
2254
0
        if (!PINFO_FD_VISITED(pinfo)) {
2255
0
            ssh_decrypt_packet(tvb, pinfo, peer_data, offset);
2256
0
            if (pinfo->desegment_len) {
2257
0
                return offset;
2258
0
            }
2259
0
        }
2260
2261
0
        int record_id = tvb_raw_offset(tvb) + offset;
2262
0
        message = ssh_get_message(pinfo, record_id);
2263
2264
0
        if (message) {
2265
0
            offset += ssh_dissect_decrypted_packet(tvb_new_subset_remaining(tvb, offset), pinfo, peer_data, tree, message);
2266
0
            return offset;
2267
0
        }
2268
0
    }
2269
2270
22
    return ssh_dissect_encrypted_packet(tvb, pinfo, peer_data, offset, tree);
2271
22
}
2272
2273
static int
2274
ssh_dissect_encrypted_packet(tvbuff_t *tvb, packet_info *pinfo,
2275
        struct ssh_peer_data *peer_data,
2276
        int offset, proto_tree *tree)
2277
22
{
2278
22
    int len;
2279
22
    unsigned plen;
2280
2281
22
    len = tvb_reported_length_remaining(tvb, offset);
2282
22
    col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Encrypted packet (len=%d)", len);
2283
2284
22
    if (tree) {
2285
22
        int encrypted_len = len;
2286
2287
22
        if (len > 4 && peer_data->length_is_plaintext) {
2288
0
            plen = tvb_get_ntohl(tvb, offset) ;
2289
0
            proto_tree_add_uint(tree, hf_ssh_packet_length, tvb, offset, 4, plen);
2290
0
            encrypted_len -= 4;
2291
0
        }
2292
22
        else if (len > 4) {
2293
19
            proto_tree_add_item(tree, hf_ssh_packet_length_encrypted, tvb, offset, 4, ENC_NA);
2294
19
            encrypted_len -= 4;
2295
19
        }
2296
2297
22
        if (peer_data->mac_length>0)
2298
0
            encrypted_len -= peer_data->mac_length;
2299
2300
22
        proto_tree_add_item(tree, hf_ssh_encrypted_packet,
2301
22
                    tvb, offset+4, encrypted_len, ENC_NA);
2302
2303
22
        if (peer_data->mac_length>0)
2304
0
            proto_tree_add_item(tree, hf_ssh_mac_string,
2305
0
                tvb, offset+4+encrypted_len,
2306
0
                peer_data->mac_length, ENC_NA);
2307
22
    }
2308
22
    offset += len;
2309
22
    return offset;
2310
22
}
2311
2312
static int
2313
ssh_dissect_protocol(tvbuff_t *tvb, packet_info *pinfo,
2314
        struct ssh_flow_data *global_data,
2315
        unsigned offset, proto_tree *tree, int is_response, unsigned * version,
2316
        bool *need_desegmentation)
2317
15
{
2318
15
    unsigned   protolen, next_offset;
2319
2320
    /*
2321
     *  If the first packet do not contain the banner,
2322
     *  it is dump in the middle of a flow or not a ssh at all
2323
     */
2324
15
    if (tvb_strncaseeql(tvb, offset, "SSH-", 4) != 0) {
2325
0
        offset = ssh_dissect_encrypted_packet(tvb, pinfo,
2326
0
            &global_data->peer_data[is_response], offset, tree);
2327
0
        return offset;
2328
0
    }
2329
2330
15
    if (!is_response) {
2331
15
        if (tvb_strncaseeql(tvb, offset, "SSH-2.", 6) == 0) {
2332
0
            *(version) = SSH_VERSION_2;
2333
15
        } else if (tvb_strncaseeql(tvb, offset, "SSH-1.99-", 9) == 0) {
2334
0
            *(version) = SSH_VERSION_2;
2335
15
        } else if (tvb_strncaseeql(tvb, offset, "SSH-1.", 6) == 0) {
2336
0
            *(version) = SSH_VERSION_1;
2337
0
        }
2338
15
    }
2339
2340
15
    if (!tvb_find_line_end_remaining(tvb, offset, &protolen, &next_offset)) {
2341
7
        if (ssh_desegment && pinfo->can_desegment) {
2342
0
            pinfo->desegment_offset = offset;
2343
0
            pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
2344
0
            *need_desegmentation = true;
2345
0
            return offset;
2346
0
        }
2347
7
    }
2348
    /* Either we found it, or we're not reassembling and take everything. */
2349
2350
15
    col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Protocol (%s)",
2351
15
            tvb_format_text(pinfo->pool, tvb, offset, protolen));
2352
2353
    // V_C / V_S (client and server identification strings) RFC4253 4.2
2354
    // format: SSH-protoversion-softwareversion SP comments [CR LF not incl.]
2355
15
    if (!PINFO_FD_VISITED(pinfo)) {
2356
15
        uint8_t *data = (uint8_t *)tvb_memdup(pinfo->pool, tvb, offset, protolen);
2357
15
        if(!is_response){
2358
15
            ssh_hash_buffer_put_string(global_data->kex_client_version, data, protolen);
2359
15
        }else{
2360
0
            ssh_hash_buffer_put_string(global_data->kex_server_version, data, protolen);
2361
0
        }
2362
15
    }
2363
2364
15
    proto_tree_add_item(tree, hf_ssh_protocol,
2365
15
                    tvb, offset, protolen, ENC_ASCII);
2366
15
    offset += next_offset;
2367
15
    return offset;
2368
15
}
2369
2370
static void
2371
ssh_set_mac_length(struct ssh_peer_data *peer_data)
2372
0
{
2373
0
    char *size_str;
2374
0
    uint32_t size = 0;
2375
0
    char *mac_name = peer_data->mac;
2376
0
    char *strip;
2377
2378
0
    if (!mac_name)
2379
0
        return;
2380
2381
    /* wmem_strdup() never returns NULL */
2382
0
    mac_name = wmem_strdup(NULL, (const char *)mac_name);
2383
2384
    /* strip trailing "-etm@openssh.com" or "@openssh.com" */
2385
0
    strip = strstr(mac_name, "-etm@openssh.com");
2386
0
    if (strip) {
2387
0
        peer_data->length_is_plaintext = 1;
2388
0
        *strip = '\0';
2389
0
    }
2390
0
    else {
2391
0
        strip = strstr(mac_name, "@openssh.com");
2392
0
        if (strip) *strip = '\0';
2393
0
    }
2394
2395
0
    size_str = g_strrstr(mac_name, "-");
2396
0
    if (size_str && ws_strtou32(size_str + 1, NULL, &size) && size > 0 && size % 8 == 0) {
2397
0
        peer_data->mac_length = size / 8;
2398
0
    }
2399
0
    else if (strcmp(mac_name, "hmac-sha1") == 0) {
2400
0
        peer_data->mac_length = 20;
2401
0
    }
2402
0
    else if (strcmp(mac_name, "hmac-md5") == 0) {
2403
0
        peer_data->mac_length = 16;
2404
0
    }
2405
0
    else if (strcmp(mac_name, "hmac-ripemd160") == 0) {
2406
0
        peer_data->mac_length = 20;
2407
0
    }
2408
0
    else if (strcmp(mac_name, "none") == 0) {
2409
0
        peer_data->mac_length = 0;
2410
0
    }
2411
2412
0
    wmem_free(NULL, mac_name);
2413
0
}
2414
2415
static void ssh_set_kex_specific_dissector(struct ssh_flow_data *global_data)
2416
0
{
2417
0
    const char *kex_name = global_data->kex;
2418
2419
0
    if (!kex_name) return;
2420
2421
0
    if (strcmp(kex_name, "diffie-hellman-group-exchange-sha1") == 0 ||
2422
0
        strcmp(kex_name, "diffie-hellman-group-exchange-sha256") == 0)
2423
0
    {
2424
0
        global_data->kex_specific_dissector = ssh_dissect_kex_dh_gex;
2425
0
    }
2426
0
    else if (g_str_has_prefix(kex_name, "ecdh-sha2-") ||
2427
0
        strcmp(kex_name, "curve25519-sha256@libssh.org") == 0 ||
2428
0
        strcmp(kex_name, "curve25519-sha256") == 0 ||
2429
0
        strcmp(kex_name, "curve448-sha512") == 0)
2430
0
    {
2431
0
        global_data->kex_specific_dissector = ssh_dissect_kex_ecdh;
2432
0
    }
2433
0
    else if (strcmp(kex_name, "diffie-hellman-group14-sha256") == 0 ||
2434
0
        strcmp(kex_name, "diffie-hellman-group16-sha512") == 0 ||
2435
0
        strcmp(kex_name, "diffie-hellman-group18-sha512") == 0 ||
2436
0
        strcmp(kex_name, "diffie-hellman-group1-sha1") == 0 ||
2437
0
        strcmp(kex_name, "diffie-hellman-group14-sha1") == 0)
2438
0
    {
2439
0
        global_data->kex_specific_dissector = ssh_dissect_kex_dh;
2440
0
    }
2441
0
    else if (strcmp(kex_name, "sntrup761x25519-sha512") == 0 ||
2442
0
        strcmp(kex_name, "mlkem768x25519-sha256") == 0 ||
2443
0
        strcmp(kex_name, "mlkem768nistp256-sha256") == 0 ||
2444
0
        strcmp(kex_name, "mlkem1024nistp384-sha384") == 0)
2445
0
    {
2446
0
        global_data->kex_specific_dissector = ssh_dissect_kex_pq_hybrid;
2447
0
    }
2448
0
    else
2449
0
    {
2450
0
        ws_warning("NOT SUPPORTED OR UNKNOWN KEX DETECTED: ALGORITHM = %s", kex_name);
2451
0
    }
2452
0
}
2453
2454
static int
2455
ssh_gslist_compare_strings(const void *a, const void *b)
2456
0
{
2457
0
    if (a == NULL && b == NULL)
2458
0
        return 0;
2459
0
    if (a == NULL)
2460
0
        return -1;
2461
0
    if (b == NULL)
2462
0
        return 1;
2463
0
    return strcmp((const char*)a, (const char*)b);
2464
0
}
2465
2466
/* expects that *result is NULL */
2467
static bool
2468
ssh_choose_algo(char *client, char *server, char **result)
2469
0
{
2470
0
    char **server_strings = NULL;
2471
0
    char **client_strings = NULL;
2472
0
    char **step;
2473
0
    GSList *server_list = NULL;
2474
2475
0
    static const char* client_strict = "kex-strict-c-v00@openssh.com";
2476
0
    static const char* server_strict = "kex-strict-s-v00@openssh.com";
2477
0
    bool kex_strict = false;
2478
2479
0
    if (!client || !server || !result || *result)
2480
0
        return false;
2481
2482
0
    server_strings = g_strsplit(server, ",", 0);
2483
0
    for (step = server_strings; *step; step++) {
2484
0
        server_list = g_slist_append(server_list, *step);
2485
0
    }
2486
2487
0
    client_strings = g_strsplit(client, ",", 0);
2488
0
    for (step = client_strings; *step; step++) {
2489
0
        GSList *agreed;
2490
0
        if ((agreed = g_slist_find_custom(server_list, *step, ssh_gslist_compare_strings))) {
2491
0
            *result = wmem_strdup(wmem_file_scope(), (const char *)agreed->data);
2492
0
            break;
2493
0
        }
2494
0
    }
2495
2496
    /* Check for the OpenSSH strict key exchange extension designed to
2497
     * mitigate the Terrapin attack by resetting the packet sequence
2498
     * number to zero after a SSH2_MSG_NEWKEYS message.
2499
     * https://www.openssh.com/txt/release-9.6
2500
     * Also see PROTOCOL in the OpenSSH source distribution.
2501
     *
2502
     * OpenSSH says this is activated "when an endpoint that supports this
2503
     * extension observes this algorithm name in a peer's KEXINIT packet".
2504
     * We'll have to assume that any endpoint that supports this also
2505
     * indicates support for it in its own first SSH2_MSG_KEXINIT.
2506
     */
2507
0
    if (g_strv_contains((const char* const*)client_strings, client_strict) &&
2508
0
        g_strv_contains((const char* const*)server_strings, server_strict)) {
2509
2510
0
        kex_strict = true;
2511
0
    }
2512
2513
0
    g_strfreev(client_strings);
2514
0
    g_slist_free(server_list);
2515
0
    g_strfreev(server_strings);
2516
2517
0
    return kex_strict;
2518
0
}
2519
2520
static int
2521
ssh_dissect_key_init(tvbuff_t *tvb, packet_info *pinfo, int offset,
2522
        proto_tree *tree, int is_response, struct ssh_flow_data *global_data)
2523
0
{
2524
0
    int start_offset = offset;
2525
0
    int payload_length;
2526
0
    wmem_strbuf_t *hassh_algo;
2527
0
    char   *hassh;
2528
2529
0
    proto_item *tf, *ti;
2530
0
    proto_tree *key_init_tree;
2531
2532
0
    struct ssh_peer_data *peer_data = &global_data->peer_data[is_response];
2533
2534
0
    key_init_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_key_init, &tf, "Algorithms");
2535
0
    if (!PINFO_FD_VISITED(pinfo)) {
2536
0
        peer_data->bn_cookie = ssh_kex_make_bignum(tvb_get_ptr(tvb, offset, 16), 16);
2537
0
    }
2538
0
    proto_tree_add_item(key_init_tree, hf_ssh_cookie,
2539
0
                    tvb, offset, 16, ENC_NA);
2540
0
    offset += 16;
2541
2542
0
    offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
2543
0
        hf_ssh_kex_algorithms_length, hf_ssh_kex_algorithms,
2544
0
        &peer_data->kex_proposal);
2545
0
    offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
2546
0
        hf_ssh_server_host_key_algorithms_length,
2547
0
        hf_ssh_server_host_key_algorithms, NULL);
2548
0
    offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
2549
0
        hf_ssh_encryption_algorithms_client_to_server_length,
2550
0
        hf_ssh_encryption_algorithms_client_to_server,
2551
0
        &peer_data->enc_proposals[CLIENT_TO_SERVER_PROPOSAL]);
2552
0
    offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
2553
0
        hf_ssh_encryption_algorithms_server_to_client_length,
2554
0
        hf_ssh_encryption_algorithms_server_to_client,
2555
0
        &peer_data->enc_proposals[SERVER_TO_CLIENT_PROPOSAL]);
2556
0
    offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
2557
0
        hf_ssh_mac_algorithms_client_to_server_length,
2558
0
        hf_ssh_mac_algorithms_client_to_server,
2559
0
        &peer_data->mac_proposals[CLIENT_TO_SERVER_PROPOSAL]);
2560
0
    offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
2561
0
        hf_ssh_mac_algorithms_server_to_client_length,
2562
0
        hf_ssh_mac_algorithms_server_to_client,
2563
0
        &peer_data->mac_proposals[SERVER_TO_CLIENT_PROPOSAL]);
2564
0
    offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
2565
0
        hf_ssh_compression_algorithms_client_to_server_length,
2566
0
        hf_ssh_compression_algorithms_client_to_server,
2567
0
        &peer_data->comp_proposals[CLIENT_TO_SERVER_PROPOSAL]);
2568
0
    offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
2569
0
        hf_ssh_compression_algorithms_server_to_client_length,
2570
0
        hf_ssh_compression_algorithms_server_to_client,
2571
0
        &peer_data->comp_proposals[SERVER_TO_CLIENT_PROPOSAL]);
2572
0
    offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
2573
0
        hf_ssh_languages_client_to_server_length,
2574
0
        hf_ssh_languages_client_to_server, NULL);
2575
0
    offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
2576
0
        hf_ssh_languages_server_to_client_length,
2577
0
        hf_ssh_languages_server_to_client, NULL);
2578
2579
0
    proto_tree_add_item(key_init_tree, hf_ssh_first_kex_packet_follows,
2580
0
        tvb, offset, 1, ENC_BIG_ENDIAN);
2581
0
    offset+=1;
2582
2583
0
    proto_tree_add_item(key_init_tree, hf_ssh_kex_reserved,
2584
0
        tvb, offset, 4, ENC_NA);
2585
0
    offset+=4;
2586
2587
0
    hassh_algo = wmem_strbuf_new(pinfo->pool, "");
2588
0
    if(!is_response) {
2589
0
        wmem_strbuf_append_printf(hassh_algo, "%s;%s;%s;%s", peer_data->kex_proposal, peer_data->enc_proposals[CLIENT_TO_SERVER_PROPOSAL],
2590
0
                peer_data->mac_proposals[CLIENT_TO_SERVER_PROPOSAL], peer_data->comp_proposals[CLIENT_TO_SERVER_PROPOSAL]);
2591
0
        hassh = g_compute_checksum_for_string(G_CHECKSUM_MD5, wmem_strbuf_get_str(hassh_algo), wmem_strbuf_get_len(hassh_algo));
2592
0
        ti = proto_tree_add_string(key_init_tree, hf_ssh_kex_hassh_algo, tvb, offset, 0, wmem_strbuf_get_str(hassh_algo));
2593
0
        proto_item_set_generated(ti);
2594
0
        ti = proto_tree_add_string(key_init_tree, hf_ssh_kex_hassh, tvb, offset, 0, hassh);
2595
0
        proto_item_set_generated(ti);
2596
0
        g_free(hassh);
2597
0
    } else {
2598
0
        wmem_strbuf_append_printf(hassh_algo, "%s;%s;%s;%s", peer_data->kex_proposal, peer_data->enc_proposals[SERVER_TO_CLIENT_PROPOSAL],
2599
0
                peer_data->mac_proposals[SERVER_TO_CLIENT_PROPOSAL], peer_data->comp_proposals[SERVER_TO_CLIENT_PROPOSAL]);
2600
0
        hassh = g_compute_checksum_for_string(G_CHECKSUM_MD5, wmem_strbuf_get_str(hassh_algo), wmem_strbuf_get_len(hassh_algo));
2601
0
        ti = proto_tree_add_string(key_init_tree, hf_ssh_kex_hasshserver_algo, tvb, offset, 0, wmem_strbuf_get_str(hassh_algo));
2602
0
        proto_item_set_generated(ti);
2603
0
        ti = proto_tree_add_string(key_init_tree, hf_ssh_kex_hasshserver, tvb, offset, 0, hassh);
2604
0
        proto_item_set_generated(ti);
2605
0
        g_free(hassh);
2606
0
    }
2607
2608
0
    if (global_data->peer_data[CLIENT_PEER_DATA].kex_proposal &&
2609
0
        global_data->peer_data[SERVER_PEER_DATA].kex_proposal &&
2610
0
        !global_data->kex)
2611
0
    {
2612
        /* Note: we're ignoring first_kex_packet_follows. */
2613
0
        global_data->ext_kex_strict = ssh_choose_algo(
2614
0
            global_data->peer_data[CLIENT_PEER_DATA].kex_proposal,
2615
0
            global_data->peer_data[SERVER_PEER_DATA].kex_proposal,
2616
0
            &global_data->kex);
2617
0
        ssh_set_kex_specific_dissector(global_data);
2618
0
    }
2619
2620
0
    payload_length = offset - start_offset;
2621
2622
0
    if (tf != NULL) {
2623
0
        proto_item_set_len(tf, payload_length);
2624
0
    }
2625
2626
    // I_C / I_S (client and server SSH_MSG_KEXINIT payload) RFC4253 4.2
2627
0
    if (!PINFO_FD_VISITED(pinfo)) {
2628
0
        uint8_t *data = (uint8_t *)wmem_alloc(pinfo->pool, payload_length + 1);
2629
0
        tvb_memcpy(tvb, data + 1, start_offset, payload_length);
2630
0
        data[0] = SSH_MSG_KEXINIT;
2631
0
        if(is_response){
2632
0
            ssh_hash_buffer_put_string(global_data->kex_server_key_exchange_init, data, payload_length + 1);
2633
0
        }else{
2634
            // Reset array while REKEY: sanitize client key
2635
0
            global_data->kex_client_key_exchange_init = wmem_array_new(wmem_file_scope(), 1);
2636
0
            ssh_hash_buffer_put_string(global_data->kex_client_key_exchange_init, data, payload_length + 1);
2637
0
        }
2638
0
    }
2639
2640
0
    return offset;
2641
0
}
2642
2643
static int
2644
ssh_dissect_proposal(tvbuff_t *tvb, int offset, proto_tree *tree,
2645
             int hf_index_length, int hf_index_value, char **store)
2646
0
{
2647
0
    uint32_t len = tvb_get_ntohl(tvb, offset);
2648
0
    proto_tree_add_uint(tree, hf_index_length, tvb, offset, 4, len);
2649
0
    offset += 4;
2650
2651
0
    proto_tree_add_item(tree, hf_index_value, tvb, offset, len,
2652
0
                ENC_ASCII);
2653
0
    if (store)
2654
0
        *store = (char *) tvb_get_string_enc(wmem_file_scope(), tvb, offset, len, ENC_ASCII);
2655
0
    offset += len;
2656
2657
0
    return offset;
2658
0
}
2659
2660
static void
2661
ssh_keylog_read_file(void)
2662
0
{
2663
0
    if (!pref_keylog_file || !*pref_keylog_file) {
2664
0
        ws_debug("no keylog file preference set");
2665
0
        return;
2666
0
    }
2667
2668
0
    if (ssh_keylog_file && file_needs_reopen(ws_fileno(ssh_keylog_file),
2669
0
                pref_keylog_file)) {
2670
0
        ssh_keylog_reset();
2671
0
        g_hash_table_remove_all(ssh_master_key_map);
2672
0
    }
2673
2674
0
    if (!ssh_keylog_file) {
2675
0
        ssh_keylog_file = ws_fopen(pref_keylog_file, "r");
2676
0
        if (!ssh_keylog_file) {
2677
0
            ws_debug("ssh: failed to open key log file %s: %s",
2678
0
                    pref_keylog_file, g_strerror(errno));
2679
0
            return;
2680
0
        }
2681
0
    }
2682
2683
    /* File format: each line follows the format "<cookie> <type> <key>".
2684
     * <cookie> is the hex-encoded (client or server) 16 bytes cookie
2685
     * (32 characters) found in the SSH_MSG_KEXINIT of the endpoint whose
2686
     * private random is disclosed.
2687
     * <type> is either SHARED_SECRET or PRIVATE_KEY depending on the
2688
     * type of key provided. PRIVAT_KEY is only supported for DH,
2689
     * DH group exchange, and ECDH (including Curve25519) key exchanges.
2690
     * <key> is the private random number that is used to generate the DH
2691
     * negotiation (length depends on algorithm). In RFC4253 it is called
2692
     * x for the client and y for the server.
2693
     * For openssh and DH group exchange, it can be retrieved using
2694
     * DH_get0_key(kex->dh, NULL, &server_random)
2695
     * for groupN in file kexdh.c function kex_dh_compute_key
2696
     * for custom group in file kexgexs.c function input_kex_dh_gex_init
2697
     * For openssh and curve25519, it can be found in function kex_c25519_enc
2698
     * in variable server_key. One may also provide the shared secret
2699
     * directly if <type> is set to SHARED_SECRET.
2700
     *
2701
     * Example:
2702
     *  90d886612f9c35903db5bb30d11f23c2 PRIVATE_KEY DEF830C22F6C927E31972FFB20B46C96D0A5F2D5E7BE5A3A8804D6BFC431619ED10AF589EEDFF4750DEA00EFD7AFDB814B6F3528729692B1F2482041521AE9DC
2703
     */
2704
0
    for (;;) {
2705
        // XXX - What is a reasonable max line length here? Note at a certain
2706
        // point we have to increase the maximum ssh_kex_make_bignum supports (not needed for post quantum material (pure binary)).
2707
0
        char buf[4096];// 4096 is needed for mlkem1024 private_key binary meterial: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.203.pdf
2708
0
        buf[0] = 0;
2709
2710
0
        if (!fgets(buf, sizeof(buf), ssh_keylog_file)) {
2711
0
            rewind(ssh_keylog_file); // Resets to start of file (to handle parallel multi sessions decryption)
2712
0
            if (ferror(ssh_keylog_file)) {
2713
0
                ws_debug("Error while reading %s, closing it.", pref_keylog_file);
2714
0
                ssh_keylog_reset();
2715
0
                g_hash_table_remove_all(ssh_master_key_map);
2716
0
            }
2717
0
            break;
2718
0
        }
2719
2720
0
        size_t len = strlen(buf);
2721
0
        while(len>0 && (buf[len-1]=='\r' || buf[len-1]=='\n')){len-=1;buf[len]=0;}
2722
0
        ws_noisy("ssh: raw keylog line read: %s", buf);
2723
2724
0
        ssh_keylog_process_line(buf);
2725
0
    }
2726
0
}
2727
2728
static void
2729
ssh_keylog_process_lines(const uint8_t *data, unsigned datalen)
2730
0
{
2731
0
    const char *next_line = (const char *)data;
2732
0
    const char *line_end = next_line + datalen;
2733
0
    while (next_line && next_line < line_end) {
2734
0
        const char *line = next_line;
2735
0
        next_line = (const char *)memchr(line, '\n', line_end - line);
2736
0
        ssize_t linelen;
2737
2738
0
        if (next_line) {
2739
0
            linelen = next_line - line;
2740
0
            next_line++;    /* drop LF */
2741
0
        } else {
2742
0
            linelen = (ssize_t)(line_end - line);
2743
0
        }
2744
0
        if (linelen > 0 && line[linelen - 1] == '\r') {
2745
0
            linelen--;      /* drop CR */
2746
0
        }
2747
2748
0
        ssh_debug_printf("  checking keylog line: %.*s\n", (int)linelen, line);
2749
0
        ws_noisy("ssh: about to process line: %.*s", (int)linelen, line);
2750
2751
0
        char * strippedline = g_strndup(line, linelen);
2752
0
        ssh_keylog_process_line(strippedline);
2753
0
        g_free(strippedline);
2754
0
    }
2755
0
}
2756
2757
static void
2758
ssh_keylog_process_line(const char *line)
2759
0
{
2760
0
    ws_noisy("ssh: process line: %s", line);
2761
2762
0
    char **split = g_strsplit(line, " ", 3);
2763
0
    char *cookie, *type, *key;
2764
0
    size_t cookie_len, key_len;
2765
2766
0
    if (g_strv_length(split) == 3) {
2767
        // New format: [hex-encoded cookie] [key type] [hex-encoded key material]
2768
0
        cookie = split[0];
2769
0
        type = split[1];
2770
0
        key = split[2];
2771
0
    } else if (g_strv_length(split) == 2) {
2772
        // Old format: [hex-encoded cookie] [hex-encoded private key]
2773
0
        ws_debug("ssh keylog: detected old keylog format without explicit key type");
2774
0
        type = "PRIVATE_KEY";
2775
0
        cookie = split[0];
2776
0
        key = split[1];
2777
0
    } else {
2778
0
        ws_debug("ssh keylog: invalid format");
2779
0
        g_strfreev(split);
2780
0
        return;
2781
0
    }
2782
2783
0
    key_len = strlen(key);
2784
0
    cookie_len = strlen(cookie);
2785
0
    if(key_len & 1){
2786
0
        ws_debug("ssh keylog: invalid format (key should at least be even!)");
2787
0
        g_strfreev(split);
2788
0
        return;
2789
0
    }
2790
0
    if(cookie_len & 1){
2791
0
        ws_debug("ssh keylog: invalid format (cookie should at least be even!)");
2792
0
        g_strfreev(split);
2793
0
        return;
2794
0
    }
2795
0
    ssh_bignum * bn_cookie = ssh_kex_make_bignum(NULL, (unsigned)(cookie_len/2));
2796
0
    ssh_bignum * bn_priv   = ssh_kex_make_bignum(NULL, (unsigned)(key_len/2));
2797
0
    uint8_t c;
2798
0
    for (size_t i = 0; i < key_len/2; i ++) {
2799
0
        char v0 = key[i * 2];
2800
0
        int8_t h0 = ws_xton(v0);
2801
0
        char v1 = key[i * 2 + 1];
2802
0
        int8_t h1 = ws_xton(v1);
2803
2804
0
        if (h0==-1 || h1==-1) {
2805
0
            ws_debug("ssh: can't process key, invalid hex number: %c%c", v0, v1);
2806
0
            g_strfreev(split);
2807
0
            return;
2808
0
        }
2809
2810
0
        c = (h0 << 4) | h1;
2811
2812
0
        bn_priv->data[i] = c;
2813
0
    }
2814
0
    for (size_t i = 0; i < cookie_len/2; i ++) {
2815
0
        char v0 = cookie[i * 2];
2816
0
        int8_t h0 = ws_xton(v0);
2817
0
        char v1 = cookie[i * 2 + 1];
2818
0
        int8_t h1 = ws_xton(v1);
2819
2820
0
        if (h0==-1 || h1==-1) {
2821
0
            ws_debug("ssh: can't process cookie, invalid hex number: %c%c", v0, v1);
2822
0
            g_strfreev(split);
2823
0
            return;
2824
0
        }
2825
2826
0
        c = (h0 << 4) | h1;
2827
2828
0
        bn_cookie->data[i] = c;
2829
0
    }
2830
0
    ssh_bignum * bn_priv_ht = g_new(ssh_bignum, 1);
2831
0
    bn_priv_ht->length = bn_priv->length;
2832
0
    bn_priv_ht->data = (uint8_t *) g_memdup2(bn_priv->data, bn_priv->length);
2833
0
    ssh_bignum * bn_cookie_ht = g_new(ssh_bignum, 1);
2834
0
    bn_cookie_ht->length = bn_cookie->length;
2835
0
    bn_cookie_ht->data = (uint8_t *) g_memdup2(bn_cookie->data, bn_cookie->length);
2836
2837
0
    char * type_ht = (char *) g_memdup2(type, strlen(type) + 1);
2838
0
    ssh_key_map_entry_t * entry_ht = g_new(ssh_key_map_entry_t, 1);
2839
0
    entry_ht->type = type_ht;
2840
0
    entry_ht->key_material = bn_priv_ht;
2841
0
    g_hash_table_insert(ssh_master_key_map, bn_cookie_ht, entry_ht);
2842
0
    g_strfreev(split);
2843
0
}
2844
2845
static void
2846
ssh_keylog_reset(void)
2847
0
{
2848
0
    if (ssh_keylog_file) {
2849
0
        fclose(ssh_keylog_file);
2850
0
        ssh_keylog_file = NULL;
2851
0
    }
2852
0
}
2853
2854
static unsigned
2855
ssh_kex_type(char *type)
2856
0
{
2857
0
    if (type) {
2858
0
        if (g_str_has_prefix(type, "curve25519")) {
2859
0
            return SSH_KEX_CURVE25519;
2860
0
        }else if (g_str_has_prefix(type, "sntrup761x25519")) {
2861
0
            return SSH_KEX_SNTRUP761X25519;
2862
0
        }else if (g_str_has_prefix(type, "mlkem768x25519")) {
2863
0
            return SSH_KEX_MLKEM768X25519;
2864
0
        }else if (g_str_has_prefix(type, "diffie-hellman-group-exchange")) {
2865
0
            return SSH_KEX_DH_GEX;
2866
0
        }else if (g_str_has_prefix(type, "diffie-hellman-group14")) {
2867
0
            return SSH_KEX_DH_GROUP14;
2868
0
        }else if (g_str_has_prefix(type, "diffie-hellman-group16")) {
2869
0
            return SSH_KEX_DH_GROUP16;
2870
0
        }else if (g_str_has_prefix(type, "diffie-hellman-group18")) {
2871
0
            return SSH_KEX_DH_GROUP18;
2872
0
        }else if (g_str_has_prefix(type, "diffie-hellman-group1")) {
2873
0
            return SSH_KEX_DH_GROUP1;
2874
0
        }
2875
0
    }
2876
2877
0
    return 0;
2878
0
}
2879
2880
static unsigned
2881
ssh_kex_hash_type(char *type_string)
2882
0
{
2883
0
    if (type_string && g_str_has_suffix(type_string, "sha1")) {
2884
0
        return SSH_KEX_HASH_SHA1;
2885
0
    }else if (type_string && g_str_has_suffix(type_string, "sha256")) {
2886
0
        return SSH_KEX_HASH_SHA256;
2887
0
    }else if (type_string && g_str_has_suffix(type_string, "sha256@libssh.org")) {
2888
0
        return SSH_KEX_HASH_SHA256;
2889
0
    }else if (type_string && g_str_has_suffix(type_string, "sha512")) {
2890
0
        return SSH_KEX_HASH_SHA512;
2891
0
    } else {
2892
0
        ws_debug("hash type %s not supported", type_string);
2893
0
        return 0;
2894
0
    }
2895
0
}
2896
2897
static ssh_bignum *
2898
ssh_kex_make_bignum(const uint8_t *data, unsigned length)
2899
0
{
2900
    // 512 bytes (4096 bits) is the maximum bignum size we're supporting
2901
    // Actually we need 513 bytes, to make provision for signed values
2902
    // Diffie-Hellman group 18 has 8192 bits
2903
0
    if (length == 0 || length > 1025) {
2904
0
        return NULL;
2905
0
    }
2906
2907
0
    ssh_bignum *bn = wmem_new0(wmem_file_scope(), ssh_bignum);
2908
0
    bn->data = (uint8_t *)wmem_alloc0(wmem_file_scope(), length);
2909
2910
0
    if (data) {
2911
0
        memcpy(bn->data, data, length);
2912
0
    }
2913
2914
0
    bn->length = length;
2915
0
    return bn;
2916
0
}
2917
2918
static bool
2919
ssh_read_e(tvbuff_t *tvb, int offset, struct ssh_flow_data *global_data)
2920
0
{
2921
    // store the client's public part (e) for later usage
2922
0
    uint32_t length = tvb_get_ntohl(tvb, offset);
2923
0
    global_data->kex_e = ssh_kex_make_bignum(NULL, length);
2924
0
    if (!global_data->kex_e) {
2925
0
        return false;
2926
0
    }
2927
0
    tvb_memcpy(tvb, global_data->kex_e->data, offset + 4, length);
2928
0
    return true;
2929
0
}
2930
2931
static bool
2932
ssh_read_f(tvbuff_t *tvb, int offset, struct ssh_flow_data *global_data)
2933
0
{
2934
    // store the server's public part (f) for later usage
2935
0
    uint32_t length = tvb_get_ntohl(tvb, offset);
2936
0
    global_data->kex_f = ssh_kex_make_bignum(NULL, length);
2937
0
    if (!global_data->kex_f) {
2938
0
        return false;
2939
0
    }
2940
0
    tvb_memcpy(tvb, global_data->kex_f->data, offset + 4, length);
2941
0
    return true;
2942
0
}
2943
2944
static int  // add support of client PQ hybrid key (e)
2945
ssh_read_e_pq(tvbuff_t *tvb, int offset, struct ssh_flow_data *global_data)
2946
0
{
2947
    // Read length of PQ client key
2948
0
    uint32_t length = tvb_get_ntohl(tvb, offset);
2949
2950
    // Sanity check
2951
0
    if (length == 0 || length > 65535) {
2952
0
        ws_debug("ssh_read_e_pq: Invalid PQ key length: %u", length);
2953
0
        return false;
2954
0
    }
2955
2956
    // Free any existing data (if dissecting multiple sessions)
2957
0
    wmem_free(wmem_file_scope(), global_data->kex_e_pq);
2958
2959
    // Allocate and store the PQ client key
2960
0
    global_data->kex_e_pq = (unsigned char *)wmem_alloc(wmem_file_scope(), length);
2961
0
    global_data->kex_e_pq_len = length;
2962
2963
0
    tvb_memcpy(tvb, global_data->kex_e_pq, offset + 4, length);
2964
2965
0
    ws_debug("Stored %u bytes of client PQ key - stored new_offset_client: %d - offset: %d", length, offset + 4 + length, offset);
2966
0
    return offset + 4 + length;  // consuming packet (advancing offset)
2967
0
}
2968
2969
static int  // add support of server PQ hybrid key (f)
2970
ssh_read_f_pq(tvbuff_t *tvb, int offset, struct ssh_flow_data *global_data)
2971
0
{
2972
    // Read length of PQ server key
2973
0
    uint32_t length = tvb_get_ntohl(tvb, offset);
2974
2975
    // Sanity check
2976
0
    if (length == 0 || length > 65535) {
2977
0
        ws_debug("ssh_read_f_pq: Invalid PQ key length: %u", length);
2978
0
        return false;
2979
0
    }
2980
2981
    // Free any existing data
2982
0
    wmem_free(wmem_file_scope(), global_data->kex_f_pq);
2983
2984
    // Allocate and store the PQ server key
2985
0
    global_data->kex_f_pq = (unsigned char *)wmem_alloc(wmem_file_scope(), length);
2986
0
    global_data->kex_f_pq_len = length;
2987
2988
0
    tvb_memcpy(tvb, global_data->kex_f_pq, offset + 4, length);
2989
2990
0
    ws_debug("Stored %u bytes of server PQ key - stored new_offset_server: %d - offset: %d", length, offset + 4 + length, offset);
2991
0
    return offset + 4 + length;  // consuming packet (advancing offset)
2992
0
}
2993
2994
2995
static ssh_bignum *
2996
ssh_read_mpint(tvbuff_t *tvb, int offset)
2997
0
{
2998
    // store the DH group modulo (p) for later usage
2999
0
    int length = tvb_get_ntohl(tvb, offset);
3000
0
    ssh_bignum * bn = ssh_kex_make_bignum(NULL, length);
3001
0
    if (!bn) {
3002
0
        ws_debug("invalid bignum length %u", length);
3003
0
        return NULL;
3004
0
    }
3005
0
    tvb_memcpy(tvb, bn->data, offset + 4, length);
3006
0
    return bn;
3007
0
}
3008
3009
static void
3010
ssh_keylog_hash_write_secret(struct ssh_flow_data *global_data, wmem_allocator_t* tmp_allocator)
3011
0
{
3012
    /*
3013
     * This computation is defined differently for each key exchange method:
3014
     * https://tools.ietf.org/html/rfc4253#page-23
3015
     * https://tools.ietf.org/html/rfc5656#page-8
3016
     * https://tools.ietf.org/html/rfc4419#page-4
3017
     * All key exchange methods:
3018
     * https://www.iana.org/assignments/ssh-parameters/ssh-parameters.xhtml#ssh-parameters-16
3019
     */
3020
3021
0
    gcry_md_hd_t hd;
3022
0
    ssh_key_map_entry_t *entry;
3023
0
    ssh_bignum *secret = NULL;
3024
0
    int length;
3025
0
    bool client_cookie = false;
3026
3027
0
    ssh_keylog_read_file();
3028
3029
0
    unsigned kex_type = ssh_kex_type(global_data->kex);
3030
0
    unsigned kex_hash_type = ssh_kex_hash_type(global_data->kex);
3031
3032
0
    entry = (ssh_key_map_entry_t *)g_hash_table_lookup(ssh_master_key_map, global_data->peer_data[SERVER_PEER_DATA].bn_cookie);
3033
0
    if (!entry) {
3034
0
        entry = (ssh_key_map_entry_t *)g_hash_table_lookup(ssh_master_key_map, global_data->peer_data[CLIENT_PEER_DATA].bn_cookie);
3035
0
        client_cookie = true;
3036
0
    }
3037
0
    if (!entry) {
3038
0
        ws_debug("ssh decryption: no entry in keylog file for this session");
3039
0
        global_data->do_decrypt = false;
3040
0
        return;
3041
0
    }
3042
3043
0
    if (!strcmp(entry->type, "PRIVATE_KEY")) {
3044
0
        if (client_cookie) {
3045
0
            secret = ssh_kex_shared_secret(kex_type, global_data->kex_f, entry->key_material, global_data->kex_gex_p);
3046
0
        } else {
3047
0
            secret = ssh_kex_shared_secret(kex_type, global_data->kex_e, entry->key_material, global_data->kex_gex_p);
3048
0
        }
3049
0
    } else if (!strcmp(entry->type, "SHARED_SECRET")) {
3050
0
        secret = ssh_kex_make_bignum(entry->key_material->data, entry->key_material->length);
3051
0
    } else {
3052
0
        ws_debug("ssh decryption: unknown key type in keylog file");
3053
0
        global_data->do_decrypt = false;
3054
0
        return;
3055
0
    }
3056
3057
0
    if (!secret) {
3058
0
        ws_debug("ssh decryption: no key material for this session");
3059
0
        global_data->do_decrypt = false;
3060
0
        return;
3061
0
    }
3062
3063
    // shared secret data needs to be written as an mpint, and we need it later
3064
0
    if (kex_type == SSH_KEX_SNTRUP761X25519 || kex_type == SSH_KEX_MLKEM768X25519) {
3065
        // Reset array while REKEY: sanitize shared_secret:
3066
0
        global_data->kex_shared_secret = wmem_array_new(wmem_file_scope(), 1);
3067
        // For PQ KEMs: use shared_secret as-is, whether SHARED_SECRET or PRIVATE_KEY
3068
        // Do NOT prepend 0x00 (OpenSSH already encodes correctly for PQ KEM)
3069
0
        ssh_hash_buffer_put_string(global_data->kex_shared_secret, secret->data, secret->length);
3070
0
    } else {
3071
        // For all other KEX types (e.g., curve25519, ecdh-sha2, etc.)
3072
        // Pad with 0x00 if MSB is set, to comply with mpint format (RFC 4251)
3073
0
        if (secret->data[0] & 0x80) {         // Stored in Big endian
3074
0
            length = secret->length + 1;
3075
0
            uint8_t *tmp = (uint8_t *)wmem_alloc0(tmp_allocator, length);
3076
0
            memcpy(tmp + 1, secret->data, secret->length);
3077
0
            tmp[0] = 0;
3078
0
            secret->data = tmp;
3079
0
            secret->length = length;
3080
0
        }
3081
        // Reset array while REKEY: sanitize shared_secret:
3082
0
        global_data->kex_shared_secret = wmem_array_new(wmem_file_scope(), 1);
3083
0
        ssh_hash_buffer_put_string(global_data->kex_shared_secret, secret->data, secret->length);
3084
0
    }
3085
3086
0
    wmem_array_t    * kex_gex_p = wmem_array_new(tmp_allocator, 1);
3087
0
    if(global_data->kex_gex_p){ssh_hash_buffer_put_string(kex_gex_p, global_data->kex_gex_p->data, global_data->kex_gex_p->length);}
3088
0
    wmem_array_t    * kex_gex_g = wmem_array_new(tmp_allocator, 1);
3089
0
    if(global_data->kex_gex_g){ssh_hash_buffer_put_string(kex_gex_g, global_data->kex_gex_g->data, global_data->kex_gex_g->length);}
3090
0
    wmem_array_t    * kex_e = wmem_array_new(tmp_allocator, 1);
3091
0
    if(global_data->kex_e){ssh_hash_buffer_put_string(kex_e, global_data->kex_e->data, global_data->kex_e->length);}
3092
0
    wmem_array_t    * kex_f = wmem_array_new(tmp_allocator, 1);
3093
0
    if(global_data->kex_f){ssh_hash_buffer_put_string(kex_f, global_data->kex_f->data, global_data->kex_f->length);}
3094
0
    wmem_array_t    * kex_e_pq = wmem_array_new(tmp_allocator, 1);
3095
0
    if(global_data->kex_e_pq){ssh_hash_buffer_put_string(kex_e_pq, global_data->kex_e_pq, global_data->kex_e_pq_len);}
3096
0
    wmem_array_t    * kex_f_pq = wmem_array_new(tmp_allocator, 1);
3097
0
    if(global_data->kex_f_pq){ssh_hash_buffer_put_string(kex_f_pq, global_data->kex_f_pq, global_data->kex_f_pq_len);}
3098
3099
0
    wmem_array_t    * kex_hash_buffer = wmem_array_new(tmp_allocator, 1);
3100
0
    ssh_print_data("client_version", (const unsigned char *)wmem_array_get_raw(global_data->kex_client_version), wmem_array_get_count(global_data->kex_client_version));
3101
0
    wmem_array_append(kex_hash_buffer, wmem_array_get_raw(global_data->kex_client_version), wmem_array_get_count(global_data->kex_client_version));
3102
0
    ssh_print_data("server_version", (const unsigned char *)wmem_array_get_raw(global_data->kex_server_version), wmem_array_get_count(global_data->kex_server_version));
3103
0
    wmem_array_append(kex_hash_buffer, wmem_array_get_raw(global_data->kex_server_version), wmem_array_get_count(global_data->kex_server_version));
3104
0
    ssh_print_data("client_key_exchange_init", (const unsigned char *)wmem_array_get_raw(global_data->kex_client_key_exchange_init), wmem_array_get_count(global_data->kex_client_key_exchange_init));
3105
0
    wmem_array_append(kex_hash_buffer, wmem_array_get_raw(global_data->kex_client_key_exchange_init), wmem_array_get_count(global_data->kex_client_key_exchange_init));
3106
0
    ssh_print_data("server_key_exchange_init", (const unsigned char *)wmem_array_get_raw(global_data->kex_server_key_exchange_init), wmem_array_get_count(global_data->kex_server_key_exchange_init));
3107
0
    wmem_array_append(kex_hash_buffer, wmem_array_get_raw(global_data->kex_server_key_exchange_init), wmem_array_get_count(global_data->kex_server_key_exchange_init));
3108
0
    ssh_print_data("kex_server_host_key_blob", (const unsigned char *)wmem_array_get_raw(global_data->kex_server_host_key_blob), wmem_array_get_count(global_data->kex_server_host_key_blob));
3109
0
    wmem_array_append(kex_hash_buffer, wmem_array_get_raw(global_data->kex_server_host_key_blob), wmem_array_get_count(global_data->kex_server_host_key_blob));
3110
0
    if(kex_type==SSH_KEX_DH_GEX){
3111
0
        ssh_print_data("kex_gex_bits_min", (const unsigned char *)wmem_array_get_raw(global_data->kex_gex_bits_min), wmem_array_get_count(global_data->kex_gex_bits_min));
3112
0
        wmem_array_append(kex_hash_buffer, wmem_array_get_raw(global_data->kex_gex_bits_min), wmem_array_get_count(global_data->kex_gex_bits_min));
3113
0
        ssh_print_data("kex_gex_bits_req", (const unsigned char *)wmem_array_get_raw(global_data->kex_gex_bits_req), wmem_array_get_count(global_data->kex_gex_bits_req));
3114
0
        wmem_array_append(kex_hash_buffer, wmem_array_get_raw(global_data->kex_gex_bits_req), wmem_array_get_count(global_data->kex_gex_bits_req));
3115
0
        ssh_print_data("kex_gex_bits_max", (const unsigned char *)wmem_array_get_raw(global_data->kex_gex_bits_max), wmem_array_get_count(global_data->kex_gex_bits_max));
3116
0
        wmem_array_append(kex_hash_buffer, wmem_array_get_raw(global_data->kex_gex_bits_max), wmem_array_get_count(global_data->kex_gex_bits_max));
3117
0
        ssh_print_data("key modulo  (p)", (const unsigned char *)wmem_array_get_raw(kex_gex_p), wmem_array_get_count(kex_gex_p));
3118
0
        wmem_array_append(kex_hash_buffer, wmem_array_get_raw(kex_gex_p), wmem_array_get_count(kex_gex_p));
3119
0
        ssh_print_data("key base    (g)", (const unsigned char *)wmem_array_get_raw(kex_gex_g), wmem_array_get_count(kex_gex_g));
3120
0
        wmem_array_append(kex_hash_buffer, wmem_array_get_raw(kex_gex_g), wmem_array_get_count(kex_gex_g));
3121
0
        ssh_print_data("key client  (e)", (const unsigned char *)wmem_array_get_raw(kex_e), wmem_array_get_count(kex_e));
3122
0
        wmem_array_append(kex_hash_buffer, wmem_array_get_raw(kex_e), wmem_array_get_count(kex_e));
3123
0
        ssh_print_data("key server  (f)", (const unsigned char *)wmem_array_get_raw(kex_f), wmem_array_get_count(kex_f));
3124
0
        wmem_array_append(kex_hash_buffer, wmem_array_get_raw(kex_f), wmem_array_get_count(kex_f));
3125
0
    }
3126
0
    if(kex_type==SSH_KEX_DH_GROUP1 || kex_type==SSH_KEX_DH_GROUP14 || kex_type==SSH_KEX_DH_GROUP16 || kex_type==SSH_KEX_DH_GROUP18){
3127
0
        ssh_print_data("key client  (e)", (const unsigned char *)wmem_array_get_raw(kex_e), wmem_array_get_count(kex_e));
3128
0
        wmem_array_append(kex_hash_buffer, wmem_array_get_raw(kex_e), wmem_array_get_count(kex_e));
3129
0
        ssh_print_data("key server (f)", (const unsigned char *)wmem_array_get_raw(kex_f), wmem_array_get_count(kex_f));
3130
0
        wmem_array_append(kex_hash_buffer, wmem_array_get_raw(kex_f), wmem_array_get_count(kex_f));
3131
0
    }
3132
0
    if(kex_type==SSH_KEX_CURVE25519){
3133
0
        ssh_print_data("key client  (Q_C)", (const unsigned char *)wmem_array_get_raw(kex_e), wmem_array_get_count(kex_e));
3134
0
        wmem_array_append(kex_hash_buffer, wmem_array_get_raw(kex_e), wmem_array_get_count(kex_e));
3135
0
        ssh_print_data("key server (Q_S)", (const unsigned char *)wmem_array_get_raw(kex_f), wmem_array_get_count(kex_f));
3136
0
        wmem_array_append(kex_hash_buffer, wmem_array_get_raw(kex_f), wmem_array_get_count(kex_f));
3137
0
    }
3138
0
    if (kex_type==SSH_KEX_SNTRUP761X25519){ // Add support of sntrup761x25519
3139
0
        ssh_print_data("key client  (Q_C)", (const unsigned char *)wmem_array_get_raw(kex_e_pq), wmem_array_get_count(kex_e_pq));
3140
0
        wmem_array_append(kex_hash_buffer, wmem_array_get_raw(kex_e_pq), wmem_array_get_count(kex_e_pq));
3141
0
        ssh_print_data("key server (Q_S)", (const unsigned char *)wmem_array_get_raw(kex_f_pq), wmem_array_get_count(kex_f_pq));
3142
0
        wmem_array_append(kex_hash_buffer, wmem_array_get_raw(kex_f_pq), wmem_array_get_count(kex_f_pq));
3143
0
        ws_noisy("Switch to SSH_KEX_SNTRUP761X25519");
3144
0
    }
3145
0
    if (kex_type==SSH_KEX_MLKEM768X25519){ // Add support of mlkem768x25519
3146
0
        ssh_print_data("key client  (Q_C)", (const unsigned char *)wmem_array_get_raw(kex_e_pq), wmem_array_get_count(kex_e_pq));
3147
0
        wmem_array_append(kex_hash_buffer, wmem_array_get_raw(kex_e_pq), wmem_array_get_count(kex_e_pq));
3148
0
        ssh_print_data("key server (Q_S)", (const unsigned char *)wmem_array_get_raw(kex_f_pq), wmem_array_get_count(kex_f_pq));
3149
0
        wmem_array_append(kex_hash_buffer, wmem_array_get_raw(kex_f_pq), wmem_array_get_count(kex_f_pq));
3150
0
        ws_noisy("Switch to SSH_KEX_MLKEM768X25519");
3151
0
    }
3152
0
    ssh_print_data("shared secret", (const unsigned char *)wmem_array_get_raw(global_data->kex_shared_secret), wmem_array_get_count(global_data->kex_shared_secret));
3153
0
    wmem_array_append(kex_hash_buffer, wmem_array_get_raw(global_data->kex_shared_secret), wmem_array_get_count(global_data->kex_shared_secret));
3154
3155
0
    ssh_print_data("exchange", (const unsigned char *)wmem_array_get_raw(kex_hash_buffer), wmem_array_get_count(kex_hash_buffer));
3156
3157
0
    unsigned hash_len = 32;
3158
0
    if(kex_hash_type==SSH_KEX_HASH_SHA1) {
3159
0
        gcry_md_open(&hd, GCRY_MD_SHA1, 0);
3160
0
        hash_len = 20;
3161
0
    } else if(kex_hash_type==SSH_KEX_HASH_SHA256) {
3162
0
        gcry_md_open(&hd, GCRY_MD_SHA256, 0);
3163
0
        hash_len = 32;
3164
0
    } else if(kex_hash_type==SSH_KEX_HASH_SHA512) {
3165
0
        gcry_md_open(&hd, GCRY_MD_SHA512, 0);
3166
0
        hash_len = 64;
3167
0
    } else {
3168
0
        ws_debug("kex_hash_type type %d not supported", kex_hash_type);
3169
0
        return;
3170
0
    }
3171
0
    uint8_t *exchange_hash = (uint8_t *)wmem_alloc0(wmem_file_scope(), hash_len);
3172
0
    gcry_md_write(hd, wmem_array_get_raw(kex_hash_buffer), wmem_array_get_count(kex_hash_buffer));
3173
0
    memcpy(exchange_hash, gcry_md_read(hd, 0), hash_len);
3174
0
    gcry_md_close(hd);
3175
0
    ssh_print_data("hash", exchange_hash, hash_len);
3176
0
    global_data->secret = secret;
3177
0
    ssh_derive_symmetric_keys(secret, exchange_hash, hash_len, global_data);
3178
0
}
3179
3180
// the purpose of this function is to deal with all different kex methods
3181
static ssh_bignum *
3182
ssh_kex_shared_secret(int kex_type, ssh_bignum *pub, ssh_bignum *priv, ssh_bignum *modulo)
3183
0
{
3184
0
    DISSECTOR_ASSERT(pub != NULL);
3185
0
    DISSECTOR_ASSERT(priv != NULL);
3186
3187
0
    ssh_bignum *secret = ssh_kex_make_bignum(NULL, pub->length);
3188
0
    if (!secret) {
3189
0
        ws_debug("invalid key length %u", pub->length);
3190
0
        return NULL;
3191
0
    }
3192
3193
0
    if(kex_type==SSH_KEX_DH_GEX){
3194
0
        if (modulo == NULL) {
3195
0
            ws_debug("Missing group modulo");
3196
0
            return NULL;
3197
0
        }
3198
0
        gcry_mpi_t b = NULL;
3199
0
        gcry_mpi_scan(&b, GCRYMPI_FMT_USG, pub->data, pub->length, NULL);
3200
0
        gcry_mpi_t d = NULL, e = NULL, m = NULL;
3201
0
        size_t result_len = 0;
3202
0
        d = gcry_mpi_new(pub->length*8);
3203
0
        gcry_mpi_scan(&e, GCRYMPI_FMT_USG, priv->data, priv->length, NULL);
3204
0
        gcry_mpi_scan(&m, GCRYMPI_FMT_USG, modulo->data, modulo->length, NULL);
3205
0
        gcry_mpi_powm(d, b, e, m);                 // gcry_mpi_powm(d, b, e, m)    => d = b^e % m
3206
0
        gcry_mpi_print(GCRYMPI_FMT_USG, secret->data, secret->length, &result_len, d);
3207
0
        secret->length = (unsigned)result_len;        // Should not be larger than what fits in a 32-bit unsigned integer...
3208
0
        gcry_mpi_release(d);
3209
0
        gcry_mpi_release(b);
3210
0
        gcry_mpi_release(e);
3211
0
        gcry_mpi_release(m);
3212
3213
0
    }else if(kex_type==SSH_KEX_DH_GROUP1 || kex_type==SSH_KEX_DH_GROUP14 || kex_type==SSH_KEX_DH_GROUP16 || kex_type==SSH_KEX_DH_GROUP18){
3214
0
        gcry_mpi_t m = NULL;
3215
0
        if(kex_type==SSH_KEX_DH_GROUP1){
3216
0
            static const uint8_t p[] = {
3217
0
                    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
3218
0
                    0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
3219
0
                    0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
3220
0
                    0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
3221
0
                    0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
3222
0
                    0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
3223
0
                    0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
3224
0
                    0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,};
3225
0
            gcry_mpi_scan(&m, GCRYMPI_FMT_USG, p, sizeof(p), NULL);
3226
0
        }else if(kex_type==SSH_KEX_DH_GROUP14){
3227
//p:FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF
3228
0
            static const uint8_t p[] = {
3229
0
                    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
3230
0
                    0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
3231
0
                    0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
3232
0
                    0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
3233
0
                    0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
3234
0
                    0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
3235
0
                    0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
3236
0
                    0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
3237
0
                    0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
3238
0
                    0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
3239
0
                    0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
3240
0
                    0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
3241
0
                    0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
3242
0
                    0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
3243
0
                    0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
3244
0
                    0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
3245
0
            gcry_mpi_scan(&m, GCRYMPI_FMT_USG, p, sizeof(p), NULL);
3246
0
        }else if(kex_type==SSH_KEX_DH_GROUP16){
3247
//p:FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF
3248
0
            static const uint8_t p[] = {
3249
0
                    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
3250
0
                    0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
3251
0
                    0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
3252
0
                    0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
3253
0
                    0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
3254
0
                    0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
3255
0
                    0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
3256
0
                    0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
3257
0
                    0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
3258
0
                    0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
3259
0
                    0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
3260
0
                    0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
3261
0
                    0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
3262
0
                    0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
3263
0
                    0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
3264
0
                    0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33,
3265
0
                    0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A,
3266
0
                    0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
3267
0
                    0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D,
3268
0
                    0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64,
3269
0
                    0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
3270
0
                    0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2,
3271
0
                    0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E,
3272
0
                    0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
3273
0
                    0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C,
3274
0
                    0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8,
3275
0
                    0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
3276
0
                    0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2,
3277
0
                    0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF,
3278
0
                    0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
3279
0
                    0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F,
3280
0
                    0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,};
3281
0
            gcry_mpi_scan(&m, GCRYMPI_FMT_USG, p, sizeof(p), NULL);
3282
0
        }else if(kex_type==SSH_KEX_DH_GROUP18){
3283
//p:FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E438777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F5683423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD922222E04A4037C0713EB57A81A23F0C73473FC646CEA306B4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A364597E899A0255DC164F31CC50846851DF9AB48195DED7EA1B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F924009438B481C6CD7889A002ED5EE382BC9190DA6FC026E479558E4475677E9AA9E3050E2765694DFC81F56E880B96E7160C980DD98EDD3DFFFFFFFFFFFFFFFFF
3284
0
            static const uint8_t p[] = {
3285
0
                    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
3286
0
                    0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
3287
0
                    0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
3288
0
                    0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
3289
0
                    0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
3290
0
                    0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
3291
0
                    0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
3292
0
                    0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
3293
0
                    0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
3294
0
                    0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
3295
0
                    0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
3296
0
                    0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
3297
0
                    0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
3298
0
                    0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
3299
0
                    0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
3300
0
                    0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33,
3301
0
                    0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A,
3302
0
                    0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
3303
0
                    0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D,
3304
0
                    0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64,
3305
0
                    0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
3306
0
                    0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2,
3307
0
                    0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E,
3308
0
                    0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
3309
0
                    0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C,
3310
0
                    0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8,
3311
0
                    0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
3312
0
                    0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2,
3313
0
                    0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF,
3314
0
                    0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
3315
0
                    0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F,
3316
0
                    0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92, 0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26,
3317
0
                    0xC1, 0xD4, 0xDC, 0xB2, 0x60, 0x26, 0x46, 0xDE, 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD,
3318
0
                    0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E, 0xE5, 0xDB, 0x38, 0x2F, 0x41, 0x30, 0x01, 0xAE,
3319
0
                    0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31, 0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18,
3320
0
                    0xDA, 0x3E, 0xDB, 0xEB, 0xCF, 0x9B, 0x14, 0xED, 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B,
3321
0
                    0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B, 0x33, 0x20, 0x51, 0x51, 0x2B, 0xD7, 0xAF, 0x42,
3322
0
                    0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF, 0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC,
3323
0
                    0xF0, 0x32, 0xEA, 0x15, 0xD1, 0x72, 0x1D, 0x03, 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6,
3324
0
                    0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82, 0xB5, 0xA8, 0x40, 0x31, 0x90, 0x0B, 0x1C, 0x9E,
3325
0
                    0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3, 0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE,
3326
0
                    0x0F, 0x1D, 0x45, 0xB7, 0xFF, 0x58, 0x5A, 0xC5, 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA,
3327
0
                    0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8, 0x14, 0xCC, 0x5E, 0xD2, 0x0F, 0x80, 0x37, 0xE0,
3328
0
                    0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28, 0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76,
3329
0
                    0xF5, 0x50, 0xAA, 0x3D, 0x8A, 0x1F, 0xBF, 0xF0, 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C,
3330
0
                    0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, 0x38, 0x7F, 0xE8, 0xD7, 0x6E, 0x3C, 0x04, 0x68,
3331
0
                    0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE, 0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6,
3332
0
                    0xE6, 0x94, 0xF9, 0x1E, 0x6D, 0xBE, 0x11, 0x59, 0x74, 0xA3, 0x92, 0x6F, 0x12, 0xFE, 0xE5, 0xE4,
3333
0
                    0x38, 0x77, 0x7C, 0xB6, 0xA9, 0x32, 0xDF, 0x8C, 0xD8, 0xBE, 0xC4, 0xD0, 0x73, 0xB9, 0x31, 0xBA,
3334
0
                    0x3B, 0xC8, 0x32, 0xB6, 0x8D, 0x9D, 0xD3, 0x00, 0x74, 0x1F, 0xA7, 0xBF, 0x8A, 0xFC, 0x47, 0xED,
3335
0
                    0x25, 0x76, 0xF6, 0x93, 0x6B, 0xA4, 0x24, 0x66, 0x3A, 0xAB, 0x63, 0x9C, 0x5A, 0xE4, 0xF5, 0x68,
3336
0
                    0x34, 0x23, 0xB4, 0x74, 0x2B, 0xF1, 0xC9, 0x78, 0x23, 0x8F, 0x16, 0xCB, 0xE3, 0x9D, 0x65, 0x2D,
3337
0
                    0xE3, 0xFD, 0xB8, 0xBE, 0xFC, 0x84, 0x8A, 0xD9, 0x22, 0x22, 0x2E, 0x04, 0xA4, 0x03, 0x7C, 0x07,
3338
0
                    0x13, 0xEB, 0x57, 0xA8, 0x1A, 0x23, 0xF0, 0xC7, 0x34, 0x73, 0xFC, 0x64, 0x6C, 0xEA, 0x30, 0x6B,
3339
0
                    0x4B, 0xCB, 0xC8, 0x86, 0x2F, 0x83, 0x85, 0xDD, 0xFA, 0x9D, 0x4B, 0x7F, 0xA2, 0xC0, 0x87, 0xE8,
3340
0
                    0x79, 0x68, 0x33, 0x03, 0xED, 0x5B, 0xDD, 0x3A, 0x06, 0x2B, 0x3C, 0xF5, 0xB3, 0xA2, 0x78, 0xA6,
3341
0
                    0x6D, 0x2A, 0x13, 0xF8, 0x3F, 0x44, 0xF8, 0x2D, 0xDF, 0x31, 0x0E, 0xE0, 0x74, 0xAB, 0x6A, 0x36,
3342
0
                    0x45, 0x97, 0xE8, 0x99, 0xA0, 0x25, 0x5D, 0xC1, 0x64, 0xF3, 0x1C, 0xC5, 0x08, 0x46, 0x85, 0x1D,
3343
0
                    0xF9, 0xAB, 0x48, 0x19, 0x5D, 0xED, 0x7E, 0xA1, 0xB1, 0xD5, 0x10, 0xBD, 0x7E, 0xE7, 0x4D, 0x73,
3344
0
                    0xFA, 0xF3, 0x6B, 0xC3, 0x1E, 0xCF, 0xA2, 0x68, 0x35, 0x90, 0x46, 0xF4, 0xEB, 0x87, 0x9F, 0x92,
3345
0
                    0x40, 0x09, 0x43, 0x8B, 0x48, 0x1C, 0x6C, 0xD7, 0x88, 0x9A, 0x00, 0x2E, 0xD5, 0xEE, 0x38, 0x2B,
3346
0
                    0xC9, 0x19, 0x0D, 0xA6, 0xFC, 0x02, 0x6E, 0x47, 0x95, 0x58, 0xE4, 0x47, 0x56, 0x77, 0xE9, 0xAA,
3347
0
                    0x9E, 0x30, 0x50, 0xE2, 0x76, 0x56, 0x94, 0xDF, 0xC8, 0x1F, 0x56, 0xE8, 0x80, 0xB9, 0x6E, 0x71,
3348
0
                    0x60, 0xC9, 0x80, 0xDD, 0x98, 0xED, 0xD3, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,};
3349
0
            gcry_mpi_scan(&m, GCRYMPI_FMT_USG, p, sizeof(p), NULL);
3350
0
        }
3351
3352
0
        gcry_mpi_t b = NULL;
3353
0
        gcry_mpi_scan(&b, GCRYMPI_FMT_USG, pub->data, pub->length, NULL);
3354
0
        gcry_mpi_t d = NULL, e = NULL;
3355
0
        size_t result_len = 0;
3356
0
        d = gcry_mpi_new(pub->length*8);
3357
0
        gcry_mpi_scan(&e, GCRYMPI_FMT_USG, priv->data, priv->length, NULL);
3358
0
        gcry_mpi_powm(d, b, e, m);                 // gcry_mpi_powm(d, b, e, m)    => d = b^e % m
3359
0
        gcry_mpi_print(GCRYMPI_FMT_USG, secret->data, secret->length, &result_len, d);
3360
0
        secret->length = (unsigned)result_len;        // Should not be larger than what fits in a 32-bit unsigned integer...
3361
0
        gcry_mpi_release(d);
3362
0
        gcry_mpi_release(b);
3363
0
        gcry_mpi_release(e);
3364
0
        gcry_mpi_release(m);
3365
0
    }else if(kex_type==SSH_KEX_CURVE25519){
3366
0
        if (crypto_scalarmult_curve25519(secret->data, priv->data, pub->data)) {
3367
0
            ws_debug("curve25519: can't compute shared secret");
3368
0
            return NULL;
3369
0
        }
3370
0
    } else {
3371
0
        ws_debug("kex_type type %d not supported", kex_type);
3372
0
        return 0;
3373
0
    }
3374
3375
0
    return secret;
3376
0
}
3377
3378
static char *
3379
ssh_string(wmem_allocator_t* allocator, const uint8_t *string, unsigned length)
3380
15
{
3381
15
    char *ssh_string = (char *)wmem_alloc(allocator, length + 4);
3382
15
    ssh_string[0] = (length >> 24) & 0xff;
3383
15
    ssh_string[1] = (length >> 16) & 0xff;
3384
15
    ssh_string[2] = (length >> 8) & 0xff;
3385
15
    ssh_string[3] = length & 0xff;
3386
15
    memcpy(ssh_string + 4, string, length);
3387
15
    return ssh_string;
3388
15
}
3389
3390
static void
3391
ssh_hash_buffer_put_string(wmem_array_t *buffer, const uint8_t *string,
3392
        unsigned length)
3393
15
{
3394
15
    if (!buffer) {
3395
0
        return;
3396
0
    }
3397
3398
15
    char *string_with_length = ssh_string(wmem_array_get_allocator(buffer), string, length);
3399
15
    wmem_array_append(buffer, string_with_length, length + 4);
3400
15
}
3401
3402
static void
3403
ssh_hash_buffer_put_uint32(wmem_array_t *buffer, unsigned val)
3404
0
{
3405
0
    if (!buffer) {
3406
0
        return;
3407
0
    }
3408
3409
0
    char buf[4];
3410
0
    buf[0] = (val >> 24); buf[1] = (val >> 16); buf[2] = (val >>  8); buf[3] = (val >>  0);
3411
0
    wmem_array_append(buffer, buf, 4);
3412
0
}
3413
3414
static void ssh_derive_symmetric_keys(ssh_bignum *secret, uint8_t *exchange_hash,
3415
        unsigned hash_length, struct ssh_flow_data *global_data)
3416
0
{
3417
0
    if (!global_data->session_id) {
3418
0
        global_data->session_id = exchange_hash;
3419
0
        global_data->session_id_length = hash_length;
3420
0
    }
3421
3422
0
    unsigned int we_need = 0;
3423
0
    for(int peer_cnt=0;peer_cnt<2;peer_cnt++){
3424
0
        struct ssh_peer_data * peer_data = &global_data->peer_data[peer_cnt];
3425
        // required size of key depends on cipher used. chacha20 wants 64 bytes
3426
0
        unsigned need = 0;
3427
0
        if (GCRY_CIPHER_CHACHA20 == peer_data->cipher_id) {
3428
0
            need = 64;
3429
0
        } else if (CIPHER_AES128_CBC == peer_data->cipher_id || CIPHER_AES128_CTR == peer_data->cipher_id || CIPHER_AES128_GCM == peer_data->cipher_id) {
3430
0
            need = 16;
3431
0
        } else if (CIPHER_AES192_CBC == peer_data->cipher_id || CIPHER_AES192_CTR == peer_data->cipher_id) {
3432
0
            need = 24;
3433
0
        } else if (CIPHER_AES256_CBC == peer_data->cipher_id || CIPHER_AES256_CTR == peer_data->cipher_id || CIPHER_AES256_GCM == peer_data->cipher_id) {
3434
0
            need = 32;
3435
0
        } else {
3436
0
            ssh_debug_printf("ssh: cipher (%d) is unknown or not set\n", peer_data->cipher_id);
3437
0
            ssh_debug_flush();
3438
0
        }
3439
0
        if(peer_data->mac_id == CIPHER_MAC_SHA2_256){
3440
0
            need = 32;
3441
0
        }else{
3442
0
            ssh_debug_printf("ssh: MAC (%d) is unknown or not set\n", peer_data->mac_id);
3443
0
            ssh_debug_flush();
3444
0
        }
3445
0
        if (we_need<need) {
3446
0
            we_need = need;
3447
0
        }
3448
0
    }
3449
3450
0
    for (int i = 0; i < 6; i ++) {
3451
0
        ssh_derive_symmetric_key(secret, exchange_hash, hash_length,
3452
0
                'A' + i, &global_data->new_keys[i], global_data, we_need);
3453
0
        if(i==0){       ssh_print_data("Initial IV client to server", global_data->new_keys[i].data, global_data->new_keys[i].length);
3454
0
        }else if(i==1){ ssh_print_data("Initial IV server to client", global_data->new_keys[i].data, global_data->new_keys[i].length);
3455
0
        }else if(i==2){ ssh_print_data("Encryption key client to server", global_data->new_keys[i].data, global_data->new_keys[i].length);
3456
0
        }else if(i==3){ ssh_print_data("Encryption key server to client", global_data->new_keys[i].data, global_data->new_keys[i].length);
3457
0
        }else if(i==4){ ssh_print_data("Integrity key client to server", global_data->new_keys[i].data, global_data->new_keys[i].length);
3458
0
        }else if(i==5){ ssh_print_data("Integrity key server to client", global_data->new_keys[i].data, global_data->new_keys[i].length);
3459
0
        }
3460
0
    }
3461
0
}
3462
3463
static void ssh_derive_symmetric_key(ssh_bignum *secret, const uint8_t *exchange_hash,
3464
        unsigned hash_length, char id, ssh_bignum *result_key,
3465
        struct ssh_flow_data *global_data, unsigned we_need)
3466
0
{
3467
0
    gcry_md_hd_t hd;
3468
3469
0
    unsigned kex_hash_type = ssh_kex_hash_type(global_data->kex);
3470
0
    int algo = GCRY_MD_SHA256;
3471
0
    if(kex_hash_type==SSH_KEX_HASH_SHA1){
3472
0
        algo = GCRY_MD_SHA1;
3473
0
    }else if(kex_hash_type==SSH_KEX_HASH_SHA256){
3474
0
        algo = GCRY_MD_SHA256;
3475
0
    }else if(kex_hash_type==SSH_KEX_HASH_SHA512){
3476
0
        algo = GCRY_MD_SHA512;
3477
0
    }
3478
0
    unsigned len = gcry_md_get_algo_dlen(algo);
3479
3480
0
    result_key->data = (unsigned char *)wmem_alloc(wmem_file_scope(), we_need);
3481
3482
0
    char *secret_with_length = ssh_string(NULL, secret->data, secret->length);
3483
3484
0
    if (gcry_md_open(&hd, algo, 0) == 0) {
3485
0
        gcry_md_write(hd, secret_with_length, secret->length + 4);
3486
0
        gcry_md_write(hd, exchange_hash, hash_length);
3487
0
        gcry_md_putc(hd, id);
3488
0
        gcry_md_write(hd, global_data->session_id, hash_length);
3489
0
        unsigned add_length = MIN(len, we_need);
3490
0
        memcpy(result_key->data, gcry_md_read(hd, 0), add_length);
3491
0
        gcry_md_close(hd);
3492
0
    }
3493
3494
    // expand key
3495
0
    for (unsigned have = len; have < we_need; have += len) {
3496
0
        if (gcry_md_open(&hd, algo, 0) == 0) {
3497
0
            gcry_md_write(hd, secret_with_length, secret->length + 4);
3498
0
            gcry_md_write(hd, exchange_hash, hash_length);
3499
0
            gcry_md_write(hd, result_key->data+have-len, len);
3500
0
            unsigned add_length = MIN(len, we_need - have);
3501
0
            memcpy(result_key->data+have, gcry_md_read(hd, 0), add_length);
3502
0
            gcry_md_close(hd);
3503
0
        }
3504
0
    }
3505
0
    wmem_free(NULL, secret_with_length);
3506
3507
0
    result_key->length = we_need;
3508
0
}
3509
3510
static void
3511
ssh_choose_enc_mac(struct ssh_flow_data *global_data)
3512
0
{
3513
0
    for(int peer_cnt=0;peer_cnt<2;peer_cnt++){
3514
0
        struct ssh_peer_data * peer_data = &global_data->peer_data[peer_cnt];
3515
0
        ssh_choose_algo(global_data->peer_data[CLIENT_PEER_DATA].enc_proposals[peer_cnt],
3516
0
                        global_data->peer_data[SERVER_PEER_DATA].enc_proposals[peer_cnt],
3517
0
                        &peer_data->enc);
3518
        /* some ciphers have their own MAC so the "negotiated" one is meaningless */
3519
0
        if(peer_data->enc && (0 == strcmp(peer_data->enc, "aes128-gcm@openssh.com") ||
3520
0
                              0 == strcmp(peer_data->enc, "aes256-gcm@openssh.com"))) {
3521
0
            peer_data->mac = wmem_strdup(wmem_file_scope(), (const char *)"<implicit>");
3522
0
            peer_data->mac_length = 16;
3523
0
            peer_data->length_is_plaintext = 1;
3524
0
        }
3525
0
        else if(peer_data->enc && 0 == strcmp(peer_data->enc, "chacha20-poly1305@openssh.com")) {
3526
0
            peer_data->mac = wmem_strdup(wmem_file_scope(), (const char *)"<implicit>");
3527
0
            peer_data->mac_length = 16;
3528
0
        }
3529
0
        else {
3530
0
            ssh_choose_algo(global_data->peer_data[CLIENT_PEER_DATA].mac_proposals[peer_cnt],
3531
0
                            global_data->peer_data[SERVER_PEER_DATA].mac_proposals[peer_cnt],
3532
0
                            &peer_data->mac);
3533
0
            ssh_set_mac_length(peer_data);
3534
0
        }
3535
0
        ssh_choose_algo(global_data->peer_data[CLIENT_PEER_DATA].comp_proposals[peer_cnt],
3536
0
                        global_data->peer_data[SERVER_PEER_DATA].comp_proposals[peer_cnt],
3537
0
                        &peer_data->comp);
3538
0
    }
3539
3540
0
    ssh_decryption_set_cipher_id(&global_data->peer_data[CLIENT_PEER_DATA]);
3541
0
    ssh_decryption_set_mac_id(&global_data->peer_data[CLIENT_PEER_DATA]);
3542
0
    ssh_decryption_set_cipher_id(&global_data->peer_data[SERVER_PEER_DATA]);
3543
0
    ssh_decryption_set_mac_id(&global_data->peer_data[SERVER_PEER_DATA]);
3544
0
}
3545
3546
static void
3547
ssh_decryption_set_cipher_id(struct ssh_peer_data *peer)
3548
0
{
3549
0
    char *cipher_name = peer->enc;
3550
3551
0
    if (!cipher_name) {
3552
0
        peer->cipher = NULL;
3553
0
        ws_debug("ERROR: cipher_name is NULL");
3554
0
    } else if (0 == strcmp(cipher_name, "chacha20-poly1305@openssh.com")) { // add chacha20-poly1305@openssh.com
3555
0
        peer->cipher_id = GCRY_CIPHER_CHACHA20;
3556
0
    } else if (0 == strcmp(cipher_name, "chacha20-poly1305")) { // add chacha20-poly1305
3557
0
        peer->cipher_id = GCRY_CIPHER_CHACHA20;
3558
0
    } else if (0 == strcmp(cipher_name, "aes128-gcm@openssh.com")) {
3559
0
        peer->cipher_id = CIPHER_AES128_GCM;
3560
0
    } else if (0 == strcmp(cipher_name, "aes128-gcm")) {
3561
0
        peer->cipher_id = CIPHER_AES128_GCM;
3562
0
    } else if (0 == strcmp(cipher_name, "aes256-gcm@openssh.com")) {
3563
0
        peer->cipher_id = CIPHER_AES256_GCM;
3564
0
    } else if (0 == strcmp(cipher_name, "aes256-gcm")) {
3565
0
        peer->cipher_id = CIPHER_AES256_GCM;
3566
0
    } else if (0 == strcmp(cipher_name, "aes128-cbc")) {
3567
0
        peer->cipher_id = CIPHER_AES128_CBC;
3568
0
    } else if (0 == strcmp(cipher_name, "aes192-cbc")) {
3569
0
        peer->cipher_id = CIPHER_AES192_CBC;
3570
0
    } else if (0 == strcmp(cipher_name, "aes256-cbc")) {
3571
0
        peer->cipher_id = CIPHER_AES256_CBC;
3572
0
    } else if (0 == strcmp(cipher_name, "aes128-ctr")) {
3573
0
        peer->cipher_id = CIPHER_AES128_CTR;
3574
0
    } else if (0 == strcmp(cipher_name, "aes192-ctr")) {
3575
0
        peer->cipher_id = CIPHER_AES192_CTR;
3576
0
    } else if (0 == strcmp(cipher_name, "aes256-ctr")) {
3577
0
        peer->cipher_id = CIPHER_AES256_CTR;
3578
0
    } else if (0 == strcmp(cipher_name, "none")) {
3579
0
        peer->cipher_id = CIPHER_NULL;
3580
0
        peer->length_is_plaintext = 1;
3581
0
    } else {
3582
0
        peer->cipher = NULL;
3583
0
        ws_debug("decryption not supported: %s", cipher_name);
3584
0
    }
3585
0
}
3586
3587
static void
3588
ssh_decryption_set_mac_id(struct ssh_peer_data *peer)
3589
0
{
3590
0
    char *mac_name = peer->mac;
3591
3592
0
    if (!mac_name) {
3593
0
        peer->mac = NULL;
3594
0
        ws_debug("ERROR: mac_name is NULL");
3595
0
    } else if (0 == strcmp(mac_name, "hmac-sha2-256")) {
3596
0
        peer->mac_id = CIPHER_MAC_SHA2_256;
3597
0
    } else {
3598
0
        ws_debug("decryption MAC not supported: %s", mac_name);
3599
0
    }
3600
0
}
3601
3602
static bool
3603
gcry_cipher_destroy_cb(wmem_allocator_t *allocator _U_, wmem_cb_event_t event _U_, void *user_data)
3604
0
{
3605
0
    gcry_cipher_hd_t hd = (gcry_cipher_hd_t)user_data;
3606
3607
0
    gcry_cipher_close(hd);
3608
3609
0
    return false;
3610
0
}
3611
3612
static void
3613
ssh_decryption_setup_cipher(struct ssh_peer_data *peer_data,
3614
        ssh_bignum *iv, ssh_bignum *key)
3615
0
{
3616
0
    gcry_error_t err;
3617
0
    gcry_cipher_hd_t *hd1, *hd2;
3618
3619
0
    hd1 = &peer_data->cipher;
3620
0
    hd2 = &peer_data->cipher_2;
3621
3622
0
    if (GCRY_CIPHER_CHACHA20 == peer_data->cipher_id) {
3623
0
        if (gcry_cipher_open(hd1, GCRY_CIPHER_CHACHA20, GCRY_CIPHER_MODE_STREAM, 0) ||
3624
0
            gcry_cipher_open(hd2, GCRY_CIPHER_CHACHA20, GCRY_CIPHER_MODE_STREAM, 0)) {
3625
0
            gcry_cipher_close(*hd1);
3626
0
            gcry_cipher_close(*hd2);
3627
0
            ws_debug("ssh: can't open chacha20 cipher handles");
3628
0
            return;
3629
0
        }
3630
3631
0
        uint8_t k1[32];
3632
0
        uint8_t k2[32];
3633
0
        if(key->data){
3634
0
            memcpy(k1, key->data, 32);
3635
0
            memcpy(k2, key->data + 32, 32);
3636
0
        }else{
3637
0
            memset(k1, 0, 32);
3638
0
            memset(k2, 0, 32);
3639
0
        }
3640
3641
0
        ssh_debug_printf("ssh: cipher is chacha20\n");
3642
0
        ssh_print_data("key 1", k1, 32);
3643
0
        ssh_print_data("key 2", k2, 32);
3644
3645
0
        if ((err = gcry_cipher_setkey(*hd1, k1, 32))) {
3646
0
            gcry_cipher_close(*hd1);
3647
0
            ws_debug("ssh: can't set chacha20 cipher key %s", gcry_strerror(err));
3648
0
            return;
3649
0
        }
3650
3651
0
        if ((err = gcry_cipher_setkey(*hd2, k2, 32))) {
3652
0
            gcry_cipher_close(*hd1);
3653
0
            gcry_cipher_close(*hd2);
3654
0
            ws_debug("ssh: can't set chacha20 cipher key %s", gcry_strerror(err));
3655
0
            return;
3656
0
        }
3657
3658
0
        wmem_register_callback(wmem_file_scope(), gcry_cipher_destroy_cb, *hd1);
3659
0
        wmem_register_callback(wmem_file_scope(), gcry_cipher_destroy_cb, *hd2);
3660
3661
0
    } else if (CIPHER_AES128_CBC == peer_data->cipher_id  || CIPHER_AES192_CBC == peer_data->cipher_id || CIPHER_AES256_CBC == peer_data->cipher_id) {
3662
0
        int iKeyLen = CIPHER_AES128_CBC == peer_data->cipher_id?16:CIPHER_AES192_CBC == peer_data->cipher_id?24:32;
3663
0
        if (gcry_cipher_open(hd1, CIPHER_AES128_CBC == peer_data->cipher_id?GCRY_CIPHER_AES128:CIPHER_AES192_CBC == peer_data->cipher_id?GCRY_CIPHER_AES192:GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC, 0)) {
3664
0
            gcry_cipher_close(*hd1);
3665
0
            ws_debug("ssh: can't open aes%d cipher handle", iKeyLen*8);
3666
0
            return;
3667
0
        }
3668
0
        uint8_t k1[32], iv1[16];
3669
0
        if(key->data){
3670
0
            memcpy(k1, key->data, iKeyLen);
3671
0
        }else{
3672
0
            memset(k1, 0, iKeyLen);
3673
0
        }
3674
0
        if(iv->data){
3675
0
            memcpy(iv1, iv->data, 16);
3676
0
        }else{
3677
0
            memset(iv1, 0, 16);
3678
0
        }
3679
3680
0
        ssh_debug_printf("ssh: cipher is aes%d-cbc\n", iKeyLen*8);
3681
0
        ssh_print_data("key", k1, iKeyLen);
3682
0
        ssh_print_data("iv", iv1, 16);
3683
3684
0
        if ((err = gcry_cipher_setkey(*hd1, k1, iKeyLen))) {
3685
0
            gcry_cipher_close(*hd1);
3686
0
            ws_debug("ssh: can't set aes%d cipher key", iKeyLen*8);
3687
0
            ws_debug("libgcrypt: %d %s %s", gcry_err_code(err), gcry_strsource(err), gcry_strerror(err));
3688
0
            return;
3689
0
        }
3690
3691
0
        if ((err = gcry_cipher_setiv(*hd1, iv1, 16))) {
3692
0
            gcry_cipher_close(*hd1);
3693
0
            ws_debug("ssh: can't set aes%d cipher iv", iKeyLen*8);
3694
0
            ws_debug("libgcrypt: %d %s %s", gcry_err_code(err), gcry_strsource(err), gcry_strerror(err));
3695
0
            return;
3696
0
        }
3697
3698
0
        wmem_register_callback(wmem_file_scope(), gcry_cipher_destroy_cb, *hd1);
3699
3700
0
    } else if (CIPHER_AES128_CTR == peer_data->cipher_id  || CIPHER_AES192_CTR == peer_data->cipher_id || CIPHER_AES256_CTR == peer_data->cipher_id) {
3701
0
        int iKeyLen = CIPHER_AES128_CTR == peer_data->cipher_id?16:CIPHER_AES192_CTR == peer_data->cipher_id?24:32;
3702
0
        if (gcry_cipher_open(hd1, CIPHER_AES128_CTR == peer_data->cipher_id?GCRY_CIPHER_AES128:CIPHER_AES192_CTR == peer_data->cipher_id?GCRY_CIPHER_AES192:GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CTR, 0)) {
3703
0
            gcry_cipher_close(*hd1);
3704
0
            ws_debug("ssh: can't open aes%d cipher handle", iKeyLen*8);
3705
0
            return;
3706
0
        }
3707
0
        uint8_t k1[32], iv1[16];
3708
0
        if(key->data){
3709
0
            memcpy(k1, key->data, iKeyLen);
3710
0
        }else{
3711
0
            memset(k1, 0, iKeyLen);
3712
0
        }
3713
0
        if(iv->data){
3714
0
            memcpy(iv1, iv->data, 16);
3715
0
        }else{
3716
0
            memset(iv1, 0, 16);
3717
0
        }
3718
3719
0
        ssh_debug_printf("ssh: cipher is aes%d-ctr\n", iKeyLen*8);
3720
0
        ssh_print_data("key", k1, iKeyLen);
3721
0
        ssh_print_data("iv", iv1, 16);
3722
3723
0
        if ((err = gcry_cipher_setkey(*hd1, k1, iKeyLen))) {
3724
0
            gcry_cipher_close(*hd1);
3725
0
            ws_debug("ssh: can't set aes%d cipher key", iKeyLen*8);
3726
0
            ws_debug("libgcrypt: %d %s %s", gcry_err_code(err), gcry_strsource(err), gcry_strerror(err));
3727
0
            return;
3728
0
        }
3729
3730
0
        if ((err = gcry_cipher_setctr(*hd1, iv1, 16))) {
3731
0
            gcry_cipher_close(*hd1);
3732
0
            ws_debug("ssh: can't set aes%d cipher iv", iKeyLen*8);
3733
0
            ws_debug("libgcrypt: %d %s %s", gcry_err_code(err), gcry_strsource(err), gcry_strerror(err));
3734
0
            return;
3735
0
        }
3736
3737
0
        wmem_register_callback(wmem_file_scope(), gcry_cipher_destroy_cb, *hd1);
3738
3739
0
    } else if (CIPHER_AES128_GCM == peer_data->cipher_id  || CIPHER_AES256_GCM == peer_data->cipher_id) {
3740
0
        int iKeyLen = CIPHER_AES128_GCM == peer_data->cipher_id?16:32;
3741
0
        if (gcry_cipher_open(hd1, CIPHER_AES128_GCM == peer_data->cipher_id?GCRY_CIPHER_AES128:GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_GCM, 0)) {
3742
0
            gcry_cipher_close(*hd1);
3743
0
            ws_debug("ssh: can't open aes%d cipher handle", iKeyLen*8);
3744
0
            return;
3745
0
        }
3746
3747
0
        uint8_t k1[32], iv2[12];
3748
0
        if(key->data){
3749
0
            memcpy(k1, key->data, iKeyLen);
3750
0
        }else{
3751
0
            memset(k1, 0, iKeyLen);
3752
0
        }
3753
0
        if(iv->data){
3754
0
            memcpy(peer_data->iv, iv->data, 12);
3755
0
        }else{
3756
0
            memset(iv2, 0, 12);
3757
0
        }
3758
3759
0
        ssh_debug_printf("ssh: cipher is aes%d-gcm\n", iKeyLen*8);
3760
0
        ssh_print_data("key", k1, iKeyLen);
3761
0
        ssh_print_data("iv", peer_data->iv, 12);
3762
3763
0
        if ((err = gcry_cipher_setkey(*hd1, k1, iKeyLen))) {
3764
0
            gcry_cipher_close(*hd1);
3765
0
            ws_debug("ssh: can't set aes%d cipher key", iKeyLen*8);
3766
0
            ws_debug("libgcrypt: %d %s %s", gcry_err_code(err), gcry_strsource(err), gcry_strerror(err));
3767
0
            return;
3768
0
        }
3769
3770
0
        wmem_register_callback(wmem_file_scope(), gcry_cipher_destroy_cb, *hd1);
3771
3772
0
    } else {
3773
0
        ssh_debug_printf("ssh: cipher (%d) is unknown or not set\n", peer_data->cipher_id);
3774
0
    }
3775
0
}
3776
3777
static void
3778
ssh_decryption_setup_mac(struct ssh_peer_data *peer_data,
3779
        ssh_bignum *iv)
3780
0
{
3781
0
    if(peer_data->mac_id == CIPHER_MAC_SHA2_256){
3782
0
        if(iv->data){
3783
0
            memcpy(peer_data->hmac_iv, iv->data, 32);
3784
0
        }else{
3785
0
            memset(peer_data->hmac_iv, 0, 32);
3786
0
        }
3787
0
        peer_data->hmac_iv_len = 32;
3788
0
        ssh_debug_printf("ssh: mac is hmac-sha2-256\n");
3789
0
        ssh_print_data("iv", peer_data->hmac_iv, peer_data->hmac_iv_len);
3790
0
    }else{
3791
0
        ws_debug("ssh: unsupported MAC");
3792
0
    }
3793
0
}
3794
3795
/* libgcrypt wrappers for HMAC/message digest operations {{{ */
3796
/* hmac abstraction layer */
3797
0
#define SSH_HMAC gcry_md_hd_t
3798
3799
static inline int
3800
ssh_hmac_init(SSH_HMAC* md, const void * key, int len, int algo)
3801
0
{
3802
0
    gcry_error_t  err;
3803
0
    const char   *err_str, *err_src;
3804
3805
0
    err = gcry_md_open(md,algo, GCRY_MD_FLAG_HMAC);
3806
0
    if (err != 0) {
3807
0
        err_str = gcry_strerror(err);
3808
0
        err_src = gcry_strsource(err);
3809
0
        ssh_debug_printf("ssh_hmac_init(): gcry_md_open failed %s/%s", err_str, err_src);
3810
0
        return -1;
3811
0
    }
3812
0
    err = gcry_md_setkey(*(md), key, len);
3813
0
    if (err != 0) {
3814
0
        err_str = gcry_strerror(err);
3815
0
        err_src = gcry_strsource(err);
3816
0
        ssh_debug_printf("ssh_hmac_init(): gcry_md_setkey(..., ..., %d) failed %s/%s", len, err_str, err_src);
3817
0
        return -1;
3818
0
    }
3819
0
    return 0;
3820
0
}
3821
3822
static inline void
3823
ssh_hmac_update(SSH_HMAC* md, const void* data, int len)
3824
0
{
3825
0
    gcry_md_write(*(md), data, len);
3826
0
}
3827
3828
static inline void
3829
ssh_hmac_final(SSH_HMAC* md, unsigned char* data, unsigned* datalen)
3830
0
{
3831
0
    int   algo;
3832
0
    unsigned len;
3833
3834
0
    algo = gcry_md_get_algo (*(md));
3835
0
    len  = gcry_md_get_algo_dlen(algo);
3836
0
    DISSECTOR_ASSERT(len <= *datalen);
3837
0
    memcpy(data, gcry_md_read(*(md), algo), len);
3838
0
    *datalen = len;
3839
0
}
3840
3841
static inline void
3842
ssh_hmac_cleanup(SSH_HMAC* md)
3843
0
{
3844
0
    gcry_md_close(*(md));
3845
0
}
3846
/* libgcrypt wrappers for HMAC/message digest operations }}} */
3847
3848
/* Decryption integrity check {{{ */
3849
3850
static int
3851
ssh_get_digest_by_id(unsigned mac_id)
3852
0
{
3853
0
    if(mac_id==CIPHER_MAC_SHA2_256){
3854
0
        return GCRY_MD_SHA256;
3855
0
    }
3856
0
    return -1;
3857
0
}
3858
3859
static void
3860
ssh_calc_mac(struct ssh_peer_data *peer_data, uint32_t seqnr, uint8_t* data, uint32_t datalen, uint8_t* calc_mac)
3861
0
{
3862
0
    SSH_HMAC hm;
3863
0
    int      md;
3864
0
    uint32_t len;
3865
0
    uint8_t  buf[DIGEST_MAX_SIZE];
3866
3867
0
    md=ssh_get_digest_by_id(peer_data->mac_id);
3868
//    ssl_debug_printf("ssh_check_mac mac type:%s md %d\n",
3869
//        ssl_cipher_suite_dig(decoder->cipher_suite)->name, md);
3870
3871
0
    memset(calc_mac, 0, DIGEST_MAX_SIZE);
3872
3873
0
    if (md == -1) {
3874
0
        return;
3875
0
    }
3876
0
    if (ssh_hmac_init(&hm, peer_data->hmac_iv, peer_data->hmac_iv_len, md) != 0)
3877
0
        return;
3878
3879
    /* hash sequence number */
3880
0
    phtonu32(buf, seqnr);
3881
3882
0
    ssh_print_data("Mac IV", peer_data->hmac_iv, peer_data->hmac_iv_len);
3883
0
    ssh_print_data("Mac seq", buf, 4);
3884
0
    ssh_print_data("Mac data", data, datalen);
3885
3886
0
    ssh_hmac_update(&hm,buf,4);
3887
3888
0
    ssh_hmac_update(&hm,data,datalen);
3889
3890
    /* get digest and digest len*/
3891
0
    len = sizeof(buf);
3892
0
    ssh_hmac_final(&hm,buf,&len);
3893
0
    ssh_hmac_cleanup(&hm);
3894
0
    ssh_print_data("Mac", buf, len);
3895
0
    memcpy(calc_mac, buf, len);
3896
3897
0
    return;
3898
0
}
3899
/* Decryption integrity check }}} */
3900
3901
static ssh_packet_info_t *
3902
ssh_get_packet_info(packet_info *pinfo, bool is_response)
3903
0
{
3904
0
    ssh_packet_info_t *packet = (ssh_packet_info_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ssh, 0);
3905
0
    if(!packet){
3906
0
        packet = wmem_new0(wmem_file_scope(), ssh_packet_info_t);
3907
0
        packet->from_server = is_response;
3908
0
        packet->messages = NULL;
3909
0
        p_add_proto_data(wmem_file_scope(), pinfo, proto_ssh, 0, packet);
3910
0
    }
3911
0
    return packet;
3912
0
}
3913
3914
static unsigned
3915
ssh_decrypt_packet(tvbuff_t *tvb, packet_info *pinfo,
3916
        struct ssh_peer_data *peer_data, int offset)
3917
0
{
3918
0
    bool is_response = ssh_peer_data_from_server(peer_data);
3919
3920
0
    gcry_error_t err;
3921
0
    unsigned message_length = 0, seqnr;
3922
0
    uint8_t *plain = NULL;
3923
0
    const uint8_t *mac;
3924
0
    unsigned mac_len, data_len = 0;
3925
0
    uint8_t calc_mac[DIGEST_MAX_SIZE];
3926
0
    memset(calc_mac, 0, DIGEST_MAX_SIZE);
3927
0
    unsigned remaining = tvb_captured_length_remaining(tvb, offset);
3928
3929
0
    mac_len = peer_data->mac_length > 0 ? peer_data->mac_length : 0;
3930
0
    seqnr = peer_data->sequence_number;
3931
3932
    /* General algorithm:
3933
     * 1. If there are not enough bytes for the packet_length, and we can
3934
     * do reassembly, ask for one more segment.
3935
     * 2. Retrieve packet_length (encrypted in some modes).
3936
     * 3. Sanity check packet_length (the field is 4 bytes, but packet_length
3937
     * is unlikely to be much larger than 32768, which provides good indication
3938
     * a packet is continuation data or, in some modes, failed decryption.
3939
     * https://www.rfc-editor.org/rfc/rfc4253.html#section-6.1 )
3940
     * 4. If there are not enough bytes for packet_length, and we can do
3941
     * reassembly, tell the TCP dissector how many more bytes we need.
3942
     * 5. If the packet is truncated and we cannot reassemble, at this
3943
     * point we conclude that it is the next SSH packet, and advance the
3944
     * sequence number, invocation_counter, etc. before throwing an exception.
3945
     * 6. If we do have all the data, we decrypt and check the MAC before
3946
     * doing all that. (XXX - Advancing seqnr regardless could make sense
3947
     * in some ciphers.)
3948
     * 7. Possibly the MAC should be checked before decryption in some ciphers
3949
     * if we have all the data; possibly there should be a "do not check the
3950
     * MAC" preference a la TLS.
3951
     */
3952
3953
0
    if (GCRY_CIPHER_CHACHA20 == peer_data->cipher_id) {
3954
0
        if (ssh_desegment && pinfo->can_desegment && remaining < 4) {
3955
            /* Can do reassembly, and the packet length is split across
3956
             * segment boundaries. */
3957
0
            pinfo->desegment_offset = offset;
3958
0
            pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
3959
0
            return tvb_captured_length(tvb);
3960
0
        }
3961
3962
0
        const uint8_t *ctext = tvb_get_ptr(tvb, offset, 4);
3963
0
        uint8_t plain_length_buf[4];
3964
3965
0
        if (!ssh_decrypt_chacha20(peer_data->cipher_2, seqnr, 0, ctext, 4,
3966
0
                    plain_length_buf, 4)) {
3967
0
            ws_debug("ERROR: could not decrypt packet len");
3968
0
            return tvb_captured_length(tvb);
3969
0
        }
3970
3971
0
        message_length = pntohu32(plain_length_buf);
3972
3973
0
        ssh_debug_printf("chachapoly_crypt seqnr=%d [%u]\n", seqnr, message_length);
3974
3975
0
        ssh_debug_printf("%s plain for seq = %d len = %u\n", is_response?"s2c":"c2s", seqnr, message_length);
3976
0
        if (message_length > SSH_MAX_PACKET_LEN) {
3977
0
            ws_debug("ssh: unreasonable message length %u", message_length);
3978
0
            return tvb_captured_length(tvb);
3979
0
        }
3980
0
        if (remaining < message_length + 4 + mac_len) {
3981
            // Need desegmentation; as "the chacha20-poly1305@openssh.com AEAD
3982
            // uses the sequence number as an initialisation vector (IV) to
3983
            // generate its per-packet MAC key and is otherwise stateless
3984
            // between packets," we need no special handling here.
3985
            // https://www.ietf.org/id/draft-miller-sshm-strict-kex-01.html
3986
            //
3987
0
            if (ssh_desegment && pinfo->can_desegment) {
3988
0
                pinfo->desegment_offset = offset;
3989
0
                pinfo->desegment_len = message_length + 4 + mac_len - remaining;
3990
0
                return tvb_captured_length(tvb);
3991
0
            }
3992
            // If we can't desegment, we will have an exception below in
3993
            // the tvb_get_ptr. Advance the sequence number so that the
3994
            // next SSH packet start will decrypt correctly.
3995
0
            peer_data->sequence_number++;
3996
0
        }
3997
3998
0
        plain = (uint8_t *)wmem_alloc0(pinfo->pool, message_length+4);
3999
0
        memcpy(plain, plain_length_buf, 4);
4000
0
        const uint8_t *ctext2 = tvb_get_ptr(tvb, offset+4, message_length);
4001
4002
        /* XXX - "Once the entire packet has been received, the MAC MUST be
4003
         * checked before decryption," but we decrypt first.
4004
         * https://datatracker.ietf.org/doc/html/draft-ietf-sshm-chacha20-poly1305-01
4005
         */
4006
0
        if (!ssh_decrypt_chacha20(peer_data->cipher, seqnr, 1, ctext2,
4007
0
                    message_length, plain+4, message_length)) {
4008
0
            ws_debug("ERROR: could not decrypt packet payload");
4009
0
            return tvb_captured_length(tvb);
4010
0
        }
4011
4012
0
        mac = tvb_get_ptr(tvb, offset + 4 + message_length, mac_len);
4013
0
        uint8_t poly_key[32], iv[16];
4014
4015
0
        memset(poly_key, 0, 32);
4016
0
        memset(iv, 0, 8);
4017
0
        phtonu64(iv+8, (uint64_t)seqnr);
4018
0
        gcry_cipher_setiv(peer_data->cipher, iv, mac_len);
4019
0
        gcry_cipher_encrypt(peer_data->cipher, poly_key, 32, poly_key, 32);
4020
4021
0
        gcry_mac_hd_t mac_hd;
4022
0
        gcry_mac_open(&mac_hd, GCRY_MAC_POLY1305, 0, NULL);
4023
0
        gcry_mac_setkey(mac_hd, poly_key, 32);
4024
0
        gcry_mac_write(mac_hd, ctext, 4);
4025
0
        gcry_mac_write(mac_hd, ctext2, message_length);
4026
0
        if (gcry_mac_verify(mac_hd, mac, mac_len)) {
4027
0
            ws_debug("ssh: MAC does not match");
4028
0
        }
4029
0
        size_t buflen = DIGEST_MAX_SIZE;
4030
0
        gcry_mac_read(mac_hd, calc_mac, &buflen);
4031
0
        gcry_mac_close(mac_hd);
4032
4033
0
        data_len   = message_length + 4;
4034
4035
0
        ssh_debug_printf("%s plain text seq=%d", is_response?"s2c":"c2s",seqnr);
4036
0
        ssh_print_data("", plain, message_length+4);
4037
0
    } else if (CIPHER_AES128_GCM == peer_data->cipher_id || CIPHER_AES256_GCM == peer_data->cipher_id) {
4038
4039
        /* AES GCM for Secure Shell [RFC 5647] */
4040
        /* The message length is Additional Authenticated Data */
4041
0
        if (ssh_desegment && pinfo->can_desegment && remaining < 4) {
4042
            /* Can do reassembly, and the packet length is split across
4043
             * segment boundaries. */
4044
0
            pinfo->desegment_offset = offset;
4045
0
            pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
4046
0
            return tvb_captured_length(tvb);
4047
0
        }
4048
0
        message_length = tvb_get_uint32(tvb, offset, ENC_BIG_ENDIAN);
4049
0
        ssh_debug_printf("length: %d, remaining: %d\n", message_length, remaining);
4050
        /* The minimum size of a packet (not counting mac) is 16. */
4051
0
        if (message_length > SSH_MAX_PACKET_LEN || message_length < 16) {
4052
0
            ws_debug("ssh: unreasonable message length %u", message_length);
4053
0
            return tvb_captured_length(tvb);
4054
0
        }
4055
4056
        /* SSH requires that the data to be encrypted (not including the AAD,
4057
         * so message_length) be a multiple of the block size, 16 octets */
4058
0
        if (message_length % 16 != 0) {
4059
0
            ssh_debug_printf("length not a multiple of block length (16)!\n");
4060
0
        }
4061
4062
0
        if (message_length + 4 + mac_len > remaining) {
4063
            // Need desegmentation; as the message length was unencrypted
4064
            // AAD, we need no special handling here.
4065
0
            if (pinfo->can_desegment) {
4066
0
                pinfo->desegment_offset = offset;
4067
0
                pinfo->desegment_len = message_length + 4 + mac_len - remaining;
4068
0
                return tvb_captured_length(tvb);
4069
0
            }
4070
            // If we can't desegment, we will have an exception below in
4071
            // the tvb_get_ptr. Advance the sequence number (less crucial
4072
            // than with ChaCha20, as it's not an input.)
4073
0
            peer_data->sequence_number++;
4074
0
        }
4075
4076
        /* Set the IV and increment the invocation_counter for the next
4077
         * packet. Do this before retrieving the ciphertext with tvb_get_ptr
4078
         * in case this packet is truncated.
4079
         */
4080
0
        if ((err = gcry_cipher_setiv(peer_data->cipher, peer_data->iv, 12))) {
4081
            //gcry_cipher_close(peer_data->cipher);
4082
            //Don't close this unless we also remove the wmem callback
4083
// TODO: temporary work-around as long as a Windows python bug is triggered by automated tests
4084
0
#ifndef _WIN32
4085
0
            ws_debug("ssh: can't set aes128 cipher iv");
4086
0
            ws_debug("libgcrypt: %d %s %s", gcry_err_code(err), gcry_strsource(err), gcry_strerror(err));
4087
0
#endif        //ndef _WIN32
4088
0
            return tvb_captured_length(tvb);
4089
0
        }
4090
        // Increment invocation_counter for next packet
4091
0
        int idx = 12;
4092
0
        do{
4093
0
            idx -= 1;
4094
0
            peer_data->iv[idx] += 1;
4095
0
        }while(idx>4 && peer_data->iv[idx]==0);
4096
4097
0
        const char *ctext = (const char *)tvb_get_ptr(tvb, offset + 4,
4098
0
                message_length);
4099
0
        plain = (uint8_t *)wmem_alloc(pinfo->pool, message_length+4);
4100
0
        phtonu32(plain, message_length);
4101
4102
0
        if ((err = gcry_cipher_authenticate(peer_data->cipher, plain, 4))) {
4103
// TODO: temporary work-around as long as a Windows python bug is triggered by automated tests
4104
0
#ifndef _WIN32
4105
0
            ws_debug("can't authenticate using aes128-gcm: %s\n", gpg_strerror(err));
4106
0
#endif        //ndef _WIN32
4107
0
            return tvb_captured_length(tvb);
4108
0
        }
4109
4110
0
        if ((err = gcry_cipher_decrypt(peer_data->cipher, plain+4, message_length,
4111
0
                ctext, message_length))) {
4112
// TODO: temporary work-around as long as a Windows python bug is triggered by automated tests
4113
0
#ifndef _WIN32
4114
0
            ws_debug("can't decrypt aes-gcm %d %s %s", gcry_err_code(err), gcry_strsource(err), gcry_strerror(err));
4115
4116
0
#endif        //ndef _WIN32
4117
0
            return tvb_captured_length(tvb);
4118
0
        }
4119
4120
0
        if (gcry_cipher_gettag (peer_data->cipher, calc_mac, 16)) {
4121
// TODO: temporary work-around as long as a Windows python bug is triggered by automated tests
4122
0
#ifndef _WIN32
4123
0
            ws_debug ("aes128-gcm, gcry_cipher_gettag() failed\n");
4124
0
#endif        //ndef _WIN32
4125
0
            return tvb_captured_length(tvb);
4126
0
        }
4127
4128
0
        if ((err = gcry_cipher_reset(peer_data->cipher))) {
4129
// TODO: temporary work-around as long as a Windows python bug is triggered by automated tests
4130
0
#ifndef _WIN32
4131
0
            ws_debug("aes-gcm, gcry_cipher_reset failed: %s\n", gpg_strerror (err));
4132
0
#endif        //ndef _WIN32
4133
0
            return tvb_captured_length(tvb);
4134
0
        }
4135
4136
0
        data_len   = message_length + 4;
4137
4138
0
        ssh_debug_printf("%s plain text seq=%d", is_response?"s2c":"c2s",seqnr);
4139
0
        ssh_print_data("", plain, message_length+4);
4140
4141
0
    } else if (CIPHER_AES128_CBC == peer_data->cipher_id || CIPHER_AES128_CTR == peer_data->cipher_id ||
4142
0
        CIPHER_AES192_CBC == peer_data->cipher_id || CIPHER_AES192_CTR == peer_data->cipher_id ||
4143
0
        CIPHER_AES256_CBC == peer_data->cipher_id || CIPHER_AES256_CTR == peer_data->cipher_id) {
4144
4145
0
        ws_noisy("Getting raw bytes of length %d", tvb_reported_length_remaining(tvb, offset));
4146
        /* In CBC and CTR mode, the message length is encrypted as well.
4147
         * We need to decrypt one block, 16 octets, to get the length.
4148
         */
4149
0
        if (ssh_desegment && pinfo->can_desegment && remaining < 16) {
4150
            /* Can do reassembly, and the packet length is split across
4151
             * segment boundaries. */
4152
0
            pinfo->desegment_offset = offset;
4153
0
            pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
4154
0
            return tvb_captured_length(tvb);
4155
0
        }
4156
        /* Do we already have the first block decrypted from when the packet
4157
         * was too large and segmented?
4158
         */
4159
0
        if (!peer_data->plain0_valid) {
4160
0
            const char *cypher_buf0 = (const char *)tvb_get_ptr(tvb, offset, 16);
4161
4162
0
            if (gcry_cipher_decrypt(peer_data->cipher, peer_data->plain0, 16, cypher_buf0, 16))
4163
0
            {
4164
0
                ws_debug("can\'t decrypt aes128");
4165
0
                return tvb_captured_length(tvb);
4166
0
            }
4167
0
        }
4168
4169
0
        message_length = pntohu32(peer_data->plain0);
4170
4171
        /* The message_length value doesn't include the length of the
4172
         * message_length field itself, so it must be at least 12 bytes.
4173
         */
4174
0
        if (message_length > SSH_MAX_PACKET_LEN || message_length < 12){
4175
0
            ws_debug("ssh: unreasonable message length %u", message_length);
4176
0
            return tvb_captured_length(tvb);
4177
0
        }
4178
4179
        /* SSH requires that the data to be encrypted (message_length+4)
4180
         * be a multiple of the block size, 16 octets. */
4181
0
        if (message_length % 16 != 12) {
4182
0
            ssh_debug_printf("total length not a multiple of block length (16)!\n");
4183
0
        }
4184
0
        if (remaining < message_length + 4 + mac_len) {
4185
            /* Need desegmentation
4186
             *
4187
             * We will be handed the full encrypted packet again. We can either
4188
             * store the decrypted first block, or will need to reset the CTR
4189
             * or IV appropriately before decrypting the first block again.
4190
             * libgcrypt does not provide an easy way to get the current value
4191
             * of the CTR or (or IV/last block for CBC), so we just store the
4192
             * decrypted first block.
4193
             */
4194
0
            if (ssh_desegment && pinfo->can_desegment) {
4195
0
                ws_noisy("  need_desegmentation: offset = %d, reported_length_remaining = %d\n",
4196
0
                                offset, tvb_reported_length_remaining(tvb, offset));
4197
0
                peer_data->plain0_valid = true;
4198
0
                pinfo->desegment_offset = offset;
4199
0
                pinfo->desegment_len = message_length + 4 + mac_len - remaining;
4200
0
                return tvb_captured_length(tvb);
4201
0
            } else {
4202
                // If we can't desegment, we will have an exception below in
4203
                // the tvb_get_ptr. Advance the sequence number so that the
4204
                // the hash will work for the next packet.
4205
                //
4206
                // XXX - In CTR mode, we should advance the CTR based on the
4207
                // known length so we can dissect the next block. We would
4208
                // also need to reset the CTR after failing to dissect a
4209
                // packet_length on the continuation data that comes next.
4210
0
                peer_data->sequence_number++;
4211
0
            }
4212
0
        }
4213
0
        peer_data->plain0_valid = false;
4214
0
        plain = (uint8_t *)wmem_alloc(pinfo->pool, message_length+4);
4215
0
        memcpy(plain, peer_data->plain0, 16);
4216
4217
0
        if (message_length > 12) {
4218
            /* All of these functions actually do handle the case where
4219
             * there is no data left, so the check is unnecessary.
4220
             */
4221
0
            char *ct = (char *)tvb_get_ptr(tvb, offset + 16, message_length - 12);
4222
0
            if ((err = gcry_cipher_decrypt(peer_data->cipher, plain + 16, message_length - 12, ct, message_length - 12)))
4223
0
            {
4224
0
                ws_debug("can't decrypt aes-cbc/ctr %d %s %s", gcry_err_code(err), gcry_strsource(err), gcry_strerror(err));
4225
0
                return tvb_captured_length(tvb);
4226
0
            }
4227
0
        }
4228
4229
0
        ssh_debug_printf("%s plain text seq=%d", is_response?"s2c":"c2s",seqnr);
4230
0
        ssh_print_data("", plain, message_length+4);
4231
4232
0
        data_len   = message_length + 4;
4233
4234
        // XXX - In -etm modes, should calculate MAC based on ciphertext.
4235
0
        ssh_calc_mac(peer_data, seqnr, plain, data_len, calc_mac);
4236
0
    } else if (CIPHER_NULL == peer_data->cipher_id) {
4237
0
        if (ssh_desegment && pinfo->can_desegment && remaining < 4) {
4238
            /* Can do reassembly, and the packet length is split across
4239
             * segment boundaries. */
4240
0
            pinfo->desegment_offset = offset;
4241
0
            pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
4242
0
            return tvb_captured_length(tvb);
4243
0
        }
4244
0
        message_length = tvb_get_uint32(tvb, offset, ENC_BIG_ENDIAN);
4245
0
        ssh_debug_printf("length: %d, remaining: %d\n", message_length, remaining);
4246
0
        if (message_length > SSH_MAX_PACKET_LEN || message_length < 8) {
4247
0
            ws_debug("ssh: unreasonable message length %u", message_length);
4248
0
            return tvb_captured_length(tvb);
4249
0
        }
4250
4251
0
        if (message_length + 4 + mac_len > remaining) {
4252
            // Need desegmentation; as the message length was unencrypted
4253
            // AAD, we need no special handling here.
4254
0
            if (pinfo->can_desegment) {
4255
0
                pinfo->desegment_offset = offset;
4256
0
                pinfo->desegment_len = message_length + 4 + mac_len - remaining;
4257
0
                return tvb_captured_length(tvb);
4258
0
            }
4259
            // If we can't desegment, we will have an exception below in
4260
            // the tvb_memdup. Advance the sequence number (not crucial).
4261
0
            peer_data->sequence_number++;
4262
0
        }
4263
0
        data_len = message_length + 4;
4264
0
        plain = tvb_memdup(pinfo->pool, tvb, offset, data_len);
4265
4266
        // XXX - In -etm modes, should calculate MAC based on ciphertext.
4267
0
        ssh_calc_mac(peer_data, seqnr, plain, data_len, calc_mac);
4268
0
    }
4269
4270
0
    if (mac_len && data_len) {
4271
0
        if (mac_len <= DIGEST_MAX_SIZE && !memcmp(tvb_get_ptr(tvb, offset + data_len, mac_len), calc_mac, mac_len)){
4272
0
            ws_noisy("MAC OK");
4273
0
        }else{
4274
0
            ws_debug("MAC ERR");
4275
            /* Bad MAC, just show the packet as encrypted. We can get
4276
             * this for a known encryption type with no keys currently. */
4277
0
            if (!ssh_ignore_mac_failed) {
4278
0
                return tvb_captured_length(tvb);
4279
0
            }
4280
0
        }
4281
0
    }
4282
4283
0
    if(plain){
4284
        // Save message
4285
4286
0
        ssh_packet_info_t *packet = ssh_get_packet_info(pinfo, is_response);
4287
4288
0
        int record_id = tvb_raw_offset(tvb)+offset;
4289
0
        ssh_message_info_t *message;
4290
4291
0
        message = wmem_new(wmem_file_scope(), ssh_message_info_t);
4292
0
        message->sequence_number = peer_data->sequence_number++;
4293
0
        message->plain_data = wmem_memdup(wmem_file_scope(), plain, data_len);
4294
0
        message->data_len = data_len;
4295
0
        message->id = record_id;
4296
0
        message->next = NULL;
4297
0
        memcpy(message->calc_mac, calc_mac, DIGEST_MAX_SIZE);
4298
0
        ssh_debug_printf("%s->sequence_number++ > %d\n", is_response?"server":"client", peer_data->sequence_number);
4299
4300
0
        ssh_message_info_t **pmessage = &packet->messages;
4301
0
        while(*pmessage){
4302
0
            pmessage = &(*pmessage)->next;
4303
0
        }
4304
0
        *pmessage = message;
4305
0
    }
4306
4307
0
    offset += message_length + mac_len + 4;
4308
0
    return offset;
4309
0
}
4310
4311
static bool
4312
ssh_decrypt_chacha20(gcry_cipher_hd_t hd,
4313
        uint32_t seqnr, uint32_t counter, const unsigned char *ctext, unsigned ctext_len,
4314
        unsigned char *plain, unsigned plain_len)
4315
0
{
4316
0
    unsigned char seq[8];
4317
0
    unsigned char iv[16];
4318
4319
0
    phtonu64(seq, (uint64_t)seqnr);
4320
4321
    // chacha20 uses a different cipher handle for the packet payload & length
4322
    // the payload uses a block counter
4323
0
    if (counter) {
4324
0
        unsigned char ctr[8] = {1,0,0,0,0,0,0,0};
4325
0
        memcpy(iv, ctr, 8);
4326
0
        memcpy(iv+8, seq, 8);
4327
0
    }
4328
4329
0
    return ((!counter && gcry_cipher_setiv(hd, seq, 8) == 0) ||
4330
0
            (counter && gcry_cipher_setiv(hd, iv, 16) == 0)) &&
4331
0
            gcry_cipher_decrypt(hd, plain, plain_len, ctext, ctext_len) == 0;
4332
0
}
4333
4334
static int
4335
ssh_dissect_decrypted_packet(tvbuff_t *tvb, packet_info *pinfo,
4336
        struct ssh_peer_data *peer_data, proto_tree *tree,
4337
        ssh_message_info_t *message)
4338
0
{
4339
0
    int offset = 0;      // TODO:
4340
0
    int dissected_len = 0;
4341
0
    tvbuff_t* payload_tvb;
4342
4343
0
    const uint8_t* plaintext = message->plain_data;
4344
0
    unsigned plaintext_len = message->data_len;
4345
4346
0
    col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Encrypted packet (plaintext_len=%d)", plaintext_len);
4347
4348
0
    tvbuff_t *packet_tvb = tvb_new_child_real_data(tvb, plaintext, plaintext_len, plaintext_len);
4349
0
    add_new_data_source(pinfo, packet_tvb, "Decrypted Packet");
4350
4351
0
    unsigned   plen;
4352
0
    uint32_t   padding_length;
4353
0
    unsigned   remain_length;
4354
0
    unsigned   msg_code;
4355
4356
0
    proto_item *ti, *padding_ti;
4357
0
    proto_item *msg_type_tree = NULL;
4358
4359
    /*
4360
     * We use "tvb_ensure_captured_length_remaining()" to make sure there
4361
     * actually *is* data remaining.
4362
     *
4363
     * This means we're guaranteed that "remain_length" is positive.
4364
     */
4365
0
    remain_length = tvb_ensure_captured_length_remaining(packet_tvb, offset);
4366
    /*
4367
     * Can we do reassembly?
4368
     */
4369
0
    if (ssh_desegment && pinfo->can_desegment) {
4370
        /*
4371
         * Yes - would an SSH header starting at this offset
4372
         * be split across segment boundaries?
4373
         */
4374
0
        if (remain_length < 4) {
4375
            /*
4376
             * Yes.  Tell the TCP dissector where the data for
4377
             * this message starts in the data it handed us and
4378
             * that we need "some more data."  Don't tell it
4379
             * exactly how many bytes we need because if/when we
4380
             * ask for even more (after the header) that will
4381
             * break reassembly.
4382
             */
4383
0
            pinfo->desegment_offset = offset;
4384
0
            pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
4385
0
            return offset;
4386
0
        }
4387
0
    }
4388
    /* XXX - Defragmentation needs to be done in ssh_decrypt_packet, and the
4389
     * checks there should mean that the above never has an effect. (It's
4390
     * copied from ssh_dissect_key_exchange.)
4391
     */
4392
0
    plen = tvb_get_ntohl(packet_tvb, offset);
4393
4394
0
    if (ssh_desegment && pinfo->can_desegment) {
4395
0
        if (plen + 4 > remain_length) {
4396
0
            pinfo->desegment_offset = offset;
4397
0
            pinfo->desegment_len = plen+4 - remain_length;
4398
0
            return offset;
4399
0
        }
4400
0
    }
4401
    /*
4402
     * Need to check plen > 0x80000000 here
4403
     */
4404
4405
0
    ti = proto_tree_add_uint(tree, hf_ssh_packet_length, packet_tvb,
4406
0
                    offset, 4, plen);
4407
0
    if (plen < 8) {
4408
        /* RFC 4253 6: "[T]he length of the concatenation of 'packet_length',
4409
         * 'padding_length', 'payload', and 'random padding' MUST be a multiple
4410
         * of the cipher block size or 8, whichever is larger,... even when
4411
         * using stream ciphers."
4412
         *
4413
         * Modes that do not encrypt plen with the same key as the other three
4414
         * cannot follow this as written and delete 'packet_length' from the
4415
         * above sentence. As padding_length is one byte and random_padding at
4416
         * least four, packet_length must be at least 8 in all modes.
4417
         */
4418
0
        expert_add_info_format(pinfo, ti, &ei_ssh_packet_length, "Packet length is %d, MUST be at least 8", plen);
4419
0
    } else if (plen >= SSH_MAX_PACKET_LEN) {
4420
0
        expert_add_info_format(pinfo, ti, &ei_ssh_packet_length, "Overly large number %d", plen);
4421
0
        plen = remain_length-4;
4422
0
    }
4423
0
    offset+=4;
4424
4425
    /* padding length */
4426
0
    padding_ti = proto_tree_add_item_ret_uint(tree, hf_ssh_padding_length, packet_tvb, offset, 1, ENC_NA, &padding_length);
4427
    /* RFC 4253 6: "There MUST be at least four bytes of padding." */
4428
0
    if (padding_length < 4) {
4429
0
        expert_add_info_format(pinfo, padding_ti, &ei_ssh_padding_length, "Padding length is %d, MUST be at least 4", padding_length);
4430
0
    }
4431
0
    unsigned payload_length;
4432
0
    if (ckd_sub(&payload_length, plen, padding_length + 1)) {
4433
0
        expert_add_info_format(pinfo, padding_ti, &ei_ssh_padding_length, "Padding length is too large [%d], implies a negative payload length", padding_length);
4434
0
        payload_length = 0;
4435
0
    }
4436
0
    offset += 1;
4437
4438
    /* msg_code */
4439
0
    msg_code = tvb_get_uint8(packet_tvb, offset);
4440
    /* XXX - Payload compression could have been negotiated */
4441
0
    payload_tvb = tvb_new_subset_length(packet_tvb, offset, (int)payload_length);
4442
0
    bool is_response = ssh_peer_data_from_server(peer_data);
4443
4444
    /* Transport layer protocol */
4445
    /* Generic (1-19) */
4446
0
    if(msg_code >= 1 && msg_code <= 19) {
4447
0
        col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, val_to_str(pinfo->pool, msg_code, ssh2_msg_vals, "Unknown (%u)"));
4448
0
        msg_type_tree = proto_tree_add_subtree(tree, packet_tvb, offset, plen-1, ett_key_exchange, NULL, "Message: Transport (generic)");
4449
0
        proto_tree_add_item(msg_type_tree, hf_ssh2_msg_code, packet_tvb, offset, 1, ENC_BIG_ENDIAN);
4450
0
        dissected_len = ssh_dissect_transport_generic(payload_tvb, pinfo, 1, peer_data, msg_type_tree, msg_code);
4451
0
    }
4452
    /* Algorithm negotiation (20-29) */
4453
    /* Normally these messages are all dissected in ssh_dissect_key_exchange */
4454
0
    else if(msg_code >=20 && msg_code <= 29) {
4455
//TODO: See if the complete dissector should be refactored to always go through here first        offset = ssh_dissect_transport_algorithm_negotiation(packet_tvb, pinfo, global_data, offset, msg_type_tree, is_response, msg_code);
4456
4457
0
        col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, val_to_str(pinfo->pool, msg_code, ssh2_msg_vals, "Unknown (%u)"));
4458
0
        msg_type_tree = proto_tree_add_subtree(tree, packet_tvb, offset, plen-1, ett_key_exchange, NULL, "Message: Transport (algorithm negotiation)");
4459
0
        proto_tree_add_item(msg_type_tree, hf_ssh2_msg_code, packet_tvb, offset, 1, ENC_BIG_ENDIAN);
4460
0
        dissected_len = 1;
4461
4462
0
        ws_debug("SSH dissect: pass %u, frame %u, msg_code %u, do_decrypt=%d", pinfo->fd->visited, pinfo->fd->num, msg_code, peer_data->global_data->do_decrypt);
4463
0
        switch(msg_code)
4464
0
        {
4465
0
            case SSH_MSG_KEXINIT:
4466
0
            {
4467
0
                ws_debug("ssh: REKEY msg_code 20: storing frame %u number, offset %d" , pinfo->num, offset);
4468
0
                peer_data->rekey_trigger_frame = pinfo->num;
4469
                // Reset array while REKEY: sanitize server_key_exchange_init and force do_decrypt :
4470
0
                peer_data->global_data->kex_server_key_exchange_init = wmem_array_new(wmem_file_scope(), 1);
4471
0
                peer_data->global_data->do_decrypt      = true;
4472
0
                dissected_len = ssh_dissect_key_init(payload_tvb, pinfo, offset - 4, msg_type_tree, is_response, peer_data->global_data);
4473
0
            break;
4474
0
            }
4475
0
            case SSH_MSG_NEWKEYS:
4476
0
            {
4477
0
                if (peer_data->rekey_pending) {
4478
0
                    ws_debug("ssh: REKEY pending... NEWKEYS frame %u", pinfo->num);
4479
0
                    ws_debug("ssh: decrypting frame %u with key ID %u, seq=%u", pinfo->num, peer_data->cipher_id, peer_data->sequence_number);
4480
0
                    if (peer_data->global_data->ext_kex_strict) {
4481
0
                        peer_data->sequence_number = 0;
4482
0
                        ssh_debug_printf("%s->sequence_number reset to 0 (Strict KEX)\n", is_response ? "server" : "client");
4483
0
                        ws_debug("ssh: REKEY reset %s sequence number to 0 at frame %u (Strict KEX)", is_response ? "server" : "client", pinfo->num);
4484
0
                    }
4485
                    // finalize the rekey (activate the new keys)
4486
0
                    if (!is_response) {  // Only process client-sent NEWKEYS
4487
                        // Activate new key material into peer_data->cipher
4488
0
                        ssh_debug_printf("Activating new keys for CLIENT => SERVER\n");
4489
0
                        ssh_decryption_setup_cipher(peer_data, &peer_data->global_data->new_keys[0], &peer_data->global_data->new_keys[2]);
4490
0
                        ssh_decryption_setup_mac(peer_data, &peer_data->global_data->new_keys[4]);
4491
0
                    } else {  // Only process server-sent NEWKEYS
4492
                        // Activate new key material into peer_data->cipher
4493
0
                        ssh_debug_printf("Activating new keys for SERVER => CLIENT\n");
4494
0
                        ssh_decryption_setup_cipher(peer_data, &peer_data->global_data->new_keys[1], &peer_data->global_data->new_keys[3]);
4495
0
                        ssh_decryption_setup_mac(peer_data, &peer_data->global_data->new_keys[5]);
4496
0
                    }
4497
                    // Finishing REKEY
4498
0
                    peer_data->rekey_pending = false;
4499
0
                    ws_debug("ssh: REKEY done... switched to NEWKEYS at frame %u", pinfo->num);
4500
0
                }
4501
0
                break;
4502
0
            }
4503
0
        }
4504
0
    }
4505
    /* Key exchange method specific (reusable) (30-49) */
4506
    /* Normally these messages are all dissected in ssh_dissect_key_exchange */
4507
0
    else if (msg_code >=30 && msg_code <= 49) {
4508
//TODO: See if the complete dissector should be refactored to always go through here first                offset = global_data->kex_specific_dissector(msg_code, packet_tvb, pinfo, offset, msg_type_tree);
4509
4510
0
        msg_type_tree = proto_tree_add_subtree(tree, packet_tvb, offset, plen-1, ett_key_exchange, NULL, "Message: Transport (key exchange method specific)");
4511
0
        ws_debug("ssh: rekey KEX_xxx_INIT/KEX_xxx_REPLY detected in frame %u", pinfo->num);
4512
0
        peer_data->rekey_pending = true;
4513
0
        dissected_len = peer_data->global_data->kex_specific_dissector(msg_code, payload_tvb, pinfo, offset -5, msg_type_tree, peer_data->global_data);
4514
0
    }
4515
4516
    /* User authentication protocol */
4517
    /* Generic (50-59) */
4518
0
    else if (msg_code >= 50 && msg_code <= 59) {
4519
0
        col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, val_to_str(pinfo->pool, msg_code, ssh2_msg_vals, "Unknown (%u)"));
4520
0
        msg_type_tree = proto_tree_add_subtree(tree, packet_tvb, offset, plen-1, ett_key_exchange, NULL, "Message: User Authentication (generic)");
4521
0
        proto_tree_add_item(msg_type_tree, hf_ssh2_msg_code, packet_tvb, offset, 1, ENC_BIG_ENDIAN);
4522
0
        dissected_len = ssh_dissect_userauth_generic(payload_tvb, pinfo, 1, msg_type_tree, msg_code);
4523
0
    }
4524
    /* User authentication method specific (reusable) (60-79) */
4525
0
    else if (msg_code >= 60 && msg_code <= 79) {
4526
0
        col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, val_to_str(pinfo->pool, msg_code, ssh2_msg_vals, "Unknown (%u)"));
4527
0
        msg_type_tree = proto_tree_add_subtree(tree, packet_tvb, offset, plen-1, ett_key_exchange, NULL, "Message: User Authentication: (method specific)");
4528
0
        proto_tree_add_item(msg_type_tree, hf_ssh2_msg_code, packet_tvb, offset, 1, ENC_BIG_ENDIAN);
4529
0
        dissected_len = ssh_dissect_userauth_specific(payload_tvb, pinfo, 1, msg_type_tree, msg_code);
4530
0
    }
4531
4532
    /* Connection protocol */
4533
    /* Generic (80-89) */
4534
0
    else if (msg_code >= 80 && msg_code <= 89) {
4535
0
        col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, val_to_str(pinfo->pool, msg_code, ssh2_msg_vals, "Unknown (%u)"));
4536
0
        msg_type_tree = proto_tree_add_subtree(tree, packet_tvb, offset, plen-1, ett_key_exchange, NULL, "Message: Connection (generic)");
4537
0
        proto_tree_add_item(msg_type_tree, hf_ssh2_msg_code, packet_tvb, offset, 1, ENC_BIG_ENDIAN);
4538
0
        dissected_len = ssh_dissect_connection_generic(payload_tvb, pinfo, 1, msg_type_tree, msg_code);
4539
0
    }
4540
    /* Channel related messages (90-127) */
4541
0
    else if (msg_code >= 90 && msg_code <= 127) {
4542
0
        col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, val_to_str(pinfo->pool, msg_code, ssh2_msg_vals, "Unknown (%u)"));
4543
0
        msg_type_tree = proto_tree_add_subtree(tree, packet_tvb, offset, plen-1, ett_key_exchange, NULL, "Message: Connection: (channel related message)");
4544
0
        proto_tree_add_item(msg_type_tree, hf_ssh2_msg_code, packet_tvb, offset, 1, ENC_BIG_ENDIAN);
4545
0
        dissected_len = ssh_dissect_connection_specific(payload_tvb, pinfo, peer_data, 1, msg_type_tree, msg_code, message);
4546
0
    }
4547
4548
    /* Reserved for client protocols (128-191) */
4549
0
    else if (msg_code >= 128 && msg_code <= 191) {
4550
0
        col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, val_to_str(pinfo->pool, msg_code, ssh2_msg_vals, "Unknown (%u)"));
4551
0
        msg_type_tree = proto_tree_add_subtree(tree, packet_tvb, offset, plen-1, ett_key_exchange, NULL, "Message: Client protocol");
4552
0
        proto_tree_add_item(msg_type_tree, hf_ssh2_msg_code, packet_tvb, offset, 1, ENC_BIG_ENDIAN);
4553
0
        offset+=1;
4554
        // TODO: dissected_len = ssh_dissect_client(payload_tvb, pinfo, global_data, 1, msg_type_tree, is_response, msg_code);
4555
0
    }
4556
4557
    /* Local extensions (192-255) */
4558
0
    else if (msg_code >= 192 && msg_code <= 255) {
4559
0
        msg_type_tree = proto_tree_add_subtree(tree, packet_tvb, offset, plen-1, ett_key_exchange, NULL, "Message: Local extension");
4560
0
        dissected_len = ssh_dissect_local_extension(payload_tvb, pinfo, 0, peer_data, msg_type_tree, msg_code);
4561
0
    }
4562
4563
    /* XXX - ssh_dissect_key_exchange only adds undecoded payload here,
4564
     * i.e., tvb_reported_length_remaining(payload_tvb, dissected_len)
4565
     */
4566
0
    if (payload_length > 0) {
4567
0
        proto_tree_add_item(msg_type_tree, hf_ssh_payload, packet_tvb, offset, payload_length, ENC_NA);
4568
0
    }
4569
0
    if(dissected_len!=(int)payload_length){
4570
0
        expert_add_info_format(pinfo, ti, &ei_ssh_packet_decode, "Decoded %d bytes, but payload length is %d bytes [%d]", dissected_len, payload_length, msg_code);
4571
0
    }
4572
0
    offset += payload_length;
4573
4574
    /* padding */
4575
0
    proto_tree_add_item(tree, hf_ssh_padding_string, packet_tvb, offset, padding_length, ENC_NA);
4576
0
    offset += padding_length;
4577
4578
0
    if (peer_data->mac_length > 0) {
4579
0
        proto_tree_add_checksum_bytes(tree, tvb, offset, hf_ssh_mac_string, hf_ssh_mac_status, &ei_ssh_mac_bad, pinfo, message->calc_mac, peer_data->mac_length, PROTO_CHECKSUM_VERIFY);
4580
0
        offset += peer_data->mac_length;
4581
0
    }
4582
0
    ti = proto_tree_add_uint(tree, hf_ssh_seq_num, tvb, offset, 0, message->sequence_number);
4583
0
    proto_item_set_generated(ti);
4584
0
    return offset;
4585
0
}
4586
4587
static int
4588
ssh_dissect_transport_generic(tvbuff_t *packet_tvb, packet_info *pinfo,
4589
        int offset, struct ssh_peer_data *peer_data, proto_item *msg_type_tree, unsigned msg_code)
4590
0
{
4591
0
        (void)pinfo;
4592
0
        if(msg_code==SSH_MSG_DISCONNECT){
4593
0
                proto_tree_add_item(msg_type_tree, hf_ssh_disconnect_reason, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
4594
0
                offset += 4;
4595
0
                unsigned   nlen;
4596
0
                nlen = tvb_get_ntohl(packet_tvb, offset) ;
4597
0
                proto_tree_add_item(msg_type_tree, hf_ssh_disconnect_description_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
4598
0
                offset += 4;
4599
0
                proto_tree_add_item(msg_type_tree, hf_ssh_disconnect_description, packet_tvb, offset, nlen, ENC_ASCII);
4600
0
                offset += nlen;
4601
0
                nlen = tvb_get_ntohl(packet_tvb, offset) ;
4602
0
                proto_tree_add_item(msg_type_tree, hf_ssh_lang_tag_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
4603
0
                offset += 4;
4604
0
                proto_tree_add_item(msg_type_tree, hf_ssh_lang_tag, packet_tvb, offset, nlen, ENC_ASCII);
4605
0
                offset += nlen;
4606
0
        }else if(msg_code==SSH_MSG_IGNORE){
4607
0
                offset += ssh_tree_add_string(packet_tvb, offset, msg_type_tree, hf_ssh_ignore_data, hf_ssh_ignore_data_length);
4608
0
        }else if(msg_code==SSH_MSG_DEBUG){
4609
0
                unsigned   slen;
4610
0
                proto_tree_add_item(msg_type_tree, hf_ssh_debug_always_display, packet_tvb, offset, 1, ENC_BIG_ENDIAN);
4611
0
                offset += 1;
4612
0
                slen = tvb_get_ntohl(packet_tvb, offset) ;
4613
0
                proto_tree_add_item(msg_type_tree, hf_ssh_debug_message_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
4614
0
                offset += 4;
4615
0
                proto_tree_add_item(msg_type_tree, hf_ssh_debug_message, packet_tvb, offset, slen, ENC_UTF_8);
4616
0
                offset += slen;
4617
0
                slen = tvb_get_ntohl(packet_tvb, offset) ;
4618
0
                proto_tree_add_item(msg_type_tree, hf_ssh_lang_tag_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
4619
0
                offset += 4;
4620
0
                proto_tree_add_item(msg_type_tree, hf_ssh_lang_tag, packet_tvb, offset, slen, ENC_ASCII);
4621
0
                offset += slen;
4622
0
        }else if(msg_code==SSH_MSG_SERVICE_REQUEST){
4623
0
                unsigned   nlen;
4624
0
                nlen = tvb_get_ntohl(packet_tvb, offset) ;
4625
0
                proto_tree_add_item(msg_type_tree, hf_ssh_service_name_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
4626
0
                offset += 4;
4627
0
                proto_tree_add_item(msg_type_tree, hf_ssh_service_name, packet_tvb, offset, nlen, ENC_ASCII);
4628
0
                offset += nlen;
4629
0
        }else if(msg_code==SSH_MSG_SERVICE_ACCEPT){
4630
0
                unsigned   nlen;
4631
0
                nlen = tvb_get_ntohl(packet_tvb, offset) ;
4632
0
                proto_tree_add_item(msg_type_tree, hf_ssh_service_name_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
4633
0
                offset += 4;
4634
0
                proto_tree_add_item(msg_type_tree, hf_ssh_service_name, packet_tvb, offset, nlen, ENC_ASCII);
4635
0
                offset += nlen;
4636
0
        }else if(msg_code==SSH_MSG_EXT_INFO){
4637
0
                unsigned   ext_cnt;
4638
0
                ext_cnt = tvb_get_ntohl(packet_tvb, offset);
4639
0
                proto_tree_add_item(msg_type_tree, hf_ssh_ext_count, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
4640
0
                offset += 4;
4641
0
                for(unsigned ext_index = 0; ext_index < ext_cnt; ext_index++) {
4642
0
                    offset = ssh_dissect_rfc8308_extension(packet_tvb, pinfo, offset, peer_data, msg_type_tree);
4643
0
                }
4644
0
        }
4645
0
        return offset;
4646
0
}
4647
4648
static int
4649
ssh_dissect_rfc8308_extension(tvbuff_t *packet_tvb, packet_info *pinfo,
4650
        int offset, struct ssh_peer_data *peer_data, proto_item *msg_type_tree)
4651
0
{
4652
0
    (void)pinfo;
4653
0
    unsigned ext_name_slen = tvb_get_ntohl(packet_tvb, offset);
4654
0
    uint8_t *ext_name = tvb_get_string_enc(pinfo->pool, packet_tvb, offset + 4, ext_name_slen, ENC_ASCII);
4655
0
    unsigned ext_value_slen = tvb_get_ntohl(packet_tvb, offset + 4 + ext_name_slen);
4656
0
    unsigned ext_len = 8 + ext_name_slen + ext_value_slen;
4657
0
    proto_item *ext_tree = proto_tree_add_subtree_format(msg_type_tree, packet_tvb, offset, ext_len, ett_extension, NULL, "Extension: %s", ext_name);
4658
4659
0
    proto_tree_add_item(ext_tree, hf_ssh_ext_name_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
4660
0
    offset += 4;
4661
0
    proto_tree_add_item(ext_tree, hf_ssh_ext_name, packet_tvb, offset, ext_name_slen, ENC_ASCII);
4662
0
    offset += ext_name_slen;
4663
0
    proto_tree_add_item(ext_tree, hf_ssh_ext_value_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
4664
0
    offset += 4;
4665
0
    proto_tree_add_item(ext_tree, hf_ssh_ext_value, packet_tvb, offset, ext_value_slen, ENC_NA);
4666
4667
0
    if (g_str_equal(ext_name, "server-sig-algs")) {
4668
        // server-sig-algs (RFC8308 Sec. 3.1)
4669
0
        proto_tree_add_item(ext_tree, hf_ssh_ext_server_sig_algs_algorithms, packet_tvb, offset, ext_value_slen, ENC_ASCII);
4670
0
        offset += ext_value_slen;
4671
0
    } else if (g_str_equal(ext_name, "delay-compression")) {
4672
        // delay-compression (RFC8308 Sec 3.2)
4673
0
        unsigned slen;
4674
0
        slen = tvb_get_ntohl(packet_tvb, offset);
4675
0
        proto_tree_add_item(ext_tree, hf_ssh_ext_delay_compression_algorithms_client_to_server_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
4676
0
        offset += 4;
4677
0
        proto_tree_add_item(ext_tree, hf_ssh_ext_delay_compression_algorithms_client_to_server, packet_tvb, offset, slen, ENC_ASCII);
4678
0
        offset += slen;
4679
0
        slen = tvb_get_ntohl(packet_tvb, offset);
4680
0
        proto_tree_add_item(ext_tree, hf_ssh_ext_delay_compression_algorithms_server_to_client_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
4681
0
        offset += 4;
4682
0
        proto_tree_add_item(ext_tree, hf_ssh_ext_delay_compression_algorithms_server_to_client, packet_tvb, offset, slen, ENC_ASCII);
4683
0
        offset += slen;
4684
0
    } else if (g_str_equal(ext_name, "no-flow-control")) {
4685
        // no-flow-control (RFC 8308 Sec 3.3)
4686
0
        proto_tree_add_item(ext_tree, hf_ssh_ext_no_flow_control_value, packet_tvb, offset, ext_value_slen, ENC_ASCII);
4687
0
        offset += ext_value_slen;
4688
0
    } else if (g_str_equal(ext_name, "elevation")) {
4689
        // elevation (RFC 8308 Sec 3.4)
4690
0
        proto_tree_add_item(ext_tree, hf_ssh_ext_elevation_value, packet_tvb, offset, ext_value_slen, ENC_ASCII);
4691
0
        offset += ext_value_slen;
4692
0
    } else if (g_str_equal(ext_name, "publickey-algorithms@roumenpetrov.info")) {
4693
        // publickey-algorithms@roumenpetrov.info (proprietary)
4694
0
        proto_tree_add_item(ext_tree, hf_ssh_ext_prop_publickey_algorithms_algorithms, packet_tvb, offset, ext_value_slen, ENC_ASCII);
4695
0
        offset += ext_value_slen;
4696
0
    } else if (g_str_equal(ext_name, "ping@openssh.com")) {
4697
        // ping@openssh.com (proprietary w/ primitive extension value)
4698
0
        peer_data->global_data->ext_ping_openssh_offered = true;
4699
0
        offset += ext_value_slen;
4700
0
    } else {
4701
0
        offset += ext_value_slen;
4702
0
    }
4703
4704
    // The following extensions do not require advanced dissection:
4705
    //  - global-requests-ok
4706
    //  - ext-auth-info
4707
    //  - publickey-hostbound@openssh.com
4708
    //  - ext-info-in-auth@openssh.com
4709
4710
0
    return offset;
4711
0
}
4712
4713
static int
4714
ssh_dissect_userauth_generic(tvbuff_t *packet_tvb, packet_info *pinfo,
4715
        int offset, proto_item *msg_type_tree, unsigned msg_code)
4716
0
{
4717
0
        if(msg_code==SSH_MSG_USERAUTH_REQUEST){
4718
0
                uint32_t  slen;
4719
0
                proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_userauth_user_name_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN, &slen);
4720
0
                offset += 4;
4721
0
                proto_tree_add_item(msg_type_tree, hf_ssh_userauth_user_name, packet_tvb, offset, slen, ENC_ASCII);
4722
0
                offset += slen;
4723
0
                proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_userauth_service_name_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN, &slen);
4724
0
                offset += 4;
4725
0
                proto_tree_add_item(msg_type_tree, hf_ssh_userauth_service_name, packet_tvb, offset, slen, ENC_ASCII);
4726
0
                offset += slen;
4727
0
                proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_userauth_method_name_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN, &slen);
4728
0
                offset += 4;
4729
0
                const char* key_type;
4730
0
                proto_tree_add_item_ret_string(msg_type_tree, hf_ssh_userauth_method_name, packet_tvb, offset, slen, ENC_ASCII, pinfo->pool, (const uint8_t**)&key_type);
4731
0
                offset += slen;
4732
0
                if (0 == strcmp(key_type, "none")) {
4733
0
                }else if (0 == strcmp(key_type, "publickey") || 0 == strcmp(key_type, "publickey-hostbound-v00@openssh.com")) {
4734
0
                        uint8_t bHaveSignature = tvb_get_uint8(packet_tvb, offset);
4735
0
                        int dissected_len = 0;
4736
0
                        proto_tree_add_item(msg_type_tree, hf_ssh_userauth_have_signature, packet_tvb, offset, 1, ENC_BIG_ENDIAN);
4737
0
                        offset += 1;
4738
0
                        proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_userauth_pka_name_len, packet_tvb, offset, 4, ENC_BIG_ENDIAN, &slen);
4739
0
                        offset += 4;
4740
0
                        proto_tree_add_item(msg_type_tree, hf_ssh_userauth_pka_name, packet_tvb, offset, slen, ENC_ASCII);
4741
0
                        offset += slen;
4742
0
                        proto_item *ti;
4743
0
                        ti = proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_blob_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN, &slen);
4744
0
                        offset += 4;
4745
0
                        dissected_len = ssh_dissect_public_key_blob(tvb_new_subset_length(packet_tvb, offset, slen), pinfo, msg_type_tree);
4746
0
                        if(dissected_len!=(int)slen){
4747
0
                            expert_add_info_format(pinfo, ti, &ei_ssh_packet_decode, "Decoded %d bytes, but packet length is %d bytes", dissected_len, slen);
4748
0
                        }
4749
0
                        offset += slen;
4750
0
                        if (0 == strcmp(key_type, "publickey-hostbound-v00@openssh.com")) {
4751
                            // Host key - but should we add it to global data or not?
4752
0
                            offset += ssh_tree_add_hostkey(packet_tvb, pinfo, offset, msg_type_tree, "Server host key",
4753
0
                                    ett_key_exchange_host_key, NULL);
4754
0
                        }
4755
0
                        if(bHaveSignature){
4756
0
                                proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_signature_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN, &slen);
4757
0
                                offset += 4;
4758
0
                                proto_item *signature_tree = NULL;
4759
0
                                signature_tree = proto_tree_add_subtree(msg_type_tree, packet_tvb, offset, slen, ett_userauth_pk_signature, NULL, "Public key signature");
4760
0
                                dissected_len = ssh_dissect_public_key_signature(packet_tvb, pinfo, offset, signature_tree) - offset;
4761
0
                                if(dissected_len!=(int)slen){
4762
0
                                    expert_add_info_format(pinfo, signature_tree, &ei_ssh_packet_decode, "Decoded %d bytes, but packet length is %d bytes", dissected_len, slen);
4763
0
                                }
4764
0
                                offset += slen;
4765
0
                        }
4766
0
                }else if (0 == strcmp(key_type, "password")) {
4767
0
                        uint8_t bChangePassword = tvb_get_uint8(packet_tvb, offset);
4768
0
                        proto_tree_add_item(msg_type_tree, hf_ssh_userauth_change_password, packet_tvb, offset, 1, ENC_BIG_ENDIAN);
4769
0
                        offset += 1;
4770
0
                        proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_userauth_password_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN, &slen);
4771
0
                        offset += 4;
4772
0
                        proto_tree_add_item(msg_type_tree, hf_ssh_userauth_password, packet_tvb, offset, slen, ENC_ASCII);
4773
0
                        offset += slen;
4774
0
                        if(bChangePassword){
4775
0
                            proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_userauth_new_password_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN, &slen);
4776
0
                            offset += 4;
4777
0
                            proto_tree_add_item(msg_type_tree, hf_ssh_userauth_new_password, packet_tvb, offset, slen, ENC_ASCII);
4778
0
                            offset += slen;
4779
0
                        }
4780
0
                }else{
4781
0
                }
4782
4783
0
        }else if(msg_code==SSH_MSG_USERAUTH_FAILURE){
4784
0
                unsigned   slen;
4785
0
                proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_auth_failure_list_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN, &slen);
4786
0
                offset += 4;
4787
0
                proto_tree_add_item(msg_type_tree, hf_ssh_auth_failure_list, packet_tvb, offset, slen, ENC_ASCII);
4788
0
                offset += slen;
4789
0
                proto_tree_add_item(msg_type_tree, hf_ssh_userauth_partial_success, packet_tvb, offset, 1, ENC_BIG_ENDIAN);
4790
0
                offset += 1;
4791
0
        }
4792
0
        return offset;
4793
0
}
4794
4795
static int
4796
ssh_dissect_userauth_specific(tvbuff_t *packet_tvb, packet_info *pinfo,
4797
        int offset, proto_item *msg_type_tree, unsigned msg_code)
4798
0
{
4799
0
        if(msg_code==SSH_MSG_USERAUTH_PK_OK){
4800
0
                proto_item *ti;
4801
0
                int dissected_len = 0;
4802
0
                unsigned   slen;
4803
0
                slen = tvb_get_ntohl(packet_tvb, offset) ;
4804
0
                proto_tree_add_item(msg_type_tree, hf_ssh_userauth_pka_name_len, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
4805
0
                offset += 4;
4806
0
                proto_tree_add_item(msg_type_tree, hf_ssh_userauth_pka_name, packet_tvb, offset, slen, ENC_ASCII);
4807
0
                offset += slen;
4808
0
                ti = proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_blob_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN, &slen);
4809
0
                offset += 4;
4810
0
                dissected_len = ssh_dissect_public_key_blob(tvb_new_subset_length(packet_tvb, offset, slen), pinfo, msg_type_tree);
4811
0
                if(dissected_len!=(int)slen){
4812
0
                    expert_add_info_format(pinfo, ti, &ei_ssh_packet_decode, "Decoded %d bytes, but packet length is %d bytes", dissected_len, slen);
4813
0
                }
4814
0
                offset += slen;
4815
0
        }
4816
0
        return offset;
4817
0
}
4818
4819
static void
4820
ssh_process_payload(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, ssh_channel_info_t *channel)
4821
0
{
4822
0
    tvbuff_t *next_tvb = tvb_new_subset_remaining(tvb, offset);
4823
0
    if (channel->handle) {
4824
0
        call_dissector(channel->handle, next_tvb, pinfo, proto_tree_get_root(tree));
4825
0
    } else {
4826
0
        call_data_dissector(next_tvb, pinfo, proto_tree_get_root(tree));
4827
0
    }
4828
0
}
4829
4830
static void
4831
print_ssh_fragment_tree(fragment_head *ipfd_head, proto_tree *tree, proto_tree *ssh_tree, packet_info *pinfo, tvbuff_t *next_tvb)
4832
0
{
4833
0
    proto_item *ssh_tree_item, *frag_tree_item;
4834
4835
    /*
4836
     * The subdissector thought it was completely
4837
     * desegmented (although the stuff at the
4838
     * end may, in turn, require desegmentation),
4839
     * so we show a tree with all segments.
4840
     */
4841
0
    show_fragment_tree(ipfd_head, &ssh_segment_items,
4842
0
                       tree, pinfo, next_tvb, &frag_tree_item);
4843
    /*
4844
     * The toplevel fragment subtree is now
4845
     * behind all desegmented data; move it
4846
     * right behind the SSH tree.
4847
     */
4848
0
    ssh_tree_item = proto_tree_get_parent(ssh_tree);
4849
    /* The SSH protocol item is up a few levels from the message tree */
4850
0
    ssh_tree_item = proto_item_get_parent_nth(ssh_tree_item, 2);
4851
0
    if (frag_tree_item && ssh_tree_item) {
4852
0
        proto_tree_move_item(tree, ssh_tree_item, frag_tree_item);
4853
0
    }
4854
0
}
4855
4856
static uint32_t
4857
ssh_msp_fragment_id(struct tcp_multisegment_pdu *msp)
4858
0
{
4859
    /*
4860
     * If a frame contains multiple PDUs, then "first_frame" is not
4861
     * sufficient to uniquely identify groups of fragments. Therefore we use
4862
     * the tcp reassembly functions that also test msp->seq (the position of
4863
     * the initial fragment in the SSH channel).
4864
     */
4865
0
    return msp->first_frame;
4866
0
}
4867
4868
static void
4869
ssh_proto_tree_add_segment_data(
4870
    proto_tree  *tree,
4871
    tvbuff_t    *tvb,
4872
    int          offset,
4873
    int          length,
4874
    const char *prefix)
4875
0
{
4876
0
    proto_tree_add_bytes_format(
4877
0
        tree,
4878
0
        hf_ssh_segment_data,
4879
0
        tvb,
4880
0
        offset,
4881
0
        length,
4882
0
        NULL,
4883
0
        "%sSSH segment data (%u %s)",
4884
0
        prefix != NULL ? prefix : "",
4885
0
        length,
4886
0
        plurality(length, "byte", "bytes"));
4887
0
}
4888
4889
static void
4890
desegment_ssh(tvbuff_t *tvb, packet_info *pinfo, uint32_t seq,
4891
        uint32_t nxtseq, proto_tree *tree, ssh_channel_info_t *channel)
4892
0
{
4893
0
    fragment_head *ipfd_head;
4894
0
    bool           must_desegment;
4895
0
    bool           called_dissector;
4896
0
    unsigned       another_pdu_follows;
4897
0
    bool           another_segment_in_frame = false;
4898
0
    int            deseg_offset, offset = 0;
4899
0
    uint32_t       deseg_seq;
4900
0
    int            nbytes;
4901
0
    proto_item    *item;
4902
0
    struct tcp_multisegment_pdu *msp;
4903
0
    bool           first_pdu = true;
4904
4905
0
again:
4906
0
    ipfd_head = NULL;
4907
0
    must_desegment = false;
4908
0
    called_dissector = false;
4909
0
    another_pdu_follows = 0;
4910
0
    msp = NULL;
4911
4912
    /*
4913
     * Initialize these to assume no desegmentation.
4914
     * If that's not the case, these will be set appropriately
4915
     * by the subdissector.
4916
     */
4917
0
    pinfo->desegment_offset = 0;
4918
0
    pinfo->desegment_len = 0;
4919
4920
   /*
4921
     * Initialize this to assume that this segment will just be
4922
     * added to the middle of a desegmented chunk of data, so
4923
     * that we should show it all as data.
4924
     * If that's not the case, it will be set appropriately.
4925
     */
4926
0
    deseg_offset = offset;
4927
4928
    /* If we've seen this segment before (e.g., it's a retransmission),
4929
     * there's nothing for us to do.  Certainly, don't add it to the list
4930
     * of multisegment_pdus (that would cause subsequent lookups to find
4931
     * the retransmission instead of the original transmission, breaking
4932
     * dissection of the desegmented pdu if we'd already seen the end of
4933
     * the pdu).
4934
     */
4935
0
    if ((msp = (struct tcp_multisegment_pdu *)wmem_tree_lookup32(channel->multisegment_pdus, seq))) {
4936
0
        const char *prefix;
4937
0
        bool is_retransmission = false;
4938
4939
0
        if (msp->first_frame == pinfo->num) {
4940
            /* This must be after the first pass. */
4941
0
            prefix = "";
4942
0
            if (msp->last_frame == pinfo->num) {
4943
0
                col_clear(pinfo->cinfo, COL_INFO);
4944
0
            } else {
4945
0
                if (first_pdu) {
4946
0
                    col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "[SSH segment of a reassembled PDU]");
4947
0
                }
4948
0
            }
4949
0
        } else {
4950
0
            prefix = "Retransmitted ";
4951
0
            is_retransmission = true;
4952
0
        }
4953
4954
0
        if (!is_retransmission) {
4955
0
            ipfd_head = fragment_get(&ssh_reassembly_table, pinfo, msp->first_frame, msp);
4956
0
            if (ipfd_head != NULL && ipfd_head->reassembled_in !=0 &&
4957
0
                ipfd_head->reassembled_in != pinfo->num) {
4958
                /* Show what frame this was reassembled in if not this one. */
4959
0
                item=proto_tree_add_uint(tree, *ssh_segment_items.hf_reassembled_in,
4960
0
                                         tvb, 0, 0, ipfd_head->reassembled_in);
4961
0
                proto_item_set_generated(item);
4962
0
            }
4963
0
        }
4964
0
        nbytes = tvb_reported_length_remaining(tvb, offset);
4965
0
        ssh_proto_tree_add_segment_data(tree, tvb, offset, nbytes, prefix);
4966
0
        return;
4967
0
    }
4968
4969
    /* Else, find the most previous PDU starting before this sequence number */
4970
0
    msp = (struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(channel->multisegment_pdus, seq-1);
4971
0
    if (msp && msp->seq <= seq && msp->nxtpdu > seq) {
4972
0
        unsigned len;
4973
4974
0
        if (!PINFO_FD_VISITED(pinfo)) {
4975
0
            msp->last_frame = pinfo->num;
4976
0
            msp->last_frame_time = pinfo->abs_ts;
4977
0
        }
4978
4979
        /* OK, this PDU was found, which means the segment continues
4980
         * a higher-level PDU and that we must desegment it.
4981
         */
4982
0
        if (msp->flags & MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT) {
4983
            /* The dissector asked for the entire segment */
4984
0
            len = tvb_reported_length_remaining(tvb, offset);
4985
0
        } else {
4986
0
            len = MIN(nxtseq, msp->nxtpdu) - seq;
4987
0
        }
4988
4989
0
        ipfd_head = fragment_add(&ssh_reassembly_table, tvb, offset,
4990
0
                                 pinfo, ssh_msp_fragment_id(msp), msp,
4991
0
                                 seq - msp->seq,
4992
0
                                 len, (LT_SEQ (nxtseq,msp->nxtpdu)));
4993
4994
0
        if (!PINFO_FD_VISITED(pinfo)
4995
0
        && msp->flags & MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT) {
4996
0
            msp->flags &= (~MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT);
4997
4998
            /* If we consumed the entire segment there is no
4999
             * other pdu starting anywhere inside this segment.
5000
             * So update nxtpdu to point at least to the start
5001
             * of the next segment.
5002
             * (If the subdissector asks for even more data we
5003
             * will advance nxtpdu even further later down in
5004
             * the code.)
5005
             */
5006
0
            msp->nxtpdu = nxtseq;
5007
0
        }
5008
5009
0
        if ( (msp->nxtpdu < nxtseq)
5010
0
        &&  (msp->nxtpdu >= seq)
5011
0
        &&  (len > 0)) {
5012
0
            another_pdu_follows = msp->nxtpdu - seq;
5013
0
        }
5014
0
    } else {
5015
        /* This segment was not found in our table, so it doesn't
5016
         * contain a continuation of a higher-level PDU.
5017
         * Call the normal subdissector.
5018
         */
5019
0
        ssh_process_payload(tvb, offset, pinfo, tree, channel);
5020
0
        called_dissector = true;
5021
5022
        /* Did the subdissector ask us to desegment some more data
5023
         * before it could handle the packet?
5024
         * If so we have to create some structures in our table but
5025
         * this is something we only do the first time we see this
5026
         * packet.
5027
         */
5028
0
        if (pinfo->desegment_len) {
5029
0
            if (!PINFO_FD_VISITED(pinfo))
5030
0
                must_desegment = true;
5031
5032
            /*
5033
             * Set "deseg_offset" to the offset in "tvb"
5034
             * of the first byte of data that the
5035
             * subdissector didn't process.
5036
             */
5037
0
            deseg_offset = offset + pinfo->desegment_offset;
5038
0
        }
5039
5040
        /* Either no desegmentation is necessary, or this is
5041
         * segment contains the beginning but not the end of
5042
         * a higher-level PDU and thus isn't completely
5043
         * desegmented.
5044
         */
5045
0
        ipfd_head = NULL;
5046
0
    }
5047
5048
    /* is it completely desegmented? */
5049
0
    if (ipfd_head && ipfd_head->reassembled_in == pinfo->num) {
5050
        /*
5051
         * Yes, we think it is.
5052
         * We only call subdissector for the last segment.
5053
         * Note that the last segment may include more than what
5054
         * we needed.
5055
         */
5056
0
        if (nxtseq < msp->nxtpdu) {
5057
            /*
5058
             * This is *not* the last segment. It is part of a PDU in the same
5059
             * frame, so no another PDU can follow this one.
5060
             * Do not reassemble SSH yet, it will be done in the final segment.
5061
             * (If we are reassembling at FIN, we will do that in dissect_ssl()
5062
             * after iterating through all the records.)
5063
             * Clear the Info column and avoid displaying [SSH segment of a
5064
             * reassembled PDU], the payload dissector will typically set it.
5065
             * (This is needed here for the second pass.)
5066
             */
5067
0
            another_pdu_follows = 0;
5068
0
            col_clear(pinfo->cinfo, COL_INFO);
5069
0
            another_segment_in_frame = true;
5070
0
        } else {
5071
            /*
5072
             * OK, this is the last segment of the PDU and also the
5073
             * last segment in this frame.
5074
             * Let's call the subdissector with the desegmented
5075
             * data.
5076
             */
5077
0
            tvbuff_t *next_tvb;
5078
0
            int old_len;
5079
5080
            /*
5081
             * Reset column in case multiple SSH segments form the PDU
5082
             * and this last SSH segment is not in the first TCP segment of
5083
             * this frame.
5084
             * XXX prevent clearing the column if the last layer is not SSH?
5085
             */
5086
            /* Clear column during the first pass. */
5087
0
            col_clear(pinfo->cinfo, COL_INFO);
5088
5089
            /* create a new TVB structure for desegmented data */
5090
0
            next_tvb = tvb_new_chain(tvb, ipfd_head->tvb_data);
5091
5092
            /* add desegmented data to the data source list */
5093
0
            add_new_data_source(pinfo, next_tvb, "Reassembled SSH");
5094
5095
            /* call subdissector */
5096
0
            ssh_process_payload(next_tvb, 0, pinfo, tree, channel);
5097
0
            called_dissector = true;
5098
5099
            /*
5100
             * OK, did the subdissector think it was completely
5101
             * desegmented, or does it think we need even more
5102
             * data?
5103
             */
5104
0
            old_len = (int)(tvb_reported_length(next_tvb) - tvb_reported_length_remaining(tvb, offset));
5105
0
            if (pinfo->desegment_len && pinfo->desegment_offset <= old_len) {
5106
                /*
5107
                 * "desegment_len" isn't 0, so it needs more
5108
                 * data for something - and "desegment_offset"
5109
                 * is before "old_len", so it needs more data
5110
                 * to dissect the stuff we thought was
5111
                 * completely desegmented (as opposed to the
5112
                 * stuff at the beginning being completely
5113
                 * desegmented, but the stuff at the end
5114
                 * being a new higher-level PDU that also
5115
                 * needs desegmentation).
5116
                 */
5117
0
                fragment_set_partial_reassembly(&ssh_reassembly_table,
5118
0
                                                pinfo, ssh_msp_fragment_id(msp), msp);
5119
                /* Update msp->nxtpdu to point to the new next
5120
                 * pdu boundary.
5121
                 */
5122
0
                if (pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT) {
5123
                    /* We want reassembly of at least one
5124
                     * more segment so set the nxtpdu
5125
                     * boundary to one byte into the next
5126
                     * segment.
5127
                     * This means that the next segment
5128
                     * will complete reassembly even if it
5129
                     * is only one single byte in length.
5130
                     */
5131
0
                    msp->nxtpdu = seq + tvb_reported_length_remaining(tvb, offset) + 1;
5132
0
                    msp->flags |= MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT;
5133
0
                } else if (pinfo->desegment_len == DESEGMENT_UNTIL_FIN) {
5134
                    /* This is not the first segment, and we thought reassembly
5135
                     * would be done now, but now we know we desegment at FIN.
5136
                     * E.g., a HTTP response where the headers were split
5137
                     * across segments (so previous ONE_MORE_SEGMENT) and
5138
                     * also no Content-Length (so now DESEGMENT_UNTIL_FIN).
5139
                     */
5140
0
                    channel->flags |= TCP_FLOW_REASSEMBLE_UNTIL_FIN;
5141
0
                    msp->nxtpdu = nxtseq + 0x40000000;
5142
0
                } else {
5143
0
                    msp->nxtpdu = seq + tvb_reported_length_remaining(tvb, offset) + pinfo->desegment_len;
5144
0
                }
5145
                /* Since we need at least some more data
5146
                 * there can be no pdu following in the
5147
                 * tail of this segment.
5148
                 */
5149
0
                another_pdu_follows = 0;
5150
0
            } else {
5151
                /*
5152
                 * Show the stuff in this TCP segment as
5153
                 * just raw TCP segment data.
5154
                 */
5155
0
                nbytes = another_pdu_follows > 0
5156
0
                    ? another_pdu_follows
5157
0
                    : tvb_reported_length_remaining(tvb, offset);
5158
0
                ssh_proto_tree_add_segment_data(tree, tvb, offset, nbytes, NULL);
5159
5160
                /* Show details of the reassembly */
5161
0
                print_ssh_fragment_tree(ipfd_head, proto_tree_get_root(tree), tree, pinfo, next_tvb);
5162
5163
                /* Did the subdissector ask us to desegment
5164
                 * some more data?  This means that the data
5165
                 * at the beginning of this segment completed
5166
                 * a higher-level PDU, but the data at the
5167
                 * end of this segment started a higher-level
5168
                 * PDU but didn't complete it.
5169
                 *
5170
                 * If so, we have to create some structures
5171
                 * in our table, but this is something we
5172
                 * only do the first time we see this packet.
5173
                 */
5174
0
                if (pinfo->desegment_len) {
5175
0
                    if (!PINFO_FD_VISITED(pinfo))
5176
0
                        must_desegment = true;
5177
5178
                    /* The stuff we couldn't dissect
5179
                     * must have come from this segment,
5180
                     * so it's all in "tvb".
5181
                     *
5182
                     * "pinfo->desegment_offset" is
5183
                     * relative to the beginning of
5184
                     * "next_tvb"; we want an offset
5185
                     * relative to the beginning of "tvb".
5186
                     *
5187
                     * First, compute the offset relative
5188
                     * to the *end* of "next_tvb" - i.e.,
5189
                     * the number of bytes before the end
5190
                     * of "next_tvb" at which the
5191
                     * subdissector stopped.  That's the
5192
                     * length of "next_tvb" minus the
5193
                     * offset, relative to the beginning
5194
                     * of "next_tvb, at which the
5195
                     * subdissector stopped.
5196
                     */
5197
0
                    deseg_offset = ipfd_head->datalen - pinfo->desegment_offset;
5198
5199
                    /* "tvb" and "next_tvb" end at the
5200
                     * same byte of data, so the offset
5201
                     * relative to the end of "next_tvb"
5202
                     * of the byte at which we stopped
5203
                     * is also the offset relative to
5204
                     * the end of "tvb" of the byte at
5205
                     * which we stopped.
5206
                     *
5207
                     * Convert that back into an offset
5208
                     * relative to the beginning of
5209
                     * "tvb", by taking the length of
5210
                     * "tvb" and subtracting the offset
5211
                     * relative to the end.
5212
                     */
5213
0
                    deseg_offset = tvb_reported_length(tvb) - deseg_offset;
5214
0
                }
5215
0
            }
5216
0
        }
5217
0
    }
5218
5219
0
    if (must_desegment) {
5220
        /* If the dissector requested "reassemble until FIN"
5221
         * just set this flag for the flow and let reassembly
5222
         * proceed at normal.  We will check/pick up these
5223
         * reassembled PDUs later down in dissect_tcp() when checking
5224
         * for the FIN flag.
5225
         */
5226
0
        if (pinfo->desegment_len == DESEGMENT_UNTIL_FIN) {
5227
0
            channel->flags |= TCP_FLOW_REASSEMBLE_UNTIL_FIN;
5228
0
        }
5229
        /*
5230
         * The sequence number at which the stuff to be desegmented
5231
         * starts is the sequence number of the byte at an offset
5232
         * of "deseg_offset" into "tvb".
5233
         *
5234
         * The sequence number of the byte at an offset of "offset"
5235
         * is "seq", i.e. the starting sequence number of this
5236
         * segment, so the sequence number of the byte at
5237
         * "deseg_offset" is "seq + (deseg_offset - offset)".
5238
         */
5239
0
        deseg_seq = seq + (deseg_offset - offset);
5240
5241
0
        if (((nxtseq - deseg_seq) <= 1024*1024)
5242
0
            &&  (!PINFO_FD_VISITED(pinfo))) {
5243
0
            if (pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT) {
5244
                /* The subdissector asked to reassemble using the
5245
                 * entire next segment.
5246
                 * Just ask reassembly for one more byte
5247
                 * but set this msp flag so we can pick it up
5248
                 * above.
5249
                 */
5250
0
                msp = pdu_store_sequencenumber_of_next_pdu(pinfo,
5251
0
                    deseg_seq, nxtseq+1, channel->multisegment_pdus);
5252
0
                msp->flags |= MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT;
5253
0
            } else if (pinfo->desegment_len == DESEGMENT_UNTIL_FIN) {
5254
                /* Set nxtseq very large so that reassembly won't happen
5255
                 * until we force it at the end of the stream in dissect_ssl()
5256
                 * outside this function.
5257
                 */
5258
0
                msp = pdu_store_sequencenumber_of_next_pdu(pinfo,
5259
0
                    deseg_seq, nxtseq+0x40000000, channel->multisegment_pdus);
5260
0
            } else {
5261
0
                msp = pdu_store_sequencenumber_of_next_pdu(pinfo,
5262
0
                    deseg_seq, nxtseq+pinfo->desegment_len, channel->multisegment_pdus);
5263
0
            }
5264
5265
            /* add this segment as the first one for this new pdu */
5266
0
            fragment_add(&ssh_reassembly_table, tvb, deseg_offset,
5267
0
                         pinfo, ssh_msp_fragment_id(msp), msp,
5268
0
                         0, nxtseq - deseg_seq,
5269
0
                         LT_SEQ(nxtseq, msp->nxtpdu));
5270
0
        }
5271
0
    }
5272
5273
0
    if (!called_dissector || pinfo->desegment_len != 0) {
5274
0
        if (ipfd_head != NULL && ipfd_head->reassembled_in != 0 &&
5275
0
            ipfd_head->reassembled_in != pinfo->num &&
5276
0
            !(ipfd_head->flags & FD_PARTIAL_REASSEMBLY)) {
5277
            /*
5278
             * We know what other frame this PDU is reassembled in;
5279
             * let the user know.
5280
             */
5281
0
            item=proto_tree_add_uint(tree, *ssh_segment_items.hf_reassembled_in,
5282
0
                                     tvb, 0, 0, ipfd_head->reassembled_in);
5283
0
            proto_item_set_generated(item);
5284
0
        }
5285
5286
        /*
5287
         * Either we didn't call the subdissector at all (i.e.,
5288
         * this is a segment that contains the middle of a
5289
         * higher-level PDU, but contains neither the beginning
5290
         * nor the end), or the subdissector couldn't dissect it
5291
         * all, as some data was missing (i.e., it set
5292
         * "pinfo->desegment_len" to the amount of additional
5293
         * data it needs).
5294
         */
5295
0
        if (!another_segment_in_frame && pinfo->desegment_offset == 0) {
5296
            /*
5297
             * It couldn't, in fact, dissect any of it (the
5298
             * first byte it couldn't dissect is at an offset
5299
             * of "pinfo->desegment_offset" from the beginning
5300
             * of the payload, and that's 0).
5301
             * Just mark this as SSH.
5302
             */
5303
5304
            /* SFTP checks the length before setting the protocol column.
5305
             * If other subdissectors don't do this, we'd want to set the
5306
             * protocol column back - but we want to get the SSH version
5307
             */
5308
            //col_set_str(pinfo->cinfo, COL_PROTOCOL,
5309
            //        val_to_str_const(session->version, ssl_version_short_names, "SSH"));
5310
0
            if (first_pdu) {
5311
0
                col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "[SSH segment of a reassembled PDU]");
5312
0
            }
5313
0
        }
5314
5315
        /*
5316
         * Show what's left in the packet as just raw SSH segment data.
5317
         * XXX - remember what protocol the last subdissector
5318
         * was, and report it as a continuation of that, instead?
5319
         */
5320
0
        nbytes = tvb_reported_length_remaining(tvb, deseg_offset);
5321
0
        ssh_proto_tree_add_segment_data(tree, tvb, deseg_offset, nbytes, NULL);
5322
0
    }
5323
0
    pinfo->can_desegment = 0;
5324
0
    pinfo->desegment_offset = 0;
5325
0
    pinfo->desegment_len = 0;
5326
5327
0
    if (another_pdu_follows) {
5328
        /* there was another pdu following this one. */
5329
0
        pinfo->can_desegment=2;
5330
        /* we also have to prevent the dissector from changing the
5331
         * PROTOCOL and INFO colums since what follows may be an
5332
         * incomplete PDU and we don't want it be changed back from
5333
         *  <Protocol>   to <SSH>
5334
         */
5335
0
        col_set_fence(pinfo->cinfo, COL_INFO);
5336
0
        col_set_writable(pinfo->cinfo, COL_PROTOCOL, false);
5337
0
        first_pdu = false;
5338
0
        offset += another_pdu_follows;
5339
0
        seq += another_pdu_follows;
5340
0
        goto again;
5341
0
    }
5342
0
}
5343
5344
static void
5345
ssh_dissect_channel_data(tvbuff_t *tvb, packet_info *pinfo,
5346
        struct ssh_peer_data *peer_data _U_, proto_tree *tree,
5347
        ssh_message_info_t *message _U_, ssh_channel_info_t *channel)
5348
0
{
5349
5350
0
    uint16_t save_can_desegment = pinfo->can_desegment;
5351
5352
0
    if (ssh_desegment) {
5353
0
        pinfo->can_desegment = 2;
5354
0
        desegment_ssh(tvb, pinfo, message->byte_seq, message->next_byte_seq, tree, channel);
5355
0
    } else {
5356
0
        pinfo->can_desegment = 0;
5357
0
        bool save_fragmented = pinfo->fragmented;
5358
0
        pinfo->fragmented = true;
5359
5360
0
        ssh_process_payload(tvb, 0, pinfo, tree, channel);
5361
0
        pinfo->fragmented = save_fragmented;
5362
0
    }
5363
5364
0
    pinfo->can_desegment = save_can_desegment;
5365
0
}
5366
5367
static int
5368
ssh_dissect_term_modes(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
5369
0
{
5370
0
    proto_item *ti;
5371
0
    proto_tree *term_mode_tree, *subtree;
5372
0
    int offset = 0;
5373
0
    uint32_t opcode, value, idx;
5374
0
    bool boolval;
5375
5376
0
    struct tty_opt_info {
5377
0
        unsigned id;
5378
0
        int *hfindex;
5379
0
    };
5380
0
    static const struct tty_opt_info tty_opts[] = {
5381
0
        { SSH_TTY_OP_END, NULL},
5382
0
        { SSH_TTY_OP_VINTR, &hf_ssh_pty_term_mode_vintr },
5383
0
        { SSH_TTY_OP_VQUIT, &hf_ssh_pty_term_mode_vquit },
5384
0
        { SSH_TTY_OP_VERASE, &hf_ssh_pty_term_mode_verase },
5385
0
        { SSH_TTY_OP_VKILL, &hf_ssh_pty_term_mode_vkill },
5386
0
        { SSH_TTY_OP_VEOF, &hf_ssh_pty_term_mode_veof },
5387
0
        { SSH_TTY_OP_VEOL, &hf_ssh_pty_term_mode_veol },
5388
0
        { SSH_TTY_OP_VEOL2, &hf_ssh_pty_term_mode_veol2 },
5389
0
        { SSH_TTY_OP_VSTART, &hf_ssh_pty_term_mode_vstart },
5390
0
        { SSH_TTY_OP_VSTOP, &hf_ssh_pty_term_mode_vstop },
5391
0
        { SSH_TTY_OP_VSUSP, &hf_ssh_pty_term_mode_vsusp },
5392
0
        { SSH_TTY_OP_VDSUSP, &hf_ssh_pty_term_mode_vdsusp },
5393
0
        { SSH_TTY_OP_VREPRINT, &hf_ssh_pty_term_mode_vreprint },
5394
0
        { SSH_TTY_OP_VWERASE, &hf_ssh_pty_term_mode_vwerase },
5395
0
        { SSH_TTY_OP_VLNEXT, &hf_ssh_pty_term_mode_vlnext },
5396
0
        { SSH_TTY_OP_VFLUSH, &hf_ssh_pty_term_mode_vflush },
5397
0
        { SSH_TTY_OP_VSWTCH, &hf_ssh_pty_term_mode_vswtch },
5398
0
        { SSH_TTY_OP_VSTATUS, &hf_ssh_pty_term_mode_vstatus },
5399
0
        { SSH_TTY_OP_VDISCARD, &hf_ssh_pty_term_mode_vdiscard },
5400
0
        { SSH_TTY_OP_IGNPAR, &hf_ssh_pty_term_mode_ignpar },
5401
0
        { SSH_TTY_OP_PARMRK, &hf_ssh_pty_term_mode_parmrk },
5402
0
        { SSH_TTY_OP_INPCK, &hf_ssh_pty_term_mode_inpck },
5403
0
        { SSH_TTY_OP_ISTRIP, &hf_ssh_pty_term_mode_istrip },
5404
0
        { SSH_TTY_OP_INLCR, &hf_ssh_pty_term_mode_inlcr },
5405
0
        { SSH_TTY_OP_IGNCR, &hf_ssh_pty_term_mode_igncr },
5406
0
        { SSH_TTY_OP_ICRNL, &hf_ssh_pty_term_mode_icrnl },
5407
0
        { SSH_TTY_OP_IUCLC, &hf_ssh_pty_term_mode_iuclc },
5408
0
        { SSH_TTY_OP_IXON, &hf_ssh_pty_term_mode_ixon },
5409
0
        { SSH_TTY_OP_IXANY, &hf_ssh_pty_term_mode_ixany },
5410
0
        { SSH_TTY_OP_IXOFF, &hf_ssh_pty_term_mode_ixoff },
5411
0
        { SSH_TTY_OP_IMAXBEL, &hf_ssh_pty_term_mode_imaxbel },
5412
0
        { SSH_TTY_OP_IUTF8, &hf_ssh_pty_term_mode_iutf8 },
5413
0
        { SSH_TTY_OP_ISIG, &hf_ssh_pty_term_mode_isig },
5414
0
        { SSH_TTY_OP_ICANON, &hf_ssh_pty_term_mode_icanon },
5415
0
        { SSH_TTY_OP_XCASE, &hf_ssh_pty_term_mode_xcase },
5416
0
        { SSH_TTY_OP_ECHO, &hf_ssh_pty_term_mode_echo },
5417
0
        { SSH_TTY_OP_ECHOE, &hf_ssh_pty_term_mode_echoe },
5418
0
        { SSH_TTY_OP_ECHOK, &hf_ssh_pty_term_mode_echok },
5419
0
        { SSH_TTY_OP_ECHONL, &hf_ssh_pty_term_mode_echonl },
5420
0
        { SSH_TTY_OP_NOFLSH, &hf_ssh_pty_term_mode_noflsh },
5421
0
        { SSH_TTY_OP_TOSTOP, &hf_ssh_pty_term_mode_tostop },
5422
0
        { SSH_TTY_OP_IEXTEN, &hf_ssh_pty_term_mode_iexten },
5423
0
        { SSH_TTY_OP_ECHOCTL, &hf_ssh_pty_term_mode_echoctl },
5424
0
        { SSH_TTY_OP_ECHOKE, &hf_ssh_pty_term_mode_echoke },
5425
0
        { SSH_TTY_OP_PENDIN, &hf_ssh_pty_term_mode_pendin },
5426
0
        { SSH_TTY_OP_OPOST, &hf_ssh_pty_term_mode_opost },
5427
0
        { SSH_TTY_OP_OLCUC, &hf_ssh_pty_term_mode_olcuc },
5428
0
        { SSH_TTY_OP_ONLCR, &hf_ssh_pty_term_mode_onlcr },
5429
0
        { SSH_TTY_OP_OCRNL, &hf_ssh_pty_term_mode_ocrnl },
5430
0
        { SSH_TTY_OP_ONOCR, &hf_ssh_pty_term_mode_onocr },
5431
0
        { SSH_TTY_OP_ONLRET, &hf_ssh_pty_term_mode_onlret },
5432
0
        { SSH_TTY_OP_CS7, &hf_ssh_pty_term_mode_cs7 },
5433
0
        { SSH_TTY_OP_CS8, &hf_ssh_pty_term_mode_cs8 },
5434
0
        { SSH_TTY_OP_PARENB, &hf_ssh_pty_term_mode_parenb },
5435
0
        { SSH_TTY_OP_PARODD, &hf_ssh_pty_term_mode_parodd },
5436
0
        { SSH_TTY_OP_ISPEED, &hf_ssh_pty_term_mode_ispeed },
5437
0
        { SSH_TTY_OP_OSPEED, &hf_ssh_pty_term_mode_ospeed }
5438
0
    };
5439
5440
0
    ti = proto_tree_add_item(tree, hf_ssh_pty_term_modes, tvb, offset, tvb_reported_length(tvb), ENC_NA);
5441
0
    term_mode_tree = proto_item_add_subtree(ti, ett_term_modes);
5442
0
    while (tvb_reported_length_remaining(tvb, offset)) {
5443
0
        ti = proto_tree_add_item(term_mode_tree, hf_ssh_pty_term_mode, tvb, offset, 5, ENC_NA);
5444
0
        subtree = proto_item_add_subtree(ti, ett_term_mode);
5445
0
        proto_tree_add_item_ret_uint(subtree, hf_ssh_pty_term_mode_opcode, tvb, offset, 1, ENC_NA, &opcode);
5446
0
        proto_item_append_text(ti, ": %s", val_to_str_const(opcode, ssh_tty_op_vals, "Unknown"));
5447
0
        offset += 1;
5448
0
        if (opcode == SSH_TTY_OP_END) {
5449
0
            break;
5450
0
        }
5451
0
        for (idx = 0; idx < array_length(tty_opts); idx++) {
5452
0
            if (tty_opts[idx].id == opcode) break;
5453
0
        }
5454
0
        if (idx >= array_length(tty_opts)) {
5455
0
            proto_tree_add_item_ret_uint(subtree, hf_ssh_pty_term_mode_value, tvb, offset, 4, ENC_BIG_ENDIAN, &value);
5456
0
            proto_item_append_text(ti, "=%d", value);
5457
0
        } else {
5458
0
            DISSECTOR_ASSERT(tty_opts[idx].hfindex);
5459
0
            int hfindex = *tty_opts[idx].hfindex;
5460
0
            switch (proto_registrar_get_ftype(hfindex)) {
5461
0
            case FT_BOOLEAN:
5462
0
                proto_tree_add_item_ret_boolean(subtree, hfindex, tvb, offset + 3, 1, ENC_NA, &boolval);
5463
0
                proto_item_append_text(ti, "=%s", boolval ? "True" : "False");
5464
0
                break;
5465
0
            case FT_CHAR:
5466
0
                proto_tree_add_item_ret_uint(subtree, hfindex, tvb, offset + 3, 1, ENC_NA, &value);
5467
0
                proto_item_append_text(ti, "='%s'", format_char(pinfo->pool, (char)value));
5468
0
                break;
5469
0
            case FT_UINT32:
5470
0
                proto_tree_add_item_ret_uint(subtree, hfindex, tvb, offset, 4, ENC_BIG_ENDIAN, &value);
5471
0
                proto_item_append_text(ti, "=%d", value);
5472
0
                break;
5473
0
            default:
5474
0
                DISSECTOR_ASSERT_NOT_REACHED();
5475
0
            }
5476
0
        }
5477
0
        offset += 4;
5478
0
    }
5479
0
    return offset;
5480
0
}
5481
5482
static int
5483
ssh_dissect_connection_specific(tvbuff_t *packet_tvb, packet_info *pinfo,
5484
        struct ssh_peer_data *peer_data, int offset, proto_tree *msg_type_tree,
5485
        unsigned msg_code, ssh_message_info_t *message)
5486
0
{
5487
0
    uint32_t recipient_channel, sender_channel;
5488
5489
0
    if (msg_code == SSH_MSG_CHANNEL_OPEN) {
5490
0
        uint32_t slen;
5491
0
        proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_connection_type_name_len, packet_tvb, offset, 4, ENC_BIG_ENDIAN, &slen);
5492
0
        offset += 4;
5493
0
        proto_tree_add_item(msg_type_tree, hf_ssh_connection_type_name, packet_tvb, offset, slen, ENC_UTF_8);
5494
0
        offset += slen;
5495
0
        proto_tree_add_item(msg_type_tree, hf_ssh_connection_sender_channel, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
5496
0
        offset += 4;
5497
0
        proto_tree_add_item(msg_type_tree, hf_ssh_connection_initial_window, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
5498
0
        offset += 4;
5499
0
        proto_tree_add_item(msg_type_tree, hf_ssh_connection_maximum_packet_size, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
5500
0
        offset += 4;
5501
0
    } else if (msg_code == SSH_MSG_CHANNEL_OPEN_CONFIRMATION) {
5502
0
        proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_connection_recipient_channel, packet_tvb, offset, 4, ENC_BIG_ENDIAN, &recipient_channel);
5503
0
        offset += 4;
5504
0
        proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_connection_sender_channel, packet_tvb, offset, 4, ENC_BIG_ENDIAN, &sender_channel);
5505
0
        offset += 4;
5506
0
        if (!PINFO_FD_VISITED(pinfo)) {
5507
0
            create_channel(peer_data, recipient_channel, sender_channel);
5508
0
        }
5509
0
        proto_tree_add_item(msg_type_tree, hf_ssh_connection_initial_window, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
5510
0
        offset += 4;
5511
0
        proto_tree_add_item(msg_type_tree, hf_ssh_connection_maximum_packet_size, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
5512
0
        offset += 4;
5513
0
    } else if (msg_code == SSH_MSG_CHANNEL_WINDOW_ADJUST) {
5514
0
        proto_tree_add_item(msg_type_tree, hf_ssh_connection_recipient_channel, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
5515
0
        offset += 4;
5516
0
        proto_tree_add_item(msg_type_tree, hf_ssh_channel_window_adjust, packet_tvb, offset, 4, ENC_BIG_ENDIAN);         // TODO: maintain count of transferred bytes and window size
5517
0
        offset += 4;
5518
0
    } else if (msg_code == SSH_MSG_CHANNEL_DATA) {
5519
0
        proto_item* ti = proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_connection_recipient_channel, packet_tvb, offset, 4, ENC_BIG_ENDIAN, &recipient_channel);
5520
0
        offset += 4;
5521
        // TODO: process according to the type of channel
5522
0
        uint32_t slen;
5523
0
        proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_channel_data_len, packet_tvb, offset, 4, ENC_BIG_ENDIAN, &slen);
5524
0
        offset += 4;
5525
0
        tvbuff_t* next_tvb = tvb_new_subset_length(packet_tvb, offset, slen);
5526
5527
0
        ssh_channel_info_t* channel = get_channel_info_for_channel(peer_data, recipient_channel);
5528
0
        if (channel) {
5529
0
            if (!PINFO_FD_VISITED(pinfo)) {
5530
0
                message->byte_seq = channel->byte_seq;
5531
0
                channel->byte_seq += slen;
5532
0
                message->next_byte_seq = channel->byte_seq;
5533
0
            }
5534
0
            ssh_dissect_channel_data(next_tvb, pinfo, peer_data, msg_type_tree, message, channel);
5535
0
        } else {
5536
0
            expert_add_info_format(pinfo, ti, &ei_ssh_channel_number, "Could not find configuration for channel %d", recipient_channel);
5537
0
        }
5538
0
        offset += slen;
5539
0
    } else if (msg_code == SSH_MSG_CHANNEL_EXTENDED_DATA) {
5540
0
        proto_item* ti = proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_connection_recipient_channel, packet_tvb, offset, 4, ENC_BIG_ENDIAN, &recipient_channel);
5541
0
        offset += 4;
5542
        // TODO: process according to the type of channel
5543
0
        proto_tree_add_item(msg_type_tree, hf_ssh_channel_data_type_code, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
5544
0
        offset += 4;
5545
0
        uint32_t slen;
5546
0
        proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_channel_data_len, packet_tvb, offset, 4, ENC_BIG_ENDIAN, &slen);
5547
0
        offset += 4;
5548
0
        tvbuff_t* next_tvb = tvb_new_subset_length(packet_tvb, offset, slen);
5549
5550
0
        ssh_channel_info_t* channel = get_channel_info_for_channel(peer_data, recipient_channel);
5551
0
        if (channel) {
5552
0
            if (!PINFO_FD_VISITED(pinfo)) {
5553
0
                message->byte_seq = channel->byte_seq;
5554
0
                channel->byte_seq += slen;
5555
0
                message->next_byte_seq = channel->byte_seq;
5556
0
            }
5557
0
            ssh_dissect_channel_data(next_tvb, pinfo, peer_data, msg_type_tree, message, channel);
5558
0
        } else {
5559
0
            expert_add_info_format(pinfo, ti, &ei_ssh_channel_number, "Could not find configuration for channel %d", recipient_channel);
5560
0
        }
5561
0
        offset += slen;
5562
0
    } else if (msg_code == SSH_MSG_CHANNEL_EOF) {
5563
0
        proto_tree_add_item(msg_type_tree, hf_ssh_connection_recipient_channel, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
5564
0
        offset += 4;
5565
0
    } else if (msg_code == SSH_MSG_CHANNEL_CLOSE) {
5566
0
        proto_tree_add_item(msg_type_tree, hf_ssh_connection_recipient_channel, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
5567
0
        offset += 4;
5568
0
    } else if (msg_code == SSH_MSG_CHANNEL_REQUEST) {
5569
0
        proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_connection_recipient_channel, packet_tvb, offset, 4, ENC_BIG_ENDIAN, &recipient_channel);
5570
0
        offset += 4;
5571
0
        const char* request_name;
5572
0
        uint32_t slen;
5573
0
        int item_len;
5574
0
        proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_channel_request_name_len, packet_tvb, offset, 4, ENC_BIG_ENDIAN, &slen);
5575
0
        offset += 4;
5576
0
        proto_tree_add_item_ret_string(msg_type_tree, hf_ssh_channel_request_name, packet_tvb, offset, slen, ENC_UTF_8, pinfo->pool, (const uint8_t**)&request_name);
5577
0
        offset += slen;
5578
0
        proto_tree_add_item(msg_type_tree, hf_ssh_channel_request_want_reply, packet_tvb, offset, 1, ENC_BIG_ENDIAN);
5579
0
        offset += 1;
5580
        /* RFC 4254 6.5: "Only one of these requests ["shell", "exec",
5581
         * or "subsystem"] can succeed per channel." Set up the
5582
         * appropriate handler for future CHANNEL_DATA and
5583
         * CHANNEL_EXTENDED_DATA messages on the channel.
5584
         *
5585
         * XXX - For "shell" and "exec", it might make more sense to send
5586
         * CHANNEL_DATA to the "data-text-lines" dissector rather than "data".
5587
         * Ideally if a pty has been setup there would be a way to interpret
5588
         * the escape codes.
5589
         */
5590
0
        if (0 == strcmp(request_name, "subsystem")) {
5591
0
            proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_subsystem_name_len, packet_tvb, offset, 4, ENC_BIG_ENDIAN, &slen);
5592
0
            offset += 4;
5593
0
            const char* subsystem_name;
5594
0
            proto_tree_add_item_ret_string(msg_type_tree, hf_ssh_subsystem_name, packet_tvb, offset, slen, ENC_UTF_8, pinfo->pool, (const uint8_t**)&subsystem_name);
5595
0
            set_subdissector_for_channel(peer_data, recipient_channel, subsystem_name);
5596
0
            offset += slen;
5597
0
        } else if (0 == strcmp(request_name, "env")) {
5598
            /* The encoding for "env" variables and "exec" commands is not
5599
             * specified in the SSH protocol, and must match whatever the
5600
             * server expects. (Unlike CHANNEL_DATA, it is not affected by
5601
             * whatever is in "env" or anything else in the protocol, and the
5602
             * strings are passed to execve directly.) In practice the strings
5603
             * must not have internal NULs (no UTF-16), and OpenSSH for Windows
5604
             * and IBM z/OS force the use of UTF-8 and ISO-8859-1, respectively.
5605
             *
5606
             * These will probably be ASCII-compatible.
5607
             */
5608
0
            proto_tree_add_item_ret_length(msg_type_tree, hf_ssh_env_name, packet_tvb, offset, 4, ENC_BIG_ENDIAN | ENC_UTF_8, &item_len);
5609
0
            offset += item_len;
5610
0
            proto_tree_add_item_ret_length(msg_type_tree, hf_ssh_env_value, packet_tvb, offset, 4, ENC_BIG_ENDIAN | ENC_UTF_8, &item_len);
5611
0
            offset += item_len;
5612
0
        } else if (0 == strcmp(request_name, "exec")) {
5613
0
            proto_tree_add_item_ret_length(msg_type_tree, hf_ssh_exec_cmd, packet_tvb, offset, 4, ENC_BIG_ENDIAN | ENC_UTF_8, &item_len);
5614
0
            offset += item_len;
5615
0
            set_subdissector_for_channel(peer_data, recipient_channel, "exec");
5616
0
        } else if (0 == strcmp(request_name, "exit-status")) {
5617
0
            proto_tree_add_item(msg_type_tree, hf_ssh_exit_status, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
5618
0
            offset += 4;
5619
0
        } else if (0 == strcmp(request_name, "shell")) {
5620
0
            set_subdissector_for_channel(peer_data, recipient_channel, "shell");
5621
0
        } else if (0 == strcmp(request_name, "pty-req")) {
5622
0
            proto_tree_add_item_ret_length(msg_type_tree, hf_ssh_pty_term, packet_tvb, offset, 4, ENC_BIG_ENDIAN | ENC_UTF_8, &item_len);
5623
0
            offset += item_len;
5624
0
            proto_tree_add_item(msg_type_tree, hf_ssh_pty_term_width_char, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
5625
0
            offset += 4;
5626
0
            proto_tree_add_item(msg_type_tree, hf_ssh_pty_term_height_row, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
5627
0
            offset += 4;
5628
0
            proto_tree_add_item(msg_type_tree, hf_ssh_pty_term_width_pixel, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
5629
0
            offset += 4;
5630
0
            proto_tree_add_item(msg_type_tree, hf_ssh_pty_term_height_pixel, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
5631
0
            offset += 4;
5632
0
            proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_pty_term_modes_len, packet_tvb, offset, 4, ENC_BIG_ENDIAN, &slen);
5633
0
            offset += 4;
5634
0
            offset += ssh_dissect_term_modes(tvb_new_subset_length(packet_tvb, offset, slen), pinfo, msg_type_tree);
5635
0
        }
5636
0
    } else if (msg_code == SSH_MSG_CHANNEL_SUCCESS) {
5637
0
        proto_tree_add_item(msg_type_tree, hf_ssh_connection_recipient_channel, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
5638
0
        offset += 4;
5639
0
    }
5640
0
    return offset;
5641
0
}
5642
5643
/* Channel mapping {{{ */
5644
5645
/* The usual flow:
5646
 * 1. client sends SSH_MSG_CHANNEL_OPEN with its (sender) channel number
5647
 * 2. server responds with SSH_MSG_CHANNEL_OPEN_CONFIRMATION with
5648
 *    its channel number and echoing the client's number, creating
5649
 *    a bijective map
5650
 * 3. client sends SSH_MSG_CHANNEL_REQUEST which has the name of
5651
 *    the shell, command, or subsystem to start. This has the recipient's
5652
 *    channel number (i.e. the server's)
5653
 * 4. server may send back a SSG_MSG_CHANNEL_SUCCESS (or _FAILURE) with
5654
 *    the the recipient (i.e., client) channel number, but this does not
5655
 *    contain the subsystem name or anything identifying the request to
5656
 *    which it responds. It MUST be sent in the same order as the
5657
 *    corresponding request message (RFC 4254 4 Global Requests), so we
5658
 *    could track it that way, but for our purposes we just treat all
5659
 *    requests as successes. (If not, either there won't be data or another
5660
 *    request will supercede it later.)
5661
 *
5662
 * Either side can open a channel (RFC 4254 5 Channel Mechanism). The
5663
 * typical flow is the client opening a channel, but in the case of
5664
 * remote port forwarding (7 TCP/IP Port Forwarding) the directions are
5665
 * swapped. For port forwarding, all the information is contained in the
5666
 * SSH_MSG_CHANNEL_OPEN, there is no SSH_MSG_CHANNEL_REQUEST.
5667
*
5668
 * XXX: Channel numbers can be re-used after being closed (5.3 Closing a
5669
 * Channel), but not necessarily mapped to the same channel number on the
5670
 * other side. If that actually happens, the right way to handle this is
5671
 * to track the state changes over time for random packet access (e.g.,
5672
 * using a multimap with the packet number instead of maps.)
5673
 */
5674
5675
static struct ssh_peer_data*
5676
get_other_peer_data(struct ssh_peer_data *peer_data)
5677
0
{
5678
0
    bool is_server = &peer_data->global_data->peer_data[SERVER_PEER_DATA]==peer_data;
5679
0
    if (is_server) {
5680
0
        return &peer_data->global_data->peer_data[CLIENT_PEER_DATA];
5681
0
    } else {
5682
0
        return &peer_data->global_data->peer_data[SERVER_PEER_DATA];
5683
0
    }
5684
0
}
5685
5686
/* Create pairings between a recipient channel and the sender's channel,
5687
 * from a SSH_MSG_CHANNEL_OPEN_CONFIRMATION. */
5688
static void
5689
create_channel(struct ssh_peer_data *peer_data, uint32_t recipient_channel, uint32_t sender_channel)
5690
0
{
5691
0
    if (peer_data->channel_info == NULL) {
5692
0
        peer_data->channel_info = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
5693
0
    }
5694
0
    wmem_map_insert(peer_data->channel_info, GUINT_TO_POINTER(sender_channel), GUINT_TO_POINTER(recipient_channel));
5695
5696
0
    if (peer_data->channel_handles == NULL) {
5697
0
        peer_data->channel_handles = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
5698
0
    }
5699
5700
0
    ssh_channel_info_t *new_channel = wmem_new0(wmem_file_scope(), ssh_channel_info_t);
5701
0
    new_channel->multisegment_pdus = wmem_tree_new(wmem_file_scope());
5702
0
    wmem_map_insert(peer_data->channel_handles, GUINT_TO_POINTER(recipient_channel), new_channel);
5703
5704
    /* If the recipient channel is already configured in the other direction,
5705
     * set the handle. We need this if we eventually handle port forwarding,
5706
     * where all the information to handle the traffic is sent in the
5707
     * SSH_MSG_CHANNEL_OPEN message before the CONFIRMATION. It might also
5708
     * help if the packets are out of order (i.e. we get the client
5709
     * CHANNEL_REQUEST before the CHANNEL_OPEN_CONFIRMATION.)
5710
     */
5711
0
    struct ssh_peer_data *other_peer_data = get_other_peer_data(peer_data);
5712
0
    if (other_peer_data->channel_handles) {
5713
0
        ssh_channel_info_t *peer_channel = wmem_map_lookup(other_peer_data->channel_handles, GUINT_TO_POINTER(sender_channel));
5714
0
        if (peer_channel) {
5715
0
            new_channel->handle = peer_channel->handle;
5716
0
        }
5717
0
    }
5718
0
}
5719
5720
static ssh_channel_info_t*
5721
get_channel_info_for_channel(struct ssh_peer_data *peer_data, uint32_t recipient_channel)
5722
0
{
5723
0
    if (peer_data->channel_handles == NULL) {
5724
0
        return NULL;
5725
0
    }
5726
0
    ssh_channel_info_t *channel = wmem_map_lookup(peer_data->channel_handles, GUINT_TO_POINTER(recipient_channel));
5727
5728
0
    return channel;
5729
0
}
5730
5731
static void
5732
set_subdissector_for_channel(struct ssh_peer_data *peer_data, uint32_t recipient_channel, const char* subsystem_name)
5733
0
{
5734
0
    dissector_handle_t handle = NULL;
5735
0
    if (0 == strcmp(subsystem_name, "sftp")) {
5736
0
        handle = sftp_handle;
5737
0
    } else if (0 == strcmp(subsystem_name, "shell") ||
5738
0
               0 == strcmp(subsystem_name, "exec")) {
5739
0
        handle = data_text_lines_handle;
5740
0
    }
5741
5742
0
    if (handle) {
5743
        /* Map this handle to the recipient channel */
5744
0
        ssh_channel_info_t *channel = NULL;
5745
0
        if (peer_data->channel_handles == NULL) {
5746
0
            peer_data->channel_handles = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
5747
0
        } else {
5748
0
            channel = wmem_map_lookup(peer_data->channel_handles, GUINT_TO_POINTER(recipient_channel));
5749
0
        }
5750
0
        if (channel == NULL) {
5751
0
            channel = wmem_new0(wmem_file_scope(), ssh_channel_info_t);
5752
0
            channel->multisegment_pdus = wmem_tree_new(wmem_file_scope());
5753
0
            wmem_map_insert(peer_data->channel_handles, GUINT_TO_POINTER(recipient_channel), channel);
5754
0
        }
5755
0
        channel->handle = handle;
5756
5757
        /* This recipient channel is the sender channel for the other side.
5758
         * Do we know what the recipient channel on the other side is?  */
5759
0
        struct ssh_peer_data *other_peer_data = get_other_peer_data(peer_data);
5760
5761
0
        wmem_map_t *channel_info = other_peer_data->channel_info;
5762
0
        if (channel_info) {
5763
0
            void *sender_channel_p;
5764
0
            if (wmem_map_lookup_extended(channel_info, GUINT_TO_POINTER(recipient_channel), NULL, &sender_channel_p)) {
5765
0
                uint32_t sender_channel = GPOINTER_TO_UINT(sender_channel_p);
5766
                /* Yes. See the handle for the other side too. */
5767
0
                if (other_peer_data->channel_handles == NULL) {
5768
0
                    other_peer_data->channel_handles = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
5769
0
                    channel = NULL;
5770
0
                } else {
5771
0
                    channel = wmem_map_lookup(other_peer_data->channel_handles, GUINT_TO_POINTER(sender_channel));
5772
0
                }
5773
0
                if (channel == NULL) {
5774
0
                    channel = wmem_new0(wmem_file_scope(), ssh_channel_info_t);
5775
0
                    channel->multisegment_pdus = wmem_tree_new(wmem_file_scope());
5776
0
                    wmem_map_insert(other_peer_data->channel_handles, GUINT_TO_POINTER(sender_channel), channel);
5777
0
                }
5778
0
                channel->handle = handle;
5779
0
            }
5780
0
        }
5781
0
    }
5782
0
}
5783
5784
/* Channel mapping. }}} */
5785
5786
static int
5787
ssh_dissect_connection_generic(tvbuff_t *packet_tvb, packet_info *pinfo,
5788
        int offset, proto_item *msg_type_tree, unsigned msg_code)
5789
0
{
5790
0
        (void)pinfo;
5791
0
        if(msg_code==SSH_MSG_GLOBAL_REQUEST){
5792
0
                const char* request_name;
5793
0
                unsigned   slen;
5794
0
                slen = tvb_get_ntohl(packet_tvb, offset) ;
5795
0
                proto_tree_add_item(msg_type_tree, hf_ssh_global_request_name_len, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
5796
0
                offset += 4;
5797
0
                request_name = (char*)tvb_get_string_enc(pinfo->pool, packet_tvb, offset, slen, ENC_ASCII|ENC_NA);
5798
0
                proto_tree_add_item(msg_type_tree, hf_ssh_global_request_name, packet_tvb, offset, slen, ENC_ASCII);
5799
0
                offset += slen;
5800
0
                proto_tree_add_item(msg_type_tree, hf_ssh_global_request_want_reply, packet_tvb, offset, 1, ENC_BIG_ENDIAN);
5801
0
                offset += 1;
5802
0
                if (0 == strcmp(request_name, "hostkeys-00@openssh.com") ||
5803
0
                    0 == strcmp(request_name, "hostkeys-prove-00@openssh.com")) {
5804
0
                    while (tvb_reported_length_remaining(packet_tvb, offset)) {
5805
0
                        offset += ssh_tree_add_hostkey(packet_tvb, pinfo, offset, msg_type_tree,
5806
0
                                "Server host key", ett_key_exchange_host_key, NULL);
5807
0
                    }
5808
0
                }
5809
0
        }
5810
0
        return offset;
5811
0
}
5812
5813
static int
5814
ssh_dissect_local_extension(tvbuff_t *packet_tvb, packet_info *pinfo,
5815
0
        int offset, struct ssh_peer_data *peer_data, proto_item *msg_type_tree, unsigned msg_code) {
5816
0
    unsigned slen;
5817
0
    if (peer_data->global_data->ext_ping_openssh_offered && msg_code >= SSH_MSG_PING && msg_code <= SSH_MSG_PONG) {
5818
0
        col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, val_to_str(pinfo->pool, msg_code, ssh2_ext_ping_msg_vals, "Unknown (%u)"));
5819
0
        proto_tree_add_item(msg_type_tree, hf_ssh2_ext_ping_msg_code, packet_tvb, offset, 1, ENC_BIG_ENDIAN);
5820
0
        offset += 1;
5821
0
        if (msg_code == SSH_MSG_PING) {
5822
0
            slen = tvb_get_ntohl(packet_tvb, offset) ;
5823
0
            proto_tree_add_item(msg_type_tree, hf_ssh_ping_data_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
5824
0
            offset += 4;
5825
0
            proto_tree_add_item(msg_type_tree, hf_ssh_ping_data, packet_tvb, offset, slen, ENC_NA);
5826
0
            offset += slen;
5827
0
        } else if (msg_code == SSH_MSG_PONG) {
5828
0
            slen = tvb_get_ntohl(packet_tvb, offset) ;
5829
0
            proto_tree_add_item(msg_type_tree, hf_ssh_pong_data_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
5830
0
            offset += 4;
5831
0
            proto_tree_add_item(msg_type_tree, hf_ssh_pong_data, packet_tvb, offset, slen, ENC_NA);
5832
0
            offset += slen;
5833
0
        }
5834
0
    } else {
5835
0
        col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, val_to_str(pinfo->pool, msg_code, ssh2_msg_vals, "Unknown (%u)"));
5836
0
        proto_tree_add_item(msg_type_tree, hf_ssh2_msg_code, packet_tvb, offset, 1, ENC_BIG_ENDIAN);
5837
0
        offset += 1;
5838
0
    }
5839
0
    return offset;
5840
0
}
5841
5842
static int
5843
ssh_dissect_public_key_blob(tvbuff_t *tvb, packet_info *pinfo, proto_item *tree)
5844
0
{
5845
0
    uint32_t slen;
5846
0
    const char* key_type;
5847
5848
0
    int offset = 0;
5849
0
    proto_tree *blob_tree = NULL;
5850
0
    proto_item *blob_item = NULL;
5851
5852
0
    blob_item = proto_tree_add_item(tree, hf_ssh_blob, tvb, offset, tvb_reported_length(tvb), ENC_NA);
5853
0
    blob_tree = proto_item_add_subtree(blob_item, ett_userauth_pk_blob);
5854
0
    proto_tree_add_item_ret_uint(blob_tree, hf_ssh_pk_blob_name_length, tvb, offset, 4, ENC_BIG_ENDIAN, &slen);
5855
0
    offset += 4;
5856
0
    proto_tree_add_item_ret_string(blob_tree, hf_ssh_pk_blob_name, tvb, offset, slen, ENC_ASCII, pinfo->pool, (const uint8_t**)&key_type);
5857
0
    proto_item_append_text(blob_item, " (type: %s)", key_type);
5858
0
    offset += slen;
5859
5860
0
    if (0 == strcmp(key_type, "ssh-rsa")) {
5861
0
        offset += ssh_tree_add_mpint(tvb, offset, blob_tree, hf_ssh_blob_e);
5862
0
        offset += ssh_tree_add_mpint(tvb, offset, blob_tree, hf_ssh_blob_n);
5863
0
    } else if (0 == strcmp(key_type, "ssh-dss")) {
5864
0
        offset += ssh_tree_add_mpint(tvb, offset, blob_tree, hf_ssh_blob_dsa_p);
5865
0
        offset += ssh_tree_add_mpint(tvb, offset, blob_tree, hf_ssh_blob_dsa_q);
5866
0
        offset += ssh_tree_add_mpint(tvb, offset, blob_tree, hf_ssh_blob_dsa_g);
5867
0
        offset += ssh_tree_add_mpint(tvb, offset, blob_tree, hf_ssh_blob_dsa_y);
5868
0
    } else if (g_str_has_prefix(key_type, "ecdsa-sha2-")) {
5869
0
        offset += ssh_tree_add_string(tvb, offset, blob_tree,
5870
0
                            hf_ssh_blob_ecdsa_curve_id, hf_ssh_blob_ecdsa_curve_id_length);
5871
0
        offset += ssh_tree_add_string(tvb, offset, blob_tree,
5872
0
                            hf_ssh_blob_ecdsa_q, hf_ssh_blob_ecdsa_q_length);
5873
0
    } else if (g_str_has_prefix(key_type, "ssh-ed")) {
5874
0
        offset += ssh_tree_add_string(tvb, offset, blob_tree,
5875
0
                            hf_ssh_blob_eddsa_key, hf_ssh_blob_eddsa_key_length);
5876
0
    } else {
5877
0
        proto_tree_add_item(blob_tree, hf_ssh_blob_data, tvb, offset, tvb_reported_length_remaining(tvb, offset), ENC_NA);
5878
0
        offset += tvb_reported_length_remaining(tvb, offset);
5879
0
    }
5880
5881
0
    return offset;
5882
0
}
5883
5884
static int
5885
ssh_dissect_public_key_signature(tvbuff_t *packet_tvb, packet_info *pinfo,
5886
        int offset, proto_item *msg_type_tree)
5887
0
{
5888
0
        (void)pinfo;
5889
0
        unsigned   slen;
5890
0
        slen = tvb_get_ntohl(packet_tvb, offset) ;
5891
0
        proto_tree_add_item(msg_type_tree, hf_ssh_pk_sig_blob_name_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
5892
0
        offset += 4;
5893
0
        proto_tree_add_item(msg_type_tree, hf_ssh_pk_sig_blob_name, packet_tvb, offset, slen, ENC_ASCII);
5894
0
        offset += slen;
5895
0
        slen = tvb_get_ntohl(packet_tvb, offset) ;
5896
0
        proto_tree_add_item(msg_type_tree, hf_ssh_pk_sig_s_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
5897
0
        offset += 4;
5898
0
        proto_tree_add_item(msg_type_tree, hf_ssh_pk_sig_s, packet_tvb, offset, slen, ENC_NA);
5899
0
        offset += slen;
5900
0
        return offset;
5901
0
}
5902
5903
#ifdef SSH_DECRYPT_DEBUG /* {{{ */
5904
5905
static FILE* ssh_debug_file;
5906
5907
static void
5908
ssh_prefs_apply_cb(void)
5909
0
{
5910
0
    ssh_set_debug(ssh_debug_file_name);
5911
0
}
5912
5913
static void
5914
ssh_set_debug(const char* name)
5915
14
{
5916
14
    static int debug_file_must_be_closed;
5917
14
    int         use_stderr;
5918
5919
14
    use_stderr                = name?(strcmp(name, SSH_DEBUG_USE_STDERR) == 0):0;
5920
5921
14
    if (debug_file_must_be_closed)
5922
0
        fclose(ssh_debug_file);
5923
5924
14
    if (use_stderr)
5925
0
        ssh_debug_file = stderr;
5926
14
    else if (!name || (strcmp(name, "") ==0))
5927
14
        ssh_debug_file = NULL;
5928
0
    else
5929
0
        ssh_debug_file = ws_fopen(name, "w");
5930
5931
14
    if (!use_stderr && ssh_debug_file)
5932
0
        debug_file_must_be_closed = 1;
5933
14
    else
5934
14
        debug_file_must_be_closed = 0;
5935
5936
14
    ssh_debug_printf("Wireshark SSH debug log \n\n");
5937
#ifdef HAVE_LIBGNUTLS
5938
    ssh_debug_printf("GnuTLS version:    %s\n", gnutls_check_version(NULL));
5939
#endif
5940
14
    ssh_debug_printf("Libgcrypt version: %s\n", gcry_check_version(NULL));
5941
14
    ssh_debug_printf("\n");
5942
14
}
5943
5944
static void
5945
ssh_debug_flush(void)
5946
27
{
5947
27
    if (ssh_debug_file)
5948
0
        fflush(ssh_debug_file);
5949
27
}
5950
5951
static void
5952
ssh_debug_printf(const char* fmt, ...)
5953
102
{
5954
102
    va_list ap;
5955
5956
102
    if (!ssh_debug_file)
5957
102
        return;
5958
5959
102
    va_start(ap, fmt);
5960
0
    vfprintf(ssh_debug_file, fmt, ap);
5961
0
    va_end(ap);
5962
0
}
5963
5964
static void
5965
ssh_print_data(const char* name, const unsigned char* data, size_t len)
5966
0
{
5967
0
    size_t i, j, k;
5968
0
    if (!ssh_debug_file)
5969
0
        return;
5970
0
#ifdef OPENSSH_STYLE
5971
0
    fprintf(ssh_debug_file,"%s[%d]\n",name, (int) len);
5972
#else
5973
    fprintf(ssh_debug_file,"%s[%d]:\n",name, (int) len);
5974
#endif
5975
0
    for (i=0; i<len; i+=16) {
5976
0
#ifdef OPENSSH_STYLE
5977
0
        fprintf(ssh_debug_file,"%04u: ", (unsigned int)i);
5978
#else
5979
        fprintf(ssh_debug_file,"| ");
5980
#endif
5981
0
        for (j=i, k=0; k<16 && j<len; ++j, ++k)
5982
0
            fprintf(ssh_debug_file,"%.2x ",data[j]);
5983
0
        for (; k<16; ++k)
5984
0
            fprintf(ssh_debug_file,"   ");
5985
0
#ifdef OPENSSH_STYLE
5986
0
        fputc(' ', ssh_debug_file);
5987
#else
5988
        fputc('|', ssh_debug_file);
5989
#endif
5990
0
        for (j=i, k=0; k<16 && j<len; ++j, ++k) {
5991
0
            unsigned char c = data[j];
5992
0
            if (!g_ascii_isprint(c) || (c=='\t')) c = '.';
5993
0
            fputc(c, ssh_debug_file);
5994
0
        }
5995
0
#ifdef OPENSSH_STYLE
5996
0
        fprintf(ssh_debug_file,"\n");
5997
#else
5998
        for (; k<16; ++k)
5999
            fputc(' ', ssh_debug_file);
6000
        fprintf(ssh_debug_file,"|\n");
6001
#endif
6002
0
    }
6003
0
}
6004
6005
#endif /* SSH_DECRYPT_DEBUG }}} */
6006
6007
static void
6008
ssh_secrets_block_callback(const void *secrets, unsigned size)
6009
0
{
6010
0
    ssh_keylog_process_lines((const uint8_t *)secrets, size);
6011
0
}
6012
6013
/* Functions for SSH random hashtables. {{{ */
6014
static int
6015
ssh_equal (const void *v, const void *v2)
6016
0
{
6017
0
    if (v == NULL || v2 == NULL) {
6018
0
        return 0;
6019
0
    }
6020
6021
0
    const ssh_bignum *val1;
6022
0
    const ssh_bignum *val2;
6023
0
    val1 = (const ssh_bignum *)v;
6024
0
    val2 = (const ssh_bignum *)v2;
6025
6026
0
    if (val1->length == val2->length &&
6027
0
        !memcmp(val1->data, val2->data, val2->length)) {
6028
0
        return 1;
6029
0
    }
6030
0
    return 0;
6031
0
}
6032
6033
static unsigned
6034
ssh_hash  (const void *v)
6035
0
{
6036
0
    unsigned l,hash;
6037
0
    const ssh_bignum* id;
6038
0
    const unsigned* cur;
6039
6040
0
    if (v == NULL) {
6041
0
        return 0;
6042
0
    }
6043
6044
0
    hash = 0;
6045
0
    id = (const ssh_bignum*) v;
6046
6047
    /*  id and id->data are mallocated in ssh_save_master_key().  As such 'data'
6048
     *  should be aligned for any kind of access (for example as a unsigned as
6049
     *  is done below).  The intermediate void* cast is to prevent "cast
6050
     *  increases required alignment of target type" warnings on CPUs (such
6051
     *  as SPARCs) that do not allow misaligned memory accesses.
6052
     */
6053
0
    cur = (const unsigned*)(void*) id->data;
6054
6055
0
    for (l=4; (l < id->length); l+=4, cur++)
6056
0
        hash = hash ^ (*cur);
6057
6058
0
    return hash;
6059
0
}
6060
6061
static void
6062
ssh_free_glib_allocated_bignum(void *data)
6063
0
{
6064
0
    ssh_bignum * bignum;
6065
0
    if (data == NULL) {
6066
0
        return;
6067
0
    }
6068
6069
0
    bignum = (ssh_bignum *) data;
6070
0
    g_free(bignum->data);
6071
0
    g_free(bignum);
6072
0
}
6073
6074
static void
6075
ssh_free_glib_allocated_entry(void *data)
6076
0
{
6077
0
    ssh_key_map_entry_t * entry;
6078
0
    if (data == NULL) {
6079
0
        return;
6080
0
    }
6081
6082
0
    entry = (ssh_key_map_entry_t *) data;
6083
0
    g_free(entry->type);
6084
0
    ssh_free_glib_allocated_bignum(entry->key_material);
6085
0
    g_free(entry);
6086
0
}
6087
/* Functions for SSH random hashtables. }}} */
6088
6089
static void
6090
0
ssh_shutdown(void) {
6091
0
    g_hash_table_destroy(ssh_master_key_map);
6092
0
}
6093
6094
void
6095
proto_register_ssh(void)
6096
14
{
6097
14
    static hf_register_info hf[] = {
6098
14
        { &hf_ssh_protocol,
6099
14
          { "Protocol", "ssh.protocol",
6100
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6101
14
            NULL, HFILL }},
6102
6103
14
        { &hf_ssh_packet_length,
6104
14
          { "Packet Length", "ssh.packet_length",
6105
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6106
14
            NULL, HFILL }},
6107
6108
14
        { &hf_ssh_packet_length_encrypted,
6109
14
          { "Packet Length (encrypted)", "ssh.packet_length_encrypted",
6110
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6111
14
            NULL, HFILL }},
6112
6113
14
        { &hf_ssh_padding_length,
6114
14
          { "Padding Length", "ssh.padding_length",
6115
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
6116
14
            NULL, HFILL }},
6117
6118
14
        { &hf_ssh_payload,
6119
14
          { "Payload", "ssh.payload",
6120
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6121
14
            NULL, HFILL }},
6122
6123
14
        { &hf_ssh_encrypted_packet,
6124
14
          { "Encrypted Packet", "ssh.encrypted_packet",
6125
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6126
14
            NULL, HFILL }},
6127
6128
14
        { &hf_ssh_padding_string,
6129
14
          { "Padding String", "ssh.padding_string",
6130
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6131
14
            NULL, HFILL }},
6132
6133
14
        { &hf_ssh_seq_num,
6134
14
          { "Sequence number", "ssh.seq_num",
6135
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6136
14
            NULL, HFILL }},
6137
6138
14
        { &hf_ssh_mac_string,
6139
14
          { "MAC", "ssh.mac",
6140
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6141
14
            "Message authentication code", HFILL }},
6142
6143
14
        { &hf_ssh_mac_status,
6144
14
          { "MAC Status", "ssh.mac.status", FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0,
6145
14
            NULL, HFILL }},
6146
6147
14
        { &hf_ssh_direction,
6148
14
          { "Direction", "ssh.direction",
6149
14
            FT_BOOLEAN, BASE_NONE, TFS(&tfs_s2c_c2s), 0x0,
6150
14
            "Message direction", HFILL }},
6151
6152
14
        { &hf_ssh_msg_code,
6153
14
          { "Message Code", "ssh.message_code",
6154
14
            FT_UINT8, BASE_DEC, VALS(ssh1_msg_vals), 0x0,
6155
14
            NULL, HFILL }},
6156
6157
14
        { &hf_ssh2_msg_code,
6158
14
          { "Message Code", "ssh.message_code",
6159
14
            FT_UINT8, BASE_DEC, VALS(ssh2_msg_vals), 0x0,
6160
14
            NULL, HFILL }},
6161
6162
14
        { &hf_ssh2_kex_dh_msg_code,
6163
14
          { "Message Code", "ssh.message_code",
6164
14
            FT_UINT8, BASE_DEC, VALS(ssh2_kex_dh_msg_vals), 0x0,
6165
14
            NULL, HFILL }},
6166
6167
14
        { &hf_ssh2_kex_dh_gex_msg_code,
6168
14
          { "Message Code", "ssh.message_code",
6169
14
            FT_UINT8, BASE_DEC, VALS(ssh2_kex_dh_gex_msg_vals), 0x0,
6170
14
            NULL, HFILL }},
6171
6172
14
        { &hf_ssh2_kex_ecdh_msg_code,
6173
14
          { "Message Code", "ssh.message_code",
6174
14
            FT_UINT8, BASE_DEC, VALS(ssh2_kex_ecdh_msg_vals), 0x0,
6175
14
            NULL, HFILL }},
6176
6177
14
        { &hf_ssh2_kex_hybrid_msg_code,
6178
14
          { "Message Code", "ssh.message_code",
6179
14
            FT_UINT8, BASE_DEC, VALS(ssh2_kex_hybrid_msg_vals), 0x0,
6180
14
            NULL, HFILL }},
6181
6182
14
        { &hf_ssh2_ext_ping_msg_code,
6183
14
          { "Message Code", "ssh.message_code",
6184
14
            FT_UINT8, BASE_DEC, VALS(ssh2_ext_ping_msg_vals), 0x0,
6185
14
            NULL, HFILL }},
6186
6187
14
        { &hf_ssh_cookie,
6188
14
          { "Cookie", "ssh.cookie",
6189
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6190
14
            NULL, HFILL }},
6191
6192
14
        { &hf_ssh_kex_algorithms,
6193
14
          { "kex_algorithms string", "ssh.kex_algorithms",
6194
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6195
14
            NULL, HFILL }},
6196
6197
14
        { &hf_ssh_server_host_key_algorithms,
6198
14
          { "server_host_key_algorithms string", "ssh.server_host_key_algorithms",
6199
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6200
14
            NULL, HFILL }},
6201
6202
14
        { &hf_ssh_encryption_algorithms_client_to_server,
6203
14
          { "encryption_algorithms_client_to_server string", "ssh.encryption_algorithms_client_to_server",
6204
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6205
14
            NULL, HFILL }},
6206
6207
14
        { &hf_ssh_encryption_algorithms_server_to_client,
6208
14
          { "encryption_algorithms_server_to_client string", "ssh.encryption_algorithms_server_to_client",
6209
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6210
14
            NULL, HFILL }},
6211
6212
14
        { &hf_ssh_mac_algorithms_client_to_server,
6213
14
          { "mac_algorithms_client_to_server string", "ssh.mac_algorithms_client_to_server",
6214
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6215
14
            NULL, HFILL }},
6216
6217
14
        { &hf_ssh_mac_algorithms_server_to_client,
6218
14
          { "mac_algorithms_server_to_client string", "ssh.mac_algorithms_server_to_client",
6219
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6220
14
            NULL, HFILL }},
6221
6222
14
        { &hf_ssh_compression_algorithms_client_to_server,
6223
14
          { "compression_algorithms_client_to_server string", "ssh.compression_algorithms_client_to_server",
6224
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6225
14
            NULL, HFILL }},
6226
6227
14
        { &hf_ssh_compression_algorithms_server_to_client,
6228
14
          { "compression_algorithms_server_to_client string", "ssh.compression_algorithms_server_to_client",
6229
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6230
14
            NULL, HFILL }},
6231
6232
14
        { &hf_ssh_languages_client_to_server,
6233
14
          { "languages_client_to_server string", "ssh.languages_client_to_server",
6234
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6235
14
            NULL, HFILL }},
6236
6237
14
        { &hf_ssh_languages_server_to_client,
6238
14
          { "languages_server_to_client string", "ssh.languages_server_to_client",
6239
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6240
14
            NULL, HFILL }},
6241
6242
14
        { &hf_ssh_kex_algorithms_length,
6243
14
          { "kex_algorithms length", "ssh.kex_algorithms_length",
6244
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6245
14
            NULL, HFILL }},
6246
6247
14
        { &hf_ssh_server_host_key_algorithms_length,
6248
14
          { "server_host_key_algorithms length", "ssh.server_host_key_algorithms_length",
6249
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6250
14
            NULL, HFILL }},
6251
6252
14
        { &hf_ssh_encryption_algorithms_client_to_server_length,
6253
14
          { "encryption_algorithms_client_to_server length", "ssh.encryption_algorithms_client_to_server_length",
6254
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6255
14
            NULL, HFILL }},
6256
6257
14
        { &hf_ssh_encryption_algorithms_server_to_client_length,
6258
14
          { "encryption_algorithms_server_to_client length", "ssh.encryption_algorithms_server_to_client_length",
6259
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6260
14
            NULL, HFILL }},
6261
6262
14
        { &hf_ssh_mac_algorithms_client_to_server_length,
6263
14
          { "mac_algorithms_client_to_server length", "ssh.mac_algorithms_client_to_server_length",
6264
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6265
14
            NULL, HFILL }},
6266
6267
14
        { &hf_ssh_mac_algorithms_server_to_client_length,
6268
14
          { "mac_algorithms_server_to_client length", "ssh.mac_algorithms_server_to_client_length",
6269
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6270
14
            NULL, HFILL }},
6271
6272
14
        { &hf_ssh_compression_algorithms_client_to_server_length,
6273
14
          { "compression_algorithms_client_to_server length", "ssh.compression_algorithms_client_to_server_length",
6274
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6275
14
            NULL, HFILL }},
6276
6277
14
        { &hf_ssh_compression_algorithms_server_to_client_length,
6278
14
          { "compression_algorithms_server_to_client length", "ssh.compression_algorithms_server_to_client_length",
6279
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6280
14
            NULL, HFILL }},
6281
6282
14
        { &hf_ssh_languages_client_to_server_length,
6283
14
          { "languages_client_to_server length", "ssh.languages_client_to_server_length",
6284
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6285
14
            NULL, HFILL }},
6286
6287
14
        { &hf_ssh_languages_server_to_client_length,
6288
14
          { "languages_server_to_client length", "ssh.languages_server_to_client_length",
6289
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6290
14
            NULL, HFILL }},
6291
6292
14
        { &hf_ssh_first_kex_packet_follows,
6293
14
          { "First KEX Packet Follows", "ssh.first_kex_packet_follows",
6294
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
6295
14
            NULL, HFILL }},
6296
6297
14
        { &hf_ssh_kex_reserved,
6298
14
          { "Reserved", "ssh.kex.reserved",
6299
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6300
14
            NULL, HFILL }},
6301
6302
14
        { &hf_ssh_kex_hassh_algo,
6303
14
          { "hasshAlgorithms", "ssh.kex.hassh_algorithms",
6304
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6305
14
            NULL, HFILL }},
6306
6307
14
        { &hf_ssh_kex_hassh,
6308
14
          { "hassh", "ssh.kex.hassh",
6309
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6310
14
            NULL, HFILL }},
6311
6312
14
        { &hf_ssh_kex_hasshserver_algo,
6313
14
          { "hasshServerAlgorithms", "ssh.kex.hasshserver_algorithms",
6314
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6315
14
            NULL, HFILL }},
6316
6317
14
        { &hf_ssh_kex_hasshserver,
6318
14
          { "hasshServer", "ssh.kex.hasshserver",
6319
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6320
14
            NULL, HFILL }},
6321
6322
14
        { &hf_ssh_hostkey_length,
6323
14
          { "Host key length", "ssh.host_key.length",
6324
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6325
14
            NULL, HFILL }},
6326
6327
14
        { &hf_ssh_hostkey_type_length,
6328
14
          { "Host key type length", "ssh.host_key.type_length",
6329
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6330
14
            NULL, HFILL }},
6331
6332
14
        { &hf_ssh_hostkey_type,
6333
14
          { "Host key type", "ssh.host_key.type",
6334
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6335
14
            NULL, HFILL }},
6336
6337
14
        { &hf_ssh_hostkey_data,
6338
14
          { "Host key data", "ssh.host_key.data",
6339
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6340
14
            NULL, HFILL }},
6341
6342
14
        { &hf_ssh_hostkey_rsa_n,
6343
14
          { "RSA modulus (N)", "ssh.host_key.rsa.n",
6344
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6345
14
            NULL, HFILL }},
6346
6347
14
        { &hf_ssh_hostkey_rsa_e,
6348
14
          { "RSA public exponent (e)", "ssh.host_key.rsa.e",
6349
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6350
14
            NULL, HFILL }},
6351
6352
14
        { &hf_ssh_hostkey_dsa_p,
6353
14
          { "DSA prime modulus (p)", "ssh.host_key.dsa.p",
6354
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6355
14
            NULL, HFILL }},
6356
6357
14
        { &hf_ssh_hostkey_dsa_q,
6358
14
          { "DSA prime divisor (q)", "ssh.host_key.dsa.q",
6359
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6360
14
            NULL, HFILL }},
6361
6362
14
        { &hf_ssh_hostkey_dsa_g,
6363
14
          { "DSA subgroup generator (g)", "ssh.host_key.dsa.g",
6364
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6365
14
            NULL, HFILL }},
6366
6367
14
        { &hf_ssh_hostkey_dsa_y,
6368
14
          { "DSA public key (y)", "ssh.host_key.dsa.y",
6369
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6370
14
            NULL, HFILL }},
6371
6372
14
        { &hf_ssh_hostkey_ecdsa_curve_id,
6373
14
          { "ECDSA elliptic curve identifier", "ssh.host_key.ecdsa.id",
6374
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6375
14
            NULL, HFILL }},
6376
6377
14
        { &hf_ssh_hostkey_ecdsa_curve_id_length,
6378
14
          { "ECDSA elliptic curve identifier length", "ssh.host_key.ecdsa.id_length",
6379
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6380
14
            NULL, HFILL }},
6381
6382
14
        { &hf_ssh_hostkey_ecdsa_q,
6383
14
          { "ECDSA public key (Q)", "ssh.host_key.ecdsa.q",
6384
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6385
14
            NULL, HFILL }},
6386
6387
14
        { &hf_ssh_hostkey_ecdsa_q_length,
6388
14
          { "ECDSA public key length", "ssh.host_key.ecdsa.q_length",
6389
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6390
14
            NULL, HFILL }},
6391
6392
14
        { &hf_ssh_hostkey_eddsa_key,
6393
14
          { "EdDSA public key", "ssh.host_key.eddsa.key",
6394
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6395
14
            NULL, HFILL }},
6396
6397
14
        { &hf_ssh_hostkey_eddsa_key_length,
6398
14
          { "EdDSA public key length", "ssh.host_key.eddsa.key_length",
6399
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6400
14
            NULL, HFILL }},
6401
6402
14
        { &hf_ssh_hostsig_length,
6403
14
          { "Host signature length", "ssh.host_sig.length",
6404
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6405
14
            NULL, HFILL }},
6406
6407
14
        { &hf_ssh_hostsig_type_length,
6408
14
          { "Host signature type length", "ssh.host_sig.type_length",
6409
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6410
14
            NULL, HFILL }},
6411
6412
14
        { &hf_ssh_hostsig_type,
6413
14
          { "Host signature type", "ssh.host_sig.type",
6414
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6415
14
            NULL, HFILL }},
6416
6417
14
        { &hf_ssh_hostsig_data_length,
6418
14
          { "Host signature data length", "ssh.host_sig.data_length",
6419
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6420
14
            NULL, HFILL }},
6421
6422
14
        { &hf_ssh_hostsig_data,
6423
14
          { "Host signature data", "ssh.host_sig.data",
6424
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6425
14
            NULL, HFILL }},
6426
6427
14
        { &hf_ssh_hostsig_rsa,
6428
14
          { "RSA signature", "ssh.host_sig.rsa",
6429
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6430
14
            NULL, HFILL }},
6431
6432
14
        { &hf_ssh_hostsig_dsa,
6433
14
          { "DSA signature", "ssh.host_sig.dsa",
6434
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6435
14
            NULL, HFILL }},
6436
6437
14
        { &hf_ssh_dh_e,
6438
14
          { "DH client e", "ssh.dh.e",
6439
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6440
14
            NULL, HFILL }},
6441
6442
14
        { &hf_ssh_dh_f,
6443
14
          { "DH server f", "ssh.dh.f",
6444
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6445
14
            NULL, HFILL }},
6446
6447
14
        { &hf_ssh_dh_gex_min,
6448
14
          { "DH GEX Min", "ssh.dh_gex.min",
6449
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6450
14
            "Minimal acceptable group size", HFILL }},
6451
6452
14
        { &hf_ssh_dh_gex_nbits,
6453
14
          { "DH GEX Number of Bits", "ssh.dh_gex.nbits",
6454
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6455
14
            "Preferred group size", HFILL }},
6456
6457
14
        { &hf_ssh_dh_gex_max,
6458
14
          { "DH GEX Max", "ssh.dh_gex.max",
6459
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6460
14
            "Maximal acceptable group size", HFILL }},
6461
6462
14
        { &hf_ssh_dh_gex_p,
6463
14
          { "DH GEX modulus (P)", "ssh.dh_gex.p",
6464
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6465
14
            NULL, HFILL }},
6466
6467
14
        { &hf_ssh_dh_gex_g,
6468
14
          { "DH GEX base (G)", "ssh.dh_gex.g",
6469
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6470
14
            NULL, HFILL }},
6471
6472
14
        { &hf_ssh_ecdh_q_c,
6473
14
          { "ECDH client's ephemeral public key (Q_C)", "ssh.ecdh.q_c",
6474
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6475
14
            NULL, HFILL }},
6476
6477
14
        { &hf_ssh_ecdh_q_c_length,
6478
14
          { "ECDH client's ephemeral public key length", "ssh.ecdh.q_c_length",
6479
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6480
14
            NULL, HFILL }},
6481
6482
14
        { &hf_ssh_ecdh_q_s,
6483
14
          { "ECDH server's ephemeral public key (Q_S)", "ssh.ecdh.q_s",
6484
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6485
14
            NULL, HFILL }},
6486
6487
14
        { &hf_ssh_ecdh_q_s_length,
6488
14
          { "ECDH server's ephemeral public key length", "ssh.ecdh.q_s_length",
6489
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6490
14
            NULL, HFILL }},
6491
6492
14
        { &hf_ssh_mpint_length,
6493
14
          { "Multi Precision Integer Length", "ssh.mpint_length",
6494
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6495
14
            NULL, HFILL }},
6496
6497
14
        { &hf_ssh_ignore_data_length,
6498
14
          { "Debug message length", "ssh.ignore_data_length",
6499
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6500
14
            NULL, HFILL }},
6501
6502
14
        { &hf_ssh_ignore_data,
6503
14
          { "Ignore data", "ssh.ignore_data",
6504
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6505
14
            NULL, HFILL }},
6506
6507
14
        { &hf_ssh_debug_always_display,
6508
14
          { "Always Display", "ssh.debug_always_display",
6509
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
6510
14
            NULL, HFILL }},
6511
6512
14
        { &hf_ssh_debug_message_length,
6513
14
          { "Debug message length", "ssh.debug_name_length",
6514
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6515
14
            NULL, HFILL }},
6516
6517
14
        { &hf_ssh_debug_message,
6518
14
          { "Debug message", "ssh.debug_name",
6519
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6520
14
            NULL, HFILL }},
6521
6522
14
        { &hf_ssh_service_name_length,
6523
14
          { "Service Name length", "ssh.service_name_length",
6524
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6525
14
            NULL, HFILL }},
6526
6527
14
        { &hf_ssh_service_name,
6528
14
          { "Service Name", "ssh.service_name",
6529
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6530
14
            NULL, HFILL }},
6531
6532
14
        { &hf_ssh_disconnect_reason,
6533
14
          { "Disconnect reason", "ssh.disconnect_reason",
6534
14
            FT_UINT32, BASE_HEX, NULL, 0x0,
6535
14
            NULL, HFILL }},
6536
6537
14
        { &hf_ssh_disconnect_description_length,
6538
14
          { "Disconnect description length", "ssh.disconnect_description_length",
6539
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6540
14
            NULL, HFILL }},
6541
6542
14
        { &hf_ssh_disconnect_description,
6543
14
          { "Disconnect description", "ssh.disconnect_description",
6544
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6545
14
            NULL, HFILL }},
6546
6547
14
        { &hf_ssh_ext_count,
6548
14
          { "Extension count", "ssh.extension.count",
6549
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6550
14
            NULL, HFILL }},
6551
6552
14
        { &hf_ssh_ext_name_length,
6553
14
          { "Extension name length", "ssh.extension.name_length",
6554
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6555
14
            NULL, HFILL }},
6556
6557
14
        { &hf_ssh_ext_name,
6558
14
          { "Extension name", "ssh.extension.name",
6559
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6560
14
            NULL, HFILL }},
6561
6562
14
        { &hf_ssh_ext_value_length,
6563
14
          { "Extension value length", "ssh.extension.value_length",
6564
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6565
14
            NULL, HFILL }},
6566
6567
14
        { &hf_ssh_ext_value,
6568
14
          { "Extension value", "ssh.extension.value",
6569
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6570
14
            NULL, HFILL }},
6571
6572
14
        { &hf_ssh_ext_server_sig_algs_algorithms,
6573
14
          { "Accepted signature algorithms", "ssh.extension.server_sig_algs.algorithms",
6574
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6575
14
            NULL, HFILL }},
6576
6577
14
        { &hf_ssh_ext_delay_compression_algorithms_client_to_server_length,
6578
14
          { "Compression algorithms (client to server) length", "ssh.extension.delay_compression.compression_algorithms_client_to_server_length",
6579
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6580
14
            NULL, HFILL }},
6581
6582
14
        { &hf_ssh_ext_delay_compression_algorithms_client_to_server,
6583
14
          { "Compression algorithms (client to server)", "ssh.extension.delay_compression.compression_algorithms_client_to_server",
6584
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6585
14
            NULL, HFILL }},
6586
6587
14
        { &hf_ssh_ext_delay_compression_algorithms_server_to_client_length,
6588
14
          { "Compression algorithms (server to client) length", "ssh.extension.delay_compression.compression_algorithms_server_to_client_length",
6589
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6590
14
            NULL, HFILL }},
6591
6592
14
        { &hf_ssh_ext_delay_compression_algorithms_server_to_client,
6593
14
          { "Compression algorithms (server to client)", "ssh.extension.delay_compression.compression_algorithms_server_to_client",
6594
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6595
14
            NULL, HFILL }},
6596
6597
14
        { &hf_ssh_ext_no_flow_control_value,
6598
14
          { "No flow control flag", "ssh.extension.no_flow_control.value",
6599
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6600
14
            NULL, HFILL }},
6601
6602
14
        { &hf_ssh_ext_elevation_value,
6603
14
          { "Elevation flag", "ssh.extension.elevation.value",
6604
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6605
14
            NULL, HFILL }},
6606
6607
14
        { &hf_ssh_ext_prop_publickey_algorithms_algorithms,
6608
14
          { "Public key algorithms", "ssh.extension.prop_publickey_algorithms.algorithms",
6609
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6610
14
            NULL, HFILL }},
6611
6612
14
        { &hf_ssh_lang_tag_length,
6613
14
          { "Language tag length", "ssh.lang_tag_length",
6614
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6615
14
            NULL, HFILL }},
6616
6617
14
        { &hf_ssh_lang_tag,
6618
14
          { "Language tag", "ssh.lang_tag",
6619
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6620
14
            NULL, HFILL }},
6621
6622
14
        { &hf_ssh_ping_data_length,
6623
14
          { "Data length", "ssh.ping_data_length",
6624
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6625
14
            NULL, HFILL }},
6626
6627
14
        { &hf_ssh_ping_data,
6628
14
          { "Data", "ssh.ping_data",
6629
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6630
14
            NULL, HFILL }},
6631
6632
14
        { &hf_ssh_pong_data_length,
6633
14
          { "Data length", "ssh.pong_data_length",
6634
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6635
14
            NULL, HFILL }},
6636
6637
14
        { &hf_ssh_pong_data,
6638
14
          { "Data", "ssh.pong_data",
6639
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6640
14
            NULL, HFILL }},
6641
6642
6643
14
        { &hf_ssh_userauth_user_name_length,
6644
14
          { "User Name length", "ssh.userauth_user_name_length",
6645
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6646
14
            NULL, HFILL }},
6647
6648
14
        { &hf_ssh_userauth_user_name,
6649
14
          { "User Name", "ssh.userauth_user_name",
6650
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6651
14
            NULL, HFILL }},
6652
6653
14
        { &hf_ssh_userauth_change_password,
6654
14
          { "Change password", "ssh.userauth.change_password",
6655
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
6656
14
            NULL, HFILL }},
6657
6658
14
        { &hf_ssh_userauth_service_name_length,
6659
14
          { "Service Name length", "ssh.userauth_service_name_length",
6660
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6661
14
            NULL, HFILL }},
6662
6663
14
        { &hf_ssh_userauth_service_name,
6664
14
          { "Service Name", "ssh.userauth_service_name",
6665
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6666
14
            NULL, HFILL }},
6667
6668
14
        { &hf_ssh_userauth_method_name_length,
6669
14
          { "Method Name length", "ssh.userauth_method_name_length",
6670
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6671
14
            NULL, HFILL }},
6672
6673
14
        { &hf_ssh_userauth_method_name,
6674
14
          { "Method Name", "ssh.userauth_method_name",
6675
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6676
14
            NULL, HFILL }},
6677
6678
14
        { &hf_ssh_userauth_have_signature,
6679
14
          { "Have signature", "ssh.userauth.have_signature",
6680
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
6681
14
            NULL, HFILL }},
6682
6683
14
        { &hf_ssh_userauth_password_length,
6684
14
          { "Password length", "ssh.userauth_password_length",
6685
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6686
14
            NULL, HFILL }},
6687
6688
14
        { &hf_ssh_userauth_password,
6689
14
          { "Password", "ssh.userauth_password",
6690
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6691
14
            NULL, HFILL }},
6692
6693
14
        { &hf_ssh_userauth_new_password_length,
6694
14
          { "New password length", "ssh.userauth_new_password_length",
6695
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6696
14
            NULL, HFILL }},
6697
6698
14
        { &hf_ssh_userauth_new_password,
6699
14
          { "New password", "ssh.userauth_new_password",
6700
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6701
14
            NULL, HFILL }},
6702
6703
14
        { &hf_ssh_auth_failure_list_length,
6704
14
          { "Authentications that can continue list len", "ssh.auth_failure_cont_list_length",
6705
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6706
14
            NULL, HFILL }},
6707
6708
14
        { &hf_ssh_auth_failure_list,
6709
14
          { "Authentications that can continue list", "ssh.auth_failure_cont_list",
6710
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6711
14
            NULL, HFILL }},
6712
6713
14
        { &hf_ssh_userauth_partial_success,
6714
14
          { "Partial success", "ssh.userauth.partial_success",
6715
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
6716
14
            NULL, HFILL }},
6717
6718
14
        { &hf_ssh_userauth_pka_name_len,
6719
14
          { "Public key algorithm name length", "ssh.userauth_pka_name_length",
6720
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6721
14
            NULL, HFILL }},
6722
6723
14
        { &hf_ssh_userauth_pka_name,
6724
14
          { "Public key algorithm name", "ssh.userauth_pka_name",
6725
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6726
14
            NULL, HFILL }},
6727
6728
14
        { &hf_ssh_pk_blob_name_length,
6729
14
          { "Public key blob algorithm name length", "ssh.pk_blob_name_length",
6730
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6731
14
            NULL, HFILL }},
6732
6733
14
        { &hf_ssh_pk_blob_name,
6734
14
          { "Public key blob algorithm name", "ssh.pk_blob_name",
6735
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6736
14
            NULL, HFILL }},
6737
6738
14
        { &hf_ssh_blob_length,
6739
14
          { "Public key blob length", "ssh.pk_blob_length",
6740
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6741
14
            NULL, HFILL }},
6742
6743
14
        { &hf_ssh_blob,
6744
14
          { "Public key blob", "ssh.pk_blob",
6745
14
            FT_NONE, BASE_NONE, NULL, 0x0,
6746
14
            NULL, HFILL }},
6747
6748
14
        { &hf_ssh_blob_e,
6749
14
          { "ssh-rsa public exponent (e)", "ssh.pk_blob.ssh-rsa.e",
6750
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6751
14
            NULL, HFILL }},
6752
6753
14
        { &hf_ssh_blob_n,
6754
14
          { "ssh-rsa modulus (n)", "ssh.pk_blob.ssh-rsa.n",
6755
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6756
14
            NULL, HFILL }},
6757
6758
14
        { &hf_ssh_blob_dsa_p,
6759
14
          { "DSA prime modulus (p)", "ssh.pk_blob.dsa.p",
6760
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6761
14
            NULL, HFILL }},
6762
6763
14
        { &hf_ssh_blob_dsa_q,
6764
14
          { "DSA prime divisor (q)", "ssh.pk_blob.dsa.q",
6765
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6766
14
            NULL, HFILL }},
6767
6768
14
        { &hf_ssh_blob_dsa_g,
6769
14
          { "DSA subgroup generator (g)", "ssh.pk_blob.dsa.g",
6770
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6771
14
            NULL, HFILL }},
6772
6773
14
        { &hf_ssh_blob_dsa_y,
6774
14
          { "DSA public key (y)", "ssh.pk_blob.dsa.y",
6775
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6776
14
            NULL, HFILL }},
6777
6778
14
        { &hf_ssh_blob_ecdsa_curve_id,
6779
14
          { "ECDSA elliptic curve identifier", "ssh.pk_blob.ecdsa.id",
6780
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6781
14
            NULL, HFILL }},
6782
6783
14
        { &hf_ssh_blob_ecdsa_curve_id_length,
6784
14
          { "ECDSA elliptic curve identifier length", "ssh.pk_blob.ecdsa.id_length",
6785
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6786
14
            NULL, HFILL }},
6787
6788
14
        { &hf_ssh_blob_ecdsa_q,
6789
14
          { "ECDSA public key (Q)", "ssh.pk_blob.ecdsa.q",
6790
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6791
14
            NULL, HFILL }},
6792
6793
14
        { &hf_ssh_blob_ecdsa_q_length,
6794
14
          { "ECDSA public key length", "ssh.pk_blob.ecdsa.q_length",
6795
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6796
14
            NULL, HFILL }},
6797
6798
14
        { &hf_ssh_blob_eddsa_key,
6799
14
          { "EdDSA public key", "ssh.pk_blob.eddsa.key",
6800
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6801
14
            NULL, HFILL }},
6802
6803
14
        { &hf_ssh_blob_eddsa_key_length,
6804
14
          { "EdDSA public key length", "ssh.pk_blob.eddsa.key_length",
6805
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6806
14
            NULL, HFILL }},
6807
6808
14
        { &hf_ssh_blob_data,
6809
14
          { "Public key blob data", "ssh.pk_blob.data",
6810
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6811
14
            NULL, HFILL }},
6812
6813
14
        { &hf_ssh_signature_length,
6814
14
          { "Public key signature blob length", "ssh.pk_sig_blob_length",
6815
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6816
14
            NULL, HFILL }},
6817
6818
14
        { &hf_ssh_pk_sig_blob_name_length,
6819
14
          { "Public key signature blob algorithm name length", "ssh.pk_sig_blob_name_length",
6820
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6821
14
            NULL, HFILL }},
6822
6823
14
        { &hf_ssh_pk_sig_blob_name,
6824
14
          { "Public key signature blob algorithm name", "ssh.pk_sig_blob_name",
6825
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6826
14
            NULL, HFILL }},
6827
6828
14
        { &hf_ssh_pk_sig_s_length,
6829
14
          { "ssh-rsa signature length", "ssh.sig.ssh-rsa.length",
6830
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6831
14
            NULL, HFILL }},
6832
6833
14
        { &hf_ssh_pk_sig_s,
6834
14
          { "ssh-rsa signature (s)", "ssh.sig.ssh-rsa.s",
6835
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
6836
14
            NULL, HFILL }},
6837
6838
14
        { &hf_ssh_connection_type_name_len,
6839
14
          { "Channel type name length", "ssh.connection_type_name_length",
6840
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6841
14
            NULL, HFILL }},
6842
6843
14
        { &hf_ssh_connection_type_name,
6844
14
          { "Channel type name", "ssh.connection_type_name",
6845
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6846
14
            NULL, HFILL }},
6847
6848
14
        { &hf_ssh_connection_sender_channel,
6849
14
          { "Sender channel", "ssh.connection_sender_channel",
6850
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6851
14
            NULL, HFILL }},
6852
6853
14
        { &hf_ssh_connection_recipient_channel,
6854
14
          { "Recipient channel", "ssh.connection_recipient_channel",
6855
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6856
14
            NULL, HFILL }},
6857
6858
14
        { &hf_ssh_connection_initial_window,
6859
14
          { "Initial window size", "ssh.connection_initial_window_size",
6860
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6861
14
            NULL, HFILL }},
6862
6863
14
        { &hf_ssh_connection_maximum_packet_size,
6864
14
          { "Maximum packet size", "ssh.userauth_maximum_packet_size",
6865
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6866
14
            NULL, HFILL }},
6867
6868
14
        { &hf_ssh_global_request_name_len,
6869
14
          { "Global request name length", "ssh.global_request_name_length",
6870
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6871
14
            NULL, HFILL }},
6872
6873
14
        { &hf_ssh_global_request_name,
6874
14
          { "Global request name", "ssh.global_request_name",
6875
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6876
14
            NULL, HFILL }},
6877
6878
14
        { &hf_ssh_global_request_want_reply,
6879
14
          { "Global request want reply", "ssh.global_request_want_reply",
6880
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
6881
14
            NULL, HFILL }},
6882
6883
14
        { &hf_ssh_global_request_hostkeys_array_len,
6884
14
          { "Host keys array length", "ssh.global_request_hostkeys",
6885
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6886
14
            NULL, HFILL }},
6887
6888
14
        { &hf_ssh_channel_request_name_len,
6889
14
          { "Channel request name length", "ssh.channel_request_name_length",
6890
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6891
14
            NULL, HFILL }},
6892
6893
14
        { &hf_ssh_channel_request_name,
6894
14
          { "Channel request name", "ssh.channel_request_name",
6895
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6896
14
            NULL, HFILL }},
6897
6898
14
        { &hf_ssh_channel_request_want_reply,
6899
14
          { "Channel request want reply", "ssh.channel_request_want_reply",
6900
14
            FT_UINT8, BASE_DEC, NULL, 0x0,
6901
14
            NULL, HFILL }},
6902
6903
14
        { &hf_ssh_subsystem_name_len,
6904
14
          { "Subsystem name length", "ssh.subsystem_name_length",
6905
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6906
14
            NULL, HFILL }},
6907
6908
14
        { &hf_ssh_subsystem_name,
6909
14
          { "Subsystem name", "ssh.subsystem_name",
6910
14
            FT_STRING, BASE_NONE, NULL, 0x0,
6911
14
            NULL, HFILL }},
6912
6913
14
        { &hf_ssh_exec_cmd,
6914
14
          { "Command", "ssh.exec_command",
6915
14
            FT_UINT_STRING, BASE_NONE, NULL, 0x0,
6916
14
            NULL, HFILL } },
6917
6918
14
        { &hf_ssh_env_name,
6919
14
          { "Variable name", "ssh.env_name",
6920
14
            FT_UINT_STRING, BASE_NONE, NULL, 0x0,
6921
14
            NULL, HFILL } },
6922
6923
14
        { &hf_ssh_env_value,
6924
14
          { "Variable value", "ssh.env_value",
6925
14
            FT_UINT_STRING, BASE_NONE, NULL, 0x0,
6926
14
            NULL, HFILL } },
6927
6928
14
        { &hf_ssh_pty_term,
6929
14
          { "TERM environment variable", "ssh.pty_term",
6930
14
            FT_UINT_STRING, BASE_NONE, NULL, 0x0,
6931
14
            NULL, HFILL } },
6932
6933
14
        { &hf_ssh_pty_term_width_char,
6934
14
          { "Terminal width, characters", "ssh.pty_term_width_char",
6935
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6936
14
            NULL, HFILL } },
6937
6938
14
        { &hf_ssh_pty_term_height_row,
6939
14
          { "Terminal height, rows", "ssh.pty_term_height_row",
6940
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6941
14
            NULL, HFILL } },
6942
6943
14
        { &hf_ssh_pty_term_width_pixel,
6944
14
          { "Terminal width, pixels", "ssh.pty_term_width_pixel",
6945
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6946
14
            NULL, HFILL } },
6947
6948
14
        { &hf_ssh_pty_term_height_pixel,
6949
14
          { "Terminal height, pixels", "ssh.pty_term_height_pixel",
6950
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6951
14
            NULL, HFILL } },
6952
6953
14
        { &hf_ssh_pty_term_modes_len,
6954
14
          { "Encoded Terminal Modes Length", "ssh.pty_term_modes_length",
6955
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
6956
14
            NULL, HFILL } },
6957
6958
14
        { &hf_ssh_pty_term_modes,
6959
14
          { "Encoded Terminal Modes", "ssh.pty_term_modes",
6960
14
            FT_NONE, BASE_NONE, NULL, 0x0,
6961
14
            NULL, HFILL } },
6962
6963
14
        { &hf_ssh_pty_term_mode,
6964
14
          { "Mode", "ssh.pty_term_mode",
6965
14
            FT_NONE, BASE_NONE, NULL, 0x0,
6966
14
            NULL, HFILL } },
6967
6968
14
        { &hf_ssh_pty_term_mode_opcode,
6969
14
          { "Opcode", "ssh.pty_term_mode.opcode",
6970
14
            FT_UINT8, BASE_DEC, VALS(ssh_tty_op_vals), 0x0,
6971
14
            NULL, HFILL } },
6972
6973
14
        { &hf_ssh_pty_term_mode_vintr,
6974
14
          { "Interrupt character", "ssh.pty_term_mode.vintr",
6975
14
            FT_CHAR, BASE_HEX, NULL, 0x0,
6976
14
            NULL, HFILL } },
6977
6978
14
        { &hf_ssh_pty_term_mode_vquit,
6979
14
          { "Quit character", "ssh.pty_term_mode.vquit",
6980
14
            FT_CHAR, BASE_HEX, NULL, 0x0,
6981
14
            "Sends SIGQUIT on POSIX systems", HFILL}},
6982
6983
14
        { &hf_ssh_pty_term_mode_verase,
6984
14
          { "Erase the character to the left of the cursor", "ssh.pty_term_mode.verase",
6985
14
            FT_CHAR, BASE_HEX, NULL, 0x0,
6986
14
            NULL, HFILL} },
6987
6988
14
        { &hf_ssh_pty_term_mode_vkill,
6989
14
          { "Kill the current input line", "ssh.pty_term_mode.vkill",
6990
14
            FT_CHAR, BASE_HEX, NULL, 0x0,
6991
14
            NULL, HFILL} },
6992
6993
14
        { &hf_ssh_pty_term_mode_veof,
6994
14
          { "End-of-file character", "ssh.pty_term_mode.veof",
6995
14
            FT_CHAR, BASE_HEX, NULL, 0x0,
6996
14
            "Sends EOF from the terminal", HFILL}},
6997
6998
14
        { &hf_ssh_pty_term_mode_veol,
6999
14
          { "End-of-line character", "ssh.pty_term_mode.veol",
7000
14
            FT_CHAR, BASE_HEX, NULL, 0x0,
7001
14
            "In additional to carriage return and/or line feed", HFILL} },
7002
7003
14
        { &hf_ssh_pty_term_mode_veol2,
7004
14
          { "Additional end-of-line character", "ssh.pty_term_mode.veol2",
7005
14
            FT_CHAR, BASE_HEX, NULL, 0x0,
7006
14
            NULL, HFILL} },
7007
7008
14
        { &hf_ssh_pty_term_mode_vstart,
7009
14
          { "Continues paused output", "ssh.pty_term_mode.vstart",
7010
14
            FT_CHAR, BASE_HEX, NULL, 0x0,
7011
14
            "Normally Control-Q", HFILL}},
7012
7013
14
        { &hf_ssh_pty_term_mode_vstop,
7014
14
          { "Pauses output", "ssh.pty_term_mode.vstop",
7015
14
            FT_CHAR, BASE_HEX, NULL, 0x0,
7016
14
            "Normally Control-S", HFILL} },
7017
7018
14
        { &hf_ssh_pty_term_mode_vsusp,
7019
14
          { "Suspends the current program", "ssh.pty_term_mode.vsusp",
7020
14
            FT_CHAR, BASE_HEX, NULL, 0x0,
7021
14
            NULL, HFILL} },
7022
7023
14
        { &hf_ssh_pty_term_mode_vdsusp,
7024
14
          { "Another suspend character", "ssh.pty_term_mode.vdsusp",
7025
14
            FT_CHAR, BASE_HEX, NULL, 0x0,
7026
14
            NULL, HFILL} },
7027
7028
14
        { &hf_ssh_pty_term_mode_vreprint,
7029
14
          { "Reprints the current input line", "ssh.pty_term_mode.vreprint",
7030
14
            FT_CHAR, BASE_HEX, NULL, 0x0,
7031
14
            NULL, HFILL} },
7032
7033
14
        { &hf_ssh_pty_term_mode_vwerase,
7034
14
          { "Erase a word to the left of the cursor", "ssh.pty_term_mode.vwerase",
7035
14
            FT_CHAR, BASE_HEX, NULL, 0x0,
7036
14
            NULL, HFILL} },
7037
7038
14
        { &hf_ssh_pty_term_mode_vlnext,
7039
14
          { "Enter the next character typed literally", "ssh.pty_term_mode.vlnext",
7040
14
            FT_CHAR, BASE_HEX, NULL, 0x0,
7041
14
            "Even if a special character", HFILL} },
7042
7043
14
        { &hf_ssh_pty_term_mode_vflush,
7044
14
          { "Character to flush output", "ssh.pty_term_mode.vflush",
7045
14
            FT_CHAR, BASE_HEX, NULL, 0x0,
7046
14
            NULL, HFILL} },
7047
7048
14
        { &hf_ssh_pty_term_mode_vswtch,
7049
14
          { "Switch to a different shell layer", "ssh.pty_term_mode.vswtch",
7050
14
            FT_CHAR, BASE_HEX, NULL, 0x0,
7051
14
            NULL, HFILL} },
7052
7053
14
        { &hf_ssh_pty_term_mode_vstatus,
7054
14
          { "Print system status line", "ssh.pty_term_mode.vstatus",
7055
14
            FT_CHAR, BASE_HEX, NULL, 0x0,
7056
14
            "Load, command, pid, etc.", HFILL}},
7057
7058
14
        { &hf_ssh_pty_term_mode_vdiscard,
7059
14
          { "Toggles the flushing of terminal output", "ssh.pty_term_mode.vdiscard",
7060
14
            FT_CHAR, BASE_HEX, NULL, 0x0,
7061
14
            NULL, HFILL} },
7062
7063
14
        { &hf_ssh_pty_term_mode_ignpar,
7064
14
          { "Ignore parity flag", "ssh.pty_term_mode.ignpar",
7065
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7066
14
            NULL, HFILL } },
7067
7068
14
        { &hf_ssh_pty_term_mode_parmrk,
7069
14
          { "Mark parity and framing errors", "ssh.pty_term_mode.parmrk",
7070
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7071
14
            NULL, HFILL } },
7072
7073
14
        { &hf_ssh_pty_term_mode_inpck,
7074
14
          { "Enable checking of parity errors", "ssh.pty_term_mode.inpck",
7075
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7076
14
            NULL, HFILL } },
7077
7078
14
        { &hf_ssh_pty_term_mode_istrip,
7079
14
          { "Strip 8th bit off characters", "ssh.pty_term_mode.istrip",
7080
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7081
14
            NULL, HFILL } },
7082
7083
14
        { &hf_ssh_pty_term_mode_inlcr,
7084
14
          { "Map NL into CR on input", "ssh.pty_term_mode.inlcr",
7085
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7086
14
            NULL, HFILL } },
7087
7088
14
        { &hf_ssh_pty_term_mode_igncr,
7089
14
          { "Ignore CR on input", "ssh.pty_term_mode.igncr",
7090
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7091
14
            NULL, HFILL } },
7092
7093
14
        { &hf_ssh_pty_term_mode_icrnl,
7094
14
          { "Map CR to NL on input", "ssh.pty_term_mode.icrnl",
7095
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7096
14
            NULL, HFILL } },
7097
7098
14
        { &hf_ssh_pty_term_mode_iuclc,
7099
14
          { "Translate uppercase characters to lowercase", "ssh.pty_term_mode.iuclc",
7100
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7101
14
            NULL, HFILL } },
7102
7103
14
        { &hf_ssh_pty_term_mode_ixon,
7104
14
          { "Enable output flow control", "ssh.pty_term_mode.ixon",
7105
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7106
14
            NULL, HFILL } },
7107
7108
14
        { &hf_ssh_pty_term_mode_ixany,
7109
14
          { "Any char will restart after stop", "ssh.pty_term_mode.ixany",
7110
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7111
14
            NULL, HFILL } },
7112
7113
14
        { &hf_ssh_pty_term_mode_ixoff,
7114
14
          { "Enable input flow control", "ssh.pty_term_mode.ixoff",
7115
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7116
14
            NULL, HFILL } },
7117
7118
14
        { &hf_ssh_pty_term_mode_imaxbel,
7119
14
          { "Ring bell on input queue full", "ssh.pty_term_mode.imaxbel",
7120
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7121
14
            NULL, HFILL } },
7122
7123
14
        { &hf_ssh_pty_term_mode_iutf8,
7124
14
          { "Terminal input and output is assumed to be encoded in UTF-8", "ssh.pty_term_mode.iutf8",
7125
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7126
14
            NULL, HFILL } },
7127
7128
14
        { &hf_ssh_pty_term_mode_isig,
7129
14
          { "Enable signals INTR, QUIT, [D]SUSP", "ssh.pty_term_mode.isig",
7130
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7131
14
            NULL, HFILL } },
7132
7133
14
        { &hf_ssh_pty_term_mode_icanon,
7134
14
          { "Canonicalize input lines", "ssh.pty_term_mode.icanon",
7135
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7136
14
            NULL, HFILL } },
7137
7138
14
        { &hf_ssh_pty_term_mode_xcase,
7139
14
          { "Enable input and output of uppercase characters by preceding their lowercase equivalents with '\'", "ssh.pty_term_mode.xcase",
7140
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7141
14
            NULL, HFILL } },
7142
7143
14
        { &hf_ssh_pty_term_mode_echo,
7144
14
          { "Enable echoing", "ssh.pty_term_mode.echo",
7145
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7146
14
            NULL, HFILL } },
7147
7148
14
        { &hf_ssh_pty_term_mode_echoe,
7149
14
          { "Visually erase chars", "ssh.pty_term_mode.echoe",
7150
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7151
14
            NULL, HFILL } },
7152
7153
14
        { &hf_ssh_pty_term_mode_echok,
7154
14
          { "Kill character discards current line", "ssh.pty_term_mode.echok",
7155
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7156
14
            NULL, HFILL } },
7157
7158
14
        { &hf_ssh_pty_term_mode_echonl,
7159
14
          { "Echo NL even if ECHO is off", "ssh.pty_term_mode.echonl",
7160
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7161
14
            NULL, HFILL } },
7162
7163
14
        { &hf_ssh_pty_term_mode_noflsh,
7164
14
          { "No flush after interrupt", "ssh.pty_term_mode.noflsh",
7165
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7166
14
            NULL, HFILL } },
7167
7168
14
        { &hf_ssh_pty_term_mode_tostop,
7169
14
          { "Stop background jobs from output", "ssh.pty_term_mode.tostop",
7170
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7171
14
            NULL, HFILL } },
7172
7173
14
        { &hf_ssh_pty_term_mode_iexten,
7174
14
          { "Enable extensions", "ssh.pty_term_mode.iexten",
7175
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7176
14
            NULL, HFILL } },
7177
7178
14
        { &hf_ssh_pty_term_mode_echoctl,
7179
14
          { "Echo control characters as ^(Char)", "ssh.pty_term_mode.echoctl",
7180
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7181
14
            NULL, HFILL } },
7182
7183
14
        { &hf_ssh_pty_term_mode_echoke,
7184
14
          { "Visual erase for line kill", "ssh.pty_term_mode.echoke",
7185
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7186
14
            NULL, HFILL } },
7187
7188
14
        { &hf_ssh_pty_term_mode_pendin,
7189
14
          { "Retype pending input", "ssh.pty_term_mode.pendin",
7190
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7191
14
            NULL, HFILL } },
7192
7193
14
        { &hf_ssh_pty_term_mode_opost,
7194
14
          { "Enable output processing", "ssh.pty_term_mode.opost",
7195
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7196
14
            NULL, HFILL } },
7197
7198
14
        { &hf_ssh_pty_term_mode_olcuc,
7199
14
          { "Convert lowercase to uppercase", "ssh.pty_term_mode.olcuc",
7200
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7201
14
            NULL, HFILL } },
7202
7203
14
        { &hf_ssh_pty_term_mode_onlcr,
7204
14
          { "Map NL to CR-NL", "ssh.pty_term_mode.onlcr",
7205
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7206
14
            NULL, HFILL } },
7207
7208
14
        { &hf_ssh_pty_term_mode_ocrnl,
7209
14
          { "Translate carriage return to newline (output)", "ssh.pty_term_mode.ocrnl",
7210
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7211
14
            NULL, HFILL } },
7212
7213
14
        { &hf_ssh_pty_term_mode_onocr,
7214
14
          { "Translate newline to carriage-return newline (output)", "ssh.pty_term_mode.onocr",
7215
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7216
14
            NULL, HFILL } },
7217
7218
14
        { &hf_ssh_pty_term_mode_onlret,
7219
14
          { "Newline performs a carriage return (output)", "ssh.pty_term_mode.onlret",
7220
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7221
14
            NULL, HFILL } },
7222
7223
14
        { &hf_ssh_pty_term_mode_cs7,
7224
14
          { "7 bit mode", "ssh.pty_term_mode.cs7",
7225
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7226
14
            NULL, HFILL } },
7227
7228
14
        { &hf_ssh_pty_term_mode_cs8,
7229
14
          { "8 bit mode", "ssh.pty_term_mode.cs8",
7230
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7231
14
            NULL, HFILL } },
7232
7233
14
        { &hf_ssh_pty_term_mode_parenb,
7234
14
          { "Parity enable", "ssh.pty_term_mode.parenb",
7235
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7236
14
            NULL, HFILL } },
7237
7238
14
        { &hf_ssh_pty_term_mode_parodd,
7239
14
          { "Odd parity", "ssh.pty_term_mode.parodd",
7240
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7241
14
            NULL, HFILL } },
7242
7243
14
        { &hf_ssh_pty_term_mode_ispeed,
7244
14
          { "Input baud rate", "ssh.pty_term_mode.ispeed",
7245
14
            FT_UINT32, BASE_DEC|BASE_UNIT_STRING, UNS(&units_bit_sec), 0x0,
7246
14
            NULL, HFILL } },
7247
7248
14
        { &hf_ssh_pty_term_mode_ospeed,
7249
14
          { "Output baud rate", "ssh.pty_term_mode.ospeed",
7250
14
            FT_UINT32, BASE_DEC|BASE_UNIT_STRING, UNS(&units_bit_sec), 0x0,
7251
14
            NULL, HFILL } },
7252
7253
14
        { &hf_ssh_pty_term_mode_value,
7254
14
          { "Value", "ssh.pty_term_mode.value",
7255
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
7256
14
            NULL, HFILL } },
7257
7258
14
        { &hf_ssh_exit_status,
7259
14
          { "Exit status", "ssh.exit_status",
7260
14
            FT_UINT32, BASE_HEX, NULL, 0x0,
7261
14
            NULL, HFILL }},
7262
7263
14
        { &hf_ssh_channel_window_adjust,
7264
14
          { "Bytes to add", "ssh.channel_window_adjust",
7265
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
7266
14
            NULL, HFILL }},
7267
7268
14
        { &hf_ssh_channel_data_len,
7269
14
          { "Data length", "ssh.channel_data_length",
7270
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
7271
14
            NULL, HFILL }},
7272
7273
14
        { &hf_ssh_channel_data_type_code,
7274
14
          { "Data Type Code", "ssh.channel_data_type_code",
7275
14
            FT_UINT32, BASE_DEC, VALS(ssh_channel_data_type_code_vals), 0x0,
7276
14
            NULL, HFILL } },
7277
7278
14
        { &hf_ssh_reassembled_in,
7279
14
          { "Reassembled PDU in frame", "ssh.reassembled_in",
7280
14
            FT_FRAMENUM, BASE_NONE, NULL, 0x0,
7281
14
            "The PDU that doesn't end in this segment is reassembled in this frame", HFILL }},
7282
7283
14
        { &hf_ssh_reassembled_length,
7284
14
          { "Reassembled PDU length", "ssh.reassembled.length",
7285
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
7286
14
            "The total length of the reassembled payload", HFILL }},
7287
7288
14
        { &hf_ssh_reassembled_data,
7289
14
          { "Reassembled PDU data", "ssh.reassembled.data",
7290
14
            FT_BYTES, BASE_NONE, NULL, 0x00,
7291
14
            "The payload of multiple reassembled SSH segments", HFILL }},
7292
7293
14
        { &hf_ssh_segments,
7294
14
          { "Reassembled SSH segments", "ssh.segments",
7295
14
            FT_NONE, BASE_NONE, NULL, 0x0,
7296
14
            NULL, HFILL }},
7297
7298
14
        { &hf_ssh_segment,
7299
14
          { "SSH segment", "ssh.segment",
7300
14
            FT_FRAMENUM, BASE_NONE, NULL, 0x0,
7301
14
            NULL, HFILL }},
7302
7303
14
        { &hf_ssh_segment_overlap,
7304
14
          { "Segment overlap", "ssh.segment.overlap",
7305
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7306
14
            "Segment overlaps with other segments", HFILL }},
7307
7308
14
        { &hf_ssh_segment_overlap_conflict,
7309
14
          { "Conflicting data in segment overlap", "ssh.segment.overlap.conflict",
7310
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7311
14
            "Overlapping segments contained conflicting data", HFILL }},
7312
7313
14
        { &hf_ssh_segment_multiple_tails,
7314
14
          { "Multiple tail segments found", "ssh.segment.multipletails",
7315
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7316
14
            "Several tails were found when reassembling the pdu", HFILL }},
7317
7318
14
        { &hf_ssh_segment_too_long_fragment,
7319
14
          { "Segment too long", "ssh.segment.toolongfragment",
7320
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7321
14
            "Segment contained data past end of the pdu", HFILL }},
7322
7323
14
        { &hf_ssh_segment_error,
7324
14
          { "Reassembling error", "ssh.segment.error",
7325
14
            FT_FRAMENUM, BASE_NONE, NULL, 0x0,
7326
14
            "Reassembling error due to illegal segments", HFILL }},
7327
7328
14
        { &hf_ssh_segment_count,
7329
14
          { "Segment count", "ssh.segment.count",
7330
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
7331
14
            NULL, HFILL }},
7332
7333
14
        { &hf_ssh_segment_data,
7334
14
          { "SSH segment data", "ssh.segment.data",
7335
14
            FT_BYTES, BASE_NONE, NULL, 0x00,
7336
14
            "The payload of a single SSH segment", HFILL }},
7337
7338
14
        { &hf_ssh_hybrid_blob_client,
7339
14
          { "Hybrid Key Exchange Blob Client", "ssh.kex_hybrid_blob_client",
7340
14
            FT_BYTES, BASE_NONE, NULL, 0x0, "Client post-quantum hybrid blob", HFILL }
7341
14
        },
7342
7343
14
        { &hf_ssh_hybrid_blob_client_len,
7344
14
          { "Hybrid Key Exchange Blob Client Length", "ssh.kex_hybrid_blob_client_len",
7345
14
            FT_UINT32, BASE_DEC, NULL, 0x0, "Length of client post-quantum hybrid blob", HFILL }
7346
14
        },
7347
7348
14
        { &hf_ssh_hybrid_blob_server,
7349
14
          { "Hybrid Key Exchange Blob Server", "ssh.kex_hybrid_blob_server",
7350
14
            FT_BYTES, BASE_NONE, NULL, 0x0, "Server post-quantum hybrid blob", HFILL }
7351
14
        },
7352
7353
14
        { &hf_ssh_hybrid_blob_server_len,
7354
14
          { "Hybrid Key Exchange Blob Server Length", "ssh.kex_hybrid_blob_server_len",
7355
14
            FT_UINT32, BASE_DEC, NULL, 0x0, "Length of server post-quantum hybrid blob", HFILL }
7356
14
        },
7357
7358
14
        { &hf_ssh_pq_kem_client,
7359
14
          { "Client PQ KEM Public Key", "ssh.kex.pq_kem_client",
7360
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
7361
14
            "Post-quantum key (client)", HFILL }
7362
14
        },
7363
7364
14
        { &hf_ssh_pq_kem_server,
7365
14
          { "Server PQ KEM Response", "ssh.kex.pq_kem_server",
7366
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
7367
14
            "Post-quantum ciphertext (server response)", HFILL }
7368
14
        },
7369
7370
14
    };
7371
7372
14
    static int *ett[] = {
7373
14
        &ett_ssh,
7374
14
        &ett_key_exchange,
7375
14
        &ett_key_exchange_host_key,
7376
14
        &ett_key_exchange_host_sig,
7377
14
        &ett_extension,
7378
14
        &ett_userauth_pk_blob,
7379
14
        &ett_userauth_pk_signature,
7380
14
        &ett_term_modes,
7381
14
        &ett_term_mode,
7382
14
        &ett_ssh1,
7383
14
        &ett_ssh2,
7384
14
        &ett_key_init,
7385
14
        &ett_ssh_segments,
7386
14
        &ett_ssh_pqhybrid_client,  // added for PQ hybrid CLIENT dissection
7387
14
        &ett_ssh_pqhybrid_server,  // added for PQ hybrid SERVER dissection
7388
14
        &ett_ssh_segment
7389
14
    };
7390
7391
14
    static ei_register_info ei[] = {
7392
14
        { &ei_ssh_packet_length,  { "ssh.packet_length.error", PI_PROTOCOL, PI_WARN, "Invalid packet length", EXPFILL }},
7393
14
        { &ei_ssh_padding_length,  { "ssh.padding_length.error", PI_PROTOCOL, PI_WARN, "Invalid padding length", EXPFILL }},
7394
14
        { &ei_ssh_packet_decode,  { "ssh.packet_decode.error", PI_UNDECODED, PI_WARN, "Packet decoded length not equal to packet length", EXPFILL }},
7395
14
        { &ei_ssh_channel_number, { "ssh.channel_number.error", PI_PROTOCOL, PI_WARN, "Could not find channel", EXPFILL }},
7396
14
        { &ei_ssh_invalid_keylen, { "ssh.key_length.error", PI_PROTOCOL, PI_ERROR, "Invalid key length", EXPFILL }},
7397
14
        { &ei_ssh_mac_bad,        { "ssh.mac_bad.expert", PI_CHECKSUM, PI_ERROR, "Bad MAC", EXPFILL }},
7398
14
        { &ei_ssh2_kex_hybrid_msg_code, { "ssh.kex_hybrid_msg_code", PI_SECURITY, PI_NOTE, "Hybrid KEX encountered", EXPFILL }},
7399
14
        { &ei_ssh2_kex_hybrid_msg_code_unknown, { "ssh.kex_hybrid_msg_code.unknown", PI_UNDECODED, PI_NOTE, "Unknown KEX_HYBRID message code", EXPFILL }},
7400
7401
14
    };
7402
14
    module_t *ssh_module;
7403
14
    expert_module_t *expert_ssh;
7404
7405
14
    proto_ssh = proto_register_protocol("SSH Protocol", "SSH", "ssh");
7406
14
    proto_register_field_array(proto_ssh, hf, array_length(hf));
7407
14
    proto_register_subtree_array(ett, array_length(ett));
7408
14
    expert_ssh = expert_register_protocol(proto_ssh);
7409
14
    expert_register_field_array(expert_ssh, ei, array_length(ei));
7410
7411
14
#ifdef SSH_DECRYPT_DEBUG
7412
14
    ssh_module = prefs_register_protocol(proto_ssh, ssh_prefs_apply_cb);
7413
#else
7414
    ssh_module = prefs_register_protocol(proto_ssh, NULL);
7415
#endif
7416
14
    prefs_register_bool_preference(ssh_module, "desegment_buffers",
7417
14
                       "Reassemble SSH buffers spanning multiple TCP segments",
7418
14
                       "Whether the SSH dissector should reassemble SSH buffers spanning multiple TCP segments. "
7419
14
                       "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
7420
14
                       &ssh_desegment);
7421
14
    prefs_register_bool_preference(ssh_module, "ignore_ssh_mac_failed",
7422
14
                        "Ignore Message Authentication Code (MAC) failure",
7423
14
                        "For troubleshooting purposes, decrypt even if the "
7424
14
                        "Message Authentication Code (MAC) check fails.",
7425
14
                        &ssh_ignore_mac_failed);
7426
7427
14
    ssh_master_key_map = g_hash_table_new_full(ssh_hash, ssh_equal, ssh_free_glib_allocated_bignum, ssh_free_glib_allocated_entry);
7428
14
    prefs_register_filename_preference(ssh_module, "keylog_file", "Key log filename",
7429
14
            "The path to the file which contains a list of key exchange secrets in the following format:\n"
7430
14
            "\"<hex-encoded-cookie> <PRIVATE_KEY|SHARED_SECRET> <hex-encoded-key>\" (without quotes or leading spaces).\n",
7431
14
            &pref_keylog_file, false);
7432
7433
14
    prefs_register_filename_preference(ssh_module, "debug_file", "SSH debug file",
7434
14
        "Redirect SSH debug to the file specified. Leave empty to disable debugging "
7435
14
        "or use \"" SSH_DEBUG_USE_STDERR "\" to redirect output to stderr.",
7436
14
        &ssh_debug_file_name, true);
7437
7438
14
    secrets_register_type(SECRETS_TYPE_SSH, ssh_secrets_block_callback);
7439
7440
14
    ssh_handle = register_dissector("ssh", dissect_ssh, proto_ssh);
7441
14
    reassembly_table_register(&ssh_reassembly_table, &tcp_reassembly_table_functions);
7442
14
    register_shutdown_routine(ssh_shutdown);
7443
14
}
7444
7445
void
7446
proto_reg_handoff_ssh(void)
7447
14
{
7448
14
#ifdef SSH_DECRYPT_DEBUG
7449
14
    ssh_set_debug(ssh_debug_file_name);
7450
14
#endif
7451
14
    dissector_add_uint_range_with_preference("tcp.port", TCP_RANGE_SSH, ssh_handle);
7452
14
    dissector_add_uint("sctp.port", SCTP_PORT_SSH, ssh_handle);
7453
14
    dissector_add_uint("sctp.ppi", SSH_PAYLOAD_PROTOCOL_ID, ssh_handle);
7454
14
    sftp_handle = find_dissector_add_dependency("sftp", proto_ssh);
7455
14
    data_text_lines_handle = find_dissector_add_dependency("data-text-lines", proto_ssh);
7456
7457
14
    heur_dissector_add("tcp", dissect_ssh_heur, "SSH over TCP", "ssh_tcp", proto_ssh, HEURISTIC_ENABLE);
7458
14
}
7459
7460
/*
7461
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
7462
 *
7463
 * Local variables:
7464
 * c-basic-offset: 4
7465
 * tab-width: 8
7466
 * indent-tabs-mode: nil
7467
 * End:
7468
 *
7469
 * vi: set shiftwidth=4 tabstop=8 expandtab:
7470
 * :indentSize=4:tabSize=8:noTabs=true:
7471
 */