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