Coverage Report

Created: 2026-08-14 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-sftp.c
Line
Count
Source
1
/* packet-sftp.c
2
 * Routines for ssh packet dissection
3
 *
4
 * Jérôme Hamm
5
 *
6
 * Wireshark - Network traffic analyzer
7
 * By Gerald Combs <gerald@wireshark.org>
8
 * Copyright 1998 Gerald Combs
9
 *
10
 * Copied from packet-ssh.c
11
 *
12
 * SPDX-License-Identifier: GPL-2.0-or-later
13
 *
14
 *
15
 * Note:  support for SFTP.
16
 *
17
 */
18
19
/* SFTP is defined in:
20
 *
21
 * draft-ietf-secsh-filexfer-02 - SSH File Transfer Protocol
22
 *
23
 */
24
25
#include "config.h"
26
#define WS_LOG_DOMAIN "sftp"
27
28
#include <epan/packet.h>
29
#include <epan/expert.h>
30
31
void proto_register_sftp(void);
32
33
static int proto_sftp;
34
35
static int hf_ssh_sftp_len;
36
static int hf_ssh_sftp_type;
37
static int hf_ssh_sftp_version;
38
static int hf_ssh_sftp_id;
39
static int hf_ssh_sftp_path_len;
40
static int hf_ssh_sftp_path;
41
static int hf_ssh_sftp_pflags;
42
static int hf_ssh_sftp_name_count;
43
static int hf_ssh_sftp_name_fn_len;
44
static int hf_ssh_sftp_name_fn;
45
static int hf_ssh_sftp_name_ln_len;
46
static int hf_ssh_sftp_name_ln;
47
static int hf_ssh_sftp_attrs_flags;
48
static int hf_ssh_sftp_attrs_size;
49
static int hf_ssh_sftp_attrs_uid;
50
static int hf_ssh_sftp_attrs_gid;
51
static int hf_ssh_sftp_attrs_permissions;
52
static int hf_ssh_sftp_attrs_atime;
53
static int hf_ssh_sftp_attrs_mtime;
54
static int hf_ssh_sftp_attrs_extended_count;
55
static int hf_ssh_sftp_handle_len;
56
static int hf_ssh_sftp_handle;
57
static int hf_ssh_sftp_status;
58
static int hf_ssh_sftp_error_message_len;
59
static int hf_ssh_sftp_error_message;
60
static int hf_ssh_sftp_offset;
61
static int hf_ssh_sftp_length;
62
static int hf_ssh_sftp_data_len;
63
static int hf_ssh_sftp_data;
64
static int hf_ssh_lang_tag_length;
65
static int hf_ssh_lang_tag;
66
67
static int ett_sftp;
68
static int ett_sftp_attrs;
69
70
static dissector_handle_t sftp_handle;
71
72
0
#define SSH_FXP_INIT                1
73
0
#define SSH_FXP_VERSION             2
74
0
#define SSH_FXP_OPEN                3
75
0
#define SSH_FXP_CLOSE               4
76
0
#define SSH_FXP_READ                5
77
0
#define SSH_FXP_WRITE               6
78
0
#define SSH_FXP_LSTAT               7
79
0
#define SSH_FXP_FSTAT               8
80
0
#define SSH_FXP_SETSTAT             9
81
#define SSH_FXP_FSETSTAT           10
82
0
#define SSH_FXP_OPENDIR            11
83
0
#define SSH_FXP_READDIR            12
84
0
#define SSH_FXP_REMOVE             13
85
#define SSH_FXP_MKDIR              14
86
#define SSH_FXP_RMDIR              15
87
0
#define SSH_FXP_REALPATH           16
88
0
#define SSH_FXP_STAT               17
89
0
#define SSH_FXP_RENAME             18
90
#define SSH_FXP_READLINK           19
91
#define SSH_FXP_LINK               21
92
#define SSH_FXP_BLOCK              22
93
#define SSH_FXP_UNBLOCK            23
94
95
0
#define SSH_FXP_STATUS            101
96
0
#define SSH_FXP_HANDLE            102
97
0
#define SSH_FXP_DATA              103
98
0
#define SSH_FXP_NAME              104
99
0
#define SSH_FXP_ATTRS             105
100
101
#define SSH_FXP_EXTENDED          200
102
#define SSH_FXP_EXTENDED_REPLY    201
103
104
0
#define SSH_FILEXFER_ATTR_SIZE          0x00000001
105
0
#define SSH_FILEXFER_ATTR_UIDGID        0x00000002
106
0
#define SSH_FILEXFER_ATTR_PERMISSIONS   0x00000004
107
0
#define SSH_FILEXFER_ATTR_ACMODTIME     0x00000008
108
0
#define SSH_FILEXFER_ATTR_EXTENDED      0x80000000
109
110
static const value_string ssh2_sftp_vals[] = {
111
    {SSH_FXP_INIT,                       "SSH_FXP_INIT"},
112
    {SSH_FXP_VERSION,                    "SSH_FXP_VERSION"},
113
    {SSH_FXP_OPEN,                       "SSH_FXP_OPEN"},
114
    {SSH_FXP_CLOSE,                      "SSH_FXP_CLOSE"},
115
    {SSH_FXP_READ,                       "SSH_FXP_READ"},
116
    {SSH_FXP_WRITE,                      "SSH_FXP_WRITE"},
117
    {SSH_FXP_LSTAT,                      "SSH_FXP_LSTAT"},
118
    {SSH_FXP_FSTAT,                      "SSH_FXP_FSTAT"},
119
    {SSH_FXP_SETSTAT,                    "SSH_FXP_SETSTAT"},
120
    {SSH_FXP_FSETSTAT,                   "SSH_FXP_FSETSTAT"},
121
    {SSH_FXP_OPENDIR,                    "SSH_FXP_OPENDIR"},
122
    {SSH_FXP_READDIR,                    "SSH_FXP_READDIR"},
123
    {SSH_FXP_REMOVE,                     "SSH_FXP_REMOVE"},
124
    {SSH_FXP_MKDIR,                      "SSH_FXP_MKDIR"},
125
    {SSH_FXP_RMDIR,                      "SSH_FXP_RMDIR"},
126
    {SSH_FXP_REALPATH,                   "SSH_FXP_REALPATH"},
127
    {SSH_FXP_STAT,                       "SSH_FXP_STAT"},
128
    {SSH_FXP_RENAME,                     "SSH_FXP_RENAME"},
129
    {SSH_FXP_READLINK,                   "SSH_FXP_READLINK"},
130
    {SSH_FXP_LINK,                       "SSH_FXP_LINK"},
131
    {SSH_FXP_BLOCK,                      "SSH_FXP_BLOCK"},
132
    {SSH_FXP_UNBLOCK,                    "SSH_FXP_UNBLOCK"},
133
    {SSH_FXP_STATUS,                     "SSH_FXP_STATUS"},
134
    {SSH_FXP_HANDLE,                     "SSH_FXP_HANDLE"},
135
    {SSH_FXP_DATA,                       "SSH_FXP_DATA"},
136
    {SSH_FXP_NAME,                       "SSH_FXP_NAME"},
137
    {SSH_FXP_ATTRS,                      "SSH_FXP_ATTRS"},
138
    {SSH_FXP_EXTENDED,                   "SSH_FXP_EXTENDED"},
139
    {SSH_FXP_EXTENDED_REPLY,             "SSH_FXP_EXTENDED_REPLY"},
140
    {0, NULL}
141
};
142
143
static int dissect_sftp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_);
144
static int dissect_sftp_attrs(tvbuff_t *packet_tvb, packet_info *pinfo,
145
        int offset, proto_item *msg_type_tree);
