From Stefan Metzmacher:
[obnox/wireshark/wip.git] / epan / dissectors / packet-dcerpc.c
1 /* packet-dcerpc.c
2  * Routines for DCERPC packet disassembly
3  * Copyright 2001, Todd Sabin <tas@webspan.net>
4  * Copyright 2003, Tim Potter <tpot@samba.org>
5  *
6  * $Id$
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  */
26
27 /* The DCE RPC specification can be found at:
28  * http://www.opengroup.org/dce/
29  */
30
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34
35 #include <string.h>
36 #include <ctype.h>
37
38 #include <glib.h>
39 #include <epan/packet.h>
40 #include <epan/dissectors/packet-dcerpc.h>
41 #include <epan/conversation.h>
42 #include <epan/prefs.h>
43 #include <epan/reassemble.h>
44 #include <epan/tap.h>
45 #include <epan/emem.h>
46 #include <epan/dissectors/packet-frame.h>
47 #include <epan/dissectors/packet-dcerpc-nt.h>
48 #include <epan/expert.h>
49 #include <epan/strutil.h>
50
51 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         { 0x8004CB09, "CBA_E_INVALIDCOOKIE" },
314         { 0x8004CB0B, "CBA_E_QOSTYPEUNSUPPORTED" },
315         { 0x8004CB0C, "CBA_E_QOSVALUEUNSUPPORTED" },
316         { 0x8004CB0F, "CBA_E_NOTAPPLICABLE" },
317         { 0x8004CB12, "CBA_E_LIMITVIOLATION" },
318         { 0x8004CB13, "CBA_E_QOSTYPENOTAPPLICABLE" },
319         { 0x8004CB18, "CBA_E_OUTOFPARTNERACCOS" },
320         { 0x8004CB1C, "CBA_E_FLAGUNSUPPORTED" },
321         { 0x8004CB23, "CBA_E_FRAMECOUNTUNSUPPORTED" },
322         { 0x8004CB25, "CBA_E_MODECHANGE" },
323         { 0x8007000E, "E_OUTOFMEMORY" },
324         { 0x80070057, "E_INVALIDARG" },
325         { 0x800706d1, "RPC_S_PROCNUM_OUT_OF_RANGE" },
326         { 0x80070776, "OR_INVALID_OXID" },
327         { 0,          NULL }
328 };
329
330
331 /* we need to keep track of what transport were used, ie what handle we came
332  * in through so we know what kind of pinfo->dce_smb_fid was passed to us.
333  */
334 /* Value of -1 is reserved for "not DCE packet" in packet_info.dcetransporttype. */
335 #define DCE_TRANSPORT_UNKNOWN           0
336 #define DCE_CN_TRANSPORT_SMBPIPE        1
337
338
339 static int proto_dcerpc = -1;
340
341 /* field defines */
342 static int hf_dcerpc_request_in = -1;
343 static int hf_dcerpc_time = -1;
344 static int hf_dcerpc_response_in = -1;
345 static int hf_dcerpc_ver = -1;
346 static int hf_dcerpc_ver_minor = -1;
347 static int hf_dcerpc_packet_type = -1;
348 static int hf_dcerpc_cn_flags = -1;
349 static int hf_dcerpc_cn_flags_first_frag = -1;
350 static int hf_dcerpc_cn_flags_last_frag = -1;
351 static int hf_dcerpc_cn_flags_cancel_pending = -1;
352 static int hf_dcerpc_cn_flags_reserved = -1;
353 static int hf_dcerpc_cn_flags_mpx = -1;
354 static int hf_dcerpc_cn_flags_dne = -1;
355 static int hf_dcerpc_cn_flags_maybe = -1;
356 static int hf_dcerpc_cn_flags_object = -1;
357 static int hf_dcerpc_drep = -1;
358 static int hf_dcerpc_drep_byteorder = -1;
359 static int hf_dcerpc_drep_character = -1;
360 static int hf_dcerpc_drep_fp = -1;
361 static int hf_dcerpc_cn_frag_len = -1;
362 static int hf_dcerpc_cn_auth_len = -1;
363 static int hf_dcerpc_cn_call_id = -1;
364 static int hf_dcerpc_cn_max_xmit = -1;
365 static int hf_dcerpc_cn_max_recv = -1;
366 static int hf_dcerpc_cn_assoc_group = -1;
367 static int hf_dcerpc_cn_num_ctx_items = -1;
368 static int hf_dcerpc_cn_ctx_item = -1;
369 static int hf_dcerpc_cn_ctx_id = -1;
370 static int hf_dcerpc_cn_num_trans_items = -1;
371 static int hf_dcerpc_cn_bind_abstract_syntax = -1;
372 static int hf_dcerpc_cn_bind_if_id = -1;
373 static int hf_dcerpc_cn_bind_if_ver = -1;
374 static int hf_dcerpc_cn_bind_if_ver_minor = -1;
375 static int hf_dcerpc_cn_bind_trans_syntax = -1;
376 static int hf_dcerpc_cn_bind_trans_id = -1;
377 static int hf_dcerpc_cn_bind_trans_ver = -1;
378 static int hf_dcerpc_cn_alloc_hint = -1;
379 static int hf_dcerpc_cn_sec_addr_len = -1;
380 static int hf_dcerpc_cn_sec_addr = -1;
381 static int hf_dcerpc_cn_num_results = -1;
382 static int hf_dcerpc_cn_ack_result = -1;
383 static int hf_dcerpc_cn_ack_reason = -1;
384 static int hf_dcerpc_cn_ack_trans_id = -1;
385 static int hf_dcerpc_cn_ack_trans_ver = -1;
386 static int hf_dcerpc_cn_reject_reason = -1;
387 static int hf_dcerpc_cn_num_protocols = -1;
388 static int hf_dcerpc_cn_protocol_ver_major = -1;
389 static int hf_dcerpc_cn_protocol_ver_minor = -1;
390 static int hf_dcerpc_cn_cancel_count = -1;
391 static int hf_dcerpc_cn_status = -1;
392 static int hf_dcerpc_cn_deseg_req = -1;
393 static int hf_dcerpc_auth_type = -1;
394 static int hf_dcerpc_auth_level = -1;
395 static int hf_dcerpc_auth_pad_len = -1;
396 static int hf_dcerpc_auth_rsrvd = -1;
397 static int hf_dcerpc_auth_ctx_id = -1;
398 static int hf_dcerpc_dg_flags1 = -1;
399 static int hf_dcerpc_dg_flags1_rsrvd_01 = -1;
400 static int hf_dcerpc_dg_flags1_last_frag = -1;
401 static int hf_dcerpc_dg_flags1_frag = -1;
402 static int hf_dcerpc_dg_flags1_nofack = -1;
403 static int hf_dcerpc_dg_flags1_maybe = -1;
404 static int hf_dcerpc_dg_flags1_idempotent = -1;
405 static int hf_dcerpc_dg_flags1_broadcast = -1;
406 static int hf_dcerpc_dg_flags1_rsrvd_80 = -1;
407 static int hf_dcerpc_dg_flags2 = -1;
408 static int hf_dcerpc_dg_flags2_rsrvd_01 = -1;
409 static int hf_dcerpc_dg_flags2_cancel_pending = -1;
410 static int hf_dcerpc_dg_flags2_rsrvd_04 = -1;
411 static int hf_dcerpc_dg_flags2_rsrvd_08 = -1;
412 static int hf_dcerpc_dg_flags2_rsrvd_10 = -1;
413 static int hf_dcerpc_dg_flags2_rsrvd_20 = -1;
414 static int hf_dcerpc_dg_flags2_rsrvd_40 = -1;
415 static int hf_dcerpc_dg_flags2_rsrvd_80 = -1;
416 static int hf_dcerpc_dg_serial_hi = -1;
417 static int hf_dcerpc_obj_id = -1;
418 static int hf_dcerpc_dg_if_id = -1;
419 static int hf_dcerpc_dg_act_id = -1;
420 static int hf_dcerpc_dg_serial_lo = -1;
421 static int hf_dcerpc_dg_ahint = -1;
422 static int hf_dcerpc_dg_ihint = -1;
423 static int hf_dcerpc_dg_frag_len = -1;
424 static int hf_dcerpc_dg_frag_num = -1;
425 static int hf_dcerpc_dg_auth_proto = -1;
426 static int hf_dcerpc_opnum = -1;
427 static int hf_dcerpc_dg_seqnum = -1;
428 static int hf_dcerpc_dg_server_boot = -1;
429 static int hf_dcerpc_dg_if_ver = -1;
430 static int hf_dcerpc_krb5_av_prot_level = -1;
431 static int hf_dcerpc_krb5_av_key_vers_num = -1;
432 static int hf_dcerpc_krb5_av_key_auth_verifier = -1;
433 static int hf_dcerpc_dg_cancel_vers = -1;
434 static int hf_dcerpc_dg_cancel_id = -1;
435 static int hf_dcerpc_dg_server_accepting_cancels = -1;
436 static int hf_dcerpc_dg_fack_vers = -1;
437 static int hf_dcerpc_dg_fack_window_size = -1;
438 static int hf_dcerpc_dg_fack_max_tsdu = -1;
439 static int hf_dcerpc_dg_fack_max_frag_size = -1;
440 static int hf_dcerpc_dg_fack_serial_num = -1;
441 static int hf_dcerpc_dg_fack_selack_len = -1;
442 static int hf_dcerpc_dg_fack_selack = -1;
443 static int hf_dcerpc_dg_status = -1;
444 static int hf_dcerpc_array_max_count = -1;
445 static int hf_dcerpc_array_offset = -1;
446 static int hf_dcerpc_array_actual_count = -1;
447 static int hf_dcerpc_array_buffer = -1;
448 static int hf_dcerpc_op = -1;
449 static int hf_dcerpc_referent_id = -1;
450 static int hf_dcerpc_fragments = -1;
451 static int hf_dcerpc_fragment = -1;
452 static int hf_dcerpc_fragment_overlap = -1;
453 static int hf_dcerpc_fragment_overlap_conflict = -1;
454 static int hf_dcerpc_fragment_multiple_tails = -1;
455 static int hf_dcerpc_fragment_too_long_fragment = -1;
456 static int hf_dcerpc_fragment_error = -1;
457 static int hf_dcerpc_reassembled_in = -1;
458 static int hf_dcerpc_unknown_if_id = -1;
459
460 static gint ett_dcerpc = -1;
461 static gint ett_dcerpc_cn_flags = -1;
462 static gint ett_dcerpc_cn_ctx = -1;
463 static gint ett_dcerpc_cn_iface = -1;
464 static gint ett_dcerpc_cn_trans_syntax = -1;
465 static gint ett_dcerpc_drep = -1;
466 static gint ett_dcerpc_dg_flags1 = -1;
467 static gint ett_dcerpc_dg_flags2 = -1;
468 static gint ett_dcerpc_pointer_data = -1;
469 static gint ett_dcerpc_string = -1;
470 static gint ett_dcerpc_fragments = -1;
471 static gint ett_dcerpc_fragment = -1;
472 static gint ett_dcerpc_krb5_auth_verf = -1;
473
474 static const fragment_items dcerpc_frag_items = {
475         &ett_dcerpc_fragments,
476         &ett_dcerpc_fragment,
477
478         &hf_dcerpc_fragments,
479         &hf_dcerpc_fragment,
480         &hf_dcerpc_fragment_overlap,
481         &hf_dcerpc_fragment_overlap_conflict,
482         &hf_dcerpc_fragment_multiple_tails,
483         &hf_dcerpc_fragment_too_long_fragment,
484         &hf_dcerpc_fragment_error,
485         NULL,
486
487         "fragments"
488 };
489
490 /* list of hooks to be called when init_protocols is done */
491 GHookList dcerpc_hooks_init_protos;
492
493 static dcerpc_info *
494 get_next_di(void)
495 {
496         static dcerpc_info di[20];
497         static int di_counter=0;
498
499         di_counter++;
500         if(di_counter>=20){
501                 di_counter=0;
502         }
503         return &di[di_counter];
504 }
505
506 /* try to desegment big DCE/RPC packets over TCP? */
507 static gboolean dcerpc_cn_desegment = TRUE;
508
509 /* reassemble DCE/RPC fragments */
510 /* reassembly of cl dcerpc fragments will not work for the case where ONE frame
511    might contain multiple dcerpc fragments for different PDUs.
512    this case would be so unusual/weird so if you got captures like that:
513         too bad
514
515    reassembly of co dcerpc fragments will not work for the case where TCP/SMB frames
516    are coming in out of sequence, but that will hurt in a lot of other places as well.
517 */
518 static gboolean dcerpc_reassemble = TRUE;
519 static GHashTable *dcerpc_co_fragment_table = NULL;
520 static GHashTable *dcerpc_co_reassemble_table = NULL;
521 static GHashTable *dcerpc_cl_reassemble_table = NULL;
522
523 static void
524 dcerpc_reassemble_init(void)
525 {
526   fragment_table_init(&dcerpc_co_fragment_table);
527   reassembled_table_init(&dcerpc_co_reassemble_table);
528   dcerpc_fragment_table_init(&dcerpc_cl_reassemble_table);
529 }
530
531 /*
532  * Authentication subdissectors.  Used to dissect authentication blobs in
533  * DCERPC binds, requests and responses.
534  */
535
536 typedef struct _dcerpc_auth_subdissector {
537         guint8 auth_level;
538         guint8 auth_type;
539         dcerpc_auth_subdissector_fns auth_fns;
540 } dcerpc_auth_subdissector;
541
542 static GSList *dcerpc_auth_subdissector_list;
543
544 static dcerpc_auth_subdissector_fns *get_auth_subdissector_fns(
545         guint8 auth_level, guint8 auth_type)
546 {
547         gpointer data;
548         int i;
549
550         for (i = 0; (data = g_slist_nth_data(dcerpc_auth_subdissector_list, i)); i++) {
551                 dcerpc_auth_subdissector *asd = (dcerpc_auth_subdissector *)data;
552
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
683     key->uuid = *uuid;
684     key->ver = ver;
685
686     value->proto = find_protocol_by_id(proto);
687     value->proto_id = proto;
688     value->ett = ett;
689     value->name = proto_get_protocol_short_name (value->proto);
690     value->procs = procs;
691     value->opnum_hf = opnum_hf;
692
693     g_hash_table_insert (dcerpc_uuids, key, value);
694
695     hf_info = proto_registrar_get_nth(opnum_hf);
696     hf_info->strings = value_string_from_subdissectors(procs);
697
698     /* add this GUID to the global name resolving */
699     guids_add_uuid(uuid, proto_get_protocol_short_name (value->proto));
700 }
701
702 /* Function to find the name of a registered protocol
703  * or NULL if the protocol/version is not known to wireshark.
704  */
705 const char *
706 dcerpc_get_proto_name(e_uuid_t *uuid, guint16 ver)
707 {
708     dcerpc_uuid_key key;
709     dcerpc_uuid_value *sub_proto;
710
711     key.uuid = *uuid;
712     key.ver = ver;
713     if(!(sub_proto = g_hash_table_lookup (dcerpc_uuids, &key))){
714         return NULL;
715     }
716     return sub_proto->name;
717 }
718
719 /* Function to find the opnum hf-field of a registered protocol
720  * or -1 if the protocol/version is not known to wireshark.
721  */
722 int
723 dcerpc_get_proto_hf_opnum(e_uuid_t *uuid, guint16 ver)
724 {
725     dcerpc_uuid_key key;
726     dcerpc_uuid_value *sub_proto;
727
728     key.uuid = *uuid;
729     key.ver = ver;
730     if(!(sub_proto = g_hash_table_lookup (dcerpc_uuids, &key))){
731         return -1;
732     }
733     return sub_proto->opnum_hf;
734 }
735
736 /* Create a value_string consisting of DCERPC opnum and name from a
737    subdissector array. */
738
739 value_string *value_string_from_subdissectors(dcerpc_sub_dissector *sd)
740 {
741         value_string *vs = NULL;
742         int i, num_sd = 0;
743
744  again:
745         for (i = 0; sd[i].name; i++) {
746                 if (vs) {
747                         vs[i].value = sd[i].num;
748                         vs[i].strptr = sd[i].name;
749                 } else
750                         num_sd++;
751         }
752
753         if (!vs) {
754                 vs = g_malloc((num_sd + 1) * sizeof(value_string));
755                 goto again;
756         }
757
758         vs[num_sd].value = 0;
759         vs[num_sd].strptr = NULL;
760
761         return vs;
762 }
763
764 /* Function to find the subdissector table of a registered protocol
765  * or NULL if the protocol/version is not known to wireshark.
766  */
767 dcerpc_sub_dissector *
768 dcerpc_get_proto_sub_dissector(e_uuid_t *uuid, guint16 ver)
769 {
770     dcerpc_uuid_key key;
771     dcerpc_uuid_value *sub_proto;
772
773     key.uuid = *uuid;
774     key.ver = ver;
775     if(!(sub_proto = g_hash_table_lookup (dcerpc_uuids, &key))){
776         return NULL;
777     }
778     return sub_proto->procs;
779 }
780
781
782 /*
783  * To keep track of ctx_id mappings.
784  *
785  * Everytime we see a bind call we update this table.
786  * Note that we always specify a SMB FID. For non-SMB transports this
787  * value is 0.
788  */
789 static GHashTable *dcerpc_binds=NULL;
790
791 typedef struct _dcerpc_bind_key {
792     conversation_t *conv;
793     guint16 ctx_id;
794     guint16 smb_fid;
795 } dcerpc_bind_key;
796
797 typedef struct _dcerpc_bind_value {
798         e_uuid_t uuid;
799         guint16 ver;
800 } dcerpc_bind_value;
801
802 static gint
803 dcerpc_bind_equal (gconstpointer k1, gconstpointer k2)
804 {
805     const dcerpc_bind_key *key1 = (const dcerpc_bind_key *)k1;
806     const dcerpc_bind_key *key2 = (const dcerpc_bind_key *)k2;
807     return (key1->conv == key2->conv
808             && key1->ctx_id == key2->ctx_id
809             && key1->smb_fid == key2->smb_fid);
810 }
811
812 static guint
813 dcerpc_bind_hash (gconstpointer k)
814 {
815     const dcerpc_bind_key *key = (const dcerpc_bind_key *)k;
816     guint hash;
817
818     hash=GPOINTER_TO_UINT(key->conv) + key->ctx_id + key->smb_fid;
819     return hash;
820
821 }
822
823 /*
824  * To keep track of callid mappings.  Should really use some generic
825  * conversation support instead.
826  */
827 static GHashTable *dcerpc_cn_calls=NULL;
828 static GHashTable *dcerpc_dg_calls=NULL;
829
830 typedef struct _dcerpc_cn_call_key {
831     conversation_t *conv;
832     guint32 call_id;
833     guint16 smb_fid;
834 } dcerpc_cn_call_key;
835
836 typedef struct _dcerpc_dg_call_key {
837     conversation_t *conv;
838     guint32 seqnum;
839     e_uuid_t act_id ;
840 } dcerpc_dg_call_key;
841
842
843 static gint
844 dcerpc_cn_call_equal (gconstpointer k1, gconstpointer k2)
845 {
846     const dcerpc_cn_call_key *key1 = (const dcerpc_cn_call_key *)k1;
847     const dcerpc_cn_call_key *key2 = (const dcerpc_cn_call_key *)k2;
848     return (key1->conv == key2->conv
849             && key1->call_id == key2->call_id
850             && key1->smb_fid == key2->smb_fid);
851 }
852
853 static gint
854 dcerpc_dg_call_equal (gconstpointer k1, gconstpointer k2)
855 {
856     const dcerpc_dg_call_key *key1 = (const dcerpc_dg_call_key *)k1;
857     const dcerpc_dg_call_key *key2 = (const dcerpc_dg_call_key *)k2;
858     return (key1->conv == key2->conv
859             && key1->seqnum == key2->seqnum
860             && (memcmp (&key1->act_id, &key2->act_id, sizeof (e_uuid_t)) == 0));
861 }
862
863 static guint
864 dcerpc_cn_call_hash (gconstpointer k)
865 {
866     const dcerpc_cn_call_key *key = (const dcerpc_cn_call_key *)k;
867     return GPOINTER_TO_UINT(key->conv) + key->call_id + key->smb_fid;
868 }
869
870 static guint
871 dcerpc_dg_call_hash (gconstpointer k)
872 {
873     const dcerpc_dg_call_key *key = (const dcerpc_dg_call_key *)k;
874     return (GPOINTER_TO_UINT(key->conv) + key->seqnum + key->act_id.Data1
875             + (key->act_id.Data2 << 16) + key->act_id.Data3
876             + (key->act_id.Data4[0] << 24) + (key->act_id.Data4[1] << 16)
877             + (key->act_id.Data4[2] << 8) + (key->act_id.Data4[3] << 0)
878             + (key->act_id.Data4[4] << 24) + (key->act_id.Data4[5] << 16)
879             + (key->act_id.Data4[6] << 8) + (key->act_id.Data4[7] << 0));
880 }
881
882 /* to keep track of matched calls/responses
883    this one uses the same value struct as calls, but the key is the frame id
884    and call id; there can be more than one call in a frame.
885
886    XXX - why not just use the same keys as are used for calls?
887 */
888
889 static GHashTable *dcerpc_matched=NULL;
890
891 typedef struct _dcerpc_matched_key {
892     guint32 frame;
893     guint32 call_id;
894 } dcerpc_matched_key;
895
896 static gint
897 dcerpc_matched_equal (gconstpointer k1, gconstpointer k2)
898 {
899     const dcerpc_matched_key *key1 = (const dcerpc_matched_key *)k1;
900     const dcerpc_matched_key *key2 = (const dcerpc_matched_key *)k2;
901     return (key1->frame == key2->frame
902             && key1->call_id == key2->call_id);
903 }
904
905 static guint
906 dcerpc_matched_hash (gconstpointer k)
907 {
908     const dcerpc_matched_key *key = (const dcerpc_matched_key *)k;
909     return key->frame;
910 }
911
912
913
914 /*
915  * Utility functions.  Modeled after packet-rpc.c
916  */
917
918 int
919 dissect_dcerpc_uint8 (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
920                       proto_tree *tree, guint8 *drep,
921                       int hfindex, guint8 *pdata)
922 {
923     guint8 data;
924
925     data = tvb_get_guint8 (tvb, offset);
926     if (tree) {
927         proto_tree_add_item (tree, hfindex, tvb, offset, 1, (drep[0] & 0x10));
928     }
929     if (pdata)
930         *pdata = data;
931     return offset + 1;
932 }
933
934 int
935 dissect_dcerpc_uint16 (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
936                        proto_tree *tree, guint8 *drep,
937                        int hfindex, guint16 *pdata)
938 {
939     guint16 data;
940
941     data = ((drep[0] & 0x10)
942             ? tvb_get_letohs (tvb, offset)
943             : tvb_get_ntohs (tvb, offset));
944
945     if (tree) {
946         proto_tree_add_item (tree, hfindex, tvb, offset, 2, (drep[0] & 0x10));
947     }
948     if (pdata)
949         *pdata = data;
950     return offset + 2;
951 }
952
953 int
954 dissect_dcerpc_uint32 (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
955                        proto_tree *tree, guint8 *drep,
956                        int hfindex, guint32 *pdata)
957 {
958     guint32 data;
959
960     data = ((drep[0] & 0x10)
961             ? tvb_get_letohl (tvb, offset)
962             : tvb_get_ntohl (tvb, offset));
963
964     if (tree) {
965         proto_tree_add_item (tree, hfindex, tvb, offset, 4, (drep[0] & 0x10));
966     }
967     if (pdata)
968         *pdata = data;
969     return offset+4;
970 }
971
972 /* handles 32 bit unix time_t */
973 int
974 dissect_dcerpc_time_t (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
975                        proto_tree *tree, guint8 *drep,
976                        int hfindex, guint32 *pdata)
977 {
978     guint32 data;
979     nstime_t tv;
980
981     data = ((drep[0] & 0x10)
982             ? tvb_get_letohl (tvb, offset)
983             : tvb_get_ntohl (tvb, offset));
984
985     tv.secs=data;
986     tv.nsecs=0;
987     if (tree) {
988         if(data==0xffffffff){
989             /* special case,   no time specified */
990             proto_tree_add_time_format_value(tree, hfindex, tvb, offset, 4, &tv, "No time specified");
991         } else {
992             proto_tree_add_time (tree, hfindex, tvb, offset, 4, &tv);
993         }
994     }
995     if (pdata)
996         *pdata = data;
997
998     return offset+4;
999 }
1000
1001 int
1002 dissect_dcerpc_uint64 (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
1003                        proto_tree *tree, guint8 *drep,
1004                        int hfindex, guint64 *pdata)
1005 {
1006     guint64 data;
1007
1008     data = ((drep[0] & 0x10)
1009             ? tvb_get_letoh64 (tvb, offset)
1010             : tvb_get_ntoh64 (tvb, offset));
1011
1012     if (tree) {
1013         proto_tree_add_item(tree, hfindex, tvb, offset, 8, (drep[0] & 0x10));
1014     }
1015     if (pdata)
1016         *pdata = data;
1017     return offset+8;
1018 }
1019
1020
1021 int
1022 dissect_dcerpc_float(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
1023                     proto_tree *tree, guint8 *drep,
1024                     int hfindex, gfloat *pdata)
1025 {
1026         gfloat data;
1027
1028
1029         switch(drep[1]) {
1030                 case(DCE_RPC_DREP_FP_IEEE):
1031                         data = ((drep[0] & 0x10)
1032                                         ? tvb_get_letohieee_float(tvb, offset)
1033                                         : tvb_get_ntohieee_float(tvb, offset));
1034                         if (tree) {
1035                                 proto_tree_add_float(tree, hfindex, tvb, offset, 4, data);
1036                         }
1037                         break;
1038                 case(DCE_RPC_DREP_FP_VAX):  /* (fall trough) */
1039                 case(DCE_RPC_DREP_FP_CRAY): /* (fall trough) */
1040                 case(DCE_RPC_DREP_FP_IBM):  /* (fall trough) */
1041                 default:
1042                         /* ToBeDone: non IEEE floating formats */
1043                         /* Set data to a negative infinity value */
1044                         data = -G_MAXFLOAT;
1045                         if (tree) {
1046                                 proto_tree_add_debug_text(tree, "DCE RPC: dissection of non IEEE floating formats currently not implemented (drep=%u)!", drep[1]);
1047                         }
1048         }
1049     if (pdata)
1050         *pdata = data;
1051     return offset + 4;
1052 }
1053
1054
1055 int
1056 dissect_dcerpc_double(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
1057                     proto_tree *tree, guint8 *drep,
1058                     int hfindex, gdouble *pdata)
1059 {
1060     gdouble data;
1061
1062
1063         switch(drep[1]) {
1064                 case(DCE_RPC_DREP_FP_IEEE):
1065                         data = ((drep[0] & 0x10)
1066                                         ? tvb_get_letohieee_double(tvb, offset)
1067                                         : tvb_get_ntohieee_double(tvb, offset));
1068                         if (tree) {
1069                                 proto_tree_add_double(tree, hfindex, tvb, offset, 8, data);
1070                         }
1071                         break;
1072                 case(DCE_RPC_DREP_FP_VAX):  /* (fall trough) */
1073                 case(DCE_RPC_DREP_FP_CRAY): /* (fall trough) */
1074                 case(DCE_RPC_DREP_FP_IBM):  /* (fall trough) */
1075                 default:
1076                         /* ToBeDone: non IEEE double formats */
1077                         /* Set data to a negative infinity value */
1078                         data = -G_MAXDOUBLE;
1079                         if (tree) {
1080                                 proto_tree_add_debug_text(tree, "DCE RPC: dissection of non IEEE double formats currently not implemented (drep=%u)!", drep[1]);
1081                         }
1082         }
1083     if (pdata)
1084         *pdata = data;
1085     return offset + 8;
1086 }
1087
1088
1089 int
1090 dissect_dcerpc_uuid_t (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
1091                     proto_tree *tree, guint8 *drep,
1092                     int hfindex, e_uuid_t *pdata)
1093 {
1094     e_uuid_t uuid;
1095
1096
1097     if (drep[0] & 0x10) {
1098         tvb_get_letohguid (tvb, offset, (e_guid_t *) &uuid);
1099     } else {
1100         tvb_get_ntohguid (tvb, offset, (e_guid_t *) &uuid);
1101     }
1102     if (tree) {
1103                 proto_tree_add_guid(tree, hfindex, tvb, offset, 16, (e_guid_t *) &uuid);
1104     }
1105     if (pdata) {
1106         *pdata = uuid;
1107     }
1108     return offset + 16;
1109 }
1110
1111
1112 /*
1113  * a couple simpler things
1114  */
1115 guint16
1116 dcerpc_tvb_get_ntohs (tvbuff_t *tvb, gint offset, guint8 *drep)
1117 {
1118     if (drep[0] & 0x10) {
1119         return tvb_get_letohs (tvb, offset);
1120     } else {
1121         return tvb_get_ntohs (tvb, offset);
1122     }
1123 }
1124
1125 guint32
1126 dcerpc_tvb_get_ntohl (tvbuff_t *tvb, gint offset, guint8 *drep)
1127 {
1128     if (drep[0] & 0x10) {
1129         return tvb_get_letohl (tvb, offset);
1130     } else {
1131         return tvb_get_ntohl (tvb, offset);
1132     }
1133 }
1134
1135 void
1136 dcerpc_tvb_get_uuid (tvbuff_t *tvb, gint offset, guint8 *drep, e_uuid_t *uuid)
1137 {
1138     if (drep[0] & 0x10) {
1139         tvb_get_letohguid (tvb, offset, (e_guid_t *) uuid);
1140     } else {
1141         tvb_get_ntohguid (tvb, offset, (e_guid_t *) uuid);
1142     }
1143 }
1144
1145
1146 /* NDR arrays */
1147 /* function to dissect a unidimensional conformant array */
1148 int
1149 dissect_ndr_ucarray(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1150                 proto_tree *tree, guint8 *drep,
1151                 dcerpc_dissect_fnct_t *fnct)
1152 {
1153         guint32 i;
1154         dcerpc_info *di;
1155         int old_offset;
1156
1157         di=pinfo->private_data;
1158         if(di->conformant_run){
1159                 /* conformant run, just dissect the max_count header */
1160                 old_offset=offset;
1161                 di->conformant_run=0;
1162                 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1163                                 hf_dcerpc_array_max_count, &di->array_max_count);
1164                 di->array_max_count_offset=offset-4;
1165                 di->conformant_run=1;
1166                 di->conformant_eaten=offset-old_offset;
1167         } else {
1168                 /* we don't remember where in the bytestream this field was */
1169                 proto_tree_add_uint(tree, hf_dcerpc_array_max_count, tvb, di->array_max_count_offset, 4, di->array_max_count);
1170
1171                 /* real run, dissect the elements */
1172                 for(i=0;i<di->array_max_count;i++){
1173                         offset = (*fnct)(tvb, offset, pinfo, tree, drep);
1174                 }
1175         }
1176
1177         return offset;
1178 }
1179 /* function to dissect a unidimensional conformant and varying array */
1180 int
1181 dissect_ndr_ucvarray(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1182                 proto_tree *tree, guint8 *drep,
1183                 dcerpc_dissect_fnct_t *fnct)
1184 {
1185         guint32 i;
1186         dcerpc_info *di;
1187         int old_offset;
1188
1189         di=pinfo->private_data;
1190         if(di->conformant_run){
1191                 /* conformant run, just dissect the max_count header */
1192                 old_offset=offset;
1193                 di->conformant_run=0;
1194                 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1195                                 hf_dcerpc_array_max_count, &di->array_max_count);
1196                 di->array_max_count_offset=offset-4;
1197                 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1198                                 hf_dcerpc_array_offset, &di->array_offset);
1199                 di->array_offset_offset=offset-4;
1200                 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1201                                 hf_dcerpc_array_actual_count, &di->array_actual_count);
1202                 di->array_actual_count_offset=offset-4;
1203                 di->conformant_run=1;
1204                 di->conformant_eaten=offset-old_offset;
1205         } else {
1206                 /* we dont dont remember where  in the bytestream these fields were */
1207                 proto_tree_add_uint(tree, hf_dcerpc_array_max_count, tvb, di->array_max_count_offset, 4, di->array_max_count);
1208                 proto_tree_add_uint(tree, hf_dcerpc_array_offset, tvb, di->array_offset_offset, 4, di->array_offset);
1209                 proto_tree_add_uint(tree, hf_dcerpc_array_actual_count, tvb, di->array_actual_count_offset, 4, di->array_actual_count);
1210
1211                 /* real run, dissect the elements */
1212                 for(i=0;i<di->array_actual_count;i++){
1213                         old_offset = offset;
1214                         offset = (*fnct)(tvb, offset, pinfo, tree, drep);
1215                         if (offset <= old_offset)
1216                                 THROW(ReportedBoundsError);
1217                 }
1218         }
1219
1220         return offset;
1221 }
1222 /* function to dissect a unidimensional varying array */
1223 int
1224 dissect_ndr_uvarray(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1225                 proto_tree *tree, guint8 *drep,
1226                 dcerpc_dissect_fnct_t *fnct)
1227 {
1228         guint32 i;
1229         dcerpc_info *di;
1230         int old_offset;
1231
1232         di=pinfo->private_data;
1233         if(di->conformant_run){
1234                 /* conformant run, just dissect the max_count header */
1235                 old_offset=offset;
1236                 di->conformant_run=0;
1237                 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1238                                 hf_dcerpc_array_offset, &di->array_offset);
1239                 di->array_offset_offset=offset-4;
1240                 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1241                                 hf_dcerpc_array_actual_count, &di->array_actual_count);
1242                 di->array_actual_count_offset=offset-4;
1243                 di->conformant_run=1;
1244                 di->conformant_eaten=offset-old_offset;
1245         } else {
1246                 /* we dont dont remember where  in the bytestream these fields were */
1247                 proto_tree_add_uint(tree, hf_dcerpc_array_offset, tvb, di->array_offset_offset, 4, di->array_offset);
1248                 proto_tree_add_uint(tree, hf_dcerpc_array_actual_count, tvb, di->array_actual_count_offset, 4, di->array_actual_count);
1249
1250                 /* real run, dissect the elements */
1251                 for(i=0;i<di->array_actual_count;i++){
1252                         offset = (*fnct)(tvb, offset, pinfo, tree, drep);
1253                 }
1254         }
1255
1256         return offset;
1257 }
1258
1259 /* Dissect an string of bytes.  This corresponds to
1260    IDL of the form '[string] byte *foo'.
1261
1262    It can also be used for a conformant varying array of bytes if
1263    the contents of the array should be shown as a big blob, rather
1264    than showing each byte as an individual element.
1265
1266    XXX - which of those is really the IDL type for, for example,
1267    the encrypted data in some MAPI packets?  (Microsoft haven't
1268    released that IDL.)
1269
1270    XXX - does this need to do all the conformant array stuff that
1271    "dissect_ndr_ucvarray()" does?  These are presumably for strings
1272    that are conformant and varying - they're stored like conformant
1273    varying arrays of bytes.  */
1274 int
1275 dissect_ndr_byte_array(tvbuff_t *tvb, int offset, packet_info *pinfo,
1276                             proto_tree *tree, guint8 *drep)
1277 {
1278     dcerpc_info *di;
1279     guint32 len;
1280
1281     di=pinfo->private_data;
1282     if(di->conformant_run){
1283       /* just a run to handle conformant arrays, no scalars to dissect */
1284       return offset;
1285     }
1286
1287     /* NDR array header */
1288
1289     offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
1290                                 hf_dcerpc_array_max_count, NULL);
1291
1292     offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
1293                                 hf_dcerpc_array_offset, NULL);
1294
1295     offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
1296                                 hf_dcerpc_array_actual_count, &len);
1297
1298     if (tree && len) {
1299         tvb_ensure_bytes_exist(tvb, offset, len);
1300         proto_tree_add_item(tree, hf_dcerpc_array_buffer,
1301                             tvb, offset, len, drep[0] & 0x10);
1302     }
1303
1304     offset += len;
1305
1306     return offset;
1307 }
1308
1309 /* For dissecting arrays that are to be interpreted as strings.  */
1310
1311 /* Dissect an NDR conformant varying string of elements.
1312    The length of each element is given by the 'size_is' parameter;
1313    the elements are assumed to be characters or wide characters.
1314
1315    XXX - does this need to do all the conformant array stuff that
1316    "dissect_ndr_ucvarray()" does?  */
1317 int
1318 dissect_ndr_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
1319                      proto_tree *tree, guint8 *drep, int size_is,
1320                      int hfindex, gboolean add_subtree, char **data)
1321 {
1322     dcerpc_info *di;
1323     proto_item *string_item;
1324     proto_tree *string_tree;
1325     guint32 len, buffer_len;
1326     char *s;
1327     header_field_info *hfinfo;
1328
1329     di=pinfo->private_data;
1330     if(di->conformant_run){
1331       /* just a run to handle conformant arrays, no scalars to dissect */
1332       return offset;
1333     }
1334
1335     if (add_subtree) {
1336         string_item = proto_tree_add_text(tree, tvb, offset, -1, "%s",
1337                                           proto_registrar_get_name(hfindex));
1338         string_tree = proto_item_add_subtree(string_item, ett_dcerpc_string);
1339     } else {
1340         string_item = NULL;
1341         string_tree = tree;
1342     }
1343
1344     /* NDR array header */
1345
1346     offset = dissect_ndr_uint32(tvb, offset, pinfo, string_tree, drep,
1347                                 hf_dcerpc_array_max_count, NULL);
1348
1349     offset = dissect_ndr_uint32(tvb, offset, pinfo, string_tree, drep,
1350                                 hf_dcerpc_array_offset, NULL);
1351
1352     offset = dissect_ndr_uint32(tvb, offset, pinfo, string_tree, drep,
1353                                 hf_dcerpc_array_actual_count, &len);
1354
1355     buffer_len = size_is * len;
1356
1357     /* Adjust offset */
1358     if (offset % size_is)
1359         offset += size_is - (offset % size_is);
1360
1361     if (size_is == sizeof(guint16)) {
1362         /* XXX - use drep to determine the byte order? */
1363         s = tvb_fake_unicode(tvb, offset, buffer_len / 2, TRUE);
1364         /*
1365          * XXX - we don't support a string type with Unicode
1366          * characters, so if this is a string item, we make
1367          * its value be the "fake Unicode" string.
1368          */
1369         if (tree && buffer_len) {
1370             hfinfo = proto_registrar_get_nth(hfindex);
1371             tvb_ensure_bytes_exist(tvb, offset, buffer_len);
1372             if (hfinfo->type == FT_STRING) {
1373                 proto_tree_add_string(string_tree, hfindex, tvb, offset,
1374                                       buffer_len, s);
1375             } else {
1376                 proto_tree_add_item(string_tree, hfindex, tvb, offset,
1377                                     buffer_len, drep[0] & 0x10);
1378             }
1379         }
1380     } else {
1381         /*
1382          * "tvb_get_string()" throws an exception if the entire string
1383          * isn't in the tvbuff.  If the length is bogus, this should
1384          * keep us from trying to allocate an immensely large buffer.
1385          * (It won't help if the length is *valid* but immensely large,
1386          * but that's another matter; in any case, that would happen only
1387          * if we had an immensely large tvbuff....)
1388          */
1389         tvb_ensure_bytes_exist(tvb, offset, buffer_len);
1390         s = tvb_get_string(tvb, offset, buffer_len);
1391         if (tree && buffer_len)
1392             proto_tree_add_item(string_tree, hfindex, tvb, offset,
1393                                 buffer_len, drep[0] & 0x10);
1394     }
1395
1396     if (string_item != NULL)
1397         proto_item_append_text(string_item, ": %s", s);
1398
1399     if (data)
1400             *data = s;
1401     else
1402             g_free(s);
1403
1404     offset += buffer_len;
1405
1406     proto_item_set_end(string_item, tvb, offset);
1407
1408     return offset;
1409 }
1410
1411 /* Dissect an conformant varying string of chars.
1412    This corresponds to IDL of the form '[string] char *foo'.
1413
1414    XXX - at least according to the DCE RPC 1.1 spec, a string has
1415    a null terminator, which isn't necessary as a terminator for
1416    the transfer language (as there's a length), but is presumably
1417    there for the benefit of null-terminated-string languages
1418    such as C.  Is this ever used for purely counted strings?
1419    (Not that it matters if it is.) */
1420 int
1421 dissect_ndr_char_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
1422                         proto_tree *tree, guint8 *drep)
1423 {
1424     dcerpc_info *di;
1425     di=pinfo->private_data;
1426
1427     return dissect_ndr_cvstring(tvb, offset, pinfo, tree, drep,
1428                                 sizeof(guint8), di->hf_index,
1429                                 FALSE, NULL);
1430 }
1431
1432 /* Dissect a conformant varying string of wchars (wide characters).
1433    This corresponds to IDL of the form '[string] wchar *foo'
1434
1435    XXX - at least according to the DCE RPC 1.1 spec, a string has
1436    a null terminator, which isn't necessary as a terminator for
1437    the transfer language (as there's a length), but is presumably
1438    there for the benefit of null-terminated-string languages
1439    such as C.  Is this ever used for purely counted strings?
1440    (Not that it matters if it is.) */
1441 int
1442 dissect_ndr_wchar_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
1443                         proto_tree *tree, guint8 *drep)
1444 {
1445     dcerpc_info *di;
1446     di=pinfo->private_data;
1447
1448     return dissect_ndr_cvstring(tvb, offset, pinfo, tree, drep,
1449                                 sizeof(guint16), di->hf_index,
1450                                 FALSE, NULL);
1451 }
1452
1453 /* Dissect an NDR varying string of elements.
1454    The length of each element is given by the 'size_is' parameter;
1455    the elements are assumed to be characters or wide characters.
1456 */
1457 int
1458 dissect_ndr_vstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
1459                      proto_tree *tree, guint8 *drep, int size_is,
1460                      int hfindex, gboolean add_subtree, char **data)
1461 {
1462     dcerpc_info *di;
1463     proto_item *string_item;
1464     proto_tree *string_tree;
1465     guint32 len, buffer_len;
1466     char *s;
1467     header_field_info *hfinfo;
1468
1469     di=pinfo->private_data;
1470     if(di->conformant_run){
1471       /* just a run to handle conformant arrays, no scalars to dissect */
1472       return offset;
1473     }
1474
1475     if (add_subtree) {
1476         string_item = proto_tree_add_text(tree, tvb, offset, -1, "%s",
1477                                           proto_registrar_get_name(hfindex));
1478         string_tree = proto_item_add_subtree(string_item, ett_dcerpc_string);
1479     } else {
1480         string_item = NULL;
1481         string_tree = tree;
1482     }
1483
1484     /* NDR array header */
1485     offset = dissect_ndr_uint32(tvb, offset, pinfo, string_tree, drep,
1486                                 hf_dcerpc_array_offset, NULL);
1487
1488     offset = dissect_ndr_uint32(tvb, offset, pinfo, string_tree, drep,
1489                                 hf_dcerpc_array_actual_count, &len);
1490
1491     buffer_len = size_is * len;
1492
1493     /* Adjust offset */
1494     if (offset % size_is)
1495         offset += size_is - (offset % size_is);
1496
1497     if (size_is == sizeof(guint16)) {
1498         /* XXX - use drep to determine the byte order? */
1499         s = tvb_fake_unicode(tvb, offset, buffer_len / 2, TRUE);
1500         /*
1501          * XXX - we don't support a string type with Unicode
1502          * characters, so if this is a string item, we make
1503          * its value be the "fake Unicode" string.
1504          */
1505         if (tree && buffer_len) {
1506             hfinfo = proto_registrar_get_nth(hfindex);
1507             tvb_ensure_bytes_exist(tvb, offset, buffer_len);
1508             if (hfinfo->type == FT_STRING) {
1509                 proto_tree_add_string(string_tree, hfindex, tvb, offset,
1510                                       buffer_len, s);
1511             } else {
1512                 proto_tree_add_item(string_tree, hfindex, tvb, offset,
1513                                     buffer_len, drep[0] & 0x10);
1514             }
1515         }
1516     } else {
1517         /*
1518          * "tvb_get_string()" throws an exception if the entire string
1519          * isn't in the tvbuff.  If the length is bogus, this should
1520          * keep us from trying to allocate an immensely large buffer.
1521          * (It won't help if the length is *valid* but immensely large,
1522          * but that's another matter; in any case, that would happen only
1523          * if we had an immensely large tvbuff....)
1524          */
1525         tvb_ensure_bytes_exist(tvb, offset, buffer_len);
1526         s = tvb_get_string(tvb, offset, buffer_len);
1527         if (tree && buffer_len)
1528             proto_tree_add_item(string_tree, hfindex, tvb, offset,
1529                                 buffer_len, drep[0] & 0x10);
1530     }
1531
1532     if (string_item != NULL)
1533         proto_item_append_text(string_item, ": %s", s);
1534
1535     if (data)
1536             *data = s;
1537     else
1538             g_free(s);
1539
1540     offset += buffer_len;
1541
1542     proto_item_set_end(string_item, tvb, offset);
1543
1544     return offset;
1545 }
1546 /* Dissect an varying string of chars.
1547    This corresponds to IDL of the form '[string] char *foo'.
1548
1549    XXX - at least according to the DCE RPC 1.1 spec, a string has
1550    a null terminator, which isn't necessary as a terminator for
1551    the transfer language (as there's a length), but is presumably
1552    there for the benefit of null-terminated-string languages
1553    such as C.  Is this ever used for purely counted strings?
1554    (Not that it matters if it is.) */
1555 int
1556 dissect_ndr_char_vstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
1557                         proto_tree *tree, guint8 *drep)
1558 {
1559     dcerpc_info *di;
1560     di=pinfo->private_data;
1561
1562     return dissect_ndr_vstring(tvb, offset, pinfo, tree, drep,
1563                                 sizeof(guint8), di->hf_index,
1564                                 FALSE, NULL);
1565 }
1566
1567 /* Dissect a varying string of wchars (wide characters).
1568    This corresponds to IDL of the form '[string] wchar *foo'
1569
1570    XXX - at least according to the DCE RPC 1.1 spec, a string has
1571    a null terminator, which isn't necessary as a terminator for
1572    the transfer language (as there's a length), but is presumably
1573    there for the benefit of null-terminated-string languages
1574    such as C.  Is this ever used for purely counted strings?
1575    (Not that it matters if it is.) */
1576 int
1577 dissect_ndr_wchar_vstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
1578                         proto_tree *tree, guint8 *drep)
1579 {
1580     dcerpc_info *di;
1581     di=pinfo->private_data;
1582
1583     return dissect_ndr_vstring(tvb, offset, pinfo, tree, drep,
1584                                 sizeof(guint16), di->hf_index,
1585                                 FALSE, NULL);
1586 }
1587
1588
1589 /* ndr pointer handling */
1590 /* list of pointers encountered so far */
1591 static GSList *ndr_pointer_list = NULL;
1592
1593 /* position where in the list to insert newly encountered pointers */
1594 static int ndr_pointer_list_pos=0;
1595
1596 /* boolean controlling whether pointers are top-level or embedded */
1597 static gboolean pointers_are_top_level = TRUE;
1598
1599 /* as a kludge, we represent all embedded reference pointers as id==-1
1600    hoping that his will not collide with any non-ref pointers */
1601 typedef struct ndr_pointer_data {
1602         guint32 id;
1603         proto_item *item;       /* proto_item for pointer */
1604         proto_tree *tree;       /* subtree of above item */
1605         dcerpc_dissect_fnct_t *fnct; /*if non-NULL, we have not called it yet*/
1606         int hf_index;
1607         dcerpc_callback_fnct_t *callback;
1608         void *callback_args;
1609 } ndr_pointer_data_t;
1610
1611 void
1612 init_ndr_pointer_list(packet_info *pinfo)
1613 {
1614         dcerpc_info *di;
1615
1616         di=pinfo->private_data;
1617         di->conformant_run=0;
1618
1619         while(ndr_pointer_list){
1620                 ndr_pointer_data_t *npd;
1621
1622                 npd=g_slist_nth_data(ndr_pointer_list, 0);
1623                 ndr_pointer_list=g_slist_remove(ndr_pointer_list, npd);
1624                 if(npd){
1625                         g_free(npd);
1626                 }
1627         }
1628
1629         ndr_pointer_list=NULL;
1630         ndr_pointer_list_pos=0;
1631         pointers_are_top_level=TRUE;
1632 }
1633
1634 int
1635 dissect_deferred_pointers(packet_info *pinfo, tvbuff_t *tvb, int offset, guint8 *drep)
1636 {
1637         int found_new_pointer;
1638         dcerpc_info *di;
1639         int old_offset;
1640         int next_pointer;
1641
1642         next_pointer=0;
1643         di=pinfo->private_data;
1644         do{
1645                 int i, len;
1646
1647                 found_new_pointer=0;
1648                 len=g_slist_length(ndr_pointer_list);
1649                 for(i=next_pointer;i<len;i++){
1650                         ndr_pointer_data_t *tnpd;
1651                         tnpd=g_slist_nth_data(ndr_pointer_list, i);
1652                         if(tnpd->fnct){
1653                                 dcerpc_dissect_fnct_t *fnct;
1654
1655                                 next_pointer=i+1;
1656                                 found_new_pointer=1;
1657                                 fnct=tnpd->fnct;
1658                                 tnpd->fnct=NULL;
1659                                 ndr_pointer_list_pos=i+1;
1660                                 di->hf_index=tnpd->hf_index;
1661                                 /* first a run to handle any conformant
1662                                    array headers */
1663                                 di->conformant_run=1;
1664                                 di->conformant_eaten=0;
1665                                 old_offset = offset;
1666                                 offset = (*(fnct))(tvb, offset, pinfo, NULL, drep);
1667
1668                                 DISSECTOR_ASSERT((offset-old_offset)==di->conformant_eaten);
1669                                 /* This is to check for any bugs in the dissectors.
1670                                  *
1671                                  * Basically, the NDR representation will store all
1672                                  * arrays in two blocks, one block with the dimension
1673                                  * discreption, like size, number of elements and such,
1674                                  * and another block that contains the actual data stored
1675                                  * in the array.
1676                                  * If the array is embedded directly inside another,
1677                                  * encapsulating aggregate type, like a union or struct,
1678                                  * then these two blocks will be stored at different places
1679                                  * in the bytestream, with other data between the blocks.
1680                                  *
1681                                  * For this reason, all pointers to types (both aggregate
1682                                  * and scalar, for simplicity no distinction is made)
1683                                  * will have its dissector called twice.
1684                                  * The dissector will first be called with conformant_run==1
1685                                  * in which mode the dissector MUST NOT consume any data from
1686                                  * the tvbuff (i.e. may not dissect anything) except the
1687                                  * initial control block for arrays.
1688                                  * The second time the dissector is called, with
1689                                  * conformant_run==0, all other data for the type will be
1690                                  * dissected.
1691                                  *
1692                                  * All dissect_ndr_<type> dissectors are already prepared
1693                                  * for this and knows when it should eat data from the tvb
1694                                  * and when not to, so implementors of dissectors will
1695                                  * normally not need to worry about this or even know about
1696                                  * it. However, if a dissector for an aggregate type calls
1697                                  * a subdissector from outside packet-dcerpc.c, such as
1698                                  * the dissector in packet-smb.c for NT Security Descriptors
1699                                  * as an example, then it is VERY important to encapsulate
1700                                  * this call to an external subdissector with the appropriate
1701                                  * test for conformant_run, i.e. it will need something like
1702                                  *
1703                                  *      dcerpc_info *di;
1704                                  *
1705                                  *      di=pinfo->private_data;
1706                                  *      if(di->conformant_run){
1707                                  *              return offset;
1708                                  *      }
1709                                  *
1710                                  * to make sure it makes the right thing.
1711                                  * This assert will signal when someone has forgotten to
1712                                  * make the dissector aware of this requirement.
1713                                  */
1714
1715                                 /* now we dissect the actual pointer */
1716                                 di->conformant_run=0;
1717                                 old_offset = offset;
1718                                 offset = (*(fnct))(tvb, offset, pinfo, tnpd->tree, drep);
1719                                 if (tnpd->callback)
1720                                         tnpd->callback(pinfo, tnpd->tree, tnpd->item, tvb, old_offset, offset, tnpd->callback_args);
1721                                 break;
1722                         }
1723                 }
1724         } while(found_new_pointer);
1725
1726         return offset;
1727 }
1728
1729
1730 static void
1731 add_pointer_to_list(packet_info *pinfo, proto_tree *tree, proto_item *item,
1732                     dcerpc_dissect_fnct_t *fnct, guint32 id, int hf_index,
1733                     dcerpc_callback_fnct_t *callback, void *callback_args)
1734 {
1735         ndr_pointer_data_t *npd;
1736
1737         /* check if this pointer is valid */
1738         if(id!=0xffffffff){
1739                 dcerpc_info *di;
1740                 dcerpc_call_value *value;
1741
1742                 di=pinfo->private_data;
1743                 value=di->call_data;
1744
1745                 if(di->ptype == PDU_REQ){
1746                         if(!(pinfo->fd->flags.visited)){
1747                                 if(id>value->max_ptr){
1748                                         value->max_ptr=id;
1749                                 }
1750                         }
1751                 } else {
1752                         /* if we havent seen the request bail out since we cant
1753                            know whether this is the first non-NULL instance
1754                            or not */
1755                         if(value->req_frame==0){
1756                                 /* XXX THROW EXCEPTION */
1757                         }
1758
1759                         /* We saw this one in the request frame, nothing to
1760                            dissect later */
1761                         if(id<=value->max_ptr){
1762                                 return;
1763                         }
1764                 }
1765         }
1766
1767         npd=g_malloc(sizeof(ndr_pointer_data_t));
1768         npd->id=id;
1769         npd->tree=tree;
1770         npd->item=item;
1771         npd->fnct=fnct;
1772         npd->hf_index=hf_index;
1773         npd->callback=callback;
1774         npd->callback_args=callback_args;
1775         ndr_pointer_list = g_slist_insert(ndr_pointer_list, npd,
1776                                         ndr_pointer_list_pos);
1777         ndr_pointer_list_pos++;
1778 }
1779
1780
1781 static int
1782 find_pointer_index(guint32 id)
1783 {
1784         ndr_pointer_data_t *npd;
1785         int i,len;
1786
1787         len=g_slist_length(ndr_pointer_list);
1788         for(i=0;i<len;i++){
1789                 npd=g_slist_nth_data(ndr_pointer_list, i);
1790                 if(npd){
1791                         if(npd->id==id){
1792                                 return i;
1793                         }
1794                 }
1795         }
1796
1797         return -1;
1798 }
1799
1800 /* This function dissects an NDR pointer and stores the callback for later
1801  * deferred dissection.
1802  *
1803  *   fnct is the callback function for when we have reached this object in
1804  *   the bytestream.
1805  *
1806  *   type is what type of pointer.
1807  *
1808  *   this is text is what text we should put in any created tree node.
1809  *
1810  *   hf_index is what hf value we want to pass to the callback function when
1811  *   it is called, the callback can later pich this one up from di->hf_index.
1812  *
1813  *   callback is executed after the pointer has been dereferenced.
1814  *
1815  *   callback_args is passed as an argument to the callback function
1816  *
1817  * See packet-dcerpc-samr.c for examples
1818  */
1819 int
1820 dissect_ndr_pointer_cb(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1821                     proto_tree *tree, guint8 *drep, dcerpc_dissect_fnct_t *fnct,
1822                     int type, const char *text, int hf_index,
1823                     dcerpc_callback_fnct_t *callback, void *callback_args)
1824 {
1825         dcerpc_info *di;
1826         proto_tree *tr = NULL;
1827         gint start_offset = offset;
1828
1829         di=pinfo->private_data;
1830         if(di->conformant_run){
1831                 /* this call was only for dissecting the header for any
1832                    embedded conformant array. we will not parse any
1833                    pointers in this mode.
1834                 */
1835                 return offset;
1836         }
1837
1838         /*TOP LEVEL REFERENCE POINTER*/
1839         if( pointers_are_top_level
1840         &&(type==NDR_POINTER_REF) ){
1841                 proto_item *item;
1842
1843                 /* we must find out a nice way to do the length here */
1844                 item=proto_tree_add_text(tree, tvb, offset, 0,
1845                         "%s", text);
1846                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1847
1848                 add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff,
1849                                     hf_index, callback, callback_args);
1850                 goto after_ref_id;
1851         }
1852
1853         /*TOP LEVEL FULL POINTER*/
1854         if( pointers_are_top_level
1855         && (type==NDR_POINTER_PTR) ){
1856                 int idx;
1857                 guint32 id;
1858                 proto_item *item;
1859
1860                 /* get the referent id */
1861                 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
1862
1863                 tvb_ensure_bytes_exist(tvb, offset-4, 4);
1864                 /* we got a NULL pointer */
1865                 if(id==0){
1866                         proto_tree_add_text(tree, tvb, offset-4, 4,
1867                                 "(NULL pointer) %s",text);
1868                         goto after_ref_id;
1869                 }
1870
1871                 /* see if we have seen this pointer before */
1872                 idx=find_pointer_index(id);
1873
1874                 /* we have seen this pointer before */
1875                 if(idx>=0){
1876                         proto_tree_add_text(tree, tvb, offset-4, 4,
1877                                 "(duplicate PTR) %s",text);
1878                         goto after_ref_id;
1879                 }
1880
1881                 /* new pointer */
1882                 item=proto_tree_add_text(tree, tvb, offset-4, 4,
1883                         "%s", text);
1884                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1885                 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
1886                 add_pointer_to_list(pinfo, tr, item, fnct, id, hf_index,
1887                                     callback, callback_args);
1888                 goto after_ref_id;
1889         }
1890         /*TOP LEVEL UNIQUE POINTER*/
1891         if( pointers_are_top_level
1892         && (type==NDR_POINTER_UNIQUE) ){
1893                 guint32 id;
1894                 proto_item *item;
1895
1896                 /* get the referent id */
1897                 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
1898
1899                 tvb_ensure_bytes_exist(tvb, offset-4, 4);
1900                 /* we got a NULL pointer */
1901                 if(id==0){
1902                         proto_tree_add_text(tree, tvb, offset-4, 4,
1903                                 "(NULL pointer) %s",text);
1904                         goto after_ref_id;
1905                 }
1906
1907                 /* new pointer */
1908                 item=proto_tree_add_text(tree, tvb, offset-4, 4,
1909                         "%s", text);
1910                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1911                 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
1912                 add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff,
1913                                     hf_index, callback, callback_args);
1914                 goto after_ref_id;
1915         }
1916
1917         /*EMBEDDED REFERENCE POINTER*/
1918         if( (!pointers_are_top_level)
1919         && (type==NDR_POINTER_REF) ){
1920                 guint32 id;
1921                 proto_item *item;
1922
1923                 /* get the referent id */
1924                 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
1925
1926                 tvb_ensure_bytes_exist(tvb, offset-4, 4);
1927                 /* new pointer */
1928                 item=proto_tree_add_text(tree, tvb, offset-4, 4,
1929                         "%s",text);
1930                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1931                 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
1932                 add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff,
1933                                     hf_index, callback, callback_args);
1934                 goto after_ref_id;
1935         }
1936
1937         /*EMBEDDED UNIQUE POINTER*/
1938         if( (!pointers_are_top_level)
1939         && (type==NDR_POINTER_UNIQUE) ){
1940                 guint32 id;
1941                 proto_item *item;
1942
1943                 /* get the referent id */
1944                 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
1945
1946                 tvb_ensure_bytes_exist(tvb, offset-4, 4);
1947                 /* we got a NULL pointer */
1948                 if(id==0){
1949                         proto_tree_add_text(tree, tvb, offset-4, 4,
1950                                 "(NULL pointer) %s", text);
1951                         goto after_ref_id;
1952                 }
1953
1954                 /* new pointer */
1955                 item=proto_tree_add_text(tree, tvb, offset-4, 4,
1956                         "%s",text);
1957                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1958                 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
1959                 add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff,
1960                                     hf_index, callback, callback_args);
1961                 goto after_ref_id;
1962         }
1963
1964         /*EMBEDDED FULL POINTER*/
1965         if( (!pointers_are_top_level)
1966         && (type==NDR_POINTER_PTR) ){
1967                 int idx;
1968                 guint32 id;
1969                 proto_item *item;
1970
1971                 /* get the referent id */
1972                 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
1973
1974                 tvb_ensure_bytes_exist(tvb, offset-4, 4);
1975                 /* we got a NULL pointer */
1976                 if(id==0){
1977                         proto_tree_add_text(tree, tvb, offset-4, 4,
1978                                 "(NULL pointer) %s",text);
1979                         goto after_ref_id;
1980                 }
1981
1982                 /* see if we have seen this pointer before */
1983                 idx=find_pointer_index(id);
1984
1985                 /* we have seen this pointer before */
1986                 if(idx>=0){
1987                         proto_tree_add_text(tree, tvb, offset-4, 4,
1988                                 "(duplicate PTR) %s",text);
1989                         goto after_ref_id;
1990                 }
1991
1992                 /* new pointer */
1993                 item=proto_tree_add_text(tree, tvb, offset-4, 4,
1994                         "%s", text);
1995                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1996                 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
1997                 add_pointer_to_list(pinfo, tr, item, fnct, id, hf_index,
1998                                     callback, callback_args);
1999                 goto after_ref_id;
2000         }
2001
2002
2003 after_ref_id:
2004         /* After each top level pointer we have dissected we have to
2005            dissect all deferrals before we move on to the next top level
2006            argument */
2007         if(pointers_are_top_level==TRUE){
2008                 pointers_are_top_level=FALSE;
2009                 offset = dissect_deferred_pointers(pinfo, tvb, offset, drep);
2010                 pointers_are_top_level=TRUE;
2011         }
2012
2013         /* Set the length for the new subtree */
2014         if (tr){
2015                 proto_item_set_len(tr, offset-start_offset);
2016         }
2017         return offset;
2018 }
2019
2020 int
2021 dissect_ndr_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2022                     proto_tree *tree, guint8 *drep, dcerpc_dissect_fnct_t *fnct,
2023                     int type, const char *text, int hf_index)
2024 {
2025         return dissect_ndr_pointer_cb(
2026                 tvb, offset, pinfo, tree, drep, fnct, type, text, hf_index,
2027                 NULL, NULL);
2028 }
2029 int
2030 dissect_ndr_toplevel_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2031                     proto_tree *tree, guint8 *drep, dcerpc_dissect_fnct_t *fnct,
2032                     int type, const char *text, int hf_index)
2033 {
2034         int ret;
2035
2036         pointers_are_top_level=TRUE;
2037         ret=dissect_ndr_pointer_cb(
2038                 tvb, offset, pinfo, tree, drep, fnct, type, text, hf_index,
2039                 NULL, NULL);
2040         return ret;
2041 }
2042 int
2043 dissect_ndr_embedded_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2044                     proto_tree *tree, guint8 *drep, dcerpc_dissect_fnct_t *fnct,
2045                     int type, const char *text, int hf_index)
2046 {
2047         int ret;
2048
2049         pointers_are_top_level=FALSE;
2050         ret=dissect_ndr_pointer_cb(
2051                 tvb, offset, pinfo, tree, drep, fnct, type, text, hf_index,
2052                 NULL, NULL);
2053         return ret;
2054 }
2055
2056 static void
2057 show_stub_data (tvbuff_t *tvb, gint offset, proto_tree *dcerpc_tree,
2058                 dcerpc_auth_info *auth_info, gboolean is_encrypted)
2059 {
2060     int length, plain_length, auth_pad_len;
2061     guint auth_pad_offset;
2062
2063     /*
2064      * We don't show stub data unless we have some in the tvbuff;
2065      * however, in the protocol tree, we show, as the number of
2066      * bytes, the reported number of bytes, not the number of bytes
2067      * that happen to be in the tvbuff.
2068      */
2069     if (tvb_length_remaining (tvb, offset) > 0) {
2070         auth_pad_len = auth_info?auth_info->auth_pad_len:0;
2071         length = tvb_reported_length_remaining (tvb, offset);
2072
2073         /* if auth_pad_len is larger than length then we ignore auth_pad_len totally */
2074         plain_length = length - auth_pad_len;
2075         if (plain_length < 1) {
2076             plain_length = length;
2077             auth_pad_len = 0;
2078         }
2079         auth_pad_offset = offset + plain_length;
2080
2081         if (auth_info != NULL &&
2082             auth_info->auth_level == DCE_C_AUTHN_LEVEL_PKT_PRIVACY) {
2083             if (is_encrypted) {
2084                 tvb_ensure_bytes_exist(tvb, offset, length);
2085                 proto_tree_add_text(dcerpc_tree, tvb, offset, length,
2086                                     "Encrypted stub data (%d byte%s)",
2087                                     length, plurality(length, "", "s"));
2088                 /* is the padding is still inside the encrypted blob, don't display it explicit */
2089                 auth_pad_len = 0;
2090             } else {
2091                 tvb_ensure_bytes_exist(tvb, offset, plain_length);
2092                 proto_tree_add_text(dcerpc_tree, tvb, offset, plain_length,
2093                                     "Decrypted stub data (%d byte%s)",
2094                                     plain_length, plurality(plain_length, "", "s"));
2095             }
2096         } else {
2097             tvb_ensure_bytes_exist(tvb, offset, plain_length);
2098             proto_tree_add_text (dcerpc_tree, tvb, offset, plain_length,
2099                                  "Stub data (%d byte%s)", plain_length,
2100                                  plurality(plain_length, "", "s"));
2101         }
2102         /* If there is auth padding at the end of the stub, display it */
2103         if (auth_pad_len != 0) {
2104                 tvb_ensure_bytes_exist(tvb, auth_pad_offset, auth_pad_len);
2105                 proto_tree_add_text (dcerpc_tree, tvb, auth_pad_offset,
2106                                      auth_pad_len,
2107                                      "Auth Padding (%u byte%s)",
2108                                      auth_pad_len,
2109                                      plurality(auth_pad_len, "", "s"));
2110             }
2111     }
2112 }
2113
2114 static int
2115 dcerpc_try_handoff (packet_info *pinfo, proto_tree *tree,
2116                     proto_tree *dcerpc_tree,
2117                     tvbuff_t *volatile tvb, tvbuff_t *decrypted_tvb,
2118                     guint8 *drep, dcerpc_info *info,
2119                     dcerpc_auth_info *auth_info)
2120 {
2121     volatile gint offset = 0;
2122     dcerpc_uuid_key key;
2123     dcerpc_uuid_value *sub_proto;
2124     proto_tree *volatile sub_tree = NULL;
2125     dcerpc_sub_dissector *proc;
2126     const gchar *name = NULL;
2127     dcerpc_dissect_fnct_t *volatile sub_dissect;
2128     const char *volatile saved_proto;
2129     void *volatile saved_private_data;
2130     guint length = 0, reported_length = 0;
2131     tvbuff_t *volatile stub_tvb;
2132     volatile guint auth_pad_len;
2133     volatile int auth_pad_offset;
2134     proto_item *sub_item=NULL;
2135     proto_item *pi;
2136
2137     key.uuid = info->call_data->uuid;
2138     key.ver = info->call_data->ver;
2139
2140
2141     if ((sub_proto = g_hash_table_lookup (dcerpc_uuids, &key)) == NULL
2142          || !proto_is_protocol_enabled(sub_proto->proto)) {
2143         /*
2144          * We don't have a dissector for this UUID, or the protocol
2145          * for that UUID is disabled.
2146          */
2147
2148         proto_tree_add_boolean_hidden(dcerpc_tree, hf_dcerpc_unknown_if_id,
2149                                           tvb, offset, 0, TRUE);
2150         if (check_col (pinfo->cinfo, COL_INFO)) {
2151                 col_append_fstr (pinfo->cinfo, COL_INFO, " %s V%u",
2152                         guids_resolve_uuid_to_str(&info->call_data->uuid), info->call_data->ver);
2153         }
2154
2155         if (decrypted_tvb != NULL) {
2156             show_stub_data (decrypted_tvb, 0, dcerpc_tree, auth_info,
2157                             FALSE);
2158         } else
2159             show_stub_data (tvb, 0, dcerpc_tree, auth_info, TRUE);
2160         return -1;
2161     }
2162
2163     for (proc = sub_proto->procs; proc->name; proc++) {
2164         if (proc->num == info->call_data->opnum) {
2165             name = proc->name;
2166             break;
2167         }
2168     }
2169
2170     if (!name)
2171         name = "Unknown?!";
2172
2173     if (check_col (pinfo->cinfo, COL_PROTOCOL)) {
2174         col_set_str (pinfo->cinfo, COL_PROTOCOL, sub_proto->name);
2175     }
2176
2177     if (check_col (pinfo->cinfo, COL_INFO)) {
2178         col_add_fstr (pinfo->cinfo, COL_INFO, "%s %s",
2179                       name, (info->ptype == PDU_REQ) ? "request" : "response");
2180     }
2181
2182     sub_dissect = (info->ptype == PDU_REQ) ?
2183             proc->dissect_rqst : proc->dissect_resp;
2184
2185     if (tree) {
2186         sub_item = proto_tree_add_item (tree, sub_proto->proto_id,
2187                                         (decrypted_tvb != NULL)?decrypted_tvb:tvb,
2188                                         0, -1, FALSE);
2189
2190         if (sub_item) {
2191             sub_tree = proto_item_add_subtree (sub_item, sub_proto->ett);
2192             proto_item_append_text(sub_item, ", %s", name);
2193         }
2194
2195         /*
2196          * Put the operation number into the tree along with
2197          * the operation's name.
2198          */
2199         if (sub_proto->opnum_hf != -1)
2200                 proto_tree_add_uint_format(sub_tree, sub_proto->opnum_hf,
2201                                            tvb, 0, 0, info->call_data->opnum,
2202                                            "Operation: %s (%u)",
2203                                            name, info->call_data->opnum);
2204         else
2205                 proto_tree_add_uint_format(sub_tree, hf_dcerpc_op, tvb,
2206                                            0, 0, info->call_data->opnum,
2207                                            "Operation: %s (%u)",
2208                                            name, info->call_data->opnum);
2209
2210         if(info->ptype == PDU_REQ && info->call_data->rep_frame!=0) {
2211             pi = proto_tree_add_uint(sub_tree, hf_dcerpc_response_in,
2212                                      tvb, 0, 0, info->call_data->rep_frame);
2213             PROTO_ITEM_SET_GENERATED(pi);
2214         }
2215         if(info->ptype == PDU_RESP && info->call_data->req_frame!=0) {
2216             pi = proto_tree_add_uint(sub_tree, hf_dcerpc_request_in,
2217                                      tvb, 0, 0, info->call_data->req_frame);
2218             PROTO_ITEM_SET_GENERATED(pi);
2219         }
2220     } /* tree */
2221
2222     if (decrypted_tvb != NULL) {
2223         /* Either there was no encryption or we successfully decrypted
2224            the encrypted payload. */
2225         if (sub_dissect) {
2226             /* We have a subdissector - call it. */
2227             saved_proto = pinfo->current_proto;
2228             saved_private_data = pinfo->private_data;
2229             pinfo->current_proto = sub_proto->name;
2230             pinfo->private_data = (void *)info;
2231
2232             init_ndr_pointer_list(pinfo);
2233
2234             length = tvb_length(decrypted_tvb);
2235             reported_length = tvb_reported_length(decrypted_tvb);
2236
2237             /*
2238              * Remove the authentication padding from the stub data.
2239              */
2240             if (auth_info != NULL && auth_info->auth_pad_len != 0) {
2241                 if (reported_length >= auth_info->auth_pad_len) {
2242                     /*
2243                      * OK, the padding length isn't so big that it
2244                      * exceeds the stub length.  Trim the reported
2245                      * length of the tvbuff.
2246                      */
2247                     reported_length -= auth_info->auth_pad_len;
2248
2249                     /*
2250                      * If that exceeds the actual amount of data in
2251                      * the tvbuff (which means we have at least one
2252                      * byte of authentication padding in the tvbuff),
2253                      * trim the actual amount.
2254                      */
2255                     if (length > reported_length)
2256                         length = reported_length;
2257
2258                     stub_tvb = tvb_new_subset(decrypted_tvb, 0, length, reported_length);
2259                     auth_pad_len = auth_info->auth_pad_len;
2260                     auth_pad_offset = reported_length;
2261                 } else {
2262                     /*
2263                      * The padding length exceeds the stub length.
2264                      * Don't bother dissecting the stub, trim the padding
2265                      * length to what's in the stub data, and show the
2266                      * entire stub as authentication padding.
2267                      */
2268                     stub_tvb = NULL;
2269                     auth_pad_len = reported_length;
2270                     auth_pad_offset = 0;
2271                     length = 0;
2272                     reported_length = 0;
2273                 }
2274             } else {
2275                 /*
2276                  * No authentication padding.
2277                  */
2278                 stub_tvb = decrypted_tvb;
2279                 auth_pad_len = 0;
2280                 auth_pad_offset = 0;
2281             }
2282
2283             if (sub_item) {
2284                 proto_item_set_len(sub_item, length);
2285             }
2286
2287             if (stub_tvb != NULL) {
2288                 /*
2289                  * Catch all exceptions other than BoundsError, so that even
2290                  * if the stub data is bad, we still show the authentication
2291                  * padding, if any.
2292                  *
2293                  * If we get BoundsError, it means the frame was cut short
2294                  * by a snapshot length, so there's nothing more to
2295                  * dissect; just re-throw that exception.
2296                  */
2297                 TRY {
2298                     offset = sub_dissect (stub_tvb, 0, pinfo, sub_tree,
2299                                           drep);
2300                     if(tree && offset > 0) {
2301                         proto_item_set_len(sub_item, offset);
2302                     }
2303
2304                     /* If we have a subdissector and it didn't dissect all
2305                        data in the tvb, make a note of it. */
2306                     if (tvb_reported_length_remaining(stub_tvb, offset) > 0) {
2307                         if (check_col(pinfo->cinfo, COL_INFO))
2308                             col_append_fstr(pinfo->cinfo, COL_INFO,
2309                                             "[Long frame (%d bytes)]",
2310                                             tvb_reported_length_remaining(stub_tvb, offset));
2311                     }
2312                 } CATCH(BoundsError) {
2313                     RETHROW;
2314                 } CATCH_ALL {
2315                     show_exception(stub_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
2316                 } ENDTRY;
2317             }
2318
2319             /* If there is auth padding at the end of the stub, display it */
2320             if (auth_pad_len != 0) {
2321                 tvb_ensure_bytes_exist(tvb, auth_pad_offset, auth_pad_len);
2322                 proto_tree_add_text (sub_tree, decrypted_tvb, auth_pad_offset,
2323                                      auth_pad_len,
2324                                      "Auth Padding (%u byte%s)",
2325                                      auth_pad_len,
2326                                      plurality(auth_pad_len, "", "s"));
2327             }
2328
2329             pinfo->current_proto = saved_proto;
2330             pinfo->private_data = saved_private_data;
2331         } else {
2332             /* No subdissector - show it as stub data. */
2333             if(decrypted_tvb){
2334                show_stub_data (decrypted_tvb, 0, sub_tree, auth_info, FALSE);
2335             } else {
2336                show_stub_data (tvb, 0, sub_tree, auth_info, TRUE);
2337             }
2338         }
2339     } else
2340         show_stub_data (tvb, 0, sub_tree, auth_info, TRUE);
2341
2342     tap_queue_packet(dcerpc_tap, pinfo, info);
2343     return 0;
2344 }
2345
2346 static int
2347 dissect_dcerpc_verifier (tvbuff_t *tvb, packet_info *pinfo,
2348                          proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr,
2349                          dcerpc_auth_info *auth_info)
2350 {
2351     int auth_offset;
2352
2353     auth_info->auth_data = NULL;
2354
2355     if (auth_info->auth_size != 0) {
2356         dcerpc_auth_subdissector_fns *auth_fns;
2357         tvbuff_t *auth_tvb;
2358
2359         auth_offset = hdr->frag_len - hdr->auth_len;
2360
2361         auth_tvb = tvb_new_subset(tvb, auth_offset, hdr->auth_len,
2362                                   hdr->auth_len);
2363
2364         auth_info->auth_data = auth_tvb;
2365
2366         if ((auth_fns = get_auth_subdissector_fns(auth_info->auth_level,
2367                                                   auth_info->auth_type))) {
2368             /*
2369              * Catch all exceptions, so that even if the verifier is bad
2370              * or we don't have all of it, we still show the stub data.
2371              */
2372             TRY {
2373                 dissect_auth_verf(auth_tvb, pinfo, dcerpc_tree, auth_fns,
2374                                   hdr, auth_info);
2375             } CATCH_ALL {
2376                 show_exception(auth_tvb, pinfo, dcerpc_tree, EXCEPT_CODE, GET_MESSAGE);
2377             } ENDTRY;
2378         } else {
2379             tvb_ensure_bytes_exist(tvb, 0, hdr->auth_len);
2380             proto_tree_add_text (dcerpc_tree, auth_tvb, 0, hdr->auth_len,
2381                                  "Auth Verifier");
2382         }
2383     }
2384
2385     return hdr->auth_len;
2386 }
2387
2388 static void
2389 dissect_dcerpc_cn_auth (tvbuff_t *tvb, int stub_offset, packet_info *pinfo,
2390                         proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr,
2391                         gboolean are_credentials, dcerpc_auth_info *auth_info)
2392 {
2393     volatile int offset;
2394
2395     /*
2396      * Initially set auth_level and auth_type to zero to indicate that we
2397      * haven't yet seen any authentication level information.
2398      */
2399     auth_info->auth_level = 0;
2400     auth_info->auth_type = 0;
2401     auth_info->auth_size = 0;
2402     auth_info->auth_pad_len = 0;
2403
2404     /*
2405      * The authentication information is at the *end* of the PDU; in
2406      * request and response PDUs, the request and response stub data
2407      * come before it.
2408      *
2409      * Is there any authentication data (i.e., is the authentication length
2410      * non-zero), and is the authentication length valid (i.e., is it, plus
2411      * 8 bytes for the type/level/pad length/reserved/context id, less than
2412      * or equal to the fragment length minus the starting offset of the
2413      * stub data?)
2414      */
2415
2416     if (hdr->auth_len
2417         && (hdr->auth_len + 8 <= hdr->frag_len - stub_offset)) {
2418
2419         /*
2420          * Yes, there is authentication data, and the length is valid.
2421          * Do we have all the bytes of stub data?
2422          * (If not, we'd throw an exception dissecting *that*, so don't
2423          * bother trying to dissect the authentication information and
2424          * throwing another exception there.)
2425          */
2426         offset = hdr->frag_len - (hdr->auth_len + 8);
2427         if (offset == 0 || tvb_offset_exists(tvb, offset - 1)) {
2428             /*
2429              * Either there's no stub data, or the last byte of the stub
2430              * data is present in the captured data, so we shouldn't
2431              * get a BoundsError dissecting the stub data.
2432              *
2433              * Try dissecting the authentication data.
2434              * Catch all exceptions, so that even if the auth info is bad
2435              * or we don't have all of it, we still show the stuff we
2436              * dissect after this, such as stub data.
2437              */
2438             TRY {
2439                 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2440                                                hf_dcerpc_auth_type,
2441                                                &auth_info->auth_type);
2442                 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2443                                                hf_dcerpc_auth_level,
2444                                                &auth_info->auth_level);
2445
2446                 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2447                                                hf_dcerpc_auth_pad_len,
2448                                                &auth_info->auth_pad_len);
2449                 offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2450                                                hf_dcerpc_auth_rsrvd, NULL);
2451                 offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2452                                                 hf_dcerpc_auth_ctx_id, NULL);
2453
2454                 /*
2455                  * Dissect the authentication data.
2456                  */
2457                 if (are_credentials) {
2458                     tvbuff_t *auth_tvb;
2459                     dcerpc_auth_subdissector_fns *auth_fns;
2460
2461                     auth_tvb = tvb_new_subset(tvb, offset,
2462                                    MIN(hdr->auth_len,tvb_length_remaining(tvb, offset)),
2463                                    hdr->auth_len);
2464
2465                     if ((auth_fns = get_auth_subdissector_fns(auth_info->auth_level,
2466                                                               auth_info->auth_type)))
2467                         dissect_auth_verf(auth_tvb, pinfo, dcerpc_tree, auth_fns,
2468                                           hdr, auth_info);
2469                     else
2470                         proto_tree_add_text (dcerpc_tree, tvb, offset, hdr->auth_len,
2471                                              "Auth Credentials");
2472                 }
2473
2474                 /* Compute the size of the auth block.  Note that this should not
2475                    include auth padding, since when NTLMSSP encryption is used, the
2476                    padding is actually inside the encrypted stub */
2477                    auth_info->auth_size = hdr->auth_len + 8;
2478             } CATCH_ALL {
2479                 show_exception(tvb, pinfo, dcerpc_tree, EXCEPT_CODE, GET_MESSAGE);
2480             } ENDTRY;
2481         }
2482     }
2483 }
2484
2485
2486 /* We need to hash in the SMB fid number to generate a unique hash table
2487  * key as DCERPC over SMB allows several pipes over the same TCP/IP
2488  * socket.
2489  * We pass this function the transport type here to make sure we only look
2490  * at this function if it came across an SMB pipe.
2491  * Other transports might need to mix in their own extra multiplexing data
2492  * as well in the future.
2493  */
2494
2495 guint16 dcerpc_get_transport_salt (packet_info *pinfo)
2496 {
2497     switch(pinfo->dcetransporttype){
2498         case DCE_CN_TRANSPORT_SMBPIPE:
2499             /* DCERPC over smb */
2500             return pinfo->dcetransportsalt;
2501     }
2502
2503     /* Some other transport... */
2504     return 0;
2505 }
2506
2507 /*
2508  * Connection oriented packet types
2509  */
2510
2511 static void
2512 dissect_dcerpc_cn_bind (tvbuff_t *tvb, gint offset, packet_info *pinfo,
2513                         proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr)
2514 {
2515     conversation_t *conv = NULL;
2516     guint8 num_ctx_items = 0;
2517     guint i;
2518     gboolean saw_ctx_item = FALSE;
2519     guint16 ctx_id;
2520     guint8 num_trans_items;
2521     guint j;
2522     e_uuid_t if_id;
2523     e_uuid_t trans_id;
2524     guint32 trans_ver;
2525     guint16 if_ver, if_ver_minor;
2526     dcerpc_auth_info auth_info;
2527     char *uuid_str;
2528     const char *uuid_name = NULL;
2529         proto_item *iface_item;
2530
2531     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2532                                     hf_dcerpc_cn_max_xmit, NULL);
2533
2534     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2535                                     hf_dcerpc_cn_max_recv, NULL);
2536
2537     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2538                                     hf_dcerpc_cn_assoc_group, NULL);
2539
2540     offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2541                                     hf_dcerpc_cn_num_ctx_items, &num_ctx_items);
2542
2543     /* padding */
2544     offset += 3;
2545
2546     for (i = 0; i < num_ctx_items; i++) {
2547             proto_item *ctx_item;
2548             proto_tree *ctx_tree = NULL, *iface_tree = NULL;
2549         gint ctx_offset = offset;
2550
2551       dissect_dcerpc_uint16 (tvb, offset, pinfo, NULL, hdr->drep,
2552                                       hf_dcerpc_cn_ctx_id, &ctx_id);
2553
2554       if (check_col (pinfo->cinfo, COL_DCE_CTX)) {
2555                 if(pinfo->dcectxid == 0) {
2556                         col_append_fstr (pinfo->cinfo, COL_DCE_CTX, "%u", ctx_id);
2557                 } else {
2558                         /* this is not the first DCE-RPC request/response in this (TCP?-)PDU,
2559                          * prepend a delimiter */
2560                         col_append_fstr (pinfo->cinfo, COL_DCE_CTX, "#%u", ctx_id);
2561                 }
2562       }
2563
2564       /* save context ID for use with dcerpc_add_conv_to_bind_table() */
2565       /* (if we have multiple contexts, this might cause "decode as"
2566        *  to behave unpredictably) */
2567       pinfo->dcectxid = ctx_id;
2568
2569       if (dcerpc_tree) {
2570               ctx_item = proto_tree_add_item(dcerpc_tree, hf_dcerpc_cn_ctx_item,
2571                                              tvb, offset, 0,
2572                                              hdr->drep[0] & 0x10);
2573               ctx_tree = proto_item_add_subtree(ctx_item, ett_dcerpc_cn_ctx);
2574       }
2575
2576       offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, ctx_tree, hdr->drep,
2577                                       hf_dcerpc_cn_ctx_id, &ctx_id);
2578       offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, ctx_tree, hdr->drep,
2579                                       hf_dcerpc_cn_num_trans_items, &num_trans_items);
2580
2581       if(dcerpc_tree) {
2582         proto_item_append_text(ctx_item, "[%u]: ID:%u", i+1, ctx_id);
2583       }
2584
2585       /* padding */
2586       offset += 1;
2587
2588       dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &if_id);
2589       if (ctx_tree) {
2590
2591       iface_item = proto_tree_add_item(ctx_tree, hf_dcerpc_cn_bind_abstract_syntax, tvb, offset, 0, FALSE);
2592           iface_tree = proto_item_add_subtree(iface_item, ett_dcerpc_cn_iface);
2593
2594       uuid_str = guid_to_str((e_guid_t*)&if_id);
2595       uuid_name = guids_get_uuid_name(&if_id);
2596       if(uuid_name) {
2597                   proto_tree_add_guid_format (iface_tree, hf_dcerpc_cn_bind_if_id, tvb,
2598                                         offset, 16, (e_guid_t *) &if_id, "Interface: %s UUID: %s", uuid_name, uuid_str);
2599           proto_item_append_text(iface_item, ": %s", uuid_name);
2600       } else {
2601           proto_tree_add_guid_format (iface_tree, hf_dcerpc_cn_bind_if_id, tvb,
2602                                         offset, 16, (e_guid_t *) &if_id, "Interface UUID: %s", uuid_str);
2603           proto_item_append_text(iface_item, ": %s", uuid_str);
2604       }
2605       }
2606       offset += 16;
2607
2608       if (hdr->drep[0] & 0x10) {
2609           offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, iface_tree, hdr->drep,
2610                                           hf_dcerpc_cn_bind_if_ver, &if_ver);
2611           offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, iface_tree, hdr->drep,
2612                                           hf_dcerpc_cn_bind_if_ver_minor, &if_ver_minor);
2613       } else {
2614           offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, iface_tree, hdr->drep,
2615                                           hf_dcerpc_cn_bind_if_ver_minor, &if_ver_minor);
2616           offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, iface_tree, hdr->drep,
2617                                           hf_dcerpc_cn_bind_if_ver, &if_ver);
2618       }
2619
2620       if (ctx_tree) {
2621           proto_item_append_text(iface_item, " V%u.%u", if_ver, if_ver_minor);
2622           proto_item_set_len(iface_item, 20);
2623       }
2624
2625       if (!saw_ctx_item) {
2626         conv = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
2627                                   pinfo->srcport, pinfo->destport, 0);
2628         if (conv == NULL) {
2629             conv = conversation_new (pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
2630                                      pinfo->srcport, pinfo->destport, 0);
2631         }
2632
2633
2634         /* if this is the first time we see this packet, we need to
2635            update the dcerpc_binds table so that any later calls can
2636            match to the interface.
2637            XXX We assume that BINDs will NEVER be fragmented.
2638         */
2639         if(!(pinfo->fd->flags.visited)){
2640                 dcerpc_bind_key *key;
2641                 dcerpc_bind_value *value;
2642
2643                 key = se_alloc (sizeof (dcerpc_bind_key));
2644                 key->conv = conv;
2645                 key->ctx_id = ctx_id;
2646                 key->smb_fid = dcerpc_get_transport_salt(pinfo);
2647
2648                 value = se_alloc (sizeof (dcerpc_bind_value));
2649                 value->uuid = if_id;
2650                 value->ver = if_ver;
2651
2652                 /* add this entry to the bind table, first removing any
2653                    previous ones that are identical
2654                  */
2655                 if(g_hash_table_lookup(dcerpc_binds, key)){
2656                         g_hash_table_remove(dcerpc_binds, key);
2657                 }
2658                 g_hash_table_insert (dcerpc_binds, key, value);
2659         }
2660
2661         if (check_col (pinfo->cinfo, COL_INFO)) {
2662           if (num_ctx_items > 1)
2663                   col_append_fstr(pinfo->cinfo, COL_INFO, ", %u context items, 1st", num_ctx_items);
2664
2665                 col_append_fstr(pinfo->cinfo, COL_INFO, " %s V%u.%u",
2666                        guids_resolve_uuid_to_str(&if_id), if_ver, if_ver_minor);
2667         }
2668         saw_ctx_item = TRUE;
2669       }
2670
2671       for (j = 0; j < num_trans_items; j++) {
2672             proto_tree *trans_tree = NULL;
2673             proto_item *trans_item = NULL;
2674
2675         dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &trans_id);
2676         if (ctx_tree) {
2677
2678         trans_item = proto_tree_add_item(ctx_tree, hf_dcerpc_cn_bind_trans_syntax, tvb, offset, 0, FALSE);
2679         trans_tree = proto_item_add_subtree(trans_item, ett_dcerpc_cn_trans_syntax);
2680
2681         uuid_str = guid_to_str((e_guid_t *) &trans_id);
2682             proto_tree_add_guid_format (trans_tree, hf_dcerpc_cn_bind_trans_id, tvb,
2683                                           offset, 16, (e_guid_t *) &trans_id, "Transfer Syntax: %s", uuid_str);
2684             proto_item_append_text(trans_item, "[%u]: %s", j+1, uuid_str);
2685         }
2686         offset += 16;
2687
2688         offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, trans_tree, hdr->drep,
2689                                         hf_dcerpc_cn_bind_trans_ver, &trans_ver);
2690         if (ctx_tree) {
2691           proto_item_set_len(trans_item, 20);
2692           proto_item_append_text(trans_item, " V%u", trans_ver);
2693         }
2694       }
2695
2696       if(ctx_tree) {
2697         proto_item_set_len(ctx_item, offset - ctx_offset);
2698       }
2699     }
2700
2701     /*
2702      * XXX - we should save the authentication type *if* we have
2703      * an authentication header, and associate it with an authentication
2704      * context, so subsequent PDUs can use that context.
2705      */
2706     dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, hdr, TRUE, &auth_info);
2707 }
2708
2709 static void
2710 dissect_dcerpc_cn_bind_ack (tvbuff_t *tvb, gint offset, packet_info *pinfo,
2711                             proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr)
2712 {
2713     guint16 max_xmit, max_recv;
2714     guint16 sec_addr_len;
2715     guint8 num_results;
2716     guint i;
2717     guint16 result;
2718     guint16 reason;
2719     e_uuid_t trans_id;
2720     guint32 trans_ver;
2721     dcerpc_auth_info auth_info;
2722
2723     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2724                                     hf_dcerpc_cn_max_xmit, &max_xmit);
2725
2726     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2727                                     hf_dcerpc_cn_max_recv, &max_recv);
2728
2729     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2730                                     hf_dcerpc_cn_assoc_group, NULL);
2731
2732     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2733                                     hf_dcerpc_cn_sec_addr_len, &sec_addr_len);
2734     if (sec_addr_len != 0) {
2735         tvb_ensure_bytes_exist(tvb, offset, sec_addr_len);
2736         proto_tree_add_item (dcerpc_tree, hf_dcerpc_cn_sec_addr, tvb, offset,
2737                              sec_addr_len, FALSE);
2738         offset += sec_addr_len;
2739     }
2740
2741     if (offset % 4) {
2742         offset += 4 - offset % 4;
2743     }
2744
2745     offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2746                                    hf_dcerpc_cn_num_results, &num_results);
2747
2748     /* padding */
2749     offset += 3;
2750
2751     for (i = 0; i < num_results; i++) {
2752         proto_tree *ctx_tree = NULL;
2753
2754         if(dcerpc_tree){
2755                 proto_item *ctx_item;
2756                 ctx_item = proto_tree_add_text(dcerpc_tree, tvb, offset, 24, "Context ID[%u]", i+1);
2757                 ctx_tree = proto_item_add_subtree(ctx_item, ett_dcerpc_cn_ctx);
2758         }
2759
2760         offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, ctx_tree,
2761                                         hdr->drep, hf_dcerpc_cn_ack_result,
2762                                         &result);
2763         if (result != 0) {
2764             offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, ctx_tree,
2765                                             hdr->drep, hf_dcerpc_cn_ack_reason,
2766                                             &reason);
2767         } else {
2768             /*
2769              * The reason for rejection isn't meaningful, and often isn't
2770              * set, when the syntax was accepted.
2771              */
2772             offset += 2;
2773         }
2774
2775         dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &trans_id);
2776         if (ctx_tree) {
2777             proto_tree_add_guid_format (ctx_tree, hf_dcerpc_cn_ack_trans_id, tvb,
2778                                           offset, 16, (e_guid_t *) &trans_id, "Transfer Syntax: %s",
2779                                           guid_to_str((e_guid_t *) &trans_id));
2780         }
2781         offset += 16;
2782
2783         offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, ctx_tree, hdr->drep,
2784                                         hf_dcerpc_cn_ack_trans_ver, &trans_ver);
2785     }
2786
2787     /*
2788      * XXX - do we need to do anything with the authentication level
2789      * we get back from this?
2790      */
2791     dissect_dcerpc_cn_auth (tvb, offset, pinfo, dcerpc_tree, hdr, TRUE, &auth_info);
2792
2793     if (check_col (pinfo->cinfo, COL_INFO)) {
2794         if (num_results != 0 && result == 0) {
2795             /* XXX - only checks the last result */
2796             col_append_fstr (pinfo->cinfo, COL_INFO,
2797                              " accept max_xmit: %u max_recv: %u",
2798                              max_xmit, max_recv);
2799         } else {
2800             /* XXX - only shows the last result and reason */
2801             col_append_fstr (pinfo->cinfo, COL_INFO, " %s, reason: %s",
2802                              val_to_str(result, p_cont_result_vals,
2803                                         "Unknown result (%u)"),
2804                              val_to_str(reason, p_provider_reason_vals,
2805                                         "Unknown (%u)"));
2806         }
2807     }
2808 }
2809
2810 static void
2811 dissect_dcerpc_cn_bind_nak (tvbuff_t *tvb, gint offset, packet_info *pinfo,
2812                             proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr)
2813 {
2814     guint16 reason;
2815     guint8 num_protocols;
2816     guint i;
2817
2818     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
2819                                     hdr->drep, hf_dcerpc_cn_reject_reason,
2820                                     &reason);
2821
2822     if (check_col (pinfo->cinfo, COL_INFO)) {
2823         col_append_fstr (pinfo->cinfo, COL_INFO, " reason: %s",
2824                       val_to_str(reason, reject_reason_vals, "Unknown (%u)"));
2825     }
2826
2827     if (reason == PROTOCOL_VERSION_NOT_SUPPORTED) {
2828         offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2829                                        hf_dcerpc_cn_num_protocols,
2830                                        &num_protocols);
2831
2832         for (i = 0; i < num_protocols; i++) {
2833             offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree,
2834                                         hdr->drep, hf_dcerpc_cn_protocol_ver_major,
2835                                         NULL);
2836             offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree,
2837                                         hdr->drep, hf_dcerpc_cn_protocol_ver_minor,
2838                                         NULL);
2839         }
2840     }
2841 }
2842
2843 /* Return a string describing a DCE/RPC fragment as first, middle, or end
2844    fragment. */
2845
2846 #define PFC_FRAG_MASK  0x03
2847
2848 static const char *
2849 fragment_type(guint8 flags)
2850 {
2851         flags = flags & PFC_FRAG_MASK;
2852
2853         if (flags == PFC_FIRST_FRAG)
2854                 return "first";
2855
2856         if (flags == 0)
2857                 return "middle";
2858
2859         if (flags == PFC_LAST_FRAG)
2860                 return "last";
2861
2862         if (flags == (PFC_FIRST_FRAG | PFC_LAST_FRAG))
2863                 return "whole";
2864
2865         return "unknown";
2866 }
2867
2868 /* Dissect stub data (payload) of a DCERPC packet. */
2869
2870 static void
2871 dissect_dcerpc_cn_stub (tvbuff_t *tvb, int offset, packet_info *pinfo,
2872                         proto_tree *dcerpc_tree, proto_tree *tree,
2873                         e_dce_cn_common_hdr_t *hdr, dcerpc_info *di,
2874                         dcerpc_auth_info *auth_info, guint32 alloc_hint _U_,
2875                         guint32 frame)
2876 {
2877     gint length, reported_length;
2878     gboolean save_fragmented;
2879     fragment_data *fd_head=NULL;
2880
2881     tvbuff_t *auth_tvb, *payload_tvb, *decrypted_tvb;
2882     proto_item *pi;
2883     proto_item *parent_pi;
2884     proto_item *dcerpc_tree_item;
2885
2886     save_fragmented = pinfo->fragmented;
2887
2888     length = tvb_length_remaining(tvb, offset);
2889     reported_length = tvb_reported_length_remaining(tvb, offset);
2890     if (reported_length < 0 ||
2891         (guint32)reported_length < auth_info->auth_size) {
2892         /* We don't even have enough bytes for the authentication
2893            stuff. */
2894         return;
2895     }
2896     reported_length -= auth_info->auth_size;
2897     if (length > reported_length)
2898         length = reported_length;
2899     payload_tvb = tvb_new_subset(tvb, offset, length, reported_length);
2900
2901     auth_tvb=NULL;
2902     /*dont bother if we dont have the entire tvb */
2903     /*XXX we should really make sure we calculate auth_info->auth_data
2904         and use that one instead of this auth_tvb hack
2905     */
2906     if(tvb_length(tvb)==tvb_reported_length(tvb)){
2907         if(tvb_length_remaining(tvb, offset+length)>8){
2908             auth_tvb = tvb_new_subset(tvb, offset+length+8, -1, -1);
2909         }
2910     }
2911
2912     /* Decrypt the PDU if it is encrypted */
2913
2914     if (auth_info->auth_type &&
2915         auth_info->auth_level == DCE_C_AUTHN_LEVEL_PKT_PRIVACY) {
2916             /*
2917              * We know the authentication type, and the authentication
2918              * level is "Packet privacy", meaning the payload is
2919              * encrypted; attempt to decrypt it.
2920              */
2921             dcerpc_auth_subdissector_fns *auth_fns;
2922
2923             /* Start out assuming we won't succeed in decrypting. */
2924             decrypted_tvb = NULL;
2925
2926             if ((auth_fns = get_auth_subdissector_fns(
2927                          auth_info->auth_level, auth_info->auth_type))) {
2928                     tvbuff_t *result;
2929
2930                     result = decode_encrypted_data(
2931                             payload_tvb, auth_tvb, pinfo, auth_fns,
2932                             hdr->ptype == PDU_REQ, auth_info);
2933
2934                     if (result) {
2935                             if (dcerpc_tree)
2936                                 proto_tree_add_text(
2937                                             dcerpc_tree, payload_tvb, 0, -1,
2938                                             "Encrypted stub data (%d byte%s)",
2939                                             tvb_reported_length(payload_tvb),
2940
2941                             plurality(tvb_length(payload_tvb), "", "s"));
2942
2943                             add_new_data_source(
2944                                     pinfo, result, "Decrypted stub data");
2945
2946                             /* We succeeded. */
2947                             decrypted_tvb = result;
2948                     }
2949             }
2950     } else
2951             decrypted_tvb = payload_tvb;
2952
2953     /* if this packet is not fragmented, just dissect it and exit */
2954     if(PFC_NOT_FRAGMENTED(hdr)){
2955         pinfo->fragmented = FALSE;
2956
2957         dcerpc_try_handoff(
2958                 pinfo, tree, dcerpc_tree, payload_tvb, decrypted_tvb,
2959                 hdr->drep, di, auth_info);
2960
2961         pinfo->fragmented = save_fragmented;
2962         return;
2963     }
2964
2965     /* The packet is fragmented. */
2966     pinfo->fragmented = TRUE;
2967
2968         /* debug output of essential fragment data. */
2969         /* leave it here for future debugging sessions */
2970         /*printf("DCE num:%u offset:%u frag_len:%u tvb_len:%u\n",
2971                    pinfo->fd->num, offset, hdr->frag_len, tvb_length(decrypted_tvb));*/
2972
2973     /* if we are not doing reassembly and this is the first fragment
2974        then just dissect it and exit
2975        XXX - if we're not doing reassembly, can we decrypt an
2976        encrypted stub?
2977     */
2978     if( (!dcerpc_reassemble) && hdr->flags&PFC_FIRST_FRAG ){
2979
2980         dcerpc_try_handoff(
2981                 pinfo, tree, dcerpc_tree, payload_tvb, decrypted_tvb,
2982                 hdr->drep, di, auth_info);
2983
2984         if (check_col(pinfo->cinfo, COL_INFO)) {
2985             col_append_fstr(pinfo->cinfo, COL_INFO,
2986                             " [DCE/RPC %s fragment]", fragment_type(hdr->flags));
2987         }
2988                 expert_add_info_format(pinfo, NULL, PI_REASSEMBLE, PI_CHAT,
2989                         "%s fragment", fragment_type(hdr->flags));
2990         pinfo->fragmented = save_fragmented;
2991         return;
2992     }
2993
2994     /* if we have already seen this packet, see if it was reassembled
2995        and if so dissect the full pdu.
2996        then exit
2997     */
2998     if(pinfo->fd->flags.visited){
2999         fd_head=fragment_get_reassembled(pinfo, frame, dcerpc_co_reassemble_table);
3000         goto end_cn_stub;
3001     }
3002
3003     /* if we are not doing reassembly and it was neither a complete PDU
3004        nor the first fragment then there is nothing more we can do
3005        so we just have to exit
3006     */
3007     if( !dcerpc_reassemble || (tvb_length(tvb)!=tvb_reported_length(tvb)) )
3008         goto end_cn_stub;
3009
3010     /* if we didnt get 'frame' we dont know where the PDU started and thus
3011        it is pointless to continue
3012     */
3013     if(!frame)
3014         goto end_cn_stub;
3015
3016     /* from now on we must attempt to reassemble the PDU
3017     */
3018
3019     /* if we get here we know it is the first time we see the packet
3020        and we also know it is only a fragment and not a full PDU,
3021        thus we must reassemble it.
3022     */
3023
3024     /* Do we have any non-encrypted data to reassemble? */
3025     if (decrypted_tvb == NULL) {
3026       /* No.  We can't even try to reassemble.  */
3027       goto end_cn_stub;
3028     }
3029
3030     /* defragmentation is a bit tricky, as there's no offset of the fragment
3031      * in the protocol data.
3032      *
3033      * just use fragment_add_seq_next() and hope that TCP/SMB segments coming
3034      * in with the correct sequence.
3035      */
3036     fd_head = fragment_add_seq_next(decrypted_tvb, 0, pinfo, frame,
3037                 dcerpc_co_fragment_table, dcerpc_co_reassemble_table,
3038                 tvb_length(decrypted_tvb),
3039                 hdr->flags&PFC_LAST_FRAG ? FALSE : TRUE /* more_frags */);
3040
3041 end_cn_stub:
3042
3043     /* if reassembly is complete and this is the last fragment
3044          * (multiple fragments in one PDU are possible!)
3045          * dissect the full PDU
3046      */
3047     if(fd_head && (fd_head->flags&FD_DEFRAGMENTED) ){
3048
3049         if(pinfo->fd->num==fd_head->reassembled_in && (hdr->flags&PFC_LAST_FRAG) ){
3050             tvbuff_t *next_tvb;
3051         proto_item *frag_tree_item;
3052
3053             next_tvb = tvb_new_real_data(fd_head->data, fd_head->len, fd_head->len);
3054             if(decrypted_tvb){
3055                 tvb_set_child_real_data_tvbuff(decrypted_tvb, next_tvb);
3056             } else {
3057                 tvb_set_child_real_data_tvbuff(payload_tvb, next_tvb);
3058             }
3059             add_new_data_source(pinfo, next_tvb, "Reassembled DCE/RPC");
3060             show_fragment_tree(fd_head, &dcerpc_frag_items,
3061                         tree, pinfo, next_tvb, &frag_tree_item);
3062                 /* the toplevel fragment subtree is now behind all desegmented data,
3063                  * move it right behind the DCE/RPC tree */
3064                 dcerpc_tree_item = proto_tree_get_parent(dcerpc_tree);
3065                 if(frag_tree_item && dcerpc_tree_item) {
3066                         proto_tree_move_item(tree, dcerpc_tree_item, frag_tree_item);
3067                 }
3068
3069             pinfo->fragmented = FALSE;
3070
3071                 expert_add_info_format(pinfo, frag_tree_item, PI_REASSEMBLE, PI_CHAT,
3072                         "%s fragment, reassembled",
3073                         fragment_type(hdr->flags));
3074
3075             dcerpc_try_handoff (pinfo, tree, dcerpc_tree, next_tvb,
3076                 next_tvb, hdr->drep, di, auth_info);
3077
3078         } else {
3079             if(decrypted_tvb){
3080                 pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_reassembled_in,
3081                                 decrypted_tvb, 0, 0, fd_head->reassembled_in);
3082             } else {
3083                 pi = proto_tree_add_uint(dcerpc_tree, hf_dcerpc_reassembled_in,
3084                                 payload_tvb, 0, 0, fd_head->reassembled_in);
3085             }
3086         PROTO_ITEM_SET_GENERATED(pi);
3087         parent_pi = proto_tree_get_parent(dcerpc_tree);
3088         if(parent_pi != NULL) {
3089             proto_item_append_text(parent_pi, ", [Reas: #%u]", fd_head->reassembled_in);
3090         }
3091             if (check_col(pinfo->cinfo, COL_INFO)) {
3092                 col_append_fstr(pinfo->cinfo, COL_INFO,
3093                         " [DCE/RPC %s fragment, reas: #%u]", fragment_type(hdr->flags),&nbs