/src/wireshark/epan/dissectors/packet-pcnfsd.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* packet-pcnfsd.c |
2 | | * Routines for PCNFSD dissection |
3 | | * |
4 | | * Wireshark - Network traffic analyzer |
5 | | * By Gerald Combs <gerald@wireshark.org> |
6 | | * Copyright 1998 Gerald Combs |
7 | | * |
8 | | * Copied from packet-ypbind.c |
9 | | * |
10 | | * SPDX-License-Identifier: GPL-2.0-or-later |
11 | | */ |
12 | | |
13 | | |
14 | | /* |
15 | | Protocol information comes from the book |
16 | | "NFS Illustrated" by Brent Callaghan, ISBN 0-201-32570-5 |
17 | | */ |
18 | | |
19 | | |
20 | | #include "config.h" |
21 | | |
22 | | |
23 | | #include "packet-rpc.h" |
24 | | #include "packet-pcnfsd.h" |
25 | | |
26 | | void proto_register_pcnfsd(void); |
27 | | void proto_reg_handoff_pcnfsd(void); |
28 | | |
29 | | static int proto_pcnfsd; |
30 | | static int hf_pcnfsd_procedure_v1; |
31 | | static int hf_pcnfsd_procedure_v2; |
32 | | static int hf_pcnfsd_auth_client; |
33 | | static int hf_pcnfsd_auth_ident_obscure; |
34 | | static int hf_pcnfsd_auth_ident_clear; |
35 | | static int hf_pcnfsd_auth_password; |
36 | | static int hf_pcnfsd_auth_password_obscure; |
37 | | static int hf_pcnfsd_auth_password_clear; |
38 | | static int hf_pcnfsd_comment; |
39 | | static int hf_pcnfsd_status; |
40 | | static int hf_pcnfsd_uid; |
41 | | static int hf_pcnfsd_gid; |
42 | | static int hf_pcnfsd_gids_count; |
43 | | static int hf_pcnfsd_homedir; |
44 | | static int hf_pcnfsd_def_umask; |
45 | | static int hf_pcnfsd_mapreq; |
46 | | static int hf_pcnfsd_mapreq_status; |
47 | | static int hf_pcnfsd_username; |
48 | | |
49 | | |
50 | | static int ett_pcnfsd; |
51 | | static int ett_pcnfsd_auth_ident; |
52 | | static int ett_pcnfsd_auth_password; |
53 | | static int ett_pcnfsd_gids; |
54 | | |
55 | | static int |
56 | | dissect_pcnfsd_username(tvbuff_t *tvb, int offset, proto_tree *tree) |
57 | 0 | { |
58 | 0 | return dissect_rpc_string(tvb, tree, hf_pcnfsd_username, offset, NULL); |
59 | 0 | } |
60 | | |
61 | | #define MAP_REQ_UID 0 |
62 | | #define MAP_REQ_GID 1 |
63 | | #define MAP_REQ_UNAME 2 |
64 | | #define MAP_REQ_GNAME 3 |
65 | | |
66 | | static const value_string names_mapreq[] = |
67 | | { |
68 | | { MAP_REQ_UID, "MAP_REQ_UID" }, |
69 | | { MAP_REQ_GID, "MAP_REQ_GID" }, |
70 | | { MAP_REQ_UNAME, "MAP_REQ_UNAME" }, |
71 | | { MAP_REQ_GNAME, "MAP_REQ_GNAME" }, |
72 | | { 0, NULL } |
73 | | }; |
74 | | |
75 | | static int |
76 | | dissect_pcnfsd2_dissect_mapreq_arg_item(tvbuff_t *tvb, int offset, |
77 | | packet_info *pinfo _U_, proto_tree *tree, void* data _U_) |
78 | 0 | { |
79 | 0 | proto_tree_add_item(tree, hf_pcnfsd_mapreq, tvb, offset, 4, ENC_BIG_ENDIAN); |
80 | 0 | offset += 4; |
81 | |
|
82 | 0 | offset = dissect_rpc_uint32(tvb, tree, hf_pcnfsd_uid, offset); |
83 | |
|
84 | 0 | offset = dissect_pcnfsd_username(tvb, offset, tree); |
85 | |
|
86 | 0 | return offset; |
87 | 0 | } |
88 | | |
89 | | static int |
90 | | dissect_pcnfsd2_mapid_call(tvbuff_t *tvb, packet_info *pinfo, |
91 | | proto_tree *tree, void* data _U_) |
92 | 0 | { |
93 | 0 | int offset = 0; |
94 | 0 | offset = dissect_rpc_string(tvb, tree, hf_pcnfsd_comment, offset, NULL); |
95 | |
|
96 | 0 | offset = dissect_rpc_list(tvb, pinfo, tree, offset, |
97 | 0 | dissect_pcnfsd2_dissect_mapreq_arg_item, NULL); |
98 | |
|
99 | 0 | return offset; |
100 | 0 | } |
101 | | |
102 | | #define MAP_RES_OK 0 |
103 | | #define MAP_RES_UNKNOWN 1 |
104 | | #define MAP_RES_DENIED 2 |
105 | | |
106 | | static const value_string names_maprstat[] = |
107 | | { |
108 | | { MAP_RES_OK, "MAP_RES_OK" }, |
109 | | { MAP_RES_UNKNOWN, "MAP_RES_UNKNOWN" }, |
110 | | { MAP_RES_DENIED, "MAP_RES_DENIED" }, |
111 | | { 0, NULL } |
112 | | }; |
113 | | |
114 | | static int |
115 | | dissect_pcnfsd2_dissect_mapreq_res_item(tvbuff_t *tvb, int offset, |
116 | | packet_info *pinfo _U_, proto_tree *tree, void* data _U_) |
117 | 0 | { |
118 | 0 | proto_tree_add_item(tree, hf_pcnfsd_mapreq, tvb, offset, 4, ENC_BIG_ENDIAN); |
119 | 0 | offset += 4; |
120 | |
|
121 | 0 | proto_tree_add_item(tree, hf_pcnfsd_mapreq_status, tvb, offset, 4, ENC_BIG_ENDIAN); |
122 | 0 | offset += 4; |
123 | |
|
124 | 0 | offset = dissect_rpc_uint32(tvb, tree, hf_pcnfsd_uid, offset); |
125 | |
|
126 | 0 | offset = dissect_pcnfsd_username(tvb, offset, tree); |
127 | |
|
128 | 0 | return offset; |
129 | 0 | } |
130 | | |
131 | | static int |
132 | | dissect_pcnfsd2_mapid_reply(tvbuff_t *tvb, packet_info *pinfo, |
133 | | proto_tree *tree, void* data _U_) |
134 | 0 | { |
135 | 0 | int offset = 0; |
136 | 0 | offset = dissect_rpc_string(tvb, tree, hf_pcnfsd_comment, offset, NULL); |
137 | |
|
138 | 0 | offset = dissect_rpc_list(tvb, pinfo, tree, offset, |
139 | 0 | dissect_pcnfsd2_dissect_mapreq_res_item, NULL); |
140 | |
|
141 | 0 | return offset; |
142 | 0 | } |
143 | | |
144 | | /* "NFS Illustrated 14.7.13 */ |
145 | | static char * |
146 | | pcnfsd_decode_obscure(wmem_allocator_t *pool, const char* data, int len) |
147 | 0 | { |
148 | 0 | char *decoded_buf; |
149 | 0 | char *decoded_data; |
150 | |
|
151 | 0 | decoded_buf = (char *)wmem_alloc(pool, len); |
152 | 0 | decoded_data = decoded_buf; |
153 | 0 | for ( ; len>0 ; len--, data++, decoded_data++) { |
154 | 0 | *decoded_data = (*data ^ 0x5b) & 0x7f; |
155 | 0 | } |
156 | 0 | return decoded_buf; |
157 | 0 | } |
158 | | |
159 | | |
160 | | /* "NFS Illustrated" 14.7.13 */ |
161 | | static int |
162 | | dissect_pcnfsd2_auth_call(tvbuff_t *tvb, packet_info *pinfo, |
163 | | proto_tree *tree, void* data _U_) |
164 | 0 | { |
165 | 0 | int newoffset; |
166 | 0 | const char *ident = NULL; |
167 | 0 | const char *ident_decoded; |
168 | 0 | proto_item *ident_item; |
169 | 0 | proto_tree *ident_tree; |
170 | 0 | const char *password = NULL; |
171 | 0 | proto_item *password_item = NULL; |
172 | 0 | proto_tree *password_tree = NULL; |
173 | 0 | int offset = 0; |
174 | |
|
175 | 0 | offset = dissect_rpc_string(tvb, tree, |
176 | 0 | hf_pcnfsd_auth_client, offset, NULL); |
177 | |
|
178 | 0 | ident_tree = proto_tree_add_subtree(tree, tvb, |
179 | 0 | offset, -1, ett_pcnfsd_auth_ident, &ident_item, "Authentication Ident"); |
180 | |
|
181 | 0 | newoffset = dissect_rpc_string(tvb, ident_tree, |
182 | 0 | hf_pcnfsd_auth_ident_obscure, offset, &ident); |
183 | 0 | proto_item_set_len(ident_item, newoffset-offset); |
184 | |
|
185 | 0 | if (ident) { |
186 | | /* Only attempt to decode the ident if it has been specified */ |
187 | 0 | if (strcmp(ident, RPC_STRING_EMPTY) != 0) |
188 | 0 | ident_decoded = pcnfsd_decode_obscure(pinfo->pool, ident, (int)strlen(ident)); |
189 | 0 | else |
190 | 0 | ident_decoded = ident; |
191 | |
|
192 | 0 | if (ident_tree) |
193 | 0 | proto_tree_add_string(ident_tree, |
194 | 0 | hf_pcnfsd_auth_ident_clear, |
195 | 0 | tvb, offset+4, (int)strlen(ident_decoded), ident_decoded); |
196 | 0 | } |
197 | 0 | if (ident_item) { |
198 | 0 | proto_item_set_text(ident_item, "Authentication Ident: %s", |
199 | 0 | ident); |
200 | 0 | } |
201 | |
|
202 | 0 | offset = newoffset; |
203 | |
|
204 | 0 | password_item = proto_tree_add_string_format(tree, hf_pcnfsd_auth_password, |
205 | 0 | tvb, 0, 0, "", "Authentication Password"); |
206 | 0 | password_tree = proto_item_add_subtree(password_item, ett_pcnfsd_auth_password); |
207 | |
|
208 | 0 | newoffset = dissect_rpc_string(tvb, password_tree, |
209 | 0 | hf_pcnfsd_auth_password_obscure, offset, &password); |
210 | 0 | if (password_item) { |
211 | 0 | proto_item_set_len(password_item, newoffset-offset); |
212 | 0 | } |
213 | |
|
214 | 0 | if (password) { |
215 | | /* Only attempt to decode the password if it has been specified */ |
216 | 0 | if (strcmp(password, RPC_STRING_EMPTY)) |
217 | 0 | pcnfsd_decode_obscure(pinfo->pool, password, (int)strlen(password)); |
218 | |
|
219 | 0 | if (password_tree) |
220 | 0 | proto_tree_add_string(password_tree, |
221 | 0 | hf_pcnfsd_auth_password_clear, |
222 | 0 | tvb, offset+4, (int)strlen(password), password); |
223 | 0 | } |
224 | 0 | if (password_item) { |
225 | 0 | proto_item_set_text(password_item, "Authentication Password: %s", |
226 | 0 | password); |
227 | 0 | } |
228 | |
|
229 | 0 | offset = newoffset; |
230 | |
|
231 | 0 | offset = dissect_rpc_string(tvb, tree, |
232 | 0 | hf_pcnfsd_comment, offset, NULL); |
233 | |
|
234 | 0 | return offset; |
235 | 0 | } |
236 | | |
237 | | |
238 | | /* "NFS Illustrated" 14.7.13 */ |
239 | | static int |
240 | | dissect_pcnfsd2_auth_reply(tvbuff_t *tvb, packet_info *pinfo _U_, |
241 | | proto_tree *tree, void* data _U_) |
242 | 0 | { |
243 | 0 | int gids_count; |
244 | 0 | proto_tree *gtree; |
245 | 0 | int gids_i; |
246 | 0 | int offset = 0; |
247 | |
|
248 | 0 | offset = dissect_rpc_uint32(tvb, tree, hf_pcnfsd_status, offset); |
249 | 0 | offset = dissect_rpc_uint32(tvb, tree, hf_pcnfsd_uid, offset); |
250 | 0 | offset = dissect_rpc_uint32(tvb, tree, hf_pcnfsd_gid, offset); |
251 | 0 | gids_count = tvb_get_ntohl(tvb,offset+0); |
252 | 0 | gtree = proto_tree_add_subtree_format(tree, tvb, |
253 | 0 | offset, 4+gids_count*4, ett_pcnfsd_gids, NULL, "Group IDs: %d", gids_count); |
254 | |
|
255 | 0 | proto_tree_add_item(gtree, hf_pcnfsd_gids_count, tvb, offset, 4, ENC_BIG_ENDIAN); |
256 | |
|
257 | 0 | offset += 4; |
258 | 0 | for (gids_i = 0 ; gids_i < gids_count ; gids_i++) { |
259 | 0 | offset = dissect_rpc_uint32(tvb, gtree, |
260 | 0 | hf_pcnfsd_gid, offset); |
261 | 0 | } |
262 | 0 | offset = dissect_rpc_string(tvb, tree, |
263 | 0 | hf_pcnfsd_homedir, offset, NULL); |
264 | | /* should be signed int32 */ |
265 | 0 | offset = dissect_rpc_uint32(tvb, tree, hf_pcnfsd_def_umask, offset); |
266 | 0 | offset = dissect_rpc_string(tvb, tree, |
267 | 0 | hf_pcnfsd_comment, offset, NULL); |
268 | |
|
269 | 0 | return offset; |
270 | 0 | } |
271 | | |
272 | | |
273 | | /* "NFS Illustrated", 14.6 */ |
274 | | /* proc number, "proc name", dissect_request, dissect_reply */ |
275 | | static const vsff pcnfsd1_proc[] = { |
276 | | { 0, "NULL", dissect_rpc_void, dissect_rpc_void }, |
277 | | { 1, "AUTH", dissect_rpc_unknown, dissect_rpc_unknown }, |
278 | | { 2, "PR_INIT", dissect_rpc_unknown, dissect_rpc_unknown }, |
279 | | { 3, "PR_START", dissect_rpc_unknown, dissect_rpc_unknown }, |
280 | | { 0, NULL, NULL, NULL } |
281 | | }; |
282 | | static const value_string pcnfsd1_proc_vals[] = { |
283 | | { 0, "NULL" }, |
284 | | { 1, "AUTH" }, |
285 | | { 2, "PR_INIT" }, |
286 | | { 3, "PR_START" }, |
287 | | { 0, NULL } |
288 | | }; |
289 | | /* end of PCNFS version 1 */ |
290 | | |
291 | | |
292 | | /* "NFS Illustrated", 14.7 */ |
293 | | static const vsff pcnfsd2_proc[] = { |
294 | | { 0, "NULL", |
295 | | dissect_rpc_void, dissect_rpc_void }, |
296 | | { 1, "INFO", dissect_rpc_unknown, dissect_rpc_unknown }, |
297 | | { 2, "PR_INIT", dissect_rpc_unknown, dissect_rpc_unknown }, |
298 | | { 3, "PR_START", dissect_rpc_unknown, dissect_rpc_unknown }, |
299 | | { 4, "PR_LIST", dissect_rpc_unknown, dissect_rpc_unknown }, |
300 | | { 5, "PR_QUEUE", dissect_rpc_unknown, dissect_rpc_unknown }, |
301 | | { 6, "PR_STATUS", dissect_rpc_unknown, dissect_rpc_unknown }, |
302 | | { 7, "PR_CANCEL", dissect_rpc_unknown, dissect_rpc_unknown }, |
303 | | { 8, "PR_ADMIN", dissect_rpc_unknown, dissect_rpc_unknown }, |
304 | | { 9, "PR_REQUEUE", dissect_rpc_unknown, dissect_rpc_unknown }, |
305 | | { 10, "PR_HOLD", dissect_rpc_unknown, dissect_rpc_unknown }, |
306 | | { 11, "PR_RELEASE", dissect_rpc_unknown, dissect_rpc_unknown }, |
307 | | { 12, "MAPID", |
308 | | dissect_pcnfsd2_mapid_call, dissect_pcnfsd2_mapid_reply }, |
309 | | { 13, "AUTH", |
310 | | dissect_pcnfsd2_auth_call, dissect_pcnfsd2_auth_reply }, |
311 | | { 14, "ALERT", dissect_rpc_unknown, dissect_rpc_unknown }, |
312 | | { 0, NULL, NULL, NULL } |
313 | | }; |
314 | | static const value_string pcnfsd2_proc_vals[] = { |
315 | | { 0, "NULL" }, |
316 | | { 1, "INFO" }, |
317 | | { 2, "PR_INIT" }, |
318 | | { 3, "PR_START" }, |
319 | | { 4, "PR_LIST" }, |
320 | | { 5, "PR_QUEUE" }, |
321 | | { 6, "PR_STATUS" }, |
322 | | { 7, "PR_CANCEL" }, |
323 | | { 8, "PR_ADMIN" }, |
324 | | { 9, "PR_REQUEUE" }, |
325 | | { 10, "PR_HOLD" }, |
326 | | { 11, "PR_RELEASE" }, |
327 | | { 12, "MAPID" }, |
328 | | { 13, "AUTH" }, |
329 | | { 14, "ALERT" }, |
330 | | { 0, NULL } |
331 | | }; |
332 | | /* end of PCNFS version 2 */ |
333 | | |
334 | | static const rpc_prog_vers_info pcnfsd_vers_info[] = { |
335 | | { 1, pcnfsd1_proc, &hf_pcnfsd_procedure_v1 }, |
336 | | { 2, pcnfsd2_proc, &hf_pcnfsd_procedure_v2 }, |
337 | | }; |
338 | | |
339 | | void |
340 | | proto_register_pcnfsd(void) |
341 | 14 | { |
342 | 14 | static hf_register_info hf[] = { |
343 | 14 | { &hf_pcnfsd_procedure_v1, { |
344 | 14 | "V1 Procedure", "pcnfsd.procedure_v1", FT_UINT32, BASE_DEC, |
345 | 14 | VALS(pcnfsd1_proc_vals), 0, NULL, HFILL }}, |
346 | 14 | { &hf_pcnfsd_procedure_v2, { |
347 | 14 | "V2 Procedure", "pcnfsd.procedure_v2", FT_UINT32, BASE_DEC, |
348 | 14 | VALS(pcnfsd2_proc_vals), 0, NULL, HFILL }}, |
349 | 14 | { &hf_pcnfsd_auth_client, { |
350 | 14 | "Authentication Client", "pcnfsd.auth.client", FT_STRING, BASE_NONE, |
351 | 14 | NULL, 0, NULL, HFILL }}, |
352 | 14 | { &hf_pcnfsd_auth_ident_obscure, { |
353 | 14 | "Obscure Ident", "pcnfsd.auth.ident.obscure", FT_STRING, BASE_NONE, |
354 | 14 | NULL, 0, "Authentication Obscure Ident", HFILL }}, |
355 | 14 | { &hf_pcnfsd_auth_ident_clear, { |
356 | 14 | "Clear Ident", "pcnfsd.auth.ident.clear", FT_STRING, BASE_NONE, |
357 | 14 | NULL, 0, "Authentication Clear Ident", HFILL }}, |
358 | 14 | { &hf_pcnfsd_auth_password, { |
359 | 14 | "Password", "pcnfsd.auth.password", FT_STRING, BASE_NONE, |
360 | 14 | NULL, 0, NULL, HFILL }}, |
361 | 14 | { &hf_pcnfsd_auth_password_obscure, { |
362 | 14 | "Obscure Password", "pcnfsd.auth.password.obscure", FT_STRING, BASE_NONE, |
363 | 14 | NULL, 0, "Authentication Obscure Password", HFILL }}, |
364 | 14 | { &hf_pcnfsd_auth_password_clear, { |
365 | 14 | "Clear Password", "pcnfsd.auth.password.clear", FT_STRING, BASE_NONE, |
366 | 14 | NULL, 0, "Authentication Clear Password", HFILL }}, |
367 | 14 | { &hf_pcnfsd_comment, { |
368 | 14 | "Comment", "pcnfsd.comment", FT_STRING, BASE_NONE, |
369 | 14 | NULL, 0, NULL, HFILL }}, |
370 | 14 | { &hf_pcnfsd_status, { |
371 | 14 | "Reply Status", "pcnfsd.status", FT_UINT32, BASE_DEC, |
372 | 14 | NULL, 0, NULL, HFILL }}, |
373 | 14 | { &hf_pcnfsd_uid, { |
374 | 14 | "User ID", "pcnfsd.uid", FT_UINT32, BASE_DEC, |
375 | 14 | NULL, 0, NULL, HFILL }}, |
376 | 14 | { &hf_pcnfsd_gid, { |
377 | 14 | "Group ID", "pcnfsd.gid", FT_UINT32, BASE_DEC, |
378 | 14 | NULL, 0, NULL, HFILL }}, |
379 | 14 | { &hf_pcnfsd_gids_count, { |
380 | 14 | "Group ID Count", "pcnfsd.gids.count", FT_UINT32, BASE_DEC, |
381 | 14 | NULL, 0, NULL, HFILL }}, |
382 | 14 | { &hf_pcnfsd_homedir, { |
383 | 14 | "Home Directory", "pcnfsd.homedir", FT_STRING, BASE_NONE, |
384 | 14 | NULL, 0, NULL, HFILL }}, |
385 | 14 | { &hf_pcnfsd_def_umask, { |
386 | 14 | "def_umask", "pcnfsd.def_umask", FT_UINT32, BASE_OCT, |
387 | 14 | NULL, 0, NULL, HFILL }}, |
388 | 14 | { &hf_pcnfsd_mapreq, { |
389 | 14 | "Request", "pcnfsd.mapreq", FT_UINT32, BASE_DEC, |
390 | 14 | VALS(names_mapreq), 0, NULL, HFILL }}, |
391 | 14 | { &hf_pcnfsd_mapreq_status, { |
392 | 14 | "Status", "pcnfsd.mapreq_status", FT_UINT32, BASE_DEC, |
393 | 14 | VALS(names_maprstat), 0, NULL, HFILL }}, |
394 | 14 | { &hf_pcnfsd_username, { |
395 | 14 | "User name", "pcnfsd.username", FT_STRING, BASE_NONE, |
396 | 14 | NULL, 0, "pcnfsd.username", HFILL }}, |
397 | 14 | }; |
398 | | |
399 | 14 | static int *ett[] = { |
400 | 14 | &ett_pcnfsd, |
401 | 14 | &ett_pcnfsd_auth_ident, |
402 | 14 | &ett_pcnfsd_auth_password, |
403 | 14 | &ett_pcnfsd_gids |
404 | 14 | }; |
405 | | |
406 | 14 | proto_pcnfsd = proto_register_protocol("PC NFS", "PCNFSD", "pcnfsd"); |
407 | 14 | proto_register_field_array(proto_pcnfsd, hf, array_length(hf)); |
408 | 14 | proto_register_subtree_array(ett, array_length(ett)); |
409 | 14 | } |
410 | | |
411 | | void |
412 | | proto_reg_handoff_pcnfsd(void) |
413 | 14 | { |
414 | | /* Register the protocol as RPC */ |
415 | 14 | rpc_init_prog(proto_pcnfsd, PCNFSD_PROGRAM, ett_pcnfsd, |
416 | 14 | G_N_ELEMENTS(pcnfsd_vers_info), pcnfsd_vers_info); |
417 | 14 | } |
418 | | |
419 | | /* |
420 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
421 | | * |
422 | | * Local variables: |
423 | | * c-basic-offset: 4 |
424 | | * tab-width: 8 |
425 | | * indent-tabs-mode: nil |
426 | | * End: |
427 | | * |
428 | | * vi: set shiftwidth=4 tabstop=8 expandtab: |
429 | | * :indentSize=4:tabSize=8:noTabs=true: |
430 | | */ |