146
147
static int dissect_sftp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
148
0
{
149
0
        unsigned offset = 0;
150
0
        unsigned   plen;
151
0
        unsigned   slen;
152
0
        if (pinfo->can_desegment) {
153
0
                if (tvb_captured_length_remaining(tvb, offset) < 4) {
154
0
                        pinfo->desegment_offset = offset;
155
0
                        pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
156
0
                        return tvb_captured_length(tvb);
157
0
                }
158
0
        }
159
160
0
        plen = tvb_get_ntohl(tvb, offset);
161
0
        if (pinfo->can_desegment) {
162
0
                unsigned length_remaining = tvb_captured_length_remaining(tvb, offset + 4);
163
0
                if (length_remaining < plen) {
164
0
                        pinfo->desegment_offset = offset;
165
0
                        pinfo->desegment_len = plen - length_remaining;
166
0
                        return tvb_captured_length(tvb);
167
0
                }
168
0
        }
169
170
0
        wmem_strbuf_t *title = wmem_strbuf_new(pinfo->pool, "");
171
0
        proto_item *ti = proto_tree_add_item(tree, proto_sftp, tvb, offset, -1, ENC_NA);
172
0
        proto_tree *sftp_tree = proto_item_add_subtree(ti, ett_sftp);
173
0
        proto_tree_add_item(sftp_tree, hf_ssh_sftp_len, tvb, offset, 4, ENC_BIG_ENDIAN);
174
0
        offset += 4;
175
0
        uint8_t typ;
176
0
        typ = tvb_get_uint8(tvb, offset) ;
177
0
        proto_tree_add_item(sftp_tree, hf_ssh_sftp_type, tvb, offset, 1, ENC_BIG_ENDIAN);
178
0
        offset += 1;
179
0
        col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, val_to_str(pinfo->pool, typ, ssh2_sftp_vals, "Unknown (%u)"));
180
0
        switch(typ){
181
0
        case SSH_FXP_INIT:{
182
0
                int ver = tvb_get_ntohl(tvb, offset) ;
183
0
                wmem_strbuf_append_printf(title, " SSH_FXP_INIT (%d) version %d", typ, ver);
184
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_version, tvb, offset, 4, ENC_BIG_ENDIAN);
185
0
                offset += 4;
186
0
                break;
187
0
                }
188
0
        case SSH_FXP_VERSION:{
189
0
                int ver = tvb_get_ntohl(tvb, offset) ;
190
0
                wmem_strbuf_append_printf(title, " SSH_FXP_VERSION (%d) version %d", typ, ver);
191
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_version, tvb, offset, 4, ENC_BIG_ENDIAN);
192
0
                offset += 4;
193
0
                break;
194
0
                }
195
0
        case SSH_FXP_OPEN:{
196
0
                int id = tvb_get_ntohl(tvb, offset) ;
197
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_id, tvb, offset, 4, ENC_BIG_ENDIAN);
198
0
                offset += 4;
199
0
                slen = tvb_get_ntohl(tvb, offset) ;
200
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_path_len, tvb, offset, 4, ENC_BIG_ENDIAN);
201
0
                offset += 4;
202
0
                uint8_t * path = tvb_get_string_enc(pinfo->pool, tvb, offset, slen, ENC_UTF_8);
203
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_path, tvb, offset, slen, ENC_UTF_8);
204
0
                offset += slen;
205
//                int pflags = tvb_get_ntohl(tvb, offset) ;
206
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_pflags, tvb, offset, 4, ENC_BIG_ENDIAN);
207
0
                offset += 4;
208
0
                slen = dissect_sftp_attrs(tvb, pinfo, offset, sftp_tree);
209
0
                offset += slen;
210
0
                wmem_strbuf_append_printf(title, " SSH_FXP_OPEN (%d) id=%d [%s]", typ, id, path);
211
0
                break;
212
0
                }
213
0
        case SSH_FXP_CLOSE:{
214
0
                int id = tvb_get_ntohl(tvb, offset) ;
215
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_id, tvb, offset, 4, ENC_BIG_ENDIAN);
216
0
                offset += 4;
217
0
                slen = tvb_get_ntohl(tvb, offset) ;
218
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_handle_len, tvb, offset, 4, ENC_BIG_ENDIAN);
219
0
                offset += 4;
220
0
                char * handle = tvb_bytes_to_str(pinfo->pool, tvb, offset, slen);
221
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_handle, tvb, offset, slen, ENC_NA);
222
0
                offset += slen;
223
0
                wmem_strbuf_append_printf(title, " SSH_FXP_CLOSE (%d) id=%d {%s}", typ, id, handle);
224
0
                break;
225
0
                }
226
0
        case SSH_FXP_READ:{
227
0
                int id = tvb_get_ntohl(tvb, offset) ;
228
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_id, tvb, offset, 4, ENC_BIG_ENDIAN);
229
0
                offset += 4;
230
0
                slen = tvb_get_ntohl(tvb, offset) ;
231
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_handle_len, tvb, offset, 4, ENC_BIG_ENDIAN);
232
0
                offset += 4;
233
0
                char * handle = tvb_bytes_to_str(pinfo->pool, tvb, offset, slen);
234
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_handle, tvb, offset, slen, ENC_NA);
235
0
                offset += slen;
236
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_offset, tvb, offset, 8, ENC_BIG_ENDIAN);
237
0
                offset += 8;
238
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_length, tvb, offset, 4, ENC_BIG_ENDIAN);
239
0
                offset += 4;
240
0
                wmem_strbuf_append_printf(title, " SSH_FXP_READ (%d) id=%d {%s}", typ, id, handle);
241
0
                break;
242
0
                }
243
0
        case SSH_FXP_WRITE:{
244
0
                int id = tvb_get_ntohl(tvb, offset);
245
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_id, tvb, offset, 4, ENC_BIG_ENDIAN);
246
0
                offset += 4;
247
0
                slen = tvb_get_ntohl(tvb, offset) ;
248
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_handle_len, tvb, offset, 4, ENC_BIG_ENDIAN);
249
0
                offset += 4;
250
0
                char * handle = tvb_bytes_to_str(pinfo->pool, tvb, offset, slen);
251
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_handle, tvb, offset, slen, ENC_NA);
252
0
                offset += slen;
253
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_offset, tvb, offset, 8, ENC_BIG_ENDIAN);
254
0
                offset += 8;
255
0
                int dlen = tvb_get_ntohl(tvb, offset);
256
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_data_len, tvb, offset, 4, ENC_BIG_ENDIAN);
257
0
                offset += 4;
258
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_data, tvb, offset, dlen, ENC_NA);
259
0
                offset += dlen;
260
0
                wmem_strbuf_append_printf(title, " SSH_FXP_WRITE (%d) id=%d {%s} len=%d", typ, id, handle, dlen);
261
0
                break;
262
0
                }
263
0
        case SSH_FXP_LSTAT:{
264
0
                int id = tvb_get_ntohl(tvb, offset);
265
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_id, tvb, offset, 4, ENC_BIG_ENDIAN);
266
0
                offset += 4;
267
0
                slen = tvb_get_ntohl(tvb, offset) ;
268
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_path_len, tvb, offset, 4, ENC_BIG_ENDIAN);
269
0
                offset += 4;
270
0
                uint8_t * path = tvb_get_string_enc(pinfo->pool, tvb, offset, slen, ENC_UTF_8);
