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