Bug Summary

File:builds/wireshark/wireshark/epan/dissectors/packet-ssh.c
Warning:line 2632, 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-nonliteral -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/2026-01-29-100357-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 const uint8_t *session_id;
209 unsigned session_id_length;
210 ssh_bignum *kex_e;
211 ssh_bignum *kex_f;
212 ssh_bignum *kex_gex_p; // Group modulo
213 ssh_bignum *kex_gex_g; // Group generator
214 ssh_bignum *secret;
215 wmem_array_t *kex_client_version;
216 wmem_array_t *kex_server_version;
217 wmem_array_t *kex_client_key_exchange_init;
218 wmem_array_t *kex_server_key_exchange_init;
219 wmem_array_t *kex_server_host_key_blob;
220 wmem_array_t *kex_gex_bits_min;
221 wmem_array_t *kex_gex_bits_req;
222 wmem_array_t *kex_gex_bits_max;
223 wmem_array_t *kex_shared_secret;
224 bool_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 unsigned 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 uint8_t *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 uint8_t *string, unsigned len);
935static void ssh_derive_symmetric_keys(ssh_bignum *shared_secret,
936 uint8_t *exchange_hash, unsigned hash_length,
937 struct ssh_flow_data *global_data);
938static void ssh_derive_symmetric_key(ssh_bignum *shared_secret,
939 const uint8_t *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 char* 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 uint8_t *data = (uint8_t *)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 const char* 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 = (char*)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 unsigned offset, proto_tree *tree, int is_response, unsigned * version,
2232 bool_Bool *need_desegmentation)
2233{
2234 unsigned protolen, next_offset;
2235
2236 /*
2237 * If the first packet do not contain the banner,
2238 * it is dump in the middle of a flow or not a ssh at all
2239 */
2240 if (tvb_strncaseeql(tvb, offset, "SSH-", 4) != 0) {
2241 offset = ssh_dissect_encrypted_packet(tvb, pinfo,
2242 &global_data->peer_data[is_response], offset, tree);
2243 return offset;
2244 }
2245
2246 if (!is_response) {
2247 if (tvb_strncaseeql(tvb, offset, "SSH-2.", 6) == 0) {
2248 *(version) = SSH_VERSION_22;
2249 } else if (tvb_strncaseeql(tvb, offset, "SSH-1.99-", 9) == 0) {
2250 *(version) = SSH_VERSION_22;
2251 } else if (tvb_strncaseeql(tvb, offset, "SSH-1.", 6) == 0) {
2252 *(version) = SSH_VERSION_11;
2253 }
2254 }
2255
2256 if (!tvb_find_line_end_remaining(tvb, offset, &protolen, &next_offset)) {
2257 if (ssh_desegment && pinfo->can_desegment) {
2258 pinfo->desegment_offset = offset;
2259 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT0x0fffffff;
2260 *need_desegmentation = true1;
2261 return offset;
2262 }
2263 }
2264 /* Either we found it, or we're not reassembling and take everything. */
2265
2266 col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL((void*)0), "Protocol (%s)",
2267 tvb_format_text(pinfo->pool, tvb, offset, protolen));
2268
2269 // V_C / V_S (client and server identification strings) RFC4253 4.2
2270 // format: SSH-protoversion-softwareversion SP comments [CR LF not incl.]
2271 if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) {
2272 uint8_t *data = (uint8_t *)tvb_memdup(pinfo->pool, tvb, offset, protolen);
2273 if(!is_response){
2274 ssh_hash_buffer_put_string(global_data->kex_client_version, data, protolen);
2275 }else{
2276 ssh_hash_buffer_put_string(global_data->kex_server_version, data, protolen);
2277 }
2278 }
2279
2280 proto_tree_add_item(tree, hf_ssh_protocol,
2281 tvb, offset, protolen, ENC_ASCII0x00000000);
2282 offset += next_offset;
2283 return offset;
2284}
2285
2286static void
2287ssh_set_mac_length(struct ssh_peer_data *peer_data)
2288{
2289 char *size_str;
2290 uint32_t size = 0;
2291 char *mac_name = peer_data->mac;
2292 char *strip;
2293
2294 if (!mac_name)
2295 return;
2296
2297 /* wmem_strdup() never returns NULL */
2298 mac_name = wmem_strdup(NULL((void*)0), (const char *)mac_name);
2299
2300 /* strip trailing "[email protected]" or "@openssh.com" */
2301 strip = strstr(mac_name, "[email protected]");
2302 if (strip) {
2303 peer_data->length_is_plaintext = 1;
2304 *strip = '\0';
2305 }
2306 else {
2307 strip = strstr(mac_name, "@openssh.com");
2308 if (strip) *strip = '\0';
2309 }
2310
2311 size_str = g_strrstr(mac_name, "-");
2312 if (size_str && ws_strtou32(size_str + 1, NULL((void*)0), &size) && size > 0 && size % 8 == 0) {
2313 peer_data->mac_length = size / 8;
2314 }
2315 else if (strcmp(mac_name, "hmac-sha1") == 0) {
2316 peer_data->mac_length = 20;
2317 }
2318 else if (strcmp(mac_name, "hmac-md5") == 0) {
2319 peer_data->mac_length = 16;
2320 }
2321 else if (strcmp(mac_name, "hmac-ripemd160") == 0) {
2322 peer_data->mac_length = 20;
2323 }
2324 else if (strcmp(mac_name, "none") == 0) {
2325 peer_data->mac_length = 0;
2326 }
2327
2328 wmem_free(NULL((void*)0), mac_name);
2329}
2330
2331static void ssh_set_kex_specific_dissector(struct ssh_flow_data *global_data)
2332{
2333 const char *kex_name = global_data->kex;
2334
2335 if (!kex_name) return;
2336
2337 if (strcmp(kex_name, "diffie-hellman-group-exchange-sha1") == 0 ||
2338 strcmp(kex_name, "diffie-hellman-group-exchange-sha256") == 0)
2339 {
2340 global_data->kex_specific_dissector = ssh_dissect_kex_dh_gex;
2341 }
2342 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-"
) )
||
2343 strcmp(kex_name, "[email protected]") == 0 ||
2344 strcmp(kex_name, "curve25519-sha256") == 0 ||
2345 strcmp(kex_name, "curve448-sha512") == 0)
2346 {
2347 global_data->kex_specific_dissector = ssh_dissect_kex_ecdh;
2348 }
2349 else if (strcmp(kex_name, "diffie-hellman-group14-sha256") == 0 ||
2350 strcmp(kex_name, "diffie-hellman-group16-sha512") == 0 ||
2351 strcmp(kex_name, "diffie-hellman-group18-sha512") == 0 ||
2352 strcmp(kex_name, "diffie-hellman-group1-sha1") == 0 ||
2353 strcmp(kex_name, "diffie-hellman-group14-sha1") == 0)
2354 {
2355 global_data->kex_specific_dissector = ssh_dissect_kex_dh;
2356 }
2357 else if (strcmp(kex_name, "mlkem768nistp256-sha256") == 0 ||
2358 strcmp(kex_name, "mlkem1024nistp384-sha384") == 0)
2359 {
2360 global_data->kex_specific_dissector = ssh_dissect_kex_hybrid;
2361 }
2362 else if (strcmp(kex_name, "sntrup761x25519-sha512") == 0 ||
2363 strcmp(kex_name, "mlkem768x25519-sha256") == 0)
2364 /* ___add support for post-quantum hybrid KEM */
2365 {
2366 global_data->kex_specific_dissector = ssh_dissect_kex_pq_hybrid;
2367 }
2368 else
2369 {
2370 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"
, 2370, __func__, "NOT SUPPORTED OR UNKNOWN KEX DETECTED: ALGORITHM = %s"
, kex_name); } } while (0)
;
2371 }
2372}
2373
2374static int
2375ssh_gslist_compare_strings(const void *a, const void *b)
2376{
2377 if (a == NULL((void*)0) && b == NULL((void*)0))
2378 return 0;
2379 if (a == NULL((void*)0))
2380 return -1;
2381 if (b == NULL((void*)0))
2382 return 1;
2383 return strcmp((const char*)a, (const char*)b);
2384}
2385
2386/* expects that *result is NULL */
2387static bool_Bool
2388ssh_choose_algo(char *client, char *server, char **result)
2389{
2390 char **server_strings = NULL((void*)0);
2391 char **client_strings = NULL((void*)0);
2392 char **step;
2393 GSList *server_list = NULL((void*)0);
2394
2395 static const char* client_strict = "[email protected]";
2396 static const char* server_strict = "[email protected]";
2397 bool_Bool kex_strict = false0;
2398
2399 if (!client || !server || !result || *result)
2400 return false0;
2401
2402 server_strings = g_strsplit(server, ",", 0);
2403 for (step = server_strings; *step; step++) {
2404 server_list = g_slist_append(server_list, *step);
2405 }
2406
2407 client_strings = g_strsplit(client, ",", 0);
2408 for (step = client_strings; *step; step++) {
2409 GSList *agreed;
2410 if ((agreed = g_slist_find_custom(server_list, *step, ssh_gslist_compare_strings))) {
2411 *result = wmem_strdup(wmem_file_scope(), (const char *)agreed->data);
2412 break;
2413 }
2414 }
2415
2416 /* Check for the OpenSSH strict key exchange extension designed to
2417 * mitigate the Terrapin attack by resetting the packet sequence
2418 * number to zero after a SSH2_MSG_NEWKEYS message.
2419 * https://www.openssh.com/txt/release-9.6
2420 * Also see PROTOCOL in the OpenSSH source distribution.
2421 *
2422 * OpenSSH says this is activated "when an endpoint that supports this
2423 * extension observes this algorithm name in a peer's KEXINIT packet".
2424 * We'll have to assume that any endpoint that supports this also
2425 * indicates support for it in its own first SSH2_MSG_KEXINIT.
2426 */
2427 if (g_strv_contains((const char* const*)client_strings, client_strict) &&
2428 g_strv_contains((const char* const*)server_strings, server_strict)) {
2429
2430 kex_strict = true1;
2431 }
2432
2433 g_strfreev(client_strings);
2434 g_slist_free(server_list);
2435 g_strfreev(server_strings);
2436
2437 return kex_strict;
2438}
2439
2440static int
2441ssh_dissect_key_init(tvbuff_t *tvb, packet_info *pinfo, int offset,
2442 proto_tree *tree, int is_response, struct ssh_flow_data *global_data)
2443{
2444 int start_offset = offset;
2445 int payload_length;
2446 wmem_strbuf_t *hassh_algo;
2447 char *hassh;
2448
2449 proto_item *tf, *ti;
2450 proto_tree *key_init_tree;
2451
2452 struct ssh_peer_data *peer_data = &global_data->peer_data[is_response];
2453
2454 key_init_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_key_init, &tf, "Algorithms");
2455 if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) {
2456 peer_data->bn_cookie = ssh_kex_make_bignum(tvb_get_ptr(tvb, offset, 16), 16);
2457 }
2458 proto_tree_add_item(key_init_tree, hf_ssh_cookie,
2459 tvb, offset, 16, ENC_NA0x00000000);
2460 offset += 16;
2461
2462 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
2463 hf_ssh_kex_algorithms_length, hf_ssh_kex_algorithms,
2464 &peer_data->kex_proposal);
2465 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
2466 hf_ssh_server_host_key_algorithms_length,
2467 hf_ssh_server_host_key_algorithms, NULL((void*)0));
2468 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
2469 hf_ssh_encryption_algorithms_client_to_server_length,
2470 hf_ssh_encryption_algorithms_client_to_server,
2471 &peer_data->enc_proposals[CLIENT_TO_SERVER_PROPOSAL0]);
2472 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
2473 hf_ssh_encryption_algorithms_server_to_client_length,
2474 hf_ssh_encryption_algorithms_server_to_client,
2475 &peer_data->enc_proposals[SERVER_TO_CLIENT_PROPOSAL1]);
2476 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
2477 hf_ssh_mac_algorithms_client_to_server_length,
2478 hf_ssh_mac_algorithms_client_to_server,
2479 &peer_data->mac_proposals[CLIENT_TO_SERVER_PROPOSAL0]);
2480 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
2481 hf_ssh_mac_algorithms_server_to_client_length,
2482 hf_ssh_mac_algorithms_server_to_client,
2483 &peer_data->mac_proposals[SERVER_TO_CLIENT_PROPOSAL1]);
2484 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
2485 hf_ssh_compression_algorithms_client_to_server_length,
2486 hf_ssh_compression_algorithms_client_to_server,
2487 &peer_data->comp_proposals[CLIENT_TO_SERVER_PROPOSAL0]);
2488 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
2489 hf_ssh_compression_algorithms_server_to_client_length,
2490 hf_ssh_compression_algorithms_server_to_client,
2491 &peer_data->comp_proposals[SERVER_TO_CLIENT_PROPOSAL1]);
2492 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
2493 hf_ssh_languages_client_to_server_length,
2494 hf_ssh_languages_client_to_server, NULL((void*)0));
2495 offset = ssh_dissect_proposal(tvb, offset, key_init_tree,
2496 hf_ssh_languages_server_to_client_length,
2497 hf_ssh_languages_server_to_client, NULL((void*)0));
2498
2499 proto_tree_add_item(key_init_tree, hf_ssh_first_kex_packet_follows,
2500 tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
2501 offset+=1;
2502
2503 proto_tree_add_item(key_init_tree, hf_ssh_kex_reserved,
2504 tvb, offset, 4, ENC_NA0x00000000);
2505 offset+=4;
2506
2507 hassh_algo = wmem_strbuf_new(pinfo->pool, "");
2508 if(!is_response) {
2509 wmem_strbuf_append_printf(hassh_algo, "%s;%s;%s;%s", peer_data->kex_proposal, peer_data->enc_proposals[CLIENT_TO_SERVER_PROPOSAL0],
2510 peer_data->mac_proposals[CLIENT_TO_SERVER_PROPOSAL0], peer_data->comp_proposals[CLIENT_TO_SERVER_PROPOSAL0]);
2511 hassh = g_compute_checksum_for_string(G_CHECKSUM_MD5, wmem_strbuf_get_str(hassh_algo), wmem_strbuf_get_len(hassh_algo));
2512 ti = proto_tree_add_string(key_init_tree, hf_ssh_kex_hassh_algo, tvb, offset, 0, wmem_strbuf_get_str(hassh_algo));
2513 proto_item_set_generated(ti);
2514 ti = proto_tree_add_string(key_init_tree, hf_ssh_kex_hassh, tvb, offset, 0, hassh);
2515 proto_item_set_generated(ti);
2516 g_free(hassh);
2517 } else {
2518 wmem_strbuf_append_printf(hassh_algo, "%s;%s;%s;%s", peer_data->kex_proposal, peer_data->enc_proposals[SERVER_TO_CLIENT_PROPOSAL1],
2519 peer_data->mac_proposals[SERVER_TO_CLIENT_PROPOSAL1], peer_data->comp_proposals[SERVER_TO_CLIENT_PROPOSAL1]);
2520 hassh = g_compute_checksum_for_string(G_CHECKSUM_MD5, wmem_strbuf_get_str(hassh_algo), wmem_strbuf_get_len(hassh_algo));
2521 ti = proto_tree_add_string(key_init_tree, hf_ssh_kex_hasshserver_algo, tvb, offset, 0, wmem_strbuf_get_str(hassh_algo));
2522 proto_item_set_generated(ti);
2523 ti = proto_tree_add_string(key_init_tree, hf_ssh_kex_hasshserver, tvb, offset, 0, hassh);
2524 proto_item_set_generated(ti);
2525 g_free(hassh);
2526 }
2527
2528 if (global_data->peer_data[CLIENT_PEER_DATA0].kex_proposal &&
2529 global_data->peer_data[SERVER_PEER_DATA1].kex_proposal &&
2530 !global_data->kex)
2531 {
2532 /* Note: we're ignoring first_kex_packet_follows. */
2533 global_data->ext_kex_strict = ssh_choose_algo(
2534 global_data->peer_data[CLIENT_PEER_DATA0].kex_proposal,
2535 global_data->peer_data[SERVER_PEER_DATA1].kex_proposal,
2536 &global_data->kex);
2537 ssh_set_kex_specific_dissector(global_data);
2538 }
2539
2540 payload_length = offset - start_offset;
2541
2542 if (tf != NULL((void*)0)) {
2543 proto_item_set_len(tf, payload_length);
2544 }
2545
2546 // I_C / I_S (client and server SSH_MSG_KEXINIT payload) RFC4253 4.2
2547 if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) {
2548 uint8_t *data = (uint8_t *)wmem_alloc(pinfo->pool, payload_length + 1);
2549 tvb_memcpy(tvb, data + 1, start_offset, payload_length);
2550 data[0] = SSH_MSG_KEXINIT20;
2551 if(is_response){
2552 ssh_hash_buffer_put_string(global_data->kex_server_key_exchange_init, data, payload_length + 1);
2553 }else{
2554 // Reset array while REKEY: sanitize client key
2555 global_data->kex_client_key_exchange_init = wmem_array_new(wmem_file_scope(), 1);
2556 ssh_hash_buffer_put_string(global_data->kex_client_key_exchange_init, data, payload_length + 1);
2557 }
2558 }
2559
2560 return offset;
2561}
2562
2563static int
2564ssh_dissect_proposal(tvbuff_t *tvb, int offset, proto_tree *tree,
2565 int hf_index_length, int hf_index_value, char **store)
2566{
2567 uint32_t len = tvb_get_ntohl(tvb, offset);
2568 proto_tree_add_uint(tree, hf_index_length, tvb, offset, 4, len);
2569 offset += 4;
2570
2571 proto_tree_add_item(tree, hf_index_value, tvb, offset, len,
2572 ENC_ASCII0x00000000);
2573 if (store)
2574 *store = (char *) tvb_get_string_enc(wmem_file_scope(), tvb, offset, len, ENC_ASCII0x00000000);
2575 offset += len;
2576
2577 return offset;
2578}
2579
2580static void
2581ssh_keylog_read_file(void)
2582{
2583 if (!pref_keylog_file || !*pref_keylog_file) {
5
Assuming 'pref_keylog_file' is non-null
6
Assuming the condition is false
2584 ws_debug("no keylog file preference set")do { if (1) { ws_log_full("packet-ssh", LOG_LEVEL_DEBUG, "epan/dissectors/packet-ssh.c"
, 2584, __func__, "no keylog file preference set"); } } while
(0)
;
2585 return;
2586 }
2587
2588 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
2589 pref_keylog_file)) {
2590 ssh_keylog_reset();
2591 g_hash_table_remove_all(ssh_master_key_map);
2592 }
2593
2594 if (!ssh_keylog_file) {
10
Assuming 'ssh_keylog_file' is non-null
11
Taking false branch
2595 ssh_keylog_file = ws_fopenfopen(pref_keylog_file, "r");
2596 if (!ssh_keylog_file) {
2597 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"
, 2598, __func__, "ssh: failed to open key log file %s: %s", pref_keylog_file
, g_strerror((*__errno_location ()))); } } while (0)
2598 pref_keylog_file, g_strerror(errno))do { if (1) { ws_log_full("packet-ssh", LOG_LEVEL_DEBUG, "epan/dissectors/packet-ssh.c"
, 2598, __func__, "ssh: failed to open key log file %s: %s", pref_keylog_file
, g_strerror((*__errno_location ()))); } } while (0)
;
2599 return;
2600 }
2601 }
2602
2603 /* File format: each line follows the format "<cookie> <type> <key>".
2604 * <cookie> is the hex-encoded (client or server) 16 bytes cookie
2605 * (32 characters) found in the SSH_MSG_KEXINIT of the endpoint whose
2606 * private random is disclosed.
2607 * <type> is either SHARED_SECRET or PRIVATE_KEY depending on the
2608 * type of key provided. PRIVAT_KEY is only supported for DH,
2609 * DH group exchange, and ECDH (including Curve25519) key exchanges.
2610 * <key> is the private random number that is used to generate the DH
2611 * negotiation (length depends on algorithm). In RFC4253 it is called
2612 * x for the client and y for the server.
2613 * For openssh and DH group exchange, it can be retrieved using
2614 * DH_get0_key(kex->dh, NULL, &server_random)
2615 * for groupN in file kexdh.c function kex_dh_compute_key
2616 * for custom group in file kexgexs.c function input_kex_dh_gex_init
2617 * For openssh and curve25519, it can be found in function kex_c25519_enc
2618 * in variable server_key. One may also provide the shared secret
2619 * directly if <type> is set to SHARED_SECRET.
2620 *
2621 * Example:
2622 * 90d886612f9c35903db5bb30d11f23c2 PRIVATE_KEY DEF830C22F6C927E31972FFB20B46C96D0A5F2D5E7BE5A3A8804D6BFC431619ED10AF589EEDFF4750DEA00EFD7AFDB814B6F3528729692B1F2482041521AE9DC
2623 */
2624 for (;;) {
12
Loop condition is true. Entering loop body
2625 // XXX - What is a reasonable max line length here? Note at a certain
2626 // point we have to increase the maximum ssh_kex_make_bignum supports (not needed for post quantum material (pure binary)).
2627 char buf[4096];// 4096 is needed for mlkem1024 private_key binary meterial: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.203.pdf
2628 buf[0] = 0;
2629
2630 if (!fgets(buf, sizeof(buf), ssh_keylog_file)) {
13
Taking true branch
2631 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
2632 if (ferror(ssh_keylog_file)) {
15
Value of 'errno' was not checked and may be overwritten by function 'ferror'
2633 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"
, 2633, __func__, "Error while reading %s, closing it.", pref_keylog_file
); } } while (0)
;
2634 ssh_keylog_reset();
2635 g_hash_table_remove_all(ssh_master_key_map);
2636 }
2637 break;
2638 }
2639
2640 size_t len = strlen(buf);
2641 while(len>0 && (buf[len-1]=='\r' || buf[len-1]=='\n')){len-=1;buf[len]=0;}
2642 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"
, 2642, __func__, "ssh: raw keylog line read: %s", buf); } } while
(0)
;
2643
2644 ssh_keylog_process_line(buf);
2645 }
2646}
2647
2648static void
2649ssh_keylog_process_lines(const uint8_t *data, unsigned datalen)
2650{
2651 const char *next_line = (const char *)data;
2652 const char *line_end = next_line + datalen;
2653 while (next_line && next_line < line_end) {
2654 const char *line = next_line;
2655 next_line = (const char *)memchr(line, '\n', line_end - line);
2656 ssize_t linelen;
2657
2658 if (next_line) {
2659 linelen = next_line - line;
2660 next_line++; /* drop LF */
2661 } else {
2662 linelen = (ssize_t)(line_end - line);
2663 }
2664 if (linelen > 0 && line[linelen - 1] == '\r') {
2665 linelen--; /* drop CR */
2666 }
2667
2668 ssh_debug_printf(" checking keylog line: %.*s\n", (int)linelen, line);
2669 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"
, 2669, __func__, "ssh: about to process line: %.*s", (int)linelen
, line); } } while (0)
;
2670
2671 char * strippedline = g_strndup(line, linelen);
2672 ssh_keylog_process_line(strippedline);
2673 g_free(strippedline);
2674 }
2675}
2676
2677static void
2678ssh_keylog_process_line(const char *line)
2679{
2680 ws_noisy("ssh: process line: %s", line)do { if (1) { ws_log_full("packet-ssh", LOG_LEVEL_NOISY, "epan/dissectors/packet-ssh.c"
, 2680, __func__, "ssh: process line: %s", line); } } while (
0)
;
2681
2682 char **split = g_strsplit(line, " ", 3);
2683 char *cookie, *type, *key;
2684 size_t cookie_len, key_len;
2685
2686 if (g_strv_length(split) == 3) {
2687 // New format: [hex-encoded cookie] [key type] [hex-encoded key material]
2688 cookie = split[0];
2689 type = split[1];
2690 key = split[2];
2691 } else if (g_strv_length(split) == 2) {
2692 // Old format: [hex-encoded cookie] [hex-encoded private key]
2693 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"
, 2693, __func__, "ssh keylog: detected old keylog format without explicit key type"
); } } while (0)
;
2694 type = "PRIVATE_KEY";
2695 cookie = split[0];
2696 key = split[1];
2697 } else {
2698 ws_debug("ssh keylog: invalid format")do { if (1) { ws_log_full("packet-ssh", LOG_LEVEL_DEBUG, "epan/dissectors/packet-ssh.c"
, 2698, __func__, "ssh keylog: invalid format"); } } while (0
)
;
2699 g_strfreev(split);
2700 return;
2701 }
2702
2703 key_len = strlen(key);
2704 cookie_len = strlen(cookie);
2705 if(key_len & 1){
2706 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"
, 2706, __func__, "ssh keylog: invalid format (key should at least be even!)"
); } } while (0)
;
2707 g_strfreev(split);
2708 return;
2709 }
2710 if(cookie_len & 1){
2711 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"
, 2711, __func__, "ssh keylog: invalid format (cookie should at least be even!)"
); } } while (0)
;
2712 g_strfreev(split);
2713 return;
2714 }
2715 ssh_bignum * bn_cookie = ssh_kex_make_bignum(NULL((void*)0), (unsigned)(cookie_len/2));
2716 ssh_bignum * bn_priv = ssh_kex_make_bignum(NULL((void*)0), (unsigned)(key_len/2));
2717 uint8_t c;
2718 for (size_t i = 0; i < key_len/2; i ++) {
2719 char v0 = key[i * 2];
2720 int8_t h0 = ws_xton(v0);
2721 char v1 = key[i * 2 + 1];
2722 int8_t h1 = ws_xton(v1);
2723
2724 if (h0==-1 || h1==-1) {
2725 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"
, 2725, __func__, "ssh: can't process key, invalid hex number: %c%c"
, v0, v1); } } while (0)
;
2726 g_strfreev(split);
2727 return;
2728 }
2729
2730 c = (h0 << 4) | h1;
2731
2732 bn_priv->data[i] = c;
2733 }
2734 for (size_t i = 0; i < cookie_len/2; i ++) {
2735 char v0 = cookie[i * 2];
2736 int8_t h0 = ws_xton(v0);
2737 char v1 = cookie[i * 2 + 1];
2738 int8_t h1 = ws_xton(v1);
2739
2740 if (h0==-1 || h1==-1) {
2741 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"
, 2741, __func__, "ssh: can't process cookie, invalid hex number: %c%c"
, v0, v1); } } while (0)
;
2742 g_strfreev(split);
2743 return;
2744 }
2745
2746 c = (h0 << 4) | h1;
2747
2748 bn_cookie->data[i] = c;
2749 }
2750 ssh_bignum * bn_priv_ht = g_new(ssh_bignum, 1)((ssh_bignum *) g_malloc_n ((1), sizeof (ssh_bignum)));
2751 bn_priv_ht->length = bn_priv->length;
2752 bn_priv_ht->data = (uint8_t *) g_memdup2(bn_priv->data, bn_priv->length);
2753 ssh_bignum * bn_cookie_ht = g_new(ssh_bignum, 1)((ssh_bignum *) g_malloc_n ((1), sizeof (ssh_bignum)));
2754 bn_cookie_ht->length = bn_cookie->length;
2755 bn_cookie_ht->data = (uint8_t *) g_memdup2(bn_cookie->data, bn_cookie->length);
2756
2757 char * type_ht = (char *) g_memdup2(type, strlen(type) + 1);
2758 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
)))
;
2759 entry_ht->type = type_ht;
2760 entry_ht->key_material = bn_priv_ht;
2761 g_hash_table_insert(ssh_master_key_map, bn_cookie_ht, entry_ht);
2762 g_strfreev(split);
2763}
2764
2765static void
2766ssh_keylog_reset(void)
2767{
2768 if (ssh_keylog_file) {
2769 fclose(ssh_keylog_file);
2770 ssh_keylog_file = NULL((void*)0);
2771 }
2772}
2773
2774static unsigned
2775ssh_kex_type(char *type)
2776{
2777 if (type) {
2778 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") )
) {
2779 return SSH_KEX_CURVE255190x00010000;
2780 }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"
) )
) {
2781 return SSH_KEX_SNTRUP761X255190x00040000;
2782 }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"
) )
) {
2783 return SSH_KEX_MLKEM768X255190x00050000;
2784 }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") )
) {
2785 return SSH_KEX_DH_GEX0x00020000;
2786 }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"
) )
) {
2787 return SSH_KEX_DH_GROUP140x00030014;
2788 }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"
) )
) {
2789 return SSH_KEX_DH_GROUP160x00030016;
2790 }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"
) )
) {
2791 return SSH_KEX_DH_GROUP180x00030018;
2792 }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"
) )
) {
2793 return SSH_KEX_DH_GROUP10x00030001;
2794 }
2795 }
2796
2797 return 0;
2798}
2799
2800static unsigned
2801ssh_kex_hash_type(char *type_string)
2802{
2803 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"
) )
) {
2804 return SSH_KEX_HASH_SHA11;
2805 }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") )
) {
2806 return SSH_KEX_HASH_SHA2562;
2807 }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]") )
) {
2808 return SSH_KEX_HASH_SHA2562;
2809 }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") )
) {
2810 return SSH_KEX_HASH_SHA5124;
2811 } else {
2812 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"
, 2812, __func__, "hash type %s not supported", type_string);
} } while (0)
;
2813 return 0;
2814 }
2815}
2816
2817static ssh_bignum *
2818ssh_kex_make_bignum(const uint8_t *data, unsigned length)
2819{
2820 // 512 bytes (4096 bits) is the maximum bignum size we're supporting
2821 // Actually we need 513 bytes, to make provision for signed values
2822 // Diffie-Hellman group 18 has 8192 bits
2823 if (length == 0 || length > 1025) {
2824 return NULL((void*)0);
2825 }
2826
2827 ssh_bignum *bn = wmem_new0(wmem_file_scope(), ssh_bignum)((ssh_bignum*)wmem_alloc0((wmem_file_scope()), sizeof(ssh_bignum
)))
;
2828 bn->data = (uint8_t *)wmem_alloc0(wmem_file_scope(), length);
2829
2830 if (data) {
2831 memcpy(bn->data, data, length);
2832 }
2833
2834 bn->length = length;
2835 return bn;
2836}
2837
2838static bool_Bool
2839ssh_read_e(tvbuff_t *tvb, int offset, struct ssh_flow_data *global_data)
2840{
2841 // store the client's public part (e) for later usage
2842 uint32_t length = tvb_get_ntohl(tvb, offset);
2843 global_data->kex_e = ssh_kex_make_bignum(NULL((void*)0), length);
2844 if (!global_data->kex_e) {
2845 return false0;
2846 }
2847 tvb_memcpy(tvb, global_data->kex_e->data, offset + 4, length);
2848 return true1;
2849}
2850
2851static bool_Bool
2852ssh_read_f(tvbuff_t *tvb, int offset, struct ssh_flow_data *global_data)
2853{
2854 // store the server's public part (f) for later usage
2855 uint32_t length = tvb_get_ntohl(tvb, offset);
2856 global_data->kex_f = ssh_kex_make_bignum(NULL((void*)0), length);
2857 if (!global_data->kex_f) {
2858 return false0;
2859 }
2860 tvb_memcpy(tvb, global_data->kex_f->data, offset + 4, length);
2861 return true1;
2862}
2863
2864static int // add support of client PQ hybrid key (e)
2865ssh_read_e_pq(tvbuff_t *tvb, int offset, struct ssh_flow_data *global_data)
2866{
2867 // Read length of PQ client key
2868 uint32_t length = tvb_get_ntohl(tvb, offset);
2869
2870 // Sanity check
2871 if (length == 0 || length > 65535) {
2872 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"
, 2872, __func__, "ssh_read_e_pq: Invalid PQ key length: %u",
length); } } while (0)
;
2873 return false0;
2874 }
2875
2876 // Free any existing data (if dissecting multiple sessions)
2877 wmem_free(wmem_file_scope(), global_data->kex_e_pq);
2878
2879 // Allocate and store the PQ client key
2880 global_data->kex_e_pq = (unsigned char *)wmem_alloc(wmem_file_scope(), length);
2881 global_data->kex_e_pq_len = length;
2882
2883 tvb_memcpy(tvb, global_data->kex_e_pq, offset + 4, length);
2884
2885 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"
, 2885, __func__, "Stored %u bytes of client PQ key - stored new_offset_client: %d - offset: %d"
, length, offset + 4 + length, offset); } } while (0)
;
2886 return offset + 4 + length; // consuming packet (advancing offset)
2887}
2888
2889static int // add support of server PQ hybrid key (f)
2890ssh_read_f_pq(tvbuff_t *tvb, int offset, struct ssh_flow_data *global_data)
2891{
2892 // Read length of PQ server key
2893 uint32_t length = tvb_get_ntohl(tvb, offset);
2894
2895 // Sanity check
2896 if (length == 0 || length > 65535) {
2897 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"
, 2897, __func__, "ssh_read_f_pq: Invalid PQ key length: %u",
length); } } while (0)
;
2898 return false0;
2899 }
2900
2901 // Free any existing data
2902 wmem_free(wmem_file_scope(), global_data->kex_f_pq);
2903
2904 // Allocate and store the PQ server key
2905 global_data->kex_f_pq = (unsigned char *)wmem_alloc(wmem_file_scope(), length);
2906 global_data->kex_f_pq_len = length;
2907
2908 tvb_memcpy(tvb, global_data->kex_f_pq, offset + 4, length);
2909
2910 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"
, 2910, __func__, "Stored %u bytes of server PQ key - stored new_offset_server: %d - offset: %d"
, length, offset + 4 + length, offset); } } while (0)
;
2911 return offset + 4 + length; // consuming packet (advancing offset)
2912}
2913
2914
2915static ssh_bignum *
2916ssh_read_mpint(tvbuff_t *tvb, int offset)
2917{
2918 // store the DH group modulo (p) for later usage
2919 int length = tvb_get_ntohl(tvb, offset);
2920 ssh_bignum * bn = ssh_kex_make_bignum(NULL((void*)0), length);
2921 if (!bn) {
2922 ws_debug("invalid bignum length %u", length)do { if (1) { ws_log_full("packet-ssh", LOG_LEVEL_DEBUG, "epan/dissectors/packet-ssh.c"
, 2922, __func__, "invalid bignum length %u", length); } } while
(0)
;
2923 return NULL((void*)0);
2924 }
2925 tvb_memcpy(tvb, bn->data, offset + 4, length);
2926 return bn;
2927}
2928
2929static void
2930ssh_keylog_hash_write_secret(struct ssh_flow_data *global_data, wmem_allocator_t* tmp_allocator)
2931{
2932 /*
2933 * This computation is defined differently for each key exchange method:
2934 * https://tools.ietf.org/html/rfc4253#page-23
2935 * https://tools.ietf.org/html/rfc5656#page-8
2936 * https://tools.ietf.org/html/rfc4419#page-4
2937 * All key exchange methods:
2938 * https://www.iana.org/assignments/ssh-parameters/ssh-parameters.xhtml#ssh-parameters-16
2939 */
2940
2941 gcry_md_hd_t hd;
2942 ssh_key_map_entry_t *entry;
2943 ssh_bignum *secret = NULL((void*)0);
2944 int length;
2945 bool_Bool client_cookie = false0;
2946
2947 ssh_keylog_read_file();
4
Calling 'ssh_keylog_read_file'
2948
2949 unsigned kex_type = ssh_kex_type(global_data->kex);
2950 unsigned kex_hash_type = ssh_kex_hash_type(global_data->kex);
2951
2952 entry = (ssh_key_map_entry_t *)g_hash_table_lookup(ssh_master_key_map, global_data->peer_data[SERVER_PEER_DATA1].bn_cookie);
2953 if (!entry) {
2954 entry = (ssh_key_map_entry_t *)g_hash_table_lookup(ssh_master_key_map, global_data->peer_data[CLIENT_PEER_DATA0].bn_cookie);
2955 client_cookie = true1;
2956 }
2957 if (!entry) {
2958 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"
, 2958, __func__, "ssh decryption: no entry in keylog file for this session"
); } } while (0)
;
2959 global_data->do_decrypt = false0;
2960 return;
2961 }
2962
2963 if (!strcmp(entry->type, "PRIVATE_KEY")) {
2964 if (client_cookie) {
2965 secret = ssh_kex_shared_secret(kex_type, global_data->kex_f, entry->key_material, global_data->kex_gex_p);
2966 } else {
2967 secret = ssh_kex_shared_secret(kex_type, global_data->kex_e, entry->key_material, global_data->kex_gex_p);
2968 }
2969 } else if (!strcmp(entry->type, "SHARED_SECRET")) {
2970 secret = ssh_kex_make_bignum(entry->key_material->data, entry->key_material->length);
2971 } else {
2972 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"
, 2972, __func__, "ssh decryption: unknown key type in keylog file"
); } } while (0)
;
2973 global_data->do_decrypt = false0;
2974 return;
2975 }
2976
2977 if (!secret) {
2978 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"
, 2978, __func__, "ssh decryption: no key material for this session"
); } } while (0)
;
2979 global_data->do_decrypt = false0;
2980 return;
2981 }
2982
2983 // shared secret data needs to be written as an mpint, and we need it later
2984 if (kex_type == SSH_KEX_SNTRUP761X255190x00040000 || kex_type == SSH_KEX_MLKEM768X255190x00050000) {
2985 // Reset array while REKEY: sanitize shared_secret:
2986 global_data->kex_shared_secret = wmem_array_new(wmem_file_scope(), 1);
2987 // For PQ KEMs: use shared_secret as-is, whether SHARED_SECRET or PRIVATE_KEY
2988 // Do NOT prepend 0x00 (OpenSSH already encodes correctly for PQ KEM)
2989 ssh_hash_buffer_put_string(global_data->kex_shared_secret, secret->data, secret->length);
2990 } else {
2991 // For all other KEX types (e.g., curve25519, ecdh-sha2, etc.)
2992 // Pad with 0x00 if MSB is set, to comply with mpint format (RFC 4251)
2993 if (secret->data[0] & 0x80) { // Stored in Big endian
2994 length = secret->length + 1;
2995 uint8_t *tmp = (uint8_t *)wmem_alloc0(tmp_allocator, length);
2996 memcpy(tmp + 1, secret->data, secret->length);
2997 tmp[0] = 0;
2998 secret->data = tmp;
2999 secret->length = length;
3000 }
3001 // Reset array while REKEY: sanitize shared_secret:
3002 global_data->kex_shared_secret = wmem_array_new(wmem_file_scope(), 1);
3003 ssh_hash_buffer_put_string(global_data->kex_shared_secret, secret->data, secret->length);
3004 }
3005
3006 wmem_array_t * kex_gex_p = wmem_array_new(tmp_allocator, 1);
3007 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);}
3008 wmem_array_t * kex_gex_g = wmem_array_new(tmp_allocator, 1);
3009 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);}
3010 wmem_array_t * kex_e = wmem_array_new(tmp_allocator, 1);
3011 if(global_data->kex_e){ssh_hash_buffer_put_string(kex_e, global_data->kex_e->data, global_data->kex_e->length);}
3012 wmem_array_t * kex_f = wmem_array_new(tmp_allocator, 1);
3013 if(global_data->kex_f){ssh_hash_buffer_put_string(kex_f, global_data->kex_f->data, global_data->kex_f->length);}
3014 wmem_array_t * kex_e_pq = wmem_array_new(tmp_allocator, 1);
3015 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);}
3016 wmem_array_t * kex_f_pq = wmem_array_new(tmp_allocator, 1);
3017 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);}
3018
3019 wmem_array_t * kex_hash_buffer = wmem_array_new(tmp_allocator, 1);
3020 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));
3021 wmem_array_append(kex_hash_buffer, wmem_array_get_raw(global_data->kex_client_version), wmem_array_get_count(global_data->kex_client_version));
3022 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));
3023 wmem_array_append(kex_hash_buffer, wmem_array_get_raw(global_data->kex_server_version), wmem_array_get_count(global_data->kex_server_version));
3024 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));
3025 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));
3026 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));
3027 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));
3028 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));
3029 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));
3030 if(kex_type==SSH_KEX_DH_GEX0x00020000){
3031 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));
3032 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));
3033 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));
3034 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));
3035 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));
3036 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));
3037 ssh_print_data("key modulo (p)", (const unsigned char *)wmem_array_get_raw(kex_gex_p), wmem_array_get_count(kex_gex_p));
3038 wmem_array_append(kex_hash_buffer, wmem_array_get_raw(kex_gex_p), wmem_array_get_count(kex_gex_p));
3039 ssh_print_data("key base (g)", (const unsigned char *)wmem_array_get_raw(kex_gex_g), wmem_array_get_count(kex_gex_g));
3040 wmem_array_append(kex_hash_buffer, wmem_array_get_raw(kex_gex_g), wmem_array_get_count(kex_gex_g));
3041 ssh_print_data("key client (e)", (const unsigned char *)wmem_array_get_raw(kex_e), wmem_array_get_count(kex_e));
3042 wmem_array_append(kex_hash_buffer, wmem_array_get_raw(kex_e), wmem_array_get_count(kex_e));
3043 ssh_print_data("key server (f)", (const unsigned char *)wmem_array_get_raw(kex_f), wmem_array_get_count(kex_f));
3044 wmem_array_append(kex_hash_buffer, wmem_array_get_raw(kex_f), wmem_array_get_count(kex_f));
3045 }
3046 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){
3047 ssh_print_data("key client (e)", (const unsigned char *)wmem_array_get_raw(kex_e), wmem_array_get_count(kex_e));
3048 wmem_array_append(kex_hash_buffer, wmem_array_get_raw(kex_e), wmem_array_get_count(kex_e));
3049 ssh_print_data("key server (f)", (const unsigned char *)wmem_array_get_raw(kex_f), wmem_array_get_count(kex_f));
3050 wmem_array_append(kex_hash_buffer, wmem_array_get_raw(kex_f), wmem_array_get_count(kex_f));
3051 }
3052 if(kex_type==SSH_KEX_CURVE255190x00010000){
3053 ssh_print_data("key client (Q_C)", (const unsigned char *)wmem_array_get_raw(kex_e), wmem_array_get_count(kex_e));
3054 wmem_array_append(kex_hash_buffer, wmem_array_get_raw(kex_e), wmem_array_get_count(kex_e));
3055 ssh_print_data("key server (Q_S)", (const unsigned char *)wmem_array_get_raw(kex_f), wmem_array_get_count(kex_f));
3056 wmem_array_append(kex_hash_buffer, wmem_array_get_raw(kex_f), wmem_array_get_count(kex_f));
3057 }
3058 if (kex_type==SSH_KEX_SNTRUP761X255190x00040000){ // Add support of sntrup761x25519
3059 ssh_print_data("key client (Q_C)", (const unsigned char *)wmem_array_get_raw(kex_e_pq), wmem_array_get_count(kex_e_pq));
3060 wmem_array_append(kex_hash_buffer, wmem_array_get_raw(kex_e_pq), wmem_array_get_count(kex_e_pq));
3061 ssh_print_data("key server (Q_S)", (const unsigned char *)wmem_array_get_raw(kex_f_pq), wmem_array_get_count(kex_f_pq));
3062 wmem_array_append(kex_hash_buffer, wmem_array_get_raw(kex_f_pq), wmem_array_get_count(kex_f_pq));
3063 ws_noisy("Switch to SSH_KEX_SNTRUP761X25519")do { if (1) { ws_log_full("packet-ssh", LOG_LEVEL_NOISY, "epan/dissectors/packet-ssh.c"
, 3063, __func__, "Switch to SSH_KEX_SNTRUP761X25519"); } } while
(0)
;
3064 }
3065 if (kex_type==SSH_KEX_MLKEM768X255190x00050000){ // Add support of mlkem768x25519
3066 ssh_print_data("key client (Q_C)", (const unsigned char *)wmem_array_get_raw(kex_e_pq), wmem_array_get_count(kex_e_pq));
3067 wmem_array_append(kex_hash_buffer, wmem_array_get_raw(kex_e_pq), wmem_array_get_count(kex_e_pq));
3068 ssh_print_data("key server (Q_S)", (const unsigned char *)wmem_array_get_raw(kex_f_pq), wmem_array_get_count(kex_f_pq));
3069 wmem_array_append(kex_hash_buffer, wmem_array_get_raw(kex_f_pq), wmem_array_get_count(kex_f_pq));
3070 ws_noisy("Switch to SSH_KEX_MLKEM768X25519")do { if (1) { ws_log_full("packet-ssh", LOG_LEVEL_NOISY, "epan/dissectors/packet-ssh.c"
, 3070, __func__, "Switch to SSH_KEX_MLKEM768X25519"); } } while
(0)
;
3071 }
3072 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));
3073 wmem_array_append(kex_hash_buffer, wmem_array_get_raw(global_data->kex_shared_secret), wmem_array_get_count(global_data->kex_shared_secret));
3074
3075 ssh_print_data("exchange", (const unsigned char *)wmem_array_get_raw(kex_hash_buffer), wmem_array_get_count(kex_hash_buffer));
3076
3077 unsigned hash_len = 32;
3078 if(kex_hash_type==SSH_KEX_HASH_SHA11) {
3079 gcry_md_open(&hd, GCRY_MD_SHA1, 0);
3080 hash_len = 20;
3081 } else if(kex_hash_type==SSH_KEX_HASH_SHA2562) {
3082 gcry_md_open(&hd, GCRY_MD_SHA256, 0);
3083 hash_len = 32;
3084 } else if(kex_hash_type==SSH_KEX_HASH_SHA5124) {
3085 gcry_md_open(&hd, GCRY_MD_SHA512, 0);
3086 hash_len = 64;
3087 } else {
3088 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"
, 3088, __func__, "kex_hash_type type %d not supported", kex_hash_type
); } } while (0)
;
3089 return;
3090 }
3091 uint8_t *exchange_hash = (uint8_t *)wmem_alloc0(wmem_file_scope(), hash_len);
3092 gcry_md_write(hd, wmem_array_get_raw(kex_hash_buffer), wmem_array_get_count(kex_hash_buffer));
3093 memcpy(exchange_hash, gcry_md_read(hd, 0), hash_len);
3094 gcry_md_close(hd);
3095 ssh_print_data("hash", exchange_hash, hash_len);
3096 global_data->secret = secret;
3097 ssh_derive_symmetric_keys(secret, exchange_hash, hash_len, global_data);
3098}
3099
3100// the purpose of this function is to deal with all different kex methods
3101static ssh_bignum *
3102ssh_kex_shared_secret(int kex_type, ssh_bignum *pub, ssh_bignum *priv, ssh_bignum *modulo)
3103{
3104 DISSECTOR_ASSERT(pub != NULL)((void) ((pub != ((void*)0)) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/dissectors/packet-ssh.c"
, 3104, "pub != ((void*)0)"))))
;
3105 DISSECTOR_ASSERT(priv != NULL)((void) ((priv != ((void*)0)) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/dissectors/packet-ssh.c"
, 3105, "priv != ((void*)0)"))))
;
3106
3107 ssh_bignum *secret = ssh_kex_make_bignum(NULL((void*)0), pub->length);
3108 if (!secret) {
3109 ws_debug("invalid key length %u", pub->length)do { if (1) { ws_log_full("packet-ssh", LOG_LEVEL_DEBUG, "epan/dissectors/packet-ssh.c"
, 3109, __func__, "invalid key length %u", pub->length); }
} while (0)
;
3110 return NULL((void*)0);
3111 }
3112
3113 if(kex_type==SSH_KEX_DH_GEX0x00020000){
3114 if (modulo == NULL((void*)0)) {
3115 ws_debug("Missing group modulo")do { if (1) { ws_log_full("packet-ssh", LOG_LEVEL_DEBUG, "epan/dissectors/packet-ssh.c"
, 3115, __func__, "Missing group modulo"); } } while (0)
;
3116 return NULL((void*)0);
3117 }
3118 gcry_mpi_t b = NULL((void*)0);
3119 gcry_mpi_scan(&b, GCRYMPI_FMT_USG, pub->data, pub->length, NULL((void*)0));
3120 gcry_mpi_t d = NULL((void*)0), e = NULL((void*)0), m = NULL((void*)0);
3121 size_t result_len = 0;
3122 d = gcry_mpi_new(pub->length*8);
3123 gcry_mpi_scan(&e, GCRYMPI_FMT_USG, priv->data, priv->length, NULL((void*)0));
3124 gcry_mpi_scan(&m, GCRYMPI_FMT_USG, modulo->data, modulo->length, NULL((void*)0));
3125 gcry_mpi_powm(d, b, e, m); // gcry_mpi_powm(d, b, e, m) => d = b^e % m
3126 gcry_mpi_print(GCRYMPI_FMT_USG, secret->data, secret->length, &result_len, d);
3127 secret->length = (unsigned)result_len; // Should not be larger than what fits in a 32-bit unsigned integer...
3128 gcry_mpi_release(d);
3129 gcry_mpi_release(b);
3130 gcry_mpi_release(e);
3131 gcry_mpi_release(m);
3132
3133 }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){
3134 gcry_mpi_t m = NULL((void*)0);
3135 if(kex_type==SSH_KEX_DH_GROUP10x00030001){
3136 static const uint8_t p[] = {
3137 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
3138 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
3139 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
3140 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
3141 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
3142 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
3143 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
3144 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,};
3145 gcry_mpi_scan(&m, GCRYMPI_FMT_USG, p, sizeof(p), NULL((void*)0));
3146 }else if(kex_type==SSH_KEX_DH_GROUP140x00030014){
3147//p:FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF
3148 static const uint8_t p[] = {
3149 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
3150 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
3151 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
3152 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
3153 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
3154 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
3155 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
3156 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
3157 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
3158 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
3159 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
3160 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
3161 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
3162 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
3163 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
3164 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
3165 gcry_mpi_scan(&m, GCRYMPI_FMT_USG, p, sizeof(p), NULL((void*)0));
3166 }else if(kex_type==SSH_KEX_DH_GROUP160x00030016){
3167//p:FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF
3168 static const uint8_t p[] = {
3169 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
3170 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
3171 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
3172 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
3173 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
3174 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
3175 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
3176 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
3177 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
3178 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
3179 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
3180 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
3181 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
3182 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
3183 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
3184 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33,
3185 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A,
3186 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
3187 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D,
3188 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64,
3189 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
3190 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2,
3191 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E,
3192 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
3193 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C,
3194 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8,
3195 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
3196 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2,
3197 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF,
3198 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
3199 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F,
3200 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,};
3201 gcry_mpi_scan(&m, GCRYMPI_FMT_USG, p, sizeof(p), NULL((void*)0));
3202 }else if(kex_type==SSH_KEX_DH_GROUP180x00030018){
3203//p:FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E438777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F5683423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD922222E04A4037C0713EB57A81A23F0C73473FC646CEA306B4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A364597E899A0255DC164F31CC50846851DF9AB48195DED7EA1B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F924009438B481C6CD7889A002ED5EE382BC9190DA6FC026E479558E4475677E9AA9E3050E2765694DFC81F56E880B96E7160C980DD98EDD3DFFFFFFFFFFFFFFFFF
3204 static const uint8_t p[] = {
3205 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
3206 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
3207 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
3208 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
3209 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
3210 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
3211 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
3212 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
3213 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
3214 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
3215 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
3216 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
3217 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
3218 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
3219 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
3220 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33,
3221 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A,
3222 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
3223 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D,
3224 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64,
3225 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
3226 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2,
3227 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E,
3228 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
3229 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C,
3230 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8,
3231 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
3232 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2,
3233 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF,
3234 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
3235 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F,
3236 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92, 0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26,
3237 0xC1, 0xD4, 0xDC, 0xB2, 0x60, 0x26, 0x46, 0xDE, 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD,
3238 0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E, 0xE5, 0xDB, 0x38, 0x2F, 0x41, 0x30, 0x01, 0xAE,
3239 0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31, 0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18,
3240 0xDA, 0x3E, 0xDB, 0xEB, 0xCF, 0x9B, 0x14, 0xED, 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B,
3241 0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B, 0x33, 0x20, 0x51, 0x51, 0x2B, 0xD7, 0xAF, 0x42,
3242 0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF, 0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC,
3243 0xF0, 0x32, 0xEA, 0x15, 0xD1, 0x72, 0x1D, 0x03, 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6,
3244 0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82, 0xB5, 0xA8, 0x40, 0x31, 0x90, 0x0B, 0x1C, 0x9E,
3245 0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3, 0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE,
3246 0x0F, 0x1D, 0x45, 0xB7, 0xFF, 0x58, 0x5A, 0xC5, 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA,
3247 0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8, 0x14, 0xCC, 0x5E, 0xD2, 0x0F, 0x80, 0x37, 0xE0,
3248 0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28, 0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76,
3249 0xF5, 0x50, 0xAA, 0x3D, 0x8A, 0x1F, 0xBF, 0xF0, 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C,
3250 0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, 0x38, 0x7F, 0xE8, 0xD7, 0x6E, 0x3C, 0x04, 0x68,
3251 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE, 0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6,
3252 0xE6, 0x94, 0xF9, 0x1E, 0x6D, 0xBE, 0x11, 0x59, 0x74, 0xA3, 0x92, 0x6F, 0x12, 0xFE, 0xE5, 0xE4,
3253 0x38, 0x77, 0x7C, 0xB6, 0xA9, 0x32, 0xDF, 0x8C, 0xD8, 0xBE, 0xC4, 0xD0, 0x73, 0xB9, 0x31, 0xBA,
3254 0x3B, 0xC8, 0x32, 0xB6, 0x8D, 0x9D, 0xD3, 0x00, 0x74, 0x1F, 0xA7, 0xBF, 0x8A, 0xFC, 0x47, 0xED,
3255 0x25, 0x76, 0xF6, 0x93, 0x6B, 0xA4, 0x24, 0x66, 0x3A, 0xAB, 0x63, 0x9C, 0x5A, 0xE4, 0xF5, 0x68,
3256 0x34, 0x23, 0xB4, 0x74, 0x2B, 0xF1, 0xC9, 0x78, 0x23, 0x8F, 0x16, 0xCB, 0xE3, 0x9D, 0x65, 0x2D,
3257 0xE3, 0xFD, 0xB8, 0xBE, 0xFC, 0x84, 0x8A, 0xD9, 0x22, 0x22, 0x2E, 0x04, 0xA4, 0x03, 0x7C, 0x07,
3258 0x13, 0xEB, 0x57, 0xA8, 0x1A, 0x23, 0xF0, 0xC7, 0x34, 0x73, 0xFC, 0x64, 0x6C, 0xEA, 0x30, 0x6B,
3259 0x4B, 0xCB, 0xC8, 0x86, 0x2F, 0x83, 0x85, 0xDD, 0xFA, 0x9D, 0x4B, 0x7F, 0xA2, 0xC0, 0x87, 0xE8,
3260 0x79, 0x68, 0x33, 0x03, 0xED, 0x5B, 0xDD, 0x3A, 0x06, 0x2B, 0x3C, 0xF5, 0xB3, 0xA2, 0x78, 0xA6,
3261 0x6D, 0x2A, 0x13, 0xF8, 0x3F, 0x44, 0xF8, 0x2D, 0xDF, 0x31, 0x0E, 0xE0, 0x74, 0xAB, 0x6A, 0x36,
3262 0x45, 0x97, 0xE8, 0x99, 0xA0, 0x25, 0x5D, 0xC1, 0x64, 0xF3, 0x1C, 0xC5, 0x08, 0x46, 0x85, 0x1D,
3263 0xF9, 0xAB, 0x48, 0x19, 0x5D, 0xED, 0x7E, 0xA1, 0xB1, 0xD5, 0x10, 0xBD, 0x7E, 0xE7, 0x4D, 0x73,
3264 0xFA, 0xF3, 0x6B, 0xC3, 0x1E, 0xCF, 0xA2, 0x68, 0x35, 0x90, 0x46, 0xF4, 0xEB, 0x87, 0x9F, 0x92,
3265 0x40, 0x09, 0x43, 0x8B, 0x48, 0x1C, 0x6C, 0xD7, 0x88, 0x9A, 0x00, 0x2E, 0xD5, 0xEE, 0x38, 0x2B,
3266 0xC9, 0x19, 0x0D, 0xA6, 0xFC, 0x02, 0x6E, 0x47, 0x95, 0x58, 0xE4, 0x47, 0x56, 0x77, 0xE9, 0xAA,
3267 0x9E, 0x30, 0x50, 0xE2, 0x76, 0x56, 0x94, 0xDF, 0xC8, 0x1F, 0x56, 0xE8, 0x80, 0xB9, 0x6E, 0x71,
3268 0x60, 0xC9, 0x80, 0xDD, 0x98, 0xED, 0xD3, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,};
3269 gcry_mpi_scan(&m, GCRYMPI_FMT_USG, p, sizeof(p), NULL((void*)0));
3270 }
3271
3272 gcry_mpi_t b = NULL((void*)0);
3273 gcry_mpi_scan(&b, GCRYMPI_FMT_USG, pub->data, pub->length, NULL((void*)0));
3274 gcry_mpi_t d = NULL((void*)0), e = NULL((void*)0);
3275 size_t result_len = 0;
3276 d = gcry_mpi_new(pub->length*8);
3277 gcry_mpi_scan(&e, GCRYMPI_FMT_USG, priv->data, priv->length, NULL((void*)0));
3278 gcry_mpi_powm(d, b, e, m); // gcry_mpi_powm(d, b, e, m) => d = b^e % m
3279 gcry_mpi_print(GCRYMPI_FMT_USG, secret->data, secret->length, &result_len, d);
3280 secret->length = (unsigned)result_len; // Should not be larger than what fits in a 32-bit unsigned integer...
3281 gcry_mpi_release(d);
3282 gcry_mpi_release(b);
3283 gcry_mpi_release(e);
3284 gcry_mpi_release(m);
3285 }else if(kex_type==SSH_KEX_CURVE255190x00010000){
3286 if (crypto_scalarmult_curve25519(secret->data, priv->data, pub->data)) {
3287 ws_debug("curve25519: can't compute shared secret")do { if (1) { ws_log_full("packet-ssh", LOG_LEVEL_DEBUG, "epan/dissectors/packet-ssh.c"
, 3287, __func__, "curve25519: can't compute shared secret");
} } while (0)
;
3288 return NULL((void*)0);
3289 }
3290 } else {
3291 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"
, 3291, __func__, "kex_type type %d not supported", kex_type)
; } } while (0)
;
3292 return 0;
3293 }
3294
3295 return secret;
3296}
3297
3298static char *
3299ssh_string(wmem_allocator_t* allocator, const uint8_t *string, unsigned length)
3300{
3301 char *ssh_string = (char *)wmem_alloc(allocator, length + 4);
3302 ssh_string[0] = (length >> 24) & 0xff;
3303 ssh_string[1] = (length >> 16) & 0xff;
3304 ssh_string[2] = (length >> 8) & 0xff;
3305 ssh_string[3] = length & 0xff;
3306 memcpy(ssh_string + 4, string, length);
3307 return ssh_string;
3308}
3309
3310static void
3311ssh_hash_buffer_put_string(wmem_array_t *buffer, const uint8_t *string,
3312 unsigned length)
3313{
3314 if (!buffer) {
3315 return;
3316 }
3317
3318 char *string_with_length = ssh_string(wmem_array_get_allocator(buffer), string, length);
3319 wmem_array_append(buffer, string_with_length, length + 4);
3320}
3321
3322static void
3323ssh_hash_buffer_put_uint32(wmem_array_t *buffer, unsigned val)
3324{
3325 if (!buffer) {
3326 return;
3327 }
3328
3329 char buf[4];
3330 buf[0] = (val >> 24); buf[1] = (val >> 16); buf[2] = (val >> 8); buf[3] = (val >> 0);
3331 wmem_array_append(buffer, buf, 4);
3332}
3333
3334static void ssh_derive_symmetric_keys(ssh_bignum *secret, uint8_t *exchange_hash,
3335 unsigned hash_length, struct ssh_flow_data *global_data)
3336{
3337 if (!global_data->session_id) {
3338 global_data->session_id = exchange_hash;
3339 global_data->session_id_length = hash_length;
3340 }
3341
3342 unsigned int we_need = 0;
3343 for(int peer_cnt=0;peer_cnt<2;peer_cnt++){
3344 struct ssh_peer_data * peer_data = &global_data->peer_data[peer_cnt];
3345 // required size of key depends on cipher used. chacha20 wants 64 bytes
3346 unsigned need = 0;
3347 if (GCRY_CIPHER_CHACHA20 == peer_data->cipher_id) {
3348 need = 64;
3349 } else if (CIPHER_AES128_CBC0x00020001 == peer_data->cipher_id || CIPHER_AES128_CTR0x00010001 == peer_data->cipher_id || CIPHER_AES128_GCM0x00040001 == peer_data->cipher_id) {
3350 need = 16;
3351 } else if (CIPHER_AES192_CBC0x00020002 == peer_data->cipher_id || CIPHER_AES192_CTR0x00010003 == peer_data->cipher_id) {
3352 need = 24;
3353 } else if (CIPHER_AES256_CBC0x00020004 == peer_data->cipher_id || CIPHER_AES256_CTR0x00010004 == peer_data->cipher_id || CIPHER_AES256_GCM0x00040004 == peer_data->cipher_id) {
3354 need = 32;
3355 } else {
3356 ssh_debug_printf("ssh: cipher (%d) is unknown or not set\n", peer_data->cipher_id);
3357 ssh_debug_flush();
3358 }
3359 if(peer_data->mac_id == CIPHER_MAC_SHA2_2560x00020001){
3360 need = 32;
3361 }else{
3362 ssh_debug_printf("ssh: MAC (%d) is unknown or not set\n", peer_data->mac_id);
3363 ssh_debug_flush();
3364 }
3365 if (we_need<need) {
3366 we_need = need;
3367 }
3368 }
3369
3370 for (int i = 0; i < 6; i ++) {
3371 ssh_derive_symmetric_key(secret, exchange_hash, hash_length,
3372 'A' + i, &global_data->new_keys[i], global_data, we_need);
3373 if(i==0){ ssh_print_data("Initial IV client to server", global_data->new_keys[i].data, global_data->new_keys[i].length);
3374 }else if(i==1){ ssh_print_data("Initial IV server to client", global_data->new_keys[i].data, global_data->new_keys[i].length);
3375 }else if(i==2){ ssh_print_data("Encryption key client to server", global_data->new_keys[i].data, global_data->new_keys[i].length);
3376 }else if(i==3){ ssh_print_data("Encryption key server to client", global_data->new_keys[i].data, global_data->new_keys[i].length);
3377 }else if(i==4){ ssh_print_data("Integrity key client to server", global_data->new_keys[i].data, global_data->new_keys[i].length);
3378 }else if(i==5){ ssh_print_data("Integrity key server to client", global_data->new_keys[i].data, global_data->new_keys[i].length);
3379 }
3380 }
3381}
3382
3383static void ssh_derive_symmetric_key(ssh_bignum *secret, const uint8_t *exchange_hash,
3384 unsigned hash_length, char id, ssh_bignum *result_key,
3385 struct ssh_flow_data *global_data, unsigned we_need)
3386{
3387 gcry_md_hd_t hd;
3388
3389 unsigned kex_hash_type = ssh_kex_hash_type(global_data->kex);
3390 int algo = GCRY_MD_SHA256;
3391 if(kex_hash_type==SSH_KEX_HASH_SHA11){
3392 algo = GCRY_MD_SHA1;
3393 }else if(kex_hash_type==SSH_KEX_HASH_SHA2562){
3394 algo = GCRY_MD_SHA256;
3395 }else if(kex_hash_type==SSH_KEX_HASH_SHA5124){
3396 algo = GCRY_MD_SHA512;
3397 }
3398 unsigned len = gcry_md_get_algo_dlen(algo);
3399
3400 result_key->data = (unsigned char *)wmem_alloc(wmem_file_scope(), we_need);
3401
3402 char *secret_with_length = ssh_string(NULL((void*)0), secret->data, secret->length);
3403
3404 if (gcry_md_open(&hd, algo, 0) == 0) {
3405 gcry_md_write(hd, secret_with_length, secret->length + 4);
3406 gcry_md_write(hd, exchange_hash, hash_length);
3407 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)
;
3408 gcry_md_write(hd, global_data->session_id, hash_length);
3409 unsigned add_length = MIN(len, we_need)(((len) < (we_need)) ? (len) : (we_need));
3410 memcpy(result_key->data, gcry_md_read(hd, 0), add_length);
3411 gcry_md_close(hd);
3412 }
3413
3414 // expand key
3415 for (unsigned have = len; have < we_need; have += len) {
3416 if (gcry_md_open(&hd, algo, 0) == 0) {
3417 gcry_md_write(hd, secret_with_length, secret->length + 4);
3418 gcry_md_write(hd, exchange_hash, hash_length);
3419 gcry_md_write(hd, result_key->data+have-len, len);
3420 unsigned add_length = MIN(len, we_need - have)(((len) < (we_need - have)) ? (len) : (we_need - have));
3421 memcpy(result_key->data+have, gcry_md_read(hd, 0), add_length);
3422 gcry_md_close(hd);
3423 }
3424 }
3425 wmem_free(NULL((void*)0), secret_with_length);
3426
3427 result_key->length = we_need;
3428}
3429
3430static void
3431ssh_choose_enc_mac(struct ssh_flow_data *global_data)
3432{
3433 for(int peer_cnt=0;peer_cnt<2;peer_cnt++){
3434 struct ssh_peer_data * peer_data = &global_data->peer_data[peer_cnt];
3435 ssh_choose_algo(global_data->peer_data[CLIENT_PEER_DATA0].enc_proposals[peer_cnt],
3436 global_data->peer_data[SERVER_PEER_DATA1].enc_proposals[peer_cnt],
3437 &peer_data->enc);
3438 /* some ciphers have their own MAC so the "negotiated" one is meaningless */
3439 if(peer_data->enc && (0 == strcmp(peer_data->enc, "[email protected]") ||
3440 0 == strcmp(peer_data->enc, "[email protected]"))) {
3441 peer_data->mac = wmem_strdup(wmem_file_scope(), (const char *)"<implicit>");
3442 peer_data->mac_length = 16;
3443 peer_data->length_is_plaintext = 1;
3444 }
3445 else if(peer_data->enc && 0 == strcmp(peer_data->enc, "[email protected]")) {
3446 peer_data->mac = wmem_strdup(wmem_file_scope(), (const char *)"<implicit>");
3447 peer_data->mac_length = 16;
3448 }
3449 else {
3450 ssh_choose_algo(global_data->peer_data[CLIENT_PEER_DATA0].mac_proposals[peer_cnt],
3451 global_data->peer_data[SERVER_PEER_DATA1].mac_proposals[peer_cnt],
3452 &peer_data->mac);
3453 ssh_set_mac_length(peer_data);
3454 }
3455 ssh_choose_algo(global_data->peer_data[CLIENT_PEER_DATA0].comp_proposals[peer_cnt],
3456 global_data->peer_data[SERVER_PEER_DATA1].comp_proposals[peer_cnt],
3457 &peer_data->comp);
3458 }
3459
3460 ssh_decryption_set_cipher_id(&global_data->peer_data[CLIENT_PEER_DATA0]);
3461 ssh_decryption_set_mac_id(&global_data->peer_data[CLIENT_PEER_DATA0]);
3462 ssh_decryption_set_cipher_id(&global_data->peer_data[SERVER_PEER_DATA1]);
3463 ssh_decryption_set_mac_id(&global_data->peer_data[SERVER_PEER_DATA1]);
3464}
3465
3466static void
3467ssh_decryption_set_cipher_id(struct ssh_peer_data *peer)
3468{
3469 char *cipher_name = peer->enc;
3470
3471 if (!cipher_name) {
3472 peer->cipher = NULL((void*)0);
3473 ws_debug("ERROR: cipher_name is NULL")do { if (1) { ws_log_full("packet-ssh", LOG_LEVEL_DEBUG, "epan/dissectors/packet-ssh.c"
, 3473, __func__, "ERROR: cipher_name is NULL"); } } while (0
)
;
3474 } else if (0 == strcmp(cipher_name, "[email protected]")) { // add [email protected]
3475 peer->cipher_id = GCRY_CIPHER_CHACHA20;
3476 } else if (0 == strcmp(cipher_name, "chacha20-poly1305")) { // add chacha20-poly1305
3477 peer->cipher_id = GCRY_CIPHER_CHACHA20;
3478 } else if (0 == strcmp(cipher_name, "[email protected]")) {
3479 peer->cipher_id = CIPHER_AES128_GCM0x00040001;
3480 } else if (0 == strcmp(cipher_name, "aes128-gcm")) {
3481 peer->cipher_id = CIPHER_AES128_GCM0x00040001;
3482 } else if (0 == strcmp(cipher_name, "[email protected]")) {
3483 peer->cipher_id = CIPHER_AES256_GCM0x00040004;
3484 } else if (0 == strcmp(cipher_name, "aes256-gcm")) {
3485 peer->cipher_id = CIPHER_AES256_GCM0x00040004;
3486 } else if (0 == strcmp(cipher_name, "aes128-cbc")) {
3487 peer->cipher_id = CIPHER_AES128_CBC0x00020001;
3488 } else if (0 == strcmp(cipher_name, "aes192-cbc")) {
3489 peer->cipher_id = CIPHER_AES192_CBC0x00020002;
3490 } else if (0 == strcmp(cipher_name, "aes256-cbc")) {
3491 peer->cipher_id = CIPHER_AES256_CBC0x00020004;
3492 } else if (0 == strcmp(cipher_name, "aes128-ctr")) {
3493 peer->cipher_id = CIPHER_AES128_CTR0x00010001;
3494 } else if (0 == strcmp(cipher_name, "aes192-ctr")) {
3495 peer->cipher_id = CIPHER_AES192_CTR0x00010003;
3496 } else if (0 == strcmp(cipher_name, "aes256-ctr")) {
3497 peer->cipher_id = CIPHER_AES256_CTR0x00010004;
3498 } else if (0 == strcmp(cipher_name, "none")) {
3499 peer->cipher_id = CIPHER_NULL0x00080000;
3500 peer->length_is_plaintext = 1;
3501 } else {
3502 peer->cipher = NULL((void*)0);
3503 ws_debug("decryption not supported: %s", cipher_name)do { if (1) { ws_log_full("packet-ssh", LOG_LEVEL_DEBUG, "epan/dissectors/packet-ssh.c"
, 3503, __func__, "decryption not supported: %s", cipher_name
); } } while (0)
;
3504 }
3505}
3506
3507static void
3508ssh_decryption_set_mac_id(struct ssh_peer_data *peer)
3509{
3510 char *mac_name = peer->mac;
3511
3512 if (!mac_name) {
3513 peer->mac = NULL((void*)0);
3514 ws_debug("ERROR: mac_name is NULL")do { if (1) { ws_log_full("packet-ssh", LOG_LEVEL_DEBUG, "epan/dissectors/packet-ssh.c"
, 3514, __func__, "ERROR: mac_name is NULL"); } } while (0)
;
3515 } else if (0 == strcmp(mac_name, "hmac-sha2-256")) {
3516 peer->mac_id = CIPHER_MAC_SHA2_2560x00020001;
3517 } else {
3518 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"
, 3518, __func__, "decryption MAC not supported: %s", mac_name
); } } while (0)
;
3519 }
3520}
3521
3522static bool_Bool
3523gcry_cipher_destroy_cb(wmem_allocator_t *allocator _U___attribute__((unused)), wmem_cb_event_t event _U___attribute__((unused)), void *user_data)
3524{
3525 gcry_cipher_hd_t hd = (gcry_cipher_hd_t)user_data;
3526
3527 gcry_cipher_close(hd);
3528
3529 return false0;
3530}
3531
3532static void
3533ssh_decryption_setup_cipher(struct ssh_peer_data *peer_data,
3534 ssh_bignum *iv, ssh_bignum *key)
3535{
3536 gcry_error_t err;
3537 gcry_cipher_hd_t *hd1, *hd2;
3538
3539 hd1 = &peer_data->cipher;
3540 hd2 = &peer_data->cipher_2;
3541
3542 if (GCRY_CIPHER_CHACHA20 == peer_data->cipher_id) {
3543 if (gcry_cipher_open(hd1, GCRY_CIPHER_CHACHA20, GCRY_CIPHER_MODE_STREAM, 0) ||
3544 gcry_cipher_open(hd2, GCRY_CIPHER_CHACHA20, GCRY_CIPHER_MODE_STREAM, 0)) {
3545 gcry_cipher_close(*hd1);
3546 gcry_cipher_close(*hd2);
3547 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"
, 3547, __func__, "ssh: can't open chacha20 cipher handles");
} } while (0)
;
3548 return;
3549 }
3550
3551 uint8_t k1[32];
3552 uint8_t k2[32];
3553 if(key->data){
3554 memcpy(k1, key->data, 32);
3555 memcpy(k2, key->data + 32, 32);
3556 }else{
3557 memset(k1, 0, 32);
3558 memset(k2, 0, 32);
3559 }
3560
3561 ssh_debug_printf("ssh: cipher is chacha20\n");
3562 ssh_print_data("key 1", k1, 32);
3563 ssh_print_data("key 2", k2, 32);
3564
3565 if ((err = gcry_cipher_setkey(*hd1, k1, 32))) {
3566 gcry_cipher_close(*hd1);
3567 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"
, 3567, __func__, "ssh: can't set chacha20 cipher key %s", gcry_strerror
(err)); } } while (0)
;
3568 return;
3569 }
3570
3571 if ((err = gcry_cipher_setkey(*hd2, k2, 32))) {
3572 gcry_cipher_close(*hd1);
3573 gcry_cipher_close(*hd2);
3574 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"
, 3574, __func__, "ssh: can't set chacha20 cipher key %s", gcry_strerror
(err)); } } while (0)
;
3575 return;
3576 }
3577
3578 wmem_register_callback(wmem_file_scope(), gcry_cipher_destroy_cb, *hd1);
3579 wmem_register_callback(wmem_file_scope(), gcry_cipher_destroy_cb, *hd2);
3580
3581 } else if (CIPHER_AES128_CBC0x00020001 == peer_data->cipher_id || CIPHER_AES192_CBC0x00020002 == peer_data->cipher_id || CIPHER_AES256_CBC0x00020004 == peer_data->cipher_id) {
3582 int iKeyLen = CIPHER_AES128_CBC0x00020001 == peer_data->cipher_id?16:CIPHER_AES192_CBC0x00020002 == peer_data->cipher_id?24:32;
3583 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)) {
3584 gcry_cipher_close(*hd1);
3585 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"
, 3585, __func__, "ssh: can't open aes%d cipher handle", iKeyLen
*8); } } while (0)
;
3586 return;
3587 }
3588 uint8_t k1[32], iv1[16];
3589 if(key->data){
3590 memcpy(k1, key->data, iKeyLen);
3591 }else{
3592 memset(k1, 0, iKeyLen);
3593 }
3594 if(iv->data){
3595 memcpy(iv1, iv->data, 16);
3596 }else{
3597 memset(iv1, 0, 16);
3598 }
3599
3600 ssh_debug_printf("ssh: cipher is aes%d-cbc\n", iKeyLen*8);
3601 ssh_print_data("key", k1, iKeyLen);
3602 ssh_print_data("iv", iv1, 16);
3603
3604 if ((err = gcry_cipher_setkey(*hd1, k1, iKeyLen))) {
3605 gcry_cipher_close(*hd1);
3606 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"
, 3606, __func__, "ssh: can't set aes%d cipher key", iKeyLen*
8); } } while (0)
;
3607 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"
, 3607, __func__, "libgcrypt: %d %s %s", gcry_err_code(err), gcry_strsource
(err), gcry_strerror(err)); } } while (0)
;
3608 return;
3609 }
3610
3611 if ((err = gcry_cipher_setiv(*hd1, iv1, 16))) {
3612 gcry_cipher_close(*hd1);
3613 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"
, 3613, __func__, "ssh: can't set aes%d cipher iv", iKeyLen*8
); } } while (0)
;
3614 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"
, 3614, __func__, "libgcrypt: %d %s %s", gcry_err_code(err), gcry_strsource
(err), gcry_strerror(err)); } } while (0)
;
3615 return;
3616 }
3617
3618 wmem_register_callback(wmem_file_scope(), gcry_cipher_destroy_cb, *hd1);
3619
3620 } else if (CIPHER_AES128_CTR0x00010001 == peer_data->cipher_id || CIPHER_AES192_CTR0x00010003 == peer_data->cipher_id || CIPHER_AES256_CTR0x00010004 == peer_data->cipher_id) {
3621 int iKeyLen = CIPHER_AES128_CTR0x00010001 == peer_data->cipher_id?16:CIPHER_AES192_CTR0x00010003 == peer_data->cipher_id?24:32;
3622 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)) {
3623 gcry_cipher_close(*hd1);
3624 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"
, 3624, __func__, "ssh: can't open aes%d cipher handle", iKeyLen
*8); } } while (0)
;
3625 return;
3626 }
3627 uint8_t k1[32], iv1[16];
3628 if(key->data){
3629 memcpy(k1, key->data, iKeyLen);
3630 }else{
3631 memset(k1, 0, iKeyLen);
3632 }
3633 if(iv->data){
3634 memcpy(iv1, iv->data, 16);
3635 }else{
3636 memset(iv1, 0, 16);
3637 }
3638
3639 ssh_debug_printf("ssh: cipher is aes%d-ctr\n", iKeyLen*8);
3640 ssh_print_data("key", k1, iKeyLen);
3641 ssh_print_data("iv", iv1, 16);
3642
3643 if ((err = gcry_cipher_setkey(*hd1, k1, iKeyLen))) {
3644 gcry_cipher_close(*hd1);
3645 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"
, 3645, __func__, "ssh: can't set aes%d cipher key", iKeyLen*
8); } } while (0)
;
3646 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"
, 3646, __func__, "libgcrypt: %d %s %s", gcry_err_code(err), gcry_strsource
(err), gcry_strerror(err)); } } while (0)
;
3647 return;
3648 }
3649
3650 if ((err = gcry_cipher_setctr(*hd1, iv1, 16))) {
3651 gcry_cipher_close(*hd1);
3652 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"
, 3652, __func__, "ssh: can't set aes%d cipher iv", iKeyLen*8
); } } while (0)
;
3653 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"
, 3653, __func__, "libgcrypt: %d %s %s", gcry_err_code(err), gcry_strsource
(err), gcry_strerror(err)); } } while (0)
;
3654 return;
3655 }
3656
3657 wmem_register_callback(wmem_file_scope(), gcry_cipher_destroy_cb, *hd1);
3658
3659 } else if (CIPHER_AES128_GCM0x00040001 == peer_data->cipher_id || CIPHER_AES256_GCM0x00040004 == peer_data->cipher_id) {
3660 int iKeyLen = CIPHER_AES128_GCM0x00040001 == peer_data->cipher_id?16:32;
3661 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)) {
3662 gcry_cipher_close(*hd1);
3663 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"
, 3663, __func__, "ssh: can't open aes%d cipher handle", iKeyLen
*8); } } while (0)
;
3664 return;
3665 }
3666
3667 uint8_t k1[32], iv2[12];
3668 if(key->data){
3669 memcpy(k1, key->data, iKeyLen);
3670 }else{
3671 memset(k1, 0, iKeyLen);
3672 }
3673 if(iv->data){
3674 memcpy(peer_data->iv, iv->data, 12);
3675 }else{
3676 memset(iv2, 0, 12);
3677 }
3678
3679 ssh_debug_printf("ssh: cipher is aes%d-gcm\n", iKeyLen*8);
3680 ssh_print_data("key", k1, iKeyLen);
3681 ssh_print_data("iv", peer_data->iv, 12);
3682
3683 if ((err = gcry_cipher_setkey(*hd1, k1, iKeyLen))) {
3684 gcry_cipher_close(*hd1);
3685 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"
, 3685, __func__, "ssh: can't set aes%d cipher key", iKeyLen*
8); } } while (0)
;
3686 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"
, 3686, __func__, "libgcrypt: %d %s %s", gcry_err_code(err), gcry_strsource
(err), gcry_strerror(err)); } } while (0)
;
3687 return;
3688 }
3689
3690 wmem_register_callback(wmem_file_scope(), gcry_cipher_destroy_cb, *hd1);
3691
3692 } else {
3693 ssh_debug_printf("ssh: cipher (%d) is unknown or not set\n", peer_data->cipher_id);
3694 }
3695}
3696
3697static void
3698ssh_decryption_setup_mac(struct ssh_peer_data *peer_data,
3699 ssh_bignum *iv)
3700{
3701 if(peer_data->mac_id == CIPHER_MAC_SHA2_2560x00020001){
3702 if(iv->data){
3703 memcpy(peer_data->hmac_iv, iv->data, 32);
3704 }else{
3705 memset(peer_data->hmac_iv, 0, 32);
3706 }
3707 peer_data->hmac_iv_len = 32;
3708 ssh_debug_printf("ssh: mac is hmac-sha2-256\n");
3709 ssh_print_data("iv", peer_data->hmac_iv, peer_data->hmac_iv_len);
3710 }else{
3711 ws_debug("ssh: unsupported MAC")do { if (1) { ws_log_full("packet-ssh", LOG_LEVEL_DEBUG, "epan/dissectors/packet-ssh.c"
, 3711, __func__, "ssh: unsupported MAC"); } } while (0)
;
3712 }
3713}
3714
3715/* libgcrypt wrappers for HMAC/message digest operations {{{ */
3716/* hmac abstraction layer */
3717#define SSH_HMACgcry_md_hd_t gcry_md_hd_t
3718
3719static inline int
3720ssh_hmac_init(SSH_HMACgcry_md_hd_t* md, const void * key, int len, int algo)
3721{
3722 gcry_error_t err;
3723 const char *err_str, *err_src;
3724
3725 err = gcry_md_open(md,algo, GCRY_MD_FLAG_HMAC);
3726 if (err != 0) {
3727 err_str = gcry_strerror(err);
3728 err_src = gcry_strsource(err);
3729 ssh_debug_printf("ssh_hmac_init(): gcry_md_open failed %s/%s", err_str, err_src);
3730 return -1;
3731 }
3732 err = gcry_md_setkey(*(md), key, len);
3733 if (err != 0) {
3734 err_str = gcry_strerror(err);
3735 err_src = gcry_strsource(err);
3736 ssh_debug_printf("ssh_hmac_init(): gcry_md_setkey(..., ..., %d) failed %s/%s", len, err_str, err_src);
3737 return -1;
3738 }
3739 return 0;
3740}
3741
3742static inline void
3743ssh_hmac_update(SSH_HMACgcry_md_hd_t* md, const void* data, int len)
3744{
3745 gcry_md_write(*(md), data, len);
3746}
3747
3748static inline void
3749ssh_hmac_final(SSH_HMACgcry_md_hd_t* md, unsigned char* data, unsigned* datalen)
3750{
3751 int algo;
3752 unsigned len;
3753
3754 algo = gcry_md_get_algo (*(md));
3755 len = gcry_md_get_algo_dlen(algo);
3756 DISSECTOR_ASSERT(len <= *datalen)((void) ((len <= *datalen) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/dissectors/packet-ssh.c"
, 3756, "len <= *datalen"))))
;
3757 memcpy(data, gcry_md_read(*(md), algo), len);
3758 *datalen = len;
3759}
3760
3761static inline void
3762ssh_hmac_cleanup(SSH_HMACgcry_md_hd_t* md)
3763{
3764 gcry_md_close(*(md));
3765}
3766/* libgcrypt wrappers for HMAC/message digest operations }}} */
3767
3768/* Decryption integrity check {{{ */
3769
3770static int
3771ssh_get_digest_by_id(unsigned mac_id)
3772{
3773 if(mac_id==CIPHER_MAC_SHA2_2560x00020001){
3774 return GCRY_MD_SHA256;
3775 }
3776 return -1;
3777}
3778
3779static void
3780ssh_calc_mac(struct ssh_peer_data *peer_data, uint32_t seqnr, uint8_t* data, uint32_t datalen, uint8_t* calc_mac)
3781{
3782 SSH_HMACgcry_md_hd_t hm;
3783 int md;
3784 uint32_t len;
3785 uint8_t buf[DIGEST_MAX_SIZE48];
3786
3787 md=ssh_get_digest_by_id(peer_data->mac_id);
3788// ssl_debug_printf("ssh_check_mac mac type:%s md %d\n",
3789// ssl_cipher_suite_dig(decoder->cipher_suite)->name, md);
3790
3791 memset(calc_mac, 0, DIGEST_MAX_SIZE48);
3792
3793 if (md == -1) {
3794 return;
3795 }
3796 if (ssh_hmac_init(&hm, peer_data->hmac_iv, peer_data->hmac_iv_len, md) != 0)
3797 return;
3798
3799 /* hash sequence number */
3800 phtonu32(buf, seqnr);
3801
3802 ssh_print_data("Mac IV", peer_data->hmac_iv, peer_data->hmac_iv_len);
3803 ssh_print_data("Mac seq", buf, 4);
3804 ssh_print_data("Mac data", data, datalen);
3805
3806 ssh_hmac_update(&hm,buf,4);
3807
3808 ssh_hmac_update(&hm,data,datalen);
3809
3810 /* get digest and digest len*/
3811 len = sizeof(buf);
3812 ssh_hmac_final(&hm,buf,&len);
3813 ssh_hmac_cleanup(&hm);
3814 ssh_print_data("Mac", buf, len);
3815 memcpy(calc_mac, buf, len);
3816
3817 return;
3818}
3819/* Decryption integrity check }}} */
3820
3821static ssh_packet_info_t *
3822ssh_get_packet_info(packet_info *pinfo, bool_Bool is_response)
3823{
3824 ssh_packet_info_t *packet = (ssh_packet_info_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_ssh, 0);
3825 if(!packet){
3826 packet = wmem_new0(wmem_file_scope(), ssh_packet_info_t)((ssh_packet_info_t*)wmem_alloc0((wmem_file_scope()), sizeof(
ssh_packet_info_t)))
;
3827 packet->from_server = is_response;
3828 packet->messages = NULL((void*)0);
3829 p_add_proto_data(wmem_file_scope(), pinfo, proto_ssh, 0, packet);
3830 }
3831 return packet;
3832}
3833
3834static unsigned
3835ssh_decrypt_packet(tvbuff_t *tvb, packet_info *pinfo,
3836 struct ssh_peer_data *peer_data, int offset)
3837{
3838 bool_Bool is_response = ssh_peer_data_from_server(peer_data);
3839
3840 gcry_error_t err;
3841 unsigned message_length = 0, seqnr;
3842 uint8_t *plain = NULL((void*)0);
3843 const uint8_t *mac;
3844 unsigned mac_len, data_len = 0;
3845 uint8_t calc_mac[DIGEST_MAX_SIZE48];
3846 memset(calc_mac, 0, DIGEST_MAX_SIZE48);
3847 unsigned remaining = tvb_captured_length_remaining(tvb, offset);
3848
3849 mac_len = peer_data->mac_length > 0 ? peer_data->mac_length : 0;
3850 seqnr = peer_data->sequence_number;
3851
3852 /* General algorithm:
3853 * 1. If there are not enough bytes for the packet_length, and we can
3854 * do reassembly, ask for one more segment.
3855 * 2. Retrieve packet_length (encrypted in some modes).
3856 * 3. Sanity check packet_length (the field is 4 bytes, but packet_length
3857 * is unlikely to be much larger than 32768, which provides good indication
3858 * a packet is continuation data or, in some modes, failed decryption.
3859 * https://www.rfc-editor.org/rfc/rfc4253.html#section-6.1 )
3860 * 4. If there are not enough bytes for packet_length, and we can do
3861 * reassembly, tell the TCP dissector how many more bytes we need.
3862 * 5. If the packet is truncated and we cannot reassemble, at this
3863 * point we conclude that it is the next SSH packet, and advance the
3864 * sequence number, invocation_counter, etc. before throwing an exception.
3865 * 6. If we do have all the data, we decrypt and check the MAC before
3866 * doing all that. (XXX - Advancing seqnr regardless could make sense
3867 * in some ciphers.)
3868 * 7. Possibly the MAC should be checked before decryption in some ciphers
3869 * if we have all the data; possibly there should be a "do not check the
3870 * MAC" preference a la TLS.
3871 */
3872
3873 if (GCRY_CIPHER_CHACHA20 == peer_data->cipher_id) {
3874 if (ssh_desegment && pinfo->can_desegment && remaining < 4) {
3875 /* Can do reassembly, and the packet length is split across
3876 * segment boundaries. */
3877 pinfo->desegment_offset = offset;
3878 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT0x0fffffff;
3879 return tvb_captured_length(tvb);
3880 }
3881
3882 const uint8_t *ctext = tvb_get_ptr(tvb, offset, 4);
3883 uint8_t plain_length_buf[4];
3884
3885 if (!ssh_decrypt_chacha20(peer_data->cipher_2, seqnr, 0, ctext, 4,
3886 plain_length_buf, 4)) {
3887 ws_debug("ERROR: could not decrypt packet len")do { if (1) { ws_log_full("packet-ssh", LOG_LEVEL_DEBUG, "epan/dissectors/packet-ssh.c"
, 3887, __func__, "ERROR: could not decrypt packet len"); } }
while (0)
;
3888 return tvb_captured_length(tvb);
3889 }
3890
3891 message_length = pntohu32(plain_length_buf);
3892
3893 ssh_debug_printf("chachapoly_crypt seqnr=%d [%u]\n", seqnr, message_length);
3894
3895 ssh_debug_printf("%s plain for seq = %d len = %u\n", is_response?"s2c":"c2s", seqnr, message_length);
3896 if (message_length > SSH_MAX_PACKET_LEN32768) {
3897 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"
, 3897, __func__, "ssh: unreasonable message length %u", message_length
); } } while (0)
;
3898 return tvb_captured_length(tvb);
3899 }
3900 if (remaining < message_length + 4 + mac_len) {
3901 // Need desegmentation; as "the [email protected] AEAD
3902 // uses the sequence number as an initialisation vector (IV) to
3903 // generate its per-packet MAC key and is otherwise stateless
3904 // between packets," we need no special handling here.
3905 // https://www.ietf.org/id/draft-miller-sshm-strict-kex-01.html
3906 //
3907 if (ssh_desegment && pinfo->can_desegment) {
3908 pinfo->desegment_offset = offset;
3909 pinfo->desegment_len = message_length + 4 + mac_len - remaining;
3910 return tvb_captured_length(tvb);
3911 }
3912 // If we can't desegment, we will have an exception below in
3913 // the tvb_get_ptr. Advance the sequence number so that the
3914 // next SSH packet start will decrypt correctly.
3915 peer_data->sequence_number++;
3916 }
3917
3918 plain = (uint8_t *)wmem_alloc0(pinfo->pool, message_length+4);
3919 memcpy(plain, plain_length_buf, 4);
3920 const uint8_t *ctext2 = tvb_get_ptr(tvb, offset+4, message_length);
3921
3922 /* XXX - "Once the entire packet has been received, the MAC MUST be
3923 * checked before decryption," but we decrypt first.
3924 * https://datatracker.ietf.org/doc/html/draft-ietf-sshm-chacha20-poly1305-01
3925 */
3926 if (!ssh_decrypt_chacha20(peer_data->cipher, seqnr, 1, ctext2,
3927 message_length, plain+4, message_length)) {
3928 ws_debug("ERROR: could not decrypt packet payload")do { if (1) { ws_log_full("packet-ssh", LOG_LEVEL_DEBUG, "epan/dissectors/packet-ssh.c"
, 3928, __func__, "ERROR: could not decrypt packet payload");
} } while (0)
;
3929 return tvb_captured_length(tvb);
3930 }
3931
3932 mac = tvb_get_ptr(tvb, offset + 4 + message_length, mac_len);
3933 uint8_t poly_key[32], iv[16];
3934
3935 memset(poly_key, 0, 32);
3936 memset(iv, 0, 8);
3937 phtonu64(iv+8, (uint64_t)seqnr);
3938 gcry_cipher_setiv(peer_data->cipher, iv, mac_len);
3939 gcry_cipher_encrypt(peer_data->cipher, poly_key, 32, poly_key, 32);
3940
3941 gcry_mac_hd_t mac_hd;
3942 gcry_mac_open(&mac_hd, GCRY_MAC_POLY1305, 0, NULL((void*)0));
3943 gcry_mac_setkey(mac_hd, poly_key, 32);
3944 gcry_mac_write(mac_hd, ctext, 4);
3945 gcry_mac_write(mac_hd, ctext2, message_length);
3946 if (gcry_mac_verify(mac_hd, mac, mac_len)) {
3947 ws_debug("ssh: MAC does not match")do { if (1) { ws_log_full("packet-ssh", LOG_LEVEL_DEBUG, "epan/dissectors/packet-ssh.c"
, 3947, __func__, "ssh: MAC does not match"); } } while (0)
;
3948 }
3949 size_t buflen = DIGEST_MAX_SIZE48;
3950 gcry_mac_read(mac_hd, calc_mac, &buflen);
3951 gcry_mac_close(mac_hd);
3952
3953 data_len = message_length + 4;
3954
3955 ssh_debug_printf("%s plain text seq=%d", is_response?"s2c":"c2s",seqnr);
3956 ssh_print_data("", plain, message_length+4);
3957 } else if (CIPHER_AES128_GCM0x00040001 == peer_data->cipher_id || CIPHER_AES256_GCM0x00040004 == peer_data->cipher_id) {
3958
3959 /* AES GCM for Secure Shell [RFC 5647] */
3960 /* The message length is Additional Authenticated Data */
3961 if (ssh_desegment && pinfo->can_desegment && remaining < 4) {
3962 /* Can do reassembly, and the packet length is split across
3963 * segment boundaries. */
3964 pinfo->desegment_offset = offset;
3965 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT0x0fffffff;
3966 return tvb_captured_length(tvb);
3967 }
3968 message_length = tvb_get_uint32(tvb, offset, ENC_BIG_ENDIAN0x00000000);
3969 ssh_debug_printf("length: %d, remaining: %d\n", message_length, remaining);
3970 /* The minimum size of a packet (not counting mac) is 16. */
3971 if (message_length > SSH_MAX_PACKET_LEN32768 || message_length < 16) {
3972 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"
, 3972, __func__, "ssh: unreasonable message length %u", message_length
); } } while (0)
;
3973 return tvb_captured_length(tvb);
3974 }
3975
3976 /* SSH requires that the data to be encrypted (not including the AAD,
3977 * so message_length) be a multiple of the block size, 16 octets */
3978 if (message_length % 16 != 0) {
3979 ssh_debug_printf("length not a multiple of block length (16)!\n");
3980 }
3981
3982 if (message_length + 4 + mac_len > remaining) {
3983 // Need desegmentation; as the message length was unencrypted
3984 // AAD, we need no special handling here.
3985 if (pinfo->can_desegment) {
3986 pinfo->desegment_offset = offset;
3987 pinfo->desegment_len = message_length + 4 + mac_len - remaining;
3988 return tvb_captured_length(tvb);
3989 }
3990 // If we can't desegment, we will have an exception below in
3991 // the tvb_get_ptr. Advance the sequence number (less crucial
3992 // than with ChaCha20, as it's not an input.)
3993 peer_data->sequence_number++;
3994 }
3995
3996 /* Set the IV and increment the invocation_counter for the next
3997 * packet. Do this before retrieving the ciphertext with tvb_get_ptr
3998 * in case this packet is truncated.
3999 */
4000 if ((err = gcry_cipher_setiv(peer_data->cipher, peer_data->iv, 12))) {
4001 //gcry_cipher_close(peer_data->cipher);
4002 //Don't close this unless we also remove the wmem callback
4003// TODO: temporary work-around as long as a Windows python bug is triggered by automated tests
4004#ifndef _WIN32
4005 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"
, 4005, __func__, "ssh: can't set aes128 cipher iv"); } } while
(0)
;
4006 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"
, 4006, __func__, "libgcrypt: %d %s %s", gcry_err_code(err), gcry_strsource
(err), gcry_strerror(err)); } } while (0)
;
4007#endif //ndef _WIN32
4008 return tvb_captured_length(tvb);
4009 }
4010 // Increment invocation_counter for next packet
4011 int idx = 12;
4012 do{
4013 idx -= 1;
4014 peer_data->iv[idx] += 1;
4015 }while(idx>4 && peer_data->iv[idx]==0);
4016
4017 const char *ctext = (const char *)tvb_get_ptr(tvb, offset + 4,
4018 message_length);
4019 plain = (uint8_t *)wmem_alloc(pinfo->pool, message_length+4);
4020 phtonu32(plain, message_length);
4021
4022 if ((err = gcry_cipher_authenticate(peer_data->cipher, plain, 4))) {
4023// TODO: temporary work-around as long as a Windows python bug is triggered by automated tests
4024#ifndef _WIN32
4025 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"
, 4025, __func__, "can't authenticate using aes128-gcm: %s\n"
, gpg_strerror(err)); } } while (0)
;
4026#endif //ndef _WIN32
4027 return tvb_captured_length(tvb);
4028 }
4029
4030 if ((err = gcry_cipher_decrypt(peer_data->cipher, plain+4, message_length,
4031 ctext, message_length))) {
4032// TODO: temporary work-around as long as a Windows python bug is triggered by automated tests
4033#ifndef _WIN32
4034 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"
, 4034, __func__, "can't decrypt aes-gcm %d %s %s", gcry_err_code
(err), gcry_strsource(err), gcry_strerror(err)); } } while (0
)
;
4035
4036#endif //ndef _WIN32
4037 return tvb_captured_length(tvb);
4038 }
4039
4040 if (gcry_cipher_gettag (peer_data->cipher, calc_mac, 16)) {
4041// TODO: temporary work-around as long as a Windows python bug is triggered by automated tests
4042#ifndef _WIN32
4043 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"
, 4043, __func__, "aes128-gcm, gcry_cipher_gettag() failed\n"
); } } while (0)
;
4044#endif //ndef _WIN32
4045 return tvb_captured_length(tvb);
4046 }
4047
4048 if ((err = gcry_cipher_reset(peer_data->cipher)gcry_cipher_ctl ((peer_data->cipher), GCRYCTL_RESET, ((void
*)0), 0)
)) {
4049// TODO: temporary work-around as long as a Windows python bug is triggered by automated tests
4050#ifndef _WIN32
4051 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"
, 4051, __func__, "aes-gcm, gcry_cipher_reset failed: %s\n", gpg_strerror
(err)); } } while (0)
;
4052#endif //ndef _WIN32
4053 return tvb_captured_length(tvb);
4054 }
4055
4056 data_len = message_length + 4;
4057
4058 ssh_debug_printf("%s plain text seq=%d", is_response?"s2c":"c2s",seqnr);
4059 ssh_print_data("", plain, message_length+4);
4060
4061 } else if (CIPHER_AES128_CBC0x00020001 == peer_data->cipher_id || CIPHER_AES128_CTR0x00010001 == peer_data->cipher_id ||
4062 CIPHER_AES192_CBC0x00020002 == peer_data->cipher_id || CIPHER_AES192_CTR0x00010003 == peer_data->cipher_id ||
4063 CIPHER_AES256_CBC0x00020004 == peer_data->cipher_id || CIPHER_AES256_CTR0x00010004 == peer_data->cipher_id) {
4064
4065 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"
, 4065, __func__, "Getting raw bytes of length %d", tvb_reported_length_remaining
(tvb, offset)); } } while (0)
;
4066 /* In CBC and CTR mode, the message length is encrypted as well.
4067 * We need to decrypt one block, 16 octets, to get the length.
4068 */
4069 if (ssh_desegment && pinfo->can_desegment && remaining < 16) {
4070 /* Can do reassembly, and the packet length is split across
4071 * segment boundaries. */
4072 pinfo->desegment_offset = offset;
4073 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT0x0fffffff;
4074 return tvb_captured_length(tvb);
4075 }
4076 /* Do we already have the first block decrypted from when the packet
4077 * was too large and segmented?
4078 */
4079 if (!peer_data->plain0_valid) {
4080 const char *cypher_buf0 = (const char *)tvb_get_ptr(tvb, offset, 16);
4081
4082 if (gcry_cipher_decrypt(peer_data->cipher, peer_data->plain0, 16, cypher_buf0, 16))
4083 {
4084 ws_debug("can\'t decrypt aes128")do { if (1) { ws_log_full("packet-ssh", LOG_LEVEL_DEBUG, "epan/dissectors/packet-ssh.c"
, 4084, __func__, "can\'t decrypt aes128"); } } while (0)
;
4085 return tvb_captured_length(tvb);
4086 }
4087 }
4088
4089 message_length = pntohu32(peer_data->plain0);
4090
4091 /* The message_length value doesn't include the length of the
4092 * message_length field itself, so it must be at least 12 bytes.
4093 */
4094 if (message_length > SSH_MAX_PACKET_LEN32768 || message_length < 12){
4095 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"
, 4095, __func__, "ssh: unreasonable message length %u", message_length
); } } while (0)
;
4096 return tvb_captured_length(tvb);
4097 }
4098
4099 /* SSH requires that the data to be encrypted (message_length+4)
4100 * be a multiple of the block size, 16 octets. */
4101 if (message_length % 16 != 12) {
4102 ssh_debug_printf("total length not a multiple of block length (16)!\n");
4103 }
4104 if (remaining < message_length + 4 + mac_len) {
4105 /* Need desegmentation
4106 *
4107 * We will be handed the full encrypted packet again. We can either
4108 * store the decrypted first block, or will need to reset the CTR
4109 * or IV appropriately before decrypting the first block again.
4110 * libgcrypt does not provide an easy way to get the current value
4111 * of the CTR or (or IV/last block for CBC), so we just store the
4112 * decrypted first block.
4113 */
4114 if (ssh_desegment && pinfo->can_desegment) {
4115 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"
, 4116, __func__, " need_desegmentation: offset = %d, reported_length_remaining = %d\n"
, offset, tvb_reported_length_remaining(tvb, offset)); } } while
(0)
4116 offset, tvb_reported_length_remaining(tvb, offset))do { if (1) { ws_log_full("packet-ssh", LOG_LEVEL_NOISY, "epan/dissectors/packet-ssh.c"
, 4116, __func__, " need_desegmentation: offset = %d, reported_length_remaining = %d\n"
, offset, tvb_reported_length_remaining(tvb, offset)); } } while
(0)
;
4117 peer_data->plain0_valid = true1;
4118 pinfo->desegment_offset = offset;
4119 pinfo->desegment_len = message_length + 4 + mac_len - remaining;
4120 return tvb_captured_length(tvb);
4121 } else {
4122 // If we can't desegment, we will have an exception below in
4123 // the tvb_get_ptr. Advance the sequence number so that the
4124 // the hash will work for the next packet.
4125 //
4126 // XXX - In CTR mode, we should advance the CTR based on the
4127 // known length so we can dissect the next block. We would
4128 // also need to reset the CTR after failing to dissect a
4129 // packet_length on the continuation data that comes next.
4130 peer_data->sequence_number++;
4131 }
4132 }
4133 peer_data->plain0_valid = false0;
4134 plain = (uint8_t *)wmem_alloc(pinfo->pool, message_length+4);
4135 memcpy(plain, peer_data->plain0, 16);
4136
4137 if (message_length > 12) {
4138 /* All of these functions actually do handle the case where
4139 * there is no data left, so the check is unnecessary.
4140 */
4141 char *ct = (char *)tvb_get_ptr(tvb, offset + 16, message_length - 12);
4142 if ((err = gcry_cipher_decrypt(peer_data->cipher, plain + 16, message_length - 12, ct, message_length - 12)))
4143 {
4144 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"
, 4144, __func__, "can't decrypt aes-cbc/ctr %d %s %s", gcry_err_code
(err), gcry_strsource(err), gcry_strerror(err)); } } while (0
)
;
4145 return tvb_captured_length(tvb);
4146 }
4147 }
4148
4149 ssh_debug_printf("%s plain text seq=%d", is_response?"s2c":"c2s",seqnr);
4150 ssh_print_data("", plain, message_length+4);
4151
4152 data_len = message_length + 4;
4153
4154 // XXX - In -etm modes, should calculate MAC based on ciphertext.
4155 ssh_calc_mac(peer_data, seqnr, plain, data_len, calc_mac);
4156 } else if (CIPHER_NULL0x00080000 == peer_data->cipher_id) {
4157 if (ssh_desegment && pinfo->can_desegment && remaining < 4) {
4158 /* Can do reassembly, and the packet length is split across
4159 * segment boundaries. */
4160 pinfo->desegment_offset = offset;
4161 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT0x0fffffff;
4162 return tvb_captured_length(tvb);
4163 }
4164 message_length = tvb_get_uint32(tvb, offset, ENC_BIG_ENDIAN0x00000000);
4165 ssh_debug_printf("length: %d, remaining: %d\n", message_length, remaining);
4166 if (message_length > SSH_MAX_PACKET_LEN32768 || message_length < 8) {
4167 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"
, 4167, __func__, "ssh: unreasonable message length %u", message_length
); } } while (0)
;
4168 return tvb_captured_length(tvb);
4169 }
4170
4171 if (message_length + 4 + mac_len > remaining) {
4172 // Need desegmentation; as the message length was unencrypted
4173 // AAD, we need no special handling here.
4174 if (pinfo->can_desegment) {
4175 pinfo->desegment_offset = offset;
4176 pinfo->desegment_len = message_length + 4 + mac_len - remaining;
4177 return tvb_captured_length(tvb);
4178 }
4179 // If we can't desegment, we will have an exception below in
4180 // the tvb_memdup. Advance the sequence number (not crucial).
4181 peer_data->sequence_number++;
4182 }
4183 data_len = message_length + 4;
4184 plain = tvb_memdup(pinfo->pool, tvb, offset, data_len);
4185
4186 // XXX - In -etm modes, should calculate MAC based on ciphertext.
4187 ssh_calc_mac(peer_data, seqnr, plain, data_len, calc_mac);
4188 }
4189
4190 if (mac_len && data_len) {
4191 mac = tvb_get_ptr(tvb, offset + data_len, mac_len);
4192 if (!memcmp(mac, calc_mac, mac_len)){
4193 ws_noisy("MAC OK")do { if (1) { ws_log_full("packet-ssh", LOG_LEVEL_NOISY, "epan/dissectors/packet-ssh.c"
, 4193, __func__, "MAC OK"); } } while (0)
;
4194 }else{
4195 ws_debug("MAC ERR")do { if (1) { ws_log_full("packet-ssh", LOG_LEVEL_DEBUG, "epan/dissectors/packet-ssh.c"
, 4195, __func__, "MAC ERR"); } } while (0)
;
4196 /* Bad MAC, just show the packet as encrypted. We can get
4197 * this for a known encryption type with no keys currently. */
4198 if (!ssh_ignore_mac_failed) {
4199 return tvb_captured_length(tvb);
4200 }
4201 }
4202 }
4203
4204 if(plain){
4205 // Save message
4206
4207 ssh_packet_info_t *packet = ssh_get_packet_info(pinfo, is_response);
4208
4209 int record_id = tvb_raw_offset(tvb)+offset;
4210 ssh_message_info_t *message;
4211
4212 message = wmem_new(wmem_file_scope(), ssh_message_info_t)((ssh_message_info_t*)wmem_alloc((wmem_file_scope()), sizeof(
ssh_message_info_t)))
;
4213 message->sequence_number = peer_data->sequence_number++;
4214 message->plain_data = wmem_memdup(wmem_file_scope(), plain, data_len);
4215 message->data_len = data_len;
4216 message->id = record_id;
4217 message->next = NULL((void*)0);
4218 memcpy(message->calc_mac, calc_mac, DIGEST_MAX_SIZE48);
4219 ssh_debug_printf("%s->sequence_number++ > %d\n", is_response?"server":"client", peer_data->sequence_number);
4220
4221 ssh_message_info_t **pmessage = &packet->messages;
4222 while(*pmessage){
4223 pmessage = &(*pmessage)->next;
4224 }
4225 *pmessage = message;
4226 }
4227
4228 offset += message_length + mac_len + 4;
4229 return offset;
4230}
4231
4232static bool_Bool
4233ssh_decrypt_chacha20(gcry_cipher_hd_t hd,
4234 uint32_t seqnr, uint32_t counter, const unsigned char *ctext, unsigned ctext_len,
4235 unsigned char *plain, unsigned plain_len)
4236{
4237 unsigned char seq[8];
4238 unsigned char iv[16];
4239
4240 phtonu64(seq, (uint64_t)seqnr);
4241
4242 // chacha20 uses a different cipher handle for the packet payload & length
4243 // the payload uses a block counter
4244 if (counter) {
4245 unsigned char ctr[8] = {1,0,0,0,0,0,0,0};
4246 memcpy(iv, ctr, 8);
4247 memcpy(iv+8, seq, 8);
4248 }
4249
4250 return ((!counter && gcry_cipher_setiv(hd, seq, 8) == 0) ||
4251 (counter && gcry_cipher_setiv(hd, iv, 16) == 0)) &&
4252 gcry_cipher_decrypt(hd, plain, plain_len, ctext, ctext_len) == 0;
4253}
4254
4255static int
4256ssh_dissect_decrypted_packet(tvbuff_t *tvb, packet_info *pinfo,
4257 struct ssh_peer_data *peer_data, proto_tree *tree,
4258 ssh_message_info_t *message)
4259{
4260 int offset = 0; // TODO:
4261 int dissected_len = 0;
4262 tvbuff_t* payload_tvb;
4263
4264 const uint8_t* plaintext = message->plain_data;
4265 unsigned plaintext_len = message->data_len;
4266
4267 col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL((void*)0), "Encrypted packet (plaintext_len=%d)", plaintext_len);
4268
4269 tvbuff_t *packet_tvb = tvb_new_child_real_data(tvb, plaintext, plaintext_len, plaintext_len);
4270 add_new_data_source(pinfo, packet_tvb, "Decrypted Packet");
4271
4272 unsigned plen;
4273 uint32_t padding_length;
4274 unsigned remain_length;
4275 unsigned msg_code;
4276
4277 proto_item *ti, *padding_ti;
4278 proto_item *msg_type_tree = NULL((void*)0);
4279
4280 /*
4281 * We use "tvb_ensure_captured_length_remaining()" to make sure there
4282 * actually *is* data remaining.
4283 *
4284 * This means we're guaranteed that "remain_length" is positive.
4285 */
4286 remain_length = tvb_ensure_captured_length_remaining(packet_tvb, offset);
4287 /*
4288 * Can we do reassembly?
4289 */
4290 if (ssh_desegment && pinfo->can_desegment) {
4291 /*
4292 * Yes - would an SSH header starting at this offset
4293 * be split across segment boundaries?
4294 */
4295 if (remain_length < 4) {
4296 /*
4297 * Yes. Tell the TCP dissector where the data for
4298 * this message starts in the data it handed us and
4299 * that we need "some more data." Don't tell it
4300 * exactly how many bytes we need because if/when we
4301 * ask for even more (after the header) that will
4302 * break reassembly.
4303 */
4304 pinfo->desegment_offset = offset;
4305 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT0x0fffffff;
4306 return offset;
4307 }
4308 }
4309 /* XXX - Defragmentation needs to be done in ssh_decrypt_packet, and the
4310 * checks there should mean that the above never has an effect. (It's
4311 * copied from ssh_dissect_key_exchange.)
4312 */
4313 plen = tvb_get_ntohl(packet_tvb, offset);
4314
4315 if (ssh_desegment && pinfo->can_desegment) {
4316 if (plen + 4 > remain_length) {
4317 pinfo->desegment_offset = offset;
4318 pinfo->desegment_len = plen+4 - remain_length;
4319 return offset;
4320 }
4321 }
4322 /*
4323 * Need to check plen > 0x80000000 here
4324 */
4325
4326 ti = proto_tree_add_uint(tree, hf_ssh_packet_length, packet_tvb,
4327 offset, 4, plen);
4328 if (plen < 8) {
4329 /* RFC 4253 6: "[T]he length of the concatenation of 'packet_length',
4330 * 'padding_length', 'payload', and 'random padding' MUST be a multiple
4331 * of the cipher block size or 8, whichever is larger,... even when
4332 * using stream ciphers."
4333 *
4334 * Modes that do not encrypt plen with the same key as the other three
4335 * cannot follow this as written and delete 'packet_length' from the
4336 * above sentence. As padding_length is one byte and random_padding at
4337 * least four, packet_length must be at least 8 in all modes.
4338 */
4339 expert_add_info_format(pinfo, ti, &ei_ssh_packet_length, "Packet length is %d, MUST be at least 8", plen);
4340 } else if (plen >= SSH_MAX_PACKET_LEN32768) {
4341 expert_add_info_format(pinfo, ti, &ei_ssh_packet_length, "Overly large number %d", plen);
4342 plen = remain_length-4;
4343 }
4344 offset+=4;
4345
4346 /* padding length */
4347 padding_ti = proto_tree_add_item_ret_uint(tree, hf_ssh_padding_length, packet_tvb, offset, 1, ENC_NA0x00000000, &padding_length);
4348 /* RFC 4253 6: "There MUST be at least four bytes of padding." */
4349 if (padding_length < 4) {
4350 expert_add_info_format(pinfo, padding_ti, &ei_ssh_padding_length, "Padding length is %d, MUST be at least 4", padding_length);
4351 }
4352 unsigned payload_length;
4353 if (ckd_sub(&payload_length, plen, padding_length + 1)__builtin_sub_overflow((plen), (padding_length + 1), (&payload_length
))
) {
4354 expert_add_info_format(pinfo, padding_ti, &ei_ssh_padding_length, "Padding length is too large [%d], implies a negative payload length", padding_length);
4355 payload_length = 0;
4356 }
4357 offset += 1;
4358
4359 /* msg_code */
4360 msg_code = tvb_get_uint8(packet_tvb, offset);
4361 /* XXX - Payload compression could have been negotiated */
4362 payload_tvb = tvb_new_subset_length(packet_tvb, offset, (int)payload_length);
4363 bool_Bool is_response = ssh_peer_data_from_server(peer_data);
4364
4365 /* Transport layer protocol */
4366 /* Generic (1-19) */
4367 if(msg_code >= 1 && msg_code <= 19) {
4368 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL((void*)0), val_to_str(pinfo->pool, msg_code, ssh2_msg_vals, "Unknown (%u)"));
4369 msg_type_tree = proto_tree_add_subtree(tree, packet_tvb, offset, plen-1, ett_key_exchange, NULL((void*)0), "Message: Transport (generic)");
4370 proto_tree_add_item(msg_type_tree, hf_ssh2_msg_code, packet_tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
4371 dissected_len = ssh_dissect_transport_generic(payload_tvb, pinfo, 1, peer_data, msg_type_tree, msg_code);
4372 }
4373 /* Algorithm negotiation (20-29) */
4374 /* Normally these messages are all dissected in ssh_dissect_key_exchange */
4375 else if(msg_code >=20 && msg_code <= 29) {
4376//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);
4377
4378 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL((void*)0), val_to_str(pinfo->pool, msg_code, ssh2_msg_vals, "Unknown (%u)"));
4379 msg_type_tree = proto_tree_add_subtree(tree, packet_tvb, offset, plen-1, ett_key_exchange, NULL((void*)0), "Message: Transport (algorithm negotiation)");
4380 proto_tree_add_item(msg_type_tree, hf_ssh2_msg_code, packet_tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
4381 dissected_len = 1;
4382
4383 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"
, 4383, __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)
;
4384 switch(msg_code)
4385 {
4386 case SSH_MSG_KEXINIT20:
4387 {
4388 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"
, 4388, __func__, "ssh: REKEY msg_code 20: storing frame %u number, offset %d"
, pinfo->num, offset); } } while (0)
;
4389 peer_data->rekey_trigger_frame = pinfo->num;
4390 // Reset array while REKEY: sanitize server_key_exchange_init and force do_decrypt :
4391 peer_data->global_data->kex_server_key_exchange_init = wmem_array_new(wmem_file_scope(), 1);
4392 peer_data->global_data->do_decrypt = true1;
4393 dissected_len = ssh_dissect_key_init(payload_tvb, pinfo, offset - 4, msg_type_tree, is_response, peer_data->global_data);
4394 break;
4395 }
4396 case SSH_MSG_NEWKEYS21:
4397 {
4398 if (peer_data->rekey_pending) {
4399 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"
, 4399, __func__, "ssh: REKEY pending... NEWKEYS frame %u", pinfo
->num); } } while (0)
;
4400 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"
, 4400, __func__, "ssh: decrypting frame %u with key ID %u, seq=%u"
, pinfo->num, peer_data->cipher_id, peer_data->sequence_number
); } } while (0)
;
4401 if (peer_data->global_data->ext_kex_strict) {
4402 peer_data->sequence_number = 0;
4403 ssh_debug_printf("%s->sequence_number reset to 0 (Strict KEX)\n", is_response ? "server" : "client");
4404 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"
, 4404, __func__, "ssh: REKEY reset %s sequence number to 0 at frame %u (Strict KEX)"
, is_response ? "server" : "client", pinfo->num); } } while
(0)
;
4405 }
4406 // finalize the rekey (activate the new keys)
4407 if (!is_response) { // Only process client-sent NEWKEYS
4408 // Activate new key material into peer_data->cipher
4409 ssh_debug_printf("Activating new keys for CLIENT => SERVER\n");
4410 ssh_decryption_setup_cipher(peer_data, &peer_data->global_data->new_keys[0], &peer_data->global_data->new_keys[2]);
4411 ssh_decryption_setup_mac(peer_data, &peer_data->global_data->new_keys[4]);
4412 } else { // Only process server-sent NEWKEYS
4413 // Activate new key material into peer_data->cipher
4414 ssh_debug_printf("Activating new keys for SERVER => CLIENT\n");
4415 ssh_decryption_setup_cipher(peer_data, &peer_data->global_data->new_keys[1], &peer_data->global_data->new_keys[3]);
4416 ssh_decryption_setup_mac(peer_data, &peer_data->global_data->new_keys[5]);
4417 }
4418 // Finishing REKEY
4419 peer_data->rekey_pending = false0;
4420 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"
, 4420, __func__, "ssh: REKEY done... switched to NEWKEYS at frame %u"
, pinfo->num); } } while (0)
;
4421 }
4422 break;
4423 }
4424 }
4425 }
4426 /* Key exchange method specific (reusable) (30-49) */
4427 /* Normally these messages are all dissected in ssh_dissect_key_exchange */
4428 else if (msg_code >=30 && msg_code <= 49) {
4429//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);
4430
4431 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)");
4432 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"
, 4432, __func__, "ssh: rekey KEX_xxx_INIT/KEX_xxx_REPLY detected in frame %u"
, pinfo->num); } } while (0)
;
4433 peer_data->rekey_pending = true1;
4434 dissected_len = peer_data->global_data->kex_specific_dissector(msg_code, payload_tvb, pinfo, offset -5, msg_type_tree, peer_data->global_data);
4435 }
4436
4437 /* User authentication protocol */
4438 /* Generic (50-59) */
4439 else if (msg_code >= 50 && msg_code <= 59) {
4440 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL((void*)0), val_to_str(pinfo->pool, msg_code, ssh2_msg_vals, "Unknown (%u)"));
4441 msg_type_tree = proto_tree_add_subtree(tree, packet_tvb, offset, plen-1, ett_key_exchange, NULL((void*)0), "Message: User Authentication (generic)");
4442 proto_tree_add_item(msg_type_tree, hf_ssh2_msg_code, packet_tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
4443 dissected_len = ssh_dissect_userauth_generic(payload_tvb, pinfo, 1, msg_type_tree, msg_code);
4444 }
4445 /* User authentication method specific (reusable) (60-79) */
4446 else if (msg_code >= 60 && msg_code <= 79) {
4447 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL((void*)0), val_to_str(pinfo->pool, msg_code, ssh2_msg_vals, "Unknown (%u)"));
4448 msg_type_tree = proto_tree_add_subtree(tree, packet_tvb, offset, plen-1, ett_key_exchange, NULL((void*)0), "Message: User Authentication: (method specific)");
4449 proto_tree_add_item(msg_type_tree, hf_ssh2_msg_code, packet_tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
4450 dissected_len = ssh_dissect_userauth_specific(payload_tvb, pinfo, 1, msg_type_tree, msg_code);
4451 }
4452
4453 /* Connection protocol */
4454 /* Generic (80-89) */
4455 else if (msg_code >= 80 && msg_code <= 89) {
4456 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL((void*)0), val_to_str(pinfo->pool, msg_code, ssh2_msg_vals, "Unknown (%u)"));
4457 msg_type_tree = proto_tree_add_subtree(tree, packet_tvb, offset, plen-1, ett_key_exchange, NULL((void*)0), "Message: Connection (generic)");
4458 proto_tree_add_item(msg_type_tree, hf_ssh2_msg_code, packet_tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
4459 dissected_len = ssh_dissect_connection_generic(payload_tvb, pinfo, 1, msg_type_tree, msg_code);
4460 }
4461 /* Channel related messages (90-127) */
4462 else if (msg_code >= 90 && msg_code <= 127) {
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: Connection: (channel related message)");
4465 proto_tree_add_item(msg_type_tree, hf_ssh2_msg_code, packet_tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
4466 dissected_len = ssh_dissect_connection_specific(payload_tvb, pinfo, peer_data, 1, msg_type_tree, msg_code, message);
4467 }
4468
4469 /* Reserved for client protocols (128-191) */
4470 else if (msg_code >= 128 && msg_code <= 191) {
4471 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL((void*)0), val_to_str(pinfo->pool, msg_code, ssh2_msg_vals, "Unknown (%u)"));
4472 msg_type_tree = proto_tree_add_subtree(tree, packet_tvb, offset, plen-1, ett_key_exchange, NULL((void*)0), "Message: Client protocol");
4473 proto_tree_add_item(msg_type_tree, hf_ssh2_msg_code, packet_tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
4474 offset+=1;
4475 // TODO: dissected_len = ssh_dissect_client(payload_tvb, pinfo, global_data, 1, msg_type_tree, is_response, msg_code);
4476 }
4477
4478 /* Local extensions (192-255) */
4479 else if (msg_code >= 192 && msg_code <= 255) {
4480 msg_type_tree = proto_tree_add_subtree(tree, packet_tvb, offset, plen-1, ett_key_exchange, NULL((void*)0), "Message: Local extension");
4481 dissected_len = ssh_dissect_local_extension(payload_tvb, pinfo, 0, peer_data, msg_type_tree, msg_code);
4482 }
4483
4484 /* XXX - ssh_dissect_key_exchange only adds undecoded payload here,
4485 * i.e., tvb_reported_length_remaining(payload_tvb, dissected_len)
4486 */
4487 if (payload_length > 0) {
4488 proto_tree_add_item(msg_type_tree, hf_ssh_payload, packet_tvb, offset, payload_length, ENC_NA0x00000000);
4489 }
4490 if(dissected_len!=(int)payload_length){
4491 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);
4492 }
4493 offset += payload_length;
4494
4495 /* padding */
4496 proto_tree_add_item(tree, hf_ssh_padding_string, packet_tvb, offset, padding_length, ENC_NA0x00000000);
4497 offset += padding_length;
4498
4499 if (peer_data->mac_length > 0) {
4500 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);
4501 offset += peer_data->mac_length;
4502 }
4503 ti = proto_tree_add_uint(tree, hf_ssh_seq_num, tvb, offset, 0, message->sequence_number);
4504 proto_item_set_generated(ti);
4505 return offset;
4506}
4507
4508static int
4509ssh_dissect_transport_generic(tvbuff_t *packet_tvb, packet_info *pinfo,
4510 int offset, struct ssh_peer_data *peer_data, proto_item *msg_type_tree, unsigned msg_code)
4511{
4512 (void)pinfo;
4513 if(msg_code==SSH_MSG_DISCONNECT1){
4514 proto_tree_add_item(msg_type_tree, hf_ssh_disconnect_reason, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
4515 offset += 4;
4516 unsigned nlen;
4517 nlen = tvb_get_ntohl(packet_tvb, offset) ;
4518 proto_tree_add_item(msg_type_tree, hf_ssh_disconnect_description_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
4519 offset += 4;
4520 proto_tree_add_item(msg_type_tree, hf_ssh_disconnect_description, packet_tvb, offset, nlen, ENC_ASCII0x00000000);
4521 offset += nlen;
4522 nlen = tvb_get_ntohl(packet_tvb, offset) ;
4523 proto_tree_add_item(msg_type_tree, hf_ssh_lang_tag_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
4524 offset += 4;
4525 proto_tree_add_item(msg_type_tree, hf_ssh_lang_tag, packet_tvb, offset, nlen, ENC_ASCII0x00000000);
4526 offset += nlen;
4527 }else if(msg_code==SSH_MSG_IGNORE2){
4528 offset += ssh_tree_add_string(packet_tvb, offset, msg_type_tree, hf_ssh_ignore_data, hf_ssh_ignore_data_length);
4529 }else if(msg_code==SSH_MSG_DEBUG4){
4530 unsigned slen;
4531 proto_tree_add_item(msg_type_tree, hf_ssh_debug_always_display, packet_tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
4532 offset += 1;
4533 slen = tvb_get_ntohl(packet_tvb, offset) ;
4534 proto_tree_add_item(msg_type_tree, hf_ssh_debug_message_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
4535 offset += 4;
4536 proto_tree_add_item(msg_type_tree, hf_ssh_debug_message, packet_tvb, offset, slen, ENC_UTF_80x00000002);
4537 offset += slen;
4538 slen = tvb_get_ntohl(packet_tvb, offset) ;
4539 proto_tree_add_item(msg_type_tree, hf_ssh_lang_tag_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
4540 offset += 4;
4541 proto_tree_add_item(msg_type_tree, hf_ssh_lang_tag, packet_tvb, offset, slen, ENC_ASCII0x00000000);
4542 offset += slen;
4543 }else if(msg_code==SSH_MSG_SERVICE_REQUEST5){
4544 unsigned nlen;
4545 nlen = tvb_get_ntohl(packet_tvb, offset) ;
4546 proto_tree_add_item(msg_type_tree, hf_ssh_service_name_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
4547 offset += 4;
4548 proto_tree_add_item(msg_type_tree, hf_ssh_service_name, packet_tvb, offset, nlen, ENC_ASCII0x00000000);
4549 offset += nlen;
4550 }else if(msg_code==SSH_MSG_SERVICE_ACCEPT6){
4551 unsigned nlen;
4552 nlen = tvb_get_ntohl(packet_tvb, offset) ;
4553 proto_tree_add_item(msg_type_tree, hf_ssh_service_name_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
4554 offset += 4;
4555 proto_tree_add_item(msg_type_tree, hf_ssh_service_name, packet_tvb, offset, nlen, ENC_ASCII0x00000000);
4556 offset += nlen;
4557 }else if(msg_code==SSH_MSG_EXT_INFO7){
4558 unsigned ext_cnt;
4559 ext_cnt = tvb_get_ntohl(packet_tvb, offset);
4560 proto_tree_add_item(msg_type_tree, hf_ssh_ext_count, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
4561 offset += 4;
4562 for(unsigned ext_index = 0; ext_index < ext_cnt; ext_index++) {
4563 offset = ssh_dissect_rfc8308_extension(packet_tvb, pinfo, offset, peer_data, msg_type_tree);
4564 }
4565 }
4566 return offset;
4567}
4568
4569static int
4570ssh_dissect_rfc8308_extension(tvbuff_t *packet_tvb, packet_info *pinfo,
4571 int offset, struct ssh_peer_data *peer_data, proto_item *msg_type_tree)
4572{
4573 (void)pinfo;
4574 unsigned ext_name_slen = tvb_get_ntohl(packet_tvb, offset);
4575 uint8_t *ext_name = tvb_get_string_enc(pinfo->pool, packet_tvb, offset + 4, ext_name_slen, ENC_ASCII0x00000000);
4576 unsigned ext_value_slen = tvb_get_ntohl(packet_tvb, offset + 4 + ext_name_slen);
4577 unsigned ext_len = 8 + ext_name_slen + ext_value_slen;
4578 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);
4579
4580 proto_tree_add_item(ext_tree, hf_ssh_ext_name_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
4581 offset += 4;
4582 proto_tree_add_item(ext_tree, hf_ssh_ext_name, packet_tvb, offset, ext_name_slen, ENC_ASCII0x00000000);
4583 offset += ext_name_slen;
4584 proto_tree_add_item(ext_tree, hf_ssh_ext_value_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
4585 offset += 4;
4586 proto_tree_add_item(ext_tree, hf_ssh_ext_value, packet_tvb, offset, ext_value_slen, ENC_NA0x00000000);
4587
4588 if (g_str_equal(ext_name, "server-sig-algs")(strcmp ((const char *) (ext_name), (const char *) ("server-sig-algs"
)) == 0)
) {
4589 // server-sig-algs (RFC8308 Sec. 3.1)
4590 proto_tree_add_item(ext_tree, hf_ssh_ext_server_sig_algs_algorithms, packet_tvb, offset, ext_value_slen, ENC_ASCII0x00000000);
4591 offset += ext_value_slen;
4592 } else if (g_str_equal(ext_name, "delay-compression")(strcmp ((const char *) (ext_name), (const char *) ("delay-compression"
)) == 0)
) {
4593 // delay-compression (RFC8308 Sec 3.2)
4594 unsigned slen;
4595 slen = tvb_get_ntohl(packet_tvb, offset);
4596 proto_tree_add_item(ext_tree, hf_ssh_ext_delay_compression_algorithms_client_to_server_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
4597 offset += 4;
4598 proto_tree_add_item(ext_tree, hf_ssh_ext_delay_compression_algorithms_client_to_server, packet_tvb, offset, slen, ENC_ASCII0x00000000);
4599 offset += slen;
4600 slen = tvb_get_ntohl(packet_tvb, offset);
4601 proto_tree_add_item(ext_tree, hf_ssh_ext_delay_compression_algorithms_server_to_client_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
4602 offset += 4;
4603 proto_tree_add_item(ext_tree, hf_ssh_ext_delay_compression_algorithms_server_to_client, packet_tvb, offset, slen, ENC_ASCII0x00000000);
4604 offset += slen;
4605 } else if (g_str_equal(ext_name, "no-flow-control")(strcmp ((const char *) (ext_name), (const char *) ("no-flow-control"
)) == 0)
) {
4606 // no-flow-control (RFC 8308 Sec 3.3)
4607 proto_tree_add_item(ext_tree, hf_ssh_ext_no_flow_control_value, packet_tvb, offset, ext_value_slen, ENC_ASCII0x00000000);
4608 offset += ext_value_slen;
4609 } else if (g_str_equal(ext_name, "elevation")(strcmp ((const char *) (ext_name), (const char *) ("elevation"
)) == 0)
) {
4610 // elevation (RFC 8308 Sec 3.4)
4611 proto_tree_add_item(ext_tree, hf_ssh_ext_elevation_value, packet_tvb, offset, ext_value_slen, ENC_ASCII0x00000000);
4612 offset += ext_value_slen;
4613 } else if (g_str_equal(ext_name, "[email protected]")(strcmp ((const char *) (ext_name), (const char *) ("[email protected]"
)) == 0)
) {
4614 // [email protected] (proprietary)
4615 proto_tree_add_item(ext_tree, hf_ssh_ext_prop_publickey_algorithms_algorithms, packet_tvb, offset, ext_value_slen, ENC_ASCII0x00000000);
4616 offset += ext_value_slen;
4617 } else if (g_str_equal(ext_name, "[email protected]")(strcmp ((const char *) (ext_name), (const char *) ("[email protected]"
)) == 0)
) {
4618 // [email protected] (proprietary w/ primitive extension value)
4619 peer_data->global_data->ext_ping_openssh_offered = true1;
4620 offset += ext_value_slen;
4621 } else {
4622 offset += ext_value_slen;
4623 }
4624
4625 // The following extensions do not require advanced dissection:
4626 // - global-requests-ok
4627 // - ext-auth-info
4628 // - [email protected]
4629 // - [email protected]
4630
4631 return offset;
4632}
4633
4634static int
4635ssh_dissect_userauth_generic(tvbuff_t *packet_tvb, packet_info *pinfo,
4636 int offset, proto_item *msg_type_tree, unsigned msg_code)
4637{
4638 if(msg_code==SSH_MSG_USERAUTH_REQUEST50){
4639 uint32_t slen;
4640 proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_userauth_user_name_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000, &slen);
4641 offset += 4;
4642 proto_tree_add_item(msg_type_tree, hf_ssh_userauth_user_name, packet_tvb, offset, slen, ENC_ASCII0x00000000);
4643 offset += slen;
4644 proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_userauth_service_name_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000, &slen);
4645 offset += 4;
4646 proto_tree_add_item(msg_type_tree, hf_ssh_userauth_service_name, packet_tvb, offset, slen, ENC_ASCII0x00000000);
4647 offset += slen;
4648 proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_userauth_method_name_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000, &slen);
4649 offset += 4;
4650 const char* key_type;
4651 proto_tree_add_item_ret_string(msg_type_tree, hf_ssh_userauth_method_name, packet_tvb, offset, slen, ENC_ASCII0x00000000, pinfo->pool, (const uint8_t**)&key_type);
4652 offset += slen;
4653 if (0 == strcmp(key_type, "none")) {
4654 }else if (0 == strcmp(key_type, "publickey") || 0 == strcmp(key_type, "[email protected]")) {
4655 uint8_t bHaveSignature = tvb_get_uint8(packet_tvb, offset);
4656 int dissected_len = 0;
4657 proto_tree_add_item(msg_type_tree, hf_ssh_userauth_have_signature, packet_tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
4658 offset += 1;
4659 proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_userauth_pka_name_len, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000, &slen);
4660 offset += 4;
4661 proto_tree_add_item(msg_type_tree, hf_ssh_userauth_pka_name, packet_tvb, offset, slen, ENC_ASCII0x00000000);
4662 offset += slen;
4663 proto_item *ti;
4664 ti = proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_blob_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000, &slen);
4665 offset += 4;
4666 dissected_len = ssh_dissect_public_key_blob(tvb_new_subset_length(packet_tvb, offset, slen), pinfo, msg_type_tree);
4667 if(dissected_len!=(int)slen){
4668 expert_add_info_format(pinfo, ti, &ei_ssh_packet_decode, "Decoded %d bytes, but packet length is %d bytes", dissected_len, slen);
4669 }
4670 offset += slen;
4671 if (0 == strcmp(key_type, "[email protected]")) {
4672 // Host key - but should we add it to global data or not?
4673 offset += ssh_tree_add_hostkey(packet_tvb, pinfo, offset, msg_type_tree, "Server host key",
4674 ett_key_exchange_host_key, NULL((void*)0));
4675 }
4676 if(bHaveSignature){
4677 proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_signature_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000, &slen);
4678 offset += 4;
4679 proto_item *signature_tree = NULL((void*)0);
4680 signature_tree = proto_tree_add_subtree(msg_type_tree, packet_tvb, offset, slen, ett_userauth_pk_signature, NULL((void*)0), "Public key signature");
4681 dissected_len = ssh_dissect_public_key_signature(packet_tvb, pinfo, offset, signature_tree) - offset;
4682 if(dissected_len!=(int)slen){
4683 expert_add_info_format(pinfo, signature_tree, &ei_ssh_packet_decode, "Decoded %d bytes, but packet length is %d bytes", dissected_len, slen);
4684 }
4685 offset += slen;
4686 }
4687 }else if (0 == strcmp(key_type, "password")) {
4688 uint8_t bChangePassword = tvb_get_uint8(packet_tvb, offset);
4689 proto_tree_add_item(msg_type_tree, hf_ssh_userauth_change_password, packet_tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
4690 offset += 1;
4691 proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_userauth_password_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000, &slen);
4692 offset += 4;
4693 proto_tree_add_item(msg_type_tree, hf_ssh_userauth_password, packet_tvb, offset, slen, ENC_ASCII0x00000000);
4694 offset += slen;
4695 if(bChangePassword){
4696 proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_userauth_new_password_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000, &slen);
4697 offset += 4;
4698 proto_tree_add_item(msg_type_tree, hf_ssh_userauth_new_password, packet_tvb, offset, slen, ENC_ASCII0x00000000);
4699 offset += slen;
4700 }
4701 }else{
4702 }
4703
4704 }else if(msg_code==SSH_MSG_USERAUTH_FAILURE51){
4705 unsigned slen;
4706 proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_auth_failure_list_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000, &slen);
4707 offset += 4;
4708 proto_tree_add_item(msg_type_tree, hf_ssh_auth_failure_list, packet_tvb, offset, slen, ENC_ASCII0x00000000);
4709 offset += slen;
4710 proto_tree_add_item(msg_type_tree, hf_ssh_userauth_partial_success, packet_tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
4711 offset += 1;
4712 }
4713 return offset;
4714}
4715
4716static int
4717ssh_dissect_userauth_specific(tvbuff_t *packet_tvb, packet_info *pinfo,
4718 int offset, proto_item *msg_type_tree, unsigned msg_code)
4719{
4720 if(msg_code==SSH_MSG_USERAUTH_PK_OK60){
4721 proto_item *ti;
4722 int dissected_len = 0;
4723 unsigned slen;
4724 slen = tvb_get_ntohl(packet_tvb, offset) ;
4725 proto_tree_add_item(msg_type_tree, hf_ssh_userauth_pka_name_len, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
4726 offset += 4;
4727 proto_tree_add_item(msg_type_tree, hf_ssh_userauth_pka_name, packet_tvb, offset, slen, ENC_ASCII0x00000000);
4728 offset += slen;
4729 ti = proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_blob_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000, &slen);
4730 offset += 4;
4731 dissected_len = ssh_dissect_public_key_blob(tvb_new_subset_length(packet_tvb, offset, slen), pinfo, msg_type_tree);
4732 if(dissected_len!=(int)slen){
4733 expert_add_info_format(pinfo, ti, &ei_ssh_packet_decode, "Decoded %d bytes, but packet length is %d bytes", dissected_len, slen);
4734 }
4735 offset += slen;
4736 }
4737 return offset;
4738}
4739
4740static void
4741ssh_process_payload(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, ssh_channel_info_t *channel)
4742{
4743 tvbuff_t *next_tvb = tvb_new_subset_remaining(tvb, offset);
4744 if (channel->handle) {
4745 call_dissector(channel->handle, next_tvb, pinfo, proto_tree_get_root(tree));
4746 } else {
4747 call_data_dissector(next_tvb, pinfo, proto_tree_get_root(tree));
4748 }
4749}
4750
4751static void
4752print_ssh_fragment_tree(fragment_head *ipfd_head, proto_tree *tree, proto_tree *ssh_tree, packet_info *pinfo, tvbuff_t *next_tvb)
4753{
4754 proto_item *ssh_tree_item, *frag_tree_item;
4755
4756 /*
4757 * The subdissector thought it was completely
4758 * desegmented (although the stuff at the
4759 * end may, in turn, require desegmentation),
4760 * so we show a tree with all segments.
4761 */
4762 show_fragment_tree(ipfd_head, &ssh_segment_items,
4763 tree, pinfo, next_tvb, &frag_tree_item);
4764 /*
4765 * The toplevel fragment subtree is now
4766 * behind all desegmented data; move it
4767 * right behind the SSH tree.
4768 */
4769 ssh_tree_item = proto_tree_get_parent(ssh_tree);
4770 /* The SSH protocol item is up a few levels from the message tree */
4771 ssh_tree_item = proto_item_get_parent_nth(ssh_tree_item, 2);
4772 if (frag_tree_item && ssh_tree_item) {
4773 proto_tree_move_item(tree, ssh_tree_item, frag_tree_item);
4774 }
4775}
4776
4777static uint32_t
4778ssh_msp_fragment_id(struct tcp_multisegment_pdu *msp)
4779{
4780 /*
4781 * If a frame contains multiple PDUs, then "first_frame" is not
4782 * sufficient to uniquely identify groups of fragments. Therefore we use
4783 * the tcp reassembly functions that also test msp->seq (the position of
4784 * the initial fragment in the SSH channel).
4785 */
4786 return msp->first_frame;
4787}
4788
4789static void
4790ssh_proto_tree_add_segment_data(
4791 proto_tree *tree,
4792 tvbuff_t *tvb,
4793 int offset,
4794 int length,
4795 const char *prefix)
4796{
4797 proto_tree_add_bytes_format(
4798 tree,
4799 hf_ssh_segment_data,
4800 tvb,
4801 offset,
4802 length,
4803 NULL((void*)0),
4804 "%sSSH segment data (%u %s)",
4805 prefix != NULL((void*)0) ? prefix : "",
4806 length,
4807 plurality(length, "byte", "bytes")((length) == 1 ? ("byte") : ("bytes")));
4808}
4809
4810static void
4811desegment_ssh(tvbuff_t *tvb, packet_info *pinfo, uint32_t seq,
4812 uint32_t nxtseq, proto_tree *tree, ssh_channel_info_t *channel)
4813{
4814 fragment_head *ipfd_head;
4815 bool_Bool must_desegment;
4816 bool_Bool called_dissector;
4817 unsigned another_pdu_follows;
4818 bool_Bool another_segment_in_frame = false0;
4819 int deseg_offset, offset = 0;
4820 uint32_t deseg_seq;
4821 int nbytes;
4822 proto_item *item;
4823 struct tcp_multisegment_pdu *msp;
4824 bool_Bool first_pdu = true1;
4825
4826again:
4827 ipfd_head = NULL((void*)0);
4828 must_desegment = false0;
4829 called_dissector = false0;
4830 another_pdu_follows = 0;
4831 msp = NULL((void*)0);
4832
4833 /*
4834 * Initialize these to assume no desegmentation.
4835 * If that's not the case, these will be set appropriately
4836 * by the subdissector.
4837 */
4838 pinfo->desegment_offset = 0;
4839 pinfo->desegment_len = 0;
4840
4841 /*
4842 * Initialize this to assume that this segment will just be
4843 * added to the middle of a desegmented chunk of data, so
4844 * that we should show it all as data.
4845 * If that's not the case, it will be set appropriately.
4846 */
4847 deseg_offset = offset;
4848
4849 /* If we've seen this segment before (e.g., it's a retransmission),
4850 * there's nothing for us to do. Certainly, don't add it to the list
4851 * of multisegment_pdus (that would cause subsequent lookups to find
4852 * the retransmission instead of the original transmission, breaking
4853 * dissection of the desegmented pdu if we'd already seen the end of
4854 * the pdu).
4855 */
4856 if ((msp = (struct tcp_multisegment_pdu *)wmem_tree_lookup32(channel->multisegment_pdus, seq))) {
4857 const char *prefix;
4858 bool_Bool is_retransmission = false0;
4859
4860 if (msp->first_frame == pinfo->num) {
4861 /* This must be after the first pass. */
4862 prefix = "";
4863 if (msp->last_frame == pinfo->num) {
4864 col_clear(pinfo->cinfo, COL_INFO);
4865 } else {
4866 if (first_pdu) {
4867 col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "[SSH segment of a reassembled PDU]");
4868 }
4869 }
4870 } else {
4871 prefix = "Retransmitted ";
4872 is_retransmission = true1;
4873 }
4874
4875 if (!is_retransmission) {
4876 ipfd_head = fragment_get(&ssh_reassembly_table, pinfo, msp->first_frame, msp);
4877 if (ipfd_head != NULL((void*)0) && ipfd_head->reassembled_in !=0 &&
4878 ipfd_head->reassembled_in != pinfo->num) {
4879 /* Show what frame this was reassembled in if not this one. */
4880 item=proto_tree_add_uint(tree, *ssh_segment_items.hf_reassembled_in,
4881 tvb, 0, 0, ipfd_head->reassembled_in);
4882 proto_item_set_generated(item);
4883 }
4884 }
4885 nbytes = tvb_reported_length_remaining(tvb, offset);
4886 ssh_proto_tree_add_segment_data(tree, tvb, offset, nbytes, prefix);
4887 return;
4888 }
4889
4890 /* Else, find the most previous PDU starting before this sequence number */
4891 msp = (struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(channel->multisegment_pdus, seq-1);
4892 if (msp && msp->seq <= seq && msp->nxtpdu > seq) {
4893 unsigned len;
4894
4895 if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) {
4896 msp->last_frame = pinfo->num;
4897 msp->last_frame_time = pinfo->abs_ts;
4898 }
4899
4900 /* OK, this PDU was found, which means the segment continues
4901 * a higher-level PDU and that we must desegment it.
4902 */
4903 if (msp->flags & MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT0x00000001) {
4904 /* The dissector asked for the entire segment */
4905 len = tvb_reported_length_remaining(tvb, offset);
4906 } else {
4907 len = MIN(nxtseq, msp->nxtpdu)(((nxtseq) < (msp->nxtpdu)) ? (nxtseq) : (msp->nxtpdu
))
- seq;
4908 }
4909
4910 ipfd_head = fragment_add(&ssh_reassembly_table, tvb, offset,
4911 pinfo, ssh_msp_fragment_id(msp), msp,
4912 seq - msp->seq,
4913 len, (LT_SEQ (nxtseq,msp->nxtpdu)((int32_t)((nxtseq) - (msp->nxtpdu)) < 0)));
4914
4915 if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)
4916 && msp->flags & MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT0x00000001) {
4917 msp->flags &= (~MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT0x00000001);
4918
4919 /* If we consumed the entire segment there is no
4920 * other pdu starting anywhere inside this segment.
4921 * So update nxtpdu to point at least to the start
4922 * of the next segment.
4923 * (If the subdissector asks for even more data we
4924 * will advance nxtpdu even further later down in
4925 * the code.)
4926 */
4927 msp->nxtpdu = nxtseq;
4928 }
4929
4930 if ( (msp->nxtpdu < nxtseq)
4931 && (msp->nxtpdu >= seq)
4932 && (len > 0)) {
4933 another_pdu_follows = msp->nxtpdu - seq;
4934 }
4935 } else {
4936 /* This segment was not found in our table, so it doesn't
4937 * contain a continuation of a higher-level PDU.
4938 * Call the normal subdissector.
4939 */
4940 ssh_process_payload(tvb, offset, pinfo, tree, channel);
4941 called_dissector = true1;
4942
4943 /* Did the subdissector ask us to desegment some more data
4944 * before it could handle the packet?
4945 * If so we have to create some structures in our table but
4946 * this is something we only do the first time we see this
4947 * packet.
4948 */
4949 if (pinfo->desegment_len) {
4950 if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited))
4951 must_desegment = true1;
4952
4953 /*
4954 * Set "deseg_offset" to the offset in "tvb"
4955 * of the first byte of data that the
4956 * subdissector didn't process.
4957 */
4958 deseg_offset = offset + pinfo->desegment_offset;
4959 }
4960
4961 /* Either no desegmentation is necessary, or this is
4962 * segment contains the beginning but not the end of
4963 * a higher-level PDU and thus isn't completely
4964 * desegmented.
4965 */
4966 ipfd_head = NULL((void*)0);
4967 }
4968
4969 /* is it completely desegmented? */
4970 if (ipfd_head && ipfd_head->reassembled_in == pinfo->num) {
4971 /*
4972 * Yes, we think it is.
4973 * We only call subdissector for the last segment.
4974 * Note that the last segment may include more than what
4975 * we needed.
4976 */
4977 if (nxtseq < msp->nxtpdu) {
4978 /*
4979 * This is *not* the last segment. It is part of a PDU in the same
4980 * frame, so no another PDU can follow this one.
4981 * Do not reassemble SSH yet, it will be done in the final segment.
4982 * (If we are reassembling at FIN, we will do that in dissect_ssl()
4983 * after iterating through all the records.)
4984 * Clear the Info column and avoid displaying [SSH segment of a
4985 * reassembled PDU], the payload dissector will typically set it.
4986 * (This is needed here for the second pass.)
4987 */
4988 another_pdu_follows = 0;
4989 col_clear(pinfo->cinfo, COL_INFO);
4990 another_segment_in_frame = true1;
4991 } else {
4992 /*
4993 * OK, this is the last segment of the PDU and also the
4994 * last segment in this frame.
4995 * Let's call the subdissector with the desegmented
4996 * data.
4997 */
4998 tvbuff_t *next_tvb;
4999 int old_len;
5000
5001 /*
5002 * Reset column in case multiple SSH segments form the PDU
5003 * and this last SSH segment is not in the first TCP segment of
5004 * this frame.
5005 * XXX prevent clearing the column if the last layer is not SSH?
5006 */
5007 /* Clear column during the first pass. */
5008 col_clear(pinfo->cinfo, COL_INFO);
5009
5010 /* create a new TVB structure for desegmented data */
5011 next_tvb = tvb_new_chain(tvb, ipfd_head->tvb_data);
5012
5013 /* add desegmented data to the data source list */
5014 add_new_data_source(pinfo, next_tvb, "Reassembled SSH");
5015
5016 /* call subdissector */
5017 ssh_process_payload(next_tvb, 0, pinfo, tree, channel);
5018 called_dissector = true1;
5019
5020 /*
5021 * OK, did the subdissector think it was completely
5022 * desegmented, or does it think we need even more
5023 * data?
5024 */
5025 old_len = (int)(tvb_reported_length(next_tvb) - tvb_reported_length_remaining(tvb, offset));
5026 if (pinfo->desegment_len && pinfo->desegment_offset <= old_len) {
5027 /*
5028 * "desegment_len" isn't 0, so it needs more
5029 * data for something - and "desegment_offset"
5030 * is before "old_len", so it needs more data
5031 * to dissect the stuff we thought was
5032 * completely desegmented (as opposed to the
5033 * stuff at the beginning being completely
5034 * desegmented, but the stuff at the end
5035 * being a new higher-level PDU that also
5036 * needs desegmentation).
5037 */
5038 fragment_set_partial_reassembly(&ssh_reassembly_table,
5039 pinfo, ssh_msp_fragment_id(msp), msp);
5040 /* Update msp->nxtpdu to point to the new next
5041 * pdu boundary.
5042 */
5043 if (pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT0x0fffffff) {
5044 /* We want reassembly of at least one
5045 * more segment so set the nxtpdu
5046 * boundary to one byte into the next
5047 * segment.
5048 * This means that the next segment
5049 * will complete reassembly even if it
5050 * is only one single byte in length.
5051 */
5052 msp->nxtpdu = seq + tvb_reported_length_remaining(tvb, offset) + 1;
5053 msp->flags |= MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT0x00000001;
5054 } else if (pinfo->desegment_len == DESEGMENT_UNTIL_FIN0x0ffffffe) {
5055 /* This is not the first segment, and we thought reassembly
5056 * would be done now, but now we know we desegment at FIN.
5057 * E.g., a HTTP response where the headers were split
5058 * across segments (so previous ONE_MORE_SEGMENT) and
5059 * also no Content-Length (so now DESEGMENT_UNTIL_FIN).
5060 */
5061 channel->flags |= TCP_FLOW_REASSEMBLE_UNTIL_FIN0x0001;
5062 msp->nxtpdu = nxtseq + 0x40000000;
5063 } else {
5064 msp->nxtpdu = seq + tvb_reported_length_remaining(tvb, offset) + pinfo->desegment_len;
5065 }
5066 /* Since we need at least some more data
5067 * there can be no pdu following in the
5068 * tail of this segment.
5069 */
5070 another_pdu_follows = 0;
5071 } else {
5072 /*
5073 * Show the stuff in this TCP segment as
5074 * just raw TCP segment data.
5075 */
5076 nbytes = another_pdu_follows > 0
5077 ? another_pdu_follows
5078 : tvb_reported_length_remaining(tvb, offset);
5079 ssh_proto_tree_add_segment_data(tree, tvb, offset, nbytes, NULL((void*)0));
5080
5081 /* Show details of the reassembly */
5082 print_ssh_fragment_tree(ipfd_head, proto_tree_get_root(tree), tree, pinfo, next_tvb);
5083
5084 /* Did the subdissector ask us to desegment
5085 * some more data? This means that the data
5086 * at the beginning of this segment completed
5087 * a higher-level PDU, but the data at the
5088 * end of this segment started a higher-level
5089 * PDU but didn't complete it.
5090 *
5091 * If so, we have to create some structures
5092 * in our table, but this is something we
5093 * only do the first time we see this packet.
5094 */
5095 if (pinfo->desegment_len) {
5096 if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited))
5097 must_desegment = true1;
5098
5099 /* The stuff we couldn't dissect
5100 * must have come from this segment,
5101 * so it's all in "tvb".
5102 *
5103 * "pinfo->desegment_offset" is
5104 * relative to the beginning of
5105 * "next_tvb"; we want an offset
5106 * relative to the beginning of "tvb".
5107 *
5108 * First, compute the offset relative
5109 * to the *end* of "next_tvb" - i.e.,
5110 * the number of bytes before the end
5111 * of "next_tvb" at which the
5112 * subdissector stopped. That's the
5113 * length of "next_tvb" minus the
5114 * offset, relative to the beginning
5115 * of "next_tvb, at which the
5116 * subdissector stopped.
5117 */
5118 deseg_offset = ipfd_head->datalen - pinfo->desegment_offset;
5119
5120 /* "tvb" and "next_tvb" end at the
5121 * same byte of data, so the offset
5122 * relative to the end of "next_tvb"
5123 * of the byte at which we stopped
5124 * is also the offset relative to
5125 * the end of "tvb" of the byte at
5126 * which we stopped.
5127 *
5128 * Convert that back into an offset
5129 * relative to the beginning of
5130 * "tvb", by taking the length of
5131 * "tvb" and subtracting the offset
5132 * relative to the end.
5133 */
5134 deseg_offset = tvb_reported_length(tvb) - deseg_offset;
5135 }
5136 }
5137 }
5138 }
5139
5140 if (must_desegment) {
5141 /* If the dissector requested "reassemble until FIN"
5142 * just set this flag for the flow and let reassembly
5143 * proceed at normal. We will check/pick up these
5144 * reassembled PDUs later down in dissect_tcp() when checking
5145 * for the FIN flag.
5146 */
5147 if (pinfo->desegment_len == DESEGMENT_UNTIL_FIN0x0ffffffe) {
5148 channel->flags |= TCP_FLOW_REASSEMBLE_UNTIL_FIN0x0001;
5149 }
5150 /*
5151 * The sequence number at which the stuff to be desegmented
5152 * starts is the sequence number of the byte at an offset
5153 * of "deseg_offset" into "tvb".
5154 *
5155 * The sequence number of the byte at an offset of "offset"
5156 * is "seq", i.e. the starting sequence number of this
5157 * segment, so the sequence number of the byte at
5158 * "deseg_offset" is "seq + (deseg_offset - offset)".
5159 */
5160 deseg_seq = seq + (deseg_offset - offset);
5161
5162 if (((nxtseq - deseg_seq) <= 1024*1024)
5163 && (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited))) {
5164 if (pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT0x0fffffff) {
5165 /* The subdissector asked to reassemble using the
5166 * entire next segment.
5167 * Just ask reassembly for one more byte
5168 * but set this msp flag so we can pick it up
5169 * above.
5170 */
5171 msp = pdu_store_sequencenumber_of_next_pdu(pinfo,
5172 deseg_seq, nxtseq+1, channel->multisegment_pdus);
5173 msp->flags |= MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT0x00000001;
5174 } else if (pinfo->desegment_len == DESEGMENT_UNTIL_FIN0x0ffffffe) {
5175 /* Set nxtseq very large so that reassembly won't happen
5176 * until we force it at the end of the stream in dissect_ssl()
5177 * outside this function.
5178 */
5179 msp = pdu_store_sequencenumber_of_next_pdu(pinfo,
5180 deseg_seq, nxtseq+0x40000000, channel->multisegment_pdus);
5181 } else {
5182 msp = pdu_store_sequencenumber_of_next_pdu(pinfo,
5183 deseg_seq, nxtseq+pinfo->desegment_len, channel->multisegment_pdus);
5184 }
5185
5186 /* add this segment as the first one for this new pdu */
5187 fragment_add(&ssh_reassembly_table, tvb, deseg_offset,
5188 pinfo, ssh_msp_fragment_id(msp), msp,
5189 0, nxtseq - deseg_seq,
5190 LT_SEQ(nxtseq, msp->nxtpdu)((int32_t)((nxtseq) - (msp->nxtpdu)) < 0));
5191 }
5192 }
5193
5194 if (!called_dissector || pinfo->desegment_len != 0) {
5195 if (ipfd_head != NULL((void*)0) && ipfd_head->reassembled_in != 0 &&
5196 ipfd_head->reassembled_in != pinfo->num &&
5197 !(ipfd_head->flags & FD_PARTIAL_REASSEMBLY0x0040)) {
5198 /*
5199 * We know what other frame this PDU is reassembled in;
5200 * let the user know.
5201 */
5202 item=proto_tree_add_uint(tree, *ssh_segment_items.hf_reassembled_in,
5203 tvb, 0, 0, ipfd_head->reassembled_in);
5204 proto_item_set_generated(item);
5205 }
5206
5207 /*
5208 * Either we didn't call the subdissector at all (i.e.,
5209 * this is a segment that contains the middle of a
5210 * higher-level PDU, but contains neither the beginning
5211 * nor the end), or the subdissector couldn't dissect it
5212 * all, as some data was missing (i.e., it set
5213 * "pinfo->desegment_len" to the amount of additional
5214 * data it needs).
5215 */
5216 if (!another_segment_in_frame && pinfo->desegment_offset == 0) {
5217 /*
5218 * It couldn't, in fact, dissect any of it (the
5219 * first byte it couldn't dissect is at an offset
5220 * of "pinfo->desegment_offset" from the beginning
5221 * of the payload, and that's 0).
5222 * Just mark this as SSH.
5223 */
5224
5225 /* SFTP checks the length before setting the protocol column.
5226 * If other subdissectors don't do this, we'd want to set the
5227 * protocol column back - but we want to get the SSH version
5228 */
5229 //col_set_str(pinfo->cinfo, COL_PROTOCOL,
5230 // val_to_str_const(session->version, ssl_version_short_names, "SSH"));
5231 if (first_pdu) {
5232 col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "[SSH segment of a reassembled PDU]");
5233 }
5234 }
5235
5236 /*
5237 * Show what's left in the packet as just raw SSH segment data.
5238 * XXX - remember what protocol the last subdissector
5239 * was, and report it as a continuation of that, instead?
5240 */
5241 nbytes = tvb_reported_length_remaining(tvb, deseg_offset);
5242 ssh_proto_tree_add_segment_data(tree, tvb, deseg_offset, nbytes, NULL((void*)0));
5243 }
5244 pinfo->can_desegment = 0;
5245 pinfo->desegment_offset = 0;
5246 pinfo->desegment_len = 0;
5247
5248 if (another_pdu_follows) {
5249 /* there was another pdu following this one. */
5250 pinfo->can_desegment=2;
5251 /* we also have to prevent the dissector from changing the
5252 * PROTOCOL and INFO colums since what follows may be an
5253 * incomplete PDU and we don't want it be changed back from
5254 * <Protocol> to <SSH>
5255 */
5256 col_set_fence(pinfo->cinfo, COL_INFO);
5257 col_set_writable(pinfo->cinfo, COL_PROTOCOL, false0);
5258 first_pdu = false0;
5259 offset += another_pdu_follows;
5260 seq += another_pdu_follows;
5261 goto again;
5262 }
5263}
5264
5265static void
5266ssh_dissect_channel_data(tvbuff_t *tvb, packet_info *pinfo,
5267 struct ssh_peer_data *peer_data _U___attribute__((unused)), proto_tree *tree,
5268 ssh_message_info_t *message _U___attribute__((unused)), ssh_channel_info_t *channel)
5269{
5270
5271 uint16_t save_can_desegment = pinfo->can_desegment;
5272
5273 if (ssh_desegment) {
5274 pinfo->can_desegment = 2;
5275 desegment_ssh(tvb, pinfo, message->byte_seq, message->next_byte_seq, tree, channel);
5276 } else {
5277 pinfo->can_desegment = 0;
5278 bool_Bool save_fragmented = pinfo->fragmented;
5279 pinfo->fragmented = true1;
5280
5281 ssh_process_payload(tvb, 0, pinfo, tree, channel);
5282 pinfo->fragmented = save_fragmented;
5283 }
5284
5285 pinfo->can_desegment = save_can_desegment;
5286}
5287
5288static int
5289ssh_dissect_term_modes(tvbuff_t *tvb, packet_info *pinfo _U___attribute__((unused)), proto_tree *tree)
5290{
5291 proto_item *ti;
5292 proto_tree *term_mode_tree, *subtree;
5293 int offset = 0;
5294 uint32_t opcode, value, idx;
5295 bool_Bool boolval;
5296
5297 struct tty_opt_info {
5298 unsigned id;
5299 int *hfindex;
5300 };
5301 static const struct tty_opt_info tty_opts[] = {
5302 { SSH_TTY_OP_END0, NULL((void*)0)},
5303 { SSH_TTY_OP_VINTR1, &hf_ssh_pty_term_mode_vintr },
5304 { SSH_TTY_OP_VQUIT2, &hf_ssh_pty_term_mode_vquit },
5305 { SSH_TTY_OP_VERASE3, &hf_ssh_pty_term_mode_verase },
5306 { SSH_TTY_OP_VKILL4, &hf_ssh_pty_term_mode_vkill },
5307 { SSH_TTY_OP_VEOF5, &hf_ssh_pty_term_mode_veof },
5308 { SSH_TTY_OP_VEOL6, &hf_ssh_pty_term_mode_veol },
5309 { SSH_TTY_OP_VEOL27, &hf_ssh_pty_term_mode_veol2 },
5310 { SSH_TTY_OP_VSTART8, &hf_ssh_pty_term_mode_vstart },
5311 { SSH_TTY_OP_VSTOP9, &hf_ssh_pty_term_mode_vstop },
5312 { SSH_TTY_OP_VSUSP10, &hf_ssh_pty_term_mode_vsusp },
5313 { SSH_TTY_OP_VDSUSP11, &hf_ssh_pty_term_mode_vdsusp },
5314 { SSH_TTY_OP_VREPRINT12, &hf_ssh_pty_term_mode_vreprint },
5315 { SSH_TTY_OP_VWERASE13, &hf_ssh_pty_term_mode_vwerase },
5316 { SSH_TTY_OP_VLNEXT14, &hf_ssh_pty_term_mode_vlnext },
5317 { SSH_TTY_OP_VFLUSH15, &hf_ssh_pty_term_mode_vflush },
5318 { SSH_TTY_OP_VSWTCH16, &hf_ssh_pty_term_mode_vswtch },
5319 { SSH_TTY_OP_VSTATUS17, &hf_ssh_pty_term_mode_vstatus },
5320 { SSH_TTY_OP_VDISCARD18, &hf_ssh_pty_term_mode_vdiscard },
5321 { SSH_TTY_OP_IGNPAR30, &hf_ssh_pty_term_mode_ignpar },
5322 { SSH_TTY_OP_PARMRK31, &hf_ssh_pty_term_mode_parmrk },
5323 { SSH_TTY_OP_INPCK32, &hf_ssh_pty_term_mode_inpck },
5324 { SSH_TTY_OP_ISTRIP33, &hf_ssh_pty_term_mode_istrip },
5325 { SSH_TTY_OP_INLCR34, &hf_ssh_pty_term_mode_inlcr },
5326 { SSH_TTY_OP_IGNCR35, &hf_ssh_pty_term_mode_igncr },
5327 { SSH_TTY_OP_ICRNL36, &hf_ssh_pty_term_mode_icrnl },
5328 { SSH_TTY_OP_IUCLC37, &hf_ssh_pty_term_mode_iuclc },
5329 { SSH_TTY_OP_IXON38, &hf_ssh_pty_term_mode_ixon },
5330 { SSH_TTY_OP_IXANY39, &hf_ssh_pty_term_mode_ixany },
5331 { SSH_TTY_OP_IXOFF40, &hf_ssh_pty_term_mode_ixoff },
5332 { SSH_TTY_OP_IMAXBEL41, &hf_ssh_pty_term_mode_imaxbel },
5333 { SSH_TTY_OP_IUTF842, &hf_ssh_pty_term_mode_iutf8 },
5334 { SSH_TTY_OP_ISIG50, &hf_ssh_pty_term_mode_isig },
5335 { SSH_TTY_OP_ICANON51, &hf_ssh_pty_term_mode_icanon },
5336 { SSH_TTY_OP_XCASE52, &hf_ssh_pty_term_mode_xcase },
5337 { SSH_TTY_OP_ECHO53, &hf_ssh_pty_term_mode_echo },
5338 { SSH_TTY_OP_ECHOE54, &hf_ssh_pty_term_mode_echoe },
5339 { SSH_TTY_OP_ECHOK55, &hf_ssh_pty_term_mode_echok },
5340 { SSH_TTY_OP_ECHONL56, &hf_ssh_pty_term_mode_echonl },
5341 { SSH_TTY_OP_NOFLSH57, &hf_ssh_pty_term_mode_noflsh },
5342 { SSH_TTY_OP_TOSTOP58, &hf_ssh_pty_term_mode_tostop },
5343 { SSH_TTY_OP_IEXTEN59, &hf_ssh_pty_term_mode_iexten },
5344 { SSH_TTY_OP_ECHOCTL60, &hf_ssh_pty_term_mode_echoctl },
5345 { SSH_TTY_OP_ECHOKE61, &hf_ssh_pty_term_mode_echoke },
5346 { SSH_TTY_OP_PENDIN62, &hf_ssh_pty_term_mode_pendin },
5347 { SSH_TTY_OP_OPOST70, &hf_ssh_pty_term_mode_opost },
5348 { SSH_TTY_OP_OLCUC71, &hf_ssh_pty_term_mode_olcuc },
5349 { SSH_TTY_OP_ONLCR72, &hf_ssh_pty_term_mode_onlcr },
5350 { SSH_TTY_OP_OCRNL73, &hf_ssh_pty_term_mode_ocrnl },
5351 { SSH_TTY_OP_ONOCR74, &hf_ssh_pty_term_mode_onocr },
5352 { SSH_TTY_OP_ONLRET75, &hf_ssh_pty_term_mode_onlret },
5353 { SSH_TTY_OP_CS790, &hf_ssh_pty_term_mode_cs7 },
5354 { SSH_TTY_OP_CS891, &hf_ssh_pty_term_mode_cs8 },
5355 { SSH_TTY_OP_PARENB92, &hf_ssh_pty_term_mode_parenb },
5356 { SSH_TTY_OP_PARODD93, &hf_ssh_pty_term_mode_parodd },
5357 { SSH_TTY_OP_ISPEED128, &hf_ssh_pty_term_mode_ispeed },
5358 { SSH_TTY_OP_OSPEED129, &hf_ssh_pty_term_mode_ospeed }
5359 };
5360
5361 ti = proto_tree_add_item(tree, hf_ssh_pty_term_modes, tvb, offset, tvb_reported_length(tvb), ENC_NA0x00000000);
5362 term_mode_tree = proto_item_add_subtree(ti, ett_term_modes);
5363 while (tvb_reported_length_remaining(tvb, offset)) {
5364 ti = proto_tree_add_item(term_mode_tree, hf_ssh_pty_term_mode, tvb, offset, 5, ENC_NA0x00000000);
5365 subtree = proto_item_add_subtree(ti, ett_term_mode);
5366 proto_tree_add_item_ret_uint(subtree, hf_ssh_pty_term_mode_opcode, tvb, offset, 1, ENC_NA0x00000000, &opcode);
5367 proto_item_append_text(ti, ": %s", val_to_str_const(opcode, ssh_tty_op_vals, "Unknown"));
5368 offset += 1;
5369 if (opcode == SSH_TTY_OP_END0) {
5370 break;
5371 }
5372 for (idx = 0; idx < array_length(tty_opts)(sizeof (tty_opts) / sizeof (tty_opts)[0]); idx++) {
5373 if (tty_opts[idx].id == opcode) break;
5374 }
5375 if (idx >= array_length(tty_opts)(sizeof (tty_opts) / sizeof (tty_opts)[0])) {
5376 proto_tree_add_item_ret_uint(subtree, hf_ssh_pty_term_mode_value, tvb, offset, 4, ENC_BIG_ENDIAN0x00000000, &value);
5377 proto_item_append_text(ti, "=%d", value);
5378 } else {
5379 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"
, 5379, "tty_opts[idx].hfindex"))))
;
5380 int hfindex = *tty_opts[idx].hfindex;
5381 switch (proto_registrar_get_ftype(hfindex)) {
5382 case FT_BOOLEAN:
5383 proto_tree_add_item_ret_boolean(subtree, hfindex, tvb, offset + 3, 1, ENC_NA0x00000000, &boolval);
5384 proto_item_append_text(ti, "=%s", boolval ? "True" : "False");
5385 break;
5386 case FT_CHAR:
5387 proto_tree_add_item_ret_uint(subtree, hfindex, tvb, offset + 3, 1, ENC_NA0x00000000, &value);
5388 proto_item_append_text(ti, "='%s'", format_char(pinfo->pool, (char)value));
5389 break;
5390 case FT_UINT32:
5391 proto_tree_add_item_ret_uint(subtree, hfindex, tvb, offset, 4, ENC_BIG_ENDIAN0x00000000, &value);
5392 proto_item_append_text(ti, "=%d", value);
5393 break;
5394 default:
5395 DISSECTOR_ASSERT_NOT_REACHED()(proto_report_dissector_bug("%s:%u: failed assertion \"DISSECTOR_ASSERT_NOT_REACHED\""
, "epan/dissectors/packet-ssh.c", 5395))
;
5396 }
5397 }
5398 offset += 4;
5399 }
5400 return offset;
5401}
5402
5403static int
5404ssh_dissect_connection_specific(tvbuff_t *packet_tvb, packet_info *pinfo,
5405 struct ssh_peer_data *peer_data, int offset, proto_tree *msg_type_tree,
5406 unsigned msg_code, ssh_message_info_t *message)
5407{
5408 uint32_t recipient_channel, sender_channel;
5409
5410 if (msg_code == SSH_MSG_CHANNEL_OPEN90) {
5411 uint32_t slen;
5412 proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_connection_type_name_len, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000, &slen);
5413 offset += 4;
5414 proto_tree_add_item(msg_type_tree, hf_ssh_connection_type_name, packet_tvb, offset, slen, ENC_UTF_80x00000002);
5415 offset += slen;
5416 proto_tree_add_item(msg_type_tree, hf_ssh_connection_sender_channel, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
5417 offset += 4;
5418 proto_tree_add_item(msg_type_tree, hf_ssh_connection_initial_window, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
5419 offset += 4;
5420 proto_tree_add_item(msg_type_tree, hf_ssh_connection_maximum_packet_size, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
5421 offset += 4;
5422 } else if (msg_code == SSH_MSG_CHANNEL_OPEN_CONFIRMATION91) {
5423 proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_connection_recipient_channel, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000, &recipient_channel);
5424 offset += 4;
5425 proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_connection_sender_channel, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000, &sender_channel);
5426 offset += 4;
5427 if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) {
5428 create_channel(peer_data, recipient_channel, sender_channel);
5429 }
5430 proto_tree_add_item(msg_type_tree, hf_ssh_connection_initial_window, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
5431 offset += 4;
5432 proto_tree_add_item(msg_type_tree, hf_ssh_connection_maximum_packet_size, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
5433 offset += 4;
5434 } else if (msg_code == SSH_MSG_CHANNEL_WINDOW_ADJUST93) {
5435 proto_tree_add_item(msg_type_tree, hf_ssh_connection_recipient_channel, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
5436 offset += 4;
5437 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
5438 offset += 4;
5439 } else if (msg_code == SSH_MSG_CHANNEL_DATA94) {
5440 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);
5441 offset += 4;
5442 // TODO: process according to the type of channel
5443 uint32_t slen;
5444 proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_channel_data_len, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000, &slen);
5445 offset += 4;
5446 tvbuff_t* next_tvb = tvb_new_subset_length(packet_tvb, offset, slen);
5447
5448 ssh_channel_info_t* channel = get_channel_info_for_channel(peer_data, recipient_channel);
5449 if (channel) {
5450 if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) {
5451 message->byte_seq = channel->byte_seq;
5452 channel->byte_seq += slen;
5453 message->next_byte_seq = channel->byte_seq;
5454 }
5455 ssh_dissect_channel_data(next_tvb, pinfo, peer_data, msg_type_tree, message, channel);
5456 } else {
5457 expert_add_info_format(pinfo, ti, &ei_ssh_channel_number, "Could not find configuration for channel %d", recipient_channel);
5458 }
5459 offset += slen;
5460 } else if (msg_code == SSH_MSG_CHANNEL_EXTENDED_DATA95) {
5461 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);
5462 offset += 4;
5463 // TODO: process according to the type of channel
5464 proto_tree_add_item(msg_type_tree, hf_ssh_channel_data_type_code, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
5465 offset += 4;
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_EOF96) {
5484 proto_tree_add_item(msg_type_tree, hf_ssh_connection_recipient_channel, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
5485 offset += 4;
5486 } else if (msg_code == SSH_MSG_CHANNEL_CLOSE97) {
5487 proto_tree_add_item(msg_type_tree, hf_ssh_connection_recipient_channel, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
5488 offset += 4;
5489 } else if (msg_code == SSH_MSG_CHANNEL_REQUEST98) {
5490 proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_connection_recipient_channel, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000, &recipient_channel);
5491 offset += 4;
5492 const char* request_name;
5493 uint32_t slen;
5494 int item_len;
5495 proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_channel_request_name_len, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000, &slen);
5496 offset += 4;
5497 proto_tree_add_item_ret_string(msg_type_tree, hf_ssh_channel_request_name, packet_tvb, offset, slen, ENC_UTF_80x00000002, pinfo->pool, (const uint8_t**)&request_name);
5498 offset += slen;
5499 proto_tree_add_item(msg_type_tree, hf_ssh_channel_request_want_reply, packet_tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
5500 offset += 1;
5501 /* RFC 4254 6.5: "Only one of these requests ["shell", "exec",
5502 * or "subsystem"] can succeed per channel." Set up the
5503 * appropriate handler for future CHANNEL_DATA and
5504 * CHANNEL_EXTENDED_DATA messages on the channel.
5505 *
5506 * XXX - For "shell" and "exec", it might make more sense to send
5507 * CHANNEL_DATA to the "data-text-lines" dissector rather than "data".
5508 * Ideally if a pty has been setup there would be a way to interpret
5509 * the escape codes.
5510 */
5511 if (0 == strcmp(request_name, "subsystem")) {
5512 proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_subsystem_name_len, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000, &slen);
5513 offset += 4;
5514 const char* subsystem_name;
5515 proto_tree_add_item_ret_string(msg_type_tree, hf_ssh_subsystem_name, packet_tvb, offset, slen, ENC_UTF_80x00000002, pinfo->pool, (const uint8_t**)&subsystem_name);
5516 set_subdissector_for_channel(peer_data, recipient_channel, subsystem_name);
5517 offset += slen;
5518 } else if (0 == strcmp(request_name, "env")) {
5519 /* The encoding for "env" variables and "exec" commands is not
5520 * specified in the SSH protocol, and must match whatever the
5521 * server expects. (Unlike CHANNEL_DATA, it is not affected by
5522 * whatever is in "env" or anything else in the protocol, and the
5523 * strings are passed to execve directly.) In practice the strings
5524 * must not have internal NULs (no UTF-16), and OpenSSH for Windows
5525 * and IBM z/OS force the use of UTF-8 and ISO-8859-1, respectively.
5526 *
5527 * These will probably be ASCII-compatible.
5528 */
5529 proto_tree_add_item_ret_length(msg_type_tree, hf_ssh_env_name, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000 | ENC_UTF_80x00000002, &item_len);
5530 offset += item_len;
5531 proto_tree_add_item_ret_length(msg_type_tree, hf_ssh_env_value, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000 | ENC_UTF_80x00000002, &item_len);
5532 offset += item_len;
5533 } else if (0 == strcmp(request_name, "exec")) {
5534 proto_tree_add_item_ret_length(msg_type_tree, hf_ssh_exec_cmd, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000 | ENC_UTF_80x00000002, &item_len);
5535 offset += item_len;
5536 set_subdissector_for_channel(peer_data, recipient_channel, "exec");
5537 } else if (0 == strcmp(request_name, "exit-status")) {
5538 proto_tree_add_item(msg_type_tree, hf_ssh_exit_status, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
5539 offset += 4;
5540 } else if (0 == strcmp(request_name, "shell")) {
5541 set_subdissector_for_channel(peer_data, recipient_channel, "shell");
5542 } else if (0 == strcmp(request_name, "pty-req")) {
5543 proto_tree_add_item_ret_length(msg_type_tree, hf_ssh_pty_term, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000 | ENC_UTF_80x00000002, &item_len);
5544 offset += item_len;
5545 proto_tree_add_item(msg_type_tree, hf_ssh_pty_term_width_char, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
5546 offset += 4;
5547 proto_tree_add_item(msg_type_tree, hf_ssh_pty_term_height_row, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
5548 offset += 4;
5549 proto_tree_add_item(msg_type_tree, hf_ssh_pty_term_width_pixel, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
5550 offset += 4;
5551 proto_tree_add_item(msg_type_tree, hf_ssh_pty_term_height_pixel, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
5552 offset += 4;
5553 proto_tree_add_item_ret_uint(msg_type_tree, hf_ssh_pty_term_modes_len, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000, &slen);
5554 offset += 4;
5555 offset += ssh_dissect_term_modes(tvb_new_subset_length(packet_tvb, offset, slen), pinfo, msg_type_tree);
5556 }
5557 } else if (msg_code == SSH_MSG_CHANNEL_SUCCESS99) {
5558 proto_tree_add_item(msg_type_tree, hf_ssh_connection_recipient_channel, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
5559 offset += 4;
5560 }
5561 return offset;
5562}
5563
5564/* Channel mapping {{{ */
5565
5566/* The usual flow:
5567 * 1. client sends SSH_MSG_CHANNEL_OPEN with its (sender) channel number
5568 * 2. server responds with SSH_MSG_CHANNEL_OPEN_CONFIRMATION with
5569 * its channel number and echoing the client's number, creating
5570 * a bijective map
5571 * 3. client sends SSH_MSG_CHANNEL_REQUEST which has the name of
5572 * the shell, command, or subsystem to start. This has the recipient's
5573 * channel number (i.e. the server's)
5574 * 4. server may send back a SSG_MSG_CHANNEL_SUCCESS (or _FAILURE) with
5575 * the the recipient (i.e., client) channel number, but this does not
5576 * contain the subsystem name or anything identifying the request to
5577 * which it responds. It MUST be sent in the same order as the
5578 * corresponding request message (RFC 4254 4 Global Requests), so we
5579 * could track it that way, but for our purposes we just treat all
5580 * requests as successes. (If not, either there won't be data or another
5581 * request will supercede it later.)
5582 *
5583 * Either side can open a channel (RFC 4254 5 Channel Mechanism). The
5584 * typical flow is the client opening a channel, but in the case of
5585 * remote port forwarding (7 TCP/IP Port Forwarding) the directions are
5586 * swapped. For port forwarding, all the information is contained in the
5587 * SSH_MSG_CHANNEL_OPEN, there is no SSH_MSG_CHANNEL_REQUEST.
5588*
5589 * XXX: Channel numbers can be re-used after being closed (5.3 Closing a
5590 * Channel), but not necessarily mapped to the same channel number on the
5591 * other side. If that actually happens, the right way to handle this is
5592 * to track the state changes over time for random packet access (e.g.,
5593 * using a multimap with the packet number instead of maps.)
5594 */
5595
5596static struct ssh_peer_data*
5597get_other_peer_data(struct ssh_peer_data *peer_data)
5598{
5599 bool_Bool is_server = &peer_data->global_data->peer_data[SERVER_PEER_DATA1]==peer_data;
5600 if (is_server) {
5601 return &peer_data->global_data->peer_data[CLIENT_PEER_DATA0];
5602 } else {
5603 return &peer_data->global_data->peer_data[SERVER_PEER_DATA1];
5604 }
5605}
5606
5607/* Create pairings between a recipient channel and the sender's channel,
5608 * from a SSH_MSG_CHANNEL_OPEN_CONFIRMATION. */
5609static void
5610create_channel(struct ssh_peer_data *peer_data, uint32_t recipient_channel, uint32_t sender_channel)
5611{
5612 if (peer_data->channel_info == NULL((void*)0)) {
5613 peer_data->channel_info = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
5614 }
5615 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)));
5616
5617 if (peer_data->channel_handles == NULL((void*)0)) {
5618 peer_data->channel_handles = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
5619 }
5620
5621 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)))
;
5622 new_channel->multisegment_pdus = wmem_tree_new(wmem_file_scope());
5623 wmem_map_insert(peer_data->channel_handles, GUINT_TO_POINTER(recipient_channel)((gpointer) (gulong) (recipient_channel)), new_channel);
5624
5625 /* If the recipient channel is already configured in the other direction,
5626 * set the handle. We need this if we eventually handle port forwarding,
5627 * where all the information to handle the traffic is sent in the
5628 * SSH_MSG_CHANNEL_OPEN message before the CONFIRMATION. It might also
5629 * help if the packets are out of order (i.e. we get the client
5630 * CHANNEL_REQUEST before the CHANNEL_OPEN_CONFIRMATION.)
5631 */
5632 struct ssh_peer_data *other_peer_data = get_other_peer_data(peer_data);
5633 if (other_peer_data->channel_handles) {
5634 ssh_channel_info_t *peer_channel = wmem_map_lookup(other_peer_data->channel_handles, GUINT_TO_POINTER(sender_channel)((gpointer) (gulong) (sender_channel)));
5635 if (peer_channel) {
5636 new_channel->handle = peer_channel->handle;
5637 }
5638 }
5639}
5640
5641static ssh_channel_info_t*
5642get_channel_info_for_channel(struct ssh_peer_data *peer_data, uint32_t recipient_channel)
5643{
5644 if (peer_data->channel_handles == NULL((void*)0)) {
5645 return NULL((void*)0);
5646 }
5647 ssh_channel_info_t *channel = wmem_map_lookup(peer_data->channel_handles, GUINT_TO_POINTER(recipient_channel)((gpointer) (gulong) (recipient_channel)));
5648
5649 return channel;
5650}
5651
5652static void
5653set_subdissector_for_channel(struct ssh_peer_data *peer_data, uint32_t recipient_channel, const char* subsystem_name)
5654{
5655 dissector_handle_t handle = NULL((void*)0);
5656 if (0 == strcmp(subsystem_name, "sftp")) {
5657 handle = sftp_handle;
5658 } else if (0 == strcmp(subsystem_name, "shell") ||
5659 0 == strcmp(subsystem_name, "exec")) {
5660 handle = data_text_lines_handle;
5661 }
5662
5663 if (handle) {
5664 /* Map this handle to the recipient channel */
5665 ssh_channel_info_t *channel = NULL((void*)0);
5666 if (peer_data->channel_handles == NULL((void*)0)) {
5667 peer_data->channel_handles = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
5668 } else {
5669 channel = wmem_map_lookup(peer_data->channel_handles, GUINT_TO_POINTER(recipient_channel)((gpointer) (gulong) (recipient_channel)));
5670 }
5671 if (channel == NULL((void*)0)) {
5672 channel = wmem_new0(wmem_file_scope(), ssh_channel_info_t)((ssh_channel_info_t*)wmem_alloc0((wmem_file_scope()), sizeof
(ssh_channel_info_t)))
;
5673 channel->multisegment_pdus = wmem_tree_new(wmem_file_scope());
5674 wmem_map_insert(peer_data->channel_handles, GUINT_TO_POINTER(recipient_channel)((gpointer) (gulong) (recipient_channel)), channel);
5675 }
5676 channel->handle = handle;
5677
5678 /* This recipient channel is the sender channel for the other side.
5679 * Do we know what the recipient channel on the other side is? */
5680 struct ssh_peer_data *other_peer_data = get_other_peer_data(peer_data);
5681
5682 wmem_map_t *channel_info = other_peer_data->channel_info;
5683 if (channel_info) {
5684 void *sender_channel_p;
5685 if (wmem_map_lookup_extended(channel_info, GUINT_TO_POINTER(recipient_channel)((gpointer) (gulong) (recipient_channel)), NULL((void*)0), &sender_channel_p)) {
5686 uint32_t sender_channel = GPOINTER_TO_UINT(sender_channel_p)((guint) (gulong) (sender_channel_p));
5687 /* Yes. See the handle for the other side too. */
5688 if (other_peer_data->channel_handles == NULL((void*)0)) {
5689 other_peer_data->channel_handles = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
5690 channel = NULL((void*)0);
5691 } else {
5692 channel = wmem_map_lookup(other_peer_data->channel_handles, GUINT_TO_POINTER(sender_channel)((gpointer) (gulong) (sender_channel)));
5693 }
5694 if (channel == NULL((void*)0)) {
5695 channel = wmem_new0(wmem_file_scope(), ssh_channel_info_t)((ssh_channel_info_t*)wmem_alloc0((wmem_file_scope()), sizeof
(ssh_channel_info_t)))
;
5696 channel->multisegment_pdus = wmem_tree_new(wmem_file_scope());
5697 wmem_map_insert(other_peer_data->channel_handles, GUINT_TO_POINTER(sender_channel)((gpointer) (gulong) (sender_channel)), channel);
5698 }
5699 channel->handle = handle;
5700 }
5701 }
5702 }
5703}
5704
5705/* Channel mapping. }}} */
5706
5707static int
5708ssh_dissect_connection_generic(tvbuff_t *packet_tvb, packet_info *pinfo,
5709 int offset, proto_item *msg_type_tree, unsigned msg_code)
5710{
5711 (void)pinfo;
5712 if(msg_code==SSH_MSG_GLOBAL_REQUEST80){
5713 const char* request_name;
5714 unsigned slen;
5715 slen = tvb_get_ntohl(packet_tvb, offset) ;
5716 proto_tree_add_item(msg_type_tree, hf_ssh_global_request_name_len, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
5717 offset += 4;
5718 request_name = (char*)tvb_get_string_enc(pinfo->pool, packet_tvb, offset, slen, ENC_ASCII0x00000000|ENC_NA0x00000000);
5719 proto_tree_add_item(msg_type_tree, hf_ssh_global_request_name, packet_tvb, offset, slen, ENC_ASCII0x00000000);
5720 offset += slen;
5721 proto_tree_add_item(msg_type_tree, hf_ssh_global_request_want_reply, packet_tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
5722 offset += 1;
5723 if (0 == strcmp(request_name, "[email protected]") ||
5724 0 == strcmp(request_name, "[email protected]")) {
5725 while (tvb_reported_length_remaining(packet_tvb, offset)) {
5726 offset += ssh_tree_add_hostkey(packet_tvb, pinfo, offset, msg_type_tree,
5727 "Server host key", ett_key_exchange_host_key, NULL((void*)0));
5728 }
5729 }
5730 }
5731 return offset;
5732}
5733
5734static int
5735ssh_dissect_local_extension(tvbuff_t *packet_tvb, packet_info *pinfo,
5736 int offset, struct ssh_peer_data *peer_data, proto_item *msg_type_tree, unsigned msg_code) {
5737 unsigned slen;
5738 if (peer_data->global_data->ext_ping_openssh_offered && msg_code >= SSH_MSG_PING192 && msg_code <= SSH_MSG_PONG193) {
5739 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)"));
5740 proto_tree_add_item(msg_type_tree, hf_ssh2_ext_ping_msg_code, packet_tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
5741 offset += 1;
5742 if (msg_code == SSH_MSG_PING192) {
5743 slen = tvb_get_ntohl(packet_tvb, offset) ;
5744 proto_tree_add_item(msg_type_tree, hf_ssh_ping_data_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
5745 offset += 4;
5746 proto_tree_add_item(msg_type_tree, hf_ssh_ping_data, packet_tvb, offset, slen, ENC_NA0x00000000);
5747 offset += slen;
5748 } else if (msg_code == SSH_MSG_PONG193) {
5749 slen = tvb_get_ntohl(packet_tvb, offset) ;
5750 proto_tree_add_item(msg_type_tree, hf_ssh_pong_data_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
5751 offset += 4;
5752 proto_tree_add_item(msg_type_tree, hf_ssh_pong_data, packet_tvb, offset, slen, ENC_NA0x00000000);
5753 offset += slen;
5754 }
5755 } else {
5756 col_append_sep_str(pinfo->cinfo, COL_INFO, NULL((void*)0), val_to_str(pinfo->pool, msg_code, ssh2_msg_vals, "Unknown (%u)"));
5757 proto_tree_add_item(msg_type_tree, hf_ssh2_msg_code, packet_tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
5758 offset += 1;
5759 }
5760 return offset;
5761}
5762
5763static int
5764ssh_dissect_public_key_blob(tvbuff_t *tvb, packet_info *pinfo, proto_item *tree)
5765{
5766 uint32_t slen;
5767 const char* key_type;
5768
5769 int offset = 0;
5770 proto_tree *blob_tree = NULL((void*)0);
5771 proto_item *blob_item = NULL((void*)0);
5772
5773 blob_item = proto_tree_add_item(tree, hf_ssh_blob, tvb, offset, tvb_reported_length(tvb), ENC_NA0x00000000);
5774 blob_tree = proto_item_add_subtree(blob_item, ett_userauth_pk_blob);
5775 proto_tree_add_item_ret_uint(blob_tree, hf_ssh_pk_blob_name_length, tvb, offset, 4, ENC_BIG_ENDIAN0x00000000, &slen);
5776 offset += 4;
5777 proto_tree_add_item_ret_string(blob_tree, hf_ssh_pk_blob_name, tvb, offset, slen, ENC_ASCII0x00000000, pinfo->pool, (const uint8_t**)&key_type);
5778 proto_item_append_text(blob_item, " (type: %s)", key_type);
5779 offset += slen;
5780
5781 if (0 == strcmp(key_type, "ssh-rsa")) {
5782 offset += ssh_tree_add_mpint(tvb, offset, blob_tree, hf_ssh_blob_e);
5783 offset += ssh_tree_add_mpint(tvb, offset, blob_tree, hf_ssh_blob_n);
5784 } else if (0 == strcmp(key_type, "ssh-dss")) {
5785 offset += ssh_tree_add_mpint(tvb, offset, blob_tree, hf_ssh_blob_dsa_p);
5786 offset += ssh_tree_add_mpint(tvb, offset, blob_tree, hf_ssh_blob_dsa_q);
5787 offset += ssh_tree_add_mpint(tvb, offset, blob_tree, hf_ssh_blob_dsa_g);
5788 offset += ssh_tree_add_mpint(tvb, offset, blob_tree, hf_ssh_blob_dsa_y);
5789 } 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-"
) )
) {
5790 offset += ssh_tree_add_string(tvb, offset, blob_tree,
5791 hf_ssh_blob_ecdsa_curve_id, hf_ssh_blob_ecdsa_curve_id_length);
5792 offset += ssh_tree_add_string(tvb, offset, blob_tree,
5793 hf_ssh_blob_ecdsa_q, hf_ssh_blob_ecdsa_q_length);
5794 } 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") )
) {
5795 offset += ssh_tree_add_string(tvb, offset, blob_tree,
5796 hf_ssh_blob_eddsa_key, hf_ssh_blob_eddsa_key_length);
5797 } else {
5798 proto_tree_add_item(blob_tree, hf_ssh_blob_data, tvb, offset, tvb_reported_length_remaining(tvb, offset), ENC_NA0x00000000);
5799 offset += tvb_reported_length_remaining(tvb, offset);
5800 }
5801
5802 return offset;
5803}
5804
5805static int
5806ssh_dissect_public_key_signature(tvbuff_t *packet_tvb, packet_info *pinfo,
5807 int offset, proto_item *msg_type_tree)
5808{
5809 (void)pinfo;
5810 unsigned slen;
5811 slen = tvb_get_ntohl(packet_tvb, offset) ;
5812 proto_tree_add_item(msg_type_tree, hf_ssh_pk_sig_blob_name_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
5813 offset += 4;
5814 proto_tree_add_item(msg_type_tree, hf_ssh_pk_sig_blob_name, packet_tvb, offset, slen, ENC_ASCII0x00000000);
5815 offset += slen;
5816 slen = tvb_get_ntohl(packet_tvb, offset) ;
5817 proto_tree_add_item(msg_type_tree, hf_ssh_pk_sig_s_length, packet_tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
5818 offset += 4;
5819 proto_tree_add_item(msg_type_tree, hf_ssh_pk_sig_s, packet_tvb, offset, slen, ENC_NA0x00000000);
5820 offset += slen;
5821 return offset;
5822}
5823
5824#ifdef SSH_DECRYPT_DEBUG /* {{{ */
5825
5826static FILE* ssh_debug_file;
5827
5828static void
5829ssh_prefs_apply_cb(void)
5830{
5831 ssh_set_debug(ssh_debug_file_name);
5832}
5833
5834static void
5835ssh_set_debug(const char* name)
5836{
5837 static int debug_file_must_be_closed;
5838 int use_stderr;
5839
5840 use_stderr = name?(strcmp(name, SSH_DEBUG_USE_STDERR"-") == 0):0;
5841
5842 if (debug_file_must_be_closed)
5843 fclose(ssh_debug_file);
5844
5845 if (use_stderr)
5846 ssh_debug_file = stderrstderr;
5847 else if (!name || (strcmp(name, "") ==0))
5848 ssh_debug_file = NULL((void*)0);
5849 else
5850 ssh_debug_file = ws_fopenfopen(name, "w");
5851
5852 if (!use_stderr && ssh_debug_file)
5853 debug_file_must_be_closed = 1;
5854 else
5855 debug_file_must_be_closed = 0;
5856
5857 ssh_debug_printf("Wireshark SSH debug log \n\n");
5858#ifdef HAVE_LIBGNUTLS1
5859 ssh_debug_printf("GnuTLS version: %s\n", gnutls_check_version(NULL((void*)0)));
5860#endif
5861 ssh_debug_printf("Libgcrypt version: %s\n", gcry_check_version(NULL((void*)0)));
5862 ssh_debug_printf("\n");
5863}
5864
5865static void
5866ssh_debug_flush(void)
5867{
5868 if (ssh_debug_file)
5869 fflush(ssh_debug_file);
5870}
5871
5872static void
5873ssh_debug_printf(const char* fmt, ...)
5874{
5875 va_list ap;
5876
5877 if (!ssh_debug_file)
5878 return;
5879
5880 va_start(ap, fmt)__builtin_va_start(ap, fmt);
5881 vfprintf(ssh_debug_file, fmt, ap);
5882 va_end(ap)__builtin_va_end(ap);
5883}
5884
5885static void
5886ssh_print_data(const char* name, const unsigned char* data, size_t len)
5887{
5888 size_t i, j, k;
5889 if (!ssh_debug_file)
5890 return;
5891#ifdef OPENSSH_STYLE
5892 fprintf(ssh_debug_file,"%s[%d]\n",name, (int) len);
5893#else
5894 fprintf(ssh_debug_file,"%s[%d]:\n",name, (int) len);
5895#endif
5896 for (i=0; i<len; i+=16) {
5897#ifdef OPENSSH_STYLE
5898 fprintf(ssh_debug_file,"%04u: ", (unsigned int)i);
5899#else
5900 fprintf(ssh_debug_file,"| ");
5901#endif
5902 for (j=i, k=0; k<16 && j<len; ++j, ++k)
5903 fprintf(ssh_debug_file,"%.2x ",data[j]);
5904 for (; k<16; ++k)
5905 fprintf(ssh_debug_file," ");
5906#ifdef OPENSSH_STYLE
5907 fputc(' ', ssh_debug_file);
5908#else
5909 fputc('|', ssh_debug_file);
5910#endif
5911 for (j=i, k=0; k<16 && j<len; ++j, ++k) {
5912 unsigned char c = data[j];
5913 if (!g_ascii_isprint(c)((g_ascii_table[(guchar) (c)] & G_ASCII_PRINT) != 0) || (c=='\t')) c = '.';
5914 fputc(c, ssh_debug_file);
5915 }
5916#ifdef OPENSSH_STYLE
5917 fprintf(ssh_debug_file,"\n");
5918#else
5919 for (; k<16; ++k)
5920 fputc(' ', ssh_debug_file);
5921 fprintf(ssh_debug_file,"|\n");
5922#endif
5923 }
5924}
5925
5926#endif /* SSH_DECRYPT_DEBUG }}} */
5927
5928static void
5929ssh_secrets_block_callback(const void *secrets, unsigned size)
5930{
5931 ssh_keylog_process_lines((const uint8_t *)secrets, size);
5932}
5933
5934/* Functions for SSH random hashtables. {{{ */
5935static int
5936ssh_equal (const void *v, const void *v2)
5937{
5938 if (v == NULL((void*)0) || v2 == NULL((void*)0)) {
5939 return 0;
5940 }
5941
5942 const ssh_bignum *val1;
5943 const ssh_bignum *val2;
5944 val1 = (const ssh_bignum *)v;
5945 val2 = (const ssh_bignum *)v2;
5946
5947 if (val1->length == val2->length &&
5948 !memcmp(val1->data, val2->data, val2->length)) {
5949 return 1;
5950 }
5951 return 0;
5952}
5953
5954static unsigned
5955ssh_hash (const void *v)
5956{
5957 unsigned l,hash;
5958 const ssh_bignum* id;
5959 const unsigned* cur;
5960
5961 if (v == NULL((void*)0)) {
5962 return 0;
5963 }
5964
5965 hash = 0;
5966 id = (const ssh_bignum*) v;
5967
5968 /* id and id->data are mallocated in ssh_save_master_key(). As such 'data'
5969 * should be aligned for any kind of access (for example as a unsigned as
5970 * is done below). The intermediate void* cast is to prevent "cast
5971 * increases required alignment of target type" warnings on CPUs (such
5972 * as SPARCs) that do not allow misaligned memory accesses.
5973 */
5974 cur = (const unsigned*)(void*) id->data;
5975
5976 for (l=4; (l < id->length); l+=4, cur++)
5977 hash = hash ^ (*cur);
5978
5979 return hash;
5980}
5981
5982static void
5983ssh_free_glib_allocated_bignum(void *data)
5984{
5985 ssh_bignum * bignum;
5986 if (data == NULL((void*)0)) {
5987 return;
5988 }
5989
5990 bignum = (ssh_bignum *) data;
5991 g_free(bignum->data);
5992 g_free(bignum);
5993}
5994
5995static void
5996ssh_free_glib_allocated_entry(void *data)
5997{
5998 ssh_key_map_entry_t * entry;
5999 if (data == NULL((void*)0)) {
6000 return;
6001 }
6002
6003 entry = (ssh_key_map_entry_t *) data;
6004 g_free(entry->type);
6005 ssh_free_glib_allocated_bignum(entry->key_material);
6006 g_free(entry);
6007}
6008/* Functions for SSH random hashtables. }}} */
6009
6010static void
6011ssh_shutdown(void) {
6012 g_hash_table_destroy(ssh_master_key_map);
6013}
6014
6015void
6016proto_register_ssh(void)
6017{
6018 static hf_register_info hf[] = {
6019 { &hf_ssh_protocol,
6020 { "Protocol", "ssh.protocol",
6021 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6022 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6023
6024 { &hf_ssh_packet_length,
6025 { "Packet Length", "ssh.packet_length",
6026 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6027 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6028
6029 { &hf_ssh_packet_length_encrypted,
6030 { "Packet Length (encrypted)", "ssh.packet_length_encrypted",
6031 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6032 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6033
6034 { &hf_ssh_padding_length,
6035 { "Padding Length", "ssh.padding_length",
6036 FT_UINT8, BASE_DEC, NULL((void*)0), 0x0,
6037 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6038
6039 { &hf_ssh_payload,
6040 { "Payload", "ssh.payload",
6041 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6042 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6043
6044 { &hf_ssh_encrypted_packet,
6045 { "Encrypted Packet", "ssh.encrypted_packet",
6046 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6047 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6048
6049 { &hf_ssh_padding_string,
6050 { "Padding String", "ssh.padding_string",
6051 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6052 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6053
6054 { &hf_ssh_seq_num,
6055 { "Sequence number", "ssh.seq_num",
6056 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6057 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6058
6059 { &hf_ssh_mac_string,
6060 { "MAC", "ssh.mac",
6061 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6062 "Message authentication code", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6063
6064 { &hf_ssh_mac_status,
6065 { "MAC Status", "ssh.mac.status", FT_UINT8, BASE_NONE, VALS(proto_checksum_vals)((0 ? (const struct _value_string*)0 : ((proto_checksum_vals)
)))
, 0x0,
6066 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6067
6068 { &hf_ssh_direction,
6069 { "Direction", "ssh.direction",
6070 FT_BOOLEAN, BASE_NONE, TFS(&tfs_s2c_c2s)((0 ? (const struct true_false_string*)0 : ((&tfs_s2c_c2s
))))
, 0x0,
6071 "Message direction", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6072
6073 { &hf_ssh_msg_code,
6074 { "Message Code", "ssh.message_code",
6075 FT_UINT8, BASE_DEC, VALS(ssh1_msg_vals)((0 ? (const struct _value_string*)0 : ((ssh1_msg_vals)))), 0x0,
6076 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6077
6078 { &hf_ssh2_msg_code,
6079 { "Message Code", "ssh.message_code",
6080 FT_UINT8, BASE_DEC, VALS(ssh2_msg_vals)((0 ? (const struct _value_string*)0 : ((ssh2_msg_vals)))), 0x0,
6081 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6082
6083 { &hf_ssh2_kex_dh_msg_code,
6084 { "Message Code", "ssh.message_code",
6085 FT_UINT8, BASE_DEC, VALS(ssh2_kex_dh_msg_vals)((0 ? (const struct _value_string*)0 : ((ssh2_kex_dh_msg_vals
))))
, 0x0,
6086 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6087
6088 { &hf_ssh2_kex_dh_gex_msg_code,
6089 { "Message Code", "ssh.message_code",
6090 FT_UINT8, BASE_DEC, VALS(ssh2_kex_dh_gex_msg_vals)((0 ? (const struct _value_string*)0 : ((ssh2_kex_dh_gex_msg_vals
))))
, 0x0,
6091 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6092
6093 { &hf_ssh2_kex_ecdh_msg_code,
6094 { "Message Code", "ssh.message_code",
6095 FT_UINT8, BASE_DEC, VALS(ssh2_kex_ecdh_msg_vals)((0 ? (const struct _value_string*)0 : ((ssh2_kex_ecdh_msg_vals
))))
, 0x0,
6096 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6097
6098 { &hf_ssh2_kex_hybrid_msg_code,
6099 { "Message Code", "ssh.message_code",
6100 FT_UINT8, BASE_DEC, VALS(ssh2_kex_hybrid_msg_vals)((0 ? (const struct _value_string*)0 : ((ssh2_kex_hybrid_msg_vals
))))
, 0x0,
6101 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6102
6103 { &hf_ssh2_ext_ping_msg_code,
6104 { "Message Code", "ssh.message_code",
6105 FT_UINT8, BASE_DEC, VALS(ssh2_ext_ping_msg_vals)((0 ? (const struct _value_string*)0 : ((ssh2_ext_ping_msg_vals
))))
, 0x0,
6106 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6107
6108 { &hf_ssh_cookie,
6109 { "Cookie", "ssh.cookie",
6110 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6111 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6112
6113 { &hf_ssh_kex_algorithms,
6114 { "kex_algorithms string", "ssh.kex_algorithms",
6115 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6116 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6117
6118 { &hf_ssh_server_host_key_algorithms,
6119 { "server_host_key_algorithms string", "ssh.server_host_key_algorithms",
6120 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6121 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6122
6123 { &hf_ssh_encryption_algorithms_client_to_server,
6124 { "encryption_algorithms_client_to_server string", "ssh.encryption_algorithms_client_to_server",
6125 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6126 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6127
6128 { &hf_ssh_encryption_algorithms_server_to_client,
6129 { "encryption_algorithms_server_to_client string", "ssh.encryption_algorithms_server_to_client",
6130 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6131 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6132
6133 { &hf_ssh_mac_algorithms_client_to_server,
6134 { "mac_algorithms_client_to_server string", "ssh.mac_algorithms_client_to_server",
6135 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6136 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6137
6138 { &hf_ssh_mac_algorithms_server_to_client,
6139 { "mac_algorithms_server_to_client string", "ssh.mac_algorithms_server_to_client",
6140 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6141 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6142
6143 { &hf_ssh_compression_algorithms_client_to_server,
6144 { "compression_algorithms_client_to_server string", "ssh.compression_algorithms_client_to_server",
6145 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6146 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6147
6148 { &hf_ssh_compression_algorithms_server_to_client,
6149 { "compression_algorithms_server_to_client string", "ssh.compression_algorithms_server_to_client",
6150 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6151 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6152
6153 { &hf_ssh_languages_client_to_server,
6154 { "languages_client_to_server string", "ssh.languages_client_to_server",
6155 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6156 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6157
6158 { &hf_ssh_languages_server_to_client,
6159 { "languages_server_to_client string", "ssh.languages_server_to_client",
6160 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6161 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6162
6163 { &hf_ssh_kex_algorithms_length,
6164 { "kex_algorithms length", "ssh.kex_algorithms_length",
6165 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6166 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6167
6168 { &hf_ssh_server_host_key_algorithms_length,
6169 { "server_host_key_algorithms length", "ssh.server_host_key_algorithms_length",
6170 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6171 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6172
6173 { &hf_ssh_encryption_algorithms_client_to_server_length,
6174 { "encryption_algorithms_client_to_server length", "ssh.encryption_algorithms_client_to_server_length",
6175 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6176 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6177
6178 { &hf_ssh_encryption_algorithms_server_to_client_length,
6179 { "encryption_algorithms_server_to_client length", "ssh.encryption_algorithms_server_to_client_length",
6180 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6181 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6182
6183 { &hf_ssh_mac_algorithms_client_to_server_length,
6184 { "mac_algorithms_client_to_server length", "ssh.mac_algorithms_client_to_server_length",
6185 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6186 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6187
6188 { &hf_ssh_mac_algorithms_server_to_client_length,
6189 { "mac_algorithms_server_to_client length", "ssh.mac_algorithms_server_to_client_length",
6190 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6191 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6192
6193 { &hf_ssh_compression_algorithms_client_to_server_length,
6194 { "compression_algorithms_client_to_server length", "ssh.compression_algorithms_client_to_server_length",
6195 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6196 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6197
6198 { &hf_ssh_compression_algorithms_server_to_client_length,
6199 { "compression_algorithms_server_to_client length", "ssh.compression_algorithms_server_to_client_length",
6200 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6201 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6202
6203 { &hf_ssh_languages_client_to_server_length,
6204 { "languages_client_to_server length", "ssh.languages_client_to_server_length",
6205 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6206 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6207
6208 { &hf_ssh_languages_server_to_client_length,
6209 { "languages_server_to_client length", "ssh.languages_server_to_client_length",
6210 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6211 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6212
6213 { &hf_ssh_first_kex_packet_follows,
6214 { "First KEX Packet Follows", "ssh.first_kex_packet_follows",
6215 FT_UINT8, BASE_DEC, NULL((void*)0), 0x0,
6216 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6217
6218 { &hf_ssh_kex_reserved,
6219 { "Reserved", "ssh.kex.reserved",
6220 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6221 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6222
6223 { &hf_ssh_kex_hassh_algo,
6224 { "hasshAlgorithms", "ssh.kex.hassh_algorithms",
6225 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6226 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6227
6228 { &hf_ssh_kex_hassh,
6229 { "hassh", "ssh.kex.hassh",
6230 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6231 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6232
6233 { &hf_ssh_kex_hasshserver_algo,
6234 { "hasshServerAlgorithms", "ssh.kex.hasshserver_algorithms",
6235 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6236 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6237
6238 { &hf_ssh_kex_hasshserver,
6239 { "hasshServer", "ssh.kex.hasshserver",
6240 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6241 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6242
6243 { &hf_ssh_hostkey_length,
6244 { "Host key length", "ssh.host_key.length",
6245 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6246 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6247
6248 { &hf_ssh_hostkey_type_length,
6249 { "Host key type length", "ssh.host_key.type_length",
6250 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6251 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6252
6253 { &hf_ssh_hostkey_type,
6254 { "Host key type", "ssh.host_key.type",
6255 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6256 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6257
6258 { &hf_ssh_hostkey_data,
6259 { "Host key data", "ssh.host_key.data",
6260 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6261 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6262
6263 { &hf_ssh_hostkey_rsa_n,
6264 { "RSA modulus (N)", "ssh.host_key.rsa.n",
6265 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6266 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6267
6268 { &hf_ssh_hostkey_rsa_e,
6269 { "RSA public exponent (e)", "ssh.host_key.rsa.e",
6270 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6271 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6272
6273 { &hf_ssh_hostkey_dsa_p,
6274 { "DSA prime modulus (p)", "ssh.host_key.dsa.p",
6275 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6276 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6277
6278 { &hf_ssh_hostkey_dsa_q,
6279 { "DSA prime divisor (q)", "ssh.host_key.dsa.q",
6280 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6281 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6282
6283 { &hf_ssh_hostkey_dsa_g,
6284 { "DSA subgroup generator (g)", "ssh.host_key.dsa.g",
6285 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6286 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6287
6288 { &hf_ssh_hostkey_dsa_y,
6289 { "DSA public key (y)", "ssh.host_key.dsa.y",
6290 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6291 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6292
6293 { &hf_ssh_hostkey_ecdsa_curve_id,
6294 { "ECDSA elliptic curve identifier", "ssh.host_key.ecdsa.id",
6295 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6296 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6297
6298 { &hf_ssh_hostkey_ecdsa_curve_id_length,
6299 { "ECDSA elliptic curve identifier length", "ssh.host_key.ecdsa.id_length",
6300 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6301 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6302
6303 { &hf_ssh_hostkey_ecdsa_q,
6304 { "ECDSA public key (Q)", "ssh.host_key.ecdsa.q",
6305 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6306 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6307
6308 { &hf_ssh_hostkey_ecdsa_q_length,
6309 { "ECDSA public key length", "ssh.host_key.ecdsa.q_length",
6310 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6311 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6312
6313 { &hf_ssh_hostkey_eddsa_key,
6314 { "EdDSA public key", "ssh.host_key.eddsa.key",
6315 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6316 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6317
6318 { &hf_ssh_hostkey_eddsa_key_length,
6319 { "EdDSA public key length", "ssh.host_key.eddsa.key_length",
6320 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6321 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6322
6323 { &hf_ssh_hostsig_length,
6324 { "Host signature length", "ssh.host_sig.length",
6325 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6326 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6327
6328 { &hf_ssh_hostsig_type_length,
6329 { "Host signature type length", "ssh.host_sig.type_length",
6330 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6331 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6332
6333 { &hf_ssh_hostsig_type,
6334 { "Host signature type", "ssh.host_sig.type",
6335 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6336 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6337
6338 { &hf_ssh_hostsig_data,
6339 { "Host signature data", "ssh.host_sig.data",
6340 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6341 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6342
6343 { &hf_ssh_hostsig_rsa,
6344 { "RSA signature", "ssh.host_sig.rsa",
6345 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6346 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6347
6348 { &hf_ssh_hostsig_dsa,
6349 { "DSA signature", "ssh.host_sig.dsa",
6350 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6351 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6352
6353 { &hf_ssh_dh_e,
6354 { "DH client e", "ssh.dh.e",
6355 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6356 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6357
6358 { &hf_ssh_dh_f,
6359 { "DH server f", "ssh.dh.f",
6360 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6361 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6362
6363 { &hf_ssh_dh_gex_min,
6364 { "DH GEX Min", "ssh.dh_gex.min",
6365 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6366 "Minimal acceptable group size", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6367
6368 { &hf_ssh_dh_gex_nbits,
6369 { "DH GEX Number of Bits", "ssh.dh_gex.nbits",
6370 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6371 "Preferred group size", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6372
6373 { &hf_ssh_dh_gex_max,
6374 { "DH GEX Max", "ssh.dh_gex.max",
6375 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6376 "Maximal acceptable group size", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6377
6378 { &hf_ssh_dh_gex_p,
6379 { "DH GEX modulus (P)", "ssh.dh_gex.p",
6380 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6381 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6382
6383 { &hf_ssh_dh_gex_g,
6384 { "DH GEX base (G)", "ssh.dh_gex.g",
6385 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6386 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6387
6388 { &hf_ssh_ecdh_q_c,
6389 { "ECDH client's ephemeral public key (Q_C)", "ssh.ecdh.q_c",
6390 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6391 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6392
6393 { &hf_ssh_ecdh_q_c_length,
6394 { "ECDH client's ephemeral public key length", "ssh.ecdh.q_c_length",
6395 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6396 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6397
6398 { &hf_ssh_ecdh_q_s,
6399 { "ECDH server's ephemeral public key (Q_S)", "ssh.ecdh.q_s",
6400 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6401 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6402
6403 { &hf_ssh_ecdh_q_s_length,
6404 { "ECDH server's ephemeral public key length", "ssh.ecdh.q_s_length",
6405 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6406 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6407
6408 { &hf_ssh_mpint_length,
6409 { "Multi Precision Integer Length", "ssh.mpint_length",
6410 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6411 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6412
6413 { &hf_ssh_ignore_data_length,
6414 { "Debug message length", "ssh.ignore_data_length",
6415 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6416 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6417
6418 { &hf_ssh_ignore_data,
6419 { "Ignore data", "ssh.ignore_data",
6420 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6421 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6422
6423 { &hf_ssh_debug_always_display,
6424 { "Always Display", "ssh.debug_always_display",
6425 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
6426 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6427
6428 { &hf_ssh_debug_message_length,
6429 { "Debug message length", "ssh.debug_name_length",
6430 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6431 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6432
6433 { &hf_ssh_debug_message,
6434 { "Debug message", "ssh.debug_name",
6435 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6436 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6437
6438 { &hf_ssh_service_name_length,
6439 { "Service Name length", "ssh.service_name_length",
6440 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6441 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6442
6443 { &hf_ssh_service_name,
6444 { "Service Name", "ssh.service_name",
6445 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6446 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6447
6448 { &hf_ssh_disconnect_reason,
6449 { "Disconnect reason", "ssh.disconnect_reason",
6450 FT_UINT32, BASE_HEX, NULL((void*)0), 0x0,
6451 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6452
6453 { &hf_ssh_disconnect_description_length,
6454 { "Disconnect description length", "ssh.disconnect_description_length",
6455 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6456 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6457
6458 { &hf_ssh_disconnect_description,
6459 { "Disconnect description", "ssh.disconnect_description",
6460 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6461 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6462
6463 { &hf_ssh_ext_count,
6464 { "Extension count", "ssh.extension.count",
6465 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6466 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6467
6468 { &hf_ssh_ext_name_length,
6469 { "Extension name length", "ssh.extension.name_length",
6470 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6471 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6472
6473 { &hf_ssh_ext_name,
6474 { "Extension name", "ssh.extension.name",
6475 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6476 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6477
6478 { &hf_ssh_ext_value_length,
6479 { "Extension value length", "ssh.extension.value_length",
6480 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6481 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6482
6483 { &hf_ssh_ext_value,
6484 { "Extension value", "ssh.extension.value",
6485 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6486 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6487
6488 { &hf_ssh_ext_server_sig_algs_algorithms,
6489 { "Accepted signature algorithms", "ssh.extension.server_sig_algs.algorithms",
6490 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6491 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6492
6493 { &hf_ssh_ext_delay_compression_algorithms_client_to_server_length,
6494 { "Compression algorithms (client to server) length", "ssh.extension.delay_compression.compression_algorithms_client_to_server_length",
6495 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6496 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6497
6498 { &hf_ssh_ext_delay_compression_algorithms_client_to_server,
6499 { "Compression algorithms (client to server)", "ssh.extension.delay_compression.compression_algorithms_client_to_server",
6500 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6501 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6502
6503 { &hf_ssh_ext_delay_compression_algorithms_server_to_client_length,
6504 { "Compression algorithms (server to client) length", "ssh.extension.delay_compression.compression_algorithms_server_to_client_length",
6505 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6506 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6507
6508 { &hf_ssh_ext_delay_compression_algorithms_server_to_client,
6509 { "Compression algorithms (server to client)", "ssh.extension.delay_compression.compression_algorithms_server_to_client",
6510 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6511 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6512
6513 { &hf_ssh_ext_no_flow_control_value,
6514 { "No flow control flag", "ssh.extension.no_flow_control.value",
6515 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6516 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6517
6518 { &hf_ssh_ext_elevation_value,
6519 { "Elevation flag", "ssh.extension.elevation.value",
6520 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6521 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6522
6523 { &hf_ssh_ext_prop_publickey_algorithms_algorithms,
6524 { "Public key algorithms", "ssh.extension.prop_publickey_algorithms.algorithms",
6525 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6526 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6527
6528 { &hf_ssh_lang_tag_length,
6529 { "Language tag length", "ssh.lang_tag_length",
6530 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6531 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6532
6533 { &hf_ssh_lang_tag,
6534 { "Language tag", "ssh.lang_tag",
6535 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6536 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6537
6538 { &hf_ssh_ping_data_length,
6539 { "Data length", "ssh.ping_data_length",
6540 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6541 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6542
6543 { &hf_ssh_ping_data,
6544 { "Data", "ssh.ping_data",
6545 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6546 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6547
6548 { &hf_ssh_pong_data_length,
6549 { "Data length", "ssh.pong_data_length",
6550 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6551 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6552
6553 { &hf_ssh_pong_data,
6554 { "Data", "ssh.pong_data",
6555 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6556 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6557
6558
6559 { &hf_ssh_userauth_user_name_length,
6560 { "User Name length", "ssh.userauth_user_name_length",
6561 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6562 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6563
6564 { &hf_ssh_userauth_user_name,
6565 { "User Name", "ssh.userauth_user_name",
6566 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6567 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6568
6569 { &hf_ssh_userauth_change_password,
6570 { "Change password", "ssh.userauth.change_password",
6571 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
6572 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6573
6574 { &hf_ssh_userauth_service_name_length,
6575 { "Service Name length", "ssh.userauth_service_name_length",
6576 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6577 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6578
6579 { &hf_ssh_userauth_service_name,
6580 { "Service Name", "ssh.userauth_service_name",
6581 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6582 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6583
6584 { &hf_ssh_userauth_method_name_length,
6585 { "Method Name length", "ssh.userauth_method_name_length",
6586 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6587 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6588
6589 { &hf_ssh_userauth_method_name,
6590 { "Method Name", "ssh.userauth_method_name",
6591 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6592 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6593
6594 { &hf_ssh_userauth_have_signature,
6595 { "Have signature", "ssh.userauth.have_signature",
6596 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
6597 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6598
6599 { &hf_ssh_userauth_password_length,
6600 { "Password length", "ssh.userauth_password_length",
6601 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6602 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6603
6604 { &hf_ssh_userauth_password,
6605 { "Password", "ssh.userauth_password",
6606 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6607 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6608
6609 { &hf_ssh_userauth_new_password_length,
6610 { "New password length", "ssh.userauth_new_password_length",
6611 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6612 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6613
6614 { &hf_ssh_userauth_new_password,
6615 { "New password", "ssh.userauth_new_password",
6616 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6617 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6618
6619 { &hf_ssh_auth_failure_list_length,
6620 { "Authentications that can continue list len", "ssh.auth_failure_cont_list_length",
6621 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6622 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6623
6624 { &hf_ssh_auth_failure_list,
6625 { "Authentications that can continue list", "ssh.auth_failure_cont_list",
6626 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6627 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6628
6629 { &hf_ssh_userauth_partial_success,
6630 { "Partial success", "ssh.userauth.partial_success",
6631 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
6632 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6633
6634 { &hf_ssh_userauth_pka_name_len,
6635 { "Public key algorithm name length", "ssh.userauth_pka_name_length",
6636 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6637 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6638
6639 { &hf_ssh_userauth_pka_name,
6640 { "Public key algorithm name", "ssh.userauth_pka_name",
6641 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6642 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6643
6644 { &hf_ssh_pk_blob_name_length,
6645 { "Public key blob algorithm name length", "ssh.pk_blob_name_length",
6646 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6647 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6648
6649 { &hf_ssh_pk_blob_name,
6650 { "Public key blob algorithm name", "ssh.pk_blob_name",
6651 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6652 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6653
6654 { &hf_ssh_blob_length,
6655 { "Public key blob length", "ssh.pk_blob_length",
6656 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6657 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6658
6659 { &hf_ssh_blob,
6660 { "Public key blob", "ssh.pk_blob",
6661 FT_NONE, BASE_NONE, NULL((void*)0), 0x0,
6662 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6663
6664 { &hf_ssh_blob_e,
6665 { "ssh-rsa public exponent (e)", "ssh.pk_blob.ssh-rsa.e",
6666 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6667 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6668
6669 { &hf_ssh_blob_n,
6670 { "ssh-rsa modulus (n)", "ssh.pk_blob.ssh-rsa.n",
6671 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6672 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6673
6674 { &hf_ssh_blob_dsa_p,
6675 { "DSA prime modulus (p)", "ssh.pk_blob.dsa.p",
6676 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6677 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6678
6679 { &hf_ssh_blob_dsa_q,
6680 { "DSA prime divisor (q)", "ssh.pk_blob.dsa.q",
6681 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6682 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6683
6684 { &hf_ssh_blob_dsa_g,
6685 { "DSA subgroup generator (g)", "ssh.pk_blob.dsa.g",
6686 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6687 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6688
6689 { &hf_ssh_blob_dsa_y,
6690 { "DSA public key (y)", "ssh.pk_blob.dsa.y",
6691 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6692 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6693
6694 { &hf_ssh_blob_ecdsa_curve_id,
6695 { "ECDSA elliptic curve identifier", "ssh.pk_blob.ecdsa.id",
6696 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6697 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6698
6699 { &hf_ssh_blob_ecdsa_curve_id_length,
6700 { "ECDSA elliptic curve identifier length", "ssh.pk_blob.ecdsa.id_length",
6701 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6702 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6703
6704 { &hf_ssh_blob_ecdsa_q,
6705 { "ECDSA public key (Q)", "ssh.pk_blob.ecdsa.q",
6706 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6707 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6708
6709 { &hf_ssh_blob_ecdsa_q_length,
6710 { "ECDSA public key length", "ssh.pk_blob.ecdsa.q_length",
6711 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6712 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6713
6714 { &hf_ssh_blob_eddsa_key,
6715 { "EdDSA public key", "ssh.pk_blob.eddsa.key",
6716 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6717 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6718
6719 { &hf_ssh_blob_eddsa_key_length,
6720 { "EdDSA public key length", "ssh.pk_blob.eddsa.key_length",
6721 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6722 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6723
6724 { &hf_ssh_blob_data,
6725 { "Public key blob data", "ssh.pk_blob.data",
6726 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6727 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6728
6729 { &hf_ssh_signature_length,
6730 { "Public key signature blob length", "ssh.pk_sig_blob_length",
6731 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6732 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6733
6734 { &hf_ssh_pk_sig_blob_name_length,
6735 { "Public key signature blob algorithm name length", "ssh.pk_sig_blob_name_length",
6736 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6737 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6738
6739 { &hf_ssh_pk_sig_blob_name,
6740 { "Public key signature blob algorithm name", "ssh.pk_sig_blob_name",
6741 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6742 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6743
6744 { &hf_ssh_pk_sig_s_length,
6745 { "ssh-rsa signature length", "ssh.sig.ssh-rsa.length",
6746 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6747 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6748
6749 { &hf_ssh_pk_sig_s,
6750 { "ssh-rsa signature (s)", "ssh.sig.ssh-rsa.s",
6751 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
6752 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6753
6754 { &hf_ssh_connection_type_name_len,
6755 { "Channel type name length", "ssh.connection_type_name_length",
6756 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6757 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6758
6759 { &hf_ssh_connection_type_name,
6760 { "Channel type name", "ssh.connection_type_name",
6761 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6762 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6763
6764 { &hf_ssh_connection_sender_channel,
6765 { "Sender channel", "ssh.connection_sender_channel",
6766 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6767 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6768
6769 { &hf_ssh_connection_recipient_channel,
6770 { "Recipient channel", "ssh.connection_recipient_channel",
6771 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6772 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6773
6774 { &hf_ssh_connection_initial_window,
6775 { "Initial window size", "ssh.connection_initial_window_size",
6776 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6777 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6778
6779 { &hf_ssh_connection_maximum_packet_size,
6780 { "Maximum packet size", "ssh.userauth_maximum_packet_size",
6781 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6782 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6783
6784 { &hf_ssh_global_request_name_len,
6785 { "Global request name length", "ssh.global_request_name_length",
6786 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6787 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6788
6789 { &hf_ssh_global_request_name,
6790 { "Global request name", "ssh.global_request_name",
6791 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6792 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6793
6794 { &hf_ssh_global_request_want_reply,
6795 { "Global request want reply", "ssh.global_request_want_reply",
6796 FT_UINT8, BASE_DEC, NULL((void*)0), 0x0,
6797 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6798
6799 { &hf_ssh_global_request_hostkeys_array_len,
6800 { "Host keys array length", "ssh.global_request_hostkeys",
6801 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6802 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6803
6804 { &hf_ssh_channel_request_name_len,
6805 { "Channel request name length", "ssh.channel_request_name_length",
6806 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6807 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6808
6809 { &hf_ssh_channel_request_name,
6810 { "Channel request name", "ssh.channel_request_name",
6811 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6812 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6813
6814 { &hf_ssh_channel_request_want_reply,
6815 { "Channel request want reply", "ssh.channel_request_want_reply",
6816 FT_UINT8, BASE_DEC, NULL((void*)0), 0x0,
6817 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6818
6819 { &hf_ssh_subsystem_name_len,
6820 { "Subsystem name length", "ssh.subsystem_name_length",
6821 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6822 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6823
6824 { &hf_ssh_subsystem_name,
6825 { "Subsystem name", "ssh.subsystem_name",
6826 FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6827 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6828
6829 { &hf_ssh_exec_cmd,
6830 { "Command", "ssh.exec_command",
6831 FT_UINT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6832 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
6833
6834 { &hf_ssh_env_name,
6835 { "Variable name", "ssh.env_name",
6836 FT_UINT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6837 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
6838
6839 { &hf_ssh_env_value,
6840 { "Variable value", "ssh.env_value",
6841 FT_UINT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6842 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
6843
6844 { &hf_ssh_pty_term,
6845 { "TERM environment variable", "ssh.pty_term",
6846 FT_UINT_STRING, BASE_NONE, NULL((void*)0), 0x0,
6847 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
6848
6849 { &hf_ssh_pty_term_width_char,
6850 { "Terminal width, characters", "ssh.pty_term_width_char",
6851 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6852 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
6853
6854 { &hf_ssh_pty_term_height_row,
6855 { "Terminal height, rows", "ssh.pty_term_height_row",
6856 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6857 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
6858
6859 { &hf_ssh_pty_term_width_pixel,
6860 { "Terminal width, pixels", "ssh.pty_term_width_pixel",
6861 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6862 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
6863
6864 { &hf_ssh_pty_term_height_pixel,
6865 { "Terminal height, pixels", "ssh.pty_term_height_pixel",
6866 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6867 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
6868
6869 { &hf_ssh_pty_term_modes_len,
6870 { "Encoded Terminal Modes Length", "ssh.pty_term_modes_length",
6871 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
6872 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
6873
6874 { &hf_ssh_pty_term_modes,
6875 { "Encoded Terminal Modes", "ssh.pty_term_modes",
6876 FT_NONE, BASE_NONE, NULL((void*)0), 0x0,
6877 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
6878
6879 { &hf_ssh_pty_term_mode,
6880 { "Mode", "ssh.pty_term_mode",
6881 FT_NONE, BASE_NONE, NULL((void*)0), 0x0,
6882 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
6883
6884 { &hf_ssh_pty_term_mode_opcode,
6885 { "Opcode", "ssh.pty_term_mode.opcode",
6886 FT_UINT8, BASE_DEC, VALS(ssh_tty_op_vals)((0 ? (const struct _value_string*)0 : ((ssh_tty_op_vals)))), 0x0,
6887 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
6888
6889 { &hf_ssh_pty_term_mode_vintr,
6890 { "Interrupt character", "ssh.pty_term_mode.vintr",
6891 FT_CHAR, BASE_HEX, NULL((void*)0), 0x0,
6892 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
6893
6894 { &hf_ssh_pty_term_mode_vquit,
6895 { "Quit character", "ssh.pty_term_mode.vquit",
6896 FT_CHAR, BASE_HEX, NULL((void*)0), 0x0,
6897 "Sends SIGQUIT on POSIX systems", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},
6898
6899 { &hf_ssh_pty_term_mode_verase,
6900 { "Erase the character to the left of the cursor", "ssh.pty_term_mode.verase",
6901 FT_CHAR, BASE_HEX, NULL((void*)0), 0x0,
6902 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)} },
6903
6904 { &hf_ssh_pty_term_mode_vkill,
6905 { "Kill the current input line", "ssh.pty_term_mode.vkill",
6906 FT_CHAR, BASE_HEX, NULL((void*)0), 0x0,
6907 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)} },
6908
6909 { &hf_ssh_pty_term_mode_veof,
6910 { "End-of-file character", "ssh.pty_term_mode.veof",
6911 FT_CHAR, BASE_HEX, NULL((void*)0), 0x0,
6912 "Sends EOF from the terminal", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},
6913
6914 { &hf_ssh_pty_term_mode_veol,
6915 { "End-of-line character", "ssh.pty_term_mode.veol",
6916 FT_CHAR, BASE_HEX, NULL((void*)0), 0x0,
6917 "In additional to carriage return and/or line feed", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)} },
6918
6919 { &hf_ssh_pty_term_mode_veol2,
6920 { "Additional end-of-line character", "ssh.pty_term_mode.veol2",
6921 FT_CHAR, BASE_HEX, NULL((void*)0), 0x0,
6922 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)} },
6923
6924 { &hf_ssh_pty_term_mode_vstart,
6925 { "Continues paused output", "ssh.pty_term_mode.vstart",
6926 FT_CHAR, BASE_HEX, NULL((void*)0), 0x0,
6927 "Normally Control-Q", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},
6928
6929 { &hf_ssh_pty_term_mode_vstop,
6930 { "Pauses output", "ssh.pty_term_mode.vstop",
6931 FT_CHAR, BASE_HEX, NULL((void*)0), 0x0,
6932 "Normally Control-S", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)} },
6933
6934 { &hf_ssh_pty_term_mode_vsusp,
6935 { "Suspends the current program", "ssh.pty_term_mode.vsusp",
6936 FT_CHAR, BASE_HEX, NULL((void*)0), 0x0,
6937 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)} },
6938
6939 { &hf_ssh_pty_term_mode_vdsusp,
6940 { "Another suspend character", "ssh.pty_term_mode.vdsusp",
6941 FT_CHAR, BASE_HEX, NULL((void*)0), 0x0,
6942 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)} },
6943
6944 { &hf_ssh_pty_term_mode_vreprint,
6945 { "Reprints the current input line", "ssh.pty_term_mode.vreprint",
6946 FT_CHAR, BASE_HEX, NULL((void*)0), 0x0,
6947 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)} },
6948
6949 { &hf_ssh_pty_term_mode_vwerase,
6950 { "Erase a word to the left of the cursor", "ssh.pty_term_mode.vwerase",
6951 FT_CHAR, BASE_HEX, NULL((void*)0), 0x0,
6952 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)} },
6953
6954 { &hf_ssh_pty_term_mode_vlnext,
6955 { "Enter the next character typed literally", "ssh.pty_term_mode.vlnext",
6956 FT_CHAR, BASE_HEX, NULL((void*)0), 0x0,
6957 "Even if a special character", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)} },
6958
6959 { &hf_ssh_pty_term_mode_vflush,
6960 { "Character to flush output", "ssh.pty_term_mode.vflush",
6961 FT_CHAR, BASE_HEX, NULL((void*)0), 0x0,
6962 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)} },
6963
6964 { &hf_ssh_pty_term_mode_vswtch,
6965 { "Switch to a different shell layer", "ssh.pty_term_mode.vswtch",
6966 FT_CHAR, BASE_HEX, NULL((void*)0), 0x0,
6967 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)} },
6968
6969 { &hf_ssh_pty_term_mode_vstatus,
6970 { "Print system status line", "ssh.pty_term_mode.vstatus",
6971 FT_CHAR, BASE_HEX, NULL((void*)0), 0x0,
6972 "Load, command, pid, etc.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}},
6973
6974 { &hf_ssh_pty_term_mode_vdiscard,
6975 { "Toggles the flushing of terminal output", "ssh.pty_term_mode.vdiscard",
6976 FT_CHAR, BASE_HEX, NULL((void*)0), 0x0,
6977 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)} },
6978
6979 { &hf_ssh_pty_term_mode_ignpar,
6980 { "Ignore parity flag", "ssh.pty_term_mode.ignpar",
6981 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
6982 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
6983
6984 { &hf_ssh_pty_term_mode_parmrk,
6985 { "Mark parity and framing errors", "ssh.pty_term_mode.parmrk",
6986 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
6987 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
6988
6989 { &hf_ssh_pty_term_mode_inpck,
6990 { "Enable checking of parity errors", "ssh.pty_term_mode.inpck",
6991 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
6992 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
6993
6994 { &hf_ssh_pty_term_mode_istrip,
6995 { "Strip 8th bit off characters", "ssh.pty_term_mode.istrip",
6996 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
6997 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
6998
6999 { &hf_ssh_pty_term_mode_inlcr,
7000 { "Map NL into CR on input", "ssh.pty_term_mode.inlcr",
7001 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7002 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7003
7004 { &hf_ssh_pty_term_mode_igncr,
7005 { "Ignore CR on input", "ssh.pty_term_mode.igncr",
7006 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7007 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7008
7009 { &hf_ssh_pty_term_mode_icrnl,
7010 { "Map CR to NL on input", "ssh.pty_term_mode.icrnl",
7011 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7012 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7013
7014 { &hf_ssh_pty_term_mode_iuclc,
7015 { "Translate uppercase characters to lowercase", "ssh.pty_term_mode.iuclc",
7016 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7017 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7018
7019 { &hf_ssh_pty_term_mode_ixon,
7020 { "Enable output flow control", "ssh.pty_term_mode.ixon",
7021 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7022 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7023
7024 { &hf_ssh_pty_term_mode_ixany,
7025 { "Any char will restart after stop", "ssh.pty_term_mode.ixany",
7026 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7027 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7028
7029 { &hf_ssh_pty_term_mode_ixoff,
7030 { "Enable input flow control", "ssh.pty_term_mode.ixoff",
7031 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7032 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7033
7034 { &hf_ssh_pty_term_mode_imaxbel,
7035 { "Ring bell on input queue full", "ssh.pty_term_mode.imaxbel",
7036 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7037 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7038
7039 { &hf_ssh_pty_term_mode_iutf8,
7040 { "Terminal input and output is assumed to be encoded in UTF-8", "ssh.pty_term_mode.iutf8",
7041 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7042 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7043
7044 { &hf_ssh_pty_term_mode_isig,
7045 { "Enable signals INTR, QUIT, [D]SUSP", "ssh.pty_term_mode.isig",
7046 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7047 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7048
7049 { &hf_ssh_pty_term_mode_icanon,
7050 { "Canonicalize input lines", "ssh.pty_term_mode.icanon",
7051 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7052 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7053
7054 { &hf_ssh_pty_term_mode_xcase,
7055 { "Enable input and output of uppercase characters by preceding their lowercase equivalents with '\'", "ssh.pty_term_mode.xcase",
7056 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7057 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7058
7059 { &hf_ssh_pty_term_mode_echo,
7060 { "Enable echoing", "ssh.pty_term_mode.echo",
7061 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7062 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7063
7064 { &hf_ssh_pty_term_mode_echoe,
7065 { "Visually erase chars", "ssh.pty_term_mode.echoe",
7066 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7067 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7068
7069 { &hf_ssh_pty_term_mode_echok,
7070 { "Kill character discards current line", "ssh.pty_term_mode.echok",
7071 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7072 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7073
7074 { &hf_ssh_pty_term_mode_echonl,
7075 { "Echo NL even if ECHO is off", "ssh.pty_term_mode.echonl",
7076 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7077 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7078
7079 { &hf_ssh_pty_term_mode_noflsh,
7080 { "No flush after interrupt", "ssh.pty_term_mode.noflsh",
7081 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7082 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7083
7084 { &hf_ssh_pty_term_mode_tostop,
7085 { "Stop background jobs from output", "ssh.pty_term_mode.tostop",
7086 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7087 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7088
7089 { &hf_ssh_pty_term_mode_iexten,
7090 { "Enable extensions", "ssh.pty_term_mode.iexten",
7091 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7092 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7093
7094 { &hf_ssh_pty_term_mode_echoctl,
7095 { "Echo control characters as ^(Char)", "ssh.pty_term_mode.echoctl",
7096 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7097 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7098
7099 { &hf_ssh_pty_term_mode_echoke,
7100 { "Visual erase for line kill", "ssh.pty_term_mode.echoke",
7101 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7102 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7103
7104 { &hf_ssh_pty_term_mode_pendin,
7105 { "Retype pending input", "ssh.pty_term_mode.pendin",
7106 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7107 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7108
7109 { &hf_ssh_pty_term_mode_opost,
7110 { "Enable output processing", "ssh.pty_term_mode.opost",
7111 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7112 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7113
7114 { &hf_ssh_pty_term_mode_olcuc,
7115 { "Convert lowercase to uppercase", "ssh.pty_term_mode.olcuc",
7116 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7117 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7118
7119 { &hf_ssh_pty_term_mode_onlcr,
7120 { "Map NL to CR-NL", "ssh.pty_term_mode.onlcr",
7121 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7122 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7123
7124 { &hf_ssh_pty_term_mode_ocrnl,
7125 { "Translate carriage return to newline (output)", "ssh.pty_term_mode.ocrnl",
7126 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7127 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7128
7129 { &hf_ssh_pty_term_mode_onocr,
7130 { "Translate newline to carriage-return newline (output)", "ssh.pty_term_mode.onocr",
7131 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7132 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7133
7134 { &hf_ssh_pty_term_mode_onlret,
7135 { "Newline performs a carriage return (output)", "ssh.pty_term_mode.onlret",
7136 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7137 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7138
7139 { &hf_ssh_pty_term_mode_cs7,
7140 { "7 bit mode", "ssh.pty_term_mode.cs7",
7141 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7142 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7143
7144 { &hf_ssh_pty_term_mode_cs8,
7145 { "8 bit mode", "ssh.pty_term_mode.cs8",
7146 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7147 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7148
7149 { &hf_ssh_pty_term_mode_parenb,
7150 { "Parity enable", "ssh.pty_term_mode.parenb",
7151 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7152 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7153
7154 { &hf_ssh_pty_term_mode_parodd,
7155 { "Odd parity", "ssh.pty_term_mode.parodd",
7156 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7157 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7158
7159 { &hf_ssh_pty_term_mode_ispeed,
7160 { "Input baud rate", "ssh.pty_term_mode.ispeed",
7161 FT_UINT32, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_bit_sec)((0 ? (const struct unit_name_string*)0 : ((&units_bit_sec
))))
, 0x0,
7162 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7163
7164 { &hf_ssh_pty_term_mode_ospeed,
7165 { "Output baud rate", "ssh.pty_term_mode.ospeed",
7166 FT_UINT32, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_bit_sec)((0 ? (const struct unit_name_string*)0 : ((&units_bit_sec
))))
, 0x0,
7167 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7168
7169 { &hf_ssh_pty_term_mode_value,
7170 { "Value", "ssh.pty_term_mode.value",
7171 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
7172 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7173
7174 { &hf_ssh_exit_status,
7175 { "Exit status", "ssh.exit_status",
7176 FT_UINT32, BASE_HEX, NULL((void*)0), 0x0,
7177 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7178
7179 { &hf_ssh_channel_window_adjust,
7180 { "Bytes to add", "ssh.channel_window_adjust",
7181 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
7182 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7183
7184 { &hf_ssh_channel_data_len,
7185 { "Data length", "ssh.channel_data_length",
7186 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
7187 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7188
7189 { &hf_ssh_channel_data_type_code,
7190 { "Data Type Code", "ssh.channel_data_type_code",
7191 FT_UINT32, BASE_DEC, VALS(ssh_channel_data_type_code_vals)((0 ? (const struct _value_string*)0 : ((ssh_channel_data_type_code_vals
))))
, 0x0,
7192 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
7193
7194 { &hf_ssh_reassembled_in,
7195 { "Reassembled PDU in frame", "ssh.reassembled_in",
7196 FT_FRAMENUM, BASE_NONE, NULL((void*)0), 0x0,
7197 "The PDU that doesn't end in this segment is reassembled in this frame", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7198
7199 { &hf_ssh_reassembled_length,
7200 { "Reassembled PDU length", "ssh.reassembled.length",
7201 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
7202 "The total length of the reassembled payload", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7203
7204 { &hf_ssh_reassembled_data,
7205 { "Reassembled PDU data", "ssh.reassembled.data",
7206 FT_BYTES, BASE_NONE, NULL((void*)0), 0x00,
7207 "The payload of multiple reassembled SSH segments", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7208
7209 { &hf_ssh_segments,
7210 { "Reassembled SSH segments", "ssh.segments",
7211 FT_NONE, BASE_NONE, NULL((void*)0), 0x0,
7212 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7213
7214 { &hf_ssh_segment,
7215 { "SSH segment", "ssh.segment",
7216 FT_FRAMENUM, BASE_NONE, NULL((void*)0), 0x0,
7217 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7218
7219 { &hf_ssh_segment_overlap,
7220 { "Segment overlap", "ssh.segment.overlap",
7221 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7222 "Segment overlaps with other segments", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7223
7224 { &hf_ssh_segment_overlap_conflict,
7225 { "Conflicting data in segment overlap", "ssh.segment.overlap.conflict",
7226 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7227 "Overlapping segments contained conflicting data", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7228
7229 { &hf_ssh_segment_multiple_tails,
7230 { "Multiple tail segments found", "ssh.segment.multipletails",
7231 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7232 "Several tails were found when reassembling the pdu", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7233
7234 { &hf_ssh_segment_too_long_fragment,
7235 { "Segment too long", "ssh.segment.toolongfragment",
7236 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
7237 "Segment contained data past end of the pdu", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7238
7239 { &hf_ssh_segment_error,
7240 { "Reassembling error", "ssh.segment.error",
7241 FT_FRAMENUM, BASE_NONE, NULL((void*)0), 0x0,
7242 "Reassembling error due to illegal segments", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7243
7244 { &hf_ssh_segment_count,
7245 { "Segment count", "ssh.segment.count",
7246 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
7247 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7248
7249 { &hf_ssh_segment_data,
7250 { "SSH segment data", "ssh.segment.data",
7251 FT_BYTES, BASE_NONE, NULL((void*)0), 0x00,
7252 "The payload of a single SSH segment", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7253
7254 { &hf_ssh_hybrid_blob_client,
7255 { "Hybrid Key Exchange Blob Client", "ssh.kex_hybrid_blob_client",
7256 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0, "Client post-quantum hybrid blob", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
7257 },
7258
7259 { &hf_ssh_hybrid_blob_client_len,
7260 { "Hybrid Key Exchange Blob Client Length", "ssh.kex_hybrid_blob_client_len",
7261 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) }
7262 },
7263
7264 { &hf_ssh_hybrid_blob_server,
7265 { "Hybrid Key Exchange Blob Server", "ssh.kex_hybrid_blob_server",
7266 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0, "Server post-quantum hybrid blob", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
7267 },
7268
7269 { &hf_ssh_hybrid_blob_server_len,
7270 { "Hybrid Key Exchange Blob Server Length", "ssh.kex_hybrid_blob_server_len",
7271 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) }
7272 },
7273
7274 { &hf_ssh_pq_kem_client,
7275 { "Client PQ KEM Public Key", "ssh.kex.pq_kem_client",
7276 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
7277 "Post-quantum key (client)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
7278 },
7279
7280 { &hf_ssh_pq_kem_server,
7281 { "Server PQ KEM Response", "ssh.kex.pq_kem_server",
7282 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
7283 "Post-quantum ciphertext (server response)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
7284 },
7285
7286 };
7287
7288 static int *ett[] = {
7289 &ett_ssh,
7290 &ett_key_exchange,
7291 &ett_key_exchange_host_key,
7292 &ett_key_exchange_host_sig,
7293 &ett_extension,
7294 &ett_userauth_pk_blob,
7295 &ett_userauth_pk_signature,
7296 &ett_term_modes,
7297 &ett_term_mode,
7298 &ett_ssh1,
7299 &ett_ssh2,
7300 &ett_key_init,
7301 &ett_ssh_segments,
7302 &ett_ssh_pqhybrid_client, // added for PQ hybrid CLIENT dissection
7303 &ett_ssh_pqhybrid_server, // added for PQ hybrid SERVER dissection
7304 &ett_ssh_segment
7305 };
7306
7307 static ei_register_info ei[] = {
7308 { &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)}}
}},
7309 { &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)}}
}},
7310 { &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)}}
}},
7311 { &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)}}
}},
7312 { &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)}}
}},
7313 { &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)}}
}},
7314 { &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)}}
}},
7315 { &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)}}
}},
7316
7317 };
7318 module_t *ssh_module;
7319 expert_module_t *expert_ssh;
7320
7321 proto_ssh = proto_register_protocol("SSH Protocol", "SSH", "ssh");
7322 proto_register_field_array(proto_ssh, hf, array_length(hf)(sizeof (hf) / sizeof (hf)[0]));
7323 proto_register_subtree_array(ett, array_length(ett)(sizeof (ett) / sizeof (ett)[0]));
7324 expert_ssh = expert_register_protocol(proto_ssh);
7325 expert_register_field_array(expert_ssh, ei, array_length(ei)(sizeof (ei) / sizeof (ei)[0]));
7326
7327#ifdef SSH_DECRYPT_DEBUG
7328 ssh_module = prefs_register_protocol(proto_ssh, ssh_prefs_apply_cb);
7329#else
7330 ssh_module = prefs_register_protocol(proto_ssh, NULL((void*)0));
7331#endif
7332 prefs_register_bool_preference(ssh_module, "desegment_buffers",
7333 "Reassemble SSH buffers spanning multiple TCP segments",
7334 "Whether the SSH dissector should reassemble SSH buffers spanning multiple TCP segments. "
7335 "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
7336 &ssh_desegment);
7337 prefs_register_bool_preference(ssh_module, "ignore_ssh_mac_failed",
7338 "Ignore Message Authentication Code (MAC) failure",
7339 "For troubleshooting purposes, decrypt even if the "
7340 "Message Authentication Code (MAC) check fails.",
7341 &ssh_ignore_mac_failed);
7342
7343 ssh_master_key_map = g_hash_table_new_full(ssh_hash, ssh_equal, ssh_free_glib_allocated_bignum, ssh_free_glib_allocated_entry);
7344 prefs_register_filename_preference(ssh_module, "keylog_file", "Key log filename",
7345 "The path to the file which contains a list of key exchange secrets in the following format:\n"
7346 "\"<hex-encoded-cookie> <PRIVATE_KEY|SHARED_SECRET> <hex-encoded-key>\" (without quotes or leading spaces).\n",
7347 &pref_keylog_file, false0);
7348
7349 prefs_register_filename_preference(ssh_module, "debug_file", "SSH debug file",
7350 "Redirect SSH debug to the file specified. Leave empty to disable debugging "
7351 "or use \"" SSH_DEBUG_USE_STDERR"-" "\" to redirect output to stderr.",
7352 &ssh_debug_file_name, true1);
7353
7354 secrets_register_type(SECRETS_TYPE_SSH0x5353484b, ssh_secrets_block_callback);
7355
7356 ssh_handle = register_dissector("ssh", dissect_ssh, proto_ssh);
7357 reassembly_table_register(&ssh_reassembly_table, &tcp_reassembly_table_functions);
7358 register_shutdown_routine(ssh_shutdown);
7359}
7360
7361void
7362proto_reg_handoff_ssh(void)
7363{
7364#ifdef SSH_DECRYPT_DEBUG
7365 ssh_set_debug(ssh_debug_file_name);
7366#endif
7367 dissector_add_uint_range_with_preference("tcp.port", TCP_RANGE_SSH"22", ssh_handle);
7368 dissector_add_uint("sctp.port", SCTP_PORT_SSH22, ssh_handle);
7369 dissector_add_uint("sctp.ppi", SSH_PAYLOAD_PROTOCOL_ID45, ssh_handle);
7370 sftp_handle = find_dissector_add_dependency("sftp", proto_ssh);
7371 data_text_lines_handle = find_dissector_add_dependency("data-text-lines", proto_ssh);
7372
7373 heur_dissector_add("tcp", dissect_ssh_heur, "SSH over TCP", "ssh_tcp", proto_ssh, HEURISTIC_ENABLE);
7374}
7375
7376/*
7377 * Editor modelines - https://www.wireshark.org/tools/modelines.html
7378 *
7379 * Local variables:
7380 * c-basic-offset: 4
7381 * tab-width: 8
7382 * indent-tabs-mode: nil
7383 * End:
7384 *
7385 * vi: set shiftwidth=4 tabstop=8 expandtab:
7386 * :indentSize=4:tabSize=8:noTabs=true:
7387 */