2 * wireshark's xml dissector .
4 * (C) 2005, Luis E. Garcia Ontanon.
6 * Refer to the AUTHORS file or the AUTHORS section in the man page
7 * for contacting the author(s) of this file.
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * SPDX-License-Identifier: GPL-2.0-or-later
21 #include <epan/packet.h>
22 #include <epan/tvbparse.h>
24 #include <epan/proto_data.h>
25 #include <wsutil/filesystem.h>
26 #include <epan/prefs.h>
27 #include <epan/expert.h>
28 #include <epan/iana_charsets.h>
29 #include <epan/asn1.h>
30 #include <wsutil/str_util.h>
31 #include <wsutil/report_message.h>
32 #include <wsutil/wsgcrypt.h>
33 #include "packet-kerberos.h"
34 #include "read_keytab_file.h"
36 #include "packet-xml.h"
37 #include "packet-acdr.h"
39 void proto_register_xml(void);
40 void proto_reg_handoff_xml(void);
42 struct _attr_reg_data
{
51 static int hf_unknowwn_attrib
;
52 static int hf_comment
;
54 static int hf_dtd_tag
;
55 static int hf_doctype
;
56 static int hf_cdatasection
;
58 static expert_field ei_xml_closing_unopened_tag
;
59 static expert_field ei_xml_closing_unopened_xmpli_tag
;
60 static expert_field ei_xml_unrecognized_text
;
62 /* dissector handles */
63 static dissector_handle_t xml_handle
;
64 static dissector_handle_t gssapi_handle
;
66 /* Port 3702 is IANA-registered for Web Service Discovery, which uses
67 * SOAP-over-UDP to send XML */
68 #define XML_UDP_PORT_RANGE "3702"
70 /* parser definitions */
71 static tvbparse_wanted_t
*want
;
72 static tvbparse_wanted_t
*want_ignore
;
73 static tvbparse_wanted_t
*want_heur
;
75 static wmem_map_t
*xmpli_names
;
76 static wmem_map_t
*media_types
;
78 static xml_ns_t xml_ns
= {"xml", "/", -1, -1, -1, NULL
, NULL
, NULL
};
79 static xml_ns_t unknown_ns
= {"unknown", "?", -1, -1, -1, NULL
, NULL
, NULL
};
80 static xml_ns_t
*root_ns
;
82 static bool pref_heuristic_unicode
;
83 static int pref_default_encoding
= IANA_CS_UTF_8
;
86 #define XML_CDATA -1000
87 #define XML_SCOPED_NAME -1001
90 static wmem_array_t
*hf_arr
;
91 static GArray
*ett_arr
;
92 static GRegex
* encoding_pattern
;
94 static const char *default_media_types
[] = {
101 "application/3gpp-ims+xml",
102 "application/atom+xml",
103 "application/auth-policy+xml",
104 "application/ccmp+xml",
105 "application/conference-info+xml", /*RFC4575*/
106 "application/cpim-pidf+xml",
107 "application/cpl+xml",
108 "application/dds-web+xml",
109 "application/im-iscomposing+xml", /*RFC3994*/
110 "application/load-control+xml", /*RFC7200*/
111 "application/mathml+xml",
112 "application/media_control+xml",
113 "application/note+xml",
114 "application/pidf+xml",
115 "application/pidf-diff+xml",
116 "application/poc-settings+xml",
117 "application/rdf+xml",
118 "application/reginfo+xml",
119 "application/resource-lists+xml",
120 "application/rlmi+xml",
121 "application/rls-services+xml",
122 "application/rss+xml",
123 "application/rs-metadata+xml",
125 "application/simple-filter+xml",
126 "application/simple-message-summary+xml", /*RFC3842*/
127 "application/simservs+xml",
128 "application/soap+xml",
129 "application/vnd.etsi.aoc+xml",
130 "application/vnd.etsi.cug+xml",
131 "application/vnd.etsi.iptvcommand+xml",
132 "application/vnd.etsi.iptvdiscovery+xml",
133 "application/vnd.etsi.iptvprofile+xml",
134 "application/vnd.etsi.iptvsad-bc+xml",
135 "application/vnd.etsi.iptvsad-cod+xml",
136 "application/vnd.etsi.iptvsad-npvr+xml",
137 "application/vnd.etsi.iptvservice+xml",
138 "application/vnd.etsi.iptvsync+xml",
139 "application/vnd.etsi.iptvueprofile+xml",
140 "application/vnd.etsi.mcid+xml",
141 "application/vnd.etsi.overload-control-policy-dataset+xml",
142 "application/vnd.etsi.pstn+xml",
143 "application/vnd.etsi.sci+xml",
144 "application/vnd.etsi.simservs+xml",
145 "application/vnd.etsi.tsl+xml",
146 "application/vnd.oma.xdm-apd+xml",
147 "application/vnd.oma.fnl+xml",
148 "application/vnd.oma.access-permissions-list+xml",
149 "application/vnd.oma.alias-principals-list+xml",
150 "application/upp-directory+xml", /*OMA-ERELD-XDM-V2_2_1-20170124-A*/
151 "application/vnd.oma.xdm-hi+xml",
152 "application/vnd.oma.xdm-rhi+xml",
153 "application/vnd.oma.xdm-prefs+xml",
154 "application/vnd.oma.xdcp+xml",
155 "application/vnd.oma.bcast.associated-procedure-parameter+xml",
156 "application/vnd.oma.bcast.drm-trigger+xml",
157 "application/vnd.oma.bcast.imd+xml",
158 "application/vnd.oma.bcast.notification+xml",
159 "application/vnd.oma.bcast.sgdd+xml",
160 "application/vnd.oma.bcast.smartcard-trigger+xml",
161 "application/vnd.oma.bcast.sprov+xml",
162 "application/vnd.oma.cab-address-book+xml",
163 "application/vnd.oma.cab-feature-handler+xml",
164 "application/vnd.oma.cab-pcc+xml",
165 "application/vnd.oma.cab-subs-invite+xml",
166 "application/vnd.oma.cab-user-prefs+xml",
167 "application/vnd.oma.dd2+xml",
168 "application/vnd.oma.drm.risd+xml",
169 "application/vnd.oma.group-usage-list+xml",
170 "application/vnd.oma.pal+xml",
171 "application/vnd.oma.poc.detailed-progress-report+xml",
172 "application/vnd.oma.poc.final-report+xml",
173 "application/vnd.oma.poc.groups+xml",
174 "application/vnd.oma.poc.invocation-descriptor+xml",
175 "application/vnd.oma.poc.optimized-progress-report+xml",
176 "application/vnd.oma.scidm.messages+xml",
177 "application/vnd.oma.suppnot+xml", /*OMA-ERELD-Presence_SIMPLE-V2_0-20120710-A*/
178 "application/vnd.oma.xcap-directory+xml",
179 "application/vnd.omads-email+xml",
180 "application/vnd.omads-file+xml",
181 "application/vnd.omads-folder+xml",
182 "application/vnd.3gpp.access-transfer-events+xml",
183 "application/vnd.3gpp.bsf+xml",
184 "application/vnd.3gpp.comm-div-info+xml", /*3GPP TS 24.504 version 8.19.0*/
185 "application/vnd.3gpp.cw+xml",
186 "application/vnd.3gpp.iut+xml", /*3GPP TS 24.337*/
187 "application/vnc.3gpp.iut-config+xml", /*3GPP TS 24.337*/
188 "application/vnd.3gpp.mcptt-info+xml", /*3GPP TS 24.379 version 17.6.0*/
189 "application/vnd.3gpp.mcptt-mbms-usage-info+xml", /*3GPP TS 24.379 version 17.6.0*/
190 "application/vnd.3gpp.mcptt-location-info+xml", /*3GPP TS 24.379 version 17.6.0*/
191 "application/vnd.3gpp.mcptt-affiliation-command+xml", /*3GPP TS 24.379 version 17.6.0*/
192 "application/vnd.3gpp.mcptt-floor-request+xml", /*3GPP TS 24.379 version 17.6.0*/
193 "application/vnd.3gpp.mcptt-signed+xml", /*3GPP TS 24.379 version 17.6.0*/
194 "application/vnd.3gpp.mcptt-regroup+xml", /*3GPP TS 24.379 version 17.6.0*/
195 "application/vnd.3gpp.mcdata-info+xml", /*3GPP TS 24.282 version 17.6.2*/
196 "application/vnd.3gpp.mcdata-mbms-usage-info+xml", /*3GPP TS 24.282 version 17.6.2*/
197 "application/vnd.3gpp.mcdata-location-info+xml", /*3GPP TS 24.282 version 17.6.2*/
198 "application/vnd.3gpp.mcdata-affiliation-command+xml", /*3GPP TS 24.282 version 17.6.2*/
199 "application/vnd.3gpp.mcdata-regroup+xml", /*3GPP TS 24.282 version 17.6.2*/
200 "application/vnd.3gpp.mcvideo-info+xml", /*3GPP TS 24.281 version 17.6.0*/
201 "application/vnd.3gpp.mcvideo-mbms-usage-info+xml", /*3GPP TS 24.281 version 17.6.0*/
202 "application/vnd.3gpp.mcvideo-location-info+xml", /*3GPP TS 24.281 version 17.6.0*/
203 "application/vnd.3gpp.mcvideo-affiliation-command+xml",/*3GPP TS 24.281 version 17.6.0*/
204 "application/vnd.3gpp.transmission-request+xml", /*3GPP TS 24.281 version 17.6.0*/
205 "application/vnd.3gpp.mcptt-ue-init-config+xml", /*3GPP TS 24.484 version 17.5.0*/
206 "application/vnd.3gpp.mcptt-ue-config+xml", /*3GPP TS 24.484 version 17.5.0*/
207 "application/vnd.3gpp.mcptt-user-profile+xml", /*3GPP TS 24.484 version 17.5.0*/
208 "application/vnd.3gpp.mcptt-service-config+xml", /*3GPP TS 24.484 version 17.5.0*/
209 "application/vnd.3gpp.mcdata-service-config+xml", /*3GPP TS 24.484 version 17.5.0*/
210 "application/vnd.3gpp.mcvideo-service-config+xml", /*3GPP TS 24.484 version 17.5.0*/
211 "application/vnd.3gpp.mcvideo-ue-config+xml", /*3GPP TS 24.484 version 17.5.0*/
212 "application/vnd.3gpp.mcvideo-user-profile+xml", /*3GPP TS 24.484 version 17.5.0*/
213 "application/vnd.3gpp.mcdata-ue-config+xml", /*3GPP TS 24.484 version 17.5.0*/
214 "application/vnd.3gpp.mcdata-user-profile+xml", /*3GPP TS 24.484 version 17.5.0*/
215 "application/vnd.3gpp.mid-call+xml",
216 "application/vnd.3gpp-prose-pc3ch+xml",
217 "application/vnd.3gpp-prose+xml",
218 "application/vnd.3gpp.replication+xml", /*3GPP TS 24.337*/
219 "application/vnd.3gpp.sms+xml",
220 "application/vnd.3gpp.srvcc-info+xml",
221 "application/vnd.3gpp.srvcc-ext+xml",
222 "application/vnd.3gpp.state-and-event-info+xml",
223 "application/vnd.3gpp.ussd+xml",
224 "application/vnd.3gpp2.bcmcsinfo+xml",
225 "application/vnd.wv.csp+xml",
226 "application/vnd.wv.csp.xml",
227 "application/watcherinfo+xml",
228 "application/xcap-att+xml",
229 "application/xcap-caps+xml",
230 "application/xcap-diff+xml",
231 "application/xcap-el+xml",
232 "application/xcap-error+xml",
233 "application/xcap-ns+xml",
235 "application/xml-dtd",
236 "application/xpidf+xml",
237 "application/xslt+xml",
238 "application/x-crd+xml",
239 "application/x-wms-logconnectstats",
240 "application/x-wms-logplaystats",
241 "application/x-wms-sendevent",
243 "message/imdn+xml", /*RFC5438*/
246 static void insert_xml_frame(xml_frame_t
*parent
, xml_frame_t
*new_child
)
248 new_child
->first_child
= NULL
;
249 new_child
->last_child
= NULL
;
251 new_child
->parent
= parent
;
252 new_child
->next_sibling
= NULL
;
253 new_child
->prev_sibling
= NULL
;
254 if (parent
== NULL
) return; /* root */
256 if (parent
->first_child
== NULL
) { /* the 1st child */
257 parent
->first_child
= new_child
;
258 } else { /* following children */
259 parent
->last_child
->next_sibling
= new_child
;
260 new_child
->prev_sibling
= parent
->last_child
;
262 parent
->last_child
= new_child
;
265 /* Try to get the 'encoding' attribute from XML declaration, and convert it to
266 * Wireshark character encoding.
269 get_char_encoding(tvbuff_t
* tvb
, packet_info
* pinfo
, char** ret_encoding_name
) {
270 uint32_t iana_charset_id
;
271 unsigned ws_encoding_id
;
273 GMatchInfo
* match_info
;
274 const char* xmldecl
= (char*)tvb_get_string_enc(pinfo
->pool
, tvb
, 0,
275 MIN(100, tvb_captured_length(tvb
)), ENC_UTF_8
);
277 g_regex_match(encoding_pattern
, xmldecl
, 0, &match_info
);
278 if (g_match_info_matches(match_info
)) {
279 char* match_ret
= g_match_info_fetch(match_info
, 1);
280 encoding_str
= ascii_strup_inplace(wmem_strdup(pinfo
->pool
, match_ret
));
282 /* Get the iana charset enum number by the name of the charset. */
283 iana_charset_id
= str_to_val(encoding_str
,
284 VALUE_STRING_EXT_VS_P(&mibenum_vals_character_sets_ext
), IANA_CS_US_ASCII
);
286 /* Use default encoding preference if this xml does not contains 'encoding' attribute. */
287 iana_charset_id
= pref_default_encoding
;
288 encoding_str
= val_to_str_ext_wmem(pinfo
->pool
, iana_charset_id
,
289 &mibenum_vals_character_sets_ext
, "UNKNOWN");
291 g_match_info_free(match_info
);
293 ws_encoding_id
= mibenum_charset_to_encoding((unsigned)iana_charset_id
);
295 /* UTF-8 compatible with ASCII */
296 if (ws_encoding_id
== (ENC_NA
| ENC_ASCII
)) {
297 ws_encoding_id
= ENC_UTF_8
;
298 *ret_encoding_name
= wmem_strdup(pinfo
->pool
, "UTF-8");
300 *ret_encoding_name
= encoding_str
;
303 return ws_encoding_id
;
307 dissect_xml(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
310 static GPtrArray
*stack
;
311 xml_frame_t
*current_frame
;
312 const char *colinfo_str
;
317 g_ptr_array_free(stack
, true);
319 stack
= g_ptr_array_new();
320 current_frame
= wmem_new(wmem_packet_scope(), xml_frame_t
);
321 current_frame
->type
= XML_FRAME_ROOT
;
322 current_frame
->name
= NULL
;
323 current_frame
->name_orig_case
= NULL
;
324 current_frame
->value
= NULL
;
325 current_frame
->pinfo
= pinfo
;
326 insert_xml_frame(NULL
, current_frame
);
327 g_ptr_array_add(stack
, current_frame
);
329 /* Detect and act on possible byte-order mark (BOM) */
330 try_bom
= tvb_get_ntohs(tvb
, 0);
331 if (try_bom
== 0xFEFF) {
333 const uint8_t *data_str
= tvb_get_string_enc(pinfo
->pool
, tvb
, 0, tvb_captured_length(tvb
), ENC_UTF_16
|ENC_BIG_ENDIAN
);
334 size_t l
= strlen(data_str
);
335 decoded
= tvb_new_child_real_data(tvb
, data_str
, (unsigned)l
, (int)l
);
336 add_new_data_source(pinfo
, decoded
, "Decoded UTF-16BE text");
338 else if(try_bom
== 0xFFFE) {
339 /* UTF-16LE (or possibly UTF-32LE, but Wireshark doesn't support UTF-32) */
340 const uint8_t *data_str
= tvb_get_string_enc(pinfo
->pool
, tvb
, 0, tvb_captured_length(tvb
), ENC_UTF_16
|ENC_LITTLE_ENDIAN
);
341 size_t l
= strlen(data_str
);
342 decoded
= tvb_new_child_real_data(tvb
, data_str
, (unsigned)l
, (int)l
);
343 add_new_data_source(pinfo
, decoded
, "Decoded UTF-16LE text");
345 /* Could also test if try_bom is 0xnn00 or 0x00nn to guess endianness if we wanted */
347 /* Get character encoding according to XML declaration or preference. */
349 unsigned encoding
= get_char_encoding(tvb
, pinfo
, &encoding_name
);
351 /* Encoding string with encoding, either with or without BOM */
352 const uint8_t *data_str
= tvb_get_string_enc(pinfo
->pool
, tvb
, 0, tvb_captured_length(tvb
), encoding
);
353 size_t l
= strlen(data_str
);
354 decoded
= tvb_new_child_real_data(tvb
, data_str
, (unsigned)l
, (int)l
);
355 add_new_data_source(pinfo
, decoded
, wmem_strdup_printf(pinfo
->pool
, "Decoded %s text", encoding_name
));
358 tt
= tvbparse_init(pinfo
->pool
, decoded
, 0, -1, stack
, want_ignore
);
359 current_frame
->start_offset
= 0;
360 current_frame
->length
= tvb_captured_length(decoded
);
362 current_frame
->decryption_keys
= wmem_map_new(wmem_packet_scope(), g_str_hash
, g_str_equal
);
366 if (pinfo
->match_string
)
367 root_ns
= (xml_ns_t
*)wmem_map_lookup(media_types
, pinfo
->match_string
);
371 colinfo_str
= "/XML";
373 char *colinfo_str_buf
;
374 colinfo_str_buf
= wmem_strconcat(wmem_packet_scope(), "/", root_ns
->name
, NULL
);
375 ascii_strup_inplace(colinfo_str_buf
);
376 colinfo_str
= colinfo_str_buf
;
379 col_append_str(pinfo
->cinfo
, COL_PROTOCOL
, colinfo_str
);
381 current_frame
->ns
= root_ns
;
383 current_frame
->item
= proto_tree_add_item(tree
, current_frame
->ns
->hf_tag
, decoded
, 0, -1, ENC_UTF_8
|ENC_NA
);
384 current_frame
->tree
= proto_item_add_subtree(current_frame
->item
, current_frame
->ns
->ett
);
385 current_frame
->last_item
= current_frame
->item
;
387 while(tvbparse_get(tt
, want
)) ;
389 /* Save XML structure in case it is useful for the caller */
390 p_add_proto_data(pinfo
->pool
, pinfo
, xml_ns
.hf_tag
, 0, current_frame
);
392 return tvb_captured_length(tvb
);
395 static bool dissect_xml_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
397 if (tvbparse_peek(tvbparse_init(pinfo
->pool
, tvb
, 0, -1, NULL
, want_ignore
), want_heur
)) {
398 dissect_xml(tvb
, pinfo
, tree
, data
);
400 } else if (pref_heuristic_unicode
) {
401 const uint8_t *data_str
;
402 tvbuff_t
*unicode_tvb
;
404 /* XXX - UCS-2, or UTF-16? */
405 int enc
= ENC_UCS_2
|ENC_LITTLE_ENDIAN
;
408 try_bom
= tvb_get_ntohs(tvb
, 0);
409 if (try_bom
== 0xFEFF) {
410 enc
= ENC_UTF_16
|ENC_BIG_ENDIAN
;
412 else if(try_bom
== 0xFFFE) {
413 enc
= ENC_UTF_16
|ENC_LITTLE_ENDIAN
;
416 data_str
= tvb_get_string_enc(pinfo
->pool
, tvb
, 0, tvb_captured_length(tvb
), enc
);
417 l
= strlen(data_str
);
418 unicode_tvb
= tvb_new_child_real_data(tvb
, data_str
, (unsigned)l
, (int)l
);
419 if (tvbparse_peek(tvbparse_init(pinfo
->pool
, unicode_tvb
, 0, -1, NULL
, want_ignore
), want_heur
)) {
420 add_new_data_source(pinfo
, unicode_tvb
, "UTF8");
421 dissect_xml(unicode_tvb
, pinfo
, tree
, data
);
428 xml_frame_t
*xml_get_tag(xml_frame_t
*frame
, const char *name
)
430 xml_frame_t
*tag
= NULL
;
432 xml_frame_t
*xml_item
= frame
->first_child
;
434 if (xml_item
->type
== XML_FRAME_TAG
) {
435 if (!name
) { /* get the 1st tag */
438 } else if (xml_item
->name_orig_case
&& !strcmp(xml_item
->name_orig_case
, name
)) {
443 xml_item
= xml_item
->next_sibling
;
449 xml_frame_t
*xml_get_attrib(xml_frame_t
*frame
, const char *name
)
451 xml_frame_t
*attr
= NULL
;
453 xml_frame_t
*xml_item
= frame
->first_child
;
455 if ((xml_item
->type
== XML_FRAME_ATTRIB
) &&
456 xml_item
->name_orig_case
&& !strcmp(xml_item
->name_orig_case
, name
)) {
460 xml_item
= xml_item
->next_sibling
;
466 xml_frame_t
*xml_get_cdata(xml_frame_t
*frame
)
468 xml_frame_t
*cdata
= NULL
;
470 xml_frame_t
*xml_item
= frame
->first_child
;
472 if (xml_item
->type
== XML_FRAME_CDATA
) {
476 xml_item
= xml_item
->next_sibling
;
482 static void after_token(void *tvbparse_data
, const void *wanted_data _U_
, tvbparse_elem_t
*tok
)
484 GPtrArray
*stack
= (GPtrArray
*)tvbparse_data
;
485 xml_frame_t
*current_frame
= (xml_frame_t
*)g_ptr_array_index(stack
, stack
->len
- 1);
487 bool is_cdata
= false;
489 xml_frame_t
*new_frame
= NULL
;
492 if (tok
->id
== XML_CDATA
) {
493 hfid
= current_frame
->ns
? current_frame
->ns
->hf_cdata
: xml_ns
.hf_cdata
;
495 } else if ( tok
->id
> 0) {
498 hfid
= xml_ns
.hf_cdata
;
501 pi
= proto_tree_add_item(current_frame
->tree
, hfid
, tok
->tvb
, tok
->offset
, tok
->len
, ENC_UTF_8
|ENC_NA
);
503 text
= tvb_format_text(wmem_packet_scope(), tok
->tvb
, tok
->offset
, tok
->len
);
504 proto_item_set_text(pi
, "%s", text
);
507 new_frame
= wmem_new(wmem_packet_scope(), xml_frame_t
);
508 new_frame
->type
= XML_FRAME_CDATA
;
509 new_frame
->name
= NULL
;
510 new_frame
->name_orig_case
= NULL
;
511 new_frame
->value
= tvb_new_subset_length(tok
->tvb
, tok
->offset
, tok
->len
);
512 insert_xml_frame(current_frame
, new_frame
);
513 new_frame
->item
= pi
;
514 new_frame
->last_item
= pi
;
515 new_frame
->tree
= NULL
;
516 new_frame
->start_offset
= tok
->offset
;
517 new_frame
->length
= tok
->len
;
518 new_frame
->ns
= NULL
;
519 new_frame
->pinfo
= current_frame
->pinfo
;
522 if (new_frame
!= NULL
&&
523 current_frame
!= NULL
&&
524 current_frame
->name_orig_case
!= NULL
&&
525 strcmp(current_frame
->name_orig_case
, "BinarySecurityToken") == 0)
527 xml_frame_t
*value_type
= NULL
;
529 value_type
= xml_get_attrib(current_frame
, "ValueType");
530 if (value_type
!= NULL
) {
531 const char *s
= "http://docs.oasis-open.org/wss/oasis-wss-kerberos-token-profile-1.1#GSS_Kerberosv5_AP_REQ";
532 size_t l
= strlen(s
);
534 c
= tvb_strneql(value_type
->value
, 0, s
, l
);
536 tvbuff_t
*ssp_tvb
= base64_to_tvb(new_frame
->value
, text
);
537 add_new_data_source(current_frame
->pinfo
, ssp_tvb
, "GSSAPI Data");
538 call_dissector(gssapi_handle
, ssp_tvb
,
539 current_frame
->pinfo
, current_frame
->tree
);
545 static void before_xmpli(void *tvbparse_data
, const void *wanted_data _U_
, tvbparse_elem_t
*tok
)
547 GPtrArray
*stack
= (GPtrArray
*)tvbparse_data
;
548 xml_frame_t
*current_frame
= (xml_frame_t
*)g_ptr_array_index(stack
, stack
->len
- 1);
551 tvbparse_elem_t
*name_tok
= tok
->sub
->next
;
552 char *name
= tvb_get_string_enc(wmem_packet_scope(), name_tok
->tvb
, name_tok
->offset
, name_tok
->len
, ENC_ASCII
);
553 xml_ns_t
*ns
= (xml_ns_t
*)wmem_map_lookup(xmpli_names
, name
);
554 xml_frame_t
*new_frame
;
559 ascii_strdown_inplace(name
);
568 pi
= proto_tree_add_item(current_frame
->tree
, hf_tag
, tok
->tvb
, tok
->offset
, tok
->len
, ENC_UTF_8
|ENC_NA
);
570 proto_item_set_text(pi
, "%s", tvb_format_text(wmem_packet_scope(), tok
->tvb
, tok
->offset
, (name_tok
->offset
- tok
->offset
) + name_tok
->len
));
572 pt
= proto_item_add_subtree(pi
, ett
);
574 new_frame
= wmem_new(wmem_packet_scope(), xml_frame_t
);
575 new_frame
->type
= XML_FRAME_XMPLI
;
576 new_frame
->name
= name
;
577 new_frame
->name_orig_case
= name
;
578 new_frame
->value
= NULL
;
579 insert_xml_frame(current_frame
, new_frame
);
580 new_frame
->item
= pi
;
581 new_frame
->last_item
= pi
;
582 new_frame
->tree
= pt
;
583 new_frame
->start_offset
= tok
->offset
;
584 new_frame
->length
= tok
->len
;
586 new_frame
->pinfo
= current_frame
->pinfo
;
588 g_ptr_array_add(stack
, new_frame
);
592 static void after_xmlpi(void *tvbparse_data
, const void *wanted_data _U_
, tvbparse_elem_t
*tok
)
594 GPtrArray
*stack
= (GPtrArray
*)tvbparse_data
;
595 xml_frame_t
*current_frame
= (xml_frame_t
*)g_ptr_array_index(stack
, stack
->len
- 1);
597 proto_tree_add_format_text(current_frame
->tree
, tok
->tvb
, tok
->offset
, tok
->len
);
599 if (stack
->len
> 1) {
600 g_ptr_array_remove_index_fast(stack
, stack
->len
- 1);
602 proto_tree_add_expert(current_frame
->tree
, current_frame
->pinfo
, &ei_xml_closing_unopened_xmpli_tag
,
603 tok
->tvb
, tok
->offset
, tok
->len
);
607 static void before_tag(void *tvbparse_data
, const void *wanted_data _U_
, tvbparse_elem_t
*tok
)
609 GPtrArray
*stack
= (GPtrArray
*)tvbparse_data
;
610 xml_frame_t
*current_frame
= (xml_frame_t
*)g_ptr_array_index(stack
, stack
->len
- 1);
611 tvbparse_elem_t
*name_tok
= tok
->sub
->next
;
613 char *name
= NULL
, *name_orig_case
= NULL
;
615 xml_frame_t
*new_frame
;
619 if (name_tok
->sub
->id
== XML_SCOPED_NAME
) {
620 tvbparse_elem_t
*root_tok
= name_tok
->sub
->sub
;
621 tvbparse_elem_t
*leaf_tok
= name_tok
->sub
->sub
->next
->next
;
622 xml_ns_t
*nameroot_ns
;
624 root_name
= (char *)tvb_get_string_enc(wmem_packet_scope(), root_tok
->tvb
, root_tok
->offset
, root_tok
->len
, ENC_ASCII
);
625 name
= (char *)tvb_get_string_enc(wmem_packet_scope(), leaf_tok
->tvb
, leaf_tok
->offset
, leaf_tok
->len
, ENC_ASCII
);
626 name_orig_case
= name
;
628 nameroot_ns
= (xml_ns_t
*)wmem_map_lookup(xml_ns
.elements
, root_name
);
631 ns
= (xml_ns_t
*)wmem_map_lookup(nameroot_ns
->elements
, name
);
640 name
= tvb_get_string_enc(wmem_packet_scope(), name_tok
->tvb
, name_tok
->offset
, name_tok
->len
, ENC_ASCII
);
641 name_orig_case
= wmem_strdup(wmem_packet_scope(), name
);
642 ascii_strdown_inplace(name
);
644 if(current_frame
->ns
) {
645 ns
= (xml_ns_t
*)wmem_map_lookup(current_frame
->ns
->elements
, name
);
648 if (! ( ns
= (xml_ns_t
*)wmem_map_lookup(root_ns
->elements
, name
) ) ) {
657 pi
= proto_tree_add_item(current_frame
->tree
, ns
->hf_tag
, tok
->tvb
, tok
->offset
, tok
->len
, ENC_UTF_8
|ENC_NA
);
658 proto_item_set_text(pi
, "%s", tvb_format_text(wmem_packet_scope(), tok
->tvb
,
660 (name_tok
->offset
- tok
->offset
) + name_tok
->len
));
662 pt
= proto_item_add_subtree(pi
, ns
->ett
);
664 new_frame
= wmem_new(wmem_packet_scope(), xml_frame_t
);
665 new_frame
->type
= XML_FRAME_TAG
;
666 new_frame
->name
= name
;
667 new_frame
->name_orig_case
= name_orig_case
;
668 new_frame
->value
= NULL
;
669 insert_xml_frame(current_frame
, new_frame
);
670 new_frame
->item
= pi
;
671 new_frame
->last_item
= pi
;
672 new_frame
->tree
= pt
;
673 new_frame
->start_offset
= tok
->offset
;
674 new_frame
->length
= tok
->len
;
676 new_frame
->pinfo
= current_frame
->pinfo
;
678 g_ptr_array_add(stack
, new_frame
);
682 static void after_open_tag(void *tvbparse_data
, const void *wanted_data _U_
, tvbparse_elem_t
*tok _U_
)
684 GPtrArray
*stack
= (GPtrArray
*)tvbparse_data
;
685 xml_frame_t
*current_frame
= (xml_frame_t
*)g_ptr_array_index(stack
, stack
->len
- 1);
687 proto_item_append_text(current_frame
->last_item
, ">");
690 static void after_closed_tag(void *tvbparse_data
, const void *wanted_data _U_
, tvbparse_elem_t
*tok
)
692 GPtrArray
*stack
= (GPtrArray
*)tvbparse_data
;
693 xml_frame_t
*current_frame
= (xml_frame_t
*)g_ptr_array_index(stack
, stack
->len
- 1);
695 proto_item_append_text(current_frame
->last_item
, "/>");
697 if (stack
->len
> 1) {
698 g_ptr_array_remove_index_fast(stack
, stack
->len
- 1);
700 proto_tree_add_expert(current_frame
->tree
, current_frame
->pinfo
, &ei_xml_closing_unopened_tag
,
701 tok
->tvb
, tok
->offset
, tok
->len
);
706 struct decryption_key
{
709 uint8_t key
[HASH_SHA1_LENGTH
];
712 static void P_SHA1(const uint8_t *Secret
, size_t Secret_len
,
713 const uint8_t *Seed
, size_t Seed_len
,
714 uint8_t Result
[HASH_SHA1_LENGTH
])
716 gcry_md_hd_t hd
= NULL
;
717 uint8_t *digest
= NULL
;
720 * 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
722 gcry_md_open(&hd
, GCRY_MD_SHA1
, GCRY_MD_FLAG_HMAC
);
723 gcry_md_setkey(hd
, Secret
, Secret_len
);
724 gcry_md_write(hd
, Seed
, Seed_len
);
725 digest
= gcry_md_read(hd
, GCRY_MD_SHA1
);
726 memcpy(Result
, digest
, HASH_SHA1_LENGTH
);
730 #endif /* HAVE_KERBEROS */
732 static void after_untag(void *tvbparse_data
, const void *wanted_data _U_
, tvbparse_elem_t
*tok
)
734 GPtrArray
*stack
= (GPtrArray
*)tvbparse_data
;
735 xml_frame_t
*current_frame
= (xml_frame_t
*)g_ptr_array_index(stack
, stack
->len
- 1);
737 xml_frame_t
*top_frame
= (xml_frame_t
*)g_ptr_array_index(stack
, 0);
738 #endif /* HAVE_KERBEROS */
740 proto_item_set_len(current_frame
->item
, (tok
->offset
- current_frame
->start_offset
) + tok
->len
);
741 current_frame
->length
= (tok
->offset
- current_frame
->start_offset
) + tok
->len
;
743 proto_tree_add_format_text(current_frame
->tree
, tok
->tvb
, tok
->offset
, tok
->len
);
745 if (stack
->len
> 1) {
746 g_ptr_array_remove_index_fast(stack
, stack
->len
- 1);
748 proto_tree_add_expert(current_frame
->tree
, current_frame
->pinfo
, &ei_xml_closing_unopened_tag
,
749 tok
->tvb
, tok
->offset
, tok
->len
);
753 if (current_frame
->name_orig_case
== NULL
) {
757 if (strcmp(current_frame
->name_orig_case
, "DerivedKeyToken") == 0) {
758 xml_frame_t
*id_frame
= xml_get_attrib(current_frame
, "u:Id");
759 xml_frame_t
*nonce_frame
= xml_get_tag(current_frame
, "Nonce");
760 xml_frame_t
*nonce_cdata
= NULL
;
761 tvbuff_t
*nonce_tvb
= NULL
;
762 enc_key_t
*ek
= NULL
;
764 size_t seed_length
= 16; // TODO
765 const size_t key_length
= 16; //TODO
767 if (id_frame
!= NULL
&& nonce_frame
!= NULL
) {
768 nonce_cdata
= xml_get_cdata(nonce_frame
);
770 if (nonce_cdata
!= NULL
) {
771 char *text
= tvb_format_text(wmem_packet_scope(), nonce_cdata
->value
, 0,
772 tvb_reported_length(nonce_cdata
->value
));
773 nonce_tvb
= base64_to_tvb(nonce_cdata
->value
, text
);
775 if (nonce_tvb
!= NULL
) {
776 seed_length
= tvb_reported_length(nonce_tvb
);
777 seed_length
= MIN(seed_length
, sizeof(seed
));
778 tvb_memcpy(nonce_tvb
, seed
, 0, seed_length
);
781 read_keytab_file_from_preferences();
784 for (ek
=enc_key_list
;ek
;ek
=ek
->next
) {
785 if (ek
->fd_num
== (int)current_frame
->pinfo
->num
) {
791 struct decryption_key
*key
;
794 id_str
= tvb_format_text(wmem_packet_scope(),
796 tvb_reported_length(id_frame
->value
));
798 key
= wmem_new0(wmem_packet_scope(), struct decryption_key
);
799 key
->id
= wmem_strdup_printf(wmem_packet_scope(), "#%s", id_str
);
800 P_SHA1(ek
->keyvalue
, ek
->keylength
, seed
, seed_length
, key
->key
);
801 key
->key_length
= key_length
;
803 wmem_map_insert(top_frame
->decryption_keys
, key
->id
, key
);
806 if (strcmp(current_frame
->name_orig_case
, "CipherValue") == 0) {
807 xml_frame_t
*encrypted_frame
= current_frame
->parent
->parent
;
808 xml_frame_t
*key_info_frame
= NULL
;
809 xml_frame_t
*token_frame
= NULL
;
810 xml_frame_t
*reference_frame
= NULL
;
811 xml_frame_t
*uri_frame
= NULL
;
812 const struct decryption_key
*key
= NULL
;
813 xml_frame_t
*cdata_frame
= NULL
;
814 tvbuff_t
*crypt_tvb
= NULL
;
815 tvbuff_t
*plain_tvb
= NULL
;
817 key_info_frame
= xml_get_tag(encrypted_frame
, "KeyInfo");
818 if (key_info_frame
!= NULL
) {
819 token_frame
= xml_get_tag(key_info_frame
, "SecurityTokenReference");
821 if (token_frame
!= NULL
) {
822 reference_frame
= xml_get_tag(token_frame
, "Reference");
824 if (reference_frame
!= NULL
) {
825 uri_frame
= xml_get_attrib(reference_frame
, "URI");
828 if (uri_frame
!= NULL
) {
829 char *key_id
= tvb_format_text(wmem_packet_scope(), uri_frame
->value
, 0,
830 tvb_reported_length(uri_frame
->value
));
832 key
= (const struct decryption_key
*)wmem_map_lookup(top_frame
->decryption_keys
, key_id
);
835 cdata_frame
= xml_get_cdata(current_frame
);
837 if (cdata_frame
!= NULL
) {
838 char *text
= tvb_format_text(wmem_packet_scope(), cdata_frame
->value
, 0,
839 tvb_reported_length(cdata_frame
->value
));
840 crypt_tvb
= base64_to_tvb(cdata_frame
->value
, text
);
842 if (crypt_tvb
!= NULL
) {
843 gcry_cipher_hd_t cipher_hd
= NULL
;
844 uint8_t *data
= NULL
;
845 unsigned data_length
= tvb_reported_length(crypt_tvb
);
847 data
= (uint8_t *)tvb_memdup(wmem_packet_scope(),
848 crypt_tvb
, 0, data_length
);
850 /* Open the cipher. */
851 gcry_cipher_open(&cipher_hd
, GCRY_CIPHER_AES128
, GCRY_CIPHER_MODE_CBC
, 0);
853 gcry_cipher_setkey(cipher_hd
, key
->key
, key
->key_length
);
854 gcry_cipher_encrypt(cipher_hd
, data
, data_length
, NULL
, 0);
855 gcry_cipher_close(cipher_hd
);
857 plain_tvb
= tvb_new_child_real_data(crypt_tvb
, data
,
858 data_length
, data_length
);
859 add_new_data_source(current_frame
->pinfo
, plain_tvb
, "Decrypted Data");
862 #endif /* HAVE_KERBEROS */
865 static void before_dtd_doctype(void *tvbparse_data
, const void *wanted_data _U_
, tvbparse_elem_t
*tok
)
867 GPtrArray
*stack
= (GPtrArray
*)tvbparse_data
;
868 xml_frame_t
*current_frame
= (xml_frame_t
*)g_ptr_array_index(stack
, stack
->len
- 1);
869 xml_frame_t
*new_frame
;
870 tvbparse_elem_t
*name_tok
= tok
->sub
->next
->next
->next
->sub
->sub
;
871 proto_tree
*dtd_item
= proto_tree_add_item(current_frame
->tree
, hf_doctype
,
872 name_tok
->tvb
, name_tok
->offset
,
873 name_tok
->len
, ENC_ASCII
);
875 proto_item_set_text(dtd_item
, "%s", tvb_format_text(wmem_packet_scope(), tok
->tvb
, tok
->offset
, tok
->len
));
877 new_frame
= wmem_new(wmem_packet_scope(), xml_frame_t
);
878 new_frame
->type
= XML_FRAME_DTD_DOCTYPE
;
879 new_frame
->name
= (char *)tvb_get_string_enc(wmem_packet_scope(), name_tok
->tvb
,
881 name_tok
->len
, ENC_ASCII
);
882 new_frame
->name_orig_case
= new_frame
->name
;
883 new_frame
->value
= NULL
;
884 insert_xml_frame(current_frame
, new_frame
);
885 new_frame
->item
= dtd_item
;
886 new_frame
->last_item
= dtd_item
;
887 new_frame
->tree
= proto_item_add_subtree(dtd_item
, ett_dtd
);
888 new_frame
->start_offset
= tok
->offset
;
889 new_frame
->length
= tok
->len
;
890 new_frame
->ns
= NULL
;
891 new_frame
->pinfo
= current_frame
->pinfo
;
893 g_ptr_array_add(stack
, new_frame
);
896 static void pop_stack(void *tvbparse_data
, const void *wanted_data _U_
, tvbparse_elem_t
*tok _U_
)
898 GPtrArray
*stack
= (GPtrArray
*)tvbparse_data
;
899 xml_frame_t
*current_frame
= (xml_frame_t
*)g_ptr_array_index(stack
, stack
->len
- 1);
901 if (stack
->len
> 1) {
902 g_ptr_array_remove_index_fast(stack
, stack
->len
- 1);
904 proto_tree_add_expert(current_frame
->tree
, current_frame
->pinfo
, &ei_xml_closing_unopened_tag
,
905 tok
->tvb
, tok
->offset
, tok
->len
);
909 static void after_dtd_close(void *tvbparse_data
, const void *wanted_data _U_
, tvbparse_elem_t
*tok
)
911 GPtrArray
*stack
= (GPtrArray
*)tvbparse_data
;
912 xml_frame_t
*current_frame
= (xml_frame_t
*)g_ptr_array_index(stack
, stack
->len
- 1);
914 proto_tree_add_format_text(current_frame
->tree
, tok
->tvb
, tok
->offset
, tok
->len
);
915 if (stack
->len
> 1) {
916 g_ptr_array_remove_index_fast(stack
, stack
->len
- 1);
918 proto_tree_add_expert(current_frame
->tree
, current_frame
->pinfo
, &ei_xml_closing_unopened_tag
,
919 tok
->tvb
, tok
->offset
, tok
->len
);
923 static void get_attrib_value(void *tvbparse_data _U_
, const void *wanted_data _U_
, tvbparse_elem_t
*tok
)
925 tok
->data
= tok
->sub
;
928 static void after_attrib(void *tvbparse_data
, const void *wanted_data _U_
, tvbparse_elem_t
*tok
)
930 GPtrArray
*stack
= (GPtrArray
*)tvbparse_data
;
931 xml_frame_t
*current_frame
= (xml_frame_t
*)g_ptr_array_index(stack
, stack
->len
- 1);
932 char *name
, *name_orig_case
;
933 tvbparse_elem_t
*value
;
934 tvbparse_elem_t
*value_part
= (tvbparse_elem_t
*)tok
->sub
->next
->next
->data
;
938 xml_frame_t
*new_frame
;
940 name
= tvb_get_string_enc(wmem_packet_scope(), tok
->sub
->tvb
, tok
->sub
->offset
, tok
->sub
->len
, ENC_ASCII
);
941 name_orig_case
= wmem_strdup(wmem_packet_scope(), name
);
942 ascii_strdown_inplace(name
);
944 if(current_frame
->ns
&& (hfidp
= (int *)wmem_map_lookup(current_frame
->ns
->attributes
, name
) )) {
948 hfid
= hf_unknowwn_attrib
;
952 pi
= proto_tree_add_item(current_frame
->tree
, hfid
, value
->tvb
, value
->offset
, value
->len
, ENC_UTF_8
|ENC_NA
);
953 proto_item_set_text(pi
, "%s", tvb_format_text(wmem_packet_scope(), tok
->tvb
, tok
->offset
, tok
->len
));
955 current_frame
->last_item
= pi
;
957 new_frame
= wmem_new(wmem_packet_scope(), xml_frame_t
);
958 new_frame
->type
= XML_FRAME_ATTRIB
;
959 new_frame
->name
= name
;
960 new_frame
->name_orig_case
= name_orig_case
;
961 new_frame
->value
= tvb_new_subset_length(value_part
->tvb
, value_part
->offset
,
963 insert_xml_frame(current_frame
, new_frame
);
964 new_frame
->item
= pi
;
965 new_frame
->last_item
= pi
;
966 new_frame
->tree
= NULL
;
967 new_frame
->start_offset
= tok
->offset
;
968 new_frame
->length
= tok
->len
;
969 new_frame
->ns
= NULL
;
970 new_frame
->pinfo
= current_frame
->pinfo
;
974 static void unrecognized_token(void *tvbparse_data
, const void *wanted_data _U_
, tvbparse_elem_t
*tok _U_
)
976 GPtrArray
*stack
= (GPtrArray
*)tvbparse_data
;
977 xml_frame_t
*current_frame
= (xml_frame_t
*)g_ptr_array_index(stack
, stack
->len
- 1);
979 proto_tree_add_expert(current_frame
->tree
, current_frame
->pinfo
, &ei_xml_unrecognized_text
,
980 tok
->tvb
, tok
->offset
, tok
->len
);
986 static void init_xml_parser(void)
988 tvbparse_wanted_t
*want_name
=
989 tvbparse_chars(-1, 1, 0,
990 "abcdefghijklmnopqrstuvwxyz.-_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",
992 tvbparse_wanted_t
*want_attr_name
=
993 tvbparse_chars(-1, 1, 0,
994 "abcdefghijklmnopqrstuvwxyz.-_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789:",
997 tvbparse_wanted_t
*want_scoped_name
= tvbparse_set_seq(XML_SCOPED_NAME
, NULL
, NULL
, NULL
,
999 tvbparse_char(-1, ":", NULL
, NULL
, NULL
),
1003 tvbparse_wanted_t
*want_tag_name
= tvbparse_set_oneof(0, NULL
, NULL
, NULL
,
1008 tvbparse_wanted_t
*want_attrib_value
= tvbparse_set_oneof(0, NULL
, NULL
, get_attrib_value
,
1009 tvbparse_quoted(-1, NULL
, NULL
, tvbparse_shrink_token_cb
, '\"', '\\'),
1010 tvbparse_quoted(-1, NULL
, NULL
, tvbparse_shrink_token_cb
, '\'', '\\'),
1011 tvbparse_chars(-1, 1, 0, "0123456789", NULL
, NULL
, NULL
),
1015 tvbparse_wanted_t
*want_attributes
= tvbparse_one_or_more(-1, NULL
, NULL
, NULL
,
1016 tvbparse_set_seq(-1, NULL
, NULL
, after_attrib
,
1018 tvbparse_char(-1, "=", NULL
, NULL
, NULL
),
1022 tvbparse_wanted_t
*want_stoptag
= tvbparse_set_oneof(-1, NULL
, NULL
, NULL
,
1023 tvbparse_char(-1, ">", NULL
, NULL
, after_open_tag
),
1024 tvbparse_string(-1, "/>", NULL
, NULL
, after_closed_tag
),
1027 tvbparse_wanted_t
*want_stopxmlpi
= tvbparse_string(-1, "?>", NULL
, NULL
, after_xmlpi
);
1029 tvbparse_wanted_t
*want_comment
= tvbparse_set_seq(hf_comment
, NULL
, NULL
, after_token
,
1030 tvbparse_string(-1, "<!--", NULL
, NULL
, NULL
),
1031 tvbparse_until(-1, NULL
, NULL
, NULL
,
1032 tvbparse_string(-1, "-->", NULL
, NULL
, NULL
),
1036 tvbparse_wanted_t
*want_cdatasection
= tvbparse_set_seq(hf_cdatasection
, NULL
, NULL
, after_token
,
1037 tvbparse_string(-1, "<![CDATA[", NULL
, NULL
, NULL
),
1038 tvbparse_until(-1, NULL
, NULL
, NULL
,
1039 tvbparse_string(-1, "]]>", NULL
, NULL
, NULL
),
1043 tvbparse_wanted_t
*want_xmlpi
= tvbparse_set_seq(hf_xmlpi
, NULL
, before_xmpli
, NULL
,
1044 tvbparse_string(-1, "<?", NULL
, NULL
, NULL
),
1046 tvbparse_set_oneof(-1, NULL
, NULL
, NULL
,
1048 tvbparse_set_seq(-1, NULL
, NULL
, NULL
,
1055 tvbparse_wanted_t
*want_closing_tag
= tvbparse_set_seq(0, NULL
, NULL
, after_untag
,
1056 tvbparse_char(-1, "<", NULL
, NULL
, NULL
),
1057 tvbparse_char(-1, "/", NULL
, NULL
, NULL
),
1059 tvbparse_char(-1, ">", NULL
, NULL
, NULL
),
1062 tvbparse_wanted_t
*want_doctype_start
= tvbparse_set_seq(-1, NULL
, before_dtd_doctype
, NULL
,
1063 tvbparse_char(-1, "<", NULL
, NULL
, NULL
),
1064 tvbparse_char(-1, "!", NULL
, NULL
, NULL
),
1065 tvbparse_casestring(-1, "DOCTYPE", NULL
, NULL
, NULL
),
1066 tvbparse_set_oneof(-1, NULL
, NULL
, NULL
,
1067 tvbparse_set_seq(-1, NULL
, NULL
, NULL
,
1069 tvbparse_char(-1, "[", NULL
, NULL
, NULL
),
1071 tvbparse_set_seq(-1, NULL
, NULL
, pop_stack
,
1073 tvbparse_set_oneof(-1, NULL
, NULL
, NULL
,
1074 tvbparse_casestring(-1, "PUBLIC", NULL
, NULL
, NULL
),
1075 tvbparse_casestring(-1, "SYSTEM", NULL
, NULL
, NULL
),
1077 tvbparse_until(-1, NULL
, NULL
, NULL
,
1078 tvbparse_char(-1, ">", NULL
, NULL
, NULL
),
1084 tvbparse_wanted_t
*want_dtd_tag
= tvbparse_set_seq(hf_dtd_tag
, NULL
, NULL
, after_token
,
1085 tvbparse_char(-1, "<", NULL
, NULL
, NULL
),
1086 tvbparse_char(-1, "!", NULL
, NULL
, NULL
),
1087 tvbparse_until(-1, NULL
, NULL
, NULL
,
1088 tvbparse_char(-1, ">", NULL
, NULL
, NULL
),
1092 tvbparse_wanted_t
*want_tag
= tvbparse_set_seq(-1, NULL
, before_tag
, NULL
,
1093 tvbparse_char(-1, "<", NULL
, NULL
, NULL
),
1095 tvbparse_set_oneof(-1, NULL
, NULL
, NULL
,
1096 tvbparse_set_seq(-1, NULL
, NULL
, NULL
,
1104 tvbparse_wanted_t
*want_dtd_close
= tvbparse_set_seq(-1, NULL
, NULL
, after_dtd_close
,
1105 tvbparse_char(-1, "]", NULL
, NULL
, NULL
),
1106 tvbparse_char(-1, ">", NULL
, NULL
, NULL
),
1109 want_ignore
= tvbparse_chars(-1, 1, 0, " \t\r\n", NULL
, NULL
, NULL
);
1112 want
= tvbparse_set_oneof(-1, NULL
, NULL
, NULL
,
1121 tvbparse_not_chars(XML_CDATA
, 1, 0, "<", NULL
, NULL
, after_token
),
1122 tvbparse_not_chars(-1, 1, 0, " \t\r\n", NULL
, NULL
, unrecognized_token
),
1125 want_heur
= tvbparse_set_oneof(-1, NULL
, NULL
, NULL
,
1137 static xml_ns_t
*xml_new_namespace(wmem_map_t
*hash
, const char *name
, ...)
1139 xml_ns_t
*ns
= wmem_new(wmem_epan_scope(), xml_ns_t
);
1143 ns
->name
= wmem_strdup(wmem_epan_scope(), name
);
1147 ns
->attributes
= wmem_map_new(wmem_epan_scope(), g_str_hash
, g_str_equal
);
1148 ns
->elements
= NULL
;
1152 while(( attr_name
= va_arg(ap
, char *) )) {
1153 int *hfp
= wmem_new(wmem_epan_scope(), int);
1155 wmem_map_insert(ns
->attributes
, wmem_strdup(wmem_epan_scope(), attr_name
), hfp
);
1160 wmem_map_insert(hash
, ns
->name
, ns
);
1166 static void add_xml_field(wmem_array_t
*hfs
, int *p_id
, const char *name
, const char *fqn
)
1168 hf_register_info hfri
;
1171 hfri
.hfinfo
.name
= name
;
1172 hfri
.hfinfo
.abbrev
= fqn
;
1173 hfri
.hfinfo
.type
= FT_STRING
;
1174 hfri
.hfinfo
.display
= BASE_NONE
;
1175 hfri
.hfinfo
.strings
= NULL
;
1176 hfri
.hfinfo
.bitmask
= 0x0;
1177 hfri
.hfinfo
.blurb
= NULL
;
1180 wmem_array_append_one(hfs
, hfri
);
1183 static void add_xml_attribute_names(void *k
, void *v
, void *p
)
1185 struct _attr_reg_data
*d
= (struct _attr_reg_data
*)p
;
1186 const char *basename
= wmem_strconcat(wmem_epan_scope(), d
->basename
, ".", (char *)k
, NULL
);
1188 add_xml_field(d
->hf
, (int*) v
, (char *)k
, basename
);
1192 static void add_xmlpi_namespace(void *k _U_
, void *v
, void *p
)
1194 xml_ns_t
*ns
= (xml_ns_t
*)v
;
1195 const char *basename
= wmem_strconcat(wmem_epan_scope(), (char *)p
, ".", ns
->name
, NULL
);
1196 int *ett_p
= &(ns
->ett
);
1197 struct _attr_reg_data d
;
1199 add_xml_field(hf_arr
, &(ns
->hf_tag
), basename
, basename
);
1201 g_array_append_val(ett_arr
, ett_p
);
1203 d
.basename
= basename
;
1206 wmem_map_foreach(ns
->attributes
, add_xml_attribute_names
, &d
);
1210 static void destroy_dtd_data(dtd_build_data_t
*dtd_data
)
1212 g_free(dtd_data
->proto_name
);
1213 g_free(dtd_data
->media_type
);
1214 g_free(dtd_data
->description
);
1215 g_free(dtd_data
->proto_root
);
1217 g_string_free(dtd_data
->error
, true);
1219 while(dtd_data
->elements
->len
) {
1220 dtd_named_list_t
*nl
= (dtd_named_list_t
*)g_ptr_array_remove_index_fast(dtd_data
->elements
, 0);
1221 g_ptr_array_free(nl
->list
, true);
1226 g_ptr_array_free(dtd_data
->elements
, true);
1228 while(dtd_data
->attributes
->len
) {
1229 dtd_named_list_t
*nl
= (dtd_named_list_t
*)g_ptr_array_remove_index_fast(dtd_data
->attributes
, 0);
1230 g_ptr_array_free(nl
->list
, true);
1235 g_ptr_array_free(dtd_data
->attributes
, true);
1240 static void copy_attrib_item(void *k
, void *v _U_
, void *p
)
1242 char *key
= (char *)wmem_strdup(wmem_epan_scope(), (const char *)k
);
1243 int *value
= wmem_new(wmem_epan_scope(), int);
1244 wmem_map_t
*dst
= (wmem_map_t
*)p
;
1247 wmem_map_insert(dst
, key
, value
);
1251 static wmem_map_t
*copy_attributes_hash(wmem_map_t
*src
)
1253 wmem_map_t
*dst
= wmem_map_new(wmem_epan_scope(), g_str_hash
, g_str_equal
);
1255 wmem_map_foreach(src
, copy_attrib_item
, dst
);
1260 static xml_ns_t
*duplicate_element(xml_ns_t
*orig
)
1262 xml_ns_t
*new_item
= wmem_new(wmem_epan_scope(), xml_ns_t
);
1265 new_item
->name
= wmem_strdup(wmem_epan_scope(), orig
->name
);
1266 new_item
->hf_tag
= -1;
1267 new_item
->hf_cdata
= -1;
1269 new_item
->attributes
= copy_attributes_hash(orig
->attributes
);
1270 new_item
->elements
= wmem_map_new(wmem_epan_scope(), g_str_hash
, g_str_equal
);
1271 new_item
->element_names
= g_ptr_array_new();
1273 for(i
=0; i
< orig
->element_names
->len
; i
++) {
1274 g_ptr_array_add(new_item
->element_names
,
1275 g_ptr_array_index(orig
->element_names
, i
));
1281 static char *fully_qualified_name(GPtrArray
*hier
, char *name
, char *proto_name
)
1284 wmem_strbuf_t
*s
= wmem_strbuf_new(wmem_epan_scope(), proto_name
);
1286 wmem_strbuf_append(s
, ".");
1288 for (i
= 1; i
< hier
->len
; i
++) {
1289 wmem_strbuf_append_printf(s
, "%s.", (char *)g_ptr_array_index(hier
, i
));
1292 wmem_strbuf_append(s
, name
);
1294 return wmem_strbuf_finalize(s
);
1298 // NOLINTNEXTLINE(misc-no-recursion)
1299 static xml_ns_t
*make_xml_hier(char *elem_name
,
1301 wmem_map_t
*elements
,
1312 bool recurred
= false;
1314 struct _attr_reg_data d
;
1316 if ( g_str_equal(elem_name
, root
->name
) ) {
1320 if (! ( orig
= (xml_ns_t
*)wmem_map_lookup(elements
, elem_name
) )) {
1321 g_string_append_printf(error
, "element '%s' is not defined\n", elem_name
);
1325 if (hier
->len
>= prefs
.gui_max_tree_depth
) {
1326 g_string_append_printf(error
, "hierarchy too deep: %u\n", hier
->len
);
1330 for (i
= 0; i
< hier
->len
; i
++) {
1331 if( (elem_name
) && (strcmp(elem_name
, (char *) g_ptr_array_index(hier
, i
) ) == 0 )) {
1340 fqn
= fully_qualified_name(hier
, elem_name
, proto_name
);
1342 fresh
= duplicate_element(orig
);
1345 add_xml_field(hfs
, &(fresh
->hf_tag
), wmem_strdup(wmem_epan_scope(), elem_name
), fqn
);
1346 add_xml_field(hfs
, &(fresh
->hf_cdata
), wmem_strdup(wmem_epan_scope(), elem_name
), fqn
);
1348 ett_p
= &fresh
->ett
;
1349 g_array_append_val(etts
, ett_p
);
1354 wmem_map_foreach(fresh
->attributes
, add_xml_attribute_names
, &d
);
1356 while(fresh
->element_names
->len
) {
1357 char *child_name
= (char *)g_ptr_array_remove_index(fresh
->element_names
, 0);
1358 xml_ns_t
*child_element
= NULL
;
1360 g_ptr_array_add(hier
, elem_name
);
1361 child_element
= make_xml_hier(child_name
, root
, elements
, hier
, error
, hfs
, etts
, proto_name
);
1362 g_ptr_array_remove_index_fast(hier
, hier
->len
- 1);
1364 if (child_element
) {
1365 wmem_map_insert(fresh
->elements
, child_element
->name
, child_element
);
1369 g_ptr_array_free(fresh
->element_names
, true);
1370 fresh
->element_names
= NULL
;
1374 static void free_elements(void *k _U_
, void *v
, void *p _U_
)
1376 xml_ns_t
*e
= (xml_ns_t
*)v
;
1378 while (e
->element_names
->len
) {
1379 g_free(g_ptr_array_remove_index(e
->element_names
, 0));
1382 g_ptr_array_free(e
->element_names
, true);
1385 static void register_dtd(dtd_build_data_t
*dtd_data
, GString
*errors
)
1387 wmem_map_t
*elements
= wmem_map_new(wmem_epan_scope(), g_str_hash
, g_str_equal
);
1388 char *root_name
= NULL
;
1389 xml_ns_t
*root_element
= NULL
;
1394 GPtrArray
*element_names
= g_ptr_array_new();
1396 /* we first populate elements with the those coming from the parser */
1397 while(dtd_data
->elements
->len
) {
1398 dtd_named_list_t
*nl
= (dtd_named_list_t
*)g_ptr_array_remove_index(dtd_data
->elements
, 0);
1399 xml_ns_t
*element
= wmem_new(wmem_epan_scope(), xml_ns_t
);
1401 /* we will use the first element found as root in case no other one was given. */
1402 if (root_name
== NULL
)
1403 root_name
= wmem_strdup(wmem_epan_scope(), nl
->name
);
1405 element
->name
= wmem_strdup(wmem_epan_scope(), nl
->name
);
1406 element
->element_names
= nl
->list
;
1407 element
->hf_tag
= -1;
1408 element
->hf_cdata
= -1;
1410 element
->attributes
= wmem_map_new(wmem_epan_scope(), g_str_hash
, g_str_equal
);
1411 element
->elements
= wmem_map_new(wmem_epan_scope(), g_str_hash
, g_str_equal
);
1413 if( wmem_map_lookup(elements
, element
->name
) ) {
1414 g_string_append_printf(errors
, "element %s defined more than once\n", element
->name
);
1415 free_elements(NULL
, element
, NULL
);
1417 wmem_map_insert(elements
, element
->name
, element
);
1418 g_ptr_array_add(element_names
, wmem_strdup(wmem_epan_scope(), element
->name
));
1425 /* then we add the attributes to its relative elements */
1426 while(dtd_data
->attributes
->len
) {
1427 dtd_named_list_t
*nl
= (dtd_named_list_t
*)g_ptr_array_remove_index(dtd_data
->attributes
, 0);
1428 xml_ns_t
*element
= (xml_ns_t
*)wmem_map_lookup(elements
, nl
->name
);
1431 while(nl
->list
->len
) {
1432 char *name
= (char *)g_ptr_array_remove_index(nl
->list
, 0);
1433 int *id_p
= wmem_new(wmem_epan_scope(), int);
1436 wmem_map_insert(element
->attributes
, wmem_strdup(wmem_epan_scope(), name
), id_p
);
1440 g_string_append_printf(errors
, "element %s is not defined\n", nl
->name
);
1444 g_ptr_array_free(nl
->list
, true);
1448 /* if a proto_root is defined in the dtd we'll use that as root */
1449 if( dtd_data
->proto_root
) {
1450 wmem_free(wmem_epan_scope(), root_name
);
1451 root_name
= wmem_strdup(wmem_epan_scope(), dtd_data
->proto_root
);
1454 /* we use a stack with the names to avoid recurring infinitely */
1455 hier
= g_ptr_array_new();
1458 * if a proto name was given in the dtd the dtd will be used as a protocol
1459 * or else the dtd will be loaded as a branch of the xml namespace
1461 if( ! dtd_data
->proto_name
) {
1464 g_ptr_array_add(hier
, wmem_strdup(wmem_epan_scope(), "xml"));
1467 * if we were given a proto_name the namespace will be registered
1468 * as an independent protocol with its own hf and ett arrays.
1470 hfs
= wmem_array_new(wmem_epan_scope(), sizeof(hf_register_info
));
1471 etts
= g_array_new(false, false, sizeof(int *));
1474 /* the root element of the dtd's namespace */
1475 root_element
= wmem_new(wmem_epan_scope(), xml_ns_t
);
1476 root_element
->name
= wmem_strdup(wmem_epan_scope(), root_name
);
1477 root_element
->fqn
= dtd_data
->proto_name
? wmem_strdup(wmem_epan_scope(), dtd_data
->proto_name
) : root_element
->name
;
1478 root_element
->hf_tag
= -1;
1479 root_element
->hf_cdata
= -1;
1480 root_element
->ett
= -1;
1481 root_element
->elements
= wmem_map_new(wmem_epan_scope(), g_str_hash
, g_str_equal
);
1482 root_element
->element_names
= element_names
;
1485 * we can either create a namespace as a flat namespace
1486 * in which all the elements are at the root level
1487 * or we can create a recursive namespace
1489 if (dtd_data
->recursion
) {
1490 xml_ns_t
*orig_root
;
1492 make_xml_hier(root_name
, root_element
, elements
, hier
, errors
, hfs
, etts
, dtd_data
->proto_name
);
1494 wmem_map_insert(root_element
->elements
, (void *)root_element
->name
, root_element
);
1496 orig_root
= (xml_ns_t
*)wmem_map_lookup(elements
, root_name
);
1498 /* if the root element was defined copy its attrlist to the child */
1500 struct _attr_reg_data d
;
1502 d
.basename
= dtd_data
->proto_name
;
1505 root_element
->attributes
= copy_attributes_hash(orig_root
->attributes
);
1506 wmem_map_foreach(root_element
->attributes
, add_xml_attribute_names
, &d
);
1508 root_element
->attributes
= wmem_map_new(wmem_epan_scope(), g_str_hash
, g_str_equal
);
1511 /* we then create all the sub hierarchies to catch the recurred cases */
1512 g_ptr_array_add(hier
, root_name
);
1514 while(root_element
->element_names
->len
) {
1515 curr_name
= (char *)g_ptr_array_remove_index(root_element
->element_names
, 0);
1517 if( ! wmem_map_lookup(root_element
->elements
, curr_name
) ) {
1518 xml_ns_t
*fresh
= make_xml_hier(curr_name
, root_element
, elements
, hier
, errors
,
1519 hfs
, etts
, dtd_data
->proto_name
);
1520 wmem_map_insert(root_element
->elements
, (void *)fresh
->name
, fresh
);
1525 /* a flat namespace */
1526 g_ptr_array_add(hier
, root_name
);
1528 root_element
->attributes
= wmem_map_new(wmem_epan_scope(), g_str_hash
, g_str_equal
);
1530 while(root_element
->element_names
->len
) {
1533 struct _attr_reg_data d
;
1535 curr_name
= (char *)g_ptr_array_remove_index(root_element
->element_names
, 0);
1536 fresh
= duplicate_element((xml_ns_t
*)wmem_map_lookup(elements
, curr_name
));
1537 fresh
->fqn
= fully_qualified_name(hier
, curr_name
, root_name
);
1539 add_xml_field(hfs
, &(fresh
->hf_tag
), curr_name
, fresh
->fqn
);
1540 add_xml_field(hfs
, &(fresh
->hf_cdata
), curr_name
, fresh
->fqn
);
1542 d
.basename
= fresh
->fqn
;
1545 wmem_map_foreach(fresh
->attributes
, add_xml_attribute_names
, &d
);
1547 ett_p
= &fresh
->ett
;
1548 g_array_append_val(etts
, ett_p
);
1550 g_ptr_array_free(fresh
->element_names
, true);
1552 wmem_map_insert(root_element
->elements
, (void *)fresh
->name
, fresh
);
1556 g_ptr_array_free(element_names
, true);
1558 g_ptr_array_free(hier
, true);
1561 * if we were given a proto_name the namespace will be registered
1562 * as an independent protocol.
1564 if( dtd_data
->proto_name
) {
1566 char *full_name
, *short_name
;
1568 if (dtd_data
->description
) {
1569 full_name
= wmem_strdup(wmem_epan_scope(), dtd_data
->description
);
1571 full_name
= wmem_strdup(wmem_epan_scope(), root_name
);
1573 short_name
= wmem_strdup(wmem_epan_scope(), dtd_data
->proto_name
);
1575 ett_p
= &root_element
->ett
;
1576 g_array_append_val(etts
, ett_p
);
1578 add_xml_field(hfs
, &root_element
->hf_cdata
, root_element
->name
, root_element
->fqn
);
1580 root_element
->hf_tag
= proto_register_protocol(full_name
, short_name
, short_name
);
1581 proto_register_field_array(root_element
->hf_tag
, (hf_register_info
*)wmem_array_get_raw(hfs
), wmem_array_get_count(hfs
));
1582 proto_register_subtree_array((int **)etts
->data
, etts
->len
);
1584 if (dtd_data
->media_type
) {
1585 char* media_type
= wmem_strdup(wmem_epan_scope(), dtd_data
->media_type
);
1586 wmem_map_insert(media_types
, media_type
, root_element
);
1589 g_array_free(etts
, true);
1592 wmem_map_insert(xml_ns
.elements
, root_element
->name
, root_element
);
1593 wmem_map_foreach(elements
, free_elements
, NULL
);
1595 destroy_dtd_data(dtd_data
);
1596 wmem_free(wmem_epan_scope(), root_name
);
1599 # define DIRECTORY_T GDir
1600 # define FILE_T char
1601 # define OPENDIR_OP(name) g_dir_open(name, 0, dummy)
1602 # define DIRGETNEXT_OP(dir) g_dir_read_name(dir)
1603 # define GETFNAME_OP(file) (file);
1604 # define CLOSEDIR_OP(dir) g_dir_close(dir)
1606 static void init_xml_names(void)
1611 const char *filename
;
1614 GError
**dummy
= wmem_new(wmem_epan_scope(), GError
*);
1617 xmpli_names
= wmem_map_new(wmem_epan_scope(), g_str_hash
, g_str_equal
);
1618 media_types
= wmem_map_new(wmem_epan_scope(), g_str_hash
, g_str_equal
);
1620 unknown_ns
.elements
= xml_ns
.elements
= wmem_map_new(wmem_epan_scope(), g_str_hash
, g_str_equal
);
1621 unknown_ns
.attributes
= xml_ns
.attributes
= wmem_map_new(wmem_epan_scope(), g_str_hash
, g_str_equal
);
1623 xml_new_namespace(xmpli_names
, "xml", "version", "encoding", "standalone", NULL
);
1625 dirname
= get_persconffile_path("dtds", false);
1627 if (test_for_directory(dirname
) != EISDIR
) {
1628 /* Although dir isn't a directory it may still use memory */
1630 dirname
= get_datafile_path("dtds");
1633 if (test_for_directory(dirname
) == EISDIR
) {
1634 if ((dir
= OPENDIR_OP(dirname
)) != NULL
) {
1635 GString
*errors
= g_string_new("");
1637 while ((file
= DIRGETNEXT_OP(dir
)) != NULL
) {
1639 filename
= GETFNAME_OP(file
);
1641 namelen
= (int)strlen(filename
);
1642 if ( namelen
> 4 && ( g_ascii_strcasecmp(filename
+(namelen
-4), ".dtd") == 0 ) ) {
1644 dtd_build_data_t
*dtd_data
;
1646 g_string_truncate(errors
, 0);
1647 preparsed
= dtd_preparse(dirname
, filename
, errors
);
1650 report_failure("Dtd Preparser in file %s%c%s: %s",
1651 dirname
, G_DIR_SEPARATOR
, filename
, errors
->str
);
1655 dtd_data
= dtd_parse(preparsed
);
1657 g_string_free(preparsed
, true);
1659 if (dtd_data
->error
->len
) {
1660 report_failure("Dtd Parser in file %s%c%s: %s",
1661 dirname
, G_DIR_SEPARATOR
, filename
, dtd_data
->error
->str
);
1662 destroy_dtd_data(dtd_data
);
1666 register_dtd(dtd_data
, errors
);
1669 report_failure("Dtd Registration in file: %s%c%s: %s",
1670 dirname
, G_DIR_SEPARATOR
, filename
, errors
->str
);
1675 g_string_free(errors
, true);
1683 for(i
=0;i
<array_length(default_media_types
);i
++) {
1684 if( ! wmem_map_lookup(media_types
, default_media_types
[i
]) ) {
1685 wmem_map_insert(media_types
, (void *)default_media_types
[i
], &xml_ns
);
1689 wmem_map_foreach(xmpli_names
, add_xmlpi_namespace
, (void *)"xml.xmlpi");
1691 wmem_free(wmem_epan_scope(), dummy
);
1695 xml_init_protocol(void)
1697 // The longest encoding at https://www.iana.org/assignments/character-sets/character-sets.xml
1698 // is 45 characters (Extended_UNIX_Code_Packed_Format_for_Japanese).
1699 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);
1703 xml_cleanup_protocol(void) {
1704 g_regex_unref(encoding_pattern
);
1708 proto_register_xml(void)
1710 static int *ett_base
[] = {
1717 static hf_register_info hf_base
[] = {
1719 {"XMLPI", "xml.xmlpi",
1720 FT_STRING
, BASE_NONE
, NULL
, 0,
1724 {"CDATASection", "xml.cdatasection",
1725 FT_STRING
, BASE_NONE
, NULL
, 0,
1729 {"Comment", "xml.comment",
1730 FT_STRING
, BASE_NONE
, NULL
, 0,
1733 { &hf_unknowwn_attrib
,
1734 {"Attribute", "xml.attribute",
1735 FT_STRING
, BASE_NONE
, NULL
, 0,
1739 {"Doctype", "xml.doctype",
1740 FT_STRING
, BASE_NONE
, NULL
, 0,
1744 {"DTD Tag", "xml.dtdtag",
1745 FT_STRING
, BASE_NONE
, NULL
, 0,
1748 { &unknown_ns
.hf_cdata
,
1749 {"CDATA", "xml.cdata",
1750 FT_STRING
, BASE_NONE
, NULL
, 0, NULL
,
1753 { &unknown_ns
.hf_tag
,
1755 FT_STRING
, BASE_NONE
, NULL
, 0,
1759 {"Unknown", "xml.unknown",
1760 FT_STRING
, BASE_NONE
, NULL
, 0,
1765 static ei_register_info ei
[] = {
1766 { &ei_xml_closing_unopened_tag
, { "xml.closing_unopened_tag", PI_MALFORMED
, PI_ERROR
, "Closing an unopened tag", EXPFILL
}},
1767 { &ei_xml_closing_unopened_xmpli_tag
, { "xml.closing_unopened_xmpli_tag", PI_MALFORMED
, PI_ERROR
, "Closing an unopened xmpli tag", EXPFILL
}},
1768 { &ei_xml_unrecognized_text
, { "xml.unrecognized_text", PI_PROTOCOL
, PI_WARN
, "Unrecognized text", EXPFILL
}},
1771 module_t
*xml_module
;
1772 expert_module_t
* expert_xml
;
1774 hf_arr
= wmem_array_new(wmem_epan_scope(), sizeof(hf_register_info
));
1775 ett_arr
= g_array_new(false, false, sizeof(int *));
1777 wmem_array_append(hf_arr
, hf_base
, array_length(hf_base
));
1778 g_array_append_vals(ett_arr
, ett_base
, array_length(ett_base
));
1782 xml_ns
.hf_tag
= proto_register_protocol("eXtensible Markup Language", "XML", xml_ns
.name
);
1784 proto_register_field_array(xml_ns
.hf_tag
, (hf_register_info
*)wmem_array_get_raw(hf_arr
), wmem_array_get_count(hf_arr
));
1785 proto_register_subtree_array((int **)ett_arr
->data
, ett_arr
->len
);
1786 expert_xml
= expert_register_protocol(xml_ns
.hf_tag
);
1787 expert_register_field_array(expert_xml
, ei
, array_length(ei
));
1789 xml_module
= prefs_register_protocol(xml_ns
.hf_tag
, NULL
);
1790 prefs_register_obsolete_preference(xml_module
, "heuristic");
1791 prefs_register_obsolete_preference(xml_module
, "heuristic_tcp");
1792 prefs_register_obsolete_preference(xml_module
, "heuristic_udp");
1793 /* XXX - UCS-2, or UTF-16? */
1794 prefs_register_bool_preference(xml_module
, "heuristic_unicode", "Use Unicode in heuristics",
1795 "Try to recognize XML encoded in Unicode (UCS-2BE)",
1796 &pref_heuristic_unicode
);
1798 prefs_register_enum_preference(xml_module
, "default_encoding", "Default character encoding",
1799 "Use this charset if the 'encoding' attribute of XML declaration is missing."
1800 "Unsupported encoding will be replaced by the default UTF-8.",
1801 &pref_default_encoding
, ws_supported_mibenum_vals_character_sets_ev_array
, false);
1803 g_array_free(ett_arr
, true);
1805 register_init_routine(&xml_init_protocol
);
1806 register_cleanup_routine(&xml_cleanup_protocol
);
1808 xml_handle
= register_dissector("xml", dissect_xml
, xml_ns
.hf_tag
);
1814 add_dissector_media(void *k
, void *v _U_
, void *p _U_
)
1816 dissector_add_string("media_type", (char *)k
, xml_handle
);
1820 proto_reg_handoff_xml(void)
1822 wmem_map_foreach(media_types
, add_dissector_media
, NULL
);
1823 dissector_add_string("media_type.suffix", "xml", xml_handle
); /* RFC 7303 9.6 */
1824 dissector_add_uint_range_with_preference("tcp.port", "", xml_handle
);
1825 dissector_add_uint_range_with_preference("udp.port", XML_UDP_PORT_RANGE
, xml_handle
);
1827 gssapi_handle
= find_dissector_add_dependency("gssapi", xml_ns
.hf_tag
);
1829 heur_dissector_add("http", dissect_xml_heur
, "XML in HTTP", "xml_http", xml_ns
.hf_tag
, HEURISTIC_DISABLE
);
1830 heur_dissector_add("sip", dissect_xml_heur
, "XML in SIP", "xml_sip", xml_ns
.hf_tag
, HEURISTIC_DISABLE
);
1831 heur_dissector_add("media", dissect_xml_heur
, "XML in media", "xml_media", xml_ns
.hf_tag
, HEURISTIC_DISABLE
);
1832 heur_dissector_add("tcp", dissect_xml_heur
, "XML over TCP", "xml_tcp", xml_ns
.hf_tag
, HEURISTIC_DISABLE
);
1833 heur_dissector_add("udp", dissect_xml_heur
, "XML over UDP", "xml_udp", xml_ns
.hf_tag
, HEURISTIC_DISABLE
);
1835 heur_dissector_add("wtap_file", dissect_xml_heur
, "XML file", "xml_wtap", xml_ns
.hf_tag
, HEURISTIC_ENABLE
);
1837 dissector_add_uint("acdr.tls_application", TLS_APP_XML
, xml_handle
);
1841 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1846 * indent-tabs-mode: nil
1849 * vi: set shiftwidth=4 tabstop=8 expandtab:
1850 * :indentSize=4:tabSize=8:noTabs=true: