add missing _WIN32 encapsulation so braces match and compilation under non-win32...
[obnox/wireshark/wip.git] / epan / dissectors / packet-dcerpc.c
1 /* packet-dcerpc.c
2  * Routines for DCERPC packet disassembly
3  * Copyright 2001, Todd Sabin <tas@webspan.net>
4  * Copyright 2003, Tim Potter <tpot@samba.org>
5  *
6  * $Id$
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  *
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.
16  *
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.
21  *
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.
25  */
26
27 /* The DCE RPC specification can be found at:
28  * http://www.opengroup.org/dce/
29  */
30
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34
35 #include <string.h>
36 #include <ctype.h>
37
38 #include <glib.h>
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>
44 #include <epan/tap.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>
50
51 #ifdef _WIN32
52 #include <tchar.h>
53 #endif
54
55 static int dcerpc_tap = -1;
56
57
58 static const value_string pckt_vals[] = {
59     { PDU_REQ,        "Request"},
60     { PDU_PING,       "Ping"},
61     { PDU_RESP,       "Response"},
62     { PDU_FAULT,      "Fault"},
63     { PDU_WORKING,    "Working"},
64     { PDU_NOCALL,     "Nocall"},
65     { PDU_REJECT,     "Reject"},
66     { PDU_ACK,        "Ack"},
67     { PDU_CL_CANCEL,  "Cl_cancel"},
68     { PDU_FACK,       "Fack"},
69     { PDU_CANCEL_ACK, "Cancel_ack"},
70     { PDU_BIND,       "Bind"},
71     { PDU_BIND_ACK,   "Bind_ack"},
72     { PDU_BIND_NAK,   "Bind_nak"},
73     { PDU_ALTER,      "Alter_context"},
74     { PDU_ALTER_ACK,  "Alter_context_resp"},
75     { PDU_AUTH3,      "AUTH3"},
76     { PDU_SHUTDOWN,   "Shutdown"},
77     { PDU_CO_CANCEL,  "Co_cancel"},
78     { PDU_ORPHANED,   "Orphaned"},
79     { 0,              NULL }
80 };
81
82 static const value_string drep_byteorder_vals[] = {
83     { 0, "Big-endian" },
84     { 1, "Little-endian" },
85     { 0,  NULL }
86 };
87
88 static const value_string drep_character_vals[] = {
89     { 0, "ASCII" },
90     { 1, "EBCDIC" },
91     { 0,  NULL }
92 };
93
94 #define DCE_RPC_DREP_FP_IEEE 0
95 #define DCE_RPC_DREP_FP_VAX  1
96 #define DCE_RPC_DREP_FP_CRAY 2
97 #define DCE_RPC_DREP_FP_IBM  3
98
99 static const value_string drep_fp_vals[] = {
100     { DCE_RPC_DREP_FP_IEEE, "IEEE" },
101     { DCE_RPC_DREP_FP_VAX,  "VAX"  },
102     { DCE_RPC_DREP_FP_CRAY, "Cray" },
103     { DCE_RPC_DREP_FP_IBM,  "IBM"  },
104     { 0,  NULL }
105 };
106
107 /*
108  * Authentication services.
109  */
110 static const value_string authn_protocol_vals[] = {
111         { DCE_C_RPC_AUTHN_PROTOCOL_NONE,    "None" },
112         { DCE_C_RPC_AUTHN_PROTOCOL_KRB5,    "Kerberos 5" },
113         { DCE_C_RPC_AUTHN_PROTOCOL_SPNEGO,  "SPNEGO" },
114         { DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP, "NTLMSSP" },
115         { DCE_C_RPC_AUTHN_PROTOCOL_GSS_SCHANNEL, "SCHANNEL SSP" },
116         { DCE_C_RPC_AUTHN_PROTOCOL_GSS_KERBEROS, "Kerberos SSP" },
117         { DCE_C_RPC_AUTHN_PROTOCOL_DPA,
118                 "Distributed Password Authentication SSP"},
119         { DCE_C_RPC_AUTHN_PROTOCOL_MSN, "MSN SSP"},
120         { DCE_C_RPC_AUTHN_PROTOCOL_DIGEST, "Digest SSP"},
121         { DCE_C_RPC_AUTHN_PROTOCOL_SEC_CHAN,"NETLOGON Secure Channel" },
122         { DCE_C_RPC_AUTHN_PROTOCOL_MQ, "MSMQ SSP"},
123         { 0, NULL }
124 };
125
126 /*
127  * Protection levels.
128  */
129 static const value_string authn_level_vals[] = {
130         { DCE_C_AUTHN_LEVEL_NONE,          "None" },
131         { DCE_C_AUTHN_LEVEL_CONNECT,       "Connect" },
132         { DCE_C_AUTHN_LEVEL_CALL,          "Call" },
133         { DCE_C_AUTHN_LEVEL_PKT,           "Packet" },
134         { DCE_C_AUTHN_LEVEL_PKT_INTEGRITY, "Packet integrity" },
135         { DCE_C_AUTHN_LEVEL_PKT_PRIVACY,   "Packet privacy" },
136         { 0,                               NULL }
137 };
138
139 /*
140  * Flag bits in first flag field in connectionless PDU header.
141  */
142 #define PFCL1_RESERVED_01       0x01    /* Reserved for use by implementations */
143 #define PFCL1_LASTFRAG          0x02    /* If set, the PDU is the last
144                                          * fragment of a multi-PDU
145                                          * transmission */
146 #define PFCL1_FRAG              0x04    /* If set, the PDU is a fragment of
147                                            a multi-PDU transmission */
148 #define PFCL1_NOFACK            0x08    /* If set, the receiver is not
149                                          * requested to send a `fack' PDU
150                                          * for the fragment */
151 #define PFCL1_MAYBE             0x10    /* If set, the PDU is for a `maybe'
152                                          * request */
153 #define PFCL1_IDEMPOTENT        0x20    /* If set, the PDU is for an idempotent
154                                          * request */
155 #define PFCL1_BROADCAST         0x40    /* If set, the PDU is for a broadcast
156                                          * request */
157 #define PFCL1_RESERVED_80       0x80    /* Reserved for use by implementations */
158
159 /*
160  * Flag bits in second flag field in connectionless PDU header.
161  */
162 #define PFCL2_RESERVED_01       0x01    /* Reserved for use by implementations */
163 #define PFCL2_CANCEL_PENDING    0x02    /* Cancel pending at the call end */
164 #define PFCL2_RESERVED_04       0x04    /* Reserved for future use */
165 #define PFCL2_RESERVED_08       0x08    /* Reserved for future use */
166 #define PFCL2_RESERVED_10       0x10    /* Reserved for future use */
167 #define PFCL2_RESERVED_20       0x20    /* Reserved for future use */
168 #define PFCL2_RESERVED_40       0x40    /* Reserved for future use */
169 #define PFCL2_RESERVED_80       0x80    /* Reserved for future use */
170
171 /*
172  * Flag bits in connection-oriented PDU header.
173  */
174 #define PFC_FIRST_FRAG          0x01    /* First fragment */
175 #define PFC_LAST_FRAG           0x02    /* Last fragment */
176 #define PFC_PENDING_CANCEL      0x04    /* Cancel was pending at sender */
177 #define PFC_RESERVED_1          0x08
178 #define PFC_CONC_MPX            0x10    /* suports concurrent multiplexing
179                                          * of a single connection. */
180 #define PFC_DID_NOT_EXECUTE     0x20    /* only meaningful on `fault' packet;
181                                          * if true, guaranteed call did not
182                                          * execute. */
183 #define PFC_MAYBE               0x40    /* `maybe' call semantics requested */
184 #define PFC_OBJECT_UUID         0x80    /* if true, a non-nil object UUID
185                                          * was specified in the handle, and
186                                          * is present in the optional object
187                                          * field. If false, the object field
188                                          * is omitted. */
189
190 /*
191  * Tests whether a connection-oriented PDU is fragmented; returns TRUE if
192  * it's not fragmented (i.e., this is both the first *and* last fragment),
193  * and FALSE otherwise.
194  */
195 #define PFC_NOT_FRAGMENTED(hdr) \
196   ((hdr->flags&(PFC_FIRST_FRAG|PFC_LAST_FRAG))==(PFC_FIRST_FRAG|PFC_LAST_FRAG))
197
198 /*
199  * Presentation context negotiation result.
200  */
201 static const value_string p_cont_result_vals[] = {
202         { 0, "Acceptance" },
203         { 1, "User rejection" },
204         { 2, "Provider rejection" },
205         { 0, NULL }
206 };
207
208 /*
209  * Presentation context negotiation rejection reasons.
210  */
211 static const value_string p_provider_reason_vals[] = {
212         { 0, "Reason not specified" },
213         { 1, "Abstract syntax not supported" },
214         { 2, "Proposed transfer syntaxes not supported" },
215         { 3, "Local limit exceeded" },
216         { 0, NULL }
217 };
218
219 /*
220  * Reject reasons.
221  */
222 #define REASON_NOT_SPECIFIED            0
223 #define TEMPORARY_CONGESTION            1
224 #define LOCAL_LIMIT_EXCEEDED            2
225 #define CALLED_PADDR_UNKNOWN            3 /* not used */
226 #define PROTOCOL_VERSION_NOT_SUPPORTED  4
227 #define DEFAULT_CONTEXT_NOT_SUPPORTED   5 /* not used */
228 #define USER_DATA_NOT_READABLE          6 /* not used */
229 #define NO_PSAP_AVAILABLE               7 /* not used */
230 #define AUTH_TYPE_NOT_RECOGNIZED        8
231 #define INVALID_CHECKSUM                        9
232
233 static const value_string reject_reason_vals[] = {
234         { REASON_NOT_SPECIFIED,           "Reason not specified" },
235         { TEMPORARY_CONGESTION,           "Temporary congestion" },
236         { LOCAL_LIMIT_EXCEEDED,           "Local limit exceeded" },
237         { CALLED_PADDR_UNKNOWN,           "Called paddr unknown" },
238         { PROTOCOL_VERSION_NOT_SUPPORTED, "Protocol version not supported" },
239         { DEFAULT_CONTEXT_NOT_SUPPORTED,  "Default context not supported" },
240         { USER_DATA_NOT_READABLE,         "User data not readable" },
241         { NO_PSAP_AVAILABLE,              "No PSAP available" },
242         { AUTH_TYPE_NOT_RECOGNIZED,       "Authentication type not recognized" },
243         { INVALID_CHECKSUM,               "Invalid checksum" },
244         { 0,                              NULL }
245 };
246
247 /*
248  * Reject status codes.
249  */
250 static const value_string reject_status_vals[] = {
251         { 0,          "Stub-defined exception" },
252         { 0x00000001, "nca_s_fault_other" },
253         { 0x00000005, "nca_s_fault_access_denied" },
254         { 0x000006f7, "nca_s_fault_ndr" },
255         { 0x000006d8, "nca_s_fault_cant_perform" },
256         { 0x1c000001, "nca_s_fault_int_div_by_zero" },
257         { 0x1c000002, "nca_s_fault_addr_error" },
258         { 0x1c000003, "nca_s_fault_fp_div_zero" },
259         { 0x1c000004, "nca_s_fault_fp_underflow" },
260         { 0x1c000005, "nca_s_fault_fp_overflow" },
261         { 0x1c000006, "nca_s_fault_invalid_tag" },
262         { 0x1c000007, "nca_s_fault_invalid_bound" },
263         { 0x1c000008, "nca_rpc_version_mismatch" },
264         { 0x1c000009, "nca_unspec_reject" },
265         { 0x1c00000a, "nca_s_bad_actid" },
266         { 0x1c00000b, "nca_who_are_you_failed" },
267         { 0x1c00000c, "nca_manager_not_entered" },
268         { 0x1c00000d, "nca_s_fault_cancel" },
269         { 0x1c00000e, "nca_s_fault_ill_inst" },
270         { 0x1c00000f, "nca_s_fault_fp_error" },
271         { 0x1c000010, "nca_s_fault_int_overflow" },
272         { 0x1c000014, "nca_s_fault_pipe_empty" },
273         { 0x1c000015, "nca_s_fault_pipe_closed" },
274         { 0x1c000016, "nca_s_fault_pipe_order" },
275         { 0x1c000017, "nca_s_fault_pipe_discipline" },
276         { 0x1c000018, "nca_s_fault_pipe_comm_error" },
277         { 0x1c000019, "nca_s_fault_pipe_memory" },
278         { 0x1c00001a, "nca_s_fault_context_mismatch" },
279         { 0x1c00001b, "nca_s_fault_remote_no_memory" },
280         { 0x1c00001c, "nca_invalid_pres_context_id" },
281         { 0x1c00001d, "nca_unsupported_authn_level" },
282         { 0x1c00001f, "nca_invalid_checksum" },
283         { 0x1c000020, "nca_invalid_crc" },
284         { 0x1c000021, "ncs_s_fault_user_defined" },
285         { 0x1c000022, "nca_s_fault_tx_open_failed" },
286         { 0x1c000023, "nca_s_fault_codeset_conv_error" },
287         { 0x1c000024, "nca_s_fault_object_not_found" },
288         { 0x1c000025, "nca_s_fault_no_client_stub" },
289         { 0x1c010002, "nca_op_rng_error" },
290         { 0x1c010003, "nca_unk_if"},
291         { 0x1c010006, "nca_wrong_boot_time" },
292         { 0x1c010009, "nca_s_you_crashed" },
293         { 0x1c01000b, "nca_proto_error" },
294         { 0x1c010013, "nca_out_args_too_big" },
295         { 0x1c010014, "nca_server_too_busy" },
296         { 0x1c010017, "nca_unsupported_type" },
297         /* MS Windows specific values
298          * see: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/debug/base/system_error_codes__1700-3999_.asp
299          * and: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/seccrypto/security/common_hresult_values.asp
300          * and: http://www.megos.ch/support/doserrors.txt
301          *
302          * XXX - we might need a way to dynamically add entries here, as higher layer protocols use these values too,
303          * at least MS protocols (like DCOM) do it that way ... */
304         { 0x80004001, "E_NOTIMPL" },
305         { 0x80004003, "E_POINTER" },
306         { 0x80004004, "E_ABORT" },
307         { 0x8000FFFF, "E_UNEXPECTED" },
308         { 0x80010105, "RPC_E_SERVERFAULT" },
309         { 0x80010108, "RPC_E_DISCONNECTED" },
310         { 0x80010113, "RPC_E_INVALID_IPID" },
311         { 0x8001011F, "RPC_E_TIMEOUT" },
312         { 0x80020003, "DISP_E_MEMBERNOTFOUND" },
313         { 0x80020006, "DISP_E_UNKNOWNNAME" },
314         { 0x8002000E, "DISP_E_BADPARAMCOUNT" },
315         { 0x8004CB00, "CBA_E_MALFORMED" },
316         { 0x8004CB01, "CBA_E_UNKNOWNOBJECT" },
317         { 0x8004CB09, "CBA_E_INVALIDCOOKIE" },
318         { 0x8004CB0B, "CBA_E_QOSTYPEUNSUPPORTED" },
319         { 0x8004CB0C, "CBA_E_QOSVALUEUNSUPPORTED" },
320         { 0x8004CB0F, "CBA_E_NOTAPPLICABLE" },
321         { 0x8004CB12, "CBA_E_LIMITVIOLATION" },
322         { 0x8004CB13, "CBA_E_QOSTYPENOTAPPLICABLE" },
323         { 0x8004CB18, "CBA_E_OUTOFPARTNERACCOS" },
324         { 0x8004CB1C, "CBA_E_FLAGUNSUPPORTED" },
325         { 0x8004CB23, "CBA_E_FRAMECOUNTUNSUPPORTED" },
326         { 0x8004CB25, "CBA_E_MODECHANGE" },
327         { 0x8007000E, "E_OUTOFMEMORY" },
328         { 0x80070057, "E_INVALIDARG" },
329         { 0x800706d1, "RPC_S_PROCNUM_OUT_OF_RANGE" },
330         { 0x80070776, "OR_INVALID_OXID" },
331         { 0,          NULL }
332 };
333
334
335 /* we need to keep track of what transport were used, ie what handle we came
336  * in through so we know what kind of pinfo->dce_smb_fid was passed to us.
337  */
338 /* Value of -1 is reserved for "not DCE packet" in packet_info.dcetransporttype. */
339 #define DCE_TRANSPORT_UNKNOWN           0
340 #define DCE_CN_TRANSPORT_SMBPIPE        1
341
342
343 static int proto_dcerpc = -1;
344
345 /* field defines */
346 static int hf_dcerpc_request_in = -1;
347 static int hf_dcerpc_time = -1;
348 static int hf_dcerpc_response_in = -1;
349 static int hf_dcerpc_ver = -1;
350 static int hf_dcerpc_ver_minor = -1;
351 static int hf_dcerpc_packet_type = -1;
352 static int hf_dcerpc_cn_flags = -1;
353 static int hf_dcerpc_cn_flags_first_frag = -1;
354 static int hf_dcerpc_cn_flags_last_frag = -1;
355 static int hf_dcerpc_cn_flags_cancel_pending = -1;
356 static int hf_dcerpc_cn_flags_reserved = -1;
357 static int hf_dcerpc_cn_flags_mpx = -1;
358 static int hf_dcerpc_cn_flags_dne = -1;
359 static int hf_dcerpc_cn_flags_maybe = -1;
360 static int hf_dcerpc_cn_flags_object = -1;
361 static int hf_dcerpc_drep = -1;
362 static int hf_dcerpc_drep_byteorder = -1;
363 static int hf_dcerpc_drep_character = -1;
364 static int hf_dcerpc_drep_fp = -1;
365 static int hf_dcerpc_cn_frag_len = -1;
366 static int hf_dcerpc_cn_auth_len = -1;
367 static int hf_dcerpc_cn_call_id = -1;
368 static int hf_dcerpc_cn_max_xmit = -1;
369 static int hf_dcerpc_cn_max_recv = -1;
370 static int hf_dcerpc_cn_assoc_group = -1;
371 static int hf_dcerpc_cn_num_ctx_items = -1;
372 static int hf_dcerpc_cn_ctx_item = -1;
373 static int hf_dcerpc_cn_ctx_id = -1;
374 static int hf_dcerpc_cn_num_trans_items = -1;
375 static int hf_dcerpc_cn_bind_abstract_syntax = -1;
376 static int hf_dcerpc_cn_bind_if_id = -1;
377 static int hf_dcerpc_cn_bind_if_ver = -1;
378 static int hf_dcerpc_cn_bind_if_ver_minor = -1;
379 static int hf_dcerpc_cn_bind_trans_syntax = -1;
380 static int hf_dcerpc_cn_bind_trans_id = -1;
381 static int hf_dcerpc_cn_bind_trans_ver = -1;
382 static int hf_dcerpc_cn_alloc_hint = -1;
383 static int hf_dcerpc_cn_sec_addr_len = -1;
384 static int hf_dcerpc_cn_sec_addr = -1;
385 static int hf_dcerpc_cn_num_results = -1;
386 static int hf_dcerpc_cn_ack_result = -1;
387 static int hf_dcerpc_cn_ack_reason = -1;
388 static int hf_dcerpc_cn_ack_trans_id = -1;
389 static int hf_dcerpc_cn_ack_trans_ver = -1;
390 static int hf_dcerpc_cn_reject_reason = -1;
391 static int hf_dcerpc_cn_num_protocols = -1;
392 static int hf_dcerpc_cn_protocol_ver_major = -1;
393 static int hf_dcerpc_cn_protocol_ver_minor = -1;
394 static int hf_dcerpc_cn_cancel_count = -1;
395 static int hf_dcerpc_cn_status = -1;
396 static int hf_dcerpc_cn_deseg_req = -1;
397 static int hf_dcerpc_auth_type = -1;
398 static int hf_dcerpc_auth_level = -1;
399 static int hf_dcerpc_auth_pad_len = -1;
400 static int hf_dcerpc_auth_rsrvd = -1;
401 static int hf_dcerpc_auth_ctx_id = -1;
402 static int hf_dcerpc_dg_flags1 = -1;
403 static int hf_dcerpc_dg_flags1_rsrvd_01 = -1;
404 static int hf_dcerpc_dg_flags1_last_frag = -1;
405 static int hf_dcerpc_dg_flags1_frag = -1;
406 static int hf_dcerpc_dg_flags1_nofack = -1;
407 static int hf_dcerpc_dg_flags1_maybe = -1;
408 static int hf_dcerpc_dg_flags1_idempotent = -1;
409 static int hf_dcerpc_dg_flags1_broadcast = -1;
410 static int hf_dcerpc_dg_flags1_rsrvd_80 = -1;
411 static int hf_dcerpc_dg_flags2 = -1;
412 static int hf_dcerpc_dg_flags2_rsrvd_01 = -1;
413 static int hf_dcerpc_dg_flags2_cancel_pending = -1;
414 static int hf_dcerpc_dg_flags2_rsrvd_04 = -1;
415 static int hf_dcerpc_dg_flags2_rsrvd_08 = -1;
416 static int hf_dcerpc_dg_flags2_rsrvd_10 = -1;
417 static int hf_dcerpc_dg_flags2_rsrvd_20 = -1;
418 static int hf_dcerpc_dg_flags2_rsrvd_40 = -1;
419 static int hf_dcerpc_dg_flags2_rsrvd_80 = -1;
420 static int hf_dcerpc_dg_serial_hi = -1;
421 static int hf_dcerpc_obj_id = -1;
422 static int hf_dcerpc_dg_if_id = -1;
423 static int hf_dcerpc_dg_act_id = -1;
424 static int hf_dcerpc_dg_serial_lo = -1;
425 static int hf_dcerpc_dg_ahint = -1;
426 static int hf_dcerpc_dg_ihint = -1;
427 static int hf_dcerpc_dg_frag_len = -1;
428 static int hf_dcerpc_dg_frag_num = -1;
429 static int hf_dcerpc_dg_auth_proto = -1;
430 static int hf_dcerpc_opnum = -1;
431 static int hf_dcerpc_dg_seqnum = -1;
432 static int hf_dcerpc_dg_server_boot = -1;
433 static int hf_dcerpc_dg_if_ver = -1;
434 static int hf_dcerpc_krb5_av_prot_level = -1;
435 static int hf_dcerpc_krb5_av_key_vers_num = -1;
436 static int hf_dcerpc_krb5_av_key_auth_verifier = -1;
437 static int hf_dcerpc_dg_cancel_vers = -1;
438 static int hf_dcerpc_dg_cancel_id = -1;
439 static int hf_dcerpc_dg_server_accepting_cancels = -1;
440 static int hf_dcerpc_dg_fack_vers = -1;
441 static int hf_dcerpc_dg_fack_window_size = -1;
442 static int hf_dcerpc_dg_fack_max_tsdu = -1;
443 static int hf_dcerpc_dg_fack_max_frag_size = -1;
444 static int hf_dcerpc_dg_fack_serial_num = -1;
445 static int hf_dcerpc_dg_fack_selack_len = -1;
446 static int hf_dcerpc_dg_fack_selack = -1;
447 static int hf_dcerpc_dg_status = -1;
448 static int hf_dcerpc_array_max_count = -1;
449 static int hf_dcerpc_array_offset = -1;
450 static int hf_dcerpc_array_actual_count = -1;
451 static int hf_dcerpc_array_buffer = -1;
452 static int hf_dcerpc_op = -1;
453 static int hf_dcerpc_referent_id = -1;
454 static int hf_dcerpc_fragments = -1;
455 static int hf_dcerpc_fragment = -1;
456 static int hf_dcerpc_fragment_overlap = -1;
457 static int hf_dcerpc_fragment_overlap_conflict = -1;
458 static int hf_dcerpc_fragment_multiple_tails = -1;
459 static int hf_dcerpc_fragment_too_long_fragment = -1;
460 static int hf_dcerpc_fragment_error = -1;
461 static int hf_dcerpc_reassembled_in = -1;
462 static int hf_dcerpc_unknown_if_id = -1;
463
464 static gint ett_dcerpc = -1;
465 static gint ett_dcerpc_cn_flags = -1;
466 static gint ett_dcerpc_cn_ctx = -1;
467 static gint ett_dcerpc_cn_iface = -1;
468 static gint ett_dcerpc_cn_trans_syntax = -1;
469 static gint ett_dcerpc_drep = -1;
470 static gint ett_dcerpc_dg_flags1 = -1;
471 static gint ett_dcerpc_dg_flags2 = -1;
472 static gint ett_dcerpc_pointer_data = -1;
473 static gint ett_dcerpc_string = -1;
474 static gint ett_dcerpc_fragments = -1;
475 static gint ett_dcerpc_fragment = -1;
476 static gint ett_dcerpc_krb5_auth_verf = -1;
477
478 static const fragment_items dcerpc_frag_items = {
479         &ett_dcerpc_fragments,
480         &ett_dcerpc_fragment,
481
482         &hf_dcerpc_fragments,
483         &hf_dcerpc_fragment,
484         &hf_dcerpc_fragment_overlap,
485         &hf_dcerpc_fragment_overlap_conflict,
486         &hf_dcerpc_fragment_multiple_tails,
487         &hf_dcerpc_fragment_too_long_fragment,
488         &hf_dcerpc_fragment_error,
489         NULL,
490
491         "fragments"
492 };
493
494 /* list of hooks to be called when init_protocols is done */
495 GHookList dcerpc_hooks_init_protos;
496
497 #ifdef _WIN32
498 int ResolveWin32UUID(e_uuid_t if_id, char *uuid_name, int uuid_name_max_len)
499 {
500         TCHAR reg_uuid_name[MAX_PATH];
501         HKEY hKey = NULL;
502         DWORD uuid_max_size = MAX_PATH;
503         TCHAR reg_uuid_str[MAX_PATH];
504
505         if(uuid_name_max_len < 2)
506                 return 0;
507         reg_uuid_name[0] = '\0';
508         _snwprintf(reg_uuid_str, MAX_PATH, _T("SOFTWARE\\Classes\\Interface\\{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}"),
509                         if_id.Data1, if_id.Data2, if_id.Data3,
510                         if_id.Data4[0], if_id.Data4[1],
511                         if_id.Data4[2], if_id.Data4[3],
512                         if_id.Data4[4], if_id.Data4[5],
513                         if_id.Data4[6], if_id.Data4[7]);
514         if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, reg_uuid_str, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
515         {
516                 if (RegQueryValueEx(hKey, NULL, NULL, NULL, (LPBYTE)reg_uuid_name, &uuid_max_size) == ERROR_SUCCESS && uuid_max_size <= MAX_PATH)
517                         {
518                         g_snprintf(uuid_name, uuid_name_max_len, "%s", utf_16to8(reg_uuid_name));
519                         RegCloseKey(hKey);
520                         return strlen(uuid_name);
521                 }
522                 RegCloseKey(hKey);
523         }
524         return 0; /* we didn't find anything anyhow. Please don't use the string! */
525
526 }
527 #endif
528
529 static dcerpc_info *
530 get_next_di(void)
531 {
532         static dcerpc_info di[20];
533         static int di_counter=0;
534
535         di_counter++;
536         if(di_counter>=20){
537                 di_counter=0;
538         }
539         return &di[di_counter];
540 }
541
542 /* try to desegment big DCE/RPC packets over TCP? */
543 static gboolean dcerpc_cn_desegment = TRUE;
544
545 /* reassemble DCE/RPC fragments */
546 /* reassembly of cl dcerpc fragments will not work for the case where ONE frame
547    might contain multiple dcerpc fragments for different PDUs.
548    this case would be so unusual/weird so if you got captures like that:
549         too bad
550
551    reassembly of co dcerpc fragments will not work for the case where TCP/SMB frames
552    are coming in out of sequence, but that will hurt in a lot of other places as well.
553 */
554 static gboolean dcerpc_reassemble = TRUE;
555 static GHashTable *dcerpc_co_fragment_table = NULL;
556 static GHashTable *dcerpc_co_reassemble_table = NULL;
557 static GHashTable *dcerpc_cl_reassemble_table = NULL;
558
559 static void
560 dcerpc_reassemble_init(void)
561 {
562   fragment_table_init(&dcerpc_co_fragment_table);
563   reassembled_table_init(&dcerpc_co_reassemble_table);
564   dcerpc_fragment_table_init(&dcerpc_cl_reassemble_table);
565 }
566
567 /*
568  * Authentication subdissectors.  Used to dissect authentication blobs in
569  * DCERPC binds, requests and responses.
570  */
571
572 typedef struct _dcerpc_auth_subdissector {
573         guint8 auth_level;
574         guint8 auth_type;
575         dcerpc_auth_subdissector_fns auth_fns;
576 } dcerpc_auth_subdissector;
577
578 static GSList *dcerpc_auth_subdissector_list;
579
580 static dcerpc_auth_subdissector_fns *get_auth_subdissector_fns(
581         guint8 auth_level, guint8 auth_type)
582 {
583         gpointer data;
584         int i;
585
586         for (i = 0; (data = g_slist_nth_data(dcerpc_auth_subdissector_list, i)); i++) {
587                 dcerpc_auth_subdissector *asd = (dcerpc_auth_subdissector *)data;
588
589                 if (asd->auth_level == auth_level &&
590                     asd->auth_type == auth_type)
591                         return &asd->auth_fns;
592         }
593
594         return NULL;
595 }
596
597 void register_dcerpc_auth_subdissector(guint8 auth_level, guint8 auth_type,
598                                        dcerpc_auth_subdissector_fns *fns)
599 {
600         dcerpc_auth_subdissector *d;
601
602         if (get_auth_subdissector_fns(auth_level, auth_type))
603                 return;
604
605         d = (dcerpc_auth_subdissector *)g_malloc(sizeof(dcerpc_auth_subdissector));
606
607         d->auth_level = auth_level;
608         d->auth_type = auth_type;
609         memcpy(&d->auth_fns, fns, sizeof(dcerpc_auth_subdissector_fns));
610
611         dcerpc_auth_subdissector_list = g_slist_append(dcerpc_auth_subdissector_list, d);
612 }
613
614 /* Hand off verifier data to a registered dissector */
615
616 static void dissect_auth_verf(tvbuff_t *auth_tvb, packet_info *pinfo,
617                               proto_tree *tree,
618                               dcerpc_auth_subdissector_fns *auth_fns,
619                               e_dce_cn_common_hdr_t *hdr,
620                               dcerpc_auth_info *auth_info)
621 {
622         dcerpc_dissect_fnct_t *volatile fn = NULL;
623
624         switch (hdr->ptype) {
625         case PDU_BIND:
626         case PDU_ALTER:
627                 fn = auth_fns->bind_fn;
628                 break;
629         case PDU_BIND_ACK:
630         case PDU_ALTER_ACK:
631                 fn = auth_fns->bind_ack_fn;
632                 break;
633         case PDU_AUTH3:
634                 fn = auth_fns->auth3_fn;
635                 break;
636         case PDU_REQ:
637                 fn = auth_fns->req_verf_fn;
638                 break;
639         case PDU_RESP:
640                 fn = auth_fns->resp_verf_fn;
641                 break;
642
643                 /* Don't know how to handle authentication data in this
644                    pdu type. */
645
646         default:
647                 g_warning("attempt to dissect %s pdu authentication data",
648                           val_to_str(hdr->ptype, pckt_vals, "Unknown (%u)"));
649                 break;
650         }
651
652         if (fn)
653                 fn(auth_tvb, 0, pinfo, tree, hdr->drep);
654         else {
655                 tvb_ensure_bytes_exist(auth_tvb, 0, hdr->auth_len);
656                 proto_tree_add_text(tree, auth_tvb, 0, hdr->auth_len,
657                                     "%s Verifier",
658                                     val_to_str(auth_info->auth_type,
659                                                authn_protocol_vals,
660                                                "Unknown (%u)"));
661         }
662 }
663
664 /* Hand off payload data to a registered dissector */
665
666 static tvbuff_t *decode_encrypted_data(tvbuff_t *data_tvb,
667                                        tvbuff_t *auth_tvb,
668                                        packet_info *pinfo,
669                                        dcerpc_auth_subdissector_fns *auth_fns,
670                                        gboolean is_request,
671                                        dcerpc_auth_info *auth_info)
672 {
673         dcerpc_decode_data_fnct_t *fn;
674
675         if (is_request)
676                 fn = auth_fns->req_data_fn;
677         else
678                 fn = auth_fns->resp_data_fn;
679
680         if (fn)
681                 return fn(data_tvb, auth_tvb, 0, pinfo, auth_info);
682
683         return NULL;
684 }
685
686 /*
687  * Subdissectors
688  */
689
690 /* the registered subdissectors */
691 GHashTable *dcerpc_uuids=NULL;
692
693 static gint
694 dcerpc_uuid_equal (gconstpointer k1, gconstpointer k2)
695 {
696     const dcerpc_uuid_key *key1 = (const dcerpc_uuid_key *)k1;
697     const dcerpc_uuid_key *key2 = (const dcerpc_uuid_key *)k2;
698     return ((memcmp (&key1->uuid, &key2->uuid, sizeof (e_uuid_t)) == 0)
699             && (key1->ver == key2->ver));
700 }
701
702 static guint
703 dcerpc_uuid_hash (gconstpointer k)
704 {
705     const dcerpc_uuid_key *key = (const dcerpc_uuid_key *)k;
706     /* This isn't perfect, but the Data1 part of these is almost always
707        unique. */
708     return key->uuid.Data1;
709 }
710
711 void
712 dcerpc_init_uuid (int proto, int ett, e_uuid_t *uuid, guint16 ver,
713                   dcerpc_sub_dissector *procs, int opnum_hf)
714 {
715     dcerpc_uuid_key *key = g_malloc (sizeof (*key));
716     dcerpc_uuid_value *value = g_malloc (sizeof (*value));
717     header_field_info *hf_info;
718
719     key->uuid = *uuid;
720     key->ver = ver;
721
722     value->proto = find_protocol_by_id(proto);
723     value->proto_id = proto;
724     value->ett = ett;
725     value->name = proto_get_protocol_short_name (value->proto);
726     value->procs = procs;
727     value->opnum_hf = opnum_hf;
728
729     g_hash_table_insert (dcerpc_uuids, key, value);
730
731     hf_info = proto_registrar_get_nth(opnum_hf);
732     hf_info->strings = value_string_from_subdissectors(procs);
733 }
734
735
736 /* try to get registered name for this uuid */
737 const gchar *dcerpc_get_uuid_name(e_uuid_t *uuid, guint16 ver)
738 {
739     dcerpc_uuid_key key;
740     dcerpc_uuid_value *sub_proto;
741
742
743         /* try to get registered uuid "name" of if_id */
744         key.uuid = *uuid;
745         key.ver = ver;
746
747         if ((sub_proto = g_hash_table_lookup (dcerpc_uuids, &key)) != NULL
748                  && proto_is_protocol_enabled(sub_proto->proto)) {
749
750                 return sub_proto->name;
751         }
752
753         return NULL;
754 }
755
756
757 /* Function to find the name of a registered protocol
758  * or NULL if the protocol/version is not known to wireshark.
759  */
760 const char *
761 dcerpc_get_proto_name(e_uuid_t *uuid, guint16 ver)
762 {
763     dcerpc_uuid_key key;
764     dcerpc_uuid_value *sub_proto;
765
766     key.uuid = *uuid;
767     key.ver = ver;
768     if(!(sub_proto = g_hash_table_lookup (dcerpc_uuids, &key))){
769         return NULL;
770     }
771     return sub_proto->name;
772 }
773
774 /* Function to find the opnum hf-field of a registered protocol
775  * or -1 if the protocol/version is not known to wireshark.
776  */
777 int
778 dcerpc_get_proto_hf_opnum(e_uuid_t *uuid, guint16 ver)
779 {
780     dcerpc_uuid_key key;
781     dcerpc_uuid_value *sub_proto;
782
783     key.uuid = *uuid;
784     key.ver = ver;
785     if(!(sub_proto = g_hash_table_lookup (dcerpc_uuids, &key))){
786         return -1;
787     }
788     return sub_proto->opnum_hf;
789 }
790
791 /* Create a value_string consisting of DCERPC opnum and name from a
792    subdissector array. */
793
794 value_string *value_string_from_subdissectors(dcerpc_sub_dissector *sd)
795 {
796         value_string *vs = NULL;
797         int i, num_sd = 0;
798
799  again:
800         for (i = 0; sd[i].name; i++) {
801                 if (vs) {
802                         vs[i].value = sd[i].num;
803                         vs[i].strptr = sd[i].name;
804                 } else
805                         num_sd++;
806         }
807
808         if (!vs) {
809                 vs = g_malloc((num_sd + 1) * sizeof(value_string));
810                 goto again;
811         }
812
813         vs[num_sd].value = 0;
814         vs[num_sd].strptr = NULL;
815
816         return vs;
817 }
818
819 /* Function to find the subdissector table of a registered protocol
820  * or NULL if the protocol/version is not known to wireshark.
821  */
822 dcerpc_sub_dissector *
823 dcerpc_get_proto_sub_dissector(e_uuid_t *uuid, guint16 ver)
824 {
825     dcerpc_uuid_key key;
826     dcerpc_uuid_value *sub_proto;
827
828     key.uuid = *uuid;
829     key.ver = ver;
830     if(!(sub_proto = g_hash_table_lookup (dcerpc_uuids, &key))){
831         return NULL;
832     }
833     return sub_proto->procs;
834 }
835
836
837 /*
838  * To keep track of ctx_id mappings.
839  *
840  * Everytime we see a bind call we update this table.
841  * Note that we always specify a SMB FID. For non-SMB transports this
842  * value is 0.
843  */
844 static GHashTable *dcerpc_binds=NULL;
845
846 typedef struct _dcerpc_bind_key {
847     conversation_t *conv;
848     guint16 ctx_id;
849     guint16 smb_fid;
850 } dcerpc_bind_key;
851
852 typedef struct _dcerpc_bind_value {
853         e_uuid_t uuid;
854         guint16 ver;
855 } dcerpc_bind_value;
856
857 static gint
858 dcerpc_bind_equal (gconstpointer k1, gconstpointer k2)
859 {
860     const dcerpc_bind_key *key1 = (const dcerpc_bind_key *)k1;
861     const dcerpc_bind_key *key2 = (const dcerpc_bind_key *)k2;
862     return (key1->conv == key2->conv
863             && key1->ctx_id == key2->ctx_id
864             && key1->smb_fid == key2->smb_fid);
865 }
866
867 static guint
868 dcerpc_bind_hash (gconstpointer k)
869 {
870     const dcerpc_bind_key *key = (const dcerpc_bind_key *)k;
871     guint hash;
872
873     hash=GPOINTER_TO_UINT(key->conv) + key->ctx_id + key->smb_fid;
874     return hash;
875
876 }
877
878 /*
879  * To keep track of callid mappings.  Should really use some generic
880  * conversation support instead.
881  */
882 static GHashTable *dcerpc_cn_calls=NULL;
883 static GHashTable *dcerpc_dg_calls=NULL;
884
885 typedef struct _dcerpc_cn_call_key {
886     conversation_t *conv;
887     guint32 call_id;
888     guint16 smb_fid;
889 } dcerpc_cn_call_key;
890
891 typedef struct _dcerpc_dg_call_key {
892     conversation_t *conv;
893     guint32 seqnum;
894     e_uuid_t act_id ;
895 } dcerpc_dg_call_key;
896
897
898 static gint
899 dcerpc_cn_call_equal (gconstpointer k1, gconstpointer k2)
900 {
901     const dcerpc_cn_call_key *key1 = (const dcerpc_cn_call_key *)k1;
902     const dcerpc_cn_call_key *key2 = (const dcerpc_cn_call_key *)k2;
903     return (key1->conv == key2->conv
904             && key1->call_id == key2->call_id
905             && key1->smb_fid == key2->smb_fid);
906 }
907
908 static gint
909 dcerpc_dg_call_equal (gconstpointer k1, gconstpointer k2)
910 {
911     const dcerpc_dg_call_key *key1 = (const dcerpc_dg_call_key *)k1;
912     const dcerpc_dg_call_key *key2 = (const dcerpc_dg_call_key *)k2;
913     return (key1->conv == key2->conv
914             && key1->seqnum == key2->seqnum
915             && (memcmp (&key1->act_id, &key2->act_id, sizeof (e_uuid_t)) == 0));
916 }
917
918 static guint
919 dcerpc_cn_call_hash (gconstpointer k)
920 {
921     const dcerpc_cn_call_key *key = (const dcerpc_cn_call_key *)k;
922     return GPOINTER_TO_UINT(key->conv) + key->call_id + key->smb_fid;
923 }
924
925 static guint
926 dcerpc_dg_call_hash (gconstpointer k)
927 {
928     const dcerpc_dg_call_key *key = (const dcerpc_dg_call_key *)k;
929     return (GPOINTER_TO_UINT(key->conv) + key->seqnum + key->act_id.Data1
930             + (key->act_id.Data2 << 16) + key->act_id.Data3
931             + (key->act_id.Data4[0] << 24) + (key->act_id.Data4[1] << 16)
932             + (key->act_id.Data4[2] << 8) + (key->act_id.Data4[3] << 0)
933             + (key->act_id.Data4[4] << 24) + (key->act_id.Data4[5] << 16)
934             + (key->act_id.Data4[6] << 8) + (key->act_id.Data4[7] << 0));
935 }
936
937 /* to keep track of matched calls/responses
938    this one uses the same value struct as calls, but the key is the frame id
939    and call id; there can be more than one call in a frame.
940
941    XXX - why not just use the same keys as are used for calls?
942 */
943
944 static GHashTable *dcerpc_matched=NULL;
945
946 typedef struct _dcerpc_matched_key {
947     guint32 frame;
948     guint32 call_id;
949 } dcerpc_matched_key;
950
951 static gint
952 dcerpc_matched_equal (gconstpointer k1, gconstpointer k2)
953 {
954     const dcerpc_matched_key *key1 = (const dcerpc_matched_key *)k1;
955     const dcerpc_matched_key *key2 = (const dcerpc_matched_key *)k2;
956     return (key1->frame == key2->frame
957             && key1->call_id == key2->call_id);
958 }
959
960 static guint
961 dcerpc_matched_hash (gconstpointer k)
962 {
963     const dcerpc_matched_key *key = (const dcerpc_matched_key *)k;
964     return key->frame;
965 }
966
967
968
969 /*
970  * Utility functions.  Modeled after packet-rpc.c
971  */
972
973 int
974 dissect_dcerpc_uint8 (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
975                       proto_tree *tree, guint8 *drep,
976                       int hfindex, guint8 *pdata)
977 {
978     guint8 data;
979
980     data = tvb_get_guint8 (tvb, offset);
981     if (tree) {
982         proto_tree_add_item (tree, hfindex, tvb, offset, 1, (drep[0] & 0x10));
983     }
984     if (pdata)
985         *pdata = data;
986     return offset + 1;
987 }
988
989 int
990 dissect_dcerpc_uint16 (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
991                        proto_tree *tree, guint8 *drep,
992                        int hfindex, guint16 *pdata)
993 {
994     guint16 data;
995
996     data = ((drep[0] & 0x10)
997             ? tvb_get_letohs (tvb, offset)
998             : tvb_get_ntohs (tvb, offset));
999
1000     if (tree) {
1001         proto_tree_add_item (tree, hfindex, tvb, offset, 2, (drep[0] & 0x10));
1002     }
1003     if (pdata)
1004         *pdata = data;
1005     return offset + 2;
1006 }
1007
1008 int
1009 dissect_dcerpc_uint32 (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
1010                        proto_tree *tree, guint8 *drep,
1011                        int hfindex, guint32 *pdata)
1012 {
1013     guint32 data;
1014
1015     data = ((drep[0] & 0x10)
1016             ? tvb_get_letohl (tvb, offset)
1017             : tvb_get_ntohl (tvb, offset));
1018
1019     if (tree) {
1020         proto_tree_add_item (tree, hfindex, tvb, offset, 4, (drep[0] & 0x10));
1021     }
1022     if (pdata)
1023         *pdata = data;
1024     return offset+4;
1025 }
1026
1027 /* handles 32 bit unix time_t */
1028 int
1029 dissect_dcerpc_time_t (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
1030                        proto_tree *tree, guint8 *drep,
1031                        int hfindex, guint32 *pdata)
1032 {
1033     guint32 data;
1034     nstime_t tv;
1035
1036     data = ((drep[0] & 0x10)
1037             ? tvb_get_letohl (tvb, offset)
1038             : tvb_get_ntohl (tvb, offset));
1039
1040     tv.secs=data;
1041     tv.nsecs=0;
1042     if (tree) {
1043         if(data==0xffffffff){
1044             /* special case,   no time specified */
1045             proto_tree_add_time_format_value(tree, hfindex, tvb, offset, 4, &tv, "No time specified");
1046         } else {
1047             proto_tree_add_time (tree, hfindex, tvb, offset, 4, &tv);
1048         }
1049     }
1050     if (pdata)
1051         *pdata = data;
1052
1053     return offset+4;
1054 }
1055
1056 int
1057 dissect_dcerpc_uint64 (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
1058                        proto_tree *tree, guint8 *drep,
1059                        int hfindex, guint64 *pdata)
1060 {
1061     guint64 data;
1062
1063     data = ((drep[0] & 0x10)
1064             ? tvb_get_letoh64 (tvb, offset)
1065             : tvb_get_ntoh64 (tvb, offset));
1066
1067     if (tree) {
1068         proto_tree_add_item(tree, hfindex, tvb, offset, 8, (drep[0] & 0x10));
1069     }
1070     if (pdata)
1071         *pdata = data;
1072     return offset+8;
1073 }
1074
1075
1076 int
1077 dissect_dcerpc_float(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
1078                     proto_tree *tree, guint8 *drep,
1079                     int hfindex, gfloat *pdata)
1080 {
1081         gfloat data;
1082
1083
1084         switch(drep[1]) {
1085                 case(DCE_RPC_DREP_FP_IEEE):
1086                         data = ((drep[0] & 0x10)
1087                                         ? tvb_get_letohieee_float(tvb, offset)
1088                                         : tvb_get_ntohieee_float(tvb, offset));
1089                         if (tree) {
1090                                 proto_tree_add_float(tree, hfindex, tvb, offset, 4, data);
1091                         }
1092                         break;
1093                 case(DCE_RPC_DREP_FP_VAX):  /* (fall trough) */
1094                 case(DCE_RPC_DREP_FP_CRAY): /* (fall trough) */
1095                 case(DCE_RPC_DREP_FP_IBM):  /* (fall trough) */
1096                 default:
1097                         /* ToBeDone: non IEEE floating formats */
1098                         /* Set data to a negative infinity value */
1099                         data = -G_MAXFLOAT;
1100                         if (tree) {
1101                                 proto_tree_add_debug_text(tree, "DCE RPC: dissection of non IEEE floating formats currently not implemented (drep=%u)!", drep[1]);
1102                         }
1103         }
1104     if (pdata)
1105         *pdata = data;
1106     return offset + 4;
1107 }
1108
1109
1110 int
1111 dissect_dcerpc_double(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
1112                     proto_tree *tree, guint8 *drep,
1113                     int hfindex, gdouble *pdata)
1114 {
1115     gdouble data;
1116
1117
1118         switch(drep[1]) {
1119                 case(DCE_RPC_DREP_FP_IEEE):
1120                         data = ((drep[0] & 0x10)
1121                                         ? tvb_get_letohieee_double(tvb, offset)
1122                                         : tvb_get_ntohieee_double(tvb, offset));
1123                         if (tree) {
1124                                 proto_tree_add_double(tree, hfindex, tvb, offset, 8, data);
1125                         }
1126                         break;
1127                 case(DCE_RPC_DREP_FP_VAX):  /* (fall trough) */
1128                 case(DCE_RPC_DREP_FP_CRAY): /* (fall trough) */
1129                 case(DCE_RPC_DREP_FP_IBM):  /* (fall trough) */
1130                 default:
1131                         /* ToBeDone: non IEEE double formats */
1132                         /* Set data to a negative infinity value */
1133                         data = -G_MAXDOUBLE;
1134                         if (tree) {
1135                                 proto_tree_add_debug_text(tree, "DCE RPC: dissection of non IEEE double formats currently not implemented (drep=%u)!", drep[1]);
1136                         }
1137         }
1138     if (pdata)
1139         *pdata = data;
1140     return offset + 8;
1141 }
1142
1143
1144 int
1145 dissect_dcerpc_uuid_t (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
1146                     proto_tree *tree, guint8 *drep,
1147                     int hfindex, e_uuid_t *pdata)
1148 {
1149     e_uuid_t uuid;
1150 #if 0
1151         header_field_info* hfi;
1152         gchar *uuid_name;
1153 #endif
1154
1155
1156     dcerpc_tvb_get_uuid (tvb, offset, drep, &uuid);
1157     if (tree) {
1158 #if 0
1159                 /* get name of protocol field to prepend it later */
1160                 hfi = proto_registrar_get_nth(hfindex);
1161
1162         /* XXX - get the name won't work correct, as we don't know the version of this uuid (if it has one) */
1163                 /* look for a registered uuid name */
1164                 uuid_name = dcerpc_get_uuid_name(&uuid, 0);
1165
1166                 if (uuid_name) {
1167                         /* we know the name of this uuid */
1168                         proto_tree_add_string_format (tree, hfindex, tvb, offset, 16, "",
1169                                       "%s: %s (%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
1170                                                                           hfi->name, uuid_name,
1171                                       uuid.Data1, uuid.Data2, uuid.Data3,
1172                                       uuid.Data4[0], uuid.Data4[1],
1173                                       uuid.Data4[2], uuid.Data4[3],
1174                                       uuid.Data4[4], uuid.Data4[5],
1175                                       uuid.Data4[6], uuid.Data4[7]);
1176                 } else {
1177 #endif
1178                         /* GUID have changed from FT_STRING to FT_GUID
1179                            (XXX - have we changed all dissectors?).
1180                          */
1181                     proto_tree_add_guid(tree, hfindex, tvb, offset, 16, (e_guid_t *) &uuid);
1182 #if 0
1183                 }
1184 #endif
1185     }
1186     if (pdata) {
1187         *pdata = uuid;
1188     }
1189     return offset + 16;
1190 }
1191
1192
1193 /*
1194  * a couple simpler things
1195  */
1196 guint16
1197 dcerpc_tvb_get_ntohs (tvbuff_t *tvb, gint offset, guint8 *drep)
1198 {
1199     if (drep[0] & 0x10) {
1200         return tvb_get_letohs (tvb, offset);
1201     } else {
1202         return tvb_get_ntohs (tvb, offset);
1203     }
1204 }
1205
1206 guint32
1207 dcerpc_tvb_get_ntohl (tvbuff_t *tvb, gint offset, guint8 *drep)
1208 {
1209     if (drep[0] & 0x10) {
1210         return tvb_get_letohl (tvb, offset);
1211     } else {
1212         return tvb_get_ntohl (tvb, offset);
1213     }
1214 }
1215
1216 void
1217 dcerpc_tvb_get_uuid (tvbuff_t *tvb, gint offset, guint8 *drep, e_uuid_t *uuid)
1218 {
1219     if (drep[0] & 0x10) {
1220         tvb_get_letohguid (tvb, offset, (e_guid_t *) uuid);
1221     } else {
1222         tvb_get_ntohguid (tvb, offset, (e_guid_t *) uuid);
1223     }
1224 }
1225
1226
1227
1228 /* NDR arrays */
1229 /* function to dissect a unidimensional conformant array */
1230 int
1231 dissect_ndr_ucarray(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1232                 proto_tree *tree, guint8 *drep,
1233                 dcerpc_dissect_fnct_t *fnct)
1234 {
1235         guint32 i;
1236         dcerpc_info *di;
1237         int old_offset;
1238
1239         di=pinfo->private_data;
1240         if(di->conformant_run){
1241                 /* conformant run, just dissect the max_count header */
1242                 old_offset=offset;
1243                 di->conformant_run=0;
1244                 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1245                                 hf_dcerpc_array_max_count, &di->array_max_count);
1246                 di->array_max_count_offset=offset-4;
1247                 di->conformant_run=1;
1248                 di->conformant_eaten=offset-old_offset;
1249         } else {
1250                 /* we don't remember where in the bytestream this field was */
1251                 proto_tree_add_uint(tree, hf_dcerpc_array_max_count, tvb, di->array_max_count_offset, 4, di->array_max_count);
1252
1253                 /* real run, dissect the elements */
1254                 for(i=0;i<di->array_max_count;i++){
1255                         offset = (*fnct)(tvb, offset, pinfo, tree, drep);
1256                 }
1257         }
1258
1259         return offset;
1260 }
1261 /* function to dissect a unidimensional conformant and varying array */
1262 int
1263 dissect_ndr_ucvarray(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1264                 proto_tree *tree, guint8 *drep,
1265                 dcerpc_dissect_fnct_t *fnct)
1266 {
1267         guint32 i;
1268         dcerpc_info *di;
1269         int old_offset;
1270
1271         di=pinfo->private_data;
1272         if(di->conformant_run){
1273                 /* conformant run, just dissect the max_count header */
1274                 old_offset=offset;
1275                 di->conformant_run=0;
1276                 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1277                                 hf_dcerpc_array_max_count, &di->array_max_count);
1278                 di->array_max_count_offset=offset-4;
1279                 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1280                                 hf_dcerpc_array_offset, &di->array_offset);
1281                 di->array_offset_offset=offset-4;
1282                 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1283                                 hf_dcerpc_array_actual_count, &di->array_actual_count);
1284                 di->array_actual_count_offset=offset-4;
1285                 di->conformant_run=1;
1286                 di->conformant_eaten=offset-old_offset;
1287         } else {
1288                 /* we dont dont remember where  in the bytestream these fields were */
1289                 proto_tree_add_uint(tree, hf_dcerpc_array_max_count, tvb, di->array_max_count_offset, 4, di->array_max_count);
1290                 proto_tree_add_uint(tree, hf_dcerpc_array_offset, tvb, di->array_offset_offset, 4, di->array_offset);
1291                 proto_tree_add_uint(tree, hf_dcerpc_array_actual_count, tvb, di->array_actual_count_offset, 4, di->array_actual_count);
1292
1293                 /* real run, dissect the elements */
1294                 for(i=0;i<di->array_actual_count;i++){
1295                         offset = (*fnct)(tvb, offset, pinfo, tree, drep);
1296                 }
1297         }
1298
1299         return offset;
1300 }
1301 /* function to dissect a unidimensional varying array */
1302 int
1303 dissect_ndr_uvarray(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1304                 proto_tree *tree, guint8 *drep,
1305                 dcerpc_dissect_fnct_t *fnct)
1306 {
1307         guint32 i;
1308         dcerpc_info *di;
1309         int old_offset;
1310
1311         di=pinfo->private_data;
1312         if(di->conformant_run){
1313                 /* conformant run, just dissect the max_count header */
1314                 old_offset=offset;
1315                 di->conformant_run=0;
1316                 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1317                                 hf_dcerpc_array_offset, &di->array_offset);
1318                 di->array_offset_offset=offset-4;
1319                 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1320                                 hf_dcerpc_array_actual_count, &di->array_actual_count);
1321                 di->array_actual_count_offset=offset-4;
1322                 di->conformant_run=1;
1323                 di->conformant_eaten=offset-old_offset;
1324         } else {
1325                 /* we dont dont remember where  in the bytestream these fields were */
1326                 proto_tree_add_uint(tree, hf_dcerpc_array_offset, tvb, di->array_offset_offset, 4, di->array_offset);
1327                 proto_tree_add_uint(tree, hf_dcerpc_array_actual_count, tvb, di->array_actual_count_offset, 4, di->array_actual_count);
1328
1329                 /* real run, dissect the elements */
1330                 for(i=0;i<di->array_actual_count;i++){
1331                         offset = (*fnct)(tvb, offset, pinfo, tree, drep);
1332                 }
1333         }
1334
1335         return offset;
1336 }
1337
1338 /* Dissect an string of bytes.  This corresponds to
1339    IDL of the form '[string] byte *foo'.
1340
1341    It can also be used for a conformant varying array of bytes if
1342    the contents of the array should be shown as a big blob, rather
1343    than showing each byte as an individual element.
1344
1345    XXX - which of those is really the IDL type for, for example,
1346    the encrypted data in some MAPI packets?  (Microsoft haven't
1347    released that IDL.)
1348
1349    XXX - does this need to do all the conformant array stuff that
1350    "dissect_ndr_ucvarray()" does?  These are presumably for strings
1351    that are conformant and varying - they're stored like conformant
1352    varying arrays of bytes.  */
1353 int
1354 dissect_ndr_byte_array(tvbuff_t *tvb, int offset, packet_info *pinfo,
1355                             proto_tree *tree, guint8 *drep)
1356 {
1357     dcerpc_info *di;
1358     guint32 len;
1359
1360     di=pinfo->private_data;
1361     if(di->conformant_run){
1362       /* just a run to handle conformant arrays, no scalars to dissect */
1363       return offset;
1364     }
1365
1366     /* NDR array header */
1367
1368     offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
1369                                 hf_dcerpc_array_max_count, NULL);
1370
1371     offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
1372                                 hf_dcerpc_array_offset, NULL);
1373
1374     offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
1375                                 hf_dcerpc_array_actual_count, &len);
1376
1377     if (tree && len) {
1378         tvb_ensure_bytes_exist(tvb, offset, len);
1379         proto_tree_add_item(tree, hf_dcerpc_array_buffer,
1380                             tvb, offset, len, drep[0] & 0x10);
1381     }
1382
1383     offset += len;
1384
1385     return offset;
1386 }
1387
1388 /* For dissecting arrays that are to be interpreted as strings.  */
1389
1390 /* Dissect an NDR conformant varying string of elements.
1391    The length of each element is given by the 'size_is' parameter;
1392    the elements are assumed to be characters or wide characters.
1393
1394    XXX - does this need to do all the conformant array stuff that
1395    "dissect_ndr_ucvarray()" does?  */
1396 int
1397 dissect_ndr_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
1398                      proto_tree *tree, guint8 *drep, int size_is,
1399                      int hfindex, gboolean add_subtree, char **data)
1400 {
1401     dcerpc_info *di;
1402     proto_item *string_item;
1403     proto_tree *string_tree;
1404     guint32 len, buffer_len;
1405     char *s;
1406     header_field_info *hfinfo;
1407
1408     di=pinfo->private_data;
1409     if(di->conformant_run){
1410       /* just a run to handle conformant arrays, no scalars to dissect */
1411       return offset;
1412     }
1413
1414     if (add_subtree) {
1415         string_item = proto_tree_add_text(tree, tvb, offset, -1, "%s",
1416                                           proto_registrar_get_name(hfindex));
1417         string_tree = proto_item_add_subtree(string_item, ett_dcerpc_string);
1418     } else {
1419         string_item = NULL;
1420         string_tree = tree;
1421     }
1422
1423     /* NDR array header */
1424
1425     offset = dissect_ndr_uint32(tvb, offset, pinfo, string_tree, drep,
1426                                 hf_dcerpc_array_max_count, NULL);
1427
1428     offset = dissect_ndr_uint32(tvb, offset, pinfo, string_tree, drep,
1429                                 hf_dcerpc_array_offset, NULL);
1430
1431     offset = dissect_ndr_uint32(tvb, offset, pinfo, string_tree, drep,
1432                                 hf_dcerpc_array_actual_count, &len);
1433
1434     buffer_len = size_is * len;
1435
1436     /* Adjust offset */
1437     if (offset % size_is)
1438         offset += size_is - (offset % size_is);
1439
1440     if (size_is == sizeof(guint16)) {
1441         /* XXX - use drep to determine the byte order? */
1442         s = tvb_fake_unicode(tvb, offset, buffer_len / 2, TRUE);
1443         /*
1444          * XXX - we don't support a string type with Unicode
1445          * characters, so if this is a string item, we make
1446          * its value be the "fake Unicode" string.
1447          */
1448         if (tree && buffer_len) {
1449             hfinfo = proto_registrar_get_nth(hfindex);
1450             tvb_ensure_bytes_exist(tvb, offset, buffer_len);
1451             if (hfinfo->type == FT_STRING) {
1452                 proto_tree_add_string(string_tree, hfindex, tvb, offset,
1453                                       buffer_len, s);
1454             } else {
1455                 proto_tree_add_item(string_tree, hfindex, tvb, offset,
1456                                     buffer_len, drep[0] & 0x10);
1457             }
1458         }
1459     } else {
1460         /*
1461          * "tvb_get_string()" throws an exception if the entire string
1462          * isn't in the tvbuff.  If the length is bogus, this should
1463          * keep us from trying to allocate an immensely large buffer.
1464          * (It won't help if the length is *valid* but immensely large,
1465          * but that's another matter; in any case, that would happen only
1466          * if we had an immensely large tvbuff....)
1467          */
1468         tvb_ensure_bytes_exist(tvb, offset, buffer_len);
1469         s = tvb_get_string(tvb, offset, buffer_len);
1470         if (tree && buffer_len)
1471             proto_tree_add_item(string_tree, hfindex, tvb, offset,
1472                                 buffer_len, drep[0] & 0x10);
1473     }
1474
1475     if (string_item != NULL)
1476         proto_item_append_text(string_item, ": %s", s);
1477
1478     if (data)
1479             *data = s;
1480     else
1481             g_free(s);
1482
1483     offset += buffer_len;
1484
1485     proto_item_set_end(string_item, tvb, offset);
1486
1487     return offset;
1488 }
1489
1490 /* Dissect an conformant varying string of chars.
1491    This corresponds to IDL of the form '[string] char *foo'.
1492
1493    XXX - at least according to the DCE RPC 1.1 spec, a string has
1494    a null terminator, which isn't necessary as a terminator for
1495    the transfer language (as there's a length), but is presumably
1496    there for the benefit of null-terminated-string languages
1497    such as C.  Is this ever used for purely counted strings?
1498    (Not that it matters if it is.) */
1499 int
1500 dissect_ndr_char_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
1501                         proto_tree *tree, guint8 *drep)
1502 {
1503     dcerpc_info *di;
1504     di=pinfo->private_data;
1505
1506     return dissect_ndr_cvstring(tvb, offset, pinfo, tree, drep,
1507                                 sizeof(guint8), di->hf_index,
1508                                 FALSE, NULL);
1509 }
1510
1511 /* Dissect a conformant varying string of wchars (wide characters).
1512    This corresponds to IDL of the form '[string] wchar *foo'
1513
1514    XXX - at least according to the DCE RPC 1.1 spec, a string has
1515    a null terminator, which isn't necessary as a terminator for
1516    the transfer language (as there's a length), but is presumably
1517    there for the benefit of null-terminated-string languages
1518    such as C.  Is this ever used for purely counted strings?
1519    (Not that it matters if it is.) */
1520 int
1521 dissect_ndr_wchar_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
1522                         proto_tree *tree, guint8 *drep)
1523 {
1524     dcerpc_info *di;
1525     di=pinfo->private_data;
1526
1527     return dissect_ndr_cvstring(tvb, offset, pinfo, tree, drep,
1528                                 sizeof(guint16), di->hf_index,
1529                                 FALSE, NULL);
1530 }
1531
1532 /* Dissect an NDR varying string of elements.
1533    The length of each element is given by the 'size_is' parameter;
1534    the elements are assumed to be characters or wide characters.
1535 */
1536 int
1537 dissect_ndr_vstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
1538                      proto_tree *tree, guint8 *drep, int size_is,
1539                      int hfindex, gboolean add_subtree, char **data)
1540 {
1541     dcerpc_info *di;
1542     proto_item *string_item;
1543     proto_tree *string_tree;
1544     guint32 len, buffer_len;
1545     char *s;
1546     header_field_info *hfinfo;
1547
1548     di=pinfo->private_data;
1549     if(di->conformant_run){
1550       /* just a run to handle conformant arrays, no scalars to dissect */
1551       return offset;
1552     }
1553
1554     if (add_subtree) {
1555         string_item = proto_tree_add_text(tree, tvb, offset, -1, "%s",
1556                                           proto_registrar_get_name(hfindex));
1557         string_tree = proto_item_add_subtree(string_item, ett_dcerpc_string);
1558     } else {
1559         string_item = NULL;
1560         string_tree = tree;
1561     }
1562
1563     /* NDR array header */
1564     offset = dissect_ndr_uint32(tvb, offset, pinfo, string_tree, drep,
1565                                 hf_dcerpc_array_offset, NULL);
1566
1567     offset = dissect_ndr_uint32(tvb, offset, pinfo, string_tree, drep,
1568                                 hf_dcerpc_array_actual_count, &len);
1569
1570     buffer_len = size_is * len;
1571
1572     /* Adjust offset */
1573     if (offset % size_is)
1574         offset += size_is - (offset % size_is);
1575
1576     if (size_is == sizeof(guint16)) {
1577         /* XXX - use drep to determine the byte order? */
1578         s = tvb_fake_unicode(tvb, offset, buffer_len / 2, TRUE);
1579         /*
1580          * XXX - we don't support a string type with Unicode
1581          * characters, so if this is a string item, we make
1582          * its value be the "fake Unicode" string.
1583          */
1584         if (tree && buffer_len) {
1585             hfinfo = proto_registrar_get_nth(hfindex);
1586             tvb_ensure_bytes_exist(tvb, offset, buffer_len);
1587             if (hfinfo->type == FT_STRING) {
1588                 proto_tree_add_string(string_tree, hfindex, tvb, offset,
1589                                       buffer_len, s);
1590             } else {
1591                 proto_tree_add_item(string_tree, hfindex, tvb, offset,
1592                                     buffer_len, drep[0] & 0x10);
1593             }
1594         }
1595     } else {
1596         /*
1597          * "tvb_get_string()" throws an exception if the entire string
1598          * isn't in the tvbuff.  If the length is bogus, this should
1599          * keep us from trying to allocate an immensely large buffer.
1600          * (It won't help if the length is *valid* but immensely large,
1601          * but that's another matter; in any case, that would happen only
1602          * if we had an immensely large tvbuff....)
1603          */
1604         tvb_ensure_bytes_exist(tvb, offset, buffer_len);
1605         s = tvb_get_string(tvb, offset, buffer_len);
1606         if (tree && buffer_len)
1607             proto_tree_add_item(string_tree, hfindex, tvb, offset,
1608                                 buffer_len, drep[0] & 0x10);
1609     }
1610
1611     if (string_item != NULL)
1612         proto_item_append_text(string_item, ": %s", s);
1613
1614     if (data)
1615             *data = s;
1616     else
1617             g_free(s);
1618
1619     offset += buffer_len;
1620
1621     proto_item_set_end(string_item, tvb, offset);
1622
1623     return offset;
1624 }
1625 /* Dissect an varying string of chars.
1626    This corresponds to IDL of the form '[string] char *foo'.
1627
1628    XXX - at least according to the DCE RPC 1.1 spec, a string has
1629    a null terminator, which isn't necessary as a terminator for
1630    the transfer language (as there's a length), but is presumably
1631    there for the benefit of null-terminated-string languages
1632    such as C.  Is this ever used for purely counted strings?
1633    (Not that it matters if it is.) */
1634 int
1635 dissect_ndr_char_vstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
1636                         proto_tree *tree, guint8 *drep)
1637 {
1638     dcerpc_info *di;
1639     di=pinfo->private_data;
1640
1641     return dissect_ndr_vstring(tvb, offset, pinfo, tree, drep,
1642                                 sizeof(guint8), di->hf_index,
1643                                 FALSE, NULL);
1644 }
1645
1646 /* Dissect a varying string of wchars (wide characters).
1647    This corresponds to IDL of the form '[string] wchar *foo'
1648
1649    XXX - at least according to the DCE RPC 1.1 spec, a string has
1650    a null terminator, which isn't necessary as a terminator for
1651    the transfer language (as there's a length), but is presumably
1652    there for the benefit of null-terminated-string languages
1653    such as C.  Is this ever used for purely counted strings?
1654    (Not that it matters if it is.) */
1655 int
1656 dissect_ndr_wchar_vstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
1657                         proto_tree *tree, guint8 *drep)
1658 {
1659     dcerpc_info *di;
1660     di=pinfo->private_data;
1661
1662     return dissect_ndr_vstring(tvb, offset, pinfo, tree, drep,
1663                                 sizeof(guint16), di->hf_index,
1664                                 FALSE, NULL);
1665 }
1666
1667
1668 /* ndr pointer handling */
1669 /* list of pointers encountered so far */
1670 static GSList *ndr_pointer_list = NULL;
1671
1672 /* position where in the list to insert newly encountered pointers */
1673 static int ndr_pointer_list_pos=0;
1674
1675 /* boolean controlling whether pointers are top-level or embedded */
1676 static gboolean pointers_are_top_level = TRUE;
1677
1678 /* as a kludge, we represent all embedded reference pointers as id==-1
1679    hoping that his will not collide with any non-ref pointers */
1680 typedef struct ndr_pointer_data {
1681         guint32 id;
1682         proto_item *item;       /* proto_item for pointer */
1683         proto_tree *tree;       /* subtree of above item */
1684         dcerpc_dissect_fnct_t *fnct; /*if non-NULL, we have not called it yet*/
1685         int hf_index;
1686         dcerpc_callback_fnct_t *callback;
1687         void *callback_args;
1688 } ndr_pointer_data_t;
1689
1690 void
1691 init_ndr_pointer_list(packet_info *pinfo)
1692 {
1693         dcerpc_info *di;
1694
1695         di=pinfo->private_data;
1696         di->conformant_run=0;
1697
1698         while(ndr_pointer_list){
1699                 ndr_pointer_data_t *npd;
1700
1701                 npd=g_slist_nth_data(ndr_pointer_list, 0);
1702                 ndr_pointer_list=g_slist_remove(ndr_pointer_list, npd);
1703                 if(npd){
1704                         g_free(npd);
1705                 }
1706         }
1707
1708         ndr_pointer_list=NULL;
1709         ndr_pointer_list_pos=0;
1710         pointers_are_top_level=TRUE;
1711 }
1712
1713 int
1714 dissect_deferred_pointers(packet_info *pinfo, tvbuff_t *tvb, int offset, guint8 *drep)
1715 {
1716         int found_new_pointer;
1717         dcerpc_info *di;
1718         int old_offset;
1719         int next_pointer;
1720
1721         next_pointer=0;
1722         di=pinfo->private_data;
1723         do{
1724                 int i, len;
1725
1726                 found_new_pointer=0;
1727                 len=g_slist_length(ndr_pointer_list);
1728                 for(i=next_pointer;i<len;i++){
1729                         ndr_pointer_data_t *tnpd;
1730                         tnpd=g_slist_nth_data(ndr_pointer_list, i);
1731                         if(tnpd->fnct){
1732                                 dcerpc_dissect_fnct_t *fnct;
1733
1734                                 next_pointer=i+1;
1735                                 found_new_pointer=1;
1736                                 fnct=tnpd->fnct;
1737                                 tnpd->fnct=NULL;
1738                                 ndr_pointer_list_pos=i+1;
1739                                 di->hf_index=tnpd->hf_index;
1740                                 /* first a run to handle any conformant
1741                                    array headers */
1742                                 di->conformant_run=1;
1743                                 di->conformant_eaten=0;
1744                                 old_offset = offset;
1745                                 offset = (*(fnct))(tvb, offset, pinfo, NULL, drep);
1746
1747                                 DISSECTOR_ASSERT((offset-old_offset)==di->conformant_eaten);
1748                                 /* This is to check for any bugs in the dissectors.
1749                                  *
1750                                  * Basically, the NDR representation will store all
1751                                  * arrays in two blocks, one block with the dimension
1752                                  * discreption, like size, number of elements and such,
1753                                  * and another block that contains the actual data stored
1754                                  * in the array.
1755                                  * If the array is embedded directly inside another,
1756                                  * encapsulating aggregate type, like a union or struct,
1757                                  * then these two blocks will be stored at different places
1758                                  * in the bytestream, with other data between the blocks.
1759                                  *
1760                                  * For this reason, all pointers to types (both aggregate
1761                                  * and scalar, for simplicity no distinction is made)
1762                                  * will have its dissector called twice.
1763                                  * The dissector will first be called with conformant_run==1
1764                                  * in which mode the dissector MUST NOT consume any data from
1765                                  * the tvbuff (i.e. may not dissect anything) except the
1766                                  * initial control block for arrays.
1767                                  * The second time the dissector is called, with
1768                                  * conformant_run==0, all other data for the type will be
1769                                  * dissected.
1770                                  *
1771                                  * All dissect_ndr_<type> dissectors are already prepared
1772                                  * for this and knows when it should eat data from the tvb
1773                                  * and when not to, so implementors of dissectors will
1774                                  * normally not need to worry about this or even know about
1775                                  * it. However, if a dissector for an aggregate type calls
1776                                  * a subdissector from outside packet-dcerpc.c, such as
1777                                  * the dissector in packet-smb.c for NT Security Descriptors
1778                                  * as an example, then it is VERY important to encapsulate
1779                                  * this call to an external subdissector with the appropriate
1780                                  * test for conformant_run, i.e. it will need something like
1781                                  *
1782                                  *      dcerpc_info *di;
1783                                  *
1784                                  *      di=pinfo->private_data;
1785                                  *      if(di->conformant_run){
1786                                  *              return offset;
1787                                  *      }
1788                                  *
1789                                  * to make sure it makes the right thing.
1790                                  * This assert will signal when someone has forgotten to
1791                                  * make the dissector aware of this requirement.
1792                                  */
1793
1794                                 /* now we dissect the actual pointer */
1795                                 di->conformant_run=0;
1796                                 old_offset = offset;
1797                                 offset = (*(fnct))(tvb, offset, pinfo, tnpd->tree, drep);
1798                                 if (tnpd->callback)
1799                                         tnpd->callback(pinfo, tnpd->tree, tnpd->item, tvb, old_offset, offset, tnpd->callback_args);
1800                                 break;
1801                         }
1802                 }
1803         } while(found_new_pointer);
1804
1805         return offset;
1806 }
1807
1808
1809 static void
1810 add_pointer_to_list(packet_info *pinfo, proto_tree *tree, proto_item *item,
1811                     dcerpc_dissect_fnct_t *fnct, guint32 id, int hf_index,
1812                     dcerpc_callback_fnct_t *callback, void *callback_args)
1813 {
1814         ndr_pointer_data_t *npd;
1815
1816         /* check if this pointer is valid */
1817         if(id!=0xffffffff){
1818                 dcerpc_info *di;
1819                 dcerpc_call_value *value;
1820
1821                 di=pinfo->private_data;
1822                 value=di->call_data;
1823
1824                 if(di->ptype == PDU_REQ){
1825                         if(!(pinfo->fd->flags.visited)){
1826                                 if(id>value->max_ptr){
1827                                         value->max_ptr=id;
1828                                 }
1829                         }
1830                 } else {
1831                         /* if we havent seen the request bail out since we cant
1832                            know whether this is the first non-NULL instance
1833                            or not */
1834                         if(value->req_frame==0){
1835                                 /* XXX THROW EXCEPTION */
1836                         }
1837
1838                         /* We saw this one in the request frame, nothing to
1839                            dissect later */
1840                         if(id<=value->max_ptr){
1841                                 return;
1842                         }
1843                 }
1844         }
1845
1846         npd=g_malloc(sizeof(ndr_pointer_data_t));
1847         npd->id=id;
1848         npd->tree=tree;
1849         npd->item=item;
1850         npd->fnct=fnct;
1851         npd->hf_index=hf_index;
1852         npd->callback=callback;
1853         npd->callback_args=callback_args;
1854         ndr_pointer_list = g_slist_insert(ndr_pointer_list, npd,
1855                                         ndr_pointer_list_pos);
1856         ndr_pointer_list_pos++;
1857 }
1858
1859
1860 static int
1861 find_pointer_index(guint32 id)
1862 {
1863         ndr_pointer_data_t *npd;
1864         int i,len;
1865
1866         len=g_slist_length(ndr_pointer_list);
1867         for(i=0;i<len;i++){
1868                 npd=g_slist_nth_data(ndr_pointer_list, i);
1869                 if(npd){
1870                         if(npd->id==id){
1871                                 return i;
1872                         }
1873                 }
1874         }
1875
1876         return -1;
1877 }
1878
1879 /* This function dissects an NDR pointer and stores the callback for later
1880  * deferred dissection.
1881  *
1882  *   fnct is the callback function for when we have reached this object in
1883  *   the bytestream.
1884  *
1885  *   type is what type of pointer.
1886  *
1887  *   this is text is what text we should put in any created tree node.
1888  *
1889  *   hf_index is what hf value we want to pass to the callback function when
1890  *   it is called, the callback can later pich this one up from di->hf_index.
1891  *
1892  *   callback is executed after the pointer has been dereferenced.
1893  *
1894  *   callback_args is passed as an argument to the callback function
1895  *
1896  * See packet-dcerpc-samr.c for examples
1897  */
1898 int
1899 dissect_ndr_pointer_cb(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1900                     proto_tree *tree, guint8 *drep, dcerpc_dissect_fnct_t *fnct,
1901                     int type, const char *text, int hf_index,
1902                     dcerpc_callback_fnct_t *callback, void *callback_args)
1903 {
1904         dcerpc_info *di;
1905         proto_tree *tr = NULL;
1906         gint start_offset = offset;
1907
1908         di=pinfo->private_data;
1909         if(di->conformant_run){
1910                 /* this call was only for dissecting the header for any
1911                    embedded conformant array. we will not parse any
1912                    pointers in this mode.
1913                 */
1914                 return offset;
1915         }
1916
1917         /*TOP LEVEL REFERENCE POINTER*/
1918         if( pointers_are_top_level
1919         &&(type==NDR_POINTER_REF) ){
1920                 proto_item *item;
1921
1922                 /* we must find out a nice way to do the length here */
1923                 item=proto_tree_add_text(tree, tvb, offset, 0,
1924                         "%s", text);
1925                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1926
1927                 add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff,
1928                                     hf_index, callback, callback_args);
1929                 goto after_ref_id;
1930         }
1931
1932         /*TOP LEVEL FULL POINTER*/
1933         if( pointers_are_top_level
1934         && (type==NDR_POINTER_PTR) ){
1935                 int idx;
1936                 guint32 id;
1937                 proto_item *item;
1938
1939                 /* get the referent id */
1940                 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
1941
1942                 tvb_ensure_bytes_exist(tvb, offset-4, 4);
1943                 /* we got a NULL pointer */
1944                 if(id==0){
1945                         proto_tree_add_text(tree, tvb, offset-4, 4,
1946                                 "(NULL pointer) %s",text);
1947                         goto after_ref_id;
1948                 }
1949
1950                 /* see if we have seen this pointer before */
1951                 idx=find_pointer_index(id);
1952
1953                 /* we have seen this pointer before */
1954                 if(idx>=0){
1955                         proto_tree_add_text(tree, tvb, offset-4, 4,
1956                                 "(duplicate PTR) %s",text);
1957                         goto after_ref_id;
1958                 }
1959
1960                 /* new pointer */
1961                 item=proto_tree_add_text(tree, tvb, offset-4, 4,
1962                         "%s", text);
1963                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1964                 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
1965                 add_pointer_to_list(pinfo, tr, item, fnct, id, hf_index,
1966                                     callback, callback_args);
1967                 goto after_ref_id;
1968         }
1969         /*TOP LEVEL UNIQUE POINTER*/
1970         if( pointers_are_top_level
1971         && (type==NDR_POINTER_UNIQUE) ){
1972                 guint32 id;
1973                 proto_item *item;
1974
1975                 /* get the referent id */
1976                 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
1977
1978                 tvb_ensure_bytes_exist(tvb, offset-4, 4);
1979                 /* we got a NULL pointer */
1980                 if(id==0){
1981                         proto_tree_add_text(tree, tvb, offset-4, 4,
1982                                 "(NULL pointer) %s",text);
1983                         goto after_ref_id;
1984                 }
1985
1986                 /* new pointer */
1987                 item=proto_tree_add_text(tree, tvb, offset-4, 4,
1988                         "%s", text);
1989                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1990                 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
1991                 add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff,
1992                                     hf_index, callback, callback_args);
1993                 goto after_ref_id;
1994         }
1995
1996         /*EMBEDDED REFERENCE POINTER*/
1997         if( (!pointers_are_top_level)
1998         && (type==NDR_POINTER_REF) ){
1999                 guint32 id;
2000                 proto_item *item;
2001
2002                 /* get the referent id */
2003                 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
2004
2005                 tvb_ensure_bytes_exist(tvb, offset-4, 4);
2006                 /* new pointer */
2007                 item=proto_tree_add_text(tree, tvb, offset-4, 4,
2008                         "%s",text);
2009                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
2010                 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
2011                 add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff,
2012                                     hf_index, callback, callback_args);
2013                 goto after_ref_id;
2014         }
2015
2016         /*EMBEDDED UNIQUE POINTER*/
2017         if( (!pointers_are_top_level)
2018         && (type==NDR_POINTER_UNIQUE) ){
2019                 guint32 id;
2020                 proto_item *item;
2021
2022                 /* get the referent id */
2023                 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
2024
2025                 tvb_ensure_bytes_exist(tvb, offset-4, 4);
2026                 /* we got a NULL pointer */
2027                 if(id==0){
2028                         proto_tree_add_text(tree, tvb, offset-4, 4,
2029                                 "(NULL pointer) %s", text);
2030                         goto after_ref_id;
2031                 }
2032
2033                 /* new pointer */
2034                 item=proto_tree_add_text(tree, tvb, offset-4, 4,
2035                         "%s",text);
2036                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
2037                 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
2038                 add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff,
2039                                     hf_index, callback, callback_args);
2040                 goto after_ref_id;
2041         }
2042
2043         /*EMBEDDED FULL POINTER*/
2044         if( (!pointers_are_top_level)
2045         && (type==NDR_POINTER_PTR) ){
2046                 int idx;
2047                 guint32 id;
2048                 proto_item *item;
2049
2050                 /* get the referent id */
2051                 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
2052
2053                 tvb_ensure_bytes_exist(tvb, offset-4, 4);
2054                 /* we got a NULL pointer */
2055                 if(id==0){
2056                         proto_tree_add_text(tree, tvb, offset-4, 4,
2057                                 "(NULL pointer) %s",text);
2058                         goto after_ref_id;
2059                 }
2060
2061                 /* see if we have seen this pointer before */
2062                 idx=find_pointer_index(id);
2063
2064                 /* we have seen this pointer before */
2065                 if(idx>=0){
2066                         proto_tree_add_text(tree, tvb, offset-4, 4,
2067                                 "(duplicate PTR) %s",text);
2068                         goto after_ref_id;
2069                 }
2070
2071                 /* new pointer */
2072                 item=proto_tree_add_text(tree, tvb, offset-4, 4,
2073                         "%s", text);
2074                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
2075                 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
2076                 add_pointer_to_list(pinfo, tr, item, fnct, id, hf_index,
2077                                     callback, callback_args);
2078                 goto after_ref_id;
2079         }
2080
2081
2082 after_ref_id:
2083         /* After each top level pointer we have dissected we have to
2084            dissect all deferrals before we move on to the next top level
2085            argument */
2086         if(pointers_are_top_level==TRUE){
2087                 pointers_are_top_level=FALSE;
2088                 offset = dissect_deferred_pointers(pinfo, tvb, offset, drep);
2089                 pointers_are_top_level=TRUE;
2090         }
2091
2092         /* Set the length for the new subtree */
2093         if (tr){
2094                 proto_item_set_len(tr, offset-start_offset);
2095         }
2096         return offset;
2097 }
2098
2099 int
2100 dissect_ndr_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2101                     proto_tree *tree, guint8 *drep, dcerpc_dissect_fnct_t *fnct,
2102                     int type, const char *text, int hf_index)
2103 {
2104         return dissect_ndr_pointer_cb(
2105                 tvb, offset, pinfo, tree, drep, fnct, type, text, hf_index,
2106                 NULL, NULL);
2107 }
2108 int
2109 dissect_ndr_toplevel_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2110                     proto_tree *tree, guint8 *drep, dcerpc_dissect_fnct_t *fnct,
2111                     int type, const char *text, int hf_index)
2112 {
2113         int ret;
2114
2115         pointers_are_top_level=TRUE;
2116         ret=dissect_ndr_pointer_cb(
2117                 tvb, offset, pinfo, tree, drep, fnct, type, text, hf_index,
2118                 NULL, NULL);
2119         return ret;
2120 }
2121 int
2122 dissect_ndr_embedded_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2123                     proto_tree *tree, guint8 *drep, dcerpc_dissect_fnct_t *fnct,
2124                     int type, const char *text, int hf_index)
2125 {
2126         int ret;
2127
2128         pointers_are_top_level=FALSE;
2129         ret=dissect_ndr_pointer_cb(
2130                 tvb, offset, pinfo, tree, drep, fnct, type, text, hf_index,
2131                 NULL, NULL);
2132         return ret;
2133 }
2134
2135 static void
2136 show_stub_data (tvbuff_t *tvb, gint offset, proto_tree *dcerpc_tree,
2137                 dcerpc_auth_info *auth_info, gboolean is_encrypted)
2138 {
2139     int length, plain_length, auth_pad_len;
2140     guint auth_pad_offset;
2141
2142     /*
2143      * We don't show stub data unless we have some in the tvbuff;
2144      * however, in the protocol tree, we show, as the number of
2145      * bytes, the reported number of bytes, not the number of bytes
2146      * that happen to be in the tvbuff.
2147      */
2148     if (tvb_length_remaining (tvb, offset) > 0) {
2149         auth_pad_len = auth_info?auth_info->auth_pad_len:0;
2150         length = tvb_reported_length_remaining (tvb, offset);
2151
2152         /* if auth_pad_len is larger than length then we ignore auth_pad_len totally */
2153         plain_length = length - auth_pad_len;
2154         if (plain_length < 1) {
2155             plain_length = length;
2156             auth_pad_len = 0;
2157         }
2158         auth_pad_offset = offset + plain_length;
2159
2160         if (auth_info != NULL &&
2161             auth_info->auth_level == DCE_C_AUTHN_LEVEL_PKT_PRIVACY) {
2162             if (is_encrypted) {
2163                 tvb_ensure_bytes_exist(tvb, offset, length);
2164                 proto_tree_add_text(dcerpc_tree, tvb, offset, length,
2165                                     "Encrypted stub data (%d byte%s)",
2166                                     length, plurality(length, "", "s"));
2167                 /* is the padding is still inside the encrypted blob, don't display it explicit */
2168                 auth_pad_len = 0;
2169             } else {
2170                 tvb_ensure_bytes_exist(tvb, offset, plain_length);
2171                 proto_tree_add_text(dcerpc_tree, tvb, offset, plain_length,
2172                                     "Decrypted stub data (%d byte%s)",
2173                                     plain_length, plurality(plain_length, "", "s"));
2174             }
2175         } else {
2176             tvb_ensure_bytes_exist(tvb, offset, plain_length);
2177             proto_tree_add_text (dcerpc_tree, tvb, offset, plain_length,
2178                                  "Stub data (%d byte%s)", plain_length,
2179                                  plurality(plain_length, "", "s"));
2180         }
2181         /* If there is auth padding at the end of the stub, display it */
2182         if (auth_pad_len != 0) {
2183                 tvb_ensure_bytes_exist(tvb, auth_pad_offset, auth_pad_len);
2184                 proto_tree_add_text (dcerpc_tree, tvb, auth_pad_offset,
2185                                      auth_pad_len,
2186                                      "Auth Padding (%u byte%s)",
2187                                      auth_pad_len,
2188                                      plurality(auth_pad_len, "", "s"));
2189             }
2190     }
2191 }
2192
2193 static int
2194 dcerpc_try_handoff (packet_info *pinfo, proto_tree *tree,
2195                     proto_tree *dcerpc_tree,
2196                     tvbuff_t *volatile tvb, tvbuff_t *decrypted_tvb,
2197                     guint8 *drep, dcerpc_info *info,
2198                     dcerpc_auth_info *auth_info)
2199 {
2200     volatile gint offset = 0;
2201     dcerpc_uuid_key key;
2202     dcerpc_uuid_value *sub_proto;
2203     proto_tree *volatile sub_tree = NULL;
2204     dcerpc_sub_dissector *proc;
2205     const gchar *name = NULL;
2206     dcerpc_dissect_fnct_t *volatile sub_dissect;
2207     const char *volatile saved_proto;
2208     void *volatile saved_private_data;
2209     guint length, reported_length;
2210     tvbuff_t *volatile stub_tvb;
2211     volatile guint auth_pad_len;
2212     volatile int auth_pad_offset;
2213 #ifdef _WIN32
2214     char uuid_name[MAX_PATH];
2215 #endif
2216     proto_item *sub_item=NULL;
2217     proto_item *pi;
2218
2219     key.uuid = info->call_data->uuid;
2220     key.ver = info->call_data->ver;
2221
2222
2223     if ((sub_proto = g_hash_table_lookup (dcerpc_uuids, &key)) == NULL
2224          || !proto_is_protocol_enabled(sub_proto->proto)) {
2225         /*
2226          * We don't have a dissector for this UUID, or the protocol
2227          * for that UUID is disabled.
2228          */
2229
2230         proto_tree_add_boolean_hidden(dcerpc_tree, hf_dcerpc_unknown_if_id,
2231                                           tvb, offset, 0, TRUE);
2232         if (check_col (pinfo->cinfo, COL_INFO)) {
2233 #ifdef _WIN32
2234                 if(ResolveWin32UUID(info->call_data->uuid, uuid_name, MAX_PATH))
2235                         col_append_fstr (pinfo->cinfo, COL_INFO, " [%s] UUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x rpcver: %u",
2236                                 uuid_name, info->call_data->uuid.Data1, info->call_data->uuid.Data2, info->call_data->uuid.Data3, info->call_data->uuid.Data4[0],
2237                                 info->call_data->uuid.Data4[1], info->call_data->uuid.Data4[2], info->call_data->uuid.Data4[3],
2238                                 info->call_data->uuid.Data4[4], info->call_data->uuid.Data4[5], info->call_data->uuid.Data4[6],
2239                                 info->call_data->uuid.Data4[7], info->call_data->ver);
2240 else
2241 #endif
2242                 col_append_fstr (pinfo->cinfo, COL_INFO, " UNKUUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x rpcver: %u",
2243                         info->call_data->uuid.Data1, info->call_data->uuid.Data2, info->call_data->uuid.Data3, info->call_data->uuid.Data4[0],
2244                         info->call_data->uuid.Data4[1], info->call_data->uuid.Data4[2], info->call_data->uuid.Data4[3],
2245                         info->call_data->uuid.Data4[4], info->call_data->uuid.Data4[5], info->call_data->uuid.Data4[6],
2246                         info->call_data->uuid.Data4[7], info->call_data->ver);
2247         }
2248
2249         if (decrypted_tvb != NULL) {
2250             show_stub_data (decrypted_tvb, 0, dcerpc_tree, auth_info,
2251                             FALSE);
2252         } else
2253             show_stub_data (tvb, 0, dcerpc_tree, auth_info, TRUE);
2254         return -1;
2255     }
2256
2257     for (proc = sub_proto->procs; proc->name; proc++) {
2258         if (proc->num == info->call_data->opnum) {
2259             name = proc->name;
2260             break;
2261         }
2262     }
2263
2264     if (!name)
2265         name = "Unknown?!";
2266
2267     if (check_col (pinfo->cinfo, COL_PROTOCOL)) {
2268         col_set_str (pinfo->cinfo, COL_PROTOCOL, sub_proto->name);
2269     }
2270
2271     if (check_col (pinfo->cinfo, COL_INFO)) {
2272         col_add_fstr (pinfo->cinfo, COL_INFO, "%s %s",
2273                       name, (info->ptype == PDU_REQ) ? "request" : "response");
2274     }
2275
2276     sub_dissect = (info->ptype == PDU_REQ) ?
2277             proc->dissect_rqst : proc->dissect_resp;
2278
2279     if (tree) {
2280         sub_item = proto_tree_add_item (tree, sub_proto->proto_id, tvb, 0,
2281                                         -1, FALSE);
2282
2283         if (sub_item) {
2284             sub_tree = proto_item_add_subtree (sub_item, sub_proto->ett);
2285             proto_item_append_text(sub_item, ", %s", name);
2286         }
2287
2288         /*
2289          * Put the operation number into the tree along with
2290          * the operation's name.
2291          */
2292     if(sub_dissect == NULL)
2293         if (sub_proto->opnum_hf != -1)
2294             proto_tree_add_uint_format(sub_tree, sub_proto->opnum_hf,
2295                                        tvb, 0, 0, info->call_data->opnum,
2296                                        "Operation: %s (%u)",
2297                                        name, info->call_data->opnum);
2298         else
2299             proto_tree_add_uint_format(sub_tree, hf_dcerpc_op, tvb,
2300                                        0, 0, info->call_data->opnum,
2301                                        "Operation: %s (%u)",
2302                                        name, info->call_data->opnum);
2303
2304     if(info->ptype == PDU_REQ && info->call_data->rep_frame!=0) {
2305                 pi = proto_tree_add_uint(sub_tree, hf_dcerpc_response_in,
2306                                     tvb, 0, 0, info->call_data->rep_frame);
2307         PROTO_ITEM_SET_GENERATED(pi);
2308     }
2309     if(info->ptype == PDU_RESP && info->call_data->req_frame!=0) {
2310                 pi = proto_tree_add_uint(sub_tree, hf_dcerpc_request_in,
2311                                     tvb, 0, 0, info->call_data->req_frame);
2312         PROTO_ITEM_SET_GENERATED(pi);
2313     }
2314     } /* tree */
2315
2316     if (decrypted_tvb != NULL) {
2317         /* Either there was no encryption or we successfully decrypted
2318            the encrypted payload. */
2319         if (sub_dissect) {
2320             /* We have a subdissector - call it. */
2321             saved_proto = pinfo->current_proto;
2322             saved_private_data = pinfo->private_data;
2323             pinfo->current_proto = sub_proto->name;
2324             pinfo->private_data = (void *)info;
2325
2326             init_ndr_pointer_list(pinfo);
2327
2328             /*
2329              * Remove the authentication padding from the stub data.
2330              */
2331             if (auth_info != NULL && auth_info->auth_pad_len != 0) {
2332                 length = tvb_length(decrypted_tvb);
2333                 reported_length = tvb_reported_length(decrypted_tvb);
2334                 if (reported_length >= auth_info->auth_pad_len) {
2335                     /*
2336                      * OK, the padding length isn't so big that it
2337                      * exceeds the stub length.  Trim the reported
2338                      * length of the tvbuff.
2339                      */
2340                     reported_length -= auth_info->auth_pad_len;
2341
2342                     /*
2343                      * If that exceeds the actual amount of data in
2344                      * the tvbuff (which means we have at least one
2345                      * byte of authentication padding in the tvbuff),
2346                      * trim the actual amount.
2347                      */
2348                     if (length > reported_length)
2349                         length = reported_length;
2350
2351                     stub_tvb = tvb_new_subset(tvb, 0, length, reported_length);
2352                     auth_pad_len = auth_info->auth_pad_len;
2353                     auth_pad_offset = reported_length;
2354                 } else {
2355                     /*
2356                      * The padding length exceeds the stub length.
2357                      * Don't bother dissecting the stub, trim the padding
2358                      * length to what's in the stub data, and show the
2359                      * entire stub as authentication padding.
2360                      */
2361                     stub_tvb = NULL;
2362                     auth_pad_len = reported_length;
2363                     auth_pad_offset = 0;
2364                 }
2365             } else {
2366                 /*
2367                  * No authentication padding.
2368                  */
2369                 stub_tvb = decrypted_tvb;
2370                 auth_pad_len = 0;
2371                 auth_pad_offset = 0;
2372             }
2373
2374             if (stub_tvb != NULL) {
2375                 /*
2376                  * Catch all exceptions other than BoundsError, so that even
2377                  * if the stub data is bad, we still show the authentication
2378                  * padding, if any.
2379                  *
2380                  * If we get BoundsError, it means the frame was cut short
2381                  * by a snapshot length, so there's nothing more to
2382                  * dissect; just re-throw that exception.
2383                  */
2384                 TRY {
2385                     offset = sub_dissect (decrypted_tvb, 0, pinfo, sub_tree,
2386                                           drep);
2387                     if(tree) {
2388                         proto_item_set_len(sub_item, offset);
2389                     }
2390
2391                     /* If we have a subdissector and it didn't dissect all
2392                        data in the tvb, make a note of it. */
2393                     /* XXX - don't do this, as this could be just another RPC Req./Resp. in this PDU */
2394                     /*if (tvb_reported_length_remaining(stub_tvb, offset) > 0) {
2395                         if (check_col(pinfo->cinfo, COL_INFO))
2396                             col_append_fstr(pinfo->cinfo, COL_INFO,
2397                                             "[Long frame (%d bytes)]",
2398                                             tvb_reported_length_remaining(stub_tvb, offset));
2399                     }*/
2400                 } CATCH(BoundsError) {
2401                     RETHROW;
2402                 } CATCH_ALL {
2403                     show_exception(decrypted_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
2404                 } ENDTRY;
2405             }
2406
2407             /* If there is auth padding at the end of the stub, display it */
2408             if (auth_pad_len != 0) {
2409                 tvb_ensure_bytes_exist(tvb, auth_pad_offset, auth_pad_len);
2410                 proto_tree_add_text (sub_tree, decrypted_tvb, auth_pad_offset,
2411                                      auth_pad_len,
2412                                      "Auth Padding (%u byte%s)",
2413                                      auth_pad_len,
2414                                      plurality(auth_pad_len, "", "s"));
2415             }
2416
2417             pinfo->current_proto = saved_proto;
2418             pinfo->private_data = saved_private_data;
2419         } else {
2420             /* No subdissector - show it as stub data. */
2421             if(decrypted_tvb){
2422                show_stub_data (decrypted_tvb, 0, sub_tree, auth_info, FALSE);
2423             } else {
2424                show_stub_data (tvb, 0, sub_tree, auth_info, TRUE);
2425             }
2426         }
2427     } else
2428         show_stub_data (tvb, 0, sub_tree, auth_info, TRUE);
2429
2430     tap_queue_packet(dcerpc_tap, pinfo, info);
2431     return 0;
2432 }
2433
2434 static int
2435 dissect_dcerpc_verifier (tvbuff_t *tvb, packet_info *pinfo,
2436                          proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr,
2437                          dcerpc_auth_info *auth_info)
2438 {
2439     int auth_offset;
2440
2441     auth_info->auth_data = NULL;
2442
2443     if (auth_info->auth_size != 0) {
2444         dcerpc_auth_subdissector_fns *auth_fns;
2445         tvbuff_t *auth_tvb;
2446
2447         auth_offset = hdr->frag_len - hdr->auth_len;
2448
2449         auth_tvb = tvb_new_subset(tvb, auth_offset, hdr->auth_len,
2450                                   hdr->auth_len);
2451
2452         auth_info->auth_data = auth_tvb;
2453
2454         if ((auth_fns = get_auth_subdissector_fns(auth_info->auth_level,
2455                                                   auth_info->auth_type))) {
2456             /*
2457              * Catch all exceptions, so that even if the verifier is bad
2458              * or we don't have all of it, we still show the stub data.
2459              */
2460             TRY {
2461                 dissect_auth_verf(auth_tvb, pinfo, dcerpc_tree, auth_fns,
2462                                   hdr, auth_info);
2463             } CATCH_ALL {
2464                 show_exception(auth_tvb, pinfo, dcerpc_tree, EXCEPT_CODE, GET_MESSAGE);
2465             } ENDTRY;
2466         } else {
2467             tvb_ensure_bytes_exist(tvb, 0, hdr->auth_len);
2468             proto_tree_add_text (dcerpc_tree, auth_tvb, 0, hdr->auth_len,
2469                                  "Auth Verifier");
2470         }
2471     }
2472
2473     return hdr->auth_len;
2474 }
2475
2476 static void
2477 dissect_dcerpc_cn_auth (tvbuff_t *tvb, int stub_offset, packet_info *pinfo,
2478                         proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr,
2479                         gboolean are_credentials, dcerpc_auth_info *auth_info)
2480 {
2481     volatile int offset;
2482
2483     /*
2484      * Initially set auth_level and auth_type to zero to indicate that we
2485      * haven't yet seen any authentication level information.
2486      */
2487     auth_info->auth_level = 0;
2488     auth_info->auth_type = 0;
2489     auth_info->auth_size = 0;
2490     auth_info->auth_pad_len = 0;
2491
2492     /*
2493      * The authentication information is at the *end* of the PDU; in
2494      * request and response PDUs, the request and response stub data
2495      * come before it.
2496      *
2497      * Is there any authentication data (i.e., is the authentication length
2498      * non-zero), and is the authentication length valid (i.e., is it, plus
2499      * 8 bytes for the type/level/pad length/reserved/context id, less than
2500      * or equal to the fragment length minus the starting offset of the
2501      * stub data?)
2502      */
2503
2504     if (hdr->auth_len
2505         && (hdr->auth_len + 8 <= hdr->frag_len - stub_offset)) {
2506
2507         /*
2508          * Yes, there is authentication data, and the length is valid.
2509          * Do we have all the bytes of stub data?
2510          * (If not, we'd throw an exception dissecting *that*, so don't
2511          * bother trying to dissect the authentication information and
2512          * throwing another exception there.)
2513          */
2514         offset = hdr->frag_len - (hdr->auth_len + 8);
2515         if (offset == 0 || tvb_offset_exists(tvb, offset - 1)) {
2516             /*
2517              * Either there's no stub data, or the last byte of the stub
2518              * data is present in the captured data, so we shouldn't
2519              * get a BoundsError dissecting the stub data.
2520              *
2521              * Try dissecting the authentication data.
2522              * Catch all exceptions, so that even if the auth info is bad
2523              * or we don't have all of it, we still show the stuff we
2524              * dissect after this, such as stub data.
2525              */
2526             TRY {
2527                 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2528                                                hf_dcerpc_auth_type,
2529                                                &auth_info->auth_type);
2530                 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2531                                                hf_dcerpc_auth_level,
2532                                                &auth_info->auth_level);
2533
2534                 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2535                                                hf_dcerpc_auth_pad_len,
2536                                                &auth_info->auth_pad_len);
2537                 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2538                                                hf_dcerpc_auth_rsrvd, NULL);
2539                 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2540                                                 hf_dcerpc_auth_ctx_id, NULL);
2541
2542                 /*
2543                  * Dissect the authentication data.
2544                  */
2545                 if (are_credentials) {
2546                     tvbuff_t *auth_tvb;
2547                     dcerpc_auth_subdissector_fns *auth_fns;
2548
2549                     auth_tvb = tvb_new_subset(tvb, offset,
2550                                    MIN(hdr->auth_len,tvb_length_remaining(tvb, offset)),
2551                                    hdr->auth_len);
2552
2553                     if ((auth_fns = get_auth_subdissector_fns(auth_info->auth_level,
2554                                                               auth_info->auth_type)))
2555                         dissect_auth_verf(auth_tvb, pinfo, dcerpc_tree, auth_fns,
2556                                           hdr, auth_info);
2557                     else
2558                         proto_tree_add_text (dcerpc_tree, tvb, offset, hdr->auth_len,
2559                                              "Auth Credentials");
2560                 }
2561
2562                 /* Compute the size of the auth block.  Note that this should not
2563                    include auth padding, since when NTLMSSP encryption is used, the
2564                    padding is actually inside the encrypted stub */
2565                    auth_info->auth_size = hdr->auth_len + 8;
2566             } CATCH_ALL {
2567                 show_exception(tvb, pinfo, dcerpc_tree, EXCEPT_CODE, GET_MESSAGE);
2568             } ENDTRY;
2569         }
2570     }
2571 }
2572
2573
2574 /* We need to hash in the SMB fid number to generate a unique hash table
2575  * key as DCERPC over SMB allows several pipes over the same TCP/IP
2576  * socket.
2577  * We pass this function the transport type here to make sure we only look
2578  * at this function if it came across an SMB pipe.
2579  * Other transports might need to mix in their own extra multiplexing data
2580  * as well in the future.
2581  */
2582
2583 guint16 dcerpc_get_transport_salt (packet_info *pinfo)
2584 {
2585     switch(pinfo->dcetransporttype){
2586         case DCE_CN_TRANSPORT_SMBPIPE:
2587             /* DCERPC over smb */
2588             return pinfo->dcetransportsalt;
2589     }
2590
2591     /* Some other transport... */
2592     return 0;
2593 }
2594
2595 /*
2596  * Connection oriented packet types
2597  */
2598
2599 static void
2600 dissect_dcerpc_cn_bind (tvbuff_t *tvb, gint offset, packet_info *pinfo,
2601                         proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr)
2602 {
2603     conversation_t *conv = NULL;
2604     guint8 num_ctx_items = 0;
2605     guint i;
2606     gboolean saw_ctx_item = FALSE;
2607     guint16 ctx_id;
2608     guint8 num_trans_items;
2609     guint j;
2610     e_uuid_t if_id;
2611     e_uuid_t trans_id;
2612     guint32 trans_ver;
2613     guint16 if_ver, if_ver_minor;
2614     char uuid_str[DCERPC_UUID_STR_LEN];
2615     int uuid_str_len;
2616     dcerpc_auth_info auth_info;
2617     char *uuid_name = NULL;
2618 #ifdef _WIN32
2619     char uuid_name2[MAX_PATH];
2620 #endif
2621         proto_item *iface_item;
2622
2623     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2624                                     hf_dcerpc_cn_max_xmit, NULL);
2625
2626     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2627                                     hf_dcerpc_cn_max_recv, NULL);
2628
2629     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2630                                     hf_dcerpc_cn_assoc_group, NULL);
2631
2632     offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2633                                     hf_dcerpc_cn_num_ctx_items, &num_ctx_items);
2634
2635     /* padding */
2636     offset += 3;
2637
2638     for (i = 0; i < num_ctx_items; i++) {
2639             proto_item *ctx_item;
2640             proto_tree *ctx_tree = NULL, *iface_tree = NULL;
2641         gint ctx_offset = offset;
2642
2643       dissect_dcerpc_uint16 (tvb, offset, pinfo, NULL, hdr->drep,
2644                                       hf_dcerpc_cn_ctx_id, &ctx_id);
2645
2646       if (check_col (pinfo->cinfo, COL_DCE_CTX)) {
2647                 if(pinfo->dcectxid == 0) {
2648                         col_append_fstr (pinfo->cinfo, COL_DCE_CTX, "%u", ctx_id);
2649                 } else {
2650                         /* this is not the first DCE-RPC request/response in this (TCP?-)PDU,
2651                          * prepend a delimiter */
2652                         col_append_fstr (pinfo->cinfo, COL_DCE_CTX, "#%u", ctx_id);
2653                 }
2654       } 
2655
2656       /* save context ID for use with dcerpc_add_conv_to_bind_table() */
2657       /* (if we have multiple contexts, this might cause "decode as"
2658        *  to behave unpredictably) */
2659       pinfo->dcectxid = ctx_id;
2660
2661       if (dcerpc_tree) {
2662               ctx_item = proto_tree_add_item(dcerpc_tree, hf_dcerpc_cn_ctx_item,
2663                                              tvb, offset, 0,
2664                                              hdr->drep[0] & 0x10);
2665               ctx_tree = proto_item_add_subtree(ctx_item, ett_dcerpc_cn_ctx);
2666       }
2667
2668       offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, ctx_tree, hdr->drep,
2669                                       hf_dcerpc_cn_ctx_id, &ctx_id);
2670       offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, ctx_tree, hdr->drep,
2671                                       hf_dcerpc_cn_num_trans_items, &num_trans_items);
2672
2673       if(dcerpc_tree) {
2674         proto_item_append_text(ctx_item, "[%u]: ID:%u", i+1, ctx_id);
2675       }
2676
2677       /* padding */
2678       offset += 1;
2679
2680       dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &if_id);
2681       if (ctx_tree) {
2682
2683       iface_item = proto_tree_add_item(ctx_tree, hf_dcerpc_cn_bind_abstract_syntax, tvb, offset, 0, FALSE);
2684           iface_tree = proto_item_add_subtree(iface_item, ett_dcerpc_cn_iface);
2685
2686           uuid_str_len = g_snprintf(uuid_str, DCERPC_UUID_STR_LEN,
2687                                   "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
2688                                   if_id.Data1, if_id.Data2, if_id.Data3,
2689                                   if_id.Data4[0], if_id.Data4[1],
2690                                   if_id.Data4[2], if_id.Data4[3],
2691                                   if_id.Data4[4], if_id.Data4[5],
2692                                   if_id.Data4[6], if_id.Data4[7]);
2693
2694           if (uuid_str_len == -1 || uuid_str_len >= DCERPC_UUID_STR_LEN)
2695                   memset(uuid_str, 0, DCERPC_UUID_STR_LEN);
2696
2697 #ifdef _WIN32
2698       if(ResolveWin32UUID(if_id, uuid_name2, MAX_PATH)) {
2699         uuid_name = uuid_name2;
2700       }
2701       if(uuid_name) {
2702                   proto_tree_add_guid_format (iface_tree, hf_dcerpc_cn_bind_if_id, tvb,
2703                                         offset, 16, (e_guid_t *) &if_id, "Interface: %s UUID: %s", uuid_name, uuid_str);
2704           proto_item_append_text(iface_item, "%s", uuid_name);
2705       } else {
2706 #endif
2707           proto_tree_add_guid_format (iface_tree, hf_dcerpc_cn_bind_if_id, tvb,
2708                                         offset, 16, (e_guid_t *) &if_id, "Interface UUID: %s", uuid_str);
2709           proto_item_append_text(iface_item, "%s", uuid_str);
2710 #ifdef _WIN32
2711       }
2712 #endif
2713       }
2714       offset += 16;
2715
2716       if (hdr->drep[0] & 0x10) {
2717           offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, iface_tree, hdr->drep,
2718                                           hf_dcerpc_cn_bind_if_ver, &if_ver);
2719           offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, iface_tree, hdr->drep,
2720                                           hf_dcerpc_cn_bind_if_ver_minor, &if_ver_minor);
2721       } else {
2722           offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, iface_tree, hdr->drep,
2723                                           hf_dcerpc_cn_bind_if_ver_minor, &if_ver_minor);
2724           offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, iface_tree, hdr->drep,
2725                                           hf_dcerpc_cn_bind_if_ver, &if_ver);
2726       }
2727
2728       if (ctx_tree) {
2729           proto_item_append_text(iface_item, " V%u.%u", if_ver, if_ver_minor);
2730           proto_item_set_len(iface_item, 20);
2731       }
2732
2733       if (!saw_ctx_item) {
2734         conv = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
2735                                   pinfo->srcport, pinfo->destport, 0);
2736         if (conv == NULL) {
2737             conv = conversation_new (pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
2738                                      pinfo->srcport, pinfo->destport, 0);
2739         }
2740
2741
2742         /* if this is the first time we see this packet, we need to
2743            update the dcerpc_binds table so that any later calls can
2744            match to the interface.
2745            XXX We assume that BINDs will NEVER be fragmented.
2746         */
2747         if(!(pinfo->fd->flags.visited)){
2748                 dcerpc_bind_key *key;
2749                 dcerpc_bind_value *value;
2750
2751                 key = se_alloc (sizeof (dcerpc_bind_key));
2752                 key->conv = conv;
2753                 key->ctx_id = ctx_id;
2754                 key->smb_fid = dcerpc_get_transport_salt(pinfo);
2755
2756                 value = se_alloc (sizeof (dcerpc_bind_value));
2757                 value->uuid = if_id;
2758                 value->ver = if_ver;
2759
2760                 /* add this entry to the bind table, first removing any
2761                    previous ones that are identical
2762                  */
2763                 if(g_hash_table_lookup(dcerpc_binds, key)){
2764                         g_hash_table_remove(dcerpc_binds, key);
2765                 }
2766                 g_hash_table_insert (dcerpc_binds, key, value);
2767         }
2768
2769         if (check_col (pinfo->cinfo, COL_INFO)) {
2770           dcerpc_uuid_key key;
2771           dcerpc_uuid_value *value;
2772
2773           key.uuid = if_id;
2774           key.ver = if_ver;
2775
2776           if (num_ctx_items > 1)
2777                   col_append_fstr(pinfo->cinfo, COL_INFO, ", %u context items, 1st", num_ctx_items);
2778
2779           if ((value = g_hash_table_lookup(dcerpc_uuids, &key)))
2780                   col_append_fstr(pinfo->cinfo, COL_INFO, " UUID: %s", value->name);
2781           else
2782 #ifdef _WIN32
2783                 if(ResolveWin32UUID(if_id, uuid_name2, MAX_PATH))
2784                         col_append_fstr(pinfo->cinfo, COL_INFO, " [%s] UUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x ver %u.%u",
2785                            uuid_name2, if_id.Data1, if_id.Data2, if_id.Data3,
2786                            if_id.Data4[0], if_id.Data4[1],
2787                            if_id.Data4[2], if_id.Data4[3],
2788                            if_id.Data4[4], if_id.Data4[5],
2789                            if_id.Data4[6], if_id.Data4[7],
2790                            if_ver, if_ver_minor);
2791           else
2792 #endif
2793                         col_append_fstr(pinfo->cinfo, COL_INFO, " UUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x ver %u.%u",
2794                            if_id.Data1, if_id.Data2, if_id.Data3,
2795                            if_id.Data4[0], if_id.Data4[1],
2796                            if_id.Data4[2], if_id.Data4[3],
2797                            if_id.Data4[4], if_id.Data4[5],
2798                            if_id.Data4[6], if_id.Data4[7],
2799                            if_ver, if_ver_minor);
2800         }
2801         saw_ctx_item = TRUE;
2802       }
2803
2804       for (j = 0; j < num_trans_items; j++) {
2805             proto_tree *trans_tree = NULL;
2806             proto_item *trans_item = NULL;
2807
2808         dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &trans_id);
2809         if (ctx_tree) {
2810
2811         trans_item = proto_tree_add_item(ctx_tree, hf_dcerpc_cn_bind_trans_syntax, tvb, offset, 0, FALSE);
2812         trans_tree = proto_item_add_subtree(trans_item, ett_dcerpc_cn_trans_syntax);
2813
2814             uuid_str_len = g_snprintf(uuid_str, DCERPC_UUID_STR_LEN,
2815                                   "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
2816                                   trans_id.Data1, trans_id.Data2, trans_id.Data3,
2817                                   trans_id.Data4[0], trans_id.Data4[1],
2818                                   trans_id.Data4[2], trans_id.Data4[3],
2819                                   trans_id.Data4[4], trans_id.Data4[5],
2820                                   trans_id.Data4[6], trans_id.Data4[7]);
2821             if (uuid_str_len == -1 || uuid_str_len >= DCERPC_UUID_STR_LEN)
2822                 memset(uuid_str, 0, DCERPC_UUID_STR_LEN);
2823             proto_tree_add_guid_format (trans_tree, hf_dcerpc_cn_bind_trans_id, tvb,
2824                                           offset, 16, (e_guid_t *) &trans_id, "Transfer Syntax: %s", uuid_str);
2825             proto_item_append_text(trans_item, "[%u]: %s", j+1, uuid_str);
2826         }
2827         offset += 16;
2828
2829         offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, trans_tree, hdr->drep,
2830                                         hf_dcerpc_cn_bind_trans_ver, &trans_ver);
2831         if (ctx_tree) {
2832           proto_item_set_len(trans_item, 20);
2833           proto_item_append_text(trans_item, " V%u", trans_ver);
2834         }
2835       }
2836
2837       if(ctx_tree) {
2838         proto_item_set_len(ctx_item, offset - ctx_offset);
2839       }
2840     }
2841
2842     /*
2843      * XXX - we should save the authentication type *if* we have
2844      * an authentication header, and associate it with an authentication
2845      * context, so subsequent PDUs can use that context.
2846      */
2847     dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, hdr, TRUE, &auth_info);
2848 }
2849
2850 static void
2851 dissect_dcerpc_cn_bind_ack (tvbuff_t *tvb, gint offset, packet_info *pinfo,
2852                             proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr)
2853 {
2854     guint16 max_xmit, max_recv;
2855     guint16 sec_addr_len;
2856     guint8 num_results;
2857     guint i;
2858     guint16 result;
2859     guint16 reason;
2860     e_uuid_t trans_id;
2861     guint32 trans_ver;
2862     char uuid_str[DCERPC_UUID_STR_LEN];
2863     int uuid_str_len;
2864     dcerpc_auth_info auth_info;
2865
2866     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2867                                     hf_dcerpc_cn_max_xmit, &max_xmit);
2868
2869     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2870                                     hf_dcerpc_cn_max_recv, &max_recv);
2871
2872     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2873                                     hf_dcerpc_cn_assoc_group, NULL);
2874
2875     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2876                                     hf_dcerpc_cn_sec_addr_len, &sec_addr_len);
2877     if (sec_addr_len != 0) {
2878         tvb_ensure_bytes_exist(tvb, offset, sec_addr_len);
2879         proto_tree_add_item (dcerpc_tree, hf_dcerpc_cn_sec_addr, tvb, offset,
2880                              sec_addr_len, FALSE);
2881         offset += sec_addr_len;
2882     }
2883
2884     if (offset % 4) {
2885         offset += 4 - offset % 4;
2886     }
2887
2888     offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2889                                    hf_dcerpc_cn_num_results, &num_results);
2890
2891     /* padding */
2892     offset += 3;
2893
2894     for (i = 0; i < num_results; i++) {
2895         proto_tree *ctx_tree = NULL;
2896
2897         if(dcerpc_tree){
2898                 proto_item *ctx_item;
2899                 ctx_item = proto_tree_add_text(dcerpc_tree, tvb, offset, 24, "Context ID[%u]", i+1);
2900                 ctx_tree = proto_item_add_subtree(ctx_item, ett_dcerpc_cn_ctx);
2901         }
2902
2903         offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, ctx_tree,
2904                                         hdr->drep, hf_dcerpc_cn_ack_result,
2905                                         &result);
2906         if (result != 0) {
2907             offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, ctx_tree,
2908                                             hdr->drep, hf_dcerpc_cn_ack_reason,
2909                                             &reason);
2910         } else {
2911             /*
2912              * The reason for rejection isn't meaningful, and often isn't
2913              * set, when the syntax was accepted.
2914              */
2915             offset += 2;
2916         }
2917
2918         dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &trans_id);
2919         if (ctx_tree) {
2920             uuid_str_len = g_snprintf(uuid_str, DCERPC_UUID_STR_LEN,
2921                                   "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
2922                                   trans_id.Data1, trans_id.Data2, trans_id.Data3,
2923                                   trans_id.Data4[0], trans_id.Data4[1],
2924                                   trans_id.Data4[2], trans_id.Data4[3],
2925                                   trans_id.Data4[4], trans_id.Data4[5],
2926                                   trans_id.Data4[6], trans_id.Data4[7]);
2927             if (uuid_str_len == -1 || uuid_str_len >= DCERPC_UUID_STR_LEN)
2928                   memset(uuid_str, 0, DCERPC_UUID_STR_LEN);
2929             proto_tree_add_guid_format (ctx_tree, hf_dcerpc_cn_ack_trans_id, tvb,
2930                                           offset, 16, (e_guid_t *) &trans_id, "Transfer Syntax: %s", uuid_str);
2931         }
2932         offset += 16;
2933
2934         offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, ctx_tree, hdr->drep,
2935                                         hf_dcerpc_cn_ack_trans_ver, &trans_ver);
2936     }
2937
2938     /*
2939      * XXX - do we need to do anything with the authentication level
2940      * we get back from this?
2941      */
2942     dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, hdr, TRUE, &auth_info);
2943
2944     if (check_col (pinfo->cinfo, COL_INFO)) {
2945         if (num_results != 0 && result == 0) {
2946             /* XXX - only checks the last result */
2947             col_append_fstr (pinfo->cinfo, COL_INFO,
2948                              " accept max_xmit: %u max_recv: %u",
2949                              max_xmit, max_recv);
2950         } else {
2951             /* XXX - only shows the last result and reason */
2952             col_append_fstr (pinfo->cinfo, COL_INFO, " %s, reason: %s",
2953                              val_to_str(result, p_cont_result_vals,
2954                                         "Unknown result (%u)"),
2955                              val_to_str(reason, p_provider_reason_vals,
2956                                         "Unknown (%u)"));
2957         }
2958     }
2959 }
2960
2961 static void
2962 dissect_dcerpc_cn_bind_nak (tvbuff_t *tvb, gint offset, packet_info *pinfo,
2963                             proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr)
2964 {
2965     guint16 reason;
2966     guint8 num_protocols;
2967     guint i;
2968
2969     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
2970                                     hdr->drep, hf_dcerpc_cn_reject_reason,
2971                                     &reason);
2972
2973     if (check_col (pinfo->cinfo, COL_INFO)) {
2974         col_append_fstr (pinfo->cinfo, COL_INFO, " reason: %s",
2975                       val_to_str(reason, reject_reason_vals, "Unknown (%u)"));
2976     }
2977
2978     if (reason == PROTOCOL_VERSION_NOT_SUPPORTED) {
2979         offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2980                                        hf_dcerpc_cn_num_protocols,
2981                                        &num_protocols);
2982
2983         for (i = 0; i < num_protocols; i++) {
2984             offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree,
2985                                         hdr->drep, hf_dcerpc_cn_protocol_ver_major,
2986                                         NULL);
2987             offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree,
2988                                         hdr->drep, hf_dcerpc_cn_protocol_ver_minor,
2989                                         NULL);
2990         }
2991     }
2992 }
2993
2994 /* Return a string describing a DCE/RPC fragment as first, middle, or end
2995    fragment. */
2996
2997 #define PFC_FRAG_MASK  0x03
2998
2999 static const char *
3000 fragment_type(guint8 flags)
3001 {
3002         flags = flags & PFC_FRAG_MASK;
3003
3004         if (flags == PFC_FIRST_FRAG)
3005                 return "first";
3006
3007         if (flags == 0)
3008                 return "middle";
3009
3010         if (flags == PFC_LAST_FRAG)
3011                 return "last";
3012
3013         if (flags == (PFC_FIRST_FRAG | PFC_LAST_FRAG))
3014                 return "whole";
3015
3016         return "unknown";
3017 }
3018
3019 /* Dissect stub data (payload) of a DCERPC packet. */
3020
3021 static void
3022 dissect_dcerpc_cn_stub (tvbuff_t *tvb, int offset, packet_info *pinfo,
3023                         proto_tree *dcerpc_tree, proto_tree *tree,
3024                         e_dce_cn_common_hdr_t *hdr, dcerpc_info *di,
3025                         dcerpc_auth_info *auth_info, guint32 alloc_hint _U_,
3026                         guint32 frame)
3027 {
3028     gint length, reported_length;
3029     gboolean save_fragmented;
3030     fragment_data *fd_head=NULL;
3031
3032     tvbuff_t *auth_tvb, *payload_tvb, *decrypted_tvb;
3033     proto_item *pi;
3034     proto_item *parent_pi;
3035     proto_item *dcerpc_tree_item;
3036
3037     save_fragmented = pinfo->fragmented;
3038
3039     length = tvb_length_remaining(tvb, offset);
3040     reported_length = tvb_reported_length_remaining(tvb, offset);
3041     if (reported_length < 0 ||
3042         (guint32)reported_length < auth_info->auth_size) {
3043         /* We don't even have enough bytes for the authentication
3044            stuff. */
3045         return;
3046     }
3047     reported_length -= auth_info->auth_size;
3048     if (length > reported_length)
3049         length = reported_length;
3050     payload_tvb = tvb_new_subset(tvb, offset, length, reported_length);
3051
3052     auth_tvb=NULL;
3053     /*dont bother if we dont have the entire tvb */
3054     /*XXX we should really make sure we calculate auth_info->auth_data
3055         and use that one instead of this auth_tvb hack
3056     */
3057     if(tvb_length(tvb)==tvb_reported_length(tvb)){
3058         if(tvb_length_remaining(tvb, offset+length)>8){
3059             auth_tvb = tvb_new_subset(tvb, offset+length+8, -1, -1);
3060         }
3061     }
3062
3063     /* Decrypt the PDU if it is encrypted */
3064
3065     if (auth_info->auth_type &&
3066         auth_info->auth_level == DCE_C_AUTHN_LEVEL_PKT_PRIVACY) {
3067             /*
3068              * We know the authentication type, and the authentication
3069              * level is "Packet privacy", meaning the payload is
3070              * encrypted; attempt to decrypt it.
3071              */
3072             dcerpc_auth_subdissector_fns *auth_fns;
3073
3074             /* Start out assuming we won't succeed in decrypting. */
3075             decrypted_tvb = NULL;
3076
3077             if ((auth_fns = get_auth_subdissector_fns(
3078                          auth_info->auth_level, auth_info->auth_type))) {
3079                     tvbuff_t *result;
3080
3081                     result = decode_encrypted_data(
3082                             payload_tvb, auth_tvb, pinfo, auth_fns,
3083                             hdr->ptype == PDU_REQ, auth_info);
3084
3085                     if (result) {
3086                             if (dcerpc_tree)
3087                                 proto_tree_add_text(
3088                                             dcerpc_tree, payload_tvb, 0, -1,
3089                                             "Encrypted stub data (%d byte%s)",
3090                                             tvb_reported_length(payload_tvb),
3091
3092                             plurality(tvb_length(payload_tvb), "", "s"));
3093
3094                             add_new_data_source(
3095                                     pinfo, result, "Decrypted stub data");
3096
3097                             /* We succeeded. */
3098                             decrypted_tvb = result;
3099                     }
3100             }
3101     } else
3102             decrypted_tvb = payload_tvb;
3103
3104     /* if this packet is not fragmented, just dissect it and exit */
3105     if(PFC_NOT_FRAGMENTED(hdr)){
3106         pinfo->fragmented = FALSE;
3107
3108         dcerpc_try_handoff(
3109                 pinfo, tree, dcerpc_tree, payload_tvb, decrypted_tvb,
3110                 hdr->drep, di, auth_info);
3111
3112         pinfo->fragmented = save_fragmented;
3113         return;
3114     }
3115
3116     /* The packet is fragmented. */
3117     pinfo->fragmented = TRUE;
3118
3119         /* debug output of essential fragment data. */
3120         /* leave it here for future debugging sessions */
3121         /*printf("DCE num:%u offset:%u frag_len:%u tvb_len:%u\n",
3122                    pinfo->fd->num, offset, hdr->frag_len, tvb_length(decrypted_tvb));*/
3123
3124     /* if we are not doing reassembly and this is the first fragment
3125        then just dissect it and exit
3126        XXX - if we're not doing reassembly, can we decrypt an
3127        encrypted stub?
3128     */
3129     if( (!dcerpc_reassemble) && hdr->flags&PFC_FIRST_FRAG ){
3130
3131         dcerpc_try_handoff(
3132                 pinfo, tree, dcerpc_tree, payload_tvb, decrypted_tvb,
3133                 hdr->drep, di, auth_info);
3134
3135         if (check_col(pinfo->cinfo, COL_INFO)) {
3136             col_append_fstr(pinfo->cinfo, COL_INFO,
3137                             " [DCE/RPC %s fragment]", fragment_type(hdr->flags));
3138         }
3139                 expert_add_info_format(pinfo, NULL, PI_REASSEMBLE, PI_CHAT,
3140                         "%s fragment", fragment_type(hdr->flags));
3141         pinfo->fragmented = save_fragmented;
3142         return;
3143     }
3144
3145     /* if we have already seen this packet, see if it was reassembled
3146        and if so dissect the full pdu.
3147        then exit
3148     */
3149     if(pinfo->fd->flags.visited){
3150         fd_head=fragment_get_reassembled(pinfo, frame, dcerpc_co_reassemble_table);
3151         goto end_cn_stub;
3152     }
3153
3154     /* if we are not doing reassembly and it was neither a complete PDU
3155        nor the first fragment then there is nothing more we can do
3156        so we just have to exit
3157     */
3158     if( !dcerpc_reassemble )
3159         goto end_cn_stub;
3160
3161     /* if we didnt get 'frame' we dont know where the PDU started and thus
3162        it is pointless to continue
3163     */
3164     if(!frame)
3165         goto end_cn_stub;
3166
3167     /* from now on we must attempt to reassemble the PDU
3168     */
3169
3170     /* if we get here we know it is the first time we see the packet
3171        and we also know it is only a fragment and not a full PDU,
3172        thus we must reassemble it.
3173     */
3174
3175     /* Do we have any non-encrypted data to reassemble? */
3176     if (decrypted_tvb == NULL) {
3177       /* No.  We can't even try to reassemble.  */
3178       goto end_cn_stub;
3179     }
3180
3181     /* defragmentation is a bit tricky, as there's no offset of the fragment
3182      * in the protocol data.
3183      *
3184          * just use fragment_add_seq_next() and hope that TCP/SMB segments coming
3185          * in with the correct sequence.
3186     */
3187     fd_head = fragment_add_seq_next(decrypted_tvb, 0, pinfo, frame,
3188                 dcerpc_co_fragment_table, dcerpc_co_reassemble_table,
3189                 tvb_length(decrypted_tvb),
3190                 hdr->flags&PFC_LAST_FRAG ? FALSE : TRUE /* more_frags */);
3191
3192 end_cn_stub:
3193
3194     /* if reassembly is complete and this is the last fragment
3195          * (multiple fragments in one PDU are possible!)
3196          * dissect the full PDU
3197      */
3198     if(fd_head && (fd_head->flags&FD_DEFRAGMENTED) ){
3199
3200         if(pinfo->fd->num==fd_head->reassembled_in && (hdr->flags&PFC_LAST_FRAG) ){
3201             tvbuff_t *next_tvb;
3202         proto_item *frag_tree_item;
3203
3204             next_tvb = tvb_new_real_data(fd_head->data, fd_head->len, fd_head->len);
3205             if(decrypted_tvb){
3206                 tvb_set_child_real_data_tvbuff(decrypted_tvb, next_tvb);
3207             } else {
3208                 tvb_set_child_real_data_tvbuff(payload_tvb, next_tvb);
3209             }
3210             add_new_data_source(pinfo, next_tvb, "Reassembled DCE/RPC");
3211             show_fragment_tree(fd_head, &dcerpc_frag_items,
3212                         tree, pinfo, next_tvb, &frag_tree_item);
3213                 /* the toplevel fragment subtree is now behind all desegmented data,
3214                  * move it right behind the DCE/RPC tree */
3215                 dcerpc_tree_item = proto_tree_get_parent(dcerpc_tree);
3216                 if(frag_tree_item && dcerpc_tree_item) {
3217                         proto_tree_move_item(tree, dcerpc_tree_item, frag_tree_item);
3218                 }
3219
3220             pinfo->fragmented = FALSE;
3221
3222                 expert_add_info_format(pinfo, frag_tree_item, PI_REASSEMBLE, PI_CHAT,
3223                         "%s fragment, %u bytes reassembled here in #%u",
3224                         fragment_type(hdr->flags), fd_head->len, fd_head->reassembled_in);
3225
3226             dcerpc_try_handoff (pinfo, tree, dcerpc_tree, next_tvb,
3227                 next_tvb, hdr->drep, di, auth_info);
3228
3229         } else {
3230             if(decrypted_tvb){
3231                 pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_reassembled_in,
3232                                 decrypted_tvb, 0, 0, fd_head->reassembled_in);
3233             } else {
3234                 pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_reassembled_in,
3235                                 payload_tvb, 0, 0, fd_head->reassembled_in);
3236             }
3237         PROTO_ITEM_SET_GENERATED(pi);
3238         parent_pi = proto_tree_get_parent(dcerpc_tree);
3239         if(parent_pi != NULL) {
3240             proto_item_append_text(parent_pi, ", [Reas: #%u]", fd_head->reassembled_in);
3241         }
3242             if (check_col(pinfo->cinfo, COL_INFO)) {
3243                 col_append_fstr(pinfo->cinfo, COL_INFO,
3244                         " [DCE/RPC %s fragment, reas: #%u]", fragment_type(hdr->flags), fd_head->reassembled_in);
3245             }
3246                 expert_add_info_format(pinfo, NULL, PI_REASSEMBLE, PI_CHAT,
3247                         "%s fragment, reassembled in #%u", fragment_type(hdr->flags), fd_head->reassembled_in);
3248         }
3249     } else {
3250         /* Reassembly not complete - some fragments
3251            are missing.  Just show the stub data. */
3252         if (check_col(pinfo->cinfo, COL_INFO)) {
3253             col_append_fstr(pinfo->cinfo, COL_INFO,
3254                         " [DCE/RPC %s fragment]", fragment_type(hdr->flags));
3255         }
3256         expert_add_info_format(pinfo, NULL, PI_REASSEMBLE, PI_CHAT,
3257                 "%s fragment", fragment_type(hdr->flags));
3258
3259         if(decrypted_tvb){
3260                 show_stub_data (decrypted_tvb, 0, tree, auth_info, FALSE);
3261         } else {
3262                 show_stub_data (payload_tvb, 0, tree, auth_info, TRUE);
3263         }
3264     }
3265
3266     pinfo->fragmented = save_fragmented;
3267 }
3268
3269 /**
3270  *  Registers a conversation/UUID binding association, so that
3271  *  we can invoke the proper sub-dissector for a given DCERPC
3272  *  conversation.
3273  *
3274  *  @param binding all values needed to create and bind a new conversation
3275  *
3276  *  @return Pointer to newly-added UUID/conversation binding.
3277  */
3278 struct _dcerpc_bind_value *
3279 dcerpc_add_conv_to_bind_table(decode_dcerpc_bind_values_t *binding)
3280 {
3281     dcerpc_bind_value *bind_value;
3282     dcerpc_bind_key *key;
3283     conversation_t *conv;
3284
3285     conv = find_conversation (
3286         0,
3287         &binding->addr_a,
3288         &binding->addr_b,
3289         binding->ptype,
3290         binding->port_a,
3291         binding->port_b,
3292         0);
3293
3294     if (!conv) {
3295         conv = conversation_new (
3296             0,
3297             &binding->addr_a,
3298             &binding->addr_b,
3299             binding->ptype,
3300             binding->port_a,
3301             binding->port_b,
3302             0);
3303     }
3304
3305     bind_value = se_alloc (sizeof (dcerpc_bind_value));
3306     bind_value->uuid = binding->uuid;
3307     bind_value->ver = binding->ver;
3308
3309     key = se_alloc(sizeof (dcerpc_bind_key));
3310     key->conv = conv;
3311     key->ctx_id = binding->ctx_id;
3312     key->smb_fid = binding->smb_fid;
3313
3314     /* add this entry to the bind table, first removing any
3315        previous ones that are identical
3316      */
3317     if(g_hash_table_lookup(dcerpc_binds, key)){
3318             g_hash_table_remove(dcerpc_binds, key);
3319     }
3320     g_hash_table_insert(dcerpc_binds, key, bind_value);
3321
3322     return bind_value;
3323
3324 }
3325
3326 static void
3327 dissect_dcerpc_cn_rqst (tvbuff_t *tvb, gint offset, packet_info *pinfo,
3328                         proto_tree *dcerpc_tree, proto_tree *tree,
3329                         e_dce_cn_common_hdr_t *hdr)
3330 {
3331     conversation_t *conv;
3332     guint16 ctx_id;
3333     guint16 opnum;
3334     e_uuid_t obj_id = DCERPC_UUID_NULL;
3335     dcerpc_auth_info auth_info;
3336     guint32 alloc_hint;
3337     char uuid_str[DCERPC_UUID_STR_LEN];
3338     int uuid_str_len;
3339     proto_item *pi;
3340     proto_item *parent_pi;
3341
3342     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3343                                     hf_dcerpc_cn_alloc_hint, &alloc_hint);
3344
3345     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3346                                     hf_dcerpc_cn_ctx_id, &ctx_id);
3347     parent_pi = proto_tree_get_parent(dcerpc_tree);
3348     if(parent_pi != NULL) {
3349         proto_item_append_text(parent_pi, " Ctx: %u", ctx_id);
3350     }
3351
3352     if (check_col (pinfo->cinfo, COL_DCE_CTX)) {
3353                 if(pinfo->dcectxid == 0) {
3354                         col_append_fstr (pinfo->cinfo, COL_DCE_CTX, "%u", ctx_id);
3355                 } else {
3356                         /* this is not the first DCE-RPC request/response in this (TCP?-)PDU,
3357                          * prepend a delimiter */
3358                         col_append_fstr (pinfo->cinfo, COL_DCE_CTX, "#%u", ctx_id);
3359                 }
3360     } 
3361
3362     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3363                                     hf_dcerpc_opnum, &opnum);
3364
3365     /* save context ID for use with dcerpc_add_conv_to_bind_table() */
3366     pinfo->dcectxid = ctx_id;
3367
3368     if (check_col (pinfo->cinfo, COL_INFO)) {
3369         col_append_fstr (pinfo->cinfo, COL_INFO, " opnum: %u ctx_id: %u",
3370                          opnum, ctx_id);
3371     }
3372
3373     if (hdr->flags & PFC_OBJECT_UUID) {
3374         dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &obj_id);
3375         if (dcerpc_tree) {
3376             uuid_str_len = g_snprintf(uuid_str, DCERPC_UUID_STR_LEN,
3377                                     "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
3378                                     obj_id.Data1, obj_id.Data2, obj_id.Data3,
3379                                     obj_id.Data4[0],
3380                                     obj_id.Data4[1],
3381                                     obj_id.Data4[2],
3382                                     obj_id.Data4[3],
3383                                     obj_id.Data4[4],
3384                                     obj_id.Data4[5],
3385                                     obj_id.Data4[6],
3386                                     obj_id.Data4[7]);
3387             if (uuid_str_len == -1 || uuid_str_len >= DCERPC_UUID_STR_LEN)
3388                   memset(uuid_str, 0, DCERPC_UUID_STR_LEN);
3389             proto_tree_add_guid_format (dcerpc_tree, hf_dcerpc_obj_id, tvb,
3390                                           offset, 16, (e_guid_t *) &obj_id, "Object UUID: %s", uuid_str);
3391         }
3392         offset += 16;
3393     }
3394
3395     /*
3396      * XXX - what if this was set when the connection was set up,
3397      * and we just have a security context?
3398      */
3399     dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, hdr, FALSE, &auth_info);
3400
3401     conv = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
3402                               pinfo->srcport, pinfo->destport, 0);
3403     if (!conv)
3404         show_stub_data (tvb, offset, dcerpc_tree, &auth_info, TRUE);
3405     else {
3406         dcerpc_matched_key matched_key, *new_matched_key;
3407         dcerpc_call_value *value;
3408
3409         /* !!! we can NOT check flags.visited here since this will interact
3410            badly with when SMB handles (i.e. calls the subdissector)
3411            and desegmented pdu's .
3412            Instead we check if this pdu is already in the matched table or not
3413         */
3414         matched_key.frame = pinfo->fd->num;
3415         matched_key.call_id = hdr->call_id;
3416         value = g_hash_table_lookup(dcerpc_matched, &matched_key);
3417         if(!value){
3418                 dcerpc_bind_key bind_key;
3419                 dcerpc_bind_value *bind_value;
3420
3421                 bind_key.conv=conv;
3422                 bind_key.ctx_id=ctx_id;
3423                 bind_key.smb_fid=dcerpc_get_transport_salt(pinfo);
3424
3425                 if((bind_value=g_hash_table_lookup(dcerpc_binds, &bind_key)) ){
3426                         if(!(hdr->flags&PFC_FIRST_FRAG)){
3427                                 dcerpc_cn_call_key call_key;
3428                                 dcerpc_call_value *call_value;
3429
3430                                 call_key.conv=conv;
3431                                 call_key.call_id=hdr->call_id;
3432                                 call_key.smb_fid=dcerpc_get_transport_salt(pinfo);
3433                                 if((call_value=g_hash_table_lookup(dcerpc_cn_calls, &call_key))){
3434                                         new_matched_key = se_alloc(sizeof (dcerpc_matched_key));
3435                                         *new_matched_key = matched_key;
3436                                         g_hash_table_insert (dcerpc_matched, new_matched_key, call_value);
3437                                         value = call_value;
3438                                 }
3439                         } else {
3440                                 dcerpc_cn_call_key *call_key;
3441                                 dcerpc_call_value *call_value;
3442
3443                                 /* We found the binding and it is the first fragment
3444                                    (or a complete PDU) of a dcerpc pdu so just add
3445                                    the call to both the call table and the
3446                                    matched table
3447                                 */
3448                                 call_key=se_alloc (sizeof (dcerpc_cn_call_key));
3449                                 call_key->conv=conv;
3450                                 call_key->call_id=hdr->call_id;
3451                                 call_key->smb_fid=dcerpc_get_transport_salt(pinfo);
3452
3453                                 /* if there is already a matching call in the table
3454                                    remove it so it is replaced with the new one */
3455                                 if(g_hash_table_lookup(dcerpc_cn_calls, call_key)){
3456                                         g_hash_table_remove(dcerpc_cn_calls, call_key);
3457                                 }
3458
3459                                 call_value=se_alloc (sizeof (dcerpc_call_value));
3460                                 call_value->uuid = bind_value->uuid;
3461                                 call_value->ver = bind_value->ver;
3462                 call_value->object_uuid = obj_id;
3463                                 call_value->opnum = opnum;
3464                                 call_value->req_frame=pinfo->fd->num;
3465                                 call_value->req_time=pinfo->fd->abs_ts;
3466                                 call_value->rep_frame=0;
3467                                 call_value->max_ptr=0;
3468                                 call_value->private_data = NULL;
3469                                 g_hash_table_insert (dcerpc_cn_calls, call_key, call_value);
3470
3471                                 new_matched_key = se_alloc(sizeof (dcerpc_matched_key));
3472                                 *new_matched_key = matched_key;
3473                                 g_hash_table_insert (dcerpc_matched, new_matched_key, call_value);
3474                                 value = call_value;
3475                         }
3476                 }
3477         }
3478
3479         if (value) {
3480             dcerpc_info *di;
3481
3482             di=get_next_di();
3483             /* handoff this call */
3484             di->conv = conv;
3485             di->call_id = hdr->call_id;
3486             di->smb_fid = dcerpc_get_transport_salt(pinfo);
3487             di->ptype = PDU_REQ;
3488             di->call_data = value;
3489                 di->hf_index = -1;
3490
3491             if(value->rep_frame!=0){
3492                 pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_response_in,
3493                                     tvb, 0, 0, value->rep_frame);
3494         PROTO_ITEM_SET_GENERATED(pi);
3495         if(parent_pi != NULL) {
3496             proto_item_append_text(parent_pi, ", [Resp: #%u]", value->rep_frame);
3497         }
3498             }
3499
3500             dissect_dcerpc_cn_stub (tvb, offset, pinfo, dcerpc_tree, tree,
3501                                     hdr, di, &auth_info, alloc_hint,
3502                                     value->req_frame);
3503         } else {
3504         /* no bind information, simply show stub data */
3505         pi = proto_tree_add_text(dcerpc_tree, tvb, offset, 0, "No bind info for this interface Context ID - capture start too late?");
3506         PROTO_ITEM_SET_GENERATED(pi);
3507             expert_add_info_format(pinfo, pi, PI_UNDECODED, PI_NOTE, "No bind info for interface Context ID:%u (Call ID:%u)", 
3508             ctx_id, hdr->call_id);
3509             show_stub_data (tvb, offset, dcerpc_tree, &auth_info, TRUE);
3510         }
3511     }
3512
3513     /* Dissect the verifier */
3514     dissect_dcerpc_verifier (tvb, pinfo, dcerpc_tree, hdr, &auth_info);
3515
3516 }
3517
3518 static void
3519 dissect_dcerpc_cn_resp (tvbuff_t *tvb, gint offset, packet_info *pinfo,
3520                         proto_tree *dcerpc_tree, proto_tree *tree,
3521                         e_dce_cn_common_hdr_t *hdr)
3522 {
3523     dcerpc_call_value *value = NULL;
3524     conversation_t *conv;
3525     guint16 ctx_id;
3526     dcerpc_auth_info auth_info;
3527     guint32 alloc_hint;
3528     proto_item *pi;
3529     proto_item *parent_pi;
3530     char uuid_str[DCERPC_UUID_STR_LEN];
3531     int uuid_str_len;
3532     e_uuid_t obj_id_null = DCERPC_UUID_NULL;
3533
3534     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3535                                     hf_dcerpc_cn_alloc_hint, &alloc_hint);
3536
3537     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3538                                     hf_dcerpc_cn_ctx_id, &ctx_id);
3539     parent_pi = proto_tree_get_parent(dcerpc_tree);
3540     if(parent_pi != NULL) {
3541         proto_item_append_text(parent_pi, " Ctx: %u", ctx_id);
3542     }
3543
3544     if (check_col (pinfo->cinfo, COL_DCE_CTX)) {
3545                 if(pinfo->dcectxid == 0) {
3546                         col_append_fstr (pinfo->cinfo, COL_DCE_CTX, "%u", ctx_id);
3547                 } else {
3548                         /* this is not the first DCE-RPC request/response in this (TCP?-)PDU,
3549                          * prepend a delimiter */
3550                         col_append_fstr (pinfo->cinfo, COL_DCE_CTX, "#%u", ctx_id);
3551                 }
3552     } 
3553
3554
3555     /* save context ID for use with dcerpc_add_conv_to_bind_table() */
3556     pinfo->dcectxid = ctx_id;
3557
3558     if (check_col (pinfo->cinfo, COL_INFO)) {
3559         col_append_fstr (pinfo->cinfo, COL_INFO, " ctx_id: %u", ctx_id);
3560     }
3561
3562     offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3563                                    hf_dcerpc_cn_cancel_count, NULL);
3564     /* padding */
3565     offset++;
3566
3567     /*
3568      * XXX - what if this was set when the connection was set up,
3569      * and we just have a security context?
3570      */
3571     dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, hdr, FALSE, &auth_info);
3572
3573     conv = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
3574                               pinfo->srcport, pinfo->destport, 0);
3575
3576     if (!conv) {
3577         /* no point in creating one here, really */
3578         show_stub_data (tvb, offset, dcerpc_tree, &auth_info, TRUE);
3579     } else {
3580         dcerpc_matched_key matched_key, *new_matched_key;
3581
3582         /* !!! we can NOT check flags.visited here since this will interact
3583            badly with when SMB handles (i.e. calls the subdissector)
3584            and desegmented pdu's .
3585            Instead we check if this pdu is already in the matched table or not
3586         */
3587         matched_key.frame = pinfo->fd->num;
3588         matched_key.call_id = hdr->call_id;
3589         value=g_hash_table_lookup(dcerpc_matched, &matched_key);
3590         if(!value){
3591                 dcerpc_cn_call_key call_key;
3592                 dcerpc_call_value *call_value;
3593
3594                 call_key.conv=conv;
3595                 call_key.call_id=hdr->call_id;
3596                 call_key.smb_fid=dcerpc_get_transport_salt(pinfo);
3597
3598                 if((call_value=g_hash_table_lookup(dcerpc_cn_calls, &call_key))){
3599                         /* extra sanity check,  only match them if the reply
3600                            came after the request */
3601                         if(call_value->req_frame<pinfo->fd->num){
3602                                 new_matched_key = se_alloc(sizeof (dcerpc_matched_key));
3603                                 *new_matched_key = matched_key;
3604                                 g_hash_table_insert (dcerpc_matched, new_matched_key, call_value);
3605                                 value = call_value;
3606                                 if(call_value->rep_frame==0){
3607                                         call_value->rep_frame=pinfo->fd->num;
3608                                 }
3609                         }
3610                 }
3611         }
3612
3613         if (value) {
3614             dcerpc_info *di;
3615
3616             di=get_next_di();
3617             /* handoff this call */
3618             di->conv = conv;
3619             di->call_id = hdr->call_id;
3620             di->smb_fid = dcerpc_get_transport_salt(pinfo);
3621             di->ptype = PDU_RESP;
3622             di->call_data = value;
3623
3624             proto_tree_add_uint (dcerpc_tree, hf_dcerpc_opnum, tvb, 0, 0, value->opnum);
3625
3626         /* (optional) "Object UUID" from request */
3627         if (value && dcerpc_tree && memcmp(&value->object_uuid, &obj_id_null, sizeof(obj_id_null)) != 0) {
3628                 uuid_str_len = g_snprintf(uuid_str, DCERPC_UUID_STR_LEN,
3629                                         "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
3630                                         value->object_uuid.Data1, value->object_uuid.Data2, value->object_uuid.Data3,
3631                                         value->object_uuid.Data4[0],
3632                                         value->object_uuid.Data4[1],
3633                                         value->object_uuid.Data4[2],
3634                                         value->object_uuid.Data4[3],
3635                                         value->object_uuid.Data4[4],
3636                                         value->object_uuid.Data4[5],
3637                                         value->object_uuid.Data4[6],
3638                                         value->object_uuid.Data4[7]);
3639                 if (uuid_str_len == -1 || uuid_str_len >= DCERPC_UUID_STR_LEN)
3640                       memset(uuid_str, 0, DCERPC_UUID_STR_LEN);
3641                 pi = proto_tree_add_guid_format (dcerpc_tree, hf_dcerpc_obj_id, tvb,
3642                                               offset, 0, (e_guid_t *) &value->object_uuid, "Object UUID: %s", uuid_str);
3643                 PROTO_ITEM_SET_GENERATED(pi);
3644         }
3645
3646         /* request in */
3647             if(value->req_frame!=0){
3648                 nstime_t delta_ts;
3649                 pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_request_in,
3650                                     tvb, 0, 0, value->req_frame);
3651         PROTO_ITEM_SET_GENERATED(pi);
3652         if(parent_pi != NULL) {
3653             proto_item_append_text(parent_pi, ", [Req: #%u]", value->req_frame);
3654         }
3655                 nstime_delta(&delta_ts, &pinfo->fd->abs_ts, &value->req_time);
3656                 pi = proto_tree_add_time(dcerpc_tree, hf_dcerpc_time, tvb, offset, 0, &delta_ts);
3657         PROTO_ITEM_SET_GENERATED(pi);
3658         } else {
3659                     pi = proto_tree_add_text(dcerpc_tree, 
3660                                         tvb, 0, 0, "No request to this DCE/RPC call found");
3661                     expert_add_info_format(pinfo, pi, PI_SEQUENCE, PI_NOTE,
3662                             "No request to this DCE/RPC call found");
3663             }
3664
3665             dissect_dcerpc_cn_stub (tvb, offset, pinfo, dcerpc_tree, tree,
3666                                     hdr, di, &auth_info, alloc_hint,
3667                                     value->rep_frame);
3668         } else {
3669             /* no bind information, simply show stub data */
3670             pi = proto_tree_add_text(dcerpc_tree, tvb, offset, 0, "No bind info for this interface Context ID - capture start too late?");
3671             PROTO_ITEM_SET_GENERATED(pi);
3672                 expert_add_info_format(pinfo, pi, PI_UNDECODED, PI_NOTE, "No bind info for interface Context ID:%u (Call ID:%u)", 
3673                 ctx_id, hdr->call_id);
3674             show_stub_data (tvb, offset, dcerpc_tree, &auth_info, TRUE);
3675         }
3676     }
3677
3678     /* Dissect the verifier */
3679     dissect_dcerpc_verifier (tvb, pinfo, dcerpc_tree, hdr, &auth_info);
3680 }
3681
3682 static void
3683 dissect_dcerpc_cn_fault (tvbuff_t *tvb, gint offset, packet_info *pinfo,
3684                          proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr)
3685 {
3686     dcerpc_call_value *value = NULL;
3687     conversation_t *conv;
3688     guint16 ctx_id;
3689     guint32 status;
3690     guint32 alloc_hint;
3691     dcerpc_auth_info auth_info;
3692     proto_item *pi = NULL;
3693
3694     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3695                                     hf_dcerpc_cn_alloc_hint, &alloc_hint);
3696
3697     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3698                                     hf_dcerpc_cn_ctx_id, &ctx_id);
3699
3700     if (check_col (pinfo->cinfo, COL_DCE_CTX)) {
3701                 if(pinfo->dcectxid == 0) {
3702                         col_append_fstr (pinfo->cinfo, COL_DCE_CTX, "%u", ctx_id);
3703                 } else {
3704                         /* this is not the first DCE-RPC request/response in this (TCP?-)PDU,
3705                          * prepend a delimiter */
3706                         col_append_fstr (pinfo->cinfo, COL_DCE_CTX, "#%u", ctx_id);
3707                 }
3708     } 
3709
3710     offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3711                                    hf_dcerpc_cn_cancel_count, NULL);
3712     /* padding */
3713     offset++;
3714
3715     /*offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3716                                     hf_dcerpc_cn_status, &status);*/
3717     status = ((hdr->drep[0] & 0x10)
3718             ? tvb_get_letohl (tvb, offset)
3719             : tvb_get_ntohl (tvb, offset));
3720
3721     if (dcerpc_tree) {
3722         pi = proto_tree_add_item (dcerpc_tree, hf_dcerpc_cn_status, tvb, offset, 4, (hdr->drep[0] & 0x10));
3723     }
3724         offset+=4;
3725
3726         expert_add_info_format(pinfo, pi, PI_RESPONSE_CODE, PI_NOTE, "Fault: %s",
3727                 val_to_str(status, reject_status_vals, "Unknown (0x%08x)"));
3728
3729     /* save context ID for use with dcerpc_add_conv_to_bind_table() */
3730     pinfo->dcectxid = ctx_id;
3731
3732     if (check_col (pinfo->cinfo, COL_INFO)) {
3733         col_append_fstr (pinfo->cinfo, COL_INFO,
3734                       " ctx_id: %u status: %s", ctx_id,
3735                       val_to_str(status, reject_status_vals,
3736                                  "Unknown (0x%08x)"));
3737     }
3738
3739     /* padding */
3740     offset += 4;
3741
3742     /*
3743      * XXX - what if this was set when the connection was set up,
3744      * and we just have a security context?
3745      */
3746     dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, hdr, FALSE, &auth_info);
3747
3748     conv = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
3749                               pinfo->srcport, pinfo->destport, 0);
3750     if (!conv) {
3751         /* no point in creating one here, really */
3752     } else {
3753         dcerpc_matched_key matched_key, *new_matched_key;
3754
3755         /* !!! we can NOT check flags.visited here since this will interact
3756            badly with when SMB handles (i.e. calls the subdissector)
3757            and desegmented pdu's .
3758            Instead we check if this pdu is already in the matched table or not
3759         */
3760         matched_key.frame = pinfo->fd->num;
3761         matched_key.call_id = hdr->call_id;
3762         value=g_hash_table_lookup(dcerpc_matched, &matched_key);
3763         if(!value){
3764                 dcerpc_cn_call_key call_key;
3765                 dcerpc_call_value *call_value;
3766
3767                 call_key.conv=conv;
3768                 call_key.call_id=hdr->call_id;
3769                 call_key.smb_fid=dcerpc_get_transport_salt(pinfo);
3770
3771                 if((call_value=g_hash_table_lookup(dcerpc_cn_calls, &call_key))){
3772                         new_matched_key = se_alloc(sizeof (dcerpc_matched_key));
3773                         *new_matched_key = matched_key;
3774                         g_hash_table_insert (dcerpc_matched, new_matched_key, call_value);
3775                         value = call_value;
3776                         if(call_value->rep_frame==0){
3777                                 call_value->rep_frame=pinfo->fd->num;
3778                         }
3779
3780                 }
3781         }
3782
3783         if (value) {
3784             int length, reported_length, stub_length;
3785             dcerpc_info *di;
3786             proto_item *parent_pi;
3787
3788             di=get_next_di();
3789             /* handoff this call */
3790             di->conv = conv;
3791             di->call_id = hdr->call_id;
3792             di->smb_fid = dcerpc_get_transport_salt(pinfo);
3793             di->ptype = PDU_FAULT;
3794             di->call_data = value;
3795
3796             proto_tree_add_uint (dcerpc_tree, hf_dcerpc_opnum, tvb, 0, 0, value->opnum);
3797             if(value->req_frame!=0){
3798                 nstime_t delta_ts;
3799                 pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_request_in,
3800                                     tvb, 0, 0, value->req_frame);
3801         PROTO_ITEM_SET_GENERATED(pi);
3802         parent_pi = proto_tree_get_parent(dcerpc_tree);
3803         if(parent_pi != NULL) {
3804             proto_item_append_text(parent_pi, ", [Req: #%u]", value->req_frame);
3805         }
3806                 nstime_delta(&delta_ts, &pinfo->fd->abs_ts, &value->req_time);
3807                 pi = proto_tree_add_time(dcerpc_tree, hf_dcerpc_time, tvb, offset, 0, &delta_ts);
3808         PROTO_ITEM_SET_GENERATED(pi);
3809         } else {
3810                     pi = proto_tree_add_text(dcerpc_tree, 
3811                                         tvb, 0, 0, "No request to this DCE/RPC call found");
3812                     expert_add_info_format(pinfo, pi, PI_SEQUENCE, PI_NOTE,
3813                             "No request to this DCE/RPC call found");
3814             }
3815
3816             length = tvb_length_remaining(tvb, offset);
3817             reported_length = tvb_reported_length_remaining(tvb, offset);
3818                 /* as we now create a tvb in dissect_dcerpc_cn() containing only the
3819                  * stub_data, the following calculation is no longer valid:
3820              * stub_length = hdr->frag_len - offset - auth_info.auth_size;
3821                  * simply use the remaining length of the tvb instead.
3822                  * XXX - or better use the reported_length?!?
3823                  */
3824             stub_length = length;
3825             if (length > stub_length)
3826               length = stub_length;
3827             if (reported_length > stub_length)
3828               reported_length = stub_length;
3829
3830             /* If we don't have reassembly enabled, or this packet contains
3831                the entire PDU, or if we don't have all the data in this
3832                fragment, just call the handoff directly if this is the
3833                first fragment or the PDU isn't fragmented. */
3834             if( (!dcerpc_reassemble) || PFC_NOT_FRAGMENTED(hdr) ||
3835                         !tvb_bytes_exist(tvb, offset, stub_length) ){
3836                 if(hdr->flags&PFC_FIRST_FRAG){
3837                     /* First fragment, possibly the only fragment */
3838                     /*
3839                      * XXX - should there be a third routine for each
3840                      * function in an RPC subdissector, to handle
3841                      * fault responses?  The DCE RPC 1.1 spec says
3842                      * three's "stub data" here, which I infer means
3843                      * that it's protocol-specific and call-specific.
3844                      *
3845                      * It should probably get passed the status code
3846                      * as well, as that might be protocol-specific.
3847                      */
3848                     if (dcerpc_tree) {
3849                         if (stub_length > 0) {
3850                             tvb_ensure_bytes_exist(tvb, offset, stub_length);
3851                             proto_tree_add_text (dcerpc_tree, tvb, offset, stub_length,
3852                                                  "Fault stub data (%d byte%s)",
3853                                                  stub_length,
3854                                                  plurality(stub_length, "", "s"));
3855                         }
3856                     }
3857                 } else {
3858                     /* PDU is fragmented and this isn't the first fragment */
3859                     if (check_col(pinfo->cinfo, COL_INFO)) {
3860                         col_append_fstr(pinfo->cinfo, COL_INFO,
3861                                         " [DCE/RPC fragment]");
3862                     }
3863                     if (dcerpc_tree) {
3864                         if (stub_length > 0) {
3865                             tvb_ensure_bytes_exist(tvb, offset, stub_length);
3866                             proto_tree_add_text (dcerpc_tree, tvb, offset, stub_length,
3867                                                  "Fragment data (%d byte%s)",
3868                                                  stub_length,
3869                                                  plurality(stub_length, "", "s"));
3870                         }
3871                     }
3872                 }
3873             } else {
3874                 /* Reassembly is enabled, the PDU is fragmented, and
3875                    we have all the data in the fragment; the first two
3876                    of those mean we should attempt reassembly, and the
3877                    third means we can attempt reassembly. */
3878                 if (dcerpc_tree) {
3879                     if (length > 0) {
3880                         tvb_ensure_bytes_exist(tvb, offset, stub_length);
3881                         proto_tree_add_text (dcerpc_tree, tvb, offset, stub_length,
3882                                              "Fragment data (%d byte%s)",
3883                                              stub_length,
3884                                              plurality(stub_length, "", "s"));
3885                     }
3886                 }
3887                 if(hdr->flags&PFC_FIRST_FRAG){  /* FIRST fragment */
3888                     if( (!pinfo->fd->flags.visited) && value->rep_frame ){
3889                         fragment_add_seq_next(tvb, offset, pinfo, value->rep_frame,
3890                              dcerpc_co_fragment_table, dcerpc_co_reassemble_table,
3891                              stub_length,
3892                              TRUE);
3893                     }
3894                     if (check_col(pinfo->cinfo, COL_INFO)) {
3895                         col_append_fstr(pinfo->cinfo, COL_INFO,
3896                                         " [DCE/RPC fragment]");
3897                     }
3898                 } else if(hdr->flags&PFC_LAST_FRAG){  /* LAST fragment */
3899                     if( value->rep_frame ){
3900                         fragment_data *fd_head;
3901
3902                         fd_head = fragment_add_seq_next(tvb, offset, pinfo,
3903                              value->rep_frame,
3904                              dcerpc_co_fragment_table, dcerpc_co_reassemble_table,
3905                              stub_length,
3906                              TRUE);
3907
3908                         if(fd_head){
3909                             /* We completed reassembly */
3910                             tvbuff_t *next_tvb;
3911                 proto_item *frag_tree_item;
3912
3913                             next_tvb = tvb_new_real_data(fd_head->data, fd_head->len, fd_head->len);
3914                             tvb_set_child_real_data_tvbuff(tvb, next_tvb);
3915                             add_new_data_source(pinfo, next_tvb, "Reassembled DCE/RPC");
3916                             show_fragment_tree(fd_head, &dcerpc_frag_items,
3917                                 dcerpc_tree, pinfo, next_tvb, &frag_tree_item);
3918
3919                             /*
3920                              * XXX - should there be a third routine for each
3921                              * function in an RPC subdissector, to handle
3922                              * fault responses?  The DCE RPC 1.1 spec says
3923                              * three's "stub data" here, which I infer means
3924                              * that it's protocol-specific and call-specific.
3925                              *
3926                              * It should probably get passed the status code
3927                              * as well, as that might be protocol-specific.
3928                              */
3929                             if (dcerpc_tree) {
3930                                 if (length > 0) {
3931                                     tvb_ensure_bytes_exist(tvb, offset, stub_length);
3932                                      proto_tree_add_text (dcerpc_tree, tvb, offset, stub_length,
3933                                                           "Fault stub data (%d byte%s)",
3934                                                           stub_length,
3935                                                           plurality(stub_length, "", "s"));
3936                                 }
3937                             }
3938                         } else {
3939                             /* Reassembly not complete - some fragments
3940                                are missing */
3941                             if (check_col(pinfo->cinfo, COL_INFO)) {
3942                                 col_append_fstr(pinfo->cinfo, COL_INFO,
3943                                                 " [DCE/RPC fragment]");
3944                             }
3945                         }
3946                     }
3947                 } else {  /* MIDDLE fragment(s) */
3948                     if( (!pinfo->fd->flags.visited) && value->rep_frame ){
3949                         fragment_add_seq_next(tvb, offset, pinfo, value->rep_frame,
3950                              dcerpc_co_fragment_table, dcerpc_co_reassemble_table,
3951                              stub_length,
3952                              TRUE);
3953                     }
3954                     if (check_col(pinfo->cinfo, COL_INFO)) {
3955                         col_append_fstr(pinfo->cinfo, COL_INFO,
3956                                         " [DCE/RPC fragment]");
3957                     }
3958                 }
3959             }
3960         }
3961     }
3962 }
3963
3964 /*
3965  * DCERPC dissector for connection oriented calls.
3966  * We use transport type to later multiplex between what kind of
3967  * pinfo->private_data structure to expect.
3968  */
3969 static gboolean
3970 dissect_dcerpc_cn (tvbuff_t *tvb, int offset, packet_info *pinfo,
3971                    proto_tree *tree, gboolean can_desegment, int *pkt_len)
3972 {
3973     static const guint8 nulls[4] = { 0 };
3974     int start_offset;
3975     int padding = 0;
3976     proto_item *ti = NULL;
3977     proto_item *tf = NULL;
3978     proto_tree *dcerpc_tree = NULL;
3979     proto_tree *cn_flags_tree = NULL;
3980     proto_tree *drep_tree = NULL;
3981     e_dce_cn_common_hdr_t hdr;
3982     dcerpc_auth_info auth_info;
3983         tvbuff_t *fragment_tvb;
3984
3985     /*
3986      * when done over nbt, dcerpc requests are padded with 4 bytes of null
3987      * data for some reason.
3988      *
3989      * XXX - if that's always the case, the right way to do this would
3990      * be to have a "dissect_dcerpc_cn_nb" routine which strips off
3991      * the 4 bytes of null padding, and make that the dissector
3992      * used for "netbios".
3993      */
3994     if (tvb_memeql (tvb, offset, nulls, 4) == 0) {
3995
3996         /*
3997          * Skip the padding.
3998          */
3999         offset += 4;
4000         padding += 4;
4001     }
4002     /*
4003      * Check if this looks like a C/O DCERPC call
4004      */
4005     if (!tvb_bytes_exist (tvb, offset, sizeof (hdr))) {
4006         return FALSE;   /* not enough information to check */
4007     }
4008     start_offset = offset;
4009     hdr.rpc_ver = tvb_get_guint8 (tvb, offset++);
4010     if (hdr.rpc_ver != 5)
4011         return FALSE;
4012     hdr.rpc_ver_minor = tvb_get_guint8 (tvb, offset++);
4013     if (hdr.rpc_ver_minor != 0 && hdr.rpc_ver_minor != 1)
4014         return FALSE;
4015     hdr.ptype = tvb_get_guint8 (tvb, offset++);
4016     if (hdr.ptype > 19)
4017         return FALSE;
4018
4019     hdr.flags = tvb_get_guint8 (tvb, offset++);
4020     tvb_memcpy (tvb, (guint8 *)hdr.drep, offset, sizeof (hdr.drep));
4021     offset += sizeof (hdr.drep);
4022
4023     hdr.frag_len = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
4024     offset += 2;
4025     hdr.auth_len = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
4026     offset += 2;
4027     hdr.call_id = dcerpc_tvb_get_ntohl (tvb, offset, hdr.drep);
4028     offset += 4;
4029
4030     if (check_col (pinfo->cinfo, COL_DCE_CALL)) {
4031                 if(pinfo->dcectxid == 0) {
4032                         col_append_fstr (pinfo->cinfo, COL_DCE_CALL, "%u", hdr.call_id);
4033                 } else {
4034                         /* this is not the first DCE-RPC request/response in this (TCP?-)PDU,
4035                          * prepend a delimiter */
4036                         col_append_fstr (pinfo->cinfo, COL_DCE_CALL, "#%u", hdr.call_id);
4037                 }
4038     }
4039
4040     if (can_desegment && pinfo->can_desegment
4041         && !tvb_bytes_exist(tvb, start_offset, hdr.frag_len)) {
4042         pinfo->desegment_offset = start_offset;
4043         pinfo->desegment_len = hdr.frag_len - tvb_length_remaining (tvb, start_offset);
4044         *pkt_len = 0;   /* desegmentation required */
4045         return TRUE;
4046     }
4047
4048     if (check_col (pinfo->cinfo, COL_PROTOCOL))
4049         col_set_str (pinfo->cinfo, COL_PROTOCOL, "DCERPC");
4050
4051     if (check_col (pinfo->cinfo, COL_INFO)) {
4052         if(pinfo->dcectxid != 0) {
4053             /* this is not the first DCE-RPC request/response in this (TCP?-)PDU,
4054              * append a delimiter and set a column fence */
4055             col_append_str (pinfo->cinfo, COL_INFO, " # ");
4056             col_set_fence(pinfo->cinfo,COL_INFO);
4057         }
4058         col_add_fstr (pinfo->cinfo, COL_INFO, "%s: call_id: %u",
4059                 pckt_vals[hdr.ptype].strptr, hdr.call_id);
4060     }
4061
4062     if(pinfo->dcectxid != 0) {
4063         /* this is not the first DCE-RPC request/response in this (TCP?-)PDU */
4064                 expert_add_info_format(pinfo, NULL, PI_SEQUENCE, PI_CHAT, "Multiple DCE/RPC fragments/PDU's in one packet");
4065         }
4066
4067     offset = start_offset;
4068     tvb_ensure_bytes_exist(tvb, offset, 16);
4069     if (tree) {
4070         ti = proto_tree_add_item (tree, proto_dcerpc, tvb, offset, hdr.frag_len, FALSE);
4071         dcerpc_tree = proto_item_add_subtree (ti, ett_dcerpc);
4072     }
4073
4074     proto_tree_add_uint (dcerpc_tree, hf_dcerpc_ver, tvb, offset, 1, hdr.rpc_ver);
4075     offset++;
4076
4077     proto_tree_add_uint (dcerpc_tree, hf_dcerpc_ver_minor, tvb, offset, 1, hdr.rpc_ver_minor);
4078     offset++;
4079
4080     tf = proto_tree_add_uint (dcerpc_tree, hf_dcerpc_packet_type, tvb, offset, 1, hdr.ptype);
4081     offset++;
4082
4083     /* XXX - too much "output noise", removed for now
4084     if(hdr.ptype == PDU_BIND || hdr.ptype == PDU_ALTER ||
4085         hdr.ptype == PDU_BIND_ACK || hdr.ptype == PDU_ALTER_ACK)
4086         expert_add_info_format(pinfo, tf, PI_SEQUENCE, PI_CHAT, "Context change: %s",
4087             val_to_str(hdr.ptype, pckt_vals, "(0x%x)"));*/
4088     if(hdr.ptype == PDU_BIND_NAK)
4089         expert_add_info_format(pinfo, tf, PI_SEQUENCE, PI_WARN, "Bind not acknowledged");
4090
4091     if (tree) {
4092         proto_item_append_text(ti, " %s, Fragment:", val_to_str(hdr.ptype, pckt_vals, "Unknown (0x%02x)"));
4093
4094         tf = proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_flags, tvb, offset, 1, hdr.flags);
4095         cn_flags_tree = proto_item_add_subtree (tf, ett_dcerpc_cn_flags);
4096     }
4097     proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_object, tvb, offset, 1, hdr.flags);
4098     proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_maybe, tvb, offset, 1, hdr.flags);
4099     proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_dne, tvb, offset, 1, hdr.flags);
4100     proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_mpx, tvb, offset, 1, hdr.flags);
4101     proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_reserved, tvb, offset, 1, hdr.flags);
4102     proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_cancel_pending, tvb, offset, 1, hdr.flags);
4103     proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_last_frag, tvb, offset, 1, hdr.flags);
4104     proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_first_frag, tvb, offset, 1, hdr.flags);
4105     if( (hdr.flags & PFC_FIRST_FRAG) && (hdr.flags & PFC_LAST_FRAG) ) {
4106         proto_item_append_text(ti, " Single");
4107     } else {
4108         if(hdr.flags & PFC_FIRST_FRAG) {
4109              proto_item_append_text(ti, " 1st");
4110         }
4111         if(hdr.flags & PFC_LAST_FRAG) {
4112             proto_item_append_text(ti, " Last");
4113         }
4114         if( !(hdr.flags & PFC_FIRST_FRAG) && !(hdr.flags & PFC_LAST_FRAG) ) {
4115             proto_item_append_text(ti, " Mid");
4116         }
4117     }
4118     offset++;
4119
4120     if(dcerpc_tree){
4121         tf = proto_tree_add_bytes (dcerpc_tree, hf_dcerpc_drep, tvb, offset, 4, hdr.drep);
4122         drep_tree = proto_item_add_subtree (tf, ett_dcerpc_drep);
4123     }
4124     proto_tree_add_uint(drep_tree, hf_dcerpc_drep_byteorder, tvb, offset, 1, hdr.drep[0] >> 4);
4125     proto_tree_add_uint(drep_tree, hf_dcerpc_drep_character, tvb, offset, 1, hdr.drep[0] & 0x0f);
4126     proto_tree_add_uint(drep_tree, hf_dcerpc_drep_fp, tvb, offset+1, 1, hdr.drep[1]);
4127     offset += sizeof (hdr.drep);
4128
4129     proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_frag_len, tvb, offset, 2, hdr.frag_len);
4130     offset += 2;
4131
4132     proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_auth_len, tvb, offset, 2, hdr.auth_len);
4133     offset += 2;
4134
4135     proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_call_id, tvb, offset, 4, hdr.call_id);
4136     offset += 4;
4137
4138     if(ti){
4139         proto_item_append_text(ti, ", FragLen: %u, Call: %u", hdr.frag_len, hdr.call_id);
4140     }
4141
4142     /*
4143      * None of the stuff done above should throw an exception, because
4144      * we would have rejected this as "not DCE RPC" if we didn't have all
4145      * of it.  (XXX - perhaps we should request reassembly if we have
4146      * enough of the header to consider it DCE RPC but not enough to
4147      * get the fragment length; in that case the stuff still wouldn't
4148      * throw an exception.)
4149      *
4150      * The rest of the stuff might, so return the PDU length to our caller.
4151      * XXX - should we construct a tvbuff containing only the PDU and
4152      * use that?  Or should we have separate "is this a DCE RPC PDU",
4153      * "how long is it", and "dissect it" routines - which might let us
4154      * do most of the work in "tcp_dissect_pdus()"?
4155      */
4156     if (pkt_len != NULL)
4157         *pkt_len = hdr.frag_len + padding;
4158
4159     /* The remaining bytes in the current tvb might contain multiple
4160      * DCE/RPC fragments, so create a new tvb subset for this fragment.
4161      * Only limit the end of the fragment, but not the offset start,
4162      * as the authentication function dissect_dcerpc_cn_auth() will fail
4163      * (and other functions might fail as well) computing the right start
4164      * offset otherwise.
4165      */
4166     fragment_tvb = tvb_new_subset(tvb, 0,
4167         MIN((hdr.frag_len + (guint) start_offset), tvb_length(tvb)) /* length */,
4168         hdr.frag_len + start_offset /* reported_length */);
4169
4170     /*
4171      * Packet type specific stuff is next.
4172      */
4173     switch (hdr.ptype) {
4174     case PDU_BIND:
4175     case PDU_ALTER:
4176         dissect_dcerpc_cn_bind (fragment_tvb, offset, pinfo, dcerpc_tree, &hdr);
4177         break;
4178
4179     case PDU_BIND_ACK:
4180     case PDU_ALTER_ACK:
4181         dissect_dcerpc_cn_bind_ack (fragment_tvb, offset, pinfo, dcerpc_tree, &hdr);
4182         break;
4183
4184     case PDU_AUTH3:
4185         /*
4186          * Nothing after the common header other than credentials.
4187          */
4188         dissect_dcerpc_cn_auth (fragment_tvb, offset, pinfo, dcerpc_tree, &hdr, TRUE,
4189                                 &auth_info);
4190         break;
4191
4192     case PDU_REQ:
4193         dissect_dcerpc_cn_rqst (fragment_tvb, offset, pinfo, dcerpc_tree, tree, &hdr);
4194         break;
4195
4196     case PDU_RESP:
4197         dissect_dcerpc_cn_resp (fragment_tvb, offset, pinfo, dcerpc_tree, tree, &hdr);
4198         break;
4199
4200     case PDU_FAULT:
4201         dissect_dcerpc_cn_fault (fragment_tvb, offset, pinfo, dcerpc_tree, &hdr);
4202         break;
4203
4204     case PDU_BIND_NAK:
4205         dissect_dcerpc_cn_bind_nak (fragment_tvb, offset, pinfo, dcerpc_tree, &hdr);
4206         break;
4207
4208     case PDU_CO_CANCEL:
4209     case PDU_ORPHANED:
4210         /*
4211          * Nothing after the common header other than an authentication
4212          * verifier.
4213          */
4214         dissect_dcerpc_cn_auth (fragment_tvb, offset, pinfo, dcerpc_tree, &hdr, FALSE,
4215                                 &auth_info);
4216         break;
4217
4218     case PDU_SHUTDOWN:
4219         /*
4220          * Nothing after the common header, not even an authentication
4221          * verifier.
4222          */
4223         break;
4224
4225     default:
4226         /* might as well dissect the auth info */
4227         dissect_dcerpc_cn_auth (fragment_tvb, offset, pinfo, dcerpc_tree, &hdr, FALSE,
4228                                 &auth_info);
4229         break;
4230     }
4231     return TRUE;
4232 }
4233
4234 /*
4235  * DCERPC dissector for connection oriented calls over packet-oriented
4236  * transports
4237  */
4238 static gboolean
4239 dissect_dcerpc_cn_pk (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4240 {
4241     /*
4242      * Only one PDU per transport packet, and only one transport
4243      * packet per PDU.
4244      */
4245     pinfo->dcetransporttype=DCE_TRANSPORT_UNKNOWN;
4246     if (!dissect_dcerpc_cn (tvb, 0, pinfo, tree, FALSE, NULL)) {
4247         /*
4248          * It wasn't a DCERPC PDU.
4249          */
4250         return FALSE;
4251     } else {
4252         /*
4253          * It was.
4254          */
4255         return TRUE;
4256     }
4257 }
4258
4259 /*
4260  * DCERPC dissector for connection oriented calls over byte-stream
4261  * transports.
4262  * we need to distinguish here between SMB and non-TCP (more in the future?)
4263  * to be able to know what kind of private_data structure to expect.
4264  */
4265 static gboolean
4266 dissect_dcerpc_cn_bs_body (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4267 {
4268     volatile int offset = 0;
4269     int pdu_len;
4270     volatile gboolean dcerpc_pdus = 0;
4271     volatile gboolean ret = FALSE;
4272
4273     /*
4274      * There may be multiple PDUs per transport packet; keep
4275      * processing them.
4276      */
4277     while (tvb_reported_length_remaining(tvb, offset) != 0) {
4278         /*
4279          * Catch ReportedBoundsError, so that even if the stub data is bad,
4280          * we don't abort the full DCE RPC dissection - there might be more
4281          * than one DCE RPC PDU in the data being dissected.
4282          *
4283          * If we get BoundsError, it means the frame was cut short by a
4284          * snapshot length, so there's nothing more to dissect; just
4285          * re-throw that exception.
4286          */
4287         TRY {
4288             pdu_len = 0;
4289             if(dissect_dcerpc_cn (tvb, offset, pinfo, tree,
4290                 dcerpc_cn_desegment, &pdu_len)) {
4291                 dcerpc_pdus++;
4292             }
4293         } CATCH(BoundsError) {
4294             RETHROW;
4295         } CATCH(ReportedBoundsError) {
4296             show_reported_bounds_error(tvb, pinfo, tree);
4297             /*
4298              * Presumably it looked enough like a DCE RPC PDU that we
4299              * dissected enough of it to throw an exception.
4300              */
4301             dcerpc_pdus++;
4302         } ENDTRY;
4303
4304         if (!dcerpc_pdus) {
4305             /*
4306              * Not a DCERPC PDU.
4307              */
4308             break;
4309         }
4310
4311         /*
4312          * Well, we've seen at least one DCERPC PDU.
4313          */
4314         ret = TRUE;
4315
4316         /* if we had more than one Req/Resp in this PDU change the protocol column */
4317         /* this will formerly contain the last interface name, which may not be the same for all Req/Resp */
4318         if (dcerpc_pdus >= 2 && check_col (pinfo->cinfo, COL_PROTOCOL))
4319             col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "%u*DCERPC", dcerpc_pdus);
4320
4321         if (pdu_len == 0) {
4322             /*
4323              * Desegmentation required - bail now, but give the user a hint that desegmentation might be done later.
4324              */
4325             proto_tree_add_uint_format(tree, hf_dcerpc_cn_deseg_req, tvb, offset,
4326                 0,
4327                 tvb_reported_length_remaining(tvb, offset),
4328                 "[DCE RPC: %u byte%s left, desegmentation might follow]",
4329                 tvb_reported_length_remaining(tvb, offset),
4330                 plurality(tvb_reported_length_remaining(tvb, offset), "", "s"));
4331             break;
4332         }
4333
4334         /*
4335          * Step to the next PDU.
4336          */
4337         offset += pdu_len;
4338     }
4339     return ret;
4340 }
4341
4342 static gboolean
4343 dissect_dcerpc_cn_bs (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4344 {
4345         pinfo->dcetransporttype=DCE_TRANSPORT_UNKNOWN;
4346         return dissect_dcerpc_cn_bs_body(tvb, pinfo, tree);
4347 }
4348
4349 static gboolean
4350 dissect_dcerpc_cn_smbpipe (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4351 {
4352         pinfo->dcetransporttype=DCE_CN_TRANSPORT_SMBPIPE;
4353         return dissect_dcerpc_cn_bs_body(tvb, pinfo, tree);
4354 }
4355
4356 static gboolean
4357 dissect_dcerpc_cn_smb2 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4358 {
4359         pinfo->dcetransporttype=DCE_TRANSPORT_UNKNOWN;
4360         return dissect_dcerpc_cn_bs_body(tvb, pinfo, tree);
4361 }
4362
4363
4364
4365 static void
4366 dissect_dcerpc_dg_auth (tvbuff_t *tvb, int offset, proto_tree *dcerpc_tree,
4367                         e_dce_dg_common_hdr_t *hdr, int *auth_level_p)
4368 {
4369     proto_item *ti = NULL;
4370     proto_tree *auth_tree = NULL;
4371     guint8 protection_level;
4372
4373     /*
4374      * Initially set "*auth_level_p" to -1 to indicate that we haven't
4375      * yet seen any authentication level information.
4376      */
4377     if (auth_level_p != NULL)
4378         *auth_level_p = -1;
4379
4380     /*
4381      * The authentication information is at the *end* of the PDU; in
4382      * request and response PDUs, the request and response stub data
4383      * come before it.
4384      *
4385      * If the full packet is here, and there's data past the end of the
4386      * packet body, then dissect the auth info.
4387      */
4388     offset += hdr->frag_len;
4389     if (tvb_length_remaining(tvb, offset) > 0) {
4390         switch (hdr->auth_proto) {
4391
4392         case DCE_C_RPC_AUTHN_PROTOCOL_KRB5:
4393             ti = proto_tree_add_text (dcerpc_tree, tvb, offset, -1, "Kerberos authentication verifier");
4394             auth_tree = proto_item_add_subtree (ti, ett_dcerpc_krb5_auth_verf);
4395             protection_level = tvb_get_guint8 (tvb, offset);
4396             if (auth_level_p != NULL)
4397                 *auth_level_p = protection_level;
4398             proto_tree_add_uint (auth_tree, hf_dcerpc_krb5_av_prot_level, tvb, offset, 1, protection_level);
4399             offset++;
4400             proto_tree_add_item (auth_tree, hf_dcerpc_krb5_av_key_vers_num, tvb, offset, 1, FALSE);
4401             offset++;
4402             if (protection_level == DCE_C_AUTHN_LEVEL_PKT_PRIVACY)
4403                 offset += 6;    /* 6 bytes of padding */
4404             else
4405                 offset += 2;    /* 6 bytes of padding */
4406             proto_tree_add_item (auth_tree, hf_dcerpc_krb5_av_key_auth_verifier, tvb, offset, 16, FALSE);
4407             offset += 16;
4408             break;
4409
4410         default:
4411             proto_tree_add_text (dcerpc_tree, tvb, offset, -1, "Authentication verifier");
4412             break;
4413         }
4414     }
4415 }
4416
4417 static void
4418 dissect_dcerpc_dg_cancel_ack (tvbuff_t *tvb, int offset, packet_info *pinfo,
4419                               proto_tree *dcerpc_tree,
4420                               e_dce_dg_common_hdr_t *hdr)
4421 {
4422     guint32 version;
4423
4424     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
4425                                     hdr->drep, hf_dcerpc_dg_cancel_vers,
4426                                     &version);
4427
4428     switch (version) {
4429
4430     case 0:
4431         /* The only version we know about */
4432         offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
4433                                         hdr->drep, hf_dcerpc_dg_cancel_id,
4434                                         NULL);
4435         offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree,
4436                                        hdr->drep, hf_dcerpc_dg_server_accepting_cancels,
4437                                        NULL);
4438         break;
4439     }
4440 }
4441
4442 static void
4443 dissect_dcerpc_dg_cancel (tvbuff_t *tvb, int offset, packet_info *pinfo,
4444                           proto_tree *dcerpc_tree,
4445                           e_dce_dg_common_hdr_t *hdr)
4446 {
4447     guint32 version;
4448
4449     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
4450                                     hdr->drep, hf_dcerpc_dg_cancel_vers,
4451                                     &version);
4452
4453     switch (version) {
4454
4455     case 0:
4456         /* The only version we know about */
4457         offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
4458                                         hdr->drep, hf_dcerpc_dg_cancel_id,
4459                                         NULL);
4460         /* XXX - are NDR booleans 32 bits? */
4461
4462         /* XXX - the RPC reference in chapter: "the cancel PDU" doesn't mention
4463            the accepting_cancels field (it's only in the cancel_ack PDU)! */
4464         /*offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
4465                                         hdr->drep, hf_dcerpc_dg_server_accepting_cancels,
4466                                         NULL);*/
4467         break;
4468     }
4469 }
4470
4471 static void
4472 dissect_dcerpc_dg_fack (tvbuff_t *tvb, int offset, packet_info *pinfo,
4473                         proto_tree *dcerpc_tree,
4474                         e_dce_dg_common_hdr_t *hdr)
4475 {
4476     guint8 version;
4477     guint16 serial_num;
4478     guint16 selack_len;
4479     guint i;
4480
4481     offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree,
4482                                   hdr->drep, hf_dcerpc_dg_fack_vers,
4483                                   &version);
4484     /* padding */
4485     offset++;
4486
4487     switch (version) {
4488
4489     case 0:     /* The only version documented in the DCE RPC 1.1 spec */
4490     case 1:     /* This appears to be the same */
4491         offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
4492                                         hdr->drep, hf_dcerpc_dg_fack_window_size,
4493                                         NULL);
4494         offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
4495                                         hdr->drep, hf_dcerpc_dg_fack_max_tsdu,
4496                                         NULL);
4497         offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
4498                                         hdr->drep, hf_dcerpc_dg_fack_max_frag_size,
4499                                         NULL);
4500         offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
4501                                         hdr->drep, hf_dcerpc_dg_fack_serial_num,
4502                                         &serial_num);
4503         if (check_col (pinfo->cinfo, COL_INFO)) {
4504             col_append_fstr (pinfo->cinfo, COL_INFO, " serial: %u",
4505                              serial_num);
4506         }
4507         offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
4508                                         hdr->drep, hf_dcerpc_dg_fack_selack_len,
4509                                         &selack_len);
4510         for (i = 0; i < selack_len; i++) {
4511             offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
4512                                             hdr->drep, hf_dcerpc_dg_fack_selack,
4513                                             NULL);
4514         }
4515
4516         break;
4517     }
4518 }
4519
4520 static void
4521 dissect_dcerpc_dg_reject_fault (tvbuff_t *tvb, int offset, packet_info *pinfo,
4522                         proto_tree *dcerpc_tree,
4523                         e_dce_dg_common_hdr_t *hdr)
4524 {
4525     guint32 status;
4526
4527     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
4528                                     hdr->drep, hf_dcerpc_dg_status,
4529                                     &status);
4530
4531     if (check_col (pinfo->cinfo, COL_INFO)) {
4532         col_append_fstr (pinfo->cinfo, COL_INFO,
4533                       ": status: %s",
4534                       val_to_str(status, reject_status_vals, "Unknown (0x%08x)"));
4535     }
4536 }
4537
4538 static void
4539 dissect_dcerpc_dg_stub (tvbuff_t *tvb, int offset, packet_info *pinfo,
4540                         proto_tree *dcerpc_tree, proto_tree *tree,
4541                         e_dce_dg_common_hdr_t *hdr, dcerpc_info *di)
4542 {
4543     int length, reported_length, stub_length;
4544     gboolean save_fragmented;
4545     fragment_data *fd_head;
4546     tvbuff_t *next_tvb;
4547     proto_item *pi;
4548     proto_item *parent_pi;
4549
4550     if (check_col (pinfo->cinfo, COL_INFO))
4551         col_append_fstr (pinfo->cinfo, COL_INFO, " opnum: %u len: %u",
4552             di->call_data->opnum, hdr->frag_len );
4553
4554     length = tvb_length_remaining (tvb, offset);
4555     reported_length = tvb_reported_length_remaining (tvb, offset);
4556     stub_length = hdr->frag_len;
4557     if (length > stub_length)
4558         length = stub_length;
4559     if (reported_length > stub_length)
4560         reported_length = stub_length;
4561
4562     save_fragmented = pinfo->fragmented;
4563
4564     /* If we don't have reassembly enabled, or this packet contains
4565        the entire PDU, or if this is a short frame (or a frame
4566        not reassembled at a lower layer) that doesn't include all
4567        the data in the fragment, just call the handoff directly if
4568        this is the first fragment or the PDU isn't fragmented. */
4569     if( (!dcerpc_reassemble) || !(hdr->flags1 & PFCL1_FRAG) ||
4570                 !tvb_bytes_exist(tvb, offset, stub_length) ){
4571         if(hdr->frag_num == 0) {
4572
4573
4574             /* First fragment, possibly the only fragment */
4575
4576             /*
4577              * XXX - authentication info?
4578              */
4579             pinfo->fragmented = (hdr->flags1 & PFCL1_FRAG);
4580             next_tvb = tvb_new_subset (tvb, offset, length,
4581                                        reported_length);
4582             dcerpc_try_handoff (pinfo, tree, dcerpc_tree, next_tvb,
4583                                 next_tvb, hdr->drep, di, NULL);
4584         } else {
4585             /* PDU is fragmented and this isn't the first fragment */
4586             if (check_col(pinfo->cinfo, COL_INFO)) {
4587                 col_append_fstr(pinfo->cinfo, COL_INFO, " [DCE/RPC fragment]");
4588             }
4589             if (dcerpc_tree) {
4590                 if (length > 0) {
4591                     tvb_ensure_bytes_exist(tvb, offset, stub_length);
4592                     proto_tree_add_text (dcerpc_tree, tvb, offset, stub_length,
4593                                          "Fragment data (%d byte%s)",
4594                                          stub_length,
4595                                          plurality(stub_length, "", "s"));
4596                 }
4597             }
4598         }
4599     } else {
4600         /* Reassembly is enabled, the PDU is fragmented, and
4601            we have all the data in the fragment; the first two
4602            of those mean we should attempt reassembly, and the
4603            third means we can attempt reassembly. */
4604         if (dcerpc_tree) {
4605             if (length > 0) {
4606                 tvb_ensure_bytes_exist(tvb, offset, stub_length);
4607                 proto_tree_add_text (dcerpc_tree, tvb, offset, stub_length,
4608                                      "Fragment data (%d byte%s)", stub_length,
4609                                      plurality(stub_length, "", "s"));
4610             }
4611         }
4612
4613         fd_head = fragment_add_dcerpc_dg(tvb, offset, pinfo,
4614                         hdr->seqnum, &hdr->act_id, dcerpc_cl_reassemble_table,
4615                         hdr->frag_num, stub_length,
4616                         !(hdr->flags1 & PFCL1_LASTFRAG));
4617     if (fd_head != NULL) {
4618             /* We completed reassembly... */
4619         if(pinfo->fd->num==fd_head->reassembled_in) {
4620             /* ...and this is the reassembled RPC PDU */
4621                 next_tvb = tvb_new_real_data(fd_head->data, fd_head->len, fd_head->len);
4622                 tvb_set_child_real_data_tvbuff(tvb, next_tvb);
4623                 add_new_data_source(pinfo, next_tvb, "Reassembled DCE/RPC");
4624                 show_fragment_seq_tree(fd_head, &dcerpc_frag_items,
4625                                            tree, pinfo, next_tvb, &pi);
4626
4627                 /*
4628                  * XXX - authentication info?
4629                  */
4630                 pinfo->fragmented = FALSE;
4631                 dcerpc_try_handoff (pinfo, tree, dcerpc_tree, next_tvb,
4632                                         next_tvb, hdr->drep, di, NULL);
4633                 } else {
4634             /* ...and this isn't the reassembled RPC PDU */
4635                 pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_reassembled_in,
4636                                     tvb, 0, 0, fd_head->reassembled_in);
4637             PROTO_ITEM_SET_GENERATED(pi);
4638             parent_pi = proto_tree_get_parent(dcerpc_tree);
4639             if(parent_pi != NULL) {
4640                 proto_item_append_text(parent_pi, ", [Reas: #%u]", fd_head->reassembled_in);
4641             }
4642                 if (check_col(pinfo->cinfo, COL_INFO)) {
4643                     col_append_fstr(pinfo->cinfo, COL_INFO,
4644                             " [DCE/RPC fragment, reas: #%u]", fd_head->reassembled_in);
4645                 }
4646         }
4647         } else {
4648             /* Reassembly isn't completed yet */
4649             if (check_col(pinfo->cinfo, COL_INFO)) {
4650                 col_append_fstr(pinfo->cinfo, COL_INFO, " [DCE/RPC fragment]");
4651             }
4652         }
4653     }
4654     pinfo->fragmented = save_fragmented;
4655 }
4656
4657 static void
4658 dissect_dcerpc_dg_rqst (tvbuff_t *tvb, int offset, packet_info *pinfo,
4659                         proto_tree *dcerpc_tree, proto_tree *tree,
4660                         e_dce_dg_common_hdr_t *hdr, conversation_t *conv)
4661 {
4662     dcerpc_info *di;
4663     dcerpc_call_value *value, v;
4664     dcerpc_matched_key matched_key, *new_matched_key;
4665     proto_item *pi;
4666     proto_item *parent_pi;
4667
4668     di=get_next_di();
4669     if(!(pinfo->fd->flags.visited)){
4670         dcerpc_call_value *call_value;
4671         dcerpc_dg_call_key *call_key;
4672
4673         call_key=se_alloc (sizeof (dcerpc_dg_call_key));
4674         call_key->conv=conv;
4675         call_key->seqnum=hdr->seqnum;
4676         call_key->act_id=hdr->act_id;
4677
4678         call_value=se_alloc (sizeof (dcerpc_call_value));
4679         call_value->uuid = hdr->if_id;
4680         call_value->ver = hdr->if_ver;
4681         call_value->object_uuid = hdr->obj_id;
4682         call_value->opnum = hdr->opnum;
4683         call_value->req_frame=pinfo->fd->num;
4684         call_value->req_time=pinfo->fd->abs_ts;
4685         call_value->rep_frame=0;
4686         call_value->max_ptr=0;
4687         call_value->private_data = NULL;
4688         g_hash_table_insert (dcerpc_dg_calls, call_key, call_value);
4689
4690         new_matched_key = se_alloc(sizeof (dcerpc_matched_key));
4691         new_matched_key->frame = pinfo->fd->num;
4692         new_matched_key->call_id = hdr->seqnum;
4693         g_hash_table_insert (dcerpc_matched, new_matched_key, call_value);
4694     }
4695
4696     matched_key.frame = pinfo->fd->num;
4697     matched_key.call_id = hdr->seqnum;
4698     value=g_hash_table_lookup(dcerpc_matched, &matched_key);
4699     if (!value) {
4700         v.uuid = hdr->if_id;
4701         v.ver = hdr->if_ver;
4702         v.object_uuid = hdr->obj_id;
4703         v.opnum = hdr->opnum;
4704         v.req_frame = pinfo->fd->num;
4705         v.rep_frame = 0;
4706         v.max_ptr = 0;
4707         v.private_data=NULL;
4708         value = &v;
4709     }
4710
4711     di->conv = conv;
4712     di->call_id = hdr->seqnum;
4713     di->smb_fid = -1;
4714     di->ptype = PDU_REQ;
4715     di->call_data = value;
4716
4717     if(value->rep_frame!=0){
4718         pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_response_in,
4719                             tvb, 0, 0, value->rep_frame);
4720     PROTO_ITEM_SET_GENERATED(pi);
4721     parent_pi = proto_tree_get_parent(dcerpc_tree);
4722     if(parent_pi != NULL) {
4723         proto_item_append_text(parent_pi, ", [Resp: #%u]", value->rep_frame);
4724     }
4725     }
4726     dissect_dcerpc_dg_stub (tvb, offset, pinfo, dcerpc_tree, tree, hdr, di);
4727 }
4728
4729 static void
4730 dissect_dcerpc_dg_resp (tvbuff_t *tvb, int offset, packet_info *pinfo,
4731                         proto_tree *dcerpc_tree, proto_tree *tree,
4732                         e_dce_dg_common_hdr_t *hdr, conversation_t *conv)
4733 {
4734     dcerpc_info *di;
4735     dcerpc_call_value *value, v;
4736     dcerpc_matched_key matched_key, *new_matched_key;
4737     proto_item *pi;
4738     proto_item *parent_pi;
4739
4740     di=get_next_di();
4741     if(!(pinfo->fd->flags.visited)){
4742         dcerpc_call_value *call_value;
4743         dcerpc_dg_call_key call_key;
4744
4745         call_key.conv=conv;
4746         call_key.seqnum=hdr->seqnum;
4747         call_key.act_id=hdr->act_id;
4748
4749         if((call_value=g_hash_table_lookup(dcerpc_dg_calls, &call_key))){
4750             new_matched_key = se_alloc(sizeof (dcerpc_matched_key));
4751             new_matched_key->frame = pinfo->fd->num;
4752             new_matched_key->call_id = hdr->seqnum;
4753             g_hash_table_insert (dcerpc_matched, new_matched_key, call_value);
4754             if(call_value->rep_frame==0){
4755                 call_value->rep_frame=pinfo->fd->num;
4756             }
4757         }
4758     }
4759
4760     matched_key.frame = pinfo->fd->num;
4761     matched_key.call_id = hdr->seqnum;
4762     value=g_hash_table_lookup(dcerpc_matched, &matched_key);
4763     if (!value) {
4764         v.uuid = hdr->if_id;
4765         v.ver = hdr->if_ver;
4766         v.object_uuid = hdr->obj_id;
4767         v.opnum = hdr->opnum;
4768         v.req_frame=0;
4769         v.rep_frame=pinfo->fd->num;
4770         v.private_data=NULL;
4771         value = &v;
4772     }
4773
4774     di->conv = conv;
4775     di->call_id = 0;
4776     di->smb_fid = -1;
4777     di->ptype = PDU_RESP;
4778     di->call_data = value;
4779
4780     if(value->req_frame!=0){
4781         nstime_t delta_ts;
4782         pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_request_in,
4783                             tvb, 0, 0, value->req_frame);
4784     PROTO_ITEM_SET_GENERATED(pi);
4785     parent_pi = proto_tree_get_parent(dcerpc_tree);
4786     if(parent_pi != NULL) {
4787         proto_item_append_text(parent_pi, ", [Req: #%u]", value->req_frame);
4788     }
4789         nstime_delta(&delta_ts, &pinfo->fd->abs_ts, &value->req_time);
4790         pi = proto_tree_add_time(dcerpc_tree, hf_dcerpc_time, tvb, offset, 0, &delta_ts);
4791     PROTO_ITEM_SET_GENERATED(pi);
4792     } else {
4793                 pi = proto_tree_add_text(dcerpc_tree, 
4794                                     tvb, 0, 0, "No request to this DCE/RPC call found");
4795                 expert_add_info_format(pinfo, pi, PI_SEQUENCE, PI_NOTE,
4796                         "No request to this DCE/RPC call found");
4797     }
4798     dissect_dcerpc_dg_stub (tvb, offset, pinfo, dcerpc_tree, tree, hdr, di);
4799 }
4800
4801 static void
4802 dissect_dcerpc_dg_ping_ack (tvbuff_t *tvb, int offset, packet_info *pinfo,
4803                         proto_tree *dcerpc_tree,
4804                         e_dce_dg_common_hdr_t *hdr, conversation_t *conv)
4805 {
4806     proto_item *parent_pi;
4807 /*    if(!(pinfo->fd->flags.visited)){*/
4808         dcerpc_call_value *call_value;
4809         dcerpc_dg_call_key call_key;
4810
4811         call_key.conv=conv;
4812         call_key.seqnum=hdr->seqnum;
4813         call_key.act_id=hdr->act_id;
4814
4815         if((call_value=g_hash_table_lookup(dcerpc_dg_calls, &call_key))){
4816         proto_item *pi;
4817                 nstime_t delta_ts;
4818
4819                 pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_request_in,
4820                                     tvb, 0, 0, call_value->req_frame);
4821         PROTO_ITEM_SET_GENERATED(pi);
4822         parent_pi = proto_tree_get_parent(dcerpc_tree);
4823         if(parent_pi != NULL) {
4824             proto_item_append_text(parent_pi, ", [Req: #%u]", call_value->req_frame);
4825         }
4826
4827         if (check_col (pinfo->cinfo, COL_INFO))
4828             col_append_fstr(pinfo->cinfo, COL_INFO, " [req: #%u]", call_value->req_frame);
4829
4830                 nstime_delta(&delta_ts, &pinfo->fd->abs_ts, &call_value->req_time);
4831                 pi = proto_tree_add_time(dcerpc_tree, hf_dcerpc_time, tvb, offset, 0, &delta_ts);
4832         PROTO_ITEM_SET_GENERATED(pi);
4833 /*    }*/
4834     }
4835 }
4836
4837 /*
4838  * DCERPC dissector for connectionless calls
4839  */
4840 static gboolean
4841 dissect_dcerpc_dg (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4842 {
4843     proto_item *ti = NULL;
4844     proto_item *tf = NULL;
4845     proto_tree *dcerpc_tree = NULL;
4846     proto_tree *dg_flags1_tree = NULL;
4847     proto_tree *dg_flags2_tree = NULL;
4848     proto_tree *drep_tree = NULL;
4849     e_dce_dg_common_hdr_t hdr;
4850     int offset = 0;
4851     conversation_t *conv;
4852     int auth_level;
4853     char uuid_str[DCERPC_UUID_STR_LEN];
4854     int uuid_str_len;
4855
4856     /*
4857      * Check if this looks like a CL DCERPC call.  All dg packets
4858      * have an 80 byte header on them.  Which starts with
4859      * version (4), pkt_type.
4860      */
4861     if (!tvb_bytes_exist (tvb, 0, sizeof (hdr))) {
4862         return FALSE;
4863     }
4864
4865     /* Version must be 4 */
4866     hdr.rpc_ver = tvb_get_guint8 (tvb, offset++);
4867     if (hdr.rpc_ver != 4)
4868         return FALSE;
4869
4870     /* Type must be <=19 or its not DCE/RPC */
4871     hdr.ptype = tvb_get_guint8 (tvb, offset++);
4872     if (hdr.ptype > 19)
4873         return FALSE;
4874
4875     /* flags1 has bit 1 and 8 as reserved so if any of them are set, it is
4876        probably not a DCE/RPC packet
4877      */
4878     hdr.flags1 = tvb_get_guint8 (tvb, offset++);
4879     if(hdr.flags1&0x81)
4880         return FALSE;
4881
4882     /* flags2 has all bits except bit 2 as reserved so if any of them are set
4883        it is probably not DCE/RPC.
4884      */
4885     hdr.flags2 = tvb_get_guint8 (tvb, offset++);
4886     if(hdr.flags2&0xfd)
4887         return FALSE;
4888
4889
4890     if (check_col (pinfo->cinfo, COL_PROTOCOL))
4891         col_set_str (pinfo->cinfo, COL_PROTOCOL, "DCERPC");
4892     if (check_col (pinfo->cinfo, COL_INFO))
4893         col_add_str (pinfo->cinfo, COL_INFO, pckt_vals[hdr.ptype].strptr);
4894
4895     tvb_memcpy (tvb, (guint8 *)hdr.drep, offset, sizeof (hdr.drep));
4896     offset += sizeof (hdr.drep);
4897     hdr.serial_hi = tvb_get_guint8 (tvb, offset++);
4898     dcerpc_tvb_get_uuid (tvb, offset, hdr.drep, &hdr.obj_id);
4899     offset += 16;
4900     dcerpc_tvb_get_uuid (tvb, offset, hdr.drep, &hdr.if_id);
4901     offset += 16;
4902     dcerpc_tvb_get_uuid (tvb, offset, hdr.drep, &hdr.act_id);
4903     offset += 16;
4904     hdr.server_boot = dcerpc_tvb_get_ntohl (tvb, offset, hdr.drep);
4905     offset += 4;
4906     hdr.if_ver = dcerpc_tvb_get_ntohl (tvb, offset, hdr.drep);
4907     offset += 4;
4908     hdr.seqnum = dcerpc_tvb_get_ntohl (tvb, offset, hdr.drep);
4909     offset += 4;
4910     hdr.opnum = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
4911     offset += 2;
4912     hdr.ihint = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
4913     offset += 2;
4914     hdr.ahint = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
4915     offset += 2;
4916     hdr.frag_len = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
4917     offset += 2;
4918     hdr.frag_num = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
4919     offset += 2;
4920     hdr.auth_proto = tvb_get_guint8 (tvb, offset++);
4921     hdr.serial_lo = tvb_get_guint8 (tvb, offset++);
4922
4923     if (tree) {
4924         ti = proto_tree_add_item (tree, proto_dcerpc, tvb, 0, -1, FALSE);
4925         if (ti) {
4926             dcerpc_tree = proto_item_add_subtree(ti, ett_dcerpc);
4927                     proto_item_append_text(ti, " %s, Seq: %u, Serial: %u, Frag: %u, FragLen: %u",
4928                 val_to_str(hdr.ptype, pckt_vals, "Unknown (0x%02x)"),
4929                 hdr.seqnum, hdr.serial_hi*256+hdr.serial_lo,
4930                 hdr.frag_num, hdr.frag_len);
4931         }
4932     }
4933     offset = 0;
4934
4935     if (tree)
4936         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_ver, tvb, offset, 1, hdr.rpc_ver);
4937     offset++;
4938
4939     if (tree)
4940         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_packet_type, tvb, offset, 1, hdr.ptype);
4941     offset++;
4942
4943     if (tree) {
4944         tf = proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_flags1, tvb, offset, 1, hdr.flags1);
4945         dg_flags1_tree = proto_item_add_subtree (tf, ett_dcerpc_dg_flags1);
4946         if (dg_flags1_tree) {
4947             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_rsrvd_80, tvb, offset, 1, hdr.flags1);
4948             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_broadcast, tvb, offset, 1, hdr.flags1);
4949             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_idempotent, tvb, offset, 1, hdr.flags1);
4950             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_maybe, tvb, offset, 1, hdr.flags1);
4951             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_nofack, tvb, offset, 1, hdr.flags1);
4952             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_frag, tvb, offset, 1, hdr.flags1);
4953             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_last_frag, tvb, offset, 1, hdr.flags1);
4954             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_rsrvd_01, tvb, offset, 1, hdr.flags1);
4955             if(hdr.flags1) {
4956                         proto_item_append_text(tf, " %s%s%s%s%s%s",
4957                     (hdr.flags1 & PFCL1_BROADCAST) ? "\"Broadcast\" " : "",
4958                     (hdr.flags1 & PFCL1_IDEMPOTENT) ? "\"Idempotent\" " : "",
4959                     (hdr.flags1 & PFCL1_MAYBE) ? "\"Maybe\" " : "",
4960                     (hdr.flags1 & PFCL1_NOFACK) ? "\"No Fack\" " : "",
4961                     (hdr.flags1 & PFCL1_FRAG) ? "\"Fragment\" " : "",
4962                     (hdr.flags1 & PFCL1_LASTFRAG) ? "\"Last Fragment\" " : "");
4963             }
4964         }
4965     }
4966     offset++;
4967
4968     if (tree) {
4969         tf = proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_flags2, tvb, offset, 1, hdr.flags2);
4970         dg_flags2_tree = proto_item_add_subtree (tf, ett_dcerpc_dg_flags2);
4971         if (dg_flags2_tree) {
4972             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_80, tvb, offset, 1, hdr.flags2);
4973             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_40, tvb, offset, 1, hdr.flags2);
4974             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_20, tvb, offset, 1, hdr.flags2);
4975             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_10, tvb, offset, 1, hdr.flags2);
4976             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_08, tvb, offset, 1, hdr.flags2);
4977             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_04, tvb, offset, 1, hdr.flags2);
4978             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_cancel_pending, tvb, offset, 1, hdr.flags2);
4979             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_01, tvb, offset, 1, hdr.flags2);
4980             if(hdr.flags2) {
4981                         proto_item_append_text(tf, " %s",
4982                     (hdr.flags2 & PFCL2_CANCEL_PENDING) ? "\"Cancel Pending\" " : "");
4983             }
4984         }
4985     }
4986     offset++;
4987
4988     if (tree) {
4989         tf = proto_tree_add_bytes (dcerpc_tree, hf_dcerpc_drep, tvb, offset, sizeof (hdr.drep), hdr.drep);
4990         drep_tree = proto_item_add_subtree (tf, ett_dcerpc_drep);
4991         if (drep_tree) {
4992             proto_tree_add_uint(drep_tree, hf_dcerpc_drep_byteorder, tvb, offset, 1, hdr.drep[0] >> 4);
4993             proto_tree_add_uint(drep_tree, hf_dcerpc_drep_character, tvb, offset, 1, hdr.drep[0] & 0x0f);
4994             proto_tree_add_uint(drep_tree, hf_dcerpc_drep_fp, tvb, offset+1, 1, hdr.drep[1]);
4995                     proto_item_append_text(tf, " (Order: %s, Char: %s, Float: %s)",
4996                 val_to_str(hdr.drep[0] >> 4, drep_byteorder_vals, "Unknown"),
4997                 val_to_str(hdr.drep[0] & 0x0f, drep_character_vals, "Unknown"),
4998                 val_to_str(hdr.drep[1], drep_fp_vals, "Unknown"));
4999         }
5000     }
5001     offset += sizeof (hdr.drep);
5002
5003     if (tree)
5004         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_serial_hi, tvb, offset, 1, hdr.serial_hi);
5005     offset++;
5006
5007     if (tree) {
5008         uuid_str_len = g_snprintf(uuid_str, DCERPC_UUID_STR_LEN,
5009                                 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
5010                                 hdr.obj_id.Data1, hdr.obj_id.Data2, hdr.obj_id.Data3,
5011                                 hdr.obj_id.Data4[0],
5012                                 hdr.obj_id.Data4[1],
5013                                 hdr.obj_id.Data4[2],
5014                                 hdr.obj_id.Data4[3],
5015                                 hdr.obj_id.Data4[4],
5016                                 hdr.obj_id.Data4[5],
5017                                 hdr.obj_id.Data4[6],
5018                                 hdr.obj_id.Data4[7]);
5019         if (uuid_str_len == -1 || uuid_str_len >= DCERPC_UUID_STR_LEN)
5020                 memset(uuid_str, 0, DCERPC_UUID_STR_LEN);
5021         proto_tree_add_guid_format (dcerpc_tree, hf_dcerpc_obj_id, tvb,
5022             offset, 16, (e_guid_t *) &hdr.obj_id, "Object UUID: %s", uuid_str);
5023     }
5024     offset += 16;
5025
5026     if (tree) {
5027         uuid_str_len = g_snprintf(uuid_str, DCERPC_UUID_STR_LEN,
5028                                 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
5029                                 hdr.if_id.Data1, hdr.if_id.Data2, hdr.if_id.Data3,
5030                                 hdr.if_id.Data4[0],
5031                                 hdr.if_id.Data4[1],
5032                                 hdr.if_id.Data4[2],
5033                                 hdr.if_id.Data4[3],
5034                                 hdr.if_id.Data4[4],
5035                                 hdr.if_id.Data4[5],
5036                                 hdr.if_id.Data4[6],
5037                                 hdr.if_id.Data4[7]);
5038         if (uuid_str_len == -1 || uuid_str_len >= DCERPC_UUID_STR_LEN)
5039                 memset(uuid_str, 0, DCERPC_UUID_STR_LEN);
5040         proto_tree_add_guid_format (dcerpc_tree, hf_dcerpc_dg_if_id, tvb,
5041                                       offset, 16, (e_guid_t *) &hdr.if_id, "Interface: %s", uuid_str);
5042     }
5043     offset += 16;
5044
5045     if (tree) {
5046         uuid_str_len = g_snprintf(uuid_str, DCERPC_UUID_STR_LEN,
5047                                 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
5048                                 hdr.act_id.Data1, hdr.act_id.Data2, hdr.act_id.Data3,
5049                                 hdr.act_id.Data4[0],
5050                                 hdr.act_id.Data4[1],
5051                                 hdr.act_id.Data4[2],
5052                                 hdr.act_id.Data4[3],
5053                                 hdr.act_id.Data4[4],
5054                                 hdr.act_id.Data4[5],
5055                                 hdr.act_id.Data4[6],
5056                                 hdr.act_id.Data4[7]);
5057         if (uuid_str_len == -1 || uuid_str_len >= DCERPC_UUID_STR_LEN)
5058                 memset(uuid_str, 0, DCERPC_UUID_STR_LEN);
5059         proto_tree_add_guid_format (dcerpc_tree, hf_dcerpc_dg_act_id, tvb,
5060                                       offset, 16, (e_guid_t *) &hdr.act_id, "Activity: %s", uuid_str);
5061     }
5062     offset += 16;
5063
5064     if (tree) {
5065         nstime_t server_boot;
5066
5067         server_boot.secs  = hdr.server_boot;
5068         server_boot.nsecs = 0;
5069
5070         if (hdr.server_boot == 0)
5071             proto_tree_add_time_format (dcerpc_tree, hf_dcerpc_dg_server_boot,
5072                                         tvb, offset, 4, &server_boot,
5073                                         "Server boot time: Unknown (0)");
5074         else
5075             proto_tree_add_time (dcerpc_tree, hf_dcerpc_dg_server_boot,
5076                                  tvb, offset, 4, &server_boot);
5077     }
5078     offset += 4;
5079
5080     if (tree)
5081         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_if_ver, tvb, offset, 4, hdr.if_ver);
5082     offset += 4;
5083
5084     if (tree)
5085         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_seqnum, tvb, offset, 4, hdr.seqnum);
5086     if (check_col (pinfo->cinfo, COL_INFO)) {
5087         col_append_fstr (pinfo->cinfo, COL_INFO, ": seq: %u", hdr.seqnum);
5088     }
5089     if (check_col (pinfo->cinfo, COL_DCE_CALL)) {
5090         col_append_fstr (pinfo->cinfo, COL_DCE_CALL, "%u", hdr.seqnum);
5091     }
5092     offset += 4;
5093
5094     if (tree)
5095         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_opnum, tvb, offset, 2, hdr.opnum);
5096     offset += 2;
5097
5098     if (tree)
5099         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_ihint, tvb, offset, 2, hdr.ihint);
5100     offset += 2;
5101
5102     if (tree)
5103         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_ahint, tvb, offset, 2, hdr.ahint);
5104     offset += 2;
5105
5106     if (tree)
5107         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_frag_len, tvb, offset, 2, hdr.frag_len);
5108     offset += 2;
5109
5110     if (tree)
5111         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_frag_num, tvb, offset, 2, hdr.frag_num);
5112     if (check_col (pinfo->cinfo, COL_INFO)) {
5113         if (hdr.flags1 & PFCL1_FRAG) {
5114             /* Fragmented - put the fragment number into the Info column */
5115             col_append_fstr (pinfo->cinfo, COL_INFO, " frag: %u",
5116                              hdr.frag_num);
5117         }
5118     }
5119     offset += 2;
5120
5121     if (tree)
5122         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_auth_proto, tvb, offset, 1, hdr.auth_proto);
5123     offset++;
5124
5125     if (tree)
5126         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_serial_lo, tvb, offset, 1, hdr.serial_lo);
5127     if (check_col (pinfo->cinfo, COL_INFO)) {
5128         if (hdr.flags1 & PFCL1_FRAG) {
5129             /* Fragmented - put the serial number into the Info column */
5130             col_append_fstr (pinfo->cinfo, COL_INFO, " serial: %u",
5131                              (hdr.serial_hi << 8) | hdr.serial_lo);
5132         }
5133     }
5134     offset++;
5135
5136     if (tree) {
5137         /*
5138          * XXX - for Kerberos, we get a protection level; if it's
5139          * DCE_C_AUTHN_LEVEL_PKT_PRIVACY, we can't dissect the
5140          * stub data.
5141          */
5142         dissect_dcerpc_dg_auth (tvb, offset, dcerpc_tree, &hdr,
5143                                 &auth_level);
5144     }
5145
5146     /*
5147      * keeping track of the conversation shouldn't really be necessary
5148      * for connectionless packets, because everything we need to know
5149      * to dissect is in the header for each packet.  Unfortunately,
5150      * Microsoft's implementation is buggy and often puts the
5151      * completely wrong if_id in the header.  go figure.  So, keep
5152      * track of the seqnum and use that if possible.  Note: that's not
5153      * completely correct.  It should really be done based on both the
5154      * activity_id and seqnum.  I haven't seen anywhere that it would
5155      * make a difference, but for future reference...
5156      */
5157     conv = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
5158                               pinfo->srcport, pinfo->destport, 0);
5159     if (!conv) {
5160         conv = conversation_new (pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
5161                                  pinfo->srcport, pinfo->destport, 0);
5162     }
5163
5164     /*
5165      * Packet type specific stuff is next.
5166      */
5167
5168     switch (hdr.ptype) {
5169
5170     case PDU_CANCEL_ACK:
5171         /* Body is optional */
5172         /* XXX - we assume "frag_len" is the length of the body */
5173         if (hdr.frag_len != 0)
5174             dissect_dcerpc_dg_cancel_ack (tvb, offset, pinfo, dcerpc_tree, &hdr);
5175         break;
5176
5177     case PDU_CL_CANCEL:
5178         /*
5179          * XXX - The DCE RPC 1.1 spec doesn't say the body is optional,
5180          * but in at least one capture none of the Cl_cancel PDUs had a
5181          * body.
5182          */
5183         /* XXX - we assume "frag_len" is the length of the body */
5184         if (hdr.frag_len != 0)
5185             dissect_dcerpc_dg_cancel (tvb, offset, pinfo, dcerpc_tree, &hdr);
5186         break;
5187
5188     case PDU_NOCALL:
5189         /* Body is optional; if present, it's the same as PDU_FACK */
5190         /* XXX - we assume "frag_len" is the length of the body */
5191         if (hdr.frag_len != 0)
5192             dissect_dcerpc_dg_fack (tvb, offset, pinfo, dcerpc_tree, &hdr);
5193         break;
5194
5195     case PDU_FACK:
5196         dissect_dcerpc_dg_fack (tvb, offset, pinfo, dcerpc_tree, &hdr);
5197         break;
5198
5199     case PDU_REJECT:
5200     case PDU_FAULT:
5201         dissect_dcerpc_dg_reject_fault (tvb, offset, pinfo, dcerpc_tree, &hdr);
5202         break;
5203
5204     case PDU_REQ:
5205         dissect_dcerpc_dg_rqst (tvb, offset, pinfo, dcerpc_tree, tree, &hdr, conv);
5206         break;
5207
5208     case PDU_RESP:
5209         dissect_dcerpc_dg_resp (tvb, offset, pinfo, dcerpc_tree, tree, &hdr, conv);
5210         break;
5211
5212     /* these requests have no body */
5213     case PDU_ACK:
5214     case PDU_PING:
5215         dissect_dcerpc_dg_ping_ack (tvb, offset, pinfo, dcerpc_tree, &hdr, conv);
5216         break;
5217     case PDU_WORKING:
5218     default:
5219         break;
5220     }
5221
5222     return TRUE;
5223 }
5224
5225 static void
5226 dcerpc_init_protocol (void)
5227 {
5228         /* structures and data for BIND */
5229         if (dcerpc_binds){
5230                 g_hash_table_destroy (dcerpc_binds);
5231                 dcerpc_binds=NULL;
5232         }
5233         if(!dcerpc_binds){
5234                 dcerpc_binds = g_hash_table_new (dcerpc_bind_hash, dcerpc_bind_equal);
5235         }
5236
5237         /* structures and data for CALL */
5238         if (dcerpc_cn_calls){
5239                 g_hash_table_destroy (dcerpc_cn_calls);
5240         }
5241         dcerpc_cn_calls = g_hash_table_new (dcerpc_cn_call_hash, dcerpc_cn_call_equal);
5242         if (dcerpc_dg_calls){
5243                 g_hash_table_destroy (dcerpc_dg_calls);
5244         }
5245         dcerpc_dg_calls = g_hash_table_new (dcerpc_dg_call_hash, dcerpc_dg_call_equal);
5246
5247         /* structure and data for MATCHED */
5248         if (dcerpc_matched){
5249                 g_hash_table_destroy (dcerpc_matched);
5250         }
5251         dcerpc_matched = g_hash_table_new (dcerpc_matched_hash, dcerpc_matched_equal);
5252
5253     /* call the registered hooks */
5254     g_hook_list_invoke(&dcerpc_hooks_init_protos, FALSE /* not may_recurse */);
5255 }
5256
5257 void
5258 proto_register_dcerpc (void)
5259 {
5260     static hf_register_info hf[] = {
5261         { &hf_dcerpc_request_in,
5262                 { "Request in frame", "dcerpc.request_in", FT_FRAMENUM, BASE_NONE,
5263                 NULL, 0, "This packet is a response to the packet with this number", HFILL }},
5264         { &hf_dcerpc_response_in,
5265                 { "Response in frame", "dcerpc.response_in", FT_FRAMENUM, BASE_NONE,
5266                 NULL, 0, "This packet will be responded in the packet with this number", HFILL }},
5267         { &hf_dcerpc_referent_id,
5268                 { "Referent ID", "dcerpc.referent_id", FT_UINT32, BASE_HEX,
5269                 NULL, 0, "Referent ID for this NDR encoded pointer", HFILL }},
5270         { &hf_dcerpc_ver,
5271           { "Version", "dcerpc.ver", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
5272         { &hf_dcerpc_ver_minor,
5273           { "Version (minor)", "dcerpc.ver_minor", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
5274         { &hf_dcerpc_packet_type,
5275           { "Packet type", "dcerpc.pkt_type", FT_UINT8, BASE_DEC, VALS (pckt_vals), 0x0, "", HFILL }},
5276         { &hf_dcerpc_cn_flags,
5277           { "Packet Flags", "dcerpc.cn_flags", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
5278         { &hf_dcerpc_cn_flags_first_frag,
5279           { "First Frag", "dcerpc.cn_flags.first_frag", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFC_FIRST_FRAG, "", HFILL }},
5280         { &hf_dcerpc_cn_flags_last_frag,
5281           { "Last Frag", "dcerpc.cn_flags.last_frag", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFC_LAST_FRAG, "", HFILL }},
5282         { &hf_dcerpc_cn_flags_cancel_pending,
5283           { "Cancel Pending", "dcerpc.cn_flags.cancel_pending", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFC_PENDING_CANCEL, "", HFILL }},
5284         { &hf_dcerpc_cn_flags_reserved,
5285           { "Reserved", "dcerpc.cn_flags.reserved", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFC_RESERVED_1, "", HFILL }},
5286         { &hf_dcerpc_cn_flags_mpx,
5287           { "Multiplex", "dcerpc.cn_flags.mpx", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFC_CONC_MPX, "", HFILL }},
5288         { &hf_dcerpc_cn_flags_dne,
5289           { "Did Not Execute", "dcerpc.cn_flags.dne", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFC_DID_NOT_EXECUTE, "", HFILL }},
5290         { &hf_dcerpc_cn_flags_maybe,
5291           { "Maybe", "dcerpc.cn_flags.maybe", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFC_MAYBE, "", HFILL }},
5292         { &hf_dcerpc_cn_flags_object,
5293           { "Object", "dcerpc.cn_flags.object", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFC_OBJECT_UUID, "", HFILL }},
5294         { &hf_dcerpc_drep,
5295           { "Data Representation", "dcerpc.drep", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
5296         { &hf_dcerpc_drep_byteorder,
5297           { "Byte order", "dcerpc.drep.byteorder", FT_UINT8, BASE_DEC, VALS (drep_byteorder_vals), 0x0, "", HFILL }},
5298         { &hf_dcerpc_drep_character,
5299           { "Character", "dcerpc.drep.character", FT_UINT8, BASE_DEC, VALS (drep_character_vals), 0x0, "", HFILL }},
5300         { &hf_dcerpc_drep_fp,
5301           { "Floating-point", "dcerpc.drep.fp", FT_UINT8, BASE_DEC, VALS (drep_fp_vals), 0x0, "", HFILL }},
5302         { &hf_dcerpc_cn_frag_len,
5303           { "Frag Length", "dcerpc.cn_frag_len", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
5304         { &hf_dcerpc_cn_auth_len,
5305           { "Auth Length", "dcerpc.cn_auth_len", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
5306         { &hf_dcerpc_cn_call_id,
5307           { "Call ID", "dcerpc.cn_call_id", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
5308         { &hf_dcerpc_cn_max_xmit,
5309           { "Max Xmit Frag", "dcerpc.cn_max_xmit", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
5310         { &hf_dcerpc_cn_max_recv,
5311           { "Max Recv Frag", "dcerpc.cn_max_recv", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
5312         { &hf_dcerpc_cn_assoc_group,
5313           { "Assoc Group", "dcerpc.cn_assoc_group", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
5314         { &hf_dcerpc_cn_num_ctx_items,
5315           { "Num Ctx Items", "dcerpc.cn_num_ctx_items", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
5316         { &hf_dcerpc_cn_ctx_item,
5317           { "Ctx Item", "dcerpc.cn_ctx_item", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
5318         { &hf_dcerpc_cn_ctx_id,
5319           { "Context ID", "dcerpc.cn_ctx_id", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
5320         { &hf_dcerpc_cn_num_trans_items,
5321           { "Num Trans Items", "dcerpc.cn_num_trans_items", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
5322         { &hf_dcerpc_cn_bind_abstract_syntax,
5323           { "Abstract Syntax", "dcerpc.cn_bind_abstract_syntax", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
5324         { &hf_dcerpc_cn_bind_if_id,
5325           { "Interface UUID", "dcerpc.cn_bind_to_uuid", FT_GUID, BASE_NONE, NULL, 0x0, "", HFILL }},
5326         { &hf_dcerpc_cn_bind_if_ver,
5327           { "Interface Ver", "dcerpc.cn_bind_if_ver", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
5328         { &hf_dcerpc_cn_bind_if_ver_minor,
5329           { "Interface Ver Minor", "dcerpc.cn_bind_if_ver_minor", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
5330         { &hf_dcerpc_cn_bind_trans_syntax,
5331           { "Transfer Syntax", "dcerpc.cn_bind_trans", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
5332         { &hf_dcerpc_cn_bind_trans_id,
5333           { "ID", "dcerpc.cn_bind_trans_id", FT_GUID, BASE_NONE, NULL, 0x0, "", HFILL }},
5334         { &hf_dcerpc_cn_bind_trans_ver,
5335           { "ver", "dcerpc.cn_bind_trans_ver", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
5336         { &hf_dcerpc_cn_alloc_hint,
5337           { "Alloc hint", "dcerpc.cn_alloc_hint", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
5338         { &hf_dcerpc_cn_sec_addr_len,
5339           { "Scndry Addr len", "dcerpc.cn_sec_addr_len", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
5340         { &hf_dcerpc_cn_sec_addr,
5341           { "Scndry Addr", "dcerpc.cn_sec_addr", FT_STRINGZ, BASE_NONE, NULL, 0x0, "", HFILL }},
5342         { &hf_dcerpc_cn_num_results,
5343           { "Num results", "dcerpc.cn_num_results", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
5344         { &hf_dcerpc_cn_ack_result,
5345           { "Ack result", "dcerpc.cn_ack_result", FT_UINT16, BASE_DEC, VALS(p_cont_result_vals), 0x0, "", HFILL }},
5346         { &hf_dcerpc_cn_ack_reason,
5347           { "Ack reason", "dcerpc.cn_ack_reason", FT_UINT16, BASE_DEC, VALS(p_provider_reason_vals), 0x0, "", HFILL }},
5348         { &hf_dcerpc_cn_ack_trans_id,
5349           { "Transfer Syntax", "dcerpc.cn_ack_trans_id", FT_GUID, BASE_NONE, NULL, 0x0, "", HFILL }},
5350         { &hf_dcerpc_cn_ack_trans_ver,
5351           { "Syntax ver", "dcerpc.cn_ack_trans_ver", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
5352         { &hf_dcerpc_cn_reject_reason,
5353           { "Reject reason", "dcerpc.cn_reject_reason", FT_UINT16, BASE_DEC, VALS(reject_reason_vals), 0x0, "", HFILL }},
5354         { &hf_dcerpc_cn_num_protocols,
5355           { "Number of protocols", "dcerpc.cn_num_protocols", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
5356         { &hf_dcerpc_cn_protocol_ver_major,
5357           { "Protocol major version", "dcerpc.cn_protocol_ver_major", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
5358         { &hf_dcerpc_cn_protocol_ver_minor,
5359           { "Protocol minor version", "dcerpc.cn_protocol_ver_minor", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
5360         { &hf_dcerpc_cn_cancel_count,
5361           { "Cancel count", "dcerpc.cn_cancel_count", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
5362         { &hf_dcerpc_cn_status,
5363           { "Status", "dcerpc.cn_status", FT_UINT32, BASE_HEX, VALS(reject_status_vals), 0x0, "", HFILL }},
5364         { &hf_dcerpc_cn_deseg_req,
5365           { "Desegmentation Required", "dcerpc.cn_deseg_req", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
5366         { &hf_dcerpc_auth_type,
5367           { "Auth type", "dcerpc.auth_type", FT_UINT8, BASE_DEC, VALS (authn_protocol_vals), 0x0, "", HFILL }},
5368         { &hf_dcerpc_auth_level,
5369           { "Auth level", "dcerpc.auth_level", FT_UINT8, BASE_DEC, VALS (authn_level_vals), 0x0, "", HFILL }},
5370         { &hf_dcerpc_auth_pad_len,
5371           { "Auth pad len", "dcerpc.auth_pad_len", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
5372         { &hf_dcerpc_auth_rsrvd,
5373           { "Auth Rsrvd", "dcerpc.auth_rsrvd", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
5374         { &hf_dcerpc_auth_ctx_id,
5375           { "Auth Context ID", "dcerpc.auth_ctx_id", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
5376         { &hf_dcerpc_dg_flags1,
5377           { "Flags1", "dcerpc.dg_flags1", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
5378         { &hf_dcerpc_dg_flags1_rsrvd_01,
5379           { "Reserved", "dcerpc.dg_flags1_rsrvd_01", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL1_RESERVED_01, "", HFILL }},
5380         { &hf_dcerpc_dg_flags1_last_frag,
5381           { "Last Fragment", "dcerpc.dg_flags1_last_frag", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL1_LASTFRAG, "", HFILL }},
5382         { &hf_dcerpc_dg_flags1_frag,
5383           { "Fragment", "dcerpc.dg_flags1_frag", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL1_FRAG, "", HFILL }},
5384         { &hf_dcerpc_dg_flags1_nofack,
5385           { "No Fack", "dcerpc.dg_flags1_nofack", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL1_NOFACK, "", HFILL }},
5386         { &hf_dcerpc_dg_flags1_maybe,
5387           { "Maybe", "dcerpc.dg_flags1_maybe", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL1_MAYBE, "", HFILL }},
5388         { &hf_dcerpc_dg_flags1_idempotent,
5389           { "Idempotent", "dcerpc.dg_flags1_idempotent", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL1_IDEMPOTENT, "", HFILL }},
5390         { &hf_dcerpc_dg_flags1_broadcast,
5391           { "Broadcast", "dcerpc.dg_flags1_broadcast", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL1_BROADCAST, "", HFILL }},
5392         { &hf_dcerpc_dg_flags1_rsrvd_80,
5393           { "Reserved", "dcerpc.dg_flags1_rsrvd_80", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL1_RESERVED_80, "", HFILL }},
5394         { &hf_dcerpc_dg_flags2,
5395           { "Flags2", "dcerpc.dg_flags2", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
5396         { &hf_dcerpc_dg_flags2_rsrvd_01,
5397           { "Reserved", "dcerpc.dg_flags2_rsrvd_01", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL2_RESERVED_01, "", HFILL }},
5398         { &hf_dcerpc_dg_flags2_cancel_pending,
5399           { "Cancel Pending", "dcerpc.dg_flags2_cancel_pending", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL2_CANCEL_PENDING, "", HFILL }},
5400         { &hf_dcerpc_dg_flags2_rsrvd_04,
5401           { "Reserved", "dcerpc.dg_flags2_rsrvd_04", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL2_RESERVED_04, "", HFILL }},
5402         { &hf_dcerpc_dg_flags2_rsrvd_08,
5403           { "Reserved", "dcerpc.dg_flags2_rsrvd_08", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL2_RESERVED_08, "", HFILL }},
5404         { &hf_dcerpc_dg_flags2_rsrvd_10,
5405           { "Reserved", "dcerpc.dg_flags2_rsrvd_10", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL2_RESERVED_10, "", HFILL }},
5406         { &hf_dcerpc_dg_flags2_rsrvd_20,
5407           { "Reserved", "dcerpc.dg_flags2_rsrvd_20", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL2_RESERVED_20, "", HFILL }},
5408         { &hf_dcerpc_dg_flags2_rsrvd_40,
5409           { "Reserved", "dcerpc.dg_flags2_rsrvd_40", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL2_RESERVED_40, "", HFILL }},
5410         { &hf_dcerpc_dg_flags2_rsrvd_80,
5411           { "Reserved", "dcerpc.dg_flags2_rsrvd_80", FT_BOOLEAN, 8, TFS (&flags_set_truth), PFCL2_RESERVED_80, "", HFILL }},
5412         { &hf_dcerpc_dg_serial_lo,
5413           { "Serial Low", "dcerpc.dg_serial_lo", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
5414         { &hf_dcerpc_dg_serial_hi,
5415           { "Serial High", "dcerpc.dg_serial_hi", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
5416         { &hf_dcerpc_dg_ahint,
5417           { "Activity Hint", "dcerpc.dg_ahint", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
5418         { &hf_dcerpc_dg_ihint,
5419           { "Interface Hint", "dcerpc.dg_ihint", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
5420         { &hf_dcerpc_dg_frag_len,
5421           { "Fragment len", "dcerpc.dg_frag_len", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
5422         { &hf_dcerpc_dg_frag_num,
5423           { "Fragment num", "dcerpc.dg_frag_num", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
5424         { &hf_dcerpc_dg_auth_proto,
5425           { "Auth proto", "dcerpc.dg_auth_proto", FT_UINT8, BASE_DEC, VALS (authn_protocol_vals), 0x0, "", HFILL }},
5426         { &hf_dcerpc_dg_seqnum,
5427           { "Sequence num", "dcerpc.dg_seqnum", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
5428         { &hf_dcerpc_dg_server_boot,
5429           { "Server boot time", "dcerpc.dg_server_boot", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0, "", HFILL }},
5430         { &hf_dcerpc_dg_if_ver,
5431           { "Interface Ver", "dcerpc.dg_if_ver", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
5432         { &hf_dcerpc_krb5_av_prot_level,
5433           { "Protection Level", "dcerpc.krb5_av.prot_level", FT_UINT8, BASE_DEC, VALS(authn_level_vals), 0x0, "", HFILL }},
5434         { &hf_dcerpc_krb5_av_key_vers_num,
5435           { "Key Version Number", "dcerpc.krb5_av.key_vers_num", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
5436         { &hf_dcerpc_krb5_av_key_auth_verifier,
5437           { "Authentication Verifier", "dcerpc.krb5_av.auth_verifier", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }},
5438         { &hf_dcerpc_obj_id,
5439           { "Object", "dcerpc.obj_id", FT_GUID, BASE_NONE, NULL, 0x0, "", HFILL }},
5440         { &hf_dcerpc_dg_if_id,
5441           { "Interface", "dcerpc.dg_if_id", FT_GUID, BASE_NONE, NULL, 0x0, "", HFILL }},
5442         { &hf_dcerpc_dg_act_id,
5443           { "Activity", "dcerpc.dg_act_id", FT_GUID, BASE_NONE, NULL, 0x0, "", HFILL }},
5444         { &hf_dcerpc_opnum,
5445           { "Opnum", "dcerpc.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
5446
5447         { &hf_dcerpc_dg_cancel_vers,
5448           { "Cancel Version", "dcerpc.dg_cancel_vers", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
5449
5450         { &hf_dcerpc_dg_cancel_id,
5451           { "Cancel ID", "dcerpc.dg_cancel_id", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
5452
5453         { &hf_dcerpc_dg_server_accepting_cancels,
5454           { "Server accepting cancels", "dcerpc.server_accepting_cancels", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL }},
5455
5456         { &hf_dcerpc_dg_fack_vers,
5457           { "FACK Version", "dcerpc.fack_vers", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
5458
5459         { &hf_dcerpc_dg_fack_window_size,
5460           { "Window Size", "dcerpc.fack_window_size", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
5461
5462         { &hf_dcerpc_dg_fack_max_tsdu,
5463           { "Max TSDU", "dcerpc.fack_max_tsdu", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
5464
5465         { &hf_dcerpc_dg_fack_max_frag_size,
5466           { "Max Frag Size", "dcerpc.fack_max_frag_size", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
5467
5468         { &hf_dcerpc_dg_fack_serial_num,
5469           { "Serial Num", "dcerpc.fack_serial_num", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
5470
5471         { &hf_dcerpc_dg_fack_selack_len,
5472           { "Selective ACK Len", "dcerpc.fack_selack_len", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
5473
5474         { &hf_dcerpc_dg_fack_selack,
5475           { "Selective ACK", "dcerpc.fack_selack", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
5476
5477         { &hf_dcerpc_dg_status,
5478           { "Status", "dcerpc.dg_status", FT_UINT32, BASE_HEX, VALS(reject_status_vals), 0x0, "", HFILL }},
5479
5480         { &hf_dcerpc_array_max_count,
5481           { "Max Count", "dcerpc.array.max_count", FT_UINT32, BASE_DEC, NULL, 0x0, "Maximum Count: Number of elements in the array", HFILL }},
5482
5483         { &hf_dcerpc_array_offset,
5484           { "Offset", "dcerpc.array.offset", FT_UINT32, BASE_DEC, NULL, 0x0, "Offset for first element in array", HFILL }},
5485
5486         { &hf_dcerpc_array_actual_count,
5487           { "Actual Count", "dcerpc.array.actual_count", FT_UINT32, BASE_DEC, NULL, 0x0, "Actual Count: Actual number of elements in the array", HFILL }},
5488
5489         { &hf_dcerpc_array_buffer,
5490           { "Buffer", "dcerpc.array.buffer", FT_BYTES, BASE_NONE, NULL, 0x0, "Buffer: Buffer containing elements of the array", HFILL }},
5491
5492         { &hf_dcerpc_op,
5493           { "Operation", "dcerpc.op", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
5494
5495         { &hf_dcerpc_fragments,
5496           { "Reassembled DCE/RPC Fragments", "dcerpc.fragments", FT_NONE, BASE_NONE,
5497           NULL, 0x0, "DCE/RPC Fragments", HFILL }},
5498
5499         { &hf_dcerpc_fragment,
5500           { "DCE/RPC Fragment", "dcerpc.fragment", FT_FRAMENUM, BASE_NONE,
5501           NULL, 0x0, "DCE/RPC Fragment", HFILL }},
5502
5503         { &hf_dcerpc_fragment_overlap,
5504           { "Fragment overlap", "dcerpc.fragment.overlap", FT_BOOLEAN, BASE_NONE,
5505       NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
5506
5507         { &hf_dcerpc_fragment_overlap_conflict,
5508           { "Conflicting data in fragment overlap", "dcerpc.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE,
5509       NULL, 0x0, "Overlapping fragments contained conflicting data", HFILL }},
5510
5511         { &hf_dcerpc_fragment_multiple_tails,
5512           { "Multiple tail fragments found", "dcerpc.fragment.multipletails", FT_BOOLEAN, BASE_NONE,
5513       NULL, 0x0, "Several tails were found when defragmenting the packet", HFILL }},
5514
5515         { &hf_dcerpc_fragment_too_long_fragment,
5516           { "Fragment too long", "dcerpc.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE,
5517       NULL, 0x0, "Fragment contained data past end of packet", HFILL }},
5518
5519         { &hf_dcerpc_fragment_error,
5520           { "Defragmentation error", "dcerpc.fragment.error", FT_FRAMENUM, BASE_NONE,
5521       NULL, 0x0, "Defragmentation error due to illegal fragments", HFILL }},
5522
5523         { &hf_dcerpc_time,
5524           { "Time from request", "dcerpc.time", FT_RELATIVE_TIME, BASE_NONE,
5525       NULL, 0, "Time between Request and Response for DCE-RPC calls", HFILL }},
5526
5527         { &hf_dcerpc_reassembled_in,
5528       { "Reassembled PDU in frame", "dcerpc.reassembled_in", FT_FRAMENUM, BASE_NONE,
5529       NULL, 0x0, "The DCE/RPC PDU is completely reassembled in the packet with this number", HFILL }},
5530
5531         { &hf_dcerpc_unknown_if_id,
5532           { "Unknown DCERPC interface id", "dcerpc.unknown_if_id", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL }},
5533    };
5534     static gint *ett[] = {
5535         &ett_dcerpc,
5536         &ett_dcerpc_cn_flags,
5537         &ett_dcerpc_cn_ctx,
5538         &ett_dcerpc_cn_iface,
5539         &ett_dcerpc_cn_trans_syntax,
5540         &ett_dcerpc_drep,
5541         &ett_dcerpc_dg_flags1,
5542         &ett_dcerpc_dg_flags2,
5543         &ett_dcerpc_pointer_data,
5544         &ett_dcerpc_string,
5545         &ett_dcerpc_fragments,
5546         &ett_dcerpc_fragment,
5547         &ett_dcerpc_krb5_auth_verf,
5548     };
5549     module_t *dcerpc_module;
5550
5551     proto_dcerpc = proto_register_protocol ("DCE RPC", "DCERPC", "dcerpc");
5552     proto_register_field_array (proto_dcerpc, hf, array_length (hf));
5553     proto_register_subtree_array (ett, array_length (ett));
5554     register_init_routine (dcerpc_init_protocol);
5555     dcerpc_module = prefs_register_protocol (proto_dcerpc, NULL);
5556     prefs_register_bool_preference (dcerpc_module,
5557                                     "desegment_dcerpc",
5558                                     "Reassemble DCE/RPC messages spanning multiple TCP segments",
5559                                     "Whether the DCE/RPC dissector should reassemble messages spanning multiple TCP segments."
5560                                     " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
5561                                     &dcerpc_cn_desegment);
5562     prefs_register_bool_preference (dcerpc_module,
5563                                     "reassemble_dcerpc",
5564                                     "Reassemble DCE/RPC fragments",
5565                                     "Whether the DCE/RPC dissector should reassemble fragmented DCE/RPC PDUs",
5566                                     &dcerpc_reassemble);
5567     register_init_routine(dcerpc_reassemble_init);
5568     dcerpc_uuids = g_hash_table_new (dcerpc_uuid_hash, dcerpc_uuid_equal);
5569     dcerpc_tap=register_tap("dcerpc");
5570
5571     g_hook_list_init(&dcerpc_hooks_init_protos, sizeof(GHook));
5572 }
5573
5574 void
5575 proto_reg_handoff_dcerpc (void)
5576 {
5577     heur_dissector_add ("tcp", dissect_dcerpc_cn_bs, proto_dcerpc);
5578     heur_dissector_add ("netbios", dissect_dcerpc_cn_pk, proto_dcerpc);
5579     heur_dissector_add ("udp", dissect_dcerpc_dg, proto_dcerpc);
5580     heur_dissector_add ("smb_transact", dissect_dcerpc_cn_smbpipe, proto_dcerpc);
5581     heur_dissector_add ("smb2_heur_subdissectors", dissect_dcerpc_cn_smb2, proto_dcerpc);
5582     heur_dissector_add ("http", dissect_dcerpc_cn_bs, proto_dcerpc);
5583     dcerpc_smb_init(proto_dcerpc);
5584 }