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 <wsutil/array.h>
34 #include "packet-kerberos.h"
35 #include "read_keytab_file.h"
37 #include "packet-xml.h"
38 #include "packet-acdr.h"
40 void proto_register_xml(void);
41 void proto_reg_handoff_xml(void);
43 struct _attr_reg_data
{
52 static int hf_unknowwn_attrib
;
53 static int hf_comment
;
55 static int hf_dtd_tag
;
56 static int hf_doctype
;
57 static int hf_cdatasection
;
59 static expert_field ei_xml_closing_unopened_tag
;
60 static expert_field ei_xml_closing_unopened_xmpli_tag
;
61 static expert_field ei_xml_unrecognized_text
;
63 /* dissector handles */
64 static dissector_handle_t xml_handle
;
65 static dissector_handle_t gssapi_handle
;
67 /* Port 3702 is IANA-registered for Web Service Discovery, which uses
68 * SOAP-over-UDP to send XML */
69 #define XML_UDP_PORT_RANGE "3702"
71 /* parser definitions */
72 static tvbparse_wanted_t
*want
;
73 static tvbparse_wanted_t
*want_ignore
;
74 static tvbparse_wanted_t
*want_heur
;
76 static wmem_map_t
*xmpli_names
;
77 static wmem_map_t
*media_types
;
79 static xml_ns_t xml_ns
= {"xml", "/", -1, -1, -1, NULL
, NULL
, NULL
};
80 static xml_ns_t unknown_ns
= {"unknown", "?", -1, -1, -1, NULL
, NULL
, NULL
};
81 static xml_ns_t
*root_ns
;
83 static bool pref_heuristic_unicode
;
84 static int pref_default_encoding
= IANA_CS_UTF_8
;
87 #define XML_CDATA -1000
88 #define XML_SCOPED_NAME -1001
91 static wmem_array_t
*hf_arr
;
92 static GArray
*ett_arr
;
93 static GRegex
* encoding_pattern
;
95 static const char *default_media_types
[] = {
102 "application/3gpp-ims+xml",
103 "application/atom+xml",
104 "application/auth-policy+xml",
105 "application/ccmp+xml",
106 "application/conference-info+xml", /*RFC4575*/
107 "application/cpim-pidf+xml",
108 "application/cpl+xml",
109 "application/dds-web+xml",
110 "application/im-iscomposing+xml", /*RFC3994*/
111 "application/load-control+xml", /*RFC7200*/
112 "application/mathml+xml",
113 "application/media_control+xml",
114 "application/note+xml",
115 "application/pidf+xml",
116 "application/pidf-diff+xml",
117 "application/poc-settings+xml",
118 "application/rdf+xml",
119 "application/reginfo+xml",
120 "application/resource-lists+xml",
121 "application/rlmi+xml",
122 "application/rls-services+xml",
123 "application/rss+xml",
124 "application/rs-metadata+xml",
126 "application/simple-filter+xml",
127 "application/simple-message-summary+xml", /*RFC3842*/
128 "application/simservs+xml",
129 "application/soap+xml",
130 "application/vnd.etsi.aoc+xml",
131 "application/vnd.etsi.cug+xml",
132 "application/vnd.etsi.iptvcommand+xml",
133 "application/vnd.etsi.iptvdiscovery+xml",
134 "application/vnd.etsi.iptvprofile+xml",
135 "application/vnd.etsi.iptvsad-bc+xml",
136 "application/vnd.etsi.iptvsad-cod+xml",
137 "application/vnd.etsi.iptvsad-npvr+xml",
138 "application/vnd.etsi.iptvservice+xml",
139 "application/vnd.etsi.iptvsync+xml",
140 "application/vnd.etsi.iptvueprofile+xml",
141 "application/vnd.etsi.mcid+xml",
142 "application/vnd.etsi.overload-control-policy-dataset+xml",
143 "application/vnd.etsi.pstn+xml",
144 "application/vnd.etsi.sci+xml",
145 "application/vnd.etsi.simservs+xml",
146 "application/vnd.etsi.tsl+xml",
147 "application/vnd.oma.xdm-apd+xml",
148 "application/vnd.oma.fnl+xml",
149 "application/vnd.oma.access-permissions-list+xml",
150 "application/vnd.oma.alias-principals-list+xml",
151 "application/upp-directory+xml", /*OMA-ERELD-XDM-V2_2_1-20170124-A*/
152 "application/vnd.oma.xdm-hi+xml",
153 "application/vnd.oma.xdm-rhi+xml",
154 "application/vnd.oma.xdm-prefs+xml",
155 "application/vnd.oma.xdcp+xml",
156 "application/vnd.oma.bcast.associated-procedure-parameter+xml",
157 "application/vnd.oma.bcast.drm-trigger+xml",
158 "application/vnd.oma.bcast.imd+xml",
159 "application/vnd.oma.bcast.notification+xml",
160 "application/vnd.oma.bcast.sgdd+xml",
161 "application/vnd.oma.bcast.smartcard-trigger+xml",
162 "application/vnd.oma.bcast.sprov+xml",
163 "application/vnd.oma.cab-address-book+xml",
164 "application/vnd.oma.cab-feature-handler+xml",
165 "application/vnd.oma.cab-pcc+xml",
166 "application/vnd.oma.cab-subs-invite+xml",
167 "application/vnd.oma.cab-user-prefs+xml",
168 "application/vnd.oma.dd2+xml",
169 "application/vnd.oma.drm.risd+xml",
170 "application/vnd.oma.group-usage-list+xml",
171 "application/vnd.oma.pal+xml",
172 "application/vnd.oma.poc.detailed-progress-report+xml",
173 "application/vnd.oma.poc.final-report+xml",
174 "application/vnd.oma.poc.groups+xml",
175 "application/vnd.oma.poc.invocation-descriptor+xml",
176 "application/vnd.oma.poc.optimized-progress-report+xml",
177 "application/vnd.oma.scidm.messages+xml",
178 "application/vnd.oma.suppnot+xml", /*OMA-ERELD-Presence_SIMPLE-V2_0-20120710-A*/
179 "application/vnd.oma.xcap-directory+xml",
180 "application/vnd.omads-email+xml",
181 "application/vnd.omads-file+xml",
182 "application/vnd.omads-folder+xml",
183 "application/vnd.3gpp.access-transfer-events+xml",
184 "application/vnd.3gpp.bsf+xml",
185 "application/vnd.3gpp.comm-div-info+xml", /*3GPP TS 24.504 version 8.19.0*/
186 "application/vnd.3gpp.cw+xml",
187 "application/vnd.3gpp.iut+xml", /*3GPP TS 24.337*/
188 "application/vnc.3gpp.iut-config+xml", /*3GPP TS 24.337*/
189 "application/vnd.3gpp.mcptt-info+xml", /*3GPP TS 24.379 version 17.6.0*/
190 "application/vnd.3gpp.mcptt-mbms-usage-info+xml", /*3GPP TS 24.379 version 17.6.0*/
191 "application/vnd.3gpp.mcptt-location-info+xml", /*3GPP TS 24.379 version 17.6.0*/
192 "application/vnd.3gpp.mcptt-affiliation-command+xml", /*3GPP TS 24.379 version 17.6.0*/
193 "application/vnd.3gpp.mcptt-floor-request+xml", /*3GPP TS 24.379 version 17.6.0*/
194 "application/vnd.3gpp.mcptt-signed+xml", /*3GPP TS 24.379 version 17.6.0*/
195 "application/vnd.3gpp.mcptt-regroup+xml", /*3GPP TS 24.379 version 17.6.0*/
196 "application/vnd.3gpp.mcdata-info+xml", /*3GPP TS 24.282 version 17.6.2*/
197 "application/vnd.3gpp.mcdata-mbms-usage-info+xml", /*3GPP TS 24.282 version 17.6.2*/
198 "application/vnd.3gpp.mcdata-location-info+xml", /*3GPP TS 24.282 version 17.6.2*/
199 "application/vnd.3gpp.mcdata-affiliation-command+xml", /*3GPP TS 24.282 version 17.6.2*/
200 "application/vnd.3gpp.mcdata-regroup+xml", /*3GPP TS 24.282 version 17.6.2*/
201 "application/vnd.3gpp.mcvideo-info+xml", /*3GPP TS 24.281 version 17.6.0*/
202 "application/vnd.3gpp.mcvideo-mbms-usage-info+xml", /*3GPP TS 24.281 version 17.6.0*/
203 "application/vnd.3gpp.mcvideo-location-info+xml", /*3GPP TS 24.281 version 17.6.0*/
204 "application/vnd.3gpp.mcvideo-affiliation-command+xml",/*3GPP TS 24.281 version 17.6.0*/
205 "application/vnd.3gpp.transmission-request+xml", /*3GPP TS 24.281 version 17.6.0*/
206 "application/vnd.3gpp.mcptt-ue-init-config+xml", /*3GPP TS 24.484 version 17.5.0*/
207 "application/vnd.3gpp.mcptt-ue-config+xml", /*3GPP TS 24.484 version 17.5.0*/
208 "application/vnd.3gpp.mcptt-user-profile+xml", /*3GPP TS 24.484 version 17.5.0*/
209 "application/vnd.3gpp.mcptt-service-config+xml", /*3GPP TS 24.484 version 17.5.0*/
210 "application/vnd.3gpp.mcdata-service-config+xml", /*3GPP TS 24.484 version 17.5.0*/
211 "application/vnd.3gpp.mcvideo-service-config+xml", /*3GPP TS 24.484 version 17.5.0*/
212 "application/vnd.3gpp.mcvideo-ue-config+xml", /*3GPP TS 24.484 version 17.5.0*/
213 "application/vnd.3gpp.mcvideo-user-profile+xml", /*3GPP TS 24.484 version 17.5.0*/
214 "application/vnd.3gpp.mcdata-ue-config+xml", /*3GPP TS 24.484 version 17.5.0*/
215 "application/vnd.3gpp.mcdata-user-profile+xml", /*3GPP TS 24.484 version 17.5.0*/
216 "application/vnd.3gpp.mid-call+xml",
217 "application/vnd.3gpp-prose-pc3ch+xml",
218 "application/vnd.3gpp-prose+xml",
219 "application/vnd.3gpp.replication+xml", /*3GPP TS 24.337*/
220 "application/vnd.3gpp.sms+xml",
221 "application/vnd.3gpp.srvcc-info+xml",
222 "application/vnd.3gpp.srvcc-ext+xml",
223 "application/vnd.3gpp.state-and-event-info+xml",
224 "application/vnd.3gpp.ussd+xml",
225 "application/vnd.3gpp2.bcmcsinfo+xml",
226 "application/vnd.wv.csp+xml",
227 "application/vnd.wv.csp.xml",
228 "application/watcherinfo+xml",
229 "application/xcap-att+xml",
230 "application/xcap-caps+xml",
231 "application/xcap-diff+xml",
232 "application/xcap-el+xml",
233 "application/xcap-error+xml",
234 "application/xcap-ns+xml",
236 "application/xml-dtd",
237 "application/xpidf+xml",
238 "application/xslt+xml",
239 "application/x-crd+xml",
240 "application/x-wms-logconnectstats",
241 "application/x-wms-logplaystats",
242 "application/x-wms-sendevent",
244 "message/imdn+xml", /*RFC5438*/
247 static void insert_xml_frame(xml_frame_t
*parent
, xml_frame_t
*new_child
)
249 new_child
->first_child
= NULL
;
250 new_child
->last_child
= NULL
;
252 new_child
->parent
= parent
;
253 new_child
->next_sibling
= NULL
;
254 new_child
->prev_sibling
= NULL
;
255 if (parent
== NULL
) return; /* root */
257 if (parent
->first_child
== NULL
) { /* the 1st child */
258 parent
->first_child
= new_child
;
259 } else { /* following children */
260 parent
->last_child
->next_sibling
= new_child
;
261 new_child
->prev_sibling
= parent
->last_child
;
263 parent
->last_child
= new_child
;
266 /* Try to get the 'encoding' attribute from XML declaration, and convert it to
267 * Wireshark character encoding.
270 get_char_encoding(tvbuff_t
* tvb
, packet_info
* pinfo
, char** ret_encoding_name
) {
271 uint32_t iana_charset_id
;
272 unsigned ws_encoding_id
;
274 GMatchInfo
* match_info
;
275 const char* xmldecl
= (char*)tvb_get_string_enc(pinfo
->pool
, tvb
, 0,
276 MIN(100, tvb_captured_length(tvb
)), ENC_UTF_8
);
278 g_regex_match(encoding_pattern
, xmldecl
, 0, &match_info
);
279 if (g_match_info_matches(match_info
)) {
280 char* match_ret
= g_match_info_fetch(match_info
, 1);
281 encoding_str
= ascii_strup_inplace(wmem_strdup(pinfo
->pool
, match_ret
));
283 /* Get the iana charset enum number by the name of the charset. */
284 iana_charset_id
= str_to_val(encoding_str
,
285 VALUE_STRING_EXT_VS_P(&mibenum_vals_character_sets_ext
), IANA_CS_US_ASCII
);
287 /* Use default encoding preference if this xml does not contains 'encoding' attribute. */
288 iana_charset_id
= pref_default_encoding
;
289 encoding_str
= val_to_str_ext_wmem(pinfo
->pool
, iana_charset_id
,
290 &mibenum_vals_character_sets_ext
, "UNKNOWN");
292 g_match_info_free(match_info
);
294 ws_encoding_id
= mibenum_charset_to_encoding((unsigned)iana_charset_id
);
296 /* UTF-8 compatible with ASCII */
297 if (ws_encoding_id
== (ENC_NA
| ENC_ASCII
)) {
298 ws_encoding_id
= ENC_UTF_8
;
299 *ret_encoding_name
= wmem_strdup(pinfo
->pool
, "UTF-8");
301 *ret_encoding_name
= encoding_str
;
304 return ws_encoding_id
;
308 dissect_xml(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
311 static GPtrArray
*stack
;
312 xml_frame_t
*current_frame
;
313 const char *colinfo_str
;
318 g_ptr_array_free(stack
, true);
320 stack
= g_ptr_array_new();
321 current_frame
= wmem_new(wmem_packet_scope(), xml_frame_t
);
322 current_frame
->type
= XML_FRAME_ROOT
;
323 current_frame
->name
= NULL
;
324 current_frame
->name_orig_case
= NULL
;
325 current_frame
->value
= NULL
;
326 current_frame
->pinfo
= pinfo
;
327 insert_xml_frame(NULL
, current_frame
);
328 g_ptr_array_add(stack
, current_frame
);
330 /* Detect and act on possible byte-order mark (BOM) */
331 try_bom
= tvb_get_ntohs(tvb
, 0);
332 if (try_bom
== 0xFEFF) {
334 const uint8_t *data_str
= tvb_get_string_enc(pinfo
->pool
, tvb
, 0, tvb_captured_length(tvb
), ENC_UTF_16
|ENC_BIG_ENDIAN
);
335 size_t l
= strlen(data_str
);
336 decoded
= tvb_new_child_real_data(tvb
, data_str
, (unsigned)l
, (int)l
);
337 add_new_data_source(pinfo
, decoded
, "Decoded UTF-16BE text");
339 else if(try_bom
== 0xFFFE) {
340 /* UTF-16LE (or possibly UTF-32LE, but Wireshark doesn't support UTF-32) */
341 const uint8_t *data_str
= tvb_get_string_enc(pinfo
->pool
, tvb
, 0, tvb_captured_length(tvb
), ENC_UTF_16
|ENC_LITTLE_ENDIAN
);
342 size_t l
= strlen(data_str
);
343 decoded
= tvb_new_child_real_data(tvb
, data_str
, (unsigned)l
, (int)l
);
344 add_new_data_source(pinfo
, decoded
, "Decoded UTF-16LE text");
346 /* Could also test if try_bom is 0xnn00 or 0x00nn to guess endianness if we wanted */
348 /* Get character encoding according to XML declaration or preference. */
350 unsigned encoding
= get_char_encoding(tvb
, pinfo
, &encoding_name
);
352 /* Encoding string with encoding, either with or without BOM */
353 const uint8_t *data_str
= tvb_get_string_enc(pinfo
->pool
, tvb
, 0, tvb_captured_length(tvb
), encoding
);
354 size_t l
= strlen(data_str
);
355 decoded
= tvb_new_child_real_data(tvb
, data_str
, (unsigned)l
, (int)l
);
356 add_new_data_source(pinfo
, decoded
, wmem_strdup_printf(pinfo
->pool
, "Decoded %s text", encoding_name
));
359 tt
= tvbparse_init(pinfo
->pool
, decoded
, 0, -1, stack
, want_ignore
);
360 current_frame
->start_offset
= 0;
361 current_frame
->length
= tvb_captured_length(decoded
);
363 current_frame
->decryption_keys
= wmem_map_new(wmem_packet_scope(), g_str_hash
, g_str_equal
);
367 if (pinfo
->match_string
)
368 root_ns
= (xml_ns_t
*)wmem_map_lookup(media_types
, pinfo
->match_string
);
372 colinfo_str
= "/XML";
374 char *colinfo_str_buf
;
375 colinfo_str_buf
= wmem_strconcat(wmem_packet_scope(), "/", root_ns
->name
, NULL
);
376 ascii_strup_inplace(colinfo_str_buf
);
377 colinfo_str
= colinfo_str_buf
;
380 col_append_str(pinfo
->cinfo
, COL_PROTOCOL
, colinfo_str
);
382 current_frame
->ns
= root_ns
;
384 current_frame
->item
= proto_tree_add_item(tree
, current_frame
->ns
->hf_tag
, decoded
, 0, -1, ENC_UTF_8
|ENC_NA
);
385 current_frame
->tree
= proto_item_add_subtree(current_frame
->item
, current_frame
->ns
->ett
);
386 current_frame
->last_item
= current_frame
->item
;
388 while(tvbparse_get(tt
, want
)) ;
390 /* Save XML structure in case it is useful for the caller */
391 p_add_proto_data(pinfo
->pool
, pinfo
, xml_ns
.hf_tag
, 0, current_frame
);
393 return tvb_captured_length(tvb
);
396 static bool dissect_xml_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
398 if (tvbparse_peek(tvbparse_init(pinfo
->pool
, tvb
, 0, -1, NULL
, want_ignore
), want_heur
)) {
399 dissect_xml(tvb
, pinfo
, tree
, data
);
401 } else if (pref_heuristic_unicode
) {
402 const uint8_t *data_str
;
403 tvbuff_t
*unicode_tvb
;
405 /* XXX - UCS-2, or UTF-16? */
406 int enc
= ENC_UCS_2
|ENC_LITTLE_ENDIAN
;
409 try_bom
= tvb_get_ntohs(tvb
, 0);
410 if (try_bom
== 0xFEFF) {
411 enc
= ENC_UTF_16
|ENC_BIG_ENDIAN
;
413 else if(try_bom
== 0xFFFE) {
414 enc
= ENC_UTF_16
|ENC_LITTLE_ENDIAN
;
417 data_str
= tvb_get_string_enc(pinfo
->pool
, tvb
, 0, tvb_captured_length(tvb
), enc
);
418 l
= strlen(data_str
);
419 unicode_tvb
= tvb_new_child_real_data(tvb
, data_str
, (unsigned)l
, (int)l
);
420 if (tvbparse_peek(tvbparse_init(pinfo
->pool
, unicode_tvb
, 0, -1, NULL
, want_ignore
), want_heur
)) {
421 add_new_data_source(pinfo
, unicode_tvb
, "UTF8");
422 dissect_xml(unicode_tvb
, pinfo
, tree
, data
);
429 xml_frame_t
*xml_get_tag(xml_frame_t
*frame
, const char *name
)
431 xml_frame_t
*tag
= NULL
;
433 xml_frame_t
*xml_item
= frame
->first_child
;
435 if (xml_item
->type
== XML_FRAME_TAG
) {
436 if (!name
) { /* get the 1st tag */
439 } else if (xml_item
->name_orig_case
&& !strcmp(xml_item
->name_orig_case
, name
)) {
444 xml_item
= xml_item
->next_sibling
;
450 xml_frame_t
*xml_get_attrib(xml_frame_t
*frame
, const char *name
)
452 xml_frame_t
*attr
= NULL
;
454 xml_frame_t
*xml_item
= frame
->first_child
;
456 if ((xml_item
->type
== XML_FRAME_ATTRIB
) &&
457 xml_item
->name_orig_case
&& !strcmp(xml_item
->name_orig_case
, name
)) {
461 xml_item
= xml_item
->next_sibling
;
467 xml_frame_t
*xml_get_cdata(xml_frame_t
*frame
)
469 xml_frame_t
*cdata
= NULL
;
471 xml_frame_t
*xml_item
= frame
->first_child
;
473 if (xml_item
->type
== XML_FRAME_CDATA
) {
477 xml_item
= xml_item
->next_sibling
;
483 static void after_token(void *tvbparse_data
, const void *wanted_data _U_
, tvbparse_elem_t
*tok
)
485 GPtrArray
*stack
= (GPtrArray
*)tvbparse_data
;
486 xml_frame_t
*current_frame
= (xml_frame_t
*)g_ptr_array_index(stack
, stack
->len
- 1);
488 bool is_cdata
= false;
490 xml_frame_t
*new_frame
= NULL
;
493 if (tok
->id
== XML_CDATA
) {
494 hfid
= current_frame
->ns
? current_frame
->ns
->hf_cdata
: xml_ns
.hf_cdata
;
496 } else if ( tok
->id
> 0) {
499 hfid
= xml_ns
.hf_cdata
;
502 pi
= proto_tree_add_item(current_frame
->tree
, hfid
, tok
->tvb
, tok
->offset
, tok
->len
, ENC_UTF_8
|ENC_NA
);
504 text
= tvb_format_text(wmem_packet_scope(), tok
->tvb
, tok
->offset
, tok
->len
);
505 proto_item_set_text(pi
, "%s", text
);
508 new_frame
= wmem_new(wmem_packet_scope(), xml_frame_t
);
509 new_frame
->type
= XML_FRAME_CDATA
;
510 new_frame
->name
= NULL
;
511 new_frame
->name_orig_case
= NULL
;
512 new_frame
->value
= tvb_new_subset_length(tok
->tvb
, tok
->offset
, tok
->len
);
513 insert_xml_frame(current_frame
, new_frame
);
514 new_frame
->item
= pi
;
515 new_frame
->last_item
= pi
;
516 new_frame
->tree
= NULL
;
517 new_frame
->start_offset
= tok
->offset
;
518 new_frame
->length
= tok
->len
;
519 new_frame
->ns
= NULL
;
520 new_frame
->pinfo
= current_frame
->pinfo
;
523 if (new_frame
!= NULL
&&
524 current_frame
!= NULL
&&
525 current_frame
->name_orig_case
!= NULL
&&
526 strcmp(current_frame
->name_orig_case
, "BinarySecurityToken") == 0)
528 xml_frame_t
*value_type
= NULL
;
530 value_type
= xml_get_attrib(current_frame
, "ValueType");
531 if (value_type
!= NULL
) {
532 const char *s
= "http://docs.oasis-open.org/wss/oasis-wss-kerberos-token-profile-1.1#GSS_Kerberosv5_AP_REQ";
533 size_t l
= strlen(s
);
535 c
= tvb_strneql(value_type
->value
, 0, s
, l
);
537 tvbuff_t
*ssp_tvb
= base64_to_tvb(new_frame
->value
, text
);
538 add_new_data_source(current_frame
->pinfo
, ssp_tvb
, "GSSAPI Data");
539 call_dissector(gssapi_handle
, ssp_tvb
,
540 current_frame
->pinfo
, current_frame
->tree
);
546 static void before_xmpli(void *tvbparse_data
, const void *wanted_data _U_
, tvbparse_elem_t
*tok
)
548 GPtrArray
*stack
= (GPtrArray
*)tvbparse_data
;
549 xml_frame_t
*current_frame
= (xml_frame_t
*)g_ptr_array_index(stack
, stack
->len
- 1);
552 tvbparse_elem_t
*name_tok
= tok
->sub
->next
;
553 char *name
= tvb_get_string_enc(wmem_packet_scope(), name_tok
->tvb
, name_tok
->offset
, name_tok
->len
, ENC_ASCII
);
554 xml_ns_t
*ns
= (xml_ns_t
*)wmem_map_lookup(xmpli_names
, name
);
555 xml_frame_t
*new_frame
;
560 ascii_strdown_inplace(name
);
569 pi
= proto_tree_add_item(current_frame
->tree
, hf_tag
, tok
->tvb
, tok
->offset
, tok
->len
, ENC_UTF_8
|ENC_NA
);
571 proto_item_set_text(pi
, "%s", tvb_format_text(wmem_packet_scope(), tok
->tvb
, tok
->offset
, (name_tok
->offset
- tok
->offset
) + name_tok
->len
));
573 pt
= proto_item_add_subtree(pi
, ett
);
575 new_frame
= wmem_new(wmem_packet_scope(), xml_frame_t
);
576 new_frame
->type
= XML_FRAME_XMPLI
;
577 new_frame
->name
= name
;
578 new_frame
->name_orig_case
= name
;
579 new_frame
->value
= NULL
;
580 insert_xml_frame(current_frame
, new_frame
);
581 new_frame
->item
= pi
;
582 new_frame
->last_item
= pi
;
583 new_frame
->tree
= pt
;
584 new_frame
->start_offset
= tok
->offset
;
585 new_frame
->length
= tok
->len
;
587 new_frame
->pinfo
= current_frame
->pinfo
;
589 g_ptr_array_add(stack
, new_frame
);
593 static void after_xmlpi(void *tvbparse_data
, const void *wanted_data _U_
, tvbparse_elem_t
*tok
)
595 GPtrArray
*stack
= (GPtrArray
*)tvbparse_data
;
596 xml_frame_t
*current_frame
= (xml_frame_t
*)g_ptr_array_index(stack
, stack
->len
- 1);
598 proto_tree_add_format_text(current_frame
->tree
, tok
->tvb
, tok
->offset
, tok
->len
);
600 if (stack
->len
> 1) {
601 g_ptr_array_remove_index_fast(stack
, stack
->len
- 1);
603 proto_tree_add_expert(current_frame
->tree
, current_frame
->pinfo
, &ei_xml_closing_unopened_xmpli_tag
,
604 tok
->tvb
, tok
->offset
, tok
->len
);
608 static void before_tag(void *tvbparse_data
, const void *wanted_data _U_
, tvbparse_elem_t
*tok
)
610 GPtrArray
*stack
= (GPtrArray
*)tvbparse_data
;
611 xml_frame_t
*current_frame
= (xml_frame_t
*)g_ptr_array_index(stack
, stack
->len
- 1);
612 tvbparse_elem_t
*name_tok
= tok
->sub
->next
;
614 char *name
= NULL
, *name_orig_case
= NULL
;
616 xml_frame_t
*new_frame
;
620 if (name_tok
->sub
->id
== XML_SCOPED_NAME
) {
621 tvbparse_elem_t
*root_tok
= name_tok
->sub
->sub
;
622 tvbparse_elem_t
*leaf_tok
= name_tok
->sub
->sub
->next
->next
;
623 xml_ns_t
*nameroot_ns
;
625 root_name
= (char *)tvb_get_string_enc(wmem_packet_scope(), root_tok
->tvb
, root_tok
->offset
, root_tok
->len
, ENC_ASCII
);
626 name
= (char *)tvb_get_string_enc(wmem_packet_scope(), leaf_tok
->tvb
, leaf_tok
->offset
, leaf_tok
->len
, ENC_ASCII
);
627 name_orig_case
= name
;
629 nameroot_ns
= (xml_ns_t
*)wmem_map_lookup(xml_ns
.elements
, root_name
);
632 ns
= (xml_ns_t
*)wmem_map_lookup(nameroot_ns
->elements
, name
);
641 name
= tvb_get_string_enc(wmem_packet_scope(), name_tok
->tvb
, name_tok
->offset
, name_tok
->len
, ENC_ASCII
);
642 name_orig_case
= wmem_strdup(wmem_packet_scope(), name
);
643 ascii_strdown_inplace(name
);
645 if(current_frame
->ns
) {
646 ns
= (xml_ns_t
*)wmem_map_lookup(current_frame
->ns
->elements
, name
);
649 if (! ( ns
= (xml_ns_t
*)wmem_map_lookup(root_ns
->elements
, name
) ) ) {
658 pi
= proto_tree_add_item(current_frame
->tree
, ns
->hf_tag
, tok
->tvb
, tok
->offset
, tok
->len
, ENC_UTF_8
|ENC_NA
);
659 proto_item_set_text(pi
, "%s", tvb_format_text(wmem_packet_scope(), tok
->tvb
,
661 (name_tok
->offset
- tok
->offset
) + name_tok
->len
));
663 pt
= proto_item_add_subtree(pi
, ns
->ett
);
665 new_frame
= wmem_new(wmem_packet_scope(), xml_frame_t
);
666 new_frame
->type
= XML_FRAME_TAG
;
667 new_frame
->name
= name
;
668 new_frame
->name_orig_case
= name_orig_case
;
669 new_frame
->value
= NULL
;
670 insert_xml_frame(current_frame
, new_frame
);
671 new_frame
->item
= pi
;
672 new_frame
->last_item
= pi
;
673 new_frame
->tree
= pt
;
674 new_frame
->start_offset
= tok
->offset
;
675 new_frame
->length
= tok
->len
;
677 new_frame
->pinfo
= current_frame
->pinfo
;
679 g_ptr_array_add(stack
, new_frame
);
683 static void after_open_tag(void *tvbparse_data
, const void *wanted_data _U_
, tvbparse_elem_t
*tok _U_
)
685 GPtrArray
*stack
= (GPtrArray
*)tvbparse_data
;
686 xml_frame_t
*current_frame
= (xml_frame_t
*)g_ptr_array_index(stack
, stack
->len
- 1);
688 proto_item_append_text(current_frame
->last_item
, ">");
691 static void after_closed_tag(void *tvbparse_data
, const void *wanted_data _U_
, tvbparse_elem_t
*tok
)
693 GPtrArray
*stack
= (GPtrArray
*)tvbparse_data
;
694 xml_frame_t
*current_frame
= (xml_frame_t
*)g_ptr_array_index(stack
, stack
->len
- 1);
696 proto_item_append_text(current_frame
->last_item
, "/>");
698 if (stack
->len
> 1) {
699 g_ptr_array_remove_index_fast(stack
, stack
->len
- 1);
701 proto_tree_add_expert(current_frame
->tree
, current_frame
->pinfo
, &ei_xml_closing_unopened_tag
,
702 tok
->tvb
, tok
->offset
, tok
->len
);
707 struct decryption_key
{
710 uint8_t key
[HASH_SHA1_LENGTH
];
713 static void P_SHA1(const uint8_t *Secret
, size_t Secret_len
,
714 const uint8_t *Seed
, size_t Seed_len
,
715 uint8_t Result
[HASH_SHA1_LENGTH
])
717 gcry_md_hd_t hd
= NULL
;
718 uint8_t *digest
= NULL
;
721 * 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
723 gcry_md_open(&hd
, GCRY_MD_SHA1
, GCRY_MD_FLAG_HMAC
);
724 gcry_md_setkey(hd
, Secret
, Secret_len
);
725 gcry_md_write(hd
, Seed
, Seed_len
);
726 digest
= gcry_md_read(hd
, GCRY_MD_SHA1
);
727 memcpy(Result
, digest
, HASH_SHA1_LENGTH
);
731 #endif /* HAVE_KERBEROS */
733 static void after_untag(void *tvbparse_data
, const void *wanted_data _U_
, tvbparse_elem_t
*tok
)
735 GPtrArray
*stack
= (GPtrArray
*)tvbparse_data
;
736 xml_frame_t
*current_frame
= (xml_frame_t
*)g_ptr_array_index(stack
, stack
->len
- 1);
738 xml_frame_t
*top_frame
= (xml_frame_t
*)g_ptr_array_index(stack
, 0);
739 #endif /* HAVE_KERBEROS */
741 proto_item_set_len(current_frame
->item
, (tok
->offset
- current_frame
->start_offset
) + tok
->len
);
742 current_frame
->length
= (tok
->offset
- current_frame
->start_offset
) + tok
->len
;
744 proto_tree_add_format_text(current_frame
->tree
, tok
->tvb
, tok
->offset
, tok
->len
);
746 if (stack
->len
> 1) {
747 g_ptr_array_remove_index_fast(stack
, stack
->len
- 1);
749 proto_tree_add_expert(current_frame
->tree
, current_frame
->pinfo
, &ei_xml_closing_unopened_tag
,
750 tok
->tvb
, tok
->offset
, tok
->len
);
754 if (current_frame
->name_orig_case
== NULL
) {
758 if (strcmp(current_frame
->name_orig_case
, "DerivedKeyToken") == 0) {
759 xml_frame_t
*id_frame
= xml_get_attrib(current_frame
, "u:Id");
760 xml_frame_t
*nonce_frame
= xml_get_tag(current_frame
, "Nonce");
761 xml_frame_t
*nonce_cdata
= NULL
;
762 tvbuff_t
*nonce_tvb
= NULL
;
763 enc_key_t
*ek
= NULL
;
765 size_t seed_length
= 16; // TODO
766 const size_t key_length
= 16; //TODO
768 if (id_frame
!= NULL
&& nonce_frame
!= NULL
) {
769 nonce_cdata
= xml_get_cdata(nonce_frame
);
771 if (nonce_cdata
!= NULL
) {
772 char *text
= tvb_format_text(wmem_packet_scope(), nonce_cdata
->value
, 0,
773 tvb_reported_length(nonce_cdata
->value
));
774 nonce_tvb
= base64_to_tvb(nonce_cdata
->value
, text
);
776 if (nonce_tvb
!= NULL
) {
777 seed_length
= tvb_reported_length(nonce_tvb
);
778 seed_length
= MIN(seed_length
, sizeof(seed
));
779 tvb_memcpy(nonce_tvb
, seed
, 0, seed_length
);
782 read_keytab_file_from_preferences();
785 for (ek
=enc_key_list
;ek
;ek
=ek
->next
) {
786 if (ek
->fd_num
== (int)current_frame
->pinfo
->num
) {
792 struct decryption_key
*key
;
795 id_str
= tvb_format_text(wmem_packet_scope(),
797 tvb_reported_length(id_frame
->value
));
799 key
= wmem_new0(wmem_packet_scope(), struct decryption_key
);
800 key
->id
= wmem_strdup_printf(wmem_packet_scope(), "#%s", id_str
);
801 P_SHA1(ek
->keyvalue
, ek
->keylength
, seed
, seed_length
, key
->key
);
802 key
->key_length
= key_length
;
804 wmem_map_insert(top_frame
->decryption_keys
, key
->id
, key
);
807 if (strcmp(current_frame
->name_orig_case
, "CipherValue") == 0) {
808 xml_frame_t
*encrypted_frame
= current_frame
->parent
->parent
;
809 xml_frame_t
*key_info_frame
= NULL
;
810 xml_frame_t
*token_frame
= NULL
;
811 xml_frame_t
*reference_frame
= NULL
;
812 xml_frame_t
*uri_frame
= NULL
;
813 const struct decryption_key
*key
= NULL
;
814 xml_frame_t
*cdata_frame
= NULL
;
815 tvbuff_t
*crypt_tvb
= NULL
;
816 tvbuff_t
*plain_tvb
= NULL
;
818 key_info_frame
= xml_get_tag(encrypted_frame
, "KeyInfo");
819 if (key_info_frame
!= NULL
) {
820 token_frame
= xml_get_tag(key_info_frame
, "SecurityTokenReference");
822 if (token_frame
!= NULL
) {
823 reference_frame
= xml_get_tag(token_frame
, "Reference");
825 if (reference_frame
!= NULL
) {
826 uri_frame
= xml_get_attrib(reference_frame
, "URI");
829 if (uri_frame
!= NULL
) {
830 char *key_id
= tvb_format_text(wmem_packet_scope(), uri_frame
->value
, 0,
831 tvb_reported_length(uri_frame
->value
));
833 key
= (const struct decryption_key
*)wmem_map_lookup(top_frame
->decryption_keys
, key_id
);
836 cdata_frame
= xml_get_cdata(current_frame
);
838 if (cdata_frame
!= NULL
) {
839 char *text
= tvb_format_text(wmem_packet_scope(), cdata_frame
->value
, 0,
840 tvb_reported_length(cdata_frame
->value
));
841 crypt_tvb
= base64_to_tvb(cdata_frame
->value
, text
);
843 if (crypt_tvb
!= NULL
) {
844 gcry_cipher_hd_t cipher_hd
= NULL
;
845 uint8_t *data
= NULL
;
846 unsigned data_length
= tvb_reported_length(crypt_tvb
);
848 data
= (uint8_t *)tvb_memdup(wmem_packet_scope(),
849 crypt_tvb
, 0, data_length
);
851 /* Open the cipher. */
852 gcry_cipher_open(&cipher_hd
, GCRY_CIPHER_AES128
, GCRY_CIPHER_MODE_CBC
, 0);
854 gcry_cipher_setkey(cipher_hd
, key
->key
, key
->key_length
);
855 gcry_cipher_encrypt(cipher_hd
, data
, data_length
, NULL
, 0);
856 gcry_cipher_close(cipher_hd
);
858 plain_tvb
= tvb_new_child_real_data(crypt_tvb
, data
,
859 data_length
, data_length
);
860 add_new_data_source(current_frame
->pinfo
, plain_tvb
, "Decrypted Data");
863 #endif /* HAVE_KERBEROS */
866 static void before_dtd_doctype(void *tvbparse_data
, const void *wanted_data _U_
, tvbparse_elem_t
*tok
)
868 GPtrArray
*stack
= (GPtrArray
*)tvbparse_data
;
869 xml_frame_t
*current_frame
= (xml_frame_t
*)g_ptr_array_index(stack
, stack
->len
- 1);
870 xml_frame_t
*new_frame
;
871 tvbparse_elem_t
*name_tok
= tok
->sub
->next
->next
->next
->sub
->sub
;
872 proto_tree
*dtd_item
= proto_tree_add_item(current_frame
->tree
, hf_doctype
,
873 name_tok
->tvb
, name_tok
->offset
,
874 name_tok
->len
, ENC_ASCII
);
876 proto_item_set_text(dtd_item
, "%s", tvb_format_text(wmem_packet_scope(), tok
->tvb
, tok
->offset
, tok
->len
));
878 new_frame
= wmem_new(wmem_packet_scope(), xml_frame_t
);
879 new_frame
->type
= XML_FRAME_DTD_DOCTYPE
;
880 new_frame
->name
= (char *)tvb_get_string_enc(wmem_packet_scope(), name_tok
->tvb
,
882 name_tok
->len
, ENC_ASCII
);
883 new_frame
->name_orig_case
= new_frame
->name
;
884 new_frame
->value
= NULL
;
885 insert_xml_frame(current_frame
, new_frame
);
886 new_frame
->item
= dtd_item
;
887 new_frame
->last_item
= dtd_item
;
888 new_frame
->tree
= proto_item_add_subtree(dtd_item
, ett_dtd
);
889 new_frame
->start_offset
= tok
->offset
;
890 new_frame
->length
= tok
->len
;
891 new_frame
->ns
= NULL
;
892 new_frame
->pinfo
= current_frame
->pinfo
;
894 g_ptr_array_add(stack
, new_frame
);
897 static void pop_stack(void *tvbparse_data
, const void *wanted_data _U_
, tvbparse_elem_t
*tok _U_
)
899 GPtrArray
*stack
= (GPtrArray
*)tvbparse_data
;
900 xml_frame_t
*current_frame
= (xml_frame_t
*)g_ptr_array_index(stack
, stack
->len
- 1);
902 if (stack
->len
> 1) {
903 g_ptr_array_remove_index_fast(stack
, stack
->len
- 1);
905 proto_tree_add_expert(current_frame
->tree
, current_frame
->pinfo
, &ei_xml_closing_unopened_tag
,
906 tok
->tvb
, tok
->offset
, tok
->len
);
910 static void after_dtd_close(void *tvbparse_data
, const void *wanted_data _U_
, tvbparse_elem_t
*tok
)
912 GPtrArray
*stack
= (GPtrArray
*)tvbparse_data
;
913 xml_frame_t
*current_frame
= (xml_frame_t
*)g_ptr_array_index(stack
, stack
->len
- 1);
915 proto_tree_add_format_text(current_frame
->tree
, tok
->tvb
, tok
->offset
, tok
->len
);
916 if (stack
->len
> 1) {
917 g_ptr_array_remove_index_fast(stack
, stack
->len
- 1);
919 proto_tree_add_expert(current_frame
->tree
, current_frame
->pinfo
, &ei_xml_closing_unopened_tag
,
920 tok
->tvb
, tok
->offset
, tok
->len
);
924 static void get_attrib_value(void *tvbparse_data _U_
, const void *wanted_data _U_
, tvbparse_elem_t
*tok
)
926 tok
->data
= tok
->sub
;
929 static void after_attrib(void *tvbparse_data
, const void *wanted_data _U_
, tvbparse_elem_t
*tok
)
931 GPtrArray
*stack
= (GPtrArray
*)tvbparse_data
;
932 xml_frame_t
*current_frame
= (xml_frame_t
*)g_ptr_array_index(stack
, stack
->len
- 1);
933 char *name
, *name_orig_case
;
934 tvbparse_elem_t
*value
;
935 tvbparse_elem_t
*value_part
= (tvbparse_elem_t
*)tok
->sub
->next
->next
->data
;
939 xml_frame_t
*new_frame
;
941 name
= tvb_get_string_enc(wmem_packet_scope(), tok
->sub
->tvb
, tok
->sub
->offset
, tok
->sub
->len
, ENC_ASCII
);
942 name_orig_case
= wmem_strdup(wmem_packet_scope(), name
);
943 ascii_strdown_inplace(name
);
945 if(current_frame
->ns
&& (hfidp
= (int *)wmem_map_lookup(current_frame
->ns
->attributes
, name
) )) {
949 hfid
= hf_unknowwn_attrib
;
953 pi
= proto_tree_add_item(current_frame
->tree
, hfid
, value
->tvb
, value
->offset
, value
->len
, ENC_UTF_8
|ENC_NA
);
954 proto_item_set_text(pi
, "%s", tvb_format_text(wmem_packet_scope(), tok
->tvb
, tok
->offset
, tok
->len
));
956 current_frame
->last_item
= pi
;
958 new_frame
= wmem_new(wmem_packet_scope(), xml_frame_t
);
959 new_frame
->type
= XML_FRAME_ATTRIB
;
960 new_frame
->name
= name
;
961 new_frame
->name_orig_case
= name_orig_case
;
962 new_frame
->value
= tvb_new_subset_length(value_part
->tvb
, value_part
->offset
,
964 insert_xml_frame(current_frame
, new_frame
);
965 new_frame
->item
= pi
;
966 new_frame
->last_item
= pi
;
967 new_frame
->tree
= NULL
;
968 new_frame
->start_offset
= tok
->offset
;
969 new_frame
->length
= tok
->len
;
970 new_frame
->ns
= NULL
;
971 new_frame
->pinfo
= current_frame
->pinfo
;
975 static void unrecognized_token(void *tvbparse_data
, const void *wanted_data _U_
, tvbparse_elem_t
*tok _U_
)
977 GPtrArray
*stack
= (GPtrArray
*)tvbparse_data
;
978 xml_frame_t
*current_frame
= (xml_frame_t
*)g_ptr_array_index(stack
, stack
->len
- 1);
980 proto_tree_add_expert(current_frame
->tree
, current_frame
->pinfo
, &ei_xml_unrecognized_text
,
981 tok
->tvb
, tok
->offset
, tok
->len
);
987 static void init_xml_parser(void)
989 tvbparse_wanted_t
*want_name
=
990 tvbparse_chars(-1, 1, 0,
991 "abcdefghijklmnopqrstuvwxyz.-_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",
993 tvbparse_wanted_t
*want_attr_name
=
994 tvbparse_chars(-1, 1, 0,
995 "abcdefghijklmnopqrstuvwxyz.-_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789:",
998 tvbparse_wanted_t
*want_scoped_name
= tvbparse_set_seq(XML_SCOPED_NAME
, NULL
, NULL
, NULL
,
1000 tvbparse_char(-1, ":", NULL
, NULL
, NULL
),
1004 tvbparse_wanted_t
*want_tag_name
= tvbparse_set_oneof(0, NULL
, NULL
, NULL
,
1009 tvbparse_wanted_t
*want_attrib_value
= tvbparse_set_oneof(0, NULL
, NULL
, get_attrib_value
,
1010 tvbparse_quoted(-1, NULL
, NULL
, tvbparse_shrink_token_cb
, '\"', '\\'),
1011 tvbparse_quoted(-1, NULL
, NULL
, tvbparse_shrink_token_cb
, '\'', '\\'),
1012 tvbparse_chars(-1, 1, 0, "0123456789", NULL
, NULL
, NULL
),
1016 tvbparse_wanted_t
*want_attributes
= tvbparse_one_or_more(-1, NULL
, NULL
, NULL
,
1017 tvbparse_set_seq(-1, NULL
, NULL
, after_attrib
,
1019 tvbparse_char(-1, "=", NULL
, NULL
, NULL
),
1023 tvbparse_wanted_t
*want_stoptag
= tvbparse_set_oneof(-1, NULL
, NULL
, NULL
,
1024 tvbparse_char(-1, ">", NULL
, NULL
, after_open_tag
),
1025 tvbparse_string(-1, "/>", NULL
, NULL
, after_closed_tag
),
1028 tvbparse_wanted_t
*want_stopxmlpi
= tvbparse_string(-1, "?>", NULL
, NULL
, after_xmlpi
);
1030 tvbparse_wanted_t
*want_comment
= tvbparse_set_seq(hf_comment
, NULL
, NULL
, after_token
,
1031 tvbparse_string(-1, "<!--", NULL
, NULL
, NULL
),
1032 tvbparse_until(-1, NULL
, NULL
, NULL
,
1033 tvbparse_string(-1, "-->", NULL
, NULL
, NULL
),
1037 tvbparse_wanted_t
*want_cdatasection
= tvbparse_set_seq(hf_cdatasection
, NULL
, NULL
, after_token
,
1038 tvbparse_string(-1, "<![CDATA[", NULL
, NULL
, NULL
),
1039 tvbparse_until(-1, NULL
, NULL
, NULL
,
1040 tvbparse_string(-1, "]]>", NULL
, NULL
, NULL
),
1044 tvbparse_wanted_t
*want_xmlpi
= tvbparse_set_seq(hf_xmlpi
, NULL
, before_xmpli
, NULL
,
1045 tvbparse_string(-1, "<?", NULL
, NULL
, NULL
),
1047 tvbparse_set_oneof(-1, NULL
, NULL
, NULL
,
1049 tvbparse_set_seq(-1, NULL
, NULL
, NULL
,
1056 tvbparse_wanted_t
*want_closing_tag
= tvbparse_set_seq(0, NULL
, NULL
, after_untag
,
1057 tvbparse_char(-1, "<", NULL
, NULL
, NULL
),
1058 tvbparse_char(-1, "/", NULL
, NULL
, NULL
),
1060 tvbparse_char(-1, ">", NULL
, NULL
, NULL
),
1063 tvbparse_wanted_t
*want_doctype_start
= tvbparse_set_seq(-1, NULL
, before_dtd_doctype
, NULL
,
1064 tvbparse_char(-1, "<", NULL
, NULL
, NULL
),
1065 tvbparse_char(-1, "!", NULL
, NULL
, NULL
),
1066 tvbparse_casestring(-1, "DOCTYPE", NULL
, NULL
, NULL
),
1067 tvbparse_set_oneof(-1, NULL
, NULL
, NULL
,
1068 tvbparse_set_seq(-1, NULL
, NULL
, NULL
,
1070 tvbparse_char(-1, "[", NULL
, NULL
, NULL
),
1072 tvbparse_set_seq(-1, NULL
, NULL
, pop_stack
,
1074 tvbparse_set_oneof(-1, NULL
, NULL
, NULL
,
1075 tvbparse_casestring(-1, "PUBLIC", NULL
, NULL
, NULL
),
1076 tvbparse_casestring(-1, "SYSTEM", NULL
, NULL
, NULL
),
1078 tvbparse_until(-1, NULL
, NULL
, NULL
,
1079 tvbparse_char(-1, ">", NULL
, NULL
, NULL
),
1085 tvbparse_wanted_t
*want_dtd_tag
= tvbparse_set_seq(hf_dtd_tag
, NULL
, NULL
, after_token
,
1086 tvbparse_char(-1, "<", NULL
, NULL
, NULL
),
1087 tvbparse_char(-1, "!", NULL
, NULL
, NULL
),
1088 tvbparse_until(-1, NULL
, NULL
, NULL
,
1089 tvbparse_char(-1, ">", NULL
, NULL
, NULL
),
1093 tvbparse_wanted_t
*want_tag
= tvbparse_set_seq(-1, NULL
, before_tag
, NULL
,
1094 tvbparse_char(-1, "<", NULL
, NULL
, NULL
),
1096 tvbparse_set_oneof(-1, NULL
, NULL
, NULL
,
1097 tvbparse_set_seq(-1, NULL
, NULL
, NULL
,
1105 tvbparse_wanted_t
*want_dtd_close
= tvbparse_set_seq(-1, NULL
, NULL
, after_dtd_close
,
1106 tvbparse_char(-1, "]", NULL
, NULL
, NULL
),
1107 tvbparse_char(-1, ">", NULL
, NULL
, NULL
),
1110 want_ignore
= tvbparse_chars(-1, 1, 0, " \t\r\n", NULL
, NULL
, NULL
);
1113 want
= tvbparse_set_oneof(-1, NULL
, NULL
, NULL
,
1122 tvbparse_not_chars(XML_CDATA
, 1, 0, "<", NULL
, NULL
, after_token
),
1123 tvbparse_not_chars(-1, 1, 0, " \t\r\n", NULL
, NULL
, unrecognized_token
),
1126 want_heur
= tvbparse_set_oneof(-1, NULL
, NULL
, NULL
,
1138 static xml_ns_t
*xml_new_namespace(wmem_map_t
*hash
, const char *name
, ...)
1140 xml_ns_t
*ns
= wmem_new(wmem_epan_scope(), xml_ns_t
);
1144 ns
->name
= wmem_strdup(wmem_epan_scope(), name
);
1148 ns
->attributes
= wmem_map_new(wmem_epan_scope(), g_str_hash
, g_str_equal
);
1149 ns
->elements
= NULL
;
1153 while(( attr_name
= va_arg(ap
, char *) )) {
1154 int *hfp
= wmem_new(wmem_epan_scope(), int);
1156 wmem_map_insert(ns
->attributes
, wmem_strdup(wmem_epan_scope(), attr_name
), hfp
);
1161 wmem_map_insert(hash
, ns
->name
, ns
);
1167 static void add_xml_field(wmem_array_t
*hfs
, int *p_id
, const char *name
, const char *fqn
)
1169 hf_register_info hfri
;
1172 hfri
.hfinfo
.name
= name
;
1173 hfri
.hfinfo
.abbrev
= fqn
;
1174 hfri
.hfinfo
.type
= FT_STRING
;
1175 hfri
.hfinfo
.display
= BASE_NONE
;
1176 hfri
.hfinfo
.strings
= NULL
;
1177 hfri
.hfinfo
.bitmask
= 0x0;
1178 hfri
.hfinfo
.blurb
= NULL
;
1181 wmem_array_append_one(hfs
, hfri
);
1184 static void add_xml_attribute_names(void *k
, void *v
, void *p
)
1186 struct _attr_reg_data
*d
= (struct _attr_reg_data
*)p
;
1187 const char *basename
= wmem_strconcat(wmem_epan_scope(), d
->basename
, ".", (char *)k
, NULL
);
1189 add_xml_field(d
->hf
, (int*) v
, (char *)k
, basename
);
1193 static void add_xmlpi_namespace(void *k _U_
, void *v
, void *p
)
1195 xml_ns_t
*ns
= (xml_ns_t
*)v
;
1196 const char *basename
= wmem_strconcat(wmem_epan_scope(), (char *)p
, ".", ns
->name
, NULL
);
1197 int *ett_p
= &(ns
->ett
);
1198 struct _attr_reg_data d
;
1200 add_xml_field(hf_arr
, &(ns
->hf_tag
), basename
, basename
);
1202 g_array_append_val(ett_arr
, ett_p
);
1204 d
.basename
= basename
;
1207 wmem_map_foreach(ns
->attributes
, add_xml_attribute_names
, &d
);
1211 static void destroy_dtd_data(dtd_build_data_t
*dtd_data
)
1213 g_free(dtd_data
->proto_name
);
1214 g_free(dtd_data
->media_type
);
1215 g_free(dtd_data
->description
);
1216 g_free(dtd_data
->proto_root
);
1218 g_string_free(dtd_data
->error
, true);
1220 while(dtd_data
->elements
->len
) {
1221 dtd_named_list_t
*nl
= (dtd_named_list_t
*)g_ptr_array_remove_index_fast(dtd_data
->elements
, 0);
1222 g_ptr_array_free(nl
->list
, true);
1227 g_ptr_array_free(dtd_data
->elements
, true);
1229 while(dtd_data
->attributes
->len
) {
1230 dtd_named_list_t
*nl
= (dtd_named_list_t
*)g_ptr_array_remove_index_fast(dtd_data
->attributes
, 0);
1231 g_ptr_array_free(nl
->list
, true);
1236 g_ptr_array_free(dtd_data
->attributes
, true);
1241 static void copy_attrib_item(void *k
, void *v _U_
, void *p
)
1243 char *key
= (char *)wmem_strdup(wmem_epan_scope(), (const char *)k
);
1244 int *value
= wmem_new(wmem_epan_scope(), int);
1245 wmem_map_t
*dst
= (wmem_map_t
*)p
;
1248 wmem_map_insert(dst
, key
, value
);
1252 static wmem_map_t
*copy_attributes_hash(wmem_map_t
*src
)
1254 wmem_map_t
*dst
= wmem_map_new(wmem_epan_scope(), g_str_hash
, g_str_equal
);
1256 wmem_map_foreach(src
, copy_attrib_item
, dst
);
1261 static xml_ns_t
*duplicate_element(xml_ns_t
*orig
)
1263 xml_ns_t
*new_item
= wmem_new(wmem_epan_scope(), xml_ns_t
);
1266 new_item
->name
= wmem_strdup(wmem_epan_scope(), orig
->name
);
1267 new_item
->hf_tag
= -1;
1268 new_item
->hf_cdata
= -1;
1270 new_item
->attributes
= copy_attributes_hash(orig
->attributes
);
1271 new_item
->elements
= wmem_map_new(wmem_epan_scope(), g_str_hash
, g_str_equal
);
1272 new_item
->element_names
= g_ptr_array_new();
1274 for(i
=0; i
< orig
->element_names
->len
; i
++) {
1275 g_ptr_array_add(new_item
->element_names
,
1276 g_ptr_array_index(orig
->element_names
, i
));
1282 static char *fully_qualified_name(GPtrArray
*hier
, char *name
, char *proto_name
)
1285 wmem_strbuf_t
*s
= wmem_strbuf_new(wmem_epan_scope(), proto_name
);
1287 wmem_strbuf_append(s
, ".");
1289 for (i
= 1; i
< hier
->len
; i
++) {
1290 wmem_strbuf_append_printf(s
, "%s.", (char *)g_ptr_array_index(hier
, i
));
1293 wmem_strbuf_append(s
, name
);
1295 return wmem_strbuf_finalize(s
);
1299 // NOLINTNEXTLINE(misc-no-recursion)
1300 static xml_ns_t
*make_xml_hier(char *elem_name
,
1302 wmem_map_t
*elements
,
1313 bool recurred
= false;
1315 struct _attr_reg_data d
;
1317 if ( g_str_equal(elem_name
, root
->name
) ) {
1321 if (! ( orig
= (xml_ns_t
*)wmem_map_lookup(elements
, elem_name
) )) {
1322 g_string_append_printf(error
, "element '%s' is not defined\n", elem_name
);
1326 if (hier
->len
>= prefs
.gui_max_tree_depth
) {
1327 g_string_append_printf(error
, "hierarchy too deep: %u\n", hier
->len
);
1331 for (i
= 0; i
< hier
->len
; i
++) {
1332 if( (elem_name
) && (strcmp(elem_name
, (char *) g_ptr_array_index(hier
, i
) ) == 0 )) {
1341 fqn
= fully_qualified_name(hier
, elem_name
, proto_name
);
1343 fresh
= duplicate_element(orig
);
1346 add_xml_field(hfs
, &(fresh
->hf_tag
), wmem_strdup(wmem_epan_scope(), elem_name
), fqn
);
1347 add_xml_field(hfs
, &(fresh
->hf_cdata
), wmem_strdup(wmem_epan_scope(), elem_name
), fqn
);
1349 ett_p
= &fresh
->ett
;
1350 g_array_append_val(etts
, ett_p
);
1355 wmem_map_foreach(fresh
->attributes
, add_xml_attribute_names
, &d
);
1357 while(fresh
->element_names
->len
) {
1358 char *child_name
= (char *)g_ptr_array_remove_index(fresh
->element_names
, 0);
1359 xml_ns_t
*child_element
= NULL
;
1361 g_ptr_array_add(hier
, elem_name
);
1362 child_element
= make_xml_hier(child_name
, root
, elements
, hier
, error
, hfs
, etts
, proto_name
);
1363 g_ptr_array_remove_index_fast(hier
, hier
->len
- 1);
1365 if (child_element
) {
1366 wmem_map_insert(fresh
->elements
, child_element
->name
, child_element
);
1370 g_ptr_array_free(fresh
->element_names
, true);
1371 fresh
->element_names
= NULL
;
1375 static void free_elements(void *k _U_
, void *v
, void *p _U_
)
1377 xml_ns_t
*e
= (xml_ns_t
*)v
;
1379 while (e
->element_names
->len
) {
1380 g_free(g_ptr_array_remove_index(e
->element_names
, 0));
1383 g_ptr_array_free(e
->element_names
, true);
1386 static void register_dtd(dtd_build_data_t
*dtd_data
, GString
*errors
)
1388 wmem_map_t
*elements
= wmem_map_new(wmem_epan_scope(), g_str_hash
, g_str_equal
);
1389 char *root_name
= NULL
;
1390 xml_ns_t
*root_element
= NULL
;
1395 GPtrArray
*element_names
= g_ptr_array_new();
1397 /* we first populate elements with the those coming from the parser */
1398 while(dtd_data
->elements
->len
) {
1399 dtd_named_list_t
*nl
= (dtd_named_list_t
*)g_ptr_array_remove_index(dtd_data
->elements
, 0);
1400 xml_ns_t
*element
= wmem_new(wmem_epan_scope(), xml_ns_t
);
1402 /* we will use the first element found as root in case no other one was given. */
1403 if (root_name
== NULL
)
1404 root_name
= wmem_strdup(wmem_epan_scope(), nl
->name
);
1406 element
->name
= wmem_strdup(wmem_epan_scope(), nl
->name
);
1407 element
->element_names
= nl
->list
;
1408 element
->hf_tag
= -1;
1409 element
->hf_cdata
= -1;
1411 element
->attributes
= wmem_map_new(wmem_epan_scope(), g_str_hash
, g_str_equal
);
1412 element
->elements
= wmem_map_new(wmem_epan_scope(), g_str_hash
, g_str_equal
);
1414 if( wmem_map_lookup(elements
, element
->name
) ) {
1415 g_string_append_printf(errors
, "element %s defined more than once\n", element
->name
);
1416 free_elements(NULL
, element
, NULL
);
1418 wmem_map_insert(elements
, element
->name
, element
);
1419 g_ptr_array_add(element_names
, wmem_strdup(wmem_epan_scope(), element
->name
));
1426 /* then we add the attributes to its relative elements */
1427 while(dtd_data
->attributes
->len
) {
1428 dtd_named_list_t
*nl
= (dtd_named_list_t
*)g_ptr_array_remove_index(dtd_data
->attributes
, 0);
1429 xml_ns_t
*element
= (xml_ns_t
*)wmem_map_lookup(elements
, nl
->name
);
1432 while(nl
->list
->len
) {
1433 char *name
= (char *)g_ptr_array_remove_index(nl
->list
, 0);
1434 int *id_p
= wmem_new(wmem_epan_scope(), int);
1437 wmem_map_insert(element
->attributes
, wmem_strdup(wmem_epan_scope(), name
), id_p
);
1441 g_string_append_printf(errors
, "element %s is not defined\n", nl
->name
);
1445 g_ptr_array_free(nl
->list
, true);
1449 /* if a proto_root is defined in the dtd we'll use that as root */
1450 if( dtd_data
->proto_root
) {
1451 wmem_free(wmem_epan_scope(), root_name
);
1452 root_name
= wmem_strdup(wmem_epan_scope(), dtd_data
->proto_root
);
1455 /* we use a stack with the names to avoid recurring infinitely */
1456 hier
= g_ptr_array_new();
1459 * if a proto name was given in the dtd the dtd will be used as a protocol
1460 * or else the dtd will be loaded as a branch of the xml namespace
1462 if( ! dtd_data
->proto_name
) {
1465 g_ptr_array_add(hier
, wmem_strdup(wmem_epan_scope(), "xml"));
1468 * if we were given a proto_name the namespace will be registered
1469 * as an independent protocol with its own hf and ett arrays.
1471 hfs
= wmem_array_new(wmem_epan_scope(), sizeof(hf_register_info
));
1472 etts
= g_array_new(false, false, sizeof(int *));
1475 /* the root element of the dtd's namespace */
1476 root_element
= wmem_new(wmem_epan_scope(), xml_ns_t
);
1477 root_element
->name
= wmem_strdup(wmem_epan_scope(), root_name
);
1478 root_element
->fqn
= dtd_data
->proto_name
? wmem_strdup(wmem_epan_scope(), dtd_data
->proto_name
) : root_element
->name
;
1479 root_element
->hf_tag
= -1;
1480 root_element
->hf_cdata
= -1;
1481 root_element
->ett
= -1;
1482 root_element
->elements
= wmem_map_new(wmem_epan_scope(), g_str_hash
, g_str_equal
);
1483 root_element
->element_names
= element_names
;
1486 * we can either create a namespace as a flat namespace
1487 * in which all the elements are at the root level
1488 * or we can create a recursive namespace
1490 if (dtd_data
->recursion
) {
1491 xml_ns_t
*orig_root
;
1493 make_xml_hier(root_name
, root_element
, elements
, hier
, errors
, hfs
, etts
, dtd_data
->proto_name
);
1495 wmem_map_insert(root_element
->elements
, (void *)root_element
->name
, root_element
);
1497 orig_root
= (xml_ns_t
*)wmem_map_lookup(elements
, root_name
);
1499 /* if the root element was defined copy its attrlist to the child */
1501 struct _attr_reg_data d
;
1503 d
.basename
= dtd_data
->proto_name
;
1506 root_element
->attributes
= copy_attributes_hash(orig_root
->attributes
);
1507 wmem_map_foreach(root_element
->attributes
, add_xml_attribute_names
, &d
);
1509 root_element
->attributes
= wmem_map_new(wmem_epan_scope(), g_str_hash
, g_str_equal
);
1512 /* we then create all the sub hierarchies to catch the recurred cases */
1513 g_ptr_array_add(hier
, root_name
);
1515 while(root_element
->element_names
->len
) {
1516 curr_name
= (char *)g_ptr_array_remove_index(root_element
->element_names
, 0);
1518 if( ! wmem_map_lookup(root_element
->elements
, curr_name
) ) {
1519 xml_ns_t
*fresh
= make_xml_hier(curr_name
, root_element
, elements
, hier
, errors
,
1520 hfs
, etts
, dtd_data
->proto_name
);
1521 wmem_map_insert(root_element
->elements
, (void *)fresh
->name
, fresh
);
1526 /* a flat namespace */
1527 g_ptr_array_add(hier
, root_name
);
1529 root_element
->attributes
= wmem_map_new(wmem_epan_scope(), g_str_hash
, g_str_equal
);
1531 while(root_element
->element_names
->len
) {
1534 struct _attr_reg_data d
;
1536 curr_name
= (char *)g_ptr_array_remove_index(root_element
->element_names
, 0);
1537 fresh
= duplicate_element((xml_ns_t
*)wmem_map_lookup(elements
, curr_name
));
1538 fresh
->fqn
= fully_qualified_name(hier
, curr_name
, root_name
);
1540 add_xml_field(hfs
, &(fresh
->hf_tag
), curr_name
, fresh
->fqn
);
1541 add_xml_field(hfs
, &(fresh
->hf_cdata
), curr_name
, fresh
->fqn
);
1543 d
.basename
= fresh
->fqn
;
1546 wmem_map_foreach(fresh
->attributes
, add_xml_attribute_names
, &d
);
1548 ett_p
= &fresh
->ett
;
1549 g_array_append_val(etts
, ett_p
);
1551 g_ptr_array_free(fresh
->element_names
, true);
1553 wmem_map_insert(root_element
->elements
, (void *)fresh
->name
, fresh
);
1557 g_ptr_array_free(element_names
, true);
1559 g_ptr_array_free(hier
, true);
1562 * if we were given a proto_name the namespace will be registered
1563 * as an independent protocol.
1565 if( dtd_data
->proto_name
) {
1567 char *full_name
, *short_name
;
1569 if (dtd_data
->description
) {
1570 full_name
= wmem_strdup(wmem_epan_scope(), dtd_data
->description
);
1572 full_name
= wmem_strdup(wmem_epan_scope(), root_name
);
1574 short_name
= wmem_strdup_printf(wmem_epan_scope(),"%s_%s", dtd_data
->proto_name
, "dtd");
1576 ett_p
= &root_element
->ett
;
1577 g_array_append_val(etts
, ett_p
);
1579 add_xml_field(hfs
, &root_element
->hf_cdata
, root_element
->name
, root_element
->fqn
);
1581 root_element
->hf_tag
= proto_register_protocol(full_name
, short_name
, short_name
);
1582 proto_register_field_array(root_element
->hf_tag
, (hf_register_info
*)wmem_array_get_raw(hfs
), wmem_array_get_count(hfs
));
1583 proto_register_subtree_array((int **)etts
->data
, etts
->len
);
1585 if (dtd_data
->media_type
) {
1586 char* media_type
= wmem_strdup(wmem_epan_scope(), dtd_data
->media_type
);
1587 wmem_map_insert(media_types
, media_type
, root_element
);
1590 g_array_free(etts
, true);
1593 wmem_map_insert(xml_ns
.elements
, root_element
->name
, root_element
);
1594 wmem_map_foreach(elements
, free_elements
, NULL
);
1596 destroy_dtd_data(dtd_data
);
1597 wmem_free(wmem_epan_scope(), root_name
);
1600 # define DIRECTORY_T GDir
1601 # define FILE_T char
1602 # define OPENDIR_OP(name) g_dir_open(name, 0, dummy)
1603 # define DIRGETNEXT_OP(dir) g_dir_read_name(dir)
1604 # define GETFNAME_OP(file) (file);
1605 # define CLOSEDIR_OP(dir) g_dir_close(dir)
1607 static void init_xml_names(void)
1612 const char *filename
;
1615 GError
**dummy
= wmem_new(wmem_epan_scope(), GError
*);
1618 xmpli_names
= wmem_map_new(wmem_epan_scope(), g_str_hash
, g_str_equal
);
1619 media_types
= wmem_map_new(wmem_epan_scope(), g_str_hash
, g_str_equal
);
1621 unknown_ns
.elements
= xml_ns
.elements
= wmem_map_new(wmem_epan_scope(), g_str_hash
, g_str_equal
);
1622 unknown_ns
.attributes
= xml_ns
.attributes
= wmem_map_new(wmem_epan_scope(), g_str_hash
, g_str_equal
);
1624 xml_new_namespace(xmpli_names
, "xml", "version", "encoding", "standalone", NULL
);
1626 dirname
= get_persconffile_path("dtds", false);
1628 if (test_for_directory(dirname
) != EISDIR
) {
1629 /* Although dir isn't a directory it may still use memory */
1631 dirname
= get_datafile_path("dtds");
1634 if (test_for_directory(dirname
) == EISDIR
) {
1635 if ((dir
= OPENDIR_OP(dirname
)) != NULL
) {
1636 GString
*errors
= g_string_new("");
1638 while ((file
= DIRGETNEXT_OP(dir
)) != NULL
) {
1640 filename
= GETFNAME_OP(file
);
1642 namelen
= (int)strlen(filename
);
1643 if ( namelen
> 4 && ( g_ascii_strcasecmp(filename
+(namelen
-4), ".dtd") == 0 ) ) {
1645 dtd_build_data_t
*dtd_data
;
1647 g_string_truncate(errors
, 0);
1648 preparsed
= dtd_preparse(dirname
, filename
, errors
);
1651 report_failure("Dtd Preparser in file %s%c%s: %s",
1652 dirname
, G_DIR_SEPARATOR
, filename
, errors
->str
);
1656 dtd_data
= dtd_parse(preparsed
);
1658 g_string_free(preparsed
, true);
1660 if (dtd_data
->error
->len
) {
1661 report_failure("Dtd Parser in file %s%c%s: %s",
1662 dirname
, G_DIR_SEPARATOR
, filename
, dtd_data
->error
->str
);
1663 destroy_dtd_data(dtd_data
);
1667 register_dtd(dtd_data
, errors
);
1670 report_failure("Dtd Registration in file: %s%c%s: %s",
1671 dirname
, G_DIR_SEPARATOR
, filename
, errors
->str
);
1676 g_string_free(errors
, true);
1684 for(i
=0;i
<array_length(default_media_types
);i
++) {
1685 if( ! wmem_map_lookup(media_types
, default_media_types
[i
]) ) {
1686 wmem_map_insert(media_types
, (void *)default_media_types
[i
], &xml_ns
);
1690 wmem_map_foreach(xmpli_names
, add_xmlpi_namespace
, (void *)"xml.xmlpi");
1692 wmem_free(wmem_epan_scope(), dummy
);
1696 xml_init_protocol(void)
1698 // The longest encoding at https://www.iana.org/assignments/character-sets/character-sets.xml
1699 // is 45 characters (Extended_UNIX_Code_Packed_Format_for_Japanese).
1700 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);
1704 xml_cleanup_protocol(void) {
1705 g_regex_unref(encoding_pattern
);
1709 proto_register_xml(void)
1711 static int *ett_base
[] = {
1718 static hf_register_info hf_base
[] = {
1720 {"XMLPI", "xml.xmlpi",
1721 FT_STRING
, BASE_NONE
, NULL
, 0,
1725 {"CDATASection", "xml.cdatasection",
1726 FT_STRING
, BASE_NONE
, NULL
, 0,
1730 {"Comment", "xml.comment",
1731 FT_STRING
, BASE_NONE
, NULL
, 0,
1734 { &hf_unknowwn_attrib
,
1735 {"Attribute", "xml.attribute",
1736 FT_STRING
, BASE_NONE
, NULL
, 0,
1740 {"Doctype", "xml.doctype",
1741 FT_STRING
, BASE_NONE
, NULL
, 0,
1745 {"DTD Tag", "xml.dtdtag",
1746 FT_STRING
, BASE_NONE
, NULL
, 0,
1749 { &unknown_ns
.hf_cdata
,
1750 {"CDATA", "xml.cdata",
1751 FT_STRING
, BASE_NONE
, NULL
, 0, NULL
,
1754 { &unknown_ns
.hf_tag
,
1756 FT_STRING
, BASE_NONE
, NULL
, 0,
1760 {"Unknown", "xml.unknown",
1761 FT_STRING
, BASE_NONE
, NULL
, 0,
1766 static ei_register_info ei
[] = {
1767 { &ei_xml_closing_unopened_tag
, { "xml.closing_unopened_tag", PI_MALFORMED
, PI_ERROR
, "Closing an unopened tag", EXPFILL
}},
1768 { &ei_xml_closing_unopened_xmpli_tag
, { "xml.closing_unopened_xmpli_tag", PI_MALFORMED
, PI_ERROR
, "Closing an unopened xmpli tag", EXPFILL
}},
1769 { &ei_xml_unrecognized_text
, { "xml.unrecognized_text", PI_PROTOCOL
, PI_WARN
, "Unrecognized text", EXPFILL
}},
1772 module_t
*xml_module
;
1773 expert_module_t
* expert_xml
;
1775 hf_arr
= wmem_array_new(wmem_epan_scope(), sizeof(hf_register_info
));
1776 ett_arr
= g_array_new(false, false, sizeof(int *));
1778 wmem_array_append(hf_arr
, hf_base
, array_length(hf_base
));
1779 g_array_append_vals(ett_arr
, ett_base
, array_length(ett_base
));
1783 xml_ns
.hf_tag
= proto_register_protocol("eXtensible Markup Language", "XML", xml_ns
.name
);
1785 proto_register_field_array(xml_ns
.hf_tag
, (hf_register_info
*)wmem_array_get_raw(hf_arr
), wmem_array_get_count(hf_arr
));
1786 proto_register_subtree_array((int **)ett_arr
->data
, ett_arr
->len
);
1787 expert_xml
= expert_register_protocol(xml_ns
.hf_tag
);
1788 expert_register_field_array(expert_xml
, ei
, array_length(ei
));
1790 xml_module
= prefs_register_protocol(xml_ns
.hf_tag
, NULL
);
1791 prefs_register_obsolete_preference(xml_module
, "heuristic");
1792 prefs_register_obsolete_preference(xml_module
, "heuristic_tcp");
1793 prefs_register_obsolete_preference(xml_module
, "heuristic_udp");
1794 /* XXX - UCS-2, or UTF-16? */
1795 prefs_register_bool_preference(xml_module
, "heuristic_unicode", "Use Unicode in heuristics",
1796 "Try to recognize XML encoded in Unicode (UCS-2BE)",
1797 &pref_heuristic_unicode
);
1799 prefs_register_enum_preference(xml_module
, "default_encoding", "Default character encoding",
1800 "Use this charset if the 'encoding' attribute of XML declaration is missing."
1801 "Unsupported encoding will be replaced by the default UTF-8.",
1802 &pref_default_encoding
, ws_supported_mibenum_vals_character_sets_ev_array
, false);
1804 g_array_free(ett_arr
, true);
1806 register_init_routine(&xml_init_protocol
);
1807 register_cleanup_routine(&xml_cleanup_protocol
);
1809 xml_handle
= register_dissector("xml", dissect_xml
, xml_ns
.hf_tag
);
1815 add_dissector_media(void *k
, void *v _U_
, void *p _U_
)
1817 dissector_add_string("media_type", (char *)k
, xml_handle
);
1821 proto_reg_handoff_xml(void)
1823 wmem_map_foreach(media_types
, add_dissector_media
, NULL
);
1824 dissector_add_string("media_type.suffix", "xml", xml_handle
); /* RFC 7303 9.6 */
1825 dissector_add_uint_range_with_preference("tcp.port", "", xml_handle
);
1826 dissector_add_uint_range_with_preference("udp.port", XML_UDP_PORT_RANGE
, xml_handle
);
1828 gssapi_handle
= find_dissector_add_dependency("gssapi", xml_ns
.hf_tag
);
1830 heur_dissector_add("http", dissect_xml_heur
, "XML in HTTP", "xml_http", xml_ns
.hf_tag
, HEURISTIC_DISABLE
);
1831 heur_dissector_add("sip", dissect_xml_heur
, "XML in SIP", "xml_sip", xml_ns
.hf_tag
, HEURISTIC_DISABLE
);
1832 heur_dissector_add("media", dissect_xml_heur
, "XML in media", "xml_media", xml_ns
.hf_tag
, HEURISTIC_DISABLE
);
1833 heur_dissector_add("tcp", dissect_xml_heur
, "XML over TCP", "xml_tcp", xml_ns
.hf_tag
, HEURISTIC_DISABLE
);
1834 heur_dissector_add("udp", dissect_xml_heur
, "XML over UDP", "xml_udp", xml_ns
.hf_tag
, HEURISTIC_DISABLE
);
1836 heur_dissector_add("wtap_file", dissect_xml_heur
, "XML file", "xml_wtap", xml_ns
.hf_tag
, HEURISTIC_ENABLE
);
1838 dissector_add_uint("acdr.tls_application", TLS_APP_XML
, xml_handle
);
1842 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1847 * indent-tabs-mode: nil
1850 * vi: set shiftwidth=4 tabstop=8 expandtab:
1851 * :indentSize=4:tabSize=8:noTabs=true: