TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags
[wireshark-sm.git] / epan / dissectors / asn1 / kerberos / packet-kerberos-template.c
blob626f9dab4307d20917452490aba0514b2da11f55
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 enc_key_t *kerberos_last_decryption_key=NULL;
728 static unsigned kerberos_longterm_ids;
729 wmem_map_t *kerberos_longterm_keys;
730 static wmem_map_t *kerberos_all_keys;
731 static wmem_map_t *kerberos_app_session_keys;
733 static bool
734 enc_key_list_cb(wmem_allocator_t* allocator _U_, wmem_cb_event_t event _U_, void *user_data _U_)
736 enc_key_list = NULL;
737 kerberos_longterm_ids = 0;
738 /* keep the callback registered */
739 return true;
742 static int enc_key_cmp_id(const void *k1, const void *k2)
744 const enc_key_t *key1 = (const enc_key_t *)k1;
745 const enc_key_t *key2 = (const enc_key_t *)k2;
747 if (key1->fd_num < key2->fd_num) {
748 return -1;
750 if (key1->fd_num > key2->fd_num) {
751 return 1;
754 if (key1->id < key2->id) {
755 return -1;
757 if (key1->id > key2->id) {
758 return 1;
761 return 0;
764 static gboolean
765 enc_key_content_equal(const void *k1, const void *k2)
767 const enc_key_t *key1 = (const enc_key_t *)k1;
768 const enc_key_t *key2 = (const enc_key_t *)k2;
769 int cmp;
771 if (key1->keytype != key2->keytype) {
772 return false;
775 if (key1->keylength != key2->keylength) {
776 return false;
779 cmp = memcmp(key1->keyvalue, key2->keyvalue, key1->keylength);
780 if (cmp != 0) {
781 return false;
784 return true;
787 static unsigned
788 enc_key_content_hash(const void *k)
790 const enc_key_t *key = (const enc_key_t *)k;
791 unsigned ret = 0;
793 ret += wmem_strong_hash((const uint8_t *)&key->keytype,
794 sizeof(key->keytype));
795 ret += wmem_strong_hash((const uint8_t *)&key->keylength,
796 sizeof(key->keylength));
797 ret += wmem_strong_hash((const uint8_t *)key->keyvalue,
798 key->keylength);
800 return ret;
803 static void
804 kerberos_key_map_insert(wmem_map_t *key_map, enc_key_t *new_key)
806 enc_key_t *existing = NULL;
807 enc_key_t *cur = NULL;
808 int cmp;
810 existing = (enc_key_t *)wmem_map_lookup(key_map, new_key);
811 if (existing == NULL) {
812 wmem_map_insert(key_map, new_key, new_key);
813 return;
816 if (key_map != kerberos_all_keys) {
818 * It should already be linked to the existing key...
820 return;
823 if (existing->fd_num == -1 && new_key->fd_num != -1) {
825 * We can't reference a learnt key
826 * from a longterm key. As they have
827 * a shorter lifetime.
829 * So just let the learnt key remember the
830 * match.
832 new_key->same_list = existing;
833 new_key->num_same = existing->num_same + 1;
834 return;
838 * If a key with the same content (keytype,keylength,keyvalue)
839 * already exists, we want the earliest key to be
840 * in the list.
842 cmp = enc_key_cmp_id(new_key, existing);
843 if (cmp == 0) {
845 * It's the same, nothing to do...
847 return;
849 if (cmp < 0) {
850 /* The new key has should be added to the list. */
851 new_key->same_list = existing;
852 new_key->num_same = existing->num_same + 1;
853 wmem_map_insert(key_map, new_key, new_key);
854 return;
858 * We want to link the new_key to the existing one.
860 * But we want keep the list sorted, so we need to forward
861 * to the correct spot.
863 for (cur = existing; cur->same_list != NULL; cur = cur->same_list) {
864 cmp = enc_key_cmp_id(new_key, cur->same_list);
865 if (cmp == 0) {
867 * It's the same, nothing to do...
869 return;
872 if (cmp < 0) {
874 * We found the correct spot,
875 * the new_key should added
876 * between existing and existing->same_list
878 new_key->same_list = cur->same_list;
879 new_key->num_same = cur->num_same;
880 break;
885 * finally link new_key to existing
886 * and fix up the numbers
888 cur->same_list = new_key;
889 for (cur = existing; cur != new_key; cur = cur->same_list) {
890 cur->num_same += 1;
893 return;
896 struct insert_longterm_keys_into_key_map_state {
897 wmem_map_t *key_map;
900 static void insert_longterm_keys_into_key_map_cb(void *__key _U_,
901 void *value,
902 void *user_data)
904 struct insert_longterm_keys_into_key_map_state *state =
905 (struct insert_longterm_keys_into_key_map_state *)user_data;
906 enc_key_t *key = (enc_key_t *)value;
908 kerberos_key_map_insert(state->key_map, key);
911 static void insert_longterm_keys_into_key_map(wmem_map_t *key_map)
914 * Because the kerberos_longterm_keys are allocated on
915 * wmem_epan_scope() and kerberos_all_keys are allocated
916 * on wmem_file_scope(), we need to plug the longterm keys
917 * back to kerberos_all_keys if a new file was loaded
918 * and wmem_file_scope() got cleared.
920 if (wmem_map_size(key_map) < wmem_map_size(kerberos_longterm_keys)) {
921 struct insert_longterm_keys_into_key_map_state state = {
922 .key_map = key_map,
925 * Reference all longterm keys into kerberos_all_keys
927 wmem_map_foreach(kerberos_longterm_keys,
928 insert_longterm_keys_into_key_map_cb,
929 &state);
933 static void
934 kerberos_key_list_append(wmem_list_t *key_list, enc_key_t *new_key)
936 enc_key_t *existing = NULL;
938 existing = (enc_key_t *)wmem_list_find(key_list, new_key);
939 if (existing != NULL) {
940 return;
943 wmem_list_append(key_list, new_key);
946 void
947 kerberos_inject_longterm_key(packet_info *pinfo,
948 proto_tree *key_tree,
949 proto_item *key_hidden_item,
950 tvbuff_t *key_tvb,
951 int keytype, int keylength, const uint8_t *keyvalue,
952 const char *origin)
954 wmem_allocator_t *key_scope = NULL;
955 enc_key_t *new_key = NULL;
956 const char *methodl = "learnt";
957 const char *methodu = "Learnt";
958 proto_item *item = NULL;
960 if(pinfo->fd->visited){
962 * We already processed this,
963 * we can use a shortterm scope
965 key_scope = pinfo->pool;
966 } else {
968 * As long as we have enc_key_list, we need to
969 * use wmem_epan_scope(), when that's gone
970 * we can dynamically select the scope based on
971 * how long we'll need the particular key.
973 key_scope = wmem_epan_scope();
976 new_key = wmem_new0(key_scope, enc_key_t);
977 snprintf(new_key->key_origin, KRB_MAX_ORIG_LEN, "%s %s in frame %u",
978 methodl, origin, pinfo->num);
979 new_key->fd_num = -1; /* indication for longterm key for FAST */
980 new_key->id = ++kerberos_longterm_ids;
981 snprintf(new_key->id_str, KRB_MAX_ID_STR_LEN, "learnt.%d.%u",
982 pinfo->num, new_key->id);
983 new_key->keytype=keytype;
984 new_key->keylength=keylength;
985 memcpy(new_key->keyvalue, keyvalue, MIN(keylength, KRB_MAX_KEY_LENGTH));
987 if(!pinfo->fd->visited){
989 * Only keep it if we don't processed it before.
991 new_key->next=enc_key_list;
992 enc_key_list=new_key;
993 kerberos_key_map_insert(kerberos_longterm_keys, new_key);
994 insert_longterm_keys_into_key_map(kerberos_all_keys);
995 kerberos_key_map_insert(kerberos_all_keys, new_key);
998 item = proto_tree_add_expert_format(key_tree, pinfo, &ei_kerberos_learnt_keytype,
999 key_tvb, 0, keylength,
1000 "%s %s keytype %d (id=%s) (%02x%02x%02x%02x...)",
1001 methodu, origin, keytype, new_key->id_str,
1002 keyvalue[0] & 0xFF, keyvalue[1] & 0xFF,
1003 keyvalue[2] & 0xFF, keyvalue[3] & 0xFF);
1004 if (item != NULL && key_hidden_item != NULL) {
1005 proto_tree_move_item(key_tree, key_hidden_item, item);
1009 static void
1010 add_encryption_key(packet_info *pinfo,
1011 kerberos_private_data_t *private_data,
1012 proto_tree *key_tree,
1013 proto_item *key_hidden_item,
1014 tvbuff_t *key_tvb,
1015 int keytype, int keylength, const char *keyvalue,
1016 const char *origin,
1017 enc_key_t *src1, enc_key_t *src2)
1019 wmem_allocator_t *key_scope = NULL;
1020 enc_key_t *new_key = NULL;
1021 const char *methodl = "learnt";
1022 const char *methodu = "Learnt";
1023 proto_item *item = NULL;
1025 private_data->last_added_key = NULL;
1027 if (src1 != NULL && src2 != NULL) {
1028 methodl = "derived";
1029 methodu = "Derived";
1031 // dummy
1032 if(pinfo->fd->visited){
1034 * We already processed this,
1035 * we can use a shortterm scope
1037 key_scope = pinfo->pool;
1038 } else {
1040 * As long as we have enc_key_list, we need to
1041 * use wmem_epan_scope(), when that's gone
1042 * we can dynamically select the scope based on
1043 * how long we'll need the particular key.
1045 key_scope = wmem_epan_scope();
1048 new_key = wmem_new0(key_scope, enc_key_t);
1049 snprintf(new_key->key_origin, KRB_MAX_ORIG_LEN, "%s %s in frame %u",
1050 methodl, origin, pinfo->num);
1051 new_key->fd_num = pinfo->num;
1052 new_key->id = ++private_data->learnt_key_ids;
1053 snprintf(new_key->id_str, KRB_MAX_ID_STR_LEN, "%d.%u",
1054 new_key->fd_num, new_key->id);
1055 new_key->keytype=keytype;
1056 new_key->keylength=keylength;
1057 memcpy(new_key->keyvalue, keyvalue, MIN(keylength, KRB_MAX_KEY_LENGTH));
1058 new_key->src1 = src1;
1059 new_key->src2 = src2;
1061 if(!pinfo->fd->visited){
1063 * Only keep it if we don't processed it before.
1065 new_key->next=enc_key_list;
1066 enc_key_list=new_key;
1067 insert_longterm_keys_into_key_map(kerberos_all_keys);
1068 kerberos_key_map_insert(kerberos_all_keys, new_key);
1071 item = proto_tree_add_expert_format(key_tree, pinfo, &ei_kerberos_learnt_keytype,
1072 key_tvb, 0, keylength,
1073 "%s %s keytype %d (id=%d.%u) (%02x%02x%02x%02x...)",
1074 methodu, origin, keytype, pinfo->num, new_key->id,
1075 keyvalue[0] & 0xFF, keyvalue[1] & 0xFF,
1076 keyvalue[2] & 0xFF, keyvalue[3] & 0xFF);
1077 if (item != NULL && key_hidden_item != NULL) {
1078 proto_tree_move_item(key_tree, key_hidden_item, item);
1080 if (src1 != NULL) {
1081 enc_key_t *sek = src1;
1082 expert_add_info_format(pinfo, item, &ei_kerberos_learnt_keytype,
1083 "SRC1 %s keytype %d (id=%s same=%u) (%02x%02x%02x%02x...)",
1084 sek->key_origin, sek->keytype,
1085 sek->id_str, sek->num_same,
1086 sek->keyvalue[0] & 0xFF, sek->keyvalue[1] & 0xFF,
1087 sek->keyvalue[2] & 0xFF, sek->keyvalue[3] & 0xFF);
1089 if (src2 != NULL) {
1090 enc_key_t *sek = src2;
1091 expert_add_info_format(pinfo, item, &ei_kerberos_learnt_keytype,
1092 "SRC2 %s keytype %d (id=%s same=%u) (%02x%02x%02x%02x...)",
1093 sek->key_origin, sek->keytype,
1094 sek->id_str, sek->num_same,
1095 sek->keyvalue[0] & 0xFF, sek->keyvalue[1] & 0xFF,
1096 sek->keyvalue[2] & 0xFF, sek->keyvalue[3] & 0xFF);
1099 kerberos_key_list_append(private_data->learnt_keys, new_key);
1100 private_data->last_added_key = new_key;
1103 static void
1104 save_encryption_key(tvbuff_t *tvb _U_, int offset _U_, int length _U_,
1105 asn1_ctx_t *actx _U_, proto_tree *tree _U_,
1106 int parent_hf_index _U_,
1107 int hf_index _U_)
1109 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
1110 const char *parent = proto_registrar_get_name(parent_hf_index);
1111 const char *element = proto_registrar_get_name(hf_index);
1112 char origin[KRB_MAX_ORIG_LEN] = { 0, };
1114 snprintf(origin, KRB_MAX_ORIG_LEN, "%s_%s", parent, element);
1116 add_encryption_key(actx->pinfo,
1117 private_data,
1118 private_data->key_tree,
1119 private_data->key_hidden_item,
1120 private_data->key_tvb,
1121 private_data->key.keytype,
1122 private_data->key.keylength,
1123 private_data->key.keyvalue,
1124 origin,
1125 NULL,
1126 NULL);
1129 static void
1130 save_Authenticator_subkey(tvbuff_t *tvb, int offset, int length,
1131 asn1_ctx_t *actx, proto_tree *tree,
1132 int parent_hf_index,
1133 int hf_index)
1135 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
1137 save_encryption_key(tvb, offset, length, actx, tree, parent_hf_index, hf_index);
1139 if (private_data->last_decryption_key == NULL) {
1140 return;
1142 if (private_data->last_added_key == NULL) {
1143 return;
1146 if (private_data->within_PA_TGS_REQ != 0) {
1147 private_data->PA_TGS_REQ_key = private_data->last_decryption_key;
1148 private_data->PA_TGS_REQ_subkey = private_data->last_added_key;
1150 if (private_data->fast_armor_within_armor_value != 0) {
1151 private_data->PA_FAST_ARMOR_AP_key = private_data->last_decryption_key;
1152 private_data->PA_FAST_ARMOR_AP_subkey = private_data->last_added_key;
1156 static void
1157 save_EncAPRepPart_subkey(tvbuff_t *tvb, int offset, int length,
1158 asn1_ctx_t *actx, proto_tree *tree,
1159 int parent_hf_index,
1160 int hf_index)
1162 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
1164 save_encryption_key(tvb, offset, length, actx, tree, parent_hf_index, hf_index);
1166 if (actx->pinfo->fd->visited) {
1167 return;
1170 if (private_data->last_added_key == NULL) {
1171 return;
1174 private_data->last_added_key->is_ap_rep_key = true;
1176 if (private_data->last_decryption_key != NULL &&
1177 private_data->last_decryption_key->is_ticket_key)
1179 enc_key_t *ak = private_data->last_added_key;
1180 enc_key_t *tk = private_data->last_decryption_key;
1183 * The enc_key_t structures and their strings
1184 * in pac_names are all allocated on wmem_epan_scope(),
1185 * so we don't need to copy the content.
1187 ak->pac_names = tk->pac_names;
1190 kerberos_key_map_insert(kerberos_app_session_keys, private_data->last_added_key);
1193 static void
1194 save_EncKDCRepPart_key(tvbuff_t *tvb, int offset, int length,
1195 asn1_ctx_t *actx, proto_tree *tree,
1196 int parent_hf_index,
1197 int hf_index)
1199 save_encryption_key(tvb, offset, length, actx, tree, parent_hf_index, hf_index);
1202 static void
1203 save_EncTicketPart_key(tvbuff_t *tvb, int offset, int length,
1204 asn1_ctx_t *actx, proto_tree *tree,
1205 int parent_hf_index,
1206 int hf_index)
1208 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
1210 save_encryption_key(tvb, offset, length, actx, tree, parent_hf_index, hf_index);
1212 if (actx->pinfo->fd->visited) {
1213 return;
1216 if (private_data->last_added_key == NULL) {
1217 return;
1220 private_data->current_ticket_key = private_data->last_added_key;
1221 private_data->current_ticket_key->is_ticket_key = true;
1224 static void
1225 save_KrbCredInfo_key(tvbuff_t *tvb, int offset, int length,
1226 asn1_ctx_t *actx, proto_tree *tree,
1227 int parent_hf_index,
1228 int hf_index)
1230 save_encryption_key(tvb, offset, length, actx, tree, parent_hf_index, hf_index);
1233 static void
1234 save_KrbFastResponse_strengthen_key(tvbuff_t *tvb, int offset, int length,
1235 asn1_ctx_t *actx, proto_tree *tree,
1236 int parent_hf_index,
1237 int hf_index)
1239 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
1241 save_encryption_key(tvb, offset, length, actx, tree, parent_hf_index, hf_index);
1243 private_data->fast_strengthen_key = private_data->last_added_key;
1246 static void used_encryption_key(proto_tree *tree, packet_info *pinfo,
1247 kerberos_private_data_t *private_data,
1248 enc_key_t *ek, int usage, tvbuff_t *cryptotvb,
1249 const char *keymap_name,
1250 unsigned keymap_size,
1251 unsigned decryption_count)
1253 proto_item *item = NULL;
1254 enc_key_t *sek = NULL;
1256 item = proto_tree_add_expert_format(tree, pinfo, &ei_kerberos_decrypted_keytype,
1257 cryptotvb, 0, 0,
1258 "Decrypted keytype %d usage %d "
1259 "using %s (id=%s same=%u) (%02x%02x%02x%02x...)",
1260 ek->keytype, usage, ek->key_origin, ek->id_str, ek->num_same,
1261 ek->keyvalue[0] & 0xFF, ek->keyvalue[1] & 0xFF,
1262 ek->keyvalue[2] & 0xFF, ek->keyvalue[3] & 0xFF);
1263 expert_add_info_format(pinfo, item, &ei_kerberos_decrypted_keytype,
1264 "Used keymap=%s num_keys=%u num_tries=%u)",
1265 keymap_name,
1266 keymap_size,
1267 decryption_count);
1268 if (ek->src1 != NULL) {
1269 sek = ek->src1;
1270 expert_add_info_format(pinfo, item, &ei_kerberos_decrypted_keytype,
1271 "SRC1 %s keytype %d (id=%s same=%u) (%02x%02x%02x%02x...)",
1272 sek->key_origin, sek->keytype,
1273 sek->id_str, sek->num_same,
1274 sek->keyvalue[0] & 0xFF, sek->keyvalue[1] & 0xFF,
1275 sek->keyvalue[2] & 0xFF, sek->keyvalue[3] & 0xFF);
1277 if (ek->src2 != NULL) {
1278 sek = ek->src2;
1279 expert_add_info_format(pinfo, item, &ei_kerberos_decrypted_keytype,
1280 "SRC2 %s keytype %d (id=%s same=%u) (%02x%02x%02x%02x...)",
1281 sek->key_origin, sek->keytype,
1282 sek->id_str, sek->num_same,
1283 sek->keyvalue[0] & 0xFF, sek->keyvalue[1] & 0xFF,
1284 sek->keyvalue[2] & 0xFF, sek->keyvalue[3] & 0xFF);
1286 sek = ek->same_list;
1287 while (sek != NULL) {
1288 expert_add_info_format(pinfo, item, &ei_kerberos_decrypted_keytype,
1289 "Decrypted keytype %d usage %d "
1290 "using %s (id=%s same=%u) (%02x%02x%02x%02x...)",
1291 sek->keytype, usage, sek->key_origin, sek->id_str, sek->num_same,
1292 sek->keyvalue[0] & 0xFF, sek->keyvalue[1] & 0xFF,
1293 sek->keyvalue[2] & 0xFF, sek->keyvalue[3] & 0xFF);
1294 sek = sek->same_list;
1296 kerberos_key_list_append(private_data->decryption_keys, ek);
1297 private_data->last_decryption_key = ek;
1298 kerberos_last_decryption_key = ek;
1300 #endif /* HAVE_HEIMDAL_KERBEROS || HAVE_MIT_KERBEROS */
1302 #ifdef HAVE_MIT_KERBEROS
1304 static void missing_encryption_key(proto_tree *tree, packet_info *pinfo,
1305 kerberos_private_data_t *private_data,
1306 int keytype, int usage, tvbuff_t *cryptotvb,
1307 const char *keymap_name,
1308 unsigned keymap_size,
1309 unsigned decryption_count)
1311 proto_item *item = NULL;
1312 enc_key_t *mek = NULL;
1314 mek = wmem_new0(pinfo->pool, enc_key_t);
1315 snprintf(mek->key_origin, KRB_MAX_ORIG_LEN,
1316 "keytype %d usage %d missing in frame %u",
1317 keytype, usage, pinfo->num);
1318 mek->fd_num = pinfo->num;
1319 mek->id = ++private_data->missing_key_ids;
1320 snprintf(mek->id_str, KRB_MAX_ID_STR_LEN, "missing.%u",
1321 mek->id);
1322 mek->keytype=keytype;
1324 item = proto_tree_add_expert_format(tree, pinfo, &ei_kerberos_missing_keytype,
1325 cryptotvb, 0, 0,
1326 "Missing keytype %d usage %d (id=%s)",
1327 keytype, usage, mek->id_str);
1328 expert_add_info_format(pinfo, item, &ei_kerberos_missing_keytype,
1329 "Used keymap=%s num_keys=%u num_tries=%u)",
1330 keymap_name,
1331 keymap_size,
1332 decryption_count);
1334 kerberos_key_list_append(private_data->missing_keys, mek);
1337 #ifdef HAVE_KRB5_PAC_VERIFY
1338 static void used_signing_key(proto_tree *tree, packet_info *pinfo,
1339 kerberos_private_data_t *private_data,
1340 enc_key_t *ek, tvbuff_t *tvb,
1341 krb5_cksumtype checksum,
1342 const char *reason,
1343 const char *keymap_name,
1344 unsigned keymap_size,
1345 unsigned verify_count)
1347 proto_item *item = NULL;
1348 enc_key_t *sek = NULL;
1350 item = proto_tree_add_expert_format(tree, pinfo, &ei_kerberos_decrypted_keytype,
1351 tvb, 0, 0,
1352 "%s checksum %d keytype %d "
1353 "using %s (id=%s same=%u) (%02x%02x%02x%02x...)",
1354 reason, checksum, ek->keytype, ek->key_origin,
1355 ek->id_str, ek->num_same,
1356 ek->keyvalue[0] & 0xFF, ek->keyvalue[1] & 0xFF,
1357 ek->keyvalue[2] & 0xFF, ek->keyvalue[3] & 0xFF);
1358 expert_add_info_format(pinfo, item, &ei_kerberos_decrypted_keytype,
1359 "Used keymap=%s num_keys=%u num_tries=%u)",
1360 keymap_name,
1361 keymap_size,
1362 verify_count);
1363 sek = ek->same_list;
1364 while (sek != NULL) {
1365 expert_add_info_format(pinfo, item, &ei_kerberos_decrypted_keytype,
1366 "%s checksum %d keytype %d "
1367 "using %s (id=%s same=%u) (%02x%02x%02x%02x...)",
1368 reason, checksum, sek->keytype, sek->key_origin,
1369 sek->id_str, sek->num_same,
1370 sek->keyvalue[0] & 0xFF, sek->keyvalue[1] & 0xFF,
1371 sek->keyvalue[2] & 0xFF, sek->keyvalue[3] & 0xFF);
1372 sek = sek->same_list;
1374 kerberos_key_list_append(private_data->decryption_keys, ek);
1377 static void missing_signing_key(proto_tree *tree, packet_info *pinfo,
1378 kerberos_private_data_t *private_data,
1379 tvbuff_t *tvb,
1380 krb5_cksumtype checksum,
1381 int keytype,
1382 const char *reason,
1383 const char *keymap_name,
1384 unsigned keymap_size,
1385 unsigned verify_count)
1387 proto_item *item = NULL;
1388 enc_key_t *mek = NULL;
1390 mek = wmem_new0(pinfo->pool, enc_key_t);
1391 snprintf(mek->key_origin, KRB_MAX_ORIG_LEN,
1392 "checksum %d keytype %d missing in frame %u",
1393 checksum, keytype, pinfo->num);
1394 mek->fd_num = pinfo->num;
1395 mek->id = ++private_data->missing_key_ids;
1396 snprintf(mek->id_str, KRB_MAX_ID_STR_LEN, "missing.%u",
1397 mek->id);
1398 mek->keytype=keytype;
1400 item = proto_tree_add_expert_format(tree, pinfo, &ei_kerberos_missing_keytype,
1401 tvb, 0, 0,
1402 "%s checksum %d keytype %d (id=%s)",
1403 reason, checksum, keytype, mek->id_str);
1404 expert_add_info_format(pinfo, item, &ei_kerberos_missing_keytype,
1405 "Used keymap=%s num_keys=%u num_tries=%u)",
1406 keymap_name,
1407 keymap_size,
1408 verify_count);
1410 kerberos_key_list_append(private_data->missing_keys, mek);
1413 #endif /* HAVE_KRB5_PAC_VERIFY */
1415 static krb5_context krb5_ctx;
1417 #ifdef HAVE_KRB5_C_FX_CF2_SIMPLE
1418 static void
1419 krb5_fast_key(asn1_ctx_t *actx, proto_tree *tree, tvbuff_t *tvb,
1420 enc_key_t *ek1 _U_, const char *p1 _U_,
1421 enc_key_t *ek2 _U_, const char *p2 _U_,
1422 const char *origin _U_)
1424 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
1425 krb5_error_code ret;
1426 krb5_keyblock k1;
1427 krb5_keyblock k2;
1428 krb5_keyblock *k = NULL;
1430 if (!krb_decrypt) {
1431 return;
1434 if (ek1 == NULL) {
1435 return;
1438 if (ek2 == NULL) {
1439 return;
1442 k1.magic = KV5M_KEYBLOCK;
1443 k1.enctype = ek1->keytype;
1444 k1.length = ek1->keylength;
1445 k1.contents = (uint8_t *)ek1->keyvalue;
1447 k2.magic = KV5M_KEYBLOCK;
1448 k2.enctype = ek2->keytype;
1449 k2.length = ek2->keylength;
1450 k2.contents = (uint8_t *)ek2->keyvalue;
1452 ret = krb5_c_fx_cf2_simple(krb5_ctx, &k1, p1, &k2, p2, &k);
1453 if (ret != 0) {
1454 return;
1457 add_encryption_key(actx->pinfo,
1458 private_data,
1459 tree, NULL, tvb,
1460 k->enctype, k->length,
1461 (const char *)k->contents,
1462 origin,
1463 ek1, ek2);
1465 krb5_free_keyblock(krb5_ctx, k);
1467 #else /* HAVE_KRB5_C_FX_CF2_SIMPLE */
1468 static void
1469 krb5_fast_key(asn1_ctx_t *actx _U_, proto_tree *tree _U_, tvbuff_t *tvb _U_,
1470 enc_key_t *ek1 _U_, const char *p1 _U_,
1471 enc_key_t *ek2 _U_, const char *p2 _U_,
1472 const char *origin _U_)
1475 #endif /* HAVE_KRB5_C_FX_CF2_SIMPLE */
1477 USES_APPLE_DEPRECATED_API
1478 void
1479 read_keytab_file(const char *filename)
1481 krb5_keytab keytab;
1482 krb5_error_code ret;
1483 krb5_keytab_entry key;
1484 krb5_kt_cursor cursor;
1485 static bool first_time=true;
1487 if (filename == NULL || filename[0] == 0) {
1488 return;
1491 if(first_time){
1492 first_time=false;
1493 ret = krb5_init_context(&krb5_ctx);
1494 if(ret && ret != KRB5_CONFIG_CANTOPEN){
1495 return;
1499 /* should use a file in the wireshark users dir */
1500 ret = krb5_kt_resolve(krb5_ctx, filename, &keytab);
1501 if(ret){
1502 fprintf(stderr, "KERBEROS ERROR: Badly formatted keytab filename :%s\n",filename);
1504 return;
1507 ret = krb5_kt_start_seq_get(krb5_ctx, keytab, &cursor);
1508 if(ret){
1509 fprintf(stderr, "KERBEROS ERROR: Could not open or could not read from keytab file :%s\n",filename);
1510 return;
1514 ret = krb5_kt_next_entry(krb5_ctx, keytab, &key, &cursor);
1515 if(ret==0){
1516 enc_key_t *new_key;
1517 int i;
1518 char *pos;
1520 new_key = wmem_new0(wmem_epan_scope(), enc_key_t);
1521 new_key->fd_num = -1;
1522 new_key->id = ++kerberos_longterm_ids;
1523 snprintf(new_key->id_str, KRB_MAX_ID_STR_LEN, "keytab.%u", new_key->id);
1524 new_key->next = enc_key_list;
1526 /* generate origin string, describing where this key came from */
1527 pos=new_key->key_origin;
1528 pos+=MIN(KRB_MAX_ORIG_LEN,
1529 snprintf(pos, KRB_MAX_ORIG_LEN, "keytab principal "));
1530 for(i=0;i<key.principal->length;i++){
1531 pos+=MIN(KRB_MAX_ORIG_LEN-(pos-new_key->key_origin),
1532 snprintf(pos, KRB_MAX_ORIG_LEN-(pos-new_key->key_origin), "%s%s",(i?"/":""),(key.principal->data[i]).data));
1534 pos+=MIN(KRB_MAX_ORIG_LEN-(pos-new_key->key_origin),
1535 snprintf(pos, KRB_MAX_ORIG_LEN-(pos-new_key->key_origin), "@%s",key.principal->realm.data));
1536 *pos=0;
1537 new_key->keytype=key.key.enctype;
1538 new_key->keylength=key.key.length;
1539 memcpy(new_key->keyvalue,
1540 key.key.contents,
1541 MIN(key.key.length, KRB_MAX_KEY_LENGTH));
1543 enc_key_list=new_key;
1544 ret = krb5_free_keytab_entry_contents(krb5_ctx, &key);
1545 if (ret) {
1546 fprintf(stderr, "KERBEROS ERROR: Could not release the entry: %d", ret);
1547 ret = 0; /* try to continue with the next entry */
1549 kerberos_key_map_insert(kerberos_longterm_keys, new_key);
1551 }while(ret==0);
1553 ret = krb5_kt_end_seq_get(krb5_ctx, keytab, &cursor);
1554 if(ret){
1555 fprintf(stderr, "KERBEROS ERROR: Could not release the keytab cursor: %d", ret);
1557 ret = krb5_kt_close(krb5_ctx, keytab);
1558 if(ret){
1559 fprintf(stderr, "KERBEROS ERROR: Could not close the key table handle: %d", ret);
1563 struct decrypt_krb5_with_cb_state {
1564 proto_tree *tree;
1565 packet_info *pinfo;
1566 kerberos_private_data_t *private_data;
1567 int usage;
1568 int keytype;
1569 tvbuff_t *cryptotvb;
1570 krb5_error_code (*decrypt_cb_fn)(
1571 const krb5_keyblock *key,
1572 int usage,
1573 void *decrypt_cb_data);
1574 void *decrypt_cb_data;
1575 unsigned count;
1576 enc_key_t *ek;
1579 static void
1580 decrypt_krb5_with_cb_try_key(void *__key _U_, void *value, void *userdata)
1582 struct decrypt_krb5_with_cb_state *state =
1583 (struct decrypt_krb5_with_cb_state *)userdata;
1584 enc_key_t *ek = (enc_key_t *)value;
1585 krb5_error_code ret;
1586 krb5_keytab_entry key;
1587 #ifdef HAVE_KRB5_C_FX_CF2_SIMPLE
1588 enc_key_t *ak = state->private_data->fast_armor_key;
1589 enc_key_t *sk = state->private_data->fast_strengthen_key;
1590 bool try_with_armor_key = false;
1591 bool try_with_strengthen_key = false;
1592 #endif
1594 if (state->ek != NULL) {
1596 * we're done.
1598 return;
1601 #ifdef HAVE_KRB5_C_FX_CF2_SIMPLE
1602 if (ak != NULL && ak != ek && ak->keytype == state->keytype && ek->fd_num == -1) {
1603 switch (state->usage) {
1604 case KEY_USAGE_ENC_CHALLENGE_CLIENT:
1605 case KEY_USAGE_ENC_CHALLENGE_KDC:
1606 if (ek->fd_num == -1) {
1607 /* Challenges are based on a long term key */
1608 try_with_armor_key = true;
1610 break;
1614 * If we already have a strengthen_key
1615 * we don't need to try with the armor key
1616 * again
1618 if (sk != NULL) {
1619 try_with_armor_key = false;
1623 if (sk != NULL && sk != ek && sk->keytype == state->keytype && sk->keytype == ek->keytype) {
1624 switch (state->usage) {
1625 case 3:
1626 if (ek->fd_num == -1) {
1627 /* AS-REP is based on a long term key */
1628 try_with_strengthen_key = true;
1630 break;
1631 case 8:
1632 case 9:
1633 if (ek->fd_num != -1) {
1634 /* TGS-REP is not based on a long term key */
1635 try_with_strengthen_key = true;
1637 break;
1641 if (try_with_armor_key) {
1642 krb5_keyblock k1;
1643 krb5_keyblock k2;
1644 krb5_keyblock *k = NULL;
1645 const char *p1 = NULL;
1647 k1.magic = KV5M_KEYBLOCK;
1648 k1.enctype = ak->keytype;
1649 k1.length = ak->keylength;
1650 k1.contents = (uint8_t *)ak->keyvalue;
1652 k2.magic = KV5M_KEYBLOCK;
1653 k2.enctype = ek->keytype;
1654 k2.length = ek->keylength;
1655 k2.contents = (uint8_t *)ek->keyvalue;
1657 switch (state->usage) {
1658 case KEY_USAGE_ENC_CHALLENGE_CLIENT:
1659 p1 = "clientchallengearmor";
1660 break;
1661 case KEY_USAGE_ENC_CHALLENGE_KDC:
1662 p1 = "kdcchallengearmor";
1663 break;
1664 default:
1666 * Should never be called!
1669 * try the next one...
1671 return;
1674 ret = krb5_c_fx_cf2_simple(krb5_ctx,
1675 &k1, p1,
1676 &k2, "challengelongterm",
1677 &k);
1678 if (ret != 0) {
1680 * try the next one...
1682 return;
1685 state->count += 1;
1686 ret = state->decrypt_cb_fn(k,
1687 state->usage,
1688 state->decrypt_cb_data);
1689 if (ret == 0) {
1690 add_encryption_key(state->pinfo,
1691 state->private_data,
1692 state->tree,
1693 NULL,
1694 state->cryptotvb,
1695 k->enctype, k->length,
1696 (const char *)k->contents,
1698 ak, ek);
1699 krb5_free_keyblock(krb5_ctx, k);
1701 * remember the key and stop traversing
1703 state->ek = state->private_data->last_added_key;
1704 return;
1706 krb5_free_keyblock(krb5_ctx, k);
1708 * don't stop traversing...
1709 * try the next one...
1711 return;
1714 if (try_with_strengthen_key) {
1715 krb5_keyblock k1;
1716 krb5_keyblock k2;
1717 krb5_keyblock *k = NULL;
1719 k1.magic = KV5M_KEYBLOCK;
1720 k1.enctype = sk->keytype;
1721 k1.length = sk->keylength;
1722 k1.contents = (uint8_t *)sk->keyvalue;
1724 k2.magic = KV5M_KEYBLOCK;
1725 k2.enctype = ek->keytype;
1726 k2.length = ek->keylength;
1727 k2.contents = (uint8_t *)ek->keyvalue;
1729 ret = krb5_c_fx_cf2_simple(krb5_ctx,
1730 &k1, "strengthenkey",
1731 &k2, "replykey",
1732 &k);
1733 if (ret != 0) {
1735 * try the next one...
1737 return;
1740 state->count += 1;
1741 ret = state->decrypt_cb_fn(k,
1742 state->usage,
1743 state->decrypt_cb_data);
1744 if (ret == 0) {
1745 add_encryption_key(state->pinfo,
1746 state->private_data,
1747 state->tree,
1748 NULL,
1749 state->cryptotvb,
1750 k->enctype, k->length,
1751 (const char *)k->contents,
1752 "strengthen-reply-key",
1753 sk, ek);
1754 krb5_free_keyblock(krb5_ctx, k);
1756 * remember the key and stop traversing
1758 state->ek = state->private_data->last_added_key;
1759 return;
1761 krb5_free_keyblock(krb5_ctx, k);
1763 * don't stop traversing...
1764 * try the next one...
1766 return;
1768 #endif /* HAVE_KRB5_C_FX_CF2_SIMPLE */
1770 /* shortcircuit and bail out if enctypes are not matching */
1771 if ((state->keytype != -1) && (ek->keytype != state->keytype)) {
1773 * don't stop traversing...
1774 * try the next one...
1776 return;
1779 key.key.enctype=ek->keytype;
1780 key.key.length=ek->keylength;
1781 key.key.contents=ek->keyvalue;
1782 state->count += 1;
1783 ret = state->decrypt_cb_fn(&(key.key),
1784 state->usage,
1785 state->decrypt_cb_data);
1786 if (ret != 0) {
1788 * don't stop traversing...
1789 * try the next one...
1791 return;
1795 * we're done, remember the key
1797 state->ek = ek;
1800 static krb5_error_code
1801 decrypt_krb5_with_cb(proto_tree *tree,
1802 packet_info *pinfo,
1803 kerberos_private_data_t *private_data,
1804 int usage,
1805 int keytype,
1806 tvbuff_t *cryptotvb,
1807 krb5_error_code (*decrypt_cb_fn)(
1808 const krb5_keyblock *key,
1809 int usage,
1810 void *decrypt_cb_data),
1811 void *decrypt_cb_data)
1813 const char *key_map_name = NULL;
1814 wmem_map_t *key_map = NULL;
1815 struct decrypt_krb5_with_cb_state state = {
1816 .tree = tree,
1817 .pinfo = pinfo,
1818 .private_data = private_data,
1819 .usage = usage,
1820 .cryptotvb = cryptotvb,
1821 .keytype = keytype,
1822 .decrypt_cb_fn = decrypt_cb_fn,
1823 .decrypt_cb_data = decrypt_cb_data,
1826 read_keytab_file_from_preferences();
1828 switch (usage) {
1829 case KRB5_KU_USAGE_INITIATOR_SEAL:
1830 case KRB5_KU_USAGE_ACCEPTOR_SEAL:
1831 key_map_name = "app_session_keys";
1832 key_map = kerberos_app_session_keys;
1833 break;
1834 default:
1835 key_map_name = "all_keys";
1836 key_map = kerberos_all_keys;
1837 insert_longterm_keys_into_key_map(key_map);
1838 break;
1841 wmem_map_foreach(key_map, decrypt_krb5_with_cb_try_key, &state);
1842 if (state.ek != NULL) {
1843 used_encryption_key(tree, pinfo, private_data,
1844 state.ek, usage, cryptotvb,
1845 key_map_name,
1846 wmem_map_size(key_map),
1847 state.count);
1848 return 0;
1851 missing_encryption_key(tree, pinfo, private_data,
1852 keytype, usage, cryptotvb,
1853 key_map_name,
1854 wmem_map_size(key_map),
1855 state.count);
1856 return -1;
1859 struct decrypt_krb5_data_state {
1860 krb5_data input;
1861 krb5_data output;
1864 static krb5_error_code
1865 decrypt_krb5_data_cb(const krb5_keyblock *key,
1866 int usage,
1867 void *decrypt_cb_data)
1869 struct decrypt_krb5_data_state *state =
1870 (struct decrypt_krb5_data_state *)decrypt_cb_data;
1871 krb5_enc_data input;
1873 memset(&input, 0, sizeof(input));
1874 input.enctype = key->enctype;
1875 input.ciphertext = state->input;
1877 return krb5_c_decrypt(krb5_ctx,
1878 key,
1879 usage,
1881 &input,
1882 &state->output);
1885 static uint8_t *
1886 decrypt_krb5_data_private(proto_tree *tree _U_, packet_info *pinfo,
1887 kerberos_private_data_t *private_data,
1888 int usage, tvbuff_t *cryptotvb, int keytype,
1889 int *datalen)
1891 #define HAVE_DECRYPT_KRB5_DATA_PRIVATE 1
1892 struct decrypt_krb5_data_state state;
1893 krb5_error_code ret;
1894 int length = tvb_captured_length(cryptotvb);
1895 const uint8_t *cryptotext = tvb_get_ptr(cryptotvb, 0, length);
1897 /* don't do anything if we are not attempting to decrypt data */
1898 if(!krb_decrypt || length < 1){
1899 return NULL;
1902 /* make sure we have all the data we need */
1903 if (tvb_captured_length(cryptotvb) < tvb_reported_length(cryptotvb)) {
1904 return NULL;
1907 memset(&state, 0, sizeof(state));
1908 state.input.length = length;
1909 state.input.data = (uint8_t *)cryptotext;
1910 state.output.data = (char *)wmem_alloc(pinfo->pool, length);
1911 state.output.length = length;
1913 ret = decrypt_krb5_with_cb(tree,
1914 pinfo,
1915 private_data,
1916 usage,
1917 keytype,
1918 cryptotvb,
1919 decrypt_krb5_data_cb,
1920 &state);
1921 if (ret != 0) {
1922 return NULL;
1925 if (datalen) {
1926 *datalen = state.output.length;
1928 return (uint8_t *)state.output.data;
1931 uint8_t *
1932 decrypt_krb5_data(proto_tree *tree _U_, packet_info *pinfo,
1933 int usage,
1934 tvbuff_t *cryptotvb,
1935 int keytype,
1936 int *datalen)
1938 kerberos_private_data_t *zero_private = kerberos_new_private_data(pinfo);
1939 return decrypt_krb5_data_private(tree, pinfo, zero_private,
1940 usage, cryptotvb, keytype,
1941 datalen);
1944 USES_APPLE_RST
1946 #ifdef KRB5_CRYPTO_TYPE_SIGN_ONLY
1947 struct decrypt_krb5_krb_cfx_dce_state {
1948 const uint8_t *gssapi_header_ptr;
1949 unsigned gssapi_header_len;
1950 tvbuff_t *gssapi_encrypted_tvb;
1951 uint8_t *gssapi_payload;
1952 unsigned gssapi_payload_len;
1953 const uint8_t *gssapi_trailer_ptr;
1954 unsigned gssapi_trailer_len;
1955 tvbuff_t *checksum_tvb;
1956 uint8_t *checksum;
1957 unsigned checksum_len;
1960 static krb5_error_code
1961 decrypt_krb5_krb_cfx_dce_cb(const krb5_keyblock *key,
1962 int usage,
1963 void *decrypt_cb_data)
1965 struct decrypt_krb5_krb_cfx_dce_state *state =
1966 (struct decrypt_krb5_krb_cfx_dce_state *)decrypt_cb_data;
1967 unsigned int k5_headerlen = 0;
1968 unsigned int k5_headerofs = 0;
1969 unsigned int k5_trailerlen = 0;
1970 unsigned int k5_trailerofs = 0;
1971 size_t _k5_blocksize = 0;
1972 unsigned k5_blocksize;
1973 krb5_crypto_iov iov[6];
1974 krb5_error_code ret;
1975 unsigned checksum_remain = state->checksum_len;
1976 unsigned checksum_crypt_len;
1978 memset(iov, 0, sizeof(iov));
1980 ret = krb5_c_crypto_length(krb5_ctx,
1981 key->enctype,
1982 KRB5_CRYPTO_TYPE_HEADER,
1983 &k5_headerlen);
1984 if (ret != 0) {
1985 return ret;
1987 if (checksum_remain < k5_headerlen) {
1988 return -1;
1990 checksum_remain -= k5_headerlen;
1991 k5_headerofs = checksum_remain;
1992 ret = krb5_c_crypto_length(krb5_ctx,
1993 key->enctype,
1994 KRB5_CRYPTO_TYPE_TRAILER,
1995 &k5_trailerlen);
1996 if (ret != 0) {
1997 return ret;
1999 if (checksum_remain < k5_trailerlen) {
2000 return -1;
2002 checksum_remain -= k5_trailerlen;
2003 k5_trailerofs = checksum_remain;
2004 checksum_crypt_len = checksum_remain;
2006 ret = krb5_c_block_size(krb5_ctx,
2007 key->enctype,
2008 &_k5_blocksize);
2009 if (ret != 0) {
2010 return ret;
2013 * The cast is required for the Windows build in order
2014 * to avoid the following warning.
2016 * warning C4267: '-=': conversion from 'size_t' to 'unsigned',
2017 * possible loss of data
2019 k5_blocksize = (unsigned)_k5_blocksize;
2020 if (checksum_remain < k5_blocksize) {
2021 return -1;
2023 checksum_remain -= k5_blocksize;
2024 if (checksum_remain < 16) {
2025 return -1;
2028 tvb_memcpy(state->gssapi_encrypted_tvb,
2029 state->gssapi_payload,
2031 state->gssapi_payload_len);
2032 tvb_memcpy(state->checksum_tvb,
2033 state->checksum,
2035 state->checksum_len);
2037 iov[0].flags = KRB5_CRYPTO_TYPE_HEADER;
2038 iov[0].data.data = state->checksum + k5_headerofs;
2039 iov[0].data.length = k5_headerlen;
2041 if (state->gssapi_header_ptr != NULL) {
2042 iov[1].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY;
2043 iov[1].data.data = (uint8_t *)(uintptr_t)state->gssapi_header_ptr;
2044 iov[1].data.length = state->gssapi_header_len;
2045 } else {
2046 iov[1].flags = KRB5_CRYPTO_TYPE_EMPTY;
2049 iov[2].flags = KRB5_CRYPTO_TYPE_DATA;
2050 iov[2].data.data = state->gssapi_payload;
2051 iov[2].data.length = state->gssapi_payload_len;
2053 if (state->gssapi_trailer_ptr != NULL) {
2054 iov[3].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY;
2055 iov[3].data.data = (uint8_t *)(uintptr_t)state->gssapi_trailer_ptr;
2056 iov[3].data.length = state->gssapi_trailer_len;
2057 } else {
2058 iov[3].flags = KRB5_CRYPTO_TYPE_EMPTY;
2061 iov[4].flags = KRB5_CRYPTO_TYPE_DATA;
2062 iov[4].data.data = state->checksum;
2063 iov[4].data.length = checksum_crypt_len;
2065 iov[5].flags = KRB5_CRYPTO_TYPE_TRAILER;
2066 iov[5].data.data = state->checksum + k5_trailerofs;
2067 iov[5].data.length = k5_trailerlen;
2069 return krb5_c_decrypt_iov(krb5_ctx,
2070 key,
2071 usage,
2073 iov,
2077 tvbuff_t *
2078 decrypt_krb5_krb_cfx_dce(proto_tree *tree,
2079 packet_info *pinfo,
2080 int usage,
2081 int keytype,
2082 tvbuff_t *gssapi_header_tvb,
2083 tvbuff_t *gssapi_encrypted_tvb,
2084 tvbuff_t *gssapi_trailer_tvb,
2085 tvbuff_t *checksum_tvb)
2087 struct decrypt_krb5_krb_cfx_dce_state state;
2088 kerberos_private_data_t *zero_private = kerberos_new_private_data(pinfo);
2089 tvbuff_t *gssapi_decrypted_tvb = NULL;
2090 krb5_error_code ret;
2092 /* don't do anything if we are not attempting to decrypt data */
2093 if (!krb_decrypt) {
2094 return NULL;
2097 memset(&state, 0, sizeof(state));
2099 /* make sure we have all the data we need */
2100 #define __CHECK_TVB_LEN(__tvb) (tvb_captured_length(__tvb) < tvb_reported_length(__tvb))
2101 if (gssapi_header_tvb != NULL) {
2102 if (__CHECK_TVB_LEN(gssapi_header_tvb)) {
2103 return NULL;
2106 state.gssapi_header_len = tvb_captured_length(gssapi_header_tvb);
2107 state.gssapi_header_ptr = tvb_get_ptr(gssapi_header_tvb,
2109 state.gssapi_header_len);
2111 if (gssapi_encrypted_tvb == NULL || __CHECK_TVB_LEN(gssapi_encrypted_tvb)) {
2112 return NULL;
2114 state.gssapi_encrypted_tvb = gssapi_encrypted_tvb;
2115 state.gssapi_payload_len = tvb_captured_length(gssapi_encrypted_tvb);
2116 state.gssapi_payload = (uint8_t *)wmem_alloc0(pinfo->pool, state.gssapi_payload_len);
2117 if (state.gssapi_payload == NULL) {
2118 return NULL;
2120 if (gssapi_trailer_tvb != NULL) {
2121 if (__CHECK_TVB_LEN(gssapi_trailer_tvb)) {
2122 return NULL;
2125 state.gssapi_trailer_len = tvb_captured_length(gssapi_trailer_tvb);
2126 state.gssapi_trailer_ptr = tvb_get_ptr(gssapi_trailer_tvb,
2128 state.gssapi_trailer_len);
2130 if (checksum_tvb == NULL || __CHECK_TVB_LEN(checksum_tvb)) {
2131 return NULL;
2133 state.checksum_tvb = checksum_tvb;
2134 state.checksum_len = tvb_captured_length(checksum_tvb);
2135 state.checksum = (uint8_t *)wmem_alloc0(pinfo->pool, state.checksum_len);
2136 if (state.checksum == NULL) {
2137 return NULL;
2140 ret = decrypt_krb5_with_cb(tree,
2141 pinfo,
2142 zero_private,
2143 usage,
2144 keytype,
2145 gssapi_encrypted_tvb,
2146 decrypt_krb5_krb_cfx_dce_cb,
2147 &state);
2148 wmem_free(pinfo->pool, state.checksum);
2149 if (ret != 0) {
2150 wmem_free(pinfo->pool, state.gssapi_payload);
2151 return NULL;
2154 gssapi_decrypted_tvb = tvb_new_child_real_data(gssapi_encrypted_tvb,
2155 state.gssapi_payload,
2156 state.gssapi_payload_len,
2157 state.gssapi_payload_len);
2158 if (gssapi_decrypted_tvb == NULL) {
2159 wmem_free(pinfo->pool, state.gssapi_payload);
2160 return NULL;
2163 return gssapi_decrypted_tvb;
2165 #else /* NOT KRB5_CRYPTO_TYPE_SIGN_ONLY */
2166 #define NEED_DECRYPT_KRB5_KRB_CFX_DCE_NOOP 1
2167 #endif /* NOT KRB5_CRYPTO_TYPE_SIGN_ONLY */
2169 #ifdef HAVE_KRB5_PAC_VERIFY
2171 * macOS up to 10.14.5 only has a MIT shim layer on top
2172 * of heimdal. It means that krb5_pac_verify() is not available
2173 * in /usr/lib/libkrb5.dylib
2175 * https://opensource.apple.com/tarballs/Heimdal/Heimdal-520.260.1.tar.gz
2176 * https://opensource.apple.com/tarballs/MITKerberosShim/MITKerberosShim-71.200.1.tar.gz
2179 extern krb5_error_code
2180 krb5int_c_mandatory_cksumtype(krb5_context, krb5_enctype, krb5_cksumtype *);
2182 extern void krb5_free_enc_tkt_part(krb5_context, krb5_enc_tkt_part *);
2183 extern krb5_error_code
2184 decode_krb5_enc_tkt_part(const krb5_data *output, krb5_enc_tkt_part **rep);
2185 extern krb5_error_code
2186 encode_krb5_enc_tkt_part(const krb5_enc_tkt_part *rep, krb5_data **code);
2188 static int
2189 keytype_for_cksumtype(krb5_cksumtype checksum)
2191 static const int keytypes[] = {
2196 unsigned i;
2198 for (i = 0; i < array_length(keytypes); i++) {
2199 krb5_cksumtype checksumtype = 0;
2200 krb5_error_code ret;
2202 ret = krb5int_c_mandatory_cksumtype(krb5_ctx,
2203 keytypes[i],
2204 &checksumtype);
2205 if (ret != 0) {
2206 continue;
2208 if (checksum == checksumtype) {
2209 return keytypes[i];
2213 return -1;
2216 struct verify_krb5_pac_state {
2217 int pacbuffer_length;
2218 const uint8_t *pacbuffer;
2219 krb5_pac pac;
2220 krb5_cksumtype server_checksum;
2221 unsigned server_count;
2222 enc_key_t *server_ek;
2223 krb5_cksumtype kdc_checksum;
2224 unsigned kdc_count;
2225 enc_key_t *kdc_ek;
2226 krb5_cksumtype ticket_checksum_type;
2227 const krb5_data *ticket_checksum_data;
2228 krb5_cksumtype full_checksum_type;
2229 const krb5_data *full_checksum_data;
2230 unsigned full_count;
2231 enc_key_t *full_ek;
2234 static void
2235 verify_krb5_pac_try_server_key(void *__key _U_, void *value, void *userdata)
2237 struct verify_krb5_pac_state *state =
2238 (struct verify_krb5_pac_state *)userdata;
2239 enc_key_t *ek = (enc_key_t *)value;
2240 krb5_keyblock keyblock;
2241 krb5_cksumtype checksumtype = 0;
2242 krb5_error_code ret;
2244 if (state->server_checksum == 0) {
2246 * nothing more todo, stop traversing.
2248 return;
2251 if (state->server_ek != NULL) {
2253 * we're done.
2255 return;
2258 ret = krb5int_c_mandatory_cksumtype(krb5_ctx, ek->keytype,
2259 &checksumtype);
2260 if (ret != 0) {
2262 * the key is not usable, keep traversing.
2263 * try the next key...
2265 return;
2268 keyblock.magic = KV5M_KEYBLOCK;
2269 keyblock.enctype = ek->keytype;
2270 keyblock.length = ek->keylength;
2271 keyblock.contents = (uint8_t *)ek->keyvalue;
2273 if (checksumtype == state->server_checksum) {
2274 state->server_count += 1;
2275 ret = krb5_pac_verify(krb5_ctx, state->pac, 0, NULL,
2276 &keyblock, NULL);
2277 if (ret == 0) {
2278 state->server_ek = ek;
2283 static void
2284 verify_krb5_pac_try_kdc_key(void *__key _U_, void *value, void *userdata)
2286 struct verify_krb5_pac_state *state =
2287 (struct verify_krb5_pac_state *)userdata;
2288 enc_key_t *ek = (enc_key_t *)value;
2289 krb5_keyblock keyblock;
2290 krb5_cksumtype checksumtype = 0;
2291 krb5_error_code ret;
2293 if (state->kdc_checksum == 0) {
2295 * nothing more todo, stop traversing.
2297 return;
2300 if (state->kdc_ek != NULL) {
2302 * we're done.
2304 return;
2307 ret = krb5int_c_mandatory_cksumtype(krb5_ctx, ek->keytype,
2308 &checksumtype);
2309 if (ret != 0) {
2311 * the key is not usable, keep traversing.
2312 * try the next key...
2314 return;
2317 keyblock.magic = KV5M_KEYBLOCK;
2318 keyblock.enctype = ek->keytype;
2319 keyblock.length = ek->keylength;
2320 keyblock.contents = (uint8_t *)ek->keyvalue;
2322 if (checksumtype == state->kdc_checksum) {
2323 state->kdc_count += 1;
2324 ret = krb5_pac_verify(krb5_ctx, state->pac, 0, NULL,
2325 NULL, &keyblock);
2326 if (ret == 0) {
2327 state->kdc_ek = ek;
2332 #define __KRB5_PAC_TICKET_CHECKSUM 16
2334 static void
2335 verify_krb5_pac_ticket_checksum(proto_tree *tree _U_,
2336 asn1_ctx_t *actx _U_,
2337 tvbuff_t *pactvb _U_,
2338 struct verify_krb5_pac_state *state _U_)
2340 #ifdef HAVE_DECODE_KRB5_ENC_TKT_PART
2341 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
2342 tvbuff_t *teptvb = private_data->last_ticket_enc_part_tvb;
2343 unsigned teplength = 0;
2344 const uint8_t *tepbuffer = NULL;
2345 krb5_data tepdata = { .length = 0, };
2346 krb5_enc_tkt_part *tep = NULL;
2347 krb5_data *tmpdata = NULL;
2348 krb5_error_code ret;
2349 krb5_authdata **recoded_container = NULL;
2350 int ad_orig_idx = -1;
2351 krb5_authdata *ad_orig_ptr = NULL;
2352 int l0idx = 0;
2353 krb5_keyblock kdc_key = { .magic = KV5M_KEYBLOCK, };
2354 size_t checksum_length = 0;
2355 krb5_checksum checksum = { .checksum_type = 0, };
2356 krb5_boolean valid = false;
2358 if (state->kdc_ek == NULL) {
2359 int keytype = keytype_for_cksumtype(state->ticket_checksum_type);
2360 missing_signing_key(tree, actx->pinfo, private_data,
2361 pactvb, state->ticket_checksum_type,
2362 keytype,
2363 "Missing KDC (for ticket)",
2364 "kdc_checksum_key",
2367 return;
2370 if (teptvb == NULL) {
2371 return;
2374 teplength = tvb_captured_length(teptvb);
2375 /* make sure we have all the data we need */
2376 if (teplength < tvb_reported_length(teptvb)) {
2377 return;
2380 tepbuffer = tvb_get_ptr(teptvb, 0, teplength);
2381 if (tepbuffer == NULL) {
2382 return;
2385 kdc_key.magic = KV5M_KEYBLOCK;
2386 kdc_key.enctype = state->kdc_ek->keytype;
2387 kdc_key.length = state->kdc_ek->keylength;
2388 kdc_key.contents = (uint8_t *)state->kdc_ek->keyvalue;
2390 checksum.checksum_type = state->ticket_checksum_type;
2391 checksum.length = state->ticket_checksum_data->length;
2392 checksum.contents = (uint8_t *)state->ticket_checksum_data->data;
2393 if (checksum.length >= 4) {
2394 checksum.length -= 4;
2395 checksum.contents += 4;
2398 ret = krb5_c_checksum_length(krb5_ctx,
2399 checksum.checksum_type,
2400 &checksum_length);
2401 if (ret != 0) {
2402 missing_signing_key(tree, actx->pinfo, private_data,
2403 pactvb, state->ticket_checksum_type,
2404 state->kdc_ek->keytype,
2405 "krb5_c_checksum_length failed for Ticket Signature",
2406 "kdc_checksum_key",
2409 return;
2411 checksum.length = MIN(checksum.length, (unsigned int)checksum_length);
2413 tepdata.data = (void *)tepbuffer;
2414 tepdata.length = teplength;
2416 ret = decode_krb5_enc_tkt_part(&tepdata, &tep);
2417 if (ret != 0) {
2418 missing_signing_key(tree, actx->pinfo, private_data,
2419 pactvb, state->ticket_checksum_type,
2420 state->kdc_ek->keytype,
2421 "decode_krb5_enc_tkt_part failed",
2422 "kdc_checksum_key",
2425 return;
2428 for (l0idx = 0; tep->authorization_data[l0idx]; l0idx++) {
2429 krb5_authdata *adl0 = tep->authorization_data[l0idx];
2430 krb5_authdata **decoded_container = NULL;
2431 krb5_authdata *ad_pac = NULL;
2432 int l1idx = 0;
2434 if (adl0->ad_type != KRB5_AUTHDATA_IF_RELEVANT) {
2435 continue;
2438 ret = krb5_decode_authdata_container(krb5_ctx,
2439 KRB5_AUTHDATA_IF_RELEVANT,
2440 adl0,
2441 &decoded_container);
2442 if (ret != 0) {
2443 missing_signing_key(tree, actx->pinfo, private_data,
2444 pactvb, state->ticket_checksum_type,
2445 state->kdc_ek->keytype,
2446 "krb5_decode_authdata_container failed",
2447 "kdc_checksum_key",
2450 krb5_free_enc_tkt_part(krb5_ctx, tep);
2451 return;
2454 for (l1idx = 0; decoded_container[l1idx]; l1idx++) {
2455 krb5_authdata *adl1 = decoded_container[l1idx];
2457 if (adl1->ad_type != KRB5_AUTHDATA_WIN2K_PAC) {
2458 continue;
2461 ad_pac = adl1;
2462 break;
2465 if (ad_pac == NULL) {
2466 krb5_free_authdata(krb5_ctx, decoded_container);
2467 continue;
2470 ad_pac->length = 1;
2471 ad_pac->contents[0] = '\0';
2473 ret = krb5_encode_authdata_container(krb5_ctx,
2474 KRB5_AUTHDATA_IF_RELEVANT,
2475 decoded_container,
2476 &recoded_container);
2477 krb5_free_authdata(krb5_ctx, decoded_container);
2478 decoded_container = NULL;
2479 if (ret != 0) {
2480 missing_signing_key(tree, actx->pinfo, private_data,
2481 pactvb, state->ticket_checksum_type,
2482 state->kdc_ek->keytype,
2483 "krb5_encode_authdata_container failed",
2484 "kdc_checksum_key",
2487 krb5_free_enc_tkt_part(krb5_ctx, tep);
2488 return;
2491 ad_orig_idx = l0idx;
2492 ad_orig_ptr = adl0;
2493 tep->authorization_data[l0idx] = recoded_container[0];
2494 break;
2497 ret = encode_krb5_enc_tkt_part(tep, &tmpdata);
2498 if (ad_orig_ptr != NULL) {
2499 tep->authorization_data[ad_orig_idx] = ad_orig_ptr;
2501 krb5_free_enc_tkt_part(krb5_ctx, tep);
2502 tep = NULL;
2503 if (recoded_container != NULL) {
2504 krb5_free_authdata(krb5_ctx, recoded_container);
2505 recoded_container = NULL;
2507 if (ret != 0) {
2508 missing_signing_key(tree, actx->pinfo, private_data,
2509 pactvb, state->ticket_checksum_type,
2510 state->kdc_ek->keytype,
2511 "encode_krb5_enc_tkt_part failed",
2512 "kdc_checksum_key",
2515 return;
2518 ret = krb5_c_verify_checksum(krb5_ctx, &kdc_key,
2519 KRB5_KEYUSAGE_APP_DATA_CKSUM,
2520 tmpdata, &checksum, &valid);
2521 krb5_free_data(krb5_ctx, tmpdata);
2522 tmpdata = NULL;
2523 if (ret != 0) {
2524 missing_signing_key(tree, actx->pinfo, private_data,
2525 pactvb, state->ticket_checksum_type,
2526 state->kdc_ek->keytype,
2527 "krb5_c_verify_checksum failed for Ticket Signature",
2528 "kdc_checksum_key",
2531 return;
2534 if (valid == false) {
2535 missing_signing_key(tree, actx->pinfo, private_data,
2536 pactvb, state->ticket_checksum_type,
2537 state->kdc_ek->keytype,
2538 "Invalid Ticket",
2539 "kdc_checksum_key",
2542 return;
2545 used_signing_key(tree, actx->pinfo, private_data,
2546 state->kdc_ek, pactvb,
2547 state->ticket_checksum_type,
2548 "Verified Ticket",
2549 "kdc_checksum_key",
2552 #endif /* HAVE_DECODE_KRB5_ENC_TKT_PART */
2555 #define __KRB5_PAC_FULL_CHECKSUM 19
2557 static void
2558 verify_krb5_pac_full_checksum(proto_tree *tree,
2559 asn1_ctx_t *actx,
2560 tvbuff_t *orig_pactvb,
2561 struct verify_krb5_pac_state *state)
2563 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
2564 krb5_error_code ret;
2565 krb5_keyblock kdc_key = { .magic = KV5M_KEYBLOCK, };
2566 size_t checksum_length = 0;
2567 krb5_checksum checksum = { .checksum_type = 0, };
2568 krb5_data pac_data = { .length = 0, };
2569 tvbuff_t *copy_pactvb = NULL;
2570 uint32_t cur_offset;
2571 uint32_t num_buffers;
2572 uint32_t idx;
2573 krb5_boolean valid = false;
2575 if (state->kdc_ek == NULL) {
2576 int keytype = keytype_for_cksumtype(state->full_checksum_type);
2577 missing_signing_key(tree, actx->pinfo, private_data,
2578 orig_pactvb, state->full_checksum_type,
2579 keytype,
2580 "Missing KDC (for full)",
2581 "kdc_checksum_key",
2584 return;
2587 kdc_key.magic = KV5M_KEYBLOCK;
2588 kdc_key.enctype = state->kdc_ek->keytype;
2589 kdc_key.length = state->kdc_ek->keylength;
2590 kdc_key.contents = (uint8_t *)state->kdc_ek->keyvalue;
2592 ret = krb5_c_checksum_length(krb5_ctx,
2593 state->full_checksum_type,
2594 &checksum_length);
2595 if (ret != 0) {
2596 missing_signing_key(tree, actx->pinfo, private_data,
2597 orig_pactvb, state->full_checksum_type,
2598 state->kdc_ek->keytype,
2599 "krb5_c_checksum_length failed for Full Signature",
2600 "kdc_checksum_key",
2603 return;
2607 * The checksum element begins with 4 bytes of type
2608 * (state->full_checksum_type) before the crypto checksum
2610 if (state->full_checksum_data->length < (4 + checksum_length)) {
2611 missing_signing_key(tree, actx->pinfo, private_data,
2612 orig_pactvb, state->full_checksum_type,
2613 state->kdc_ek->keytype,
2614 "pacbuffer_length too short for Full Signature",
2615 "kdc_checksum_key",
2618 return;
2621 pac_data.data = wmem_memdup(actx->pinfo->pool, state->pacbuffer, state->pacbuffer_length);
2622 if (pac_data.data == NULL) {
2623 missing_signing_key(tree, actx->pinfo, private_data,
2624 orig_pactvb, state->full_checksum_type,
2625 state->kdc_ek->keytype,
2626 "wmem_memdup(pacbuffer) failed",
2627 "kdc_checksum_key",
2630 return;
2632 pac_data.length = state->pacbuffer_length;
2634 copy_pactvb = tvb_new_child_real_data(orig_pactvb,
2635 (uint8_t *)pac_data.data,
2636 pac_data.length,
2637 pac_data.length);
2638 if (copy_pactvb == NULL) {
2639 missing_signing_key(tree, actx->pinfo, private_data,
2640 orig_pactvb, state->full_checksum_type,
2641 state->kdc_ek->keytype,
2642 "tvb_new_child_real_data(pac_copy) failed",
2643 "kdc_checksum_key",
2646 return;
2649 #define __PAC_CHECK_OFFSET_SIZE(__offset, __length, __reason) do { \
2650 uint64_t __end = state->pacbuffer_length; \
2651 uint64_t __offset64 = __offset; \
2652 uint64_t __length64 = __length; \
2653 uint64_t __last; \
2654 if (__offset64 > INT32_MAX) { \
2655 missing_signing_key(tree, actx->pinfo, private_data, \
2656 orig_pactvb, state->full_checksum_type, \
2657 state->kdc_ek->keytype, \
2658 __reason, \
2659 "kdc_checksum_key", \
2660 1, \
2661 0); \
2662 return; \
2664 if (__length64 > INT32_MAX) { \
2665 missing_signing_key(tree, actx->pinfo, private_data, \
2666 orig_pactvb, state->full_checksum_type, \
2667 state->kdc_ek->keytype, \
2668 __reason, \
2669 "kdc_checksum_key", \
2670 1, \
2671 0); \
2672 return; \
2674 __last = __offset64 + __length64; \
2675 if (__last > __end) { \
2676 missing_signing_key(tree, actx->pinfo, private_data, \
2677 orig_pactvb, state->full_checksum_type, \
2678 state->kdc_ek->keytype, \
2679 __reason, \
2680 "kdc_checksum_key", \
2681 1, \
2682 0); \
2683 return; \
2685 } while(0)
2687 cur_offset = 0;
2688 __PAC_CHECK_OFFSET_SIZE(cur_offset, 8, "PACTYPE Header");
2689 num_buffers = tvb_get_uint32(copy_pactvb, cur_offset, ENC_LITTLE_ENDIAN);
2690 cur_offset += 4;
2691 /* ignore 4 byte version */
2692 cur_offset += 4;
2694 for (idx = 0; idx < num_buffers; idx++) {
2695 uint32_t b_type;
2696 uint32_t b_length;
2697 uint64_t b_offset;
2699 __PAC_CHECK_OFFSET_SIZE(cur_offset, 16, "PAC_INFO_BUFFER Header");
2700 b_type = tvb_get_uint32(copy_pactvb, cur_offset, ENC_LITTLE_ENDIAN);
2701 cur_offset += 4;
2702 b_length = tvb_get_uint32(copy_pactvb, cur_offset, ENC_LITTLE_ENDIAN);
2703 cur_offset += 4;
2704 b_offset = tvb_get_uint64(copy_pactvb, cur_offset, ENC_LITTLE_ENDIAN);
2705 cur_offset += 8;
2707 __PAC_CHECK_OFFSET_SIZE(b_offset, b_length, "PAC_INFO_BUFFER Payload");
2709 if (b_length <= 4) {
2710 continue;
2714 * Leave PAC_TICKET_CHECKSUM and clear all other checksums
2715 * and their possible RODC identifier, but leaving their
2716 * checksum type as is.
2718 switch (b_type) {
2719 case KRB5_PAC_SERVER_CHECKSUM:
2720 case KRB5_PAC_PRIVSVR_CHECKSUM:
2721 case __KRB5_PAC_FULL_CHECKSUM:
2722 memset(pac_data.data + b_offset+4, 0, b_length-4);
2723 break;
2727 checksum.checksum_type = state->full_checksum_type;
2728 checksum.contents = (uint8_t *)state->full_checksum_data->data + 4;
2729 checksum.length = (unsigned)checksum_length;
2731 ret = krb5_c_verify_checksum(krb5_ctx, &kdc_key,
2732 KRB5_KEYUSAGE_APP_DATA_CKSUM,
2733 &pac_data, &checksum, &valid);
2734 if (ret != 0) {
2735 missing_signing_key(tree, actx->pinfo, private_data,
2736 orig_pactvb, state->full_checksum_type,
2737 state->kdc_ek->keytype,
2738 "krb5_c_verify_checksum failed for Full PAC Signature",
2739 "kdc_checksum_key",
2742 return;
2745 if (valid == false) {
2746 missing_signing_key(tree, actx->pinfo, private_data,
2747 orig_pactvb, state->full_checksum_type,
2748 state->kdc_ek->keytype,
2749 "Invalid Full PAC Signature",
2750 "kdc_checksum_key",
2753 return;
2756 used_signing_key(tree, actx->pinfo, private_data,
2757 state->kdc_ek, orig_pactvb,
2758 state->full_checksum_type,
2759 "Verified Full PAC",
2760 "kdc_checksum_key",
2765 static void
2766 verify_krb5_pac(proto_tree *tree _U_, asn1_ctx_t *actx, tvbuff_t *pactvb)
2768 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
2769 krb5_error_code ret;
2770 krb5_data checksum_data = {0,0,NULL};
2771 krb5_data ticket_checksum_data = {0,0,NULL};
2772 krb5_data full_checksum_data = {0,0,NULL};
2773 int length = tvb_captured_length(pactvb);
2774 const uint8_t *pacbuffer = NULL;
2775 struct verify_krb5_pac_state state = {
2776 .kdc_checksum = 0,
2779 /* don't do anything if we are not attempting to decrypt data */
2780 if(!krb_decrypt || length < 1){
2781 return;
2784 /* make sure we have all the data we need */
2785 if (tvb_captured_length(pactvb) < tvb_reported_length(pactvb)) {
2786 return;
2789 pacbuffer = tvb_get_ptr(pactvb, 0, length);
2790 state.pacbuffer_length = length;
2791 state.pacbuffer = pacbuffer;
2793 ret = krb5_pac_parse(krb5_ctx, pacbuffer, length, &state.pac);
2794 if (ret != 0) {
2795 proto_tree_add_expert_format(tree, actx->pinfo, &ei_kerberos_decrypted_keytype,
2796 pactvb, 0, 0,
2797 "Failed to parse PAC buffer %d in frame %u",
2798 ret, actx->pinfo->fd->num);
2799 return;
2802 ret = krb5_pac_get_buffer(krb5_ctx, state.pac, KRB5_PAC_SERVER_CHECKSUM,
2803 &checksum_data);
2804 if (ret == 0) {
2805 state.server_checksum = pletoh32(checksum_data.data);
2806 krb5_free_data_contents(krb5_ctx, &checksum_data);
2808 ret = krb5_pac_get_buffer(krb5_ctx, state.pac, KRB5_PAC_PRIVSVR_CHECKSUM,
2809 &checksum_data);
2810 if (ret == 0) {
2811 state.kdc_checksum = pletoh32(checksum_data.data);
2812 krb5_free_data_contents(krb5_ctx, &checksum_data);
2814 ret = krb5_pac_get_buffer(krb5_ctx, state.pac,
2815 __KRB5_PAC_TICKET_CHECKSUM,
2816 &ticket_checksum_data);
2817 if (ret == 0) {
2818 state.ticket_checksum_data = &ticket_checksum_data;
2819 state.ticket_checksum_type = pletoh32(ticket_checksum_data.data);
2821 ret = krb5_pac_get_buffer(krb5_ctx, state.pac,
2822 __KRB5_PAC_FULL_CHECKSUM,
2823 &full_checksum_data);
2824 if (ret == 0) {
2825 state.full_checksum_data = &full_checksum_data;
2826 state.full_checksum_type = pletoh32(full_checksum_data.data);
2829 read_keytab_file_from_preferences();
2831 wmem_map_foreach(kerberos_all_keys,
2832 verify_krb5_pac_try_server_key,
2833 &state);
2834 if (state.server_ek != NULL) {
2835 used_signing_key(tree, actx->pinfo, private_data,
2836 state.server_ek, pactvb,
2837 state.server_checksum, "Verified Server",
2838 "all_keys",
2839 wmem_map_size(kerberos_all_keys),
2840 state.server_count);
2841 } else {
2842 int keytype = keytype_for_cksumtype(state.server_checksum);
2843 missing_signing_key(tree, actx->pinfo, private_data,
2844 pactvb, state.server_checksum, keytype,
2845 "Missing Server",
2846 "all_keys",
2847 wmem_map_size(kerberos_all_keys),
2848 state.server_count);
2850 wmem_map_foreach(kerberos_longterm_keys,
2851 verify_krb5_pac_try_kdc_key,
2852 &state);
2853 if (state.kdc_ek != NULL) {
2854 used_signing_key(tree, actx->pinfo, private_data,
2855 state.kdc_ek, pactvb,
2856 state.kdc_checksum, "Verified KDC",
2857 "longterm_keys",
2858 wmem_map_size(kerberos_longterm_keys),
2859 state.kdc_count);
2860 } else {
2861 int keytype = keytype_for_cksumtype(state.kdc_checksum);
2862 missing_signing_key(tree, actx->pinfo, private_data,
2863 pactvb, state.kdc_checksum, keytype,
2864 "Missing KDC",
2865 "longterm_keys",
2866 wmem_map_size(kerberos_longterm_keys),
2867 state.kdc_count);
2870 if (state.ticket_checksum_type != 0) {
2871 verify_krb5_pac_ticket_checksum(tree, actx, pactvb, &state);
2874 if (state.ticket_checksum_data != NULL) {
2875 krb5_free_data_contents(krb5_ctx, &ticket_checksum_data);
2878 if (state.full_checksum_type != 0) {
2879 verify_krb5_pac_full_checksum(tree, actx, pactvb, &state);
2882 if (state.full_checksum_data != NULL) {
2883 krb5_free_data_contents(krb5_ctx, &full_checksum_data);
2886 krb5_pac_free(krb5_ctx, state.pac);
2888 #endif /* HAVE_KRB5_PAC_VERIFY */
2890 #elif defined(HAVE_HEIMDAL_KERBEROS)
2891 static krb5_context krb5_ctx;
2893 USES_APPLE_DEPRECATED_API
2895 static void
2896 krb5_fast_key(asn1_ctx_t *actx _U_, proto_tree *tree _U_, tvbuff_t *tvb _U_,
2897 enc_key_t *ek1 _U_, const char *p1 _U_,
2898 enc_key_t *ek2 _U_, const char *p2 _U_,
2899 const char *origin _U_)
2901 /* TODO: use krb5_crypto_fx_cf2() from Heimdal */
2903 void
2904 read_keytab_file(const char *filename)
2906 krb5_keytab keytab;
2907 krb5_error_code ret;
2908 krb5_keytab_entry key;
2909 krb5_kt_cursor cursor;
2910 enc_key_t *new_key;
2911 static bool first_time=true;
2913 if (filename == NULL || filename[0] == 0) {
2914 return;
2917 if(first_time){
2918 first_time=false;
2919 ret = krb5_init_context(&krb5_ctx);
2920 if(ret){
2921 return;
2925 /* should use a file in the wireshark users dir */
2926 ret = krb5_kt_resolve(krb5_ctx, filename, &keytab);
2927 if(ret){
2928 fprintf(stderr, "KERBEROS ERROR: Could not open keytab file :%s\n",filename);
2930 return;
2933 ret = krb5_kt_start_seq_get(krb5_ctx, keytab, &cursor);
2934 if(ret){
2935 fprintf(stderr, "KERBEROS ERROR: Could not read from keytab file :%s\n",filename);
2936 return;
2940 ret = krb5_kt_next_entry(krb5_ctx, keytab, &key, &cursor);
2941 if(ret==0){
2942 unsigned int i;
2943 char *pos;
2945 new_key = wmem_new0(wmem_epan_scope(), enc_key_t);
2946 new_key->fd_num = -1;
2947 new_key->id = ++kerberos_longterm_ids;
2948 snprintf(new_key->id_str, KRB_MAX_ID_STR_LEN, "keytab.%u", new_key->id);
2949 new_key->next = enc_key_list;
2951 /* generate origin string, describing where this key came from */
2952 pos=new_key->key_origin;
2953 pos+=MIN(KRB_MAX_ORIG_LEN,
2954 snprintf(pos, KRB_MAX_ORIG_LEN, "keytab principal "));
2955 for(i=0;i<key.principal->name.name_string.len;i++){
2956 pos+=MIN(KRB_MAX_ORIG_LEN-(pos-new_key->key_origin),
2957 snprintf(pos, KRB_MAX_ORIG_LEN-(pos-new_key->key_origin), "%s%s",(i?"/":""),key.principal->name.name_string.val[i]));
2959 pos+=MIN(KRB_MAX_ORIG_LEN-(pos-new_key->key_origin),
2960 snprintf(pos, KRB_MAX_ORIG_LEN-(pos-new_key->key_origin), "@%s",key.principal->realm));
2961 *pos=0;
2962 new_key->keytype=key.keyblock.keytype;
2963 new_key->keylength=(int)key.keyblock.keyvalue.length;
2964 memcpy(new_key->keyvalue,
2965 key.keyblock.keyvalue.data,
2966 MIN((unsigned)key.keyblock.keyvalue.length, KRB_MAX_KEY_LENGTH));
2968 enc_key_list=new_key;
2969 ret = krb5_kt_free_entry(krb5_ctx, &key);
2970 if (ret) {
2971 fprintf(stderr, "KERBEROS ERROR: Could not release the entry: %d", ret);
2972 ret = 0; /* try to continue with the next entry */
2974 kerberos_key_map_insert(kerberos_longterm_keys, new_key);
2976 }while(ret==0);
2978 ret = krb5_kt_end_seq_get(krb5_ctx, keytab, &cursor);
2979 if(ret){
2980 fprintf(stderr, "KERBEROS ERROR: Could not release the keytab cursor: %d", ret);
2982 ret = krb5_kt_close(krb5_ctx, keytab);
2983 if(ret){
2984 fprintf(stderr, "KERBEROS ERROR: Could not close the key table handle: %d", ret);
2988 USES_APPLE_RST
2991 uint8_t *
2992 decrypt_krb5_data(proto_tree *tree _U_, packet_info *pinfo,
2993 int usage,
2994 tvbuff_t *cryptotvb,
2995 int keytype,
2996 int *datalen)
2998 kerberos_private_data_t *zero_private = kerberos_new_private_data(pinfo);
2999 krb5_error_code ret;
3000 krb5_data data;
3001 enc_key_t *ek;
3002 int length = tvb_captured_length(cryptotvb);
3003 const uint8_t *cryptotext = tvb_get_ptr(cryptotvb, 0, length);
3005 /* don't do anything if we are not attempting to decrypt data */
3006 if(!krb_decrypt){
3007 return NULL;
3010 /* make sure we have all the data we need */
3011 if (tvb_captured_length(cryptotvb) < tvb_reported_length(cryptotvb)) {
3012 return NULL;
3015 read_keytab_file_from_preferences();
3017 for(ek=enc_key_list;ek;ek=ek->next){
3018 krb5_keytab_entry key;
3019 krb5_crypto crypto;
3020 uint8_t *cryptocopy; /* workaround for pre-0.6.1 heimdal bug */
3022 /* shortcircuit and bail out if enctypes are not matching */
3023 if((keytype != -1) && (ek->keytype != keytype)) {
3024 continue;
3027 key.keyblock.keytype=ek->keytype;
3028 key.keyblock.keyvalue.length=ek->keylength;
3029 key.keyblock.keyvalue.data=ek->keyvalue;
3030 ret = krb5_crypto_init(krb5_ctx, &(key.keyblock), (krb5_enctype)ENCTYPE_NULL, &crypto);
3031 if(ret){
3032 return NULL;
3035 /* pre-0.6.1 versions of Heimdal would sometimes change
3036 the cryptotext data even when the decryption failed.
3037 This would obviously not work since we iterate over the
3038 keys. So just give it a copy of the crypto data instead.
3039 This has been seen for RC4-HMAC blobs.
3041 cryptocopy = (uint8_t *)wmem_memdup(pinfo->pool, cryptotext, length);
3042 ret = krb5_decrypt_ivec(krb5_ctx, crypto, usage,
3043 cryptocopy, length,
3044 &data,
3045 NULL);
3046 if((ret == 0) && (length>0)){
3047 char *user_data;
3049 used_encryption_key(tree, pinfo, zero_private,
3050 ek, usage, cryptotvb,
3051 "enc_key_list", 0, 0);
3053 krb5_crypto_destroy(krb5_ctx, crypto);
3054 /* return a private wmem_alloced blob to the caller */
3055 user_data = (char *)wmem_memdup(pinfo->pool, data.data, (unsigned)data.length);
3056 if (datalen) {
3057 *datalen = (int)data.length;
3059 return user_data;
3061 krb5_crypto_destroy(krb5_ctx, crypto);
3063 return NULL;
3066 #define NEED_DECRYPT_KRB5_KRB_CFX_DCE_NOOP 1
3068 #elif defined (HAVE_LIBNETTLE)
3070 #define SERVICE_KEY_SIZE (DES3_KEY_SIZE + 2)
3071 #define KEYTYPE_DES3_CBC_MD5 5 /* Currently the only one supported */
3073 typedef struct _service_key_t {
3074 uint16_t kvno;
3075 int keytype;
3076 int length;
3077 uint8_t *contents;
3078 char origin[KRB_MAX_ORIG_LEN+1];
3079 } service_key_t;
3080 GSList *service_key_list;
3083 static void
3084 add_encryption_key(packet_info *pinfo, int keytype, int keylength, const char *keyvalue, const char *origin)
3086 service_key_t *new_key;
3088 if(pinfo->fd->visited){
3089 return;
3092 new_key = g_malloc(sizeof(service_key_t));
3093 new_key->kvno = 0;
3094 new_key->keytype = keytype;
3095 new_key->length = keylength;
3096 new_key->contents = g_memdup2(keyvalue, keylength);
3097 snprintf(new_key->origin, KRB_MAX_ORIG_LEN, "%s learnt from frame %u", origin, pinfo->num);
3098 service_key_list = g_slist_append(service_key_list, (void *) new_key);
3101 static void
3102 save_encryption_key(tvbuff_t *tvb _U_, int offset _U_, int length _U_,
3103 asn1_ctx_t *actx _U_, proto_tree *tree _U_,
3104 int parent_hf_index _U_,
3105 int hf_index _U_)
3107 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
3108 const char *parent = proto_registrar_get_name(parent_hf_index);
3109 const char *element = proto_registrar_get_name(hf_index);
3110 char origin[KRB_MAX_ORIG_LEN] = { 0, };
3112 snprintf(origin, KRB_MAX_ORIG_LEN, "%s_%s", parent, element);
3114 add_encryption_key(actx->pinfo,
3115 private_data->key.keytype,
3116 private_data->key.keylength,
3117 private_data->key.keyvalue,
3118 origin);
3121 static void
3122 save_Authenticator_subkey(tvbuff_t *tvb, int offset, int length,
3123 asn1_ctx_t *actx, proto_tree *tree,
3124 int parent_hf_index,
3125 int hf_index)
3127 save_encryption_key(tvb, offset, length, actx, tree, parent_hf_index, hf_index);
3130 static void
3131 save_EncAPRepPart_subkey(tvbuff_t *tvb, int offset, int length,
3132 asn1_ctx_t *actx, proto_tree *tree,
3133 int parent_hf_index,
3134 int hf_index)
3136 save_encryption_key(tvb, offset, length, actx, tree, parent_hf_index, hf_index);
3139 static void
3140 save_EncKDCRepPart_key(tvbuff_t *tvb, int offset, int length,
3141 asn1_ctx_t *actx, proto_tree *tree,
3142 int parent_hf_index,
3143 int hf_index)
3145 save_encryption_key(tvb, offset, length, actx, tree, parent_hf_index, hf_index);
3148 static void
3149 save_EncTicketPart_key(tvbuff_t *tvb, int offset, int length,
3150 asn1_ctx_t *actx, proto_tree *tree,
3151 int parent_hf_index,
3152 int hf_index)
3154 save_encryption_key(tvb, offset, length, actx, tree, parent_hf_index, hf_index);
3157 static void
3158 save_KrbCredInfo_key(tvbuff_t *tvb, int offset, int length,
3159 asn1_ctx_t *actx, proto_tree *tree,
3160 int parent_hf_index,
3161 int hf_index)
3163 save_encryption_key(tvb, offset, length, actx, tree, parent_hf_index, hf_index);
3166 static void
3167 save_KrbFastResponse_strengthen_key(tvbuff_t *tvb _U_, int offset _U_, int length _U_,
3168 asn1_ctx_t *actx _U_, proto_tree *tree _U_, int hf_index _U_)
3170 save_encryption_key(tvb, offset, length, actx, tree, hf_index);
3173 static void
3174 clear_keytab(void) {
3175 GSList *ske;
3176 service_key_t *sk;
3178 for(ske = service_key_list; ske != NULL; ske = g_slist_next(ske)){
3179 sk = (service_key_t *) ske->data;
3180 if (sk) {
3181 g_free(sk->contents);
3182 g_free(sk);
3185 g_slist_free(service_key_list);
3186 service_key_list = NULL;
3189 static void
3190 read_keytab_file(const char *service_key_file)
3192 FILE *skf;
3193 ws_statb64 st;
3194 service_key_t *sk;
3195 unsigned char buf[SERVICE_KEY_SIZE];
3196 int newline_skip = 0, count = 0;
3198 if (service_key_file != NULL && ws_stat64 (service_key_file, &st) == 0) {
3200 /* The service key file contains raw 192-bit (24 byte) 3DES keys.
3201 * There can be zero, one (\n), or two (\r\n) characters between
3202 * keys. Trailing characters are ignored.
3205 /* XXX We should support the standard keytab format instead */
3206 if (st.st_size > SERVICE_KEY_SIZE) {
3207 if ( (st.st_size % (SERVICE_KEY_SIZE + 1) == 0) ||
3208 (st.st_size % (SERVICE_KEY_SIZE + 1) == SERVICE_KEY_SIZE) ) {
3209 newline_skip = 1;
3210 } else if ( (st.st_size % (SERVICE_KEY_SIZE + 2) == 0) ||
3211 (st.st_size % (SERVICE_KEY_SIZE + 2) == SERVICE_KEY_SIZE) ) {
3212 newline_skip = 2;
3216 skf = ws_fopen(service_key_file, "rb");
3217 if (! skf) return;
3219 while (fread(buf, SERVICE_KEY_SIZE, 1, skf) == 1) {
3220 sk = g_malloc(sizeof(service_key_t));
3221 sk->kvno = buf[0] << 8 | buf[1];
3222 sk->keytype = KEYTYPE_DES3_CBC_MD5;
3223 sk->length = DES3_KEY_SIZE;
3224 sk->contents = g_memdup2(buf + 2, DES3_KEY_SIZE);
3225 snprintf(sk->origin, KRB_MAX_ORIG_LEN, "3DES service key file, key #%d, offset %ld", count, ftell(skf));
3226 service_key_list = g_slist_append(service_key_list, (void *) sk);
3227 if (fseek(skf, newline_skip, SEEK_CUR) < 0) {
3228 fprintf(stderr, "unable to seek...\n");
3229 fclose(skf);
3230 return;
3232 count++;
3234 fclose(skf);
3238 #define CONFOUNDER_PLUS_CHECKSUM 24
3240 uint8_t *
3241 decrypt_krb5_data(proto_tree *tree, packet_info *pinfo,
3242 int _U_ usage,
3243 tvbuff_t *cryptotvb,
3244 int keytype,
3245 int *datalen)
3247 tvbuff_t *encr_tvb;
3248 uint8_t *decrypted_data = NULL, *plaintext = NULL;
3249 uint8_t cls;
3250 bool pc;
3251 uint32_t tag, item_len, data_len;
3252 int id_offset, offset;
3253 uint8_t key[DES3_KEY_SIZE];
3254 uint8_t initial_vector[DES_BLOCK_SIZE];
3255 gcry_md_hd_t md5_handle;
3256 uint8_t *digest;
3257 uint8_t zero_fill[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
3258 uint8_t confounder[8];
3259 bool ind;
3260 GSList *ske;
3261 service_key_t *sk;
3262 struct des3_ctx ctx;
3263 int length = tvb_captured_length(cryptotvb);
3264 const uint8_t *cryptotext = tvb_get_ptr(cryptotvb, 0, length);
3267 /* don't do anything if we are not attempting to decrypt data */
3268 if(!krb_decrypt){
3269 return NULL;
3272 /* make sure we have all the data we need */
3273 if (tvb_captured_length(cryptotvb) < tvb_reported_length(cryptotvb)) {
3274 return NULL;
3277 if (keytype != KEYTYPE_DES3_CBC_MD5 || service_key_list == NULL) {
3278 return NULL;
3281 decrypted_data = wmem_alloc(pinfo->pool, length);
3282 for(ske = service_key_list; ske != NULL; ske = g_slist_next(ske)){
3283 bool do_continue = false;
3284 bool digest_ok;
3285 sk = (service_key_t *) ske->data;
3287 des_fix_parity(DES3_KEY_SIZE, key, sk->contents);
3289 memset(initial_vector, 0, DES_BLOCK_SIZE);
3290 des3_set_key(&ctx, key);
3291 cbc_decrypt(&ctx, des3_decrypt, DES_BLOCK_SIZE, initial_vector,
3292 length, decrypted_data, cryptotext);
3293 encr_tvb = tvb_new_real_data(decrypted_data, length, length);
3295 tvb_memcpy(encr_tvb, confounder, 0, 8);
3297 /* We have to pull the decrypted data length from the decrypted
3298 * content. If the key doesn't match or we otherwise get garbage,
3299 * an exception may get thrown while decoding the ASN.1 header.
3300 * Catch it, just in case.
3302 TRY {
3303 id_offset = get_ber_identifier(encr_tvb, CONFOUNDER_PLUS_CHECKSUM, &cls, &pc, &tag);
3304 offset = get_ber_length(encr_tvb, id_offset, &item_len, &ind);
3306 CATCH_BOUNDS_ERRORS {
3307 tvb_free(encr_tvb);
3308 do_continue = true;
3310 ENDTRY;
3312 if (do_continue) continue;
3314 data_len = item_len + offset - CONFOUNDER_PLUS_CHECKSUM;
3315 if ((int) item_len + offset > length) {
3316 tvb_free(encr_tvb);
3317 continue;
3320 if (gcry_md_open(&md5_handle, GCRY_MD_MD5, 0)) {
3321 return NULL;
3323 gcry_md_write(md5_handle, confounder, 8);
3324 gcry_md_write(md5_handle, zero_fill, 16);
3325 gcry_md_write(md5_handle, decrypted_data + CONFOUNDER_PLUS_CHECKSUM, data_len);
3326 digest = gcry_md_read(md5_handle, 0);
3328 digest_ok = (tvb_memeql (encr_tvb, 8, digest, HASH_MD5_LENGTH) == 0);
3329 gcry_md_close(md5_handle);
3330 if (digest_ok) {
3331 plaintext = (uint8_t* )tvb_memdup(pinfo->pool, encr_tvb, CONFOUNDER_PLUS_CHECKSUM, data_len);
3332 tvb_free(encr_tvb);
3334 if (datalen) {
3335 *datalen = data_len;
3337 return plaintext;
3339 tvb_free(encr_tvb);
3342 return NULL;
3345 #endif /* HAVE_MIT_KERBEROS / HAVE_HEIMDAL_KERBEROS / HAVE_LIBNETTLE */
3347 #ifdef NEED_DECRYPT_KRB5_KRB_CFX_DCE_NOOP
3348 tvbuff_t *
3349 decrypt_krb5_krb_cfx_dce(proto_tree *tree _U_,
3350 packet_info *pinfo _U_,
3351 int usage _U_,
3352 int keytype _U_,
3353 tvbuff_t *gssapi_header_tvb _U_,
3354 tvbuff_t *gssapi_encrypted_tvb _U_,
3355 tvbuff_t *gssapi_trailer_tvb _U_,
3356 tvbuff_t *checksum_tvb _U_)
3358 return NULL;
3360 #endif /* NEED_DECRYPT_KRB5_KRB_CFX_DCE_NOOP */
3362 #define INET6_ADDRLEN 16
3364 /* TCP Record Mark */
3365 #define KRB_RM_RESERVED 0x80000000U
3366 #define KRB_RM_RECLEN 0x7fffffffU
3368 #define KRB5_MSG_TICKET 1 /* Ticket */
3369 #define KRB5_MSG_AUTHENTICATOR 2 /* Authenticator */
3370 #define KRB5_MSG_ENC_TICKET_PART 3 /* EncTicketPart */
3371 #define KRB5_MSG_AS_REQ 10 /* AS-REQ type */
3372 #define KRB5_MSG_AS_REP 11 /* AS-REP type */
3373 #define KRB5_MSG_TGS_REQ 12 /* TGS-REQ type */
3374 #define KRB5_MSG_TGS_REP 13 /* TGS-REP type */
3375 #define KRB5_MSG_AP_REQ 14 /* AP-REQ type */
3376 #define KRB5_MSG_AP_REP 15 /* AP-REP type */
3377 #define KRB5_MSG_TGT_REQ 16 /* TGT-REQ type */
3378 #define KRB5_MSG_TGT_REP 17 /* TGT-REP type */
3380 #define KRB5_MSG_SAFE 20 /* KRB-SAFE type */
3381 #define KRB5_MSG_PRIV 21 /* KRB-PRIV type */
3382 #define KRB5_MSG_CRED 22 /* KRB-CRED type */
3383 #define KRB5_MSG_ENC_AS_REP_PART 25 /* EncASRepPart */
3384 #define KRB5_MSG_ENC_TGS_REP_PART 26 /* EncTGSRepPart */
3385 #define KRB5_MSG_ENC_AP_REP_PART 27 /* EncAPRepPart */
3386 #define KRB5_MSG_ENC_KRB_PRIV_PART 28 /* EncKrbPrivPart */
3387 #define KRB5_MSG_ENC_KRB_CRED_PART 29 /* EncKrbCredPart */
3388 #define KRB5_MSG_ERROR 30 /* KRB-ERROR type */
3390 #define KRB5_CHKSUM_GSSAPI 0x8003
3392 * For KERB_ENCTYPE_RC4_HMAC and KERB_ENCTYPE_RC4_HMAC_EXP, see
3394 * https://tools.ietf.org/html/draft-brezak-win2k-krb-rc4-hmac-04
3396 * unless it's expired.
3399 /* Principal name-type */
3400 #define KRB5_NT_UNKNOWN 0
3401 #define KRB5_NT_PRINCIPAL 1
3402 #define KRB5_NT_SRV_INST 2
3403 #define KRB5_NT_SRV_HST 3
3404 #define KRB5_NT_SRV_XHST 4
3405 #define KRB5_NT_UID 5
3406 #define KRB5_NT_X500_PRINCIPAL 6
3407 #define KRB5_NT_SMTP_NAME 7
3408 #define KRB5_NT_ENTERPRISE 10
3411 * MS specific name types, from
3413 * http://msdn.microsoft.com/library/en-us/security/security/kerb_external_name.asp
3415 #define KRB5_NT_MS_PRINCIPAL -128
3416 #define KRB5_NT_MS_PRINCIPAL_AND_SID -129
3417 #define KRB5_NT_ENT_PRINCIPAL_AND_SID -130
3418 #define KRB5_NT_PRINCIPAL_AND_SID -131
3419 #define KRB5_NT_SRV_INST_AND_SID -132
3421 /* error table constants */
3422 /* I prefixed the krb5_err.et constant names with KRB5_ET_ for these */
3423 #define KRB5_ET_KRB5KDC_ERR_NONE 0
3424 #define KRB5_ET_KRB5KDC_ERR_NAME_EXP 1
3425 #define KRB5_ET_KRB5KDC_ERR_SERVICE_EXP 2
3426 #define KRB5_ET_KRB5KDC_ERR_BAD_PVNO 3
3427 #define KRB5_ET_KRB5KDC_ERR_C_OLD_MAST_KVNO 4
3428 #define KRB5_ET_KRB5KDC_ERR_S_OLD_MAST_KVNO 5
3429 #define KRB5_ET_KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN 6
3430 #define KRB5_ET_KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN 7
3431 #define KRB5_ET_KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE 8
3432 #define KRB5_ET_KRB5KDC_ERR_NULL_KEY 9
3433 #define KRB5_ET_KRB5KDC_ERR_CANNOT_POSTDATE 10
3434 #define KRB5_ET_KRB5KDC_ERR_NEVER_VALID 11
3435 #define KRB5_ET_KRB5KDC_ERR_POLICY 12
3436 #define KRB5_ET_KRB5KDC_ERR_BADOPTION 13
3437 #define KRB5_ET_KRB5KDC_ERR_ETYPE_NOSUPP 14
3438 #define KRB5_ET_KRB5KDC_ERR_SUMTYPE_NOSUPP 15
3439 #define KRB5_ET_KRB5KDC_ERR_PADATA_TYPE_NOSUPP 16
3440 #define KRB5_ET_KRB5KDC_ERR_TRTYPE_NOSUPP 17
3441 #define KRB5_ET_KRB5KDC_ERR_CLIENT_REVOKED 18
3442 #define KRB5_ET_KRB5KDC_ERR_SERVICE_REVOKED 19
3443 #define KRB5_ET_KRB5KDC_ERR_TGT_REVOKED 20
3444 #define KRB5_ET_KRB5KDC_ERR_CLIENT_NOTYET 21
3445 #define KRB5_ET_KRB5KDC_ERR_SERVICE_NOTYET 22
3446 #define KRB5_ET_KRB5KDC_ERR_KEY_EXP 23
3447 #define KRB5_ET_KRB5KDC_ERR_PREAUTH_FAILED 24
3448 #define KRB5_ET_KRB5KDC_ERR_PREAUTH_REQUIRED 25
3449 #define KRB5_ET_KRB5KDC_ERR_SERVER_NOMATCH 26
3450 #define KRB5_ET_KRB5KDC_ERR_MUST_USE_USER2USER 27
3451 #define KRB5_ET_KRB5KDC_ERR_PATH_NOT_ACCEPTED 28
3452 #define KRB5_ET_KRB5KDC_ERR_SVC_UNAVAILABLE 29
3453 #define KRB5_ET_KRB5KRB_AP_ERR_BAD_INTEGRITY 31
3454 #define KRB5_ET_KRB5KRB_AP_ERR_TKT_EXPIRED 32
3455 #define KRB5_ET_KRB5KRB_AP_ERR_TKT_NYV 33
3456 #define KRB5_ET_KRB5KRB_AP_ERR_REPEAT 34
3457 #define KRB5_ET_KRB5KRB_AP_ERR_NOT_US 35
3458 #define KRB5_ET_KRB5KRB_AP_ERR_BADMATCH 36
3459 #define KRB5_ET_KRB5KRB_AP_ERR_SKEW 37
3460 #define KRB5_ET_KRB5KRB_AP_ERR_BADADDR 38
3461 #define KRB5_ET_KRB5KRB_AP_ERR_BADVERSION 39
3462 #define KRB5_ET_KRB5KRB_AP_ERR_MSG_TYPE 40
3463 #define KRB5_ET_KRB5KRB_AP_ERR_MODIFIED 41
3464 #define KRB5_ET_KRB5KRB_AP_ERR_BADORDER 42
3465 #define KRB5_ET_KRB5KRB_AP_ERR_ILL_CR_TKT 43
3466 #define KRB5_ET_KRB5KRB_AP_ERR_BADKEYVER 44
3467 #define KRB5_ET_KRB5KRB_AP_ERR_NOKEY 45
3468 #define KRB5_ET_KRB5KRB_AP_ERR_MUT_FAIL 46
3469 #define KRB5_ET_KRB5KRB_AP_ERR_BADDIRECTION 47
3470 #define KRB5_ET_KRB5KRB_AP_ERR_METHOD 48
3471 #define KRB5_ET_KRB5KRB_AP_ERR_BADSEQ 49
3472 #define KRB5_ET_KRB5KRB_AP_ERR_INAPP_CKSUM 50
3473 #define KRB5_ET_KRB5KDC_AP_PATH_NOT_ACCEPTED 51
3474 #define KRB5_ET_KRB5KRB_ERR_RESPONSE_TOO_BIG 52
3475 #define KRB5_ET_KRB5KRB_ERR_GENERIC 60
3476 #define KRB5_ET_KRB5KRB_ERR_FIELD_TOOLONG 61
3477 #define KRB5_ET_KDC_ERROR_CLIENT_NOT_TRUSTED 62
3478 #define KRB5_ET_KDC_ERROR_KDC_NOT_TRUSTED 63
3479 #define KRB5_ET_KDC_ERROR_INVALID_SIG 64
3480 #define KRB5_ET_KDC_ERR_KEY_TOO_WEAK 65
3481 #define KRB5_ET_KDC_ERR_CERTIFICATE_MISMATCH 66
3482 #define KRB5_ET_KRB_AP_ERR_NO_TGT 67
3483 #define KRB5_ET_KDC_ERR_WRONG_REALM 68
3484 #define KRB5_ET_KRB_AP_ERR_USER_TO_USER_REQUIRED 69
3485 #define KRB5_ET_KDC_ERR_CANT_VERIFY_CERTIFICATE 70
3486 #define KRB5_ET_KDC_ERR_INVALID_CERTIFICATE 71
3487 #define KRB5_ET_KDC_ERR_REVOKED_CERTIFICATE 72
3488 #define KRB5_ET_KDC_ERR_REVOCATION_STATUS_UNKNOWN 73
3489 #define KRB5_ET_KDC_ERR_REVOCATION_STATUS_UNAVAILABLE 74
3490 #define KRB5_ET_KDC_ERR_CLIENT_NAME_MISMATCH 75
3491 #define KRB5_ET_KDC_ERR_KDC_NAME_MISMATCH 76
3492 #define KRB5_ET_KDC_ERR_PREAUTH_EXPIRED 90
3493 #define KRB5_ET_KDC_ERR_MORE_PREAUTH_DATA_REQUIRED 91
3494 #define KRB5_ET_KDC_ERR_PREAUTH_BAD_AUTHENTICATION_SET 92
3495 #define KRB5_ET_KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS 93
3497 static const value_string krb5_error_codes[] = {
3498 { KRB5_ET_KRB5KDC_ERR_NONE, "KRB5KDC_ERR_NONE" },
3499 { KRB5_ET_KRB5KDC_ERR_NAME_EXP, "KRB5KDC_ERR_NAME_EXP" },
3500 { KRB5_ET_KRB5KDC_ERR_SERVICE_EXP, "KRB5KDC_ERR_SERVICE_EXP" },
3501 { KRB5_ET_KRB5KDC_ERR_BAD_PVNO, "KRB5KDC_ERR_BAD_PVNO" },
3502 { KRB5_ET_KRB5KDC_ERR_C_OLD_MAST_KVNO, "KRB5KDC_ERR_C_OLD_MAST_KVNO" },
3503 { KRB5_ET_KRB5KDC_ERR_S_OLD_MAST_KVNO, "KRB5KDC_ERR_S_OLD_MAST_KVNO" },
3504 { KRB5_ET_KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN, "KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN" },
3505 { KRB5_ET_KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN, "KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN" },
3506 { KRB5_ET_KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE, "KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE" },
3507 { KRB5_ET_KRB5KDC_ERR_NULL_KEY, "KRB5KDC_ERR_NULL_KEY" },
3508 { KRB5_ET_KRB5KDC_ERR_CANNOT_POSTDATE, "KRB5KDC_ERR_CANNOT_POSTDATE" },
3509 { KRB5_ET_KRB5KDC_ERR_NEVER_VALID, "KRB5KDC_ERR_NEVER_VALID" },
3510 { KRB5_ET_KRB5KDC_ERR_POLICY, "KRB5KDC_ERR_POLICY" },
3511 { KRB5_ET_KRB5KDC_ERR_BADOPTION, "KRB5KDC_ERR_BADOPTION" },
3512 { KRB5_ET_KRB5KDC_ERR_ETYPE_NOSUPP, "KRB5KDC_ERR_ETYPE_NOSUPP" },
3513 { KRB5_ET_KRB5KDC_ERR_SUMTYPE_NOSUPP, "KRB5KDC_ERR_SUMTYPE_NOSUPP" },
3514 { KRB5_ET_KRB5KDC_ERR_PADATA_TYPE_NOSUPP, "KRB5KDC_ERR_PADATA_TYPE_NOSUPP" },
3515 { KRB5_ET_KRB5KDC_ERR_TRTYPE_NOSUPP, "KRB5KDC_ERR_TRTYPE_NOSUPP" },
3516 { KRB5_ET_KRB5KDC_ERR_CLIENT_REVOKED, "KRB5KDC_ERR_CLIENT_REVOKED" },
3517 { KRB5_ET_KRB5KDC_ERR_SERVICE_REVOKED, "KRB5KDC_ERR_SERVICE_REVOKED" },
3518 { KRB5_ET_KRB5KDC_ERR_TGT_REVOKED, "KRB5KDC_ERR_TGT_REVOKED" },
3519 { KRB5_ET_KRB5KDC_ERR_CLIENT_NOTYET, "KRB5KDC_ERR_CLIENT_NOTYET" },
3520 { KRB5_ET_KRB5KDC_ERR_SERVICE_NOTYET, "KRB5KDC_ERR_SERVICE_NOTYET" },
3521 { KRB5_ET_KRB5KDC_ERR_KEY_EXP, "KRB5KDC_ERR_KEY_EXP" },
3522 { KRB5_ET_KRB5KDC_ERR_PREAUTH_FAILED, "KRB5KDC_ERR_PREAUTH_FAILED" },
3523 { KRB5_ET_KRB5KDC_ERR_PREAUTH_REQUIRED, "KRB5KDC_ERR_PREAUTH_REQUIRED" },
3524 { KRB5_ET_KRB5KDC_ERR_SERVER_NOMATCH, "KRB5KDC_ERR_SERVER_NOMATCH" },
3525 { KRB5_ET_KRB5KDC_ERR_MUST_USE_USER2USER, "KRB5KDC_ERR_MUST_USE_USER2USER" },
3526 { KRB5_ET_KRB5KDC_ERR_PATH_NOT_ACCEPTED, "KRB5KDC_ERR_PATH_NOT_ACCEPTED" },
3527 { KRB5_ET_KRB5KDC_ERR_SVC_UNAVAILABLE, "KRB5KDC_ERR_SVC_UNAVAILABLE" },
3528 { KRB5_ET_KRB5KRB_AP_ERR_BAD_INTEGRITY, "KRB5KRB_AP_ERR_BAD_INTEGRITY" },
3529 { KRB5_ET_KRB5KRB_AP_ERR_TKT_EXPIRED, "KRB5KRB_AP_ERR_TKT_EXPIRED" },
3530 { KRB5_ET_KRB5KRB_AP_ERR_TKT_NYV, "KRB5KRB_AP_ERR_TKT_NYV" },
3531 { KRB5_ET_KRB5KRB_AP_ERR_REPEAT, "KRB5KRB_AP_ERR_REPEAT" },
3532 { KRB5_ET_KRB5KRB_AP_ERR_NOT_US, "KRB5KRB_AP_ERR_NOT_US" },
3533 { KRB5_ET_KRB5KRB_AP_ERR_BADMATCH, "KRB5KRB_AP_ERR_BADMATCH" },
3534 { KRB5_ET_KRB5KRB_AP_ERR_SKEW, "KRB5KRB_AP_ERR_SKEW" },
3535 { KRB5_ET_KRB5KRB_AP_ERR_BADADDR, "KRB5KRB_AP_ERR_BADADDR" },
3536 { KRB5_ET_KRB5KRB_AP_ERR_BADVERSION, "KRB5KRB_AP_ERR_BADVERSION" },
3537 { KRB5_ET_KRB5KRB_AP_ERR_MSG_TYPE, "KRB5KRB_AP_ERR_MSG_TYPE" },
3538 { KRB5_ET_KRB5KRB_AP_ERR_MODIFIED, "KRB5KRB_AP_ERR_MODIFIED" },
3539 { KRB5_ET_KRB5KRB_AP_ERR_BADORDER, "KRB5KRB_AP_ERR_BADORDER" },
3540 { KRB5_ET_KRB5KRB_AP_ERR_ILL_CR_TKT, "KRB5KRB_AP_ERR_ILL_CR_TKT" },
3541 { KRB5_ET_KRB5KRB_AP_ERR_BADKEYVER, "KRB5KRB_AP_ERR_BADKEYVER" },
3542 { KRB5_ET_KRB5KRB_AP_ERR_NOKEY, "KRB5KRB_AP_ERR_NOKEY" },
3543 { KRB5_ET_KRB5KRB_AP_ERR_MUT_FAIL, "KRB5KRB_AP_ERR_MUT_FAIL" },
3544 { KRB5_ET_KRB5KRB_AP_ERR_BADDIRECTION, "KRB5KRB_AP_ERR_BADDIRECTION" },
3545 { KRB5_ET_KRB5KRB_AP_ERR_METHOD, "KRB5KRB_AP_ERR_METHOD" },
3546 { KRB5_ET_KRB5KRB_AP_ERR_BADSEQ, "KRB5KRB_AP_ERR_BADSEQ" },
3547 { KRB5_ET_KRB5KRB_AP_ERR_INAPP_CKSUM, "KRB5KRB_AP_ERR_INAPP_CKSUM" },
3548 { KRB5_ET_KRB5KDC_AP_PATH_NOT_ACCEPTED, "KRB5KDC_AP_PATH_NOT_ACCEPTED" },
3549 { KRB5_ET_KRB5KRB_ERR_RESPONSE_TOO_BIG, "KRB5KRB_ERR_RESPONSE_TOO_BIG"},
3550 { KRB5_ET_KRB5KRB_ERR_GENERIC, "KRB5KRB_ERR_GENERIC" },
3551 { KRB5_ET_KRB5KRB_ERR_FIELD_TOOLONG, "KRB5KRB_ERR_FIELD_TOOLONG" },
3552 { KRB5_ET_KDC_ERROR_CLIENT_NOT_TRUSTED, "KDC_ERROR_CLIENT_NOT_TRUSTED" },
3553 { KRB5_ET_KDC_ERROR_KDC_NOT_TRUSTED, "KDC_ERROR_KDC_NOT_TRUSTED" },
3554 { KRB5_ET_KDC_ERROR_INVALID_SIG, "KDC_ERROR_INVALID_SIG" },
3555 { KRB5_ET_KDC_ERR_KEY_TOO_WEAK, "KDC_ERR_KEY_TOO_WEAK" },
3556 { KRB5_ET_KDC_ERR_CERTIFICATE_MISMATCH, "KDC_ERR_CERTIFICATE_MISMATCH" },
3557 { KRB5_ET_KRB_AP_ERR_NO_TGT, "KRB_AP_ERR_NO_TGT" },
3558 { KRB5_ET_KDC_ERR_WRONG_REALM, "KDC_ERR_WRONG_REALM" },
3559 { KRB5_ET_KRB_AP_ERR_USER_TO_USER_REQUIRED, "KRB_AP_ERR_USER_TO_USER_REQUIRED" },
3560 { KRB5_ET_KDC_ERR_CANT_VERIFY_CERTIFICATE, "KDC_ERR_CANT_VERIFY_CERTIFICATE" },
3561 { KRB5_ET_KDC_ERR_INVALID_CERTIFICATE, "KDC_ERR_INVALID_CERTIFICATE" },
3562 { KRB5_ET_KDC_ERR_REVOKED_CERTIFICATE, "KDC_ERR_REVOKED_CERTIFICATE" },
3563 { KRB5_ET_KDC_ERR_REVOCATION_STATUS_UNKNOWN, "KDC_ERR_REVOCATION_STATUS_UNKNOWN" },
3564 { KRB5_ET_KDC_ERR_REVOCATION_STATUS_UNAVAILABLE, "KDC_ERR_REVOCATION_STATUS_UNAVAILABLE" },
3565 { KRB5_ET_KDC_ERR_CLIENT_NAME_MISMATCH, "KDC_ERR_CLIENT_NAME_MISMATCH" },
3566 { KRB5_ET_KDC_ERR_KDC_NAME_MISMATCH, "KDC_ERR_KDC_NAME_MISMATCH" },
3567 { KRB5_ET_KDC_ERR_PREAUTH_EXPIRED, "KDC_ERR_PREAUTH_EXPIRED" },
3568 { KRB5_ET_KDC_ERR_MORE_PREAUTH_DATA_REQUIRED, "KDC_ERR_MORE_PREAUTH_DATA_REQUIRED" },
3569 { KRB5_ET_KDC_ERR_PREAUTH_BAD_AUTHENTICATION_SET, "KDC_ERR_PREAUTH_BAD_AUTHENTICATION_SET" },
3570 { KRB5_ET_KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS, "KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS" },
3571 { 0, NULL }
3575 #define PAC_LOGON_INFO 1
3576 #define PAC_CREDENTIAL_TYPE 2
3577 #define PAC_SERVER_CHECKSUM 6
3578 #define PAC_PRIVSVR_CHECKSUM 7
3579 #define PAC_CLIENT_INFO_TYPE 10
3580 #define PAC_S4U_DELEGATION_INFO 11
3581 #define PAC_UPN_DNS_INFO 12
3582 #define PAC_CLIENT_CLAIMS_INFO 13
3583 #define PAC_DEVICE_INFO 14
3584 #define PAC_DEVICE_CLAIMS_INFO 15
3585 #define PAC_TICKET_CHECKSUM 16
3586 #define PAC_ATTRIBUTES_INFO 17
3587 #define PAC_REQUESTER_SID 18
3588 #define PAC_FULL_CHECKSUM 19
3589 static const value_string w2k_pac_types[] = {
3590 { PAC_LOGON_INFO , "Logon Info" },
3591 { PAC_CREDENTIAL_TYPE , "Credential Type" },
3592 { PAC_SERVER_CHECKSUM , "Server Checksum" },
3593 { PAC_PRIVSVR_CHECKSUM , "Privsvr Checksum" },
3594 { PAC_CLIENT_INFO_TYPE , "Client Info Type" },
3595 { PAC_S4U_DELEGATION_INFO , "S4U Delegation Info" },
3596 { PAC_UPN_DNS_INFO , "UPN DNS Info" },
3597 { PAC_CLIENT_CLAIMS_INFO , "Client Claims Info" },
3598 { PAC_DEVICE_INFO , "Device Info" },
3599 { PAC_DEVICE_CLAIMS_INFO , "Device Claims Info" },
3600 { PAC_TICKET_CHECKSUM , "Ticket Checksum" },
3601 { PAC_ATTRIBUTES_INFO , "Attributes Info" },
3602 { PAC_REQUESTER_SID , "Requester Sid" },
3603 { PAC_FULL_CHECKSUM , "Full Checksum" },
3604 { 0, NULL },
3607 static const value_string krb5_msg_types[] = {
3608 { KRB5_MSG_TICKET, "Ticket" },
3609 { KRB5_MSG_AUTHENTICATOR, "Authenticator" },
3610 { KRB5_MSG_ENC_TICKET_PART, "EncTicketPart" },
3611 { KRB5_MSG_TGS_REQ, "TGS-REQ" },
3612 { KRB5_MSG_TGS_REP, "TGS-REP" },
3613 { KRB5_MSG_AS_REQ, "AS-REQ" },
3614 { KRB5_MSG_AS_REP, "AS-REP" },
3615 { KRB5_MSG_AP_REQ, "AP-REQ" },
3616 { KRB5_MSG_AP_REP, "AP-REP" },
3617 { KRB5_MSG_TGT_REQ, "TGT-REQ" },
3618 { KRB5_MSG_TGT_REP, "TGT-REP" },
3619 { KRB5_MSG_SAFE, "KRB-SAFE" },
3620 { KRB5_MSG_PRIV, "KRB-PRIV" },
3621 { KRB5_MSG_CRED, "KRB-CRED" },
3622 { KRB5_MSG_ENC_AS_REP_PART, "EncASRepPart" },
3623 { KRB5_MSG_ENC_TGS_REP_PART, "EncTGSRepPart" },
3624 { KRB5_MSG_ENC_AP_REP_PART, "EncAPRepPart" },
3625 { KRB5_MSG_ENC_KRB_PRIV_PART, "EncKrbPrivPart" },
3626 { KRB5_MSG_ENC_KRB_CRED_PART, "EncKrbCredPart" },
3627 { KRB5_MSG_ERROR, "KRB-ERROR" },
3628 { 0, NULL },
3631 #define KRB5_GSS_C_DELEG_FLAG 0x00000001
3632 #define KRB5_GSS_C_MUTUAL_FLAG 0x00000002
3633 #define KRB5_GSS_C_REPLAY_FLAG 0x00000004
3634 #define KRB5_GSS_C_SEQUENCE_FLAG 0x00000008
3635 #define KRB5_GSS_C_CONF_FLAG 0x00000010
3636 #define KRB5_GSS_C_INTEG_FLAG 0x00000020
3637 #define KRB5_GSS_C_ANON_FLAG 0x00000040
3638 #define KRB5_GSS_C_PROT_READY_FLAG 0x00000080
3639 #define KRB5_GSS_C_TRANS_FLAG 0x00000100
3640 #define KRB5_GSS_C_DCE_STYLE 0x00001000
3641 #define KRB5_GSS_C_IDENTIFY_FLAG 0x00002000
3642 #define KRB5_GSS_C_EXTENDED_ERROR_FLAG 0x00004000
3643 #define KRB5_GSS_C_DELEG_POLICY_FLAG 0x00008000
3645 static const true_false_string tfs_gss_flags_deleg = {
3646 "Delegate credentials to remote peer",
3647 "Do NOT delegate"
3649 static const true_false_string tfs_gss_flags_mutual = {
3650 "Request that remote peer authenticates itself",
3651 "Mutual authentication NOT required"
3653 static const true_false_string tfs_gss_flags_replay = {
3654 "Enable replay protection for signed or sealed messages",
3655 "Do NOT enable replay protection"
3657 static const true_false_string tfs_gss_flags_sequence = {
3658 "Enable Out-of-sequence detection for sign or sealed messages",
3659 "Do NOT enable out-of-sequence detection"
3661 static const true_false_string tfs_gss_flags_conf = {
3662 "Confidentiality (sealing) may be invoked",
3663 "Do NOT use Confidentiality (sealing)"
3665 static const true_false_string tfs_gss_flags_integ = {
3666 "Integrity protection (signing) may be invoked",
3667 "Do NOT use integrity protection"
3670 static const true_false_string tfs_gss_flags_integ = {
3671 "Anonymous",
3672 "Do NOT use integrity protection"
3674 static const true_false_string tfs_gss_flags_dce_style = {
3675 "DCE-STYLE",
3676 "Not using DCE-STYLE"
3679 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)
3681 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
3682 proto_item *pi1 = proto_item_get_parent(actx->created_item);
3683 proto_item *pi2 = proto_item_get_parent(pi1);
3684 int8_t ber_class;
3685 bool pc;
3686 int32_t tag;
3689 * dissect_ber_octet_string_wcb() always passes
3690 * implicit_tag=false, offset=0 and hf_index=-1
3692 ws_assert(implicit_tag == false);
3693 ws_assert(offset == 0);
3694 ws_assert(hf_index <= 0);
3696 get_ber_identifier(tvb, offset, &ber_class, &pc, &tag);
3697 if (ber_class != BER_CLASS_APP) {
3698 if (kerberos_private_is_kdc_req(private_data)) {
3699 goto unknown;
3701 if (private_data->errorcode != KRB5_ET_KRB5KDC_ERR_PREAUTH_REQUIRED) {
3702 goto unknown;
3705 proto_item_append_text(pi1, " KRB5_SRP_PA_ANNOUNCE");
3706 proto_item_append_text(pi2, ": KRB5_SRP_PA_ANNOUNCE");
3707 return dissect_kerberos_KRB5_SRP_PA_ANNOUNCE(implicit_tag, tvb, offset, actx, tree, hf_index);
3710 switch (tag) {
3711 case 0:
3712 proto_item_append_text(pi1, " KRB5_SRP_PA_INIT");
3713 proto_item_append_text(pi2, ": KRB5_SRP_PA_INIT");
3714 return dissect_kerberos_KRB5_SRP_PA_INIT(implicit_tag, tvb, offset, actx, tree, hf_index);
3715 case 1:
3716 proto_item_append_text(pi1, " KRB5_SRP_PA_SERVER_CHALLENGE");
3717 proto_item_append_text(pi2, ": KRB5_SRP_PA_SERVER_CHALLENGE");
3718 return dissect_kerberos_KRB5_SRP_PA_SERVER_CHALLENGE(implicit_tag, tvb, offset, actx, tree, hf_index);
3719 case 2:
3720 proto_item_append_text(pi1, " KRB5_SRP_PA_CLIENT_RESPONSE");
3721 proto_item_append_text(pi2, ": KRB5_SRP_PA_CLIENT_RESPONSE");
3722 return dissect_kerberos_KRB5_SRP_PA_CLIENT_RESPONSE(implicit_tag, tvb, offset, actx, tree, hf_index);
3723 case 3:
3724 proto_item_append_text(pi1, " KRB5_SRP_PA_SERVER_VERIFIER");
3725 proto_item_append_text(pi2, ": KRB5_SRP_PA_SERVER_VERIFIER");
3726 return dissect_kerberos_KRB5_SRP_PA_SERVER_VERIFIER(implicit_tag, tvb, offset, actx, tree, hf_index);
3727 default:
3728 break;
3731 unknown:
3732 proto_item_append_text(pi1, " KRB5_SRP_PA_UNKNOWN: ber_class:%u ber_pc=%u ber_tag:%"PRIu32"", ber_class, pc, tag);
3733 proto_item_append_text(pi2, ": KRB5_SRP_PA_UNKNOWN");
3734 return tvb_reported_length_remaining(tvb, offset);
3737 #ifdef HAVE_KERBEROS
3738 static uint8_t *
3739 decrypt_krb5_data_asn1(proto_tree *tree, asn1_ctx_t *actx,
3740 int usage, tvbuff_t *cryptotvb, int *datalen)
3742 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
3744 #ifdef HAVE_DECRYPT_KRB5_DATA_PRIVATE
3745 return decrypt_krb5_data_private(tree, actx->pinfo, private_data,
3746 usage, cryptotvb,
3747 private_data->etype,
3748 datalen);
3749 #else
3750 return decrypt_krb5_data(tree, actx->pinfo, usage, cryptotvb,
3751 private_data->etype, datalen);
3752 #endif
3755 static int
3756 dissect_krb5_decrypt_ticket_data (bool imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
3757 proto_tree *tree, int hf_index _U_)
3759 uint8_t *plaintext;
3760 int length;
3761 tvbuff_t *next_tvb;
3763 next_tvb=tvb_new_subset_remaining(tvb, offset);
3764 length=tvb_captured_length_remaining(tvb, offset);
3766 /* draft-ietf-krb-wg-kerberos-clarifications-05.txt :
3767 * 7.5.1
3768 * All Ticket encrypted parts use usage == 2
3770 plaintext=decrypt_krb5_data_asn1(tree, actx, 2, next_tvb, &length);
3772 if(plaintext){
3773 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
3774 tvbuff_t *last_ticket_enc_part_tvb = private_data->last_ticket_enc_part_tvb;
3775 enc_key_t *current_ticket_key = private_data->current_ticket_key;
3776 tvbuff_t *child_tvb;
3777 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
3779 /* Add the decrypted data to the data source list. */
3780 add_new_data_source(actx->pinfo, child_tvb, "Krb5 Ticket");
3782 private_data->last_ticket_enc_part_tvb = child_tvb;
3783 private_data->current_ticket_key = NULL;
3784 offset=dissect_kerberos_Applications(false, child_tvb, 0, actx , tree, /* hf_index*/ -1);
3785 private_data->current_ticket_key = current_ticket_key;
3786 private_data->last_ticket_enc_part_tvb = last_ticket_enc_part_tvb;
3788 return offset;
3791 static int
3792 dissect_krb5_decrypt_authenticator_data (bool imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
3793 proto_tree *tree, int hf_index _U_)
3795 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
3796 uint8_t *plaintext;
3797 int length;
3798 tvbuff_t *next_tvb;
3800 next_tvb=tvb_new_subset_remaining(tvb, offset);
3801 length=tvb_captured_length_remaining(tvb, offset);
3803 /* draft-ietf-krb-wg-kerberos-clarifications-05.txt :
3804 * 7.5.1
3805 * Authenticators are encrypted with usage
3806 * == 7 or
3807 * == 11
3809 * 7. TGS-REQ PA-TGS-REQ padata AP-REQ Authenticator
3810 * (includes TGS authenticator subkey), encrypted with the
3811 * TGS session key (section 5.5.1)
3812 * 11. AP-REQ Authenticator (includes application
3813 * authenticator subkey), encrypted with the application
3814 * session key (section 5.5.1)
3816 if (private_data->within_PA_TGS_REQ > 0) {
3817 plaintext=decrypt_krb5_data_asn1(tree, actx, 7, next_tvb, &length);
3818 } else {
3819 plaintext=decrypt_krb5_data_asn1(tree, actx, 11, next_tvb, &length);
3822 if(plaintext){
3823 tvbuff_t *child_tvb;
3824 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
3826 /* Add the decrypted data to the data source list. */
3827 add_new_data_source(actx->pinfo, child_tvb, "Krb5 Authenticator");
3829 offset=dissect_kerberos_Applications(false, child_tvb, 0, actx , tree, /* hf_index*/ -1);
3831 return offset;
3834 static int
3835 dissect_krb5_decrypt_authorization_data(bool imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
3836 proto_tree *tree, int hf_index _U_)
3838 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
3839 uint8_t *plaintext;
3840 int length;
3841 tvbuff_t *next_tvb;
3843 next_tvb=tvb_new_subset_remaining(tvb, offset);
3844 length=tvb_captured_length_remaining(tvb, offset);
3846 /* draft-ietf-krb-wg-kerberos-clarifications-05.txt :
3847 * 7.5.1
3848 * Authenticators are encrypted with usage
3849 * == 5 or
3850 * == 4
3852 * 4. TGS-REQ KDC-REQ-BODY AuthorizationData, encrypted with
3853 * the TGS session key (section 5.4.1)
3854 * 5. TGS-REQ KDC-REQ-BODY AuthorizationData, encrypted with
3855 * the TGS authenticator subkey (section 5.4.1)
3857 if (private_data->PA_TGS_REQ_subkey != NULL) {
3858 plaintext=decrypt_krb5_data_asn1(tree, actx, 5, next_tvb, &length);
3859 } else {
3860 plaintext=decrypt_krb5_data_asn1(tree, actx, 4, next_tvb, &length);
3863 if(plaintext){
3864 tvbuff_t *child_tvb;
3865 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
3867 /* Add the decrypted data to the data source list. */
3868 add_new_data_source(actx->pinfo, child_tvb, "Krb5 AuthorizationData");
3870 offset=dissect_kerberos_AuthorizationData(false, child_tvb, 0, actx , tree, /* hf_index*/ -1);
3872 return offset;
3875 static int
3876 dissect_krb5_decrypt_KDC_REP_data (bool imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
3877 proto_tree *tree, int hf_index _U_)
3879 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
3880 uint8_t *plaintext = NULL;
3881 int length;
3882 tvbuff_t *next_tvb;
3884 next_tvb=tvb_new_subset_remaining(tvb, offset);
3885 length=tvb_captured_length_remaining(tvb, offset);
3887 /* draft-ietf-krb-wg-kerberos-clarifications-05.txt :
3888 * 7.5.1
3889 * ASREP/TGSREP encryptedparts are encrypted with usage
3890 * == 3 or
3891 * == 8 or
3892 * == 9
3894 * 3. AS-REP encrypted part (includes TGS session key or
3895 * application session key), encrypted with the client key
3896 * (section 5.4.2)
3898 * 8. TGS-REP encrypted part (includes application session
3899 * key), encrypted with the TGS session key (section
3900 * 5.4.2)
3901 * 9. TGS-REP encrypted part (includes application session
3902 * key), encrypted with the TGS authenticator subkey
3903 * (section 5.4.2)
3905 * We currently don't have a way to find the TGS-REQ state
3906 * in order to check if an authenticator subkey was used.
3908 * But if we client used FAST and we got a strengthen_key,
3909 * we're sure an authenticator subkey was used.
3911 * Windows don't use an authenticator subkey without FAST,
3912 * but heimdal does.
3914 * For now try 8 before 9 in order to avoid overhead and false
3915 * positives for the 'kerberos.missing_keytype' filter in pure
3916 * windows captures.
3918 switch (private_data->msg_type) {
3919 case KERBEROS_APPLICATIONS_AS_REP:
3920 plaintext=decrypt_krb5_data_asn1(tree, actx, 3, next_tvb, &length);
3921 break;
3922 case KERBEROS_APPLICATIONS_TGS_REP:
3923 if (private_data->fast_strengthen_key != NULL) {
3924 plaintext=decrypt_krb5_data_asn1(tree, actx, 9, next_tvb, &length);
3925 } else {
3926 plaintext=decrypt_krb5_data_asn1(tree, actx, 8, next_tvb, &length);
3927 if(!plaintext){
3928 plaintext=decrypt_krb5_data_asn1(tree, actx, 9, next_tvb, &length);
3931 break;
3934 if(plaintext){
3935 tvbuff_t *child_tvb;
3936 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
3938 /* Add the decrypted data to the data source list. */
3939 add_new_data_source(actx->pinfo, child_tvb, "Krb5 KDC-REP");
3941 offset=dissect_kerberos_Applications(false, child_tvb, 0, actx , tree, /* hf_index*/ -1);
3943 return offset;
3946 static int
3947 dissect_krb5_decrypt_PA_ENC_TIMESTAMP (bool imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
3948 proto_tree *tree, int hf_index _U_)
3950 uint8_t *plaintext;
3951 int length;
3952 tvbuff_t *next_tvb;
3954 next_tvb=tvb_new_subset_remaining(tvb, offset);
3955 length=tvb_captured_length_remaining(tvb, offset);
3957 /* draft-ietf-krb-wg-kerberos-clarifications-05.txt :
3958 * 7.5.1
3959 * AS-REQ PA_ENC_TIMESTAMP are encrypted with usage
3960 * == 1
3962 plaintext=decrypt_krb5_data_asn1(tree, actx, 1, next_tvb, &length);
3964 if(plaintext){
3965 tvbuff_t *child_tvb;
3966 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
3968 /* Add the decrypted data to the data source list. */
3969 add_new_data_source(actx->pinfo, child_tvb, "Krb5 EncTimestamp");
3971 offset=dissect_kerberos_PA_ENC_TS_ENC(false, child_tvb, 0, actx , tree, /* hf_index*/ -1);
3973 return offset;
3976 static int
3977 dissect_krb5_decrypt_AP_REP_data (bool imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
3978 proto_tree *tree, int hf_index _U_)
3980 uint8_t *plaintext;
3981 int length;
3982 tvbuff_t *next_tvb;
3984 next_tvb=tvb_new_subset_remaining(tvb, offset);
3985 length=tvb_captured_length_remaining(tvb, offset);
3987 /* draft-ietf-krb-wg-kerberos-clarifications-05.txt :
3988 * 7.5.1
3989 * AP-REP are encrypted with usage == 12
3991 plaintext=decrypt_krb5_data_asn1(tree, actx, 12, next_tvb, &length);
3993 if(plaintext){
3994 tvbuff_t *child_tvb;
3995 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
3997 /* Add the decrypted data to the data source list. */
3998 add_new_data_source(actx->pinfo, child_tvb, "Krb5 AP-REP");
4000 offset=dissect_kerberos_Applications(false, child_tvb, 0, actx , tree, /* hf_index*/ -1);
4002 return offset;
4005 static int
4006 dissect_krb5_decrypt_PRIV_data (bool imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
4007 proto_tree *tree, int hf_index _U_)
4009 uint8_t *plaintext;
4010 int length;
4011 tvbuff_t *next_tvb;
4013 next_tvb=tvb_new_subset_remaining(tvb, offset);
4014 length=tvb_captured_length_remaining(tvb, offset);
4016 /* RFC4120 :
4017 * EncKrbPrivPart encrypted with usage
4018 * == 13
4020 plaintext=decrypt_krb5_data_asn1(tree, actx, 13, next_tvb, &length);
4022 if(plaintext){
4023 tvbuff_t *child_tvb;
4024 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
4026 /* Add the decrypted data to the data source list. */
4027 add_new_data_source(actx->pinfo, child_tvb, "Krb5 PRIV");
4029 offset=dissect_kerberos_Applications(false, child_tvb, 0, actx , tree, /* hf_index*/ -1);
4031 return offset;
4034 static int
4035 dissect_krb5_decrypt_CRED_data (bool imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
4036 proto_tree *tree, int hf_index _U_)
4038 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
4039 uint8_t *plaintext;
4040 int length;
4041 tvbuff_t *next_tvb;
4043 next_tvb=tvb_new_subset_remaining(tvb, offset);
4044 length=tvb_captured_length_remaining(tvb, offset);
4046 if (private_data->etype == 0) {
4047 offset=dissect_kerberos_Applications(false, next_tvb, 0, actx , tree, /* hf_index*/ -1);
4048 return offset;
4051 /* RFC4120 :
4052 * EncKrbCredPart encrypted with usage
4053 * == 14
4055 plaintext=decrypt_krb5_data_asn1(tree, actx, 14, next_tvb, &length);
4057 if(plaintext){
4058 tvbuff_t *child_tvb;
4059 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
4061 /* Add the decrypted data to the data source list. */
4062 add_new_data_source(actx->pinfo, child_tvb, "Krb5 CRED");
4064 offset=dissect_kerberos_Applications(false, child_tvb, 0, actx , tree, /* hf_index*/ -1);
4066 return offset;
4069 static int
4070 dissect_krb5_decrypt_KrbFastReq(bool imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
4071 proto_tree *tree, int hf_index _U_)
4073 uint8_t *plaintext;
4074 int length;
4075 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
4076 tvbuff_t *next_tvb;
4078 next_tvb=tvb_new_subset_remaining(tvb, offset);
4079 length=tvb_captured_length_remaining(tvb, offset);
4081 private_data->fast_armor_key = NULL;
4082 if (private_data->PA_FAST_ARMOR_AP_subkey != NULL) {
4083 krb5_fast_key(actx, tree, tvb,
4084 private_data->PA_FAST_ARMOR_AP_subkey,
4085 "subkeyarmor",
4086 private_data->PA_FAST_ARMOR_AP_key,
4087 "ticketarmor",
4088 "KrbFastReq_FAST_armorKey");
4089 if (private_data->PA_TGS_REQ_subkey != NULL) {
4090 enc_key_t *explicit_armor_key = private_data->last_added_key;
4093 * See [MS-KILE] 3.3.5.7.4 Compound Identity
4095 krb5_fast_key(actx, tree, tvb,
4096 explicit_armor_key,
4097 "explicitarmor",
4098 private_data->PA_TGS_REQ_subkey,
4099 "tgsarmor",
4100 "KrbFastReq_explicitArmorKey");
4102 private_data->fast_armor_key = private_data->last_added_key;
4103 } else if (private_data->PA_TGS_REQ_subkey != NULL) {
4104 krb5_fast_key(actx, tree, tvb,
4105 private_data->PA_TGS_REQ_subkey,
4106 "subkeyarmor",
4107 private_data->PA_TGS_REQ_key,
4108 "ticketarmor",
4109 "KrbFastReq_TGS_armorKey");
4110 private_data->fast_armor_key = private_data->last_added_key;
4113 /* RFC6113 :
4114 * KrbFastResponse encrypted with usage
4115 * KEY_USAGE_FAST_ENC 51
4117 plaintext=decrypt_krb5_data_asn1(tree, actx, KEY_USAGE_FAST_ENC,
4118 next_tvb, &length);
4120 if(plaintext){
4121 tvbuff_t *child_tvb;
4122 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
4124 /* Add the decrypted data to the data source list. */
4125 add_new_data_source(actx->pinfo, child_tvb, "Krb5 FastReq");
4127 offset=dissect_kerberos_KrbFastReq(false, child_tvb, 0, actx , tree, /* hf_index*/ -1);
4129 return offset;
4132 static int
4133 dissect_krb5_decrypt_KrbFastResponse(bool imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
4134 proto_tree *tree, int hf_index _U_)
4136 uint8_t *plaintext;
4137 int length;
4138 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
4139 tvbuff_t *next_tvb;
4141 next_tvb=tvb_new_subset_remaining(tvb, offset);
4142 length=tvb_captured_length_remaining(tvb, offset);
4145 * RFC6113 :
4146 * KrbFastResponse encrypted with usage
4147 * KEY_USAGE_FAST_REP 52
4149 plaintext=decrypt_krb5_data_asn1(tree, actx, KEY_USAGE_FAST_REP,
4150 next_tvb, &length);
4152 if(plaintext){
4153 tvbuff_t *child_tvb;
4154 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
4156 /* Add the decrypted data to the data source list. */
4157 add_new_data_source(actx->pinfo, child_tvb, "Krb5 FastRep");
4159 private_data->fast_armor_key = private_data->last_decryption_key;
4160 offset=dissect_kerberos_KrbFastResponse(false, child_tvb, 0, actx , tree, /* hf_index*/ -1);
4162 return offset;
4165 static int
4166 dissect_krb5_decrypt_EncryptedChallenge(bool imp_tag _U_, tvbuff_t *tvb, int offset, asn1_ctx_t *actx,
4167 proto_tree *tree, int hf_index _U_)
4169 uint8_t *plaintext;
4170 int length;
4171 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
4172 tvbuff_t *next_tvb;
4173 int usage = 0;
4174 const char *name = NULL;
4176 next_tvb=tvb_new_subset_remaining(tvb, offset);
4177 length=tvb_captured_length_remaining(tvb, offset);
4179 /* RFC6113 :
4180 * KEY_USAGE_ENC_CHALLENGE_CLIENT 54
4181 * KEY_USAGE_ENC_CHALLENGE_KDC 55
4183 if (kerberos_private_is_kdc_req(private_data)) {
4184 usage = KEY_USAGE_ENC_CHALLENGE_CLIENT;
4185 name = "Krb5 CHALLENGE_CLIENT";
4186 } else {
4187 usage = KEY_USAGE_ENC_CHALLENGE_KDC;
4188 name = "Krb5 CHALLENGE_KDC";
4190 plaintext=decrypt_krb5_data_asn1(tree, actx, usage, next_tvb, &length);
4192 if(plaintext){
4193 tvbuff_t *child_tvb;
4194 child_tvb = tvb_new_child_real_data(tvb, plaintext, length, length);
4196 /* Add the decrypted data to the data source list. */
4197 add_new_data_source(actx->pinfo, child_tvb, name);
4199 offset=dissect_kerberos_PA_ENC_TS_ENC(false, child_tvb, 0, actx , tree, /* hf_index*/ -1);
4201 return offset;
4203 #endif /* HAVE_KERBEROS */
4205 static int * const hf_krb_pa_supported_enctypes_fields[] = {
4206 &hf_krb_pa_supported_enctypes_des_cbc_crc,
4207 &hf_krb_pa_supported_enctypes_des_cbc_md5,
4208 &hf_krb_pa_supported_enctypes_rc4_hmac,
4209 &hf_krb_pa_supported_enctypes_aes128_cts_hmac_sha1_96,
4210 &hf_krb_pa_supported_enctypes_aes256_cts_hmac_sha1_96,
4211 &hf_krb_pa_supported_enctypes_aes256_cts_hmac_sha1_96_sk,
4212 &hf_krb_pa_supported_enctypes_fast_supported,
4213 &hf_krb_pa_supported_enctypes_compound_identity_supported,
4214 &hf_krb_pa_supported_enctypes_claims_supported,
4215 &hf_krb_pa_supported_enctypes_resource_sid_compression_disabled,
4216 NULL,
4219 static int
4220 dissect_kerberos_PA_SUPPORTED_ENCTYPES(bool implicit_tag _U_, tvbuff_t *tvb _U_,
4221 int offset _U_, asn1_ctx_t *actx _U_,
4222 proto_tree *tree _U_, int hf_index _U_)
4224 actx->created_item = proto_tree_add_bitmask(tree, tvb, offset,
4225 hf_krb_pa_supported_enctypes,
4226 ett_krb_pa_supported_enctypes,
4227 hf_krb_pa_supported_enctypes_fields,
4228 ENC_LITTLE_ENDIAN);
4229 offset += 4;
4231 return offset;
4234 static int * const hf_krb_ad_ap_options_fields[] = {
4235 &hf_krb_ad_ap_options_cbt,
4236 &hf_krb_ad_ap_options_unverified_target_name,
4237 NULL,
4241 static int
4242 dissect_kerberos_AD_AP_OPTIONS(bool implicit_tag _U_, tvbuff_t *tvb _U_,
4243 int offset _U_, asn1_ctx_t *actx _U_,
4244 proto_tree *tree _U_, int hf_index _U_)
4246 actx->created_item = proto_tree_add_bitmask(tree, tvb, offset,
4247 hf_krb_ad_ap_options,
4248 ett_krb_ad_ap_options,
4249 hf_krb_ad_ap_options_fields,
4250 ENC_LITTLE_ENDIAN);
4251 offset += 4;
4253 return offset;
4256 static int
4257 dissect_kerberos_AD_TARGET_PRINCIPAL(bool implicit_tag _U_, tvbuff_t *tvb _U_,
4258 int offset _U_, asn1_ctx_t *actx _U_,
4259 proto_tree *tree _U_, int hf_index _U_)
4261 int tp_offset, tp_len;
4262 uint16_t bc;
4264 bc = tvb_reported_length_remaining(tvb, offset);
4265 tp_offset = offset;
4266 tp_len = bc;
4267 proto_tree_add_item(tree, hf_krb_ad_target_principal, tvb,
4268 tp_offset, tp_len,
4269 ENC_UTF_16 | ENC_LITTLE_ENDIAN);
4271 return offset;
4274 /* Dissect a GSSAPI checksum as per RFC1964. This is NOT ASN.1 encoded.
4276 static int
4277 dissect_krb5_rfc1964_checksum(asn1_ctx_t *actx _U_, proto_tree *tree, tvbuff_t *tvb)
4279 int offset=0;
4280 uint32_t len;
4281 uint16_t dlglen;
4283 /* Length of Bnd field */
4284 len=tvb_get_letohl(tvb, offset);
4285 proto_tree_add_item(tree, hf_krb_gssapi_len, tvb, offset, 4, ENC_LITTLE_ENDIAN);
4286 offset += 4;
4288 /* Bnd field */
4289 proto_tree_add_item(tree, hf_krb_gssapi_bnd, tvb, offset, len, ENC_NA);
4290 offset += len;
4293 /* flags */
4294 proto_tree_add_item(tree, hf_krb_gssapi_c_flag_dce_style, tvb, offset, 4, ENC_LITTLE_ENDIAN);
4295 proto_tree_add_item(tree, hf_krb_gssapi_c_flag_integ, tvb, offset, 4, ENC_LITTLE_ENDIAN);
4296 proto_tree_add_item(tree, hf_krb_gssapi_c_flag_conf, tvb, offset, 4, ENC_LITTLE_ENDIAN);
4297 proto_tree_add_item(tree, hf_krb_gssapi_c_flag_sequence, tvb, offset, 4, ENC_LITTLE_ENDIAN);
4298 proto_tree_add_item(tree, hf_krb_gssapi_c_flag_replay, tvb, offset, 4, ENC_LITTLE_ENDIAN);
4299 proto_tree_add_item(tree, hf_krb_gssapi_c_flag_mutual, tvb, offset, 4, ENC_LITTLE_ENDIAN);
4300 proto_tree_add_item(tree, hf_krb_gssapi_c_flag_deleg, tvb, offset, 4, ENC_LITTLE_ENDIAN);
4301 offset += 4;
4303 /* the next fields are optional so we have to check that we have
4304 * more data in our buffers */
4305 if(tvb_reported_length_remaining(tvb, offset)<2){
4306 return offset;
4308 /* dlgopt identifier */
4309 proto_tree_add_item(tree, hf_krb_gssapi_dlgopt, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4310 offset += 2;
4312 if(tvb_reported_length_remaining(tvb, offset)<2){
4313 return offset;
4315 /* dlglen identifier */
4316 dlglen=tvb_get_letohs(tvb, offset);
4317 proto_tree_add_item(tree, hf_krb_gssapi_dlglen, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4318 offset += 2;
4320 if(dlglen!=tvb_reported_length_remaining(tvb, offset)){
4321 proto_tree_add_expert_format(tree, actx->pinfo, &ei_krb_gssapi_dlglen, tvb, 0, 0,
4322 "Error: DlgLen:%d is not the same as number of bytes remaining:%d", dlglen, tvb_captured_length_remaining(tvb, offset));
4323 return offset;
4326 /* this should now be a KRB_CRED message */
4327 offset=dissect_kerberos_Applications(false, tvb, offset, actx, tree, /* hf_index */ -1);
4329 return offset;
4332 static int
4333 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_)
4335 offset=dissect_ber_GeneralString(actx, tree, tvb, offset, hf_krb_provsrv_location, NULL, 0);
4337 return offset;
4340 static int
4341 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_)
4343 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
4344 int length;
4345 uint32_t nt_status = 0;
4346 uint32_t reserved = 0;
4347 uint32_t flags = 0;
4350 * Microsoft stores a special 12 byte blob here
4351 * [MS-KILE] 2.2.1 KERB-EXT-ERROR
4352 * uint32_t NT_status
4353 * uint32_t reserved (== 0)
4354 * uint32_t flags (at least 0x00000001 is set)
4356 length = tvb_reported_length_remaining(tvb, offset);
4357 if (length <= 0) {
4358 return offset;
4360 if (length != 12) {
4361 goto no_error;
4364 if (private_data->errorcode == 0) {
4365 goto no_error;
4368 nt_status = tvb_get_letohl(tvb, offset);
4369 reserved = tvb_get_letohl(tvb, offset + 4);
4370 flags = tvb_get_letohl(tvb, offset + 8);
4372 if (reserved != 0 || (flags & 1) != 1 || !try_val_to_str_ext(nt_status, &NT_errors_ext)) {
4373 goto no_error;
4376 proto_tree_add_item(tree, hf_krb_ext_error_nt_status, tvb, offset, 4,
4377 ENC_LITTLE_ENDIAN);
4378 col_append_fstr(actx->pinfo->cinfo, COL_INFO,
4379 " NT Status: %s",
4380 val_to_str_ext(nt_status, &NT_errors_ext,
4381 "Unknown error code %#x"));
4382 offset += 4;
4384 proto_tree_add_item(tree, hf_krb_ext_error_reserved, tvb, offset, 4,
4385 ENC_LITTLE_ENDIAN);
4386 offset += 4;
4388 proto_tree_add_item(tree, hf_krb_ext_error_flags, tvb, offset, 4,
4389 ENC_LITTLE_ENDIAN);
4390 offset += 4;
4392 return offset;
4394 no_error:
4395 proto_tree_add_item(tree, hf_krb_pw_salt, tvb, offset, length, ENC_NA);
4396 offset += length;
4398 return offset;
4401 static int
4402 dissect_krb5_PAC_DREP(proto_tree *parent_tree, tvbuff_t *tvb, int offset, uint8_t *drep)
4404 proto_tree *tree;
4405 uint8_t val;
4407 tree = proto_tree_add_subtree(parent_tree, tvb, offset, 16, ett_krb_pac_drep, NULL, "DREP");
4409 val = tvb_get_uint8(tvb, offset);
4410 proto_tree_add_uint(tree, hf_dcerpc_drep_byteorder, tvb, offset, 1, val>>4);
4412 offset++;
4414 if (drep) {
4415 *drep = val;
4418 return offset;
4421 /* This might be some sort of header that MIDL generates when creating
4422 * marshalling/unmarshalling code for blobs that are not to be transported
4423 * ontop of DCERPC and where the DREP fields specifying things such as
4424 * endianess and similar are not available.
4427 dissect_krb5_PAC_NDRHEADERBLOB(proto_tree *parent_tree, tvbuff_t *tvb, int offset, uint8_t *drep)
4429 proto_tree *tree;
4431 tree = proto_tree_add_subtree(parent_tree, tvb, offset, 16, ett_krb_pac_midl_blob, NULL, "MES header");
4433 /* modified DREP field that is used for stuff that is transporetd ontop
4434 of non dcerpc
4436 proto_tree_add_item(tree, hf_krb_midl_version, tvb, offset, 1, ENC_LITTLE_ENDIAN);
4437 offset++;
4439 offset = dissect_krb5_PAC_DREP(tree, tvb, offset, drep);
4442 proto_tree_add_item(tree, hf_krb_midl_hdr_len, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4443 offset+=2;
4445 proto_tree_add_item(tree, hf_krb_midl_fill_bytes, tvb, offset, 4, ENC_LITTLE_ENDIAN);
4446 offset += 4;
4448 /* length of blob that follows */
4449 proto_tree_add_item(tree, hf_krb_midl_blob_len, tvb, offset, 8, ENC_LITTLE_ENDIAN);
4450 offset += 8;
4452 return offset;
4455 static int
4456 dissect_krb5_PAC_LOGON_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
4458 proto_item *item;
4459 proto_tree *tree;
4460 uint8_t drep[4] = { 0x10, 0x00, 0x00, 0x00}; /* fake DREP struct */
4461 /* fake dcerpc_info struct */
4462 dcerpc_call_value call_data = { .flags = 0, };
4463 dcerpc_info di = { .ptype = UINT8_MAX, .call_data = &call_data, };
4465 item = proto_tree_add_item(parent_tree, hf_krb_pac_logon_info, tvb, offset, -1, ENC_NA);
4466 tree = proto_item_add_subtree(item, ett_krb_pac_logon_info);
4468 /* skip the first 16 bytes, they are some magic created by the idl
4469 * compiler the first 4 bytes might be flags?
4471 offset = dissect_krb5_PAC_NDRHEADERBLOB(tree, tvb, offset, &drep[0]);
4473 /* the PAC_LOGON_INFO blob */
4474 init_ndr_pointer_list(&di);
4475 offset = dissect_ndr_pointer(tvb, offset, actx->pinfo, tree, &di, drep,
4476 netlogon_dissect_PAC_LOGON_INFO, NDR_POINTER_UNIQUE,
4477 "PAC_LOGON_INFO:", -1);
4478 free_ndr_pointer_list(&di);
4480 return offset;
4484 static int
4485 dissect_krb5_PAC_CREDENTIAL_DATA(proto_tree *parent_tree, tvbuff_t *tvb, int offset, packet_info *pinfo _U_)
4487 proto_tree_add_item(parent_tree, hf_krb_pac_credential_data, tvb, offset, -1, ENC_NA);
4489 return offset;
4492 static int
4493 dissect_krb5_PAC_CREDENTIAL_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx)
4495 proto_item *item;
4496 proto_tree *tree;
4497 uint8_t *plaintext = NULL;
4498 int plainlen = 0;
4499 int length = 0;
4500 #define KRB5_KU_OTHER_ENCRYPTED 16
4501 #ifdef HAVE_KERBEROS
4502 uint32_t etype;
4503 tvbuff_t *next_tvb;
4504 int usage = KRB5_KU_OTHER_ENCRYPTED;
4505 #endif
4507 item = proto_tree_add_item(parent_tree, hf_krb_pac_credential_info, tvb, offset, -1, ENC_NA);
4508 tree = proto_item_add_subtree(item, ett_krb_pac_credential_info);
4510 /* version */
4511 proto_tree_add_item(tree, hf_krb_pac_credential_info_version, tvb,
4512 offset, 4, ENC_LITTLE_ENDIAN);
4513 offset+=4;
4515 #ifdef HAVE_KERBEROS
4516 /* etype */
4517 etype = tvb_get_letohl(tvb, offset);
4518 #endif
4519 proto_tree_add_item(tree, hf_krb_pac_credential_info_etype, tvb,
4520 offset, 4, ENC_LITTLE_ENDIAN);
4521 offset+=4;
4523 #ifdef HAVE_KERBEROS
4524 /* data */
4525 next_tvb=tvb_new_subset_remaining(tvb, offset);
4526 length=tvb_captured_length_remaining(tvb, offset);
4528 plaintext=decrypt_krb5_data(tree, actx->pinfo, usage, next_tvb, (int)etype, &plainlen);
4529 #endif
4531 if (plaintext != NULL) {
4532 tvbuff_t *child_tvb;
4533 child_tvb = tvb_new_child_real_data(tvb, plaintext, plainlen, plainlen);
4535 /* Add the decrypted data to the data source list. */
4536 add_new_data_source(actx->pinfo, child_tvb, "Krb5 PAC_CREDENTIAL");
4538 dissect_krb5_PAC_CREDENTIAL_DATA(tree, child_tvb, 0, actx->pinfo);
4541 return offset + length;
4544 static int
4545 dissect_krb5_PAC_S4U_DELEGATION_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx)
4547 proto_item *item;
4548 proto_tree *tree;
4549 uint8_t drep[4] = { 0x10, 0x00, 0x00, 0x00}; /* fake DREP struct */
4550 /* fake dcerpc_info struct */
4551 dcerpc_call_value call_data = { .flags = 0, };
4552 dcerpc_info di = { .ptype = UINT8_MAX, .call_data = &call_data, };
4554 item = proto_tree_add_item(parent_tree, hf_krb_pac_s4u_delegation_info, tvb, offset, -1, ENC_NA);
4555 tree = proto_item_add_subtree(item, ett_krb_pac_s4u_delegation_info);
4557 /* skip the first 16 bytes, they are some magic created by the idl
4558 * compiler the first 4 bytes might be flags?
4560 offset = dissect_krb5_PAC_NDRHEADERBLOB(tree, tvb, offset, &drep[0]);
4562 /* the S4U_DELEGATION_INFO blob. See [MS-PAC] */
4563 init_ndr_pointer_list(&di);
4564 offset = dissect_ndr_pointer(tvb, offset, actx->pinfo, tree, &di, drep,
4565 netlogon_dissect_PAC_S4U_DELEGATION_INFO, NDR_POINTER_UNIQUE,
4566 "PAC_S4U_DELEGATION_INFO:", -1);
4567 free_ndr_pointer_list(&di);
4569 return offset;
4572 #define PAC_UPN_DNS_FLAG_CONSTRUCTED 0x00000001
4573 #define PAC_UPN_DNS_FLAG_HAS_SAM_NAME_AND_SID 0x00000002
4574 static const true_false_string tfs_krb_pac_upn_flag_upn_constructed = {
4575 "UPN Name is Constructed",
4576 "UPN Name is NOT Constructed",
4578 static const true_false_string tfs_krb_pac_upn_flag_has_sam_name_and_sid = {
4579 "SAM_NAME and SID are included",
4580 "SAM_NAME and SID are NOT included",
4582 static int * const hf_krb_pac_upn_flags_fields[] = {
4583 &hf_krb_pac_upn_flag_upn_constructed,
4584 &hf_krb_pac_upn_flag_has_sam_name_and_sid,
4585 NULL
4588 static int
4589 dissect_krb5_PAC_UPN_DNS_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
4591 #ifdef HAVE_KERBEROS
4592 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
4593 #endif /* HAVE_KERBEROS */
4594 proto_item *item;
4595 proto_tree *tree;
4596 uint16_t dns_offset, dns_len;
4597 uint16_t upn_offset, upn_len;
4598 uint16_t samaccountname_offset = 0, samaccountname_len = 0;
4599 uint16_t objectsid_offset = 0, objectsid_len = 0;
4600 char *sid_str = NULL;
4601 uint32_t flags;
4603 item = proto_tree_add_item(parent_tree, hf_krb_pac_upn_dns_info, tvb, offset, -1, ENC_NA);
4604 tree = proto_item_add_subtree(item, ett_krb_pac_upn_dns_info);
4606 /* upn */
4607 upn_len = tvb_get_letohs(tvb, offset);
4608 proto_tree_add_item(tree, hf_krb_pac_upn_upn_len, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4609 offset+=2;
4610 upn_offset = tvb_get_letohs(tvb, offset);
4611 proto_tree_add_item(tree, hf_krb_pac_upn_upn_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4612 offset+=2;
4614 /* dns */
4615 dns_len = tvb_get_letohs(tvb, offset);
4616 proto_tree_add_item(tree, hf_krb_pac_upn_dns_len, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4617 offset+=2;
4618 dns_offset = tvb_get_letohs(tvb, offset);
4619 proto_tree_add_item(tree, hf_krb_pac_upn_dns_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4620 offset+=2;
4622 /* flags */
4623 flags = tvb_get_letohl(tvb, offset);
4624 proto_tree_add_bitmask(tree, tvb, offset,
4625 hf_krb_pac_upn_flags,
4626 ett_krb_pac_upn_dns_info_flags,
4627 hf_krb_pac_upn_flags_fields,
4628 ENC_LITTLE_ENDIAN);
4629 offset+=4;
4631 if (flags & PAC_UPN_DNS_FLAG_HAS_SAM_NAME_AND_SID) {
4632 samaccountname_len = tvb_get_letohs(tvb, offset);
4633 proto_tree_add_item(tree, hf_krb_pac_upn_samaccountname_len, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4634 offset+=2;
4635 samaccountname_offset = tvb_get_letohs(tvb, offset);
4636 proto_tree_add_item(tree, hf_krb_pac_upn_samaccountname_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4637 offset+=2;
4639 objectsid_len = tvb_get_letohs(tvb, offset);
4640 proto_tree_add_item(tree, hf_krb_pac_upn_objectsid_len, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4641 offset+=2;
4642 objectsid_offset = tvb_get_letohs(tvb, offset);
4643 proto_tree_add_item(tree, hf_krb_pac_upn_objectsid_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
4644 /* offset+=2; */
4647 /* upn */
4648 proto_tree_add_item(tree, hf_krb_pac_upn_upn_name, tvb, upn_offset, upn_len, ENC_UTF_16|ENC_LITTLE_ENDIAN);
4650 /* dns */
4651 proto_tree_add_item(tree, hf_krb_pac_upn_dns_name, tvb, dns_offset, dns_len, ENC_UTF_16|ENC_LITTLE_ENDIAN);
4653 /* samaccountname */
4654 if (samaccountname_offset != 0 && samaccountname_len != 0) {
4655 proto_tree_add_item(tree, hf_krb_pac_upn_samaccountname, tvb, samaccountname_offset, samaccountname_len, ENC_UTF_16|ENC_LITTLE_ENDIAN);
4657 /* objectsid */
4658 if (objectsid_offset != 0 && objectsid_len != 0) {
4659 tvbuff_t *sid_tvb;
4660 sid_tvb=tvb_new_subset_length(tvb, objectsid_offset, objectsid_len);
4661 dissect_nt_sid(sid_tvb, 0, tree, "objectSid", &sid_str, -1);
4664 #ifdef HAVE_KERBEROS
4665 if (private_data->current_ticket_key != NULL) {
4666 enc_key_t *ek = private_data->current_ticket_key;
4668 if (samaccountname_offset != 0 && samaccountname_len != 0) {
4669 ek->pac_names.account_name = tvb_get_string_enc(wmem_epan_scope(),
4670 tvb,
4671 samaccountname_offset,
4672 samaccountname_len,
4673 ENC_UTF_16|ENC_LITTLE_ENDIAN);
4674 } else {
4675 ek->pac_names.account_name = tvb_get_string_enc(wmem_epan_scope(),
4676 tvb,
4677 upn_offset,
4678 upn_len,
4679 ENC_UTF_16|ENC_LITTLE_ENDIAN);
4681 ek->pac_names.account_domain = tvb_get_string_enc(wmem_epan_scope(),
4682 tvb,
4683 dns_offset,
4684 dns_len,
4685 ENC_UTF_16|ENC_LITTLE_ENDIAN);
4686 if (sid_str != NULL) {
4687 ek->pac_names.account_sid = wmem_strdup(wmem_epan_scope(),
4688 sid_str);
4691 #endif /* HAVE_KERBEROS */
4693 return dns_offset;
4696 static int
4697 dissect_krb5_PAC_CLIENT_CLAIMS_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
4699 int length = tvb_captured_length_remaining(tvb, offset);
4701 if (length == 0) {
4702 return offset;
4705 proto_tree_add_item(parent_tree, hf_krb_pac_client_claims_info, tvb, offset, -1, ENC_NA);
4707 return offset;
4710 static int
4711 dissect_krb5_PAC_DEVICE_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
4713 #ifdef HAVE_KERBEROS
4714 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
4715 const char *device_sid = NULL;
4716 #endif /* HAVE_KERBEROS */
4717 proto_item *item;
4718 proto_tree *tree;
4719 uint8_t drep[4] = { 0x10, 0x00, 0x00, 0x00}; /* fake DREP struct */
4720 /* fake dcerpc_info struct */
4721 dcerpc_call_value call_data = { .flags = 0, };
4722 dcerpc_info di = { .ptype = UINT8_MAX, .call_data = &call_data, };
4724 #ifdef HAVE_KERBEROS
4725 if (private_data->current_ticket_key != NULL) {
4726 call_data.private_data = (void*)&device_sid;
4728 #endif /* HAVE_KERBEROS */
4730 item = proto_tree_add_item(parent_tree, hf_krb_pac_device_info, tvb, offset, -1, ENC_NA);
4731 tree = proto_item_add_subtree(item, ett_krb_pac_device_info);
4733 /* skip the first 16 bytes, they are some magic created by the idl
4734 * compiler the first 4 bytes might be flags?
4736 offset = dissect_krb5_PAC_NDRHEADERBLOB(tree, tvb, offset, &drep[0]);
4738 /* the PAC_DEVICE_INFO blob */
4739 init_ndr_pointer_list(&di);
4740 offset = dissect_ndr_pointer(tvb, offset, actx->pinfo, tree, &di, drep,
4741 netlogon_dissect_PAC_DEVICE_INFO, NDR_POINTER_UNIQUE,
4742 "PAC_DEVICE_INFO:", -1);
4743 free_ndr_pointer_list(&di);
4745 #ifdef HAVE_KERBEROS
4746 if (private_data->current_ticket_key != NULL) {
4747 enc_key_t *ek = private_data->current_ticket_key;
4750 * netlogon_dissect_PAC_DEVICE_INFO allocated on
4751 * wmem_epan_scope() for us
4753 ek->pac_names.device_sid = device_sid;
4755 #endif /* HAVE_KERBEROS */
4757 return offset;
4760 static int
4761 dissect_krb5_PAC_DEVICE_CLAIMS_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
4763 int length = tvb_captured_length_remaining(tvb, offset);
4765 if (length == 0) {
4766 return offset;
4769 proto_tree_add_item(parent_tree, hf_krb_pac_device_claims_info, tvb, offset, -1, ENC_NA);
4771 return offset;
4774 static int
4775 dissect_krb5_PAC_SERVER_CHECKSUM(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
4777 proto_item *item;
4778 proto_tree *tree;
4780 item = proto_tree_add_item(parent_tree, hf_krb_pac_server_checksum, tvb, offset, -1, ENC_NA);
4781 tree = proto_item_add_subtree(item, ett_krb_pac_server_checksum);
4783 /* signature type */
4784 proto_tree_add_item(tree, hf_krb_pac_signature_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
4785 offset+=4;
4787 /* signature data */
4788 proto_tree_add_item(tree, hf_krb_pac_signature_signature, tvb, offset, -1, ENC_NA);
4790 return offset;
4793 static int
4794 dissect_krb5_PAC_PRIVSVR_CHECKSUM(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
4796 proto_item *item;
4797 proto_tree *tree;
4799 item = proto_tree_add_item(parent_tree, hf_krb_pac_privsvr_checksum, tvb, offset, -1, ENC_NA);
4800 tree = proto_item_add_subtree(item, ett_krb_pac_privsvr_checksum);
4802 /* signature type */
4803 proto_tree_add_item(tree, hf_krb_pac_signature_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
4804 offset+=4;
4806 /* signature data */
4807 proto_tree_add_item(tree, hf_krb_pac_signature_signature, tvb, offset, -1, ENC_NA);
4809 return offset;
4812 static int
4813 dissect_krb5_PAC_CLIENT_INFO_TYPE(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
4815 proto_item *item;
4816 proto_tree *tree;
4817 uint16_t namelen;
4819 item = proto_tree_add_item(parent_tree, hf_krb_pac_client_info_type, tvb, offset, -1, ENC_NA);
4820 tree = proto_item_add_subtree(item, ett_krb_pac_client_info_type);
4822 /* clientid */
4823 dissect_nttime(tvb, tree, offset, hf_krb_pac_clientid, ENC_LITTLE_ENDIAN);
4824 offset+=8;
4826 /* name length */
4827 namelen=tvb_get_letohs(tvb, offset);
4828 proto_tree_add_uint(tree, hf_krb_pac_namelen, tvb, offset, 2, namelen);
4829 offset+=2;
4831 /* client name */
4832 proto_tree_add_item(tree, hf_krb_pac_clientname, tvb, offset, namelen, ENC_UTF_16|ENC_LITTLE_ENDIAN);
4833 offset+=namelen;
4835 return offset;
4838 static int
4839 dissect_krb5_PAC_TICKET_CHECKSUM(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
4841 proto_item *item;
4842 proto_tree *tree;
4844 item = proto_tree_add_item(parent_tree, hf_krb_pac_ticket_checksum, tvb, offset, -1, ENC_NA);
4845 tree = proto_item_add_subtree(item, ett_krb_pac_ticket_checksum);
4847 /* signature type */
4848 proto_tree_add_item(tree, hf_krb_pac_signature_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
4849 offset+=4;
4851 /* signature data */
4852 proto_tree_add_item(tree, hf_krb_pac_signature_signature, tvb, offset, -1, ENC_NA);
4854 return offset;
4857 #define PAC_ATTRIBUTE_FLAG_PAC_WAS_REQUESTED 0x00000001
4858 #define PAC_ATTRIBUTE_FLAG_PAC_WAS_GIVEN_IMPLICITLY 0x00000002
4859 static const true_false_string tfs_krb_pac_attributes_info_pac_was_requested = {
4860 "PAC was requested",
4861 "PAC was NOT requested",
4863 static const true_false_string tfs_krb_pac_attributes_info_pac_was_given_implicitly = {
4864 "PAC was given implicitly",
4865 "PAC was NOT given implicitly",
4867 static int * const hf_krb_pac_attributes_info_flags_fields[] = {
4868 &hf_krb_pac_attributes_info_flags_pac_was_requested,
4869 &hf_krb_pac_attributes_info_flags_pac_was_given_implicitly,
4870 NULL
4873 static int
4874 dissect_krb5_PAC_ATTRIBUTES_INFO(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
4876 proto_item *item;
4877 proto_tree *tree;
4879 item = proto_tree_add_item(parent_tree, hf_krb_pac_attributes_info, tvb, offset, -1, ENC_NA);
4880 tree = proto_item_add_subtree(item, ett_krb_pac_attributes_info);
4882 /* flags length*/
4883 proto_tree_add_item(tree, hf_krb_pac_attributes_info_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
4884 offset+=4;
4886 /* flags */
4887 proto_tree_add_bitmask(tree, tvb, offset,
4888 hf_krb_pac_attributes_info_flags,
4889 ett_krb_pac_attributes_info_flags,
4890 hf_krb_pac_attributes_info_flags_fields,
4891 ENC_LITTLE_ENDIAN);
4892 offset+=4;
4894 return offset;
4897 static int
4898 dissect_krb5_PAC_REQUESTER_SID(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
4900 proto_item *item;
4901 proto_tree *tree;
4903 item = proto_tree_add_item(parent_tree, hf_krb_pac_requester_sid, tvb, offset, -1, ENC_NA);
4904 tree = proto_item_add_subtree(item, ett_krb_pac_requester_sid);
4906 offset = dissect_nt_sid(tvb, offset, tree, "RequesterSid", NULL, -1);
4908 return offset;
4911 static int
4912 dissect_krb5_PAC_FULL_CHECKSUM(proto_tree *parent_tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
4914 proto_item *item;
4915 proto_tree *tree;
4917 item = proto_tree_add_item(parent_tree, hf_krb_pac_full_checksum, tvb, offset, -1, ENC_NA);
4918 tree = proto_item_add_subtree(item, ett_krb_pac_full_checksum);
4920 /* signature type */
4921 proto_tree_add_item(tree, hf_krb_pac_signature_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
4922 offset+=4;
4924 /* signature data */
4925 proto_tree_add_item(tree, hf_krb_pac_signature_signature, tvb, offset, -1, ENC_NA);
4927 return offset;
4930 static int
4931 dissect_krb5_AD_WIN2K_PAC_struct(proto_tree *tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx)
4933 uint32_t pac_type;
4934 uint32_t pac_size;
4935 uint32_t pac_offset;
4936 proto_item *it=NULL;
4937 proto_tree *tr=NULL;
4938 tvbuff_t *next_tvb;
4940 /* type of pac data */
4941 pac_type=tvb_get_letohl(tvb, offset);
4942 it=proto_tree_add_uint(tree, hf_krb_w2k_pac_type, tvb, offset, 4, pac_type);
4943 tr=proto_item_add_subtree(it, ett_krb_pac);
4945 offset += 4;
4947 /* size of pac data */
4948 pac_size=tvb_get_letohl(tvb, offset);
4949 proto_tree_add_uint(tr, hf_krb_w2k_pac_size, tvb, offset, 4, pac_size);
4950 offset += 4;
4952 /* offset to pac data */
4953 pac_offset=tvb_get_letohl(tvb, offset);
4954 proto_tree_add_uint(tr, hf_krb_w2k_pac_offset, tvb, offset, 4, pac_offset);
4955 offset += 8;
4957 next_tvb=tvb_new_subset_length_caplen(tvb, pac_offset, pac_size, pac_size);
4958 switch(pac_type){
4959 case PAC_LOGON_INFO:
4960 dissect_krb5_PAC_LOGON_INFO(tr, next_tvb, 0, actx);
4961 break;
4962 case PAC_CREDENTIAL_TYPE:
4963 dissect_krb5_PAC_CREDENTIAL_INFO(tr, next_tvb, 0, actx);
4964 break;
4965 case PAC_SERVER_CHECKSUM:
4966 dissect_krb5_PAC_SERVER_CHECKSUM(tr, next_tvb, 0, actx);
4967 break;
4968 case PAC_PRIVSVR_CHECKSUM:
4969 dissect_krb5_PAC_PRIVSVR_CHECKSUM(tr, next_tvb, 0, actx);
4970 break;
4971 case PAC_CLIENT_INFO_TYPE:
4972 dissect_krb5_PAC_CLIENT_INFO_TYPE(tr, next_tvb, 0, actx);
4973 break;
4974 case PAC_S4U_DELEGATION_INFO:
4975 dissect_krb5_PAC_S4U_DELEGATION_INFO(tr, next_tvb, 0, actx);
4976 break;
4977 case PAC_UPN_DNS_INFO:
4978 dissect_krb5_PAC_UPN_DNS_INFO(tr, next_tvb, 0, actx);
4979 break;
4980 case PAC_CLIENT_CLAIMS_INFO:
4981 dissect_krb5_PAC_CLIENT_CLAIMS_INFO(tr, next_tvb, 0, actx);
4982 break;
4983 case PAC_DEVICE_INFO:
4984 dissect_krb5_PAC_DEVICE_INFO(tr, next_tvb, 0, actx);
4985 break;
4986 case PAC_DEVICE_CLAIMS_INFO:
4987 dissect_krb5_PAC_DEVICE_CLAIMS_INFO(tr, next_tvb, 0, actx);
4988 break;
4989 case PAC_TICKET_CHECKSUM:
4990 dissect_krb5_PAC_TICKET_CHECKSUM(tr, next_tvb, 0, actx);
4991 break;
4992 case PAC_ATTRIBUTES_INFO:
4993 dissect_krb5_PAC_ATTRIBUTES_INFO(tr, next_tvb, 0, actx);
4994 break;
4995 case PAC_REQUESTER_SID:
4996 dissect_krb5_PAC_REQUESTER_SID(tr, next_tvb, 0, actx);
4997 break;
4998 case PAC_FULL_CHECKSUM:
4999 dissect_krb5_PAC_FULL_CHECKSUM(tr, next_tvb, 0, actx);
5000 break;
5002 default:
5003 break;
5005 return offset;
5008 static int
5009 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_)
5011 uint32_t entries;
5012 uint32_t version;
5013 uint32_t i;
5015 #if defined(HAVE_MIT_KERBEROS) && defined(HAVE_KRB5_PAC_VERIFY)
5016 verify_krb5_pac(tree, actx, tvb);
5017 #endif
5019 /* first in the PAC structure comes the number of entries */
5020 entries=tvb_get_letohl(tvb, offset);
5021 proto_tree_add_uint(tree, hf_krb_w2k_pac_entries, tvb, offset, 4, entries);
5022 offset += 4;
5024 /* second comes the version */
5025 version=tvb_get_letohl(tvb, offset);
5026 proto_tree_add_uint(tree, hf_krb_w2k_pac_version, tvb, offset, 4, version);
5027 offset += 4;
5029 for(i=0;i<entries;i++){
5030 offset=dissect_krb5_AD_WIN2K_PAC_struct(tree, tvb, offset, actx);
5033 return offset;
5036 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)
5038 int8_t ber_class;
5039 bool pc;
5040 int32_t tag;
5041 int len_offset;
5042 uint32_t len;
5043 bool ind;
5044 int next_offset;
5047 * dissect_ber_octet_string_wcb() always passes
5048 * implicit_tag=false, offset=0 and hf_index=-1
5050 ws_assert(implicit_tag == false);
5051 ws_assert(offset == 0);
5052 ws_assert(hf_index <= 0);
5054 len_offset = get_ber_identifier(tvb, offset, &ber_class, &pc, &tag);
5055 if (ber_class != BER_CLASS_UNI || !pc || tag != BER_UNI_TAG_SEQUENCE) {
5056 goto unknown;
5058 next_offset = get_ber_length(tvb, len_offset, &len, &ind);
5059 if (len < 1) {
5060 goto unknown;
5062 get_ber_identifier(tvb, next_offset, &ber_class, &pc, &tag);
5063 if (ber_class == BER_CLASS_CON && pc && tag == 1) {
5064 return dissect_kerberos_PA_DATA(implicit_tag, tvb, offset, actx, tree, hf_index);
5066 if (ber_class == BER_CLASS_UNI && pc && tag == BER_UNI_TAG_SEQUENCE) {
5067 return dissect_kerberos_T_rEP_SEQUENCE_OF_PA_DATA(implicit_tag, tvb, offset, actx, tree, hf_index);
5069 unknown:
5070 return tvb_reported_length_remaining(tvb, offset);
5073 #include "packet-kerberos-fn.c"
5075 #ifdef HAVE_KERBEROS
5076 static const ber_sequence_t PA_ENC_TS_ENC_sequence[] = {
5077 { &hf_krb_patimestamp, BER_CLASS_CON, 0, 0, dissect_kerberos_KerberosTime },
5078 { &hf_krb_pausec , BER_CLASS_CON, 1, BER_FLAGS_OPTIONAL, dissect_kerberos_Microseconds },
5079 { NULL, 0, 0, 0, NULL }
5082 static int
5083 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_) {
5084 offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
5085 PA_ENC_TS_ENC_sequence, hf_index, ett_krb_pa_enc_ts_enc);
5086 return offset;
5089 static int
5090 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_) {
5091 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
5092 int save_encryption_key_parent_hf_index = private_data->save_encryption_key_parent_hf_index;
5093 kerberos_key_save_fn saved_encryption_key_fn = private_data->save_encryption_key_fn;
5094 private_data->save_encryption_key_parent_hf_index = hf_kerberos_KrbFastResponse;
5095 #ifdef HAVE_KERBEROS
5096 private_data->save_encryption_key_fn = save_KrbFastResponse_strengthen_key;
5097 #endif
5098 offset = dissect_kerberos_EncryptionKey(implicit_tag, tvb, offset, actx, tree, hf_index);
5100 private_data->save_encryption_key_parent_hf_index = save_encryption_key_parent_hf_index;
5101 private_data->save_encryption_key_fn = saved_encryption_key_fn;
5102 return offset;
5105 static const ber_sequence_t KrbFastFinished_sequence[] = {
5106 { &hf_kerberos_timestamp , BER_CLASS_CON, 0, 0, dissect_kerberos_KerberosTime },
5107 { &hf_kerberos_usec , BER_CLASS_CON, 1, 0, dissect_kerberos_Microseconds },
5108 { &hf_kerberos_crealm , BER_CLASS_CON, 2, 0, dissect_kerberos_Realm },
5109 { &hf_kerberos_cname_01 , BER_CLASS_CON, 3, 0, dissect_kerberos_PrincipalName },
5110 { &hf_kerberos_ticket_checksum, BER_CLASS_CON, 4, 0, dissect_kerberos_Checksum },
5111 { NULL, 0, 0, 0, NULL }
5114 static int
5115 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_) {
5116 offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
5117 KrbFastFinished_sequence, hf_index, ett_kerberos_KrbFastFinished);
5119 return offset;
5122 static const ber_sequence_t KrbFastResponse_sequence[] = {
5123 { &hf_kerberos_rEP_SEQUENCE_OF_PA_DATA, BER_CLASS_CON, 0, 0, dissect_kerberos_T_rEP_SEQUENCE_OF_PA_DATA },
5124 { &hf_kerberos_strengthen_key, BER_CLASS_CON, 1, BER_FLAGS_OPTIONAL, dissect_kerberos_T_strengthen_key },
5125 { &hf_kerberos_finished , BER_CLASS_CON, 2, BER_FLAGS_OPTIONAL, dissect_kerberos_KrbFastFinished },
5126 { &hf_kerberos_nonce , BER_CLASS_CON, 3, 0, dissect_kerberos_UInt32 },
5127 { NULL, 0, 0, 0, NULL }
5130 static int
5131 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_) {
5132 offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
5133 KrbFastResponse_sequence, hf_index, ett_kerberos_KrbFastResponse);
5135 return offset;
5138 static const ber_sequence_t KrbFastReq_sequence[] = {
5139 { &hf_kerberos_fast_options, BER_CLASS_CON, 0, 0, dissect_kerberos_FastOptions },
5140 { &hf_kerberos_rEQ_SEQUENCE_OF_PA_DATA, BER_CLASS_CON, 1, 0, dissect_kerberos_T_rEQ_SEQUENCE_OF_PA_DATA },
5141 { &hf_kerberos_req_body , BER_CLASS_CON, 2, 0, dissect_kerberos_KDC_REQ_BODY },
5142 { NULL, 0, 0, 0, NULL }
5145 static int
5146 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_) {
5147 kerberos_private_data_t *private_data = kerberos_get_private_data(actx);
5148 struct _kerberos_PA_FX_FAST_REQUEST saved_stack = private_data->PA_FX_FAST_REQUEST;
5149 private_data->PA_FX_FAST_REQUEST = (struct _kerberos_PA_FX_FAST_REQUEST) { .defer = false, };
5150 offset = dissect_ber_sequence(implicit_tag, actx, tree, tvb, offset,
5151 KrbFastReq_sequence, hf_index, ett_kerberos_KrbFastReq);
5152 private_data->PA_FX_FAST_REQUEST = saved_stack;
5154 return offset;
5157 static int * const FastOptions_bits[] = {
5158 &hf_kerberos_FastOptions_reserved,
5159 &hf_kerberos_FastOptions_hide_client_names,
5160 &hf_kerberos_FastOptions_spare_bit2,
5161 &hf_kerberos_FastOptions_spare_bit3,
5162 &hf_kerberos_FastOptions_spare_bit4,
5163 &hf_kerberos_FastOptions_spare_bit5,
5164 &hf_kerberos_FastOptions_spare_bit6,
5165 &hf_kerberos_FastOptions_spare_bit7,
5166 &hf_kerberos_FastOptions_spare_bit8,
5167 &hf_kerberos_FastOptions_spare_bit9,
5168 &hf_kerberos_FastOptions_spare_bit10,
5169 &hf_kerberos_FastOptions_spare_bit11,
5170 &hf_kerberos_FastOptions_spare_bit12,
5171 &hf_kerberos_FastOptions_spare_bit13,
5172 &hf_kerberos_FastOptions_spare_bit14,
5173 &hf_kerberos_FastOptions_spare_bit15,
5174 &hf_kerberos_FastOptions_kdc_follow_referrals,
5175 NULL
5178 static int
5179 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_) {
5180 offset = dissect_ber_bitstring(implicit_tag, actx, tree, tvb, offset,
5181 FastOptions_bits, 17, hf_index, ett_kerberos_FastOptions,
5182 NULL);
5184 return offset;
5187 #endif /* HAVE_KERBEROS */
5189 /* Make wrappers around exported functions for now */
5191 dissect_krb5_Checksum(proto_tree *tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
5193 return dissect_kerberos_Checksum(false, tvb, offset, actx, tree, hf_kerberos_cksum);
5198 dissect_krb5_ctime(proto_tree *tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
5200 return dissect_kerberos_KerberosTime(false, tvb, offset, actx, tree, hf_kerberos_ctime);
5205 dissect_krb5_cname(proto_tree *tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
5207 return dissect_kerberos_PrincipalName(false, tvb, offset, actx, tree, hf_kerberos_cname);
5210 dissect_krb5_realm(proto_tree *tree, tvbuff_t *tvb, int offset, asn1_ctx_t *actx _U_)
5212 return dissect_kerberos_Realm(false, tvb, offset, actx, tree, hf_kerberos_realm);
5215 struct kerberos_display_key_state {
5216 proto_tree *tree;
5217 packet_info *pinfo;
5218 expert_field *expindex;
5219 const char *name;
5220 tvbuff_t *tvb;
5221 int start;
5222 int length;
5225 static void
5226 #ifdef HAVE_KERBEROS
5227 kerberos_display_key(void *data, void *userdata)
5228 #else
5229 kerberos_display_key(void *data _U_, void *userdata _U_)
5230 #endif
5232 #ifdef HAVE_KERBEROS
5233 struct kerberos_display_key_state *state =
5234 (struct kerberos_display_key_state *)userdata;
5235 const enc_key_t *ek = (const enc_key_t *)data;
5236 proto_item *item = NULL;
5237 enc_key_t *sek = NULL;
5239 item = proto_tree_add_expert_format(state->tree,
5240 state->pinfo,
5241 state->expindex,
5242 state->tvb,
5243 state->start,
5244 state->length,
5245 "%s %s keytype %d (id=%s same=%u) (%02x%02x%02x%02x...)",
5246 state->name,
5247 ek->key_origin, ek->keytype,
5248 ek->id_str, ek->num_same,
5249 ek->keyvalue[0] & 0xFF, ek->keyvalue[1] & 0xFF,
5250 ek->keyvalue[2] & 0xFF, ek->keyvalue[3] & 0xFF);
5251 if (ek->src1 != NULL) {
5252 sek = ek->src1;
5253 expert_add_info_format(state->pinfo,
5254 item,
5255 state->expindex,
5256 "SRC1 %s keytype %d (id=%s same=%u) (%02x%02x%02x%02x...)",
5257 sek->key_origin, sek->keytype,
5258 sek->id_str, sek->num_same,
5259 sek->keyvalue[0] & 0xFF, sek->keyvalue[1] & 0xFF,
5260 sek->keyvalue[2] & 0xFF, sek->keyvalue[3] & 0xFF);
5262 if (ek->src2 != NULL) {
5263 sek = ek->src2;
5264 expert_add_info_format(state->pinfo,
5265 item,
5266 state->expindex,
5267 "SRC2 %s keytype %d (id=%s same=%u) (%02x%02x%02x%02x...)",
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);
5273 sek = ek->same_list;
5274 while (sek != NULL) {
5275 expert_add_info_format(state->pinfo,
5276 item,
5277 state->expindex,
5278 "%s %s keytype %d (id=%s same=%u) (%02x%02x%02x%02x...)",
5279 state->name,
5280 sek->key_origin, sek->keytype,
5281 sek->id_str, sek->num_same,
5282 sek->keyvalue[0] & 0xFF, sek->keyvalue[1] & 0xFF,
5283 sek->keyvalue[2] & 0xFF, sek->keyvalue[3] & 0xFF);
5284 sek = sek->same_list;
5286 #endif /* HAVE_KERBEROS */
5289 static const value_string KERB_LOGON_SUBMIT_TYPE[] = {
5290 { 2, "KerbInteractiveLogon" },
5291 { 6, "KerbSmartCardLogon" },
5292 { 7, "KerbWorkstationUnlockLogon" },
5293 { 8, "KerbSmartCardUnlockLogon" },
5294 { 9, "KerbProxyLogon" },
5295 { 10, "KerbTicketLogon" },
5296 { 11, "KerbTicketUnlockLogon" },
5297 { 12, "KerbS4ULogon" },
5298 { 13, "KerbCertificateLogon" },
5299 { 14, "KerbCertificateS4ULogon" },
5300 { 15, "KerbCertificateUnlockLogon" },
5301 { 0, NULL }
5305 #define KERB_LOGON_FLAG_ALLOW_EXPIRED_TICKET 0x1
5306 #define KERB_LOGON_FLAG_REDIRECTED 0x2
5308 static int* const ktl_flags_bits[] = {
5309 &hf_kerberos_KERB_TICKET_LOGON_FLAG_ALLOW_EXPIRED_TICKET,
5310 &hf_kerberos_KERB_TICKET_LOGON_FLAG_REDIRECTED,
5311 NULL
5315 dissect_kerberos_KERB_TICKET_LOGON(tvbuff_t *tvb, int offset, asn1_ctx_t *actx, proto_tree *tree)
5317 proto_item *item;
5318 proto_tree *subtree;
5319 uint32_t ServiceTicketLength;
5320 uint32_t TicketGrantingTicketLength;
5321 int orig_offset;
5323 if (tvb_captured_length(tvb) < 32)
5324 return offset;
5326 item = proto_tree_add_item(tree, hf_kerberos_KERB_TICKET_LOGON, tvb, offset, -1, ENC_NA);
5327 subtree = proto_item_add_subtree(item, ett_kerberos_KERB_TICKET_LOGON);
5329 proto_tree_add_item(subtree, hf_kerberos_KERB_TICKET_LOGON_MessageType, tvb, offset, 4,
5330 ENC_LITTLE_ENDIAN);
5331 offset+=4;
5333 proto_tree_add_bitmask(subtree, tvb, offset, hf_kerberos_KERB_TICKET_LOGON_Flags,
5334 ett_kerberos, ktl_flags_bits, ENC_LITTLE_ENDIAN);
5335 offset+=4;
5337 ServiceTicketLength = tvb_get_letohl(tvb, offset);
5338 proto_tree_add_item(subtree, hf_kerberos_KERB_TICKET_LOGON_ServiceTicketLength, tvb,
5339 offset, 4, ENC_LITTLE_ENDIAN);
5340 offset+=4;
5342 TicketGrantingTicketLength = tvb_get_letohl(tvb, offset);
5343 proto_tree_add_item(subtree, hf_kerberos_KERB_TICKET_LOGON_TicketGrantingTicketLength,
5344 tvb, offset, 4, ENC_LITTLE_ENDIAN);
5345 offset+=4;
5347 /* Skip two PUCHAR of ServiceTicket and TicketGrantingTicket */
5348 offset+=16;
5350 if (ServiceTicketLength == 0)
5351 return offset;
5353 orig_offset = offset;
5354 offset = dissect_kerberos_Ticket(false, tvb, offset, actx, subtree,
5355 hf_kerberos_KERB_TICKET_LOGON_ServiceTicket);
5357 if ((unsigned)(offset-orig_offset) != ServiceTicketLength)
5358 return offset;
5360 if (TicketGrantingTicketLength == 0)
5361 return offset;
5363 offset = dissect_kerberos_KRB_CRED(false, tvb, offset, actx, subtree,
5364 hf_kerberos_KERB_TICKET_LOGON_TicketGrantingTicket);
5366 if ((unsigned)(offset-orig_offset) != ServiceTicketLength + TicketGrantingTicketLength)
5367 return offset;
5369 return offset;
5372 static int
5373 dissect_kerberos_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5374 bool dci, bool do_col_protocol, bool have_rm,
5375 kerberos_callbacks *cb)
5377 volatile int offset = 0;
5378 proto_tree *volatile kerberos_tree = NULL;
5379 proto_item *volatile item = NULL;
5380 kerberos_private_data_t *private_data = NULL;
5381 asn1_ctx_t asn1_ctx;
5383 /* TCP record mark and length */
5384 uint32_t krb_rm = 0;
5385 int krb_reclen = 0;
5387 gbl_do_col_info=dci;
5389 if (have_rm) {
5390 krb_rm = tvb_get_ntohl(tvb, offset);
5391 krb_reclen = kerberos_rm_to_reclen(krb_rm);
5393 * What is a reasonable size limit?
5395 if (krb_reclen > 10 * 1024 * 1024) {
5396 return (-1);
5399 if (do_col_protocol) {
5400 col_set_str(pinfo->cinfo, COL_PROTOCOL, "KRB5");
5403 if (tree) {
5404 item = proto_tree_add_item(tree, proto_kerberos, tvb, 0, -1, ENC_NA);
5405 kerberos_tree = proto_item_add_subtree(item, ett_kerberos);
5408 show_krb_recordmark(kerberos_tree, tvb, offset, krb_rm);
5409 offset += 4;
5410 } else {
5411 /* Do some sanity checking here,
5412 * All krb5 packets start with a TAG class that is BER_CLASS_APP
5413 * and a tag value that is either of the values below:
5414 * If it doesn't look like kerberos, return 0 and let someone else have
5415 * a go at it.
5417 int8_t tmp_class;
5418 bool tmp_pc;
5419 int32_t tmp_tag;
5421 get_ber_identifier(tvb, offset, &tmp_class, &tmp_pc, &tmp_tag);
5422 if(tmp_class!=BER_CLASS_APP){
5423 return 0;
5425 switch(tmp_tag){
5426 case KRB5_MSG_TICKET:
5427 case KRB5_MSG_AUTHENTICATOR:
5428 case KRB5_MSG_ENC_TICKET_PART:
5429 case KRB5_MSG_AS_REQ:
5430 case KRB5_MSG_AS_REP:
5431 case KRB5_MSG_TGS_REQ:
5432 case KRB5_MSG_TGS_REP:
5433 case KRB5_MSG_AP_REQ:
5434 case KRB5_MSG_AP_REP:
5435 case KRB5_MSG_ENC_AS_REP_PART:
5436 case KRB5_MSG_ENC_TGS_REP_PART:
5437 case KRB5_MSG_ENC_AP_REP_PART:
5438 case KRB5_MSG_ENC_KRB_PRIV_PART:
5439 case KRB5_MSG_ENC_KRB_CRED_PART:
5440 case KRB5_MSG_SAFE:
5441 case KRB5_MSG_PRIV:
5442 case KRB5_MSG_ERROR:
5443 break;
5444 default:
5445 return 0;
5447 if (do_col_protocol) {
5448 col_set_str(pinfo->cinfo, COL_PROTOCOL, "KRB5");
5450 if (gbl_do_col_info) {
5451 col_clear(pinfo->cinfo, COL_INFO);
5453 if (tree) {
5454 item = proto_tree_add_item(tree, proto_kerberos, tvb, 0, -1, ENC_NA);
5455 kerberos_tree = proto_item_add_subtree(item, ett_kerberos);
5458 asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, true, pinfo);
5459 asn1_ctx.private_data = NULL;
5460 private_data = kerberos_get_private_data(&asn1_ctx);
5461 private_data->callbacks = cb;
5463 TRY {
5464 offset=dissect_kerberos_Applications(false, tvb, offset, &asn1_ctx , kerberos_tree, /* hf_index */ -1);
5465 } CATCH_BOUNDS_ERRORS {
5466 RETHROW;
5467 } ENDTRY;
5469 if (private_data->frame_rep != UINT32_MAX) {
5470 proto_item *tmp_item;
5472 tmp_item = proto_tree_add_uint(kerberos_tree, hf_krb_response_in, tvb, 0, 0, private_data->frame_rep);
5473 proto_item_set_generated(tmp_item);
5476 if (private_data->frame_req != UINT32_MAX) {
5477 proto_item *tmp_item;
5478 nstime_t t, deltat;
5480 tmp_item = proto_tree_add_uint(kerberos_tree, hf_krb_response_to, tvb, 0, 0, private_data->frame_req);
5481 proto_item_set_generated(tmp_item);
5483 t = pinfo->abs_ts;
5484 nstime_delta(&deltat, &t, &private_data->req_time);
5485 tmp_item = proto_tree_add_time(kerberos_tree, hf_krb_time, tvb, 0, 0, &deltat);
5486 proto_item_set_generated(tmp_item);
5489 if (kerberos_tree != NULL) {
5490 struct kerberos_display_key_state display_state = {
5491 .tree = kerberos_tree,
5492 .pinfo = pinfo,
5493 .expindex = &ei_kerberos_learnt_keytype,
5494 .name = "Provides",
5495 .tvb = tvb,
5498 wmem_list_foreach(private_data->learnt_keys,
5499 kerberos_display_key,
5500 &display_state);
5503 if (kerberos_tree != NULL) {
5504 struct kerberos_display_key_state display_state = {
5505 .tree = kerberos_tree,
5506 .pinfo = pinfo,
5507 .expindex = &ei_kerberos_missing_keytype,
5508 .name = "Missing",
5509 .tvb = tvb,
5512 wmem_list_foreach(private_data->missing_keys,
5513 kerberos_display_key,
5514 &display_state);
5517 if (kerberos_tree != NULL) {
5518 struct kerberos_display_key_state display_state = {
5519 .tree = kerberos_tree,
5520 .pinfo = pinfo,
5521 .expindex = &ei_kerberos_decrypted_keytype,
5522 .name = "Used",
5523 .tvb = tvb,
5526 wmem_list_foreach(private_data->decryption_keys,
5527 kerberos_display_key,
5528 &display_state);
5531 proto_item_set_len(item, offset);
5532 return offset;
5536 * Display the TCP record mark.
5538 void
5539 show_krb_recordmark(proto_tree *tree, tvbuff_t *tvb, int start, uint32_t krb_rm)
5541 int rec_len;
5542 proto_tree *rm_tree;
5544 if (tree == NULL)
5545 return;
5547 rec_len = kerberos_rm_to_reclen(krb_rm);
5548 rm_tree = proto_tree_add_subtree_format(tree, tvb, start, 4, ett_krb_recordmark, NULL,
5549 "Record Mark: %u %s", rec_len, plurality(rec_len, "byte", "bytes"));
5550 proto_tree_add_boolean(rm_tree, hf_krb_rm_reserved, tvb, start, 4, krb_rm);
5551 proto_tree_add_uint(rm_tree, hf_krb_rm_reclen, tvb, start, 4, krb_rm);
5555 dissect_kerberos_main(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, bool do_col_info, kerberos_callbacks *cb)
5557 return (dissect_kerberos_common(tvb, pinfo, tree, do_col_info, false, false, cb));
5560 uint32_t
5561 kerberos_output_keytype(void)
5563 return gbl_keytype;
5566 static int
5567 dissect_kerberos_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
5569 /* Some weird kerberos implementation apparently do krb4 on the krb5 port.
5570 Since all (except weirdo transarc krb4 stuff) use
5571 an opcode <=16 in the first byte, use this to see if it might
5572 be krb4.
5573 All krb5 commands start with an APPL tag and thus is >=0x60
5574 so if first byte is <=16 just blindly assume it is krb4 then
5576 if(tvb_captured_length(tvb) >= 1 && tvb_get_uint8(tvb, 0)<=0x10){
5577 if(krb4_handle){
5578 bool res;
5580 res=call_dissector_only(krb4_handle, tvb, pinfo, tree, NULL);
5581 return res;
5582 }else{
5583 return 0;
5588 return dissect_kerberos_common(tvb, pinfo, tree, true, true, false, NULL);
5592 kerberos_rm_to_reclen(unsigned krb_rm)
5594 return (krb_rm & KRB_RM_RECLEN);
5597 unsigned
5598 get_krb_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
5600 unsigned krb_rm;
5601 int pdulen;
5603 krb_rm = tvb_get_ntohl(tvb, offset);
5604 pdulen = kerberos_rm_to_reclen(krb_rm);
5605 return (pdulen + 4);
5607 static void
5608 kerberos_prefs_apply_cb(void) {
5609 #ifdef HAVE_LIBNETTLE
5610 clear_keytab();
5611 read_keytab_file(keytab_filename);
5612 #endif
5615 static int
5616 dissect_kerberos_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
5618 pinfo->fragmented = true;
5619 if (dissect_kerberos_common(tvb, pinfo, tree, true, true, true, NULL) < 0) {
5621 * The dissector failed to recognize this as a valid
5622 * Kerberos message. Mark it as a continuation packet.
5624 col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
5627 return tvb_captured_length(tvb);
5630 static int
5631 dissect_kerberos_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
5633 col_set_str(pinfo->cinfo, COL_PROTOCOL, "KRB5");
5634 col_clear(pinfo->cinfo, COL_INFO);
5636 tcp_dissect_pdus(tvb, pinfo, tree, krb_desegment, 4, get_krb_pdu_len,
5637 dissect_kerberos_tcp_pdu, data);
5638 return tvb_captured_length(tvb);
5641 /*--- proto_register_kerberos -------------------------------------------*/
5642 void proto_register_kerberos(void) {
5644 /* List of fields */
5646 static hf_register_info hf[] = {
5647 { &hf_krb_response_to,
5648 { "Response to", "kerberos.response_to", FT_FRAMENUM, BASE_NONE,
5649 FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0, "This packet is a response to the packet in this frame", HFILL }},
5650 { &hf_krb_response_in,
5651 { "Response in", "kerberos.response_in", FT_FRAMENUM, BASE_NONE,
5652 FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE), 0, "The response to this packet is in this packet", HFILL }},
5653 { &hf_krb_time,
5654 { "Time from request", "kerberos.time", FT_RELATIVE_TIME, BASE_NONE,
5655 NULL, 0, "Time between Request and Response for Kerberos KDC requests", HFILL }},
5656 { &hf_krb_rm_reserved, {
5657 "Reserved", "kerberos.rm.reserved", FT_BOOLEAN, 32,
5658 TFS(&tfs_set_notset), KRB_RM_RESERVED, "Record mark reserved bit", HFILL }},
5659 { &hf_krb_rm_reclen, {
5660 "Record Length", "kerberos.rm.length", FT_UINT32, BASE_DEC,
5661 NULL, KRB_RM_RECLEN, NULL, HFILL }},
5662 { &hf_krb_provsrv_location, {
5663 "PROVSRV Location", "kerberos.provsrv_location", FT_STRING, BASE_NONE,
5664 NULL, 0, "PacketCable PROV SRV Location", HFILL }},
5665 { &hf_krb_pw_salt,
5666 { "pw-salt", "kerberos.pw_salt", FT_BYTES, BASE_NONE,
5667 NULL, 0, NULL, HFILL }},
5668 { &hf_krb_ext_error_nt_status, /* we keep kerberos.smb.nt_status for compat reasons */
5669 { "NT Status", "kerberos.smb.nt_status", FT_UINT32, BASE_HEX|BASE_EXT_STRING,
5670 &NT_errors_ext, 0, "NT Status code", HFILL }},
5671 { &hf_krb_ext_error_reserved,
5672 { "Reserved", "kerberos.ext_error.reserved", FT_UINT32, BASE_HEX,
5673 NULL, 0, NULL, HFILL }},
5674 { &hf_krb_ext_error_flags,
5675 { "Flags", "kerberos.ext_error.flags", FT_UINT32, BASE_HEX,
5676 NULL, 0, NULL, HFILL }},
5677 { &hf_krb_address_ip, {
5678 "IP Address", "kerberos.addr_ip", FT_IPv4, BASE_NONE,
5679 NULL, 0, NULL, HFILL }},
5680 { &hf_krb_address_ipv6, {
5681 "IPv6 Address", "kerberos.addr_ipv6", FT_IPv6, BASE_NONE,
5682 NULL, 0, NULL, HFILL }},
5683 { &hf_krb_address_netbios, {
5684 "NetBIOS Address", "kerberos.addr_nb", FT_STRING, BASE_NONE,
5685 NULL, 0, "NetBIOS Address and type", HFILL }},
5686 { &hf_krb_gssapi_len, {
5687 "Length", "kerberos.gssapi.len", FT_UINT32, BASE_DEC,
5688 NULL, 0, "Length of GSSAPI Bnd field", HFILL }},
5689 { &hf_krb_gssapi_bnd, {
5690 "Bnd", "kerberos.gssapi.bdn", FT_BYTES, BASE_NONE,
5691 NULL, 0, "GSSAPI Bnd field", HFILL }},
5692 { &hf_krb_gssapi_c_flag_deleg, {
5693 "Deleg", "kerberos.gssapi.checksum.flags.deleg", FT_BOOLEAN, 32,
5694 TFS(&tfs_gss_flags_deleg), KRB5_GSS_C_DELEG_FLAG, NULL, HFILL }},
5695 { &hf_krb_gssapi_c_flag_mutual, {
5696 "Mutual", "kerberos.gssapi.checksum.flags.mutual", FT_BOOLEAN, 32,
5697 TFS(&tfs_gss_flags_mutual), KRB5_GSS_C_MUTUAL_FLAG, NULL, HFILL }},
5698 { &hf_krb_gssapi_c_flag_replay, {
5699 "Replay", "kerberos.gssapi.checksum.flags.replay", FT_BOOLEAN, 32,
5700 TFS(&tfs_gss_flags_replay), KRB5_GSS_C_REPLAY_FLAG, NULL, HFILL }},
5701 { &hf_krb_gssapi_c_flag_sequence, {
5702 "Sequence", "kerberos.gssapi.checksum.flags.sequence", FT_BOOLEAN, 32,
5703 TFS(&tfs_gss_flags_sequence), KRB5_GSS_C_SEQUENCE_FLAG, NULL, HFILL }},
5704 { &hf_krb_gssapi_c_flag_conf, {
5705 "Conf", "kerberos.gssapi.checksum.flags.conf", FT_BOOLEAN, 32,
5706 TFS(&tfs_gss_flags_conf), KRB5_GSS_C_CONF_FLAG, NULL, HFILL }},
5707 { &hf_krb_gssapi_c_flag_integ, {
5708 "Integ", "kerberos.gssapi.checksum.flags.integ", FT_BOOLEAN, 32,
5709 TFS(&tfs_gss_flags_integ), KRB5_GSS_C_INTEG_FLAG, NULL, HFILL }},
5710 { &hf_krb_gssapi_c_flag_dce_style, {
5711 "DCE-style", "kerberos.gssapi.checksum.flags.dce-style", FT_BOOLEAN, 32,
5712 TFS(&tfs_gss_flags_dce_style), KRB5_GSS_C_DCE_STYLE, NULL, HFILL }},
5713 { &hf_krb_gssapi_dlgopt, {
5714 "DlgOpt", "kerberos.gssapi.dlgopt", FT_UINT16, BASE_DEC,
5715 NULL, 0, "GSSAPI DlgOpt", HFILL }},
5716 { &hf_krb_gssapi_dlglen, {
5717 "DlgLen", "kerberos.gssapi.dlglen", FT_UINT16, BASE_DEC,
5718 NULL, 0, "GSSAPI DlgLen", HFILL }},
5719 { &hf_krb_midl_blob_len, {
5720 "Blob Length", "kerberos.midl_blob_len", FT_UINT64, BASE_DEC,
5721 NULL, 0, "Length of NDR encoded data that follows", HFILL }},
5722 { &hf_krb_midl_fill_bytes, {
5723 "Fill bytes", "kerberos.midl.fill_bytes", FT_UINT32, BASE_HEX,
5724 NULL, 0, "Just some fill bytes", HFILL }},
5725 { &hf_krb_midl_version, {
5726 "Version", "kerberos.midl.version", FT_UINT8, BASE_DEC,
5727 NULL, 0, "Version of pickling", HFILL }},
5728 { &hf_krb_midl_hdr_len, {
5729 "HDR Length", "kerberos.midl.hdr_len", FT_UINT16, BASE_DEC,
5730 NULL, 0, "Length of header", HFILL }},
5731 { &hf_krb_pac_signature_type, {
5732 "Type", "kerberos.pac.signature.type", FT_INT32, BASE_DEC,
5733 NULL, 0, "PAC Signature Type", HFILL }},
5734 { &hf_krb_pac_signature_signature, {
5735 "Signature", "kerberos.pac.signature.signature", FT_BYTES, BASE_NONE,
5736 NULL, 0, "A PAC signature blob", HFILL }},
5737 { &hf_krb_w2k_pac_entries, {
5738 "Num Entries", "kerberos.pac.entries", FT_UINT32, BASE_DEC,
5739 NULL, 0, "Number of W2k PAC entries", HFILL }},
5740 { &hf_krb_w2k_pac_version, {
5741 "Version", "kerberos.pac.version", FT_UINT32, BASE_DEC,
5742 NULL, 0, "Version of PAC structures", HFILL }},
5743 { &hf_krb_w2k_pac_type, {
5744 "Type", "kerberos.pac.type", FT_UINT32, BASE_DEC,
5745 VALS(w2k_pac_types), 0, "Type of W2k PAC entry", HFILL }},
5746 { &hf_krb_w2k_pac_size, {
5747 "Size", "kerberos.pac.size", FT_UINT32, BASE_DEC,
5748 NULL, 0, "Size of W2k PAC entry", HFILL }},
5749 { &hf_krb_w2k_pac_offset, {
5750 "Offset", "kerberos.pac.offset", FT_UINT32, BASE_DEC,
5751 NULL, 0, "Offset to W2k PAC entry", HFILL }},
5752 { &hf_krb_pac_clientid, {
5753 "ClientID", "kerberos.pac.clientid", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL,
5754 NULL, 0, "ClientID Timestamp", HFILL }},
5755 { &hf_krb_pac_namelen, {
5756 "Name Length", "kerberos.pac.namelen", FT_UINT16, BASE_DEC,
5757 NULL, 0, "Length of client name", HFILL }},
5758 { &hf_krb_pac_clientname, {
5759 "Name", "kerberos.pac.name", FT_STRING, BASE_NONE,
5760 NULL, 0, "Name of the Client in the PAC structure", HFILL }},
5761 { &hf_krb_pac_logon_info, {
5762 "PAC_LOGON_INFO", "kerberos.pac_logon_info", FT_BYTES, BASE_NONE,
5763 NULL, 0, "PAC_LOGON_INFO structure", HFILL }},
5764 { &hf_krb_pac_credential_data, {
5765 "PAC_CREDENTIAL_DATA", "kerberos.pac_credential_data", FT_BYTES, BASE_NONE,
5766 NULL, 0, "PAC_CREDENTIAL_DATA structure", HFILL }},
5767 { &hf_krb_pac_credential_info, {
5768 "PAC_CREDENTIAL_INFO", "kerberos.pac_credential_info", FT_BYTES, BASE_NONE,
5769 NULL, 0, "PAC_CREDENTIAL_INFO structure", HFILL }},
5770 { &hf_krb_pac_credential_info_version, {
5771 "Version", "kerberos.pac_credential_info.version", FT_UINT32, BASE_DEC,
5772 NULL, 0, NULL, HFILL }},
5773 { &hf_krb_pac_credential_info_etype, {
5774 "Etype", "kerberos.pac_credential_info.etype", FT_UINT32, BASE_DEC,
5775 NULL, 0, NULL, HFILL }},
5776 { &hf_krb_pac_server_checksum, {
5777 "PAC_SERVER_CHECKSUM", "kerberos.pac_server_checksum", FT_BYTES, BASE_NONE,
5778 NULL, 0, "PAC_SERVER_CHECKSUM structure", HFILL }},
5779 { &hf_krb_pac_privsvr_checksum, {
5780 "PAC_PRIVSVR_CHECKSUM", "kerberos.pac_privsvr_checksum", FT_BYTES, BASE_NONE,
5781 NULL, 0, "PAC_PRIVSVR_CHECKSUM structure", HFILL }},
5782 { &hf_krb_pac_client_info_type, {
5783 "PAC_CLIENT_INFO_TYPE", "kerberos.pac_client_info_type", FT_BYTES, BASE_NONE,
5784 NULL, 0, "PAC_CLIENT_INFO_TYPE structure", HFILL }},
5785 { &hf_krb_pac_s4u_delegation_info, {
5786 "PAC_S4U_DELEGATION_INFO", "kerberos.pac_s4u_delegation_info", FT_BYTES, BASE_NONE,
5787 NULL, 0, "PAC_S4U_DELEGATION_INFO structure", HFILL }},
5788 { &hf_krb_pac_upn_dns_info, {
5789 "UPN_DNS_INFO", "kerberos.pac_upn_dns_info", FT_BYTES, BASE_NONE,
5790 NULL, 0, "UPN_DNS_INFO structure", HFILL }},
5791 { &hf_krb_pac_upn_flags, {
5792 "Flags", "kerberos.pac.upn.flags", FT_UINT32, BASE_HEX,
5793 NULL, 0, "UPN flags", HFILL }},
5794 { &hf_krb_pac_upn_flag_upn_constructed, {
5795 "UPN Name Constructed",
5796 "kerberos.pac.upn.flags.upn_constructed",
5797 FT_BOOLEAN, 32,
5798 TFS(&tfs_krb_pac_upn_flag_upn_constructed),
5799 PAC_UPN_DNS_FLAG_CONSTRUCTED,
5800 "Is the UPN Name constructed?", HFILL }},
5801 { &hf_krb_pac_upn_flag_has_sam_name_and_sid, {
5802 "SAM_NAME and SID Included",
5803 "kerberos.pac.upn.flags.has_sam_name_and_sid",
5804 FT_BOOLEAN, 32,
5805 TFS(&tfs_krb_pac_upn_flag_has_sam_name_and_sid),
5806 PAC_UPN_DNS_FLAG_HAS_SAM_NAME_AND_SID,
5807 "Are SAM_NAME and SID included?", HFILL }},
5808 { &hf_krb_pac_upn_upn_offset, {
5809 "UPN Offset", "kerberos.pac.upn.upn_offset", FT_UINT16, BASE_DEC,
5810 NULL, 0, NULL, HFILL }},
5811 { &hf_krb_pac_upn_upn_len, {
5812 "UPN Len", "kerberos.pac.upn.upn_len", FT_UINT16, BASE_DEC,
5813 NULL, 0, NULL, HFILL }},
5814 { &hf_krb_pac_upn_upn_name, {
5815 "UPN Name", "kerberos.pac.upn.upn_name", FT_STRING, BASE_NONE,
5816 NULL, 0, NULL, HFILL }},
5817 { &hf_krb_pac_upn_dns_offset, {
5818 "DNS Offset", "kerberos.pac.upn.dns_offset", FT_UINT16, BASE_DEC,
5819 NULL, 0, NULL, HFILL }},
5820 { &hf_krb_pac_upn_dns_len, {
5821 "DNS Len", "kerberos.pac.upn.dns_len", FT_UINT16, BASE_DEC,
5822 NULL, 0, NULL, HFILL }},
5823 { &hf_krb_pac_upn_dns_name, {
5824 "DNS Name", "kerberos.pac.upn.dns_name", FT_STRING, BASE_NONE,
5825 NULL, 0, NULL, HFILL }},
5826 { &hf_krb_pac_upn_samaccountname_offset, {
5827 "sAMAccountName Offset", "kerberos.pac.upn.samaccountname_offset", FT_UINT16, BASE_DEC,
5828 NULL, 0, NULL, HFILL }},
5829 { &hf_krb_pac_upn_samaccountname_len, {
5830 "sAMAccountName Len", "kerberos.pac.upn.samaccountname_len", FT_UINT16, BASE_DEC,
5831 NULL, 0, NULL, HFILL }},
5832 { &hf_krb_pac_upn_samaccountname, {
5833 "sAMAccountName", "kerberos.pac.upn.samaccountname", FT_STRING, BASE_NONE,
5834 NULL, 0, NULL, HFILL }},
5835 { &hf_krb_pac_upn_objectsid_offset, {
5836 "objectSid Offset", "kerberos.pac.upn.objectsid_offset", FT_UINT16, BASE_DEC,
5837 NULL, 0, NULL, HFILL }},
5838 { &hf_krb_pac_upn_objectsid_len, {
5839 "objectSid Len", "kerberos.pac.upn.objectsid_len", FT_UINT16, BASE_DEC,
5840 NULL, 0, NULL, HFILL }},
5841 { &hf_krb_pac_client_claims_info, {
5842 "PAC_CLIENT_CLAIMS_INFO", "kerberos.pac_client_claims_info", FT_BYTES, BASE_NONE,
5843 NULL, 0, "PAC_CLIENT_CLAIMS_INFO structure", HFILL }},
5844 { &hf_krb_pac_device_info, {
5845 "PAC_DEVICE_INFO", "kerberos.pac_device_info", FT_BYTES, BASE_NONE,
5846 NULL, 0, "PAC_DEVICE_INFO structure", HFILL }},
5847 { &hf_krb_pac_device_claims_info, {
5848 "PAC_DEVICE_CLAIMS_INFO", "kerberos.pac_device_claims_info", FT_BYTES, BASE_NONE,
5849 NULL, 0, "PAC_DEVICE_CLAIMS_INFO structure", HFILL }},
5850 { &hf_krb_pac_ticket_checksum, {
5851 "PAC_TICKET_CHECKSUM", "kerberos.pac_ticket_checksum", FT_BYTES, BASE_NONE,
5852 NULL, 0, "PAC_TICKET_CHECKSUM structure", HFILL }},
5853 { &hf_krb_pac_attributes_info, {
5854 "PAC_ATTRIBUTES_INFO", "kerberos.pac_attributes_info", FT_BYTES, BASE_NONE,
5855 NULL, 0, "PAC_ATTRIBUTES_INFO structure", HFILL }},
5856 { &hf_krb_pac_attributes_info_length, {
5857 "Flags Valid Length", "kerberos.pac.attributes_info.length", FT_UINT32, BASE_DEC,
5858 NULL, 0, NULL, HFILL }},
5859 { &hf_krb_pac_attributes_info_flags, {
5860 "Flags", "kerberos.pac.attributes_info.flags",
5861 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
5862 { &hf_krb_pac_attributes_info_flags_pac_was_requested, {
5863 "PAC Requested",
5864 "kerberos.pac.attributes.flags.pac_was_requested",
5865 FT_BOOLEAN, 32,
5866 TFS(&tfs_krb_pac_attributes_info_pac_was_requested),
5867 PAC_ATTRIBUTE_FLAG_PAC_WAS_REQUESTED,
5868 "Was a PAC requested?", HFILL }},
5869 { &hf_krb_pac_attributes_info_flags_pac_was_given_implicitly, {
5870 "PAC given Implicitly",
5871 "kerberos.pac.attributes.flags.pac_was_given_implicitly",
5872 FT_BOOLEAN, 32,
5873 TFS(&tfs_krb_pac_attributes_info_pac_was_given_implicitly),
5874 PAC_ATTRIBUTE_FLAG_PAC_WAS_GIVEN_IMPLICITLY,
5875 "Was PAC given implicitly?", HFILL }},
5876 { &hf_krb_pac_requester_sid, {
5877 "PAC_REQUESTER_SID", "kerberos.pac_requester_sid", FT_BYTES, BASE_NONE,
5878 NULL, 0, "PAC_REQUESTER_SID structure", HFILL }},
5879 { &hf_krb_pac_full_checksum, {
5880 "PAC_FULL_CHECKSUM", "kerberos.pac_full_checksum", FT_BYTES, BASE_NONE,
5881 NULL, 0, "PAC_FULL_CHECKSUM structure", HFILL }},
5882 { &hf_krb_pa_supported_enctypes,
5883 { "SupportedEnctypes", "kerberos.supported_entypes",
5884 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
5885 { &hf_krb_pa_supported_enctypes_des_cbc_crc,
5886 { "des-cbc-crc", "kerberos.supported_entypes.des-cbc-crc",
5887 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x00000001, NULL, HFILL }},
5888 { &hf_krb_pa_supported_enctypes_des_cbc_md5,
5889 { "des-cbc-md5", "kerberos.supported_entypes.des-cbc-md5",
5890 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x00000002, NULL, HFILL }},
5891 { &hf_krb_pa_supported_enctypes_rc4_hmac,
5892 { "rc4-hmac", "kerberos.supported_entypes.rc4-hmac",
5893 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x00000004, NULL, HFILL }},
5894 { &hf_krb_pa_supported_enctypes_aes128_cts_hmac_sha1_96,
5895 { "aes128-cts-hmac-sha1-96", "kerberos.supported_entypes.aes128-cts-hmac-sha1-96",
5896 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x00000008, NULL, HFILL }},
5897 { &hf_krb_pa_supported_enctypes_aes256_cts_hmac_sha1_96,
5898 { "aes256-cts-hmac-sha1-96", "kerberos.supported_entypes.aes256-cts-hmac-sha1-96",
5899 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x00000010, NULL, HFILL }},
5900 { &hf_krb_pa_supported_enctypes_aes256_cts_hmac_sha1_96_sk,
5901 { "aes256-cts-hmac-sha1-96-sk", "kerberos.supported_entypes.aes256-cts-hmac-sha1-96-sk",
5902 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x00000020, NULL, HFILL }},
5903 { &hf_krb_pa_supported_enctypes_fast_supported,
5904 { "fast-supported", "kerberos.supported_entypes.fast-supported",
5905 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x00010000, NULL, HFILL }},
5906 { &hf_krb_pa_supported_enctypes_compound_identity_supported,
5907 { "compound-identity-supported", "kerberos.supported_entypes.compound-identity-supported",
5908 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x00020000, NULL, HFILL }},
5909 { &hf_krb_pa_supported_enctypes_claims_supported,
5910 { "claims-supported", "kerberos.supported_entypes.claims-supported",
5911 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x00040000, NULL, HFILL }},
5912 { &hf_krb_pa_supported_enctypes_resource_sid_compression_disabled,
5913 { "resource-sid-compression-disabled", "kerberos.supported_entypes.resource-sid-compression-disabled",
5914 FT_BOOLEAN, 32, TFS(&tfs_supported_not_supported), 0x00080000, NULL, HFILL }},
5915 { &hf_krb_ad_ap_options,
5916 { "AD-AP-Options", "kerberos.ad_ap_options",
5917 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
5918 { &hf_krb_ad_ap_options_cbt,
5919 { "ChannelBindings", "kerberos.ad_ap_options.cbt",
5920 FT_BOOLEAN, 32, TFS(&tfs_set_notset), 0x00004000, NULL, HFILL }},
5921 { &hf_krb_ad_ap_options_unverified_target_name,
5922 { "UnverifiedTargetName", "kerberos.ad_ap_options.unverified_target_name",
5923 FT_BOOLEAN, 32, TFS(&tfs_set_notset), 0x00008000, NULL, HFILL }},
5924 { &hf_krb_ad_target_principal,
5925 { "Target Principal", "kerberos.ad_target_principal",
5926 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
5927 { &hf_krb_key_hidden_item,
5928 { "KeyHiddenItem", "krb5.key_hidden_item",
5929 FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
5930 { &hf_kerberos_KERB_TICKET_LOGON,
5931 { "KERB_TICKET_LOGON", "kerberos.KERB_TICKET_LOGON",
5932 FT_NONE, BASE_NONE, NULL, 0,
5933 NULL, HFILL }},
5934 { &hf_kerberos_KERB_TICKET_LOGON_MessageType,
5935 { "MessageType", "kerberos.KERB_TICKET_LOGON.MessageType",
5936 FT_UINT32, BASE_DEC, VALS(KERB_LOGON_SUBMIT_TYPE), 0,
5937 NULL, HFILL }},
5938 { &hf_kerberos_KERB_TICKET_LOGON_Flags,
5939 { "Flags", "kerberos.KERB_TICKET_LOGON.Flags",
5940 FT_UINT32, BASE_DEC, NULL, 0,
5941 NULL, HFILL }},
5942 { &hf_kerberos_KERB_TICKET_LOGON_ServiceTicketLength,
5943 { "ServiceTicketLength", "kerberos.KERB_TICKET_LOGON.ServiceTicketLength",
5944 FT_UINT32, BASE_DEC, NULL, 0,
5945 NULL, HFILL }},
5946 { &hf_kerberos_KERB_TICKET_LOGON_TicketGrantingTicketLength,
5947 { "TicketGrantingTicketLength", "kerberos.KERB_TICKET_LOGON.TicketGrantingTicketLength",
5948 FT_UINT32, BASE_DEC, NULL, 0,
5949 NULL, HFILL }},
5950 { &hf_kerberos_KERB_TICKET_LOGON_ServiceTicket,
5951 { "ServiceTicket", "kerberos.KERB_TICKET_LOGON.ServiceTicket",
5952 FT_NONE, BASE_NONE, NULL, 0,
5953 NULL, HFILL }},
5954 { &hf_kerberos_KERB_TICKET_LOGON_TicketGrantingTicket,
5955 { "TicketGrantingTicket", "kerberos.KERB_TICKET_LOGON.TicketGrantingTicket",
5956 FT_NONE, BASE_NONE, NULL, 0,
5957 NULL, HFILL }},
5958 { &hf_kerberos_KERB_TICKET_LOGON_FLAG_ALLOW_EXPIRED_TICKET,
5959 { "allow_expired_ticket", "kerberos.KERB_TICKET_LOGON.FLAG_ALLOW_EXPIRED_TICKET",
5960 FT_BOOLEAN, 32, NULL, KERB_LOGON_FLAG_ALLOW_EXPIRED_TICKET,
5961 NULL, HFILL }},
5962 { &hf_kerberos_KERB_TICKET_LOGON_FLAG_REDIRECTED,
5963 { "redirected", "kerberos.KERB_TICKET_LOGON.FLAG_REDIRECTED",
5964 FT_BOOLEAN, 32, NULL, KERB_LOGON_FLAG_REDIRECTED,
5965 NULL, HFILL }},
5966 #ifdef HAVE_KERBEROS
5967 { &hf_kerberos_KrbFastResponse,
5968 { "KrbFastResponse", "kerberos.KrbFastResponse_element",
5969 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL }},
5970 { &hf_kerberos_strengthen_key,
5971 { "strengthen-key", "kerberos.strengthen_key_element",
5972 FT_NONE, BASE_NONE, NULL, 0,
5973 NULL, HFILL }},
5974 { &hf_kerberos_finished,
5975 { "finished", "kerberos.finished_element",
5976 FT_NONE, BASE_NONE, NULL, 0,
5977 "KrbFastFinished", HFILL }},
5978 { &hf_kerberos_fast_options,
5979 { "fast-options", "kerberos.fast_options",
5980 FT_BYTES, BASE_NONE, NULL, 0,
5981 "FastOptions", HFILL }},
5982 { &hf_kerberos_FastOptions_reserved,
5983 { "reserved", "kerberos.FastOptions.reserved",
5984 FT_BOOLEAN, 8, NULL, 0x80,
5985 NULL, HFILL }},
5986 { &hf_kerberos_FastOptions_hide_client_names,
5987 { "hide-client-names", "kerberos.FastOptions.hide.client.names",
5988 FT_BOOLEAN, 8, NULL, 0x40,
5989 NULL, HFILL }},
5990 { &hf_kerberos_FastOptions_spare_bit2,
5991 { "spare_bit2", "kerberos.FastOptions.spare.bit2",
5992 FT_BOOLEAN, 8, NULL, 0x20,
5993 NULL, HFILL }},
5994 { &hf_kerberos_FastOptions_spare_bit3,
5995 { "spare_bit3", "kerberos.FastOptions.spare.bit3",
5996 FT_BOOLEAN, 8, NULL, 0x10,
5997 NULL, HFILL }},
5998 { &hf_kerberos_FastOptions_spare_bit4,
5999 { "spare_bit4", "kerberos.FastOptions.spare.bit4",
6000 FT_BOOLEAN, 8, NULL, 0x08,
6001 NULL, HFILL }},
6002 { &hf_kerberos_FastOptions_spare_bit5,
6003 { "spare_bit5", "kerberos.FastOptions.spare.bit5",
6004 FT_BOOLEAN, 8, NULL, 0x04,
6005 NULL, HFILL }},
6006 { &hf_kerberos_FastOptions_spare_bit6,
6007 { "spare_bit6", "kerberos.FastOptions.spare.bit6",
6008 FT_BOOLEAN, 8, NULL, 0x02,
6009 NULL, HFILL }},
6010 { &hf_kerberos_FastOptions_spare_bit7,
6011 { "spare_bit7", "kerberos.FastOptions.spare.bit7",
6012 FT_BOOLEAN, 8, NULL, 0x01,
6013 NULL, HFILL }},
6014 { &hf_kerberos_FastOptions_spare_bit8,
6015 { "spare_bit8", "kerberos.FastOptions.spare.bit8",
6016 FT_BOOLEAN, 8, NULL, 0x80,
6017 NULL, HFILL }},
6018 { &hf_kerberos_FastOptions_spare_bit9,
6019 { "spare_bit9", "kerberos.FastOptions.spare.bit9",
6020 FT_BOOLEAN, 8, NULL, 0x40,
6021 NULL, HFILL }},
6022 { &hf_kerberos_FastOptions_spare_bit10,
6023 { "spare_bit10", "kerberos.FastOptions.spare.bit10",
6024 FT_BOOLEAN, 8, NULL, 0x20,
6025 NULL, HFILL }},
6026 { &hf_kerberos_FastOptions_spare_bit11,
6027 { "spare_bit11", "kerberos.FastOptions.spare.bit11",
6028 FT_BOOLEAN, 8, NULL, 0x10,
6029 NULL, HFILL }},
6030 { &hf_kerberos_FastOptions_spare_bit12,
6031 { "spare_bit12", "kerberos.FastOptions.spare.bit12",
6032 FT_BOOLEAN, 8, NULL, 0x08,
6033 NULL, HFILL }},
6034 { &hf_kerberos_FastOptions_spare_bit13,
6035 { "spare_bit13", "kerberos.FastOptions.spare.bit13",
6036 FT_BOOLEAN, 8, NULL, 0x04,
6037 NULL, HFILL }},
6038 { &hf_kerberos_FastOptions_spare_bit14,
6039 { "spare_bit14", "kerberos.FastOptions.spare.bit14",
6040 FT_BOOLEAN, 8, NULL, 0x02,
6041 NULL, HFILL }},
6042 { &hf_kerberos_FastOptions_spare_bit15,
6043 { "spare_bit15", "kerberos.FastOptions.spare.bit15",
6044 FT_BOOLEAN, 8, NULL, 0x01,
6045 NULL, HFILL }},
6046 { &hf_kerberos_FastOptions_kdc_follow_referrals,
6047 { "kdc-follow-referrals", "kerberos.FastOptions.kdc.follow.referrals",
6048 FT_BOOLEAN, 8, NULL, 0x80,
6049 NULL, HFILL }},
6050 { &hf_kerberos_ticket_checksum,
6051 { "ticket-checksum", "kerberos.ticket_checksum_element",
6052 FT_NONE, BASE_NONE, NULL, 0,
6053 "Checksum", HFILL }},
6054 { &hf_krb_patimestamp,
6055 { "patimestamp", "kerberos.patimestamp",
6056 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0, "KerberosTime", HFILL }},
6057 { &hf_krb_pausec,
6058 { "pausec", "kerberos.pausec",
6059 FT_UINT32, BASE_DEC, NULL, 0, "Microseconds", HFILL }},
6060 #endif /* HAVE_KERBEROS */
6062 #include "packet-kerberos-hfarr.c"
6065 /* List of subtrees */
6066 static int *ett[] = {
6067 &ett_kerberos,
6068 &ett_krb_recordmark,
6069 &ett_krb_pac,
6070 &ett_krb_pac_drep,
6071 &ett_krb_pac_midl_blob,
6072 &ett_krb_pac_logon_info,
6073 &ett_krb_pac_credential_info,
6074 &ett_krb_pac_s4u_delegation_info,
6075 &ett_krb_pac_upn_dns_info,
6076 &ett_krb_pac_upn_dns_info_flags,
6077 &ett_krb_pac_device_info,
6078 &ett_krb_pac_server_checksum,
6079 &ett_krb_pac_privsvr_checksum,
6080 &ett_krb_pac_client_info_type,
6081 &ett_krb_pac_ticket_checksum,
6082 &ett_krb_pac_attributes_info,
6083 &ett_krb_pac_attributes_info_flags,
6084 &ett_krb_pac_requester_sid,
6085 &ett_krb_pac_full_checksum,
6086 &ett_krb_pa_supported_enctypes,
6087 &ett_krb_ad_ap_options,
6088 &ett_kerberos_KERB_TICKET_LOGON,
6089 #ifdef HAVE_KERBEROS
6090 &ett_krb_pa_enc_ts_enc,
6091 &ett_kerberos_KrbFastFinished,
6092 &ett_kerberos_KrbFastResponse,
6093 &ett_kerberos_KrbFastReq,
6094 &ett_kerberos_FastOptions,
6095 #endif
6096 #include "packet-kerberos-ettarr.c"
6099 static ei_register_info ei[] = {
6100 { &ei_kerberos_missing_keytype, { "kerberos.missing_keytype", PI_DECRYPTION, PI_WARN, "Missing keytype", EXPFILL }},
6101 { &ei_kerberos_decrypted_keytype, { "kerberos.decrypted_keytype", PI_SECURITY, PI_CHAT, "Decrypted keytype", EXPFILL }},
6102 { &ei_kerberos_learnt_keytype, { "kerberos.learnt_keytype", PI_SECURITY, PI_CHAT, "Learnt keytype", EXPFILL }},
6103 { &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 }},
6104 { &ei_krb_gssapi_dlglen, { "kerberos.gssapi.dlglen.error", PI_MALFORMED, PI_ERROR, "DlgLen is not the same as number of bytes remaining", EXPFILL }},
6107 expert_module_t* expert_krb;
6108 module_t *krb_module;
6110 proto_kerberos = proto_register_protocol("Kerberos", "KRB5", "kerberos");
6111 proto_register_field_array(proto_kerberos, hf, array_length(hf));
6112 proto_register_subtree_array(ett, array_length(ett));
6113 expert_krb = expert_register_protocol(proto_kerberos);
6114 expert_register_field_array(expert_krb, ei, array_length(ei));
6116 kerberos_tap = register_tap("kerberos");
6117 register_srt_table(proto_kerberos, NULL, 1, krb5stat_packet, krb5stat_init, NULL);
6119 /* Register dissectors */
6120 kerberos_handle_udp = register_dissector("kerberos.udp", dissect_kerberos_udp, proto_kerberos);
6121 kerberos_handle_tcp = register_dissector("kerberos.tcp", dissect_kerberos_tcp, proto_kerberos);
6123 /* Register preferences */
6124 krb_module = prefs_register_protocol(proto_kerberos, kerberos_prefs_apply_cb);
6125 prefs_register_bool_preference(krb_module, "desegment",
6126 "Reassemble Kerberos over TCP messages spanning multiple TCP segments",
6127 "Whether the Kerberos dissector should reassemble messages spanning multiple TCP segments."
6128 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
6129 &krb_desegment);
6130 #ifdef HAVE_KERBEROS
6131 prefs_register_bool_preference(krb_module, "decrypt",
6132 "Try to decrypt Kerberos blobs",
6133 "Whether the dissector should try to decrypt "
6134 "encrypted Kerberos blobs. This requires that the proper "
6135 "keytab file is installed as well.", &krb_decrypt);
6137 prefs_register_filename_preference(krb_module, "file",
6138 "Kerberos keytab file",
6139 "The keytab file containing all the secrets",
6140 &keytab_filename, false);
6142 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
6143 wmem_register_callback(wmem_epan_scope(), enc_key_list_cb, NULL);
6144 kerberos_longterm_keys = wmem_map_new(wmem_epan_scope(),
6145 enc_key_content_hash,
6146 enc_key_content_equal);
6147 kerberos_all_keys = wmem_map_new_autoreset(wmem_epan_scope(),
6148 wmem_file_scope(),
6149 enc_key_content_hash,
6150 enc_key_content_equal);
6151 kerberos_app_session_keys = wmem_map_new_autoreset(wmem_epan_scope(),
6152 wmem_file_scope(),
6153 enc_key_content_hash,
6154 enc_key_content_equal);
6155 #endif /* defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS) */
6156 #endif /* HAVE_KERBEROS */
6159 static int wrap_dissect_gss_kerb(tvbuff_t *tvb, int offset, packet_info *pinfo,
6160 proto_tree *tree, dcerpc_info *di _U_,uint8_t *drep _U_)
6162 tvbuff_t *auth_tvb;
6164 auth_tvb = tvb_new_subset_remaining(tvb, offset);
6166 dissect_kerberos_main(auth_tvb, pinfo, tree, false, NULL);
6168 return tvb_captured_length_remaining(tvb, offset);
6172 static dcerpc_auth_subdissector_fns gss_kerb_auth_connect_fns = {
6173 wrap_dissect_gss_kerb, /* Bind */
6174 wrap_dissect_gss_kerb, /* Bind ACK */
6175 wrap_dissect_gss_kerb, /* AUTH3 */
6176 NULL, /* Request verifier */
6177 NULL, /* Response verifier */
6178 NULL, /* Request data */
6179 NULL /* Response data */
6182 static dcerpc_auth_subdissector_fns gss_kerb_auth_sign_fns = {
6183 wrap_dissect_gss_kerb, /* Bind */
6184 wrap_dissect_gss_kerb, /* Bind ACK */
6185 wrap_dissect_gss_kerb, /* AUTH3 */
6186 wrap_dissect_gssapi_verf, /* Request verifier */
6187 wrap_dissect_gssapi_verf, /* Response verifier */
6188 NULL, /* Request data */
6189 NULL /* Response data */
6192 static dcerpc_auth_subdissector_fns gss_kerb_auth_seal_fns = {
6193 wrap_dissect_gss_kerb, /* Bind */
6194 wrap_dissect_gss_kerb, /* Bind ACK */
6195 wrap_dissect_gss_kerb, /* AUTH3 */
6196 wrap_dissect_gssapi_verf, /* Request verifier */
6197 wrap_dissect_gssapi_verf, /* Response verifier */
6198 wrap_dissect_gssapi_payload, /* Request data */
6199 wrap_dissect_gssapi_payload /* Response data */
6204 void
6205 proto_reg_handoff_kerberos(void)
6207 krb4_handle = find_dissector_add_dependency("krb4", proto_kerberos);
6209 dissector_add_uint_with_preference("udp.port", UDP_PORT_KERBEROS, kerberos_handle_udp);
6210 dissector_add_uint_with_preference("tcp.port", TCP_PORT_KERBEROS, kerberos_handle_tcp);
6212 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_CONNECT,
6213 DCE_C_RPC_AUTHN_PROTOCOL_GSS_KERBEROS,
6214 &gss_kerb_auth_connect_fns);
6216 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_INTEGRITY,
6217 DCE_C_RPC_AUTHN_PROTOCOL_GSS_KERBEROS,
6218 &gss_kerb_auth_sign_fns);
6220 register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_PRIVACY,
6221 DCE_C_RPC_AUTHN_PROTOCOL_GSS_KERBEROS,
6222 &gss_kerb_auth_seal_fns);
6226 * Editor modelines - https://www.wireshark.org/tools/modelines.html
6228 * Local variables:
6229 * c-basic-offset: 8
6230 * tab-width: 8
6231 * indent-tabs-mode: t
6232 * End:
6234 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
6235 * :indentSize=8:tabSize=8:noTabs=false: