Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

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