Kerberos: add kerberos_inject_longterm_key() helper function
[wireshark-sm.git] / epan / dissectors / asn1 / kerberos / packet-kerberos-template.c
blob172c2a0ddec3a8b3b4c30ec3fd73a659fc9db0ff
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
8 * Ronnie Sahlberg (C) 2004, major rewrite for new ASN.1/BER API.
9 * decryption of kerberos blobs if keytab is provided
11 * See RFC 1510, and various I-Ds and other documents showing additions,
12 * e.g. ones listed under
14 * http://clifford.neuman.name/krb-revisions/
16 * and
18 * https://tools.ietf.org/html/rfc4120
20 * and
22 * https://tools.ietf.org/html/rfc6806
24 * Some structures from RFC2630
26 * Wireshark - Network traffic analyzer
27 * By Gerald Combs <gerald@wireshark.org>
28 * Copyright 1998 Gerald Combs
30 * SPDX-License-Identifier: GPL-2.0-or-later
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.
43 #include <config.h>
45 #include <stdio.h>
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
56 #include <epan/packet.h>
57 #include <epan/proto_data.h>
58 #include <epan/exceptions.h>
59 #include <epan/strutil.h>
60 #include <epan/conversation.h>
61 #include <epan/expert.h>
62 #include <epan/prefs.h>
63 #include <epan/srt_table.h>
64 #include <epan/tfs.h>
65 #include <wsutil/wsgcrypt.h>
66 #include <wsutil/file_util.h>
67 #include <wsutil/str_util.h>
68 #include <wsutil/pint.h>
69 #include <wsutil/array.h>
70 #include "packet-kerberos.h"
71 #include "packet-netbios.h"
72 #include "packet-tcp.h"
73 #include "packet-ber.h"
74 #include "packet-pkinit.h"
75 #include "packet-cms.h"
76 #include "packet-windows-common.h"
78 #include "read_keytab_file.h"
80 #include "packet-dcerpc-netlogon.h"
81 #include "packet-dcerpc.h"
83 #include "packet-gssapi.h"
84 #include "packet-x509af.h"
86 #define KEY_USAGE_FAST_REQ_CHKSUM 50
87 #define KEY_USAGE_FAST_ENC 51
88 #define KEY_USAGE_FAST_REP 52
89 #define KEY_USAGE_FAST_FINISHED 53
90 #define KEY_USAGE_ENC_CHALLENGE_CLIENT 54
91 #define KEY_USAGE_ENC_CHALLENGE_KDC 55
93 void proto_register_kerberos(void);
94 void proto_reg_handoff_kerberos(void);
96 #define UDP_PORT_KERBEROS 88
97 #define TCP_PORT_KERBEROS 88
99 #define ADDRESS_STR_BUFSIZ 256
101 typedef struct kerberos_key {
102 uint32_t keytype;
103 int keylength;
104 const uint8_t *keyvalue;
105 } kerberos_key_t;
107 typedef void (*kerberos_key_save_fn)(tvbuff_t *tvb _U_, int offset _U_, int length _U_,
108 asn1_ctx_t *actx _U_, proto_tree *tree _U_,
109 int parent_hf_index _U_,
110 int hf_index _U_);
112 typedef struct kerberos_conv_t {
113 wmem_list_t *frames;
114 } kerberos_conv_t;
116 typedef struct kerberos_frame_t {
117 struct kerberos_frame_t *req;
118 uint32_t frame;
119 nstime_t time;
120 uint32_t msg_type;
121 int srt_idx;
122 } kerberos_frame_t;
124 typedef struct {
125 uint32_t msg_type;
126 bool is_win2k_pkinit;
127 uint32_t errorcode;
128 uint32_t etype;
129 uint32_t padata_type;
130 uint32_t is_enc_padata;
131 uint32_t enctype;
132 kerberos_key_t key;
133 proto_tree *key_tree;
134 proto_item *key_hidden_item;
135 tvbuff_t *key_tvb;
136 kerberos_callbacks *callbacks;
137 uint32_t ad_type;
138 uint32_t addr_type;
139 uint32_t checksum_type;
140 #ifdef HAVE_KERBEROS
141 enc_key_t *last_decryption_key;
142 enc_key_t *last_added_key;
143 enc_key_t *current_ticket_key;
144 tvbuff_t *last_ticket_enc_part_tvb;
145 #endif
146 int save_encryption_key_parent_hf_index;
147 kerberos_key_save_fn save_encryption_key_fn;
148 unsigned learnt_key_ids;
149 unsigned missing_key_ids;
150 wmem_list_t *decryption_keys;
151 wmem_list_t *learnt_keys;
152 wmem_list_t *missing_keys;
153 uint32_t within_PA_TGS_REQ;
154 struct _kerberos_PA_FX_FAST_REQUEST {
155 bool defer;
156 tvbuff_t *tvb;
157 proto_tree *tree;
158 } PA_FX_FAST_REQUEST;
159 #ifdef HAVE_KERBEROS
160 enc_key_t *PA_TGS_REQ_key;
161 enc_key_t *PA_TGS_REQ_subkey;
162 #endif
163 uint32_t fast_type;
164 uint32_t fast_armor_within_armor_value;
165 #ifdef HAVE_KERBEROS
166 enc_key_t *PA_FAST_ARMOR_AP_key;
167 enc_key_t *PA_FAST_ARMOR_AP_subkey;
168 enc_key_t *fast_armor_key;
169 enc_key_t *fast_strengthen_key;
170 #endif
171 kerberos_conv_t *krb5_conv;
172 uint32_t frame_req, frame_rep;
173 nstime_t req_time;
174 } kerberos_private_data_t;
176 static dissector_handle_t kerberos_handle_tcp;
177 static dissector_handle_t kerberos_handle_udp;
179 /* Forward declarations */
180 static kerberos_private_data_t *kerberos_get_private_data(asn1_ctx_t *actx);
181 static int dissect_kerberos_Applications(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
182 static int dissect_kerberos_AuthorizationData(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
183 static int dissect_kerberos_PA_ENC_TIMESTAMP(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
184 #ifdef HAVE_KERBEROS
185 static int dissect_kerberos_PA_ENC_TS_ENC(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
186 #endif
187 static int dissect_kerberos_PA_PAC_REQUEST(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
188 static int dissect_kerberos_PA_S4U2Self(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
189 static int dissect_kerberos_PA_S4U_X509_USER(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
190 static int dissect_kerberos_ETYPE_INFO(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
191 static int dissect_kerberos_ETYPE_INFO2(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
192 static int dissect_kerberos_AD_IF_RELEVANT(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
193 static int dissect_kerberos_PA_AUTHENTICATION_SET_ELEM(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
194 static int dissect_kerberos_PA_FX_FAST_REQUEST(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
195 static int dissect_kerberos_EncryptedChallenge(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
196 static int dissect_kerberos_PA_KERB_KEY_LIST_REQ(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
197 static int dissect_kerberos_PA_KERB_KEY_LIST_REP(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
198 static int dissect_kerberos_PA_FX_FAST_REPLY(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
199 static int dissect_kerberos_PA_PAC_OPTIONS(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
200 static int dissect_kerberos_KERB_AD_RESTRICTION_ENTRY(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
201 static int dissect_kerberos_SEQUENCE_OF_ENCTYPE(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
202 static int dissect_kerberos_PA_SPAKE(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
203 static int dissect_kerberos_PA_DATA(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
204 static int dissect_kerberos_T_rEP_SEQUENCE_OF_PA_DATA(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
205 #ifdef HAVE_KERBEROS
206 static int dissect_kerberos_KrbFastReq(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
207 static int dissect_kerberos_KrbFastResponse(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
208 static int dissect_kerberos_FastOptions(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
209 #endif
210 static int dissect_kerberos_KRB5_SRP_PA_ANNOUNCE(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
211 static int dissect_kerberos_KRB5_SRP_PA_INIT(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
212 static int dissect_kerberos_KRB5_SRP_PA_SERVER_CHALLENGE(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
213 static int dissect_kerberos_KRB5_SRP_PA_CLIENT_RESPONSE(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
214 static int dissect_kerberos_KRB5_SRP_PA_SERVER_VERIFIER(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_);
216 /* Desegment Kerberos over TCP messages */
217 static bool krb_desegment = true;
219 static int proto_kerberos;
220 static int kerberos_tap;
222 static int hf_krb_response_to;
223 static int hf_krb_response_in;
224 static int hf_krb_time;
225 static int hf_krb_rm_reserved;
226 static int hf_krb_rm_reclen;
227 static int hf_krb_provsrv_location;
228 static int hf_krb_pw_salt;
229 static int hf_krb_ext_error_nt_status;
230 static int hf_krb_ext_error_reserved;
231 static int hf_krb_ext_error_flags;
232 static int hf_krb_address_ip;
233 static int hf_krb_address_netbios;
234 static int hf_krb_address_ipv6;
235 static int hf_krb_gssapi_len;
236 static int hf_krb_gssapi_bnd;
237 static int hf_krb_gssapi_dlgopt;
238 static int hf_krb_gssapi_dlglen;
239 static int hf_krb_gssapi_c_flag_deleg;
240 static int hf_krb_gssapi_c_flag_mutual;
241 static int hf_krb_gssapi_c_flag_replay;
242 static int hf_krb_gssapi_c_flag_sequence;
243 static int hf_krb_gssapi_c_flag_conf;
244 static int hf_krb_gssapi_c_flag_integ;
245 static int hf_krb_gssapi_c_flag_dce_style;
246 static int hf_krb_midl_version;
247 static int hf_krb_midl_hdr_len;
248 static int hf_krb_midl_fill_bytes;
249 static int hf_krb_midl_blob_len;
250 static int hf_krb_pac_signature_type;
251 static int hf_krb_pac_signature_signature;
252 static int hf_krb_w2k_pac_entries;
253 static int hf_krb_w2k_pac_version;
254 static int hf_krb_w2k_pac_type;
255 static int hf_krb_w2k_pac_size;
256 static int hf_krb_w2k_pac_offset;
257 static int hf_krb_pac_clientid;
258 static int hf_krb_pac_namelen;
259 static int hf_krb_pac_clientname;
260 static int hf_krb_pac_logon_info;
261 static int hf_krb_pac_credential_data;
262 static int hf_krb_pac_credential_info;
263 static int hf_krb_pac_credential_info_version;
264 static int hf_krb_pac_credential_info_etype;
265 static int hf_krb_pac_s4u_delegation_info;
266 static int hf_krb_pac_upn_dns_info;
267 static int hf_krb_pac_upn_flags;
268 static int hf_krb_pac_upn_flag_upn_constructed;
269 static int hf_krb_pac_upn_flag_has_sam_name_and_sid;
270 static int hf_krb_pac_upn_upn_offset;
271 static int hf_krb_pac_upn_upn_len;
272 static int hf_krb_pac_upn_upn_name;
273 static int hf_krb_pac_upn_dns_offset;
274 static int hf_krb_pac_upn_dns_len;
275 static int hf_krb_pac_upn_dns_name;
276 static int hf_krb_pac_upn_samaccountname_offset;
277 static int hf_krb_pac_upn_samaccountname_len;
278 static int hf_krb_pac_upn_samaccountname;
279 static int hf_krb_pac_upn_objectsid_offset;
280 static int hf_krb_pac_upn_objectsid_len;
281 static int hf_krb_pac_server_checksum;
282 static int hf_krb_pac_privsvr_checksum;
283 static int hf_krb_pac_client_info_type;
284 static int hf_krb_pac_client_claims_info;
285 static int hf_krb_pac_device_info;
286 static int hf_krb_pac_device_claims_info;
287 static int hf_krb_pac_ticket_checksum;
288 static int hf_krb_pac_attributes_info;
289 static int hf_krb_pac_attributes_info_length;
290 static int hf_krb_pac_attributes_info_flags;
291 static int hf_krb_pac_attributes_info_flags_pac_was_requested;
292 static int hf_krb_pac_attributes_info_flags_pac_was_given_implicitly;
293 static int hf_krb_pac_requester_sid;
294 static int hf_krb_pac_full_checksum;
295 static int hf_krb_pa_supported_enctypes;
296 static int hf_krb_pa_supported_enctypes_des_cbc_crc;
297 static int hf_krb_pa_supported_enctypes_des_cbc_md5;
298 static int hf_krb_pa_supported_enctypes_rc4_hmac;
299 static int hf_krb_pa_supported_enctypes_aes128_cts_hmac_sha1_96;
300 static int hf_krb_pa_supported_enctypes_aes256_cts_hmac_sha1_96;
301 static int hf_krb_pa_supported_enctypes_aes256_cts_hmac_sha1_96_sk;
302 static int hf_krb_pa_supported_enctypes_fast_supported;
303 static int hf_krb_pa_supported_enctypes_compound_identity_supported;
304 static int hf_krb_pa_supported_enctypes_claims_supported;
305 static int hf_krb_pa_supported_enctypes_resource_sid_compression_disabled;
306 static int hf_krb_ad_ap_options;
307 static int hf_krb_ad_ap_options_cbt;
308 static int hf_krb_ad_ap_options_unverified_target_name;
309 static int hf_krb_ad_target_principal;
310 static int hf_krb_key_hidden_item;
311 static int hf_kerberos_KERB_TICKET_LOGON;
312 static int hf_kerberos_KERB_TICKET_LOGON_MessageType;
313 static int hf_kerberos_KERB_TICKET_LOGON_Flags;
314 static int hf_kerberos_KERB_TICKET_LOGON_ServiceTicketLength;
315 static int hf_kerberos_KERB_TICKET_LOGON_TicketGrantingTicketLength;
316 static int hf_kerberos_KERB_TICKET_LOGON_ServiceTicket;
317 static int hf_kerberos_KERB_TICKET_LOGON_TicketGrantingTicket;
318 static int hf_kerberos_KERB_TICKET_LOGON_FLAG_ALLOW_EXPIRED_TICKET;
319 static int hf_kerberos_KERB_TICKET_LOGON_FLAG_REDIRECTED;
320 #ifdef HAVE_KERBEROS
321 static int hf_kerberos_KrbFastResponse;
322 static int hf_kerberos_strengthen_key;
323 static int hf_kerberos_finished;
324 static int hf_kerberos_fast_options;
325 static int hf_kerberos_ticket_checksum;
326 static int hf_krb_patimestamp;
327 static int hf_krb_pausec;
328 static int hf_kerberos_FastOptions_reserved;
329 static int hf_kerberos_FastOptions_hide_client_names;
330 static int hf_kerberos_FastOptions_spare_bit2;
331 static int hf_kerberos_FastOptions_spare_bit3;
332 static int hf_kerberos_FastOptions_spare_bit4;
333 static int hf_kerberos_FastOptions_spare_bit5;
334 static int hf_kerberos_FastOptions_spare_bit6;
335 static int hf_kerberos_FastOptions_spare_bit7;
336 static int hf_kerberos_FastOptions_spare_bit8;
337 static int hf_kerberos_FastOptions_spare_bit9;
338 static int hf_kerberos_FastOptions_spare_bit10;
339 static int hf_kerberos_FastOptions_spare_bit11;
340 static int hf_kerberos_FastOptions_spare_bit12;
341 static int hf_kerberos_FastOptions_spare_bit13;
342 static int hf_kerberos_FastOptions_spare_bit14;
343 static int hf_kerberos_FastOptions_spare_bit15;
344 static int hf_kerberos_FastOptions_kdc_follow_referrals;
346 #endif
347 #include "packet-kerberos-hf.c"
349 /* Initialize the subtree pointers */
350 static int ett_kerberos;
351 static int ett_krb_recordmark;
352 static int ett_krb_pac;
353 static int ett_krb_pac_drep;
354 static int ett_krb_pac_midl_blob;
355 static int ett_krb_pac_logon_info;
356 static int ett_krb_pac_credential_info;
357 static int ett_krb_pac_s4u_delegation_info;
358 static int ett_krb_pac_upn_dns_info;
359 static int ett_krb_pac_upn_dns_info_flags;
360 static int ett_krb_pac_device_info;
361 static int ett_krb_pac_server_checksum;
362 static int ett_krb_pac_privsvr_checksum;
363 static int ett_krb_pac_client_info_type;
364 static int ett_krb_pac_ticket_checksum;
365 static int ett_krb_pac_attributes_info;
366 static int ett_krb_pac_attributes_info_flags;
367 static int ett_krb_pac_requester_sid;
368 static int ett_krb_pac_full_checksum;
369 static int ett_krb_pa_supported_enctypes;
370 static int ett_krb_ad_ap_options;
371 static int ett_kerberos_KERB_TICKET_LOGON;
372 #ifdef HAVE_KERBEROS
373 static int ett_krb_pa_enc_ts_enc;
374 static int ett_kerberos_KrbFastFinished;
375 static int ett_kerberos_KrbFastResponse;
376 static int ett_kerberos_KrbFastReq;
377 static int ett_kerberos_FastOptions;
378 #endif
379 #include "packet-kerberos-ett.c"
381 static expert_field ei_kerberos_missing_keytype;
382 static expert_field ei_kerberos_decrypted_keytype;
383 static expert_field ei_kerberos_learnt_keytype;
384 static expert_field ei_kerberos_address;
385 static expert_field ei_krb_gssapi_dlglen;
387 static dissector_handle_t krb4_handle;
389 /* Global variables */
390 static uint32_t gbl_keytype;
391 static bool gbl_do_col_info;
393 #include "packet-kerberos-val.h"
395 static void
396 call_kerberos_callbacks(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int tag, kerberos_callbacks *cb)
398 if(!cb){
399 return;
402 while(cb->tag){
403 if(cb->tag==tag){
404 cb->callback(pinfo, tvb, tree);
405 return;
407 cb++;
409 return;
412 static int
413 krb5_frame_compare(gconstpointer a, gconstpointer b)
415 kerberos_frame_t *fa = (kerberos_frame_t *)a;
416 kerberos_frame_t *fb = (kerberos_frame_t *)b;
418 return fa->frame - fb->frame;
421 static kerberos_conv_t *krb5_conv_find_or_create(packet_info *pinfo)
423 conversation_t *conversation = NULL;
424 kerberos_conv_t *kconv = NULL;
426 conversation = find_or_create_conversation(pinfo);
427 kconv = (kerberos_conv_t *)conversation_get_proto_data(conversation,
428 proto_kerberos);
429 if (kconv == NULL) {
430 kconv = wmem_new0(wmem_file_scope(), kerberos_conv_t);
431 kconv->frames = wmem_list_new(wmem_file_scope());
433 conversation_add_proto_data(conversation, proto_kerberos, kconv);
436 return kconv;
439 static void krb5_conf_add_request(asn1_ctx_t *actx)
441 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
442 packet_info *pinfo = actx->pinfo;
443 kerberos_frame_t _krqf = { .frame = 0, };
444 kerberos_frame_t *krqf = NULL;
445 wmem_list_frame_t *wf = NULL;
446 kerberos_frame_t *krpf = NULL;
448 if (private_data->krb5_conv == NULL)
449 return;
451 if (!pinfo->fd->visited) {
452 krqf = wmem_new0(wmem_file_scope(), kerberos_frame_t);
453 if (krqf == NULL) {
454 return;
456 } else {
457 krqf = &_krqf;
460 krqf->frame = pinfo->num;
461 krqf->time = pinfo->abs_ts;
462 krqf->msg_type = private_data->msg_type;
463 krqf->srt_idx = -1;
465 if (!pinfo->fd->visited) {
466 wmem_list_insert_sorted(private_data->krb5_conv->frames,
467 krqf, krb5_frame_compare);
470 wf = wmem_list_find_custom(private_data->krb5_conv->frames,
471 krqf, krb5_frame_compare);
472 if (wf != NULL) {
473 /* The next one should be the response */
474 wf = wmem_list_frame_next(wf);
476 if (wf == NULL) {
477 return;
479 krpf = (kerberos_frame_t *)wmem_list_frame_data(wf);
481 switch (krpf->msg_type) {
482 case KERBEROS_APPLICATIONS_AS_REP:
483 case KERBEROS_APPLICATIONS_TGS_REP:
484 case KERBEROS_APPLICATIONS_KRB_ERROR:
485 break;
486 default:
487 return;
490 private_data->frame_rep = krpf->frame;
493 static void krb5_conf_add_response(asn1_ctx_t *actx)
495 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
496 packet_info *pinfo = actx->pinfo;
497 kerberos_frame_t _krpf = { .frame = 0, };
498 kerberos_frame_t *krpf = NULL;
499 wmem_list_frame_t *wf = NULL;
500 kerberos_frame_t *krqf = NULL;
502 if (private_data->krb5_conv == NULL)
503 return;
505 if (!pinfo->fd->visited) {
506 krpf = wmem_new0(wmem_file_scope(), kerberos_frame_t);
507 if (krpf == NULL) {
508 return;
510 } else {
511 krpf = &_krpf;
514 krpf->frame = pinfo->num;
515 krpf->time = pinfo->abs_ts;
516 krpf->msg_type = private_data->msg_type;
517 krpf->srt_idx = -1;
519 if (!pinfo->fd->visited) {
520 wmem_list_insert_sorted(private_data->krb5_conv->frames,
521 krpf, krb5_frame_compare);
524 wf = wmem_list_find_custom(private_data->krb5_conv->frames,
525 krpf, krb5_frame_compare);
526 if (wf != NULL) {
528 * replace the pointer with the one allocated on
529 * wmem_file_scope()
531 krpf = (kerberos_frame_t *)wmem_list_frame_data(wf);
532 /* The previous one should be the request */
533 wf = wmem_list_frame_prev(wf);
535 if (wf == NULL) {
536 return;
538 krqf = (kerberos_frame_t *)wmem_list_frame_data(wf);
539 krpf->req = krqf;
541 switch (krqf->msg_type) {
542 case KERBEROS_APPLICATIONS_AS_REQ:
543 if (private_data->msg_type == KERBEROS_APPLICATIONS_AS_REP) {
544 krpf->srt_idx = 0;
545 break;
547 if (private_data->msg_type == KERBEROS_APPLICATIONS_KRB_ERROR) {
548 krpf->srt_idx = 1;
549 break;
551 return;
552 case KERBEROS_APPLICATIONS_TGS_REQ:
553 if (private_data->msg_type == KERBEROS_APPLICATIONS_TGS_REP) {
554 krpf->srt_idx = 2;
555 break;
557 if (private_data->msg_type == KERBEROS_APPLICATIONS_KRB_ERROR) {
558 krpf->srt_idx = 3;
559 break;
561 return;
562 default:
563 return;
566 private_data->frame_req = krqf->frame;
567 private_data->req_time = krqf->time;
569 tap_queue_packet(kerberos_tap, pinfo, krpf);
572 static void
573 krb5stat_init(struct register_srt* srt _U_, GArray* srt_array _U_)
575 srt_stat_table *krb5_srt_table = NULL;
577 krb5_srt_table = init_srt_table("Kerberos", "krb5", srt_array, 4, NULL, "kerberos.msg_type", NULL);
578 init_srt_table_row(krb5_srt_table, 0, "AS-REP");
579 init_srt_table_row(krb5_srt_table, 1, "AS-ERROR");
580 init_srt_table_row(krb5_srt_table, 2, "TGS-REP");
581 init_srt_table_row(krb5_srt_table, 3, "TGS-ERROR");
584 static tap_packet_status
585 krb5stat_packet(void *pss _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prv, tap_flags_t flags _U_)
587 srt_stat_table *krb5_srt_table = NULL;
588 srt_data_t *data = (srt_data_t *)pss;
589 kerberos_frame_t *krpf = (kerberos_frame_t *)prv;
591 if (krpf == NULL)
592 return TAP_PACKET_DONT_REDRAW;
594 if (krpf->req == NULL)
595 return TAP_PACKET_DONT_REDRAW;
597 krb5_srt_table = g_array_index(data->srt_array, srt_stat_table*, 0);
598 add_srt_table_data(krb5_srt_table, krpf->srt_idx, &krpf->req->time, pinfo);
599 return TAP_PACKET_REDRAW;
602 static kerberos_private_data_t*
603 kerberos_new_private_data(packet_info *pinfo)
605 kerberos_private_data_t *p;
606 void *existing;
608 p = wmem_new0(pinfo->pool, kerberos_private_data_t);
609 if (p == NULL) {
610 return NULL;
612 p->frame_req = UINT32_MAX;
613 p->frame_rep = UINT32_MAX;
615 p->decryption_keys = wmem_list_new(pinfo->pool);
616 p->learnt_keys = wmem_list_new(pinfo->pool);
617 p->missing_keys = wmem_list_new(pinfo->pool);
619 existing = p_get_proto_data(pinfo->pool, pinfo, proto_kerberos, 0);
620 if (existing != NULL) {
622 * We only remember the first one.
624 return p;
627 p_add_proto_data(pinfo->pool, pinfo, proto_kerberos, 0, p);
628 p->krb5_conv = krb5_conv_find_or_create(pinfo);
629 return p;
632 static kerberos_private_data_t*
633 kerberos_get_private_data(asn1_ctx_t *actx)
635 if (!actx->private_data) {
636 actx->private_data = kerberos_new_private_data(actx->pinfo);
638 return (kerberos_private_data_t *)(actx->private_data);
641 static bool
642 kerberos_private_is_kdc_req(kerberos_private_data_t *private_data)
644 switch (private_data->msg_type) {
645 case KERBEROS_APPLICATIONS_AS_REQ:
646 case KERBEROS_APPLICATIONS_TGS_REQ:
647 return true;
650 return false;
653 bool
654 kerberos_is_win2k_pkinit(asn1_ctx_t *actx)
656 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
658 return private_data->is_win2k_pkinit;
661 static int dissect_kerberos_defer_PA_FX_FAST_REQUEST(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_)
663 kerberos_private_data_t* private_data = kerberos_get_private_data(actx);
666 * dissect_ber_octet_string_wcb() always passes
667 * implicit_tag=false, offset=0 and hf_index=-1
669 * It means we only need to remember tvb and tree
670 * in order to replay dissect_kerberos_PA_FX_FAST_REQUEST()
671 * in dissect_kerberos_T_rEQ_SEQUENCE_OF_PA_DATA()
673 ws_assert(implicit_tag == false);
674 ws_assert(offset == 0);
675 ws_assert(hf_index <= 0);
677 if (private_data->PA_FX_FAST_REQUEST.defer) {
679 * Remember the tvb (and the optional tree)
681 private_data->PA_FX_FAST_REQUEST.tvb = tvb;
682 private_data->PA_FX_FAST_REQUEST.tree = tree;
684 * only handle the first PA_FX_FAST_REQUEST...
686 private_data->PA_FX_FAST_REQUEST.defer = false;
687 return tvb_reported_length_remaining(tvb, offset);
690 return dissect_kerberos_PA_FX_FAST_REQUEST(implicit_tag, tvb, offset, actx, tree, hf_index);
693 #ifdef HAVE_KERBEROS
695 /* Decrypt Kerberos blobs */
696 bool krb_decrypt;
698 /* keytab filename */
699 static const char *keytab_filename = "";
701 void
702 read_keytab_file_from_preferences(void)
704 static char *last_keytab = NULL;
706 if (!krb_decrypt) {
707 return;
710 if (keytab_filename == NULL) {
711 return;
714 if (last_keytab && !strcmp(last_keytab, keytab_filename)) {
715 return;
718 g_free(last_keytab);
719 last_keytab = g_strdup(keytab_filename);
721 read_keytab_file(last_keytab);
723 #endif /* HAVE_KERBEROS */
725 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
726 enc_key_t *enc_key_list=NULL;
727 static unsigned kerberos_longterm_ids;
728 wmem_map_t *kerberos_longterm_keys;
729 static wmem_map_t *kerberos_all_keys;
730 static wmem_map_t *kerberos_app_session_keys;
732 static bool
733 enc_key_list_cb(wmem_allocator_t* allocator _U_, wmem_cb_event_t event _U_, void *user_data _U_)
735 enc_key_list = NULL;
736 kerberos_longterm_ids = 0;
737 /* keep the callback registered */
738 return true;
741 static int enc_key_cmp_id(const void *k1, const void *k2)
743 const enc_key_t *key1 = (const enc_key_t *)k1;
744 const enc_key_t *key2 = (const enc_key_t *)k2;
746 if (key1->fd_num < key2->fd_num) {
747 return -1;
749 if (key1->fd_num > key2->fd_num) {
750 return 1;
753 if (key1->id < key2->id) {
754 return -1;
756 if (key1->id > key2->id) {
757 return 1;
760 return 0;
763 static gboolean
764 enc_key_content_equal(const void *k1, const void *k2)
766 const enc_key_t *key1 = (const enc_key_t *)k1;
767 const enc_key_t *key2 = (const enc_key_t *)k2;
768 int cmp;
770 if (key1->keytype != key2->keytype) {
771 return false;
774 if (key1->keylength != key2->keylength) {
775 return false;
778 cmp = memcmp(key1->keyvalue, key2->keyvalue, key1->keylength);
779 if (cmp != 0) {
780 return false;
783 return true;
786 static unsigned
787 enc_key_content_hash(const void *k)
789 const enc_key_t *key = (const enc_key_t *)k;
790 unsigned ret = 0;
792 ret += wmem_strong_hash((const uint8_t *)&key->keytype,
793 sizeof(key->keytype));
794 ret += wmem_strong_hash((const uint8_t *)&key->keylength,
795 sizeof(key->keylength));
796 ret += wmem_strong_hash((const uint8_t *)key->keyvalue,
797 key->keylength);
799 return ret;
802 static void
803 kerberos_key_map_insert(wmem_map_t *key_map, enc_key_t *new_key)
805 enc_key_t *existing = NULL;
806 enc_key_t *cur = NULL;
807 int cmp;
809 existing = (enc_key_t *)wmem_map_lookup(key_map, new_key);
810 if (existing == NULL) {
811 wmem_map_insert(key_map, new_key, new_key);
812 return;
815 if (key_map != kerberos_all_keys) {
817 * It should already be linked to the existing key...
819 return;
822 if (existing->fd_num == -1 && new_key->fd_num != -1) {
824 * We can't reference a learnt key
825 * from a longterm key. As they have
826 * a shorter lifetime.
828 * So just let the learnt key remember the
829 * match.
831 new_key->same_list = existing;
832 new_key->num_same = existing->num_same + 1;
833 return;
837 * If a key with the same content (keytype,keylength,keyvalue)
838 * already exists, we want the earliest key to be
839 * in the list.
841 cmp = enc_key_cmp_id(new_key, existing);
842 if (cmp == 0) {
844 * It's the same, nothing to do...
846 return;
848 if (cmp < 0) {
849 /* The new key has should be added to the list. */
850 new_key->same_list = existing;
851 new_key->num_same = existing->num_same + 1;
852 wmem_map_insert(key_map, new_key, new_key);
853 return;
857 * We want to link the new_key to the existing one.
859 * But we want keep the list sorted, so we need to forward
860 * to the correct spot.
862 for (cur = existing; cur->same_list != NULL; cur = cur->same_list) {
863 cmp = enc_key_cmp_id(new_key, cur->same_list);
864 if (cmp == 0) {
866 * It's the same, nothing to do...
868 return;
871 if (cmp < 0) {
873 * We found the correct spot,
874 * the new_key should added
875 * between existing and existing->same_list
877 new_key->same_list = cur->same_list;
878 new_key->num_same = cur->num_same;
879 break;
884 * finally link new_key to existing
885 * and fix up the numbers
887 cur->same_list = new_key;
888 for (cur = existing; cur != new_key; cur = cur->same_list) {
889 cur->num_same += 1;
892 return;
895 struct insert_longterm_keys_into_key_map_state {
896 wmem_map_t *key_map;
899 static void insert_longterm_keys_into_key_map_cb(void *__key _U_,
900 void *value,
901 void *user_data)
903 struct insert_longterm_keys_into_key_map_state *state =
904 (struct insert_longterm_keys_into_key_map_state *)user_data;
905 enc_key_t *key = (enc_key_t *)value;
907 kerberos_key_map_insert(state->key_map, key);
910 static void insert_longterm_keys_into_key_map(wmem_map_t *key_map)
913 * Because the kerberos_longterm_keys are allocated on
914 * wmem_epan_scope() and kerberos_all_keys are allocated
915 * on wmem_file_scope(), we need to plug the longterm keys
916 * back to kerberos_all_keys if a new file was loaded
917 * and wmem_file_scope() got cleared.
919 if (wmem_map_size(key_map) < wmem_map_size(kerberos_longterm_keys)) {
920 struct insert_longterm_keys_into_key_map_state state = {
921 .key_map = key_map,
924 * Reference all longterm keys into kerberos_all_keys
926 wmem_map_foreach(kerberos_longterm_keys,
927 insert_longterm_keys_into_key_map_cb,
928 &state);
932 static void
933 kerberos_key_list_append(wmem_list_t *key_list, enc_key_t *new_key)
935 enc_key_t *existing = NULL;
937 existing = (enc_key_t *)wmem_list_find(key_list, new_key);
938 if (existing != NULL) {
939 return;
942 wmem_list_append(key_list, new_key);
945 void
946 kerberos_inject_longterm_key(packet_info *pinfo,
947 proto_tree *key_tree,
948 proto_item *key_hidden_item,
949 tvbuff_t *key_tvb,
950 int keytype, int keylength, const uint8_t *keyvalue,
951 const char *origin)
953 wmem_allocator_t *key_scope = NULL;
954 enc_key_t *new_key = NULL;
955 const char *methodl = "learnt";
956 const char *methodu = "Learnt";
957 proto_item *item = NULL;
959 if(pinfo->fd->visited){
961 * We already processed this,
962 * we can use a shortterm scope
964 key_scope = pinfo->pool;
965 } else {
967 * As long as we have enc_key_list, we need to
968 * use wmem_epan_scope(), when that's gone
969 * we can dynamically select the scope based on
970 * how long we'll need the particular key.
972 key_scope = wmem_epan_scope();
975 new_key = wmem_new0(key_scope, enc_key_t);
976 snprintf(new_key->key_origin, KRB_MAX_ORIG_LEN, "%s %s in frame %u",
977 methodl, origin, pinfo->num);
978 new_key->fd_num = -1; /* indication for longterm key for FAST */
979 new_key->id = ++kerberos_longterm_ids;
980 snprintf(new_key->id_str, KRB_MAX_ID_STR_LEN, "learnt.%d.%u",
981 pinfo->num, new_key->id);
982 new_key->keytype=keytype;
983 new_key->keylength=keylength;
984 memcpy(new_key->keyvalue, keyvalue, MIN(keylength, KRB_MAX_KEY_LENGTH));
986 if(!pinfo->fd->visited){
988 * Only keep it if we don't processed it before.
990 new_key->next=enc_key_list;
991 enc_key_list=new_key;
992 kerberos_key_map_insert(kerberos_longterm_keys, new_key);
993 insert_longterm_keys_into_key_map(kerberos_all_keys);
994 kerberos_key_map_insert(kerberos_all_keys, new_key);
997 item = proto_tree_add_expert_format(key_tree, pinfo, &ei_kerberos_learnt_keytype,
998 key_tvb, 0, keylength,
999 "%s %s keytype %d (id=%s) (%02x%02x%02x%02x...)",
1000 methodu, origin, keytype, new_key->id_str,
1001 keyvalue[0] & 0xFF, keyvalue[1] & 0xFF,
1002 keyvalue[2] & 0xFF, keyvalue[3] & 0xFF);
1003 if (item != NULL && key_hidden_item != NULL) {
1004 proto_tree_move_item(key_tree, key_hidden_item, item);
1008 static void
1009 add_encryption_key(packet_info *pinfo,
1010 kerberos_private_data_t *private_data,
1011 proto_tree *key_tree,
1012 proto_item *key_hidden_item,
1013 tvbuff_t *key_tvb,
1014 int keytype, int keylength, const char *keyvalue,
1015 const char *origin,
1016 enc_key_t *src1, enc_key_t *src2)
1018 wmem_allocator_t *key_scope = NULL;
1019 enc_key_t *new_key = NULL;
1020 const char *methodl = "learnt";
1021 const char *methodu = "Learnt";
1022 proto_item *item = NULL;
1024 private_data->last_added_key = NULL;
1026 if (src1 != NULL && src2 != NULL) {
1027 methodl = "derived";
1028 methodu = "Derived";
1031 if(pinfo->fd->visited){
1033 * We already processed this,
1034 * we can use a shortterm scope
1036 key_scope = pinfo->pool;
1037 } else {
1039 * As long as we have enc_key_list, we need to
1040 * use wmem_epan_scope(), when that's gone
1041 * we can dynamically select the scope based on
1042 * how long we'll need the particular key.
1044 key_scope = wmem_epan_scope();
1047 new_key = wmem_new0(key_scope, enc_key_t);
1048 snprintf(new_key->key_origin, KRB_MAX_ORIG_LEN, "%s %s in frame %u",
1049 methodl, origin, pinfo->num);
1050 new_key->fd_num = pinfo->num;
1051 new_key->id = ++private_data->learnt_key_ids;
1052 snprintf(new_key->id_str, KRB_MAX_ID_STR_LEN, "%d.%u",
1053 new_key->fd_num, new_key->id);
1054 new_key->keytype=keytype;
1055 new_key->keylength=keylength;
1056 memcpy(new_key->keyvalue, keyvalue, MIN(keylength, KRB_MAX_KEY_LENGTH));
1057 new_key->src1 = src1;
1058 new_key->src2 = src2;
1060 if(!pinfo->fd->visited){
1062 * Only keep it if we don't processed it before.
1064 new_key->next=enc_key_list;
1065 enc_key_list=new_key;
1066 insert_longterm_keys_into_key_map(kerberos_all_keys);
1067 kerberos_key_map_insert(kerberos_all_keys, new_key);
1070 item = proto_tree_add_expert_format(key_tree, pinfo, &ei_kerberos_learnt_keytype,
1071 key_tvb, 0, keylength,
1072 "%s %s keytype %d (id=%d.%u) (%02x%02x%02x%02x...)",
1073 methodu, origin, keytype, pinfo->num, new_key->id,
1074 keyvalue[0] & 0xFF, keyvalue[1] & 0xFF,
1075 keyvalue[2] & 0xFF, keyvalue[3] & 0xFF);
1076 if (item != NULL && key_hidden_item != NULL) {
1077 proto_tree_move_item(key_tree, key_hidden_item, item);
1079 if (src1 != NULL) {
1080 enc_key_t *sek = src1;
1081 expert_add_info_format(pinfo, item, &ei_kerberos_learnt_keytype,
1082 "SRC1 %s keytype %d (id=%s same=%u) (%02x%02x%02x%02x...)",
1083 sek->key_origin, sek->keytype,
1084 sek->id_str, sek->num_same,
1085 sek->keyvalue[0] & 0xFF, sek->keyvalue[1] & 0xFF,
1086 sek->keyvalue[2] & 0xFF, sek->keyvalue[3] & 0xFF);
1088 if (src2 != NULL) {
1089 enc_key_t *sek = src2;
1090 expert_add_info_format(pinfo, item, &ei_kerberos_learnt_keytype,
1091 "SRC2 %s keytype %d (id=%s same=%u) (%02x%02x%02x%02x...)",
1092 sek->key_origin, sek->keytype,
1093 sek->id_str, sek->num_same,
1094 sek->keyvalue[0] & 0xFF, sek->keyvalue[1] & 0xFF,
1095 sek->keyvalue[2] & 0xFF, sek->keyvalue[3] & 0xFF);
1098 kerberos_key_list_append(private_data->learnt_keys, new_key);
1099 private_data->last_added_key = new_key;
1102 static void
1103 save_encryption_key(tvbuff_t *tvb _U_, int offset _U_, int length _U_,
1104 asn1_ctx_t *actx _U_, proto_tree *tree _U_,
1105 int parent_hf_index _U_,
1106 int hf_index _U_)
1108 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
1109 const char *parent = proto_registrar_get_name(parent_hf_index);
1110 const char *element = proto_registrar_get_name(hf_index);
1111 char origin[KRB_MAX_ORIG_LEN] = { 0, };
1113 snprintf(origin, KRB_MAX_ORIG_LEN, "%s_%s", parent, element);
1115 add_encryption_key(actx->pinfo,
1116 private_data,
1117 private_data->key_tree,
1118 private_data->key_hidden_item,
1119 private_data->key_tvb,
1120 private_data->key.keytype,
1121 private_data->key.keylength,
1122 private_data->key.keyvalue,
1123 origin,
1124 NULL,
1125 NULL);
1128 static void
1129 save_Authenticator_subkey(tvbuff_t *tvb, int offset, int length,
1130 asn1_ctx_t *actx, proto_tree *tree,
1131 int parent_hf_index,
1132 int hf_index)
1134 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
1136 save_encryption_key(tvb, offset, length, actx, tree, parent_hf_index, hf_index);
1138 if (private_data->last_decryption_key == NULL) {
1139 return;
1141 if (private_data->last_added_key == NULL) {
1142 return;
1145 if (private_data->within_PA_TGS_REQ != 0) {
1146 private_data->PA_TGS_REQ_key = private_data->last_decryption_key;
1147 private_data->PA_TGS_REQ_subkey = private_data->last_added_key;
1149 if (private_data->fast_armor_within_armor_value != 0) {
1150 private_data->PA_FAST_ARMOR_AP_key = private_data->last_decryption_key;
1151 private_data->PA_FAST_ARMOR_AP_subkey = private_data->last_added_key;
1155 static void
1156 save_EncAPRepPart_subkey(tvbuff_t *tvb, int offset, int length,
1157 asn1_ctx_t *actx, proto_tree *tree,
1158 int parent_hf_index,
1159 int hf_index)
1161 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
1163 save_encryption_key(tvb, offset, length, actx, tree, parent_hf_index, hf_index);
1165 if (actx->pinfo->fd->visited) {
1166 return;
1169 if (private_data->last_added_key == NULL) {
1170 return;
1173 private_data->last_added_key->is_ap_rep_key = true;
1175 if (private_data->last_decryption_key != NULL &&
1176 private_data->last_decryption_key->is_ticket_key)
1178 enc_key_t *ak = private_data->last_added_key;
1179 enc_key_t *tk = private_data->last_decryption_key;
1182 * The enc_key_t structures and their strings
1183 * in pac_names are all allocated on wmem_epan_scope(),
1184 * so we don't need to copy the content.
1186 ak->pac_names = tk->pac_names;
1189 kerberos_key_map_insert(kerberos_app_session_keys, private_data->last_added_key);
1192 static void
1193 save_EncKDCRepPart_key(tvbuff_t *tvb, int offset, int length,
1194 asn1_ctx_t *actx, proto_tree *tree,
1195 int parent_hf_index,
1196 int hf_index)
1198 save_encryption_key(tvb, offset, length, actx, tree, parent_hf_index, hf_index);
1201 static void
1202 save_EncTicketPart_key(tvbuff_t *tvb, int offset, int length,
1203 asn1_ctx_t *actx, proto_tree *tree,
1204 int parent_hf_index,
1205 int hf_index)
1207 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
1209 save_encryption_key(tvb, offset, length, actx, tree, parent_hf_index, hf_index);
1211 if (actx->pinfo->fd->visited) {
1212 return;
1215 if (private_data->last_added_key == NULL) {
1216 return;
1219 private_data->current_ticket_key = private_data->last_added_key;
1220 private_data->current_ticket_key->is_ticket_key = true;
1223 static void
1224 save_KrbCredInfo_key(tvbuff_t *tvb, int offset, int length,
1225 asn1_ctx_t *actx, proto_tree *tree,
1226 int parent_hf_index,
1227 int hf_index)
1229 save_encryption_key(tvb, offset, length, actx, tree, parent_hf_index, hf_index);
1232 static void
1233 save_KrbFastResponse_strengthen_key(tvbuff_t *tvb, int offset, int length,
1234 asn1_ctx_t *actx, proto_tree *tree,
1235 int parent_hf_index,
1236 int hf_index)
1238 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
1240 save_encryption_key(tvb, offset, length, actx, tree, parent_hf_index, hf_index);
1242 private_data->fast_strengthen_key = private_data->last_added_key;
1245 static void used_encryption_key(proto_tree *tree, packet_info *pinfo,
1246 kerberos_private_data_t *private_data,
1247 enc_key_t *ek, int usage, tvbuff_t *cryptotvb,
1248 const char *keymap_name,
1249 unsigned keymap_size,
1250 unsigned decryption_count)
1252 proto_item *item = NULL;
1253 enc_key_t *sek = NULL;
1255 item = proto_tree_add_expert_format(tree, pinfo, &ei_kerberos_decrypted_keytype,
1256 cryptotvb, 0, 0,
1257 "Decrypted keytype %d usage %d "
1258 "using %s (id=%s same=%u) (%02x%02x%02x%02x...)",
1259 ek->keytype, usage, ek->key_origin, ek->id_str, ek->num_same,
1260 ek->keyvalue[0] & 0xFF, ek->keyvalue[1] & 0xFF,
1261 ek->keyvalue[2] & 0xFF, ek->keyvalue[3] & 0xFF);
1262 expert_add_info_format(pinfo, item, &ei_kerberos_decrypted_keytype,
1263 "Used keymap=%s num_keys=%u num_tries=%u)",
1264 keymap_name,
1265 keymap_size,
1266 decryption_count);
1267 if (ek->src1 != NULL) {
1268 sek = ek->src1;
1269 expert_add_info_format(pinfo, item, &ei_kerberos_decrypted_keytype,
1270 "SRC1 %s keytype %d (id=%s same=%u) (%02x%02x%02x%02x...)",
1271 sek->key_origin, sek->keytype,
1272 sek->id_str, sek->num_same,
1273 sek->keyvalue[0] & 0xFF, sek->keyvalue[1] & 0xFF,
1274 sek->keyvalue[2] & 0xFF, sek->keyvalue[3] & 0xFF);
1276 if (ek->src2 != NULL) {
1277 sek = ek->src2;
1278 expert_add_info_format(pinfo, item, &ei_kerberos_decrypted_keytype,
1279 "SRC2 %s keytype %d (id=%s same=%u) (%02x%02x%02x%02x...)",
1280 sek->key_origin, sek->keytype,
1281 sek->id_str, sek->num_same,
1282 sek->keyvalue[0] & 0xFF, sek->keyvalue[1] & 0xFF,
1283 sek->keyvalue[2] & 0xFF, sek->keyvalue[3] & 0xFF);
1285 sek = ek->same_list;
1286 while (sek != NULL) {
1287 expert_add_info_format(pinfo, item, &ei_kerberos_decrypted_keytype,
1288 "Decrypted keytype %d usage %d "
1289 "using %s (id=%s same=%u) (%02x%02x%02x%02x...)",
1290 sek->keytype, usage, sek->key_origin, sek->id_str, sek->num_same,
1291 sek->keyvalue[0] & 0xFF, sek->keyvalue[1] & 0xFF,
1292 sek->keyvalue[2] & 0xFF, sek->keyvalue[3] & 0xFF);
1293 sek = sek->same_list;
1295 kerberos_key_list_append(private_data->decryption_keys, ek);
1296 private_data->last_decryption_key = ek;
1298 #endif /* HAVE_HEIMDAL_KERBEROS || HAVE_MIT_KERBEROS */
1300 #ifdef HAVE_MIT_KERBEROS
1302 static void missing_encryption_key(proto_tree *tree, packet_info *pinfo,
1303 kerberos_private_data_t *private_data,
1304 int keytype, int usage, tvbuff_t *cryptotvb,
1305 const char *keymap_name,
1306 unsigned keymap_size,
1307 unsigned decryption_count)
1309 proto_item *item = NULL;
1310 enc_key_t *mek = NULL;
1312 mek = wmem_new0(pinfo->pool, enc_key_t);
1313 snprintf(mek->key_origin, KRB_MAX_ORIG_LEN,
1314 "keytype %d usage %d missing in frame %u",
1315 keytype, usage, pinfo->num);
1316 mek->fd_num = pinfo->num;
1317 mek->id = ++private_data->missing_key_ids;
1318 snprintf(mek->id_str, KRB_MAX_ID_STR_LEN, "missing.%u",
1319 mek->id);
1320 mek->keytype=keytype;
1322 item = proto_tree_add_expert_format(tree, pinfo, &ei_kerberos_missing_keytype,
1323 cryptotvb, 0, 0,
1324 "Missing keytype %d usage %d (id=%s)",
1325 keytype, usage, mek->id_str);
1326 expert_add_info_format(pinfo, item, &ei_kerberos_missing_keytype,
1327 "Used keymap=%s num_keys=%u num_tries=%u)",
1328 keymap_name,
1329 keymap_size,
1330 decryption_count);
1332 kerberos_key_list_append(private_data->missing_keys, mek);
1335 #ifdef HAVE_KRB5_PAC_VERIFY
1336 static void used_signing_key(proto_tree *tree, packet_info *pinfo,
1337 kerberos_private_data_t *private_data,
1338 enc_key_t *ek, tvbuff_t *tvb,
1339 krb5_cksumtype checksum,
1340 const char *reason,
1341 const char *keymap_name,
1342 unsigned keymap_size,
1343 unsigned verify_count)
1345 proto_item *item = NULL;
1346 enc_key_t *sek = NULL;
1348 item = proto_tree_add_expert_format(tree, pinfo, &ei_kerberos_decrypted_keytype,
1349 tvb, 0, 0,
1350 "%s checksum %d keytype %d "
1351 "using %s (id=%s same=%u) (%02x%02x%02x%02x...)",
1352 reason, checksum, ek->keytype, ek->key_origin,
1353 ek->id_str, ek->num_same,
1354 ek->keyvalue[0] & 0xFF, ek->keyvalue[1] & 0xFF,
1355 ek->keyvalue[2] & 0xFF, ek->keyvalue[3] & 0xFF);
1356 expert_add_info_format(pinfo, item, &ei_kerberos_decrypted_keytype,
1357 "Used keymap=%s num_keys=%u num_tries=%u)",
1358 keymap_name,
1359 keymap_size,
1360 verify_count);
1361 sek = ek->same_list;
1362 while (sek != NULL) {
1363 expert_add_info_format(pinfo, item, &ei_kerberos_decrypted_keytype,
1364 "%s checksum %d keytype %d "
1365 "using %s (id=%s same=%u) (%02x%02x%02x%02x...)",
1366 reason, checksum, sek->keytype, sek->key_origin,
1367 sek->id_str, sek->num_same,
1368 sek->keyvalue[0] & 0xFF, sek->keyvalue[1] & 0xFF,
1369 sek->keyvalue[2] & 0xFF, sek->keyvalue[3] & 0xFF);
1370 sek = sek->same_list;
1372 kerberos_key_list_append(private_data->decryption_keys, ek);
1375 static void missing_signing_key(proto_tree *tree, packet_info *pinfo,
1376 kerberos_private_data_t *private_data,
1377 tvbuff_t *tvb,
1378 krb5_cksumtype checksum,
1379 int keytype,
1380 const char *reason,
1381 const char *keymap_name,
1382 unsigned keymap_size,
1383 unsigned verify_count)
1385 proto_item *item = NULL;
1386 enc_key_t *mek = NULL;
1388 mek = wmem_new0(pinfo->pool, enc_key_t);
1389 snprintf(mek->key_origin, KRB_MAX_ORIG_LEN,
1390 "checksum %d keytype %d missing in frame %u",
1391 checksum, keytype, pinfo->num);
1392 mek->fd_num = pinfo->num;
1393 mek->id = ++private_data->missing_key_ids;
1394 snprintf(mek->id_str, KRB_MAX_ID_STR_LEN, "missing.%u",
1395 mek->id);
1396 mek->keytype=keytype;
1398 item = proto_tree_add_expert_format(tree, pinfo, &ei_kerberos_missing_keytype,
1399 tvb, 0, 0,
1400 "%s checksum %d keytype %d (id=%s)",
1401 reason, checksum, keytype, mek->id_str);
1402 expert_add_info_format(pinfo, item, &ei_kerberos_missing_keytype,
1403 "Used keymap=%s num_keys=%u num_tries=%u)",
1404 keymap_name,
1405 keymap_size,
1406 verify_count);
1408 kerberos_key_list_append(private_data->missing_keys, mek);
1411 #endif /* HAVE_KRB5_PAC_VERIFY */
1413 static krb5_context krb5_ctx;
1415 #ifdef HAVE_KRB5_C_FX_CF2_SIMPLE
1416 static void
1417 krb5_fast_key(asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb,
1418 enc_key_t *ek1 _U_, const char *p1 _U_,
1419 enc_key_t *ek2 _U_, const char *p2 _U_,
1420 const char *origin _U_)
1422 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
1423 krb5_error_code ret;
1424 krb5_keyblock k1;
1425 krb5_keyblock k2;
1426 krb5_keyblock *k = NULL;
1428 if (!krb_decrypt) {
1429 return;
1432 if (ek1 == NULL) {
1433 return;
1436 if (ek2 == NULL) {
1437 return;
1440 k1.magic = KV5M_KEYBLOCK;
1441 k1.enctype = ek1->keytype;
1442 k1.length = ek1->keylength;
1443 k1.contents = (uint8_t *)ek1->keyvalue;
1445 k2.magic = KV5M_KEYBLOCK;
1446 k2.enctype = ek2->keytype;
1447 k2.length = ek2->keylength;
1448 k2.contents = (uint8_t *)ek2->keyvalue;
1450 ret = krb5_c_fx_cf2_simple(krb5_ctx, &k1, p1, &k2, p2, &k);
1451 if (ret != 0) {
1452 return;
1455 add_encryption_key(actx->pinfo,
1456 private_data,
1457 tree, NULL, tvb,
1458 k->enctype, k->length,
1459 (const char *)k->contents,
1460 origin,
1461 ek1, ek2);
1463 krb5_free_keyblock(krb5_ctx, k);
1465 #else /* HAVE_KRB5_C_FX_CF2_SIMPLE */
1466 static void
1467 krb5_fast_key(asn1_ctx_t *actx _U_, proto_tree *tree _U_, tvbuff_t *tvb _U_,
1468 enc_key_t *ek1 _U_, const char *p1 _U_,
1469 enc_key_t *ek2 _U_, const char *p2 _U_,
1470 const char *origin _U_)
1473 #endif /* HAVE_KRB5_C_FX_CF2_SIMPLE */
1475 USES_APPLE_DEPRECATED_API
1476 void
1477 read_keytab_file(const char *filename)
1479 krb5_keytab keytab;
1480 krb5_error_code ret;
1481 krb5_keytab_entry key;
1482 krb5_kt_cursor cursor;
1483 static bool first_time=true;
1485 if (filename == NULL || filename[0] == 0) {
1486 return;
1489 if(first_time){
1490 first_time=false;
1491 ret = krb5_init_context(&krb5_ctx);
1492 if(ret && ret != KRB5_CONFIG_CANTOPEN){
1493 return;
1497 /* should use a file in the wireshark users dir */
1498 ret = krb5_kt_resolve(krb5_ctx, filename, &keytab);
1499 if(ret){
1500 fprintf(stderr, "KERBEROS ERROR: Badly formatted keytab filename :%s\n",filename);
1502 return;
1505 ret = krb5_kt_start_seq_get(krb5_ctx, keytab, &cursor);
1506 if(ret){
1507 fprintf(stderr, "KERBEROS ERROR: Could not open or could not read from keytab file :%s\n",filename);
1508 return;
1512 ret = krb5_kt_next_entry(krb5_ctx, keytab, &key, &cursor);
1513 if(ret==0){
1514 enc_key_t *new_key;
1515 int i;
1516 char *pos;
1518 new_key = wmem_new0(wmem_epan_scope(), enc_key_t);
1519 new_key->fd_num = -1;
1520 new_key->id = ++kerberos_longterm_ids;
1521 snprintf(new_key->id_str, KRB_MAX_ID_STR_LEN, "keytab.%u", new_key->id);
1522 new_key->next = enc_key_list;
1524 /* generate origin string, describing where this key came from */
1525 pos=new_key->key_origin;
1526 pos+=MIN(KRB_MAX_ORIG_LEN,
1527 snprintf(pos, KRB_MAX_ORIG_LEN, "keytab principal "));
1528 for(i=0;i<key.principal->length;i++){
1529 pos+=MIN(KRB_MAX_ORIG_LEN-(pos-new_key->key_origin),
1530 snprintf(pos, KRB_MAX_ORIG_LEN-(pos-new_key->key_origin), "%s%s",(i?"/":""),(key.principal->data[i]).data));
1532 pos+=MIN(KRB_MAX_ORIG_LEN-(pos-new_key->key_origin),
1533 snprintf(pos, KRB_MAX_ORIG_LEN-(pos-new_key->key_origin), "@%s",key.principal->realm.data));
1534 *pos=0;
1535 new_key->keytype=key.key.enctype;
1536 new_key->keylength=key.key.length;
1537 memcpy(new_key->keyvalue,
1538 key.key.contents,
1539 MIN(key.key.length, KRB_MAX_KEY_LENGTH));
1541 enc_key_list=new_key;
1542 ret = krb5_free_keytab_entry_contents(krb5_ctx, &key);
1543 if (ret) {
1544 fprintf(stderr, "KERBEROS ERROR: Could not release the entry: %d", ret);
1545 ret = 0; /* try to continue with the next entry */
1547 kerberos_key_map_insert(kerberos_longterm_keys, new_key);
1549 }while(ret==0);
1551 ret = krb5_kt_end_seq_get(krb5_ctx, keytab, &cursor);
1552 if(ret){
1553 fprintf(stderr, "KERBEROS ERROR: Could not release the keytab cursor: %d", ret);
1555 ret = krb5_kt_close(krb5_ctx, keytab);
1556 if(ret){
1557 fprintf(stderr, "KERBEROS ERROR: Could not close the key table handle: %d", ret);
1561 struct decrypt_krb5_with_cb_state {
1562 proto_tree *tree;
1563 packet_info *pinfo;
1564 kerberos_private_data_t *private_data;
1565 int usage;
1566 int keytype;
1567 tvbuff_t *cryptotvb;
1568 krb5_error_code (*decrypt_cb_fn)(
1569 const krb5_keyblock *key,
1570 int usage,
1571 void *decrypt_cb_data);
1572 void *decrypt_cb_data;
1573 unsigned count;
1574 enc_key_t *ek;
1577 static void
1578 decrypt_krb5_with_cb_try_key(void *__key _U_, void *value, void *userdata)
1580 struct decrypt_krb5_with_cb_state *state =
1581 (struct decrypt_krb5_with_cb_state *)userdata;
1582 enc_key_t *ek = (enc_key_t *)value;
1583 krb5_error_code ret;
1584 krb5_keytab_entry key;
1585 #ifdef HAVE_KRB5_C_FX_CF2_SIMPLE
1586 enc_key_t *ak = state->private_data->fast_armor_key;
1587 enc_key_t *sk = state->private_data->fast_strengthen_key;
1588 bool try_with_armor_key = false;
1589 bool try_with_strengthen_key = false;
1590 #endif
1592 if (state->ek != NULL) {
1594 * we're done.
1596 return;
1599 #ifdef HAVE_KRB5_C_FX_CF2_SIMPLE
1600 if (ak != NULL && ak != ek && ak->keytype == state->keytype && ek->fd_num == -1) {
1601 switch (state->usage) {
1602 case KEY_USAGE_ENC_CHALLENGE_CLIENT:
1603 case KEY_USAGE_ENC_CHALLENGE_KDC:
1604 if (ek->fd_num == -1) {
1605 /* Challenges are based on a long term key */
1606 try_with_armor_key = true;
1608 break;
1612 * If we already have a strengthen_key
1613 * we don't need to try with the armor key
1614 * again
1616 if (sk != NULL) {
1617 try_with_armor_key = false;
1621 if (sk != NULL && sk != ek && sk->keytype == state->keytype && sk->keytype == ek->keytype) {
1622 switch (state->usage) {
1623 case 3:
1624 if (ek->fd_num == -1) {
1625 /* AS-REP is based on a long term key */
1626 try_with_strengthen_key = true;
1628 break;
1629 case 8:
1630 case 9:
1631 if (ek->fd_num != -1) {
1632 /* TGS-REP is not based on a long term key */
1633 try_with_strengthen_key = true;
1635 break;
1639 if (try_with_armor_key) {
1640 krb5_keyblock k1;
1641 krb5_keyblock k2;
1642 krb5_keyblock *k = NULL;
1643 const char *p1 = NULL;
1645 k1.magic = KV5M_KEYBLOCK;
1646 k1.enctype = ak->keytype;
1647 k1.length = ak->keylength;
1648 k1.contents = (uint8_t *)ak->keyvalue;
1650 k2.magic = KV5M_KEYBLOCK;
1651 k2.enctype = ek->keytype;
1652 k2.length = ek->keylength;
1653 k2.contents = (uint8_t *)ek->keyvalue;
1655 switch (state->usage) {
1656 case KEY_USAGE_ENC_CHALLENGE_CLIENT:
1657 p1 = "clientchallengearmor";
1658 break;
1659 case KEY_USAGE_ENC_CHALLENGE_KDC:
1660 p1 = "kdcchallengearmor";
1661 break;
1662 default:
1664 * Should never be called!
1667 * try the next one...
1669 return;
1672 ret = krb5_c_fx_cf2_simple(krb5_ctx,
1673 &k1, p1,
1674 &k2, "challengelongterm",
1675 &k);
1676 if (ret != 0) {
1678 * try the next one...
1680 return;
1683 state->count += 1;
1684 ret = state->decrypt_cb_fn(k,
1685 state->usage,
1686 state->decrypt_cb_data);
1687 if (ret == 0) {
1688 add_encryption_key(state->pinfo,
1689 state->private_data,
1690 state->tree,
1691 NULL,
1692 state->cryptotvb,
1693 k->enctype, k->length,
1694 (const char *)k->contents,
1696 ak, ek);
1697 krb5_free_keyblock(krb5_ctx, k);
1699 * remember the key and stop traversing
1701 state->ek = state->private_data->last_added_key;
1702 return;
1704 krb5_free_keyblock(krb5_ctx, k);
1706 * don't stop traversing...
1707 * try the next one...
1709 return;
1712 if (try_with_strengthen_key) {
1713 krb5_keyblock k1;
1714 krb5_keyblock k2;
1715 krb5_keyblock *k = NULL;
1717 k1.magic = KV5M_KEYBLOCK;
1718 k1.enctype = sk->keytype;
1719 k1.length = sk->keylength;
1720 k1.contents = (uint8_t *)sk->keyvalue;
1722 k2.magic = KV5M_KEYBLOCK;
1723 k2.enctype = ek->keytype;
1724 k2.length = ek->keylength;
1725 k2.contents = (uint8_t *)ek->keyvalue;
1727 ret = krb5_c_fx_cf2_simple(krb5_ctx,
1728 &k1, "strengthenkey",
1729 &k2, "replykey",
1730 &k);
1731 if (ret != 0) {
1733 * try the next one...
1735 return;
1738 state->count += 1;
1739 ret = state->decrypt_cb_fn(k,
1740 state->usage,
1741 state->decrypt_cb_data);
1742 if (ret == 0) {
1743 add_encryption_key(state->pinfo,
1744 state->private_data,
1745 state->tree,
1746 NULL,
1747 state->cryptotvb,
1748 k->enctype, k->length,
1749 (const char *)k->contents,
1750 "strengthen-reply-key",
1751 sk, ek);
1752 krb5_free_keyblock(krb5_ctx, k);
1754 * remember the key and stop traversing
1756 state->ek = state->private_data->last_added_key;
1757 return;
1759 krb5_free_keyblock(krb5_ctx, k);
1761 * don't stop traversing...
1762 * try the next one...
1764 return;
1766 #endif /* HAVE_KRB5_C_FX_CF2_SIMPLE */
1768 /* shortcircuit and bail out if enctypes are not matching */
1769 if ((state->keytype != -1) && (ek->keytype != state->keytype)) {
1771 * don't stop traversing...
1772 * try the next one...
1774 return;
1777 key.key.enctype=ek->keytype;
1778 key.key.length=ek->keylength;
1779 key.key.contents=ek->keyvalue;
1780 state->count += 1;
1781 ret = state->decrypt_cb_fn(&(key.key),
1782 state->usage,
1783 state->decrypt_cb_data);
1784 if (ret != 0) {
1786 * don't stop traversing...
1787 * try the next one...
1789 return;
1793 * we're done, remember the key
1795 state->ek = ek;
1798 static krb5_error_code
1799 decrypt_krb5_with_cb(proto_tree *tree,
1800 packet_info *pinfo,
1801 kerberos_private_data_t *private_data,
1802 int usage,
1803 int keytype,
1804 tvbuff_t *cryptotvb,
1805 krb5_error_code (*decrypt_cb_fn)(
1806 const krb5_keyblock *key,
1807 int usage,
1808 void *decrypt_cb_data),
1809 void *decrypt_cb_data)
1811 const char *key_map_name = NULL;
1812 wmem_map_t *key_map = NULL;
1813 struct decrypt_krb5_with_cb_state state = {
1814 .tree = tree,
1815 .pinfo = pinfo,
1816 .private_data = private_data,
1817 .usage = usage,
1818 .cryptotvb = cryptotvb,
1819 .keytype = keytype,
1820 .decrypt_cb_fn = decrypt_cb_fn,
1821 .decrypt_cb_data = decrypt_cb_data,
1824 read_keytab_file_from_preferences();
1826 switch (usage) {
1827 case KRB5_KU_USAGE_INITIATOR_SEAL:
1828 case KRB5_KU_USAGE_ACCEPTOR_SEAL:
1829 key_map_name = "app_session_keys";
1830 key_map = kerberos_app_session_keys;
1831 break;
1832 default:
1833 key_map_name = "all_keys";
1834 key_map = kerberos_all_keys;
1835 insert_longterm_keys_into_key_map(key_map);
1836 break;
1839 wmem_map_foreach(key_map, decrypt_krb5_with_cb_try_key, &state);
1840 if (state.ek != NULL) {
1841 used_encryption_key(tree, pinfo, private_data,
1842 state.ek, usage, cryptotvb,
1843 key_map_name,
1844 wmem_map_size(key_map),
1845 state.count);
1846 return 0;
1849 missing_encryption_key(tree, pinfo, private_data,
1850 keytype, usage, cryptotvb,
1851 key_map_name,
1852 wmem_map_size(key_map),
1853 state.count);
1854 return -1;
1857 struct decrypt_krb5_data_state {
1858 krb5_data input;
1859 krb5_data output;
1862 static krb5_error_code
1863 decrypt_krb5_data_cb(const krb5_keyblock *key,
1864 int usage,
1865 void *decrypt_cb_data)
1867 struct decrypt_krb5_data_state *state =
1868 (struct decrypt_krb5_data_state *)decrypt_cb_data;
1869 krb5_enc_data input;
1871 memset(&input, 0, sizeof(input));
1872 input.enctype = key->enctype;
1873 input.ciphertext = state->input;
1875 return krb5_c_decrypt(krb5_ctx,
1876 key,
1877 usage,
1879 &input,
1880 &state->output);
1883 static uint8_t *
1884 decrypt_krb5_data_private(proto_tree *tree _U_, packet_info *pinfo,
1885 kerberos_private_data_t *private_data,
1886 int usage, tvbuff_t *cryptotvb, int keytype,
1887 int *datalen)
1889 #define HAVE_DECRYPT_KRB5_DATA_PRIVATE 1
1890 struct decrypt_krb5_data_state state;
1891 krb5_error_code ret;
1892 int length = tvb_captured_length(cryptotvb);
1893 const uint8_t *cryptotext = tvb_get_ptr(cryptotvb, 0, length);
1895 /* don't do anything if we are not attempting to decrypt data */
1896 if(!krb_decrypt || length < 1){
1897 return NULL;
1900 /* make sure we have all the data we need */
1901 if (tvb_captured_length(cryptotvb) < tvb_reported_length(cryptotvb)) {
1902 return NULL;
1905 memset(&state, 0, sizeof(state));
1906 state.input.length = length;
1907 state.input.data = (uint8_t *)cryptotext;
1908 state.output.data = (char *)wmem_alloc(pinfo->pool, length);
1909 state.output.length = length;
1911 ret = decrypt_krb5_with_cb(tree,
1912 pinfo,
1913 private_data,
1914 usage,
1915 keytype,
1916 cryptotvb,
1917 decrypt_krb5_data_cb,
1918 &state);
1919 if (ret != 0) {
1920 return NULL;
1923 if (datalen) {
1924 *datalen = state.output.length;
1926 return (uint8_t *)state.output.data;
1929 uint8_t *
1930 decrypt_krb5_data(proto_tree *tree _U_, packet_info *pinfo,
1931 int usage,
1932 tvbuff_t *cryptotvb,
1933 int keytype,
1934 int *datalen)
1936 kerberos_private_data_t *zero_private = kerberos_new_private_data(pinfo);
1937 return decrypt_krb5_data_private(tree, pinfo, zero_private,
1938 usage, cryptotvb, keytype,
1939 datalen);
1942 USES_APPLE_RST
1944 #ifdef KRB5_CRYPTO_TYPE_SIGN_ONLY
1945 struct decrypt_krb5_krb_cfx_dce_state {
1946 const uint8_t *gssapi_header_ptr;
1947 unsigned gssapi_header_len;
1948 tvbuff_t *gssapi_encrypted_tvb;
1949 uint8_t *gssapi_payload;
1950 unsigned gssapi_payload_len;
1951 const uint8_t *gssapi_trailer_ptr;
1952 unsigned gssapi_trailer_len;
1953 tvbuff_t *checksum_tvb;
1954 uint8_t *checksum;
1955 unsigned checksum_len;
1958 static krb5_error_code
1959 decrypt_krb5_krb_cfx_dce_cb(const krb5_keyblock *key,
1960 int usage,
1961 void *decrypt_cb_data)
1963 struct decrypt_krb5_krb_cfx_dce_state *state =
1964 (struct decrypt_krb5_krb_cfx_dce_state *)decrypt_cb_data;
1965 unsigned int k5_headerlen = 0;
1966 unsigned int k5_headerofs = 0;
1967 unsigned int k5_trailerlen = 0;
1968 unsigned int k5_trailerofs = 0;
1969 size_t _k5_blocksize = 0;
1970 unsigned k5_blocksize;
1971 krb5_crypto_iov iov[6];
1972 krb5_error_code ret;
1973 unsigned checksum_remain = state->checksum_len;
1974 unsigned checksum_crypt_len;
1976 memset(iov, 0, sizeof(iov));
1978 ret = krb5_c_crypto_length(krb5_ctx,
1979 key->enctype,
1980 KRB5_CRYPTO_TYPE_HEADER,
1981 &k5_headerlen);
1982 if (ret != 0) {
1983 return ret;
1985 if (checksum_remain < k5_headerlen) {
1986 return -1;
1988 checksum_remain -= k5_headerlen;
1989 k5_headerofs = checksum_remain;
1990 ret = krb5_c_crypto_length(krb5_ctx,
1991 key->enctype,
1992 KRB5_CRYPTO_TYPE_TRAILER,
1993 &k5_trailerlen);
1994 if (ret != 0) {
1995 return ret;
1997 if (checksum_remain < k5_trailerlen) {
1998 return -1;
2000 checksum_remain -= k5_trailerlen;
2001 k5_trailerofs = checksum_remain;
2002 checksum_crypt_len = checksum_remain;
2004 ret = krb5_c_block_size(krb5_ctx,
2005 key->enctype,
2006 &_k5_blocksize);
2007 if (ret != 0) {
2008 return ret;
2011 * The cast is required for the Windows build in order
2012 * to avoid the following warning.
2014 * warning C4267: '-=': conversion from 'size_t' to 'unsigned',
2015 * possible loss of data
2017 k5_blocksize = (unsigned)_k5_blocksize;
2018 if (checksum_remain < k5_blocksize) {
2019 return -1;
2021 checksum_remain -= k5_blocksize;
2022 if (checksum_remain < 16) {
2023 return -1;
2026 tvb_memcpy(state->gssapi_encrypted_tvb,
2027 state->gssapi_payload,
2029 state->gssapi_payload_len);
2030 tvb_memcpy(state->checksum_tvb,
2031 state->checksum,
2033 state->checksum_len);
2035 iov[0].flags = KRB5_CRYPTO_TYPE_HEADER;
2036 iov[0].data.data = state->checksum + k5_headerofs;
2037 iov[0].data.length = k5_headerlen;
2039 if (state->gssapi_header_ptr != NULL) {
2040 iov[1].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY;
2041 iov[1].data.data = (uint8_t *)(uintptr_t)state->gssapi_header_ptr;
2042 iov[1].data.length = state->gssapi_header_len;
2043 } else {
2044 iov[1].flags = KRB5_CRYPTO_TYPE_EMPTY;
2047 iov[2].flags = KRB5_CRYPTO_TYPE_DATA;
2048 iov[2].data.data = state->gssapi_payload;
2049 iov[2].data.length = state->gssapi_payload_len;
2051 if (state->gssapi_trailer_ptr != NULL) {
2052 iov[3].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY;
2053 iov[3].data.data = (uint8_t *)(uintptr_t)state->gssapi_trailer_ptr;
2054 iov[3].data.length = state->gssapi_trailer_len;
2055 } else {
2056 iov[3].flags = KRB5_CRYPTO_TYPE_EMPTY;
2059 iov[4].flags = KRB5_CRYPTO_TYPE_DATA;
2060 iov[4].data.data = state->checksum;
2061 iov[4].data.length = checksum_crypt_len;
2063 iov[5].flags = KRB5_CRYPTO_TYPE_TRAILER;
2064 iov[5].data.data = state->checksum + k5_trailerofs;
2065 iov[5].data.length = k5_trailerlen;
2067 return krb5_c_decrypt_iov(krb5_ctx,
2068 key,
2069 usage,
2071 iov,
2075 tvbuff_t *
2076 decrypt_krb5_krb_cfx_dce(proto_tree *tree,
2077 packet_info *pinfo,
2078 int usage,
2079 int keytype,
2080 tvbuff_t *gssapi_header_tvb,
2081 tvbuff_t *gssapi_encrypted_tvb,
2082 tvbuff_t *gssapi_trailer_tvb,
2083 tvbuff_t *checksum_tvb)
2085 struct decrypt_krb5_krb_cfx_dce_state state;
2086 kerberos_private_data_t *zero_private = kerberos_new_private_data(pinfo);
2087 tvbuff_t *gssapi_decrypted_tvb = NULL;
2088 krb5_error_code ret;
2090 /* don't do anything if we are not attempting to decrypt data */
2091 if (!krb_decrypt) {
2092 return NULL;
2095 memset(&state, 0, sizeof(state));
2097 /* make sure we have all the data we need */
2098 #define __CHECK_TVB_LEN(__tvb) (tvb_captured_length(__tvb) < tvb_reported_length(__tvb))
2099 if (gssapi_header_tvb != NULL) {
2100 if (__CHECK_TVB_LEN(gssapi_header_tvb)) {
2101 return NULL;
2104 state.gssapi_header_len = tvb_captured_length(gssapi_header_tvb);
2105 state.gssapi_header_ptr = tvb_get_ptr(gssapi_header_tvb,
2107 state.gssapi_header_len);
2109 if (gssapi_encrypted_tvb == NULL || __CHECK_TVB_LEN(gssapi_encrypted_tvb)) {
2110 return NULL;
2112 state.gssapi_encrypted_tvb = gssapi_encrypted_tvb;
2113 state.gssapi_payload_len = tvb_captured_length(gssapi_encrypted_tvb);
2114 state.gssapi_payload = (uint8_t *)wmem_alloc0(pinfo->pool, state.gssapi_payload_len);
2115 if (state.gssapi_payload == NULL) {
2116 return NULL;
2118 if (gssapi_trailer_tvb != NULL) {
2119 if (__CHECK_TVB_LEN(gssapi_trailer_tvb)) {
2120 return NULL;
2123 state.gssapi_trailer_len = tvb_captured_length(gssapi_trailer_tvb);
2124 state.gssapi_trailer_ptr = tvb_get_ptr(gssapi_trailer_tvb,
2126 state.gssapi_trailer_len);
2128 if (checksum_tvb == NULL || __CHECK_TVB_LEN(checksum_tvb)) {
2129 return NULL;
2131 state.checksum_tvb = checksum_tvb;
2132 state.checksum_len = tvb_captured_length(checksum_tvb);
2133 state.checksum = (uint8_t *)wmem_alloc0(pinfo->pool, state.checksum_len);
2134 if (state.checksum == NULL) {
2135 return NULL;
2138 ret = decrypt_krb5_with_cb(tree,
2139 pinfo,
2140 zero_private,
2141 usage,
2142 keytype,
2143 gssapi_encrypted_tvb,
2144 decrypt_krb5_krb_cfx_dce_cb,
2145 &state);
2146 wmem_free(pinfo->pool, state.checksum);
2147 if (ret != 0) {
2148 wmem_free(pinfo->pool, state.gssapi_payload);
2149 return NULL;
2152 gssapi_decrypted_tvb = tvb_new_child_real_data(gssapi_encrypted_tvb,
2153 state.gssapi_payload,
2154 state.gssapi_payload_len,
2155 state.gssapi_payload_len);
2156 if (gssapi_decrypted_tvb == NULL) {
2157 wmem_free(pinfo->pool, state.gssapi_payload);
2158 return NULL;
2161 return gssapi_decrypted_tvb;
2163 #else /* NOT KRB5_CRYPTO_TYPE_SIGN_ONLY */
2164 #define NEED_DECRYPT_KRB5_KRB_CFX_DCE_NOOP 1
2165 #endif /* NOT KRB5_CRYPTO_TYPE_SIGN_ONLY */
2167 #ifdef HAVE_KRB5_PAC_VERIFY
2169 * macOS up to 10.14.5 only has a MIT shim layer on top
2170 * of heimdal. It means that krb5_pac_verify() is not available
2171 * in /usr/lib/libkrb5.dylib
2173 * https://opensource.apple.com/tarballs/Heimdal/Heimdal-520.260.1.tar.gz
2174 * https://opensource.apple.com/tarballs/MITKerberosShim/MITKerberosShim-71.200.1.tar.gz
2177 extern krb5_error_code
2178 krb5int_c_mandatory_cksumtype(krb5_context, krb5_enctype, krb5_cksumtype *);
2180 extern void krb5_free_enc_tkt_part(krb5_context, krb5_enc_tkt_part *);
2181 extern krb5_error_code
2182 decode_krb5_enc_tkt_part(const krb5_data *output, krb5_enc_tkt_part **rep);
2183 extern krb5_error_code
2184 encode_krb5_enc_tkt_part(const krb5_enc_tkt_part *rep, krb5_data **code);
2186 static int
2187 keytype_for_cksumtype(krb5_cksumtype checksum)
2189 static const int keytypes[] = {
2194 unsigned i;
2196 for (i = 0; i < array_length(keytypes); i++) {
2197 krb5_cksumtype checksumtype = 0;
2198 krb5_error_code ret;
2200 ret = krb5int_c_mandatory_cksumtype(krb5_ctx,
2201 keytypes[i],
2202 &checksumtype);
2203 if (ret != 0) {
2204 continue;
2206 if (checksum == checksumtype) {
2207 return keytypes[i];
2211 return -1;
2214 struct verify_krb5_pac_state {
2215 int pacbuffer_length;
2216 const uint8_t *pacbuffer;
2217 krb5_pac pac;
2218 krb5_cksumtype server_checksum;
2219 unsigned server_count;
2220 enc_key_t *server_ek;
2221 krb5_cksumtype kdc_checksum;
2222 unsigned kdc_count;
2223 enc_key_t *kdc_ek;
2224 krb5_cksumtype ticket_checksum_type;
2225 const krb5_data *ticket_checksum_data;
2226 krb5_cksumtype full_checksum_type;
2227 const krb5_data *full_checksum_data;
2228 unsigned full_count;
2229 enc_key_t *full_ek;
2232 static void
2233 verify_krb5_pac_try_server_key(void *__key _U_, void *value, void *userdata)
2235 struct verify_krb5_pac_state *state =
2236 (struct verify_krb5_pac_state *)userdata;
2237 enc_key_t *ek = (enc_key_t *)value;
2238 krb5_keyblock keyblock;
2239 krb5_cksumtype checksumtype = 0;
2240 krb5_error_code ret;
2242 if (state->server_checksum == 0) {
2244 * nothing more todo, stop traversing.
2246 return;
2249 if (state->server_ek != NULL) {
2251 * we're done.
2253 return;
2256 ret = krb5int_c_mandatory_cksumtype(krb5_ctx, ek->keytype,
2257 &checksumtype);
2258 if (ret != 0) {
2260 * the key is not usable, keep traversing.
2261 * try the next key...
2263 return;
2266 keyblock.magic = KV5M_KEYBLOCK;
2267 keyblock.enctype = ek->keytype;
2268 keyblock.length = ek->keylength;
2269 keyblock.contents = (uint8_t *)ek->keyvalue;
2271 if (checksumtype == state->server_checksum) {
2272 state->server_count += 1;
2273 ret = krb5_pac_verify(krb5_ctx, state->pac, 0, NULL,
2274 &keyblock, NULL);
2275 if (ret == 0) {
2276 state->server_ek = ek;
2281 static void
2282 verify_krb5_pac_try_kdc_key(void *__key _U_, void *value, void *userdata)
2284 struct verify_krb5_pac_state *state =
2285 (struct verify_krb5_pac_state *)userdata;
2286 enc_key_t *ek = (enc_key_t *)value;
2287 krb5_keyblock keyblock;
2288 krb5_cksumtype checksumtype = 0;
2289 krb5_error_code ret;
2291 if (state->kdc_checksum == 0) {
2293 * nothing more todo, stop traversing.
2295 return;
2298 if (state->kdc_ek != NULL) {
2300 * we're done.
2302 return;
2305 ret = krb5int_c_mandatory_cksumtype(krb5_ctx, ek->keytype,
2306 &checksumtype);
2307 if (ret != 0) {
2309 * the key is not usable, keep traversing.
2310 * try the next key...
2312 return;
2315 keyblock.magic = KV5M_KEYBLOCK;
2316 keyblock.enctype = ek->keytype;
2317 keyblock.length = ek->keylength;
2318 keyblock.contents = (uint8_t *)ek->keyvalue;
2320 if (checksumtype == state->kdc_checksum) {
2321 state->kdc_count += 1;
2322 ret = krb5_pac_verify(krb5_ctx, state->pac, 0, NULL,
2323 NULL, &keyblock);
2324 if (ret == 0) {
2325 state->kdc_ek = ek;
2330 #define __KRB5_PAC_TICKET_CHECKSUM 16
2332 static void
2333 verify_krb5_pac_ticket_checksum(proto_tree *tree _U_,
2334 asn1_ctx_t *actx _U_,
2335 tvbuff_t *pactvb _U_,
2336 struct verify_krb5_pac_state *state _U_)
2338 #ifdef HAVE_DECODE_KRB5_ENC_TKT_PART
2339 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
2340 tvbuff_t *teptvb = private_data->last_ticket_enc_part_tvb;
2341 unsigned teplength = 0;
2342 const uint8_t *tepbuffer = NULL;
2343 krb5_data tepdata = { .length = 0, };
2344 krb5_enc_tkt_part *tep = NULL;
2345 krb5_data *tmpdata = NULL;
2346 krb5_error_code ret;
2347 krb5_authdata **recoded_container = NULL;
2348 int ad_orig_idx = -1;
2349 krb5_authdata *ad_orig_ptr = NULL;
2350 int l0idx = 0;
2351 krb5_keyblock kdc_key = { .magic = KV5M_KEYBLOCK, };
2352 size_t checksum_length = 0;
2353 krb5_checksum checksum = { .checksum_type = 0, };
2354 krb5_boolean valid = false;
2356 if (state->kdc_ek == NULL) {
2357 int keytype = keytype_for_cksumtype(state->ticket_checksum_type);
2358 missing_signing_key(tree, actx->pinfo, private_data,
2359 pactvb, state->ticket_checksum_type,
2360 keytype,
2361 "Missing KDC (for ticket)",
2362 "kdc_checksum_key",
2365 return;
2368 if (teptvb == NULL) {
2369 return;
2372 teplength = tvb_captured_length(teptvb);
2373 /* make sure we have all the data we need */
2374 if (teplength < tvb_reported_length(teptvb)) {
2375 return;
2378 tepbuffer = tvb_get_ptr(teptvb, 0, teplength);
2379 if (tepbuffer == NULL) {
2380 return;
2383 kdc_key.magic = KV5M_KEYBLOCK;
2384 kdc_key.enctype = state->kdc_ek->keytype;
2385 kdc_key.length = state->kdc_ek->keylength;
2386 kdc_key.contents = (uint8_t *)state->kdc_ek->keyvalue;
2388 checksum.checksum_type = state->ticket_checksum_type;
2389 checksum.length = state->ticket_checksum_data->length;
2390 checksum.contents = (uint8_t *)state->ticket_checksum_data->data;
2391 if (checksum.length >= 4) {
2392 checksum.length -= 4;
2393 checksum.contents += 4;
2396 ret = krb5_c_checksum_length(krb5_ctx,
2397 checksum.checksum_type,
2398 &checksum_length);
2399 if (ret != 0) {
2400 missing_signing_key(tree, actx->pinfo, private_data,
2401 pactvb, state->ticket_checksum_type,
2402 state->kdc_ek->keytype,
2403 "krb5_c_checksum_length failed for Ticket Signature",
2404 "kdc_checksum_key",
2407 return;
2409 checksum.length = MIN(checksum.length, (unsigned int)checksum_length);
2411 tepdata.data = (void *)tepbuffer;
2412 tepdata.length = teplength;
2414 ret = decode_krb5_enc_tkt_part(&tepdata, &tep);
2415 if (ret != 0) {
2416 missing_signing_key(tree, actx->pinfo, private_data,
2417 pactvb, state->ticket_checksum_type,
2418 state->kdc_ek->keytype,
2419 "decode_krb5_enc_tkt_part failed",
2420 "kdc_checksum_key",
2423 return;
2426 for (l0idx = 0; tep->authorization_data[l0idx]; l0idx++) {
2427 krb5_authdata *adl0 = tep->authorization_data[l0idx];
2428 krb5_authdata **decoded_container = NULL;
2429 krb5_authdata *ad_pac = NULL;
2430 int l1idx = 0;
2432 if (adl0->ad_type != KRB5_AUTHDATA_IF_RELEVANT) {
2433 continue;
2436 ret = krb5_decode_authdata_container(krb5_ctx,
2437 KRB5_AUTHDATA_IF_RELEVANT,
2438 adl0,
2439 &decoded_container);
2440 if (ret != 0) {
2441 missing_signing_key(tree, actx->pinfo, private_data,
2442 pactvb, state->ticket_checksum_type,
2443 state->kdc_ek->keytype,
2444 "krb5_decode_authdata_container failed",
2445 "kdc_checksum_key",
2448 krb5_free_enc_tkt_part(krb5_ctx, tep);
2449 return;
2452 for (l1idx = 0; decoded_container[l1idx]; l1idx++) {
2453 krb5_authdata *adl1 = decoded_container[l1idx];
2455 if (adl1->ad_type != KRB5_AUTHDATA_WIN2K_PAC) {
2456 continue;
2459 ad_pac = adl1;
2460 break;
2463 if (ad_pac == NULL) {
2464 krb5_free_authdata(krb5_ctx, decoded_container);
2465 continue;
2468 ad_pac->length = 1;
2469 ad_pac->contents[0] = '\0';
2471 ret = krb5_encode_authdata_container(krb5_ctx,
2472 KRB5_AUTHDATA_IF_RELEVANT,
2473 decoded_container,
2474 &recoded_container);
2475 krb5_free_authdata(krb5_ctx, decoded_container);
2476 decoded_container = NULL;
2477 if (ret != 0) {
2478 missing_signing_key(tree, actx->pinfo, private_data,
2479 pactvb, state->ticket_checksum_type,
2480 state->kdc_ek->keytype,
2481 "krb5_encode_authdata_container failed",
2482 "kdc_checksum_key",
2485 krb5_free_enc_tkt_part(krb5_ctx, tep);
2486 return;
2489 ad_orig_idx = l0idx;
2490 ad_orig_ptr = adl0;
2491 tep->authorization_data[l0idx] = recoded_container[0];
2492 break;
2495 ret = encode_krb5_enc_tkt_part(tep, &tmpdata);
2496 if (ad_orig_ptr != NULL) {
2497 tep->authorization_data[ad_orig_idx] = ad_orig_ptr;
2499 krb5_free_enc_tkt_part(krb5_ctx, tep);
2500 tep = NULL;
2501 if (recoded_container != NULL) {
2502 krb5_free_authdata(krb5_ctx, recoded_container);
2503 recoded_container = NULL;
2505 if (ret != 0) {
2506 missing_signing_key(tree, actx->pinfo, private_data,
2507 pactvb, state->ticket_checksum_type,
2508 state->kdc_ek->keytype,
2509 "encode_krb5_enc_tkt_part failed",
2510 "kdc_checksum_key",
2513 return;
2516 ret = krb5_c_verify_checksum(krb5_ctx, &kdc_key,
2517 KRB5_KEYUSAGE_APP_DATA_CKSUM,
2518 tmpdata, &checksum, &valid);
2519 krb5_free_data(krb5_ctx, tmpdata);
2520 tmpdata = NULL;
2521 if (ret != 0) {
2522 missing_signing_key(tree, actx->pinfo, private_data,
2523 pactvb, state->ticket_checksum_type,
2524 state->kdc_ek->keytype,
2525 "krb5_c_verify_checksum failed for Ticket Signature",
2526 "kdc_checksum_key",
2529 return;
2532 if (valid == false) {
2533 missing_signing_key(tree, actx->pinfo, private_data,
2534 pactvb, state->ticket_checksum_type,
2535 state->kdc_ek->keytype,
2536 "Invalid Ticket",
2537 "kdc_checksum_key",
2540 return;
2543 used_signing_key(tree, actx->pinfo, private_data,
2544 state->kdc_ek, pactvb,
2545 state->ticket_checksum_type,
2546 "Verified Ticket",
2547 "kdc_checksum_key",
2550 #endif /* HAVE_DECODE_KRB5_ENC_TKT_PART */
2553 #define __KRB5_PAC_FULL_CHECKSUM 19
2555 static void
2556 verify_krb5_pac_full_checksum(proto_tree *tree,
2557 asn1_ctx_t *actx,
2558 tvbuff_t *orig_pactvb,
2559 struct verify_krb5_pac_state *state)
2561 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
2562 krb5_error_code ret;
2563 krb5_keyblock kdc_key = { .magic = KV5M_KEYBLOCK, };
2564 size_t checksum_length = 0;
2565 krb5_checksum checksum = { .checksum_type = 0, };
2566 krb5_data pac_data = { .length = 0, };
2567 tvbuff_t *copy_pactvb = NULL;
2568 uint32_t cur_offset;
2569 uint32_t num_buffers;
2570 uint32_t idx;
2571 krb5_boolean valid = false;
2573 if (state->kdc_ek == NULL) {
2574 int keytype = keytype_for_cksumtype(state->full_checksum_type);
2575 missing_signing_key(tree, actx->pinfo, private_data,
2576 orig_pactvb, state->full_checksum_type,
2577 keytype,
2578 "Missing KDC (for full)",
2579 "kdc_checksum_key",
2582 return;
2585 kdc_key.magic = KV5M_KEYBLOCK;
2586 kdc_key.enctype = state->kdc_ek->keytype;
2587 kdc_key.length = state->kdc_ek->keylength;
2588 kdc_key.contents = (uint8_t *)state->kdc_ek->keyvalue;
2590 ret = krb5_c_checksum_length(krb5_ctx,
2591 state->full_checksum_type,
2592 &checksum_length);
2593 if (ret != 0) {
2594 missing_signing_key(tree, actx->pinfo, private_data,
2595 orig_pactvb, state->full_checksum_type,
2596 state->kdc_ek->keytype,
2597 "krb5_c_checksum_length failed for Full Signature",
2598 "kdc_checksum_key",
2601 return;
2605 * The checksum element begins with 4 bytes of type
2606 * (state->full_checksum_type) before the crypto checksum
2608 if (state->full_checksum_data->length < (4 + checksum_length)) {
2609 missing_signing_key(tree, actx->pinfo, private_data,
2610 orig_pactvb, state->full_checksum_type,
2611 state->kdc_ek->keytype,
2612 "pacbuffer_length too short for Full Signature",
2613 "kdc_checksum_key",
2616 return;
2619 pac_data.data = wmem_memdup(actx->pinfo->pool, state->pacbuffer, state->pacbuffer_length);
2620 if (pac_data.data == NULL) {
2621 missing_signing_key(tree, actx->pinfo, private_data,
2622 orig_pactvb, state->full_checksum_type,
2623 state->kdc_ek->keytype,
2624 "wmem_memdup(pacbuffer) failed",
2625 "kdc_checksum_key",
2628 return;
2630 pac_data.length = state->pacbuffer_length;
2632 copy_pactvb = tvb_new_child_real_data(orig_pactvb,
2633 (uint8_t *)pac_data.data,
2634 pac_data.length,
2635 pac_data.length);
2636 if (copy_pactvb == NULL) {
2637 missing_signing_key(tree, actx->pinfo, private_data,
2638 orig_pactvb, state->full_checksum_type,
2639 state->kdc_ek->keytype,
2640 "tvb_new_child_real_data(pac_copy) failed",
2641 "kdc_checksum_key",
2644 return;
2647 #define __PAC_CHECK_OFFSET_SIZE(__offset, __length, __reason) do { \
2648 uint64_t __end = state->pacbuffer_length; \
2649 uint64_t __offset64 = __offset; \
2650 uint64_t __length64 = __length; \
2651 uint64_t __last; \
2652 if (__offset64 > INT32_MAX) { \
2653 missing_signing_key(tree, actx->pinfo, private_data, \
2654 orig_pactvb, state->full_checksum_type, \
2655 state->kdc_ek->keytype, \
2656 __reason, \
2657 "kdc_checksum_key", \
2658 1, \
2659 0); \
2660 return; \
2662 if (__length64 > INT32_MAX) { \
2663 missing_signing_key(tree, actx->pinfo, private_data, \
2664 orig_pactvb, state->full_checksum_type, \
2665 state->kdc_ek->keytype, \
2666 __reason, \
2667 "kdc_checksum_key", \
2668 1, \
2669 0); \
2670 return; \
2672 __last = __offset64 + __length64; \
2673 if (__last > __end) { \
2674 missing_signing_key(tree, actx->pinfo, private_data, \
2675 orig_pactvb, state->full_checksum_type, \
2676 state->kdc_ek->keytype, \
2677 __reason, \
2678 "kdc_checksum_key", \
2679 1, \
2680 0); \
2681 return; \
2683 } while(0)
2685 cur_offset = 0;
2686 __PAC_CHECK_OFFSET_SIZE(cur_offset, 8, "PACTYPE Header");
2687 num_buffers = tvb_get_uint32(copy_pactvb, cur_offset, ENC_LITTLE_ENDIAN);
2688 cur_offset += 4;
2689 /* ignore 4 byte version */
2690 cur_offset += 4;
2692 for (idx = 0; idx < num_buffers; idx++) {
2693 uint32_t b_type;
2694 uint32_t b_length;
2695 uint64_t b_offset;
2697 __PAC_CHECK_OFFSET_SIZE(cur_offset, 16, "PAC_INFO_BUFFER Header");
2698 b_type = tvb_get_uint32(copy_pactvb, cur_offset, ENC_LITTLE_ENDIAN);
2699 cur_offset += 4;
2700 b_length = tvb_get_uint32(copy_pactvb, cur_offset, ENC_LITTLE_ENDIAN);
2701 cur_offset += 4;
2702 b_offset = tvb_get_uint64(copy_pactvb, cur_offset, ENC_LITTLE_ENDIAN);
2703 cur_offset += 8;
2705 __PAC_CHECK_OFFSET_SIZE(b_offset, b_length, "PAC_INFO_BUFFER Payload");
2707 if (b_length <= 4) {
2708 continue;
2712 * Leave PAC_TICKET_CHECKSUM and clear all other checksums
2713 * and their possible RODC identifier, but leaving their
2714 * checksum type as is.
2716 switch (b_type) {
2717 case KRB5_PAC_SERVER_CHECKSUM:
2718 case KRB5_PAC_PRIVSVR_CHECKSUM:
2719 case __KRB5_PAC_FULL_CHECKSUM:
2720 memset(pac_data.data + b_offset+4, 0, b_length-4);
2721 break;
2725 checksum.checksum_type = state->full_checksum_type;
2726 checksum.contents = (uint8_t *)state->full_checksum_data->data + 4;
2727 checksum.length = (unsigned)checksum_length;
2729 ret = krb5_c_verify_checksum(krb5_ctx, &kdc_key,
2730 KRB5_KEYUSAGE_APP_DATA_CKSUM,
2731 &pac_data, &checksum, &valid);
2732 if (ret != 0) {
2733 missing_signing_key(tree, actx->pinfo, private_data,
2734 orig_pactvb, state->full_checksum_type,
2735 state->kdc_ek->keytype,
2736 "krb5_c_verify_checksum failed for Full PAC Signature",
2737 "kdc_checksum_key",
2740 return;
2743 if (valid == false) {
2744 missing_signing_key(tree, actx->pinfo, private_data,
2745 orig_pactvb, state->full_checksum_type,
2746 state->kdc_ek->keytype,
2747 "Invalid Full PAC Signature",
2748 "kdc_checksum_key",
2751 return;
2754 used_signing_key(tree, actx->pinfo, private_data,
2755 state->kdc_ek, orig_pactvb,
2756 state->full_checksum_type,
2757 "Verified Full PAC",
2758 "kdc_checksum_key",
2763 static void
2764 verify_krb5_pac(proto_tree *tree _U_, asn1_ctx_t *actx, tvbuff_t *pactvb)
2766 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
2767 krb5_error_code ret;
2768 krb5_data checksum_data = {0,0,NULL};
2769 krb5_data ticket_checksum_data = {0,0,NULL};
2770 krb5_data full_checksum_data = {0,0,NULL};
2771 int length = tvb_captured_length(pactvb);
2772 const uint8_t *pacbuffer = NULL;
2773 struct verify_krb5_pac_state state = {
2774 .kdc_checksum = 0,
2777 /* don't do anything if we are not attempting to decrypt data */
2778 if(!krb_decrypt || length < 1){
2779 return;
2782 /* make sure we have all the data we need */
2783 if (tvb_captured_length(pactvb) < tvb_reported_length(pactvb)) {
2784 return;
2787 pacbuffer = tvb_get_ptr(pactvb, 0, length);
2788 state.pacbuffer_length = length;
2789 state.pacbuffer = pacbuffer;
2791 ret = krb5_pac_parse(krb5_ctx, pacbuffer, length, &state.pac);
2792 if (ret != 0) {
2793 proto_tree_add_expert_format(tree, actx->pinfo, &ei_kerberos_decrypted_keytype,
2794 pactvb, 0, 0,
2795 "Failed to parse PAC buffer %d in frame %u",
2796 ret, actx->pinfo->fd->num);
2797 return;
2800 ret = krb5_pac_get_buffer(krb5_ctx, state.pac, KRB5_PAC_SERVER_CHECKSUM,
2801 &checksum_data);
2802 if (ret == 0) {
2803 state.server_checksum = pletoh32(checksum_data.data);
2804 krb5_free_data_contents(krb5_ctx, &checksum_data);
2806 ret = krb5_pac_get_buffer(krb5_ctx, state.pac, KRB5_PAC_PRIVSVR_CHECKSUM,
2807 &checksum_data);
2808 if (ret == 0) {
2809 state.kdc_checksum = pletoh32(checksum_data.data);
2810 krb5_free_data_contents(krb5_ctx, &checksum_data);
2812 ret = krb5_pac_get_buffer(krb5_ctx, state.pac,
2813 __KRB5_PAC_TICKET_CHECKSUM,
2814 &ticket_checksum_data);
2815 if (ret == 0) {
2816 state.ticket_checksum_data = &ticket_checksum_data;
2817 state.ticket_checksum_type = pletoh32(ticket_checksum_data.data);
2819 ret = krb5_pac_get_buffer(krb5_ctx, state.pac,
2820 __KRB5_PAC_FULL_CHECKSUM,
2821 &full_checksum_data);
2822 if (ret == 0) {
2823 state.full_checksum_data = &full_checksum_data;
2824 state.full_checksum_type = pletoh32(full_checksum_data.data);
2827 read_keytab_file_from_preferences();
2829 wmem_map_foreach(kerberos_all_keys,
2830 verify_krb5_pac_try_server_key,
2831 &state);
2832 if (state.server_ek != NULL) {
2833 used_signing_key(tree, actx->pinfo, private_data,
2834 state.server_ek, pactvb,
2835 state.server_checksum, "Verified Server",
2836 "all_keys",
2837 wmem_map_size(kerberos_all_keys),
2838 state.server_count);
2839 } else {
2840 int keytype = keytype_for_cksumtype(state.server_checksum);
2841 missing_signing_key(tree, actx->pinfo, private_data,
2842 pactvb, state.server_checksum, keytype,
2843 "Missing Server",
2844 "all_keys",
2845 wmem_map_size(kerberos_all_keys),
2846 state.server_count);
2848 wmem_map_foreach(kerberos_longterm_keys,
2849 verify_krb5_pac_try_kdc_key,
2850 &state);
2851 if (state.kdc_ek != NULL) {
2852 used_signing_key(tree, actx->pinfo, private_data,
2853 state.kdc_ek, pactvb,
2854 state.kdc_checksum, "Verified KDC",
2855 "longterm_keys",
2856 wmem_map_size(kerberos_longterm_keys),
2857 state.kdc_count);
2858 } else {
2859 int keytype = keytype_for_cksumtype(state.kdc_checksum);
2860 missing_signing_key(tree, actx->pinfo, private_data,
2861 pactvb, state.kdc_checksum, keytype,
2862 "Missing KDC",
2863 "longterm_keys",
2864 wmem_map_size(kerberos_longterm_keys),
2865 state.kdc_count);
2868 if (state.ticket_checksum_type != 0) {
2869 verify_krb5_pac_ticket_checksum(tree, actx, pactvb, &state);
2872 if (state.ticket_checksum_data != NULL) {
2873 krb5_free_data_contents(krb5_ctx, &ticket_checksum_data);
2876 if (state.full_checksum_type != 0) {
2877 verify_krb5_pac_full_checksum(tree, actx, pactvb, &state);
2880 if (state.full_checksum_data != NULL) {
2881 krb5_free_data_contents(krb5_ctx, &full_checksum_data);
2884 krb5_pac_free(krb5_ctx, state.pac);
2886 #endif /* HAVE_KRB5_PAC_VERIFY */
2888 #elif defined(HAVE_HEIMDAL_KERBEROS)
2889 static krb5_context krb5_ctx;
2891 USES_APPLE_DEPRECATED_API
2893 static void
2894 krb5_fast_key(asn1_ctx_t *actx _U_, proto_tree *tree _U_, tvbuff_t *tvb _U_,
2895 enc_key_t *ek1 _U_, const char *p1 _U_,
2896 enc_key_t *ek2 _U_, const char *p2 _U_,
2897 const char *origin _U_)
2899 /* TODO: use krb5_crypto_fx_cf2() from Heimdal */
2901 void
2902 read_keytab_file(const char *filename)
2904 krb5_keytab keytab;
2905 krb5_error_code ret;
2906 krb5_keytab_entry key;
2907 krb5_kt_cursor cursor;
2908 enc_key_t *new_key;
2909 static bool first_time=true;
2911 if (filename == NULL || filename[0] == 0) {
2912 return;
2915 if(first_time){
2916 first_time=false;
2917 ret = krb5_init_context(&krb5_ctx);
2918 if(ret){
2919 return;
2923 /* should use a file in the wireshark users dir */
2924 ret = krb5_kt_resolve(krb5_ctx, filename, &keytab);
2925 if(ret){
2926 fprintf(stderr, "KERBEROS ERROR: Could not open keytab file :%s\n",filename);
2928 return;
2931 ret = krb5_kt_start_seq_get(krb5_ctx, keytab, &cursor);
2932 if(ret){
2933 fprintf(stderr, "KERBEROS ERROR: Could not read from keytab file :%s\n",filename);
2934 return;
2938 ret = krb5_kt_next_entry(krb5_ctx, keytab, &key, &cursor);
2939 if(ret==0){
2940 unsigned int i;
2941 char *pos;
2943 new_key = wmem_new0(wmem_epan_scope(), enc_key_t);
2944 new_key->fd_num = -1;
2945 new_key->id = ++kerberos_longterm_ids;
2946 snprintf(new_key->id_str, KRB_MAX_ID_STR_LEN, "keytab.%u", new_key->id);
2947 new_key->next = enc_key_list;
2949 /* generate origin string, describing where this key came from */
2950 pos=new_key->key_origin;
2951 pos+=MIN(KRB_MAX_ORIG_LEN,
2952 snprintf(pos, KRB_MAX_ORIG_LEN, "keytab principal "));
2953 for(i=0;i<key.principal->name.name_string.len;i++){
2954 pos+=MIN(KRB_MAX_ORIG_LEN-(pos-new_key->key_origin),
2955 snprintf(pos, KRB_MAX_ORIG_LEN-(pos-new_key->key_origin), "%s%s",(i?"/":""),key.principal->name.name_string.val[i]));
2957 pos+=MIN(KRB_MAX_ORIG_LEN-(pos-new_key->key_origin),
2958 snprintf(pos, KRB_MAX_ORIG_LEN-(pos-new_key->key_origin), "@%s",key.principal->realm));
2959 *pos=0;
2960 new_key->keytype=key.keyblock.keytype;
2961 new_key->keylength=(int)key.keyblock.keyvalue.length;
2962 memcpy(new_key->keyvalue,
2963 key.keyblock.keyvalue.data,
2964 MIN((unsigned)key.keyblock.keyvalue.length, KRB_MAX_KEY_LENGTH));
2966 enc_key_list=new_key;
2967 ret = krb5_kt_free_entry(krb5_ctx, &key);
2968 if (ret) {
2969 fprintf(stderr, "KERBEROS ERROR: Could not release the entry: %d", ret);
2970 ret = 0; /* try to continue with the next entry */
2972 kerberos_key_map_insert(kerberos_longterm_keys, new_key);
2974 }while(ret==0);
2976 ret = krb5_kt_end_seq_get(krb5_ctx, keytab, &cursor);
2977 if(ret){
2978 fprintf(stderr, "KERBEROS ERROR: Could not release the keytab cursor: %d", ret);
2980 ret = krb5_kt_close(krb5_ctx, keytab);
2981 if(ret){
2982 fprintf(stderr, "KERBEROS ERROR: Could not close the key table handle: %d", ret);
2986 USES_APPLE_RST
2989 uint8_t *
2990 decrypt_krb5_data(proto_tree *tree _U_, packet_info *pinfo,
2991 int usage,
2992 tvbuff_t *cryptotvb,
2993 int keytype,
2994 int *datalen)
2996 kerberos_private_data_t *zero_private = kerberos_new_private_data(pinfo);
2997 krb5_error_code ret;
2998 krb5_data data;
2999 enc_key_t *ek;
3000 int length = tvb_captured_length(cryptotvb);
3001 const uint8_t *cryptotext = tvb_get_ptr(cryptotvb, 0, length);
3003 /* don't do anything if we are not attempting to decrypt data */
3004 if(!krb_decrypt){
3005 return NULL;
3008 /* make sure we have all the data we need */
3009 if (tvb_captured_length(cryptotvb) < tvb_reported_length(cryptotvb)) {
3010 return NULL;
3013 read_keytab_file_from_preferences();
3015 for(ek=enc_key_list;ek;ek=ek->next){
3016 krb5_keytab_entry key;
3017 krb5_crypto crypto;
3018 uint8_t *cryptocopy; /* workaround for pre-0.6.1 heimdal bug */
3020 /* shortcircuit and bail out if enctypes are not matching */
3021 if((keytype != -1) && (ek->keytype != keytype)) {
3022 continue;
3025 key.keyblock.keytype=ek->keytype;
3026 key.keyblock.keyvalue.length=ek->keylength;
3027 key.keyblock.keyvalue.data=ek->keyvalue;
3028 ret = krb5_crypto_init(krb5_ctx, &(key.keyblock), (krb5_enctype)ENCTYPE_NULL, &crypto);
3029 if(ret){
3030 return NULL;
3033 /* pre-0.6.1 versions of Heimdal would sometimes change
3034 the cryptotext data even when the decryption failed.
3035 This would obviously not work since we iterate over the
3036 keys. So just give it a copy of the crypto data instead.
3037 This has been seen for RC4-HMAC blobs.
3039 cryptocopy = (uint8_t *)wmem_memdup(pinfo->pool, cryptotext, length);
3040 ret = krb5_decrypt_ivec(krb5_ctx, crypto, usage,
3041 cryptocopy, length,
3042 &data,
3043 NULL);
3044 if((ret == 0) && (length>0)){
3045 char *user_data;
3047 used_encryption_key(tree, pinfo, zero_private,
3048 ek, usage, cryptotvb,
3049 "enc_key_list", 0, 0);
3051 krb5_crypto_destroy(krb5_ctx, crypto);
3052 /* return a private wmem_alloced blob to the caller */
3053 user_data = (char *)wmem_memdup(pinfo->pool, data.data, (unsigned)data.length);
3054 if (datalen) {
3055 *datalen = (int)data.length;
3057 return user_data;
3059 krb5_crypto_destroy(krb5_ctx, crypto);
3061 return NULL;
3064 #define NEED_DECRYPT_KRB5_KRB_CFX_DCE_NOOP 1
3066 #elif defined (HAVE_LIBNETTLE)
3068 #define SERVICE_KEY_SIZE (DES3_KEY_SIZE + 2)
3069 #define KEYTYPE_DES3_CBC_MD5 5 /* Currently the only one supported */
3071 typedef struct _service_key_t {
3072 uint16_t kvno;
3073 int keytype;
3074 int length;
3075 uint8_t *contents;
3076 char origin[KRB_MAX_ORIG_LEN+1];
3077 } service_key_t;
3078 GSList *service_key_list;
3081 static void
3082 add_encryption_key(packet_info *pinfo, int keytype, int keylength, const char *keyvalue, const char *origin)
3084 service_key_t *new_key;
3086 if(pinfo->fd->visited){
3087 return;
3090 new_key = g_malloc(sizeof(service_key_t));
3091 new_key->kvno = 0;
3092 new_key->keytype = keytype;
3093 new_key->length = keylength;
3094 new_key->contents = g_memdup2(keyvalue, keylength);
3095 snprintf(new_key->origin, KRB_MAX_ORIG_LEN, "%s learnt from frame %u", origin, pinfo->num);
3096 service_key_list = g_slist_append(service_key_list, (void *) new_key);
3099 static void
3100 save_encryption_key(tvbuff_t *tvb _U_, int offset _U_, int length _U_,
3101 asn1_ctx_t *actx _U_, proto_tree *tree _U_,
3102 int parent_hf_index _U_,
3103 int hf_index _U_)
3105 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
3106 const char *parent = proto_registrar_get_name(parent_hf_index);
3107 const char *element = proto_registrar_get_name(hf_index);
3108 char origin[KRB_MAX_ORIG_LEN] = { 0, };
3110 snprintf(origin, KRB_MAX_ORIG_LEN, "%s_%s", parent, element);
3112 add_encryption_key(actx->pinfo,
3113 private_data->key.keytype,
3114 private_data->key.keylength,
3115 private_data->key.keyvalue,
3116 origin);
3119 static void
3120 save_Authenticator_subkey(tvbuff_t *tvb, int offset, int length,
3121 asn1_ctx_t *actx, proto_tree *tree,
3122 int parent_hf_index,
3123 int hf_index)
3125 save_encryption_key(tvb, offset, length, actx, tree, parent_hf_index, hf_index);
3128 static void
3129 save_EncAPRepPart_subkey(tvbuff_t *tvb, int offset, int length,
3130 asn1_ctx_t *actx, proto_tree *tree,
3131 int parent_hf_index,
3132 int hf_index)
3134 save_encryption_key(tvb, offset, length, actx, tree, parent_hf_index, hf_index);
3137 static void
3138 save_EncKDCRepPart_key(tvbuff_t *tvb, int offset, int length,
3139 asn1_ctx_t *actx, proto_tree *tree,
3140 int parent_hf_index,
3141 int hf_index)
3143 save_encryption_key(tvb, offset, length, actx, tree, parent_hf_index, hf_index);
3146 static void
3147 save_EncTicketPart_key(tvbuff_t *tvb, int offset, int length,
3148 asn1_ctx_t *actx, proto_tree *tree,
3149 int parent_hf_index,
3150 int hf_index)
3152 save_encryption_key(tvb, offset, length, actx, tree, parent_hf_index, hf_index);
3155 static void
3156 save_KrbCredInfo_key(tvbuff_t *tvb, int offset, int length,
3157 asn1_ctx_t *actx, proto_tree *tree,
3158 int parent_hf_index,
3159 int hf_index)
3161 save_encryption_key(tvb, offset, length, actx, tree, parent_hf_index, hf_index);
3164 static void
3165 save_KrbFastResponse_strengthen_key(tvbuff_t *tvb _U_, int offset _U_, int length _U_,
3166 asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_)
3168 save_encryption_key(tvb, offset, length, actx, tree, hf_index);
3171 static void
3172 clear_keytab(void) {
3173 GSList *ske;
3174 service_key_t *sk;
3176 for(ske = service_key_list; ske != NULL; ske = g_slist_next(ske)){
3177 sk = (service_key_t *) ske->data;
3178 if (sk) {
3179 g_free(sk->contents);
3180 g_free(sk);
3183 g_slist_free(service_key_list);
3184 service_key_list = NULL;
3187 static void
3188 read_keytab_file(const char *service_key_file)
3190 FILE *skf;
3191 ws_statb64 st;
3192 service_key_t *sk;
3193 unsigned char buf[SERVICE_KEY_SIZE];
3194 int newline_skip = 0, count = 0;
3196 if (service_key_file != NULL && ws_stat64 (service_key_file, &st) == 0) {
3198 /* The service key file contains raw 192-bit (24 byte) 3DES keys.
3199 * There can be zero, one (\n), or two (\r\n) characters between
3200 * keys. Trailing characters are ignored.
3203 /* XXX We should support the standard keytab format instead */
3204 if (st.st_size > SERVICE_KEY_SIZE) {
3205 if ( (st.st_size % (SERVICE_KEY_SIZE + 1) == 0) ||
3206 (st.st_size % (SERVICE_KEY_SIZE + 1) == SERVICE_KEY_SIZE) ) {
3207 newline_skip = 1;
3208 } else if ( (st.st_size % (SERVICE_KEY_SIZE + 2) == 0) ||
3209 (st.st_size % (SERVICE_KEY_SIZE + 2) == SERVICE_KEY_SIZE) ) {
3210 newline_skip = 2;
3214 skf = ws_fopen(service_key_file, "rb");
3215 if (! skf) return;
3217 while (fread(buf, SERVICE_KEY_SIZE, 1, skf) == 1) {
3218 sk = g_malloc(sizeof(service_key_t));
3219 sk->kvno = buf[0] << 8 | buf[1];
3220 sk->keytype = KEYTYPE_DES3_CBC_MD5;
3221 sk->length = DES3_KEY_SIZE;
3222 sk->contents = g_memdup2(buf + 2, DES3_KEY_SIZE);
3223 snprintf(sk->origin, KRB_MAX_ORIG_LEN, "3DES service key file, key #%d, offset %ld", count, ftell(skf));
3224 service_key_list = g_slist_append(service_key_list, (void *) sk);
3225 if (fseek(skf, newline_skip, SEEK_CUR) < 0) {
3226 fprintf(stderr, "unable to seek...\n");
3227 fclose(skf);
3228 return;
3230 count++;
3232 fclose(skf);
3236 #define CONFOUNDER_PLUS_CHECKSUM 24
3238 uint8_t *
3239 decrypt_krb5_data(proto_tree *tree, packet_info *pinfo,
3240 int _U_ usage,
3241 tvbuff_t *cryptotvb,
3242 int keytype,
3243 int *datalen)
3245 tvbuff_t *encr_tvb;
3246 uint8_t *decrypted_data = NULL, *plaintext = NULL;
3247 uint8_t cls;
3248 bool pc;
3249 uint32_t tag, item_len, data_len;
3250 int id_offset, offset;
3251 uint8_t key[DES3_KEY_SIZE];
3252 uint8_t initial_vector[DES_BLOCK_SIZE];
3253 gcry_md_hd_t md5_handle;
3254 uint8_t *digest;
3255 uint8_t zero_fill[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
3256 uint8_t confounder[8];
3257 bool ind;
3258 GSList *ske;
3259 service_key_t *sk;
3260 struct des3_ctx ctx;
3261 int length = tvb_captured_length(cryptotvb);
3262 const uint8_t *cryptotext = tvb_get_ptr(cryptotvb, 0, length);
3265 /* don't do anything if we are not attempting to decrypt data */
3266 if(!krb_decrypt){
3267 return NULL;
3270 /* make sure we have all the data we need */
3271 if (tvb_captured_length(cryptotvb) < tvb_reported_length(cryptotvb)) {
3272 return NULL;
3275 if (keytype != KEYTYPE_DES3_CBC_MD5 || service_key_list == NULL) {
3276 return NULL;
3279 decrypted_data = wmem_alloc(pinfo->pool, length);
3280 for(ske = service_key_list; ske != NULL; ske = g_slist_next(ske)){
3281 bool do_continue = false;
3282 bool digest_ok;
3283 sk = (service_key_t *) ske->data;
3285 des_fix_parity(DES3_KEY_SIZE, key, sk->contents);
3287 memset(initial_vector, 0, DES_BLOCK_SIZE);
3288 des3_set_key(&ctx, key);
3289 cbc_decrypt(&ctx, des3_decrypt, DES_BLOCK_SIZE, initial_vector,
3290 length, decrypted_data, cryptotext);
3291 encr_tvb = tvb_new_real_data(decrypted_data, length, length);
3293 tvb_memcpy(encr_tvb, confounder, 0, 8);
3295 /* We have to pull the decrypted data length from the decrypted
3296 * content. If the key doesn't match or we otherwise get garbage,
3297 * an exception may get thrown while decoding the ASN.1 header.
3298 * Catch it, just in case.
3300 TRY {
3301 id_offset = get_ber_identifier(encr_tvb, CONFOUNDER_PLUS_CHECKSUM, &cls, &pc, &tag);
3302 offset = get_ber_length(encr_tvb, id_offset, &item_len, &ind);
3304 CATCH_BOUNDS_ERRORS {
3305 tvb_free(encr_tvb);
3306 do_continue = true;
3308 ENDTRY;
3310 if (do_continue) continue;
3312 data_len = item_len + offset - CONFOUNDER_PLUS_CHECKSUM;
3313 if ((int) item_len + offset > length) {
3314 tvb_free(encr_tvb);
3315 continue;
3318 if (gcry_md_open(&md5_handle, GCRY_MD_MD5, 0)) {
3319 return NULL;
3321 gcry_md_write(md5_handle, confounder, 8);
3322 gcry_md_write(md5_handle, zero_fill, 16);
3323 gcry_md_write(md5_handle, decrypted_data + CONFOUNDER_PLUS_CHECKSUM, data_len);
3324 digest = gcry_md_read(md5_handle, 0);
3326 digest_ok = (tvb_memeql (encr_tvb, 8, digest, HASH_MD5_LENGTH) == 0);
3327 gcry_md_close(md5_handle);
3328 if (digest_ok) {
3329 plaintext = (uint8_t* )tvb_memdup(pinfo->pool, encr_tvb, CONFOUNDER_PLUS_CHECKSUM, data_len);
3330 tvb_free(encr_tvb);
3332 if (datalen) {
3333 *datalen = data_len;
3335 return plaintext;
3337 tvb_free(encr_tvb);
3340 return NULL;
3343 #endif /* HAVE_MIT_KERBEROS / HAVE_HEIMDAL_KERBEROS / HAVE_LIBNETTLE */
3345 #ifdef NEED_DECRYPT_KRB5_KRB_CFX_DCE_NOOP
3346 tvbuff_t *
3347 decrypt_krb5_krb_cfx_dce(proto_tree *tree _U_,
3348 packet_info *pinfo _U_,
3349 int usage _U_,
3350 int keytype _U_,
3351 tvbuff_t *gssapi_header_tvb _U_,
3352 tvbuff_t *gssapi_encrypted_tvb _U_,
3353 tvbuff_t *gssapi_trailer_tvb _U_,
3354 tvbuff_t *checksum_tvb _U_)
3356 return NULL;
3358 #endif /* NEED_DECRYPT_KRB5_KRB_CFX_DCE_NOOP */
3360 #define INET6_ADDRLEN 16
3362 /* TCP Record Mark */
3363 #define KRB_RM_RESERVED 0x80000000U
3364 #define KRB_RM_RECLEN 0x7fffffffU
3366 #define KRB5_MSG_TICKET 1 /* Ticket */
3367 #define KRB5_MSG_AUTHENTICATOR 2 /* Authenticator */
3368 #define KRB5_MSG_ENC_TICKET_PART 3 /* EncTicketPart */
3369 #define KRB5_MSG_AS_REQ 10 /* AS-REQ type */
3370 #define KRB5_MSG_AS_REP 11 /* AS-REP type */
3371 #define KRB5_MSG_TGS_REQ 12 /* TGS-REQ type */
3372 #define KRB5_MSG_TGS_REP 13 /* TGS-REP type */
3373 #define KRB5_MSG_AP_REQ 14 /* AP-REQ type */
3374 #define KRB5_MSG_AP_REP 15 /* AP-REP type */
3375 #define KRB5_MSG_TGT_REQ 16 /* TGT-REQ type */
3376 #define KRB5_MSG_TGT_REP 17 /* TGT-REP type */
3378 #define KRB5_MSG_SAFE 20 /* KRB-SAFE type */
3379 #define KRB5_MSG_PRIV 21 /* KRB-PRIV type */
3380 #define KRB5_MSG_CRED 22 /* KRB-CRED type */
3381 #define KRB5_MSG_ENC_AS_REP_PART 25 /* EncASRepPart */
3382 #define KRB5_MSG_ENC_TGS_REP_PART 26 /* EncTGSRepPart */
3383 #define KRB5_MSG_ENC_AP_REP_PART 27 /* EncAPRepPart */
3384 #define KRB5_MSG_ENC_KRB_PRIV_PART 28 /* EncKrbPrivPart */
3385 #define KRB5_MSG_ENC_KRB_CRED_PART 29 /* EncKrbCredPart */
3386 #define KRB5_MSG_ERROR 30 /* KRB-ERROR type */
3388 #define KRB5_CHKSUM_GSSAPI 0x8003
3390 * For KERB_ENCTYPE_RC4_HMAC and KERB_ENCTYPE_RC4_HMAC_EXP, see
3392 * https://tools.ietf.org/html/draft-brezak-win2k-krb-rc4-hmac-04
3394 * unless it's expired.
3397 /* Principal name-type */
3398 #define KRB5_NT_UNKNOWN 0
3399 #define KRB5_NT_PRINCIPAL 1
3400 #define KRB5_NT_SRV_INST 2
3401 #define KRB5_NT_SRV_HST 3
3402 #define KRB5_NT_SRV_XHST 4
3403 #define KRB5_NT_UID 5
3404 #define KRB5_NT_X500_PRINCIPAL 6
3405 #define KRB5_NT_SMTP_NAME 7
3406 #define KRB5_NT_ENTERPRISE 10
3409 * MS specific name types, from
3411 * http://msdn.microsoft.com/library/en-us/security/security/kerb_external_name.asp
3413 #define KRB5_NT_MS_PRINCIPAL -128
3414 #define KRB5_NT_MS_PRINCIPAL_AND_SID -129
3415 #define KRB5_NT_ENT_PRINCIPAL_AND_SID -130
3416 #define KRB5_NT_PRINCIPAL_AND_SID -131
3417 #define KRB5_NT_SRV_INST_AND_SID -132
3419 /* error table constants */
3420 /* I prefixed the krb5_err.et constant names with KRB5_ET_ for these */
3421 #define KRB5_ET_KRB5KDC_ERR_NONE 0
3422 #define KRB5_ET_KRB5KDC_ERR_NAME_EXP 1
3423 #define KRB5_ET_KRB5KDC_ERR_SERVICE_EXP 2
3424 #define KRB5_ET_KRB5KDC_ERR_BAD_PVNO 3
3425 #define KRB5_ET_KRB5KDC_ERR_C_OLD_MAST_KVNO 4
3426 #define KRB5_ET_KRB5KDC_ERR_S_OLD_MAST_KVNO 5
3427 #define KRB5_ET_KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN 6
3428 #define KRB5_ET_KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN 7
3429 #define KRB5_ET_KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE 8
3430 #define KRB5_ET_KRB5KDC_ERR_NULL_KEY 9
3431 #define KRB5_ET_KRB5KDC_ERR_CANNOT_POSTDATE 10
3432 #define KRB5_ET_KRB5KDC_ERR_NEVER_VALID 11
3433 #define KRB5_ET_KRB5KDC_ERR_POLICY 12
3434 #define KRB5_ET_KRB5KDC_ERR_BADOPTION 13
3435 #define KRB5_ET_KRB5KDC_ERR_ETYPE_NOSUPP 14
3436 #define KRB5_ET_KRB5KDC_ERR_SUMTYPE_NOSUPP 15
3437 #define KRB5_ET_KRB5KDC_ERR_PADATA_TYPE_NOSUPP 16
3438 #define KRB5_ET_KRB5KDC_ERR_TRTYPE_NOSUPP 17
3439 #define KRB5_ET_KRB5KDC_ERR_CLIENT_REVOKED 18
3440 #define KRB5_ET_KRB5KDC_ERR_SERVICE_REVOKED 19
3441 #define KRB5_ET_KRB5KDC_ERR_TGT_REVOKED 20
3442 #define KRB5_ET_KRB5KDC_ERR_CLIENT_NOTYET 21
3443 #define KRB5_ET_KRB5KDC_ERR_SERVICE_NOTYET 22
3444 #define KRB5_ET_KRB5KDC_ERR_KEY_EXP 23
3445 #define KRB5_ET_KRB5KDC_ERR_PREAUTH_FAILED 24
3446 #define KRB5_ET_KRB5KDC_ERR_PREAUTH_REQUIRED 25
3447 #define KRB5_ET_KRB5KDC_ERR_SERVER_NOMATCH 26
3448 #define KRB5_ET_KRB5KDC_ERR_MUST_USE_USER2USER 27
3449 #define KRB5_ET_KRB5KDC_ERR_PATH_NOT_ACCEPTED 28
3450 #define KRB5_ET_KRB5KDC_ERR_SVC_UNAVAILABLE 29
3451 #define KRB5_ET_KRB5KRB_AP_ERR_BAD_INTEGRITY 31
3452 #define KRB5_ET_KRB5KRB_AP_ERR_TKT_EXPIRED 32
3453 #define KRB5_ET_KRB5KRB_AP_ERR_TKT_NYV 33
3454 #define KRB5_ET_KRB5KRB_AP_ERR_REPEAT 34
3455 #define KRB5_ET_KRB5KRB_AP_ERR_NOT_US 35
3456 #define KRB5_ET_KRB5KRB_AP_ERR_BADMATCH 36
3457 #define KRB5_ET_KRB5KRB_AP_ERR_SKEW 37
3458 #define KRB5_ET_KRB5KRB_AP_ERR_BADADDR 38
3459 #define KRB5_ET_KRB5KRB_AP_ERR_BADVERSION 39
3460 #define KRB5_ET_KRB5KRB_AP_ERR_MSG_TYPE 40
3461 #define KRB5_ET_KRB5KRB_AP_ERR_MODIFIED 41
3462 #define KRB5_ET_KRB5KRB_AP_ERR_BADORDER 42
3463 #define KRB5_ET_KRB5KRB_AP_ERR_ILL_CR_TKT 43
3464 #define KRB5_ET_KRB5KRB_AP_ERR_BADKEYVER 44
3465 #define KRB5_ET_KRB5KRB_AP_ERR_NOKEY 45
3466 #define KRB5_ET_KRB5KRB_AP_ERR_MUT_FAIL 46
3467 #define KRB5_ET_KRB5KRB_AP_ERR_BADDIRECTION 47
3468 #define KRB5_ET_KRB5KRB_AP_ERR_METHOD 48
3469 #define KRB5_ET_KRB5KRB_AP_ERR_BADSEQ 49
3470 #define KRB5_ET_KRB5KRB_AP_ERR_INAPP_CKSUM 50
3471 #define KRB5_ET_KRB5KDC_AP_PATH_NOT_ACCEPTED 51
3472 #define KRB5_ET_KRB5KRB_ERR_RESPONSE_TOO_BIG 52
3473 #define KRB5_ET_KRB5KRB_ERR_GENERIC 60
3474 #define KRB5_ET_KRB5KRB_ERR_FIELD_TOOLONG 61
3475 #define KRB5_ET_KDC_ERROR_CLIENT_NOT_TRUSTED 62
3476 #define KRB5_ET_KDC_ERROR_KDC_NOT_TRUSTED 63
3477 #define KRB5_ET_KDC_ERROR_INVALID_SIG 64
3478 #define KRB5_ET_KDC_ERR_KEY_TOO_WEAK 65
3479 #define KRB5_ET_KDC_ERR_CERTIFICATE_MISMATCH 66
3480 #define KRB5_ET_KRB_AP_ERR_NO_TGT 67
3481 #define KRB5_ET_KDC_ERR_WRONG_REALM 68
3482 #define KRB5_ET_KRB_AP_ERR_USER_TO_USER_REQUIRED 69
3483 #define KRB5_ET_KDC_ERR_CANT_VERIFY_CERTIFICATE 70
3484 #define KRB5_ET_KDC_ERR_INVALID_CERTIFICATE 71
3485 #define KRB5_ET_KDC_ERR_REVOKED_CERTIFICATE 72
3486 #define KRB5_ET_KDC_ERR_REVOCATION_STATUS_UNKNOWN 73
3487 #define KRB5_ET_KDC_ERR_REVOCATION_STATUS_UNAVAILABLE 74
3488 #define KRB5_ET_KDC_ERR_CLIENT_NAME_MISMATCH 75
3489 #define KRB5_ET_KDC_ERR_KDC_NAME_MISMATCH 76
3490 #define KRB5_ET_KDC_ERR_PREAUTH_EXPIRED 90
3491 #define KRB5_ET_KDC_ERR_MORE_PREAUTH_DATA_REQUIRED 91
3492 #define KRB5_ET_KDC_ERR_PREAUTH_BAD_AUTHENTICATION_SET 92
3493 #define KRB5_ET_KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS 93
3495 static const value_string krb5_error_codes[] = {
3496 { KRB5_ET_KRB5KDC_ERR_NONE, "KRB5KDC_ERR_NONE" },
3497 { KRB5_ET_KRB5KDC_ERR_NAME_EXP, "KRB5KDC_ERR_NAME_EXP" },
3498 { KRB5_ET_KRB5KDC_ERR_SERVICE_EXP, "KRB5KDC_ERR_SERVICE_EXP" },
3499 { KRB5_ET_KRB5KDC_ERR_BAD_PVNO, "KRB5KDC_ERR_BAD_PVNO" },
3500 { KRB5_ET_KRB5KDC_ERR_C_OLD_MAST_KVNO, "KRB5KDC_ERR_C_OLD_MAST_KVNO" },
3501 { KRB5_ET_KRB5KDC_ERR_S_OLD_MAST_KVNO, "KRB5KDC_ERR_S_OLD_MAST_KVNO" },
3502 { KRB5_ET_KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN, "KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN" },
3503 { KRB5_ET_KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN, "KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN" },
3504 { KRB5_ET_KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE, "KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE" },
3505 { KRB5_ET_KRB5KDC_ERR_NULL_KEY, "KRB5KDC_ERR_NULL_KEY" },
3506 { KRB5_ET_KRB5KDC_ERR_CANNOT_POSTDATE, "KRB5KDC_ERR_CANNOT_POSTDATE" },
3507 { KRB5_ET_KRB5KDC_ERR_NEVER_VALID, "KRB5KDC_ERR_NEVER_VALID" },
3508 { KRB5_ET_KRB5KDC_ERR_POLICY, "KRB5KDC_ERR_POLICY" },
3509 { KRB5_ET_KRB5KDC_ERR_BADOPTION, "KRB5KDC_ERR_BADOPTION" },
3510 { KRB5_ET_KRB5KDC_ERR_ETYPE_NOSUPP, "KRB5KDC_ERR_ETYPE_NOSUPP" },
3511 { KRB5_ET_KRB5KDC_ERR_SUMTYPE_NOSUPP, "KRB5KDC_ERR_SUMTYPE_NOSUPP" },
3512 { KRB5_ET_KRB5KDC_ERR_PADATA_TYPE_NOSUPP, "KRB5KDC_ERR_PADATA_TYPE_NOSUPP" },
3513 { KRB5_ET_KRB5KDC_ERR_TRTYPE_NOSUPP, "KRB5KDC_ERR_TRTYPE_NOSUPP" },
3514 { KRB5_ET_KRB5KDC_ERR_CLIENT_REVOKED, "KRB5KDC_ERR_CLIENT_REVOKED" },
3515 { KRB5_ET_KRB5KDC_ERR_SERVICE_REVOKED, "KRB5KDC_ERR_SERVICE_REVOKED" },
3516 { KRB5_ET_KRB5KDC_ERR_TGT_REVOKED, "KRB5KDC_ERR_TGT_REVOKED" },
3517 { KRB5_ET_KRB5KDC_ERR_CLIENT_NOTYET, "KRB5KDC_ERR_CLIENT_NOTYET" },
3518 { KRB5_ET_KRB5KDC_ERR_SERVICE_NOTYET, "KRB5KDC_ERR_SERVICE_NOTYET" },
3519 { KRB5_ET_KRB5KDC_ERR_KEY_EXP, "KRB5KDC_ERR_KEY_EXP" },
3520 { KRB5_ET_KRB5KDC_ERR_PREAUTH_FAILED, "KRB5KDC_ERR_PREAUTH_FAILED" },
3521 { KRB5_ET_KRB5KDC_ERR_PREAUTH_REQUIRED, "KRB5KDC_ERR_PREAUTH_REQUIRED" },
3522 { KRB5_ET_KRB5KDC_ERR_SERVER_NOMATCH, "KRB5KDC_ERR_SERVER_NOMATCH" },
3523 { KRB5_ET_KRB5KDC_ERR_MUST_USE_USER2USER, "KRB5KDC_ERR_MUST_USE_USER2USER" },
3524 { KRB5_ET_KRB5KDC_ERR_PATH_NOT_ACCEPTED, "KRB5KDC_ERR_PATH_NOT_ACCEPTED" },
3525 { KRB5_ET_KRB5KDC_ERR_SVC_UNAVAILABLE, "KRB5KDC_ERR_SVC_UNAVAILABLE" },
3526 { KRB5_ET_KRB5KRB_AP_ERR_BAD_INTEGRITY, "KRB5KRB_AP_ERR_BAD_INTEGRITY" },
3527 { KRB5_ET_KRB5KRB_AP_ERR_TKT_EXPIRED, "KRB5KRB_AP_ERR_TKT_EXPIRED" },
3528 { KRB5_ET_KRB5KRB_AP_ERR_TKT_NYV, "KRB5KRB_AP_ERR_TKT_NYV" },
3529 { KRB5_ET_KRB5KRB_AP_ERR_REPEAT, "KRB5KRB_AP_ERR_REPEAT" },
3530 { KRB5_ET_KRB5KRB_AP_ERR_NOT_US, "KRB5KRB_AP_ERR_NOT_US" },
3531 { KRB5_ET_KRB5KRB_AP_ERR_BADMATCH, "KRB5KRB_AP_ERR_BADMATCH" },
3532 { KRB5_ET_KRB5KRB_AP_ERR_SKEW, "KRB5KRB_AP_ERR_SKEW" },
3533 { KRB5_ET_KRB5KRB_AP_ERR_BADADDR, "KRB5KRB_AP_ERR_BADADDR" },
3534 { KRB5_ET_KRB5KRB_AP_ERR_BADVERSION, "KRB5KRB_AP_ERR_BADVERSION" },
3535 { KRB5_ET_KRB5KRB_AP_ERR_MSG_TYPE, "KRB5KRB_AP_ERR_MSG_TYPE" },
3536 { KRB5_ET_KRB5KRB_AP_ERR_MODIFIED, "KRB5KRB_AP_ERR_MODIFIED" },
3537 { KRB5_ET_KRB5KRB_AP_ERR_BADORDER, "KRB5KRB_AP_ERR_BADORDER" },
3538 { KRB5_ET_KRB5KRB_AP_ERR_ILL_CR_TKT, "KRB5KRB_AP_ERR_ILL_CR_TKT" },
3539 { KRB5_ET_KRB5KRB_AP_ERR_BADKEYVER, "KRB5KRB_AP_ERR_BADKEYVER" },
3540 { KRB5_ET_KRB5KRB_AP_ERR_NOKEY, "KRB5KRB_AP_ERR_NOKEY" },
3541 { KRB5_ET_KRB5KRB_AP_ERR_MUT_FAIL, "KRB5KRB_AP_ERR_MUT_FAIL" },
3542 { KRB5_ET_KRB5KRB_AP_ERR_BADDIRECTION, "KRB5KRB_AP_ERR_BADDIRECTION" },
3543 { KRB5_ET_KRB5KRB_AP_ERR_METHOD, "KRB5KRB_AP_ERR_METHOD" },
3544 { KRB5_ET_KRB5KRB_AP_ERR_BADSEQ, "KRB5KRB_AP_ERR_BADSEQ" },
3545 { KRB5_ET_KRB5KRB_AP_ERR_INAPP_CKSUM, "KRB5KRB_AP_ERR_INAPP_CKSUM" },
3546 { KRB5_ET_KRB5KDC_AP_PATH_NOT_ACCEPTED, "KRB5KDC_AP_PATH_NOT_ACCEPTED" },
3547 { KRB5_ET_KRB5KRB_ERR_RESPONSE_TOO_BIG, "KRB5KRB_ERR_RESPONSE_TOO_BIG"},
3548 { KRB5_ET_KRB5KRB_ERR_GENERIC, "KRB5KRB_ERR_GENERIC" },
3549 { KRB5_ET_KRB5KRB_ERR_FIELD_TOOLONG, "KRB5KRB_ERR_FIELD_TOOLONG" },
3550 { KRB5_ET_KDC_ERROR_CLIENT_NOT_TRUSTED, "KDC_ERROR_CLIENT_NOT_TRUSTED" },
3551 { KRB5_ET_KDC_ERROR_KDC_NOT_TRUSTED, "KDC_ERROR_KDC_NOT_TRUSTED" },
3552 { KRB5_ET_KDC_ERROR_INVALID_SIG, "KDC_ERROR_INVALID_SIG" },
3553 { KRB5_ET_KDC_ERR_KEY_TOO_WEAK, "KDC_ERR_KEY_TOO_WEAK" },
3554 { KRB5_ET_KDC_ERR_CERTIFICATE_MISMATCH, "KDC_ERR_CERTIFICATE_MISMATCH" },
3555 { KRB5_ET_KRB_AP_ERR_NO_TGT, "KRB_AP_ERR_NO_TGT" },
3556 { KRB5_ET_KDC_ERR_WRONG_REALM, "KDC_ERR_WRONG_REALM" },
3557 { KRB5_ET_KRB_AP_ERR_USER_TO_USER_REQUIRED, "KRB_AP_ERR_USER_TO_USER_REQUIRED" },
3558 { KRB5_ET_KDC_ERR_CANT_VERIFY_CERTIFICATE, "KDC_ERR_CANT_VERIFY_CERTIFICATE" },
3559 { KRB5_ET_KDC_ERR_INVALID_CERTIFICATE, "KDC_ERR_INVALID_CERTIFICATE" },
3560 { KRB5_ET_KDC_ERR_REVOKED_CERTIFICATE, "KDC_ERR_REVOKED_CERTIFICATE" },
3561 { KRB5_ET_KDC_ERR_REVOCATION_STATUS_UNKNOWN, "KDC_ERR_REVOCATION_STATUS_UNKNOWN" },
3562 { KRB5_ET_KDC_ERR_REVOCATION_STATUS_UNAVAILABLE, "KDC_ERR_REVOCATION_STATUS_UNAVAILABLE" },
3563 { KRB5_ET_KDC_ERR_CLIENT_NAME_MISMATCH, "KDC_ERR_CLIENT_NAME_MISMATCH" },
3564 { KRB5_ET_KDC_ERR_KDC_NAME_MISMATCH, "KDC_ERR_KDC_NAME_MISMATCH" },
3565 { KRB5_ET_KDC_ERR_PREAUTH_EXPIRED, "KDC_ERR_PREAUTH_EXPIRED" },
3566 { KRB5_ET_KDC_ERR_MORE_PREAUTH_DATA_REQUIRED, "KDC_ERR_MORE_PREAUTH_DATA_REQUIRED" },
3567 { KRB5_ET_KDC_ERR_PREAUTH_BAD_AUTHENTICATION_SET, "KDC_ERR_PREAUTH_BAD_AUTHENTICATION_SET" },
3568 { KRB5_ET_KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS, "KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS" },
3569 { 0, NULL }
3573 #define PAC_LOGON_INFO 1
3574 #define PAC_CREDENTIAL_TYPE 2
3575 #define PAC_SERVER_CHECKSUM 6
3576 #define PAC_PRIVSVR_CHECKSUM 7
3577 #define PAC_CLIENT_INFO_TYPE 10
3578 #define PAC_S4U_DELEGATION_INFO 11
3579 #define PAC_UPN_DNS_INFO 12
3580 #define PAC_CLIENT_CLAIMS_INFO 13
3581 #define PAC_DEVICE_INFO 14
3582 #define PAC_DEVICE_CLAIMS_INFO 15
3583 #define PAC_TICKET_CHECKSUM 16
3584 #define PAC_ATTRIBUTES_INFO 17
3585 #define PAC_REQUESTER_SID 18
3586 #define PAC_FULL_CHECKSUM 19
3587 static const value_string w2k_pac_types[] = {
3588 { PAC_LOGON_INFO , "Logon Info" },
3589 { PAC_CREDENTIAL_TYPE , "Credential Type" },
3590 { PAC_SERVER_CHECKSUM , "Server Checksum" },
3591 { PAC_PRIVSVR_CHECKSUM , "Privsvr Checksum" },
3592 { PAC_CLIENT_INFO_TYPE , "Client Info Type" },
3593 { PAC_S4U_DELEGATION_INFO , "S4U Delegation Info" },
3594 { PAC_UPN_DNS_INFO , "UPN DNS Info" },
3595 { PAC_CLIENT_CLAIMS_INFO , "Client Claims Info" },
3596 { PAC_DEVICE_INFO , "Device Info" },
3597 { PAC_DEVICE_CLAIMS_INFO , "Device Claims Info" },
3598 { PAC_TICKET_CHECKSUM , "Ticket Checksum" },
3599 { PAC_ATTRIBUTES_INFO , "Attributes Info" },
3600 { PAC_REQUESTER_SID , "Requester Sid" },
3601 { PAC_FULL_CHECKSUM , "Full Checksum" },
3602 { 0, NULL },
3605 static const value_string krb5_msg_types[] = {
3606 { KRB5_MSG_TICKET, "Ticket" },
3607 { KRB5_MSG_AUTHENTICATOR, "Authenticator" },
3608 { KRB5_MSG_ENC_TICKET_PART, "EncTicketPart" },
3609 { KRB5_MSG_TGS_REQ, "TGS-REQ" },
3610 { KRB5_MSG_TGS_REP, "TGS-REP" },
3611 { KRB5_MSG_AS_REQ, "AS-REQ" },
3612 { KRB5_MSG_AS_REP, "AS-REP" },
3613 { KRB5_MSG_AP_REQ, "AP-REQ" },
3614 { KRB5_MSG_AP_REP, "AP-REP" },
3615 { KRB5_MSG_TGT_REQ, "TGT-REQ" },
3616 { KRB5_MSG_TGT_REP, "TGT-REP" },
3617 { KRB5_MSG_SAFE, "KRB-SAFE" },
3618 { KRB5_MSG_PRIV, "KRB-PRIV" },
3619 { KRB5_MSG_CRED, "KRB-CRED" },
3620 { KRB5_MSG_ENC_AS_REP_PART, "EncASRepPart" },
3621 { KRB5_MSG_ENC_TGS_REP_PART, "EncTGSRepPart" },
3622 { KRB5_MSG_ENC_AP_REP_PART, "EncAPRepPart" },
3623 { KRB5_MSG_ENC_KRB_PRIV_PART, "EncKrbPrivPart" },
3624 { KRB5_MSG_ENC_KRB_CRED_PART, "EncKrbCredPart" },
3625 { KRB5_MSG_ERROR, "KRB-ERROR" },
3626 { 0, NULL },
3629 #define KRB5_GSS_C_DELEG_FLAG 0x00000001
3630 #define KRB5_GSS_C_MUTUAL_FLAG 0x00000002
3631 #define KRB5_GSS_C_REPLAY_FLAG 0x00000004
3632 #define KRB5_GSS_C_SEQUENCE_FLAG 0x00000008
3633 #define KRB5_GSS_C_CONF_FLAG 0x00000010
3634 #define KRB5_GSS_C_INTEG_FLAG 0x00000020
3635 #define KRB5_GSS_C_DCE_STYLE 0x00001000
3637 static const true_false_string tfs_gss_flags_deleg = {
3638 "Delegate credentials to remote peer",
3639 "Do NOT delegate"
3641 static const true_false_string tfs_gss_flags_mutual = {
3642 "Request that remote peer authenticates itself",
3643 "Mutual authentication NOT required"
3645 static const true_false_string tfs_gss_flags_replay = {
3646 "Enable replay protection for signed or sealed messages",
3647 "Do NOT enable replay protection"
3649 static const true_false_string tfs_gss_flags_sequence = {
3650 "Enable Out-of-sequence detection for sign or sealed messages",
3651 "Do NOT enable out-of-sequence detection"
3653 static const true_false_string tfs_gss_flags_conf = {
3654 "Confidentiality (sealing) may be invoked",
3655 "Do NOT use Confidentiality (sealing)"
3657 static const true_false_string tfs_gss_flags_integ = {
3658 "Integrity protection (signing) may be invoked",
3659 "Do NOT use integrity protection"
3662 static const true_false_string tfs_gss_flags_dce_style = {
3663 "DCE-STYLE",
3664 "Not using DCE-STYLE"
3667 static int dissect_kerberos_KRB5_SRP_PA_APPLICATIONS(bool implicit_tag, tvbuff_t *tvb, int offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index)
3669 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
3670 proto_item *pi1 = proto_item_get_parent(actx->created_item);
3671 proto_item *pi2 = proto_item_get_parent(pi1);
3672 int8_t ber_class;
3673 bool pc;
3674 int32_t tag;
3677 * dissect_ber_octet_string_wcb() always passes
3678 * implicit_tag=false, offset=0 and hf_index=-1
3680 ws_assert(implicit_tag == false);
3681 ws_assert(offset == 0);
3682 ws_assert(hf_index <= 0);
3684 get_ber_identifier(tvb, offset, &ber_class, &pc, &tag);
3685 if (ber_class != BER_CLASS_APP) {
3686 if (kerberos_private_is_kdc_req(private_data)) {
3687 goto unknown;
3689 if (private_data->errorcode != KRB5_ET_KRB5KDC_ERR_PREAUTH_REQUIRED) {
3690 goto unknown;
3693 proto_item_append_text(pi1, " KRB5_SRP_PA_ANNOUNCE");
3694 proto_item_append_text(pi2, ": KRB5_SRP_PA_ANNOUNCE");
3695 return dissect_kerberos_KRB5_SRP_PA_ANNOUNCE(implicit_tag, tvb, offset, actx, tree, hf_index);
3698 switch (tag) {
3699 case 0:
3700 proto_item_append_text(pi1, " KRB5_SRP_PA_INIT");
3701 proto_item_append_text(pi2, ": KRB5_SRP_PA_INIT");
3702 return dissect_kerberos_KRB5_SRP_PA_INIT(implicit_tag, tvb, offset, actx, tree, hf_index);
3703 case 1:
3704 proto_item_append_text(pi1, " KRB5_SRP_PA_SERVER_CHALLENGE");
3705 proto_item_append_text(pi2, ": KRB5_SRP_PA_SERVER_CHALLENGE");
3706 return dissect_kerberos_KRB5_SRP_PA_SERVER_CHALLENGE(implicit_tag, tvb, offset, actx, tree, hf_index);
3707 case 2:
3708 proto_item_append_text(pi1, " KRB5_SRP_PA_CLIENT_RESPONSE");
3709 proto_item_append_text(pi2, ": KRB5_SRP_PA_CLIENT_RESPONSE");
3710 return dissect_kerberos_KRB5_SRP_PA_CLIENT_RESPONSE(implicit_tag, tvb, offset, actx, tree, hf_index);
3711 case 3:
3712 proto_item_append_text(pi1, " KRB5_SRP_PA_SERVER_VERIFIER");
3713 proto_item_append_text(pi2, ": KRB5_SRP_PA_SERVER_VERIFIER");
3714 return dissect_kerberos_KRB5_SRP_PA_SERVER_VERIFIER(implicit_tag, tvb, offset, actx, tree, hf_index);
3715 default:
3716 break;
3719 unknown:
3720 proto_item_append_text(pi1, " KRB5_SRP_PA_UNKNOWN: ber_class:%u ber_pc=%u ber_tag:%"PRIu32"", ber_class, pc, tag);
3721 proto_item_append_text(pi2, ": KRB5_SRP_PA_UNKNOWN");
3722 return tvb_reported_length_remaining(tvb, offset);
3725 #ifdef HAVE_KERBEROS
3726 static uint8_t *
3727 decrypt_krb5_data_asn1(proto_tree *tree, asn1_ctx_t *actx,
3728 int usage, tvbuff_t *cryptotvb, int *datalen)
3730 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
3732 #ifdef HAVE_DECRYPT_KRB5_DATA_PRIVATE
3733 return decrypt_krb5_data_private(tree, actx->pinfo, private_data,
3734 usage, cryptotvb,
3735 private_data->etype,
3736 datalen);
3737 #else
3738 return decrypt_krb5_data(tree, actx->pinfo, usage, cryptotvb,
3739 private_data->etype, datalen);
3740 #endif
3743 static int
3744 dissect_krb5_decrypt_ticket_data (bool imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
3745 proto_tree *tree, int hf_index _U_)
3747 uint8_t *plaintext;
3748 int length;
3749 tvbuff_t *next_tvb;
3751 next_tvb=tvb_new_subset_remaining(tvb, offset);
3752 length=tvb_captured_length_remaining(tvb, offset);
3754 /* draft-ietf-krb-wg-kerberos-clarifications-05.txt :
3755 * 7.5.1
3756 * All Ticket encrypted parts use usage == 2
3758 plaintext=decrypt_krb5_data_asn1(tree, actx, 2, next_tvb, &length);
3760 if(plaintext){
3761 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
3762 tvbuff_t *last_ticket_enc_part_tvb = private_data->last_ticket_enc_part_tvb;
3763 enc_key_t *current_ticket_key = private_data->current_ticket_key;
3764 tvbuff_t *child_tvb;
3765 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
3767 /* Add the decrypted data to the data source list. */
3768 add_new_data_source(actx->pinfo, child_tvb, "Krb5 Ticket");
3770 private_data->last_ticket_enc_part_tvb = child_tvb;
3771 private_data->current_ticket_key = NULL;
3772 offset=dissect_kerberos_Applications(false, child_tvb, 0, actx , tree, /* hf_index*/ -1);
3773 private_data->current_ticket_key = current_ticket_key;
3774 private_data->last_ticket_enc_part_tvb = last_ticket_enc_part_tvb;
3776 return offset;
3779 static int
3780 dissect_krb5_decrypt_authenticator_data (bool imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
3781 proto_tree *tree, int hf_index _U_)
3783 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
3784 uint8_t *plaintext;
3785 int length;
3786 tvbuff_t *next_tvb;
3788 next_tvb=tvb_new_subset_remaining(tvb, offset);
3789 length=tvb_captured_length_remaining(tvb, offset);
3791 /* draft-ietf-krb-wg-kerberos-clarifications-05.txt :
3792 * 7.5.1
3793 * Authenticators are encrypted with usage
3794 * == 7 or
3795 * == 11
3797 * 7. TGS-REQ PA-TGS-REQ padata AP-REQ Authenticator
3798 * (includes TGS authenticator subkey), encrypted with the
3799 * TGS session key (section 5.5.1)
3800 * 11. AP-REQ Authenticator (includes application
3801 * authenticator subkey), encrypted with the application
3802 * session key (section 5.5.1)
3804 if (private_data->within_PA_TGS_REQ > 0) {
3805 plaintext=decrypt_krb5_data_asn1(tree, actx, 7, next_tvb, &length);
3806 } else {
3807 plaintext=decrypt_krb5_data_asn1(tree, actx, 11, next_tvb, &length);
3810 if(plaintext){
3811 tvbuff_t *child_tvb;
3812 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
3814 /* Add the decrypted data to the data source list. */
3815 add_new_data_source(actx->pinfo, child_tvb, "Krb5 Authenticator");
3817 offset=dissect_kerberos_Applications(false, child_tvb, 0, actx , tree, /* hf_index*/ -1);
3819 return offset;
3822 static int
3823 dissect_krb5_decrypt_authorization_data(bool imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
3824 proto_tree *tree, int hf_index _U_)
3826 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
3827 uint8_t *plaintext;
3828 int length;
3829 tvbuff_t *next_tvb;
3831 next_tvb=tvb_new_subset_remaining(tvb, offset);
3832 length=tvb_captured_length_remaining(tvb, offset);
3834 /* draft-ietf-krb-wg-kerberos-clarifications-05.txt :
3835 * 7.5.1
3836 * Authenticators are encrypted with usage
3837 * == 5 or
3838 * == 4
3840 * 4. TGS-REQ KDC-REQ-BODY AuthorizationData, encrypted with
3841 * the TGS session key (section 5.4.1)
3842 * 5. TGS-REQ KDC-REQ-BODY AuthorizationData, encrypted with
3843 * the TGS authenticator subkey (section 5.4.1)
3845 if (private_data->PA_TGS_REQ_subkey != NULL) {
3846 plaintext=decrypt_krb5_data_asn1(tree, actx, 5, next_tvb, &length);
3847 } else {
3848 plaintext=decrypt_krb5_data_asn1(tree, actx, 4, next_tvb, &length);
3851 if(plaintext){
3852 tvbuff_t *child_tvb;
3853 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
3855 /* Add the decrypted data to the data source list. */
3856 add_new_data_source(actx->pinfo, child_tvb, "Krb5 AuthorizationData");
3858 offset=dissect_kerberos_AuthorizationData(false, child_tvb, 0, actx , tree, /* hf_index*/ -1);
3860 return offset;
3863 static int
3864 dissect_krb5_decrypt_KDC_REP_data (bool imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
3865 proto_tree *tree, int hf_index _U_)
3867 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
3868 uint8_t *plaintext = NULL;
3869 int length;
3870 tvbuff_t *next_tvb;
3872 next_tvb=tvb_new_subset_remaining(tvb, offset);
3873 length=tvb_captured_length_remaining(tvb, offset);
3875 /* draft-ietf-krb-wg-kerberos-clarifications-05.txt :
3876 * 7.5.1
3877 * ASREP/TGSREP encryptedparts are encrypted with usage
3878 * == 3 or
3879 * == 8 or
3880 * == 9
3882 * 3. AS-REP encrypted part (includes TGS session key or
3883 * application session key), encrypted with the client key
3884 * (section 5.4.2)
3886 * 8. TGS-REP encrypted part (includes application session
3887 * key), encrypted with the TGS session key (section
3888 * 5.4.2)
3889 * 9. TGS-REP encrypted part (includes application session
3890 * key), encrypted with the TGS authenticator subkey
3891 * (section 5.4.2)
3893 * We currently don't have a way to find the TGS-REQ state
3894 * in order to check if an authenticator subkey was used.
3896 * But if we client used FAST and we got a strengthen_key,
3897 * we're sure an authenticator subkey was used.
3899 * Windows don't use an authenticator subkey without FAST,
3900 * but heimdal does.
3902 * For now try 8 before 9 in order to avoid overhead and false
3903 * positives for the 'kerberos.missing_keytype' filter in pure
3904 * windows captures.
3906 switch (private_data->msg_type) {
3907 case KERBEROS_APPLICATIONS_AS_REP:
3908 plaintext=decrypt_krb5_data_asn1(tree, actx, 3, next_tvb, &length);
3909 break;
3910 case KERBEROS_APPLICATIONS_TGS_REP:
3911 if (private_data->fast_strengthen_key != NULL) {
3912 plaintext=decrypt_krb5_data_asn1(tree, actx, 9, next_tvb, &length);
3913 } else {
3914 plaintext=decrypt_krb5_data_asn1(tree, actx, 8, next_tvb, &length);
3915 if(!plaintext){
3916 plaintext=decrypt_krb5_data_asn1(tree, actx, 9, next_tvb, &length);
3919 break;
3922 if(plaintext){
3923 tvbuff_t *child_tvb;
3924 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
3926 /* Add the decrypted data to the data source list. */
3927 add_new_data_source(actx->pinfo, child_tvb, "Krb5 KDC-REP");
3929 offset=dissect_kerberos_Applications(false, child_tvb, 0, actx , tree, /* hf_index*/ -1);
3931 return offset;
3934 static int
3935 dissect_krb5_decrypt_PA_ENC_TIMESTAMP (bool imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
3936 proto_tree *tree, int hf_index _U_)
3938 uint8_t *plaintext;
3939 int length;
3940 tvbuff_t *next_tvb;
3942 next_tvb=tvb_new_subset_remaining(tvb, offset);
3943 length=tvb_captured_length_remaining(tvb, offset);
3945 /* draft-ietf-krb-wg-kerberos-clarifications-05.txt :
3946 * 7.5.1
3947 * AS-REQ PA_ENC_TIMESTAMP are encrypted with usage
3948 * == 1
3950 plaintext=decrypt_krb5_data_asn1(tree, actx, 1, next_tvb, &length);
3952 if(plaintext){
3953 tvbuff_t *child_tvb;
3954 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
3956 /* Add the decrypted data to the data source list. */
3957 add_new_data_source(actx->pinfo, child_tvb, "Krb5 EncTimestamp");
3959 offset=dissect_kerberos_PA_ENC_TS_ENC(false, child_tvb, 0, actx , tree, /* hf_index*/ -1);
3961 return offset;
3964 static int
3965 dissect_krb5_decrypt_AP_REP_data (bool imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
3966 proto_tree *tree, int hf_index _U_)
3968 uint8_t *plaintext;
3969 int length;
3970 tvbuff_t *next_tvb;
3972 next_tvb=tvb_new_subset_remaining(tvb, offset);
3973 length=tvb_captured_length_remaining(tvb, offset);
3975 /* draft-ietf-krb-wg-kerberos-clarifications-05.txt :
3976 * 7.5.1
3977 * AP-REP are encrypted with usage == 12
3979 plaintext=decrypt_krb5_data_asn1(tree, actx, 12, next_tvb, &length);
3981 if(plaintext){
3982 tvbuff_t *child_tvb;
3983 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
3985 /* Add the decrypted data to the data source list. */
3986 add_new_data_source(actx->pinfo, child_tvb, "Krb5 AP-REP");
3988 offset=dissect_kerberos_Applications(false, child_tvb, 0, actx , tree, /* hf_index*/ -1);
3990 return offset;
3993 static int
3994 dissect_krb5_decrypt_PRIV_data (bool imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
3995 proto_tree *tree, int hf_index _U_)
3997 uint8_t *plaintext;
3998 int length;
3999 tvbuff_t *next_tvb;
4001 next_tvb=tvb_new_subset_remaining(tvb, offset);
4002 length=tvb_captured_length_remaining(tvb, offset);
4004 /* RFC4120 :
4005 * EncKrbPrivPart encrypted with usage
4006 * == 13
4008 plaintext=decrypt_krb5_data_asn1(tree, actx, 13, next_tvb, &length);
4010 if(plaintext){
4011 tvbuff_t *child_tvb;
4012 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
4014 /* Add the decrypted data to the data source list. */
4015 add_new_data_source(actx->pinfo, child_tvb, "Krb5 PRIV");
4017 offset=dissect_kerberos_Applications(false, child_tvb, 0, actx , tree, /* hf_index*/ -1);
4019 return offset;
4022 static int
4023 dissect_krb5_decrypt_CRED_data (bool imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
4024 proto_tree *tree, int hf_index _U_)
4026 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
4027 uint8_t *plaintext;
4028 int length;
4029 tvbuff_t *next_tvb;
4031 next_tvb=tvb_new_subset_remaining(tvb, offset);
4032 length=tvb_captured_length_remaining(tvb, offset);
4034 if (private_data->etype == 0) {
4035 offset=dissect_kerberos_Applications(false, next_tvb, 0, actx , tree, /* hf_index*/ -1);
4036 return offset;
4039 /* RFC4120 :
4040 * EncKrbCredPart encrypted with usage
4041 * == 14
4043 plaintext=decrypt_krb5_data_asn1(tree, actx, 14, next_tvb, &length);
4045 if(plaintext){
4046 tvbuff_t *child_tvb;
4047 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
4049 /* Add the decrypted data to the data source list. */
4050 add_new_data_source(actx->pinfo, child_tvb, "Krb5 CRED");
4052 offset=dissect_kerberos_Applications(false, child_tvb, 0, actx , tree, /* hf_index*/ -1);
4054 return offset;
4057 static int
4058 dissect_krb5_decrypt_KrbFastReq(bool imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
4059 proto_tree *tree, int hf_index _U_)
4061 uint8_t *plaintext;
4062 int length;
4063 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
4064 tvbuff_t *next_tvb;
4066 next_tvb=tvb_new_subset_remaining(tvb, offset);
4067 length=tvb_captured_length_remaining(tvb, offset);
4069 private_data->fast_armor_key = NULL;
4070 if (private_data->PA_FAST_ARMOR_AP_subkey != NULL) {
4071 krb5_fast_key(actx, tree, tvb,
4072 private_data->PA_FAST_ARMOR_AP_subkey,
4073 "subkeyarmor",
4074 private_data->PA_FAST_ARMOR_AP_key,
4075 "ticketarmor",
4076 "KrbFastReq_FAST_armorKey");
4077 if (private_data->PA_TGS_REQ_subkey != NULL) {
4078 enc_key_t *explicit_armor_key = private_data->last_added_key;
4081 * See [MS-KILE] 3.3.5.7.4 Compound Identity
4083 krb5_fast_key(actx, tree, tvb,
4084 explicit_armor_key,
4085 "explicitarmor",
4086 private_data->PA_TGS_REQ_subkey,
4087 "tgsarmor",
4088 "KrbFastReq_explicitArmorKey");
4090 private_data->fast_armor_key = private_data->last_added_key;
4091 } else if (private_data->PA_TGS_REQ_subkey != NULL) {
4092 krb5_fast_key(actx, tree, tvb,
4093 private_data->PA_TGS_REQ_subkey,
4094 "subkeyarmor",
4095 private_data->PA_TGS_REQ_key,
4096 "ticketarmor",
4097 "KrbFastReq_TGS_armorKey");
4098 private_data->fast_armor_key = private_data->last_added_key;
4101 /* RFC6113 :
4102 * KrbFastResponse encrypted with usage
4103 * KEY_USAGE_FAST_ENC 51
4105 plaintext=decrypt_krb5_data_asn1(tree, actx, KEY_USAGE_FAST_ENC,
4106 next_tvb, &length);
4108 if(plaintext){
4109 tvbuff_t *child_tvb;
4110 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
4112 /* Add the decrypted data to the data source list. */
4113 add_new_data_source(actx->pinfo, child_tvb, "Krb5 FastReq");
4115 offset=dissect_kerberos_KrbFastReq(false, child_tvb, 0, actx , tree, /* hf_index*/ -1);
4117 return offset;
4120 static int
4121 dissect_krb5_decrypt_KrbFastResponse(bool imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
4122 proto_tree *tree, int hf_index _U_)
4124 uint8_t *plaintext;
4125 int length;
4126 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
4127 tvbuff_t *next_tvb;
4129 next_tvb=tvb_new_subset_remaining(tvb, offset);
4130 length=tvb_captured_length_remaining(tvb, offset);
4133 * RFC6113 :
4134 * KrbFastResponse encrypted with usage
4135 * KEY_USAGE_FAST_REP 52
4137 plaintext=decrypt_krb5_data_asn1(tree, actx, KEY_USAGE_FAST_REP,
4138 next_tvb, &length);
4140 if(plaintext){
4141 tvbuff_t *child_tvb;
4142 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
4144 /* Add the decrypted data to the data source list. */
4145 add_new_data_source(actx->pinfo, child_tvb, "Krb5 FastRep");
4147 private_data->fast_armor_key = private_data->last_decryption_key;
4148 offset=dissect_kerberos_KrbFastResponse(false, child_tvb, 0, actx , tree, /* hf_index*/ -1);
4150 return offset;
4153 static int
4154 dissect_krb5_decrypt_EncryptedChallenge(bool imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
4155 proto_tree *tree, int hf_index _U_)
4157 uint8_t *plaintext;
4158 int length;
4159 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
4160 tvbuff_t *next_tvb;
4161 int usage = 0;
4162 const char *name = NULL;
4164 next_tvb=tvb_new_subset_remaining(tvb, offset);
4165 length=tvb_captured_length_remaining(tvb, offset);
4167 /* RFC6113 :
4168 * KEY_USAGE_ENC_CHALLENGE_CLIENT 54
4169 * KEY_USAGE_ENC_CHALLENGE_KDC 55
4171 if (kerberos_private_is_kdc_req(private_data)) {
4172 usage = KEY_USAGE_ENC_CHALLENGE_CLIENT;
4173 name = "Krb5 CHALLENGE_CLIENT";
4174 } else {
4175 usage = KEY_USAGE_ENC_CHALLENGE_KDC;
4176 name = "Krb5 CHALLENGE_KDC";
4178 plaintext=decrypt_krb5_data_asn1(tree, actx, usage, next_tvb, &length);
4180 if(plaintext){
4181 tvbuff_t *child_tvb;
4182 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
4184 /* Add the decrypted data to the data source list. */
4185 add_new_data_source(actx->pinfo, child_tvb, name);
4187 offset=dissect_kerberos_PA_ENC_TS_ENC(false, child_tvb, 0, actx , tree, /* hf_index*/ -1);
4189 return offset;
4191 #endif /* HAVE_KERBEROS */
4193 static int * const hf_krb_pa_supported_enctypes_fields[] = {
4194 &hf_krb_pa_supported_enctypes_des_cbc_crc,
4195 &hf_krb_pa_supported_enctypes_des_cbc_md5,
4196 &hf_krb_pa_supported_enctypes_rc4_hmac,
4197 &hf_krb_pa_supported_enctypes_aes128_cts_hmac_sha1_96,
4198 &hf_krb_pa_supported_enctypes_aes256_cts_hmac_sha1_96,
4199 &hf_krb_pa_supported_enctypes_aes256_cts_hmac_sha1_96_sk,
4200 &hf_krb_pa_supported_enctypes_fast_supported,
4201 &hf_krb_pa_supported_enctypes_compound_identity_supported,
4202 &hf_krb_pa_supported_enctypes_claims_supported,
4203 &hf_krb_pa_supported_enctypes_resource_sid_compression_disabled,
4204 NULL,
4207 static int
4208 dissect_kerberos_PA_SUPPORTED_ENCTYPES(bool implicit_tag _U_, tvbuff_t *tvb _U_,
4209 int offset _U_, asn1_ctx_t *actx _U_,
4210 proto_tree *tree _U_, int hf_index _U_)
4212 actx->created_item = proto_tree_add_bitmask(tree, tvb, offset,
4213 hf_krb_pa_supported_enctypes,
4214 ett_krb_pa_supported_enctypes,
4215 hf_krb_pa_supported_enctypes_fields,
4216 ENC_LITTLE_ENDIAN);
4217 offset += 4;
4219 return offset;
4222 static int * const hf_krb_ad_ap_options_fields[] = {
4223 &hf_krb_ad_ap_options_cbt,
4224 &hf_krb_ad_ap_options_unverified_target_name,
4225 NULL,
4229 static int
4230 dissect_kerberos_AD_AP_OPTIONS(bool implicit_tag _U_, tvbuff_t *tvb _U_,
4231 int offset _U_, asn1_ctx_t *actx _U_,
4232 proto_tree *tree _U_, int hf_index _U_)
4234 actx->created_item = proto_tree_add_bitmask(tree, tvb, offset,
4235 hf_krb_ad_ap_options,
4236 ett_krb_ad_ap_options,
4237 hf_krb_ad_ap_options_fields,
4238 ENC_LITTLE_ENDIAN);
4239 offset += 4;
4241 return offset;
4244 static int
4245 dissect_kerberos_AD_TARGET_PRINCIPAL(bool implicit_tag _U_, tvbuff_t *tvb _U_,
4246 int offset _U_, asn1_ctx_t *actx _U_,
4247 proto_tree *tree _U_, int hf_index _U_)
4249 int tp_offset, tp_len;
4250 uint16_t bc;
4252 bc = tvb_reported_length_remaining(tvb, offset);
4253 tp_offset = offset;
4254 tp_len = bc;
4255 proto_tree_add_item(tree, hf_krb_ad_target_principal, tvb,
4256 tp_offset, tp_len,
4257 ENC_UTF_16 | ENC_LITTLE_ENDIAN);
4259 return offset;
4262 /* Dissect a GSSAPI checksum as per RFC1964. This is NOT ASN.1 encoded.
4264 static int
4265 dissect_krb5_rfc1964_checksum(asn1_ctx_t *actx _U_, proto_tree *tree, tvbuff_t *tvb)
4267 int offset=0;
4268 uint32_t len;
4269 uint16_t dlglen;
4271 /* Length of Bnd field */
4272 len=tvb_get_letohl(tvb, offset);
4273 proto_tree_add_item(tree, hf_krb_gssapi_len, tvb, offset, 4, ENC_LITTLE_ENDIAN);
4274 offset += 4;
4276 /* Bnd field */
4277 proto_tree_add_item(tree, hf_krb_gssapi_bnd, tvb, offset, len, ENC_NA);
4278 offset += len;
4281 /* flags */
4282 proto_tree_add_item(tree, hf_krb_gssapi_c_flag_dce_style, tvb, offset, 4, ENC_LITTLE_ENDIAN);
4283 proto_tree_add_item(tree, hf_krb_gssapi_c_flag_integ, tvb, offset, 4, ENC_LITTLE_ENDIAN);
4284 proto_tree_add_item(tree, hf_krb_gssapi_c_flag_conf, tvb, offset, 4, ENC_LITTLE_ENDIAN);
4285 proto_tree_add_item(tree, hf_krb_gssapi_c_flag_sequence, tvb, offset, 4, ENC_LITTLE_ENDIAN);
4286 proto_tree_add_item(tree, hf_krb_gssapi_c_flag_replay, tvb, offset, 4, ENC_LITTLE_ENDIAN);
4287 proto_tree_add_item(tree, hf_krb_gssapi_c_flag_mutual, tvb, offset, 4, ENC_LITTLE_ENDIAN);
4288 proto_tree_add_item(tree, hf_krb_gssapi_c_flag_deleg, tvb, offset, 4, ENC_LITTLE_ENDIAN);
4289 offset += 4;
4291 /* the next fields are optional so we have to check that we have
4292 * more data in our buffers */
4293 if(tvb_reported_length_remaining(tvb, offset)<2){
4294 return offset;
4296 /* dlgopt identifier */
4297 proto_tree_add_item(tree, hf_krb_gssapi_dlgopt, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4298 offset += 2;
4300 if(tvb_reported_length_remaining(tvb, offset)<2){
4301 return offset;
4303 /* dlglen identifier */
4304 dlglen=tvb_get_letohs(tvb, offset);
4305 proto_tree_add_item(tree, hf_krb_gssapi_dlglen, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4306 offset += 2;
4308 if(dlglen!=tvb_reported_length_remaining(tvb, offset)){
4309 proto_tree_add_expert_format(tree, actx->pinfo, &ei_krb_gssapi_dlglen, tvb, 0, 0,
4310 "Error: DlgLen:%d is not the same as number of bytes remaining:%d", dlglen, tvb_captured_length_remaining(tvb, offset));
4311 return offset;
4314 /* this should now be a KRB_CRED message */
4315 offset=dissect_kerberos_Applications(false, tvb, offset, actx, tree, /* hf_index */ -1);
4317 return offset;
4320 static int
4321 dissect_krb5_PA_PROV_SRV_LOCATION(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_)
4323 offset=dissect_ber_GeneralString(actx, tree, tvb, offset, hf_krb_provsrv_location, NULL, 0);
4325 return offset;
4328 static int
4329 dissect_krb5_PW_SALT(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_)
4331 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
4332 int length;
4333 uint32_t nt_status = 0;
4334 uint32_t reserved = 0;
4335 uint32_t flags = 0;
4338 * Microsoft stores a special 12 byte blob here
4339 * [MS-KILE] 2.2.1 KERB-EXT-ERROR
4340 * uint32_t NT_status
4341 * uint32_t reserved (== 0)
4342 * uint32_t flags (at least 0x00000001 is set)
4344 length = tvb_reported_length_remaining(tvb, offset);
4345 if (length <= 0) {
4346 return offset;
4348 if (length != 12) {
4349 goto no_error;
4352 if (private_data->errorcode == 0) {
4353 goto no_error;
4356 nt_status = tvb_get_letohl(tvb, offset);
4357 reserved = tvb_get_letohl(tvb, offset + 4);
4358 flags = tvb_get_letohl(tvb, offset + 8);
4360 if (reserved != 0 || flags != 1 || !try_val_to_str_ext(nt_status, &NT_errors_ext)) {
4361 goto no_error;
4364 proto_tree_add_item(tree, hf_krb_ext_error_nt_status, tvb, offset, 4,
4365 ENC_LITTLE_ENDIAN);
4366 col_append_fstr(actx->pinfo->cinfo, COL_INFO,
4367 " NT Status: %s",
4368 val_to_str_ext(nt_status, &NT_errors_ext,
4369 "Unknown error code %#x"));
4370 offset += 4;
4372 proto_tree_add_item(tree, hf_krb_ext_error_reserved, tvb, offset, 4,
4373 ENC_LITTLE_ENDIAN);
4374 offset += 4;
4376 proto_tree_add_item(tree, hf_krb_ext_error_flags, tvb, offset, 4,
4377 ENC_LITTLE_ENDIAN);
4378 offset += 4;
4380 return offset;
4382 no_error:
4383 proto_tree_add_item(tree, hf_krb_pw_salt, tvb, offset, length, ENC_NA);
4384 offset += length;
4386 return offset;
4389 static int
4390 dissect_krb5_PAC_DREP(proto_tree *parent_tree, tvbuff_t *tvb, int offset, uint8_t *drep)
4392 proto_tree *tree;
4393 uint8_t val;
4395 tree = proto_tree_add_subtree(parent_tree, tvb, offset, 16, ett_krb_pac_drep, NULL, "DREP");
4397 val = tvb_get_uint8(tvb, offset);
4398 proto_tree_add_uint(tree, hf_dcerpc_drep_byteorder, tvb, offset, 1, val>>4);
4400 offset++;
4402 if (drep) {
4403 *drep = val;
4406 return offset;
4409 /* This might be some sort of header that MIDL generates when creating
4410 * marshalling/unmarshalling code for blobs that are not to be transported
4411 * ontop of DCERPC and where the DREP fields specifying things such as
4412 * endianess and similar are not available.
4414 static int
4415 dissect_krb5_PAC_NDRHEADERBLOB(proto_tree *parent_tree, tvbuff_t *tvb, int offset, uint8_t *drep, asn1_ctx_t *actx _U_)
4417 proto_tree *tree;
4419 tree = proto_tree_add_subtree(parent_tree, tvb, offset, 16, ett_krb_pac_midl_blob, NULL, "MES header");
4421 /* modified DREP field that is used for stuff that is transporetd ontop
4422 of non dcerpc
4424 proto_tree_add_item(tree, hf_krb_midl_version, tvb, offset, 1, ENC_LITTLE_ENDIAN);
4425 offset++;
4427 offset = dissect_krb5_PAC_DREP(tree, tvb, offset, drep);
4430 proto_tree_add_item(tree, hf_krb_midl_hdr_len, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4431 offset+=2;
4433 proto_tree_add_item(tree, hf_krb_midl_fill_bytes, tvb, offset, 4, ENC_LITTLE_ENDIAN);
4434 offset += 4;
4436 /* length of blob that follows */
4437 proto_tree_add_item(tree, hf_krb_midl_blob_len, tvb, offset, 8, ENC_LITTLE_ENDIAN);
4438 offset += 8;
4440 return offset;
4443 static int
4444 dissect_krb5_PAC_LOGON_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
4446 proto_item *item;
4447 proto_tree *tree;
4448 uint8_t drep[4] = { 0x10, 0x00, 0x00, 0x00}; /* fake DREP struct */
4449 /* fake dcerpc_info struct */
4450 dcerpc_call_value call_data = { .flags = 0, };
4451 dcerpc_info di = { .ptype = UINT8_MAX, .call_data = &call_data, };
4453 item = proto_tree_add_item(parent_tree, hf_krb_pac_logon_info, tvb, offset, -1, ENC_NA);
4454 tree = proto_item_add_subtree(item, ett_krb_pac_logon_info);
4456 /* skip the first 16 bytes, they are some magic created by the idl
4457 * compiler the first 4 bytes might be flags?
4459 offset = dissect_krb5_PAC_NDRHEADERBLOB(tree, tvb, offset, &drep[0], actx);
4461 /* the PAC_LOGON_INFO blob */
4462 init_ndr_pointer_list(&di);
4463 offset = dissect_ndr_pointer(tvb, offset, actx->pinfo, tree, &di, drep,
4464 netlogon_dissect_PAC_LOGON_INFO, NDR_POINTER_UNIQUE,
4465 "PAC_LOGON_INFO:", -1);
4466 free_ndr_pointer_list(&di);
4468 return offset;
4472 static int
4473 dissect_krb5_PAC_CREDENTIAL_DATA(proto_tree *parent_tree, tvbuff_t *tvb, int offset, packet_info *pinfo _U_)
4475 proto_tree_add_item(parent_tree, hf_krb_pac_credential_data, tvb, offset, -1, ENC_NA);
4477 return offset;
4480 static int
4481 dissect_krb5_PAC_CREDENTIAL_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx)
4483 proto_item *item;
4484 proto_tree *tree;
4485 uint8_t *plaintext = NULL;
4486 int plainlen = 0;
4487 int length = 0;
4488 #define KRB5_KU_OTHER_ENCRYPTED 16
4489 #ifdef HAVE_KERBEROS
4490 uint32_t etype;
4491 tvbuff_t *next_tvb;
4492 int usage = KRB5_KU_OTHER_ENCRYPTED;
4493 #endif
4495 item = proto_tree_add_item(parent_tree, hf_krb_pac_credential_info, tvb, offset, -1, ENC_NA);
4496 tree = proto_item_add_subtree(item, ett_krb_pac_credential_info);
4498 /* version */
4499 proto_tree_add_item(tree, hf_krb_pac_credential_info_version, tvb,
4500 offset, 4, ENC_LITTLE_ENDIAN);
4501 offset+=4;
4503 #ifdef HAVE_KERBEROS
4504 /* etype */
4505 etype = tvb_get_letohl(tvb, offset);
4506 #endif
4507 proto_tree_add_item(tree, hf_krb_pac_credential_info_etype, tvb,
4508 offset, 4, ENC_LITTLE_ENDIAN);
4509 offset+=4;
4511 #ifdef HAVE_KERBEROS
4512 /* data */
4513 next_tvb=tvb_new_subset_remaining(tvb, offset);
4514 length=tvb_captured_length_remaining(tvb, offset);
4516 plaintext=decrypt_krb5_data(tree, actx->pinfo, usage, next_tvb, (int)etype, &plainlen);
4517 #endif
4519 if (plaintext != NULL) {
4520 tvbuff_t *child_tvb;
4521 child_tvb = tvb_new_child_real_data(tvb, plaintext, plainlen, plainlen);
4523 /* Add the decrypted data to the data source list. */
4524 add_new_data_source(actx->pinfo, child_tvb, "Krb5 PAC_CREDENTIAL");
4526 dissect_krb5_PAC_CREDENTIAL_DATA(tree, child_tvb, 0, actx->pinfo);
4529 return offset + length;
4532 static int
4533 dissect_krb5_PAC_S4U_DELEGATION_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx)
4535 proto_item *item;
4536 proto_tree *tree;
4537 uint8_t drep[4] = { 0x10, 0x00, 0x00, 0x00}; /* fake DREP struct */
4538 /* fake dcerpc_info struct */
4539 dcerpc_call_value call_data = { .flags = 0, };
4540 dcerpc_info di = { .ptype = UINT8_MAX, .call_data = &call_data, };
4542 item = proto_tree_add_item(parent_tree, hf_krb_pac_s4u_delegation_info, tvb, offset, -1, ENC_NA);
4543 tree = proto_item_add_subtree(item, ett_krb_pac_s4u_delegation_info);
4545 /* skip the first 16 bytes, they are some magic created by the idl
4546 * compiler the first 4 bytes might be flags?
4548 offset = dissect_krb5_PAC_NDRHEADERBLOB(tree, tvb, offset, &drep[0], actx);
4550 /* the S4U_DELEGATION_INFO blob. See [MS-PAC] */
4551 init_ndr_pointer_list(&di);
4552 offset = dissect_ndr_pointer(tvb, offset, actx->pinfo, tree, &di, drep,
4553 netlogon_dissect_PAC_S4U_DELEGATION_INFO, NDR_POINTER_UNIQUE,
4554 "PAC_S4U_DELEGATION_INFO:", -1);
4555 free_ndr_pointer_list(&di);
4557 return offset;
4560 #define PAC_UPN_DNS_FLAG_CONSTRUCTED 0x00000001
4561 #define PAC_UPN_DNS_FLAG_HAS_SAM_NAME_AND_SID 0x00000002
4562 static const true_false_string tfs_krb_pac_upn_flag_upn_constructed = {
4563 "UPN Name is Constructed",
4564 "UPN Name is NOT Constructed",
4566 static const true_false_string tfs_krb_pac_upn_flag_has_sam_name_and_sid = {
4567 "SAM_NAME and SID are included",
4568 "SAM_NAME and SID are NOT included",
4570 static int * const hf_krb_pac_upn_flags_fields[] = {
4571 &hf_krb_pac_upn_flag_upn_constructed,
4572 &hf_krb_pac_upn_flag_has_sam_name_and_sid,
4573 NULL
4576 static int
4577 dissect_krb5_PAC_UPN_DNS_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
4579 #ifdef HAVE_KERBEROS
4580 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
4581 #endif /* HAVE_KERBEROS */
4582 proto_item *item;
4583 proto_tree *tree;
4584 uint16_t dns_offset, dns_len;
4585 uint16_t upn_offset, upn_len;
4586 uint16_t samaccountname_offset = 0, samaccountname_len = 0;
4587 uint16_t objectsid_offset = 0, objectsid_len = 0;
4588 char *sid_str = NULL;
4589 uint32_t flags;
4591 item = proto_tree_add_item(parent_tree, hf_krb_pac_upn_dns_info, tvb, offset, -1, ENC_NA);
4592 tree = proto_item_add_subtree(item, ett_krb_pac_upn_dns_info);
4594 /* upn */
4595 upn_len = tvb_get_letohs(tvb, offset);
4596 proto_tree_add_item(tree, hf_krb_pac_upn_upn_len, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4597 offset+=2;
4598 upn_offset = tvb_get_letohs(tvb, offset);
4599 proto_tree_add_item(tree, hf_krb_pac_upn_upn_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4600 offset+=2;
4602 /* dns */
4603 dns_len = tvb_get_letohs(tvb, offset);
4604 proto_tree_add_item(tree, hf_krb_pac_upn_dns_len, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4605 offset+=2;
4606 dns_offset = tvb_get_letohs(tvb, offset);
4607 proto_tree_add_item(tree, hf_krb_pac_upn_dns_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4608 offset+=2;
4610 /* flags */
4611 flags = tvb_get_letohl(tvb, offset);
4612 proto_tree_add_bitmask(tree, tvb, offset,
4613 hf_krb_pac_upn_flags,
4614 ett_krb_pac_upn_dns_info_flags,
4615 hf_krb_pac_upn_flags_fields,
4616 ENC_LITTLE_ENDIAN);
4617 offset+=4;
4619 if (flags & PAC_UPN_DNS_FLAG_HAS_SAM_NAME_AND_SID) {
4620 samaccountname_len = tvb_get_letohs(tvb, offset);
4621 proto_tree_add_item(tree, hf_krb_pac_upn_samaccountname_len, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4622 offset+=2;
4623 samaccountname_offset = tvb_get_letohs(tvb, offset);
4624 proto_tree_add_item(tree, hf_krb_pac_upn_samaccountname_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4625 offset+=2;
4627 objectsid_len = tvb_get_letohs(tvb, offset);
4628 proto_tree_add_item(tree, hf_krb_pac_upn_objectsid_len, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4629 offset+=2;
4630 objectsid_offset = tvb_get_letohs(tvb, offset);
4631 proto_tree_add_item(tree, hf_krb_pac_upn_objectsid_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4632 /* offset+=2; */
4635 /* upn */
4636 proto_tree_add_item(tree, hf_krb_pac_upn_upn_name, tvb, upn_offset, upn_len, ENC_UTF_16|ENC_LITTLE_ENDIAN);
4638 /* dns */
4639 proto_tree_add_item(tree, hf_krb_pac_upn_dns_name, tvb, dns_offset, dns_len, ENC_UTF_16|ENC_LITTLE_ENDIAN);
4641 /* samaccountname */
4642 if (samaccountname_offset != 0 && samaccountname_len != 0) {
4643 proto_tree_add_item(tree, hf_krb_pac_upn_samaccountname, tvb, samaccountname_offset, samaccountname_len, ENC_UTF_16|ENC_LITTLE_ENDIAN);
4645 /* objectsid */
4646 if (objectsid_offset != 0 && objectsid_len != 0) {
4647 tvbuff_t *sid_tvb;
4648 sid_tvb=tvb_new_subset_length(tvb, objectsid_offset, objectsid_len);
4649 dissect_nt_sid(sid_tvb, 0, tree, "objectSid", &sid_str, -1);
4652 #ifdef HAVE_KERBEROS
4653 if (private_data->current_ticket_key != NULL) {
4654 enc_key_t *ek = private_data->current_ticket_key;
4656 if (samaccountname_offset != 0 && samaccountname_len != 0) {
4657 ek->pac_names.account_name = tvb_get_string_enc(wmem_epan_scope(),
4658 tvb,
4659 samaccountname_offset,
4660 samaccountname_len,
4661 ENC_UTF_16|ENC_LITTLE_ENDIAN);
4662 } else {
4663 ek->pac_names.account_name = tvb_get_string_enc(wmem_epan_scope(),
4664 tvb,
4665 upn_offset,
4666 upn_len,
4667 ENC_UTF_16|ENC_LITTLE_ENDIAN);
4669 ek->pac_names.account_domain = tvb_get_string_enc(wmem_epan_scope(),
4670 tvb,
4671 dns_offset,
4672 dns_len,
4673 ENC_UTF_16|ENC_LITTLE_ENDIAN);
4674 if (sid_str != NULL) {
4675 ek->pac_names.account_sid = wmem_strdup(wmem_epan_scope(),
4676 sid_str);
4679 #endif /* HAVE_KERBEROS */
4681 return dns_offset;
4684 static int
4685 dissect_krb5_PAC_CLIENT_CLAIMS_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
4687 int length = tvb_captured_length_remaining(tvb, offset);
4689 if (length == 0) {
4690 return offset;
4693 proto_tree_add_item(parent_tree, hf_krb_pac_client_claims_info, tvb, offset, -1, ENC_NA);
4695 return offset;
4698 static int
4699 dissect_krb5_PAC_DEVICE_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
4701 #ifdef HAVE_KERBEROS
4702 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
4703 const char *device_sid = NULL;
4704 #endif /* HAVE_KERBEROS */
4705 proto_item *item;
4706 proto_tree *tree;
4707 uint8_t drep[4] = { 0x10, 0x00, 0x00, 0x00}; /* fake DREP struct */
4708 /* fake dcerpc_info struct */
4709 dcerpc_call_value call_data = { .flags = 0, };
4710 dcerpc_info di = { .ptype = UINT8_MAX, .call_data = &call_data, };
4712 #ifdef HAVE_KERBEROS
4713 if (private_data->current_ticket_key != NULL) {
4714 call_data.private_data = (void*)&device_sid;
4716 #endif /* HAVE_KERBEROS */
4718 item = proto_tree_add_item(parent_tree, hf_krb_pac_device_info, tvb, offset, -1, ENC_NA);
4719 tree = proto_item_add_subtree(item, ett_krb_pac_device_info);
4721 /* skip the first 16 bytes, they are some magic created by the idl
4722 * compiler the first 4 bytes might be flags?
4724 offset = dissect_krb5_PAC_NDRHEADERBLOB(tree, tvb, offset, &drep[0], actx);
4726 /* the PAC_DEVICE_INFO blob */
4727 init_ndr_pointer_list(&di);
4728 offset = dissect_ndr_pointer(tvb, offset, actx->pinfo, tree, &di, drep,
4729 netlogon_dissect_PAC_DEVICE_INFO, NDR_POINTER_UNIQUE,
4730 "PAC_DEVICE_INFO:", -1);
4731 free_ndr_pointer_list(&di);
4733 #ifdef HAVE_KERBEROS
4734 if (private_data->current_ticket_key != NULL) {
4735 enc_key_t *ek = private_data->current_ticket_key;
4738 * netlogon_dissect_PAC_DEVICE_INFO allocated on
4739 * wmem_epan_scope() for us
4741 ek->pac_names.device_sid = device_sid;
4743 #endif /* HAVE_KERBEROS */
4745 return offset;
4748 static int
4749 dissect_krb5_PAC_DEVICE_CLAIMS_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
4751 int length = tvb_captured_length_remaining(tvb, offset);
4753 if (length == 0) {
4754 return offset;
4757 proto_tree_add_item(parent_tree, hf_krb_pac_device_claims_info, tvb, offset, -1, ENC_NA);
4759 return offset;
4762 static int
4763 dissect_krb5_PAC_SERVER_CHECKSUM(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
4765 proto_item *item;
4766 proto_tree *tree;
4768 item = proto_tree_add_item(parent_tree, hf_krb_pac_server_checksum, tvb, offset, -1, ENC_NA);
4769 tree = proto_item_add_subtree(item, ett_krb_pac_server_checksum);
4771 /* signature type */
4772 proto_tree_add_item(tree, hf_krb_pac_signature_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
4773 offset+=4;
4775 /* signature data */
4776 proto_tree_add_item(tree, hf_krb_pac_signature_signature, tvb, offset, -1, ENC_NA);
4778 return offset;
4781 static int
4782 dissect_krb5_PAC_PRIVSVR_CHECKSUM(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
4784 proto_item *item;
4785 proto_tree *tree;
4787 item = proto_tree_add_item(parent_tree, hf_krb_pac_privsvr_checksum, tvb, offset, -1, ENC_NA);
4788 tree = proto_item_add_subtree(item, ett_krb_pac_privsvr_checksum);
4790 /* signature type */
4791 proto_tree_add_item(tree, hf_krb_pac_signature_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
4792 offset+=4;
4794 /* signature data */
4795 proto_tree_add_item(tree, hf_krb_pac_signature_signature, tvb, offset, -1, ENC_NA);
4797 return offset;
4800 static int
4801 dissect_krb5_PAC_CLIENT_INFO_TYPE(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
4803 proto_item *item;
4804 proto_tree *tree;
4805 uint16_t namelen;
4807 item = proto_tree_add_item(parent_tree, hf_krb_pac_client_info_type, tvb, offset, -1, ENC_NA);
4808 tree = proto_item_add_subtree(item, ett_krb_pac_client_info_type);
4810 /* clientid */
4811 dissect_nttime(tvb, tree, offset, hf_krb_pac_clientid, ENC_LITTLE_ENDIAN);
4812 offset+=8;
4814 /* name length */
4815 namelen=tvb_get_letohs(tvb, offset);
4816 proto_tree_add_uint(tree, hf_krb_pac_namelen, tvb, offset, 2, namelen);
4817 offset+=2;
4819 /* client name */
4820 proto_tree_add_item(tree, hf_krb_pac_clientname, tvb, offset, namelen, ENC_UTF_16|ENC_LITTLE_ENDIAN);
4821 offset+=namelen;
4823 return offset;
4826 static int
4827 dissect_krb5_PAC_TICKET_CHECKSUM(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
4829 proto_item *item;
4830 proto_tree *tree;
4832 item = proto_tree_add_item(parent_tree, hf_krb_pac_ticket_checksum, tvb, offset, -1, ENC_NA);
4833 tree = proto_item_add_subtree(item, ett_krb_pac_ticket_checksum);
4835 /* signature type */
4836 proto_tree_add_item(tree, hf_krb_pac_signature_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
4837 offset+=4;
4839 /* signature data */
4840 proto_tree_add_item(tree, hf_krb_pac_signature_signature, tvb, offset, -1, ENC_NA);
4842 return offset;
4845 #define PAC_ATTRIBUTE_FLAG_PAC_WAS_REQUESTED 0x00000001
4846 #define PAC_ATTRIBUTE_FLAG_PAC_WAS_GIVEN_IMPLICITLY 0x00000002
4847 static const true_false_string tfs_krb_pac_attributes_info_pac_was_requested = {
4848 "PAC was requested",
4849 "PAC was NOT requested",
4851 static const true_false_string tfs_krb_pac_attributes_info_pac_was_given_implicitly = {
4852 "PAC was given implicitly",
4853 "PAC was NOT given implicitly",
4855 static int * const hf_krb_pac_attributes_info_flags_fields[] = {
4856 &hf_krb_pac_attributes_info_flags_pac_was_requested,
4857 &hf_krb_pac_attributes_info_flags_pac_was_given_implicitly,
4858 NULL
4861 static int
4862 dissect_krb5_PAC_ATTRIBUTES_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
4864 proto_item *item;
4865 proto_tree *tree;
4867 item = proto_tree_add_item(parent_tree, hf_krb_pac_attributes_info, tvb, offset, -1, ENC_NA);
4868 tree = proto_item_add_subtree(item, ett_krb_pac_attributes_info);
4870 /* flags length*/
4871 proto_tree_add_item(tree, hf_krb_pac_attributes_info_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
4872 offset+=4;
4874 /* flags */
4875 proto_tree_add_bitmask(tree, tvb, offset,
4876 hf_krb_pac_attributes_info_flags,
4877 ett_krb_pac_attributes_info_flags,
4878 hf_krb_pac_attributes_info_flags_fields,
4879 ENC_LITTLE_ENDIAN);
4880 offset+=4;
4882 return offset;
4885 static int
4886 dissect_krb5_PAC_REQUESTER_SID(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
4888 proto_item *item;
4889 proto_tree *tree;
4891 item = proto_tree_add_item(parent_tree, hf_krb_pac_requester_sid, tvb, offset, -1, ENC_NA);
4892 tree = proto_item_add_subtree(item, ett_krb_pac_requester_sid);
4894 offset = dissect_nt_sid(tvb, offset, tree, "RequesterSid", NULL, -1);
4896 return offset;
4899 static int
4900 dissect_krb5_PAC_FULL_CHECKSUM(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
4902 proto_item *item;
4903 proto_tree *tree;
4905 item = proto_tree_add_item(parent_tree, hf_krb_pac_full_checksum, tvb, offset, -1, ENC_NA);
4906 tree = proto_item_add_subtree(item, ett_krb_pac_full_checksum);
4908 /* signature type */
4909 proto_tree_add_item(tree, hf_krb_pac_signature_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
4910 offset+=4;
4912 /* signature data */
4913 proto_tree_add_item(tree, hf_krb_pac_signature_signature, tvb, offset, -1, ENC_NA);
4915 return offset;
4918 static int
4919 dissect_krb5_AD_WIN2K_PAC_struct(proto_tree *tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx)
4921 uint32_t pac_type;
4922 uint32_t pac_size;
4923 uint32_t pac_offset;
4924 proto_item *it=NULL;
4925 proto_tree *tr=NULL;
4926 tvbuff_t *next_tvb;
4928 /* type of pac data */
4929 pac_type=tvb_get_letohl(tvb, offset);
4930 it=proto_tree_add_uint(tree, hf_krb_w2k_pac_type, tvb, offset, 4, pac_type);
4931 tr=proto_item_add_subtree(it, ett_krb_pac);
4933 offset += 4;
4935 /* size of pac data */
4936 pac_size=tvb_get_letohl(tvb, offset);
4937 proto_tree_add_uint(tr, hf_krb_w2k_pac_size, tvb, offset, 4, pac_size);
4938 offset += 4;
4940 /* offset to pac data */
4941 pac_offset=tvb_get_letohl(tvb, offset);
4942 proto_tree_add_uint(tr, hf_krb_w2k_pac_offset, tvb, offset, 4, pac_offset);
4943 offset += 8;
4945 next_tvb=tvb_new_subset_length_caplen(tvb, pac_offset, pac_size, pac_size);
4946 switch(pac_type){
4947 case PAC_LOGON_INFO:
4948 dissect_krb5_PAC_LOGON_INFO(tr, next_tvb, 0, actx);
4949 break;
4950 case PAC_CREDENTIAL_TYPE:
4951 dissect_krb5_PAC_CREDENTIAL_INFO(tr, next_tvb, 0, actx);
4952 break;
4953 case PAC_SERVER_CHECKSUM:
4954 dissect_krb5_PAC_SERVER_CHECKSUM(tr, next_tvb, 0, actx);
4955 break;
4956 case PAC_PRIVSVR_CHECKSUM:
4957 dissect_krb5_PAC_PRIVSVR_CHECKSUM(tr, next_tvb, 0, actx);
4958 break;
4959 case PAC_CLIENT_INFO_TYPE:
4960 dissect_krb5_PAC_CLIENT_INFO_TYPE(tr, next_tvb, 0, actx);
4961 break;
4962 case PAC_S4U_DELEGATION_INFO:
4963 dissect_krb5_PAC_S4U_DELEGATION_INFO(tr, next_tvb, 0, actx);
4964 break;
4965 case PAC_UPN_DNS_INFO:
4966 dissect_krb5_PAC_UPN_DNS_INFO(tr, next_tvb, 0, actx);
4967 break;
4968 case PAC_CLIENT_CLAIMS_INFO:
4969 dissect_krb5_PAC_CLIENT_CLAIMS_INFO(tr, next_tvb, 0, actx);
4970 break;
4971 case PAC_DEVICE_INFO:
4972 dissect_krb5_PAC_DEVICE_INFO(tr, next_tvb, 0, actx);
4973 break;
4974 case PAC_DEVICE_CLAIMS_INFO:
4975 dissect_krb5_PAC_DEVICE_CLAIMS_INFO(tr, next_tvb, 0, actx);
4976 break;
4977 case PAC_TICKET_CHECKSUM:
4978 dissect_krb5_PAC_TICKET_CHECKSUM(tr, next_tvb, 0, actx);
4979 break;
4980 case PAC_ATTRIBUTES_INFO:
4981 dissect_krb5_PAC_ATTRIBUTES_INFO(tr, next_tvb, 0, actx);
4982 break;
4983 case PAC_REQUESTER_SID:
4984 dissect_krb5_PAC_REQUESTER_SID(tr, next_tvb, 0, actx);
4985 break;
4986 case PAC_FULL_CHECKSUM:
4987 dissect_krb5_PAC_FULL_CHECKSUM(tr, next_tvb, 0, actx);
4988 break;
4990 default:
4991 break;
4993 return offset;
4996 static int
4997 dissect_krb5_AD_WIN2K_PAC(bool implicit_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index _U_)
4999 uint32_t entries;
5000 uint32_t version;
5001 uint32_t i;
5003 #if defined(HAVE_MIT_KERBEROS) && defined(HAVE_KRB5_PAC_VERIFY)
5004 verify_krb5_pac(tree, actx, tvb);
5005 #endif
5007 /* first in the PAC structure comes the number of entries */
5008 entries=tvb_get_letohl(tvb, offset);
5009 proto_tree_add_uint(tree, hf_krb_w2k_pac_entries, tvb, offset, 4, entries);
5010 offset += 4;
5012 /* second comes the version */
5013 version=tvb_get_letohl(tvb, offset);
5014 proto_tree_add_uint(tree, hf_krb_w2k_pac_version, tvb, offset, 4, version);
5015 offset += 4;
5017 for(i=0;i<entries;i++){
5018 offset=dissect_krb5_AD_WIN2K_PAC_struct(tree, tvb, offset, actx);
5021 return offset;
5024 static int dissect_kerberos_T_e_data_octets(bool implicit_tag, tvbuff_t *tvb, int offset, asn1_ctx_t *actx, proto_tree *tree, int hf_index)
5026 int8_t ber_class;
5027 bool pc;
5028 int32_t tag;
5029 int len_offset;
5030 uint32_t len;
5031 bool ind;
5032 int next_offset;
5035 * dissect_ber_octet_string_wcb() always passes
5036 * implicit_tag=false, offset=0 and hf_index=-1
5038 ws_assert(implicit_tag == false);
5039 ws_assert(offset == 0);
5040 ws_assert(hf_index <= 0);
5042 len_offset = get_ber_identifier(tvb, offset, &ber_class, &pc, &tag);
5043 if (ber_class != BER_CLASS_UNI || !pc || tag != BER_UNI_TAG_SEQUENCE) {
5044 goto unknown;
5046 next_offset = get_ber_length(tvb, len_offset, &len, &ind);
5047 if (len < 1) {
5048 goto unknown;
5050 get_ber_identifier(tvb, next_offset, &ber_class, &pc, &tag);
5051 if (ber_class == BER_CLASS_CON && pc && tag == 1) {
5052 return dissect_kerberos_PA_DATA(implicit_tag, tvb, offset, actx, tree, hf_index);
5054 if (ber_class == BER_CLASS_UNI && pc && tag == BER_UNI_TAG_SEQUENCE) {
5055 return dissect_kerberos_T_rEP_SEQUENCE_OF_PA_DATA(implicit_tag, tvb, offset, actx, tree, hf_index);
5057 unknown:
5058 return tvb_reported_length_remaining(tvb, offset);
5061 #include "packet-kerberos-fn.c"
5063 #ifdef HAVE_KERBEROS
5064 static const ber_sequence_t PA_ENC_TS_ENC_sequence[] = {
5065 { &hf_krb_patimestamp, BER_CLASS_CON, 0, 0, dissect_kerberos_KerberosTime },
5066 { &hf_krb_pausec , BER_CLASS_CON, 1, BER_FLAGS_OPTIONAL, dissect_kerberos_Microseconds },
5067 { NULL, 0, 0, 0, NULL }
5070 static int
5071 dissect_kerberos_PA_ENC_TS_ENC(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
5072 offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
5073 PA_ENC_TS_ENC_sequence, hf_index, ett_krb_pa_enc_ts_enc);
5074 return offset;
5077 static int
5078 dissect_kerberos_T_strengthen_key(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
5079 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
5080 int save_encryption_key_parent_hf_index = private_data->save_encryption_key_parent_hf_index;
5081 kerberos_key_save_fn saved_encryption_key_fn = private_data->save_encryption_key_fn;
5082 private_data->save_encryption_key_parent_hf_index = hf_kerberos_KrbFastResponse;
5083 #ifdef HAVE_KERBEROS
5084 private_data->save_encryption_key_fn = save_KrbFastResponse_strengthen_key;
5085 #endif
5086 offset = dissect_kerberos_EncryptionKey(implicit_tag, tvb, offset, actx, tree, hf_index);
5088 private_data->save_encryption_key_parent_hf_index = save_encryption_key_parent_hf_index;
5089 private_data->save_encryption_key_fn = saved_encryption_key_fn;
5090 return offset;
5093 static const ber_sequence_t KrbFastFinished_sequence[] = {
5094 { &hf_kerberos_timestamp , BER_CLASS_CON, 0, 0, dissect_kerberos_KerberosTime },
5095 { &hf_kerberos_usec , BER_CLASS_CON, 1, 0, dissect_kerberos_Microseconds },
5096 { &hf_kerberos_crealm , BER_CLASS_CON, 2, 0, dissect_kerberos_Realm },
5097 { &hf_kerberos_cname_01 , BER_CLASS_CON, 3, 0, dissect_kerberos_PrincipalName },
5098 { &hf_kerberos_ticket_checksum, BER_CLASS_CON, 4, 0, dissect_kerberos_Checksum },
5099 { NULL, 0, 0, 0, NULL }
5102 static int
5103 dissect_kerberos_KrbFastFinished(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
5104 offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
5105 KrbFastFinished_sequence, hf_index, ett_kerberos_KrbFastFinished);
5107 return offset;
5110 static const ber_sequence_t KrbFastResponse_sequence[] = {
5111 { &hf_kerberos_rEP_SEQUENCE_OF_PA_DATA, BER_CLASS_CON, 0, 0, dissect_kerberos_T_rEP_SEQUENCE_OF_PA_DATA },
5112 { &hf_kerberos_strengthen_key, BER_CLASS_CON, 1, BER_FLAGS_OPTIONAL, dissect_kerberos_T_strengthen_key },
5113 { &hf_kerberos_finished , BER_CLASS_CON, 2, BER_FLAGS_OPTIONAL, dissect_kerberos_KrbFastFinished },
5114 { &hf_kerberos_nonce , BER_CLASS_CON, 3, 0, dissect_kerberos_UInt32 },
5115 { NULL, 0, 0, 0, NULL }
5118 static int
5119 dissect_kerberos_KrbFastResponse(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
5120 offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
5121 KrbFastResponse_sequence, hf_index, ett_kerberos_KrbFastResponse);
5123 return offset;
5126 static const ber_sequence_t KrbFastReq_sequence[] = {
5127 { &hf_kerberos_fast_options, BER_CLASS_CON, 0, 0, dissect_kerberos_FastOptions },
5128 { &hf_kerberos_rEQ_SEQUENCE_OF_PA_DATA, BER_CLASS_CON, 1, 0, dissect_kerberos_T_rEQ_SEQUENCE_OF_PA_DATA },
5129 { &hf_kerberos_req_body , BER_CLASS_CON, 2, 0, dissect_kerberos_KDC_REQ_BODY },
5130 { NULL, 0, 0, 0, NULL }
5133 static int
5134 dissect_kerberos_KrbFastReq(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
5135 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
5136 struct _kerberos_PA_FX_FAST_REQUEST saved_stack = private_data->PA_FX_FAST_REQUEST;
5137 private_data->PA_FX_FAST_REQUEST = (struct _kerberos_PA_FX_FAST_REQUEST) { .defer = false, };
5138 offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
5139 KrbFastReq_sequence, hf_index, ett_kerberos_KrbFastReq);
5140 private_data->PA_FX_FAST_REQUEST = saved_stack;
5142 return offset;
5145 static int * const FastOptions_bits[] = {
5146 &hf_kerberos_FastOptions_reserved,
5147 &hf_kerberos_FastOptions_hide_client_names,
5148 &hf_kerberos_FastOptions_spare_bit2,
5149 &hf_kerberos_FastOptions_spare_bit3,
5150 &hf_kerberos_FastOptions_spare_bit4,
5151 &hf_kerberos_FastOptions_spare_bit5,
5152 &hf_kerberos_FastOptions_spare_bit6,
5153 &hf_kerberos_FastOptions_spare_bit7,
5154 &hf_kerberos_FastOptions_spare_bit8,
5155 &hf_kerberos_FastOptions_spare_bit9,
5156 &hf_kerberos_FastOptions_spare_bit10,
5157 &hf_kerberos_FastOptions_spare_bit11,
5158 &hf_kerberos_FastOptions_spare_bit12,
5159 &hf_kerberos_FastOptions_spare_bit13,
5160 &hf_kerberos_FastOptions_spare_bit14,
5161 &hf_kerberos_FastOptions_spare_bit15,
5162 &hf_kerberos_FastOptions_kdc_follow_referrals,
5163 NULL
5166 static int
5167 dissect_kerberos_FastOptions(bool implicit_tag _U_, tvbuff_t *tvb _U_, int offset _U_, asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_) {
5168 offset = dissect_ber_bitstring(implicit_tag, actx, tree, tvb, offset,
5169 FastOptions_bits, 17, hf_index, ett_kerberos_FastOptions,
5170 NULL);
5172 return offset;
5175 #endif /* HAVE_KERBEROS */
5177 /* Make wrappers around exported functions for now */
5179 dissect_krb5_Checksum(proto_tree *tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
5181 return dissect_kerberos_Checksum(false, tvb, offset, actx, tree, hf_kerberos_cksum);
5186 dissect_krb5_ctime(proto_tree *tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
5188 return dissect_kerberos_KerberosTime(false, tvb, offset, actx, tree, hf_kerberos_ctime);
5193 dissect_krb5_cname(proto_tree *tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
5195 return dissect_kerberos_PrincipalName(false, tvb, offset, actx, tree, hf_kerberos_cname);
5198 dissect_krb5_realm(proto_tree *tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
5200 return dissect_kerberos_Realm(false, tvb, offset, actx, tree, hf_kerberos_realm);
5203 struct kerberos_display_key_state {
5204 proto_tree *tree;
5205 packet_info *pinfo;
5206 expert_field *expindex;
5207 const char *name;
5208 tvbuff_t *tvb;
5209 int start;
5210 int length;
5213 static void
5214 #ifdef HAVE_KERBEROS
5215 kerberos_display_key(void *data, void *userdata)
5216 #else
5217 kerberos_display_key(void *data _U_, void *userdata _U_)
5218 #endif
5220 #ifdef HAVE_KERBEROS
5221 struct kerberos_display_key_state *state =
5222 (struct kerberos_display_key_state *)userdata;
5223 const enc_key_t *ek = (const enc_key_t *)data;
5224 proto_item *item = NULL;
5225 enc_key_t *sek = NULL;
5227 item = proto_tree_add_expert_format(state->tree,
5228 state->pinfo,
5229 state->expindex,
5230 state->tvb,
5231 state->start,
5232 state->length,
5233 "%s %s keytype %d (id=%s same=%u) (%02x%02x%02x%02x...)",
5234 state->name,
5235 ek->key_origin, ek->keytype,
5236 ek->id_str, ek->num_same,
5237 ek->keyvalue[0] & 0xFF, ek->keyvalue[1] & 0xFF,
5238 ek->keyvalue[2] & 0xFF, ek->keyvalue[3] & 0xFF);
5239 if (ek->src1 != NULL) {
5240 sek = ek->src1;
5241 expert_add_info_format(state->pinfo,
5242 item,
5243 state->expindex,
5244 "SRC1 %s keytype %d (id=%s same=%u) (%02x%02x%02x%02x...)",
5245 sek->key_origin, sek->keytype,
5246 sek->id_str, sek->num_same,
5247 sek->keyvalue[0] & 0xFF, sek->keyvalue[1] & 0xFF,
5248 sek->keyvalue[2] & 0xFF, sek->keyvalue[3] & 0xFF);
5250 if (ek->src2 != NULL) {
5251 sek = ek->src2;
5252 expert_add_info_format(state->pinfo,
5253 item,
5254 state->expindex,
5255 "SRC2 %s keytype %d (id=%s same=%u) (%02x%02x%02x%02x...)",
5256 sek->key_origin, sek->keytype,
5257 sek->id_str, sek->num_same,
5258 sek->keyvalue[0] & 0xFF, sek->keyvalue[1] & 0xFF,
5259 sek->keyvalue[2] & 0xFF, sek->keyvalue[3] & 0xFF);
5261 sek = ek->same_list;
5262 while (sek != NULL) {
5263 expert_add_info_format(state->pinfo,
5264 item,
5265 state->expindex,
5266 "%s %s keytype %d (id=%s same=%u) (%02x%02x%02x%02x...)",
5267 state->name,
5268 sek->key_origin, sek->keytype,
5269 sek->id_str, sek->num_same,
5270 sek->keyvalue[0] & 0xFF, sek->keyvalue[1] & 0xFF,
5271 sek->keyvalue[2] & 0xFF, sek->keyvalue[3] & 0xFF);
5272 sek = sek->same_list;
5274 #endif /* HAVE_KERBEROS */
5277 static const value_string KERB_LOGON_SUBMIT_TYPE[] = {
5278 { 2, "KerbInteractiveLogon" },
5279 { 6, "KerbSmartCardLogon" },
5280 { 7, "KerbWorkstationUnlockLogon" },
5281 { 8, "KerbSmartCardUnlockLogon" },
5282 { 9, "KerbProxyLogon" },
5283 { 10, "KerbTicketLogon" },
5284 { 11, "KerbTicketUnlockLogon" },
5285 { 12, "KerbS4ULogon" },
5286 { 13, "KerbCertificateLogon" },
5287 { 14, "KerbCertificateS4ULogon" },
5288 { 15, "KerbCertificateUnlockLogon" },
5289 { 0, NULL }
5293 #define KERB_LOGON_FLAG_ALLOW_EXPIRED_TICKET 0x1
5294 #define KERB_LOGON_FLAG_REDIRECTED 0x2
5296 static int* const ktl_flags_bits[] = {
5297 &hf_kerberos_KERB_TICKET_LOGON_FLAG_ALLOW_EXPIRED_TICKET,
5298 &hf_kerberos_KERB_TICKET_LOGON_FLAG_REDIRECTED,
5299 NULL
5303 dissect_kerberos_KERB_TICKET_LOGON(tvbuff_t *tvb, int offset, asn1_ctx_t *actx, proto_tree *tree)
5305 proto_item *item;
5306 proto_tree *subtree;
5307 uint32_t ServiceTicketLength;
5308 uint32_t TicketGrantingTicketLength;
5309 int orig_offset;
5311 if (tvb_captured_length(tvb) < 32)
5312 return offset;
5314 item = proto_tree_add_item(tree, hf_kerberos_KERB_TICKET_LOGON, tvb, offset, -1, ENC_NA);
5315 subtree = proto_item_add_subtree(item, ett_kerberos_KERB_TICKET_LOGON);
5317 proto_tree_add_item(subtree, hf_kerberos_KERB_TICKET_LOGON_MessageType, tvb, offset, 4,
5318 ENC_LITTLE_ENDIAN);
5319 offset+=4;
5321 proto_tree_add_bitmask(subtree, tvb, offset, hf_kerberos_KERB_TICKET_LOGON_Flags,
5322 ett_kerberos, ktl_flags_bits, ENC_LITTLE_ENDIAN);
5323 offset+=4;
5325 ServiceTicketLength = tvb_get_letohl(tvb, offset);
5326 proto_tree_add_item(subtree, hf_kerberos_KERB_TICKET_LOGON_ServiceTicketLength, tvb,
5327 offset, 4, ENC_LITTLE_ENDIAN);
5328 offset+=4;
5330 TicketGrantingTicketLength = tvb_get_letohl(tvb, offset);
5331 proto_tree_add_item(subtree, hf_kerberos_KERB_TICKET_LOGON_TicketGrantingTicketLength,
5332 tvb, offset, 4, ENC_LITTLE_ENDIAN);
5333 offset+=4;
5335 /* Skip two PUCHAR of ServiceTicket and TicketGrantingTicket */
5336 offset+=16;
5338 if (ServiceTicketLength == 0)
5339 return offset;
5341 orig_offset = offset;
5342 offset = dissect_kerberos_Ticket(false, tvb, offset, actx, subtree,
5343 hf_kerberos_KERB_TICKET_LOGON_ServiceTicket);
5345 if ((unsigned)(offset-orig_offset) != ServiceTicketLength)
5346 return offset;
5348 if (TicketGrantingTicketLength == 0)
5349 return offset;
5351 offset = dissect_kerberos_KRB_CRED(false, tvb, offset, actx, subtree,
5352 hf_kerberos_KERB_TICKET_LOGON_TicketGrantingTicket);
5354 if ((unsigned)(offset-orig_offset) != ServiceTicketLength + TicketGrantingTicketLength)
5355 return offset;
5357 return offset;
5360 static int
5361 dissect_kerberos_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5362 bool dci, bool do_col_protocol, bool have_rm,
5363 kerberos_callbacks *cb)
5365 volatile int offset = 0;
5366 proto_tree *volatile kerberos_tree = NULL;
5367 proto_item *volatile item = NULL;
5368 kerberos_private_data_t *private_data = NULL;
5369 asn1_ctx_t asn1_ctx;
5371 /* TCP record mark and length */
5372 uint32_t krb_rm = 0;
5373 int krb_reclen = 0;
5375 gbl_do_col_info=dci;
5377 if (have_rm) {
5378 krb_rm = tvb_get_ntohl(tvb, offset);
5379 krb_reclen = kerberos_rm_to_reclen(krb_rm);
5381 * What is a reasonable size limit?
5383 if (krb_reclen > 10 * 1024 * 1024) {
5384 return (-1);
5387 if (do_col_protocol) {
5388 col_set_str(pinfo->cinfo, COL_PROTOCOL, "KRB5");
5391 if (tree) {
5392 item = proto_tree_add_item(tree, proto_kerberos, tvb, 0, -1, ENC_NA);
5393 kerberos_tree = proto_item_add_subtree(item, ett_kerberos);
5396 show_krb_recordmark(kerberos_tree, tvb, offset, krb_rm);
5397 offset += 4;
5398 } else {
5399 /* Do some sanity checking here,
5400 * All krb5 packets start with a TAG class that is BER_CLASS_APP
5401 * and a tag value that is either of the values below:
5402 * If it doesn't look like kerberos, return 0 and let someone else have
5403 * a go at it.
5405 int8_t tmp_class;
5406 bool tmp_pc;
5407 int32_t tmp_tag;
5409 get_ber_identifier(tvb, offset, &tmp_class, &tmp_pc, &tmp_tag);
5410 if(tmp_class!=BER_CLASS_APP){
5411 return 0;
5413 switch(tmp_tag){
5414 case KRB5_MSG_TICKET:
5415 case KRB5_MSG_AUTHENTICATOR:
5416 case KRB5_MSG_ENC_TICKET_PART:
5417 case KRB5_MSG_AS_REQ:
5418 case KRB5_MSG_AS_REP:
5419 case KRB5_MSG_TGS_REQ:
5420 case KRB5_MSG_TGS_REP:
5421 case KRB5_MSG_AP_REQ:
5422 case KRB5_MSG_AP_REP:
5423 case KRB5_MSG_ENC_AS_REP_PART:
5424 case KRB5_MSG_ENC_TGS_REP_PART:
5425 case KRB5_MSG_ENC_AP_REP_PART:
5426 case KRB5_MSG_ENC_KRB_PRIV_PART:
5427 case KRB5_MSG_ENC_KRB_CRED_PART:
5428 case KRB5_MSG_SAFE:
5429 case KRB5_MSG_PRIV:
5430 case KRB5_MSG_ERROR:
5431 break;
5432 default:
5433 return 0;
5435 if (do_col_protocol) {
5436 col_set_str(pinfo->cinfo, COL_PROTOCOL, "KRB5");
5438 if (gbl_do_col_info) {
5439 col_clear(pinfo->cinfo, COL_INFO);
5441 if (tree) {
5442 item = proto_tree_add_item(tree, proto_kerberos, tvb, 0, -1, ENC_NA);
5443 kerberos_tree = proto_item_add_subtree(item, ett_kerberos);
5446 asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, true, pinfo);
5447 asn1_ctx.private_data = NULL;
5448 private_data = kerberos_get_private_data(&asn1_ctx);
5449 private_data->callbacks = cb;
5451 TRY {
5452 offset=dissect_kerberos_Applications(false, tvb, offset, &asn1_ctx , kerberos_tree, /* hf_index */ -1);
5453 } CATCH_BOUNDS_ERRORS {
5454 RETHROW;
5455 } ENDTRY;
5457 if (private_data->frame_rep != UINT32_MAX) {
5458 proto_item *tmp_item;
5460 tmp_item = proto_tree_add_uint(kerberos_tree, hf_krb_response_in, tvb, 0, 0, private_data->frame_rep);
5461 proto_item_set_generated(tmp_item);
5464 if (private_data->frame_req != UINT32_MAX) {
5465 proto_item *tmp_item;
5466 nstime_t t, deltat;
5468 tmp_item = proto_tree_add_uint(kerberos_tree, hf_krb_response_to, tvb, 0, 0, private_data->frame_req);
5469 proto_item_set_generated(tmp_item);
5471 t = pinfo->abs_ts;
5472 nstime_delta(&deltat, &t, &private_data->req_time);
5473 tmp_item = proto_tree_add_time(kerberos_tree, hf_krb_time, tvb, 0, 0, &deltat);
5474 proto_item_set_generated(tmp_item);
5477 if (kerberos_tree != NULL) {
5478 struct kerberos_display_key_state display_state = {
5479 .tree = kerberos_tree,
5480 .pinfo = pinfo,
5481 .expindex = &ei_kerberos_learnt_keytype,
5482 .name = "Provides",
5483 .tvb = tvb,
5486 wmem_list_foreach(private_data->learnt_keys,
5487 kerberos_display_key,
5488 &display_state);
5491 if (kerberos_tree != NULL) {
5492 struct kerberos_display_key_state display_state = {
5493 .tree = kerberos_tree,
5494 .pinfo = pinfo,
5495 .expindex = &ei_kerberos_missing_keytype,
5496 .name = "Missing",
5497 .tvb = tvb,
5500 wmem_list_foreach(private_data->missing_keys,
5501 kerberos_display_key,
5502 &display_state);
5505 if (kerberos_tree != NULL) {
5506 struct kerberos_display_key_state display_state = {
5507 .tree = kerberos_tree,
5508 .pinfo = pinfo,
5509 .expindex = &ei_kerberos_decrypted_keytype,
5510 .name = "Used",
5511 .tvb = tvb,
5514 wmem_list_foreach(private_data->decryption_keys,
5515 kerberos_display_key,
5516 &display_state);
5519 proto_item_set_len(item, offset);
5520 return offset;
5524 * Display the TCP record mark.
5526 void
5527 show_krb_recordmark(proto_tree *tree, tvbuff_t *tvb, int start, uint32_t krb_rm)
5529 int rec_len;
5530 proto_tree *rm_tree;
5532 if (tree == NULL)
5533 return;
5535 rec_len = kerberos_rm_to_reclen(krb_rm);
5536 rm_tree = proto_tree_add_subtree_format(tree, tvb, start, 4, ett_krb_recordmark, NULL,
5537 "Record Mark: %u %s", rec_len, plurality(rec_len, "byte", "bytes"));
5538 proto_tree_add_boolean(rm_tree, hf_krb_rm_reserved, tvb, start, 4, krb_rm);
5539 proto_tree_add_uint(rm_tree, hf_krb_rm_reclen, tvb, start, 4, krb_rm);
5543 dissect_kerberos_main(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, bool do_col_info, kerberos_callbacks *cb)
5545 return (dissect_kerberos_common(tvb, pinfo, tree, do_col_info, false, false, cb));
5548 uint32_t
5549 kerberos_output_keytype(void)
5551 return gbl_keytype;
5554 static int
5555 dissect_kerberos_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
5557 /* Some weird kerberos implementation apparently do krb4 on the krb5 port.
5558 Since all (except weirdo transarc krb4 stuff) use
5559 an opcode <=16 in the first byte, use this to see if it might
5560 be krb4.
5561 All krb5 commands start with an APPL tag and thus is >=0x60
5562 so if first byte is <=16 just blindly assume it is krb4 then
5564 if(tvb_captured_length(tvb) >= 1 && tvb_get_uint8(tvb, 0)<=0x10){
5565 if(krb4_handle){
5566 bool res;
5568 res=call_dissector_only(krb4_handle, tvb, pinfo, tree, NULL);
5569 return res;
5570 }else{
5571 return 0;
5576 return dissect_kerberos_common(tvb, pinfo, tree, true, true, false, NULL);
5580 kerberos_rm_to_reclen(unsigned krb_rm)
5582 return (krb_rm & KRB_RM_RECLEN);
5585 unsigned
5586 get_krb_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
5588 unsigned krb_rm;
5589 int pdulen;
5591 krb_rm = tvb_get_ntohl(tvb, offset);
5592 pdulen = kerberos_rm_to_reclen(krb_rm);
5593 return (pdulen + 4);
5595 static void
5596 kerberos_prefs_apply_cb(void) {
5597 #ifdef HAVE_LIBNETTLE
5598 clear_keytab();
5599 read_keytab_file(keytab_filename);
5600 #endif
5603 static int
5604 dissect_kerberos_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
5606 pinfo->fragmented = true;
5607 if (dissect_kerberos_common(tvb, pinfo, tree, true, true, true, NULL) < 0) {
5609 * The dissector failed to recognize this as a valid
5610 * Kerberos message. Mark it as a continuation packet.
5612 col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
5615 return tvb_captured_length(tvb);
5618 static int
5619 dissect_kerberos_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
5621 col_set_str(pinfo->cinfo, COL_PROTOCOL, "KRB5");
5622 col_clear(pinfo->cinfo, COL_INFO);
5624 tcp_dissect_pdus(tvb, pinfo, tree, krb_desegment, 4, get_krb_pdu_len,
5625 dissect_kerberos_tcp_pdu, data);
5626 return tvb_captured_length(tvb);
5629 /*--- proto_register_kerberos -------------------------------------------*/
5630 void proto_register_kerberos(void) {
5632 /* List of fields */
5634 static hf_register_info hf[] = {
5635 { &hf_krb_response_to,
5636 { "Response to", "kerberos.response_to", FT_FRAMENUM, BASE_NONE,
5637 FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0, "This packet is a response to the packet in this frame", HFILL }},
5638 { &hf_krb_response_in,
5639 { "Response in", "kerberos.response_in", FT_FRAMENUM, BASE_NONE,
5640 FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE), 0, "The response to this packet is in this packet", HFILL }},
5641 { &hf_krb_time,
5642 { "Time from request", "kerberos.time", FT_RELATIVE_TIME, BASE_NONE,
5643 NULL, 0, "Time between Request and Response for Kerberos KDC requests", HFILL }},
5644 { &hf_krb_rm_reserved, {
5645 "Reserved", "kerberos.rm.reserved", FT_BOOLEAN, 32,
5646 TFS(&tfs_set_notset), KRB_RM_RESERVED, "Record mark reserved bit", HFILL }},
5647 { &hf_krb_rm_reclen, {
5648 "Record Length", "kerberos.rm.length", FT_UINT32, BASE_DEC,
5649 NULL, KRB_RM_RECLEN, NULL, HFILL }},
5650 { &hf_krb_provsrv_location, {
5651 "PROVSRV Location", "kerberos.provsrv_location", FT_STRING, BASE_NONE,
5652 NULL, 0, "PacketCable PROV SRV Location", HFILL }},
5653 { &hf_krb_pw_salt,
5654 { "pw-salt", "kerberos.pw_salt", FT_BYTES, BASE_NONE,
5655 NULL, 0, NULL, HFILL }},
5656 { &hf_krb_ext_error_nt_status, /* we keep kerberos.smb.nt_status for compat reasons */
5657 { "NT Status", "kerberos.smb.nt_status", FT_UINT32, BASE_HEX|BASE_EXT_STRING,
5658 &NT_errors_ext, 0, "NT Status code", HFILL }},
5659 { &hf_krb_ext_error_reserved,
5660 { "Reserved", "kerberos.ext_error.reserved", FT_UINT32, BASE_HEX,
5661 NULL, 0, NULL, HFILL }},
5662 { &hf_krb_ext_error_flags,
5663 { "Flags", "kerberos.ext_error.flags", FT_UINT32, BASE_HEX,
5664 NULL, 0, NULL, HFILL }},
5665 { &hf_krb_address_ip, {
5666 "IP Address", "kerberos.addr_ip", FT_IPv4, BASE_NONE,
5667 NULL, 0, NULL, HFILL }},
5668 { &hf_krb_address_ipv6, {
5669 "IPv6 Address", "kerberos.addr_ipv6", FT_IPv6, BASE_NONE,
5670 NULL, 0, NULL, HFILL }},
5671 { &hf_krb_address_netbios, {
5672 "NetBIOS Address", "kerberos.addr_nb", FT_STRING, BASE_NONE,
5673 NULL, 0, "NetBIOS Address and type", HFILL }},
5674 { &hf_krb_gssapi_len, {
5675 "Length", "kerberos.gssapi.len", FT_UINT32, BASE_DEC,
5676 NULL, 0, "Length of GSSAPI Bnd field", HFILL }},
5677 { &hf_krb_gssapi_bnd, {
5678 "Bnd", "kerberos.gssapi.bdn", FT_BYTES, BASE_NONE,
5679 NULL, 0, "GSSAPI Bnd field", HFILL }},
5680 { &hf_krb_gssapi_c_flag_deleg, {
5681 "Deleg", "kerberos.gssapi.checksum.flags.deleg", FT_BOOLEAN, 32,
5682 TFS(&tfs_gss_flags_deleg), KRB5_GSS_C_DELEG_FLAG, NULL, HFILL }},
5683 { &hf_krb_gssapi_c_flag_mutual, {
5684 "Mutual", "kerberos.gssapi.checksum.flags.mutual", FT_BOOLEAN, 32,
5685 TFS(&tfs_gss_flags_mutual), KRB5_GSS_C_MUTUAL_FLAG, NULL, HFILL }},
5686 { &hf_krb_gssapi_c_flag_replay, {
5687 "Replay", "kerberos.gssapi.checksum.flags.replay", FT_BOOLEAN, 32,
5688 TFS(&tfs_gss_flags_replay), KRB5_GSS_C_REPLAY_FLAG, NULL, HFILL }},
5689 { &hf_krb_gssapi_c_flag_sequence, {
5690 "Sequence", "kerberos.gssapi.checksum.flags.sequence", FT_BOOLEAN, 32,
5691 TFS(&tfs_gss_flags_sequence), KRB5_GSS_C_SEQUENCE_FLAG, NULL, HFILL }},
5692 { &hf_krb_gssapi_c_flag_conf, {
5693 "Conf", "kerberos.gssapi.checksum.flags.conf", FT_BOOLEAN, 32,
5694 TFS(&tfs_gss_flags_conf), KRB5_GSS_C_CONF_FLAG, NULL, HFILL }},
5695 { &hf_krb_gssapi_c_flag_integ, {
5696 "Integ", "kerberos.gssapi.checksum.flags.integ", FT_BOOLEAN, 32,
5697 TFS(&tfs_gss_flags_integ), KRB5_GSS_C_INTEG_FLAG, NULL, HFILL }},
5698 { &hf_krb_gssapi_c_flag_dce_style, {
5699 "DCE-style", "kerberos.gssapi.checksum.flags.dce-style", FT_BOOLEAN, 32,
5700 TFS(&tfs_gss_flags_dce_style), KRB5_GSS_C_DCE_STYLE, NULL, HFILL }},
5701 { &hf_krb_gssapi_dlgopt, {
5702 "DlgOpt", "kerberos.gssapi.dlgopt", FT_UINT16, BASE_DEC,
5703 NULL, 0, "GSSAPI DlgOpt", HFILL }},
5704 { &hf_krb_gssapi_dlglen, {
5705 "DlgLen", "kerberos.gssapi.dlglen", FT_UINT16, BASE_DEC,
5706 NULL, 0, "GSSAPI DlgLen", HFILL }},
5707 { &hf_krb_midl_blob_len, {
5708 "Blob Length", "kerberos.midl_blob_len", FT_UINT64, BASE_DEC,
5709 NULL, 0, "Length of NDR encoded data that follows", HFILL }},
5710 { &hf_krb_midl_fill_bytes, {
5711 "Fill bytes", "kerberos.midl.fill_bytes", FT_UINT32, BASE_HEX,
5712 NULL, 0, "Just some fill bytes", HFILL }},
5713 { &hf_krb_midl_version, {
5714 "Version", "kerberos.midl.version", FT_UINT8, BASE_DEC,
5715 NULL, 0, "Version of pickling", HFILL }},
5716 { &hf_krb_midl_hdr_len, {
5717 "HDR Length", "kerberos.midl.hdr_len", FT_UINT16, BASE_DEC,
5718 NULL, 0, "Length of header", HFILL }},
5719 { &hf_krb_pac_signature_type, {
5720 "Type", "kerberos.pac.signature.type", FT_INT32, BASE_DEC,
5721 NULL, 0, "PAC Signature Type", HFILL }},
5722 { &hf_krb_pac_signature_signature, {
5723 "Signature", "kerberos.pac.signature.signature", FT_BYTES, BASE_NONE,
5724 NULL, 0, "A PAC signature blob", HFILL }},
5725 { &hf_krb_w2k_pac_entries, {
5726 "Num Entries", "kerberos.pac.entries", FT_UINT32, BASE_DEC,
5727 NULL, 0, "Number of W2k PAC entries", HFILL }},
5728 { &hf_krb_w2k_pac_version, {
5729 "Version", "kerberos.pac.version", FT_UINT32, BASE_DEC,
5730 NULL, 0, "Version of PAC structures", HFILL }},
5731 { &hf_krb_w2k_pac_type, {
5732 "Type", "kerberos.pac.type", FT_UINT32, BASE_DEC,
5733 VALS(w2k_pac_types), 0, "Type of W2k PAC entry", HFILL }},
5734 { &hf_krb_w2k_pac_size, {
5735 "Size", "kerberos.pac.size", FT_UINT32, BASE_DEC,
5736 NULL, 0, "Size of W2k PAC entry", HFILL }},
5737 { &hf_krb_w2k_pac_offset, {
5738 "Offset", "kerberos.pac.offset", FT_UINT32, BASE_DEC,
5739 NULL, 0, "Offset to W2k PAC entry", HFILL }},
5740 { &hf_krb_pac_clientid, {
5741 "ClientID", "kerberos.pac.clientid", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL,
5742 NULL, 0, "ClientID Timestamp", HFILL }},
5743 { &hf_krb_pac_namelen, {
5744 "Name Length", "kerberos.pac.namelen", FT_UINT16, BASE_DEC,
5745 NULL, 0, "Length of client name", HFILL }},
5746 { &hf_krb_pac_clientname, {
5747 "Name", "kerberos.pac.name", FT_STRING, BASE_NONE,
5748 NULL, 0, "Name of the Client in the PAC structure", HFILL }},
5749 { &hf_krb_pac_logon_info, {
5750 "PAC_LOGON_INFO", "kerberos.pac_logon_info", FT_BYTES, BASE_NONE,
5751 NULL, 0, "PAC_LOGON_INFO structure", HFILL }},
5752 { &hf_krb_pac_credential_data, {
5753 "PAC_CREDENTIAL_DATA", "kerberos.pac_credential_data", FT_BYTES, BASE_NONE,
5754 NULL, 0, "PAC_CREDENTIAL_DATA structure", HFILL }},
5755 { &hf_krb_pac_credential_info, {
5756 "PAC_CREDENTIAL_INFO", "kerberos.pac_credential_info", FT_BYTES, BASE_NONE,
5757 NULL, 0, "PAC_CREDENTIAL_INFO structure", HFILL }},
5758 { &hf_krb_pac_credential_info_version, {
5759 "Version", "kerberos.pac_credential_info.version", FT_UINT32, BASE_DEC,
5760 NULL, 0, NULL, HFILL }},
5761 { &hf_krb_pac_credential_info_etype, {
5762 "Etype", "kerberos.pac_credential_info.etype", FT_UINT32, BASE_DEC,
5763 NULL, 0, NULL, HFILL }},
5764 { &hf_krb_pac_server_checksum, {
5765 "PAC_SERVER_CHECKSUM", "kerberos.pac_server_checksum", FT_BYTES, BASE_NONE,
5766 NULL, 0, "PAC_SERVER_CHECKSUM structure", HFILL }},
5767 { &hf_krb_pac_privsvr_checksum, {
5768 "PAC_PRIVSVR_CHECKSUM", "kerberos.pac_privsvr_checksum", FT_BYTES, BASE_NONE,
5769 NULL, 0, "PAC_PRIVSVR_CHECKSUM structure", HFILL }},
5770 { &hf_krb_pac_client_info_type, {
5771 "PAC_CLIENT_INFO_TYPE", "kerberos.pac_client_info_type", FT_BYTES, BASE_NONE,
5772 NULL, 0, "PAC_CLIENT_INFO_TYPE structure", HFILL }},
5773 { &hf_krb_pac_s4u_delegation_info, {
5774 "PAC_S4U_DELEGATION_INFO", "kerberos.pac_s4u_delegation_info", FT_BYTES, BASE_NONE,
5775 NULL, 0, "PAC_S4U_DELEGATION_INFO structure", HFILL }},
5776 { &hf_krb_pac_upn_dns_info, {
5777 "UPN_DNS_INFO", "kerberos.pac_upn_dns_info", FT_BYTES, BASE_NONE,
5778 NULL, 0, "UPN_DNS_INFO structure", HFILL }},
5779 { &hf_krb_pac_upn_flags, {
5780 "Flags", "kerberos.pac.upn.flags", FT_UINT32, BASE_HEX,
5781 NULL, 0, "UPN flags", HFILL }},
5782 { &hf_krb_pac_upn_flag_upn_constructed, {
5783 "UPN Name Constructed",
5784 "kerberos.pac.upn.flags.upn_constructed",
5785 FT_BOOLEAN, 32,
5786 TFS(&tfs_krb_pac_upn_flag_upn_constructed),
5787 PAC_UPN_DNS_FLAG_CONSTRUCTED,
5788 "Is the UPN Name constructed?", HFILL }},
5789 { &hf_krb_pac_upn_flag_has_sam_name_and_sid, {
5790 "SAM_NAME and SID Included",
5791 "kerberos.pac.upn.flags.has_sam_name_and_sid",
5792 FT_BOOLEAN, 32,
5793 TFS(&tfs_krb_pac_upn_flag_has_sam_name_and_sid),
5794 PAC_UPN_DNS_FLAG_HAS_SAM_NAME_AND_SID,
5795 "Are SAM_NAME and SID included?", HFILL }},
5796 { &hf_krb_pac_upn_upn_offset, {
5797 "UPN Offset", "kerberos.pac.upn.upn_offset", FT_UINT16, BASE_DEC,
5798 NULL, 0, NULL, HFILL }},
5799 { &hf_krb_pac_upn_upn_len, {
5800 "UPN Len", "kerberos.pac.upn.upn_len", FT_UINT16, BASE_DEC,
5801 NULL, 0, NULL, HFILL }},
5802 { &hf_krb_pac_upn_upn_name, {
5803 "UPN Name", "kerberos.pac.upn.upn_name", FT_STRING, BASE_NONE,
5804 NULL, 0, NULL, HFILL }},
5805 { &hf_krb_pac_upn_dns_offset, {
5806 "DNS Offset", "kerberos.pac.upn.dns_offset", FT_UINT16, BASE_DEC,
5807 NULL, 0, NULL, HFILL }},
5808 { &hf_krb_pac_upn_dns_len, {
5809 "DNS Len", "kerberos.pac.upn.dns_len", FT_UINT16, BASE_DEC,
5810 NULL, 0, NULL, HFILL }},
5811 { &hf_krb_pac_upn_dns_name, {
5812 "DNS Name", "kerberos.pac.upn.dns_name", FT_STRING, BASE_NONE,
5813 NULL, 0, NULL, HFILL }},
5814 { &hf_krb_pac_upn_samaccountname_offset, {
5815 "sAMAccountName Offset", "kerberos.pac.upn.samaccountname_offset", FT_UINT16, BASE_DEC,
5816 NULL, 0, NULL, HFILL }},
5817 { &hf_krb_pac_upn_samaccountname_len, {
5818 "sAMAccountName Len", "kerberos.pac.upn.samaccountname_len", FT_UINT16, BASE_DEC,
5819 NULL, 0, NULL, HFILL }},
5820 { &hf_krb_pac_upn_samaccountname, {
5821 "sAMAccountName", "kerberos.pac.upn.samaccountname", FT_STRING, BASE_NONE,
5822 NULL, 0, NULL, HFILL }},
5823 { &hf_krb_pac_upn_objectsid_offset, {
5824 "objectSid Offset", "kerberos.pac.upn.objectsid_offset", FT_UINT16, BASE_DEC,
5825 NULL, 0, NULL, HFILL }},
5826 { &hf_krb_pac_upn_objectsid_len, {
5827 "objectSid Len", "kerberos.pac.upn.objectsid_len", FT_UINT16, BASE_DEC,
5828 NULL, 0, NULL, HFILL }},
5829 { &hf_krb_pac_client_claims_info, {
5830 "PAC_CLIENT_CLAIMS_INFO", "kerberos.pac_client_claims_info", FT_BYTES, BASE_NONE,
5831 NULL, 0, "PAC_CLIENT_CLAIMS_INFO structure", HFILL }},
5832 { &hf_krb_pac_device_info, {
5833 "PAC_DEVICE_INFO", "kerberos.pac_device_info", FT_BYTES, BASE_NONE,
5834 NULL, 0, "PAC_DEVICE_INFO structure", HFILL }},
5835 { &hf_krb_pac_device_claims_info, {
5836 "PAC_DEVICE_CLAIMS_INFO", "kerberos.pac_device_claims_info", FT_BYTES, BASE_NONE,
5837 NULL, 0, "PAC_DEVICE_CLAIMS_INFO structure", HFILL }},
5838 { &hf_krb_pac_ticket_checksum, {
5839 "PAC_TICKET_CHECKSUM", "kerberos.pac_ticket_checksum", FT_BYTES, BASE_NONE,
5840 NULL, 0, "PAC_TICKET_CHECKSUM structure", HFILL }},
5841 { &hf_krb_pac_attributes_info, {
5842 "PAC_ATTRIBUTES_INFO", "kerberos.pac_attributes_info", FT_BYTES, BASE_NONE,
5843 NULL, 0, "PAC_ATTRIBUTES_INFO structure", HFILL }},
5844 { &hf_krb_pac_attributes_info_length, {
5845 "Flags Valid Length", "kerberos.pac.attributes_info.length", FT_UINT32, BASE_DEC,
5846 NULL, 0, NULL, HFILL }},
5847 { &hf_krb_pac_attributes_info_flags, {
5848 "Flags", "kerberos.pac.attributes_info.flags",
5849 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
5850 { &hf_krb_pac_attributes_info_flags_pac_was_requested, {
5851 "PAC Requested",
5852 "kerberos.pac.attributes.flags.pac_was_requested",
5853 FT_BOOLEAN, 32,
5854 TFS(&tfs_krb_pac_attributes_info_pac_was_requested),
5855 PAC_ATTRIBUTE_FLAG_PAC_WAS_REQUESTED,
5856 "Was a PAC requested?", HFILL }},
5857 { &hf_krb_pac_attributes_info_flags_pac_was_given_implicitly, {
5858 "PAC given Implicitly",
5859 "kerberos.pac.attributes.flags.pac_was_given_implicitly",
5860 FT_BOOLEAN, 32,
5861 TFS(&tfs_krb_pac_attributes_info_pac_was_given_implicitly),
5862 PAC_ATTRIBUTE_FLAG_PAC_WAS_GIVEN_IMPLICITLY,
5863 "Was PAC given implicitly?", HFILL }},
5864 { &hf_krb_pac_requester_sid, {
5865 "PAC_REQUESTER_SID", "kerberos.pac_requester_sid", FT_BYTES, BASE_NONE,
5866 NULL, 0, "PAC_REQUESTER_SID structure", HFILL }},
5867 { &hf_krb_pac_full_checksum, {
5868 "PAC_FULL_CHECKSUM", "kerberos.pac_full_checksum", FT_BYTES, BASE_NONE,
5869 NULL, 0, "PAC_FULL_CHECKSUM structure", HFILL }},
5870 { &hf_krb_pa_supported_enctypes,
5871 { "SupportedEnctypes", "kerberos.supported_entypes",
5872 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
5873 { &hf_krb_pa_supported_enctypes_des_cbc_crc,
5874 { "des-cbc-crc", "kerberos.supported_entypes.des-cbc-crc",
5875 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x00000001, NULL, HFILL }},
5876 { &hf_krb_pa_supported_enctypes_des_cbc_md5,
5877 { "des-cbc-md5", "kerberos.supported_entypes.des-cbc-md5",
5878 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x00000002, NULL, HFILL }},
5879 { &hf_krb_pa_supported_enctypes_rc4_hmac,
5880 { "rc4-hmac", "kerberos.supported_entypes.rc4-hmac",
5881 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x00000004, NULL, HFILL }},
5882 { &hf_krb_pa_supported_enctypes_aes128_cts_hmac_sha1_96,
5883 { "aes128-cts-hmac-sha1-96", "kerberos.supported_entypes.aes128-cts-hmac-sha1-96",
5884 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x00000008, NULL, HFILL }},
5885 { &hf_krb_pa_supported_enctypes_aes256_cts_hmac_sha1_96,
5886 { "aes256-cts-hmac-sha1-96", "kerberos.supported_entypes.aes256-cts-hmac-sha1-96",
5887 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x00000010, NULL, HFILL }},
5888 { &hf_krb_pa_supported_enctypes_aes256_cts_hmac_sha1_96_sk,
5889 { "aes256-cts-hmac-sha1-96-sk", "kerberos.supported_entypes.aes256-cts-hmac-sha1-96-sk",
5890 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x00000020, NULL, HFILL }},
5891 { &hf_krb_pa_supported_enctypes_fast_supported,
5892 { "fast-supported", "kerberos.supported_entypes.fast-supported",
5893 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x00010000, NULL, HFILL }},
5894 { &hf_krb_pa_supported_enctypes_compound_identity_supported,
5895 { "compound-identity-supported", "kerberos.supported_entypes.compound-identity-supported",
5896 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x00020000, NULL, HFILL }},
5897 { &hf_krb_pa_supported_enctypes_claims_supported,
5898 { "claims-supported", "kerberos.supported_entypes.claims-supported",
5899 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x00040000, NULL, HFILL }},
5900 { &hf_krb_pa_supported_enctypes_resource_sid_compression_disabled,
5901 { "resource-sid-compression-disabled", "kerberos.supported_entypes.resource-sid-compression-disabled",
5902 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x00080000, NULL, HFILL }},
5903 { &hf_krb_ad_ap_options,
5904 { "AD-AP-Options", "kerberos.ad_ap_options",
5905 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
5906 { &hf_krb_ad_ap_options_cbt,
5907 { "ChannelBindings", "kerberos.ad_ap_options.cbt",
5908 FT_BOOLEAN, 32, TFS(&tfs_set_notset), 0x00004000, NULL, HFILL }},
5909 { &hf_krb_ad_ap_options_unverified_target_name,
5910 { "UnverifiedTargetName", "kerberos.ad_ap_options.unverified_target_name",
5911 FT_BOOLEAN, 32, TFS(&tfs_set_notset), 0x00008000, NULL, HFILL }},
5912 { &hf_krb_ad_target_principal,
5913 { "Target Principal", "kerberos.ad_target_principal",
5914 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
5915 { &hf_krb_key_hidden_item,
5916 { "KeyHiddenItem", "krb5.key_hidden_item",
5917 FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5918 { &hf_kerberos_KERB_TICKET_LOGON,
5919 { "KERB_TICKET_LOGON", "kerberos.KERB_TICKET_LOGON",
5920 FT_NONE, BASE_NONE, NULL, 0,
5921 NULL, HFILL }},
5922 { &hf_kerberos_KERB_TICKET_LOGON_MessageType,
5923 { "MessageType", "kerberos.KERB_TICKET_LOGON.MessageType",
5924 FT_UINT32, BASE_DEC, VALS(KERB_LOGON_SUBMIT_TYPE), 0,
5925 NULL, HFILL }},
5926 { &hf_kerberos_KERB_TICKET_LOGON_Flags,
5927 { "Flags", "kerberos.KERB_TICKET_LOGON.Flags",
5928 FT_UINT32, BASE_DEC, NULL, 0,
5929 NULL, HFILL }},
5930 { &hf_kerberos_KERB_TICKET_LOGON_ServiceTicketLength,
5931 { "ServiceTicketLength", "kerberos.KERB_TICKET_LOGON.ServiceTicketLength",
5932 FT_UINT32, BASE_DEC, NULL, 0,
5933 NULL, HFILL }},
5934 { &hf_kerberos_KERB_TICKET_LOGON_TicketGrantingTicketLength,
5935 { "TicketGrantingTicketLength", "kerberos.KERB_TICKET_LOGON.TicketGrantingTicketLength",
5936 FT_UINT32, BASE_DEC, NULL, 0,
5937 NULL, HFILL }},
5938 { &hf_kerberos_KERB_TICKET_LOGON_ServiceTicket,
5939 { "ServiceTicket", "kerberos.KERB_TICKET_LOGON.ServiceTicket",
5940 FT_NONE, BASE_NONE, NULL, 0,
5941 NULL, HFILL }},
5942 { &hf_kerberos_KERB_TICKET_LOGON_TicketGrantingTicket,
5943 { "TicketGrantingTicket", "kerberos.KERB_TICKET_LOGON.TicketGrantingTicket",
5944 FT_NONE, BASE_NONE, NULL, 0,
5945 NULL, HFILL }},
5946 { &hf_kerberos_KERB_TICKET_LOGON_FLAG_ALLOW_EXPIRED_TICKET,
5947 { "allow_expired_ticket", "kerberos.KERB_TICKET_LOGON.FLAG_ALLOW_EXPIRED_TICKET",
5948 FT_BOOLEAN, 32, NULL, KERB_LOGON_FLAG_ALLOW_EXPIRED_TICKET,
5949 NULL, HFILL }},
5950 { &hf_kerberos_KERB_TICKET_LOGON_FLAG_REDIRECTED,
5951 { "redirected", "kerberos.KERB_TICKET_LOGON.FLAG_REDIRECTED",
5952 FT_BOOLEAN, 32, NULL, KERB_LOGON_FLAG_REDIRECTED,
5953 NULL, HFILL }},
5954 #ifdef HAVE_KERBEROS
5955 { &hf_kerberos_KrbFastResponse,
5956 { "KrbFastResponse", "kerberos.KrbFastResponse_element",
5957 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }},
5958 { &hf_kerberos_strengthen_key,
5959 { "strengthen-key", "kerberos.strengthen_key_element",
5960 FT_NONE, BASE_NONE, NULL, 0,
5961 NULL, HFILL }},
5962 { &hf_kerberos_finished,
5963 { "finished", "kerberos.finished_element",
5964 FT_NONE, BASE_NONE, NULL, 0,
5965 "KrbFastFinished", HFILL }},
5966 { &hf_kerberos_fast_options,
5967 { "fast-options", "kerberos.fast_options",
5968 FT_BYTES, BASE_NONE, NULL, 0,
5969 "FastOptions", HFILL }},
5970 { &hf_kerberos_FastOptions_reserved,
5971 { "reserved", "kerberos.FastOptions.reserved",
5972 FT_BOOLEAN, 8, NULL, 0x80,
5973 NULL, HFILL }},
5974 { &hf_kerberos_FastOptions_hide_client_names,
5975 { "hide-client-names", "kerberos.FastOptions.hide.client.names",
5976 FT_BOOLEAN, 8, NULL, 0x40,
5977 NULL, HFILL }},
5978 { &hf_kerberos_FastOptions_spare_bit2,
5979 { "spare_bit2", "kerberos.FastOptions.spare.bit2",
5980 FT_BOOLEAN, 8, NULL, 0x20,
5981 NULL, HFILL }},
5982 { &hf_kerberos_FastOptions_spare_bit3,
5983 { "spare_bit3", "kerberos.FastOptions.spare.bit3",
5984 FT_BOOLEAN, 8, NULL, 0x10,
5985 NULL, HFILL }},
5986 { &hf_kerberos_FastOptions_spare_bit4,
5987 { "spare_bit4", "kerberos.FastOptions.spare.bit4",
5988 FT_BOOLEAN, 8, NULL, 0x08,
5989 NULL, HFILL }},
5990 { &hf_kerberos_FastOptions_spare_bit5,
5991 { "spare_bit5", "kerberos.FastOptions.spare.bit5",
5992 FT_BOOLEAN, 8, NULL, 0x04,
5993 NULL, HFILL }},
5994 { &hf_kerberos_FastOptions_spare_bit6,
5995 { "spare_bit6", "kerberos.FastOptions.spare.bit6",
5996 FT_BOOLEAN, 8, NULL, 0x02,
5997 NULL, HFILL }},
5998 { &hf_kerberos_FastOptions_spare_bit7,
5999 { "spare_bit7", "kerberos.FastOptions.spare.bit7",
6000 FT_BOOLEAN, 8, NULL, 0x01,
6001 NULL, HFILL }},
6002 { &hf_kerberos_FastOptions_spare_bit8,
6003 { "spare_bit8", "kerberos.FastOptions.spare.bit8",
6004 FT_BOOLEAN, 8, NULL, 0x80,
6005 NULL, HFILL }},
6006 { &hf_kerberos_FastOptions_spare_bit9,
6007 { "spare_bit9", "kerberos.FastOptions.spare.bit9",
6008 FT_BOOLEAN, 8, NULL, 0x40,
6009 NULL, HFILL }},
6010 { &hf_kerberos_FastOptions_spare_bit10,
6011 { "spare_bit10", "kerberos.FastOptions.spare.bit10",
6012 FT_BOOLEAN, 8, NULL, 0x20,
6013 NULL, HFILL }},
6014 { &hf_kerberos_FastOptions_spare_bit11,
6015 { "spare_bit11", "kerberos.FastOptions.spare.bit11",
6016 FT_BOOLEAN, 8, NULL, 0x10,
6017 NULL, HFILL }},
6018 { &hf_kerberos_FastOptions_spare_bit12,
6019 { "spare_bit12", "kerberos.FastOptions.spare.bit12",
6020 FT_BOOLEAN, 8, NULL, 0x08,
6021 NULL, HFILL }},
6022 { &hf_kerberos_FastOptions_spare_bit13,
6023 { "spare_bit13", "kerberos.FastOptions.spare.bit13",
6024 FT_BOOLEAN, 8, NULL, 0x04,
6025 NULL, HFILL }},
6026 { &hf_kerberos_FastOptions_spare_bit14,
6027 { "spare_bit14", "kerberos.FastOptions.spare.bit14",
6028 FT_BOOLEAN, 8, NULL, 0x02,
6029 NULL, HFILL }},
6030 { &hf_kerberos_FastOptions_spare_bit15,
6031 { "spare_bit15", "kerberos.FastOptions.spare.bit15",
6032 FT_BOOLEAN, 8, NULL, 0x01,
6033 NULL, HFILL }},
6034 { &hf_kerberos_FastOptions_kdc_follow_referrals,
6035 { "kdc-follow-referrals", "kerberos.FastOptions.kdc.follow.referrals",
6036 FT_BOOLEAN, 8, NULL, 0x80,
6037 NULL, HFILL }},
6038 { &hf_kerberos_ticket_checksum,
6039 { "ticket-checksum", "kerberos.ticket_checksum_element",
6040 FT_NONE, BASE_NONE, NULL, 0,
6041 "Checksum", HFILL }},
6042 { &hf_krb_patimestamp,
6043 { "patimestamp", "kerberos.patimestamp",
6044 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0, "KerberosTime", HFILL }},
6045 { &hf_krb_pausec,
6046 { "pausec", "kerberos.pausec",
6047 FT_UINT32, BASE_DEC, NULL, 0, "Microseconds", HFILL }},
6048 #endif /* HAVE_KERBEROS */
6050 #include "packet-kerberos-hfarr.c"
6053 /* List of subtrees */
6054 static int *ett[] = {
6055 &ett_kerberos,
6056 &ett_krb_recordmark,
6057 &ett_krb_pac,
6058 &ett_krb_pac_drep,
6059 &ett_krb_pac_midl_blob,
6060 &ett_krb_pac_logon_info,
6061 &ett_krb_pac_credential_info,
6062 &ett_krb_pac_s4u_delegation_info,
6063 &ett_krb_pac_upn_dns_info,
6064 &ett_krb_pac_upn_dns_info_flags,
6065 &ett_krb_pac_device_info,
6066 &ett_krb_pac_server_checksum,
6067 &ett_krb_pac_privsvr_checksum,
6068 &ett_krb_pac_client_info_type,
6069 &ett_krb_pac_ticket_checksum,
6070 &ett_krb_pac_attributes_info,
6071 &ett_krb_pac_attributes_info_flags,
6072 &ett_krb_pac_requester_sid,
6073 &ett_krb_pac_full_checksum,
6074 &ett_krb_pa_supported_enctypes,
6075 &ett_krb_ad_ap_options,
6076 &ett_kerberos_KERB_TICKET_LOGON,
6077 #ifdef HAVE_KERBEROS
6078 &ett_krb_pa_enc_ts_enc,
6079 &ett_kerberos_KrbFastFinished,
6080 &ett_kerberos_KrbFastResponse,
6081 &ett_kerberos_KrbFastReq,
6082 &ett_kerberos_FastOptions,
6083 #endif
6084 #include "packet-kerberos-ettarr.c"
6087 static ei_register_info ei[] = {
6088 { &ei_kerberos_missing_keytype, { "kerberos.missing_keytype", PI_DECRYPTION, PI_WARN, "Missing keytype", EXPFILL }},
6089 { &ei_kerberos_decrypted_keytype, { "kerberos.decrypted_keytype", PI_SECURITY, PI_CHAT, "Decrypted keytype", EXPFILL }},
6090 { &ei_kerberos_learnt_keytype, { "kerberos.learnt_keytype", PI_SECURITY, PI_CHAT, "Learnt keytype", EXPFILL }},
6091 { &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 }},
6092 { &ei_krb_gssapi_dlglen, { "kerberos.gssapi.dlglen.error", PI_MALFORMED, PI_ERROR, "DlgLen is not the same as number of bytes remaining", EXPFILL }},
6095 expert_module_t* expert_krb;
6096 module_t *krb_module;
6098 proto_kerberos = proto_register_protocol("Kerberos", "KRB5", "kerberos");
6099 proto_register_field_array(proto_kerberos, hf, array_length(hf));
6100 proto_register_subtree_array(ett, array_length(ett));
6101 expert_krb = expert_register_protocol(proto_kerberos);
6102 expert_register_field_array(expert_krb, ei, array_length(ei));
6104 kerberos_tap = register_tap("kerberos");
6105 register_srt_table(proto_kerberos, NULL, 1, krb5stat_packet, krb5stat_init, NULL);
6107 /* Register dissectors */
6108 kerberos_handle_udp = register_dissector("kerberos.udp", dissect_kerberos_udp, proto_kerberos);
6109 kerberos_handle_tcp = register_dissector("kerberos.tcp", dissect_kerberos_tcp, proto_kerberos);
6111 /* Register preferences */
6112 krb_module = prefs_register_protocol(proto_kerberos, kerberos_prefs_apply_cb);
6113 prefs_register_bool_preference(krb_module, "desegment",
6114 "Reassemble Kerberos over TCP messages spanning multiple TCP segments",
6115 "Whether the Kerberos dissector should reassemble messages spanning multiple TCP segments."
6116 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
6117 &krb_desegment);
6118 #ifdef HAVE_KERBEROS
6119 prefs_register_bool_preference(krb_module, "decrypt",
6120 "Try to decrypt Kerberos blobs",
6121 "Whether the dissector should try to decrypt "
6122 "encrypted Kerberos blobs. This requires that the proper "
6123 "keytab file is installed as well.", &krb_decrypt);
6125 prefs_register_filename_preference(krb_module, "file",
6126 "Kerberos keytab file",
6127 "The keytab file containing all the secrets",
6128 &keytab_filename, false);
6130 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
6131 wmem_register_callback(wmem_epan_scope(), enc_key_list_cb, NULL);
6132 kerberos_longterm_keys = wmem_map_new(wmem_epan_scope(),
6133 enc_key_content_hash,
6134 enc_key_content_equal);
6135 kerberos_all_keys = wmem_map_new_autoreset(wmem_epan_scope(),
6136 wmem_file_scope(),
6137 enc_key_content_hash,
6138 enc_key_content_equal);
6139 kerberos_app_session_keys = wmem_map_new_autoreset(wmem_epan_scope(),
6140 wmem_file_scope(),
6141 enc_key_content_hash,
6142 enc_key_content_equal);
6143 #endif /* defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS) */
6144 #endif /* HAVE_KERBEROS */
6147 static int wrap_dissect_gss_kerb(tvbuff_t *tvb, int offset, packet_info *pinfo,
6148 proto_tree *tree, dcerpc_info *di _U_,uint8_t *drep _U_)
6150 tvbuff_t *auth_tvb;
6152 auth_tvb = tvb_new_subset_remaining(tvb, offset);
6154 dissect_kerberos_main(auth_tvb, pinfo, tree, false, NULL);
6156 return tvb_captured_length_remaining(tvb, offset);
6160 static dcerpc_auth_subdissector_fns gss_kerb_auth_connect_fns = {
6161 wrap_dissect_gss_kerb, /* Bind */
6162 wrap_dissect_gss_kerb, /* Bind ACK */
6163 wrap_dissect_gss_kerb, /* AUTH3 */
6164 NULL, /* Request verifier */
6165 NULL, /* Response verifier */
6166 NULL, /* Request data */
6167 NULL /* Response data */
6170 static dcerpc_auth_subdissector_fns gss_kerb_auth_sign_fns = {
6171 wrap_dissect_gss_kerb, /* Bind */
6172 wrap_dissect_gss_kerb, /* Bind ACK */
6173 wrap_dissect_gss_kerb, /* AUTH3 */
6174 wrap_dissect_gssapi_verf, /* Request verifier */
6175 wrap_dissect_gssapi_verf, /* Response verifier */
6176 NULL, /* Request data */
6177 NULL /* Response data */
6180 static dcerpc_auth_subdissector_fns gss_kerb_auth_seal_fns = {
6181 wrap_dissect_gss_kerb, /* Bind */
6182 wrap_dissect_gss_kerb, /* Bind ACK */
6183 wrap_dissect_gss_kerb, /* AUTH3 */
6184 wrap_dissect_gssapi_verf, /* Request verifier */
6185 wrap_dissect_gssapi_verf, /* Response verifier */
6186 wrap_dissect_gssapi_payload, /* Request data */
6187 wrap_dissect_gssapi_payload /* Response data */
6192 void
6193 proto_reg_handoff_kerberos(void)
6195 krb4_handle = find_dissector_add_dependency("krb4", proto_kerberos);
6197 dissector_add_uint_with_preference("udp.port", UDP_PORT_KERBEROS, kerberos_handle_udp);
6198 dissector_add_uint_with_preference("tcp.port", TCP_PORT_KERBEROS, kerberos_handle_tcp);
6200 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_CONNECT,
6201 DCE_C_RPC_AUTHN_PROTOCOL_GSS_KERBEROS,
6202 &gss_kerb_auth_connect_fns);
6204 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_INTEGRITY,
6205 DCE_C_RPC_AUTHN_PROTOCOL_GSS_KERBEROS,
6206 &gss_kerb_auth_sign_fns);
6208 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_PRIVACY,
6209 DCE_C_RPC_AUTHN_PROTOCOL_GSS_KERBEROS,
6210 &gss_kerb_auth_seal_fns);
6214 * Editor modelines - https://www.wireshark.org/tools/modelines.html
6216 * Local variables:
6217 * c-basic-offset: 8
6218 * tab-width: 8
6219 * indent-tabs-mode: t
6220 * End:
6222 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
6223 * :indentSize=8:tabSize=8:noTabs=false: