epan/dissectors/pidl/ C99 drsuapi
[wireshark-sm.git] / epan / dissectors / packet-kink.c
blob7ab4628b3c316f214367865b9cecdec7d5434ff6
1 /* packet-kink.c
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
15 #include "config.h"
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;
28 #define KINK_PORT 910
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;
39 static int hf_kink_A;
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 */
62 static int ett_kink;
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"},
97 {0, NULL},
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"},
107 {0, NULL},
110 /* Define the kink payload */
111 #define KINK_DONE 0
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"},
131 {0, NULL},
134 /* Define the magic number
135 * Using at the kink error
137 #define KINK_OK 0
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 */
150 #define IPSEC 1
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
157 #define PADDING 4
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);
186 #ifdef HAVE_KERBEROS
187 static void dissect_decrypt_kink_encrypt(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree, int payload_length);
188 #endif
190 /* This function is dissecting the kink header. */
191 static int
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;
195 uint8_t type;
196 uint32_t doi;
197 unsigned chsumlen;
198 uint8_t next_payload;
199 uint8_t value_a_and_front_reserved;
200 uint8_t value_a;
201 int offset=0;
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);
215 offset++;
217 proto_tree_add_item(kink_tree, hf_kink_version, tvb, offset, 1, ENC_BIG_ENDIAN);
218 offset++;
220 proto_tree_add_item(kink_tree, hf_kink_length, tvb, offset, 2, ENC_BIG_ENDIAN);
221 offset += 2;
223 doi = tvb_get_ntohl(tvb, offset);
225 if(doi == IPSEC){
226 proto_tree_add_uint_format_value(kink_tree, hf_kink_domain_of_interpretation, tvb, offset, 4, doi, "IPsec (%u)", doi);
228 else{
229 proto_tree_add_uint_format_value(kink_tree, hf_kink_domain_of_interpretation, tvb, offset, 4, doi, "Not IPsec (%u)", doi);
231 offset += 4;
233 proto_tree_add_item(kink_tree, hf_kink_transactionId, tvb, offset, 4, ENC_BIG_ENDIAN);
234 offset += 4;
236 chsumlen = tvb_get_uint8(tvb, offset);
237 proto_tree_add_item(kink_tree, hf_kink_checkSumLength, tvb, offset, 1, ENC_BIG_ENDIAN);
238 offset ++;
240 next_payload = tvb_get_uint8(tvb, offset);
241 proto_tree_add_uint(kink_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
242 offset ++;
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);
256 offset += 2;
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));
263 offset += chsumlen;
265 else{
266 offset += chsumlen;
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.
277 static void
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){
281 case KINK_DONE:
282 break;
283 case KINK_AP_REQ:
284 dissect_payload_kink_ap_req(pinfo, tvb, offset, kink_tree);
285 break;
286 case KINK_AP_REP:
287 dissect_payload_kink_ap_rep(pinfo, tvb, offset, kink_tree);
288 break;
289 case KINK_KRB_ERROR:
290 dissect_payload_kink_krb_error(pinfo, tvb, offset, kink_tree);
291 break;
292 case KINK_TGT_REQ:
293 dissect_payload_kink_tgt_req(pinfo, tvb, offset, kink_tree);
294 break;
295 case KINK_TGT_REP:
296 dissect_payload_kink_tgt_rep(pinfo, tvb, offset, kink_tree);
297 break;
298 case KINK_ISAKMP:
299 dissect_payload_kink_isakmp(pinfo, tvb, offset, kink_tree);
300 break;
301 case KINK_ENCRYPT:
302 dissect_payload_kink_encrypt(pinfo, tvb, offset, kink_tree);
303 break;
304 case KINK_ERROR:
305 dissect_payload_kink_error(pinfo, tvb, offset, kink_tree);
306 break;
307 default:
308 dissect_payload_kink_not_defined(pinfo, tvb, offset, kink_tree);
309 break;
313 static void
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;
317 proto_item *ti;
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);
332 offset ++;
334 proto_tree_add_item(payload_kink_ap_req_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
335 offset ++;
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);
341 offset += 2;
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);
345 offset += 4;
347 if(payload_length > PAYLOAD_HEADER){
348 tvbuff_t *krb_tvb;
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() */
369 static void
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;
373 proto_item *ti;
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);
388 offset ++;
390 proto_tree_add_item(payload_kink_ap_rep_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
391 offset ++;
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);
397 offset += 2;
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);
401 offset += 4;
403 if(payload_length > PAYLOAD_HEADER){
404 tvbuff_t *krb_tvb;
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() */
425 static void
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;
429 proto_item *ti;
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);
444 offset ++;
446 proto_tree_add_item(payload_kink_krb_error_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
447 offset ++;
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);
453 else {
454 offset += 2;
457 if(payload_length > KINK_KRB_ERROR_HEADER){
458 tvbuff_t *krb_tvb;
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() */
478 static void
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);
497 offset ++;
499 proto_tree_add_item(payload_kink_tgt_req_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
500 offset ++;
502 proto_tree_add_uint(payload_kink_tgt_req_tree, hf_kink_payload_length, tvb, offset, 2, payload_length);
503 offset += 2;
505 proto_tree_add_uint(payload_kink_tgt_req_tree, hf_kink_realm_name_length, tvb, offset, 2, realm_name_length);
506 offset += 2;
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() */
521 static void
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;
528 uint16_t tgt_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);
540 offset ++;
542 proto_tree_add_item(payload_kink_tgt_rep_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
543 offset ++;
545 proto_tree_add_uint(payload_kink_tgt_rep_tree, hf_kink_payload_length, tvb, offset, 2, payload_length);
546 offset += 2;
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);
550 offset += 2;
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));
558 else{
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);
564 offset += 2;
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() */
580 static void
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;
584 proto_item *ti;
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);
601 offset ++;
603 proto_tree_add_item(payload_kink_isakmp_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
604 offset ++;
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);
610 offset += 2;
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);
614 offset += 1;
616 proto_tree_add_item(payload_kink_isakmp_tree, hf_kink_qmversion, tvb, offset, 1, ENC_BIG_ENDIAN);
617 offset += 1;
619 proto_tree_add_item(payload_kink_isakmp_tree, hf_kink_reserved16, tvb, offset, 2, ENC_BIG_ENDIAN);
620 offset += 2;
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() */
645 static void
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;
649 proto_item *ti;
650 uint8_t next_payload;
651 unsigned payload_length;
652 #ifdef HAVE_KERBEROS
653 int encrypt_length;
654 #endif
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;
662 #ifdef HAVE_KERBEROS
663 encrypt_length = payload_length - FROM_NP_TO_PL;
664 #endif
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);
671 offset ++;
673 proto_tree_add_item(payload_kink_encrypt_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
674 offset ++;
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);
680 offset += 2;
682 /* decrypt kink encrypt */
684 if(keytype != 0){
685 #ifdef HAVE_KERBEROS
686 tvbuff_t *next_tvb;
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);
691 if(plaintext){
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);
696 #endif
698 else{
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);
701 offset += 1;
703 proto_tree_add_item(payload_kink_encrypt_tree, hf_kink_reserved24, tvb, offset, 3, ENC_BIG_ENDIAN);
704 offset += 3;
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() */
723 #ifdef HAVE_KERBEROS
724 static void
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;
729 int offset=0;
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);
738 offset ++;
740 proto_tree_add_item(decrypt_kink_encrypt_tree, hf_kink_reserved24, tvb, offset, 3, ENC_BIG_ENDIAN);
741 offset += 3;
743 control_payload(pinfo, tvb, offset, next_payload, decrypt_kink_encrypt_tree);
745 #endif
747 static const range_string kink_error_rvals[] = {
748 { 0, 0, "KINK_OK" },
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." },
758 { 0, 0, NULL }
761 static void
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;
765 proto_item *ti;
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);
779 offset ++;
781 proto_tree_add_item(payload_kink_error_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
782 offset ++;
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);
788 offset += 2;
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() */
796 static void
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);
813 offset ++;
815 proto_tree_add_item(payload_kink_not_defined_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
816 offset ++;
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);
832 static void
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);
852 /* Output part */
853 void
854 proto_register_kink(void) {
856 static hf_register_info hf[] = {
857 { &hf_kink_type,
858 { "Type", "kink.type",
859 FT_UINT8, BASE_DEC, VALS(kink_type_vals), 0x0,
860 NULL, HFILL }},
861 { &hf_kink_length,
862 { "Length", "kink.length",
863 FT_UINT16, BASE_DEC, NULL, 0x0,
864 NULL, HFILL }},
865 { &hf_kink_transactionId,
866 { "Transaction ID", "kink.transactionId",
867 FT_UINT32, BASE_DEC, NULL, 0x0,
868 NULL, HFILL }},
869 { &hf_kink_checkSumLength,
870 { "Checksum Length", "kink.checkSumLength",
871 FT_UINT8, BASE_DEC, NULL, 0x0,
872 NULL, HFILL }},
873 { &hf_kink_A,
874 { "A", "kink.A",
875 FT_UINT8, BASE_DEC, VALS(kink_A_vals), 0x0,
876 NULL, HFILL }},
877 { &hf_kink_version,
878 { "Version", "kink.version",
879 FT_UINT8, BASE_CUSTOM, CF_FUNC(kink_fmt_version), 0x0,
880 NULL, HFILL }},
881 { &hf_kink_domain_of_interpretation,
882 { "Domain Of Interpretation", "kink.domain_of_interpretation",
883 FT_UINT32, BASE_DEC, NULL, 0x0,
884 NULL, HFILL }},
885 { &hf_kink_qmversion,
886 { "QMVersion", "kink.qmversion",
887 FT_UINT8, BASE_CUSTOM, CF_FUNC(kink_fmt_version), 0x0,
888 NULL, HFILL }},
889 { &hf_kink_error_code,
890 { "ErrorCode", "kink.error_code",
891 FT_UINT32, BASE_DEC|BASE_RANGE_STRING, RVALS(kink_error_rvals), 0x0,
892 NULL, HFILL }},
893 { &hf_kink_reserved8,
894 { "Reserved", "kink.reserved",
895 FT_UINT8, BASE_DEC, NULL, 0x0,
896 NULL, HFILL }},
897 { &hf_kink_reserved15,
898 { "Reserved", "kink.reserved",
899 FT_UINT16, BASE_DEC, NULL, SECOND_FIFTEEN_BIT,
900 NULL, HFILL }},
901 { &hf_kink_reserved16,
902 { "Reserved", "kink.reserved",
903 FT_UINT16, BASE_DEC, NULL, 0,
904 NULL, HFILL }},
905 { &hf_kink_reserved24,
906 { "Reserved", "kink.reserved",
907 FT_UINT24, BASE_DEC, NULL, 0,
908 NULL, HFILL }},
909 { &hf_kink_checkSum,
910 { "Checksum", "kink.checkSum",
911 FT_BYTES, BASE_NONE, NULL, 0x0,
912 NULL, HFILL }},
913 { &hf_kink_next_payload,
914 { "Next Payload", "kink.nextPayload",
915 FT_UINT8, BASE_DEC, VALS(kink_next_payload), 0x0,
916 NULL, HFILL }},
917 { &hf_kink_payload_length,
918 { "Payload Length", "kink.payloadLength",
919 FT_UINT16, BASE_DEC, NULL, 0x0,
920 NULL, HFILL }},
921 { &hf_kink_epoch,
922 { "EPOCH", "kink.epoch",
923 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0x0,
924 NULL, HFILL }},
925 { &hf_kink_inner_next_pload,
926 { "InnerNextPload", "kink.innerNextPload",
927 FT_UINT8, BASE_DEC, NULL, 0x0,
928 NULL, HFILL }},
929 { &hf_kink_realm_name_length,
930 { "RealmNameLength", "kink.realmNameLength",
931 FT_UINT16, BASE_DEC, NULL, 0,
932 NULL, HFILL }},
933 { &hf_kink_realm_name,
934 { "RealmName", "kink.realmName",
935 FT_STRING, BASE_NONE, NULL, 0,
936 NULL, HFILL }},
937 { &hf_kink_princ_name_length,
938 { "PrincNameLength", "kink.princNameLength",
939 FT_UINT16, BASE_DEC, NULL, 0,
940 NULL, HFILL }},
941 { &hf_kink_princ_name,
942 { "PrincName", "kink.princName",
943 FT_STRING, BASE_NONE, NULL, 0,
944 NULL, HFILL }},
945 { &hf_kink_tgt_length,
946 { "TGT Length", "kink.tgtLength",
947 FT_UINT16, BASE_DEC, NULL, 0,
948 NULL, HFILL }},
949 { &hf_kink_tgt,
950 { "TGT", "kink.tgt",
951 FT_STRING, BASE_NONE, NULL, 0,
952 NULL, HFILL }},
953 { &hf_kink_payload,
954 { "Payload", "kink.payload",
955 FT_BYTES, BASE_NONE, NULL, 0,
956 NULL, HFILL }},
959 /* Argument for making the subtree. */
960 static int *ett[] = {
961 &ett_kink,
962 /* &ett_kink_version, */
963 &ett_kink_payload,
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
1001 * Local Variables:
1002 * c-basic-offset: 2
1003 * tab-width: 8
1004 * indent-tabs-mode: nil
1005 * End:
1007 * ex: set shiftwidth=2 tabstop=8 expandtab:
1008 * :indentSize=2:tabSize=8:noTabs=true: