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