2 * Routines for KINK packet disassembly
3 * It is referenced draft-ietf-kink-kink-jp-04.txt,v 1.14 2003/02/10
5 * Copyright 2004, Takeshi Nakashima <T.Nakashima@jp.yokogawa.com>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * SPDX-License-Identifier: GPL-2.0-or-later
17 #include <epan/packet.h>
18 #include <epan/expert.h>
19 #include <epan/asn1.h>
20 #include "packet-kerberos.h"
21 #include "packet-isakmp.h"
23 void proto_register_kink(void);
24 void proto_reg_handoff_kink(void);
26 #define KINK_PORT 57203 /* Not IANA registered */
28 #define KINK_ISAKMP_PAYLOAD_BASE 14
30 static int proto_kink = -1;
32 /* Argument for proto_tree_add_uint() */
33 static int hf_kink_type = -1;
34 static int hf_kink_length = -1;
35 static int hf_kink_transactionId = -1;
36 static int hf_kink_checkSumLength = -1;
37 static int hf_kink_A = -1;
38 static int hf_kink_version = -1;
39 static int hf_kink_domain_of_interpretation = -1;
40 static int hf_kink_qmversion = -1;
41 static int hf_kink_error_code = -1;
42 static int hf_kink_reserved8 = -1;
43 static int hf_kink_reserved15 = -1;
44 static int hf_kink_reserved16 = -1;
45 static int hf_kink_reserved24 = -1;
46 static int hf_kink_checkSum = -1;
47 static int hf_kink_next_payload = -1;
48 static int hf_kink_payload_length = -1;
49 static int hf_kink_epoch = -1;
50 static int hf_kink_inner_next_pload = -1;
51 static int hf_kink_realm_name_length = -1;
52 static int hf_kink_realm_name = -1;
53 static int hf_kink_princ_name_length = -1;
54 static int hf_kink_princ_name = -1;
55 static int hf_kink_tgt_length = -1;
56 static int hf_kink_tgt = -1;
57 static int hf_kink_payload = -1;
59 /* Argument for making the subtree */
60 static gint ett_kink = -1;
61 /*static gint ett_kink_version = -1;*/
62 static gint ett_kink_payload = -1;
63 static gint ett_payload_kink_ap_req = -1;
64 static gint ett_payload_kink_ap_rep = -1;
65 static gint ett_payload_kink_krb_error = -1;
66 static gint ett_payload_kink_tgt_req = -1;
67 static gint ett_payload_kink_tgt_rep = -1;
68 static gint ett_payload_kink_isakmp = -1;
69 static gint ett_payload_kink_encrypt = -1;
70 static gint ett_payload_kink_error = -1;
71 static gint ett_payload_not_defined = -1;
72 static gint ett_decrypt_kink_encrypt = -1;
74 static expert_field ei_kink_payload_length_small = EI_INIT;
75 static expert_field ei_kink_payload_length_mismatch = EI_INIT;
78 /* Define the kink type value */
79 #define KINK_TYPE_RESERVED 0
80 #define KINK_TYPE_CREATE 1
81 #define KINK_TYPE_DELETE 2
82 #define KINK_TYPE_REPLY 3
83 #define KINK_TYPE_GETTGT 4
84 #define KINK_TYPE_ACK 5
85 #define KINK_TYPE_STATUS 6
87 static const value_string kink_type_vals[]={
88 {KINK_TYPE_RESERVED,"RESERVED"},
89 {KINK_TYPE_CREATE,"CREATE"},
90 {KINK_TYPE_DELETE,"DELETE"},
91 {KINK_TYPE_REPLY,"REPLY"},
92 {KINK_TYPE_GETTGT,"GETTGT"},
93 {KINK_TYPE_ACK,"ACK"},
94 {KINK_TYPE_STATUS,"STATUS"},
98 /* Define the kink A value */
99 #define KINK_A_NOT_REQUEST_ACK 0
100 #define KINK_A_REQUEST_ACK 1
102 static const value_string kink_A_vals[]={
103 {KINK_A_NOT_REQUEST_ACK,"Not Request ACK"},
104 {KINK_A_REQUEST_ACK,"Request ACK"},
108 /* Define the kink payload */
110 #define KINK_AP_REQ KINK_ISAKMP_PAYLOAD_BASE+0
111 #define KINK_AP_REP KINK_ISAKMP_PAYLOAD_BASE+1
112 #define KINK_KRB_ERROR KINK_ISAKMP_PAYLOAD_BASE+2
113 #define KINK_TGT_REQ KINK_ISAKMP_PAYLOAD_BASE+3
114 #define KINK_TGT_REP KINK_ISAKMP_PAYLOAD_BASE+4
115 #define KINK_ISAKMP KINK_ISAKMP_PAYLOAD_BASE+5
116 #define KINK_ENCRYPT KINK_ISAKMP_PAYLOAD_BASE+6
117 #define KINK_ERROR KINK_ISAKMP_PAYLOAD_BASE+7
119 static const value_string kink_next_payload[]={
120 {KINK_DONE, "KINK_DONE"},
121 {KINK_AP_REQ, "KINK_AP_REQ"},
122 {KINK_AP_REP, "KINK_AP_REP"},
123 {KINK_KRB_ERROR, "KINK_KRB_ERROR"},
124 {KINK_TGT_REQ, "KINK_TGT_REQ"},
125 {KINK_TGT_REP, "KINK_TGT_REP"},
126 {KINK_ISAKMP, "KINK_ISAKMP"},
127 {KINK_ENCRYPT, "KINK_ENCRYPT"},
128 {KINK_ERROR, "KINK_ERROR"},
132 /* Define the magic number
133 * Using at the kink error
136 #define KINK_PROTOERR 1
137 #define KINK_INVDOI 2
138 #define KINK_INVMAJ 3
139 #define KINK_INVMIN 4
140 #define KINK_INTERR 5
141 #define KINK_BADQMVERS 6
142 #define BOTTOM_RESERVED 7
143 #define TOP_RESERVED 8191
144 #define BOTTOM_PRIVATE_USE 8192
145 #define TOP_PRIVATE_USE 16383
147 /* Using at the kink header */
149 #define VERSION_BIT_SHIFT 4
150 #define A_BIT_SHIFT 7
151 #define FROM_TYPE_TO_RESERVED 16
153 /* Using at the payload */
154 #define TO_PAYLOAD_LENGTH 2
156 #define KINK_KRB_ERROR_HEADER 4
157 #define FROM_NP_TO_PL 4
158 #define TO_REALM_NAME_LENGTH 4
159 #define KINK_TGT_REQ_HEADER 6
160 #define FRONT_TGT_REP_HEADER 6
161 #define PAYLOAD_HEADER 8
162 #define KINK_ERROR_LENGTH 8
165 /* define hexadecimal */
166 #define FRONT_FOUR_BIT 0xf0
167 #define SECOND_FOUR_BIT 0x0f
168 #define FRONT_ONE_BIT 0x80
169 #define SECOND_FIFTEEN_BIT 0x7fff
171 /* decrypt element */
172 static guint32 keytype;
174 static void control_payload(packet_info *pinfo, tvbuff_t *tvb, int offset, guint8 next_payload, proto_tree *kink_payload_tree);
175 static void dissect_payload_kink_ap_req(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
176 static void dissect_payload_kink_ap_rep(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
177 static void dissect_payload_kink_krb_error(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
178 static void dissect_payload_kink_tgt_req(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
179 static void dissect_payload_kink_tgt_rep(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
180 static void dissect_payload_kink_isakmp(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
181 static void dissect_payload_kink_encrypt(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
182 static void dissect_payload_kink_error(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
183 static void dissect_payload_kink_not_defined(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
185 static void dissect_decrypt_kink_encrypt(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree, int payload_length);
188 /* This function is dissecting the kink header. */
190 dissect_kink(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_){
191 proto_item *ti = NULL;
192 proto_tree *kink_tree = NULL;
197 guint8 value_a_and_front_reserved;
201 type = tvb_get_guint8(tvb,offset);
203 col_set_str(pinfo->cinfo, COL_PROTOCOL, "KINK");
205 /* It shows kink type by the type value. */
206 col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(type, kink_type_vals, "unknown"));
208 /* Make the kink tree */
209 ti = proto_tree_add_item(tree, proto_kink, tvb, offset, -1, ENC_NA);
210 kink_tree = proto_item_add_subtree(ti, ett_kink);
212 proto_tree_add_uint(kink_tree, hf_kink_type, tvb, offset, 1, type);
215 proto_tree_add_item(kink_tree, hf_kink_version, tvb, offset, 1, ENC_BIG_ENDIAN);
218 proto_tree_add_item(kink_tree, hf_kink_length, tvb, offset, 2, ENC_BIG_ENDIAN);
221 doi = tvb_get_ntohl(tvb, offset);
224 proto_tree_add_uint_format_value(kink_tree, hf_kink_domain_of_interpretation, tvb, offset, 4, doi, "IPsec (%u)", doi);
227 proto_tree_add_uint_format_value(kink_tree, hf_kink_domain_of_interpretation, tvb, offset, 4, doi, "Not IPsec (%u)", doi);
231 proto_tree_add_item(kink_tree, hf_kink_transactionId, tvb, offset, 4, ENC_BIG_ENDIAN);
234 chsumlen = tvb_get_guint8(tvb, offset);
235 proto_tree_add_item(kink_tree, hf_kink_checkSumLength, tvb, offset, 1, ENC_BIG_ENDIAN);
238 next_payload = tvb_get_guint8(tvb, offset);
239 proto_tree_add_uint(kink_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
242 /* A is 1bit field. The calculation of A is shown below.
243 * The logical product of 1octet value and 0x80 is performed.
244 * And It is performed 7bit right shift.
246 value_a_and_front_reserved = tvb_get_guint8(tvb, offset);
247 value_a = (value_a_and_front_reserved & FRONT_ONE_BIT) >> A_BIT_SHIFT;
248 proto_tree_add_uint(kink_tree, hf_kink_A, tvb, offset, 1, value_a);
250 /* The reserved field is 15bit.
251 * The logical product of 2octet value and 0x7fff is performed.
253 proto_tree_add_item(kink_tree, hf_kink_reserved15, tvb, offset, 2, ENC_BIG_ENDIAN);
256 proto_tree_add_item(kink_tree, hf_kink_checkSum, tvb, offset, chsumlen, ENC_NA);
258 /* This part consider the padding. Chsumlen don't contain the padding. */
259 if((chsumlen % PADDING) != 0){
260 chsumlen += (PADDING - (chsumlen % PADDING));
267 control_payload(pinfo, tvb, offset, next_payload, kink_tree);
269 return tvb_captured_length(tvb);
272 /* This part call the dissect payload function by next_payload value.
273 * This function called by the respective function again.
276 control_payload(packet_info *pinfo, tvbuff_t *tvb, int offset, guint8 next_payload, proto_tree *kink_tree){
277 switch(next_payload){
281 dissect_payload_kink_ap_req(pinfo, tvb, offset, kink_tree);
284 dissect_payload_kink_ap_rep(pinfo, tvb, offset, kink_tree);
287 dissect_payload_kink_krb_error(pinfo, tvb, offset, kink_tree);
290 dissect_payload_kink_tgt_req(pinfo, tvb, offset, kink_tree);
293 dissect_payload_kink_tgt_rep(pinfo, tvb, offset, kink_tree);
296 dissect_payload_kink_isakmp(pinfo, tvb, offset, kink_tree);
299 dissect_payload_kink_encrypt(pinfo, tvb, offset, kink_tree);
302 dissect_payload_kink_error(pinfo, tvb, offset, kink_tree);
305 dissect_payload_kink_not_defined(pinfo, tvb, offset, kink_tree);
311 dissect_payload_kink_ap_req(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
312 proto_tree *payload_kink_ap_req_tree;
315 guint payload_length;
316 guint16 krb_ap_req_length;
317 int start_payload_offset = 0; /* Keep beginning of payload offset */
319 start_payload_offset = offset;
320 payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH);
322 /* Make the subtree. */
323 payload_kink_ap_req_tree = proto_tree_add_subtree(tree, tvb, offset, payload_length,
324 ett_payload_kink_ap_req, NULL, "KINK_AP_REQ");
326 next_payload = tvb_get_guint8(tvb, offset);
327 proto_tree_add_uint(payload_kink_ap_req_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
330 proto_tree_add_item(payload_kink_ap_req_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
333 ti = proto_tree_add_uint(payload_kink_ap_req_tree, hf_kink_payload_length, tvb, offset, 2, payload_length);
334 if(payload_length <= PAYLOAD_HEADER){
335 expert_add_info(pinfo, ti, &ei_kink_payload_length_small);
339 /* Show time as UTC, not local time. */
340 proto_tree_add_item(payload_kink_ap_req_tree, hf_kink_epoch, tvb, offset, 4, ENC_BIG_ENDIAN);
343 if(payload_length > PAYLOAD_HEADER){
346 krb_ap_req_length = payload_length - PAYLOAD_HEADER;
347 krb_tvb=tvb_new_subset_length_caplen(tvb, offset, (krb_ap_req_length>tvb_captured_length_remaining(tvb, offset))?tvb_captured_length_remaining(tvb, offset):krb_ap_req_length, krb_ap_req_length);
348 keytype=kerberos_output_keytype();
349 dissect_kerberos_main(krb_tvb, pinfo, payload_kink_ap_req_tree, FALSE, NULL);
350 /*offset += krb_ap_req_length;*/
353 /* This part consider padding the padding. Payload_length don't contain the padding. */
354 if(payload_length % PADDING != 0){
355 payload_length += (PADDING - (payload_length % PADDING));
357 offset = start_payload_offset + payload_length;
359 if(payload_length > 0) {
360 control_payload(pinfo, tvb, offset, next_payload, tree); /* Recur control_payload() */
366 dissect_payload_kink_ap_rep(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
367 proto_tree *payload_kink_ap_rep_tree;
370 guint payload_length;
371 guint16 krb_ap_rep_length;
372 int start_payload_offset = 0; /* Keep beginning of payload offset */
374 payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH);
375 start_payload_offset = offset;
377 /* Make the subtree */
378 payload_kink_ap_rep_tree = proto_tree_add_subtree(tree, tvb, offset, payload_length,
379 ett_payload_kink_ap_rep, NULL, "KINK_AP_REP");
381 next_payload = tvb_get_guint8(tvb, offset);
382 proto_tree_add_uint(payload_kink_ap_rep_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
385 proto_tree_add_item(payload_kink_ap_rep_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
388 ti = proto_tree_add_uint(payload_kink_ap_rep_tree, hf_kink_payload_length, tvb, offset, 2, payload_length);
389 if(payload_length <= PAYLOAD_HEADER){
390 expert_add_info(pinfo, ti, &ei_kink_payload_length_small);
394 /* Show time as UTC, not local time. */
395 proto_tree_add_item(payload_kink_ap_rep_tree, hf_kink_epoch, tvb, offset, 4, ENC_BIG_ENDIAN);
398 if(payload_length > PAYLOAD_HEADER){
401 krb_ap_rep_length = payload_length - PAYLOAD_HEADER;
402 krb_tvb=tvb_new_subset_length_caplen(tvb, offset, (krb_ap_rep_length>tvb_captured_length_remaining(tvb, offset))?tvb_captured_length_remaining(tvb, offset):krb_ap_rep_length, krb_ap_rep_length);
403 keytype=kerberos_output_keytype();
404 dissect_kerberos_main(krb_tvb, pinfo, payload_kink_ap_rep_tree, FALSE, NULL);
406 /*offset += krb_ap_rep_length;*/
409 /* This part consider the padding. Payload_length don't contain the padding. */
410 if(payload_length % PADDING != 0){
411 payload_length += (PADDING - (payload_length % PADDING));
413 offset = start_payload_offset + payload_length;
415 if(payload_length > 0) {
416 control_payload(pinfo, tvb, offset, next_payload, tree); /* Recur control_payload() */
421 dissect_payload_kink_krb_error(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
422 proto_tree *payload_kink_krb_error_tree;
425 guint payload_length;
426 guint16 krb_error_length;
427 int start_payload_offset = 0; /* Keep the beginning of the payload offset */
429 payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH);
430 start_payload_offset = offset;
432 /* Make the subtree */
433 payload_kink_krb_error_tree = proto_tree_add_subtree(tree, tvb, offset, payload_length,
434 ett_payload_kink_krb_error, NULL, "KINK_KRB_ERROR");
436 next_payload = tvb_get_guint8(tvb, offset);
437 proto_tree_add_uint(payload_kink_krb_error_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
440 proto_tree_add_item(payload_kink_krb_error_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
443 ti = proto_tree_add_uint(payload_kink_krb_error_tree, hf_kink_payload_length, tvb, offset, 2, payload_length);
444 if(payload_length <= KINK_KRB_ERROR_HEADER){
445 expert_add_info(pinfo, ti, &ei_kink_payload_length_small);
451 if(payload_length > KINK_KRB_ERROR_HEADER){
454 krb_error_length = payload_length - KINK_KRB_ERROR_HEADER;
455 krb_tvb=tvb_new_subset_length_caplen(tvb, offset, (krb_error_length>tvb_captured_length_remaining(tvb, offset))?tvb_captured_length_remaining(tvb, offset):krb_error_length, krb_error_length);
457 dissect_kerberos_main(krb_tvb, pinfo, payload_kink_krb_error_tree, FALSE, NULL);
458 /*offset += krb_error_length;*/
461 /* This part consider the padding. Payload_length don't contain the padding. */
462 if(payload_length % PADDING != 0){
463 payload_length += (PADDING - (payload_length % PADDING));
465 offset = start_payload_offset + payload_length;
467 if(payload_length > 0) {
468 control_payload(pinfo, tvb, offset, next_payload, tree); /* Recur control_payload() */
473 dissect_payload_kink_tgt_req(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
474 proto_tree *payload_kink_tgt_req_tree;
476 guint payload_length;
477 guint16 realm_name_length;
478 int start_payload_offset = 0; /* Keep the beginning of the payload offset */
480 payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH);
481 realm_name_length = tvb_get_ntohs(tvb, offset + TO_REALM_NAME_LENGTH);
482 start_payload_offset = offset;
484 /* Make the subtree */
485 payload_kink_tgt_req_tree = proto_tree_add_subtree(tree, tvb, offset, payload_length,
486 ett_payload_kink_tgt_req, NULL, "KINK_TGT_REQ");
488 next_payload = tvb_get_guint8(tvb, offset);
489 proto_tree_add_uint(payload_kink_tgt_req_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
492 proto_tree_add_item(payload_kink_tgt_req_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
495 proto_tree_add_uint(payload_kink_tgt_req_tree, hf_kink_payload_length, tvb, offset, 2, payload_length);
498 proto_tree_add_uint(payload_kink_tgt_req_tree, hf_kink_realm_name_length, tvb, offset, 2, realm_name_length);
501 proto_tree_add_item(payload_kink_tgt_req_tree, hf_kink_realm_name, tvb, offset, realm_name_length, ENC_NA|ENC_ASCII);
503 /* This part consider the padding. Payload_length don't contain the padding. */
504 if(payload_length % PADDING != 0){
505 payload_length += (PADDING - (payload_length % PADDING));
507 offset = start_payload_offset + payload_length;
509 if(payload_length > 0) {
510 control_payload(pinfo, tvb, offset, next_payload, tree); /* Recur control_payload() */
515 dissect_payload_kink_tgt_rep(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
516 proto_tree *payload_kink_tgt_rep_tree;
518 guint payload_length;
519 guint princ_name_length;
521 int start_payload_offset = 0; /* Keep the beginning of the payload offset */
523 payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH);
524 start_payload_offset = offset;
526 /* Make the subtree */
527 payload_kink_tgt_rep_tree = proto_tree_add_subtree(tree, tvb, offset, payload_length,
528 ett_payload_kink_tgt_rep, NULL, "KINK_TGT_REP");
530 next_payload = tvb_get_guint8(tvb, offset);
531 proto_tree_add_uint(payload_kink_tgt_rep_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
534 proto_tree_add_item(payload_kink_tgt_rep_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
537 proto_tree_add_uint(payload_kink_tgt_rep_tree, hf_kink_payload_length, tvb, offset, 2, payload_length);
540 princ_name_length = tvb_get_ntohs(tvb, offset);
541 proto_tree_add_uint(payload_kink_tgt_rep_tree, hf_kink_princ_name_length, tvb, offset, 2, princ_name_length);
544 proto_tree_add_item(payload_kink_tgt_rep_tree, hf_kink_princ_name, tvb, offset, princ_name_length, ENC_NA|ENC_ASCII);
546 /* This part consider the padding. Princ_name_length don't contain the padding. */
547 if((princ_name_length + FRONT_TGT_REP_HEADER) % PADDING != 0){
548 offset += (princ_name_length + PADDING - ((princ_name_length + FRONT_TGT_REP_HEADER) % PADDING));
551 offset += princ_name_length;
554 tgt_length = tvb_get_ntohs(tvb, offset);
555 proto_tree_add_uint(payload_kink_tgt_rep_tree, hf_kink_tgt_length, tvb, offset, 2, tgt_length);
558 proto_tree_add_item(payload_kink_tgt_rep_tree, hf_kink_tgt, tvb, offset, tgt_length, ENC_NA|ENC_ASCII);
559 /*offset += tgt_length;*/
561 /* This part consider the padding. Payload_length don't contain the padding. */
562 if(payload_length % PADDING!=0){
563 payload_length += (PADDING - (payload_length % PADDING));
565 offset = start_payload_offset + payload_length;
567 if(payload_length > 0) {
568 control_payload(pinfo, tvb, offset, next_payload, tree); /* Recur control_payload() */
573 dissect_payload_kink_isakmp(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
574 proto_tree *payload_kink_isakmp_tree;
577 guint payload_length,isakmp_length;
578 int length, reported_length;
579 guint8 inner_next_pload;
580 int start_payload_offset = 0; /* Keep the beginning of the payload offset */
581 tvbuff_t *isakmp_tvb;
583 payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH);
584 start_payload_offset = offset;
586 /* Make the subtree. */
587 payload_kink_isakmp_tree = proto_tree_add_subtree(tree, tvb, offset, payload_length,
588 ett_payload_kink_isakmp, NULL, "KINK_ISAKMP");
590 next_payload = tvb_get_guint8(tvb, offset);
591 proto_tree_add_uint(payload_kink_isakmp_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
594 proto_tree_add_item(payload_kink_isakmp_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
597 ti = proto_tree_add_uint(payload_kink_isakmp_tree, hf_kink_payload_length, tvb, offset, 2, payload_length);
598 if(payload_length <= PAYLOAD_HEADER){
599 expert_add_info(pinfo, ti, &ei_kink_payload_length_small);
603 inner_next_pload = tvb_get_guint8(tvb, offset);
604 proto_tree_add_uint(payload_kink_isakmp_tree, hf_kink_inner_next_pload, tvb, offset, 1, inner_next_pload);
607 proto_tree_add_item(payload_kink_isakmp_tree, hf_kink_qmversion, tvb, offset, 1, ENC_BIG_ENDIAN);
610 proto_tree_add_item(payload_kink_isakmp_tree, hf_kink_reserved16, tvb, offset, 2, ENC_BIG_ENDIAN);
613 if(payload_length > PAYLOAD_HEADER){
614 isakmp_length = payload_length - PAYLOAD_HEADER;
615 length = tvb_captured_length_remaining(tvb, offset);
616 if (length > (int)isakmp_length)
617 length = isakmp_length;
618 reported_length = tvb_reported_length_remaining(tvb, offset);
619 if (reported_length > (int)isakmp_length)
620 reported_length = isakmp_length;
621 isakmp_tvb = tvb_new_subset_length_caplen(tvb, offset, length, reported_length);
622 isakmp_dissect_payloads(isakmp_tvb, payload_kink_isakmp_tree, 1, inner_next_pload, 0, isakmp_length, pinfo);
625 /* This part consider the padding. Payload_length don't contain the padding. */
626 if(payload_length % PADDING != 0){
627 payload_length += (PADDING - (payload_length % PADDING));
629 offset = start_payload_offset + payload_length;
631 if(payload_length > 0) {
632 control_payload(pinfo, tvb, offset, next_payload, tree); /* Recur control_payload() */
637 dissect_payload_kink_encrypt(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
638 proto_tree *payload_kink_encrypt_tree;
641 guint payload_length;
645 guint8 inner_next_pload;
646 guint16 inner_payload_length;
647 int start_payload_offset = 0; /* Keep the beginning of the payload offset */
649 payload_length = tvb_get_ntohs(tvb,offset + TO_PAYLOAD_LENGTH);
650 start_payload_offset = offset;
653 encrypt_length = payload_length - FROM_NP_TO_PL;
655 /* Make the subtree */
656 payload_kink_encrypt_tree = proto_tree_add_subtree(tree, tvb, offset, payload_length,
657 ett_payload_kink_encrypt, NULL, "KINK_ENCRYPT");
659 next_payload = tvb_get_guint8(tvb, offset);
660 proto_tree_add_uint(payload_kink_encrypt_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
663 proto_tree_add_item(payload_kink_encrypt_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
666 ti = proto_tree_add_uint(payload_kink_encrypt_tree, hf_kink_payload_length, tvb, offset, 2, payload_length);
667 if(payload_length <= PAYLOAD_HEADER){
668 expert_add_info(pinfo, ti, &ei_kink_payload_length_small);
672 /* decrypt kink encrypt */
677 guint8 *plaintext=NULL;
679 next_tvb=tvb_new_subset_length_caplen(tvb, offset, MIN(tvb_captured_length_remaining(tvb, offset), encrypt_length), encrypt_length);
680 plaintext=decrypt_krb5_data(tree, pinfo, 0, next_tvb, keytype, NULL);
682 next_tvb=tvb_new_child_real_data(tvb, plaintext, encrypt_length, encrypt_length);
683 add_new_data_source(pinfo, next_tvb, "decrypted kink encrypt");
684 dissect_decrypt_kink_encrypt(pinfo, next_tvb, tree, encrypt_length);
689 inner_next_pload = tvb_get_guint8(tvb, offset);
690 proto_tree_add_uint(payload_kink_encrypt_tree, hf_kink_inner_next_pload, tvb, offset, 1, inner_next_pload);
693 proto_tree_add_item(payload_kink_encrypt_tree, hf_kink_reserved24, tvb, offset, 3, ENC_BIG_ENDIAN);
696 if(payload_length > PAYLOAD_HEADER){
697 inner_payload_length = payload_length - PAYLOAD_HEADER;
698 proto_tree_add_item(payload_kink_encrypt_tree, hf_kink_payload, tvb, offset, inner_payload_length, ENC_NA);
699 /*offset += inner_payload_length;*/
702 /* This part consider the padding. Payload_length don't contain the padding. */
703 if(payload_length % PADDING !=0){
704 payload_length += (PADDING - (payload_length % PADDING));
706 offset = start_payload_offset + payload_length;
708 if(payload_length > 0) {
709 control_payload(pinfo, tvb, offset, next_payload, tree); /* Recur control_payload() */
715 dissect_decrypt_kink_encrypt(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree, int payload_length){
717 proto_tree *decrypt_kink_encrypt_tree;
721 decrypt_kink_encrypt_tree = proto_tree_add_subtree(tree, tvb, offset, payload_length,
722 ett_decrypt_kink_encrypt, NULL, "decrypted data");
724 next_payload = tvb_get_guint8(tvb, offset);
726 proto_tree_add_uint(decrypt_kink_encrypt_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
729 proto_tree_add_item(decrypt_kink_encrypt_tree, hf_kink_reserved24, tvb, offset, 3, ENC_BIG_ENDIAN);
732 control_payload(pinfo, tvb, offset, next_payload, decrypt_kink_encrypt_tree);
736 static const range_string kink_error_rvals[] = {
738 { 1, 1, "KINK_PROTOERR" },
739 { 2, 2, "KINK_INVDOI" },
740 { 3, 3, "KINK_INVMAJ" },
741 { 4, 4, "KINK_INVMIN" },
742 { 5, 5, "KINK_INTERR" },
743 { 6, 6, "KINK_BADQMVERS" },
744 { BOTTOM_RESERVED, TOP_RESERVED, "RESERVED" },
745 { BOTTOM_PRIVATE_USE, TOP_PRIVATE_USE, "PRIVATE USE" },
746 { TOP_PRIVATE_USE+1, 0xffffffff, "This Error Code is not Defined." },
751 dissect_payload_kink_error(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
752 proto_tree *payload_kink_error_tree;
755 guint16 payload_length;
756 int start_payload_offset = 0; /* Keep the beginning of the payload offset */
758 payload_length = tvb_get_ntohs(tvb,offset + TO_PAYLOAD_LENGTH);
759 start_payload_offset = offset;
761 /* Make the subtree */
762 payload_kink_error_tree = proto_tree_add_subtree(tree, tvb, offset, payload_length,
763 ett_payload_kink_error, NULL, "KINK_ERROR");
765 next_payload = tvb_get_guint8(tvb, offset);
766 proto_tree_add_uint(payload_kink_error_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
769 proto_tree_add_item(payload_kink_error_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
772 ti = proto_tree_add_uint(payload_kink_error_tree, hf_kink_payload_length, tvb, offset, 2, payload_length);
773 if(payload_length != KINK_ERROR_LENGTH){
774 expert_add_info(pinfo, ti, &ei_kink_payload_length_mismatch);
778 proto_tree_add_item(payload_kink_error_tree, hf_kink_error_code, tvb, offset, 4, ENC_BIG_ENDIAN);
780 offset = start_payload_offset + KINK_ERROR_LENGTH;
781 control_payload(pinfo, tvb, offset, next_payload, tree); /* Recur control_payload() */
785 dissect_payload_kink_not_defined(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
786 proto_tree *payload_kink_not_defined_tree;
788 guint payload_length;
789 int start_payload_offset = 0; /* Keep the beginning of the payload offset */
791 start_payload_offset = offset;
792 payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH);
794 /* Make the subtree */
795 payload_kink_not_defined_tree = proto_tree_add_subtree(tree, tvb, offset, payload_length,
796 ett_payload_not_defined, NULL, "UNKNOWN PAYLOAD");
798 next_payload = tvb_get_guint8(tvb, offset);
799 proto_tree_add_uint(payload_kink_not_defined_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
802 proto_tree_add_item(payload_kink_not_defined_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
805 proto_tree_add_uint(payload_kink_not_defined_tree, hf_kink_payload_length, tvb, offset, 2, payload_length);
807 /* This part consider the padding. Payload_length don't contain the padding. */
808 if(payload_length % PADDING != 0){
809 payload_length += (PADDING - (payload_length % PADDING));
811 offset = start_payload_offset + payload_length;
813 /* XXX - prevent an endless loop if payload_length is 0, don't know the correct way to handle this! */
814 if(payload_length > 0) {
815 control_payload(pinfo, tvb, offset, next_payload, tree);
820 kink_fmt_version( gchar *result, guint32 version )
822 guint8 major_version, minor_version;
824 /* This part is the version. Consider less than 1 octet value.
825 * Major version and minor version is 4bit. Front half of 1octet
826 * is major version, and second half of 1octet is minor version.
827 * The calculation of major version is shown below.
828 * The logical product of the value of 1octet and 0xf0 is performed.
829 * And It is performed 4bit right shift.
830 * Secondarily, the calculation of minor version is shown below.
831 * The logical product of the value of 1octet and 0x0f is performed.
833 major_version = (guint8)((version & FRONT_FOUR_BIT) >> VERSION_BIT_SHIFT);
834 minor_version = (guint8)(version & SECOND_FOUR_BIT);
836 g_snprintf( result, ITEM_LABEL_LENGTH, "%d.%02d", major_version, minor_version);
841 proto_register_kink(void) {
843 static hf_register_info hf[] = {
845 { "Type", "kink.type",
846 FT_UINT8, BASE_DEC, VALS(kink_type_vals), 0x0,
849 { "Length", "kink.length",
850 FT_UINT16, BASE_DEC, NULL, 0x0,
852 { &hf_kink_transactionId,
853 { "Transaction ID", "kink.transactionId",
854 FT_UINT32, BASE_DEC, NULL, 0x0,
856 { &hf_kink_checkSumLength,
857 { "Checksum Length", "kink.checkSumLength",
858 FT_UINT8, BASE_DEC, NULL, 0x0,
862 FT_UINT8, BASE_DEC, VALS(kink_A_vals), 0x0,
865 { "Version", "kink.version",
866 FT_UINT8, BASE_CUSTOM, CF_FUNC(kink_fmt_version), 0x0,
868 { &hf_kink_domain_of_interpretation,
869 { "Domain Of Interpretation", "kink.domain_of_interpretation",
870 FT_UINT32, BASE_DEC, NULL, 0x0,
872 { &hf_kink_qmversion,
873 { "QMVersion", "kink.qmversion",
874 FT_UINT8, BASE_CUSTOM, CF_FUNC(kink_fmt_version), 0x0,
876 { &hf_kink_error_code,
877 { "ErrorCode", "kink.error_code",
878 FT_UINT32, BASE_DEC|BASE_RANGE_STRING, RVALS(kink_error_rvals), 0x0,
880 { &hf_kink_reserved8,
881 { "Reserved", "kink.reserved",
882 FT_UINT8, BASE_DEC, NULL, 0x0,
884 { &hf_kink_reserved15,
885 { "Reserved", "kink.reserved",
886 FT_UINT16, BASE_DEC, NULL, SECOND_FIFTEEN_BIT,
888 { &hf_kink_reserved16,
889 { "Reserved", "kink.reserved",
890 FT_UINT16, BASE_DEC, NULL, 0,
892 { &hf_kink_reserved24,
893 { "Reserved", "kink.reserved",
894 FT_UINT24, BASE_DEC, NULL, 0,
897 { "Checksum", "kink.checkSum",
898 FT_BYTES, BASE_NONE, NULL, 0x0,
900 { &hf_kink_next_payload,
901 { "Next Payload", "kink.nextPayload",
902 FT_UINT8, BASE_DEC, VALS(kink_next_payload), 0x0,
904 { &hf_kink_payload_length,
905 { "Payload Length", "kink.payloadLength",
906 FT_UINT8, BASE_DEC, NULL, 0x0,
909 { "EPOCH", "kink.epoch",
910 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0x0,
912 { &hf_kink_inner_next_pload,
913 { "InnerNextPload", "kink.innerNextPload",
914 FT_UINT8, BASE_DEC, NULL, 0x0,
916 { &hf_kink_realm_name_length,
917 { "RealmNameLength", "kink.realmNameLength",
918 FT_UINT16, BASE_DEC, NULL, 0,
920 { &hf_kink_realm_name,
921 { "RealmName", "kink.realmName",
922 FT_STRING, BASE_NONE, NULL, 0,
924 { &hf_kink_princ_name_length,
925 { "PrincNameLength", "kink.princNameLength",
926 FT_UINT16, BASE_DEC, NULL, 0,
928 { &hf_kink_princ_name,
929 { "PrincName", "kink.princName",
930 FT_STRING, BASE_NONE, NULL, 0,
932 { &hf_kink_tgt_length,
933 { "TGT Length", "kink.tgtLength",
934 FT_UINT16, BASE_DEC, NULL, 0,
938 FT_STRING, BASE_NONE, NULL, 0,
941 { "Payload", "kink.payload",
942 FT_BYTES, BASE_NONE, NULL, 0,
946 /* Argument for making the subtree. */
947 static gint *ett[] = {
949 /* &ett_kink_version, */
951 &ett_payload_kink_ap_req,
952 &ett_payload_kink_ap_rep,
953 &ett_payload_kink_krb_error,
954 &ett_payload_kink_tgt_req,
955 &ett_payload_kink_tgt_rep,
956 &ett_payload_kink_isakmp,
957 &ett_payload_kink_encrypt,
958 &ett_payload_kink_error,
959 &ett_payload_not_defined,
960 &ett_decrypt_kink_encrypt,
964 static ei_register_info ei[] = {
965 { &ei_kink_payload_length_small, { "kink.payload_length_small", PI_PROTOCOL, PI_WARN, "This Payload Length is too small", EXPFILL }},
966 { &ei_kink_payload_length_mismatch, { "kink.payload_length_mismatch", PI_PROTOCOL, PI_WARN, "This Payload Length is mismatch", EXPFILL }},
969 expert_module_t* expert_kink;
971 proto_kink = proto_register_protocol("Kerberized Internet Negotiation of Key", "KINK", "kink");
972 proto_register_field_array(proto_kink, hf, array_length(hf));
973 proto_register_subtree_array(ett, array_length(ett));
974 expert_kink = expert_register_protocol(proto_kink);
975 expert_register_field_array(expert_kink, ei, array_length(ei));
979 void proto_reg_handoff_kink(void) {
981 dissector_handle_t kink_handle;
983 kink_handle = create_dissector_handle(dissect_kink, proto_kink);
985 dissector_add_uint_with_preference("udp.port", KINK_PORT, kink_handle);
990 * Editor modelines - http://www.wireshark.org/tools/modelines.html
995 * indent-tabs-mode: nil
998 * ex: set shiftwidth=2 tabstop=8 expandtab:
999 * :indentSize=2:tabSize=8:noTabs=true: