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