Bug Summary

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