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