Guy suggested that the dcerpc opnum value_string code could be simplified
[obnox/wireshark/wip.git] / packet-dcerpc.c
1 /* packet-dcerpc.c
2  * Routines for DCERPC packet disassembly
3  * Copyright 2001, Todd Sabin <tas@webspan.net>
4  * Copyright 2003, Tim Potter <tpot@samba.org>
5  *
6  * $Id: packet-dcerpc.c,v 1.138 2003/08/04 02:48:59 tpot Exp $
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@ethereal.com>
10  * Copyright 1998 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include <string.h>
32 #include <ctype.h>
33
34 #include <glib.h>
35 #include <epan/packet.h>
36 #include "packet-dcerpc.h"
37 #include <epan/conversation.h>
38 #include "prefs.h"
39 #include "reassemble.h"
40 #include "tap.h"
41 #include "packet-frame.h"
42 #include "packet-dcerpc-nt.h"
43
44 static int dcerpc_tap = -1;
45
46 static const value_string pckt_vals[] = {
47     { PDU_REQ,        "Request"},
48     { PDU_PING,       "Ping"},
49     { PDU_RESP,       "Response"},
50     { PDU_FAULT,      "Fault"},
51     { PDU_WORKING,    "Working"},
52     { PDU_NOCALL,     "Nocall"},
53     { PDU_REJECT,     "Reject"},
54     { PDU_ACK,        "Ack"},
55     { PDU_CL_CANCEL,  "Cl_cancel"},
56     { PDU_FACK,       "Fack"},
57     { PDU_CANCEL_ACK, "Cancel_ack"},
58     { PDU_BIND,       "Bind"},
59     { PDU_BIND_ACK,   "Bind_ack"},
60     { PDU_BIND_NAK,   "Bind_nak"},
61     { PDU_ALTER,      "Alter_context"},
62     { PDU_ALTER_ACK,  "Alter_context_resp"},
63     { PDU_AUTH3,      "AUTH3"},
64     { PDU_SHUTDOWN,   "Shutdown"},
65     { PDU_CO_CANCEL,  "Co_cancel"},
66     { PDU_ORPHANED,   "Orphaned"},
67     { 0,              NULL }
68 };
69
70 static const value_string drep_byteorder_vals[] = {
71     { 0, "Big-endian" },
72     { 1, "Little-endian" },
73     { 0,  NULL }
74 };
75
76 static const value_string drep_character_vals[] = {
77     { 0, "ASCII" },
78     { 1, "EBCDIC" },
79     { 0,  NULL }
80 };
81
82 #define DCE_RPC_DREP_FP_IEEE 0
83 #define DCE_RPC_DREP_FP_VAX  1
84 #define DCE_RPC_DREP_FP_CRAY 2
85 #define DCE_RPC_DREP_FP_IBM  3
86
87 static const value_string drep_fp_vals[] = {
88     { DCE_RPC_DREP_FP_IEEE, "IEEE" },
89     { DCE_RPC_DREP_FP_VAX,  "VAX"  },
90     { DCE_RPC_DREP_FP_CRAY, "Cray" },
91     { DCE_RPC_DREP_FP_IBM,  "IBM"  },
92     { 0,  NULL }
93 };
94
95 /*
96  * Authentication services.
97  */
98 static const value_string authn_protocol_vals[] = {
99         { DCE_C_RPC_AUTHN_PROTOCOL_NONE,    "None" },
100         { DCE_C_RPC_AUTHN_PROTOCOL_KRB5,    "Kerberos 5" },
101         { DCE_C_RPC_AUTHN_PROTOCOL_SPNEGO,  "SPNEGO" },
102         { DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP, "NTLMSSP" },
103         { DCE_C_RPC_AUTHN_PROTOCOL_SEC_CHAN,"NETLOGON Secure Channel" },
104         { 0, NULL }
105 };
106
107 /*
108  * Protection levels.
109  */
110 static const value_string authn_level_vals[] = {
111         { DCE_C_AUTHN_LEVEL_NONE,          "None" },
112         { DCE_C_AUTHN_LEVEL_CONNECT,       "Connect" },
113         { DCE_C_AUTHN_LEVEL_CALL,          "Call" },
114         { DCE_C_AUTHN_LEVEL_PKT,           "Packet" },
115         { DCE_C_AUTHN_LEVEL_PKT_INTEGRITY, "Packet integrity" },
116         { DCE_C_AUTHN_LEVEL_PKT_PRIVACY,   "Packet privacy" },
117         { 0,                               NULL }
118 };
119
120 /*
121  * Flag bits in first flag field in connectionless PDU header.
122  */
123 #define PFCL1_RESERVED_01       0x01    /* Reserved for use by implementations */
124 #define PFCL1_LASTFRAG          0x02    /* If set, the PDU is the last
125                                          * fragment of a multi-PDU
126                                          * transmission */
127 #define PFCL1_FRAG              0x04    /* If set, the PDU is a fragment of
128                                            a multi-PDU transmission */
129 #define PFCL1_NOFACK            0x08    /* If set, the receiver is not
130                                          * requested to send a `fack' PDU
131                                          * for the fragment */
132 #define PFCL1_MAYBE             0x10    /* If set, the PDU is for a `maybe'
133                                          * request */
134 #define PFCL1_IDEMPOTENT        0x20    /* If set, the PDU is for an idempotent
135                                          * request */
136 #define PFCL1_BROADCAST         0x40    /* If set, the PDU is for a broadcast
137                                          * request */
138 #define PFCL1_RESERVED_80       0x80    /* Reserved for use by implementations */
139
140 /*
141  * Flag bits in second flag field in connectionless PDU header.
142  */
143 #define PFCL2_RESERVED_01       0x01    /* Reserved for use by implementations */
144 #define PFCL2_CANCEL_PENDING    0x02    /* Cancel pending at the call end */
145 #define PFCL2_RESERVED_04       0x04    /* Reserved for future use */
146 #define PFCL2_RESERVED_08       0x08    /* Reserved for future use */
147 #define PFCL2_RESERVED_10       0x10    /* Reserved for future use */
148 #define PFCL2_RESERVED_20       0x20    /* Reserved for future use */
149 #define PFCL2_RESERVED_40       0x40    /* Reserved for future use */
150 #define PFCL2_RESERVED_80       0x80    /* Reserved for future use */
151
152 /*
153  * Flag bits in connection-oriented PDU header.
154  */
155 #define PFC_FIRST_FRAG          0x01    /* First fragment */
156 #define PFC_LAST_FRAG           0x02    /* Last fragment */
157 #define PFC_PENDING_CANCEL      0x04    /* Cancel was pending at sender */
158 #define PFC_RESERVED_1          0x08
159 #define PFC_CONC_MPX            0x10    /* suports concurrent multiplexing
160                                          * of a single connection. */
161 #define PFC_DID_NOT_EXECUTE     0x20    /* only meaningful on `fault' packet;
162                                          * if true, guaranteed call did not
163                                          * execute. */
164 #define PFC_MAYBE               0x40    /* `maybe' call semantics requested */
165 #define PFC_OBJECT_UUID         0x80    /* if true, a non-nil object UUID
166                                          * was specified in the handle, and
167                                          * is present in the optional object
168                                          * field. If false, the object field
169                                          * is omitted. */
170
171 /*
172  * Tests whether a connection-oriented PDU is fragmented; returns TRUE if
173  * it's not fragmented (i.e., this is both the first *and* last fragment),
174  * and FALSE otherwise.
175  */
176 #define PFC_NOT_FRAGMENTED(hdr) \
177   ((hdr->flags&(PFC_FIRST_FRAG|PFC_LAST_FRAG))==(PFC_FIRST_FRAG|PFC_LAST_FRAG))
178
179 /*
180  * Presentation context negotiation result.
181  */
182 static const value_string p_cont_result_vals[] = {
183         { 0, "Acceptance" },
184         { 1, "User rejection" },
185         { 2, "Provider rejection" },
186         { 0, NULL }
187 };
188
189 /*
190  * Presentation context negotiation rejection reasons.
191  */
192 static const value_string p_provider_reason_vals[] = {
193         { 0, "Reason not specified" },
194         { 1, "Abstract syntax not supported" },
195         { 2, "Proposed transfer syntaxes not supported" },
196         { 3, "Local limit exceeded" },
197         { 0, NULL }
198 };
199
200 /*
201  * Reject reasons.
202  */
203 #define REASON_NOT_SPECIFIED            0
204 #define TEMPORARY_CONGESTION            1
205 #define LOCAL_LIMIT_EXCEEDED            2
206 #define CALLED_PADDR_UNKNOWN            3 /* not used */
207 #define PROTOCOL_VERSION_NOT_SUPPORTED  4
208 #define DEFAULT_CONTEXT_NOT_SUPPORTED   5 /* not used */
209 #define USER_DATA_NOT_READABLE          6 /* not used */
210 #define NO_PSAP_AVAILABLE               7 /* not used */
211
212 static const value_string reject_reason_vals[] = {
213         { REASON_NOT_SPECIFIED,           "Reason not specified" },
214         { TEMPORARY_CONGESTION,           "Temporary congestion" },
215         { LOCAL_LIMIT_EXCEEDED,           "Local limit exceeded" },
216         { CALLED_PADDR_UNKNOWN,           "Called paddr unknown" },
217         { PROTOCOL_VERSION_NOT_SUPPORTED, "Protocol version not supported" },
218         { DEFAULT_CONTEXT_NOT_SUPPORTED,  "Default context not supported" },
219         { USER_DATA_NOT_READABLE,         "User data not readable" },
220         { NO_PSAP_AVAILABLE,              "No PSAP available" },
221         { 0,                              NULL }
222 };
223
224 /*
225  * Reject status codes.
226  */
227 static const value_string reject_status_vals[] = {
228         { 0,          "Stub-defined exception" },
229         { 0x1c000001, "nca_s_fault_int_div_by_zero" },
230         { 0x1c000002, "nca_s_fault_addr_error" },
231         { 0x1c000003, "nca_s_fault_fp_div_zero" },
232         { 0x1c000004, "nca_s_fault_fp_underflow" },
233         { 0x1c000005, "nca_s_fault_fp_overflow" },
234         { 0x1c000006, "nca_s_fault_invalid_tag" },
235         { 0x1c000007, "nca_s_fault_invalid_bound" },
236         { 0x1c000008, "nca_rpc_version_mismatch" },
237         { 0x1c000009, "nca_unspec_reject" },
238         { 0x1c00000a, "nca_s_bad_actid" },
239         { 0x1c00000b, "nca_who_are_you_failed" },
240         { 0x1c00000c, "nca_manager_not_entered" },
241         { 0x1c00000d, "nca_s_fault_cancel" },
242         { 0x1c00000e, "nca_s_fault_ill_inst" },
243         { 0x1c00000f, "nca_s_fault_fp_error" },
244         { 0x1c000010, "nca_s_fault_int_overflow" },
245         { 0x1c000014, "nca_s_fault_pipe_empty" },
246         { 0x1c000015, "nca_s_fault_pipe_closed" },
247         { 0x1c000016, "nca_s_fault_pipe_order" },
248         { 0x1c000017, "nca_s_fault_pipe_discipline" },
249         { 0x1c000018, "nca_s_fault_pipe_comm_error" },
250         { 0x1c000019, "nca_s_fault_pipe_memory" },
251         { 0x1c00001a, "nca_s_fault_context_mismatch" },
252         { 0x1c00001b, "nca_s_fault_remote_no_memory" },
253         { 0x1c00001c, "nca_invalid_pres_context_id" },
254         { 0x1c00001d, "nca_unsupported_authn_level" },
255         { 0x1c00001f, "nca_invalid_checksum" },
256         { 0x1c000020, "nca_invalid_crc" },
257         { 0x1c000021, "ncs_s_fault_user_defined" },
258         { 0x1c000022, "nca_s_fault_tx_open_failed" },
259         { 0x1c000023, "nca_s_fault_codeset_conv_error" },
260         { 0x1c000024, "nca_s_fault_object_not_found" },
261         { 0x1c000025, "nca_s_fault_no_client_stub" },
262         { 0x1c010002, "nca_op_rng_error" },
263         { 0x1c010003, "nca_unk_if"},
264         { 0x1c010006, "nca_wrong_boot_time" },
265         { 0x1c010009, "nca_s_you_crashed" },
266         { 0x1c01000b, "nca_proto_error" },
267         { 0x1c010013, "nca_out_args_too_big" },
268         { 0x1c010014, "nca_server_too_busy" },
269         { 0x1c010017, "nca_unsupported_type" },
270         { 0,          NULL }
271 };
272
273 static int proto_dcerpc = -1;
274
275 /* field defines */
276 static int hf_dcerpc_request_in = -1;
277 static int hf_dcerpc_time = -1;
278 static int hf_dcerpc_response_in = -1;
279 static int hf_dcerpc_ver = -1;
280 static int hf_dcerpc_ver_minor = -1;
281 static int hf_dcerpc_packet_type = -1;
282 static int hf_dcerpc_cn_flags = -1;
283 static int hf_dcerpc_cn_flags_first_frag = -1;
284 static int hf_dcerpc_cn_flags_last_frag = -1;
285 static int hf_dcerpc_cn_flags_cancel_pending = -1;
286 static int hf_dcerpc_cn_flags_reserved = -1;
287 static int hf_dcerpc_cn_flags_mpx = -1;
288 static int hf_dcerpc_cn_flags_dne = -1;
289 static int hf_dcerpc_cn_flags_maybe = -1;
290 static int hf_dcerpc_cn_flags_object = -1;
291 static int hf_dcerpc_drep = -1;
292 static int hf_dcerpc_drep_byteorder = -1;
293 static int hf_dcerpc_drep_character = -1;
294 static int hf_dcerpc_drep_fp = -1;
295 static int hf_dcerpc_cn_frag_len = -1;
296 static int hf_dcerpc_cn_auth_len = -1;
297 static int hf_dcerpc_cn_call_id = -1;
298 static int hf_dcerpc_cn_max_xmit = -1;
299 static int hf_dcerpc_cn_max_recv = -1;
300 static int hf_dcerpc_cn_assoc_group = -1;
301 static int hf_dcerpc_cn_num_ctx_items = -1;
302 static int hf_dcerpc_cn_ctx_id = -1;
303 static int hf_dcerpc_cn_num_trans_items = -1;
304 static int hf_dcerpc_cn_bind_if_id = -1;
305 static int hf_dcerpc_cn_bind_if_ver = -1;
306 static int hf_dcerpc_cn_bind_if_ver_minor = -1;
307 static int hf_dcerpc_cn_bind_trans_id = -1;
308 static int hf_dcerpc_cn_bind_trans_ver = -1;
309 static int hf_dcerpc_cn_alloc_hint = -1;
310 static int hf_dcerpc_cn_sec_addr_len = -1;
311 static int hf_dcerpc_cn_sec_addr = -1;
312 static int hf_dcerpc_cn_num_results = -1;
313 static int hf_dcerpc_cn_ack_result = -1;
314 static int hf_dcerpc_cn_ack_reason = -1;
315 static int hf_dcerpc_cn_ack_trans_id = -1;
316 static int hf_dcerpc_cn_ack_trans_ver = -1;
317 static int hf_dcerpc_cn_reject_reason = -1;
318 static int hf_dcerpc_cn_num_protocols = -1;
319 static int hf_dcerpc_cn_protocol_ver_major = -1;
320 static int hf_dcerpc_cn_protocol_ver_minor = -1;
321 static int hf_dcerpc_cn_cancel_count = -1;
322 static int hf_dcerpc_cn_status = -1;
323 static int hf_dcerpc_auth_type = -1;
324 static int hf_dcerpc_auth_level = -1;
325 static int hf_dcerpc_auth_pad_len = -1;
326 static int hf_dcerpc_auth_rsrvd = -1;
327 static int hf_dcerpc_auth_ctx_id = -1;
328 static int hf_dcerpc_dg_flags1 = -1;
329 static int hf_dcerpc_dg_flags1_rsrvd_01 = -1;
330 static int hf_dcerpc_dg_flags1_last_frag = -1;
331 static int hf_dcerpc_dg_flags1_frag = -1;
332 static int hf_dcerpc_dg_flags1_nofack = -1;
333 static int hf_dcerpc_dg_flags1_maybe = -1;
334 static int hf_dcerpc_dg_flags1_idempotent = -1;
335 static int hf_dcerpc_dg_flags1_broadcast = -1;
336 static int hf_dcerpc_dg_flags1_rsrvd_80 = -1;
337 static int hf_dcerpc_dg_flags2 = -1;
338 static int hf_dcerpc_dg_flags2_rsrvd_01 = -1;
339 static int hf_dcerpc_dg_flags2_cancel_pending = -1;
340 static int hf_dcerpc_dg_flags2_rsrvd_04 = -1;
341 static int hf_dcerpc_dg_flags2_rsrvd_08 = -1;
342 static int hf_dcerpc_dg_flags2_rsrvd_10 = -1;
343 static int hf_dcerpc_dg_flags2_rsrvd_20 = -1;
344 static int hf_dcerpc_dg_flags2_rsrvd_40 = -1;
345 static int hf_dcerpc_dg_flags2_rsrvd_80 = -1;
346 static int hf_dcerpc_dg_serial_hi = -1;
347 static int hf_dcerpc_obj_id = -1;
348 static int hf_dcerpc_dg_if_id = -1;
349 static int hf_dcerpc_dg_act_id = -1;
350 static int hf_dcerpc_dg_serial_lo = -1;
351 static int hf_dcerpc_dg_ahint = -1;
352 static int hf_dcerpc_dg_ihint = -1;
353 static int hf_dcerpc_dg_frag_len = -1;
354 static int hf_dcerpc_dg_frag_num = -1;
355 static int hf_dcerpc_dg_auth_proto = -1;
356 static int hf_dcerpc_opnum = -1;
357 static int hf_dcerpc_dg_seqnum = -1;
358 static int hf_dcerpc_dg_server_boot = -1;
359 static int hf_dcerpc_dg_if_ver = -1;
360 static int hf_dcerpc_krb5_av_prot_level = -1;
361 static int hf_dcerpc_krb5_av_key_vers_num = -1;
362 static int hf_dcerpc_krb5_av_key_auth_verifier = -1;
363 static int hf_dcerpc_dg_cancel_vers = -1;
364 static int hf_dcerpc_dg_cancel_id = -1;
365 static int hf_dcerpc_dg_server_accepting_cancels = -1;
366 static int hf_dcerpc_dg_fack_vers = -1;
367 static int hf_dcerpc_dg_fack_window_size = -1;
368 static int hf_dcerpc_dg_fack_max_tsdu = -1;
369 static int hf_dcerpc_dg_fack_max_frag_size = -1;
370 static int hf_dcerpc_dg_fack_serial_num = -1;
371 static int hf_dcerpc_dg_fack_selack_len = -1;
372 static int hf_dcerpc_dg_fack_selack = -1;
373 static int hf_dcerpc_dg_status = -1;
374 static int hf_dcerpc_array_max_count = -1;
375 static int hf_dcerpc_array_offset = -1;
376 static int hf_dcerpc_array_actual_count = -1;
377 static int hf_dcerpc_array_buffer = -1;
378 static int hf_dcerpc_op = -1;
379 static int hf_dcerpc_referent_id = -1;
380 static int hf_dcerpc_fragments = -1;
381 static int hf_dcerpc_fragment = -1;
382 static int hf_dcerpc_fragment_overlap = -1;
383 static int hf_dcerpc_fragment_overlap_conflict = -1;
384 static int hf_dcerpc_fragment_multiple_tails = -1;
385 static int hf_dcerpc_fragment_too_long_fragment = -1;
386 static int hf_dcerpc_fragment_error = -1;
387 static int hf_dcerpc_reassembled_in = -1;
388
389 static gint ett_dcerpc = -1;
390 static gint ett_dcerpc_cn_flags = -1;
391 static gint ett_dcerpc_drep = -1;
392 static gint ett_dcerpc_dg_flags1 = -1;
393 static gint ett_dcerpc_dg_flags2 = -1;
394 static gint ett_dcerpc_pointer_data = -1;
395 static gint ett_dcerpc_string = -1;
396 static gint ett_dcerpc_fragments = -1;
397 static gint ett_dcerpc_fragment = -1;
398 static gint ett_dcerpc_krb5_auth_verf = -1;
399
400 static const fragment_items dcerpc_frag_items = {
401         &ett_dcerpc_fragments,
402         &ett_dcerpc_fragment,
403
404         &hf_dcerpc_fragments,
405         &hf_dcerpc_fragment,
406         &hf_dcerpc_fragment_overlap,
407         &hf_dcerpc_fragment_overlap_conflict,
408         &hf_dcerpc_fragment_multiple_tails,
409         &hf_dcerpc_fragment_too_long_fragment,
410         &hf_dcerpc_fragment_error,
411         NULL,
412
413         "fragments"
414 };
415
416 typedef struct _dcerpc_auth_info {
417   guint8 auth_pad_len;
418   guint8 auth_level;
419   guint8 auth_type;
420   guint32 auth_size;
421 } dcerpc_auth_info;
422
423 /* try to desegment big DCE/RPC packets over TCP? */
424 static gboolean dcerpc_cn_desegment = TRUE;
425
426 /* reassemble DCE/RPC fragments */
427 /* reassembly of dcerpc fragments will not work for the case where ONE frame
428    might contain multiple dcerpc fragments for different PDUs.
429    this case would be so unusual/weird so if you got captures like that:
430         too bad
431 */
432 static gboolean dcerpc_reassemble = FALSE;
433 static GHashTable *dcerpc_co_reassemble_table = NULL;
434 static GHashTable *dcerpc_cl_reassemble_table = NULL;
435
436 static void
437 dcerpc_reassemble_init(void)
438 {
439   fragment_table_init(&dcerpc_co_reassemble_table);
440   fragment_table_init(&dcerpc_cl_reassemble_table);
441 }
442
443 /*
444  * Authentication subdissectors.  Used to dissect authentication blobs in
445  * DCERPC binds, requests and responses.
446  */
447
448 typedef struct _dcerpc_auth_subdissector {
449         guint8 auth_level;
450         guint8 auth_type;
451         dcerpc_auth_subdissector_fns auth_fns;
452 } dcerpc_auth_subdissector;
453
454 static GSList *dcerpc_auth_subdissector_list;
455
456 static dcerpc_auth_subdissector_fns *get_auth_subdissector_fns(
457         guint8 auth_level, guint8 auth_type)
458 {
459         gpointer data;
460         int i;
461
462         for (i = 0; (data = g_slist_nth_data(dcerpc_auth_subdissector_list, i)); i++) {
463                 dcerpc_auth_subdissector *asd = (dcerpc_auth_subdissector *)data;
464
465                 if (asd->auth_level == auth_level && 
466                     asd->auth_type == auth_type)
467                         return &asd->auth_fns;
468         }
469
470         return NULL;
471 }
472
473 void register_dcerpc_auth_subdissector(guint8 auth_level, guint8 auth_type,
474                                        dcerpc_auth_subdissector_fns *fns)
475 {
476         dcerpc_auth_subdissector *d;
477
478         if (get_auth_subdissector_fns(auth_level, auth_type))
479                 return;
480
481         d = (dcerpc_auth_subdissector *)g_malloc(sizeof(dcerpc_auth_subdissector));
482
483         d->auth_level = auth_level;
484         d->auth_type = auth_type;
485         memcpy(&d->auth_fns, fns, sizeof(dcerpc_auth_subdissector_fns));
486
487         dcerpc_auth_subdissector_list = g_slist_append(dcerpc_auth_subdissector_list, d);
488 }
489
490 /* Hand off verifier data to a registered dissector */
491
492 static void dissect_auth_verf(tvbuff_t *auth_tvb, packet_info *pinfo,
493                               proto_tree *tree, 
494                               dcerpc_auth_subdissector_fns *auth_fns,
495                               e_dce_cn_common_hdr_t *hdr, 
496                               dcerpc_auth_info *auth_info)
497 {
498         dcerpc_dissect_fnct_t *fn = NULL;
499
500         switch (hdr->ptype) {
501         case PDU_BIND:
502         case PDU_ALTER:
503                 fn = auth_fns->bind_fn;
504                 break;
505         case PDU_BIND_ACK:
506         case PDU_ALTER_ACK:
507                 fn = auth_fns->bind_ack_fn;
508                 break;
509         case PDU_AUTH3:
510                 fn = auth_fns->auth3_fn;
511                 break;
512         case PDU_REQ:
513                 fn = auth_fns->req_verf_fn;
514                 break;
515         case PDU_RESP:
516                 fn = auth_fns->resp_verf_fn;
517                 break;
518
519                 /* Don't know how to handle authentication data in this 
520                    pdu type. */
521
522         default:
523                 g_warning("attempt to dissect %s pdu authentication data",
524                           val_to_str(hdr->ptype, pckt_vals, "Unknown (%u)"));
525                 break;
526         }
527
528         if (fn)
529                 fn(auth_tvb, 0, pinfo, tree, hdr->drep);
530         else
531                 proto_tree_add_text(tree, auth_tvb, 0, hdr->auth_len,
532                                     "%s Verifier", 
533                                     val_to_str(auth_info->auth_type, 
534                                                authn_protocol_vals,
535                                                "Unknown (%u)"));
536 }
537
538 /* Hand off payload data to a registered dissector */
539
540 static void dissect_encrypted_data(tvbuff_t *enc_tvb, packet_info *pinfo,
541                                    proto_tree *tree,
542                                    dcerpc_auth_subdissector_fns *auth_fns,
543                                    guint8 ptype, char *drep)
544 {
545         dcerpc_dissect_fnct_t *fn = NULL;
546
547         switch (ptype) {
548         case PDU_REQ:
549                 fn = auth_fns->req_data_fn;
550                 break;
551         case PDU_RESP:
552                 fn = auth_fns->resp_data_fn;
553                 break;
554         default:
555                 g_warning("attempt to dissect %s pdu encrypted data",
556                           val_to_str(ptype, pckt_vals, "Unknown (%u)"));
557                 break;          
558         }
559
560         if (fn)
561                 fn(enc_tvb, 0, pinfo, tree, drep);
562 }
563
564 /*
565  * Subdissectors
566  */
567
568 /* the registered subdissectors */
569 GHashTable *dcerpc_uuids=NULL;
570
571 static gint
572 dcerpc_uuid_equal (gconstpointer k1, gconstpointer k2)
573 {
574     const dcerpc_uuid_key *key1 = (const dcerpc_uuid_key *)k1;
575     const dcerpc_uuid_key *key2 = (const dcerpc_uuid_key *)k2;
576     return ((memcmp (&key1->uuid, &key2->uuid, sizeof (e_uuid_t)) == 0)
577             && (key1->ver == key2->ver));
578 }
579
580 static guint
581 dcerpc_uuid_hash (gconstpointer k)
582 {
583     const dcerpc_uuid_key *key = (const dcerpc_uuid_key *)k;
584     /* This isn't perfect, but the Data1 part of these is almost always
585        unique. */
586     return key->uuid.Data1;
587 }
588
589 void
590 dcerpc_init_uuid (int proto, int ett, e_uuid_t *uuid, guint16 ver,
591                   dcerpc_sub_dissector *procs, int opnum_hf)
592 {
593     dcerpc_uuid_key *key = g_malloc (sizeof (*key));
594     dcerpc_uuid_value *value = g_malloc (sizeof (*value));
595     header_field_info *hf_info;
596
597     key->uuid = *uuid;
598     key->ver = ver;
599
600     value->proto = proto;
601     value->ett = ett;
602     value->name = proto_get_protocol_short_name (proto);
603     value->procs = procs;
604     value->opnum_hf = opnum_hf;
605
606     g_hash_table_insert (dcerpc_uuids, key, value);
607
608     hf_info = proto_registrar_get_nth(opnum_hf);
609     hf_info->strings = value_string_from_subdissectors(procs);
610 }
611
612 /* Function to find the name of a registered protocol
613  * or NULL if the protocol/version is not known to ethereal.
614  */
615 char *
616 dcerpc_get_proto_name(e_uuid_t *uuid, guint16 ver)
617 {
618     dcerpc_uuid_key key;
619     dcerpc_uuid_value *sub_proto;
620
621     key.uuid = *uuid;
622     key.ver = ver;
623     if(!(sub_proto = g_hash_table_lookup (dcerpc_uuids, &key))){
624         return NULL;
625     }
626     return sub_proto->name;
627 }
628
629 /* Create a value_string consisting of DCERPC opnum and name from a
630    subdissector array. */
631
632 value_string *value_string_from_subdissectors(dcerpc_sub_dissector *sd)
633 {
634         value_string *vs = NULL;
635         int i, num_sd = 0;
636
637  again:
638         for (i = 0; sd[i].name; i++) {
639                 if (vs) {
640                         vs[i].value = sd[i].num;
641                         vs[i].strptr = sd[i].name;
642                 } else
643                         num_sd++;
644         }
645
646         if (!vs) {
647                 vs = g_malloc((num_sd + 1) * sizeof(value_string));
648                 goto again;
649         }
650
651         vs[num_sd].value = 0;
652         vs[num_sd].strptr = NULL;
653
654         return vs;
655 }
656
657 /* Function to find the subdissector table of a registered protocol
658  * or NULL if the protocol/version is not known to ethereal.
659  */
660 dcerpc_sub_dissector *
661 dcerpc_get_proto_sub_dissector(e_uuid_t *uuid, guint16 ver)
662 {
663     dcerpc_uuid_key key;
664     dcerpc_uuid_value *sub_proto;
665
666     key.uuid = *uuid;
667     key.ver = ver;
668     if(!(sub_proto = g_hash_table_lookup (dcerpc_uuids, &key))){
669         return NULL;
670     }
671     return sub_proto->procs;
672 }
673
674
675 /*
676  * To keep track of ctx_id mappings.
677  *
678  * Everytime we see a bind call we update this table.
679  * Note that we always specify a SMB FID. For non-SMB transports this
680  * value is 0.
681  */
682 static GHashTable *dcerpc_binds=NULL;
683
684 typedef struct _dcerpc_bind_key {
685     conversation_t *conv;
686     guint16 ctx_id;
687     guint16 smb_fid;
688 } dcerpc_bind_key;
689
690 typedef struct _dcerpc_bind_value {
691         e_uuid_t uuid;
692         guint16 ver;
693 } dcerpc_bind_value;
694
695 static GMemChunk *dcerpc_bind_key_chunk=NULL;
696 static GMemChunk *dcerpc_bind_value_chunk=NULL;
697
698 static gint
699 dcerpc_bind_equal (gconstpointer k1, gconstpointer k2)
700 {
701     const dcerpc_bind_key *key1 = (const dcerpc_bind_key *)k1;
702     const dcerpc_bind_key *key2 = (const dcerpc_bind_key *)k2;
703     return (key1->conv == key2->conv
704             && key1->ctx_id == key2->ctx_id
705             && key1->smb_fid == key2->smb_fid);
706 }
707
708 static guint
709 dcerpc_bind_hash (gconstpointer k)
710 {
711     const dcerpc_bind_key *key = (const dcerpc_bind_key *)k;
712     return GPOINTER_TO_UINT(key->conv) + key->ctx_id + key->smb_fid;
713
714 }
715
716 /*
717  * To keep track of callid mappings.  Should really use some generic
718  * conversation support instead.
719  */
720 static GHashTable *dcerpc_calls=NULL;
721
722 typedef struct _dcerpc_call_key {
723     conversation_t *conv;
724     guint32 call_id;
725     guint16 smb_fid;
726 } dcerpc_call_key;
727
728 static GMemChunk *dcerpc_call_key_chunk=NULL;
729
730 static GMemChunk *dcerpc_call_value_chunk=NULL;
731
732 static gint
733 dcerpc_call_equal (gconstpointer k1, gconstpointer k2)
734 {
735     const dcerpc_call_key *key1 = (const dcerpc_call_key *)k1;
736     const dcerpc_call_key *key2 = (const dcerpc_call_key *)k2;
737     return (key1->conv == key2->conv
738             && key1->call_id == key2->call_id
739             && key1->smb_fid == key2->smb_fid);
740 }
741
742 static guint
743 dcerpc_call_hash (gconstpointer k)
744 {
745     const dcerpc_call_key *key = (const dcerpc_call_key *)k;
746     return ((guint32)key->conv) + key->call_id + key->smb_fid;
747 }
748
749
750 /* to keep track of matched calls/responses
751    this one uses the same value struct as calls, but the key is the frame id
752    and call id; there can be more than one call in a frame.
753
754    XXX - why not just use the same keys as are used for calls?
755 */
756
757 static GHashTable *dcerpc_matched=NULL;
758
759 typedef struct _dcerpc_matched_key {
760     guint32 frame;
761     guint32 call_id;
762 } dcerpc_matched_key;
763
764 static GMemChunk *dcerpc_matched_key_chunk=NULL;
765
766 static gint
767 dcerpc_matched_equal (gconstpointer k1, gconstpointer k2)
768 {
769     const dcerpc_matched_key *key1 = (const dcerpc_matched_key *)k1;
770     const dcerpc_matched_key *key2 = (const dcerpc_matched_key *)k2;
771     return (key1->frame == key2->frame
772             && key1->call_id == key2->call_id);
773 }
774
775 static guint
776 dcerpc_matched_hash (gconstpointer k)
777 {
778     const dcerpc_matched_key *key = (const dcerpc_matched_key *)k;
779     return key->frame;
780 }
781
782
783
784 /*
785  * Utility functions.  Modeled after packet-rpc.c
786  */
787
788 int
789 dissect_dcerpc_uint8 (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
790                       proto_tree *tree, char *drep,
791                       int hfindex, guint8 *pdata)
792 {
793     guint8 data;
794
795     data = tvb_get_guint8 (tvb, offset);
796     if (tree) {
797         proto_tree_add_item (tree, hfindex, tvb, offset, 1, (drep[0] & 0x10));
798     }
799     if (pdata)
800         *pdata = data;
801     return offset + 1;
802 }
803
804 int
805 dissect_dcerpc_uint16 (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
806                        proto_tree *tree, char *drep,
807                        int hfindex, guint16 *pdata)
808 {
809     guint16 data;
810
811     data = ((drep[0] & 0x10)
812             ? tvb_get_letohs (tvb, offset)
813             : tvb_get_ntohs (tvb, offset));
814
815     if (tree) {
816         proto_tree_add_item (tree, hfindex, tvb, offset, 2, (drep[0] & 0x10));
817     }
818     if (pdata)
819         *pdata = data;
820     return offset + 2;
821 }
822
823 int
824 dissect_dcerpc_uint32 (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
825                        proto_tree *tree, char *drep,
826                        int hfindex, guint32 *pdata)
827 {
828     guint32 data;
829
830     data = ((drep[0] & 0x10)
831             ? tvb_get_letohl (tvb, offset)
832             : tvb_get_ntohl (tvb, offset));
833
834     if (tree) {
835         proto_tree_add_item (tree, hfindex, tvb, offset, 4, (drep[0] & 0x10));
836     }
837     if (pdata)
838         *pdata = data;
839     return offset+4;
840 }
841
842 /* handles 32 bit unix time_t */
843 int
844 dissect_dcerpc_time_t (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
845                        proto_tree *tree, char *drep,
846                        int hfindex, guint32 *pdata)
847 {
848     guint32 data;
849     nstime_t tv;
850
851     data = ((drep[0] & 0x10)
852             ? tvb_get_letohl (tvb, offset)
853             : tvb_get_ntohl (tvb, offset));
854
855     tv.secs=data;
856     tv.nsecs=0;
857     if (tree) {
858         proto_tree_add_time (tree, hfindex, tvb, offset, 4, &tv);
859     }
860     if (pdata)
861         *pdata = data;
862
863     return offset+4;
864 }
865
866 int
867 dissect_dcerpc_uint64 (tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
868                        proto_tree *tree, char *drep,
869                        int hfindex, unsigned char *pdata)
870 {
871     if(pdata){
872       tvb_memcpy(tvb, pdata, offset, 8);
873       if(drep[0] & 0x10){/* XXX this might be the wrong way around */
874         unsigned char data;
875         data=pdata[0];pdata[0]=pdata[7];pdata[7]=data;
876         data=pdata[1];pdata[1]=pdata[6];pdata[6]=data;
877         data=pdata[2];pdata[2]=pdata[5];pdata[5]=data;
878         data=pdata[3];pdata[3]=pdata[4];pdata[4]=data;
879       }
880     }
881
882     if (tree) {
883         proto_tree_add_item(tree, hfindex, tvb, offset, 8, (drep[0] & 0x10));
884     }
885
886     return offset+8;
887 }
888
889
890 int
891 dissect_dcerpc_float(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
892                     proto_tree *tree, char *drep, 
893                     int hfindex, gfloat *pdata)
894 {
895         gfloat data;
896
897
898         switch(drep[1]) {
899                 case(DCE_RPC_DREP_FP_IEEE):
900                         data = ((drep[0] & 0x10)
901                                         ? tvb_get_letohieee_float(tvb, offset)
902                                         : tvb_get_ntohieee_float(tvb, offset));
903                         if (tree) {
904                                 proto_tree_add_float(tree, hfindex, tvb, offset, 4, data);
905                         }
906                         break;
907                 case(DCE_RPC_DREP_FP_VAX):  /* (fall trough) */
908                 case(DCE_RPC_DREP_FP_CRAY): /* (fall trough) */
909                 case(DCE_RPC_DREP_FP_IBM):  /* (fall trough) */
910                 default:
911                         /* ToBeDone: non IEEE floating formats */
912                         /* Set data to a negative infinity value */
913                         data = -1.0 * 1e100 * 1e100;
914                         if (tree) {
915                                 proto_tree_add_debug_text(tree, "DCE RPC: dissection of non IEEE floating formats currently not implemented (drep=%u)!", drep[1]);
916                         }
917         }
918     if (pdata)
919         *pdata = data;
920     return offset + 4;
921 }
922
923
924 int
925 dissect_dcerpc_double(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
926                     proto_tree *tree, char *drep, 
927                     int hfindex, gdouble *pdata)
928 {
929     gdouble data;
930
931
932         switch(drep[1]) {
933                 case(DCE_RPC_DREP_FP_IEEE):
934                         data = ((drep[0] & 0x10)
935                                         ? tvb_get_letohieee_double(tvb, offset)
936                                         : tvb_get_ntohieee_double(tvb, offset));
937                         if (tree) {
938                                 proto_tree_add_double(tree, hfindex, tvb, offset, 8, data);
939                         }
940                         break;
941                 case(DCE_RPC_DREP_FP_VAX):  /* (fall trough) */
942                 case(DCE_RPC_DREP_FP_CRAY): /* (fall trough) */
943                 case(DCE_RPC_DREP_FP_IBM):  /* (fall trough) */
944                 default:
945                         /* ToBeDone: non IEEE double formats */
946                         /* Set data to a negative infinity value */
947                         data = -1.0 * 1e100 * 1e100;
948                         if (tree) {
949                                 proto_tree_add_debug_text(tree, "DCE RPC: dissection of non IEEE double formats currently not implemented (drep=%u)!", drep[1]);
950                         }
951         }
952     if (pdata)
953         *pdata = data;
954     return offset + 8;
955 }
956
957
958 /*
959  * a couple simpler things
960  */
961 guint16
962 dcerpc_tvb_get_ntohs (tvbuff_t *tvb, gint offset, char *drep)
963 {
964     if (drep[0] & 0x10) {
965         return tvb_get_letohs (tvb, offset);
966     } else {
967         return tvb_get_ntohs (tvb, offset);
968     }
969 }
970
971 guint32
972 dcerpc_tvb_get_ntohl (tvbuff_t *tvb, gint offset, char *drep)
973 {
974     if (drep[0] & 0x10) {
975         return tvb_get_letohl (tvb, offset);
976     } else {
977         return tvb_get_ntohl (tvb, offset);
978     }
979 }
980
981 void
982 dcerpc_tvb_get_uuid (tvbuff_t *tvb, gint offset, char *drep, e_uuid_t *uuid)
983 {
984     unsigned int i;
985     uuid->Data1 = dcerpc_tvb_get_ntohl (tvb, offset, drep);
986     uuid->Data2 = dcerpc_tvb_get_ntohs (tvb, offset+4, drep);
987     uuid->Data3 = dcerpc_tvb_get_ntohs (tvb, offset+6, drep);
988
989     for (i=0; i<sizeof (uuid->Data4); i++) {
990         uuid->Data4[i] = tvb_get_guint8 (tvb, offset+8+i);
991     }
992 }
993
994
995
996 /* NDR arrays */
997 /* function to dissect a unidimensional conformant array */
998 int
999 dissect_ndr_ucarray(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1000                 proto_tree *tree, char *drep,
1001                 dcerpc_dissect_fnct_t *fnct)
1002 {
1003         guint32 i;
1004         dcerpc_info *di;
1005         int old_offset;
1006
1007         di=pinfo->private_data;
1008         if(di->conformant_run){
1009                 /* conformant run, just dissect the max_count header */
1010                 old_offset=offset;
1011                 di->conformant_run=0;
1012                 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1013                                 hf_dcerpc_array_max_count, &di->array_max_count);
1014                 di->array_max_count_offset=offset-4;
1015                 di->conformant_run=1;
1016                 di->conformant_eaten=offset-old_offset;
1017         } else {
1018                 /* we don't remember where in the bytestream this field was */
1019                 proto_tree_add_uint(tree, hf_dcerpc_array_max_count, tvb, di->array_max_count_offset, 4, di->array_max_count);
1020
1021                 /* real run, dissect the elements */
1022                 for(i=0;i<di->array_max_count;i++){
1023                         offset = (*fnct)(tvb, offset, pinfo, tree, drep);
1024                 }
1025         }
1026
1027         return offset;
1028 }
1029 /* function to dissect a unidimensional conformant and varying array */
1030 int
1031 dissect_ndr_ucvarray(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1032                 proto_tree *tree, char *drep,
1033                 dcerpc_dissect_fnct_t *fnct)
1034 {
1035         guint32 i;
1036         dcerpc_info *di;
1037         int old_offset;
1038
1039         di=pinfo->private_data;
1040         if(di->conformant_run){
1041                 /* conformant run, just dissect the max_count header */
1042                 old_offset=offset;
1043                 di->conformant_run=0;
1044                 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1045                                 hf_dcerpc_array_max_count, &di->array_max_count);
1046                 di->array_max_count_offset=offset-4;
1047                 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1048                                 hf_dcerpc_array_offset, &di->array_offset);
1049                 di->array_offset_offset=offset-4;
1050                 offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
1051                                 hf_dcerpc_array_actual_count, &di->array_actual_count);
1052                 di->array_actual_count_offset=offset-4;
1053                 di->conformant_run=1;
1054                 di->conformant_eaten=offset-old_offset;
1055         } else {
1056                 /* we dont dont remember where  in the bytestream these fields were */
1057                 proto_tree_add_uint(tree, hf_dcerpc_array_max_count, tvb, di->array_max_count_offset, 4, di->array_max_count);
1058                 proto_tree_add_uint(tree, hf_dcerpc_array_offset, tvb, di->array_offset_offset, 4, di->array_offset);
1059                 proto_tree_add_uint(tree, hf_dcerpc_array_actual_count, tvb, di->array_actual_count_offset, 4, di->array_actual_count);
1060
1061                 /* real run, dissect the elements */
1062                 for(i=0;i<di->array_actual_count;i++){
1063                         offset = (*fnct)(tvb, offset, pinfo, tree, drep);
1064                 }
1065         }
1066
1067         return offset;
1068 }
1069
1070 /* Dissect an string of bytes.  This corresponds to
1071    IDL of the form '[string] byte *foo'.
1072
1073    It can also be used for a conformant varying array of bytes if
1074    the contents of the array should be shown as a big blob, rather
1075    than showing each byte as an individual element.
1076
1077    XXX - which of those is really the IDL type for, for example,
1078    the encrypted data in some MAPI packets?  (Microsoft haven't
1079    released that IDL.)
1080
1081    XXX - does this need to do all the conformant array stuff that
1082    "dissect_ndr_ucvarray()" does?  These are presumably for strings
1083    that are conformant and varying - they're stored like conformant
1084    varying arrays of bytes.  */
1085 int
1086 dissect_ndr_byte_array(tvbuff_t *tvb, int offset, packet_info *pinfo, 
1087                             proto_tree *tree, char *drep)
1088 {
1089     dcerpc_info *di;
1090     guint32 len;
1091
1092     di=pinfo->private_data;
1093     if(di->conformant_run){
1094       /* just a run to handle conformant arrays, no scalars to dissect */
1095       return offset;
1096     }
1097
1098     /* NDR array header */
1099
1100     offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
1101                                 hf_dcerpc_array_max_count, NULL);
1102
1103     offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
1104                                 hf_dcerpc_array_offset, NULL);
1105
1106     offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
1107                                 hf_dcerpc_array_actual_count, &len);
1108
1109     if (tree && len)
1110         proto_tree_add_item(tree, hf_dcerpc_array_buffer,
1111                             tvb, offset, len, drep[0] & 0x10);
1112
1113     offset += len;
1114
1115     return offset;
1116 }
1117
1118 /* For dissecting arrays that are to be interpreted as strings.  */
1119
1120 /* Dissect an NDR conformant varying string of elements.
1121    The length of each element is given by the 'size_is' parameter;
1122    the elements are assumed to be characters or wide characters.
1123
1124    XXX - does this need to do all the conformant array stuff that
1125    "dissect_ndr_ucvarray()" does?  */
1126 int
1127 dissect_ndr_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo, 
1128                      proto_tree *tree, char *drep, int size_is,
1129                      int hfindex, gboolean add_subtree, char **data)
1130 {
1131     dcerpc_info *di;
1132     proto_item *string_item;
1133     proto_tree *string_tree;
1134     guint32 len, buffer_len;
1135     char *s;
1136     header_field_info *hfinfo;
1137
1138     di=pinfo->private_data;
1139     if(di->conformant_run){
1140       /* just a run to handle conformant arrays, no scalars to dissect */
1141       return offset;
1142     }
1143
1144     if (add_subtree) {
1145         string_item = proto_tree_add_text(tree, tvb, offset, -1, "%s",
1146                                           proto_registrar_get_name(hfindex));
1147         string_tree = proto_item_add_subtree(string_item, ett_dcerpc_string);
1148     } else {
1149         string_item = NULL;
1150         string_tree = tree;
1151     }
1152
1153     /* NDR array header */
1154
1155     offset = dissect_ndr_uint32(tvb, offset, pinfo, string_tree, drep,
1156                                 hf_dcerpc_array_max_count, NULL);
1157
1158     offset = dissect_ndr_uint32(tvb, offset, pinfo, string_tree, drep,
1159                                 hf_dcerpc_array_offset, NULL);
1160
1161     offset = dissect_ndr_uint32(tvb, offset, pinfo, string_tree, drep,
1162                                 hf_dcerpc_array_actual_count, &len);
1163
1164     buffer_len = size_is * len;
1165
1166     /* Adjust offset */
1167     if (offset % size_is)
1168         offset += size_is - (offset % size_is);
1169
1170     if (size_is == sizeof(guint16)) {
1171         /* XXX - use drep to determine the byte order? */
1172         s = tvb_fake_unicode(tvb, offset, buffer_len / 2, TRUE);
1173         /*
1174          * XXX - we don't support a string type with Unicode
1175          * characters, so if this is a string item, we make
1176          * its value be the "fake Unicode" string.
1177          */
1178         if (tree && buffer_len) {
1179             hfinfo = proto_registrar_get_nth(hfindex);
1180             if (hfinfo->type == FT_STRING) {
1181                 proto_tree_add_string(string_tree, hfindex, tvb, offset,
1182                                       buffer_len, s);
1183             } else {
1184                 proto_tree_add_item(string_tree, hfindex, tvb, offset,
1185                                     buffer_len, drep[0] & 0x10);
1186             }
1187         }
1188     } else {
1189         /*
1190          * "tvb_get_string()" throws an exception if the entire string
1191          * isn't in the tvbuff.  If the length is bogus, this should
1192          * keep us from trying to allocate an immensely large buffer.
1193          * (It won't help if the length is *valid* but immensely large,
1194          * but that's another matter; in any case, that would happen only
1195          * if we had an immensely large tvbuff....)
1196          */
1197         s = tvb_get_string(tvb, offset, buffer_len);
1198         if (tree && buffer_len)
1199             proto_tree_add_item(string_tree, hfindex, tvb, offset,
1200                                 buffer_len, drep[0] & 0x10);
1201     }
1202
1203     if (string_item != NULL)
1204         proto_item_append_text(string_item, ": %s", s);
1205
1206     if (data)
1207             *data = s;
1208     else
1209             g_free(s);
1210     
1211     offset += buffer_len;
1212
1213     proto_item_set_end(string_item, tvb, offset);
1214
1215     return offset;
1216 }
1217
1218 /* Dissect an conformant varying string of chars.
1219    This corresponds to IDL of the form '[string] char *foo'.
1220
1221    XXX - at least according to the DCE RPC 1.1 spec, a string has
1222    a null terminator, which isn't necessary as a terminator for
1223    the transfer language (as there's a length), but is presumably
1224    there for the benefit of null-terminated-string languages
1225    such as C.  Is this ever used for purely counted strings?
1226    (Not that it matters if it is.) */
1227 int
1228 dissect_ndr_char_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo, 
1229                         proto_tree *tree, char *drep)
1230 {
1231     dcerpc_info *di;
1232     di=pinfo->private_data;
1233
1234     return dissect_ndr_cvstring(tvb, offset, pinfo, tree, drep,
1235                                 sizeof(guint8), di->hf_index,
1236                                 FALSE, NULL);
1237 }
1238
1239 /* Dissect a conformant varying string of wchars (wide characters).
1240    This corresponds to IDL of the form '[string] wchar *foo'
1241
1242    XXX - at least according to the DCE RPC 1.1 spec, a string has
1243    a null terminator, which isn't necessary as a terminator for
1244    the transfer language (as there's a length), but is presumably
1245    there for the benefit of null-terminated-string languages
1246    such as C.  Is this ever used for purely counted strings?
1247    (Not that it matters if it is.) */
1248 int
1249 dissect_ndr_wchar_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo, 
1250                         proto_tree *tree, char *drep)
1251 {
1252     dcerpc_info *di;
1253     di=pinfo->private_data;
1254
1255     return dissect_ndr_cvstring(tvb, offset, pinfo, tree, drep,
1256                                 sizeof(guint16), di->hf_index,
1257                                 FALSE, NULL);
1258 }
1259
1260 /* ndr pointer handling */
1261 /* list of pointers encountered so far */
1262 static GSList *ndr_pointer_list = NULL;
1263
1264 /* position where in the list to insert newly encountered pointers */
1265 static int ndr_pointer_list_pos=0;
1266
1267 /* boolean controlling whether pointers are top-level or embedded */
1268 static gboolean pointers_are_top_level = TRUE;
1269
1270 /* as a kludge, we represent all embedded reference pointers as id==-1
1271    hoping that his will not collide with any non-ref pointers */
1272 typedef struct ndr_pointer_data {
1273         guint32 id;
1274         proto_item *item;       /* proto_item for pointer */
1275         proto_tree *tree;       /* subtree of above item */
1276         dcerpc_dissect_fnct_t *fnct; /*if non-NULL, we have not called it yet*/
1277         int hf_index;
1278         dcerpc_callback_fnct_t *callback;
1279         void *callback_args;
1280 } ndr_pointer_data_t;
1281
1282 static void
1283 init_ndr_pointer_list(packet_info *pinfo)
1284 {
1285         dcerpc_info *di;
1286
1287         di=pinfo->private_data;
1288         di->conformant_run=0;
1289
1290         while(ndr_pointer_list){
1291                 ndr_pointer_data_t *npd;
1292
1293                 npd=g_slist_nth_data(ndr_pointer_list, 0);
1294                 ndr_pointer_list=g_slist_remove(ndr_pointer_list, npd);
1295                 if(npd){
1296                         g_free(npd);
1297                 }
1298         }
1299
1300         ndr_pointer_list=NULL;
1301         ndr_pointer_list_pos=0;
1302         pointers_are_top_level=TRUE;
1303 }
1304
1305 static int
1306 dissect_deferred_pointers(packet_info *pinfo, tvbuff_t *tvb, int offset, char *drep)
1307 {
1308         int found_new_pointer;
1309         dcerpc_info *di;
1310         int old_offset;
1311
1312         di=pinfo->private_data;
1313         do{
1314                 int i, len;
1315
1316                 found_new_pointer=0;
1317                 len=g_slist_length(ndr_pointer_list);
1318                 for(i=0;i<len;i++){
1319                         ndr_pointer_data_t *tnpd;
1320                         tnpd=g_slist_nth_data(ndr_pointer_list, i);
1321                         if(tnpd->fnct){
1322                                 dcerpc_dissect_fnct_t *fnct;
1323
1324                                 found_new_pointer=1;
1325                                 fnct=tnpd->fnct;
1326                                 tnpd->fnct=NULL;
1327                                 ndr_pointer_list_pos=i+1;
1328                                 di->hf_index=tnpd->hf_index;
1329                                 /* first a run to handle any conformant
1330                                    array headers */
1331                                 di->conformant_run=1;
1332                                 di->conformant_eaten=0;
1333                                 old_offset = offset;
1334                                 offset = (*(fnct))(tvb, offset, pinfo, NULL, drep);
1335
1336                                 g_assert((offset-old_offset)==di->conformant_eaten);
1337                                 /* This is to check for any bugs in the dissectors.
1338                                  *
1339                                  * Basically, the NDR representation will store all
1340                                  * arrays in two blocks, one block with the dimension
1341                                  * discreption, like size, number of elements and such,
1342                                  * and another block that contains the actual data stored
1343                                  * in the array.
1344                                  * If the array is embedded directly inside another,
1345                                  * encapsulating aggregate type, like a union or struct,
1346                                  * then these two blocks will be stored at different places
1347                                  * in the bytestream, with other data between the blocks.
1348                                  *
1349                                  * For this reason, all pointers to types (both aggregate
1350                                  * and scalar, for simplicity no distinction is made)
1351                                  * will have its dissector called twice.
1352                                  * The dissector will first be called with conformant_run==1
1353                                  * in which mode the dissector MUST NOT consume any data from
1354                                  * the tvbuff (i.e. may not dissect anything) except the
1355                                  * initial control block for arrays.
1356                                  * The second time the dissector is called, with
1357                                  * conformant_run==0, all other data for the type will be
1358                                  * dissected.
1359                                  *
1360                                  * All dissect_ndr_<type> dissectors are already prepared
1361                                  * for this and knows when it should eat data from the tvb
1362                                  * and when not to, so implementors of dissectors will
1363                                  * normally not need to worry about this or even know about
1364                                  * it. However, if a dissector for an aggregate type calls
1365                                  * a subdissector from outside packet-dcerpc.c, such as
1366                                  * the dissector in packet-smb.c for NT Security Descriptors
1367                                  * as an example, then it is VERY important to encapsulate
1368                                  * this call to an external subdissector with the appropriate
1369                                  * test for conformant_run, i.e. it will need something like
1370                                  *
1371                                  *      dcerpc_info *di;
1372                                  *
1373                                  *      di=pinfo->private_data;
1374                                  *      if(di->conformant_run){
1375                                  *              return offset;
1376                                  *      }
1377                                  *
1378                                  * to make sure it makes the right thing.
1379                                  * This assert will signal when someone has forgotten to
1380                                  * make the dissector aware of this requirement.
1381                                  */
1382
1383                                 /* now we dissect the actual pointer */
1384                                 di->conformant_run=0;
1385                                 old_offset = offset;
1386                                 offset = (*(fnct))(tvb, offset, pinfo, tnpd->tree, drep);
1387                                 if (tnpd->callback)
1388                                         tnpd->callback(pinfo, tnpd->tree, tnpd->item, tvb, old_offset, offset, tnpd->callback_args);
1389                                 break;
1390                         }
1391                 }
1392         } while(found_new_pointer);
1393
1394         return offset;
1395 }
1396
1397
1398 static void
1399 add_pointer_to_list(packet_info *pinfo, proto_tree *tree, proto_item *item,
1400                     dcerpc_dissect_fnct_t *fnct, guint32 id, int hf_index, 
1401                     dcerpc_callback_fnct_t *callback, void *callback_args)
1402 {
1403         ndr_pointer_data_t *npd;
1404
1405         /* check if this pointer is valid */
1406         if(id!=0xffffffff){
1407                 dcerpc_info *di;
1408                 dcerpc_call_value *value;
1409
1410                 di=pinfo->private_data;
1411                 value=di->call_data;
1412
1413                 if(di->request){
1414                         if(!(pinfo->fd->flags.visited)){
1415                                 if(id>value->max_ptr){
1416                                         value->max_ptr=id;
1417                                 }
1418                         }
1419                 } else {
1420                         /* if we havent seen the request bail out since we cant
1421                            know whether this is the first non-NULL instance
1422                            or not */
1423                         if(value->req_frame==0){
1424                                 /* XXX THROW EXCEPTION */
1425                         }
1426
1427                         /* We saw this one in the request frame, nothing to
1428                            dissect later */
1429                         if(id<=value->max_ptr){
1430                                 return;
1431                         }
1432                 }
1433         }
1434
1435         npd=g_malloc(sizeof(ndr_pointer_data_t));
1436         npd->id=id;
1437         npd->tree=tree;
1438         npd->item=item;
1439         npd->fnct=fnct;
1440         npd->hf_index=hf_index;
1441         npd->callback=callback;
1442         npd->callback_args=callback_args;
1443         ndr_pointer_list = g_slist_insert(ndr_pointer_list, npd,
1444                                         ndr_pointer_list_pos);
1445         ndr_pointer_list_pos++;
1446 }
1447
1448
1449 static int
1450 find_pointer_index(guint32 id)
1451 {
1452         ndr_pointer_data_t *npd;
1453         int i,len;
1454
1455         len=g_slist_length(ndr_pointer_list);
1456         for(i=0;i<len;i++){
1457                 npd=g_slist_nth_data(ndr_pointer_list, i);
1458                 if(npd){
1459                         if(npd->id==id){
1460                                 return i;
1461                         }
1462                 }
1463         }
1464
1465         return -1;
1466 }
1467
1468 /* This function dissects an NDR pointer and stores the callback for later
1469  * deferred dissection.
1470  *
1471  *   fnct is the callback function for when we have reached this object in
1472  *   the bytestream.
1473  *
1474  *   type is what type of pointer.
1475  *
1476  *   this is text is what text we should put in any created tree node.
1477  *
1478  *   hf_index is what hf value we want to pass to the callback function when
1479  *   it is called, the callback can later pich this one up from di->hf_index.
1480  *
1481  *   callback is executed after the pointer has been dereferenced.
1482  *
1483  *   callback_args is passed as an argument to the callback function
1484  *
1485  * See packet-dcerpc-samr.c for examples
1486  */
1487 int
1488 dissect_ndr_pointer_cb(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1489                     proto_tree *tree, char *drep, dcerpc_dissect_fnct_t *fnct,
1490                     int type, char *text, int hf_index, 
1491                     dcerpc_callback_fnct_t *callback, void *callback_args)
1492 {
1493         dcerpc_info *di;
1494
1495         di=pinfo->private_data;
1496         if(di->conformant_run){
1497                 /* this call was only for dissecting the header for any
1498                    embedded conformant array. we will not parse any
1499                    pointers in this mode.
1500                 */
1501                 return offset;
1502         }
1503
1504         /*TOP LEVEL REFERENCE POINTER*/
1505         if( pointers_are_top_level
1506         &&(type==NDR_POINTER_REF) ){
1507                 proto_item *item;
1508                 proto_tree *tr;
1509
1510                 /* we must find out a nice way to do the length here */
1511                 item=proto_tree_add_text(tree, tvb, offset, 0,
1512                         "%s", text);
1513                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1514
1515                 add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff, 
1516                                     hf_index, callback, callback_args);
1517                 goto after_ref_id;
1518         }
1519
1520         /*TOP LEVEL FULL POINTER*/
1521         if( pointers_are_top_level
1522         && (type==NDR_POINTER_PTR) ){
1523                 int idx;
1524                 guint32 id;
1525                 proto_item *item;
1526                 proto_tree *tr;
1527
1528                 /* get the referent id */
1529                 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
1530
1531                 /* we got a NULL pointer */
1532                 if(id==0){
1533                         proto_tree_add_text(tree, tvb, offset-4, 4,
1534                                 "(NULL pointer) %s",text);
1535                         goto after_ref_id;
1536                 }
1537
1538                 /* see if we have seen this pointer before */
1539                 idx=find_pointer_index(id);
1540
1541                 /* we have seen this pointer before */
1542                 if(idx>=0){
1543                         proto_tree_add_text(tree, tvb, offset-4, 4,
1544                                 "(duplicate PTR) %s",text);
1545                         goto after_ref_id;
1546                 }
1547
1548                 /* new pointer */
1549                 item=proto_tree_add_text(tree, tvb, offset-4, 4,
1550                         "%s", text);
1551                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1552                 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
1553                 add_pointer_to_list(pinfo, tr, item, fnct, id, hf_index, 
1554                                     callback, callback_args);
1555                 goto after_ref_id;
1556         }
1557         /*TOP LEVEL UNIQUE POINTER*/
1558         if( pointers_are_top_level
1559         && (type==NDR_POINTER_UNIQUE) ){
1560                 guint32 id;
1561                 proto_item *item;
1562                 proto_tree *tr;
1563
1564                 /* get the referent id */
1565                 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
1566
1567                 /* we got a NULL pointer */
1568                 if(id==0){
1569                         proto_tree_add_text(tree, tvb, offset-4, 4,
1570                                 "(NULL pointer) %s",text);
1571                         goto after_ref_id;
1572                 }
1573
1574                 /* new pointer */
1575                 item=proto_tree_add_text(tree, tvb, offset-4, 4,
1576                         "%s", text);
1577                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1578                 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
1579                 add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff, 
1580                                     hf_index, callback, callback_args);
1581                 goto after_ref_id;
1582         }
1583
1584         /*EMBEDDED REFERENCE POINTER*/
1585         if( (!pointers_are_top_level)
1586         && (type==NDR_POINTER_REF) ){
1587                 guint32 id;
1588                 proto_item *item;
1589                 proto_tree *tr;
1590
1591                 /* get the referent id */
1592                 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
1593
1594                 /* new pointer */
1595                 item=proto_tree_add_text(tree, tvb, offset-4, 4,
1596                         "%s",text);
1597                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1598                 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
1599                 add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff, 
1600                                     hf_index, callback, callback_args);
1601                 goto after_ref_id;
1602         }
1603
1604         /*EMBEDDED UNIQUE POINTER*/
1605         if( (!pointers_are_top_level)
1606         && (type==NDR_POINTER_UNIQUE) ){
1607                 guint32 id;
1608                 proto_item *item;
1609                 proto_tree *tr;
1610
1611                 /* get the referent id */
1612                 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
1613
1614                 /* we got a NULL pointer */
1615                 if(id==0){
1616                         proto_tree_add_text(tree, tvb, offset-4, 4,
1617                                 "(NULL pointer) %s", text);
1618                         goto after_ref_id;
1619                 }
1620
1621                 /* new pointer */
1622                 item=proto_tree_add_text(tree, tvb, offset-4, 4,
1623                         "%s",text);
1624                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1625                 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
1626                 add_pointer_to_list(pinfo, tr, item, fnct, 0xffffffff, 
1627                                     hf_index, callback, callback_args);
1628                 goto after_ref_id;
1629         }
1630
1631         /*EMBEDDED FULL POINTER*/
1632         if( (!pointers_are_top_level)
1633         && (type==NDR_POINTER_PTR) ){
1634                 int idx;
1635                 guint32 id;
1636                 proto_item *item;
1637                 proto_tree *tr;
1638
1639                 /* get the referent id */
1640                 offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep, -1, &id);
1641
1642                 /* we got a NULL pointer */
1643                 if(id==0){
1644                         proto_tree_add_text(tree, tvb, offset-4, 4,
1645                                 "(NULL pointer) %s",text);
1646                         goto after_ref_id;
1647                 }
1648
1649                 /* see if we have seen this pointer before */
1650                 idx=find_pointer_index(id);
1651
1652                 /* we have seen this pointer before */
1653                 if(idx>=0){
1654                         proto_tree_add_text(tree, tvb, offset-4, 4,
1655                                 "(duplicate PTR) %s",text);
1656                         goto after_ref_id;
1657                 }
1658
1659                 /* new pointer */
1660                 item=proto_tree_add_text(tree, tvb, offset-4, 4,
1661                         "%s", text);
1662                 tr=proto_item_add_subtree(item,ett_dcerpc_pointer_data);
1663                 proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, offset-4, 4, id);
1664                 add_pointer_to_list(pinfo, tr, item, fnct, id, hf_index, 
1665                                     callback, callback_args);
1666                 goto after_ref_id;
1667         }
1668
1669
1670 after_ref_id:
1671         /* After each top level pointer we have dissected we have to
1672            dissect all deferrals before we move on to the next top level
1673            argument */
1674         if(pointers_are_top_level==TRUE){
1675                 pointers_are_top_level=FALSE;
1676                 offset = dissect_deferred_pointers(pinfo, tvb, offset, drep);
1677                 pointers_are_top_level=TRUE;
1678         }
1679
1680         return offset;
1681 }
1682
1683 int
1684 dissect_ndr_pointer(tvbuff_t *tvb, gint offset, packet_info *pinfo,
1685                     proto_tree *tree, char *drep, dcerpc_dissect_fnct_t *fnct,
1686                     int type, char *text, int hf_index)
1687 {
1688         return dissect_ndr_pointer_cb(
1689                 tvb, offset, pinfo, tree, drep, fnct, type, text, hf_index,
1690                 NULL, NULL);
1691 }
1692
1693 static void
1694 show_stub_data (tvbuff_t *tvb, gint offset, proto_tree *dcerpc_tree,
1695                 dcerpc_auth_info *auth_info)
1696 {
1697     int length;
1698
1699     /*
1700      * We don't show stub data unless we have some in the tvbuff;
1701      * however, in the protocol tree, we show, as the number of
1702      * bytes, the reported number of bytes, not the number of bytes
1703      * that happen to be in the tvbuff.
1704      */
1705     if (tvb_length_remaining (tvb, offset) > 0) {
1706         length = tvb_reported_length_remaining (tvb, offset);
1707         if (auth_info != NULL &&
1708             auth_info->auth_level == DCE_C_AUTHN_LEVEL_PKT_PRIVACY) {
1709             proto_tree_add_text(dcerpc_tree, tvb, offset, -1,
1710                                 "Encrypted stub data (%d byte%s)",
1711                                 length, plurality(length, "", "s"));
1712         } else {
1713             proto_tree_add_text (dcerpc_tree, tvb, offset, -1,
1714                                  "Stub data (%d byte%s)", length,
1715                                  plurality(length, "", "s"));
1716         }
1717     }
1718 }
1719
1720 static int
1721 dcerpc_try_handoff (packet_info *pinfo, proto_tree *tree,
1722                     proto_tree *dcerpc_tree,
1723                     tvbuff_t *volatile tvb, volatile gint offset,
1724                     char *drep, dcerpc_info *info,
1725                     dcerpc_auth_info *auth_info)
1726 {
1727     dcerpc_uuid_key key;
1728     dcerpc_uuid_value *sub_proto;
1729     int length;
1730     proto_tree *volatile sub_tree = NULL;
1731     dcerpc_sub_dissector *proc;
1732     gchar *name = NULL;
1733     dcerpc_dissect_fnct_t *volatile sub_dissect;
1734     const char *volatile saved_proto;
1735     void *volatile saved_private_data;
1736
1737     key.uuid = info->call_data->uuid;
1738     key.ver = info->call_data->ver;
1739
1740
1741     if ((sub_proto = g_hash_table_lookup (dcerpc_uuids, &key)) == NULL
1742          || !proto_is_protocol_enabled(sub_proto->proto)) {
1743         /*
1744          * We don't have a dissector for this UUID, or the protocol
1745          * for that UUID is disabled.
1746          */
1747         show_stub_data (tvb, offset, dcerpc_tree, auth_info);
1748         return -1;
1749     }
1750
1751     for (proc = sub_proto->procs; proc->name; proc++) {
1752         if (proc->num == info->call_data->opnum) {
1753             name = proc->name;
1754             break;
1755         }
1756     }
1757
1758     if (!name)
1759         name = "Unknown?!";
1760
1761     if (check_col (pinfo->cinfo, COL_PROTOCOL)) {
1762         col_set_str (pinfo->cinfo, COL_PROTOCOL, sub_proto->name);
1763     }
1764
1765     if (check_col (pinfo->cinfo, COL_INFO)) {
1766         col_add_fstr (pinfo->cinfo, COL_INFO, "%s %s",
1767                       name, info->request ? "request" : "reply");
1768     }
1769
1770     if (tree) {
1771         proto_item *sub_item;
1772         sub_item = proto_tree_add_item (tree, sub_proto->proto, tvb, offset,
1773                                         -1, FALSE);
1774
1775         if (sub_item) {
1776             sub_tree = proto_item_add_subtree (sub_item, sub_proto->ett);
1777         }
1778
1779         /*
1780          * Put the operation number into the tree along with
1781          * the operation's name.
1782          */
1783
1784         if (sub_proto->opnum_hf != -1)
1785                 proto_tree_add_uint_format(sub_tree, sub_proto->opnum_hf,
1786                                            tvb, 0, 0, info->call_data->opnum,
1787                                            "Operation: %s (%u)",
1788                                            name, info->call_data->opnum);
1789         else
1790                 proto_tree_add_uint_format(sub_tree, hf_dcerpc_op, tvb,
1791                                            0, 0, info->call_data->opnum,
1792                                            "Operation: %s (%u)",
1793                                            name, info->call_data->opnum);
1794     }
1795
1796     /*
1797      * If the authentication level is DCE_C_AUTHN_LEVEL_PKT_PRIVACY,
1798      * the stub data is encrypted, and we'd have to decrypt it in
1799      * order to dissect it.
1800      */
1801     if (auth_info != NULL &&
1802           auth_info->auth_level == DCE_C_AUTHN_LEVEL_PKT_PRIVACY) {
1803             length = tvb_length_remaining (tvb, offset);
1804
1805             if (length > 0) {
1806                     dcerpc_auth_subdissector_fns *auth_fns;
1807                     decrypted_info_t *dit;
1808                     tvbuff_t *enc_tvb;
1809             
1810                     enc_tvb = tvb_new_subset(tvb, offset, length, length);
1811
1812                     proto_tree_add_text(sub_tree, enc_tvb, 0, length,
1813                                         "Encrypted stub data (%d byte%s)",
1814                                         length, plurality(length, "", "s"));
1815                     
1816                     pinfo->decrypted_data = NULL;
1817
1818                     if ((auth_fns = get_auth_subdissector_fns(
1819                                  auth_info->auth_level, auth_info->auth_type)))
1820                             dissect_encrypted_data(
1821                                     enc_tvb, pinfo, sub_tree, auth_fns,
1822                                     info->request ? PDU_REQ : PDU_RESP, drep);
1823
1824                     /* No decrypted data so don't try and call a subdissector */
1825
1826                     if (!pinfo->decrypted_data)
1827                             goto done;
1828
1829                     dit = (decrypted_info_t *)pinfo->decrypted_data;
1830                     tvb = dit->decr_tvb;
1831                     sub_tree = dit->decr_tree;
1832             }
1833     }
1834
1835     sub_dissect = info->request ? proc->dissect_rqst : proc->dissect_resp;
1836     if (sub_dissect) {
1837             saved_proto = pinfo->current_proto;
1838             saved_private_data = pinfo->private_data;
1839             pinfo->current_proto = sub_proto->name;
1840             pinfo->private_data = (void *)info;
1841             
1842             init_ndr_pointer_list(pinfo);
1843             /*
1844              * Catch ReportedBoundsError, so that even if the stub
1845              * data is bad, we still show the verifier.
1846              */
1847             TRY {
1848                 offset = sub_dissect (tvb, offset, pinfo, sub_tree, drep);
1849             } CATCH(BoundsError) {
1850                 RETHROW;
1851             } CATCH(ReportedBoundsError) {
1852                 show_reported_bounds_error(tvb, pinfo, tree);
1853             } ENDTRY;
1854
1855             /* If there is auth padding at the end of the stub, display it */
1856             if (auth_info != NULL && auth_info->auth_pad_len != 0) {
1857                 proto_tree_add_text (sub_tree, tvb, offset, 
1858                                      auth_info->auth_pad_len,
1859                                      "Auth Padding (%u byte%s)",
1860                                      auth_info->auth_pad_len,
1861                                      plurality(auth_info->auth_pad_len, "", "s"));
1862                 offset += auth_info->auth_pad_len;
1863             }
1864
1865             /* If we have a subdissector and it didn't dissect all data in
1866                the tvb, make a note of it. */
1867
1868             if (tvb_length_remaining(tvb, offset)) {
1869                 if (check_col(pinfo->cinfo, COL_INFO))
1870                         col_append_fstr(pinfo->cinfo, COL_INFO,
1871                                         "[Long frame (%d bytes)]",
1872                                         tvb_length_remaining(tvb, offset));
1873             }
1874
1875             pinfo->current_proto = saved_proto;
1876             pinfo->private_data = saved_private_data;
1877         } else {
1878             length = tvb_length_remaining (tvb, offset);
1879             if (length > 0) {
1880                 proto_tree_add_text (sub_tree, tvb, offset, length,
1881                                      "Stub data (%d byte%s)", length,
1882                                      plurality(length, "", "s"));
1883             }
1884         }
1885
1886  done:
1887     tap_queue_packet(dcerpc_tap, pinfo, info);
1888     return 0;
1889 }
1890
1891 static int
1892 dissect_dcerpc_verifier (tvbuff_t *tvb, packet_info *pinfo, 
1893                          proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr,
1894                          dcerpc_auth_info *auth_info)
1895 {
1896     int auth_offset;
1897
1898     if (auth_info->auth_size != 0) {
1899             dcerpc_auth_subdissector_fns *auth_fns;
1900             tvbuff_t *auth_tvb;
1901
1902             auth_offset = hdr->frag_len - hdr->auth_len;
1903
1904             auth_tvb = tvb_new_subset(tvb, auth_offset, hdr->auth_len,
1905                                       hdr->auth_len);
1906
1907             if ((auth_fns = get_auth_subdissector_fns(auth_info->auth_level,
1908                                                       auth_info->auth_type)))
1909                     dissect_auth_verf(auth_tvb, pinfo, dcerpc_tree, auth_fns,
1910                                       hdr, auth_info);
1911             else
1912                     proto_tree_add_text (dcerpc_tree, auth_tvb, 0, hdr->auth_len,
1913                                          "Auth Verifier");
1914     }
1915
1916     return hdr->auth_len;
1917 }
1918
1919 static void
1920 dissect_dcerpc_cn_auth (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tree,
1921                         e_dce_cn_common_hdr_t *hdr, gboolean are_credentials, 
1922                         dcerpc_auth_info *auth_info)
1923 {
1924     int offset;
1925
1926     /*
1927      * Initially set auth_level to -1 to indicate that we haven't
1928      * yet seen any authentication level information.
1929      */
1930     auth_info->auth_level = -1;
1931
1932     /*
1933      * The authentication information is at the *end* of the PDU; in
1934      * request and response PDUs, the request and response stub data
1935      * come before it.
1936      *
1937      * If the full packet is here, and we've got an auth len, and it's
1938      * valid, then dissect the auth info.
1939      */
1940     if (tvb_length (tvb) >= hdr->frag_len
1941         && hdr->auth_len
1942         && (hdr->auth_len + 8 <= hdr->frag_len)) {
1943
1944         offset = hdr->frag_len - (hdr->auth_len + 8);
1945
1946         offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1947                                        hf_dcerpc_auth_type, 
1948                                        &auth_info->auth_type);
1949         offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1950                                        hf_dcerpc_auth_level, 
1951                                        &auth_info->auth_level);
1952
1953         offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1954                                        hf_dcerpc_auth_pad_len, 
1955                                        &auth_info->auth_pad_len);
1956         offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1957                                        hf_dcerpc_auth_rsrvd, NULL);
1958         offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
1959                                         hf_dcerpc_auth_ctx_id, NULL);
1960
1961         /*
1962          * Dissect the authentication data.
1963          */
1964         if (are_credentials) {
1965             tvbuff_t *auth_tvb;
1966             dcerpc_auth_subdissector_fns *auth_fns;
1967
1968             auth_tvb = tvb_new_subset(
1969                     tvb, offset, hdr->auth_len, hdr->auth_len);
1970
1971             if ((auth_fns = get_auth_subdissector_fns(auth_info->auth_level,
1972                                                       auth_info->auth_type)))
1973                     dissect_auth_verf(auth_tvb, pinfo, dcerpc_tree, auth_fns, 
1974                                       hdr, auth_info);
1975             else
1976                     proto_tree_add_text (dcerpc_tree, tvb, offset, hdr->auth_len,
1977                                          "Auth Credentials");
1978         }
1979         
1980         /* Compute the size of the auth block.  Note that this should not 
1981            include auth padding, since when NTLMSSP encryption is used, the
1982            padding is actually inside the encrypted stub */
1983         auth_info->auth_size = hdr->auth_len + 8;
1984     } else {
1985         auth_info->auth_size = 0;
1986         auth_info->auth_pad_len = 0;
1987     }
1988 }
1989
1990
1991 /* We need to hash in the SMB fid number to generate a unique hash table
1992    key as DCERPC over SMB allows several pipes over the same TCP/IP
1993    socket. */
1994
1995 static guint16 get_smb_fid (void *private_data)
1996 {
1997     dcerpc_private_info *priv = (dcerpc_private_info *)private_data;
1998
1999     if (!priv)
2000         return 0;       /* Nothing to see here */
2001
2002     /* DCERPC over smb */
2003
2004     if (priv->transport_type == DCERPC_TRANSPORT_SMB)
2005         return priv->data.smb.fid;
2006
2007     /* Some other transport... */
2008
2009     return 0;
2010 }
2011
2012 /*
2013  * Connection oriented packet types
2014  */
2015
2016 static void
2017 dissect_dcerpc_cn_bind (tvbuff_t *tvb, gint offset, packet_info *pinfo, 
2018                         proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr)
2019 {
2020     conversation_t *conv = NULL;
2021     guint8 num_ctx_items;
2022     guint i;
2023     gboolean saw_ctx_item = FALSE;
2024     guint16 ctx_id;
2025     guint16 num_trans_items;
2026     guint j;
2027     e_uuid_t if_id;
2028     e_uuid_t trans_id;
2029     guint32 trans_ver;
2030     guint16 if_ver, if_ver_minor;
2031     char uuid_str[DCERPC_UUID_STR_LEN]; 
2032     int uuid_str_len;
2033     dcerpc_auth_info auth_info;
2034
2035     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2036                                     hf_dcerpc_cn_max_xmit, NULL);
2037
2038     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2039                                     hf_dcerpc_cn_max_recv, NULL);
2040
2041     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2042                                     hf_dcerpc_cn_assoc_group, NULL);
2043
2044     offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2045                                     hf_dcerpc_cn_num_ctx_items, &num_ctx_items);
2046
2047     /* padding */
2048     offset += 3;
2049
2050     for (i = 0; i < num_ctx_items; i++) {
2051       offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2052                                       hf_dcerpc_cn_ctx_id, &ctx_id);
2053
2054       offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2055                                       hf_dcerpc_cn_num_trans_items, &num_trans_items);
2056
2057       /* XXX - use "dissect_ndr_uuid_t()"? */
2058       dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &if_id);
2059       if (dcerpc_tree) {
2060           uuid_str_len = snprintf(uuid_str, DCERPC_UUID_STR_LEN, 
2061                                   "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
2062                                   if_id.Data1, if_id.Data2, if_id.Data3,
2063                                   if_id.Data4[0], if_id.Data4[1],
2064                                   if_id.Data4[2], if_id.Data4[3],
2065                                   if_id.Data4[4], if_id.Data4[5],
2066                                   if_id.Data4[6], if_id.Data4[7]);
2067           if (uuid_str_len >= DCERPC_UUID_STR_LEN)
2068                   memset(uuid_str, 0, DCERPC_UUID_STR_LEN);
2069           proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_cn_bind_if_id, tvb,
2070                                         offset, 16, uuid_str, "Interface UUID: %s", uuid_str);
2071       }
2072       offset += 16;
2073
2074       if (hdr->drep[0] & 0x10) {
2075           offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2076                                           hf_dcerpc_cn_bind_if_ver, &if_ver);
2077           offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2078                                           hf_dcerpc_cn_bind_if_ver_minor, &if_ver_minor);
2079       } else {
2080           offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2081                                           hf_dcerpc_cn_bind_if_ver_minor, &if_ver_minor);
2082           offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2083                                           hf_dcerpc_cn_bind_if_ver, &if_ver);
2084       }
2085
2086       if (!saw_ctx_item) {
2087         conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
2088                                   pinfo->srcport, pinfo->destport, 0);
2089         if (conv == NULL) {
2090             conv = conversation_new (&pinfo->src, &pinfo->dst, pinfo->ptype,
2091                                      pinfo->srcport, pinfo->destport, 0);
2092         }
2093
2094         /* if this is the first time we see this packet, we need to
2095            update the dcerpc_binds table so that any later calls can
2096            match to the interface.
2097            XXX We assume that BINDs will NEVER be fragmented.
2098         */
2099         if(!(pinfo->fd->flags.visited)){
2100                 dcerpc_bind_key *key;
2101                 dcerpc_bind_value *value;
2102
2103                 key = g_mem_chunk_alloc (dcerpc_bind_key_chunk);
2104                 key->conv = conv;
2105                 key->ctx_id = ctx_id;
2106                 key->smb_fid = get_smb_fid(pinfo->private_data);
2107
2108                 value = g_mem_chunk_alloc (dcerpc_bind_value_chunk);
2109                 value->uuid = if_id;
2110                 value->ver = if_ver;
2111
2112                 /* add this entry to the bind table, first removing any
2113                    previous ones that are identical
2114                  */
2115                 if(g_hash_table_lookup(dcerpc_binds, key)){
2116                         g_hash_table_remove(dcerpc_binds, key);
2117                 }
2118                 g_hash_table_insert (dcerpc_binds, key, value);
2119         }
2120
2121         if (check_col (pinfo->cinfo, COL_INFO)) {
2122           dcerpc_uuid_key key;
2123           dcerpc_uuid_value *value;
2124
2125           key.uuid = if_id;
2126           key.ver = if_ver;
2127
2128           if ((value = g_hash_table_lookup(dcerpc_uuids, &key)))
2129                   col_append_fstr(pinfo->cinfo, COL_INFO, " UUID: %s", value->name);
2130           else
2131                   col_append_fstr(pinfo->cinfo, COL_INFO, " UUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x ver %u.%u",
2132                            if_id.Data1, if_id.Data2, if_id.Data3,
2133                            if_id.Data4[0], if_id.Data4[1],
2134                            if_id.Data4[2], if_id.Data4[3],
2135                            if_id.Data4[4], if_id.Data4[5],
2136                            if_id.Data4[6], if_id.Data4[7],
2137                            if_ver, if_ver_minor);
2138         }
2139         saw_ctx_item = TRUE;
2140       }
2141
2142       for (j = 0; j < num_trans_items; j++) {
2143         /* XXX - use "dissect_ndr_uuid_t()"? */
2144         dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &trans_id);
2145         if (dcerpc_tree) {
2146             uuid_str_len = snprintf(uuid_str, DCERPC_UUID_STR_LEN, 
2147                                   "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
2148                                   trans_id.Data1, trans_id.Data2, trans_id.Data3,
2149                                   trans_id.Data4[0], trans_id.Data4[1],
2150                                   trans_id.Data4[2], trans_id.Data4[3],
2151                                   trans_id.Data4[4], trans_id.Data4[5],
2152                                   trans_id.Data4[6], trans_id.Data4[7]);
2153             if (uuid_str_len >= DCERPC_UUID_STR_LEN)
2154                 memset(uuid_str, 0, DCERPC_UUID_STR_LEN);
2155             proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_cn_bind_trans_id, tvb,
2156                                           offset, 16, uuid_str, "Transfer Syntax: %s", uuid_str);
2157         }
2158         offset += 16;
2159
2160         offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2161                                         hf_dcerpc_cn_bind_trans_ver, &trans_ver);
2162       }
2163     }
2164
2165     /*
2166      * XXX - we should save the authentication type *if* we have
2167      * an authentication header, and associate it with an authentication
2168      * context, so subsequent PDUs can use that context.
2169      */
2170     dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, hdr, TRUE, &auth_info);
2171 }
2172
2173 static void
2174 dissect_dcerpc_cn_bind_ack (tvbuff_t *tvb, gint offset, packet_info *pinfo, 
2175                             proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr)
2176 {
2177     guint16 max_xmit, max_recv;
2178     guint16 sec_addr_len;
2179     guint8 num_results;
2180     guint i;
2181     guint16 result;
2182     guint16 reason;
2183     e_uuid_t trans_id;
2184     guint32 trans_ver;
2185     char uuid_str[DCERPC_UUID_STR_LEN]; 
2186     int uuid_str_len;
2187     dcerpc_auth_info auth_info;
2188
2189     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2190                                     hf_dcerpc_cn_max_xmit, &max_xmit);
2191
2192     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2193                                     hf_dcerpc_cn_max_recv, &max_recv);
2194
2195     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2196                                     hf_dcerpc_cn_assoc_group, NULL);
2197
2198     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2199                                     hf_dcerpc_cn_sec_addr_len, &sec_addr_len);
2200     if (sec_addr_len != 0) {
2201         proto_tree_add_item (dcerpc_tree, hf_dcerpc_cn_sec_addr, tvb, offset,
2202                              sec_addr_len, FALSE);
2203         offset += sec_addr_len;
2204     }
2205
2206     if (offset % 4) {
2207         offset += 4 - offset % 4;
2208     }
2209
2210     offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2211                                    hf_dcerpc_cn_num_results, &num_results);
2212
2213     /* padding */
2214     offset += 3;
2215
2216     for (i = 0; i < num_results; i++) {
2217         offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
2218                                         hdr->drep, hf_dcerpc_cn_ack_result,
2219                                         &result);
2220         if (result != 0) {
2221             offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
2222                                             hdr->drep, hf_dcerpc_cn_ack_reason,
2223                                             &reason);
2224         } else {
2225             /*
2226              * The reason for rejection isn't meaningful, and often isn't
2227              * set, when the syntax was accepted.
2228              */
2229             offset += 2;
2230         }
2231
2232         /* XXX - use "dissect_ndr_uuid_t()"? */
2233         dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &trans_id);
2234         if (dcerpc_tree) {
2235             uuid_str_len = snprintf(uuid_str, DCERPC_UUID_STR_LEN, 
2236                                   "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
2237                                   trans_id.Data1, trans_id.Data2, trans_id.Data3,
2238                                   trans_id.Data4[0], trans_id.Data4[1],
2239                                   trans_id.Data4[2], trans_id.Data4[3],
2240                                   trans_id.Data4[4], trans_id.Data4[5],
2241                                   trans_id.Data4[6], trans_id.Data4[7]);
2242             if (uuid_str_len >= DCERPC_UUID_STR_LEN)
2243                   memset(uuid_str, 0, DCERPC_UUID_STR_LEN);
2244             proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_cn_ack_trans_id, tvb,
2245                                           offset, 16, uuid_str, "Transfer Syntax: %s", uuid_str);
2246         }
2247         offset += 16;
2248
2249         offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2250                                         hf_dcerpc_cn_ack_trans_ver, &trans_ver);
2251     }
2252
2253     /*
2254      * XXX - do we need to do anything with the authentication level
2255      * we get back from this?
2256      */
2257     dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, hdr, TRUE, &auth_info);
2258
2259     if (check_col (pinfo->cinfo, COL_INFO)) {
2260         if (num_results != 0 && result == 0) {
2261             /* XXX - only checks the last result */
2262             col_append_fstr (pinfo->cinfo, COL_INFO,
2263                              " accept max_xmit: %u max_recv: %u",
2264                              max_xmit, max_recv);
2265         } else {
2266             /* XXX - only shows the last result and reason */
2267             col_append_fstr (pinfo->cinfo, COL_INFO, " %s, reason: %s",
2268                              val_to_str(result, p_cont_result_vals,
2269                                         "Unknown result (%u)"),
2270                              val_to_str(reason, p_provider_reason_vals,
2271                                         "Unknown (%u)"));
2272         }
2273     }
2274 }
2275
2276 static void
2277 dissect_dcerpc_cn_bind_nak (tvbuff_t *tvb, gint offset, packet_info *pinfo, 
2278                             proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr)
2279 {
2280     guint16 reason;
2281     guint8 num_protocols;
2282     guint i;
2283
2284     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree,
2285                                     hdr->drep, hf_dcerpc_cn_reject_reason,
2286                                     &reason);
2287
2288     if (check_col (pinfo->cinfo, COL_INFO)) {
2289         col_append_fstr (pinfo->cinfo, COL_INFO, " reason: %s",
2290                       val_to_str(reason, reject_reason_vals, "Unknown (%u)"));
2291     }
2292
2293     if (reason == PROTOCOL_VERSION_NOT_SUPPORTED) {
2294         offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2295                                        hf_dcerpc_cn_num_protocols,
2296                                        &num_protocols);
2297
2298         for (i = 0; i < num_protocols; i++) {
2299             offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree,
2300                                         hdr->drep, hf_dcerpc_cn_protocol_ver_major,
2301                                         NULL);
2302             offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree,
2303                                         hdr->drep, hf_dcerpc_cn_protocol_ver_minor,
2304                                         NULL);
2305         }
2306     }
2307 }
2308
2309 /* Return a string describing a DCE/RPC fragment as first, middle, or end
2310    fragment. */
2311
2312 #define PFC_FRAG_MASK  0x03
2313
2314 static char *
2315 fragment_type(guint8 flags)
2316 {
2317         flags = flags & PFC_FRAG_MASK;
2318
2319         if (flags == PFC_FIRST_FRAG)
2320                 return "first";
2321
2322         if (flags == 0)
2323                 return "middle";
2324
2325         if (flags == PFC_LAST_FRAG)
2326                 return "last";
2327
2328         if (flags == (PFC_FIRST_FRAG | PFC_LAST_FRAG))
2329                 return "whole";
2330
2331         return "unknown";
2332 }
2333
2334 static void
2335 dissect_dcerpc_cn_stub (tvbuff_t *tvb, int offset, packet_info *pinfo,
2336                         proto_tree *dcerpc_tree, proto_tree *tree,
2337                         e_dce_cn_common_hdr_t *hdr, dcerpc_info *di,
2338                         dcerpc_auth_info *auth_info, guint32 alloc_hint,
2339                         guint32 frame)
2340 {
2341     int length, reported_length, stub_length;
2342     gboolean save_fragmented;
2343     fragment_data *fd_head=NULL;
2344     guint32 tot_len;
2345
2346
2347     length = tvb_length_remaining(tvb, offset);
2348     reported_length = tvb_reported_length_remaining(tvb, offset);
2349     stub_length = hdr->frag_len - offset - auth_info->auth_size;
2350     if (length > stub_length)
2351       length = stub_length;
2352     if (reported_length > stub_length)
2353       reported_length = stub_length;
2354
2355     save_fragmented = pinfo->fragmented;
2356
2357     /* if this packet is not fragmented, just dissect it and exit */
2358     if(PFC_NOT_FRAGMENTED(hdr)){
2359         pinfo->fragmented = FALSE;
2360         dcerpc_try_handoff (pinfo, tree, dcerpc_tree, 
2361                 tvb_new_subset (tvb, offset, length, reported_length), 
2362                 0, hdr->drep, di, auth_info);
2363
2364         pinfo->fragmented = save_fragmented;
2365         return;
2366     }
2367
2368     /* The packet is fragmented. */
2369     pinfo->fragmented = TRUE;
2370
2371     /* if we are not doing reassembly and this is the first fragment
2372        then just dissect it and exit
2373     */
2374     if( (!dcerpc_reassemble) && hdr->flags&PFC_FIRST_FRAG ){
2375         dcerpc_try_handoff (pinfo, tree, dcerpc_tree,
2376                             tvb_new_subset (tvb, offset, length,
2377                                             reported_length),
2378                             0, hdr->drep, di, auth_info);
2379         if (check_col(pinfo->cinfo, COL_INFO)) {
2380             col_append_fstr(pinfo->cinfo, COL_INFO,
2381                             " [DCE/RPC %s fragment]", fragment_type(hdr->flags));
2382         }
2383         pinfo->fragmented = save_fragmented;
2384         return;
2385     }
2386
2387     /* if we have already seen this packet, see if it was reassembled
2388        and if so dissect the full pdu.
2389        then exit 
2390     */
2391     if(pinfo->fd->flags.visited){
2392         fd_head=fragment_get(pinfo, frame, dcerpc_co_reassemble_table);
2393
2394         goto end_cn_stub;
2395     }
2396
2397
2398     /* if we are not doing reassembly and it was neither a complete PDU
2399        nor the first fragment then there is nothing more we can do
2400        so we just have to exit
2401     */
2402     if( !dcerpc_reassemble ){
2403         goto end_cn_stub;
2404     }
2405
2406     /* if we didnt get 'frame' we dont know where the PDU started and thus
2407        it is pointless to continue 
2408     */
2409     if(!frame){
2410         goto end_cn_stub;
2411     }
2412
2413
2414     /* from now on we must attempt to reassemble the PDU 
2415     */
2416
2417
2418     /* we dont have the full fragment so we just have to abort and exit
2419     */
2420     if( !tvb_bytes_exist(tvb, offset, stub_length) ){
2421         goto end_cn_stub;
2422     }
2423
2424
2425     /* if we get here we know it is the first time we see the packet
2426        and we also know it is only a fragment and not a full PDU,
2427        thus we must reassemble it.
2428     */
2429
2430
2431     /* if this is the first fragment we need to start reassembly
2432     */
2433     if(hdr->flags&PFC_FIRST_FRAG){
2434         fragment_add(tvb, offset, pinfo, frame,
2435                  dcerpc_co_reassemble_table,
2436                  0, stub_length, TRUE);
2437         fragment_set_tot_len(pinfo, frame,
2438                  dcerpc_co_reassemble_table, alloc_hint);
2439
2440         goto end_cn_stub;
2441     }
2442
2443     /* if this is a middle fragment, just add it and exit */
2444     if(!(hdr->flags&PFC_LAST_FRAG)){
2445         tot_len = fragment_get_tot_len(pinfo, frame,
2446                  dcerpc_co_reassemble_table);
2447         fragment_add(tvb, offset, pinfo, frame,
2448                  dcerpc_co_reassemble_table,
2449                  tot_len-alloc_hint,
2450                  stub_length,
2451                  TRUE);
2452
2453         goto end_cn_stub;
2454     }
2455
2456     /* this was the last fragment add it to reassembly
2457     */
2458     tot_len = fragment_get_tot_len(pinfo, frame,
2459                 dcerpc_co_reassemble_table);
2460     fd_head = fragment_add(tvb, offset, pinfo,
2461                 frame,
2462                 dcerpc_co_reassemble_table,
2463                 tot_len-alloc_hint,
2464                 stub_length,
2465                 TRUE);
2466
2467 end_cn_stub:
2468
2469     /* Show the fragment data. */
2470     if (dcerpc_tree) {
2471         if (length > 0) {
2472             proto_tree_add_text (dcerpc_tree, tvb, offset, length,
2473                                  "Fragment data (%d byte%s)",
2474                                  stub_length,
2475                                  plurality(stub_length, "", "s"));
2476         }
2477     }
2478
2479     /* if reassembly is complete, dissect the full PDU
2480     */
2481     if(fd_head && (fd_head->flags&FD_DEFRAGMENTED) ){
2482         if(pinfo->fd->num==fd_head->reassembled_in){
2483             tvbuff_t *next_tvb;
2484
2485             next_tvb = tvb_new_real_data(fd_head->data, fd_head->datalen, fd_head->datalen);
2486             tvb_set_child_real_data_tvbuff(tvb, next_tvb);
2487             add_new_data_source(pinfo, next_tvb, "Reassembled DCE/RPC");
2488             show_fragment_tree(fd_head, &dcerpc_frag_items,
2489                 dcerpc_tree, pinfo, next_tvb);
2490
2491             pinfo->fragmented = FALSE;
2492             dcerpc_try_handoff (pinfo, tree, dcerpc_tree, next_tvb,
2493                 0, hdr->drep, di, auth_info);
2494         } else {
2495             proto_tree_add_uint(dcerpc_tree, hf_dcerpc_reassembled_in, tvb, 0, 0, fd_head->reassembled_in);
2496             if (check_col(pinfo->cinfo, COL_INFO)) {
2497                 col_append_fstr(pinfo->cinfo, COL_INFO,
2498                         " [DCE/RPC %s fragment]", fragment_type(hdr->flags));
2499             }
2500         }
2501     } else {
2502         /* Reassembly not complete - some fragments
2503            are missing */
2504         if (check_col(pinfo->cinfo, COL_INFO)) {
2505             col_append_fstr(pinfo->cinfo, COL_INFO,
2506                         " [DCE/RPC %s fragment]", fragment_type(hdr->flags));
2507         }
2508     }
2509
2510     pinfo->fragmented = save_fragmented;
2511 }
2512
2513 static void
2514 dissect_dcerpc_cn_rqst (tvbuff_t *tvb, gint offset, packet_info *pinfo, 
2515                         proto_tree *dcerpc_tree, proto_tree *tree, e_dce_cn_common_hdr_t *hdr)
2516 {
2517     conversation_t *conv;
2518     guint16 ctx_id;
2519     guint16 opnum;
2520     e_uuid_t obj_id;
2521     dcerpc_auth_info auth_info;
2522     guint32 alloc_hint;
2523     char uuid_str[DCERPC_UUID_STR_LEN]; 
2524     int uuid_str_len;
2525
2526     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2527                                     hf_dcerpc_cn_alloc_hint, &alloc_hint);
2528
2529     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2530                                     hf_dcerpc_cn_ctx_id, &ctx_id);
2531
2532     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2533                                     hf_dcerpc_opnum, &opnum);
2534
2535     if (check_col (pinfo->cinfo, COL_INFO)) {
2536         col_append_fstr (pinfo->cinfo, COL_INFO, " opnum: %u ctx_id: %u",
2537                          opnum, ctx_id);
2538     }
2539
2540     if (hdr->flags & PFC_OBJECT_UUID) {
2541         /* XXX - use "dissect_ndr_uuid_t()"? */
2542         dcerpc_tvb_get_uuid (tvb, offset, hdr->drep, &obj_id);
2543         if (dcerpc_tree) {
2544             uuid_str_len = snprintf(uuid_str, DCERPC_UUID_STR_LEN, 
2545                                     "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
2546                                     obj_id.Data1, obj_id.Data2, obj_id.Data3,
2547                                     obj_id.Data4[0],
2548                                     obj_id.Data4[1],
2549                                     obj_id.Data4[2],
2550                                     obj_id.Data4[3],
2551                                     obj_id.Data4[4],
2552                                     obj_id.Data4[5],
2553                                     obj_id.Data4[6],
2554                                     obj_id.Data4[7]);
2555             if (uuid_str_len >= DCERPC_UUID_STR_LEN)
2556                   memset(uuid_str, 0, DCERPC_UUID_STR_LEN);
2557             proto_tree_add_string_format (dcerpc_tree, hf_dcerpc_obj_id, tvb,
2558                                           offset, 16, uuid_str, "Object UUID: %s", uuid_str);
2559         }
2560         offset += 16;
2561     }
2562
2563     /*
2564      * XXX - what if this was set when the connection was set up,
2565      * and we just have a security context?
2566      */
2567     dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, hdr, FALSE, &auth_info);
2568
2569     conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
2570                               pinfo->srcport, pinfo->destport, 0);
2571     if (!conv)
2572         show_stub_data (tvb, offset, dcerpc_tree, &auth_info);
2573     else {
2574         dcerpc_matched_key matched_key, *new_matched_key;
2575         dcerpc_call_value *value;
2576
2577         /* !!! we can NOT check flags.visited here since this will interact
2578            badly with when SMB handles (i.e. calls the subdissector)
2579            and desegmented pdu's .
2580            Instead we check if this pdu is already in the matched table or not
2581         */
2582         matched_key.frame = pinfo->fd->num;
2583         matched_key.call_id = hdr->call_id;
2584         value = g_hash_table_lookup(dcerpc_matched, &matched_key);
2585         if(!value){
2586                 dcerpc_bind_key bind_key;
2587                 dcerpc_bind_value *bind_value;
2588
2589                 bind_key.conv=conv;
2590                 bind_key.ctx_id=ctx_id;
2591                 bind_key.smb_fid=get_smb_fid(pinfo->private_data);
2592
2593                 if((bind_value=g_hash_table_lookup(dcerpc_binds, &bind_key)) ){
2594                         if(!(hdr->flags&PFC_FIRST_FRAG)){
2595                                 dcerpc_call_key call_key;
2596                                 dcerpc_call_value *call_value;
2597
2598                                 call_key.conv=conv;
2599                                 call_key.call_id=hdr->call_id;
2600                                 call_key.smb_fid=get_smb_fid(pinfo->private_data);
2601                                 if((call_value=g_hash_table_lookup(dcerpc_calls, &call_key))){
2602                                         new_matched_key = g_mem_chunk_alloc(dcerpc_matched_key_chunk);
2603                                         *new_matched_key = matched_key;
2604                                         g_hash_table_insert (dcerpc_matched, new_matched_key, call_value);
2605                                         value = call_value;
2606                                 }
2607                         } else {
2608                                 dcerpc_call_key *call_key;
2609                                 dcerpc_call_value *call_value;
2610
2611                                 /* We found the binding and it is the first fragment 
2612                                    (or a complete PDU) of a dcerpc pdu so just add 
2613                                    the call to both the call table and the 
2614                                    matched table
2615                                 */
2616                                 call_key=g_mem_chunk_alloc (dcerpc_call_key_chunk);
2617                                 call_key->conv=conv;
2618                                 call_key->call_id=hdr->call_id;
2619                                 call_key->smb_fid=get_smb_fid(pinfo->private_data);
2620
2621                                 /* if there is already a matching call in the table
2622                                    remove it so it is replaced with the new one */
2623                                 if(g_hash_table_lookup(dcerpc_calls, call_key)){
2624                                         g_hash_table_remove(dcerpc_calls, call_key);
2625                                 }
2626
2627                                 call_value=g_mem_chunk_alloc (dcerpc_call_value_chunk);
2628                                 call_value->uuid = bind_value->uuid;
2629                                 call_value->ver = bind_value->ver;
2630                                 call_value->opnum = opnum;
2631                                 call_value->req_frame=pinfo->fd->num;
2632                                 call_value->req_time.secs=pinfo->fd->abs_secs;
2633                                 call_value->req_time.nsecs=pinfo->fd->abs_usecs*1000;
2634                                 call_value->rep_frame=0;
2635                                 call_value->max_ptr=0;
2636                                 call_value->private_data = NULL;
2637                                 g_hash_table_insert (dcerpc_calls, call_key, call_value);
2638
2639                                 new_matched_key = g_mem_chunk_alloc(dcerpc_matched_key_chunk);
2640                                 *new_matched_key = matched_key;
2641                                 g_hash_table_insert (dcerpc_matched, new_matched_key, call_value);
2642                                 value = call_value;
2643                         }
2644                 }
2645         }
2646
2647         if (value) {
2648             dcerpc_info di;
2649
2650             /* handoff this call */
2651             di.conv = conv;
2652             di.call_id = hdr->call_id;
2653             di.smb_fid = get_smb_fid(pinfo->private_data);
2654             di.request = TRUE;
2655             di.call_data = value;
2656                 di.hf_index = -1;
2657
2658             if(value->rep_frame!=0){
2659                 proto_tree_add_uint(dcerpc_tree, hf_dcerpc_response_in,
2660                                     tvb, 0, 0, value->rep_frame);
2661             }
2662 /*qqq request, broken*/
2663             dissect_dcerpc_cn_stub (tvb, offset, pinfo, dcerpc_tree, tree,
2664                                     hdr, &di, &auth_info, alloc_hint,
2665                                     value->req_frame);
2666         } else
2667             show_stub_data (tvb, offset, dcerpc_tree, &auth_info);
2668     }
2669
2670     /* Decrypt the verifier, if present */
2671     dissect_dcerpc_verifier (tvb, pinfo, dcerpc_tree, hdr, &auth_info);
2672 }
2673
2674 static void
2675 dissect_dcerpc_cn_resp (tvbuff_t *tvb, gint offset, packet_info *pinfo,
2676                         proto_tree *dcerpc_tree, proto_tree *tree, e_dce_cn_common_hdr_t *hdr)
2677 {
2678     dcerpc_call_value *value = NULL;
2679     conversation_t *conv;
2680     guint16 ctx_id;
2681     dcerpc_auth_info auth_info;
2682     guint32 alloc_hint;
2683
2684     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2685                                     hf_dcerpc_cn_alloc_hint, &alloc_hint);
2686
2687     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2688                                     hf_dcerpc_cn_ctx_id, &ctx_id);
2689
2690     if (check_col (pinfo->cinfo, COL_INFO)) {
2691         col_append_fstr (pinfo->cinfo, COL_INFO, " ctx_id: %u", ctx_id);
2692     }
2693
2694     offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2695                                    hf_dcerpc_cn_cancel_count, NULL);
2696     /* padding */
2697     offset++;
2698
2699     /*
2700      * XXX - what if this was set when the connection was set up,
2701      * and we just have a security context?
2702      */
2703     dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, hdr, FALSE, &auth_info);
2704
2705     conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
2706                               pinfo->srcport, pinfo->destport, 0);
2707     if (!conv) {
2708         /* no point in creating one here, really */
2709         show_stub_data (tvb, offset, dcerpc_tree, &auth_info);
2710     } else {
2711         dcerpc_matched_key matched_key, *new_matched_key;
2712
2713         /* !!! we can NOT check flags.visited here since this will interact
2714            badly with when SMB handles (i.e. calls the subdissector)
2715            and desegmented pdu's .
2716            Instead we check if this pdu is already in the matched table or not
2717         */
2718         matched_key.frame = pinfo->fd->num;
2719         matched_key.call_id = hdr->call_id;
2720         value=g_hash_table_lookup(dcerpc_matched, &matched_key);
2721         if(!value){
2722                 dcerpc_call_key call_key;
2723                 dcerpc_call_value *call_value;
2724
2725                 call_key.conv=conv;
2726                 call_key.call_id=hdr->call_id;
2727                 call_key.smb_fid=get_smb_fid(pinfo->private_data);
2728
2729                 if((call_value=g_hash_table_lookup(dcerpc_calls, &call_key))){
2730                         new_matched_key = g_mem_chunk_alloc(dcerpc_matched_key_chunk);
2731                         *new_matched_key = matched_key;
2732                         g_hash_table_insert (dcerpc_matched, new_matched_key, call_value);
2733                         value = call_value;
2734                         if(call_value->rep_frame==0){
2735                                 call_value->rep_frame=pinfo->fd->num;
2736                         }
2737                 }
2738         }
2739
2740         if (value) {
2741             dcerpc_info di;
2742
2743             /* handoff this call */
2744             di.conv = conv;
2745             di.call_id = hdr->call_id;
2746             di.smb_fid = get_smb_fid(pinfo->private_data);
2747             di.request = FALSE;
2748             di.call_data = value;
2749
2750             proto_tree_add_uint (dcerpc_tree, hf_dcerpc_opnum, tvb, 0, 0, value->opnum);
2751             if(value->req_frame!=0){
2752                 nstime_t ns;
2753                 proto_tree_add_uint(dcerpc_tree, hf_dcerpc_request_in,
2754                                     tvb, 0, 0, value->req_frame);
2755                 ns.secs= pinfo->fd->abs_secs-value->req_time.secs;
2756                 ns.nsecs=pinfo->fd->abs_usecs*1000-value->req_time.nsecs;
2757                 if(ns.nsecs<0){
2758                         ns.nsecs+=1000000000;
2759                         ns.secs--;
2760                 }
2761                 proto_tree_add_time(dcerpc_tree, hf_dcerpc_time, tvb, offset, 0, &ns);
2762             }
2763
2764 /*qqq response ok*/
2765             dissect_dcerpc_cn_stub (tvb, offset, pinfo, dcerpc_tree, tree,
2766                                     hdr, &di, &auth_info, alloc_hint,
2767                                     value->rep_frame);
2768         } else
2769             show_stub_data (tvb, offset, dcerpc_tree, &auth_info);
2770     }
2771
2772     /* Decrypt the verifier, if present */
2773     dissect_dcerpc_verifier (tvb, pinfo, dcerpc_tree, hdr, &auth_info);
2774 }
2775
2776 static void
2777 dissect_dcerpc_cn_fault (tvbuff_t *tvb, gint offset, packet_info *pinfo,
2778                          proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr)
2779 {
2780     dcerpc_call_value *value = NULL;
2781     conversation_t *conv;
2782     guint16 ctx_id;
2783     guint32 status;
2784     guint32 alloc_hint;
2785     dcerpc_auth_info auth_info;
2786
2787     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2788                                     hf_dcerpc_cn_alloc_hint, &alloc_hint);
2789
2790     offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2791                                     hf_dcerpc_cn_ctx_id, &ctx_id);
2792
2793     offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2794                                    hf_dcerpc_cn_cancel_count, NULL);
2795     /* padding */
2796     offset++;
2797
2798     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
2799                                     hf_dcerpc_cn_status, &status);
2800
2801     if (check_col (pinfo->cinfo, COL_INFO)) {
2802         col_append_fstr (pinfo->cinfo, COL_INFO,
2803                       " ctx_id: %u status: %s", ctx_id,
2804                       val_to_str(status, reject_status_vals,
2805                                  "Unknown (0x%08x)"));
2806     }
2807
2808     /* padding */
2809     offset += 4;
2810
2811     /*
2812      * XXX - what if this was set when the connection was set up,
2813      * and we just have a security context?
2814      */
2815     dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, hdr, FALSE, &auth_info);
2816
2817     conv = find_conversation (&pinfo->src, &pinfo->dst, pinfo->ptype,
2818                               pinfo->srcport, pinfo->destport, 0);
2819     if (!conv) {
2820         /* no point in creating one here, really */
2821     } else {
2822         dcerpc_matched_key matched_key, *new_matched_key;
2823
2824         /* !!! we can NOT check flags.visited here since this will interact
2825            badly with when SMB handles (i.e. calls the subdissector)
2826            and desegmented pdu's .
2827            Instead we check if this pdu is already in the matched table or not
2828         */
2829         matched_key.frame = pinfo->fd->num;
2830         matched_key.call_id = hdr->call_id;
2831         value=g_hash_table_lookup(dcerpc_matched, &matched_key);
2832         if(!value){
2833                 dcerpc_call_key call_key;
2834                 dcerpc_call_value *call_value;
2835
2836                 call_key.conv=conv;
2837                 call_key.call_id=hdr->call_id;
2838                 call_key.smb_fid=get_smb_fid(pinfo->private_data);
2839
2840                 if((call_value=g_hash_table_lookup(dcerpc_calls, &call_key))){
2841                         new_matched_key = g_mem_chunk_alloc(dcerpc_matched_key_chunk);
2842                         *new_matched_key = matched_key;
2843                         g_hash_table_insert (dcerpc_matched, new_matched_key, call_value);
2844                         value = call_value;
2845                         if(call_value->rep_frame==0){
2846                                 call_value->rep_frame=pinfo->fd->num;
2847                         }
2848
2849                 }
2850         }
2851
2852         if (value) {
2853             int length, reported_length, stub_length;
2854             dcerpc_info di;
2855
2856             /* handoff this call */
2857             di.conv = conv;
2858             di.call_id = hdr->call_id;
2859             di.smb_fid = get_smb_fid(pinfo->private_data);
2860             di.request = FALSE;
2861             di.call_data = value;
2862
2863             proto_tree_add_uint (dcerpc_tree, hf_dcerpc_opnum, tvb, 0, 0, value->opnum);
2864             if(value->req_frame!=0){
2865                 nstime_t ns;
2866                 proto_tree_add_uint(dcerpc_tree, hf_dcerpc_request_in,
2867                                     tvb, 0, 0, value->req_frame);
2868                 ns.secs= pinfo->fd->abs_secs-value->req_time.secs;
2869                 ns.nsecs=pinfo->fd->abs_usecs*1000-value->req_time.nsecs;
2870                 if(ns.nsecs<0){
2871                         ns.nsecs+=1000000000;
2872                         ns.secs--;
2873                 }
2874                 proto_tree_add_time(dcerpc_tree, hf_dcerpc_time, tvb, offset, 0, &ns);
2875             }
2876
2877             length = tvb_length_remaining(tvb, offset);
2878             reported_length = tvb_reported_length_remaining(tvb, offset);
2879             stub_length = hdr->frag_len - offset - auth_info.auth_size;
2880             if (length > stub_length)
2881               length = stub_length;
2882             if (reported_length > stub_length)
2883               reported_length = stub_length;
2884
2885             /* If we don't have reassembly enabled, or this packet contains
2886                the entire PDU, or if we don't have all the data in this
2887                fragment, just call the handoff directly if this is the
2888                first fragment or the PDU isn't fragmented. */
2889             if( (!dcerpc_reassemble) || PFC_NOT_FRAGMENTED(hdr) ||
2890                         !tvb_bytes_exist(tvb, offset, stub_length) ){
2891                 if(hdr->flags&PFC_FIRST_FRAG){
2892                     /* First fragment, possibly the only fragment */
2893                     /*
2894                      * XXX - should there be a third routine for each
2895                      * function in an RPC subdissector, to handle
2896                      * fault responses?  The DCE RPC 1.1 spec says
2897                      * three's "stub data" here, which I infer means
2898                      * that it's protocol-specific and call-specific.
2899                      *
2900                      * It should probably get passed the status code
2901                      * as well, as that might be protocol-specific.
2902                      */
2903                     if (dcerpc_tree) {
2904                         if (stub_length > 0) {
2905                             proto_tree_add_text (dcerpc_tree, tvb, offset, stub_length,
2906                                                  "Fault stub data (%d byte%s)",
2907                                                  stub_length,
2908                                                  plurality(stub_length, "", "s"));
2909                         }
2910                     }
2911                 } else {
2912                     /* PDU is fragmented and this isn't the first fragment */
2913                     if (check_col(pinfo->cinfo, COL_INFO)) {
2914                         col_append_fstr(pinfo->cinfo, COL_INFO,
2915                                         " [DCE/RPC fragment]");
2916                     }
2917                     if (dcerpc_tree) {
2918                         if (stub_length > 0) {
2919                             proto_tree_add_text (dcerpc_tree, tvb, offset, stub_length,
2920                                                  "Fragment data (%d byte%s)",
2921                                                  stub_length,
2922                                                  plurality(stub_length, "", "s"));
2923                         }
2924                     }
2925                 }
2926             } else {
2927                 /* Reassembly is enabled, the PDU is fragmented, and
2928                    we have all the data in the fragment; the first two
2929                    of those mean we should attempt reassembly, and the
2930                    third means we can attempt reassembly. */
2931                 if (dcerpc_tree) {
2932                     if (length > 0) {
2933                         proto_tree_add_text (dcerpc_tree, tvb, offset, stub_length,
2934                                              "Fragment data (%d byte%s)",
2935                                              stub_length,
2936                                              plurality(stub_length, "", "s"));
2937                     }
2938                 }
2939                 if(hdr->flags&PFC_FIRST_FRAG){  /* FIRST fragment */
2940                     if( (!pinfo->fd->flags.visited) && value->rep_frame ){
2941                         fragment_add(tvb, offset, pinfo, value->rep_frame,
2942                              dcerpc_co_reassemble_table,
2943                              0,
2944                              stub_length,
2945                              TRUE);
2946                         fragment_set_tot_len(pinfo, value->rep_frame,
2947                              dcerpc_co_reassemble_table, alloc_hint);
2948                     }
2949                     if (check_col(pinfo->cinfo, COL_INFO)) {
2950                         col_append_fstr(pinfo->cinfo, COL_INFO,
2951                                         " [DCE/RPC fragment]");
2952                     }
2953                 } else if(hdr->flags&PFC_LAST_FRAG){  /* LAST fragment */
2954                     if( value->rep_frame ){
2955                         fragment_data *fd_head;
2956                         guint32 tot_len;
2957
2958                         tot_len = fragment_get_tot_len(pinfo, value->rep_frame,
2959                                        dcerpc_co_reassemble_table);
2960                         fd_head = fragment_add(tvb, offset, pinfo,
2961                              value->rep_frame,
2962                              dcerpc_co_reassemble_table,
2963                              tot_len-alloc_hint,
2964                              stub_length,
2965                              TRUE);
2966
2967                         if(fd_head){
2968                             /* We completed reassembly */
2969                             tvbuff_t *next_tvb;
2970
2971                             next_tvb = tvb_new_real_data(fd_head->data, fd_head->datalen, fd_head->datalen);
2972                             tvb_set_child_real_data_tvbuff(tvb, next_tvb);
2973                             add_new_data_source(pinfo, next_tvb, "Reassembled DCE/RPC");
2974                             show_fragment_tree(fd_head, &dcerpc_frag_items,
2975                                 dcerpc_tree, pinfo, next_tvb);
2976
2977                             /*
2978                              * XXX - should there be a third routine for each
2979                              * function in an RPC subdissector, to handle
2980                              * fault responses?  The DCE RPC 1.1 spec says
2981                              * three's "stub data" here, which I infer means
2982                              * that it's protocol-specific and call-specific.
2983                              *
2984                              * It should probably get passed the status code
2985                              * as well, as that might be protocol-specific.
2986                              */
2987                             if (dcerpc_tree) {
2988                                 if (length > 0) {
2989                                      proto_tree_add_text (dcerpc_tree, tvb, offset, stub_length,
2990                                                           "Fault stub data (%d byte%s)",
2991                                                           stub_length,
2992                                                           plurality(stub_length, "", "s"));
2993                                 }
2994                             }
2995                         } else {
2996                             /* Reassembly not complete - some fragments
2997                                are missing */
2998                             if (check_col(pinfo->cinfo, COL_INFO)) {
2999                                 col_append_fstr(pinfo->cinfo, COL_INFO,
3000                                                 " [DCE/RPC fragment]");
3001                             }
3002                         }
3003                     }
3004                 } else {  /* MIDDLE fragment(s) */
3005                     if( (!pinfo->fd->flags.visited) && value->rep_frame ){
3006                         guint32 tot_len;
3007                         tot_len = fragment_get_tot_len(pinfo, value->rep_frame,
3008                                        dcerpc_co_reassemble_table);
3009                         fragment_add(tvb, offset, pinfo, value->rep_frame,
3010                              dcerpc_co_reassemble_table,
3011                              tot_len-alloc_hint,
3012                              stub_length,
3013                              TRUE);
3014                     }
3015                     if (check_col(pinfo->cinfo, COL_INFO)) {
3016                         col_append_fstr(pinfo->cinfo, COL_INFO,
3017                                         " [DCE/RPC fragment]");
3018                     }
3019                 }
3020             }
3021         }
3022     }
3023 }
3024
3025 /*
3026  * DCERPC dissector for connection oriented calls
3027  */
3028 static int
3029 dissect_dcerpc_cn (tvbuff_t *tvb, int offset, packet_info *pinfo,
3030                    proto_tree *tree, gboolean can_desegment)
3031 {
3032     static char nulls[4] = { 0 };
3033     int start_offset;
3034     int padding = 0;
3035     proto_item *ti = NULL;
3036     proto_item *tf = NULL;
3037     proto_tree *dcerpc_tree = NULL;
3038     proto_tree *cn_flags_tree = NULL;
3039     proto_tree *drep_tree = NULL;
3040     e_dce_cn_common_hdr_t hdr;
3041     dcerpc_auth_info auth_info;
3042
3043     /*
3044      * when done over nbt, dcerpc requests are padded with 4 bytes of null
3045      * data for some reason.
3046      *
3047      * XXX - if that's always the case, the right way to do this would
3048      * be to have a "dissect_dcerpc_cn_nb" routine which strips off
3049      * the 4 bytes of null padding, and make that the dissector
3050      * used for "netbios".
3051      */
3052     if (tvb_memeql (tvb, offset, nulls, 4) == 0) {
3053
3054         /*
3055          * Skip the padding.
3056          */
3057         offset += 4;
3058         padding += 4;
3059     }
3060
3061     /*
3062      * Check if this looks like a C/O DCERPC call
3063      */
3064     if (!tvb_bytes_exist (tvb, offset, sizeof (hdr))) {
3065         return -1;
3066     }
3067     start_offset = offset;
3068     hdr.rpc_ver = tvb_get_guint8 (tvb, offset++);
3069     if (hdr.rpc_ver != 5)
3070         return -1;
3071     hdr.rpc_ver_minor = tvb_get_guint8 (tvb, offset++);
3072     if (hdr.rpc_ver_minor != 0 && hdr.rpc_ver_minor != 1)
3073         return -1;
3074     hdr.ptype = tvb_get_guint8 (tvb, offset++);
3075     if (hdr.ptype > 19)
3076         return -1;
3077
3078     hdr.flags = tvb_get_guint8 (tvb, offset++);
3079     tvb_memcpy (tvb, (guint8 *)hdr.drep, offset, sizeof (hdr.drep));
3080     offset += sizeof (hdr.drep);
3081
3082     hdr.frag_len = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
3083     offset += 2;
3084     hdr.auth_len = dcerpc_tvb_get_ntohs (tvb, offset, hdr.drep);
3085     offset += 2;
3086     hdr.call_id = dcerpc_tvb_get_ntohl (tvb, offset, hdr.drep);
3087     offset += 4;
3088
3089     if (can_desegment && pinfo->can_desegment
3090         && !tvb_bytes_exist(tvb, start_offset, hdr.frag_len)) {
3091         pinfo->desegment_offset = start_offset;
3092         pinfo->desegment_len = hdr.frag_len - tvb_length_remaining (tvb, start_offset);
3093         return 0;       /* desegmentation required */
3094     }
3095
3096     if (check_col (pinfo->cinfo, COL_PROTOCOL))
3097         col_set_str (pinfo->cinfo, COL_PROTOCOL, "DCERPC");
3098     if (check_col (pinfo->cinfo, COL_INFO))
3099         col_add_fstr (pinfo->cinfo, COL_INFO, "%s: call_id: %u",
3100             pckt_vals[hdr.ptype].strptr, hdr.call_id);
3101
3102     if (tree) {
3103       offset = start_offset;
3104         ti = proto_tree_add_item (tree, proto_dcerpc, tvb, offset, hdr.frag_len, FALSE);
3105         if (ti) {
3106             dcerpc_tree = proto_item_add_subtree (ti, ett_dcerpc);
3107         }
3108         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_ver, tvb, offset++, 1, hdr.rpc_ver);
3109         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_ver_minor, tvb, offset++, 1, hdr.rpc_ver_minor);
3110         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_packet_type, tvb, offset++, 1, hdr.ptype);
3111         tf = proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_flags, tvb, offset, 1, hdr.flags);
3112         cn_flags_tree = proto_item_add_subtree (tf, ett_dcerpc_cn_flags);
3113         if (cn_flags_tree) {
3114             proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_object, tvb, offset, 1, hdr.flags);
3115             proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_maybe, tvb, offset, 1, hdr.flags);
3116             proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_dne, tvb, offset, 1, hdr.flags);
3117             proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_mpx, tvb, offset, 1, hdr.flags);
3118             proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_reserved, tvb, offset, 1, hdr.flags);
3119             proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_cancel_pending, tvb, offset, 1, hdr.flags);
3120             proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_last_frag, tvb, offset, 1, hdr.flags);
3121             proto_tree_add_boolean (cn_flags_tree, hf_dcerpc_cn_flags_first_frag, tvb, offset, 1, hdr.flags);
3122         }
3123         offset++;
3124
3125         tf = proto_tree_add_bytes (dcerpc_tree, hf_dcerpc_drep, tvb, offset, 4, hdr.drep);
3126         drep_tree = proto_item_add_subtree (tf, ett_dcerpc_drep);
3127         if (drep_tree) {
3128             proto_tree_add_uint(drep_tree, hf_dcerpc_drep_byteorder, tvb, offset, 1, hdr.drep[0] >> 4);
3129             proto_tree_add_uint(drep_tree, hf_dcerpc_drep_character, tvb, offset, 1, hdr.drep[0] & 0x0f);
3130             proto_tree_add_uint(drep_tree, hf_dcerpc_drep_fp, tvb, offset+1, 1, hdr.drep[1]);
3131         }
3132         offset += sizeof (hdr.drep);
3133
3134         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_frag_len, tvb, offset, 2, hdr.frag_len);
3135         offset += 2;
3136
3137         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_auth_len, tvb, offset, 2, hdr.auth_len);
3138         offset += 2;
3139
3140         proto_tree_add_uint (dcerpc_tree, hf_dcerpc_cn_call_id, tvb, offset, 4, hdr.call_id);
3141         offset += 4;
3142     }
3143
3144     /*
3145      * Packet type specific stuff is next.
3146      */
3147     switch (hdr.ptype) {
3148     case PDU_BIND:
3149     case PDU_ALTER:
3150         dissect_dcerpc_cn_bind (tvb, offset, pinfo, dcerpc_tree, &hdr);
3151         break;
3152
3153     case PDU_BIND_ACK:
3154     case PDU_ALTER_ACK:
3155         dissect_dcerpc_cn_bind_ack (tvb, offset, pinfo, dcerpc_tree, &hdr);
3156         break;
3157
3158     case PDU_AUTH3:
3159         /*
3160          * Nothing after the common header other than credentials.
3161          */
3162         dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, &hdr, TRUE, 
3163                                 &auth_info);
3164         break;
3165
3166     case PDU_REQ:
3167         dissect_dcerpc_cn_rqst (tvb, offset, pinfo, dcerpc_tree, tree, &hdr);
3168         break;
3169
3170     case PDU_RESP:
3171         dissect_dcerpc_cn_resp (tvb, offset, pinfo, dcerpc_tree, tree, &hdr);
3172         break;
3173
3174     case PDU_FAULT:
3175         dissect_dcerpc_cn_fault (tvb, offset, pinfo, dcerpc_tree, &hdr);
3176         break;
3177
3178     case PDU_BIND_NAK:
3179         dissect_dcerpc_cn_bind_nak (tvb, offset, pinfo, dcerpc_tree, &hdr);
3180         break;
3181
3182     case PDU_CO_CANCEL:
3183     case PDU_ORPHANED:
3184         /*
3185          * Nothing after the common header other than an authentication
3186          * verifier.
3187          */
3188         dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, &hdr, FALSE, 
3189                                 &auth_info);
3190         break;
3191
3192     case PDU_SHUTDOWN:
3193         /*
3194          * Nothing after the common header, not even an authentication
3195          * verifier.
3196          */
3197         break;
3198
3199     default:
3200         /* might as well dissect the auth info */