Fixup: tvb_get_string(z) -> tvb_get_string(z)_enc
[metze/wireshark/wip.git] / epan / dissectors / packet-negoex.c
1 /* packet-negoex.c
2  * Dissect the NEGOEX security protocol
3  * as described here: http://tools.ietf.org/id/draft-zhu-negoex-04.txt
4  * Copyright 2012 Richard Sharpe <realrichardsharpe@gmail.com>
5  * Routines for SPNEGO Extended Negotiation Security Mechanism
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  */
25
26 #include "config.h"
27
28 #include <glib.h>
29 #include <epan/packet.h>
30 #include <epan/exceptions.h>
31 #include <epan/show_exception.h>
32
33 #include "packet-dcerpc.h"
34 #include "packet-gssapi.h"
35
36 void proto_register_negoex(void);
37 void proto_reg_handoff_negoex(void);
38
39 static int proto_negoex = -1;
40 static int hf_negoex_sig = -1;
41 static int hf_negoex_message_type = -1;
42 static int hf_negoex_sequence_num = -1;
43 static int hf_negoex_header_len = -1;
44 static int hf_negoex_message_len = -1;
45 static int hf_negoex_conversation_id = -1;
46 static int hf_negoex_random = -1;
47 static int hf_negoex_proto_version = -1;
48 static int hf_negoex_authscheme = -1;
49 static int hf_negoex_authscheme_vector_offset = -1;
50 static int hf_negoex_authscheme_vector_count = -1;
51 static int hf_negoex_authscheme_vector_pad = -1;
52 static int hf_negoex_extension = -1;
53 static int hf_negoex_extension_vector_offset = -1;
54 static int hf_negoex_extension_vector_count = -1;
55 static int hf_negoex_extension_vector_pad = -1;
56 static int hf_negoex_exchange_vector_offset = -1;
57 static int hf_negoex_exchange_vector_count = -1;
58 static int hf_negoex_exchange_vector_pad = -1;
59 static int hf_negoex_exchange = -1;
60 static int hf_negoex_checksum_scheme = -1;
61 static int hf_negoex_checksum_type = -1;
62 static int hf_negoex_checksum_vector_offset = -1;
63 static int hf_negoex_checksum_vector_count = -1;
64 static int hf_negoex_checksum_vector_pad = -1;
65 static int hf_negoex_checksum = -1;
66 static int hf_negoex_errorcode = -1;
67
68 static gint ett_negoex = -1;
69 static gint ett_negoex_msg = -1;
70 static gint ett_negoex_hdr = -1;
71 static gint ett_negoex_authscheme_vector = -1;
72 static gint ett_negoex_extension_vector = -1;
73 static gint ett_negoex_exchange = -1;
74 static gint ett_negoex_checksum = -1;
75 static gint ett_negoex_checksum_vector = -1;
76 static gint ett_negoex_byte_vector = -1;
77
78 /* If you add more message types, add them in sequence and update MAX_MSG */
79 #define MESSAGE_TYPE_INITIATOR_NEGO      0
80 #define MESSAGE_TYPE_ACCEPTOR_NEGO       1
81 #define MESSAGE_TYPE_INITIATOR_META_DATA 2
82 #define MESSAGE_TYPE_ACCEPTOR_META_DATA  3
83 #define MESSAGE_TYPE_CHALLENGE           4
84 #define MESSAGE_TYPE_AP_REQUEST          5
85 #define MESSAGE_TYPE_VERIFY              6
86 #define MESSAGE_TYPE_ALERT               7
87 #define MESSAGE_TYPE_MAX_MSG             MESSAGE_TYPE_ALERT
88
89 static const value_string negoex_message_types[] = {
90   {MESSAGE_TYPE_INITIATOR_NEGO,      "INITATOR_NEGO"},
91   {MESSAGE_TYPE_ACCEPTOR_NEGO,       "ACCEPTOR_NEGO"},
92   {MESSAGE_TYPE_INITIATOR_META_DATA, "INITIATOR_META_DATA"},
93   {MESSAGE_TYPE_ACCEPTOR_META_DATA,  "ACCEPTOR_META_DATA"},
94   {MESSAGE_TYPE_CHALLENGE,           "CHALLENGE"},
95   {MESSAGE_TYPE_AP_REQUEST,          "AP_REQUEST"},
96   {MESSAGE_TYPE_VERIFY,              "VERIFY"},
97   {MESSAGE_TYPE_ALERT,               "ALERT"},
98   {0, NULL}
99 };
100
101 static const value_string checksum_schemes[] = {
102   {1, "rfc3961"},
103   {0, NULL}
104 };
105
106 #if 0
107 static const value_string alert_types[] = {
108   {1, "ALERT_TYPE_PULSE"},
109   {0, NULL}
110 };
111
112 static const value_string alert_reasons[] = {
113   {1, "ALERT_VERIFY_NO_KEY"},
114   {0, NULL}
115 };
116 #endif
117
118 static void
119 dissect_negoex_alert_message(tvbuff_t *tvb,
120                              packet_info *pinfo _U_,
121                              proto_tree *tree,
122                              guint32 start_off)
123 {
124   guint32 offset;
125
126   offset = start_off;
127
128   /* AuthScheme */
129   proto_tree_add_item(tree, hf_negoex_authscheme, tvb, offset, 16, ENC_LITTLE_ENDIAN);
130   offset += 16;
131
132   /* ErrorCode, an NTSTATUS :-) */
133   proto_tree_add_item(tree, hf_negoex_errorcode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
134   offset += 4;
135
136   /* The rest */
137   proto_tree_add_text(tree, tvb, offset, tvb_length(tvb) - offset,
138                       "The rest of the alert message");
139
140 }
141
142 static void
143 dissect_negoex_verify_message(tvbuff_t *tvb,
144                               packet_info *pinfo _U_,
145                               proto_tree *tree,
146                               guint32 start_off)
147 {
148   guint32 offset;
149   guint32 checksum_vector_offset;
150   guint32 checksum_vector_count;
151   proto_item *pi;
152   proto_tree *checksum;
153   proto_item *pi_chk;
154   proto_tree *checksum_vector;
155
156   offset = start_off;
157
158   /* AuthScheme */
159   proto_tree_add_item(tree, hf_negoex_authscheme, tvb, offset, 16, ENC_LITTLE_ENDIAN);
160   offset += 16;
161
162   /* Checksum */
163   pi = proto_tree_add_text(tree, tvb, offset, 20, "Checksum");
164   checksum = proto_item_add_subtree(pi, ett_negoex_checksum);
165
166   /* cbHeaderLength */
167   proto_tree_add_item(checksum, hf_negoex_header_len, tvb, offset, 4, ENC_LITTLE_ENDIAN);
168   offset += 4;
169
170   /* ChecksumScheme */
171   proto_tree_add_item(checksum, hf_negoex_checksum_scheme, tvb, offset, 4, ENC_LITTLE_ENDIAN);
172   offset += 4;
173
174   /* ChecksumType */
175   proto_tree_add_item(checksum, hf_negoex_checksum_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
176   offset += 4;
177
178   /* Checksum Byte Vector */
179   checksum_vector_offset = tvb_get_letohl(tvb, offset);
180   checksum_vector_count = tvb_get_letohs(tvb, offset + 4);
181
182   pi_chk = proto_tree_add_text(checksum, tvb, offset, 8,
183                                "Checksum Vector: %u at %u",
184                                checksum_vector_count,
185                                checksum_vector_offset);
186   checksum_vector = proto_item_add_subtree(pi_chk, ett_negoex_checksum_vector);
187
188   proto_tree_add_item(checksum_vector, hf_negoex_checksum_vector_offset, tvb,
189                       offset, 4, ENC_LITTLE_ENDIAN);
190   offset += 4;
191
192   proto_tree_add_item(checksum_vector, hf_negoex_checksum_vector_count, tvb,
193                       offset, 2, ENC_LITTLE_ENDIAN);
194   offset += 2;
195
196   proto_tree_add_item(checksum_vector, hf_negoex_checksum_vector_pad, tvb,
197                       offset, 2, ENC_NA);
198   /*offset += 2;*/
199
200   proto_tree_add_item(checksum_vector, hf_negoex_checksum, tvb,
201                       checksum_vector_offset, checksum_vector_count, ENC_NA);
202
203 }
204
205 static void
206 dissect_negoex_exchange_message(tvbuff_t *tvb,
207                                 packet_info *pinfo _U_,
208                                 proto_tree *tree,
209                                 guint32 start_off)
210 {
211   guint32 offset;
212   guint32 exchange_vector_offset;
213   guint32 exchange_vector_count;
214   proto_item *pi;
215   proto_tree *exchange_vector;
216
217   offset = start_off;
218
219   /* AuthScheme */
220   proto_tree_add_item(tree, hf_negoex_authscheme, tvb, offset, 16, ENC_LITTLE_ENDIAN);
221   offset += 16;
222
223   /* Exchange Byte Vector */
224   exchange_vector_offset = tvb_get_letohl(tvb, offset);
225   exchange_vector_count = tvb_get_letohs(tvb, offset + 4);
226
227   pi = proto_tree_add_text(tree, tvb, offset, 8, "Exchange: %u bytes at %u",
228                            exchange_vector_count, exchange_vector_offset);
229   exchange_vector = proto_item_add_subtree(pi, ett_negoex_exchange);
230
231   proto_tree_add_item(exchange_vector, hf_negoex_exchange_vector_offset, tvb,
232                       offset, 4, ENC_LITTLE_ENDIAN);
233   offset += 4;
234
235   proto_tree_add_item(exchange_vector, hf_negoex_exchange_vector_count, tvb,
236                       offset, 2, ENC_LITTLE_ENDIAN);
237   offset += 2;
238
239   proto_tree_add_item(exchange_vector, hf_negoex_exchange_vector_pad, tvb,
240                       offset, 2, ENC_NA);
241   /*offset += 2;*/
242
243   proto_tree_add_item(exchange_vector, hf_negoex_exchange, tvb,
244                       exchange_vector_offset, exchange_vector_count, ENC_NA);
245 }
246
247 /*
248  * In each of the subdissectors we are handed the whole message, but the
249  * header is already dissected. The offset tells us where in the buffer the
250  * actual data starts. This is a bit redundant, but it allows for changes
251  * to the header structure ...
252  *
253  * Eventually we want to treat the header and body differently perhaps.
254  */
255 static void
256 dissect_negoex_nego_message(tvbuff_t *tvb,
257                             packet_info *pinfo _U_,
258                             proto_tree *tree,
259                             guint32 start_off)
260 {
261   volatile guint32 offset;
262   guint32 authscheme_vector_offset;
263   guint16 authscheme_vector_count;
264   guint32 extension_vector_offset;
265   guint32 extension_vector_count;
266   proto_item *pi, *ext_pi;
267   proto_tree *authscheme_vector;
268   proto_tree *extension_vector;
269   guint32 i;
270
271   offset = start_off;
272
273   TRY {
274     /* The Random field */
275     proto_tree_add_item(tree, hf_negoex_random, tvb, offset, 32, ENC_ASCII);
276     offset += 32;
277
278     /* Protocol version */
279     proto_tree_add_item(tree, hf_negoex_proto_version, tvb, offset, 8, ENC_LITTLE_ENDIAN);
280     offset += 8;
281
282     /* AuthScheme offset and count */
283     authscheme_vector_offset = tvb_get_letohl(tvb, offset);
284     authscheme_vector_count = tvb_get_letohs(tvb, offset + 4);
285
286     pi = proto_tree_add_text(tree, tvb, offset, 8, "AuthSchemes: %u at %u",
287                              authscheme_vector_count, authscheme_vector_offset);
288     authscheme_vector = proto_item_add_subtree(pi, ett_negoex_authscheme_vector);
289     proto_tree_add_item(authscheme_vector, hf_negoex_authscheme_vector_offset,
290                         tvb, offset, 4, ENC_LITTLE_ENDIAN);
291     offset += 4;
292
293     proto_tree_add_item(authscheme_vector, hf_negoex_authscheme_vector_count,
294                         tvb, offset, 2, ENC_LITTLE_ENDIAN);
295     offset += 2;
296
297     proto_tree_add_item(authscheme_vector, hf_negoex_authscheme_vector_pad,
298                         tvb, offset, 2, ENC_NA);
299     offset += 2;
300
301     /* Now, add the various items */
302     for (i = 0; i < authscheme_vector_count; i++) {
303       proto_tree_add_item(authscheme_vector, hf_negoex_authscheme, tvb,
304                           authscheme_vector_offset + i * 16, 16, ENC_LITTLE_ENDIAN);
305     }
306
307     extension_vector_offset = tvb_get_letohl(tvb, offset);
308     extension_vector_count = tvb_get_letohs(tvb, offset + 4);
309
310     ext_pi = proto_tree_add_text(tree, tvb, offset, 8, "Extensions: %u at %u",
311                                  extension_vector_count, extension_vector_count);
312     extension_vector = proto_item_add_subtree(ext_pi, ett_negoex_extension_vector);
313
314     proto_tree_add_item(extension_vector, hf_negoex_extension_vector_offset,
315                         tvb, offset, 4, ENC_LITTLE_ENDIAN);
316     offset += 4;
317
318     proto_tree_add_item(extension_vector, hf_negoex_extension_vector_count,
319                         tvb, offset, 2, ENC_LITTLE_ENDIAN);
320     offset += 2;
321
322     proto_tree_add_item(extension_vector, hf_negoex_extension_vector_pad,
323                         tvb, offset, 2, ENC_NA);
324     offset += 2;
325
326     for (i = 0; i < extension_vector_count; i++) {
327       guint32 byte_vector_offset, byte_vector_count;
328       proto_item *bv_pi;
329       proto_tree *bv_tree;
330
331       /*
332        * Dissect these things ... they consist of a byte vector, so we
333        * add a subtree and point to the relevant bytes
334        */
335       byte_vector_offset = tvb_get_letohl(tvb, offset);
336       byte_vector_count = tvb_get_letohs(tvb, offset + 4);
337
338       bv_pi = proto_tree_add_text(extension_vector, tvb,
339                                   extension_vector_offset + i * 8, 8,
340                                   "Extension: %u bytes at %u",
341                                   byte_vector_count, byte_vector_offset);
342       bv_tree = proto_item_add_subtree(bv_pi, ett_negoex_byte_vector);
343
344       proto_tree_add_item(bv_tree, hf_negoex_extension, tvb,
345                           byte_vector_offset, byte_vector_count, ENC_NA);
346     }
347
348
349   } ENDTRY;
350
351 }
352
353 static void
354 dissect_negoex(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
355 {
356   volatile guint32 offset;
357   proto_tree * volatile negoex_tree;
358   proto_item *tf;
359   volatile gboolean done;
360   guint32 payload_len;
361   guint32 message_len;
362   guint32 message_type;
363   guint32 header_len;
364
365   offset = 0;
366   negoex_tree = NULL;
367   tf = NULL;
368   done = FALSE;
369   payload_len = tvb_length(tvb);
370
371   /* Set up the initial NEGOEX payload */
372   if (tree) {
373     tf = proto_tree_add_item(tree, proto_negoex, tvb, offset, -1, ENC_NA);
374     negoex_tree = proto_item_add_subtree(tf, ett_negoex);
375   }
376
377   /*
378    * There can be multiple negoex messages, each with a header with a length.
379    * However, the payload might not have been reassembled ...
380    */
381
382   while (offset < payload_len && !done) {
383     proto_tree *negoex_msg_tree;
384     proto_tree *negoex_hdr_tree;
385     proto_item *msg;
386     proto_item *hdr;
387     tvbuff_t *msg_tvb;
388     guint32 start_offset;
389
390     start_offset = offset;
391
392     TRY {
393      /* Message type, it is after the signature */
394       message_type = tvb_get_letohl(tvb, offset + 8);
395
396       /* Add the message type tree ... set its length below */
397       msg = proto_tree_add_text(negoex_tree, tvb, offset, -1,
398                                 "NEGOEX %s",
399                                 val_to_str_const(message_type,
400                                                  negoex_message_types,
401                                                  "Unknown NEGOEX message type"));
402
403       /* Add a subtree for the message */
404       negoex_msg_tree = proto_item_add_subtree(msg, ett_negoex_msg);
405
406       /* Add a subtree for the header */
407       hdr = proto_tree_add_text(negoex_msg_tree, tvb, offset, 40, "Header");
408       negoex_hdr_tree = proto_item_add_subtree(hdr, ett_negoex_hdr);
409
410       /* Signature, NEGOEXTS */
411       proto_tree_add_item(negoex_hdr_tree, hf_negoex_sig,
412                           tvb, offset, 8, ENC_ASCII | ENC_NA);
413       offset += 8;
414
415       col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "%s",
416                           val_to_str_const(message_type,
417                                            negoex_message_types,
418                                            "Unknown NEGOEX message type"));
419       proto_tree_add_uint(negoex_hdr_tree, hf_negoex_message_type,
420                           tvb, offset, 4, message_type);
421
422       /*
423        * If this is an unknown message type, we have to punt because anything
424        * following cannot be handled
425        */
426       if (message_type > MESSAGE_TYPE_MAX_MSG) {
427         offset = payload_len; /* Can't do any more */
428         goto bad_message;
429       } else {
430         offset += 4;
431       }
432
433       /* Sequence Number */
434       proto_tree_add_item(negoex_hdr_tree, hf_negoex_sequence_num,
435                           tvb, offset, 4, ENC_LITTLE_ENDIAN);
436       offset += 4;
437
438       /* Header Length */
439       header_len = tvb_get_letohl(tvb, offset);
440       proto_tree_add_uint(negoex_hdr_tree, hf_negoex_header_len,
441                           tvb, offset, 4, header_len);
442       offset += 4;
443
444       /* Message Length */
445       message_len = tvb_get_letohl(tvb, offset);
446       proto_tree_add_uint(negoex_hdr_tree, hf_negoex_message_len,
447                           tvb, offset, 4, message_len);
448       offset += 4;
449
450       /* Set the message len so the tree item has correct len */
451       proto_item_set_len(msg, message_len);
452
453       /* Conversation ID */
454       proto_tree_add_item(negoex_hdr_tree, hf_negoex_conversation_id,
455                           tvb, offset, 16, ENC_LITTLE_ENDIAN);
456       offset += 16;
457
458       /*
459        * Construct a new TVB covering just this message and pass to the
460        * sub-dissector
461        */
462       msg_tvb = tvb_new_subset(tvb,
463                                start_offset,
464                                MIN(message_len, tvb_length(tvb)),
465                                message_len);
466
467       switch (message_type) {
468       case MESSAGE_TYPE_INITIATOR_NEGO:
469       case MESSAGE_TYPE_ACCEPTOR_NEGO:
470         dissect_negoex_nego_message(msg_tvb,
471                                     pinfo,
472                                     negoex_msg_tree,
473                                     offset - start_offset);
474         break;
475
476       case MESSAGE_TYPE_INITIATOR_META_DATA:
477       case MESSAGE_TYPE_ACCEPTOR_META_DATA:
478       case MESSAGE_TYPE_CHALLENGE:
479       case MESSAGE_TYPE_AP_REQUEST:
480         dissect_negoex_exchange_message(msg_tvb,
481                                         pinfo,
482                                         negoex_msg_tree,
483                                         offset - start_offset);
484         break;
485
486       case MESSAGE_TYPE_VERIFY:
487         dissect_negoex_verify_message(msg_tvb,
488                                       pinfo,
489                                       negoex_msg_tree,
490                                       offset - start_offset);
491         break;
492
493       case MESSAGE_TYPE_ALERT:
494         dissect_negoex_alert_message(msg_tvb,
495                                      pinfo,
496                                      negoex_msg_tree,
497                                      offset - start_offset);
498         break;
499
500       default:
501         proto_tree_add_text(negoex_msg_tree, tvb, offset, message_len - 40,
502                             "The rest of the message");
503       }
504
505       offset = start_offset + message_len;
506
507       /* We cannot branch out of the TRY block, but we can branch here */
508     bad_message:
509         ;
510
511     } CATCH_NONFATAL_ERRORS {
512       done = TRUE;
513       show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
514     } ENDTRY;
515   }
516
517 }
518
519 void
520 proto_register_negoex(void)
521 {
522
523   static hf_register_info hf[] = {
524     { &hf_negoex_sig,
525       { "Signature", "negoex.message.sig", FT_STRING, BASE_NONE,
526         NULL, 0x0, NULL, HFILL }},
527     { &hf_negoex_message_type,
528       { "MessageType", "negoex.message.type", FT_UINT32, BASE_HEX,
529          VALS(negoex_message_types), 0x00, NULL, HFILL }},
530     { &hf_negoex_sequence_num,
531       { "SequencNum", "negoex.message.seq_num", FT_UINT32, BASE_DEC,
532         NULL, 0x0, NULL, HFILL }},
533     { &hf_negoex_header_len,
534       { "cbHeaderLength", "negoex.header.len", FT_UINT32, BASE_DEC,
535         NULL, 0x0, NULL, HFILL }},
536     { &hf_negoex_message_len,
537       { "cbMessageLength", "negoex.message.len", FT_UINT32, BASE_DEC,
538         NULL, 0x0, NULL, HFILL }},
539     { &hf_negoex_conversation_id,
540       { "ConversationID", "negoex.message.conv_id", FT_GUID, BASE_NONE,
541         NULL, 0x0, NULL, HFILL}},
542     { &hf_negoex_random,
543       { "Random", "negoex.message.random", FT_BYTES, BASE_NONE,
544         NULL, 0x0, "Random data", HFILL }},
545     { &hf_negoex_proto_version,
546       { "ProtocolVersion", "negoex.proto_version", FT_UINT64, BASE_DEC,
547         NULL, 0x0, NULL, HFILL}},
548     { &hf_negoex_authscheme,
549       { "AuthScheme", "negoex.auth_scheme", FT_GUID, BASE_NONE,
550         NULL, 0x0, NULL, HFILL}},
551     { &hf_negoex_authscheme_vector_offset,
552       { "AuthSchemeArrayOffset", "negoex.auth_scheme_array_offset", FT_UINT32,
553         BASE_DEC, NULL, 0x0, NULL, HFILL }},
554     { &hf_negoex_authscheme_vector_count,
555       { "AuthSchemeCount", "negoex.auth_scheme_array_count", FT_UINT16,
556         BASE_DEC, NULL, 0x0, NULL, HFILL }},
557     { &hf_negoex_authscheme_vector_pad,
558       { "AuthSchemePad", "negoex.auth_scheme_array_pad", FT_BYTES,
559         BASE_NONE, NULL, 0x0, NULL, HFILL }},
560     { &hf_negoex_extension,
561       { "Extension", "negoex.extension", FT_BYTES, BASE_NONE,
562         NULL, 0x0, "Extension data", HFILL }},
563     { &hf_negoex_extension_vector_offset,
564       { "ExtensionArrayOffset", "negoex.extension_array_offset", FT_UINT32,
565         BASE_DEC, NULL, 0x0, NULL, HFILL }},
566     { &hf_negoex_extension_vector_count,
567       { "ExtensionCount", "negoex.extension_array_count", FT_UINT16,
568         BASE_DEC, NULL, 0x0, NULL, HFILL }},
569     { &hf_negoex_extension_vector_pad,
570       { "ExtensionPad", "negoex.extension_pad", FT_BYTES,
571         BASE_NONE, NULL, 0x0, NULL, HFILL }},
572     { &hf_negoex_exchange_vector_offset,
573       { "ExchangeOffset", "negoex.exchange_vec_offset", FT_UINT32, BASE_DEC,
574         NULL, 0x0, NULL, HFILL}},
575     { &hf_negoex_exchange_vector_count,
576       { "ExchangeByteCount", "negoex.exchange_vec_byte_count", FT_UINT16,
577         BASE_DEC, NULL, 0x0, NULL, HFILL}},
578     { &hf_negoex_exchange_vector_pad,
579       { "ExchangePad", "negoex.exchange_vec_pad", FT_BYTES, BASE_NONE,
580         NULL, 0x0, NULL, HFILL}},
581     { &hf_negoex_exchange,
582       { "Exchange Bytes", "negoex.exchange", FT_BYTES, BASE_NONE,
583         NULL, 0x0, NULL, HFILL}},
584     { &hf_negoex_checksum_scheme,
585       { "ChecksumScheme", "negoex.checksum_scheme", FT_UINT32, BASE_DEC,
586         VALS(checksum_schemes), 0x0, NULL, HFILL}},
587     { &hf_negoex_checksum_vector_offset,
588       { "ChecksumOffset", "negoex.checksum_vec_offset", FT_UINT32, BASE_DEC,
589         NULL, 0x0, NULL, HFILL}},
590     { &hf_negoex_checksum_vector_count,
591       { "ChecksumCount", "negoex.checksum_vec_count", FT_UINT16, BASE_DEC,
592         NULL, 0x0, NULL, HFILL}},
593     { &hf_negoex_checksum_vector_pad,
594       { "ChecksumPad", "negoex.checksum_pad", FT_BYTES, BASE_NONE,
595         NULL, 0x0, NULL, HFILL}},
596     { &hf_negoex_checksum_type,
597       { "ChecksumType", "negoex.checksum_type", FT_UINT32, BASE_DEC,
598         NULL, 0x0, NULL, HFILL}},
599     { &hf_negoex_checksum,
600       { "Checksum", "negoex.checksum", FT_BYTES, BASE_NONE,
601         NULL, 0x0, NULL, HFILL}},
602     { &hf_negoex_errorcode,
603       { "ErrorCode", "negoex.errorcode", FT_UINT32, BASE_HEX,
604         NULL, 0x0, NULL, HFILL}},
605   };
606
607   static gint *ett[] = {
608     &ett_negoex,
609     &ett_negoex_msg,
610     &ett_negoex_hdr,
611     &ett_negoex_authscheme_vector,
612     &ett_negoex_extension_vector,
613     &ett_negoex_exchange,
614     &ett_negoex_checksum,
615     &ett_negoex_checksum_vector,
616     &ett_negoex_byte_vector,
617   };
618   /*module_t *negoex_module = NULL; */
619
620   proto_negoex = proto_register_protocol (
621     "SPNEGO Extended Negotiation Security Mechanism", /* name */
622     "NEGOEX",  /* short name */
623     "negoex"   /* abbrev */
624     );
625   proto_register_field_array(proto_negoex, hf, array_length(hf));
626   proto_register_subtree_array(ett, array_length(ett));
627
628   /* negoex_module = prefs_register_protocol(proto_negoex, NULL);*/
629
630   register_dissector("negoex", dissect_negoex, proto_negoex);
631 }
632
633 void
634 proto_reg_handoff_negoex(void)
635 {
636   dissector_handle_t negoex_handle;
637
638   /* Register protocol with the GSS-API module */
639
640   negoex_handle = find_dissector("negoex");
641   gssapi_init_oid("1.3.6.1.4.1.311.2.2.30", proto_negoex, ett_negoex,
642                   negoex_handle, NULL,
643                   "NEGOEX - SPNEGO Extended Negotiation Security Mechanism");
644
645 }
646
647 /*
648  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
649  *
650  * Local variables:
651  * c-basic-offset: 2
652  * tab-width: 8
653  * indent-tabs-mode: nil
654  * End:
655  *
656  * vi: set shiftwidth=2 tabstop=8 expandtab:
657  * :indentSize=2:tabSize=8:noTabs=true:
658  */