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