Bug Summary

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