Coverage Report

Created: 2026-05-14 06:28

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