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
sanitize_length(length, ds)13  *
14  *	http://clifford.neuman.name/krb-revisions/
15  *
16  * and
17  *
18  *	https://tools.ietf.org/html/draft-ietf-krb-wg-kerberos-clarifications-07
19  *
20  * and
21  *
22  *  https://tools.ietf.org/html/draft-ietf-krb-wg-kerberos-referrals-05
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 // krb5.h needs to be included before the defines in packet-kerberos.h
48 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
49 #ifdef _WIN32
50 /* prevent redefinition warnings in krb5's win-mac.h */
51 #define SSIZE_T_DEFINED
52 #endif /* _WIN32 */
53 #include <krb5.h>
54 #endif
55 
56 #include <epan/packet.h>
57 #include <epan/exceptions.h>
58 #include <epan/strutil.h>
59 #include <epan/conversation.h>
60 #include <epan/asn1.h>
61 #include <epan/expert.h>
62 #include <epan/prefs.h>
63 #include <wsutil/wsgcrypt.h>
64 #include <wsutil/file_util.h>
65 #include <wsutil/str_util.h>
66 #include <wsutil/pint.h>
67 #include "packet-kerberos.h"
68 #include "packet-netbios.h"
69 #include "packet-tcp.h"
70 #include "packet-ber.h"
71 #include "packet-pkinit.h"
72 #include "packet-cms.h"
73 #include "packet-windows-common.h"
74 
75 #include "read_keytab_file.h"
76 
77 #include "packet-dcerpc-netlogon.h"
78 #include "packet-dcerpc.h"
79 
80 #include "packet-gssapi.h"
81 #include "packet-x509af.h"
82 
83 #define KEY_USAGE_FAST_REQ_CHKSUM       50
84 #define KEY_USAGE_FAST_ENC              51
85 #define KEY_USAGE_FAST_REP              52
86 #define KEY_USAGE_FAST_FINISHED         53
87 #define KEY_USAGE_ENC_CHALLENGE_CLIENT  54
88 #define KEY_USAGE_ENC_CHALLENGE_KDC     55
89 
90 void proto_register_kerberos(void);
91 void proto_reg_handoff_kerberos(void);
92 
93 #define UDP_PORT_KERBEROS		88
94 #define TCP_PORT_KERBEROS		88
95 
96 #define ADDRESS_STR_BUFSIZ 256
97 
98 typedef struct kerberos_key {
99 	guint32 keytype;
100 	int keylength;
101 	const guint8 *keyvalue;
102 } kerberos_key_t;
103 
104 typedef void (*kerberos_key_save_fn)(tvbuff_t *tvb _U_, int offset _U_, int length _U_,
105 				     asn1_ctx_t *actx _U_, proto_tree *tree _U_,
106 				     int parent_hf_index _U_,
107 				     int hf_index _U_);
108 
109 typedef struct {
110 	guint32 msg_type;
111 	gboolean is_win2k_pkinit;
112 	guint32 errorcode;
113 	gboolean try_nt_status;
114 	guint32 etype;
115 	guint32 padata_type;
116 	guint32 is_enc_padata;
117 	guint32 enctype;
118 	kerberos_key_t key;
119 	proto_tree *key_tree;
120 	proto_item *key_hidden_item;
121 	tvbuff_t *key_tvb;
122 	kerberos_callbacks *callbacks;
123 	guint32 ad_type;
124 	guint32 addr_type;
125 	guint32 checksum_type;
126 #ifdef HAVE_KERBEROS
127 	enc_key_t *last_decryption_key;
128 	enc_key_t *last_added_key;
129 	tvbuff_t *last_ticket_enc_part_tvb;
130 #endif
131 	gint save_encryption_key_parent_hf_index;
132 	kerberos_key_save_fn save_encryption_key_fn;
133 	guint learnt_key_ids;
134 	guint missing_key_ids;
135 	wmem_list_t *decryption_keys;
136 	wmem_list_t *learnt_keys;
137 	wmem_list_t *missing_keys;
138 	guint32 within_PA_TGS_REQ;
139 #ifdef HAVE_KERBEROS
140 	enc_key_t *PA_TGS_REQ_key;
141 	enc_key_t *PA_TGS_REQ_subkey;
142 #endif
143 	guint32 fast_type;
144 	guint32 fast_armor_within_armor_value;
145 #ifdef HAVE_KERBEROS
146 	enc_key_t *PA_FAST_ARMOR_AP_key;
147 	enc_key_t *PA_FAST_ARMOR_AP_subkey;
148 	enc_key_t *fast_armor_key;
149 	enc_key_t *fast_strengthen_key;
150 #endif
151 } kerberos_private_data_t;
152 
153 static dissector_handle_t kerberos_handle_udp;
154 
155 /* Forward declarations */
156 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_);
157 static int dissect_kerberos_AuthorizationData(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
158 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_);
159 #ifdef HAVE_KERBEROS
160 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_);
161 #endif
162 static int dissect_kerberos_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_);
163 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_);
164 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_);
165 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_);
166 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_);
167 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_);
168 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_);
169 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_);
170 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_);
171 static int dissect_kerberos_PA_KERB_KEY_LIST_REQ(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
172 static int dissect_kerberos_PA_KERB_KEY_LIST_REP(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
173 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_);
174 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_);
175 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_);
176 static int dissect_kerberos_SEQUENCE_OF_ENCTYPE(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
177 static int dissect_kerberos_PA_SPAKE(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
178 #ifdef HAVE_KERBEROS
179 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_);
180 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_);
181 static int dissect_kerberos_FastOptions(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
182 #endif
183 
184 /* Desegment Kerberos over TCP messages */
185 static gboolean krb_desegment = TRUE;
186 
187 static gint proto_kerberos = -1;
188 
189 static gint hf_krb_rm_reserved = -1;
190 static gint hf_krb_rm_reclen = -1;
191 static gint hf_krb_provsrv_location = -1;
192 static gint hf_krb_pw_salt = -1;
193 static gint hf_krb_ext_error_nt_status = -1;
194 static gint hf_krb_ext_error_reserved = -1;
195 static gint hf_krb_ext_error_flags = -1;
196 static gint hf_krb_address_ip = -1;
197 static gint hf_krb_address_netbios = -1;
198 static gint hf_krb_address_ipv6 = -1;
199 static gint hf_krb_gssapi_len = -1;
200 static gint hf_krb_gssapi_bnd = -1;
201 static gint hf_krb_gssapi_dlgopt = -1;
202 static gint hf_krb_gssapi_dlglen = -1;
203 static gint hf_krb_gssapi_c_flag_deleg = -1;
204 static gint hf_krb_gssapi_c_flag_mutual = -1;
205 static gint hf_krb_gssapi_c_flag_replay = -1;
206 static gint hf_krb_gssapi_c_flag_sequence = -1;
207 static gint hf_krb_gssapi_c_flag_conf = -1;
208 static gint hf_krb_gssapi_c_flag_integ = -1;
209 static gint hf_krb_gssapi_c_flag_dce_style = -1;
210 static gint hf_krb_midl_version = -1;
211 static gint hf_krb_midl_hdr_len = -1;
212 static gint hf_krb_midl_fill_bytes = -1;
213 static gint hf_krb_midl_blob_len = -1;
214 static gint hf_krb_pac_signature_type = -1;
215 static gint hf_krb_pac_signature_signature = -1;
216 static gint hf_krb_w2k_pac_entries = -1;
217 static gint hf_krb_w2k_pac_version = -1;
218 static gint hf_krb_w2k_pac_type = -1;
219 static gint hf_krb_w2k_pac_size = -1;
220 static gint hf_krb_w2k_pac_offset = -1;
221 static gint hf_krb_pac_clientid = -1;
222 static gint hf_krb_pac_namelen = -1;
223 static gint hf_krb_pac_clientname = -1;
224 static gint hf_krb_pac_logon_info = -1;
225 static gint hf_krb_pac_credential_data = -1;
226 static gint hf_krb_pac_credential_info = -1;
227 static gint hf_krb_pac_credential_info_version = -1;
228 static gint hf_krb_pac_credential_info_etype = -1;
229 static gint hf_krb_pac_s4u_delegation_info = -1;
230 static gint hf_krb_pac_upn_dns_info = -1;
231 static gint hf_krb_pac_upn_flags = -1;
232 static gint hf_krb_pac_upn_dns_offset = -1;
233 static gint hf_krb_pac_upn_dns_len = -1;
234 static gint hf_krb_pac_upn_upn_offset = -1;
235 static gint hf_krb_pac_upn_upn_len = -1;
236 static gint hf_krb_pac_upn_upn_name = -1;
237 static gint hf_krb_pac_upn_dns_name = -1;
238 static gint hf_krb_pac_server_checksum = -1;
239 static gint hf_krb_pac_privsvr_checksum = -1;
240 static gint hf_krb_pac_client_info_type = -1;
241 static gint hf_krb_pac_client_claims_info = -1;
242 static gint hf_krb_pac_device_info = -1;
243 static gint hf_krb_pac_device_claims_info = -1;
244 static gint hf_krb_pac_ticket_checksum = -1;
245 static gint hf_krb_pa_supported_enctypes = -1;
246 static gint hf_krb_pa_supported_enctypes_des_cbc_crc = -1;
247 static gint hf_krb_pa_supported_enctypes_des_cbc_md5 = -1;
248 static gint hf_krb_pa_supported_enctypes_rc4_hmac = -1;
249 static gint hf_krb_pa_supported_enctypes_aes128_cts_hmac_sha1_96 = -1;
250 static gint hf_krb_pa_supported_enctypes_aes256_cts_hmac_sha1_96 = -1;
251 static gint hf_krb_pa_supported_enctypes_fast_supported = -1;
252 static gint hf_krb_pa_supported_enctypes_compound_identity_supported = -1;
253 static gint hf_krb_pa_supported_enctypes_claims_supported = -1;
254 static gint hf_krb_pa_supported_enctypes_resource_sid_compression_disabled = -1;
255 static gint hf_krb_ad_ap_options = -1;
256 static gint hf_krb_ad_ap_options_cbt = -1;
257 static gint hf_krb_ad_target_principal = -1;
258 static gint hf_krb_key_hidden_item = -1;
259 static gint hf_kerberos_KERB_TICKET_LOGON = -1;
260 static gint hf_kerberos_KERB_TICKET_LOGON_MessageType = -1;
261 static gint hf_kerberos_KERB_TICKET_LOGON_Flags = -1;
262 static gint hf_kerberos_KERB_TICKET_LOGON_ServiceTicketLength = -1;
263 static gint hf_kerberos_KERB_TICKET_LOGON_TicketGrantingTicketLength = -1;
264 static gint hf_kerberos_KERB_TICKET_LOGON_ServiceTicket = -1;
265 static gint hf_kerberos_KERB_TICKET_LOGON_TicketGrantingTicket = -1;
266 static gint hf_kerberos_KERB_TICKET_LOGON_FLAG_ALLOW_EXPIRED_TICKET = -1;
267 static gint hf_kerberos_KERB_TICKET_LOGON_FLAG_REDIRECTED = -1;
268 #ifdef HAVE_KERBEROS
269 static gint hf_kerberos_KrbFastResponse = -1;
270 static gint hf_kerberos_strengthen_key = -1;
271 static gint hf_kerberos_finished = -1;
272 static gint hf_kerberos_fast_options = -1;
273 static gint hf_kerberos_ticket_checksum = -1;
274 static gint hf_krb_patimestamp = -1;
275 static gint hf_krb_pausec = -1;
276 static gint hf_kerberos_FastOptions_reserved = -1;
277 static gint hf_kerberos_FastOptions_hide_client_names = -1;
278 static gint hf_kerberos_FastOptions_spare_bit2 = -1;
279 static gint hf_kerberos_FastOptions_spare_bit3 = -1;
280 static gint hf_kerberos_FastOptions_spare_bit4 = -1;
281 static gint hf_kerberos_FastOptions_spare_bit5 = -1;
282 static gint hf_kerberos_FastOptions_spare_bit6 = -1;
283 static gint hf_kerberos_FastOptions_spare_bit7 = -1;
284 static gint hf_kerberos_FastOptions_spare_bit8 = -1;
285 static gint hf_kerberos_FastOptions_spare_bit9 = -1;
286 static gint hf_kerberos_FastOptions_spare_bit10 = -1;
287 static gint hf_kerberos_FastOptions_spare_bit11 = -1;
288 static gint hf_kerberos_FastOptions_spare_bit12 = -1;
289 static gint hf_kerberos_FastOptions_spare_bit13 = -1;
290 static gint hf_kerberos_FastOptions_spare_bit14 = -1;
291 static gint hf_kerberos_FastOptions_spare_bit15 = -1;
292 static gint hf_kerberos_FastOptions_kdc_follow_referrals = -1;
293 
294 #endif
295 #include "packet-kerberos-hf.c"
296 
297 /* Initialize the subtree pointers */
298 static gint ett_kerberos = -1;
299 static gint ett_krb_recordmark = -1;
300 static gint ett_krb_pac = -1;
301 static gint ett_krb_pac_drep = -1;
302 static gint ett_krb_pac_midl_blob = -1;
303 static gint ett_krb_pac_logon_info = -1;
304 static gint ett_krb_pac_credential_info = -1;
305 static gint ett_krb_pac_s4u_delegation_info = -1;
306 static gint ett_krb_pac_upn_dns_info = -1;
307 static gint ett_krb_pac_device_info = -1;
308 static gint ett_krb_pac_server_checksum = -1;
309 static gint ett_krb_pac_privsvr_checksum = -1;
310 static gint ett_krb_pac_client_info_type = -1;
311 static gint ett_krb_pac_ticket_checksum = -1;
312 static gint ett_krb_pa_supported_enctypes = -1;
313 static gint ett_krb_ad_ap_options = -1;
314 static gint ett_kerberos_KERB_TICKET_LOGON = -1;
315 #ifdef HAVE_KERBEROS
316 static gint ett_krb_pa_enc_ts_enc = -1;
317 static gint ett_kerberos_KrbFastFinished = -1;
318 static gint ett_kerberos_KrbFastResponse = -1;
319 static gint ett_kerberos_KrbFastReq = -1;
320 static gint ett_kerberos_FastOptions = -1;
321 #endif
322 #include "packet-kerberos-ett.c"
323 
324 static expert_field ei_kerberos_missing_keytype = EI_INIT;
325 static expert_field ei_kerberos_decrypted_keytype = EI_INIT;
326 static expert_field ei_kerberos_learnt_keytype = EI_INIT;
327 static expert_field ei_kerberos_address = EI_INIT;
328 static expert_field ei_krb_gssapi_dlglen = EI_INIT;
329 
330 static dissector_handle_t krb4_handle=NULL;
331 
332 /* Global variables */
333 static guint32 gbl_keytype;
334 static gboolean gbl_do_col_info;
335 
336 #include "packet-kerberos-val.h"
337 
338 static void
339 call_kerberos_callbacks(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int tag, kerberos_callbacks *cb)
340 {
341 	if(!cb){
342 		return;
343 	}
344 
345 	while(cb->tag){
346 		if(cb->tag==tag){
347 			cb->callback(pinfo, tvb, tree);
348 			return;
349 		}
350 		cb++;
351 	}
352 	return;
353 }
354 
355 static kerberos_private_data_t*
356 kerberos_new_private_data(packet_info *pinfo)
357 {
358 	kerberos_private_data_t *p;
359 
360 	p = wmem_new0(pinfo->pool, kerberos_private_data_t);
361 	if (p == NULL) {
362 		return NULL;
363 	}
364 
365 	p->decryption_keys = wmem_list_new(pinfo->pool);
366 	p->learnt_keys = wmem_list_new(pinfo->pool);
367 	p->missing_keys = wmem_list_new(pinfo->pool);
368 
369 	return p;
370 }
371 
372 static kerberos_private_data_t*
373 kerberos_get_private_data(asn1_ctx_t *actx)
374 {
375 	if (!actx->private_data) {
376 		actx->private_data = kerberos_new_private_data(actx->pinfo);
377 	}
378 	return (kerberos_private_data_t *)(actx->private_data);
379 }
380 
381 static gboolean
382 kerberos_private_is_kdc_req(kerberos_private_data_t *private_data)
383 {
384 	switch (private_data->msg_type) {
385 	case KERBEROS_APPLICATIONS_AS_REQ:
386 	case KERBEROS_APPLICATIONS_TGS_REQ:
387 		return TRUE;
388 	}
389 
390 	return FALSE;
391 }
392 
393 gboolean
394 kerberos_is_win2k_pkinit(asn1_ctx_t *actx)
395 {
396 	kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
397 
398 	return private_data->is_win2k_pkinit;
399 }
400 
401 #ifdef HAVE_KERBEROS
402 
403 /* Decrypt Kerberos blobs */
404 gboolean krb_decrypt = FALSE;
405 
406 /* keytab filename */
407 static const char *keytab_filename = "";
408 
409 void
410 read_keytab_file_from_preferences(void)
411 {
412 	static char *last_keytab = NULL;
413 
414 	if (!krb_decrypt) {
415 		return;
416 	}
417 
418 	if (keytab_filename == NULL) {
419 		return;
420 	}
421 
422 	if (last_keytab && !strcmp(last_keytab, keytab_filename)) {
423 		return;
424 	}
425 
426 	g_free(last_keytab);
427 	last_keytab = g_strdup(keytab_filename);
428 
429 	read_keytab_file(last_keytab);
430 }
431 #endif /* HAVE_KERBEROS */
432 
433 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
434 enc_key_t *enc_key_list=NULL;
435 static guint kerberos_longterm_ids = 0;
436 wmem_map_t *kerberos_longterm_keys = NULL;
437 static wmem_map_t *kerberos_all_keys = NULL;
438 static wmem_map_t *kerberos_app_session_keys = NULL;
439 
440 static gboolean
441 enc_key_list_cb(wmem_allocator_t* allocator _U_, wmem_cb_event_t event _U_, void *user_data _U_)
442 {
443 	enc_key_list = NULL;
444 	kerberos_longterm_ids = 0;
445 	/* keep the callback registered */
446 	return TRUE;
447 }
448 
449 static gint enc_key_cmp_id(gconstpointer k1, gconstpointer k2)
450 {
451 	const enc_key_t *key1 = (const enc_key_t *)k1;
452 	const enc_key_t *key2 = (const enc_key_t *)k2;
453 
454 	if (key1->fd_num < key2->fd_num) {
455 		return -1;
456 	}
457 	if (key1->fd_num > key2->fd_num) {
458 		return 1;
459 	}
460 
461 	if (key1->id < key2->id) {
462 		return -1;
463 	}
464 	if (key1->id > key2->id) {
465 		return 1;
466 	}
467 
468 	return 0;
469 }
470 
471 static gboolean
472 enc_key_content_equal(gconstpointer k1, gconstpointer k2)
473 {
474 	const enc_key_t *key1 = (const enc_key_t *)k1;
475 	const enc_key_t *key2 = (const enc_key_t *)k2;
476 	int cmp;
477 
478 	if (key1->keytype != key2->keytype) {
479 		return FALSE;
480 	}
481 
482 	if (key1->keylength != key2->keylength) {
483 		return FALSE;
484 	}
485 
486 	cmp = memcmp(key1->keyvalue, key2->keyvalue, key1->keylength);
487 	if (cmp != 0) {
488 		return FALSE;
489 	}
490 
491 	return TRUE;
492 }
493 
494 static guint
495 enc_key_content_hash(gconstpointer k)
496 {
497 	const enc_key_t *key = (const enc_key_t *)k;
498 	guint ret = 0;
499 
500 	ret += wmem_strong_hash((const guint8 *)&key->keytype,
501 				sizeof(key->keytype));
502 	ret += wmem_strong_hash((const guint8 *)&key->keylength,
503 				sizeof(key->keylength));
504 	ret += wmem_strong_hash((const guint8 *)key->keyvalue,
505 				key->keylength);
506 
507 	return ret;
508 }
509 
510 static void
511 kerberos_key_map_insert(wmem_map_t *key_map, enc_key_t *new_key)
512 {
513 	enc_key_t *existing = NULL;
514 	enc_key_t *cur = NULL;
515 	gint cmp;
516 
517 	existing = (enc_key_t *)wmem_map_lookup(key_map, new_key);
518 	if (existing == NULL) {
519 		wmem_map_insert(key_map, new_key, new_key);
520 		return;
521 	}
522 
523 	if (key_map != kerberos_all_keys) {
524 		/*
525 		 * It should already be linked to the existing key...
526 		 */
527 		return;
528 	}
529 
530 	if (existing->fd_num == -1 && new_key->fd_num != -1) {
531 		/*
532 		 * We can't reference a learnt key
533 		 * from a longterm key. As they have
534 		 * a shorter lifetime.
535 		 *
536 		 * So just let the learnt key remember the
537 		 * match.
538 		 */
539 		new_key->same_list = existing;
540 		new_key->num_same = existing->num_same + 1;
541 		return;
542 	}
543 
544 	/*
545 	 * If a key with the same content (keytype,keylength,keyvalue)
546 	 * already exists, we want the earliest key to be
547 	 * in the list.
548 	 */
549 	cmp = enc_key_cmp_id(new_key, existing);
550 	if (cmp == 0) {
551 		/*
552 		 * It's the same, nothing to do...
553 		 */
554 		return;
555 	}
556 	if (cmp < 0) {
557 		/* The new key has should be added to the list. */
558 		new_key->same_list = existing;
559 		new_key->num_same = existing->num_same + 1;
560 		wmem_map_insert(key_map, new_key, new_key);
561 		return;
562 	}
563 
564 	/*
565 	 * We want to link the new_key to the existing one.
566 	 *
567 	 * But we want keep the list sorted, so we need to forward
568 	 * to the correct spot.
569 	 */
570 	for (cur = existing; cur->same_list != NULL; cur = cur->same_list) {
571 		cmp = enc_key_cmp_id(new_key, cur->same_list);
572 		if (cmp == 0) {
573 			/*
574 			 * It's the same, nothing to do...
575 			 */
576 			return;
577 		}
578 
579 		if (cmp < 0) {
580 			/*
581 			 * We found the correct spot,
582 			 * the new_key should added
583 			 * between existing and existing->same_list
584 			 */
585 			new_key->same_list = cur->same_list;
586 			new_key->num_same = cur->num_same;
587 			break;
588 		}
589 	}
590 
591 	/*
592 	 * finally link new_key to existing
593 	 * and fix up the numbers
594 	 */
595 	cur->same_list = new_key;
596 	for (cur = existing; cur != new_key; cur = cur->same_list) {
597 		cur->num_same += 1;
598 	}
599 
600 	return;
601 }
602 
603 struct insert_longterm_keys_into_key_map_state {
604 	wmem_map_t *key_map;
605 };
606 
607 static void insert_longterm_keys_into_key_map_cb(gpointer __key _U_,
608 						 gpointer value,
609 						 gpointer user_data)
610 {
611 	struct insert_longterm_keys_into_key_map_state *state =
612 		(struct insert_longterm_keys_into_key_map_state *)user_data;
613 	enc_key_t *key = (enc_key_t *)value;
614 
615 	kerberos_key_map_insert(state->key_map, key);
616 }
617 
618 static void insert_longterm_keys_into_key_map(wmem_map_t *key_map)
619 {
620 	/*
621 	 * Because the kerberos_longterm_keys are allocated on
622 	 * wmem_epan_scope() and kerberos_all_keys are allocated
623 	 * on wmem_file_scope(), we need to plug the longterm keys
624 	 * back to kerberos_all_keys if a new file was loaded
625 	 * and wmem_file_scope() got cleared.
626 	 */
627 	if (wmem_map_size(key_map) < wmem_map_size(kerberos_longterm_keys)) {
628 		struct insert_longterm_keys_into_key_map_state state = {
629 			.key_map = key_map,
630 		};
631 		/*
632 		 * Reference all longterm keys into kerberos_all_keys
633 		 */
634 		wmem_map_foreach(kerberos_longterm_keys,
635 				 insert_longterm_keys_into_key_map_cb,
636 				 &state);
637 	}
638 }
639 
640 static void
641 kerberos_key_list_append(wmem_list_t *key_list, enc_key_t *new_key)
642 {
643 	enc_key_t *existing = NULL;
644 
645 	existing = (enc_key_t *)wmem_list_find(key_list, new_key);
646 	if (existing != NULL) {
647 		return;
648 	}
649 
650 	wmem_list_append(key_list, new_key);
651 }
652 
653 static void
654 add_encryption_key(packet_info *pinfo,
655 		   kerberos_private_data_t *private_data,
656 		   proto_tree *key_tree,
657 		   proto_item *key_hidden_item,
658 		   tvbuff_t *key_tvb,
659 		   int keytype, int keylength, const char *keyvalue,
660 		   const char *origin,
661 		   enc_key_t *src1, enc_key_t *src2)
662 {
663 	wmem_allocator_t *key_scope = NULL;
664 	enc_key_t *new_key = NULL;
665 	const char *methodl = "learnt";
666 	const char *methodu = "Learnt";
667 	proto_item *item = NULL;
668 
669 	private_data->last_added_key = NULL;
670 
671 	if (src1 != NULL && src2 != NULL) {
672 		methodl = "derived";
673 		methodu = "Derived";
674 	}
675 
676 	if(pinfo->fd->visited){
677 		/*
678 		 * We already processed this,
679 		 * we can use a shortterm scope
680 		 */
681 		key_scope = pinfo->pool;
682 	} else {
683 		/*
684 		 * As long as we have enc_key_list, we need to
685 		 * use wmem_epan_scope(), when that's gone
686 		 * we can dynamically select the scope based on
687 		 * how long we'll need the particular key.
688 		 */
689 		key_scope = wmem_epan_scope();
690 	}
691 
692 	new_key = wmem_new0(key_scope, enc_key_t);
693 	g_snprintf(new_key->key_origin, KRB_MAX_ORIG_LEN, "%s %s in frame %u",
694 		   methodl, origin, pinfo->num);
695 	new_key->fd_num = pinfo->num;
696 	new_key->id = ++private_data->learnt_key_ids;
697 	g_snprintf(new_key->id_str, KRB_MAX_ID_STR_LEN, "%d.%u",
698 		   new_key->fd_num, new_key->id);
699 	new_key->keytype=keytype;
700 	new_key->keylength=keylength;
701 	memcpy(new_key->keyvalue, keyvalue, MIN(keylength, KRB_MAX_KEY_LENGTH));
702 	new_key->src1 = src1;
703 	new_key->src2 = src2;
704 
705 	if(!pinfo->fd->visited){
706 		/*
707 		 * Only keep it if we don't processed it before.
708 		 */
709 		new_key->next=enc_key_list;
710 		enc_key_list=new_key;
711 		insert_longterm_keys_into_key_map(kerberos_all_keys);
712 		kerberos_key_map_insert(kerberos_all_keys, new_key);
713 	}
714 
715 	item = proto_tree_add_expert_format(key_tree, pinfo, &ei_kerberos_learnt_keytype,
716 			key_tvb, 0, keylength,
717 			"%s %s keytype %d (id=%d.%u) (%02x%02x%02x%02x...)",
718 			methodu, origin, keytype, pinfo->num, new_key->id,
719 			keyvalue[0] & 0xFF, keyvalue[1] & 0xFF,
720 			keyvalue[2] & 0xFF, keyvalue[3] & 0xFF);
721 	if (item != NULL && key_hidden_item != NULL) {
722 		proto_tree_move_item(key_tree, key_hidden_item, item);
723 	}
724 	if (src1 != NULL) {
725 		enc_key_t *sek = src1;
726 		expert_add_info_format(pinfo, item, &ei_kerberos_learnt_keytype,
727 				       "SRC1 %s keytype %d (id=%s same=%u) (%02x%02x%02x%02x...)",
728 				       sek->key_origin, sek->keytype,
729 				       sek->id_str, sek->num_same,
730 				       sek->keyvalue[0] & 0xFF, sek->keyvalue[1] & 0xFF,
731 				       sek->keyvalue[2] & 0xFF, sek->keyvalue[3] & 0xFF);
732 	}
733 	if (src2 != NULL) {
734 		enc_key_t *sek = src2;
735 		expert_add_info_format(pinfo, item, &ei_kerberos_learnt_keytype,
736 				       "SRC2 %s keytype %d (id=%s same=%u) (%02x%02x%02x%02x...)",
737 				       sek->key_origin, sek->keytype,
738 				       sek->id_str, sek->num_same,
739 				       sek->keyvalue[0] & 0xFF, sek->keyvalue[1] & 0xFF,
740 				       sek->keyvalue[2] & 0xFF, sek->keyvalue[3] & 0xFF);
741 	}
742 
743 	kerberos_key_list_append(private_data->learnt_keys, new_key);
744 	private_data->last_added_key = new_key;
745 }
746 
747 static void
748 save_encryption_key(tvbuff_t *tvb _U_, int offset _U_, int length _U_,
749 		    asn1_ctx_t *actx _U_, proto_tree *tree _U_,
750 		    int parent_hf_index _U_,
751 		    int hf_index _U_)
752 {
753 	kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
754 	const char *parent = proto_registrar_get_name(parent_hf_index);
755 	const char *element = proto_registrar_get_name(hf_index);
756 	char origin[KRB_MAX_ORIG_LEN] = { 0, };
757 
758 	g_snprintf(origin, KRB_MAX_ORIG_LEN, "%s_%s", parent, element);
759 
760 	add_encryption_key(actx->pinfo,
761 			   private_data,
762 			   private_data->key_tree,
763 			   private_data->key_hidden_item,
764 			   private_data->key_tvb,
765 			   private_data->key.keytype,
766 			   private_data->key.keylength,
767 			   private_data->key.keyvalue,
768 			   origin,
769 			   NULL,
770 			   NULL);
771 }
772 
773 static void
774 save_Authenticator_subkey(tvbuff_t *tvb, int offset, int length,
775 			  asn1_ctx_t *actx, proto_tree *tree,
776 			  int parent_hf_index,
777 			  int hf_index)
778 {
779 	kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
780 
781 	save_encryption_key(tvb, offset, length, actx, tree, parent_hf_index, hf_index);
782 
783 	if (private_data->last_decryption_key == NULL) {
784 		return;
785 	}
786 	if (private_data->last_added_key == NULL) {
787 		return;
788 	}
789 
790 	if (private_data->within_PA_TGS_REQ != 0) {
791 		private_data->PA_TGS_REQ_key = private_data->last_decryption_key;
792 		private_data->PA_TGS_REQ_subkey = private_data->last_added_key;
793 	}
794 	if (private_data->fast_armor_within_armor_value != 0) {
795 		private_data->PA_FAST_ARMOR_AP_key = private_data->last_decryption_key;
796 		private_data->PA_FAST_ARMOR_AP_subkey = private_data->last_added_key;
797 	}
798 }
799 
800 static void
801 save_EncAPRepPart_subkey(tvbuff_t *tvb, int offset, int length,
802 			 asn1_ctx_t *actx, proto_tree *tree,
803 			 int parent_hf_index,
804 			 int hf_index)
805 {
806 	kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
807 
808 	save_encryption_key(tvb, offset, length, actx, tree, parent_hf_index, hf_index);
809 
810 	if (actx->pinfo->fd->visited) {
811 		return;
812 	}
813 
814 	if (private_data->last_added_key == NULL) {
815 		return;
816 	}
817 
818 	kerberos_key_map_insert(kerberos_app_session_keys, private_data->last_added_key);
819 }
820 
821 static void
822 save_EncKDCRepPart_key(tvbuff_t *tvb, int offset, int length,
823 		       asn1_ctx_t *actx, proto_tree *tree,
824 		       int parent_hf_index,
825 		       int hf_index)
826 {
827 	save_encryption_key(tvb, offset, length, actx, tree, parent_hf_index, hf_index);
828 }
829 
830 static void
831 save_EncTicketPart_key(tvbuff_t *tvb, int offset, int length,
832 		       asn1_ctx_t *actx, proto_tree *tree,
833 		       int parent_hf_index,
834 		       int hf_index)
835 {
836 	save_encryption_key(tvb, offset, length, actx, tree, parent_hf_index, hf_index);
837 }
838 
839 static void
840 save_KrbCredInfo_key(tvbuff_t *tvb, int offset, int length,
841 		     asn1_ctx_t *actx, proto_tree *tree,
842 		     int parent_hf_index,
843 		     int hf_index)
844 {
845 	save_encryption_key(tvb, offset, length, actx, tree, parent_hf_index, hf_index);
846 }
847 
848 static void
849 save_KrbFastResponse_strengthen_key(tvbuff_t *tvb, int offset, int length,
850 				    asn1_ctx_t *actx, proto_tree *tree,
851 				    int parent_hf_index,
852 				    int hf_index)
853 {
854 	kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
855 
856 	save_encryption_key(tvb, offset, length, actx, tree, parent_hf_index, hf_index);
857 
858 	private_data->fast_strengthen_key = private_data->last_added_key;
859 }
860 
861 static void used_encryption_key(proto_tree *tree, packet_info *pinfo,
862 				kerberos_private_data_t *private_data,
863 				enc_key_t *ek, int usage, tvbuff_t *cryptotvb,
864 				const char *keymap_name,
865 				guint keymap_size,
866 				guint decryption_count)
867 {
868 	proto_item *item = NULL;
869 	enc_key_t *sek = NULL;
870 
871 	item = proto_tree_add_expert_format(tree, pinfo, &ei_kerberos_decrypted_keytype,
872 				     cryptotvb, 0, 0,
873 				     "Decrypted keytype %d usage %d "
874 				     "using %s (id=%s same=%u) (%02x%02x%02x%02x...)",
875 				     ek->keytype, usage, ek->key_origin, ek->id_str, ek->num_same,
876 				     ek->keyvalue[0] & 0xFF, ek->keyvalue[1] & 0xFF,
877 				     ek->keyvalue[2] & 0xFF, ek->keyvalue[3] & 0xFF);
878 	expert_add_info_format(pinfo, item, &ei_kerberos_decrypted_keytype,
879 			       "Used keymap=%s num_keys=%u num_tries=%u)",
880 			       keymap_name,
881 			       keymap_size,
882 			       decryption_count);
883 	if (ek->src1 != NULL) {
884 		sek = ek->src1;
885 		expert_add_info_format(pinfo, item, &ei_kerberos_decrypted_keytype,
886 				       "SRC1 %s keytype %d (id=%s same=%u) (%02x%02x%02x%02x...)",
887 				       sek->key_origin, sek->keytype,
888 				       sek->id_str, sek->num_same,
889 				       sek->keyvalue[0] & 0xFF, sek->keyvalue[1] & 0xFF,
890 				       sek->keyvalue[2] & 0xFF, sek->keyvalue[3] & 0xFF);
891 	}
892 	if (ek->src2 != NULL) {
893 		sek = ek->src2;
894 		expert_add_info_format(pinfo, item, &ei_kerberos_decrypted_keytype,
895 				       "SRC2 %s keytype %d (id=%s same=%u) (%02x%02x%02x%02x...)",
896 				       sek->key_origin, sek->keytype,
897 				       sek->id_str, sek->num_same,
898 				       sek->keyvalue[0] & 0xFF, sek->keyvalue[1] & 0xFF,
899 				       sek->keyvalue[2] & 0xFF, sek->keyvalue[3] & 0xFF);
900 	}
901 	sek = ek->same_list;
902 	while (sek != NULL) {
903 		expert_add_info_format(pinfo, item, &ei_kerberos_decrypted_keytype,
904 				       "Decrypted keytype %d usage %d "
905 				       "using %s (id=%s same=%u) (%02x%02x%02x%02x...)",
906 				       sek->keytype, usage, sek->key_origin, sek->id_str, sek->num_same,
907 				       sek->keyvalue[0] & 0xFF, sek->keyvalue[1] & 0xFF,
908 				       sek->keyvalue[2] & 0xFF, sek->keyvalue[3] & 0xFF);
909 		sek = sek->same_list;
910 	}
911 	kerberos_key_list_append(private_data->decryption_keys, ek);
912 	private_data->last_decryption_key = ek;
913 }
914 #endif /* HAVE_HEIMDAL_KERBEROS || HAVE_MIT_KERBEROS */
915 
916 #ifdef HAVE_MIT_KERBEROS
917 
918 static void missing_encryption_key(proto_tree *tree, packet_info *pinfo,
919 				   kerberos_private_data_t *private_data,
920 				   int keytype, int usage, tvbuff_t *cryptotvb,
921 				   const char *keymap_name,
922 				   guint keymap_size,
923 				   guint decryption_count)
924 {
925 	proto_item *item = NULL;
926 	enc_key_t *mek = NULL;
927 
928 	mek = wmem_new0(pinfo->pool, enc_key_t);
929 	g_snprintf(mek->key_origin, KRB_MAX_ORIG_LEN,
930 		   "keytype %d usage %d missing in frame %u",
931 		   keytype, usage, pinfo->num);
932 	mek->fd_num = pinfo->num;
933 	mek->id = ++private_data->missing_key_ids;
934 	g_snprintf(mek->id_str, KRB_MAX_ID_STR_LEN, "missing.%u",
935 		   mek->id);
936 	mek->keytype=keytype;
937 
938 	item = proto_tree_add_expert_format(tree, pinfo, &ei_kerberos_missing_keytype,
939 					    cryptotvb, 0, 0,
940 					    "Missing keytype %d usage %d (id=%s)",
941 					    keytype, usage, mek->id_str);
942 	expert_add_info_format(pinfo, item, &ei_kerberos_missing_keytype,
943 			       "Used keymap=%s num_keys=%u num_tries=%u)",
944 			       keymap_name,
945 			       keymap_size,
946 			       decryption_count);
947 
948 	kerberos_key_list_append(private_data->missing_keys, mek);
949 }
950 
951 #ifdef HAVE_KRB5_PAC_VERIFY
952 static void used_signing_key(proto_tree *tree, packet_info *pinfo,
953 			     kerberos_private_data_t *private_data,
954 			     enc_key_t *ek, tvbuff_t *tvb,
955 			     krb5_cksumtype checksum,
956 			     const char *reason,
957 			     const char *keymap_name,
958 			     guint keymap_size,
959 			     guint verify_count)
960 {
961 	proto_item *item = NULL;
962 	enc_key_t *sek = NULL;
963 
964 	item = proto_tree_add_expert_format(tree, pinfo, &ei_kerberos_decrypted_keytype,
965 				     tvb, 0, 0,
966 				     "%s checksum %d keytype %d "
967 				     "using %s (id=%s same=%u) (%02x%02x%02x%02x...)",
968 				     reason, checksum, ek->keytype, ek->key_origin,
969 				     ek->id_str, ek->num_same,
970 				     ek->keyvalue[0] & 0xFF, ek->keyvalue[1] & 0xFF,
971 				     ek->keyvalue[2] & 0xFF, ek->keyvalue[3] & 0xFF);
972 	expert_add_info_format(pinfo, item, &ei_kerberos_decrypted_keytype,
973 			       "Used keymap=%s num_keys=%u num_tries=%u)",
974 			       keymap_name,
975 			       keymap_size,
976 			       verify_count);
977 	sek = ek->same_list;
978 	while (sek != NULL) {
979 		expert_add_info_format(pinfo, item, &ei_kerberos_decrypted_keytype,
980 				       "%s checksum %d keytype %d "
981 				       "using %s (id=%s same=%u) (%02x%02x%02x%02x...)",
982 				       reason, checksum, sek->keytype, sek->key_origin,
983 				       sek->id_str, sek->num_same,
984 				       sek->keyvalue[0] & 0xFF, sek->keyvalue[1] & 0xFF,
985 				       sek->keyvalue[2] & 0xFF, sek->keyvalue[3] & 0xFF);
986 		sek = sek->same_list;
987 	}
988 	kerberos_key_list_append(private_data->decryption_keys, ek);
989 }
990 
991 static void missing_signing_key(proto_tree *tree, packet_info *pinfo,
992 				kerberos_private_data_t *private_data,
993 				tvbuff_t *tvb,
994 				krb5_cksumtype checksum,
995 				int keytype,
996 				const char *reason,
997 				const char *keymap_name,
998 				guint keymap_size,
999 				guint verify_count)
1000 {
1001 	proto_item *item = NULL;
1002 	enc_key_t *mek = NULL;
1003 
1004 	mek = wmem_new0(pinfo->pool, enc_key_t);
1005 	g_snprintf(mek->key_origin, KRB_MAX_ORIG_LEN,
1006 		   "checksum %d keytype %d missing in frame %u",
1007 		   checksum, keytype, pinfo->num);
1008 	mek->fd_num = pinfo->num;
1009 	mek->id = ++private_data->missing_key_ids;
1010 	g_snprintf(mek->id_str, KRB_MAX_ID_STR_LEN, "missing.%u",
1011 		   mek->id);
1012 	mek->keytype=keytype;
1013 
1014 	item = proto_tree_add_expert_format(tree, pinfo, &ei_kerberos_missing_keytype,
1015 					    tvb, 0, 0,
1016 					    "%s checksum %d keytype %d (id=%s)",
1017 					    reason, checksum, keytype, mek->id_str);
1018 	expert_add_info_format(pinfo, item, &ei_kerberos_missing_keytype,
1019 			       "Used keymap=%s num_keys=%u num_tries=%u)",
1020 			       keymap_name,
1021 			       keymap_size,
1022 			       verify_count);
1023 
1024 	kerberos_key_list_append(private_data->missing_keys, mek);
1025 }
1026 
1027 #endif /* HAVE_KRB5_PAC_VERIFY */
1028 
1029 static krb5_context krb5_ctx;
1030 
1031 #ifdef HAVE_KRB5_C_FX_CF2_SIMPLE
1032 static void
1033 krb5_fast_key(asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb,
1034 	      enc_key_t *ek1 _U_, const char *p1 _U_,
1035 	      enc_key_t *ek2 _U_, const char *p2 _U_,
1036 	      const char *origin _U_)
1037 {
1038 	kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
1039 	krb5_error_code ret;
1040 	krb5_keyblock k1;
1041 	krb5_keyblock k2;
1042 	krb5_keyblock *k = NULL;
1043 
1044 	if (!krb_decrypt) {
1045 		return;
1046 	}
1047 
1048 	if (ek1 == NULL) {
1049 		return;
1050 	}
1051 
1052 	if (ek2 == NULL) {
1053 		return;
1054 	}
1055 
1056 	k1.magic = KV5M_KEYBLOCK;
1057 	k1.enctype = ek1->keytype;
1058 	k1.length = ek1->keylength;
1059 	k1.contents = (guint8 *)ek1->keyvalue;
1060 
1061 	k2.magic = KV5M_KEYBLOCK;
1062 	k2.enctype = ek2->keytype;
1063 	k2.length = ek2->keylength;
1064 	k2.contents = (guint8 *)ek2->keyvalue;
1065 
1066 	ret = krb5_c_fx_cf2_simple(krb5_ctx, &k1, p1, &k2, p2, &k);
1067 	if (ret != 0) {
1068 		return;
1069 	}
1070 
1071 	add_encryption_key(actx->pinfo,
1072 			   private_data,
1073 			   tree, NULL, tvb,
1074 			   k->enctype, k->length,
1075 			   (const char *)k->contents,
1076 			   origin,
1077 			   ek1, ek2);
1078 
1079 	krb5_free_keyblock(krb5_ctx, k);
1080 }
1081 #else /* HAVE_KRB5_C_FX_CF2_SIMPLE */
1082 static void
1083 krb5_fast_key(asn1_ctx_t *actx _U_, proto_tree *tree _U_, tvbuff_t *tvb _U_,
1084 	      enc_key_t *ek1 _U_, const char *p1 _U_,
1085 	      enc_key_t *ek2 _U_, const char *p2 _U_,
1086 	      const char *origin _U_)
1087 {
1088 }
1089 #endif /* HAVE_KRB5_C_FX_CF2_SIMPLE */
1090 
1091 USES_APPLE_DEPRECATED_API
1092 void
1093 read_keytab_file(const char *filename)
1094 {
1095 	krb5_keytab keytab;
1096 	krb5_error_code ret;
1097 	krb5_keytab_entry key;
1098 	krb5_kt_cursor cursor;
1099 	static gboolean first_time=TRUE;
1100 
1101 	if (filename == NULL || filename[0] == 0) {
1102 		return;
1103 	}
1104 
1105 	if(first_time){
1106 		first_time=FALSE;
1107 		ret = krb5_init_context(&krb5_ctx);
1108 		if(ret && ret != KRB5_CONFIG_CANTOPEN){
1109 			return;
1110 		}
1111 	}
1112 
1113 	/* should use a file in the wireshark users dir */
1114 	ret = krb5_kt_resolve(krb5_ctx, filename, &keytab);
1115 	if(ret){
1116 		fprintf(stderr, "KERBEROS ERROR: Badly formatted keytab filename :%s\n",filename);
1117 
1118 		return;
1119 	}
1120 
1121 	ret = krb5_kt_start_seq_get(krb5_ctx, keytab, &cursor);
1122 	if(ret){
1123 		fprintf(stderr, "KERBEROS ERROR: Could not open or could not read from keytab file :%s\n",filename);
1124 		return;
1125 	}
1126 
1127 	do{
1128 		ret = krb5_kt_next_entry(krb5_ctx, keytab, &key, &cursor);
1129 		if(ret==0){
1130 			enc_key_t *new_key;
1131 			int i;
1132 			char *pos;
1133 
1134 			new_key = wmem_new0(wmem_epan_scope(), enc_key_t);
1135 			new_key->fd_num = -1;
1136 			new_key->id = ++kerberos_longterm_ids;
1137 			g_snprintf(new_key->id_str, KRB_MAX_ID_STR_LEN, "keytab.%u", new_key->id);
1138 			new_key->next = enc_key_list;
1139 
1140 			/* generate origin string, describing where this key came from */
1141 			pos=new_key->key_origin;
1142 			pos+=MIN(KRB_MAX_ORIG_LEN,
1143 					 g_snprintf(pos, KRB_MAX_ORIG_LEN, "keytab principal "));
1144 			for(i=0;i<key.principal->length;i++){
1145 				pos+=MIN(KRB_MAX_ORIG_LEN-(pos-new_key->key_origin),
1146 						 g_snprintf(pos, (gulong)(KRB_MAX_ORIG_LEN-(pos-new_key->key_origin)), "%s%s",(i?"/":""),(key.principal->data[i]).data));
1147 			}
1148 			pos+=MIN(KRB_MAX_ORIG_LEN-(pos-new_key->key_origin),
1149 					 g_snprintf(pos, (gulong)(KRB_MAX_ORIG_LEN-(pos-new_key->key_origin)), "@%s",key.principal->realm.data));
1150 			*pos=0;
1151 			new_key->keytype=key.key.enctype;
1152 			new_key->keylength=key.key.length;
1153 			memcpy(new_key->keyvalue,
1154 			       key.key.contents,
1155 			       MIN(key.key.length, KRB_MAX_KEY_LENGTH));
1156 
1157 			enc_key_list=new_key;
1158 			ret = krb5_free_keytab_entry_contents(krb5_ctx, &key);
1159 			if (ret) {
1160 				fprintf(stderr, "KERBEROS ERROR: Could not release the entry: %d", ret);
1161 				ret = 0; /* try to continue with the next entry */
1162 			}
1163 			kerberos_key_map_insert(kerberos_longterm_keys, new_key);
1164 		}
1165 	}while(ret==0);
1166 
1167 	ret = krb5_kt_end_seq_get(krb5_ctx, keytab, &cursor);
1168 	if(ret){
1169 		fprintf(stderr, "KERBEROS ERROR: Could not release the keytab cursor: %d", ret);
1170 	}
1171 	ret = krb5_kt_close(krb5_ctx, keytab);
1172 	if(ret){
1173 		fprintf(stderr, "KERBEROS ERROR: Could not close the key table handle: %d", ret);
1174 	}
1175 }
1176 
1177 struct decrypt_krb5_with_cb_state {
1178 	proto_tree *tree;
1179 	packet_info *pinfo;
1180 	kerberos_private_data_t *private_data;
1181 	int usage;
1182 	int keytype;
1183 	tvbuff_t *cryptotvb;
1184 	krb5_error_code (*decrypt_cb_fn)(
1185 		const krb5_keyblock *key,
1186 		int usage,
1187 		void *decrypt_cb_data);
1188 	void *decrypt_cb_data;
1189 	guint count;
1190 	enc_key_t *ek;
1191 };
1192 
1193 static void
1194 decrypt_krb5_with_cb_try_key(gpointer __key _U_, gpointer value, gpointer userdata)
1195 {
1196 	struct decrypt_krb5_with_cb_state *state =
1197 		(struct decrypt_krb5_with_cb_state *)userdata;
1198 	enc_key_t *ek = (enc_key_t *)value;
1199 	krb5_error_code ret;
1200 	krb5_keytab_entry key;
1201 #ifdef HAVE_KRB5_C_FX_CF2_SIMPLE
1202 	enc_key_t *ak = state->private_data->fast_armor_key;
1203 	enc_key_t *sk = state->private_data->fast_strengthen_key;
1204 	gboolean try_with_armor_key = FALSE;
1205 	gboolean try_with_strengthen_key = FALSE;
1206 #endif
1207 
1208 	if (state->ek != NULL) {
1209 		/*
1210 		 * we're done.
1211 		 */
1212 		return;
1213 	}
1214 
1215 #ifdef HAVE_KRB5_C_FX_CF2_SIMPLE
1216 	if (ak != NULL && ak != ek && ak->keytype == state->keytype && ek->fd_num == -1) {
1217 		switch (state->usage) {
1218 		case KEY_USAGE_ENC_CHALLENGE_CLIENT:
1219 		case KEY_USAGE_ENC_CHALLENGE_KDC:
1220 			if (ek->fd_num == -1) {
1221 				/* Challenges are based on a long term key */
1222 				try_with_armor_key = TRUE;
1223 			}
1224 			break;
1225 		}
1226 
1227 		/*
1228 		 * If we already have a strengthen_key
1229 		 * we don't need to try with the armor key
1230 		 * again
1231 		 */
1232 		if (sk != NULL) {
1233 			try_with_armor_key = FALSE;
1234 		}
1235 	}
1236 
1237 	if (sk != NULL && sk != ek && sk->keytype == state->keytype && sk->keytype == ek->keytype) {
1238 		switch (state->usage) {
1239 		case 3:
1240 			if (ek->fd_num == -1) {
1241 				/* AS-REP is based on a long term key */
1242 				try_with_strengthen_key = TRUE;
1243 			}
1244 			break;
1245 		case 8:
1246 		case 9:
1247 			if (ek->fd_num != -1) {
1248 				/* TGS-REP is not based on a long term key */
1249 				try_with_strengthen_key = TRUE;
1250 			}
1251 			break;
1252 		}
1253 	}
1254 
1255 	if (try_with_armor_key) {
1256 		krb5_keyblock k1;
1257 		krb5_keyblock k2;
1258 		krb5_keyblock *k = NULL;
1259 		const char *p1 = NULL;
1260 
1261 		k1.magic = KV5M_KEYBLOCK;
1262 		k1.enctype = ak->keytype;
1263 		k1.length = ak->keylength;
1264 		k1.contents = (guint8 *)ak->keyvalue;
1265 
1266 		k2.magic = KV5M_KEYBLOCK;
1267 		k2.enctype = ek->keytype;
1268 		k2.length = ek->keylength;
1269 		k2.contents = (guint8 *)ek->keyvalue;
1270 
1271 		switch (state->usage) {
1272 		case KEY_USAGE_ENC_CHALLENGE_CLIENT:
1273 			p1 = "clientchallengearmor";
1274 			break;
1275 		case KEY_USAGE_ENC_CHALLENGE_KDC:
1276 			p1 = "kdcchallengearmor";
1277 			break;
1278 		default:
1279 			/*
1280 			 * Should never be called!
1281 			 */
1282 			/*
1283 			 * try the next one...
1284 			 */
1285 			return;
1286 		}
1287 
1288 		ret = krb5_c_fx_cf2_simple(krb5_ctx,
1289 					   &k1, p1,
1290 					   &k2, "challengelongterm",
1291 					   &k);
1292 		if (ret != 0) {
1293 			/*
1294 			 * try the next one...
1295 			 */
1296 			return;
1297 		}
1298 
1299 		state->count += 1;
1300 		ret = state->decrypt_cb_fn(k,
1301 					   state->usage,
1302 					   state->decrypt_cb_data);
1303 		if (ret == 0) {
1304 			add_encryption_key(state->pinfo,
1305 					   state->private_data,
1306 					   state->tree,
1307 					   NULL,
1308 					   state->cryptotvb,
1309 					   k->enctype, k->length,
1310 					   (const char *)k->contents,
1311 					   p1,
1312 					   ak, ek);
1313 			krb5_free_keyblock(krb5_ctx, k);
1314 			/*
1315 			 * remember the key and stop traversing
1316 			 */
1317 			state->ek = state->private_data->last_added_key;
1318 			return;
1319 		}
1320 		krb5_free_keyblock(krb5_ctx, k);
1321 		/*
1322 		 * don't stop traversing...
1323 		 * try the next one...
1324 		 */
1325 		return;
1326 	}
1327 
1328 	if (try_with_strengthen_key) {
1329 		krb5_keyblock k1;
1330 		krb5_keyblock k2;
1331 		krb5_keyblock *k = NULL;
1332 
1333 		k1.magic = KV5M_KEYBLOCK;
1334 		k1.enctype = sk->keytype;
1335 		k1.length = sk->keylength;
1336 		k1.contents = (guint8 *)sk->keyvalue;
1337 
1338 		k2.magic = KV5M_KEYBLOCK;
1339 		k2.enctype = ek->keytype;
1340 		k2.length = ek->keylength;
1341 		k2.contents = (guint8 *)ek->keyvalue;
1342 
1343 		ret = krb5_c_fx_cf2_simple(krb5_ctx,
1344 					   &k1, "strengthenkey",
1345 					   &k2, "replykey",
1346 					   &k);
1347 		if (ret != 0) {
1348 			/*
1349 			 * try the next one...
1350 			 */
1351 			return;
1352 		}
1353 
1354 		state->count += 1;
1355 		ret = state->decrypt_cb_fn(k,
1356 					   state->usage,
1357 					   state->decrypt_cb_data);
1358 		if (ret == 0) {
1359 			add_encryption_key(state->pinfo,
1360 					   state->private_data,
1361 					   state->tree,
1362 					   NULL,
1363 					   state->cryptotvb,
1364 					   k->enctype, k->length,
1365 					   (const char *)k->contents,
1366 					    "strengthen-reply-key",
1367 					   sk, ek);
1368 			krb5_free_keyblock(krb5_ctx, k);
1369 			/*
1370 			 * remember the key and stop traversing
1371 			 */
1372 			state->ek = state->private_data->last_added_key;
1373 			return;
1374 		}
1375 		krb5_free_keyblock(krb5_ctx, k);
1376 		/*
1377 		 * don't stop traversing...
1378 		 * try the next one...
1379 		 */
1380 		return;
1381 	}
1382 #endif /* HAVE_KRB5_C_FX_CF2_SIMPLE */
1383 
1384 	/* shortcircuit and bail out if enctypes are not matching */
1385 	if ((state->keytype != -1) && (ek->keytype != state->keytype)) {
1386 		/*
1387 		 * don't stop traversing...
1388 		 * try the next one...
1389 		 */
1390 		return;
1391 	}
1392 
1393 	key.key.enctype=ek->keytype;
1394 	key.key.length=ek->keylength;
1395 	key.key.contents=ek->keyvalue;
1396 	state->count += 1;
1397 	ret = state->decrypt_cb_fn(&(key.key),
1398 				   state->usage,
1399 				   state->decrypt_cb_data);
1400 	if (ret != 0) {
1401 		/*
1402 		 * don't stop traversing...
1403 		 * try the next one...
1404 		 */
1405 		return;
1406 	}
1407 
1408 	/*
1409 	 * we're done, remember the key
1410 	 */
1411 	state->ek = ek;
1412 }
1413 
1414 static krb5_error_code
1415 decrypt_krb5_with_cb(proto_tree *tree,
1416 		     packet_info *pinfo,
1417 		     kerberos_private_data_t *private_data,
1418 		     int usage,
1419 		     int keytype,
1420 		     tvbuff_t *cryptotvb,
1421 		     krb5_error_code (*decrypt_cb_fn)(
1422 			const krb5_keyblock *key,
1423 			int usage,
1424 			void *decrypt_cb_data),
1425 		     void *decrypt_cb_data)
1426 {
1427 	const char *key_map_name = NULL;
1428 	wmem_map_t *key_map = NULL;
1429 	struct decrypt_krb5_with_cb_state state = {
1430 		.tree = tree,
1431 		.pinfo = pinfo,
1432 		.private_data = private_data,
1433 		.usage = usage,
1434 		.cryptotvb = cryptotvb,
1435 		.keytype = keytype,
1436 		.decrypt_cb_fn = decrypt_cb_fn,
1437 		.decrypt_cb_data = decrypt_cb_data,
1438 	};
1439 
1440 	read_keytab_file_from_preferences();
1441 
1442 	switch (usage) {
1443 	case KRB5_KU_USAGE_INITIATOR_SEAL:
1444 	case KRB5_KU_USAGE_ACCEPTOR_SEAL:
1445 		key_map_name = "app_session_keys";
1446 		key_map = kerberos_app_session_keys;
1447 		break;
1448 	default:
1449 		key_map_name = "all_keys";
1450 		key_map = kerberos_all_keys;
1451 		insert_longterm_keys_into_key_map(key_map);
1452 		break;
1453 	}
1454 
1455 	wmem_map_foreach(key_map, decrypt_krb5_with_cb_try_key, &state);
1456 	if (state.ek != NULL) {
1457 		used_encryption_key(tree, pinfo, private_data,
1458 				    state.ek, usage, cryptotvb,
1459 				    key_map_name,
1460 				    wmem_map_size(key_map),
1461 				    state.count);
1462 		return 0;
1463 	}
1464 
1465 	missing_encryption_key(tree, pinfo, private_data,
1466 			       keytype, usage, cryptotvb,
1467 			       key_map_name,
1468 			       wmem_map_size(key_map),
1469 			       state.count);
1470 	return -1;
1471 }
1472 
1473 struct decrypt_krb5_data_state {
1474 	krb5_data input;
1475 	krb5_data output;
1476 };
1477 
1478 static krb5_error_code
1479 decrypt_krb5_data_cb(const krb5_keyblock *key,
1480 		     int usage,
1481 		     void *decrypt_cb_data)
1482 {
1483 	struct decrypt_krb5_data_state *state =
1484 		(struct decrypt_krb5_data_state *)decrypt_cb_data;
1485 	krb5_enc_data input;
1486 
1487 	memset(&input, 0, sizeof(input));
1488 	input.enctype = key->enctype;
1489 	input.ciphertext = state->input;
1490 
1491 	return krb5_c_decrypt(krb5_ctx,
1492 			      key,
1493 			      usage,
1494 			      0,
1495 			      &input,
1496 			      &state->output);
1497 }
1498 
1499 static guint8 *
1500 decrypt_krb5_data_private(proto_tree *tree _U_, packet_info *pinfo,
1501 			  kerberos_private_data_t *private_data,
1502 			  int usage, tvbuff_t *cryptotvb, int keytype,
1503 			  int *datalen)
1504 {
1505 #define HAVE_DECRYPT_KRB5_DATA_PRIVATE 1
1506 	struct decrypt_krb5_data_state state;
1507 	krb5_error_code ret;
1508 	int length = tvb_captured_length(cryptotvb);
1509 	const guint8 *cryptotext = tvb_get_ptr(cryptotvb, 0, length);
1510 
1511 	/* don't do anything if we are not attempting to decrypt data */
1512 	if(!krb_decrypt || length < 1){
1513 		return NULL;
1514 	}
1515 
1516 	/* make sure we have all the data we need */
1517 	if (tvb_captured_length(cryptotvb) < tvb_reported_length(cryptotvb)) {
1518 		return NULL;
1519 	}
1520 
1521 	memset(&state, 0, sizeof(state));
1522 	state.input.length = length;
1523 	state.input.data = (guint8 *)cryptotext;
1524 	state.output.data = (char *)wmem_alloc(pinfo->pool, length);
1525 	state.output.length = length;
1526 
1527 	ret = decrypt_krb5_with_cb(tree,
1528 				   pinfo,
1529 				   private_data,
1530 				   usage,
1531 				   keytype,
1532 				   cryptotvb,
1533 				   decrypt_krb5_data_cb,
1534 				   &state);
1535 	if (ret != 0) {
1536 		return NULL;
1537 	}
1538 
1539 	if (datalen) {
1540 		*datalen = state.output.length;
1541 	}
1542 	return (guint8 *)state.output.data;
1543 }
1544 
1545 guint8 *
1546 decrypt_krb5_data(proto_tree *tree _U_, packet_info *pinfo,
1547 					int usage,
1548 					tvbuff_t *cryptotvb,
1549 					int keytype,
1550 					int *datalen)
1551 {
1552 	kerberos_private_data_t *zero_private = kerberos_new_private_data(pinfo);
1553 	return decrypt_krb5_data_private(tree, pinfo, zero_private,
1554 					 usage, cryptotvb, keytype,
1555 					 datalen);
1556 }
1557 
1558 USES_APPLE_RST
1559 
1560 #ifdef KRB5_CRYPTO_TYPE_SIGN_ONLY
1561 struct decrypt_krb5_krb_cfx_dce_state {
1562 	const guint8 *gssapi_header_ptr;
1563 	guint gssapi_header_len;
1564 	tvbuff_t *gssapi_encrypted_tvb;
1565 	guint8 *gssapi_payload;
1566 	guint gssapi_payload_len;
1567 	const guint8 *gssapi_trailer_ptr;
1568 	guint gssapi_trailer_len;
1569 	tvbuff_t *checksum_tvb;
1570 	guint8 *checksum;
1571 	guint checksum_len;
1572 };
1573 
1574 static krb5_error_code
1575 decrypt_krb5_krb_cfx_dce_cb(const krb5_keyblock *key,
1576 			    int usage,
1577 			    void *decrypt_cb_data)
1578 {
1579 	struct decrypt_krb5_krb_cfx_dce_state *state =
1580 		(struct decrypt_krb5_krb_cfx_dce_state *)decrypt_cb_data;
1581 	unsigned int k5_headerlen = 0;
1582 	unsigned int k5_headerofs = 0;
1583 	unsigned int k5_trailerlen = 0;
1584 	unsigned int k5_trailerofs = 0;
1585 	size_t _k5_blocksize = 0;
1586 	guint k5_blocksize;
1587 	krb5_crypto_iov iov[6];
1588 	krb5_error_code ret;
1589 	guint checksum_remain = state->checksum_len;
1590 	guint checksum_crypt_len;
1591 
1592 	memset(iov, 0, sizeof(iov));
1593 
1594 	ret = krb5_c_crypto_length(krb5_ctx,
1595 				   key->enctype,
1596 				   KRB5_CRYPTO_TYPE_HEADER,
1597 				   &k5_headerlen);
1598 	if (ret != 0) {
1599 		return ret;
1600 	}
1601 	if (checksum_remain < k5_headerlen) {
1602 		return -1;
1603 	}
1604 	checksum_remain -= k5_headerlen;
1605 	k5_headerofs = checksum_remain;
1606 	ret = krb5_c_crypto_length(krb5_ctx,
1607 				   key->enctype,
1608 				   KRB5_CRYPTO_TYPE_TRAILER,
1609 				   &k5_trailerlen);
1610 	if (ret != 0) {
1611 		return ret;
1612 	}
1613 	if (checksum_remain < k5_trailerlen) {
1614 		return -1;
1615 	}
1616 	checksum_remain -= k5_trailerlen;
1617 	k5_trailerofs = checksum_remain;
1618 	checksum_crypt_len = checksum_remain;
1619 
1620 	ret = krb5_c_block_size(krb5_ctx,
1621 				key->enctype,
1622 				&_k5_blocksize);
1623 	if (ret != 0) {
1624 		return ret;
1625 	}
1626 	/*
1627 	 * The cast is required for the Windows build in order
1628 	 * to avoid the following warning.
1629 	 *
1630 	 * warning C4267: '-=': conversion from 'size_t' to 'guint',
1631 	 * possible loss of data
1632 	 */
1633 	k5_blocksize = (guint)_k5_blocksize;
1634 	if (checksum_remain < k5_blocksize) {
1635 		return -1;
1636 	}
1637 	checksum_remain -= k5_blocksize;
1638 	if (checksum_remain < 16) {
1639 		return -1;
1640 	}
1641 
1642 	tvb_memcpy(state->gssapi_encrypted_tvb,
1643 		   state->gssapi_payload,
1644 		   0,
1645 		   state->gssapi_payload_len);
1646 	tvb_memcpy(state->checksum_tvb,
1647 		   state->checksum,
1648 		   0,
1649 		   state->checksum_len);
1650 
1651 	iov[0].flags = KRB5_CRYPTO_TYPE_HEADER;
1652 	iov[0].data.data = state->checksum + k5_headerofs;
1653 	iov[0].data.length = k5_headerlen;
1654 
1655 	if (state->gssapi_header_ptr != NULL) {
1656 		iov[1].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY;
1657 		iov[1].data.data = (guint8 *)(guintptr)state->gssapi_header_ptr;
1658 		iov[1].data.length = state->gssapi_header_len;
1659 	} else {
1660 		iov[1].flags = KRB5_CRYPTO_TYPE_EMPTY;
1661 	}
1662 
1663 	iov[2].flags = KRB5_CRYPTO_TYPE_DATA;
1664 	iov[2].data.data = state->gssapi_payload;
1665 	iov[2].data.length = state->gssapi_payload_len;
1666 
1667 	if (state->gssapi_trailer_ptr != NULL) {
1668 		iov[3].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY;
1669 		iov[3].data.data = (guint8 *)(guintptr)state->gssapi_trailer_ptr;
1670 		iov[3].data.length = state->gssapi_trailer_len;
1671 	} else {
1672 		iov[3].flags = KRB5_CRYPTO_TYPE_EMPTY;
1673 	}
1674 
1675 	iov[4].flags = KRB5_CRYPTO_TYPE_DATA;
1676 	iov[4].data.data = state->checksum;
1677 	iov[4].data.length = checksum_crypt_len;
1678 
1679 	iov[5].flags = KRB5_CRYPTO_TYPE_TRAILER;
1680 	iov[5].data.data = state->checksum + k5_trailerofs;
1681 	iov[5].data.length = k5_trailerlen;
1682 
1683 	return krb5_c_decrypt_iov(krb5_ctx,
1684 				  key,
1685 				  usage,
1686 				  0,
1687 				  iov,
1688 				  6);
1689 }
1690 
1691 tvbuff_t *
1692 decrypt_krb5_krb_cfx_dce(proto_tree *tree,
1693 			 packet_info *pinfo,
1694 			 int usage,
1695 			 int keytype,
1696 			 tvbuff_t *gssapi_header_tvb,
1697 			 tvbuff_t *gssapi_encrypted_tvb,
1698 			 tvbuff_t *gssapi_trailer_tvb,
1699 			 tvbuff_t *checksum_tvb)
1700 {
1701 	struct decrypt_krb5_krb_cfx_dce_state state;
1702 	kerberos_private_data_t *zero_private = kerberos_new_private_data(pinfo);
1703 	tvbuff_t *gssapi_decrypted_tvb = NULL;
1704 	krb5_error_code ret;
1705 
1706 	/* don't do anything if we are not attempting to decrypt data */
1707 	if (!krb_decrypt) {
1708 		return NULL;
1709 	}
1710 
1711 	memset(&state, 0, sizeof(state));
1712 
1713 	/* make sure we have all the data we need */
1714 #define __CHECK_TVB_LEN(__tvb) (tvb_captured_length(__tvb) < tvb_reported_length(__tvb))
1715 	if (gssapi_header_tvb != NULL) {
1716 		if (__CHECK_TVB_LEN(gssapi_header_tvb)) {
1717 			return NULL;
1718 		}
1719 
1720 		state.gssapi_header_len = tvb_captured_length(gssapi_header_tvb);
1721 		state.gssapi_header_ptr = tvb_get_ptr(gssapi_header_tvb,
1722 						       0,
1723 						       state.gssapi_header_len);
1724 	}
1725 	if (gssapi_encrypted_tvb == NULL || __CHECK_TVB_LEN(gssapi_encrypted_tvb)) {
1726 		return NULL;
1727 	}
1728 	state.gssapi_encrypted_tvb = gssapi_encrypted_tvb;
1729 	state.gssapi_payload_len = tvb_captured_length(gssapi_encrypted_tvb);
1730 	state.gssapi_payload = (guint8 *)wmem_alloc0(pinfo->pool, state.gssapi_payload_len);
1731 	if (state.gssapi_payload == NULL) {
1732 		return NULL;
1733 	}
1734 	if (gssapi_trailer_tvb != NULL) {
1735 		if (__CHECK_TVB_LEN(gssapi_trailer_tvb)) {
1736 			return NULL;
1737 		}
1738 
1739 		state.gssapi_trailer_len = tvb_captured_length(gssapi_trailer_tvb);
1740 		state.gssapi_trailer_ptr = tvb_get_ptr(gssapi_trailer_tvb,
1741 						       0,
1742 						       state.gssapi_trailer_len);
1743 	}
1744 	if (checksum_tvb == NULL || __CHECK_TVB_LEN(checksum_tvb)) {
1745 		return NULL;
1746 	}
1747 	state.checksum_tvb = checksum_tvb;
1748 	state.checksum_len = tvb_captured_length(checksum_tvb);
1749 	state.checksum = (guint8 *)wmem_alloc0(pinfo->pool, state.checksum_len);
1750 	if (state.checksum == NULL) {
1751 		return NULL;
1752 	}
1753 
1754 	ret = decrypt_krb5_with_cb(tree,
1755 				   pinfo,
1756 				   zero_private,
1757 				   usage,
1758 				   keytype,
1759 				   gssapi_encrypted_tvb,
1760 				   decrypt_krb5_krb_cfx_dce_cb,
1761 				   &state);
1762 	wmem_free(pinfo->pool, state.checksum);
1763 	if (ret != 0) {
1764 		wmem_free(pinfo->pool, state.gssapi_payload);
1765 		return NULL;
1766 	}
1767 
1768 	gssapi_decrypted_tvb = tvb_new_child_real_data(gssapi_encrypted_tvb,
1769 						       state.gssapi_payload,
1770 						       state.gssapi_payload_len,
1771 						       state.gssapi_payload_len);
1772 	if (gssapi_decrypted_tvb == NULL) {
1773 		wmem_free(pinfo->pool, state.gssapi_payload);
1774 		return NULL;
1775 	}
1776 
1777 	return gssapi_decrypted_tvb;
1778 }
1779 #else /* NOT KRB5_CRYPTO_TYPE_SIGN_ONLY */
1780 #define NEED_DECRYPT_KRB5_KRB_CFX_DCE_NOOP 1
1781 #endif /* NOT KRB5_CRYPTO_TYPE_SIGN_ONLY */
1782 
1783 #ifdef HAVE_KRB5_PAC_VERIFY
1784 /*
1785  * macOS up to 10.14.5 only has a MIT shim layer on top
1786  * of heimdal. It means that krb5_pac_verify() is not available
1787  * in /usr/lib/libkrb5.dylib
1788  *
1789  * https://opensource.apple.com/tarballs/Heimdal/Heimdal-520.260.1.tar.gz
1790  * https://opensource.apple.com/tarballs/MITKerberosShim/MITKerberosShim-71.200.1.tar.gz
1791  */
1792 
1793 extern krb5_error_code
1794 krb5int_c_mandatory_cksumtype(krb5_context, krb5_enctype, krb5_cksumtype *);
1795 
1796 extern void krb5_free_enc_tkt_part(krb5_context, krb5_enc_tkt_part *);
1797 extern krb5_error_code
1798 decode_krb5_enc_tkt_part(const krb5_data *output, krb5_enc_tkt_part **rep);
1799 extern krb5_error_code
1800 encode_krb5_enc_tkt_part(const krb5_enc_tkt_part *rep, krb5_data **code);
1801 
1802 static int
1803 keytype_for_cksumtype(krb5_cksumtype checksum)
1804 {
1805 #define _ARRAY_SIZE(X) (sizeof(X) / sizeof((X)[0]))
1806 	static const int keytypes[] = {
1807 		18,
1808 		17,
1809 		23,
1810 	};
1811 	guint i;
1812 
1813 	for (i = 0; i < _ARRAY_SIZE(keytypes); i++) {
1814 		krb5_cksumtype checksumtype = 0;
1815 		krb5_error_code ret;
1816 
1817 		ret = krb5int_c_mandatory_cksumtype(krb5_ctx,
1818 						    keytypes[i],
1819 						    &checksumtype);
1820 		if (ret != 0) {
1821 			continue;
1822 		}
1823 		if (checksum == checksumtype) {
1824 			return keytypes[i];
1825 		}
1826 	}
1827 
1828 	return -1;
1829 }
1830 
1831 struct verify_krb5_pac_state {
1832 	krb5_pac pac;
1833 	krb5_cksumtype server_checksum;
1834 	guint server_count;
1835 	enc_key_t *server_ek;
1836 	krb5_cksumtype kdc_checksum;
1837 	guint kdc_count;
1838 	enc_key_t *kdc_ek;
1839 	krb5_cksumtype ticket_checksum_type;
1840 	const krb5_data *ticket_checksum_data;
1841 };
1842 
1843 static void
1844 verify_krb5_pac_try_server_key(gpointer __key _U_, gpointer value, gpointer userdata)
1845 {
1846 	struct verify_krb5_pac_state *state =
1847 		(struct verify_krb5_pac_state *)userdata;
1848 	enc_key_t *ek = (enc_key_t *)value;
1849 	krb5_keyblock keyblock;
1850 	krb5_cksumtype checksumtype = 0;
1851 	krb5_error_code ret;
1852 
1853 	if (state->server_checksum == 0) {
1854 		/*
1855 		 * nothing more todo, stop traversing.
1856 		 */
1857 		return;
1858 	}
1859 
1860 	if (state->server_ek != NULL) {
1861 		/*
1862 		 * we're done.
1863 		 */
1864 		return;
1865 	}
1866 
1867 	ret = krb5int_c_mandatory_cksumtype(krb5_ctx, ek->keytype,
1868 					    &checksumtype);
1869 	if (ret != 0) {
1870 		/*
1871 		 * the key is not usable, keep traversing.
1872 		 * try the next key...
1873 		 */
1874 		return;
1875 	}
1876 
1877 	keyblock.magic = KV5M_KEYBLOCK;
1878 	keyblock.enctype = ek->keytype;
1879 	keyblock.length = ek->keylength;
1880 	keyblock.contents = (guint8 *)ek->keyvalue;
1881 
1882 	if (checksumtype == state->server_checksum) {
1883 		state->server_count += 1;
1884 		ret = krb5_pac_verify(krb5_ctx, state->pac, 0, NULL,
1885 				      &keyblock, NULL);
1886 		if (ret == 0) {
1887 			state->server_ek = ek;
1888 		}
1889 	}
1890 }
1891 
1892 static void
1893 verify_krb5_pac_try_kdc_key(gpointer __key _U_, gpointer value, gpointer userdata)
1894 {
1895 	struct verify_krb5_pac_state *state =
1896 		(struct verify_krb5_pac_state *)userdata;
1897 	enc_key_t *ek = (enc_key_t *)value;
1898 	krb5_keyblock keyblock;
1899 	krb5_cksumtype checksumtype = 0;
1900 	krb5_error_code ret;
1901 
1902 	if (state->kdc_checksum == 0) {
1903 		/*
1904 		 * nothing more todo, stop traversing.
1905 		 */
1906 		return;
1907 	}
1908 
1909 	if (state->kdc_ek != NULL) {
1910 		/*
1911 		 * we're done.
1912 		 */
1913 		return;
1914 	}
1915 
1916 	ret = krb5int_c_mandatory_cksumtype(krb5_ctx, ek->keytype,
1917 					    &checksumtype);
1918 	if (ret != 0) {
1919 		/*
1920 		 * the key is not usable, keep traversing.
1921 		 * try the next key...
1922 		 */
1923 		return;
1924 	}
1925 
1926 	keyblock.magic = KV5M_KEYBLOCK;
1927 	keyblock.enctype = ek->keytype;
1928 	keyblock.length = ek->keylength;
1929 	keyblock.contents = (guint8 *)ek->keyvalue;
1930 
1931 	if (checksumtype == state->kdc_checksum) {
1932 		state->kdc_count += 1;
1933 		ret = krb5_pac_verify(krb5_ctx, state->pac, 0, NULL,
1934 				      NULL, &keyblock);
1935 		if (ret == 0) {
1936 			state->kdc_ek = ek;
1937 		}
1938 	}
1939 }
1940 
1941 #define __KRB5_PAC_TICKET_CHECKSUM 16
1942 
1943 static void
1944 verify_krb5_pac_ticket_checksum(proto_tree *tree _U_,
1945 				asn1_ctx_t *actx _U_,
1946 				tvbuff_t *pactvb _U_,
1947 				struct verify_krb5_pac_state *state _U_)
1948 {
1949 #ifdef HAVE_DECODE_KRB5_ENC_TKT_PART
1950 	kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
1951 	tvbuff_t *teptvb = private_data->last_ticket_enc_part_tvb;
1952 	guint teplength = 0;
1953 	const guint8 *tepbuffer = NULL;
1954 	krb5_data tepdata = { .length = 0, };
1955 	krb5_enc_tkt_part *tep = NULL;
1956 	krb5_data *tmpdata = NULL;
1957 	krb5_error_code ret;
1958 	krb5_authdata **recoded_container = NULL;
1959 	gint ad_orig_idx = -1;
1960 	krb5_authdata *ad_orig_ptr = NULL;
1961 	gint l0idx = 0;
1962 	krb5_keyblock kdc_key = { .magic = KV5M_KEYBLOCK, };
1963 	size_t checksum_length = 0;
1964 	krb5_checksum checksum = { .checksum_type = 0, };
1965 	krb5_boolean valid = FALSE;
1966 
1967 	if (state->kdc_ek == NULL) {
1968 		int keytype = keytype_for_cksumtype(state->ticket_checksum_type);
1969 		missing_signing_key(tree, actx->pinfo, private_data,
1970 				    pactvb, state->ticket_checksum_type,
1971 				    keytype,
1972 				    "Missing KDC (for ticket)",
1973 				    "kdc_checksum_key",
1974 				    0,
1975 				    0);
1976 		return;
1977 	}
1978 
1979 	if (teptvb == NULL) {
1980 		return;
1981 	}
1982 
1983 	teplength = tvb_captured_length(teptvb);
1984 	/* make sure we have all the data we need */
1985 	if (teplength < tvb_reported_length(teptvb)) {
1986 		return;
1987 	}
1988 
1989 	tepbuffer = tvb_get_ptr(teptvb, 0, teplength);
1990 	if (tepbuffer == NULL) {
1991 		return;
1992 	}
1993 
1994 	kdc_key.magic = KV5M_KEYBLOCK;
1995 	kdc_key.enctype = state->kdc_ek->keytype;
1996 	kdc_key.length = state->kdc_ek->keylength;
1997 	kdc_key.contents = (guint8 *)state->kdc_ek->keyvalue;
1998 
1999 	checksum.checksum_type = state->ticket_checksum_type;
2000 	checksum.length = state->ticket_checksum_data->length;
2001 	checksum.contents = (guint8 *)state->ticket_checksum_data->data;
2002 	if (checksum.length >= 4) {
2003 		checksum.length -= 4;
2004 		checksum.contents += 4;
2005 	}
2006 
2007 	ret = krb5_c_checksum_length(krb5_ctx,
2008 				     checksum.checksum_type,
2009 				     &checksum_length);
2010 	if (ret != 0) {
2011 		missing_signing_key(tree, actx->pinfo, private_data,
2012 				    pactvb, state->ticket_checksum_type,
2013 				    state->kdc_ek->keytype,
2014 				    "krb5_c_checksum_length failed for Ticket Signature",
2015 				    "kdc_checksum_key",
2016 				    1,
2017 				    0);
2018 		return;
2019 	}
2020 	checksum.length = MIN(checksum.length, (unsigned int)checksum_length);
2021 
2022 	tepdata.data = (void *)(uintptr_t)tepbuffer;
2023 	tepdata.length = teplength;
2024 
2025 	ret = decode_krb5_enc_tkt_part(&tepdata, &tep);
2026 	if (ret != 0) {
2027 		missing_signing_key(tree, actx->pinfo, private_data,
2028 				    pactvb, state->ticket_checksum_type,
2029 				    state->kdc_ek->keytype,
2030 				    "decode_krb5_enc_tkt_part failed",
2031 				    "kdc_checksum_key",
2032 				    1,
2033 				    0);
2034 		return;
2035 	}
2036 
2037 	for (l0idx = 0; tep->authorization_data[l0idx]; l0idx++) {
2038 		krb5_authdata *adl0 = tep->authorization_data[l0idx];
2039 		krb5_authdata **decoded_container = NULL;
2040 		krb5_authdata *ad_pac = NULL;
2041 		gint l1idx = 0;
2042 
2043 		if (adl0->ad_type != KRB5_AUTHDATA_IF_RELEVANT) {
2044 			continue;
2045 		}
2046 
2047 		ret = krb5_decode_authdata_container(krb5_ctx,
2048 						     KRB5_AUTHDATA_IF_RELEVANT,
2049 						     adl0,
2050 						     &decoded_container);
2051 		if (ret != 0) {
2052 			missing_signing_key(tree, actx->pinfo, private_data,
2053 					    pactvb, state->ticket_checksum_type,
2054 					    state->kdc_ek->keytype,
2055 					    "krb5_decode_authdata_container failed",
2056 					    "kdc_checksum_key",
2057 					    1,
2058 					    0);
2059 			krb5_free_enc_tkt_part(krb5_ctx, tep);
2060 			return;
2061 		}
2062 
2063 		for (l1idx = 0; decoded_container[l1idx]; l1idx++) {
2064 			krb5_authdata *adl1 = decoded_container[l1idx];
2065 
2066 			if (adl1->ad_type != KRB5_AUTHDATA_WIN2K_PAC) {
2067 				continue;
2068 			}
2069 
2070 			ad_pac = adl1;
2071 			break;
2072 		}
2073 
2074 		if (ad_pac == NULL) {
2075 			krb5_free_authdata(krb5_ctx, decoded_container);
2076 			continue;
2077 		}
2078 
2079 		ad_pac->length = 1;
2080 		ad_pac->contents[0] = '\0';
2081 
2082 		ret = krb5_encode_authdata_container(krb5_ctx,
2083 						     KRB5_AUTHDATA_IF_RELEVANT,
2084 						     decoded_container,
2085 						     &recoded_container);
2086 		krb5_free_authdata(krb5_ctx, decoded_container);
2087 		decoded_container = NULL;
2088 		if (ret != 0) {
2089 			missing_signing_key(tree, actx->pinfo, private_data,
2090 					    pactvb, state->ticket_checksum_type,
2091 					    state->kdc_ek->keytype,
2092 					    "krb5_encode_authdata_container failed",
2093 					    "kdc_checksum_key",
2094 					    1,
2095 					    0);
2096 			krb5_free_enc_tkt_part(krb5_ctx, tep);
2097 			return;
2098 		}
2099 
2100 		ad_orig_idx = l0idx;
2101 		ad_orig_ptr = adl0;
2102 		tep->authorization_data[l0idx] = recoded_container[0];
2103 		break;
2104 	}
2105 
2106 	ret = encode_krb5_enc_tkt_part(tep, &tmpdata);
2107 	if (ad_orig_ptr != NULL) {
2108 		tep->authorization_data[ad_orig_idx] = ad_orig_ptr;
2109 	}
2110 	krb5_free_enc_tkt_part(krb5_ctx, tep);
2111 	tep = NULL;
2112 	if (recoded_container != NULL) {
2113 		krb5_free_authdata(krb5_ctx, recoded_container);
2114 		recoded_container = NULL;
2115 	}
2116 	if (ret != 0) {
2117 		missing_signing_key(tree, actx->pinfo, private_data,
2118 				    pactvb, state->ticket_checksum_type,
2119 				    state->kdc_ek->keytype,
2120 				    "encode_krb5_enc_tkt_part failed",
2121 				    "kdc_checksum_key",
2122 				    1,
2123 				    0);
2124 		return;
2125 	}
2126 
2127 	ret = krb5_c_verify_checksum(krb5_ctx, &kdc_key,
2128 				     KRB5_KEYUSAGE_APP_DATA_CKSUM,
2129 				     tmpdata, &checksum, &valid);
2130 	krb5_free_data(krb5_ctx, tmpdata);
2131 	tmpdata = NULL;
2132 	if (ret != 0) {
2133 		missing_signing_key(tree, actx->pinfo, private_data,
2134 				    pactvb, state->ticket_checksum_type,
2135 				    state->kdc_ek->keytype,
2136 				    "krb5_c_verify_checksum failed for Ticket Signature",
2137 				    "kdc_checksum_key",
2138 				    1,
2139 				    1);
2140 		return;
2141 	}
2142 
2143 	if (valid == FALSE) {
2144 		missing_signing_key(tree, actx->pinfo, private_data,
2145 				    pactvb, state->ticket_checksum_type,
2146 				    state->kdc_ek->keytype,
2147 				    "Invalid Ticket",
2148 				    "kdc_checksum_key",
2149 				    1,
2150 				    1);
2151 		return;
2152 	}
2153 
2154 	used_signing_key(tree, actx->pinfo, private_data,
2155 			 state->kdc_ek, pactvb,
2156 			 state->ticket_checksum_type,
2157 			 "Verified Ticket",
2158 			 "kdc_checksum_key",
2159 			 1,
2160 			 1);
2161 #endif /* HAVE_DECODE_KRB5_ENC_TKT_PART */
2162 }
2163 
2164 static void
2165 verify_krb5_pac(proto_tree *tree _U_, asn1_ctx_t *actx, tvbuff_t *pactvb)
2166 {
2167 	kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
2168 	krb5_error_code ret;
2169 	krb5_data checksum_data = {0,0,NULL};
2170 	krb5_data ticket_checksum_data = {0,0,NULL};
2171 	int length = tvb_captured_length(pactvb);
2172 	const guint8 *pacbuffer = NULL;
2173 	struct verify_krb5_pac_state state = {
2174 		.kdc_checksum = 0,
2175 	};
2176 
2177 	/* don't do anything if we are not attempting to decrypt data */
2178 	if(!krb_decrypt || length < 1){
2179 		return;
2180 	}
2181 
2182 	/* make sure we have all the data we need */
2183 	if (tvb_captured_length(pactvb) < tvb_reported_length(pactvb)) {
2184 		return;
2185 	}
2186 
2187 	pacbuffer = tvb_get_ptr(pactvb, 0, length);
2188 
2189 	ret = krb5_pac_parse(krb5_ctx, pacbuffer, length, &state.pac);
2190 	if (ret != 0) {
2191 		proto_tree_add_expert_format(tree, actx->pinfo, &ei_kerberos_decrypted_keytype,
2192 					     pactvb, 0, 0,
2193 					     "Failed to parse PAC buffer %d in frame %u",
2194 					     ret, actx->pinfo->fd->num);
2195 		return;
2196 	}
2197 
2198 	ret = krb5_pac_get_buffer(krb5_ctx, state.pac, KRB5_PAC_SERVER_CHECKSUM,
2199 				  &checksum_data);
2200 	if (ret == 0) {
2201 		state.server_checksum = pletoh32(checksum_data.data);
2202 		krb5_free_data_contents(krb5_ctx, &checksum_data);
2203 	};
2204 	ret = krb5_pac_get_buffer(krb5_ctx, state.pac, KRB5_PAC_PRIVSVR_CHECKSUM,
2205 				  &checksum_data);
2206 	if (ret == 0) {
2207 		state.kdc_checksum = pletoh32(checksum_data.data);
2208 		krb5_free_data_contents(krb5_ctx, &checksum_data);
2209 	};
2210 	ret = krb5_pac_get_buffer(krb5_ctx, state.pac,
2211 				  __KRB5_PAC_TICKET_CHECKSUM,
2212 				  &ticket_checksum_data);
2213 	if (ret == 0) {
2214 		state.ticket_checksum_data = &ticket_checksum_data;
2215 		state.ticket_checksum_type = pletoh32(ticket_checksum_data.data);
2216 	};
2217 
2218 	read_keytab_file_from_preferences();
2219 
2220 	wmem_map_foreach(kerberos_all_keys,
2221 			 verify_krb5_pac_try_server_key,
2222 			 &state);
2223 	if (state.server_ek != NULL) {
2224 		used_signing_key(tree, actx->pinfo, private_data,
2225 				 state.server_ek, pactvb,
2226 				 state.server_checksum, "Verified Server",
2227 				 "all_keys",
2228 				 wmem_map_size(kerberos_all_keys),
2229 				 state.server_count);
2230 	} else {
2231 		int keytype = keytype_for_cksumtype(state.server_checksum);
2232 		missing_signing_key(tree, actx->pinfo, private_data,
2233 				    pactvb, state.server_checksum, keytype,
2234 				    "Missing Server",
2235 				    "all_keys",
2236 				    wmem_map_size(kerberos_all_keys),
2237 				    state.server_count);
2238 	}
2239 	wmem_map_foreach(kerberos_longterm_keys,
2240 			 verify_krb5_pac_try_kdc_key,
2241 			 &state);
2242 	if (state.kdc_ek != NULL) {
2243 		used_signing_key(tree, actx->pinfo, private_data,
2244 				 state.kdc_ek, pactvb,
2245 				 state.kdc_checksum, "Verified KDC",
2246 				 "longterm_keys",
2247 				 wmem_map_size(kerberos_longterm_keys),
2248 				 state.kdc_count);
2249 	} else {
2250 		int keytype = keytype_for_cksumtype(state.kdc_checksum);
2251 		missing_signing_key(tree, actx->pinfo, private_data,
2252 				    pactvb, state.kdc_checksum, keytype,
2253 				    "Missing KDC",
2254 				    "longterm_keys",
2255 				    wmem_map_size(kerberos_longterm_keys),
2256 				    state.kdc_count);
2257 	}
2258 
2259 	if (state.ticket_checksum_type != 0) {
2260 		verify_krb5_pac_ticket_checksum(tree, actx, pactvb, &state);
2261 	}
2262 
2263 	if (state.ticket_checksum_data != NULL) {
2264 		krb5_free_data_contents(krb5_ctx, &ticket_checksum_data);
2265 	}
2266 
2267 	krb5_pac_free(krb5_ctx, state.pac);
2268 }
2269 #endif /* HAVE_KRB5_PAC_VERIFY */
2270 
2271 #elif defined(HAVE_HEIMDAL_KERBEROS)
2272 static krb5_context krb5_ctx;
2273 
2274 USES_APPLE_DEPRECATED_API
2275 
2276 static void
2277 krb5_fast_key(asn1_ctx_t *actx _U_, proto_tree *tree _U_, tvbuff_t *tvb _U_,
2278 	      enc_key_t *ek1 _U_, const char *p1 _U_,
2279 	      enc_key_t *ek2 _U_, const char *p2 _U_,
2280 	      const char *origin _U_)
2281 {
2282 /* TODO: use krb5_crypto_fx_cf2() from Heimdal */
2283 }
2284 void
2285 read_keytab_file(const char *filename)
2286 {
2287 	krb5_keytab keytab;
2288 	krb5_error_code ret;
2289 	krb5_keytab_entry key;
2290 	krb5_kt_cursor cursor;
2291 	enc_key_t *new_key;
2292 	static gboolean first_time=TRUE;
2293 
2294 	if (filename == NULL || filename[0] == 0) {
2295 		return;
2296 	}
2297 
2298 	if(first_time){
2299 		first_time=FALSE;
2300 		ret = krb5_init_context(&krb5_ctx);
2301 		if(ret){
2302 			return;
2303 		}
2304 	}
2305 
2306 	/* should use a file in the wireshark users dir */
2307 	ret = krb5_kt_resolve(krb5_ctx, filename, &keytab);
2308 	if(ret){
2309 		fprintf(stderr, "KERBEROS ERROR: Could not open keytab file :%s\n",filename);
2310 
2311 		return;
2312 	}
2313 
2314 	ret = krb5_kt_start_seq_get(krb5_ctx, keytab, &cursor);
2315 	if(ret){
2316 		fprintf(stderr, "KERBEROS ERROR: Could not read from keytab file :%s\n",filename);
2317 		return;
2318 	}
2319 
2320 	do{
2321 		ret = krb5_kt_next_entry(krb5_ctx, keytab, &key, &cursor);
2322 		if(ret==0){
2323 			unsigned int i;
2324 			char *pos;
2325 
2326 			new_key = wmem_new0(wmem_epan_scope(), enc_key_t);
2327 			new_key->fd_num = -1;
2328 			new_key->id = ++kerberos_longterm_ids;
2329 			g_snprintf(new_key->id_str, KRB_MAX_ID_STR_LEN, "keytab.%u", new_key->id);
2330 			new_key->next = enc_key_list;
2331 
2332 			/* generate origin string, describing where this key came from */
2333 			pos=new_key->key_origin;
2334 			pos+=MIN(KRB_MAX_ORIG_LEN,
2335 					 g_snprintf(pos, KRB_MAX_ORIG_LEN, "keytab principal "));
2336 			for(i=0;i<key.principal->name.name_string.len;i++){
2337 				pos+=MIN(KRB_MAX_ORIG_LEN-(pos-new_key->key_origin),
2338 						 g_snprintf(pos, KRB_MAX_ORIG_LEN-(pos-new_key->key_origin), "%s%s",(i?"/":""),key.principal->name.name_string.val[i]));
2339 			}
2340 			pos+=MIN(KRB_MAX_ORIG_LEN-(pos-new_key->key_origin),
2341 					 g_snprintf(pos, KRB_MAX_ORIG_LEN-(pos-new_key->key_origin), "@%s",key.principal->realm));
2342 			*pos=0;
2343 			new_key->keytype=key.keyblock.keytype;
2344 			new_key->keylength=(int)key.keyblock.keyvalue.length;
2345 			memcpy(new_key->keyvalue,
2346 			       key.keyblock.keyvalue.data,
2347 			       MIN((guint)key.keyblock.keyvalue.length, KRB_MAX_KEY_LENGTH));
2348 
2349 			enc_key_list=new_key;
2350 			ret = krb5_kt_free_entry(krb5_ctx, &key);
2351 			if (ret) {
2352 				fprintf(stderr, "KERBEROS ERROR: Could not release the entry: %d", ret);
2353 				ret = 0; /* try to continue with the next entry */
2354 			}
2355 			kerberos_key_map_insert(kerberos_longterm_keys, new_key);
2356 		}
2357 	}while(ret==0);
2358 
2359 	ret = krb5_kt_end_seq_get(krb5_ctx, keytab, &cursor);
2360 	if(ret){
2361 		fprintf(stderr, "KERBEROS ERROR: Could not release the keytab cursor: %d", ret);
2362 	}
2363 	ret = krb5_kt_close(krb5_ctx, keytab);
2364 	if(ret){
2365 		fprintf(stderr, "KERBEROS ERROR: Could not close the key table handle: %d", ret);
2366 	}
2367 
2368 }
2369 USES_APPLE_RST
2370 
2371 
2372 guint8 *
2373 decrypt_krb5_data(proto_tree *tree _U_, packet_info *pinfo,
2374 					int usage,
2375 					tvbuff_t *cryptotvb,
2376 					int keytype,
2377 					int *datalen)
2378 {
2379 	kerberos_private_data_t *zero_private = kerberos_new_private_data(pinfo);
2380 	krb5_error_code ret;
2381 	krb5_data data;
2382 	enc_key_t *ek;
2383 	int length = tvb_captured_length(cryptotvb);
2384 	const guint8 *cryptotext = tvb_get_ptr(cryptotvb, 0, length);
2385 
2386 	/* don't do anything if we are not attempting to decrypt data */
2387 	if(!krb_decrypt){
2388 		return NULL;
2389 	}
2390 
2391 	/* make sure we have all the data we need */
2392 	if (tvb_captured_length(cryptotvb) < tvb_reported_length(cryptotvb)) {
2393 		return NULL;
2394 	}
2395 
2396 	read_keytab_file_from_preferences();
2397 
2398 	for(ek=enc_key_list;ek;ek=ek->next){
2399 		krb5_keytab_entry key;
2400 		krb5_crypto crypto;
2401 		guint8 *cryptocopy; /* workaround for pre-0.6.1 heimdal bug */
2402 
2403 		/* shortcircuit and bail out if enctypes are not matching */
2404 		if((keytype != -1) && (ek->keytype != keytype)) {
2405 			continue;
2406 		}
2407 
2408 		key.keyblock.keytype=ek->keytype;
2409 		key.keyblock.keyvalue.length=ek->keylength;
2410 		key.keyblock.keyvalue.data=ek->keyvalue;
2411 		ret = krb5_crypto_init(krb5_ctx, &(key.keyblock), (krb5_enctype)ENCTYPE_NULL, &crypto);
2412 		if(ret){
2413 			return NULL;
2414 		}
2415 
2416 		/* pre-0.6.1 versions of Heimdal would sometimes change
2417 		   the cryptotext data even when the decryption failed.
2418 		   This would obviously not work since we iterate over the
2419 		   keys. So just give it a copy of the crypto data instead.
2420 		   This has been seen for RC4-HMAC blobs.
2421 		*/
2422 		cryptocopy = (guint8 *)wmem_memdup(pinfo->pool, cryptotext, length);
2423 		ret = krb5_decrypt_ivec(krb5_ctx, crypto, usage,
2424 								cryptocopy, length,
2425 								&data,
2426 								NULL);
2427 		if((ret == 0) && (length>0)){
2428 			char *user_data;
2429 
2430 			used_encryption_key(tree, pinfo, zero_private,
2431 					    ek, usage, cryptotvb,
2432 					    "enc_key_list", 0, 0);
2433 
2434 			krb5_crypto_destroy(krb5_ctx, crypto);
2435 			/* return a private wmem_alloced blob to the caller */
2436 			user_data = (char *)wmem_memdup(pinfo->pool, data.data, (guint)data.length);
2437 			if (datalen) {
2438 				*datalen = (int)data.length;
2439 			}
2440 			return user_data;
2441 		}
2442 		krb5_crypto_destroy(krb5_ctx, crypto);
2443 	}
2444 	return NULL;
2445 }
2446 
2447 #define NEED_DECRYPT_KRB5_KRB_CFX_DCE_NOOP 1
2448 
2449 #elif defined (HAVE_LIBNETTLE)
2450 
2451 #define SERVICE_KEY_SIZE (DES3_KEY_SIZE + 2)
2452 #define KEYTYPE_DES3_CBC_MD5 5	/* Currently the only one supported */
2453 
2454 typedef struct _service_key_t {
2455 	guint16 kvno;
2456 	int     keytype;
2457 	int     length;
2458 	guint8 *contents;
2459 	char    origin[KRB_MAX_ORIG_LEN+1];
2460 } service_key_t;
2461 GSList *service_key_list = NULL;
2462 
2463 
2464 static void
2465 add_encryption_key(packet_info *pinfo, int keytype, int keylength, const char *keyvalue, const char *origin)
2466 {
2467 	service_key_t *new_key;
2468 
2469 	if(pinfo->fd->visited){
2470 		return;
2471 	}
2472 
2473 	new_key = g_malloc(sizeof(service_key_t));
2474 	new_key->kvno = 0;
2475 	new_key->keytype = keytype;
2476 	new_key->length = keylength;
2477 	new_key->contents = g_memdup2(keyvalue, keylength);
2478 	g_snprintf(new_key->origin, KRB_MAX_ORIG_LEN, "%s learnt from frame %u", origin, pinfo->num);
2479 	service_key_list = g_slist_append(service_key_list, (gpointer) new_key);
2480 }
2481 
2482 static void
2483 save_encryption_key(tvbuff_t *tvb _U_, int offset _U_, int length _U_,
2484 		    asn1_ctx_t *actx _U_, proto_tree *tree _U_,
2485 		    int parent_hf_index _U_,
2486 		    int hf_index _U_)
2487 {
2488 	kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
2489 	const char *parent = proto_registrar_get_name(parent_hf_index);
2490 	const char *element = proto_registrar_get_name(hf_index);
2491 	char origin[KRB_MAX_ORIG_LEN] = { 0, };
2492 
2493 	g_snprintf(origin, KRB_MAX_ORIG_LEN, "%s_%s", parent, element);
2494 
2495 	add_encryption_key(actx->pinfo,
2496 			   private_data->key.keytype,
2497 			   private_data->key.keylength,
2498 			   private_data->key.keyvalue,
2499 			   origin);
2500 }
2501 
2502 static void
2503 save_Authenticator_subkey(tvbuff_t *tvb, int offset, int length,
2504 			  asn1_ctx_t *actx, proto_tree *tree,
2505 			  int parent_hf_index,
2506 			  int hf_index)
2507 {
2508 	save_encryption_key(tvb, offset, length, actx, tree, parent_hf_index, hf_index);
2509 }
2510 
2511 static void
2512 save_EncAPRepPart_subkey(tvbuff_t *tvb, int offset, int length,
2513 			 asn1_ctx_t *actx, proto_tree *tree,
2514 			 int parent_hf_index,
2515 			 int hf_index)
2516 {
2517 	save_encryption_key(tvb, offset, length, actx, tree, parent_hf_index, hf_index);
2518 }
2519 
2520 static void
2521 save_EncKDCRepPart_key(tvbuff_t *tvb, int offset, int length,
2522 		       asn1_ctx_t *actx, proto_tree *tree,
2523 		       int parent_hf_index,
2524 		       int hf_index)
2525 {
2526 	save_encryption_key(tvb, offset, length, actx, tree, parent_hf_index, hf_index);
2527 }
2528 
2529 static void
2530 save_EncTicketPart_key(tvbuff_t *tvb, int offset, int length,
2531 		       asn1_ctx_t *actx, proto_tree *tree,
2532 		       int parent_hf_index,
2533 		       int hf_index)
2534 {
2535 	save_encryption_key(tvb, offset, length, actx, tree, parent_hf_index, hf_index);
2536 }
2537 
2538 static void
2539 save_KrbCredInfo_key(tvbuff_t *tvb, int offset, int length,
2540 		     asn1_ctx_t *actx, proto_tree *tree,
2541 		     int parent_hf_index,
2542 		     int hf_index)
2543 {
2544 	save_encryption_key(tvb, offset, length, actx, tree, parent_hf_index, hf_index);
2545 }
2546 
2547 static void
2548 save_KrbFastResponse_strengthen_key(tvbuff_t *tvb _U_, int offset _U_, int length _U_,
2549 				    asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_)
2550 {
2551 	save_encryption_key(tvb, offset, length, actx, tree, hf_index);
2552 }
2553 
2554 static void
2555 clear_keytab(void) {
2556 	GSList *ske;
2557 	service_key_t *sk;
2558 
2559 	for(ske = service_key_list; ske != NULL; ske = g_slist_next(ske)){
2560 		sk = (service_key_t *) ske->data;
2561 		if (sk) {
2562 			g_free(sk->contents);
2563 			g_free(sk);
2564 		}
2565 	}
2566 	g_slist_free(service_key_list);
2567 	service_key_list = NULL;
2568 }
2569 
2570 static void
2571 read_keytab_file(const char *service_key_file)
2572 {
2573 	FILE *skf;
2574 	ws_statb64 st;
2575 	service_key_t *sk;
2576 	unsigned char buf[SERVICE_KEY_SIZE];
2577 	int newline_skip = 0, count = 0;
2578 
2579 	if (service_key_file != NULL && ws_stat64 (service_key_file, &st) == 0) {
2580 
2581 		/* The service key file contains raw 192-bit (24 byte) 3DES keys.
2582 		 * There can be zero, one (\n), or two (\r\n) characters between
2583 		 * keys.  Trailing characters are ignored.
2584 		 */
2585 
2586 		/* XXX We should support the standard keytab format instead */
2587 		if (st.st_size > SERVICE_KEY_SIZE) {
2588 			if ( (st.st_size % (SERVICE_KEY_SIZE + 1) == 0) ||
2589 				 (st.st_size % (SERVICE_KEY_SIZE + 1) == SERVICE_KEY_SIZE) ) {
2590 				newline_skip = 1;
2591 			} else if ( (st.st_size % (SERVICE_KEY_SIZE + 2) == 0) ||
2592 				 (st.st_size % (SERVICE_KEY_SIZE + 2) == SERVICE_KEY_SIZE) ) {
2593 				newline_skip = 2;
2594 			}
2595 		}
2596 
2597 		skf = ws_fopen(service_key_file, "rb");
2598 		if (! skf) return;
2599 
2600 		while (fread(buf, SERVICE_KEY_SIZE, 1, skf) == 1) {
2601 			sk = g_malloc(sizeof(service_key_t));
2602 			sk->kvno = buf[0] << 8 | buf[1];
2603 			sk->keytype = KEYTYPE_DES3_CBC_MD5;
2604 			sk->length = DES3_KEY_SIZE;
2605 			sk->contents = g_memdup2(buf + 2, DES3_KEY_SIZE);
2606 			g_snprintf(sk->origin, KRB_MAX_ORIG_LEN, "3DES service key file, key #%d, offset %ld", count, ftell(skf));
2607 			service_key_list = g_slist_append(service_key_list, (gpointer) sk);
2608 			if (fseek(skf, newline_skip, SEEK_CUR) < 0) {
2609 				fprintf(stderr, "unable to seek...\n");
2610 				fclose(skf);
2611 				return;
2612 			}
2613 			count++;
2614 		}
2615 		fclose(skf);
2616 	}
2617 }
2618 
2619 #define CONFOUNDER_PLUS_CHECKSUM 24
2620 
2621 guint8 *
2622 decrypt_krb5_data(proto_tree *tree, packet_info *pinfo,
2623 					int _U_ usage,
2624 					tvbuff_t *cryptotvb,
2625 					int keytype,
2626 					int *datalen)
2627 {
2628 	tvbuff_t *encr_tvb;
2629 	guint8 *decrypted_data = NULL, *plaintext = NULL;
2630 	guint8 cls;
2631 	gboolean pc;
2632 	guint32 tag, item_len, data_len;
2633 	int id_offset, offset;
2634 	guint8 key[DES3_KEY_SIZE];
2635 	guint8 initial_vector[DES_BLOCK_SIZE];
2636 	gcry_md_hd_t md5_handle;
2637 	guint8 *digest;
2638 	guint8 zero_fill[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
2639 	guint8 confounder[8];
2640 	gboolean ind;
2641 	GSList *ske;
2642 	service_key_t *sk;
2643 	struct des3_ctx ctx;
2644 	int length = tvb_captured_length(cryptotvb);
2645 	const guint8 *cryptotext = tvb_get_ptr(cryptotvb, 0, length);
2646 
2647 
2648 	/* don't do anything if we are not attempting to decrypt data */
2649 	if(!krb_decrypt){
2650 		return NULL;
2651 	}
2652 
2653 	/* make sure we have all the data we need */
2654 	if (tvb_captured_length(cryptotvb) < tvb_reported_length(cryptotvb)) {
2655 		return NULL;
2656 	}
2657 
2658 	if (keytype != KEYTYPE_DES3_CBC_MD5 || service_key_list == NULL) {
2659 		return NULL;
2660 	}
2661 
2662 	decrypted_data = wmem_alloc(pinfo->pool, length);
2663 	for(ske = service_key_list; ske != NULL; ske = g_slist_next(ske)){
2664 		gboolean do_continue = FALSE;
2665 		gboolean digest_ok;
2666 		sk = (service_key_t *) ske->data;
2667 
2668 		des_fix_parity(DES3_KEY_SIZE, key, sk->contents);
2669 
2670 		memset(initial_vector, 0, DES_BLOCK_SIZE);
2671 		des3_set_key(&ctx, key);
2672 		cbc_decrypt(&ctx, des3_decrypt, DES_BLOCK_SIZE, initial_vector,
2673 					length, decrypted_data, cryptotext);
2674 		encr_tvb = tvb_new_real_data(decrypted_data, length, length);
2675 
2676 		tvb_memcpy(encr_tvb, confounder, 0, 8);
2677 
2678 		/* We have to pull the decrypted data length from the decrypted
2679 		 * content.  If the key doesn't match or we otherwise get garbage,
2680 		 * an exception may get thrown while decoding the ASN.1 header.
2681 		 * Catch it, just in case.
2682 		 */
2683 		TRY {
2684 			id_offset = get_ber_identifier(encr_tvb, CONFOUNDER_PLUS_CHECKSUM, &cls, &pc, &tag);
2685 			offset = get_ber_length(encr_tvb, id_offset, &item_len, &ind);
2686 		}
2687 		CATCH_BOUNDS_ERRORS {
2688 			tvb_free(encr_tvb);
2689 			do_continue = TRUE;
2690 		}
2691 		ENDTRY;
2692 
2693 		if (do_continue) continue;
2694 
2695 		data_len = item_len + offset - CONFOUNDER_PLUS_CHECKSUM;
2696 		if ((int) item_len + offset > length) {
2697 			tvb_free(encr_tvb);
2698 			continue;
2699 		}
2700 
2701 		if (gcry_md_open(&md5_handle, GCRY_MD_MD5, 0)) {
2702 			return NULL;
2703 		}
2704 		gcry_md_write(md5_handle, confounder, 8);
2705 		gcry_md_write(md5_handle, zero_fill, 16);
2706 		gcry_md_write(md5_handle, decrypted_data + CONFOUNDER_PLUS_CHECKSUM, data_len);
2707 		digest = gcry_md_read(md5_handle, 0);
2708 
2709 		digest_ok = (tvb_memeql (encr_tvb, 8, digest, HASH_MD5_LENGTH) == 0);
2710 		gcry_md_close(md5_handle);
2711 		if (digest_ok) {
2712 			plaintext = (guint8* )tvb_memdup(pinfo->pool, encr_tvb, CONFOUNDER_PLUS_CHECKSUM, data_len);
2713 			tvb_free(encr_tvb);
2714 
2715 			if (datalen) {
2716 				*datalen = data_len;
2717 			}
2718 			return(plaintext);
2719 		}
2720 		tvb_free(encr_tvb);
2721 	}
2722 
2723 	return NULL;
2724 }
2725 
2726 #endif	/* HAVE_MIT_KERBEROS / HAVE_HEIMDAL_KERBEROS / HAVE_LIBNETTLE */
2727 
2728 #ifdef NEED_DECRYPT_KRB5_KRB_CFX_DCE_NOOP
2729 tvbuff_t *
2730 decrypt_krb5_krb_cfx_dce(proto_tree *tree _U_,
2731 			 packet_info *pinfo _U_,
2732 			 int usage _U_,
2733 			 int keytype _U_,
2734 			 tvbuff_t *gssapi_header_tvb _U_,
2735 			 tvbuff_t *gssapi_encrypted_tvb _U_,
2736 			 tvbuff_t *gssapi_trailer_tvb _U_,
2737 			 tvbuff_t *checksum_tvb _U_)
2738 {
2739 	return NULL;
2740 }
2741 #endif /* NEED_DECRYPT_KRB5_KRB_CFX_DCE_NOOP */
2742 
2743 #define	INET6_ADDRLEN	16
2744 
2745 /* TCP Record Mark */
2746 #define	KRB_RM_RESERVED	0x80000000U
2747 #define	KRB_RM_RECLEN	0x7fffffffU
2748 
2749 #define KRB5_MSG_TICKET			1	/* Ticket */
2750 #define KRB5_MSG_AUTHENTICATOR		2	/* Authenticator */
2751 #define KRB5_MSG_ENC_TICKET_PART	3	/* EncTicketPart */
2752 #define KRB5_MSG_AS_REQ			10	/* AS-REQ type */
2753 #define KRB5_MSG_AS_REP			11	/* AS-REP type */
2754 #define KRB5_MSG_TGS_REQ		12	/* TGS-REQ type */
2755 #define KRB5_MSG_TGS_REP		13	/* TGS-REP type */
2756 #define KRB5_MSG_AP_REQ			14	/* AP-REQ type */
2757 #define KRB5_MSG_AP_REP			15	/* AP-REP type */
2758 #define KRB5_MSG_TGT_REQ		16	/* TGT-REQ type */
2759 #define KRB5_MSG_TGT_REP		17	/* TGT-REP type */
2760 
2761 #define KRB5_MSG_SAFE			20	/* KRB-SAFE type */
2762 #define KRB5_MSG_PRIV			21	/* KRB-PRIV type */
2763 #define KRB5_MSG_CRED			22	/* KRB-CRED type */
2764 #define KRB5_MSG_ENC_AS_REP_PART	25	/* EncASRepPart */
2765 #define KRB5_MSG_ENC_TGS_REP_PART	26	/* EncTGSRepPart */
2766 #define KRB5_MSG_ENC_AP_REP_PART	27	/* EncAPRepPart */
2767 #define KRB5_MSG_ENC_KRB_PRIV_PART	28	/* EncKrbPrivPart */
2768 #define KRB5_MSG_ENC_KRB_CRED_PART	29	/* EncKrbCredPart */
2769 #define KRB5_MSG_ERROR			30	/* KRB-ERROR type */
2770 
2771 #define KRB5_CHKSUM_GSSAPI		0x8003
2772 /*
2773  * For KERB_ENCTYPE_RC4_HMAC and KERB_ENCTYPE_RC4_HMAC_EXP, see
2774  *
2775  *	https://tools.ietf.org/html/draft-brezak-win2k-krb-rc4-hmac-04
2776  *
2777  * unless it's expired.
2778  */
2779 
2780 /* Principal name-type */
2781 #define KRB5_NT_UNKNOWN		0
2782 #define KRB5_NT_PRINCIPAL	1
2783 #define KRB5_NT_SRV_INST	2
2784 #define KRB5_NT_SRV_HST		3
2785 #define KRB5_NT_SRV_XHST	4
2786 #define KRB5_NT_UID		5
2787 #define KRB5_NT_X500_PRINCIPAL	6
2788 #define KRB5_NT_SMTP_NAME	7
2789 #define KRB5_NT_ENTERPRISE	10
2790 
2791 /*
2792  * MS specific name types, from
2793  *
2794  *	http://msdn.microsoft.com/library/en-us/security/security/kerb_external_name.asp
2795  */
2796 #define KRB5_NT_MS_PRINCIPAL		-128
2797 #define KRB5_NT_MS_PRINCIPAL_AND_SID	-129
2798 #define KRB5_NT_ENT_PRINCIPAL_AND_SID	-130
2799 #define KRB5_NT_PRINCIPAL_AND_SID 	-131
2800 #define KRB5_NT_SRV_INST_AND_SID	-132
2801 
2802 /* error table constants */
2803 /* I prefixed the krb5_err.et constant names with KRB5_ET_ for these */
2804 #define KRB5_ET_KRB5KDC_ERR_NONE			0
2805 #define KRB5_ET_KRB5KDC_ERR_NAME_EXP			1
2806 #define KRB5_ET_KRB5KDC_ERR_SERVICE_EXP			2
2807 #define KRB5_ET_KRB5KDC_ERR_BAD_PVNO			3
2808 #define KRB5_ET_KRB5KDC_ERR_C_OLD_MAST_KVNO		4
2809 #define KRB5_ET_KRB5KDC_ERR_S_OLD_MAST_KVNO		5
2810 #define KRB5_ET_KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN		6
2811 #define KRB5_ET_KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN		7
2812 #define KRB5_ET_KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE	8
2813 #define KRB5_ET_KRB5KDC_ERR_NULL_KEY			9
2814 #define KRB5_ET_KRB5KDC_ERR_CANNOT_POSTDATE		10
2815 #define KRB5_ET_KRB5KDC_ERR_NEVER_VALID			11
2816 #define KRB5_ET_KRB5KDC_ERR_POLICY			12
2817 #define KRB5_ET_KRB5KDC_ERR_BADOPTION			13
2818 #define KRB5_ET_KRB5KDC_ERR_ETYPE_NOSUPP		14
2819 #define KRB5_ET_KRB5KDC_ERR_SUMTYPE_NOSUPP		15
2820 #define KRB5_ET_KRB5KDC_ERR_PADATA_TYPE_NOSUPP		16
2821 #define KRB5_ET_KRB5KDC_ERR_TRTYPE_NOSUPP		17
2822 #define KRB5_ET_KRB5KDC_ERR_CLIENT_REVOKED		18
2823 #define KRB5_ET_KRB5KDC_ERR_SERVICE_REVOKED		19
2824 #define KRB5_ET_KRB5KDC_ERR_TGT_REVOKED			20
2825 #define KRB5_ET_KRB5KDC_ERR_CLIENT_NOTYET		21
2826 #define KRB5_ET_KRB5KDC_ERR_SERVICE_NOTYET		22
2827 #define KRB5_ET_KRB5KDC_ERR_KEY_EXP			23
2828 #define KRB5_ET_KRB5KDC_ERR_PREAUTH_FAILED		24
2829 #define KRB5_ET_KRB5KDC_ERR_PREAUTH_REQUIRED		25
2830 #define KRB5_ET_KRB5KDC_ERR_SERVER_NOMATCH		26
2831 #define KRB5_ET_KRB5KDC_ERR_MUST_USE_USER2USER		27
2832 #define KRB5_ET_KRB5KDC_ERR_PATH_NOT_ACCEPTED		28
2833 #define KRB5_ET_KRB5KDC_ERR_SVC_UNAVAILABLE		29
2834 #define KRB5_ET_KRB5KRB_AP_ERR_BAD_INTEGRITY		31
2835 #define KRB5_ET_KRB5KRB_AP_ERR_TKT_EXPIRED		32
2836 #define KRB5_ET_KRB5KRB_AP_ERR_TKT_NYV			33
2837 #define KRB5_ET_KRB5KRB_AP_ERR_REPEAT			34
2838 #define KRB5_ET_KRB5KRB_AP_ERR_NOT_US			35
2839 #define KRB5_ET_KRB5KRB_AP_ERR_BADMATCH			36
2840 #define KRB5_ET_KRB5KRB_AP_ERR_SKEW			37
2841 #define KRB5_ET_KRB5KRB_AP_ERR_BADADDR			38
2842 #define KRB5_ET_KRB5KRB_AP_ERR_BADVERSION		39
2843 #define KRB5_ET_KRB5KRB_AP_ERR_MSG_TYPE			40
2844 #define KRB5_ET_KRB5KRB_AP_ERR_MODIFIED			41
2845 #define KRB5_ET_KRB5KRB_AP_ERR_BADORDER			42
2846 #define KRB5_ET_KRB5KRB_AP_ERR_ILL_CR_TKT		43
2847 #define KRB5_ET_KRB5KRB_AP_ERR_BADKEYVER		44
2848 #define KRB5_ET_KRB5KRB_AP_ERR_NOKEY			45
2849 #define KRB5_ET_KRB5KRB_AP_ERR_MUT_FAIL			46
2850 #define KRB5_ET_KRB5KRB_AP_ERR_BADDIRECTION		47
2851 #define KRB5_ET_KRB5KRB_AP_ERR_METHOD			48
2852 #define KRB5_ET_KRB5KRB_AP_ERR_BADSEQ			49
2853 #define KRB5_ET_KRB5KRB_AP_ERR_INAPP_CKSUM		50
2854 #define KRB5_ET_KRB5KDC_AP_PATH_NOT_ACCEPTED		51
2855 #define KRB5_ET_KRB5KRB_ERR_RESPONSE_TOO_BIG		52
2856 #define KRB5_ET_KRB5KRB_ERR_GENERIC			60
2857 #define KRB5_ET_KRB5KRB_ERR_FIELD_TOOLONG		61
2858 #define KRB5_ET_KDC_ERROR_CLIENT_NOT_TRUSTED		62
2859 #define KRB5_ET_KDC_ERROR_KDC_NOT_TRUSTED		63
2860 #define KRB5_ET_KDC_ERROR_INVALID_SIG			64
2861 #define KRB5_ET_KDC_ERR_KEY_TOO_WEAK			65
2862 #define KRB5_ET_KDC_ERR_CERTIFICATE_MISMATCH		66
2863 #define KRB5_ET_KRB_AP_ERR_NO_TGT			67
2864 #define KRB5_ET_KDC_ERR_WRONG_REALM			68
2865 #define KRB5_ET_KRB_AP_ERR_USER_TO_USER_REQUIRED	69
2866 #define KRB5_ET_KDC_ERR_CANT_VERIFY_CERTIFICATE		70
2867 #define KRB5_ET_KDC_ERR_INVALID_CERTIFICATE		71
2868 #define KRB5_ET_KDC_ERR_REVOKED_CERTIFICATE		72
2869 #define KRB5_ET_KDC_ERR_REVOCATION_STATUS_UNKNOWN	73
2870 #define KRB5_ET_KDC_ERR_REVOCATION_STATUS_UNAVAILABLE	74
2871 #define KRB5_ET_KDC_ERR_CLIENT_NAME_MISMATCH		75
2872 #define KRB5_ET_KDC_ERR_KDC_NAME_MISMATCH		76
2873 #define KRB5_ET_KDC_ERR_PREAUTH_EXPIRED			90
2874 #define KRB5_ET_KDC_ERR_MORE_PREAUTH_DATA_REQUIRED	91
2875 #define KRB5_ET_KDC_ERR_PREAUTH_BAD_AUTHENTICATION_SET	92
2876 #define KRB5_ET_KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS	93
2877 
2878 static const value_string krb5_error_codes[] = {
2879 	{ KRB5_ET_KRB5KDC_ERR_NONE, "KRB5KDC_ERR_NONE" },
2880 	{ KRB5_ET_KRB5KDC_ERR_NAME_EXP, "KRB5KDC_ERR_NAME_EXP" },
2881 	{ KRB5_ET_KRB5KDC_ERR_SERVICE_EXP, "KRB5KDC_ERR_SERVICE_EXP" },
2882 	{ KRB5_ET_KRB5KDC_ERR_BAD_PVNO, "KRB5KDC_ERR_BAD_PVNO" },
2883 	{ KRB5_ET_KRB5KDC_ERR_C_OLD_MAST_KVNO, "KRB5KDC_ERR_C_OLD_MAST_KVNO" },
2884 	{ KRB5_ET_KRB5KDC_ERR_S_OLD_MAST_KVNO, "KRB5KDC_ERR_S_OLD_MAST_KVNO" },
2885 	{ KRB5_ET_KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN, "KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN" },
2886 	{ KRB5_ET_KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN, "KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN" },
2887 	{ KRB5_ET_KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE, "KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE" },
2888 	{ KRB5_ET_KRB5KDC_ERR_NULL_KEY, "KRB5KDC_ERR_NULL_KEY" },
2889 	{ KRB5_ET_KRB5KDC_ERR_CANNOT_POSTDATE, "KRB5KDC_ERR_CANNOT_POSTDATE" },
2890 	{ KRB5_ET_KRB5KDC_ERR_NEVER_VALID, "KRB5KDC_ERR_NEVER_VALID" },
2891 	{ KRB5_ET_KRB5KDC_ERR_POLICY, "KRB5KDC_ERR_POLICY" },
2892 	{ KRB5_ET_KRB5KDC_ERR_BADOPTION, "KRB5KDC_ERR_BADOPTION" },
2893 	{ KRB5_ET_KRB5KDC_ERR_ETYPE_NOSUPP, "KRB5KDC_ERR_ETYPE_NOSUPP" },
2894 	{ KRB5_ET_KRB5KDC_ERR_SUMTYPE_NOSUPP, "KRB5KDC_ERR_SUMTYPE_NOSUPP" },
2895 	{ KRB5_ET_KRB5KDC_ERR_PADATA_TYPE_NOSUPP, "KRB5KDC_ERR_PADATA_TYPE_NOSUPP" },
2896 	{ KRB5_ET_KRB5KDC_ERR_TRTYPE_NOSUPP, "KRB5KDC_ERR_TRTYPE_NOSUPP" },
2897 	{ KRB5_ET_KRB5KDC_ERR_CLIENT_REVOKED, "KRB5KDC_ERR_CLIENT_REVOKED" },
2898 	{ KRB5_ET_KRB5KDC_ERR_SERVICE_REVOKED, "KRB5KDC_ERR_SERVICE_REVOKED" },
2899 	{ KRB5_ET_KRB5KDC_ERR_TGT_REVOKED, "KRB5KDC_ERR_TGT_REVOKED" },
2900 	{ KRB5_ET_KRB5KDC_ERR_CLIENT_NOTYET, "KRB5KDC_ERR_CLIENT_NOTYET" },
2901 	{ KRB5_ET_KRB5KDC_ERR_SERVICE_NOTYET, "KRB5KDC_ERR_SERVICE_NOTYET" },
2902 	{ KRB5_ET_KRB5KDC_ERR_KEY_EXP, "KRB5KDC_ERR_KEY_EXP" },
2903 	{ KRB5_ET_KRB5KDC_ERR_PREAUTH_FAILED, "KRB5KDC_ERR_PREAUTH_FAILED" },
2904 	{ KRB5_ET_KRB5KDC_ERR_PREAUTH_REQUIRED, "KRB5KDC_ERR_PREAUTH_REQUIRED" },
2905 	{ KRB5_ET_KRB5KDC_ERR_SERVER_NOMATCH, "KRB5KDC_ERR_SERVER_NOMATCH" },
2906 	{ KRB5_ET_KRB5KDC_ERR_MUST_USE_USER2USER, "KRB5KDC_ERR_MUST_USE_USER2USER" },
2907 	{ KRB5_ET_KRB5KDC_ERR_PATH_NOT_ACCEPTED, "KRB5KDC_ERR_PATH_NOT_ACCEPTED" },
2908 	{ KRB5_ET_KRB5KDC_ERR_SVC_UNAVAILABLE, "KRB5KDC_ERR_SVC_UNAVAILABLE" },
2909 	{ KRB5_ET_KRB5KRB_AP_ERR_BAD_INTEGRITY, "KRB5KRB_AP_ERR_BAD_INTEGRITY" },
2910 	{ KRB5_ET_KRB5KRB_AP_ERR_TKT_EXPIRED, "KRB5KRB_AP_ERR_TKT_EXPIRED" },
2911 	{ KRB5_ET_KRB5KRB_AP_ERR_TKT_NYV, "KRB5KRB_AP_ERR_TKT_NYV" },
2912 	{ KRB5_ET_KRB5KRB_AP_ERR_REPEAT, "KRB5KRB_AP_ERR_REPEAT" },
2913 	{ KRB5_ET_KRB5KRB_AP_ERR_NOT_US, "KRB5KRB_AP_ERR_NOT_US" },
2914 	{ KRB5_ET_KRB5KRB_AP_ERR_BADMATCH, "KRB5KRB_AP_ERR_BADMATCH" },
2915 	{ KRB5_ET_KRB5KRB_AP_ERR_SKEW, "KRB5KRB_AP_ERR_SKEW" },
2916 	{ KRB5_ET_KRB5KRB_AP_ERR_BADADDR, "KRB5KRB_AP_ERR_BADADDR" },
2917 	{ KRB5_ET_KRB5KRB_AP_ERR_BADVERSION, "KRB5KRB_AP_ERR_BADVERSION" },
2918 	{ KRB5_ET_KRB5KRB_AP_ERR_MSG_TYPE, "KRB5KRB_AP_ERR_MSG_TYPE" },
2919 	{ KRB5_ET_KRB5KRB_AP_ERR_MODIFIED, "KRB5KRB_AP_ERR_MODIFIED" },
2920 	{ KRB5_ET_KRB5KRB_AP_ERR_BADORDER, "KRB5KRB_AP_ERR_BADORDER" },
2921 	{ KRB5_ET_KRB5KRB_AP_ERR_ILL_CR_TKT, "KRB5KRB_AP_ERR_ILL_CR_TKT" },
2922 	{ KRB5_ET_KRB5KRB_AP_ERR_BADKEYVER, "KRB5KRB_AP_ERR_BADKEYVER" },
2923 	{ KRB5_ET_KRB5KRB_AP_ERR_NOKEY, "KRB5KRB_AP_ERR_NOKEY" },
2924 	{ KRB5_ET_KRB5KRB_AP_ERR_MUT_FAIL, "KRB5KRB_AP_ERR_MUT_FAIL" },
2925 	{ KRB5_ET_KRB5KRB_AP_ERR_BADDIRECTION, "KRB5KRB_AP_ERR_BADDIRECTION" },
2926 	{ KRB5_ET_KRB5KRB_AP_ERR_METHOD, "KRB5KRB_AP_ERR_METHOD" },
2927 	{ KRB5_ET_KRB5KRB_AP_ERR_BADSEQ, "KRB5KRB_AP_ERR_BADSEQ" },
2928 	{ KRB5_ET_KRB5KRB_AP_ERR_INAPP_CKSUM, "KRB5KRB_AP_ERR_INAPP_CKSUM" },
2929 	{ KRB5_ET_KRB5KDC_AP_PATH_NOT_ACCEPTED, "KRB5KDC_AP_PATH_NOT_ACCEPTED" },
2930 	{ KRB5_ET_KRB5KRB_ERR_RESPONSE_TOO_BIG, "KRB5KRB_ERR_RESPONSE_TOO_BIG"},
2931 	{ KRB5_ET_KRB5KRB_ERR_GENERIC, "KRB5KRB_ERR_GENERIC" },
2932 	{ KRB5_ET_KRB5KRB_ERR_FIELD_TOOLONG, "KRB5KRB_ERR_FIELD_TOOLONG" },
2933 	{ KRB5_ET_KDC_ERROR_CLIENT_NOT_TRUSTED, "KDC_ERROR_CLIENT_NOT_TRUSTED" },
2934 	{ KRB5_ET_KDC_ERROR_KDC_NOT_TRUSTED, "KDC_ERROR_KDC_NOT_TRUSTED" },
2935 	{ KRB5_ET_KDC_ERROR_INVALID_SIG, "KDC_ERROR_INVALID_SIG" },
2936 	{ KRB5_ET_KDC_ERR_KEY_TOO_WEAK, "KDC_ERR_KEY_TOO_WEAK" },
2937 	{ KRB5_ET_KDC_ERR_CERTIFICATE_MISMATCH, "KDC_ERR_CERTIFICATE_MISMATCH" },
2938 	{ KRB5_ET_KRB_AP_ERR_NO_TGT, "KRB_AP_ERR_NO_TGT" },
2939 	{ KRB5_ET_KDC_ERR_WRONG_REALM, "KDC_ERR_WRONG_REALM" },
2940 	{ KRB5_ET_KRB_AP_ERR_USER_TO_USER_REQUIRED, "KRB_AP_ERR_USER_TO_USER_REQUIRED" },
2941 	{ KRB5_ET_KDC_ERR_CANT_VERIFY_CERTIFICATE, "KDC_ERR_CANT_VERIFY_CERTIFICATE" },
2942 	{ KRB5_ET_KDC_ERR_INVALID_CERTIFICATE, "KDC_ERR_INVALID_CERTIFICATE" },
2943 	{ KRB5_ET_KDC_ERR_REVOKED_CERTIFICATE, "KDC_ERR_REVOKED_CERTIFICATE" },
2944 	{ KRB5_ET_KDC_ERR_REVOCATION_STATUS_UNKNOWN, "KDC_ERR_REVOCATION_STATUS_UNKNOWN" },
2945 	{ KRB5_ET_KDC_ERR_REVOCATION_STATUS_UNAVAILABLE, "KDC_ERR_REVOCATION_STATUS_UNAVAILABLE" },
2946 	{ KRB5_ET_KDC_ERR_CLIENT_NAME_MISMATCH, "KDC_ERR_CLIENT_NAME_MISMATCH" },
2947 	{ KRB5_ET_KDC_ERR_KDC_NAME_MISMATCH, "KDC_ERR_KDC_NAME_MISMATCH" },
2948 	{ KRB5_ET_KDC_ERR_PREAUTH_EXPIRED, "KDC_ERR_PREAUTH_EXPIRED" },
2949 	{ KRB5_ET_KDC_ERR_MORE_PREAUTH_DATA_REQUIRED, "KDC_ERR_MORE_PREAUTH_DATA_REQUIRED" },
2950 	{ KRB5_ET_KDC_ERR_PREAUTH_BAD_AUTHENTICATION_SET, "KDC_ERR_PREAUTH_BAD_AUTHENTICATION_SET" },
2951 	{ KRB5_ET_KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS, "KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS" },
2952 	{ 0, NULL }
2953 };
2954 
2955 
2956 #define PAC_LOGON_INFO		1
2957 #define PAC_CREDENTIAL_TYPE	2
2958 #define PAC_SERVER_CHECKSUM	6
2959 #define PAC_PRIVSVR_CHECKSUM	7
2960 #define PAC_CLIENT_INFO_TYPE	10
2961 #define PAC_S4U_DELEGATION_INFO	11
2962 #define PAC_UPN_DNS_INFO	12
2963 #define PAC_CLIENT_CLAIMS_INFO	13
2964 #define PAC_DEVICE_INFO		14
2965 #define PAC_DEVICE_CLAIMS_INFO	15
2966 #define PAC_TICKET_CHECKSUM	16
2967 static const value_string w2k_pac_types[] = {
2968 	{ PAC_LOGON_INFO		, "Logon Info" },
2969 	{ PAC_CREDENTIAL_TYPE		, "Credential Type" },
2970 	{ PAC_SERVER_CHECKSUM		, "Server Checksum" },
2971 	{ PAC_PRIVSVR_CHECKSUM		, "Privsvr Checksum" },
2972 	{ PAC_CLIENT_INFO_TYPE		, "Client Info Type" },
2973 	{ PAC_S4U_DELEGATION_INFO	, "S4U Delegation Info" },
2974 	{ PAC_UPN_DNS_INFO		, "UPN DNS Info" },
2975 	{ PAC_CLIENT_CLAIMS_INFO	, "Client Claims Info" },
2976 	{ PAC_DEVICE_INFO		, "Device Info" },
2977 	{ PAC_DEVICE_CLAIMS_INFO	, "Device Claims Info" },
2978 	{ PAC_TICKET_CHECKSUM		, "Ticket Checksum" },
2979 	{ 0, NULL },
2980 };
2981 
2982 static const value_string krb5_msg_types[] = {
2983 	{ KRB5_MSG_TICKET,		"Ticket" },
2984 	{ KRB5_MSG_AUTHENTICATOR,	"Authenticator" },
2985 	{ KRB5_MSG_ENC_TICKET_PART,	"EncTicketPart" },
2986 	{ KRB5_MSG_TGS_REQ,		"TGS-REQ" },
2987 	{ KRB5_MSG_TGS_REP,		"TGS-REP" },
2988 	{ KRB5_MSG_AS_REQ,		"AS-REQ" },
2989 	{ KRB5_MSG_AS_REP,		"AS-REP" },
2990 	{ KRB5_MSG_AP_REQ,		"AP-REQ" },
2991 	{ KRB5_MSG_AP_REP,		"AP-REP" },
2992 	{ KRB5_MSG_TGT_REQ,		"TGT-REQ" },
2993 	{ KRB5_MSG_TGT_REP,		"TGT-REP" },
2994 	{ KRB5_MSG_SAFE,		"KRB-SAFE" },
2995 	{ KRB5_MSG_PRIV,		"KRB-PRIV" },
2996 	{ KRB5_MSG_CRED,		"KRB-CRED" },
2997 	{ KRB5_MSG_ENC_AS_REP_PART,	"EncASRepPart" },
2998 	{ KRB5_MSG_ENC_TGS_REP_PART,	"EncTGSRepPart" },
2999 	{ KRB5_MSG_ENC_AP_REP_PART,	"EncAPRepPart" },
3000 	{ KRB5_MSG_ENC_KRB_PRIV_PART,	"EncKrbPrivPart" },
3001 	{ KRB5_MSG_ENC_KRB_CRED_PART,	"EncKrbCredPart" },
3002 	{ KRB5_MSG_ERROR,		"KRB-ERROR" },
3003 	{ 0, NULL },
3004 };
3005 
3006 #define KRB5_GSS_C_DELEG_FLAG             0x01
3007 #define KRB5_GSS_C_MUTUAL_FLAG            0x02
3008 #define KRB5_GSS_C_REPLAY_FLAG            0x04
3009 #define KRB5_GSS_C_SEQUENCE_FLAG          0x08
3010 #define KRB5_GSS_C_CONF_FLAG              0x10
3011 #define KRB5_GSS_C_INTEG_FLAG             0x20
3012 #define KRB5_GSS_C_DCE_STYLE            0x1000
3013 
3014 static const true_false_string tfs_gss_flags_deleg = {
3015 	"Delegate credentials to remote peer",
3016 	"Do NOT delegate"
3017 };
3018 static const true_false_string tfs_gss_flags_mutual = {
3019 	"Request that remote peer authenticates itself",
3020 	"Mutual authentication NOT required"
3021 };
3022 static const true_false_string tfs_gss_flags_replay = {
3023 	"Enable replay protection for signed or sealed messages",
3024 	"Do NOT enable replay protection"
3025 };
3026 static const true_false_string tfs_gss_flags_sequence = {
3027 	"Enable Out-of-sequence detection for sign or sealed messages",
3028 	"Do NOT enable out-of-sequence detection"
3029 };
3030 static const true_false_string tfs_gss_flags_conf = {
3031 	"Confidentiality (sealing) may be invoked",
3032 	"Do NOT use Confidentiality (sealing)"
3033 };
3034 static const true_false_string tfs_gss_flags_integ = {
3035 	"Integrity protection (signing) may be invoked",
3036 	"Do NOT use integrity protection"
3037 };
3038 
3039 static const true_false_string tfs_gss_flags_dce_style = {
3040 	"DCE-STYLE",
3041 	"Not using DCE-STYLE"
3042 };
3043 
3044 #ifdef HAVE_KERBEROS
3045 static guint8 *
3046 decrypt_krb5_data_asn1(proto_tree *tree, asn1_ctx_t *actx,
3047 		       int usage, tvbuff_t *cryptotvb, int *datalen)
3048 {
3049 	kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
3050 
3051 #ifdef HAVE_DECRYPT_KRB5_DATA_PRIVATE
3052 	return decrypt_krb5_data_private(tree, actx->pinfo, private_data,
3053 					 usage, cryptotvb,
3054 					 private_data->etype,
3055 					 datalen);
3056 #else
3057 	return decrypt_krb5_data(tree, actx->pinfo, usage, cryptotvb,
3058 				 private_data->etype, datalen);
3059 #endif
3060 }
3061 
3062 static int
3063 dissect_krb5_decrypt_ticket_data (gboolean imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
3064 									proto_tree *tree, int hf_index _U_)
3065 {
3066 	guint8 *plaintext;
3067 	int length;
3068 	tvbuff_t *next_tvb;
3069 
3070 	next_tvb=tvb_new_subset_remaining(tvb, offset);
3071 	length=tvb_captured_length_remaining(tvb, offset);
3072 
3073 	/* draft-ietf-krb-wg-kerberos-clarifications-05.txt :
3074 	 * 7.5.1
3075 	 * All Ticket encrypted parts use usage == 2
3076 	 */
3077 	plaintext=decrypt_krb5_data_asn1(tree, actx, 2, next_tvb, &length);
3078 
3079 	if(plaintext){
3080 		kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
3081 		tvbuff_t *last_ticket_enc_part_tvb = private_data->last_ticket_enc_part_tvb;
3082 		tvbuff_t *child_tvb;
3083 		child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
3084 
3085 		/* Add the decrypted data to the data source list. */
3086 		add_new_data_source(actx->pinfo, child_tvb, "Krb5 Ticket");
3087 
3088 		private_data->last_ticket_enc_part_tvb = child_tvb;
3089 		offset=dissect_kerberos_Applications(FALSE, child_tvb, 0, actx , tree, /* hf_index*/ -1);
3090 		private_data->last_ticket_enc_part_tvb = last_ticket_enc_part_tvb;
3091 	}
3092 	return offset;
3093 }
3094 
3095 static int
3096 dissect_krb5_decrypt_authenticator_data (gboolean imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
3097 											proto_tree *tree, int hf_index _U_)
3098 {
3099 	kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
3100 	guint8 *plaintext;
3101 	int length;
3102 	tvbuff_t *next_tvb;
3103 
3104 	next_tvb=tvb_new_subset_remaining(tvb, offset);
3105 	length=tvb_captured_length_remaining(tvb, offset);
3106 
3107 	/* draft-ietf-krb-wg-kerberos-clarifications-05.txt :
3108 	 * 7.5.1
3109 	 * Authenticators are encrypted with usage
3110 	 * == 7 or
3111 	 * == 11
3112 	 *
3113 	 * 7.  TGS-REQ PA-TGS-REQ padata AP-REQ Authenticator
3114 	 *     (includes TGS authenticator subkey), encrypted with the
3115 	 *     TGS session key (section 5.5.1)
3116 	 * 11. AP-REQ Authenticator (includes application
3117 	 *     authenticator subkey), encrypted with the application
3118 	 *     session key (section 5.5.1)
3119 	 */
3120 	if (private_data->within_PA_TGS_REQ > 0) {
3121 		plaintext=decrypt_krb5_data_asn1(tree, actx, 7, next_tvb, &length);
3122 	} else {
3123 		plaintext=decrypt_krb5_data_asn1(tree, actx, 11, next_tvb, &length);
3124 	}
3125 
3126 	if(plaintext){
3127 		tvbuff_t *child_tvb;
3128 		child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
3129 
3130 		/* Add the decrypted data to the data source list. */
3131 		add_new_data_source(actx->pinfo, child_tvb, "Krb5 Authenticator");
3132 
3133 		offset=dissect_kerberos_Applications(FALSE, child_tvb, 0, actx , tree, /* hf_index*/ -1);
3134 	}
3135 	return offset;
3136 }
3137 
3138 static int
3139 dissect_krb5_decrypt_authorization_data(gboolean imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
3140 					proto_tree *tree, int hf_index _U_)
3141 {
3142 	kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
3143 	guint8 *plaintext;
3144 	int length;
3145 	tvbuff_t *next_tvb;
3146 
3147 	next_tvb=tvb_new_subset_remaining(tvb, offset);
3148 	length=tvb_captured_length_remaining(tvb, offset);
3149 
3150 	/* draft-ietf-krb-wg-kerberos-clarifications-05.txt :
3151 	 * 7.5.1
3152 	 * Authenticators are encrypted with usage
3153 	 * == 5 or
3154 	 * == 4
3155 	 *
3156 	 * 4. TGS-REQ KDC-REQ-BODY AuthorizationData, encrypted with
3157 	 *    the TGS session key (section 5.4.1)
3158 	 * 5. TGS-REQ KDC-REQ-BODY AuthorizationData, encrypted with
3159 	 *    the TGS authenticator subkey (section 5.4.1)
3160 	 */
3161 	if (private_data->PA_TGS_REQ_subkey != NULL) {
3162 		plaintext=decrypt_krb5_data_asn1(tree, actx, 5, next_tvb, &length);
3163 	} else {
3164 		plaintext=decrypt_krb5_data_asn1(tree, actx, 4, next_tvb, &length);
3165 	}
3166 
3167 	if(plaintext){
3168 		tvbuff_t *child_tvb;
3169 		child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
3170 
3171 		/* Add the decrypted data to the data source list. */
3172 		add_new_data_source(actx->pinfo, child_tvb, "Krb5 AuthorizationData");
3173 
3174 		offset=dissect_kerberos_AuthorizationData(FALSE, child_tvb, 0, actx , tree, /* hf_index*/ -1);
3175 	}
3176 	return offset;
3177 }
3178 
3179 static int
3180 dissect_krb5_decrypt_KDC_REP_data (gboolean imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
3181 									proto_tree *tree, int hf_index _U_)
3182 {
3183 	kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
3184 	guint8 *plaintext = NULL;
3185 	int length;
3186 	tvbuff_t *next_tvb;
3187 
3188 	next_tvb=tvb_new_subset_remaining(tvb, offset);
3189 	length=tvb_captured_length_remaining(tvb, offset);
3190 
3191 	/* draft-ietf-krb-wg-kerberos-clarifications-05.txt :
3192 	 * 7.5.1
3193 	 * ASREP/TGSREP encryptedparts are encrypted with usage
3194 	 * == 3 or
3195 	 * == 8 or
3196 	 * == 9
3197 	 *
3198 	 * 3. AS-REP encrypted part (includes TGS session key or
3199 	 *    application session key), encrypted with the client key
3200 	 *    (section 5.4.2)
3201 	 *
3202 	 * 8. TGS-REP encrypted part (includes application session
3203 	 *    key), encrypted with the TGS session key (section
3204 	 *    5.4.2)
3205 	 * 9. TGS-REP encrypted part (includes application session
3206 	 *    key), encrypted with the TGS authenticator subkey
3207 	 *    (section 5.4.2)
3208 	 *
3209 	 * We currently don't have a way to find the TGS-REQ state
3210 	 * in order to check if an authenticator subkey was used.
3211 	 *
3212 	 * But if we client used FAST and we got a strengthen_key,
3213 	 * we're sure an authenticator subkey was used.
3214 	 *
3215 	 * Windows don't use an authenticator subkey without FAST,
3216 	 * but heimdal does.
3217 	 *
3218 	 * For now try 8 before 9 in order to avoid overhead and false
3219 	 * positives for the 'kerberos.missing_keytype' filter in pure
3220 	 * windows captures.
3221 	 */
3222 	switch (private_data->msg_type) {
3223 	case KERBEROS_APPLICATIONS_AS_REP:
3224 		plaintext=decrypt_krb5_data_asn1(tree, actx, 3, next_tvb, &length);
3225 		break;
3226 	case KERBEROS_APPLICATIONS_TGS_REP:
3227 		if (private_data->fast_strengthen_key != NULL) {
3228 			plaintext=decrypt_krb5_data_asn1(tree, actx, 9, next_tvb, &length);
3229 		} else {
3230 			plaintext=decrypt_krb5_data_asn1(tree, actx, 8, next_tvb, &length);
3231 			if(!plaintext){
3232 				plaintext=decrypt_krb5_data_asn1(tree, actx, 9, next_tvb, &length);
3233 			}
3234 		}
3235 		break;
3236 	}
3237 
3238 	if(plaintext){
3239 		tvbuff_t *child_tvb;
3240 		child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
3241 
3242 		/* Add the decrypted data to the data source list. */
3243 		add_new_data_source(actx->pinfo, child_tvb, "Krb5 KDC-REP");
3244 
3245 		offset=dissect_kerberos_Applications(FALSE, child_tvb, 0, actx , tree, /* hf_index*/ -1);
3246 	}
3247 	return offset;
3248 }
3249 
3250 static int
3251 dissect_krb5_decrypt_PA_ENC_TIMESTAMP (gboolean imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
3252 										proto_tree *tree, int hf_index _U_)
3253 {
3254 	guint8 *plaintext;
3255 	int length;
3256 	tvbuff_t *next_tvb;
3257 
3258 	next_tvb=tvb_new_subset_remaining(tvb, offset);
3259 	length=tvb_captured_length_remaining(tvb, offset);
3260 
3261 	/* draft-ietf-krb-wg-kerberos-clarifications-05.txt :
3262 	 * 7.5.1
3263 	 * AS-REQ PA_ENC_TIMESTAMP are encrypted with usage
3264 	 * == 1
3265 	 */
3266 	plaintext=decrypt_krb5_data_asn1(tree, actx, 1, next_tvb, &length);
3267 
3268 	if(plaintext){
3269 		tvbuff_t *child_tvb;
3270 		child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
3271 
3272 		/* Add the decrypted data to the data source list. */
3273 		add_new_data_source(actx->pinfo, child_tvb, "Krb5 EncTimestamp");
3274 
3275 		offset=dissect_kerberos_PA_ENC_TS_ENC(FALSE, child_tvb, 0, actx , tree, /* hf_index*/ -1);
3276 	}
3277 	return offset;
3278 }
3279 
3280 static int
3281 dissect_krb5_decrypt_AP_REP_data (gboolean imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
3282 									proto_tree *tree, int hf_index _U_)
3283 {
3284 	guint8 *plaintext;
3285 	int length;
3286 	tvbuff_t *next_tvb;
3287 
3288 	next_tvb=tvb_new_subset_remaining(tvb, offset);
3289 	length=tvb_captured_length_remaining(tvb, offset);
3290 
3291 	/* draft-ietf-krb-wg-kerberos-clarifications-05.txt :
3292 	 * 7.5.1
3293 	 * AP-REP are encrypted with usage == 12
3294 	 */
3295 	plaintext=decrypt_krb5_data_asn1(tree, actx, 12, next_tvb, &length);
3296 
3297 	if(plaintext){
3298 		tvbuff_t *child_tvb;
3299 		child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
3300 
3301 		/* Add the decrypted data to the data source list. */
3302 		add_new_data_source(actx->pinfo, child_tvb, "Krb5 AP-REP");
3303 
3304 		offset=dissect_kerberos_Applications(FALSE, child_tvb, 0, actx , tree, /* hf_index*/ -1);
3305 	}
3306 	return offset;
3307 }
3308 
3309 static int
3310 dissect_krb5_decrypt_PRIV_data (gboolean imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
3311 									proto_tree *tree, int hf_index _U_)
3312 {
3313 	guint8 *plaintext;
3314 	int length;
3315 	tvbuff_t *next_tvb;
3316 
3317 	next_tvb=tvb_new_subset_remaining(tvb, offset);
3318 	length=tvb_captured_length_remaining(tvb, offset);
3319 
3320 	/* RFC4120 :
3321 	 * EncKrbPrivPart encrypted with usage
3322 	 * == 13
3323 	 */
3324 	plaintext=decrypt_krb5_data_asn1(tree, actx, 13, next_tvb, &length);
3325 
3326 	if(plaintext){
3327 		tvbuff_t *child_tvb;
3328 		child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
3329 
3330 		/* Add the decrypted data to the data source list. */
3331 		add_new_data_source(actx->pinfo, child_tvb, "Krb5 PRIV");
3332 
3333 		offset=dissect_kerberos_Applications(FALSE, child_tvb, 0, actx , tree, /* hf_index*/ -1);
3334 	}
3335 	return offset;
3336 }
3337 
3338 static int
3339 dissect_krb5_decrypt_CRED_data (gboolean imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
3340 									proto_tree *tree, int hf_index _U_)
3341 {
3342 	guint8 *plaintext;
3343 	int length;
3344 	tvbuff_t *next_tvb;
3345 
3346 	next_tvb=tvb_new_subset_remaining(tvb, offset);
3347 	length=tvb_captured_length_remaining(tvb, offset);
3348 
3349 	/* RFC4120 :
3350 	 * EncKrbCredPart encrypted with usage
3351 	 * == 14
3352 	 */
3353 	plaintext=decrypt_krb5_data_asn1(tree, actx, 14, next_tvb, &length);
3354 
3355 	if(plaintext){
3356 		tvbuff_t *child_tvb;
3357 		child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
3358 
3359 		/* Add the decrypted data to the data source list. */
3360 		add_new_data_source(actx->pinfo, child_tvb, "Krb5 CRED");
3361 
3362 		offset=dissect_kerberos_Applications(FALSE, child_tvb, 0, actx , tree, /* hf_index*/ -1);
3363 	}
3364 	return offset;
3365 }
3366 
3367 static int
3368 dissect_krb5_decrypt_KrbFastReq(gboolean imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
3369 				proto_tree *tree, int hf_index _U_)
3370 {
3371 	guint8 *plaintext;
3372 	int length;
3373 	kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
3374 	tvbuff_t *next_tvb;
3375 
3376 	next_tvb=tvb_new_subset_remaining(tvb, offset);
3377 	length=tvb_captured_length_remaining(tvb, offset);
3378 
3379 	private_data->fast_armor_key = NULL;
3380 	if (private_data->PA_FAST_ARMOR_AP_subkey != NULL) {
3381 		krb5_fast_key(actx, tree, tvb,
3382 			      private_data->PA_FAST_ARMOR_AP_subkey,
3383 			      "subkeyarmor",
3384 			      private_data->PA_FAST_ARMOR_AP_key,
3385 			      "ticketarmor",
3386 			      "KrbFastReq_FAST_armorKey");
3387 		if (private_data->PA_TGS_REQ_subkey != NULL) {
3388 			enc_key_t *explicit_armor_key = private_data->last_added_key;
3389 
3390 			/*
3391 			 * See [MS-KILE] 3.3.5.7.4 Compound Identity
3392 			 */
3393 			krb5_fast_key(actx, tree, tvb,
3394 				      explicit_armor_key,
3395 				      "explicitarmor",
3396 				      private_data->PA_TGS_REQ_subkey,
3397 				      "tgsarmor",
3398 				      "KrbFastReq_explicitArmorKey");
3399 		}
3400 		private_data->fast_armor_key = private_data->last_added_key;
3401 	} else if (private_data->PA_TGS_REQ_subkey != NULL) {
3402 		krb5_fast_key(actx, tree, tvb,
3403 			      private_data->PA_TGS_REQ_subkey,
3404 			      "subkeyarmor",
3405 			      private_data->PA_TGS_REQ_key,
3406 			      "ticketarmor",
3407 			      "KrbFastReq_TGS_armorKey");
3408 		private_data->fast_armor_key = private_data->last_added_key;
3409 	}
3410 
3411 	/* RFC6113 :
3412 	 * KrbFastResponse encrypted with usage
3413 	 * KEY_USAGE_FAST_ENC 51
3414 	 */
3415 	plaintext=decrypt_krb5_data_asn1(tree, actx, KEY_USAGE_FAST_ENC,
3416 					 next_tvb, &length);
3417 
3418 	if(plaintext){
3419 		tvbuff_t *child_tvb;
3420 		child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
3421 
3422 		/* Add the decrypted data to the data source list. */
3423 		add_new_data_source(actx->pinfo, child_tvb, "Krb5 FastReq");
3424 
3425 		offset=dissect_kerberos_KrbFastReq(FALSE, child_tvb, 0, actx , tree, /* hf_index*/ -1);
3426 	}
3427 	return offset;
3428 }
3429 
3430 static int
3431 dissect_krb5_decrypt_KrbFastResponse(gboolean imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
3432 				     proto_tree *tree, int hf_index _U_)
3433 {
3434 	guint8 *plaintext;
3435 	int length;
3436 	kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
3437 	tvbuff_t *next_tvb;
3438 
3439 	next_tvb=tvb_new_subset_remaining(tvb, offset);
3440 	length=tvb_captured_length_remaining(tvb, offset);
3441 
3442 	/*
3443 	 * RFC6113 :
3444 	 * KrbFastResponse encrypted with usage
3445 	 * KEY_USAGE_FAST_REP 52
3446 	 */
3447 	plaintext=decrypt_krb5_data_asn1(tree, actx, KEY_USAGE_FAST_REP,
3448 					 next_tvb, &length);
3449 
3450 	if(plaintext){
3451 		tvbuff_t *child_tvb;
3452 		child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
3453 
3454 		/* Add the decrypted data to the data source list. */
3455 		add_new_data_source(actx->pinfo, child_tvb, "Krb5 FastRep");
3456 
3457 		private_data->fast_armor_key = private_data->last_decryption_key;
3458 		offset=dissect_kerberos_KrbFastResponse(FALSE, child_tvb, 0, actx , tree, /* hf_index*/ -1);
3459 	}
3460 	return offset;
3461 }
3462 
3463 static int
3464 dissect_krb5_decrypt_EncryptedChallenge(gboolean imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
3465 					proto_tree *tree, int hf_index _U_)
3466 {
3467 	guint8 *plaintext;
3468 	int length;
3469 	kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
3470 	tvbuff_t *next_tvb;
3471 	int usage = 0;
3472 	const char *name = NULL;
3473 
3474 	next_tvb=tvb_new_subset_remaining(tvb, offset);
3475 	length=tvb_captured_length_remaining(tvb, offset);
3476 
3477 	/* RFC6113 :
3478 	 * KEY_USAGE_ENC_CHALLENGE_CLIENT  54
3479 	 * KEY_USAGE_ENC_CHALLENGE_KDC     55
3480 	 */
3481 	if (kerberos_private_is_kdc_req(private_data)) {
3482 		usage = KEY_USAGE_ENC_CHALLENGE_CLIENT;
3483 		name = "Krb5 CHALLENGE_CLIENT";
3484 	} else {
3485 		usage = KEY_USAGE_ENC_CHALLENGE_KDC;
3486 		name = "Krb5 CHALLENGE_KDC";
3487 	}
3488 	plaintext=decrypt_krb5_data_asn1(tree, actx, usage, next_tvb, &length);
3489 
3490 	if(plaintext){
3491 		tvbuff_t *child_tvb;
3492 		child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
3493 
3494 		/* Add the decrypted data to the data source list. */
3495 		add_new_data_source(actx->pinfo, child_tvb, name);
3496 
3497 		offset=dissect_kerberos_PA_ENC_TS_ENC(FALSE, child_tvb, 0, actx , tree, /* hf_index*/ -1);
3498 	}
3499 	return offset;
3500 }
3501 #endif /* HAVE_KERBEROS */
3502 
3503 static int * const hf_krb_pa_supported_enctypes_fields[] = {
3504 	&hf_krb_pa_supported_enctypes_des_cbc_crc,
3505 	&hf_krb_pa_supported_enctypes_des_cbc_md5,
3506 	&hf_krb_pa_supported_enctypes_rc4_hmac,
3507 	&hf_krb_pa_supported_enctypes_aes128_cts_hmac_sha1_96,
3508 	&hf_krb_pa_supported_enctypes_aes256_cts_hmac_sha1_96,
3509 	&hf_krb_pa_supported_enctypes_fast_supported,
3510 	&hf_krb_pa_supported_enctypes_compound_identity_supported,
3511 	&hf_krb_pa_supported_enctypes_claims_supported,
3512 	&hf_krb_pa_supported_enctypes_resource_sid_compression_disabled,
3513 	NULL,
3514 };
3515 
3516 static int
3517 dissect_kerberos_PA_SUPPORTED_ENCTYPES(gboolean implicit_tag _U_, tvbuff_t *tvb _U_,
3518 				       int offset _U_, asn1_ctx_t *actx _U_,
3519 				       proto_tree *tree _U_, int hf_index _U_)
3520 {
3521 	actx->created_item = proto_tree_add_bitmask(tree, tvb, offset,
3522 						    hf_krb_pa_supported_enctypes,
3523 						    ett_krb_pa_supported_enctypes,
3524 						    hf_krb_pa_supported_enctypes_fields,
3525 						    ENC_LITTLE_ENDIAN);
3526 	offset += 4;
3527 
3528 	return offset;
3529 }
3530 
3531 static int * const hf_krb_ad_ap_options_fields[] = {
3532 	&hf_krb_ad_ap_options_cbt,
3533 	NULL,
3534 };
3535 
3536 
3537 static int
3538 dissect_kerberos_AD_AP_OPTIONS(gboolean implicit_tag _U_, tvbuff_t *tvb _U_,
3539 			       int offset _U_, asn1_ctx_t *actx _U_,
3540 			       proto_tree *tree _U_, int hf_index _U_)
3541 {
3542 	actx->created_item = proto_tree_add_bitmask(tree, tvb, offset,
3543 						    hf_krb_ad_ap_options,
3544 						    ett_krb_ad_ap_options,
3545 						    hf_krb_ad_ap_options_fields,
3546 						    ENC_LITTLE_ENDIAN);
3547 	offset += 4;
3548 
3549 	return offset;
3550 }
3551 
3552 static int
3553 dissect_kerberos_AD_TARGET_PRINCIPAL(gboolean implicit_tag _U_, tvbuff_t *tvb _U_,
3554 				     int offset _U_, asn1_ctx_t *actx _U_,
3555 				     proto_tree *tree _U_, int hf_index _U_)
3556 {
3557 	int tp_offset, tp_len;
3558 	guint16 bc;
3559 
3560 	bc = tvb_reported_length_remaining(tvb, offset);
3561 	tp_offset = offset;
3562 	tp_len = bc;
3563 	proto_tree_add_item(tree, hf_krb_ad_target_principal, tvb,
3564 			    tp_offset, tp_len,
3565 			    ENC_UTF_16 | ENC_LITTLE_ENDIAN);
3566 
3567 	return offset;
3568 }
3569 
3570 /* Dissect a GSSAPI checksum as per RFC1964. This is NOT ASN.1 encoded.
3571  */
3572 static int
3573 dissect_krb5_rfc1964_checksum(asn1_ctx_t *actx _U_, proto_tree *tree, tvbuff_t *tvb)
3574 {
3575 	int offset=0;
3576 	guint32 len;
3577 	guint16 dlglen;
3578 
3579 	/* Length of Bnd field */
3580 	len=tvb_get_letohl(tvb, offset);
3581 	proto_tree_add_item(tree, hf_krb_gssapi_len, tvb, offset, 4, ENC_LITTLE_ENDIAN);
3582 	offset += 4;
3583 
3584 	/* Bnd field */
3585 	proto_tree_add_item(tree, hf_krb_gssapi_bnd, tvb, offset, len, ENC_NA);
3586 	offset += len;
3587 
3588 
3589 	/* flags */
3590 	proto_tree_add_item(tree, hf_krb_gssapi_c_flag_dce_style, tvb, offset, 4, ENC_LITTLE_ENDIAN);
3591 	proto_tree_add_item(tree, hf_krb_gssapi_c_flag_integ, tvb, offset, 4, ENC_LITTLE_ENDIAN);
3592 	proto_tree_add_item(tree, hf_krb_gssapi_c_flag_conf, tvb, offset, 4, ENC_LITTLE_ENDIAN);
3593 	proto_tree_add_item(tree, hf_krb_gssapi_c_flag_sequence, tvb, offset, 4, ENC_LITTLE_ENDIAN);
3594 	proto_tree_add_item(tree, hf_krb_gssapi_c_flag_replay, tvb, offset, 4, ENC_LITTLE_ENDIAN);
3595 	proto_tree_add_item(tree, hf_krb_gssapi_c_flag_mutual, tvb, offset, 4, ENC_LITTLE_ENDIAN);
3596 	proto_tree_add_item(tree, hf_krb_gssapi_c_flag_deleg, tvb, offset, 4, ENC_LITTLE_ENDIAN);
3597 	offset += 4;
3598 
3599 	/* the next fields are optional so we have to check that we have
3600 	 * more data in our buffers */
3601 	if(tvb_reported_length_remaining(tvb, offset)<2){
3602 		return offset;
3603 	}
3604 	/* dlgopt identifier */
3605 	proto_tree_add_item(tree, hf_krb_gssapi_dlgopt, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3606 	offset += 2;
3607 
3608 	if(tvb_reported_length_remaining(tvb, offset)<2){
3609 		return offset;
3610 	}
3611 	/* dlglen identifier */
3612 	dlglen=tvb_get_letohs(tvb, offset);
3613 	proto_tree_add_item(tree, hf_krb_gssapi_dlglen, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3614 	offset += 2;
3615 
3616 	if(dlglen!=tvb_reported_length_remaining(tvb, offset)){
3617 		proto_tree_add_expert_format(tree, actx->pinfo, &ei_krb_gssapi_dlglen, tvb, 0, 0,
3618 				"Error: DlgLen:%d is not the same as number of bytes remaining:%d", dlglen, tvb_captured_length_remaining(tvb, offset));
3619 		return offset;
3620 	}
3621 
3622 	/* this should now be a KRB_CRED message */
3623 	offset=dissect_kerberos_Applications(FALSE, tvb, offset, actx, tree, /* hf_index */ -1);
3624 
3625 	return offset;
3626 }
3627 
3628 static int
3629 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_)
3630 {
3631 	offset=dissect_ber_GeneralString(actx, tree, tvb, offset, hf_krb_provsrv_location, NULL, 0);
3632 
3633 	return offset;
3634 }
3635 
3636 static int
3637 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_)
3638 {
3639 	kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
3640 	gint length;
3641 	guint32 nt_status = 0;
3642 	guint32 reserved = 0;
3643 	guint32 flags = 0;
3644 
3645 	/*
3646 	 * Microsoft stores a special 12 byte blob here
3647 	 * [MS-KILE] 2.2.1 KERB-EXT-ERROR
3648 	 * guint32 NT_status
3649 	 * guint32 reserved (== 0)
3650 	 * guint32 flags (at least 0x00000001 is set)
3651 	 */
3652 	length = tvb_reported_length_remaining(tvb, offset);
3653 	if (length <= 0) {
3654 		return offset;
3655 	}
3656 	if (length != 12) {
3657 		goto no_error;
3658 	}
3659 
3660 	if (private_data->errorcode == 0) {
3661 		goto no_error;
3662 	}
3663 
3664 	if (!private_data->try_nt_status) {
3665 		goto no_error;
3666 	}
3667 
3668 	nt_status = tvb_get_letohl(tvb, offset);
3669 	reserved = tvb_get_letohl(tvb, offset + 4);
3670 	flags = tvb_get_letohl(tvb, offset + 8);
3671 
3672 	if (nt_status == 0 || reserved != 0 || flags == 0) {
3673 		goto no_error;
3674 	}
3675 
3676 	proto_tree_add_item(tree, hf_krb_ext_error_nt_status, tvb, offset, 4,
3677 			ENC_LITTLE_ENDIAN);
3678 	col_append_fstr(actx->pinfo->cinfo, COL_INFO,
3679 			" NT Status: %s",
3680 			val_to_str(nt_status, NT_errors,
3681 			"Unknown error code %#x"));
3682 	offset += 4;
3683 
3684 	proto_tree_add_item(tree, hf_krb_ext_error_reserved, tvb, offset, 4,
3685 			ENC_LITTLE_ENDIAN);
3686 	offset += 4;
3687 
3688 	proto_tree_add_item(tree, hf_krb_ext_error_flags, tvb, offset, 4,
3689 			ENC_LITTLE_ENDIAN);
3690 	offset += 4;
3691 
3692 	return offset;
3693 
3694  no_error:
3695 	proto_tree_add_item(tree, hf_krb_pw_salt, tvb, offset, length, ENC_NA);
3696 	offset += length;
3697 
3698 	return offset;
3699 }
3700 
3701 static int
3702 dissect_krb5_PAC_DREP(proto_tree *parent_tree, tvbuff_t *tvb, int offset, guint8 *drep)
3703 {
3704 	proto_tree *tree;
3705 	guint8 val;
3706 
3707 	tree = proto_tree_add_subtree(parent_tree, tvb, offset, 16, ett_krb_pac_drep, NULL, "DREP");
3708 
3709 	val = tvb_get_guint8(tvb, offset);
3710 	proto_tree_add_uint(tree, hf_dcerpc_drep_byteorder, tvb, offset, 1, val>>4);
3711 
3712 	offset++;
3713 
3714 	if (drep) {
3715 		*drep = val;
3716 	}
3717 
3718 	return offset;
3719 }
3720 
3721 /* This might be some sort of header that MIDL generates when creating
3722  * marshalling/unmarshalling code for blobs that are not to be transported
3723  * ontop of DCERPC and where the DREP fields specifying things such as
3724  * endianess and similar are not available.
3725  */
3726 static int
3727 dissect_krb5_PAC_NDRHEADERBLOB(proto_tree *parent_tree, tvbuff_t *tvb, int offset, guint8 *drep, asn1_ctx_t *actx _U_)
3728 {
3729 	proto_tree *tree;
3730 
3731 	tree = proto_tree_add_subtree(parent_tree, tvb, offset, 16, ett_krb_pac_midl_blob, NULL, "MES header");
3732 
3733 	/* modified DREP field that is used for stuff that is transporetd ontop
3734 	   of non dcerpc
3735 	*/
3736 	proto_tree_add_item(tree, hf_krb_midl_version, tvb, offset, 1, ENC_LITTLE_ENDIAN);
3737 	offset++;
3738 
3739 	offset = dissect_krb5_PAC_DREP(tree, tvb, offset, drep);
3740 
3741 
3742 	proto_tree_add_item(tree, hf_krb_midl_hdr_len, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3743 	offset+=2;
3744 
3745 	proto_tree_add_item(tree, hf_krb_midl_fill_bytes, tvb, offset, 4, ENC_LITTLE_ENDIAN);
3746 	offset += 4;
3747 
3748 	/* length of blob that follows */
3749 	proto_tree_add_item(tree, hf_krb_midl_blob_len, tvb, offset, 8, ENC_LITTLE_ENDIAN);
3750 	offset += 8;
3751 
3752 	return offset;
3753 }
3754 
3755 static int
3756 dissect_krb5_PAC_LOGON_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
3757 {
3758 	proto_item *item;
3759 	proto_tree *tree;
3760 	guint8 drep[4] = { 0x10, 0x00, 0x00, 0x00}; /* fake DREP struct */
3761 	static dcerpc_info di;      /* fake dcerpc_info struct */
3762 	static dcerpc_call_value call_data;
3763 
3764 	item = proto_tree_add_item(parent_tree, hf_krb_pac_logon_info, tvb, offset, -1, ENC_NA);
3765 	tree = proto_item_add_subtree(item, ett_krb_pac_logon_info);
3766 
3767 	/* skip the first 16 bytes, they are some magic created by the idl
3768 	 * compiler   the first 4 bytes might be flags?
3769 	 */
3770 	offset = dissect_krb5_PAC_NDRHEADERBLOB(tree, tvb, offset, &drep[0], actx);
3771 
3772 	/* the PAC_LOGON_INFO blob */
3773 	/* fake whatever state the dcerpc runtime support needs */
3774 	di.conformant_run=0;
3775 	/* we need di->call_data->flags.NDR64 == 0 */
3776 	di.call_data=&call_data;
3777 	init_ndr_pointer_list(&di);
3778 	offset = dissect_ndr_pointer(tvb, offset, actx->pinfo, tree, &di, drep,
3779 									netlogon_dissect_PAC_LOGON_INFO, NDR_POINTER_UNIQUE,
3780 									"PAC_LOGON_INFO:", -1);
3781 
3782 	return offset;
3783 }
3784 
3785 
3786 static int
3787 dissect_krb5_PAC_CREDENTIAL_DATA(proto_tree *parent_tree, tvbuff_t *tvb, int offset, packet_info *pinfo _U_)
3788 {
3789 	proto_tree_add_item(parent_tree, hf_krb_pac_credential_data, tvb, offset, -1, ENC_NA);
3790 
3791 	return offset;
3792 }
3793 
3794 static int
3795 dissect_krb5_PAC_CREDENTIAL_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx)
3796 {
3797 	proto_item *item;
3798 	proto_tree *tree;
3799 	guint8 *plaintext = NULL;
3800 	int plainlen = 0;
3801 	int length = 0;
3802 #define KRB5_KU_OTHER_ENCRYPTED 16
3803 #ifdef  HAVE_KERBEROS
3804 	guint32 etype;
3805 	tvbuff_t *next_tvb;
3806 	int usage = KRB5_KU_OTHER_ENCRYPTED;
3807 #endif
3808 
3809 	item = proto_tree_add_item(parent_tree, hf_krb_pac_credential_info, tvb, offset, -1, ENC_NA);
3810 	tree = proto_item_add_subtree(item, ett_krb_pac_credential_info);
3811 
3812 	/* version */
3813 	proto_tree_add_item(tree, hf_krb_pac_credential_info_version, tvb,
3814 			    offset, 4, ENC_LITTLE_ENDIAN);
3815 	offset+=4;
3816 
3817 #ifdef HAVE_KERBEROS
3818 	/* etype */
3819 	etype = tvb_get_letohl(tvb, offset);
3820 #endif
3821 	proto_tree_add_item(tree, hf_krb_pac_credential_info_etype, tvb,
3822 			    offset, 4, ENC_LITTLE_ENDIAN);
3823 	offset+=4;
3824 
3825 #ifdef HAVE_KERBEROS
3826 	/* data */
3827 	next_tvb=tvb_new_subset_remaining(tvb, offset);
3828 	length=tvb_captured_length_remaining(tvb, offset);
3829 
3830 	plaintext=decrypt_krb5_data(tree, actx->pinfo, usage, next_tvb, (int)etype, &plainlen);
3831 #endif
3832 
3833 	if (plaintext != NULL) {
3834 		tvbuff_t *child_tvb;
3835 		child_tvb = tvb_new_child_real_data(tvb, plaintext, plainlen, plainlen);
3836 
3837 		/* Add the decrypted data to the data source list. */
3838 		add_new_data_source(actx->pinfo, child_tvb, "Krb5 PAC_CREDENTIAL");
3839 
3840 		dissect_krb5_PAC_CREDENTIAL_DATA(tree, child_tvb, 0, actx->pinfo);
3841 	}
3842 
3843 	return offset + length;
3844 }
3845 
3846 static int
3847 dissect_krb5_PAC_S4U_DELEGATION_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx)
3848 {
3849 	proto_item *item;
3850 	proto_tree *tree;
3851 	guint8 drep[4] = { 0x10, 0x00, 0x00, 0x00}; /* fake DREP struct */
3852 	static dcerpc_info di;      /* fake dcerpc_info struct */
3853 	static dcerpc_call_value call_data;
3854 
3855 	item = proto_tree_add_item(parent_tree, hf_krb_pac_s4u_delegation_info, tvb, offset, -1, ENC_NA);
3856 	tree = proto_item_add_subtree(item, ett_krb_pac_s4u_delegation_info);
3857 
3858 	/* skip the first 16 bytes, they are some magic created by the idl
3859 	 * compiler   the first 4 bytes might be flags?
3860 	 */
3861 	offset = dissect_krb5_PAC_NDRHEADERBLOB(tree, tvb, offset, &drep[0], actx);
3862 
3863 
3864 	/* the S4U_DELEGATION_INFO blob. See [MS-PAC] */
3865 	/* fake whatever state the dcerpc runtime support needs */
3866 	di.conformant_run=0;
3867 	/* we need di->call_data->flags.NDR64 == 0 */
3868 	di.call_data=&call_data;
3869 	init_ndr_pointer_list(&di);
3870 	offset = dissect_ndr_pointer(tvb, offset, actx->pinfo, tree, &di, drep,
3871 									netlogon_dissect_PAC_S4U_DELEGATION_INFO, NDR_POINTER_UNIQUE,
3872 									"PAC_S4U_DELEGATION_INFO:", -1);
3873 
3874 	return offset;
3875 }
3876 
3877 static int
3878 dissect_krb5_PAC_UPN_DNS_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
3879 {
3880 	proto_item *item;
3881 	proto_tree *tree;
3882 	guint16 dns_offset, dns_len;
3883 	guint16 upn_offset, upn_len;
3884 
3885 	item = proto_tree_add_item(parent_tree, hf_krb_pac_upn_dns_info, tvb, offset, -1, ENC_NA);
3886 	tree = proto_item_add_subtree(item, ett_krb_pac_upn_dns_info);
3887 
3888 	/* upn */
3889 	upn_len = tvb_get_letohs(tvb, offset);
3890 	proto_tree_add_item(tree, hf_krb_pac_upn_upn_len, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3891 	offset+=2;
3892 	upn_offset = tvb_get_letohs(tvb, offset);
3893 	proto_tree_add_item(tree, hf_krb_pac_upn_upn_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3894 	offset+=2;
3895 
3896 	/* dns */
3897 	dns_len = tvb_get_letohs(tvb, offset);
3898 	proto_tree_add_item(tree, hf_krb_pac_upn_dns_len, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3899 	offset+=2;
3900 	dns_offset = tvb_get_letohs(tvb, offset);
3901 	proto_tree_add_item(tree, hf_krb_pac_upn_dns_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3902 	offset+=2;
3903 
3904 	/* flags */
3905 	proto_tree_add_item(tree, hf_krb_pac_upn_flags, tvb, offset, 4, ENC_LITTLE_ENDIAN);
3906 
3907 	/* upn */
3908 	proto_tree_add_item(tree, hf_krb_pac_upn_upn_name, tvb, upn_offset, upn_len, ENC_UTF_16|ENC_LITTLE_ENDIAN);
3909 
3910 	/* dns */
3911 	proto_tree_add_item(tree, hf_krb_pac_upn_dns_name, tvb, dns_offset, dns_len, ENC_UTF_16|ENC_LITTLE_ENDIAN);
3912 
3913 	return dns_offset;
3914 }
3915 
3916 static int
3917 dissect_krb5_PAC_CLIENT_CLAIMS_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
3918 {
3919 	int length = tvb_captured_length_remaining(tvb, offset);
3920 
3921 	if (length == 0) {
3922 		return offset;
3923 	}
3924 
3925 	proto_tree_add_item(parent_tree, hf_krb_pac_client_claims_info, tvb, offset, -1, ENC_NA);
3926 
3927 	return offset;
3928 }
3929 
3930 static int
3931 dissect_krb5_PAC_DEVICE_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
3932 {
3933 	proto_item *item;
3934 	proto_tree *tree;
3935 	guint8 drep[4] = { 0x10, 0x00, 0x00, 0x00}; /* fake DREP struct */
3936 	static dcerpc_info di;      /* fake dcerpc_info struct */
3937 	static dcerpc_call_value call_data;
3938 
3939 	item = proto_tree_add_item(parent_tree, hf_krb_pac_device_info, tvb, offset, -1, ENC_NA);
3940 	tree = proto_item_add_subtree(item, ett_krb_pac_device_info);
3941 
3942 	/* skip the first 16 bytes, they are some magic created by the idl
3943 	 * compiler   the first 4 bytes might be flags?
3944 	 */
3945 	offset = dissect_krb5_PAC_NDRHEADERBLOB(tree, tvb, offset, &drep[0], actx);
3946 
3947 	/* the PAC_DEVICE_INFO blob */
3948 	/* fake whatever state the dcerpc runtime support needs */
3949 	di.conformant_run=0;
3950 	/* we need di->call_data->flags.NDR64 == 0 */
3951 	di.call_data=&call_data;
3952 	init_ndr_pointer_list(&di);
3953 	offset = dissect_ndr_pointer(tvb, offset, actx->pinfo, tree, &di, drep,
3954 				     netlogon_dissect_PAC_DEVICE_INFO, NDR_POINTER_UNIQUE,
3955 				     "PAC_DEVICE_INFO:", -1);
3956 
3957 	return offset;
3958 }
3959 
3960 static int
3961 dissect_krb5_PAC_DEVICE_CLAIMS_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
3962 {
3963 	int length = tvb_captured_length_remaining(tvb, offset);
3964 
3965 	if (length == 0) {
3966 		return offset;
3967 	}
3968 
3969 	proto_tree_add_item(parent_tree, hf_krb_pac_device_claims_info, tvb, offset, -1, ENC_NA);
3970 
3971 	return offset;
3972 }
3973 
3974 static int
3975 dissect_krb5_PAC_SERVER_CHECKSUM(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
3976 {
3977 	proto_item *item;
3978 	proto_tree *tree;
3979 
3980 	item = proto_tree_add_item(parent_tree, hf_krb_pac_server_checksum, tvb, offset, -1, ENC_NA);
3981 	tree = proto_item_add_subtree(item, ett_krb_pac_server_checksum);
3982 
3983 	/* signature type */
3984 	proto_tree_add_item(tree, hf_krb_pac_signature_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
3985 	offset+=4;
3986 
3987 	/* signature data */
3988 	proto_tree_add_item(tree, hf_krb_pac_signature_signature, tvb, offset, -1, ENC_NA);
3989 
3990 	return offset;
3991 }
3992 
3993 static int
3994 dissect_krb5_PAC_PRIVSVR_CHECKSUM(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
3995 {
3996 	proto_item *item;
3997 	proto_tree *tree;
3998 
3999 	item = proto_tree_add_item(parent_tree, hf_krb_pac_privsvr_checksum, tvb, offset, -1, ENC_NA);
4000 	tree = proto_item_add_subtree(item, ett_krb_pac_privsvr_checksum);
4001 
4002 	/* signature type */
4003 	proto_tree_add_item(tree, hf_krb_pac_signature_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
4004 	offset+=4;
4005 
4006 	/* signature data */
4007 	proto_tree_add_item(tree, hf_krb_pac_signature_signature, tvb, offset, -1, ENC_NA);
4008 
4009 	return offset;
4010 }
4011 
4012 static int
4013 dissect_krb5_PAC_CLIENT_INFO_TYPE(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
4014 {
4015 	proto_item *item;
4016 	proto_tree *tree;
4017 	guint16 namelen;
4018 
4019 	item = proto_tree_add_item(parent_tree, hf_krb_pac_client_info_type, tvb, offset, -1, ENC_NA);
4020 	tree = proto_item_add_subtree(item, ett_krb_pac_client_info_type);
4021 
4022 	/* clientid */
4023 	offset = dissect_nt_64bit_time(tvb, tree, offset, hf_krb_pac_clientid);
4024 
4025 	/* name length */
4026 	namelen=tvb_get_letohs(tvb, offset);
4027 	proto_tree_add_uint(tree, hf_krb_pac_namelen, tvb, offset, 2, namelen);
4028 	offset+=2;
4029 
4030 	/* client name */
4031 	proto_tree_add_item(tree, hf_krb_pac_clientname, tvb, offset, namelen, ENC_UTF_16|ENC_LITTLE_ENDIAN);
4032 	offset+=namelen;
4033 
4034 	return offset;
4035 }
4036 
4037 static int
4038 dissect_krb5_PAC_TICKET_CHECKSUM(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
4039 {
4040 	proto_item *item;
4041 	proto_tree *tree;
4042 
4043 	item = proto_tree_add_item(parent_tree, hf_krb_pac_ticket_checksum, tvb, offset, -1, ENC_NA);
4044 	tree = proto_item_add_subtree(item, ett_krb_pac_ticket_checksum);
4045 
4046 	/* signature type */
4047 	proto_tree_add_item(tree, hf_krb_pac_signature_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
4048 	offset+=4;
4049 
4050 	/* signature data */
4051 	proto_tree_add_item(tree, hf_krb_pac_signature_signature, tvb, offset, -1, ENC_NA);
4052 
4053 	return offset;
4054 }
4055 
4056 static int
4057 dissect_krb5_AD_WIN2K_PAC_struct(proto_tree *tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx)
4058 {
4059 	guint32 pac_type;
4060 	guint32 pac_size;
4061 	guint32 pac_offset;
4062 	proto_item *it=NULL;
4063 	proto_tree *tr=NULL;
4064 	tvbuff_t *next_tvb;
4065 
4066 	/* type of pac data */
4067 	pac_type=tvb_get_letohl(tvb, offset);
4068 	it=proto_tree_add_uint(tree, hf_krb_w2k_pac_type, tvb, offset, 4, pac_type);
4069 	tr=proto_item_add_subtree(it, ett_krb_pac);
4070 
4071 	offset += 4;
4072 
4073 	/* size of pac data */
4074 	pac_size=tvb_get_letohl(tvb, offset);
4075 	proto_tree_add_uint(tr, hf_krb_w2k_pac_size, tvb, offset, 4, pac_size);
4076 	offset += 4;
4077 
4078 	/* offset to pac data */
4079 	pac_offset=tvb_get_letohl(tvb, offset);
4080 	proto_tree_add_uint(tr, hf_krb_w2k_pac_offset, tvb, offset, 4, pac_offset);
4081 	offset += 8;
4082 
4083 	next_tvb=tvb_new_subset_length_caplen(tvb, pac_offset, pac_size, pac_size);
4084 	switch(pac_type){
4085 	case PAC_LOGON_INFO:
4086 		dissect_krb5_PAC_LOGON_INFO(tr, next_tvb, 0, actx);
4087 		break;
4088 	case PAC_CREDENTIAL_TYPE:
4089 		dissect_krb5_PAC_CREDENTIAL_INFO(tr, next_tvb, 0, actx);
4090 		break;
4091 	case PAC_SERVER_CHECKSUM:
4092 		dissect_krb5_PAC_SERVER_CHECKSUM(tr, next_tvb, 0, actx);
4093 		break;
4094 	case PAC_PRIVSVR_CHECKSUM:
4095 		dissect_krb5_PAC_PRIVSVR_CHECKSUM(tr, next_tvb, 0, actx);
4096 		break;
4097 	case PAC_CLIENT_INFO_TYPE:
4098 		dissect_krb5_PAC_CLIENT_INFO_TYPE(tr, next_tvb, 0, actx);
4099 		break;
4100 	case PAC_S4U_DELEGATION_INFO:
4101 		dissect_krb5_PAC_S4U_DELEGATION_INFO(tr, next_tvb, 0, actx);
4102 		break;
4103 	case PAC_UPN_DNS_INFO:
4104 		dissect_krb5_PAC_UPN_DNS_INFO(tr, next_tvb, 0, actx);
4105 		break;
4106 	case PAC_CLIENT_CLAIMS_INFO:
4107 		dissect_krb5_PAC_CLIENT_CLAIMS_INFO(tr, next_tvb, 0, actx);
4108 		break;
4109 	case PAC_DEVICE_INFO:
4110 		dissect_krb5_PAC_DEVICE_INFO(tr, next_tvb, 0, actx);
4111 		break;
4112 	case PAC_DEVICE_CLAIMS_INFO:
4113 		dissect_krb5_PAC_DEVICE_CLAIMS_INFO(tr, next_tvb, 0, actx);
4114 		break;
4115 	case PAC_TICKET_CHECKSUM:
4116 		dissect_krb5_PAC_TICKET_CHECKSUM(tr, next_tvb, 0, actx);
4117 		break;
4118 
4119 	default:
4120 		break;
4121 	}
4122 	return offset;
4123 }
4124 
4125 static int
4126 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_)
4127 {
4128 	guint32 entries;
4129 	guint32 version;
4130 	guint32 i;
4131 
4132 #if defined(HAVE_MIT_KERBEROS) && defined(HAVE_KRB5_PAC_VERIFY)
4133 	verify_krb5_pac(tree, actx, tvb);
4134 #endif
4135 
4136 	/* first in the PAC structure comes the number of entries */
4137 	entries=tvb_get_letohl(tvb, offset);
4138 	proto_tree_add_uint(tree, hf_krb_w2k_pac_entries, tvb, offset, 4, entries);
4139 	offset += 4;
4140 
4141 	/* second comes the version */
4142 	version=tvb_get_letohl(tvb, offset);
4143 	proto_tree_add_uint(tree, hf_krb_w2k_pac_version, tvb, offset, 4, version);
4144 	offset += 4;
4145 
4146 	for(i=0;i<entries;i++){
4147 		offset=dissect_krb5_AD_WIN2K_PAC_struct(tree, tvb, offset, actx);
4148 	}
4149 
4150 	return offset;
4151 }
4152 
4153 #include "packet-kerberos-fn.c"
4154 
4155 #ifdef HAVE_KERBEROS
4156 static const ber_sequence_t PA_ENC_TS_ENC_sequence[] = {
4157 	{ &hf_krb_patimestamp, BER_CLASS_CON, 0, 0, dissect_kerberos_KerberosTime },
4158 	{ &hf_krb_pausec     , BER_CLASS_CON, 1, BER_FLAGS_OPTIONAL, dissect_kerberos_Microseconds },
4159 	{ NULL, 0, 0, 0, NULL }
4160 };
4161 
4162 static int
4163 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_) {
4164 	offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
4165 									PA_ENC_TS_ENC_sequence, hf_index, ett_krb_pa_enc_ts_enc);
4166 	return offset;
4167 }
4168 
4169 static int
4170 dissect_kerberos_T_strengthen_key(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
4171 #line 491 "./asn1/kerberos/kerberos.cnf"
4172   kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
4173   gint save_encryption_key_parent_hf_index = private_data->save_encryption_key_parent_hf_index;
4174   kerberos_key_save_fn saved_encryption_key_fn = private_data->save_encryption_key_fn;
4175   private_data->save_encryption_key_parent_hf_index = hf_kerberos_KrbFastResponse;
4176 #ifdef HAVE_KERBEROS
4177   private_data->save_encryption_key_fn = save_KrbFastResponse_strengthen_key;
4178 #endif
4179   offset = dissect_kerberos_EncryptionKey(implicit_tag, tvb, offset, actx, tree, hf_index);
4180 
4181   private_data->save_encryption_key_parent_hf_index = save_encryption_key_parent_hf_index;
4182   private_data->save_encryption_key_fn = saved_encryption_key_fn;
4183   return offset;
4184 }
4185 
4186 static const ber_sequence_t KrbFastFinished_sequence[] = {
4187   { &hf_kerberos_timestamp  , BER_CLASS_CON, 0, 0, dissect_kerberos_KerberosTime },
4188   { &hf_kerberos_usec       , BER_CLASS_CON, 1, 0, dissect_kerberos_Microseconds },
4189   { &hf_kerberos_crealm     , BER_CLASS_CON, 2, 0, dissect_kerberos_Realm },
4190   { &hf_kerberos_cname_01   , BER_CLASS_CON, 3, 0, dissect_kerberos_PrincipalName },
4191   { &hf_kerberos_ticket_checksum, BER_CLASS_CON, 4, 0, dissect_kerberos_Checksum },
4192   { NULL, 0, 0, 0, NULL }
4193 };
4194 
4195 static int
4196 dissect_kerberos_KrbFastFinished(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
4197   offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
4198                                    KrbFastFinished_sequence, hf_index, ett_kerberos_KrbFastFinished);
4199 
4200   return offset;
4201 }
4202 
4203 static const ber_sequence_t KrbFastResponse_sequence[] = {
4204   { &hf_kerberos_padata     , BER_CLASS_CON, 0, 0, dissect_kerberos_SEQUENCE_OF_PA_DATA },
4205   { &hf_kerberos_strengthen_key, BER_CLASS_CON, 1, BER_FLAGS_OPTIONAL, dissect_kerberos_T_strengthen_key },
4206   { &hf_kerberos_finished   , BER_CLASS_CON, 2, BER_FLAGS_OPTIONAL, dissect_kerberos_KrbFastFinished },
4207   { &hf_kerberos_nonce      , BER_CLASS_CON, 3, 0, dissect_kerberos_UInt32 },
4208   { NULL, 0, 0, 0, NULL }
4209 };
4210 
4211 static int
4212 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_) {
4213   offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
4214                                    KrbFastResponse_sequence, hf_index, ett_kerberos_KrbFastResponse);
4215 
4216   return offset;
4217 }
4218 
4219 static const ber_sequence_t KrbFastReq_sequence[] = {
4220   { &hf_kerberos_fast_options, BER_CLASS_CON, 0, 0, dissect_kerberos_FastOptions },
4221   { &hf_kerberos_padata     , BER_CLASS_CON, 1, 0, dissect_kerberos_SEQUENCE_OF_PA_DATA },
4222   { &hf_kerberos_req_body   , BER_CLASS_CON, 2, 0, dissect_kerberos_KDC_REQ_BODY },
4223   { NULL, 0, 0, 0, NULL }
4224 };
4225 
4226 static int
4227 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_) {
4228   offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
4229                                    KrbFastReq_sequence, hf_index, ett_kerberos_KrbFastReq);
4230 
4231   return offset;
4232 }
4233 
4234 static int * const FastOptions_bits[] = {
4235   &hf_kerberos_FastOptions_reserved,
4236   &hf_kerberos_FastOptions_hide_client_names,
4237   &hf_kerberos_FastOptions_spare_bit2,
4238   &hf_kerberos_FastOptions_spare_bit3,
4239   &hf_kerberos_FastOptions_spare_bit4,
4240   &hf_kerberos_FastOptions_spare_bit5,
4241   &hf_kerberos_FastOptions_spare_bit6,
4242   &hf_kerberos_FastOptions_spare_bit7,
4243   &hf_kerberos_FastOptions_spare_bit8,
4244   &hf_kerberos_FastOptions_spare_bit9,
4245   &hf_kerberos_FastOptions_spare_bit10,
4246   &hf_kerberos_FastOptions_spare_bit11,
4247   &hf_kerberos_FastOptions_spare_bit12,
4248   &hf_kerberos_FastOptions_spare_bit13,
4249   &hf_kerberos_FastOptions_spare_bit14,
4250   &hf_kerberos_FastOptions_spare_bit15,
4251   &hf_kerberos_FastOptions_kdc_follow_referrals,
4252   NULL
4253 };
4254 
4255 static int
4256 dissect_kerberos_FastOptions(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
4257   offset = dissect_ber_bitstring(implicit_tag, actx, tree, tvb, offset,
4258                                     FastOptions_bits, 17, hf_index, ett_kerberos_FastOptions,
4259                                     NULL);
4260 
4261   return offset;
4262 }
4263 
4264 #endif /* HAVE_KERBEROS */
4265 
4266 /* Make wrappers around exported functions for now */
4267 int
4268 dissect_krb5_Checksum(proto_tree *tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
4269 {
4270 	return dissect_kerberos_Checksum(FALSE, tvb, offset, actx, tree, hf_kerberos_cksum);
4271 
4272 }
4273 
4274 int
4275 dissect_krb5_ctime(proto_tree *tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
4276 {
4277 	return dissect_kerberos_KerberosTime(FALSE, tvb, offset, actx, tree, hf_kerberos_ctime);
4278 }
4279 
4280 
4281 int
4282 dissect_krb5_cname(proto_tree *tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
4283 {
4284 	return dissect_kerberos_PrincipalName(FALSE, tvb, offset, actx, tree, hf_kerberos_cname);
4285 }
4286 int
4287 dissect_krb5_realm(proto_tree *tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
4288 {
4289 	return dissect_kerberos_Realm(FALSE, tvb, offset, actx, tree, hf_kerberos_realm);
4290 }
4291 
4292 struct kerberos_display_key_state {
4293 	proto_tree *tree;
4294 	packet_info *pinfo;
4295 	expert_field *expindex;
4296 	const char *name;
4297 	tvbuff_t *tvb;
4298 	gint start;
4299 	gint length;
4300 };
4301 
4302 static void
4303 #ifdef HAVE_KERBEROS
4304 kerberos_display_key(gpointer data, gpointer userdata)
4305 #else
4306 kerberos_display_key(gpointer data _U_, gpointer userdata _U_)
4307 #endif
4308 {
4309 #ifdef HAVE_KERBEROS
4310 	struct kerberos_display_key_state *state =
4311 		(struct kerberos_display_key_state *)userdata;
4312 	const enc_key_t *ek = (const enc_key_t *)data;
4313 	proto_item *item = NULL;
4314 	enc_key_t *sek = NULL;
4315 
4316 	item = proto_tree_add_expert_format(state->tree,
4317 					    state->pinfo,
4318 					    state->expindex,
4319 					    state->tvb,
4320 					    state->start,
4321 					    state->length,
4322 					    "%s %s keytype %d (id=%s same=%u) (%02x%02x%02x%02x...)",
4323 					    state->name,
4324 					    ek->key_origin, ek->keytype,
4325 					    ek->id_str, ek->num_same,
4326 					    ek->keyvalue[0] & 0xFF, ek->keyvalue[1] & 0xFF,
4327 					    ek->keyvalue[2] & 0xFF, ek->keyvalue[3] & 0xFF);
4328 	if (ek->src1 != NULL) {
4329 		sek = ek->src1;
4330 		expert_add_info_format(state->pinfo,
4331 				       item,
4332 				       state->expindex,
4333 				       "SRC1 %s keytype %d (id=%s same=%u) (%02x%02x%02x%02x...)",
4334 				       sek->key_origin, sek->keytype,
4335 				       sek->id_str, sek->num_same,
4336 				       sek->keyvalue[0] & 0xFF, sek->keyvalue[1] & 0xFF,
4337 				       sek->keyvalue[2] & 0xFF, sek->keyvalue[3] & 0xFF);
4338 	}
4339 	if (ek->src2 != NULL) {
4340 		sek = ek->src2;
4341 		expert_add_info_format(state->pinfo,
4342 				       item,
4343 				       state->expindex,
4344 				       "SRC2 %s keytype %d (id=%s same=%u) (%02x%02x%02x%02x...)",
4345 				       sek->key_origin, sek->keytype,
4346 				       sek->id_str, sek->num_same,
4347 				       sek->keyvalue[0] & 0xFF, sek->keyvalue[1] & 0xFF,
4348 				       sek->keyvalue[2] & 0xFF, sek->keyvalue[3] & 0xFF);
4349 	}
4350 	sek = ek->same_list;
4351 	while (sek != NULL) {
4352 		expert_add_info_format(state->pinfo,
4353 				       item,
4354 				       state->expindex,
4355 				       "%s %s keytype %d (id=%s same=%u) (%02x%02x%02x%02x...)",
4356 				       state->name,
4357 				       sek->key_origin, sek->keytype,
4358 				       sek->id_str, sek->num_same,
4359 				       sek->keyvalue[0] & 0xFF, sek->keyvalue[1] & 0xFF,
4360 				       sek->keyvalue[2] & 0xFF, sek->keyvalue[3] & 0xFF);
4361 		sek = sek->same_list;
4362 	}
4363 #endif /* HAVE_KERBEROS */
4364 }
4365 
4366 static const value_string KERB_LOGON_SUBMIT_TYPE[] = {
4367     { 2, "KerbInteractiveLogon" },
4368     { 6, "KerbSmartCardLogon" },
4369     { 7, "KerbWorkstationUnlockLogon" },
4370     { 8, "KerbSmartCardUnlockLogon" },
4371     { 9, "KerbProxyLogon" },
4372     { 10, "KerbTicketLogon" },
4373     { 11, "KerbTicketUnlockLogon" },
4374     { 12, "KerbS4ULogon" },
4375     { 13, "KerbCertificateLogon" },
4376     { 14, "KerbCertificateS4ULogon" },
4377     { 15, "KerbCertificateUnlockLogon" },
4378     { 0, NULL }
4379 };
4380 
4381 
4382 #define KERB_LOGON_FLAG_ALLOW_EXPIRED_TICKET 0x1
4383 #define KERB_LOGON_FLAG_REDIRECTED           0x2
4384 
4385 static int* const ktl_flags_bits[] = {
4386 	&hf_kerberos_KERB_TICKET_LOGON_FLAG_ALLOW_EXPIRED_TICKET,
4387 	&hf_kerberos_KERB_TICKET_LOGON_FLAG_REDIRECTED,
4388 	NULL
4389 };
4390 
4391 int
4392 dissect_kerberos_KERB_TICKET_LOGON(tvbuff_t *tvb, int offset, asn1_ctx_t *actx, proto_tree *tree)
4393 {
4394 	proto_item *item;
4395 	proto_tree *subtree;
4396 	guint32 ServiceTicketLength;
4397 	guint32 TicketGrantingTicketLength;
4398 	int orig_offset;
4399 
4400 	if (tvb_captured_length(tvb) < 32)
4401 		return offset;
4402 
4403 	item = proto_tree_add_item(tree, hf_kerberos_KERB_TICKET_LOGON, tvb, offset, -1, ENC_NA);
4404 	subtree = proto_item_add_subtree(item, ett_kerberos_KERB_TICKET_LOGON);
4405 
4406 	proto_tree_add_item(subtree, hf_kerberos_KERB_TICKET_LOGON_MessageType, tvb, offset, 4,
4407 			    ENC_LITTLE_ENDIAN);
4408 	offset+=4;
4409 
4410 	proto_tree_add_bitmask(subtree, tvb, offset, hf_kerberos_KERB_TICKET_LOGON_Flags,
4411 			       ett_kerberos, ktl_flags_bits, ENC_LITTLE_ENDIAN);
4412 	offset+=4;
4413 
4414 	ServiceTicketLength = tvb_get_letohl(tvb, offset);
4415 	proto_tree_add_item(subtree, hf_kerberos_KERB_TICKET_LOGON_ServiceTicketLength, tvb,
4416 			    offset, 4, ENC_LITTLE_ENDIAN);
4417 	offset+=4;
4418 
4419 	TicketGrantingTicketLength = tvb_get_letohl(tvb, offset);
4420 	proto_tree_add_item(subtree, hf_kerberos_KERB_TICKET_LOGON_TicketGrantingTicketLength,
4421 			    tvb, offset, 4, ENC_LITTLE_ENDIAN);
4422 	offset+=4;
4423 
4424 	/* Skip two PUCHAR of ServiceTicket and TicketGrantingTicket */
4425 	offset+=16;
4426 
4427 	if (ServiceTicketLength == 0)
4428 		return offset;
4429 
4430 	orig_offset = offset;
4431 	offset = dissect_kerberos_Ticket(FALSE, tvb, offset, actx, subtree,
4432 					 hf_kerberos_KERB_TICKET_LOGON_ServiceTicket);
4433 
4434 	if ((unsigned)(offset-orig_offset) != ServiceTicketLength)
4435 		return offset;
4436 
4437 	if (TicketGrantingTicketLength == 0)
4438 		return offset;
4439 
4440 	offset = dissect_kerberos_KRB_CRED(FALSE, tvb, offset, actx, subtree,
4441 					   hf_kerberos_KERB_TICKET_LOGON_TicketGrantingTicket);
4442 
4443 	if ((unsigned)(offset-orig_offset) != ServiceTicketLength + TicketGrantingTicketLength)
4444 		return offset;
4445 
4446 	return offset;
4447 }
4448 
4449 static gint
4450 dissect_kerberos_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4451     gboolean dci, gboolean do_col_protocol, gboolean have_rm,
4452     kerberos_callbacks *cb)
4453 {
4454 	volatile int offset = 0;
4455 	proto_tree *volatile kerberos_tree = NULL;
4456 	proto_item *volatile item = NULL;
4457 	kerberos_private_data_t *private_data = NULL;
4458 	asn1_ctx_t asn1_ctx;
4459 
4460 	/* TCP record mark and length */
4461 	guint32 krb_rm = 0;
4462 	gint krb_reclen = 0;
4463 
4464 	gbl_do_col_info=dci;
4465 
4466 	if (have_rm) {
4467 		krb_rm = tvb_get_ntohl(tvb, offset);
4468 		krb_reclen = kerberos_rm_to_reclen(krb_rm);
4469 		/*
4470 		 * What is a reasonable size limit?
4471 		 */
4472 		if (krb_reclen > 10 * 1024 * 1024) {
4473 			return (-1);
4474 		}
4475 
4476 		if (do_col_protocol) {
4477 			col_set_str(pinfo->cinfo, COL_PROTOCOL, "KRB5");
4478 		}
4479 
4480 		if (tree) {
4481 			item = proto_tree_add_item(tree, proto_kerberos, tvb, 0, -1, ENC_NA);
4482 			kerberos_tree = proto_item_add_subtree(item, ett_kerberos);
4483 		}
4484 
4485 		show_krb_recordmark(kerberos_tree, tvb, offset, krb_rm);
4486 		offset += 4;
4487 	} else {
4488 		/* Do some sanity checking here,
4489 		 * All krb5 packets start with a TAG class that is BER_CLASS_APP
4490 		 * and a tag value that is either of the values below:
4491 		 * If it doesn't look like kerberos, return 0 and let someone else have
4492 		 * a go at it.
4493 		 */
4494 		gint8 tmp_class;
4495 		gboolean tmp_pc;
4496 		gint32 tmp_tag;
4497 
4498 		get_ber_identifier(tvb, offset, &tmp_class, &tmp_pc, &tmp_tag);
4499 		if(tmp_class!=BER_CLASS_APP){
4500 			return 0;
4501 		}
4502 		switch(tmp_tag){
4503 			case KRB5_MSG_TICKET:
4504 			case KRB5_MSG_AUTHENTICATOR:
4505 			case KRB5_MSG_ENC_TICKET_PART:
4506 			case KRB5_MSG_AS_REQ:
4507 			case KRB5_MSG_AS_REP:
4508 			case KRB5_MSG_TGS_REQ:
4509 			case KRB5_MSG_TGS_REP:
4510 			case KRB5_MSG_AP_REQ:
4511 			case KRB5_MSG_AP_REP:
4512 			case KRB5_MSG_ENC_AS_REP_PART:
4513 			case KRB5_MSG_ENC_TGS_REP_PART:
4514 			case KRB5_MSG_ENC_AP_REP_PART:
4515 			case KRB5_MSG_ENC_KRB_PRIV_PART:
4516 			case KRB5_MSG_ENC_KRB_CRED_PART:
4517 			case KRB5_MSG_SAFE:
4518 			case KRB5_MSG_PRIV:
4519 			case KRB5_MSG_ERROR:
4520 				break;
4521 			default:
4522 				return 0;
4523 		}
4524 		if (do_col_protocol) {
4525 			col_set_str(pinfo->cinfo, COL_PROTOCOL, "KRB5");
4526 		}
4527 		if (gbl_do_col_info) {
4528 			col_clear(pinfo->cinfo, COL_INFO);
4529 		}
4530 		if (tree) {
4531 			item = proto_tree_add_item(tree, proto_kerberos, tvb, 0, -1, ENC_NA);
4532 			kerberos_tree = proto_item_add_subtree(item, ett_kerberos);
4533 		}
4534 	}
4535 	asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
4536 	asn1_ctx.private_data = NULL;
4537 	private_data = kerberos_get_private_data(&asn1_ctx);
4538 	private_data->callbacks = cb;
4539 
4540 	TRY {
4541 		offset=dissect_kerberos_Applications(FALSE, tvb, offset, &asn1_ctx , kerberos_tree, /* hf_index */ -1);
4542 	} CATCH_BOUNDS_ERRORS {
4543 		RETHROW;
4544 	} ENDTRY;
4545 
4546 	if (kerberos_tree != NULL) {
4547 		struct kerberos_display_key_state display_state = {
4548 			.tree = kerberos_tree,
4549 			.pinfo = pinfo,
4550 			.expindex = &ei_kerberos_learnt_keytype,
4551 			.name = "Provides",
4552 			.tvb = tvb,
4553 		};
4554 
4555 		wmem_list_foreach(private_data->learnt_keys,
4556 				  kerberos_display_key,
4557 				  &display_state);
4558 	}
4559 
4560 	if (kerberos_tree != NULL) {
4561 		struct kerberos_display_key_state display_state = {
4562 			.tree = kerberos_tree,
4563 			.pinfo = pinfo,
4564 			.expindex = &ei_kerberos_missing_keytype,
4565 			.name = "Missing",
4566 			.tvb = tvb,
4567 		};
4568 
4569 		wmem_list_foreach(private_data->missing_keys,
4570 				  kerberos_display_key,
4571 				  &display_state);
4572 	}
4573 
4574 	if (kerberos_tree != NULL) {
4575 		struct kerberos_display_key_state display_state = {
4576 			.tree = kerberos_tree,
4577 			.pinfo = pinfo,
4578 			.expindex = &ei_kerberos_decrypted_keytype,
4579 			.name = "Used",
4580 			.tvb = tvb,
4581 		};
4582 
4583 		wmem_list_foreach(private_data->decryption_keys,
4584 				  kerberos_display_key,
4585 				  &display_state);
4586 	}
4587 
4588 	proto_item_set_len(item, offset);
4589 	return offset;
4590 }
4591 
4592 /*
4593  * Display the TCP record mark.
4594  */
4595 void
4596 show_krb_recordmark(proto_tree *tree, tvbuff_t *tvb, gint start, guint32 krb_rm)
4597 {
4598 	gint rec_len;
4599 	proto_tree *rm_tree;
4600 
4601 	if (tree == NULL)
4602 		return;
4603 
4604 	rec_len = kerberos_rm_to_reclen(krb_rm);
4605 	rm_tree = proto_tree_add_subtree_format(tree, tvb, start, 4, ett_krb_recordmark, NULL,
4606 		"Record Mark: %u %s", rec_len, plurality(rec_len, "byte", "bytes"));
4607 	proto_tree_add_boolean(rm_tree, hf_krb_rm_reserved, tvb, start, 4, krb_rm);
4608 	proto_tree_add_uint(rm_tree, hf_krb_rm_reclen, tvb, start, 4, krb_rm);
4609 }
4610 
4611 gint
4612 dissect_kerberos_main(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int do_col_info, kerberos_callbacks *cb)
4613 {
4614 	return (dissect_kerberos_common(tvb, pinfo, tree, do_col_info, FALSE, FALSE, cb));
4615 }
4616 
4617 guint32
4618 kerberos_output_keytype(void)
4619 {
4620 	return gbl_keytype;
4621 }
4622 
4623 static gint
4624 dissect_kerberos_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
4625 {
4626 	/* Some weird kerberos implementation apparently do krb4 on the krb5 port.
4627 	   Since all (except weirdo transarc krb4 stuff) use
4628 	   an opcode <=16 in the first byte, use this to see if it might
4629 	   be krb4.
4630 	   All krb5 commands start with an APPL tag and thus is >=0x60
4631 	   so if first byte is <=16  just blindly assume it is krb4 then
4632 	*/
4633 	if(tvb_captured_length(tvb) >= 1 && tvb_get_guint8(tvb, 0)<=0x10){
4634 		if(krb4_handle){
4635 			gboolean res;
4636 
4637 			res=call_dissector_only(krb4_handle, tvb, pinfo, tree, NULL);
4638 			return res;
4639 		}else{
4640 			return 0;
4641 		}
4642 	}
4643 
4644 
4645 	return dissect_kerberos_common(tvb, pinfo, tree, TRUE, TRUE, FALSE, NULL);
4646 }
4647 
4648 gint
4649 kerberos_rm_to_reclen(guint krb_rm)
4650 {
4651     return (krb_rm & KRB_RM_RECLEN);
4652 }
4653 
4654 guint
4655 get_krb_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
4656 {
4657 	guint krb_rm;
4658 	gint pdulen;
4659 
4660 	krb_rm = tvb_get_ntohl(tvb, offset);
4661 	pdulen = kerberos_rm_to_reclen(krb_rm);
4662 	return (pdulen + 4);
4663 }
4664 static void
4665 kerberos_prefs_apply_cb(void) {
4666 #ifdef HAVE_LIBNETTLE
4667 	clear_keytab();
4668 	read_keytab_file(keytab_filename);
4669 #endif
4670 }
4671 
4672 static int
4673 dissect_kerberos_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
4674 {
4675 	pinfo->fragmented = TRUE;
4676 	if (dissect_kerberos_common(tvb, pinfo, tree, TRUE, TRUE, TRUE, NULL) < 0) {
4677 		/*
4678 		 * The dissector failed to recognize this as a valid
4679 		 * Kerberos message.  Mark it as a continuation packet.
4680 		 */
4681 		col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
4682 	}
4683 
4684 	return tvb_captured_length(tvb);
4685 }
4686 
4687 static int
4688 dissect_kerberos_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
4689 {
4690 	col_set_str(pinfo->cinfo, COL_PROTOCOL, "KRB5");
4691 	col_clear(pinfo->cinfo, COL_INFO);
4692 
4693 	tcp_dissect_pdus(tvb, pinfo, tree, krb_desegment, 4, get_krb_pdu_len,
4694 					 dissect_kerberos_tcp_pdu, data);
4695 	return tvb_captured_length(tvb);
4696 }
4697 
4698 /*--- proto_register_kerberos -------------------------------------------*/
4699 void proto_register_kerberos(void) {
4700 
4701 	/* List of fields */
4702 
4703 	static hf_register_info hf[] = {
4704 	{ &hf_krb_rm_reserved, {
4705 		"Reserved", "kerberos.rm.reserved", FT_BOOLEAN, 32,
4706 		TFS(&tfs_set_notset), KRB_RM_RESERVED, "Record mark reserved bit", HFILL }},
4707 	{ &hf_krb_rm_reclen, {
4708 		"Record Length", "kerberos.rm.length", FT_UINT32, BASE_DEC,
4709 		NULL, KRB_RM_RECLEN, NULL, HFILL }},
4710 	{ &hf_krb_provsrv_location, {
4711 		"PROVSRV Location", "kerberos.provsrv_location", FT_STRING, BASE_NONE,
4712 		NULL, 0, "PacketCable PROV SRV Location", HFILL }},
4713 	{ &hf_krb_pw_salt,
4714 		{ "pw-salt", "kerberos.pw_salt", FT_BYTES, BASE_NONE,
4715 		NULL, 0, NULL, HFILL }},
4716 	{ &hf_krb_ext_error_nt_status, /* we keep kerberos.smb.nt_status for compat reasons */
4717 		{ "NT Status", "kerberos.smb.nt_status", FT_UINT32, BASE_HEX,
4718 		VALS(NT_errors), 0, "NT Status code", HFILL }},
4719 	{ &hf_krb_ext_error_reserved,
4720 		{ "Reserved", "kerberos.ext_error.reserved", FT_UINT32, BASE_HEX,
4721 		NULL, 0, NULL, HFILL }},
4722 	{ &hf_krb_ext_error_flags,
4723 		{ "Flags", "kerberos.ext_error.flags", FT_UINT32, BASE_HEX,
4724 		NULL, 0, NULL, HFILL }},
4725 	{ &hf_krb_address_ip, {
4726 		"IP Address", "kerberos.addr_ip", FT_IPv4, BASE_NONE,
4727 		NULL, 0, NULL, HFILL }},
4728 	{ &hf_krb_address_ipv6, {
4729 		"IPv6 Address", "kerberos.addr_ipv6", FT_IPv6, BASE_NONE,
4730 		NULL, 0, NULL, HFILL }},
4731 	{ &hf_krb_address_netbios, {
4732 		"NetBIOS Address", "kerberos.addr_nb", FT_STRING, BASE_NONE,
4733 		NULL, 0, "NetBIOS Address and type", HFILL }},
4734 	{ &hf_krb_gssapi_len, {
4735 		"Length", "kerberos.gssapi.len", FT_UINT32, BASE_DEC,
4736 		NULL, 0, "Length of GSSAPI Bnd field", HFILL }},
4737 	{ &hf_krb_gssapi_bnd, {
4738 		"Bnd", "kerberos.gssapi.bdn", FT_BYTES, BASE_NONE,
4739 		NULL, 0, "GSSAPI Bnd field", HFILL }},
4740 	{ &hf_krb_gssapi_c_flag_deleg, {
4741 		"Deleg", "kerberos.gssapi.checksum.flags.deleg", FT_BOOLEAN, 32,
4742 		TFS(&tfs_gss_flags_deleg), KRB5_GSS_C_DELEG_FLAG, NULL, HFILL }},
4743 	{ &hf_krb_gssapi_c_flag_mutual, {
4744 		"Mutual", "kerberos.gssapi.checksum.flags.mutual", FT_BOOLEAN, 32,
4745 		TFS(&tfs_gss_flags_mutual), KRB5_GSS_C_MUTUAL_FLAG, NULL, HFILL }},
4746 	{ &hf_krb_gssapi_c_flag_replay, {
4747 		"Replay", "kerberos.gssapi.checksum.flags.replay", FT_BOOLEAN, 32,
4748 		TFS(&tfs_gss_flags_replay), KRB5_GSS_C_REPLAY_FLAG, NULL, HFILL }},
4749 	{ &hf_krb_gssapi_c_flag_sequence, {
4750 		"Sequence", "kerberos.gssapi.checksum.flags.sequence", FT_BOOLEAN, 32,
4751 		TFS(&tfs_gss_flags_sequence), KRB5_GSS_C_SEQUENCE_FLAG, NULL, HFILL }},
4752 	{ &hf_krb_gssapi_c_flag_conf, {
4753 		"Conf", "kerberos.gssapi.checksum.flags.conf", FT_BOOLEAN, 32,
4754 		TFS(&tfs_gss_flags_conf), KRB5_GSS_C_CONF_FLAG, NULL, HFILL }},
4755 	{ &hf_krb_gssapi_c_flag_integ, {
4756 		"Integ", "kerberos.gssapi.checksum.flags.integ", FT_BOOLEAN, 32,
4757 		TFS(&tfs_gss_flags_integ), KRB5_GSS_C_INTEG_FLAG, NULL, HFILL }},
4758 	{ &hf_krb_gssapi_c_flag_dce_style, {
4759 		"DCE-style", "kerberos.gssapi.checksum.flags.dce-style", FT_BOOLEAN, 32,
4760 		TFS(&tfs_gss_flags_dce_style), KRB5_GSS_C_DCE_STYLE, NULL, HFILL }},
4761 	{ &hf_krb_gssapi_dlgopt, {
4762 		"DlgOpt", "kerberos.gssapi.dlgopt", FT_UINT16, BASE_DEC,
4763 		NULL, 0, "GSSAPI DlgOpt", HFILL }},
4764 	{ &hf_krb_gssapi_dlglen, {
4765 		"DlgLen", "kerberos.gssapi.dlglen", FT_UINT16, BASE_DEC,
4766 		NULL, 0, "GSSAPI DlgLen", HFILL }},
4767 	{ &hf_krb_midl_blob_len, {
4768 		"Blob Length", "kerberos.midl_blob_len", FT_UINT64, BASE_DEC,
4769 		NULL, 0, "Length of NDR encoded data that follows", HFILL }},
4770 	{ &hf_krb_midl_fill_bytes, {
4771 		"Fill bytes", "kerberos.midl.fill_bytes", FT_UINT32, BASE_HEX,
4772 		NULL, 0, "Just some fill bytes", HFILL }},
4773 	{ &hf_krb_midl_version, {
4774 	"Version", "kerberos.midl.version", FT_UINT8, BASE_DEC,
4775 	NULL, 0, "Version of pickling", HFILL }},
4776 	{ &hf_krb_midl_hdr_len, {
4777 		"HDR Length", "kerberos.midl.hdr_len", FT_UINT16, BASE_DEC,
4778 		NULL, 0, "Length of header", HFILL }},
4779 	{ &hf_krb_pac_signature_type, {
4780 		"Type", "kerberos.pac.signature.type", FT_INT32, BASE_DEC,
4781 		NULL, 0, "PAC Signature Type", HFILL }},
4782 	{ &hf_krb_pac_signature_signature, {
4783 		"Signature", "kerberos.pac.signature.signature", FT_BYTES, BASE_NONE,
4784 		NULL, 0, "A PAC signature blob", HFILL }},
4785 	{ &hf_krb_w2k_pac_entries, {
4786 		"Num Entries", "kerberos.pac.entries", FT_UINT32, BASE_DEC,
4787 		NULL, 0, "Number of W2k PAC entries", HFILL }},
4788 	{ &hf_krb_w2k_pac_version, {
4789 		"Version", "kerberos.pac.version", FT_UINT32, BASE_DEC,
4790 		NULL, 0, "Version of PAC structures", HFILL }},
4791 	{ &hf_krb_w2k_pac_type, {
4792 		"Type", "kerberos.pac.type", FT_UINT32, BASE_DEC,
4793 		VALS(w2k_pac_types), 0, "Type of W2k PAC entry", HFILL }},
4794 	{ &hf_krb_w2k_pac_size, {
4795 		"Size", "kerberos.pac.size", FT_UINT32, BASE_DEC,
4796 		NULL, 0, "Size of W2k PAC entry", HFILL }},
4797 	{ &hf_krb_w2k_pac_offset, {
4798 		"Offset", "kerberos.pac.offset", FT_UINT32, BASE_DEC,
4799 		NULL, 0, "Offset to W2k PAC entry", HFILL }},
4800 	{ &hf_krb_pac_clientid, {
4801 		"ClientID", "kerberos.pac.clientid", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL,
4802 		NULL, 0, "ClientID Timestamp", HFILL }},
4803 	{ &hf_krb_pac_namelen, {
4804 		"Name Length", "kerberos.pac.namelen", FT_UINT16, BASE_DEC,
4805 		NULL, 0, "Length of client name", HFILL }},
4806 	{ &hf_krb_pac_clientname, {
4807 		"Name", "kerberos.pac.name", FT_STRING, BASE_NONE,
4808 		NULL, 0, "Name of the Client in the PAC structure", HFILL }},
4809 	{ &hf_krb_pac_logon_info, {
4810 		"PAC_LOGON_INFO", "kerberos.pac_logon_info", FT_BYTES, BASE_NONE,
4811 		NULL, 0, "PAC_LOGON_INFO structure", HFILL }},
4812 	{ &hf_krb_pac_credential_data, {
4813 		"PAC_CREDENTIAL_DATA", "kerberos.pac_credential_data", FT_BYTES, BASE_NONE,
4814 		NULL, 0, "PAC_CREDENTIAL_DATA structure", HFILL }},
4815 	{ &hf_krb_pac_credential_info, {
4816 		"PAC_CREDENTIAL_INFO", "kerberos.pac_credential_info", FT_BYTES, BASE_NONE,
4817 		NULL, 0, "PAC_CREDENTIAL_INFO structure", HFILL }},
4818 	{ &hf_krb_pac_credential_info_version, {
4819 		"Version", "kerberos.pac_credential_info.version", FT_UINT32, BASE_DEC,
4820 		NULL, 0, NULL, HFILL }},
4821 	{ &hf_krb_pac_credential_info_etype, {
4822 		"Etype", "kerberos.pac_credential_info.etype", FT_UINT32, BASE_DEC,
4823 		NULL, 0, NULL, HFILL }},
4824 	{ &hf_krb_pac_server_checksum, {
4825 		"PAC_SERVER_CHECKSUM", "kerberos.pac_server_checksum", FT_BYTES, BASE_NONE,
4826 		NULL, 0, "PAC_SERVER_CHECKSUM structure", HFILL }},
4827 	{ &hf_krb_pac_privsvr_checksum, {
4828 		"PAC_PRIVSVR_CHECKSUM", "kerberos.pac_privsvr_checksum", FT_BYTES, BASE_NONE,
4829 		NULL, 0, "PAC_PRIVSVR_CHECKSUM structure", HFILL }},
4830 	{ &hf_krb_pac_client_info_type, {
4831 		"PAC_CLIENT_INFO_TYPE", "kerberos.pac_client_info_type", FT_BYTES, BASE_NONE,
4832 		NULL, 0, "PAC_CLIENT_INFO_TYPE structure", HFILL }},
4833 	{ &hf_krb_pac_s4u_delegation_info, {
4834 		"PAC_S4U_DELEGATION_INFO", "kerberos.pac_s4u_delegation_info", FT_BYTES, BASE_NONE,
4835 		NULL, 0, "PAC_S4U_DELEGATION_INFO structure", HFILL }},
4836 	{ &hf_krb_pac_upn_dns_info, {
4837 		"UPN_DNS_INFO", "kerberos.pac_upn_dns_info", FT_BYTES, BASE_NONE,
4838 		NULL, 0, "UPN_DNS_INFO structure", HFILL }},
4839 	{ &hf_krb_pac_upn_flags, {
4840 		"Flags", "kerberos.pac.upn.flags", FT_UINT32, BASE_HEX,
4841 		NULL, 0, "UPN flags", HFILL }},
4842 	{ &hf_krb_pac_upn_dns_offset, {
4843 		"DNS Offset", "kerberos.pac.upn.dns_offset", FT_UINT16, BASE_DEC,
4844 		NULL, 0, NULL, HFILL }},
4845 	{ &hf_krb_pac_upn_dns_len, {
4846 		"DNS Len", "kerberos.pac.upn.dns_len", FT_UINT16, BASE_DEC,
4847 		NULL, 0, NULL, HFILL }},
4848 	{ &hf_krb_pac_upn_upn_offset, {
4849 		"UPN Offset", "kerberos.pac.upn.upn_offset", FT_UINT16, BASE_DEC,
4850 		NULL, 0, NULL, HFILL }},
4851 	{ &hf_krb_pac_upn_upn_len, {
4852 		"UPN Len", "kerberos.pac.upn.upn_len", FT_UINT16, BASE_DEC,
4853 		NULL, 0, NULL, HFILL }},
4854 	{ &hf_krb_pac_upn_upn_name, {
4855 		"UPN Name", "kerberos.pac.upn.upn_name", FT_STRING, BASE_NONE,
4856 		NULL, 0, NULL, HFILL }},
4857 	{ &hf_krb_pac_upn_dns_name, {
4858 		"DNS Name", "kerberos.pac.upn.dns_name", FT_STRING, BASE_NONE,
4859 		NULL, 0, NULL, HFILL }},
4860 	{ &hf_krb_pac_client_claims_info, {
4861 		"PAC_CLIENT_CLAIMS_INFO", "kerberos.pac_client_claims_info", FT_BYTES, BASE_NONE,
4862 		NULL, 0, "PAC_CLIENT_CLAIMS_INFO structure", HFILL }},
4863 	{ &hf_krb_pac_device_info, {
4864 		"PAC_DEVICE_INFO", "kerberos.pac_device_info", FT_BYTES, BASE_NONE,
4865 		NULL, 0, "PAC_DEVICE_INFO structure", HFILL }},
4866 	{ &hf_krb_pac_device_claims_info, {
4867 		"PAC_DEVICE_CLAIMS_INFO", "kerberos.pac_device_claims_info", FT_BYTES, BASE_NONE,
4868 		NULL, 0, "PAC_DEVICE_CLAIMS_INFO structure", HFILL }},
4869 	{ &hf_krb_pac_ticket_checksum, {
4870 		"PAC_TICKET_CHECKSUM", "kerberos.pac_ticket_checksum", FT_BYTES, BASE_NONE,
4871 		NULL, 0, "PAC_TICKET_CHECKSUM structure", HFILL }},
4872 	{ &hf_krb_pa_supported_enctypes,
4873 	  { "SupportedEnctypes", "kerberos.supported_entypes",
4874 	    FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
4875 	{ &hf_krb_pa_supported_enctypes_des_cbc_crc,
4876 	  { "des-cbc-crc", "kerberos.supported_entypes.des-cbc-crc",
4877 		FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x00000001, NULL, HFILL }},
4878 	{ &hf_krb_pa_supported_enctypes_des_cbc_md5,
4879 	  { "des-cbc-md5", "kerberos.supported_entypes.des-cbc-md5",
4880 		FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x00000002, NULL, HFILL }},
4881 	{ &hf_krb_pa_supported_enctypes_rc4_hmac,
4882 	  { "rc4-hmac", "kerberos.supported_entypes.rc4-hmac",
4883 		FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x00000004, NULL, HFILL }},
4884 	{ &hf_krb_pa_supported_enctypes_aes128_cts_hmac_sha1_96,
4885 	  { "aes128-cts-hmac-sha1-96", "kerberos.supported_entypes.aes128-cts-hmac-sha1-96",
4886 		FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x00000008, NULL, HFILL }},
4887 	{ &hf_krb_pa_supported_enctypes_aes256_cts_hmac_sha1_96,
4888 	  { "aes256-cts-hmac-sha1-96", "kerberos.supported_entypes.aes256-cts-hmac-sha1-96",
4889 		FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x00000010, NULL, HFILL }},
4890 	{ &hf_krb_pa_supported_enctypes_fast_supported,
4891 	  { "fast-supported", "kerberos.supported_entypes.fast-supported",
4892 		FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x00010000, NULL, HFILL }},
4893 	{ &hf_krb_pa_supported_enctypes_compound_identity_supported,
4894 	  { "compound-identity-supported", "kerberos.supported_entypes.compound-identity-supported",
4895 		FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x00020000, NULL, HFILL }},
4896 	{ &hf_krb_pa_supported_enctypes_claims_supported,
4897 	  { "claims-supported", "kerberos.supported_entypes.claims-supported",
4898 		FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x00040000, NULL, HFILL }},
4899 	{ &hf_krb_pa_supported_enctypes_resource_sid_compression_disabled,
4900 	  { "resource-sid-compression-disabled", "kerberos.supported_entypes.resource-sid-compression-disabled",
4901 		FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x00080000, NULL, HFILL }},
4902 	{ &hf_krb_ad_ap_options,
4903 	  { "AD-AP-Options", "kerberos.ad_ap_options",
4904 	    FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
4905 	{ &hf_krb_ad_ap_options_cbt,
4906 	  { "ChannelBindings", "kerberos.ad_ap_options.cbt",
4907 		FT_BOOLEAN, 32, TFS(&tfs_set_notset), 0x00004000, NULL, HFILL }},
4908 	{ &hf_krb_ad_target_principal,
4909 	  { "Target Principal", "kerberos.ad_target_principal",
4910 	    FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
4911 	{ &hf_krb_key_hidden_item,
4912 	  { "KeyHiddenItem", "krb5.key_hidden_item",
4913 	    FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
4914     { &hf_kerberos_KERB_TICKET_LOGON,
4915       { "KERB_TICKET_LOGON", "kerberos.KERB_TICKET_LOGON",
4916         FT_NONE, BASE_NONE, NULL, 0,
4917         NULL, HFILL }},
4918     { &hf_kerberos_KERB_TICKET_LOGON_MessageType,
4919       { "MessageType", "kerberos.KERB_TICKET_LOGON.MessageType",
4920         FT_UINT32, BASE_DEC, VALS(KERB_LOGON_SUBMIT_TYPE), 0,
4921         NULL, HFILL }},
4922     { &hf_kerberos_KERB_TICKET_LOGON_Flags,
4923       { "Flags", "kerberos.KERB_TICKET_LOGON.Flags",
4924         FT_UINT32, BASE_DEC, NULL, 0,
4925         NULL, HFILL }},
4926     { &hf_kerberos_KERB_TICKET_LOGON_ServiceTicketLength,
4927       { "ServiceTicketLength", "kerberos.KERB_TICKET_LOGON.ServiceTicketLength",
4928         FT_UINT32, BASE_DEC, NULL, 0,
4929         NULL, HFILL }},
4930     { &hf_kerberos_KERB_TICKET_LOGON_TicketGrantingTicketLength,
4931       { "TicketGrantingTicketLength", "kerberos.KERB_TICKET_LOGON.TicketGrantingTicketLength",
4932         FT_UINT32, BASE_DEC, NULL, 0,
4933         NULL, HFILL }},
4934     { &hf_kerberos_KERB_TICKET_LOGON_ServiceTicket,
4935       { "ServiceTicket", "kerberos.KERB_TICKET_LOGON.ServiceTicket",
4936         FT_NONE, BASE_NONE, NULL, 0,
4937         NULL, HFILL }},
4938     { &hf_kerberos_KERB_TICKET_LOGON_TicketGrantingTicket,
4939       { "TicketGrantingTicket", "kerberos.KERB_TICKET_LOGON.TicketGrantingTicket",
4940         FT_NONE, BASE_NONE, NULL, 0,
4941         NULL, HFILL }},
4942     { &hf_kerberos_KERB_TICKET_LOGON_FLAG_ALLOW_EXPIRED_TICKET,
4943       { "allow_expired_ticket", "kerberos.KERB_TICKET_LOGON.FLAG_ALLOW_EXPIRED_TICKET",
4944         FT_BOOLEAN, 32, NULL, KERB_LOGON_FLAG_ALLOW_EXPIRED_TICKET,
4945         NULL, HFILL }},
4946     { &hf_kerberos_KERB_TICKET_LOGON_FLAG_REDIRECTED,
4947       { "redirected", "kerberos.KERB_TICKET_LOGON.FLAG_REDIRECTED",
4948         FT_BOOLEAN, 32, NULL, KERB_LOGON_FLAG_REDIRECTED,
4949         NULL, HFILL }},
4950 #ifdef HAVE_KERBEROS
4951 	{ &hf_kerberos_KrbFastResponse,
4952 	   { "KrbFastResponse", "kerberos.KrbFastResponse_element",
4953 	    FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }},
4954 	{ &hf_kerberos_strengthen_key,
4955       { "strengthen-key", "kerberos.strengthen_key_element",
4956         FT_NONE, BASE_NONE, NULL, 0,
4957         NULL, HFILL }},
4958     { &hf_kerberos_finished,
4959       { "finished", "kerberos.finished_element",
4960         FT_NONE, BASE_NONE, NULL, 0,
4961         "KrbFastFinished", HFILL }},
4962     { &hf_kerberos_fast_options,
4963       { "fast-options", "kerberos.fast_options",
4964         FT_BYTES, BASE_NONE, NULL, 0,
4965         "FastOptions", HFILL }},
4966     { &hf_kerberos_FastOptions_reserved,
4967       { "reserved", "kerberos.FastOptions.reserved",
4968         FT_BOOLEAN, 8, NULL, 0x80,
4969         NULL, HFILL }},
4970     { &hf_kerberos_FastOptions_hide_client_names,
4971       { "hide-client-names", "kerberos.FastOptions.hide.client.names",
4972         FT_BOOLEAN, 8, NULL, 0x40,
4973         NULL, HFILL }},
4974     { &hf_kerberos_FastOptions_spare_bit2,
4975       { "spare_bit2", "kerberos.FastOptions.spare.bit2",
4976         FT_BOOLEAN, 8, NULL, 0x20,
4977         NULL, HFILL }},
4978     { &hf_kerberos_FastOptions_spare_bit3,
4979       { "spare_bit3", "kerberos.FastOptions.spare.bit3",
4980         FT_BOOLEAN, 8, NULL, 0x10,
4981         NULL, HFILL }},
4982     { &hf_kerberos_FastOptions_spare_bit4,
4983       { "spare_bit4", "kerberos.FastOptions.spare.bit4",
4984         FT_BOOLEAN, 8, NULL, 0x08,
4985         NULL, HFILL }},
4986     { &hf_kerberos_FastOptions_spare_bit5,
4987       { "spare_bit5", "kerberos.FastOptions.spare.bit5",
4988         FT_BOOLEAN, 8, NULL, 0x04,
4989         NULL, HFILL }},
4990     { &hf_kerberos_FastOptions_spare_bit6,
4991       { "spare_bit6", "kerberos.FastOptions.spare.bit6",
4992         FT_BOOLEAN, 8, NULL, 0x02,
4993         NULL, HFILL }},
4994     { &hf_kerberos_FastOptions_spare_bit7,
4995       { "spare_bit7", "kerberos.FastOptions.spare.bit7",
4996         FT_BOOLEAN, 8, NULL, 0x01,
4997         NULL, HFILL }},
4998     { &hf_kerberos_FastOptions_spare_bit8,
4999       { "spare_bit8", "kerberos.FastOptions.spare.bit8",
5000         FT_BOOLEAN, 8, NULL, 0x80,
5001         NULL, HFILL }},
5002     { &hf_kerberos_FastOptions_spare_bit9,
5003       { "spare_bit9", "kerberos.FastOptions.spare.bit9",
5004         FT_BOOLEAN, 8, NULL, 0x40,
5005         NULL, HFILL }},
5006     { &hf_kerberos_FastOptions_spare_bit10,
5007       { "spare_bit10", "kerberos.FastOptions.spare.bit10",
5008         FT_BOOLEAN, 8, NULL, 0x20,
5009         NULL, HFILL }},
5010     { &hf_kerberos_FastOptions_spare_bit11,
5011       { "spare_bit11", "kerberos.FastOptions.spare.bit11",
5012         FT_BOOLEAN, 8, NULL, 0x10,
5013         NULL, HFILL }},
5014     { &hf_kerberos_FastOptions_spare_bit12,
5015       { "spare_bit12", "kerberos.FastOptions.spare.bit12",
5016         FT_BOOLEAN, 8, NULL, 0x08,
5017         NULL, HFILL }},
5018     { &hf_kerberos_FastOptions_spare_bit13,
5019       { "spare_bit13", "kerberos.FastOptions.spare.bit13",
5020         FT_BOOLEAN, 8, NULL, 0x04,
5021         NULL, HFILL }},
5022     { &hf_kerberos_FastOptions_spare_bit14,
5023       { "spare_bit14", "kerberos.FastOptions.spare.bit14",
5024         FT_BOOLEAN, 8, NULL, 0x02,
5025         NULL, HFILL }},
5026     { &hf_kerberos_FastOptions_spare_bit15,
5027       { "spare_bit15", "kerberos.FastOptions.spare.bit15",
5028         FT_BOOLEAN, 8, NULL, 0x01,
5029         NULL, HFILL }},
5030     { &hf_kerberos_FastOptions_kdc_follow_referrals,
5031       { "kdc-follow-referrals", "kerberos.FastOptions.kdc.follow.referrals",
5032         FT_BOOLEAN, 8, NULL, 0x80,
5033         NULL, HFILL }},
5034     { &hf_kerberos_ticket_checksum,
5035       { "ticket-checksum", "kerberos.ticket_checksum_element",
5036         FT_NONE, BASE_NONE, NULL, 0,
5037         "Checksum", HFILL }},
5038     { &hf_krb_patimestamp,
5039       { "patimestamp", "kerberos.patimestamp",
5040         FT_STRING, BASE_NONE, NULL, 0, "KerberosTime", HFILL }},
5041     { &hf_krb_pausec,
5042       { "pausec", "kerberos.pausec",
5043         FT_UINT32, BASE_DEC, NULL, 0, "Microseconds", HFILL }},
5044 #endif /* HAVE_KERBEROS */
5045 
5046 #include "packet-kerberos-hfarr.c"
5047 	};
5048 
5049 	/* List of subtrees */
5050 	static gint *ett[] = {
5051 		&ett_kerberos,
5052 		&ett_krb_recordmark,
5053 		&ett_krb_pac,
5054 		&ett_krb_pac_drep,
5055 		&ett_krb_pac_midl_blob,
5056 		&ett_krb_pac_logon_info,
5057 		&ett_krb_pac_credential_info,
5058 		&ett_krb_pac_s4u_delegation_info,
5059 		&ett_krb_pac_upn_dns_info,
5060 		&ett_krb_pac_device_info,
5061 		&ett_krb_pac_server_checksum,
5062 		&ett_krb_pac_privsvr_checksum,
5063 		&ett_krb_pac_client_info_type,
5064 		&ett_krb_pac_ticket_checksum,
5065 		&ett_krb_pa_supported_enctypes,
5066 		&ett_krb_ad_ap_options,
5067 		&ett_kerberos_KERB_TICKET_LOGON,
5068 #ifdef HAVE_KERBEROS
5069 		&ett_krb_pa_enc_ts_enc,
5070 	    &ett_kerberos_KrbFastFinished,
5071 	    &ett_kerberos_KrbFastResponse,
5072         &ett_kerberos_KrbFastReq,
5073         &ett_kerberos_FastOptions,
5074 #endif
5075 #include "packet-kerberos-ettarr.c"
5076 	};
5077 
5078 	static ei_register_info ei[] = {
5079 		{ &ei_kerberos_missing_keytype, { "kerberos.missing_keytype", PI_DECRYPTION, PI_WARN, "Missing keytype", EXPFILL }},
5080 		{ &ei_kerberos_decrypted_keytype, { "kerberos.decrypted_keytype", PI_SECURITY, PI_CHAT, "Decrypted keytype", EXPFILL }},
5081 		{ &ei_kerberos_learnt_keytype, { "kerberos.learnt_keytype", PI_SECURITY, PI_CHAT, "Learnt keytype", EXPFILL }},
5082 		{ &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 }},
5083 		{ &ei_krb_gssapi_dlglen, { "kerberos.gssapi.dlglen.error", PI_MALFORMED, PI_ERROR, "DlgLen is not the same as number of bytes remaining", EXPFILL }},
5084 	};
5085 
5086 	expert_module_t* expert_krb;
5087 	module_t *krb_module;
5088 
5089 	proto_kerberos = proto_register_protocol("Kerberos", "KRB5", "kerberos");
5090 	proto_register_field_array(proto_kerberos, hf, array_length(hf));
5091 	proto_register_subtree_array(ett, array_length(ett));
5092 	expert_krb = expert_register_protocol(proto_kerberos);
5093 	expert_register_field_array(expert_krb, ei, array_length(ei));
5094 
5095 	/* Register preferences */
5096 	krb_module = prefs_register_protocol(proto_kerberos, kerberos_prefs_apply_cb);
5097 	prefs_register_bool_preference(krb_module, "desegment",
5098 	"Reassemble Kerberos over TCP messages spanning multiple TCP segments",
5099 	"Whether the Kerberos dissector should reassemble messages spanning multiple TCP segments."
5100 	" To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
5101 	&krb_desegment);
5102 #ifdef HAVE_KERBEROS
5103 	prefs_register_bool_preference(krb_module, "decrypt",
5104 	"Try to decrypt Kerberos blobs",
5105 	"Whether the dissector should try to decrypt "
5106 	"encrypted Kerberos blobs. This requires that the proper "
5107 	"keytab file is installed as well.", &krb_decrypt);
5108 
5109 	prefs_register_filename_preference(krb_module, "file",
5110 				   "Kerberos keytab file",
5111 				   "The keytab file containing all the secrets",
5112 				   &keytab_filename, FALSE);
5113 
5114 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
5115 	wmem_register_callback(wmem_epan_scope(), enc_key_list_cb, NULL);
5116 	kerberos_longterm_keys = wmem_map_new(wmem_epan_scope(),
5117 					      enc_key_content_hash,
5118 					      enc_key_content_equal);
5119 	kerberos_all_keys = wmem_map_new_autoreset(wmem_epan_scope(),
5120 						   wmem_file_scope(),
5121 						   enc_key_content_hash,
5122 						   enc_key_content_equal);
5123 	kerberos_app_session_keys = wmem_map_new_autoreset(wmem_epan_scope(),
5124 							   wmem_file_scope(),
5125 							   enc_key_content_hash,
5126 							   enc_key_content_equal);
5127 #endif /* defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS) */
5128 #endif /* HAVE_KERBEROS */
5129 
5130 }
5131 static int wrap_dissect_gss_kerb(tvbuff_t *tvb, int offset, packet_info *pinfo,
5132 				 proto_tree *tree, dcerpc_info *di _U_,guint8 *drep _U_)
5133 {
5134 	tvbuff_t *auth_tvb;
5135 
5136 	auth_tvb = tvb_new_subset_remaining(tvb, offset);
5137 
5138 	dissect_kerberos_main(auth_tvb, pinfo, tree, FALSE, NULL);
5139 
5140 	return tvb_captured_length_remaining(tvb, offset);
5141 }
5142 
5143 
5144 static dcerpc_auth_subdissector_fns gss_kerb_auth_connect_fns = {
5145 	wrap_dissect_gss_kerb,                      /* Bind */
5146 	wrap_dissect_gss_kerb,                      /* Bind ACK */
5147 	wrap_dissect_gss_kerb,                      /* AUTH3 */
5148 	NULL,                                       /* Request verifier */
5149 	NULL,                                       /* Response verifier */
5150 	NULL,                                       /* Request data */
5151 	NULL                                        /* Response data */
5152 };
5153 
5154 static dcerpc_auth_subdissector_fns gss_kerb_auth_sign_fns = {
5155 	wrap_dissect_gss_kerb,                      /* Bind */
5156 	wrap_dissect_gss_kerb,                      /* Bind ACK */
5157 	wrap_dissect_gss_kerb,                      /* AUTH3 */
5158 	wrap_dissect_gssapi_verf,                   /* Request verifier */
5159 	wrap_dissect_gssapi_verf,                   /* Response verifier */
5160 	NULL,                                       /* Request data */
5161 	NULL                                        /* Response data */
5162 };
5163 
5164 static dcerpc_auth_subdissector_fns gss_kerb_auth_seal_fns = {
5165 	wrap_dissect_gss_kerb,                      /* Bind */
5166 	wrap_dissect_gss_kerb,                      /* Bind ACK */
5167 	wrap_dissect_gss_kerb,                      /* AUTH3 */
5168 	wrap_dissect_gssapi_verf,                   /* Request verifier */
5169 	wrap_dissect_gssapi_verf,                   /* Response verifier */
5170 	wrap_dissect_gssapi_payload,                /* Request data */
5171 	wrap_dissect_gssapi_payload                 /* Response data */
5172 };
5173 
5174 
5175 
5176 void
5177 proto_reg_handoff_kerberos(void)
5178 {
5179 	dissector_handle_t kerberos_handle_tcp;
5180 
5181 	krb4_handle = find_dissector_add_dependency("krb4", proto_kerberos);
5182 
5183 	kerberos_handle_udp = create_dissector_handle(dissect_kerberos_udp,
5184 	proto_kerberos);
5185 
5186 	kerberos_handle_tcp = create_dissector_handle(dissect_kerberos_tcp,
5187 	proto_kerberos);
5188 
5189 	dissector_add_uint_with_preference("udp.port", UDP_PORT_KERBEROS, kerberos_handle_udp);
5190 	dissector_add_uint_with_preference("tcp.port", TCP_PORT_KERBEROS, kerberos_handle_tcp);
5191 
5192 	register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_CONNECT,
5193 									  DCE_C_RPC_AUTHN_PROTOCOL_GSS_KERBEROS,
5194 									  &gss_kerb_auth_connect_fns);
5195 
5196 	register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_INTEGRITY,
5197 									  DCE_C_RPC_AUTHN_PROTOCOL_GSS_KERBEROS,
5198 									  &gss_kerb_auth_sign_fns);
5199 
5200 	register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_PRIVACY,
5201 									  DCE_C_RPC_AUTHN_PROTOCOL_GSS_KERBEROS,
5202 									  &gss_kerb_auth_seal_fns);
5203 }
5204 
5205 /*
5206  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
5207  *
5208  * Local variables:
5209  * c-basic-offset: 8
5210  * tab-width: 8
5211  * indent-tabs-mode: t
5212  * End:
5213  *
5214  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
5215  * :indentSize=8:tabSize=8:noTabs=false:
5216  */
5217