271
0
                wmem_strbuf_append_printf(title, " SSH_FXP_LSTAT (%d) id=%d [%s]", typ, id, path);
272
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_path, tvb, offset, slen, ENC_UTF_8);
273
0
                offset += slen;
274
0
                break;
275
0
                }
276
0
        case SSH_FXP_FSTAT:{
277
0
                int id = tvb_get_ntohl(tvb, offset);
278
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_id, tvb, offset, 4, ENC_BIG_ENDIAN);
279
0
                offset += 4;
280
0
                slen = tvb_get_ntohl(tvb, offset) ;
281
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_handle_len, tvb, offset, 4, ENC_BIG_ENDIAN);
282
0
                offset += 4;
283
0
                char * handle = tvb_bytes_to_str(pinfo->pool, tvb, offset, slen);
284
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_handle, tvb, offset, slen, ENC_NA);
285
0
                offset += slen;
286
0
                wmem_strbuf_append_printf(title, " SSH_FXP_FSTAT (%d) id=%d {%s}", typ, id, handle);
287
0
                break;
288
0
                }
289
0
        case SSH_FXP_SETSTAT:{
290
0
                int id = tvb_get_ntohl(tvb, offset);
291
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_id, tvb, offset, 4, ENC_BIG_ENDIAN);
292
0
                offset += 4;
293
0
                slen = tvb_get_ntohl(tvb, offset) ;
294
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_path_len, tvb, offset, 4, ENC_BIG_ENDIAN);
295
0
                offset += 4;
296
0
                uint8_t * path = tvb_get_string_enc(pinfo->pool, tvb, offset, slen, ENC_UTF_8);
297
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_path, tvb, offset, slen, ENC_UTF_8);
298
0
                offset += slen;
299
0
                slen = dissect_sftp_attrs(tvb, pinfo, offset, sftp_tree);
300
0
                proto_item_set_len(sftp_tree, slen);
301
0
                offset += slen;
302
0
                wmem_strbuf_append_printf(title, " SSH_FXP_SETSTAT (%d) id=%d [%s]", typ, id, path);
303
0
                break;
304
0
                }
305
//        case SSH_FXP_FSETSTAT):{
306
//                break;
307
//                }
308
0
        case SSH_FXP_OPENDIR:{
309
0
                int id = tvb_get_ntohl(tvb, offset);
310
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_id, tvb, offset, 4, ENC_BIG_ENDIAN);
311
0
                offset += 4;
312
0
                slen = tvb_get_ntohl(tvb, offset) ;
313
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_path_len, tvb, offset, 4, ENC_BIG_ENDIAN);
314
0
                offset += 4;
315
0
                uint8_t * path = tvb_get_string_enc(pinfo->pool, tvb, offset, slen, ENC_UTF_8);
316
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_path, tvb, offset, slen, ENC_UTF_8);
317
0
                offset += slen;
318
0
                wmem_strbuf_append_printf(title, " SSH_FXP_OPENDIR (%d) id=%d [%s]", typ, id, path);
319
0
                break;
320
0
                }
321
0
        case SSH_FXP_READDIR:{
322
0
                int id = tvb_get_ntohl(tvb, offset);
323
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_id, tvb, offset, 4, ENC_BIG_ENDIAN);
324
0
                offset += 4;
325
0
                slen = tvb_get_ntohl(tvb, offset) ;
326
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_handle_len, tvb, offset, 4, ENC_BIG_ENDIAN);
327
0
                offset += 4;
328
0
                char * handle = tvb_bytes_to_str(pinfo->pool, tvb, offset, slen);
329
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_handle, tvb, offset, slen, ENC_NA);
330
0
                offset += slen;
331
0
                wmem_strbuf_append_printf(title, " SSH_FXP_READDIR (%d) id=%d {%s}", typ, id, handle);
332
0
                break;
333
0
                }
334
0
        case SSH_FXP_REMOVE:{
335
0
                int id = tvb_get_ntohl(tvb, offset);
336
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_id, tvb, offset, 4, ENC_BIG_ENDIAN);
337
0
                offset += 4;
338
0
                slen = tvb_get_ntohl(tvb, offset) ;
339
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_path_len, tvb, offset, 4, ENC_BIG_ENDIAN);
340
0
                offset += 4;
341
0
                uint8_t * path = tvb_get_string_enc(pinfo->pool, tvb, offset, slen, ENC_UTF_8);
342
0
                wmem_strbuf_append_printf(title, " SSH_FXP_REMOVE (%d) id=%d [%s]", typ, id, path);
343
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_path, tvb, offset, slen, ENC_UTF_8);
344
0
                offset += slen;
345
0
                break;
346
0
                }
347
//        case SSH_FXP_MKDIR:{
348
//                break;
349
//                }
350
//        case SSH_FXP_RMDIR:{
351
//                break;
352
//                }
353
0
        case SSH_FXP_REALPATH:{
354
0
                int id = tvb_get_ntohl(tvb, offset);
355
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_id, tvb, offset, 4, ENC_BIG_ENDIAN);
356
0
                offset += 4;
