MSWSP: add ids for another unknown Property Set
[wireshark-wip.git] / epan / dissectors / packet-kink.c
blobd95fd4d5be93b312a4e6a0bde350bc3eff05fe73
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
5 * Copyright 2004, Takeshi Nakashima <T.Nakashima@jp.yokogawa.com>
7 * $Id$
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
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.
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.
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.
29 #include "config.h"
31 #include <glib.h>
32 #include <epan/packet.h>
33 #include <epan/expert.h>
34 #include <epan/asn1.h>
35 #include "packet-kerberos.h"
36 #include "packet-isakmp.h"
38 #define KINK_PORT 57203
40 #define KINK_ISAKMP_PAYLOAD_BASE 14
42 static int proto_kink = -1;
44 /* Argument for proto_tree_add_uint() */
45 static int hf_kink_type = -1;
46 static int hf_kink_length = -1;
47 static int hf_kink_transactionId = -1;
48 static int hf_kink_checkSumLength = -1;
49 static int hf_kink_A = -1;
50 static int hf_kink_reserved8 = -1;
51 static int hf_kink_reserved15 = -1;
52 static int hf_kink_reserved16 = -1;
53 static int hf_kink_reserved24 = -1;
54 static int hf_kink_checkSum = -1;
55 static int hf_kink_next_payload = -1;
56 static int hf_kink_payload_length = -1;
57 static int hf_kink_epoch = -1;
58 static int hf_kink_inner_next_pload = -1;
59 static int hf_kink_realm_name_length = -1;
60 static int hf_kink_realm_name = -1;
61 static int hf_kink_princ_name_length = -1;
62 static int hf_kink_princ_name = -1;
63 static int hf_kink_tgt_length = -1;
64 static int hf_kink_tgt = -1;
66 /* Argument for making the subtree */
67 static gint ett_kink = -1;
68 /*static gint ett_kink_version = -1;*/
69 static gint ett_kink_payload = -1;
70 static gint ett_payload_kink_ap_req = -1;
71 static gint ett_payload_kink_ap_rep = -1;
72 static gint ett_payload_kink_krb_error = -1;
73 static gint ett_payload_kink_tgt_req = -1;
74 static gint ett_payload_kink_tgt_rep = -1;
75 static gint ett_payload_kink_isakmp = -1;
76 static gint ett_payload_kink_encrypt = -1;
77 static gint ett_payload_kink_error = -1;
78 static gint ett_payload_not_defined = -1;
79 static gint ett_decrypt_kink_encrypt = -1;
81 static expert_field ei_kink_payload_length_small = EI_INIT;
82 static expert_field ei_kink_payload_length_mismatch = EI_INIT;
85 /* Define the kink type value */
86 #define KINK_TYPE_RESERVED 0
87 #define KINK_TYPE_CREATE 1
88 #define KINK_TYPE_DELETE 2
89 #define KINK_TYPE_REPLY 3
90 #define KINK_TYPE_GETTGT 4
91 #define KINK_TYPE_ACK 5
92 #define KINK_TYPE_STATUS 6
94 static const value_string kink_type_vals[]={
95 {KINK_TYPE_RESERVED,"RESERVED"},
96 {KINK_TYPE_CREATE,"CREATE"},
97 {KINK_TYPE_DELETE,"DELETE"},
98 {KINK_TYPE_REPLY,"REPLY"},
99 {KINK_TYPE_GETTGT,"GETTGT"},
100 {KINK_TYPE_ACK,"ACK"},
101 {KINK_TYPE_STATUS,"STATUS"},
102 {0, NULL},
105 /* Define the kink A value */
106 #define KINK_A_NOT_REQUEST_ACK 0
107 #define KINK_A_REQUEST_ACK 1
109 static const value_string kink_A_vals[]={
110 {KINK_A_NOT_REQUEST_ACK,"Not Request ACK"},
111 {KINK_A_REQUEST_ACK,"Request ACK"},
112 {0, NULL},
115 /* Define the kink payload */
116 #define KINK_DONE 0
117 #define KINK_AP_REQ KINK_ISAKMP_PAYLOAD_BASE+0
118 #define KINK_AP_REP KINK_ISAKMP_PAYLOAD_BASE+1
119 #define KINK_KRB_ERROR KINK_ISAKMP_PAYLOAD_BASE+2
120 #define KINK_TGT_REQ KINK_ISAKMP_PAYLOAD_BASE+3
121 #define KINK_TGT_REP KINK_ISAKMP_PAYLOAD_BASE+4
122 #define KINK_ISAKMP KINK_ISAKMP_PAYLOAD_BASE+5
123 #define KINK_ENCRYPT KINK_ISAKMP_PAYLOAD_BASE+6
124 #define KINK_ERROR KINK_ISAKMP_PAYLOAD_BASE+7
126 static const value_string kink_next_payload[]={
127 {KINK_DONE, "KINK_DONE"},
128 {KINK_AP_REQ, "KINK_AP_REQ"},
129 {KINK_AP_REP, "KINK_AP_REP"},
130 {KINK_KRB_ERROR, "KINK_KRB_ERROR"},
131 {KINK_TGT_REQ, "KINK_TGT_REQ"},
132 {KINK_TGT_REP, "KINK_TGT_REP"},
133 {KINK_ISAKMP, "KINK_ISAKMP"},
134 {KINK_ENCRYPT, "KINK_ENCRYPT"},
135 {KINK_ERROR, "KINK_ERROR"},
136 {0, NULL},
139 /* Define the magic number
140 * Using at the kink error
142 #define KINK_OK 0
143 #define KINK_PROTOERR 1
144 #define KINK_INVDOI 2
145 #define KINK_INVMAJ 3
146 #define KINK_INVMIN 4
147 #define KINK_INTERR 5
148 #define KINK_BADQMVERS 6
149 #define BOTTOM_RESERVED 7
150 #define TOP_RESERVED 8191
151 #define BOTTOM_PRIVATE_USE 8192
152 #define TOP_PRIVATE_USE 16383
154 /* Using at the kink header */
155 #define IPSEC 1
156 #define VERSION_BIT_SHIFT 4
157 #define A_BIT_SHIFT 7
158 #define FROM_TYPE_TO_RESERVED 16
160 /* Using at the payload */
161 #define TO_PAYLOAD_LENGTH 2
162 #define PADDING 4
163 #define KINK_KRB_ERROR_HEADER 4
164 #define FROM_NP_TO_PL 4
165 #define TO_REALM_NAME_LENGTH 4
166 #define KINK_TGT_REQ_HEADER 6
167 #define FRONT_TGT_REP_HEADER 6
168 #define PAYLOAD_HEADER 8
169 #define KINK_ERROR_LENGTH 8
172 /* define hexadecimal */
173 #define FRONT_FOUR_BIT 0xf0
174 #define SECOND_FOUR_BIT 0x0f
175 #define FRONT_ONE_BIT 0x80
176 #define SECOND_FIFTEEN_BIT 0x7fff
178 /* decrypt element */
179 static guint32 keytype;
181 static void control_payload(packet_info *pinfo, tvbuff_t *tvb, int offset, guint8 next_payload, proto_tree *kink_payload_tree);
182 static void dissect_payload_kink_ap_req(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
183 static void dissect_payload_kink_ap_rep(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
184 static void dissect_payload_kink_krb_error(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
185 static void dissect_payload_kink_tgt_req(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
186 static void dissect_payload_kink_tgt_rep(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
187 static void dissect_payload_kink_isakmp(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
188 static void dissect_payload_kink_encrypt(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
189 static void dissect_payload_kink_error(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
190 static void dissect_payload_kink_not_defined(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree);
191 #ifdef HAVE_KERBEROS
192 static void dissect_decrypt_kink_encrypt(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree, int payload_length);
193 #endif
195 /* This function is dissecting the kink header. */
196 static void
197 dissect_kink(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree){
198 proto_item *ti = NULL;
199 proto_tree *kink_tree = NULL;
200 guint8 type;
201 guint8 major_version, minor_version, version;
202 guint32 doi;
203 guint chsumlen;
204 guint8 next_payload;
205 guint8 value_a_and_front_reserved;
206 guint8 value_a;
207 int offset=0;
209 type = tvb_get_guint8(tvb,offset);
211 col_set_str(pinfo->cinfo, COL_PROTOCOL, "KINK");
213 /* It shows kink type by the type value. */
214 col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(type, kink_type_vals, "unknown"));
216 /* Make the kink tree */
217 ti = proto_tree_add_item(tree, proto_kink, tvb, offset, -1, ENC_NA);
218 kink_tree = proto_item_add_subtree(ti, ett_kink);
220 proto_tree_add_uint(kink_tree, hf_kink_type, tvb, offset, 1, type);
221 offset++;
223 /* This part is the version. Consider less than 1 octet value.
224 * Major version and minor version is 4bit. Front half of 1octet
225 * is major version, and second half of 1octet is minor version.
226 * The calculation of major version is shown below.
227 * The logical product of the value of 1octet and 0xf0 is performed.
228 * And It is performed 4bit right shift.
229 * Secondarily, the calculation of minor version is shown below.
230 * The logical product of the value of 1octet and 0x0f is performed.
232 version = tvb_get_guint8(tvb,offset);
233 major_version = (version & FRONT_FOUR_BIT) >> VERSION_BIT_SHIFT;
234 minor_version = version & SECOND_FOUR_BIT;
235 proto_tree_add_text(kink_tree, tvb, offset, 1, "version: %u.%u", major_version, minor_version);
236 offset++;
238 proto_tree_add_item(kink_tree, hf_kink_length, tvb, offset, 2, ENC_BIG_ENDIAN);
239 offset += 2;
241 doi = tvb_get_ntohl(tvb, offset);
243 if(doi == IPSEC){
244 proto_tree_add_text(kink_tree, tvb, offset, 4, "Domain Of Interpretation: %s (%u)", "IPsec", doi);
246 else{
247 proto_tree_add_text(kink_tree, tvb, offset, 4, "Domain Of Interpretation: %s (%u)", "Not IPsec", doi);
249 offset += 4;
251 proto_tree_add_item(kink_tree, hf_kink_transactionId, tvb, offset, 4, ENC_BIG_ENDIAN);
252 offset += 4;
254 chsumlen = tvb_get_guint8(tvb, offset);
255 proto_tree_add_item(kink_tree, hf_kink_checkSumLength, tvb, offset, 1, ENC_BIG_ENDIAN);
256 offset ++;
258 next_payload = tvb_get_guint8(tvb, offset);
259 proto_tree_add_uint(kink_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
260 offset ++;
262 /* A is 1bit field. The caluculation of A is shown below.
263 * The logical product of 1octet value and 0x80 is performed.
264 * And It is performed 7bit right shift.
266 value_a_and_front_reserved = tvb_get_guint8(tvb, offset);
267 value_a = (value_a_and_front_reserved & FRONT_ONE_BIT) >> A_BIT_SHIFT;
268 proto_tree_add_uint(kink_tree, hf_kink_A, tvb, offset, 1, value_a);
270 /* The reserved field is 15bit.
271 * The logical product of 2octet value and 0x7fff is performed.
273 proto_tree_add_item(kink_tree, hf_kink_reserved15, tvb, offset, 2, ENC_BIG_ENDIAN);
274 offset += 2;
276 proto_tree_add_item(kink_tree, hf_kink_checkSum, tvb, offset, chsumlen, ENC_NA);
278 /* This part consider the padding. Chsumlen don't contain the padding. */
279 if((chsumlen % PADDING) != 0){
280 chsumlen += (PADDING - (chsumlen % PADDING));
281 offset += chsumlen;
283 else{
284 offset += chsumlen;
287 control_payload(pinfo, tvb, offset, next_payload, kink_tree);
291 /* This part call the dissect payload function by next_payload value.
292 * This function called by the respective function again.
294 static void
295 control_payload(packet_info *pinfo, tvbuff_t *tvb, int offset, guint8 next_payload, proto_tree *kink_tree){
296 switch(next_payload){
297 case KINK_DONE:
298 break;
299 case KINK_AP_REQ:
300 dissect_payload_kink_ap_req(pinfo, tvb, offset, kink_tree);
301 break;
302 case KINK_AP_REP:
303 dissect_payload_kink_ap_rep(pinfo, tvb, offset, kink_tree);
304 break;
305 case KINK_KRB_ERROR:
306 dissect_payload_kink_krb_error(pinfo, tvb, offset, kink_tree);
307 break;
308 case KINK_TGT_REQ:
309 dissect_payload_kink_tgt_req(pinfo, tvb, offset, kink_tree);
310 break;
311 case KINK_TGT_REP:
312 dissect_payload_kink_tgt_rep(pinfo, tvb, offset, kink_tree);
313 break;
314 case KINK_ISAKMP:
315 dissect_payload_kink_isakmp(pinfo, tvb, offset, kink_tree);
316 break;
317 case KINK_ENCRYPT:
318 dissect_payload_kink_encrypt(pinfo, tvb, offset, kink_tree);
319 break;
320 case KINK_ERROR:
321 dissect_payload_kink_error(pinfo, tvb, offset, kink_tree);
322 break;
323 default:
324 dissect_payload_kink_not_defined(pinfo, tvb, offset, kink_tree);
325 break;
329 static void
330 dissect_payload_kink_ap_req(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
331 proto_tree *payload_kink_ap_req_tree;
332 proto_item *ti;
333 guint8 next_payload;
334 guint payload_length;
335 guint16 krb_ap_req_length;
336 int start_payload_offset = 0; /* Keep beginning of payload offset */
338 start_payload_offset = offset;
339 payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH);
341 /* Make the subtree. */
342 ti = proto_tree_add_text(tree, tvb, offset, payload_length, "KINK_AP_REQ");
343 payload_kink_ap_req_tree = proto_item_add_subtree(ti, ett_payload_kink_ap_req);
345 next_payload = tvb_get_guint8(tvb, offset);
346 proto_tree_add_uint(payload_kink_ap_req_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
347 offset ++;
349 proto_tree_add_item(payload_kink_ap_req_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
350 offset ++;
352 ti = proto_tree_add_uint(payload_kink_ap_req_tree, hf_kink_payload_length, tvb, offset, 2, payload_length);
353 if(payload_length <= PAYLOAD_HEADER){
354 expert_add_info(pinfo, ti, &ei_kink_payload_length_small);
356 offset += 2;
358 /* Show time as UTC, not local time. */
359 proto_tree_add_item(payload_kink_ap_req_tree, hf_kink_epoch, tvb, offset, 4, ENC_BIG_ENDIAN);
360 offset += 4;
362 if(payload_length > PAYLOAD_HEADER){
363 tvbuff_t *krb_tvb;
365 krb_ap_req_length = payload_length - PAYLOAD_HEADER;
366 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);
367 keytype=kerberos_output_keytype();
368 dissect_kerberos_main(krb_tvb, pinfo, payload_kink_ap_req_tree, FALSE, NULL);
369 /*offset += krb_ap_req_length;*/
372 /* This part consider padding the padding. Payload_length don't contain the padding. */
373 if(payload_length % PADDING != 0){
374 payload_length += (PADDING - (payload_length % PADDING));
376 offset = start_payload_offset + payload_length;
378 if(payload_length > 0) {
379 control_payload(pinfo, tvb, offset, next_payload, tree); /* Recur control_payload() */
384 static void
385 dissect_payload_kink_ap_rep(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
386 proto_tree *payload_kink_ap_rep_tree;
387 proto_item *ti;
388 guint8 next_payload;
389 guint payload_length;
390 guint16 krb_ap_rep_length;
391 int start_payload_offset = 0; /* Keep beginning of payload offset */
393 payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH);
394 start_payload_offset = offset;
396 /* Make the subtree */
397 ti = proto_tree_add_text(tree, tvb, offset, payload_length,"KINK_AP_REP");
398 payload_kink_ap_rep_tree = proto_item_add_subtree(ti, ett_payload_kink_ap_rep);
400 next_payload = tvb_get_guint8(tvb, offset);
401 proto_tree_add_uint(payload_kink_ap_rep_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
402 offset ++;
404 proto_tree_add_item(payload_kink_ap_rep_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
405 offset ++;
407 ti = proto_tree_add_uint(payload_kink_ap_rep_tree, hf_kink_payload_length, tvb, offset, 2, payload_length);
408 if(payload_length <= PAYLOAD_HEADER){
409 expert_add_info(pinfo, ti, &ei_kink_payload_length_small);
411 offset += 2;
413 /* Show time as UTC, not local time. */
414 proto_tree_add_item(payload_kink_ap_rep_tree, hf_kink_epoch, tvb, offset, 4, ENC_BIG_ENDIAN);
415 offset += 4;
417 if(payload_length > PAYLOAD_HEADER){
418 tvbuff_t *krb_tvb;
420 krb_ap_rep_length = payload_length - PAYLOAD_HEADER;
421 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);
422 keytype=kerberos_output_keytype();
423 dissect_kerberos_main(krb_tvb, pinfo, payload_kink_ap_rep_tree, FALSE, NULL);
425 /*offset += krb_ap_rep_length;*/
428 /* This part consider the padding. Payload_length don't contain the padding. */
429 if(payload_length % PADDING != 0){
430 payload_length += (PADDING - (payload_length % PADDING));
432 offset = start_payload_offset + payload_length;
434 if(payload_length > 0) {
435 control_payload(pinfo, tvb, offset, next_payload, tree); /* Recur control_payload() */
439 static void
440 dissect_payload_kink_krb_error(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
441 proto_tree *payload_kink_krb_error_tree;
442 proto_item *ti;
443 guint8 next_payload;
444 guint payload_length;
445 guint16 krb_error_length;
446 int start_payload_offset = 0; /* Keep the beginning of the payload offset */
448 payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH);
449 start_payload_offset = offset;
451 /* Make the subtree */
452 ti = proto_tree_add_text(tree, tvb, offset, payload_length,"KINK_KRB_ERROR");
453 payload_kink_krb_error_tree = proto_item_add_subtree(ti, ett_payload_kink_krb_error);
455 next_payload = tvb_get_guint8(tvb, offset);
456 proto_tree_add_uint(payload_kink_krb_error_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
457 offset ++;
459 proto_tree_add_item(payload_kink_krb_error_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
460 offset ++;
462 ti = proto_tree_add_uint(payload_kink_krb_error_tree, hf_kink_payload_length, tvb, offset, 2, payload_length);
463 if(payload_length <= KINK_KRB_ERROR_HEADER){
464 expert_add_info(pinfo, ti, &ei_kink_payload_length_small);
466 else {
467 offset += 2;
470 if(payload_length > KINK_KRB_ERROR_HEADER){
471 tvbuff_t *krb_tvb;
473 krb_error_length = payload_length - KINK_KRB_ERROR_HEADER;
474 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);
476 dissect_kerberos_main(krb_tvb, pinfo, payload_kink_krb_error_tree, FALSE, NULL);
477 /*offset += krb_error_length;*/
480 /* This part consider the padding. Payload_length don't contain the padding. */
481 if(payload_length % PADDING != 0){
482 payload_length += (PADDING - (payload_length % PADDING));
484 offset = start_payload_offset + payload_length;
486 if(payload_length > 0) {
487 control_payload(pinfo, tvb, offset, next_payload, tree); /* Recur control_payload() */
491 static void
492 dissect_payload_kink_tgt_req(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
493 proto_tree *payload_kink_tgt_req_tree;
494 proto_item *ti;
495 guint8 next_payload;
496 guint payload_length;
497 guint16 realm_name_length;
498 int start_payload_offset = 0; /* Keep the beginning of the payload offset */
500 payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH);
501 realm_name_length = tvb_get_ntohs(tvb, offset + TO_REALM_NAME_LENGTH);
502 start_payload_offset = offset;
504 /* Make the subtree */
505 ti = proto_tree_add_text(tree, tvb, offset, payload_length,"KINK_TGT_REQ");
506 payload_kink_tgt_req_tree = proto_item_add_subtree(ti, ett_payload_kink_tgt_req);
508 next_payload = tvb_get_guint8(tvb, offset);
509 proto_tree_add_uint(payload_kink_tgt_req_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
510 offset ++;
512 proto_tree_add_item(payload_kink_tgt_req_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
513 offset ++;
515 proto_tree_add_uint(payload_kink_tgt_req_tree, hf_kink_payload_length, tvb, offset, 2, payload_length);
516 offset += 2;
518 proto_tree_add_uint(payload_kink_tgt_req_tree, hf_kink_realm_name_length, tvb, offset, 2, realm_name_length);
519 offset += 2;
521 proto_tree_add_item(payload_kink_tgt_req_tree, hf_kink_realm_name, tvb, offset, realm_name_length, ENC_NA|ENC_ASCII);
523 /* This part consider the padding. Payload_length don't contain the padding. */
524 if(payload_length % PADDING != 0){
525 payload_length += (PADDING - (payload_length % PADDING));
527 offset = start_payload_offset + payload_length;
529 if(payload_length > 0) {
530 control_payload(pinfo, tvb, offset, next_payload, tree); /* Recur control_payload() */
534 static void
535 dissect_payload_kink_tgt_rep(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
536 proto_tree *payload_kink_tgt_rep_tree;
537 proto_item *ti;
538 guint8 next_payload;
539 guint payload_length;
540 guint princ_name_length;
541 guint16 tgt_length;
542 int start_payload_offset = 0; /* Keep the beginning of the payload offset */
544 payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH);
545 start_payload_offset = offset;
547 /* Make the subtree */
548 ti = proto_tree_add_text(tree, tvb, offset, payload_length,"KINK_TGT_REP");
549 payload_kink_tgt_rep_tree = proto_item_add_subtree(ti, ett_payload_kink_tgt_rep);
551 next_payload = tvb_get_guint8(tvb, offset);
552 proto_tree_add_uint(payload_kink_tgt_rep_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
553 offset ++;
555 proto_tree_add_item(payload_kink_tgt_rep_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
556 offset ++;
558 proto_tree_add_uint(payload_kink_tgt_rep_tree, hf_kink_payload_length, tvb, offset, 2, payload_length);
559 offset += 2;
561 princ_name_length = tvb_get_ntohs(tvb, offset);
562 proto_tree_add_uint(payload_kink_tgt_rep_tree, hf_kink_princ_name_length, tvb, offset, 2, princ_name_length);
563 offset += 2;
565 proto_tree_add_item(payload_kink_tgt_rep_tree, hf_kink_princ_name, tvb, offset, princ_name_length, ENC_NA|ENC_ASCII);
567 /* This part consider the padding. Princ_name_length don't contain the padding. */
568 if((princ_name_length + FRONT_TGT_REP_HEADER) % PADDING != 0){
569 offset += (princ_name_length + PADDING - ((princ_name_length + FRONT_TGT_REP_HEADER) % PADDING));
571 else{
572 offset += princ_name_length;
575 tgt_length = tvb_get_ntohs(tvb, offset);
576 proto_tree_add_uint(payload_kink_tgt_rep_tree, hf_kink_tgt_length, tvb, offset, 2, tgt_length);
577 offset += 2;
579 proto_tree_add_item(payload_kink_tgt_rep_tree, hf_kink_tgt, tvb, offset, tgt_length, ENC_NA|ENC_ASCII);
580 /*offset += tgt_length;*/
582 /* This part consider the padding. Payload_length don't contain the padding. */
583 if(payload_length % PADDING!=0){
584 payload_length += (PADDING - (payload_length % PADDING));
586 offset = start_payload_offset + payload_length;
588 if(payload_length > 0) {
589 control_payload(pinfo, tvb, offset, next_payload, tree); /* Recur control_payload() */
593 static void
594 dissect_payload_kink_isakmp(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
595 proto_tree *payload_kink_isakmp_tree;
596 proto_item *ti;
597 guint8 next_payload;
598 guint payload_length,isakmp_length;
599 int length, reported_length;
600 guint8 inner_next_pload;
601 guint8 qm, qmmaj, qmmin;
602 int start_payload_offset = 0; /* Keep the beginning of the payload offset */
603 tvbuff_t *isakmp_tvb;
605 payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH);
606 start_payload_offset = offset;
608 /* Make the subtree. */
609 ti = proto_tree_add_text(tree, tvb, offset, payload_length,"KINK_ISAKMP");
610 payload_kink_isakmp_tree = proto_item_add_subtree(ti, ett_payload_kink_isakmp);
612 next_payload = tvb_get_guint8(tvb, offset);
613 proto_tree_add_uint(payload_kink_isakmp_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
614 offset ++;
616 proto_tree_add_item(payload_kink_isakmp_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
617 offset ++;
619 ti = proto_tree_add_uint(payload_kink_isakmp_tree, hf_kink_payload_length, tvb, offset, 2, payload_length);
620 if(payload_length <= PAYLOAD_HEADER){
621 expert_add_info(pinfo, ti, &ei_kink_payload_length_small);
623 offset += 2;
625 inner_next_pload = tvb_get_guint8(tvb, offset);
626 proto_tree_add_uint(payload_kink_isakmp_tree, hf_kink_inner_next_pload, tvb, offset, 1, inner_next_pload);
627 offset += 1;
629 /* The qmmaj is first half 4bit field of the octet. Therefore, the logical product
630 * of the 1octet value and 0xf0 is performed, and performed 4bit right shift.
631 * The qmmin is second half 4bit field of the octet. Therefore, the logical product
632 * of the 1octet value and 0x0f is performed.
634 qm = tvb_get_guint8(tvb,offset);
635 qmmaj = (qm & FRONT_FOUR_BIT) >> VERSION_BIT_SHIFT;
636 qmmin = qm & SECOND_FOUR_BIT;
638 proto_tree_add_text(payload_kink_isakmp_tree, tvb, offset, 1, "QMVersion: %u.%u", qmmaj, qmmin);
639 offset += 1;
641 proto_tree_add_item(payload_kink_isakmp_tree, hf_kink_reserved16, tvb, offset, 2, ENC_BIG_ENDIAN);
642 offset += 2;
644 if(payload_length > PAYLOAD_HEADER){
645 isakmp_length = payload_length - PAYLOAD_HEADER;
646 length = tvb_length_remaining(tvb, offset);
647 if (length > (int)isakmp_length)
648 length = isakmp_length;
649 reported_length = tvb_reported_length_remaining(tvb, offset);
650 if (reported_length > (int)isakmp_length)
651 reported_length = isakmp_length;
652 isakmp_tvb = tvb_new_subset(tvb, offset, length, reported_length);
653 isakmp_dissect_payloads(isakmp_tvb, payload_kink_isakmp_tree, 1, inner_next_pload, 0, isakmp_length, pinfo);
656 /* This part consider the padding. Payload_length don't contain the padding. */
657 if(payload_length % PADDING != 0){
658 payload_length += (PADDING - (payload_length % PADDING));
660 offset = start_payload_offset + payload_length;
662 if(payload_length > 0) {
663 control_payload(pinfo, tvb, offset, next_payload, tree); /* Recur control_payload() */
667 static void
668 dissect_payload_kink_encrypt(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
669 proto_tree *payload_kink_encrypt_tree;
670 proto_item *ti;
671 guint8 next_payload;
672 guint payload_length;
673 #ifdef HAVE_KERBEROS
674 gint encrypt_length;
675 #endif
676 guint8 inner_next_pload;
677 guint16 inner_payload_length;
678 int start_payload_offset = 0; /* Keep the beginning of the payload offset */
680 payload_length = tvb_get_ntohs(tvb,offset + TO_PAYLOAD_LENGTH);
681 start_payload_offset = offset;
683 #ifdef HAVE_KERBEROS
684 encrypt_length = payload_length - FROM_NP_TO_PL;
685 #endif
686 /* Make the subtree */
687 ti = proto_tree_add_text(tree, tvb, offset, payload_length,"KINK_ENCRYPT");
688 payload_kink_encrypt_tree = proto_item_add_subtree(ti, ett_payload_kink_encrypt);
690 next_payload = tvb_get_guint8(tvb, offset);
691 proto_tree_add_uint(payload_kink_encrypt_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
692 offset ++;
694 proto_tree_add_item(payload_kink_encrypt_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
695 offset ++;
697 ti = proto_tree_add_uint(payload_kink_encrypt_tree, hf_kink_payload_length, tvb, offset, 2, payload_length);
698 if(payload_length <= PAYLOAD_HEADER){
699 expert_add_info(pinfo, ti, &ei_kink_payload_length_small);
701 offset += 2;
703 /* decrypt kink encrypt */
705 if(keytype != 0){
706 #ifdef HAVE_KERBEROS
707 tvbuff_t *next_tvb;
708 guint8 *plaintext=NULL;
710 next_tvb=tvb_new_subset(tvb, offset, MIN(tvb_length_remaining(tvb, offset), encrypt_length), encrypt_length);
711 plaintext=decrypt_krb5_data(tree, pinfo, 0, next_tvb, keytype, NULL);
712 if(plaintext){
713 next_tvb=tvb_new_child_real_data(tvb, plaintext, encrypt_length, encrypt_length);
714 tvb_set_free_cb(next_tvb, g_free);
715 add_new_data_source(pinfo, next_tvb, "decrypted kink encrypt");
716 dissect_decrypt_kink_encrypt(pinfo, next_tvb, tree, encrypt_length);
718 #endif
720 else{
721 inner_next_pload = tvb_get_guint8(tvb, offset);
722 proto_tree_add_uint(payload_kink_encrypt_tree, hf_kink_inner_next_pload, tvb, offset, 1, inner_next_pload);
723 offset += 1;
725 proto_tree_add_item(payload_kink_encrypt_tree, hf_kink_reserved24, tvb, offset, 3, ENC_BIG_ENDIAN);
726 offset += 3;
728 if(payload_length > PAYLOAD_HEADER){
729 inner_payload_length = payload_length - PAYLOAD_HEADER;
730 proto_tree_add_text(payload_kink_encrypt_tree, tvb, offset, inner_payload_length, "Payload");
731 /*offset += inner_payload_length;*/
734 /* This part consider the padding. Payload_length don't contain the padding. */
735 if(payload_length % PADDING !=0){
736 payload_length += (PADDING - (payload_length % PADDING));
738 offset = start_payload_offset + payload_length;
740 if(payload_length > 0) {
741 control_payload(pinfo, tvb, offset, next_payload, tree); /* Recur control_payload() */
745 #ifdef HAVE_KERBEROS
746 static void
747 dissect_decrypt_kink_encrypt(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree, int payload_length){
749 proto_tree *decrypt_kink_encrypt_tree;
750 proto_item *ti;
751 int offset=0;
752 guint8 next_payload;
754 ti = proto_tree_add_text(tree, tvb, offset, payload_length, "decrypted data");
755 decrypt_kink_encrypt_tree = proto_item_add_subtree(ti, ett_decrypt_kink_encrypt);
757 next_payload = tvb_get_guint8(tvb, offset);
759 proto_tree_add_uint(decrypt_kink_encrypt_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
760 offset ++;
762 proto_tree_add_item(decrypt_kink_encrypt_tree, hf_kink_reserved24, tvb, offset, 3, ENC_BIG_ENDIAN);
763 offset += 3;
765 control_payload(pinfo, tvb, offset, next_payload, decrypt_kink_encrypt_tree);
767 #endif
769 static void
770 dissect_payload_kink_error(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
771 proto_tree *payload_kink_error_tree;
772 proto_item *ti;
773 guint8 next_payload;
774 guint16 payload_length;
775 guint32 error_code;
776 int start_payload_offset = 0; /* Keep the beginning of the payload offset */
777 static const char *char_error_code[] = {
778 "KINK_OK",
779 "KINK_PROTOERR",
780 "KINK_INVDOI",
781 "KINK_INVMAJ",
782 "KINK_INVMIN",
783 "KINK_INTERR",
784 "KINK_BADQMVERS"
787 payload_length = tvb_get_ntohs(tvb,offset + TO_PAYLOAD_LENGTH);
788 start_payload_offset = offset;
790 /* Make the subtree */
791 ti = proto_tree_add_text(tree, tvb, offset, payload_length,"KINK_ERROR");
792 payload_kink_error_tree = proto_item_add_subtree(ti, ett_payload_kink_error);
794 next_payload = tvb_get_guint8(tvb, offset);
795 proto_tree_add_uint(payload_kink_error_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
796 offset ++;
798 proto_tree_add_item(payload_kink_error_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
799 offset ++;
801 ti = proto_tree_add_uint(payload_kink_error_tree, hf_kink_payload_length, tvb, offset, 2, payload_length);
802 if(payload_length != KINK_ERROR_LENGTH){
803 expert_add_info(pinfo, ti, &ei_kink_payload_length_mismatch);
805 offset += 2;
807 error_code = tvb_get_ntohl(tvb, offset);
809 /* Choosed the error code by erro_code */
810 switch(error_code){
811 case KINK_OK:
812 case KINK_PROTOERR:
813 case KINK_INVDOI:
814 case KINK_INVMAJ:
815 case KINK_INVMIN:
816 case KINK_INTERR:
817 case KINK_BADQMVERS:
818 proto_tree_add_text(payload_kink_error_tree, tvb, offset, 4, "ErrorCode: %s (%u)", char_error_code[error_code], error_code);
819 break;
820 default:
821 if(BOTTOM_RESERVED <= error_code && TOP_RESERVED >= error_code){
822 proto_tree_add_text(payload_kink_error_tree, tvb, offset, 4, "ErrorCode: %s (%u)", "RESERVED", error_code);
824 else if(BOTTOM_PRIVATE_USE <= error_code && TOP_PRIVATE_USE >= error_code){
825 proto_tree_add_text(payload_kink_error_tree, tvb, offset, 4, "ErrorCode: %s (%u)", "PRIVATE USE", error_code);
827 else{
828 proto_tree_add_text(payload_kink_error_tree, tvb, offset, 4, "ErrorCode: %s (%u)", "This Error Code is not Defined.", error_code);
830 break;
833 offset = start_payload_offset + KINK_ERROR_LENGTH;
834 control_payload(pinfo, tvb, offset, next_payload, tree); /* Recur control_payload() */
837 static void
838 dissect_payload_kink_not_defined(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree){
839 proto_tree *payload_kink_not_defined_tree;
840 proto_item *ti;
841 guint8 next_payload;
842 guint payload_length;
843 int start_payload_offset = 0; /* Keep the beginning of the payload offset */
845 start_payload_offset = offset;
846 payload_length = tvb_get_ntohs(tvb, offset + TO_PAYLOAD_LENGTH);
848 /* Make the subtree */
849 ti = proto_tree_add_text(tree, tvb, offset, payload_length, "UNKNOWN PAYLOAD");
850 payload_kink_not_defined_tree = proto_item_add_subtree(ti, ett_payload_not_defined);
852 next_payload = tvb_get_guint8(tvb, offset);
853 proto_tree_add_uint(payload_kink_not_defined_tree, hf_kink_next_payload, tvb, offset, 1, next_payload);
854 offset ++;
856 proto_tree_add_item(payload_kink_not_defined_tree, hf_kink_reserved8, tvb, offset, 1, ENC_BIG_ENDIAN);
857 offset ++;
859 proto_tree_add_uint(payload_kink_not_defined_tree, hf_kink_payload_length, tvb, offset, 2, payload_length);
861 /* This part consider the padding. Payload_length don't contain the padding. */
862 if(payload_length % PADDING != 0){
863 payload_length += (PADDING - (payload_length % PADDING));
865 offset = start_payload_offset + payload_length;
867 /* XXX - prevent an endless loop if payload_length is 0, don't know the correct way to handle this! */
868 if(payload_length > 0) {
869 control_payload(pinfo, tvb, offset, next_payload, tree);
873 /* Output part */
874 void
875 proto_register_kink(void) {
877 static hf_register_info hf[] = {
878 { &hf_kink_type,
879 { "Type", "kink.type",
880 FT_UINT8, BASE_DEC, VALS(kink_type_vals), 0x0,
881 "the type of the kink", HFILL }},
882 { &hf_kink_length,
883 { "Length", "kink.length",
884 FT_UINT16, BASE_DEC, NULL, 0x0,
885 "the length of the kink length", HFILL }},
886 { &hf_kink_transactionId,
887 { "Transaction ID", "kink.transactionId",
888 FT_UINT32, BASE_DEC, NULL, 0x0,
889 "the transactionID of kink", HFILL }},
890 { &hf_kink_checkSumLength,
891 { "Checksum Length", "kink.checkSumLength",
892 FT_UINT8, BASE_DEC, NULL, 0x0,
893 "the check sum length of kink", HFILL }},
894 { &hf_kink_A,
895 { "A", "kink.A",
896 FT_UINT8, BASE_DEC, VALS(kink_A_vals), 0x0,
897 "the A of kink", HFILL }},
898 { &hf_kink_reserved8,
899 { "Reserved", "kink.reserved",
900 FT_UINT8, BASE_DEC, NULL, 0x0,
901 "the reserved of kink", HFILL }},
902 { &hf_kink_reserved15,
903 { "Reserved", "kink.reserved",
904 FT_UINT16, BASE_DEC, NULL, SECOND_FIFTEEN_BIT,
905 "the reserved of kink", HFILL }},
906 { &hf_kink_reserved16,
907 { "Reserved", "kink.reserved",
908 FT_UINT16, BASE_DEC, NULL, 0,
909 "the reserved of kink", HFILL }},
910 { &hf_kink_reserved24,
911 { "Reserved", "kink.reserved",
912 FT_UINT24, BASE_DEC, NULL, 0,
913 "the reserved of kink", HFILL }},
914 { &hf_kink_checkSum,
915 { "Checksum", "kink.checkSum",
916 FT_BYTES, BASE_NONE, NULL, 0x0,
917 "the checkSum of kink", HFILL }},
918 { &hf_kink_next_payload,
919 { "Next Payload", "kink.nextPayload",
920 FT_UINT8, BASE_DEC, VALS(kink_next_payload), 0x0,
921 "the next payload of kink", HFILL }},
922 { &hf_kink_payload_length,
923 { "Payload Length", "kink.payloadLength",
924 FT_UINT8, BASE_DEC, NULL, 0x0,
925 NULL, HFILL }},
926 { &hf_kink_epoch,
927 { "EPOCH", "kink.epoch",
928 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0x0,
929 NULL, HFILL }},
930 { &hf_kink_inner_next_pload,
931 { "InnerNextPload", "kink.innerNextPload",
932 FT_UINT8, BASE_DEC, NULL, 0x0,
933 NULL, HFILL }},
934 { &hf_kink_realm_name_length,
935 { "RealmNameLength", "kink.realmNameLength",
936 FT_UINT16, BASE_DEC, NULL, 0,
937 NULL, HFILL }},
938 { &hf_kink_realm_name,
939 { "RealmName", "kink.realmName",
940 FT_STRING, BASE_NONE, NULL, 0,
941 NULL, HFILL }},
942 { &hf_kink_princ_name_length,
943 { "PrincNameLength", "kink.princNameLength",
944 FT_UINT16, BASE_DEC, NULL, 0,
945 NULL, HFILL }},
946 { &hf_kink_princ_name,
947 { "PrincName", "kink.princName",
948 FT_STRING, BASE_NONE, NULL, 0,
949 NULL, HFILL }},
950 { &hf_kink_tgt_length,
951 { "TGT Length", "kink.tgtLength",
952 FT_UINT16, BASE_DEC, NULL, 0,
953 NULL, HFILL }},
954 { &hf_kink_tgt,
955 { "TGT", "kink.tgt",
956 FT_STRING, BASE_NONE, NULL, 0,
957 NULL, HFILL }},
960 /* Argument for making the subtree. */
961 static gint *ett[] = {
962 &ett_kink,
963 /* &ett_kink_version, */
964 &ett_kink_payload,
965 &ett_payload_kink_ap_req,
966 &ett_payload_kink_ap_rep,
967 &ett_payload_kink_krb_error,
968 &ett_payload_kink_tgt_req,
969 &ett_payload_kink_tgt_rep,
970 &ett_payload_kink_isakmp,
971 &ett_payload_kink_encrypt,
972 &ett_payload_kink_error,
973 &ett_payload_not_defined,
974 &ett_decrypt_kink_encrypt,
978 static ei_register_info ei[] = {
979 { &ei_kink_payload_length_small, { "kink.payload_length_small", PI_PROTOCOL, PI_WARN, "This Payload Length is too small", EXPFILL }},
980 { &ei_kink_payload_length_mismatch, { "kink.payload_length_mismatch", PI_PROTOCOL, PI_WARN, "This Payload Length is mismatch", EXPFILL }},
983 expert_module_t* expert_kink;
985 proto_kink = proto_register_protocol("Kerberized Internet Negotiation of Key", "KINK", "kink");
986 proto_register_field_array(proto_kink, hf, array_length(hf));
987 proto_register_subtree_array(ett, array_length(ett));
988 expert_kink = expert_register_protocol(proto_kink);
989 expert_register_field_array(expert_kink, ei, array_length(ei));
993 void proto_reg_handoff_kink(void) {
995 dissector_handle_t kink_handle = NULL;
997 kink_handle = create_dissector_handle(dissect_kink, proto_kink);
999 dissector_add_uint("udp.port", KINK_PORT, kink_handle);