Bug Summary

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