2 * Dissector for GSS-API tokens as described in rfc2078, section 3.1
3 * Copyright 2002, Tim Potter <tpot@samba.org>
4 * Copyright 2002, Richard Sharpe <rsharpe@samba.org> Added a few
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
34 #include <epan/packet.h>
35 #include <epan/exceptions.h>
36 #include <epan/conversation.h>
37 #include <epan/wmem/wmem.h>
38 #include <epan/prefs.h>
39 #include <epan/reassemble.h>
40 #include <epan/asn1.h>
41 #include <epan/to_str.h>
42 #include <epan/show_exception.h>
44 #include <epan/dissectors/packet-ber.h>
45 #include <epan/dissectors/packet-dcerpc.h>
46 #include <epan/dissectors/packet-gssapi.h>
48 static int proto_gssapi
= -1;
50 static int hf_gssapi_oid
= -1;
51 static int hf_gssapi_segments
= -1;
52 static int hf_gssapi_segment
= -1;
53 static int hf_gssapi_segment_overlap
= -1;
54 static int hf_gssapi_segment_overlap_conflict
= -1;
55 static int hf_gssapi_segment_multiple_tails
= -1;
56 static int hf_gssapi_segment_too_long_fragment
= -1;
57 static int hf_gssapi_segment_error
= -1;
58 static int hf_gssapi_segment_count
= -1;
59 static int hf_gssapi_reassembled_in
= -1;
60 static int hf_gssapi_reassembled_length
= -1;
62 static gint ett_gssapi
= -1;
63 static gint ett_gssapi_segment
= -1;
64 static gint ett_gssapi_segments
= -1;
66 static gboolean gssapi_reassembly
= TRUE
;
68 typedef struct _gssapi_conv_info_t
{
69 gssapi_oid_value
*oid
;
73 gboolean do_reassembly
; /* this field is used on first sequential scan of packets to help indicate when the next blob is a fragment continuing a previous one */
78 typedef struct _gssapi_frag_info_t
{
80 guint32 reassembled_in
;
83 static const fragment_items gssapi_frag_items
= {
89 &hf_gssapi_segment_overlap
,
90 &hf_gssapi_segment_overlap_conflict
,
91 &hf_gssapi_segment_multiple_tails
,
92 &hf_gssapi_segment_too_long_fragment
,
93 &hf_gssapi_segment_error
,
94 &hf_gssapi_segment_count
,
96 &hf_gssapi_reassembled_length
,
97 /* Reassembled data field */
103 static reassembly_table gssapi_reassembly_table
;
106 gssapi_reassembly_init(void)
108 reassembly_table_init(&gssapi_reassembly_table
,
109 &addresses_reassembly_table_functions
);
116 static dissector_handle_t ntlmssp_handle
;
117 static dissector_handle_t ntlmssp_payload_handle
;
118 static dissector_handle_t ntlmssp_verf_handle
;
119 static dissector_handle_t ntlmssp_data_only_handle
;
120 static dissector_handle_t spnego_krb5_wrap_handle
;
122 static GHashTable
*gssapi_oids
;
125 gssapi_oid_equal(gconstpointer k1
, gconstpointer k2
)
127 const char *key1
= (const char *)k1
;
128 const char *key2
= (const char *)k2
;
130 return strcmp(key1
, key2
) == 0;
134 gssapi_oid_hash(gconstpointer k
)
136 const char *key
= (const char *)k
;
139 for (i
= 0; key
[i
]; i
++)
146 gssapi_init_oid(const char *oid
, int proto
, int ett
, dissector_handle_t handle
,
147 dissector_handle_t wrap_handle
, const gchar
*comment
)
149 char *key
= g_strdup(oid
);
150 gssapi_oid_value
*value
= (gssapi_oid_value
*)g_malloc(sizeof(*value
));
152 value
->proto
= find_protocol_by_id(proto
);
154 value
->handle
= handle
;
155 value
->wrap_handle
= wrap_handle
;
156 value
->comment
= comment
;
158 g_hash_table_insert(gssapi_oids
, key
, value
);
159 register_ber_oid_dissector_handle(key
, handle
, proto
, comment
);
163 * This takes an OID in text string form as
167 gssapi_lookup_oid_str(const char *oid_key
)
169 gssapi_oid_value
*value
;
173 value
= (gssapi_oid_value
*)g_hash_table_lookup(gssapi_oids
, oid_key
);
178 dissect_gssapi_work(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
179 gboolean is_verifier
)
181 proto_item
*volatile item
;
182 proto_tree
*volatile subtree
;
183 volatile int return_offset
= 0;
184 gssapi_conv_info_t
*volatile gss_info
;
185 gssapi_oid_value
*oidvalue
;
186 dissector_handle_t handle
;
187 conversation_t
*conversation
;
189 int len
, start_offset
, oid_start_offset
;
192 gboolean pc
, ind_field
;
196 fragment_head
*fd_head
=NULL
;
197 gssapi_frag_info_t
*fi
;
198 tvbuff_t
*volatile gss_tvb
=NULL
;
204 asn1_ctx_init(&asn1_ctx
, ASN1_ENC_BER
, TRUE
, pinfo
);
206 * We don't know whether the data is encrypted, so say it's
207 * not, for now. The subdissector must set gssapi_data_encrypted
210 pinfo
->gssapi_data_encrypted
= FALSE
;
214 * We need a conversation for later
216 conversation
= find_or_create_conversation(pinfo
);
218 gss_info
= (gssapi_conv_info_t
*)conversation_get_proto_data(conversation
, proto_gssapi
);
220 gss_info
= wmem_new(wmem_file_scope(), gssapi_conv_info_t
);
222 gss_info
->do_reassembly
=FALSE
;
223 gss_info
->frags
=wmem_tree_new(wmem_file_scope());
225 conversation_add_proto_data(conversation
, proto_gssapi
, gss_info
);
228 item
= proto_tree_add_item(
229 tree
, proto_gssapi
, tvb
, offset
, -1, ENC_NA
);
231 subtree
= proto_item_add_subtree(item
, ett_gssapi
);
234 * Catch the ReportedBoundsError exception; the stuff we've been
235 * handed doesn't necessarily run to the end of the packet, it's
236 * an item inside a packet, so if it happens to be malformed (or
237 * we, or a dissector we call, has a bug), so that an exception
238 * is thrown, we want to report the error, but return and let
239 * our caller dissect the rest of the packet.
241 * If it gets a BoundsError, we can stop, as there's nothing more
242 * in the packet after our blob to see, so we just re-throw the
245 pd_save
= pinfo
->private_data
;
250 /* First of all, if it's the first time we see this packet
251 * then check whether we are in the middle of reassembly or not
253 if( (!pinfo
->fd
->flags
.visited
)
254 && (gss_info
->do_reassembly
)
255 && (gssapi_reassembly
) ){
256 fi
=(gssapi_frag_info_t
*)wmem_tree_lookup32(gss_info
->frags
, gss_info
->first_frame
);
260 wmem_tree_insert32(gss_info
->frags
, pinfo
->fd
->num
, fi
);
261 fd_head
=fragment_add(&gssapi_reassembly_table
,
262 tvb
, 0, pinfo
, fi
->first_frame
, NULL
,
263 gss_info
->frag_offset
,
264 tvb_length(tvb
), TRUE
);
265 gss_info
->frag_offset
+=tvb_length(tvb
);
267 /* we need more fragments */
272 /* this blob is now fully reassembled */
273 gss_info
->do_reassembly
=FALSE
;
274 fi
->reassembled_in
=pinfo
->fd
->num
;
276 gss_tvb
=tvb_new_chain(tvb
, fd_head
->tvb_data
);
277 add_new_data_source(pinfo
, gss_tvb
, "Reassembled GSSAPI");
279 /* We have seen this packet before.
280 * Is this blob part of reassembly or a normal blob ?
282 if( (pinfo
->fd
->flags
.visited
)
283 && (gssapi_reassembly
) ){
284 fi
=(gssapi_frag_info_t
*)wmem_tree_lookup32(gss_info
->frags
, pinfo
->fd
->num
);
286 fd_head
=fragment_get(&gssapi_reassembly_table
,
287 pinfo
, fi
->first_frame
, NULL
);
288 if(fd_head
&& (fd_head
->flags
&FD_DEFRAGMENTED
)){
289 if(pinfo
->fd
->num
==fi
->reassembled_in
){
290 proto_item
*frag_tree_item
;
291 gss_tvb
=tvb_new_chain(tvb
, fd_head
->tvb_data
);
292 add_new_data_source(pinfo
, gss_tvb
, "Reassembled GSSAPI");
293 show_fragment_tree(fd_head
, &gssapi_frag_items
, tree
, pinfo
, tvb
, &frag_tree_item
);
296 it
=proto_tree_add_uint(tree
, hf_gssapi_reassembled_in
, tvb
, 0, 0, fi
->reassembled_in
);
297 PROTO_ITEM_SET_GENERATED(it
);
305 offset
= get_ber_identifier(gss_tvb
, offset
, &appclass
, &pc
, &tag
);
306 offset
= get_ber_length(gss_tvb
, offset
, &len1
, &ind_field
);
309 if (!(appclass
== BER_CLASS_APP
&& pc
&& tag
== 0)) {
310 /* It could be NTLMSSP, with no OID. This can happen
311 for anything that microsoft calls 'Negotiate' or GSS-SPNEGO */
312 if ((tvb_length_remaining(gss_tvb
, start_offset
)>7) && (tvb_strneql(gss_tvb
, start_offset
, "NTLMSSP", 7) == 0)) {
313 return_offset
= call_dissector(ntlmssp_handle
,
314 tvb_new_subset_remaining(gss_tvb
, start_offset
),
318 /* Maybe it's new NTLMSSP payload */
319 if ((tvb_length_remaining(gss_tvb
, start_offset
)>16) &&
320 ((tvb_memeql(gss_tvb
, start_offset
, "\x01\x00\x00\x00", 4) == 0))) {
321 return_offset
= call_dissector(ntlmssp_payload_handle
,
322 tvb_new_subset_remaining(gss_tvb
, start_offset
),
324 pinfo
->gssapi_data_encrypted
= TRUE
;
327 if ((tvb_length_remaining(gss_tvb
, start_offset
)==16) &&
328 ((tvb_memeql(gss_tvb
, start_offset
, "\x01\x00\x00\x00", 4) == 0))) {
330 return_offset
= call_dissector(ntlmssp_verf_handle
,
331 tvb_new_subset_remaining(gss_tvb
, start_offset
),
334 else if( pinfo
->gssapi_encrypted_tvb
) {
335 return_offset
= call_dissector(ntlmssp_data_only_handle
,
336 tvb_new_subset_remaining(pinfo
->gssapi_encrypted_tvb
, 0),
338 pinfo
->gssapi_data_encrypted
= TRUE
;
343 /* Maybe it's new GSSKRB5 CFX Wrapping */
344 if ((tvb_length_remaining(gss_tvb
, start_offset
)>2) &&
345 ((tvb_memeql(gss_tvb
, start_offset
, "\04\x04", 2) == 0) ||
346 (tvb_memeql(gss_tvb
, start_offset
, "\05\x04", 2) == 0))) {
347 return_offset
= call_dissector(spnego_krb5_wrap_handle
,
348 tvb_new_subset_remaining(gss_tvb
, start_offset
),
354 * If we do not recognise an Application class,
355 * then we are probably dealing with an inner context
356 * token or a wrap token, and we should retrieve the
357 * gssapi_oid_value pointer from the per-frame data or,
358 * if there is no per-frame data (as would be the case
359 * the first time we dissect this frame), from the
360 * conversation that exists or that we created from
361 * pinfo (and then make it per-frame data).
362 * We need to make it per-frame data as there can be
363 * more than one GSS-API negotiation in a conversation.
365 * Note! We "cheat". Since we only need the pointer,
366 * we store that as the data. (That's not really
367 * "cheating" - the per-frame data and per-conversation
368 * data code doesn't care what you supply as a data
369 * pointer; it just treats it as an opaque pointer, it
370 * doesn't dereference it or free what it points to.)
372 oidvalue
= (gssapi_oid_value
*)p_get_proto_data(pinfo
->fd
, proto_gssapi
, 0);
373 if (!oidvalue
&& !pinfo
->fd
->flags
.visited
)
375 /* No handle attached to this frame, but it's the first */
376 /* pass, so it'd be attached to the conversation. */
377 oidvalue
= gss_info
->oid
;
379 p_add_proto_data(pinfo
->fd
, proto_gssapi
, 0, gss_info
->oid
);
383 proto_tree_add_text(subtree
, gss_tvb
, start_offset
, 0,
384 "Unknown header (class=%d, pc=%d, tag=%d)",
386 return_offset
= tvb_length(gss_tvb
);
389 tvbuff_t
*oid_tvb_local
;
391 oid_tvb_local
= tvb_new_subset_remaining(gss_tvb
, start_offset
);
393 handle
= oidvalue
->wrap_handle
;
395 handle
= oidvalue
->handle
;
396 len
= call_dissector(handle
, oid_tvb_local
, pinfo
, subtree
);
398 return_offset
= tvb_length(gss_tvb
);
400 return_offset
= start_offset
+ len
;
401 goto done
; /* We are finished here */
406 oid_start_offset
=offset
;
407 offset
=dissect_ber_object_identifier_str(FALSE
, &asn1_ctx
, subtree
, gss_tvb
, offset
, hf_gssapi_oid
, &oid
);
408 oidvalue
= gssapi_lookup_oid_str(oid
);
411 /* Check if we need reassembly of this blob.
412 * Only try reassembly for OIDs we recognize
413 * and when we have the entire tvb
415 * SMB will sometimes split one large GSSAPI blob
416 * across multiple SMB/SessionSetup commands.
417 * While we should look at the uid returned in the response
418 * to the first SessionSetup and use that as a key
419 * instead for simplicity we assume there will not be several
420 * such authentication at once on a single tcp session
422 if( (!pinfo
->fd
->flags
.visited
)
424 && (tvb_length(gss_tvb
)==tvb_reported_length(gss_tvb
))
425 && (len1
>(guint32
)tvb_length_remaining(gss_tvb
, oid_start_offset
))
426 && (gssapi_reassembly
) ){
427 fi
=wmem_new(wmem_file_scope(), gssapi_frag_info_t
);
428 fi
->first_frame
=pinfo
->fd
->num
;
429 fi
->reassembled_in
=0;
430 wmem_tree_insert32(gss_info
->frags
, pinfo
->fd
->num
, fi
);
432 fragment_add(&gssapi_reassembly_table
,
433 gss_tvb
, 0, pinfo
, pinfo
->fd
->num
, NULL
,
434 0, tvb_length(gss_tvb
), TRUE
);
435 fragment_set_tot_len(&gssapi_reassembly_table
,
436 pinfo
, pinfo
->fd
->num
, NULL
, len1
+oid_start_offset
);
438 gss_info
->do_reassembly
=TRUE
;
439 gss_info
->first_frame
=pinfo
->fd
->num
;
440 gss_info
->frag_offset
=tvb_length(gss_tvb
);
446 * Hand off to subdissector.
449 if ((oidvalue
== NULL
) ||
450 !proto_is_protocol_enabled(oidvalue
->proto
)) {
451 /* No dissector for this oid */
452 proto_tree_add_text(subtree
, gss_tvb
, oid_start_offset
, -1,
455 return_offset
= tvb_length(gss_tvb
);
459 /* Save a pointer to the data for the OID for the
460 * GSSAPI protocol for this conversation.
464 * Now add the proto data ...
465 * but only if it is not already there.
468 gss_info
->oid
=oidvalue
;
472 handle
= oidvalue
->wrap_handle
;
473 if (handle
!= NULL
) {
474 oid_tvb
= tvb_new_subset_remaining(gss_tvb
, offset
);
475 len
= call_dissector(handle
, oid_tvb
, pinfo
,
478 return_offset
= tvb_length(gss_tvb
);
480 return_offset
= offset
+ len
;
482 proto_tree_add_text(subtree
, gss_tvb
, offset
, -1,
483 "Authentication verifier");
484 return_offset
= tvb_length(gss_tvb
);
487 handle
= oidvalue
->handle
;
488 if (handle
!= NULL
) {
489 oid_tvb
= tvb_new_subset_remaining(gss_tvb
, offset
);
490 len
= call_dissector(handle
, oid_tvb
, pinfo
,
493 return_offset
= tvb_length(gss_tvb
);
495 return_offset
= offset
+ len
;
497 proto_tree_add_text(subtree
, gss_tvb
, offset
, -1,
498 "Authentication credentials");
499 return_offset
= tvb_length(gss_tvb
);
505 } CATCH_NONFATAL_ERRORS
{
507 * Somebody threw an exception that means that there
508 * was a problem dissecting the payload; that means
509 * that a dissector was found, so we don't need to
510 * dissect the payload as data or update the protocol
513 * Just show the exception and then drive on to show
514 * the trailer, after noting that a dissector was found
515 * and restoring the protocol value that was in effect
516 * before we called the subdissector.
518 * Restore the private_data structure in case one of the
519 * called dissectors modified it (and, due to the exception,
520 * was unable to restore it).
522 pinfo
->private_data
= pd_save
;
523 show_exception(gss_tvb
, pinfo
, tree
, EXCEPT_CODE
, GET_MESSAGE
);
526 proto_item_set_len(item
, return_offset
);
527 return return_offset
;
531 dissect_gssapi(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
533 dissect_gssapi_work(tvb
, pinfo
, tree
, FALSE
);
537 dissect_gssapi_verf(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
539 return dissect_gssapi_work(tvb
, pinfo
, tree
, TRUE
);
543 proto_register_gssapi(void)
545 static hf_register_info hf
[] = {
547 { "OID", "gss-api.OID", FT_STRING
, BASE_NONE
,
548 NULL
, 0, "This is a GSS-API Object Identifier", HFILL
}},
549 { &hf_gssapi_segment
,
550 { "GSSAPI Segment", "gss-api.segment", FT_FRAMENUM
, BASE_NONE
,
551 NULL
, 0x0, NULL
, HFILL
}},
552 { &hf_gssapi_segments
,
553 { "GSSAPI Segments", "gss-api.segment.segments", FT_NONE
, BASE_NONE
,
554 NULL
, 0x0, NULL
, HFILL
}},
555 { &hf_gssapi_segment_overlap
,
556 { "Fragment overlap", "gss-api.segment.overlap", FT_BOOLEAN
, BASE_NONE
,
557 NULL
, 0x0, "Fragment overlaps with other fragments", HFILL
}},
558 { &hf_gssapi_segment_overlap_conflict
,
559 { "Conflicting data in fragment overlap", "gss-api.segment.overlap.conflict", FT_BOOLEAN
, BASE_NONE
,
560 NULL
, 0x0, "Overlapping fragments contained conflicting data", HFILL
}},
561 { &hf_gssapi_segment_multiple_tails
,
562 { "Multiple tail fragments found", "gss-api.segment.multipletails", FT_BOOLEAN
, BASE_NONE
,
563 NULL
, 0x0, "Several tails were found when defragmenting the packet", HFILL
}},
564 { &hf_gssapi_segment_too_long_fragment
,
565 { "Fragment too long", "gss-api.segment.toolongfragment", FT_BOOLEAN
, BASE_NONE
,
566 NULL
, 0x0, "Fragment contained data past end of packet", HFILL
}},
567 { &hf_gssapi_segment_error
,
568 { "Defragmentation error", "gss-api.segment.error", FT_FRAMENUM
, BASE_NONE
,
569 NULL
, 0x0, "Defragmentation error due to illegal fragments", HFILL
}},
570 { &hf_gssapi_segment_count
,
571 { "Fragment count", "gss-api.segment.count", FT_UINT32
, BASE_DEC
,
572 NULL
, 0x0, NULL
, HFILL
}},
573 { &hf_gssapi_reassembled_in
,
574 { "Reassembled In", "gss-api.reassembled_in", FT_FRAMENUM
, BASE_NONE
,
575 NULL
, 0x0, "The frame where this pdu is reassembled", HFILL
}},
576 { &hf_gssapi_reassembled_length
,
577 { "Reassembled GSSAPI length", "gss-api.reassembled.length", FT_UINT32
, BASE_DEC
,
578 NULL
, 0x0, "The total length of the reassembled payload", HFILL
}},
581 static gint
*ett
[] = {
584 &ett_gssapi_segments
,
586 module_t
*gssapi_module
;
588 proto_gssapi
= proto_register_protocol(
589 "GSS-API Generic Security Service Application Program Interface",
590 "GSS-API", "gss-api");
592 gssapi_module
= prefs_register_protocol(proto_gssapi
, NULL
);
593 prefs_register_bool_preference(gssapi_module
, "gssapi_reassembly",
594 "Reassemble fragmented GSSAPI blobs",
595 "Whether or not to try reassembling GSSAPI blobs spanning multiple (SMB/SessionSetup) PDUs",
597 proto_register_field_array(proto_gssapi
, hf
, array_length(hf
));
598 proto_register_subtree_array(ett
, array_length(ett
));
600 register_dissector("gssapi", dissect_gssapi
, proto_gssapi
);
601 new_register_dissector("gssapi_verf", dissect_gssapi_verf
, proto_gssapi
);
603 gssapi_oids
= g_hash_table_new(gssapi_oid_hash
, gssapi_oid_equal
);
604 register_init_routine(gssapi_reassembly_init
);
608 wrap_dissect_gssapi(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
609 proto_tree
*tree
, dcerpc_info
*di _U_
, guint8
*drep _U_
)
613 auth_tvb
= tvb_new_subset_remaining(tvb
, offset
);
615 dissect_gssapi(auth_tvb
, pinfo
, tree
);
617 return tvb_length_remaining(tvb
, offset
);
621 wrap_dissect_gssapi_verf(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
622 proto_tree
*tree
, dcerpc_info
*di _U_
, guint8
*drep _U_
)
626 auth_tvb
= tvb_new_subset_remaining(tvb
, offset
);
628 return dissect_gssapi_verf(auth_tvb
, pinfo
, tree
, NULL
);
632 wrap_dissect_gssapi_payload(tvbuff_t
*data_tvb
, tvbuff_t
*auth_tvb
,
633 int offset _U_
, packet_info
*pinfo
,
634 dcerpc_auth_info
*auth_info _U_
)
638 /* we need a full auth and a full data tvb or else we cant
641 if((!auth_tvb
)||(!data_tvb
)){
645 pinfo
->decrypt_gssapi_tvb
=DECRYPT_GSSAPI_DCE
;
646 pinfo
->gssapi_wrap_tvb
=NULL
;
647 pinfo
->gssapi_encrypted_tvb
=data_tvb
;
648 pinfo
->gssapi_decrypted_tvb
=NULL
;
649 dissect_gssapi(auth_tvb
, pinfo
, NULL
);
650 result
=pinfo
->gssapi_decrypted_tvb
;
652 pinfo
->decrypt_gssapi_tvb
=0;
653 pinfo
->gssapi_wrap_tvb
=NULL
;
654 pinfo
->gssapi_encrypted_tvb
=NULL
;
655 pinfo
->gssapi_decrypted_tvb
=NULL
;
660 static dcerpc_auth_subdissector_fns gssapi_auth_fns
= {
661 wrap_dissect_gssapi
, /* Bind */
662 wrap_dissect_gssapi
, /* Bind ACK */
663 wrap_dissect_gssapi
, /* AUTH3 */
664 wrap_dissect_gssapi_verf
, /* Request verifier */
665 wrap_dissect_gssapi_verf
, /* Response verifier */
666 wrap_dissect_gssapi_payload
, /* Request data */
667 wrap_dissect_gssapi_payload
/* Response data */
671 proto_reg_handoff_gssapi(void)
673 dissector_handle_t gssapi_handle
;
675 ntlmssp_handle
= find_dissector("ntlmssp");
676 ntlmssp_payload_handle
= find_dissector("ntlmssp_payload");
677 ntlmssp_verf_handle
= find_dissector("ntlmssp_verf");
678 ntlmssp_data_only_handle
= find_dissector("ntlmssp_data_only");
679 spnego_krb5_wrap_handle
= find_dissector("spnego-krb5-wrap");
681 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_CONNECT
,
682 DCE_C_RPC_AUTHN_PROTOCOL_SPNEGO
,
684 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_INTEGRITY
,
685 DCE_C_RPC_AUTHN_PROTOCOL_SPNEGO
,
687 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_PRIVACY
,
688 DCE_C_RPC_AUTHN_PROTOCOL_SPNEGO
,
691 gssapi_handle
= find_dissector("gssapi");
692 dissector_add_string("dns.tsig.mac", "gss.microsoft.com", gssapi_handle
);