checkAPIs.pl: support for new-style dissectors in check_hf_entries
[metze/wireshark/wip.git] / epan / dissectors / packet-kink.c
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
4  *
5  * Copyright 2004, Takeshi Nakashima <T.Nakashima@jp.yokogawa.com>
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * SPDX-License-Identifier: GPL-2.0-or-later
12  */
13
14
15 #include "config.h"
16
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"
22
23 void proto_register_kink(void);
24 void proto_reg_handoff_kink(void);
25
26 #define KINK_PORT       57203 /* Not IANA registered */
27
28 #define KINK_ISAKMP_PAYLOAD_BASE 14
29
30 static int proto_kink = -1;
31
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;
58
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;
73
74 static expert_field ei_kink_payload_length_small = EI_INIT;
75 static expert_field ei_kink_payload_length_mismatch = EI_INIT;
76
77
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
86
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"},
95   {0, NULL},
96 };
97
98 /* Define the kink A value */
99 #define KINK_A_NOT_REQUEST_ACK  0
100 #define KINK_A_REQUEST_ACK      1
101
102 static const value_string kink_A_vals[]={
103   {KINK_A_NOT_REQUEST_ACK,"Not Request ACK"},
104   {KINK_A_REQUEST_ACK,"Request ACK"},
105   {0, NULL},
106 };
107
108 /* Define the kink payload */
109 #define KINK_DONE                                0
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
118
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"},
129   {0, NULL},
130 };
131
132 /* Define the magic number
133  * Using at the kink error
134  */
135 #define KINK_OK                   0
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
146
147 /* Using at the kink header */
148 #define IPSEC                     1
149 #define VERSION_BIT_SHIFT         4
150 #define A_BIT_SHIFT               7
151 #define FROM_TYPE_TO_RESERVED    16
152
153 /* Using at the payload */
154 #define TO_PAYLOAD_LENGTH         2
155 #define PADDING                   4
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
163
164
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
170
171 /* decrypt element */
172 static guint32 keytype;
173
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);
184 #ifdef HAVE_KERBEROS
185 static void dissect_decrypt_kink_encrypt(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree, int payload_length);
186 #endif
187
188 /* This function is dissecting the kink header. */
189 static int
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;
193   guint8 type;
194   guint32 doi;
195   guint chsumlen;
196   guint8 next_payload;
197   guint8 value_a_and_front_reserved;
198   guint8 value_a;
199   int offset=0;
200
201   type = tvb_get_guint8(tvb,offset);
202
203   col_set_str(pinfo->cinfo, COL_PROTOCOL, "KINK");
204
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"));
207
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);
211
212   proto_tree_add_uint(kink_tree, hf_kink_type, tvb, offset, 1, type);
213   offset++;
214
215   proto_tree_add_item(kink_tree, hf_kink_version, tvb, offset, 1, ENC_BIG_ENDIAN);
216   offset++;
217
218   proto_tree_add_item(kink_tree, hf_kink_length, tvb, offset, 2, ENC_BIG_ENDIAN);
219   offset += 2;
220
221   doi = tvb_get_ntohl(tvb, offset);
222
223   if(doi == IPSEC){
224     proto_tree_add_uint_format_value(kink_tree, hf_kink_domain_of_interpretation, tvb, offset, 4, doi, "IPsec (%u)", doi);
225   }
226   else{
227     proto_tree_add_uint_format_value(kink_tree, hf_kink_domain_of_interpretation, tvb, offset, 4, doi, "Not IPsec (%u)", doi);
228   }
229   offset += 4;
230
231   proto_tree_add_item(kink_tree, hf_kink_transactionId, tvb, offset, 4,  ENC_BIG_ENDIAN);
232   offset += 4;
233
234   chsumlen = tvb_get_guint8(tvb, offset);
235   proto_tree_add_item(kink_tree, hf_kink_checkSumLength, tvb, offset, 1, ENC_BIG_ENDIAN);
236   offset ++;
237
238   next_payload = tvb_get_guint8(tvb, offset);
239   proto_tree_add_uint(kink_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
240   offset ++;
241
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.
245    */
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);
249
250   /* The reserved field is 15bit.
251    * The logical product of 2octet value and 0x7fff is performed.
252    */
253   proto_tree_add_item(kink_tree, hf_kink_reserved15, tvb, offset, 2, ENC_BIG_ENDIAN);
254   offset += 2;
255
256   proto_tree_add_item(kink_tree, hf_kink_checkSum, tvb, offset, chsumlen, ENC_NA);
257
258   /* This part consider the padding. Chsumlen don't contain the padding. */
259   if((chsumlen % PADDING) != 0){
260     chsumlen += (PADDING - (chsumlen % PADDING));
261     offset += chsumlen;
262   }
263   else{
264     offset += chsumlen;
265   }
266
267   control_payload(pinfo, tvb, offset, next_payload, kink_tree);
268
269   return tvb_captured_length(tvb);
270 }
271
272 /* This part call the dissect payload function by next_payload value.
273  * This function called by the respective function again.
274  */
275 static void
276 control_payload(packet_info *pinfo, tvbuff_t *tvb, int offset, guint8 next_payload, proto_tree *kink_tree){
277   switch(next_payload){
278   case KINK_DONE:
279     break;
280   case KINK_AP_REQ:
281     dissect_payload_kink_ap_req(pinfo, tvb, offset, kink_tree);
282     break;
283   case KINK_AP_REP:
284     dissect_payload_kink_ap_rep(pinfo, tvb, offset, kink_tree);
285     break;
286   case KINK_KRB_ERROR:
287     dissect_payload_kink_krb_error(pinfo, tvb, offset, kink_tree);
288     break;
289   case KINK_TGT_REQ:
290     dissect_payload_kink_tgt_req(pinfo, tvb, offset, kink_tree);
291     break;
292   case KINK_TGT_REP:
293     dissect_payload_kink_tgt_rep(pinfo, tvb, offset, kink_tree);
294     break;
295   case KINK_ISAKMP:
296     dissect_payload_kink_isakmp(pinfo, tvb, offset, kink_tree);
297     break;
298   case KINK_ENCRYPT:
299     dissect_payload_kink_encrypt(pinfo, tvb, offset, kink_tree);
300     break;
301   case KINK_ERROR:
302     dissect_payload_kink_error(pinfo, tvb, offset, kink_tree);
303     break;
304   default:
305     dissect_payload_kink_not_defined(pinfo, tvb, offset, kink_tree);
306     break;
307   }
308 }
309
310 static void
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;
313   proto_item *ti;
314   guint8 next_payload;
315   guint payload_length;
316   guint16 krb_ap_req_length;
317   int start_payload_offset = 0;  /* Keep beginning of payload offset */
318
319   start_payload_offset = offset;
320   payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH);
321
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");
325
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);
328   offset ++;
329
330   proto_tree_add_item(payload_kink_ap_req_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
331   offset ++;
332
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);
336   }
337   offset += 2;
338
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);
341   offset += 4;
342
343   if(payload_length > PAYLOAD_HEADER){
344     tvbuff_t *krb_tvb;
345
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;*/
351   }
352
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));
356   }
357   offset = start_payload_offset + payload_length;
358
359   if(payload_length > 0) {
360     control_payload(pinfo, tvb, offset, next_payload, tree); /* Recur control_payload() */
361   }
362 }
363
364
365 static void
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;
368   proto_item *ti;
369   guint8 next_payload;
370   guint payload_length;
371   guint16 krb_ap_rep_length;
372   int start_payload_offset = 0; /* Keep beginning of payload offset */
373
374   payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH);
375   start_payload_offset = offset;
376
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");
380
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);
383   offset ++;
384
385   proto_tree_add_item(payload_kink_ap_rep_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
386   offset ++;
387
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);
391   }
392   offset += 2;
393
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);
396   offset += 4;
397
398   if(payload_length > PAYLOAD_HEADER){
399     tvbuff_t *krb_tvb;
400
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);
405
406     /*offset += krb_ap_rep_length;*/
407   }
408
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));
412   }
413   offset = start_payload_offset + payload_length;
414
415   if(payload_length > 0) {
416     control_payload(pinfo, tvb, offset, next_payload, tree); /* Recur control_payload() */
417   }
418 }
419
420 static void
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;
423   proto_item *ti;
424   guint8 next_payload;
425   guint payload_length;
426   guint16 krb_error_length;
427   int start_payload_offset = 0; /* Keep the beginning of the payload offset  */
428
429   payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH);
430   start_payload_offset = offset;
431
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");
435
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);
438   offset ++;
439
440   proto_tree_add_item(payload_kink_krb_error_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
441   offset ++;
442
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);
446   }
447   else {
448     offset += 2;
449   }
450
451   if(payload_length > KINK_KRB_ERROR_HEADER){
452     tvbuff_t *krb_tvb;
453
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);
456
457     dissect_kerberos_main(krb_tvb, pinfo, payload_kink_krb_error_tree, FALSE, NULL);
458     /*offset += krb_error_length;*/
459   }
460
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));
464   }
465   offset = start_payload_offset + payload_length;
466
467   if(payload_length > 0) {
468     control_payload(pinfo, tvb, offset, next_payload, tree); /* Recur control_payload() */
469   }
470 }
471
472 static void
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;
475   guint8 next_payload;
476   guint payload_length;
477   guint16 realm_name_length;
478   int start_payload_offset = 0; /* Keep the beginning of the payload offset  */
479
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;
483
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");
487
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);
490   offset ++;
491
492   proto_tree_add_item(payload_kink_tgt_req_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
493   offset ++;
494
495   proto_tree_add_uint(payload_kink_tgt_req_tree, hf_kink_payload_length, tvb, offset, 2, payload_length);
496   offset += 2;
497
498   proto_tree_add_uint(payload_kink_tgt_req_tree, hf_kink_realm_name_length, tvb, offset, 2, realm_name_length);
499   offset += 2;
500
501   proto_tree_add_item(payload_kink_tgt_req_tree, hf_kink_realm_name, tvb, offset, realm_name_length, ENC_NA|ENC_ASCII);
502
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));
506   }
507   offset = start_payload_offset + payload_length;
508
509   if(payload_length > 0) {
510     control_payload(pinfo, tvb, offset, next_payload, tree); /* Recur control_payload() */
511   }
512 }
513
514 static void
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;
517   guint8 next_payload;
518   guint payload_length;
519   guint princ_name_length;
520   guint16 tgt_length;
521   int start_payload_offset = 0; /* Keep the beginning of the payload offset  */
522
523   payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH);
524   start_payload_offset = offset;
525
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");
529
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);
532   offset ++;
533
534   proto_tree_add_item(payload_kink_tgt_rep_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
535   offset ++;
536
537   proto_tree_add_uint(payload_kink_tgt_rep_tree, hf_kink_payload_length, tvb, offset, 2, payload_length);
538   offset += 2;
539
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);
542   offset += 2;
543
544   proto_tree_add_item(payload_kink_tgt_rep_tree, hf_kink_princ_name, tvb, offset, princ_name_length, ENC_NA|ENC_ASCII);
545
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));
549   }
550   else{
551     offset += princ_name_length;
552   }
553
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);
556   offset += 2;
557
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;*/
560
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));
564   }
565   offset = start_payload_offset + payload_length;
566
567   if(payload_length > 0) {
568     control_payload(pinfo, tvb, offset, next_payload, tree); /* Recur control_payload() */
569   }
570 }
571
572 static void
573 dissect_payload_kink_isakmp(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
574   proto_tree *payload_kink_isakmp_tree;
575   proto_item *ti;
576   guint8 next_payload;
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;
582
583   payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH);
584   start_payload_offset = offset;
585
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");
589
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);
592   offset ++;
593
594   proto_tree_add_item(payload_kink_isakmp_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
595   offset ++;
596
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);
600   }
601   offset += 2;
602
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);
605   offset += 1;
606
607   proto_tree_add_item(payload_kink_isakmp_tree, hf_kink_qmversion, tvb, offset, 1, ENC_BIG_ENDIAN);
608   offset += 1;
609
610   proto_tree_add_item(payload_kink_isakmp_tree, hf_kink_reserved16, tvb, offset, 2, ENC_BIG_ENDIAN);
611   offset += 2;
612
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);
623   }
624
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));
628   }
629   offset = start_payload_offset + payload_length;
630
631   if(payload_length > 0) {
632     control_payload(pinfo, tvb, offset, next_payload, tree);  /* Recur control_payload() */
633   }
634 }
635
636 static void
637 dissect_payload_kink_encrypt(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
638   proto_tree *payload_kink_encrypt_tree;
639   proto_item *ti;
640   guint8 next_payload;
641   guint payload_length;
642 #ifdef HAVE_KERBEROS
643   gint encrypt_length;
644 #endif
645   guint8 inner_next_pload;
646   guint16 inner_payload_length;
647   int start_payload_offset = 0;    /* Keep the beginning of the payload offset */
648
649   payload_length = tvb_get_ntohs(tvb,offset + TO_PAYLOAD_LENGTH);
650   start_payload_offset = offset;
651
652 #ifdef HAVE_KERBEROS
653   encrypt_length = payload_length - FROM_NP_TO_PL;
654 #endif
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");
658
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);
661   offset ++;
662
663   proto_tree_add_item(payload_kink_encrypt_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
664   offset ++;
665
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);
669   }
670   offset += 2;
671
672   /* decrypt kink encrypt */
673
674   if(keytype != 0){
675 #ifdef HAVE_KERBEROS
676     tvbuff_t *next_tvb;
677     guint8 *plaintext=NULL;
678
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);
681     if(plaintext){
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);
685     }
686 #endif
687   }
688   else{
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);
691     offset += 1;
692
693     proto_tree_add_item(payload_kink_encrypt_tree, hf_kink_reserved24, tvb, offset, 3, ENC_BIG_ENDIAN);
694     offset += 3;
695
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;*/
700     }
701   }
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));
705   }
706   offset = start_payload_offset + payload_length;
707
708   if(payload_length > 0) {
709     control_payload(pinfo, tvb, offset, next_payload, tree);  /* Recur control_payload() */
710   }
711 }
712
713 #ifdef HAVE_KERBEROS
714 static void
715 dissect_decrypt_kink_encrypt(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree, int payload_length){
716
717   proto_tree *decrypt_kink_encrypt_tree;
718   int offset=0;
719   guint8 next_payload;
720
721   decrypt_kink_encrypt_tree = proto_tree_add_subtree(tree, tvb, offset, payload_length,
722                                     ett_decrypt_kink_encrypt, NULL, "decrypted data");
723
724   next_payload = tvb_get_guint8(tvb, offset);
725
726   proto_tree_add_uint(decrypt_kink_encrypt_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
727   offset ++;
728
729   proto_tree_add_item(decrypt_kink_encrypt_tree, hf_kink_reserved24, tvb, offset, 3, ENC_BIG_ENDIAN);
730   offset += 3;
731
732   control_payload(pinfo, tvb, offset, next_payload, decrypt_kink_encrypt_tree);
733 }
734 #endif
735
736 static const range_string kink_error_rvals[] = {
737     { 0, 0,  "KINK_OK" },
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." },
747     { 0, 0, NULL }
748 };
749
750 static void
751 dissect_payload_kink_error(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
752   proto_tree *payload_kink_error_tree;
753   proto_item *ti;
754   guint8 next_payload;
755   guint16 payload_length;
756   int start_payload_offset = 0; /* Keep the beginning of the payload offset */
757
758   payload_length = tvb_get_ntohs(tvb,offset + TO_PAYLOAD_LENGTH);
759   start_payload_offset = offset;
760
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");
764
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);
767   offset ++;
768
769   proto_tree_add_item(payload_kink_error_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
770   offset ++;
771
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);
775   }
776   offset += 2;
777
778   proto_tree_add_item(payload_kink_error_tree, hf_kink_error_code, tvb, offset, 4, ENC_BIG_ENDIAN);
779
780   offset = start_payload_offset + KINK_ERROR_LENGTH;
781   control_payload(pinfo, tvb, offset, next_payload, tree);  /* Recur control_payload() */
782 }
783
784 static void
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;
787   guint8 next_payload;
788   guint payload_length;
789   int start_payload_offset = 0;   /* Keep the beginning of the payload offset */
790
791   start_payload_offset = offset;
792   payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH);
793
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");
797
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);
800   offset ++;
801
802   proto_tree_add_item(payload_kink_not_defined_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
803   offset ++;
804
805   proto_tree_add_uint(payload_kink_not_defined_tree, hf_kink_payload_length, tvb, offset, 2, payload_length);
806
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));
810   }
811   offset = start_payload_offset + payload_length;
812
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);
816   }
817 }
818
819 static void
820 kink_fmt_version( gchar *result, guint32 version )
821 {
822   guint8 major_version, minor_version;
823
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.
832    */
833   major_version = (guint8)((version & FRONT_FOUR_BIT) >> VERSION_BIT_SHIFT);
834   minor_version = (guint8)(version & SECOND_FOUR_BIT);
835
836   g_snprintf( result, ITEM_LABEL_LENGTH, "%d.%02d", major_version, minor_version);
837 }
838
839 /* Output part */
840 void
841 proto_register_kink(void) {
842
843   static hf_register_info hf[] = {
844     { &hf_kink_type,
845       { "Type", "kink.type",
846         FT_UINT8,       BASE_DEC,       VALS(kink_type_vals),   0x0,
847         NULL, HFILL }},
848     { &hf_kink_length,
849       { "Length",       "kink.length",
850         FT_UINT16,      BASE_DEC,       NULL,   0x0,
851         NULL, HFILL }},
852     { &hf_kink_transactionId,
853       { "Transaction ID",       "kink.transactionId",
854         FT_UINT32,      BASE_DEC,       NULL,   0x0,
855         NULL, HFILL }},
856     { &hf_kink_checkSumLength,
857       { "Checksum Length",       "kink.checkSumLength",
858         FT_UINT8,       BASE_DEC,       NULL,   0x0,
859         NULL, HFILL }},
860     { &hf_kink_A,
861       { "A",       "kink.A",
862         FT_UINT8,       BASE_DEC,       VALS(kink_A_vals),      0x0,
863         NULL, HFILL }},
864     { &hf_kink_version,
865       { "Version",       "kink.version",
866         FT_UINT8,       BASE_CUSTOM,       CF_FUNC(kink_fmt_version),      0x0,
867         NULL, HFILL }},
868     { &hf_kink_domain_of_interpretation,
869       { "Domain Of Interpretation",       "kink.domain_of_interpretation",
870         FT_UINT32,      BASE_DEC,       NULL,   0x0,
871         NULL, HFILL }},
872     { &hf_kink_qmversion,
873       { "QMVersion",       "kink.qmversion",
874         FT_UINT8,       BASE_CUSTOM,       CF_FUNC(kink_fmt_version),      0x0,
875         NULL, HFILL }},
876     { &hf_kink_error_code,
877       { "ErrorCode",       "kink.error_code",
878         FT_UINT32,      BASE_DEC|BASE_RANGE_STRING,       RVALS(kink_error_rvals),   0x0,
879         NULL, HFILL }},
880     { &hf_kink_reserved8,
881       { "Reserved",       "kink.reserved",
882         FT_UINT8,      BASE_DEC,       NULL,   0x0,
883         NULL, HFILL }},
884     { &hf_kink_reserved15,
885       { "Reserved",       "kink.reserved",
886         FT_UINT16,      BASE_DEC,       NULL,   SECOND_FIFTEEN_BIT,
887         NULL, HFILL }},
888     { &hf_kink_reserved16,
889       { "Reserved",       "kink.reserved",
890         FT_UINT16,      BASE_DEC,       NULL,   0,
891         NULL, HFILL }},
892     { &hf_kink_reserved24,
893       { "Reserved",       "kink.reserved",
894         FT_UINT24,      BASE_DEC,       NULL,   0,
895         NULL, HFILL }},
896     { &hf_kink_checkSum,
897       { "Checksum",       "kink.checkSum",
898         FT_BYTES,       BASE_NONE,      NULL,   0x0,
899         NULL, HFILL }},
900     { &hf_kink_next_payload,
901       { "Next Payload",       "kink.nextPayload",
902         FT_UINT8,       BASE_DEC,       VALS(kink_next_payload),        0x0,
903         NULL, HFILL }},
904     { &hf_kink_payload_length,
905       { "Payload Length",       "kink.payloadLength",
906         FT_UINT8,       BASE_DEC,       NULL,        0x0,
907         NULL, HFILL }},
908     { &hf_kink_epoch,
909       { "EPOCH",       "kink.epoch",
910         FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC,       NULL,        0x0,
911         NULL, HFILL }},
912     { &hf_kink_inner_next_pload,
913       { "InnerNextPload",       "kink.innerNextPload",
914         FT_UINT8,       BASE_DEC,       NULL,        0x0,
915         NULL, HFILL }},
916     { &hf_kink_realm_name_length,
917       { "RealmNameLength",       "kink.realmNameLength",
918         FT_UINT16,      BASE_DEC,       NULL,   0,
919         NULL, HFILL }},
920     { &hf_kink_realm_name,
921       { "RealmName",       "kink.realmName",
922         FT_STRING,      BASE_NONE,       NULL,   0,
923         NULL, HFILL }},
924     { &hf_kink_princ_name_length,
925       { "PrincNameLength",       "kink.princNameLength",
926         FT_UINT16,      BASE_DEC,       NULL,   0,
927         NULL, HFILL }},
928     { &hf_kink_princ_name,
929       { "PrincName",       "kink.princName",
930         FT_STRING,      BASE_NONE,       NULL,   0,
931         NULL, HFILL }},
932     { &hf_kink_tgt_length,
933       { "TGT Length",       "kink.tgtLength",
934         FT_UINT16,      BASE_DEC,       NULL,   0,
935         NULL, HFILL }},
936     { &hf_kink_tgt,
937       { "TGT",       "kink.tgt",
938         FT_STRING,      BASE_NONE,       NULL,   0,
939         NULL, HFILL }},
940     { &hf_kink_payload,
941       { "Payload",       "kink.payload",
942         FT_BYTES,      BASE_NONE,       NULL,   0,
943         NULL, HFILL }},
944   };
945
946   /* Argument for making the subtree. */
947   static gint *ett[] = {
948     &ett_kink,
949     /*    &ett_kink_version, */
950     &ett_kink_payload,
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,
961
962   };
963
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 }},
967   };
968
969   expert_module_t* expert_kink;
970
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));
976
977 }
978
979 void proto_reg_handoff_kink(void) {
980
981   dissector_handle_t kink_handle;
982
983   kink_handle = create_dissector_handle(dissect_kink, proto_kink);
984
985   dissector_add_uint_with_preference("udp.port", KINK_PORT, kink_handle);
986
987 }
988
989 /*
990  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
991  *
992  * Local Variables:
993  * c-basic-offset: 2
994  * tab-width: 8
995  * indent-tabs-mode: nil
996  * End:
997  *
998  * ex: set shiftwidth=2 tabstop=8 expandtab:
999  * :indentSize=2:tabSize=8:noTabs=true:
1000  */