3db149a2d083b8bd02e905c68f968ca5bd38625c
[obnox/wireshark/wip.git] / packet-isakmp.c
1 /* packet-gre.c
2  * Routines for the Internet Security Association and Key Management Protocol (ISAKMP)
3  * Brad Robel-Forrest <brad.robel-forrest@watchguard.com>
4  *
5  * $Id: packet-isakmp.c,v 1.3 1999/07/06 06:10:31 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@unicom.net>
9  * Copyright 1998 Gerald Combs
10  *
11  * 
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  * 
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  * 
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #ifdef HAVE_SYS_TYPES_H
32 # include <sys/types.h>
33 #endif
34
35 #include <stdio.h>
36 #include <netinet/in.h>
37 #include <glib.h>
38 #include "packet.h"
39
40 #ifdef NEED_SNPRINTF_H
41 # ifdef HAVE_STDARG_H
42 #  include <stdarg.h>
43 # else
44 #  include <varargs.h>
45 # endif
46 # include "snprintf.h"
47 #endif
48
49 #define NUM_PROTO_TYPES 5
50 #define proto2str(t)    \
51   ((t < NUM_PROTO_TYPES) ? prototypestr[t] : "UNKNOWN-PROTO-TYPE")
52
53 static const char *prototypestr[NUM_PROTO_TYPES] = {
54   "RESERVED",
55   "ISAKMP",
56   "IPSEC_AH",
57   "IPSEC_ESP",
58   "IPCOMP"
59 };
60
61 #define NUM_ATT_TYPES   13
62 #define atttype2str(t)  \
63   ((t < NUM_ATT_TYPES) ? atttypestr[t] : "UNKNOWN-ATTRIBUTE-TYPE")
64
65 static const char *atttypestr[NUM_ATT_TYPES] = {
66   "UNKNOWN-ATTRIBUTE-TYPE",
67   "SA-Life-Type",
68   "SA-Life-Duration",
69   "Group-Description",
70   "Encapsulation-Mode",
71   "Authentication-Algorithm",
72   "Key-Length",
73   "Key-Rounds",
74   "Compress-Dictinary-Size",
75   "Compress-Private-Algorithm"
76   "UNKNOWN-ATTRIBUTE-TYPE",
77   "Oakley-Life",
78   "Oakley-Value",
79   "Oakley-Life-Duration"
80 };
81
82 #define NUM_TRANS_TYPES 2
83 #define trans2str(t)    \
84   ((t < NUM_TRANS_TYPES) ? transtypestr[t] : "UNKNOWN-TRANS-TYPE")
85
86 static const char *transtypestr[NUM_TRANS_TYPES] = {
87   "RESERVED",
88   "KEY_IKE"
89 };
90
91 #define NUM_ID_TYPES    12
92 #define id2str(t)       \
93   ((t < NUM_ID_TYPES) ? idtypestr[t] : "UNKNOWN-ID-TYPE")
94
95 static const char *idtypestr[NUM_ID_TYPES] = {
96   "RESERVED",
97   "IPV4_ADDR",
98   "FQDN",
99   "USER_FQDN",
100   "IPV4_ADDR_SUBNET",
101   "IPV6_ADDR",
102   "IPV6_ADDR_SUBNET",
103   "IPV4_ADDR_RANGE",
104   "IPV6_ADDR_RANGE",
105   "DER_ASN1_DN",
106   "DER_ASN1_GN",
107   "KEY_ID"
108 };
109
110 struct isakmp_hdr {
111   guint8        icookie[8];
112   guint8        rcookie[8];
113   guint8        next_payload;
114   guint8        version;
115   guint8        exch_type;
116   guint8        flags;
117 #define E_FLAG          0x01
118 #define C_FLAG          0x02
119 #define A_FLAG          0x04
120   guint32       message_id;
121   guint32       length;
122 };
123
124 struct sa_hdr {
125   guint8        next_payload;
126   guint8        reserved;
127   guint16       length;
128   guint32       doi;
129   guint32       situation;
130 };
131
132 struct proposal_hdr {
133   guint8        next_payload;
134   guint8        reserved;
135   guint16       length;
136   guint8        proposal_num;
137   guint8        protocol_id;
138   guint8        spi_size;
139   guint8        num_transforms;
140 };
141
142 struct trans_hdr {
143   guint8        next_payload;
144   guint8        reserved;
145   guint16       length;
146   guint8        transform_num;
147   guint8        transform_id;
148   guint16       reserved2;
149 };
150
151 #define TRANS_LEN(p)    (pntohs(&((struct trans_hdr *)(p))->length))
152
153 struct ke_hdr {
154   guint8        next_payload;
155   guint8        reserved;
156   guint16       length;
157 };
158
159 struct id_hdr {
160   guint8        next_payload;
161   guint8        reserved;
162   guint16       length;
163   guint8        id_type;
164   guint8        protocol_id;
165   guint16       port;
166 };
167
168 struct cert_hdr {
169   guint8        next_payload;
170   guint8        reserved;
171   guint16       length;
172   guint8        cert_enc;
173 };
174
175 struct certreq_hdr {
176   guint8        next_payload;
177   guint8        reserved;
178   guint16       length;
179   guint8        cert_type;
180 };
181
182 struct hash_hdr {
183   guint8        next_payload;
184   guint8        reserved;
185   guint16       length;
186 };
187
188 struct sig_hdr {
189   guint8        next_payload;
190   guint8        reserved;
191   guint16       length;
192 };
193
194 struct nonce_hdr {
195   guint8        next_payload;
196   guint8        reserved;
197   guint16       length;
198 };
199
200 struct notif_hdr {
201   guint8        next_payload;
202   guint8        reserved;
203   guint16       length;
204   guint32       doi;
205   guint8        protocol_id;
206   guint8        spi_size;
207   guint16       msgtype;
208 };
209
210 struct delete_hdr {
211   guint8        next_payload;
212   guint8        reserved;
213   guint16       length;
214   guint32       doi;
215   guint8        protocol_id;
216   guint8        spi_size;
217   guint16       num_spis;
218 };
219
220 struct vid_hdr {
221   guint8        next_payload;
222   guint8        reserved;
223   guint16       length;
224 };
225
226 static void dissect_none(const u_char *, int, frame_data *, proto_tree *);
227 static void dissect_sa(const u_char *, int, frame_data *, proto_tree *);
228 static void dissect_proposal(const u_char *, int, frame_data *, proto_tree *);
229 static void dissect_transform(const u_char *, int, frame_data *, proto_tree *);
230 static void dissect_key_exch(const u_char *, int, frame_data *, proto_tree *);
231 static void dissect_id(const u_char *, int, frame_data *, proto_tree *);
232 static void dissect_cert(const u_char *, int, frame_data *, proto_tree *);
233 static void dissect_certreq(const u_char *, int, frame_data *, proto_tree *);
234 static void dissect_hash(const u_char *, int, frame_data *, proto_tree *);
235 static void dissect_sig(const u_char *, int, frame_data *, proto_tree *);
236 static void dissect_nonce(const u_char *, int, frame_data *, proto_tree *);
237 static void dissect_notif(const u_char *, int, frame_data *, proto_tree *);
238 static void dissect_delete(const u_char *, int, frame_data *, proto_tree *);
239 static void dissect_vid(const u_char *, int, frame_data *, proto_tree *);
240
241 static const char *payloadtype2str(guint8);
242 static const char *exchtype2str(guint8);
243 static const char *doitype2str(guint32);
244 static const char *msgtype2str(guint16);
245 static const char *situation2str(guint32);
246 static const char *value2str(guint16, guint16);
247 static const char *num2str(const guint8 *, guint16);
248
249 #define NUM_LOAD_TYPES          14
250 #define loadtype2str(t) \
251   ((t < NUM_LOAD_TYPES) ? strfuncs[t].str : "Unknown payload type")
252
253 static struct strfunc {
254   const char *  str;
255   void          (*func)(const u_char *, int, frame_data *, proto_tree *);
256 } strfuncs[NUM_LOAD_TYPES] = {
257   {"NONE",                      dissect_none      },
258   {"Security Association",      dissect_sa        },
259   {"Proposal",                  dissect_proposal  },
260   {"Transform",                 dissect_transform },
261   {"Key Exchange",              dissect_key_exch  },
262   {"Identification",            dissect_id        },
263   {"Certificate",               dissect_cert      },
264   {"Certificate Request",       dissect_certreq   },
265   {"Hash",                      dissect_hash      },
266   {"Signature",                 dissect_sig       },
267   {"Nonce",                     dissect_nonce     },
268   {"Notification",              dissect_notif     },
269   {"Delete",                    dissect_delete    },
270   {"Vendor ID",                 dissect_vid       }
271 };
272
273 void dissect_isakmp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
274   
275   struct isakmp_hdr *   hdr = (struct isakmp_hdr *)(pd + offset);
276   guint32               len;
277   
278   if (check_col(fd, COL_PROTOCOL))
279     col_add_str(fd, COL_PROTOCOL, "ISAKMP");
280   
281   len = pntohl(&hdr->length);
282   
283   if (check_col(fd, COL_INFO))
284     col_add_fstr(fd, COL_INFO, "%s", exchtype2str(hdr->exch_type));
285   
286   if (fd->cap_len > offset && tree) {
287     proto_item *        ti;
288     proto_tree *        isakmp_tree;
289     
290     ti = proto_tree_add_item(tree, offset, len,
291                              "Internet Security Association and Key Management Protocol");
292     isakmp_tree = proto_tree_new();
293     proto_item_add_subtree(ti, isakmp_tree, ETT_ISAKMP);
294     
295     proto_tree_add_item(isakmp_tree, offset, sizeof(hdr->icookie),
296                         "Initiator cookie");
297     offset += sizeof(hdr->icookie);
298     
299     proto_tree_add_item(isakmp_tree, offset, sizeof(hdr->rcookie),
300                         "Responder cookie");
301     offset += sizeof(hdr->rcookie);
302
303     proto_tree_add_item(isakmp_tree, offset, sizeof(hdr->next_payload),
304                         "Next payload: %s (%u)",
305                         payloadtype2str(hdr->next_payload), hdr->next_payload);
306     offset += sizeof(hdr->next_payload);
307
308     proto_tree_add_item(isakmp_tree, offset, sizeof(hdr->version),
309                         "Version: %u.%u",
310                         hi_nibble(hdr->version), lo_nibble(hdr->version));
311     offset += sizeof(hdr->version);
312     
313     proto_tree_add_item(isakmp_tree, offset, sizeof(hdr->exch_type),
314                         "Exchange type: %s (%u)",
315                         exchtype2str(hdr->exch_type), hdr->exch_type);
316     offset += sizeof(hdr->exch_type);
317     
318     {
319       proto_item *      fti;
320       proto_tree *      ftree;
321       
322       fti   = proto_tree_add_item(isakmp_tree, offset, sizeof(hdr->flags), "Flags");
323       ftree = proto_tree_new();
324       proto_item_add_subtree(fti, ftree, ETT_ISAKMP_FLAGS);
325       
326       proto_tree_add_item(ftree, offset, 1, "%s",
327                           decode_boolean_bitfield(hdr->flags, E_FLAG, sizeof(hdr->flags)*8,
328                                                   "Encryption", "No encryption"));
329       proto_tree_add_item(ftree, offset, 1, "%s",
330                           decode_boolean_bitfield(hdr->flags, C_FLAG, sizeof(hdr->flags)*8,
331                                                   "Commit", "No commit"));
332       proto_tree_add_item(ftree, offset, 1, "%s",
333                           decode_boolean_bitfield(hdr->flags, A_FLAG, sizeof(hdr->flags)*8,
334                                                   "Authentication", "No authentication"));
335       offset += sizeof(hdr->flags);
336     }
337
338     proto_tree_add_item(isakmp_tree, offset, sizeof(hdr->message_id), "Message ID");
339     offset += sizeof(hdr->message_id);
340     
341     proto_tree_add_item(isakmp_tree, offset, sizeof(hdr->length),
342                         "Length: %u", len);
343     offset += sizeof(hdr->length);
344
345     if (hdr->next_payload < NUM_LOAD_TYPES)
346       (*strfuncs[hdr->next_payload].func)(pd, offset, fd, isakmp_tree);
347     else
348       dissect_data(pd, offset, fd, isakmp_tree);
349   }
350 }
351
352 static void
353 dissect_none(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
354 }
355
356 static void
357 dissect_sa(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
358
359   struct sa_hdr *       hdr       = (struct sa_hdr *)(pd + offset);
360   guint16               length    = pntohs(&hdr->length);
361   guint32               doi       = pntohl(&hdr->doi);
362   guint32               situation = pntohl(&hdr->situation);
363   proto_item *          ti        = proto_tree_add_item(tree, offset, length, "Security Association payload");
364   proto_tree *          ntree     = proto_tree_new();
365
366   proto_item_add_subtree(ti, ntree, ETT_ISAKMP_PAYLOAD);
367   
368   proto_tree_add_item(ntree, offset, sizeof(hdr->next_payload),
369                       "Next payload: %s (%u)",
370                       payloadtype2str(hdr->next_payload), hdr->next_payload);
371   offset += sizeof(hdr->next_payload) * 2;
372   
373   proto_tree_add_item(ntree, offset, sizeof(length),
374                       "Length: %u", length);
375   offset += sizeof(length);
376   
377   proto_tree_add_item(ntree, offset, sizeof(doi),
378                       "Domain of interpretation: %s (%u)",
379                       doitype2str(doi), doi);
380   offset += sizeof(doi);
381   
382   proto_tree_add_item(ntree, offset, sizeof(situation),
383                       "Situation: %s (%u)",
384                       situation2str(situation), situation);
385   offset += sizeof(situation);
386   
387   dissect_proposal(pd, offset, fd, ntree);
388   offset += (length - sizeof(*hdr));
389   
390   if (hdr->next_payload < NUM_LOAD_TYPES)
391     (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
392   else
393     dissect_data(pd, offset, fd, tree);
394 }
395
396 static void
397 dissect_proposal(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
398
399   struct proposal_hdr * hdr     = (struct proposal_hdr *)(pd + offset);
400   guint16               length  = pntohs(&hdr->length);
401   proto_item *          ti      = proto_tree_add_item(tree, offset, length, "Proposal payload");
402   proto_tree *          ntree   = proto_tree_new();
403   guint8                i;
404   
405   proto_item_add_subtree(ti, ntree, ETT_ISAKMP_PAYLOAD);
406   
407   proto_tree_add_item(ntree, offset, sizeof(hdr->next_payload),
408                       "Next payload: %s (%u)",
409                       payloadtype2str(hdr->next_payload), hdr->next_payload);
410   offset += sizeof(hdr->next_payload) * 2;
411   
412   proto_tree_add_item(ntree, offset, sizeof(length),
413                       "Length: %u", length);
414   offset += sizeof(length);
415   
416   proto_tree_add_item(ntree, offset, sizeof(hdr->proposal_num),
417                       "Proposal number: %u", hdr->proposal_num);
418   offset += sizeof(hdr->proposal_num);
419   
420   proto_tree_add_item(ntree, offset, sizeof(hdr->protocol_id),
421                       "Protocol ID: %s (%u)",
422                       proto2str(hdr->protocol_id), hdr->protocol_id);
423   offset += sizeof(hdr->protocol_id);
424   
425   proto_tree_add_item(ntree, offset, sizeof(hdr->spi_size),
426                       "SPI size: %u", hdr->spi_size);
427   offset += sizeof(hdr->spi_size);
428   
429   if (hdr->spi_size) {
430     proto_tree_add_item(ntree, offset, hdr->spi_size, "SPI");
431     offset += hdr->spi_size;
432   }
433
434   proto_tree_add_item(ntree, offset, sizeof(hdr->num_transforms),
435                       "Number of transforms: %u", hdr->num_transforms);
436   offset += sizeof(hdr->num_transforms);
437   
438   for (i = 0; i < hdr->num_transforms; ++i) {
439     dissect_transform(pd, offset, fd, ntree);
440     offset += TRANS_LEN(pd+offset);
441   }
442
443   if (hdr->next_payload < NUM_LOAD_TYPES)
444     (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
445   else
446     dissect_data(pd, offset, fd, tree);
447 }
448
449 static void
450 dissect_transform(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
451
452   struct trans_hdr *    hdr     = (struct trans_hdr *)(pd + offset);
453   guint16               length  = pntohs(&hdr->length);
454   proto_item *          ti      = proto_tree_add_item(tree, offset, length, "Transform payload");
455   proto_tree *          ntree   = proto_tree_new();
456
457   proto_item_add_subtree(ti, ntree, ETT_ISAKMP_PAYLOAD);
458   
459   proto_tree_add_item(ntree, offset, sizeof(hdr->next_payload),
460                       "Next payload: %s (%u)",
461                       payloadtype2str(hdr->next_payload), hdr->next_payload);
462   offset += sizeof(hdr->next_payload) * 2;
463   
464   proto_tree_add_item(ntree, offset, sizeof(length),
465                       "Length: %u", length);
466   offset += sizeof(length);
467   
468   proto_tree_add_item(ntree, offset, sizeof(hdr->transform_num),
469                       "Transform number: %u", hdr->transform_num);
470   offset += sizeof(hdr->transform_num);
471   
472   proto_tree_add_item(ntree, offset, sizeof(hdr->transform_id),
473                       "Transform ID: %s (%u)",
474                       trans2str(hdr->transform_id), hdr->transform_id);
475   offset += sizeof(hdr->transform_id) + sizeof(hdr->reserved2);
476   
477   length -= sizeof(*hdr);
478   while (length) {
479     guint16 type    = pntohs(pd + offset) & 0x7fff;
480     guint16 val_len = pntohs(pd + offset + 2);
481     
482     if (pd[offset] & 0xf0) {
483       proto_tree_add_item(ntree, offset, 4,
484                           "%s (%u): %s (%u)",
485                           atttype2str(type), type,
486                           value2str(type, val_len), val_len);
487       offset += 4;
488       length -= 4;
489     }
490     else {
491       guint16   pack_len = 4 + val_len;
492       
493       proto_tree_add_item(ntree, offset, pack_len,
494                           "%s (%u): %s",
495                           atttype2str(type), type,
496                           num2str(pd + offset + 4, val_len));
497       offset += pack_len;
498       length -= pack_len;
499     }
500   }
501
502   if (hdr->next_payload < NUM_LOAD_TYPES)
503     (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
504   else
505     dissect_data(pd, offset, fd, tree);
506 }
507
508 static void
509 dissect_key_exch(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
510
511   struct ke_hdr *       hdr     = (struct ke_hdr *)(pd + offset);
512   guint16               length  = pntohs(&hdr->length);
513   proto_item *          ti      = proto_tree_add_item(tree, offset, length, "Key Exchange payload");
514   proto_tree *          ntree   = proto_tree_new();
515
516   proto_item_add_subtree(ti, ntree, ETT_ISAKMP_PAYLOAD);
517   
518   proto_tree_add_item(ntree, offset, sizeof(hdr->next_payload),
519                       "Next payload: %s (%u)",
520                       payloadtype2str(hdr->next_payload), hdr->next_payload);
521   offset += sizeof(hdr->next_payload) * 2;
522   
523   proto_tree_add_item(ntree, offset, sizeof(length),
524                       "Length: %u", length);
525   offset += sizeof(length);
526   
527   proto_tree_add_item(ntree, offset, length - sizeof(*hdr), "Key Exchange Data");
528   offset += (length - sizeof(*hdr));
529   
530   if (hdr->next_payload < NUM_LOAD_TYPES)
531     (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
532   else
533     dissect_data(pd, offset, fd, tree);
534 }
535
536 static void
537 dissect_id(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
538
539   struct id_hdr *       hdr     = (struct id_hdr *)(pd + offset);
540   guint16               length  = pntohs(&hdr->length);
541   proto_item *          ti      = proto_tree_add_item(tree, offset, length, "Identification payload");
542   proto_tree *          ntree   = proto_tree_new();
543
544   proto_item_add_subtree(ti, ntree, ETT_ISAKMP_PAYLOAD);
545   
546   proto_tree_add_item(ntree, offset, sizeof(hdr->next_payload),
547                       "Next payload: %s (%u)",
548                       payloadtype2str(hdr->next_payload), hdr->next_payload);
549   offset += sizeof(hdr->next_payload) * 2;
550   
551   proto_tree_add_item(ntree, offset, sizeof(length),
552                       "Length: %u", length);
553   offset += sizeof(length);
554   
555   proto_tree_add_item(ntree, offset, sizeof(hdr->id_type),
556                       "ID type: %s (%u)", id2str(hdr->id_type), hdr->id_type);
557   offset += sizeof(hdr->id_type);
558
559   proto_tree_add_item(ntree, offset, sizeof(hdr->protocol_id),
560                       "Protocol ID: %u", hdr->protocol_id);
561   offset += sizeof(hdr->protocol_id);
562   
563   proto_tree_add_item(ntree, offset, sizeof(hdr->port),
564                       "Port: %u", pntohs(&hdr->port));
565   offset += sizeof(hdr->port);
566   
567   switch (hdr->id_type) {
568     case 1:
569     case 4:
570       proto_tree_add_item(ntree, offset, length-sizeof(*hdr),
571                           "Identification data: %s", ip_to_str(pd+offset));
572       break;
573     case 2:
574     case 3:
575       proto_tree_add_item(ntree, offset, length-sizeof(*hdr),
576                           "Identification data: %s", (char *)(pd+offset));
577       break;
578     default:
579       proto_tree_add_item(ntree, offset, length - sizeof(*hdr), "Identification Data");
580   }
581   offset += (length - sizeof(*hdr));
582   
583   if (hdr->next_payload < NUM_LOAD_TYPES)
584     (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
585   else
586     dissect_data(pd, offset, fd, tree);
587 }
588
589 static void
590 dissect_cert(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
591
592   struct cert_hdr *     hdr     = (struct cert_hdr *)(pd + offset);
593   guint16               length  = pntohs(&hdr->length);
594   proto_item *          ti      = proto_tree_add_item(tree, offset, length, "Certificate payload");
595   proto_tree *          ntree   = proto_tree_new();
596
597   proto_item_add_subtree(ti, ntree, ETT_ISAKMP_PAYLOAD);
598   
599   proto_tree_add_item(ntree, offset, sizeof(hdr->next_payload),
600                       "Next payload: %s (%u)",
601                       payloadtype2str(hdr->next_payload), hdr->next_payload);
602   offset += sizeof(hdr->next_payload) * 2;
603   
604   proto_tree_add_item(ntree, offset, sizeof(length),
605                       "Length: %u", length);
606   offset += sizeof(length);
607   
608   proto_tree_add_item(ntree, offset, sizeof(hdr->cert_enc),
609                       "Certificate encoding: %u", hdr->cert_enc);
610   offset += sizeof(hdr->cert_enc);
611
612   proto_tree_add_item(ntree, offset, length - sizeof(*hdr), "Certificate Data");
613   offset += (length - sizeof(*hdr));
614   
615   if (hdr->next_payload < NUM_LOAD_TYPES)
616     (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
617   else
618     dissect_data(pd, offset, fd, tree);
619 }
620
621 static void
622 dissect_certreq(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
623
624   struct certreq_hdr *  hdr     = (struct certreq_hdr *)(pd + offset);
625   guint16               length  = pntohs(&hdr->length);
626   proto_item *          ti      = proto_tree_add_item(tree, offset, length, "Certificate Request payload");
627   proto_tree *          ntree   = proto_tree_new();
628
629   proto_item_add_subtree(ti, ntree, ETT_ISAKMP_PAYLOAD);
630   
631   proto_tree_add_item(ntree, offset, sizeof(hdr->next_payload),
632                       "Next payload: %s (%u)",
633                       payloadtype2str(hdr->next_payload), hdr->next_payload);
634   offset += sizeof(hdr->next_payload) * 2;
635   
636   proto_tree_add_item(ntree, offset, sizeof(length),
637                       "Length: %u", length);
638   offset += sizeof(length);
639   
640   proto_tree_add_item(ntree, offset, sizeof(hdr->cert_type),
641                       "Certificate type: %u", hdr->cert_type);
642   offset += sizeof(hdr->cert_type);
643
644   proto_tree_add_item(ntree, offset, length - sizeof(*hdr), "Certificate Authority");
645   offset += (length - sizeof(*hdr));
646   
647   if (hdr->next_payload < NUM_LOAD_TYPES)
648     (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
649   else
650     dissect_data(pd, offset, fd, tree);
651 }
652
653 static void
654 dissect_hash(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
655
656   struct hash_hdr *     hdr     = (struct hash_hdr *)(pd + offset);
657   guint16               length  = pntohs(&hdr->length);
658   proto_item *          ti      = proto_tree_add_item(tree, offset, length, "Hash payload");
659   proto_tree *          ntree   = proto_tree_new();
660
661   proto_item_add_subtree(ti, ntree, ETT_ISAKMP_PAYLOAD);
662   
663   proto_tree_add_item(ntree, offset, sizeof(hdr->next_payload),
664                       "Next payload: %s (%u)",
665                       payloadtype2str(hdr->next_payload), hdr->next_payload);
666   offset += sizeof(hdr->next_payload) * 2;
667   
668   proto_tree_add_item(ntree, offset, sizeof(length),
669                       "Length: %u", length);
670   offset += sizeof(length);
671   
672   proto_tree_add_item(ntree, offset, length - sizeof(*hdr), "Hash Data");
673   offset += (length - sizeof(*hdr));
674   
675   if (hdr->next_payload < NUM_LOAD_TYPES)
676     (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
677   else
678     dissect_data(pd, offset, fd, tree);
679 }
680
681 static void
682 dissect_sig(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
683
684   struct sig_hdr *      hdr     = (struct sig_hdr *)(pd + offset);
685   guint16               length  = pntohs(&hdr->length);
686   proto_item *          ti      = proto_tree_add_item(tree, offset, length, "Signature payload");
687   proto_tree *          ntree   = proto_tree_new();
688
689   proto_item_add_subtree(ti, ntree, ETT_ISAKMP_PAYLOAD);
690   
691   proto_tree_add_item(ntree, offset, sizeof(hdr->next_payload),
692                       "Next payload: %s (%u)",
693                       payloadtype2str(hdr->next_payload), hdr->next_payload);
694   offset += sizeof(hdr->next_payload) * 2;
695   
696   proto_tree_add_item(ntree, offset, sizeof(length),
697                       "Length: %u", length);
698   offset += sizeof(length);
699   
700   proto_tree_add_item(ntree, offset, length - sizeof(*hdr), "Signature Data");
701   offset += (length - sizeof(*hdr));
702   
703   if (hdr->next_payload < NUM_LOAD_TYPES)
704     (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
705   else
706     dissect_data(pd, offset, fd, tree);
707 }
708
709 static void
710 dissect_nonce(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
711
712   struct nonce_hdr *    hdr     = (struct nonce_hdr *)(pd + offset);
713   guint16               length  = pntohs(&hdr->length);
714   proto_item *          ti      = proto_tree_add_item(tree, offset, length, "Nonce payload");
715   proto_tree *          ntree   = proto_tree_new();
716
717   proto_item_add_subtree(ti, ntree, ETT_ISAKMP_PAYLOAD);
718   
719   proto_tree_add_item(ntree, offset, sizeof(hdr->next_payload),
720                       "Next payload: %s (%u)",
721                       payloadtype2str(hdr->next_payload), hdr->next_payload);
722   offset += sizeof(hdr->next_payload) * 2;
723   
724   proto_tree_add_item(ntree, offset, sizeof(length),
725                       "Length: %u", length);
726   offset += sizeof(length);
727   
728   proto_tree_add_item(ntree, offset, length - sizeof(*hdr), "Nonce Data");
729   offset += (length - sizeof(*hdr));
730   
731   if (hdr->next_payload < NUM_LOAD_TYPES)
732     (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
733   else
734     dissect_data(pd, offset, fd, tree);
735 }
736
737 static void
738 dissect_notif(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
739
740   struct notif_hdr *    hdr     = (struct notif_hdr *)(pd + offset);
741   guint16               length  = pntohs(&hdr->length);
742   guint32               doi     = pntohl(&hdr->doi);
743   guint16               msgtype = pntohs(&hdr->msgtype);
744   proto_item *          ti      = proto_tree_add_item(tree, offset, length, "Notification payload");
745   proto_tree *          ntree   = proto_tree_new();
746
747   proto_item_add_subtree(ti, ntree, ETT_ISAKMP_PAYLOAD);
748   
749   proto_tree_add_item(ntree, offset, sizeof(hdr->next_payload),
750                       "Next payload: %s (%u)",
751                       payloadtype2str(hdr->next_payload), hdr->next_payload);
752   offset += sizeof(hdr->next_payload) * 2;
753   
754   proto_tree_add_item(ntree, offset, sizeof(length),
755                       "Length: %u", length);
756   offset += sizeof(length);
757   
758   proto_tree_add_item(ntree, offset, sizeof(doi),
759                       "Domain of Interpretation: %s (%u)", doitype2str(doi), doi);
760   offset += sizeof(doi);
761
762   proto_tree_add_item(ntree, offset, sizeof(hdr->protocol_id),
763                       "Protocol ID: %s (%u)",
764                       proto2str(hdr->protocol_id), hdr->protocol_id);
765   offset += sizeof(hdr->protocol_id);
766   
767   proto_tree_add_item(ntree, offset, sizeof(hdr->spi_size),
768                       "SPI size: %u", hdr->spi_size);
769   offset += sizeof(hdr->spi_size);
770   
771   proto_tree_add_item(ntree, offset, sizeof(msgtype),
772                       "Message type: %s (%u)", msgtype2str(msgtype), msgtype);
773   offset += sizeof(msgtype);
774
775   if (hdr->spi_size) {
776     proto_tree_add_item(ntree, offset, hdr->spi_size, "Security Parameter Index");
777     offset += hdr->spi_size;
778   }
779
780   if (length - sizeof(*hdr)) {
781     proto_tree_add_item(ntree, offset, length - sizeof(*hdr) - hdr->spi_size,
782                         "Notification Data");
783     offset += (length - sizeof(*hdr) - hdr->spi_size);
784   }
785   
786   if (hdr->next_payload < NUM_LOAD_TYPES)
787     (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
788   else
789     dissect_data(pd, offset, fd, tree);
790 }
791
792 static void
793 dissect_delete(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
794
795   struct delete_hdr *   hdr      = (struct delete_hdr *)(pd + offset);
796   guint16               length   = pntohs(&hdr->length);
797   guint32               doi      = pntohl(&hdr->doi);
798   guint16               num_spis = pntohs(&hdr->num_spis);
799   proto_item *          ti       = proto_tree_add_item(tree, offset, length, "Delete payload");
800   proto_tree *          ntree    = proto_tree_new();
801   guint16               i;
802   
803   proto_item_add_subtree(ti, ntree, ETT_ISAKMP_PAYLOAD);
804   
805   proto_tree_add_item(ntree, offset, sizeof(hdr->next_payload),
806                       "Next payload: %s (%u)",
807                       payloadtype2str(hdr->next_payload), hdr->next_payload);
808   offset += sizeof(hdr->next_payload) * 2;
809   
810   proto_tree_add_item(ntree, offset, sizeof(length),
811                       "Length: %u", length);
812   offset += sizeof(length);
813   
814   proto_tree_add_item(ntree, offset, sizeof(doi),
815                       "Domain of Interpretation: %s (%u)", doitype2str(doi), doi);
816   offset += sizeof(doi);
817
818   proto_tree_add_item(ntree, offset, sizeof(hdr->protocol_id),
819                       "Protocol ID: %s (%u)",
820                       proto2str(hdr->protocol_id), hdr->protocol_id);
821   offset += sizeof(hdr->protocol_id);
822   
823   proto_tree_add_item(ntree, offset, sizeof(hdr->spi_size),
824                       "SPI size: %u", hdr->spi_size);
825   offset += sizeof(hdr->spi_size);
826   
827   proto_tree_add_item(ntree, offset, num_spis,
828                       "Number of SPIs: %u", num_spis);
829   offset += sizeof(hdr->num_spis);
830   
831   for (i = 0; i < num_spis; ++i) {
832     proto_tree_add_item(ntree, offset, hdr->spi_size,
833                         "SPI (%d)", i);
834     offset += hdr->spi_size;
835   }
836
837   if (hdr->next_payload < NUM_LOAD_TYPES)
838     (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
839   else
840     dissect_data(pd, offset, fd, tree);
841 }
842
843 static void
844 dissect_vid(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) {
845
846   struct vid_hdr *      hdr     = (struct vid_hdr *)(pd + offset);
847   guint16               length  = pntohs(&hdr->length);
848   proto_item *          ti      = proto_tree_add_item(tree, offset, length, "Vendor ID payload");
849   proto_tree *          ntree   = proto_tree_new();
850
851   proto_item_add_subtree(ti, ntree, ETT_ISAKMP_PAYLOAD);
852   
853   proto_tree_add_item(ntree, offset, sizeof(hdr->next_payload),
854                       "Next payload: %s (%u)",
855                       payloadtype2str(hdr->next_payload), hdr->next_payload);
856   offset += sizeof(hdr->next_payload) * 2;
857   
858   proto_tree_add_item(ntree, offset, sizeof(length),
859                       "Length: %u", length);
860   offset += sizeof(length);
861   
862   proto_tree_add_item(ntree, offset, length - sizeof(*hdr), "Vendor ID");
863   offset += (length - sizeof(*hdr));
864   
865   if (hdr->next_payload < NUM_LOAD_TYPES)
866     (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree);
867   else
868     dissect_data(pd, offset, fd, tree);
869 }
870
871 static const char *
872 payloadtype2str(guint8 type) {
873
874   if (type < NUM_LOAD_TYPES) return strfuncs[type].str;
875   if (type < 128)            return "RESERVED";
876   if (type < 256)            return "Private USE";
877
878   return "Huh? You should never see this! Shame on you!";
879 }
880
881 static const char *
882 exchtype2str(guint8 type) {
883
884 #define NUM_EXCHSTRS    6
885   static const char * exchstrs[NUM_EXCHSTRS] = {
886     "NONE",
887     "Base",
888     "Identity Protection",
889     "Authentication Only",
890     "Aggressive",
891     "Informational"
892   };
893   
894   if (type < NUM_EXCHSTRS) return exchstrs[type];
895   if (type < 32)           return "ISAKMP Future Use";
896   if (type < 240)          return "DOI Specific Use";
897   if (type < 256)          return "Private Use";
898   
899   return "Huh? You should never see this! Shame on you!";
900 }
901
902 static const char *
903 doitype2str(guint32 type) {
904   if (type == 1) return "IPSEC";
905   return "Unknown DOI Type";
906 }
907
908 static const char *
909 msgtype2str(guint16 type) {
910
911 #define NUM_PREDEFINED  31
912   static const char *msgs[NUM_PREDEFINED] = {
913     "<UNKNOWN>",
914     "INVALID-PAYLOAD-TYPE",
915     "DOI-NOT-SUPPORTED",
916     "SITUATION-NOT-SUPPORTED",
917     "INVALID-COOKIE",
918     "INVALID-MAJOR-VERSION",
919     "INVALID-MINOR-VERSION",
920     "INVALID-EXCHANGE-TYPE",
921     "INVALID-FLAGS",
922     "INVALID-MESSAGE-ID",
923     "INVALID-PROTOCOL-ID",
924     "INVALID-SPI",
925     "INVALID-TRANSFORM-ID",
926     "ATTRIBUTES-NOT-SUPPORTED",
927     "NO-PROPOSAL-CHOSEN",
928     "BAD-PROPOSAL-SYNTAX",
929     "PAYLOAD-MALFORMED",
930     "INVALID-KEY-INFORMATION",
931     "INVALID-ID-INFORMATION",
932     "INVALID-CERT-ENCODING",
933     "INVALID-CERTIFICATE",
934     "CERT-TYPE-UNSUPPORTED",
935     "INVALID-CERT-AUTHORITY",
936     "INVALID-HASH-INFORMATION",
937     "AUTHENTICATION-FAILED",
938     "INVALID-SIGNATURE",
939     "ADDRESS-NOTIFICATION",
940     "NOTIFY-SA-LIFETIME",
941     "CERTIFICATE-UNAVAILABLE",
942     "UNSUPPORTED-EXCHANGE-TYPE",
943     "UNEQUAL-PAYLOAD-LENGTHS"
944   };
945
946   if (type < NUM_PREDEFINED) return msgs[type];
947   if (type < 8192)           return "RESERVED (Future Use)";
948   if (type < 16384)          return "Private Use";
949   if (type < 16385)          return "CONNECTED";
950   if (type < 24576)          return "RESERVED (Future Use) - status";
951   if (type < 24577)          return "RESPONDER-LIFETIME";
952   if (type < 24578)          return "REPLAY-STATUS";
953   if (type < 24579)          return "INITIAL-CONTACT";
954   if (type < 32768)          return "DOI-specific codes";
955   if (type < 40960)          return "Private Use - status";
956   if (type < 65535)          return "RESERVED (Future Use) - status (2)";
957
958   return "Huh? You should never see this! Shame on you!";
959 }
960
961 static const char *
962 situation2str(guint32 type) {
963
964 #define SIT_MSG_NUM     1024
965 #define SIT_IDENTITY    0x01
966 #define SIT_SECRECY     0x02
967 #define SIT_INTEGRITY   0x04
968
969   static char   msg[SIT_MSG_NUM];
970   int           n = 0;
971   char *        sep = "";
972   
973   if (type & SIT_IDENTITY) {
974     n += snprintf(msg, SIT_MSG_NUM-n, "%sIDENTITY", sep);
975     sep = " & ";
976   }
977   if (type & SIT_SECRECY) {
978     n += snprintf(msg, SIT_MSG_NUM-n, "%sSECRECY", sep);
979     sep = " & ";
980   }
981   if (type & SIT_INTEGRITY) {
982     n += snprintf(msg, SIT_MSG_NUM-n, "%sINTEGRITY", sep);
983     sep = " & ";
984   }
985
986   return msg;
987 }
988
989 static const char *
990 value2str(guint16 att_type, guint16 value) {
991   
992   if (value == 0) return "RESERVED";
993   
994   switch (att_type) {
995     case 1:
996     case 2:
997       switch (value) {
998         case 1:  return "Seconds";
999         case 2:  return "Kilobytes";
1000         default: return "UNKNOWN-SA-VALUE";
1001       }
1002     case 3:
1003       return "Group-Value";
1004     case 4:
1005       switch (value) {
1006         case 1:  return "Tunnel";
1007         case 2:  return "Transport";
1008         default: return "UNKNOWN-ENCAPSULATION-VALUE";
1009       }
1010     case 5:
1011       switch (value) {
1012         case 1:  return "HMAC-MD5";
1013         case 2:  return "HMAC-SHA";
1014         case 3:  return "DES-MAC";
1015         case 4:  return "KPDK";
1016         default: return "UNKNOWN-AUTHENTICATION-VALUE";
1017       }
1018     case 11:
1019       return "Life-Type";
1020     default: return "UNKNOWN-ATTRIBUTE-TYPE";
1021   }
1022 }
1023
1024 static const char *
1025 num2str(const guint8 *pd, guint16 len) {
1026
1027 #define NUMSTR_LEN      1024
1028   static char           numstr[NUMSTR_LEN];
1029   
1030   switch (len) {
1031   case 1:
1032     snprintf(numstr, NUMSTR_LEN, "%u", *pd);
1033     break;
1034   case 2:
1035     snprintf(numstr, NUMSTR_LEN, "%u", pntohs(pd));
1036     break;
1037   case 3:
1038     snprintf(numstr, NUMSTR_LEN, "%u", pntohl(pd) & 0x0fff);
1039     break;
1040   case 4:
1041     snprintf(numstr, NUMSTR_LEN, "%u", pntohl(pd));
1042     break;
1043   default:
1044     snprintf(numstr, NUMSTR_LEN, "<too big>");
1045   }
1046
1047   return numstr;
1048 }
1049