2 * Wireshark's XMPP dissector.
4 * Copyright 2011, Mariusz Okroj <okrojmariusz[]gmail.com>
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
15 #include <epan/packet.h>
16 #include <epan/conversation.h>
18 #include "packet-xmpp.h"
19 #include "packet-xmpp-core.h"
20 #include "packet-xmpp-jingle.h"
21 #include "packet-xmpp-other.h"
22 #include "packet-xmpp-gtalk.h"
23 #include "packet-xmpp-conference.h"
24 #include "packet-tls-utils.h"
26 tvbparse_wanted_t
*want_ignore
;
27 tvbparse_wanted_t
*want_stream_end_tag
;
28 tvbparse_wanted_t
*want_stream_end_with_ns
;
30 static void xmpp_error(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*element
);
31 static void xmpp_error_text(proto_tree
*tree
, tvbuff_t
*tvb
, xmpp_element_t
*element
);
33 static void xmpp_presence_status(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*element
);
35 static void xmpp_message_thread(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*element
);
36 static void xmpp_message_body(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*element
);
37 static void xmpp_message_subject(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*element
);
39 static void xmpp_failure_text(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*element
);
41 static void xmpp_features_mechanisms(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*packet
);
44 xmpp_init_parsers(void)
46 tvbparse_wanted_t
*want_name
;
47 tvbparse_wanted_t
*want_stream_end
;
49 want_name
= tvbparse_chars(2,1,0,"abcdefghijklmnopqrstuvwxyz.-_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",NULL
,NULL
,NULL
);
51 want_stream_end_with_ns
= tvbparse_set_seq(3, NULL
, NULL
, NULL
,
53 tvbparse_char(4, ":", NULL
, NULL
, NULL
),
57 want_stream_end
= tvbparse_set_oneof(5, NULL
, NULL
, NULL
,
58 want_stream_end_with_ns
,
62 want_ignore
= tvbparse_chars(1,1,0," \t\r\n",NULL
,NULL
,NULL
);
64 want_stream_end_tag
= tvbparse_set_seq(6, NULL
, NULL
, NULL
,
65 tvbparse_string(-1,"</",NULL
,NULL
,NULL
),
67 tvbparse_char(-1,">",NULL
,NULL
,NULL
),
72 xmpp_iq(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*packet
)
74 proto_item
*xmpp_iq_item
;
75 proto_tree
*xmpp_iq_tree
;
77 xmpp_attr_t
*attr_id
, *attr_type
;
79 xmpp_attr_info attrs_info
[] = {
80 {"xmlns", &hf_xmpp_xmlns
, false, false, NULL
, NULL
},
81 {"id", &hf_xmpp_id
, true, true, NULL
, NULL
},
82 {"type", &hf_xmpp_type
, true, true, NULL
, NULL
},
83 {"from", &hf_xmpp_from
, false, true, NULL
, NULL
},
84 {"to", &hf_xmpp_to
, false, true, NULL
, NULL
},
85 {"xml:lang", NULL
, false, false, NULL
, NULL
}
88 conversation_t
*conversation
;
89 xmpp_conv_info_t
*xmpp_info
;
90 xmpp_transaction_t
*reqresp_trans
;
92 xmpp_elem_info elems_info
[] = {
93 {NAME_AND_ATTR
, xmpp_name_attr_struct(pinfo
->pool
, "query", "xmlns","http://jabber.org/protocol/disco#items"), xmpp_disco_items_query
, ONE
},
94 {NAME_AND_ATTR
, xmpp_name_attr_struct(pinfo
->pool
, "query", "xmlns", "jabber:iq:roster"), xmpp_roster_query
, ONE
},
95 {NAME_AND_ATTR
, xmpp_name_attr_struct(pinfo
->pool
, "query", "xmlns", "http://jabber.org/protocol/disco#info"), xmpp_disco_info_query
, ONE
},
96 {NAME_AND_ATTR
, xmpp_name_attr_struct(pinfo
->pool
, "query", "xmlns", "http://jabber.org/protocol/bytestreams"), xmpp_bytestreams_query
, ONE
},
97 {NAME_AND_ATTR
, xmpp_name_attr_struct(pinfo
->pool
, "query", "xmlns", "http://jabber.org/protocol/muc#owner"), xmpp_muc_owner_query
, ONE
},
98 {NAME_AND_ATTR
, xmpp_name_attr_struct(pinfo
->pool
, "query", "xmlns", "http://jabber.org/protocol/muc#admin"), xmpp_muc_admin_query
, ONE
},
99 {NAME
, "bind", xmpp_iq_bind
, ONE
},
100 {NAME_AND_ATTR
, xmpp_name_attr_struct(pinfo
->pool
, "session", "xmlns", "urn:ietf:params:xml:ns:xmpp-session"), xmpp_session
, ONE
},
101 {NAME
, "vCard", xmpp_vcard
, ONE
},
102 {NAME
, "jingle", xmpp_jingle
, ONE
},
103 {NAME_AND_ATTR
, xmpp_name_attr_struct(pinfo
->pool
, "services", "xmlns", "http://jabber.org/protocol/jinglenodes"), xmpp_jinglenodes_services
, ONE
},
104 {NAME_AND_ATTR
, xmpp_name_attr_struct(pinfo
->pool
, "channel", "xmlns", "http://jabber.org/protocol/jinglenodes#channel"), xmpp_jinglenodes_channel
, ONE
},
105 {NAME_AND_ATTR
, xmpp_name_attr_struct(pinfo
->pool
, "open", "xmlns", "http://jabber.org/protocol/ibb"), xmpp_ibb_open
, ONE
},
106 {NAME_AND_ATTR
, xmpp_name_attr_struct(pinfo
->pool
, "close", "xmlns", "http://jabber.org/protocol/ibb"), xmpp_ibb_close
, ONE
},
107 {NAME_AND_ATTR
, xmpp_name_attr_struct(pinfo
->pool
, "data", "xmlns", "http://jabber.org/protocol/ibb"), xmpp_ibb_data
, ONE
},
108 {NAME
, "si", xmpp_si
, ONE
},
109 {NAME
, "error", xmpp_error
, ONE
},
110 {NAME_AND_ATTR
, xmpp_name_attr_struct(pinfo
->pool
, "session", "xmlns", "http://www.google.com/session"), xmpp_gtalk_session
, ONE
},
111 {NAME_AND_ATTR
, xmpp_name_attr_struct(pinfo
->pool
, "query", "xmlns","google:jingleinfo"), xmpp_gtalk_jingleinfo_query
, ONE
},
112 {NAME_AND_ATTR
, xmpp_name_attr_struct(pinfo
->pool
, "usersetting", "xmlns","google:setting"), xmpp_gtalk_usersetting
, ONE
},
113 {NAME_AND_ATTR
, xmpp_name_attr_struct(pinfo
->pool
, "query", "xmlns","jabber:iq:last"), xmpp_last_query
, ONE
},
114 {NAME_AND_ATTR
, xmpp_name_attr_struct(pinfo
->pool
, "query", "xmlns","jabber:iq:version"), xmpp_version_query
, ONE
},
115 {NAME_AND_ATTR
, xmpp_name_attr_struct(pinfo
->pool
, "query", "xmlns","google:mail:notify"), xmpp_gtalk_mail_query
, ONE
},
116 {NAME
, "mailbox", xmpp_gtalk_mail_mailbox
, ONE
},
117 {NAME
, "new-mail", xmpp_gtalk_mail_new_mail
, ONE
},
118 {NAME_AND_ATTR
, xmpp_name_attr_struct(pinfo
->pool
, "query", "xmlns","google:shared-status"), xmpp_gtalk_status_query
, ONE
},
119 {NAME
, "conference-info", xmpp_conference_info
, ONE
},
120 {NAME_AND_ATTR
, xmpp_name_attr_struct(pinfo
->pool
, "ping", "xmlns","urn:xmpp:ping"), xmpp_ping
, ONE
},
121 {NAME_AND_ATTR
, xmpp_name_attr_struct(pinfo
->pool
, "inputevt", "xmlns","http://jitsi.org/protocol/inputevt"), xmpp_jitsi_inputevt
, ONE
},
124 attr_id
= xmpp_get_attr(packet
, "id");
125 attr_type
= xmpp_get_attr(packet
, "type");
127 conversation
= find_or_create_conversation(pinfo
);
128 xmpp_info
= (xmpp_conv_info_t
*)conversation_get_proto_data(conversation
, proto_xmpp
);
130 xmpp_iq_item
= proto_tree_add_item(tree
, hf_xmpp_iq
, tvb
, packet
->offset
, packet
->length
, ENC_LITTLE_ENDIAN
);
131 xmpp_iq_tree
= proto_item_add_subtree(xmpp_iq_item
,ett_xmpp_iq
);
133 xmpp_display_attrs(xmpp_iq_tree
, packet
, pinfo
, tvb
, attrs_info
, array_length(attrs_info
));
136 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "IQ(%s) ", attr_type
?attr_type
->value
:"");
138 xmpp_display_elems(xmpp_iq_tree
, packet
, pinfo
, tvb
, elems_info
, array_length(elems_info
));
140 /*displays generated info such as req/resp tracking, jingle sid
141 * in each packet related to specified jingle session and IBB sid in packet related to it*/
142 if(xmpp_info
&& attr_id
)
144 char *jingle_sid
, *ibb_sid
, *gtalk_sid
;
146 jingle_sid
= (char *)wmem_tree_lookup_string(xmpp_info
->jingle_sessions
, attr_id
->value
, WMEM_TREE_STRING_NOCASE
);
149 proto_item
*it
= proto_tree_add_string(tree
, hf_xmpp_jingle_session
, tvb
, 0, 0, jingle_sid
);
150 proto_item_set_generated(it
);
153 ibb_sid
= (char *)wmem_tree_lookup_string(xmpp_info
->ibb_sessions
, attr_id
->value
, WMEM_TREE_STRING_NOCASE
);
156 proto_item
*it
= proto_tree_add_string(tree
, hf_xmpp_ibb
, tvb
, 0, 0, ibb_sid
);
157 proto_item_set_generated(it
);
160 gtalk_sid
= (char *)wmem_tree_lookup_string(xmpp_info
->gtalk_sessions
, attr_id
->value
, WMEM_TREE_STRING_NOCASE
);
163 proto_item
*it
= proto_tree_add_string(tree
, hf_xmpp_gtalk
, tvb
, 0, 0, gtalk_sid
);
164 proto_item_set_generated(it
);
167 reqresp_trans
= (xmpp_transaction_t
*)wmem_tree_lookup_string(xmpp_info
->req_resp
, attr_id
->value
, WMEM_TREE_STRING_NOCASE
);
168 /*displays request/response field in each iq packet*/
171 if (reqresp_trans
->req_frame
== pinfo
->num
) {
172 if (reqresp_trans
->resp_frame
) {
173 proto_item
*it
= proto_tree_add_uint(tree
, hf_xmpp_response_in
, tvb
, 0, 0, reqresp_trans
->resp_frame
);
174 proto_item_set_generated(it
);
177 expert_add_info(pinfo
, xmpp_iq_item
, &ei_xmpp_packet_without_response
);
181 if (reqresp_trans
->req_frame
) {
182 proto_item
*it
= proto_tree_add_uint(tree
, hf_xmpp_response_to
, tvb
, 0, 0, reqresp_trans
->req_frame
);
183 proto_item_set_generated(it
);
186 expert_add_info(pinfo
, xmpp_iq_item
, &ei_xmpp_packet_without_response
);
195 xmpp_error(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*element
)
197 proto_item
*error_item
;
198 proto_tree
*error_tree
;
200 xmpp_element_t
*text_element
, *cond_element
;
202 xmpp_attr_info attrs_info
[] = {
203 {"type", &hf_xmpp_error_type
, true, true, NULL
, NULL
},
204 {"code", &hf_xmpp_error_code
, false, true, NULL
, NULL
},
205 {"condition", &hf_xmpp_error_condition
, true, true, NULL
, NULL
} /*TODO: validate list to the condition element*/
210 xmpp_attr_t
*fake_condition
= NULL
;
212 error_info
= wmem_strdup(pinfo
->pool
, "Stanza error");
214 error_item
= proto_tree_add_item(tree
, hf_xmpp_error
, tvb
, element
->offset
, element
->length
, ENC_BIG_ENDIAN
);
215 error_tree
= proto_item_add_subtree(error_item
, ett_xmpp_query_item
);
217 cond_element
= xmpp_steal_element_by_attr(element
, "xmlns", "urn:ietf:params:xml:ns:xmpp-stanzas");
220 fake_condition
= xmpp_ep_init_attr_t(pinfo
->pool
, cond_element
->name
, cond_element
->offset
, cond_element
->length
);
221 g_hash_table_insert(element
->attrs
, (void *)"condition", fake_condition
);
223 error_info
= wmem_strdup_printf(pinfo
->pool
, "%s: %s;", error_info
, cond_element
->name
);
227 xmpp_display_attrs(error_tree
, element
, pinfo
, tvb
, attrs_info
, array_length(attrs_info
));
229 while((text_element
= xmpp_steal_element_by_name(element
, "text")) != NULL
)
231 xmpp_error_text(error_tree
, tvb
, text_element
);
233 error_info
= wmem_strdup_printf(pinfo
->pool
, "%s Text: %s", error_info
, text_element
->data
?text_element
->data
->value
:"");
236 expert_add_info_format(pinfo
, error_item
, &ei_xmpp_response
, "%s", error_info
);
238 xmpp_unknown(error_tree
, tvb
, pinfo
, element
);
242 xmpp_error_text(proto_tree
*tree
, tvbuff_t
*tvb
, xmpp_element_t
*element
)
244 proto_tree_add_string(tree
, hf_xmpp_error_text
, tvb
, element
->offset
, element
->length
, element
->data
?element
->data
->value
:"");
249 xmpp_presence(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*packet
)
251 proto_item
*presence_item
;
252 proto_tree
*presence_tree
;
254 static const char *type_enums
[] = {"error", "probe", "subscribe", "subscribed",
255 "unavailable", "unsubscribe", "unsubscribed"};
256 xmpp_array_t
*type_array
= xmpp_ep_init_array_t(pinfo
->pool
, type_enums
, array_length(type_enums
));
258 static const char *show_enums
[] = {"away", "chat", "dnd", "xa"};
259 xmpp_array_t
*show_array
= xmpp_ep_init_array_t(pinfo
->pool
, show_enums
, array_length(show_enums
));
261 xmpp_attr_info attrs_info
[] = {
262 {"from", &hf_xmpp_from
, false, false, NULL
, NULL
},
263 {"id", &hf_xmpp_id
, false, true, NULL
, NULL
},
264 {"to", &hf_xmpp_to
, false, false, NULL
, NULL
},
265 {"type", &hf_xmpp_type
, false, true, xmpp_val_enum_list
, type_array
},
266 {"xml:lang", NULL
, false, false, NULL
,NULL
},
267 {"show", &hf_xmpp_presence_show
, false, true, xmpp_val_enum_list
, show_array
},
268 {"priority", NULL
, false, false, NULL
, NULL
}
271 xmpp_elem_info elems_info
[] = {
272 {NAME
, "status", xmpp_presence_status
, MANY
},
273 {NAME_AND_ATTR
, xmpp_name_attr_struct(pinfo
->pool
, "c","xmlns","http://jabber.org/protocol/caps"), xmpp_presence_caps
, ONE
},
274 {NAME
, "delay", xmpp_delay
, ONE
},
275 {NAME_AND_ATTR
, xmpp_name_attr_struct(pinfo
->pool
, "x","xmlns", "jabber:x:delay"), xmpp_delay
, ONE
},
276 {NAME_AND_ATTR
, xmpp_name_attr_struct(pinfo
->pool
, "x","xmlns", "vcard-temp:x:update"), xmpp_vcard_x_update
, ONE
},
277 {NAME_AND_ATTR
, xmpp_name_attr_struct(pinfo
->pool
, "x","xmlns","http://jabber.org/protocol/muc"), xmpp_muc_x
, ONE
},
278 {NAME_AND_ATTR
, xmpp_name_attr_struct(pinfo
->pool
, "x","xmlns","http://jabber.org/protocol/muc#user"), xmpp_muc_user_x
, ONE
},
279 {NAME
, "error", xmpp_error
, ONE
},
280 {NAME_AND_ATTR
, xmpp_name_attr_struct(pinfo
->pool
, "query", "xmlns","jabber:iq:last"), xmpp_last_query
, ONE
}
284 xmpp_element_t
*show
, *priority
;
286 col_set_str(pinfo
->cinfo
, COL_INFO
, "PRESENCE ");
288 presence_item
= proto_tree_add_item(tree
, hf_xmpp_presence
, tvb
, packet
->offset
, packet
->length
, ENC_BIG_ENDIAN
);
289 presence_tree
= proto_item_add_subtree(presence_item
, ett_xmpp_presence
);
291 if((show
= xmpp_steal_element_by_name(packet
, "show"))!=NULL
)
293 xmpp_attr_t
*fake_show
= xmpp_ep_init_attr_t(pinfo
->pool
, show
->data
?show
->data
->value
:"",show
->offset
, show
->length
);
294 g_hash_table_insert(packet
->attrs
, (void *)"show", fake_show
);
297 if((priority
= xmpp_steal_element_by_name(packet
, "priority"))!=NULL
)
299 xmpp_attr_t
*fake_priority
= xmpp_ep_init_attr_t(pinfo
->pool
, priority
->data
?priority
->data
->value
:"",priority
->offset
, priority
->length
);
300 g_hash_table_insert(packet
->attrs
, (void *)"priority", fake_priority
);
302 xmpp_display_attrs(presence_tree
, packet
, pinfo
, tvb
, attrs_info
, array_length(attrs_info
));
304 xmpp_display_elems(presence_tree
, packet
, pinfo
, tvb
, elems_info
, array_length(elems_info
));
308 xmpp_presence_status(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*element
)
310 proto_item
*status_item
;
311 proto_tree
*status_tree
;
313 xmpp_attr_info attrs_info
[] = {
314 {"xml:lang", NULL
, false, true, NULL
, NULL
},
315 {"value", NULL
, true, true, NULL
, NULL
}
318 xmpp_attr_t
*fake_value
;
320 status_item
= proto_tree_add_item(tree
, hf_xmpp_presence_status
, tvb
, element
->offset
, element
->length
, ENC_BIG_ENDIAN
);
321 status_tree
= proto_item_add_subtree(status_item
, ett_xmpp_presence_status
);
324 fake_value
= xmpp_ep_init_attr_t(pinfo
->pool
, element
->data
->value
, element
->offset
, element
->length
);
326 fake_value
= xmpp_ep_init_attr_t(pinfo
->pool
, "(empty)", element
->offset
, element
->length
);
329 g_hash_table_insert(element
->attrs
, (void *)"value", fake_value
);
331 xmpp_display_attrs(status_tree
, element
, pinfo
, tvb
, attrs_info
, array_length(attrs_info
));
333 xmpp_unknown(status_tree
, tvb
, pinfo
, element
);
338 xmpp_message(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*packet
)
340 proto_item
*message_item
;
341 proto_tree
*message_tree
;
343 static const char *type_enums
[] = {"chat", "error", "groupchat", "headline", "normal"};
344 xmpp_array_t
*type_array
= xmpp_ep_init_array_t(pinfo
->pool
, type_enums
, array_length(type_enums
));
346 xmpp_attr_info attrs_info
[] = {
347 {"from", &hf_xmpp_from
, false, false, NULL
, NULL
},
348 {"id", &hf_xmpp_id
, false, true, NULL
, NULL
},
349 {"to", &hf_xmpp_to
, false, false, NULL
, NULL
},
350 {"type", &hf_xmpp_type
, false, true, xmpp_val_enum_list
, type_array
},
351 {"xml:lang", NULL
, false, false, NULL
,NULL
},
352 {"chatstate", &hf_xmpp_message_chatstate
, false, true, NULL
, NULL
}
355 xmpp_elem_info elems_info
[] = {
356 {NAME_AND_ATTR
, xmpp_name_attr_struct(pinfo
->pool
, "data", "xmlns", "http://jabber.org/protocol/ibb"), xmpp_ibb_data
, ONE
},
357 {NAME
, "thread", xmpp_message_thread
, ONE
},
358 {NAME
, "body", xmpp_message_body
, MANY
},
359 {NAME
, "subject", xmpp_message_subject
, MANY
},
360 {NAME
, "delay", xmpp_delay
, ONE
},
361 {NAME_AND_ATTR
, xmpp_name_attr_struct(pinfo
->pool
, "x","xmlns","jabber:x:event"), xmpp_x_event
, ONE
},
362 {NAME_AND_ATTR
, xmpp_name_attr_struct(pinfo
->pool
, "x","xmlns","http://jabber.org/protocol/muc#user"), xmpp_muc_user_x
, ONE
},
363 {NAME_AND_ATTR
, xmpp_name_attr_struct(pinfo
->pool
, "x","xmlns","google:nosave"), xmpp_gtalk_nosave_x
, ONE
},
364 {NAME
, "error", xmpp_error
, ONE
}
367 xmpp_element_t
*chatstate
;
371 conversation_t
*conversation
;
372 xmpp_conv_info_t
*xmpp_info
;
374 col_set_str(pinfo
->cinfo
, COL_INFO
, "MESSAGE ");
376 id
= xmpp_get_attr(packet
, "id");
378 conversation
= find_or_create_conversation(pinfo
);
379 xmpp_info
= (xmpp_conv_info_t
*)conversation_get_proto_data(conversation
, proto_xmpp
);
381 message_item
= proto_tree_add_item(tree
, hf_xmpp_message
, tvb
, packet
->offset
, packet
->length
, ENC_BIG_ENDIAN
);
382 message_tree
= proto_item_add_subtree(message_item
, ett_xmpp_message
);
384 if((chatstate
= xmpp_steal_element_by_attr(packet
, "xmlns", "http://jabber.org/protocol/chatstates"))!=NULL
)
386 xmpp_attr_t
*fake_chatstate_attr
= xmpp_ep_init_attr_t(pinfo
->pool
, chatstate
->name
, chatstate
->offset
, chatstate
->length
);
387 g_hash_table_insert(packet
->attrs
, (void *)"chatstate", fake_chatstate_attr
);
390 xmpp_display_attrs(message_tree
, packet
, pinfo
, tvb
, attrs_info
, array_length(attrs_info
));
392 xmpp_display_elems(message_tree
, packet
, pinfo
, tvb
, elems_info
, array_length(elems_info
));
394 /*Displays data about IBB session*/
399 ibb_sid
= (char *)wmem_tree_lookup_string(xmpp_info
->ibb_sessions
, id
->value
, WMEM_TREE_STRING_NOCASE
);
402 proto_item
*it
= proto_tree_add_string(tree
, hf_xmpp_ibb
, tvb
, 0, 0, ibb_sid
);
403 proto_item_set_generated(it
);
410 xmpp_message_body(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*element
)
412 proto_item
*body_item
;
413 proto_tree
*body_tree
;
415 xmpp_attr_info attrs_info
[] = {
416 {"xml:lang", NULL
, false, true, NULL
, NULL
},
417 {"value", NULL
, true, true, NULL
, NULL
}
420 xmpp_attr_t
*fake_data_attr
;
422 body_item
= proto_tree_add_item(tree
, hf_xmpp_message_body
, tvb
, element
->offset
, element
->length
, ENC_BIG_ENDIAN
);
423 body_tree
= proto_item_add_subtree(body_item
, ett_xmpp_message_body
);
425 fake_data_attr
= xmpp_ep_init_attr_t(pinfo
->pool
, element
->data
?element
->data
->value
:"", element
->offset
, element
->length
);
426 g_hash_table_insert(element
->attrs
, (void *)"value", fake_data_attr
);
429 xmpp_display_attrs(body_tree
, element
, pinfo
, tvb
, attrs_info
, array_length(attrs_info
));
431 xmpp_unknown(body_tree
, tvb
, pinfo
, element
);
435 xmpp_message_subject(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*element
) {
436 proto_item
*subject_item
;
437 proto_tree
*subject_tree
;
439 xmpp_attr_info attrs_info
[] = {
440 {"xml:lang", NULL
, false, true, NULL
, NULL
},
441 {"value", NULL
, true, false, NULL
, NULL
}
444 xmpp_attr_t
*fake_data_attr
;
446 subject_item
= proto_tree_add_item(tree
, hf_xmpp_message_subject
, tvb
, element
->offset
, element
->length
, ENC_BIG_ENDIAN
);
447 subject_tree
= proto_item_add_subtree(subject_item
, ett_xmpp_message_subject
);
449 fake_data_attr
= xmpp_ep_init_attr_t(pinfo
->pool
, element
->data
?element
->data
->value
:"", element
->offset
, element
->length
);
450 g_hash_table_insert(element
->attrs
, (void *)"value", fake_data_attr
);
453 xmpp_display_attrs(subject_tree
, element
, pinfo
, tvb
, attrs_info
, array_length(attrs_info
));
455 xmpp_unknown(subject_tree
, tvb
, pinfo
, element
);
459 xmpp_message_thread(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*element
)
461 proto_item
*thread_item
;
462 proto_tree
*thread_tree
;
464 xmpp_attr_info attrs_info
[] = {
465 {"parent", &hf_xmpp_message_thread_parent
, false, true, NULL
, NULL
},
466 {"value", NULL
, true, true, NULL
, NULL
}
469 xmpp_attr_t
*fake_value
;
471 thread_item
= proto_tree_add_item(tree
, hf_xmpp_message_thread
, tvb
, element
->offset
, element
->length
, ENC_BIG_ENDIAN
);
472 thread_tree
= proto_item_add_subtree(thread_item
, ett_xmpp_message_thread
);
474 fake_value
= xmpp_ep_init_attr_t(pinfo
->pool
, element
->data
?element
->data
->value
:"", element
->offset
, element
->length
);
475 g_hash_table_insert(element
->attrs
, (void *)"value", fake_value
);
478 xmpp_display_attrs(thread_tree
, element
, pinfo
, tvb
, attrs_info
, array_length(attrs_info
));
480 xmpp_unknown(thread_tree
, tvb
, pinfo
, element
);
484 xmpp_auth(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*packet
)
486 proto_item
*auth_item
;
487 proto_tree
*auth_tree
;
489 xmpp_attr_info_ext attrs_info
[]={
490 {"urn:ietf:params:xml:ns:xmpp-sasl", {"xmlns", &hf_xmpp_xmlns
, true, true, NULL
, NULL
}},
491 {"urn:ietf:params:xml:ns:xmpp-sasl", {"mechanism", NULL
, true, true, NULL
, NULL
}},
492 {"http://www.google.com/talk/protocol/auth", {"xmlns", &hf_xmpp_xmlns
, true, true, NULL
, NULL
}},
493 {"http://www.google.com/talk/protocol/auth", {"client-uses-full-bind-result", NULL
, true, true, NULL
, NULL
}},
496 col_set_str(pinfo
->cinfo
, COL_INFO
, "AUTH");
498 auth_item
= proto_tree_add_item(tree
, hf_xmpp_auth
, tvb
, packet
->offset
, packet
->length
, ENC_BIG_ENDIAN
);
499 auth_tree
= proto_item_add_subtree(auth_item
, ett_xmpp_auth
);
501 xmpp_display_attrs_ext(auth_tree
, packet
, pinfo
, tvb
, attrs_info
, array_length(attrs_info
));
503 xmpp_cdata(auth_tree
, tvb
, packet
, -1);
505 xmpp_unknown(auth_tree
, tvb
, pinfo
, packet
);
509 xmpp_challenge_response_success(proto_tree
*tree
, tvbuff_t
*tvb
,
510 packet_info
*pinfo
, xmpp_element_t
*packet
, expert_field
* ei
, int ett
, const char *col_info
)
515 xmpp_attr_info attrs_info
[] = {
516 {"xmlns", &hf_xmpp_xmlns
, true, true, NULL
, NULL
}
519 col_set_str(pinfo
->cinfo
, COL_INFO
, col_info
);
521 item
= proto_tree_add_expert(tree
, pinfo
, ei
, tvb
, packet
->offset
, packet
->length
);
522 subtree
= proto_item_add_subtree(item
, ett
);
524 xmpp_display_attrs(subtree
, packet
, pinfo
, tvb
, attrs_info
, array_length(attrs_info
));
525 xmpp_cdata(subtree
, tvb
, packet
, -1);
527 xmpp_unknown(subtree
, tvb
, pinfo
, packet
);
531 xmpp_failure(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*packet
)
533 proto_item
*fail_item
;
534 proto_tree
*fail_tree
;
536 xmpp_attr_info attrs_info
[] = {
537 {"xmlns", &hf_xmpp_xmlns
, true, true, NULL
, NULL
},
538 {"condition", NULL
, false, true, NULL
, NULL
}
541 static const char *fail_names
[] = {"aborted","account-disabled", "credentials-expired",
542 "encryption-required", "incorrect-encoding", "invalid-authzid", "invalid-mechanism",
543 "malformed-request", "mechanism-too-weak", "not-authorized", "temporary-auth-failure",
547 xmpp_element_t
*fail_condition
, *text
;
549 col_set_str(pinfo
->cinfo
, COL_INFO
, "FAILURE ");
551 fail_item
= proto_tree_add_item(tree
, hf_xmpp_failure
, tvb
, packet
->offset
, packet
->length
, ENC_BIG_ENDIAN
);
552 fail_tree
= proto_item_add_subtree(fail_item
, ett_xmpp_failure
);
554 if((fail_condition
= xmpp_steal_element_by_names(packet
, fail_names
, array_length(fail_names
)))!=NULL
)
556 xmpp_attr_t
*fake_cond
= xmpp_ep_init_attr_t(pinfo
->pool
, fail_condition
->name
, fail_condition
->offset
, fail_condition
->length
);
557 g_hash_table_insert(packet
->attrs
, (void *)"condition", fake_cond
);
560 if((text
= xmpp_steal_element_by_name(packet
, "text"))!=NULL
)
562 xmpp_failure_text(fail_tree
, tvb
, pinfo
, text
);
565 xmpp_display_attrs(fail_tree
, packet
, pinfo
, tvb
, attrs_info
, array_length(attrs_info
));
567 xmpp_unknown(fail_tree
, tvb
, pinfo
, packet
);
571 xmpp_failure_text(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*element
)
573 xmpp_attr_t
*lang
= xmpp_get_attr(element
,"xml:lang");
575 proto_tree_add_string_format(tree
, hf_xmpp_failure_text
, tvb
, element
->offset
, element
->length
,
576 element
->data
?element
->data
->value
:"", "TEXT%s: %s",
577 lang
?wmem_strdup_printf(pinfo
->pool
, "(%s)",lang
->value
):"",
578 element
->data
?element
->data
->value
:"");
582 xmpp_xml_header(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo _U_
, xmpp_element_t
*packet
)
584 col_set_str(pinfo
->cinfo
, COL_INFO
, "XML ");
585 proto_tree_add_string(tree
, hf_xmpp_xml_header_version
, tvb
, packet
->offset
, packet
->length
, "1.0");
589 xmpp_stream(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*packet
)
591 proto_item
*stream_item
;
592 proto_tree
*stream_tree
;
594 xmpp_attr_info_ext attrs_info
[] = {
595 {"http://etherx.jabber.org/streams",{"xmlns", &hf_xmpp_xmlns
, false, true, NULL
, NULL
}},
596 {"http://etherx.jabber.org/streams",{"version", NULL
, false, true, NULL
, NULL
}},
597 {"http://etherx.jabber.org/streams",{"from", NULL
, false, true, NULL
, NULL
}},
598 {"http://etherx.jabber.org/streams",{"to", NULL
, false, true, NULL
, NULL
}},
599 {"http://etherx.jabber.org/streams",{"id", NULL
, false, true, NULL
, NULL
}},
600 {"http://etherx.jabber.org/streams",{"xml:lang", NULL
, false, true, NULL
, NULL
}},
601 {"jabber:client",{"xmlns", &hf_xmpp_xmlns
, false, true, NULL
, NULL
}},
605 col_set_str(pinfo
->cinfo
, COL_INFO
, "STREAM ");
607 stream_item
= proto_tree_add_item(tree
, hf_xmpp_stream
, tvb
, packet
->offset
, packet
->length
, ENC_BIG_ENDIAN
);
608 stream_tree
= proto_item_add_subtree(stream_item
, ett_xmpp_stream
);
610 xmpp_display_attrs_ext(stream_tree
, packet
, pinfo
, tvb
, attrs_info
, array_length(attrs_info
));
611 xmpp_display_elems(stream_tree
, packet
, pinfo
, tvb
, NULL
, 0);
614 /*returns true if stream end occurs*/
616 xmpp_stream_close(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
* pinfo
)
619 tvbparse_elem_t
*elem
;
621 tt
= tvbparse_init(pinfo
->pool
, tvb
,0,-1,NULL
,want_ignore
);
623 if((elem
= tvbparse_get(tt
,want_stream_end_tag
))!=NULL
)
625 proto_tree_add_item(tree
, hf_xmpp_stream_end
, tvb
, elem
->offset
, elem
->len
, ENC_NA
);
626 col_set_str(pinfo
->cinfo
, COL_INFO
, "STREAM END");
634 xmpp_features(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*packet
)
636 proto_item
*features_item
;
637 proto_tree
*features_tree
;
639 xmpp_elem_info elems_info
[] = {
640 {NAME
, "mechanisms", xmpp_features_mechanisms
, MANY
}
643 features_item
= proto_tree_add_item(tree
, hf_xmpp_features
, tvb
, packet
->offset
, packet
->length
,
645 features_tree
= proto_item_add_subtree(features_item
, ett_xmpp_features
);
647 col_set_str(pinfo
->cinfo
, COL_INFO
, "FEATURES ");
649 xmpp_display_attrs(features_tree
, packet
, pinfo
, tvb
, NULL
, 0);
650 xmpp_display_elems(features_tree
, packet
, pinfo
, tvb
, elems_info
, array_length(elems_info
));
654 xmpp_features_mechanisms(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, xmpp_element_t
*packet
)
656 proto_tree
*mechanisms_tree
;
658 xmpp_attr_info attrs_info
[] = {
659 {"xmlns", &hf_xmpp_xmlns
, true, true, NULL
, NULL
}
662 xmpp_elem_info elems_info
[] = {
663 {NAME
, "mechanism", xmpp_simple_cdata_elem
, MANY
},
666 mechanisms_tree
= proto_tree_add_subtree(tree
, tvb
, packet
->offset
, packet
->length
, ett_xmpp_features_mechanisms
, NULL
, "MECHANISMS");
668 xmpp_display_attrs(mechanisms_tree
, packet
, pinfo
, tvb
, attrs_info
, array_length(attrs_info
));
669 xmpp_display_elems(mechanisms_tree
, packet
, pinfo
, tvb
, elems_info
, array_length(elems_info
));
673 xmpp_starttls(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
,
674 xmpp_element_t
*packet
, xmpp_conv_info_t
*xmpp_info
)
676 proto_item
*tls_item
;
677 proto_tree
*tls_tree
;
679 xmpp_attr_info attrs_info
[] = {
680 {"xmlns", &hf_xmpp_xmlns
, true, true, NULL
, NULL
},
683 col_set_str(pinfo
->cinfo
, COL_INFO
, "STARTTLS ");
685 tls_item
= proto_tree_add_item(tree
, hf_xmpp_starttls
, tvb
, packet
->offset
, packet
->length
, ENC_BIG_ENDIAN
);
686 tls_tree
= proto_item_add_subtree(tls_item
, ett_xmpp_starttls
);
688 if (xmpp_info
->ssl_start
&& xmpp_info
->ssl_start
!= pinfo
->num
) {
689 expert_add_info_format(pinfo
, tls_item
, &ei_xmpp_starttls_already_in_frame
, "Already saw STARTTLS in frame %u", xmpp_info
->ssl_start
);
692 xmpp_info
->ssl_start
= pinfo
->num
;
695 xmpp_display_attrs(tls_tree
, packet
, pinfo
, tvb
, attrs_info
, array_length(attrs_info
));
696 xmpp_display_elems(tls_tree
, packet
, pinfo
, tvb
, NULL
, 0);
700 xmpp_proceed(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
,
701 xmpp_element_t
*packet
, xmpp_conv_info_t
*xmpp_info
)
703 proto_item
*proceed_item
;
704 proto_tree
*proceed_tree
;
705 uint32_t ssl_proceed
;
707 xmpp_attr_info attrs_info
[] = {
708 {"xmlns", &hf_xmpp_xmlns
, true, true, NULL
, NULL
},
711 col_set_str(pinfo
->cinfo
, COL_INFO
, "PROCEED ");
713 proceed_item
= proto_tree_add_item(tree
, hf_xmpp_proceed
, tvb
, packet
->offset
, packet
->length
, ENC_BIG_ENDIAN
);
714 proceed_tree
= proto_item_add_subtree(proceed_item
, ett_xmpp_proceed
);
716 if (!xmpp_info
->ssl_start
) {
717 expert_add_info(pinfo
, proceed_item
, &ei_xmpp_starttls_missing
);
721 ssl_starttls_ack(find_dissector("tls"), pinfo
, find_dissector("xmpp"));
722 if (ssl_proceed
> 0 && ssl_proceed
!= pinfo
->num
) {
723 expert_add_info_format(pinfo
, proceed_item
, &ei_xmpp_proceed_already_in_frame
,
724 "Already saw PROCEED in frame %u", ssl_proceed
);
727 xmpp_display_attrs(proceed_tree
, packet
, pinfo
, tvb
, attrs_info
, array_length(attrs_info
));
728 xmpp_display_elems(proceed_tree
, packet
, pinfo
, tvb
, NULL
, 0);
731 * Editor modelines - https://www.wireshark.org/tools/modelines.html
736 * indent-tabs-mode: nil
739 * ex: set shiftwidth=4 tabstop=8 expandtab:
740 * :indentSize=4:tabSize=8:noTabs=true: