2 * Routines for Kerberos
3 * Wes Hardaker (c) 2000
4 * wjhardaker@ucdavis.edu
6 * $Id: packet-kerberos.c,v 1.10 2000/12/25 06:59:33 guy Exp $
8 * Ethereal - Network traffic analyzer
9 * By Gerald Combs <gerald@zing.org>
10 * Copyright 1998 Didier Jorand
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
35 #ifdef HAVE_SYS_TYPES_H
36 # include <sys/types.h>
47 #define UDP_PORT_KERBEROS 88
48 #define TCP_PORT_KERBEROS 88
50 static gint ett_kerberos = -1;
51 static gint ett_preauth = -1;
52 static gint ett_addresses = -1;
53 static gint ett_request = -1;
54 static gint ett_princ = -1;
55 static gint ett_ticket = -1;
56 static gint ett_encrypted = -1;
57 static gint ett_etype = -1;
58 static gint proto_kerberos = -1;
60 #define KRB5_MSG_AS_REQ 10 /* AS-REQ type */
61 #define KRB5_MSG_AS_REP 11 /* AS-REP type */
62 #define KRB5_MSG_TGS_REQ 12 /* TGS-REQ type */
63 #define KRB5_MSG_TGS_REP 13 /* TGS-REP type */
64 #define KRB5_MSG_AP_REQ 14 /* AP-REQ type */
65 #define KRB5_MSG_AP_REP 15 /* AP-REP type */
67 #define KRB5_MSG_SAFE 20 /* KRB-SAFE type */
68 #define KRB5_MSG_PRIV 21 /* KRB-PRIV type */
69 #define KRB5_MSG_CRED 22 /* KRB-CRED type */
70 #define KRB5_MSG_ERROR 30 /* KRB-ERROR type */
72 /* Type tags within KDC-REQ */
73 #define KRB5_KDC_REQ_PVNO 1
74 #define KRB5_KDC_REQ_MSG_TYPE 2
75 #define KRB5_KDC_REQ_PADATA 3
76 #define KRB5_KDC_REQ_REQBODY 4
78 /* Type tags within KDC-REP */
79 #define KRB5_KDC_REP_PVNO 0
80 #define KRB5_KDC_REP_MSG_TYPE 1
81 #define KRB5_KDC_REP_PADATA 2
82 #define KRB5_KDC_REP_CREALM 3
83 #define KRB5_KDC_REP_CNAME 4
84 #define KRB5_KDC_REP_TICKET 5
85 #define KRB5_KDC_REP_ENC_PART 6
87 /* Type tags within KDC-REQ-BODY */
88 #define KRB5_BODY_KDC_OPTIONS 0
89 #define KRB5_BODY_CNAME 1
90 #define KRB5_BODY_REALM 2
91 #define KRB5_BODY_SNAME 3
92 #define KRB5_BODY_FROM 4
93 #define KRB5_BODY_TILL 5
94 #define KRB5_BODY_RTIME 6
95 #define KRB5_BODY_NONCE 7
96 #define KRB5_BODY_ENCTYPE 8
97 #define KRB5_BODY_ADDRESSES 9
98 #define KRB5_BODY_ENC_AUTHORIZATION_DATA 10
99 #define KRB5_BODY_ADDITIONAL_TICKETS 11
101 #define KRB5_ADDR_IPv4 0x02
102 #define KRB5_ADDR_CHAOS 0x05
103 #define KRB5_ADDR_XEROX 0x06
104 #define KRB5_ADDR_ISO 0x07
105 #define KRB5_ADDR_DECNET 0x0c
106 #define KRB5_ADDR_APPLETALK 0x10
108 #define KRB5_ENCTYPE_NULL 0
109 #define KRB5_ENCTYPE_DES_CBC_CRC 1
110 #define KRB5_ENCTYPE_DES_CBC_MD4 2
111 #define KRB5_ENCTYPE_DES_CBC_MD5 3
112 #define KRB5_ENCTYPE_DES_CBC_RAW 4
113 #define KRB5_ENCTYPE_DES3_CBC_SHA 5
114 #define KRB5_ENCTYPE_DES3_CBC_RAW 6
115 #define KRB5_ENCTYPE_DES_HMAC_SHA1 8
116 #define KRB5_ENCTYPE_DES3_CBC_SHA1 0x10
117 #define KRB5_ENCTYPE_UNKNOWN 0x1ff
118 #define KRB5_ENCTYPE_LOCAL_DES3_HMAC_SHA1 0x7007
120 #define KRB5_PA_TGS_REQ 1
121 #define KRB5_PA_ENC_TIMESTAMP 2
122 #define KRB5_PA_PW_SALT 3
123 #define KRB5_PA_ENC_ENCKEY 4
124 #define KRB5_PA_ENC_UNIX_TIME 5
125 #define KRB5_PA_ENC_SANDIA_SECURID 6
126 #define KRB5_PA_SESAME 7
127 #define KRB5_PA_OSF_DCE 8
128 #define KRB5_PA_CYBERSAFE_SECUREID 9
129 #define KRB5_PA_AFS3_SALT 10
130 #define KRB5_PA_ENCTYPE_INFO 11
131 #define KRB5_PA_SAM_CHALLENGE 12
132 #define KRB5_PA_SAM_RESPONSE 13
133 #define KRB5_PA_DASS 16
135 /* Type tags within Ticket */
136 #define KRB5_TKT_TKT_VNO 0
137 #define KRB5_TKT_REALM 1
138 #define KRB5_TKT_SNAME 2
139 #define KRB5_TKT_ENC_PART 3
141 /* Principal name-type */
142 #define KRB5_NT_UNKNOWN 0
143 #define KRB5_NT_PRINCIPAL 1
144 #define KRB5_NT_SRV_INST 2
145 #define KRB5_NT_SRV_HST 3
146 #define KRB5_NT_SRV_XHST 4
147 #define KRB5_NT_UID 5
149 static const value_string krb5_princ_types[] = {
150 { KRB5_NT_UNKNOWN , "Unknown" },
151 { KRB5_NT_PRINCIPAL , "Principal" },
152 { KRB5_NT_SRV_INST , "Service and Instance" },
153 { KRB5_NT_SRV_HST , "Service and Host" },
154 { KRB5_NT_SRV_XHST , "Service and Host Components" },
155 { KRB5_NT_UID , "Unique ID" },
158 static const value_string krb5_preauthentication_types[] = {
159 { KRB5_PA_TGS_REQ , "PA-TGS-REQ" },
160 { KRB5_PA_ENC_TIMESTAMP , "PA-ENC-TIMESTAMP" },
161 { KRB5_PA_PW_SALT , "PA-PW-SALT" },
162 { KRB5_PA_ENC_ENCKEY , "PA-ENC-ENCKEY" },
163 { KRB5_PA_ENC_UNIX_TIME , "PA-ENC-UNIX-TIME" },
164 { KRB5_PA_ENC_SANDIA_SECURID , "PA-PW-SALT" },
165 { KRB5_PA_SESAME , "PA-SESAME" },
166 { KRB5_PA_OSF_DCE , "PA-OSF-DCE" },
167 { KRB5_PA_CYBERSAFE_SECUREID , "PA-CYBERSAFE-SECURID" },
168 { KRB5_PA_AFS3_SALT , "PA-AFS3-SALT" },
169 { KRB5_PA_ENCTYPE_INFO , "PA-ENCTYPE-INFO" },
170 { KRB5_PA_SAM_CHALLENGE , "PA-SAM-CHALLENGE" },
171 { KRB5_PA_SAM_RESPONSE , "PA-SAM-RESPONSE" },
172 { KRB5_PA_DASS , "PA-DASS" },
175 static const value_string krb5_encryption_types[] = {
176 { KRB5_ENCTYPE_NULL , "NULL" },
177 { KRB5_ENCTYPE_DES_CBC_CRC , "des-cbc-crc" },
178 { KRB5_ENCTYPE_DES_CBC_MD4 , "des-cbc-md4" },
179 { KRB5_ENCTYPE_DES_CBC_MD5 , "des-cbc-md5" },
180 { KRB5_ENCTYPE_DES_CBC_RAW , "des-cbc-raw" },
181 { KRB5_ENCTYPE_DES3_CBC_SHA , "des3-cbc-sha" },
182 { KRB5_ENCTYPE_DES3_CBC_RAW , "des3-cbc-raw" },
183 { KRB5_ENCTYPE_DES_HMAC_SHA1 , "des-hmac-sha1" },
184 { KRB5_ENCTYPE_DES3_CBC_SHA1 , "des3-cbc-sha1" },
185 { KRB5_ENCTYPE_UNKNOWN , "unknown" },
186 { KRB5_ENCTYPE_LOCAL_DES3_HMAC_SHA1 , "local-des3-hmac-sha1" },
189 static const value_string krb5_address_types[] = {
190 { KRB5_ADDR_IPv4, "IPv4"},
191 { KRB5_ADDR_CHAOS, "CHAOS"},
192 { KRB5_ADDR_XEROX, "XEROX"},
193 { KRB5_ADDR_ISO, "ISO"},
194 { KRB5_ADDR_DECNET, "DECNET"},
195 { KRB5_ADDR_APPLETALK, "APPLETALK"}
198 static const value_string krb5_msg_types[] = {
199 { KRB5_MSG_TGS_REQ, "TGS-REQ" },
200 { KRB5_MSG_TGS_REP, "TGS-REP" },
201 { KRB5_MSG_AS_REQ, "AS-REQ" },
202 { KRB5_MSG_AS_REP, "AS-REP" },
203 { KRB5_MSG_AP_REQ, "AP-REQ" },
204 { KRB5_MSG_AP_REP, "AP-REP" },
205 { KRB5_MSG_SAFE, "KRB-SAFE" },
206 { KRB5_MSG_PRIV, "KRB-PRIV" },
207 { KRB5_MSG_CRED, "KRB-CRED" },
208 { KRB5_MSG_ERROR, "KRB-ERROR" }
211 static int dissect_PrincipalName(char *title, ASN1_SCK *asn1p,
212 frame_data *fd, proto_tree *tree,
214 static int dissect_Ticket(char *title, ASN1_SCK *asn1p, frame_data *fd,
215 proto_tree *tree, int start_offset);
216 static int dissect_EncryptedData(char *title, ASN1_SCK *asn1p, frame_data *fd,
217 proto_tree *tree, int start_offset);
218 static int dissect_Addresses(char *title, ASN1_SCK *asn1p, frame_data *fd,
219 proto_tree *tree, int start_offset);
222 to_error_str(int ret) {
226 return("Ran out of data");
228 case ASN1_ERR_EOC_MISMATCH:
229 return("EOC mismatch");
231 case ASN1_ERR_WRONG_TYPE:
232 return("Wrong type for that item");
234 case ASN1_ERR_LENGTH_NOT_DEFINITE:
235 return("Length was indefinite");
237 case ASN1_ERR_LENGTH_MISMATCH:
238 return("Length mismatch");
240 case ASN1_ERR_WRONG_LENGTH_FOR_TYPE:
241 return("Wrong length for that item's type");
244 return("Unknown error");
248 krb_proto_tree_add_time(proto_tree *tree, int offset, int str_len,
249 char *name, guchar *str) {
251 proto_tree_add_text(tree, NullTVB, offset, str_len,
252 "%s: %.4s-%.2s-%.2s %.2s:%.2s:%.2s (%.1s)",
253 name, str, str+4, str+6,
254 str+8, str+10, str+12,
260 * You must be kidding. I'm going to actually use a macro to do something?
264 #define KRB_HEAD_DECODE_OR_DIE(token) \
265 start = asn1p->pointer; \
266 ret = asn1_header_decode (asn1p, &cls, &con, &tag, &def, &item_len); \
267 if (ret != ASN1_ERR_NOERROR && ret != ASN1_ERR_EMPTY) {\
268 if (check_col(fd, COL_INFO)) \
269 col_add_fstr(fd, COL_INFO, "ERROR: Problem at %s: %s", \
270 token, to_error_str(ret)); \
274 if (check_col(fd, COL_INFO)) \
275 col_add_fstr(fd, COL_INFO, "not definite: %s", token); \
276 fprintf(stderr,"not definite: %s\n", token); \
279 offset += (asn1p->pointer - start);
281 #define CHECK_APPLICATION_TYPE(expected_tag) \
282 (cls == ASN1_APL && con == ASN1_CON && tag == expected_tag)
284 #define DIE_IF_NOT_APPLICATION_TYPE(token, expected_tag) \
285 if (!CHECK_APPLICATION_TYPE(expected_tag)) \
286 DIE_WITH_BAD_TYPE(token);
288 #define CHECK_CONTEXT_TYPE(expected_tag) \
289 (cls == ASN1_CTX && con == ASN1_CON && tag == expected_tag)
291 #define DIE_IF_NOT_CONTEXT_TYPE(token, expected_tag) \
292 if (!CHECK_CONTEXT_TYPE(expected_tag)) \
293 DIE_WITH_BAD_TYPE(token);
295 #define DIE_WITH_BAD_TYPE(token) \
297 if (check_col(fd, COL_INFO)) \
298 col_add_fstr(fd, COL_INFO, "ERROR: Problem at %s: %s", \
299 token, to_error_str(ASN1_ERR_WRONG_TYPE)); \
303 #define KRB_DECODE_APPLICATION_TAGGED_HEAD_OR_DIE(token, expected_tag) \
304 KRB_HEAD_DECODE_OR_DIE(token); \
305 DIE_IF_NOT_APPLICATION_TYPE(token, expected_tag);
307 #define KRB_DECODE_CONTEXT_HEAD_OR_DIE(token, expected_tag) \
308 KRB_HEAD_DECODE_OR_DIE(token); \
309 DIE_IF_NOT_CONTEXT_TYPE(token, expected_tag);
311 #define KRB_SEQ_HEAD_DECODE_OR_DIE(token) \
312 ret = asn1_sequence_decode (asn1p, &item_len, &header_len); \
313 if (ret != ASN1_ERR_NOERROR && ret != ASN1_ERR_EMPTY) {\
314 if (check_col(fd, COL_INFO)) \
315 col_add_fstr(fd, COL_INFO, "ERROR: Problem at %s: %s", \
316 token, to_error_str(ret)); \
319 offset += header_len;
321 #define KRB_DECODE_OR_DIE(token, fn, val) \
322 ret = fn (asn1p, &val, &length); \
323 if (ret != ASN1_ERR_NOERROR) { \
324 if (check_col(fd, COL_INFO)) \
325 col_add_fstr(fd, COL_INFO, "ERROR: Problem at %s: %s", \
326 token, to_error_str(ret)); \
330 #define KRB_DECODE_UINT32_OR_DIE(token, val) \
331 KRB_DECODE_OR_DIE(token, asn1_uint32_decode, val);
333 #define KRB_DECODE_STRING_OR_DIE(token, expected_tag, val, val_len, item_len) \
334 ret = asn1_string_decode (asn1p, &val, &val_len, &item_len, expected_tag); \
335 if (ret != ASN1_ERR_NOERROR) { \
336 if (check_col(fd, COL_INFO)) \
337 col_add_fstr(fd, COL_INFO, "ERROR: Problem at %s: %s", \
338 token, to_error_str(ret)); \
342 #define KRB_DECODE_OCTET_STRING_OR_DIE(token, val, val_len, item_len) \
343 KRB_DECODE_STRING_OR_DIE(token, ASN1_OTS, val, val_len, item_len)
345 #define KRB_DECODE_GENERAL_STRING_OR_DIE(token, val, val_len, item_len) \
346 KRB_DECODE_STRING_OR_DIE(token, ASN1_GENSTR, val, val_len, item_len)
348 #define KRB_DECODE_GENERAL_TIME_OR_DIE(token, val, val_len, item_len) \
349 KRB_DECODE_STRING_OR_DIE(token, ASN1_GENTIM, val, val_len, item_len)
351 /* dissect_type_value_pair decodes (roughly) this:
358 which is all over the place in krb5 */
361 dissect_type_value_pair(ASN1_SCK *asn1p, int *inoff,
362 guint32 *type, int *type_len, int *type_off,
363 guchar **val, int *val_len, int *val_off) {
372 start = asn1p->pointer;
373 asn1_header_decode (asn1p, &cls, &con, &tag, &def, &tmp_len);
374 offset += (asn1p->pointer - start);
378 start = asn1p->pointer;
379 asn1_header_decode (asn1p, &cls, &con, &tag, &def, &tmp_len);
380 offset += (asn1p->pointer - start);
386 ret = asn1_uint32_decode(asn1p, type, type_len);
387 if (ret != ASN1_ERR_NOERROR) {
388 fprintf(stderr,"die: type_value_pair: type, %s\n", to_error_str(ret));
393 /* OCTET STRING (or generic data) */
395 start = asn1p->pointer;
396 asn1_header_decode (asn1p, &cls, &con, &tag, &def, val_len);
397 asn1_header_decode (asn1p, &cls, &con, &tag, &def, val_len);
398 offset += asn1p->pointer - start;
404 asn1_string_value_decode (asn1p, *val_len, val);
406 *inoff = offset + *val_len;
410 dissect_kerberos_main(const u_char *pd, int offset, frame_data *fd,
413 proto_tree *kerberos_tree = NULL;
414 proto_tree *etype_tree = NULL;
415 proto_tree *preauth_tree = NULL;
416 proto_tree *request_tree = NULL;
417 ASN1_SCK asn1, *asn1p = &asn1;
418 proto_item *item = NULL;
423 guint item_len, total_len;
428 guint protocol_message_type;
432 guint32 preauth_type;
438 int tmp_pos1, tmp_pos2;
441 item = proto_tree_add_item(tree, proto_kerberos, NullTVB, offset,
442 END_OF_FRAME, FALSE);
443 kerberos_tree = proto_item_add_subtree(item, ett_kerberos);
446 asn1_open(&asn1, &pd[offset], END_OF_FRAME);
449 KRB_HEAD_DECODE_OR_DIE("top");
450 protocol_message_type = tag;
453 KRB_HEAD_DECODE_OR_DIE("top2");
456 KRB_HEAD_DECODE_OR_DIE("version-wrap");
457 KRB_DECODE_UINT32_OR_DIE("version", version);
460 proto_tree_add_text(kerberos_tree, NullTVB, offset, length,
467 KRB_HEAD_DECODE_OR_DIE("message-type-wrap");
468 KRB_DECODE_UINT32_OR_DIE("message-type", msg_type);
471 proto_tree_add_text(kerberos_tree, NullTVB, offset, length,
473 val_to_str(msg_type, krb5_msg_types,
474 "Unknown msg type %#x"));
478 if (check_col(fd, COL_INFO))
479 col_add_str(fd, COL_INFO, val_to_str(msg_type, krb5_msg_types,
480 "Unknown msg type %#x"));
482 /* is preauthentication present? */
483 KRB_HEAD_DECODE_OR_DIE("padata-or-body");
484 if (((protocol_message_type == KRB5_MSG_AS_REQ ||
485 protocol_message_type == KRB5_MSG_TGS_REQ) &&
486 tag == KRB5_KDC_REQ_PADATA) ||
487 ((protocol_message_type == KRB5_MSG_AS_REP ||
488 protocol_message_type == KRB5_MSG_TGS_REP) &&
489 tag == KRB5_KDC_REP_PADATA)) {
490 /* pre-authentication supplied */
493 item = proto_tree_add_text(kerberos_tree, NullTVB, offset,
494 item_len, "Pre-Authentication");
495 preauth_tree = proto_item_add_subtree(item, ett_preauth);
498 KRB_HEAD_DECODE_OR_DIE("sequence of pa-data");
499 start = asn1p->pointer + item_len;
501 while(start > asn1p->pointer) {
502 dissect_type_value_pair(asn1p, &offset,
503 &preauth_type, &item_len, &tmp_pos1,
504 &str, &str_len, &tmp_pos2);
507 proto_tree_add_text(preauth_tree, NullTVB, tmp_pos1,
508 item_len, "Type: %s",
509 val_to_str(preauth_type,
510 krb5_preauthentication_types,
511 "Unknown preauth type %#x"));
512 proto_tree_add_text(preauth_tree, NullTVB, tmp_pos2,
513 str_len, "Value: %s",
514 bytes_to_str(str, str_len));
517 KRB_HEAD_DECODE_OR_DIE("message-body");
520 switch (protocol_message_type) {
522 case KRB5_MSG_AS_REQ:
523 case KRB5_MSG_TGS_REQ:
525 AS-REQ ::= [APPLICATION 10] KDC-REQ
526 TGS-REQ ::= [APPLICATION 12] KDC-REQ
528 KDC-REQ ::= SEQUENCE {
531 padata[3] SEQUENCE OF PA-DATA OPTIONAL,
532 req-body[4] KDC-REQ-BODY
535 KDC-REQ-BODY ::= SEQUENCE {
536 kdc-options[0] KDCOptions,
537 cname[1] PrincipalName OPTIONAL,
538 -- Used only in AS-REQ
539 realm[2] Realm, -- Server's realm
540 -- Also client's in AS-REQ
541 sname[3] PrincipalName OPTIONAL,
542 from[4] KerberosTime OPTIONAL,
543 till[5] KerberosTime,
544 rtime[6] KerberosTime OPTIONAL,
546 etype[8] SEQUENCE OF INTEGER, -- EncryptionType,
547 -- in preference order
548 addresses[9] HostAddresses OPTIONAL,
549 enc-authorization-data[10] EncryptedData OPTIONAL,
550 -- Encrypted AuthorizationData encoding
551 additional-tickets[11] SEQUENCE OF Ticket OPTIONAL
556 KRB_HEAD_DECODE_OR_DIE("body-sequence");
558 item = proto_tree_add_text(kerberos_tree, NullTVB, offset,
559 item_len, "Request");
560 request_tree = proto_item_add_subtree(item, ett_request);
564 KRB_HEAD_DECODE_OR_DIE("kdc options");
566 KRB_HEAD_DECODE_OR_DIE("kdc options:bits");
569 proto_tree_add_text(request_tree, NullTVB, offset, item_len,
571 bytes_to_str(asn1.pointer, item_len));
574 asn1.pointer += item_len;
576 KRB_HEAD_DECODE_OR_DIE("Client Name or Realm");
578 if (CHECK_CONTEXT_TYPE(KRB5_BODY_CNAME)) {
579 item_len = dissect_PrincipalName("Client Name", asn1p, fd,
580 request_tree, offset);
584 KRB_HEAD_DECODE_OR_DIE("Realm");
587 DIE_IF_NOT_CONTEXT_TYPE("Realm", KRB5_BODY_REALM);
588 KRB_DECODE_GENERAL_STRING_OR_DIE("Realm", str, str_len, item_len);
590 proto_tree_add_text(request_tree, NullTVB, offset, item_len,
591 "Realm: %.*s", str_len, str);
595 KRB_HEAD_DECODE_OR_DIE("Server Name");
596 if (CHECK_CONTEXT_TYPE(KRB5_BODY_SNAME)) {
597 item_len = dissect_PrincipalName("Server Name", asn1p, fd,
598 request_tree, offset);
602 KRB_HEAD_DECODE_OR_DIE("From or Till");
605 if (CHECK_CONTEXT_TYPE(KRB5_BODY_FROM)) {
606 KRB_DECODE_GENERAL_TIME_OR_DIE("From", str, str_len, item_len);
607 krb_proto_tree_add_time(request_tree, offset, item_len,
610 KRB_HEAD_DECODE_OR_DIE("Till");
613 DIE_IF_NOT_CONTEXT_TYPE("Till", KRB5_BODY_TILL);
614 KRB_DECODE_GENERAL_TIME_OR_DIE("Till", str, str_len, item_len);
615 krb_proto_tree_add_time(request_tree, offset, item_len,
619 KRB_HEAD_DECODE_OR_DIE("Renewable Until or Nonce");
620 if (CHECK_CONTEXT_TYPE(KRB5_BODY_RTIME)) {
621 KRB_DECODE_GENERAL_TIME_OR_DIE("Renewable Until", str, str_len, item_len);
622 krb_proto_tree_add_time(request_tree, offset, item_len,
623 "Renewable Until", str);
625 KRB_HEAD_DECODE_OR_DIE("Nonce");
628 DIE_IF_NOT_CONTEXT_TYPE("Nonce", KRB5_BODY_NONCE);
629 KRB_DECODE_UINT32_OR_DIE("Nonce", tmp_int);
631 proto_tree_add_text(request_tree, NullTVB, offset, length,
637 KRB_DECODE_CONTEXT_HEAD_OR_DIE("encryption type spot",
639 KRB_HEAD_DECODE_OR_DIE("encryption type list");
641 item = proto_tree_add_text(request_tree, NullTVB, offset,
642 item_len, "Encryption Types");
643 etype_tree = proto_item_add_subtree(item, ett_etype);
645 total_len = item_len;
646 while(total_len > 0) {
647 KRB_DECODE_UINT32_OR_DIE("encryption type", tmp_int);
649 proto_tree_add_text(etype_tree, NullTVB, offset, length,
652 krb5_encryption_types,
653 "Unknown encryption type %#x"));
659 KRB_HEAD_DECODE_OR_DIE("addresses");
660 if (CHECK_CONTEXT_TYPE(KRB5_BODY_ADDRESSES)) {
661 /* pre-authentication supplied */
663 offset = dissect_Addresses("Addresses", asn1p, fd, kerberos_tree,
667 KRB_HEAD_DECODE_OR_DIE("auth-data");
671 case KRB5_MSG_AS_REP:
672 case KRB5_MSG_TGS_REP:
674 AS-REP ::= [APPLICATION 11] KDC-REP
675 TGS-REP ::= [APPLICATION 13] KDC-REP
677 KDC-REP ::= SEQUENCE {
680 padata[2] SEQUENCE OF PA-DATA OPTIONAL,
682 cname[4] PrincipalName,
684 enc-part[6] EncryptedData
688 if (tag == KRB5_KDC_REP_CREALM) {
689 KRB_DECODE_GENERAL_STRING_OR_DIE("realm name", str, str_len, item_len);
691 proto_tree_add_text(kerberos_tree, NullTVB, offset, item_len,
692 "Realm: %.*s", str_len, str);
696 DIE_WITH_BAD_TYPE("crealm");
699 KRB_DECODE_CONTEXT_HEAD_OR_DIE("cname", KRB5_KDC_REP_CNAME);
700 item_len = dissect_PrincipalName("Client Name", asn1p, fd,
701 kerberos_tree, offset);
706 KRB_DECODE_CONTEXT_HEAD_OR_DIE("ticket", KRB5_KDC_REP_TICKET);
707 offset = dissect_Ticket("ticket", asn1p, fd, kerberos_tree, offset);
711 KRB_DECODE_CONTEXT_HEAD_OR_DIE("enc-msg-part",
712 KRB5_KDC_REP_ENC_PART);
713 offset = dissect_EncryptedData("Encrypted Payload", asn1p, fd,
714 kerberos_tree, offset);
723 dissect_kerberos(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
725 OLD_CHECK_DISPLAY_AS_DATA(proto_kerberos, pd, offset, fd, tree);
727 if (check_col(fd, COL_PROTOCOL))
728 col_set_str(fd, COL_PROTOCOL, "KRB5");
730 dissect_kerberos_main(pd, offset, fd, tree);
734 dissect_PrincipalName(char *title, ASN1_SCK *asn1p, frame_data *fd,
735 proto_tree *tree, int start_offset)
738 PrincipalName ::= SEQUENCE {
739 name-type[0] INTEGER,
740 name-string[1] SEQUENCE OF GeneralString
743 proto_tree *princ_tree = NULL;
744 int offset = start_offset;
750 guint header_len, item_len, total_len, type_len;
753 proto_item *item = NULL;
763 KRB_SEQ_HEAD_DECODE_OR_DIE("principal section");
766 item = proto_tree_add_text(tree, NullTVB, start_offset,
767 (offset - start_offset) + item_len, "%s",
769 princ_tree = proto_item_add_subtree(item, ett_princ);
775 KRB_DECODE_CONTEXT_HEAD_OR_DIE("principal type", 0);
776 KRB_DECODE_UINT32_OR_DIE("princ-type", princ_type);
777 type_offset = offset;
782 proto_tree_add_text(princ_tree, NullTVB, type_offset, type_len,
784 val_to_str(princ_type, krb5_princ_types,
785 "Unknown name type %#x"));
788 KRB_DECODE_CONTEXT_HEAD_OR_DIE("principal name-string", 1);
789 KRB_SEQ_HEAD_DECODE_OR_DIE("principal name-string sequence-of");
790 total_len = item_len;
791 if (total_len == 0) {
792 /* There are no name strings in this PrincipalName, so we can't
793 put any in the top-level item. */
794 return offset - start_offset;
797 /* Put the first name string in the top-level item. */
798 KRB_DECODE_GENERAL_STRING_OR_DIE("principal name", name, name_len, item_len);
800 proto_item_set_text(item, "%s: %.*s", title, (int) name_len, name);
801 proto_tree_add_text(princ_tree, NullTVB, offset, item_len,
802 "Name: %.*s", (int) name_len, name);
804 total_len -= item_len;
807 /* Now process the rest of the strings.
808 XXX - put them in the item as well? */
809 while (total_len > 0) {
810 KRB_DECODE_GENERAL_STRING_OR_DIE("principal name", name, name_len, item_len);
812 proto_tree_add_text(princ_tree, NullTVB, offset, item_len,
813 "Name: %.*s", (int) name_len, name);
815 total_len -= item_len;
818 return offset - start_offset;
822 dissect_Addresses(char *title, ASN1_SCK *asn1p, frame_data *fd,
823 proto_tree *tree, int start_offset) {
824 proto_tree *address_tree = NULL;
825 int offset = start_offset;
832 proto_item *item = NULL;
835 int tmp_pos1, tmp_pos2;
836 guint32 address_type;
841 KRB_HEAD_DECODE_OR_DIE("sequence of addresses");
843 item = proto_tree_add_text(tree, NullTVB, offset,
844 item_len, "Addresses");
845 address_tree = proto_item_add_subtree(item, ett_addresses);
848 start = asn1p->pointer + item_len;
850 while(start > asn1p->pointer) {
851 dissect_type_value_pair(asn1p, &offset,
852 &address_type, &item_len, &tmp_pos1,
853 &str, &str_len, &tmp_pos2);
856 proto_tree_add_text(address_tree, NullTVB, tmp_pos1,
857 item_len, "Type: %s",
858 val_to_str(address_type, krb5_address_types,
859 "Unknown address type %#x"));
860 switch(address_type) {
862 proto_tree_add_text(address_tree, NullTVB, tmp_pos2,
863 str_len, "Value: %d.%d.%d.%d",
864 str[0], str[1], str[2], str[3]);
868 proto_tree_add_text(address_tree, NullTVB, tmp_pos2,
869 str_len, "Value: %s",
870 bytes_to_str(str, str_len));
879 dissect_EncryptedData(char *title, ASN1_SCK *asn1p, frame_data *fd,
880 proto_tree *tree, int start_offset)
883 EncryptedData ::= SEQUENCE {
884 etype[0] INTEGER, -- EncryptionType
885 kvno[1] INTEGER OPTIONAL,
886 cipher[2] OCTET STRING -- ciphertext
889 proto_tree *encr_tree = NULL;
890 int offset = start_offset;
894 guint header_len, item_len, data_len;
897 proto_item *item = NULL;
904 KRB_SEQ_HEAD_DECODE_OR_DIE("encrypted data section");
907 item = proto_tree_add_text(tree, NullTVB, start_offset,
908 (offset - start_offset) + item_len,
909 "Encrypted Data: %s", title);
910 encr_tree = proto_item_add_subtree(item, ett_princ);
914 KRB_DECODE_CONTEXT_HEAD_OR_DIE("encryption type", 0);
915 KRB_DECODE_UINT32_OR_DIE("encr-type", val);
917 proto_tree_add_text(encr_tree, NullTVB, offset, length,
919 val_to_str(val, krb5_encryption_types,
920 "Unknown encryption type %#x"));
925 KRB_HEAD_DECODE_OR_DIE("kvno-wrap or cipher-wrap");
926 if (CHECK_CONTEXT_TYPE(1)) {
927 KRB_DECODE_UINT32_OR_DIE("kvno", val);
929 proto_tree_add_text(encr_tree, NullTVB, offset, length,
933 KRB_HEAD_DECODE_OR_DIE("cipher-wrap");
936 DIE_IF_NOT_CONTEXT_TYPE("cipher-wrap", 2);
937 KRB_DECODE_OCTET_STRING_OR_DIE("cipher", data, data_len, item_len);
940 proto_tree_add_text(encr_tree, NullTVB, offset, data_len,
941 "CipherText: %s", bytes_to_str(data, item_len));
949 dissect_Ticket(char *title, ASN1_SCK *asn1p, frame_data *fd, proto_tree *tree,
953 Ticket ::= [APPLICATION 1] SEQUENCE {
956 sname[2] PrincipalName,
957 enc-part[3] EncryptedData
960 proto_tree *ticket_tree = NULL;
961 int offset = start_offset;
965 guint header_len, item_len, total_len;
968 proto_item *item = NULL;
976 KRB_DECODE_APPLICATION_TAGGED_HEAD_OR_DIE("Ticket section", 1);
977 KRB_SEQ_HEAD_DECODE_OR_DIE("Ticket sequence");
978 total_len = item_len;
981 item = proto_tree_add_text(tree, NullTVB, start_offset,
982 (offset - start_offset) + item_len,
984 ticket_tree = proto_item_add_subtree(item, ett_ticket);
988 KRB_DECODE_CONTEXT_HEAD_OR_DIE("Ticket tkt-vno", KRB5_TKT_TKT_VNO);
989 KRB_DECODE_UINT32_OR_DIE("Ticket tkt-vno", val);
991 proto_tree_add_text(ticket_tree, NullTVB, offset, length,
998 KRB_DECODE_CONTEXT_HEAD_OR_DIE("Ticket realm", KRB5_TKT_REALM);
999 KRB_DECODE_GENERAL_STRING_OR_DIE("Ticket realm string", str, str_len, item_len);
1001 proto_tree_add_text(ticket_tree, NullTVB, offset, item_len,
1002 "Realm: %.*s", str_len, str);
1005 total_len -= item_len;
1007 /* server name (sname) */
1008 KRB_DECODE_CONTEXT_HEAD_OR_DIE("Ticket sname", KRB5_TKT_SNAME);
1009 item_len = dissect_PrincipalName("Service Name", asn1p, fd, ticket_tree,
1015 /* encrypted part */
1016 KRB_DECODE_CONTEXT_HEAD_OR_DIE("enc-part", KRB5_TKT_ENC_PART);
1017 offset = dissect_EncryptedData("Ticket data", asn1p, fd, ticket_tree,
1027 proto_register_kerberos(void) {
1029 static hf_register_info hf[] = {
1032 static gint *ett[] = {
1042 proto_kerberos = proto_register_protocol("Kerberos", "kerberos");
1044 proto_register_field_array(proto_kerberos, hf, array_length(hf));
1046 proto_register_subtree_array(ett, array_length(ett));
1050 proto_reg_handoff_kerberos(void)
1052 old_dissector_add("udp.port", UDP_PORT_KERBEROS, dissect_kerberos);
1053 old_dissector_add("tcp.port", TCP_PORT_KERBEROS, dissect_kerberos);
1058 MISC definitions from RFC1510:
1060 Realm ::= GeneralString
1062 KerberosTime ::= GeneralizedTime
1064 HostAddress ::= SEQUENCE {
1065 addr-type[0] INTEGER,
1066 address[1] OCTET STRING
1069 HostAddresses ::= SEQUENCE OF SEQUENCE {
1070 addr-type[0] INTEGER,
1071 address[1] OCTET STRING
1074 AuthorizationData ::= SEQUENCE OF SEQUENCE {
1076 ad-data[1] OCTET STRING
1078 APOptions ::= BIT STRING {
1085 TicketFlags ::= BIT STRING {
1100 KDCOptions ::= BIT STRING {
1114 enc-tkt-in-skey(28),
1120 LastReq ::= SEQUENCE OF SEQUENCE {
1122 lr-value[1] KerberosTime
1125 Ticket ::= [APPLICATION 1] SEQUENCE {
1128 sname[2] PrincipalName,
1129 enc-part[3] EncryptedData
1132 -- Encrypted part of ticket
1133 EncTicketPart ::= [APPLICATION 3] SEQUENCE {
1134 flags[0] TicketFlags,
1135 key[1] EncryptionKey,
1137 cname[3] PrincipalName,
1138 transited[4] TransitedEncoding,
1139 authtime[5] KerberosTime,
1140 starttime[6] KerberosTime OPTIONAL,
1141 endtime[7] KerberosTime,
1142 renew-till[8] KerberosTime OPTIONAL,
1143 caddr[9] HostAddresses OPTIONAL,
1144 authorization-data[10] AuthorizationData OPTIONAL
1147 -- encoded Transited field
1148 TransitedEncoding ::= SEQUENCE {
1149 tr-type[0] INTEGER, -- must be registered
1150 contents[1] OCTET STRING
1153 -- Unencrypted authenticator
1154 Authenticator ::= [APPLICATION 2] SEQUENCE {
1155 authenticator-vno[0] INTEGER,
1157 cname[2] PrincipalName,
1158 cksum[3] Checksum OPTIONAL,
1160 ctime[5] KerberosTime,
1161 subkey[6] EncryptionKey OPTIONAL,
1162 seq-number[7] INTEGER OPTIONAL,
1163 authorization-data[8] AuthorizationData OPTIONAL
1166 PA-DATA ::= SEQUENCE {
1167 padata-type[1] INTEGER,
1168 padata-value[2] OCTET STRING,
1169 -- might be encoded AP-REQ
1172 padata-type ::= PA-ENC-TIMESTAMP
1173 padata-value ::= EncryptedData -- PA-ENC-TS-ENC
1175 PA-ENC-TS-ENC ::= SEQUENCE {
1176 patimestamp[0] KerberosTime, -- client's time
1177 pausec[1] INTEGER OPTIONAL
1180 EncASRepPart ::= [APPLICATION 25[25]] EncKDCRepPart
1181 EncTGSRepPart ::= [APPLICATION 26] EncKDCRepPart
1183 EncKDCRepPart ::= SEQUENCE {
1184 key[0] EncryptionKey,
1185 last-req[1] LastReq,
1187 key-expiration[3] KerberosTime OPTIONAL,
1188 flags[4] TicketFlags,
1189 authtime[5] KerberosTime,
1190 starttime[6] KerberosTime OPTIONAL,
1191 endtime[7] KerberosTime,
1192 renew-till[8] KerberosTime OPTIONAL,
1194 sname[10] PrincipalName,
1195 caddr[11] HostAddresses OPTIONAL
1198 AP-REQ ::= [APPLICATION 14] SEQUENCE {
1200 msg-type[1] INTEGER,
1201 ap-options[2] APOptions,
1203 authenticator[4] EncryptedData
1206 APOptions ::= BIT STRING {
1212 AP-REP ::= [APPLICATION 15] SEQUENCE {
1214 msg-type[1] INTEGER,
1215 enc-part[2] EncryptedData
1218 EncAPRepPart ::= [APPLICATION 27] SEQUENCE {
1219 ctime[0] KerberosTime,
1221 subkey[2] EncryptionKey OPTIONAL,
1222 seq-number[3] INTEGER OPTIONAL
1225 KRB-SAFE ::= [APPLICATION 20] SEQUENCE {
1227 msg-type[1] INTEGER,
1228 safe-body[2] KRB-SAFE-BODY,
1232 KRB-SAFE-BODY ::= SEQUENCE {
1233 user-data[0] OCTET STRING,
1234 timestamp[1] KerberosTime OPTIONAL,
1235 usec[2] INTEGER OPTIONAL,
1236 seq-number[3] INTEGER OPTIONAL,
1237 s-address[4] HostAddress,
1238 r-address[5] HostAddress OPTIONAL
1241 KRB-PRIV ::= [APPLICATION 21] SEQUENCE {
1243 msg-type[1] INTEGER,
1244 enc-part[3] EncryptedData
1247 EncKrbPrivPart ::= [APPLICATION 28] SEQUENCE {
1248 user-data[0] OCTET STRING,
1249 timestamp[1] KerberosTime OPTIONAL,
1250 usec[2] INTEGER OPTIONAL,
1251 seq-number[3] INTEGER OPTIONAL,
1252 s-address[4] HostAddress, -- sender's addr
1253 r-address[5] HostAddress OPTIONAL
1257 KRB-CRED ::= [APPLICATION 22] SEQUENCE {
1259 msg-type[1] INTEGER, -- KRB_CRED
1260 tickets[2] SEQUENCE OF Ticket,
1261 enc-part[3] EncryptedData
1264 EncKrbCredPart ::= [APPLICATION 29] SEQUENCE {
1265 ticket-info[0] SEQUENCE OF KrbCredInfo,
1266 nonce[1] INTEGER OPTIONAL,
1267 timestamp[2] KerberosTime OPTIONAL,
1268 usec[3] INTEGER OPTIONAL,
1269 s-address[4] HostAddress OPTIONAL,
1270 r-address[5] HostAddress OPTIONAL
1273 KrbCredInfo ::= SEQUENCE {
1274 key[0] EncryptionKey,
1275 prealm[1] Realm OPTIONAL,
1276 pname[2] PrincipalName OPTIONAL,
1277 flags[3] TicketFlags OPTIONAL,
1278 authtime[4] KerberosTime OPTIONAL,
1279 starttime[5] KerberosTime OPTIONAL,
1280 endtime[6] KerberosTime OPTIONAL
1281 renew-till[7] KerberosTime OPTIONAL,
1282 srealm[8] Realm OPTIONAL,
1283 sname[9] PrincipalName OPTIONAL,
1284 caddr[10] HostAddresses OPTIONAL
1287 KRB-ERROR ::= [APPLICATION 30] SEQUENCE {
1289 msg-type[1] INTEGER,
1290 ctime[2] KerberosTime OPTIONAL,
1291 cusec[3] INTEGER OPTIONAL,
1292 stime[4] KerberosTime,
1294 error-code[6] INTEGER,
1295 crealm[7] Realm OPTIONAL,
1296 cname[8] PrincipalName OPTIONAL,
1297 realm[9] Realm, -- Correct realm
1298 sname[10] PrincipalName, -- Correct name
1299 e-text[11] GeneralString OPTIONAL,
1300 e-data[12] OCTET STRING OPTIONAL
1303 e-data This field contains additional data about the error for use
1304 by the application to help it recover from or handle the
1305 error. If the errorcode is KDC_ERR_PREAUTH_REQUIRED, then
1306 the e-data field will contain an encoding of a sequence of
1307 padata fields, each corresponding to an acceptable pre-
1308 authentication method and optionally containing data for
1311 METHOD-DATA ::= SEQUENCE of PA-DATA
1313 If the error-code is KRB_AP_ERR_METHOD, then the e-data field will
1314 contain an encoding of the following sequence:
1316 METHOD-DATA ::= SEQUENCE {
1317 method-type[0] INTEGER,
1318 method-data[1] OCTET STRING OPTIONAL
1321 EncryptionKey ::= SEQUENCE {
1323 keyvalue[1] OCTET STRING
1326 Checksum ::= SEQUENCE {
1327 cksumtype[0] INTEGER,
1328 checksum[1] OCTET STRING