packet-dcerpc: let dissect_dcerpc_cn_auth() always dissect the whole auth_info
[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_info = -1;
614 static int hf_dcerpc_auth_credentials = -1;
615 static int hf_dcerpc_fault_stub_data = -1;
616 static int hf_dcerpc_fragment_data = -1;
617 static int hf_dcerpc_cmd_client_ipv4 = -1;
618 static int hf_dcerpc_cmd_client_ipv6 = -1;
619 static int hf_dcerpc_authentication_verifier = -1;
620
621 static const int *dcerpc_cn_bind_trans_btfn_fields[] = {
622         &hf_dcerpc_cn_bind_trans_btfn_01,
623         &hf_dcerpc_cn_bind_trans_btfn_02,
624         NULL
625 };
626
627 static const int *sec_vt_bitmask_fields[] = {
628     &hf_dcerpc_sec_vt_bitmask_sign,
629     NULL
630 };
631
632 static const value_string sec_vt_command_cmd_vals[] = {
633     {1, "BITMASK_1"},
634     {2, "PCONTEXT"},
635     {3, "HEADER2"},
636     {0, NULL}
637 };
638
639 static gint ett_dcerpc = -1;
640 static gint ett_dcerpc_cn_flags = -1;
641 static gint ett_dcerpc_cn_ctx = -1;
642 static gint ett_dcerpc_cn_iface = -1;
643 static gint ett_dcerpc_cn_trans_syntax = -1;
644 static gint ett_dcerpc_cn_trans_btfn = -1;
645 static gint ett_dcerpc_cn_bind_trans_btfn = -1;
646 static gint ett_dcerpc_cn_rts_flags = -1;
647 static gint ett_dcerpc_cn_rts_command = -1;
648 static gint ett_dcerpc_cn_rts_pdu = -1;
649 static gint ett_dcerpc_drep = -1;
650 static gint ett_dcerpc_dg_flags1 = -1;
651 static gint ett_dcerpc_dg_flags2 = -1;
652 static gint ett_dcerpc_pointer_data = -1;
653 static gint ett_dcerpc_string = -1;
654 static gint ett_dcerpc_fragments = -1;
655 static gint ett_dcerpc_fragment = -1;
656 static gint ett_dcerpc_krb5_auth_verf = -1;
657 static gint ett_dcerpc_auth_info = -1;
658 static gint ett_dcerpc_verification_trailer = -1;
659 static gint ett_dcerpc_sec_vt_command = -1;
660 static gint ett_dcerpc_sec_vt_bitmask = -1;
661 static gint ett_dcerpc_sec_vt_pcontext = -1;
662 static gint ett_dcerpc_sec_vt_header = -1;
663 static gint ett_dcerpc_complete_stub_data = -1;
664
665 static expert_field ei_dcerpc_fragment_multiple = EI_INIT;
666 static expert_field ei_dcerpc_cn_status = EI_INIT;
667 static expert_field ei_dcerpc_fragment_reassembled = EI_INIT;
668 static expert_field ei_dcerpc_fragment = EI_INIT;
669 static expert_field ei_dcerpc_no_request_found = EI_INIT;
670 static expert_field ei_dcerpc_context_change = EI_INIT;
671 static expert_field ei_dcerpc_cn_ctx_id_no_bind = EI_INIT;
672 static expert_field ei_dcerpc_bind_not_acknowledged = EI_INIT;
673 static expert_field ei_dcerpc_verifier_unavailable = EI_INIT;
674 static expert_field ei_dcerpc_invalid_pdu_authentication_attempt = EI_INIT;
675 /* Generated from convert_proto_tree_add_text.pl */
676 static expert_field ei_dcerpc_long_frame = EI_INIT;
677 static expert_field ei_dcerpc_cn_rts_command = EI_INIT;
678
679 static const guint8 TRAILER_SIGNATURE[] = {0x8a, 0xe3, 0x13, 0x71, 0x02, 0xf4, 0x36, 0x71};
680 static tvbuff_t *tvb_trailer_signature = NULL;
681
682 static GSList *decode_dcerpc_bindings = NULL;
683 /*
684  * To keep track of ctx_id mappings.
685  *
686  * Every time we see a bind call we update this table.
687  * Note that we always specify a SMB FID. For non-SMB transports this
688  * value is 0.
689  */
690 static GHashTable *dcerpc_binds = NULL;
691
692 typedef struct _dcerpc_bind_key {
693     conversation_t *conv;
694     guint16         ctx_id;
695     guint64         transport_salt;
696 } dcerpc_bind_key;
697
698 typedef struct _dcerpc_bind_value {
699     e_guid_t uuid;
700     guint16  ver;
701     e_guid_t transport;
702 } dcerpc_bind_value;
703
704 /* Extra data for DCERPC handling and tracking of context ids */
705 typedef struct _dcerpc_decode_as_data {
706     guint16 dcectxid;             /**< Context ID (DCERPC-specific) */
707     int     dcetransporttype;     /**< Transport type
708                                     * Value -1 means "not a DCERPC packet"
709                                     */
710     guint64 dcetransportsalt;     /**< fid: if transporttype==DCE_CN_TRANSPORT_SMBPIPE */
711 } dcerpc_decode_as_data;
712
713 static dcerpc_decode_as_data*
714 dcerpc_get_decode_data(packet_info* pinfo)
715 {
716     dcerpc_decode_as_data* data = (dcerpc_decode_as_data*)p_get_proto_data(pinfo->pool, pinfo, proto_dcerpc, 0);
717     if (data == NULL)
718     {
719         data = wmem_new0(pinfo->pool, dcerpc_decode_as_data);
720         data->dcetransporttype = -1;
721         p_add_proto_data(pinfo->pool, pinfo, proto_dcerpc, 0, data);
722     }
723
724     return data;
725 }
726
727 /**
728  *  Registers a conversation/UUID binding association, so that
729  *  we can invoke the proper sub-dissector for a given DCERPC
730  *  conversation.
731  *
732  *  @param binding all values needed to create and bind a new conversation
733  *
734  *  @return Pointer to newly-added UUID/conversation binding.
735  */
736 static struct _dcerpc_bind_value *
737 dcerpc_add_conv_to_bind_table(decode_dcerpc_bind_values_t *binding)
738 {
739     dcerpc_bind_value *bind_value;
740     dcerpc_bind_key   *key;
741     conversation_t    *conv;
742
743     conv = find_conversation(
744         0,
745         &binding->addr_a,
746         &binding->addr_b,
747         binding->ptype,
748         binding->port_a,
749         binding->port_b,
750         0);
751
752     if (!conv) {
753         conv = conversation_new(
754             0,
755             &binding->addr_a,
756             &binding->addr_b,
757             binding->ptype,
758             binding->port_a,
759             binding->port_b,
760             0);
761     }
762
763     bind_value = (dcerpc_bind_value *)wmem_alloc(wmem_file_scope(), sizeof (dcerpc_bind_value));
764     bind_value->uuid = binding->uuid;
765     bind_value->ver = binding->ver;
766     /* For now, assume all DCE/RPC we pick from "decode as" is using
767        standard ndr and not ndr64.
768        We should make this selectable from the dialog in the future
769     */
770     bind_value->transport = uuid_data_repr_proto;
771
772     key = (dcerpc_bind_key *)wmem_alloc(wmem_file_scope(), sizeof (dcerpc_bind_key));
773     key->conv = conv;
774     key->ctx_id = binding->ctx_id;
775     key->transport_salt = binding->transport_salt;
776
777     /* add this entry to the bind table */
778     g_hash_table_insert(dcerpc_binds, key, bind_value);
779
780     return bind_value;
781
782 }
783
784 /* inject one of our bindings into the dcerpc binding table */
785 static void
786 decode_dcerpc_inject_binding(gpointer data, gpointer user_data _U_)
787 {
788     dcerpc_add_conv_to_bind_table((decode_dcerpc_bind_values_t *) data);
789 }
790
791 /* inject all of our bindings into the dcerpc binding table */
792 static void
793 decode_dcerpc_inject_bindings(void) {
794     g_slist_foreach(decode_dcerpc_bindings, decode_dcerpc_inject_binding, NULL /* user_data */);
795 }
796
797 /* free a binding */
798 static void
799 decode_dcerpc_binding_free(void *binding_in)
800 {
801     decode_dcerpc_bind_values_t *binding = (decode_dcerpc_bind_values_t *)binding_in;
802
803     free_address(&binding->addr_a);
804     free_address(&binding->addr_b);
805     if (binding->ifname)
806         g_string_free(binding->ifname, TRUE);
807     g_free(binding);
808 }
809
810 static void
811 dcerpc_decode_as_free(gpointer value)
812 {
813     decode_dcerpc_bind_values_t *binding = (decode_dcerpc_bind_values_t *)value;
814     if (binding != NULL)
815         decode_dcerpc_binding_free(binding);
816 }
817
818 /* removes all bindings */
819 void
820 decode_dcerpc_reset_all(void)
821 {
822     decode_dcerpc_bind_values_t *binding;
823
824     while (decode_dcerpc_bindings) {
825         binding = (decode_dcerpc_bind_values_t *)decode_dcerpc_bindings->data;
826
827         decode_dcerpc_binding_free(binding);
828         decode_dcerpc_bindings = g_slist_remove(
829             decode_dcerpc_bindings,
830             decode_dcerpc_bindings->data);
831     }
832 }
833
834
835 void
836 decode_dcerpc_add_show_list(decode_add_show_list_func func, gpointer user_data)
837 {
838     g_slist_foreach(decode_dcerpc_bindings, func, user_data);
839 }
840
841 static void
842 dcerpc_prompt(packet_info *pinfo, gchar* result)
843 {
844     GString *str = g_string_new("Replace binding between:\r\n"),
845             *address_str = g_string_new("");
846     dcerpc_decode_as_data* decode_data = dcerpc_get_decode_data(pinfo);
847
848     switch (pinfo->ptype) {
849     case(PT_TCP):
850         g_string_append(address_str, "Address: ToBeDone TCP port");
851         break;
852     case(PT_UDP):
853         g_string_append(address_str, "Address: ToBeDone UDP port");
854         break;
855     default:
856         g_string_append(address_str, "Address: ToBeDone Unknown port type");
857     }
858
859     g_string_append_printf(str, "%s: %u\r\n", address_str->str, pinfo->srcport);
860     g_string_append(str, "&\r\n");
861     g_string_append_printf(str, "%s: %u\r\n", address_str->str, pinfo->destport);
862     g_string_append_printf(str, "&\r\nContext ID: %u\r\n", decode_data->dcectxid);
863     g_string_append_printf(str, "&\r\nSMB FID: %"G_GINT64_MODIFIER"u\r\n",
864                            dcerpc_get_transport_salt(pinfo));
865     g_string_append(str, "with:\r\n");
866
867     g_strlcpy(result, str->str, MAX_DECODE_AS_PROMPT_LEN);
868     g_string_free(str, TRUE);
869     g_string_free(address_str, TRUE);
870 }
871
872 static gpointer
873 dcerpc_value(packet_info *pinfo)
874 {
875     decode_dcerpc_bind_values_t *binding;
876     dcerpc_decode_as_data* decode_data = dcerpc_get_decode_data(pinfo);
877
878     /* clone binding */
879     binding = g_new(decode_dcerpc_bind_values_t,1);
880     copy_address(&binding->addr_a, &pinfo->src);
881     copy_address(&binding->addr_b, &pinfo->dst);
882     binding->ptype = pinfo->ptype;
883     binding->port_a = pinfo->srcport;
884     binding->port_b = pinfo->destport;
885     binding->ctx_id = decode_data->dcectxid;
886     binding->transport_salt = dcerpc_get_transport_salt(pinfo);
887     binding->ifname = NULL;
888     /*binding->uuid = NULL;*/
889     binding->ver = 0;
890
891     return binding;
892 }
893
894 struct dcerpc_decode_as_populate
895 {
896     decode_as_add_to_list_func add_to_list;
897     gpointer ui_element;
898 };
899
900 static void
901 decode_dcerpc_add_to_list(gpointer key, gpointer value, gpointer user_data)
902 {
903     struct dcerpc_decode_as_populate* populate = (struct dcerpc_decode_as_populate*)user_data;
904
905     /*guid_key *k = key;*/
906     dcerpc_uuid_value *v = (dcerpc_uuid_value *)value;
907
908     if (strcmp(v->name, "(none)"))
909         populate->add_to_list("DCE-RPC", v->name, key, populate->ui_element);
910 }
911
912 static void
913 dcerpc_populate_list(const gchar *table_name _U_, decode_as_add_to_list_func add_to_list, gpointer ui_element)
914 {
915     struct dcerpc_decode_as_populate populate;
916
917     populate.add_to_list = add_to_list;
918     populate.ui_element = ui_element;
919
920     g_hash_table_foreach(dcerpc_uuids, decode_dcerpc_add_to_list, &populate);
921 }
922
923 /* compare two bindings (except the interface related things, e.g. uuid) */
924 static gint
925 decode_dcerpc_binding_cmp(gconstpointer a, gconstpointer b)
926 {
927     const decode_dcerpc_bind_values_t *binding_a = (const decode_dcerpc_bind_values_t *)a;
928     const decode_dcerpc_bind_values_t *binding_b = (const decode_dcerpc_bind_values_t *)b;
929
930
931     /* don't compare uuid and ver! */
932     if (
933         addresses_equal(&binding_a->addr_a, &binding_b->addr_a) &&
934         addresses_equal(&binding_a->addr_b, &binding_b->addr_b) &&
935         binding_a->ptype == binding_b->ptype &&
936         binding_a->port_a == binding_b->port_a &&
937         binding_a->port_b == binding_b->port_b &&
938         binding_a->ctx_id == binding_b->ctx_id &&
939         binding_a->transport_salt == binding_b->transport_salt)
940     {
941         /* equal */
942         return 0;
943     }
944
945     /* unequal */
946     return 1;
947 }
948
949 /* remove a binding (looking the same way as the given one) */
950 static gboolean
951 decode_dcerpc_binding_reset(const char *name _U_, gconstpointer pattern)
952 {
953     const decode_dcerpc_bind_values_t *binding = (const decode_dcerpc_bind_values_t *)pattern;
954     GSList *le;
955     decode_dcerpc_bind_values_t *old_binding;
956
957     /* find the old binding (if it exists) */
958     le = g_slist_find_custom(decode_dcerpc_bindings,
959                                              binding,
960                                              decode_dcerpc_binding_cmp);
961     if (le == NULL)
962         return FALSE;
963
964     old_binding = (decode_dcerpc_bind_values_t *)le->data;
965
966     decode_dcerpc_bindings = g_slist_remove(decode_dcerpc_bindings, le->data);
967
968     free_address(&old_binding->addr_a);
969     free_address(&old_binding->addr_b);
970     g_string_free(old_binding->ifname, TRUE);
971     g_free(old_binding);
972     return FALSE;
973 }
974
975 static gboolean
976 dcerpc_decode_as_change(const char *name, gconstpointer pattern, gpointer handle, gchar* list_name)
977 {
978     decode_dcerpc_bind_values_t *binding = (decode_dcerpc_bind_values_t*)pattern;
979     decode_dcerpc_bind_values_t *stored_binding;
980     guid_key     *key = *((guid_key**)handle);
981
982
983     binding->ifname = g_string_new(list_name);
984     binding->uuid = key->guid;
985     binding->ver = key->ver;
986
987     /* remove a probably existing old binding */
988     decode_dcerpc_binding_reset(name, binding);
989
990     /* clone the new binding and append it to the list */
991     stored_binding = g_new(decode_dcerpc_bind_values_t,1);
992     *stored_binding = *binding;
993     copy_address(&stored_binding->addr_a, &binding->addr_a);
994     copy_address(&stored_binding->addr_b, &binding->addr_b);
995     stored_binding->ifname = g_string_new(binding->ifname->str);
996
997     decode_dcerpc_bindings = g_slist_append (decode_dcerpc_bindings, stored_binding);
998
999     return FALSE;
1000 }
1001
1002 static const fragment_items dcerpc_frag_items = {
1003     &ett_dcerpc_fragments,
1004     &ett_dcerpc_fragment,
1005
1006     &hf_dcerpc_fragments,
1007     &hf_dcerpc_fragment,
1008     &hf_dcerpc_fragment_overlap,
1009     &hf_dcerpc_fragment_overlap_conflict,
1010     &hf_dcerpc_fragment_multiple_tails,
1011     &hf_dcerpc_fragment_too_long_fragment,
1012     &hf_dcerpc_fragment_error,
1013     &hf_dcerpc_fragment_count,
1014     NULL,
1015     &hf_dcerpc_reassembled_length,
1016     /* Reassembled data field */
1017     NULL,
1018     "fragments"
1019 };
1020
1021 /* list of hooks to be called when init_protocols is done */
1022 GHookList dcerpc_hooks_init_protos;
1023
1024 /* try to desegment big DCE/RPC packets over TCP? */
1025 static gboolean dcerpc_cn_desegment = TRUE;
1026
1027 /* reassemble DCE/RPC fragments */
1028 /* reassembly of cl dcerpc fragments will not work for the case where ONE frame
1029    might contain multiple dcerpc fragments for different PDUs.
1030    this case would be so unusual/weird so if you got captures like that:
1031    too bad
1032
1033    reassembly of co dcerpc fragments will not work for the case where TCP/SMB frames
1034    are coming in out of sequence, but that will hurt in a lot of other places as well.
1035 */
1036 static gboolean dcerpc_reassemble = TRUE;
1037 static reassembly_table dcerpc_co_reassembly_table;
1038 static reassembly_table dcerpc_cl_reassembly_table;
1039
1040 typedef struct _dcerpc_fragment_key {
1041     address src;
1042     address dst;
1043     guint32 id;
1044     e_guid_t act_id;
1045 } dcerpc_fragment_key;
1046
1047 static guint
1048 dcerpc_fragment_hash(gconstpointer k)
1049 {
1050     const dcerpc_fragment_key* key = (const dcerpc_fragment_key*) k;
1051     guint hash_val;
1052
1053     hash_val = 0;
1054
1055     hash_val += key->id;
1056     hash_val += key->act_id.data1;
1057     hash_val += key->act_id.data2 << 16;
1058     hash_val += key->act_id.data3;
1059
1060     return hash_val;
1061 }
1062
1063 static gint
1064 dcerpc_fragment_equal(gconstpointer k1, gconstpointer k2)
1065 {
1066     const dcerpc_fragment_key* key1 = (const dcerpc_fragment_key*) k1;
1067     const dcerpc_fragment_key* key2 = (const dcerpc_fragment_key*) k2;
1068
1069     /*key.id is the first item to compare since item is most
1070       likely to differ between sessions, thus shortcircuiting
1071       the comparison of addresses.
1072     */
1073     return (((key1->id == key2->id)
1074              && (addresses_equal(&key1->src, &key2->src))
1075              && (addresses_equal(&key1->dst, &key2->dst))
1076              && (memcmp (&key1->act_id, &key2->act_id, sizeof (e_guid_t)) == 0))
1077             ? TRUE : FALSE);
1078 }
1079
1080 /* allocate a persistent dcerpc fragment key to insert in the hash */
1081 static void *
1082 dcerpc_fragment_temporary_key(const packet_info *pinfo, const guint32 id,
1083                               const void *data)
1084 {
1085     dcerpc_fragment_key *key = g_slice_new(dcerpc_fragment_key);
1086     const e_dce_dg_common_hdr_t *hdr = (const e_dce_dg_common_hdr_t *)data;
1087
1088     copy_address_shallow(&key->src, &pinfo->src);
1089     copy_address_shallow(&key->dst, &pinfo->dst);
1090     key->id = id;
1091     key->act_id = hdr->act_id;
1092
1093     return key;
1094 }
1095
1096 /* allocate a persistent dcerpc fragment key to insert in the hash */
1097 static void *
1098 dcerpc_fragment_persistent_key(const packet_info *pinfo, const guint32 id,
1099                                const void *data)
1100 {
1101     dcerpc_fragment_key *key = g_slice_new(dcerpc_fragment_key);
1102     const e_dce_dg_common_hdr_t *hdr = (const e_dce_dg_common_hdr_t *)data;
1103
1104     copy_address(&key->src, &pinfo->src);
1105     copy_address(&key->dst, &pinfo->dst);
1106     key->id = id;
1107     key->act_id = hdr->act_id;
1108
1109     return key;
1110 }
1111
1112 static void
1113 dcerpc_fragment_free_temporary_key(gpointer ptr)
1114 {
1115     dcerpc_fragment_key *key = (dcerpc_fragment_key *)ptr;
1116
1117     if (key)
1118         g_slice_free(dcerpc_fragment_key, key);
1119 }
1120
1121 static void
1122 dcerpc_fragment_free_persistent_key(gpointer ptr)
1123 {
1124     dcerpc_fragment_key *key = (dcerpc_fragment_key *)ptr;
1125
1126     if (key) {
1127         /*
1128          * Free up the copies of the addresses from the old key.
1129          */
1130         free_address(&key->src);
1131         free_address(&key->dst);
1132
1133         g_slice_free(dcerpc_fragment_key, key);
1134     }
1135 }
1136
1137 static const reassembly_table_functions dcerpc_cl_reassembly_table_functions = {
1138     dcerpc_fragment_hash,
1139     dcerpc_fragment_equal,
1140     dcerpc_fragment_temporary_key,
1141     dcerpc_fragment_persistent_key,
1142     dcerpc_fragment_free_temporary_key,
1143     dcerpc_fragment_free_persistent_key
1144 };
1145
1146 static void
1147 dcerpc_reassemble_init(void)
1148 {
1149     /*
1150      * XXX - addresses_ports_reassembly_table_functions?
1151      * Or can a single connection-oriented DCE RPC session persist
1152      * over multiple transport layer connections?
1153      */
1154     reassembly_table_init(&dcerpc_co_reassembly_table,
1155                           &addresses_reassembly_table_functions);
1156     reassembly_table_init(&dcerpc_cl_reassembly_table,
1157                           &dcerpc_cl_reassembly_table_functions);
1158 }
1159
1160 /*
1161  * Authentication subdissectors.  Used to dissect authentication blobs in
1162  * DCERPC binds, requests and responses.
1163  */
1164
1165 typedef struct _dcerpc_auth_subdissector {
1166     guint8 auth_level;
1167     guint8 auth_type;
1168     dcerpc_auth_subdissector_fns auth_fns;
1169 } dcerpc_auth_subdissector;
1170
1171 static GSList *dcerpc_auth_subdissector_list;
1172
1173 static dcerpc_auth_subdissector_fns *get_auth_subdissector_fns(
1174     guint8 auth_level, guint8 auth_type)
1175 {
1176     gpointer data;
1177     int      i;
1178
1179     for (i = 0; (data = g_slist_nth_data(dcerpc_auth_subdissector_list, i)); i++) {
1180         dcerpc_auth_subdissector *asd = (dcerpc_auth_subdissector *)data;
1181
1182         if ((asd->auth_level == auth_level) &&
1183             (asd->auth_type == auth_type))
1184             return &asd->auth_fns;
1185     }
1186
1187     return NULL;
1188 }
1189
1190 void register_dcerpc_auth_subdissector(guint8 auth_level, guint8 auth_type,
1191                                        dcerpc_auth_subdissector_fns *fns)
1192 {
1193     dcerpc_auth_subdissector *d;
1194
1195     if (get_auth_subdissector_fns(auth_level, auth_type))
1196         return;
1197
1198     d = (dcerpc_auth_subdissector *)g_malloc(sizeof(dcerpc_auth_subdissector));
1199
1200     d->auth_level = auth_level;
1201     d->auth_type = auth_type;
1202     memcpy(&d->auth_fns, fns, sizeof(dcerpc_auth_subdissector_fns));
1203
1204     dcerpc_auth_subdissector_list = g_slist_append(dcerpc_auth_subdissector_list, d);
1205 }
1206
1207 /* Hand off verifier data to a registered dissector */
1208
1209 static void dissect_auth_verf(packet_info *pinfo,
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     if (auth_info == NULL) {
1221         return;
1222     }
1223
1224     if (auth_info->auth_fns == NULL) {
1225         return;
1226     }
1227
1228     switch (hdr->ptype) {
1229     case PDU_BIND:
1230     case PDU_ALTER:
1231         fn = auth_info->auth_fns->bind_fn;
1232         break;
1233     case PDU_BIND_ACK:
1234     case PDU_ALTER_ACK:
1235         fn = auth_info->auth_fns->bind_ack_fn;
1236         break;
1237     case PDU_AUTH3:
1238         fn = auth_info->auth_fns->auth3_fn;
1239         break;
1240     case PDU_REQ:
1241     case PDU_CO_CANCEL:
1242     case PDU_ORPHANED:
1243         fn = auth_info->auth_fns->req_verf_fn;
1244         break;
1245     case PDU_RESP:
1246     case PDU_FAULT:
1247         fn = auth_info->auth_fns->resp_verf_fn;
1248         break;
1249
1250     default:
1251         /* Don't know how to handle authentication data in this
1252            pdu type. */
1253         proto_tree_add_expert_format(auth_info->auth_tree, pinfo,
1254                                      &ei_dcerpc_invalid_pdu_authentication_attempt,
1255                                      auth_info->auth_tvb, 0, 0,
1256                                      "Don't know how to dissect authentication data for %s pdu type",
1257                                      val_to_str(hdr->ptype, pckt_vals, "Unknown (%u)"));
1258         return;
1259         break;
1260     }
1261
1262     if (fn)
1263         fn(auth_info->auth_tvb, 0, pinfo, auth_info->auth_tree, &di, hdr->drep);
1264     else
1265         proto_tree_add_expert_format(auth_info->auth_tree, pinfo,
1266                                      &ei_dcerpc_verifier_unavailable,
1267                                      auth_info->auth_tvb, 0, hdr->auth_len,
1268                                      "%s Verifier unavailable",
1269                                      val_to_str(auth_info->auth_type,
1270                                                 authn_protocol_vals,
1271                                                 "Unknown (%u)"));
1272 }
1273
1274 static proto_item*
1275 proto_tree_add_dcerpc_drep(proto_tree *tree, tvbuff_t *tvb, int offset, guint8 drep[], int drep_len)
1276 {
1277     const guint8 byteorder = drep[0] >> 4;
1278     const guint8 character = drep[0] & 0x0f;
1279     const guint8 fp = drep[1];
1280     proto_item *ti = proto_tree_add_bytes(tree, hf_dcerpc_drep, tvb, offset, drep_len, drep);
1281     proto_tree *tr = proto_item_add_subtree(ti, ett_dcerpc_drep);
1282
1283     proto_tree_add_uint(tr, hf_dcerpc_drep_byteorder, tvb, offset, 1, byteorder);
1284     proto_tree_add_uint(tr, hf_dcerpc_drep_character, tvb, offset, 1, character);
1285     proto_tree_add_uint(tr, hf_dcerpc_drep_fp, tvb, offset+1, 1, fp);
1286
1287     proto_item_append_text(ti, " (Order: %s, Char: %s, Float: %s)",
1288                            val_to_str(byteorder, drep_byteorder_vals, "Unknown (%u)"),
1289                            val_to_str(character, drep_character_vals, "Unknown (%u)"),
1290                            val_to_str(fp, drep_fp_vals, "Unknown (%u)"));
1291     return ti;
1292 }
1293
1294 /* Hand off payload data to a registered dissector */
1295
1296 static tvbuff_t *decode_encrypted_data(tvbuff_t *data_tvb,
1297                                        packet_info *pinfo,
1298                                        e_dce_cn_common_hdr_t *hdr,
1299                                        dcerpc_auth_info *auth_info)
1300 {
1301     dcerpc_decode_data_fnct_t *fn = NULL;
1302
1303     if (auth_info == NULL)
1304         return NULL;
1305
1306     if (auth_info->auth_fns == NULL)
1307         return NULL;
1308
1309     switch (hdr->ptype) {
1310     case PDU_REQ:
1311         fn = auth_info->auth_fns->req_data_fn;
1312         break;
1313     case PDU_RESP:
1314     case PDU_FAULT:
1315         fn = auth_info->auth_fns->resp_data_fn;
1316         break;
1317     }
1318
1319     if (fn)
1320         return fn(data_tvb, auth_info->auth_tvb, 0, pinfo, auth_info);
1321
1322     return NULL;
1323 }
1324
1325 typedef struct _dcerpc_dissector_data
1326 {
1327     dcerpc_uuid_value *sub_proto;
1328     dcerpc_info *info;
1329     gboolean decrypted;
1330     dcerpc_auth_info *auth_info;
1331     guint8 *drep;
1332     proto_tree *dcerpc_tree;
1333 } dcerpc_dissector_data_t;
1334
1335 /*
1336  * Subdissectors
1337  */
1338
1339 dissector_table_t   uuid_dissector_table;
1340
1341 /* the registered subdissectors */
1342 GHashTable *dcerpc_uuids = NULL;
1343
1344 static gint
1345 dcerpc_uuid_equal(gconstpointer k1, gconstpointer k2)
1346 {
1347     const guid_key *key1 = (const guid_key *)k1;
1348     const guid_key *key2 = (const guid_key *)k2;
1349     return ((memcmp(&key1->guid, &key2->guid, sizeof (e_guid_t)) == 0)
1350             && (key1->ver == key2->ver));
1351 }
1352
1353 static guint
1354 dcerpc_uuid_hash(gconstpointer k)
1355 {
1356     const guid_key *key = (const guid_key *)k;
1357     /* This isn't perfect, but the Data1 part of these is almost always
1358        unique. */
1359     return key->guid.data1;
1360 }
1361
1362
1363 static int
1364 dissect_verification_trailer(packet_info *pinfo, tvbuff_t *tvb, int stub_offset,
1365                              proto_tree *parent_tree, int *signature_offset);
1366
1367 static void
1368 show_stub_data(packet_info *pinfo, tvbuff_t *tvb, gint offset, proto_tree *dcerpc_tree,
1369                dcerpc_auth_info *auth_info, gboolean is_encrypted)
1370 {
1371     int   length, plain_length, auth_pad_len;
1372     guint auth_pad_offset;
1373
1374     /*
1375      * We don't show stub data unless we have some in the tvbuff;
1376      * however, in the protocol tree, we show, as the number of
1377      * bytes, the reported number of bytes, not the number of bytes
1378      * that happen to be in the tvbuff.
1379      */
1380     if (tvb_reported_length_remaining(tvb, offset) > 0) {
1381         auth_pad_len = auth_info?auth_info->auth_pad_len:0;
1382         length = tvb_reported_length_remaining(tvb, offset);
1383
1384         /* if auth_pad_len is larger than length then we ignore auth_pad_len totally */
1385         plain_length = length - auth_pad_len;
1386         if (plain_length < 1) {
1387             plain_length = length;
1388             auth_pad_len = 0;
1389         }
1390         auth_pad_offset = offset + plain_length;
1391
1392         if ((auth_info != NULL) &&
1393             (auth_info->auth_level == DCE_C_AUTHN_LEVEL_PKT_PRIVACY)) {
1394             if (is_encrypted) {
1395                 proto_tree_add_item(dcerpc_tree, hf_dcerpc_encrypted_stub_data, tvb, offset, length, ENC_NA);
1396                 /* is the padding is still inside the encrypted blob, don't display it explicit */
1397                 auth_pad_len = 0;
1398             } else {
1399                 proto_tree_add_item(dcerpc_tree, hf_dcerpc_decrypted_stub_data, tvb, offset, plain_length, ENC_NA);
1400                 dissect_verification_trailer(pinfo, tvb, offset, dcerpc_tree, NULL);
1401             }
1402         } else {
1403             proto_tree_add_item(dcerpc_tree, hf_dcerpc_stub_data, tvb, offset, plain_length, ENC_NA);
1404             dissect_verification_trailer(pinfo, tvb, offset, dcerpc_tree, NULL);
1405         }
1406         /* If there is auth padding at the end of the stub, display it */
1407         if (auth_pad_len != 0) {
1408             proto_tree_add_item(dcerpc_tree, hf_dcerpc_auth_padding, tvb, auth_pad_offset, auth_pad_len, ENC_NA);
1409         }
1410     }
1411 }
1412
1413 static int
1414 dissect_dcerpc_guid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1415 {
1416     dcerpc_dissector_data_t* dissector_data = (dcerpc_dissector_data_t*)data;
1417     const gchar          *name     = NULL;
1418     dcerpc_sub_dissector *proc;
1419     int (*volatile sub_dissect)(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) = NULL;
1420     proto_item           *pi, *sub_item;
1421     proto_tree           *sub_tree;
1422     volatile guint        length;
1423     guint                 reported_length;
1424     volatile gint         offset   = 0;
1425     tvbuff_t *volatile    stub_tvb;
1426     tvbuff_t *volatile    payload_tvb = NULL;
1427     volatile guint        auth_pad_len;
1428     volatile int          auth_pad_offset;
1429     const char *volatile  saved_proto;
1430
1431     for (proc = dissector_data->sub_proto->procs; proc->name; proc++) {
1432         if (proc->num == dissector_data->info->call_data->opnum) {
1433             name = proc->name;
1434             break;
1435         }
1436     }
1437
1438     col_set_str(pinfo->cinfo, COL_PROTOCOL, dissector_data->sub_proto->name);
1439
1440     if (!name)
1441         col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown operation %u %s",
1442                      dissector_data->info->call_data->opnum,
1443                      (dissector_data->info->ptype == PDU_REQ) ? "request" : "response");
1444     else
1445         col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s",
1446                      name, (dissector_data->info->ptype == PDU_REQ) ? "request" : "response");
1447
1448     sub_dissect = (dissector_data->info->ptype == PDU_REQ) ?
1449         proc->dissect_rqst : proc->dissect_resp;
1450
1451     sub_item = proto_tree_add_item(tree, dissector_data->sub_proto->proto_id,
1452                                        tvb,//(decrypted_tvb != NULL)?decrypted_tvb:tvb,
1453                                        0, -1, ENC_NA);
1454     sub_tree = proto_item_add_subtree(sub_item, dissector_data->sub_proto->ett);
1455     if (!name)
1456         proto_item_append_text(sub_item, ", unknown operation %u",
1457                                 dissector_data->info->call_data->opnum);
1458     else
1459         proto_item_append_text(sub_item, ", %s", name);
1460
1461     if (tree) {
1462         /*
1463          * Put the operation number into the tree along with
1464          * the operation's name.
1465          */
1466         if (dissector_data->sub_proto->opnum_hf != -1)
1467             proto_tree_add_uint_format(sub_tree, dissector_data->sub_proto->opnum_hf,
1468                                        tvb, 0, 0, dissector_data->info->call_data->opnum,
1469                                        "Operation: %s (%u)",
1470                                        name ? name : "Unknown operation",
1471                                        dissector_data->info->call_data->opnum);
1472         else
1473             proto_tree_add_uint_format_value(sub_tree, hf_dcerpc_op, tvb,
1474                                        0, 0, dissector_data->info->call_data->opnum,
1475                                        "%s (%u)",
1476                                        name ? name : "Unknown operation",
1477                                        dissector_data->info->call_data->opnum);
1478
1479         if ((dissector_data->info->ptype == PDU_REQ) && (dissector_data->info->call_data->rep_frame != 0)) {
1480             pi = proto_tree_add_uint(sub_tree, hf_dcerpc_response_in,
1481                                      tvb, 0, 0, dissector_data->info->call_data->rep_frame);
1482             PROTO_ITEM_SET_GENERATED(pi);
1483         }
1484         if ((dissector_data->info->ptype == PDU_RESP) && (dissector_data->info->call_data->req_frame != 0)) {
1485             pi = proto_tree_add_uint(sub_tree, hf_dcerpc_request_in,
1486                                      tvb, 0, 0, dissector_data->info->call_data->req_frame);
1487             PROTO_ITEM_SET_GENERATED(pi);
1488         }
1489     } /* tree */
1490
1491     if (!dissector_data->decrypted || (sub_dissect == NULL))
1492     {
1493         show_stub_data(pinfo, tvb, 0, sub_tree, dissector_data->auth_info, !dissector_data->decrypted);
1494         return tvb_captured_length(tvb);
1495     }
1496
1497     /* Either there was no encryption or we successfully decrypted
1498        the encrypted payload. */
1499
1500     /* We have a subdissector - call it. */
1501     saved_proto          = pinfo->current_proto;
1502     pinfo->current_proto = dissector_data->sub_proto->name;
1503
1504     init_ndr_pointer_list(dissector_data->info);
1505
1506     length = tvb_captured_length(tvb);
1507     reported_length = tvb_reported_length(tvb);
1508
1509     /*
1510      * Remove the authentication padding from the stub data.
1511      */
1512     if ((dissector_data->auth_info != NULL) && (dissector_data->auth_info->auth_pad_len != 0)) {
1513         if (reported_length >= dissector_data->auth_info->auth_pad_len) {
1514             /*
1515              * OK, the padding length isn't so big that it
1516              * exceeds the stub length.  Trim the reported
1517              * length of the tvbuff.
1518              */
1519             reported_length -= dissector_data->auth_info->auth_pad_len;
1520
1521             /*
1522              * If that exceeds the actual amount of data in
1523              * the tvbuff (which means we have at least one
1524              * byte of authentication padding in the tvbuff),
1525              * trim the actual amount.
1526              */
1527             if (length > reported_length)
1528                 length = reported_length;
1529
1530             stub_tvb = tvb_new_subset(tvb, 0, length, reported_length);
1531             auth_pad_len = dissector_data->auth_info->auth_pad_len;
1532             auth_pad_offset = reported_length;
1533         } else {
1534             /*
1535              * The padding length exceeds the stub length.
1536              * Don't bother dissecting the stub, trim the padding
1537              * length to what's in the stub data, and show the
1538              * entire stub as authentication padding.
1539              */
1540             stub_tvb = NULL;
1541             auth_pad_len = reported_length;
1542             auth_pad_offset = 0;
1543             length = 0;
1544         }
1545     } else {
1546         /*
1547          * No authentication padding.
1548          */
1549         stub_tvb = tvb;
1550         auth_pad_len = 0;
1551         auth_pad_offset = 0;
1552     }
1553
1554     if (sub_item) {
1555         proto_item_set_len(sub_item, length);
1556     }
1557
1558     if (stub_tvb != NULL) {
1559         /*
1560          * Catch all exceptions other than BoundsError, so that even
1561          * if the stub data is bad, we still show the authentication
1562          * padding, if any.
1563          *
1564          * If we get BoundsError, it means the frame was cut short
1565          * by a snapshot length, so there's nothing more to
1566          * dissect; just re-throw that exception.
1567          */
1568         TRY {
1569             proto_tree *stub_tree = NULL;
1570             int remaining;
1571             int trailer_start_offset = -1;
1572             int trailer_end_offset = -1;
1573
1574             stub_tree = proto_tree_add_subtree_format(dissector_data->dcerpc_tree,
1575                                 stub_tvb, 0, length,
1576                                 ett_dcerpc_complete_stub_data, NULL,
1577                                 "Complete stub data (%d byte%s)", length,
1578                                 plurality(length, "", "s"));
1579             trailer_end_offset = dissect_verification_trailer(pinfo,
1580                                                     stub_tvb, 0,
1581                                                     stub_tree,
1582                                                     &trailer_start_offset);
1583
1584             if (trailer_end_offset != -1) {
1585                 remaining = tvb_captured_length_remaining(stub_tvb,
1586                                                     trailer_start_offset);
1587                 length -= remaining;
1588
1589                 if (sub_item) {
1590                         proto_item_set_len(sub_item, length);
1591                 }
1592             } else {
1593                 proto_item *payload_item;
1594
1595                 payload_item = proto_tree_add_item(stub_tree,
1596                                     hf_dcerpc_payload_stub_data,
1597                                     stub_tvb, 0, length, ENC_NA);
1598                 proto_item_append_text(payload_item, " (%d byte%s)",
1599                                         length, plurality(length, "", "s"));
1600             }
1601
1602             payload_tvb = tvb_new_subset(stub_tvb, 0, length, length);
1603             offset = sub_dissect(payload_tvb, 0, pinfo, sub_tree,
1604                             dissector_data->info, dissector_data->drep);
1605
1606             /* If we have a subdissector and it didn't dissect all
1607                 data in the tvb, make a note of it. */
1608             remaining = tvb_reported_length_remaining(stub_tvb, offset);
1609
1610             if (trailer_end_offset != -1) {
1611                 if (offset > trailer_start_offset) {
1612                     remaining = offset - trailer_start_offset;
1613                     proto_tree_add_item(sub_tree, hf_dcerpc_stub_data_with_sec_vt,
1614                                         stub_tvb, trailer_start_offset, remaining, ENC_NA);
1615                     col_append_fstr(pinfo->cinfo, COL_INFO,
1616                                         "[Payload with Verification Trailer (%d byte%s)]",
1617                                     remaining,
1618                                     plurality(remaining, "", "s"));
1619                     remaining = 0;
1620                 } else {
1621                     remaining = trailer_start_offset - offset;
1622                 }
1623             }
1624
1625             if (remaining > 0) {
1626                 proto_tree_add_expert(sub_tree, pinfo, &ei_dcerpc_long_frame, stub_tvb, offset, remaining);
1627                 col_append_fstr(pinfo->cinfo, COL_INFO,
1628                                     "[Long frame (%d byte%s)]",
1629                                     remaining,
1630                                     plurality(remaining, "", "s"));
1631             }
1632         } CATCH_NONFATAL_ERRORS {
1633             /*
1634              * Somebody threw an exception that means that there
1635              * was a problem dissecting the payload; that means
1636              * that a dissector was found, so we don't need to
1637              * dissect the payload as data or update the protocol
1638              * or info columns.
1639              *
1640              * Just show the exception and then drive on to show
1641              * the authentication padding.
1642              */
1643             show_exception(stub_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
1644         } ENDTRY;
1645     }
1646
1647     /* If there is auth padding at the end of the stub, display it */
1648     if (auth_pad_len != 0) {
1649         proto_tree_add_item(sub_tree, hf_dcerpc_auth_padding, tvb, auth_pad_offset, auth_pad_len, ENC_NA);
1650     }
1651
1652     pinfo->current_proto = saved_proto;
1653
1654     return tvb_captured_length(tvb);
1655 }
1656
1657 void
1658 dcerpc_init_uuid(int proto, int ett, e_guid_t *uuid, guint16 ver,
1659                  dcerpc_sub_dissector *procs, int opnum_hf)
1660 {
1661     guid_key   *key         = (guid_key *)g_malloc(sizeof (*key));
1662     dcerpc_uuid_value *value       = (dcerpc_uuid_value *)g_malloc(sizeof (*value));
1663     header_field_info *hf_info;
1664     module_t          *samr_module;
1665     const char        *filter_name = proto_get_protocol_filter_name(proto);
1666     dissector_handle_t guid_handle;
1667
1668     key->guid = *uuid;
1669     key->ver = ver;
1670
1671     value->proto    = find_protocol_by_id(proto);
1672     value->proto_id = proto;
1673     value->ett      = ett;
1674     value->name     = proto_get_protocol_short_name(value->proto);
1675     value->procs    = procs;
1676     value->opnum_hf = opnum_hf;
1677
1678     g_hash_table_insert(dcerpc_uuids, key, value);
1679
1680     hf_info = proto_registrar_get_nth(opnum_hf);
1681     hf_info->strings = value_string_from_subdissectors(procs);
1682
1683     /* Register the GUID with the dissector table */
1684     guid_handle = create_dissector_handle( dissect_dcerpc_guid, proto);
1685     dissector_add_guid( "dcerpc.uuid", key, guid_handle );
1686
1687     /* add this GUID to the global name resolving */
1688     guids_add_uuid(uuid, proto_get_protocol_short_name(value->proto));
1689
1690     /* Register the samr.nt_password preference as obsolete */
1691     /* This should be in packet-dcerpc-samr.c */
1692     if (strcmp(filter_name, "samr") == 0) {
1693         samr_module = prefs_register_protocol(proto, NULL);
1694         prefs_register_obsolete_preference(samr_module, "nt_password");
1695     }
1696 }
1697
1698 /* Function to find the name of a registered protocol
1699  * or NULL if the protocol/version is not known to wireshark.
1700  */
1701 const char *
1702 dcerpc_get_proto_name(e_guid_t *uuid, guint16 ver)
1703 {
1704     dissector_handle_t handle;
1705     guid_key    key;
1706
1707     key.guid = *uuid;
1708     key.ver = ver;
1709
1710     handle = dissector_get_guid_handle(uuid_dissector_table, &key);
1711     if (handle == NULL) {
1712         return NULL;
1713     }
1714
1715     return dissector_handle_get_short_name(handle);
1716 }
1717
1718 /* Function to find the opnum hf-field of a registered protocol
1719  * or -1 if the protocol/version is not known to wireshark.
1720  */
1721 int
1722 dcerpc_get_proto_hf_opnum(e_guid_t *uuid, guint16 ver)
1723 {
1724     guid_key    key;
1725     dcerpc_uuid_value *sub_proto;
1726
1727     key.guid = *uuid;
1728     key.ver = ver;
1729     if (!(sub_proto = (dcerpc_uuid_value *)g_hash_table_lookup(dcerpc_uuids, &key))) {
1730         return -1;
1731     }
1732     return sub_proto->opnum_hf;
1733 }
1734
1735 /* Create a value_string consisting of DCERPC opnum and name from a
1736    subdissector array. */
1737
1738 value_string *value_string_from_subdissectors(dcerpc_sub_dissector *sd)
1739 {
1740     value_string *vs     = NULL;
1741     int           i;
1742     int           num_sd = 0;
1743
1744 again:
1745     for (i = 0; sd[i].name; i++) {
1746         if (vs) {
1747             vs[i].value = sd[i].num;
1748             vs[i].strptr = sd[i].name;
1749         } else
1750             num_sd++;
1751     }
1752
1753     if (!vs) {
1754         vs = (value_string *)wmem_alloc(wmem_epan_scope(), (num_sd + 1) * sizeof(value_string));
1755         goto again;
1756     }
1757
1758     vs[num_sd].value = 0;
1759     vs[num_sd].strptr = NULL;
1760
1761     return vs;
1762 }
1763
1764 /* Function to find the subdissector table of a registered protocol
1765  * or NULL if the protocol/version is not known to wireshark.
1766  */
1767 dcerpc_sub_dissector *
1768 dcerpc_get_proto_sub_dissector(e_guid_t *uuid, guint16 ver)
1769 {
1770     guid_key    key;
1771     dcerpc_uuid_value *sub_proto;
1772
1773     key.guid = *uuid;
1774     key.ver = ver;
1775     if (!(sub_proto = (dcerpc_uuid_value *)g_hash_table_lookup(dcerpc_uuids, &key))) {
1776         return NULL;
1777     }
1778     return sub_proto->procs;
1779 }
1780
1781
1782
1783 static gint
1784 dcerpc_bind_equal(gconstpointer k1, gconstpointer k2)
1785 {
1786     const dcerpc_bind_key *key1 = (const dcerpc_bind_key *)k1;
1787     const dcerpc_bind_key *key2 = (const dcerpc_bind_key *)k2;
1788     return ((key1->conv == key2->conv)
1789             && (key1->ctx_id == key2->ctx_id)
1790             && (key1->transport_salt == key2->transport_salt));
1791 }
1792
1793 static guint
1794 dcerpc_bind_hash(gconstpointer k)
1795 {
1796     const dcerpc_bind_key *key = (const dcerpc_bind_key *)k;
1797     guint hash;
1798
1799     hash = GPOINTER_TO_UINT(key->conv);
1800     hash += key->ctx_id;
1801     /* sizeof(guint) might be smaller than sizeof(guint64) */
1802     hash += (guint)key->transport_salt;
1803     hash += (guint)(key->transport_salt << sizeof(guint));
1804
1805     return hash;
1806 }
1807
1808 /*
1809  * To keep track of callid mappings.  Should really use some generic
1810  * conversation support instead.
1811  */
1812 static GHashTable *dcerpc_cn_calls = NULL;
1813 static GHashTable *dcerpc_dg_calls = NULL;
1814
1815 typedef struct _dcerpc_cn_call_key {
1816     conversation_t *conv;
1817     guint32 call_id;
1818     guint64 transport_salt;
1819 } dcerpc_cn_call_key;
1820
1821 typedef struct _dcerpc_dg_call_key {
1822     conversation_t *conv;
1823     guint32         seqnum;
1824     e_guid_t        act_id ;
1825 } dcerpc_dg_call_key;
1826
1827
1828 static gint
1829 dcerpc_cn_call_equal(gconstpointer k1, gconstpointer k2)
1830 {
1831     const dcerpc_cn_call_key *key1 = (const dcerpc_cn_call_key *)k1;
1832     const dcerpc_cn_call_key *key2 = (const dcerpc_cn_call_key *)k2;
1833     return ((key1->conv == key2->conv)
1834             && (key1->call_id == key2->call_id)
1835             && (key1->transport_salt == key2->transport_salt));
1836 }
1837
1838 static gint
1839 dcerpc_dg_call_equal(gconstpointer k1, gconstpointer k2)
1840 {
1841     const dcerpc_dg_call_key *key1 = (const dcerpc_dg_call_key *)k1;
1842     const dcerpc_dg_call_key *key2 = (const dcerpc_dg_call_key *)k2;
1843     return ((key1->conv == key2->conv)
1844             && (key1->seqnum == key2->seqnum)
1845             && ((memcmp(&key1->act_id, &key2->act_id, sizeof (e_guid_t)) == 0)));
1846 }
1847
1848 static guint
1849 dcerpc_cn_call_hash(gconstpointer k)
1850 {
1851     const dcerpc_cn_call_key *key = (const dcerpc_cn_call_key *)k;
1852     guint hash;
1853
1854     hash = GPOINTER_TO_UINT(key->conv);
1855     hash += key->call_id;
1856     /* sizeof(guint) might be smaller than sizeof(guint64) */
1857     hash += (guint)key->transport_salt;
1858     hash += (guint)(key->transport_salt << sizeof(guint));
1859
1860     return hash;
1861 }
1862
1863 static guint
1864 dcerpc_dg_call_hash(gconstpointer k)
1865 {
1866     const dcerpc_dg_call_key *key = (const dcerpc_dg_call_key *)k;
1867     return (GPOINTER_TO_UINT(key->conv) + key->seqnum + key->act_id.data1
1868             + (key->act_id.data2 << 16)    + key->act_id.data3
1869             + (key->act_id.data4[0] << 24) + (key->act_id.data4[1] << 16)
1870             + (key->act_id.data4[2] << 8)  + (key->act_id.data4[3] << 0)
1871             + (key->act_id.data4[4] << 24) + (key->act_id.data4[5] << 16)
1872             + (key->act_id.data4[6] << 8)  + (key->act_id.data4[7] << 0));
1873 }
1874
1875 /* to keep track of matched calls/responses
1876    this one uses the same value struct as calls, but the key is the frame id
1877    and call id; there can be more than one call in a frame.
1878
1879    XXX - why not just use the same keys as are used for calls?
1880 */
1881
1882 static GHashTable *dcerpc_matched = NULL;
1883
1884 typedef struct _dcerpc_matched_key {
1885     guint32 frame;
1886     guint32 call_id;
1887 } dcerpc_matched_key;
1888
1889 static gint
1890 dcerpc_matched_equal(gconstpointer k1, gconstpointer k2)
1891 {
1892     const dcerpc_matched_key *key1 = (const dcerpc_matched_key *)k1;
1893     const dcerpc_matched_key *key2 = (const dcerpc_matched_key *)k2;
1894     return ((key1->frame == key2->frame)
1895             && (key1->call_id == key2->call_id));
1896 }
1897
1898 static guint
1899 dcerpc_matched_hash(gconstpointer k)
1900 {
1901     const dcerpc_matched_key *key = (const dcerpc_matched_key *)k;
1902     return key->frame;
1903 }
1904
1905 static gboolean
1906 uuid_equal(e_guid_t *uuid1, e_guid_t *uuid2)
1907 {
1908     if( (uuid1->data1    != uuid2->data1)
1909       ||(uuid1->data2    != uuid2->data2)
1910       ||(uuid1->data3    != uuid2->data3)
1911       ||(uuid1->data4[0] != uuid2->data4[0])
1912       ||(uuid1->data4[1] != uuid2->data4[1])
1913       ||(uuid1->data4[2] != uuid2->data4[2])
1914       ||(uuid1->data4[3] != uuid2->data4[3])
1915       ||(uuid1->data4[4] != uuid2->data4[4])
1916       ||(uuid1->data4[5] != uuid2->data4[5])
1917       ||(uuid1->data4[6] != uuid2->data4[6])
1918       ||(uuid1->data4[7] != uuid2->data4[7]) ){
1919         return FALSE;
1920     }
1921     return TRUE;
1922 }
1923
1924 static void
1925 dcerpcstat_init(struct register_srt* srt, GArray* srt_array, srt_gui_init_cb gui_callback, void* gui_data)
1926 {
1927     dcerpcstat_tap_data_t* tap_data = (dcerpcstat_tap_data_t*)get_srt_table_param_data(srt);
1928     srt_stat_table *dcerpc_srt_table;
1929     int i, hf_opnum;
1930     dcerpc_sub_dissector *procs;
1931
1932     DISSECTOR_ASSERT(tap_data);
1933
1934     hf_opnum = dcerpc_get_proto_hf_opnum(&tap_data->uuid, tap_data->ver);
1935     procs    = dcerpc_get_proto_sub_dissector(&tap_data->uuid, tap_data->ver);
1936
1937     if(hf_opnum != -1){
1938         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);
1939     } else {
1940         dcerpc_srt_table = init_srt_table(tap_data->prog, NULL, srt_array, tap_data->num_procedures, NULL, NULL, gui_callback, gui_data, tap_data);
1941     }
1942
1943     for(i=0;i<tap_data->num_procedures;i++){
1944         int j;
1945         const char *proc_name;
1946
1947         proc_name = "unknown";
1948         for(j=0;procs[j].name;j++)
1949         {
1950             if (procs[j].num == i)
1951             {
1952                 proc_name = procs[j].name;
1953             }
1954         }
1955
1956         init_srt_table_row(dcerpc_srt_table, i, proc_name);
1957     }
1958 }
1959
1960 static int
1961 dcerpcstat_packet(void *pss, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prv)
1962 {
1963     guint i = 0;
1964     srt_stat_table *dcerpc_srt_table;
1965     srt_data_t *data = (srt_data_t *)pss;
1966     const dcerpc_info *ri = (const dcerpc_info *)prv;
1967     dcerpcstat_tap_data_t* tap_data;
1968
1969     dcerpc_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
1970     tap_data = (dcerpcstat_tap_data_t*)dcerpc_srt_table->table_specific_data;
1971
1972     if(!ri->call_data){
1973         return 0;
1974     }
1975     if(!ri->call_data->req_frame){
1976         /* we have not seen the request so we don't know the delta*/
1977         return 0;
1978     }
1979     if(ri->call_data->opnum >= tap_data->num_procedures){
1980         /* don't handle this since it's outside of known table */
1981         return 0;
1982     }
1983
1984     /* we are only interested in reply packets */
1985     if(ri->ptype != PDU_RESP){
1986         return 0;
1987     }
1988
1989     /* we are only interested in certain program/versions */
1990     if( (!uuid_equal( (&ri->call_data->uuid), (&tap_data->uuid)))
1991         ||(ri->call_data->ver != tap_data->ver)){
1992         return 0;
1993     }
1994
1995     add_srt_table_data(dcerpc_srt_table, ri->call_data->opnum, &ri->call_data->req_time, pinfo);
1996
1997     return 1;
1998 }
1999
2000 static guint
2001 dcerpcstat_param(register_srt_t* srt, const char* opt_arg, char** err)
2002 {
2003     int pos = 0;
2004     guint32 i, max_procs;
2005     dcerpcstat_tap_data_t* tap_data;
2006     guint d1,d2,d3,d40,d41,d42,d43,d44,d45,d46,d47;
2007     int major, minor;
2008     guint16 ver;
2009     dcerpc_sub_dissector *procs;
2010
2011     if (sscanf(opt_arg, ",%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x,%d.%d%n",
2012            &d1,&d2,&d3,&d40,&d41,&d42,&d43,&d44,&d45,&d46,&d47,&major,&minor,&pos) == 13)
2013     {
2014         if ((major < 0) || (major > 65535)) {
2015             *err = g_strdup_printf("dcerpcstat_init() Major version number %d is invalid - must be positive and <= 65535", major);
2016             return pos;
2017         }
2018         if ((minor < 0) || (minor > 65535)) {
2019             *err = g_strdup_printf("dcerpcstat_init() Minor version number %d is invalid - must be positive and <= 65535", minor);
2020             return pos;
2021         }
2022         ver = major;
2023
2024         tap_data = g_new0(dcerpcstat_tap_data_t, 1);
2025
2026         tap_data->uuid.data1    = d1;
2027         tap_data->uuid.data2    = d2;
2028         tap_data->uuid.data3    = d3;
2029         tap_data->uuid.data4[0] = d40;
2030         tap_data->uuid.data4[1] = d41;
2031         tap_data->uuid.data4[2] = d42;
2032         tap_data->uuid.data4[3] = d43;
2033         tap_data->uuid.data4[4] = d44;
2034         tap_data->uuid.data4[5] = d45;
2035         tap_data->uuid.data4[6] = d46;
2036         tap_data->uuid.data4[7] = d47;
2037
2038         procs             = dcerpc_get_proto_sub_dissector(&tap_data->uuid, ver);
2039         tap_data->prog    = dcerpc_get_proto_name(&tap_data->uuid, ver);
2040         tap_data->ver     = ver;
2041
2042         for(i=0,max_procs=0;procs[i].name;i++)
2043         {
2044             if(procs[i].num>max_procs)
2045             {
2046                 max_procs = procs[i].num;
2047             }
2048         }
2049         tap_data->num_procedures = max_procs+1;
2050
2051         set_srt_table_param_data(srt, tap_data);
2052     }
2053     else
2054     {
2055         *err = g_strdup_printf("<uuid>,<major version>.<minor version>[,<filter>]");
2056     }
2057
2058     return pos;
2059 }
2060
2061
2062 /*
2063  * Utility functions.  Modeled after packet-rpc.c
2064  */
2065
2066 int
2067 dissect_dcerpc_char(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
2068                      proto_tree *tree, guint8 *drep,
2069                      int hfindex, guint8 *pdata)
2070 {
2071     guint8 data;
2072
2073     /*
2074      * XXX - fix to handle EBCDIC if we ever support EBCDIC FT_CHAR.
2075      */
2076     data = tvb_get_guint8(tvb, offset);
2077     if (hfindex != -1) {
2078         proto_tree_add_item(tree, hfindex, tvb, offset, 1, ENC_ASCII|DREP_ENC_INTEGER(drep));
2079     }
2080     if (pdata)
2081         *pdata = data;
2082     tvb_ensure_bytes_exist(tvb, offset, 1);
2083     return offset + 1;
2084 }
2085
2086 int
2087 dissect_dcerpc_uint8(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
2088                      proto_tree *tree, guint8 *drep,
2089                      int hfindex, guint8 *pdata)
2090 {
2091     guint8 data;
2092
2093     data = tvb_get_guint8(tvb, offset);
2094     if (hfindex != -1) {
2095         proto_tree_add_item(tree, hfindex, tvb, offset, 1, DREP_ENC_INTEGER(drep));
2096     }
2097     if (pdata)
2098         *pdata = data;
2099     tvb_ensure_bytes_exist(tvb, offset, 1);
2100     return offset + 1;
2101 }
2102
2103 int
2104 dissect_dcerpc_uint16(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
2105                       proto_tree *tree, guint8 *drep,
2106                       int hfindex, guint16 *pdata)
2107 {
2108     guint16 data;
2109
2110     data = ((drep[0] & DREP_LITTLE_ENDIAN)
2111             ? tvb_get_letohs(tvb, offset)
2112             : tvb_get_ntohs(tvb, offset));
2113
2114     if (hfindex != -1) {
2115         proto_tree_add_item(tree, hfindex, tvb, offset, 2, DREP_ENC_INTEGER(drep));
2116     }
2117     if (pdata)
2118         *pdata = data;
2119     tvb_ensure_bytes_exist(tvb, offset, 2);
2120     return offset + 2;
2121 }
2122
2123 int
2124 dissect_dcerpc_uint32(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
2125                       proto_tree *tree, guint8 *drep,
2126                       int hfindex, guint32 *pdata)
2127 {
2128     guint32 data;
2129
2130     data = ((drep[0] & DREP_LITTLE_ENDIAN)
2131             ? tvb_get_letohl(tvb, offset)
2132             : tvb_get_ntohl(tvb, offset));
2133
2134     if (hfindex != -1) {
2135         proto_tree_add_item(tree, hfindex, tvb, offset, 4, DREP_ENC_INTEGER(drep));
2136     }
2137     if (pdata)
2138         *pdata = data;
2139     tvb_ensure_bytes_exist(tvb, offset, 4);
2140     return offset+4;
2141 }
2142
2143 /* handles 32 bit unix time_t */
2144 int
2145 dissect_dcerpc_time_t(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
2146                       proto_tree *tree, guint8 *drep,
2147                       int hfindex, guint32 *pdata)
2148 {
2149     guint32 data;
2150     nstime_t tv;
2151
2152     data = ((drep[0] & DREP_LITTLE_ENDIAN)
2153             ? tvb_get_letohl(tvb, offset)
2154             : tvb_get_ntohl(tvb, offset));
2155
2156     tv.secs = data;
2157     tv.nsecs = 0;
2158     if (hfindex != -1) {
2159         if (data == 0xffffffff) {
2160             /* special case,   no time specified */
2161             proto_tree_add_time_format_value(tree, hfindex, tvb, offset, 4, &tv, "No time specified");
2162         } else {
2163             proto_tree_add_time(tree, hfindex, tvb, offset, 4, &tv);
2164         }
2165     }
2166     if (pdata)
2167         *pdata = data;
2168
2169     tvb_ensure_bytes_exist(tvb, offset, 4);
2170     return offset+4;
2171 }
2172
2173 int
2174 dissect_dcerpc_uint64(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
2175                       proto_tree *tree, dcerpc_info *di, guint8 *drep,
2176                       int hfindex, guint64 *pdata)
2177 {
2178     guint64 data;
2179
2180     data = ((drep[0] & DREP_LITTLE_ENDIAN)
2181             ? tvb_get_letoh64(tvb, offset)
2182             : tvb_get_ntoh64(tvb, offset));
2183
2184     if (hfindex != -1) {
2185         header_field_info *hfinfo;
2186
2187         /* This might be a field that is either 32bit, in NDR or
2188            64 bits in NDR64. So we must be careful and call the right
2189            helper here
2190         */
2191         hfinfo = proto_registrar_get_nth(hfindex);
2192
2193         switch (hfinfo->type) {
2194         case FT_UINT64:
2195             proto_tree_add_uint64(tree, hfindex, tvb, offset, 8, data);
2196             break;
2197         case FT_INT64:
2198             proto_tree_add_int64(tree, hfindex, tvb, offset, 8, data);
2199             break;
2200         default:
2201             /* The value is truncated to 32bits.  64bit values have only been
2202                seen on fuzz-tested files */
2203             DISSECTOR_ASSERT((di->call_data->flags & DCERPC_IS_NDR64) || (data <= G_MAXUINT32));
2204             proto_tree_add_uint(tree, hfindex, tvb, offset, 8, (guint32)data);
2205         }
2206     }
2207     if (pdata)
2208         *pdata = data;
2209     tvb_ensure_bytes_exist(tvb, offset, 8);
2210     return offset+8;
2211 }
2212
2213
2214 int
2215 dissect_dcerpc_float(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
2216                      proto_tree *tree, guint8 *drep,
2217                      int hfindex, gfloat *pdata)
2218 {
2219     gfloat data;
2220
2221
2222     switch (drep[1]) {
2223     case(DCE_RPC_DREP_FP_IEEE):
2224         data = ((drep[0] & DREP_LITTLE_ENDIAN)
2225                 ? tvb_get_letohieee_float(tvb, offset)
2226                 : tvb_get_ntohieee_float(tvb, offset));
2227         if (tree && hfindex != -1) {
2228             proto_tree_add_float(tree, hfindex, tvb, offset, 4, data);
2229         }
2230         break;
2231     case(DCE_RPC_DREP_FP_VAX):  /* (fall trough) */
2232     case(DCE_RPC_DREP_FP_CRAY): /* (fall trough) */
2233     case(DCE_RPC_DREP_FP_IBM):  /* (fall trough) */
2234     default:
2235         /* ToBeDone: non IEEE floating formats */
2236         /* Set data to a negative infinity value */
2237         data = -G_MAXFLOAT;
2238         if (tree && hfindex != -1) {
2239             proto_tree_add_debug_text(tree, "DCE RPC: dissection of non IEEE floating formats currently not implemented (drep=%u)!", drep[1]);
2240         }
2241     }
2242     if (pdata)
2243         *pdata = data;
2244     tvb_ensure_bytes_exist(tvb, offset, 4);
2245     return offset + 4;
2246 }
2247
2248
2249 int
2250 dissect_dcerpc_double(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
2251                       proto_tree *tree, guint8 *drep,
2252                       int hfindex, gdouble *pdata)
2253 {
2254     gdouble data;
2255
2256
2257     switch (drep[1]) {
2258     case(DCE_RPC_DREP_FP_IEEE):
2259         data = ((drep[0] & DREP_LITTLE_ENDIAN)
2260                 ? tvb_get_letohieee_double(tvb, offset)
2261                 : tvb_get_ntohieee_double(tvb, offset));
2262         if (tree && hfindex != -1) {
2263             proto_tree_add_double(tree, hfindex, tvb, offset, 8, data);
2264         }
2265         break;
2266     case(DCE_RPC_DREP_FP_VAX):  /* (fall trough) */
2267     case(DCE_RPC_DREP_FP_CRAY): /* (fall trough) */
2268     case(DCE_RPC_DREP_FP_IBM):  /* (fall trough) */
2269     default:
2270         /* ToBeDone: non IEEE double formats */
2271         /* Set data to a negative infinity value */
2272         data = -G_MAXDOUBLE;
2273         if (tree && hfindex != -1) {
2274             proto_tree_add_debug_text(tree, "DCE RPC: dissection of non IEEE double formats currently not implemented (drep=%u)!", drep[1]);
2275         }
2276     }
2277     if (pdata)
2278         *pdata = data;
2279     tvb_ensure_bytes_exist(tvb, offset, 8);
2280     return offset + 8;
2281 }
2282
2283
2284 int
2285 dissect_dcerpc_uuid_t(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
2286                       proto_tree *tree, guint8 *drep,
2287                       int hfindex, e_guid_t *pdata)
2288 {
2289     e_guid_t uuid;
2290
2291
2292     if (drep[0] & DREP_LITTLE_ENDIAN) {
2293         tvb_get_letohguid(tvb, offset, (e_guid_t *) &uuid);
2294     } else {
2295         tvb_get_ntohguid(tvb, offset, (e_guid_t *) &uuid);
2296     }
2297     if (tree && hfindex != -1) {
2298         proto_tree_add_guid(tree, hfindex, tvb, offset, 16, (e_guid_t *) &uuid);
2299     }
2300     if (pdata) {
2301         *pdata = uuid;
2302     }
2303     return offset + 16;
2304 }
2305
2306
2307 /*
2308  * a couple simpler things
2309  */
2310 guint16
2311 dcerpc_tvb_get_ntohs(tvbuff_t *tvb, gint offset, guint8 *drep)
2312 {
2313     if (drep[0] & DREP_LITTLE_ENDIAN) {
2314         return tvb_get_letohs(tvb, offset);
2315     } else {
2316         return tvb_get_ntohs(tvb, offset);
2317     }
2318 }
2319
2320 guint32
2321 dcerpc_tvb_get_ntohl(tvbuff_t *tvb, gint offset, guint8 *drep)
2322 {
2323     if (drep[0] & DREP_LITTLE_ENDIAN) {
2324         return tvb_get_letohl(tvb, offset);
2325     } else {
2326         return tvb_get_ntohl(tvb, offset);
2327     }
2328 }
2329
2330 void
2331 dcerpc_tvb_get_uuid(tvbuff_t *tvb, gint offset, guint8 *drep, e_guid_t *uuid)
2332 {
2333     if (drep[0] & DREP_LITTLE_ENDIAN) {
2334         tvb_get_letohguid(tvb, offset, (e_guid_t *) uuid);
2335     } else {
2336         tvb_get_ntohguid(tvb, offset, (e_guid_t *) uuid);
2337     }
2338 }
2339
2340
2341 /* NDR arrays */
2342 /* function to dissect a unidimensional conformant array */
2343 static int
2344 dissect_ndr_ucarray_core(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2345                     proto_tree *tree, dcerpc_info *di, guint8 *drep,
2346                     dcerpc_dissect_fnct_t *fnct_bytes,
2347                     dcerpc_dissect_fnct_blk_t *fnct_block)
2348 {
2349     guint32      i;
2350     int          old_offset;
2351     int          conformance_size = 4;
2352
2353     /* ensure that just one pointer is set in the call */
2354     DISSECTOR_ASSERT((fnct_bytes && !fnct_block) || (!fnct_bytes && fnct_block));
2355
2356     if (di->call_data->flags & DCERPC_IS_NDR64) {
2357         conformance_size = 8;
2358     }
2359
2360     if (di->conformant_run) {
2361         guint64 val;
2362
2363         /* conformant run, just dissect the max_count header */
2364         old_offset = offset;
2365         di->conformant_run = 0;
2366         offset = dissect_ndr_uint3264(tvb, offset, pinfo, tree, di, drep,
2367                                        hf_dcerpc_array_max_count, &val);
2368         di->array_max_count = (gint32)val;
2369         di->array_max_count_offset = offset-conformance_size;
2370         di->conformant_run = 1;
2371         di->conformant_eaten = offset-old_offset;
2372     } else {
2373         /* we don't remember where in the bytestream this field was */
2374         proto_tree_add_uint(tree, hf_dcerpc_array_max_count, tvb, di->array_max_count_offset, conformance_size, di->array_max_count);
2375
2376         /* real run, dissect the elements */
2377         if (fnct_block) {
2378                 offset = (*fnct_block)(tvb, offset, di->array_max_count,
2379                                        pinfo, tree, di, drep);
2380         } else {
2381             for (i=0 ;i<di->array_max_count; i++) {
2382                 offset = (*fnct_bytes)(tvb, offset, pinfo, tree, di, drep);
2383             }
2384         }
2385     }
2386
2387     return offset;
2388 }
2389
2390 int
2391 dissect_ndr_ucarray_block(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2392                           proto_tree *tree, dcerpc_info *di, guint8 *drep,
2393                           dcerpc_dissect_fnct_blk_t *fnct)
2394 {
2395     return dissect_ndr_ucarray_core(tvb, offset, pinfo, tree, di, drep, NULL, fnct);
2396 }
2397
2398 int
2399 dissect_ndr_ucarray(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2400                     proto_tree *tree, dcerpc_info *di, guint8 *drep,
2401                     dcerpc_dissect_fnct_t *fnct)
2402 {
2403     return dissect_ndr_ucarray_core(tvb, offset, pinfo, tree, di, drep, fnct, NULL);
2404 }
2405
2406 /* function to dissect a unidimensional conformant and varying array
2407  * depending on the dissection function passed as a parameter,
2408  * content of the array will be dissected as a block or byte by byte
2409  */
2410 static int
2411 dissect_ndr_ucvarray_core(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2412                      proto_tree *tree, dcerpc_info *di, guint8 *drep,
2413                      dcerpc_dissect_fnct_t *fnct_bytes,
2414                      dcerpc_dissect_fnct_blk_t *fnct_block)
2415 {
2416     guint32      i;
2417     int          old_offset;
2418     int          conformance_size = 4;
2419
2420     if (di->call_data->flags & DCERPC_IS_NDR64) {
2421         conformance_size = 8;
2422     }
2423
2424     if (di->conformant_run) {
2425         guint64 val;
2426
2427         /* conformant run, just dissect the max_count header */
2428         old_offset = offset;
2429         di->conformant_run = 0;
2430         offset = dissect_ndr_uint3264(tvb, offset, pinfo, tree, di, drep,
2431                                        hf_dcerpc_array_max_count, &val);
2432         DISSECTOR_ASSERT(val <= G_MAXUINT32);
2433         di->array_max_count = (guint32)val;
2434         di->array_max_count_offset = offset-conformance_size;
2435         offset = dissect_ndr_uint3264(tvb, offset, pinfo, tree, di, drep,
2436                                        hf_dcerpc_array_offset, &val);
2437         DISSECTOR_ASSERT(val <= G_MAXUINT32);
2438         di->array_offset = (guint32)val;
2439         di->array_offset_offset = offset-conformance_size;
2440         offset = dissect_ndr_uint3264(tvb, offset, pinfo, tree, di, drep,
2441                                        hf_dcerpc_array_actual_count, &val);
2442         DISSECTOR_ASSERT(val <= G_MAXUINT32);
2443         di->array_actual_count = (guint32)val;
2444         di->array_actual_count_offset = offset-conformance_size;
2445         di->conformant_run = 1;
2446         di->conformant_eaten = offset-old_offset;
2447     } else {
2448         /* we don't remember where in the bytestream these fields were */
2449         proto_tree_add_uint(tree, hf_dcerpc_array_max_count, tvb, di->array_max_count_offset, conformance_size, di->array_max_count);
2450         proto_tree_add_uint(tree, hf_dcerpc_array_offset, tvb, di->array_offset_offset, conformance_size, di->array_offset);
2451         proto_tree_add_uint(tree, hf_dcerpc_array_actual_count, tvb, di->array_actual_count_offset, conformance_size, di->array_actual_count);
2452
2453         /* real run, dissect the elements */
2454         if (fnct_block) {
2455                 offset = (*fnct_block)(tvb, offset, di->array_actual_count,
2456                                        pinfo, tree, di, drep);
2457         } else if (fnct_bytes) {
2458             for (i=0 ;i<di->array_actual_count; i++) {
2459                 old_offset = offset;
2460                 offset = (*fnct_bytes)(tvb, offset, pinfo, tree, di, drep);
2461                 /* Make sure we're moving forward */
2462                 if (old_offset >= offset)
2463                     break;
2464             }
2465         }
2466     }
2467
2468     return offset;
2469 }
2470
2471 int
2472 dissect_ndr_ucvarray_block(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2473                      proto_tree *tree, dcerpc_info *di, guint8 *drep,
2474                      dcerpc_dissect_fnct_blk_t *fnct)
2475 {
2476     return dissect_ndr_ucvarray_core(tvb, offset, pinfo, tree, di, drep, NULL, fnct);
2477 }
2478
2479 int
2480 dissect_ndr_ucvarray(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2481                      proto_tree *tree, dcerpc_info *di, guint8 *drep,
2482                      dcerpc_dissect_fnct_t *fnct)
2483 {
2484     return dissect_ndr_ucvarray_core(tvb, offset, pinfo, tree, di, drep, fnct, NULL);
2485 }
2486 /* function to dissect a unidimensional varying array */
2487 int
2488 dissect_ndr_uvarray(tvbuff_t *tvb, gint offset, packet_info *pinfo,
2489                     proto_tree *tree, dcerpc_info *di, guint8 *drep,
2490                     dcerpc_dissect_fnct_t *fnct)
2491 {
2492     guint32      i;
2493     int          old_offset;
2494     int          conformance_size = 4;
2495
2496     if (di->call_data->flags & DCERPC_IS_NDR64) {
2497         conformance_size = 8;
2498     }
2499
2500     if (di->conformant_run) {
2501         guint64 val;
2502
2503         /* conformant run, just dissect the max_count header */
2504         old_offset = offset;
2505         di->conformant_run = 0;
2506         offset = dissect_ndr_uint3264(tvb, offset, pinfo, tree, di, drep,
2507                                        hf_dcerpc_array_offset, &val);
2508         DISSECTOR_ASSERT(val <= G_MAXUINT32);
2509         di->array_offset = (guint32)val;
2510         di->array_offset_offset = offset-conformance_size;
2511         offset = dissect_ndr_uint3264(tvb, offset, pinfo, tree, di, drep,
2512                                        hf_dcerpc_array_actual_count, &val);
2513         DISSECTOR_ASSERT(val <= G_MAXUINT32);
2514         di->array_actual_count = (guint32)val;
2515         di->array_actual_count_offset = offset-conformance_size;
2516         di->conformant_run = 1;
2517         di->conformant_eaten = offset-old_offset;
2518     } else {
2519         /* we don't remember where in the bytestream these fields were */
2520         proto_tree_add_uint(tree, hf_dcerpc_array_offset, tvb, di->array_offset_offset, conformance_size, di->array_offset);
2521         proto_tree_add_uint(tree, hf_dcerpc_array_actual_count, tvb, di->array_actual_count_offset, conformance_size, di->array_actual_count);
2522
2523         /* real run, dissect the elements */
2524         for (i=0; i<di->array_actual_count; i++) {
2525             offset = (*fnct)(tvb, offset, pinfo, tree, di, drep);
2526         }
2527     }
2528
2529     return offset;
2530 }
2531
2532 /* Dissect an string of bytes.  This corresponds to
2533    IDL of the form '[string] byte *foo'.
2534
2535    It can also be used for a conformant varying array of bytes if
2536    the contents of the array should be shown as a big blob, rather
2537    than showing each byte as an individual element.
2538
2539    XXX - which of those is really the IDL type for, for example,
2540    the encrypted data in some MAPI packets?  (Microsoft hasn't
2541    released that IDL.)
2542
2543    XXX - does this need to do all the conformant array stuff that
2544    "dissect_ndr_ucvarray()" does?  These are presumably for strings
2545    that are conformant and varying - they're stored like conformant
2546    varying arrays of bytes.  */
2547 int
2548 dissect_ndr_byte_array(tvbuff_t *tvb, int offset, packet_info *pinfo,
2549                        proto_tree *tree, dcerpc_info *di, guint8 *drep)
2550 {
2551     guint64      len;
2552
2553     if (di->conformant_run) {
2554         /* just a run to handle conformant arrays, no scalars to dissect */
2555         return offset;
2556     }
2557
2558     /* NDR array header */
2559
2560     offset = dissect_ndr_uint3264(tvb, offset, pinfo, tree, di, drep,
2561                                   hf_dcerpc_array_max_count, NULL);
2562
2563     offset = dissect_ndr_uint3264(tvb, offset, pinfo, tree, di, drep,
2564                                   hf_dcerpc_array_offset, NULL);
2565
2566     offset = dissect_ndr_uint3264(tvb, offset, pinfo, tree, di, drep,
2567                                   hf_dcerpc_array_actual_count, &len);
2568
2569     DISSECTOR_ASSERT(len <= G_MAXUINT32);
2570     if (len) {
2571         proto_tree_add_item(tree, di->hf_index, tvb, offset, (guint32)len,
2572                             ENC_NA);
2573     }
2574
2575     offset += (guint32)len;
2576
2577     return offset;
2578 }
2579
2580 /* For dissecting arrays that are to be interpreted as strings.  */
2581
2582 /* Dissect an NDR conformant varying string of elements.
2583    The length of each element is given by the 'size_is' parameter;
2584    the elements are assumed to be characters or wide characters.
2585
2586    XXX - does this need to do all the conformant array stuff that
2587    "dissect_ndr_ucvarray()" does?  */
2588 int
2589 dissect_ndr_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
2590                      proto_tree *tree, dcerpc_info *di, guint8 *drep, int size_is,
2591                      int hfindex, gboolean add_subtree, char **data)
2592 {
2593     header_field_info *hfinfo;
2594     proto_item        *string_item;
2595     proto_tree        *string_tree;
2596     guint64            len;
2597     guint32            buffer_len;
2598     char              *s;
2599
2600     /* Make sure this really is a string field. */
2601     hfinfo = proto_registrar_get_nth(hfindex);
2602     DISSECTOR_ASSERT(hfinfo->type == FT_STRING);
2603
2604     if (di->conformant_run) {
2605         /* just a run to handle conformant arrays, no scalars to dissect */
2606         return offset;
2607     }
2608
2609     if (add_subtree) {
2610         string_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_dcerpc_string, &string_item,
2611                                           proto_registrar_get_name(hfindex));
2612     } else {
2613         string_item = NULL;
2614         string_tree = tree;
2615     }
2616
2617     /* NDR array header */
2618
2619     offset = dissect_ndr_uint3264(tvb, offset, pinfo, string_tree, di, drep,
2620                                   hf_dcerpc_array_max_count, NULL);
2621
2622     offset = dissect_ndr_uint3264(tvb, offset, pinfo, string_tree, di, drep,
2623                                   hf_dcerpc_array_offset, NULL);
2624
2625     offset = dissect_ndr_uint3264(tvb, offset, pinfo, string_tree, di, drep,
2626                                   hf_dcerpc_array_actual_count, &len);
2627
2628     /* The value is truncated to 32bits.  64bit values have only been
2629        seen on fuzztested files */
2630     buffer_len = size_is * (guint32)len;
2631
2632     /* Adjust offset */
2633     if (!di->no_align && (offset % size_is))
2634         offset += size_is - (offset % size_is);
2635
2636     /*
2637      * "tvb_get_string_enc()" throws an exception if the entire string
2638      * isn't in the tvbuff.  If the length is bogus, this should
2639      * keep us from trying to allocate an immensely large buffer.
2640      * (It won't help if the length is *valid* but immensely large,
2641      * but that's another matter; in any case, that would happen only
2642      * if we had an immensely large tvbuff....)
2643      *
2644      * XXX - so why are we doing tvb_ensure_bytes_exist()?
2645      */
2646     tvb_ensure_bytes_exist(tvb, offset, buffer_len);
2647     if (size_is == sizeof(guint16)) {
2648         /*
2649          * Assume little-endian UTF-16.
2650          *
2651          * XXX - is this always little-endian?
2652          */
2653         s = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, buffer_len,
2654                                ENC_UTF_16|ENC_LITTLE_ENDIAN);
2655     } else {
2656         /*
2657          * XXX - what if size_is is neither 1 nor 2?
2658          */
2659         s = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, buffer_len,
2660                                DREP_ENC_CHAR(drep));
2661     }
2662     if (tree && buffer_len)
2663         proto_tree_add_string(string_tree, hfindex, tvb, offset,
2664                               buffer_len, s);
2665
2666     if (string_item != NULL)
2667         proto_item_append_text(string_item, ": %s", s);
2668
2669     if (data)
2670         *data = s;
2671
2672     offset += buffer_len;
2673
2674     proto_item_set_end(string_item, tvb, offset);
2675
2676     return offset;
2677 }
2678
2679 int
2680 dissect_ndr_cstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
2681                     proto_tree *tree, dcerpc_info *di, guint8 *drep, int size_is,
2682                     int hfindex, gboolean add_subtree, char **data)
2683 {
2684     return dissect_ndr_cvstring(tvb, offset, pinfo, tree, di, drep, size_is, hfindex, add_subtree, data);
2685 }
2686
2687 /* Dissect an conformant varying string of chars.
2688    This corresponds to IDL of the form '[string] char *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_char_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(guint8), di->hf_index,
2702                                 FALSE, NULL);
2703 }
2704
2705 /* Dissect a conformant varying string of wchars (wide characters).
2706    This corresponds to IDL of the form '[string] wchar *foo'
2707
2708    XXX - at least according to the DCE RPC 1.1 spec, a string has
2709    a null terminator, which isn't necessary as a terminator for
2710    the transfer language (as there's a length), but is presumably
2711    there for the benefit of null-terminated-string languages
2712    such as C.  Is this ever used for purely counted strings?
2713    (Not that it matters if it is.) */
2714 int
2715 dissect_ndr_wchar_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
2716                            proto_tree *tree, dcerpc_info *di, guint8 *drep)
2717 {
2718     return dissect_ndr_cvstring(tvb, offset, pinfo, tree, di, drep,
2719                                 sizeof(guint16), di->hf_index,
2720                                 FALSE, NULL);
2721 }
2722
2723 /* This function is aimed for PIDL usage and dissects a UNIQUE pointer to
2724  * unicode string.
2725  */
2726 int
2727 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)
2728 {
2729     char        *s      = NULL;
2730     gint         levels = CB_STR_ITEM_LEVELS(param);
2731
2732     offset = dissect_ndr_cvstring(tvb, offset, pinfo, tree, di, drep,
2733                                   chsize, hfindex,
2734                                   FALSE, &s);
2735
2736     if (!di->conformant_run) {
2737         /* Append string to COL_INFO */
2738         if (param & PIDL_SET_COL_INFO) {
2739             col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", s);
2740         }
2741         /* Save string to dcv->private_data */
2742         if ((param & PIDL_STR_SAVE)
2743            && (!pinfo->fd->flags.visited)) {
2744             dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
2745             dcv->private_data = wmem_strdup(wmem_file_scope(), s);
2746         }
2747         /* Append string to upper-level proto_items */
2748         if ((levels > 0) && tree && s && s[0]) {
2749             proto_item_append_text(tree, ": %s", s);
2750             tree = tree->parent;
2751             levels--;
2752             if (levels > 0) {
2753                 proto_item_append_text(tree, ": %s", s);
2754                 tree = tree->parent;
2755                 levels--;
2756                 while (levels > 0) {
2757                     proto_item_append_text(tree, " %s", s);
2758                     tree = tree->parent;
2759                     levels--;
2760                 }
2761             }
2762         }
2763
2764     }
2765
2766     return offset;
2767 }
2768
2769 /* Dissect an NDR varying string of elements.
2770    The length of each element is given by the 'size_is' parameter;
2771    the elements are assumed to be characters or wide characters.
2772 */
2773 int
2774 dissect_ndr_vstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
2775                     proto_tree *tree, dcerpc_info *di, guint8 *drep, int size_is,
2776                     int hfindex, gboolean add_subtree, char **data)
2777 {
2778     header_field_info *hfinfo;
2779     proto_item        *string_item;
2780     proto_tree        *string_tree;
2781     guint64            len;
2782     guint32            buffer_len;
2783     char              *s;
2784
2785     /* Make sure this really is a string field. */
2786     hfinfo = proto_registrar_get_nth(hfindex);
2787     DISSECTOR_ASSERT(hfinfo->type == FT_STRING);
2788
2789     if (di->conformant_run) {
2790         /* just a run to handle conformant arrays, no scalars to dissect */
2791         return offset;
2792     }
2793
2794     if (add_subtree) {
2795         string_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_dcerpc_string, &string_item,
2796                                           proto_registrar_get_name(hfindex));
2797     } else {
2798         string_item = NULL;
2799         string_tree = tree;
2800     }
2801
2802     /* NDR array header */
2803     offset = dissect_ndr_uint3264(tvb, offset, pinfo, string_tree, di, drep,
2804                                   hf_dcerpc_array_offset, NULL);
2805
2806     offset = dissect_ndr_uint3264(tvb, offset, pinfo, string_tree, di, drep,
2807                                   hf_dcerpc_array_actual_count, &len);
2808
2809     DISSECTOR_ASSERT(len <= G_MAXUINT32);
2810     buffer_len = size_is * (guint32)len;
2811
2812     /* Adjust offset */
2813     if (!di->no_align && (offset % size_is))
2814         offset += size_is - (offset % size_is);
2815
2816     /*
2817      * "tvb_get_string_enc()" throws an exception if the entire string
2818      * isn't in the tvbuff.  If the length is bogus, this should
2819      * keep us from trying to allocate an immensely large buffer.
2820      * (It won't help if the length is *valid* but immensely large,
2821      * but that's another matter; in any case, that would happen only
2822      * if we had an immensely large tvbuff....)
2823      *
2824      * XXX - so why are we doing tvb_ensure_bytes_exist()?
2825      */
2826     tvb_ensure_bytes_exist(tvb, offset, buffer_len);
2827     if (size_is == sizeof(guint16)) {
2828         /*
2829          * Assume little-endian UTF-16.
2830          *
2831          * XXX - is this always little-endian?
2832          */
2833         s = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, buffer_len,
2834                                ENC_UTF_16|ENC_LITTLE_ENDIAN);
2835     } else {
2836         /*
2837          * XXX - what if size_is is neither 1 nor 2?
2838          */
2839         s = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, buffer_len,
2840                                DREP_ENC_CHAR(drep));
2841     }
2842     if (tree && buffer_len)
2843         proto_tree_add_string(string_tree, hfindex, tvb, offset,
2844                               buffer_len, s);
2845
2846     if (string_item != NULL)
2847         proto_item_append_text(string_item, ": %s", s);
2848
2849     if (data)
2850         *data = s;
2851
2852     offset += buffer_len;
2853
2854     proto_item_set_end(string_item, tvb, offset);
2855
2856     return offset;
2857 }
2858
2859 /* Dissect an varying string of chars.
2860    This corresponds to IDL of the form '[string] char *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_char_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(guint8), di->hf_index,
2874                                FALSE, NULL);
2875 }
2876
2877 /* Dissect a varying string of wchars (wide characters).
2878    This corresponds to IDL of the form '[string] wchar *foo'
2879
2880    XXX - at least according to the DCE RPC 1.1 spec, a string has
2881    a null terminator, which isn't necessary as a terminator for
2882    the transfer language (as there's a length), but is presumably
2883    there for the benefit of null-terminated-string languages
2884    such as C.  Is this ever used for purely counted strings?
2885    (Not that it matters if it is.) */
2886 int
2887 dissect_ndr_wchar_vstring(tvbuff_t *tvb, int offset, packet_info *pinfo,
2888                           proto_tree *tree, dcerpc_info *di, guint8 *drep)
2889 {
2890     return dissect_ndr_vstring(tvb, offset, pinfo, tree, di, drep,
2891                                sizeof(guint16), di->hf_index,
2892                                FALSE, NULL);
2893 }
2894
2895
2896 /* ndr pointer handling */
2897 /* list of pointers encountered so far */
2898 static GSList *ndr_pointer_list = NULL;
2899
2900 /* position where in the list to insert newly encountered pointers */
2901 static int ndr_pointer_list_pos = 0;
2902
2903 /* Boolean controlling whether pointers are top-level or embedded */
2904 static gboolean pointers_are_top_level = TRUE;
2905
2906 /* as a kludge, we represent all embedded reference pointers as id == -1
2907    hoping that his will not collide with any non-ref pointers */
2908 typedef struct ndr_pointer_data {
2909     guint32                 id;
2910     proto_item             *item; /* proto_item for pointer */
2911     proto_tree             *tree; /* subtree of above item */
2912     dcerpc_dissect_fnct_t  *fnct; /*if non-NULL, we have not called it yet*/
2913     int                     hf_index;
2914     dcerpc_callback_fnct_t *callback;
2915     void                   *callback_args;
2916 } ndr_pointer_data_t;
2917
2918 void
2919 init_ndr_pointer_list(dcerpc_info *di)
2920 {
2921     di->conformant_run = 0;
2922
2923     while (ndr_pointer_list) {
2924         ndr_pointer_data_t *npd = (ndr_pointer_data_t *)g_slist_nth_data(ndr_pointer_list, 0);
2925         ndr_pointer_list = g_slist_remove(ndr_pointer_list, npd);
2926         g_free(npd);
2927     }
2928
2929     ndr_pointer_list = NULL;
2930     ndr_pointer_list_pos = 0;
2931     pointers_are_top_level = TRUE;
2932 }
2933
2934 int
2935 dissect_deferred_pointers(packet_info *pinfo, tvbuff_t *tvb, int offset, dcerpc_info *di, guint8 *drep)
2936 {
2937     int          found_new_pointer;
2938     int          old_offset;
2939     int          next_pointer;
2940
2941     next_pointer = 0;
2942
2943     do{
2944         int i, len;
2945
2946         found_new_pointer = 0;
2947         len = g_slist_length(ndr_pointer_list);
2948         for (i=next_pointer; i<len; i++) {
2949             ndr_pointer_data_t *tnpd = (ndr_pointer_data_t *)g_slist_nth_data(ndr_pointer_list, i);
2950             if (tnpd->fnct) {
2951                 dcerpc_dissect_fnct_t *fnct;
2952
2953                 next_pointer = i+1;
2954                 found_new_pointer = 1;
2955                 fnct = tnpd->fnct;
2956                 tnpd->fnct = NULL;
2957                 ndr_pointer_list_pos = i+1;
2958                 di->hf_index = tnpd->hf_index;
2959                 /* first a run to handle any conformant
2960                    array headers */
2961                 di->conformant_run = 1;
2962                 di->conformant_eaten = 0;
2963                 old_offset = offset;
2964                 offset = (*(fnct))(tvb, offset, pinfo, NULL, di, drep);
2965
2966                 DISSECTOR_ASSERT((offset-old_offset) == di->conformant_eaten);
2967                 /* This is to check for any bugs in the dissectors.
2968                  *
2969                  * Basically, the NDR representation will store all
2970                  * arrays in two blocks, one block with the dimension
2971                  * description, like size, number of elements and such,
2972                  * and another block that contains the actual data stored
2973                  * in the array.
2974                  * If the array is embedded directly inside another,
2975                  * encapsulating aggregate type, like a union or struct,
2976                  * then these two blocks will be stored at different places
2977                  * in the bytestream, with other data between the blocks.
2978                  *
2979                  * For this reason, all pointers to types (both aggregate
2980                  * and scalar, for simplicity no distinction is made)
2981                  * will have its dissector called twice.
2982                  * The dissector will first be called with conformant_run == 1
2983                  * in which mode the dissector MUST NOT consume any data from
2984                  * the tvbuff (i.e. may not dissect anything) except the
2985                  * initial control block for arrays.
2986                  * The second time the dissector is called, with
2987                  * conformant_run == 0, all other data for the type will be
2988                  * dissected.
2989                  *
2990                  * All dissect_ndr_<type> dissectors are already prepared
2991                  * for this and knows when it should eat data from the tvb
2992                  * and when not to, so implementors of dissectors will
2993                  * normally not need to worry about this or even know about
2994                  * it. However, if a dissector for an aggregate type calls
2995                  * a subdissector from outside packet-dcerpc.c, such as
2996                  * the dissector in packet-smb.c for NT Security Descriptors
2997                  * as an example, then it is VERY important to encapsulate
2998                  * this call to an external subdissector with the appropriate
2999                  * test for conformant_run, i.e. it will need something like
3000                  *
3001                  *      dcerpc_info *di (received as function parameter)
3002                  *
3003                  *      if (di->conformant_run) {
3004                  *              return offset;
3005                  *      }
3006                  *
3007                  * to make sure it makes the right thing.
3008                  * This assert will signal when someone has forgotten to
3009                  * make the dissector aware of this requirement.
3010                  */
3011
3012                 /* now we dissect the actual pointer */
3013                 di->conformant_run = 0;
3014                 old_offset = offset;
3015                 offset = (*(fnct))(tvb, offset, pinfo, tnpd->tree, di, drep);
3016                 if (tnpd->callback)
3017                     tnpd->callback(pinfo, tnpd->tree, tnpd->item, di, tvb, old_offset, offset, tnpd->callback_args);
3018                 proto_item_set_len(tnpd->item, offset - old_offset);
3019                 break;
3020             }
3021         }
3022     } while (found_new_pointer);
3023
3024     return offset;
3025 }
3026
3027
3028 static void
3029 add_pointer_to_list(packet_info *pinfo, proto_tree *tree, proto_item *item,
3030                     dcerpc_info *di, dcerpc_dissect_fnct_t *fnct, guint32 id, int hf_index,
3031                     dcerpc_callback_fnct_t *callback, void *callback_args)
3032 {
3033     ndr_pointer_data_t *npd;
3034
3035     /* check if this pointer is valid */
3036     if (id != 0xffffffff) {
3037         dcerpc_call_value *value;
3038
3039         value = di->call_data;
3040
3041         if (di->ptype == PDU_REQ) {
3042             if (!(pinfo->fd->flags.visited)) {
3043                 if (id > value->max_ptr) {
3044                     value->max_ptr = id;
3045                 }
3046             }
3047         } else {
3048             /* if we haven't seen the request bail out since we can't
3049                know whether this is the first non-NULL instance
3050                or not */
3051             if (value->req_frame == 0) {
3052                 /* XXX THROW EXCEPTION */
3053             }
3054
3055             /* We saw this one in the request frame, nothing to
3056                dissect later */
3057             if (id <= value->max_ptr) {
3058                 return;
3059             }
3060         }
3061     }
3062
3063     npd = (ndr_pointer_data_t *)g_malloc(sizeof(ndr_pointer_data_t));
3064     npd->id   = id;
3065     npd->tree = tree;
3066     npd->item = item;
3067     npd->fnct = fnct;
3068     npd->hf_index = hf_index;
3069     npd->callback = callback;
3070     npd->callback_args = callback_args;
3071     ndr_pointer_list = g_slist_insert(ndr_pointer_list, npd,
3072                                       ndr_pointer_list_pos);
3073     ndr_pointer_list_pos++;
3074 }
3075
3076
3077 static int
3078 find_pointer_index(guint32 id)
3079 {
3080     ndr_pointer_data_t *npd;
3081     int                 i,len;
3082
3083     len = g_slist_length(ndr_pointer_list);
3084     for (i=0; i<len; i++) {
3085         npd = (ndr_pointer_data_t *)g_slist_nth_data(ndr_pointer_list, i);
3086         if (npd) {
3087             if (npd->id == id) {
3088                 return i;
3089             }
3090         }
3091     }
3092
3093     return -1;
3094 }
3095
3096 /* This function dissects an NDR pointer and stores the callback for later
3097  * deferred dissection.
3098  *
3099  *   fnct is the callback function for when we have reached this object in
3100  *   the bytestream.
3101  *
3102  *   type is what type of pointer.
3103  *
3104  *   this is text is what text we should put in any created tree node.
3105  *
3106  *   hf_index is what hf value we want to pass to the callback function when
3107  *   it is called, the callback can later pick this one up from di->hf_index.
3108  *
3109  *   callback is executed after the pointer has been dereferenced.
3110  *
3111  *   callback_args is passed as an argument to the callback function
3112  *
3113  * See packet-dcerpc-samr.c for examples
3114  */
3115 int
3116 dissect_ndr_pointer_cb(tvbuff_t *tvb, gint offset, packet_info *pinfo,
3117                        proto_tree *tree, dcerpc_info *di, guint8 *drep, dcerpc_dissect_fnct_t *fnct,
3118                        int type, const char *text, int hf_index,
3119                        dcerpc_callback_fnct_t *callback, void *callback_args)
3120 {
3121     proto_tree  *tr           = NULL;
3122     gint         start_offset = offset;
3123     int          pointer_size = 4;
3124
3125     if (di->conformant_run) {
3126         /* this call was only for dissecting the header for any
3127            embedded conformant array. we will not parse any
3128            pointers in this mode.
3129         */
3130         return offset;
3131     }
3132     if (di->call_data->flags & DCERPC_IS_NDR64) {
3133         pointer_size = 8;
3134     }
3135
3136
3137     /*TOP LEVEL REFERENCE POINTER*/
3138     if ( pointers_are_top_level
3139         && (type == NDR_POINTER_REF) ) {
3140         proto_item *item;
3141
3142         /* we must find out a nice way to do the length here */
3143         tr = proto_tree_add_subtree(tree, tvb, offset, 0,
3144                                    ett_dcerpc_pointer_data, &item, text);
3145
3146         add_pointer_to_list(pinfo, tr, item, di, fnct, 0xffffffff,
3147                             hf_index, callback, callback_args);
3148         goto after_ref_id;
3149     }
3150
3151     /*TOP LEVEL FULL POINTER*/
3152     if ( pointers_are_top_level
3153         && (type == NDR_POINTER_PTR) ) {
3154         int idx;
3155         guint64 id;
3156         proto_item *item;
3157
3158         /* get the referent id */
3159         offset = dissect_ndr_uint3264(tvb, offset, pinfo, NULL, di, drep, -1, &id);
3160
3161         /* we got a NULL pointer */
3162         if (id == 0) {
3163             proto_tree_add_bytes_format_value(tree, hf_dcerpc_null_pointer, tvb, offset-pointer_size,
3164                                 pointer_size, NULL, "%s", text);
3165             goto after_ref_id;
3166         }
3167
3168         /* see if we have seen this pointer before
3169            The value is truncated to 32bits.  64bit values have only been
3170            seen on fuzz-tested files */
3171         idx = find_pointer_index((guint32)id);
3172
3173         /* we have seen this pointer before */
3174         if (idx >= 0) {
3175             proto_tree_add_string(tree, hf_dcerpc_duplicate_ptr, tvb, offset-pointer_size, pointer_size, text);
3176             goto after_ref_id;
3177         }
3178
3179         /* new pointer */
3180         tr = proto_tree_add_subtree(tree, tvb, offset-pointer_size,
3181                                    pointer_size, ett_dcerpc_pointer_data, &item, text);
3182         if (di->call_data->flags & DCERPC_IS_NDR64) {
3183             proto_tree_add_uint64(tr, hf_dcerpc_referent_id64, tvb,
3184                                 offset-pointer_size, pointer_size, id);
3185         } else {
3186             proto_tree_add_uint(tr, hf_dcerpc_referent_id32, tvb,
3187                                 offset-pointer_size, pointer_size, (guint32)id);
3188         }
3189         add_pointer_to_list(pinfo, tr, item, di, fnct, (guint32)id, hf_index,
3190                             callback, callback_args);
3191         goto after_ref_id;
3192     }
3193     /*TOP LEVEL UNIQUE POINTER*/
3194     if ( pointers_are_top_level
3195         && (type == NDR_POINTER_UNIQUE) ) {
3196         guint64 id;
3197         proto_item *item;
3198
3199         /* get the referent id */
3200         offset = dissect_ndr_uint3264(tvb, offset, pinfo, NULL, di, drep, -1, &id);
3201
3202         /* we got a NULL pointer */
3203         if (id == 0) {
3204             proto_tree_add_bytes_format_value(tree, hf_dcerpc_null_pointer, tvb, offset-pointer_size,
3205                                 pointer_size, NULL, "%s",text);
3206             goto after_ref_id;
3207         }
3208
3209         /* new pointer */
3210         tr = proto_tree_add_subtree(tree, tvb, offset-pointer_size,
3211                                    pointer_size,
3212                                    ett_dcerpc_pointer_data, &item, text);
3213         if (di->call_data->flags & DCERPC_IS_NDR64) {
3214             proto_tree_add_uint64(tr, hf_dcerpc_referent_id64, tvb,
3215                             offset-pointer_size, pointer_size, id);
3216         } else {
3217             proto_tree_add_uint(tr, hf_dcerpc_referent_id32, tvb,
3218                             offset-pointer_size, pointer_size, (guint32)id);
3219         }
3220         add_pointer_to_list(pinfo, tr, item, di, fnct, 0xffffffff,
3221                             hf_index, callback, callback_args);
3222         goto after_ref_id;
3223     }
3224
3225     /*EMBEDDED REFERENCE POINTER*/
3226     if ( (!pointers_are_top_level)
3227         && (type == NDR_POINTER_REF) ) {
3228         guint64 id;
3229         proto_item *item;
3230
3231         /* get the referent id */
3232         offset = dissect_ndr_uint3264(tvb, offset, pinfo, NULL, di, drep, -1, &id);
3233
3234         /* new pointer */
3235         tr = proto_tree_add_subtree(tree, tvb, offset-pointer_size,
3236                                  pointer_size,
3237                                  ett_dcerpc_pointer_data,&item,text);
3238         if (di->call_data->flags & DCERPC_IS_NDR64) {
3239             proto_tree_add_uint64(tr, hf_dcerpc_referent_id64, tvb,
3240                             offset-pointer_size, pointer_size, id);
3241         } else {
3242             proto_tree_add_uint(tr, hf_dcerpc_referent_id32, tvb,
3243                             offset-pointer_size, pointer_size, (guint32)id);
3244         }
3245         add_pointer_to_list(pinfo, tr, item, di, fnct, 0xffffffff,
3246                             hf_index, callback, callback_args);
3247         goto after_ref_id;
3248     }
3249
3250     /*EMBEDDED UNIQUE POINTER*/
3251     if ( (!pointers_are_top_level)
3252         && (type == NDR_POINTER_UNIQUE) ) {
3253         guint64 id;
3254         proto_item *item;
3255
3256         /* get the referent id */
3257         offset = dissect_ndr_uint3264(tvb, offset, pinfo, NULL, di, drep, -1, &id);
3258
3259         /* we got a NULL pointer */
3260         if (id == 0) {
3261             proto_tree_add_bytes_format_value(tree, hf_dcerpc_null_pointer, tvb, offset-pointer_size,
3262                                 pointer_size, NULL, "%s",text);
3263             goto after_ref_id;
3264         }
3265
3266         /* new pointer */
3267         tr = proto_tree_add_subtree(tree, tvb, offset-pointer_size,
3268                                    pointer_size,
3269                                    ett_dcerpc_pointer_data,&item,text);
3270         if (di->call_data->flags & DCERPC_IS_NDR64) {
3271             proto_tree_add_uint64(tr, hf_dcerpc_referent_id64, tvb,
3272                             offset-pointer_size, pointer_size, id);
3273         } else {
3274             proto_tree_add_uint(tr, hf_dcerpc_referent_id32, tvb,
3275                             offset-pointer_size, pointer_size, (guint32)id);
3276         }
3277         add_pointer_to_list(pinfo, tr, item, di, fnct, 0xffffffff,
3278                             hf_index, callback, callback_args);
3279         goto after_ref_id;
3280     }
3281
3282     /*EMBEDDED FULL POINTER*/
3283     if ( (!pointers_are_top_level)
3284         && (type == NDR_POINTER_PTR) ) {
3285         int idx;
3286         guint64 id;
3287         proto_item *item;
3288
3289         /* get the referent id */
3290         offset = dissect_ndr_uint3264(tvb, offset, pinfo, NULL, di, drep, -1, &id);
3291
3292         /* we got a NULL pointer */
3293         if (id == 0) {
3294             proto_tree_add_bytes_format_value(tree, hf_dcerpc_null_pointer, tvb, offset-pointer_size,
3295                                 pointer_size, NULL, "%s",text);
3296             goto after_ref_id;
3297         }
3298
3299         /* see if we have seen this pointer before
3300            The value is truncated to 32bits.  64bit values have only been
3301            seen on fuzztested files */
3302         idx = find_pointer_index((guint32)id);
3303
3304         /* we have seen this pointer before */
3305         if (idx >= 0) {
3306             proto_tree_add_string(tree, hf_dcerpc_duplicate_ptr, tvb, offset-pointer_size, pointer_size, text);
3307             goto after_ref_id;
3308         }
3309
3310         /* new pointer */
3311         tr = proto_tree_add_subtree(tree, tvb, offset-pointer_size,
3312                                    pointer_size,
3313                                    ett_dcerpc_pointer_data, &item, text);
3314         if (di->call_data->flags & DCERPC_IS_NDR64) {
3315             proto_tree_add_uint64(tr, hf_dcerpc_referent_id64, tvb,
3316                             offset-pointer_size, pointer_size, id);
3317         } else {
3318             proto_tree_add_uint(tr, hf_dcerpc_referent_id32, tvb,
3319                             offset-pointer_size, pointer_size, (guint32)id);
3320         }
3321         add_pointer_to_list(pinfo, tr, item, di, fnct, (guint32)id, hf_index,
3322                             callback, callback_args);
3323         goto after_ref_id;
3324     }
3325
3326
3327 after_ref_id:
3328     /* After each top level pointer we have dissected we have to
3329        dissect all deferrals before we move on to the next top level
3330        argument */
3331     if (pointers_are_top_level == TRUE) {
3332         pointers_are_top_level = FALSE;
3333         offset = dissect_deferred_pointers(pinfo, tvb, offset, di, drep);
3334         pointers_are_top_level = TRUE;
3335     }
3336
3337     /* Set the length for the new subtree */
3338     if (tr) {
3339         proto_item_set_len(tr, offset-start_offset);
3340     }
3341     return offset;
3342 }
3343
3344 int
3345 dissect_ndr_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
3346                     proto_tree *tree, dcerpc_info *di, guint8 *drep, dcerpc_dissect_fnct_t *fnct,
3347                     int type, const char *text, int hf_index)
3348 {
3349     return dissect_ndr_pointer_cb(
3350         tvb, offset, pinfo, tree, di, drep, fnct, type, text, hf_index,
3351         NULL, NULL);
3352 }
3353 int
3354 dissect_ndr_toplevel_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
3355                              proto_tree *tree, dcerpc_info *di, guint8 *drep, dcerpc_dissect_fnct_t *fnct,
3356                              int type, const char *text, int hf_index)
3357 {
3358     int ret;
3359