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
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * SPDX-License-Identifier: GPL-2.0-or-later
17 #include <epan/packet.h>
18 #include <epan/expert.h>
19 #include <epan/exceptions.h>
20 #include <epan/prefs.h>
21 #include <epan/reassemble.h>
22 #include <epan/show_exception.h>
23 #include <epan/proto_data.h>
25 #include "packet-ber.h"
26 #include "packet-dcerpc.h"
27 #include "packet-gssapi.h"
29 void proto_register_gssapi(void);
30 void proto_reg_handoff_gssapi(void);
32 static int proto_gssapi
;
34 static int hf_gssapi_token_object
;
35 static int hf_gssapi_auth_verifier
;
36 static int hf_gssapi_auth_credentials
;
37 static int hf_gssapi_oid
;
38 static int hf_gssapi_segments
;
39 static int hf_gssapi_segment
;
40 static int hf_gssapi_segment_overlap
;
41 static int hf_gssapi_segment_overlap_conflict
;
42 static int hf_gssapi_segment_multiple_tails
;
43 static int hf_gssapi_segment_too_long_fragment
;
44 static int hf_gssapi_segment_error
;
45 static int hf_gssapi_segment_count
;
46 static int hf_gssapi_reassembled_in
;
47 static int hf_gssapi_reassembled_length
;
49 static int ett_gssapi
;
50 static int ett_gssapi_segment
;
51 static int ett_gssapi_segments
;
53 static expert_field ei_gssapi_unknown_header
;
55 static bool gssapi_reassembly
= true;
57 static dissector_handle_t gssapi_handle
;
59 typedef struct _gssapi_conv_info_t
{
60 gssapi_oid_value
*oid
;
64 bool 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 */
69 typedef struct _gssapi_frag_info_t
{
71 uint32_t reassembled_in
;
74 static const fragment_items gssapi_frag_items
= {
80 &hf_gssapi_segment_overlap
,
81 &hf_gssapi_segment_overlap_conflict
,
82 &hf_gssapi_segment_multiple_tails
,
83 &hf_gssapi_segment_too_long_fragment
,
84 &hf_gssapi_segment_error
,
85 &hf_gssapi_segment_count
,
87 &hf_gssapi_reassembled_length
,
88 /* Reassembled data field */
94 static reassembly_table gssapi_reassembly_table
;
100 static dissector_handle_t ntlmssp_handle
;
101 static dissector_handle_t ntlmssp_payload_handle
;
102 static dissector_handle_t ntlmssp_verf_handle
;
103 static dissector_handle_t ntlmssp_data_only_handle
;
104 static dissector_handle_t spnego_krb5_wrap_handle
;
106 static GHashTable
*gssapi_oids
;
109 gssapi_oid_equal(const void *k1
, const void *k2
)
111 const char *key1
= (const char *)k1
;
112 const char *key2
= (const char *)k2
;
114 return strcmp(key1
, key2
) == 0;
118 gssapi_oid_hash(const void *k
)
120 const char *key
= (const char *)k
;
121 unsigned hash
= 0, i
;
123 for (i
= 0; key
[i
]; i
++)
130 gssapi_init_oid(const char *oid
, int proto
, int ett
, dissector_handle_t handle
,
131 dissector_handle_t wrap_handle
, const char *comment
)
133 char *key
= g_strdup(oid
);
134 gssapi_oid_value
*value
= (gssapi_oid_value
*)g_malloc(sizeof(*value
));
136 value
->proto
= find_protocol_by_id(proto
);
138 value
->handle
= handle
;
139 value
->wrap_handle
= wrap_handle
;
140 value
->comment
= comment
;
142 g_hash_table_insert(gssapi_oids
, key
, value
);
143 register_ber_oid_dissector_handle(key
, handle
, proto
, comment
);
147 * This takes an OID in text string form as
151 gssapi_lookup_oid_str(const char *oid_key
)
153 gssapi_oid_value
*value
;
157 value
= (gssapi_oid_value
*)g_hash_table_lookup(gssapi_oids
, oid_key
);
162 dissect_gssapi_work(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
163 bool is_verifier
, gssapi_encrypt_info_t
* encrypt_info
)
165 proto_item
*volatile item
;
166 proto_tree
*volatile subtree
;
167 volatile int return_offset
= 0;
168 gssapi_conv_info_t
*volatile gss_info
;
169 gssapi_oid_value
*oidvalue
;
170 dissector_handle_t handle
;
171 conversation_t
*conversation
;
173 int len
, start_offset
, oid_start_offset
;
180 fragment_head
*fd_head
=NULL
;
181 gssapi_frag_info_t
*fi
;
182 tvbuff_t
*volatile gss_tvb
=NULL
;
187 asn1_ctx_init(&asn1_ctx
, ASN1_ENC_BER
, true, pinfo
);
189 * We don't know whether the data is encrypted, so say it's
190 * not, for now. The subdissector must set gssapi_data_encrypted
193 encrypt_info
->gssapi_data_encrypted
= false;
197 * We need a conversation for later
199 conversation
= find_or_create_conversation(pinfo
);
201 gss_info
= (gssapi_conv_info_t
*)conversation_get_proto_data(conversation
, proto_gssapi
);
203 gss_info
= wmem_new(wmem_file_scope(), gssapi_conv_info_t
);
205 gss_info
->do_reassembly
=false;
206 gss_info
->frags
=wmem_tree_new(wmem_file_scope());
208 conversation_add_proto_data(conversation
, proto_gssapi
, gss_info
);
211 item
= proto_tree_add_item(
212 tree
, proto_gssapi
, tvb
, offset
, -1, ENC_NA
);
214 subtree
= proto_item_add_subtree(item
, ett_gssapi
);
217 * Catch the ReportedBoundsError exception; the stuff we've been
218 * handed doesn't necessarily run to the end of the packet, it's
219 * an item inside a packet, so if it happens to be malformed (or
220 * we, or a dissector we call, has a bug), so that an exception
221 * is thrown, we want to report the error, but return and let
222 * our caller dissect the rest of the packet.
224 * If it gets a BoundsError, we can stop, as there's nothing more
225 * in the packet after our blob to see, so we just re-throw the
232 /* First of all, if it's the first time we see this packet
233 * then check whether we are in the middle of reassembly or not
235 if( (!pinfo
->fd
->visited
)
236 && (gss_info
->do_reassembly
)
237 && (gssapi_reassembly
) ){
238 fi
=(gssapi_frag_info_t
*)wmem_tree_lookup32(gss_info
->frags
, gss_info
->first_frame
);
242 wmem_tree_insert32(gss_info
->frags
, pinfo
->num
, fi
);
243 fd_head
=fragment_add(&gssapi_reassembly_table
,
244 tvb
, 0, pinfo
, fi
->first_frame
, NULL
,
245 gss_info
->frag_offset
,
246 tvb_captured_length(tvb
), true);
247 gss_info
->frag_offset
+=tvb_captured_length(tvb
);
249 /* we need more fragments */
254 /* this blob is now fully reassembled */
255 gss_info
->do_reassembly
=false;
256 fi
->reassembled_in
=pinfo
->num
;
258 gss_tvb
=tvb_new_chain(tvb
, fd_head
->tvb_data
);
259 add_new_data_source(pinfo
, gss_tvb
, "Reassembled GSSAPI");
261 /* We have seen this packet before.
262 * Is this blob part of reassembly or a normal blob ?
264 if( (pinfo
->fd
->visited
)
265 && (gssapi_reassembly
) ){
266 fi
=(gssapi_frag_info_t
*)wmem_tree_lookup32(gss_info
->frags
, pinfo
->num
);
268 fd_head
=fragment_get(&gssapi_reassembly_table
,
269 pinfo
, fi
->first_frame
, NULL
);
270 if(fd_head
&& (fd_head
->flags
&FD_DEFRAGMENTED
)){
271 if(pinfo
->num
==fi
->reassembled_in
){
272 proto_item
*frag_tree_item
;
273 gss_tvb
=tvb_new_chain(tvb
, fd_head
->tvb_data
);
274 add_new_data_source(pinfo
, gss_tvb
, "Reassembled GSSAPI");
275 show_fragment_tree(fd_head
, &gssapi_frag_items
, tree
, pinfo
, tvb
, &frag_tree_item
);
278 it
=proto_tree_add_uint(tree
, hf_gssapi_reassembled_in
, tvb
, 0, 0, fi
->reassembled_in
);
279 proto_item_set_generated(it
);
287 offset
= get_ber_identifier(gss_tvb
, offset
, &appclass
, &pc
, &tag
);
288 offset
= get_ber_length(gss_tvb
, offset
, &len1
, &ind_field
);
291 if (!(appclass
== BER_CLASS_APP
&& pc
&& tag
== 0)) {
292 /* It could be NTLMSSP, with no OID. This can happen
293 for anything that microsoft calls 'Negotiate' or GSS-SPNEGO */
294 if ((tvb_captured_length_remaining(gss_tvb
, start_offset
)>7) && (tvb_strneql(gss_tvb
, start_offset
, "NTLMSSP", 7) == 0)) {
295 return_offset
= call_dissector(ntlmssp_handle
,
296 tvb_new_subset_remaining(gss_tvb
, start_offset
),
300 /* Maybe it's new NTLMSSP payload */
301 if ((tvb_captured_length_remaining(gss_tvb
, start_offset
)>16) &&
302 ((tvb_memeql(gss_tvb
, start_offset
, (const uint8_t*)"\x01\x00\x00\x00", 4) == 0))) {
303 return_offset
= call_dissector(ntlmssp_payload_handle
,
304 tvb_new_subset_remaining(gss_tvb
, start_offset
),
306 encrypt_info
->gssapi_data_encrypted
= true;
309 if ((tvb_captured_length_remaining(gss_tvb
, start_offset
)==16) &&
310 ((tvb_memeql(gss_tvb
, start_offset
, (const uint8_t*)"\x01\x00\x00\x00", 4) == 0))) {
312 return_offset
= call_dissector(ntlmssp_verf_handle
,
313 tvb_new_subset_remaining(gss_tvb
, start_offset
),
316 else if( encrypt_info
->gssapi_encrypted_tvb
) {
317 return_offset
= call_dissector_with_data(ntlmssp_data_only_handle
,
318 tvb_new_subset_remaining(encrypt_info
->gssapi_encrypted_tvb
, 0),
319 pinfo
, subtree
, &encrypt_info
->gssapi_decrypted_tvb
);
320 encrypt_info
->gssapi_data_encrypted
= true;
325 /* Maybe it's new GSSKRB5 CFX Wrapping */
326 if ((tvb_captured_length_remaining(gss_tvb
, start_offset
)>2) &&
327 ((tvb_memeql(gss_tvb
, start_offset
, (const uint8_t*)"\04\x04", 2) == 0) ||
328 (tvb_memeql(gss_tvb
, start_offset
, (const uint8_t*)"\05\x04", 2) == 0))) {
329 return_offset
= call_dissector_with_data(spnego_krb5_wrap_handle
,
330 tvb_new_subset_remaining(gss_tvb
, start_offset
),
331 pinfo
, subtree
, encrypt_info
);
336 * If we do not recognise an Application class,
337 * then we are probably dealing with an inner context
338 * token or a wrap token, and we should retrieve the
339 * gssapi_oid_value pointer from the per-frame data or,
340 * if there is no per-frame data (as would be the case
341 * the first time we dissect this frame), from the
342 * conversation that exists or that we created from
343 * pinfo (and then make it per-frame data).
344 * We need to make it per-frame data as there can be
345 * more than one GSS-API negotiation in a conversation.
347 * Note! We "cheat". Since we only need the pointer,
348 * we store that as the data. (That's not really
349 * "cheating" - the per-frame data and per-conversation
350 * data code doesn't care what you supply as a data
351 * pointer; it just treats it as an opaque pointer, it
352 * doesn't dereference it or free what it points to.)
354 oidvalue
= (gssapi_oid_value
*)p_get_proto_data(wmem_file_scope(), pinfo
, proto_gssapi
, 0);
355 if (!oidvalue
&& !pinfo
->fd
->visited
) {
356 /* No handle attached to this frame, but it's the first */
357 /* pass, so it'd be attached to the conversation. */
358 oidvalue
= gss_info
->oid
;
360 p_add_proto_data(wmem_file_scope(), pinfo
, proto_gssapi
, 0, gss_info
->oid
);
363 proto_tree_add_expert_format(subtree
, pinfo
, &ei_gssapi_unknown_header
, gss_tvb
, start_offset
, 0,
364 "Unknown header (class=%d, pc=%d, tag=%d)",
366 return_offset
= tvb_captured_length(gss_tvb
);
369 tvbuff_t
*oid_tvb_local
;
372 handle
= oidvalue
->wrap_handle
;
373 if (handle
!= NULL
) {
374 oid_tvb_local
= tvb_new_subset_remaining(gss_tvb
, start_offset
);
375 len
= call_dissector_with_data(handle
, oid_tvb_local
, pinfo
, subtree
, encrypt_info
);
377 return_offset
= tvb_captured_length(gss_tvb
);
379 return_offset
= start_offset
+ len
;
381 proto_tree_add_item(subtree
, hf_gssapi_auth_verifier
, gss_tvb
, offset
, -1, ENC_NA
);
382 return_offset
= tvb_captured_length(gss_tvb
);
385 handle
= oidvalue
->handle
;
386 if (handle
!= NULL
) {
387 oid_tvb_local
= tvb_new_subset_remaining(gss_tvb
, start_offset
);
388 len
= call_dissector_with_data(handle
, oid_tvb_local
, pinfo
, subtree
, encrypt_info
);
390 return_offset
= tvb_captured_length(gss_tvb
);
392 return_offset
= start_offset
+ len
;
394 proto_tree_add_item(subtree
, hf_gssapi_auth_credentials
, gss_tvb
, offset
, -1, ENC_NA
);
395 return_offset
= tvb_captured_length(gss_tvb
);
399 goto done
; /* We are finished here */
404 oid_start_offset
=offset
;
405 offset
=dissect_ber_object_identifier_str(false, &asn1_ctx
, subtree
, gss_tvb
, offset
, hf_gssapi_oid
, &oid
);
406 oidvalue
= gssapi_lookup_oid_str(oid
);
409 /* Check if we need reassembly of this blob.
410 * Only try reassembly for OIDs we recognize
411 * and when we have the entire tvb
413 * SMB will sometimes split one large GSSAPI blob
414 * across multiple SMB/SessionSetup commands.
415 * While we should look at the uid returned in the response
416 * to the first SessionSetup and use that as a key
417 * instead for simplicity we assume there will not be several
418 * such authentication at once on a single tcp session
420 if( (!pinfo
->fd
->visited
)
422 && (tvb_captured_length(gss_tvb
)==tvb_reported_length(gss_tvb
))
423 && (len1
>(uint32_t)tvb_captured_length_remaining(gss_tvb
, oid_start_offset
))
424 && (gssapi_reassembly
) ){
425 fi
=wmem_new(wmem_file_scope(), gssapi_frag_info_t
);
426 fi
->first_frame
=pinfo
->num
;
427 fi
->reassembled_in
=0;
428 wmem_tree_insert32(gss_info
->frags
, pinfo
->num
, fi
);
430 fragment_add(&gssapi_reassembly_table
,
431 gss_tvb
, 0, pinfo
, pinfo
->num
, NULL
,
432 0, tvb_captured_length(gss_tvb
), true);
433 fragment_set_tot_len(&gssapi_reassembly_table
,
434 pinfo
, pinfo
->num
, NULL
, len1
+oid_start_offset
);
436 gss_info
->do_reassembly
=true;
437 gss_info
->first_frame
=pinfo
->num
;
438 gss_info
->frag_offset
=tvb_captured_length(gss_tvb
);
444 * Hand off to subdissector.
447 if ((oidvalue
== NULL
) || !proto_is_protocol_enabled(oidvalue
->proto
)) {
448 /* No dissector for this oid */
449 proto_tree_add_item(subtree
, hf_gssapi_token_object
, gss_tvb
, oid_start_offset
, -1, ENC_NA
);
451 return_offset
= tvb_captured_length(gss_tvb
);
455 /* Save a pointer to the data for the OID for the
456 * GSSAPI protocol for this conversation.
460 * Now add the proto data ...
461 * but only if it is not already there.
464 gss_info
->oid
=oidvalue
;
468 handle
= oidvalue
->wrap_handle
;
469 if (handle
!= NULL
) {
470 oid_tvb
= tvb_new_subset_remaining(gss_tvb
, offset
);
471 len
= call_dissector_with_data(handle
, oid_tvb
, pinfo
, subtree
, encrypt_info
);
473 return_offset
= tvb_captured_length(gss_tvb
);
475 return_offset
= offset
+ len
;
477 proto_tree_add_item(subtree
, hf_gssapi_auth_verifier
, gss_tvb
, offset
, -1, ENC_NA
);
478 return_offset
= tvb_captured_length(gss_tvb
);
481 handle
= oidvalue
->handle
;
482 if (handle
!= NULL
) {
483 oid_tvb
= tvb_new_subset_remaining(gss_tvb
, offset
);
484 len
= call_dissector_with_data(handle
, oid_tvb
, pinfo
, subtree
, encrypt_info
);
486 return_offset
= tvb_captured_length(gss_tvb
);
488 return_offset
= offset
+ len
;
490 proto_tree_add_item(subtree
, hf_gssapi_auth_credentials
, gss_tvb
, offset
, -1, ENC_NA
);
491 return_offset
= tvb_captured_length(gss_tvb
);
497 } CATCH_NONFATAL_ERRORS
{
499 * Somebody threw an exception that means that there
500 * was a problem dissecting the payload; that means
501 * that a dissector was found, so we don't need to
502 * dissect the payload as data or update the protocol
505 * Just show the exception and then drive on to show
506 * the trailer, after noting that a dissector was found
507 * and restoring the protocol value that was in effect
508 * before we called the subdissector.
510 show_exception(gss_tvb
, pinfo
, tree
, EXCEPT_CODE
, GET_MESSAGE
);
513 proto_item_set_len(item
, return_offset
);
514 return return_offset
;
518 dissect_gssapi_work_wrapper(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, gssapi_encrypt_info_t
* encrypt_info
, bool is_verifier
)
521 gssapi_encrypt_info_t pass_encrypt_info
;
523 /* Ensure a non-null encryption structure */
524 if (encrypt_info
!= NULL
)
526 pass_encrypt_info
= *encrypt_info
;
530 memset(&pass_encrypt_info
, 0, sizeof(pass_encrypt_info
));
533 ret
= dissect_gssapi_work(tvb
, pinfo
, tree
, is_verifier
, &pass_encrypt_info
);
535 /* Restore any changes to provided encryption structure */
536 if (encrypt_info
!= NULL
)
538 *encrypt_info
= pass_encrypt_info
;
545 dissect_gssapi(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
547 return dissect_gssapi_work_wrapper(tvb
, pinfo
, tree
, (gssapi_encrypt_info_t
*)data
, false);
551 dissect_gssapi_verf(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
553 return dissect_gssapi_work_wrapper(tvb
, pinfo
, tree
, (gssapi_encrypt_info_t
*)data
, true);
557 gssapi_shutdown(void)
559 g_hash_table_destroy(gssapi_oids
);
563 proto_register_gssapi(void)
565 static hf_register_info hf
[] = {
567 { "OID", "gss-api.OID", FT_STRING
, BASE_NONE
,
568 NULL
, 0, "This is a GSS-API Object Identifier", HFILL
}},
569 { &hf_gssapi_token_object
,
570 { "Token object", "gss-api.token_object", FT_BYTES
, BASE_NONE
,
571 NULL
, 0, NULL
, HFILL
}},
572 { &hf_gssapi_auth_verifier
,
573 { "Authentication verifier", "gss-api.auth_verifier", FT_BYTES
, BASE_NONE
,
574 NULL
, 0, NULL
, HFILL
}},
575 { &hf_gssapi_auth_credentials
,
576 { "Authentication credentials", "gss-api.auth_credentials", FT_BYTES
, BASE_NONE
,
577 NULL
, 0, NULL
, HFILL
}},
578 { &hf_gssapi_segment
,
579 { "GSSAPI Segment", "gss-api.segment", FT_FRAMENUM
, BASE_NONE
,
580 NULL
, 0x0, NULL
, HFILL
}},
581 { &hf_gssapi_segments
,
582 { "GSSAPI Segments", "gss-api.segment.segments", FT_NONE
, BASE_NONE
,
583 NULL
, 0x0, NULL
, HFILL
}},
584 { &hf_gssapi_segment_overlap
,
585 { "Fragment overlap", "gss-api.segment.overlap", FT_BOOLEAN
, BASE_NONE
,
586 NULL
, 0x0, "Fragment overlaps with other fragments", HFILL
}},
587 { &hf_gssapi_segment_overlap_conflict
,
588 { "Conflicting data in fragment overlap", "gss-api.segment.overlap.conflict", FT_BOOLEAN
, BASE_NONE
,
589 NULL
, 0x0, "Overlapping fragments contained conflicting data", HFILL
}},
590 { &hf_gssapi_segment_multiple_tails
,
591 { "Multiple tail fragments found", "gss-api.segment.multipletails", FT_BOOLEAN
, BASE_NONE
,
592 NULL
, 0x0, "Several tails were found when defragmenting the packet", HFILL
}},
593 { &hf_gssapi_segment_too_long_fragment
,
594 { "Fragment too long", "gss-api.segment.toolongfragment", FT_BOOLEAN
, BASE_NONE
,
595 NULL
, 0x0, "Fragment contained data past end of packet", HFILL
}},
596 { &hf_gssapi_segment_error
,
597 { "Defragmentation error", "gss-api.segment.error", FT_FRAMENUM
, BASE_NONE
,
598 NULL
, 0x0, "Defragmentation error due to illegal fragments", HFILL
}},
599 { &hf_gssapi_segment_count
,
600 { "Fragment count", "gss-api.segment.count", FT_UINT32
, BASE_DEC
,
601 NULL
, 0x0, NULL
, HFILL
}},
602 { &hf_gssapi_reassembled_in
,
603 { "Reassembled In", "gss-api.reassembled_in", FT_FRAMENUM
, BASE_NONE
,
604 NULL
, 0x0, "The frame where this pdu is reassembled", HFILL
}},
605 { &hf_gssapi_reassembled_length
,
606 { "Reassembled GSSAPI length", "gss-api.reassembled.length", FT_UINT32
, BASE_DEC
,
607 NULL
, 0x0, "The total length of the reassembled payload", HFILL
}},
610 static int *ett
[] = {
613 &ett_gssapi_segments
,
616 static ei_register_info ei
[] = {
617 { &ei_gssapi_unknown_header
, { "gssapi.unknown_header", PI_PROTOCOL
, PI_WARN
, "Unknown header", EXPFILL
}},
620 module_t
*gssapi_module
;
621 expert_module_t
*expert_gssapi
;
623 proto_gssapi
= proto_register_protocol("GSS-API Generic Security Service Application Program Interface", "GSS-API", "gss-api");
625 gssapi_module
= prefs_register_protocol(proto_gssapi
, NULL
);
626 prefs_register_bool_preference(gssapi_module
, "gssapi_reassembly",
627 "Reassemble fragmented GSSAPI blobs",
628 "Whether or not to try reassembling GSSAPI blobs spanning multiple (SMB/SessionSetup) PDUs",
630 proto_register_field_array(proto_gssapi
, hf
, array_length(hf
));
631 proto_register_subtree_array(ett
, array_length(ett
));
632 expert_gssapi
= expert_register_protocol(proto_gssapi
);
633 expert_register_field_array(expert_gssapi
, ei
, array_length(ei
));
635 gssapi_handle
= register_dissector("gssapi", dissect_gssapi
, proto_gssapi
);
636 register_dissector("gssapi_verf", dissect_gssapi_verf
, proto_gssapi
);
638 gssapi_oids
= g_hash_table_new_full(gssapi_oid_hash
, gssapi_oid_equal
, g_free
, g_free
);
640 reassembly_table_register(&gssapi_reassembly_table
,
641 &addresses_reassembly_table_functions
);
643 register_shutdown_routine(gssapi_shutdown
);
647 wrap_dissect_gssapi(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
648 proto_tree
*tree
, dcerpc_info
*di _U_
, uint8_t *drep _U_
)
652 auth_tvb
= tvb_new_subset_remaining(tvb
, offset
);
654 dissect_gssapi(auth_tvb
, pinfo
, tree
, NULL
);
656 return tvb_captured_length_remaining(tvb
, offset
);
660 wrap_dissect_gssapi_verf(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
,
661 proto_tree
*tree
, dcerpc_info
*di _U_
, uint8_t *drep _U_
)
665 auth_tvb
= tvb_new_subset_remaining(tvb
, offset
);
667 return dissect_gssapi_verf(auth_tvb
, pinfo
, tree
, NULL
);
671 wrap_dissect_gssapi_payload(tvbuff_t
*header_tvb
,
672 tvbuff_t
*payload_tvb
,
673 tvbuff_t
*trailer_tvb
,
676 dcerpc_auth_info
*auth_info
)
679 gssapi_encrypt_info_t gssapi_encrypt
;
681 memset(&gssapi_encrypt
, 0x0, sizeof(gssapi_encrypt_info_t
));
683 /* we need a full auth and a full data tvb or else we can't
686 if((!auth_tvb
)||(!payload_tvb
)){
690 if (!auth_info
->hdr_signing
) {
695 gssapi_encrypt
.decrypt_gssapi_tvb
=DECRYPT_GSSAPI_DCE
;
696 gssapi_encrypt
.gssapi_header_tvb
=header_tvb
;
697 gssapi_encrypt
.gssapi_encrypted_tvb
=payload_tvb
;
698 gssapi_encrypt
.gssapi_trailer_tvb
=trailer_tvb
;
700 dissect_gssapi(auth_tvb
, pinfo
, NULL
, &gssapi_encrypt
);
701 auth_info
->session_key
= gssapi_encrypt
.used_decryption_key
;
702 result
=gssapi_encrypt
.gssapi_decrypted_tvb
;
707 static dcerpc_auth_subdissector_fns gssapi_auth_fns
= {
708 wrap_dissect_gssapi
, /* Bind */
709 wrap_dissect_gssapi
, /* Bind ACK */
710 wrap_dissect_gssapi
, /* AUTH3 */
711 wrap_dissect_gssapi_verf
, /* Request verifier */
712 wrap_dissect_gssapi_verf
, /* Response verifier */
713 wrap_dissect_gssapi_payload
, /* Request data */
714 wrap_dissect_gssapi_payload
/* Response data */
718 proto_reg_handoff_gssapi(void)
720 ntlmssp_handle
= find_dissector_add_dependency("ntlmssp", proto_gssapi
);
721 ntlmssp_payload_handle
= find_dissector_add_dependency("ntlmssp_payload", proto_gssapi
);
722 ntlmssp_verf_handle
= find_dissector_add_dependency("ntlmssp_verf", proto_gssapi
);
723 ntlmssp_data_only_handle
= find_dissector_add_dependency("ntlmssp_data_only", proto_gssapi
);
724 spnego_krb5_wrap_handle
= find_dissector_add_dependency("spnego-krb5-wrap", proto_gssapi
);
726 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_CONNECT
,
727 DCE_C_RPC_AUTHN_PROTOCOL_SPNEGO
,
729 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_INTEGRITY
,
730 DCE_C_RPC_AUTHN_PROTOCOL_SPNEGO
,
732 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_PRIVACY
,
733 DCE_C_RPC_AUTHN_PROTOCOL_SPNEGO
,
736 dissector_add_string("dns.tsig.mac", "gss.microsoft.com", gssapi_handle
);
737 dissector_add_string("dns.tsig.mac", "gss-tsig", gssapi_handle
);
741 * Editor modelines - https://www.wireshark.org/tools/modelines.html
746 * indent-tabs-mode: t
749 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
750 * :indentSize=8:tabSize=8:noTabs=false: