remove wrong! string terminator detection
[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;
1336     char *s;
1337     header_field_info *hfinfo;
1338
1339     di=pinfo->private_data;
1340     if(di->conformant_run){
1341       /* just a run to handle conformant arrays, no scalars to dissect */
1342       return offset;
1343     }
1344
1345     if (add_subtree) {
1346         string_item = proto_tree_add_text(tree, tvb, offset, -1, "%s",
1347                                           proto_registrar_get_name(hfindex));
1348         string_tree = proto_item_add_subtree(string_item, ett_dcerpc_string);
1349     } else {
1350         string_item = NULL;
1351         string_tree = tree;
1352     }
1353
1354     /* NDR array header */
1355
1356     offset = dissect_ndr_uint32(tvb, offset, pinfo, string_tree, drep,
1357                                 hf_dcerpc_array_max_count, NULL);
1358
1359     offset = dissect_ndr_uint32(tvb, offset, pinfo, string_tree, drep,
1360                                 hf_dcerpc_array_offset, NULL);
1361
1362     offset = dissect_ndr_uint32(tvb, offset, pinfo, string_tree, drep,
1363                                 hf_dcerpc_array_actual_count, &len);
1364     buffer_len = size_is * len;
1365     hfinfo = proto_registrar_get_nth(hfindex);
1366
1367     /* Adjust offset */
1368     if (offset % size_is)
1369         offset += size_is - (offset % size_is);
1370     if (size_is == sizeof(guint16)) {
1371         /* XXX - use drep to determine the byte order? */
1372         s = tvb_fake_unicode(tvb, offset, buffer_len / 2, TRUE);
1373         /*
1374          * XXX - we don't support a string type with Unicode
1375          * characters, so if this is a string item, we make
1376          * its value be the "fake Unicode" string.
1377          */
1378         if (tree && buffer_len) {
1379             tvb_ensure_bytes_exist(tvb, offset, buffer_len);
1380             if (hfinfo->type == FT_STRING) {
1381                 proto_tree_add_string(string_tree, hfindex, tvb, offset,
1382                                       buffer_len, s);
1383             } else {
1384                 proto_tree_add_item(string_tree, hfindex, tvb, offset,
1385                                     buffer_len, drep[0] & 0x10);
1386             }
1387         }
1388     } else {
1389         /*
1390          * "tvb_get_ephemeral_string()" throws an exception if the entire string
1391          * isn't in the tvbuff.  If the length is bogus, this should
1392          * keep us from trying to allocate an immensely large buffer.
1393          * (It won't help if the length is *valid* but immensely large,
1394          * but that's another matter; in any case, that would happen only
1395          * if we had an immensely large tvbuff....)
1396          */
1397         tvb_ensure_bytes_exist(tvb, offset, buffer_len);
1398         s = tvb_get_ephemeral_string(tvb, offset, buffer_len);
1399         if (tree && buffer_len)
1400             proto_tree_add_item(string_tree, hfindex, tvb, offset,
1401                                 buffer_len, drep[0] & 0x10);
1402     }
1403
1404     if (string_item != NULL)
1405         proto_item_append_text(string_item, ": %s", s);
1406
1407     if (data)
1408             *data = s;
1409
1410     offset += buffer_len;
1411
1412     proto_item_set_end(string_item, tvb, offset);
1413
1414     return offset;
1415 }
1416
1417 /* Dissect an conformant varying string of chars.
1418    This corresponds to IDL of the form '[string] char *foo'.
1419
1420    XXX - at least according to the DCE RPC 1.1 spec, a string has
1421    a null terminator, which isn't necessary as a terminator for
1422    the transfer language (as there's a length), but is presumably
1423    there for the benefit of null-terminated-string languages
1424    such as C.  Is this ever used for purely counted strings?
1425    (Not that it matters if it is.) */
1426 int
1427 dissect_ndr_char_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
1428                         proto_tree *tree, guint8 *drep)
1429 {
1430     dcerpc_info *di;
1431     di=pinfo->private_data;
1432
1433     return dissect_ndr_cvstring(tvb, offset, pinfo, tree, drep,
1434                                 sizeof(guint8), di->hf_index,
1435                                 FALSE, NULL);
1436 }
1437
1438 /* Dissect a conformant varying string of wchars (wide characters).
1439    This corresponds to IDL of the form '[string] wchar *foo'
1440
1441    XXX - at least according to the DCE RPC 1.1 spec, a string has
1442    a null terminator, which isn't necessary as a terminator for
1443    the transfer language (as there's a length), but is presumably
1444    there for the benefit of null-terminated-string languages
1445    such as C.  Is this ever used for purely counted strings?
1446    (Not that it matters if it is.) */
1447 int
1448 dissect_ndr_wchar_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
1449                         proto_tree *tree, guint8 *drep)
1450 {
1451     dcerpc_info *di;
1452     di=pinfo->private_data;
1453
1454     return dissect_ndr_cvstring(tvb, offset, pinfo, tree, drep,
1455                                 sizeof(guint16), di->hf_index,
1456                                 FALSE, NULL);
1457 }
1458
1459 /* This function is aimed for PIDL useage and dissects a UNIQUE pointer to
1460  * unicode string.
1461  */
1462 int
1463 PIDL_dissect_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, int chsize, int hfindex, guint32 param)
1464 {
1465         dcerpc_info *di;
1466         char *s = NULL;
1467         gint levels = CB_STR_ITEM_LEVELS(param);
1468
1469         di=pinfo->private_data;
1470
1471         offset = dissect_ndr_cvstring(tvb, offset, pinfo, tree, drep,
1472                                 chsize, hfindex,
1473                                 FALSE, &s);
1474
1475         if(!di->conformant_run){
1476                 /* Append string to COL_INFO */
1477                 if (param & PIDL_SET_COL_INFO) {
1478                         if (check_col(pinfo->cinfo, COL_INFO))
1479                                 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", s);
1480                 }
1481                 /* Save string to dcv->private_data */
1482                 if((param & PIDL_STR_SAVE)
1483                 && (!pinfo->fd->flags.visited)){
1484                         dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
1485                         dcv->private_data = se_strdup(s);
1486                 }
1487                 /* Append string to upper-level proto_items */
1488                 if (levels > 0 && tree && s && s[0]) {
1489                         proto_item_append_text(tree, ": %s", s);
1490                         tree = tree->parent;
1491                         levels--;
1492                         if (levels > 0) {
1493                                 proto_item_append_text(tree, ": %s", s);
1494                                 tree = tree->parent;
1495                                 levels--;
1496                                 while (levels > 0) {
1497                                         proto_item_append_text(tree, " %s", s);
1498                                         tree = tree->parent;
1499                                         levels--;
1500                                 }
1501                         }
1502                 }
1503
1504         }
1505
1506         g_free(s);
1507         return offset;
1508 }
1509
1510 /* Dissect an NDR varying string of elements.
1511    The length of each element is given by the 'size_is' parameter;
1512    the elements are assumed to be characters or wide characters.
1513 */
1514 int
1515 dissect_ndr_vstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
1516                      proto_tree *tree, guint8 *drep, int size_is,
1517                      int hfindex, gboolean add_subtree, char **data)
1518 {
1519     dcerpc_info *di;
1520     proto_item *string_item;
1521     proto_tree *string_tree;
1522     guint32 len, buffer_len;
1523     char *s;
1524     header_field_info *hfinfo;
1525
1526     di=pinfo->private_data;
1527     if(di->conformant_run){
1528       /* just a run to handle conformant arrays, no scalars to dissect */
1529       return offset;
1530     }
1531
1532     if (add_subtree) {
1533         string_item = proto_tree_add_text(tree, tvb, offset, -1, "%s",
1534                                           proto_registrar_get_name(hfindex));
1535         string_tree = proto_item_add_subtree(string_item, ett_dcerpc_string);
1536     } else {
1537         string_item = NULL;
1538         string_tree = tree;
1539     }
1540
1541     /* NDR array header */
1542     offset = dissect_ndr_uint32(tvb, offset, pinfo, string_tree, drep,
1543                                 hf_dcerpc_array_offset, NULL);
1544
1545     offset = dissect_ndr_uint32(tvb, offset, pinfo, string_tree, drep,
1546                                 hf_dcerpc_array_actual_count, &len);
1547
1548     buffer_len = size_is * len;
1549
1550     /* Adjust offset */
1551     if (offset % size_is)
1552         offset += size_is - (offset % size_is);
1553
1554     if (size_is == sizeof(guint16)) {
1555         /* XXX - use drep to determine the byte order? */
1556         s = tvb_fake_unicode(tvb, offset, buffer_len / 2, TRUE);
1557         /*
1558          * XXX - we don't support a string type with Unicode
1559          * characters, so if this is a string item, we make
1560          * its value be the "fake Unicode" string.
1561          */
1562         if (tree && buffer_len) {
1563             hfinfo = proto_registrar_get_nth(hfindex);
1564             tvb_ensure_bytes_exist(tvb, offset, buffer_len);
1565             if (hfinfo->type == FT_STRING) {
1566                 proto_tree_add_string(string_tree, hfindex, tvb, offset,
1567                                       buffer_len, s);
1568             } else {
1569                 proto_tree_add_item(string_tree, hfindex, tvb, offset,
1570                                     buffer_len, drep[0] & 0x10);
1571             }
1572         }
1573     } else {
1574         /*
1575          * "tvb_get_ephemeral_string()" throws an exception if the entire string
1576          * isn't in the tvbuff.  If the length is bogus, this should
1577          * keep us from trying to allocate an immensely large buffer.
1578          * (It won't help if the length is *valid* but immensely large,
1579          * but that's another matter; in any case, that would happen only
1580          * if we had an immensely large tvbuff....)
1581          */
1582         tvb_ensure_bytes_exist(tvb, offset, buffer_len);
1583         s = tvb_get_ephemeral_string(tvb, offset, buffer_len);
1584         if (tree && buffer_len)
1585             proto_tree_add_item(string_tree, hfindex, tvb, offset,
1586                                 buffer_len, drep[0] & 0x10);
1587     }
1588
1589     if (string_item != NULL)
1590         proto_item_append_text(string_item, ": %s", s);
1591
1592     if (data)
1593             *data = s;
1594
1595     offset += buffer_len;
1596
1597     proto_item_set_end(string_item, tvb, offset);
1598
1599     return offset;
1600 }
1601
1602 /* Dissect an varying string of chars.
1603    This corresponds to IDL of the form '[string] char *foo'.
1604
1605    XXX - at least according to the DCE RPC 1.1 spec, a string has
1606    a null terminator, which isn't necessary as a terminator for
1607    the transfer language (as there's a length), but is presumably
1608    there for the benefit of null-terminated-string languages
1609    such as C.  Is this ever used for purely counted strings?
1610    (Not that it matters if it is.) */
1611 int
1612 dissect_ndr_char_vstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
1613                         proto_tree *tree, guint8 *drep)
1614 {
1615     dcerpc_info *di;
1616     di=pinfo->private_data;
1617
1618     return dissect_ndr_vstring(tvb, offset, pinfo, tree, drep,
1619                                 sizeof(guint8), di->hf_index,
1620                                 FALSE, NULL);
1621 }
1622
1623 /* Dissect a varying string of wchars (wide characters).
1624    This corresponds to IDL of the form '[string] wchar *foo'
1625
1626    XXX - at least according to the DCE RPC 1.1 spec, a string has
1627    a null terminator, which isn't necessary as a terminator for
1628    the transfer language (as there's a length), but is presumably
1629    there for the benefit of null-terminated-string languages
1630    such as C.  Is this ever used for purely counted strings?
1631    (Not that it matters if it is.) */
1632 int
1633 dissect_ndr_wchar_vstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
1634                         proto_tree *tree, guint8 *drep)
1635 {
1636     dcerpc_info *di;
1637     di=pinfo->private_data;
1638
1639     return dissect_ndr_vstring(tvb, offset, pinfo, tree, drep,
1640                                 sizeof(guint16), di->hf_index,
1641                                 FALSE, NULL);
1642 }
1643
1644
1645 /* ndr pointer handling */
1646 /* list of pointers encountered so far */
1647 static GSList *ndr_pointer_list = NULL;
1648
1649 /* position where in the list to insert newly encountered pointers */
1650 static int ndr_pointer_list_pos=0;
1651
1652 /* boolean controlling whether pointers are top-level or embedded */
1653 static gboolean pointers_are_top_level = TRUE;
1654
1655 /* as a kludge, we represent all embedded reference pointers as id==-1
1656    hoping that his will not collide with any non-ref pointers */
1657 typedef struct ndr_pointer_data {
1658         guint32 id;
1659         proto_item *item;       /* proto_item for pointer */
1660         proto_tree *tree;       /* subtree of above item */
1661         dcerpc_dissect_fnct_t *fnct; /*if non-NULL, we have not called it yet*/
1662         int hf_index;
1663         dcerpc_callback_fnct_t *callback;
1664         void *callback_args;
1665 } ndr_pointer_data_t;
1666
1667 void
1668 init_ndr_pointer_list(packet_info *pinfo)
1669 {
1670         dcerpc_info *di;
1671
1672         di=pinfo->private_data;
1673         di->conformant_run=0;
1674
1675         while(ndr_pointer_list){
1676                 ndr_pointer_data_t *npd;
1677
1678                 npd=g_slist_nth_data(ndr_pointer_list, 0);
1679                 ndr_pointer_list=g_slist_remove(ndr_pointer_list, npd);
1680                 g_free(npd);
1681         }
1682
1683         ndr_pointer_list=NULL;
1684         ndr_pointer_list_pos=0;
1685         pointers_are_top_level=TRUE;
1686 }
1687
1688 int
1689 dissect_deferred_pointers(packet_info *pinfo, tvbuff_t *tvb, int offset, guint8 *drep)
1690 {
1691         int found_new_pointer;
1692         dcerpc_info *di;
1693         int old_offset;
1694         int next_pointer;
1695
1696         next_pointer=0;
1697         di=pinfo->private_data;
1698         do{
1699                 int i, len;
1700
1701                 found_new_pointer=0;
1702                 len=g_slist_length(ndr_pointer_list);
1703                 for(i=next_pointer;i<len;i++){
1704                         ndr_pointer_data_t *tnpd;
1705                         tnpd=g_slist_nth_data(ndr_pointer_list, i);
1706                         if(tnpd->fnct){
1707                                 dcerpc_dissect_fnct_t *fnct;
1708
1709                                 next_pointer=i+1;
1710                                 found_new_pointer=1;
1711                                 fnct=tnpd->fnct;
1712                                 tnpd->fnct=NULL;
1713                                 ndr_pointer_list_pos=i+1;
1714                                 di->hf_index=tnpd->hf_index;
1715                                 /* first a run to handle any conformant
1716                                    array headers */
1717                                 di->conformant_run=1;
1718                                 di->conformant_eaten=0;
1719                                 old_offset = offset;
1720                                 offset = (*(fnct))(tvb, offset, pinfo, NULL, drep);
1721
1722                                 DISSECTOR_ASSERT((offset-old_offset)==di->conformant_eaten);
1723                                 /* This is to check for any bugs in the dissectors.
1724                                  *
1725                                  * Basically, the NDR representation will store all
1726                                  * arrays in two blocks, one block with the dimension
1727                                  * discreption, like size, number of elements and such,
1728                                  * and another block that contains the actual data stored
1729                                  * in the array.
1730                                  * If the array is embedded directly inside another,
1731                                  * encapsulating aggregate type, like a union or struct,
1732                                  * then these two blocks will be stored at different places
1733                                  * in the bytestream, with other data between the blocks.
1734                                  *
1735                                  * For this reason, all pointers to types (both aggregate
1736                                  * and scalar, for simplicity no distinction is made)
1737                                  * will have its dissector called twice.
1738                                  * The dissector will first be called with conformant_run==1
1739                                  * in which mode the dissector MUST NOT consume any data from
1740                                  * the tvbuff (i.e. may not dissect anything) except the
1741                                  * initial control block for arrays.
1742                                  * The second time the dissector is called, with
1743                                  * conformant_run==0, all other data for the type will be
1744                                  * dissected.
1745                                  *
1746                                  * All dissect_ndr_<type> dissectors are already prepared
1747                                  * for this and knows when it should eat data from the tvb
1748                                  * and when not to, so implementors of dissectors will
1749                                  * normally not need to worry about this or even know about
1750                                  * it. However, if a dissector for an aggregate type calls
1751                                  * a subdissector from outside packet-dcerpc.c, such as
1752                                  * the dissector in packet-smb.c for NT Security Descriptors
1753                                  * as an example, then it is VERY important to encapsulate
1754                                  * this call to an external subdissector with the appropriate
1755                                  * test for conformant_run, i.e. it will need something like
1756                                  *
1757                                  *      dcerpc_info *di;
1758                                  *
1759                                  *      di=pinfo->private_data;
1760                                  *      if(di->conformant_run){
1761                                  *              return offset;
1762                                  *      }
1763                                  *
1764                                  * to make sure it makes the right thing.
1765                                  * This assert will signal when someone has forgotten to
1766                                  * make the dissector aware of this requirement.
1767                                  */
1768
1769                                 /* now we dissect the actual pointer */
1770                                 di->conformant_run=0;
1771                                 old_offset = offset;
1772                                 offset = (*(fnct))(tvb, offset, pinfo, tnpd->tree, drep);
1773                                 if (tnpd->callback)
1774                                         tnpd->callback(pinfo, tnpd->tree, tnpd->item, tvb, old_offset, offset, tnpd->callback_args);
1775                                 break;
1776                         }
1777                 }
1778         } while(found_new_pointer);
1779
1780         return offset;
1781 }
1782
1783
1784 static void
1785 add_pointer_to_list(packet_info *pinfo, proto_tree *tree, proto_item *item,
1786                     dcerpc_dissect_fnct_t *fnct, guint32 id, int hf_index,
1787                     dcerpc_callback_fnct_t *callback, void *callback_args)
1788 {
1789         ndr_pointer_data_t *npd;
1790
1791         /* check if this pointer is valid */
1792         if(id!=0xffffffff){
1793                 dcerpc_info *di;
1794                 dcerpc_call_value *value;
1795
1796                 di=pinfo->private_data;
1797                 value=di->call_data;
1798
1799                 if(di->ptype == PDU_REQ){
1800                         if(!(pinfo->fd->flags.visited)){
1801                                 if(id>value->max_ptr){
1802                                         value->max_ptr=id;
1803                                 }
1804                         }
1805                 } else {
1806                         /* if we havent seen the request bail out since we cant
1807                            know whether this is the first non-NULL instance
1808                            or not */
1809                         if(value->req_frame==0){
1810                                 /* XXX THROW EXCEPTION */
1811                         }
1812
1813                         /* We saw this one in the request frame, nothing to
1814                            dissect later */
1815                         if(id<=value->max_ptr){
1816                                 return;
1817                         }
1818                 }
1819         }
1820
1821         npd=g_malloc(sizeof(ndr_pointer_data_t));
1822         npd->id=id;
1823         npd->tree=tree;
1824         npd->item=item;
1825         npd->fnct=fnct;
1826         npd->hf_index=hf_index;
1827         npd->callback=callback;
1828         npd->callback_args=callback_args;
1829         ndr_pointer_list = g_slist_insert(ndr_pointer_list, npd,
1830                                         ndr_pointer_list_pos);
1831         ndr_pointer_list_pos++;
1832 }
1833
1834
1835 static int
1836 find_pointer_index(guint32 id)
1837 {
1838         ndr_pointer_data_t *npd;
1839         int i,len;
1840
1841         len=g_slist_length(ndr_pointer_list);
1842         for(i=0;i<len;i++){
1843                 npd=g_slist_nth_data(ndr_pointer_list, i);
1844                 if(npd){
1845                         if(npd->id==id){
1846                                 return i;
1847                         }
1848                 }
1849         }
1850
1851         return -1;
1852 }
1853
1854 /* This function dissects an NDR pointer and stores the callback for later
1855  * deferred dissection.
1856  *
1857  *   fnct is the callback function for when we have reached this object in
1858  *   the bytestream.
1859  *
1860  *   type is what type of pointer.
1861  *
1862  *   this is text is what text we should put in any created tree node.
1863  *
1864  *   hf_index is what hf value we want to pass to the callback function when
1865  *   it is called, the callback can later pich this one up from di->hf_index.
1866  *
1867  *   callback is executed after the pointer has been dereferenced.
1868  *
1869  *   callback_args is passed as an argument to the callback function
1870  *
1871  * See packet-dcerpc-samr.c for examples
1872  */
1873 int
1874 dissect_ndr_pointer_cb(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1875                     proto_tree *tree, guint8 *drep, dcerpc_dissect_fnct_t *fnct,
1876                     int type, const char *text, int hf_index,
1877                     dcerpc_callback_fnct_t *callback, void *callback_args)
1878 {
1879         dcerpc_info *di;
1880         proto_tree *tr = NULL;
1881         gint start_offset = offset;
1882
1883         di=pinfo->private_data;
1884         if(di->conformant_run){
1885                 /* this call was only for dissecting the header for any
1886                    embedded conformant array. we will not parse any
1887                    pointers in this mode.
1888                 */
1889                 return offset;
1890         }
1891         /*TOP LEVEL REFERENCE POINTER*/
1892         if( pointers_are_top_level
1893         &&(type==NDR_POINTER_REF) ){
1894                 proto_item *item;
1895
1896                 /* we must find out a nice way to do the length here */
1897                 item=proto_tree_add_text(tree, tvb, offset, 0,
1898                         "%s", text);
1899                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1900
1901                 add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff,
1902                                     hf_index, callback, callback_args);
1903                 goto after_ref_id;
1904         }
1905
1906         /*TOP LEVEL FULL POINTER*/
1907         if( pointers_are_top_level
1908         && (type==NDR_POINTER_PTR) ){
1909                 int idx;
1910                 guint32 id;
1911                 proto_item *item;
1912
1913                 /* get the referent id */
1914                 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
1915
1916                 tvb_ensure_bytes_exist(tvb, offset-4, 4);
1917                 /* we got a NULL pointer */
1918                 if(id==0){
1919                         proto_tree_add_text(tree, tvb, offset-4, 4,
1920                                 "(NULL pointer) %s",text);
1921                         goto after_ref_id;
1922                 }
1923
1924                 /* see if we have seen this pointer before */
1925                 idx=find_pointer_index(id);
1926
1927                 /* we have seen this pointer before */
1928                 if(idx>=0){
1929                         proto_tree_add_text(tree, tvb, offset-4, 4,
1930                                 "(duplicate PTR) %s",text);
1931                         goto after_ref_id;
1932                 }
1933
1934                 /* new pointer */
1935                 item=proto_tree_add_text(tree, tvb, offset-4, 4,
1936                         "%s", text);
1937                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1938                 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
1939                 add_pointer_to_list(pinfo, tr, item, fnct, id, hf_index,
1940                                     callback, callback_args);
1941                 goto after_ref_id;
1942         }
1943         /*TOP LEVEL UNIQUE POINTER*/
1944         if( pointers_are_top_level
1945         && (type==NDR_POINTER_UNIQUE) ){
1946                 guint32 id;
1947                 proto_item *item;
1948
1949                 /* get the referent id */
1950                 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
1951
1952                 tvb_ensure_bytes_exist(tvb, offset-4, 4);
1953                 /* we got a NULL pointer */
1954                 if(id==0){
1955                         proto_tree_add_text(tree, tvb, offset-4, 4,
1956                                 "(NULL pointer) %s",text);
1957                         goto after_ref_id;
1958                 }
1959
1960                 /* new pointer */
1961                 item=proto_tree_add_text(tree, tvb, offset-4, 4,
1962                         "%s", text);
1963                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1964                 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
1965                 add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff,
1966                                     hf_index, callback, callback_args);
1967                 goto after_ref_id;
1968         }
1969
1970         /*EMBEDDED REFERENCE POINTER*/
1971         if( (!pointers_are_top_level)
1972         && (type==NDR_POINTER_REF) ){
1973                 guint32 id;
1974                 proto_item *item;
1975
1976                 /* get the referent id */
1977                 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
1978
1979                 tvb_ensure_bytes_exist(tvb, offset-4, 4);
1980                 /* new pointer */
1981                 item=proto_tree_add_text(tree, tvb, offset-4, 4,
1982                         "%s",text);
1983                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1984                 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
1985                 add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff,
1986                                     hf_index, callback, callback_args);
1987                 goto after_ref_id;
1988         }
1989
1990         /*EMBEDDED UNIQUE POINTER*/
1991         if( (!pointers_are_top_level)
1992         && (type==NDR_POINTER_UNIQUE) ){
1993                 guint32 id;
1994                 proto_item *item;
1995
1996                 /* get the referent id */
1997                 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
1998
1999                 tvb_ensure_bytes_exist(tvb, offset-4, 4);
2000                 /* we got a NULL pointer */
2001                 if(id==0){
2002                         proto_tree_add_text(tree, tvb, offset-4, 4,
2003                                 "(NULL pointer) %s", text);
2004                         goto after_ref_id;
2005                 }
2006
2007                 /* new pointer */
2008                 item=proto_tree_add_text(tree, tvb, offset-4, 4,
2009                         "%s",text);
2010                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
2011                 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
2012                 add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff,
2013                                     hf_index, callback, callback_args);
2014                 goto after_ref_id;
2015         }
2016
2017         /*EMBEDDED FULL POINTER*/
2018         if( (!pointers_are_top_level)
2019         && (type==NDR_POINTER_PTR) ){
2020                 int idx;
2021                 guint32 id;
2022                 proto_item *item;
2023
2024                 /* get the referent id */
2025                 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
2026                 tvb_ensure_bytes_exist(tvb, offset-4, 4);
2027                 /* we got a NULL pointer */
2028                 if(id==0){
2029                         proto_tree_add_text(tree, tvb, offset-4, 4,
2030                                 "(NULL pointer) %s",text);
2031                         goto after_ref_id;
2032                 }
2033
2034                 /* see if we have seen this pointer before */
2035                 idx=find_pointer_index(id);
2036
2037                 /* we have seen this pointer before */
2038                 if(idx>=0){
2039                         proto_tree_add_text(tree, tvb, offset-4, 4,
2040                                 "(duplicate PTR) %s",text);
2041                         goto after_ref_id;
2042                 }
2043
2044                 /* new pointer */
2045                 item=proto_tree_add_text(tree, tvb, offset-4, 4,
2046                         "%s", text);
2047                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
2048                 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
2049                 add_pointer_to_list(pinfo, tr, item, fnct, id, hf_index,
2050                                     callback, callback_args);
2051                 goto after_ref_id;
2052         }
2053
2054
2055 after_ref_id:
2056         /* After each top level pointer we have dissected we have to
2057            dissect all deferrals before we move on to the next top level
2058            argument */
2059         if(pointers_are_top_level==TRUE){
2060                 pointers_are_top_level=FALSE;
2061                 offset = dissect_deferred_pointers(pinfo, tvb, offset, drep);
2062                 pointers_are_top_level=TRUE;
2063         }
2064
2065         /* Set the length for the new subtree */
2066         if (tr){
2067                 proto_item_set_len(tr, offset-start_offset);
2068         }
2069         return offset;
2070 }
2071
2072 int
2073 dissect_ndr_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2074                     proto_tree *tree, guint8 *drep, dcerpc_dissect_fnct_t *fnct,
2075                     int type, const char *text, int hf_index)
2076 {
2077         return dissect_ndr_pointer_cb(
2078                 tvb, offset, pinfo, tree, drep, fnct, type, text, hf_index,
2079                 NULL, NULL);
2080 }
2081 int
2082 dissect_ndr_toplevel_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2083                     proto_tree *tree, guint8 *drep, dcerpc_dissect_fnct_t *fnct,
2084                     int type, const char *text, int hf_index)
2085 {
2086         int ret;
2087
2088         pointers_are_top_level=TRUE;
2089         ret=dissect_ndr_pointer_cb(
2090                 tvb, offset, pinfo, tree, drep, fnct, type, text, hf_index,
2091                 NULL, NULL);
2092         return ret;
2093 }
2094 int
2095 dissect_ndr_embedded_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2096                     proto_tree *tree, guint8 *drep, dcerpc_dissect_fnct_t *fnct,
2097                     int type, const char *text, int hf_index)
2098 {
2099         int ret;
2100
2101         pointers_are_top_level=FALSE;
2102         ret=dissect_ndr_pointer_cb(
2103                 tvb, offset, pinfo, tree, drep, fnct, type, text, hf_index,
2104                 NULL, NULL);
2105         return ret;
2106 }
2107
2108 static void
2109 show_stub_data (tvbuff_t *tvb, gint offset, proto_tree *dcerpc_tree,
2110                 dcerpc_auth_info *auth_info, gboolean is_encrypted)
2111 {
2112   int length, plain_length, auth_pad_len;
2113   guint auth_pad_offset;
2114
2115     /*
2116      * We don't show stub data unless we have some in the tvbuff;
2117      * however, in the protocol tree, we show, as the number of
2118      * bytes, the reported number of bytes, not the number of bytes
2119      * that happen to be in the tvbuff.
2120      */
2121   if (tvb_length_remaining (tvb, offset) > 0) {
2122         auth_pad_len = auth_info?auth_info->auth_pad_len:0;
2123     length = tvb_reported_length_remaining (tvb, offset);
2124
2125         /* if auth_pad_len is larger than length then we ignore auth_pad_len totally */
2126         plain_length = length - auth_pad_len;
2127           if (plain_length < 1) {
2128             plain_length = length;
2129             auth_pad_len = 0;
2130           }
2131           auth_pad_offset = offset + plain_length;
2132     if (auth_info != NULL &&
2133         auth_info->auth_level == DCE_C_AUTHN_LEVEL_PKT_PRIVACY) {
2134       if (is_encrypted) {
2135                     tvb_ensure_bytes_exist(tvb, offset, length);
2136                 proto_tree_add_text(dcerpc_tree, tvb, offset, length,
2137                 "Encrypted stub data (%d byte%s)",
2138                 length, plurality(length, "", "s"));
2139                 /* is the padding is still inside the encrypted blob, don't display it explicit */
2140                     auth_pad_len = 0;
2141       } 
2142       else {
2143                     tvb_ensure_bytes_exist(tvb, offset, plain_length);
2144         proto_tree_add_text(dcerpc_tree, tvb, offset, plain_length,
2145             "Decrypted stub data (%d byte%s)",
2146             plain_length, plurality(plain_length, "", "s"));
2147       }
2148     } 
2149     else {
2150            tvb_ensure_bytes_exist(tvb, offset, plain_length);
2151      proto_tree_add_text (dcerpc_tree, tvb, offset, plain_length,
2152             "Stub data (%d byte%s)", plain_length,
2153             plurality(plain_length, "", "s"));
2154     }
2155     /* If there is auth padding at the end of the stub, display it */
2156     if (auth_pad_len != 0) {
2157                 tvb_ensure_bytes_exist(tvb, auth_pad_offset, auth_pad_len);
2158       proto_tree_add_text (dcerpc_tree, tvb, auth_pad_offset,
2159                            auth_pad_len, "Auth Padding (%u byte%s)",
2160                            auth_pad_len, plurality(auth_pad_len, "", "s"));
2161     }
2162   }
2163 }
2164
2165 static int
2166 dcerpc_try_handoff (packet_info *pinfo, proto_tree *tree,
2167                     proto_tree *dcerpc_tree,
2168                     tvbuff_t *volatile tvb, tvbuff_t *decrypted_tvb,
2169                     guint8 *drep, dcerpc_info *info,
2170                     dcerpc_auth_info *auth_info)
2171 {
2172     volatile gint offset = 0;
2173     dcerpc_uuid_key key;
2174     dcerpc_uuid_value *sub_proto;
2175     proto_tree *volatile sub_tree = NULL;
2176     dcerpc_sub_dissector *proc;
2177     const gchar *name = NULL;
2178     dcerpc_dissect_fnct_t *volatile sub_dissect;
2179     const char *volatile saved_proto;
2180     void *volatile saved_private_data;
2181     guint length = 0, reported_length = 0;
2182     tvbuff_t *volatile stub_tvb;
2183     volatile guint auth_pad_len;
2184     volatile int auth_pad_offset;
2185     proto_item *sub_item=NULL;
2186     proto_item *pi, *hidden_item;
2187
2188     key.uuid = info->call_data->uuid;
2189     key.ver = info->call_data->ver;
2190
2191
2192     if ((sub_proto = g_hash_table_lookup (dcerpc_uuids, &key)) == NULL
2193          || !proto_is_protocol_enabled(sub_proto->proto)) {
2194         /*
2195          * We don't have a dissector for this UUID, or the protocol
2196          * for that UUID is disabled.
2197          */
2198
2199         hidden_item = proto_tree_add_boolean(dcerpc_tree, hf_dcerpc_unknown_if_id,
2200                                                   tvb, offset, 0, TRUE);
2201         PROTO_ITEM_SET_HIDDEN(hidden_item);
2202         if (check_col (pinfo->cinfo, COL_INFO)) {
2203                 col_append_fstr (pinfo->cinfo, COL_INFO, " %s V%u",
2204                         guids_resolve_uuid_to_str(&info->call_data->uuid), info->call_data->ver);
2205         }
2206
2207         if (decrypted_tvb != NULL) {
2208             show_stub_data (decrypted_tvb, 0, dcerpc_tree, auth_info,
2209                             FALSE);
2210         } else
2211             show_stub_data (tvb, 0, dcerpc_tree, auth_info, TRUE);
2212         return -1;
2213     }
2214
2215     for (proc = sub_proto->procs; proc->name; proc++) {
2216         if (proc->num == info->call_data->opnum) {
2217             name = proc->name;
2218             break;
2219         }
2220     }
2221
2222     if (!name)
2223         name = "Unknown?!";
2224
2225     if (check_col (pinfo->cinfo, COL_PROTOCOL)) {
2226         col_set_str (pinfo->cinfo, COL_PROTOCOL, sub_proto->name);
2227     }
2228
2229     if (check_col (pinfo->cinfo, COL_INFO)) {
2230         col_add_fstr (pinfo->cinfo, COL_INFO, "%s %s",
2231                       name, (info->ptype == PDU_REQ) ? "request" : "response");
2232     }
2233
2234     sub_dissect = (info->ptype == PDU_REQ) ?
2235             proc->dissect_rqst : proc->dissect_resp;
2236
2237     if (tree) {
2238         sub_item = proto_tree_add_item (tree, sub_proto->proto_id,
2239                                         (decrypted_tvb != NULL)?decrypted_tvb:tvb,
2240                                         0, -1, FALSE);
2241
2242         if (sub_item) {
2243             sub_tree = proto_item_add_subtree (sub_item, sub_proto->ett);
2244             proto_item_append_text(sub_item, ", %s", name);
2245         }
2246
2247         /*
2248          * Put the operation number into the tree along with
2249          * the operation's name.
2250          */
2251         if (sub_proto->opnum_hf != -1)
2252                 proto_tree_add_uint_format(sub_tree, sub_proto->opnum_hf,
2253                                            tvb, 0, 0, info->call_data->opnum,
2254                                            "Operation: %s (%u)",
2255                                            name, info->call_data->opnum);
2256         else
2257                 proto_tree_add_uint_format(sub_tree, hf_dcerpc_op, tvb,
2258                                            0, 0, info->call_data->opnum,
2259                                            "Operation: %s (%u)",
2260                                            name, info->call_data->opnum);
2261
2262         if(info->ptype == PDU_REQ && info->call_data->rep_frame!=0) {
2263             pi = proto_tree_add_uint(sub_tree, hf_dcerpc_response_in,
2264                                      tvb, 0, 0, info->call_data->rep_frame);
2265             PROTO_ITEM_SET_GENERATED(pi);
2266         }
2267         if(info->ptype == PDU_RESP && info->call_data->req_frame!=0) {
2268             pi = proto_tree_add_uint(sub_tree, hf_dcerpc_request_in,
2269                                      tvb, 0, 0, info->call_data->req_frame);
2270             PROTO_ITEM_SET_GENERATED(pi);
2271         }
2272     } /* tree */
2273
2274     if (decrypted_tvb != NULL) {
2275         /* Either there was no encryption or we successfully decrypted
2276            the encrypted payload. */
2277         if (sub_dissect) {
2278             /* We have a subdissector - call it. */
2279             saved_proto = pinfo->current_proto;
2280             saved_private_data = pinfo->private_data;
2281             pinfo->current_proto = sub_proto->name;
2282             pinfo->private_data = (void *)info;
2283
2284             init_ndr_pointer_list(pinfo);
2285
2286             length = tvb_length(decrypted_tvb);
2287             reported_length = tvb_reported_length(decrypted_tvb);
2288
2289             /*
2290              * Remove the authentication padding from the stub data.
2291              */
2292             if (auth_info != NULL && auth_info->auth_pad_len != 0) {
2293                 if (reported_length >= auth_info->auth_pad_len) {
2294                     /*
2295                      * OK, the padding length isn't so big that it
2296                      * exceeds the stub length.  Trim the reported
2297                      * length of the tvbuff.
2298                      */
2299                     reported_length -= auth_info->auth_pad_len;
2300
2301                     /*
2302                      * If that exceeds the actual amount of data in
2303                      * the tvbuff (which means we have at least one
2304                      * byte of authentication padding in the tvbuff),
2305                      * trim the actual amount.
2306                      */
2307                     if (length > reported_length)
2308                         length = reported_length;
2309
2310                     stub_tvb = tvb_new_subset(decrypted_tvb, 0, length, reported_length);
2311                     auth_pad_len = auth_info->auth_pad_len;
2312                     auth_pad_offset = reported_length;
2313                 } else {
2314                     /*
2315                      * The padding length exceeds the stub length.
2316                      * Don't bother dissecting the stub, trim the padding
2317                      * length to what's in the stub data, and show the
2318                      * entire stub as authentication padding.
2319                      */
2320                     stub_tvb = NULL;
2321                     auth_pad_len = reported_length;
2322                     auth_pad_offset = 0;
2323                     length = 0;
2324                     reported_length = 0;
2325                 }
2326             } else {
2327                 /*
2328                  * No authentication padding.
2329                  */
2330                 stub_tvb = decrypted_tvb;
2331                 auth_pad_len = 0;
2332                 auth_pad_offset = 0;
2333             }
2334
2335             if (sub_item) {
2336                 proto_item_set_len(sub_item, length);
2337             }
2338
2339             if (stub_tvb != NULL) {
2340                 /*
2341                  * Catch all exceptions other than BoundsError, so that even
2342                  * if the stub data is bad, we still show the authentication
2343                  * padding, if any.
2344                  *
2345                  * If we get BoundsError, it means the frame was cut short
2346                  * by a snapshot length, so there's nothing more to
2347                  * dissect; just re-throw that exception.
2348                  */
2349                 TRY {
2350                     int remaining;
2351
2352                     offset = sub_dissect (stub_tvb, 0, pinfo, sub_tree,
2353                                           drep);
2354
2355                     /* If we have a subdissector and it didn't dissect all
2356                        data in the tvb, make a note of it. */
2357                     remaining = tvb_reported_length_remaining(stub_tvb, offset);
2358                     if (remaining > 0) {
2359                         proto_tree_add_text(sub_tree, stub_tvb, offset,
2360                                             remaining,
2361                                             "[Long frame (%d byte%s)]",
2362                                             remaining,
2363                                             plurality(remaining, "", "s"));
2364                         if (check_col(pinfo->cinfo, COL_INFO))
2365                             col_append_fstr(pinfo->cinfo, COL_INFO,
2366                                             "[Long frame (%d byte%s)]",
2367                                             remaining,
2368                                             plurality(remaining, "", "s"));
2369
2370                     }
2371                 } CATCH(BoundsError) {
2372                     RETHROW;
2373                 } CATCH_ALL {
2374                     show_exception(stub_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
2375                 } ENDTRY;
2376             }
2377
2378             /* If there is auth padding at the end of the stub, display it */
2379             if (auth_pad_len != 0) {
2380                 tvb_ensure_bytes_exist(tvb, auth_pad_offset, auth_pad_len);
2381                 proto_tree_add_text (sub_tree, decrypted_tvb, auth_pad_offset,
2382                                      auth_pad_len,
2383                                      "Auth Padding (%u byte%s)",
2384                                      auth_pad_len,
2385                                      plurality(auth_pad_len, "", "s"));
2386             }
2387
2388             pinfo->current_proto = saved_proto;
2389             pinfo->private_data = saved_private_data;
2390         } else {
2391             /* No subdissector - show it as stub data. */
2392             if(decrypted_tvb){
2393                show_stub_data (decrypted_tvb, 0, sub_tree, auth_info, FALSE);
2394             } else {
2395                show_stub_data (tvb, 0, sub_tree, auth_info, TRUE);
2396             }
2397         }
2398     } else
2399         show_stub_data (tvb, 0, sub_tree, auth_info, TRUE);
2400
2401     tap_queue_packet(dcerpc_tap, pinfo, info);
2402     return 0;
2403 }
2404
2405 static int
2406 dissect_dcerpc_verifier (tvbuff_t *tvb, packet_info *pinfo,
2407                          proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr,
2408                          dcerpc_auth_info *auth_info)
2409 {
2410     int auth_offset;
2411
2412     auth_info->auth_data = NULL;
2413
2414     if (auth_info->auth_size != 0) {
2415         dcerpc_auth_subdissector_fns *auth_fns;
2416         tvbuff_t *auth_tvb;
2417
2418         auth_offset = hdr->frag_len - hdr->auth_len;
2419
2420         auth_tvb = tvb_new_subset(tvb, auth_offset, hdr->auth_len,
2421                                   hdr->auth_len);
2422
2423         auth_info->auth_data = auth_tvb;
2424
2425         if ((auth_fns = get_auth_subdissector_fns(auth_info->auth_level,
2426                                                   auth_info->auth_type))) {
2427             /*
2428              * Catch all exceptions, so that even if the verifier is bad
2429              * or we don't have all of it, we still show the stub data.
2430              */
2431             TRY {
2432                 dissect_auth_verf(auth_tvb, pinfo, dcerpc_tree, auth_fns,
2433                                   hdr, auth_info);
2434             } CATCH_ALL {
2435                 show_exception(auth_tvb, pinfo, dcerpc_tree, EXCEPT_CODE, GET_MESSAGE);
2436             } ENDTRY;
2437         } else {
2438             tvb_ensure_bytes_exist(tvb, 0, hdr->auth_len);
2439             proto_tree_add_text (dcerpc_tree, auth_tvb, 0, hdr->auth_len,
2440                                  "Auth Verifier");
2441         }
2442     }
2443
2444     return hdr->auth_len;
2445 }
2446
2447 static void
2448 dissect_dcerpc_cn_auth (tvbuff_t *tvb, int stub_offset, packet_info *pinfo,
2449                         proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr,
2450                         gboolean are_credentials, dcerpc_auth_info *auth_info)
2451 {
2452     volatile int offset;
2453
2454     /*
2455      * Initially set auth_level and auth_type to zero to indicate that we
2456      * haven't yet seen any authentication level information.
2457      */
2458     auth_info->auth_level = 0;
2459     auth_info->auth_type = 0;
2460     auth_info->auth_size = 0;
2461     auth_info->auth_pad_len = 0;
2462
2463     /*
2464      * The authentication information is at the *end* of the PDU; in
2465      * request and response PDUs, the request and response stub data
2466      * come before it.
2467      *
2468      * Is there any authentication data (i.e., is the authentication length
2469      * non-zero), and is the authentication length valid (i.e., is it, plus
2470      * 8 bytes for the type/level/pad length/reserved/context id, less than
2471      * or equal to the fragment length minus the starting offset of the
2472      * stub data?)
2473      */
2474
2475     if (hdr->auth_len
2476         && (hdr->auth_len + 8 <= hdr->frag_len - stub_offset)) {
2477
2478         /*
2479          * Yes, there is authentication data, and the length is valid.
2480          * Do we have all the bytes of stub data?
2481          * (If not, we'd throw an exception dissecting *that*, so don't
2482          * bother trying to dissect the authentication information and
2483          * throwing another exception there.)
2484          */
2485         offset = hdr->frag_len - (hdr->auth_len + 8);
2486         if (offset == 0 || tvb_offset_exists(tvb, offset - 1)) {
2487             /*
2488              * Either there's no stub data, or the last byte of the stub
2489              * data is present in the captured data, so we shouldn't
2490              * get a BoundsError dissecting the stub data.
2491              *
2492              * Try dissecting the authentication data.
2493              * Catch all exceptions, so that even if the auth info is bad
2494              * or we don't have all of it, we still show the stuff we
2495              * dissect after this, such as stub data.
2496              */
2497             TRY {
2498                 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2499                                                hf_dcerpc_auth_type,
2500                                                &auth_info->auth_type);
2501                 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2502                                                hf_dcerpc_auth_level,
2503                                                &auth_info->auth_level);
2504
2505                 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2506                                                hf_dcerpc_auth_pad_len,
2507                                                &auth_info->auth_pad_len);
2508                 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2509                                                hf_dcerpc_auth_rsrvd, NULL);
2510                 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2511                                                 hf_dcerpc_auth_ctx_id, NULL);
2512
2513                 /*
2514                  * Dissect the authentication data.
2515                  */
2516                 if (are_credentials) {
2517                     tvbuff_t *auth_tvb;
2518                     dcerpc_auth_subdissector_fns *auth_fns;
2519
2520                     auth_tvb = tvb_new_subset(tvb, offset,
2521                                    MIN(hdr->auth_len,tvb_length_remaining(tvb, offset)),
2522                                    hdr->auth_len);
2523
2524                     if ((auth_fns = get_auth_subdissector_fns(auth_info->auth_level,
2525                                                               auth_info->auth_type)))
2526                         dissect_auth_verf(auth_tvb, pinfo, dcerpc_tree, auth_fns,
2527                                           hdr, auth_info);
2528                     else
2529                         proto_tree_add_text (dcerpc_tree, tvb, offset, hdr->auth_len,
2530                                              "Auth Credentials");
2531                 }
2532
2533                 /* Compute the size of the auth block.  Note that this should not
2534                    include auth padding, since when NTLMSSP encryption is used, the
2535                    padding is actually inside the encrypted stub */
2536                    auth_info->auth_size = hdr->auth_len + 8;
2537             } CATCH_ALL {
2538                 show_exception(tvb, pinfo, dcerpc_tree, EXCEPT_CODE, GET_MESSAGE);
2539             } ENDTRY;
2540         }
2541     }
2542 }
2543
2544
2545 /* We need to hash in the SMB fid number to generate a unique hash table
2546  * key as DCERPC over SMB allows several pipes over the same TCP/IP
2547  * socket.
2548  * We pass this function the transport type here to make sure we only look
2549  * at this function if it came across an SMB pipe.
2550  * Other transports might need to mix in their own extra multiplexing data
2551  * as well in the future.
2552  */
2553
2554 guint16 dcerpc_get_transport_salt (packet_info *pinfo)
2555 {
2556     switch(pinfo->dcetransporttype){
2557         case DCE_CN_TRANSPORT_SMBPIPE:
2558             /* DCERPC over smb */
2559             return pinfo->dcetransportsalt;
2560     }
2561
2562     /* Some other transport... */
2563     return 0;
2564 }
2565
2566 /*
2567  * Connection oriented packet types
2568  */
2569
2570 static void
2571 dissect_dcerpc_cn_bind (tvbuff_t *tvb, gint offset, packet_info *pinfo,
2572                         proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr)
2573 {
2574     conversation_t *conv = NULL;
2575     guint8 num_ctx_items = 0;
2576     guint i;
2577     gboolean saw_ctx_item = FALSE;
2578     guint16 ctx_id;
2579     guint8 num_trans_items;
2580     guint j;
2581     e_uuid_t if_id;
2582     e_uuid_t trans_id;
2583     guint32 trans_ver;
2584     guint16 if_ver, if_ver_minor;
2585     dcerpc_auth_info auth_info;
2586     char *uuid_str;
2587     const char *uuid_name = NULL;
2588     proto_item *iface_item = NULL;
2589
2590     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2591                                     hf_dcerpc_cn_max_xmit, NULL);
2592
2593     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2594                                     hf_dcerpc_cn_max_recv, NULL);
2595
2596     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2597                                     hf_dcerpc_cn_assoc_group, NULL);
2598
2599     offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2600                                     hf_dcerpc_cn_num_ctx_items, &num_ctx_items);
2601
2602     /* padding */
2603     offset += 3;
2604
2605     for (i = 0; i < num_ctx_items; i++) {
2606             proto_item *ctx_item = NULL;
2607             proto_tree *ctx_tree = NULL, *iface_tree = NULL;
2608         gint ctx_offset = offset;
2609
2610       dissect_dcerpc_uint16 (tvb, offset, pinfo, NULL, hdr->drep,
2611                                       hf_dcerpc_cn_ctx_id, &ctx_id);
2612
2613       if (check_col (pinfo->cinfo, COL_DCE_CTX)) {
2614                 if(pinfo->dcectxid == 0) {
2615                         col_append_fstr (pinfo->cinfo, COL_DCE_CTX, "%u", ctx_id);
2616                 } else {
2617                         /* this is not the first DCE-RPC request/response in this (TCP?-)PDU,
2618                          * prepend a delimiter */
2619                         col_append_fstr (pinfo->cinfo, COL_DCE_CTX, "#%u", ctx_id);
2620                 }
2621       }
2622
2623       /* save context ID for use with dcerpc_add_conv_to_bind_table() */
2624       /* (if we have multiple contexts, this might cause "decode as"
2625        *  to behave unpredictably) */
2626       pinfo->dcectxid = ctx_id;
2627
2628       if (dcerpc_tree) {
2629               ctx_item = proto_tree_add_item(dcerpc_tree, hf_dcerpc_cn_ctx_item,
2630                                              tvb, offset, 0,
2631                                              hdr->drep[0] & 0x10);
2632               ctx_tree = proto_item_add_subtree(ctx_item, ett_dcerpc_cn_ctx);
2633       }
2634
2635       offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, ctx_tree, hdr->drep,
2636                                       hf_dcerpc_cn_ctx_id, &ctx_id);
2637       offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, ctx_tree, hdr->drep,
2638                                       hf_dcerpc_cn_num_trans_items, &num_trans_items);
2639
2640       if(dcerpc_tree) {
2641         proto_item_append_text(ctx_item, "[%u]: ID:%u", i+1, ctx_id);
2642       }
2643
2644       /* padding */
2645       offset += 1;
2646
2647       dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &if_id);
2648       if (ctx_tree) {
2649
2650       iface_item = proto_tree_add_item(ctx_tree, hf_dcerpc_cn_bind_abstract_syntax, tvb, offset, 0, FALSE);
2651           iface_tree = proto_item_add_subtree(iface_item, ett_dcerpc_cn_iface);
2652
2653       uuid_str = guid_to_str((e_guid_t*)&if_id);
2654       uuid_name = guids_get_uuid_name(&if_id);
2655       if(uuid_name) {
2656                   proto_tree_add_guid_format (iface_tree, hf_dcerpc_cn_bind_if_id, tvb,
2657                                         offset, 16, (e_guid_t *) &if_id, "Interface: %s UUID: %s", uuid_name, uuid_str);
2658           proto_item_append_text(iface_item, ": %s", uuid_name);
2659       } else {
2660           proto_tree_add_guid_format (iface_tree, hf_dcerpc_cn_bind_if_id, tvb,
2661                                         offset, 16, (e_guid_t *) &if_id, "Interface UUID: %s", uuid_str);
2662           proto_item_append_text(iface_item, ": %s", uuid_str);
2663       }
2664       }
2665       offset += 16;
2666
2667       if (hdr->drep[0] & 0x10) {
2668           offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, iface_tree, hdr->drep,
2669                                           hf_dcerpc_cn_bind_if_ver, &if_ver);
2670           offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, iface_tree, hdr->drep,
2671                                           hf_dcerpc_cn_bind_if_ver_minor, &if_ver_minor);
2672       } else {
2673           offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, iface_tree, hdr->drep,
2674                                           hf_dcerpc_cn_bind_if_ver_minor, &if_ver_minor);
2675           offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, iface_tree, hdr->drep,
2676                                           hf_dcerpc_cn_bind_if_ver, &if_ver);
2677       }
2678
2679       if (ctx_tree) {
2680           proto_item_append_text(iface_item, " V%u.%u", if_ver, if_ver_minor);
2681           proto_item_set_len(iface_item, 20);
2682       }
2683
2684       if (!saw_ctx_item) {
2685         conv = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
2686                                   pinfo->srcport, pinfo->destport, 0);
2687         if (conv == NULL) {
2688         fprintf(stderr,"Creating a new conv on packet %d\n",pinfo->fd->num);
2689             conv = conversation_new (pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
2690                                      pinfo->srcport, pinfo->destport, 0);
2691         }
2692
2693
2694         /* if this is the first time we see this packet, we need to
2695            update the dcerpc_binds table so that any later calls can
2696            match to the interface.
2697            XXX We assume that BINDs will NEVER be fragmented.
2698         */
2699         if(!(pinfo->fd->flags.visited)){
2700                 dcerpc_bind_key *key;
2701                 dcerpc_bind_value *value;
2702
2703                 key = se_alloc (sizeof (dcerpc_bind_key));
2704                 key->conv = conv;
2705                 key->ctx_id = ctx_id;
2706                 key->smb_fid = dcerpc_get_transport_salt(pinfo);
2707
2708                 value = se_alloc (sizeof (dcerpc_bind_value));
2709                 value->uuid = if_id;
2710                 value->ver = if_ver;
2711
2712                 /* add this entry to the bind table, first removing any
2713                    previous ones that are identical
2714                  */
2715                 if(g_hash_table_lookup(dcerpc_binds, key)){
2716                         g_hash_table_remove(dcerpc_binds, key);
2717                 }
2718                 g_hash_table_insert (dcerpc_binds, key, value);
2719         }
2720
2721         if (check_col (pinfo->cinfo, COL_INFO)) {
2722           if (num_ctx_items > 1)
2723                   col_append_fstr(pinfo->cinfo, COL_INFO, ", %u context items, 1st", num_ctx_items);
2724
2725                 col_append_fstr(pinfo->cinfo, COL_INFO, " %s V%u.%u",
2726                        guids_resolve_uuid_to_str(&if_id), if_ver, if_ver_minor);
2727         }
2728         saw_ctx_item = TRUE;
2729       }
2730
2731       for (j = 0; j < num_trans_items; j++) {
2732             proto_tree *trans_tree = NULL;
2733             proto_item *trans_item = NULL;
2734
2735         dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &trans_id);
2736         if (ctx_tree) {
2737
2738         trans_item = proto_tree_add_item(ctx_tree, hf_dcerpc_cn_bind_trans_syntax, tvb, offset, 0, FALSE);
2739         trans_tree = proto_item_add_subtree(trans_item, ett_dcerpc_cn_trans_syntax);
2740
2741         uuid_str = guid_to_str((e_guid_t *) &trans_id);
2742             proto_tree_add_guid_format (trans_tree, hf_dcerpc_cn_bind_trans_id, tvb,
2743                                           offset, 16, (e_guid_t *) &trans_id, "Transfer Syntax: %s", uuid_str);
2744             proto_item_append_text(trans_item, "[%u]: %s", j+1, uuid_str);
2745         }
2746         offset += 16;
2747
2748         offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, trans_tree, hdr->drep,
2749                                         hf_dcerpc_cn_bind_trans_ver, &trans_ver);
2750         if (ctx_tree) {
2751           proto_item_set_len(trans_item, 20);
2752           proto_item_append_text(trans_item, " V%u", trans_ver);
2753         }
2754       }
2755
2756       if(ctx_tree) {
2757         proto_item_set_len(ctx_item, offset - ctx_offset);
2758       }
2759     }
2760
2761     /*
2762      * XXX - we should save the authentication type *if* we have
2763      * an authentication header, and associate it with an authentication
2764      * context, so subsequent PDUs can use that context.
2765      */
2766     dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, hdr, TRUE, &auth_info);
2767 }
2768
2769 static void
2770 dissect_dcerpc_cn_bind_ack (tvbuff_t *tvb, gint offset, packet_info *pinfo,
2771                             proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr)
2772 {
2773     guint16 max_xmit, max_recv;
2774     guint16 sec_addr_len;
2775     guint8 num_results;
2776     guint i;
2777     guint16 result;
2778     guint16 reason;
2779     e_uuid_t trans_id;
2780     guint32 trans_ver;
2781     dcerpc_auth_info auth_info;
2782
2783     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2784                                     hf_dcerpc_cn_max_xmit, &max_xmit);
2785
2786     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2787                                     hf_dcerpc_cn_max_recv, &max_recv);
2788
2789     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2790                                     hf_dcerpc_cn_assoc_group, NULL);
2791
2792     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2793                                     hf_dcerpc_cn_sec_addr_len, &sec_addr_len);
2794     if (sec_addr_len != 0) {
2795         tvb_ensure_bytes_exist(tvb, offset, sec_addr_len);
2796         proto_tree_add_item (dcerpc_tree, hf_dcerpc_cn_sec_addr, tvb, offset,
2797                              sec_addr_len, FALSE);
2798         offset += sec_addr_len;
2799     }
2800
2801     if (offset % 4) {
2802         offset += 4 - offset % 4;
2803     }
2804
2805     offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2806                                    hf_dcerpc_cn_num_results, &num_results);
2807
2808     /* padding */
2809     offset += 3;
2810
2811     for (i = 0; i < num_results; i++) {
2812         proto_tree *ctx_tree = NULL;
2813
2814         if(dcerpc_tree){
2815                 proto_item *ctx_item;
2816                 ctx_item = proto_tree_add_text(dcerpc_tree, tvb, offset, 24, "Context ID[%u]", i+1);
2817                 ctx_tree = proto_item_add_subtree(ctx_item, ett_dcerpc_cn_ctx);
2818         }
2819
2820         offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, ctx_tree,
2821                                         hdr->drep, hf_dcerpc_cn_ack_result,
2822                                         &result);
2823         if (result != 0) {
2824             offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, ctx_tree,
2825                                             hdr->drep, hf_dcerpc_cn_ack_reason,
2826                                             &reason);
2827         } else {
2828             /*
2829              * The reason for rejection isn't meaningful, and often isn't
2830              * set, when the syntax was accepted.
2831              */
2832             offset += 2;
2833         }
2834
2835         dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &trans_id);
2836         if (ctx_tree) {
2837             proto_tree_add_guid_format (ctx_tree, hf_dcerpc_cn_ack_trans_id, tvb,
2838                                           offset, 16, (e_guid_t *) &trans_id, "Transfer Syntax: %s",
2839                                           guid_to_str((e_guid_t *) &trans_id));
2840         }
2841         offset += 16;
2842
2843         offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, ctx_tree, hdr->drep,
2844                                         hf_dcerpc_cn_ack_trans_ver, &trans_ver);
2845     }
2846
2847     /*
2848      * XXX - do we need to do anything with the authentication level
2849      * we get back from this?
2850      */
2851     dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, hdr, TRUE, &auth_info);
2852
2853     if (check_col (pinfo->cinfo, COL_INFO)) {
2854         if (num_results != 0 && result == 0) {
2855             /* XXX - only checks the last result */
2856             col_append_fstr (pinfo->cinfo, COL_INFO,
2857                              " accept max_xmit: %u max_recv: %u",
2858                              max_xmit, max_recv);
2859         } else {
2860             /* XXX - only shows the last result and reason */
2861             col_append_fstr (pinfo->cinfo, COL_INFO, " %s, reason: %s",
2862                              val_to_str(result, p_cont_result_vals,
2863                                         "Unknown result (%u)"),
2864                              val_to_str(reason, p_provider_reason_vals,
2865                                         "Unknown (%u)"));
2866         }
2867     }
2868 }
2869
2870 static void
2871 dissect_dcerpc_cn_bind_nak (tvbuff_t *tvb, gint offset, packet_info *pinfo,
2872                             proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr)
2873 {
2874     guint16 reason;
2875     guint8 num_protocols;
2876     guint i;
2877
2878     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
2879                                     hdr->drep, hf_dcerpc_cn_reject_reason,
2880                                     &reason);
2881
2882     if (check_col (pinfo->cinfo, COL_INFO)) {
2883         col_append_fstr (pinfo->cinfo, COL_INFO, " reason: %s",
2884                       val_to_str(reason, reject_reason_vals, "Unknown (%u)"));
2885     }
2886
2887     if (reason == PROTOCOL_VERSION_NOT_SUPPORTED) {
2888         offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2889                                        hf_dcerpc_cn_num_protocols,
2890                                        &num_protocols);
2891
2892         for (i = 0; i < num_protocols; i++) {
2893             offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree,
2894                                         hdr->drep, hf_dcerpc_cn_protocol_ver_major,
2895                                         NULL);
2896             offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree,
2897                                         hdr->drep, hf_dcerpc_cn_protocol_ver_minor,
2898                                         NULL);
2899         }
2900     }
2901 }
2902
2903 /* Return a string describing a DCE/RPC fragment as first, middle, or end
2904    fragment. */
2905
2906 #define PFC_FRAG_MASK  0x03
2907
2908 static const char *
2909 fragment_type(guint8 flags)
2910 {
2911         flags = flags & PFC_FRAG_MASK;
2912
2913         if (flags == PFC_FIRST_FRAG)
2914                 return "first";
2915
2916         if (flags == 0)
2917                 return "middle";
2918
2919         if (flags == PFC_LAST_FRAG)
2920                 return "last";
2921
2922         if (flags == (PFC_FIRST_FRAG | PFC_LAST_FRAG))
2923                 return "whole";
2924
2925         return "unknown";
2926 }
2927
2928 /* Dissect stub data (payload) of a DCERPC packet. */
2929
2930 static void
2931 dissect_dcerpc_cn_stub (tvbuff_t *tvb, int offset, packet_info *pinfo,
2932                         proto_tree *dcerpc_tree, proto_tree *tree,
2933                         e_dce_cn_common_hdr_t *hdr, dcerpc_info *di,
2934                         dcerpc_auth_info *auth_info, guint32 alloc_hint _U_,
2935                         guint32 frame)
2936 {
2937     gint length, reported_length;
2938     gboolean save_fragmented;
2939     fragment_data *fd_head=NULL;
2940
2941     tvbuff_t *auth_tvb, *payload_tvb, *decrypted_tvb;
2942     proto_item *pi;
2943     proto_item *parent_pi;
2944     proto_item *dcerpc_tree_item;
2945
2946     save_fragmented = pinfo->fragmented;
2947     length = tvb_length_remaining(tvb, offset);
2948     reported_length = tvb_reported_length_remaining(tvb, offset);
2949     if (reported_length < 0 ||
2950             (guint32)reported_length < auth_info->auth_size) {
2951         /* We don't even have enough bytes for the authentication
2952            stuff. */
2953             return;
2954     }
2955     reported_length -= auth_info->auth_size;
2956     if (length > reported_length)
2957             length = reported_length;
2958     payload_tvb = tvb_new_subset(tvb, offset, length, reported_length);
2959
2960     auth_tvb=NULL;
2961     /*dont bother if we dont have the entire tvb */
2962     /*XXX we should really make sure we calculate auth_info->auth_data
2963            *and use that one instead of this auth_tvb hack
2964      */
2965     if(tvb_length(tvb)==tvb_reported_length(tvb)){
2966             if(tvb_length_remaining(tvb, offset+length)>8){
2967              auth_tvb = tvb_new_subset(tvb, offset+length+8, -1, -1);
2968             }
2969     }
2970
2971     /* Decrypt the PDU if it is encrypted */
2972
2973     if (auth_info->auth_type &&
2974         auth_info->auth_level == DCE_C_AUTHN_LEVEL_PKT_PRIVACY) {
2975             /*
2976              * We know the authentication type, and the authentication
2977              * level is "Packet privacy", meaning the payload is
2978              * encrypted; attempt to decrypt it.
2979              */
2980             dcerpc_auth_subdissector_fns *auth_fns;
2981
2982             /* Start out assuming we won't succeed in decrypting. */
2983             decrypted_tvb = NULL;
2984       /* Schannel needs informations into the footer (verifier) in order to setup decryptions keys 
2985        * so we call it in order to have a chance to decypher the data 
2986        */
2987       if (DCE_C_RPC_AUTHN_PROTOCOL_SEC_CHAN == auth_info->auth_type) {
2988         dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, hdr, TRUE, auth_info);
2989       }
2990
2991             if ((auth_fns = get_auth_subdissector_fns(
2992                          auth_info->auth_level, auth_info->auth_type))) {
2993                     tvbuff_t *result;
2994                     result = decode_encrypted_data( payload_tvb, auth_tvb, pinfo, auth_fns,
2995                              hdr->ptype == PDU_REQ, auth_info);
2996                     if (result) {
2997                             if (dcerpc_tree) {
2998                                     proto_tree_add_text(dcerpc_tree, payload_tvb, 0, -1,
2999                                             "Encrypted stub data (%d byte%s)",
3000                                             tvb_reported_length(payload_tvb),
3001                                 plurality(tvb_length(payload_tvb), "", "s"));
3002           }
3003                             add_new_data_source(pinfo, result, "Decrypted stub data");
3004                             /* We succeeded. */
3005                             decrypted_tvb = result;
3006                     }
3007             }
3008     } 
3009     else
3010             decrypted_tvb = payload_tvb;
3011
3012     /* if this packet is not fragmented, just dissect it and exit */
3013     if(PFC_NOT_FRAGMENTED(hdr)) {
3014             pinfo->fragmented = FALSE;
3015
3016             dcerpc_try_handoff( pinfo, tree, dcerpc_tree, payload_tvb, 
3017           decrypted_tvb, hdr->drep, di, auth_info);
3018
3019            pinfo->fragmented = save_fragmented;
3020            return;
3021     }
3022
3023     /* The packet is fragmented. */
3024     pinfo->fragmented = TRUE;
3025
3026           /* debug output of essential fragment data. */
3027           /* leave it here for future debugging sessions */
3028           /*printf("DCE num:%u offset:%u frag_len:%u tvb_len:%u\n",
3029                    pinfo->fd->num, offset, hdr->frag_len, tvb_length(decrypted_tvb));*/
3030
3031     /* if we are not doing reassembly and this is the first fragment
3032        then just dissect it and exit
3033        XXX - if we're not doing reassembly, can we decrypt an
3034        encrypted stub?
3035     */
3036     if( (!dcerpc_reassemble) && hdr->flags&PFC_FIRST_FRAG ){
3037
3038         dcerpc_try_handoff(
3039                 pinfo, tree, dcerpc_tree, payload_tvb, decrypted_tvb,
3040                 hdr->drep, di, auth_info);
3041
3042         if (check_col(pinfo->cinfo, COL_INFO)) {
3043             col_append_fstr(pinfo->cinfo, COL_INFO,
3044                             " [DCE/RPC %s fragment]", fragment_type(hdr->flags));
3045         }
3046                 expert_add_info_format(pinfo, NULL, PI_REASSEMBLE, PI_CHAT,
3047                         "%s fragment", fragment_type(hdr->flags));
3048         pinfo->fragmented = save_fragmented;
3049         return;
3050     }
3051
3052     /* if we have already seen this packet, see if it was reassembled
3053        and if so dissect the full pdu.
3054        then exit
3055     */
3056     if(pinfo->fd->flags.visited){
3057         fd_head=fragment_get_reassembled(pinfo, frame, dcerpc_co_reassemble_table);
3058         goto end_cn_stub;
3059     }
3060
3061     /* if we are not doing reassembly and it was neither a complete PDU
3062        nor the first fragment then there is nothing more we can do
3063        so we just have to exit
3064     */
3065     if( !dcerpc_reassemble || (tvb_length(tvb)!=tvb_reported_length(tvb)) )
3066         goto end_cn_stub;
3067
3068     /* if we didnt get 'frame' we dont know where the PDU started and thus
3069        it is pointless to continue
3070     */
3071     if(!frame)
3072         goto end_cn_stub;
3073
3074     /* from now on we must attempt to reassemble the PDU
3075     */
3076
3077     /* if we get here we know it is the first time we see the packet
3078        and we also know it is only a fragment and not a full PDU,
3079        thus we must reassemble it.
3080     */
3081
3082     /* Do we have any non-encrypted data to reassemble? */
3083     if (decrypted_tvb == NULL) {
3084       /* No.  We can't even try to reassemble.  */
3085       goto end_cn_stub;
3086     }
3087
3088     /* defragmentation is a bit tricky, as there's no offset of the fragment
3089      * in the protocol data.
3090      *
3091      * just use fragment_add_seq_next() and hope that TCP/SMB segments coming
3092      * in with the correct sequence.
3093      */
3094     fd_head = fragment_add_seq_next(decrypted_tvb, 0, pinfo, frame,
3095                 dcerpc_co_fragment_table, dcerpc_co_reassemble_table,
3096                 tvb_length(decrypted_tvb),
3097                 hdr->flags&PFC_LAST_FRAG ? FALSE : TRUE /* more_frags */);
3098
3099 end_cn_stub:
3100
3101     /* if reassembly is complete and this is the last fragment
3102          * (multiple fragments in one PDU are possible!)
3103          * dissect the full PDU
3104      */
3105     if(fd_head && (fd_head->flags&FD_DEFRAGMENTED) ){
3106
3107         if(pinfo->fd->num==fd_head->reassembled_in && (hdr->flags&PFC_LAST_FRAG) ){
3108             tvbuff_t *next_tvb;
3109         proto_item *frag_tree_item;
3110
3111             next_tvb = tvb_new_child_real_data((decrypted_tvb)?decrypted_tvb:payload_tvb,
3112                                  fd_head->data, fd_head->len, fd_head->len);
3113
3114             add_new_data_source(pinfo, next_tvb, "Reassembled DCE/RPC");
3115             show_fragment_tree(fd_head, &dcerpc_frag_items,
3116                         tree, pinfo, next_tvb, &frag_tree_item);
3117                 /* the toplevel fragment subtree is now behind all desegmented data,
3118                  * move it right behind the DCE/RPC tree */
3119                 dcerpc_tree_item = proto_tree_get_parent(dcerpc_tree);
3120                 if(frag_tree_item && dcerpc_tree_item) {
3121                         proto_tree_move_item(tree, dcerpc_tree_item, frag_tree_item);
3122                 }
3123
3124             pinfo->fragmented = FALSE;
3125
3126                 expert_add_info_format(pinfo, frag_tree_item, PI_REASSEMBLE, PI_CHAT,
3127                         "%s fragment, reassembled",
3128                         fragment_type(hdr->flags));
3129
3130             dcerpc_try_handoff (pinfo, tree, dcerpc_tree, next_tvb,
3131                 next_tvb, hdr->drep, di, auth_info);
3132
3133         } else {
3134             if(decrypted_tvb){
3135                 pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_reassembled_in,
3136                                 decrypted_tvb, 0, 0, fd_head->reassembled_in);
3137             } else {
3138                 pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_reassembled_in,
3139                                 payload_tvb, 0, 0, fd_head->reassembled_in);
3140             }
3141         PROTO_ITEM_SET_GENERATED(pi);
3142         parent_pi = proto_tree_get_parent(dcerpc_tree);
3143         if(parent_pi != NULL) {
3144             proto_item_append_text(parent_pi, ", [Reas: #%u]", fd_head->reassembled_in);
3145         }
3146             if (check_col(pinfo->cinfo, COL_INFO)) {
3147                 col_append_fstr(pinfo->cinfo, COL_INFO,
3148                         " [DCE/RPC %s fragment, reas: #%u]", fragment_type(hdr->flags), fd_head->reassembled_in);
3149             }
3150                 expert_add_info_format(pinfo, NULL, PI_REASSEMBLE, PI_CHAT,
3151                         "%s fragment, reassembled in #%u", fragment_type(hdr->flags), fd_head->reassembled_in);
3152         }
3153     } else {
3154         /* Reassembly not complete - some fragments
3155            are missing.  Just show the stub data. */
3156         if (check_col(pinfo->cinfo, COL_INFO)) {
3157             col_append_fstr(pinfo->cinfo, COL_INFO,
3158                         " [DCE/RPC %s fragment]", fragment_type(hdr->flags));
3159         }
3160         expert_add_info_format(pinfo, NULL, PI_REASSEMBLE, PI_CHAT,
3161                 "%s fragment", fragment_type(hdr->flags));
3162
3163         if(decrypted_tvb){
3164                 show_stub_data (decrypted_tvb, 0, tree, auth_info, FALSE);
3165         } else {
3166                 show_stub_data (payload_tvb, 0, tree, auth_info, TRUE);
3167         }
3168     }
3169
3170     pinfo->fragmented = save_fragmented;
3171 }
3172
3173 /**
3174  *  Registers a conversation/UUID binding association, so that
3175  *  we can invoke the proper sub-dissector for a given DCERPC
3176  *  conversation.
3177  *
3178  *  @param binding all values needed to create and bind a new conversation
3179  *
3180  *  @return Pointer to newly-added UUID/conversation binding.
3181  */
3182 struct _dcerpc_bind_value *
3183 dcerpc_add_conv_to_bind_table(decode_dcerpc_bind_values_t *binding)
3184 {
3185     dcerpc_bind_value *bind_value;
3186     dcerpc_bind_key *key;
3187     conversation_t *conv;
3188
3189     conv = find_conversation (
3190         0,
3191         &binding->addr_a,
3192         &binding->addr_b,
3193         binding->ptype,
3194         binding->port_a,
3195         binding->port_b,
3196         0);
3197
3198     if (!conv) {
3199         fprintf(stderr,"Creating a new conv on this bind packet \n");
3200         conv = conversation_new (
3201             0,
3202             &binding->addr_a,
3203             &binding->addr_b,
3204             binding->ptype,
3205             binding->port_a,
3206             binding->port_b,
3207             0);
3208     }
3209
3210     bind_value = se_alloc (sizeof (dcerpc_bind_value));
3211     bind_value->uuid = binding->uuid;
3212     bind_value->ver = binding->ver;
3213
3214     key = se_alloc(sizeof (dcerpc_bind_key));
3215     key->conv = conv;
3216     key->ctx_id = binding->ctx_id;
3217     key->smb_fid = binding->smb_fid;
3218
3219     /* add this entry to the bind table, first removing any
3220        previous ones that are identical
3221      */
3222     if(g_hash_table_lookup(dcerpc_binds, key)){
3223             g_hash_table_remove(dcerpc_binds, key);
3224     }
3225     g_hash_table_insert(dcerpc_binds, key, bind_value);
3226
3227     return bind_value;
3228
3229 }
3230
3231 static void
3232 dissect_dcerpc_cn_rqst (tvbuff_t *tvb, gint offset, packet_info *pinfo,
3233                         proto_tree *dcerpc_tree, proto_tree *tree,
3234                         e_dce_cn_common_hdr_t *hdr)
3235 {
3236     conversation_t *conv;
3237     guint16 ctx_id;
3238     guint16 opnum;
3239     e_uuid_t obj_id = DCERPC_UUID_NULL;
3240     dcerpc_auth_info auth_info;
3241     guint32 alloc_hint;
3242     proto_item *pi;
3243     proto_item *parent_pi;
3244     dcerpc_matched_key matched_key, *new_matched_key;
3245     dcerpc_call_value *value;
3246
3247     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3248                                     hf_dcerpc_cn_alloc_hint, &alloc_hint);
3249
3250     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3251                                     hf_dcerpc_cn_ctx_id, &ctx_id);
3252     parent_pi = proto_tree_get_parent(dcerpc_tree);
3253     if(parent_pi != NULL) {
3254         proto_item_append_text(parent_pi, " Ctx: %u", ctx_id);
3255     }
3256
3257     if (check_col (pinfo->cinfo, COL_DCE_CTX)) {
3258                 if(pinfo->dcectxid == 0) {
3259                         col_append_fstr (pinfo->cinfo, COL_DCE_CTX, "%u", ctx_id);
3260                 } else {
3261                         /* this is not the first DCE-RPC request/response in this (TCP?-)PDU,
3262                          * prepend a delimiter */
3263                         col_append_fstr (pinfo->cinfo, COL_DCE_CTX, "#%u", ctx_id);
3264                 }
3265     }
3266     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3267                                     hf_dcerpc_opnum, &opnum);
3268
3269     /* save context ID for use with dcerpc_add_conv_to_bind_table() */
3270     pinfo->dcectxid = ctx_id;
3271
3272     if (check_col (pinfo->cinfo, COL_INFO)) {
3273         col_append_fstr (pinfo->cinfo, COL_INFO, " opnum: %u ctx_id: %u",
3274                          opnum, ctx_id);
3275     }
3276
3277     if (hdr->flags & PFC_OBJECT_UUID) {
3278         dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &obj_id);
3279         if (dcerpc_tree) {
3280             proto_tree_add_guid_format (dcerpc_tree, hf_dcerpc_obj_id, tvb,
3281                                           offset, 16, (e_guid_t *) &obj_id, "Object UUID: %s",
3282                                           guid_to_str((e_guid_t *) &obj_id));
3283         }
3284         offset += 16;
3285     }
3286
3287     /*
3288      * XXX - what if this was set when the connection was set up,
3289      * and we just have a security context?
3290      */
3291     dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, hdr, FALSE, &auth_info);
3292     conv = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
3293                               pinfo->srcport, pinfo->destport, 0);
3294     if (!conv) {
3295       /*conv = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
3296                       pinfo->srcport, pinfo->destport, 0);*/
3297        fprintf(stderr,"No conv showing raw stuf %d \n",pinfo->fd->num);
3298        show_stub_data (tvb, offset, dcerpc_tree, &auth_info, TRUE);
3299     }
3300     else {
3301     /* !!! we can NOT check flags.visited here since this will interact
3302        badly with when SMB handles (i.e. calls the subdissector)
3303        and desegmented pdu's .
3304        Instead we check if this pdu is already in the matched table or not
3305     */
3306       matched_key.frame = pinfo->fd->num;
3307       matched_key.call_id = hdr->call_id;
3308       value = g_hash_table_lookup(dcerpc_matched, &matched_key);
3309       if(!value) {
3310         dcerpc_bind_key bind_key;
3311         dcerpc_bind_value *bind_value;
3312
3313         bind_key.conv=conv;
3314         bind_key.ctx_id=ctx_id;
3315         bind_key.smb_fid=dcerpc_get_transport_salt(pinfo);
3316         if((bind_value=g_hash_table_lookup(dcerpc_binds, &bind_key)) ){
3317         if(!(hdr->flags&PFC_FIRST_FRAG)){
3318           dcerpc_cn_call_key call_key;
3319           dcerpc_call_value *call_value;
3320
3321           call_key.conv=conv;
3322           call_key.call_id=hdr->call_id;
3323           call_key.smb_fid=dcerpc_get_transport_salt(pinfo);
3324           if((call_value=g_hash_table_lookup(dcerpc_cn_calls, &call_key))){
3325             new_matched_key = se_alloc(sizeof (dcerpc_matched_key));
3326             *new_matched_key = matched_key;
3327             g_hash_table_insert (dcerpc_matched, new_matched_key, call_value);
3328             value = call_value;
3329           }
3330         } 
3331         else {
3332           dcerpc_cn_call_key *call_key;
3333           dcerpc_call_value *call_value;
3334
3335           /* We found the binding and it is the first fragment
3336              (or a complete PDU) of a dcerpc pdu so just add
3337              the call to both the call table and the
3338              matched table
3339           */
3340           call_key=se_alloc (sizeof (dcerpc_cn_call_key));
3341           call_key->conv=conv;
3342           call_key->call_id=hdr->call_id;
3343           call_key->smb_fid=dcerpc_get_transport_salt(pinfo);
3344
3345           /* if there is already a matching call in the table
3346              remove it so it is replaced with the new one */
3347           if(g_hash_table_lookup(dcerpc_cn_calls, call_key)){
3348             g_hash_table_remove(dcerpc_cn_calls, call_key);
3349           }
3350
3351           call_value=se_alloc (sizeof (dcerpc_call_value));
3352           call_value->uuid = bind_value->uuid;
3353           call_value->ver = bind_value->ver;
3354           call_value->object_uuid = obj_id;
3355           call_value->opnum = opnum;
3356           call_value->req_frame=pinfo->fd->num;
3357           call_value->req_time=pinfo->fd->abs_ts;
3358           call_value->rep_frame=0;
3359           call_value->max_ptr=0;
3360           call_value->se_data = NULL;
3361           call_value->private_data = NULL;
3362           call_value->pol = NULL;
3363           g_hash_table_insert (dcerpc_cn_calls, call_key, call_value);
3364
3365           new_matched_key = se_alloc(sizeof (dcerpc_matched_key));
3366           *new_matched_key = matched_key;
3367           g_hash_table_insert (dcerpc_matched, new_matched_key, call_value);
3368           value = call_value;   
3369         } 
3370       }
3371     }
3372     if (value) {
3373       dcerpc_info *di;
3374       di=get_next_di();
3375       /* handoff this call */
3376       di->conv = conv;
3377       di->call_id = hdr->call_id;
3378       di->smb_fid = dcerpc_get_transport_salt(pinfo);
3379       di->ptype = PDU_REQ;
3380       di->call_data = value;
3381       di->hf_index = -1;
3382
3383       if(value->rep_frame!=0){
3384         pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_response_in,
3385             tvb, 0, 0, value->rep_frame);
3386         PROTO_ITEM_SET_GENERATED(pi);
3387         if(parent_pi != NULL) {
3388             proto_item_append_text(parent_pi, ", [Resp: #%u]", value->rep_frame);
3389         }
3390       }
3391       dissect_dcerpc_cn_stub (tvb, offset, pinfo, dcerpc_tree, tree,
3392             hdr, di, &auth_info, alloc_hint,
3393             value->req_frame);
3394     } 
3395     else {
3396       /* no bind information, simply show stub data */
3397       pi = proto_tree_add_text(dcerpc_tree, tvb, offset, 0, "No bind info for this interface Context ID - capture start too late?");
3398       PROTO_ITEM_SET_GENERATED(pi);
3399       expert_add_info_format(pinfo, pi, PI_UNDECODED, PI_NOTE, "No bind info for interface Context ID:%u",
3400           ctx_id);
3401       show_stub_data (tvb, offset, dcerpc_tree, &auth_info, TRUE);
3402     }
3403   }
3404   /* Dissect the verifier */
3405   dissect_dcerpc_verifier (tvb, pinfo, dcerpc_tree, hdr, &auth_info);
3406
3407 }
3408
3409 static void
3410 dissect_dcerpc_cn_resp (tvbuff_t *tvb, gint offset, packet_info *pinfo,
3411                         proto_tree *dcerpc_tree, proto_tree *tree,
3412                         e_dce_cn_common_hdr_t *hdr)
3413 {
3414     dcerpc_call_value *value = NULL;
3415     conversation_t *conv;
3416     guint16 ctx_id;
3417     dcerpc_auth_info auth_info;
3418     guint32 alloc_hint;
3419     proto_item *pi;
3420     proto_item *parent_pi;
3421     e_uuid_t obj_id_null = DCERPC_UUID_NULL;
3422
3423     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3424                                     hf_dcerpc_cn_alloc_hint, &alloc_hint);
3425
3426     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3427                                     hf_dcerpc_cn_ctx_id, &ctx_id);
3428     parent_pi = proto_tree_get_parent(dcerpc_tree);
3429     if(parent_pi != NULL) {
3430         proto_item_append_text(parent_pi, " Ctx: %u", ctx_id);
3431     }
3432
3433     if (check_col (pinfo->cinfo, COL_DCE_CTX)) {
3434                   if(pinfo->dcectxid == 0) {
3435                         col_append_fstr (pinfo->cinfo, COL_DCE_CTX, "%u", ctx_id);
3436                 } else {
3437                         /* this is not the first DCE-RPC request/response in this (TCP?-)PDU,
3438                          * prepend a delimiter */
3439                         col_append_fstr (pinfo->cinfo, COL_DCE_CTX, "#%u", ctx_id);
3440                 }
3441     }
3442
3443
3444     /* save context ID for use with dcerpc_add_conv_to_bind_table() */
3445     pinfo->dcectxid = ctx_id;
3446
3447     if (check_col (pinfo->cinfo, COL_INFO)) {
3448         col_append_fstr (pinfo->cinfo, COL_INFO, " ctx_id: %u", ctx_id);
3449     }
3450
3451     offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3452                                    hf_dcerpc_cn_cancel_count, NULL);
3453     /* padding */
3454     offset++;
3455
3456     /*
3457      * XXX - what if this was set when the connection was set up,
3458      * and we just have a security context?
3459      */
3460     dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, hdr, FALSE, &auth_info);
3461
3462     conv = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
3463                               pinfo->srcport, pinfo->destport, 0);
3464
3465     if (!conv) {
3466         /* no point in creating one here, really */
3467         show_stub_data (tvb, offset, dcerpc_tree, &auth_info, TRUE);
3468     } else {
3469             dcerpc_matched_key matched_key, *new_matched_key;
3470
3471         /* !!! we can NOT check flags.visited here since this will interact
3472            badly with when SMB handles (i.e. calls the subdissector)
3473            and desegmented pdu's .
3474            Instead we check if this pdu is already in the matched table or not
3475         */
3476             matched_key.frame = pinfo->fd->num;
3477             matched_key.call_id = hdr->call_id;
3478             value=g_hash_table_lookup(dcerpc_matched, &matched_key);
3479             if(!value){
3480                     dcerpc_cn_call_key call_key;
3481                     dcerpc_call_value *call_value;
3482
3483                     call_key.conv=conv;
3484                     call_key.call_id=hdr->call_id;
3485                     call_key.smb_fid=dcerpc_get_transport_salt(pinfo);
3486
3487                     if((call_value=g_hash_table_lookup(dcerpc_cn_calls, &call_key))){
3488                         /* extra sanity check,  only match them if the reply
3489                            came after the request */
3490                             if(call_value->req_frame<pinfo->fd->num){
3491                                     new_matched_key = se_alloc(sizeof (dcerpc_matched_key));
3492                                     *new_matched_key = matched_key;
3493                                     g_hash_table_insert (dcerpc_matched, new_matched_key, call_value);
3494                                     value = call_value;
3495                                     if(call_value->rep_frame==0) {
3496                                             call_value->rep_frame=pinfo->fd->num;
3497                                     }
3498                             }
3499                     }
3500             }
3501
3502       if (value) {
3503         dcerpc_info *di;
3504
3505         di=get_next_di();
3506         /* handoff this call */
3507               di->conv = conv;
3508               di->call_id = hdr->call_id;
3509               di->smb_fid = dcerpc_get_transport_salt(pinfo);
3510               di->ptype = PDU_RESP;
3511               di->call_data = value;
3512
3513               proto_tree_add_uint (dcerpc_tree, hf_dcerpc_opnum, tvb, 0, 0, value->opnum);
3514
3515         /* (optional) "Object UUID" from request */
3516         if (value && dcerpc_tree && memcmp(&value->object_uuid, &obj_id_null, sizeof(obj_id_null)) != 0) {
3517           pi = proto_tree_add_guid_format (dcerpc_tree, hf_dcerpc_obj_id, tvb,
3518                 offset, 0, (e_guid_t *) &value->object_uuid, "Object UUID: %s",
3519                 guid_to_str((e_guid_t *) &value->object_uuid));
3520           PROTO_ITEM_SET_GENERATED(pi);
3521         }
3522
3523         /* request in */
3524               if(value->req_frame!=0) {
3525                       nstime_t delta_ts;
3526                       pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_request_in,
3527                                     tvb, 0, 0, value->req_frame);
3528           PROTO_ITEM_SET_GENERATED(pi);
3529           if(parent_pi != NULL) {
3530             proto_item_append_text(parent_pi, ", [Req: #%u]", value->req_frame);
3531           }
3532                       nstime_delta(&delta_ts, &pinfo->fd->abs_ts, &value->req_time);
3533                       pi = proto_tree_add_time(dcerpc_tree, hf_dcerpc_time, tvb, offset, 0, &delta_ts);
3534           PROTO_ITEM_SET_GENERATED(pi);
3535         } else {
3536                       pi = proto_tree_add_text(dcerpc_tree,
3537                                         tvb, 0, 0, "No request to this DCE/RPC call found");
3538                       expert_add_info_format(pinfo, pi, PI_SEQUENCE, PI_NOTE,
3539                             "No request to this DCE/RPC call found");
3540               }
3541
3542               dissect_dcerpc_cn_stub (tvb, offset, pinfo, dcerpc_tree, tree,
3543                                     hdr, di, &auth_info, alloc_hint,value->rep_frame);
3544       } else {
3545             /* no bind information, simply show stub data */
3546         pi = proto_tree_add_text(dcerpc_tree, tvb, offset, 0, "No bind info for this interface Context ID - capture start too late?");
3547         PROTO_ITEM_SET_GENERATED(pi);
3548               expert_add_info_format(pinfo, pi, PI_UNDECODED, PI_NOTE, "No bind info for interface Context ID:%u",ctx_id);
3549         show_stub_data (tvb, offset, dcerpc_tree, &auth_info, TRUE);
3550       }
3551     }
3552     /* Dissect the verifier */
3553     dissect_dcerpc_verifier (tvb, pinfo, dcerpc_tree, hdr, &auth_info);
3554 }
3555
3556 static void
3557 dissect_dcerpc_cn_fault (tvbuff_t *tvb, gint offset, packet_info *pinfo,
3558                          proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr)
3559 {
3560     dcerpc_call_value *value = NULL;
3561     conversation_t *conv;
3562     guint16 ctx_id;
3563     guint32 status;
3564     guint32 alloc_hint;
3565     dcerpc_auth_info auth_info;
3566     proto_item *pi = NULL;
3567
3568     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3569                                     hf_dcerpc_cn_alloc_hint, &alloc_hint);
3570
3571     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3572                                     hf_dcerpc_cn_ctx_id, &ctx_id);
3573
3574     if (check_col (pinfo->cinfo, COL_DCE_CTX)) {
3575                 if(pinfo->dcectxid == 0) {
3576                         col_append_fstr (pinfo->cinfo, COL_DCE_CTX, "%u", ctx_id);
3577                 } else {
3578                         /* this is not the first DCE-RPC request/response in this (TCP?-)PDU,
3579                          * prepend a delimiter */
3580                         col_append_fstr (pinfo->cinfo, COL_DCE_CTX, "#%u", ctx_id);
3581                 }
3582     }
3583
3584     offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3585                                    hf_dcerpc_cn_cancel_count, NULL);
3586     /* padding */
3587     offset++;
3588
3589     /*offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3590                                     hf_dcerpc_cn_status, &status);*/
3591     status = ((hdr->drep[0] & 0x10)
3592             ? tvb_get_letohl (tvb, offset)
3593             : tvb_get_ntohl (tvb, offset));
3594
3595     if (dcerpc_tree) {
3596         pi = proto_tree_add_item (dcerpc_tree, hf_dcerpc_cn_status, tvb, offset, 4, (hdr->drep[0] & 0x10));
3597     }
3598         offset+=4;
3599
3600         expert_add_info_format(pinfo, pi, PI_RESPONSE_CODE, PI_NOTE, "Fault: %s",
3601                 val_to_str(status, reject_status_vals, "Unknown (0x%08x)"));
3602
3603     /* save context ID for use with dcerpc_add_conv_to_bind_table() */
3604     pinfo->dcectxid = ctx_id;
3605
3606     if (check_col (pinfo->cinfo, COL_INFO)) {
3607         col_append_fstr (pinfo->cinfo, COL_INFO,
3608                       " ctx_id: %u status: %s", ctx_id,
3609                       val_to_str(status, reject_status_vals,
3610                                  "Unknown (0x%08x)"));
3611     }
3612
3613     /* padding */
3614     offset += 4;
3615
3616     /*
3617      * XXX - what if this was set when the connection was set up,
3618      * and we just have a security context?
3619      */
3620     dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, hdr, FALSE, &auth_info);
3621
3622     conv = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
3623                               pinfo->srcport, pinfo->destport, 0);
3624     if (!conv) {
3625         /* no point in creating one here, really */
3626     } else {
3627         dcerpc_matched_key matched_key, *new_matched_key;
3628
3629         /* !!! we can NOT check flags.visited here since this will interact
3630            badly with when SMB handles (i.e. calls the subdissector)
3631            and desegmented pdu's .
3632            Instead we check if this pdu is already in the matched table or not
3633         */
3634         matched_key.frame = pinfo->fd->num;
3635         matched_key.call_id = hdr->call_id;
3636         value=g_hash_table_lookup(dcerpc_matched, &matched_key);
3637         if(!value){
3638                 dcerpc_cn_call_key call_key;
3639                 dcerpc_call_value *call_value;
3640
3641                 call_key.conv=conv;
3642                 call_key.call_id=hdr->call_id;
3643                 call_key.smb_fid=dcerpc_get_transport_salt(pinfo);
3644
3645                 if((call_value=g_hash_table_lookup(dcerpc_cn_calls, &call_key))){
3646                         new_matched_key = se_alloc(sizeof (dcerpc_matched_key));
3647                         *new_matched_key = matched_key;
3648                         g_hash_table_insert (dcerpc_matched, new_matched_key, call_value);
3649                         value = call_value;
3650                         if(call_value->rep_frame==0){
3651                                 call_value->rep_frame=pinfo->fd->num;
3652                         }
3653
3654                 }
3655         }
3656
3657         if (value) {
3658             int length, reported_length, stub_length;
3659             dcerpc_info *di;
3660             proto_item *parent_pi;
3661
3662             di=get_next_di();
3663             /* handoff this call */
3664             di->conv = conv;
3665             di->call_id = hdr->call_id;
3666             di->smb_fid = dcerpc_get_transport_salt(pinfo);
3667             di->ptype = PDU_FAULT;
3668             di->call_data = value;
3669
3670             proto_tree_add_uint (dcerpc_tree, hf_dcerpc_opnum, tvb, 0, 0, value->opnum);
3671             if(value->req_frame!=0){
3672                 nstime_t delta_ts;
3673                 pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_request_in,
3674                                     tvb, 0, 0, value->req_frame);
3675         PROTO_ITEM_SET_GENERATED(pi);
3676         parent_pi = proto_tree_get_parent(dcerpc_tree);
3677         if(parent_pi != NULL) {
3678             proto_item_append_text(parent_pi, ", [Req: #%u]", value->req_frame);
3679         }
3680                 nstime_delta(&delta_ts, &pinfo->fd->abs_ts, &value->req_time);
3681                 pi = proto_tree_add_time(dcerpc_tree, hf_dcerpc_time, tvb, offset, 0, &delta_ts);
3682         PROTO_ITEM_SET_GENERATED(pi);
3683         } else {
3684                     pi = proto_tree_add_text(dcerpc_tree,
3685                                         tvb, 0, 0, "No request to this DCE/RPC call found");
3686                     expert_add_info_format(pinfo, pi, PI_SEQUENCE, PI_NOTE,
3687                             "No request to this DCE/RPC call found");
3688             }
3689
3690             length = tvb_length_remaining(tvb, offset);
3691             reported_length = tvb_reported_length_remaining(tvb, offset);
3692                 /* as we now create a tvb in dissect_dcerpc_cn() containing only the
3693                  * stub_data, the following calculation is no longer valid:
3694              * stub_length = hdr->frag_len - offset - auth_info.auth_size;
3695                  * simply use the remaining length of the tvb instead.
3696                  * XXX - or better use the reported_length?!?
3697                  */
3698             stub_length = length;
3699             if (length > stub_length)
3700               length = stub_length;
3701             if (reported_length > stub_length)
3702               reported_length = stub_length;
3703
3704             /* If we don't have reassembly enabled, or this packet contains
3705                the entire PDU, or if we don't have all the data in this
3706                fragment, just call the handoff directly if this is the
3707                first fragment or the PDU isn't fragmented. */
3708             if( (!dcerpc_reassemble) || PFC_NOT_FRAGMENTED(hdr) ||
3709                         !tvb_bytes_exist(tvb, offset, stub_length) ){
3710                 if(hdr->flags&PFC_FIRST_FRAG){
3711                     /* First fragment, possibly the only fragment */
3712                     /*
3713                      * XXX - should there be a third routine for each
3714                      * function in an RPC subdissector, to handle
3715                      * fault responses?  The DCE RPC 1.1 spec says
3716                      * three's "stub data" here, which I infer means
3717                      * that it's protocol-specific and call-specific.
3718                      *
3719                      * It should probably get passed the status code
3720                      * as well, as that might be protocol-specific.
3721                      */
3722                     if (dcerpc_tree) {
3723                         if (stub_length > 0) {
3724                             tvb_ensure_bytes_exist(tvb, offset, stub_length);
3725                             proto_tree_add_text (dcerpc_tree, tvb, offset, stub_length,
3726                                                  "Fault stub data (%d byte%s)",
3727                                                  stub_length,
3728                                                  plurality(stub_length, "", "s"));
3729                         }
3730                     }
3731                 } else {
3732                     /* PDU is fragmented and this isn't the first fragment */
3733                     if (check_col(pinfo->cinfo, COL_INFO)) {
3734                         col_append_str(pinfo->cinfo, COL_INFO,
3735                                         " [DCE/RPC fragment]");
3736                     }
3737                     if (dcerpc_tree) {
3738                         if (stub_length > 0) {
3739                             tvb_ensure_bytes_exist(tvb, offset, stub_length);
3740                             proto_tree_add_text (dcerpc_tree, tvb, offset, stub_length,
3741                                                  "Fragment data (%d byte%s)",
3742                                                  stub_length,
3743                                                  plurality(stub_length, "", "s"));
3744                         }
3745                     }
3746                 }
3747             } else {
3748                 /* Reassembly is enabled, the PDU is fragmented, and
3749                    we have all the data in the fragment; the first two
3750                    of those mean we should attempt reassembly, and the
3751                    third means we can attempt reassembly. */
3752                 if (dcerpc_tree) {
3753                     if (length > 0) {
3754                         tvb_ensure_bytes_exist(tvb, offset, stub_length);
3755                         proto_tree_add_text (dcerpc_tree, tvb, offset, stub_length,
3756                                              "Fragment data (%d byte%s)",
3757                                              stub_length,
3758                                              plurality(stub_length, "", "s"));
3759                     }
3760                 }
3761                 if(hdr->flags&PFC_FIRST_FRAG){  /* FIRST fragment */
3762                     if( (!pinfo->fd->flags.visited) && value->rep_frame ){
3763                         fragment_add_seq_next(tvb, offset, pinfo, value->rep_frame,
3764                              dcerpc_co_fragment_table, dcerpc_co_reassemble_table,
3765                              stub_length,
3766                              TRUE);
3767                     }
3768                     if (check_col(pinfo->cinfo, COL_INFO)) {
3769                         col_append_str(pinfo->cinfo, COL_INFO,
3770                                         " [DCE/RPC fragment]");
3771                     }
3772                 } else if(hdr->flags&PFC_LAST_FRAG){  /* LAST fragment */
3773                     if( value->rep_frame ){
3774                         fragment_data *fd_head;
3775
3776                         fd_head = fragment_add_seq_next(tvb, offset, pinfo,
3777                              value->rep_frame,
3778                              dcerpc_co_fragment_table, dcerpc_co_reassemble_table,
3779                              stub_length,
3780                              TRUE);
3781
3782                         if(fd_head){
3783                             /* We completed reassembly */
3784                             tvbuff_t *next_tvb;
3785                 proto_item *frag_tree_item;
3786
3787                             next_tvb = tvb_new_child_real_data(tvb, fd_head->data, fd_head->len, fd_head->len);
3788                             add_new_data_source(pinfo, next_tvb, "Reassembled DCE/RPC");
3789                             show_fragment_tree(fd_head, &dcerpc_frag_items,
3790                                 dcerpc_tree, pinfo, next_tvb, &frag_tree_item);
3791
3792                             /*
3793                              * XXX - should there be a third routine for each
3794                              * function in an RPC subdissector, to handle
3795                              * fault responses?  The DCE RPC 1.1 spec says
3796                              * three's "stub data" here, which I infer means
3797                              * that it's protocol-specific and call-specific.
3798                              *
3799                              * It should probably get passed the status code
3800                              * as well, as that might be protocol-specific.
3801                              */
3802                             if (dcerpc_tree) {
3803                                 if (length > 0) {
3804                                     tvb_ensure_bytes_exist(tvb, offset, stub_length);
3805                                      proto_tree_add_text (dcerpc_tree, tvb, offset, stub_length,
3806                                                           "Fault stub data (%d byte%s)",
3807                                                           stub_length,
3808                                                           plurality(stub_length, "", "s"));
3809                                 }
3810                             }
3811                         } else {
3812                             /* Reassembly not complete - some fragments
3813                                are missing */
3814                             if (check_col(pinfo->cinfo, COL_INFO)) {
3815                                 col_append_str(pinfo->cinfo, COL_INFO,
3816                                                 " [DCE/RPC fragment]");
3817                             }
3818                         }
3819                     }
3820                 } else {  /* MIDDLE fragment(s) */
3821                     if( (!pinfo->fd->flags.visited) && value->rep_frame ){
3822                         fragment_add_seq_next(tvb, offset, pinfo, value->rep_frame,
3823                              dcerpc_co_fragment_table, dcerpc_co_reassemble_table,
3824                              stub_length,
3825                              TRUE);
3826                     }
3827                     if (check_col(pinfo->cinfo, COL_INFO)) {
3828                         col_append_str(pinfo->cinfo, COL_INFO,
3829                                         " [DCE/RPC fragment]");
3830                     }
3831                 }
3832             }
3833         }
3834     }
3835 }
3836
3837 /*
3838  * DCERPC dissector for connection oriented calls.
3839  * We use transport type to later multiplex between what kind of
3840  * pinfo->private_data structure to expect.
3841  */
3842 static gboolean
3843 dissect_dcerpc_cn (tvbuff_t *tvb, int offset, packet_info *pinfo,
3844                    proto_tree *tree, gboolean can_desegment, int *pkt_len)
3845 {
3846     static const guint8 nulls[4] = { 0 };
3847     int start_offset;
3848     int padding = 0;
3849     proto_item *ti = NULL;
3850     proto_item *tf = NULL;
3851     proto_tree *dcerpc_tree = NULL;
3852     proto_tree *cn_flags_tree = NULL;
3853     proto_tree *drep_tree = NULL;
3854     e_dce_cn_common_hdr_t hdr;
3855     dcerpc_auth_info auth_info;
3856         tvbuff_t *fragment_tvb;
3857
3858     /*
3859      * when done over nbt, dcerpc requests are padded with 4 bytes of null
3860      * data for some reason.
3861      *
3862      * XXX - if that's always the case, the right way to do this would
3863      * be to have a "dissect_dcerpc_cn_nb" routine which strips off
3864      * the 4 bytes of null padding, and make that the dissector
3865      * used for "netbios".
3866      */
3867     if (tvb_memeql (tvb, offset, nulls, 4) == 0) {
3868
3869         /*
3870          * Skip the padding.
3871          */
3872         offset += 4;
3873         padding += 4;
3874     }
3875     /*
3876      * Check if this looks like a C/O DCERPC call
3877      */
3878     if (!tvb_bytes_exist (tvb, offset, sizeof (hdr))) {
3879         return FALSE;   /* not enough information to check */
3880     }
3881     start_offset = offset;
3882     hdr.rpc_ver = tvb_get_guint8 (tvb, offset++);
3883     if (hdr.rpc_ver != 5)
3884         return FALSE;
3885     hdr.rpc_ver_minor = tvb_get_guint8 (tvb, offset++);
3886     if (hdr.rpc_ver_minor != 0 && hdr.rpc_ver_minor != 1)
3887         return FALSE;
3888     hdr.ptype = tvb_get_guint8 (tvb, offset++);
3889     if (hdr.ptype > 19)
3890         return FALSE;
3891
3892     hdr.flags = tvb_get_guint8 (tvb, offset++);
3893     tvb_memcpy (tvb, (guint8 *)hdr.drep, offset, sizeof (hdr.drep));
3894     offset += sizeof (hdr.drep);
3895
3896     hdr.frag_len = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
3897     offset += 2;
3898     hdr.auth_len = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
3899     offset += 2;
3900     hdr.call_id = dcerpc_tvb_get_ntohl (tvb, offset, hdr.drep);
3901     offset += 4;
3902
3903     if (check_col (pinfo->cinfo, COL_DCE_CALL)) {
3904                 if(pinfo->dcectxid == 0) {
3905                         col_append_fstr (pinfo->cinfo, COL_DCE_CALL, "%u", hdr.call_id);
3906                 } else {
3907                         /* this is not the first DCE-RPC request/response in this (TCP?-)PDU,
3908                          * prepend a delimiter */
3909                         col_append_fstr (pinfo->cinfo, COL_DCE_CALL, "#%u", hdr.call_id);
3910                 }
3911     }
3912
3913     if (can_desegment && pinfo->can_desegment
3914         && !tvb_bytes_exist(tvb, start_offset, hdr.frag_len)) {
3915         pinfo->desegment_offset = start_offset;
3916         pinfo->desegment_len = hdr.frag_len - tvb_length_remaining (tvb, start_offset);
3917         *pkt_len = 0;   /* desegmentation required */
3918         return TRUE;
3919     }
3920
3921     if (check_col (pinfo->cinfo, COL_PROTOCOL))
3922         col_set_str (pinfo->cinfo, COL_PROTOCOL, "DCERPC");
3923
3924     if (check_col (pinfo->cinfo, COL_INFO)) {
3925         if(pinfo->dcectxid != 0) {
3926             /* this is not the first DCE-RPC request/response in this (TCP?-)PDU,
3927              * append a delimiter and set a column fence */
3928             col_append_str (pinfo->cinfo, COL_INFO, " # ");
3929             col_set_fence(pinfo->cinfo,COL_INFO);
3930         }
3931         col_add_fstr (pinfo->cinfo, COL_INFO, "%s: call_id: %u",
3932                 pckt_vals[hdr.ptype].strptr, hdr.call_id);
3933     }
3934
3935     if(pinfo->dcectxid != 0) {
3936         /* this is not the first DCE-RPC request/response in this (TCP?-)PDU */
3937                 expert_add_info_format(pinfo, NULL, PI_SEQUENCE, PI_CHAT, "Multiple DCE/RPC fragments/PDU's in one packet");
3938         }
3939
3940     offset = start_offset;
3941     tvb_ensure_bytes_exist(tvb, offset, 16);
3942     if (tree) {
3943         ti = proto_tree_add_item (tree, proto_dcerpc, tvb, offset, hdr.frag_len, FALSE);
3944         dcerpc_tree = proto_item_add_subtree (ti, ett_dcerpc);
3945     }
3946
3947     proto_tree_add_uint (dcerpc_tree, hf_dcerpc_ver, tvb, offset, 1, hdr.rpc_ver);
3948     offset++;
3949
3950     proto_tree_add_uint (dcerpc_tree, hf_dcerpc_ver_minor, tvb, offset, 1, hdr.rpc_ver_minor);
3951     offset++;
3952
3953     tf = proto_tree_add_uint (dcerpc_tree, hf_dcerpc_packet_type, tvb, offset, 1, hdr.ptype);
3954     offset++;
3955
3956     /* XXX - too much "output noise", removed for now
3957     if(hdr.ptype == PDU_BIND || hdr.ptype == PDU_ALTER ||
3958         hdr.ptype == PDU_BIND_ACK || hdr.ptype == PDU_ALTER_ACK)
3959         expert_add_info_format(pinfo, tf, PI_SEQUENCE, PI_CHAT, "Context change: %s",
3960             val_to_str(hdr.ptype, pckt_vals, "(0x%x)"));*/
3961     if(hdr.ptype == PDU_BIND_NAK)
3962         expert_add_info_format(pinfo, tf, PI_SEQUENCE, PI_WARN, "Bind not acknowledged");
3963
3964     if (tree) {
3965         proto_item_append_text(ti, " %s, Fragment:", val_to_str(hdr.ptype, pckt_vals, "Unknown (0x%02x)"));
3966
3967         tf = proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_flags, tvb, offset, 1, hdr.flags);
3968         cn_flags_tree = proto_item_add_subtree (tf, ett_dcerpc_cn_flags);
3969     }
3970     proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_object, tvb, offset, 1, hdr.flags);
3971     proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_maybe, tvb, offset, 1, hdr.flags);
3972     proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_dne, tvb, offset, 1, hdr.flags);
3973     proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_mpx, tvb, offset, 1, hdr.flags);
3974     proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_reserved, tvb, offset, 1, hdr.flags);
3975     proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_cancel_pending, tvb, offset, 1, hdr.flags);
3976     proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_last_frag, tvb, offset, 1, hdr.flags);
3977     proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_first_frag, tvb, offset, 1, hdr.flags);
3978     if( (hdr.flags & PFC_FIRST_FRAG) && (hdr.flags & PFC_LAST_FRAG) ) {
3979         proto_item_append_text(ti, " Single");
3980     } else {
3981         if(hdr.flags & PFC_FIRST_FRAG) {
3982              proto_item_append_text(ti, " 1st");
3983         }
3984         if(hdr.flags & PFC_LAST_FRAG) {
3985             proto_item_append_text(ti, " Last");
3986         }
3987         if( !(hdr.flags & PFC_FIRST_FRAG) && !(hdr.flags & PFC_LAST_FRAG) ) {
3988             proto_item_append_text(ti, " Mid");
3989         }
3990     }
3991     offset++;
3992
3993     if(dcerpc_tree){
3994         tf = proto_tree_add_bytes (dcerpc_tree, hf_dcerpc_drep, tvb, offset, 4, hdr.drep);
3995         drep_tree = proto_item_add_subtree (tf, ett_dcerpc_drep);
3996     }
3997     proto_tree_add_uint(drep_tree, hf_dcerpc_drep_byteorder, tvb, offset, 1, hdr.drep[0] >> 4);
3998     proto_tree_add_uint(drep_tree, hf_dcerpc_drep_character, tvb, offset, 1, hdr.drep[0] & 0x0f);
3999     proto_tree_add_uint(drep_tree, hf_dcerpc_drep_fp, tvb, offset+1, 1, hdr.drep[1]);
4000     offset += sizeof (hdr.drep);
4001
4002     proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_frag_len, tvb, offset, 2, hdr.frag_len);
4003     offset += 2;
4004
4005     proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_auth_len, tvb, offset, 2, hdr.auth_len);
4006     offset += 2;
4007
4008     proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_call_id, tvb, offset, 4, hdr.call_id);
4009     offset += 4;
4010
4011     if(ti){
4012         proto_item_append_text(ti, ", FragLen: %u, Call: %u", hdr.frag_len, hdr.call_id);
4013     }
4014
4015     /*
4016      * None of the stuff done above should throw an exception, because
4017      * we would have rejected this as "not DCE RPC" if we didn't have all
4018      * of it.  (XXX - perhaps we should request reassembly if we have
4019      * enough of the header to consider it DCE RPC but not enough to
4020      * get the fragment length; in that case the stuff still wouldn't
4021      * throw an exception.)
4022      *
4023      * The rest of the stuff might, so return the PDU length to our caller.
4024      * XXX - should we construct a tvbuff containing only the PDU and
4025      * use that?  Or should we have separate "is this a DCE RPC PDU",
4026      * "how long is it", and "dissect it" routines - which might let us
4027      * do most of the work in "tcp_dissect_pdus()"?
4028      */
4029     if (pkt_len != NULL)
4030         *pkt_len = hdr.frag_len + padding;
4031
4032     /* The remaining bytes in the current tvb might contain multiple
4033      * DCE/RPC fragments, so create a new tvb subset for this fragment.
4034      * Only limit the end of the fragment, but not the offset start,
4035      * as the authentication function dissect_dcerpc_cn_auth() will fail
4036      * (and other functions might fail as well) computing the right start
4037      * offset otherwise.
4038      */
4039     fragment_tvb = tvb_new_subset(tvb, 0,
4040         MIN((hdr.frag_len + (guint) start_offset), tvb_length(tvb)) /* length */,
4041         hdr.frag_len + start_offset /* reported_length */);
4042
4043     /*
4044      * Packet type specific stuff is next.
4045      */
4046     switch (hdr.ptype) {
4047     case PDU_BIND:
4048     case PDU_ALTER:
4049         dissect_dcerpc_cn_bind (fragment_tvb, offset, pinfo, dcerpc_tree, &hdr);
4050         break;
4051
4052     case PDU_BIND_ACK:
4053     case PDU_ALTER_ACK:
4054         dissect_dcerpc_cn_bind_ack (fragment_tvb, offset, pinfo, dcerpc_tree, &hdr);
4055         break;
4056
4057     case PDU_AUTH3:
4058         /*
4059          * Nothing after the common header other than credentials.
4060          */
4061         dissect_dcerpc_cn_auth (fragment_tvb, offset, pinfo, dcerpc_tree, &hdr, TRUE,
4062                                 &auth_info);
4063         break;
4064
4065     case PDU_REQ:
4066         dissect_dcerpc_cn_rqst (fragment_tvb, offset, pinfo, dcerpc_tree, tree, &hdr);
4067         break;
4068
4069     case PDU_RESP:
4070         dissect_dcerpc_cn_resp (fragment_tvb, offset, pinfo, dcerpc_tree, tree, &hdr);
4071         break;
4072
4073     case PDU_FAULT:
4074         dissect_dcerpc_cn_fault (fragment_tvb, offset, pinfo, dcerpc_tree, &hdr);
4075         break;
4076
4077     case PDU_BIND_NAK:
4078         dissect_dcerpc_cn_bind_nak (fragment_tvb, offset, pinfo, dcerpc_tree, &hdr);
4079         break;
4080
4081     case PDU_CO_CANCEL:
4082     case PDU_ORPHANED:
4083         /*
4084          * Nothing after the common header other than an authentication
4085          * verifier.
4086          */
4087         dissect_dcerpc_cn_auth (fragment_tvb, offset, pinfo, dcerpc_tree, &hdr, FALSE,
4088                                 &auth_info);
4089         break;
4090
4091     case PDU_SHUTDOWN:
4092         /*
4093          * Nothing after the common header, not even an authentication
4094          * verifier.
4095          */
4096         break;
4097
4098     default:
4099         /* might as well dissect the auth info */
4100         dissect_dcerpc_cn_auth (fragment_tvb, offset, pinfo, dcerpc_tree, &hdr, FALSE,
4101                                 &auth_info);
4102         break;
4103     }
4104     return TRUE;
4105 }
4106
4107 /*
4108  * DCERPC dissector for connection oriented calls over packet-oriented
4109  * transports
4110  */
4111 static gboolean
4112 dissect_dcerpc_cn_pk (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4113 {
4114     /*
4115      * Only one PDU per transport packet, and only one transport
4116      * packet per PDU.
4117      */
4118     pinfo->dcetransporttype=DCE_TRANSPORT_UNKNOWN;
4119     if (!dissect_dcerpc_cn (tvb, 0, pinfo, tree, FALSE, NULL)) {
4120         /*
4121          * It wasn't a DCERPC PDU.
4122          */
4123         return FALSE;
4124     } else {
4125         /*
4126          * It was.
4127          */
4128         return TRUE;
4129     }
4130 }
4131
4132 /*
4133  * DCERPC dissector for connection oriented calls over byte-stream
4134  * transports.
4135  * we need to distinguish here between SMB and non-TCP (more in the future?)
4136  * to be able to know what kind of private_data structure to expect.
4137  */
4138 static gboolean
4139 dissect_dcerpc_cn_bs_body (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4140 {
4141     volatile int offset = 0;
4142     int pdu_len;
4143     volatile gboolean dcerpc_pdus = 0;
4144     volatile gboolean ret = FALSE;
4145
4146     /*
4147      * There may be multiple PDUs per transport packet; keep
4148      * processing them.
4149      */
4150     while (tvb_reported_length_remaining(tvb, offset) != 0) {
4151         /*
4152          * Catch ReportedBoundsError, so that even if the stub data is bad,
4153          * we don't abort the full DCE RPC dissection - there might be more
4154          * than one DCE RPC PDU in the data being dissected.
4155          *
4156          * If we get BoundsError, it means the frame was cut short by a
4157          * snapshot length, so there's nothing more to dissect; just
4158          * re-throw that exception.
4159          */
4160         TRY {
4161             pdu_len = 0;
4162             if(dissect_dcerpc_cn (tvb, offset, pinfo, tree,
4163                 dcerpc_cn_desegment, &pdu_len)) {
4164                 dcerpc_pdus++;
4165             }
4166         } CATCH(BoundsError) {
4167             RETHROW;
4168         } CATCH(ReportedBoundsError) {
4169             show_reported_bounds_error(tvb, pinfo, tree);
4170             /*
4171              * Presumably it looked enough like a DCE RPC PDU that we
4172              * dissected enough of it to throw an exception.
4173              */
4174             dcerpc_pdus++;
4175         } ENDTRY;
4176
4177         if (!dcerpc_pdus) {
4178             /*
4179              * Not a DCERPC PDU.
4180              */
4181             break;
4182         }
4183
4184         /*
4185          * Well, we've seen at least one DCERPC PDU.
4186          */
4187         ret = TRUE;
4188
4189         /* if we had more than one Req/Resp in this PDU change the protocol column */
4190         /* this will formerly contain the last interface name, which may not be the same for all Req/Resp */
4191         if (dcerpc_pdus >= 2 && check_col (pinfo->cinfo, COL_PROTOCOL))
4192             col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "%u*DCERPC", dcerpc_pdus);
4193
4194         if (pdu_len == 0) {
4195             /*
4196              * Desegmentation required - bail now, but give the user a hint that desegmentation might be done later.
4197              */
4198             proto_tree_add_uint_format(tree, hf_dcerpc_cn_deseg_req, tvb, offset,
4199                 0,
4200                 tvb_reported_length_remaining(tvb, offset),
4201                 "[DCE RPC: %u byte%s left, desegmentation might follow]",
4202                 tvb_reported_length_remaining(tvb, offset),
4203                 plurality(tvb_reported_length_remaining(tvb, offset), "", "s"));
4204             break;
4205         }
4206
4207         /*
4208          * Step to the next PDU.
4209          */
4210         offset += pdu_len;
4211     }
4212     return ret;
4213 }
4214
4215 static gboolean
4216 dissect_dcerpc_cn_bs (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4217 {
4218         pinfo->dcetransporttype=DCE_TRANSPORT_UNKNOWN;
4219         return dissect_dcerpc_cn_bs_body(tvb, pinfo, tree);
4220 }
4221
4222 static gboolean
4223 dissect_dcerpc_cn_smbpipe (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4224 {
4225         pinfo->dcetransporttype=DCE_CN_TRANSPORT_SMBPIPE;
4226         return dissect_dcerpc_cn_bs_body(tvb, pinfo, tree);
4227 }
4228
4229 static gboolean
4230 dissect_dcerpc_cn_smb2 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4231 {
4232         pinfo->dcetransporttype=DCE_TRANSPORT_UNKNOWN;
4233         return dissect_dcerpc_cn_bs_body(tvb, pinfo, tree);
4234 }
4235
4236
4237
4238 static void
4239 dissect_dcerpc_dg_auth (tvbuff_t *tvb, int offset, proto_tree *dcerpc_tree,
4240                         e_dce_dg_common_hdr_t *hdr, int *auth_level_p)
4241 {
4242     proto_item *ti = NULL;
4243     proto_tree *auth_tree = NULL;
4244     guint8 protection_level;
4245
4246     /*
4247      * Initially set "*auth_level_p" to -1 to indicate that we haven't
4248      * yet seen any authentication level information.
4249      */
4250     if (auth_level_p != NULL)
4251         *auth_level_p = -1;
4252
4253     /*
4254      * The authentication information is at the *end* of the PDU; in
4255      * request and response PDUs, the request and response stub data
4256      * come before it.
4257      *
4258      * If the full packet is here, and there's data past the end of the
4259      * packet body, then dissect the auth info.
4260      */
4261     offset += hdr->frag_len;
4262     if (tvb_length_remaining(tvb, offset) > 0) {
4263         switch (hdr->auth_proto) {
4264
4265         case DCE_C_RPC_AUTHN_PROTOCOL_KRB5:
4266             ti = proto_tree_add_text (dcerpc_tree, tvb, offset, -1, "Kerberos authentication verifier");
4267             auth_tree = proto_item_add_subtree (ti, ett_dcerpc_krb5_auth_verf);
4268             protection_level = tvb_get_guint8 (tvb, offset);
4269             if (auth_level_p != NULL)
4270                 *auth_level_p = protection_level;
4271             proto_tree_add_uint (auth_tree, hf_dcerpc_krb5_av_prot_level, tvb, offset, 1, protection_level);
4272             offset++;
4273             proto_tree_add_item (auth_tree, hf_dcerpc_krb5_av_key_vers_num, tvb, offset, 1, FALSE);
4274             offset++;
4275             if (protection_level == DCE_C_AUTHN_LEVEL_PKT_PRIVACY)
4276                 offset += 6;    /* 6 bytes of padding */
4277             else
4278                 offset += 2;    /* 6 bytes of padding */
4279             proto_tree_add_item (auth_tree, hf_dcerpc_krb5_av_key_auth_verifier, tvb, offset, 16, FALSE);
4280             offset += 16;
4281             break;
4282
4283         default:
4284             proto_tree_add_text (dcerpc_tree, tvb, offset, -1, "Authentication verifier");
4285             break;
4286         }
4287     }
4288 }
4289
4290 static void
4291 dissect_dcerpc_dg_cancel_ack (tvbuff_t *tvb, int offset, packet_info *pinfo,
4292                               proto_tree *dcerpc_tree,
4293                               e_dce_dg_common_hdr_t *hdr)
4294 {
4295     guint32 version;
4296
4297     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
4298                                     hdr->drep, hf_dcerpc_dg_cancel_vers,
4299                                     &version);
4300
4301     switch (version) {
4302
4303     case 0:
4304         /* The only version we know about */
4305         offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
4306                                         hdr->drep, hf_dcerpc_dg_cancel_id,
4307                                         NULL);
4308         offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree,
4309                                        hdr->drep, hf_dcerpc_dg_server_accepting_cancels,
4310                                        NULL);
4311         break;
4312     }
4313 }
4314
4315 static void
4316 dissect_dcerpc_dg_cancel (tvbuff_t *tvb, int offset, packet_info *pinfo,
4317                           proto_tree *dcerpc_tree,
4318                           e_dce_dg_common_hdr_t *hdr)
4319 {
4320     guint32 version;
4321
4322     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
4323                                     hdr->drep, hf_dcerpc_dg_cancel_vers,
4324                                     &version);
4325
4326     switch (version) {
4327
4328     case 0:
4329         /* The only version we know about */
4330         offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
4331                                         hdr->drep, hf_dcerpc_dg_cancel_id,
4332                                         NULL);
4333         /* XXX - are NDR booleans 32 bits? */
4334
4335         /* XXX - the RPC reference in chapter: "the cancel PDU" doesn't mention
4336            the accepting_cancels field (it's only in the cancel_ack PDU)! */
4337         /*offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
4338                                         hdr->drep, hf_dcerpc_dg_server_accepting_cancels,
4339                                         NULL);*/
4340         break;
4341     }
4342 }
4343
4344 static void
4345 dissect_dcerpc_dg_fack (tvbuff_t *tvb, int offset, packet_info *pinfo,
4346                         proto_tree *dcerpc_tree,
4347                         e_dce_dg_common_hdr_t *hdr)
4348 {
4349     guint8 version;
4350     guint16 serial_num;
4351     guint16 selack_len;
4352     guint i;
4353
4354     offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree,
4355                                   hdr->drep, hf_dcerpc_dg_fack_vers,
4356                                   &version);
4357     /* padding */
4358     offset++;
4359
4360     switch (version) {
4361
4362     case 0:     /* The only version documented in the DCE RPC 1.1 spec */
4363     case 1:     /* This appears to be the same */
4364         offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
4365                                         hdr->drep, hf_dcerpc_dg_fack_window_size,
4366                                         NULL);
4367         offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
4368                                         hdr->drep, hf_dcerpc_dg_fack_max_tsdu,
4369                                         NULL);
4370         offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
4371                                         hdr->drep, hf_dcerpc_dg_fack_max_frag_size,
4372                                         NULL);
4373         offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
4374                                         hdr->drep, hf_dcerpc_dg_fack_serial_num,
4375                                         &serial_num);
4376         if (check_col (pinfo->cinfo, COL_INFO)) {
4377             col_append_fstr (pinfo->cinfo, COL_INFO, " serial: %u",
4378                              serial_num);
4379         }
4380         offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
4381                                         hdr->drep, hf_dcerpc_dg_fack_selack_len,
4382                                         &selack_len);
4383         for (i = 0; i < selack_len; i++) {
4384             offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
4385                                             hdr->drep, hf_dcerpc_dg_fack_selack,
4386                                             NULL);
4387         }
4388
4389         break;
4390     }
4391 }
4392
4393 static void
4394 dissect_dcerpc_dg_reject_fault (tvbuff_t *tvb, int offset, packet_info *pinfo,
4395                         proto_tree *dcerpc_tree,
4396                         e_dce_dg_common_hdr_t *hdr)
4397 {
4398     guint32 status;
4399
4400     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree,
4401                                     hdr->drep, hf_dcerpc_dg_status,
4402                                     &status);
4403
4404     if (check_col (pinfo->cinfo, COL_INFO)) {
4405         col_append_fstr (pinfo->cinfo, COL_INFO,
4406                       ": status: %s",
4407                       val_to_str(status, reject_status_vals, "Unknown (0x%08x)"));
4408     }
4409 }
4410
4411 static void
4412 dissect_dcerpc_dg_stub (tvbuff_t *tvb, int offset, packet_info *pinfo,
4413                         proto_tree *dcerpc_tree, proto_tree *tree,
4414                         e_dce_dg_common_hdr_t *hdr, dcerpc_info *di)
4415 {
4416     int length, reported_length, stub_length;
4417     gboolean save_fragmented;
4418     fragment_data *fd_head;
4419     tvbuff_t *next_tvb;
4420     proto_item *pi;
4421     proto_item *parent_pi;
4422
4423     if (check_col (pinfo->cinfo, COL_INFO))
4424         col_append_fstr (pinfo->cinfo, COL_INFO, " opnum: %u len: %u",
4425             di->call_data->opnum, hdr->frag_len );
4426
4427     length = tvb_length_remaining (tvb, offset);
4428     reported_length = tvb_reported_length_remaining (tvb, offset);
4429     stub_length = hdr->frag_len;
4430     if (length > stub_length)
4431         length = stub_length;
4432     if (reported_length > stub_length)
4433         reported_length = stub_length;
4434
4435     save_fragmented = pinfo->fragmented;
4436
4437     /* If we don't have reassembly enabled, or this packet contains
4438        the entire PDU, or if this is a short frame (or a frame
4439        not reassembled at a lower layer) that doesn't include all
4440        the data in the fragment, just call the handoff directly if
4441        this is the first fragment or the PDU isn't fragmented. */
4442     if( (!dcerpc_reassemble) || !(hdr->flags1 & PFCL1_FRAG) ||
4443                 !tvb_bytes_exist(tvb, offset, stub_length) ){
4444         if(hdr->frag_num == 0) {
4445
4446
4447             /* First fragment, possibly the only fragment */
4448
4449             /*
4450              * XXX - authentication info?
4451              */
4452             pinfo->fragmented = (hdr->flags1 & PFCL1_FRAG);
4453             next_tvb = tvb_new_subset (tvb, offset, length,
4454                                        reported_length);
4455             dcerpc_try_handoff (pinfo, tree, dcerpc_tree, next_tvb,
4456                                 next_tvb, hdr->drep, di, NULL);
4457         } else {
4458             /* PDU is fragmented and this isn't the first fragment */
4459             if (check_col(pinfo->cinfo, COL_INFO)) {
4460                 col_append_str(pinfo->cinfo, COL_INFO, " [DCE/RPC fragment]");
4461             }
4462             if (dcerpc_tree) {
4463                 if (length > 0) {
4464                     tvb_ensure_bytes_exist(tvb, offset, stub_length);
4465                     proto_tree_add_text (dcerpc_tree, tvb, offset, stub_length,
4466                                          "Fragment data (%d byte%s)",
4467                                          stub_length,
4468                                          plurality(stub_length, "", "s"));
4469                 }
4470             }
4471         }
4472     } else {
4473         /* Reassembly is enabled, the PDU is fragmented, and
4474            we have all the data in the fragment; the first two
4475            of those mean we should attempt reassembly, and the
4476            third means we can attempt reassembly. */
4477         if (dcerpc_tree) {
4478             if (length > 0) {
4479                 tvb_ensure_bytes_exist(tvb, offset, stub_length);
4480                 proto_tree_add_text (dcerpc_tree, tvb, offset, stub_length,
4481                                      "Fragment data (%d byte%s)", stub_length,
4482                                      plurality(stub_length, "", "s"));
4483             }
4484         }
4485
4486         fd_head = fragment_add_dcerpc_dg(tvb, offset, pinfo,
4487                         hdr->seqnum, &hdr->act_id, dcerpc_cl_reassemble_table,
4488                         hdr->frag_num, stub_length,
4489                         !(hdr->flags1 & PFCL1_LASTFRAG));
4490     if (fd_head != NULL) {
4491             /* We completed reassembly... */
4492         if(pinfo->fd->num==fd_head->reassembled_in) {
4493             /* ...and this is the reassembled RPC PDU */
4494                 next_tvb = tvb_new_child_real_data(tvb, fd_head->data, fd_head->len, fd_head->len);
4495                 add_new_data_source(pinfo, next_tvb, "Reassembled DCE/RPC");
4496                 show_fragment_seq_tree(fd_head, &dcerpc_frag_items,
4497                                            tree, pinfo, next_tvb, &pi);
4498
4499                 /*
4500                  * XXX - authentication info?
4501                  */
4502                 pinfo->fragmented = FALSE;
4503                 dcerpc_try_handoff (pinfo, tree, dcerpc_tree, next_tvb,
4504                                         next_tvb, hdr->drep, di, NULL);
4505                 } else {
4506             /* ...and this isn't the reassembled RPC PDU */
4507                 pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_reassembled_in,
4508                                     tvb, 0, 0, fd_head->reassembled_in);
4509             PROTO_ITEM_SET_GENERATED(pi);
4510             parent_pi = proto_tree_get_parent(dcerpc_tree);
4511             if(parent_pi != NULL) {
4512                 proto_item_append_text(parent_pi, ", [Reas: #%u]", fd_head->reassembled_in);
4513             }
4514                 if (check_col(pinfo->cinfo, COL_INFO)) {
4515                     col_append_fstr(pinfo->cinfo, COL_INFO,
4516                             " [DCE/RPC fragment, reas: #%u]", fd_head->reassembled_in);
4517                 }
4518         }
4519         } else {
4520             /* Reassembly isn't completed yet */
4521             if (check_col(pinfo->cinfo, COL_INFO)) {
4522                 col_append_str(pinfo->cinfo, COL_INFO, " [DCE/RPC fragment]");
4523             }
4524         }
4525     }
4526     pinfo->fragmented = save_fragmented;
4527 }
4528
4529 static void
4530 dissect_dcerpc_dg_rqst (tvbuff_t *tvb, int offset, packet_info *pinfo,
4531                         proto_tree *dcerpc_tree, proto_tree *tree,
4532                         e_dce_dg_common_hdr_t *hdr, conversation_t *conv)
4533 {
4534     dcerpc_info *di;
4535     dcerpc_call_value *value, v;
4536     dcerpc_matched_key matched_key, *new_matched_key;
4537     proto_item *pi;
4538     proto_item *parent_pi;
4539
4540     di=get_next_di();
4541     if(!(pinfo->fd->flags.visited)){
4542         dcerpc_call_value *call_value;
4543         dcerpc_dg_call_key *call_key;
4544
4545         call_key=se_alloc (sizeof (dcerpc_dg_call_key));
4546         call_key->conv=conv;
4547         call_key->seqnum=hdr->seqnum;
4548         call_key->act_id=hdr->act_id;
4549
4550         call_value=se_alloc (sizeof (dcerpc_call_value));
4551         call_value->uuid = hdr->if_id;
4552         call_value->ver = hdr->if_ver;
4553         call_value->object_uuid = hdr->obj_id;
4554         call_value->opnum = hdr->opnum;
4555         call_value->req_frame=pinfo->fd->num;
4556         call_value->req_time=pinfo->fd->abs_ts;
4557         call_value->rep_frame=0;
4558         call_value->max_ptr=0;
4559         call_value->se_data = NULL;
4560         call_value->private_data = NULL;
4561         call_value->pol = NULL;
4562         g_hash_table_insert (dcerpc_dg_calls, call_key, call_value);
4563
4564         new_matched_key = se_alloc(sizeof (dcerpc_matched_key));
4565         new_matched_key->frame = pinfo->fd->num;
4566         new_matched_key->call_id = hdr->seqnum;
4567         g_hash_table_insert (dcerpc_matched, new_matched_key, call_value);
4568     }
4569
4570     matched_key.frame = pinfo->fd->num;
4571     matched_key.call_id = hdr->seqnum;
4572     value=g_hash_table_lookup(dcerpc_matched, &matched_key);
4573     if (!value) {
4574         v.uuid = hdr->if_id;
4575         v.ver = hdr->if_ver;
4576         v.object_uuid = hdr->obj_id;
4577         v.opnum = hdr->opnum;
4578         v.req_frame = pinfo->fd->num;
4579         v.rep_frame = 0;
4580         v.max_ptr = 0;
4581         v.se_data=NULL;
4582         v.private_data=NULL;
4583         value = &v;
4584     }
4585
4586     di->conv = conv;
4587     di->call_id = hdr->seqnum;
4588     di->smb_fid = -1;
4589     di->ptype = PDU_REQ;
4590     di->call_data = value;
4591
4592     if(value->rep_frame!=0){
4593         pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_response_in,
4594                             tvb, 0, 0, value->rep_frame);
4595     PROTO_ITEM_SET_GENERATED(pi);
4596     parent_pi = proto_tree_get_parent(dcerpc_tree);
4597     if(parent_pi != NULL) {
4598         proto_item_append_text(parent_pi, ", [Resp: #%u]", value->rep_frame);
4599     }
4600     }
4601     dissect_dcerpc_dg_stub (tvb, offset, pinfo, dcerpc_tree, tree, hdr, di);
4602 }
4603
4604 static void
4605 dissect_dcerpc_dg_resp (tvbuff_t *tvb, int offset, packet_info *pinfo,
4606                         proto_tree *dcerpc_tree, proto_tree *tree,
4607                         e_dce_dg_common_hdr_t *hdr, conversation_t *conv)
4608 {
4609     dcerpc_info *di;
4610     dcerpc_call_value *value, v;
4611     dcerpc_matched_key matched_key, *new_matched_key;
4612     proto_item *pi;
4613     proto_item *parent_pi;
4614
4615     di=get_next_di();
4616     if(!(pinfo->fd->flags.visited)){
4617         dcerpc_call_value *call_value;
4618         dcerpc_dg_call_key call_key;
4619
4620         call_key.conv=conv;
4621         call_key.seqnum=hdr->seqnum;
4622         call_key.act_id=hdr->act_id;
4623
4624         if((call_value=g_hash_table_lookup(dcerpc_dg_calls, &call_key))){
4625             new_matched_key = se_alloc(sizeof (dcerpc_matched_key));
4626             new_matched_key->frame = pinfo->fd->num;
4627             new_matched_key->call_id = hdr->seqnum;
4628             g_hash_table_insert (dcerpc_matched, new_matched_key, call_value);
4629             if(call_value->rep_frame==0){
4630                 call_value->rep_frame=pinfo->fd->num;
4631             }
4632         }
4633     }
4634
4635     matched_key.frame = pinfo->fd->num;
4636     matched_key.call_id = hdr->seqnum;
4637     value=g_hash_table_lookup(dcerpc_matched, &matched_key);
4638     if (!value) {
4639         v.uuid = hdr->if_id;
4640         v.ver = hdr->if_ver;
4641         v.object_uuid = hdr->obj_id;
4642         v.opnum = hdr->opnum;
4643         v.req_frame=0;
4644         v.rep_frame=pinfo->fd->num;
4645         v.se_data=NULL;
4646         v.private_data=NULL;
4647         value = &v;
4648     }
4649
4650     di->conv = conv;
4651     di->call_id = 0;
4652     di->smb_fid = -1;
4653     di->ptype = PDU_RESP;
4654     di->call_data = value;
4655
4656     if(value->req_frame!=0){
4657         nstime_t delta_ts;
4658         pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_request_in,
4659                             tvb, 0, 0, value->req_frame);
4660     PROTO_ITEM_SET_GENERATED(pi);
4661     parent_pi = proto_tree_get_parent(dcerpc_tree);
4662     if(parent_pi != NULL) {
4663         proto_item_append_text(parent_pi, ", [Req: #%u]", value->req_frame);
4664     }
4665         nstime_delta(&delta_ts, &pinfo->fd->abs_ts, &value->req_time);
4666         pi = proto_tree_add_time(dcerpc_tree, hf_dcerpc_time, tvb, offset, 0, &delta_ts);
4667     PROTO_ITEM_SET_GENERATED(pi);
4668     } else {
4669                 pi = proto_tree_add_text(dcerpc_tree,
4670                                     tvb, 0, 0, "No request to this DCE/RPC call found");
4671                 expert_add_info_format(pinfo, pi, PI_SEQUENCE, PI_NOTE,
4672                         "No request to this DCE/RPC call found");
4673     }
4674     dissect_dcerpc_dg_stub (tvb, offset, pinfo, dcerpc_tree, tree, hdr, di);
4675 }
4676
4677 static void
4678 dissect_dcerpc_dg_ping_ack (tvbuff_t *tvb, int offset, packet_info *pinfo,
4679                         proto_tree *dcerpc_tree,
4680                         e_dce_dg_common_hdr_t *hdr, conversation_t *conv)
4681 {
4682     proto_item *parent_pi;
4683 /*    if(!(pinfo->fd->flags.visited)){*/
4684         dcerpc_call_value *call_value;
4685         dcerpc_dg_call_key call_key;
4686
4687         call_key.conv=conv;
4688         call_key.seqnum=hdr->seqnum;
4689         call_key.act_id=hdr->act_id;
4690
4691         if((call_value=g_hash_table_lookup(dcerpc_dg_calls, &call_key))){
4692         proto_item *pi;
4693                 nstime_t delta_ts;
4694
4695                 pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_request_in,
4696                                     tvb, 0, 0, call_value->req_frame);
4697         PROTO_ITEM_SET_GENERATED(pi);
4698         parent_pi = proto_tree_get_parent(dcerpc_tree);
4699         if(parent_pi != NULL) {
4700             proto_item_append_text(parent_pi, ", [Req: #%u]", call_value->req_frame);
4701         }
4702
4703         if (check_col (pinfo->cinfo, COL_INFO))
4704             col_append_fstr(pinfo->cinfo, COL_INFO, " [req: #%u]", call_value->req_frame);
4705
4706                 nstime_delta(&delta_ts, &pinfo->fd->abs_ts, &call_value->req_time);
4707                 pi = proto_tree_add_time(dcerpc_tree, hf_dcerpc_time, tvb, offset, 0, &delta_ts);
4708         PROTO_ITEM_SET_GENERATED(pi);
4709 /*    }*/
4710     }
4711 }
4712
4713 /*
4714  * DCERPC dissector for connectionless calls
4715  */
4716 static gboolean
4717 dissect_dcerpc_dg (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4718 {
4719     proto_item *ti = NULL;
4720     proto_item *tf = NULL;
4721     proto_tree *dcerpc_tree = NULL;
4722     proto_tree *dg_flags1_tree = NULL;
4723     proto_tree *dg_flags2_tree = NULL;
4724     proto_tree *drep_tree = NULL;
4725     e_dce_dg_common_hdr_t hdr;
4726     int offset = 0;
4727     conversation_t *conv;
4728     int auth_level;
4729     char *uuid_str;
4730     const char *uuid_name = NULL;
4731
4732     /*
4733      * Check if this looks like a CL DCERPC call.  All dg packets
4734      * have an 80 byte header on them.  Which starts with
4735      * version (4), pkt_type.
4736      */
4737     if (tvb_length (tvb) < sizeof (hdr)) {
4738         return FALSE;
4739     }
4740
4741     /* Version must be 4 */
4742     hdr.rpc_ver = tvb_get_guint8 (tvb, offset++);
4743     if (hdr.rpc_ver != 4)
4744         return FALSE;
4745
4746     /* Type must be <=19 or its not DCE/RPC */
4747     hdr.ptype = tvb_get_guint8 (tvb, offset++);
4748     if (hdr.ptype > 19)
4749         return FALSE;
4750
4751     /* flags1 has bit 1 and 8 as reserved so if any of them are set, it is
4752        probably not a DCE/RPC packet
4753      */
4754     hdr.flags1 = tvb_get_guint8 (tvb, offset++);
4755     if(hdr.flags1&0x81)
4756         return FALSE;
4757
4758     /* flags2 has all bits except bit 2 as reserved so if any of them are set
4759        it is probably not DCE/RPC.
4760      */
4761     hdr.flags2 = tvb_get_guint8 (tvb, offset++);
4762     if(hdr.flags2&0xfd)
4763         return FALSE;
4764
4765
4766     if (check_col (pinfo->cinfo, COL_PROTOCOL))
4767         col_set_str (pinfo->cinfo, COL_PROTOCOL, "DCERPC");
4768     if (check_col (pinfo->cinfo, COL_INFO))
4769         col_add_str (pinfo->cinfo, COL_INFO, pckt_vals[hdr.ptype].strptr);
4770
4771     tvb_memcpy (tvb, (guint8 *)hdr.drep, offset, sizeof (hdr.drep));
4772     offset += sizeof (hdr.drep);
4773     hdr.serial_hi = tvb_get_guint8 (tvb, offset++);
4774     dcerpc_tvb_get_uuid (tvb, offset, hdr.drep, &hdr.obj_id);
4775     offset += 16;
4776     dcerpc_tvb_get_uuid (tvb, offset, hdr.drep, &hdr.if_id);
4777     offset += 16;
4778     dcerpc_tvb_get_uuid (tvb, offset, hdr.drep, &hdr.act_id);
4779     offset += 16;
4780     hdr.server_boot = dcerpc_tvb_get_ntohl (tvb, offset, hdr.drep);
4781     offset += 4;
4782     hdr.if_ver = dcerpc_tvb_get_ntohl (tvb, offset, hdr.drep);
4783     offset += 4;
4784     hdr.seqnum = dcerpc_tvb_get_ntohl (tvb, offset, hdr.drep);
4785     offset += 4;
4786     hdr.opnum = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
4787     offset += 2;
4788     hdr.ihint = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
4789     offset += 2;
4790     hdr.ahint = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
4791     offset += 2;
4792     hdr.frag_len = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
4793     offset += 2;
4794     hdr.frag_num = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
4795     offset += 2;
4796     hdr.auth_proto = tvb_get_guint8 (tvb, offset++);
4797     hdr.serial_lo = tvb_get_guint8 (tvb, offset++);
4798
4799     if (tree) {
4800         ti = proto_tree_add_item (tree, proto_dcerpc, tvb, 0, -1, FALSE);
4801         if (ti) {
4802             dcerpc_tree = proto_item_add_subtree(ti, ett_dcerpc);
4803                     proto_item_append_text(ti, " %s, Seq: %u, Serial: %u, Frag: %u, FragLen: %u",
4804                 val_to_str(hdr.ptype, pckt_vals, "Unknown (0x%02x)"),
4805                 hdr.seqnum, hdr.serial_hi*256+hdr.serial_lo,
4806                 hdr.frag_num, hdr.frag_len);
4807         }
4808     }
4809     offset = 0;
4810
4811     if (tree)
4812         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_ver, tvb, offset, 1, hdr.rpc_ver);
4813     offset++;
4814
4815     if (tree)
4816         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_packet_type, tvb, offset, 1, hdr.ptype);
4817     offset++;
4818
4819     if (tree) {
4820         tf = proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_flags1, tvb, offset, 1, hdr.flags1);
4821         dg_flags1_tree = proto_item_add_subtree (tf, ett_dcerpc_dg_flags1);
4822         if (dg_flags1_tree) {
4823             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_rsrvd_80, tvb, offset, 1, hdr.flags1);
4824             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_broadcast, tvb, offset, 1, hdr.flags1);
4825             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_idempotent, tvb, offset, 1, hdr.flags1);
4826             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_maybe, tvb, offset, 1, hdr.flags1);
4827             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_nofack, tvb, offset, 1, hdr.flags1);
4828             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_frag, tvb, offset, 1, hdr.flags1);
4829             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_last_frag, tvb, offset, 1, hdr.flags1);
4830             proto_tree_add_boolean (dg_flags1_tree, hf_dcerpc_dg_flags1_rsrvd_01, tvb, offset, 1, hdr.flags1);
4831             if(hdr.flags1) {
4832                         proto_item_append_text(tf, " %s%s%s%s%s%s",
4833                     (hdr.flags1 & PFCL1_BROADCAST) ? "\"Broadcast\" " : "",
4834                     (hdr.flags1 & PFCL1_IDEMPOTENT) ? "\"Idempotent\" " : "",
4835                     (hdr.flags1 & PFCL1_MAYBE) ? "\"Maybe\" " : "",
4836                     (hdr.flags1 & PFCL1_NOFACK) ? "\"No Fack\" " : "",
4837                     (hdr.flags1 & PFCL1_FRAG) ? "\"Fragment\" " : "",
4838                     (hdr.flags1 & PFCL1_LASTFRAG) ? "\"Last Fragment\" " : "");
4839             }
4840         }
4841     }
4842     offset++;
4843
4844     if (tree) {
4845         tf = proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_flags2, tvb, offset, 1, hdr.flags2);
4846         dg_flags2_tree = proto_item_add_subtree (tf, ett_dcerpc_dg_flags2);
4847         if (dg_flags2_tree) {
4848             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_80, tvb, offset, 1, hdr.flags2);
4849             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_40, tvb, offset, 1, hdr.flags2);
4850             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_20, tvb, offset, 1, hdr.flags2);
4851             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_10, tvb, offset, 1, hdr.flags2);
4852             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_08, tvb, offset, 1, hdr.flags2);
4853             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_04, tvb, offset, 1, hdr.flags2);
4854             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_cancel_pending, tvb, offset, 1, hdr.flags2);
4855             proto_tree_add_boolean (dg_flags2_tree, hf_dcerpc_dg_flags2_rsrvd_01, tvb, offset, 1, hdr.flags2);
4856             if(hdr.flags2) {
4857                         proto_item_append_text(tf, " %s",
4858                     (hdr.flags2 & PFCL2_CANCEL_PENDING) ? "\"Cancel Pending\" " : "");
4859             }
4860         }
4861     }
4862     offset++;
4863
4864     if (tree) {
4865         tf = proto_tree_add_bytes (dcerpc_tree, hf_dcerpc_drep, tvb, offset, sizeof (hdr.drep), hdr.drep);
4866         drep_tree = proto_item_add_subtree (tf, ett_dcerpc_drep);
4867         if (drep_tree) {
4868             proto_tree_add_uint(drep_tree, hf_dcerpc_drep_byteorder, tvb, offset, 1, hdr.drep[0] >> 4);
4869             proto_tree_add_uint(drep_tree, hf_dcerpc_drep_character, tvb, offset, 1, hdr.drep[0] & 0x0f);
4870             proto_tree_add_uint(drep_tree, hf_dcerpc_drep_fp, tvb, offset+1, 1, hdr.drep[1]);
4871                     proto_item_append_text(tf, " (Order: %s, Char: %s, Float: %s)",
4872                 val_to_str(hdr.drep[0] >> 4, drep_byteorder_vals, "Unknown"),
4873                 val_to_str(hdr.drep[0] & 0x0f, drep_character_vals, "Unknown"),
4874                 val_to_str(hdr.drep[1], drep_fp_vals, "Unknown"));
4875         }
4876     }
4877     offset += sizeof (hdr.drep);
4878
4879     if (tree)
4880         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_serial_hi, tvb, offset, 1, hdr.serial_hi);
4881     offset++;
4882
4883     if (tree) {
4884         proto_tree_add_guid_format (dcerpc_tree, hf_dcerpc_obj_id, tvb,
4885             offset, 16, (e_guid_t *) &hdr.obj_id, "Object UUID: %s",
4886             guid_to_str((e_guid_t *) &hdr.obj_id));
4887     }
4888     offset += 16;
4889
4890     if (tree) {
4891         uuid_str = guid_to_str((e_guid_t*)&hdr.if_id);
4892         uuid_name = guids_get_uuid_name(&hdr.if_id);
4893         if(uuid_name) {
4894                   proto_tree_add_guid_format (dcerpc_tree, hf_dcerpc_dg_if_id, tvb,
4895                                         offset, 16, (e_guid_t *) &hdr.if_id, "Interface: %s UUID: %s", uuid_name, uuid_str);
4896         } else {
4897           proto_tree_add_guid_format (dcerpc_tree, hf_dcerpc_dg_if_id, tvb,
4898                                         offset, 16, (e_guid_t *) &hdr.if_id, "Interface UUID: %s", uuid_str);
4899         }
4900     }
4901     offset += 16;
4902
4903     if (tree) {
4904         proto_tree_add_guid_format (dcerpc_tree, hf_dcerpc_dg_act_id, tvb,
4905                                       offset, 16, (e_guid_t *) &hdr.act_id, "Activity: %s",
4906                                       guid_to_str((e_guid_t *) &hdr.act_id));
4907     }
4908     offset += 16;
4909
4910     if (tree) {
4911         nstime_t server_boot;
4912
4913         server_boot.secs  = hdr.server_boot;
4914         server_boot.nsecs = 0;
4915
4916         if (hdr.server_boot == 0)
4917             proto_tree_add_time_format (dcerpc_tree, hf_dcerpc_dg_server_boot,
4918                                         tvb, offset, 4, &server_boot,
4919                                         "Server boot time: Unknown (0)");
4920         else
4921             proto_tree_add_time (dcerpc_tree, hf_dcerpc_dg_server_boot,
4922                                  tvb, offset, 4, &server_boot);
4923     }
4924     offset += 4;
4925
4926     if (tree)
4927         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_if_ver, tvb, offset, 4, hdr.if_ver);
4928     offset += 4;
4929
4930     if (tree)
4931         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_seqnum, tvb, offset, 4, hdr.seqnum);
4932     if (check_col (pinfo->cinfo, COL_INFO)) {
4933         col_append_fstr (pinfo->cinfo, COL_INFO, ": seq: %u", hdr.seqnum);
4934     }
4935     if (check_col (pinfo->cinfo, COL_DCE_CALL)) {
4936         col_append_fstr (pinfo->cinfo, COL_DCE_CALL, "%u", hdr.seqnum);
4937     }
4938     offset += 4;
4939
4940     if (tree)
4941         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_opnum, tvb, offset, 2, hdr.opnum);
4942     offset += 2;
4943
4944     if (tree)
4945         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_ihint, tvb, offset, 2, hdr.ihint);
4946     offset += 2;
4947
4948     if (tree)
4949         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_ahint, tvb, offset, 2, hdr.ahint);
4950     offset += 2;
4951
4952     if (tree)
4953         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_frag_len, tvb, offset, 2, hdr.frag_len);
4954     offset += 2;
4955
4956     if (tree)
4957         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_frag_num, tvb, offset, 2, hdr.frag_num);
4958     if (check_col (pinfo->cinfo, COL_INFO)) {
4959         if (hdr.flags1 & PFCL1_FRAG) {
4960             /* Fragmented - put the fragment number into the Info column */
4961             col_append_fstr (pinfo->cinfo, COL_INFO, " frag: %u",
4962                              hdr.frag_num);
4963         }
4964     }
4965     offset += 2;
4966
4967     if (tree)
4968         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_auth_proto, tvb, offset, 1, hdr.auth_proto);
4969     offset++;
4970
4971     if (tree)
4972         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_dg_serial_lo, tvb, offset, 1, hdr.serial_lo);
4973     if (check_col (pinfo->cinfo, COL_INFO)) {
4974         if (hdr.flags1 & PFCL1_FRAG) {
4975             /* Fragmented - put the serial number into the Info column */
4976             col_append_fstr (pinfo->cinfo, COL_INFO, " serial: %u",
4977                              (hdr.serial_hi << 8) | hdr.serial_lo);
4978         }
4979     }
4980     offset++;
4981
4982     if (tree) {
4983         /*
4984          * XXX - for Kerberos, we get a protection level; if it's
4985          * DCE_C_AUTHN_LEVEL_PKT_PRIVACY, we can't dissect the
4986          * stub data.
4987          */
4988         dissect_dcerpc_dg_auth (tvb, offset, dcerpc_tree, &hdr,
4989                                 &auth_level);
4990     }
4991
4992     /*
4993      * keeping track of the conversation shouldn't really be necessary
4994      * for connectionless packets, because everything we need to know
4995      * to dissect is in the header for each packet.  Unfortunately,
4996      * Microsoft's implementation is buggy and often puts the
4997      * completely wrong if_id in the header.  go figure.  So, keep
4998      * track of the seqnum and use that if possible.  Note: that's not
4999      * completely correct.  It should really be done based on both the
5000      * activity_id and seqnum.  I haven't seen anywhere that it would
5001      * make a difference, but for future reference...
5002      */
5003     conv = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
5004                               pinfo->srcport, pinfo->destport, 0);
5005     if (!conv) {
5006         fprintf(stderr,"Creating a new conv on packet %d\n",pinfo->fd->num);
5007         conv = conversation_new (pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
5008                                  pinfo->srcport, pinfo->destport, 0);
5009     }
5010
5011     /*
5012      * Packet type specific stuff is next.
5013      */
5014
5015     switch (hdr.ptype) {
5016
5017     case PDU_CANCEL_ACK:
5018         /* Body is optional */
5019         /* XXX - we assume "frag_len" is the length of the body */
5020         if (hdr.frag_len != 0)
5021             dissect_dcerpc_dg_cancel_ack (tvb, offset, pinfo, dcerpc_tree, &hdr);
5022         break;
5023
5024     case PDU_CL_CANCEL:
5025         /*
5026          * XXX - The DCE RPC 1.1 spec doesn't say the body is optional,
5027          * but in at least one capture none of the Cl_cancel PDUs had a
5028          * body.
5029          */
5030         /* XXX - we assume "frag_len" is the length of the body */
5031         if (hdr.frag_len != 0)
5032             dissect_dcerpc_dg_cancel (tvb, offset, pinfo, dcerpc_tree, &hdr);
5033         break;
5034
5035     case PDU_NOCALL:
5036         /* Body is optional; if present, it's the same as PDU_FACK */
5037         /* XXX - we assume "frag_len" is the length of the body */
5038         if (hdr.frag_len != 0)
5039             dissect_dcerpc_dg_fack (tvb, offset, pinfo, dcerpc_tree, &hdr);
5040         break;
5041
5042     case PDU_FACK:
5043         /* Body is optional */
5044         /* XXX - we assume "frag_len" is the length of the body */
5045         if (hdr.frag_len != 0)
5046             dissect_dcerpc_dg_fack (tvb, offset, pinfo, dcerpc_tree, &hdr);
5047         break;
5048
5049     case PDU_REJECT:
5050     case PDU_FAULT:
5051         dissect_dcerpc_dg_reject_fault (tvb, offset, pinfo, dcerpc_tree, &hdr);
5052         break;
5053
5054     case PDU_REQ:
5055         dissect_dcerpc_dg_rqst (tvb, offset, pinfo, dcerpc_tree, tree, &hdr, conv);
5056         break;
5057
5058     case PDU_RESP:
5059         dissect_dcerpc_dg_resp (tvb, offset, pinfo, dcerpc_tree, tree, &hdr, conv);
5060         break;
5061
5062     /* these requests have no body */
5063     case PDU_ACK:
5064     case PDU_PING:
5065         dissect_dcerpc_dg_ping_ack (tvb, offset, pinfo, dcerpc_tree, &hdr, conv);
5066         break;
5067     case PDU_WORKING:
5068     default:
5069         break;
5070     }
5071
5072     return TRUE;
5073 }
5074
5075 static void
5076 dcerpc_init_protocol (void)
5077 {
5078         /* structures and data for BIND */
5079         if (dcerpc_binds){
5080                 g_hash_table_destroy (dcerpc_binds);
5081                 dcerpc_binds=NULL;
5082         }
5083         if(!dcerpc_binds){
5084                 dcerpc_binds = g_hash_table_new (dcerpc_bind_hash, dcerpc_bind_equal);
5085         }
5086
5087         /* structures and data for CALL */
5088         if (dcerpc_cn_calls){
5089                 g_hash_table_destroy (dcerpc_cn_calls);
5090         }
5091         dcerpc_cn_calls = g_hash_table_new (dcerpc_cn_call_hash, dcerpc_cn_call_equal);
5092         if (dcerpc_dg_calls){
5093                 g_hash_table_destroy (dcerpc_dg_calls);
5094         }
5095         dcerpc_dg_calls = g_hash_table_new (dcerpc_dg_call_hash, dcerpc_dg_call_equal);
5096
5097         /* structure and data for MATCHED */
5098         if (dcerpc_matched){
5099                 g_hash_table_destroy (dcerpc_matched);
5100         }
5101         dcerpc_matched = g_hash_table_new (dcerpc_matched_hash, dcerpc_matched_equal);
5102
5103     /* call the registered hooks */
5104     g_hook_list_invoke(&dcerpc_hooks_init_protos, FALSE /* not may_recurse */);
5105 }
5106
5107 void
5108 proto_register_dcerpc (void)
5109 {
5110     static hf_register_info hf[] = {
5111         { &hf_dcerpc_request_in,
5112                 { "Request in frame", "dcerpc.request_in", FT_FRAMENUM, BASE_NONE,
5113                 NULL, 0, "This packet is a response to the packet with this number", HFILL }},
5114         { &hf_dcerpc_response_in,
5115                 { "Response in frame", "dcerpc.response_in", FT_FRAMENUM, BASE_NONE,
5116                 NULL, 0, "This packet will be responded in the packet with this number", HFILL }},
5117         { &hf_dcerpc_referent_id,
5118                 { "Referent ID", "dcerpc.referent_id", FT_UINT32, BASE_HEX,
5119                 NULL, 0, "Referent ID for this NDR encoded pointer", HFILL }},
5120         { &hf_dcerpc_ver,
5121           { "Version", "dcerpc.ver", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5122         { &hf_dcerpc_ver_minor,
5123           { "Version (minor)", "dcerpc.ver_minor", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5124         { &hf_dcerpc_packet_type,
5125           { "Packet type", "dcerpc.pkt_type", FT_UINT8, BASE_DEC, VALS (pckt_vals), 0x0, NULL, HFILL }},
5126         { &hf_dcerpc_cn_flags,
5127           { "Packet Flags", "dcerpc.cn_flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
5128         { &hf_dcerpc_cn_flags_first_frag,
5129           { "First Frag", "dcerpc.cn_flags.first_frag", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFC_FIRST_FRAG, NULL, HFILL }},
5130         { &hf_dcerpc_cn_flags_last_frag,
5131           { "Last Frag", "dcerpc.cn_flags.last_frag", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFC_LAST_FRAG, NULL, HFILL }},
5132         { &hf_dcerpc_cn_flags_cancel_pending,
5133           { "Cancel Pending", "dcerpc.cn_flags.cancel_pending", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFC_PENDING_CANCEL, NULL, HFILL }},
5134         { &hf_dcerpc_cn_flags_reserved,
5135           { "Reserved", "dcerpc.cn_flags.reserved", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFC_RESERVED_1, NULL, HFILL }},
5136         { &hf_dcerpc_cn_flags_mpx,
5137           { "Multiplex", "dcerpc.cn_flags.mpx", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFC_CONC_MPX, NULL, HFILL }},
5138         { &hf_dcerpc_cn_flags_dne,
5139           { "Did Not Execute", "dcerpc.cn_flags.dne", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFC_DID_NOT_EXECUTE, NULL, HFILL }},
5140         { &hf_dcerpc_cn_flags_maybe,
5141           { "Maybe", "dcerpc.cn_flags.maybe", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFC_MAYBE, NULL, HFILL }},
5142         { &hf_dcerpc_cn_flags_object,
5143           { "Object", "dcerpc.cn_flags.object", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFC_OBJECT_UUID, NULL, HFILL }},
5144         { &hf_dcerpc_drep,
5145           { "Data Representation", "dcerpc.drep", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5146         { &hf_dcerpc_drep_byteorder,
5147           { "Byte order", "dcerpc.drep.byteorder", FT_UINT8, BASE_DEC, VALS (drep_byteorder_vals), 0x0, NULL, HFILL }},
5148         { &hf_dcerpc_drep_character,
5149           { "Character", "dcerpc.drep.character", FT_UINT8, BASE_DEC, VALS (drep_character_vals), 0x0, NULL, HFILL }},
5150         { &hf_dcerpc_drep_fp,
5151           { "Floating-point", "dcerpc.drep.fp", FT_UINT8, BASE_DEC, VALS (drep_fp_vals), 0x0, NULL, HFILL }},
5152         { &hf_dcerpc_cn_frag_len,
5153           { "Frag Length", "dcerpc.cn_frag_len", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5154         { &hf_dcerpc_cn_auth_len,
5155           { "Auth Length", "dcerpc.cn_auth_len", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5156         { &hf_dcerpc_cn_call_id,
5157           { "Call ID", "dcerpc.cn_call_id", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5158         { &hf_dcerpc_cn_max_xmit,
5159           { "Max Xmit Frag", "dcerpc.cn_max_xmit", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5160         { &hf_dcerpc_cn_max_recv,
5161           { "Max Recv Frag", "dcerpc.cn_max_recv", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5162         { &hf_dcerpc_cn_assoc_group,
5163           { "Assoc Group", "dcerpc.cn_assoc_group", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
5164         { &hf_dcerpc_cn_num_ctx_items,
5165           { "Num Ctx Items", "dcerpc.cn_num_ctx_items", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5166         { &hf_dcerpc_cn_ctx_item,
5167           { "Ctx Item", "dcerpc.cn_ctx_item", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5168         { &hf_dcerpc_cn_ctx_id,
5169           { "Context ID", "dcerpc.cn_ctx_id", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5170         { &hf_dcerpc_cn_num_trans_items,
5171           { "Num Trans Items", "dcerpc.cn_num_trans_items", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5172         { &hf_dcerpc_cn_bind_abstract_syntax,
5173           { "Abstract Syntax", "dcerpc.cn_bind_abstract_syntax", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5174         { &hf_dcerpc_cn_bind_if_id,
5175           { "Interface UUID", "dcerpc.cn_bind_to_uuid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5176         { &hf_dcerpc_cn_bind_if_ver,
5177           { "Interface Ver", "dcerpc.cn_bind_if_ver", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5178         { &hf_dcerpc_cn_bind_if_ver_minor,
5179           { "Interface Ver Minor", "dcerpc.cn_bind_if_ver_minor", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5180         { &hf_dcerpc_cn_bind_trans_syntax,
5181           { "Transfer Syntax", "dcerpc.cn_bind_trans", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5182         { &hf_dcerpc_cn_bind_trans_id,
5183           { "ID", "dcerpc.cn_bind_trans_id", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5184         { &hf_dcerpc_cn_bind_trans_ver,
5185           { "ver", "dcerpc.cn_bind_trans_ver", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5186         { &hf_dcerpc_cn_alloc_hint,
5187           { "Alloc hint", "dcerpc.cn_alloc_hint", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5188         { &hf_dcerpc_cn_sec_addr_len,
5189           { "Scndry Addr len", "dcerpc.cn_sec_addr_len", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5190         { &hf_dcerpc_cn_sec_addr,
5191           { "Scndry Addr", "dcerpc.cn_sec_addr", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5192         { &hf_dcerpc_cn_num_results,
5193           { "Num results", "dcerpc.cn_num_results", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5194         { &hf_dcerpc_cn_ack_result,
5195           { "Ack result", "dcerpc.cn_ack_result", FT_UINT16, BASE_DEC, VALS(p_cont_result_vals), 0x0, NULL, HFILL }},
5196         { &hf_dcerpc_cn_ack_reason,
5197           { "Ack reason", "dcerpc.cn_ack_reason", FT_UINT16, BASE_DEC, VALS(p_provider_reason_vals), 0x0, NULL, HFILL }},
5198         { &hf_dcerpc_cn_ack_trans_id,
5199           { "Transfer Syntax", "dcerpc.cn_ack_trans_id", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5200         { &hf_dcerpc_cn_ack_trans_ver,
5201           { "Syntax ver", "dcerpc.cn_ack_trans_ver", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5202         { &hf_dcerpc_cn_reject_reason,
5203           { "Reject reason", "dcerpc.cn_reject_reason", FT_UINT16, BASE_DEC, VALS(reject_reason_vals), 0x0, NULL, HFILL }},
5204         { &hf_dcerpc_cn_num_protocols,
5205           { "Number of protocols", "dcerpc.cn_num_protocols", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5206         { &hf_dcerpc_cn_protocol_ver_major,
5207           { "Protocol major version", "dcerpc.cn_protocol_ver_major", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5208         { &hf_dcerpc_cn_protocol_ver_minor,
5209           { "Protocol minor version", "dcerpc.cn_protocol_ver_minor", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5210         { &hf_dcerpc_cn_cancel_count,
5211           { "Cancel count", "dcerpc.cn_cancel_count", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5212         { &hf_dcerpc_cn_status,
5213           { "Status", "dcerpc.cn_status", FT_UINT32, BASE_HEX, VALS(reject_status_vals), 0x0, NULL, HFILL }},
5214         { &hf_dcerpc_cn_deseg_req,
5215           { "Desegmentation Required", "dcerpc.cn_deseg_req", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5216         { &hf_dcerpc_auth_type,
5217           { "Auth type", "dcerpc.auth_type", FT_UINT8, BASE_DEC, VALS (authn_protocol_vals), 0x0, NULL, HFILL }},
5218         { &hf_dcerpc_auth_level,
5219           { "Auth level", "dcerpc.auth_level", FT_UINT8, BASE_DEC, VALS (authn_level_vals), 0x0, NULL, HFILL }},
5220         { &hf_dcerpc_auth_pad_len,
5221           { "Auth pad len", "dcerpc.auth_pad_len", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5222         { &hf_dcerpc_auth_rsrvd,
5223           { "Auth Rsrvd", "dcerpc.auth_rsrvd", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5224         { &hf_dcerpc_auth_ctx_id,
5225           { "Auth Context ID", "dcerpc.auth_ctx_id", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5226         { &hf_dcerpc_dg_flags1,
5227           { "Flags1", "dcerpc.dg_flags1", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
5228         { &hf_dcerpc_dg_flags1_rsrvd_01,
5229           { "Reserved", "dcerpc.dg_flags1_rsrvd_01", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFCL1_RESERVED_01, NULL, HFILL }},
5230         { &hf_dcerpc_dg_flags1_last_frag,
5231           { "Last Fragment", "dcerpc.dg_flags1_last_frag", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFCL1_LASTFRAG, NULL, HFILL }},
5232         { &hf_dcerpc_dg_flags1_frag,
5233           { "Fragment", "dcerpc.dg_flags1_frag", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFCL1_FRAG, NULL, HFILL }},
5234         { &hf_dcerpc_dg_flags1_nofack,
5235           { "No Fack", "dcerpc.dg_flags1_nofack", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFCL1_NOFACK, NULL, HFILL }},
5236         { &hf_dcerpc_dg_flags1_maybe,
5237           { "Maybe", "dcerpc.dg_flags1_maybe", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFCL1_MAYBE, NULL, HFILL }},
5238         { &hf_dcerpc_dg_flags1_idempotent,
5239           { "Idempotent", "dcerpc.dg_flags1_idempotent", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFCL1_IDEMPOTENT, NULL, HFILL }},
5240         { &hf_dcerpc_dg_flags1_broadcast,
5241           { "Broadcast", "dcerpc.dg_flags1_broadcast", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFCL1_BROADCAST, NULL, HFILL }},
5242         { &hf_dcerpc_dg_flags1_rsrvd_80,
5243           { "Reserved", "dcerpc.dg_flags1_rsrvd_80", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFCL1_RESERVED_80, NULL, HFILL }},
5244         { &hf_dcerpc_dg_flags2,
5245           { "Flags2", "dcerpc.dg_flags2", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
5246         { &hf_dcerpc_dg_flags2_rsrvd_01,
5247           { "Reserved", "dcerpc.dg_flags2_rsrvd_01", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFCL2_RESERVED_01, NULL, HFILL }},
5248         { &hf_dcerpc_dg_flags2_cancel_pending,
5249           { "Cancel Pending", "dcerpc.dg_flags2_cancel_pending", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFCL2_CANCEL_PENDING, NULL, HFILL }},
5250         { &hf_dcerpc_dg_flags2_rsrvd_04,
5251           { "Reserved", "dcerpc.dg_flags2_rsrvd_04", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFCL2_RESERVED_04, NULL, HFILL }},
5252         { &hf_dcerpc_dg_flags2_rsrvd_08,
5253           { "Reserved", "dcerpc.dg_flags2_rsrvd_08", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFCL2_RESERVED_08, NULL, HFILL }},
5254         { &hf_dcerpc_dg_flags2_rsrvd_10,
5255           { "Reserved", "dcerpc.dg_flags2_rsrvd_10", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFCL2_RESERVED_10, NULL, HFILL }},
5256         { &hf_dcerpc_dg_flags2_rsrvd_20,
5257           { "Reserved", "dcerpc.dg_flags2_rsrvd_20", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFCL2_RESERVED_20, NULL, HFILL }},
5258         { &hf_dcerpc_dg_flags2_rsrvd_40,
5259           { "Reserved", "dcerpc.dg_flags2_rsrvd_40", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFCL2_RESERVED_40, NULL, HFILL }},
5260         { &hf_dcerpc_dg_flags2_rsrvd_80,
5261           { "Reserved", "dcerpc.dg_flags2_rsrvd_80", FT_BOOLEAN, 8, TFS (&tfs_set_notset), PFCL2_RESERVED_80, NULL, HFILL }},
5262         { &hf_dcerpc_dg_serial_lo,
5263           { "Serial Low", "dcerpc.dg_serial_lo", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
5264         { &hf_dcerpc_dg_serial_hi,
5265           { "Serial High", "dcerpc.dg_serial_hi", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
5266         { &hf_dcerpc_dg_ahint,
5267           { "Activity Hint", "dcerpc.dg_ahint", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
5268         { &hf_dcerpc_dg_ihint,
5269           { "Interface Hint", "dcerpc.dg_ihint", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
5270         { &hf_dcerpc_dg_frag_len,
5271           { "Fragment len", "dcerpc.dg_frag_len", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5272         { &hf_dcerpc_dg_frag_num,
5273           { "Fragment num", "dcerpc.dg_frag_num", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5274         { &hf_dcerpc_dg_auth_proto,
5275           { "Auth proto", "dcerpc.dg_auth_proto", FT_UINT8, BASE_DEC, VALS (authn_protocol_vals), 0x0, NULL, HFILL }},
5276         { &hf_dcerpc_dg_seqnum,
5277           { "Sequence num", "dcerpc.dg_seqnum", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5278         { &hf_dcerpc_dg_server_boot,
5279           { "Server boot time", "dcerpc.dg_server_boot", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5280         { &hf_dcerpc_dg_if_ver,
5281           { "Interface Ver", "dcerpc.dg_if_ver", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5282         { &hf_dcerpc_krb5_av_prot_level,
5283           { "Protection Level", "dcerpc.krb5_av.prot_level", FT_UINT8, BASE_DEC, VALS(authn_level_vals), 0x0, NULL, HFILL }},
5284         { &hf_dcerpc_krb5_av_key_vers_num,
5285           { "Key Version Number", "dcerpc.krb5_av.key_vers_num", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5286         { &hf_dcerpc_krb5_av_key_auth_verifier,
5287           { "Authentication Verifier", "dcerpc.krb5_av.auth_verifier", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5288         { &hf_dcerpc_obj_id,
5289           { "Object", "dcerpc.obj_id", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5290         { &hf_dcerpc_dg_if_id,
5291           { "Interface", "dcerpc.dg_if_id", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5292         { &hf_dcerpc_dg_act_id,
5293           { "Activity", "dcerpc.dg_act_id", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5294         { &hf_dcerpc_opnum,
5295           { "Opnum", "dcerpc.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5296
5297         { &hf_dcerpc_dg_cancel_vers,
5298           { "Cancel Version", "dcerpc.dg_cancel_vers", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5299
5300         { &hf_dcerpc_dg_cancel_id,
5301           { "Cancel ID", "dcerpc.dg_cancel_id", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5302
5303         { &hf_dcerpc_dg_server_accepting_cancels,
5304           { "Server accepting cancels", "dcerpc.server_accepting_cancels", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5305
5306         { &hf_dcerpc_dg_fack_vers,
5307           { "FACK Version", "dcerpc.fack_vers", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5308
5309         { &hf_dcerpc_dg_fack_window_size,
5310           { "Window Size", "dcerpc.fack_window_size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5311
5312         { &hf_dcerpc_dg_fack_max_tsdu,
5313           { "Max TSDU", "dcerpc.fack_max_tsdu", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5314
5315         { &hf_dcerpc_dg_fack_max_frag_size,
5316           { "Max Frag Size", "dcerpc.fack_max_frag_size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5317
5318         { &hf_dcerpc_dg_fack_serial_num,
5319           { "Serial Num", "dcerpc.fack_serial_num", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5320
5321         { &hf_dcerpc_dg_fack_selack_len,
5322           { "Selective ACK Len", "dcerpc.fack_selack_len", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5323
5324         { &hf_dcerpc_dg_fack_selack,
5325           { "Selective ACK", "dcerpc.fack_selack", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
5326
5327         { &hf_dcerpc_dg_status,
5328           { "Status", "dcerpc.dg_status", FT_UINT32, BASE_HEX, VALS(reject_status_vals), 0x0, NULL, HFILL }},
5329
5330         { &hf_dcerpc_array_max_count,
5331           { "Max Count", "dcerpc.array.max_count", FT_UINT32, BASE_DEC, NULL, 0x0, "Maximum Count: Number of elements in the array", HFILL }},
5332
5333         { &hf_dcerpc_array_offset,
5334           { "Offset", "dcerpc.array.offset", FT_UINT32, BASE_DEC, NULL, 0x0, "Offset for first element in array", HFILL }},
5335
5336         { &hf_dcerpc_array_actual_count,
5337           { "Actual Count", "dcerpc.array.actual_count", FT_UINT32, BASE_DEC, NULL, 0x0, "Actual Count: Actual number of elements in the array", HFILL }},
5338
5339         { &hf_dcerpc_array_buffer,
5340           { "Buffer", "dcerpc.array.buffer", FT_BYTES, BASE_NONE, NULL, 0x0, "Buffer: Buffer containing elements of the array", HFILL }},
5341
5342         { &hf_dcerpc_op,
5343           { "Operation", "dcerpc.op", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
5344
5345         { &hf_dcerpc_fragments,
5346           { "Reassembled DCE/RPC Fragments", "dcerpc.fragments", FT_NONE, BASE_NONE,
5347           NULL, 0x0, "DCE/RPC Fragments", HFILL }},
5348
5349         { &hf_dcerpc_fragment,
5350           { "DCE/RPC Fragment", "dcerpc.fragment", FT_FRAMENUM, BASE_NONE,
5351           NULL, 0x0, NULL, HFILL }},
5352
5353         { &hf_dcerpc_fragment_overlap,
5354           { "Fragment overlap", "dcerpc.fragment.overlap", FT_BOOLEAN, BASE_NONE,
5355       NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
5356
5357         { &hf_dcerpc_fragment_overlap_conflict,
5358           { "Conflicting data in fragment overlap", "dcerpc.fragment.overlap.conflict", FT_BOOLEAN, BASE_NONE,
5359       NULL, 0x0, "Overlapping fragments contained conflicting data", HFILL }},
5360
5361         { &hf_dcerpc_fragment_multiple_tails,
5362           { "Multiple tail fragments found", "dcerpc.fragment.multipletails", FT_BOOLEAN, BASE_NONE,
5363       NULL, 0x0, "Several tails were found when defragmenting the packet", HFILL }},
5364
5365         { &hf_dcerpc_fragment_too_long_fragment,
5366           { "Fragment too long", "dcerpc.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE,
5367       NULL, 0x0, "Fragment contained data past end of packet", HFILL }},
5368
5369         { &hf_dcerpc_fragment_error,
5370           { "Defragmentation error", "dcerpc.fragment.error", FT_FRAMENUM, BASE_NONE,
5371       NULL, 0x0, "Defragmentation error due to illegal fragments", HFILL }},
5372
5373         { &hf_dcerpc_time,
5374           { "Time from request", "dcerpc.time", FT_RELATIVE_TIME, BASE_NONE,
5375       NULL, 0, "Time between Request and Response for DCE-RPC calls", HFILL }},
5376
5377         { &hf_dcerpc_reassembled_in,
5378       { "Reassembled PDU in frame", "dcerpc.reassembled_in", FT_FRAMENUM, BASE_NONE,
5379       NULL, 0x0, "The DCE/RPC PDU is completely reassembled in the packet with this number", HFILL }},
5380
5381         { &hf_dcerpc_unknown_if_id,
5382           { "Unknown DCERPC interface id", "dcerpc.unknown_if_id", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5383    };
5384     static gint *ett[] = {
5385         &ett_dcerpc,
5386         &ett_dcerpc_cn_flags,
5387         &ett_dcerpc_cn_ctx,
5388         &ett_dcerpc_cn_iface,
5389         &ett_dcerpc_cn_trans_syntax,
5390         &ett_dcerpc_drep,
5391         &ett_dcerpc_dg_flags1,
5392         &ett_dcerpc_dg_flags2,
5393         &ett_dcerpc_pointer_data,
5394         &ett_dcerpc_string,
5395         &ett_dcerpc_fragments,
5396         &ett_dcerpc_fragment,
5397         &ett_dcerpc_krb5_auth_verf,
5398     };
5399     module_t *dcerpc_module;
5400
5401     proto_dcerpc = proto_register_protocol ("DCE RPC", "DCERPC", "dcerpc");
5402     proto_register_field_array (proto_dcerpc, hf, array_length (hf));
5403     proto_register_subtree_array (ett, array_length (ett));
5404     register_init_routine (dcerpc_init_protocol);
5405     dcerpc_module = prefs_register_protocol (proto_dcerpc, NULL);
5406     prefs_register_bool_preference (dcerpc_module,
5407                                     "desegment_dcerpc",
5408                                     "Reassemble DCE/RPC messages spanning multiple TCP segments",
5409                                     "Whether the DCE/RPC dissector should reassemble messages spanning multiple TCP segments."
5410                                     " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
5411                                     &dcerpc_cn_desegment);
5412     prefs_register_bool_preference (dcerpc_module,
5413                                     "reassemble_dcerpc",
5414                                     "Reassemble DCE/RPC fragments",
5415                                     "Whether the DCE/RPC dissector should reassemble fragmented DCE/RPC PDUs",
5416                                     &dcerpc_reassemble);
5417     register_init_routine(dcerpc_reassemble_init);
5418     dcerpc_uuids = g_hash_table_new (dcerpc_uuid_hash, dcerpc_uuid_equal);
5419     dcerpc_tap=register_tap("dcerpc");
5420
5421     g_hook_list_init(&dcerpc_hooks_init_protos, sizeof(GHook));
5422 }
5423
5424 void
5425 proto_reg_handoff_dcerpc (void)
5426 {
5427     heur_dissector_add ("tcp", dissect_dcerpc_cn_bs, proto_dcerpc);
5428     heur_dissector_add ("netbios", dissect_dcerpc_cn_pk, proto_dcerpc);
5429     heur_dissector_add ("udp", dissect_dcerpc_dg, proto_dcerpc);
5430     heur_dissector_add ("smb_transact", dissect_dcerpc_cn_smbpipe, proto_dcerpc);
5431     heur_dissector_add ("smb2_heur_subdissectors", dissect_dcerpc_cn_smb2, proto_dcerpc);
5432     heur_dissector_add ("http", dissect_dcerpc_cn_bs, proto_dcerpc);
5433     dcerpc_smb_init(proto_dcerpc);
5434 }