File: | epan/dissectors/packet-xml.c |
Warning: | line 1373, column 10 Null pointer passed to 1st parameter expecting 'nonnull' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* packet-xml.c | |||
2 | * wireshark's xml dissector . | |||
3 | * | |||
4 | * (C) 2005, Luis E. Garcia Ontanon. | |||
5 | * | |||
6 | * Refer to the AUTHORS file or the AUTHORS section in the man page | |||
7 | * for contacting the author(s) of this file. | |||
8 | * | |||
9 | * Wireshark - Network traffic analyzer | |||
10 | * By Gerald Combs <[email protected]> | |||
11 | * Copyright 1998 Gerald Combs | |||
12 | * | |||
13 | * SPDX-License-Identifier: GPL-2.0-or-later | |||
14 | */ | |||
15 | ||||
16 | #include "config.h" | |||
17 | ||||
18 | #include <string.h> | |||
19 | #include <errno(*__errno_location ()).h> | |||
20 | ||||
21 | #include <epan/packet.h> | |||
22 | #include <epan/tvbparse.h> | |||
23 | #include <epan/proto_data.h> | |||
24 | #include <wsutil/filesystem.h> | |||
25 | #include <epan/prefs.h> | |||
26 | #include <epan/expert.h> | |||
27 | #include <epan/iana_charsets.h> | |||
28 | #include <epan/asn1.h> | |||
29 | #include <epan/read_keytab_file.h> | |||
30 | #include <wsutil/str_util.h> | |||
31 | #include <wsutil/report_message.h> | |||
32 | #include <wsutil/wsgcrypt.h> | |||
33 | #include <wsutil/array.h> | |||
34 | #include "packet-kerberos.h" | |||
35 | ||||
36 | #include <libxml/parser.h> | |||
37 | ||||
38 | #include "packet-xml.h" | |||
39 | #include "packet-acdr.h" | |||
40 | ||||
41 | void proto_register_xml(void); | |||
42 | void proto_reg_handoff_xml(void); | |||
43 | ||||
44 | struct _attr_reg_data { | |||
45 | wmem_array_t *hf; | |||
46 | const char *basename; | |||
47 | }; | |||
48 | ||||
49 | ||||
50 | static int ett_dtd; | |||
51 | static int ett_xmpli; | |||
52 | ||||
53 | static int hf_unknowwn_attrib; | |||
54 | static int hf_comment; | |||
55 | static int hf_xmlpi; | |||
56 | static int hf_dtd_tag; | |||
57 | static int hf_doctype; | |||
58 | static int hf_cdatasection; | |||
59 | ||||
60 | static expert_field ei_xml_closing_unopened_tag; | |||
61 | static expert_field ei_xml_closing_unopened_xmpli_tag; | |||
62 | static expert_field ei_xml_unrecognized_text; | |||
63 | ||||
64 | /* dissector handles */ | |||
65 | static dissector_handle_t xml_handle; | |||
66 | static dissector_handle_t gssapi_handle; | |||
67 | ||||
68 | /* Port 3702 is IANA-registered for Web Service Discovery, which uses | |||
69 | * SOAP-over-UDP to send XML */ | |||
70 | #define XML_UDP_PORT_RANGE"3702" "3702" | |||
71 | ||||
72 | /* parser definitions */ | |||
73 | static tvbparse_wanted_t *want; | |||
74 | static tvbparse_wanted_t *want_ignore; | |||
75 | static tvbparse_wanted_t *want_heur; | |||
76 | ||||
77 | static wmem_map_t *xmpli_names; | |||
78 | static wmem_map_t *media_types; | |||
79 | ||||
80 | ||||
81 | typedef struct _xml_ns_t { | |||
82 | /* the name of this namespace */ | |||
83 | char* name; | |||
84 | ||||
85 | /* its fully qualified name */ | |||
86 | const char* fqn; | |||
87 | ||||
88 | /* the contents of the whole element from <> to </> */ | |||
89 | int hf_tag; | |||
90 | ||||
91 | /* chunks of cdata from <> to </> excluding sub tags */ | |||
92 | int hf_cdata; | |||
93 | ||||
94 | /* the subtree for its sub items */ | |||
95 | int ett; | |||
96 | ||||
97 | wmem_map_t* attributes; | |||
98 | /* key: the attribute name | |||
99 | value: hf_id of what's between quotes */ | |||
100 | ||||
101 | /* the namespace's namespaces */ | |||
102 | wmem_map_t* elements; | |||
103 | /* key: the element name | |||
104 | value: the child namespace */ | |||
105 | ||||
106 | GList* element_names; | |||
107 | /* imported directly from the parser and used while building the namespace */ | |||
108 | ||||
109 | } xml_ns_t; | |||
110 | ||||
111 | static xml_ns_t xml_ns = {"xml", "/", 0, 0, 0, NULL((void*)0), NULL((void*)0), NULL((void*)0)}; | |||
112 | static xml_ns_t unknown_ns = {"unknown", "?", 0, 0, 0, NULL((void*)0), NULL((void*)0), NULL((void*)0)}; | |||
113 | static xml_ns_t *root_ns; | |||
114 | ||||
115 | static bool_Bool pref_heuristic_unicode; | |||
116 | static int pref_default_encoding = IANA_CS_UTF_8; | |||
117 | ||||
118 | ||||
119 | #define XML_CDATA-1000 -1000 | |||
120 | #define XML_SCOPED_NAME-1001 -1001 | |||
121 | ||||
122 | ||||
123 | typedef struct _dtd_named_list_t { | |||
124 | char* name; | |||
125 | GList* list; | |||
126 | } dtd_named_list_t; | |||
127 | ||||
128 | typedef struct _dtd_build_data_t { | |||
129 | char* proto_name; | |||
130 | char* media_type; | |||
131 | char* description; | |||
132 | char* proto_root; | |||
133 | bool_Bool recursion; | |||
134 | ||||
135 | GPtrArray* elements; | |||
136 | GPtrArray* attributes; | |||
137 | ||||
138 | GString* error; | |||
139 | ||||
140 | } dtd_build_data_t; | |||
141 | ||||
142 | static wmem_array_t *hf_arr; | |||
143 | static GArray *ett_arr; | |||
144 | static GRegex* encoding_pattern; | |||
145 | ||||
146 | static const char *default_media_types[] = { | |||
147 | "text/xml", | |||
148 | "text/vnd.wap.wml", | |||
149 | "text/vnd.wap.si", | |||
150 | "text/vnd.wap.sl", | |||
151 | "text/vnd.wap.co", | |||
152 | "text/vnd.wap.emn", | |||
153 | "application/3gpp-ims+xml", | |||
154 | "application/atom+xml", | |||
155 | "application/auth-policy+xml", | |||
156 | "application/ccmp+xml", | |||
157 | "application/conference-info+xml", /*RFC4575*/ | |||
158 | "application/cpim-pidf+xml", | |||
159 | "application/cpl+xml", | |||
160 | "application/dds-web+xml", | |||
161 | "application/im-iscomposing+xml", /*RFC3994*/ | |||
162 | "application/load-control+xml", /*RFC7200*/ | |||
163 | "application/mathml+xml", | |||
164 | "application/media_control+xml", | |||
165 | "application/note+xml", | |||
166 | "application/pidf+xml", | |||
167 | "application/pidf-diff+xml", | |||
168 | "application/poc-settings+xml", | |||
169 | "application/rdf+xml", | |||
170 | "application/reginfo+xml", | |||
171 | "application/resource-lists+xml", | |||
172 | "application/rlmi+xml", | |||
173 | "application/rls-services+xml", | |||
174 | "application/rss+xml", | |||
175 | "application/rs-metadata+xml", | |||
176 | "application/smil", | |||
177 | "application/simple-filter+xml", | |||
178 | "application/simple-message-summary+xml", /*RFC3842*/ | |||
179 | "application/simservs+xml", | |||
180 | "application/soap+xml", | |||
181 | "application/vnd.etsi.aoc+xml", | |||
182 | "application/vnd.etsi.cug+xml", | |||
183 | "application/vnd.etsi.iptvcommand+xml", | |||
184 | "application/vnd.etsi.iptvdiscovery+xml", | |||
185 | "application/vnd.etsi.iptvprofile+xml", | |||
186 | "application/vnd.etsi.iptvsad-bc+xml", | |||
187 | "application/vnd.etsi.iptvsad-cod+xml", | |||
188 | "application/vnd.etsi.iptvsad-npvr+xml", | |||
189 | "application/vnd.etsi.iptvservice+xml", | |||
190 | "application/vnd.etsi.iptvsync+xml", | |||
191 | "application/vnd.etsi.iptvueprofile+xml", | |||
192 | "application/vnd.etsi.mcid+xml", | |||
193 | "application/vnd.etsi.overload-control-policy-dataset+xml", | |||
194 | "application/vnd.etsi.pstn+xml", | |||
195 | "application/vnd.etsi.sci+xml", | |||
196 | "application/vnd.etsi.simservs+xml", | |||
197 | "application/vnd.etsi.tsl+xml", | |||
198 | "application/vnd.oma.xdm-apd+xml", | |||
199 | "application/vnd.oma.fnl+xml", | |||
200 | "application/vnd.oma.access-permissions-list+xml", | |||
201 | "application/vnd.oma.alias-principals-list+xml", | |||
202 | "application/upp-directory+xml", /*OMA-ERELD-XDM-V2_2_1-20170124-A*/ | |||
203 | "application/vnd.oma.xdm-hi+xml", | |||
204 | "application/vnd.oma.xdm-rhi+xml", | |||
205 | "application/vnd.oma.xdm-prefs+xml", | |||
206 | "application/vnd.oma.xdcp+xml", | |||
207 | "application/vnd.oma.bcast.associated-procedure-parameter+xml", | |||
208 | "application/vnd.oma.bcast.drm-trigger+xml", | |||
209 | "application/vnd.oma.bcast.imd+xml", | |||
210 | "application/vnd.oma.bcast.notification+xml", | |||
211 | "application/vnd.oma.bcast.sgdd+xml", | |||
212 | "application/vnd.oma.bcast.smartcard-trigger+xml", | |||
213 | "application/vnd.oma.bcast.sprov+xml", | |||
214 | "application/vnd.oma.cab-address-book+xml", | |||
215 | "application/vnd.oma.cab-feature-handler+xml", | |||
216 | "application/vnd.oma.cab-pcc+xml", | |||
217 | "application/vnd.oma.cab-subs-invite+xml", | |||
218 | "application/vnd.oma.cab-user-prefs+xml", | |||
219 | "application/vnd.oma.dd2+xml", | |||
220 | "application/vnd.oma.drm.risd+xml", | |||
221 | "application/vnd.oma.group-usage-list+xml", | |||
222 | "application/vnd.oma.pal+xml", | |||
223 | "application/vnd.oma.poc.detailed-progress-report+xml", | |||
224 | "application/vnd.oma.poc.final-report+xml", | |||
225 | "application/vnd.oma.poc.groups+xml", | |||
226 | "application/vnd.oma.poc.invocation-descriptor+xml", | |||
227 | "application/vnd.oma.poc.optimized-progress-report+xml", | |||
228 | "application/vnd.oma.scidm.messages+xml", | |||
229 | "application/vnd.oma.suppnot+xml", /*OMA-ERELD-Presence_SIMPLE-V2_0-20120710-A*/ | |||
230 | "application/vnd.oma.xcap-directory+xml", | |||
231 | "application/vnd.omads-email+xml", | |||
232 | "application/vnd.omads-file+xml", | |||
233 | "application/vnd.omads-folder+xml", | |||
234 | "application/vnd.3gpp.access-transfer-events+xml", | |||
235 | "application/vnd.3gpp.bsf+xml", | |||
236 | "application/vnd.3gpp.comm-div-info+xml", /*3GPP TS 24.504 version 8.19.0*/ | |||
237 | "application/vnd.3gpp.cw+xml", | |||
238 | "application/vnd.3gpp.iut+xml", /*3GPP TS 24.337*/ | |||
239 | "application/vnc.3gpp.iut-config+xml", /*3GPP TS 24.337*/ | |||
240 | "application/vnd.3gpp.mcptt-info+xml", /*3GPP TS 24.379 version 17.6.0*/ | |||
241 | "application/vnd.3gpp.mcptt-mbms-usage-info+xml", /*3GPP TS 24.379 version 17.6.0*/ | |||
242 | "application/vnd.3gpp.mcptt-location-info+xml", /*3GPP TS 24.379 version 17.6.0*/ | |||
243 | "application/vnd.3gpp.mcptt-affiliation-command+xml", /*3GPP TS 24.379 version 17.6.0*/ | |||
244 | "application/vnd.3gpp.mcptt-floor-request+xml", /*3GPP TS 24.379 version 17.6.0*/ | |||
245 | "application/vnd.3gpp.mcptt-signed+xml", /*3GPP TS 24.379 version 17.6.0*/ | |||
246 | "application/vnd.3gpp.mcptt-regroup+xml", /*3GPP TS 24.379 version 17.6.0*/ | |||
247 | "application/vnd.3gpp.mcdata-info+xml", /*3GPP TS 24.282 version 17.6.2*/ | |||
248 | "application/vnd.3gpp.mcdata-mbms-usage-info+xml", /*3GPP TS 24.282 version 17.6.2*/ | |||
249 | "application/vnd.3gpp.mcdata-location-info+xml", /*3GPP TS 24.282 version 17.6.2*/ | |||
250 | "application/vnd.3gpp.mcdata-affiliation-command+xml", /*3GPP TS 24.282 version 17.6.2*/ | |||
251 | "application/vnd.3gpp.mcdata-regroup+xml", /*3GPP TS 24.282 version 17.6.2*/ | |||
252 | "application/vnd.3gpp.mcvideo-info+xml", /*3GPP TS 24.281 version 17.6.0*/ | |||
253 | "application/vnd.3gpp.mcvideo-mbms-usage-info+xml", /*3GPP TS 24.281 version 17.6.0*/ | |||
254 | "application/vnd.3gpp.mcvideo-location-info+xml", /*3GPP TS 24.281 version 17.6.0*/ | |||
255 | "application/vnd.3gpp.mcvideo-affiliation-command+xml",/*3GPP TS 24.281 version 17.6.0*/ | |||
256 | "application/vnd.3gpp.transmission-request+xml", /*3GPP TS 24.281 version 17.6.0*/ | |||
257 | "application/vnd.3gpp.mcptt-ue-init-config+xml", /*3GPP TS 24.484 version 17.5.0*/ | |||
258 | "application/vnd.3gpp.mcptt-ue-config+xml", /*3GPP TS 24.484 version 17.5.0*/ | |||
259 | "application/vnd.3gpp.mcptt-user-profile+xml", /*3GPP TS 24.484 version 17.5.0*/ | |||
260 | "application/vnd.3gpp.mcptt-service-config+xml", /*3GPP TS 24.484 version 17.5.0*/ | |||
261 | "application/vnd.3gpp.mcdata-service-config+xml", /*3GPP TS 24.484 version 17.5.0*/ | |||
262 | "application/vnd.3gpp.mcvideo-service-config+xml", /*3GPP TS 24.484 version 17.5.0*/ | |||
263 | "application/vnd.3gpp.mcvideo-ue-config+xml", /*3GPP TS 24.484 version 17.5.0*/ | |||
264 | "application/vnd.3gpp.mcvideo-user-profile+xml", /*3GPP TS 24.484 version 17.5.0*/ | |||
265 | "application/vnd.3gpp.mcdata-ue-config+xml", /*3GPP TS 24.484 version 17.5.0*/ | |||
266 | "application/vnd.3gpp.mcdata-user-profile+xml", /*3GPP TS 24.484 version 17.5.0*/ | |||
267 | "application/vnd.3gpp.mid-call+xml", | |||
268 | "application/vnd.3gpp-prose-pc3ch+xml", | |||
269 | "application/vnd.3gpp-prose+xml", | |||
270 | "application/vnd.3gpp.replication+xml", /*3GPP TS 24.337*/ | |||
271 | "application/vnd.3gpp.sms+xml", | |||
272 | "application/vnd.3gpp.srvcc-info+xml", | |||
273 | "application/vnd.3gpp.srvcc-ext+xml", | |||
274 | "application/vnd.3gpp.state-and-event-info+xml", | |||
275 | "application/vnd.3gpp.ussd+xml", | |||
276 | "application/vnd.3gpp2.bcmcsinfo+xml", | |||
277 | "application/vnd.wv.csp+xml", | |||
278 | "application/vnd.wv.csp.xml", | |||
279 | "application/watcherinfo+xml", | |||
280 | "application/xcap-att+xml", | |||
281 | "application/xcap-caps+xml", | |||
282 | "application/xcap-diff+xml", | |||
283 | "application/xcap-el+xml", | |||
284 | "application/xcap-error+xml", | |||
285 | "application/xcap-ns+xml", | |||
286 | "application/xml", | |||
287 | "application/xml-dtd", | |||
288 | "application/xpidf+xml", | |||
289 | "application/xslt+xml", | |||
290 | "application/x-crd+xml", | |||
291 | "application/x-wms-logconnectstats", | |||
292 | "application/x-wms-logplaystats", | |||
293 | "application/x-wms-sendevent", | |||
294 | "image/svg+xml", | |||
295 | "message/imdn+xml", /*RFC5438*/ | |||
296 | }; | |||
297 | ||||
298 | static void insert_xml_frame(xml_frame_t *parent, xml_frame_t *new_child) | |||
299 | { | |||
300 | new_child->first_child = NULL((void*)0); | |||
301 | new_child->last_child = NULL((void*)0); | |||
302 | ||||
303 | new_child->parent = parent; | |||
304 | new_child->next_sibling = NULL((void*)0); | |||
305 | new_child->prev_sibling = NULL((void*)0); | |||
306 | if (parent == NULL((void*)0)) return; /* root */ | |||
307 | ||||
308 | if (parent->first_child == NULL((void*)0)) { /* the 1st child */ | |||
309 | parent->first_child = new_child; | |||
310 | } else { /* following children */ | |||
311 | parent->last_child->next_sibling = new_child; | |||
312 | new_child->prev_sibling = parent->last_child; | |||
313 | } | |||
314 | parent->last_child = new_child; | |||
315 | } | |||
316 | ||||
317 | /* Try to get the 'encoding' attribute from XML declaration, and convert it to | |||
318 | * Wireshark character encoding. | |||
319 | */ | |||
320 | static unsigned | |||
321 | get_char_encoding(tvbuff_t* tvb, packet_info* pinfo, char** ret_encoding_name) { | |||
322 | uint32_t iana_charset_id; | |||
323 | unsigned ws_encoding_id; | |||
324 | char* encoding_str; | |||
325 | GMatchInfo* match_info; | |||
326 | const char* xmldecl = (char*)tvb_get_string_enc(pinfo->pool, tvb, 0, | |||
327 | MIN(100, tvb_captured_length(tvb))(((100) < (tvb_captured_length(tvb))) ? (100) : (tvb_captured_length (tvb))), ENC_UTF_80x00000002); | |||
328 | ||||
329 | g_regex_match(encoding_pattern, xmldecl, 0, &match_info); | |||
330 | if (g_match_info_matches(match_info)) { | |||
331 | char* match_ret = g_match_info_fetch(match_info, 1); | |||
332 | encoding_str = ascii_strup_inplace(wmem_strdup(pinfo->pool, match_ret)); | |||
333 | g_free(match_ret); | |||
334 | /* Get the iana charset enum number by the name of the charset. */ | |||
335 | iana_charset_id = str_to_val(encoding_str, | |||
336 | VALUE_STRING_EXT_VS_P(&mibenum_vals_character_sets_ext)(&mibenum_vals_character_sets_ext)->_vs_p, IANA_CS_US_ASCII); | |||
337 | } else { | |||
338 | /* Use default encoding preference if this xml does not contains 'encoding' attribute. */ | |||
339 | iana_charset_id = pref_default_encoding; | |||
340 | encoding_str = val_to_str_ext(pinfo->pool, iana_charset_id, | |||
341 | &mibenum_vals_character_sets_ext, "UNKNOWN"); | |||
342 | } | |||
343 | g_match_info_free(match_info); | |||
344 | ||||
345 | ws_encoding_id = mibenum_charset_to_encoding((unsigned)iana_charset_id); | |||
346 | ||||
347 | /* UTF-8 compatible with ASCII */ | |||
348 | if (ws_encoding_id == (ENC_NA0x00000000 | ENC_ASCII0x00000000)) { | |||
349 | ws_encoding_id = ENC_UTF_80x00000002; | |||
350 | *ret_encoding_name = wmem_strdup(pinfo->pool, "UTF-8"); | |||
351 | } else { | |||
352 | *ret_encoding_name = encoding_str; | |||
353 | } | |||
354 | ||||
355 | return ws_encoding_id; | |||
356 | } | |||
357 | ||||
358 | static int | |||
359 | dissect_xml(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused))) | |||
360 | { | |||
361 | tvbparse_t *tt; | |||
362 | static GPtrArray *stack; | |||
363 | xml_frame_t *current_frame; | |||
364 | const char *colinfo_str; | |||
365 | tvbuff_t *decoded; | |||
366 | uint16_t try_bom; | |||
367 | ||||
368 | if (stack != NULL((void*)0)) | |||
369 | g_ptr_array_free(stack, true1); | |||
370 | ||||
371 | stack = g_ptr_array_new(); | |||
372 | current_frame = wmem_new(pinfo->pool, xml_frame_t)((xml_frame_t*)wmem_alloc((pinfo->pool), sizeof(xml_frame_t ))); | |||
373 | current_frame->type = XML_FRAME_ROOT0; | |||
374 | current_frame->name = NULL((void*)0); | |||
375 | current_frame->name_orig_case = NULL((void*)0); | |||
376 | current_frame->value = NULL((void*)0); | |||
377 | current_frame->pinfo = pinfo; | |||
378 | insert_xml_frame(NULL((void*)0), current_frame); | |||
379 | g_ptr_array_add(stack, current_frame); | |||
380 | ||||
381 | /* Detect and act on possible byte-order mark (BOM) */ | |||
382 | try_bom = tvb_get_ntohs(tvb, 0); | |||
383 | if (try_bom == 0xFEFF) { | |||
384 | /* UTF-16BE */ | |||
385 | const uint8_t *data_str = tvb_get_string_enc(pinfo->pool, tvb, 0, tvb_captured_length(tvb), ENC_UTF_160x00000004|ENC_BIG_ENDIAN0x00000000); | |||
386 | size_t l = strlen(data_str); | |||
387 | decoded = tvb_new_child_real_data(tvb, data_str, (unsigned)l, (int)l); | |||
388 | add_new_data_source(pinfo, decoded, "Decoded UTF-16BE text"); | |||
389 | } | |||
390 | else if(try_bom == 0xFFFE) { | |||
391 | /* UTF-16LE (or possibly UTF-32LE, but Wireshark doesn't support UTF-32) */ | |||
392 | const uint8_t *data_str = tvb_get_string_enc(pinfo->pool, tvb, 0, tvb_captured_length(tvb), ENC_UTF_160x00000004|ENC_LITTLE_ENDIAN0x80000000); | |||
393 | size_t l = strlen(data_str); | |||
394 | decoded = tvb_new_child_real_data(tvb, data_str, (unsigned)l, (int)l); | |||
395 | add_new_data_source(pinfo, decoded, "Decoded UTF-16LE text"); | |||
396 | } | |||
397 | /* Could also test if try_bom is 0xnn00 or 0x00nn to guess endianness if we wanted */ | |||
398 | else { | |||
399 | /* Get character encoding according to XML declaration or preference. */ | |||
400 | char* encoding_name; | |||
401 | unsigned encoding = get_char_encoding(tvb, pinfo, &encoding_name); | |||
402 | ||||
403 | /* Encoding string with encoding, either with or without BOM */ | |||
404 | const uint8_t *data_str = tvb_get_string_enc(pinfo->pool, tvb, 0, tvb_captured_length(tvb), encoding); | |||
405 | size_t l = strlen(data_str); | |||
406 | decoded = tvb_new_child_real_data(tvb, data_str, (unsigned)l, (int)l); | |||
407 | add_new_data_source(pinfo, decoded, wmem_strdup_printf(pinfo->pool, "Decoded %s text", encoding_name)); | |||
408 | } | |||
409 | ||||
410 | tt = tvbparse_init(pinfo->pool, decoded, 0, -1, stack, want_ignore); | |||
411 | current_frame->start_offset = 0; | |||
412 | current_frame->length = tvb_captured_length(decoded); | |||
413 | ||||
414 | current_frame->decryption_keys = wmem_map_new(pinfo->pool, g_str_hash, g_str_equal); | |||
415 | ||||
416 | root_ns = NULL((void*)0); | |||
417 | ||||
418 | if (pinfo->match_string) | |||
419 | root_ns = (xml_ns_t *)wmem_map_lookup(media_types, pinfo->match_string); | |||
420 | ||||
421 | if (! root_ns ) { | |||
422 | root_ns = &xml_ns; | |||
423 | colinfo_str = "/XML"; | |||
424 | } else { | |||
425 | char *colinfo_str_buf; | |||
426 | colinfo_str_buf = wmem_strconcat(pinfo->pool, "/", root_ns->name, NULL((void*)0)); | |||
427 | ascii_strup_inplace(colinfo_str_buf); | |||
428 | colinfo_str = colinfo_str_buf; | |||
429 | } | |||
430 | ||||
431 | col_append_str(pinfo->cinfo, COL_PROTOCOL, colinfo_str); | |||
432 | ||||
433 | current_frame->ns = root_ns; | |||
434 | ||||
435 | current_frame->item = proto_tree_add_item(tree, current_frame->ns->hf_tag, decoded, 0, -1, ENC_UTF_80x00000002|ENC_NA0x00000000); | |||
436 | current_frame->tree = proto_item_add_subtree(current_frame->item, current_frame->ns->ett); | |||
437 | current_frame->last_item = current_frame->item; | |||
438 | ||||
439 | while(tvbparse_get(tt, want)) ; | |||
440 | ||||
441 | /* Save XML structure in case it is useful for the caller */ | |||
442 | p_add_proto_data(pinfo->pool, pinfo, xml_ns.hf_tag, 0, current_frame); | |||
443 | ||||
444 | return tvb_captured_length(tvb); | |||
445 | } | |||
446 | ||||
447 | static bool_Bool dissect_xml_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) | |||
448 | { | |||
449 | if (tvbparse_peek(tvbparse_init(pinfo->pool, tvb, 0, -1, NULL((void*)0), want_ignore), want_heur)) { | |||
450 | dissect_xml(tvb, pinfo, tree, data); | |||
451 | return true1; | |||
452 | } else if (pref_heuristic_unicode) { | |||
453 | const uint8_t *data_str; | |||
454 | tvbuff_t *unicode_tvb; | |||
455 | uint16_t try_bom; | |||
456 | /* XXX - UCS-2, or UTF-16? */ | |||
457 | int enc = ENC_UCS_20x00000006|ENC_LITTLE_ENDIAN0x80000000; | |||
458 | size_t l; | |||
459 | ||||
460 | try_bom = tvb_get_ntohs(tvb, 0); | |||
461 | if (try_bom == 0xFEFF) { | |||
462 | enc = ENC_UTF_160x00000004|ENC_BIG_ENDIAN0x00000000; | |||
463 | } | |||
464 | else if(try_bom == 0xFFFE) { | |||
465 | enc = ENC_UTF_160x00000004|ENC_LITTLE_ENDIAN0x80000000; | |||
466 | } | |||
467 | ||||
468 | data_str = tvb_get_string_enc(pinfo->pool, tvb, 0, tvb_captured_length(tvb), enc); | |||
469 | l = strlen(data_str); | |||
470 | unicode_tvb = tvb_new_child_real_data(tvb, data_str, (unsigned)l, (int)l); | |||
471 | if (tvbparse_peek(tvbparse_init(pinfo->pool, unicode_tvb, 0, -1, NULL((void*)0), want_ignore), want_heur)) { | |||
472 | add_new_data_source(pinfo, unicode_tvb, "UTF8"); | |||
473 | dissect_xml(unicode_tvb, pinfo, tree, data); | |||
474 | return true1; | |||
475 | } | |||
476 | } | |||
477 | return false0; | |||
478 | } | |||
479 | ||||
480 | xml_frame_t *xml_get_tag(xml_frame_t *frame, const char *name) | |||
481 | { | |||
482 | xml_frame_t *tag = NULL((void*)0); | |||
483 | ||||
484 | xml_frame_t *xml_item = frame->first_child; | |||
485 | while (xml_item) { | |||
486 | if (xml_item->type == XML_FRAME_TAG1) { | |||
487 | if (!name) { /* get the 1st tag */ | |||
488 | tag = xml_item; | |||
489 | break; | |||
490 | } else if (xml_item->name_orig_case && !strcmp(xml_item->name_orig_case, name)) { | |||
491 | tag = xml_item; | |||
492 | break; | |||
493 | } | |||
494 | } | |||
495 | xml_item = xml_item->next_sibling; | |||
496 | } | |||
497 | ||||
498 | return tag; | |||
499 | } | |||
500 | ||||
501 | xml_frame_t *xml_get_attrib(xml_frame_t *frame, const char *name) | |||
502 | { | |||
503 | xml_frame_t *attr = NULL((void*)0); | |||
504 | ||||
505 | xml_frame_t *xml_item = frame->first_child; | |||
506 | while (xml_item) { | |||
507 | if ((xml_item->type == XML_FRAME_ATTRIB4) && | |||
508 | xml_item->name_orig_case && !strcmp(xml_item->name_orig_case, name)) { | |||
509 | attr = xml_item; | |||
510 | break; | |||
511 | } | |||
512 | xml_item = xml_item->next_sibling; | |||
513 | } | |||
514 | ||||
515 | return attr; | |||
516 | } | |||
517 | ||||
518 | xml_frame_t *xml_get_cdata(xml_frame_t *frame) | |||
519 | { | |||
520 | xml_frame_t *cdata = NULL((void*)0); | |||
521 | ||||
522 | xml_frame_t *xml_item = frame->first_child; | |||
523 | while (xml_item) { | |||
524 | if (xml_item->type == XML_FRAME_CDATA5) { | |||
525 | cdata = xml_item; | |||
526 | break; | |||
527 | } | |||
528 | xml_item = xml_item->next_sibling; | |||
529 | } | |||
530 | ||||
531 | return cdata; | |||
532 | } | |||
533 | ||||
534 | static void after_token(void *tvbparse_data, const void *wanted_data _U___attribute__((unused)), tvbparse_elem_t *tok) | |||
535 | { | |||
536 | GPtrArray *stack = (GPtrArray *)tvbparse_data; | |||
537 | xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1)((stack)->pdata)[stack->len - 1]; | |||
538 | int hfid; | |||
539 | bool_Bool is_cdata = false0; | |||
540 | proto_item *pi; | |||
541 | xml_frame_t *new_frame = NULL((void*)0); | |||
542 | char *text = NULL((void*)0); | |||
543 | ||||
544 | if (tok->id == XML_CDATA-1000) { | |||
545 | hfid = current_frame->ns ? current_frame->ns->hf_cdata : xml_ns.hf_cdata; | |||
546 | is_cdata = true1; | |||
547 | } else if ( tok->id > 0) { | |||
548 | hfid = tok->id; | |||
549 | } else { | |||
550 | hfid = xml_ns.hf_cdata; | |||
551 | } | |||
552 | ||||
553 | pi = proto_tree_add_item(current_frame->tree, hfid, tok->tvb, tok->offset, tok->len, ENC_UTF_80x00000002|ENC_NA0x00000000); | |||
554 | ||||
555 | text = tvb_format_text(current_frame->pinfo->pool, tok->tvb, tok->offset, tok->len); | |||
556 | proto_item_set_text(pi, "%s", text); | |||
557 | ||||
558 | if (is_cdata) { | |||
559 | new_frame = wmem_new(current_frame->pinfo->pool, xml_frame_t)((xml_frame_t*)wmem_alloc((current_frame->pinfo->pool), sizeof(xml_frame_t))); | |||
560 | new_frame->type = XML_FRAME_CDATA5; | |||
561 | new_frame->name = NULL((void*)0); | |||
562 | new_frame->name_orig_case = NULL((void*)0); | |||
563 | new_frame->value = tvb_new_subset_length(tok->tvb, tok->offset, tok->len); | |||
564 | insert_xml_frame(current_frame, new_frame); | |||
565 | new_frame->item = pi; | |||
566 | new_frame->last_item = pi; | |||
567 | new_frame->tree = NULL((void*)0); | |||
568 | new_frame->start_offset = tok->offset; | |||
569 | new_frame->length = tok->len; | |||
570 | new_frame->ns = NULL((void*)0); | |||
571 | new_frame->pinfo = current_frame->pinfo; | |||
572 | } | |||
573 | ||||
574 | if (new_frame != NULL((void*)0) && | |||
575 | current_frame != NULL((void*)0) && | |||
576 | current_frame->name_orig_case != NULL((void*)0) && | |||
577 | strcmp(current_frame->name_orig_case, "BinarySecurityToken") == 0) | |||
578 | { | |||
579 | xml_frame_t *value_type = NULL((void*)0); | |||
580 | ||||
581 | value_type = xml_get_attrib(current_frame, "ValueType"); | |||
582 | if (value_type != NULL((void*)0)) { | |||
583 | const char *s = "http://docs.oasis-open.org/wss/oasis-wss-kerberos-token-profile-1.1#GSS_Kerberosv5_AP_REQ"; | |||
584 | size_t l = strlen(s); | |||
585 | int c; | |||
586 | c = tvb_strneql(value_type->value, 0, s, l); | |||
587 | if (c == 0) { | |||
588 | tvbuff_t *ssp_tvb = base64_to_tvb(new_frame->value, text); | |||
589 | add_new_data_source(current_frame->pinfo, ssp_tvb, "GSSAPI Data"); | |||
590 | call_dissector(gssapi_handle, ssp_tvb, | |||
591 | current_frame->pinfo, current_frame->tree); | |||
592 | } | |||
593 | } | |||
594 | } | |||
595 | } | |||
596 | ||||
597 | static void before_xmpli(void *tvbparse_data, const void *wanted_data _U___attribute__((unused)), tvbparse_elem_t *tok) | |||
598 | { | |||
599 | GPtrArray *stack = (GPtrArray *)tvbparse_data; | |||
600 | xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1)((stack)->pdata)[stack->len - 1]; | |||
601 | proto_item *pi; | |||
602 | proto_tree *pt; | |||
603 | tvbparse_elem_t *name_tok = tok->sub->next; | |||
604 | char *name = tvb_get_string_enc(current_frame->pinfo->pool, name_tok->tvb, name_tok->offset, name_tok->len, ENC_ASCII0x00000000); | |||
605 | xml_ns_t *ns = (xml_ns_t *)wmem_map_lookup(xmpli_names, name); | |||
606 | xml_frame_t *new_frame; | |||
607 | ||||
608 | int hf_tag; | |||
609 | int ett; | |||
610 | ||||
611 | ascii_strdown_inplace(name); | |||
612 | if (!ns) { | |||
613 | hf_tag = hf_xmlpi; | |||
614 | ett = ett_xmpli; | |||
615 | } else { | |||
616 | hf_tag = ns->hf_tag; | |||
617 | ett = ns->ett; | |||
618 | } | |||
619 | ||||
620 | pi = proto_tree_add_item(current_frame->tree, hf_tag, tok->tvb, tok->offset, tok->len, ENC_UTF_80x00000002|ENC_NA0x00000000); | |||
621 | ||||
622 | proto_item_set_text(pi, "%s", tvb_format_text(current_frame->pinfo->pool, tok->tvb, tok->offset, (name_tok->offset - tok->offset) + name_tok->len)); | |||
623 | ||||
624 | pt = proto_item_add_subtree(pi, ett); | |||
625 | ||||
626 | new_frame = wmem_new(current_frame->pinfo->pool, xml_frame_t)((xml_frame_t*)wmem_alloc((current_frame->pinfo->pool), sizeof(xml_frame_t))); | |||
627 | new_frame->type = XML_FRAME_XMPLI2; | |||
628 | new_frame->name = name; | |||
629 | new_frame->name_orig_case = name; | |||
630 | new_frame->value = NULL((void*)0); | |||
631 | insert_xml_frame(current_frame, new_frame); | |||
632 | new_frame->item = pi; | |||
633 | new_frame->last_item = pi; | |||
634 | new_frame->tree = pt; | |||
635 | new_frame->start_offset = tok->offset; | |||
636 | new_frame->length = tok->len; | |||
637 | new_frame->ns = ns; | |||
638 | new_frame->pinfo = current_frame->pinfo; | |||
639 | ||||
640 | g_ptr_array_add(stack, new_frame); | |||
641 | ||||
642 | } | |||
643 | ||||
644 | static void after_xmlpi(void *tvbparse_data, const void *wanted_data _U___attribute__((unused)), tvbparse_elem_t *tok) | |||
645 | { | |||
646 | GPtrArray *stack = (GPtrArray *)tvbparse_data; | |||
647 | xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1)((stack)->pdata)[stack->len - 1]; | |||
648 | ||||
649 | proto_tree_add_format_text(current_frame->tree, tok->tvb, tok->offset, tok->len); | |||
650 | ||||
651 | if (stack->len > 1) { | |||
652 | g_ptr_array_remove_index_fast(stack, stack->len - 1); | |||
653 | } else { | |||
654 | proto_tree_add_expert(current_frame->tree, current_frame->pinfo, &ei_xml_closing_unopened_xmpli_tag, | |||
655 | tok->tvb, tok->offset, tok->len); | |||
656 | } | |||
657 | } | |||
658 | ||||
659 | static void before_tag(void *tvbparse_data, const void *wanted_data _U___attribute__((unused)), tvbparse_elem_t *tok) | |||
660 | { | |||
661 | GPtrArray *stack = (GPtrArray *)tvbparse_data; | |||
662 | xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1)((stack)->pdata)[stack->len - 1]; | |||
663 | tvbparse_elem_t *name_tok = tok->sub->next; | |||
664 | char *root_name; | |||
665 | char *name = NULL((void*)0), *name_orig_case = NULL((void*)0); | |||
666 | xml_ns_t *ns; | |||
667 | xml_frame_t *new_frame; | |||
668 | proto_item *pi; | |||
669 | proto_tree *pt; | |||
670 | ||||
671 | if (name_tok->sub->id == XML_SCOPED_NAME-1001) { | |||
672 | tvbparse_elem_t *root_tok = name_tok->sub->sub; | |||
673 | tvbparse_elem_t *leaf_tok = name_tok->sub->sub->next->next; | |||
674 | xml_ns_t *nameroot_ns; | |||
675 | ||||
676 | root_name = (char *)tvb_get_string_enc(current_frame->pinfo->pool, root_tok->tvb, root_tok->offset, root_tok->len, ENC_ASCII0x00000000); | |||
677 | name = (char *)tvb_get_string_enc(current_frame->pinfo->pool, leaf_tok->tvb, leaf_tok->offset, leaf_tok->len, ENC_ASCII0x00000000); | |||
678 | name_orig_case = name; | |||
679 | ||||
680 | nameroot_ns = (xml_ns_t *)wmem_map_lookup(xml_ns.elements, root_name); | |||
681 | ||||
682 | if(nameroot_ns) { | |||
683 | ns = (xml_ns_t *)wmem_map_lookup(nameroot_ns->elements, name); | |||
684 | if (!ns) { | |||
685 | ns = &unknown_ns; | |||
686 | } | |||
687 | } else { | |||
688 | ns = &unknown_ns; | |||
689 | } | |||
690 | ||||
691 | } else { | |||
692 | name = tvb_get_string_enc(current_frame->pinfo->pool, name_tok->tvb, name_tok->offset, name_tok->len, ENC_ASCII0x00000000); | |||
693 | name_orig_case = wmem_strdup(current_frame->pinfo->pool, name); | |||
694 | ascii_strdown_inplace(name); | |||
695 | ||||
696 | if(current_frame->ns) { | |||
697 | ns = (xml_ns_t *)wmem_map_lookup(current_frame->ns->elements, name); | |||
698 | ||||
699 | if (!ns) { | |||
700 | if (! ( ns = (xml_ns_t *)wmem_map_lookup(root_ns->elements, name) ) ) { | |||
701 | ns = &unknown_ns; | |||
702 | } | |||
703 | } | |||
704 | } else { | |||
705 | ns = &unknown_ns; | |||
706 | } | |||
707 | } | |||
708 | ||||
709 | pi = proto_tree_add_item(current_frame->tree, ns->hf_tag, tok->tvb, tok->offset, tok->len, ENC_UTF_80x00000002|ENC_NA0x00000000); | |||
710 | proto_item_set_text(pi, "%s", tvb_format_text(current_frame->pinfo->pool, tok->tvb, | |||
711 | tok->offset, | |||
712 | (name_tok->offset - tok->offset) + name_tok->len)); | |||
713 | ||||
714 | pt = proto_item_add_subtree(pi, ns->ett); | |||
715 | ||||
716 | new_frame = wmem_new(current_frame->pinfo->pool, xml_frame_t)((xml_frame_t*)wmem_alloc((current_frame->pinfo->pool), sizeof(xml_frame_t))); | |||
717 | new_frame->type = XML_FRAME_TAG1; | |||
718 | new_frame->name = name; | |||
719 | new_frame->name_orig_case = name_orig_case; | |||
720 | new_frame->value = NULL((void*)0); | |||
721 | insert_xml_frame(current_frame, new_frame); | |||
722 | new_frame->item = pi; | |||
723 | new_frame->last_item = pi; | |||
724 | new_frame->tree = pt; | |||
725 | new_frame->start_offset = tok->offset; | |||
726 | new_frame->length = tok->len; | |||
727 | new_frame->ns = ns; | |||
728 | new_frame->pinfo = current_frame->pinfo; | |||
729 | ||||
730 | g_ptr_array_add(stack, new_frame); | |||
731 | ||||
732 | } | |||
733 | ||||
734 | static void after_open_tag(void *tvbparse_data, const void *wanted_data _U___attribute__((unused)), tvbparse_elem_t *tok _U___attribute__((unused))) | |||
735 | { | |||
736 | GPtrArray *stack = (GPtrArray *)tvbparse_data; | |||
737 | xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1)((stack)->pdata)[stack->len - 1]; | |||
738 | ||||
739 | proto_item_append_text(current_frame->last_item, ">"); | |||
740 | } | |||
741 | ||||
742 | static void after_closed_tag(void *tvbparse_data, const void *wanted_data _U___attribute__((unused)), tvbparse_elem_t *tok) | |||
743 | { | |||
744 | GPtrArray *stack = (GPtrArray *)tvbparse_data; | |||
745 | xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1)((stack)->pdata)[stack->len - 1]; | |||
746 | ||||
747 | proto_item_append_text(current_frame->last_item, "/>"); | |||
748 | ||||
749 | if (stack->len > 1) { | |||
750 | g_ptr_array_remove_index_fast(stack, stack->len - 1); | |||
751 | } else { | |||
752 | proto_tree_add_expert(current_frame->tree, current_frame->pinfo, &ei_xml_closing_unopened_tag, | |||
753 | tok->tvb, tok->offset, tok->len); | |||
754 | } | |||
755 | } | |||
756 | ||||
757 | #ifdef HAVE_KERBEROS1 | |||
758 | struct decryption_key { | |||
759 | char *id; | |||
760 | size_t key_length; | |||
761 | uint8_t key[HASH_SHA1_LENGTH20]; | |||
762 | }; | |||
763 | ||||
764 | static void P_SHA1(const uint8_t *Secret, size_t Secret_len, | |||
765 | const uint8_t *Seed, size_t Seed_len, | |||
766 | uint8_t Result[HASH_SHA1_LENGTH20]) | |||
767 | { | |||
768 | gcry_md_hd_t hd = NULL((void*)0); | |||
769 | uint8_t *digest = NULL((void*)0); | |||
770 | ||||
771 | /* | |||
772 | * https://social.microsoft.com/Forums/en-US/c485d98b-6e0b-49e7-ab34-8ecf8d694d31/signing-soap-message-request-via-adfs?forum=crmdevelopment#6cee9fa8-dc24-4524-a5a2-c3d17e05d50e | |||
773 | */ | |||
774 | gcry_md_open(&hd, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC); | |||
775 | gcry_md_setkey(hd, Secret, Secret_len); | |||
776 | gcry_md_write(hd, Seed, Seed_len); | |||
777 | digest = gcry_md_read(hd, GCRY_MD_SHA1); | |||
778 | memcpy(Result, digest, HASH_SHA1_LENGTH20); | |||
779 | ||||
780 | gcry_md_close(hd); | |||
781 | } | |||
782 | #endif /* HAVE_KERBEROS */ | |||
783 | ||||
784 | static void after_untag(void *tvbparse_data, const void *wanted_data _U___attribute__((unused)), tvbparse_elem_t *tok) | |||
785 | { | |||
786 | GPtrArray *stack = (GPtrArray *)tvbparse_data; | |||
787 | xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1)((stack)->pdata)[stack->len - 1]; | |||
788 | #ifdef HAVE_KERBEROS1 | |||
789 | xml_frame_t *top_frame = (xml_frame_t *)g_ptr_array_index(stack, 0)((stack)->pdata)[0]; | |||
790 | #endif /* HAVE_KERBEROS */ | |||
791 | ||||
792 | proto_item_set_len(current_frame->item, (tok->offset - current_frame->start_offset) + tok->len); | |||
793 | current_frame->length = (tok->offset - current_frame->start_offset) + tok->len; | |||
794 | ||||
795 | proto_tree_add_format_text(current_frame->tree, tok->tvb, tok->offset, tok->len); | |||
796 | ||||
797 | if (stack->len > 1) { | |||
798 | g_ptr_array_remove_index_fast(stack, stack->len - 1); | |||
799 | } else { | |||
800 | proto_tree_add_expert(current_frame->tree, current_frame->pinfo, &ei_xml_closing_unopened_tag, | |||
801 | tok->tvb, tok->offset, tok->len); | |||
802 | } | |||
803 | ||||
804 | #ifdef HAVE_KERBEROS1 | |||
805 | if (current_frame->name_orig_case == NULL((void*)0)) { | |||
806 | return; | |||
807 | } | |||
808 | ||||
809 | if (strcmp(current_frame->name_orig_case, "DerivedKeyToken") == 0) { | |||
810 | xml_frame_t *id_frame = xml_get_attrib(current_frame, "u:Id"); | |||
811 | xml_frame_t *nonce_frame = xml_get_tag(current_frame, "Nonce"); | |||
812 | xml_frame_t *nonce_cdata = NULL((void*)0); | |||
813 | tvbuff_t *nonce_tvb = NULL((void*)0); | |||
814 | const enc_key_t *ek = NULL((void*)0); | |||
815 | uint8_t seed[64]; | |||
816 | size_t seed_length = 16; // TODO | |||
817 | const size_t key_length = 16; //TODO | |||
818 | ||||
819 | if (id_frame != NULL((void*)0) && nonce_frame != NULL((void*)0)) { | |||
820 | nonce_cdata = xml_get_cdata(nonce_frame); | |||
821 | } | |||
822 | if (nonce_cdata != NULL((void*)0)) { | |||
823 | char *text = tvb_format_text(current_frame->pinfo->pool, nonce_cdata->value, 0, | |||
824 | tvb_reported_length(nonce_cdata->value)); | |||
825 | nonce_tvb = base64_to_tvb(nonce_cdata->value, text); | |||
826 | } | |||
827 | if (nonce_tvb != NULL((void*)0)) { | |||
828 | seed_length = tvb_reported_length(nonce_tvb); | |||
829 | seed_length = MIN(seed_length, sizeof(seed))(((seed_length) < (sizeof(seed))) ? (seed_length) : (sizeof (seed))); | |||
830 | tvb_memcpy(nonce_tvb, seed, 0, seed_length); | |||
831 | ||||
832 | if (krb_decrypt) { | |||
833 | read_keytab_file_from_preferences(); | |||
834 | } | |||
835 | ||||
836 | for (ek=keytab_get_enc_key_list();ek;ek=ek->next) { | |||
837 | if (ek->fd_num == (int)current_frame->pinfo->num) { | |||
838 | break; | |||
839 | } | |||
840 | } | |||
841 | } | |||
842 | if (ek != NULL((void*)0)) { | |||
843 | struct decryption_key *key; | |||
844 | char *id_str; | |||
845 | ||||
846 | id_str = tvb_format_text(current_frame->pinfo->pool, | |||
847 | id_frame->value, 0, | |||
848 | tvb_reported_length(id_frame->value)); | |||
849 | ||||
850 | key = wmem_new0(current_frame->pinfo->pool, struct decryption_key)((struct decryption_key*)wmem_alloc0((current_frame->pinfo ->pool), sizeof(struct decryption_key))); | |||
851 | key->id = wmem_strdup_printf(current_frame->pinfo->pool, "#%s", id_str); | |||
852 | P_SHA1(ek->keyvalue, ek->keylength, seed, seed_length, key->key); | |||
853 | key->key_length = key_length; | |||
854 | ||||
855 | wmem_map_insert(top_frame->decryption_keys, key->id, key); | |||
856 | } | |||
857 | } | |||
858 | if (strcmp(current_frame->name_orig_case, "CipherValue") == 0) { | |||
859 | xml_frame_t *encrypted_frame = current_frame->parent->parent; | |||
860 | xml_frame_t *key_info_frame = NULL((void*)0); | |||
861 | xml_frame_t *token_frame = NULL((void*)0); | |||
862 | xml_frame_t *reference_frame = NULL((void*)0); | |||
863 | xml_frame_t *uri_frame = NULL((void*)0); | |||
864 | const struct decryption_key *key = NULL((void*)0); | |||
865 | xml_frame_t *cdata_frame = NULL((void*)0); | |||
866 | tvbuff_t *crypt_tvb = NULL((void*)0); | |||
867 | tvbuff_t *plain_tvb = NULL((void*)0); | |||
868 | ||||
869 | key_info_frame = xml_get_tag(encrypted_frame, "KeyInfo"); | |||
870 | if (key_info_frame != NULL((void*)0)) { | |||
871 | token_frame = xml_get_tag(key_info_frame, "SecurityTokenReference"); | |||
872 | } | |||
873 | if (token_frame != NULL((void*)0)) { | |||
874 | reference_frame = xml_get_tag(token_frame, "Reference"); | |||
875 | } | |||
876 | if (reference_frame != NULL((void*)0)) { | |||
877 | uri_frame = xml_get_attrib(reference_frame, "URI"); | |||
878 | } | |||
879 | ||||
880 | if (uri_frame != NULL((void*)0)) { | |||
881 | char *key_id = tvb_format_text(current_frame->pinfo->pool, uri_frame->value, 0, | |||
882 | tvb_reported_length(uri_frame->value)); | |||
883 | ||||
884 | key = (const struct decryption_key *)wmem_map_lookup(top_frame->decryption_keys, key_id); | |||
885 | } | |||
886 | if (key != NULL((void*)0)) { | |||
887 | cdata_frame = xml_get_cdata(current_frame); | |||
888 | } | |||
889 | if (cdata_frame != NULL((void*)0)) { | |||
890 | char *text = tvb_format_text(current_frame->pinfo->pool, cdata_frame->value, 0, | |||
891 | tvb_reported_length(cdata_frame->value)); | |||
892 | crypt_tvb = base64_to_tvb(cdata_frame->value, text); | |||
893 | } | |||
894 | if (crypt_tvb != NULL((void*)0)) { | |||
895 | gcry_cipher_hd_t cipher_hd = NULL((void*)0); | |||
896 | uint8_t *data = NULL((void*)0); | |||
897 | unsigned data_length = tvb_reported_length(crypt_tvb); | |||
898 | ||||
899 | data = (uint8_t *)tvb_memdup(current_frame->pinfo->pool, | |||
900 | crypt_tvb, 0, data_length); | |||
901 | ||||
902 | /* Open the cipher. */ | |||
903 | gcry_cipher_open(&cipher_hd, GCRY_CIPHER_AES128GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CBC, 0); | |||
904 | ||||
905 | gcry_cipher_setkey(cipher_hd, key->key, key->key_length); | |||
906 | gcry_cipher_encrypt(cipher_hd, data, data_length, NULL((void*)0), 0); | |||
907 | gcry_cipher_close(cipher_hd); | |||
908 | ||||
909 | plain_tvb = tvb_new_child_real_data(crypt_tvb, data, | |||
910 | data_length, data_length); | |||
911 | add_new_data_source(current_frame->pinfo, plain_tvb, "Decrypted Data"); | |||
912 | } | |||
913 | } | |||
914 | #endif /* HAVE_KERBEROS */ | |||
915 | } | |||
916 | ||||
917 | static void before_dtd_doctype(void *tvbparse_data, const void *wanted_data _U___attribute__((unused)), tvbparse_elem_t *tok) | |||
918 | { | |||
919 | GPtrArray *stack = (GPtrArray *)tvbparse_data; | |||
920 | xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1)((stack)->pdata)[stack->len - 1]; | |||
921 | xml_frame_t *new_frame; | |||
922 | tvbparse_elem_t *name_tok = tok->sub->next->next->next->sub->sub; | |||
923 | proto_tree *dtd_item = proto_tree_add_item(current_frame->tree, hf_doctype, | |||
924 | name_tok->tvb, name_tok->offset, | |||
925 | name_tok->len, ENC_ASCII0x00000000); | |||
926 | ||||
927 | proto_item_set_text(dtd_item, "%s", tvb_format_text(current_frame->pinfo->pool, tok->tvb, tok->offset, tok->len)); | |||
928 | ||||
929 | new_frame = wmem_new(current_frame->pinfo->pool, xml_frame_t)((xml_frame_t*)wmem_alloc((current_frame->pinfo->pool), sizeof(xml_frame_t))); | |||
930 | new_frame->type = XML_FRAME_DTD_DOCTYPE3; | |||
931 | new_frame->name = (char *)tvb_get_string_enc(current_frame->pinfo->pool, name_tok->tvb, | |||
932 | name_tok->offset, | |||
933 | name_tok->len, ENC_ASCII0x00000000); | |||
934 | new_frame->name_orig_case = new_frame->name; | |||
935 | new_frame->value = NULL((void*)0); | |||
936 | insert_xml_frame(current_frame, new_frame); | |||
937 | new_frame->item = dtd_item; | |||
938 | new_frame->last_item = dtd_item; | |||
939 | new_frame->tree = proto_item_add_subtree(dtd_item, ett_dtd); | |||
940 | new_frame->start_offset = tok->offset; | |||
941 | new_frame->length = tok->len; | |||
942 | new_frame->ns = NULL((void*)0); | |||
943 | new_frame->pinfo = current_frame->pinfo; | |||
944 | ||||
945 | g_ptr_array_add(stack, new_frame); | |||
946 | } | |||
947 | ||||
948 | static void pop_stack(void *tvbparse_data, const void *wanted_data _U___attribute__((unused)), tvbparse_elem_t *tok _U___attribute__((unused))) | |||
949 | { | |||
950 | GPtrArray *stack = (GPtrArray *)tvbparse_data; | |||
951 | xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1)((stack)->pdata)[stack->len - 1]; | |||
952 | ||||
953 | if (stack->len > 1) { | |||
954 | g_ptr_array_remove_index_fast(stack, stack->len - 1); | |||
955 | } else { | |||
956 | proto_tree_add_expert(current_frame->tree, current_frame->pinfo, &ei_xml_closing_unopened_tag, | |||
957 | tok->tvb, tok->offset, tok->len); | |||
958 | } | |||
959 | } | |||
960 | ||||
961 | static void after_dtd_close(void *tvbparse_data, const void *wanted_data _U___attribute__((unused)), tvbparse_elem_t *tok) | |||
962 | { | |||
963 | GPtrArray *stack = (GPtrArray *)tvbparse_data; | |||
964 | xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1)((stack)->pdata)[stack->len - 1]; | |||
965 | ||||
966 | proto_tree_add_format_text(current_frame->tree, tok->tvb, tok->offset, tok->len); | |||
967 | if (stack->len > 1) { | |||
968 | g_ptr_array_remove_index_fast(stack, stack->len - 1); | |||
969 | } else { | |||
970 | proto_tree_add_expert(current_frame->tree, current_frame->pinfo, &ei_xml_closing_unopened_tag, | |||
971 | tok->tvb, tok->offset, tok->len); | |||
972 | } | |||
973 | } | |||
974 | ||||
975 | static void get_attrib_value(void *tvbparse_data _U___attribute__((unused)), const void *wanted_data _U___attribute__((unused)), tvbparse_elem_t *tok) | |||
976 | { | |||
977 | tok->data = tok->sub; | |||
978 | } | |||
979 | ||||
980 | static void after_attrib(void *tvbparse_data, const void *wanted_data _U___attribute__((unused)), tvbparse_elem_t *tok) | |||
981 | { | |||
982 | GPtrArray *stack = (GPtrArray *)tvbparse_data; | |||
983 | xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1)((stack)->pdata)[stack->len - 1]; | |||
984 | char *name, *name_orig_case; | |||
985 | tvbparse_elem_t *value; | |||
986 | tvbparse_elem_t *value_part = (tvbparse_elem_t *)tok->sub->next->next->data; | |||
987 | int *hfidp; | |||
988 | int hfid; | |||
989 | proto_item *pi; | |||
990 | xml_frame_t *new_frame; | |||
991 | ||||
992 | name = tvb_get_string_enc(current_frame->pinfo->pool, tok->sub->tvb, tok->sub->offset, tok->sub->len, ENC_ASCII0x00000000); | |||
993 | name_orig_case = wmem_strdup(current_frame->pinfo->pool, name); | |||
994 | ascii_strdown_inplace(name); | |||
995 | ||||
996 | if(current_frame->ns && (hfidp = (int *)wmem_map_lookup(current_frame->ns->attributes, name) )) { | |||
997 | hfid = *hfidp; | |||
998 | value = value_part; | |||
999 | } else { | |||
1000 | hfid = hf_unknowwn_attrib; | |||
1001 | value = tok; | |||
1002 | } | |||
1003 | ||||
1004 | pi = proto_tree_add_item(current_frame->tree, hfid, value->tvb, value->offset, value->len, ENC_UTF_80x00000002|ENC_NA0x00000000); | |||
1005 | proto_item_set_text(pi, "%s", tvb_format_text(current_frame->pinfo->pool, tok->tvb, tok->offset, tok->len)); | |||
1006 | ||||
1007 | current_frame->last_item = pi; | |||
1008 | ||||
1009 | new_frame = wmem_new(current_frame->pinfo->pool, xml_frame_t)((xml_frame_t*)wmem_alloc((current_frame->pinfo->pool), sizeof(xml_frame_t))); | |||
1010 | new_frame->type = XML_FRAME_ATTRIB4; | |||
1011 | new_frame->name = name; | |||
1012 | new_frame->name_orig_case = name_orig_case; | |||
1013 | new_frame->value = tvb_new_subset_length(value_part->tvb, value_part->offset, | |||
1014 | value_part->len); | |||
1015 | insert_xml_frame(current_frame, new_frame); | |||
1016 | new_frame->item = pi; | |||
1017 | new_frame->last_item = pi; | |||
1018 | new_frame->tree = NULL((void*)0); | |||
1019 | new_frame->start_offset = tok->offset; | |||
1020 | new_frame->length = tok->len; | |||
1021 | new_frame->ns = NULL((void*)0); | |||
1022 | new_frame->pinfo = current_frame->pinfo; | |||
1023 | ||||
1024 | } | |||
1025 | ||||
1026 | static void unrecognized_token(void *tvbparse_data, const void *wanted_data _U___attribute__((unused)), tvbparse_elem_t *tok _U___attribute__((unused))) | |||
1027 | { | |||
1028 | GPtrArray *stack = (GPtrArray *)tvbparse_data; | |||
1029 | xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1)((stack)->pdata)[stack->len - 1]; | |||
1030 | ||||
1031 | proto_tree_add_expert(current_frame->tree, current_frame->pinfo, &ei_xml_unrecognized_text, | |||
1032 | tok->tvb, tok->offset, tok->len); | |||
1033 | ||||
1034 | } | |||
1035 | ||||
1036 | ||||
1037 | ||||
1038 | static void init_xml_parser(void) | |||
1039 | { | |||
1040 | tvbparse_wanted_t *want_name = | |||
1041 | tvbparse_chars(-1, 1, 0, | |||
1042 | "abcdefghijklmnopqrstuvwxyz.-_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", | |||
1043 | NULL((void*)0), NULL((void*)0), NULL((void*)0)); | |||
1044 | tvbparse_wanted_t *want_attr_name = | |||
1045 | tvbparse_chars(-1, 1, 0, | |||
1046 | "abcdefghijklmnopqrstuvwxyz.-_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789:", | |||
1047 | NULL((void*)0), NULL((void*)0), NULL((void*)0)); | |||
1048 | ||||
1049 | tvbparse_wanted_t *want_scoped_name = tvbparse_set_seq(XML_SCOPED_NAME-1001, NULL((void*)0), NULL((void*)0), NULL((void*)0), | |||
1050 | want_name, | |||
1051 | tvbparse_char(-1, ":", NULL((void*)0), NULL((void*)0), NULL((void*)0)), | |||
1052 | want_name, | |||
1053 | NULL((void*)0)); | |||
1054 | ||||
1055 | tvbparse_wanted_t *want_tag_name = tvbparse_set_oneof(0, NULL((void*)0), NULL((void*)0), NULL((void*)0), | |||
1056 | want_scoped_name, | |||
1057 | want_name, | |||
1058 | NULL((void*)0)); | |||
1059 | ||||
1060 | tvbparse_wanted_t *want_attrib_value = tvbparse_set_oneof(0, NULL((void*)0), NULL((void*)0), get_attrib_value, | |||
1061 | tvbparse_quoted(-1, NULL((void*)0), NULL((void*)0), tvbparse_shrink_token_cb, '\"', '\\'), | |||
1062 | tvbparse_quoted(-1, NULL((void*)0), NULL((void*)0), tvbparse_shrink_token_cb, '\'', '\\'), | |||
1063 | tvbparse_chars(-1, 1, 0, "0123456789", NULL((void*)0), NULL((void*)0), NULL((void*)0)), | |||
1064 | want_name, | |||
1065 | NULL((void*)0)); | |||
1066 | ||||
1067 | tvbparse_wanted_t *want_attributes = tvbparse_one_or_more(-1, NULL, NULL, NULL,tvbparse_some(-1, 1, 2147483647, ((void*)0), ((void*)0), ((void *)0), tvbparse_set_seq(-1, ((void*)0), ((void*)0), after_attrib , want_attr_name, tvbparse_char(-1, "=", ((void*)0), ((void*) 0), ((void*)0)), want_attrib_value, ((void*)0))) | |||
1068 | tvbparse_set_seq(-1, NULL, NULL, after_attrib,tvbparse_some(-1, 1, 2147483647, ((void*)0), ((void*)0), ((void *)0), tvbparse_set_seq(-1, ((void*)0), ((void*)0), after_attrib , want_attr_name, tvbparse_char(-1, "=", ((void*)0), ((void*) 0), ((void*)0)), want_attrib_value, ((void*)0))) | |||
1069 | want_attr_name,tvbparse_some(-1, 1, 2147483647, ((void*)0), ((void*)0), ((void *)0), tvbparse_set_seq(-1, ((void*)0), ((void*)0), after_attrib , want_attr_name, tvbparse_char(-1, "=", ((void*)0), ((void*) 0), ((void*)0)), want_attrib_value, ((void*)0))) | |||
1070 | tvbparse_char(-1, "=", NULL, NULL, NULL),tvbparse_some(-1, 1, 2147483647, ((void*)0), ((void*)0), ((void *)0), tvbparse_set_seq(-1, ((void*)0), ((void*)0), after_attrib , want_attr_name, tvbparse_char(-1, "=", ((void*)0), ((void*) 0), ((void*)0)), want_attrib_value, ((void*)0))) | |||
1071 | want_attrib_value,tvbparse_some(-1, 1, 2147483647, ((void*)0), ((void*)0), ((void *)0), tvbparse_set_seq(-1, ((void*)0), ((void*)0), after_attrib , want_attr_name, tvbparse_char(-1, "=", ((void*)0), ((void*) 0), ((void*)0)), want_attrib_value, ((void*)0))) | |||
1072 | NULL))tvbparse_some(-1, 1, 2147483647, ((void*)0), ((void*)0), ((void *)0), tvbparse_set_seq(-1, ((void*)0), ((void*)0), after_attrib , want_attr_name, tvbparse_char(-1, "=", ((void*)0), ((void*) 0), ((void*)0)), want_attrib_value, ((void*)0))); | |||
1073 | ||||
1074 | tvbparse_wanted_t *want_stoptag = tvbparse_set_oneof(-1, NULL((void*)0), NULL((void*)0), NULL((void*)0), | |||
1075 | tvbparse_char(-1, ">", NULL((void*)0), NULL((void*)0), after_open_tag), | |||
1076 | tvbparse_string(-1, "/>", NULL((void*)0), NULL((void*)0), after_closed_tag), | |||
1077 | NULL((void*)0)); | |||
1078 | ||||
1079 | tvbparse_wanted_t *want_stopxmlpi = tvbparse_string(-1, "?>", NULL((void*)0), NULL((void*)0), after_xmlpi); | |||
1080 | ||||
1081 | tvbparse_wanted_t *want_comment = tvbparse_set_seq(hf_comment, NULL((void*)0), NULL((void*)0), after_token, | |||
1082 | tvbparse_string(-1, "<!--", NULL((void*)0), NULL((void*)0), NULL((void*)0)), | |||
1083 | tvbparse_until(-1, NULL((void*)0), NULL((void*)0), NULL((void*)0), | |||
1084 | tvbparse_string(-1, "-->", NULL((void*)0), NULL((void*)0), NULL((void*)0)), | |||
1085 | TP_UNTIL_INCLUDE), | |||
1086 | NULL((void*)0)); | |||
1087 | ||||
1088 | tvbparse_wanted_t *want_cdatasection = tvbparse_set_seq(hf_cdatasection, NULL((void*)0), NULL((void*)0), after_token, | |||
1089 | tvbparse_string(-1, "<![CDATA[", NULL((void*)0), NULL((void*)0), NULL((void*)0)), | |||
1090 | tvbparse_until(-1, NULL((void*)0), NULL((void*)0), NULL((void*)0), | |||
1091 | tvbparse_string(-1, "]]>", NULL((void*)0), NULL((void*)0), NULL((void*)0)), | |||
1092 | TP_UNTIL_INCLUDE), | |||
1093 | NULL((void*)0)); | |||
1094 | ||||
1095 | tvbparse_wanted_t *want_xmlpi = tvbparse_set_seq(hf_xmlpi, NULL((void*)0), before_xmpli, NULL((void*)0), | |||
1096 | tvbparse_string(-1, "<?", NULL((void*)0), NULL((void*)0), NULL((void*)0)), | |||
1097 | want_name, | |||
1098 | tvbparse_set_oneof(-1, NULL((void*)0), NULL((void*)0), NULL((void*)0), | |||
1099 | want_stopxmlpi, | |||
1100 | tvbparse_set_seq(-1, NULL((void*)0), NULL((void*)0), NULL((void*)0), | |||
1101 | want_attributes, | |||
1102 | want_stopxmlpi, | |||
1103 | NULL((void*)0)), | |||
1104 | NULL((void*)0)), | |||
1105 | NULL((void*)0)); | |||
1106 | ||||
1107 | tvbparse_wanted_t *want_closing_tag = tvbparse_set_seq(0, NULL((void*)0), NULL((void*)0), after_untag, | |||
1108 | tvbparse_char(-1, "<", NULL((void*)0), NULL((void*)0), NULL((void*)0)), | |||
1109 | tvbparse_char(-1, "/", NULL((void*)0), NULL((void*)0), NULL((void*)0)), | |||
1110 | want_tag_name, | |||
1111 | tvbparse_char(-1, ">", NULL((void*)0), NULL((void*)0), NULL((void*)0)), | |||
1112 | NULL((void*)0)); | |||
1113 | ||||
1114 | tvbparse_wanted_t *want_doctype_start = tvbparse_set_seq(-1, NULL((void*)0), before_dtd_doctype, NULL((void*)0), | |||
1115 | tvbparse_char(-1, "<", NULL((void*)0), NULL((void*)0), NULL((void*)0)), | |||
1116 | tvbparse_char(-1, "!", NULL((void*)0), NULL((void*)0), NULL((void*)0)), | |||
1117 | tvbparse_casestring(-1, "DOCTYPE", NULL((void*)0), NULL((void*)0), NULL((void*)0)), | |||
1118 | tvbparse_set_oneof(-1, NULL((void*)0), NULL((void*)0), NULL((void*)0), | |||
1119 | tvbparse_set_seq(-1, NULL((void*)0), NULL((void*)0), NULL((void*)0), | |||
1120 | want_name, | |||
1121 | tvbparse_char(-1, "[", NULL((void*)0), NULL((void*)0), NULL((void*)0)), | |||
1122 | NULL((void*)0)), | |||
1123 | tvbparse_set_seq(-1, NULL((void*)0), NULL((void*)0), pop_stack, | |||
1124 | want_name, | |||
1125 | tvbparse_set_oneof(-1, NULL((void*)0), NULL((void*)0), NULL((void*)0), | |||
1126 | tvbparse_casestring(-1, "PUBLIC", NULL((void*)0), NULL((void*)0), NULL((void*)0)), | |||
1127 | tvbparse_casestring(-1, "SYSTEM", NULL((void*)0), NULL((void*)0), NULL((void*)0)), | |||
1128 | NULL((void*)0)), | |||
1129 | tvbparse_until(-1, NULL((void*)0), NULL((void*)0), NULL((void*)0), | |||
1130 | tvbparse_char(-1, ">", NULL((void*)0), NULL((void*)0), NULL((void*)0)), | |||
1131 | TP_UNTIL_INCLUDE), | |||
1132 | NULL((void*)0)), | |||
1133 | NULL((void*)0)), | |||
1134 | NULL((void*)0)); | |||
1135 | ||||
1136 | tvbparse_wanted_t *want_dtd_tag = tvbparse_set_seq(hf_dtd_tag, NULL((void*)0), NULL((void*)0), after_token, | |||
1137 | tvbparse_char(-1, "<", NULL((void*)0), NULL((void*)0), NULL((void*)0)), | |||
1138 | tvbparse_char(-1, "!", NULL((void*)0), NULL((void*)0), NULL((void*)0)), | |||
1139 | tvbparse_until(-1, NULL((void*)0), NULL((void*)0), NULL((void*)0), | |||
1140 | tvbparse_char(-1, ">", NULL((void*)0), NULL((void*)0), NULL((void*)0)), | |||
1141 | TP_UNTIL_INCLUDE), | |||
1142 | NULL((void*)0)); | |||
1143 | ||||
1144 | tvbparse_wanted_t *want_tag = tvbparse_set_seq(-1, NULL((void*)0), before_tag, NULL((void*)0), | |||
1145 | tvbparse_char(-1, "<", NULL((void*)0), NULL((void*)0), NULL((void*)0)), | |||
1146 | want_tag_name, | |||
1147 | tvbparse_set_oneof(-1, NULL((void*)0), NULL((void*)0), NULL((void*)0), | |||
1148 | tvbparse_set_seq(-1, NULL((void*)0), NULL((void*)0), NULL((void*)0), | |||
1149 | want_attributes, | |||
1150 | want_stoptag, | |||
1151 | NULL((void*)0)), | |||
1152 | want_stoptag, | |||
1153 | NULL((void*)0)), | |||
1154 | NULL((void*)0)); | |||
1155 | ||||
1156 | tvbparse_wanted_t *want_dtd_close = tvbparse_set_seq(-1, NULL((void*)0), NULL((void*)0), after_dtd_close, | |||
1157 | tvbparse_char(-1, "]", NULL((void*)0), NULL((void*)0), NULL((void*)0)), | |||
1158 | tvbparse_char(-1, ">", NULL((void*)0), NULL((void*)0), NULL((void*)0)), | |||
1159 | NULL((void*)0)); | |||
1160 | ||||
1161 | want_ignore = tvbparse_chars(-1, 1, 0, " \t\r\n", NULL((void*)0), NULL((void*)0), NULL((void*)0)); | |||
1162 | ||||
1163 | ||||
1164 | want = tvbparse_set_oneof(-1, NULL((void*)0), NULL((void*)0), NULL((void*)0), | |||
1165 | want_comment, | |||
1166 | want_cdatasection, | |||
1167 | want_xmlpi, | |||
1168 | want_closing_tag, | |||
1169 | want_doctype_start, | |||
1170 | want_dtd_close, | |||
1171 | want_dtd_tag, | |||
1172 | want_tag, | |||
1173 | tvbparse_not_chars(XML_CDATA-1000, 1, 0, "<", NULL((void*)0), NULL((void*)0), after_token), | |||
1174 | tvbparse_not_chars(-1, 1, 0, " \t\r\n", NULL((void*)0), NULL((void*)0), unrecognized_token), | |||
1175 | NULL((void*)0)); | |||
1176 | ||||
1177 | want_heur = tvbparse_set_oneof(-1, NULL((void*)0), NULL((void*)0), NULL((void*)0), | |||
1178 | want_comment, | |||
1179 | want_cdatasection, | |||
1180 | want_xmlpi, | |||
1181 | want_doctype_start, | |||
1182 | want_dtd_tag, | |||
1183 | want_tag, | |||
1184 | NULL((void*)0)); | |||
1185 | ||||
1186 | } | |||
1187 | ||||
1188 | ||||
1189 | static xml_ns_t *xml_new_namespace(wmem_map_t *hash, const char *name, ...) | |||
1190 | { | |||
1191 | xml_ns_t *ns = wmem_new(wmem_epan_scope(), xml_ns_t)((xml_ns_t*)wmem_alloc((wmem_epan_scope()), sizeof(xml_ns_t)) ); | |||
1192 | va_list ap; | |||
1193 | char *attr_name; | |||
1194 | ||||
1195 | ns->name = wmem_strdup(wmem_epan_scope(), name); | |||
1196 | ns->hf_tag = 0; | |||
1197 | ns->hf_cdata = 0; | |||
1198 | ns->ett = 0; | |||
1199 | ns->attributes = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal); | |||
1200 | ns->elements = NULL((void*)0); | |||
1201 | ||||
1202 | va_start(ap, name)__builtin_va_start(ap, name); | |||
1203 | ||||
1204 | while(( attr_name = va_arg(ap, char *)__builtin_va_arg(ap, char *) )) { | |||
1205 | int *hfp = wmem_new(wmem_epan_scope(), int)((int*)wmem_alloc((wmem_epan_scope()), sizeof(int))); | |||
1206 | *hfp = 0; | |||
1207 | wmem_map_insert(ns->attributes, wmem_strdup(wmem_epan_scope(), attr_name), hfp); | |||
1208 | }; | |||
1209 | ||||
1210 | va_end(ap)__builtin_va_end(ap); | |||
1211 | ||||
1212 | wmem_map_insert(hash, ns->name, ns); | |||
1213 | ||||
1214 | return ns; | |||
1215 | } | |||
1216 | ||||
1217 | ||||
1218 | static void add_xml_field(wmem_array_t *hfs, int *p_id, const char *name, const char *fqn) | |||
1219 | { | |||
1220 | hf_register_info hfri; | |||
1221 | ||||
1222 | hfri.p_id = p_id; | |||
1223 | hfri.hfinfo.name = name; | |||
1224 | hfri.hfinfo.abbrev = fqn; | |||
1225 | hfri.hfinfo.type = FT_STRING; | |||
1226 | hfri.hfinfo.display = BASE_NONE; | |||
1227 | hfri.hfinfo.strings = NULL((void*)0); | |||
1228 | hfri.hfinfo.bitmask = 0x0; | |||
1229 | hfri.hfinfo.blurb = NULL((void*)0); | |||
1230 | HFILL_INIT(hfri)(hfri).hfinfo.id = -1; (hfri).hfinfo.parent = 0; (hfri).hfinfo .ref_type = HF_REF_TYPE_NONE; (hfri).hfinfo.same_name_prev_id = -1; (hfri).hfinfo.same_name_next = ((void*)0);; | |||
1231 | ||||
1232 | wmem_array_append_one(hfs, hfri)wmem_array_append((hfs), &(hfri), 1); | |||
1233 | } | |||
1234 | ||||
1235 | static char* fully_qualified_name(const char* name, const char* parent_name) | |||
1236 | { | |||
1237 | return wmem_strdup_printf(wmem_epan_scope(), "%s.%s", parent_name, name); | |||
1238 | } | |||
1239 | ||||
1240 | static void add_xml_attribute_names(void *k, void *v, void *p) | |||
1241 | { | |||
1242 | struct _attr_reg_data *d = (struct _attr_reg_data *)p; | |||
1243 | const char *basename = wmem_strconcat(wmem_epan_scope(), d->basename, ".", (char *)k, NULL((void*)0)); | |||
1244 | ||||
1245 | add_xml_field(d->hf, (int*) v, (char *)k, basename); | |||
1246 | } | |||
1247 | ||||
1248 | typedef struct _xml_element_iter_data | |||
1249 | { | |||
1250 | xml_ns_t* root_element; | |||
1251 | wmem_array_t* hfs; | |||
1252 | GArray* etts; | |||
1253 | } xml_element_iter_data; | |||
1254 | ||||
1255 | static void add_xml_flat_element_names(void* k, void* v, void* p) | |||
1256 | { | |||
1257 | char* name = (char*)k; | |||
1258 | xml_ns_t* fresh = (xml_ns_t*)v; | |||
1259 | xml_element_iter_data* data = (xml_element_iter_data*)p; | |||
1260 | struct _attr_reg_data d; | |||
1261 | int* ett_p; | |||
1262 | ||||
1263 | fresh->fqn = fully_qualified_name(name, data->root_element->name); | |||
1264 | ||||
1265 | add_xml_field(data->hfs, &(fresh->hf_tag), name, fresh->fqn); | |||
1266 | add_xml_field(data->hfs, &(fresh->hf_cdata), name, fresh->fqn); | |||
1267 | ||||
1268 | d.basename = fresh->fqn; | |||
1269 | d.hf = data->hfs; | |||
1270 | ||||
1271 | wmem_map_foreach(fresh->attributes, add_xml_attribute_names, &d); | |||
1272 | ||||
1273 | ett_p = &fresh->ett; | |||
1274 | g_array_append_val(data->etts, ett_p)g_array_append_vals (data->etts, &(ett_p), 1); | |||
1275 | ||||
1276 | wmem_map_insert(data->root_element->elements, (void*)fresh->name, fresh); | |||
1277 | } | |||
1278 | ||||
1279 | static void add_xmlpi_namespace(void *k _U___attribute__((unused)), void *v, void *p) | |||
1280 | { | |||
1281 | xml_ns_t *ns = (xml_ns_t *)v; | |||
1282 | const char *basename = wmem_strconcat(wmem_epan_scope(), (char *)p, ".", ns->name, NULL((void*)0)); | |||
1283 | int *ett_p = &(ns->ett); | |||
1284 | struct _attr_reg_data d; | |||
1285 | ||||
1286 | add_xml_field(hf_arr, &(ns->hf_tag), basename, basename); | |||
1287 | ||||
1288 | g_array_append_val(ett_arr, ett_p)g_array_append_vals (ett_arr, &(ett_p), 1); | |||
1289 | ||||
1290 | d.basename = basename; | |||
1291 | d.hf = hf_arr; | |||
1292 | ||||
1293 | wmem_map_foreach(ns->attributes, add_xml_attribute_names, &d); | |||
1294 | ||||
1295 | } | |||
1296 | ||||
1297 | static void destroy_dtd_data(dtd_build_data_t* dtd_data) | |||
1298 | { | |||
1299 | g_string_free(dtd_data->error, true)(__builtin_constant_p (1) ? ((1) ? (g_string_free) ((dtd_data ->error), (1)) : g_string_free_and_steal (dtd_data->error )) : (g_string_free) ((dtd_data->error), (1))); | |||
1300 | ||||
1301 | while (dtd_data->elements->len) { | |||
1302 | dtd_named_list_t* nl = (dtd_named_list_t*)g_ptr_array_remove_index_fast(dtd_data->elements, 0); | |||
1303 | g_list_free(nl->list); | |||
1304 | g_free(nl); | |||
1305 | } | |||
1306 | ||||
1307 | g_ptr_array_free(dtd_data->elements, true1); | |||
1308 | ||||
1309 | while (dtd_data->attributes->len) { | |||
1310 | dtd_named_list_t* nl = (dtd_named_list_t*)g_ptr_array_remove_index_fast(dtd_data->attributes, 0); | |||
1311 | g_list_free(nl->list); | |||
1312 | g_free(nl); | |||
1313 | } | |||
1314 | ||||
1315 | g_ptr_array_free(dtd_data->attributes, true1); | |||
1316 | ||||
1317 | g_free(dtd_data); | |||
1318 | } | |||
1319 | ||||
1320 | static void copy_attrib_item(void *k, void *v _U___attribute__((unused)), void *p) | |||
1321 | { | |||
1322 | char *key = (char *)wmem_strdup(wmem_epan_scope(), (const char *)k); | |||
1323 | int *value = wmem_new(wmem_epan_scope(), int)((int*)wmem_alloc((wmem_epan_scope()), sizeof(int))); | |||
1324 | wmem_map_t *dst = (wmem_map_t *)p; | |||
1325 | ||||
1326 | *value = 0; | |||
1327 | wmem_map_insert(dst, key, value); | |||
1328 | ||||
1329 | } | |||
1330 | ||||
1331 | static wmem_map_t *copy_attributes_hash(wmem_map_t *src) | |||
1332 | { | |||
1333 | wmem_map_t *dst = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal); | |||
1334 | ||||
1335 | wmem_map_foreach(src, copy_attrib_item, dst); | |||
1336 | ||||
1337 | return dst; | |||
1338 | } | |||
1339 | ||||
1340 | static xml_ns_t *duplicate_element(xml_ns_t *orig) | |||
1341 | { | |||
1342 | xml_ns_t *new_item = wmem_new(wmem_epan_scope(), xml_ns_t)((xml_ns_t*)wmem_alloc((wmem_epan_scope()), sizeof(xml_ns_t)) ); | |||
1343 | ||||
1344 | new_item->name = wmem_strdup(wmem_epan_scope(), orig->name); | |||
1345 | new_item->hf_tag = 0; | |||
1346 | new_item->hf_cdata = 0; | |||
1347 | new_item->ett = 0; | |||
1348 | new_item->attributes = copy_attributes_hash(orig->attributes); | |||
1349 | new_item->elements = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal); | |||
1350 | new_item->element_names = NULL((void*)0); // Not used for duplication | |||
1351 | ||||
1352 | return new_item; | |||
1353 | } | |||
1354 | ||||
1355 | ||||
1356 | // NOLINTNEXTLINE(misc-no-recursion) | |||
1357 | static xml_ns_t *make_xml_hier(char *elem_name, | |||
1358 | xml_ns_t *root, | |||
1359 | wmem_map_t *elements, | |||
1360 | GQueue *hier, | |||
1361 | GString *error, | |||
1362 | wmem_array_t *hfs, | |||
1363 | GArray *etts, | |||
1364 | const char *parent_name) | |||
1365 | { | |||
1366 | xml_ns_t *fresh; | |||
1367 | xml_ns_t *orig; | |||
1368 | char *fqn; | |||
1369 | int *ett_p; | |||
1370 | unsigned depth; | |||
1371 | struct _attr_reg_data d; | |||
1372 | ||||
1373 | if ( g_str_equal(elem_name, root->name)(strcmp ((const char *) (elem_name), (const char *) (root-> name)) == 0) ) { | |||
| ||||
1374 | return NULL((void*)0); | |||
1375 | } | |||
1376 | ||||
1377 | if (! ( orig = (xml_ns_t *)wmem_map_lookup(elements, elem_name) )) { | |||
1378 | g_string_append_printf(error, "element '%s' is not defined\n", elem_name); | |||
1379 | return NULL((void*)0); | |||
1380 | } | |||
1381 | ||||
1382 | depth = g_queue_get_length(hier); | |||
1383 | if (depth >= prefs.gui_max_tree_depth) { | |||
1384 | g_string_append_printf(error, "hierarchy too deep: %u\n", depth); | |||
1385 | return NULL((void*)0); | |||
1386 | } | |||
1387 | ||||
1388 | for (GList* list = hier->head; list != NULL((void*)0); list = list->next) { | |||
1389 | if( (elem_name) && (strcmp(elem_name, (char *)list->data) == 0 )) { | |||
1390 | /* Already handled */ | |||
1391 | return NULL((void*)0); | |||
1392 | } | |||
1393 | } | |||
1394 | ||||
1395 | fqn = fully_qualified_name(elem_name, parent_name); | |||
1396 | ||||
1397 | if (depth > 1) { | |||
1398 | fresh = duplicate_element(orig); | |||
1399 | } else { | |||
1400 | fresh = orig; | |||
1401 | } | |||
1402 | fresh->fqn = fqn; | |||
1403 | ||||
1404 | add_xml_field(hfs, &(fresh->hf_tag), elem_name, fqn); | |||
1405 | add_xml_field(hfs, &(fresh->hf_cdata), elem_name, fqn); | |||
1406 | ||||
1407 | ett_p = &fresh->ett; | |||
1408 | g_array_append_val(etts, ett_p)g_array_append_vals (etts, &(ett_p), 1); | |||
1409 | ||||
1410 | d.basename = fqn; | |||
1411 | d.hf = hfs; | |||
1412 | ||||
1413 | wmem_map_foreach(fresh->attributes, add_xml_attribute_names, &d); | |||
1414 | ||||
1415 | for (GList* current_element = orig->element_names; current_element != NULL((void*)0); current_element = current_element->next) { | |||
1416 | char* child_name = (char*)current_element->data; | |||
1417 | xml_ns_t* child_element = NULL((void*)0); | |||
1418 | ||||
1419 | g_queue_push_head(hier, elem_name); | |||
1420 | child_element = make_xml_hier(child_name, root, elements, hier, error, hfs, etts, fqn); | |||
1421 | g_queue_pop_head(hier); | |||
1422 | ||||
1423 | if (child_element) { | |||
1424 | wmem_map_insert(fresh->elements, child_element->name, child_element); | |||
1425 | } | |||
1426 | } | |||
1427 | return fresh; | |||
1428 | } | |||
1429 | ||||
1430 | static void free_elements(void* k _U___attribute__((unused)), void* v, void* p _U___attribute__((unused))) | |||
1431 | { | |||
1432 | xml_ns_t* e = (xml_ns_t*)v; | |||
1433 | ||||
1434 | g_list_free(e->element_names); | |||
1435 | e->element_names = NULL((void*)0); | |||
1436 | } | |||
1437 | ||||
1438 | static void register_dtd(dtd_build_data_t *dtd_data, GString *errors) | |||
1439 | { | |||
1440 | wmem_map_t *elements = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal); | |||
1441 | char *root_name = NULL((void*)0); | |||
| ||||
1442 | xml_ns_t *root_element = NULL((void*)0); | |||
1443 | wmem_array_t *hfs; | |||
1444 | GArray *etts; | |||
1445 | char *curr_name; | |||
1446 | GList *element_names = NULL((void*)0); | |||
1447 | ||||
1448 | /* we first populate elements with the those coming from the parser */ | |||
1449 | while(dtd_data->elements->len) { | |||
1450 | dtd_named_list_t *nl = (dtd_named_list_t *)g_ptr_array_remove_index(dtd_data->elements, 0); | |||
1451 | xml_ns_t *element = wmem_new(wmem_epan_scope(), xml_ns_t)((xml_ns_t*)wmem_alloc((wmem_epan_scope()), sizeof(xml_ns_t)) ); | |||
1452 | ||||
1453 | /* we will use the first element found as root in case no other one was given. */ | |||
1454 | if (root_name == NULL((void*)0)) | |||
1455 | root_name = nl->name; | |||
1456 | ||||
1457 | element->name = nl->name; | |||
1458 | element->element_names = nl->list; | |||
1459 | element->hf_tag = 0; | |||
1460 | element->hf_cdata = 0; | |||
1461 | element->ett = 0; | |||
1462 | element->attributes = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal); | |||
1463 | element->elements = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal); | |||
1464 | ||||
1465 | if( wmem_map_lookup(elements, element->name) ) { | |||
1466 | g_string_append_printf(errors, "element %s defined more than once\n", element->name); | |||
1467 | free_elements(NULL((void*)0), element, NULL((void*)0)); | |||
1468 | } else { | |||
1469 | wmem_map_insert(elements, element->name, element); | |||
1470 | element_names = g_list_prepend(element_names, element->name); | |||
1471 | } | |||
1472 | ||||
1473 | g_free(nl); | |||
1474 | } | |||
1475 | ||||
1476 | /* then we add the attributes to its relative elements */ | |||
1477 | while(dtd_data->attributes->len) { | |||
1478 | dtd_named_list_t *nl = (dtd_named_list_t *)g_ptr_array_remove_index(dtd_data->attributes, 0); | |||
1479 | xml_ns_t *element = (xml_ns_t *)wmem_map_lookup(elements, nl->name); | |||
1480 | ||||
1481 | if (element) { | |||
1482 | for (GList* current_attribute = nl->list; current_attribute != NULL((void*)0); current_attribute = current_attribute->next) { | |||
1483 | char *name = (char *)current_attribute->data; | |||
1484 | int *id_p = wmem_new(wmem_epan_scope(), int)((int*)wmem_alloc((wmem_epan_scope()), sizeof(int))); | |||
1485 | ||||
1486 | *id_p = 0; | |||
1487 | wmem_map_insert(element->attributes, name, id_p); | |||
1488 | } | |||
1489 | } | |||
1490 | else { | |||
1491 | g_string_append_printf(errors, "element %s is not defined\n", nl->name); | |||
1492 | } | |||
1493 | ||||
1494 | g_list_free(nl->list); | |||
1495 | g_free(nl); | |||
1496 | } | |||
1497 | ||||
1498 | /* if a proto_root is defined in the dtd we'll use that as root */ | |||
1499 | if ( dtd_data->proto_root ) { | |||
1500 | root_name = dtd_data->proto_root; | |||
1501 | } | |||
1502 | ||||
1503 | /* | |||
1504 | * if a proto name was given in the dtd the dtd will be used as a protocol | |||
1505 | * or else the dtd will be loaded as a branch of the xml namespace | |||
1506 | */ | |||
1507 | if( ! dtd_data->proto_name ) { | |||
1508 | hfs = hf_arr; | |||
1509 | etts = ett_arr; | |||
1510 | } else { | |||
1511 | /* | |||
1512 | * if we were given a proto_name the namespace will be registered | |||
1513 | * as an independent protocol with its own hf and ett arrays. | |||
1514 | */ | |||
1515 | hfs = wmem_array_new(wmem_epan_scope(), sizeof(hf_register_info)); | |||
1516 | etts = g_array_new(false0, false0, sizeof(int *)); | |||
1517 | } | |||
1518 | ||||
1519 | /* the root element of the dtd's namespace */ | |||
1520 | root_element = wmem_new(wmem_epan_scope(), xml_ns_t)((xml_ns_t*)wmem_alloc((wmem_epan_scope()), sizeof(xml_ns_t)) ); | |||
1521 | root_element->name = wmem_strdup(wmem_epan_scope(), root_name); | |||
1522 | root_element->fqn = dtd_data->proto_name
| |||
1523 | root_element->hf_tag = 0; | |||
1524 | root_element->hf_cdata = 0; | |||
1525 | root_element->ett = 0; | |||
1526 | root_element->elements = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal); | |||
1527 | root_element->element_names = element_names; | |||
1528 | ||||
1529 | /* | |||
1530 | * we can either create a namespace as a flat namespace | |||
1531 | * in which all the elements are at the root level | |||
1532 | * or we can create a recursive namespace | |||
1533 | */ | |||
1534 | if (dtd_data->recursion) { | |||
1535 | xml_ns_t *orig_root; | |||
1536 | GQueue* hier = g_queue_new(); /* Acts as a stack with the names to avoid recurring infinitely */ | |||
1537 | if (!dtd_data->proto_name
| |||
1538 | g_queue_push_head(hier, "xml"); | |||
1539 | ||||
1540 | make_xml_hier(root_name, root_element, elements, hier, errors, hfs, etts, dtd_data->proto_name); | |||
1541 | ||||
1542 | wmem_map_insert(root_element->elements, (void *)root_element->name, root_element); | |||
1543 | ||||
1544 | orig_root = (xml_ns_t *)wmem_map_lookup(elements, root_name); | |||
1545 | ||||
1546 | /* if the root element was defined copy its attrlist to the child */ | |||
1547 | if(orig_root) { | |||
1548 | struct _attr_reg_data d; | |||
1549 | ||||
1550 | d.basename = dtd_data->proto_name; | |||
1551 | d.hf = hfs; | |||
1552 | ||||
1553 | root_element->attributes = copy_attributes_hash(orig_root->attributes); | |||
1554 | wmem_map_foreach(root_element->attributes, add_xml_attribute_names, &d); | |||
1555 | } else { | |||
1556 | root_element->attributes = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal); | |||
1557 | } | |||
1558 | ||||
1559 | /* we then create all the sub hierarchies to catch the recurred cases */ | |||
1560 | g_queue_push_head(hier, root_name); | |||
1561 | ||||
1562 | while (root_element->element_names != NULL((void*)0)) | |||
1563 | { | |||
1564 | curr_name = (char*)root_element->element_names->data; | |||
1565 | root_element->element_names = g_list_remove(root_element->element_names, curr_name); | |||
1566 | ||||
1567 | if (!wmem_map_lookup(root_element->elements, curr_name)) { | |||
1568 | xml_ns_t* fresh = make_xml_hier(curr_name, root_element, elements, hier, errors, | |||
1569 | hfs, etts, dtd_data->proto_name); | |||
1570 | wmem_map_insert(root_element->elements, (void*)fresh->name, fresh); | |||
1571 | } | |||
1572 | } | |||
1573 | ||||
1574 | /* No longer need the hierarchy check */ | |||
1575 | g_queue_free(hier); | |||
1576 | ||||
1577 | } else { | |||
1578 | /* a flat namespace */ | |||
1579 | xml_element_iter_data iterdata = { | |||
1580 | .root_element = root_element, | |||
1581 | .hfs = hfs, | |||
1582 | .etts = etts | |||
1583 | }; | |||
1584 | ||||
1585 | root_element->attributes = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal); | |||
1586 | wmem_map_foreach(elements, add_xml_flat_element_names, &iterdata); | |||
1587 | } | |||
1588 | ||||
1589 | /* | |||
1590 | * if we were given a proto_name the namespace will be registered | |||
1591 | * as an independent protocol. | |||
1592 | * XXX - Should these be PINOs? The standard xml_handle is called, | |||
1593 | * which means that enabling and disabling the protocols has no | |||
1594 | * effect. | |||
1595 | */ | |||
1596 | if ( dtd_data->proto_name ) { | |||
1597 | int *ett_p; | |||
1598 | char *full_name, *short_name; | |||
1599 | ||||
1600 | if (dtd_data->description) { | |||
1601 | full_name = dtd_data->description; | |||
1602 | } else { | |||
1603 | full_name = root_name; | |||
1604 | } | |||
1605 | short_name = dtd_data->proto_name; | |||
1606 | ||||
1607 | ett_p = &root_element->ett; | |||
1608 | g_array_append_val(etts, ett_p)g_array_append_vals (etts, &(ett_p), 1); | |||
1609 | ||||
1610 | /* Ensure the cdata field (a FT_STRING) has a different abbrev | |||
1611 | * than the FT_PROTOCOL. (XXX - Maybe we should do this for all | |||
1612 | * the cdata fields?) */ | |||
1613 | char *cdata_name = wmem_strdup_printf(wmem_epan_scope(), "%s.cdata", root_element->fqn); | |||
1614 | add_xml_field(hfs, &root_element->hf_cdata, root_element->name, cdata_name); | |||
1615 | ||||
1616 | root_element->hf_tag = proto_register_protocol(full_name, short_name, short_name); | |||
1617 | proto_register_field_array(root_element->hf_tag, (hf_register_info*)wmem_array_get_raw(hfs), wmem_array_get_count(hfs)); | |||
1618 | proto_register_subtree_array((int **)etts->data, etts->len); | |||
1619 | ||||
1620 | if (dtd_data->media_type) { | |||
1621 | wmem_map_insert(media_types, dtd_data->media_type, root_element); | |||
1622 | } | |||
1623 | ||||
1624 | g_array_free(etts, true1); | |||
1625 | } | |||
1626 | ||||
1627 | wmem_map_insert(xml_ns.elements, root_element->name, root_element); | |||
1628 | wmem_map_foreach(elements, free_elements, NULL((void*)0)); | |||
1629 | free_elements(NULL((void*)0), root_element, NULL((void*)0)); | |||
1630 | ||||
1631 | destroy_dtd_data(dtd_data); | |||
1632 | } | |||
1633 | ||||
1634 | static dtd_build_data_t* g_build_data; | |||
1635 | ||||
1636 | static void dtd_pi_cb(void* ctx _U___attribute__((unused)), const xmlChar* target, const xmlChar* data) | |||
1637 | { | |||
1638 | if (strcmp(target, "wireshark-protocol") == 0) { | |||
1639 | ||||
1640 | xmlDocPtr fake_doc; | |||
1641 | char* fake_element; | |||
1642 | ||||
1643 | //libxml2 doesn't parse this content into attributes, so create a dummy element | |||
1644 | //to parse out the Wireshark data | |||
1645 | fake_element = wmem_strdup_printf(NULL((void*)0), "<fake_root %s />", data); | |||
1646 | fake_doc = xmlReadMemory(fake_element, (int)strlen(fake_element), NULL((void*)0), NULL((void*)0), 0); | |||
1647 | if (fake_doc != NULL((void*)0)) | |||
1648 | { | |||
1649 | if (fake_doc->children != NULL((void*)0)) | |||
1650 | { | |||
1651 | xmlChar* value; | |||
1652 | for (xmlAttrPtr attr = fake_doc->children->properties; attr != NULL((void*)0); attr = attr->next) | |||
1653 | { | |||
1654 | if (xmlStrcmp(attr->name, (const xmlChar*)"proto_name") == 0) { | |||
1655 | value = xmlNodeListGetString(fake_doc, attr->children, 1); | |||
1656 | char* lower_proto = g_ascii_strdown(value, -1); | |||
1657 | g_build_data->proto_name = wmem_strdup(wmem_epan_scope(), lower_proto); | |||
1658 | g_free(lower_proto); | |||
1659 | xmlFree(value); | |||
1660 | } | |||
1661 | if (xmlStrcmp(attr->name, (const xmlChar*)"root") == 0) { | |||
1662 | value = xmlNodeListGetString(fake_doc, attr->children, 1); | |||
1663 | g_build_data->proto_root = g_ascii_strdown(value, -1); | |||
1664 | xmlFree(value); | |||
1665 | } | |||
1666 | else if (xmlStrcmp(attr->name, (const xmlChar*)"media") == 0) { | |||
1667 | value = xmlNodeListGetString(fake_doc, attr->children, 1); | |||
1668 | g_build_data->media_type = wmem_strdup(wmem_epan_scope(), value); | |||
1669 | xmlFree(value); | |||
1670 | } | |||
1671 | else if (xmlStrcmp(attr->name, (const xmlChar*)"description") == 0) { | |||
1672 | value = xmlNodeListGetString(fake_doc, attr->children, 1); | |||
1673 | g_build_data->description = wmem_strdup(wmem_epan_scope(), value); | |||
1674 | xmlFree(value); | |||
1675 | } | |||
1676 | else if (xmlStrcmp(attr->name, (const xmlChar*)"hierarchy") == 0) { | |||
1677 | value = xmlNodeListGetString(fake_doc, attr->children, 1); | |||
1678 | g_build_data->recursion = (g_ascii_strcasecmp(value, "yes") == 0) ? true1 : false0; | |||
1679 | xmlFree(value); | |||
1680 | } | |||
1681 | } | |||
1682 | } | |||
1683 | ||||
1684 | //TODO: Error checking for required attributes? | |||
1685 | } | |||
1686 | xmlFreeDoc(fake_doc); | |||
1687 | wmem_free(NULL((void*)0), fake_element); | |||
1688 | } | |||
1689 | } | |||
1690 | ||||
1691 | static void dtd_internalSubset_cb(void* ctx _U___attribute__((unused)), const xmlChar* name, const xmlChar* publicId _U___attribute__((unused)), const xmlChar* systemId _U___attribute__((unused))) | |||
1692 | { | |||
1693 | wmem_free(wmem_epan_scope(), g_build_data->proto_root); | |||
1694 | g_build_data->proto_root = wmem_ascii_strdown(wmem_epan_scope(), (const char*)name, -1); | |||
1695 | if (!g_build_data->proto_name) { | |||
1696 | g_build_data->proto_name = g_build_data->proto_root; | |||
1697 | } | |||
1698 | } | |||
1699 | ||||
1700 | // NOLINTNEXTLINE(misc-no-recursion) | |||
1701 | static GList* dtd_elementDecl_add_list(GList* list, xmlElementContent* content) | |||
1702 | { | |||
1703 | if (content != NULL((void*)0)) { | |||
1704 | if (content->c1 != NULL((void*)0)) { | |||
1705 | if (content->c1->name != NULL((void*)0)) { | |||
1706 | list = g_list_prepend(list, wmem_ascii_strdown(wmem_epan_scope(), (const char*)content->c1->name, -1)); | |||
1707 | } | |||
1708 | list = dtd_elementDecl_add_list(list, content->c1); | |||
1709 | } | |||
1710 | if (content->c2 != NULL((void*)0)) { | |||
1711 | if (content->c2->name != NULL((void*)0)) { | |||
1712 | list = g_list_prepend(list, wmem_ascii_strdown(wmem_epan_scope(), (const char*)content->c2->name, -1)); | |||
1713 | } | |||
1714 | list = dtd_elementDecl_add_list(list, content->c2); | |||
1715 | } | |||
1716 | } | |||
1717 | ||||
1718 | return list; | |||
1719 | } | |||
1720 | ||||
1721 | static void dtd_elementDecl_cb(void* ctx _U___attribute__((unused)), const xmlChar* name, int type _U___attribute__((unused)), xmlElementContent* content _U___attribute__((unused))) | |||
1722 | { | |||
1723 | dtd_named_list_t* new_element = g_new0(dtd_named_list_t, 1)((dtd_named_list_t *) g_malloc0_n ((1), sizeof (dtd_named_list_t ))); | |||
1724 | ||||
1725 | new_element->name = wmem_ascii_strdown(wmem_epan_scope(), (const char*)name, -1); | |||
1726 | new_element->list = NULL((void*)0); | |||
1727 | ||||
1728 | /* we will use the first element found as root in case no other one was given. */ | |||
1729 | if (!g_build_data->proto_root) { | |||
1730 | g_build_data->proto_root = new_element->name; | |||
1731 | } | |||
1732 | ||||
1733 | //Make list | |||
1734 | if ((content != NULL((void*)0)) && (content->name != NULL((void*)0))) { | |||
1735 | new_element->list = g_list_prepend(new_element->list, wmem_ascii_strdown(wmem_epan_scope(), (const char*)content->name, -1)); | |||
1736 | } | |||
1737 | new_element->list = dtd_elementDecl_add_list(new_element->list, content); | |||
1738 | ||||
1739 | g_ptr_array_add(g_build_data->elements, new_element); | |||
1740 | } | |||
1741 | ||||
1742 | static void dtd_attributeDecl_cb(void* ctx _U___attribute__((unused)), const xmlChar* elem, const xmlChar* fullname, int type _U___attribute__((unused)), int def _U___attribute__((unused)), | |||
1743 | const xmlChar* defaultValue _U___attribute__((unused)), xmlEnumerationPtr tree) | |||
1744 | { | |||
1745 | /* See https://www.w3.org/TR/xml/#attdecls | |||
1746 | * elem is the name of the parent Element, which may not exist: | |||
1747 | * "At user option, an XML processor MAY issue a warning if attributes | |||
1748 | * are declared for an element type not itself declared, but this is | |||
1749 | * not an error... When more than one AttlistDecl is provided for a given | |||
1750 | * element type, the contents of all those provided are merged." | |||
1751 | */ | |||
1752 | dtd_named_list_t* attribute; | |||
1753 | bool_Bool found = false0; | |||
1754 | char* elem_down = g_ascii_strdown((const char*)elem, -1); | |||
1755 | for (unsigned i = g_build_data->attributes->len; i > 0; i--) { | |||
1756 | attribute = g_build_data->attributes->pdata[i - 1]; | |||
1757 | if (strcmp(attribute->name, elem_down) == 0) { | |||
1758 | found = true1; | |||
1759 | break; | |||
1760 | } | |||
1761 | } | |||
1762 | if (!found) { | |||
1763 | attribute = g_new0(dtd_named_list_t, 1)((dtd_named_list_t *) g_malloc0_n ((1), sizeof (dtd_named_list_t ))); | |||
1764 | attribute->name = wmem_strdup(wmem_epan_scope(), elem_down); | |||
1765 | attribute->list = NULL((void*)0); | |||
1766 | g_ptr_array_add(g_build_data->attributes, attribute); | |||
1767 | } | |||
1768 | g_free(elem_down); | |||
1769 | ||||
1770 | attribute->list = g_list_prepend(attribute->list, wmem_ascii_strdown(wmem_epan_scope(), (const char*)fullname, -1)); | |||
1771 | // We don't use this. We're allowed to free it, as the default SAX2 handler | |||
1772 | // here does and it's not used after this by the main parser. | |||
1773 | if (tree != NULL((void*)0)) | |||
1774 | xmlFreeEnumeration(tree); | |||
1775 | } | |||
1776 | ||||
1777 | static void dtd_error_cb(void* ctx _U___attribute__((unused)), const char* msg, ...) | |||
1778 | { | |||
1779 | char buf[40]; | |||
1780 | va_list args; | |||
1781 | va_start(args, msg)__builtin_va_start(args, msg); | |||
1782 | va_list args2; | |||
1783 | va_copy(args2, args)__builtin_va_copy(args2, args); | |||
1784 | vsnprintf(buf, sizeof(buf), msg, args); | |||
1785 | va_end(args)__builtin_va_end(args); | |||
1786 | /* We allow (see dc.dtd and itunes.dtd) "DTDs" that have a DOCTYPE | |||
1787 | * declaration. That makes them not valid external DTDs. They also | |||
1788 | * aren't valid XML documents with internal DTDs (which is how libxml2 | |||
1789 | * tried to parse them) because they have no tags. | |||
1790 | * Parsing them as a DTD gives the "Content error in the external subset" | |||
1791 | * error; parsing them as a document gives the "Start tag expected" | |||
1792 | * error. | |||
1793 | * | |||
1794 | * So we ignore those errors and report others. If those are the only | |||
1795 | * errors, then we'll call it valid and fully parse it later with the | |||
1796 | * lex-based parser. | |||
1797 | * | |||
1798 | * XXX - Can we achieve the same result while forcing the DTDs to | |||
1799 | * be normal standalone external DTDs? Make people use the "root" | |||
1800 | * attribute if necessary? Need to verify that it would parse the same, | |||
1801 | * but it would simplify the code. We could also insert an empty tag | |||
1802 | * or something to make libxml2 happy, but the flex-based parser complains | |||
1803 | * in that case. | |||
1804 | */ | |||
1805 | if (!g_str_has_prefix(buf, "Start tag expected")(__builtin_constant_p ("Start tag expected")? __extension__ ( { const char * const __str = (buf); const char * const __prefix = ("Start tag expected"); gboolean __result = (0); if (__str == ((void*)0) || __prefix == ((void*)0)) __result = (g_str_has_prefix ) (__str, __prefix); else { const size_t __str_len = strlen ( ((__str) + !(__str))); const size_t __prefix_len = strlen ((( __prefix) + !(__prefix))); if (__str_len >= __prefix_len) __result = memcmp (((__str) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len ) == 0; } __result; }) : (g_str_has_prefix) (buf, "Start tag expected" ) ) && | |||
1806 | !g_str_has_prefix(buf, "Content error in the external subset")(__builtin_constant_p ("Content error in the external subset" )? __extension__ ({ const char * const __str = (buf); const char * const __prefix = ("Content error in the external subset"); gboolean __result = (0); if (__str == ((void*)0) || __prefix == ((void*)0)) __result = (g_str_has_prefix) (__str, __prefix ); else { const size_t __str_len = strlen (((__str) + !(__str ))); const size_t __prefix_len = strlen (((__prefix) + !(__prefix ))); if (__str_len >= __prefix_len) __result = memcmp (((__str ) + !(__str)), ((__prefix) + !(__prefix)), __prefix_len) == 0 ; } __result; }) : (g_str_has_prefix) (buf, "Content error in the external subset" ) )) { | |||
1807 | g_string_append_vprintf(g_build_data->error, msg, args2); | |||
1808 | } | |||
1809 | va_end(args2)__builtin_va_end(args2); | |||
1810 | } | |||
1811 | ||||
1812 | static dtd_build_data_t* | |||
1813 | dtd_parse_libxml2(char* filename) | |||
1814 | { | |||
1815 | xmlSAXHandler saxHandler; | |||
1816 | xmlSAXVersion(&saxHandler, 2); | |||
1817 | saxHandler.processingInstruction = dtd_pi_cb; | |||
1818 | saxHandler.internalSubset = dtd_internalSubset_cb; | |||
1819 | saxHandler.elementDecl = dtd_elementDecl_cb; | |||
1820 | saxHandler.attributeDecl = dtd_attributeDecl_cb; | |||
1821 | saxHandler.error = dtd_error_cb; | |||
1822 | ||||
1823 | xmlParserInputBuffer* buffer; | |||
1824 | ||||
1825 | xmlDtdPtr dtd; | |||
1826 | xmlDocPtr doc; | |||
1827 | xmlParserCtxt* ctxt; | |||
1828 | bool_Bool external_dtd = false0; | |||
1829 | ||||
1830 | // Initialize the build data | |||
1831 | g_build_data = g_new0(dtd_build_data_t, 1)((dtd_build_data_t *) g_malloc0_n ((1), sizeof (dtd_build_data_t ))); | |||
1832 | g_build_data->elements = g_ptr_array_new(); | |||
1833 | g_build_data->attributes = g_ptr_array_new(); | |||
1834 | g_build_data->error = g_string_new(""); | |||
1835 | ||||
1836 | buffer = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_UTF8); | |||
1837 | ||||
1838 | // xmlCtxtParseDtd is introduced in 2.14.0; before that | |||
1839 | // there's no way to parse a DTD using a xmlParserCtxt | |||
1840 | // or userData, just with a saxHandler directly. That | |||
1841 | // also means that instead of using a dtd_build_data_t | |||
1842 | // as user data, we just use a global. | |||
1843 | dtd = xmlIOParseDTD(&saxHandler, buffer, XML_CHAR_ENCODING_UTF8); | |||
1844 | /* Is it a regular standalone external DTD? */ | |||
1845 | if (dtd) { | |||
1846 | xmlFreeDtd(dtd); | |||
1847 | external_dtd = true1; | |||
1848 | } | |||
1849 | else { | |||
1850 | /* OK, it is a XML document with an internal DTD but | |||
1851 | * possibly lacking any tags? */ | |||
1852 | #if LIBXML_VERSION20914 >= 21100 | |||
1853 | ctxt = xmlNewSAXParserCtxt(&saxHandler, NULL((void*)0) /*g_build_data*/); | |||
1854 | #else | |||
1855 | ctxt = xmlNewParserCtxt(); | |||
1856 | if (ctxt->sax != NULL((void*)0)) { | |||
1857 | xmlFree(ctxt->sax); | |||
1858 | } | |||
1859 | ctxt->sax = &saxHandler; | |||
1860 | //ctxt->userData = g_build_data; | |||
1861 | #endif | |||
1862 | // We don't actually want the document here, so | |||
1863 | // we could use xmlParseDocument, but we need | |||
1864 | // to set the input (use xmlCreateURLParserCtxt | |||
1865 | // from parserInternals.h?) | |||
1866 | doc = xmlCtxtReadFile(ctxt, filename, NULL((void*)0), 0); | |||
1867 | // We don't need XML_PARSE_DTDLOAD because we don't | |||
1868 | // want *external* DTDs or entities. We might need | |||
1869 | // XML_PARSE_NOENT eventually though. | |||
1870 | xmlFreeDoc(doc); | |||
1871 | #if LIBXML_VERSION20914 < 21100 | |||
1872 | // sax not copied here, so remove it so it doesn't get | |||
1873 | // freed (it was declared on the stack). | |||
1874 | ctxt->sax = NULL((void*)0); | |||
1875 | #endif | |||
1876 | xmlFreeParserCtxt(ctxt); | |||
1877 | } | |||
1878 | ||||
1879 | //Add a root node for the doctype itself | |||
1880 | if (!external_dtd && (g_build_data->elements->len > 0)) { | |||
1881 | ||||
1882 | dtd_named_list_t* new_element = g_new(dtd_named_list_t, 1)((dtd_named_list_t *) g_malloc_n ((1), sizeof (dtd_named_list_t ))); | |||
1883 | new_element->name = g_build_data->proto_name; | |||
1884 | new_element->list = NULL((void*)0); | |||
1885 | for (unsigned i = 0; i < g_build_data->elements->len; i++) { | |||
1886 | dtd_named_list_t* el = (dtd_named_list_t*)g_ptr_array_index(g_build_data->elements, i)((g_build_data->elements)->pdata)[i]; | |||
1887 | new_element->list = g_list_prepend(new_element->list, el->name); | |||
1888 | } | |||
1889 | ||||
1890 | g_ptr_array_add(g_build_data->elements, new_element); | |||
1891 | } | |||
1892 | ||||
1893 | // xmlIOParseDTD: "input will be freed by the function" | |||
1894 | // (even on error), so no need for | |||
1895 | // xmlFreeParserInputBuffer(buffer); | |||
1896 | ||||
1897 | return g_build_data; | |||
1898 | } | |||
1899 | ||||
1900 | # define DIRECTORY_TGDir GDir | |||
1901 | # define FILE_Tchar char | |||
1902 | # define OPENDIR_OP(name)g_dir_open(name, 0, dummy) g_dir_open(name, 0, dummy) | |||
1903 | # define DIRGETNEXT_OP(dir)g_dir_read_name(dir) g_dir_read_name(dir) | |||
1904 | # define GETFNAME_OP(file)(file); (file); | |||
1905 | # define CLOSEDIR_OP(dir)g_dir_close(dir) g_dir_close(dir) | |||
1906 | ||||
1907 | static void init_xml_names(void) | |||
1908 | { | |||
1909 | unsigned i; | |||
1910 | DIRECTORY_TGDir *dir; | |||
1911 | const FILE_Tchar *file; | |||
1912 | const char *filename; | |||
1913 | char *dirname; | |||
1914 | ||||
1915 | GError **dummy = wmem_new(wmem_epan_scope(), GError *)((GError **)wmem_alloc((wmem_epan_scope()), sizeof(GError *)) ); | |||
1916 | *dummy = NULL((void*)0); | |||
1917 | ||||
1918 | xmpli_names = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal); | |||
1919 | media_types = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal); | |||
1920 | ||||
1921 | for(i=0;i<array_length(default_media_types)(sizeof (default_media_types) / sizeof (default_media_types)[ 0]);i++) { | |||
1922 | wmem_map_insert(media_types, (void *)default_media_types[i], &xml_ns); | |||
1923 | } | |||
1924 | ||||
1925 | unknown_ns.elements = xml_ns.elements = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal); | |||
1926 | unknown_ns.attributes = xml_ns.attributes = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal); | |||
1927 | ||||
1928 | xml_new_namespace(xmpli_names, "xml", "version", "encoding", "standalone", NULL((void*)0)); | |||
1929 | ||||
1930 | dirname = get_persconffile_path("dtds", false0); | |||
1931 | ||||
1932 | if (test_for_directory(dirname) != EISDIR21) { | |||
1933 | /* Although dir isn't a directory it may still use memory */ | |||
1934 | g_free(dirname); | |||
1935 | dirname = get_datafile_path("dtds"); | |||
1936 | } | |||
1937 | ||||
1938 | if (test_for_directory(dirname) == EISDIR21) { | |||
1939 | if ((dir = OPENDIR_OP(dirname)g_dir_open(dirname, 0, dummy)) != NULL((void*)0)) { | |||
1940 | GString *errors = g_string_new(""); | |||
1941 | ||||
1942 | while ((file = DIRGETNEXT_OP(dir)g_dir_read_name(dir)) != NULL((void*)0)) { | |||
1943 | unsigned namelen; | |||
1944 | filename = GETFNAME_OP(file)(file);; | |||
1945 | ||||
1946 | namelen = (int)strlen(filename); | |||
1947 | if ( namelen > 4 && ( g_ascii_strcasecmp(filename+(namelen-4), ".dtd") == 0 ) ) { | |||
1948 | dtd_build_data_t* dtd_data; | |||
1949 | ||||
1950 | char* full_file = wmem_strdup_printf(NULL((void*)0), "%s%c%s", dirname, G_DIR_SEPARATOR'/', filename); | |||
1951 | dtd_data = dtd_parse_libxml2(full_file); | |||
1952 | ||||
1953 | if (dtd_data->error->len) { | |||
1954 | report_failure("Dtd Parser in file %s: %s", full_file, dtd_data->error->str); | |||
1955 | destroy_dtd_data(dtd_data); | |||
1956 | wmem_free(NULL((void*)0), full_file); | |||
1957 | continue; | |||
1958 | } | |||
1959 | ||||
1960 | register_dtd(dtd_data, errors); | |||
1961 | ||||
1962 | if (errors->len) { | |||
1963 | report_failure("Dtd Registration in file: %s: %s", full_file, errors->str); | |||
1964 | wmem_free(NULL((void*)0), full_file); | |||
1965 | continue; | |||
1966 | } | |||
1967 | ||||
1968 | wmem_free(NULL((void*)0), full_file); | |||
1969 | } | |||
1970 | } | |||
1971 | g_string_free(errors, true)(__builtin_constant_p (1) ? ((1) ? (g_string_free) ((errors), (1)) : g_string_free_and_steal (errors)) : (g_string_free) ( (errors), (1))); | |||
1972 | ||||
1973 | CLOSEDIR_OP(dir)g_dir_close(dir); | |||
1974 | } | |||
1975 | } | |||
1976 | ||||
1977 | g_free(dirname); | |||
1978 | ||||
1979 | wmem_map_foreach(xmpli_names, add_xmlpi_namespace, (void *)"xml.xmlpi"); | |||
1980 | ||||
1981 | wmem_free(wmem_epan_scope(), dummy); | |||
1982 | } | |||
1983 | ||||
1984 | static void | |||
1985 | xml_shutdown_protocol(void) { | |||
1986 | g_regex_unref(encoding_pattern); | |||
1987 | } | |||
1988 | ||||
1989 | void | |||
1990 | proto_register_xml(void) | |||
1991 | { | |||
1992 | static int *ett_base[] = { | |||
1993 | &unknown_ns.ett, | |||
1994 | &xml_ns.ett, | |||
1995 | &ett_dtd, | |||
1996 | &ett_xmpli | |||
1997 | }; | |||
1998 | ||||
1999 | static hf_register_info hf_base[] = { | |||
2000 | { &hf_xmlpi, | |||
2001 | {"XMLPI", "xml.xmlpi", | |||
2002 | FT_STRING, BASE_NONE, NULL((void*)0), 0, | |||
2003 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } | |||
2004 | }, | |||
2005 | { &hf_cdatasection, | |||
2006 | {"CDATASection", "xml.cdatasection", | |||
2007 | FT_STRING, BASE_NONE, NULL((void*)0), 0, | |||
2008 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } | |||
2009 | }, | |||
2010 | { &hf_comment, | |||
2011 | {"Comment", "xml.comment", | |||
2012 | FT_STRING, BASE_NONE, NULL((void*)0), 0, | |||
2013 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } | |||
2014 | }, | |||
2015 | { &hf_unknowwn_attrib, | |||
2016 | {"Attribute", "xml.attribute", | |||
2017 | FT_STRING, BASE_NONE, NULL((void*)0), 0, | |||
2018 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } | |||
2019 | }, | |||
2020 | { &hf_doctype, | |||
2021 | {"Doctype", "xml.doctype", | |||
2022 | FT_STRING, BASE_NONE, NULL((void*)0), 0, | |||
2023 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } | |||
2024 | }, | |||
2025 | { &hf_dtd_tag, | |||
2026 | {"DTD Tag", "xml.dtdtag", | |||
2027 | FT_STRING, BASE_NONE, NULL((void*)0), 0, | |||
2028 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } | |||
2029 | }, | |||
2030 | { &unknown_ns.hf_cdata, | |||
2031 | {"CDATA", "xml.cdata", | |||
2032 | FT_STRING, BASE_NONE, NULL((void*)0), 0, NULL((void*)0), | |||
2033 | HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } | |||
2034 | }, | |||
2035 | { &unknown_ns.hf_tag, | |||
2036 | {"Tag", "xml.tag", | |||
2037 | FT_STRING, BASE_NONE, NULL((void*)0), 0, | |||
2038 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } | |||
2039 | }, | |||
2040 | { &xml_ns.hf_cdata, | |||
2041 | {"Unknown", "xml.unknown", | |||
2042 | FT_STRING, BASE_NONE, NULL((void*)0), 0, | |||
2043 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } | |||
2044 | } | |||
2045 | }; | |||
2046 | ||||
2047 | static ei_register_info ei[] = { | |||
2048 | { &ei_xml_closing_unopened_tag, { "xml.closing_unopened_tag", PI_MALFORMED0x07000000, PI_ERROR0x00800000, "Closing an unopened tag", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, | |||
2049 | { &ei_xml_closing_unopened_xmpli_tag, { "xml.closing_unopened_xmpli_tag", PI_MALFORMED0x07000000, PI_ERROR0x00800000, "Closing an unopened xmpli tag", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, | |||
2050 | { &ei_xml_unrecognized_text, { "xml.unrecognized_text", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "Unrecognized text", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }}, | |||
2051 | }; | |||
2052 | ||||
2053 | module_t *xml_module; | |||
2054 | expert_module_t* expert_xml; | |||
2055 | ||||
2056 | hf_arr = wmem_array_new(wmem_epan_scope(), sizeof(hf_register_info)); | |||
2057 | ett_arr = g_array_new(false0, false0, sizeof(int *)); | |||
2058 | ||||
2059 | wmem_array_append(hf_arr, hf_base, array_length(hf_base)(sizeof (hf_base) / sizeof (hf_base)[0])); | |||
2060 | g_array_append_vals(ett_arr, ett_base, array_length(ett_base)(sizeof (ett_base) / sizeof (ett_base)[0])); | |||
2061 | ||||
2062 | init_xml_names(); | |||
2063 | ||||
2064 | xml_ns.hf_tag = proto_register_protocol("eXtensible Markup Language", "XML", xml_ns.name); | |||
2065 | ||||
2066 | proto_register_field_array(xml_ns.hf_tag, (hf_register_info*)wmem_array_get_raw(hf_arr), wmem_array_get_count(hf_arr)); | |||
2067 | proto_register_subtree_array((int **)ett_arr->data, ett_arr->len); | |||
2068 | expert_xml = expert_register_protocol(xml_ns.hf_tag); | |||
2069 | expert_register_field_array(expert_xml, ei, array_length(ei)(sizeof (ei) / sizeof (ei)[0])); | |||
2070 | ||||
2071 | xml_module = prefs_register_protocol(xml_ns.hf_tag, NULL((void*)0)); | |||
2072 | prefs_register_obsolete_preference(xml_module, "heuristic"); | |||
2073 | prefs_register_obsolete_preference(xml_module, "heuristic_tcp"); | |||
2074 | prefs_register_obsolete_preference(xml_module, "heuristic_udp"); | |||
2075 | /* XXX - UCS-2, or UTF-16? */ | |||
2076 | prefs_register_bool_preference(xml_module, "heuristic_unicode", "Use Unicode in heuristics", | |||
2077 | "Try to recognize XML encoded in Unicode (UCS-2BE)", | |||
2078 | &pref_heuristic_unicode); | |||
2079 | ||||
2080 | prefs_register_enum_preference(xml_module, "default_encoding", "Default character encoding", | |||
2081 | "Use this charset if the 'encoding' attribute of XML declaration is missing." | |||
2082 | "Unsupported encoding will be replaced by the default UTF-8.", | |||
2083 | &pref_default_encoding, ws_supported_mibenum_vals_character_sets_ev_array, false0); | |||
2084 | ||||
2085 | // The longest encoding at https://www.iana.org/assignments/character-sets/character-sets.xml | |||
2086 | // is 45 characters (Extended_UNIX_Code_Packed_Format_for_Japanese). | |||
2087 | encoding_pattern = g_regex_new("^\\s*<[?]xml\\s+version\\s*=\\s*[\"']\\s*(?U:.+)\\s*[\"']\\s+encoding\\s*=\\s*[\"']\\s*((?U).{1,50})\\s*[\"']", G_REGEX_CASELESS, 0, 0); | |||
2088 | register_shutdown_routine(&xml_shutdown_protocol); | |||
2089 | ||||
2090 | xml_handle = register_dissector("xml", dissect_xml, xml_ns.hf_tag); | |||
2091 | ||||
2092 | init_xml_parser(); | |||
2093 | } | |||
2094 | ||||
2095 | static void | |||
2096 | add_dissector_media(void *k, void *v _U___attribute__((unused)), void *p _U___attribute__((unused))) | |||
2097 | { | |||
2098 | dissector_add_string("media_type", (char *)k, xml_handle); | |||
2099 | } | |||
2100 | ||||
2101 | void | |||
2102 | proto_reg_handoff_xml(void) | |||
2103 | { | |||
2104 | wmem_map_foreach(media_types, add_dissector_media, NULL((void*)0)); | |||
2105 | dissector_add_string("media_type.suffix", "xml", xml_handle); /* RFC 7303 9.6 */ | |||
2106 | dissector_add_uint_range_with_preference("tcp.port", "", xml_handle); | |||
2107 | dissector_add_uint_range_with_preference("udp.port", XML_UDP_PORT_RANGE"3702", xml_handle); | |||
2108 | ||||
2109 | gssapi_handle = find_dissector_add_dependency("gssapi", xml_ns.hf_tag); | |||
2110 | ||||
2111 | heur_dissector_add("http", dissect_xml_heur, "XML in HTTP", "xml_http", xml_ns.hf_tag, HEURISTIC_DISABLE); | |||
2112 | heur_dissector_add("sip", dissect_xml_heur, "XML in SIP", "xml_sip", xml_ns.hf_tag, HEURISTIC_DISABLE); | |||
2113 | heur_dissector_add("media", dissect_xml_heur, "XML in media", "xml_media", xml_ns.hf_tag, HEURISTIC_DISABLE); | |||
2114 | heur_dissector_add("tcp", dissect_xml_heur, "XML over TCP", "xml_tcp", xml_ns.hf_tag, HEURISTIC_DISABLE); | |||
2115 | heur_dissector_add("udp", dissect_xml_heur, "XML over UDP", "xml_udp", xml_ns.hf_tag, HEURISTIC_DISABLE); | |||
2116 | ||||
2117 | heur_dissector_add("wtap_file", dissect_xml_heur, "XML file", "xml_wtap", xml_ns.hf_tag, HEURISTIC_ENABLE); | |||
2118 | ||||
2119 | dissector_add_uint("acdr.tls_application", TLS_APP_XML, xml_handle); | |||
2120 | } | |||
2121 | ||||
2122 | /* | |||
2123 | * Editor modelines - https://www.wireshark.org/tools/modelines.html | |||
2124 | * | |||
2125 | * Local variables: | |||
2126 | * c-basic-offset: 4 | |||
2127 | * tab-width: 8 | |||
2128 | * indent-tabs-mode: nil | |||
2129 | * End: | |||
2130 | * | |||
2131 | * vi: set shiftwidth=4 tabstop=8 expandtab: | |||
2132 | * :indentSize=4:tabSize=8:noTabs=true: | |||
2133 | */ |