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