357
0
                slen = tvb_get_ntohl(tvb, offset);
358
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_path_len, tvb, offset, 4, ENC_BIG_ENDIAN);
359
0
                offset += 4;
360
0
                uint8_t * path = tvb_get_string_enc(pinfo->pool, tvb, offset, slen, ENC_UTF_8);
361
0
                wmem_strbuf_append_printf(title, " SSH_FXP_REALPATH (%d) id=%d [%s]", typ, id, path);
362
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_path, tvb, offset, slen, ENC_UTF_8);
363
0
                offset += slen;
364
0
                break;
365
0
                }
366
0
        case SSH_FXP_STAT:{
367
0
                int id = tvb_get_ntohl(tvb, offset);
368
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_id, tvb, offset, 4, ENC_BIG_ENDIAN);
369
0
                offset += 4;
370
0
                slen = tvb_get_ntohl(tvb, offset) ;
371
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_path_len, tvb, offset, 4, ENC_BIG_ENDIAN);
372
0
                offset += 4;
373
0
                uint8_t * path = tvb_get_string_enc(pinfo->pool, tvb, offset, slen, ENC_UTF_8);
374
0
                wmem_strbuf_append_printf(title, " SSH_FXP_STAT (%d) id=%d [%s]", typ, id, path);
375
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_path, tvb, offset, slen, ENC_UTF_8);
376
0
                offset += slen;
377
0
                break;
378
0
                }
379
0
        case SSH_FXP_RENAME:{
380
0
                int id = tvb_get_ntohl(tvb, offset);
381
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_id, tvb, offset, 4, ENC_BIG_ENDIAN);
382
0
                offset += 4;
383
0
                slen = tvb_get_ntohl(tvb, offset) ;
384
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_path_len, tvb, offset, 4, ENC_BIG_ENDIAN);
385
0
                offset += 4;
386
0
                uint8_t * oldpath = tvb_get_string_enc(pinfo->pool, tvb, offset, slen, ENC_UTF_8);
387
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_path, tvb, offset, slen, ENC_UTF_8);
388
0
                offset += slen;
389
0
                slen = tvb_get_ntohl(tvb, offset) ;
390
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_path_len, tvb, offset, 4, ENC_BIG_ENDIAN);
391
0
                offset += 4;
392
0
                uint8_t * newpath = tvb_get_string_enc(pinfo->pool, tvb, offset, slen, ENC_UTF_8);
393
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_path, tvb, offset, slen, ENC_UTF_8);
394
0
                offset += slen;
395
0
                wmem_strbuf_append_printf(title, " SSH_FXP_STAT (%d) id=%d [%s] > [%s]", typ, id, oldpath, newpath);
396
0
                break;
397
0
                }
398
//        case SSH_FXP_READLINK:{
399
//                break;
400
//                }
401
//        case SSH_FXP_SYMLINK:{
402
//                break;
403
//                }
404
0
        case SSH_FXP_STATUS:{
405
0
                int id = tvb_get_ntohl(tvb, offset) ;
406
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_id, tvb, offset, 4, ENC_BIG_ENDIAN);
407
0
                offset += 4;
408
0
                int code = tvb_get_ntohl(tvb, offset) ;
409
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_status, tvb, offset, 4, ENC_BIG_ENDIAN);
410
0
                offset += 4;
411
0
                slen = tvb_get_ntohl(tvb, offset) ;
412
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_error_message_len, tvb, offset, 4, ENC_BIG_ENDIAN);
413
0
                offset += 4;
414
0
                uint8_t * err_msg = tvb_get_string_enc(pinfo->pool, tvb, offset, slen, ENC_UTF_8);
415
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_error_message, tvb, offset, slen, ENC_UTF_8);
416
0
                offset += slen;
417
0
                slen = tvb_get_ntohl(tvb, offset) ;
418
0
                proto_tree_add_item(sftp_tree, hf_ssh_lang_tag_length, tvb, offset, 4, ENC_BIG_ENDIAN);
419
0
                offset += 4;
420
0
                proto_tree_add_item(sftp_tree, hf_ssh_lang_tag, tvb, offset, slen, ENC_UTF_8);
421
0
                offset += slen;
422
0
                wmem_strbuf_append_printf(title, " SSH_FXP_STATUS (%d) id=%d code=%d [%s]", typ, id, code, err_msg);
423
0
                break;
424
0
                }
425
0
        case SSH_FXP_HANDLE:{
426
0
                int id = tvb_get_ntohl(tvb, offset);
427
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_id, tvb, offset, 4, ENC_BIG_ENDIAN);
428
0
                offset += 4;
429
0
                slen = tvb_get_ntohl(tvb, offset) ;
430
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_handle_len, tvb, offset, 4, ENC_BIG_ENDIAN);
431
0
                offset += 4;
432
0
                char * handle = tvb_bytes_to_str(pinfo->pool, tvb, offset, slen);
433
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_handle, tvb, offset, slen, ENC_NA);
434
0
                offset += slen;
