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 static dissector_handle_t kink_handle
;
30 #define KINK_ISAKMP_PAYLOAD_BASE 14
32 static int proto_kink
;
34 /* Argument for proto_tree_add_uint() */
35 static int hf_kink_type
;
36 static int hf_kink_length
;
37 static int hf_kink_transactionId
;
38 static int hf_kink_checkSumLength
;
40 static int hf_kink_version
;
41 static int hf_kink_domain_of_interpretation
;
42 static int hf_kink_qmversion
;
43 static int hf_kink_error_code
;
44 static int hf_kink_reserved8
;
45 static int hf_kink_reserved15
;
46 static int hf_kink_reserved16
;
47 static int hf_kink_reserved24
;
48 static int hf_kink_checkSum
;
49 static int hf_kink_next_payload
;
50 static int hf_kink_payload_length
;
51 static int hf_kink_epoch
;
52 static int hf_kink_inner_next_pload
;
53 static int hf_kink_realm_name_length
;
54 static int hf_kink_realm_name
;
55 static int hf_kink_princ_name_length
;
56 static int hf_kink_princ_name
;
57 static int hf_kink_tgt_length
;
58 static int hf_kink_tgt
;
59 static int hf_kink_payload
;
61 /* Argument for making the subtree */
63 /*static int ett_kink_version;*/
64 static int ett_kink_payload
;
65 static int ett_payload_kink_ap_req
;
66 static int ett_payload_kink_ap_rep
;
67 static int ett_payload_kink_krb_error
;
68 static int ett_payload_kink_tgt_req
;
69 static int ett_payload_kink_tgt_rep
;
70 static int ett_payload_kink_isakmp
;
71 static int ett_payload_kink_encrypt
;
72 static int ett_payload_kink_error
;
73 static int ett_payload_not_defined
;
74 static int ett_decrypt_kink_encrypt
;
76 static expert_field ei_kink_payload_length_small
;
77 static expert_field ei_kink_payload_length_mismatch
;
80 /* Define the kink type value */
81 #define KINK_TYPE_RESERVED 0
82 #define KINK_TYPE_CREATE 1
83 #define KINK_TYPE_DELETE 2
84 #define KINK_TYPE_REPLY 3
85 #define KINK_TYPE_GETTGT 4
86 #define KINK_TYPE_ACK 5
87 #define KINK_TYPE_STATUS 6
89 static const value_string kink_type_vals
[]={
90 {KINK_TYPE_RESERVED
,"RESERVED"},
91 {KINK_TYPE_CREATE
,"CREATE"},
92 {KINK_TYPE_DELETE
,"DELETE"},
93 {KINK_TYPE_REPLY
,"REPLY"},
94 {KINK_TYPE_GETTGT
,"GETTGT"},
95 {KINK_TYPE_ACK
,"ACK"},
96 {KINK_TYPE_STATUS
,"STATUS"},
100 /* Define the kink A value */
101 #define KINK_A_NOT_REQUEST_ACK 0
102 #define KINK_A_REQUEST_ACK 1
104 static const value_string kink_A_vals
[]={
105 {KINK_A_NOT_REQUEST_ACK
,"Not Request ACK"},
106 {KINK_A_REQUEST_ACK
,"Request ACK"},
110 /* Define the kink payload */
112 #define KINK_AP_REQ KINK_ISAKMP_PAYLOAD_BASE+0
113 #define KINK_AP_REP KINK_ISAKMP_PAYLOAD_BASE+1
114 #define KINK_KRB_ERROR KINK_ISAKMP_PAYLOAD_BASE+2
115 #define KINK_TGT_REQ KINK_ISAKMP_PAYLOAD_BASE+3
116 #define KINK_TGT_REP KINK_ISAKMP_PAYLOAD_BASE+4
117 #define KINK_ISAKMP KINK_ISAKMP_PAYLOAD_BASE+5
118 #define KINK_ENCRYPT KINK_ISAKMP_PAYLOAD_BASE+6
119 #define KINK_ERROR KINK_ISAKMP_PAYLOAD_BASE+7
121 static const value_string kink_next_payload
[]={
122 {KINK_DONE
, "KINK_DONE"},
123 {KINK_AP_REQ
, "KINK_AP_REQ"},
124 {KINK_AP_REP
, "KINK_AP_REP"},
125 {KINK_KRB_ERROR
, "KINK_KRB_ERROR"},
126 {KINK_TGT_REQ
, "KINK_TGT_REQ"},
127 {KINK_TGT_REP
, "KINK_TGT_REP"},
128 {KINK_ISAKMP
, "KINK_ISAKMP"},
129 {KINK_ENCRYPT
, "KINK_ENCRYPT"},
130 {KINK_ERROR
, "KINK_ERROR"},
134 /* Define the magic number
135 * Using at the kink error
138 #define KINK_PROTOERR 1
139 #define KINK_INVDOI 2
140 #define KINK_INVMAJ 3
141 #define KINK_INVMIN 4
142 #define KINK_INTERR 5
143 #define KINK_BADQMVERS 6
144 #define BOTTOM_RESERVED 7
145 #define TOP_RESERVED 8191
146 #define BOTTOM_PRIVATE_USE 8192
147 #define TOP_PRIVATE_USE 16383
149 /* Using at the kink header */
151 #define VERSION_BIT_SHIFT 4
152 #define A_BIT_SHIFT 7
153 #define FROM_TYPE_TO_RESERVED 16
155 /* Using at the payload */
156 #define TO_PAYLOAD_LENGTH 2
158 #define KINK_KRB_ERROR_HEADER 4
159 #define FROM_NP_TO_PL 4
160 #define TO_REALM_NAME_LENGTH 4
161 #define KINK_TGT_REQ_HEADER 6
162 #define FRONT_TGT_REP_HEADER 6
163 #define PAYLOAD_HEADER 8
164 #define KINK_ERROR_LENGTH 8
167 /* define hexadecimal */
168 #define FRONT_FOUR_BIT 0xf0
169 #define SECOND_FOUR_BIT 0x0f
170 #define FRONT_ONE_BIT 0x80
171 #define SECOND_FIFTEEN_BIT 0x7fff
173 /* decrypt element */
174 static uint32_t keytype
;
176 static void control_payload(packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, uint8_t next_payload
, proto_tree
*kink_payload_tree
);
177 static void dissect_payload_kink_ap_req(packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, proto_tree
*tree
);
178 static void dissect_payload_kink_ap_rep(packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, proto_tree
*tree
);
179 static void dissect_payload_kink_krb_error(packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, proto_tree
*tree
);
180 static void dissect_payload_kink_tgt_req(packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, proto_tree
*tree
);
181 static void dissect_payload_kink_tgt_rep(packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, proto_tree
*tree
);
182 static void dissect_payload_kink_isakmp(packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, proto_tree
*tree
);
183 static void dissect_payload_kink_encrypt(packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, proto_tree
*tree
);
184 static void dissect_payload_kink_error(packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, proto_tree
*tree
);
185 static void dissect_payload_kink_not_defined(packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, proto_tree
*tree
);
187 static void dissect_decrypt_kink_encrypt(packet_info
*pinfo
, tvbuff_t
*tvb
, proto_tree
*tree
, int payload_length
);
190 /* This function is dissecting the kink header. */
192 dissect_kink(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
){
193 proto_item
*ti
= NULL
;
194 proto_tree
*kink_tree
= NULL
;
198 uint8_t next_payload
;
199 uint8_t value_a_and_front_reserved
;
203 type
= tvb_get_uint8(tvb
,offset
);
205 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "KINK");
207 /* It shows kink type by the type value. */
208 col_set_str(pinfo
->cinfo
, COL_INFO
, val_to_str_const(type
, kink_type_vals
, "unknown"));
210 /* Make the kink tree */
211 ti
= proto_tree_add_item(tree
, proto_kink
, tvb
, offset
, -1, ENC_NA
);
212 kink_tree
= proto_item_add_subtree(ti
, ett_kink
);
214 proto_tree_add_uint(kink_tree
, hf_kink_type
, tvb
, offset
, 1, type
);
217 proto_tree_add_item(kink_tree
, hf_kink_version
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
220 proto_tree_add_item(kink_tree
, hf_kink_length
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
223 doi
= tvb_get_ntohl(tvb
, offset
);
226 proto_tree_add_uint_format_value(kink_tree
, hf_kink_domain_of_interpretation
, tvb
, offset
, 4, doi
, "IPsec (%u)", doi
);
229 proto_tree_add_uint_format_value(kink_tree
, hf_kink_domain_of_interpretation
, tvb
, offset
, 4, doi
, "Not IPsec (%u)", doi
);
233 proto_tree_add_item(kink_tree
, hf_kink_transactionId
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
236 chsumlen
= tvb_get_uint8(tvb
, offset
);
237 proto_tree_add_item(kink_tree
, hf_kink_checkSumLength
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
240 next_payload
= tvb_get_uint8(tvb
, offset
);
241 proto_tree_add_uint(kink_tree
, hf_kink_next_payload
, tvb
, offset
, 1, next_payload
);
244 /* A is 1bit field. The calculation of A is shown below.
245 * The logical product of 1octet value and 0x80 is performed.
246 * And It is performed 7bit right shift.
248 value_a_and_front_reserved
= tvb_get_uint8(tvb
, offset
);
249 value_a
= (value_a_and_front_reserved
& FRONT_ONE_BIT
) >> A_BIT_SHIFT
;
250 proto_tree_add_uint(kink_tree
, hf_kink_A
, tvb
, offset
, 1, value_a
);
252 /* The reserved field is 15bit.
253 * The logical product of 2octet value and 0x7fff is performed.
255 proto_tree_add_item(kink_tree
, hf_kink_reserved15
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
258 proto_tree_add_item(kink_tree
, hf_kink_checkSum
, tvb
, offset
, chsumlen
, ENC_NA
);
260 /* This part consider the padding. Chsumlen don't contain the padding. */
261 if((chsumlen
% PADDING
) != 0){
262 chsumlen
+= (PADDING
- (chsumlen
% PADDING
));
269 control_payload(pinfo
, tvb
, offset
, next_payload
, kink_tree
);
271 return tvb_captured_length(tvb
);
274 /* This part call the dissect payload function by next_payload value.
275 * This function called by the respective function again.
278 // NOLINTNEXTLINE(misc-no-recursion)
279 control_payload(packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, uint8_t next_payload
, proto_tree
*kink_tree
){
280 switch(next_payload
){
284 dissect_payload_kink_ap_req(pinfo
, tvb
, offset
, kink_tree
);
287 dissect_payload_kink_ap_rep(pinfo
, tvb
, offset
, kink_tree
);
290 dissect_payload_kink_krb_error(pinfo
, tvb
, offset
, kink_tree
);
293 dissect_payload_kink_tgt_req(pinfo
, tvb
, offset
, kink_tree
);
296 dissect_payload_kink_tgt_rep(pinfo
, tvb
, offset
, kink_tree
);
299 dissect_payload_kink_isakmp(pinfo
, tvb
, offset
, kink_tree
);
302 dissect_payload_kink_encrypt(pinfo
, tvb
, offset
, kink_tree
);
305 dissect_payload_kink_error(pinfo
, tvb
, offset
, kink_tree
);
308 dissect_payload_kink_not_defined(pinfo
, tvb
, offset
, kink_tree
);
314 // NOLINTNEXTLINE(misc-no-recursion)
315 dissect_payload_kink_ap_req(packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, proto_tree
*tree
){
316 proto_tree
*payload_kink_ap_req_tree
;
318 uint8_t next_payload
;
319 unsigned payload_length
;
320 uint16_t krb_ap_req_length
;
321 int start_payload_offset
= 0; /* Keep beginning of payload offset */
323 start_payload_offset
= offset
;
324 payload_length
= tvb_get_ntohs(tvb
, offset
+ TO_PAYLOAD_LENGTH
);
326 /* Make the subtree. */
327 payload_kink_ap_req_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, payload_length
,
328 ett_payload_kink_ap_req
, NULL
, "KINK_AP_REQ");
330 next_payload
= tvb_get_uint8(tvb
, offset
);
331 proto_tree_add_uint(payload_kink_ap_req_tree
, hf_kink_next_payload
, tvb
, offset
, 1, next_payload
);
334 proto_tree_add_item(payload_kink_ap_req_tree
, hf_kink_reserved8
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
337 ti
= proto_tree_add_uint(payload_kink_ap_req_tree
, hf_kink_payload_length
, tvb
, offset
, 2, payload_length
);
338 if(payload_length
<= PAYLOAD_HEADER
){
339 expert_add_info(pinfo
, ti
, &ei_kink_payload_length_small
);
343 /* Show time as UTC, not local time. */
344 proto_tree_add_item(payload_kink_ap_req_tree
, hf_kink_epoch
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
347 if(payload_length
> PAYLOAD_HEADER
){
350 krb_ap_req_length
= payload_length
- PAYLOAD_HEADER
;
351 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
);
352 keytype
=kerberos_output_keytype();
353 dissect_kerberos_main(krb_tvb
, pinfo
, payload_kink_ap_req_tree
, false, NULL
);
354 /*offset += krb_ap_req_length;*/
357 /* This part consider padding the padding. Payload_length don't contain the padding. */
358 if(payload_length
% PADDING
!= 0){
359 payload_length
+= (PADDING
- (payload_length
% PADDING
));
361 offset
= start_payload_offset
+ payload_length
;
363 if(payload_length
> 0) {
364 control_payload(pinfo
, tvb
, offset
, next_payload
, tree
); /* Recur control_payload() */
370 // NOLINTNEXTLINE(misc-no-recursion)
371 dissect_payload_kink_ap_rep(packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, proto_tree
*tree
){
372 proto_tree
*payload_kink_ap_rep_tree
;
374 uint8_t next_payload
;
375 unsigned payload_length
;
376 uint16_t krb_ap_rep_length
;
377 int start_payload_offset
= 0; /* Keep beginning of payload offset */
379 payload_length
= tvb_get_ntohs(tvb
, offset
+ TO_PAYLOAD_LENGTH
);
380 start_payload_offset
= offset
;
382 /* Make the subtree */
383 payload_kink_ap_rep_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, payload_length
,
384 ett_payload_kink_ap_rep
, NULL
, "KINK_AP_REP");
386 next_payload
= tvb_get_uint8(tvb
, offset
);
387 proto_tree_add_uint(payload_kink_ap_rep_tree
, hf_kink_next_payload
, tvb
, offset
, 1, next_payload
);
390 proto_tree_add_item(payload_kink_ap_rep_tree
, hf_kink_reserved8
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
393 ti
= proto_tree_add_uint(payload_kink_ap_rep_tree
, hf_kink_payload_length
, tvb
, offset
, 2, payload_length
);
394 if(payload_length
<= PAYLOAD_HEADER
){
395 expert_add_info(pinfo
, ti
, &ei_kink_payload_length_small
);
399 /* Show time as UTC, not local time. */
400 proto_tree_add_item(payload_kink_ap_rep_tree
, hf_kink_epoch
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
403 if(payload_length
> PAYLOAD_HEADER
){
406 krb_ap_rep_length
= payload_length
- PAYLOAD_HEADER
;
407 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
);
408 keytype
=kerberos_output_keytype();
409 dissect_kerberos_main(krb_tvb
, pinfo
, payload_kink_ap_rep_tree
, false, NULL
);
411 /*offset += krb_ap_rep_length;*/
414 /* This part consider the padding. Payload_length don't contain the padding. */
415 if(payload_length
% PADDING
!= 0){
416 payload_length
+= (PADDING
- (payload_length
% PADDING
));
418 offset
= start_payload_offset
+ payload_length
;
420 if(payload_length
> 0) {
421 control_payload(pinfo
, tvb
, offset
, next_payload
, tree
); /* Recur control_payload() */
426 // NOLINTNEXTLINE(misc-no-recursion)
427 dissect_payload_kink_krb_error(packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, proto_tree
*tree
){
428 proto_tree
*payload_kink_krb_error_tree
;
430 uint8_t next_payload
;
431 unsigned payload_length
;
432 uint16_t krb_error_length
;
433 int start_payload_offset
= 0; /* Keep the beginning of the payload offset */
435 payload_length
= tvb_get_ntohs(tvb
, offset
+ TO_PAYLOAD_LENGTH
);
436 start_payload_offset
= offset
;
438 /* Make the subtree */
439 payload_kink_krb_error_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, payload_length
,
440 ett_payload_kink_krb_error
, NULL
, "KINK_KRB_ERROR");
442 next_payload
= tvb_get_uint8(tvb
, offset
);
443 proto_tree_add_uint(payload_kink_krb_error_tree
, hf_kink_next_payload
, tvb
, offset
, 1, next_payload
);
446 proto_tree_add_item(payload_kink_krb_error_tree
, hf_kink_reserved8
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
449 ti
= proto_tree_add_uint(payload_kink_krb_error_tree
, hf_kink_payload_length
, tvb
, offset
, 2, payload_length
);
450 if(payload_length
<= KINK_KRB_ERROR_HEADER
){
451 expert_add_info(pinfo
, ti
, &ei_kink_payload_length_small
);
457 if(payload_length
> KINK_KRB_ERROR_HEADER
){
460 krb_error_length
= payload_length
- KINK_KRB_ERROR_HEADER
;
461 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
);
463 dissect_kerberos_main(krb_tvb
, pinfo
, payload_kink_krb_error_tree
, false, NULL
);
464 /*offset += krb_error_length;*/
467 /* This part consider the padding. Payload_length don't contain the padding. */
468 if(payload_length
% PADDING
!= 0){
469 payload_length
+= (PADDING
- (payload_length
% PADDING
));
471 offset
= start_payload_offset
+ payload_length
;
473 if(payload_length
> 0) {
474 control_payload(pinfo
, tvb
, offset
, next_payload
, tree
); /* Recur control_payload() */
479 // NOLINTNEXTLINE(misc-no-recursion)
480 dissect_payload_kink_tgt_req(packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, proto_tree
*tree
){
481 proto_tree
*payload_kink_tgt_req_tree
;
482 uint8_t next_payload
;
483 unsigned payload_length
;
484 uint16_t realm_name_length
;
485 int start_payload_offset
= 0; /* Keep the beginning of the payload offset */
487 payload_length
= tvb_get_ntohs(tvb
, offset
+ TO_PAYLOAD_LENGTH
);
488 realm_name_length
= tvb_get_ntohs(tvb
, offset
+ TO_REALM_NAME_LENGTH
);
489 start_payload_offset
= offset
;
491 /* Make the subtree */
492 payload_kink_tgt_req_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, payload_length
,
493 ett_payload_kink_tgt_req
, NULL
, "KINK_TGT_REQ");
495 next_payload
= tvb_get_uint8(tvb
, offset
);
496 proto_tree_add_uint(payload_kink_tgt_req_tree
, hf_kink_next_payload
, tvb
, offset
, 1, next_payload
);
499 proto_tree_add_item(payload_kink_tgt_req_tree
, hf_kink_reserved8
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
502 proto_tree_add_uint(payload_kink_tgt_req_tree
, hf_kink_payload_length
, tvb
, offset
, 2, payload_length
);
505 proto_tree_add_uint(payload_kink_tgt_req_tree
, hf_kink_realm_name_length
, tvb
, offset
, 2, realm_name_length
);
508 proto_tree_add_item(payload_kink_tgt_req_tree
, hf_kink_realm_name
, tvb
, offset
, realm_name_length
, ENC_NA
|ENC_ASCII
);
510 /* This part consider the padding. Payload_length don't contain the padding. */
511 if(payload_length
% PADDING
!= 0){
512 payload_length
+= (PADDING
- (payload_length
% PADDING
));
514 offset
= start_payload_offset
+ payload_length
;
516 if(payload_length
> 0) {
517 control_payload(pinfo
, tvb
, offset
, next_payload
, tree
); /* Recur control_payload() */
522 // NOLINTNEXTLINE(misc-no-recursion)
523 dissect_payload_kink_tgt_rep(packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, proto_tree
*tree
){
524 proto_tree
*payload_kink_tgt_rep_tree
;
525 uint8_t next_payload
;
526 unsigned payload_length
;
527 unsigned princ_name_length
;
529 int start_payload_offset
= 0; /* Keep the beginning of the payload offset */
531 payload_length
= tvb_get_ntohs(tvb
, offset
+ TO_PAYLOAD_LENGTH
);
532 start_payload_offset
= offset
;
534 /* Make the subtree */
535 payload_kink_tgt_rep_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, payload_length
,
536 ett_payload_kink_tgt_rep
, NULL
, "KINK_TGT_REP");
538 next_payload
= tvb_get_uint8(tvb
, offset
);
539 proto_tree_add_uint(payload_kink_tgt_rep_tree
, hf_kink_next_payload
, tvb
, offset
, 1, next_payload
);
542 proto_tree_add_item(payload_kink_tgt_rep_tree
, hf_kink_reserved8
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
545 proto_tree_add_uint(payload_kink_tgt_rep_tree
, hf_kink_payload_length
, tvb
, offset
, 2, payload_length
);
548 princ_name_length
= tvb_get_ntohs(tvb
, offset
);
549 proto_tree_add_uint(payload_kink_tgt_rep_tree
, hf_kink_princ_name_length
, tvb
, offset
, 2, princ_name_length
);
552 proto_tree_add_item(payload_kink_tgt_rep_tree
, hf_kink_princ_name
, tvb
, offset
, princ_name_length
, ENC_NA
|ENC_ASCII
);
554 /* This part consider the padding. Princ_name_length don't contain the padding. */
555 if((princ_name_length
+ FRONT_TGT_REP_HEADER
) % PADDING
!= 0){
556 offset
+= (princ_name_length
+ PADDING
- ((princ_name_length
+ FRONT_TGT_REP_HEADER
) % PADDING
));
559 offset
+= princ_name_length
;
562 tgt_length
= tvb_get_ntohs(tvb
, offset
);
563 proto_tree_add_uint(payload_kink_tgt_rep_tree
, hf_kink_tgt_length
, tvb
, offset
, 2, tgt_length
);
566 proto_tree_add_item(payload_kink_tgt_rep_tree
, hf_kink_tgt
, tvb
, offset
, tgt_length
, ENC_NA
|ENC_ASCII
);
567 /*offset += tgt_length;*/
569 /* This part consider the padding. Payload_length don't contain the padding. */
570 if(payload_length
% PADDING
!=0){
571 payload_length
+= (PADDING
- (payload_length
% PADDING
));
573 offset
= start_payload_offset
+ payload_length
;
575 if(payload_length
> 0) {
576 control_payload(pinfo
, tvb
, offset
, next_payload
, tree
); /* Recur control_payload() */
581 // NOLINTNEXTLINE(misc-no-recursion)
582 dissect_payload_kink_isakmp(packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, proto_tree
*tree
){
583 proto_tree
*payload_kink_isakmp_tree
;
585 uint8_t next_payload
;
586 unsigned payload_length
,isakmp_length
;
587 int length
, reported_length
;
588 uint8_t inner_next_pload
;
589 int start_payload_offset
= 0; /* Keep the beginning of the payload offset */
590 tvbuff_t
*isakmp_tvb
;
592 payload_length
= tvb_get_ntohs(tvb
, offset
+ TO_PAYLOAD_LENGTH
);
593 start_payload_offset
= offset
;
595 /* Make the subtree. */
596 payload_kink_isakmp_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, payload_length
,
597 ett_payload_kink_isakmp
, NULL
, "KINK_ISAKMP");
599 next_payload
= tvb_get_uint8(tvb
, offset
);
600 proto_tree_add_uint(payload_kink_isakmp_tree
, hf_kink_next_payload
, tvb
, offset
, 1, next_payload
);
603 proto_tree_add_item(payload_kink_isakmp_tree
, hf_kink_reserved8
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
606 ti
= proto_tree_add_uint(payload_kink_isakmp_tree
, hf_kink_payload_length
, tvb
, offset
, 2, payload_length
);
607 if(payload_length
<= PAYLOAD_HEADER
){
608 expert_add_info(pinfo
, ti
, &ei_kink_payload_length_small
);
612 inner_next_pload
= tvb_get_uint8(tvb
, offset
);
613 proto_tree_add_uint(payload_kink_isakmp_tree
, hf_kink_inner_next_pload
, tvb
, offset
, 1, inner_next_pload
);
616 proto_tree_add_item(payload_kink_isakmp_tree
, hf_kink_qmversion
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
619 proto_tree_add_item(payload_kink_isakmp_tree
, hf_kink_reserved16
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
622 if(payload_length
> PAYLOAD_HEADER
){
623 isakmp_length
= payload_length
- PAYLOAD_HEADER
;
624 length
= tvb_captured_length_remaining(tvb
, offset
);
625 if (length
> (int)isakmp_length
)
626 length
= isakmp_length
;
627 reported_length
= tvb_reported_length_remaining(tvb
, offset
);
628 if (reported_length
> (int)isakmp_length
)
629 reported_length
= isakmp_length
;
630 isakmp_tvb
= tvb_new_subset_length_caplen(tvb
, offset
, length
, reported_length
);
631 isakmp_dissect_payloads(isakmp_tvb
, payload_kink_isakmp_tree
, 1, inner_next_pload
, 0, isakmp_length
, pinfo
);
634 /* This part consider the padding. Payload_length don't contain the padding. */
635 if(payload_length
% PADDING
!= 0){
636 payload_length
+= (PADDING
- (payload_length
% PADDING
));
638 offset
= start_payload_offset
+ payload_length
;
640 if(payload_length
> 0) {
641 control_payload(pinfo
, tvb
, offset
, next_payload
, tree
); /* Recur control_payload() */
646 // NOLINTNEXTLINE(misc-no-recursion)
647 dissect_payload_kink_encrypt(packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, proto_tree
*tree
){
648 proto_tree
*payload_kink_encrypt_tree
;
650 uint8_t next_payload
;
651 unsigned payload_length
;
655 uint8_t inner_next_pload
;
656 uint16_t inner_payload_length
;
657 int start_payload_offset
= 0; /* Keep the beginning of the payload offset */
659 payload_length
= tvb_get_ntohs(tvb
,offset
+ TO_PAYLOAD_LENGTH
);
660 start_payload_offset
= offset
;
663 encrypt_length
= payload_length
- FROM_NP_TO_PL
;
665 /* Make the subtree */
666 payload_kink_encrypt_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, payload_length
,
667 ett_payload_kink_encrypt
, NULL
, "KINK_ENCRYPT");
669 next_payload
= tvb_get_uint8(tvb
, offset
);
670 proto_tree_add_uint(payload_kink_encrypt_tree
, hf_kink_next_payload
, tvb
, offset
, 1, next_payload
);
673 proto_tree_add_item(payload_kink_encrypt_tree
, hf_kink_reserved8
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
676 ti
= proto_tree_add_uint(payload_kink_encrypt_tree
, hf_kink_payload_length
, tvb
, offset
, 2, payload_length
);
677 if(payload_length
<= PAYLOAD_HEADER
){
678 expert_add_info(pinfo
, ti
, &ei_kink_payload_length_small
);
682 /* decrypt kink encrypt */
687 uint8_t *plaintext
=NULL
;
689 next_tvb
=tvb_new_subset_length_caplen(tvb
, offset
, MIN(tvb_captured_length_remaining(tvb
, offset
), encrypt_length
), encrypt_length
);
690 plaintext
=decrypt_krb5_data(tree
, pinfo
, 0, next_tvb
, keytype
, NULL
);
692 next_tvb
=tvb_new_child_real_data(tvb
, plaintext
, encrypt_length
, encrypt_length
);
693 add_new_data_source(pinfo
, next_tvb
, "decrypted kink encrypt");
694 dissect_decrypt_kink_encrypt(pinfo
, next_tvb
, tree
, encrypt_length
);
699 inner_next_pload
= tvb_get_uint8(tvb
, offset
);
700 proto_tree_add_uint(payload_kink_encrypt_tree
, hf_kink_inner_next_pload
, tvb
, offset
, 1, inner_next_pload
);
703 proto_tree_add_item(payload_kink_encrypt_tree
, hf_kink_reserved24
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
706 if(payload_length
> PAYLOAD_HEADER
){
707 inner_payload_length
= payload_length
- PAYLOAD_HEADER
;
708 proto_tree_add_item(payload_kink_encrypt_tree
, hf_kink_payload
, tvb
, offset
, inner_payload_length
, ENC_NA
);
709 /*offset += inner_payload_length;*/
712 /* This part consider the padding. Payload_length don't contain the padding. */
713 if(payload_length
% PADDING
!=0){
714 payload_length
+= (PADDING
- (payload_length
% PADDING
));
716 offset
= start_payload_offset
+ payload_length
;
718 if(payload_length
> 0) {
719 control_payload(pinfo
, tvb
, offset
, next_payload
, tree
); /* Recur control_payload() */
725 // NOLINTNEXTLINE(misc-no-recursion)
726 dissect_decrypt_kink_encrypt(packet_info
*pinfo
, tvbuff_t
*tvb
, proto_tree
*tree
, int payload_length
){
728 proto_tree
*decrypt_kink_encrypt_tree
;
730 uint8_t next_payload
;
732 decrypt_kink_encrypt_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, payload_length
,
733 ett_decrypt_kink_encrypt
, NULL
, "decrypted data");
735 next_payload
= tvb_get_uint8(tvb
, offset
);
737 proto_tree_add_uint(decrypt_kink_encrypt_tree
, hf_kink_next_payload
, tvb
, offset
, 1, next_payload
);
740 proto_tree_add_item(decrypt_kink_encrypt_tree
, hf_kink_reserved24
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
743 control_payload(pinfo
, tvb
, offset
, next_payload
, decrypt_kink_encrypt_tree
);
747 static const range_string kink_error_rvals
[] = {
749 { 1, 1, "KINK_PROTOERR" },
750 { 2, 2, "KINK_INVDOI" },
751 { 3, 3, "KINK_INVMAJ" },
752 { 4, 4, "KINK_INVMIN" },
753 { 5, 5, "KINK_INTERR" },
754 { 6, 6, "KINK_BADQMVERS" },
755 { BOTTOM_RESERVED
, TOP_RESERVED
, "RESERVED" },
756 { BOTTOM_PRIVATE_USE
, TOP_PRIVATE_USE
, "PRIVATE USE" },
757 { TOP_PRIVATE_USE
+1, 0xffffffff, "This Error Code is not Defined." },
762 // NOLINTNEXTLINE(misc-no-recursion)
763 dissect_payload_kink_error(packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, proto_tree
*tree
){
764 proto_tree
*payload_kink_error_tree
;
766 uint8_t next_payload
;
767 uint16_t payload_length
;
768 int start_payload_offset
= 0; /* Keep the beginning of the payload offset */
770 payload_length
= tvb_get_ntohs(tvb
,offset
+ TO_PAYLOAD_LENGTH
);
771 start_payload_offset
= offset
;
773 /* Make the subtree */
774 payload_kink_error_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, payload_length
,
775 ett_payload_kink_error
, NULL
, "KINK_ERROR");
777 next_payload
= tvb_get_uint8(tvb
, offset
);
778 proto_tree_add_uint(payload_kink_error_tree
, hf_kink_next_payload
, tvb
, offset
, 1, next_payload
);
781 proto_tree_add_item(payload_kink_error_tree
, hf_kink_reserved8
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
784 ti
= proto_tree_add_uint(payload_kink_error_tree
, hf_kink_payload_length
, tvb
, offset
, 2, payload_length
);
785 if(payload_length
!= KINK_ERROR_LENGTH
){
786 expert_add_info(pinfo
, ti
, &ei_kink_payload_length_mismatch
);
790 proto_tree_add_item(payload_kink_error_tree
, hf_kink_error_code
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
792 offset
= start_payload_offset
+ KINK_ERROR_LENGTH
;
793 control_payload(pinfo
, tvb
, offset
, next_payload
, tree
); /* Recur control_payload() */
797 // NOLINTNEXTLINE(misc-no-recursion)
798 dissect_payload_kink_not_defined(packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, proto_tree
*tree
){
799 proto_tree
*payload_kink_not_defined_tree
;
800 uint8_t next_payload
;
801 unsigned payload_length
;
802 int start_payload_offset
= 0; /* Keep the beginning of the payload offset */
804 start_payload_offset
= offset
;
805 payload_length
= tvb_get_ntohs(tvb
, offset
+ TO_PAYLOAD_LENGTH
);
807 /* Make the subtree */
808 payload_kink_not_defined_tree
= proto_tree_add_subtree(tree
, tvb
, offset
, payload_length
,
809 ett_payload_not_defined
, NULL
, "UNKNOWN PAYLOAD");
811 next_payload
= tvb_get_uint8(tvb
, offset
);
812 proto_tree_add_uint(payload_kink_not_defined_tree
, hf_kink_next_payload
, tvb
, offset
, 1, next_payload
);
815 proto_tree_add_item(payload_kink_not_defined_tree
, hf_kink_reserved8
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
818 proto_tree_add_uint(payload_kink_not_defined_tree
, hf_kink_payload_length
, tvb
, offset
, 2, payload_length
);
820 /* This part consider the padding. Payload_length don't contain the padding. */
821 if(payload_length
% PADDING
!= 0){
822 payload_length
+= (PADDING
- (payload_length
% PADDING
));
824 offset
= start_payload_offset
+ payload_length
;
826 /* XXX - prevent an endless loop if payload_length is 0, don't know the correct way to handle this! */
827 if(payload_length
> 0) {
828 control_payload(pinfo
, tvb
, offset
, next_payload
, tree
);
833 kink_fmt_version( char *result
, uint32_t version
)
835 uint8_t major_version
, minor_version
;
837 /* This part is the version. Consider less than 1 octet value.
838 * Major version and minor version is 4bit. Front half of 1octet
839 * is major version, and second half of 1octet is minor version.
840 * The calculation of major version is shown below.
841 * The logical product of the value of 1octet and 0xf0 is performed.
842 * And It is performed 4bit right shift.
843 * Secondarily, the calculation of minor version is shown below.
844 * The logical product of the value of 1octet and 0x0f is performed.
846 major_version
= (uint8_t)((version
& FRONT_FOUR_BIT
) >> VERSION_BIT_SHIFT
);
847 minor_version
= (uint8_t)(version
& SECOND_FOUR_BIT
);
849 snprintf( result
, ITEM_LABEL_LENGTH
, "%d.%02d", major_version
, minor_version
);
854 proto_register_kink(void) {
856 static hf_register_info hf
[] = {
858 { "Type", "kink.type",
859 FT_UINT8
, BASE_DEC
, VALS(kink_type_vals
), 0x0,
862 { "Length", "kink.length",
863 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
865 { &hf_kink_transactionId
,
866 { "Transaction ID", "kink.transactionId",
867 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
869 { &hf_kink_checkSumLength
,
870 { "Checksum Length", "kink.checkSumLength",
871 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
875 FT_UINT8
, BASE_DEC
, VALS(kink_A_vals
), 0x0,
878 { "Version", "kink.version",
879 FT_UINT8
, BASE_CUSTOM
, CF_FUNC(kink_fmt_version
), 0x0,
881 { &hf_kink_domain_of_interpretation
,
882 { "Domain Of Interpretation", "kink.domain_of_interpretation",
883 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
885 { &hf_kink_qmversion
,
886 { "QMVersion", "kink.qmversion",
887 FT_UINT8
, BASE_CUSTOM
, CF_FUNC(kink_fmt_version
), 0x0,
889 { &hf_kink_error_code
,
890 { "ErrorCode", "kink.error_code",
891 FT_UINT32
, BASE_DEC
|BASE_RANGE_STRING
, RVALS(kink_error_rvals
), 0x0,
893 { &hf_kink_reserved8
,
894 { "Reserved", "kink.reserved",
895 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
897 { &hf_kink_reserved15
,
898 { "Reserved", "kink.reserved",
899 FT_UINT16
, BASE_DEC
, NULL
, SECOND_FIFTEEN_BIT
,
901 { &hf_kink_reserved16
,
902 { "Reserved", "kink.reserved",
903 FT_UINT16
, BASE_DEC
, NULL
, 0,
905 { &hf_kink_reserved24
,
906 { "Reserved", "kink.reserved",
907 FT_UINT24
, BASE_DEC
, NULL
, 0,
910 { "Checksum", "kink.checkSum",
911 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
913 { &hf_kink_next_payload
,
914 { "Next Payload", "kink.nextPayload",
915 FT_UINT8
, BASE_DEC
, VALS(kink_next_payload
), 0x0,
917 { &hf_kink_payload_length
,
918 { "Payload Length", "kink.payloadLength",
919 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
922 { "EPOCH", "kink.epoch",
923 FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_UTC
, NULL
, 0x0,
925 { &hf_kink_inner_next_pload
,
926 { "InnerNextPload", "kink.innerNextPload",
927 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
929 { &hf_kink_realm_name_length
,
930 { "RealmNameLength", "kink.realmNameLength",
931 FT_UINT16
, BASE_DEC
, NULL
, 0,
933 { &hf_kink_realm_name
,
934 { "RealmName", "kink.realmName",
935 FT_STRING
, BASE_NONE
, NULL
, 0,
937 { &hf_kink_princ_name_length
,
938 { "PrincNameLength", "kink.princNameLength",
939 FT_UINT16
, BASE_DEC
, NULL
, 0,
941 { &hf_kink_princ_name
,
942 { "PrincName", "kink.princName",
943 FT_STRING
, BASE_NONE
, NULL
, 0,
945 { &hf_kink_tgt_length
,
946 { "TGT Length", "kink.tgtLength",
947 FT_UINT16
, BASE_DEC
, NULL
, 0,
951 FT_STRING
, BASE_NONE
, NULL
, 0,
954 { "Payload", "kink.payload",
955 FT_BYTES
, BASE_NONE
, NULL
, 0,
959 /* Argument for making the subtree. */
960 static int *ett
[] = {
962 /* &ett_kink_version, */
964 &ett_payload_kink_ap_req
,
965 &ett_payload_kink_ap_rep
,
966 &ett_payload_kink_krb_error
,
967 &ett_payload_kink_tgt_req
,
968 &ett_payload_kink_tgt_rep
,
969 &ett_payload_kink_isakmp
,
970 &ett_payload_kink_encrypt
,
971 &ett_payload_kink_error
,
972 &ett_payload_not_defined
,
973 &ett_decrypt_kink_encrypt
,
977 static ei_register_info ei
[] = {
978 { &ei_kink_payload_length_small
, { "kink.payload_length_small", PI_PROTOCOL
, PI_WARN
, "This Payload Length is too small", EXPFILL
}},
979 { &ei_kink_payload_length_mismatch
, { "kink.payload_length_mismatch", PI_PROTOCOL
, PI_WARN
, "This Payload Length is mismatch", EXPFILL
}},
982 expert_module_t
* expert_kink
;
984 proto_kink
= proto_register_protocol("Kerberized Internet Negotiation of Key", "KINK", "kink");
985 proto_register_field_array(proto_kink
, hf
, array_length(hf
));
986 proto_register_subtree_array(ett
, array_length(ett
));
987 expert_kink
= expert_register_protocol(proto_kink
);
988 expert_register_field_array(expert_kink
, ei
, array_length(ei
));
990 kink_handle
= register_dissector("kink", dissect_kink
, proto_kink
);
993 void proto_reg_handoff_kink(void) {
994 // If this is ever streamed (transported over TCP) we need to add recursion checks.
995 dissector_add_uint_with_preference("udp.port", KINK_PORT
, kink_handle
);
999 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1004 * indent-tabs-mode: nil
1007 * ex: set shiftwidth=2 tabstop=8 expandtab:
1008 * :indentSize=2:tabSize=8:noTabs=true: