ff78a1b13c640d9a1cf2a99abd328a2175102534
[metze/wireshark/wip.git] / epan / dissectors / asn1 / kerberos / packet-kerberos-template.c
1 /* packet-kerberos.c
2  * Routines for Kerberos
3  * Wes Hardaker (c) 2000
4  * wjhardaker@ucdavis.edu
5  * Richard Sharpe (C) 2002, rsharpe@samba.org, modularized a bit more and
6  *                          added AP-REQ and AP-REP dissection
7  *
8  * Ronnie Sahlberg (C) 2004, major rewrite for new ASN.1/BER API.
9  *                           decryption of kerberos blobs if keytab is provided
10  *
11  * See RFC 1510, and various I-Ds and other documents showing additions,
12  * e.g. ones listed under
13  *
14  *      http://www.isi.edu/people/bcn/krb-revisions/
15  *
16  * and
17  *
18  *      http://www.ietf.org/internet-drafts/draft-ietf-krb-wg-kerberos-clarifications-07.txt
19  *
20  * and
21  *
22  *      http://www.ietf.org/internet-drafts/draft-ietf-krb-wg-kerberos-referrals-05.txt
23  *
24  * Some structures from RFC2630
25  *
26  * Wireshark - Network traffic analyzer
27  * By Gerald Combs <gerald@wireshark.org>
28  * Copyright 1998 Gerald Combs
29  *
30  * SPDX-License-Identifier: GPL-2.0-or-later
31  */
32
33 /*
34  * Some of the development of the Kerberos protocol decoder was sponsored by
35  * Cable Television Laboratories, Inc. ("CableLabs") based upon proprietary
36  * CableLabs' specifications. Your license and use of this protocol decoder
37  * does not mean that you are licensed to use the CableLabs'
38  * specifications.  If you have questions about this protocol, contact
39  * jf.mule [AT] cablelabs.com or c.stuart [AT] cablelabs.com for additional
40  * information.
41  */
42
43 #include <config.h>
44
45 #include <stdio.h>
46
47 #include <epan/packet.h>
48 #include <epan/exceptions.h>
49 #include <epan/strutil.h>
50 #include <epan/conversation.h>
51 #include <epan/asn1.h>
52 #include <epan/expert.h>
53 #include <epan/prefs.h>
54 #include <wsutil/wsgcrypt.h>
55 #include <wsutil/file_util.h>
56 #include <wsutil/str_util.h>
57 #include "packet-kerberos.h"
58 #include "packet-netbios.h"
59 #include "packet-tcp.h"
60 #include "packet-ber.h"
61 #include "packet-pkinit.h"
62 #include "packet-cms.h"
63 #include "packet-windows-common.h"
64
65 #include "read_keytab_file.h"
66
67 #include "packet-dcerpc-netlogon.h"
68 #include "packet-dcerpc.h"
69
70 #include "packet-gssapi.h"
71 #include "packet-smb-common.h"
72 #include "packet-x509af.h"
73
74 void proto_register_kerberos(void);
75 void proto_reg_handoff_kerberos(void);
76
77 #define UDP_PORT_KERBEROS               88
78 #define TCP_PORT_KERBEROS               88
79
80 #define ADDRESS_STR_BUFSIZ 256
81
82 typedef struct kerberos_key {
83         guint32 keytype;
84         int keylength;
85         const guint8 *keyvalue;
86 } kerberos_key_t;
87
88 typedef struct {
89         guint32 msg_type;
90         guint32 etype;
91         guint32 padata_type;
92         guint32 is_enc_padata;
93         guint32 enctype;
94         kerberos_key_t key;
95         guint32 ad_type;
96         guint32 addr_type;
97         guint32 checksum_type;
98 } kerberos_private_data_t;
99
100 static dissector_handle_t kerberos_handle_udp;
101
102 /* Forward declarations */
103 static int dissect_kerberos_Applications(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
104 static int dissect_kerberos_PA_ENC_TIMESTAMP(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
105 static int dissect_kerberos_KERB_PA_PAC_REQUEST(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
106 static int dissect_kerberos_PA_S4U2Self(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
107 static int dissect_kerberos_PA_S4U_X509_USER(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
108 static int dissect_kerberos_ETYPE_INFO(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
109 static int dissect_kerberos_ETYPE_INFO2(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
110 static int dissect_kerberos_AD_IF_RELEVANT(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
111 static int dissect_kerberos_PA_AUTHENTICATION_SET(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
112 static int dissect_kerberos_PA_FX_FAST_REQUEST(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
113 static int dissect_kerberos_EncryptedChallenge(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
114 static int dissect_kerberos_PA_FX_FAST_REPLY(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
115
116 /* Desegment Kerberos over TCP messages */
117 static gboolean krb_desegment = TRUE;
118
119 static gint proto_kerberos = -1;
120
121 static gint hf_krb_rm_reserved = -1;
122 static gint hf_krb_rm_reclen = -1;
123 static gint hf_krb_provsrv_location = -1;
124 static gint hf_krb_smb_nt_status = -1;
125 static gint hf_krb_smb_unknown = -1;
126 static gint hf_krb_address_ip = -1;
127 static gint hf_krb_address_netbios = -1;
128 static gint hf_krb_address_ipv6 = -1;
129 static gint hf_krb_gssapi_len = -1;
130 static gint hf_krb_gssapi_bnd = -1;
131 static gint hf_krb_gssapi_dlgopt = -1;
132 static gint hf_krb_gssapi_dlglen = -1;
133 static gint hf_krb_gssapi_c_flag_deleg = -1;
134 static gint hf_krb_gssapi_c_flag_mutual = -1;
135 static gint hf_krb_gssapi_c_flag_replay = -1;
136 static gint hf_krb_gssapi_c_flag_sequence = -1;
137 static gint hf_krb_gssapi_c_flag_conf = -1;
138 static gint hf_krb_gssapi_c_flag_integ = -1;
139 static gint hf_krb_gssapi_c_flag_dce_style = -1;
140 static gint hf_krb_midl_version = -1;
141 static gint hf_krb_midl_hdr_len = -1;
142 static gint hf_krb_midl_fill_bytes = -1;
143 static gint hf_krb_midl_blob_len = -1;
144 static gint hf_krb_pac_signature_type = -1;
145 static gint hf_krb_pac_signature_signature = -1;
146 static gint hf_krb_w2k_pac_entries = -1;
147 static gint hf_krb_w2k_pac_version = -1;
148 static gint hf_krb_w2k_pac_type = -1;
149 static gint hf_krb_w2k_pac_size = -1;
150 static gint hf_krb_w2k_pac_offset = -1;
151 static gint hf_krb_pac_clientid = -1;
152 static gint hf_krb_pac_namelen = -1;
153 static gint hf_krb_pac_clientname = -1;
154 static gint hf_krb_pac_logon_info = -1;
155 static gint hf_krb_pac_credential_type = -1;
156 static gint hf_krb_pac_s4u_delegation_info = -1;
157 static gint hf_krb_pac_upn_dns_info = -1;
158 static gint hf_krb_pac_upn_flags = -1;
159 static gint hf_krb_pac_upn_dns_offset = -1;
160 static gint hf_krb_pac_upn_dns_len = -1;
161 static gint hf_krb_pac_upn_upn_offset = -1;
162 static gint hf_krb_pac_upn_upn_len = -1;
163 static gint hf_krb_pac_upn_upn_name = -1;
164 static gint hf_krb_pac_upn_dns_name = -1;
165 static gint hf_krb_pac_server_checksum = -1;
166 static gint hf_krb_pac_privsvr_checksum = -1;
167 static gint hf_krb_pac_client_info_type = -1;
168 #include "packet-kerberos-hf.c"
169
170 /* Initialize the subtree pointers */
171 static gint ett_kerberos = -1;
172 static gint ett_krb_recordmark = -1;
173 static gint ett_krb_pac = -1;
174 static gint ett_krb_pac_drep = -1;
175 static gint ett_krb_pac_midl_blob = -1;
176 static gint ett_krb_pac_logon_info = -1;
177 static gint ett_krb_pac_s4u_delegation_info = -1;
178 static gint ett_krb_pac_upn_dns_info = -1;
179 static gint ett_krb_pac_server_checksum = -1;
180 static gint ett_krb_pac_privsvr_checksum = -1;
181 static gint ett_krb_pac_client_info_type = -1;
182 #include "packet-kerberos-ett.c"
183
184 static expert_field ei_kerberos_decrypted_keytype = EI_INIT;
185 static expert_field ei_kerberos_address = EI_INIT;
186 static expert_field ei_krb_gssapi_dlglen = EI_INIT;
187
188 static dissector_handle_t krb4_handle=NULL;
189
190 /* Global variables */
191 static guint32 krb5_errorcode;
192 static guint32 gbl_keytype;
193 static gboolean gbl_do_col_info;
194
195 #include "packet-kerberos-val.h"
196
197 static void
198 call_kerberos_callbacks(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int tag, kerberos_callbacks *cb)
199 {
200         if(!cb){
201                 return;
202         }
203
204         while(cb->tag){
205                 if(cb->tag==tag){
206                         cb->callback(pinfo, tvb, tree);
207                         return;
208                 }
209                 cb++;
210         }
211         return;
212 }
213
214 static kerberos_private_data_t*
215 kerberos_get_private_data(asn1_ctx_t *actx)
216 {
217         if (!actx->private_data) {
218                 actx->private_data = wmem_new0(wmem_packet_scope(), kerberos_private_data_t);
219         }
220         return (kerberos_private_data_t *)(actx->private_data);
221 }
222
223 #ifdef HAVE_KERBEROS
224
225 /* Decrypt Kerberos blobs */
226 gboolean krb_decrypt = FALSE;
227
228 /* keytab filename */
229 static const char *keytab_filename = "";
230
231 void
232 read_keytab_file_from_preferences(void)
233 {
234         static char *last_keytab = NULL;
235
236         if (!krb_decrypt) {
237                 return;
238         }
239
240         if (keytab_filename == NULL) {
241                 return;
242         }
243
244         if (last_keytab && !strcmp(last_keytab, keytab_filename)) {
245                 return;
246         }
247
248         g_free(last_keytab);
249         last_keytab = g_strdup(keytab_filename);
250
251         read_keytab_file(last_keytab);
252 }
253 #endif /* HAVE_KERBEROS */
254
255 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
256 #ifdef _WIN32
257 /* prevent redefinition warnings in kfw-2.5\inc\win_mac.h */
258 #undef HAVE_GETADDRINFO
259 #undef HAVE_SYS_TYPES_H
260 #endif /* _WIN32 */
261 #include <krb5.h>
262 enc_key_t *enc_key_list=NULL;
263
264 static void
265 add_encryption_key(packet_info *pinfo, int keytype, int keylength, const char *keyvalue, const char *origin)
266 {
267         enc_key_t *new_key;
268
269         if(pinfo->fd->visited){
270                 return;
271         }
272
273         new_key=(enc_key_t *)g_malloc(sizeof(enc_key_t));
274         g_snprintf(new_key->key_origin, KRB_MAX_ORIG_LEN, "%s learnt from frame %u",origin,pinfo->num);
275         new_key->fd_num = pinfo->num;
276         new_key->next=enc_key_list;
277         enc_key_list=new_key;
278         new_key->keytype=keytype;
279         new_key->keylength=keylength;
280         /*XXX this needs to be freed later */
281         new_key->keyvalue=(char *)g_memdup(keyvalue, keylength);
282 }
283 #endif /* HAVE_HEIMDAL_KERBEROS || HAVE_MIT_KERBEROS */
284
285 #if defined(HAVE_MIT_KERBEROS)
286
287 static krb5_context krb5_ctx;
288
289 USES_APPLE_DEPRECATED_API
290 void
291 read_keytab_file(const char *filename)
292 {
293         krb5_keytab keytab;
294         krb5_error_code ret;
295         krb5_keytab_entry key;
296         krb5_kt_cursor cursor;
297         static gboolean first_time=TRUE;
298
299         if (filename == NULL || filename[0] == 0) {
300                 return;
301         }
302
303         if(first_time){
304                 first_time=FALSE;
305                 ret = krb5_init_context(&krb5_ctx);
306                 if(ret && ret != KRB5_CONFIG_CANTOPEN){
307                         return;
308                 }
309         }
310
311         /* should use a file in the wireshark users dir */
312         ret = krb5_kt_resolve(krb5_ctx, filename, &keytab);
313         if(ret){
314                 fprintf(stderr, "KERBEROS ERROR: Badly formatted keytab filename :%s\n",filename);
315
316                 return;
317         }
318
319         ret = krb5_kt_start_seq_get(krb5_ctx, keytab, &cursor);
320         if(ret){
321                 fprintf(stderr, "KERBEROS ERROR: Could not open or could not read from keytab file :%s\n",filename);
322                 return;
323         }
324
325         do{
326                 ret = krb5_kt_next_entry(krb5_ctx, keytab, &key, &cursor);
327                 if(ret==0){
328                         enc_key_t *new_key;
329                         int i;
330                         char *pos;
331
332                         new_key = g_new(enc_key_t, 1);
333                         new_key->fd_num = -1;
334                         new_key->next = enc_key_list;
335
336                         /* generate origin string, describing where this key came from */
337                         pos=new_key->key_origin;
338                         pos+=MIN(KRB_MAX_ORIG_LEN,
339                                          g_snprintf(pos, KRB_MAX_ORIG_LEN, "keytab principal "));
340                         for(i=0;i<key.principal->length;i++){
341                                 pos+=MIN(KRB_MAX_ORIG_LEN-(pos-new_key->key_origin),
342                                                  g_snprintf(pos, (gulong)(KRB_MAX_ORIG_LEN-(pos-new_key->key_origin)), "%s%s",(i?"/":""),(key.principal->data[i]).data));
343                         }
344                         pos+=MIN(KRB_MAX_ORIG_LEN-(pos-new_key->key_origin),
345                                          g_snprintf(pos, (gulong)(KRB_MAX_ORIG_LEN-(pos-new_key->key_origin)), "@%s",key.principal->realm.data));
346                         *pos=0;
347                         new_key->keytype=key.key.enctype;
348                         new_key->keylength=key.key.length;
349                         new_key->keyvalue=(char *)g_memdup(key.key.contents, key.key.length);
350                         enc_key_list=new_key;
351                         ret = krb5_free_keytab_entry_contents(krb5_ctx, &key);
352                         if (ret) {
353                                 fprintf(stderr, "KERBEROS ERROR: Could not release the entry: %d", ret);
354                                 ret = 0; /* try to continue with the next entry */
355                         }
356                 }
357         }while(ret==0);
358
359         ret = krb5_kt_end_seq_get(krb5_ctx, keytab, &cursor);
360         if(ret){
361                 fprintf(stderr, "KERBEROS ERROR: Could not release the keytab cursor: %d", ret);
362         }
363         ret = krb5_kt_close(krb5_ctx, keytab);
364         if(ret){
365                 fprintf(stderr, "KERBEROS ERROR: Could not close the key table handle: %d", ret);
366         }
367 }
368
369
370 guint8 *
371 decrypt_krb5_data(proto_tree *tree _U_, packet_info *pinfo,
372                                         int usage,
373                                         tvbuff_t *cryptotvb,
374                                         int keytype,
375                                         int *datalen)
376 {
377         krb5_error_code ret;
378         enc_key_t *ek;
379         krb5_data data = {0,0,NULL};
380         krb5_keytab_entry key;
381         int length = tvb_captured_length(cryptotvb);
382         const guint8 *cryptotext = tvb_get_ptr(cryptotvb, 0, length);
383
384         /* don't do anything if we are not attempting to decrypt data */
385         if(!krb_decrypt || length < 1){
386                 return NULL;
387         }
388
389         /* make sure we have all the data we need */
390         if (tvb_captured_length(cryptotvb) < tvb_reported_length(cryptotvb)) {
391                 return NULL;
392         }
393
394         read_keytab_file_from_preferences();
395         data.data = (char *)wmem_alloc(pinfo->pool, length);
396         data.length = length;
397
398         for(ek=enc_key_list;ek;ek=ek->next){
399                 krb5_enc_data input;
400
401                 /* shortcircuit and bail out if enctypes are not matching */
402                 if((keytype != -1) && (ek->keytype != keytype)) {
403                         continue;
404                 }
405
406                 input.enctype = ek->keytype;
407                 input.ciphertext.length = length;
408                 input.ciphertext.data = (guint8 *)cryptotext;
409
410                 key.key.enctype=ek->keytype;
411                 key.key.length=ek->keylength;
412                 key.key.contents=ek->keyvalue;
413                 ret = krb5_c_decrypt(krb5_ctx, &(key.key), usage, 0, &input, &data);
414                 if(ret == 0){
415                         char *user_data;
416
417                         expert_add_info_format(pinfo, NULL, &ei_kerberos_decrypted_keytype,
418                                                                    "Decrypted keytype %d in frame %u using %s",
419                                                                    ek->keytype, pinfo->num, ek->key_origin);
420
421                         proto_tree_add_text(tree, NULL, 0, 0, "[Decrypted using: %s]", ek->key_origin);
422
423                         user_data=data.data;
424                         if (datalen) {
425                                 *datalen = data.length;
426                         }
427                         return user_data;
428                 }
429         }
430
431         return NULL;
432 }
433 USES_APPLE_RST
434
435 #elif defined(HAVE_HEIMDAL_KERBEROS)
436 static krb5_context krb5_ctx;
437
438 USES_APPLE_DEPRECATED_API
439 void
440 read_keytab_file(const char *filename)
441 {
442         krb5_keytab keytab;
443         krb5_error_code ret;
444         krb5_keytab_entry key;
445         krb5_kt_cursor cursor;
446         enc_key_t *new_key;
447         static gboolean first_time=TRUE;
448
449         if (filename == NULL || filename[0] == 0) {
450                 return;
451         }
452
453         if(first_time){
454                 first_time=FALSE;
455                 ret = krb5_init_context(&krb5_ctx);
456                 if(ret){
457                         return;
458                 }
459         }
460
461         /* should use a file in the wireshark users dir */
462         ret = krb5_kt_resolve(krb5_ctx, filename, &keytab);
463         if(ret){
464                 fprintf(stderr, "KERBEROS ERROR: Could not open keytab file :%s\n",filename);
465
466                 return;
467         }
468
469         ret = krb5_kt_start_seq_get(krb5_ctx, keytab, &cursor);
470         if(ret){
471                 fprintf(stderr, "KERBEROS ERROR: Could not read from keytab file :%s\n",filename);
472                 return;
473         }
474
475         do{
476                 ret = krb5_kt_next_entry(krb5_ctx, keytab, &key, &cursor);
477                 if(ret==0){
478                         unsigned int i;
479                         char *pos;
480
481                         new_key = g_new0(enc_key_t, 1);
482                         new_key->fd_num = -1;
483                         new_key->next = enc_key_list;
484
485                         /* generate origin string, describing where this key came from */
486                         pos=new_key->key_origin;
487                         pos+=MIN(KRB_MAX_ORIG_LEN,
488                                          g_snprintf(pos, KRB_MAX_ORIG_LEN, "keytab principal "));
489                         for(i=0;i<key.principal->name.name_string.len;i++){
490                                 pos+=MIN(KRB_MAX_ORIG_LEN-(pos-new_key->key_origin),
491                                                  g_snprintf(pos, KRB_MAX_ORIG_LEN-(pos-new_key->key_origin), "%s%s",(i?"/":""),key.principal->name.name_string.val[i]));
492                         }
493                         pos+=MIN(KRB_MAX_ORIG_LEN-(pos-new_key->key_origin),
494                                          g_snprintf(pos, KRB_MAX_ORIG_LEN-(pos-new_key->key_origin), "@%s",key.principal->realm));
495                         *pos=0;
496                         new_key->keytype=key.keyblock.keytype;
497                         new_key->keylength=(int)key.keyblock.keyvalue.length;
498                         new_key->keyvalue = (guint8 *)g_memdup(key.keyblock.keyvalue.data, (guint)key.keyblock.keyvalue.length);
499                         enc_key_list=new_key;
500                         ret = krb5_kt_free_entry(krb5_ctx, &key);
501                         if (ret) {
502                                 fprintf(stderr, "KERBEROS ERROR: Could not release the entry: %d", ret);
503                                 ret = 0; /* try to continue with the next entry */
504                         }
505                 }
506         }while(ret==0);
507
508         ret = krb5_kt_end_seq_get(krb5_ctx, keytab, &cursor);
509         if(ret){
510                 fprintf(stderr, "KERBEROS ERROR: Could not release the keytab cursor: %d", ret);
511         }
512         ret = krb5_kt_close(krb5_ctx, keytab);
513         if(ret){
514                 fprintf(stderr, "KERBEROS ERROR: Could not close the key table handle: %d", ret);
515         }
516
517 }
518 USES_APPLE_RST
519
520
521 guint8 *
522 decrypt_krb5_data(proto_tree *tree _U_, packet_info *pinfo,
523                                         int usage,
524                                         tvbuff_t *cryptotvb,
525                                         int keytype,
526                                         int *datalen)
527 {
528         krb5_error_code ret;
529         krb5_data data;
530         enc_key_t *ek;
531         int length = tvb_captured_length(cryptotvb);
532         const guint8 *cryptotext = tvb_get_ptr(cryptotvb, 0, length);
533
534         /* don't do anything if we are not attempting to decrypt data */
535         if(!krb_decrypt){
536                 return NULL;
537         }
538
539         /* make sure we have all the data we need */
540         if (tvb_captured_length(cryptotvb) < tvb_reported_length(cryptotvb)) {
541                 return NULL;
542         }
543
544         read_keytab_file_from_preferences();
545
546         for(ek=enc_key_list;ek;ek=ek->next){
547                 krb5_keytab_entry key;
548                 krb5_crypto crypto;
549                 guint8 *cryptocopy; /* workaround for pre-0.6.1 heimdal bug */
550
551                 /* shortcircuit and bail out if enctypes are not matching */
552                 if((keytype != -1) && (ek->keytype != keytype)) {
553                         continue;
554                 }
555
556                 key.keyblock.keytype=ek->keytype;
557                 key.keyblock.keyvalue.length=ek->keylength;
558                 key.keyblock.keyvalue.data=ek->keyvalue;
559                 ret = krb5_crypto_init(krb5_ctx, &(key.keyblock), (krb5_enctype)ENCTYPE_NULL, &crypto);
560                 if(ret){
561                         return NULL;
562                 }
563
564                 /* pre-0.6.1 versions of Heimdal would sometimes change
565                    the cryptotext data even when the decryption failed.
566                    This would obviously not work since we iterate over the
567                    keys. So just give it a copy of the crypto data instead.
568                    This has been seen for RC4-HMAC blobs.
569                 */
570                 cryptocopy = (guint8 *)wmem_memdup(wmem_packet_scope(), cryptotext, length);
571                 ret = krb5_decrypt_ivec(krb5_ctx, crypto, usage,
572                                                                 cryptocopy, length,
573                                                                 &data,
574                                                                 NULL);
575                 if((ret == 0) && (length>0)){
576                         char *user_data;
577
578                         expert_add_info_format(pinfo, NULL, &ei_kerberos_decrypted_keytype,
579                                                                    "Decrypted keytype %d in frame %u using %s",
580                                                                    ek->keytype, pinfo->num, ek->key_origin);
581
582                         proto_tree_add_text(tree, NULL, 0, 0, "[Decrypted using: %s]", ek->key_origin);
583
584                         krb5_crypto_destroy(krb5_ctx, crypto);
585                         /* return a private wmem_alloced blob to the caller */
586                         user_data = (char *)wmem_memdup(pinfo->pool, data.data, (guint)data.length);
587                         if (datalen) {
588                                 *datalen = (int)data.length;
589                         }
590                         return user_data;
591                 }
592                 krb5_crypto_destroy(krb5_ctx, crypto);
593         }
594         return NULL;
595 }
596
597 #elif defined (HAVE_LIBNETTLE)
598
599 #define SERVICE_KEY_SIZE (DES3_KEY_SIZE + 2)
600 #define KEYTYPE_DES3_CBC_MD5 5  /* Currently the only one supported */
601
602 typedef struct _service_key_t {
603         guint16 kvno;
604         int     keytype;
605         int     length;
606         guint8 *contents;
607         char    origin[KRB_MAX_ORIG_LEN+1];
608 } service_key_t;
609 GSList *service_key_list = NULL;
610
611
612 static void
613 add_encryption_key(packet_info *pinfo, int keytype, int keylength, const char *keyvalue, const char *origin)
614 {
615         service_key_t *new_key;
616
617         if(pinfo->fd->visited){
618                 return;
619         }
620
621         new_key = g_malloc(sizeof(service_key_t));
622         new_key->kvno = 0;
623         new_key->keytype = keytype;
624         new_key->length = keylength;
625         new_key->contents = g_memdup(keyvalue, keylength);
626         g_snprintf(new_key->origin, KRB_MAX_ORIG_LEN, "%s learnt from frame %u", origin, pinfo->num);
627         service_key_list = g_slist_append(service_key_list, (gpointer) new_key);
628 }
629
630 static void
631 clear_keytab(void) {
632         GSList *ske;
633         service_key_t *sk;
634
635         for(ske = service_key_list; ske != NULL; ske = g_slist_next(ske)){
636                 sk = (service_key_t *) ske->data;
637                 if (sk) {
638                         g_free(sk->contents);
639                         g_free(sk);
640                 }
641         }
642         g_slist_free(service_key_list);
643         service_key_list = NULL;
644 }
645
646 static void
647 read_keytab_file(const char *service_key_file)
648 {
649         FILE *skf;
650         ws_statb64 st;
651         service_key_t *sk;
652         unsigned char buf[SERVICE_KEY_SIZE];
653         int newline_skip = 0, count = 0;
654
655         if (service_key_file != NULL && ws_stat64 (service_key_file, &st) == 0) {
656
657                 /* The service key file contains raw 192-bit (24 byte) 3DES keys.
658                  * There can be zero, one (\n), or two (\r\n) characters between
659                  * keys.  Trailing characters are ignored.
660                  */
661
662                 /* XXX We should support the standard keytab format instead */
663                 if (st.st_size > SERVICE_KEY_SIZE) {
664                         if ( (st.st_size % (SERVICE_KEY_SIZE + 1) == 0) ||
665                                  (st.st_size % (SERVICE_KEY_SIZE + 1) == SERVICE_KEY_SIZE) ) {
666                                 newline_skip = 1;
667                         } else if ( (st.st_size % (SERVICE_KEY_SIZE + 2) == 0) ||
668                                  (st.st_size % (SERVICE_KEY_SIZE + 2) == SERVICE_KEY_SIZE) ) {
669                                 newline_skip = 2;
670                         }
671                 }
672
673                 skf = ws_fopen(service_key_file, "rb");
674                 if (! skf) return;
675
676                 while (fread(buf, SERVICE_KEY_SIZE, 1, skf) == 1) {
677                         sk = g_malloc(sizeof(service_key_t));
678                         sk->kvno = buf[0] << 8 | buf[1];
679                         sk->keytype = KEYTYPE_DES3_CBC_MD5;
680                         sk->length = DES3_KEY_SIZE;
681                         sk->contents = g_memdup(buf + 2, DES3_KEY_SIZE);
682                         g_snprintf(sk->origin, KRB_MAX_ORIG_LEN, "3DES service key file, key #%d, offset %ld", count, ftell(skf));
683                         service_key_list = g_slist_append(service_key_list, (gpointer) sk);
684                         if (fseek(skf, newline_skip, SEEK_CUR) < 0) {
685                                 fprintf(stderr, "unable to seek...\n");
686                                 return;
687                         }
688                         count++;
689                 }
690                 fclose(skf);
691         }
692 }
693
694 #define CONFOUNDER_PLUS_CHECKSUM 24
695
696 guint8 *
697 decrypt_krb5_data(proto_tree *tree, packet_info *pinfo,
698                                         int _U_ usage,
699                                         tvbuff_t *cryptotvb,
700                                         int keytype,
701                                         int *datalen)
702 {
703         tvbuff_t *encr_tvb;
704         guint8 *decrypted_data = NULL, *plaintext = NULL;
705         guint8 cls;
706         gboolean pc;
707         guint32 tag, item_len, data_len;
708         int id_offset, offset;
709         guint8 key[DES3_KEY_SIZE];
710         guint8 initial_vector[DES_BLOCK_SIZE];
711         gcry_md_hd_t md5_handle;
712         guint8 *digest;
713         guint8 zero_fill[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
714         guint8 confounder[8];
715         gboolean ind;
716         GSList *ske;
717         service_key_t *sk;
718         struct des3_ctx ctx;
719         int length = tvb_captured_length(cryptotvb);
720         const guint8 *cryptotext = tvb_get_ptr(cryptotvb, 0, length);
721
722
723         /* don't do anything if we are not attempting to decrypt data */
724         if(!krb_decrypt){
725                 return NULL;
726         }
727
728         /* make sure we have all the data we need */
729         if (tvb_captured_length(cryptotvb) < tvb_reported_length(cryptotvb)) {
730                 return NULL;
731         }
732
733         if (keytype != KEYTYPE_DES3_CBC_MD5 || service_key_list == NULL) {
734                 return NULL;
735         }
736
737         decrypted_data = wmem_alloc(wmem_packet_scope(), length);
738         for(ske = service_key_list; ske != NULL; ske = g_slist_next(ske)){
739                 gboolean do_continue = FALSE;
740                 gboolean digest_ok;
741                 sk = (service_key_t *) ske->data;
742
743                 des_fix_parity(DES3_KEY_SIZE, key, sk->contents);
744
745                 memset(initial_vector, 0, DES_BLOCK_SIZE);
746                 des3_set_key(&ctx, key);
747                 cbc_decrypt(&ctx, des3_decrypt, DES_BLOCK_SIZE, initial_vector,
748                                         length, decrypted_data, cryptotext);
749                 encr_tvb = tvb_new_real_data(decrypted_data, length, length);
750
751                 tvb_memcpy(encr_tvb, confounder, 0, 8);
752
753                 /* We have to pull the decrypted data length from the decrypted
754                  * content.  If the key doesn't match or we otherwise get garbage,
755                  * an exception may get thrown while decoding the ASN.1 header.
756                  * Catch it, just in case.
757                  */
758                 TRY {
759                         id_offset = get_ber_identifier(encr_tvb, CONFOUNDER_PLUS_CHECKSUM, &cls, &pc, &tag);
760                         offset = get_ber_length(encr_tvb, id_offset, &item_len, &ind);
761                 }
762                 CATCH_BOUNDS_ERRORS {
763                         tvb_free(encr_tvb);
764                         do_continue = TRUE;
765                 }
766                 ENDTRY;
767
768                 if (do_continue) continue;
769
770                 data_len = item_len + offset - CONFOUNDER_PLUS_CHECKSUM;
771                 if ((int) item_len + offset > length) {
772                         tvb_free(encr_tvb);
773                         continue;
774                 }
775
776                 if (gcry_md_open(&md5_handle, GCRY_MD_MD5, 0)) {
777                         return NULL;
778                 }
779                 gcry_md_write(md5_handle, confounder, 8);
780                 gcry_md_write(md5_handle, zero_fill, 16);
781                 gcry_md_write(md5_handle, decrypted_data + CONFOUNDER_PLUS_CHECKSUM, data_len);
782                 digest = gcry_md_read(md5_handle, 0);
783
784                 digest_ok = (tvb_memeql (encr_tvb, 8, digest, HASH_MD5_LENGTH) == 0);
785                 gcry_md_close(md5_handle);
786                 if (digest_ok) {
787                         plaintext = (guint8* )tvb_memdup(pinfo->pool, encr_tvb, CONFOUNDER_PLUS_CHECKSUM, data_len);
788                         tvb_free(encr_tvb);
789
790                         if (datalen) {
791                                 *datalen = data_len;
792                         }
793                         return(plaintext);
794                 }
795                 tvb_free(encr_tvb);
796         }
797
798         return NULL;
799 }
800
801 #endif  /* HAVE_MIT_KERBEROS / HAVE_HEIMDAL_KERBEROS / HAVE_LIBNETTLE */
802
803 #define INET6_ADDRLEN   16
804
805 /* TCP Record Mark */
806 #define KRB_RM_RESERVED 0x80000000U
807 #define KRB_RM_RECLEN   0x7fffffffU
808
809 #define KRB5_MSG_TICKET                 1       /* Ticket */
810 #define KRB5_MSG_AUTHENTICATOR          2       /* Authenticator */
811 #define KRB5_MSG_ENC_TICKET_PART        3       /* EncTicketPart */
812 #define KRB5_MSG_AS_REQ                 10      /* AS-REQ type */
813 #define KRB5_MSG_AS_REP                 11      /* AS-REP type */
814 #define KRB5_MSG_TGS_REQ                12      /* TGS-REQ type */
815 #define KRB5_MSG_TGS_REP                13      /* TGS-REP type */
816 #define KRB5_MSG_AP_REQ                 14      /* AP-REQ type */
817 #define KRB5_MSG_AP_REP                 15      /* AP-REP type */
818
819 #define KRB5_MSG_SAFE                   20      /* KRB-SAFE type */
820 #define KRB5_MSG_PRIV                   21      /* KRB-PRIV type */
821 #define KRB5_MSG_CRED                   22      /* KRB-CRED type */
822 #define KRB5_MSG_ENC_AS_REP_PART        25      /* EncASRepPart */
823 #define KRB5_MSG_ENC_TGS_REP_PART       26      /* EncTGSRepPart */
824 #define KRB5_MSG_ENC_AP_REP_PART        27      /* EncAPRepPart */
825 #define KRB5_MSG_ENC_KRB_PRIV_PART      28      /* EncKrbPrivPart */
826 #define KRB5_MSG_ENC_KRB_CRED_PART      29      /* EncKrbCredPart */
827 #define KRB5_MSG_ERROR                  30      /* KRB-ERROR type */
828
829 #define KRB5_CHKSUM_GSSAPI              0x8003
830 /*
831  * For KERB_ENCTYPE_RC4_HMAC and KERB_ENCTYPE_RC4_HMAC_EXP, see
832  *
833  *      http://www.ietf.org/internet-drafts/draft-brezak-win2k-krb-rc4-hmac-04.txt
834  *
835  * unless it's expired.
836  */
837
838 /* Principal name-type */
839 #define KRB5_NT_UNKNOWN         0
840 #define KRB5_NT_PRINCIPAL       1
841 #define KRB5_NT_SRV_INST        2
842 #define KRB5_NT_SRV_HST         3
843 #define KRB5_NT_SRV_XHST        4
844 #define KRB5_NT_UID             5
845 #define KRB5_NT_X500_PRINCIPAL  6
846 #define KRB5_NT_SMTP_NAME       7
847 #define KRB5_NT_ENTERPRISE      10
848
849 /*
850  * MS specific name types, from
851  *
852  *      http://msdn.microsoft.com/library/en-us/security/security/kerb_external_name.asp
853  */
854 #define KRB5_NT_MS_PRINCIPAL            -128
855 #define KRB5_NT_MS_PRINCIPAL_AND_SID    -129
856 #define KRB5_NT_ENT_PRINCIPAL_AND_SID   -130
857 #define KRB5_NT_PRINCIPAL_AND_SID       -131
858 #define KRB5_NT_SRV_INST_AND_SID        -132
859
860 /* error table constants */
861 /* I prefixed the krb5_err.et constant names with KRB5_ET_ for these */
862 #define KRB5_ET_KRB5KDC_ERR_NONE                        0
863 #define KRB5_ET_KRB5KDC_ERR_NAME_EXP                    1
864 #define KRB5_ET_KRB5KDC_ERR_SERVICE_EXP                 2
865 #define KRB5_ET_KRB5KDC_ERR_BAD_PVNO                    3
866 #define KRB5_ET_KRB5KDC_ERR_C_OLD_MAST_KVNO             4
867 #define KRB5_ET_KRB5KDC_ERR_S_OLD_MAST_KVNO             5
868 #define KRB5_ET_KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN         6
869 #define KRB5_ET_KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN         7
870 #define KRB5_ET_KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE        8
871 #define KRB5_ET_KRB5KDC_ERR_NULL_KEY                    9
872 #define KRB5_ET_KRB5KDC_ERR_CANNOT_POSTDATE             10
873 #define KRB5_ET_KRB5KDC_ERR_NEVER_VALID                 11
874 #define KRB5_ET_KRB5KDC_ERR_POLICY                      12
875 #define KRB5_ET_KRB5KDC_ERR_BADOPTION                   13
876 #define KRB5_ET_KRB5KDC_ERR_ETYPE_NOSUPP                14
877 #define KRB5_ET_KRB5KDC_ERR_SUMTYPE_NOSUPP              15
878 #define KRB5_ET_KRB5KDC_ERR_PADATA_TYPE_NOSUPP          16
879 #define KRB5_ET_KRB5KDC_ERR_TRTYPE_NOSUPP               17
880 #define KRB5_ET_KRB5KDC_ERR_CLIENT_REVOKED              18
881 #define KRB5_ET_KRB5KDC_ERR_SERVICE_REVOKED             19
882 #define KRB5_ET_KRB5KDC_ERR_TGT_REVOKED                 20
883 #define KRB5_ET_KRB5KDC_ERR_CLIENT_NOTYET               21
884 #define KRB5_ET_KRB5KDC_ERR_SERVICE_NOTYET              22
885 #define KRB5_ET_KRB5KDC_ERR_KEY_EXP                     23
886 #define KRB5_ET_KRB5KDC_ERR_PREAUTH_FAILED              24
887 #define KRB5_ET_KRB5KDC_ERR_PREAUTH_REQUIRED            25
888 #define KRB5_ET_KRB5KDC_ERR_SERVER_NOMATCH              26
889 #define KRB5_ET_KRB5KDC_ERR_MUST_USE_USER2USER          27
890 #define KRB5_ET_KRB5KDC_ERR_PATH_NOT_ACCEPTED           28
891 #define KRB5_ET_KRB5KDC_ERR_SVC_UNAVAILABLE             29
892 #define KRB5_ET_KRB5KRB_AP_ERR_BAD_INTEGRITY            31
893 #define KRB5_ET_KRB5KRB_AP_ERR_TKT_EXPIRED              32
894 #define KRB5_ET_KRB5KRB_AP_ERR_TKT_NYV                  33
895 #define KRB5_ET_KRB5KRB_AP_ERR_REPEAT                   34
896 #define KRB5_ET_KRB5KRB_AP_ERR_NOT_US                   35
897 #define KRB5_ET_KRB5KRB_AP_ERR_BADMATCH                 36
898 #define KRB5_ET_KRB5KRB_AP_ERR_SKEW                     37
899 #define KRB5_ET_KRB5KRB_AP_ERR_BADADDR                  38
900 #define KRB5_ET_KRB5KRB_AP_ERR_BADVERSION               39
901 #define KRB5_ET_KRB5KRB_AP_ERR_MSG_TYPE                 40
902 #define KRB5_ET_KRB5KRB_AP_ERR_MODIFIED                 41
903 #define KRB5_ET_KRB5KRB_AP_ERR_BADORDER                 42
904 #define KRB5_ET_KRB5KRB_AP_ERR_ILL_CR_TKT               43
905 #define KRB5_ET_KRB5KRB_AP_ERR_BADKEYVER                44
906 #define KRB5_ET_KRB5KRB_AP_ERR_NOKEY                    45
907 #define KRB5_ET_KRB5KRB_AP_ERR_MUT_FAIL                 46
908 #define KRB5_ET_KRB5KRB_AP_ERR_BADDIRECTION             47
909 #define KRB5_ET_KRB5KRB_AP_ERR_METHOD                   48
910 #define KRB5_ET_KRB5KRB_AP_ERR_BADSEQ                   49
911 #define KRB5_ET_KRB5KRB_AP_ERR_INAPP_CKSUM              50
912 #define KRB5_ET_KRB5KDC_AP_PATH_NOT_ACCEPTED            51
913 #define KRB5_ET_KRB5KRB_ERR_RESPONSE_TOO_BIG            52
914 #define KRB5_ET_KRB5KRB_ERR_GENERIC                     60
915 #define KRB5_ET_KRB5KRB_ERR_FIELD_TOOLONG               61
916 #define KRB5_ET_KDC_ERROR_CLIENT_NOT_TRUSTED            62
917 #define KRB5_ET_KDC_ERROR_KDC_NOT_TRUSTED               63
918 #define KRB5_ET_KDC_ERROR_INVALID_SIG                   64
919 #define KRB5_ET_KDC_ERR_KEY_TOO_WEAK                    65
920 #define KRB5_ET_KDC_ERR_CERTIFICATE_MISMATCH            66
921 #define KRB5_ET_KRB_AP_ERR_NO_TGT                       67
922 #define KRB5_ET_KDC_ERR_WRONG_REALM                     68
923 #define KRB5_ET_KRB_AP_ERR_USER_TO_USER_REQUIRED        69
924 #define KRB5_ET_KDC_ERR_CANT_VERIFY_CERTIFICATE         70
925 #define KRB5_ET_KDC_ERR_INVALID_CERTIFICATE             71
926 #define KRB5_ET_KDC_ERR_REVOKED_CERTIFICATE             72
927 #define KRB5_ET_KDC_ERR_REVOCATION_STATUS_UNKNOWN       73
928 #define KRB5_ET_KDC_ERR_REVOCATION_STATUS_UNAVAILABLE   74
929 #define KRB5_ET_KDC_ERR_CLIENT_NAME_MISMATCH            75
930 #define KRB5_ET_KDC_ERR_KDC_NAME_MISMATCH               76
931
932 static const value_string krb5_error_codes[] = {
933         { KRB5_ET_KRB5KDC_ERR_NONE, "KRB5KDC_ERR_NONE" },
934         { KRB5_ET_KRB5KDC_ERR_NAME_EXP, "KRB5KDC_ERR_NAME_EXP" },
935         { KRB5_ET_KRB5KDC_ERR_SERVICE_EXP, "KRB5KDC_ERR_SERVICE_EXP" },
936         { KRB5_ET_KRB5KDC_ERR_BAD_PVNO, "KRB5KDC_ERR_BAD_PVNO" },
937         { KRB5_ET_KRB5KDC_ERR_C_OLD_MAST_KVNO, "KRB5KDC_ERR_C_OLD_MAST_KVNO" },
938         { KRB5_ET_KRB5KDC_ERR_S_OLD_MAST_KVNO, "KRB5KDC_ERR_S_OLD_MAST_KVNO" },
939         { KRB5_ET_KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN, "KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN" },
940         { KRB5_ET_KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN, "KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN" },
941         { KRB5_ET_KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE, "KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE" },
942         { KRB5_ET_KRB5KDC_ERR_NULL_KEY, "KRB5KDC_ERR_NULL_KEY" },
943         { KRB5_ET_KRB5KDC_ERR_CANNOT_POSTDATE, "KRB5KDC_ERR_CANNOT_POSTDATE" },
944         { KRB5_ET_KRB5KDC_ERR_NEVER_VALID, "KRB5KDC_ERR_NEVER_VALID" },
945         { KRB5_ET_KRB5KDC_ERR_POLICY, "KRB5KDC_ERR_POLICY" },
946         { KRB5_ET_KRB5KDC_ERR_BADOPTION, "KRB5KDC_ERR_BADOPTION" },
947         { KRB5_ET_KRB5KDC_ERR_ETYPE_NOSUPP, "KRB5KDC_ERR_ETYPE_NOSUPP" },
948         { KRB5_ET_KRB5KDC_ERR_SUMTYPE_NOSUPP, "KRB5KDC_ERR_SUMTYPE_NOSUPP" },
949         { KRB5_ET_KRB5KDC_ERR_PADATA_TYPE_NOSUPP, "KRB5KDC_ERR_PADATA_TYPE_NOSUPP" },
950         { KRB5_ET_KRB5KDC_ERR_TRTYPE_NOSUPP, "KRB5KDC_ERR_TRTYPE_NOSUPP" },
951         { KRB5_ET_KRB5KDC_ERR_CLIENT_REVOKED, "KRB5KDC_ERR_CLIENT_REVOKED" },
952         { KRB5_ET_KRB5KDC_ERR_SERVICE_REVOKED, "KRB5KDC_ERR_SERVICE_REVOKED" },
953         { KRB5_ET_KRB5KDC_ERR_TGT_REVOKED, "KRB5KDC_ERR_TGT_REVOKED" },
954         { KRB5_ET_KRB5KDC_ERR_CLIENT_NOTYET, "KRB5KDC_ERR_CLIENT_NOTYET" },
955         { KRB5_ET_KRB5KDC_ERR_SERVICE_NOTYET, "KRB5KDC_ERR_SERVICE_NOTYET" },
956         { KRB5_ET_KRB5KDC_ERR_KEY_EXP, "KRB5KDC_ERR_KEY_EXP" },
957         { KRB5_ET_KRB5KDC_ERR_PREAUTH_FAILED, "KRB5KDC_ERR_PREAUTH_FAILED" },
958         { KRB5_ET_KRB5KDC_ERR_PREAUTH_REQUIRED, "KRB5KDC_ERR_PREAUTH_REQUIRED" },
959         { KRB5_ET_KRB5KDC_ERR_SERVER_NOMATCH, "KRB5KDC_ERR_SERVER_NOMATCH" },
960         { KRB5_ET_KRB5KDC_ERR_MUST_USE_USER2USER, "KRB5KDC_ERR_MUST_USE_USER2USER" },
961         { KRB5_ET_KRB5KDC_ERR_PATH_NOT_ACCEPTED, "KRB5KDC_ERR_PATH_NOT_ACCEPTED" },
962         { KRB5_ET_KRB5KDC_ERR_SVC_UNAVAILABLE, "KRB5KDC_ERR_SVC_UNAVAILABLE" },
963         { KRB5_ET_KRB5KRB_AP_ERR_BAD_INTEGRITY, "KRB5KRB_AP_ERR_BAD_INTEGRITY" },
964         { KRB5_ET_KRB5KRB_AP_ERR_TKT_EXPIRED, "KRB5KRB_AP_ERR_TKT_EXPIRED" },
965         { KRB5_ET_KRB5KRB_AP_ERR_TKT_NYV, "KRB5KRB_AP_ERR_TKT_NYV" },
966         { KRB5_ET_KRB5KRB_AP_ERR_REPEAT, "KRB5KRB_AP_ERR_REPEAT" },
967         { KRB5_ET_KRB5KRB_AP_ERR_NOT_US, "KRB5KRB_AP_ERR_NOT_US" },
968         { KRB5_ET_KRB5KRB_AP_ERR_BADMATCH, "KRB5KRB_AP_ERR_BADMATCH" },
969         { KRB5_ET_KRB5KRB_AP_ERR_SKEW, "KRB5KRB_AP_ERR_SKEW" },
970         { KRB5_ET_KRB5KRB_AP_ERR_BADADDR, "KRB5KRB_AP_ERR_BADADDR" },
971         { KRB5_ET_KRB5KRB_AP_ERR_BADVERSION, "KRB5KRB_AP_ERR_BADVERSION" },
972         { KRB5_ET_KRB5KRB_AP_ERR_MSG_TYPE, "KRB5KRB_AP_ERR_MSG_TYPE" },
973         { KRB5_ET_KRB5KRB_AP_ERR_MODIFIED, "KRB5KRB_AP_ERR_MODIFIED" },
974         { KRB5_ET_KRB5KRB_AP_ERR_BADORDER, "KRB5KRB_AP_ERR_BADORDER" },
975         { KRB5_ET_KRB5KRB_AP_ERR_ILL_CR_TKT, "KRB5KRB_AP_ERR_ILL_CR_TKT" },
976         { KRB5_ET_KRB5KRB_AP_ERR_BADKEYVER, "KRB5KRB_AP_ERR_BADKEYVER" },
977         { KRB5_ET_KRB5KRB_AP_ERR_NOKEY, "KRB5KRB_AP_ERR_NOKEY" },
978         { KRB5_ET_KRB5KRB_AP_ERR_MUT_FAIL, "KRB5KRB_AP_ERR_MUT_FAIL" },
979         { KRB5_ET_KRB5KRB_AP_ERR_BADDIRECTION, "KRB5KRB_AP_ERR_BADDIRECTION" },
980         { KRB5_ET_KRB5KRB_AP_ERR_METHOD, "KRB5KRB_AP_ERR_METHOD" },
981         { KRB5_ET_KRB5KRB_AP_ERR_BADSEQ, "KRB5KRB_AP_ERR_BADSEQ" },
982         { KRB5_ET_KRB5KRB_AP_ERR_INAPP_CKSUM, "KRB5KRB_AP_ERR_INAPP_CKSUM" },
983         { KRB5_ET_KRB5KDC_AP_PATH_NOT_ACCEPTED, "KRB5KDC_AP_PATH_NOT_ACCEPTED" },
984         { KRB5_ET_KRB5KRB_ERR_RESPONSE_TOO_BIG, "KRB5KRB_ERR_RESPONSE_TOO_BIG"},
985         { KRB5_ET_KRB5KRB_ERR_GENERIC, "KRB5KRB_ERR_GENERIC" },
986         { KRB5_ET_KRB5KRB_ERR_FIELD_TOOLONG, "KRB5KRB_ERR_FIELD_TOOLONG" },
987         { KRB5_ET_KDC_ERROR_CLIENT_NOT_TRUSTED, "KDC_ERROR_CLIENT_NOT_TRUSTED" },
988         { KRB5_ET_KDC_ERROR_KDC_NOT_TRUSTED, "KDC_ERROR_KDC_NOT_TRUSTED" },
989         { KRB5_ET_KDC_ERROR_INVALID_SIG, "KDC_ERROR_INVALID_SIG" },
990         { KRB5_ET_KDC_ERR_KEY_TOO_WEAK, "KDC_ERR_KEY_TOO_WEAK" },
991         { KRB5_ET_KDC_ERR_CERTIFICATE_MISMATCH, "KDC_ERR_CERTIFICATE_MISMATCH" },
992         { KRB5_ET_KRB_AP_ERR_NO_TGT, "KRB_AP_ERR_NO_TGT" },
993         { KRB5_ET_KDC_ERR_WRONG_REALM, "KDC_ERR_WRONG_REALM" },
994         { KRB5_ET_KRB_AP_ERR_USER_TO_USER_REQUIRED, "KRB_AP_ERR_USER_TO_USER_REQUIRED" },
995         { KRB5_ET_KDC_ERR_CANT_VERIFY_CERTIFICATE, "KDC_ERR_CANT_VERIFY_CERTIFICATE" },
996         { KRB5_ET_KDC_ERR_INVALID_CERTIFICATE, "KDC_ERR_INVALID_CERTIFICATE" },
997         { KRB5_ET_KDC_ERR_REVOKED_CERTIFICATE, "KDC_ERR_REVOKED_CERTIFICATE" },
998         { KRB5_ET_KDC_ERR_REVOCATION_STATUS_UNKNOWN, "KDC_ERR_REVOCATION_STATUS_UNKNOWN" },
999         { KRB5_ET_KDC_ERR_REVOCATION_STATUS_UNAVAILABLE, "KDC_ERR_REVOCATION_STATUS_UNAVAILABLE" },
1000         { KRB5_ET_KDC_ERR_CLIENT_NAME_MISMATCH, "KDC_ERR_CLIENT_NAME_MISMATCH" },
1001         { KRB5_ET_KDC_ERR_KDC_NAME_MISMATCH, "KDC_ERR_KDC_NAME_MISMATCH" },
1002         { 0, NULL }
1003 };
1004
1005
1006 #define PAC_LOGON_INFO          1
1007 #define PAC_CREDENTIAL_TYPE     2
1008 #define PAC_SERVER_CHECKSUM     6
1009 #define PAC_PRIVSVR_CHECKSUM    7
1010 #define PAC_CLIENT_INFO_TYPE    10
1011 #define PAC_S4U_DELEGATION_INFO 11
1012 #define PAC_UPN_DNS_INFO                12
1013 static const value_string w2k_pac_types[] = {
1014         { PAC_LOGON_INFO                , "Logon Info" },
1015         { PAC_CREDENTIAL_TYPE   , "Credential Type" },
1016         { PAC_SERVER_CHECKSUM   , "Server Checksum" },
1017         { PAC_PRIVSVR_CHECKSUM  , "Privsvr Checksum" },
1018         { PAC_CLIENT_INFO_TYPE  , "Client Info Type" },
1019         { PAC_S4U_DELEGATION_INFO, "S4U Delegation Info" },
1020         { PAC_UPN_DNS_INFO              , "UPN DNS Info" },
1021         { 0, NULL },
1022 };
1023
1024 static const value_string krb5_msg_types[] = {
1025         { KRB5_MSG_TICKET,              "Ticket" },
1026         { KRB5_MSG_AUTHENTICATOR,       "Authenticator" },
1027         { KRB5_MSG_ENC_TICKET_PART,     "EncTicketPart" },
1028         { KRB5_MSG_TGS_REQ,             "TGS-REQ" },
1029         { KRB5_MSG_TGS_REP,             "TGS-REP" },
1030         { KRB5_MSG_AS_REQ,              "AS-REQ" },
1031         { KRB5_MSG_AS_REP,              "AS-REP" },
1032         { KRB5_MSG_AP_REQ,              "AP-REQ" },
1033         { KRB5_MSG_AP_REP,              "AP-REP" },
1034         { KRB5_MSG_SAFE,                "KRB-SAFE" },
1035         { KRB5_MSG_PRIV,                "KRB-PRIV" },
1036         { KRB5_MSG_CRED,                "KRB-CRED" },
1037         { KRB5_MSG_ENC_AS_REP_PART,     "EncASRepPart" },
1038         { KRB5_MSG_ENC_TGS_REP_PART,    "EncTGSRepPart" },
1039         { KRB5_MSG_ENC_AP_REP_PART,     "EncAPRepPart" },
1040         { KRB5_MSG_ENC_KRB_PRIV_PART,   "EncKrbPrivPart" },
1041         { KRB5_MSG_ENC_KRB_CRED_PART,   "EncKrbCredPart" },
1042         { KRB5_MSG_ERROR,               "KRB-ERROR" },
1043         { 0, NULL },
1044 };
1045
1046 #define KRB5_GSS_C_DELEG_FLAG             0x01
1047 #define KRB5_GSS_C_MUTUAL_FLAG            0x02
1048 #define KRB5_GSS_C_REPLAY_FLAG            0x04
1049 #define KRB5_GSS_C_SEQUENCE_FLAG          0x08
1050 #define KRB5_GSS_C_CONF_FLAG              0x10
1051 #define KRB5_GSS_C_INTEG_FLAG             0x20
1052 #define KRB5_GSS_C_DCE_STYLE            0x1000
1053
1054 static const true_false_string tfs_gss_flags_deleg = {
1055         "Delegate credentials to remote peer",
1056         "Do NOT delegate"
1057 };
1058 static const true_false_string tfs_gss_flags_mutual = {
1059         "Request that remote peer authenticates itself",
1060         "Mutual authentication NOT required"
1061 };
1062 static const true_false_string tfs_gss_flags_replay = {
1063         "Enable replay protection for signed or sealed messages",
1064         "Do NOT enable replay protection"
1065 };
1066 static const true_false_string tfs_gss_flags_sequence = {
1067         "Enable Out-of-sequence detection for sign or sealed messages",
1068         "Do NOT enable out-of-sequence detection"
1069 };
1070 static const true_false_string tfs_gss_flags_conf = {
1071         "Confidentiality (sealing) may be invoked",
1072         "Do NOT use Confidentiality (sealing)"
1073 };
1074 static const true_false_string tfs_gss_flags_integ = {
1075         "Integrity protection (signing) may be invoked",
1076         "Do NOT use integrity protection"
1077 };
1078
1079 static const true_false_string tfs_gss_flags_dce_style = {
1080         "DCE-STYLE",
1081         "Not using DCE-STYLE"
1082 };
1083
1084 #ifdef HAVE_KERBEROS
1085 static int
1086 dissect_krb5_decrypt_ticket_data (gboolean imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
1087                                                                         proto_tree *tree, int hf_index _U_)
1088 {
1089         guint8 *plaintext;
1090         int length;
1091         kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
1092         tvbuff_t *next_tvb;
1093
1094         next_tvb=tvb_new_subset_remaining(tvb, offset);
1095         length=tvb_captured_length_remaining(tvb, offset);
1096
1097         /* draft-ietf-krb-wg-kerberos-clarifications-05.txt :
1098          * 7.5.1
1099          * All Ticket encrypted parts use usage == 2
1100          */
1101         plaintext=decrypt_krb5_data(tree, actx->pinfo, 2, next_tvb, private_data->etype, NULL);
1102
1103         if(plaintext){
1104                 tvbuff_t *child_tvb;
1105                 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
1106
1107                 /* Add the decrypted data to the data source list. */
1108                 add_new_data_source(actx->pinfo, child_tvb, "Decrypted Krb5");
1109
1110                 offset=dissect_kerberos_Applications(FALSE, child_tvb, 0, actx , tree, /* hf_index*/ -1);
1111         }
1112         return offset;
1113 }
1114
1115 static int
1116 dissect_krb5_decrypt_authenticator_data (gboolean imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
1117                                                                                         proto_tree *tree, int hf_index _U_)
1118 {
1119         guint8 *plaintext;
1120         int length;
1121         kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
1122         tvbuff_t *next_tvb;
1123
1124         next_tvb=tvb_new_subset_remaining(tvb, offset);
1125         length=tvb_captured_length_remaining(tvb, offset);
1126
1127         /* draft-ietf-krb-wg-kerberos-clarifications-05.txt :
1128          * 7.5.1
1129          * Authenticators are encrypted with usage
1130          * == 7 or
1131          * == 11
1132          */
1133         plaintext=decrypt_krb5_data(tree, actx->pinfo, 7, next_tvb, private_data->etype, NULL);
1134
1135         if(!plaintext){
1136                 plaintext=decrypt_krb5_data(tree, actx->pinfo, 11, next_tvb, private_data->etype, NULL);
1137         }
1138
1139         if(plaintext){
1140                 tvbuff_t *child_tvb;
1141                 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
1142
1143                 /* Add the decrypted data to the data source list. */
1144                 add_new_data_source(actx->pinfo, child_tvb, "Decrypted Krb5");
1145
1146                 offset=dissect_kerberos_Applications(FALSE, child_tvb, 0, actx , tree, /* hf_index*/ -1);
1147         }
1148         return offset;
1149 }
1150
1151 static int
1152 dissect_krb5_decrypt_KDC_REP_data (gboolean imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
1153                                                                         proto_tree *tree, int hf_index _U_)
1154 {
1155         guint8 *plaintext;
1156         int length;
1157         kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
1158         tvbuff_t *next_tvb;
1159
1160         next_tvb=tvb_new_subset_remaining(tvb, offset);
1161         length=tvb_captured_length_remaining(tvb, offset);
1162
1163         /* draft-ietf-krb-wg-kerberos-clarifications-05.txt :
1164          * 7.5.1
1165          * ASREP/TGSREP encryptedparts are encrypted with usage
1166          * == 3 or
1167          * == 8 or
1168          * == 9
1169          */
1170         plaintext=decrypt_krb5_data(tree, actx->pinfo, 3, next_tvb, private_data->etype, NULL);
1171
1172         if(!plaintext){
1173                 plaintext=decrypt_krb5_data(tree, actx->pinfo, 8, next_tvb, private_data->etype, NULL);
1174         }
1175
1176         if(!plaintext){
1177                 plaintext=decrypt_krb5_data(tree, actx->pinfo, 9, next_tvb, private_data->etype, NULL);
1178         }
1179
1180         if(plaintext){
1181                 tvbuff_t *child_tvb;
1182                 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
1183
1184                 /* Add the decrypted data to the data source list. */
1185                 add_new_data_source(actx->pinfo, child_tvb, "Decrypted Krb5");
1186
1187                 offset=dissect_kerberos_Applications(FALSE, child_tvb, 0, actx , tree, /* hf_index*/ -1);
1188         }
1189         return offset;
1190 }
1191
1192 static int
1193 dissect_krb5_decrypt_PA_ENC_TIMESTAMP (gboolean imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
1194                                                                                 proto_tree *tree, int hf_index _U_)
1195 {
1196         guint8 *plaintext;
1197         int length;
1198         kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
1199         tvbuff_t *next_tvb;
1200
1201         next_tvb=tvb_new_subset_remaining(tvb, offset);
1202         length=tvb_captured_length_remaining(tvb, offset);
1203
1204         /* draft-ietf-krb-wg-kerberos-clarifications-05.txt :
1205          * 7.5.1
1206          * AS-REQ PA_ENC_TIMESTAMP are encrypted with usage
1207          * == 1
1208          */
1209         plaintext=decrypt_krb5_data(tree, actx->pinfo, 1, next_tvb, private_data->etype, NULL);
1210
1211         if(plaintext){
1212                 tvbuff_t *child_tvb;
1213                 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
1214
1215                 /* Add the decrypted data to the data source list. */
1216                 add_new_data_source(actx->pinfo, child_tvb, "Decrypted Krb5");
1217
1218                 offset=dissect_kerberos_Applications(FALSE, child_tvb, 0, actx , tree, /* hf_index*/ -1);
1219         }
1220         return offset;
1221 }
1222
1223 static int
1224 dissect_krb5_decrypt_AP_REP_data (gboolean imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
1225                                                                         proto_tree *tree, int hf_index _U_)
1226 {
1227         guint8 *plaintext;
1228         int length;
1229         kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
1230         tvbuff_t *next_tvb;
1231
1232         next_tvb=tvb_new_subset_remaining(tvb, offset);
1233         length=tvb_captured_length_remaining(tvb, offset);
1234
1235         /* draft-ietf-krb-wg-kerberos-clarifications-05.txt :
1236          * 7.5.1
1237          * AP-REP are encrypted with usage == 12
1238          */
1239         plaintext=decrypt_krb5_data(tree, actx->pinfo, 12, next_tvb, private_data->etype, NULL);
1240
1241         if(plaintext){
1242                 tvbuff_t *child_tvb;
1243                 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
1244
1245                 /* Add the decrypted data to the data source list. */
1246                 add_new_data_source(actx->pinfo, child_tvb, "Decrypted Krb5");
1247
1248                 offset=dissect_kerberos_Applications(FALSE, child_tvb, 0, actx , tree, /* hf_index*/ -1);
1249         }
1250         return offset;
1251 }
1252
1253 static int
1254 dissect_krb5_decrypt_PRIV_data (gboolean imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
1255                                                                         proto_tree *tree, int hf_index _U_)
1256 {
1257         guint8 *plaintext;
1258         int length;
1259         kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
1260         tvbuff_t *next_tvb;
1261
1262         next_tvb=tvb_new_subset_remaining(tvb, offset);
1263         length=tvb_captured_length_remaining(tvb, offset);
1264
1265         /* RFC4120 :
1266          * EncKrbPrivPart encrypted with usage
1267          * == 13
1268          */
1269         plaintext=decrypt_krb5_data(tree, actx->pinfo, 13, next_tvb, private_data->etype, NULL);
1270
1271         if(plaintext){
1272                 tvbuff_t *child_tvb;
1273                 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
1274
1275                 /* Add the decrypted data to the data source list. */
1276                 add_new_data_source(actx->pinfo, child_tvb, "Decrypted Krb5");
1277
1278                 offset=dissect_kerberos_Applications(FALSE, child_tvb, 0, actx , tree, /* hf_index*/ -1);
1279         }
1280         return offset;
1281 }
1282
1283 static int
1284 dissect_krb5_decrypt_CRED_data (gboolean imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
1285                                                                         proto_tree *tree, int hf_index _U_)
1286 {
1287         guint8 *plaintext;
1288         int length;
1289         kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
1290         tvbuff_t *next_tvb;
1291
1292         next_tvb=tvb_new_subset_remaining(tvb, offset);
1293         length=tvb_captured_length_remaining(tvb, offset);
1294
1295         /* RFC4120 :
1296          * EncKrbCredPart encrypted with usage
1297          * == 14
1298          */
1299         plaintext=decrypt_krb5_data(tree, actx->pinfo, 14, next_tvb, private_data->etype, NULL);
1300
1301         if(plaintext){
1302                 tvbuff_t *child_tvb;
1303                 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
1304
1305                 /* Add the decrypted data to the data source list. */
1306                 add_new_data_source(actx->pinfo, child_tvb, "Decrypted Krb5");
1307
1308                 offset=dissect_kerberos_Applications(FALSE, child_tvb, 0, actx , tree, /* hf_index*/ -1);
1309         }
1310         return offset;
1311 }
1312 #endif
1313
1314 /* Dissect a GSSAPI checksum as per RFC1964. This is NOT ASN.1 encoded.
1315  */
1316 static int
1317 dissect_krb5_rfc1964_checksum(asn1_ctx_t *actx _U_, proto_tree *tree, tvbuff_t *tvb)
1318 {
1319         int offset=0;
1320         guint32 len;
1321         guint16 dlglen;
1322
1323         /* Length of Bnd field */
1324         len=tvb_get_letohl(tvb, offset);
1325         proto_tree_add_item(tree, hf_krb_gssapi_len, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1326         offset += 4;
1327
1328         /* Bnd field */
1329         proto_tree_add_item(tree, hf_krb_gssapi_bnd, tvb, offset, len, ENC_NA);
1330         offset += len;
1331
1332
1333         /* flags */
1334         proto_tree_add_item(tree, hf_krb_gssapi_c_flag_dce_style, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1335         proto_tree_add_item(tree, hf_krb_gssapi_c_flag_integ, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1336         proto_tree_add_item(tree, hf_krb_gssapi_c_flag_conf, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1337         proto_tree_add_item(tree, hf_krb_gssapi_c_flag_sequence, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1338         proto_tree_add_item(tree, hf_krb_gssapi_c_flag_replay, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1339         proto_tree_add_item(tree, hf_krb_gssapi_c_flag_mutual, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1340         proto_tree_add_item(tree, hf_krb_gssapi_c_flag_deleg, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1341         offset += 4;
1342
1343         /* the next fields are optional so we have to check that we have
1344          * more data in our buffers */
1345         if(tvb_reported_length_remaining(tvb, offset)<2){
1346                 return offset;
1347         }
1348         /* dlgopt identifier */
1349         proto_tree_add_item(tree, hf_krb_gssapi_dlgopt, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1350         offset += 2;
1351
1352         if(tvb_reported_length_remaining(tvb, offset)<2){
1353                 return offset;
1354         }
1355         /* dlglen identifier */
1356         dlglen=tvb_get_letohs(tvb, offset);
1357         proto_tree_add_item(tree, hf_krb_gssapi_dlglen, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1358         offset += 2;
1359
1360         if(dlglen!=tvb_reported_length_remaining(tvb, offset)){
1361                 proto_tree_add_expert_format(tree, actx->pinfo, &ei_krb_gssapi_dlglen, tvb, 0, 0,
1362                                 "Error: DlgLen:%d is not the same as number of bytes remaining:%d", dlglen, tvb_captured_length_remaining(tvb, offset));
1363                 return offset;
1364         }
1365
1366         /* this should now be a KRB_CRED message */
1367         offset=dissect_kerberos_Applications(FALSE, tvb, offset, actx, tree, /* hf_index */ -1);
1368
1369         return offset;
1370 }
1371
1372 static int
1373 dissect_krb5_PA_PROV_SRV_LOCATION(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_)
1374 {
1375         offset=dissect_ber_GeneralString(actx, tree, tvb, offset, hf_krb_provsrv_location, NULL, 0);
1376
1377         return offset;
1378 }
1379
1380 static int
1381 dissect_krb5_PW_SALT(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_)
1382 {
1383         guint32 nt_status;
1384
1385         /* Microsoft stores a special 12 byte blob here
1386          * guint32 NT_status
1387          * guint32 unknown
1388          * guint32 unknown
1389          * decode everything as this blob for now until we see if anyone
1390          * else ever uses it   or we learn how to tell whether this
1391          * is such an MS blob or not.
1392          */
1393         proto_tree_add_item(tree, hf_krb_smb_nt_status, tvb, offset, 4,
1394                         ENC_LITTLE_ENDIAN);
1395         nt_status=tvb_get_letohl(tvb, offset);
1396         if(nt_status) {
1397                 col_append_fstr(actx->pinfo->cinfo, COL_INFO,
1398                         " NT Status: %s",
1399                         val_to_str(nt_status, NT_errors,
1400                         "Unknown error code %#x"));
1401         }
1402         offset += 4;
1403
1404         proto_tree_add_item(tree, hf_krb_smb_unknown, tvb, offset, 4,
1405                         ENC_LITTLE_ENDIAN);
1406         offset += 4;
1407
1408         proto_tree_add_item(tree, hf_krb_smb_unknown, tvb, offset, 4,
1409                         ENC_LITTLE_ENDIAN);
1410         offset += 4;
1411
1412         return offset;
1413 }
1414
1415 static int
1416 dissect_krb5_PAC_DREP(proto_tree *parent_tree, tvbuff_t *tvb, int offset, guint8 *drep)
1417 {
1418         proto_tree *tree;
1419         guint8 val;
1420
1421         tree = proto_tree_add_subtree(parent_tree, tvb, offset, 16, ett_krb_pac_drep, NULL, "DREP");
1422
1423         val = tvb_get_guint8(tvb, offset);
1424         proto_tree_add_uint(tree, hf_dcerpc_drep_byteorder, tvb, offset, 1, val>>4);
1425
1426         offset++;
1427
1428         if (drep) {
1429                 *drep = val;
1430         }
1431
1432         return offset;
1433 }
1434
1435 /* This might be some sort of header that MIDL generates when creating
1436  * marshalling/unmarshalling code for blobs that are not to be transported
1437  * ontop of DCERPC and where the DREP fields specifying things such as
1438  * endianess and similar are not available.
1439  */
1440 static int
1441 dissect_krb5_PAC_NDRHEADERBLOB(proto_tree *parent_tree, tvbuff_t *tvb, int offset, guint8 *drep, asn1_ctx_t *actx _U_)
1442 {
1443         proto_tree *tree;
1444
1445         tree = proto_tree_add_subtree(parent_tree, tvb, offset, 16, ett_krb_pac_midl_blob, NULL, "MES header");
1446
1447         /* modified DREP field that is used for stuff that is transporetd ontop
1448            of non dcerpc
1449         */
1450         proto_tree_add_item(tree, hf_krb_midl_version, tvb, offset, 1, ENC_LITTLE_ENDIAN);
1451         offset++;
1452
1453         offset = dissect_krb5_PAC_DREP(tree, tvb, offset, drep);
1454
1455
1456         proto_tree_add_item(tree, hf_krb_midl_hdr_len, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1457         offset+=2;
1458
1459         proto_tree_add_item(tree, hf_krb_midl_fill_bytes, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1460         offset += 4;
1461
1462         /* length of blob that follows */
1463         proto_tree_add_item(tree, hf_krb_midl_blob_len, tvb, offset, 8, ENC_LITTLE_ENDIAN);
1464         offset += 8;
1465
1466         return offset;
1467 }
1468
1469 static int
1470 dissect_krb5_PAC_LOGON_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
1471 {
1472         proto_item *item;
1473         proto_tree *tree;
1474         guint8 drep[4] = { 0x10, 0x00, 0x00, 0x00}; /* fake DREP struct */
1475         static dcerpc_info di;      /* fake dcerpc_info struct */
1476         static dcerpc_call_value call_data;
1477
1478         item = proto_tree_add_item(parent_tree, hf_krb_pac_logon_info, tvb, offset, -1, ENC_NA);
1479         tree = proto_item_add_subtree(item, ett_krb_pac_logon_info);
1480
1481         /* skip the first 16 bytes, they are some magic created by the idl
1482          * compiler   the first 4 bytes might be flags?
1483          */
1484         offset = dissect_krb5_PAC_NDRHEADERBLOB(tree, tvb, offset, &drep[0], actx);
1485
1486         /* the PAC_LOGON_INFO blob */
1487         /* fake whatever state the dcerpc runtime support needs */
1488         di.conformant_run=0;
1489         /* we need di->call_data->flags.NDR64 == 0 */
1490         di.call_data=&call_data;
1491         init_ndr_pointer_list(&di);
1492         offset = dissect_ndr_pointer(tvb, offset, actx->pinfo, tree, &di, drep,
1493                                                                         netlogon_dissect_PAC_LOGON_INFO, NDR_POINTER_UNIQUE,
1494                                                                         "PAC_LOGON_INFO:", -1);
1495
1496         return offset;
1497 }
1498
1499 static int
1500 dissect_krb5_PAC_S4U_DELEGATION_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx)
1501 {
1502         proto_item *item;
1503         proto_tree *tree;
1504         guint8 drep[4] = { 0x10, 0x00, 0x00, 0x00}; /* fake DREP struct */
1505         static dcerpc_info di;      /* fake dcerpc_info struct */
1506         static dcerpc_call_value call_data;
1507
1508         item = proto_tree_add_item(parent_tree, hf_krb_pac_s4u_delegation_info, tvb, offset, -1, ENC_NA);
1509         tree = proto_item_add_subtree(item, ett_krb_pac_s4u_delegation_info);
1510
1511         /* skip the first 16 bytes, they are some magic created by the idl
1512          * compiler   the first 4 bytes might be flags?
1513          */
1514         offset = dissect_krb5_PAC_NDRHEADERBLOB(tree, tvb, offset, &drep[0], actx);
1515
1516
1517         /* the S4U_DELEGATION_INFO blob. See [MS-PAC] */
1518         /* fake whatever state the dcerpc runtime support needs */
1519         di.conformant_run=0;
1520         /* we need di->call_data->flags.NDR64 == 0 */
1521         di.call_data=&call_data;
1522         init_ndr_pointer_list(&di);
1523         offset = dissect_ndr_pointer(tvb, offset, actx->pinfo, tree, &di, drep,
1524                                                                         netlogon_dissect_PAC_S4U_DELEGATION_INFO, NDR_POINTER_UNIQUE,
1525                                                                         "PAC_S4U_DELEGATION_INFO:", -1);
1526
1527         return offset;
1528 }
1529
1530 static int
1531 dissect_krb5_PAC_UPN_DNS_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
1532 {
1533         proto_item *item;
1534         proto_tree *tree;
1535         guint16 dns_offset, dns_len;
1536         guint16 upn_offset, upn_len;
1537         const char *dn;
1538         int dn_len;
1539         guint16 bc;
1540
1541         item = proto_tree_add_item(parent_tree, hf_krb_pac_upn_dns_info, tvb, offset, -1, ENC_NA);
1542         tree = proto_item_add_subtree(item, ett_krb_pac_upn_dns_info);
1543
1544         /* upn */
1545         upn_len = tvb_get_letohs(tvb, offset);
1546         proto_tree_add_item(tree, hf_krb_pac_upn_upn_len, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1547         offset+=2;
1548         upn_offset = tvb_get_letohs(tvb, offset);
1549         proto_tree_add_item(tree, hf_krb_pac_upn_upn_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1550         offset+=2;
1551
1552         /* dns */
1553         dns_len = tvb_get_letohs(tvb, offset);
1554         proto_tree_add_item(tree, hf_krb_pac_upn_dns_len, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1555         offset+=2;
1556         dns_offset = tvb_get_letohs(tvb, offset);
1557         proto_tree_add_item(tree, hf_krb_pac_upn_dns_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
1558         offset+=2;
1559
1560         /* flags */
1561         proto_tree_add_item(tree, hf_krb_pac_upn_flags, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1562
1563         /* upn */
1564         offset = upn_offset;
1565         dn_len = upn_len;
1566         bc = tvb_reported_length_remaining(tvb, offset);
1567         dn = get_unicode_or_ascii_string(tvb, &offset, TRUE, &dn_len, TRUE, TRUE, &bc);
1568         proto_tree_add_string(tree, hf_krb_pac_upn_upn_name, tvb, upn_offset, upn_len, dn);
1569
1570         /* dns */
1571         offset = dns_offset;
1572         dn_len = dns_len;
1573         bc = tvb_reported_length_remaining(tvb, offset);
1574         dn = get_unicode_or_ascii_string(tvb, &offset, TRUE, &dn_len, TRUE, TRUE, &bc);
1575         proto_tree_add_string(tree, hf_krb_pac_upn_dns_name, tvb, dns_offset, dns_len, dn);
1576
1577         return offset;
1578 }
1579
1580 static int
1581 dissect_krb5_PAC_CREDENTIAL_TYPE(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
1582 {
1583         proto_tree_add_item(parent_tree, hf_krb_pac_credential_type, tvb, offset, -1, ENC_NA);
1584
1585         return offset;
1586 }
1587
1588 static int
1589 dissect_krb5_PAC_SERVER_CHECKSUM(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
1590 {
1591         proto_item *item;
1592         proto_tree *tree;
1593
1594         item = proto_tree_add_item(parent_tree, hf_krb_pac_server_checksum, tvb, offset, -1, ENC_NA);
1595         tree = proto_item_add_subtree(item, ett_krb_pac_server_checksum);
1596
1597         /* signature type */
1598         proto_tree_add_item(tree, hf_krb_pac_signature_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1599         offset+=4;
1600
1601         /* signature data */
1602         proto_tree_add_item(tree, hf_krb_pac_signature_signature, tvb, offset, -1, ENC_NA);
1603
1604         return offset;
1605 }
1606
1607 static int
1608 dissect_krb5_PAC_PRIVSVR_CHECKSUM(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
1609 {
1610         proto_item *item;
1611         proto_tree *tree;
1612
1613         item = proto_tree_add_item(parent_tree, hf_krb_pac_privsvr_checksum, tvb, offset, -1, ENC_NA);
1614         tree = proto_item_add_subtree(item, ett_krb_pac_privsvr_checksum);
1615
1616         /* signature type */
1617         proto_tree_add_item(tree, hf_krb_pac_signature_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
1618         offset+=4;
1619
1620         /* signature data */
1621         proto_tree_add_item(tree, hf_krb_pac_signature_signature, tvb, offset, -1, ENC_NA);
1622
1623         return offset;
1624 }
1625
1626 static int
1627 dissect_krb5_PAC_CLIENT_INFO_TYPE(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
1628 {
1629         proto_item *item;
1630         proto_tree *tree;
1631         guint16 namelen;
1632
1633         item = proto_tree_add_item(parent_tree, hf_krb_pac_client_info_type, tvb, offset, -1, ENC_NA);
1634         tree = proto_item_add_subtree(item, ett_krb_pac_client_info_type);
1635
1636         /* clientid */
1637         offset = dissect_nt_64bit_time(tvb, tree, offset, hf_krb_pac_clientid);
1638
1639         /* name length */
1640         namelen=tvb_get_letohs(tvb, offset);
1641         proto_tree_add_uint(tree, hf_krb_pac_namelen, tvb, offset, 2, namelen);
1642         offset+=2;
1643
1644         /* client name */
1645         proto_tree_add_item(tree, hf_krb_pac_clientname, tvb, offset, namelen, ENC_UTF_16|ENC_LITTLE_ENDIAN);
1646         offset+=namelen;
1647
1648         return offset;
1649 }
1650
1651 static int
1652 dissect_krb5_AD_WIN2K_PAC_struct(proto_tree *tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx)
1653 {
1654         guint32 pac_type;
1655         guint32 pac_size;
1656         guint32 pac_offset;
1657         proto_item *it=NULL;
1658         proto_tree *tr=NULL;
1659         tvbuff_t *next_tvb;
1660
1661         /* type of pac data */
1662         pac_type=tvb_get_letohl(tvb, offset);
1663         it=proto_tree_add_uint(tree, hf_krb_w2k_pac_type, tvb, offset, 4, pac_type);
1664         tr=proto_item_add_subtree(it, ett_krb_pac);
1665
1666         offset += 4;
1667
1668         /* size of pac data */
1669         pac_size=tvb_get_letohl(tvb, offset);
1670         proto_tree_add_uint(tr, hf_krb_w2k_pac_size, tvb, offset, 4, pac_size);
1671         offset += 4;
1672
1673         /* offset to pac data */
1674         pac_offset=tvb_get_letohl(tvb, offset);
1675         proto_tree_add_uint(tr, hf_krb_w2k_pac_offset, tvb, offset, 4, pac_offset);
1676         offset += 8;
1677
1678         next_tvb=tvb_new_subset_length_caplen(tvb, pac_offset, pac_size, pac_size);
1679         switch(pac_type){
1680         case PAC_LOGON_INFO:
1681                 dissect_krb5_PAC_LOGON_INFO(tr, next_tvb, 0, actx);
1682                 break;
1683         case PAC_CREDENTIAL_TYPE:
1684                 dissect_krb5_PAC_CREDENTIAL_TYPE(tr, next_tvb, 0, actx);
1685                 break;
1686         case PAC_SERVER_CHECKSUM:
1687                 dissect_krb5_PAC_SERVER_CHECKSUM(tr, next_tvb, 0, actx);
1688                 break;
1689         case PAC_PRIVSVR_CHECKSUM:
1690                 dissect_krb5_PAC_PRIVSVR_CHECKSUM(tr, next_tvb, 0, actx);
1691                 break;
1692         case PAC_CLIENT_INFO_TYPE:
1693                 dissect_krb5_PAC_CLIENT_INFO_TYPE(tr, next_tvb, 0, actx);
1694                 break;
1695         case PAC_S4U_DELEGATION_INFO:
1696                 dissect_krb5_PAC_S4U_DELEGATION_INFO(tr, next_tvb, 0, actx);
1697                 break;
1698         case PAC_UPN_DNS_INFO:
1699                 dissect_krb5_PAC_UPN_DNS_INFO(tr, next_tvb, 0, actx);
1700                 break;
1701
1702         default:
1703                 break;
1704         }
1705         return offset;
1706 }
1707
1708 static int
1709 dissect_krb5_AD_WIN2K_PAC(gboolean implicit_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index _U_)
1710 {
1711         guint32 entries;
1712         guint32 version;
1713         guint32 i;
1714
1715         /* first in the PAC structure comes the number of entries */
1716         entries=tvb_get_letohl(tvb, offset);
1717         proto_tree_add_uint(tree, hf_krb_w2k_pac_entries, tvb, offset, 4, entries);
1718         offset += 4;
1719
1720         /* second comes the version */
1721         version=tvb_get_letohl(tvb, offset);
1722         proto_tree_add_uint(tree, hf_krb_w2k_pac_version, tvb, offset, 4, version);
1723         offset += 4;
1724
1725         for(i=0;i<entries;i++){
1726                 offset=dissect_krb5_AD_WIN2K_PAC_struct(tree, tvb, offset, actx);
1727         }
1728
1729         return offset;
1730 }
1731
1732 #include "packet-kerberos-fn.c"
1733
1734 /* Make wrappers around exported functions for now */
1735 int
1736 dissect_krb5_Checksum(proto_tree *tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
1737 {
1738         return dissect_kerberos_Checksum(FALSE, tvb, offset, actx, tree, hf_kerberos_cksum);
1739
1740 }
1741
1742 int
1743 dissect_krb5_ctime(proto_tree *tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
1744 {
1745         return dissect_kerberos_KerberosTime(FALSE, tvb, offset, actx, tree, hf_kerberos_ctime);
1746 }
1747
1748
1749 int
1750 dissect_krb5_cname(proto_tree *tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
1751 {
1752         return dissect_kerberos_PrincipalName(FALSE, tvb, offset, actx, tree, hf_kerberos_cname);
1753 }
1754 int
1755 dissect_krb5_realm(proto_tree *tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
1756 {
1757         return dissect_kerberos_Realm(FALSE, tvb, offset, actx, tree, hf_kerberos_realm);
1758 }
1759
1760
1761 static gint
1762 dissect_kerberos_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1763     gboolean dci, gboolean do_col_protocol, gboolean have_rm,
1764     kerberos_callbacks *cb)
1765 {
1766         volatile int offset = 0;
1767         proto_tree *volatile kerberos_tree = NULL;
1768         proto_item *volatile item = NULL;
1769         asn1_ctx_t asn1_ctx;
1770
1771         /* TCP record mark and length */
1772         guint32 krb_rm = 0;
1773         gint krb_reclen = 0;
1774
1775         gbl_do_col_info=dci;
1776
1777         if (have_rm) {
1778                 krb_rm = tvb_get_ntohl(tvb, offset);
1779                 krb_reclen = kerberos_rm_to_reclen(krb_rm);
1780                 /*
1781                  * What is a reasonable size limit?
1782                  */
1783                 if (krb_reclen > 10 * 1024 * 1024) {
1784                         return (-1);
1785                 }
1786
1787                 if (do_col_protocol) {
1788                         col_set_str(pinfo->cinfo, COL_PROTOCOL, "KRB5");
1789                 }
1790
1791                 if (tree) {
1792                         item = proto_tree_add_item(tree, proto_kerberos, tvb, 0, -1, ENC_NA);
1793                         kerberos_tree = proto_item_add_subtree(item, ett_kerberos);
1794                 }
1795
1796                 show_krb_recordmark(kerberos_tree, tvb, offset, krb_rm);
1797                 offset += 4;
1798         } else {
1799                 /* Do some sanity checking here,
1800                  * All krb5 packets start with a TAG class that is BER_CLASS_APP
1801                  * and a tag value that is either of the values below:
1802                  * If it doesn't look like kerberos, return 0 and let someone else have
1803                  * a go at it.
1804                  */
1805                 gint8 tmp_class;
1806                 gboolean tmp_pc;
1807                 gint32 tmp_tag;
1808
1809                 get_ber_identifier(tvb, offset, &tmp_class, &tmp_pc, &tmp_tag);
1810                 if(tmp_class!=BER_CLASS_APP){
1811                         return 0;
1812                 }
1813                 switch(tmp_tag){
1814                         case KRB5_MSG_TICKET:
1815                         case KRB5_MSG_AUTHENTICATOR:
1816                         case KRB5_MSG_ENC_TICKET_PART:
1817                         case KRB5_MSG_AS_REQ:
1818                         case KRB5_MSG_AS_REP:
1819                         case KRB5_MSG_TGS_REQ:
1820                         case KRB5_MSG_TGS_REP:
1821                         case KRB5_MSG_AP_REQ:
1822                         case KRB5_MSG_AP_REP:
1823                         case KRB5_MSG_ENC_AS_REP_PART:
1824                         case KRB5_MSG_ENC_TGS_REP_PART:
1825                         case KRB5_MSG_ENC_AP_REP_PART:
1826                         case KRB5_MSG_ENC_KRB_PRIV_PART:
1827                         case KRB5_MSG_ENC_KRB_CRED_PART:
1828                         case KRB5_MSG_SAFE:
1829                         case KRB5_MSG_PRIV:
1830                         case KRB5_MSG_ERROR:
1831                                 break;
1832                         default:
1833                                 return 0;
1834                 }
1835                 if (do_col_protocol) {
1836                         col_set_str(pinfo->cinfo, COL_PROTOCOL, "KRB5");
1837                 }
1838                 if (gbl_do_col_info) {
1839                         col_clear(pinfo->cinfo, COL_INFO);
1840                 }
1841                 if (tree) {
1842                         item = proto_tree_add_item(tree, proto_kerberos, tvb, 0, -1, ENC_NA);
1843                         kerberos_tree = proto_item_add_subtree(item, ett_kerberos);
1844                 }
1845         }
1846         asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
1847         asn1_ctx.private_data = cb;
1848
1849         TRY {
1850                 offset=dissect_kerberos_Applications(FALSE, tvb, offset, &asn1_ctx , kerberos_tree, /* hf_index */ -1);
1851         } CATCH_BOUNDS_ERRORS {
1852                 RETHROW;
1853         } ENDTRY;
1854
1855         proto_item_set_len(item, offset);
1856         return offset;
1857 }
1858
1859 /*
1860  * Display the TCP record mark.
1861  */
1862 void
1863 show_krb_recordmark(proto_tree *tree, tvbuff_t *tvb, gint start, guint32 krb_rm)
1864 {
1865         gint rec_len;
1866         proto_tree *rm_tree;
1867
1868         if (tree == NULL)
1869                 return;
1870
1871         rec_len = kerberos_rm_to_reclen(krb_rm);
1872         rm_tree = proto_tree_add_subtree_format(tree, tvb, start, 4, ett_krb_recordmark, NULL,
1873                 "Record Mark: %u %s", rec_len, plurality(rec_len, "byte", "bytes"));
1874         proto_tree_add_boolean(rm_tree, hf_krb_rm_reserved, tvb, start, 4, krb_rm);
1875         proto_tree_add_uint(rm_tree, hf_krb_rm_reclen, tvb, start, 4, krb_rm);
1876 }
1877
1878 gint
1879 dissect_kerberos_main(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int do_col_info, kerberos_callbacks *cb)
1880 {
1881         return (dissect_kerberos_common(tvb, pinfo, tree, do_col_info, FALSE, FALSE, cb));
1882 }
1883
1884 guint32
1885 kerberos_output_keytype(void)
1886 {
1887         return gbl_keytype;
1888 }
1889
1890 static gint
1891 dissect_kerberos_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1892 {
1893         /* Some weird kerberos implementation apparently do krb4 on the krb5 port.
1894            Since all (except weirdo transarc krb4 stuff) use
1895            an opcode <=16 in the first byte, use this to see if it might
1896            be krb4.
1897            All krb5 commands start with an APPL tag and thus is >=0x60
1898            so if first byte is <=16  just blindly assume it is krb4 then
1899         */
1900         if(tvb_captured_length(tvb) >= 1 && tvb_get_guint8(tvb, 0)<=0x10){
1901                 if(krb4_handle){
1902                         gboolean res;
1903
1904                         res=call_dissector_only(krb4_handle, tvb, pinfo, tree, NULL);
1905                         return res;
1906                 }else{
1907                         return 0;
1908                 }
1909         }
1910
1911
1912         return dissect_kerberos_common(tvb, pinfo, tree, TRUE, TRUE, FALSE, NULL);
1913 }
1914
1915 gint
1916 kerberos_rm_to_reclen(guint krb_rm)
1917 {
1918     return (krb_rm & KRB_RM_RECLEN);
1919 }
1920
1921 guint
1922 get_krb_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
1923 {
1924         guint krb_rm;
1925         gint pdulen;
1926
1927         krb_rm = tvb_get_ntohl(tvb, offset);
1928         pdulen = kerberos_rm_to_reclen(krb_rm);
1929         return (pdulen + 4);
1930 }
1931 static void
1932 kerberos_prefs_apply_cb(void) {
1933 #ifdef HAVE_LIBNETTLE
1934         clear_keytab();
1935         read_keytab_file(keytab_filename);
1936 #endif
1937 }
1938
1939 static int
1940 dissect_kerberos_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1941 {
1942         pinfo->fragmented = TRUE;
1943         if (dissect_kerberos_common(tvb, pinfo, tree, TRUE, TRUE, TRUE, NULL) < 0) {
1944                 /*
1945                  * The dissector failed to recognize this as a valid
1946                  * Kerberos message.  Mark it as a continuation packet.
1947                  */
1948                 col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
1949         }
1950
1951         return tvb_captured_length(tvb);
1952 }
1953
1954 static int
1955 dissect_kerberos_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
1956 {
1957         col_set_str(pinfo->cinfo, COL_PROTOCOL, "KRB5");
1958         col_clear(pinfo->cinfo, COL_INFO);
1959
1960         tcp_dissect_pdus(tvb, pinfo, tree, krb_desegment, 4, get_krb_pdu_len,
1961                                          dissect_kerberos_tcp_pdu, data);
1962         return tvb_captured_length(tvb);
1963 }
1964
1965 /*--- proto_register_kerberos -------------------------------------------*/
1966 void proto_register_kerberos(void) {
1967
1968         /* List of fields */
1969
1970         static hf_register_info hf[] = {
1971         { &hf_krb_rm_reserved, {
1972                 "Reserved", "kerberos.rm.reserved", FT_BOOLEAN, 32,
1973                 TFS(&tfs_set_notset), KRB_RM_RESERVED, "Record mark reserved bit", HFILL }},
1974         { &hf_krb_rm_reclen, {
1975                 "Record Length", "kerberos.rm.length", FT_UINT32, BASE_DEC,
1976                 NULL, KRB_RM_RECLEN, NULL, HFILL }},
1977         { &hf_krb_provsrv_location, {
1978                 "PROVSRV Location", "kerberos.provsrv_location", FT_STRING, BASE_NONE,
1979                 NULL, 0, "PacketCable PROV SRV Location", HFILL }},
1980         { &hf_krb_smb_nt_status,
1981                 { "NT Status", "kerberos.smb.nt_status", FT_UINT32, BASE_HEX,
1982                 VALS(NT_errors), 0, "NT Status code", HFILL }},
1983         { &hf_krb_smb_unknown,
1984                 { "Unknown", "kerberos.smb.unknown", FT_UINT32, BASE_HEX,
1985                 NULL, 0, NULL, HFILL }},
1986         { &hf_krb_address_ip, {
1987                 "IP Address", "kerberos.addr_ip", FT_IPv4, BASE_NONE,
1988                 NULL, 0, NULL, HFILL }},
1989         { &hf_krb_address_ipv6, {
1990                 "IPv6 Address", "kerberos.addr_ipv6", FT_IPv6, BASE_NONE,
1991                 NULL, 0, NULL, HFILL }},
1992         { &hf_krb_address_netbios, {
1993                 "NetBIOS Address", "kerberos.addr_nb", FT_STRING, BASE_NONE,
1994                 NULL, 0, "NetBIOS Address and type", HFILL }},
1995         { &hf_krb_gssapi_len, {
1996                 "Length", "kerberos.gssapi.len", FT_UINT32, BASE_DEC,
1997                 NULL, 0, "Length of GSSAPI Bnd field", HFILL }},
1998         { &hf_krb_gssapi_bnd, {
1999                 "Bnd", "kerberos.gssapi.bdn", FT_BYTES, BASE_NONE,
2000                 NULL, 0, "GSSAPI Bnd field", HFILL }},
2001         { &hf_krb_gssapi_c_flag_deleg, {
2002                 "Deleg", "kerberos.gssapi.checksum.flags.deleg", FT_BOOLEAN, 32,
2003                 TFS(&tfs_gss_flags_deleg), KRB5_GSS_C_DELEG_FLAG, NULL, HFILL }},
2004         { &hf_krb_gssapi_c_flag_mutual, {
2005                 "Mutual", "kerberos.gssapi.checksum.flags.mutual", FT_BOOLEAN, 32,
2006                 TFS(&tfs_gss_flags_mutual), KRB5_GSS_C_MUTUAL_FLAG, NULL, HFILL }},
2007         { &hf_krb_gssapi_c_flag_replay, {
2008                 "Replay", "kerberos.gssapi.checksum.flags.replay", FT_BOOLEAN, 32,
2009                 TFS(&tfs_gss_flags_replay), KRB5_GSS_C_REPLAY_FLAG, NULL, HFILL }},
2010         { &hf_krb_gssapi_c_flag_sequence, {
2011                 "Sequence", "kerberos.gssapi.checksum.flags.sequence", FT_BOOLEAN, 32,
2012                 TFS(&tfs_gss_flags_sequence), KRB5_GSS_C_SEQUENCE_FLAG, NULL, HFILL }},
2013         { &hf_krb_gssapi_c_flag_conf, {
2014                 "Conf", "kerberos.gssapi.checksum.flags.conf", FT_BOOLEAN, 32,
2015                 TFS(&tfs_gss_flags_conf), KRB5_GSS_C_CONF_FLAG, NULL, HFILL }},
2016         { &hf_krb_gssapi_c_flag_integ, {
2017                 "Integ", "kerberos.gssapi.checksum.flags.integ", FT_BOOLEAN, 32,
2018                 TFS(&tfs_gss_flags_integ), KRB5_GSS_C_INTEG_FLAG, NULL, HFILL }},
2019         { &hf_krb_gssapi_c_flag_dce_style, {
2020                 "DCE-style", "kerberos.gssapi.checksum.flags.dce-style", FT_BOOLEAN, 32,
2021                 TFS(&tfs_gss_flags_dce_style), KRB5_GSS_C_DCE_STYLE, NULL, HFILL }},
2022         { &hf_krb_gssapi_dlgopt, {
2023                 "DlgOpt", "kerberos.gssapi.dlgopt", FT_UINT16, BASE_DEC,
2024                 NULL, 0, "GSSAPI DlgOpt", HFILL }},
2025         { &hf_krb_gssapi_dlglen, {
2026                 "DlgLen", "kerberos.gssapi.dlglen", FT_UINT16, BASE_DEC,
2027                 NULL, 0, "GSSAPI DlgLen", HFILL }},
2028         { &hf_krb_midl_blob_len, {
2029                 "Blob Length", "kerberos.midl_blob_len", FT_UINT64, BASE_DEC,
2030                 NULL, 0, "Length of NDR encoded data that follows", HFILL }},
2031         { &hf_krb_midl_fill_bytes, {
2032                 "Fill bytes", "kerberos.midl.fill_bytes", FT_UINT32, BASE_HEX,
2033                 NULL, 0, "Just some fill bytes", HFILL }},
2034         { &hf_krb_midl_version, {
2035         "Version", "kerberos.midl.version", FT_UINT8, BASE_DEC,
2036         NULL, 0, "Version of pickling", HFILL }},
2037         { &hf_krb_midl_hdr_len, {
2038                 "HDR Length", "kerberos.midl.hdr_len", FT_UINT16, BASE_DEC,
2039                 NULL, 0, "Length of header", HFILL }},
2040         { &hf_krb_pac_signature_type, {
2041                 "Type", "kerberos.pac.signature.type", FT_INT32, BASE_DEC,
2042                 NULL, 0, "PAC Signature Type", HFILL }},
2043         { &hf_krb_pac_signature_signature, {
2044                 "Signature", "kerberos.pac.signature.signature", FT_BYTES, BASE_NONE,
2045                 NULL, 0, "A PAC signature blob", HFILL }},
2046         { &hf_krb_w2k_pac_entries, {
2047                 "Num Entries", "kerberos.pac.entries", FT_UINT32, BASE_DEC,
2048                 NULL, 0, "Number of W2k PAC entries", HFILL }},
2049         { &hf_krb_w2k_pac_version, {
2050                 "Version", "kerberos.pac.version", FT_UINT32, BASE_DEC,
2051                 NULL, 0, "Version of PAC structures", HFILL }},
2052         { &hf_krb_w2k_pac_type, {
2053                 "Type", "kerberos.pac.type", FT_UINT32, BASE_DEC,
2054                 VALS(w2k_pac_types), 0, "Type of W2k PAC entry", HFILL }},
2055         { &hf_krb_w2k_pac_size, {
2056                 "Size", "kerberos.pac.size", FT_UINT32, BASE_DEC,
2057                 NULL, 0, "Size of W2k PAC entry", HFILL }},
2058         { &hf_krb_w2k_pac_offset, {
2059                 "Offset", "kerberos.pac.offset", FT_UINT32, BASE_DEC,
2060                 NULL, 0, "Offset to W2k PAC entry", HFILL }},
2061         { &hf_krb_pac_clientid, {
2062                 "ClientID", "kerberos.pac.clientid", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL,
2063                 NULL, 0, "ClientID Timestamp", HFILL }},
2064         { &hf_krb_pac_namelen, {
2065                 "Name Length", "kerberos.pac.namelen", FT_UINT16, BASE_DEC,
2066                 NULL, 0, "Length of client name", HFILL }},
2067         { &hf_krb_pac_clientname, {
2068                 "Name", "kerberos.pac.name", FT_STRING, BASE_NONE,
2069                 NULL, 0, "Name of the Client in the PAC structure", HFILL }},
2070         { &hf_krb_pac_logon_info, {
2071                 "PAC_LOGON_INFO", "kerberos.pac_logon_info", FT_BYTES, BASE_NONE,
2072                 NULL, 0, "PAC_LOGON_INFO structure", HFILL }},
2073         { &hf_krb_pac_credential_type, {
2074                 "PAC_CREDENTIAL_TYPE", "kerberos.pac_credential_type", FT_BYTES, BASE_NONE,
2075                 NULL, 0, "PAC_CREDENTIAL_TYPE structure", HFILL }},
2076         { &hf_krb_pac_server_checksum, {
2077                 "PAC_SERVER_CHECKSUM", "kerberos.pac_server_checksum", FT_BYTES, BASE_NONE,
2078                 NULL, 0, "PAC_SERVER_CHECKSUM structure", HFILL }},
2079         { &hf_krb_pac_privsvr_checksum, {
2080                 "PAC_PRIVSVR_CHECKSUM", "kerberos.pac_privsvr_checksum", FT_BYTES, BASE_NONE,
2081                 NULL, 0, "PAC_PRIVSVR_CHECKSUM structure", HFILL }},
2082         { &hf_krb_pac_client_info_type, {
2083                 "PAC_CLIENT_INFO_TYPE", "kerberos.pac_client_info_type", FT_BYTES, BASE_NONE,
2084                 NULL, 0, "PAC_CLIENT_INFO_TYPE structure", HFILL }},
2085         { &hf_krb_pac_s4u_delegation_info, {
2086                 "PAC_S4U_DELEGATION_INFO", "kerberos.pac_s4u_delegation_info", FT_BYTES, BASE_NONE,
2087                 NULL, 0, "PAC_S4U_DELEGATION_INFO structure", HFILL }},
2088         { &hf_krb_pac_upn_dns_info, {
2089                 "UPN_DNS_INFO", "kerberos.pac_upn_dns_info", FT_BYTES, BASE_NONE,
2090                 NULL, 0, "UPN_DNS_INFO structure", HFILL }},
2091         { &hf_krb_pac_upn_flags, {
2092                 "Flags", "kerberos.pac.upn.flags", FT_UINT32, BASE_HEX,
2093                 NULL, 0, "UPN flags", HFILL }},
2094         { &hf_krb_pac_upn_dns_offset, {
2095                 "DNS Offset", "kerberos.pac.upn.dns_offset", FT_UINT16, BASE_DEC,
2096                 NULL, 0, NULL, HFILL }},
2097         { &hf_krb_pac_upn_dns_len, {
2098                 "DNS Len", "kerberos.pac.upn.dns_len", FT_UINT16, BASE_DEC,
2099                 NULL, 0, NULL, HFILL }},
2100         { &hf_krb_pac_upn_upn_offset, {
2101                 "UPN Offset", "kerberos.pac.upn.upn_offset", FT_UINT16, BASE_DEC,
2102                 NULL, 0, NULL, HFILL }},
2103         { &hf_krb_pac_upn_upn_len, {
2104                 "UPN Len", "kerberos.pac.upn.upn_len", FT_UINT16, BASE_DEC,
2105                 NULL, 0, NULL, HFILL }},
2106         { &hf_krb_pac_upn_upn_name, {
2107                 "UPN Name", "kerberos.pac.upn.upn_name", FT_STRING, BASE_NONE,
2108                 NULL, 0, NULL, HFILL }},
2109         { &hf_krb_pac_upn_dns_name, {
2110                 "DNS Name", "kerberos.pac.upn.dns_name", FT_STRING, BASE_NONE,
2111                 NULL, 0, NULL, HFILL }},
2112
2113 #include "packet-kerberos-hfarr.c"
2114         };
2115
2116         /* List of subtrees */
2117         static gint *ett[] = {
2118                 &ett_kerberos,
2119                 &ett_krb_recordmark,
2120                 &ett_krb_pac,
2121                 &ett_krb_pac_drep,
2122                 &ett_krb_pac_midl_blob,
2123                 &ett_krb_pac_logon_info,
2124                 &ett_krb_pac_s4u_delegation_info,
2125                 &ett_krb_pac_upn_dns_info,
2126                 &ett_krb_pac_server_checksum,
2127                 &ett_krb_pac_privsvr_checksum,
2128                 &ett_krb_pac_client_info_type,
2129 #include "packet-kerberos-ettarr.c"
2130         };
2131
2132         static ei_register_info ei[] = {
2133                 { &ei_kerberos_decrypted_keytype, { "kerberos.decrypted_keytype", PI_SECURITY, PI_CHAT, "Decryted keytype", EXPFILL }},
2134                 { &ei_kerberos_address, { "kerberos.address.unknown", PI_UNDECODED, PI_WARN, "KRB Address: I don't know how to parse this type of address yet", EXPFILL }},
2135                 { &ei_krb_gssapi_dlglen, { "kerberos.gssapi.dlglen.error", PI_MALFORMED, PI_ERROR, "DlgLen is not the same as number of bytes remaining", EXPFILL }},
2136         };
2137
2138         expert_module_t* expert_krb;
2139         module_t *krb_module;
2140
2141         proto_kerberos = proto_register_protocol("Kerberos", "KRB5", "kerberos");
2142         proto_register_field_array(proto_kerberos, hf, array_length(hf));
2143         proto_register_subtree_array(ett, array_length(ett));
2144         expert_krb = expert_register_protocol(proto_kerberos);
2145         expert_register_field_array(expert_krb, ei, array_length(ei));
2146
2147         /* Register preferences */
2148         krb_module = prefs_register_protocol(proto_kerberos, kerberos_prefs_apply_cb);
2149         prefs_register_bool_preference(krb_module, "desegment",
2150         "Reassemble Kerberos over TCP messages spanning multiple TCP segments",
2151         "Whether the Kerberos dissector should reassemble messages spanning multiple TCP segments."
2152         " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
2153         &krb_desegment);
2154 #ifdef HAVE_KERBEROS
2155         prefs_register_bool_preference(krb_module, "decrypt",
2156         "Try to decrypt Kerberos blobs",
2157         "Whether the dissector should try to decrypt "
2158         "encrypted Kerberos blobs. This requires that the proper "
2159         "keytab file is installed as well.", &krb_decrypt);
2160
2161         prefs_register_filename_preference(krb_module, "file",
2162                                    "Kerberos keytab file",
2163                                    "The keytab file containing all the secrets",
2164                                    &keytab_filename, FALSE);
2165 #endif
2166
2167 }
2168 static int wrap_dissect_gss_kerb(tvbuff_t *tvb, int offset, packet_info *pinfo,
2169                                  proto_tree *tree, dcerpc_info *di _U_,guint8 *drep _U_)
2170 {
2171         tvbuff_t *auth_tvb;
2172
2173         auth_tvb = tvb_new_subset_remaining(tvb, offset);
2174
2175         dissect_kerberos_main(auth_tvb, pinfo, tree, FALSE, NULL);
2176
2177         return tvb_captured_length_remaining(tvb, offset);
2178 }
2179
2180
2181 static dcerpc_auth_subdissector_fns gss_kerb_auth_connect_fns = {
2182         wrap_dissect_gss_kerb,                      /* Bind */
2183         wrap_dissect_gss_kerb,                      /* Bind ACK */
2184         wrap_dissect_gss_kerb,                      /* AUTH3 */
2185         NULL,                                       /* Request verifier */
2186         NULL,                                       /* Response verifier */
2187         NULL,                                       /* Request data */
2188         NULL                                        /* Response data */
2189 };
2190
2191 static dcerpc_auth_subdissector_fns gss_kerb_auth_sign_fns = {
2192         wrap_dissect_gss_kerb,                      /* Bind */
2193         wrap_dissect_gss_kerb,                      /* Bind ACK */
2194         wrap_dissect_gss_kerb,                      /* AUTH3 */
2195         wrap_dissect_gssapi_verf,                   /* Request verifier */
2196         wrap_dissect_gssapi_verf,                   /* Response verifier */
2197         NULL,                                       /* Request data */
2198         NULL                                        /* Response data */
2199 };
2200
2201 static dcerpc_auth_subdissector_fns gss_kerb_auth_seal_fns = {
2202         wrap_dissect_gss_kerb,                      /* Bind */
2203         wrap_dissect_gss_kerb,                      /* Bind ACK */
2204         wrap_dissect_gss_kerb,                      /* AUTH3 */
2205         wrap_dissect_gssapi_verf,                   /* Request verifier */
2206         wrap_dissect_gssapi_verf,                   /* Response verifier */
2207         wrap_dissect_gssapi_payload,                /* Request data */
2208         wrap_dissect_gssapi_payload                 /* Response data */
2209 };
2210
2211
2212
2213 void
2214 proto_reg_handoff_kerberos(void)
2215 {
2216         dissector_handle_t kerberos_handle_tcp;
2217
2218         krb4_handle = find_dissector_add_dependency("krb4", proto_kerberos);
2219
2220         kerberos_handle_udp = create_dissector_handle(dissect_kerberos_udp,
2221         proto_kerberos);
2222
2223         kerberos_handle_tcp = create_dissector_handle(dissect_kerberos_tcp,
2224         proto_kerberos);
2225
2226         dissector_add_uint_with_preference("udp.port", UDP_PORT_KERBEROS, kerberos_handle_udp);
2227         dissector_add_uint_with_preference("tcp.port", TCP_PORT_KERBEROS, kerberos_handle_tcp);
2228
2229         register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_CONNECT,
2230                                                                           DCE_C_RPC_AUTHN_PROTOCOL_GSS_KERBEROS,
2231                                                                           &gss_kerb_auth_connect_fns);
2232
2233         register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_INTEGRITY,
2234                                                                           DCE_C_RPC_AUTHN_PROTOCOL_GSS_KERBEROS,
2235                                                                           &gss_kerb_auth_sign_fns);
2236
2237         register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_PRIVACY,
2238                                                                           DCE_C_RPC_AUTHN_PROTOCOL_GSS_KERBEROS,
2239                                                                           &gss_kerb_auth_seal_fns);
2240 }
2241
2242 /*
2243  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
2244  *
2245  * Local variables:
2246  * c-basic-offset: 8
2247  * tab-width: 8
2248  * indent-tabs-mode: t
2249  * End:
2250  *
2251  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
2252  * :indentSize=8:tabSize=8:noTabs=false:
2253  */