435
0
                wmem_strbuf_append_printf(title, " SSH_FXP_HANDLE (%d) id=%d {%s}", typ, id, handle);
436
0
                break;
437
0
                }
438
0
        case SSH_FXP_DATA:{
439
0
                int id = tvb_get_ntohl(tvb, offset) ;
440
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_id, tvb, offset, 4, ENC_BIG_ENDIAN);
441
0
                offset += 4;
442
0
                int dlen = tvb_get_ntohl(tvb, offset) ;
443
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_data_len, tvb, offset, 4, ENC_BIG_ENDIAN);
444
0
                offset += 4;
445
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_data, tvb, offset, dlen, ENC_NA);
446
0
                offset += dlen;
447
0
                wmem_strbuf_append_printf(title, " SSH_FXP_DATA (%d) id=%d len=%d", typ, id, dlen);
448
0
                break;
449
0
                }
450
0
        case SSH_FXP_NAME:{
451
0
                wmem_strbuf_append_printf(title, " SSH_FXP_NAME (%d)", typ);
452
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_id, tvb, offset, 4, ENC_BIG_ENDIAN);
453
0
                offset += 4;
454
0
                unsigned count = tvb_get_ntohl(tvb, offset) ;
455
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_name_count, tvb, offset, 4, ENC_BIG_ENDIAN);
456
0
                offset += 4;
457
0
                unsigned cnt;
458
0
                for(cnt=0;cnt<count;cnt++){
459
0
                        slen = tvb_get_ntohl(tvb, offset) ;
460
0
                        proto_tree_add_item(sftp_tree, hf_ssh_sftp_name_fn_len, tvb, offset, 4, ENC_BIG_ENDIAN);
461
0
                        offset += 4;
462
0
                        proto_tree_add_item(sftp_tree, hf_ssh_sftp_name_fn, tvb, offset, slen, ENC_UTF_8);
463
0
                        offset += slen;
464
0
                        slen = tvb_get_ntohl(tvb, offset) ;
465
0
                        proto_tree_add_item(sftp_tree, hf_ssh_sftp_name_ln_len, tvb, offset, 4, ENC_BIG_ENDIAN);
466
0
                        offset += 4;
467
0
                        proto_tree_add_item(sftp_tree, hf_ssh_sftp_name_ln, tvb, offset, slen, ENC_UTF_8);
468
0
                        offset += slen;
469
0
                        slen = dissect_sftp_attrs(tvb, pinfo, offset, sftp_tree);
470
0
                        offset += slen;
471
0
                }
472
0
                break;
473
0
                }
474
0
        case SSH_FXP_ATTRS:{
475
0
                int id = tvb_get_ntohl(tvb, offset);
476
0
                wmem_strbuf_append_printf(title, " SSH_FXP_ATTRS (%d) id=%d", typ, id);
477
0
                proto_tree_add_item(sftp_tree, hf_ssh_sftp_id, tvb, offset, 4, ENC_BIG_ENDIAN);
478
0
                offset += 4;
479
0
                slen = dissect_sftp_attrs(tvb, pinfo, offset, sftp_tree);
480
0
                proto_item_set_len(sftp_tree, slen);
481
0
                offset += slen;
482
0
                break;
483
0
                }
484
//        case SSH_FXP_EXTENDED:{
485
//                break;
486
//                }
487
//        case SSH_FXP_EXTENDED_REPLY:{
488
//                break;
489
//                }
490
0
        default:{
491
0
                wmem_strbuf_append_printf(title, " unknown (%d)", typ);
492
0
                offset += plen;
493
0
                break;
494
0
                }
495
0
        }
496
0
        proto_item_append_text(ti, ",%s", wmem_strbuf_get_str(title));
497
0
        proto_item_set_len(sftp_tree, plen+4);
498
0
        return offset;
499
0
}
500
501
static int dissect_sftp_attrs(tvbuff_t *packet_tvb, packet_info *pinfo,
502
        int offset, proto_item *msg_type_tree)
503
0
{
504
0
        wmem_strbuf_t *title = wmem_strbuf_new(pinfo->pool, "SFTP attributes");
505
0
        proto_item * sftp_attrs_tree = proto_tree_add_subtree(msg_type_tree, packet_tvb, offset, -1, ett_sftp_attrs, NULL, NULL);
506
507
0
        int offset0 = offset;
508
0
        unsigned flags = tvb_get_ntohl(packet_tvb, offset) ;
509
0
        proto_tree_add_item(sftp_attrs_tree, hf_ssh_sftp_attrs_flags, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
510
0
        offset += 4;
511
0
        if(flags & SSH_FILEXFER_ATTR_SIZE){
512
0
                proto_tree_add_item(sftp_attrs_tree, hf_ssh_sftp_attrs_size, packet_tvb, offset, 8, ENC_BIG_ENDIAN);
513
0
                offset += 8;
514
0
        }
515
0
        if(flags & SSH_FILEXFER_ATTR_UIDGID){
516
0
                proto_tree_add_item(sftp_attrs_tree, hf_ssh_sftp_attrs_uid, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
517
0
                offset += 4;
518
0
        }
519
0
        if(flags & SSH_FILEXFER_ATTR_UIDGID){
520
0
            proto_tree_add_item(sftp_attrs_tree, hf_ssh_sftp_attrs_gid, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
521
0
            offset += 4;
522
0
        }
523
0
        if(flags & SSH_FILEXFER_ATTR_PERMISSIONS){
524
0
            proto_tree_add_item(sftp_attrs_tree, hf_ssh_sftp_attrs_permissions, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
525
0
            offset += 4;
526
0
        }
527
0
        if(flags & SSH_FILEXFER_ATTR_ACMODTIME){
528
0
            proto_tree_add_item(sftp_attrs_tree, hf_ssh_sftp_attrs_atime, packet_tvb, offset, 4, ENC_TIME_SECS|ENC_BIG_ENDIAN);
529
0
            offset += 4;
530
0
        }
531
0
        if(flags & SSH_FILEXFER_ATTR_ACMODTIME){
532
0
            proto_tree_add_item(sftp_attrs_tree, hf_ssh_sftp_attrs_mtime, packet_tvb, offset, 4, ENC_TIME_SECS|ENC_BIG_ENDIAN);
533
0
            offset += 4;
534
0
        }
535
0
        if(flags & SSH_FILEXFER_ATTR_EXTENDED){
536
0
            proto_tree_add_item(sftp_attrs_tree, hf_ssh_sftp_attrs_extended_count, packet_tvb, offset, 4, ENC_BIG_ENDIAN);
537
0
            offset += 4;
538
0
        }
539
540
0
        proto_item_set_text(sftp_attrs_tree, "%s", wmem_strbuf_get_str(title));
541
0
        proto_item_set_len(sftp_attrs_tree, offset - offset0);
542
543
0
        return offset - offset0;
544
0
}
545
546
void
547
proto_register_sftp(void)
548
16
{
549
16
    static hf_register_info hf[] = {
550
16
        { &hf_ssh_sftp_len,
551
16
          { "SFTP packet length", "sftp.packet_length",
552
16
            FT_UINT32, BASE_DEC, NULL, 0x0,
553
16
            NULL, HFILL }},
554
555
16
        { &hf_ssh_sftp_type,
556
16
          { "SFTP packet type", "sftp.packet_type",
557
16
            FT_UINT8, BASE_DEC, VALS(ssh2_sftp_vals), 0x0,
558
16
            NULL, HFILL }},
559
560
16
        { &hf_ssh_sftp_version,
561
16
          { "SFTP version", "sftp.version",
562
16
            FT_UINT32, BASE_DEC, NULL, 0x0,
563
16
            NULL, HFILL }},
564
565
16
        { &hf_ssh_sftp_id,
566
16
          { "SFTP id", "sftp.id",
567
16
            FT_UINT32, BASE_DEC, NULL, 0x0,
568
16
            NULL, HFILL }},
569
570
16
        { &hf_ssh_sftp_path_len,
571
16
          { "SFTP path length", "sftp.path_len",
572
16
            FT_UINT32, BASE_DEC, NULL, 0x0,
573
16
            NULL, HFILL }},
574
575
16
        { &hf_ssh_sftp_path,
576
16
          { "SFTP path", "sftp.path",
577
16
            FT_STRING, BASE_NONE, NULL, 0x0,
578
16
            NULL, HFILL }},
579
580
16
        { &hf_ssh_sftp_pflags,
581
16
          { "SFTP pflags", "sftp.pflags",
582
16
            FT_UINT32, BASE_HEX, NULL, 0x0,
583
16
            NULL, HFILL }},
584
585
16
        { &hf_ssh_sftp_name_count,
586
16
          { "SFTP count", "sftp.name_count",
587
16
            FT_UINT32, BASE_DEC, NULL, 0x0,
588
16
            NULL, HFILL }},
589
590
16
        { &hf_ssh_sftp_name_fn_len,
591
16
          { "SFTP name file name length", "sftp.name_fn_len",
592
16
            FT_UINT32, BASE_DEC, NULL, 0x0,
593
16
            NULL, HFILL }},
594
595
16
        { &hf_ssh_sftp_name_fn,
596
16
          { "SFTP name file name", "sftp.name_fn",
597
16
            FT_STRING, BASE_NONE, NULL, 0x0,
598
16
            NULL, HFILL }},
599
600
16
        { &hf_ssh_sftp_name_ln_len,
601
16
          { "SFTP name long name length", "sftp.name_ln_len",
602
16
            FT_UINT32, BASE_DEC, NULL, 0x0,
603
16
            NULL, HFILL }},
604
605
16
        { &hf_ssh_sftp_name_ln,
606
16
          { "SFTP name long name", "sftp.name_ln",
607
16
            FT_STRING, BASE_NONE, NULL, 0x0,
608
16
            NULL, HFILL }},
609
610
16
        { &hf_ssh_sftp_attrs_flags,
611
16
          { "SFTP attributes flags", "sftp.attrs.flags",
612
16
            FT_UINT32, BASE_DEC, NULL, 0x0,
613
16
            NULL, HFILL }},
614
615
16
        { &hf_ssh_sftp_attrs_size,
616
16
          { "SFTP attributes file size", "sftp.attrs.size",
617
16
            FT_UINT64, BASE_DEC, NULL, 0x0,
618
16
            NULL, HFILL }},
619
620
16
        { &hf_ssh_sftp_attrs_uid,
621
16
          { "SFTP attributes uid", "sftp.attrs.uid",
622
16
            FT_UINT32, BASE_DEC, NULL, 0x0,
623
16
            NULL, HFILL }},
624
625
16
        { &hf_ssh_sftp_attrs_gid,
626
16
          { "SFTP attributes gid", "sftp.attrs.gid",
627
16
            FT_UINT32, BASE_DEC, NULL, 0x0,
628
16
            NULL, HFILL }},
629
630
16
        { &hf_ssh_sftp_attrs_permissions,
631
16
          { "SFTP attributes permissions", "sftp.attrs.permissions",
632
16
            FT_UINT32, BASE_OCT, NULL, 0x0,
633
16
            NULL, HFILL }},
634
635
16
        { &hf_ssh_sftp_attrs_atime,
636
16
          { "SFTP attributes access time", "sftp.attrs.atime",
637
16
            FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
638
16
            NULL, HFILL }},
639
640
16
        { &hf_ssh_sftp_attrs_mtime,
641
16
          { "SFTP attributes modification time", "sftp.attrs.mtime",
642
16
            FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
643
16
            NULL, HFILL }},
644
645
16
        { &hf_ssh_sftp_attrs_extended_count,
646
16
          { "SFTP attributes extended count", "sftp.attrs.extended_count",
647
16
            FT_UINT32, BASE_DEC, NULL, 0x0,
648
16
            NULL, HFILL }},
649
650
16
        { &hf_ssh_sftp_offset,
651
16
          { "SFTP offset", "sftp.offset",
652
16
            FT_UINT64, BASE_DEC, NULL, 0x0,
653
16
            NULL, HFILL }},
654
655
16
        { &hf_ssh_sftp_length,
656
16
          { "SFTP length", "sftp.length",
657
16
            FT_UINT32, BASE_DEC, NULL, 0x0,
658
16
            NULL, HFILL }},
659
660
16
        { &hf_ssh_sftp_handle_len,
661
16
          { "SFTP handle length", "sftp.handle_len",
662
16
            FT_UINT32, BASE_DEC, NULL, 0x0,
663
16
            NULL, HFILL }},
664
665
16
        { &hf_ssh_sftp_handle,
666
16
          { "SFTP handle", "sftp.handle",
667
16
            FT_BYTES, BASE_NONE, NULL, 0x0,
668
16
            NULL, HFILL }},
669
670
16
        { &hf_ssh_sftp_status,
671
16
          { "SFTP error/status code", "sftp.status",
672
16
            FT_UINT32, BASE_DEC, NULL, 0x0,
673
16
            NULL, HFILL }},
674
675
16
        { &hf_ssh_sftp_error_message_len,
676
16
          { "SFTP error message length", "sftp.error_message_len",
677
16
            FT_UINT32, BASE_DEC, NULL, 0x0,
678
16
            NULL, HFILL }},
679
680
16
        { &hf_ssh_sftp_error_message,
681
16
          { "SFTP error message", "sftp.error_message",
682
16
            FT_STRING, BASE_NONE, NULL, 0x0,
683
16
            NULL, HFILL }},
684
685
16
        { &hf_ssh_sftp_data_len,
686
16
          { "SFTP data length", "sftp.data_len",
687
16
            FT_UINT32, BASE_DEC, NULL, 0x0,
688
16
            NULL, HFILL }},
689
690
16
        { &hf_ssh_sftp_data,
691
16
          { "SFTP data", "sftp.data",
692
16
            FT_BYTES, BASE_NONE, NULL, 0x0,
693
16
            NULL, HFILL }},
694
695
16
        { &hf_ssh_lang_tag_length,
696
16
          { "Language tag length", "sftp.lang_tag_length",
697
16
            FT_UINT32, BASE_DEC, NULL, 0x0,
698
16
            NULL, HFILL }},
699
700
16
        { &hf_ssh_lang_tag,
701
16
          { "Language tag", "sftp.lang_tag",
702
16
            FT_STRING, BASE_NONE, NULL, 0x0,
703
16
            NULL, HFILL }},
704
705
16
    };
706
707
16
    static int *ett[] = {
708
16
        &ett_sftp,
709
16
        &ett_sftp_attrs,
710
16
    };
711
712
16
    proto_sftp = proto_register_protocol("SSH File Transfer Protocol", "SFTP", "sftp");
713
16
    proto_register_field_array(proto_sftp, hf, array_length(hf));
714
16
    proto_register_subtree_array(ett, array_length(ett));
715
716
16
    sftp_handle = register_dissector("sftp", dissect_sftp, proto_sftp);
717
16
}