/src/wireshark/epan/dissectors/packet-dcom.c
Line | Count | Source |
1 | | /* packet-dcom.c |
2 | | * Routines for DCOM generics |
3 | | * |
4 | | * Wireshark - Network traffic analyzer |
5 | | * By Gerald Combs <gerald@wireshark.org> |
6 | | * Copyright 1998 Gerald Combs |
7 | | * |
8 | | * SPDX-License-Identifier: GPL-2.0-or-later |
9 | | */ |
10 | | |
11 | | /* A few words about DCOM: |
12 | | * |
13 | | * DCOM uses DCERPC as its underlying "transport" protocol. |
14 | | * |
15 | | * The DCOM dissectors are called by DCERPC request and response calls. |
16 | | * DCOM uses a small header after the DCERPC calls. |
17 | | * (for a DCERPC request call it's called "this", |
18 | | * for a DCERPC response call it's called "that") |
19 | | * |
20 | | * DCOM defines itself some interfaces: oxid, remact, remunk and others |
21 | | * |
22 | | * Implemented is currently "only" a static dissection of packet fields |
23 | | * (no "object recognition" included) |
24 | | * |
25 | | * User's of DCOM can define their own interface's using Microsoft IDL. |
26 | | * |
27 | | * Hint: The registered DCOM interface names can be found in the |
28 | | * windows registry at: "HKEY_CLASSES_ROOT\Interface" |
29 | | * |
30 | | * |
31 | | * Resources on the web: |
32 | | * |
33 | | * "Understanding the DCOM Wire Protocol by Analyzing Network Data Packets" |
34 | | * http:// www.microsoft.com/msj/0398/dcom.htm |
35 | | * |
36 | | * "Distributed Component Object Model Protocol -- DCOM/1.0" |
37 | | * http://www.microsoft.com/com/resources/specs.asp (link is currently down) |
38 | | * |
39 | | */ |
40 | | |
41 | | /* Files involved dissecting DCOM: |
42 | | * |
43 | | * packet-dcom.c: generic DCOM things (this, that, ...) and |
44 | | * generic DCOM datatype (DWORD, VARIANT, ...) |
45 | | * |
46 | | * DCOM common Interfaces: |
47 | | * packet-dcom-oxid.c: IOXIDResolver |
48 | | * packet-dcom-remact.c: IRemoteActivation |
49 | | * packet-dcom-remunk.c: IRemUnknown, IRemUnknown2 |
50 | | * packet-dcom-dispatch.c: IDispatch |
51 | | * packet-dcom-sysact.c: ISystemActivator |
52 | | * packet-dcom-typeinfo.c: ITypeInfo |
53 | | */ |
54 | | |
55 | | #include "config.h" |
56 | | |
57 | | #include <epan/packet.h> |
58 | | #include <epan/addr_resolv.h> |
59 | | #include <epan/expert.h> |
60 | | #include <epan/tfs.h> |
61 | | #include <epan/prefs.h> |
62 | | |
63 | | #include <wsutil/ws_roundup.h> |
64 | | |
65 | | #include "packet-dcerpc.h" |
66 | | #include "packet-dcom.h" |
67 | | |
68 | | void proto_register_dcom (void); |
69 | | void proto_reg_handoff_dcom (void); |
70 | | |
71 | | static int proto_dcom; |
72 | | |
73 | | bool dcom_prefs_display_unmarshalling_details; |
74 | | |
75 | | |
76 | | static int ett_dcom_this; |
77 | | /* static int hf_dcom_this_version_major; */ |
78 | | /* static int hf_dcom_this_version_minor; */ |
79 | | static int hf_dcom_this_flags; |
80 | | static int hf_dcom_this_res; |
81 | | static int hf_dcom_this_cid; |
82 | | |
83 | | static int ett_dcom_that; |
84 | | static int hf_dcom_that_flags; |
85 | | |
86 | | static int ett_dcom_extent; |
87 | | static int hf_dcom_extent; |
88 | | static int hf_dcom_extent_array_count; |
89 | | static int hf_dcom_extent_array_res; |
90 | | static int hf_dcom_extent_size; |
91 | | static int hf_dcom_extent_id; |
92 | | |
93 | | static int hf_dcom_hresult; |
94 | | static int hf_dcom_tobedone; |
95 | | static int hf_dcom_nospec; |
96 | | static int hf_dcom_array_size; |
97 | | static int hf_dcom_pointer_val; |
98 | | |
99 | | /* COMVERSION */ |
100 | | static int hf_dcom_version_major; |
101 | | static int hf_dcom_version_minor; |
102 | | |
103 | | static int ett_dcom_lpwstr; |
104 | | static int hf_dcom_max_count; |
105 | | static int hf_dcom_offset; |
106 | | static int hf_dcom_byte_length; |
107 | | /* static int hf_dcom_actual_count; */ |
108 | | |
109 | | static int ett_dcom_objref; |
110 | | static int hf_dcom_objref; |
111 | | static int hf_dcom_objref_signature; |
112 | | static int hf_dcom_objref_flags; |
113 | | int hf_dcom_iid; |
114 | | int hf_dcom_clsid; |
115 | | static int hf_dcom_objref_resolver_address; |
116 | | static int hf_dcom_objref_cbextension; |
117 | | static int hf_dcom_objref_size; |
118 | | |
119 | | static int ett_dcom_stdobjref; |
120 | | static int hf_dcom_stdobjref; |
121 | | static int hf_dcom_stdobjref_flags; |
122 | | static int hf_dcom_stdobjref_public_refs; |
123 | | int hf_dcom_oxid; |
124 | | int hf_dcom_oid; |
125 | | int hf_dcom_ipid; |
126 | | |
127 | | |
128 | | static int ett_dcom_custobjref; |
129 | | static int hf_dcom_custobjref; |
130 | | |
131 | | static int ett_dcom_dualstringarray; |
132 | | static int ett_dcom_dualstringarray_binding; |
133 | | static int hf_dcom_dualstringarray_num_entries; |
134 | | static int hf_dcom_dualstringarray_security_offset; |
135 | | static int hf_dcom_dualstringarray_string; |
136 | | static int hf_dcom_dualstringarray_string_network_addr; |
137 | | static int hf_dcom_dualstringarray_string_tower_id; |
138 | | static int hf_dcom_dualstringarray_security; |
139 | | static int hf_dcom_dualstringarray_security_authn_svc; |
140 | | static int hf_dcom_dualstringarray_security_authz_svc; |
141 | | static int hf_dcom_dualstringarray_security_princ_name; |
142 | | |
143 | | static int ett_dcom_interface_pointer; |
144 | | static int hf_dcom_interface_pointer; |
145 | | static int hf_dcom_ip_cnt_data; |
146 | | |
147 | | static int ett_dcom_safearray; |
148 | | static int hf_dcom_safearray; |
149 | | static int hf_dcom_sa_dims32; |
150 | | static int hf_dcom_sa_dims16; |
151 | | static int hf_dcom_sa_features; |
152 | | static int hf_dcom_sa_element_size; |
153 | | static int hf_dcom_sa_locks; |
154 | | static int hf_dcom_sa_vartype32; |
155 | | static int hf_dcom_sa_vartype16; |
156 | | static int hf_dcom_sa_elements; |
157 | | static int hf_dcom_sa_bound_elements; |
158 | | static int hf_dcom_sa_low_bound; |
159 | | |
160 | | static int ett_dcom_sa_features; |
161 | | static int hf_dcom_sa_features_auto; |
162 | | static int hf_dcom_sa_features_static; |
163 | | static int hf_dcom_sa_features_embedded; |
164 | | static int hf_dcom_sa_features_fixedsize; |
165 | | static int hf_dcom_sa_features_record; |
166 | | static int hf_dcom_sa_features_have_iid; |
167 | | static int hf_dcom_sa_features_have_vartype; |
168 | | static int hf_dcom_sa_features_bstr; |
169 | | static int hf_dcom_sa_features_unknown; |
170 | | static int hf_dcom_sa_features_dispatch; |
171 | | static int hf_dcom_sa_features_variant; |
172 | | |
173 | | static int ett_dcom_variant; |
174 | | /* static int hf_dcom_variant; */ |
175 | | static int hf_dcom_variant_type; |
176 | | static int hf_dcom_variant_size; |
177 | | static int hf_dcom_variant_rpc_res; |
178 | | static int hf_dcom_variant_wres; |
179 | | static int hf_dcom_variant_type32; |
180 | | |
181 | | static int hf_dcom_vt_bool; |
182 | | static int hf_dcom_vt_i1; |
183 | | static int hf_dcom_vt_i2; |
184 | | static int hf_dcom_vt_i4; |
185 | | static int hf_dcom_vt_i8; /* only inside a SAFEARRAY, not in VARIANTs */ |
186 | | static int hf_dcom_vt_cy; |
187 | | static int hf_dcom_vt_ui1; |
188 | | static int hf_dcom_vt_ui2; |
189 | | static int hf_dcom_vt_ui4; |
190 | | static int hf_dcom_vt_ui8; |
191 | | static int hf_dcom_vt_r4; |
192 | | static int hf_dcom_vt_r8; |
193 | | static int hf_dcom_vt_date; |
194 | | static int hf_dcom_vt_bstr; |
195 | | static int hf_dcom_vt_byref; |
196 | | static int hf_dcom_vt_dispatch; |
197 | | |
198 | | static expert_field ei_dcom_dissection_incomplete; |
199 | | static expert_field ei_dcom_no_spec; |
200 | | static expert_field ei_dcom_hresult_expert; |
201 | | static expert_field ei_dcom_dualstringarray_mult_ip; |
202 | | |
203 | | /* this/that extension UUIDs */ |
204 | | static e_guid_t uuid_debug_ext = { 0xf1f19680, 0x4d2a, 0x11ce, { 0xa6, 0x6a, 0x00, 0x20, 0xaf, 0x6e, 0x72, 0xf4} }; |
205 | | static e_guid_t uuid_ext_error_ext ={ 0xf1f19681, 0x4d2a, 0x11ce, { 0xa6, 0x6a, 0x00, 0x20, 0xaf, 0x6e, 0x72, 0xf4} }; |
206 | | |
207 | | /* general DCOM UUIDs */ |
208 | | static const e_guid_t ipid_rem_unknown = { 0x00000131, 0x1234, 0x5678, { 0xCA, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} }; |
209 | | static const e_guid_t iid_unknown = { 0x00000000, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} }; |
210 | | static const e_guid_t uuid_null = { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }; |
211 | | static const e_guid_t iid_class_factory = { 0x00000001, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} }; |
212 | | static const e_guid_t iid_type_info = { 0x00020401, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} }; |
213 | | static const e_guid_t iid_provide_class_info = { 0xb196b283, 0xbab4, 0x101a, { 0xB6, 0x9C, 0x00, 0xAA, 0x00, 0x34, 0x1D, 0x07} }; |
214 | | #if 0 |
215 | | static const e_guid_t iid_act_prop_in = { 0x000001A2, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} }; |
216 | | static const e_guid_t iid_act_prop_out = { 0x000001A3, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} }; |
217 | | #endif |
218 | | |
219 | | static GList *dcom_machines; |
220 | | static GList *dcom_interfaces; |
221 | | static GList *dcom_marshalers; |
222 | | |
223 | | static const value_string dcom_thisthat_flag_vals[] = { |
224 | | { 0, "INFO_NULL" }, |
225 | | { 1, "INFO_LOCAL" }, |
226 | | { 0, NULL } |
227 | | }; |
228 | | |
229 | | #if 0 |
230 | | static const value_string dcom_boolean_flag_vals[] = { |
231 | | { 0x00000001, "TRUE" }, |
232 | | { 0x00000000, "FALSE" }, |
233 | | { 0, NULL } |
234 | | }; |
235 | | #endif |
236 | | |
237 | | #ifdef DEBUG |
238 | | void dcom_interface_dump(void) { |
239 | | dcom_machine_t *machine; |
240 | | dcom_object_t *object; |
241 | | dcom_interface_t *interf; |
242 | | GList *machines; |
243 | | GList *objects; |
244 | | GList *interfaces; |
245 | | |
246 | | |
247 | | for(machines = dcom_machines; machines != NULL; machines = g_list_next(machines)) { |
248 | | machine = (dcom_machine_t *)machines->data; |
249 | | /*ws_warning("Machine(#%4u): IP:%s", machine->first_packet, address_to_str(pinfo->pool, &machine->ip));*/ |
250 | | |
251 | | for(objects = machine->objects; objects != NULL; objects = g_list_next(objects)) { |
252 | | object = (dcom_object_t *)objects->data; |
253 | | /*ws_warning(" Object(#%4u): OID:0x%" PRIx64 " private:%p", object->first_packet, object->oid, object->private_data);*/ |
254 | | |
255 | | for(interfaces = object->interfaces; interfaces != NULL; interfaces = g_list_next(interfaces)) { |
256 | | interf = (dcom_interface_t *)interfaces->data; |
257 | | /*ws_warning(" Interface(#%4u): iid:%s", |
258 | | interf->first_packet, guids_resolve_guid_to_str(&interf->iid)); |
259 | | ws_warning(" ipid:%s", guids_resolve_guid_to_str(&interf->ipid));*/ |
260 | | } |
261 | | } |
262 | | } |
263 | | } |
264 | | #endif |
265 | | |
266 | | dcom_interface_t *dcom_interface_find(packet_info *pinfo _U_, const address *addr _U_, e_guid_t *ipid) |
267 | 0 | { |
268 | 0 | dcom_interface_t *interf; |
269 | 0 | GList *interfaces; |
270 | | |
271 | |
|
272 | 0 | if(memcmp(ipid, &uuid_null, sizeof(uuid_null)) == 0) |
273 | 0 | { |
274 | 0 | return NULL; |
275 | 0 | } |
276 | | |
277 | 0 | for(interfaces = dcom_interfaces; interfaces != NULL; interfaces = g_list_next(interfaces)) { |
278 | 0 | interf = (dcom_interface_t *)interfaces->data; |
279 | |
|
280 | 0 | if(memcmp(&interf->ipid, ipid, sizeof(e_guid_t)) == 0) { |
281 | 0 | return interf; |
282 | 0 | } |
283 | 0 | } |
284 | | |
285 | 0 | return NULL; |
286 | 0 | } |
287 | | |
288 | | |
289 | | dcom_interface_t *dcom_interface_new(packet_info *pinfo, const address *addr, e_guid_t *iid, uint64_t oxid, uint64_t oid, e_guid_t *ipid) |
290 | 0 | { |
291 | 0 | GList *dcom_iter; |
292 | 0 | dcom_machine_t *machine; |
293 | 0 | dcom_object_t *object; |
294 | 0 | dcom_interface_t *interf; |
295 | | |
296 | |
|
297 | 0 | if( memcmp(iid, &uuid_null, sizeof(uuid_null)) == 0 || |
298 | 0 | memcmp(ipid, &uuid_null, sizeof(uuid_null)) == 0) |
299 | 0 | { |
300 | 0 | return NULL; |
301 | 0 | } |
302 | | |
303 | 0 | if(oxid == 0 || oid == 0) { |
304 | | /*ws_warning("interface_new#%u", pinfo->num);*/ |
305 | |
|
306 | 0 | interf = wmem_new(wmem_file_scope(), dcom_interface_t); |
307 | 0 | interf->parent = NULL; |
308 | 0 | interf->private_data = NULL; |
309 | 0 | interf->first_packet = pinfo->num; |
310 | 0 | interf->iid = *iid; |
311 | 0 | interf->ipid = *ipid; |
312 | |
|
313 | 0 | dcom_interfaces = g_list_append(dcom_interfaces, interf); |
314 | 0 | return interf; |
315 | 0 | } |
316 | | |
317 | | /* find machine */ |
318 | 0 | dcom_iter = dcom_machines; |
319 | 0 | while(dcom_iter != NULL) { |
320 | 0 | machine = (dcom_machine_t *)dcom_iter->data; |
321 | 0 | if(cmp_address(&machine->ip, addr) == 0) { |
322 | 0 | break; |
323 | 0 | } |
324 | 0 | dcom_iter = g_list_next(dcom_iter); |
325 | 0 | } |
326 | | |
327 | | /* create new machine if not found */ |
328 | 0 | if(dcom_iter == NULL) { |
329 | 0 | machine = g_new(dcom_machine_t,1); |
330 | 0 | copy_address(&machine->ip, addr); |
331 | 0 | machine->objects = NULL; |
332 | 0 | machine->first_packet = pinfo->num; |
333 | 0 | dcom_machines = g_list_append(dcom_machines, machine); |
334 | 0 | } |
335 | | |
336 | | /* find object */ |
337 | 0 | dcom_iter = machine->objects; |
338 | 0 | while(dcom_iter != NULL) { |
339 | 0 | object = (dcom_object_t *)dcom_iter->data; |
340 | 0 | if(object->oid == oid) { |
341 | 0 | break; |
342 | 0 | } |
343 | 0 | dcom_iter = g_list_next(dcom_iter); |
344 | 0 | } |
345 | | |
346 | | /* create new object if not found */ |
347 | 0 | if(dcom_iter == NULL) { |
348 | 0 | object = g_new(dcom_object_t,1); |
349 | 0 | object->parent = machine; |
350 | 0 | object->interfaces = NULL; |
351 | 0 | object->private_data = NULL; |
352 | 0 | object->first_packet = pinfo->num; |
353 | 0 | object->oid = oid; |
354 | 0 | object->oxid = oxid; |
355 | |
|
356 | 0 | machine->objects = g_list_append(machine->objects, object); |
357 | 0 | } |
358 | | |
359 | | /* find interface */ |
360 | 0 | dcom_iter = object->interfaces; |
361 | 0 | while(dcom_iter != NULL) { |
362 | 0 | interf = (dcom_interface_t *)dcom_iter->data; |
363 | 0 | if(memcmp(&interf->ipid, ipid, sizeof(e_guid_t)) == 0) { |
364 | 0 | break; |
365 | 0 | } |
366 | 0 | dcom_iter = g_list_next(dcom_iter); |
367 | 0 | } |
368 | | |
369 | | /* create new interface if not found */ |
370 | 0 | if(dcom_iter == NULL) { |
371 | 0 | interf = g_new(dcom_interface_t,1); |
372 | 0 | interf->parent = object; |
373 | 0 | interf->private_data = NULL; |
374 | 0 | interf->first_packet = pinfo->num; |
375 | 0 | interf->iid = *iid; |
376 | 0 | interf->ipid = *ipid; |
377 | |
|
378 | 0 | object->interfaces = g_list_append(object->interfaces, interf); |
379 | 0 | dcom_interfaces = g_list_append(dcom_interfaces, interf); |
380 | 0 | } |
381 | |
|
382 | 0 | return interf; |
383 | 0 | } |
384 | | |
385 | | |
386 | | /* |
387 | | * Flag bits in connection-oriented PDU header. |
388 | | */ |
389 | 14 | #define WIRESHARK_FADF_AUTO 0x0001 |
390 | 14 | #define WIRESHARK_FADF_STATIC 0x0002 |
391 | 14 | #define WIRESHARK_FADF_EMBEDDED 0x0004 |
392 | 14 | #define WIRESHARK_FADF_FIXEDSIZE 0x0010 |
393 | 14 | #define WIRESHARK_FADF_RECORD 0x0020 |
394 | 14 | #define WIRESHARK_FADF_HAVEIID 0x0040 |
395 | 14 | #define WIRESHARK_FADF_HAVEVARTYPE 0x0080 |
396 | 14 | #define WIRESHARK_FADF_BSTR 0x0100 |
397 | 14 | #define WIRESHARK_FADF_UNKNOWN 0x0200 |
398 | 14 | #define WIRESHARK_FADF_DISPATCH 0x0400 |
399 | 14 | #define WIRESHARK_FADF_VARIANT 0x0800 |
400 | | |
401 | | |
402 | | typedef enum { |
403 | | WIRESHARK_VT_EMPTY = 0, |
404 | | WIRESHARK_VT_NULL = 1, |
405 | | WIRESHARK_VT_I2 = 2, |
406 | | WIRESHARK_VT_I4 = 3, |
407 | | WIRESHARK_VT_R4 = 4, |
408 | | WIRESHARK_VT_R8 = 5, |
409 | | WIRESHARK_VT_CY = 6, |
410 | | WIRESHARK_VT_DATE = 7, |
411 | | WIRESHARK_VT_BSTR = 8, |
412 | | WIRESHARK_VT_DISPATCH = 9, |
413 | | WIRESHARK_VT_ERROR = 10, |
414 | | WIRESHARK_VT_BOOL = 11, |
415 | | WIRESHARK_VT_VARIANT = 12, |
416 | | WIRESHARK_VT_UNKNOWN = 13, |
417 | | WIRESHARK_VT_DECIMAL = 14, |
418 | | WIRESHARK_VT_I1 = 16, |
419 | | WIRESHARK_VT_UI1 = 17, |
420 | | WIRESHARK_VT_UI2 = 18, |
421 | | WIRESHARK_VT_UI4 = 19, |
422 | | WIRESHARK_VT_I8 = 20, |
423 | | WIRESHARK_VT_UI8 = 21, |
424 | | WIRESHARK_VT_INT = 22, |
425 | | WIRESHARK_VT_UINT = 23, |
426 | | WIRESHARK_VT_VOID = 24, |
427 | | WIRESHARK_VT_HRESULT = 25, |
428 | | WIRESHARK_VT_PTR = 26, |
429 | | WIRESHARK_VT_SAFEARRAY = 27, |
430 | | WIRESHARK_VT_CARRAY = 28, |
431 | | WIRESHARK_VT_USERDEFINED = 29, |
432 | | WIRESHARK_VT_LPSTR = 30, |
433 | | WIRESHARK_VT_LPWSTR = 31, |
434 | | WIRESHARK_VT_RECORD = 36, |
435 | | WIRESHARK_VT_FILETIME = 64, |
436 | | WIRESHARK_VT_BLOB = 65, |
437 | | WIRESHARK_VT_STREAM = 66, |
438 | | WIRESHARK_VT_STORAGE = 67, |
439 | | WIRESHARK_VT_STREAMED_OBJECT = 68, |
440 | | WIRESHARK_VT_STORED_OBJECT = 69, |
441 | | WIRESHARK_VT_BLOB_OBJECT = 70, |
442 | | WIRESHARK_VT_CF = 71, |
443 | | WIRESHARK_VT_CLSID = 72, |
444 | | |
445 | | WIRESHARK_VT_BSTR_BLOB = 0x0fff, |
446 | | |
447 | | WIRESHARK_VT_VECTOR = 0x1000, |
448 | | WIRESHARK_VT_ARRAY = 0x2000, |
449 | | WIRESHARK_VT_BYREF = 0x4000, |
450 | | WIRESHARK_VT_RESERVED = 0x8000, |
451 | | |
452 | | WIRESHARK_VT_ILLEGAL = 0xffff, |
453 | | WIRESHARK_VT_ILLEGALMASKED = 0x0fff, |
454 | | WIRESHARK_VT_TYPEMASK = 0x0fff |
455 | | } dcom_vartype_t; |
456 | | |
457 | | const value_string dcom_variant_type_vals[] = { |
458 | | { WIRESHARK_VT_EMPTY, "VT_EMPTY"}, |
459 | | { WIRESHARK_VT_NULL, "VT_NULL"}, |
460 | | { WIRESHARK_VT_I2, "VT_I2"}, |
461 | | { WIRESHARK_VT_I4, "VT_I4"}, |
462 | | { WIRESHARK_VT_R4, "VT_R4"}, |
463 | | { WIRESHARK_VT_R8, "VT_R8"}, |
464 | | { WIRESHARK_VT_CY, "VT_CY"}, |
465 | | { WIRESHARK_VT_DATE, "VT_DATE"}, |
466 | | { WIRESHARK_VT_BSTR, "VT_BSTR"}, |
467 | | { WIRESHARK_VT_DISPATCH, "VT_DISPATCH"}, |
468 | | { WIRESHARK_VT_ERROR, "VT_ERROR"}, |
469 | | { WIRESHARK_VT_BOOL, "VT_BOOL"}, |
470 | | { WIRESHARK_VT_I1, "VT_I1"}, |
471 | | { WIRESHARK_VT_UI1, "VT_UI1"}, |
472 | | { WIRESHARK_VT_UI2, "VT_UI2"}, |
473 | | { WIRESHARK_VT_UI4, "VT_UI4"}, |
474 | | { WIRESHARK_VT_I8, "VT_I8"}, |
475 | | { WIRESHARK_VT_UI8, "VT_UI8"}, |
476 | | { WIRESHARK_VT_ARRAY, "VT_ARRAY"}, |
477 | | { WIRESHARK_VT_UNKNOWN, "VT_UNKNOWN"}, |
478 | | { WIRESHARK_VT_USERDEFINED, "VT_USERDEFINED"}, |
479 | | { WIRESHARK_VT_PTR, "VT_PTR"}, |
480 | | |
481 | | /* XXX: this could be done better */ |
482 | | { WIRESHARK_VT_ARRAY | WIRESHARK_VT_I2, "VT_ARRAY|VT_I2"}, |
483 | | { WIRESHARK_VT_ARRAY | WIRESHARK_VT_I4, "VT_ARRAY|VT_I4"}, |
484 | | { WIRESHARK_VT_ARRAY | WIRESHARK_VT_R4, "VT_ARRAY|VT_R4"}, |
485 | | { WIRESHARK_VT_ARRAY | WIRESHARK_VT_R8, "VT_ARRAY|VT_R8"}, |
486 | | { WIRESHARK_VT_ARRAY | WIRESHARK_VT_DATE, "VT_ARRAY|VT_DATE"}, |
487 | | { WIRESHARK_VT_ARRAY | WIRESHARK_VT_BSTR, "VT_ARRAY|VT_BSTR"}, |
488 | | { WIRESHARK_VT_ARRAY | WIRESHARK_VT_ERROR, "VT_ARRAY|VT_ERROR"}, |
489 | | { WIRESHARK_VT_ARRAY | WIRESHARK_VT_BOOL, "VT_ARRAY|VT_BOOL"}, |
490 | | { WIRESHARK_VT_ARRAY | WIRESHARK_VT_I1, "VT_ARRAY|VT_I1"}, |
491 | | { WIRESHARK_VT_ARRAY | WIRESHARK_VT_UI1, "VT_ARRAY|VT_UI1"}, |
492 | | { WIRESHARK_VT_ARRAY | WIRESHARK_VT_UI2, "VT_ARRAY|VT_UI2"}, |
493 | | { WIRESHARK_VT_ARRAY | WIRESHARK_VT_UI4, "VT_ARRAY|VT_UI4"}, |
494 | | { WIRESHARK_VT_ARRAY | WIRESHARK_VT_I8, "VT_ARRAY|VT_I8"}, |
495 | | { WIRESHARK_VT_ARRAY | WIRESHARK_VT_UI8, "VT_ARRAY|VT_UI8"}, |
496 | | |
497 | | { WIRESHARK_VT_BYREF | WIRESHARK_VT_I2, "VT_BYREF|VT_I2"}, |
498 | | { WIRESHARK_VT_BYREF | WIRESHARK_VT_BSTR, "VT_BYREF|VT_BSTR"}, |
499 | | { WIRESHARK_VT_BYREF | WIRESHARK_VT_VARIANT, "VT_BYREF|VT_VARIANT"}, |
500 | | { 0, NULL } |
501 | | /* XXX: append more types here */ |
502 | | }; |
503 | | |
504 | | |
505 | | |
506 | | /* we need an extension mechanism here (be able to append entries by user protocol) */ |
507 | | const value_string dcom_hresult_vals[] = { |
508 | | { 0x00000000, "S_OK" }, |
509 | | { 0x00000001, "S_FALSE" }, |
510 | | { 0x8000FFFF, "E_UNEXPECTED" }, |
511 | | { 0x80004001, "E_NOTIMPL" }, |
512 | | { 0x80004002, "E_NOINTERFACE" }, |
513 | | { 0x80004003, "E_POINTER" }, |
514 | | { 0x80004004, "E_ABORT" }, |
515 | | { 0x80004005, "E_FAIL" }, |
516 | | { 0x80070005, "E_ACCESSDENIED" }, |
517 | | { 0x80070006, "E_HANDLE" }, |
518 | | { 0x8007000E, "E_OUTOFMEMORY" }, |
519 | | { 0x80070057, "E_INVALIDARG" }, |
520 | | |
521 | | { 0x80010108, "RPC_E_DISCONNECTED" }, |
522 | | { 0x80010113, "RPC_E_INVALID_IPID" }, |
523 | | { 0x8001011F, "RPC_E_TIMEOUT" }, |
524 | | |
525 | | { 0x80020003, "DISP_E_MEMBERNOTFOUND" }, |
526 | | { 0x80020004, "DISP_E_PARAMNOTFOUND" }, |
527 | | { 0x80020005, "DISP_E_TYPEMISMATCH" }, |
528 | | { 0x80020006, "DISP_E_UNKNOWNNAME" }, |
529 | | { 0x80020008, "DISP_E_BADVARTYPE" }, |
530 | | { 0x80020009, "DISP_E_EXCEPTION" }, |
531 | | { 0x8002000A, "DISP_E_OVERFLOW" }, |
532 | | |
533 | | { 0x8002801D, "TYPE_E_LIBNOTREGISTERED" }, |
534 | | |
535 | | { 0x80040154, "REGDB_E_CLASSNOTREG" }, |
536 | | { 0x80040201, "CO_E_FAILEDTOGETSECCTX" }, |
537 | | |
538 | | /* following are CBA application specific values */ |
539 | | { 0x0004CA00, "CBA_S_PERSISTPENDING" }, |
540 | | { 0x0004CA01, "CBA_S_ESTABLISHING" }, |
541 | | { 0x0004CA02, "CBA_S_NOCONNECTION" }, |
542 | | { 0x0004CA03, "CBA_S_VALUEBUFFERED" }, |
543 | | { 0x0004CA04, "CBA_S_VALUEUNCERTAIN" }, |
544 | | { 0x0004CA05, "CBA_S_NOCONNECTIONDATA" }, |
545 | | { 0x0004CA06, "CBA_S_FRAMEEMPTY" }, |
546 | | |
547 | | { 0x8004CB00, "CBA_E_MALFORMED" }, |
548 | | { 0x8004CB01, "CBA_E_UNKNOWNOBJECT" }, |
549 | | { 0x8004CB02, "CBA_E_UNKNOWNMEMBER" }, |
550 | | { 0x8004CB03, "CBA_E_TYPEMISMATCH" }, |
551 | | { 0x8004CB04, "CBA_E_INVALIDENUMVALUE" }, |
552 | | { 0x8004CB05, "CBA_E_INVALIDID" }, |
553 | | { 0x8004CB06, "CBA_E_INVALIDEPSILON" }, |
554 | | { 0x8004CB07, "CBA_E_INVALIDSUBSTITUTE" }, |
555 | | { 0x8004CB08, "CBA_E_INVALIDCONNECTION" }, |
556 | | { 0x8004CB09, "CBA_E_INVALIDCOOKIE" }, |
557 | | { 0x8004CB0A, "CBA_E_TIMEVALUEUNSUPPORTED" }, |
558 | | { 0x8004CB0B, "CBA_E_QOSTYPEUNSUPPORTED" }, |
559 | | { 0x8004CB0C, "CBA_E_QOSVALUEUNSUPPORTED" }, |
560 | | { 0x8004CB0D, "CBA_E_PERSISTRUNNING" }, |
561 | | { 0x8004CB0E, "CBA_E_INUSE" }, |
562 | | { 0x8004CB0F, "CBA_E_NOTAPPLICABLE" }, |
563 | | { 0x8004CB10, "CBA_E_NONACCESSIBLE" }, |
564 | | { 0x8004CB11, "CBA_E_DEFECT" }, |
565 | | { 0x8004CB12, "CBA_E_LIMITVIOLATION" }, |
566 | | { 0x8004CB13, "CBA_E_QOSTYPENOTAPPLICABLE" }, |
567 | | { 0x8004CB14, "CBA_E_QCNOTAPPLICABLE" }, |
568 | | { 0x8004CB15, "CBA_E_ACCESSBLOCKED" }, |
569 | | { 0x8004CB16, "CBA_E_COUNTEXCEEDED" }, |
570 | | { 0x8004CB17, "CBA_E_SIZEEXCEEDED" }, |
571 | | { 0x8004CB18, "CBA_E_OUTOFPARTNERACCOS" }, |
572 | | { 0x8004CB19, "CBA_E_OUTOFACCOPAIRS" }, |
573 | | { 0x8004CB1A, "CBA_E_ITEMTOOLARGE" }, |
574 | | { 0x8004CB1B, "CBA_E_CRDATALENGTH" }, |
575 | | { 0x8004CB1C, "CBA_E_FLAGUNSUPPORTED" }, |
576 | | { 0x8004CB1D, "CBA_E_CAPACITYEXCEEDED" }, |
577 | | { 0x8004CB1E, "CBA_E_SUBELEMENTMISMATCH" }, |
578 | | { 0x8004CB1F, "CBA_E_STATIONFAILURE" }, |
579 | | { 0x8004CB20, "CBA_E_NOTROUTABLE" }, |
580 | | { 0x8004CB21, "CBA_E_DISCONNECTRUNNING" }, |
581 | | { 0x8004CB22, "CBA_E_LOCATIONCHANGED" }, |
582 | | { 0x8004CB23, "CBA_E_FRAMECOUNTUNSUPPORTED" }, |
583 | | { 0x8004CB24, "CBA_E_LINKFAILURE" }, |
584 | | { 0x8004CB25, "CBA_E_MODECHANGE" }, |
585 | | |
586 | | { 0x80080004, "CO_E_BAD_PATH" }, |
587 | | |
588 | | { 0, NULL } |
589 | | }; |
590 | | |
591 | | static const value_string dcom_objref_flag_vals[] = { |
592 | | { 0x1, "OBJREF_STANDARD" }, |
593 | | { 0x2, "OBJREF_HANDLER" }, |
594 | | { 0x4, "OBJREF_CUSTOM" }, |
595 | | { 0, NULL } |
596 | | }; |
597 | | |
598 | | static const value_string dcom_objref_signature_vals[] = { |
599 | | { 0x574f454d, "MEOW" }, |
600 | | { 0, NULL } |
601 | | }; |
602 | | |
603 | | /* although flags, they doesn't seem to be used as such */ |
604 | | static const value_string dcom_stdobjref_flag_vals[] = { |
605 | | { 0x0000, "SORF_NULL" }, |
606 | | { 0x0001, "SORF_OXRES1" }, |
607 | | { 0x0020, "SORF_OXRES2" }, |
608 | | { 0x0040, "SORF_OXRES3" }, |
609 | | { 0x0080, "SORF_OXRES4" }, |
610 | | { 0x0100, "SORF_OXRES5" }, |
611 | | { 0x0200, "SORF_OXRES6" }, |
612 | | { 0x0400, "SORF_OXRES7" }, |
613 | | { 0x0800, "SORF_OXRES8" }, |
614 | | { 0x1000, "SORF_NOPING" }, |
615 | | { 0, NULL } |
616 | | }; |
617 | | |
618 | | static const value_string dcom_dcerpc_pointer_vals[] = { |
619 | | { 0x72657355, "User" }, |
620 | | { 0x42535452, "BSTR" }, |
621 | | { 0x00000000, "NULL" }, |
622 | | { 0, NULL } |
623 | | }; |
624 | | |
625 | | static const value_string dcom_dualstringarray_authz[] = { |
626 | | { 0x0000, "RPC_C_AUTHZ_NONE" }, |
627 | | { 0x0001, "RPC_C_AUTHZ_NAME"}, |
628 | | { 0x0002, "RPC_C_AUTHZ_DCE"}, |
629 | | { 0xffff, "Default"}, |
630 | | { 0, NULL} |
631 | | }; |
632 | | |
633 | | static const value_string dcom_dualstringarray_authn[] = { |
634 | | { 00, "RPC_C_AUTHN_NONE" }, |
635 | | { 1, "RPC_C_AUTHN_DCE_PRIVATE"}, |
636 | | { 2, "RPC_C_AUTHN_DCE_PUBLIC"}, |
637 | | { 4, "RPC_C_AUTHN_DEC_PUBLIC"}, |
638 | | { 9, "RPC_C_AUTHN_GSS_NEGOTIATE"}, |
639 | | { 10, "RPC_C_AUTH_WINNT"}, |
640 | | { 14, "RPC_C_AUTHN_GSS_SCHANNEL"}, |
641 | | { 16, "RPC_C_AUTHN_GSS_KERBEROS"}, |
642 | | { 17, "RPC_C_AUTHN_MSN"}, |
643 | | { 18, "RPC_C_AUTHN_DPA"}, |
644 | | { 100, "RPC_C_AUTHN_MQ"}, |
645 | | { 0xffff, "RPC_C_AUTHN_DEFAULT"}, |
646 | | { 0, NULL} |
647 | | }; |
648 | | |
649 | | const value_string dcom_protseq_vals[] = { |
650 | | { 0x04, "NCACN_DNET_NSP" }, |
651 | | { 0x07, "NCACN_IP_TCP" }, |
652 | | { 0x08, "NCADG_IP_UDP" }, |
653 | | { 0x09, "NCACN_IP" }, |
654 | | { 0x0C, "NCACN_SPX" }, |
655 | | { 0x0D, "NCACN_NB_IPX" }, |
656 | | { 0x0E, "NCADG_IPX" }, |
657 | | { 0x12, "NCACN_NB_NB" }, |
658 | | { 0x1F, "NCACN_HTTP" }, |
659 | | { 0, NULL } |
660 | | }; |
661 | | |
662 | | static const value_string dcom_vt_bool_vals[] = { |
663 | | { 0x0000, "FALSE" }, |
664 | | { 0xFFFF, "TRUE" }, |
665 | | { 0, NULL } |
666 | | }; |
667 | | |
668 | | |
669 | | |
670 | | /* dissect extension to DCOM "this" and "that" */ |
671 | | static unsigned |
672 | | dissect_dcom_extent(tvbuff_t *tvb, unsigned offset, |
673 | | packet_info *pinfo, proto_tree *tree, dcerpc_info *di, uint8_t *drep) |
674 | 0 | { |
675 | 0 | uint32_t u32ArraySize; |
676 | 0 | uint32_t u32ArraySize2; |
677 | 0 | uint32_t u32Pointer; |
678 | 0 | uint32_t u32VariableOffset; |
679 | 0 | uint32_t u32Idx; |
680 | 0 | uint32_t u32SubStart; |
681 | 0 | proto_item *sub_item; |
682 | 0 | proto_tree *sub_tree; |
683 | |
|
684 | 0 | uint32_t u32ArrayCount; |
685 | 0 | uint32_t u32ArrayRes; |
686 | |
|
687 | 0 | uint32_t u32ExtentSize; |
688 | 0 | e_guid_t uuidExtend; |
689 | 0 | const char *uuid_name; |
690 | | |
691 | |
|
692 | 0 | offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, &u32Pointer); |
693 | |
|
694 | 0 | if (u32Pointer == 0) { |
695 | 0 | return offset; |
696 | 0 | } |
697 | | |
698 | 0 | offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, |
699 | 0 | hf_dcom_extent_array_count, &u32ArrayCount); |
700 | 0 | offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, |
701 | 0 | hf_dcom_extent_array_res, &u32ArrayRes); |
702 | |
|
703 | 0 | offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, &u32Pointer); |
704 | |
|
705 | 0 | if (u32Pointer == 0) { |
706 | 0 | return offset; |
707 | 0 | } |
708 | | |
709 | 0 | offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, |
710 | 0 | &u32ArraySize); |
711 | |
|
712 | 0 | u32VariableOffset = offset + u32ArraySize*4; |
713 | |
|
714 | 0 | u32Idx = 1; |
715 | 0 | while (u32ArraySize--) { |
716 | 0 | sub_item = proto_tree_add_item(tree, hf_dcom_extent, tvb, offset, 0, ENC_NA); |
717 | 0 | sub_tree = proto_item_add_subtree(sub_item, ett_dcom_extent); |
718 | 0 | u32SubStart = offset; |
719 | |
|
720 | 0 | offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer); |
721 | |
|
722 | 0 | if(u32Pointer != 0) { |
723 | 0 | u32VariableOffset = dissect_dcom_DWORD(tvb, u32VariableOffset, pinfo, sub_tree, di, drep, |
724 | 0 | hf_dcom_extent_size, &u32ExtentSize); |
725 | |
|
726 | 0 | dissect_dcom_UUID(tvb, u32VariableOffset, pinfo, NULL, di, drep, |
727 | 0 | hf_dcom_extent_id, &uuidExtend); |
728 | | |
729 | | /* look for a registered uuid name */ |
730 | 0 | if((uuid_name = guids_get_guid_name(&uuidExtend, pinfo->pool)) != NULL) { |
731 | 0 | proto_tree_add_guid_format_value(sub_tree, hf_dcom_extent_id, tvb, |
732 | 0 | offset, sizeof(e_guid_t), (e_guid_t *) &uuidExtend, |
733 | 0 | "%s (%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)", |
734 | 0 | uuid_name, |
735 | 0 | uuidExtend.data1, uuidExtend.data2, uuidExtend.data3, |
736 | 0 | uuidExtend.data4[0], uuidExtend.data4[1], |
737 | 0 | uuidExtend.data4[2], uuidExtend.data4[3], |
738 | 0 | uuidExtend.data4[4], uuidExtend.data4[5], |
739 | 0 | uuidExtend.data4[6], uuidExtend.data4[7]); |
740 | 0 | u32VariableOffset += 16; |
741 | 0 | } else { |
742 | 0 | u32VariableOffset = dissect_dcom_UUID(tvb, u32VariableOffset, pinfo, sub_tree, di, drep, |
743 | 0 | hf_dcom_extent_id, &uuidExtend); |
744 | 0 | } |
745 | | |
746 | |
|
747 | 0 | u32VariableOffset = dissect_dcom_dcerpc_array_size(tvb, u32VariableOffset, pinfo, sub_tree, di, drep, |
748 | 0 | &u32ArraySize2); |
749 | 0 | u32VariableOffset = dissect_dcom_nospec_data(tvb, u32VariableOffset, pinfo, sub_tree, drep, u32ArraySize2); |
750 | | |
751 | | /* update subtree header */ |
752 | 0 | if(uuid_name != NULL) { |
753 | 0 | proto_item_append_text(sub_item, "[%u]: %s, Bytes=%u", |
754 | 0 | u32Idx, uuid_name, u32ArraySize2); |
755 | 0 | } else { |
756 | 0 | proto_item_append_text(sub_item, "[%u]: Bytes=%u", |
757 | 0 | u32Idx, u32ArraySize2); |
758 | 0 | } |
759 | 0 | proto_item_set_len(sub_item, offset - u32SubStart); |
760 | 0 | } else { |
761 | | /* update subtree header */ |
762 | 0 | proto_item_append_text(sub_item, "[%u]: NULL", u32Idx); |
763 | 0 | proto_item_set_len(sub_item, offset - u32SubStart); |
764 | 0 | } |
765 | |
|
766 | 0 | u32Idx++; |
767 | 0 | } |
768 | |
|
769 | 0 | return u32VariableOffset; |
770 | 0 | } |
771 | | |
772 | | |
773 | | /* dissect DCOM "this" (start of every DCOM request) */ |
774 | | unsigned |
775 | | dissect_dcom_this(tvbuff_t *tvb, unsigned offset, |
776 | | packet_info *pinfo, proto_tree *tree, dcerpc_info *di, uint8_t *drep) |
777 | 0 | { |
778 | 0 | uint16_t u16VersionMajor; |
779 | 0 | uint16_t u16VersionMinor; |
780 | 0 | uint32_t u32Flags; |
781 | 0 | uint32_t u32Res; |
782 | 0 | e_guid_t uuidCausality; |
783 | 0 | proto_item *sub_item; |
784 | 0 | proto_tree *sub_tree; |
785 | 0 | uint32_t u32SubStart; |
786 | 0 | proto_item *pi; |
787 | |
|
788 | 0 | sub_item = proto_tree_add_protocol_format(tree, proto_dcom, tvb, offset, 0, |
789 | 0 | "DCOM, ORPCThis"); |
790 | 0 | sub_tree = proto_item_add_subtree(sub_item, ett_dcom_this); |
791 | |
|
792 | 0 | offset = dissect_dcom_COMVERSION(tvb, offset, pinfo, sub_tree, di, drep, |
793 | 0 | &u16VersionMajor, &u16VersionMinor); |
794 | 0 | u32SubStart = offset - 4; |
795 | |
|
796 | 0 | offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, |
797 | 0 | hf_dcom_this_flags, &u32Flags); |
798 | 0 | offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, |
799 | 0 | hf_dcom_this_res, &u32Res); |
800 | |
|
801 | 0 | offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, di, drep, |
802 | 0 | hf_dcom_this_cid, &uuidCausality); |
803 | |
|
804 | 0 | offset = dissect_dcom_extent(tvb, offset, pinfo, sub_tree, di, drep); |
805 | | |
806 | | /* update subtree header */ |
807 | 0 | proto_item_append_text(sub_item, ", V%u.%u, Causality ID: %s", |
808 | 0 | u16VersionMajor, u16VersionMinor, guids_resolve_guid_to_str(&uuidCausality, pinfo->pool)); |
809 | 0 | proto_item_set_len(sub_item, offset - u32SubStart); |
810 | |
|
811 | 0 | if(memcmp(&di->call_data->object_uuid, &uuid_null, sizeof(uuid_null)) != 0) { |
812 | 0 | pi = proto_tree_add_guid_format(tree, hf_dcom_ipid, tvb, offset, 0, |
813 | 0 | (e_guid_t *) &di->call_data->object_uuid, |
814 | 0 | "Object UUID/IPID: %s", guids_resolve_guid_to_str(&di->call_data->object_uuid, pinfo->pool)); |
815 | 0 | proto_item_set_generated(pi); |
816 | 0 | } |
817 | |
|
818 | 0 | return offset; |
819 | 0 | } |
820 | | |
821 | | |
822 | | /* dissect DCOM "that" (start of every DCOM response) */ |
823 | | unsigned |
824 | | dissect_dcom_that(tvbuff_t *tvb, unsigned offset, |
825 | 0 | packet_info *pinfo, proto_tree *tree, dcerpc_info *di, uint8_t *drep) { |
826 | 0 | uint32_t u32Flags; |
827 | 0 | proto_item *sub_item; |
828 | 0 | proto_tree *sub_tree; |
829 | 0 | uint32_t u32SubStart; |
830 | 0 | proto_item *pi; |
831 | |
|
832 | 0 | sub_item = proto_tree_add_protocol_format(tree, proto_dcom, tvb, offset, 0, |
833 | 0 | "DCOM, ORPCThat"); |
834 | 0 | sub_tree = proto_item_add_subtree(sub_item, ett_dcom_that); |
835 | |
|
836 | 0 | offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, |
837 | 0 | hf_dcom_that_flags, &u32Flags); |
838 | 0 | u32SubStart = offset - 4; |
839 | |
|
840 | 0 | offset = dissect_dcom_extent(tvb, offset, pinfo, sub_tree, di, drep); |
841 | | |
842 | | /* update subtree header */ |
843 | 0 | proto_item_set_len(sub_item, offset - u32SubStart); |
844 | |
|
845 | 0 | if(memcmp(&di->call_data->object_uuid, &uuid_null, sizeof(uuid_null)) != 0) { |
846 | 0 | pi = proto_tree_add_guid_format(tree, hf_dcom_ipid, tvb, offset, 0, |
847 | 0 | (e_guid_t *) &di->call_data->object_uuid, |
848 | 0 | "Object UUID/IPID: %s", guids_resolve_guid_to_str(&di->call_data->object_uuid, pinfo->pool)); |
849 | 0 | proto_item_set_generated(pi); |
850 | 0 | } |
851 | |
|
852 | 0 | return offset; |
853 | 0 | } |
854 | | |
855 | | |
856 | | /* dissect simple dcom request, DCOM "this" only */ |
857 | | unsigned |
858 | | dissect_dcom_simple_rqst(tvbuff_t *tvb, unsigned offset, |
859 | | packet_info *pinfo, proto_tree *tree, dcerpc_info *di, uint8_t *drep) |
860 | 0 | { |
861 | |
|
862 | 0 | offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); |
863 | |
|
864 | 0 | return offset; |
865 | 0 | } |
866 | | |
867 | | |
868 | | /* dissect simple dcom response, DCOM "that" and returned HRESULT only */ |
869 | | unsigned |
870 | | dissect_dcom_simple_resp(tvbuff_t *tvb, unsigned offset, |
871 | | packet_info *pinfo, proto_tree *tree, dcerpc_info *di, uint8_t *drep) |
872 | 0 | { |
873 | 0 | uint32_t u32HResult; |
874 | | |
875 | |
|
876 | 0 | offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); |
877 | |
|
878 | 0 | offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, |
879 | 0 | &u32HResult); |
880 | |
|
881 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", |
882 | 0 | val_to_str(pinfo->pool, u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); |
883 | | |
884 | |
|
885 | 0 | return offset; |
886 | 0 | } |
887 | | |
888 | | |
889 | | /* dissect a dcerpc array size */ |
890 | | unsigned |
891 | | dissect_dcom_dcerpc_array_size(tvbuff_t *tvb, unsigned offset, packet_info *pinfo, |
892 | | proto_tree *tree, dcerpc_info *di, uint8_t *drep, uint32_t *pu32ArraySize) |
893 | 0 | { |
894 | | |
895 | | |
896 | | /* en-/disable this by preference setting */ |
897 | 0 | if (!dcom_prefs_display_unmarshalling_details) { |
898 | | /* this will read in the data, but prevent output to tree */ |
899 | 0 | tree = NULL; |
900 | 0 | } |
901 | |
|
902 | 0 | offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep, |
903 | 0 | hf_dcom_array_size, pu32ArraySize); |
904 | |
|
905 | 0 | return offset; |
906 | 0 | } |
907 | | |
908 | | |
909 | | /* dissect a dcerpc pointer value */ |
910 | | unsigned |
911 | | dissect_dcom_dcerpc_pointer(tvbuff_t *tvb, unsigned offset, packet_info *pinfo, |
912 | | proto_tree *tree, dcerpc_info *di, uint8_t *drep, uint32_t *pu32Pointer) |
913 | 0 | { |
914 | | |
915 | | /* en-/disable this by preference setting */ |
916 | 0 | if (!dcom_prefs_display_unmarshalling_details) { |
917 | | /* this will read in the data, but prevent output to tree */ |
918 | 0 | tree = NULL; |
919 | 0 | } |
920 | |
|
921 | 0 | offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep, |
922 | 0 | hf_dcom_pointer_val, pu32Pointer); |
923 | |
|
924 | 0 | return offset; |
925 | 0 | } |
926 | | |
927 | | |
928 | | /* mark data as "ToBeDone" */ |
929 | | /* XXX: handout data to generic "unknown data" dissector? */ |
930 | | extern unsigned |
931 | | dissect_dcom_tobedone_data(tvbuff_t *tvb, unsigned offset, |
932 | | packet_info *pinfo, proto_tree *tree, uint8_t *drep _U_, int length) |
933 | 0 | { |
934 | 0 | proto_item *item; |
935 | | |
936 | |
|
937 | 0 | item = proto_tree_add_item(tree, hf_dcom_tobedone, tvb, offset, length, ENC_NA); |
938 | 0 | proto_item_set_generated(item); |
939 | 0 | expert_add_info(pinfo, item, &ei_dcom_dissection_incomplete); |
940 | |
|
941 | 0 | offset += length; |
942 | |
|
943 | 0 | return offset; |
944 | 0 | } |
945 | | |
946 | | |
947 | | /* mark data as "No Specification Available" */ |
948 | | /* XXX: handout data to generic "unknown data" dissector? */ |
949 | | extern unsigned |
950 | | dissect_dcom_nospec_data(tvbuff_t *tvb, unsigned offset, |
951 | | packet_info *pinfo, proto_tree *tree, uint8_t *drep _U_, int length) |
952 | 0 | { |
953 | 0 | proto_item *item; |
954 | | |
955 | |
|
956 | 0 | item = proto_tree_add_item(tree, hf_dcom_nospec, tvb, offset, length, ENC_NA); |
957 | 0 | proto_item_set_generated(item); |
958 | 0 | expert_add_info(pinfo, item, &ei_dcom_no_spec); |
959 | |
|
960 | 0 | offset += length; |
961 | |
|
962 | 0 | return offset; |
963 | 0 | } |
964 | | |
965 | | |
966 | | /* dissect an indexed WORD, something like: "FieldName[1]: 0x1234" */ |
967 | | unsigned |
968 | | dissect_dcom_indexed_WORD(tvbuff_t *tvb, unsigned offset, packet_info *pinfo, |
969 | | proto_tree *tree, dcerpc_info *di, uint8_t *drep, |
970 | | int hfindex, uint16_t * pu16WORD, int field_index) |
971 | 0 | { |
972 | 0 | uint16_t u16WORD; |
973 | | |
974 | | |
975 | | /* dissect the WORD, but don't add to tree */ |
976 | 0 | dissect_dcom_WORD(tvb, offset, pinfo, NULL /*tree*/, di, drep, |
977 | 0 | hfindex, &u16WORD); |
978 | |
|
979 | 0 | if (tree) { |
980 | | /* special formatted output of indexed value */ |
981 | 0 | proto_tree_add_uint_format(tree, hfindex, tvb, offset, 2, u16WORD, |
982 | 0 | "%s[%u]: 0x%04x", |
983 | 0 | proto_registrar_get_name(hfindex), |
984 | 0 | field_index, u16WORD); |
985 | 0 | } |
986 | |
|
987 | 0 | offset += 2; |
988 | |
|
989 | 0 | if (pu16WORD) |
990 | 0 | *pu16WORD = u16WORD; |
991 | |
|
992 | 0 | return offset; |
993 | 0 | } |
994 | | |
995 | | |
996 | | /* dissect an indexed DWORD, something like: "FieldName[1]: 0x12345678" */ |
997 | | unsigned |
998 | | dissect_dcom_indexed_DWORD(tvbuff_t *tvb, unsigned offset, packet_info *pinfo, |
999 | | proto_tree *tree, dcerpc_info *di, uint8_t *drep, |
1000 | | int hfindex, uint32_t * pu32DWORD, int field_index) |
1001 | 0 | { |
1002 | 0 | uint32_t u32DWORD; |
1003 | | |
1004 | | |
1005 | | /* dissect the DWORD, but don't add to tree */ |
1006 | 0 | dissect_dcom_DWORD(tvb, offset, pinfo, NULL /*tree*/, di, drep, |
1007 | 0 | hfindex, &u32DWORD); |
1008 | |
|
1009 | 0 | if (tree) { |
1010 | | /* special formatted output of indexed value */ |
1011 | 0 | proto_tree_add_uint_format(tree, hfindex, tvb, offset, 4, u32DWORD, |
1012 | 0 | "%s[%u]: 0x%08x", |
1013 | 0 | proto_registrar_get_name(hfindex), |
1014 | 0 | field_index, u32DWORD); |
1015 | 0 | } |
1016 | |
|
1017 | 0 | offset += 4; |
1018 | |
|
1019 | 0 | if (pu32DWORD) |
1020 | 0 | *pu32DWORD = u32DWORD; |
1021 | |
|
1022 | 0 | return offset; |
1023 | 0 | } |
1024 | | |
1025 | | |
1026 | | /* dissect hresult field of a usual DCOM call (create "raw" item) */ |
1027 | | unsigned |
1028 | | dissect_dcom_HRESULT_item(tvbuff_t *tvb, unsigned offset, packet_info *pinfo, |
1029 | | proto_tree *tree, dcerpc_info *di, uint8_t *drep, |
1030 | | uint32_t * pu32HResult, int field_index, proto_item **item) |
1031 | 0 | { |
1032 | 0 | uint32_t u32HResult; |
1033 | | |
1034 | | /* dissect the DWORD, but don't add to tree */ |
1035 | 0 | offset = dissect_dcom_DWORD(tvb, offset, pinfo, NULL /*tree*/, di, drep, |
1036 | 0 | field_index, &u32HResult); |
1037 | |
|
1038 | 0 | if (tree) { |
1039 | | /* special formatted output of indexed value */ |
1040 | 0 | *item = proto_tree_add_item (tree, field_index, tvb, offset-4, 4, DREP_ENC_INTEGER(drep)); |
1041 | 0 | } |
1042 | |
|
1043 | 0 | if (pu32HResult) |
1044 | 0 | *pu32HResult = u32HResult; |
1045 | |
|
1046 | 0 | return offset; |
1047 | 0 | } |
1048 | | |
1049 | | |
1050 | | /* dissect hresult field of a usual DCOM call (separate method, because often used) */ |
1051 | | unsigned |
1052 | | dissect_dcom_HRESULT(tvbuff_t *tvb, unsigned offset, packet_info *pinfo, |
1053 | | proto_tree *tree, dcerpc_info *di, uint8_t *drep, |
1054 | | uint32_t * pu32HResult) |
1055 | 0 | { |
1056 | 0 | uint32_t u32HResult; |
1057 | 0 | proto_item *item = NULL; |
1058 | | |
1059 | | /* dissect the DWORD, but don't add to tree */ |
1060 | 0 | offset = dissect_dcom_DWORD(tvb, offset, pinfo, NULL /*tree*/, di, drep, |
1061 | 0 | hf_dcom_hresult, &u32HResult); |
1062 | |
|
1063 | 0 | if (tree) { |
1064 | | /* special formatted output of indexed value */ |
1065 | 0 | item = proto_tree_add_item (tree, hf_dcom_hresult, tvb, offset-4, 4, DREP_ENC_INTEGER(drep)); |
1066 | 0 | } |
1067 | | |
1068 | | /* expert info only if severity is set */ |
1069 | | /* XXX - move this to the callers of this function, to provide a more detailed error output */ |
1070 | 0 | if(u32HResult & 0x80000000) { |
1071 | 0 | expert_add_info_format(pinfo, item, &ei_dcom_hresult_expert, "Hresult: %s", |
1072 | 0 | val_to_str(pinfo->pool, u32HResult, dcom_hresult_vals, "Unknown (0x%x)")); |
1073 | 0 | } |
1074 | 0 | if (pu32HResult) |
1075 | 0 | *pu32HResult = u32HResult; |
1076 | |
|
1077 | 0 | return offset; |
1078 | 0 | } |
1079 | | |
1080 | | |
1081 | | /* partial results of indexed DCOM subcalls (e.g.: from a kind of array) */ |
1082 | | unsigned |
1083 | | dissect_dcom_indexed_HRESULT(tvbuff_t *tvb, unsigned offset, packet_info *pinfo, |
1084 | | proto_tree *tree, dcerpc_info *di, uint8_t *drep, |
1085 | | uint32_t * pu32HResult, int field_index) |
1086 | 0 | { |
1087 | 0 | uint32_t u32HResult; |
1088 | 0 | proto_item *item = NULL; |
1089 | | |
1090 | | |
1091 | | /* dissect the DWORD, but don't add to tree */ |
1092 | 0 | offset = dissect_dcom_DWORD(tvb, offset, pinfo, NULL /*tree*/, di, drep, |
1093 | 0 | hf_dcom_hresult, &u32HResult); |
1094 | |
|
1095 | 0 | if (tree) { |
1096 | | /* special formatted output of indexed value */ |
1097 | 0 | item = proto_tree_add_uint_format(tree, hf_dcom_hresult, tvb, offset-4, 4, u32HResult, |
1098 | 0 | "HResult[%u]: %s (0x%08x)", field_index, |
1099 | 0 | val_to_str_const(u32HResult, dcom_hresult_vals, "Unknown"), |
1100 | 0 | u32HResult); |
1101 | 0 | } |
1102 | | /* expert info only if severity flag is set */ |
1103 | | /* XXX - move this to the callers of this function, to provide a more detailed error output */ |
1104 | 0 | if(u32HResult & 0x80000000) { |
1105 | 0 | expert_add_info_format(pinfo, item, &ei_dcom_hresult_expert, "Hresult: %s", |
1106 | 0 | val_to_str(pinfo->pool, u32HResult, dcom_hresult_vals, "Unknown (0x%x)")); |
1107 | 0 | } |
1108 | 0 | if (pu32HResult) |
1109 | 0 | *pu32HResult = u32HResult; |
1110 | |
|
1111 | 0 | return offset; |
1112 | 0 | } |
1113 | | |
1114 | | |
1115 | | |
1116 | | unsigned |
1117 | | dissect_dcom_COMVERSION(tvbuff_t *tvb, unsigned offset, packet_info *pinfo, |
1118 | | proto_tree *tree, dcerpc_info *di, uint8_t *drep, |
1119 | | uint16_t * pu16VersionMajor, uint16_t * pu16VersionMinor) |
1120 | 0 | { |
1121 | |
|
1122 | 0 | offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep, |
1123 | 0 | hf_dcom_version_major, pu16VersionMajor); |
1124 | 0 | offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep, |
1125 | 0 | hf_dcom_version_minor, pu16VersionMinor); |
1126 | |
|
1127 | 0 | return offset; |
1128 | 0 | } |
1129 | | |
1130 | | |
1131 | | unsigned |
1132 | | dissect_dcom_SAFEARRAY(tvbuff_t *tvb, unsigned offset, packet_info *pinfo, |
1133 | | proto_tree *tree, dcerpc_info *di, uint8_t *drep, int hfindex _U_, sa_callback_t sacb) |
1134 | 0 | { |
1135 | 0 | uint32_t u32Dims; |
1136 | 0 | uint16_t u16Dims; |
1137 | 0 | uint16_t u16Features; |
1138 | 0 | uint32_t u32ElementSize; |
1139 | 0 | uint32_t u32VarType; |
1140 | 0 | uint32_t u32Elements; |
1141 | 0 | uint32_t u32Pointer; |
1142 | 0 | uint32_t u32BoundElements; |
1143 | 0 | uint32_t u32LowBound; |
1144 | 0 | char cData[100]; |
1145 | 0 | uint32_t u32ArraySize; |
1146 | 0 | uint32_t u32VariableOffset; |
1147 | 0 | uint32_t u32Data; |
1148 | 0 | uint16_t u16Data; |
1149 | 0 | uint8_t u8Data; |
1150 | 0 | uint16_t u16Locks; |
1151 | 0 | uint16_t u16VarType; |
1152 | 0 | proto_item *sub_item; |
1153 | 0 | proto_tree *sub_tree; |
1154 | 0 | uint32_t u32SubStart; |
1155 | 0 | uint32_t u32TmpOffset; |
1156 | |
|
1157 | 0 | static int * const features[] = { |
1158 | 0 | &hf_dcom_sa_features_variant, |
1159 | 0 | &hf_dcom_sa_features_dispatch, |
1160 | 0 | &hf_dcom_sa_features_unknown, |
1161 | 0 | &hf_dcom_sa_features_bstr, |
1162 | 0 | &hf_dcom_sa_features_have_vartype, |
1163 | 0 | &hf_dcom_sa_features_have_iid, |
1164 | 0 | &hf_dcom_sa_features_record, |
1165 | 0 | &hf_dcom_sa_features_fixedsize, |
1166 | 0 | &hf_dcom_sa_features_embedded, |
1167 | 0 | &hf_dcom_sa_features_static, |
1168 | 0 | &hf_dcom_sa_features_auto, |
1169 | 0 | NULL |
1170 | 0 | }; |
1171 | | |
1172 | | |
1173 | | /* XXX: which alignment do we need here? */ |
1174 | |
|
1175 | 0 | sub_item = proto_tree_add_item(tree, hf_dcom_safearray, tvb, offset, 0, ENC_NA); |
1176 | 0 | sub_tree = proto_item_add_subtree(sub_item, ett_dcom_safearray); |
1177 | 0 | u32SubStart = offset; |
1178 | |
|
1179 | 0 | offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer); |
1180 | 0 | offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer); |
1181 | |
|
1182 | 0 | offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, |
1183 | 0 | hf_dcom_sa_dims32, &u32Dims); |
1184 | 0 | offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep, |
1185 | 0 | hf_dcom_sa_dims16, &u16Dims); |
1186 | | |
1187 | | /* feature flags */ |
1188 | 0 | u32TmpOffset = dissect_dcom_WORD(tvb, offset, pinfo, NULL, di, drep, -1, &u16Features); |
1189 | |
|
1190 | 0 | proto_tree_add_bitmask_value_with_flags(sub_tree, tvb, offset, hf_dcom_sa_features, |
1191 | 0 | ett_dcom_sa_features, features, u16Features, BMT_NO_APPEND); |
1192 | 0 | offset = u32TmpOffset; |
1193 | |
|
1194 | 0 | offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, |
1195 | 0 | hf_dcom_sa_element_size, &u32ElementSize); |
1196 | 0 | offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep, |
1197 | 0 | hf_dcom_sa_locks, &u16Locks); |
1198 | 0 | offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep, |
1199 | 0 | hf_dcom_sa_vartype16, &u16VarType); |
1200 | 0 | offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, |
1201 | 0 | hf_dcom_sa_vartype32, &u32VarType); |
1202 | 0 | offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, |
1203 | 0 | hf_dcom_sa_elements, &u32Elements); |
1204 | 0 | offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer); |
1205 | |
|
1206 | 0 | u32BoundElements = 0; |
1207 | 0 | while(u32Dims != 0) { |
1208 | 0 | offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, |
1209 | 0 | hf_dcom_sa_bound_elements, &u32BoundElements); |
1210 | 0 | offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, |
1211 | 0 | hf_dcom_sa_low_bound, &u32LowBound); |
1212 | 0 | u32Dims--; |
1213 | 0 | } |
1214 | |
|
1215 | 0 | offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, sub_tree, di, drep, &u32ArraySize); |
1216 | |
|
1217 | 0 | tvb_ensure_bytes_exist(tvb, offset, u32ArraySize * u32ElementSize); |
1218 | 0 | u32VariableOffset = offset + u32ArraySize * u32ElementSize; |
1219 | |
|
1220 | 0 | if(sacb) { |
1221 | 0 | sacb(tvb, offset, pinfo, tree, di, drep, u32VarType, u32ArraySize); |
1222 | 0 | } |
1223 | |
|
1224 | 0 | while(u32ArraySize) { |
1225 | 0 | switch(u32VarType) { |
1226 | 0 | case(WIRESHARK_VT_ERROR): |
1227 | 0 | offset = dissect_dcom_HRESULT(tvb, offset, pinfo, sub_tree, di, drep, |
1228 | 0 | &u32Data); |
1229 | 0 | break; |
1230 | 0 | case(WIRESHARK_VT_I1): |
1231 | 0 | offset = dissect_dcom_BYTE(tvb, offset, pinfo, sub_tree, di, drep, |
1232 | 0 | hf_dcom_vt_i1, &u8Data); |
1233 | 0 | break; |
1234 | 0 | case(WIRESHARK_VT_I2): |
1235 | 0 | offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep, |
1236 | 0 | hf_dcom_vt_i2, &u16Data); |
1237 | 0 | break; |
1238 | 0 | case(WIRESHARK_VT_I4): |
1239 | 0 | offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, |
1240 | 0 | hf_dcom_vt_i4, &u32Data); |
1241 | 0 | break; |
1242 | 0 | case(WIRESHARK_VT_I8): |
1243 | 0 | offset = dissect_dcom_I8(tvb, offset, pinfo, sub_tree, di, drep, |
1244 | 0 | hf_dcom_vt_i8, NULL); |
1245 | | /* take care of the 8 byte alignment */ |
1246 | 0 | u32VariableOffset = offset; |
1247 | 0 | break; |
1248 | 0 | case(WIRESHARK_VT_BSTR): |
1249 | 0 | offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer); |
1250 | 0 | if (u32Pointer) { |
1251 | 0 | u32VariableOffset = dissect_dcom_BSTR(tvb, u32VariableOffset, pinfo, sub_tree, di, drep, |
1252 | 0 | hf_dcom_vt_bstr, cData, sizeof(cData) ); |
1253 | 0 | } |
1254 | 0 | break; |
1255 | 0 | default: |
1256 | | /* XXX: other types possible, but still not implemented: |
1257 | | VT_UNKNOWN |
1258 | | VT_DISPATCH |
1259 | | VT_VARIANT |
1260 | | VT_RECORD |
1261 | | VT_UNKNOWN|VT_RESERVED |
1262 | | */ |
1263 | 0 | u32VariableOffset = dissect_dcom_tobedone_data(tvb, u32VariableOffset, pinfo, sub_tree, drep, |
1264 | 0 | 10000); |
1265 | 0 | } |
1266 | 0 | u32ArraySize--; |
1267 | 0 | } |
1268 | | |
1269 | | /* update subtree header */ |
1270 | 0 | proto_item_append_text(sub_item, ": Elements: %u/%u VarType: %s", |
1271 | 0 | u32Elements, u32BoundElements, |
1272 | 0 | val_to_str(pinfo->pool, u32VarType, dcom_variant_type_vals, "Unknown (0x%08x)") ); |
1273 | |
|
1274 | 0 | proto_item_set_len(sub_item, u32VariableOffset - u32SubStart); |
1275 | |
|
1276 | 0 | return u32VariableOffset; |
1277 | 0 | } |
1278 | | |
1279 | | |
1280 | | |
1281 | | unsigned |
1282 | | dissect_dcom_VARTYPE(tvbuff_t *tvb, unsigned offset, packet_info *pinfo, |
1283 | | proto_tree *tree, dcerpc_info *di, uint8_t *drep, |
1284 | | uint16_t *pu16VarType) |
1285 | 0 | { |
1286 | |
|
1287 | 0 | offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep, |
1288 | 0 | hf_dcom_variant_type, pu16VarType); |
1289 | |
|
1290 | 0 | return offset; |
1291 | 0 | } |
1292 | | |
1293 | | |
1294 | | unsigned |
1295 | | // NOLINTNEXTLINE(misc-no-recursion) |
1296 | | dissect_dcom_VARIANT(tvbuff_t *tvb, unsigned offset, packet_info *pinfo, |
1297 | | proto_tree *tree, dcerpc_info *di, uint8_t *drep, int hfindex) |
1298 | 0 | { |
1299 | 0 | uint32_t u32Size; |
1300 | 0 | uint32_t u32RPCRes; |
1301 | 0 | uint16_t u16Res; |
1302 | 0 | uint32_t u32SubStart; |
1303 | 0 | proto_item *sub_item; |
1304 | 0 | proto_tree *sub_tree; |
1305 | 0 | uint16_t u16VarType; |
1306 | 0 | uint32_t u32VarType; |
1307 | |
|
1308 | 0 | uint8_t u8Data; |
1309 | 0 | uint16_t u16Data; |
1310 | 0 | uint32_t u32Data; |
1311 | 0 | uint64_t u64Data; |
1312 | 0 | int64_t cyData; |
1313 | 0 | char cData[500]; |
1314 | 0 | uint32_t u32Pointer; |
1315 | 0 | float f32Data; |
1316 | 0 | double f64Data; |
1317 | | |
1318 | | |
1319 | | /* alignment of 8 needed for a VARIANT */ |
1320 | 0 | offset = WS_ROUNDUP_8(offset); |
1321 | |
|
1322 | 0 | sub_item = proto_tree_add_item(tree, hfindex, tvb, offset, 0, ENC_BIG_ENDIAN); |
1323 | 0 | sub_tree = proto_item_add_subtree(sub_item, ett_dcom_variant); |
1324 | 0 | u32SubStart = offset; |
1325 | | |
1326 | | /* the following size can be VERY confusing: |
1327 | | * It is NOT the maximum size of the variant, as one could expect, |
1328 | | * but the current size of the variant padded to 8 bytes. |
1329 | | * BUT: The following data does not start AFTER this padding, |
1330 | | * it starts just after the variant-data (without padding)!!! */ |
1331 | | /* Conclusion: the size given here can be LONGER than the actual size */ |
1332 | 0 | offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, |
1333 | 0 | hf_dcom_variant_size, &u32Size); |
1334 | 0 | offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, |
1335 | 0 | hf_dcom_variant_rpc_res, &u32RPCRes); |
1336 | 0 | offset = dissect_dcom_VARTYPE(tvb, offset, pinfo, sub_tree, di, drep, |
1337 | 0 | &u16VarType); |
1338 | 0 | offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep, |
1339 | 0 | hf_dcom_variant_wres, &u16Res); |
1340 | 0 | offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep, |
1341 | 0 | hf_dcom_variant_wres, &u16Res); |
1342 | 0 | offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep, |
1343 | 0 | hf_dcom_variant_wres, &u16Res); |
1344 | | |
1345 | | /* 32 bit VarType (slightly different to the 16 bit one) */ |
1346 | 0 | offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, |
1347 | 0 | hf_dcom_variant_type32, &u32VarType); |
1348 | |
|
1349 | 0 | if (u32VarType & WIRESHARK_VT_BYREF) { |
1350 | 0 | u32VarType &=~WIRESHARK_VT_BYREF; |
1351 | 0 | offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer); |
1352 | 0 | } |
1353 | |
|
1354 | 0 | increment_dissection_depth(pinfo); |
1355 | 0 | switch (u32VarType) { |
1356 | 0 | case(WIRESHARK_VT_EMPTY): |
1357 | 0 | break; |
1358 | 0 | case(WIRESHARK_VT_BOOL): |
1359 | 0 | offset = dissect_dcom_VARIANT_BOOL(tvb, offset, pinfo, sub_tree, di, drep, |
1360 | 0 | hf_dcom_vt_bool, &u16Data); |
1361 | 0 | break; |
1362 | 0 | case(WIRESHARK_VT_I1): |
1363 | 0 | offset = dissect_dcom_BYTE(tvb, offset, pinfo, sub_tree, di, drep, |
1364 | 0 | hf_dcom_vt_i1, &u8Data); |
1365 | 0 | break; |
1366 | 0 | case(WIRESHARK_VT_UI1): |
1367 | 0 | offset = dissect_dcom_BYTE(tvb, offset, pinfo, sub_tree, di, drep, |
1368 | 0 | hf_dcom_vt_ui1, &u8Data); |
1369 | 0 | break; |
1370 | 0 | case(WIRESHARK_VT_I2): |
1371 | 0 | offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep, |
1372 | 0 | hf_dcom_vt_i2, &u16Data); |
1373 | 0 | break; |
1374 | 0 | case(WIRESHARK_VT_UI2): |
1375 | 0 | offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep, |
1376 | 0 | hf_dcom_vt_ui2, &u16Data); |
1377 | 0 | break; |
1378 | 0 | case(WIRESHARK_VT_I4): |
1379 | 0 | offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, |
1380 | 0 | hf_dcom_vt_i4, &u32Data); |
1381 | 0 | break; |
1382 | 0 | case(WIRESHARK_VT_I8): |
1383 | 0 | offset = dissect_dcom_I8(tvb, offset, pinfo, sub_tree, di, drep, |
1384 | 0 | hf_dcom_vt_i8, &u64Data); |
1385 | 0 | break; |
1386 | 0 | case(WIRESHARK_VT_CY): |
1387 | 0 | offset = dissect_dcom_I8(tvb, offset, pinfo, NULL, di, drep, |
1388 | 0 | 0, (uint64_t*)&cyData); |
1389 | 0 | proto_tree_add_int64_format(sub_tree, hf_dcom_vt_cy, tvb, offset - 8, |
1390 | 0 | 8, cyData, "%s: %" PRId64 ".%.04" PRId64, |
1391 | 0 | proto_registrar_get_name(hf_dcom_vt_cy), |
1392 | 0 | cyData / 10000, ABS(cyData % 10000)); |
1393 | 0 | break; |
1394 | 0 | case(WIRESHARK_VT_UI4): |
1395 | 0 | offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, |
1396 | 0 | hf_dcom_vt_ui4, &u32Data); |
1397 | 0 | break; |
1398 | 0 | case(WIRESHARK_VT_UI8): |
1399 | 0 | offset = dissect_dcom_I8(tvb, offset, pinfo, sub_tree, di, drep, |
1400 | 0 | hf_dcom_vt_ui8, &u64Data); |
1401 | 0 | break; |
1402 | 0 | case(WIRESHARK_VT_R4): |
1403 | 0 | offset = dissect_dcom_FLOAT(tvb, offset, pinfo, sub_tree, di, drep, |
1404 | 0 | hf_dcom_vt_r4, &f32Data); |
1405 | 0 | break; |
1406 | 0 | case(WIRESHARK_VT_R8): |
1407 | 0 | offset = dissect_dcom_DOUBLE(tvb, offset, pinfo, sub_tree, di, drep, |
1408 | 0 | hf_dcom_vt_r8, &f64Data); |
1409 | 0 | break; |
1410 | 0 | case(WIRESHARK_VT_DATE): |
1411 | 0 | offset = dissect_dcom_DATE(tvb, offset, pinfo, sub_tree, di, drep, |
1412 | 0 | hf_dcom_vt_date, &f64Data); |
1413 | 0 | break; |
1414 | 0 | case(WIRESHARK_VT_BSTR): |
1415 | 0 | offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer); |
1416 | 0 | if (u32Pointer) { |
1417 | 0 | offset = dissect_dcom_BSTR(tvb, offset, pinfo, sub_tree, di, drep, |
1418 | 0 | hf_dcom_vt_bstr, cData, sizeof(cData) ); |
1419 | 0 | } |
1420 | 0 | break; |
1421 | 0 | case(WIRESHARK_VT_DISPATCH): |
1422 | 0 | offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer); |
1423 | 0 | if (u32Pointer) { |
1424 | 0 | offset = dissect_dcom_MInterfacePointer(tvb, offset, pinfo, sub_tree, di, drep, |
1425 | 0 | hf_dcom_vt_dispatch, NULL); /* XXX - how to handle this? */ |
1426 | 0 | } |
1427 | 0 | break; |
1428 | 0 | case(WIRESHARK_VT_ARRAY): |
1429 | 0 | offset = dissect_dcom_SAFEARRAY(tvb, offset, pinfo, sub_tree, di, drep, |
1430 | 0 | 0, NULL); |
1431 | 0 | break; |
1432 | 0 | case(WIRESHARK_VT_ERROR): |
1433 | 0 | offset = dissect_dcom_HRESULT(tvb, offset, pinfo, sub_tree, di, drep, |
1434 | 0 | 0); |
1435 | 0 | break; |
1436 | 0 | case(WIRESHARK_VT_VARIANT): |
1437 | 0 | offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer); |
1438 | 0 | if (u32Pointer) { |
1439 | 0 | offset = dissect_dcom_VARIANT(tvb, offset, pinfo, sub_tree, di, drep, |
1440 | 0 | hf_dcom_vt_byref /* must be BYREF */); |
1441 | 0 | } |
1442 | 0 | break; |
1443 | 0 | case(WIRESHARK_VT_UNKNOWN): |
1444 | 0 | offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, &u32Pointer); |
1445 | 0 | break; |
1446 | 0 | default: |
1447 | | /* XXX: add more types here! */ |
1448 | 0 | offset = dissect_dcom_tobedone_data(tvb, offset, pinfo, sub_tree, drep, |
1449 | 0 | 10000); |
1450 | 0 | } |
1451 | 0 | decrement_dissection_depth(pinfo); |
1452 | | |
1453 | | /* update subtree header */ |
1454 | 0 | proto_item_append_text(sub_item, ": %s", |
1455 | 0 | val_to_str(pinfo->pool, u16VarType, dcom_variant_type_vals, "Unknown (0x%08x)") ); |
1456 | |
|
1457 | 0 | proto_item_set_len(sub_item, offset - u32SubStart); |
1458 | |
|
1459 | 0 | return offset; |
1460 | 0 | } |
1461 | | |
1462 | | |
1463 | | unsigned |
1464 | | dissect_dcom_UUID(tvbuff_t *tvb, unsigned offset, |
1465 | | packet_info *pinfo, proto_tree *tree, dcerpc_info *di, uint8_t *drep, |
1466 | | int hfindex, e_guid_t *pdata) |
1467 | 0 | { |
1468 | 0 | const char *uuid_name; |
1469 | 0 | header_field_info *hfi; |
1470 | 0 | e_guid_t uuid; |
1471 | | |
1472 | | |
1473 | | /* get the UUID, but don't put it into the tree */ |
1474 | 0 | offset = dissect_ndr_uuid_t(tvb, offset, pinfo, NULL, di, drep, |
1475 | 0 | hfindex, &uuid); |
1476 | | |
1477 | | /* add to the tree */ |
1478 | 0 | hfi = proto_registrar_get_nth(hfindex); |
1479 | 0 | uuid_name = guids_get_guid_name(&uuid, pinfo->pool); |
1480 | 0 | if(uuid_name) { |
1481 | 0 | proto_tree_add_guid_format(tree, hfindex, tvb, offset-16, 16, (e_guid_t *) &uuid, |
1482 | 0 | "%s: %s (%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)", |
1483 | 0 | hfi->name, uuid_name, |
1484 | 0 | uuid.data1, uuid.data2, uuid.data3, |
1485 | 0 | uuid.data4[0], uuid.data4[1], |
1486 | 0 | uuid.data4[2], uuid.data4[3], |
1487 | 0 | uuid.data4[4], uuid.data4[5], |
1488 | 0 | uuid.data4[6], uuid.data4[7]); |
1489 | 0 | } else { |
1490 | 0 | proto_tree_add_guid_format(tree, hfindex, tvb, offset-16, 16, (e_guid_t *) &uuid, |
1491 | 0 | "%s: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", |
1492 | 0 | hfi->name, |
1493 | 0 | uuid.data1, uuid.data2, uuid.data3, |
1494 | 0 | uuid.data4[0], uuid.data4[1], |
1495 | 0 | uuid.data4[2], uuid.data4[3], |
1496 | 0 | uuid.data4[4], uuid.data4[5], |
1497 | 0 | uuid.data4[6], uuid.data4[7]); |
1498 | 0 | } |
1499 | |
|
1500 | 0 | if(pdata != NULL) { |
1501 | 0 | *pdata = uuid; |
1502 | 0 | } |
1503 | |
|
1504 | 0 | return offset; |
1505 | 0 | } |
1506 | | |
1507 | | |
1508 | | unsigned |
1509 | | dissect_dcom_append_UUID(tvbuff_t *tvb, unsigned offset, |
1510 | | packet_info *pinfo, proto_tree *tree, dcerpc_info *di, uint8_t *drep, |
1511 | | int hfindex, int field_index, e_guid_t *uuid) |
1512 | 0 | { |
1513 | 0 | const char *uuid_name; |
1514 | 0 | proto_item *pi; |
1515 | 0 | header_field_info *hfi; |
1516 | | |
1517 | | |
1518 | | /* XXX - this is far from being performance optimized! */ |
1519 | | |
1520 | | /* get the UUID, but don't put it into the tree */ |
1521 | 0 | offset = dissect_ndr_uuid_t(tvb, offset, pinfo, NULL, di, drep, |
1522 | 0 | hfindex, uuid); |
1523 | | |
1524 | | /* look for a registered uuid name */ |
1525 | 0 | uuid_name = guids_get_guid_name(uuid, pinfo->pool); |
1526 | | |
1527 | | /* add to the tree */ |
1528 | 0 | hfi = proto_registrar_get_nth(hfindex); |
1529 | 0 | pi = proto_tree_add_guid_format(tree, hfindex, tvb, offset-16, 16, (e_guid_t *) uuid, "%s", hfi->name); |
1530 | |
|
1531 | 0 | if (field_index != -1) { |
1532 | 0 | proto_item_append_text(pi, "[%u]: ", field_index); |
1533 | 0 | } else { |
1534 | 0 | proto_item_append_text(pi, ": "); |
1535 | 0 | } |
1536 | |
|
1537 | 0 | if(uuid_name) { |
1538 | 0 | proto_item_append_text(pi, "%s (", uuid_name); |
1539 | 0 | } |
1540 | |
|
1541 | 0 | proto_item_append_text(pi, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", |
1542 | 0 | uuid->data1, uuid->data2, uuid->data3, |
1543 | 0 | uuid->data4[0], uuid->data4[1], |
1544 | 0 | uuid->data4[2], uuid->data4[3], |
1545 | 0 | uuid->data4[4], uuid->data4[5], |
1546 | 0 | uuid->data4[6], uuid->data4[7]); |
1547 | |
|
1548 | 0 | if(uuid_name) { |
1549 | 0 | proto_item_append_text(pi, ")"); |
1550 | 0 | } |
1551 | | |
1552 | | /* update column info now */ |
1553 | 0 | if (field_index != -1) { |
1554 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " %s[%u]=%s", |
1555 | 0 | hfi->name, field_index, (uuid_name) ? uuid_name : "???"); |
1556 | 0 | } else { |
1557 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " %s=%s", |
1558 | 0 | hfi->name, (uuid_name) ? uuid_name : "???"); |
1559 | 0 | } |
1560 | |
|
1561 | 0 | return offset; |
1562 | 0 | } |
1563 | | |
1564 | | |
1565 | | /* get a wide character string from tvb (zero terminated or limited through inLength) */ |
1566 | | /* the string will be converted to ASCII if possible or simple hexdump otherwise */ |
1567 | | /* outLength is in output bytes including zero termination output */ |
1568 | | static unsigned |
1569 | | dcom_tvb_get_nwstringz0(tvbuff_t *tvb, unsigned offset, uint32_t inLength, char *pszStr, uint32_t outLength, bool *isPrintable) |
1570 | 0 | { |
1571 | 0 | uint32_t u32Idx; |
1572 | 0 | uint32_t u32IdxA; |
1573 | 0 | uint32_t u32IdxW; |
1574 | 0 | uint32_t inLengthWithoutNullDelimiter = 0; |
1575 | |
|
1576 | 0 | uint8_t u8Tmp1; |
1577 | 0 | uint8_t u8Tmp2; |
1578 | | |
1579 | |
|
1580 | 0 | *isPrintable = true; |
1581 | 0 | inLengthWithoutNullDelimiter = inLength == 0 ? 0 : inLength -1; |
1582 | | |
1583 | | /* we must have at least the space for the zero termination */ |
1584 | 0 | DISSECTOR_ASSERT(outLength >= 1); |
1585 | | |
1586 | | /* determine length and printability of the string */ |
1587 | 0 | for(u32Idx = 0; u32Idx < inLengthWithoutNullDelimiter; u32Idx+=2) { |
1588 | | /* the marshalling direction of a WCHAR is fixed! */ |
1589 | 0 | u8Tmp1 = tvb_get_uint8(tvb, offset+u32Idx); |
1590 | 0 | u8Tmp2 = tvb_get_uint8(tvb, offset+u32Idx+1); |
1591 | | |
1592 | | /* is this the zero termination? */ |
1593 | 0 | if (u8Tmp1 == 0 && u8Tmp2 == 0) { |
1594 | 0 | u32Idx+=2; |
1595 | 0 | break; |
1596 | 0 | } |
1597 | | |
1598 | | /* is this character printable? */ |
1599 | | /* 10 = New Line, 13 = Carriage Return */ |
1600 | | /* XXX - there are probably more printable chars than isprint() */ |
1601 | 0 | if(!(g_ascii_isprint(u8Tmp1) || u8Tmp1 == 10 || u8Tmp1 == 13)|| u8Tmp2 != 0) { |
1602 | 0 | *isPrintable = false; |
1603 | 0 | } |
1604 | 0 | } |
1605 | | |
1606 | | /* u32Idx now contains the string length in bytes */ |
1607 | | /* (including optional zero termination) */ |
1608 | | |
1609 | | /* if this is a printable string? */ |
1610 | 0 | if(*isPrintable == true) { |
1611 | | /* convert to ascii (every "2nd char") */ |
1612 | | /* XXX - is it possible to convert to UTF8, so the output functions work with it? */ |
1613 | 0 | for(u32IdxA = 0, u32IdxW = 0; |
1614 | 0 | u32IdxW < u32Idx && u32IdxA < outLength-2; |
1615 | 0 | u32IdxW+=2, u32IdxA++) { |
1616 | 0 | pszStr[u32IdxA] = tvb_get_uint8(tvb, offset+u32IdxW); |
1617 | 0 | } |
1618 | 0 | } else { |
1619 | | /* convert to hexdump */ |
1620 | 0 | for(u32IdxA = 0, u32IdxW = 0; |
1621 | 0 | u32IdxW < u32Idx && u32IdxA < outLength-2; |
1622 | 0 | u32IdxW++, u32IdxA+=2) { |
1623 | 0 | snprintf(&pszStr[u32IdxA], 3, "%02X", tvb_get_uint8(tvb, offset+u32IdxW)); |
1624 | 0 | } |
1625 | 0 | } |
1626 | | |
1627 | | /* zero terminate the string, space must be available */ |
1628 | 0 | DISSECTOR_ASSERT(u32IdxA < outLength); |
1629 | 0 | pszStr[u32IdxA] = 0; |
1630 | |
|
1631 | 0 | return offset + u32Idx; |
1632 | 0 | } |
1633 | | |
1634 | | |
1635 | | /* dissect a LPWSTR into a given buffer */ |
1636 | | /* use FT_STRING for hfindex */ |
1637 | | /* u32MaxStr is maximum length of string (including trailing zero) */ |
1638 | | unsigned |
1639 | | dissect_dcom_indexed_LPWSTR(tvbuff_t *tvb, unsigned offset, packet_info *pinfo, |
1640 | | proto_tree *tree, dcerpc_info *di, uint8_t *drep, int hfindex, |
1641 | | char *pszStr, uint32_t u32MaxStr, int field_index) |
1642 | 0 | { |
1643 | 0 | uint32_t u32MaxCount; |
1644 | 0 | uint32_t u32Offset; |
1645 | 0 | uint32_t u32ArraySize; |
1646 | 0 | uint32_t u32StrStart; |
1647 | 0 | proto_item *sub_item; |
1648 | 0 | proto_tree *sub_tree; |
1649 | 0 | uint32_t u32SubStart; |
1650 | 0 | bool isPrintable; |
1651 | | |
1652 | | |
1653 | | /* alignment of 4 needed */ |
1654 | 0 | offset = WS_ROUNDUP_4(offset); |
1655 | | |
1656 | | /* add subtree item */ |
1657 | 0 | sub_item = proto_tree_add_string(tree, hfindex, tvb, offset, 0, ""); |
1658 | 0 | sub_tree = proto_item_add_subtree(sub_item, ett_dcom_lpwstr); |
1659 | 0 | u32SubStart = offset; |
1660 | |
|
1661 | 0 | offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, |
1662 | 0 | hf_dcom_max_count, &u32MaxCount); |
1663 | 0 | offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, |
1664 | 0 | hf_dcom_offset, &u32Offset); |
1665 | 0 | offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, sub_tree, di, drep, |
1666 | 0 | &u32ArraySize); |
1667 | |
|
1668 | 0 | u32StrStart = offset; |
1669 | 0 | offset = dcom_tvb_get_nwstringz0(tvb, offset, u32ArraySize*2, pszStr, u32MaxStr, &isPrintable); |
1670 | |
|
1671 | 0 | proto_tree_add_string(sub_tree, hfindex, tvb, u32StrStart, offset - u32StrStart, pszStr); |
1672 | | |
1673 | | /* update subtree header */ |
1674 | 0 | if (field_index != -1) { |
1675 | 0 | proto_item_set_text(sub_item, "%s[%u]: %s%s%s", |
1676 | 0 | proto_registrar_get_name(hfindex), |
1677 | 0 | field_index, |
1678 | 0 | isPrintable ? "\"" : "", pszStr, isPrintable ? "\"" : ""); |
1679 | 0 | } else { |
1680 | 0 | proto_item_append_text(sub_item, "%s%s%s", |
1681 | 0 | isPrintable ? "\"" : "", pszStr, isPrintable ? "\"" : ""); |
1682 | 0 | } |
1683 | 0 | proto_item_set_len(sub_item, offset - u32SubStart); |
1684 | |
|
1685 | 0 | return offset; |
1686 | 0 | } |
1687 | | |
1688 | | |
1689 | | unsigned |
1690 | | dissect_dcom_LPWSTR(tvbuff_t *tvb, unsigned offset, packet_info *pinfo, |
1691 | | proto_tree *tree, dcerpc_info *di, uint8_t *drep, int hfindex, |
1692 | | char *pszStr, uint32_t u32MaxStr) |
1693 | 0 | { |
1694 | | |
1695 | |
|
1696 | 0 | return dissect_dcom_indexed_LPWSTR(tvb, offset, pinfo, tree, di, drep, |
1697 | 0 | hfindex, pszStr, u32MaxStr, -1); |
1698 | 0 | } |
1699 | | |
1700 | | |
1701 | | /* dissect a BSTR to tree and into a given buffer (use FT_STRING for hfindex) */ |
1702 | | /* u32MaxStr is maximum length of string (including trailing zero) */ |
1703 | | /* (Hint: the BSTR space is always as long as the maximum size) */ |
1704 | | unsigned |
1705 | | dissect_dcom_BSTR(tvbuff_t *tvb, unsigned offset, packet_info *pinfo, |
1706 | | proto_tree *tree, dcerpc_info *di, uint8_t *drep, int hfindex, |
1707 | | char *pszStr, uint32_t u32MaxStr) |
1708 | 0 | { |
1709 | 0 | uint32_t u32MaxCount; |
1710 | 0 | uint32_t u32ArraySize; |
1711 | 0 | int strStart, subStart, realOffset; |
1712 | 0 | proto_item *sub_item; |
1713 | 0 | proto_tree *sub_tree; |
1714 | 0 | uint32_t u32ByteLength; |
1715 | 0 | bool isPrintable; |
1716 | | |
1717 | | /* alignment of 4 needed */ |
1718 | 0 | offset = WS_ROUNDUP_4(offset); |
1719 | | |
1720 | | /* add subtree item */ |
1721 | 0 | sub_item = proto_tree_add_string(tree, hfindex, tvb, offset, 0, ""); |
1722 | 0 | sub_tree = proto_item_add_subtree(sub_item, ett_dcom_lpwstr); |
1723 | 0 | subStart = offset; |
1724 | |
|
1725 | 0 | offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, |
1726 | 0 | hf_dcom_max_count, &u32MaxCount); |
1727 | 0 | offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, |
1728 | 0 | hf_dcom_byte_length, &u32ByteLength); |
1729 | 0 | offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, sub_tree, di, drep, |
1730 | 0 | &u32ArraySize); |
1731 | |
|
1732 | 0 | if ((uint32_t)offset + u32ArraySize*2 > INT_MAX) { |
1733 | 0 | pszStr[0] = 0; |
1734 | 0 | return offset; |
1735 | 0 | } |
1736 | | |
1737 | 0 | realOffset = offset + u32ArraySize*2; |
1738 | |
|
1739 | 0 | strStart = offset; |
1740 | 0 | offset = dcom_tvb_get_nwstringz0(tvb, offset, u32ArraySize*2, pszStr, u32MaxStr, &isPrintable); |
1741 | |
|
1742 | 0 | proto_tree_add_string(sub_tree, hfindex, tvb, strStart, offset - strStart, pszStr); |
1743 | | |
1744 | | /* update subtree header */ |
1745 | 0 | proto_item_append_text(sub_item, "%s%s%s", |
1746 | 0 | isPrintable ? "\"" : "", pszStr, isPrintable ? "\"" : ""); |
1747 | 0 | if (realOffset <= subStart) { |
1748 | | /* XXX - expert info */ |
1749 | 0 | return offset; |
1750 | 0 | } |
1751 | 0 | proto_item_set_len(sub_item, realOffset - subStart); |
1752 | |
|
1753 | 0 | return realOffset; |
1754 | 0 | } |
1755 | | |
1756 | | |
1757 | | /* dissect an DUALSTRINGARRAY */ |
1758 | | unsigned |
1759 | | dissect_dcom_DUALSTRINGARRAY(tvbuff_t *tvb, unsigned offset, packet_info *pinfo, |
1760 | | proto_tree *tree, dcerpc_info *di, uint8_t *drep, int hfindex, char *ip) |
1761 | 0 | { |
1762 | 0 | uint16_t u16NumEntries; |
1763 | 0 | uint16_t u16SecurityOffset; |
1764 | 0 | char szStr[1000]; |
1765 | 0 | uint32_t u32MaxStr = sizeof(szStr); |
1766 | 0 | uint32_t u32Start; |
1767 | 0 | uint16_t u16TowerId; |
1768 | 0 | uint16_t u16SecurityAuthnSvc; |
1769 | 0 | uint16_t u16SecurityAuthzSvc; |
1770 | 0 | proto_item *sub_item; |
1771 | 0 | proto_tree *sub_tree; |
1772 | 0 | uint32_t u32SubStart; |
1773 | 0 | uint32_t u32StringBindings = 0; |
1774 | 0 | uint32_t u32SecurityBindings = 0; |
1775 | 0 | proto_item *subsub_item; |
1776 | 0 | proto_tree *subsub_tree; |
1777 | 0 | uint32_t u32SubSubStart; |
1778 | 0 | bool isPrintable; |
1779 | 0 | uint32_t first_ip = 0; |
1780 | 0 | uint32_t curr_ip = 0; |
1781 | 0 | uint32_t ipaddr; |
1782 | 0 | proto_item *pi; |
1783 | | |
1784 | | |
1785 | | /* add subtree header */ |
1786 | 0 | sub_item = proto_tree_add_item(tree, hfindex, tvb, offset, 0, ENC_BIG_ENDIAN); |
1787 | 0 | sub_tree = proto_item_add_subtree(sub_item, ett_dcom_dualstringarray); |
1788 | |
|
1789 | 0 | offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep, |
1790 | 0 | hf_dcom_dualstringarray_num_entries, &u16NumEntries); |
1791 | | /* from here, alignment is ok */ |
1792 | 0 | u32SubStart = offset - 2; |
1793 | 0 | offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep, |
1794 | 0 | hf_dcom_dualstringarray_security_offset, &u16SecurityOffset); |
1795 | | |
1796 | | /* STRINGBINDINGs until first wchar zero */ |
1797 | 0 | while ( tvb_get_ntohs(tvb, offset) ) { |
1798 | 0 | u32StringBindings++; |
1799 | |
|
1800 | 0 | subsub_item = proto_tree_add_item(sub_tree, hf_dcom_dualstringarray_string, tvb, offset, 0, ENC_NA); |
1801 | 0 | subsub_tree = proto_item_add_subtree(subsub_item, ett_dcom_dualstringarray_binding); |
1802 | 0 | u32SubSubStart = offset; |
1803 | |
|
1804 | 0 | offset = dissect_dcom_WORD(tvb, offset, pinfo, subsub_tree, di, drep, |
1805 | 0 | hf_dcom_dualstringarray_string_tower_id, &u16TowerId); |
1806 | 0 | u32Start = offset; |
1807 | | /* we don't know the (zero terminated) input length, use the buffer length instead */ |
1808 | 0 | offset = dcom_tvb_get_nwstringz0(tvb, offset, u32MaxStr, szStr, u32MaxStr, &isPrintable); |
1809 | 0 | pi = proto_tree_add_string(subsub_tree, hf_dcom_dualstringarray_string_network_addr, |
1810 | 0 | tvb, u32Start, offset - u32Start, szStr); |
1811 | | |
1812 | | /* convert ip address (if it is dotted decimal) */ |
1813 | | /* XXX - this conversion is ugly */ |
1814 | 0 | if (ws_inet_pton4(szStr, &ipaddr)) { |
1815 | 0 | if(get_host_ipaddr(szStr, &curr_ip)) { |
1816 | | |
1817 | | /*expert_add_info_format(pinfo, NULL, PI_UNDECODED, PI_WARN, "DUALSTRINGARRAY: IP:%s", |
1818 | | ip_to_str( (uint8_t *) &curr_ip));*/ |
1819 | |
|
1820 | 0 | if(first_ip == 0) { |
1821 | 0 | if(ip != NULL) { |
1822 | 0 | memcpy(ip, &curr_ip, sizeof(curr_ip)); |
1823 | 0 | } |
1824 | 0 | first_ip = curr_ip; |
1825 | 0 | } else { |
1826 | 0 | if(first_ip != curr_ip) { |
1827 | 0 | address first_ip_addr, curr_ip_addr; |
1828 | |
|
1829 | 0 | set_address(&first_ip_addr, AT_IPv4, 4, &first_ip); |
1830 | 0 | set_address(&curr_ip_addr, AT_IPv4, 4, &curr_ip); |
1831 | 0 | expert_add_info_format(pinfo, pi, &ei_dcom_dualstringarray_mult_ip, |
1832 | 0 | "DUALSTRINGARRAY: multiple IP's %s %s", |
1833 | 0 | address_to_str(pinfo->pool, &first_ip_addr), address_to_str(pinfo->pool, &curr_ip_addr)); |
1834 | 0 | } |
1835 | 0 | } |
1836 | 0 | } |
1837 | 0 | } |
1838 | |
|
1839 | 0 | proto_item_append_text(subsub_item, "[%u]: TowerId=%s, NetworkAddr=\"%s\"", |
1840 | 0 | u32StringBindings, |
1841 | 0 | val_to_str(pinfo->pool, u16TowerId, dcom_protseq_vals, "Unknown (0x%04x"), |
1842 | 0 | szStr); |
1843 | 0 | proto_item_set_len(subsub_item, offset - u32SubSubStart); |
1844 | 0 | } |
1845 | 0 | offset += 2; |
1846 | | |
1847 | | /* SECURITYBINDINGs until first wchar zero */ |
1848 | 0 | while ( tvb_get_ntohs(tvb, offset) ) { |
1849 | 0 | u32SecurityBindings++; |
1850 | |
|
1851 | 0 | subsub_item = proto_tree_add_item(sub_tree, hf_dcom_dualstringarray_security, tvb, offset, 0, ENC_NA); |
1852 | 0 | subsub_tree = proto_item_add_subtree(subsub_item, ett_dcom_dualstringarray_binding); |
1853 | 0 | u32SubSubStart = offset; |
1854 | |
|
1855 | 0 | offset = dissect_dcom_WORD(tvb, offset, pinfo, subsub_tree, di, drep, |
1856 | 0 | hf_dcom_dualstringarray_security_authn_svc, |
1857 | 0 | &u16SecurityAuthnSvc); |
1858 | 0 | offset = dissect_dcom_WORD(tvb, offset, pinfo, subsub_tree, di, drep, |
1859 | 0 | hf_dcom_dualstringarray_security_authz_svc, |
1860 | 0 | &u16SecurityAuthzSvc); |
1861 | |
|
1862 | 0 | u32Start = offset; |
1863 | | /* we don't know the (zero terminated) input length, use the buffer length instead */ |
1864 | 0 | offset = dcom_tvb_get_nwstringz0(tvb, offset, u32MaxStr, szStr, u32MaxStr, &isPrintable); |
1865 | 0 | proto_tree_add_string(subsub_tree, hf_dcom_dualstringarray_security_princ_name, |
1866 | 0 | tvb, u32Start, offset - u32Start, szStr); |
1867 | |
|
1868 | 0 | proto_item_append_text(subsub_item, "[%u]: AuthnSvc=0x%04x, AuthzSvc=0x%04x, PrincName=\"%s\"", |
1869 | 0 | u32SecurityBindings, u16SecurityAuthnSvc, u16SecurityAuthzSvc, szStr); |
1870 | 0 | proto_item_set_len(subsub_item, offset - u32SubSubStart); |
1871 | 0 | } |
1872 | 0 | offset += 2; |
1873 | | |
1874 | | /* append info to subtree header */ |
1875 | 0 | proto_item_append_text(sub_item, ": STRINGBINDINGs=%u, SECURITYBINDINGs=%u", |
1876 | 0 | u32StringBindings, u32SecurityBindings); |
1877 | 0 | proto_item_set_len(sub_item, offset - u32SubStart); |
1878 | |
|
1879 | 0 | return offset; |
1880 | 0 | } |
1881 | | |
1882 | | |
1883 | | /* dissect an STDOBJREF */ |
1884 | | unsigned |
1885 | | dissect_dcom_STDOBJREF(tvbuff_t *tvb, unsigned offset, packet_info *pinfo, |
1886 | | proto_tree *tree, dcerpc_info *di, uint8_t *drep, int hfindex _U_, |
1887 | | uint64_t *oxid, uint64_t *oid, e_guid_t *ipid) |
1888 | 0 | { |
1889 | 0 | uint32_t u32Flags; |
1890 | 0 | uint32_t u32PublicRefs; |
1891 | 0 | proto_item *sub_item; |
1892 | 0 | proto_tree *sub_tree; |
1893 | 0 | uint32_t u32SubStart; |
1894 | | |
1895 | | |
1896 | | /* add subtree header */ |
1897 | 0 | sub_item = proto_tree_add_item(tree, hf_dcom_stdobjref, tvb, offset, 0, ENC_NA); |
1898 | 0 | sub_tree = proto_item_add_subtree(sub_item, ett_dcom_stdobjref); |
1899 | |
|
1900 | 0 | offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, |
1901 | 0 | hf_dcom_stdobjref_flags, &u32Flags); |
1902 | | /* from here, alignment is ok */ |
1903 | 0 | u32SubStart = offset - 4; |
1904 | 0 | offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, |
1905 | 0 | hf_dcom_stdobjref_public_refs, &u32PublicRefs); |
1906 | 0 | offset = dissect_dcom_ID(tvb, offset, pinfo, sub_tree, di, drep, |
1907 | 0 | hf_dcom_oxid, oxid); |
1908 | 0 | offset = dissect_dcom_ID(tvb, offset, pinfo, sub_tree, di, drep, |
1909 | 0 | hf_dcom_oid, oid); |
1910 | 0 | offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, di, drep, |
1911 | 0 | hf_dcom_ipid, ipid); |
1912 | | |
1913 | | /* append info to subtree header */ |
1914 | 0 | proto_item_append_text(sub_item, ": PublicRefs=%u IPID=%s", |
1915 | 0 | u32PublicRefs, guids_resolve_guid_to_str(ipid, pinfo->pool)); |
1916 | 0 | proto_item_set_len(sub_item, offset - u32SubStart); |
1917 | |
|
1918 | 0 | return offset; |
1919 | 0 | } |
1920 | | |
1921 | | |
1922 | | |
1923 | | /* |
1924 | | * |
1925 | | *static void |
1926 | | *print_uuid(const e_guid_t* uuid) |
1927 | | *{ |
1928 | | * proto_tree_add_debug_text(NULL, "UUID:(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)\n", |
1929 | | * uuid->data1, uuid->data2, uuid->data3, |
1930 | | * uuid->data4[0], uuid->data4[1], |
1931 | | * uuid->data4[2], uuid->data4[3], |
1932 | | * uuid->data4[4], uuid->data4[5], |
1933 | | * uuid->data4[6], uuid->data4[7]); |
1934 | | * |
1935 | | * return; |
1936 | | *} |
1937 | | * |
1938 | | */ |
1939 | | |
1940 | | unsigned |
1941 | | dcom_register_routine(dcom_dissect_fn_t routine, e_guid_t* uuid) |
1942 | 0 | { |
1943 | 0 | dcom_marshaler_t *marshaler; |
1944 | | |
1945 | | |
1946 | | /* check if exists already */ |
1947 | 0 | if (dcom_get_routine_by_uuid(uuid)) |
1948 | 0 | return -1; |
1949 | | |
1950 | 0 | marshaler = wmem_new(wmem_file_scope(), dcom_marshaler_t); |
1951 | 0 | if (!marshaler) { |
1952 | | /*memory error*/ |
1953 | 0 | return -1; |
1954 | 0 | } |
1955 | | |
1956 | 0 | marshaler->parent = NULL; |
1957 | 0 | marshaler->private_data = NULL; |
1958 | 0 | marshaler->uuid = *uuid; |
1959 | 0 | marshaler->routine = routine; |
1960 | |
|
1961 | 0 | dcom_marshalers = g_list_append(dcom_marshalers, marshaler); |
1962 | |
|
1963 | 0 | return 0; |
1964 | 0 | } |
1965 | | |
1966 | | |
1967 | | dcom_dissect_fn_t |
1968 | | dcom_get_routine_by_uuid(const e_guid_t* uuid) |
1969 | 0 | { |
1970 | 0 | dcom_marshaler_t *marsh; |
1971 | 0 | GList *marshalers; |
1972 | |
|
1973 | 0 | if(memcmp(uuid, &uuid_null, sizeof(uuid_null)) == 0) { |
1974 | 0 | return NULL; |
1975 | 0 | } |
1976 | | |
1977 | 0 | for(marshalers = dcom_marshalers; marshalers!= NULL; |
1978 | 0 | marshalers = g_list_next(marshalers)) { |
1979 | 0 | marsh = (dcom_marshaler_t *)marshalers->data; |
1980 | | /*print_uuid(&marsh->uuid);*/ |
1981 | | /*print_uuid(uuid);*/ |
1982 | 0 | if(memcmp(&marsh->uuid, uuid, sizeof(e_guid_t)) == 0) { |
1983 | 0 | return marsh->routine; |
1984 | 0 | } |
1985 | 0 | } |
1986 | | |
1987 | 0 | return NULL; |
1988 | 0 | } |
1989 | | |
1990 | | /* dissect an CUSTOM */ |
1991 | | static unsigned |
1992 | | dissect_dcom_CUSTOBJREF(tvbuff_t *tvb, unsigned offset, packet_info *pinfo, |
1993 | | proto_tree *tree, dcerpc_info *di, uint8_t *drep, int hfindex, |
1994 | | e_guid_t *clsid, e_guid_t *iid) |
1995 | 0 | { |
1996 | 0 | uint32_t u32CBExtension; |
1997 | 0 | uint32_t u32Size; |
1998 | 0 | uint32_t u32SubStart; |
1999 | 0 | proto_item *sub_item; |
2000 | 0 | proto_tree *sub_tree; |
2001 | 0 | dcom_dissect_fn_t routine = NULL; |
2002 | | |
2003 | | |
2004 | | /* add subtree header */ |
2005 | 0 | hfindex = hf_dcom_custobjref; |
2006 | 0 | sub_item = proto_tree_add_item(tree, hfindex, tvb, offset, 0, ENC_NA); |
2007 | 0 | sub_tree = proto_item_add_subtree(sub_item, ett_dcom_custobjref); |
2008 | |
|
2009 | 0 | u32SubStart = offset; |
2010 | 0 | offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, di, drep, |
2011 | 0 | hf_dcom_clsid, clsid); |
2012 | 0 | offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, |
2013 | 0 | hf_dcom_objref_cbextension, &u32CBExtension); |
2014 | 0 | offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, |
2015 | 0 | hf_dcom_objref_size, &u32Size); |
2016 | | |
2017 | | /* the following data depends on the iid, get the routine by iid */ |
2018 | 0 | routine = dcom_get_routine_by_uuid(iid); |
2019 | 0 | if (routine){ |
2020 | 0 | offset = routine(tvb, offset, pinfo, sub_tree, di, drep, u32Size); |
2021 | 0 | } |
2022 | | |
2023 | | /* append info to subtree header */ |
2024 | | /* proto_item_append_text(sub_item, ": ActivationPropertiesIn"); */ |
2025 | 0 | proto_item_set_len(sub_item, offset - u32SubStart); |
2026 | |
|
2027 | 0 | return offset; |
2028 | 0 | } |
2029 | | |
2030 | | /* dissect an OBJREF */ |
2031 | | unsigned |
2032 | | dissect_dcom_OBJREF(tvbuff_t *tvb, unsigned offset, packet_info *pinfo, |
2033 | | proto_tree *tree, dcerpc_info *di, uint8_t *drep, int hfindex, dcom_interface_t **interf) |
2034 | 0 | { |
2035 | 0 | uint32_t u32Signature; |
2036 | 0 | uint32_t u32Flags; |
2037 | 0 | e_guid_t iid; |
2038 | 0 | e_guid_t clsid; |
2039 | 0 | proto_item *sub_item; |
2040 | 0 | proto_tree *sub_tree; |
2041 | 0 | uint32_t u32SubStart; |
2042 | 0 | uint64_t oxid = 0; |
2043 | 0 | uint64_t oid = 0; |
2044 | 0 | e_guid_t ipid; |
2045 | 0 | dcom_interface_t *dcom_if = NULL; |
2046 | 0 | char ip[4]; |
2047 | |
|
2048 | 0 | memset(&ipid, 0, sizeof(ipid)); |
2049 | 0 | memset(ip, 0, sizeof(ip)); |
2050 | | |
2051 | | /* add subtree header */ |
2052 | 0 | sub_item = proto_tree_add_item(tree, hf_dcom_objref, tvb, offset, 0, ENC_NA); |
2053 | 0 | sub_tree = proto_item_add_subtree(sub_item, ett_dcom_objref); |
2054 | |
|
2055 | 0 | offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, |
2056 | 0 | hf_dcom_objref_signature, &u32Signature); |
2057 | | /* from here, alignment is ok */ |
2058 | 0 | u32SubStart = offset - 4; |
2059 | 0 | offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, |
2060 | 0 | hf_dcom_objref_flags, &u32Flags); |
2061 | 0 | offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, di, drep, |
2062 | 0 | hf_dcom_iid, &iid); |
2063 | |
|
2064 | 0 | switch(u32Flags) { |
2065 | 0 | case(0x1): /* standard */ |
2066 | 0 | offset = dissect_dcom_STDOBJREF(tvb, offset, pinfo, sub_tree, di, drep, hfindex, |
2067 | 0 | &oxid, &oid, &ipid); |
2068 | 0 | offset = dissect_dcom_DUALSTRINGARRAY(tvb, offset, pinfo, sub_tree, di, drep, |
2069 | 0 | hf_dcom_objref_resolver_address, ip); |
2070 | 0 | break; |
2071 | 0 | case(0x2): /* handler (untested) */ |
2072 | 0 | offset = dissect_dcom_STDOBJREF(tvb, offset, pinfo, sub_tree, di, drep, hfindex, |
2073 | 0 | &oxid, &oid, &iid); |
2074 | 0 | offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, di, drep, |
2075 | 0 | hf_dcom_clsid, &clsid); |
2076 | 0 | offset = dissect_dcom_DUALSTRINGARRAY(tvb, offset, pinfo, sub_tree, di, drep, |
2077 | 0 | hf_dcom_objref_resolver_address, ip); |
2078 | 0 | break; |
2079 | 0 | case(0x4): /* custom */ |
2080 | 0 | offset = dissect_dcom_CUSTOBJREF(tvb, offset, pinfo, sub_tree, di, drep, hfindex, |
2081 | 0 | &clsid, &iid); |
2082 | 0 | break; |
2083 | 0 | } |
2084 | | |
2085 | 0 | if(u32Flags == 0x1 || u32Flags == 0x2) { |
2086 | | /* add interface instance to database (we currently only handle IPv4) */ |
2087 | 0 | if(pinfo->net_src.type == AT_IPv4) { |
2088 | 0 | address addr; |
2089 | |
|
2090 | 0 | set_address(&addr, AT_IPv4, 4, ip); |
2091 | 0 | dcom_if = dcom_interface_new(pinfo, |
2092 | 0 | &addr, |
2093 | 0 | &iid, oxid, oid, &ipid); |
2094 | 0 | } |
2095 | 0 | } |
2096 | |
|
2097 | 0 | if(interf != NULL) { |
2098 | 0 | *interf = dcom_if; |
2099 | 0 | } |
2100 | | |
2101 | | /* append info to subtree header */ |
2102 | 0 | proto_item_set_len(sub_item, offset - u32SubStart); |
2103 | |
|
2104 | 0 | return offset; |
2105 | 0 | } |
2106 | | |
2107 | | /* dissect an MInterfacePointer */ |
2108 | | unsigned |
2109 | | dissect_dcom_MInterfacePointer(tvbuff_t *tvb, unsigned offset, packet_info *pinfo, |
2110 | | proto_tree *tree, dcerpc_info *di, uint8_t *drep, int hfindex, dcom_interface_t **interf) |
2111 | 0 | { |
2112 | 0 | uint32_t u32CntData; |
2113 | 0 | uint32_t u32ArraySize; |
2114 | 0 | proto_item *sub_item; |
2115 | 0 | proto_tree *sub_tree; |
2116 | 0 | uint32_t u32SubStart; |
2117 | | |
2118 | |
|
2119 | 0 | if (!hfindex) { |
2120 | 0 | hfindex = hf_dcom_interface_pointer; |
2121 | 0 | } |
2122 | | |
2123 | | /* add subtree header */ |
2124 | 0 | sub_item = proto_tree_add_item(tree, hfindex, tvb, offset, 0, ENC_BIG_ENDIAN); |
2125 | 0 | sub_tree = proto_item_add_subtree(sub_item, ett_dcom_interface_pointer); |
2126 | |
|
2127 | 0 | offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, sub_tree, di, drep, &u32ArraySize); |
2128 | 0 | u32SubStart = offset - 4; /* should use this trick to deal with align pad if any */ |
2129 | |
|
2130 | 0 | offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, |
2131 | 0 | hf_dcom_ip_cnt_data, &u32CntData); |
2132 | |
|
2133 | 0 | offset = dissect_dcom_OBJREF(tvb, offset, pinfo, sub_tree, di, drep, hfindex, interf); |
2134 | | |
2135 | | /* append info to subtree header */ |
2136 | 0 | proto_item_set_len(sub_item, offset - u32SubStart); |
2137 | |
|
2138 | 0 | return offset; |
2139 | 0 | } |
2140 | | |
2141 | | /* dissect a pointer to a MInterfacePointer */ |
2142 | | unsigned |
2143 | | dissect_dcom_PMInterfacePointer(tvbuff_t *tvb, unsigned offset, packet_info *pinfo, |
2144 | | proto_tree *tree, dcerpc_info *di, uint8_t *drep, int hfindex, dcom_interface_t **interf) |
2145 | 0 | { |
2146 | 0 | uint32_t u32Pointer; |
2147 | | |
2148 | |
|
2149 | 0 | offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, &u32Pointer); |
2150 | |
|
2151 | 0 | if (u32Pointer) { |
2152 | 0 | offset = dissect_dcom_MInterfacePointer(tvb, offset, pinfo, tree, di, drep, hfindex, interf); |
2153 | 0 | } else { |
2154 | 0 | if(interf != NULL) { |
2155 | 0 | *interf = NULL; |
2156 | 0 | } |
2157 | 0 | } |
2158 | |
|
2159 | 0 | return offset; |
2160 | 0 | } |
2161 | | |
2162 | 0 | static void dcom_cleanup(void) { |
2163 | 0 | if (dcom_machines != NULL) { |
2164 | 0 | GList *machines; |
2165 | |
|
2166 | 0 | for(machines = dcom_machines; machines != NULL; machines = g_list_next(machines)) { |
2167 | 0 | dcom_machine_t *machine = (dcom_machine_t *)machines->data; |
2168 | |
|
2169 | 0 | if (machine->objects != NULL) { |
2170 | 0 | GList *objects; |
2171 | 0 | for(objects = machine->objects; objects != NULL; objects = g_list_next(objects)) { |
2172 | 0 | dcom_object_t *object = (dcom_object_t *)objects->data; |
2173 | |
|
2174 | 0 | if (object->interfaces != NULL) { |
2175 | 0 | GList *interface; |
2176 | 0 | for(interface = object->interfaces; interface != NULL; interface = g_list_next(interface)) { |
2177 | 0 | g_free(interface->data); |
2178 | 0 | interface->data = NULL; /* for good measure */ |
2179 | 0 | } |
2180 | 0 | g_list_free(object->interfaces); |
2181 | 0 | object->interfaces = NULL; /* for good measure */ |
2182 | 0 | } |
2183 | |
|
2184 | 0 | g_free(objects->data); |
2185 | 0 | objects->data = NULL; /* for good measure */ |
2186 | 0 | } |
2187 | 0 | g_list_free(machine->objects); |
2188 | 0 | free_address(&machine->ip); |
2189 | 0 | machine->objects = NULL; /* for good measure */ |
2190 | 0 | } |
2191 | |
|
2192 | 0 | g_free(machines->data); |
2193 | 0 | machines->data = NULL; /* for good measure */ |
2194 | 0 | } |
2195 | 0 | g_list_free(dcom_machines); |
2196 | 0 | dcom_machines = NULL; |
2197 | 0 | } |
2198 | | |
2199 | | /* The data in dcom_interfaces is wmem_file_scoped so there's no need to free |
2200 | | * the data pointers. |
2201 | | */ |
2202 | 0 | if (dcom_interfaces != NULL) { |
2203 | 0 | g_list_free(dcom_interfaces); |
2204 | 0 | dcom_interfaces = NULL; |
2205 | 0 | } |
2206 | | |
2207 | | /* The data in dcom_marshalers is wmem_file_scoped so there's no need to free |
2208 | | * the data pointers. |
2209 | | */ |
2210 | 0 | if (dcom_marshalers != NULL) { |
2211 | 0 | g_list_free(dcom_marshalers); |
2212 | 0 | dcom_marshalers = NULL; |
2213 | 0 | } |
2214 | 0 | } |
2215 | | |
2216 | | void |
2217 | | proto_register_dcom (void) |
2218 | 14 | { |
2219 | 14 | static hf_register_info hf_dcom_this_array[] = { |
2220 | | #if 0 |
2221 | | { &hf_dcom_this_version_major, |
2222 | | { "VersionMajor", "dcom.this.version_major", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
2223 | | #endif |
2224 | | #if 0 |
2225 | | { &hf_dcom_this_version_minor, |
2226 | | { "VersionMinor", "dcom.this.version_minor", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
2227 | | #endif |
2228 | 14 | { &hf_dcom_this_flags, |
2229 | 14 | { "Flags", "dcom.this.flags", FT_UINT32, BASE_HEX, VALS(dcom_thisthat_flag_vals), 0x0, NULL, HFILL }}, |
2230 | 14 | { &hf_dcom_this_res, |
2231 | 14 | { "Reserved", "dcom.this.res", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
2232 | 14 | { &hf_dcom_this_cid, |
2233 | 14 | { "Causality ID", "dcom.this.uuid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }} |
2234 | 14 | }; |
2235 | | |
2236 | 14 | static hf_register_info hf_dcom_that_array[] = { |
2237 | 14 | { &hf_dcom_that_flags, |
2238 | 14 | { "Flags", "dcom.that.flags", FT_UINT32, BASE_HEX, VALS(dcom_thisthat_flag_vals), 0x0, NULL, HFILL }} |
2239 | 14 | }; |
2240 | | |
2241 | 14 | static hf_register_info hf_dcom_extent_array[] = { |
2242 | 14 | { &hf_dcom_extent, |
2243 | 14 | { "Extension", "dcom.extent", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
2244 | 14 | { &hf_dcom_extent_array_count, |
2245 | 14 | { "Extension Count", "dcom.extent.array_count", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
2246 | 14 | { &hf_dcom_extent_array_res, |
2247 | 14 | { "Reserved", "dcom.extent.array_res", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
2248 | 14 | { &hf_dcom_extent_size, |
2249 | 14 | { "Extension Size", "dcom.extent.size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
2250 | 14 | { &hf_dcom_extent_id, |
2251 | 14 | { "Extension Id", "dcom.extent.id", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }} |
2252 | 14 | }; |
2253 | | |
2254 | 14 | static hf_register_info hf_dcom_array[] = { |
2255 | 14 | { &hf_dcom_version_major, |
2256 | 14 | { "VersionMajor", "dcom.version_major", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
2257 | 14 | { &hf_dcom_version_minor, |
2258 | 14 | { "VersionMinor", "dcom.version_minor", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
2259 | 14 | { &hf_dcom_hresult, |
2260 | 14 | { "HResult", "dcom.hresult", FT_UINT32, BASE_HEX, VALS(dcom_hresult_vals), 0x0, NULL, HFILL }}, |
2261 | 14 | { &hf_dcom_max_count, |
2262 | 14 | { "MaxCount", "dcom.max_count", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
2263 | 14 | { &hf_dcom_offset, |
2264 | 14 | { "Offset", "dcom.offset", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
2265 | 14 | { &hf_dcom_byte_length, |
2266 | 14 | { "ByteLength", "dcom.byte_length", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
2267 | | #if 0 |
2268 | | { &hf_dcom_actual_count, |
2269 | | { "ActualCount", "dcom.actual_count", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
2270 | | #endif |
2271 | 14 | { &hf_dcom_tobedone, |
2272 | 14 | { "To Be Done", "dcom.tobedone", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
2273 | 14 | { &hf_dcom_nospec, |
2274 | 14 | { "No Specification Available", "dcom.nospec", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
2275 | | #if 0 |
2276 | | { &hf_dcom_variant, |
2277 | | { "Variant", "dcom.variant", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
2278 | | #endif |
2279 | 14 | { &hf_dcom_variant_type, |
2280 | 14 | { "VarType", "dcom.variant_type", FT_UINT16, BASE_HEX, VALS(dcom_variant_type_vals), 0x0, NULL, HFILL }}, |
2281 | 14 | { &hf_dcom_variant_type32, |
2282 | 14 | { "VarType32", "dcom.variant_type32", FT_UINT32, BASE_HEX, VALS(dcom_variant_type_vals), 0x0, NULL, HFILL }}, |
2283 | 14 | { &hf_dcom_variant_size, |
2284 | 14 | { "Size", "dcom.variant_size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
2285 | 14 | { &hf_dcom_variant_rpc_res, |
2286 | 14 | { "RPC-Reserved", "dcom.variant_rpc_res", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
2287 | 14 | { &hf_dcom_variant_wres, |
2288 | 14 | { "Reserved", "dcom.variant_wres", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
2289 | 14 | { &hf_dcom_array_size, |
2290 | 14 | { "(ArraySize)", "dcom.array_size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
2291 | 14 | { &hf_dcom_pointer_val, |
2292 | 14 | { "(PointerVal)", "dcom.pointer_val", FT_UINT32, BASE_HEX, VALS(dcom_dcerpc_pointer_vals), 0x0, NULL, HFILL }} |
2293 | 14 | }; |
2294 | | |
2295 | 14 | static hf_register_info hf_dcom_interface_pointer_array[] = { |
2296 | 14 | { &hf_dcom_interface_pointer, |
2297 | 14 | { "InterfacePointer", "dcom.ifp", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
2298 | 14 | { &hf_dcom_ip_cnt_data, |
2299 | 14 | { "CntData", "dcom.ip_cnt_data", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }} |
2300 | 14 | }; |
2301 | | |
2302 | 14 | static hf_register_info hf_dcom_objref_array[] = { |
2303 | 14 | { &hf_dcom_objref, |
2304 | 14 | { "OBJREF", "dcom.objref", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
2305 | 14 | { &hf_dcom_objref_signature, |
2306 | 14 | { "Signature", "dcom.objref.signature", FT_UINT32, BASE_HEX, VALS(dcom_objref_signature_vals), 0x0, NULL, HFILL }}, |
2307 | 14 | { &hf_dcom_objref_flags, |
2308 | 14 | { "Flags", "dcom.objref.flags", FT_UINT32, BASE_HEX, VALS(dcom_objref_flag_vals), 0x0, NULL, HFILL }}, |
2309 | 14 | { &hf_dcom_iid, |
2310 | 14 | { "IID", "dcom.iid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
2311 | 14 | { &hf_dcom_clsid, |
2312 | 14 | { "CLSID", "dcom.clsid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
2313 | 14 | { &hf_dcom_objref_resolver_address, |
2314 | 14 | { "ResolverAddress", "dcom.objref.resolver_address", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
2315 | 14 | { &hf_dcom_objref_cbextension, |
2316 | 14 | { "CBExtension", "dcom.objref.cbextension", FT_UINT32, BASE_DEC, NULL, 0x0, "Size of extension data", HFILL }}, |
2317 | 14 | { &hf_dcom_objref_size, |
2318 | 14 | { "Size", "dcom.objref.size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }} |
2319 | 14 | }; |
2320 | | |
2321 | 14 | static hf_register_info hf_dcom_stdobjref_array[] = { |
2322 | 14 | { &hf_dcom_stdobjref, |
2323 | 14 | { "STDOBJREF", "dcom.stdobjref", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
2324 | 14 | { &hf_dcom_stdobjref_flags, |
2325 | 14 | { "Flags", "dcom.stdobjref.flags", FT_UINT32, BASE_HEX, VALS(dcom_stdobjref_flag_vals), 0x0, NULL, HFILL }}, |
2326 | 14 | { &hf_dcom_stdobjref_public_refs, |
2327 | 14 | { "PublicRefs", "dcom.stdobjref.public_refs", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
2328 | 14 | { &hf_dcom_oxid, |
2329 | 14 | { "OXID", "dcom.oxid", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
2330 | 14 | { &hf_dcom_oid, |
2331 | 14 | { "OID", "dcom.oid", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
2332 | 14 | { &hf_dcom_ipid, |
2333 | 14 | { "IPID", "dcom.ipid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }} |
2334 | 14 | }; |
2335 | | |
2336 | 14 | static hf_register_info hf_dcom_custobjref_array[] = { |
2337 | 14 | { &hf_dcom_custobjref, |
2338 | 14 | { "CUSTOMOBJREF", "dcom.custobjref", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
2339 | 14 | }; |
2340 | | |
2341 | | |
2342 | 14 | static hf_register_info hf_dcom_dualstringarray_array[] = { |
2343 | 14 | { &hf_dcom_dualstringarray_num_entries, |
2344 | 14 | { "NumEntries", "dcom.dualstringarray.num_entries", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
2345 | 14 | { &hf_dcom_dualstringarray_security_offset, |
2346 | 14 | { "SecurityOffset", "dcom.dualstringarray.security_offset", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
2347 | 14 | { &hf_dcom_dualstringarray_string, |
2348 | 14 | { "StringBinding", "dcom.dualstringarray.string", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
2349 | 14 | { &hf_dcom_dualstringarray_string_tower_id, |
2350 | 14 | { "TowerId", "dcom.dualstringarray.tower_id", FT_UINT16, BASE_HEX, VALS(dcom_protseq_vals), 0x0, NULL, HFILL }}, |
2351 | 14 | { &hf_dcom_dualstringarray_string_network_addr, |
2352 | 14 | { "NetworkAddr", "dcom.dualstringarray.network_addr", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
2353 | 14 | { &hf_dcom_dualstringarray_security, |
2354 | 14 | { "SecurityBinding", "dcom.dualstringarray.security", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
2355 | 14 | { &hf_dcom_dualstringarray_security_authn_svc, |
2356 | 14 | { "AuthnSvc", "dcom.dualstringarray.security_authn_svc", FT_UINT16, BASE_HEX, VALS(dcom_dualstringarray_authn), 0x0, NULL, HFILL }}, |
2357 | 14 | { &hf_dcom_dualstringarray_security_authz_svc, |
2358 | 14 | { "AuthzSvc", "dcom.dualstringarray.security_authz_svc", FT_UINT16, BASE_HEX, VALS(dcom_dualstringarray_authz), 0x0, NULL, HFILL }}, |
2359 | 14 | { &hf_dcom_dualstringarray_security_princ_name, |
2360 | 14 | { "PrincName", "dcom.dualstringarray.security_princ_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }} |
2361 | 14 | }; |
2362 | | |
2363 | 14 | static hf_register_info hf_dcom_vt_array[] = { |
2364 | 14 | { &hf_dcom_vt_bool, |
2365 | 14 | { "VT_BOOL", "dcom.vt.bool", FT_UINT16, BASE_HEX, VALS(dcom_vt_bool_vals), 0x0, NULL, HFILL }}, |
2366 | 14 | { &hf_dcom_vt_i1, |
2367 | 14 | { "VT_I1", "dcom.vt.i1", FT_INT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
2368 | 14 | { &hf_dcom_vt_i2, |
2369 | 14 | { "VT_I2", "dcom.vt.i2", FT_INT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
2370 | 14 | { &hf_dcom_vt_i4, |
2371 | 14 | { "VT_I4", "dcom.vt.i4", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
2372 | 14 | { &hf_dcom_vt_i8, |
2373 | 14 | { "VT_I8", "dcom.vt.i8", FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
2374 | 14 | { &hf_dcom_vt_cy, |
2375 | 14 | { "VT_CY", "dcom.vt.cy", FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
2376 | 14 | { &hf_dcom_vt_ui1, |
2377 | 14 | { "VT_UI1", "dcom.vt.ui1", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
2378 | 14 | { &hf_dcom_vt_ui2, |
2379 | 14 | { "VT_UI2", "dcom.vt.ui2", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
2380 | 14 | { &hf_dcom_vt_ui4, |
2381 | 14 | { "VT_UI4", "dcom.vt.ui4", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
2382 | 14 | { &hf_dcom_vt_ui8, |
2383 | 14 | { "VT_UI8", "dcom.vt.ui8", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
2384 | 14 | { &hf_dcom_vt_r4, |
2385 | 14 | { "VT_R4", "dcom.vt.r4", FT_FLOAT, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
2386 | 14 | { &hf_dcom_vt_r8, |
2387 | 14 | { "VT_R8", "dcom.vt.r8", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
2388 | 14 | { &hf_dcom_vt_date, |
2389 | 14 | { "VT_DATE", "dcom.vt.date", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
2390 | 14 | { &hf_dcom_vt_bstr, |
2391 | 14 | { "VT_BSTR", "dcom.vt.bstr", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
2392 | 14 | { &hf_dcom_vt_byref, |
2393 | 14 | { "BYREF", "dcom.vt.byref", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
2394 | 14 | { &hf_dcom_vt_dispatch, |
2395 | 14 | { "VT_DISPATCH", "dcom.vt.dispatch", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }} |
2396 | 14 | }; |
2397 | | |
2398 | 14 | static hf_register_info hf_dcom_sa_array[] = { |
2399 | 14 | { &hf_dcom_safearray, |
2400 | 14 | { "SAFEARRAY", "dcom.sa", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
2401 | 14 | { &hf_dcom_sa_dims32, |
2402 | 14 | { "Dims32", "dcom.sa.dims32", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
2403 | 14 | { &hf_dcom_sa_dims16, |
2404 | 14 | { "Dims16", "dcom.sa.dims16", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
2405 | 14 | { &hf_dcom_sa_features, |
2406 | 14 | { "Features", "dcom.sa.features", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
2407 | 14 | { &hf_dcom_sa_element_size, |
2408 | 14 | { "ElementSize", "dcom.sa.element_size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
2409 | 14 | { &hf_dcom_sa_locks, |
2410 | 14 | { "Locks", "dcom.sa.locks", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
2411 | 14 | { &hf_dcom_sa_vartype32, |
2412 | 14 | { "VarType32", "dcom.sa.vartype", FT_UINT32, BASE_DEC, VALS(dcom_variant_type_vals), 0x0, NULL, HFILL }}, |
2413 | 14 | { &hf_dcom_sa_vartype16, |
2414 | 14 | { "VarType16", "dcom.sa.vartype", FT_UINT16, BASE_DEC, VALS(dcom_variant_type_vals), 0x0, NULL, HFILL }}, |
2415 | 14 | { &hf_dcom_sa_elements, |
2416 | 14 | { "Elements", "dcom.sa.elements", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
2417 | 14 | { &hf_dcom_sa_bound_elements, |
2418 | 14 | { "BoundElements", "dcom.sa.bound_elements", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
2419 | 14 | { &hf_dcom_sa_low_bound, |
2420 | 14 | { "LowBound", "dcom.sa.low_bound", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
2421 | | |
2422 | 14 | { &hf_dcom_sa_features_auto, |
2423 | 14 | { "AUTO", "dcom.sa.features_auto", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_AUTO, NULL, HFILL }}, |
2424 | 14 | { &hf_dcom_sa_features_static, |
2425 | 14 | { "STATIC", "dcom.sa.features_static", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_STATIC, NULL, HFILL }}, |
2426 | 14 | { &hf_dcom_sa_features_embedded, |
2427 | 14 | { "EMBEDDED", "dcom.sa.features_embedded", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_EMBEDDED, NULL, HFILL }}, |
2428 | 14 | { &hf_dcom_sa_features_fixedsize, |
2429 | 14 | { "FIXEDSIZE", "dcom.sa.features_fixedsize", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_FIXEDSIZE, NULL, HFILL }}, |
2430 | 14 | { &hf_dcom_sa_features_record, |
2431 | 14 | { "RECORD", "dcom.sa.features_record", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_RECORD, NULL, HFILL }}, |
2432 | 14 | { &hf_dcom_sa_features_have_iid, |
2433 | 14 | { "HAVEIID", "dcom.sa.features_have_iid", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_HAVEIID, NULL, HFILL }}, |
2434 | 14 | { &hf_dcom_sa_features_have_vartype, |
2435 | 14 | { "HAVEVARTYPE", "dcom.sa.features_have_vartype", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_HAVEVARTYPE, NULL, HFILL }}, |
2436 | 14 | { &hf_dcom_sa_features_bstr, |
2437 | 14 | { "BSTR", "dcom.sa.features_bstr", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_BSTR, NULL, HFILL }}, |
2438 | 14 | { &hf_dcom_sa_features_unknown, |
2439 | 14 | { "UNKNOWN", "dcom.sa.features_unknown", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_UNKNOWN, NULL, HFILL }}, |
2440 | 14 | { &hf_dcom_sa_features_dispatch, |
2441 | 14 | { "DISPATCH", "dcom.sa.features_dispatch", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_DISPATCH, NULL, HFILL }}, |
2442 | 14 | { &hf_dcom_sa_features_variant, |
2443 | 14 | { "VARIANT", "dcom.sa.features_variant", FT_BOOLEAN, 16, TFS (&tfs_set_notset), WIRESHARK_FADF_VARIANT, NULL, HFILL }} |
2444 | 14 | }; |
2445 | | |
2446 | 14 | static int *ett_dcom[] = { |
2447 | 14 | &ett_dcom_this, |
2448 | 14 | &ett_dcom_that, |
2449 | 14 | &ett_dcom_extent, |
2450 | 14 | &ett_dcom_lpwstr, |
2451 | 14 | &ett_dcom_interface_pointer, |
2452 | 14 | &ett_dcom_objref, |
2453 | 14 | &ett_dcom_stdobjref, |
2454 | 14 | &ett_dcom_custobjref, |
2455 | 14 | &ett_dcom_dualstringarray, |
2456 | 14 | &ett_dcom_dualstringarray_binding, |
2457 | 14 | &ett_dcom_variant, |
2458 | 14 | &ett_dcom_safearray, |
2459 | 14 | &ett_dcom_sa_features, |
2460 | 14 | }; |
2461 | | |
2462 | 14 | static ei_register_info ei[] = { |
2463 | 14 | { &ei_dcom_dissection_incomplete, { "dcom.dissection_incomplete", PI_UNDECODED, PI_WARN, "Dissection incomplete", EXPFILL }}, |
2464 | 14 | { &ei_dcom_no_spec, { "dcom.no_spec", PI_UNDECODED, PI_NOTE, "No specification available, dissection not possible", EXPFILL }}, |
2465 | 14 | { &ei_dcom_hresult_expert, { "dcom.hresult.expert", PI_RESPONSE_CODE, PI_NOTE, "Hresult", EXPFILL }}, |
2466 | 14 | { &ei_dcom_dualstringarray_mult_ip, { "dcom.dualstringarray.mult_ip", PI_UNDECODED, PI_NOTE, "DUALSTRINGARRAY Multiple IP", EXPFILL }}, |
2467 | 14 | }; |
2468 | | |
2469 | 14 | module_t *dcom_module; |
2470 | 14 | expert_module_t* expert_dcom; |
2471 | | |
2472 | | /* currently, the DCOM protocol "itself" has no real protocol dissector */ |
2473 | | /* we only need this, to register some generic elements */ |
2474 | 14 | proto_dcom = proto_register_protocol ("DCOM", "DCOM", "dcom"); |
2475 | 14 | proto_register_field_array(proto_dcom, hf_dcom_this_array, array_length(hf_dcom_this_array)); |
2476 | 14 | proto_register_field_array(proto_dcom, hf_dcom_that_array, array_length(hf_dcom_that_array)); |
2477 | 14 | proto_register_field_array(proto_dcom, hf_dcom_extent_array, array_length(hf_dcom_extent_array)); |
2478 | 14 | proto_register_field_array(proto_dcom, hf_dcom_array, array_length(hf_dcom_array)); |
2479 | 14 | proto_register_field_array(proto_dcom, hf_dcom_objref_array, array_length(hf_dcom_objref_array)); |
2480 | 14 | proto_register_field_array(proto_dcom, hf_dcom_stdobjref_array, array_length(hf_dcom_stdobjref_array)); |
2481 | 14 | proto_register_field_array(proto_dcom, hf_dcom_custobjref_array, array_length(hf_dcom_custobjref_array)); |
2482 | 14 | proto_register_field_array(proto_dcom, hf_dcom_dualstringarray_array, array_length(hf_dcom_dualstringarray_array)); |
2483 | 14 | proto_register_field_array(proto_dcom, hf_dcom_interface_pointer_array, array_length(hf_dcom_interface_pointer_array)); |
2484 | 14 | proto_register_field_array(proto_dcom, hf_dcom_vt_array, array_length(hf_dcom_vt_array)); |
2485 | 14 | proto_register_field_array(proto_dcom, hf_dcom_sa_array, array_length(hf_dcom_sa_array)); |
2486 | 14 | proto_register_subtree_array (ett_dcom, array_length (ett_dcom)); |
2487 | | |
2488 | 14 | expert_dcom = expert_register_protocol(proto_dcom); |
2489 | 14 | expert_register_field_array(expert_dcom, ei, array_length(ei)); |
2490 | | |
2491 | | /* preferences */ |
2492 | 14 | dcom_module = prefs_register_protocol(proto_dcom, NULL); |
2493 | | |
2494 | 14 | prefs_register_bool_preference(dcom_module, "display_unmarshalling_details", |
2495 | 14 | "Display DCOM unmarshalling details", |
2496 | 14 | "Display some DCOM unmarshalled fields " |
2497 | 14 | "usually hidden", |
2498 | 14 | &dcom_prefs_display_unmarshalling_details); |
2499 | | |
2500 | 14 | register_cleanup_routine(dcom_cleanup); |
2501 | 14 | } |
2502 | | |
2503 | | |
2504 | | void |
2505 | | proto_reg_handoff_dcom (void) |
2506 | 14 | { |
2507 | | /* register some "well known" UUID's */ |
2508 | 14 | guids_add_guid(&uuid_debug_ext, "Debug Information Body Extension"); |
2509 | 14 | guids_add_guid(&uuid_ext_error_ext, "Extended Error Info Body Extension"); |
2510 | 14 | guids_add_guid(&ipid_rem_unknown, "IRemUnknown"); |
2511 | 14 | guids_add_guid(&iid_unknown, "IUnknown"); |
2512 | 14 | guids_add_guid(&uuid_null, "NULL"); |
2513 | 14 | guids_add_guid(&iid_class_factory, "IClassFactory"); |
2514 | 14 | guids_add_guid(&iid_type_info, "ITypeInfo"); |
2515 | 14 | guids_add_guid(&iid_provide_class_info, "IProvideClassInfo"); |
2516 | | |
2517 | | /* Currently, we have nothing to register for DCOM */ |
2518 | 14 | } |
2519 | | |
2520 | | /* |
2521 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
2522 | | * |
2523 | | * Local variables: |
2524 | | * c-basic-offset: 8 |
2525 | | * tab-width: 8 |
2526 | | * indent-tabs-mode: t |
2527 | | * End: |
2528 | | * |
2529 | | * vi: set shiftwidth=8 tabstop=8 noexpandtab: |
2530 | | * :indentSize=8:tabSize=8:noTabs=false: |
2531 | | */ |