2 * Routines for KINK packet disassembly
3 * It is referrenced draft-ietf-kink-kink-jp-04.txt,v 1.14 2003/02/10
5 * Copyright 2004, Takeshi Nakashima <T.Nakashima@jp.yokogawa.com>
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
34 #include <epan/packet.h>
35 #include <epan/asn1.h>
36 #include "packet-kerberos.h"
37 #include "packet-isakmp.h"
39 #define KINK_PORT 57203
41 #define KINK_ISAKMP_PAYLOAD_BASE 14
43 static int proto_kink = -1;
45 /* Argument for proto_tree_add_uint() */
46 static int hf_kink_type = -1;
47 static int hf_kink_length = -1;
48 static int hf_kink_transactionId = -1;
49 static int hf_kink_checkSumLength = -1;
50 static int hf_kink_A = -1;
51 static int hf_kink_reserved = -1;
52 static int hf_kink_checkSum = -1;
53 static int hf_kink_next_payload = -1;
55 /* Argument for making the subtree */
56 static gint ett_kink = -1;
57 /*static gint ett_kink_version = -1;*/
58 static gint ett_kink_payload = -1;
59 static gint ett_payload_kink_ap_req = -1;
60 static gint ett_payload_kink_ap_rep = -1;
61 static gint ett_payload_kink_krb_error = -1;
62 static gint ett_payload_kink_tgt_req = -1;
63 static gint ett_payload_kink_tgt_rep = -1;
64 static gint ett_payload_kink_isakmp = -1;
65 static gint ett_payload_kink_encrypt = -1;
66 static gint ett_payload_kink_error = -1;
67 static gint ett_payload_not_defined = -1;
68 static gint ett_decrypt_kink_encrypt = -1;
70 /* Define the kink type value */
71 #define KINK_TYPE_RESERVED 0
72 #define KINK_TYPE_CREATE 1
73 #define KINK_TYPE_DELETE 2
74 #define KINK_TYPE_REPLY 3
75 #define KINK_TYPE_GETTGT 4
76 #define KINK_TYPE_ACK 5
77 #define KINK_TYPE_STATUS 6
79 static const value_string kink_type_vals[]={
80 {KINK_TYPE_RESERVED,"RESERVED"},
81 {KINK_TYPE_CREATE,"CREATE"},
82 {KINK_TYPE_DELETE,"DELETE"},
83 {KINK_TYPE_REPLY,"REPLY"},
84 {KINK_TYPE_GETTGT,"GETTGT"},
85 {KINK_TYPE_ACK,"ACK"},
86 {KINK_TYPE_STATUS,"STATUS"},
90 /* Define the kink A value */
91 #define KINK_A_NOT_REQUEST_ACK 0
92 #define KINK_A_REQUEST_ACK 1
94 static const value_string kink_A_vals[]={
95 {KINK_A_NOT_REQUEST_ACK,"Not Request ACK"},
96 {KINK_A_REQUEST_ACK,"Request ACK"},
100 /* Define the kink payload */
102 #define KINK_AP_REQ KINK_ISAKMP_PAYLOAD_BASE+0
103 #define KINK_AP_REP KINK_ISAKMP_PAYLOAD_BASE+1
104 #define KINK_KRB_ERROR KINK_ISAKMP_PAYLOAD_BASE+2
105 #define KINK_TGT_REQ KINK_ISAKMP_PAYLOAD_BASE+3
106 #define KINK_TGT_REP KINK_ISAKMP_PAYLOAD_BASE+4
107 #define KINK_ISAKMP KINK_ISAKMP_PAYLOAD_BASE+5
108 #define KINK_ENCRYPT KINK_ISAKMP_PAYLOAD_BASE+6
109 #define KINK_ERROR KINK_ISAKMP_PAYLOAD_BASE+7
111 static const value_string kink_next_payload[]={
112 {KINK_DONE, "KINK_DONE"},
113 {KINK_AP_REQ, "KINK_AP_REQ"},
114 {KINK_AP_REP, "KINK_AP_REP"},
115 {KINK_KRB_ERROR, "KINK_KRB_ERROR"},
116 {KINK_TGT_REQ, "KINK_TGT_REQ"},
117 {KINK_TGT_REP, "KINK_TGT_REP"},
118 {KINK_ISAKMP, "KINK_ISAKMP"},
119 {KINK_ENCRYPT, "KINK_ENCRYPT"},
120 {KINK_ERROR, "KINK_ERROR"},
124 /* Define the magic number
125 * Using at the kink error
128 #define KINK_PROTOERR 1
129 #define KINK_INVDOI 2
130 #define KINK_INVMAJ 3
131 #define KINK_INVMIN 4
132 #define KINK_INTERR 5
133 #define KINK_BADQMVERS 6
134 #define BOTTOM_RESERVED 7
135 #define TOP_RESERVED 8191
136 #define BOTTOM_PRIVATE_USE 8192
137 #define TOP_PRIVATE_USE 16383
139 /* Using at the kink header */
141 #define VERSION_BIT_SHIFT 4
142 #define A_BIT_SHIFT 7
143 #define FROM_TYPE_TO_RESERVED 16
145 /* Using at the payload */
146 #define TO_PAYLOAD_LENGTH 2
148 #define KINK_KRB_ERROR_HEADER 4
149 #define FROM_NP_TO_PL 4
150 #define TO_REALM_NAME_LENGTH 4
151 #define KINK_TGT_REQ_HEADER 6
152 #define FRONT_TGT_REP_HEADER 6
153 #define PAYLOAD_HEADER 8
154 #define KINK_ERROR_LENGTH 8
157 /* define hexadecimal */
158 #define FRONT_FOUR_BIT 0xf0
159 #define SECOND_FOUR_BIT 0x0f
160 #define FRONT_ONE_BIT 0x80
161 #define SECOND_FIFTEEN_BIT 0x7fff
163 /* decrypt element */
164 static guint32 keytype;
166 static void control_payload(packet_info *pinfo, tvbuff_t *tvb, int offset, guint8 next_payload, proto_tree *kink_payload_tree);
167 static void dissect_payload_kink_ap_req(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
168 static void dissect_payload_kink_ap_rep(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
169 static void dissect_payload_kink_krb_error(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
170 static void dissect_payload_kink_tgt_req(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
171 static void dissect_payload_kink_tgt_rep(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
172 static void dissect_payload_kink_isakmp(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
173 static void dissect_payload_kink_encrypt(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
174 static void dissect_payload_kink_error(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
175 static void dissect_payload_kink_not_defined(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
177 static void dissect_decrypt_kink_encrypt(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree, int payload_length);
180 /* This function is dissecting the kink header. */
182 dissect_kink(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree){
183 proto_item *ti = NULL;
184 proto_tree *kink_tree = NULL;
186 guint8 major_version, minor_version, version;
190 guint8 value_a_and_front_reserved;
191 guint16 value_a_and_reserved;
193 guint16 value_reserved;
196 type = tvb_get_guint8(tvb,offset);
198 col_set_str(pinfo->cinfo, COL_PROTOCOL, "KINK");
200 /* It shows kink type by the type value. */
201 if(check_col(pinfo->cinfo, COL_INFO)){
202 col_add_str(pinfo->cinfo, COL_INFO, val_to_str(type, kink_type_vals, "unknown"));
204 /* Make the kink tree */
206 ti = proto_tree_add_item(tree, proto_kink, tvb, offset, -1, ENC_NA);
207 kink_tree = proto_item_add_subtree(ti, ett_kink);
210 proto_tree_add_uint(kink_tree, hf_kink_type, tvb, offset, 1, type);
213 /* This part is the version. Consider less than 1 octet value.
214 * Major version and minor version is 4bit. Front half of 1octet
215 * is major version, and second half of 1octet is minor version.
216 * The calculation of major version is shown below.
217 * The logical product of the value of 1octet and 0xf0 is performed.
218 * And It is performed 4bit right shift.
219 * Secondarily, the calculation of minor version is shown below.
220 * The logical product of the value of 1octet and 0x0f is performed.
222 version = tvb_get_guint8(tvb,offset);
223 major_version = (version & FRONT_FOUR_BIT) >> VERSION_BIT_SHIFT;
224 minor_version = version & SECOND_FOUR_BIT;
225 proto_tree_add_text(kink_tree, tvb, offset, 1, "version: %u.%u", major_version, minor_version);
228 proto_tree_add_item(kink_tree, hf_kink_length, tvb, offset, 2, ENC_BIG_ENDIAN);
231 doi = tvb_get_ntohl(tvb, offset);
234 proto_tree_add_text(kink_tree, tvb, offset, 4, "Domain Of Interpretation: %s (%u)", "IPsec", doi);
237 proto_tree_add_text(kink_tree, tvb, offset, 4, "Domain Of Interpretation: %s (%u)", "Not IPsec", doi);
241 proto_tree_add_item(kink_tree, hf_kink_transactionId, tvb, offset, 4, ENC_BIG_ENDIAN);
244 chsumlen = tvb_get_guint8(tvb, offset);
245 proto_tree_add_item(kink_tree, hf_kink_checkSumLength, tvb, offset, 1, ENC_BIG_ENDIAN);
248 next_payload = tvb_get_guint8(tvb, offset);
249 proto_tree_add_uint(kink_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
252 /* A is 1bit field. The caluculation of A is shown below.
253 * The logical product of 1octet value and 0x80 is performed.
254 * And It is performed 7bit right shift.
256 value_a_and_front_reserved = tvb_get_guint8(tvb, offset);
257 value_a = (value_a_and_front_reserved & FRONT_ONE_BIT) >> A_BIT_SHIFT;
258 proto_tree_add_uint(kink_tree, hf_kink_A, tvb, offset, 1, value_a);
260 /* The reserved field is 15bit.
261 * The logical product of 2octet value and 0x7fff is performed.
263 value_a_and_reserved = tvb_get_ntohs(tvb, offset);
264 value_reserved = value_a_and_reserved & SECOND_FIFTEEN_BIT;
265 proto_tree_add_uint(kink_tree, hf_kink_reserved, tvb, offset, 2, value_reserved);
268 proto_tree_add_item(kink_tree, hf_kink_checkSum, tvb, offset, chsumlen, ENC_NA);
270 /* This part consider the padding. Chsumlen don't contain the padding. */
271 if((chsumlen % PADDING) != 0){
272 chsumlen += (PADDING - (chsumlen % PADDING));
279 control_payload(pinfo, tvb, offset, next_payload, kink_tree);
283 /* This part call the dissect payload function by next_payload value.
284 * This function called by the respective function again.
287 control_payload(packet_info *pinfo, tvbuff_t *tvb, int offset, guint8 next_payload, proto_tree *kink_tree){
288 switch(next_payload){
292 dissect_payload_kink_ap_req(pinfo, tvb, offset, kink_tree);
295 dissect_payload_kink_ap_rep(pinfo, tvb, offset, kink_tree);
298 dissect_payload_kink_krb_error(pinfo, tvb, offset, kink_tree);
301 dissect_payload_kink_tgt_req(pinfo, tvb, offset, kink_tree);
304 dissect_payload_kink_tgt_rep(pinfo, tvb, offset, kink_tree);
307 dissect_payload_kink_isakmp(pinfo, tvb, offset, kink_tree);
310 dissect_payload_kink_encrypt(pinfo, tvb, offset, kink_tree);
313 dissect_payload_kink_error(pinfo, tvb, offset, kink_tree);
316 dissect_payload_kink_not_defined(pinfo, tvb, offset, kink_tree);
322 dissect_payload_kink_ap_req(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
323 proto_tree *payload_kink_ap_req_tree;
327 guint payload_length;
328 guint16 krb_ap_req_length;
329 time_t timer; /* For showing utc */
330 int start_payload_offset = 0; /* Keep begining of payload offset */
332 start_payload_offset = offset;
333 payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH);
335 /* Make the subtree. */
336 ti = proto_tree_add_text(tree, tvb, offset, payload_length, "KINK_AP_REQ");
337 payload_kink_ap_req_tree = proto_item_add_subtree(ti, ett_payload_kink_ap_req);
339 next_payload = tvb_get_guint8(tvb, offset);
340 proto_tree_add_uint(payload_kink_ap_req_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
343 reserved = tvb_get_guint8(tvb, offset);
344 proto_tree_add_text(payload_kink_ap_req_tree, tvb, offset, 1, "RESERVED: %u", reserved);
347 if(payload_length <= PAYLOAD_HEADER){
348 proto_tree_add_text(payload_kink_ap_req_tree, tvb, offset, 2, "This Payload Length is too small.: %u", payload_length);
351 proto_tree_add_text(payload_kink_ap_req_tree, tvb, offset, 2, "Payload Length: %u", payload_length);
355 /* Show time as UTC, not local time. */
356 timer = tvb_get_ntohl(tvb, offset);
357 proto_tree_add_text(payload_kink_ap_req_tree, tvb, offset, 4, "EPOCH: %s",
358 abs_time_secs_to_str(timer, ABSOLUTE_TIME_UTC, TRUE));
361 if(payload_length > PAYLOAD_HEADER){
364 krb_ap_req_length = payload_length - PAYLOAD_HEADER;
365 krb_tvb=tvb_new_subset(tvb, offset, (krb_ap_req_length>tvb_length_remaining(tvb, offset))?tvb_length_remaining(tvb, offset):krb_ap_req_length, krb_ap_req_length);
366 keytype=kerberos_output_keytype();
367 dissect_kerberos_main(krb_tvb, pinfo, payload_kink_ap_req_tree, FALSE, NULL);
368 offset += krb_ap_req_length;
371 /* This part consider padding the padding. Payload_length don't contain the padding. */
372 if(payload_length % PADDING != 0){
373 payload_length += (PADDING - (payload_length % PADDING));
375 offset = start_payload_offset + payload_length;
377 if(payload_length > 0) {
378 control_payload(pinfo, tvb, offset, next_payload, tree); /* Recur control_payload() */
384 dissect_payload_kink_ap_rep(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
385 proto_tree *payload_kink_ap_rep_tree;
389 guint payload_length;
390 guint16 krb_ap_rep_length;
392 int start_payload_offset = 0; /* Keep begining of payload offset */
394 payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH);
395 start_payload_offset = offset;
397 /* Make the subtree */
398 ti = proto_tree_add_text(tree, tvb, offset, payload_length,"KINK_AP_REP");
399 payload_kink_ap_rep_tree = proto_item_add_subtree(ti, ett_payload_kink_ap_rep);
401 next_payload = tvb_get_guint8(tvb, offset);
402 proto_tree_add_uint(payload_kink_ap_rep_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
405 reserved = tvb_get_guint8(tvb, offset);
406 proto_tree_add_text(payload_kink_ap_rep_tree, tvb, offset, 1, "RESERVED: %u", reserved);
409 if(payload_length <= PAYLOAD_HEADER){
410 proto_tree_add_text(payload_kink_ap_rep_tree, tvb, offset, 2, "This Payload Length is too small.: %u", payload_length);
413 proto_tree_add_text(payload_kink_ap_rep_tree, tvb, offset, 2, "Payload Length: %u", payload_length);
417 /* Show time as UTC, not local time. */
418 timer = tvb_get_ntohl(tvb, offset);
419 proto_tree_add_text(payload_kink_ap_rep_tree, tvb, offset, 4, "EPOCH: %s",
420 abs_time_secs_to_str(timer, ABSOLUTE_TIME_UTC, TRUE));
423 if(payload_length > PAYLOAD_HEADER){
426 krb_ap_rep_length = payload_length - PAYLOAD_HEADER;
427 krb_tvb=tvb_new_subset(tvb, offset, (krb_ap_rep_length>tvb_length_remaining(tvb, offset))?tvb_length_remaining(tvb, offset):krb_ap_rep_length, krb_ap_rep_length);
428 keytype=kerberos_output_keytype();
429 dissect_kerberos_main(krb_tvb, pinfo, payload_kink_ap_rep_tree, FALSE, NULL);
431 offset += krb_ap_rep_length;
434 /* This part consider the padding. Payload_length don't contain the padding. */
435 if(payload_length % PADDING != 0){
436 payload_length += (PADDING - (payload_length % PADDING));
438 offset = start_payload_offset + payload_length;
440 if(payload_length > 0) {
441 control_payload(pinfo, tvb, offset, next_payload, tree); /* Recur control_payload() */
446 dissect_payload_kink_krb_error(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
447 proto_tree *payload_kink_krb_error_tree;
451 guint payload_length;
452 guint16 krb_error_length;
453 int start_payload_offset = 0; /* Keep the begining of the payload offset */
455 payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH);
456 start_payload_offset = offset;
458 /* Make the subtree */
459 ti = proto_tree_add_text(tree, tvb, offset, payload_length,"KINK_KRB_ERROR");
460 payload_kink_krb_error_tree = proto_item_add_subtree(ti, ett_payload_kink_krb_error);
462 next_payload = tvb_get_guint8(tvb, offset);
463 proto_tree_add_uint(payload_kink_krb_error_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
466 reserved = tvb_get_guint8(tvb, offset);
467 proto_tree_add_text(payload_kink_krb_error_tree, tvb, offset, 1, "RESERVED: %u", reserved);
470 if(payload_length <= KINK_KRB_ERROR_HEADER){
471 proto_tree_add_text(payload_kink_krb_error_tree, tvb, offset, 2, "This Payload Length is too small.: %u", payload_length);
474 proto_tree_add_text(payload_kink_krb_error_tree, tvb, offset, 2, "Payload Length: %u", payload_length);
478 if(payload_length > KINK_KRB_ERROR_HEADER){
481 krb_error_length = payload_length - KINK_KRB_ERROR_HEADER;
482 krb_tvb=tvb_new_subset(tvb, offset, (krb_error_length>tvb_length_remaining(tvb, offset))?tvb_length_remaining(tvb, offset):krb_error_length, krb_error_length);
484 dissect_kerberos_main(krb_tvb, pinfo, payload_kink_krb_error_tree, FALSE, NULL);
485 offset += krb_error_length;
488 /* This part consider the padding. Payload_length don't contain the padding. */
489 if(payload_length % PADDING != 0){
490 payload_length += (PADDING - (payload_length % PADDING));
492 offset = start_payload_offset + payload_length;
494 if(payload_length > 0) {
495 control_payload(pinfo, tvb, offset, next_payload, tree); /* Recur control_payload() */
500 dissect_payload_kink_tgt_req(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
501 proto_tree *payload_kink_tgt_req_tree;
505 guint payload_length;
506 guint16 realm_name_length;
507 int start_payload_offset = 0; /* Keep the begining of the payload offset */
509 payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH);
510 realm_name_length = tvb_get_ntohs(tvb, offset + TO_REALM_NAME_LENGTH);
511 start_payload_offset = offset;
513 /* Make the subtree */
514 ti = proto_tree_add_text(tree, tvb, offset, payload_length,"KINK_TGT_REQ");
515 payload_kink_tgt_req_tree = proto_item_add_subtree(ti, ett_payload_kink_tgt_req);
517 next_payload = tvb_get_guint8(tvb, offset);
518 proto_tree_add_uint(payload_kink_tgt_req_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
521 reserved = tvb_get_guint8(tvb, offset);
522 proto_tree_add_text(payload_kink_tgt_req_tree, tvb, offset, 1, "RESERVED: %u", reserved);
525 proto_tree_add_text(payload_kink_tgt_req_tree, tvb, offset, 2, "Payload Length: %u", payload_length);
528 proto_tree_add_text(payload_kink_tgt_req_tree, tvb, offset, 2, "RealmNameLength: %u", realm_name_length);
531 proto_tree_add_text(payload_kink_tgt_req_tree, tvb, offset, realm_name_length, "RealmName: %s",
532 tvb_format_text(tvb, offset, realm_name_length));
533 offset += realm_name_length;
535 /* This part consider the padding. Payload_length don't contain the padding. */
536 if(payload_length % PADDING != 0){
537 payload_length += (PADDING - (payload_length % PADDING));
539 offset = start_payload_offset + payload_length;
541 if(payload_length > 0) {
542 control_payload(pinfo, tvb, offset, next_payload, tree); /* Recur control_payload() */
547 dissect_payload_kink_tgt_rep(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
548 proto_tree *payload_kink_tgt_rep_tree;
552 guint payload_length;
553 guint princ_name_length;
555 int start_payload_offset = 0; /* Keep the begining of the payload offset */
557 payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH);
558 start_payload_offset = offset;
560 /* Make the subtree */
561 ti = proto_tree_add_text(tree, tvb, offset, payload_length,"KINK_TGT_REP");
562 payload_kink_tgt_rep_tree = proto_item_add_subtree(ti, ett_payload_kink_tgt_rep);
564 next_payload = tvb_get_guint8(tvb, offset);
565 proto_tree_add_uint(payload_kink_tgt_rep_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
568 reserved = tvb_get_guint8(tvb, offset);
569 proto_tree_add_text(payload_kink_tgt_rep_tree, tvb, offset, 1, "RESERVED: %u", reserved);
572 proto_tree_add_text(payload_kink_tgt_rep_tree, tvb, offset, 2, "Payload Length: %u", payload_length);
575 princ_name_length = tvb_get_ntohs(tvb, offset);
576 proto_tree_add_text(payload_kink_tgt_rep_tree, tvb, offset, 2, "PrincNameLength: %u", princ_name_length);
579 proto_tree_add_text(payload_kink_tgt_rep_tree, tvb, offset, princ_name_length, "PrincName: %s", tvb_format_text(tvb, offset, princ_name_length));
581 /* This part consider the padding. Princ_name_length don't contain the padding. */
582 if((princ_name_length + FRONT_TGT_REP_HEADER) % PADDING != 0){
583 offset += (princ_name_length + PADDING - ((princ_name_length + FRONT_TGT_REP_HEADER) % PADDING));
586 offset += princ_name_length;
589 tgt_length = tvb_get_ntohs(tvb,offset);
591 proto_tree_add_text(payload_kink_tgt_rep_tree, tvb, offset, 2, "TGTlength: %u", tgt_length);
594 proto_tree_add_text(payload_kink_tgt_rep_tree, tvb, offset, tgt_length, "TGT: %s", tvb_format_text(tvb, offset, tgt_length));
595 offset += tgt_length;
597 /* This part consider the padding. Payload_length don't contain the padding. */
598 if(payload_length % PADDING!=0){
599 payload_length += (PADDING - (payload_length % PADDING));
601 offset = start_payload_offset + payload_length;
603 if(payload_length > 0) {
604 control_payload(pinfo, tvb, offset, next_payload, tree); /* Recur control_payload() */
609 dissect_payload_kink_isakmp(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
610 proto_tree *payload_kink_isakmp_tree;
614 guint payload_length,isakmp_length;
615 int length, reported_length;
616 guint8 inner_next_pload;
617 guint8 qm, qmmaj, qmmin;
619 int start_payload_offset = 0; /* Keep the begining of the payload offset */
620 tvbuff_t *isakmp_tvb;
622 payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH);
623 start_payload_offset = offset;
625 /* Make the subtree. */
626 ti = proto_tree_add_text(tree, tvb, offset, payload_length,"KINK_ISAKMP");
627 payload_kink_isakmp_tree = proto_item_add_subtree(ti, ett_payload_kink_isakmp);
629 next_payload = tvb_get_guint8(tvb, offset);
630 proto_tree_add_uint(payload_kink_isakmp_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
633 reserved = tvb_get_guint8(tvb, offset);
634 proto_tree_add_text(payload_kink_isakmp_tree, tvb, offset, 1, "RESERVED: %u", reserved);
637 if(payload_length <= PAYLOAD_HEADER){
638 proto_tree_add_text(payload_kink_isakmp_tree, tvb, offset, 2, "This Payload Length is too small.: %u", payload_length);
641 proto_tree_add_text(payload_kink_isakmp_tree, tvb, offset, 2, "Payload Length: %u", payload_length);
645 inner_next_pload = tvb_get_guint8(tvb, offset);
646 proto_tree_add_text(payload_kink_isakmp_tree, tvb, offset, 1, "InnerNextPload: %u", inner_next_pload);
649 /* The qmmaj is first half 4bit field of the octet. Therefore, the logical product
650 * of the 1octet value and 0xf0 is performed, and performed 4bit right shift.
651 * The qmmin is second half 4bit field of the octet. Therefore, the logical product
652 * of the 1octet value and 0x0f is performed.
654 qm = tvb_get_guint8(tvb,offset);
655 qmmaj = (qm & FRONT_FOUR_BIT) >> VERSION_BIT_SHIFT;
656 qmmin = qm & SECOND_FOUR_BIT;
658 proto_tree_add_text(payload_kink_isakmp_tree, tvb, offset, 1, "QMVersion: %u.%u", qmmaj, qmmin);
661 reserved2 = tvb_get_ntohs(tvb, offset);
662 proto_tree_add_text(payload_kink_isakmp_tree, tvb, offset, 2, "RESERVED: %u", reserved2);
665 if(payload_length > PAYLOAD_HEADER){
666 isakmp_length = payload_length - PAYLOAD_HEADER;
667 length = tvb_length_remaining(tvb, offset);
668 if (length > (int)isakmp_length)
669 length = isakmp_length;
670 reported_length = tvb_reported_length_remaining(tvb, offset);
671 if (reported_length > (int)isakmp_length)
672 reported_length = isakmp_length;
673 isakmp_tvb = tvb_new_subset(tvb, offset, length, reported_length);
674 isakmp_dissect_payloads(isakmp_tvb, payload_kink_isakmp_tree, 1, inner_next_pload, 0, isakmp_length, pinfo);
677 /* This part consider the padding. Payload_length don't contain the padding. */
678 if(payload_length % PADDING != 0){
679 payload_length += (PADDING - (payload_length % PADDING));
681 offset = start_payload_offset + payload_length;
683 if(payload_length > 0) {
684 control_payload(pinfo, tvb, offset, next_payload, tree); /* Recur control_payload() */
689 dissect_payload_kink_encrypt(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
690 proto_tree *payload_kink_encrypt_tree;
694 guint payload_length;
698 guint8 inner_next_pload;
700 guint16 inner_payload_length;
701 int start_payload_offset = 0; /* Keep the begining of the payload offset */
703 payload_length = tvb_get_ntohs(tvb,offset + TO_PAYLOAD_LENGTH);
704 start_payload_offset = offset;
707 encrypt_length = payload_length - FROM_NP_TO_PL;
709 /* Make the subtree */
710 ti = proto_tree_add_text(tree, tvb, offset, payload_length,"KINK_ENCRYPT");
711 payload_kink_encrypt_tree = proto_item_add_subtree(ti, ett_payload_kink_encrypt);
713 next_payload = tvb_get_guint8(tvb, offset);
714 proto_tree_add_uint(payload_kink_encrypt_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
717 reserved = tvb_get_guint8(tvb, offset);
718 proto_tree_add_text(payload_kink_encrypt_tree, tvb, offset, 1, "RESERVED: %u", reserved);
721 if(payload_length <= PAYLOAD_HEADER){
722 proto_tree_add_text(payload_kink_encrypt_tree, tvb, offset, 2, "This Payload Length is too small.: %u", payload_length);
725 proto_tree_add_text(payload_kink_encrypt_tree, tvb, offset, 2, "Payload Length: %u", payload_length);
729 /* decrypt kink encrypt */
734 guint8 *plaintext=NULL;
736 next_tvb=tvb_new_subset(tvb, offset, MIN(tvb_length_remaining(tvb, offset), encrypt_length), encrypt_length);
737 plaintext=decrypt_krb5_data(tree, pinfo, 0, next_tvb, keytype, NULL);
739 next_tvb=tvb_new_child_real_data(tvb, plaintext, encrypt_length, encrypt_length);
740 tvb_set_free_cb(next_tvb, g_free);
741 add_new_data_source(pinfo, next_tvb, "decrypted kink encrypt");
742 dissect_decrypt_kink_encrypt(pinfo, next_tvb, tree, encrypt_length);
747 inner_next_pload = tvb_get_guint8(tvb, offset);
748 proto_tree_add_text(payload_kink_encrypt_tree, tvb, offset, 1, "InnerNextPload: %u", inner_next_pload);
751 reserved2 = 65536*tvb_get_guint8(tvb, offset) + 256*tvb_get_guint8(tvb, offset+1) + tvb_get_guint8(tvb, offset+2);
752 proto_tree_add_text(payload_kink_encrypt_tree, tvb, offset, 3, "RESERVED: %u", reserved2);
755 if(payload_length > PAYLOAD_HEADER){
756 inner_payload_length = payload_length - PAYLOAD_HEADER;
757 proto_tree_add_text(payload_kink_encrypt_tree, tvb, offset, inner_payload_length, "Payload");
758 offset += inner_payload_length;
761 /* This part consider the padding. Payload_length don't contain the padding. */
762 if(payload_length % PADDING !=0){
763 payload_length += (PADDING - (payload_length % PADDING));
765 offset = start_payload_offset + payload_length;
767 if(payload_length > 0) {
768 control_payload(pinfo, tvb, offset, next_payload, tree); /* Recur control_payload() */
774 dissect_decrypt_kink_encrypt(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree, int payload_length){
776 proto_tree *decrypt_kink_encrypt_tree;
782 ti = proto_tree_add_text(tree, tvb, offset, payload_length, "decrypted data");
783 decrypt_kink_encrypt_tree = proto_item_add_subtree(ti, ett_decrypt_kink_encrypt);
785 next_payload = tvb_get_guint8(tvb, offset);
787 proto_tree_add_uint(decrypt_kink_encrypt_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
790 reserved = 65536*tvb_get_guint8(tvb, offset) + 256*tvb_get_guint8(tvb, offset+1) + tvb_get_guint8(tvb, offset+2);
791 proto_tree_add_text(decrypt_kink_encrypt_tree, tvb, offset, 3, "RESERVED: %u", reserved);
794 control_payload(pinfo, tvb, offset, next_payload, decrypt_kink_encrypt_tree);
799 dissect_payload_kink_error(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
800 proto_tree *payload_kink_error_tree;
804 guint16 payload_length;
806 int start_payload_offset = 0; /* Keep the begining of the payload offset */
807 const char *char_error_code[] = {
817 payload_length = tvb_get_ntohs(tvb,offset + TO_PAYLOAD_LENGTH);
818 start_payload_offset = offset;
820 /* Make the subtree */
821 ti = proto_tree_add_text(tree, tvb, offset, payload_length,"KINK_ERROR");
822 payload_kink_error_tree = proto_item_add_subtree(ti, ett_payload_kink_error);
824 next_payload = tvb_get_guint8(tvb, offset);
825 proto_tree_add_uint(payload_kink_error_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
828 reserved = tvb_get_guint8(tvb,offset);
829 proto_tree_add_text(payload_kink_error_tree, tvb, offset, 1, "RESERVED: %u", reserved);
832 if(payload_length != KINK_ERROR_LENGTH){
833 proto_tree_add_text(payload_kink_error_tree, tvb, offset, 2, "This Payload Length is mismatch.: %u", payload_length);
836 proto_tree_add_text(payload_kink_error_tree, tvb, offset, 2, "Payload Length: %u", payload_length);
840 error_code = tvb_get_ntohl(tvb, offset);
842 /* Choosed the error code by erro_code */
851 proto_tree_add_text(payload_kink_error_tree, tvb, offset, 4, "ErrorCode: %s (%u)", char_error_code[error_code], error_code);
854 if(BOTTOM_RESERVED <= error_code && TOP_RESERVED >= error_code){
855 proto_tree_add_text(payload_kink_error_tree, tvb, offset, 4, "ErrorCode: %s (%u)", "RESERVED", error_code);
857 else if(BOTTOM_PRIVATE_USE <= error_code && TOP_PRIVATE_USE >= error_code){
858 proto_tree_add_text(payload_kink_error_tree, tvb, offset, 4, "ErrorCode: %s (%u)", "PRIVATE USE", error_code);
861 proto_tree_add_text(payload_kink_error_tree, tvb, offset, 4, "ErrorCode: %s (%u)", "This Error Code is not Defined.", error_code);
867 offset = start_payload_offset + KINK_ERROR_LENGTH;
868 control_payload(pinfo, tvb, offset, next_payload, tree); /* Recur control_payload() */
872 dissect_payload_kink_not_defined(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
873 proto_tree *payload_kink_not_defined_tree;
876 guint payload_length;
878 int start_payload_offset = 0; /* Keep the begining of the payload offset */
880 start_payload_offset = offset;
881 payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH);
883 /* Make the subtree */
884 ti = proto_tree_add_text(tree, tvb, offset, payload_length, "UNKNOWN PAYLOAD");
885 payload_kink_not_defined_tree = proto_item_add_subtree(ti, ett_payload_not_defined);
887 next_payload = tvb_get_guint8(tvb, offset);
888 proto_tree_add_uint(payload_kink_not_defined_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
891 reserved = tvb_get_guint8(tvb, offset);
892 proto_tree_add_text(payload_kink_not_defined_tree, tvb, offset, 1, "RESERVED: %u", reserved);
895 proto_tree_add_text(payload_kink_not_defined_tree, tvb, offset, 2, "Payload Length: %u", payload_length);
898 /* This part consider the padding. Payload_length don't contain the padding. */
899 if(payload_length % PADDING != 0){
900 payload_length += (PADDING - (payload_length % PADDING));
902 offset = start_payload_offset + payload_length;
904 /* XXX - prevent an endless loop if payload_length is 0, don't know the correct way to handle this! */
905 if(payload_length > 0) {
906 control_payload(pinfo, tvb, offset, next_payload, tree);
912 proto_register_kink(void) {
914 static hf_register_info hf[] = {
916 { "Type", "kink.type",
917 FT_UINT8, BASE_DEC, VALS(kink_type_vals), 0x0,
918 "the type of the kink", HFILL }},
920 { "Length", "kink.length",
921 FT_UINT16, BASE_DEC, NULL, 0x0,
922 "the length of the kink length", HFILL }},
923 { &hf_kink_transactionId,
924 { "Transaction ID", "kink.transactionId",
925 FT_UINT32, BASE_DEC, NULL, 0x0,
926 "the transactionID of kink", HFILL }},
927 { &hf_kink_checkSumLength,
928 { "Checksum Length", "kink.checkSumLength",
929 FT_UINT8, BASE_DEC, NULL, 0x0,
930 "the check sum length of kink", HFILL }},
933 FT_UINT8, BASE_DEC, VALS(kink_A_vals), 0x0,
934 "the A of kink", HFILL }},
936 { "Reserved", "kink.reserved",
937 FT_UINT16, BASE_DEC, NULL, 0x0,
938 "the reserved of kink", HFILL }},
940 { "Checksum", "kink.checkSum",
941 FT_BYTES, BASE_NONE, NULL, 0x0,
942 "the checkSum of kink", HFILL }},
943 { &hf_kink_next_payload,
944 { "Next Payload", "kink.nextPayload",
945 FT_UINT8, BASE_DEC, VALS(kink_next_payload), 0x0,
946 "the next payload of kink", HFILL }}
950 /* Argument for making the subtree. */
951 static gint *ett[] = {
953 /* &ett_kink_version, */
955 &ett_payload_kink_ap_req,
956 &ett_payload_kink_ap_rep,
957 &ett_payload_kink_krb_error,
958 &ett_payload_kink_tgt_req,
959 &ett_payload_kink_tgt_rep,
960 &ett_payload_kink_isakmp,
961 &ett_payload_kink_encrypt,
962 &ett_payload_kink_error,
963 &ett_payload_not_defined,
964 &ett_decrypt_kink_encrypt,
968 proto_kink = proto_register_protocol("Kerberized Internet Negotiation of Key", "KINK", "kink");
969 proto_register_field_array(proto_kink, hf, array_length(hf));
970 proto_register_subtree_array(ett, array_length(ett));
974 void proto_reg_handoff_kink(void) {
976 dissector_handle_t kink_handle = NULL;
978 kink_handle = create_dissector_handle(dissect_kink, proto_kink);
980 dissector_add_uint("udp.port", KINK_PORT, kink_handle);