6d61158db357b0040dd5453c8c9299909ca27216
[metze/wireshark/wip.git] / epan / dissectors / packet-dcerpc.c
1 /* packet-dcerpc.c
2  * Routines for DCERPC packet disassembly
3  * Copyright 2001, Todd Sabin <tas[AT]webspan.net>
4  * Copyright 2003, Tim Potter <tpot[AT]samba.org>
5  * Copyright 2010, Julien Kerihuel <j.kerihuel[AT]openchange.org>
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  */
25
26 /* The DCE RPC specification can be found at:
27  * http://www.opengroup.org/dce/
28  */
29
30 #include "config.h"
31
32 #include <stdio.h>
33 #include <epan/packet.h>
34 #include <epan/exceptions.h>
35 #include <epan/prefs.h>
36 #include <epan/reassemble.h>
37 #include <epan/tap.h>
38 #include <epan/srt_table.h>
39 #include <epan/expert.h>
40 #include <epan/addr_resolv.h>
41 #include <epan/show_exception.h>
42 #include <epan/decode_as.h>
43 #include <epan/proto_data.h>
44
45 #include <wsutil/str_util.h>
46 #include "packet-tcp.h"
47 #include "packet-dcerpc.h"
48 #include "packet-dcerpc-nt.h"
49
50 void proto_register_dcerpc(void);
51 void proto_reg_handoff_dcerpc(void);
52
53 static int dcerpc_tap = -1;
54
55 /* 32bit Network Data Representation, see DCE/RPC Appendix I */
56 static e_guid_t uuid_data_repr_proto        = { 0x8a885d04, 0x1ceb, 0x11c9,
57                                                 { 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60 } };
58
59 /* 64bit Network Data Representation, introduced in Windows Server 2008 */
60 static e_guid_t uuid_ndr64                  = { 0x71710533, 0xbeba, 0x4937,
61                                                 { 0x83, 0x19, 0xb5, 0xdb, 0xef, 0x9c, 0xcc, 0x36 } };
62
63 /* see [MS-OXRPC] Appendix A: Full IDL, http://msdn.microsoft.com/en-us/library/ee217991%28v=exchg.80%29.aspx */
64 static e_guid_t uuid_asyncemsmdb            = { 0x5261574a, 0x4572, 0x206e,
65                                                 { 0xb2, 0x68, 0x6b, 0x19, 0x92, 0x13, 0xb4, 0xe4 } };
66
67 static const value_string pckt_vals[] = {
68     { PDU_REQ,        "Request"},
69     { PDU_PING,       "Ping"},
70     { PDU_RESP,       "Response"},
71     { PDU_FAULT,      "Fault"},
72     { PDU_WORKING,    "Working"},
73     { PDU_NOCALL,     "Nocall"},
74     { PDU_REJECT,     "Reject"},
75     { PDU_ACK,        "Ack"},
76     { PDU_CL_CANCEL,  "Cl_cancel"},
77     { PDU_FACK,       "Fack"},
78     { PDU_CANCEL_ACK, "Cancel_ack"},
79     { PDU_BIND,       "Bind"},
80     { PDU_BIND_ACK,   "Bind_ack"},
81     { PDU_BIND_NAK,   "Bind_nak"},
82     { PDU_ALTER,      "Alter_context"},
83     { PDU_ALTER_ACK,  "Alter_context_resp"},
84     { PDU_AUTH3,      "AUTH3"},
85     { PDU_SHUTDOWN,   "Shutdown"},
86     { PDU_CO_CANCEL,  "Co_cancel"},
87     { PDU_ORPHANED,   "Orphaned"},
88     { PDU_RTS,        "RPC-over-HTTP RTS"},
89     { 0,              NULL }
90 };
91
92 static const value_string drep_byteorder_vals[] = {
93     { 0, "Big-endian" },
94     { 1, "Little-endian" },
95     { 0,  NULL }
96 };
97
98 static const value_string drep_character_vals[] = {
99     { 0, "ASCII" },
100     { 1, "EBCDIC" },
101     { 0,  NULL }
102 };
103
104 #define DCE_RPC_DREP_FP_IEEE 0
105 #define DCE_RPC_DREP_FP_VAX  1
106 #define DCE_RPC_DREP_FP_CRAY 2
107 #define DCE_RPC_DREP_FP_IBM  3
108
109 static const value_string drep_fp_vals[] = {
110     { DCE_RPC_DREP_FP_IEEE, "IEEE" },
111     { DCE_RPC_DREP_FP_VAX,  "VAX"  },
112     { DCE_RPC_DREP_FP_CRAY, "Cray" },
113     { DCE_RPC_DREP_FP_IBM,  "IBM"  },
114     { 0,  NULL }
115 };
116
117 /*
118  * Authentication services.
119  */
120 static const value_string authn_protocol_vals[] = {
121     { DCE_C_RPC_AUTHN_PROTOCOL_NONE,         "None" },
122     { DCE_C_RPC_AUTHN_PROTOCOL_KRB5,         "Kerberos 5" },
123     { DCE_C_RPC_AUTHN_PROTOCOL_SPNEGO,       "SPNEGO" },
124     { DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,      "NTLMSSP" },
125     { DCE_C_RPC_AUTHN_PROTOCOL_GSS_SCHANNEL, "SCHANNEL SSP" },
126     { DCE_C_RPC_AUTHN_PROTOCOL_GSS_KERBEROS, "Kerberos SSP" },
127     { DCE_C_RPC_AUTHN_PROTOCOL_DPA,
128       "Distributed Password Authentication SSP"},
129     { DCE_C_RPC_AUTHN_PROTOCOL_MSN,          "MSN SSP"},
130     { DCE_C_RPC_AUTHN_PROTOCOL_DIGEST,       "Digest SSP"},
131     { DCE_C_RPC_AUTHN_PROTOCOL_SEC_CHAN,     "NETLOGON Secure Channel" },
132     { DCE_C_RPC_AUTHN_PROTOCOL_MQ,           "MSMQ SSP"},
133     { 0, NULL }
134 };
135
136 /*
137  * Protection levels.
138  */
139 static const value_string authn_level_vals[] = {
140     { DCE_C_AUTHN_LEVEL_NONE,          "None" },
141     { DCE_C_AUTHN_LEVEL_CONNECT,       "Connect" },
142     { DCE_C_AUTHN_LEVEL_CALL,          "Call" },
143     { DCE_C_AUTHN_LEVEL_PKT,           "Packet" },
144     { DCE_C_AUTHN_LEVEL_PKT_INTEGRITY, "Packet integrity" },
145     { DCE_C_AUTHN_LEVEL_PKT_PRIVACY,   "Packet privacy" },
146     { 0,                               NULL }
147 };
148
149 /*
150  * Flag bits in first flag field in connectionless PDU header.
151  */
152 #define PFCL1_RESERVED_01       0x01    /* Reserved for use by implementations */
153 #define PFCL1_LASTFRAG          0x02    /* If set, the PDU is the last
154                                          * fragment of a multi-PDU
155                                          * transmission */
156 #define PFCL1_FRAG              0x04    /* If set, the PDU is a fragment of
157                                            a multi-PDU transmission */
158 #define PFCL1_NOFACK            0x08    /* If set, the receiver is not
159                                          * requested to send a `fack' PDU
160                                          * for the fragment */
161 #define PFCL1_MAYBE             0x10    /* If set, the PDU is for a `maybe'
162                                          * request */
163 #define PFCL1_IDEMPOTENT        0x20    /* If set, the PDU is for an idempotent
164                                          * request */
165 #define PFCL1_BROADCAST         0x40    /* If set, the PDU is for a broadcast
166                                          * request */
167 #define PFCL1_RESERVED_80       0x80    /* Reserved for use by implementations */
168
169 /*
170  * Flag bits in second flag field in connectionless PDU header.
171  */
172 #define PFCL2_RESERVED_01       0x01    /* Reserved for use by implementations */
173 #define PFCL2_CANCEL_PENDING    0x02    /* Cancel pending at the call end */
174 #define PFCL2_RESERVED_04       0x04    /* Reserved for future use */
175 #define PFCL2_RESERVED_08       0x08    /* Reserved for future use */
176 #define PFCL2_RESERVED_10       0x10    /* Reserved for future use */
177 #define PFCL2_RESERVED_20       0x20    /* Reserved for future use */
178 #define PFCL2_RESERVED_40       0x40    /* Reserved for future use */
179 #define PFCL2_RESERVED_80       0x80    /* Reserved for future use */
180
181 /*
182  * Flag bits in connection-oriented PDU header.
183  */
184 #define PFC_FIRST_FRAG          0x01    /* First fragment */
185 #define PFC_LAST_FRAG           0x02    /* Last fragment */
186 #define PFC_PENDING_CANCEL      0x04    /* Cancel was pending at sender */
187 #define PFC_RESERVED_1          0x08
188 #define PFC_CONC_MPX            0x10    /* supports concurrent multiplexing
189                                          * of a single connection. */
190 #define PFC_DID_NOT_EXECUTE     0x20    /* only meaningful on `fault' packet;
191                                          * if true, guaranteed call did not
192                                          * execute. */
193 #define PFC_MAYBE               0x40    /* `maybe' call semantics requested */
194 #define PFC_OBJECT_UUID         0x80    /* if true, a non-nil object UUID
195                                          * was specified in the handle, and
196                                          * is present in the optional object
197                                          * field. If false, the object field
198                                          * is omitted. */
199
200 /*
201  * Tests whether a connection-oriented PDU is fragmented; returns TRUE if
202  * it's not fragmented (i.e., this is both the first *and* last fragment),
203  * and FALSE otherwise.
204  */
205 #define PFC_NOT_FRAGMENTED(hdr)                                         \
206     ((hdr->flags&(PFC_FIRST_FRAG|PFC_LAST_FRAG)) == (PFC_FIRST_FRAG|PFC_LAST_FRAG))
207
208 /*
209  * Presentation context negotiation result.
210  */
211 static const value_string p_cont_result_vals[] = {
212     { 0, "Acceptance" },
213     { 1, "User rejection" },
214     { 2, "Provider rejection" },
215     { 3, "Negotiate ACK" }, /* [MS-RPCE] 2.2.2.4 */
216     { 0, NULL }
217 };
218
219 /*
220  * Presentation context negotiation rejection reasons.
221  */
222 static const value_string p_provider_reason_vals[] = {
223     { 0, "Reason not specified" },
224     { 1, "Abstract syntax not supported" },
225     { 2, "Proposed transfer syntaxes not supported" },
226     { 3, "Local limit exceeded" },
227     { 0, NULL }
228 };
229
230 /*
231  * Reject reasons.
232  */
233 #define REASON_NOT_SPECIFIED            0
234 #define TEMPORARY_CONGESTION            1
235 #define LOCAL_LIMIT_EXCEEDED            2
236 #define CALLED_PADDR_UNKNOWN            3 /* not used */
237 #define PROTOCOL_VERSION_NOT_SUPPORTED  4
238 #define DEFAULT_CONTEXT_NOT_SUPPORTED   5 /* not used */
239 #define USER_DATA_NOT_READABLE          6 /* not used */
240 #define NO_PSAP_AVAILABLE               7 /* not used */
241 #define AUTH_TYPE_NOT_RECOGNIZED        8 /* [MS-RPCE] 2.2.2.5 */
242 #define INVALID_CHECKSUM                9 /* [MS-RPCE] 2.2.2.5 */
243
244 static const value_string reject_reason_vals[] = {
245     { REASON_NOT_SPECIFIED,           "Reason not specified" },
246     { TEMPORARY_CONGESTION,           "Temporary congestion" },
247     { LOCAL_LIMIT_EXCEEDED,           "Local limit exceeded" },
248     { CALLED_PADDR_UNKNOWN,           "Called paddr unknown" },
249     { PROTOCOL_VERSION_NOT_SUPPORTED, "Protocol version not supported" },
250     { DEFAULT_CONTEXT_NOT_SUPPORTED,  "Default context not supported" },
251     { USER_DATA_NOT_READABLE,         "User data not readable" },
252     { NO_PSAP_AVAILABLE,              "No PSAP available" },
253     { AUTH_TYPE_NOT_RECOGNIZED,       "Authentication type not recognized" },
254     { INVALID_CHECKSUM,               "Invalid checksum" },
255     { 0,                              NULL }
256 };
257
258 /*
259  * Reject status codes.
260  */
261 static const value_string reject_status_vals[] = {
262     { 0,          "Stub-defined exception" },
263     { 0x00000001, "nca_s_fault_other" },
264     { 0x00000005, "nca_s_fault_access_denied" },
265     { 0x000006f7, "nca_s_fault_ndr" },
266     { 0x000006d8, "nca_s_fault_cant_perform" },
267     { 0x00000721, "nca_s_fault_sec_pkg_error" },
268     { 0x1c000001, "nca_s_fault_int_div_by_zero" },
269     { 0x1c000002, "nca_s_fault_addr_error" },
270     { 0x1c000003, "nca_s_fault_fp_div_zero" },
271     { 0x1c000004, "nca_s_fault_fp_underflow" },
272     { 0x1c000005, "nca_s_fault_fp_overflow" },
273     { 0x1c000006, "nca_s_fault_invalid_tag" },
274     { 0x1c000007, "nca_s_fault_invalid_bound" },
275     { 0x1c000008, "nca_rpc_version_mismatch" },
276     { 0x1c000009, "nca_unspec_reject" },
277     { 0x1c00000a, "nca_s_bad_actid" },
278     { 0x1c00000b, "nca_who_are_you_failed" },
279     { 0x1c00000c, "nca_manager_not_entered" },
280     { 0x1c00000d, "nca_s_fault_cancel" },
281     { 0x1c00000e, "nca_s_fault_ill_inst" },
282     { 0x1c00000f, "nca_s_fault_fp_error" },
283     { 0x1c000010, "nca_s_fault_int_overflow" },
284     { 0x1c000014, "nca_s_fault_pipe_empty" },
285     { 0x1c000015, "nca_s_fault_pipe_closed" },
286     { 0x1c000016, "nca_s_fault_pipe_order" },
287     { 0x1c000017, "nca_s_fault_pipe_discipline" },
288     { 0x1c000018, "nca_s_fault_pipe_comm_error" },
289     { 0x1c000019, "nca_s_fault_pipe_memory" },
290     { 0x1c00001a, "nca_s_fault_context_mismatch" },
291     { 0x1c00001b, "nca_s_fault_remote_no_memory" },
292     { 0x1c00001c, "nca_invalid_pres_context_id" },
293     { 0x1c00001d, "nca_unsupported_authn_level" },
294     { 0x1c00001f, "nca_invalid_checksum" },
295     { 0x1c000020, "nca_invalid_crc" },
296     { 0x1c000021, "ncs_s_fault_user_defined" },
297     { 0x1c000022, "nca_s_fault_tx_open_failed" },
298     { 0x1c000023, "nca_s_fault_codeset_conv_error" },
299     { 0x1c000024, "nca_s_fault_object_not_found" },
300     { 0x1c000025, "nca_s_fault_no_client_stub" },
301     { 0x1c010002, "nca_op_rng_error" },
302     { 0x1c010003, "nca_unk_if"},
303     { 0x1c010006, "nca_wrong_boot_time" },
304     { 0x1c010009, "nca_s_you_crashed" },
305     { 0x1c01000b, "nca_proto_error" },
306     { 0x1c010013, "nca_out_args_too_big" },
307     { 0x1c010014, "nca_server_too_busy" },
308     { 0x1c010017, "nca_unsupported_type" },
309     /* MS Windows specific values
310      * see: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/debug/base/system_error_codes__1700-3999_.asp
311      * and: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/seccrypto/security/common_hresult_values.asp
312      * and: http://www.megos.ch/support/doserrors.txt
313      *
314      * XXX - we might need a way to dynamically add entries here, as higher layer protocols use these values too,
315      * at least MS protocols (like DCOM) do it that way ... */
316     { 0x80004001, "E_NOTIMPL" },
317     { 0x80004003, "E_POINTER" },
318     { 0x80004004, "E_ABORT" },
319     { 0x8000FFFF, "E_UNEXPECTED" },
320     { 0x80010105, "RPC_E_SERVERFAULT" },
321     { 0x80010108, "RPC_E_DISCONNECTED" },
322     { 0x80010113, "RPC_E_INVALID_IPID" },
323     { 0x8001011F, "RPC_E_TIMEOUT" },
324     { 0x80020003, "DISP_E_MEMBERNOTFOUND" },
325     { 0x80020006, "DISP_E_UNKNOWNNAME" },
326     { 0x8002000E, "DISP_E_BADPARAMCOUNT" },
327     { 0x8004CB00, "CBA_E_MALFORMED" },
328     { 0x8004CB01, "CBA_E_UNKNOWNOBJECT" },
329     { 0x8004CB05, "CBA_E_INVALIDID" },
330     { 0x8004CB09, "CBA_E_INVALIDCOOKIE" },
331     { 0x8004CB0B, "CBA_E_QOSTYPEUNSUPPORTED" },
332     { 0x8004CB0C, "CBA_E_QOSVALUEUNSUPPORTED" },
333     { 0x8004CB0F, "CBA_E_NOTAPPLICABLE" },
334     { 0x8004CB12, "CBA_E_LIMITVIOLATION" },
335     { 0x8004CB13, "CBA_E_QOSTYPENOTAPPLICABLE" },
336     { 0x8004CB18, "CBA_E_OUTOFPARTNERACCOS" },
337     { 0x8004CB1C, "CBA_E_FLAGUNSUPPORTED" },
338     { 0x8004CB23, "CBA_E_FRAMECOUNTUNSUPPORTED" },
339     { 0x8004CB25, "CBA_E_MODECHANGE" },
340     { 0x8007000E, "E_OUTOFMEMORY" },
341     { 0x80070057, "E_INVALIDARG" },
342     { 0x800706d1, "RPC_S_PROCNUM_OUT_OF_RANGE" },
343     { 0x80070776, "OR_INVALID_OXID" },
344     { 0,          NULL }
345 };
346
347
348 /*
349  * RTS Flags
350  */
351 #define RTS_FLAG_NONE             0x0000
352 #define RTS_FLAG_PING             0x0001
353 #define RTS_FLAG_OTHER_CMD        0x0002
354 #define RTS_FLAG_RECYCLE_CHANNEL  0x0004
355 #define RTS_FLAG_IN_CHANNEL       0x0008
356 #define RTS_FLAG_OUT_CHANNEL      0x0010
357 #define RTS_FLAG_EOF              0x0020
358 #define RTS_FLAG_ECHO             0x0040
359
360 /*
361  * RTS Commands
362  */
363
364 #define RTS_CMD_RECEIVEWINDOWSIZE     0x0
365 #define RTS_CMD_FLOWCONTROLACK        0x1
366 #define RTS_CMD_CONNECTIONTIMEOUT     0x2
367 #define RTS_CMD_COOKIE                0x3
368 #define RTS_CMD_CHANNELLIFETIME       0x4
369 #define RTS_CMD_CLIENTKEEPALIVE       0x5
370 #define RTS_CMD_VERSION               0x6
371 #define RTS_CMD_EMPTY                 0x7
372 #define RTS_CMD_PADDING               0x8
373 #define RTS_CMD_NEGATIVEANCE          0x9
374 #define RTS_CMD_ANCE                  0xA
375 #define RTS_CMD_CLIENTADDRESS         0xB
376 #define RTS_CMD_ASSOCIATIONGROUPID    0xC
377 #define RTS_CMD_DESTINATION           0xD
378 #define RTS_CMD_PINGTRAFFICSENTNOTIFY 0xE
379
380 static const value_string rts_command_vals[] = {
381      { RTS_CMD_RECEIVEWINDOWSIZE,     "ReceiveWindowSize" },
382      { RTS_CMD_FLOWCONTROLACK,        "FlowControlAck" },
383      { RTS_CMD_CONNECTIONTIMEOUT,     "ConnectionTimeOut" },
384      { RTS_CMD_COOKIE,                "Cookie" },
385      { RTS_CMD_CHANNELLIFETIME,       "ChannelLifetime" },
386      { RTS_CMD_CLIENTKEEPALIVE,       "ClientKeepalive" },
387      { RTS_CMD_VERSION,               "Version" },
388      { RTS_CMD_EMPTY,                 "Empty" },
389      { RTS_CMD_PADDING,               "Padding" },
390      { RTS_CMD_NEGATIVEANCE,          "NegativeANCE" },
391      { RTS_CMD_ANCE,                  "ANCE" },
392      { RTS_CMD_CLIENTADDRESS,         "ClientAddress" },
393      { RTS_CMD_ASSOCIATIONGROUPID,    "AssociationGroupId" },
394      { RTS_CMD_DESTINATION,           "Destination" },
395      { RTS_CMD_PINGTRAFFICSENTNOTIFY, "PingTrafficSentNotify" },
396      { 0x0, NULL }
397 };
398
399 /*
400  * RTS client address type
401  */
402 #define RTS_IPV4 0
403 #define RTS_IPV6 1
404
405 static const value_string rts_addresstype_vals[] = {
406      { RTS_IPV4, "IPV4" },
407      { RTS_IPV6, "IPV6" },
408      { 0x0, NULL }
409 };
410
411 /*
412  * RTS Forward destination
413  */
414
415 static const value_string rts_forward_destination_vals[] = {
416      { 0x0, "FDClient" },
417      { 0x1, "FDInProxy" },
418      { 0x2, "FDServer" },
419      { 0x3, "FDOutProxy" },
420      { 0x0, NULL }
421 };
422
423 /* we need to keep track of what transport were used, ie what handle we came
424  * in through so we know what kind of pinfo->dce_smb_fid was passed to us.
425  */
426 /* Value of -1 is reserved for "not DCE packet" in packet_info.dcetransporttype. */
427 #define DCE_TRANSPORT_UNKNOWN           0
428 #define DCE_CN_TRANSPORT_SMBPIPE        1
429
430
431 static int proto_dcerpc = -1;
432
433 /* field defines */
434 static int hf_dcerpc_request_in = -1;
435 static int hf_dcerpc_time = -1;
436 static int hf_dcerpc_response_in = -1;
437 static int hf_dcerpc_ver = -1;
438 static int hf_dcerpc_ver_minor = -1;
439 static int hf_dcerpc_packet_type = -1;
440 static int hf_dcerpc_cn_flags = -1;
441 static int hf_dcerpc_cn_flags_first_frag = -1;
442 static int hf_dcerpc_cn_flags_last_frag = -1;
443 static int hf_dcerpc_cn_flags_cancel_pending = -1;
444 static int hf_dcerpc_cn_flags_reserved = -1;
445 static int hf_dcerpc_cn_flags_mpx = -1;
446 static int hf_dcerpc_cn_flags_dne = -1;
447 static int hf_dcerpc_cn_flags_maybe = -1;
448 static int hf_dcerpc_cn_flags_object = -1;
449 static int hf_dcerpc_drep = -1;
450        int hf_dcerpc_drep_byteorder = -1;
451        int hf_dcerpc_ndr_padding = -1;
452 static int hf_dcerpc_drep_character = -1;
453 static int hf_dcerpc_drep_fp = -1;
454 static int hf_dcerpc_cn_frag_len = -1;
455 static int hf_dcerpc_cn_auth_len = -1;
456 static int hf_dcerpc_cn_call_id = -1;
457 static int hf_dcerpc_cn_max_xmit = -1;
458 static int hf_dcerpc_cn_max_recv = -1;
459 static int hf_dcerpc_cn_assoc_group = -1;
460 static int hf_dcerpc_cn_num_ctx_items = -1;
461 static int hf_dcerpc_cn_ctx_item = -1;
462 static int hf_dcerpc_cn_ctx_id = -1;
463 static int hf_dcerpc_cn_num_trans_items = -1;
464 static int hf_dcerpc_cn_bind_abstract_syntax = -1;
465 static int hf_dcerpc_cn_bind_if_id = -1;
466 static int hf_dcerpc_cn_bind_if_ver = -1;
467 static int hf_dcerpc_cn_bind_if_ver_minor = -1;
468 static int hf_dcerpc_cn_bind_trans_syntax = -1;
469 static int hf_dcerpc_cn_bind_trans_id = -1;
470 static int hf_dcerpc_cn_bind_trans_ver = -1;
471 static int hf_dcerpc_cn_bind_trans_btfn = -1;
472 static int hf_dcerpc_cn_bind_trans_btfn_01 = -1;
473 static int hf_dcerpc_cn_bind_trans_btfn_02 = -1;
474 static int hf_dcerpc_cn_alloc_hint = -1;
475 static int hf_dcerpc_cn_sec_addr_len = -1;
476 static int hf_dcerpc_cn_sec_addr = -1;
477 static int hf_dcerpc_cn_num_results = -1;
478 static int hf_dcerpc_cn_ack_result = -1;
479 static int hf_dcerpc_cn_ack_reason = -1;
480 static int hf_dcerpc_cn_ack_trans_id = -1;
481 static int hf_dcerpc_cn_ack_trans_ver = -1;
482 static int hf_dcerpc_cn_reject_reason = -1;
483 static int hf_dcerpc_cn_num_protocols = -1;
484 static int hf_dcerpc_cn_protocol_ver_major = -1;
485 static int hf_dcerpc_cn_protocol_ver_minor = -1;
486 static int hf_dcerpc_cn_cancel_count = -1;
487 static int hf_dcerpc_cn_status = -1;
488 static int hf_dcerpc_cn_deseg_req = -1;
489 static int hf_dcerpc_cn_rts_flags = -1;
490 static int hf_dcerpc_cn_rts_flags_none = -1;
491 static int hf_dcerpc_cn_rts_flags_ping = -1;
492 static int hf_dcerpc_cn_rts_flags_other_cmd = -1;
493 static int hf_dcerpc_cn_rts_flags_recycle_channel = -1;
494 static int hf_dcerpc_cn_rts_flags_in_channel = -1;
495 static int hf_dcerpc_cn_rts_flags_out_channel = -1;
496 static int hf_dcerpc_cn_rts_flags_eof = -1;
497 static int hf_dcerpc_cn_rts_commands_nb = -1;
498 static int hf_dcerpc_cn_rts_command = -1;
499 static int hf_dcerpc_cn_rts_command_receivewindowsize = -1;
500 static int hf_dcerpc_cn_rts_command_fack_bytesreceived = -1;
501 static int hf_dcerpc_cn_rts_command_fack_availablewindow = -1;
502 static int hf_dcerpc_cn_rts_command_fack_channelcookie = -1;
503 static int hf_dcerpc_cn_rts_command_connectiontimeout = -1;
504 static int hf_dcerpc_cn_rts_command_cookie = -1;
505 static int hf_dcerpc_cn_rts_command_channellifetime = -1;
506 static int hf_dcerpc_cn_rts_command_clientkeepalive = -1;
507 static int hf_dcerpc_cn_rts_command_version = -1;
508 static int hf_dcerpc_cn_rts_command_conformancecount = -1;
509 static int hf_dcerpc_cn_rts_command_padding = -1;
510 static int hf_dcerpc_cn_rts_command_addrtype = -1;
511 static int hf_dcerpc_cn_rts_command_associationgroupid = -1;
512 static int hf_dcerpc_cn_rts_command_forwarddestination = -1;
513 static int hf_dcerpc_cn_rts_command_pingtrafficsentnotify = -1;
514 static int hf_dcerpc_auth_type = -1;
515 static int hf_dcerpc_auth_level = -1;
516 static int hf_dcerpc_auth_pad_len = -1;
517 static int hf_dcerpc_auth_rsrvd = -1;
518 static int hf_dcerpc_auth_ctx_id = -1;
519 static int hf_dcerpc_dg_flags1 = -1;
520 static int hf_dcerpc_dg_flags1_rsrvd_01 = -1;
521 static int hf_dcerpc_dg_flags1_last_frag = -1;
522 static int hf_dcerpc_dg_flags1_frag = -1;
523 static int hf_dcerpc_dg_flags1_nofack = -1;
524 static int hf_dcerpc_dg_flags1_maybe = -1;
525 static int hf_dcerpc_dg_flags1_idempotent = -1;
526 static int hf_dcerpc_dg_flags1_broadcast = -1;
527 static int hf_dcerpc_dg_flags1_rsrvd_80 = -1;
528 static int hf_dcerpc_dg_flags2 = -1;
529 static int hf_dcerpc_dg_flags2_rsrvd_01 = -1;
530 static int hf_dcerpc_dg_flags2_cancel_pending = -1;
531 static int hf_dcerpc_dg_flags2_rsrvd_04 = -1;
532 static int hf_dcerpc_dg_flags2_rsrvd_08 = -1;
533 static int hf_dcerpc_dg_flags2_rsrvd_10 = -1;
534 static int hf_dcerpc_dg_flags2_rsrvd_20 = -1;
535 static int hf_dcerpc_dg_flags2_rsrvd_40 = -1;
536 static int hf_dcerpc_dg_flags2_rsrvd_80 = -1;
537 static int hf_dcerpc_dg_serial_hi = -1;
538 static int hf_dcerpc_obj_id = -1;
539 static int hf_dcerpc_dg_if_id = -1;
540 static int hf_dcerpc_dg_act_id = -1;
541 static int hf_dcerpc_dg_serial_lo = -1;
542 static int hf_dcerpc_dg_ahint = -1;
543 static int hf_dcerpc_dg_ihint = -1;
544 static int hf_dcerpc_dg_frag_len = -1;
545 static int hf_dcerpc_dg_frag_num = -1;
546 static int hf_dcerpc_dg_auth_proto = -1;
547 static int hf_dcerpc_opnum = -1;
548 static int hf_dcerpc_dg_seqnum = -1;
549 static int hf_dcerpc_dg_server_boot = -1;
550 static int hf_dcerpc_dg_if_ver = -1;
551 static int hf_dcerpc_krb5_av_prot_level = -1;
552 static int hf_dcerpc_krb5_av_key_vers_num = -1;
553 static int hf_dcerpc_krb5_av_key_auth_verifier = -1;
554 static int hf_dcerpc_dg_cancel_vers = -1;
555 static int hf_dcerpc_dg_cancel_id = -1;
556 static int hf_dcerpc_dg_server_accepting_cancels = -1;
557 static int hf_dcerpc_dg_fack_vers = -1;
558 static int hf_dcerpc_dg_fack_window_size = -1;
559 static int hf_dcerpc_dg_fack_max_tsdu = -1;
560 static int hf_dcerpc_dg_fack_max_frag_size = -1;
561 static int hf_dcerpc_dg_fack_serial_num = -1;
562 static int hf_dcerpc_dg_fack_selack_len = -1;
563 static int hf_dcerpc_dg_fack_selack = -1;
564 static int hf_dcerpc_dg_status = -1;
565 static int hf_dcerpc_array_max_count = -1;
566 static int hf_dcerpc_array_offset = -1;
567 static int hf_dcerpc_array_actual_count = -1;
568 static int hf_dcerpc_op = -1;
569 static int hf_dcerpc_referent_id32 = -1;
570 static int hf_dcerpc_referent_id64 = -1;
571 static int hf_dcerpc_null_pointer = -1;
572 static int hf_dcerpc_fragments = -1;
573 static int hf_dcerpc_fragment = -1;
574 static int hf_dcerpc_fragment_overlap = -1;
575 static int hf_dcerpc_fragment_overlap_conflict = -1;
576 static int hf_dcerpc_fragment_multiple_tails = -1;
577 static int hf_dcerpc_fragment_too_long_fragment = -1;
578 static int hf_dcerpc_fragment_error = -1;
579 static int hf_dcerpc_fragment_count = -1;
580 static int hf_dcerpc_reassembled_in = -1;
581 static int hf_dcerpc_reassembled_length = -1;
582 static int hf_dcerpc_unknown_if_id = -1;
583 static int hf_dcerpc_sec_vt_signature = -1;
584 static int hf_dcerpc_sec_vt_command = -1;
585 static int hf_dcerpc_sec_vt_command_cmd = -1;
586 static int hf_dcerpc_sec_vt_command_end = -1;
587 static int hf_dcerpc_sec_vt_command_must = -1;
588 static int hf_dcerpc_sec_vt_command_length = -1;
589 static int hf_dcerpc_sec_vt_bitmask = -1;
590 static int hf_dcerpc_sec_vt_bitmask_sign = -1;
591 static int hf_dcerpc_sec_vt_pcontext_uuid = -1;
592 static int hf_dcerpc_sec_vt_pcontext_ver = -1;
593
594 static const int *sec_vt_command_fields[] = {
595     &hf_dcerpc_sec_vt_command_cmd,
596     &hf_dcerpc_sec_vt_command_end,
597     &hf_dcerpc_sec_vt_command_must,
598     NULL
599 };
600 static int hf_dcerpc_reserved = -1;
601 static int hf_dcerpc_unknown = -1;
602 static int hf_dcerpc_missalign = -1;
603
604 /* Generated from convert_proto_tree_add_text.pl */
605 static int hf_dcerpc_duplicate_ptr = -1;
606 static int hf_dcerpc_encrypted_stub_data = -1;
607 static int hf_dcerpc_decrypted_stub_data = -1;
608 static int hf_dcerpc_payload_stub_data = -1;
609 static int hf_dcerpc_stub_data_with_sec_vt = -1;
610 static int hf_dcerpc_stub_data = -1;
611 static int hf_dcerpc_auth_padding = -1;
612 static int hf_dcerpc_auth_verifier = -1;
613 static int hf_dcerpc_auth_credentials = -1;
614 static int hf_dcerpc_fault_stub_data = -1;
615 static int hf_dcerpc_fragment_data = -1;
616 static int hf_dcerpc_cmd_client_ipv4 = -1;
617 static int hf_dcerpc_cmd_client_ipv6 = -1;
618 static int hf_dcerpc_authentication_verifier = -1;
619
620 static const int *dcerpc_cn_bind_trans_btfn_fields[] = {
621         &hf_dcerpc_cn_bind_trans_btfn_01,
622         &hf_dcerpc_cn_bind_trans_btfn_02,
623         NULL
624 };
625
626 static const int *sec_vt_bitmask_fields[] = {
627     &hf_dcerpc_sec_vt_bitmask_sign,
628     NULL
629 };
630
631 static const value_string sec_vt_command_cmd_vals[] = {
632     {1, "BITMASK_1"},
633     {2, "PCONTEXT"},
634     {3, "HEADER2"},
635     {0, NULL}
636 };
637
638 static gint ett_dcerpc = -1;
639 static gint ett_dcerpc_cn_flags = -1;
640 static gint ett_dcerpc_cn_ctx = -1;
641 static gint ett_dcerpc_cn_iface = -1;
642 static gint ett_dcerpc_cn_trans_syntax = -1;
643 static gint ett_dcerpc_cn_trans_btfn = -1;
644 static gint ett_dcerpc_cn_bind_trans_btfn = -1;
645 static gint ett_dcerpc_cn_rts_flags = -1;
646 static gint ett_dcerpc_cn_rts_command = -1;
647 static gint ett_dcerpc_cn_rts_pdu = -1;
648 static gint ett_dcerpc_drep = -1;
649 static gint ett_dcerpc_dg_flags1 = -1;
650 static gint ett_dcerpc_dg_flags2 = -1;
651 static gint ett_dcerpc_pointer_data = -1;
652 static gint ett_dcerpc_string = -1;
653 static gint ett_dcerpc_fragments = -1;
654 static gint ett_dcerpc_fragment = -1;
655 static gint ett_dcerpc_krb5_auth_verf = -1;
656 static gint ett_dcerpc_verification_trailer = -1;
657 static gint ett_dcerpc_sec_vt_command = -1;
658 static gint ett_dcerpc_sec_vt_bitmask = -1;
659 static gint ett_dcerpc_sec_vt_pcontext = -1;
660 static gint ett_dcerpc_sec_vt_header = -1;
661 static gint ett_dcerpc_complete_stub_data = -1;
662
663 static expert_field ei_dcerpc_fragment_multiple = EI_INIT;
664 static expert_field ei_dcerpc_cn_status = EI_INIT;
665 static expert_field ei_dcerpc_fragment_reassembled = EI_INIT;
666 static expert_field ei_dcerpc_fragment = EI_INIT;
667 static expert_field ei_dcerpc_no_request_found = EI_INIT;
668 static expert_field ei_dcerpc_context_change = EI_INIT;
669 static expert_field ei_dcerpc_cn_ctx_id_no_bind = EI_INIT;
670 static expert_field ei_dcerpc_bind_not_acknowledged = EI_INIT;
671 static expert_field ei_dcerpc_verifier_unavailable = EI_INIT;
672 static expert_field ei_dcerpc_invalid_pdu_authentication_attempt = EI_INIT;
673 /* Generated from convert_proto_tree_add_text.pl */
674 static expert_field ei_dcerpc_long_frame = EI_INIT;
675 static expert_field ei_dcerpc_cn_rts_command = EI_INIT;
676
677 static const guint8 TRAILER_SIGNATURE[] = {0x8a, 0xe3, 0x13, 0x71, 0x02, 0xf4, 0x36, 0x71};
678 static tvbuff_t *tvb_trailer_signature = NULL;
679
680 static GSList *decode_dcerpc_bindings = NULL;
681 /*
682  * To keep track of ctx_id mappings.
683  *
684  * Every time we see a bind call we update this table.
685  * Note that we always specify a SMB FID. For non-SMB transports this
686  * value is 0.
687  */
688 static GHashTable *dcerpc_binds = NULL;
689
690 typedef struct _dcerpc_bind_key {
691     conversation_t *conv;
692     guint16         ctx_id;
693     guint64         transport_salt;
694 } dcerpc_bind_key;
695
696 typedef struct _dcerpc_bind_value {
697     e_guid_t uuid;
698     guint16  ver;
699     e_guid_t transport;
700 } dcerpc_bind_value;
701
702 /* Extra data for DCERPC handling and tracking of context ids */
703 typedef struct _dcerpc_decode_as_data {
704     guint16 dcectxid;             /**< Context ID (DCERPC-specific) */
705     int     dcetransporttype;     /**< Transport type
706                                     * Value -1 means "not a DCERPC packet"
707                                     */
708     guint64 dcetransportsalt;     /**< fid: if transporttype==DCE_CN_TRANSPORT_SMBPIPE */
709 } dcerpc_decode_as_data;
710
711 static dcerpc_decode_as_data*
712 dcerpc_get_decode_data(packet_info* pinfo)
713 {
714     dcerpc_decode_as_data* data = (dcerpc_decode_as_data*)p_get_proto_data(pinfo->pool, pinfo, proto_dcerpc, 0);
715     if (data == NULL)
716     {
717         data = wmem_new0(pinfo->pool, dcerpc_decode_as_data);
718         data->dcetransporttype = -1;
719         p_add_proto_data(pinfo->pool, pinfo, proto_dcerpc, 0, data);
720     }
721
722     return data;
723 }
724
725 /**
726  *  Registers a conversation/UUID binding association, so that
727  *  we can invoke the proper sub-dissector for a given DCERPC
728  *  conversation.
729  *
730  *  @param binding all values needed to create and bind a new conversation
731  *
732  *  @return Pointer to newly-added UUID/conversation binding.
733  */
734 static struct _dcerpc_bind_value *
735 dcerpc_add_conv_to_bind_table(decode_dcerpc_bind_values_t *binding)
736 {
737     dcerpc_bind_value *bind_value;
738     dcerpc_bind_key   *key;
739     conversation_t    *conv;
740
741     conv = find_conversation(
742         0,
743         &binding->addr_a,
744         &binding->addr_b,
745         binding->ptype,
746         binding->port_a,
747         binding->port_b,
748         0);
749
750     if (!conv) {
751         conv = conversation_new(
752             0,
753             &binding->addr_a,
754             &binding->addr_b,
755             binding->ptype,
756             binding->port_a,
757             binding->port_b,
758             0);
759     }
760
761     bind_value = (dcerpc_bind_value *)wmem_alloc(wmem_file_scope(), sizeof (dcerpc_bind_value));
762     bind_value->uuid = binding->uuid;
763     bind_value->ver = binding->ver;
764     /* For now, assume all DCE/RPC we pick from "decode as" is using
765        standard ndr and not ndr64.
766        We should make this selectable from the dialog in the future
767     */
768     bind_value->transport = uuid_data_repr_proto;
769
770     key = (dcerpc_bind_key *)wmem_alloc(wmem_file_scope(), sizeof (dcerpc_bind_key));
771     key->conv = conv;
772     key->ctx_id = binding->ctx_id;
773     key->transport_salt = binding->transport_salt;
774
775     /* add this entry to the bind table */
776     g_hash_table_insert(dcerpc_binds, key, bind_value);
777
778     return bind_value;
779
780 }
781
782 /* inject one of our bindings into the dcerpc binding table */
783 static void
784 decode_dcerpc_inject_binding(gpointer data, gpointer user_data _U_)
785 {
786     dcerpc_add_conv_to_bind_table((decode_dcerpc_bind_values_t *) data);
787 }
788
789 /* inject all of our bindings into the dcerpc binding table */
790 static void
791 decode_dcerpc_inject_bindings(void) {
792     g_slist_foreach(decode_dcerpc_bindings, decode_dcerpc_inject_binding, NULL /* user_data */);
793 }
794
795 /* free a binding */
796 static void
797 decode_dcerpc_binding_free(void *binding_in)
798 {
799     decode_dcerpc_bind_values_t *binding = (decode_dcerpc_bind_values_t *)binding_in;
800
801     free_address(&binding->addr_a);
802     free_address(&binding->addr_b);
803     if (binding->ifname)
804         g_string_free(binding->ifname, TRUE);
805     g_free(binding);
806 }
807
808 static void
809 dcerpc_decode_as_free(gpointer value)
810 {
811     decode_dcerpc_bind_values_t *binding = (decode_dcerpc_bind_values_t *)value;
812     if (binding != NULL)
813         decode_dcerpc_binding_free(binding);
814 }
815
816 /* removes all bindings */
817 void
818 decode_dcerpc_reset_all(void)
819 {
820     decode_dcerpc_bind_values_t *binding;
821
822     while (decode_dcerpc_bindings) {
823         binding = (decode_dcerpc_bind_values_t *)decode_dcerpc_bindings->data;
824
825         decode_dcerpc_binding_free(binding);
826         decode_dcerpc_bindings = g_slist_remove(
827             decode_dcerpc_bindings,
828             decode_dcerpc_bindings->data);
829     }
830 }
831
832
833 void
834 decode_dcerpc_add_show_list(decode_add_show_list_func func, gpointer user_data)
835 {
836     g_slist_foreach(decode_dcerpc_bindings, func, user_data);
837 }
838
839 static void
840 dcerpc_prompt(packet_info *pinfo, gchar* result)
841 {
842     GString *str = g_string_new("Replace binding between:\r\n"),
843             *address_str = g_string_new("");
844     dcerpc_decode_as_data* decode_data = dcerpc_get_decode_data(pinfo);
845
846     switch (pinfo->ptype) {
847     case(PT_TCP):
848         g_string_append(address_str, "Address: ToBeDone TCP port");
849         break;
850     case(PT_UDP):
851         g_string_append(address_str, "Address: ToBeDone UDP port");
852         break;
853     default:
854         g_string_append(address_str, "Address: ToBeDone Unknown port type");
855     }
856
857     g_string_append_printf(str, "%s: %u\r\n", address_str->str, pinfo->srcport);
858     g_string_append(str, "&\r\n");
859     g_string_append_printf(str, "%s: %u\r\n", address_str->str, pinfo->destport);
860     g_string_append_printf(str, "&\r\nContext ID: %u\r\n", decode_data->dcectxid);
861     g_string_append_printf(str, "&\r\nSMB FID: %"G_GINT64_MODIFIER"u\r\n",
862                            dcerpc_get_transport_salt(pinfo));
863     g_string_append(str, "with:\r\n");
864
865     g_strlcpy(result, str->str, MAX_DECODE_AS_PROMPT_LEN);
866     g_string_free(str, TRUE);
867     g_string_free(address_str, TRUE);
868 }
869
870 static gpointer
871 dcerpc_value(packet_info *pinfo)
872 {
873     decode_dcerpc_bind_values_t *binding;
874     dcerpc_decode_as_data* decode_data = dcerpc_get_decode_data(pinfo);
875
876     /* clone binding */
877     binding = g_new(decode_dcerpc_bind_values_t,1);
878     copy_address(&binding->addr_a, &pinfo->src);
879     copy_address(&binding->addr_b, &pinfo->dst);
880     binding->ptype = pinfo->ptype;
881     binding->port_a = pinfo->srcport;
882     binding->port_b = pinfo->destport;
883     binding->ctx_id = decode_data->dcectxid;
884     binding->transport_salt = dcerpc_get_transport_salt(pinfo);
885     binding->ifname = NULL;
886     /*binding->uuid = NULL;*/
887     binding->ver = 0;
888
889     return binding;
890 }
891
892 struct dcerpc_decode_as_populate
893 {
894     decode_as_add_to_list_func add_to_list;
895     gpointer ui_element;
896 };
897
898 static void
899 decode_dcerpc_add_to_list(gpointer key, gpointer value, gpointer user_data)
900 {
901     struct dcerpc_decode_as_populate* populate = (struct dcerpc_decode_as_populate*)user_data;
902
903     /*guid_key *k = key;*/
904     dcerpc_uuid_value *v = (dcerpc_uuid_value *)value;
905
906     if (strcmp(v->name, "(none)"))
907         populate->add_to_list("DCE-RPC", v->name, key, populate->ui_element);
908 }
909
910 static void
911 dcerpc_populate_list(const gchar *table_name _U_, decode_as_add_to_list_func add_to_list, gpointer ui_element)
912 {
913     struct dcerpc_decode_as_populate populate;
914
915     populate.add_to_list = add_to_list;
916     populate.ui_element = ui_element;
917
918     g_hash_table_foreach(dcerpc_uuids, decode_dcerpc_add_to_list, &populate);
919 }
920
921 /* compare two bindings (except the interface related things, e.g. uuid) */
922 static gint
923 decode_dcerpc_binding_cmp(gconstpointer a, gconstpointer b)
924 {
925     const decode_dcerpc_bind_values_t *binding_a = (const decode_dcerpc_bind_values_t *)a;
926     const decode_dcerpc_bind_values_t *binding_b = (const decode_dcerpc_bind_values_t *)b;
927
928
929     /* don't compare uuid and ver! */
930     if (
931         addresses_equal(&binding_a->addr_a, &binding_b->addr_a) &&
932         addresses_equal(&binding_a->addr_b, &binding_b->addr_b) &&
933         binding_a->ptype == binding_b->ptype &&
934         binding_a->port_a == binding_b->port_a &&
935         binding_a->port_b == binding_b->port_b &&
936         binding_a->ctx_id == binding_b->ctx_id &&
937         binding_a->transport_salt == binding_b->transport_salt)
938     {
939         /* equal */
940         return 0;
941     }
942
943     /* unequal */
944     return 1;
945 }
946
947 /* remove a binding (looking the same way as the given one) */
948 static gboolean
949 decode_dcerpc_binding_reset(const char *name _U_, gconstpointer pattern)
950 {
951     const decode_dcerpc_bind_values_t *binding = (const decode_dcerpc_bind_values_t *)pattern;
952     GSList *le;
953     decode_dcerpc_bind_values_t *old_binding;
954
955     /* find the old binding (if it exists) */
956     le = g_slist_find_custom(decode_dcerpc_bindings,
957                                              binding,
958                                              decode_dcerpc_binding_cmp);
959     if (le == NULL)
960         return FALSE;
961
962     old_binding = (decode_dcerpc_bind_values_t *)le->data;
963
964     decode_dcerpc_bindings = g_slist_remove(decode_dcerpc_bindings, le->data);
965
966     free_address(&old_binding->addr_a);
967     free_address(&old_binding->addr_b);
968     g_string_free(old_binding->ifname, TRUE);
969     g_free(old_binding);
970     return FALSE;
971 }
972
973 static gboolean
974 dcerpc_decode_as_change(const char *name, gconstpointer pattern, gpointer handle, gchar* list_name)
975 {
976     decode_dcerpc_bind_values_t *binding = (decode_dcerpc_bind_values_t*)pattern;
977     decode_dcerpc_bind_values_t *stored_binding;
978     guid_key     *key = *((guid_key**)handle);
979
980
981     binding->ifname = g_string_new(list_name);
982     binding->uuid = key->guid;
983     binding->ver = key->ver;
984
985     /* remove a probably existing old binding */
986     decode_dcerpc_binding_reset(name, binding);
987
988     /* clone the new binding and append it to the list */
989     stored_binding = g_new(decode_dcerpc_bind_values_t,1);
990     *stored_binding = *binding;
991     copy_address(&stored_binding->addr_a, &binding->addr_a);
992     copy_address(&stored_binding->addr_b, &binding->addr_b);
993     stored_binding->ifname = g_string_new(binding->ifname->str);
994
995     decode_dcerpc_bindings = g_slist_append (decode_dcerpc_bindings, stored_binding);
996
997     return FALSE;
998 }
999
1000 static const fragment_items dcerpc_frag_items = {
1001     &ett_dcerpc_fragments,
1002     &ett_dcerpc_fragment,
1003
1004     &hf_dcerpc_fragments,
1005     &hf_dcerpc_fragment,
1006     &hf_dcerpc_fragment_overlap,
1007     &hf_dcerpc_fragment_overlap_conflict,
1008     &hf_dcerpc_fragment_multiple_tails,
1009     &hf_dcerpc_fragment_too_long_fragment,
1010     &hf_dcerpc_fragment_error,
1011     &hf_dcerpc_fragment_count,
1012     NULL,
1013     &hf_dcerpc_reassembled_length,
1014     /* Reassembled data field */
1015     NULL,
1016     "fragments"
1017 };
1018
1019 /* list of hooks to be called when init_protocols is done */
1020 GHookList dcerpc_hooks_init_protos;
1021
1022 /* try to desegment big DCE/RPC packets over TCP? */
1023 static gboolean dcerpc_cn_desegment = TRUE;
1024
1025 /* reassemble DCE/RPC fragments */
1026 /* reassembly of cl dcerpc fragments will not work for the case where ONE frame
1027    might contain multiple dcerpc fragments for different PDUs.
1028    this case would be so unusual/weird so if you got captures like that:
1029    too bad
1030
1031    reassembly of co dcerpc fragments will not work for the case where TCP/SMB frames
1032    are coming in out of sequence, but that will hurt in a lot of other places as well.
1033 */
1034 static gboolean dcerpc_reassemble = TRUE;
1035 static reassembly_table dcerpc_co_reassembly_table;
1036 static reassembly_table dcerpc_cl_reassembly_table;
1037
1038 typedef struct _dcerpc_fragment_key {
1039     address src;
1040     address dst;
1041     guint32 id;
1042     e_guid_t act_id;
1043 } dcerpc_fragment_key;
1044
1045 static guint
1046 dcerpc_fragment_hash(gconstpointer k)
1047 {
1048     const dcerpc_fragment_key* key = (const dcerpc_fragment_key*) k;
1049     guint hash_val;
1050
1051     hash_val = 0;
1052
1053     hash_val += key->id;
1054     hash_val += key->act_id.data1;
1055     hash_val += key->act_id.data2 << 16;
1056     hash_val += key->act_id.data3;
1057
1058     return hash_val;
1059 }
1060
1061 static gint
1062 dcerpc_fragment_equal(gconstpointer k1, gconstpointer k2)
1063 {
1064     const dcerpc_fragment_key* key1 = (const dcerpc_fragment_key*) k1;
1065     const dcerpc_fragment_key* key2 = (const dcerpc_fragment_key*) k2;
1066
1067     /*key.id is the first item to compare since item is most
1068       likely to differ between sessions, thus shortcircuiting
1069       the comparison of addresses.
1070     */
1071     return (((key1->id == key2->id)
1072              && (addresses_equal(&key1->src, &key2->src))
1073              && (addresses_equal(&key1->dst, &key2->dst))
1074              && (memcmp (&key1->act_id, &key2->act_id, sizeof (e_guid_t)) == 0))
1075             ? TRUE : FALSE);
1076 }
1077
1078 /* allocate a persistent dcerpc fragment key to insert in the hash */
1079 static void *
1080 dcerpc_fragment_temporary_key(const packet_info *pinfo, const guint32 id,
1081                               const void *data)
1082 {
1083     dcerpc_fragment_key *key = g_slice_new(dcerpc_fragment_key);
1084     const e_dce_dg_common_hdr_t *hdr = (const e_dce_dg_common_hdr_t *)data;
1085
1086     copy_address_shallow(&key->src, &pinfo->src);
1087     copy_address_shallow(&key->dst, &pinfo->dst);
1088     key->id = id;
1089     key->act_id = hdr->act_id;
1090
1091     return key;
1092 }
1093
1094 /* allocate a persistent dcerpc fragment key to insert in the hash */
1095 static void *
1096 dcerpc_fragment_persistent_key(const packet_info *pinfo, const guint32 id,
1097                                const void *data)
1098 {
1099     dcerpc_fragment_key *key = g_slice_new(dcerpc_fragment_key);
1100     const e_dce_dg_common_hdr_t *hdr = (const e_dce_dg_common_hdr_t *)data;
1101
1102     copy_address(&key->src, &pinfo->src);
1103     copy_address(&key->dst, &pinfo->dst);
1104     key->id = id;
1105     key->act_id = hdr->act_id;
1106
1107     return key;
1108 }
1109
1110 static void
1111 dcerpc_fragment_free_temporary_key(gpointer ptr)
1112 {
1113     dcerpc_fragment_key *key = (dcerpc_fragment_key *)ptr;
1114
1115     if (key)
1116         g_slice_free(dcerpc_fragment_key, key);
1117 }
1118
1119 static void
1120 dcerpc_fragment_free_persistent_key(gpointer ptr)
1121 {
1122     dcerpc_fragment_key *key = (dcerpc_fragment_key *)ptr;
1123
1124     if (key) {
1125         /*
1126          * Free up the copies of the addresses from the old key.
1127          */
1128         free_address(&key->src);
1129         free_address(&key->dst);
1130
1131         g_slice_free(dcerpc_fragment_key, key);
1132     }
1133 }
1134
1135 static const reassembly_table_functions dcerpc_cl_reassembly_table_functions = {
1136     dcerpc_fragment_hash,
1137     dcerpc_fragment_equal,
1138     dcerpc_fragment_temporary_key,
1139     dcerpc_fragment_persistent_key,
1140     dcerpc_fragment_free_temporary_key,
1141     dcerpc_fragment_free_persistent_key
1142 };
1143
1144 static void
1145 dcerpc_reassemble_init(void)
1146 {
1147     /*
1148      * XXX - addresses_ports_reassembly_table_functions?
1149      * Or can a single connection-oriented DCE RPC session persist
1150      * over multiple transport layer connections?
1151      */
1152     reassembly_table_init(&dcerpc_co_reassembly_table,
1153                           &addresses_reassembly_table_functions);
1154     reassembly_table_init(&dcerpc_cl_reassembly_table,
1155                           &dcerpc_cl_reassembly_table_functions);
1156 }
1157
1158 /*
1159  * Authentication subdissectors.  Used to dissect authentication blobs in
1160  * DCERPC binds, requests and responses.
1161  */
1162
1163 typedef struct _dcerpc_auth_subdissector {
1164     guint8 auth_level;
1165     guint8 auth_type;
1166     dcerpc_auth_subdissector_fns auth_fns;
1167 } dcerpc_auth_subdissector;
1168
1169 static GSList *dcerpc_auth_subdissector_list;
1170
1171 static dcerpc_auth_subdissector_fns *get_auth_subdissector_fns(
1172     guint8 auth_level, guint8 auth_type)
1173 {
1174     gpointer data;
1175     int      i;
1176
1177     for (i = 0; (data = g_slist_nth_data(dcerpc_auth_subdissector_list, i)); i++) {
1178         dcerpc_auth_subdissector *asd = (dcerpc_auth_subdissector *)data;
1179
1180         if ((asd->auth_level == auth_level) &&
1181             (asd->auth_type == auth_type))
1182             return &asd->auth_fns;
1183     }
1184
1185     return NULL;
1186 }
1187
1188 void register_dcerpc_auth_subdissector(guint8 auth_level, guint8 auth_type,
1189                                        dcerpc_auth_subdissector_fns *fns)
1190 {
1191     dcerpc_auth_subdissector *d;
1192
1193     if (get_auth_subdissector_fns(auth_level, auth_type))
1194         return;
1195
1196     d = (dcerpc_auth_subdissector *)g_malloc(sizeof(dcerpc_auth_subdissector));
1197
1198     d->auth_level = auth_level;
1199     d->auth_type = auth_type;
1200     memcpy(&d->auth_fns, fns, sizeof(dcerpc_auth_subdissector_fns));
1201
1202     dcerpc_auth_subdissector_list = g_slist_append(dcerpc_auth_subdissector_list, d);
1203 }
1204
1205 /* Hand off verifier data to a registered dissector */
1206
1207 static void dissect_auth_verf(tvbuff_t *auth_tvb, packet_info *pinfo,
1208                               proto_tree *tree,
1209                               dcerpc_auth_subdissector_fns *auth_fns,
1210                               e_dce_cn_common_hdr_t *hdr,
1211                               dcerpc_auth_info *auth_info)
1212 {
1213     dcerpc_dissect_fnct_t *fn = NULL;
1214     /* XXX - "stub" a fake DCERPC INFO STRUCTURE
1215        If a dcerpc_info is really needed, update
1216        the call stacks to include it
1217      */
1218     FAKE_DCERPC_INFO_STRUCTURE
1219
1220     switch (hdr->ptype) {
1221     case PDU_BIND:
1222     case PDU_ALTER:
1223         fn = auth_fns->bind_fn;
1224         break;
1225     case PDU_BIND_ACK:
1226     case PDU_ALTER_ACK:
1227         fn = auth_fns->bind_ack_fn;
1228         break;
1229     case PDU_AUTH3:
1230         fn = auth_fns->auth3_fn;
1231         break;
1232     case PDU_REQ:
1233     case PDU_CO_CANCEL:
1234     case PDU_ORPHANED:
1235         fn = auth_fns->req_verf_fn;
1236         break;
1237     case PDU_RESP:
1238     case PDU_FAULT:
1239         fn = auth_fns->resp_verf_fn;
1240         break;
1241
1242     default:
1243         /* Don't know how to handle authentication data in this
1244            pdu type. */
1245         proto_tree_add_expert_format(tree, pinfo, &ei_dcerpc_invalid_pdu_authentication_attempt,
1246                                      auth_tvb, 0, 0,
1247                                      "Don't know how to dissect authentication data for %s pdu type",
1248                                      val_to_str(hdr->ptype, pckt_vals, "Unknown (%u)"));
1249         return;
1250         break;
1251     }
1252
1253     if (fn)
1254         fn(auth_tvb, 0, pinfo, tree, &di, hdr->drep);
1255     else {
1256         proto_tree_add_expert_format(tree, pinfo, &ei_dcerpc_verifier_unavailable,
1257                                      auth_tvb, 0, hdr->auth_len,
1258                                      "%s Verifier unavailable",
1259                                      val_to_str(auth_info->auth_type,
1260                                                 authn_protocol_vals,
1261                                                 "Unknown (%u)"));
1262     }
1263 }
1264
1265 static proto_item*
1266 proto_tree_add_dcerpc_drep(proto_tree *tree, tvbuff_t *tvb, int offset, guint8 drep[], int drep_len)
1267 {
1268     const guint8 byteorder = drep[0] >> 4;
1269     const guint8 character = drep[0] & 0x0f;
1270     const guint8 fp = drep[1];
1271     proto_item *ti = proto_tree_add_bytes(tree, hf_dcerpc_drep, tvb, offset, drep_len, drep);
1272     proto_tree *tr = proto_item_add_subtree(ti, ett_dcerpc_drep);
1273
1274     proto_tree_add_uint(tr, hf_dcerpc_drep_byteorder, tvb, offset, 1, byteorder);
1275     proto_tree_add_uint(tr, hf_dcerpc_drep_character, tvb, offset, 1, character);
1276     proto_tree_add_uint(tr, hf_dcerpc_drep_fp, tvb, offset+1, 1, fp);
1277
1278     proto_item_append_text(ti, " (Order: %s, Char: %s, Float: %s)",
1279                            val_to_str(byteorder, drep_byteorder_vals, "Unknown (%u)"),
1280                            val_to_str(character, drep_character_vals, "Unknown (%u)"),
1281                            val_to_str(fp, drep_fp_vals, "Unknown (%u)"));
1282     return ti;
1283 }
1284
1285 /* Hand off payload data to a registered dissector */
1286
1287 static tvbuff_t *decode_encrypted_data(tvbuff_t *data_tvb,
1288                                        tvbuff_t *auth_tvb,
1289                                        packet_info *pinfo,
1290                                        dcerpc_auth_subdissector_fns *auth_fns,
1291                                        gboolean is_request,
1292                                        dcerpc_auth_info *auth_info)
1293 {
1294     dcerpc_decode_data_fnct_t *fn;
1295
1296     if (is_request)
1297         fn = auth_fns->req_data_fn;
1298     else
1299         fn = auth_fns->resp_data_fn;
1300
1301     if (fn)
1302         return fn(data_tvb, auth_tvb, 0, pinfo, auth_info);
1303
1304     return NULL;
1305 }
1306
1307 typedef struct _dcerpc_dissector_data
1308 {
1309     dcerpc_uuid_value *sub_proto;
1310     dcerpc_info *info;
1311     gboolean decrypted;
1312     dcerpc_auth_info *auth_info;
1313     guint8 *drep;
1314     proto_tree *dcerpc_tree;
1315 } dcerpc_dissector_data_t;
1316
1317 /*
1318  * Subdissectors
1319  */
1320
1321 dissector_table_t   uuid_dissector_table;
1322
1323 /* the registered subdissectors */
1324 GHashTable *dcerpc_uuids = NULL;
1325
1326 static gint
1327 dcerpc_uuid_equal(gconstpointer k1, gconstpointer k2)
1328 {
1329     const guid_key *key1 = (const guid_key *)k1;
1330     const guid_key *key2 = (const guid_key *)k2;
1331     return ((memcmp(&key1->guid, &key2->guid, sizeof (e_guid_t)) == 0)
1332             && (key1->ver == key2->ver));
1333 }
1334
1335 static guint
1336 dcerpc_uuid_hash(gconstpointer k)
1337 {
1338     const guid_key *key = (const guid_key *)k;
1339     /* This isn't perfect, but the Data1 part of these is almost always
1340        unique. */
1341     return key->guid.data1;
1342 }
1343
1344
1345 static int
1346 dissect_verification_trailer(packet_info *pinfo, tvbuff_t *tvb, int stub_offset,
1347                              proto_tree *parent_tree, int *signature_offset);
1348
1349 static void
1350 show_stub_data(packet_info *pinfo, tvbuff_t *tvb, gint offset, proto_tree *dcerpc_tree,
1351                dcerpc_auth_info *auth_info, gboolean is_encrypted)
1352 {
1353     int   length, plain_length, auth_pad_len;
1354     guint auth_pad_offset;
1355
1356     /*
1357      * We don't show stub data unless we have some in the tvbuff;
1358      * however, in the protocol tree, we show, as the number of
1359      * bytes, the reported number of bytes, not the number of bytes
1360      * that happen to be in the tvbuff.
1361      */
1362     if (tvb_reported_length_remaining(tvb, offset) > 0) {
1363         auth_pad_len = auth_info?auth_info->auth_pad_len:0;
1364         length = tvb_reported_length_remaining(tvb, offset);
1365
1366         /* if auth_pad_len is larger than length then we ignore auth_pad_len totally */
1367         plain_length = length - auth_pad_len;
1368         if (plain_length < 1) {
1369             plain_length = length;
1370             auth_pad_len = 0;
1371         }
1372         auth_pad_offset = offset + plain_length;
1373
1374         if ((auth_info != NULL) &&
1375             (auth_info->auth_level == DCE_C_AUTHN_LEVEL_PKT_PRIVACY)) {
1376             if (is_encrypted) {
1377                 proto_tree_add_item(dcerpc_tree, hf_dcerpc_encrypted_stub_data, tvb, offset, length, ENC_NA);
1378                 /* is the padding is still inside the encrypted blob, don't display it explicit */
1379                 auth_pad_len = 0;
1380             } else {
1381                 proto_tree_add_item(dcerpc_tree, hf_dcerpc_decrypted_stub_data, tvb, offset, plain_length, ENC_NA);
1382                 dissect_verification_trailer(pinfo, tvb, offset, dcerpc_tree, NULL);
1383             }
1384         } else {
1385             proto_tree_add_item(dcerpc_tree, hf_dcerpc_stub_data, tvb, offset, plain_length, ENC_NA);
1386             dissect_verification_trailer(pinfo, tvb, offset, dcerpc_tree, NULL);
1387         }
1388         /* If there is auth padding at the end of the stub, display it */
1389         if (auth_pad_len != 0) {
1390             proto_tree_add_item(dcerpc_tree, hf_dcerpc_auth_padding, tvb, auth_pad_offset, auth_pad_len, ENC_NA);
1391         }
1392     }
1393 }
1394
1395 static int
1396 dissect_dcerpc_guid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1397 {
1398     dcerpc_dissector_data_t* dissector_data = (dcerpc_dissector_data_t*)data;
1399     const gchar          *name     = NULL;
1400     dcerpc_sub_dissector *proc;
1401     int (*volatile sub_dissect)(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) = NULL;
1402     proto_item           *pi, *sub_item;
1403     proto_tree           *sub_tree;
1404     volatile guint        length;
1405     guint                 reported_length;
1406     volatile gint         offset   = 0;
1407     tvbuff_t *volatile    stub_tvb;
1408     tvbuff_t *volatile    payload_tvb = NULL;
1409     volatile guint        auth_pad_len;
1410     volatile int          auth_pad_offset;
1411     const char *volatile  saved_proto;
1412
1413     for (proc = dissector_data->sub_proto->procs; proc->name; proc++) {
1414         if (proc->num == dissector_data->info->call_data->opnum) {
1415             name = proc->name;
1416             break;
1417         }
1418     }
1419
1420     col_set_str(pinfo->cinfo, COL_PROTOCOL, dissector_data->sub_proto->name);
1421
1422     if (!name)
1423         col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown operation %u %s",
1424                      dissector_data->info->call_data->opnum,
1425                      (dissector_data->info->ptype == PDU_REQ) ? "request" : "response");
1426     else
1427         col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
1428                      name, (dissector_data->info->ptype == PDU_REQ) ? "request" : "response");
1429
1430     sub_dissect = (dissector_data->info->ptype == PDU_REQ) ?
1431         proc->dissect_rqst : proc->dissect_resp;
1432
1433     sub_item = proto_tree_add_item(tree, dissector_data->sub_proto->proto_id,
1434                                        tvb,//(decrypted_tvb != NULL)?decrypted_tvb:tvb,
1435                                        0, -1, ENC_NA);
1436     sub_tree = proto_item_add_subtree(sub_item, dissector_data->sub_proto->ett);
1437     if (!name)
1438         proto_item_append_text(sub_item, ", unknown operation %u",
1439                                 dissector_data->info->call_data->opnum);
1440     else
1441         proto_item_append_text(sub_item, ", %s", name);
1442
1443     if (tree) {
1444         /*
1445          * Put the operation number into the tree along with
1446          * the operation's name.
1447          */
1448         if (dissector_data->sub_proto->opnum_hf != -1)
1449             proto_tree_add_uint_format(sub_tree, dissector_data->sub_proto->opnum_hf,
1450                                        tvb, 0, 0, dissector_data->info->call_data->opnum,
1451                                        "Operation: %s (%u)",
1452                                        name ? name : "Unknown operation",
1453                                        dissector_data->info->call_data->opnum);
1454         else
1455             proto_tree_add_uint_format_value(sub_tree, hf_dcerpc_op, tvb,
1456                                        0, 0, dissector_data->info->call_data->opnum,
1457                                        "%s (%u)",
1458                                        name ? name : "Unknown operation",
1459                                        dissector_data->info->call_data->opnum);
1460
1461         if ((dissector_data->info->ptype == PDU_REQ) && (dissector_data->info->call_data->rep_frame != 0)) {
1462             pi = proto_tree_add_uint(sub_tree, hf_dcerpc_response_in,
1463                                      tvb, 0, 0, dissector_data->info->call_data->rep_frame);
1464             PROTO_ITEM_SET_GENERATED(pi);
1465         }
1466         if ((dissector_data->info->ptype == PDU_RESP) && (dissector_data->info->call_data->req_frame != 0)) {
1467             pi = proto_tree_add_uint(sub_tree, hf_dcerpc_request_in,
1468                                      tvb, 0, 0, dissector_data->info->call_data->req_frame);
1469             PROTO_ITEM_SET_GENERATED(pi);
1470         }
1471     } /* tree */
1472
1473     if (!dissector_data->decrypted || (sub_dissect == NULL))
1474     {
1475         show_stub_data(pinfo, tvb, 0, sub_tree, dissector_data->auth_info, !dissector_data->decrypted);
1476         return tvb_captured_length(tvb);
1477     }
1478
1479     /* Either there was no encryption or we successfully decrypted
1480        the encrypted payload. */
1481
1482     /* We have a subdissector - call it. */
1483     saved_proto          = pinfo->current_proto;
1484     pinfo->current_proto = dissector_data->sub_proto->name;
1485
1486     init_ndr_pointer_list(dissector_data->info);
1487
1488     length = tvb_captured_length(tvb);
1489     reported_length = tvb_reported_length(tvb);
1490
1491     /*
1492      * Remove the authentication padding from the stub data.
1493      */
1494     if ((dissector_data->auth_info != NULL) && (dissector_data->auth_info->auth_pad_len != 0)) {
1495         if (reported_length >= dissector_data->auth_info->auth_pad_len) {
1496             /*
1497              * OK, the padding length isn't so big that it
1498              * exceeds the stub length.  Trim the reported
1499              * length of the tvbuff.
1500              */
1501             reported_length -= dissector_data->auth_info->auth_pad_len;
1502
1503             /*
1504              * If that exceeds the actual amount of data in
1505              * the tvbuff (which means we have at least one
1506              * byte of authentication padding in the tvbuff),
1507              * trim the actual amount.
1508              */
1509             if (length > reported_length)
1510                 length = reported_length;
1511
1512             stub_tvb = tvb_new_subset(tvb, 0, length, reported_length);
1513             auth_pad_len = dissector_data->auth_info->auth_pad_len;
1514             auth_pad_offset = reported_length;
1515         } else {
1516             /*
1517              * The padding length exceeds the stub length.
1518              * Don't bother dissecting the stub, trim the padding
1519              * length to what's in the stub data, and show the
1520              * entire stub as authentication padding.
1521              */
1522             stub_tvb = NULL;
1523             auth_pad_len = reported_length;
1524             auth_pad_offset = 0;
1525             length = 0;
1526         }
1527     } else {
1528         /*
1529          * No authentication padding.
1530          */
1531         stub_tvb = tvb;
1532         auth_pad_len = 0;
1533         auth_pad_offset = 0;
1534     }
1535
1536     if (sub_item) {
1537         proto_item_set_len(sub_item, length);
1538     }
1539
1540     if (stub_tvb != NULL) {
1541         /*
1542          * Catch all exceptions other than BoundsError, so that even
1543          * if the stub data is bad, we still show the authentication
1544          * padding, if any.
1545          *
1546          * If we get BoundsError, it means the frame was cut short
1547          * by a snapshot length, so there's nothing more to
1548          * dissect; just re-throw that exception.
1549          */
1550         TRY {
1551             proto_tree *stub_tree = NULL;
1552             int remaining;
1553             int trailer_start_offset = -1;
1554             int trailer_end_offset = -1;
1555
1556             stub_tree = proto_tree_add_subtree_format(dissector_data->dcerpc_tree,
1557                                 stub_tvb, 0, length,
1558                                 ett_dcerpc_complete_stub_data, NULL,
1559                                 "Complete stub data (%d byte%s)", length,
1560                                 plurality(length, "", "s"));
1561             trailer_end_offset = dissect_verification_trailer(pinfo,
1562                                                     stub_tvb, 0,
1563                                                     stub_tree,
1564                                                     &trailer_start_offset);
1565
1566             if (trailer_end_offset != -1) {
1567                 remaining = tvb_captured_length_remaining(stub_tvb,
1568                                                     trailer_start_offset);
1569                 length -= remaining;
1570
1571                 if (sub_item) {
1572                         proto_item_set_len(sub_item, length);
1573                 }
1574             } else {
1575                 proto_item *payload_item;
1576
1577                 payload_item = proto_tree_add_item(stub_tree,
1578                                     hf_dcerpc_payload_stub_data,
1579                                     stub_tvb, 0, length, ENC_NA);
1580                 proto_item_append_text(payload_item, " (%d byte%s)",
1581                                         length, plurality(length, "", "s"));
1582             }
1583
1584             payload_tvb = tvb_new_subset(stub_tvb, 0, length, length);
1585             offset = sub_dissect(payload_tvb, 0, pinfo, sub_tree,
1586                             dissector_data->info, dissector_data->drep);
1587
1588             /* If we have a subdissector and it didn't dissect all
1589                 data in the tvb, make a note of it. */
1590             remaining = tvb_reported_length_remaining(stub_tvb, offset);
1591
1592             if (trailer_end_offset != -1) {
1593                 if (offset > trailer_start_offset) {
1594                     remaining = offset - trailer_start_offset;
1595                     proto_tree_add_item(sub_tree, hf_dcerpc_stub_data_with_sec_vt,
1596                                         stub_tvb, trailer_start_offset, remaining, ENC_NA);
1597                     col_append_fstr(pinfo->cinfo, COL_INFO,
1598                                         "[Payload with Verification Trailer (%d byte%s)]",
1599                                     remaining,
1600                                     plurality(remaining, "", "s"));
1601                     remaining = 0;
1602                 } else {
1603                     remaining = trailer_start_offset - offset;
1604                 }
1605             }
1606
1607             if (remaining > 0) {
1608                 proto_tree_add_expert(sub_tree, pinfo, &ei_dcerpc_long_frame, stub_tvb, offset, remaining);
1609                 col_append_fstr(pinfo->cinfo, COL_INFO,
1610                                     "[Long frame (%d byte%s)]",
1611                                     remaining,
1612                                     plurality(remaining, "", "s"));
1613             }
1614         } CATCH_NONFATAL_ERRORS {
1615             /*
1616              * Somebody threw an exception that means that there
1617              * was a problem dissecting the payload; that means
1618              * that a dissector was found, so we don't need to
1619              * dissect the payload as data or update the protocol
1620              * or info columns.
1621              *
1622              * Just show the exception and then drive on to show
1623              * the authentication padding.
1624              */
1625             show_exception(stub_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
1626         } ENDTRY;
1627     }
1628
1629     /* If there is auth padding at the end of the stub, display it */
1630     if (auth_pad_len != 0) {
1631         proto_tree_add_item(sub_tree, hf_dcerpc_auth_padding, tvb, auth_pad_offset, auth_pad_len, ENC_NA);
1632     }
1633
1634     pinfo->current_proto = saved_proto;
1635
1636     return tvb_captured_length(tvb);
1637 }
1638
1639 void
1640 dcerpc_init_uuid(int proto, int ett, e_guid_t *uuid, guint16 ver,
1641                  dcerpc_sub_dissector *procs, int opnum_hf)
1642 {
1643     guid_key   *key         = (guid_key *)g_malloc(sizeof (*key));
1644     dcerpc_uuid_value *value       = (dcerpc_uuid_value *)g_malloc(sizeof (*value));
1645     header_field_info *hf_info;
1646     module_t          *samr_module;
1647     const char        *filter_name = proto_get_protocol_filter_name(proto);
1648     dissector_handle_t guid_handle;
1649
1650     key->guid = *uuid;
1651     key->ver = ver;
1652
1653     value->proto    = find_protocol_by_id(proto);
1654     value->proto_id = proto;
1655     value->ett      = ett;
1656     value->name     = proto_get_protocol_short_name(value->proto);
1657     value->procs    = procs;
1658     value->opnum_hf = opnum_hf;
1659
1660     g_hash_table_insert(dcerpc_uuids, key, value);
1661
1662     hf_info = proto_registrar_get_nth(opnum_hf);
1663     hf_info->strings = value_string_from_subdissectors(procs);
1664
1665     /* Register the GUID with the dissector table */
1666     guid_handle = create_dissector_handle( dissect_dcerpc_guid, proto);
1667     dissector_add_guid( "dcerpc.uuid", key, guid_handle );
1668
1669     /* add this GUID to the global name resolving */
1670     guids_add_uuid(uuid, proto_get_protocol_short_name(value->proto));
1671
1672     /* Register the samr.nt_password preference as obsolete */
1673     /* This should be in packet-dcerpc-samr.c */
1674     if (strcmp(filter_name, "samr") == 0) {
1675         samr_module = prefs_register_protocol(proto, NULL);
1676         prefs_register_obsolete_preference(samr_module, "nt_password");
1677     }
1678 }
1679
1680 /* Function to find the name of a registered protocol
1681  * or NULL if the protocol/version is not known to wireshark.
1682  */
1683 const char *
1684 dcerpc_get_proto_name(e_guid_t *uuid, guint16 ver)
1685 {
1686     dissector_handle_t handle;
1687     guid_key    key;
1688
1689     key.guid = *uuid;
1690     key.ver = ver;
1691
1692     handle = dissector_get_guid_handle(uuid_dissector_table, &key);
1693     if (handle == NULL) {
1694         return NULL;
1695     }
1696
1697     return dissector_handle_get_short_name(handle);
1698 }
1699
1700 /* Function to find the opnum hf-field of a registered protocol
1701  * or -1 if the protocol/version is not known to wireshark.
1702  */
1703 int
1704 dcerpc_get_proto_hf_opnum(e_guid_t *uuid, guint16 ver)
1705 {
1706     guid_key    key;
1707     dcerpc_uuid_value *sub_proto;
1708
1709     key.guid = *uuid;
1710     key.ver = ver;
1711     if (!(sub_proto = (dcerpc_uuid_value *)g_hash_table_lookup(dcerpc_uuids, &key))) {
1712         return -1;
1713     }
1714     return sub_proto->opnum_hf;
1715 }
1716
1717 /* Create a value_string consisting of DCERPC opnum and name from a
1718    subdissector array. */
1719
1720 value_string *value_string_from_subdissectors(dcerpc_sub_dissector *sd)
1721 {
1722     value_string *vs     = NULL;
1723     int           i;
1724     int           num_sd = 0;
1725
1726 again:
1727     for (i = 0; sd[i].name; i++) {
1728         if (vs) {
1729             vs[i].value = sd[i].num;
1730             vs[i].strptr = sd[i].name;
1731         } else
1732             num_sd++;
1733     }
1734
1735     if (!vs) {
1736         vs = (value_string *)wmem_alloc(wmem_epan_scope(), (num_sd + 1) * sizeof(value_string));
1737         goto again;
1738     }
1739
1740     vs[num_sd].value = 0;
1741     vs[num_sd].strptr = NULL;
1742
1743     return vs;
1744 }
1745
1746 /* Function to find the subdissector table of a registered protocol
1747  * or NULL if the protocol/version is not known to wireshark.
1748  */
1749 dcerpc_sub_dissector *
1750 dcerpc_get_proto_sub_dissector(e_guid_t *uuid, guint16 ver)
1751 {
1752     guid_key    key;
1753     dcerpc_uuid_value *sub_proto;
1754
1755     key.guid = *uuid;
1756     key.ver = ver;
1757     if (!(sub_proto = (dcerpc_uuid_value *)g_hash_table_lookup(dcerpc_uuids, &key))) {
1758         return NULL;
1759     }
1760     return sub_proto->procs;
1761 }
1762
1763
1764
1765 static gint
1766 dcerpc_bind_equal(gconstpointer k1, gconstpointer k2)
1767 {
1768     const dcerpc_bind_key *key1 = (const dcerpc_bind_key *)k1;
1769     const dcerpc_bind_key *key2 = (const dcerpc_bind_key *)k2;
1770     return ((key1->conv == key2->conv)
1771             && (key1->ctx_id == key2->ctx_id)
1772             && (key1->transport_salt == key2->transport_salt));
1773 }
1774
1775 static guint
1776 dcerpc_bind_hash(gconstpointer k)
1777 {
1778     const dcerpc_bind_key *key = (const dcerpc_bind_key *)k;
1779     guint hash;
1780
1781     hash = GPOINTER_TO_UINT(key->conv);
1782     hash += key->ctx_id;
1783     /* sizeof(guint) might be smaller than sizeof(guint64) */
1784     hash += (guint)key->transport_salt;
1785     hash += (guint)(key->transport_salt << sizeof(guint));
1786
1787     return hash;
1788 }
1789
1790 /*
1791  * To keep track of callid mappings.  Should really use some generic
1792  * conversation support instead.
1793  */
1794 static GHashTable *dcerpc_cn_calls = NULL;
1795 static GHashTable *dcerpc_dg_calls = NULL;
1796
1797 typedef struct _dcerpc_cn_call_key {
1798     conversation_t *conv;
1799     guint32 call_id;
1800     guint64 transport_salt;
1801 } dcerpc_cn_call_key;
1802
1803 typedef struct _dcerpc_dg_call_key {
1804     conversation_t *conv;
1805     guint32         seqnum;
1806     e_guid_t        act_id ;
1807 } dcerpc_dg_call_key;
1808
1809
1810 static gint
1811 dcerpc_cn_call_equal(gconstpointer k1, gconstpointer k2)
1812 {
1813     const dcerpc_cn_call_key *key1 = (const dcerpc_cn_call_key *)k1;
1814     const dcerpc_cn_call_key *key2 = (const dcerpc_cn_call_key *)k2;
1815     return ((key1->conv == key2->conv)
1816             && (key1->call_id == key2->call_id)
1817             && (key1->transport_salt == key2->transport_salt));
1818 }
1819
1820 static gint
1821 dcerpc_dg_call_equal(gconstpointer k1, gconstpointer k2)
1822 {
1823     const dcerpc_dg_call_key *key1 = (const dcerpc_dg_call_key *)k1;
1824     const dcerpc_dg_call_key *key2 = (const dcerpc_dg_call_key *)k2;
1825     return ((key1->conv == key2->conv)
1826             && (key1->seqnum == key2->seqnum)
1827             && ((memcmp(&key1->act_id, &key2->act_id, sizeof (e_guid_t)) == 0)));
1828 }
1829
1830 static guint
1831 dcerpc_cn_call_hash(gconstpointer k)
1832 {
1833     const dcerpc_cn_call_key *key = (const dcerpc_cn_call_key *)k;
1834     guint hash;
1835
1836     hash = GPOINTER_TO_UINT(key->conv);
1837     hash += key->call_id;
1838     /* sizeof(guint) might be smaller than sizeof(guint64) */
1839     hash += (guint)key->transport_salt;
1840     hash += (guint)(key->transport_salt << sizeof(guint));
1841
1842     return hash;
1843 }
1844
1845 static guint
1846 dcerpc_dg_call_hash(gconstpointer k)
1847 {
1848     const dcerpc_dg_call_key *key = (const dcerpc_dg_call_key *)k;
1849     return (GPOINTER_TO_UINT(key->conv) + key->seqnum + key->act_id.data1
1850             + (key->act_id.data2 << 16)    + key->act_id.data3
1851             + (key->act_id.data4[0] << 24) + (key->act_id.data4[1] << 16)
1852             + (key->act_id.data4[2] << 8)  + (key->act_id.data4[3] << 0)
1853             + (key->act_id.data4[4] << 24) + (key->act_id.data4[5] << 16)
1854             + (key->act_id.data4[6] << 8)  + (key->act_id.data4[7] << 0));
1855 }
1856
1857 /* to keep track of matched calls/responses
1858    this one uses the same value struct as calls, but the key is the frame id
1859    and call id; there can be more than one call in a frame.
1860
1861    XXX - why not just use the same keys as are used for calls?
1862 */
1863
1864 static GHashTable *dcerpc_matched = NULL;
1865
1866 typedef struct _dcerpc_matched_key {
1867     guint32 frame;
1868     guint32 call_id;
1869 } dcerpc_matched_key;
1870
1871 static gint
1872 dcerpc_matched_equal(gconstpointer k1, gconstpointer k2)
1873 {
1874     const dcerpc_matched_key *key1 = (const dcerpc_matched_key *)k1;
1875     const dcerpc_matched_key *key2 = (const dcerpc_matched_key *)k2;
1876     return ((key1->frame == key2->frame)
1877             && (key1->call_id == key2->call_id));
1878 }
1879
1880 static guint
1881 dcerpc_matched_hash(gconstpointer k)
1882 {
1883     const dcerpc_matched_key *key = (const dcerpc_matched_key *)k;
1884     return key->frame;
1885 }
1886
1887 static gboolean
1888 uuid_equal(e_guid_t *uuid1, e_guid_t *uuid2)
1889 {
1890     if( (uuid1->data1    != uuid2->data1)
1891       ||(uuid1->data2    != uuid2->data2)
1892       ||(uuid1->data3    != uuid2->data3)
1893       ||(uuid1->data4[0] != uuid2->data4[0])
1894       ||(uuid1->data4[1] != uuid2->data4[1])
1895       ||(uuid1->data4[2] != uuid2->data4[2])
1896       ||(uuid1->data4[3] != uuid2->data4[3])
1897       ||(uuid1->data4[4] != uuid2->data4[4])
1898       ||(uuid1->data4[5] != uuid2->data4[5])
1899       ||(uuid1->data4[6] != uuid2->data4[6])
1900       ||(uuid1->data4[7] != uuid2->data4[7]) ){
1901         return FALSE;
1902     }
1903     return TRUE;
1904 }
1905
1906 static void
1907 dcerpcstat_init(struct register_srt* srt, GArray* srt_array, srt_gui_init_cb gui_callback, void* gui_data)
1908 {
1909     dcerpcstat_tap_data_t* tap_data = (dcerpcstat_tap_data_t*)get_srt_table_param_data(srt);
1910     srt_stat_table *dcerpc_srt_table;
1911     int i, hf_opnum;
1912     dcerpc_sub_dissector *procs;
1913
1914     DISSECTOR_ASSERT(tap_data);
1915
1916     hf_opnum = dcerpc_get_proto_hf_opnum(&tap_data->uuid, tap_data->ver);
1917     procs    = dcerpc_get_proto_sub_dissector(&tap_data->uuid, tap_data->ver);
1918
1919     if(hf_opnum != -1){
1920         dcerpc_srt_table = init_srt_table(tap_data->prog, NULL, srt_array, tap_data->num_procedures, NULL, proto_registrar_get_nth(hf_opnum)->abbrev, gui_callback, gui_data, tap_data);
1921     } else {
1922         dcerpc_srt_table = init_srt_table(tap_data->prog, NULL, srt_array, tap_data->num_procedures, NULL, NULL, gui_callback, gui_data, tap_data);
1923     }
1924
1925     for(i=0;i<tap_data->num_procedures;i++){
1926         int j;
1927         const char *proc_name;
1928
1929         proc_name = "unknown";
1930         for(j=0;procs[j].name;j++)
1931         {
1932             if (procs[j].num == i)
1933             {
1934                 proc_name = procs[j].name;
1935             }
1936         }
1937
1938         init_srt_table_row(dcerpc_srt_table, i, proc_name);
1939     }
1940 }
1941
1942 static int
1943 dcerpcstat_packet(void *pss, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prv)
1944 {
1945     guint i = 0;
1946     srt_stat_table *dcerpc_srt_table;
1947     srt_data_t *data = (srt_data_t *)pss;
1948     const dcerpc_info *ri = (const dcerpc_info *)prv;
1949     dcerpcstat_tap_data_t* tap_data;
1950
1951     dcerpc_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
1952     tap_data = (dcerpcstat_tap_data_t*)dcerpc_srt_table->table_specific_data;
1953
1954     if(!ri->call_data){
1955         return 0;
1956     }
1957     if(!ri->call_data->req_frame){
1958         /* we have not seen the request so we don't know the delta*/
1959         return 0;
1960     }
1961     if(ri->call_data->opnum >= tap_data->num_procedures){
1962         /* don't handle this since it's outside of known table */
1963         return 0;
1964     }
1965
1966     /* we are only interested in reply packets */
1967     if(ri->ptype != PDU_RESP){
1968         return 0;
1969     }
1970
1971     /* we are only interested in certain program/versions */
1972     if( (!uuid_equal( (&ri->call_data->uuid), (&tap_data->uuid)))
1973         ||(ri->call_data->ver != tap_data->ver)){
1974         return 0;
1975     }
1976
1977     add_srt_table_data(dcerpc_srt_table, ri->call_data->opnum, &ri->call_data->req_time, pinfo);
1978
1979     return 1;
1980 }
1981
1982 static guint
1983 dcerpcstat_param(register_srt_t* srt, const char* opt_arg, char** err)
1984 {
1985     int pos = 0;
1986     guint32 i, max_procs;
1987     dcerpcstat_tap_data_t* tap_data;
1988     guint d1,d2,d3,d40,d41,d42,d43,d44,d45,d46,d47;
1989     int major, minor;
1990     guint16 ver;
1991     dcerpc_sub_dissector *procs;
1992
1993     if (sscanf(opt_arg, ",%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x,%d.%d%n",
1994            &d1,&d2,&d3,&d40,&d41,&d42,&d43,&d44,&d45,&d46,&d47,&major,&minor,&pos) == 13)
1995     {
1996         if ((major < 0) || (major > 65535)) {
1997             *err = g_strdup_printf("dcerpcstat_init() Major version number %d is invalid - must be positive and <= 65535", major);
1998             return pos;
1999         }
2000         if ((minor < 0) || (minor > 65535)) {
2001             *err = g_strdup_printf("dcerpcstat_init() Minor version number %d is invalid - must be positive and <= 65535", minor);
2002             return pos;
2003         }
2004         ver = major;
2005
2006         tap_data = g_new0(dcerpcstat_tap_data_t, 1);
2007
2008         tap_data->uuid.data1    = d1;
2009         tap_data->uuid.data2    = d2;
2010         tap_data->uuid.data3    = d3;
2011         tap_data->uuid.data4[0] = d40;
2012         tap_data->uuid.data4[1] = d41;
2013         tap_data->uuid.data4[2] = d42;
2014         tap_data->uuid.data4[3] = d43;
2015         tap_data->uuid.data4[4] = d44;
2016         tap_data->uuid.data4[5] = d45;
2017         tap_data->uuid.data4[6] = d46;
2018         tap_data->uuid.data4[7] = d47;
2019
2020         procs             = dcerpc_get_proto_sub_dissector(&tap_data->uuid, ver);
2021         tap_data->prog    = dcerpc_get_proto_name(&tap_data->uuid, ver);
2022         tap_data->ver     = ver;
2023
2024         for(i=0,max_procs=0;procs[i].name;i++)
2025         {
2026             if(procs[i].num>max_procs)
2027             {
2028                 max_procs = procs[i].num;
2029             }
2030         }
2031         tap_data->num_procedures = max_procs+1;
2032
2033         set_srt_table_param_data(srt, tap_data);
2034     }
2035     else
2036     {
2037         *err = g_strdup_printf("<uuid>,<major version>.<minor version>[,<filter>]");
2038     }
2039
2040     return pos;
2041 }
2042
2043
2044 /*
2045  * Utility functions.  Modeled after packet-rpc.c
2046  */
2047
2048 int
2049 dissect_dcerpc_char(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
2050                      proto_tree *tree, guint8 *drep,
2051                      int hfindex, guint8 *pdata)
2052 {
2053     guint8 data;
2054
2055     /*
2056      * XXX - fix to handle EBCDIC if we ever support EBCDIC FT_CHAR.
2057      */
2058     data = tvb_get_guint8(tvb, offset);
2059     if (hfindex != -1) {
2060         proto_tree_add_item(tree, hfindex, tvb, offset, 1, ENC_ASCII|DREP_ENC_INTEGER(drep));
2061     }
2062     if (pdata)
2063         *pdata = data;
2064     tvb_ensure_bytes_exist(tvb, offset, 1);
2065     return offset + 1;
2066 }
2067
2068 int
2069 dissect_dcerpc_uint8(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
2070                      proto_tree *tree, guint8 *drep,
2071                      int hfindex, guint8 *pdata)
2072 {
2073     guint8 data;
2074
2075     data = tvb_get_guint8(tvb, offset);
2076     if (hfindex != -1) {
2077         proto_tree_add_item(tree, hfindex, tvb, offset, 1, DREP_ENC_INTEGER(drep));
2078     }
2079     if (pdata)
2080         *pdata = data;
2081     tvb_ensure_bytes_exist(tvb, offset, 1);
2082     return offset + 1;
2083 }
2084
2085 int
2086 dissect_dcerpc_uint16(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
2087                       proto_tree *tree, guint8 *drep,
2088                       int hfindex, guint16 *pdata)
2089 {
2090     guint16 data;
2091
2092     data = ((drep[0] & DREP_LITTLE_ENDIAN)
2093             ? tvb_get_letohs(tvb, offset)
2094             : tvb_get_ntohs(tvb, offset));
2095
2096     if (hfindex != -1) {
2097         proto_tree_add_item(tree, hfindex, tvb, offset, 2, DREP_ENC_INTEGER(drep));
2098     }
2099     if (pdata)
2100         *pdata = data;
2101     tvb_ensure_bytes_exist(tvb, offset, 2);
2102     return offset + 2;
2103 }
2104
2105 int
2106 dissect_dcerpc_uint32(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
2107                       proto_tree *tree, guint8 *drep,
2108                       int hfindex, guint32 *pdata)
2109 {
2110     guint32 data;
2111
2112     data = ((drep[0] & DREP_LITTLE_ENDIAN)
2113             ? tvb_get_letohl(tvb, offset)
2114             : tvb_get_ntohl(tvb, offset));
2115
2116     if (hfindex != -1) {
2117         proto_tree_add_item(tree, hfindex, tvb, offset, 4, DREP_ENC_INTEGER(drep));
2118     }
2119     if (pdata)
2120         *pdata = data;
2121     tvb_ensure_bytes_exist(tvb, offset, 4);
2122     return offset+4;
2123 }
2124
2125 /* handles 32 bit unix time_t */
2126 int
2127 dissect_dcerpc_time_t(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
2128                       proto_tree *tree, guint8 *drep,
2129                       int hfindex, guint32 *pdata)
2130 {
2131     guint32 data;
2132     nstime_t tv;
2133
2134     data = ((drep[0] & DREP_LITTLE_ENDIAN)
2135             ? tvb_get_letohl(tvb, offset)
2136             : tvb_get_ntohl(tvb, offset));
2137
2138     tv.secs = data;
2139     tv.nsecs = 0;
2140     if (hfindex != -1) {
2141         if (data == 0xffffffff) {
2142             /* special case,   no time specified */
2143             proto_tree_add_time_format_value(tree, hfindex, tvb, offset, 4, &tv, "No time specified");
2144         } else {
2145             proto_tree_add_time(tree, hfindex, tvb, offset, 4, &tv);
2146         }
2147     }
2148     if (pdata)
2149         *pdata = data;
2150
2151     tvb_ensure_bytes_exist(tvb, offset, 4);
2152     return offset+4;
2153 }
2154
2155 int
2156 dissect_dcerpc_uint64(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
2157                       proto_tree *tree, dcerpc_info *di, guint8 *drep,
2158                       int hfindex, guint64 *pdata)
2159 {
2160     guint64 data;
2161
2162     data = ((drep[0] & DREP_LITTLE_ENDIAN)
2163             ? tvb_get_letoh64(tvb, offset)
2164             : tvb_get_ntoh64(tvb, offset));
2165
2166     if (hfindex != -1) {
2167         header_field_info *hfinfo;
2168
2169         /* This might be a field that is either 32bit, in NDR or
2170            64 bits in NDR64. So we must be careful and call the right
2171            helper here
2172         */
2173         hfinfo = proto_registrar_get_nth(hfindex);
2174
2175         switch (hfinfo->type) {
2176         case FT_UINT64:
2177             proto_tree_add_uint64(tree, hfindex, tvb, offset, 8, data);
2178             break;
2179         case FT_INT64:
2180             proto_tree_add_int64(tree, hfindex, tvb, offset, 8, data);
2181             break;
2182         default:
2183             /* The value is truncated to 32bits.  64bit values have only been
2184                seen on fuzz-tested files */
2185             DISSECTOR_ASSERT((di->call_data->flags & DCERPC_IS_NDR64) || (data <= G_MAXUINT32));
2186             proto_tree_add_uint(tree, hfindex, tvb, offset, 8, (guint32)data);
2187         }
2188     }
2189     if (pdata)
2190         *pdata = data;
2191     tvb_ensure_bytes_exist(tvb, offset, 8);
2192     return offset+8;
2193 }
2194
2195
2196 int
2197 dissect_dcerpc_float(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
2198                      proto_tree *tree, guint8 *drep,
2199                      int hfindex, gfloat *pdata)
2200 {
2201     gfloat data;
2202
2203
2204     switch (drep[1]) {
2205     case(DCE_RPC_DREP_FP_IEEE):
2206         data = ((drep[0] & DREP_LITTLE_ENDIAN)
2207                 ? tvb_get_letohieee_float(tvb, offset)
2208                 : tvb_get_ntohieee_float(tvb, offset));
2209         if (tree && hfindex != -1) {
2210             proto_tree_add_float(tree, hfindex, tvb, offset, 4, data);
2211         }
2212         break;
2213     case(DCE_RPC_DREP_FP_VAX):  /* (fall trough) */
2214     case(DCE_RPC_DREP_FP_CRAY): /* (fall trough) */
2215     case(DCE_RPC_DREP_FP_IBM):  /* (fall trough) */
2216     default:
2217         /* ToBeDone: non IEEE floating formats */
2218         /* Set data to a negative infinity value */
2219         data = -G_MAXFLOAT;
2220         if (tree && hfindex != -1) {
2221             proto_tree_add_debug_text(tree, "DCE RPC: dissection of non IEEE floating formats currently not implemented (drep=%u)!", drep[1]);
2222         }
2223     }
2224     if (pdata)
2225         *pdata = data;
2226     tvb_ensure_bytes_exist(tvb, offset, 4);
2227     return offset + 4;
2228 }
2229
2230
2231 int
2232 dissect_dcerpc_double(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
2233                       proto_tree *tree, guint8 *drep,
2234                       int hfindex, gdouble *pdata)
2235 {
2236     gdouble data;
2237
2238
2239     switch (drep[1]) {
2240     case(DCE_RPC_DREP_FP_IEEE):
2241         data = ((drep[0] & DREP_LITTLE_ENDIAN)
2242                 ? tvb_get_letohieee_double(tvb, offset)
2243                 : tvb_get_ntohieee_double(tvb, offset));
2244         if (tree && hfindex != -1) {
2245             proto_tree_add_double(tree, hfindex, tvb, offset, 8, data);
2246         }
2247         break;
2248     case(DCE_RPC_DREP_FP_VAX):  /* (fall trough) */
2249     case(DCE_RPC_DREP_FP_CRAY): /* (fall trough) */
2250     case(DCE_RPC_DREP_FP_IBM):  /* (fall trough) */
2251     default:
2252         /* ToBeDone: non IEEE double formats */
2253         /* Set data to a negative infinity value */
2254         data = -G_MAXDOUBLE;
2255         if (tree && hfindex != -1) {
2256             proto_tree_add_debug_text(tree, "DCE RPC: dissection of non IEEE double formats currently not implemented (drep=%u)!", drep[1]);
2257         }
2258     }
2259     if (pdata)
2260         *pdata = data;
2261     tvb_ensure_bytes_exist(tvb, offset, 8);
2262     return offset + 8;
2263 }
2264
2265
2266 int
2267 dissect_dcerpc_uuid_t(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
2268                       proto_tree *tree, guint8 *drep,
2269                       int hfindex, e_guid_t *pdata)
2270 {
2271     e_guid_t uuid;
2272
2273
2274     if (drep[0] & DREP_LITTLE_ENDIAN) {
2275         tvb_get_letohguid(tvb, offset, (e_guid_t *) &uuid);
2276     } else {
2277         tvb_get_ntohguid(tvb, offset, (e_guid_t *) &uuid);
2278     }
2279     if (tree && hfindex != -1) {
2280         proto_tree_add_guid(tree, hfindex, tvb, offset, 16, (e_guid_t *) &uuid);
2281     }
2282     if (pdata) {
2283         *pdata = uuid;
2284     }
2285     return offset + 16;
2286 }
2287
2288
2289 /*
2290  * a couple simpler things
2291  */
2292 guint16
2293 dcerpc_tvb_get_ntohs(tvbuff_t *tvb, gint offset, guint8 *drep)
2294 {
2295     if (drep[0] & DREP_LITTLE_ENDIAN) {
2296         return tvb_get_letohs(tvb, offset);
2297     } else {
2298         return tvb_get_ntohs(tvb, offset);
2299     }
2300 }
2301
2302 guint32
2303 dcerpc_tvb_get_ntohl(tvbuff_t *tvb, gint offset, guint8 *drep)
2304 {
2305     if (drep[0] & DREP_LITTLE_ENDIAN) {
2306         return tvb_get_letohl(tvb, offset);
2307     } else {
2308         return tvb_get_ntohl(tvb, offset);
2309     }
2310 }
2311
2312 void
2313 dcerpc_tvb_get_uuid(tvbuff_t *tvb, gint offset, guint8 *drep, e_guid_t *uuid)
2314 {
2315     if (drep[0] & DREP_LITTLE_ENDIAN) {
2316         tvb_get_letohguid(tvb, offset, (e_guid_t *) uuid);
2317     } else {
2318         tvb_get_ntohguid(tvb, offset, (e_guid_t *) uuid);
2319     }
2320 }
2321
2322
2323 /* NDR arrays */
2324 /* function to dissect a unidimensional conformant array */
2325 static int
2326 dissect_ndr_ucarray_core(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2327                     proto_tree *tree, dcerpc_info *di, guint8 *drep,
2328                     dcerpc_dissect_fnct_t *fnct_bytes,
2329                     dcerpc_dissect_fnct_blk_t *fnct_block)
2330 {
2331     guint32      i;
2332     int          old_offset;
2333     int          conformance_size = 4;
2334
2335     /* ensure that just one pointer is set in the call */
2336     DISSECTOR_ASSERT((fnct_bytes && !fnct_block) || (!fnct_bytes && fnct_block));
2337
2338     if (di->call_data->flags & DCERPC_IS_NDR64) {
2339         conformance_size = 8;
2340     }
2341
2342     if (di->conformant_run) {
2343         guint64 val;
2344
2345         /* conformant run, just dissect the max_count header */
2346         old_offset = offset;
2347         di->conformant_run = 0;
2348         offset = dissect_ndr_uint3264(tvb, offset, pinfo, tree, di, drep,
2349                                        hf_dcerpc_array_max_count, &val);
2350         di->array_max_count = (gint32)val;
2351         di->array_max_count_offset = offset-conformance_size;
2352         di->conformant_run = 1;
2353         di->conformant_eaten = offset-old_offset;
2354     } else {
2355         /* we don't remember where in the bytestream this field was */
2356         proto_tree_add_uint(tree, hf_dcerpc_array_max_count, tvb, di->array_max_count_offset, conformance_size, di->array_max_count);
2357
2358         /* real run, dissect the elements */
2359         if (fnct_block) {
2360                 offset = (*fnct_block)(tvb, offset, di->array_max_count,
2361                                        pinfo, tree, di, drep);
2362         } else {
2363             for (i=0 ;i<di->array_max_count; i++) {
2364                 offset = (*fnct_bytes)(tvb, offset, pinfo, tree, di, drep);
2365             }
2366         }
2367     }
2368
2369     return offset;
2370 }
2371
2372 int
2373 dissect_ndr_ucarray_block(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2374                           proto_tree *tree, dcerpc_info *di, guint8 *drep,
2375                           dcerpc_dissect_fnct_blk_t *fnct)
2376 {
2377     return dissect_ndr_ucarray_core(tvb, offset, pinfo, tree, di, drep, NULL, fnct);
2378 }
2379
2380 int
2381 dissect_ndr_ucarray(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2382                     proto_tree *tree, dcerpc_info *di, guint8 *drep,
2383                     dcerpc_dissect_fnct_t *fnct)
2384 {
2385     return dissect_ndr_ucarray_core(tvb, offset, pinfo, tree, di, drep, fnct, NULL);
2386 }
2387
2388 /* function to dissect a unidimensional conformant and varying array
2389  * depending on the dissection function passed as a parameter,
2390  * content of the array will be dissected as a block or byte by byte
2391  */
2392 static int
2393 dissect_ndr_ucvarray_core(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2394                      proto_tree *tree, dcerpc_info *di, guint8 *drep,
2395                      dcerpc_dissect_fnct_t *fnct_bytes,
2396                      dcerpc_dissect_fnct_blk_t *fnct_block)
2397 {
2398     guint32      i;
2399     int          old_offset;
2400     int          conformance_size = 4;
2401
2402     if (di->call_data->flags & DCERPC_IS_NDR64) {
2403         conformance_size = 8;
2404     }
2405
2406     if (di->conformant_run) {
2407         guint64 val;
2408
2409         /* conformant run, just dissect the max_count header */
2410         old_offset = offset;
2411         di->conformant_run = 0;
2412         offset = dissect_ndr_uint3264(tvb, offset, pinfo, tree, di, drep,
2413                                        hf_dcerpc_array_max_count, &val);
2414         DISSECTOR_ASSERT(val <= G_MAXUINT32);
2415         di->array_max_count = (guint32)val;
2416         di->array_max_count_offset = offset-conformance_size;
2417         offset = dissect_ndr_uint3264(tvb, offset, pinfo, tree, di, drep,
2418                                        hf_dcerpc_array_offset, &val);
2419         DISSECTOR_ASSERT(val <= G_MAXUINT32);
2420         di->array_offset = (guint32)val;
2421         di->array_offset_offset = offset-conformance_size;
2422         offset = dissect_ndr_uint3264(tvb, offset, pinfo, tree, di, drep,
2423                                        hf_dcerpc_array_actual_count, &val);
2424         DISSECTOR_ASSERT(val <= G_MAXUINT32);
2425         di->array_actual_count = (guint32)val;
2426         di->array_actual_count_offset = offset-conformance_size;
2427         di->conformant_run = 1;
2428         di->conformant_eaten = offset-old_offset;
2429     } else {
2430         /* we don't remember where in the bytestream these fields were */
2431         proto_tree_add_uint(tree, hf_dcerpc_array_max_count, tvb, di->array_max_count_offset, conformance_size, di->array_max_count);
2432         proto_tree_add_uint(tree, hf_dcerpc_array_offset, tvb, di->array_offset_offset, conformance_size, di->array_offset);
2433         proto_tree_add_uint(tree, hf_dcerpc_array_actual_count, tvb, di->array_actual_count_offset, conformance_size, di->array_actual_count);
2434
2435         /* real run, dissect the elements */
2436         if (fnct_block) {
2437                 offset = (*fnct_block)(tvb, offset, di->array_actual_count,
2438                                        pinfo, tree, di, drep);
2439         } else if (fnct_bytes) {
2440             for (i=0 ;i<di->array_actual_count; i++) {
2441                 old_offset = offset;
2442                 offset = (*fnct_bytes)(tvb, offset, pinfo, tree, di, drep);
2443                 /* Make sure we're moving forward */
2444                 if (old_offset >= offset)
2445                     break;
2446             }
2447         }
2448     }
2449
2450     return offset;
2451 }
2452
2453 int
2454 dissect_ndr_ucvarray_block(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2455                      proto_tree *tree, dcerpc_info *di, guint8 *drep,
2456                      dcerpc_dissect_fnct_blk_t *fnct)
2457 {
2458     return dissect_ndr_ucvarray_core(tvb, offset, pinfo, tree, di, drep, NULL, fnct);
2459 }
2460
2461 int
2462 dissect_ndr_ucvarray(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2463                      proto_tree *tree, dcerpc_info *di, guint8 *drep,
2464                      dcerpc_dissect_fnct_t *fnct)
2465 {
2466     return dissect_ndr_ucvarray_core(tvb, offset, pinfo, tree, di, drep, fnct, NULL);
2467 }
2468 /* function to dissect a unidimensional varying array */
2469 int
2470 dissect_ndr_uvarray(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2471                     proto_tree *tree, dcerpc_info *di, guint8 *drep,
2472                     dcerpc_dissect_fnct_t *fnct)
2473 {
2474     guint32      i;
2475     int          old_offset;
2476     int          conformance_size = 4;
2477
2478     if (di->call_data->flags & DCERPC_IS_NDR64) {
2479         conformance_size = 8;
2480     }
2481
2482     if (di->conformant_run) {
2483         guint64 val;
2484
2485         /* conformant run, just dissect the max_count header */
2486         old_offset = offset;
2487         di->conformant_run = 0;
2488         offset = dissect_ndr_uint3264(tvb, offset, pinfo, tree, di, drep,
2489                                        hf_dcerpc_array_offset, &val);
2490         DISSECTOR_ASSERT(val <= G_MAXUINT32);
2491         di->array_offset = (guint32)val;
2492         di->array_offset_offset = offset-conformance_size;
2493         offset = dissect_ndr_uint3264(tvb, offset, pinfo, tree, di, drep,
2494                                        hf_dcerpc_array_actual_count, &val);
2495         DISSECTOR_ASSERT(val <= G_MAXUINT32);
2496         di->array_actual_count = (guint32)val;
2497         di->array_actual_count_offset = offset-conformance_size;
2498         di->conformant_run = 1;
2499         di->conformant_eaten = offset-old_offset;
2500     } else {
2501         /* we don't remember where in the bytestream these fields were */
2502         proto_tree_add_uint(tree, hf_dcerpc_array_offset, tvb, di->array_offset_offset, conformance_size, di->array_offset);
2503         proto_tree_add_uint(tree, hf_dcerpc_array_actual_count, tvb, di->array_actual_count_offset, conformance_size, di->array_actual_count);
2504
2505         /* real run, dissect the elements */
2506         for (i=0; i<di->array_actual_count; i++) {
2507             offset = (*fnct)(tvb, offset, pinfo, tree, di, drep);
2508         }
2509     }
2510
2511     return offset;
2512 }
2513
2514 /* Dissect an string of bytes.  This corresponds to
2515    IDL of the form '[string] byte *foo'.
2516
2517    It can also be used for a conformant varying array of bytes if
2518    the contents of the array should be shown as a big blob, rather
2519    than showing each byte as an individual element.
2520
2521    XXX - which of those is really the IDL type for, for example,
2522    the encrypted data in some MAPI packets?  (Microsoft hasn't
2523    released that IDL.)
2524
2525    XXX - does this need to do all the conformant array stuff that
2526    "dissect_ndr_ucvarray()" does?  These are presumably for strings
2527    that are conformant and varying - they're stored like conformant
2528    varying arrays of bytes.  */
2529 int
2530 dissect_ndr_byte_array(tvbuff_t *tvb, int offset, packet_info *pinfo,
2531                        proto_tree *tree, dcerpc_info *di, guint8 *drep)
2532 {
2533     guint64      len;
2534
2535     if (di->conformant_run) {
2536         /* just a run to handle conformant arrays, no scalars to dissect */
2537         return offset;
2538     }
2539
2540     /* NDR array header */
2541
2542     offset = dissect_ndr_uint3264(tvb, offset, pinfo, tree, di, drep,
2543                                   hf_dcerpc_array_max_count, NULL);
2544
2545     offset = dissect_ndr_uint3264(tvb, offset, pinfo, tree, di, drep,
2546                                   hf_dcerpc_array_offset, NULL);
2547
2548     offset = dissect_ndr_uint3264(tvb, offset, pinfo, tree, di, drep,
2549                                   hf_dcerpc_array_actual_count, &len);
2550
2551     DISSECTOR_ASSERT(len <= G_MAXUINT32);
2552     if (len) {
2553         proto_tree_add_item(tree, di->hf_index, tvb, offset, (guint32)len,
2554                             ENC_NA);
2555     }
2556
2557     offset += (guint32)len;
2558
2559     return offset;
2560 }
2561
2562 /* For dissecting arrays that are to be interpreted as strings.  */
2563
2564 /* Dissect an NDR conformant varying string of elements.
2565    The length of each element is given by the 'size_is' parameter;
2566    the elements are assumed to be characters or wide characters.
2567
2568    XXX - does this need to do all the conformant array stuff that
2569    "dissect_ndr_ucvarray()" does?  */
2570 int
2571 dissect_ndr_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
2572                      proto_tree *tree, dcerpc_info *di, guint8 *drep, int size_is,
2573                      int hfindex, gboolean add_subtree, char **data)
2574 {
2575     header_field_info *hfinfo;
2576     proto_item        *string_item;
2577     proto_tree        *string_tree;
2578     guint64            len;
2579     guint32            buffer_len;
2580     char              *s;
2581
2582     /* Make sure this really is a string field. */
2583     hfinfo = proto_registrar_get_nth(hfindex);
2584     DISSECTOR_ASSERT(hfinfo->type == FT_STRING);
2585
2586     if (di->conformant_run) {
2587         /* just a run to handle conformant arrays, no scalars to dissect */
2588         return offset;
2589     }
2590
2591     if (add_subtree) {
2592         string_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_dcerpc_string, &string_item,
2593                                           proto_registrar_get_name(hfindex));
2594     } else {
2595         string_item = NULL;
2596         string_tree = tree;
2597     }
2598
2599     /* NDR array header */
2600
2601     offset = dissect_ndr_uint3264(tvb, offset, pinfo, string_tree, di, drep,
2602                                   hf_dcerpc_array_max_count, NULL);
2603
2604     offset = dissect_ndr_uint3264(tvb, offset, pinfo, string_tree, di, drep,
2605                                   hf_dcerpc_array_offset, NULL);
2606
2607     offset = dissect_ndr_uint3264(tvb, offset, pinfo, string_tree, di, drep,
2608                                   hf_dcerpc_array_actual_count, &len);
2609
2610     /* The value is truncated to 32bits.  64bit values have only been
2611        seen on fuzztested files */
2612     buffer_len = size_is * (guint32)len;
2613
2614     /* Adjust offset */
2615     if (!di->no_align && (offset % size_is))
2616         offset += size_is - (offset % size_is);
2617
2618     /*
2619      * "tvb_get_string_enc()" throws an exception if the entire string
2620      * isn't in the tvbuff.  If the length is bogus, this should
2621      * keep us from trying to allocate an immensely large buffer.
2622      * (It won't help if the length is *valid* but immensely large,
2623      * but that's another matter; in any case, that would happen only
2624      * if we had an immensely large tvbuff....)
2625      *
2626      * XXX - so why are we doing tvb_ensure_bytes_exist()?
2627      */
2628     tvb_ensure_bytes_exist(tvb, offset, buffer_len);
2629     if (size_is == sizeof(guint16)) {
2630         /*
2631          * Assume little-endian UTF-16.
2632          *
2633          * XXX - is this always little-endian?
2634          */
2635         s = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, buffer_len,
2636                                ENC_UTF_16|ENC_LITTLE_ENDIAN);
2637     } else {
2638         /*
2639          * XXX - what if size_is is neither 1 nor 2?
2640          */
2641         s = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, buffer_len,
2642                                DREP_ENC_CHAR(drep));
2643     }
2644     if (tree && buffer_len)
2645         proto_tree_add_string(string_tree, hfindex, tvb, offset,
2646                               buffer_len, s);
2647
2648     if (string_item != NULL)
2649         proto_item_append_text(string_item, ": %s", s);
2650
2651     if (data)
2652         *data = s;
2653
2654     offset += buffer_len;
2655
2656     proto_item_set_end(string_item, tvb, offset);
2657
2658     return offset;
2659 }
2660
2661 int
2662 dissect_ndr_cstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
2663                     proto_tree *tree, dcerpc_info *di, guint8 *drep, int size_is,
2664                     int hfindex, gboolean add_subtree, char **data)
2665 {
2666     return dissect_ndr_cvstring(tvb, offset, pinfo, tree, di, drep, size_is, hfindex, add_subtree, data);
2667 }
2668
2669 /* Dissect an conformant varying string of chars.
2670    This corresponds to IDL of the form '[string] char *foo'.
2671
2672    XXX - at least according to the DCE RPC 1.1 spec, a string has
2673    a null terminator, which isn't necessary as a terminator for
2674    the transfer language (as there's a length), but is presumably
2675    there for the benefit of null-terminated-string languages
2676    such as C.  Is this ever used for purely counted strings?
2677    (Not that it matters if it is.) */
2678 int
2679 dissect_ndr_char_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
2680                           proto_tree *tree, dcerpc_info *di, guint8 *drep)
2681 {
2682     return dissect_ndr_cvstring(tvb, offset, pinfo, tree, di, drep,
2683                                 sizeof(guint8), di->hf_index,
2684                                 FALSE, NULL);
2685 }
2686
2687 /* Dissect a conformant varying string of wchars (wide characters).
2688    This corresponds to IDL of the form '[string] wchar *foo'
2689
2690    XXX - at least according to the DCE RPC 1.1 spec, a string has
2691    a null terminator, which isn't necessary as a terminator for
2692    the transfer language (as there's a length), but is presumably
2693    there for the benefit of null-terminated-string languages
2694    such as C.  Is this ever used for purely counted strings?
2695    (Not that it matters if it is.) */
2696 int
2697 dissect_ndr_wchar_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
2698                            proto_tree *tree, dcerpc_info *di, guint8 *drep)
2699 {
2700     return dissect_ndr_cvstring(tvb, offset, pinfo, tree, di, drep,
2701                                 sizeof(guint16), di->hf_index,
2702                                 FALSE, NULL);
2703 }
2704
2705 /* This function is aimed for PIDL usage and dissects a UNIQUE pointer to
2706  * unicode string.
2707  */
2708 int
2709 PIDL_dissect_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep, int chsize, int hfindex, guint32 param)
2710 {
2711     char        *s      = NULL;
2712     gint         levels = CB_STR_ITEM_LEVELS(param);
2713
2714     offset = dissect_ndr_cvstring(tvb, offset, pinfo, tree, di, drep,
2715                                   chsize, hfindex,
2716                                   FALSE, &s);
2717
2718     if (!di->conformant_run) {
2719         /* Append string to COL_INFO */
2720         if (param & PIDL_SET_COL_INFO) {
2721             col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", s);
2722         }
2723         /* Save string to dcv->private_data */
2724         if ((param & PIDL_STR_SAVE)
2725            && (!pinfo->fd->flags.visited)) {
2726             dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2727             dcv->private_data = wmem_strdup(wmem_file_scope(), s);
2728         }
2729         /* Append string to upper-level proto_items */
2730         if ((levels > 0) && tree && s && s[0]) {
2731             proto_item_append_text(tree, ": %s", s);
2732             tree = tree->parent;
2733             levels--;
2734             if (levels > 0) {
2735                 proto_item_append_text(tree, ": %s", s);
2736                 tree = tree->parent;
2737                 levels--;
2738                 while (levels > 0) {
2739                     proto_item_append_text(tree, " %s", s);
2740                     tree = tree->parent;
2741                     levels--;
2742                 }
2743             }
2744         }
2745
2746     }
2747
2748     return offset;
2749 }
2750
2751 /* Dissect an NDR varying string of elements.
2752    The length of each element is given by the 'size_is' parameter;
2753    the elements are assumed to be characters or wide characters.
2754 */
2755 int
2756 dissect_ndr_vstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
2757                     proto_tree *tree, dcerpc_info *di, guint8 *drep, int size_is,
2758                     int hfindex, gboolean add_subtree, char **data)
2759 {
2760     header_field_info *hfinfo;
2761     proto_item        *string_item;
2762     proto_tree        *string_tree;
2763     guint64            len;
2764     guint32            buffer_len;
2765     char              *s;
2766
2767     /* Make sure this really is a string field. */
2768     hfinfo = proto_registrar_get_nth(hfindex);
2769     DISSECTOR_ASSERT(hfinfo->type == FT_STRING);
2770
2771     if (di->conformant_run) {
2772         /* just a run to handle conformant arrays, no scalars to dissect */
2773         return offset;
2774     }
2775
2776     if (add_subtree) {
2777         string_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_dcerpc_string, &string_item,
2778                                           proto_registrar_get_name(hfindex));
2779     } else {
2780         string_item = NULL;
2781         string_tree = tree;
2782     }
2783
2784     /* NDR array header */
2785     offset = dissect_ndr_uint3264(tvb, offset, pinfo, string_tree, di, drep,
2786                                   hf_dcerpc_array_offset, NULL);
2787
2788     offset = dissect_ndr_uint3264(tvb, offset, pinfo, string_tree, di, drep,
2789                                   hf_dcerpc_array_actual_count, &len);
2790
2791     DISSECTOR_ASSERT(len <= G_MAXUINT32);
2792     buffer_len = size_is * (guint32)len;
2793
2794     /* Adjust offset */
2795     if (!di->no_align && (offset % size_is))
2796         offset += size_is - (offset % size_is);
2797
2798     /*
2799      * "tvb_get_string_enc()" throws an exception if the entire string
2800      * isn't in the tvbuff.  If the length is bogus, this should
2801      * keep us from trying to allocate an immensely large buffer.
2802      * (It won't help if the length is *valid* but immensely large,
2803      * but that's another matter; in any case, that would happen only
2804      * if we had an immensely large tvbuff....)
2805      *
2806      * XXX - so why are we doing tvb_ensure_bytes_exist()?
2807      */
2808     tvb_ensure_bytes_exist(tvb, offset, buffer_len);
2809     if (size_is == sizeof(guint16)) {
2810         /*
2811          * Assume little-endian UTF-16.
2812          *
2813          * XXX - is this always little-endian?
2814          */
2815         s = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, buffer_len,
2816                                ENC_UTF_16|ENC_LITTLE_ENDIAN);
2817     } else {
2818         /*
2819          * XXX - what if size_is is neither 1 nor 2?
2820          */
2821         s = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, buffer_len,
2822                                DREP_ENC_CHAR(drep));
2823     }
2824     if (tree && buffer_len)
2825         proto_tree_add_string(string_tree, hfindex, tvb, offset,
2826                               buffer_len, s);
2827
2828     if (string_item != NULL)
2829         proto_item_append_text(string_item, ": %s", s);
2830
2831     if (data)
2832         *data = s;
2833
2834     offset += buffer_len;
2835
2836     proto_item_set_end(string_item, tvb, offset);
2837
2838     return offset;
2839 }
2840
2841 /* Dissect an varying string of chars.
2842    This corresponds to IDL of the form '[string] char *foo'.
2843
2844    XXX - at least according to the DCE RPC 1.1 spec, a string has
2845    a null terminator, which isn't necessary as a terminator for
2846    the transfer language (as there's a length), but is presumably
2847    there for the benefit of null-terminated-string languages
2848    such as C.  Is this ever used for purely counted strings?
2849    (Not that it matters if it is.) */
2850 int
2851 dissect_ndr_char_vstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
2852                          proto_tree *tree, dcerpc_info *di, guint8 *drep)
2853 {
2854     return dissect_ndr_vstring(tvb, offset, pinfo, tree, di, drep,
2855                                sizeof(guint8), di->hf_index,
2856                                FALSE, NULL);
2857 }
2858
2859 /* Dissect a varying string of wchars (wide characters).
2860    This corresponds to IDL of the form '[string] wchar *foo'
2861
2862    XXX - at least according to the DCE RPC 1.1 spec, a string has
2863    a null terminator, which isn't necessary as a terminator for
2864    the transfer language (as there's a length), but is presumably
2865    there for the benefit of null-terminated-string languages
2866    such as C.  Is this ever used for purely counted strings?
2867    (Not that it matters if it is.) */
2868 int
2869 dissect_ndr_wchar_vstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
2870                           proto_tree *tree, dcerpc_info *di, guint8 *drep)
2871 {
2872     return dissect_ndr_vstring(tvb, offset, pinfo, tree, di, drep,
2873                                sizeof(guint16), di->hf_index,
2874                                FALSE, NULL);
2875 }
2876
2877
2878 /* ndr pointer handling */
2879 /* list of pointers encountered so far */
2880 static GSList *ndr_pointer_list = NULL;
2881
2882 /* position where in the list to insert newly encountered pointers */
2883 static int ndr_pointer_list_pos = 0;
2884
2885 /* Boolean controlling whether pointers are top-level or embedded */
2886 static gboolean pointers_are_top_level = TRUE;
2887
2888 /* as a kludge, we represent all embedded reference pointers as id == -1
2889    hoping that his will not collide with any non-ref pointers */
2890 typedef struct ndr_pointer_data {
2891     guint32                 id;
2892     proto_item             *item; /* proto_item for pointer */
2893     proto_tree             *tree; /* subtree of above item */
2894     dcerpc_dissect_fnct_t  *fnct; /*if non-NULL, we have not called it yet*/
2895     int                     hf_index;
2896     dcerpc_callback_fnct_t *callback;
2897     void                   *callback_args;
2898 } ndr_pointer_data_t;
2899
2900 void
2901 init_ndr_pointer_list(dcerpc_info *di)
2902 {
2903     di->conformant_run = 0;
2904
2905     while (ndr_pointer_list) {
2906         ndr_pointer_data_t *npd = (ndr_pointer_data_t *)g_slist_nth_data(ndr_pointer_list, 0);
2907         ndr_pointer_list = g_slist_remove(ndr_pointer_list, npd);
2908         g_free(npd);
2909     }
2910
2911     ndr_pointer_list = NULL;
2912     ndr_pointer_list_pos = 0;
2913     pointers_are_top_level = TRUE;
2914 }
2915
2916 int
2917 dissect_deferred_pointers(packet_info *pinfo, tvbuff_t *tvb, int offset, dcerpc_info *di, guint8 *drep)
2918 {
2919     int          found_new_pointer;
2920     int          old_offset;
2921     int          next_pointer;
2922
2923     next_pointer = 0;
2924
2925     do{
2926         int i, len;
2927
2928         found_new_pointer = 0;
2929         len = g_slist_length(ndr_pointer_list);
2930         for (i=next_pointer; i<len; i++) {
2931             ndr_pointer_data_t *tnpd = (ndr_pointer_data_t *)g_slist_nth_data(ndr_pointer_list, i);
2932             if (tnpd->fnct) {
2933                 dcerpc_dissect_fnct_t *fnct;
2934
2935                 next_pointer = i+1;
2936                 found_new_pointer = 1;
2937                 fnct = tnpd->fnct;
2938                 tnpd->fnct = NULL;
2939                 ndr_pointer_list_pos = i+1;
2940                 di->hf_index = tnpd->hf_index;
2941                 /* first a run to handle any conformant
2942                    array headers */
2943                 di->conformant_run = 1;
2944                 di->conformant_eaten = 0;
2945                 old_offset = offset;
2946                 offset = (*(fnct))(tvb, offset, pinfo, NULL, di, drep);
2947
2948                 DISSECTOR_ASSERT((offset-old_offset) == di->conformant_eaten);
2949                 /* This is to check for any bugs in the dissectors.
2950                  *
2951                  * Basically, the NDR representation will store all
2952                  * arrays in two blocks, one block with the dimension
2953                  * description, like size, number of elements and such,
2954                  * and another block that contains the actual data stored
2955                  * in the array.
2956                  * If the array is embedded directly inside another,
2957                  * encapsulating aggregate type, like a union or struct,
2958                  * then these two blocks will be stored at different places
2959                  * in the bytestream, with other data between the blocks.
2960                  *
2961                  * For this reason, all pointers to types (both aggregate
2962                  * and scalar, for simplicity no distinction is made)
2963                  * will have its dissector called twice.
2964                  * The dissector will first be called with conformant_run == 1
2965                  * in which mode the dissector MUST NOT consume any data from
2966                  * the tvbuff (i.e. may not dissect anything) except the
2967                  * initial control block for arrays.
2968                  * The second time the dissector is called, with
2969                  * conformant_run == 0, all other data for the type will be
2970                  * dissected.
2971                  *
2972                  * All dissect_ndr_<type> dissectors are already prepared
2973                  * for this and knows when it should eat data from the tvb
2974                  * and when not to, so implementors of dissectors will
2975                  * normally not need to worry about this or even know about
2976                  * it. However, if a dissector for an aggregate type calls
2977                  * a subdissector from outside packet-dcerpc.c, such as
2978                  * the dissector in packet-smb.c for NT Security Descriptors
2979                  * as an example, then it is VERY important to encapsulate
2980                  * this call to an external subdissector with the appropriate
2981                  * test for conformant_run, i.e. it will need something like
2982                  *
2983                  *      dcerpc_info *di (received as function parameter)
2984                  *
2985                  *      if (di->conformant_run) {
2986                  *              return offset;
2987                  *      }
2988                  *
2989                  * to make sure it makes the right thing.
2990                  * This assert will signal when someone has forgotten to
2991                  * make the dissector aware of this requirement.
2992                  */
2993
2994                 /* now we dissect the actual pointer */
2995                 di->conformant_run = 0;
2996                 old_offset = offset;
2997                 offset = (*(fnct))(tvb, offset, pinfo, tnpd->tree, di, drep);
2998                 if (tnpd->callback)
2999                     tnpd->callback(pinfo, tnpd->tree, tnpd->item, di, tvb, old_offset, offset, tnpd->callback_args);
3000                 proto_item_set_len(tnpd->item, offset - old_offset);
3001                 break;
3002             }
3003         }
3004     } while (found_new_pointer);
3005
3006     return offset;
3007 }
3008
3009
3010 static void
3011 add_pointer_to_list(packet_info *pinfo, proto_tree *tree, proto_item *item,
3012                     dcerpc_info *di, dcerpc_dissect_fnct_t *fnct, guint32 id, int hf_index,
3013                     dcerpc_callback_fnct_t *callback, void *callback_args)
3014 {
3015     ndr_pointer_data_t *npd;
3016
3017     /* check if this pointer is valid */
3018     if (id != 0xffffffff) {
3019         dcerpc_call_value *value;
3020
3021         value = di->call_data;
3022
3023         if (di->ptype == PDU_REQ) {
3024             if (!(pinfo->fd->flags.visited)) {
3025                 if (id > value->max_ptr) {
3026                     value->max_ptr = id;
3027                 }
3028             }
3029         } else {
3030             /* if we haven't seen the request bail out since we can't
3031                know whether this is the first non-NULL instance
3032                or not */
3033             if (value->req_frame == 0) {
3034                 /* XXX THROW EXCEPTION */
3035             }
3036
3037             /* We saw this one in the request frame, nothing to
3038                dissect later */
3039             if (id <= value->max_ptr) {
3040                 return;
3041             }
3042         }
3043     }
3044
3045     npd = (ndr_pointer_data_t *)g_malloc(sizeof(ndr_pointer_data_t));
3046     npd->id   = id;
3047     npd->tree = tree;
3048     npd->item = item;
3049     npd->fnct = fnct;
3050     npd->hf_index = hf_index;
3051     npd->callback = callback;
3052     npd->callback_args = callback_args;
3053     ndr_pointer_list = g_slist_insert(ndr_pointer_list, npd,
3054                                       ndr_pointer_list_pos);
3055     ndr_pointer_list_pos++;
3056 }
3057
3058
3059 static int
3060 find_pointer_index(guint32 id)
3061 {
3062     ndr_pointer_data_t *npd;
3063     int                 i,len;
3064
3065     len = g_slist_length(ndr_pointer_list);
3066     for (i=0; i<len; i++) {
3067         npd = (ndr_pointer_data_t *)g_slist_nth_data(ndr_pointer_list, i);
3068         if (npd) {
3069             if (npd->id == id) {
3070                 return i;
3071             }
3072         }
3073     }
3074
3075     return -1;
3076 }
3077
3078 /* This function dissects an NDR pointer and stores the callback for later
3079  * deferred dissection.
3080  *
3081  *   fnct is the callback function for when we have reached this object in
3082  *   the bytestream.
3083  *
3084  *   type is what type of pointer.
3085  *
3086  *   this is text is what text we should put in any created tree node.
3087  *
3088  *   hf_index is what hf value we want to pass to the callback function when
3089  *   it is called, the callback can later pick this one up from di->hf_index.
3090  *
3091  *   callback is executed after the pointer has been dereferenced.
3092  *
3093  *   callback_args is passed as an argument to the callback function
3094  *
3095  * See packet-dcerpc-samr.c for examples
3096  */
3097 int
3098 dissect_ndr_pointer_cb(tvbuff_t *tvb, gint offset, packet_info *pinfo,
3099                        proto_tree *tree, dcerpc_info *di, guint8 *drep, dcerpc_dissect_fnct_t *fnct,
3100                        int type, const char *text, int hf_index,
3101                        dcerpc_callback_fnct_t *callback, void *callback_args)
3102 {
3103     proto_tree  *tr           = NULL;
3104     gint         start_offset = offset;
3105     int          pointer_size = 4;
3106
3107     if (di->conformant_run) {
3108         /* this call was only for dissecting the header for any
3109            embedded conformant array. we will not parse any
3110            pointers in this mode.
3111         */
3112         return offset;
3113     }
3114     if (di->call_data->flags & DCERPC_IS_NDR64) {
3115         pointer_size = 8;
3116     }
3117
3118
3119     /*TOP LEVEL REFERENCE POINTER*/
3120     if ( pointers_are_top_level
3121         && (type == NDR_POINTER_REF) ) {
3122         proto_item *item;
3123
3124         /* we must find out a nice way to do the length here */
3125         tr = proto_tree_add_subtree(tree, tvb, offset, 0,
3126                                    ett_dcerpc_pointer_data, &item, text);
3127
3128         add_pointer_to_list(pinfo, tr, item, di, fnct, 0xffffffff,
3129                             hf_index, callback, callback_args);
3130         goto after_ref_id;
3131     }
3132
3133     /*TOP LEVEL FULL POINTER*/
3134     if ( pointers_are_top_level
3135         && (type == NDR_POINTER_PTR) ) {
3136         int idx;
3137         guint64 id;
3138         proto_item *item;
3139
3140         /* get the referent id */
3141         offset = dissect_ndr_uint3264(tvb, offset, pinfo, NULL, di, drep, -1, &id);
3142
3143         /* we got a NULL pointer */
3144         if (id == 0) {
3145             proto_tree_add_bytes_format_value(tree, hf_dcerpc_null_pointer, tvb, offset-pointer_size,
3146                                 pointer_size, NULL, "%s", text);
3147             goto after_ref_id;
3148         }
3149
3150         /* see if we have seen this pointer before
3151            The value is truncated to 32bits.  64bit values have only been
3152            seen on fuzz-tested files */
3153         idx = find_pointer_index((guint32)id);
3154
3155         /* we have seen this pointer before */
3156         if (idx >= 0) {
3157             proto_tree_add_string(tree, hf_dcerpc_duplicate_ptr, tvb, offset-pointer_size, pointer_size, text);
3158             goto after_ref_id;
3159         }
3160
3161         /* new pointer */
3162         tr = proto_tree_add_subtree(tree, tvb, offset-pointer_size,
3163                                    pointer_size, ett_dcerpc_pointer_data, &item, text);
3164         if (di->call_data->flags & DCERPC_IS_NDR64) {
3165             proto_tree_add_uint64(tr, hf_dcerpc_referent_id64, tvb,
3166                                 offset-pointer_size, pointer_size, id);
3167         } else {
3168             proto_tree_add_uint(tr, hf_dcerpc_referent_id32, tvb,
3169                                 offset-pointer_size, pointer_size, (guint32)id);
3170         }
3171         add_pointer_to_list(pinfo, tr, item, di, fnct, (guint32)id, hf_index,
3172                             callback, callback_args);
3173         goto after_ref_id;
3174     }
3175     /*TOP LEVEL UNIQUE POINTER*/
3176     if ( pointers_are_top_level
3177         && (type == NDR_POINTER_UNIQUE) ) {
3178         guint64 id;
3179         proto_item *item;
3180
3181         /* get the referent id */
3182         offset = dissect_ndr_uint3264(tvb, offset, pinfo, NULL, di, drep, -1, &id);
3183
3184         /* we got a NULL pointer */
3185         if (id == 0) {
3186             proto_tree_add_bytes_format_value(tree, hf_dcerpc_null_pointer, tvb, offset-pointer_size,
3187                                 pointer_size, NULL, "%s",text);
3188             goto after_ref_id;
3189         }
3190
3191         /* new pointer */
3192         tr = proto_tree_add_subtree(tree, tvb, offset-pointer_size,
3193                                    pointer_size,
3194                                    ett_dcerpc_pointer_data, &item, text);
3195         if (di->call_data->flags & DCERPC_IS_NDR64) {
3196             proto_tree_add_uint64(tr, hf_dcerpc_referent_id64, tvb,
3197                             offset-pointer_size, pointer_size, id);
3198         } else {
3199             proto_tree_add_uint(tr, hf_dcerpc_referent_id32, tvb,
3200                             offset-pointer_size, pointer_size, (guint32)id);
3201         }
3202         add_pointer_to_list(pinfo, tr, item, di, fnct, 0xffffffff,
3203                             hf_index, callback, callback_args);
3204         goto after_ref_id;
3205     }
3206
3207     /*EMBEDDED REFERENCE POINTER*/
3208     if ( (!pointers_are_top_level)
3209         && (type == NDR_POINTER_REF) ) {
3210         guint64 id;
3211         proto_item *item;
3212
3213         /* get the referent id */
3214         offset = dissect_ndr_uint3264(tvb, offset, pinfo, NULL, di, drep, -1, &id);
3215
3216         /* new pointer */
3217         tr = proto_tree_add_subtree(tree, tvb, offset-pointer_size,
3218                                  pointer_size,
3219                                  ett_dcerpc_pointer_data,&item,text);
3220         if (di->call_data->flags & DCERPC_IS_NDR64) {
3221             proto_tree_add_uint64(tr, hf_dcerpc_referent_id64, tvb,
3222                             offset-pointer_size, pointer_size, id);
3223         } else {
3224             proto_tree_add_uint(tr, hf_dcerpc_referent_id32, tvb,
3225                             offset-pointer_size, pointer_size, (guint32)id);
3226         }
3227         add_pointer_to_list(pinfo, tr, item, di, fnct, 0xffffffff,
3228                             hf_index, callback, callback_args);
3229         goto after_ref_id;
3230     }
3231
3232     /*EMBEDDED UNIQUE POINTER*/
3233     if ( (!pointers_are_top_level)
3234         && (type == NDR_POINTER_UNIQUE) ) {
3235         guint64 id;
3236         proto_item *item;
3237
3238         /* get the referent id */
3239         offset = dissect_ndr_uint3264(tvb, offset, pinfo, NULL, di, drep, -1, &id);
3240
3241         /* we got a NULL pointer */
3242         if (id == 0) {
3243             proto_tree_add_bytes_format_value(tree, hf_dcerpc_null_pointer, tvb, offset-pointer_size,
3244                                 pointer_size, NULL, "%s",text);
3245             goto after_ref_id;
3246         }
3247
3248         /* new pointer */
3249         tr = proto_tree_add_subtree(tree, tvb, offset-pointer_size,
3250                                    pointer_size,
3251                                    ett_dcerpc_pointer_data,&item,text);
3252         if (di->call_data->flags & DCERPC_IS_NDR64) {
3253             proto_tree_add_uint64(tr, hf_dcerpc_referent_id64, tvb,
3254                             offset-pointer_size, pointer_size, id);
3255         } else {
3256             proto_tree_add_uint(tr, hf_dcerpc_referent_id32, tvb,
3257                             offset-pointer_size, pointer_size, (guint32)id);
3258         }
3259         add_pointer_to_list(pinfo, tr, item, di, fnct, 0xffffffff,
3260                             hf_index, callback, callback_args);
3261         goto after_ref_id;
3262     }
3263
3264     /*EMBEDDED FULL POINTER*/
3265     if ( (!pointers_are_top_level)
3266         && (type == NDR_POINTER_PTR) ) {
3267         int idx;
3268         guint64 id;
3269         proto_item *item;
3270
3271         /* get the referent id */
3272         offset = dissect_ndr_uint3264(tvb, offset, pinfo, NULL, di, drep, -1, &id);
3273
3274         /* we got a NULL pointer */
3275         if (id == 0) {
3276             proto_tree_add_bytes_format_value(tree, hf_dcerpc_null_pointer, tvb, offset-pointer_size,
3277                                 pointer_size, NULL, "%s",text);
3278             goto after_ref_id;
3279         }
3280
3281         /* see if we have seen this pointer before
3282            The value is truncated to 32bits.  64bit values have only been
3283            seen on fuzztested files */
3284         idx = find_pointer_index((guint32)id);
3285
3286         /* we have seen this pointer before */
3287         if (idx >= 0) {
3288             proto_tree_add_string(tree, hf_dcerpc_duplicate_ptr, tvb, offset-pointer_size, pointer_size, text);
3289             goto after_ref_id;
3290         }
3291
3292         /* new pointer */
3293         tr = proto_tree_add_subtree(tree, tvb, offset-pointer_size,
3294                                    pointer_size,
3295                                    ett_dcerpc_pointer_data, &item, text);
3296         if (di->call_data->flags & DCERPC_IS_NDR64) {
3297             proto_tree_add_uint64(tr, hf_dcerpc_referent_id64, tvb,
3298                             offset-pointer_size, pointer_size, id);
3299         } else {
3300             proto_tree_add_uint(tr, hf_dcerpc_referent_id32, tvb,
3301                             offset-pointer_size, pointer_size, (guint32)id);
3302         }
3303         add_pointer_to_list(pinfo, tr, item, di, fnct, (guint32)id, hf_index,
3304                             callback, callback_args);
3305         goto after_ref_id;
3306     }
3307
3308
3309 after_ref_id:
3310     /* After each top level pointer we have dissected we have to
3311        dissect all deferrals before we move on to the next top level
3312        argument */
3313     if (pointers_are_top_level == TRUE) {
3314         pointers_are_top_level = FALSE;
3315         offset = dissect_deferred_pointers(pinfo, tvb, offset, di, drep);
3316         pointers_are_top_level = TRUE;
3317     }
3318
3319     /* Set the length for the new subtree */
3320     if (tr) {
3321         proto_item_set_len(tr, offset-start_offset);
3322     }
3323     return offset;
3324 }
3325
3326 int
3327 dissect_ndr_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
3328                     proto_tree *tree, dcerpc_info *di, guint8 *drep, dcerpc_dissect_fnct_t *fnct,
3329                     int type, const char *text, int hf_index)
3330 {
3331     return dissect_ndr_pointer_cb(
3332         tvb, offset, pinfo, tree, di, drep, fnct, type, text, hf_index,
3333         NULL, NULL);
3334 }
3335 int
3336 dissect_ndr_toplevel_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
3337                              proto_tree *tree, dcerpc_info *di, guint8 *drep, dcerpc_dissect_fnct_t *fnct,
3338                              int type, const char *text, int hf_index)
3339 {
3340     int ret;
3341
3342     pointers_are_top_level = TRUE;
3343     ret = dissect_ndr_pointer_cb(
3344         tvb, offset, pinfo, tree, di, drep, fnct, type, text, hf_index,
3345         NULL, NULL);
3346     return ret;
3347 }
3348 int
3349 dissect_ndr_embedded_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
3350                              proto_tree *tree, dcerpc_info *di, guint8 *drep, dcerpc_dissect_fnct_t *fnct,
3351                              int type, const char *text, int hf_index)
3352 {
3353     int ret;
3354
3355     pointers_are_top_level = FALSE;
3356     ret = dissect_ndr_pointer_cb(
3357         tvb, offset, pinfo, tree, di, drep, fnct, type, text, hf_index,
3358         NULL, NULL);
3359     return ret;
3360 }
3361
3362 static void
3363 dissect_sec_vt_bitmask(proto_tree *tree, tvbuff_t *tvb)
3364 {
3365     proto_tree_add_bitmask(tree, tvb, 0,
3366                            hf_dcerpc_sec_vt_bitmask,
3367                            ett_dcerpc_sec_vt_bitmask,
3368                            sec_vt_bitmask_fields,
3369                            ENC_LITTLE_ENDIAN);
3370 }
3371
3372 static void
3373 dissect_sec_vt_pcontext(proto_tree *tree, tvbuff_t *tvb)
3374 {
3375     int offset = 0;
3376     proto_item *ti = NULL;
3377     proto_tree *tr = proto_tree_add_subtree(tree, tvb, offset, -1,
3378                                             ett_dcerpc_sec_vt_pcontext,
3379                                             &ti, "pcontext");
3380     e_guid_t uuid;
3381     const char *uuid_name;
3382
3383     tvb_get_letohguid(tvb, offset, &uuid);
3384     uuid_name = guids_get_uuid_name(&uuid);
3385     if (!uuid_name) {
3386             uuid_name = guid_to_str(wmem_packet_scope(), &uuid);
3387     }
3388
3389     proto_tree_add_guid_format(tr, hf_dcerpc_sec_vt_pcontext_uuid, tvb,
3390                                offset, 16, &uuid, "Abstract Syntax: %s", uuid_name);
3391     offset += 16;
3392
3393     proto_tree_add_item(tr, hf_dcerpc_sec_vt_pcontext_ver,
3394                         tvb, offset, 4, ENC_LITTLE_ENDIAN);
3395     offset += 4;
3396
3397     tvb_get_letohguid(tvb, offset, &uuid);
3398     uuid_name = guids_get_uuid_name(&uuid);
3399     if (!uuid_name) {
3400             uuid_name = guid_to_str(wmem_packet_scope(), &uuid);
3401     }
3402
3403     proto_tree_add_guid_format(tr, hf_dcerpc_sec_vt_pcontext_uuid, tvb,
3404                                offset, 16, &uuid, "Transfer Syntax: %s", uuid_name);
3405     offset += 16;
3406
3407     proto_tree_add_item(tr, hf_dcerpc_sec_vt_pcontext_ver,
3408                         tvb, offset, 4, ENC_LITTLE_ENDIAN);
3409     offset += 4;
3410
3411     proto_item_set_len(ti, offset);
3412 }
3413
3414 static void
3415 dissect_sec_vt_header(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb)
3416 {
3417     int offset = 0;
3418     proto_item *ti = NULL;
3419     proto_tree *tr = proto_tree_add_subtree(tree, tvb, offset, -1,
3420                                             ett_dcerpc_sec_vt_header,
3421                                             &ti, "header2");
3422     guint8 drep[4];
3423     guint8 ptype = tvb_get_guint8(tvb, offset);
3424
3425     proto_tree_add_uint(tr, hf_dcerpc_packet_type, tvb, offset, 1, ptype);
3426     offset += 1;
3427
3428     proto_tree_add_item(tr, hf_dcerpc_reserved, tvb, offset, 1, ENC_NA);
3429     offset += 1;
3430
3431     proto_tree_add_item(tr, hf_dcerpc_reserved, tvb, offset, 2, ENC_NA);
3432     offset += 2;
3433
3434     tvb_memcpy(tvb, drep, offset, 4);
3435     proto_tree_add_dcerpc_drep(tr, tvb, offset, drep, 4);
3436     offset += 4;
3437
3438     offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tr, drep,
3439                                    hf_dcerpc_cn_call_id, NULL);
3440
3441     offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tr, drep,
3442                                    hf_dcerpc_cn_ctx_id, NULL);
3443
3444     offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tr, drep,
3445                                    hf_dcerpc_opnum, NULL);
3446
3447     proto_item_set_len(ti, offset);
3448 }
3449
3450 static int
3451 dissect_verification_trailer_impl(packet_info *pinfo, tvbuff_t *tvb, int stub_offset,
3452                                   proto_tree *parent_tree, int *signature_offset)
3453 {
3454     int remaining = tvb_captured_length_remaining(tvb, stub_offset);
3455     int offset;
3456     gint signature_start;
3457     gint payload_length;
3458     typedef enum {
3459         SEC_VT_COMMAND_BITMASK_1    = 0x0001,
3460         SEC_VT_COMMAND_PCONTEXT     = 0x0002,
3461         SEC_VT_COMMAND_HEADER2      = 0x0003,
3462         SEC_VT_COMMAND_END          = 0x4000,
3463         SEC_VT_MUST_PROCESS_COMMAND = 0x8000,
3464         SEC_VT_COMMAND_MASK         = 0x3fff,
3465     } sec_vt_command;
3466     proto_item *payload_item;
3467     proto_item *item;
3468     proto_tree *tree;
3469
3470     if (signature_offset != NULL) {
3471         *signature_offset = -1;
3472     }
3473
3474     /* We need at least signature + the header of one command */
3475     if (remaining < (int)(sizeof(TRAILER_SIGNATURE) + 4)) {
3476          return -1;
3477     }
3478
3479     /* We only scan the last 512 bytes for a possible trailer */
3480     if (remaining > 512) {
3481          offset = remaining - 512;
3482          remaining = 512;
3483     } else {
3484          offset = 0;
3485     }
3486     offset += stub_offset;
3487
3488     signature_start = tvb_find_tvb(tvb, tvb_trailer_signature, offset);
3489     if (signature_start == -1) {
3490         return -1;
3491     }
3492     payload_length = signature_start - stub_offset;
3493     payload_item = proto_tree_add_item(parent_tree,
3494                                        hf_dcerpc_payload_stub_data,
3495                                        tvb, stub_offset, payload_length, ENC_NA);
3496     proto_item_append_text(payload_item, " (%d byte%s)",
3497                            payload_length, plurality(payload_length, "", "s"));
3498
3499     if (signature_offset != NULL) {
3500         *signature_offset = signature_start;
3501     }
3502     remaining -= (signature_start - offset);
3503     offset = signature_start;
3504
3505     tree = proto_tree_add_subtree(parent_tree, tvb, offset, -1,
3506                                   ett_dcerpc_verification_trailer,
3507                                   &item, "Verification Trailer");
3508
3509     proto_tree_add_item(tree, hf_dcerpc_sec_vt_signature,
3510                         tvb, offset, sizeof(TRAILER_SIGNATURE), ENC_NA);
3511     offset += (int)sizeof(TRAILER_SIGNATURE);
3512     remaining -= (int)sizeof(TRAILER_SIGNATURE);
3513
3514     while (remaining >= 4) {
3515         sec_vt_command cmd;
3516         guint16 len, len_missalign;
3517         gboolean cmd_end, cmd_must;
3518         proto_item *ti;
3519         proto_tree *tr;
3520         tvbuff_t *cmd_tvb = NULL;
3521
3522         cmd = (sec_vt_command)tvb_get_letohs(tvb, offset);
3523         len = tvb_get_letohs(tvb, offset + 2);
3524         cmd_end = cmd & SEC_VT_COMMAND_END;
3525         cmd_must = cmd & SEC_VT_MUST_PROCESS_COMMAND;
3526         cmd = (sec_vt_command)(cmd & SEC_VT_COMMAND_MASK);
3527
3528         tr = proto_tree_add_subtree_format(tree, tvb, offset, 4 + len,
3529                                            ett_dcerpc_sec_vt_pcontext,
3530                                            &ti, "Command: %s",
3531                                              val_to_str(cmd, sec_vt_command_cmd_vals,
3532                                                         "Unknown (0x%04x)"));
3533
3534         if (cmd_must) {
3535             proto_item_append_text(ti, "!!!");
3536         }
3537         if (cmd_end) {
3538             proto_item_append_text(ti, ", END");
3539         }
3540
3541         proto_tree_add_bitmask(tr, tvb, offset,
3542                                hf_dcerpc_sec_vt_command,
3543                                ett_dcerpc_sec_vt_command,
3544                                sec_vt_command_fields,
3545                                ENC_LITTLE_ENDIAN);
3546         offset += 2;
3547
3548         proto_tree_add_item(tr, hf_dcerpc_sec_vt_command_length, tvb,
3549                             offset, 2, ENC_LITTLE_ENDIAN);
3550         offset += 2;
3551
3552         cmd_tvb = tvb_new_subset_length(tvb, offset, len);
3553         switch (cmd) {
3554         case SEC_VT_COMMAND_BITMASK_1:
3555             dissect_sec_vt_bitmask(tr, cmd_tvb);
3556             break;
3557         case SEC_VT_COMMAND_PCONTEXT:
3558             dissect_sec_vt_pcontext(tr, cmd_tvb);
3559             break;
3560         case SEC_VT_COMMAND_HEADER2:
3561             dissect_sec_vt_header(pinfo, tr, cmd_tvb);
3562             break;
3563         default:
3564             proto_tree_add_item(tr, hf_dcerpc_unknown, cmd_tvb, 0, len, ENC_NA);
3565             break;
3566         }
3567
3568         offset += len;
3569         remaining -= (4 + len);
3570
3571         len_missalign = len & 1;
3572
3573         if (len_missalign) {
3574             int l = 2-len_missalign;
3575             proto_tree_add_item(tr, hf_dcerpc_missalign, tvb, offset, l, ENC_NA);
3576             offset += l;
3577             remaining -= l;
3578         }
3579
3580         if (cmd_end) {
3581             break;
3582         }
3583     }
3584
3585     proto_item_set_end(item, tvb, offset);
3586     return offset;
3587 }
3588
3589 static int
3590 dissect_verification_trailer(packet_info *pinfo, tvbuff_t *tvb, int stub_offset,
3591                              proto_tree *parent_tree, int *signature_offset)
3592 {
3593     volatile int ret = -1;
3594     TRY {
3595         /*
3596          * Even if we found a signature we can't be sure to have a
3597          * valid verification trailer, we're only relatively sure
3598          * if we manage to dissect it completely, otherwise it
3599          * may be part of the real payload. That's why we have
3600          * a try/catch block here.
3601          */
3602         ret = dissect_verification_trailer_impl(pinfo, tvb, stub_offset, parent_tree, signature_offset);
3603     } CATCH_NONFATAL_ERRORS {
3604     } ENDTRY;
3605     return ret;
3606 }
3607
3608 static int
3609 dcerpc_try_handoff(packet_info *pinfo, proto_tree *tree,
3610                    proto_tree *dcerpc_tree,
3611                    tvbuff_t *volatile tvb, gboolean decrypted,
3612                    guint8 *drep, dcerpc_info *info,
3613                    dcerpc_auth_info *auth_info)
3614 {
3615     volatile gint         offset   = 0;
3616     guid_key              key;
3617     dcerpc_dissector_data_t dissector_data;
3618     proto_item           *hidden_item;
3619
3620     /* GUID and UUID are same size, but compiler complains about structure "name" differences */
3621     memcpy(&key.guid, &info->call_data->uuid, sizeof(key.guid));
3622     key.ver = info->call_data->ver;
3623
3624     dissector_data.sub_proto = (dcerpc_uuid_value *)g_hash_table_lookup(dcerpc_uuids, &key);
3625     dissector_data.info = info;
3626     dissector_data.decrypted = decrypted;
3627     dissector_data.auth_info = auth_info;
3628     dissector_data.drep = drep;
3629     dissector_data.dcerpc_tree = dcerpc_tree;
3630
3631     /* Check the dissector table before the hash table.  Hopefully the hash table entries can
3632        all be converted to use dissector table */
3633     if ((dissector_data.sub_proto == NULL) ||
3634         (!dissector_try_guid_new(uuid_dissector_table, &key, tvb, pinfo, tree, FALSE, &dissector_data))) {
3635         /*
3636          * We don't have a dissector for this UUID, or the protocol
3637          * for that UUID is disabled.
3638          */
3639
3640         hidden_item = proto_tree_add_boolean(dcerpc_tree, hf_dcerpc_unknown_if_id,
3641                                              tvb, offset, 0, TRUE);
3642         PROTO_ITEM_SET_HIDDEN(hidden_item);
3643         col_append_fstr(pinfo->cinfo, COL_INFO, " %s V%u",
3644         guids_resolve_guid_to_str(&info->call_data->uuid), info->call_data->ver);
3645
3646         show_stub_data(pinfo, tvb, 0, dcerpc_tree, auth_info, !decrypted);
3647         return -1;
3648     }
3649
3650     tap_queue_packet(dcerpc_tap, pinfo, info);
3651     return 0;
3652 }
3653
3654 static int
3655 dissect_dcerpc_verifier(tvbuff_t *tvb, packet_info *pinfo,
3656                         proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr,
3657                         dcerpc_auth_info *auth_info)
3658 {
3659     int auth_offset;
3660
3661     auth_info->auth_data = NULL;
3662
3663     if (auth_info->auth_size != 0) {
3664         dcerpc_auth_subdissector_fns *auth_fns;
3665         tvbuff_t *auth_tvb;
3666
3667         auth_offset = hdr->frag_len - hdr->auth_len;
3668
3669         auth_tvb = tvb_new_subset(tvb, auth_offset, hdr->auth_len,
3670                                   hdr->auth_len);
3671
3672         auth_info->auth_data = auth_tvb;
3673
3674         if ((auth_fns = get_auth_subdissector_fns(auth_info->auth_level,
3675                                                   auth_info->auth_type))) {
3676             /*
3677              * Catch all bounds-error exceptions, so that even if the
3678              * verifier is bad or we don't have all of it, we still
3679              * show the stub data.
3680              */
3681             TRY {
3682                 dissect_auth_verf(auth_tvb, pinfo, dcerpc_tree, auth_fns,
3683                                   hdr, auth_info);
3684             } CATCH_BOUNDS_ERRORS {
3685                 show_exception(auth_tvb, pinfo, dcerpc_tree, EXCEPT_CODE, GET_MESSAGE);
3686             } ENDTRY;
3687         } else {
3688             proto_tree_add_item(dcerpc_tree, hf_dcerpc_auth_verifier, auth_tvb, 0, hdr->auth_len, ENC_NA);
3689         }
3690     }
3691
3692     return hdr->auth_len;
3693 }
3694
3695 static void
3696 dissect_dcerpc_cn_auth(tvbuff_t *tvb, int stub_offset, packet_info *pinfo,
3697                        proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr,
3698                        gboolean are_credentials, dcerpc_auth_info *auth_info)
3699 {
3700     volatile int offset;
3701
3702     /*
3703      * Initially set auth_level and auth_type to zero to indicate that we
3704      * haven't yet seen any authentication level information.
3705      */
3706     auth_info->auth_level   = 0;
3707     auth_info->auth_type    = 0;
3708     auth_info->auth_size    = 0;
3709     auth_info->auth_pad_len = 0;
3710
3711     /*
3712      * The authentication information is at the *end* of the PDU; in
3713      * request and response PDUs, the request and response stub data
3714      * come before it.
3715      *
3716      * Is there any authentication data (i.e., is the authentication length
3717      * non-zero), and is the authentication length valid (i.e., is it, plus
3718      * 8 bytes for the type/level/pad length/reserved/context id, less than
3719      * or equal to the fragment length minus the starting offset of the
3720      * stub data?)
3721      */
3722
3723     if (hdr->auth_len
3724         && ((hdr->auth_len + 8) <= (hdr->frag_len - stub_offset))) {
3725
3726         /*
3727          * Yes, there is authentication data, and the length is valid.
3728          * Do we have all the bytes of stub data?
3729          * (If not, we'd throw an exception dissecting *that*, so don't
3730          * bother trying to dissect the authentication information and
3731          * throwing another exception there.)
3732          */
3733         offset = hdr->frag_len - (hdr->auth_len + 8);
3734         if (offset == 0 || tvb_offset_exists(tvb, offset - 1)) {
3735             /*
3736              * Either there's no stub data, or the last byte of the stub
3737              * data is present in the captured data, so we shouldn't
3738              * get a BoundsError dissecting the stub data.
3739              *
3740              * Try dissecting the authentication data.
3741              * Catch all exceptions, so that even if the auth info is bad
3742              * or we don't have all of it, we still show the stuff we
3743              * dissect after this, such as stub data.
3744              */
3745             TRY {
3746                 offset = dissect_dcerpc_uint8(tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3747                                               hf_dcerpc_auth_type,
3748                                               &auth_info->auth_type);
3749                 offset = dissect_dcerpc_uint8(tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3750                                               hf_dcerpc_auth_level,
3751                                               &auth_info->auth_level);
3752
3753                 offset = dissect_dcerpc_uint8(tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3754                                               hf_dcerpc_auth_pad_len,
3755                                               &auth_info->auth_pad_len);
3756                 offset = dissect_dcerpc_uint8(tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3757                                               hf_dcerpc_auth_rsrvd, NULL);
3758                 offset = dissect_dcerpc_uint32(tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3759                                                hf_dcerpc_auth_ctx_id, NULL);
3760
3761                 /*
3762                  * Dissect the authentication data.
3763                  */
3764                 if (are_credentials) {
3765                     tvbuff_t *auth_tvb;
3766                     dcerpc_auth_subdissector_fns *auth_fns;
3767
3768                     auth_tvb = tvb_new_subset(tvb, offset,
3769                                               MIN(hdr->auth_len,tvb_reported_length_remaining(tvb, offset)),
3770                                               hdr->auth_len);
3771
3772                     if ((auth_fns = get_auth_subdissector_fns(auth_info->auth_level,
3773                                                               auth_info->auth_type)))
3774                         dissect_auth_verf(auth_tvb, pinfo, dcerpc_tree, auth_fns,
3775                                           hdr, auth_info);
3776                     else
3777                         proto_tree_add_item(dcerpc_tree, hf_dcerpc_auth_credentials, tvb, offset, hdr->auth_len, ENC_NA);
3778                 }
3779
3780                 /* Compute the size of the auth block.  Note that this should not
3781                    include auth padding, since when NTLMSSP encryption is used, the
3782                    padding is actually inside the encrypted stub */
3783                 auth_info->auth_size = hdr->auth_len + 8;
3784             } CATCH_BOUNDS_ERRORS {
3785                 show_exception(tvb, pinfo, dcerpc_tree, EXCEPT_CODE, GET_MESSAGE);
3786             } ENDTRY;
3787         }
3788     }
3789 }
3790
3791
3792 /* We need to hash in the SMB fid number to generate a unique hash table
3793  * key as DCERPC over SMB allows several pipes over the same TCP/IP
3794  * socket.
3795  * We pass this function the transport type here to make sure we only look
3796  * at this function if it came across an SMB pipe.
3797  * Other transports might need to mix in their own extra multiplexing data
3798  * as well in the future.
3799  */
3800
3801 guint64
3802 dcerpc_get_transport_salt(packet_info *pinfo)
3803 {
3804     dcerpc_decode_as_data* decode_data = dcerpc_get_decode_data(pinfo);
3805
3806     switch (decode_data->dcetransporttype) {
3807     case DCE_CN_TRANSPORT_SMBPIPE:
3808         /* DCERPC over smb */
3809         return decode_data->dcetransportsalt;
3810     }
3811
3812     /* Some other transport... */
3813     return 0;
3814 }
3815
3816 void
3817 dcerpc_set_transport_salt(guint64 dcetransportsalt, packet_info *pinfo)
3818 {
3819     dcerpc_decode_as_data* decode_data = dcerpc_get_decode_data(pinfo);
3820
3821     decode_data->dcetransportsalt = dcetransportsalt;
3822 }
3823
3824 /*
3825  * Connection oriented packet types
3826  */
3827
3828 static void
3829 dissect_dcerpc_cn_bind(tvbuff_t *tvb, gint offset, packet_info *pinfo,
3830                        proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr)
3831 {
3832     conversation_t   *conv          = find_or_create_conversation(pinfo);
3833     guint8            num_ctx_items = 0;
3834     guint             i;
3835     guint16           ctx_id;
3836     guint8            num_trans_items;
3837     guint             j;
3838     e_guid_t          if_id;
3839     e_guid_t          trans_id;
3840     guint32           trans_ver;
3841     guint16           if_ver, if_ver_minor;
3842     dcerpc_auth_info  auth_info;
3843     char             *uuid_str;
3844     const char       *uuid_name     = NULL;
3845     proto_item       *iface_item    = NULL;
3846     dcerpc_decode_as_data* decode_data = dcerpc_get_decode_data(pinfo);
3847
3848     offset = dissect_dcerpc_uint16(tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3849                                    hf_dcerpc_cn_max_xmit, NULL);
3850
3851     offset = dissect_dcerpc_uint16(tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3852                                    hf_dcerpc_cn_max_recv, NULL);
3853
3854     offset = dissect_dcerpc_uint32(tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3855                                    hf_dcerpc_cn_assoc_group, NULL);
3856
3857     offset = dissect_dcerpc_uint8(tvb, offset, pinfo, dcerpc_tree, hdr->drep,
3858                                   hf_dcerpc_cn_num_ctx_items, &num_ctx_items);
3859
3860     /* padding */
3861     offset += 3;
3862
3863     col_append_fstr(pinfo->cinfo, COL_INFO, ", %u context items:", num_ctx_items);
3864
3865     for (i = 0; i < num_ctx_items; i++) {
3866         proto_item *ctx_item = NULL;
3867         proto_tree *ctx_tree = NULL, *iface_tree = NULL;
3868         gint ctx_offset = offset;
3869
3870         dissect_dcerpc_uint16(tvb, offset, pinfo, NULL, hdr->drep,
3871                               hf_dcerpc_cn_ctx_id, &ctx_id);
3872
3873         /* save context ID for use with dcerpc_add_conv_to_bind_table() */
3874         /* (if we have multiple contexts, this might cause "decode as"
3875          *  to behave unpredictably) */
3876         decode_data->dcectxid = ctx_id;
3877
3878         if (dcerpc_tree) {
3879             ctx_item = proto_tree_add_item(dcerpc_tree, hf_dcerpc_cn_ctx_item,
3880                                            tvb, offset, 0,
3881                                            ENC_NA);
3882             ctx_tree = proto_item_add_subtree(ctx_item, ett_dcerpc_cn_ctx);
3883         }
3884
3885         offset = dissect_dcerpc_uint16(tvb, offset, pinfo, ctx_tree, hd