Update Free Software Foundation address.
[metze/wireshark/wip.git] / epan / dissectors / packet-kink.c
1 /* packet-kink.c
2  * Routines for KINK packet disassembly
3  * It is referrenced 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  * $Id$
8  *
9  * Wireshark - Network traffic analyzer
10  * By Gerald Combs <gerald@wireshark.org>
11  * Copyright 1998 Gerald Combs
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26  */
27
28
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32
33 #include <glib.h>
34 #include <epan/packet.h>
35 #include <epan/asn1.h>
36 #include "packet-kerberos.h"
37 #include "packet-isakmp.h"
38
39 #define KINK_PORT       57203
40
41 #define KINK_ISAKMP_PAYLOAD_BASE 14
42
43 static int proto_kink = -1;
44
45 /* Argument for proto_tree_add_uint() */
46 static int hf_kink_type = -1;
47 static int hf_kink_length = -1;
48 static int hf_kink_transactionId = -1;
49 static int hf_kink_checkSumLength = -1;
50 static int hf_kink_A = -1;
51 static int hf_kink_reserved = -1;
52 static int hf_kink_checkSum = -1;
53 static int hf_kink_next_payload = -1;
54
55 /* Argument for making the subtree */
56 static gint ett_kink = -1;
57 /*static gint ett_kink_version = -1;*/
58 static gint ett_kink_payload = -1;
59 static gint ett_payload_kink_ap_req = -1;
60 static gint ett_payload_kink_ap_rep = -1;
61 static gint ett_payload_kink_krb_error = -1;
62 static gint ett_payload_kink_tgt_req = -1;
63 static gint ett_payload_kink_tgt_rep = -1;
64 static gint ett_payload_kink_isakmp = -1;
65 static gint ett_payload_kink_encrypt = -1;
66 static gint ett_payload_kink_error = -1;
67 static gint ett_payload_not_defined = -1;
68 static gint ett_decrypt_kink_encrypt = -1;
69
70 /* Define the kink type value */
71 #define KINK_TYPE_RESERVED 0
72 #define KINK_TYPE_CREATE   1
73 #define KINK_TYPE_DELETE   2
74 #define KINK_TYPE_REPLY    3
75 #define KINK_TYPE_GETTGT   4
76 #define KINK_TYPE_ACK      5
77 #define KINK_TYPE_STATUS   6
78
79 static const value_string kink_type_vals[]={
80   {KINK_TYPE_RESERVED,"RESERVED"},
81   {KINK_TYPE_CREATE,"CREATE"},
82   {KINK_TYPE_DELETE,"DELETE"},
83   {KINK_TYPE_REPLY,"REPLY"},
84   {KINK_TYPE_GETTGT,"GETTGT"},
85   {KINK_TYPE_ACK,"ACK"},
86   {KINK_TYPE_STATUS,"STATUS"},
87   {0, NULL},
88 };
89
90 /* Define the kink A value */
91 #define KINK_A_NOT_REQUEST_ACK  0
92 #define KINK_A_REQUEST_ACK      1
93
94 static const value_string kink_A_vals[]={
95   {KINK_A_NOT_REQUEST_ACK,"Not Request ACK"},
96   {KINK_A_REQUEST_ACK,"Request ACK"},
97   {0, NULL},
98 };
99
100 /* Define the kink payload */
101 #define KINK_DONE                                0
102 #define KINK_AP_REQ     KINK_ISAKMP_PAYLOAD_BASE+0
103 #define KINK_AP_REP     KINK_ISAKMP_PAYLOAD_BASE+1
104 #define KINK_KRB_ERROR  KINK_ISAKMP_PAYLOAD_BASE+2
105 #define KINK_TGT_REQ    KINK_ISAKMP_PAYLOAD_BASE+3
106 #define KINK_TGT_REP    KINK_ISAKMP_PAYLOAD_BASE+4
107 #define KINK_ISAKMP     KINK_ISAKMP_PAYLOAD_BASE+5
108 #define KINK_ENCRYPT    KINK_ISAKMP_PAYLOAD_BASE+6
109 #define KINK_ERROR      KINK_ISAKMP_PAYLOAD_BASE+7
110
111 static const value_string kink_next_payload[]={
112   {KINK_DONE, "KINK_DONE"},
113   {KINK_AP_REQ, "KINK_AP_REQ"},
114   {KINK_AP_REP, "KINK_AP_REP"},
115   {KINK_KRB_ERROR, "KINK_KRB_ERROR"},
116   {KINK_TGT_REQ, "KINK_TGT_REQ"},
117   {KINK_TGT_REP, "KINK_TGT_REP"},
118   {KINK_ISAKMP, "KINK_ISAKMP"},
119   {KINK_ENCRYPT, "KINK_ENCRYPT"},
120   {KINK_ERROR, "KINK_ERROR"},
121   {0, NULL},
122 };
123
124 /* Define the magic number
125  * Using at the kink error
126  */
127 #define KINK_OK                   0
128 #define KINK_PROTOERR             1
129 #define KINK_INVDOI               2
130 #define KINK_INVMAJ               3
131 #define KINK_INVMIN               4
132 #define KINK_INTERR               5
133 #define KINK_BADQMVERS            6
134 #define BOTTOM_RESERVED           7
135 #define TOP_RESERVED           8191
136 #define BOTTOM_PRIVATE_USE     8192
137 #define TOP_PRIVATE_USE       16383
138
139 /* Using at the kink header */
140 #define IPSEC                     1
141 #define VERSION_BIT_SHIFT         4
142 #define A_BIT_SHIFT               7
143 #define FROM_TYPE_TO_RESERVED    16
144
145 /* Using at the payload */
146 #define TO_PAYLOAD_LENGTH         2
147 #define PADDING                   4
148 #define KINK_KRB_ERROR_HEADER     4
149 #define FROM_NP_TO_PL             4
150 #define TO_REALM_NAME_LENGTH      4
151 #define KINK_TGT_REQ_HEADER       6
152 #define FRONT_TGT_REP_HEADER      6
153 #define PAYLOAD_HEADER            8
154 #define KINK_ERROR_LENGTH         8
155
156
157 /* define hexadecimal */
158 #define FRONT_FOUR_BIT         0xf0
159 #define SECOND_FOUR_BIT        0x0f
160 #define FRONT_ONE_BIT          0x80
161 #define SECOND_FIFTEEN_BIT   0x7fff
162
163 /* decrypt element */
164 static guint32 keytype;
165
166 static void control_payload(packet_info *pinfo, tvbuff_t *tvb, int offset, guint8 next_payload, proto_tree *kink_payload_tree);
167 static void dissect_payload_kink_ap_req(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
168 static void dissect_payload_kink_ap_rep(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
169 static void dissect_payload_kink_krb_error(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
170 static void dissect_payload_kink_tgt_req(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
171 static void dissect_payload_kink_tgt_rep(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
172 static void dissect_payload_kink_isakmp(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
173 static void dissect_payload_kink_encrypt(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
174 static void dissect_payload_kink_error(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
175 static void dissect_payload_kink_not_defined(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
176 #ifdef HAVE_KERBEROS
177 static void dissect_decrypt_kink_encrypt(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree, int payload_length);
178 #endif
179
180 /* This function is dissecting the kink header. */
181 static void
182 dissect_kink(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree){
183   proto_item *ti = NULL;
184   proto_tree *kink_tree = NULL;
185   guint8 type;
186   guint8 major_version, minor_version, version;
187   guint32 doi;
188   guint chsumlen;
189   guint8 next_payload;
190   guint8 value_a_and_front_reserved;
191   guint16 value_a_and_reserved;
192   guint8 value_a;
193   guint16 value_reserved;
194   int offset=0;
195
196   type = tvb_get_guint8(tvb,offset);
197
198   col_set_str(pinfo->cinfo, COL_PROTOCOL, "KINK");
199
200   /* It shows kink type by the type value. */
201   if(check_col(pinfo->cinfo, COL_INFO)){
202     col_add_str(pinfo->cinfo, COL_INFO,  val_to_str(type, kink_type_vals, "unknown"));
203   }
204   /* Make the kink tree */
205   if(tree){
206     ti = proto_tree_add_item(tree, proto_kink, tvb, offset, -1, ENC_NA);
207     kink_tree = proto_item_add_subtree(ti, ett_kink);
208   }
209
210   proto_tree_add_uint(kink_tree, hf_kink_type, tvb, offset, 1, type);
211   offset++;
212
213   /* This part is the version. Consider less than 1 octet value.
214    * Major version and minor version is 4bit. Front half of 1octet
215    * is major version, and second half of 1octet is minor version.
216    * The calculation of major version is shown below.
217    * The logical product of the value of 1octet and 0xf0 is performed.
218    * And It is performed 4bit right shift.
219    * Secondarily, the calculation of minor version is shown below.
220    * The logical product of the value of 1octet and 0x0f is performed.
221    */
222   version = tvb_get_guint8(tvb,offset);
223   major_version = (version & FRONT_FOUR_BIT) >> VERSION_BIT_SHIFT;
224   minor_version = version & SECOND_FOUR_BIT;
225   proto_tree_add_text(kink_tree, tvb, offset, 1, "version: %u.%u", major_version, minor_version);
226   offset++;
227
228   proto_tree_add_item(kink_tree, hf_kink_length, tvb, offset, 2, ENC_BIG_ENDIAN);
229   offset += 2;
230
231   doi = tvb_get_ntohl(tvb, offset);
232
233   if(doi == IPSEC){
234     proto_tree_add_text(kink_tree, tvb, offset, 4, "Domain Of Interpretation: %s (%u)", "IPsec", doi);
235   }
236   else{
237     proto_tree_add_text(kink_tree, tvb, offset, 4, "Domain Of Interpretation: %s (%u)", "Not IPsec", doi);
238   }
239   offset += 4;
240
241   proto_tree_add_item(kink_tree, hf_kink_transactionId, tvb, offset, 4,  ENC_BIG_ENDIAN);
242   offset += 4;
243
244   chsumlen = tvb_get_guint8(tvb, offset);
245   proto_tree_add_item(kink_tree, hf_kink_checkSumLength, tvb, offset, 1, ENC_BIG_ENDIAN);
246   offset ++;
247
248   next_payload = tvb_get_guint8(tvb, offset);
249   proto_tree_add_uint(kink_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
250   offset ++;
251
252   /* A is 1bit field. The caluculation of A is shown below.
253    * The logical product of 1octet value and 0x80 is performed.
254    * And It is performed 7bit right shift.
255    */
256   value_a_and_front_reserved = tvb_get_guint8(tvb, offset);
257   value_a = (value_a_and_front_reserved & FRONT_ONE_BIT) >> A_BIT_SHIFT;
258   proto_tree_add_uint(kink_tree, hf_kink_A, tvb, offset, 1, value_a);
259
260   /* The reserved field is 15bit.
261    * The logical product of 2octet value and 0x7fff is performed.
262    */
263   value_a_and_reserved = tvb_get_ntohs(tvb, offset);
264   value_reserved = value_a_and_reserved & SECOND_FIFTEEN_BIT;
265   proto_tree_add_uint(kink_tree, hf_kink_reserved, tvb, offset, 2, value_reserved);
266   offset += 2;
267
268   proto_tree_add_item(kink_tree, hf_kink_checkSum, tvb, offset, chsumlen, ENC_NA);
269
270   /* This part consider the padding. Chsumlen don't contain the padding. */
271   if((chsumlen % PADDING) != 0){
272     chsumlen += (PADDING - (chsumlen % PADDING));
273     offset += chsumlen;
274   }
275   else{
276     offset += chsumlen;
277   }
278
279   control_payload(pinfo, tvb, offset, next_payload, kink_tree);
280
281 }
282
283 /* This part call the dissect payload function by next_payload value.
284  * This function called by the respective function again.
285  */
286 static void
287 control_payload(packet_info *pinfo, tvbuff_t *tvb, int offset, guint8 next_payload, proto_tree *kink_tree){
288   switch(next_payload){
289   case KINK_DONE:
290     break;
291   case KINK_AP_REQ:
292     dissect_payload_kink_ap_req(pinfo, tvb, offset, kink_tree);
293     break;
294   case KINK_AP_REP:
295     dissect_payload_kink_ap_rep(pinfo, tvb, offset, kink_tree);
296     break;
297   case KINK_KRB_ERROR:
298     dissect_payload_kink_krb_error(pinfo, tvb, offset, kink_tree);
299     break;
300   case KINK_TGT_REQ:
301     dissect_payload_kink_tgt_req(pinfo, tvb, offset, kink_tree);
302     break;
303   case KINK_TGT_REP:
304     dissect_payload_kink_tgt_rep(pinfo, tvb, offset, kink_tree);
305     break;
306   case KINK_ISAKMP:
307     dissect_payload_kink_isakmp(pinfo, tvb, offset, kink_tree);
308     break;
309   case KINK_ENCRYPT:
310     dissect_payload_kink_encrypt(pinfo, tvb, offset, kink_tree);
311     break;
312   case KINK_ERROR:
313     dissect_payload_kink_error(pinfo, tvb, offset, kink_tree);
314     break;
315   default:
316     dissect_payload_kink_not_defined(pinfo, tvb, offset, kink_tree);
317     break;
318   }
319 }
320
321 static void
322 dissect_payload_kink_ap_req(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
323   proto_tree *payload_kink_ap_req_tree;
324   proto_item *ti;
325   guint8 next_payload;
326   guint8 reserved;
327   guint payload_length;
328   guint16 krb_ap_req_length;
329   time_t timer;                  /* For showing utc */
330   int start_payload_offset = 0;  /* Keep begining of payload offset */
331
332   start_payload_offset = offset;
333   payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH);
334
335   /* Make the subtree. */
336   ti = proto_tree_add_text(tree, tvb, offset, payload_length, "KINK_AP_REQ");
337   payload_kink_ap_req_tree = proto_item_add_subtree(ti, ett_payload_kink_ap_req);
338
339   next_payload = tvb_get_guint8(tvb, offset);
340   proto_tree_add_uint(payload_kink_ap_req_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
341   offset ++;
342
343   reserved = tvb_get_guint8(tvb, offset);
344   proto_tree_add_text(payload_kink_ap_req_tree, tvb, offset, 1, "RESERVED: %u", reserved);
345   offset ++;
346
347   if(payload_length <= PAYLOAD_HEADER){
348     proto_tree_add_text(payload_kink_ap_req_tree, tvb, offset, 2, "This Payload Length is too small.: %u", payload_length);
349   }
350   else{
351     proto_tree_add_text(payload_kink_ap_req_tree, tvb, offset, 2, "Payload Length: %u", payload_length);
352   }
353   offset += 2;
354
355   /* Show time as UTC, not local time. */
356   timer = tvb_get_ntohl(tvb, offset);
357   proto_tree_add_text(payload_kink_ap_req_tree, tvb, offset, 4, "EPOCH: %s",
358                       abs_time_secs_to_str(timer, ABSOLUTE_TIME_UTC, TRUE));
359   offset += 4;
360
361   if(payload_length > PAYLOAD_HEADER){
362     tvbuff_t *krb_tvb;
363
364     krb_ap_req_length = payload_length - PAYLOAD_HEADER;
365     krb_tvb=tvb_new_subset(tvb, offset, (krb_ap_req_length>tvb_length_remaining(tvb, offset))?tvb_length_remaining(tvb, offset):krb_ap_req_length, krb_ap_req_length);
366     keytype=kerberos_output_keytype();
367     dissect_kerberos_main(krb_tvb, pinfo, payload_kink_ap_req_tree, FALSE, NULL);
368     offset += krb_ap_req_length;
369   }
370
371   /* This part consider padding the padding. Payload_length don't contain the padding. */
372   if(payload_length % PADDING != 0){
373     payload_length += (PADDING - (payload_length % PADDING));
374   }
375   offset = start_payload_offset + payload_length;
376
377   if(payload_length > 0) {
378     control_payload(pinfo, tvb, offset, next_payload, tree); /* Recur control_payload() */
379   }
380 }
381
382
383 static void
384 dissect_payload_kink_ap_rep(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
385   proto_tree *payload_kink_ap_rep_tree;
386   proto_item *ti;
387   guint8 next_payload;
388   guint8 reserved;
389   guint payload_length;
390   guint16 krb_ap_rep_length;
391   time_t timer;
392   int start_payload_offset = 0; /* Keep begining of payload offset */
393
394   payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH);
395   start_payload_offset = offset;
396
397   /* Make the subtree */
398   ti = proto_tree_add_text(tree, tvb, offset, payload_length,"KINK_AP_REP");
399   payload_kink_ap_rep_tree = proto_item_add_subtree(ti, ett_payload_kink_ap_rep);
400
401   next_payload = tvb_get_guint8(tvb, offset);
402   proto_tree_add_uint(payload_kink_ap_rep_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
403   offset ++;
404
405   reserved = tvb_get_guint8(tvb, offset);
406   proto_tree_add_text(payload_kink_ap_rep_tree, tvb, offset, 1, "RESERVED: %u", reserved);
407   offset ++;
408
409   if(payload_length <= PAYLOAD_HEADER){
410     proto_tree_add_text(payload_kink_ap_rep_tree, tvb, offset, 2, "This Payload Length is too small.: %u", payload_length);
411   }
412   else{
413     proto_tree_add_text(payload_kink_ap_rep_tree, tvb, offset, 2, "Payload Length: %u", payload_length);
414   }
415   offset += 2;
416
417   /* Show time as UTC, not local time. */
418   timer = tvb_get_ntohl(tvb, offset);
419   proto_tree_add_text(payload_kink_ap_rep_tree, tvb, offset, 4, "EPOCH: %s",
420                       abs_time_secs_to_str(timer, ABSOLUTE_TIME_UTC, TRUE));
421   offset += 4;
422
423   if(payload_length > PAYLOAD_HEADER){
424     tvbuff_t *krb_tvb;
425
426     krb_ap_rep_length = payload_length - PAYLOAD_HEADER;
427     krb_tvb=tvb_new_subset(tvb, offset, (krb_ap_rep_length>tvb_length_remaining(tvb, offset))?tvb_length_remaining(tvb, offset):krb_ap_rep_length, krb_ap_rep_length);
428     keytype=kerberos_output_keytype();
429     dissect_kerberos_main(krb_tvb, pinfo, payload_kink_ap_rep_tree, FALSE, NULL);
430
431     offset += krb_ap_rep_length;
432   }
433
434   /* This part consider the padding. Payload_length don't contain the padding. */
435   if(payload_length % PADDING != 0){
436     payload_length += (PADDING - (payload_length % PADDING));
437   }
438   offset = start_payload_offset + payload_length;
439
440   if(payload_length > 0) {
441     control_payload(pinfo, tvb, offset, next_payload, tree); /* Recur control_payload() */
442   }
443 }
444
445 static void
446 dissect_payload_kink_krb_error(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
447   proto_tree *payload_kink_krb_error_tree;
448   proto_item *ti;
449   guint8 next_payload;
450   guint8 reserved;
451   guint payload_length;
452   guint16 krb_error_length;
453   int start_payload_offset = 0; /* Keep the begining of the payload offset  */
454
455   payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH);
456   start_payload_offset = offset;
457
458   /* Make the subtree */
459   ti = proto_tree_add_text(tree, tvb, offset, payload_length,"KINK_KRB_ERROR");
460   payload_kink_krb_error_tree = proto_item_add_subtree(ti, ett_payload_kink_krb_error);
461
462   next_payload = tvb_get_guint8(tvb, offset);
463   proto_tree_add_uint(payload_kink_krb_error_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
464   offset ++;
465
466   reserved = tvb_get_guint8(tvb, offset);
467   proto_tree_add_text(payload_kink_krb_error_tree, tvb, offset, 1, "RESERVED: %u", reserved);
468   offset ++;
469
470   if(payload_length <= KINK_KRB_ERROR_HEADER){
471     proto_tree_add_text(payload_kink_krb_error_tree, tvb, offset, 2, "This Payload Length is too small.: %u", payload_length);
472   }
473   else{
474     proto_tree_add_text(payload_kink_krb_error_tree, tvb, offset, 2, "Payload Length: %u", payload_length);
475     offset += 2;
476   }
477
478   if(payload_length > KINK_KRB_ERROR_HEADER){
479     tvbuff_t *krb_tvb;
480
481     krb_error_length = payload_length - KINK_KRB_ERROR_HEADER;
482     krb_tvb=tvb_new_subset(tvb, offset, (krb_error_length>tvb_length_remaining(tvb, offset))?tvb_length_remaining(tvb, offset):krb_error_length, krb_error_length);
483
484     dissect_kerberos_main(krb_tvb, pinfo, payload_kink_krb_error_tree, FALSE, NULL);
485     offset += krb_error_length;
486   }
487
488   /* This part consider the padding. Payload_length don't contain the padding. */
489   if(payload_length % PADDING != 0){
490     payload_length += (PADDING - (payload_length % PADDING));
491   }
492   offset = start_payload_offset + payload_length;
493
494   if(payload_length > 0) {
495     control_payload(pinfo, tvb, offset, next_payload, tree); /* Recur control_payload() */
496   }
497 }
498
499 static void
500 dissect_payload_kink_tgt_req(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
501   proto_tree *payload_kink_tgt_req_tree;
502   proto_item *ti;
503   guint8 next_payload;
504   guint8 reserved;
505   guint payload_length;
506   guint16 realm_name_length;
507   int start_payload_offset = 0; /* Keep the begining of the payload offset  */
508
509   payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH);
510   realm_name_length = tvb_get_ntohs(tvb, offset + TO_REALM_NAME_LENGTH);
511   start_payload_offset = offset;
512
513   /* Make the subtree */
514   ti = proto_tree_add_text(tree, tvb, offset, payload_length,"KINK_TGT_REQ");
515   payload_kink_tgt_req_tree = proto_item_add_subtree(ti, ett_payload_kink_tgt_req);
516
517   next_payload = tvb_get_guint8(tvb, offset);
518   proto_tree_add_uint(payload_kink_tgt_req_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
519   offset ++;
520
521   reserved = tvb_get_guint8(tvb, offset);
522   proto_tree_add_text(payload_kink_tgt_req_tree, tvb, offset, 1, "RESERVED: %u", reserved);
523   offset ++;
524
525   proto_tree_add_text(payload_kink_tgt_req_tree, tvb, offset, 2, "Payload Length: %u", payload_length);
526   offset += 2;
527
528   proto_tree_add_text(payload_kink_tgt_req_tree, tvb, offset, 2, "RealmNameLength: %u", realm_name_length);
529   offset += 2;
530
531   proto_tree_add_text(payload_kink_tgt_req_tree, tvb, offset, realm_name_length, "RealmName: %s",
532                       tvb_format_text(tvb, offset, realm_name_length));
533   offset += realm_name_length;
534
535   /* This part consider the padding. Payload_length don't contain the padding. */
536   if(payload_length % PADDING != 0){
537     payload_length += (PADDING - (payload_length % PADDING));
538   }
539   offset = start_payload_offset + payload_length;
540
541   if(payload_length > 0) {
542     control_payload(pinfo, tvb, offset, next_payload, tree); /* Recur control_payload() */
543   }
544 }
545
546 static void
547 dissect_payload_kink_tgt_rep(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
548   proto_tree *payload_kink_tgt_rep_tree;
549   proto_item *ti;
550   guint8 next_payload;
551   guint8 reserved;
552   guint payload_length;
553   guint princ_name_length;
554   guint16 tgt_length;
555   int start_payload_offset = 0; /* Keep the begining of the payload offset  */
556
557   payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH);
558   start_payload_offset = offset;
559
560   /* Make the subtree */
561   ti = proto_tree_add_text(tree, tvb, offset, payload_length,"KINK_TGT_REP");
562   payload_kink_tgt_rep_tree = proto_item_add_subtree(ti, ett_payload_kink_tgt_rep);
563
564   next_payload = tvb_get_guint8(tvb, offset);
565   proto_tree_add_uint(payload_kink_tgt_rep_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
566   offset ++;
567
568   reserved = tvb_get_guint8(tvb, offset);
569   proto_tree_add_text(payload_kink_tgt_rep_tree, tvb, offset, 1, "RESERVED: %u", reserved);
570   offset ++;
571
572   proto_tree_add_text(payload_kink_tgt_rep_tree, tvb, offset, 2, "Payload Length: %u", payload_length);
573   offset += 2;
574
575   princ_name_length = tvb_get_ntohs(tvb, offset);
576   proto_tree_add_text(payload_kink_tgt_rep_tree, tvb, offset, 2, "PrincNameLength: %u", princ_name_length);
577   offset += 2;
578
579   proto_tree_add_text(payload_kink_tgt_rep_tree, tvb, offset, princ_name_length, "PrincName: %s", tvb_format_text(tvb, offset, princ_name_length));
580
581   /* This part consider the padding. Princ_name_length don't contain the padding. */
582   if((princ_name_length + FRONT_TGT_REP_HEADER) % PADDING != 0){
583     offset += (princ_name_length + PADDING - ((princ_name_length + FRONT_TGT_REP_HEADER) %  PADDING));
584   }
585   else{
586     offset += princ_name_length;
587   }
588
589   tgt_length = tvb_get_ntohs(tvb,offset);
590
591   proto_tree_add_text(payload_kink_tgt_rep_tree, tvb, offset, 2, "TGTlength: %u", tgt_length);
592   offset += 2;
593
594   proto_tree_add_text(payload_kink_tgt_rep_tree, tvb, offset, tgt_length, "TGT: %s", tvb_format_text(tvb, offset, tgt_length));
595   offset += tgt_length;
596
597   /* This part consider the padding. Payload_length don't contain the padding. */
598   if(payload_length % PADDING!=0){
599     payload_length += (PADDING - (payload_length % PADDING));
600   }
601   offset = start_payload_offset + payload_length;
602
603   if(payload_length > 0) {
604     control_payload(pinfo, tvb, offset, next_payload, tree); /* Recur control_payload() */
605   }
606 }
607
608 static void
609 dissect_payload_kink_isakmp(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
610   proto_tree *payload_kink_isakmp_tree;
611   proto_item *ti;
612   guint8 next_payload;
613   guint8 reserved;
614   guint payload_length,isakmp_length;
615   int length, reported_length;
616   guint8 inner_next_pload;
617   guint8 qm, qmmaj, qmmin;
618   guint16 reserved2;
619   int start_payload_offset = 0;      /* Keep the begining of the payload offset */
620   tvbuff_t *isakmp_tvb;
621
622   payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH);
623   start_payload_offset = offset;
624
625   /* Make the subtree. */
626   ti = proto_tree_add_text(tree, tvb, offset, payload_length,"KINK_ISAKMP");
627   payload_kink_isakmp_tree = proto_item_add_subtree(ti, ett_payload_kink_isakmp);
628
629   next_payload = tvb_get_guint8(tvb, offset);
630   proto_tree_add_uint(payload_kink_isakmp_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
631   offset ++;
632
633   reserved = tvb_get_guint8(tvb, offset);
634   proto_tree_add_text(payload_kink_isakmp_tree, tvb, offset, 1, "RESERVED: %u", reserved);
635   offset ++;
636
637   if(payload_length <= PAYLOAD_HEADER){
638     proto_tree_add_text(payload_kink_isakmp_tree, tvb, offset, 2, "This Payload Length is too small.: %u", payload_length);
639   }
640   else{
641     proto_tree_add_text(payload_kink_isakmp_tree, tvb, offset, 2, "Payload Length: %u", payload_length);
642   }
643   offset += 2;
644
645   inner_next_pload = tvb_get_guint8(tvb, offset);
646   proto_tree_add_text(payload_kink_isakmp_tree, tvb, offset, 1, "InnerNextPload: %u", inner_next_pload);
647   offset += 1;
648
649   /* The qmmaj is first half 4bit field of the octet. Therefore, the logical product
650    * of the 1octet value and 0xf0 is performed, and performed 4bit right shift.
651    * The qmmin is second half 4bit field of the octet. Therefore, the logical product
652    * of the 1octet value and 0x0f is performed.
653    */
654   qm = tvb_get_guint8(tvb,offset);
655   qmmaj = (qm & FRONT_FOUR_BIT) >> VERSION_BIT_SHIFT;
656   qmmin = qm & SECOND_FOUR_BIT;
657
658   proto_tree_add_text(payload_kink_isakmp_tree, tvb, offset, 1, "QMVersion: %u.%u", qmmaj, qmmin);
659   offset += 1;
660
661   reserved2 = tvb_get_ntohs(tvb, offset);
662   proto_tree_add_text(payload_kink_isakmp_tree, tvb, offset, 2, "RESERVED: %u", reserved2);
663   offset += 2;
664
665   if(payload_length > PAYLOAD_HEADER){
666     isakmp_length = payload_length - PAYLOAD_HEADER;
667     length = tvb_length_remaining(tvb, offset);
668     if (length > (int)isakmp_length)
669       length = isakmp_length;
670     reported_length = tvb_reported_length_remaining(tvb, offset);
671     if (reported_length > (int)isakmp_length)
672       reported_length = isakmp_length;
673     isakmp_tvb = tvb_new_subset(tvb, offset, length, reported_length);
674     isakmp_dissect_payloads(isakmp_tvb, payload_kink_isakmp_tree, 1, inner_next_pload, 0, isakmp_length, pinfo);
675   }
676
677   /* This part consider the padding. Payload_length don't contain the padding. */
678   if(payload_length % PADDING != 0){
679     payload_length += (PADDING - (payload_length % PADDING));
680   }
681   offset = start_payload_offset + payload_length;
682
683   if(payload_length > 0) {
684     control_payload(pinfo, tvb, offset, next_payload, tree);  /* Recur control_payload() */
685   }
686 }
687
688 static void
689 dissect_payload_kink_encrypt(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
690   proto_tree *payload_kink_encrypt_tree;
691   proto_item *ti;
692   guint8 next_payload;
693   guint8 reserved;
694   guint payload_length;
695 #ifdef HAVE_KERBEROS
696   gint encrypt_length;
697 #endif
698   guint8 inner_next_pload;
699   guint32 reserved2;
700   guint16 inner_payload_length;
701   int start_payload_offset = 0;    /* Keep the begining of the payload offset */
702
703   payload_length = tvb_get_ntohs(tvb,offset + TO_PAYLOAD_LENGTH);
704   start_payload_offset = offset;
705
706 #ifdef HAVE_KERBEROS
707   encrypt_length = payload_length - FROM_NP_TO_PL;
708 #endif
709   /* Make the subtree */
710   ti = proto_tree_add_text(tree, tvb, offset, payload_length,"KINK_ENCRYPT");
711   payload_kink_encrypt_tree = proto_item_add_subtree(ti, ett_payload_kink_encrypt);
712
713   next_payload = tvb_get_guint8(tvb, offset);
714   proto_tree_add_uint(payload_kink_encrypt_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
715   offset ++;
716
717   reserved = tvb_get_guint8(tvb, offset);
718   proto_tree_add_text(payload_kink_encrypt_tree, tvb, offset, 1, "RESERVED: %u", reserved);
719   offset ++;
720
721   if(payload_length <= PAYLOAD_HEADER){
722     proto_tree_add_text(payload_kink_encrypt_tree, tvb, offset, 2, "This Payload Length is too small.: %u", payload_length);
723   }
724   else{
725     proto_tree_add_text(payload_kink_encrypt_tree, tvb, offset, 2, "Payload Length: %u", payload_length);
726   }
727   offset += 2;
728
729   /* decrypt kink encrypt */
730
731   if(keytype != 0){
732 #ifdef HAVE_KERBEROS
733     tvbuff_t *next_tvb;
734     guint8 *plaintext=NULL;
735
736     next_tvb=tvb_new_subset(tvb, offset, MIN(tvb_length_remaining(tvb, offset), encrypt_length), encrypt_length);
737     plaintext=decrypt_krb5_data(tree, pinfo, 0, next_tvb, keytype, NULL);
738     if(plaintext){
739       next_tvb=tvb_new_child_real_data(tvb, plaintext, encrypt_length, encrypt_length);
740       tvb_set_free_cb(next_tvb, g_free);
741       add_new_data_source(pinfo, next_tvb, "decrypted kink encrypt");
742       dissect_decrypt_kink_encrypt(pinfo, next_tvb, tree, encrypt_length);
743     }
744 #endif
745   }
746   else{
747     inner_next_pload = tvb_get_guint8(tvb, offset);
748     proto_tree_add_text(payload_kink_encrypt_tree, tvb, offset, 1, "InnerNextPload: %u", inner_next_pload);
749     offset += 1;
750
751     reserved2 = 65536*tvb_get_guint8(tvb, offset) + 256*tvb_get_guint8(tvb, offset+1) + tvb_get_guint8(tvb, offset+2);
752     proto_tree_add_text(payload_kink_encrypt_tree, tvb, offset, 3, "RESERVED: %u", reserved2);
753     offset += 3;
754
755     if(payload_length > PAYLOAD_HEADER){
756       inner_payload_length = payload_length - PAYLOAD_HEADER;
757       proto_tree_add_text(payload_kink_encrypt_tree, tvb, offset, inner_payload_length, "Payload");
758       offset += inner_payload_length;
759     }
760   }
761   /* This part consider the padding. Payload_length don't contain the padding. */
762   if(payload_length % PADDING !=0){
763     payload_length += (PADDING - (payload_length % PADDING));
764   }
765   offset = start_payload_offset + payload_length;
766
767   if(payload_length > 0) {
768     control_payload(pinfo, tvb, offset, next_payload, tree);  /* Recur control_payload() */
769   }
770 }
771
772 #ifdef HAVE_KERBEROS
773 static void
774 dissect_decrypt_kink_encrypt(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree, int payload_length){
775
776   proto_tree *decrypt_kink_encrypt_tree;
777   proto_item *ti;
778   int offset=0;
779   guint8 next_payload;
780   guint32 reserved;
781
782   ti = proto_tree_add_text(tree, tvb, offset, payload_length, "decrypted data");
783   decrypt_kink_encrypt_tree = proto_item_add_subtree(ti, ett_decrypt_kink_encrypt);
784
785   next_payload = tvb_get_guint8(tvb, offset);
786
787   proto_tree_add_uint(decrypt_kink_encrypt_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
788   offset ++;
789
790   reserved = 65536*tvb_get_guint8(tvb, offset) + 256*tvb_get_guint8(tvb, offset+1) + tvb_get_guint8(tvb, offset+2);
791   proto_tree_add_text(decrypt_kink_encrypt_tree, tvb, offset, 3, "RESERVED: %u", reserved);
792   offset += 3;
793
794   control_payload(pinfo, tvb, offset, next_payload, decrypt_kink_encrypt_tree);
795 }
796 #endif
797
798 static void
799 dissect_payload_kink_error(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
800   proto_tree *payload_kink_error_tree;
801   proto_item *ti;
802   guint8 next_payload;
803   guint8 reserved;
804   guint16 payload_length;
805   guint32 error_code;
806   int start_payload_offset = 0; /* Keep the begining of the payload offset */
807   const char *char_error_code[] = {
808     "KINK_OK",
809     "KINK_PROTOERR",
810     "KINK_INVDOI",
811     "KINK_INVMAJ",
812     "KINK_INVMIN",
813     "KINK_INTERR",
814     "KINK_BADQMVERS"
815   };
816
817   payload_length = tvb_get_ntohs(tvb,offset + TO_PAYLOAD_LENGTH);
818   start_payload_offset = offset;
819
820   /* Make the subtree */
821   ti = proto_tree_add_text(tree, tvb, offset, payload_length,"KINK_ERROR");
822   payload_kink_error_tree = proto_item_add_subtree(ti, ett_payload_kink_error);
823
824   next_payload = tvb_get_guint8(tvb, offset);
825   proto_tree_add_uint(payload_kink_error_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
826   offset ++;
827
828   reserved = tvb_get_guint8(tvb,offset);
829   proto_tree_add_text(payload_kink_error_tree, tvb, offset, 1, "RESERVED: %u", reserved);
830   offset ++;
831
832   if(payload_length != KINK_ERROR_LENGTH){
833     proto_tree_add_text(payload_kink_error_tree, tvb, offset, 2, "This Payload Length is mismatch.: %u", payload_length);
834   }
835   else{
836     proto_tree_add_text(payload_kink_error_tree, tvb, offset, 2, "Payload Length: %u", payload_length);
837   }
838   offset += 2;
839
840   error_code = tvb_get_ntohl(tvb, offset);
841
842   /* Choosed the error code by erro_code */
843   switch(error_code){
844   case KINK_OK:
845   case KINK_PROTOERR:
846   case KINK_INVDOI:
847   case KINK_INVMAJ:
848   case KINK_INVMIN:
849   case KINK_INTERR:
850   case KINK_BADQMVERS:
851     proto_tree_add_text(payload_kink_error_tree, tvb, offset, 4, "ErrorCode: %s (%u)", char_error_code[error_code], error_code);
852     break;
853   default:
854     if(BOTTOM_RESERVED <= error_code && TOP_RESERVED >= error_code){
855       proto_tree_add_text(payload_kink_error_tree, tvb, offset, 4, "ErrorCode: %s (%u)", "RESERVED", error_code);
856     }
857     else if(BOTTOM_PRIVATE_USE <= error_code && TOP_PRIVATE_USE >= error_code){
858       proto_tree_add_text(payload_kink_error_tree, tvb, offset, 4, "ErrorCode: %s (%u)", "PRIVATE USE", error_code);
859     }
860     else{
861       proto_tree_add_text(payload_kink_error_tree, tvb, offset, 4, "ErrorCode: %s (%u)", "This Error Code is not Defined.", error_code);
862     }
863     break;
864   }
865   offset += 4;
866
867   offset = start_payload_offset + KINK_ERROR_LENGTH;
868   control_payload(pinfo, tvb, offset, next_payload, tree);  /* Recur control_payload() */
869 }
870
871 static void
872 dissect_payload_kink_not_defined(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
873   proto_tree *payload_kink_not_defined_tree;
874   proto_item *ti;
875   guint8 next_payload;
876   guint payload_length;
877   guint8 reserved;
878   int start_payload_offset = 0;   /* Keep the begining of the payload offset */
879
880   start_payload_offset = offset;
881   payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH);
882
883   /* Make the subtree */
884   ti = proto_tree_add_text(tree, tvb, offset, payload_length, "UNKNOWN PAYLOAD");
885   payload_kink_not_defined_tree = proto_item_add_subtree(ti, ett_payload_not_defined);
886
887   next_payload = tvb_get_guint8(tvb, offset);
888   proto_tree_add_uint(payload_kink_not_defined_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
889   offset ++;
890
891   reserved = tvb_get_guint8(tvb, offset);
892   proto_tree_add_text(payload_kink_not_defined_tree, tvb, offset, 1, "RESERVED: %u", reserved);
893   offset ++;
894
895   proto_tree_add_text(payload_kink_not_defined_tree, tvb, offset, 2, "Payload Length: %u", payload_length);
896   offset += 2;
897
898   /* This part consider the padding. Payload_length don't contain the padding. */
899   if(payload_length % PADDING != 0){
900     payload_length += (PADDING - (payload_length % PADDING));
901   }
902   offset = start_payload_offset + payload_length;
903
904   /* XXX - prevent an endless loop if payload_length is 0, don't know the correct way to handle this! */
905   if(payload_length > 0) {
906     control_payload(pinfo, tvb, offset, next_payload, tree);
907   }
908 }
909
910 /* Output part */
911 void
912 proto_register_kink(void) {
913
914   static hf_register_info hf[] = {
915     { &hf_kink_type,
916       { "Type", "kink.type",
917         FT_UINT8,       BASE_DEC,       VALS(kink_type_vals),   0x0,
918         "the type of the kink", HFILL }},
919     { &hf_kink_length,
920       { "Length",       "kink.length",
921         FT_UINT16,      BASE_DEC,       NULL,   0x0,
922         "the length of the kink length", HFILL }},
923     { &hf_kink_transactionId,
924       { "Transaction ID",       "kink.transactionId",
925         FT_UINT32,      BASE_DEC,       NULL,   0x0,
926         "the transactionID of kink", HFILL }},
927     { &hf_kink_checkSumLength,
928       { "Checksum Length",       "kink.checkSumLength",
929         FT_UINT8,       BASE_DEC,       NULL,   0x0,
930         "the check sum length of kink", HFILL }},
931     { &hf_kink_A,
932       { "A",       "kink.A",
933         FT_UINT8,       BASE_DEC,       VALS(kink_A_vals),      0x0,
934         "the A of kink", HFILL }},
935     { &hf_kink_reserved,
936       { "Reserved",       "kink.reserved",
937         FT_UINT16,      BASE_DEC,       NULL,   0x0,
938         "the reserved of kink", HFILL }},
939     { &hf_kink_checkSum,
940       { "Checksum",       "kink.checkSum",
941         FT_BYTES,       BASE_NONE,      NULL,   0x0,
942         "the checkSum of kink", HFILL }},
943     { &hf_kink_next_payload,
944       { "Next Payload",       "kink.nextPayload",
945         FT_UINT8,       BASE_DEC,       VALS(kink_next_payload),        0x0,
946         "the next payload of kink", HFILL }}
947
948   };
949
950   /* Argument for making the subtree. */
951   static gint *ett[] = {
952     &ett_kink,
953     /*    &ett_kink_version, */
954     &ett_kink_payload,
955     &ett_payload_kink_ap_req,
956     &ett_payload_kink_ap_rep,
957     &ett_payload_kink_krb_error,
958     &ett_payload_kink_tgt_req,
959     &ett_payload_kink_tgt_rep,
960     &ett_payload_kink_isakmp,
961     &ett_payload_kink_encrypt,
962     &ett_payload_kink_error,
963     &ett_payload_not_defined,
964     &ett_decrypt_kink_encrypt,
965
966   };
967
968   proto_kink = proto_register_protocol("Kerberized Internet Negotiation of Key", "KINK", "kink");
969   proto_register_field_array(proto_kink, hf, array_length(hf));
970   proto_register_subtree_array(ett, array_length(ett));
971
972 }
973
974 void proto_reg_handoff_kink(void) {
975
976   dissector_handle_t kink_handle = NULL;
977
978   kink_handle = create_dissector_handle(dissect_kink, proto_kink);
979
980   dissector_add_uint("udp.port", KINK_PORT, kink_handle);
981
982 }
983