HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / dissectors / packet-gssapi.c
blob9513fdf026b47d5777a3d7c5ba002aaee27065d9
1 /* packet-gssapi.c
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
5 * bits and pieces ...
7 * $Id$
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.
28 #include "config.h"
30 #include <string.h>
32 #include <glib.h>
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;
71 wmem_tree_t *frags;
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 */
74 int first_frame;
75 int frag_offset;
76 } gssapi_conv_info_t;
78 typedef struct _gssapi_frag_info_t {
79 guint32 first_frame;
80 guint32 reassembled_in;
81 } gssapi_frag_info_t;
83 static const fragment_items gssapi_frag_items = {
84 &ett_gssapi_segment,
85 &ett_gssapi_segments,
87 &hf_gssapi_segments,
88 &hf_gssapi_segment,
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,
95 NULL,
96 &hf_gssapi_reassembled_length,
97 /* Reassembled data field */
98 NULL,
99 "fragments"
103 static reassembly_table gssapi_reassembly_table;
105 static void
106 gssapi_reassembly_init(void)
108 reassembly_table_init(&gssapi_reassembly_table,
109 &addresses_reassembly_table_functions);
113 * Subdissectors
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;
124 static gint
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;
133 static guint
134 gssapi_oid_hash(gconstpointer k)
136 const char *key = (const char *)k;
137 guint hash = 0, i;
139 for (i = 0; key[i]; i++)
140 hash += key[i];
142 return hash;
145 void
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);
153 value->ett = ett;
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
164 * an argument.
166 gssapi_oid_value *
167 gssapi_lookup_oid_str(const char *oid_key)
169 gssapi_oid_value *value;
170 if(!oid_key){
171 return NULL;
173 value = (gssapi_oid_value *)g_hash_table_lookup(gssapi_oids, oid_key);
174 return value;
177 static int
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;
188 tvbuff_t *oid_tvb;
189 int len, start_offset, oid_start_offset;
190 volatile int offset;
191 gint8 appclass;
192 gboolean pc, ind_field;
193 gint32 tag;
194 guint32 len1;
195 const char *oid;
196 fragment_head *fd_head=NULL;
197 gssapi_frag_info_t *fi;
198 tvbuff_t *volatile gss_tvb=NULL;
199 asn1_ctx_t asn1_ctx;
200 void *pd_save;
202 start_offset=0;
203 offset=0;
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
208 * if it is.
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);
219 if (!gss_info) {
220 gss_info = wmem_new(wmem_file_scope(), gssapi_conv_info_t);
221 gss_info->oid=NULL;
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
243 * exception.
245 pd_save = pinfo->private_data;
246 TRY {
247 gss_tvb=tvb;
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);
257 if(!fi){
258 goto done;
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 */
268 if(!fd_head){
269 goto done;
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);
285 if(fi){
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);
294 } else {
295 proto_item *it;
296 it=proto_tree_add_uint(tree, hf_gssapi_reassembled_in, tvb, 0, 0, fi->reassembled_in);
297 PROTO_ITEM_SET_GENERATED(it);
298 goto done;
304 /* Read header */
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),
315 pinfo, subtree);
316 goto done;
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),
323 pinfo, subtree);
324 pinfo->gssapi_data_encrypted = TRUE;
325 goto done;
327 if ((tvb_length_remaining(gss_tvb, start_offset)==16) &&
328 ((tvb_memeql(gss_tvb, start_offset, "\x01\x00\x00\x00", 4) == 0))) {
329 if( is_verifier ) {
330 return_offset = call_dissector(ntlmssp_verf_handle,
331 tvb_new_subset_remaining(gss_tvb, start_offset),
332 pinfo, subtree);
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),
337 pinfo, subtree);
338 pinfo->gssapi_data_encrypted = TRUE;
340 goto done;
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),
349 pinfo, subtree);
350 goto done;
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;
378 if (gss_info->oid)
379 p_add_proto_data(pinfo->fd, proto_gssapi, 0, gss_info->oid);
381 if (!oidvalue)
383 proto_tree_add_text(subtree, gss_tvb, start_offset, 0,
384 "Unknown header (class=%d, pc=%d, tag=%d)",
385 appclass, pc, tag);
386 return_offset = tvb_length(gss_tvb);
387 goto done;
388 } else {
389 tvbuff_t *oid_tvb_local;
391 oid_tvb_local = tvb_new_subset_remaining(gss_tvb, start_offset);
392 if (is_verifier)
393 handle = oidvalue->wrap_handle;
394 else
395 handle = oidvalue->handle;
396 len = call_dissector(handle, oid_tvb_local, pinfo, subtree);
397 if (len == 0)
398 return_offset = tvb_length(gss_tvb);
399 else
400 return_offset = start_offset + len;
401 goto done; /* We are finished here */
405 /* Read oid */
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)
423 && (oidvalue)
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);
441 goto done;
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,
453 "Token object");
455 return_offset = tvb_length(gss_tvb);
456 goto done;
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.
467 if(!gss_info->oid){
468 gss_info->oid=oidvalue;
471 if (is_verifier) {
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,
476 subtree);
477 if (len == 0)
478 return_offset = tvb_length(gss_tvb);
479 else
480 return_offset = offset + len;
481 } else {
482 proto_tree_add_text(subtree, gss_tvb, offset, -1,
483 "Authentication verifier");
484 return_offset = tvb_length(gss_tvb);
486 } else {
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,
491 subtree);
492 if (len == 0)
493 return_offset = tvb_length(gss_tvb);
494 else
495 return_offset = offset + len;
496 } else {
497 proto_tree_add_text(subtree, gss_tvb, offset, -1,
498 "Authentication credentials");
499 return_offset = tvb_length(gss_tvb);
503 done:
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
511 * or info columns.
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);
524 } ENDTRY;
526 proto_item_set_len(item, return_offset);
527 return return_offset;
530 static void
531 dissect_gssapi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
533 dissect_gssapi_work(tvb, pinfo, tree, FALSE);
536 static int
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);
542 void
543 proto_register_gssapi(void)
545 static hf_register_info hf[] = {
546 { &hf_gssapi_oid,
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[] = {
582 &ett_gssapi,
583 &ett_gssapi_segment,
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",
596 &gssapi_reassembly);
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);
607 static int
608 wrap_dissect_gssapi(tvbuff_t *tvb, int offset, packet_info *pinfo,
609 proto_tree *tree, dcerpc_info *di _U_, guint8 *drep _U_)
611 tvbuff_t *auth_tvb;
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_)
624 tvbuff_t *auth_tvb;
626 auth_tvb = tvb_new_subset_remaining(tvb, offset);
628 return dissect_gssapi_verf(auth_tvb, pinfo, tree, NULL);
631 tvbuff_t *
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_)
636 tvbuff_t *result;
638 /* we need a full auth and a full data tvb or else we cant
639 decrypt anything
641 if((!auth_tvb)||(!data_tvb)){
642 return NULL;
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;
657 return result;
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 */
670 void
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,
683 &gssapi_auth_fns);
684 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_INTEGRITY,
685 DCE_C_RPC_AUTHN_PROTOCOL_SPNEGO,
686 &gssapi_auth_fns);
687 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_PRIVACY,
688 DCE_C_RPC_AUTHN_PROTOCOL_SPNEGO,
689 &gssapi_auth_fns);
691 gssapi_handle = find_dissector("gssapi");
692 dissector_add_string("dns.tsig.mac", "gss.microsoft.com", gssapi_handle);