Bug Summary

File:epan/dissectors/packet-ssh.c
Warning:line 2655, column 17
Value of 'errno' was not checked and may be overwritten by function 'ferror'

Annotated Source Code

Press '?' to see keyboard shortcuts

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