Coverage Report

Created: 2026-07-12 07:10

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