2 * Routines for DCERPC packet disassembly
3 * Copyright 2001, Todd Sabin <tas@webspan.net>
4 * Copyright 2003, Tim Potter <tpot@samba.org>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 /* The DCE RPC specification can be found at:
28 * http://www.opengroup.org/dce/
39 #include <epan/packet.h>
40 #include <epan/dissectors/packet-dcerpc.h>
41 #include <epan/conversation.h>
42 #include <epan/prefs.h>
43 #include <epan/reassemble.h>
45 #include <epan/emem.h>
46 #include <epan/dissectors/packet-frame.h>
47 #include <epan/dissectors/packet-dcerpc-nt.h>
48 #include <epan/expert.h>
49 #include <epan/strutil.h>
51 static int dcerpc_tap = -1;
54 static const value_string pckt_vals[] = {
55 { PDU_REQ, "Request"},
57 { PDU_RESP, "Response"},
58 { PDU_FAULT, "Fault"},
59 { PDU_WORKING, "Working"},
60 { PDU_NOCALL, "Nocall"},
61 { PDU_REJECT, "Reject"},
63 { PDU_CL_CANCEL, "Cl_cancel"},
65 { PDU_CANCEL_ACK, "Cancel_ack"},
67 { PDU_BIND_ACK, "Bind_ack"},
68 { PDU_BIND_NAK, "Bind_nak"},
69 { PDU_ALTER, "Alter_context"},
70 { PDU_ALTER_ACK, "Alter_context_resp"},
71 { PDU_AUTH3, "AUTH3"},
72 { PDU_SHUTDOWN, "Shutdown"},
73 { PDU_CO_CANCEL, "Co_cancel"},
74 { PDU_ORPHANED, "Orphaned"},
78 static const value_string drep_byteorder_vals[] = {
80 { 1, "Little-endian" },
84 static const value_string drep_character_vals[] = {
90 #define DCE_RPC_DREP_FP_IEEE 0
91 #define DCE_RPC_DREP_FP_VAX 1
92 #define DCE_RPC_DREP_FP_CRAY 2
93 #define DCE_RPC_DREP_FP_IBM 3
95 static const value_string drep_fp_vals[] = {
96 { DCE_RPC_DREP_FP_IEEE, "IEEE" },
97 { DCE_RPC_DREP_FP_VAX, "VAX" },
98 { DCE_RPC_DREP_FP_CRAY, "Cray" },
99 { DCE_RPC_DREP_FP_IBM, "IBM" },
104 * Authentication services.
106 static const value_string authn_protocol_vals[] = {
107 { DCE_C_RPC_AUTHN_PROTOCOL_NONE, "None" },
108 { DCE_C_RPC_AUTHN_PROTOCOL_KRB5, "Kerberos 5" },
109 { DCE_C_RPC_AUTHN_PROTOCOL_SPNEGO, "SPNEGO" },
110 { DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP, "NTLMSSP" },
111 { DCE_C_RPC_AUTHN_PROTOCOL_GSS_SCHANNEL, "SCHANNEL SSP" },
112 { DCE_C_RPC_AUTHN_PROTOCOL_GSS_KERBEROS, "Kerberos SSP" },
113 { DCE_C_RPC_AUTHN_PROTOCOL_DPA,
114 "Distributed Password Authentication SSP"},
115 { DCE_C_RPC_AUTHN_PROTOCOL_MSN, "MSN SSP"},
116 { DCE_C_RPC_AUTHN_PROTOCOL_DIGEST, "Digest SSP"},
117 { DCE_C_RPC_AUTHN_PROTOCOL_SEC_CHAN,"NETLOGON Secure Channel" },
118 { DCE_C_RPC_AUTHN_PROTOCOL_MQ, "MSMQ SSP"},
125 static const value_string authn_level_vals[] = {
126 { DCE_C_AUTHN_LEVEL_NONE, "None" },
127 { DCE_C_AUTHN_LEVEL_CONNECT, "Connect" },
128 { DCE_C_AUTHN_LEVEL_CALL, "Call" },
129 { DCE_C_AUTHN_LEVEL_PKT, "Packet" },
130 { DCE_C_AUTHN_LEVEL_PKT_INTEGRITY, "Packet integrity" },
131 { DCE_C_AUTHN_LEVEL_PKT_PRIVACY, "Packet privacy" },
136 * Flag bits in first flag field in connectionless PDU header.
138 #define PFCL1_RESERVED_01 0x01 /* Reserved for use by implementations */
139 #define PFCL1_LASTFRAG 0x02 /* If set, the PDU is the last
140 * fragment of a multi-PDU
142 #define PFCL1_FRAG 0x04 /* If set, the PDU is a fragment of
143 a multi-PDU transmission */
144 #define PFCL1_NOFACK 0x08 /* If set, the receiver is not
145 * requested to send a `fack' PDU
146 * for the fragment */
147 #define PFCL1_MAYBE 0x10 /* If set, the PDU is for a `maybe'
149 #define PFCL1_IDEMPOTENT 0x20 /* If set, the PDU is for an idempotent
151 #define PFCL1_BROADCAST 0x40 /* If set, the PDU is for a broadcast
153 #define PFCL1_RESERVED_80 0x80 /* Reserved for use by implementations */
156 * Flag bits in second flag field in connectionless PDU header.
158 #define PFCL2_RESERVED_01 0x01 /* Reserved for use by implementations */
159 #define PFCL2_CANCEL_PENDING 0x02 /* Cancel pending at the call end */
160 #define PFCL2_RESERVED_04 0x04 /* Reserved for future use */
161 #define PFCL2_RESERVED_08 0x08 /* Reserved for future use */
162 #define PFCL2_RESERVED_10 0x10 /* Reserved for future use */
163 #define PFCL2_RESERVED_20 0x20 /* Reserved for future use */
164 #define PFCL2_RESERVED_40 0x40 /* Reserved for future use */
165 #define PFCL2_RESERVED_80 0x80 /* Reserved for future use */
168 * Flag bits in connection-oriented PDU header.
170 #define PFC_FIRST_FRAG 0x01 /* First fragment */
171 #define PFC_LAST_FRAG 0x02 /* Last fragment */
172 #define PFC_PENDING_CANCEL 0x04 /* Cancel was pending at sender */
173 #define PFC_RESERVED_1 0x08
174 #define PFC_CONC_MPX 0x10 /* suports concurrent multiplexing
175 * of a single connection. */
176 #define PFC_DID_NOT_EXECUTE 0x20 /* only meaningful on `fault' packet;
177 * if true, guaranteed call did not
179 #define PFC_MAYBE 0x40 /* `maybe' call semantics requested */
180 #define PFC_OBJECT_UUID 0x80 /* if true, a non-nil object UUID
181 * was specified in the handle, and
182 * is present in the optional object
183 * field. If false, the object field
187 * Tests whether a connection-oriented PDU is fragmented; returns TRUE if
188 * it's not fragmented (i.e., this is both the first *and* last fragment),
189 * and FALSE otherwise.
191 #define PFC_NOT_FRAGMENTED(hdr) \
192 ((hdr->flags&(PFC_FIRST_FRAG|PFC_LAST_FRAG))==(PFC_FIRST_FRAG|PFC_LAST_FRAG))
195 * Presentation context negotiation result.
197 static const value_string p_cont_result_vals[] = {
199 { 1, "User rejection" },
200 { 2, "Provider rejection" },
205 * Presentation context negotiation rejection reasons.
207 static const value_string p_provider_reason_vals[] = {
208 { 0, "Reason not specified" },
209 { 1, "Abstract syntax not supported" },
210 { 2, "Proposed transfer syntaxes not supported" },
211 { 3, "Local limit exceeded" },
218 #define REASON_NOT_SPECIFIED 0
219 #define TEMPORARY_CONGESTION 1
220 #define LOCAL_LIMIT_EXCEEDED 2
221 #define CALLED_PADDR_UNKNOWN 3 /* not used */
222 #define PROTOCOL_VERSION_NOT_SUPPORTED 4
223 #define DEFAULT_CONTEXT_NOT_SUPPORTED 5 /* not used */
224 #define USER_DATA_NOT_READABLE 6 /* not used */
225 #define NO_PSAP_AVAILABLE 7 /* not used */
226 #define AUTH_TYPE_NOT_RECOGNIZED 8
227 #define INVALID_CHECKSUM 9
229 static const value_string reject_reason_vals[] = {
230 { REASON_NOT_SPECIFIED, "Reason not specified" },
231 { TEMPORARY_CONGESTION, "Temporary congestion" },
232 { LOCAL_LIMIT_EXCEEDED, "Local limit exceeded" },
233 { CALLED_PADDR_UNKNOWN, "Called paddr unknown" },
234 { PROTOCOL_VERSION_NOT_SUPPORTED, "Protocol version not supported" },
235 { DEFAULT_CONTEXT_NOT_SUPPORTED, "Default context not supported" },
236 { USER_DATA_NOT_READABLE, "User data not readable" },
237 { NO_PSAP_AVAILABLE, "No PSAP available" },
238 { AUTH_TYPE_NOT_RECOGNIZED, "Authentication type not recognized" },
239 { INVALID_CHECKSUM, "Invalid checksum" },
244 * Reject status codes.
246 static const value_string reject_status_vals[] = {
247 { 0, "Stub-defined exception" },
248 { 0x00000001, "nca_s_fault_other" },
249 { 0x00000005, "nca_s_fault_access_denied" },
250 { 0x000006f7, "nca_s_fault_ndr" },
251 { 0x000006d8, "nca_s_fault_cant_perform" },
252 { 0x1c000001, "nca_s_fault_int_div_by_zero" },
253 { 0x1c000002, "nca_s_fault_addr_error" },
254 { 0x1c000003, "nca_s_fault_fp_div_zero" },
255 { 0x1c000004, "nca_s_fault_fp_underflow" },
256 { 0x1c000005, "nca_s_fault_fp_overflow" },
257 { 0x1c000006, "nca_s_fault_invalid_tag" },
258 { 0x1c000007, "nca_s_fault_invalid_bound" },
259 { 0x1c000008, "nca_rpc_version_mismatch" },
260 { 0x1c000009, "nca_unspec_reject" },
261 { 0x1c00000a, "nca_s_bad_actid" },
262 { 0x1c00000b, "nca_who_are_you_failed" },
263 { 0x1c00000c, "nca_manager_not_entered" },
264 { 0x1c00000d, "nca_s_fault_cancel" },
265 { 0x1c00000e, "nca_s_fault_ill_inst" },
266 { 0x1c00000f, "nca_s_fault_fp_error" },
267 { 0x1c000010, "nca_s_fault_int_overflow" },
268 { 0x1c000014, "nca_s_fault_pipe_empty" },
269 { 0x1c000015, "nca_s_fault_pipe_closed" },
270 { 0x1c000016, "nca_s_fault_pipe_order" },
271 { 0x1c000017, "nca_s_fault_pipe_discipline" },
272 { 0x1c000018, "nca_s_fault_pipe_comm_error" },
273 { 0x1c000019, "nca_s_fault_pipe_memory" },
274 { 0x1c00001a, "nca_s_fault_context_mismatch" },
275 { 0x1c00001b, "nca_s_fault_remote_no_memory" },
276 { 0x1c00001c, "nca_invalid_pres_context_id" },
277 { 0x1c00001d, "nca_unsupported_authn_level" },
278 { 0x1c00001f, "nca_invalid_checksum" },
279 { 0x1c000020, "nca_invalid_crc" },
280 { 0x1c000021, "ncs_s_fault_user_defined" },
281 { 0x1c000022, "nca_s_fault_tx_open_failed" },
282 { 0x1c000023, "nca_s_fault_codeset_conv_error" },
283 { 0x1c000024, "nca_s_fault_object_not_found" },
284 { 0x1c000025, "nca_s_fault_no_client_stub" },
285 { 0x1c010002, "nca_op_rng_error" },
286 { 0x1c010003, "nca_unk_if"},
287 { 0x1c010006, "nca_wrong_boot_time" },
288 { 0x1c010009, "nca_s_you_crashed" },
289 { 0x1c01000b, "nca_proto_error" },
290 { 0x1c010013, "nca_out_args_too_big" },
291 { 0x1c010014, "nca_server_too_busy" },
292 { 0x1c010017, "nca_unsupported_type" },
293 /* MS Windows specific values
294 * see: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/debug/base/system_error_codes__1700-3999_.asp
295 * and: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/seccrypto/security/common_hresult_values.asp
296 * and: http://www.megos.ch/support/doserrors.txt
298 * XXX - we might need a way to dynamically add entries here, as higher layer protocols use these values too,
299 * at least MS protocols (like DCOM) do it that way ... */
300 { 0x80004001, "E_NOTIMPL" },
301 { 0x80004003, "E_POINTER" },
302 { 0x80004004, "E_ABORT" },
303 { 0x8000FFFF, "E_UNEXPECTED" },
304 { 0x80010105, "RPC_E_SERVERFAULT" },
305 { 0x80010108, "RPC_E_DISCONNECTED" },
306 { 0x80010113, "RPC_E_INVALID_IPID" },
307 { 0x8001011F, "RPC_E_TIMEOUT" },
308 { 0x80020003, "DISP_E_MEMBERNOTFOUND" },
309 { 0x80020006, "DISP_E_UNKNOWNNAME" },
310 { 0x8002000E, "DISP_E_BADPARAMCOUNT" },
311 { 0x8004CB00, "CBA_E_MALFORMED" },
312 { 0x8004CB01, "CBA_E_UNKNOWNOBJECT" },
313 { 0x8004CB09, "CBA_E_INVALIDCOOKIE" },
314 { 0x8004CB0B, "CBA_E_QOSTYPEUNSUPPORTED" },
315 { 0x8004CB0C, "CBA_E_QOSVALUEUNSUPPORTED" },
316 { 0x8004CB0F, "CBA_E_NOTAPPLICABLE" },
317 { 0x8004CB12, "CBA_E_LIMITVIOLATION" },
318 { 0x8004CB13, "CBA_E_QOSTYPENOTAPPLICABLE" },
319 { 0x8004CB18, "CBA_E_OUTOFPARTNERACCOS" },
320 { 0x8004CB1C, "CBA_E_FLAGUNSUPPORTED" },
321 { 0x8004CB23, "CBA_E_FRAMECOUNTUNSUPPORTED" },
322 { 0x8004CB25, "CBA_E_MODECHANGE" },
323 { 0x8007000E, "E_OUTOFMEMORY" },
324 { 0x80070057, "E_INVALIDARG" },
325 { 0x800706d1, "RPC_S_PROCNUM_OUT_OF_RANGE" },
326 { 0x80070776, "OR_INVALID_OXID" },
331 /* we need to keep track of what transport were used, ie what handle we came
332 * in through so we know what kind of pinfo->dce_smb_fid was passed to us.
334 /* Value of -1 is reserved for "not DCE packet" in packet_info.dcetransporttype. */
335 #define DCE_TRANSPORT_UNKNOWN 0
336 #define DCE_CN_TRANSPORT_SMBPIPE 1
339 static int proto_dcerpc = -1;
342 static int hf_dcerpc_request_in = -1;
343 static int hf_dcerpc_time = -1;
344 static int hf_dcerpc_response_in = -1;
345 static int hf_dcerpc_ver = -1;
346 static int hf_dcerpc_ver_minor = -1;
347 static int hf_dcerpc_packet_type = -1;
348 static int hf_dcerpc_cn_flags = -1;
349 static int hf_dcerpc_cn_flags_first_frag = -1;
350 static int hf_dcerpc_cn_flags_last_frag = -1;
351 static int hf_dcerpc_cn_flags_cancel_pending = -1;
352 static int hf_dcerpc_cn_flags_reserved = -1;
353 static int hf_dcerpc_cn_flags_mpx = -1;
354 static int hf_dcerpc_cn_flags_dne = -1;
355 static int hf_dcerpc_cn_flags_maybe = -1;
356 static int hf_dcerpc_cn_flags_object = -1;
357 static int hf_dcerpc_drep = -1;
358 static int hf_dcerpc_drep_byteorder = -1;
359 static int hf_dcerpc_drep_character = -1;
360 static int hf_dcerpc_drep_fp = -1;
361 static int hf_dcerpc_cn_frag_len = -1;
362 static int hf_dcerpc_cn_auth_len = -1;
363 static int hf_dcerpc_cn_call_id = -1;
364 static int hf_dcerpc_cn_max_xmit = -1;
365 static int hf_dcerpc_cn_max_recv = -1;
366 static int hf_dcerpc_cn_assoc_group = -1;
367 static int hf_dcerpc_cn_num_ctx_items = -1;
368 static int hf_dcerpc_cn_ctx_item = -1;
369 static int hf_dcerpc_cn_ctx_id = -1;
370 static int hf_dcerpc_cn_num_trans_items = -1;
371 static int hf_dcerpc_cn_bind_abstract_syntax = -1;
372 static int hf_dcerpc_cn_bind_if_id = -1;
373 static int hf_dcerpc_cn_bind_if_ver = -1;
374 static int hf_dcerpc_cn_bind_if_ver_minor = -1;
375 static int hf_dcerpc_cn_bind_trans_syntax = -1;
376 static int hf_dcerpc_cn_bind_trans_id = -1;
377 static int hf_dcerpc_cn_bind_trans_ver = -1;
378 static int hf_dcerpc_cn_alloc_hint = -1;
379 static int hf_dcerpc_cn_sec_addr_len = -1;
380 static int hf_dcerpc_cn_sec_addr = -1;
381 static int hf_dcerpc_cn_num_results = -1;
382 static int hf_dcerpc_cn_ack_result = -1;
383 static int hf_dcerpc_cn_ack_reason = -1;
384 static int hf_dcerpc_cn_ack_trans_id = -1;
385 static int hf_dcerpc_cn_ack_trans_ver = -1;
386 static int hf_dcerpc_cn_reject_reason = -1;
387 static int hf_dcerpc_cn_num_protocols = -1;
388 static int hf_dcerpc_cn_protocol_ver_major = -1;
389 static int hf_dcerpc_cn_protocol_ver_minor = -1;
390 static int hf_dcerpc_cn_cancel_count = -1;
391 static int hf_dcerpc_cn_status = -1;
392 static int hf_dcerpc_cn_deseg_req = -1;
393 static int hf_dcerpc_auth_type = -1;
394 static int hf_dcerpc_auth_level = -1;
395 static int hf_dcerpc_auth_pad_len = -1;
396 static int hf_dcerpc_auth_rsrvd = -1;
397 static int hf_dcerpc_auth_ctx_id = -1;
398 static int hf_dcerpc_dg_flags1 = -1;
399 static int hf_dcerpc_dg_flags1_rsrvd_01 = -1;
400 static int hf_dcerpc_dg_flags1_last_frag = -1;
401 static int hf_dcerpc_dg_flags1_frag = -1;
402 static int hf_dcerpc_dg_flags1_nofack = -1;
403 static int hf_dcerpc_dg_flags1_maybe = -1;
404 static int hf_dcerpc_dg_flags1_idempotent = -1;
405 static int hf_dcerpc_dg_flags1_broadcast = -1;
406 static int hf_dcerpc_dg_flags1_rsrvd_80 = -1;
407 static int hf_dcerpc_dg_flags2 = -1;
408 static int hf_dcerpc_dg_flags2_rsrvd_01 = -1;
409 static int hf_dcerpc_dg_flags2_cancel_pending = -1;
410 static int hf_dcerpc_dg_flags2_rsrvd_04 = -1;
411 static int hf_dcerpc_dg_flags2_rsrvd_08 = -1;
412 static int hf_dcerpc_dg_flags2_rsrvd_10 = -1;
413 static int hf_dcerpc_dg_flags2_rsrvd_20 = -1;
414 static int hf_dcerpc_dg_flags2_rsrvd_40 = -1;
415 static int hf_dcerpc_dg_flags2_rsrvd_80 = -1;
416 static int hf_dcerpc_dg_serial_hi = -1;
417 static int hf_dcerpc_obj_id = -1;
418 static int hf_dcerpc_dg_if_id = -1;
419 static int hf_dcerpc_dg_act_id = -1;
420 static int hf_dcerpc_dg_serial_lo = -1;
421 static int hf_dcerpc_dg_ahint = -1;
422 static int hf_dcerpc_dg_ihint = -1;
423 static int hf_dcerpc_dg_frag_len = -1;
424 static int hf_dcerpc_dg_frag_num = -1;
425 static int hf_dcerpc_dg_auth_proto = -1;
426 static int hf_dcerpc_opnum = -1;
427 static int hf_dcerpc_dg_seqnum = -1;
428 static int hf_dcerpc_dg_server_boot = -1;
429 static int hf_dcerpc_dg_if_ver = -1;
430 static int hf_dcerpc_krb5_av_prot_level = -1;
431 static int hf_dcerpc_krb5_av_key_vers_num = -1;
432 static int hf_dcerpc_krb5_av_key_auth_verifier = -1;
433 static int hf_dcerpc_dg_cancel_vers = -1;
434 static int hf_dcerpc_dg_cancel_id = -1;
435 static int hf_dcerpc_dg_server_accepting_cancels = -1;
436 static int hf_dcerpc_dg_fack_vers = -1;
437 static int hf_dcerpc_dg_fack_window_size = -1;
438 static int hf_dcerpc_dg_fack_max_tsdu = -1;
439 static int hf_dcerpc_dg_fack_max_frag_size = -1;
440 static int hf_dcerpc_dg_fack_serial_num = -1;
441 static int hf_dcerpc_dg_fack_selack_len = -1;
442 static int hf_dcerpc_dg_fack_selack = -1;
443 static int hf_dcerpc_dg_status = -1;
444 static int hf_dcerpc_array_max_count = -1;
445 static int hf_dcerpc_array_offset = -1;
446 static int hf_dcerpc_array_actual_count = -1;
447 static int hf_dcerpc_array_buffer = -1;
448 static int hf_dcerpc_op = -1;
449 static int hf_dcerpc_referent_id = -1;
450 static int hf_dcerpc_fragments = -1;
451 static int hf_dcerpc_fragment = -1;
452 static int hf_dcerpc_fragment_overlap = -1;
453 static int hf_dcerpc_fragment_overlap_conflict = -1;
454 static int hf_dcerpc_fragment_multiple_tails = -1;
455 static int hf_dcerpc_fragment_too_long_fragment = -1;
456 static int hf_dcerpc_fragment_error = -1;
457 static int hf_dcerpc_reassembled_in = -1;
458 static int hf_dcerpc_unknown_if_id = -1;
460 static gint ett_dcerpc = -1;
461 static gint ett_dcerpc_cn_flags = -1;
462 static gint ett_dcerpc_cn_ctx = -1;
463 static gint ett_dcerpc_cn_iface = -1;
464 static gint ett_dcerpc_cn_trans_syntax = -1;
465 static gint ett_dcerpc_drep = -1;
466 static gint ett_dcerpc_dg_flags1 = -1;
467 static gint ett_dcerpc_dg_flags2 = -1;
468 static gint ett_dcerpc_pointer_data = -1;
469 static gint ett_dcerpc_string = -1;
470 static gint ett_dcerpc_fragments = -1;
471 static gint ett_dcerpc_fragment = -1;
472 static gint ett_dcerpc_krb5_auth_verf = -1;
474 static const fragment_items dcerpc_frag_items = {
475 &ett_dcerpc_fragments,
476 &ett_dcerpc_fragment,
478 &hf_dcerpc_fragments,
480 &hf_dcerpc_fragment_overlap,
481 &hf_dcerpc_fragment_overlap_conflict,
482 &hf_dcerpc_fragment_multiple_tails,
483 &hf_dcerpc_fragment_too_long_fragment,
484 &hf_dcerpc_fragment_error,
490 /* list of hooks to be called when init_protocols is done */
491 GHookList dcerpc_hooks_init_protos;
496 static dcerpc_info di[20];
497 static int di_counter=0;
503 return &di[di_counter];
506 /* try to desegment big DCE/RPC packets over TCP? */
507 static gboolean dcerpc_cn_desegment = TRUE;
509 /* reassemble DCE/RPC fragments */
510 /* reassembly of cl dcerpc fragments will not work for the case where ONE frame
511 might contain multiple dcerpc fragments for different PDUs.
512 this case would be so unusual/weird so if you got captures like that:
515 reassembly of co dcerpc fragments will not work for the case where TCP/SMB frames
516 are coming in out of sequence, but that will hurt in a lot of other places as well.
518 static gboolean dcerpc_reassemble = TRUE;
519 static GHashTable *dcerpc_co_fragment_table = NULL;
520 static GHashTable *dcerpc_co_reassemble_table = NULL;
521 static GHashTable *dcerpc_cl_reassemble_table = NULL;
524 dcerpc_reassemble_init(void)
526 fragment_table_init(&dcerpc_co_fragment_table);
527 reassembled_table_init(&dcerpc_co_reassemble_table);
528 dcerpc_fragment_table_init(&dcerpc_cl_reassemble_table);
532 * Authentication subdissectors. Used to dissect authentication blobs in
533 * DCERPC binds, requests and responses.
536 typedef struct _dcerpc_auth_subdissector {
539 dcerpc_auth_subdissector_fns auth_fns;
540 } dcerpc_auth_subdissector;
542 static GSList *dcerpc_auth_subdissector_list;
544 static dcerpc_auth_subdissector_fns *get_auth_subdissector_fns(
545 guint8 auth_level, guint8 auth_type)
550 for (i = 0; (data = g_slist_nth_data(dcerpc_auth_subdissector_list, i)); i++) {
551 dcerpc_auth_subdissector *asd = (dcerpc_auth_subdissector *)data;
553 if (asd->auth_level == auth_level &&
554 asd->auth_type == auth_type)
555 return &asd->auth_fns;
561 void register_dcerpc_auth_subdissector(guint8 auth_level, guint8 auth_type,
562 dcerpc_auth_subdissector_fns *fns)
564 dcerpc_auth_subdissector *d;
566 if (get_auth_subdissector_fns(auth_level, auth_type))
569 d = (dcerpc_auth_subdissector *)g_malloc(sizeof(dcerpc_auth_subdissector));
571 d->auth_level = auth_level;
572 d->auth_type = auth_type;
573 memcpy(&d->auth_fns, fns, sizeof(dcerpc_auth_subdissector_fns));
575 dcerpc_auth_subdissector_list = g_slist_append(dcerpc_auth_subdissector_list, d);
578 /* Hand off verifier data to a registered dissector */
580 static void dissect_auth_verf(tvbuff_t *auth_tvb, packet_info *pinfo,
582 dcerpc_auth_subdissector_fns *auth_fns,
583 e_dce_cn_common_hdr_t *hdr,
584 dcerpc_auth_info *auth_info)
586 dcerpc_dissect_fnct_t *volatile fn = NULL;
588 switch (hdr->ptype) {
591 fn = auth_fns->bind_fn;
595 fn = auth_fns->bind_ack_fn;
598 fn = auth_fns->auth3_fn;
601 fn = auth_fns->req_verf_fn;
604 fn = auth_fns->resp_verf_fn;
607 /* Don't know how to handle authentication data in this
611 g_warning("attempt to dissect %s pdu authentication data",
612 val_to_str(hdr->ptype, pckt_vals, "Unknown (%u)"));
617 fn(auth_tvb, 0, pinfo, tree, hdr->drep);
619 tvb_ensure_bytes_exist(auth_tvb, 0, hdr->auth_len);
620 proto_tree_add_text(tree, auth_tvb, 0, hdr->auth_len,
622 val_to_str(auth_info->auth_type,
628 /* Hand off payload data to a registered dissector */
630 static tvbuff_t *decode_encrypted_data(tvbuff_t *data_tvb,
633 dcerpc_auth_subdissector_fns *auth_fns,
635 dcerpc_auth_info *auth_info)
637 dcerpc_decode_data_fnct_t *fn;
640 fn = auth_fns->req_data_fn;
642 fn = auth_fns->resp_data_fn;
645 return fn(data_tvb, auth_tvb, 0, pinfo, auth_info);
654 /* the registered subdissectors */
655 GHashTable *dcerpc_uuids=NULL;
658 dcerpc_uuid_equal (gconstpointer k1, gconstpointer k2)
660 const dcerpc_uuid_key *key1 = (const dcerpc_uuid_key *)k1;
661 const dcerpc_uuid_key *key2 = (const dcerpc_uuid_key *)k2;
662 return ((memcmp (&key1->uuid, &key2->uuid, sizeof (e_uuid_t)) == 0)
663 && (key1->ver == key2->ver));
667 dcerpc_uuid_hash (gconstpointer k)
669 const dcerpc_uuid_key *key = (const dcerpc_uuid_key *)k;
670 /* This isn't perfect, but the Data1 part of these is almost always
672 return key->uuid.Data1;
676 dcerpc_init_uuid (int proto, int ett, e_uuid_t *uuid, guint16 ver,
677 dcerpc_sub_dissector *procs, int opnum_hf)
679 dcerpc_uuid_key *key = g_malloc (sizeof (*key));
680 dcerpc_uuid_value *value = g_malloc (sizeof (*value));
681 header_field_info *hf_info;
686 value->proto = find_protocol_by_id(proto);
687 value->proto_id = proto;
689 value->name = proto_get_protocol_short_name (value->proto);
690 value->procs = procs;
691 value->opnum_hf = opnum_hf;
693 g_hash_table_insert (dcerpc_uuids, key, value);
695 hf_info = proto_registrar_get_nth(opnum_hf);
696 hf_info->strings = value_string_from_subdissectors(procs);
698 /* add this GUID to the global name resolving */
699 guids_add_uuid(uuid, proto_get_protocol_short_name (value->proto));
702 /* Function to find the name of a registered protocol
703 * or NULL if the protocol/version is not known to wireshark.
706 dcerpc_get_proto_name(e_uuid_t *uuid, guint16 ver)
709 dcerpc_uuid_value *sub_proto;
713 if(!(sub_proto = g_hash_table_lookup (dcerpc_uuids, &key))){
716 return sub_proto->name;
719 /* Function to find the opnum hf-field of a registered protocol
720 * or -1 if the protocol/version is not known to wireshark.
723 dcerpc_get_proto_hf_opnum(e_uuid_t *uuid, guint16 ver)
726 dcerpc_uuid_value *sub_proto;
730 if(!(sub_proto = g_hash_table_lookup (dcerpc_uuids, &key))){
733 return sub_proto->opnum_hf;
736 /* Create a value_string consisting of DCERPC opnum and name from a
737 subdissector array. */
739 value_string *value_string_from_subdissectors(dcerpc_sub_dissector *sd)
741 value_string *vs = NULL;
745 for (i = 0; sd[i].name; i++) {
747 vs[i].value = sd[i].num;
748 vs[i].strptr = sd[i].name;
754 vs = g_malloc((num_sd + 1) * sizeof(value_string));
758 vs[num_sd].value = 0;
759 vs[num_sd].strptr = NULL;
764 /* Function to find the subdissector table of a registered protocol
765 * or NULL if the protocol/version is not known to wireshark.
767 dcerpc_sub_dissector *
768 dcerpc_get_proto_sub_dissector(e_uuid_t *uuid, guint16 ver)
771 dcerpc_uuid_value *sub_proto;
775 if(!(sub_proto = g_hash_table_lookup (dcerpc_uuids, &key))){
778 return sub_proto->procs;
783 * To keep track of ctx_id mappings.
785 * Everytime we see a bind call we update this table.
786 * Note that we always specify a SMB FID. For non-SMB transports this
789 static GHashTable *dcerpc_binds=NULL;
791 typedef struct _dcerpc_bind_key {
792 conversation_t *conv;
797 typedef struct _dcerpc_bind_value {
803 dcerpc_bind_equal (gconstpointer k1, gconstpointer k2)
805 const dcerpc_bind_key *key1 = (const dcerpc_bind_key *)k1;
806 const dcerpc_bind_key *key2 = (const dcerpc_bind_key *)k2;
807 return (key1->conv == key2->conv
808 && key1->ctx_id == key2->ctx_id
809 && key1->smb_fid == key2->smb_fid);
813 dcerpc_bind_hash (gconstpointer k)
815 const dcerpc_bind_key *key = (const dcerpc_bind_key *)k;
818 hash=GPOINTER_TO_UINT(key->conv) + key->ctx_id + key->smb_fid;
824 * To keep track of callid mappings. Should really use some generic
825 * conversation support instead.
827 static GHashTable *dcerpc_cn_calls=NULL;
828 static GHashTable *dcerpc_dg_calls=NULL;
830 typedef struct _dcerpc_cn_call_key {
831 conversation_t *conv;
834 } dcerpc_cn_call_key;
836 typedef struct _dcerpc_dg_call_key {
837 conversation_t *conv;
840 } dcerpc_dg_call_key;
844 dcerpc_cn_call_equal (gconstpointer k1, gconstpointer k2)
846 const dcerpc_cn_call_key *key1 = (const dcerpc_cn_call_key *)k1;
847 const dcerpc_cn_call_key *key2 = (const dcerpc_cn_call_key *)k2;
848 return (key1->conv == key2->conv
849 && key1->call_id == key2->call_id
850 && key1->smb_fid == key2->smb_fid);
854 dcerpc_dg_call_equal (gconstpointer k1, gconstpointer k2)
856 const dcerpc_dg_call_key *key1 = (const dcerpc_dg_call_key *)k1;
857 const dcerpc_dg_call_key *key2 = (const dcerpc_dg_call_key *)k2;
858 return (key1->conv == key2->conv
859 && key1->seqnum == key2->seqnum
860 && (memcmp (&key1->act_id, &key2->act_id, sizeof (e_uuid_t)) == 0));
864 dcerpc_cn_call_hash (gconstpointer k)
866 const dcerpc_cn_call_key *key = (const dcerpc_cn_call_key *)k;
867 return GPOINTER_TO_UINT(key->conv) + key->call_id + key->smb_fid;
871 dcerpc_dg_call_hash (gconstpointer k)
873 const dcerpc_dg_call_key *key = (const dcerpc_dg_call_key *)k;
874 return (GPOINTER_TO_UINT(key->conv) + key->seqnum + key->act_id.Data1
875 + (key->act_id.Data2 << 16) + key->act_id.Data3
876 + (key->act_id.Data4[0] << 24) + (key->act_id.Data4[1] << 16)
877 + (key->act_id.Data4[2] << 8) + (key->act_id.Data4[3] << 0)
878 + (key->act_id.Data4[4] << 24) + (key->act_id.Data4[5] << 16)
879 + (key->act_id.Data4[6] << 8) + (key->act_id.Data4[7] << 0));
882 /* to keep track of matched calls/responses
883 this one uses the same value struct as calls, but the key is the frame id
884 and call id; there can be more than one call in a frame.
886 XXX - why not just use the same keys as are used for calls?
889 static GHashTable *dcerpc_matched=NULL;
891 typedef struct _dcerpc_matched_key {
894 } dcerpc_matched_key;
897 dcerpc_matched_equal (gconstpointer k1, gconstpointer k2)
899 const dcerpc_matched_key *key1 = (const dcerpc_matched_key *)k1;
900 const dcerpc_matched_key *key2 = (const dcerpc_matched_key *)k2;
901 return (key1->frame == key2->frame
902 && key1->call_id == key2->call_id);
906 dcerpc_matched_hash (gconstpointer k)
908 const dcerpc_matched_key *key = (const dcerpc_matched_key *)k;
915 * Utility functions. Modeled after packet-rpc.c
919 dissect_dcerpc_uint8 (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
920 proto_tree *tree, guint8 *drep,
921 int hfindex, guint8 *pdata)
925 data = tvb_get_guint8 (tvb, offset);
927 proto_tree_add_item (tree, hfindex, tvb, offset, 1, (drep[0] & 0x10));
935 dissect_dcerpc_uint16 (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
936 proto_tree *tree, guint8 *drep,
937 int hfindex, guint16 *pdata)
941 data = ((drep[0] & 0x10)
942 ? tvb_get_letohs (tvb, offset)
943 : tvb_get_ntohs (tvb, offset));
946 proto_tree_add_item (tree, hfindex, tvb, offset, 2, (drep[0] & 0x10));
954 dissect_dcerpc_uint32 (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
955 proto_tree *tree, guint8 *drep,
956 int hfindex, guint32 *pdata)
960 data = ((drep[0] & 0x10)
961 ? tvb_get_letohl (tvb, offset)
962 : tvb_get_ntohl (tvb, offset));
965 proto_tree_add_item (tree, hfindex, tvb, offset, 4, (drep[0] & 0x10));
972 /* handles 32 bit unix time_t */
974 dissect_dcerpc_time_t (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
975 proto_tree *tree, guint8 *drep,
976 int hfindex, guint32 *pdata)
981 data = ((drep[0] & 0x10)
982 ? tvb_get_letohl (tvb, offset)
983 : tvb_get_ntohl (tvb, offset));
988 if(data==0xffffffff){
989 /* special case, no time specified */
990 proto_tree_add_time_format_value(tree, hfindex, tvb, offset, 4, &tv, "No time specified");
992 proto_tree_add_time (tree, hfindex, tvb, offset, 4, &tv);
1002 dissect_dcerpc_uint64 (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
1003 proto_tree *tree, guint8 *drep,
1004 int hfindex, guint64 *pdata)
1008 data = ((drep[0] & 0x10)
1009 ? tvb_get_letoh64 (tvb, offset)
1010 : tvb_get_ntoh64 (tvb, offset));
1013 proto_tree_add_item(tree, hfindex, tvb, offset, 8, (drep[0] & 0x10));
1022 dissect_dcerpc_float(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
1023 proto_tree *tree, guint8 *drep,
1024 int hfindex, gfloat *pdata)
1030 case(DCE_RPC_DREP_FP_IEEE):
1031 data = ((drep[0] & 0x10)
1032 ? tvb_get_letohieee_float(tvb, offset)
1033 : tvb_get_ntohieee_float(tvb, offset));
1035 proto_tree_add_float(tree, hfindex, tvb, offset, 4, data);
1038 case(DCE_RPC_DREP_FP_VAX): /* (fall trough) */
1039 case(DCE_RPC_DREP_FP_CRAY): /* (fall trough) */
1040 case(DCE_RPC_DREP_FP_IBM): /* (fall trough) */
1042 /* ToBeDone: non IEEE floating formats */
1043 /* Set data to a negative infinity value */
1046 proto_tree_add_debug_text(tree, "DCE RPC: dissection of non IEEE floating formats currently not implemented (drep=%u)!", drep[1]);
1056 dissect_dcerpc_double(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
1057 proto_tree *tree, guint8 *drep,
1058 int hfindex, gdouble *pdata)
1064 case(DCE_RPC_DREP_FP_IEEE):
1065 data = ((drep[0] & 0x10)
1066 ? tvb_get_letohieee_double(tvb, offset)
1067 : tvb_get_ntohieee_double(tvb, offset));
1069 proto_tree_add_double(tree, hfindex, tvb, offset, 8, data);
1072 case(DCE_RPC_DREP_FP_VAX): /* (fall trough) */
1073 case(DCE_RPC_DREP_FP_CRAY): /* (fall trough) */
1074 case(DCE_RPC_DREP_FP_IBM): /* (fall trough) */
1076 /* ToBeDone: non IEEE double formats */
1077 /* Set data to a negative infinity value */
1078 data = -G_MAXDOUBLE;
1080 proto_tree_add_debug_text(tree, "DCE RPC: dissection of non IEEE double formats currently not implemented (drep=%u)!", drep[1]);
1090 dissect_dcerpc_uuid_t (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
1091 proto_tree *tree, guint8 *drep,
1092 int hfindex, e_uuid_t *pdata)
1097 if (drep[0] & 0x10) {
1098 tvb_get_letohguid (tvb, offset, (e_guid_t *) &uuid);
1100 tvb_get_ntohguid (tvb, offset, (e_guid_t *) &uuid);
1103 proto_tree_add_guid(tree, hfindex, tvb, offset, 16, (e_guid_t *) &uuid);
1113 * a couple simpler things
1116 dcerpc_tvb_get_ntohs (tvbuff_t *tvb, gint offset, guint8 *drep)
1118 if (drep[0] & 0x10) {
1119 return tvb_get_letohs (tvb, offset);
1121 return tvb_get_ntohs (tvb, offset);
1126 dcerpc_tvb_get_ntohl (tvbuff_t *tvb, gint offset, guint8 *drep)
1128 if (drep[0] & 0x10) {
1129 return tvb_get_letohl (tvb, offset);
1131 return tvb_get_ntohl (tvb, offset);
1136 dcerpc_tvb_get_uuid (tvbuff_t *tvb, gint offset, guint8 *drep, e_uuid_t *uuid)
1138 if (drep[0] & 0x10) {
1139 tvb_get_letohguid (tvb, offset, (e_guid_t *) uuid);
1141 tvb_get_ntohguid (tvb, offset, (e_guid_t *) uuid);
1147 /* function to dissect a unidimensional conformant array */
1149 dissect_ndr_ucarray(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1150 proto_tree *tree, guint8 *drep,
1151 dcerpc_dissect_fnct_t *fnct)
1157 di=pinfo->private_data;
1158 if(di->conformant_run){
1159 /* conformant run, just dissect the max_count header */
1161 di->conformant_run=0;
1162 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1163 hf_dcerpc_array_max_count, &di->array_max_count);
1164 di->array_max_count_offset=offset-4;
1165 di->conformant_run=1;
1166 di->conformant_eaten=offset-old_offset;
1168 /* we don't remember where in the bytestream this field was */
1169 proto_tree_add_uint(tree, hf_dcerpc_array_max_count, tvb, di->array_max_count_offset, 4, di->array_max_count);
1171 /* real run, dissect the elements */
1172 for(i=0;i<di->array_max_count;i++){
1173 offset = (*fnct)(tvb, offset, pinfo, tree, drep);
1179 /* function to dissect a unidimensional conformant and varying array */
1181 dissect_ndr_ucvarray(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1182 proto_tree *tree, guint8 *drep,
1183 dcerpc_dissect_fnct_t *fnct)
1189 di=pinfo->private_data;
1190 if(di->conformant_run){
1191 /* conformant run, just dissect the max_count header */
1193 di->conformant_run=0;
1194 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1195 hf_dcerpc_array_max_count, &di->array_max_count);
1196 di->array_max_count_offset=offset-4;
1197 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1198 hf_dcerpc_array_offset, &di->array_offset);
1199 di->array_offset_offset=offset-4;
1200 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1201 hf_dcerpc_array_actual_count, &di->array_actual_count);
1202 di->array_actual_count_offset=offset-4;
1203 di->conformant_run=1;
1204 di->conformant_eaten=offset-old_offset;
1206 /* we dont dont remember where in the bytestream these fields were */
1207 proto_tree_add_uint(tree, hf_dcerpc_array_max_count, tvb, di->array_max_count_offset, 4, di->array_max_count);
1208 proto_tree_add_uint(tree, hf_dcerpc_array_offset, tvb, di->array_offset_offset, 4, di->array_offset);
1209 proto_tree_add_uint(tree, hf_dcerpc_array_actual_count, tvb, di->array_actual_count_offset, 4, di->array_actual_count);
1211 /* real run, dissect the elements */
1212 for(i=0;i<di->array_actual_count;i++){
1213 old_offset = offset;
1214 offset = (*fnct)(tvb, offset, pinfo, tree, drep);
1215 if (offset <= old_offset)
1216 THROW(ReportedBoundsError);
1222 /* function to dissect a unidimensional varying array */
1224 dissect_ndr_uvarray(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1225 proto_tree *tree, guint8 *drep,
1226 dcerpc_dissect_fnct_t *fnct)
1232 di=pinfo->private_data;
1233 if(di->conformant_run){
1234 /* conformant run, just dissect the max_count header */
1236 di->conformant_run=0;
1237 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1238 hf_dcerpc_array_offset, &di->array_offset);
1239 di->array_offset_offset=offset-4;
1240 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1241 hf_dcerpc_array_actual_count, &di->array_actual_count);
1242 di->array_actual_count_offset=offset-4;
1243 di->conformant_run=1;
1244 di->conformant_eaten=offset-old_offset;
1246 /* we dont dont remember where in the bytestream these fields were */
1247 proto_tree_add_uint(tree, hf_dcerpc_array_offset, tvb, di->array_offset_offset, 4, di->array_offset);
1248 proto_tree_add_uint(tree, hf_dcerpc_array_actual_count, tvb, di->array_actual_count_offset, 4, di->array_actual_count);
1250 /* real run, dissect the elements */
1251 for(i=0;i<di->array_actual_count;i++){
1252 offset = (*fnct)(tvb, offset, pinfo, tree, drep);
1259 /* Dissect an string of bytes. This corresponds to
1260 IDL of the form '[string] byte *foo'.
1262 It can also be used for a conformant varying array of bytes if
1263 the contents of the array should be shown as a big blob, rather
1264 than showing each byte as an individual element.
1266 XXX - which of those is really the IDL type for, for example,
1267 the encrypted data in some MAPI packets? (Microsoft haven't
1270 XXX - does this need to do all the conformant array stuff that
1271 "dissect_ndr_ucvarray()" does? These are presumably for strings
1272 that are conformant and varying - they're stored like conformant
1273 varying arrays of bytes. */
1275 dissect_ndr_byte_array(tvbuff_t *tvb, int offset, packet_info *pinfo,
1276 proto_tree *tree, guint8 *drep)
1281 di=pinfo->private_data;
1282 if(di->conformant_run){
1283 /* just a run to handle conformant arrays, no scalars to dissect */
1287 /* NDR array header */
1289 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
1290 hf_dcerpc_array_max_count, NULL);
1292 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
1293 hf_dcerpc_array_offset, NULL);
1295 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
1296 hf_dcerpc_array_actual_count, &len);
1299 tvb_ensure_bytes_exist(tvb, offset, len);
1300 proto_tree_add_item(tree, hf_dcerpc_array_buffer,
1301 tvb, offset, len, drep[0] & 0x10);
1309 /* For dissecting arrays that are to be interpreted as strings. */
1311 /* Dissect an NDR conformant varying string of elements.
1312 The length of each element is given by the 'size_is' parameter;
1313 the elements are assumed to be characters or wide characters.
1315 XXX - does this need to do all the conformant array stuff that
1316 "dissect_ndr_ucvarray()" does? */
1318 dissect_ndr_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
1319 proto_tree *tree, guint8 *drep, int size_is,
1320 int hfindex, gboolean add_subtree, char **data)
1323 proto_item *string_item;
1324 proto_tree *string_tree;
1325 guint32 len, buffer_len;
1327 header_field_info *hfinfo;
1329 di=pinfo->private_data;
1330 if(di->conformant_run){
1331 /* just a run to handle conformant arrays, no scalars to dissect */
1336 string_item = proto_tree_add_text(tree, tvb, offset, -1, "%s",
1337 proto_registrar_get_name(hfindex));
1338 string_tree = proto_item_add_subtree(string_item, ett_dcerpc_string);
1344 /* NDR array header */
1346 offset = dissect_ndr_uint32(tvb, offset, pinfo, string_tree, drep,
1347 hf_dcerpc_array_max_count, NULL);
1349 offset = dissect_ndr_uint32(tvb, offset, pinfo, string_tree, drep,
1350 hf_dcerpc_array_offset, NULL);
1352 offset = dissect_ndr_uint32(tvb, offset, pinfo, string_tree, drep,
1353 hf_dcerpc_array_actual_count, &len);
1355 buffer_len = size_is * len;
1358 if (offset % size_is)
1359 offset += size_is - (offset % size_is);
1361 if (size_is == sizeof(guint16)) {
1362 /* XXX - use drep to determine the byte order? */
1363 s = tvb_fake_unicode(tvb, offset, buffer_len / 2, TRUE);
1365 * XXX - we don't support a string type with Unicode
1366 * characters, so if this is a string item, we make
1367 * its value be the "fake Unicode" string.
1369 if (tree && buffer_len) {
1370 hfinfo = proto_registrar_get_nth(hfindex);
1371 tvb_ensure_bytes_exist(tvb, offset, buffer_len);
1372 if (hfinfo->type == FT_STRING) {
1373 proto_tree_add_string(string_tree, hfindex, tvb, offset,
1376 proto_tree_add_item(string_tree, hfindex, tvb, offset,
1377 buffer_len, drep[0] & 0x10);
1382 * "tvb_get_string()" throws an exception if the entire string
1383 * isn't in the tvbuff. If the length is bogus, this should
1384 * keep us from trying to allocate an immensely large buffer.
1385 * (It won't help if the length is *valid* but immensely large,
1386 * but that's another matter; in any case, that would happen only
1387 * if we had an immensely large tvbuff....)
1389 tvb_ensure_bytes_exist(tvb, offset, buffer_len);
1390 s = tvb_get_string(tvb, offset, buffer_len);
1391 if (tree && buffer_len)
1392 proto_tree_add_item(string_tree, hfindex, tvb, offset,
1393 buffer_len, drep[0] & 0x10);
1396 if (string_item != NULL)
1397 proto_item_append_text(string_item, ": %s", s);
1404 offset += buffer_len;
1406 proto_item_set_end(string_item, tvb, offset);
1411 /* Dissect an conformant varying string of chars.
1412 This corresponds to IDL of the form '[string] char *foo'.
1414 XXX - at least according to the DCE RPC 1.1 spec, a string has
1415 a null terminator, which isn't necessary as a terminator for
1416 the transfer language (as there's a length), but is presumably
1417 there for the benefit of null-terminated-string languages
1418 such as C. Is this ever used for purely counted strings?
1419 (Not that it matters if it is.) */
1421 dissect_ndr_char_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
1422 proto_tree *tree, guint8 *drep)
1425 di=pinfo->private_data;
1427 return dissect_ndr_cvstring(tvb, offset, pinfo, tree, drep,
1428 sizeof(guint8), di->hf_index,
1432 /* Dissect a conformant varying string of wchars (wide characters).
1433 This corresponds to IDL of the form '[string] wchar *foo'
1435 XXX - at least according to the DCE RPC 1.1 spec, a string has
1436 a null terminator, which isn't necessary as a terminator for
1437 the transfer language (as there's a length), but is presumably
1438 there for the benefit of null-terminated-string languages
1439 such as C. Is this ever used for purely counted strings?
1440 (Not that it matters if it is.) */
1442 dissect_ndr_wchar_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
1443 proto_tree *tree, guint8 *drep)
1446 di=pinfo->private_data;
1448 return dissect_ndr_cvstring(tvb, offset, pinfo, tree, drep,
1449 sizeof(guint16), di->hf_index,
1453 /* Dissect an NDR varying string of elements.
1454 The length of each element is given by the 'size_is' parameter;
1455 the elements are assumed to be characters or wide characters.
1458 dissect_ndr_vstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
1459 proto_tree *tree, guint8 *drep, int size_is,
1460 int hfindex, gboolean add_subtree, char **data)
1463 proto_item *string_item;
1464 proto_tree *string_tree;
1465 guint32 len, buffer_len;
1467 header_field_info *hfinfo;
1469 di=pinfo->private_data;
1470 if(di->conformant_run){
1471 /* just a run to handle conformant arrays, no scalars to dissect */
1476 string_item = proto_tree_add_text(tree, tvb, offset, -1, "%s",
1477 proto_registrar_get_name(hfindex));
1478 string_tree = proto_item_add_subtree(string_item, ett_dcerpc_string);
1484 /* NDR array header */
1485 offset = dissect_ndr_uint32(tvb, offset, pinfo, string_tree, drep,
1486 hf_dcerpc_array_offset, NULL);
1488 offset = dissect_ndr_uint32(tvb, offset, pinfo, string_tree, drep,
1489 hf_dcerpc_array_actual_count, &len);
1491 buffer_len = size_is * len;
1494 if (offset % size_is)
1495 offset += size_is - (offset % size_is);
1497 if (size_is == sizeof(guint16)) {
1498 /* XXX - use drep to determine the byte order? */
1499 s = tvb_fake_unicode(tvb, offset, buffer_len / 2, TRUE);
1501 * XXX - we don't support a string type with Unicode
1502 * characters, so if this is a string item, we make
1503 * its value be the "fake Unicode" string.
1505 if (tree && buffer_len) {
1506 hfinfo = proto_registrar_get_nth(hfindex);
1507 tvb_ensure_bytes_exist(tvb, offset, buffer_len);
1508 if (hfinfo->type == FT_STRING) {
1509 proto_tree_add_string(string_tree, hfindex, tvb, offset,
1512 proto_tree_add_item(string_tree, hfindex, tvb, offset,
1513 buffer_len, drep[0] & 0x10);
1518 * "tvb_get_string()" throws an exception if the entire string
1519 * isn't in the tvbuff. If the length is bogus, this should
1520 * keep us from trying to allocate an immensely large buffer.
1521 * (It won't help if the length is *valid* but immensely large,
1522 * but that's another matter; in any case, that would happen only
1523 * if we had an immensely large tvbuff....)
1525 tvb_ensure_bytes_exist(tvb, offset, buffer_len);
1526 s = tvb_get_string(tvb, offset, buffer_len);
1527 if (tree && buffer_len)
1528 proto_tree_add_item(string_tree, hfindex, tvb, offset,
1529 buffer_len, drep[0] & 0x10);
1532 if (string_item != NULL)
1533 proto_item_append_text(string_item, ": %s", s);
1540 offset += buffer_len;
1542 proto_item_set_end(string_item, tvb, offset);
1546 /* Dissect an varying string of chars.
1547 This corresponds to IDL of the form '[string] char *foo'.
1549 XXX - at least according to the DCE RPC 1.1 spec, a string has
1550 a null terminator, which isn't necessary as a terminator for
1551 the transfer language (as there's a length), but is presumably
1552 there for the benefit of null-terminated-string languages
1553 such as C. Is this ever used for purely counted strings?
1554 (Not that it matters if it is.) */
1556 dissect_ndr_char_vstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
1557 proto_tree *tree, guint8 *drep)
1560 di=pinfo->private_data;
1562 return dissect_ndr_vstring(tvb, offset, pinfo, tree, drep,
1563 sizeof(guint8), di->hf_index,
1567 /* Dissect a varying string of wchars (wide characters).
1568 This corresponds to IDL of the form '[string] wchar *foo'
1570 XXX - at least according to the DCE RPC 1.1 spec, a string has
1571 a null terminator, which isn't necessary as a terminator for
1572 the transfer language (as there's a length), but is presumably
1573 there for the benefit of null-terminated-string languages
1574 such as C. Is this ever used for purely counted strings?
1575 (Not that it matters if it is.) */
1577 dissect_ndr_wchar_vstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
1578 proto_tree *tree, guint8 *drep)
1581 di=pinfo->private_data;
1583 return dissect_ndr_vstring(tvb, offset, pinfo, tree, drep,
1584 sizeof(guint16), di->hf_index,
1589 /* ndr pointer handling */
1590 /* list of pointers encountered so far */
1591 static GSList *ndr_pointer_list = NULL;
1593 /* position where in the list to insert newly encountered pointers */
1594 static int ndr_pointer_list_pos=0;
1596 /* boolean controlling whether pointers are top-level or embedded */
1597 static gboolean pointers_are_top_level = TRUE;
1599 /* as a kludge, we represent all embedded reference pointers as id==-1
1600 hoping that his will not collide with any non-ref pointers */
1601 typedef struct ndr_pointer_data {
1603 proto_item *item; /* proto_item for pointer */
1604 proto_tree *tree; /* subtree of above item */
1605 dcerpc_dissect_fnct_t *fnct; /*if non-NULL, we have not called it yet*/
1607 dcerpc_callback_fnct_t *callback;
1608 void *callback_args;
1609 } ndr_pointer_data_t;
1612 init_ndr_pointer_list(packet_info *pinfo)
1616 di=pinfo->private_data;
1617 di->conformant_run=0;
1619 while(ndr_pointer_list){
1620 ndr_pointer_data_t *npd;
1622 npd=g_slist_nth_data(ndr_pointer_list, 0);
1623 ndr_pointer_list=g_slist_remove(ndr_pointer_list, npd);
1629 ndr_pointer_list=NULL;
1630 ndr_pointer_list_pos=0;
1631 pointers_are_top_level=TRUE;
1635 dissect_deferred_pointers(packet_info *pinfo, tvbuff_t *tvb, int offset, guint8 *drep)
1637 int found_new_pointer;
1643 di=pinfo->private_data;
1647 found_new_pointer=0;
1648 len=g_slist_length(ndr_pointer_list);
1649 for(i=next_pointer;i<len;i++){
1650 ndr_pointer_data_t *tnpd;
1651 tnpd=g_slist_nth_data(ndr_pointer_list, i);
1653 dcerpc_dissect_fnct_t *fnct;
1656 found_new_pointer=1;
1659 ndr_pointer_list_pos=i+1;
1660 di->hf_index=tnpd->hf_index;
1661 /* first a run to handle any conformant
1663 di->conformant_run=1;
1664 di->conformant_eaten=0;
1665 old_offset = offset;
1666 offset = (*(fnct))(tvb, offset, pinfo, NULL, drep);
1668 DISSECTOR_ASSERT((offset-old_offset)==di->conformant_eaten);
1669 /* This is to check for any bugs in the dissectors.
1671 * Basically, the NDR representation will store all
1672 * arrays in two blocks, one block with the dimension
1673 * discreption, like size, number of elements and such,
1674 * and another block that contains the actual data stored
1676 * If the array is embedded directly inside another,
1677 * encapsulating aggregate type, like a union or struct,
1678 * then these two blocks will be stored at different places
1679 * in the bytestream, with other data between the blocks.
1681 * For this reason, all pointers to types (both aggregate
1682 * and scalar, for simplicity no distinction is made)
1683 * will have its dissector called twice.
1684 * The dissector will first be called with conformant_run==1
1685 * in which mode the dissector MUST NOT consume any data from
1686 * the tvbuff (i.e. may not dissect anything) except the
1687 * initial control block for arrays.
1688 * The second time the dissector is called, with
1689 * conformant_run==0, all other data for the type will be
1692 * All dissect_ndr_<type> dissectors are already prepared
1693 * for this and knows when it should eat data from the tvb
1694 * and when not to, so implementors of dissectors will
1695 * normally not need to worry about this or even know about
1696 * it. However, if a dissector for an aggregate type calls
1697 * a subdissector from outside packet-dcerpc.c, such as
1698 * the dissector in packet-smb.c for NT Security Descriptors
1699 * as an example, then it is VERY important to encapsulate
1700 * this call to an external subdissector with the appropriate
1701 * test for conformant_run, i.e. it will need something like
1705 * di=pinfo->private_data;
1706 * if(di->conformant_run){
1710 * to make sure it makes the right thing.
1711 * This assert will signal when someone has forgotten to
1712 * make the dissector aware of this requirement.
1715 /* now we dissect the actual pointer */
1716 di->conformant_run=0;
1717 old_offset = offset;
1718 offset = (*(fnct))(tvb, offset, pinfo, tnpd->tree, drep);
1720 tnpd->callback(pinfo, tnpd->tree, tnpd->item, tvb, old_offset, offset, tnpd->callback_args);
1724 } while(found_new_pointer);
1731 add_pointer_to_list(packet_info *pinfo, proto_tree *tree, proto_item *item,
1732 dcerpc_dissect_fnct_t *fnct, guint32 id, int hf_index,
1733 dcerpc_callback_fnct_t *callback, void *callback_args)
1735 ndr_pointer_data_t *npd;
1737 /* check if this pointer is valid */
1740 dcerpc_call_value *value;
1742 di=pinfo->private_data;
1743 value=di->call_data;
1745 if(di->ptype == PDU_REQ){
1746 if(!(pinfo->fd->flags.visited)){
1747 if(id>value->max_ptr){
1752 /* if we havent seen the request bail out since we cant
1753 know whether this is the first non-NULL instance
1755 if(value->req_frame==0){
1756 /* XXX THROW EXCEPTION */
1759 /* We saw this one in the request frame, nothing to
1761 if(id<=value->max_ptr){
1767 npd=g_malloc(sizeof(ndr_pointer_data_t));
1772 npd->hf_index=hf_index;
1773 npd->callback=callback;
1774 npd->callback_args=callback_args;
1775 ndr_pointer_list = g_slist_insert(ndr_pointer_list, npd,
1776 ndr_pointer_list_pos);
1777 ndr_pointer_list_pos++;
1782 find_pointer_index(guint32 id)
1784 ndr_pointer_data_t *npd;
1787 len=g_slist_length(ndr_pointer_list);
1789 npd=g_slist_nth_data(ndr_pointer_list, i);
1800 /* This function dissects an NDR pointer and stores the callback for later
1801 * deferred dissection.
1803 * fnct is the callback function for when we have reached this object in
1806 * type is what type of pointer.
1808 * this is text is what text we should put in any created tree node.
1810 * hf_index is what hf value we want to pass to the callback function when
1811 * it is called, the callback can later pich this one up from di->hf_index.
1813 * callback is executed after the pointer has been dereferenced.
1815 * callback_args is passed as an argument to the callback function
1817 * See packet-dcerpc-samr.c for examples
1820 dissect_ndr_pointer_cb(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1821 proto_tree *tree, guint8 *drep, dcerpc_dissect_fnct_t *fnct,
1822 int type, const char *text, int hf_index,
1823 dcerpc_callback_fnct_t *callback, void *callback_args)
1826 proto_tree *tr = NULL;
1827 gint start_offset = offset;
1829 di=pinfo->private_data;
1830 if(di->conformant_run){
1831 /* this call was only for dissecting the header for any
1832 embedded conformant array. we will not parse any
1833 pointers in this mode.
1838 /*TOP LEVEL REFERENCE POINTER*/
1839 if( pointers_are_top_level
1840 &&(type==NDR_POINTER_REF) ){
1843 /* we must find out a nice way to do the length here */
1844 item=proto_tree_add_text(tree, tvb, offset, 0,
1846 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1848 add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff,
1849 hf_index, callback, callback_args);
1853 /*TOP LEVEL FULL POINTER*/
1854 if( pointers_are_top_level
1855 && (type==NDR_POINTER_PTR) ){
1860 /* get the referent id */
1861 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
1863 tvb_ensure_bytes_exist(tvb, offset-4, 4);
1864 /* we got a NULL pointer */
1866 proto_tree_add_text(tree, tvb, offset-4, 4,
1867 "(NULL pointer) %s",text);
1871 /* see if we have seen this pointer before */
1872 idx=find_pointer_index(id);
1874 /* we have seen this pointer before */
1876 proto_tree_add_text(tree, tvb, offset-4, 4,
1877 "(duplicate PTR) %s",text);
1882 item=proto_tree_add_text(tree, tvb, offset-4, 4,
1884 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1885 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
1886 add_pointer_to_list(pinfo, tr, item, fnct, id, hf_index,
1887 callback, callback_args);
1890 /*TOP LEVEL UNIQUE POINTER*/
1891 if( pointers_are_top_level
1892 && (type==NDR_POINTER_UNIQUE) ){
1896 /* get the referent id */
1897 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
1899 tvb_ensure_bytes_exist(tvb, offset-4, 4);
1900 /* we got a NULL pointer */
1902 proto_tree_add_text(tree, tvb, offset-4, 4,
1903 "(NULL pointer) %s",text);
1908 item=proto_tree_add_text(tree, tvb, offset-4, 4,
1910 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1911 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
1912 add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff,
1913 hf_index, callback, callback_args);
1917 /*EMBEDDED REFERENCE POINTER*/
1918 if( (!pointers_are_top_level)
1919 && (type==NDR_POINTER_REF) ){
1923 /* get the referent id */
1924 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
1926 tvb_ensure_bytes_exist(tvb, offset-4, 4);
1928 item=proto_tree_add_text(tree, tvb, offset-4, 4,
1930 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1931 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
1932 add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff,
1933 hf_index, callback, callback_args);
1937 /*EMBEDDED UNIQUE POINTER*/
1938 if( (!pointers_are_top_level)
1939 && (type==NDR_POINTER_UNIQUE) ){
1943 /* get the referent id */
1944 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
1946 tvb_ensure_bytes_exist(tvb, offset-4, 4);
1947 /* we got a NULL pointer */
1949 proto_tree_add_text(tree, tvb, offset-4, 4,
1950 "(NULL pointer) %s", text);
1955 item=proto_tree_add_text(tree, tvb, offset-4, 4,
1957 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1958 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
1959 add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff,
1960 hf_index, callback, callback_args);
1964 /*EMBEDDED FULL POINTER*/
1965 if( (!pointers_are_top_level)
1966 && (type==NDR_POINTER_PTR) ){
1971 /* get the referent id */
1972 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
1974 tvb_ensure_bytes_exist(tvb, offset-4, 4);
1975 /* we got a NULL pointer */
1977 proto_tree_add_text(tree, tvb, offset-4, 4,
1978 "(NULL pointer) %s",text);
1982 /* see if we have seen this pointer before */
1983 idx=find_pointer_index(id);
1985 /* we have seen this pointer before */
1987 proto_tree_add_text(tree, tvb, offset-4, 4,
1988 "(duplicate PTR) %s",text);
1993 item=proto_tree_add_text(tree, tvb, offset-4, 4,
1995 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1996 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
1997 add_pointer_to_list(pinfo, tr, item, fnct, id, hf_index,
1998 callback, callback_args);
2004 /* After each top level pointer we have dissected we have to
2005 dissect all deferrals before we move on to the next top level
2007 if(pointers_are_top_level==TRUE){
2008 pointers_are_top_level=FALSE;
2009 offset = dissect_deferred_pointers(pinfo, tvb, offset, drep);
2010 pointers_are_top_level=TRUE;
2013 /* Set the length for the new subtree */
2015 proto_item_set_len(tr, offset-start_offset);
2021 dissect_ndr_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2022 proto_tree *tree, guint8 *drep, dcerpc_dissect_fnct_t *fnct,
2023 int type, const char *text, int hf_index)
2025 return dissect_ndr_pointer_cb(
2026 tvb, offset, pinfo, tree, drep, fnct, type, text, hf_index,
2030 dissect_ndr_toplevel_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2031 proto_tree *tree, guint8 *drep, dcerpc_dissect_fnct_t *fnct,
2032 int type, const char *text, int hf_index)
2036 pointers_are_top_level=TRUE;
2037 ret=dissect_ndr_pointer_cb(
2038 tvb, offset, pinfo, tree, drep, fnct, type, text, hf_index,
2043 dissect_ndr_embedded_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2044 proto_tree *tree, guint8 *drep, dcerpc_dissect_fnct_t *fnct,
2045 int type, const char *text, int hf_index)
2049 pointers_are_top_level=FALSE;
2050 ret=dissect_ndr_pointer_cb(
2051 tvb, offset, pinfo, tree, drep, fnct, type, text, hf_index,
2057 show_stub_data (tvbuff_t *tvb, gint offset, proto_tree *dcerpc_tree,
2058 dcerpc_auth_info *auth_info, gboolean is_encrypted)
2060 int length, plain_length, auth_pad_len;
2061 guint auth_pad_offset;
2064 * We don't show stub data unless we have some in the tvbuff;
2065 * however, in the protocol tree, we show, as the number of
2066 * bytes, the reported number of bytes, not the number of bytes
2067 * that happen to be in the tvbuff.
2069 if (tvb_length_remaining (tvb, offset) > 0) {
2070 auth_pad_len = auth_info?auth_info->auth_pad_len:0;
2071 length = tvb_reported_length_remaining (tvb, offset);
2073 /* if auth_pad_len is larger than length then we ignore auth_pad_len totally */
2074 plain_length = length - auth_pad_len;
2075 if (plain_length < 1) {
2076 plain_length = length;
2079 auth_pad_offset = offset + plain_length;
2081 if (auth_info != NULL &&
2082 auth_info->auth_level == DCE_C_AUTHN_LEVEL_PKT_PRIVACY) {
2084 tvb_ensure_bytes_exist(tvb, offset, length);
2085 proto_tree_add_text(dcerpc_tree, tvb, offset, length,
2086 "Encrypted stub data (%d byte%s)",
2087 length, plurality(length, "", "s"));
2088 /* is the padding is still inside the encrypted blob, don't display it explicit */
2091 tvb_ensure_bytes_exist(tvb, offset, plain_length);
2092 proto_tree_add_text(dcerpc_tree, tvb, offset, plain_length,
2093 "Decrypted stub data (%d byte%s)",
2094 plain_length, plurality(plain_length, "", "s"));
2097 tvb_ensure_bytes_exist(tvb, offset, plain_length);
2098 proto_tree_add_text (dcerpc_tree, tvb, offset, plain_length,
2099 "Stub data (%d byte%s)", plain_length,
2100 plurality(plain_length, "", "s"));
2102 /* If there is auth padding at the end of the stub, display it */
2103 if (auth_pad_len != 0) {
2104 tvb_ensure_bytes_exist(tvb, auth_pad_offset, auth_pad_len);
2105 proto_tree_add_text (dcerpc_tree, tvb, auth_pad_offset,
2107 "Auth Padding (%u byte%s)",
2109 plurality(auth_pad_len, "", "s"));
2115 dcerpc_try_handoff (packet_info *pinfo, proto_tree *tree,
2116 proto_tree *dcerpc_tree,
2117 tvbuff_t *volatile tvb, tvbuff_t *decrypted_tvb,
2118 guint8 *drep, dcerpc_info *info,
2119 dcerpc_auth_info *auth_info)
2121 volatile gint offset = 0;
2122 dcerpc_uuid_key key;
2123 dcerpc_uuid_value *sub_proto;
2124 proto_tree *volatile sub_tree = NULL;
2125 dcerpc_sub_dissector *proc;
2126 const gchar *name = NULL;
2127 dcerpc_dissect_fnct_t *volatile sub_dissect;
2128 const char *volatile saved_proto;
2129 void *volatile saved_private_data;
2130 guint length = 0, reported_length = 0;
2131 tvbuff_t *volatile stub_tvb;
2132 volatile guint auth_pad_len;
2133 volatile int auth_pad_offset;
2134 proto_item *sub_item=NULL;
2137 key.uuid = info->call_data->uuid;
2138 key.ver = info->call_data->ver;
2141 if ((sub_proto = g_hash_table_lookup (dcerpc_uuids, &key)) == NULL
2142 || !proto_is_protocol_enabled(sub_proto->proto)) {
2144 * We don't have a dissector for this UUID, or the protocol
2145 * for that UUID is disabled.
2148 proto_tree_add_boolean_hidden(dcerpc_tree, hf_dcerpc_unknown_if_id,
2149 tvb, offset, 0, TRUE);
2150 if (check_col (pinfo->cinfo, COL_INFO)) {
2151 col_append_fstr (pinfo->cinfo, COL_INFO, " %s V%u",
2152 guids_resolve_uuid_to_str(&info->call_data->uuid), info->call_data->ver);
2155 if (decrypted_tvb != NULL) {
2156 show_stub_data (decrypted_tvb, 0, dcerpc_tree, auth_info,
2159 show_stub_data (tvb, 0, dcerpc_tree, auth_info, TRUE);
2163 for (proc = sub_proto->procs; proc->name; proc++) {
2164 if (proc->num == info->call_data->opnum) {
2173 if (check_col (pinfo->cinfo, COL_PROTOCOL)) {
2174 col_set_str (pinfo->cinfo, COL_PROTOCOL, sub_proto->name);
2177 if (check_col (pinfo->cinfo, COL_INFO)) {
2178 col_add_fstr (pinfo->cinfo, COL_INFO, "%s %s",
2179 name, (info->ptype == PDU_REQ) ? "request" : "response");
2182 sub_dissect = (info->ptype == PDU_REQ) ?
2183 proc->dissect_rqst : proc->dissect_resp;
2186 sub_item = proto_tree_add_item (tree, sub_proto->proto_id,
2187 (decrypted_tvb != NULL)?decrypted_tvb:tvb,
2191 sub_tree = proto_item_add_subtree (sub_item, sub_proto->ett);
2192 proto_item_append_text(sub_item, ", %s", name);
2196 * Put the operation number into the tree along with
2197 * the operation's name.
2199 if (sub_proto->opnum_hf != -1)
2200 proto_tree_add_uint_format(sub_tree, sub_proto->opnum_hf,
2201 tvb, 0, 0, info->call_data->opnum,
2202 "Operation: %s (%u)",
2203 name, info->call_data->opnum);
2205 proto_tree_add_uint_format(sub_tree, hf_dcerpc_op, tvb,
2206 0, 0, info->call_data->opnum,
2207 "Operation: %s (%u)",
2208 name, info->call_data->opnum);
2210 if(info->ptype == PDU_REQ && info->call_data->rep_frame!=0) {
2211 pi = proto_tree_add_uint(sub_tree, hf_dcerpc_response_in,
2212 tvb, 0, 0, info->call_data->rep_frame);
2213 PROTO_ITEM_SET_GENERATED(pi);
2215 if(info->ptype == PDU_RESP && info->call_data->req_frame!=0) {
2216 pi = proto_tree_add_uint(sub_tree, hf_dcerpc_request_in,
2217 tvb, 0, 0, info->call_data->req_frame);
2218 PROTO_ITEM_SET_GENERATED(pi);
2222 if (decrypted_tvb != NULL) {
2223 /* Either there was no encryption or we successfully decrypted
2224 the encrypted payload. */
2226 /* We have a subdissector - call it. */
2227 saved_proto = pinfo->current_proto;
2228 saved_private_data = pinfo->private_data;
2229 pinfo->current_proto = sub_proto->name;
2230 pinfo->private_data = (void *)info;
2232 init_ndr_pointer_list(pinfo);
2234 length = tvb_length(decrypted_tvb);
2235 reported_length = tvb_reported_length(decrypted_tvb);
2238 * Remove the authentication padding from the stub data.
2240 if (auth_info != NULL && auth_info->auth_pad_len != 0) {
2241 if (reported_length >= auth_info->auth_pad_len) {
2243 * OK, the padding length isn't so big that it
2244 * exceeds the stub length. Trim the reported
2245 * length of the tvbuff.
2247 reported_length -= auth_info->auth_pad_len;
2250 * If that exceeds the actual amount of data in
2251 * the tvbuff (which means we have at least one
2252 * byte of authentication padding in the tvbuff),
2253 * trim the actual amount.
2255 if (length > reported_length)
2256 length = reported_length;
2258 stub_tvb = tvb_new_subset(decrypted_tvb, 0, length, reported_length);
2259 auth_pad_len = auth_info->auth_pad_len;
2260 auth_pad_offset = reported_length;
2263 * The padding length exceeds the stub length.
2264 * Don't bother dissecting the stub, trim the padding
2265 * length to what's in the stub data, and show the
2266 * entire stub as authentication padding.
2269 auth_pad_len = reported_length;
2270 auth_pad_offset = 0;
2272 reported_length = 0;
2276 * No authentication padding.
2278 stub_tvb = decrypted_tvb;
2280 auth_pad_offset = 0;
2284 proto_item_set_len(sub_item, length);
2287 if (stub_tvb != NULL) {
2289 * Catch all exceptions other than BoundsError, so that even
2290 * if the stub data is bad, we still show the authentication
2293 * If we get BoundsError, it means the frame was cut short
2294 * by a snapshot length, so there's nothing more to
2295 * dissect; just re-throw that exception.
2300 offset = sub_dissect (stub_tvb, 0, pinfo, sub_tree,
2303 /* If we have a subdissector and it didn't dissect all
2304 data in the tvb, make a note of it. */
2305 remaining = tvb_reported_length_remaining(stub_tvb, offset);
2306 if (remaining > 0) {
2307 proto_tree_add_text(sub_tree, stub_tvb, offset,
2309 "[Long frame (%d byte%s)]",
2311 plurality(remaining, "", "s"));
2312 if (check_col(pinfo->cinfo, COL_INFO))
2313 col_append_fstr(pinfo->cinfo, COL_INFO,
2314 "[Long frame (%d byte%s)]",
2316 plurality(remaining, "", "s"));
2319 } CATCH(BoundsError) {
2322 show_exception(stub_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
2326 /* If there is auth padding at the end of the stub, display it */
2327 if (auth_pad_len != 0) {
2328 tvb_ensure_bytes_exist(tvb, auth_pad_offset, auth_pad_len);
2329 proto_tree_add_text (sub_tree, decrypted_tvb, auth_pad_offset,
2331 "Auth Padding (%u byte%s)",
2333 plurality(auth_pad_len, "", "s"));
2336 pinfo->current_proto = saved_proto;
2337 pinfo->private_data = saved_private_data;
2339 /* No subdissector - show it as stub data. */
2341 show_stub_data (decrypted_tvb, 0, sub_tree, auth_info, FALSE);
2343 show_stub_data (tvb, 0, sub_tree, auth_info, TRUE);
2347 show_stub_data (tvb, 0, sub_tree, auth_info, TRUE);
2349 tap_queue_packet(dcerpc_tap, pinfo, info);
2354 dissect_dcerpc_verifier (tvbuff_t *tvb, packet_info *pinfo,
2355 proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr,
2356 dcerpc_auth_info *auth_info)
2360 auth_info->auth_data = NULL;
2362 if (auth_info->auth_size != 0) {
2363 dcerpc_auth_subdissector_fns *auth_fns;
2366 auth_offset = hdr->frag_len - hdr->auth_len;
2368 auth_tvb = tvb_new_subset(tvb, auth_offset, hdr->auth_len,
2371 auth_info->auth_data = auth_tvb;
2373 if ((auth_fns = get_auth_subdissector_fns(auth_info->auth_level,
2374 auth_info->auth_type))) {
2376 * Catch all exceptions, so that even if the verifier is bad
2377 * or we don't have all of it, we still show the stub data.
2380 dissect_auth_verf(auth_tvb, pinfo, dcerpc_tree, auth_fns,
2383 show_exception(auth_tvb, pinfo, dcerpc_tree, EXCEPT_CODE, GET_MESSAGE);
2386 tvb_ensure_bytes_exist(tvb, 0, hdr->auth_len);
2387 proto_tree_add_text (dcerpc_tree, auth_tvb, 0, hdr->auth_len,
2392 return hdr->auth_len;
2396 dissect_dcerpc_cn_auth (tvbuff_t *tvb, int stub_offset, packet_info *pinfo,
2397 proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr,
2398 gboolean are_credentials, dcerpc_auth_info *auth_info)
2400 volatile int offset;
2403 * Initially set auth_level and auth_type to zero to indicate that we
2404 * haven't yet seen any authentication level information.
2406 auth_info->auth_level = 0;
2407 auth_info->auth_type = 0;
2408 auth_info->auth_size = 0;
2409 auth_info->auth_pad_len = 0;
2412 * The authentication information is at the *end* of the PDU; in
2413 * request and response PDUs, the request and response stub data
2416 * Is there any authentication data (i.e., is the authentication length
2417 * non-zero), and is the authentication length valid (i.e., is it, plus
2418 * 8 bytes for the type/level/pad length/reserved/context id, less than
2419 * or equal to the fragment length minus the starting offset of the
2424 && (hdr->auth_len + 8 <= hdr->frag_len - stub_offset)) {
2427 * Yes, there is authentication data, and the length is valid.
2428 * Do we have all the bytes of stub data?
2429 * (If not, we'd throw an exception dissecting *that*, so don't
2430 * bother trying to dissect the authentication information and
2431 * throwing another exception there.)
2433 offset = hdr->frag_len - (hdr->auth_len + 8);
2434 if (offset == 0 || tvb_offset_exists(tvb, offset - 1)) {
2436 * Either there's no stub data, or the last byte of the stub
2437 * data is present in the captured data, so we shouldn't
2438 * get a BoundsError dissecting the stub data.
2440 * Try dissecting the authentication data.
2441 * Catch all exceptions, so that even if the auth info is bad
2442 * or we don't have all of it, we still show the stuff we
2443 * dissect after this, such as stub data.
2446 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2447 hf_dcerpc_auth_type,
2448 &auth_info->auth_type);
2449 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2450 hf_dcerpc_auth_level,
2451 &auth_info->auth_level);
2453 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2454 hf_dcerpc_auth_pad_len,
2455 &auth_info->auth_pad_len);
2456 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2457 hf_dcerpc_auth_rsrvd, NULL);
2458 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2459 hf_dcerpc_auth_ctx_id, NULL);
2462 * Dissect the authentication data.
2464 if (are_credentials) {
2466 dcerpc_auth_subdissector_fns *auth_fns;
2468 auth_tvb = tvb_new_subset(tvb, offset,
2469 MIN(hdr->auth_len,tvb_length_remaining(tvb, offset)),
2472 if ((auth_fns = get_auth_subdissector_fns(auth_info->auth_level,
2473 auth_info->auth_type)))
2474 dissect_auth_verf(auth_tvb, pinfo, dcerpc_tree, auth_fns,
2477 proto_tree_add_text (dcerpc_tree, tvb, offset, hdr->auth_len,
2478 "Auth Credentials");
2481 /* Compute the size of the auth block. Note that this should not
2482 include auth padding, since when NTLMSSP encryption is used, the
2483 padding is actually inside the encrypted stub */
2484 auth_info->auth_size = hdr->auth_len + 8;
2486 show_exception(tvb, pinfo, dcerpc_tree, EXCEPT_CODE, GET_MESSAGE);
2493 /* We need to hash in the SMB fid number to generate a unique hash table
2494 * key as DCERPC over SMB allows several pipes over the same TCP/IP
2496 * We pass this function the transport type here to make sure we only look
2497 * at this function if it came across an SMB pipe.
2498 * Other transports might need to mix in their own extra multiplexing data
2499 * as well in the future.
2502 guint16 dcerpc_get_transport_salt (packet_info *pinfo)
2504 switch(pinfo->dcetransporttype){
2505 case DCE_CN_TRANSPORT_SMBPIPE:
2506 /* DCERPC over smb */
2507 return pinfo->dcetransportsalt;
2510 /* Some other transport... */
2515 * Connection oriented packet types
2519 dissect_dcerpc_cn_bind (tvbuff_t *tvb, gint offset, packet_info *pinfo,
2520 proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr)
2522 conversation_t *conv = NULL;
2523 guint8 num_ctx_items = 0;
2525 gboolean saw_ctx_item = FALSE;
2527 guint8 num_trans_items;
2532 guint16 if_ver, if_ver_minor;
2533 dcerpc_auth_info auth_info;
2535 const char *uuid_name = NULL;
2536 proto_item *iface_item;
2538 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2539 hf_dcerpc_cn_max_xmit, NULL);
2541 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2542 hf_dcerpc_cn_max_recv, NULL);
2544 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2545 hf_dcerpc_cn_assoc_group, NULL);
2547 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2548 hf_dcerpc_cn_num_ctx_items, &num_ctx_items);
2553 for (i = 0; i < num_ctx_items; i++) {
2554 proto_item *ctx_item;
2555 proto_tree *ctx_tree = NULL, *iface_tree = NULL;
2556 gint ctx_offset = offset;
2558 dissect_dcerpc_uint16 (tvb, offset, pinfo, NULL, hdr->drep,
2559 hf_dcerpc_cn_ctx_id, &ctx_id);
2561 if (check_col (pinfo->cinfo, COL_DCE_CTX)) {
2562 if(pinfo->dcectxid == 0) {
2563 col_append_fstr (pinfo->cinfo, COL_DCE_CTX, "%u", ctx_id);
2565 /* this is not the first DCE-RPC request/response in this (TCP?-)PDU,
2566 * prepend a delimiter */
2567 col_append_fstr (pinfo->cinfo, COL_DCE_CTX, "#%u", ctx_id);
2571 /* save context ID for use with dcerpc_add_conv_to_bind_table() */
2572 /* (if we have multiple contexts, this might cause "decode as"
2573 * to behave unpredictably) */
2574 pinfo->dcectxid = ctx_id;
2577 ctx_item = proto_tree_add_item(dcerpc_tree, hf_dcerpc_cn_ctx_item,
2579 hdr->drep[0] & 0x10);
2580 ctx_tree = proto_item_add_subtree(ctx_item, ett_dcerpc_cn_ctx);
2583 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, ctx_tree, hdr->drep,
2584 hf_dcerpc_cn_ctx_id, &ctx_id);
2585 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, ctx_tree, hdr->drep,
2586 hf_dcerpc_cn_num_trans_items, &num_trans_items);
2589 proto_item_append_text(ctx_item, "[%u]: ID:%u", i+1, ctx_id);
2595 dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &if_id);
2598 iface_item = proto_tree_add_item(ctx_tree, hf_dcerpc_cn_bind_abstract_syntax, tvb, offset, 0, FALSE);
2599 iface_tree = proto_item_add_subtree(iface_item, ett_dcerpc_cn_iface);
2601 uuid_str = guid_to_str((e_guid_t*)&if_id);
2602 uuid_name = guids_get_uuid_name(&if_id);
2604 proto_tree_add_guid_format (iface_tree, hf_dcerpc_cn_bind_if_id, tvb,
2605 offset, 16, (e_guid_t *) &if_id, "Interface: %s UUID: %s", uuid_name, uuid_str);
2606 proto_item_append_text(iface_item, ": %s", uuid_name);
2608 proto_tree_add_guid_format (iface_tree, hf_dcerpc_cn_bind_if_id, tvb,
2609 offset, 16, (e_guid_t *) &if_id, "Interface UUID: %s", uuid_str);
2610 proto_item_append_text(iface_item, ": %s", uuid_str);
2615 if (hdr->drep[0] & 0x10) {
2616 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, iface_tree, hdr->drep,
2617 hf_dcerpc_cn_bind_if_ver, &if_ver);
2618 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, iface_tree, hdr->drep,
2619 hf_dcerpc_cn_bind_if_ver_minor, &if_ver_minor);
2621 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, iface_tree, hdr->drep,
2622 hf_dcerpc_cn_bind_if_ver_minor, &if_ver_minor);
2623 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, iface_tree, hdr->drep,
2624 hf_dcerpc_cn_bind_if_ver, &if_ver);
2628 proto_item_append_text(iface_item, " V%u.%u", if_ver, if_ver_minor);
2629 proto_item_set_len(iface_item, 20);
2632 if (!saw_ctx_item) {
2633 conv = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
2634 pinfo->srcport, pinfo->destport, 0);
2636 conv = conversation_new (pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
2637 pinfo->srcport, pinfo->destport, 0);
2641 /* if this is the first time we see this packet, we need to
2642 update the dcerpc_binds table so that any later calls can
2643 match to the interface.
2644 XXX We assume that BINDs will NEVER be fragmented.
2646 if(!(pinfo->fd->flags.visited)){
2647 dcerpc_bind_key *key;
2648 dcerpc_bind_value *value;
2650 key = se_alloc (sizeof (dcerpc_bind_key));
2652 key->ctx_id = ctx_id;
2653 key->smb_fid = dcerpc_get_transport_salt(pinfo);
2655 value = se_alloc (sizeof (dcerpc_bind_value));
2656 value->uuid = if_id;
2657 value->ver = if_ver;
2659 /* add this entry to the bind table, first removing any
2660 previous ones that are identical
2662 if(g_hash_table_lookup(dcerpc_binds, key)){
2663 g_hash_table_remove(dcerpc_binds, key);
2665 g_hash_table_insert (dcerpc_binds, key, value);
2668 if (check_col (pinfo->cinfo, COL_INFO)) {
2669 if (num_ctx_items > 1)
2670 col_append_fstr(pinfo->cinfo, COL_INFO, ", %u context items, 1st", num_ctx_items);
2672 col_append_fstr(pinfo->cinfo, COL_INFO, " %s V%u.%u",
2673 guids_resolve_uuid_to_str(&if_id), if_ver, if_ver_minor);
2675 saw_ctx_item = TRUE;
2678 for (j = 0; j < num_trans_items; j++) {
2679 proto_tree *trans_tree = NULL;
2680 proto_item *trans_item = NULL;
2682 dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &trans_id);
2685 trans_item = proto_tree_add_item(ctx_tree, hf_dcerpc_cn_bind_trans_syntax, tvb, offset, 0, FALSE);
2686 trans_tree = proto_item_add_subtree(trans_item, ett_dcerpc_cn_trans_syntax);
2688 uuid_str = guid_to_str((e_guid_t *) &trans_id);
2689 proto_tree_add_guid_format (trans_tree, hf_dcerpc_cn_bind_trans_id, tvb,
2690 offset, 16, (e_guid_t *) &trans_id, "Transfer Syntax: %s", uuid_str);
2691 proto_item_append_text(trans_item, "[%u]: %s", j+1, uuid_str);
2695 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, trans_tree, hdr->drep,
2696 hf_dcerpc_cn_bind_trans_ver, &trans_ver);
2698 proto_item_set_len(trans_item, 20);
2699 proto_item_append_text(trans_item, " V%u", trans_ver);
2704 proto_item_set_len(ctx_item, offset - ctx_offset);
2709 * XXX - we should save the authentication type *if* we have
2710 * an authentication header, and associate it with an authentication
2711 * context, so subsequent PDUs can use that context.
2713 dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, hdr, TRUE, &auth_info);
2717 dissect_dcerpc_cn_bind_ack (tvbuff_t *tvb, gint offset, packet_info *pinfo,
2718 proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr)
2720 guint16 max_xmit, max_recv;
2721 guint16 sec_addr_len;
2728 dcerpc_auth_info auth_info;
2730 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2731 hf_dcerpc_cn_max_xmit, &max_xmit);
2733 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2734 hf_dcerpc_cn_max_recv, &max_recv);
2736 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2737 hf_dcerpc_cn_assoc_group, NULL);
2739 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2740 hf_dcerpc_cn_sec_addr_len, &sec_addr_len);
2741 if (sec_addr_len != 0) {
2742 tvb_ensure_bytes_exist(tvb, offset, sec_addr_len);
2743 proto_tree_add_item (dcerpc_tree, hf_dcerpc_cn_sec_addr, tvb, offset,
2744 sec_addr_len, FALSE);
2745 offset += sec_addr_len;
2749 offset += 4 - offset % 4;
2752 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2753 hf_dcerpc_cn_num_results, &num_results);
2758 for (i = 0; i < num_results; i++) {
2759 proto_tree *ctx_tree = NULL;
2762 proto_item *ctx_item;
2763 ctx_item = proto_tree_add_text(dcerpc_tree, tvb, offset, 24, "Context ID[%u]", i+1);
2764 ctx_tree = proto_item_add_subtree(ctx_item, ett_dcerpc_cn_ctx);
2767 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, ctx_tree,
2768 hdr->drep, hf_dcerpc_cn_ack_result,
2771 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, ctx_tree,
2772 hdr->drep, hf_dcerpc_cn_ack_reason,
2776 * The reason for rejection isn't meaningful, and often isn't
2777 * set, when the syntax was accepted.
2782 dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &trans_id);
2784 proto_tree_add_guid_format (ctx_tree, hf_dcerpc_cn_ack_trans_id, tvb,
2785 offset, 16, (e_guid_t *) &trans_id, "Transfer Syntax: %s",
2786 guid_to_str((e_guid_t *) &trans_id));
2790 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, ctx_tree, hdr->drep,
2791 hf_dcerpc_cn_ack_trans_ver, &trans_ver);
2795 * XXX - do we need to do anything with the authentication level
2796 * we get back from this?
2798 dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, hdr, TRUE, &auth_info);
2800 if (check_col (pinfo->cinfo, COL_INFO)) {
2801 if (num_results != 0 && result == 0) {
2802 /* XXX - only checks the last result */
2803 col_append_fstr (pinfo->cinfo, COL_INFO,
2804 " accept max_xmit: %u max_recv: %u",
2805 max_xmit, max_recv);
2807 /* XXX - only shows the last result and reason */
2808 col_append_fstr (pinfo->cinfo, COL_INFO, " %s, reason: %s",
2809 val_to_str(result, p_cont_result_vals,
2810 "Unknown result (%u)"),
2811 val_to_str(reason, p_provider_reason_vals,
2818 dissect_dcerpc_cn_bind_nak (tvbuff_t *tvb, gint offset, packet_info *pinfo,
2819 proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr)
2822 guint8 num_protocols;
2825 offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
2826 hdr->drep, hf_dcerpc_cn_reject_reason,
2829 if (check_col (pinfo->cinfo, COL_INFO)) {
2830 col_append_fstr (pinfo->cinfo, COL_INFO, " reason: %s",
2831 val_to_str(reason, reject_reason_vals, "Unknown (%u)"));
2834 if (reason == PROTOCOL_VERSION_NOT_SUPPORTED) {
2835 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2836 hf_dcerpc_cn_num_protocols,
2839 for (i = 0; i < num_protocols; i++) {
2840 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree,
2841 hdr->drep, hf_dcerpc_cn_protocol_ver_major,
2843 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree,
2844 hdr->drep, hf_dcerpc_cn_protocol_ver_minor,
2850 /* Return a string describing a DCE/RPC fragment as first, middle, or end
2853 #define PFC_FRAG_MASK 0x03
2856 fragment_type(guint8 flags)
2858 flags = flags & PFC_FRAG_MASK;
2860 if (flags == PFC_FIRST_FRAG)
2866 if (flags == PFC_LAST_FRAG)
2869 if (flags == (PFC_FIRST_FRAG | PFC_LAST_FRAG))
2875 /* Dissect stub data (payload) of a DCERPC packet. */
2878 dissect_dcerpc_cn_stub (tvbuff_t *tvb, int offset, packet_info *pinfo,
2879 proto_tree *dcerpc_tree, proto_tree *tree,
2880 e_dce_cn_common_hdr_t *hdr, dcerpc_info *di,
2881 dcerpc_auth_info *auth_info, guint32 alloc_hint _U_,
2884 gint length, reported_length;
2885 gboolean save_fragmented;
2886 fragment_data *fd_head=NULL;
2888 tvbuff_t *auth_tvb, *payload_tvb, *decrypted_tvb;
2890 proto_item *parent_pi;
2891 proto_item *dcerpc_tree_item;
2893 save_fragmented = pinfo->fragmented;
2895 length = tvb_length_remaining(tvb, offset);
2896 reported_length = tvb_reported_length_remaining(tvb, offset);
2897 if (reported_length < 0 ||
2898 (guint32)reported_length < auth_info->auth_size) {
2899 /* We don't even have enough bytes for the authentication
2903 reported_length -= auth_info->auth_size;
2904 if (length > reported_length)
2905 length = reported_length;
2906 payload_tvb = tvb_new_subset(tvb, offset, length, reported_length);
2909 /*dont bother if we dont have the entire tvb */
2910 /*XXX we should really make sure we calculate auth_info->auth_data
2911 and use that one instead of this auth_tvb hack
2913 if(tvb_length(tvb)==tvb_reported_length(tvb)){
2914 if(tvb_length_remaining(tvb, offset+length)>8){
2915 auth_tvb = tvb_new_subset(tvb, offset+length+8, -1, -1);
2919 /* Decrypt the PDU if it is encrypted */
2921 if (auth_info->auth_type &&
2922 auth_info->auth_level == DCE_C_AUTHN_LEVEL_PKT_PRIVACY) {
2924 * We know the authentication type, and the authentication
2925 * level is "Packet privacy", meaning the payload is
2926 * encrypted; attempt to decrypt it.
2928 dcerpc_auth_subdissector_fns *auth_fns;
2930 /* Start out assuming we won't succeed in decrypting. */
2931 decrypted_tvb = NULL;
2933 if ((auth_fns = get_auth_subdissector_fns(
2934 auth_info->auth_level, auth_info->auth_type))) {
2937 result = decode_encrypted_data(
2938 payload_tvb, auth_tvb, pinfo, auth_fns,
2939 hdr->ptype == PDU_REQ, auth_info);
2943 proto_tree_add_text(
2944 dcerpc_tree, payload_tvb, 0, -1,
2945 "Encrypted stub data (%d byte%s)",
2946 tvb_reported_length(payload_tvb),
2948 plurality(tvb_length(payload_tvb), "", "s"));
2950 add_new_data_source(
2951 pinfo, result, "Decrypted stub data");
2954 decrypted_tvb = result;
2958 decrypted_tvb = payload_tvb;
2960 /* if this packet is not fragmented, just dissect it and exit */
2961 if(PFC_NOT_FRAGMENTED(hdr)){
2962 pinfo->fragmented = FALSE;
2965 pinfo, tree, dcerpc_tree, payload_tvb, decrypted_tvb,
2966 hdr->drep, di, auth_info);
2968 pinfo->fragmented = save_fragmented;
2972 /* The packet is fragmented. */
2973 pinfo->fragmented = TRUE;
2975 /* debug output of essential fragment data. */
2976 /* leave it here for future debugging sessions */
2977 /*printf("DCE num:%u offset:%u frag_len:%u tvb_len:%u\n",
2978 pinfo->fd->num, offset, hdr->frag_len, tvb_length(decrypted_tvb));*/
2980 /* if we are not doing reassembly and this is the first fragment
2981 then just dissect it and exit
2982 XXX - if we're not doing reassembly, can we decrypt an
2985 if( (!dcerpc_reassemble) && hdr->flags&PFC_FIRST_FRAG ){
2988 pinfo, tree, dcerpc_tree, payload_tvb, decrypted_tvb,
2989 hdr->drep, di, auth_info);
2991 if (check_col(pinfo->cinfo, COL_INFO)) {
2992 col_append_fstr(pinfo->cinfo, COL_INFO,
2993 " [DCE/RPC %s fragment]", fragment_type(hdr->flags));
2995 expert_add_info_format(pinfo, NULL, PI_REASSEMBLE, PI_CHAT,
2996 "%s fragment", fragment_type(hdr->flags));
2997 pinfo->fragmented = save_fragmented;
3001 /* if we have already seen this packet, see if it was reassembled
3002 and if so dissect the full pdu.
3005 if(pinfo->fd->flags.visited){
3006 fd_head=fragment_get_reassembled(pinfo, frame, dcerpc_co_reassemble_table);
3010 /* if we are not doing reassembly and it was neither a complete PDU
3011 nor the first fragment then there is nothing more we can do
3012 so we just have to exit
3014 if( !dcerpc_reassemble || (tvb_length(tvb)!=tvb_reported_length(tvb)) )
3017 /* if we didnt get 'frame' we dont know where the PDU started and thus
3018 it is pointless to continue
3023 /* from now on we must attempt to reassemble the PDU
3026 /* if we get here we know it is the first time we see the packet
3027 and we also know it is only a fragment and not a full PDU,
3028 thus we must reassemble it.
3031 /* Do we have any non-encrypted data to reassemble? */
3032 if (decrypted_tvb == NULL) {
3033 /* No. We can't even try to reassemble. */
3037 /* defragmentation is a bit tricky, as there's no offset of the fragment
3038 * in the protocol data.
3040 * just use fragment_add_seq_next() and hope that TCP/SMB segments coming
3041 * in with the correct sequence.
3043 fd_head = fragment_add_seq_next(decrypted_tvb, 0, pinfo, frame,
3044 dcerpc_co_fragment_table, dcerpc_co_reassemble_table,
3045 tvb_length(decrypted_tvb),
3046 hdr->flags&PFC_LAST_FRAG ? FALSE : TRUE /* more_frags */);
3050 /* if reassembly is complete and this is the last fragment
3051 * (multiple fragments in one PDU are possible!)
3052 * dissect the full PDU
3054 if(fd_head && (fd_head->flags&FD_DEFRAGMENTED) ){
3056 if(pinfo->fd->num==fd_head->reassembled_in && (hdr->flags&PFC_LAST_FRAG) ){
3058 proto_item *frag_tree_item;
3060 next_tvb = tvb_new_real_data(fd_head->data, fd_head->len, fd_head->len);
3062 tvb_set_child_real_data_tvbuff(decrypted_tvb, next_tvb);
3064 tvb_set_child_real_data_tvbuff(payload_tvb, next_tvb);
3066 add_new_data_source(pinfo, next_tvb, "Reassembled DCE/RPC");
3067 show_fragment_tree(fd_head, &dcerpc_frag_items,
3068 tree, pinfo, next_tvb, &frag_tree_item);
3069 /* the toplevel fragment subtree is now behind all desegmented data,
3070 * move it right behind the DCE/RPC tree */
3071 dcerpc_tree_item = proto_tree_get_parent(dcerpc_tree);
3072 if(frag_tree_item && dcerpc_tree_item) {
3073 proto_tree_move_item(tree, dcerpc_tree_item, frag_tree_item);
3076 pinfo->fragmented = FALSE;
3078 expert_add_info_format(pinfo, frag_tree_item, PI_REASSEMBLE, PI_CHAT,
3079 "%s fragment, reassembled",
3080 fragment_type(hdr->flags));
3082 dcerpc_try_handoff (pinfo, tree, dcerpc_tree, next_tvb,
3083 next_tvb, hdr->drep, di, auth_info);
3087 pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_reassembled_in,
3088 decrypted_tvb, 0, 0, fd_head->reassembled_in);
3090 pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_reassembled_in,
3091 payload_tvb, 0, 0, fd_head->reassembled_in);