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