Replace the types from sys/types.h and netinet/in.h by their glib.h
[obnox/wireshark/wip.git] / packet-isakmp.c
1 /* packet-isakmp.c
2  * Routines for the Internet Security Association and Key Management Protocol
3  * (ISAKMP) (RFC 2408) and the Internet IP Security Domain of Interpretation
4  * for ISAKMP (RFC 2407)
5  * Brad Robel-Forrest <brad.robel-forrest@watchguard.com>
6  *
7  * $Id: packet-isakmp.c,v 1.56 2002/08/02 23:35:51 jmayer Exp $
8  *
9  * Ethereal - Network traffic analyzer
10  * By Gerald Combs <gerald@ethereal.com>
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
26  */
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <stdio.h>
33 #include <string.h>
34
35 #include <glib.h>
36
37 #ifdef NEED_SNPRINTF_H
38 # include "snprintf.h"
39 #endif
40
41 #include <epan/packet.h>
42 #include "ipproto.h"
43
44 static int proto_isakmp = -1;
45
46 static gint ett_isakmp = -1;
47 static gint ett_isakmp_flags = -1;
48 static gint ett_isakmp_payload = -1;
49
50 #define UDP_PORT_ISAKMP 500
51 #define TCP_PORT_ISAKMP 500
52
53 #define NUM_PROTO_TYPES 5
54 #define proto2str(t)    \
55   ((t < NUM_PROTO_TYPES) ? prototypestr[t] : "UNKNOWN-PROTO-TYPE")
56
57 static const char *prototypestr[NUM_PROTO_TYPES] = {
58   "RESERVED",
59   "ISAKMP",
60   "IPSEC_AH",
61   "IPSEC_ESP",
62   "IPCOMP"
63 };
64
65 #define NUM_P1_ATT_TYPES        17
66 #define p1_atttype2str(t)       \
67   ((t < NUM_P1_ATT_TYPES) ? p1_atttypestr[t] : "UNKNOWN-ATTRIBUTE-TYPE")
68
69 static const char *p1_atttypestr[NUM_P1_ATT_TYPES] = {
70   "UNKNOWN-ATTRIBUTE-TYPE",
71   "Encryption-Algorithm",
72   "Hash-Algorithm",
73   "Authentication-Method",
74   "Group-Description",
75   "Group-Type",
76   "Group-Prime",
77   "Group-Generator-One",
78   "Group-Generator-Two",
79   "Group-Curve-A",
80   "Group-Curve-B",
81   "Life-Type",
82   "Life-Duration",
83   "PRF",
84   "Key-Length",
85   "Field-Size",
86   "Group-Order"
87 };
88
89 #define NUM_ATT_TYPES   11
90 #define atttype2str(t)  \
91   ((t < NUM_ATT_TYPES) ? atttypestr[t] : "UNKNOWN-ATTRIBUTE-TYPE")
92
93 static const char *atttypestr[NUM_ATT_TYPES] = {
94   "UNKNOWN-ATTRIBUTE-TYPE",
95   "SA-Life-Type",
96   "SA-Life-Duration",
97   "Group-Description",
98   "Encapsulation-Mode",
99   "Authentication-Algorithm",
100   "Key-Length",
101   "Key-Rounds",
102   "Compress-Dictinary-Size",
103   "Compress-Private-Algorithm",
104   "ECN Tunnel"
105 };
106
107 #define NUM_TRANS_TYPES 2
108 #define trans2str(t)    \
109   ((t < NUM_TRANS_TYPES) ? transtypestr[t] : "UNKNOWN-TRANS-TYPE")
110
111 static const char *transtypestr[NUM_TRANS_TYPES] = {
112   "RESERVED",
113   "KEY_IKE"
114 };
115
116 #define NUM_AH_TRANS_TYPES      8
117 #define ah_trans2str(t)         \
118   ((t < NUM_AH_TRANS_TYPES) ? ah_transtypestr[t] : "UNKNOWN-AH-TRANS-TYPE")
119
120 static const char *ah_transtypestr[NUM_AH_TRANS_TYPES] = {
121   "RESERVED",
122   "RESERVED",
123   "MD5",
124   "SHA",
125   "DES",
126   "SHA2-256",
127   "SHA2-384",
128   "SHA2-512"
129 };
130
131 #define NUM_ESP_TRANS_TYPES     13
132 #define esp_trans2str(t)        \
133   ((t < NUM_ESP_TRANS_TYPES) ? esp_transtypestr[t] : "UNKNOWN-ESP-TRANS-TYPE")
134
135 static const char *esp_transtypestr[NUM_ESP_TRANS_TYPES] = {
136   "RESERVED",
137   "DES-IV64",
138   "DES",
139   "3DES",
140   "RC5",
141   "IDEA",
142   "CAST",
143   "BLOWFISH",
144   "3IDEA",
145   "DES-IV32",
146   "RC4",
147   "NULL",
148   "AES"
149 };
150
151 #define NUM_IPCOMP_TRANS_TYPES    5
152 #define ipcomp_trans2str(t)  \
153   ((t < NUM_IPCOMP_TRANS_TYPES) ? ipcomp_transtypestr[t] : "UNKNOWN-IPCOMP-TRANS-TYPE")
154
155 static const char *ipcomp_transtypestr[NUM_IPCOMP_TRANS_TYPES] = {
156   "RESERVED",
157   "OUI",
158   "DEFLATE",
159   "LZS",
160   "LZJH"
161 };
162
163 #define NUM_ID_TYPES    12
164 #define id2str(t)       \
165   ((t < NUM_ID_TYPES) ? idtypestr[t] : "UNKNOWN-ID-TYPE")
166
167 static const char *idtypestr[NUM_ID_TYPES] = {
168   "RESERVED",
169   "IPV4_ADDR",
170   "FQDN",
171   "USER_FQDN",
172   "IPV4_ADDR_SUBNET",
173   "IPV6_ADDR",
174   "IPV6_ADDR_SUBNET",
175   "IPV4_ADDR_RANGE",
176   "IPV6_ADDR_RANGE",
177   "DER_ASN1_DN",
178   "DER_ASN1_GN",
179   "KEY_ID"
180 };
181
182 struct isakmp_hdr {
183   guint8        icookie[8];
184   guint8        rcookie[8];
185   guint8        next_payload;
186   guint8        version;
187   guint8        exch_type;
188   guint8        flags;
189 #define E_FLAG          0x01
190 #define C_FLAG          0x02
191 #define A_FLAG          0x04
192   guint8        message_id[4];
193   guint8        length[4];
194 };
195
196 struct udp_encap_hdr {
197   guint8        non_esp_marker[4];
198   guint32       esp_SPI;
199 };
200
201 static proto_tree *dissect_payload_header(tvbuff_t *, int, int, guint8,
202     guint8 *, guint16 *, proto_tree *);
203
204 static void dissect_sa(tvbuff_t *, int, int, proto_tree *, int);
205 static void dissect_proposal(tvbuff_t *, int, int, proto_tree *, int);
206 static void dissect_transform(tvbuff_t *, int, int, proto_tree *, int);
207 static void dissect_key_exch(tvbuff_t *, int, int, proto_tree *, int);
208 static void dissect_id(tvbuff_t *, int, int, proto_tree *, int);
209 static void dissect_cert(tvbuff_t *, int, int, proto_tree *, int);
210 static void dissect_certreq(tvbuff_t *, int, int, proto_tree *, int);
211 static void dissect_hash(tvbuff_t *, int, int, proto_tree *, int);
212 static void dissect_sig(tvbuff_t *, int, int, proto_tree *, int);
213 static void dissect_nonce(tvbuff_t *, int, int, proto_tree *, int);
214 static void dissect_notif(tvbuff_t *, int, int, proto_tree *, int);
215 static void dissect_delete(tvbuff_t *, int, int, proto_tree *, int);
216 static void dissect_vid(tvbuff_t *, int, int, proto_tree *, int);
217 static void dissect_config(tvbuff_t *, int, int, proto_tree *, int);
218
219 static const char *payloadtype2str(guint8);
220 static const char *exchtype2str(guint8);
221 static const char *doitype2str(guint32);
222 static const char *msgtype2str(guint16);
223 static const char *situation2str(guint32);
224 static const char *value2str(int, guint16, guint16);
225 static const char *attrtype2str(guint8);
226 static const char *cfgattrident2str(guint16);
227 static const char *certtype2str(guint8);
228
229 static gboolean get_num(tvbuff_t *, int, guint16, guint32 *);
230
231 #define LOAD_TYPE_NONE          0       /* payload type for None */
232 #define LOAD_TYPE_PROPOSAL      2       /* payload type for Proposal */
233 #define LOAD_TYPE_TRANSFORM     3       /* payload type for Transform */
234 #define NUM_LOAD_TYPES          15
235 #define loadtype2str(t) \
236   ((t < NUM_LOAD_TYPES) ? strfuncs[t].str : "Unknown payload type")
237
238 static struct strfunc {
239   const char *  str;
240   void          (*func)(tvbuff_t *, int, int, proto_tree *, int);
241 } strfuncs[NUM_LOAD_TYPES] = {
242   {"NONE",                      NULL              },
243   {"Security Association",      dissect_sa        },
244   {"Proposal",                  dissect_proposal  },
245   {"Transform",                 dissect_transform },
246   {"Key Exchange",              dissect_key_exch  },
247   {"Identification",            dissect_id        },
248   {"Certificate",               dissect_cert      },
249   {"Certificate Request",       dissect_certreq   },
250   {"Hash",                      dissect_hash      },
251   {"Signature",                 dissect_sig       },
252   {"Nonce",                     dissect_nonce     },
253   {"Notification",              dissect_notif     },
254   {"Delete",                    dissect_delete    },
255   {"Vendor ID",                 dissect_vid       },
256   {"Attrib",                    dissect_config    }
257 };
258
259 static dissector_handle_t esp_handle;
260 static dissector_handle_t ah_handle;
261
262 static void
263 dissect_payloads(tvbuff_t *tvb, proto_tree *tree, guint8 initial_payload,
264                  int offset, int length)
265 {
266   guint8 payload, next_payload;
267   guint16               payload_length;
268   proto_tree *          ntree;
269
270   for (payload = initial_payload; length != 0; payload = next_payload) {
271     if (payload == LOAD_TYPE_NONE) {
272       /*
273        * What?  There's more stuff in this chunk of data, but the
274        * previous payload had a "next payload" type of None?
275        */
276       proto_tree_add_text(tree, tvb, offset, length,
277                           "Extra data: %s",
278                           tvb_bytes_to_str(tvb, offset, length));
279       break;
280     }
281     ntree = dissect_payload_header(tvb, offset, length, payload,
282       &next_payload, &payload_length, tree);
283     if (ntree == NULL)
284       break;
285     if (payload_length >= 4) {  /* XXX = > 4? */
286       if (payload < NUM_LOAD_TYPES) {
287         (*strfuncs[payload].func)(tvb, offset + 4, payload_length - 4, ntree,
288                                   -1);
289       }
290       else {
291         proto_tree_add_text(ntree, tvb, offset + 4, payload_length - 4,
292             "Payload");
293       }
294     }
295     else {
296         proto_tree_add_text(ntree, tvb, offset + 4, 0,
297             "Payload (bogus, length is %u, must be at least 4)",
298             payload_length);
299         payload_length = 4;
300     }
301     offset += payload_length;
302     length -= payload_length;
303   }
304 }
305
306 static void
307 dissect_isakmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
308 {
309   int                   offset = 0;
310   struct isakmp_hdr *   hdr;
311   proto_item *          ti;
312   proto_tree *          isakmp_tree = NULL;
313   struct udp_encap_hdr * encap_hdr;
314   guint32               len;
315   static const guint8   non_esp_marker[4] = { 0, 0, 0, 0 };
316   tvbuff_t *            next_tvb;
317
318   if (check_col(pinfo->cinfo, COL_PROTOCOL))
319     col_set_str(pinfo->cinfo, COL_PROTOCOL, "ISAKMP");
320   if (check_col(pinfo->cinfo, COL_INFO))
321     col_clear(pinfo->cinfo, COL_INFO);
322
323   hdr = (struct isakmp_hdr *)tvb_get_ptr(tvb, 0, sizeof (struct isakmp_hdr));
324   len = pntohl(&hdr->length);
325   
326   if (tree) {
327     ti = proto_tree_add_item(tree, proto_isakmp, tvb, offset, len, FALSE);
328     isakmp_tree = proto_item_add_subtree(ti, ett_isakmp);
329   }
330     
331   encap_hdr = (struct udp_encap_hdr *)tvb_get_ptr(tvb, 0, sizeof(struct udp_encap_hdr));
332   
333   if (encap_hdr->non_esp_marker[0] == 0xFF) {
334     if (check_col(pinfo->cinfo, COL_INFO)) 
335       col_set_str(pinfo->cinfo, COL_INFO, "UDP encapsulated IPSec - NAT Keepalive");
336     return;
337   }
338   if (memcmp(encap_hdr->non_esp_marker,non_esp_marker,4) == 0) {
339     if (check_col(pinfo->cinfo, COL_INFO)) 
340           col_set_str(pinfo->cinfo, COL_INFO, "UDP encapsulated IPSec - ESP");
341     if (tree)
342       proto_tree_add_text(isakmp_tree, tvb, offset,
343                           sizeof(encap_hdr->non_esp_marker),
344                           "Non-ESP-Marker");
345     offset += sizeof(encap_hdr->non_esp_marker);
346     next_tvb = tvb_new_subset(tvb, offset, -1, -1);
347     call_dissector(esp_handle, next_tvb, pinfo, tree);
348     return;
349   }
350
351   if (check_col(pinfo->cinfo, COL_INFO))
352     col_add_str(pinfo->cinfo, COL_INFO, exchtype2str(hdr->exch_type));
353
354   if (tree) {
355     proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(hdr->icookie),
356                         "Initiator cookie");
357     offset += sizeof(hdr->icookie);
358     
359     proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(hdr->rcookie),
360                         "Responder cookie");
361     offset += sizeof(hdr->rcookie);
362
363     proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(hdr->next_payload),
364                         "Next payload: %s (%u)",
365                         payloadtype2str(hdr->next_payload), hdr->next_payload);
366     offset += sizeof(hdr->next_payload);
367
368     proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(hdr->version),
369                         "Version: %u.%u",
370                         hi_nibble(hdr->version), lo_nibble(hdr->version));
371     offset += sizeof(hdr->version);
372     
373     proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(hdr->exch_type),
374                         "Exchange type: %s (%u)",
375                         exchtype2str(hdr->exch_type), hdr->exch_type);
376     offset += sizeof(hdr->exch_type);
377     
378     {
379       proto_item *      fti;
380       proto_tree *      ftree;
381       
382       fti   = proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(hdr->flags), "Flags");
383       ftree = proto_item_add_subtree(fti, ett_isakmp_flags);
384       
385       proto_tree_add_text(ftree, tvb, offset, 1, "%s",
386                           decode_boolean_bitfield(hdr->flags, E_FLAG, sizeof(hdr->flags)*8,
387                                                   "Encryption", "No encryption"));
388       proto_tree_add_text(ftree, tvb, offset, 1, "%s",
389                           decode_boolean_bitfield(hdr->flags, C_FLAG, sizeof(hdr->flags)*8,
390                                                   "Commit", "No commit"));
391       proto_tree_add_text(ftree, tvb, offset, 1, "%s",
392                           decode_boolean_bitfield(hdr->flags, A_FLAG, sizeof(hdr->flags)*8,
393                                                   "Authentication", "No authentication"));
394       offset += sizeof(hdr->flags);
395     }
396
397     proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(hdr->message_id),
398         "Message ID: 0x%02x%02x%02x%02x", hdr->message_id[0],
399         hdr->message_id[1], hdr->message_id[2], hdr->message_id[3]);
400     offset += sizeof(hdr->message_id);
401     
402     proto_tree_add_text(isakmp_tree, tvb, offset, sizeof(hdr->length),
403                         "Length: %u", len);
404     offset += sizeof(hdr->length);
405     len -= sizeof(*hdr);
406
407     if (hdr->flags & E_FLAG) {
408       if (len && isakmp_tree) {
409         proto_tree_add_text(isakmp_tree, tvb, offset, len,
410                         "Encrypted payload (%d byte%s)",
411                         len, plurality(len, "", "s"));
412       }
413     } else
414       dissect_payloads(tvb, isakmp_tree, hdr->next_payload, offset, len);
415   }
416 }
417
418 static proto_tree *
419 dissect_payload_header(tvbuff_t *tvb, int offset, int length, guint8 payload,
420     guint8 *next_payload_p, guint16 *payload_length_p, proto_tree *tree)
421 {
422   guint8                next_payload;
423   guint16               payload_length;
424   proto_item *          ti;
425   proto_tree *          ntree;
426
427   if (length < 4) {
428     proto_tree_add_text(tree, tvb, offset, length,
429           "Not enough room in payload for all transforms");
430     return NULL;
431   }
432   next_payload = tvb_get_guint8(tvb, offset);
433   payload_length = tvb_get_ntohs(tvb, offset + 2);
434
435   ti = proto_tree_add_text(tree, tvb, offset, payload_length,
436             "%s payload", loadtype2str(payload));
437   ntree = proto_item_add_subtree(ti, ett_isakmp_payload);
438
439   proto_tree_add_text(ntree, tvb, offset, 1,
440                       "Next payload: %s (%u)",
441                       payloadtype2str(next_payload), next_payload);
442   proto_tree_add_text(ntree, tvb, offset+2, 2, "Length: %u", payload_length);
443
444   *next_payload_p = next_payload;
445   *payload_length_p = payload_length;
446   return ntree;
447 }
448
449 static void
450 dissect_sa(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
451     int unused _U_)
452 {
453   guint32               doi;
454   guint32               situation;
455
456   if (length < 4) {
457     proto_tree_add_text(tree, tvb, offset, length,
458                         "DOI %s (length is %u, should be >= 4)",
459                         tvb_bytes_to_str(tvb, offset, length), length);
460     return;
461   }
462   doi = tvb_get_ntohl(tvb, offset);
463   proto_tree_add_text(tree, tvb, offset, 4,
464                       "Domain of interpretation: %s (%u)",
465                       doitype2str(doi), doi);
466   offset += 4;
467   length -= 4;
468   
469   if (doi == 1) {
470     /* IPSEC */
471     if (length < 4) {
472       proto_tree_add_text(tree, tvb, offset, length,
473                           "Situation: %s (length is %u, should be >= 4)",
474                           tvb_bytes_to_str(tvb, offset, length), length);
475       return;
476     }
477     situation = tvb_get_ntohl(tvb, offset);
478     proto_tree_add_text(tree, tvb, offset, 4,
479                         "Situation: %s (%u)",
480                         situation2str(situation), situation);
481     offset += 4;
482     length -= 4;
483   
484     dissect_payloads(tvb, tree, LOAD_TYPE_PROPOSAL, offset, length);
485   } else {
486     /* Unknown */
487     proto_tree_add_text(tree, tvb, offset, length,
488                         "Situation: %s",
489                         tvb_bytes_to_str(tvb, offset, length));
490   }
491 }
492
493 static void
494 dissect_proposal(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
495     int unused _U_)
496 {
497   guint8                protocol_id;
498   guint8                spi_size;
499   guint8                num_transforms;
500   guint8                next_payload;
501   guint16               payload_length;
502   proto_tree *          ntree;
503
504   proto_tree_add_text(tree, tvb, offset, 1,
505                       "Proposal number: %u", tvb_get_guint8(tvb, offset));
506   offset += 1;
507   length -= 1;
508   
509   protocol_id = tvb_get_guint8(tvb, offset);
510   proto_tree_add_text(tree, tvb, offset, 1,
511                       "Protocol ID: %s (%u)",
512                       proto2str(protocol_id), protocol_id);
513   offset += 1;
514   length -= 1;
515   
516   spi_size = tvb_get_guint8(tvb, offset);
517   proto_tree_add_text(tree, tvb, offset, 1,
518                       "SPI size: %u", spi_size);
519   offset += 1;
520   length -= 1;
521
522   num_transforms = tvb_get_guint8(tvb, offset);
523   proto_tree_add_text(tree, tvb, offset, 1,
524                       "Number of transforms: %u", num_transforms);
525   offset += 1;
526   length -= 1;
527
528   if (spi_size) {
529     proto_tree_add_text(tree, tvb, offset, spi_size, "SPI: %s",
530                         tvb_bytes_to_str(tvb, offset, spi_size));
531     offset += spi_size;
532     length -= spi_size;
533   }
534
535   while (num_transforms > 0) {
536     ntree = dissect_payload_header(tvb, offset, length, LOAD_TYPE_TRANSFORM,
537       &next_payload, &payload_length, tree);
538     if (ntree == NULL)
539       break;
540     if (length < payload_length) {
541       proto_tree_add_text(tree, tvb, offset + 4, length,
542           "Not enough room in payload for all transforms");
543       break;
544     }
545     if (payload_length >= 4)
546       dissect_transform(tvb, offset + 4, payload_length - 4, ntree, protocol_id);
547     else
548       proto_tree_add_text(ntree, tvb, offset + 4, payload_length - 4, "Payload");
549     offset += payload_length;
550     length -= payload_length;
551     num_transforms--;
552   }
553 }
554
555 static void
556 dissect_transform(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
557     int protocol_id)
558 {
559   guint8                transform_id;
560
561   proto_tree_add_text(tree, tvb, offset, 1,
562                       "Transform number: %u", tvb_get_guint8(tvb, offset));
563   offset += 1;
564   length -= 1;
565
566   transform_id = tvb_get_guint8(tvb, offset);
567   switch (protocol_id) {
568   default:
569     proto_tree_add_text(tree, tvb, offset, 1,
570                         "Transform ID: %u", transform_id);
571     break;
572   case 1:       /* ISAKMP */
573     proto_tree_add_text(tree, tvb, offset, 1,
574                         "Transform ID: %s (%u)",
575                         trans2str(transform_id), transform_id);
576     break;
577   case 2:       /* AH */
578     proto_tree_add_text(tree, tvb, offset, 1,
579                         "Transform ID: %s (%u)",
580                         ah_trans2str(transform_id), transform_id);
581     break;
582   case 3:       /* ESP */
583     proto_tree_add_text(tree, tvb, offset, 1,
584                         "Transform ID: %s (%u)",
585                         esp_trans2str(transform_id), transform_id);
586     break;
587   case 4:       /* IPCOMP */
588     proto_tree_add_text(tree, tvb, offset, 1,
589                         "Transform ID: %s (%u)",
590                         ipcomp_trans2str(transform_id), transform_id);
591     break;
592   }
593   offset += 3;
594   length -= 3;
595   
596   while (length>0) {
597     const char *str;
598     int ike_phase1 = 0;
599     guint16 aft     = tvb_get_ntohs(tvb, offset);
600     guint16 type    = aft & 0x7fff;
601     guint16 len;
602     guint32 val;
603     guint pack_len;
604
605     if (protocol_id == 1 && transform_id == 1) {
606       ike_phase1 = 1;
607       str = p1_atttype2str(type);
608     }
609     else {
610       str = atttype2str(type);
611     }
612
613     if (aft & 0x8000) {
614       val = tvb_get_ntohs(tvb, offset + 2);
615       proto_tree_add_text(tree, tvb, offset, 4,
616                           "%s (%u): %s (%u)",
617                           str, type,
618                           value2str(ike_phase1, type, val), val);
619       offset += 4;
620       length -= 4;
621     }
622     else {
623       len = tvb_get_ntohs(tvb, offset + 2);
624       pack_len = 4 + len;
625       if (!get_num(tvb, offset + 4, len, &val)) {
626         proto_tree_add_text(tree, tvb, offset, pack_len,
627                             "%s (%u): <too big (%u bytes)>",
628                             str, type, len);
629       } else {
630         proto_tree_add_text(tree, tvb, offset, pack_len,
631                             "%s (%u): %s (%u)",
632                             str, type,
633                             value2str(ike_phase1, type, val), val);
634       }
635       offset += pack_len;
636       length -= pack_len;
637     }
638   }
639 }
640
641 static void
642 dissect_key_exch(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
643     int unused _U_)
644 {
645   proto_tree_add_text(tree, tvb, offset, length, "Key Exchange Data");
646 }
647
648 static void
649 dissect_id(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
650     int unused _U_)
651 {
652   guint8                id_type;
653   guint8                protocol_id;
654   guint16               port;
655
656   id_type = tvb_get_guint8(tvb, offset);
657   proto_tree_add_text(tree, tvb, offset, 1,
658                       "ID type: %s (%u)", id2str(id_type), id_type);
659   offset += 1;
660   length -= 1;
661
662   protocol_id = tvb_get_guint8(tvb, offset);
663   if (protocol_id == 0) {
664     proto_tree_add_text(tree, tvb, offset, 1,
665                         "Protocol ID: Unused");
666   } else {
667     proto_tree_add_text(tree, tvb, offset, 1,
668                         "Protocol ID: %s (%u)",
669                         ipprotostr(protocol_id), protocol_id);
670   }
671   offset += 1;
672   length -= 1;
673
674   port = tvb_get_ntohs(tvb, offset);
675   if (port == 0)
676     proto_tree_add_text(tree, tvb, offset, 2, "Port: Unused");
677   else
678     proto_tree_add_text(tree, tvb, offset, 2, "Port: %u", port);
679   offset += 2;
680   length -= 2;
681   
682   switch (id_type) {
683     case 1:
684       proto_tree_add_text(tree, tvb, offset, length,
685                           "Identification data: %s",
686                           ip_to_str(tvb_get_ptr(tvb, offset, 4)));
687       break;
688     case 2:
689     case 3:
690       proto_tree_add_text(tree, tvb, offset, length,
691                           "Identification data: %.*s", length,
692                           tvb_get_ptr(tvb, offset, length));
693       break;
694     case 4:
695       proto_tree_add_text(tree, tvb, offset, length,
696                           "Identification data: %s/%s",
697                           ip_to_str(tvb_get_ptr(tvb, offset, 4)),
698                           ip_to_str(tvb_get_ptr(tvb, offset+4, 4)));
699       break;
700     default:
701       proto_tree_add_text(tree, tvb, offset, length, "Identification Data");
702       break;
703   }
704 }
705
706 static void
707 dissect_cert(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
708     int unused _U_)
709 {
710   guint8                cert_enc;
711
712   cert_enc = tvb_get_guint8(tvb, offset);
713   proto_tree_add_text(tree, tvb, offset, 1,
714                       "Certificate encoding: %u - %s",
715                       cert_enc, certtype2str(cert_enc));
716   offset += 1;
717   length -= 1;
718
719   proto_tree_add_text(tree, tvb, offset, length, "Certificate Data");
720 }
721
722 static void
723 dissect_certreq(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
724     int unused _U_)
725 {
726   guint8                cert_type;
727
728   cert_type = tvb_get_guint8(tvb, offset);
729   proto_tree_add_text(tree, tvb, offset, 1,
730                       "Certificate type: %u - %s",
731                       cert_type, certtype2str(cert_type));
732   offset += 1;
733   length -= 1;
734
735   proto_tree_add_text(tree, tvb, offset, length, "Certificate Authority");
736 }
737
738 static void
739 dissect_hash(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
740     int unused _U_)
741 {
742   proto_tree_add_text(tree, tvb, offset, length, "Hash Data");
743 }
744
745 static void
746 dissect_sig(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
747     int unused _U_)
748 {
749   proto_tree_add_text(tree, tvb, offset, length, "Signature Data");
750 }
751
752 static void
753 dissect_nonce(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
754     int unused _U_)
755 {
756   proto_tree_add_text(tree, tvb, offset, length, "Nonce Data");
757 }
758
759 static void
760 dissect_notif(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
761     int unused _U_)
762 {
763   guint32               doi;
764   guint8                protocol_id;
765   guint8                spi_size;
766   guint16               msgtype;
767
768   doi = tvb_get_ntohl(tvb, offset);
769   proto_tree_add_text(tree, tvb, offset, 4,
770                       "Domain of Interpretation: %s (%u)",
771                       doitype2str(doi), doi);
772   offset += 4;
773   length -= 4;
774
775   protocol_id = tvb_get_guint8(tvb, offset);
776   proto_tree_add_text(tree, tvb, offset, 1,
777                       "Protocol ID: %s (%u)",
778                       proto2str(protocol_id), protocol_id);
779   offset += 1;
780   length -= 1;
781   
782   spi_size = tvb_get_guint8(tvb, offset);
783   proto_tree_add_text(tree, tvb, offset, 1,
784                       "SPI size: %u", spi_size);
785   offset += 1;
786   length -= 1;
787   
788   msgtype = tvb_get_ntohs(tvb, offset);
789   proto_tree_add_text(tree, tvb, offset, 2,
790                       "Message type: %s (%u)", msgtype2str(msgtype), msgtype);
791   offset += 2;
792   length -= 2;
793
794   if (spi_size) {
795     proto_tree_add_text(tree, tvb, offset, spi_size, "Security Parameter Index");
796     offset += spi_size;
797     length -= spi_size;
798   }
799
800   if (length > 0)
801     proto_tree_add_text(tree, tvb, offset, length, "Notification Data");
802 }
803
804 static void
805 dissect_delete(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
806     int unused _U_)
807 {
808   guint32               doi;
809   guint8                protocol_id;
810   guint8                spi_size;
811   guint16               num_spis;
812   guint16               i;
813   
814   doi = tvb_get_ntohl(tvb, offset);
815   proto_tree_add_text(tree, tvb, offset, 4,
816                       "Domain of Interpretation: %s (%u)",
817                       doitype2str(doi), doi);
818   offset += 4;
819   length -= 4;
820
821   protocol_id = tvb_get_guint8(tvb, offset);
822   proto_tree_add_text(tree, tvb, offset, 1,
823                       "Protocol ID: %s (%u)",
824                       proto2str(protocol_id), protocol_id);
825   offset += 1;
826   length -= 1;
827   
828   spi_size = tvb_get_guint8(tvb, offset);
829   proto_tree_add_text(tree, tvb, offset, 1,
830                       "SPI size: %u", spi_size);
831   offset += 1;
832   length -= 1;
833
834   num_spis = tvb_get_ntohs(tvb, offset);
835   proto_tree_add_text(tree, tvb, offset, 2,
836                       "Number of SPIs: %u", num_spis);
837   offset += 2;
838   length -= 2;
839   
840   for (i = 0; i < num_spis; ++i) {
841     if (length < spi_size) {
842       proto_tree_add_text(tree, tvb, offset, length,
843           "Not enough room in payload for all SPI's");
844       break;
845     }
846     proto_tree_add_text(tree, tvb, offset, spi_size,
847                         "SPI (%d)", i);
848     offset += spi_size;
849     length -= spi_size;
850   }
851 }
852
853 static void
854 dissect_vid(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
855     int unused _U_)
856 {
857   proto_tree_add_text(tree, tvb, offset, length, "Vendor ID");
858 }
859
860 static void
861 dissect_config(tvbuff_t *tvb, int offset, int length, proto_tree *tree,
862     int unused _U_)
863 {
864   guint8                type;
865
866   type = tvb_get_guint8(tvb, offset);
867   proto_tree_add_text(tree, tvb, offset, 1,
868                       "Type %s (%u)",attrtype2str(type),type);
869   
870   offset += 2;
871   length -= 2;
872   
873   proto_tree_add_text(tree, tvb, offset, 2,
874                       "Identifier: %u", tvb_get_ntohs(tvb, offset));
875   offset += 2;
876   length -= 2;
877   
878   while(length>0) {
879     guint16 aft     = tvb_get_ntohs(tvb, offset);
880     guint16 type    = aft & 0x7fff;
881     guint16 len;
882     guint32 val;
883     guint pack_len;
884
885     if (aft & 0x8000) {
886       val = tvb_get_ntohs(tvb, offset + 2);
887       proto_tree_add_text(tree, tvb, offset, 4,
888                           "%s (%u)", cfgattrident2str(type), val);
889       offset += 4;
890       length -= 4;
891     }
892     else {
893       len = tvb_get_ntohs(tvb, offset + 2);
894       pack_len = 4 + len;
895       if (!get_num(tvb, offset + 4, len, &val)) {
896         proto_tree_add_text(tree, tvb, offset, pack_len,
897                             "%s: <too big (%u bytes)>",
898                             cfgattrident2str(type), len);
899       } else {
900         proto_tree_add_text(tree, tvb, offset, 4,
901                             "%s (%ue)", cfgattrident2str(type),
902                             val);
903       }
904       offset += pack_len;
905       length -= pack_len;
906     }
907   }
908 }
909
910 static const char *
911 payloadtype2str(guint8 type) {
912
913   if (type < NUM_LOAD_TYPES) return strfuncs[type].str;
914   if (type < 128)            return "RESERVED";
915   if (type < 256)            return "Private USE";
916
917   return "Huh? You should never see this! Shame on you!";
918 }
919
920 static const char *
921 exchtype2str(guint8 type) {
922
923 #define NUM_EXCHSTRS    7
924   static const char * exchstrs[NUM_EXCHSTRS] = {
925     "NONE",
926     "Base",
927     "Identity Protection (Main Mode)",
928     "Authentication Only",
929     "Aggressive",
930     "Informational",
931     "Transaction (Config Mode)"
932   };
933   
934   if (type < NUM_EXCHSTRS) return exchstrs[type];
935   if (type < 32)           return "ISAKMP Future Use";
936   switch (type) {
937   case 32:
938     return "Quick Mode";
939   case 33:
940     return "New Group Mode";
941   }
942   if (type < 240)          return "DOI Specific Use";
943   if (type < 256)          return "Private Use";
944   
945   return "Huh? You should never see this! Shame on you!";
946 }
947
948 static const char *
949 doitype2str(guint32 type) {
950   if (type == 1) return "IPSEC";
951   return "Unknown DOI Type";
952 }
953
954 static const char *
955 msgtype2str(guint16 type) {
956
957 #define NUM_PREDEFINED  31
958   static const char *msgs[NUM_PREDEFINED] = {
959     "<UNKNOWN>",
960     "INVALID-PAYLOAD-TYPE",
961     "DOI-NOT-SUPPORTED",
962     "SITUATION-NOT-SUPPORTED",
963     "INVALID-COOKIE",
964     "INVALID-MAJOR-VERSION",
965     "INVALID-MINOR-VERSION",
966     "INVALID-EXCHANGE-TYPE",
967     "INVALID-FLAGS",
968     "INVALID-MESSAGE-ID",
969     "INVALID-PROTOCOL-ID",
970     "INVALID-SPI",
971     "INVALID-TRANSFORM-ID",
972     "ATTRIBUTES-NOT-SUPPORTED",
973     "NO-PROPOSAL-CHOSEN",
974     "BAD-PROPOSAL-SYNTAX",
975     "PAYLOAD-MALFORMED",
976     "INVALID-KEY-INFORMATION",
977     "INVALID-ID-INFORMATION",
978     "INVALID-CERT-ENCODING",
979     "INVALID-CERTIFICATE",
980     "CERT-TYPE-UNSUPPORTED",
981     "INVALID-CERT-AUTHORITY",
982     "INVALID-HASH-INFORMATION",
983     "AUTHENTICATION-FAILED",
984     "INVALID-SIGNATURE",
985     "ADDRESS-NOTIFICATION",
986     "NOTIFY-SA-LIFETIME",
987     "CERTIFICATE-UNAVAILABLE",
988     "UNSUPPORTED-EXCHANGE-TYPE",
989     "UNEQUAL-PAYLOAD-LENGTHS"
990   };
991
992   if (type < NUM_PREDEFINED) return msgs[type];
993   if (type < 8192)           return "RESERVED (Future Use)";
994   if (type < 16384)          return "Private Use";
995   if (type < 16385)          return "CONNECTED";
996   if (type < 24576)          return "RESERVED (Future Use) - status";
997   if (type < 24577)          return "RESPONDER-LIFETIME";
998   if (type < 24578)          return "REPLAY-STATUS";
999   if (type < 24579)          return "INITIAL-CONTACT";
1000   if (type < 32768)          return "DOI-specific codes";
1001   if (type < 40960)          return "Private Use - status";
1002   if (type < 65535)          return "RESERVED (Future Use) - status (2)";
1003
1004   return "Huh? You should never see this! Shame on you!";
1005 }
1006
1007 static const char *
1008 situation2str(guint32 type) {
1009
1010 #define SIT_MSG_NUM     1024
1011 #define SIT_IDENTITY    0x01
1012 #define SIT_SECRECY     0x02
1013 #define SIT_INTEGRITY   0x04
1014
1015   static char   msg[SIT_MSG_NUM];
1016   int           n = 0;
1017   char *        sep = "";
1018   int           ret;
1019   
1020   if (type & SIT_IDENTITY) {
1021     ret = snprintf(msg, SIT_MSG_NUM-n, "%sIDENTITY", sep);
1022     if (ret == -1) {
1023       /* Some versions of snprintf return -1 if they'd truncate the output. */
1024       return msg;
1025     }
1026     n += ret;
1027     sep = " & ";
1028   }
1029   if (type & SIT_SECRECY) {
1030     if (n >= SIT_MSG_NUM) {
1031       /* No more room. */
1032       return msg;
1033     }
1034     ret = snprintf(msg, SIT_MSG_NUM-n, "%sSECRECY", sep);
1035     if (ret == -1) {
1036       /* Some versions of snprintf return -1 if they'd truncate the output. */
1037       return msg;
1038     }
1039     n += ret;
1040     sep = " & ";
1041   }
1042   if (type & SIT_INTEGRITY) {
1043     if (n >= SIT_MSG_NUM) {
1044       /* No more room. */
1045       return msg;
1046     }
1047     ret = snprintf(msg, SIT_MSG_NUM-n, "%sINTEGRITY", sep);
1048     if (ret == -1) {
1049       /* Some versions of snprintf return -1 if they'd truncate the output. */
1050       return msg;
1051     }
1052     n += ret;
1053     sep = " & ";
1054   }
1055
1056   return msg;
1057 }
1058
1059 static const char *
1060 value2str(int ike_p1, guint16 att_type, guint16 value) {
1061   
1062   if (value == 0) return "RESERVED";
1063   
1064   if (!ike_p1) {
1065   switch (att_type) {
1066     case 1:
1067       switch (value) {
1068         case 1:  return "Seconds";
1069         case 2:  return "Kilobytes";
1070         default: return "UNKNOWN-SA-VALUE";
1071       }
1072     case 2:
1073       return "Duration-Value";
1074     case 3:
1075       return "Group-Value";
1076     case 4:
1077       switch (value) {
1078         case 1:  return "Tunnel";
1079         case 2:  return "Transport";
1080         case 61440: return "Check Point IPSec UDP Encapsulation";
1081         case 61443: return "UDP-Encapsulated-Tunnel (draft)";
1082         case 61444: return "UDP-Encapsulated-Transport (draft)";
1083         default: return "UNKNOWN-ENCAPSULATION-VALUE";
1084       }
1085     case 5:
1086       switch (value) {
1087         case 1:  return "HMAC-MD5";
1088         case 2:  return "HMAC-SHA";
1089         case 3:  return "DES-MAC";
1090         case 4:  return "KPDK";
1091         case 5:  return "HMAC-SHA2-256";
1092         case 6:  return "HMAC-SHA2-384";
1093         case 7:  return "HMAC-SHA2-512";
1094         default: return "UNKNOWN-AUTHENTICATION-VALUE";
1095       }
1096     case 6:
1097       return "Key-Length";
1098     case 7:
1099       return "Key-Rounds";
1100     case 8:
1101       return "log2-size";
1102     default: return "UNKNOWN-ATTRIBUTE-TYPE";
1103   }
1104   }
1105   else {
1106     switch (att_type) {
1107       case 1:
1108         switch (value) {
1109           case 1:  return "DES-CBC";
1110           case 2:  return "IDEA-CBC";
1111           case 3:  return "BLOWFISH-CBC";
1112           case 4:  return "RC5-R16-B64-CBC";
1113           case 5:  return "3DES-CBC";
1114           case 6:  return "CAST-CBC";
1115           case 7:  return "AES-CBC";
1116           default: return "UNKNOWN-ENCRYPTION-ALG";
1117         }
1118       case 2:
1119         switch (value) {
1120           case 1:  return "MD5";
1121           case 2:  return "SHA";
1122           case 3:  return "TIGER";
1123           case 4:  return "SHA2-256";
1124           case 5:  return "SHA2-384";
1125           case 6:  return "SHA2-512";
1126           default: return "UNKNOWN-HASH-ALG";
1127         }
1128       case 3:
1129         switch (value) {
1130           case 1:  return "PSK";
1131           case 2:  return "DSS-SIG";
1132           case 3:  return "RSA-SIG";
1133           case 4:  return "RSA-ENC";
1134           case 5:  return "RSA-Revised-ENC";
1135           case 64221: return "HybridInitRSA";
1136           case 64222: return "HybridRespRSA";
1137           case 64223: return "HybridInitDSS";
1138           case 64224: return "HybridRespDSS";
1139           case 65001: return "XAUTHInitPreShared";
1140           case 65002: return "XAUTHRespPreShared";
1141           case 65003: return "XAUTHInitDSS";
1142           case 65004: return "XAUTHRespDSS";
1143           case 65005: return "XAUTHInitRSA";
1144           case 65006: return "XAUTHRespRSA";
1145           case 65007: return "XAUTHInitRSAEncryption";
1146           case 65008: return "XAUTHRespRSAEncryption";
1147           case 65009: return "XAUTHInitRSARevisedEncryption";
1148           case 65010: return "XAUTHRespRSARevisedEncryption";
1149           default: return "UNKNOWN-AUTH-METHOD";
1150         }
1151       case 4:
1152       case 6:
1153       case 7:
1154       case 8:
1155       case 9:
1156       case 10:
1157       case 16:
1158         return "Group-Value";
1159       case 5:
1160         switch (value) {
1161           case 1:  return "MODP";
1162           case 2:  return "ECP";
1163           case 3:  return "EC2N";
1164           default: return "UNKNOWN-GROUPT-TYPE";
1165         }
1166       case 11:
1167         switch (value) {
1168           case 1:  return "Seconds";
1169           case 2:  return "Kilobytes";
1170           default: return "UNKNOWN-SA-VALUE";
1171         }
1172       case 12:
1173         return "Duration-Value";
1174       case 13:
1175         return "PRF-Value";
1176       case 14:
1177         return "Key-Length";
1178       case 15:
1179         return "Field-Size";
1180       default: return "UNKNOWN-ATTRIBUTE-TYPE";
1181     }
1182   }
1183 }
1184
1185 static const char * 
1186 attrtype2str(guint8 type) {
1187   switch (type) {
1188   case 0: return "Reserved";
1189   case 1: return "ISAKMP_CFG_REQUEST";
1190   case 2: return "ISAKMP_CFG_REPLY";
1191   case 3: return "ISAKMP_CFG_SET";
1192   case 4: return "ISAKMP_CFG_ACK";
1193   }
1194   if(type < 127)
1195     return "Future use";
1196   return "Private use";
1197 }
1198
1199 static const char * 
1200 cfgattrident2str(guint16 ident) {
1201 #define NUM_ATTR_DEFINED        12
1202   static const char *msgs[NUM_PREDEFINED] = {
1203     "RESERVED",
1204     "INTERNAL_IP4_ADDRESS",
1205     "INTERNAL_IP4_NETMASK",
1206     "INTERNAL_IP4_DNS",
1207     "INTERNAL_IP4_NBNS",
1208     "INTERNAL_ADDRESS_EXPIREY",
1209     "INTERNAL_IP4_DHCP",
1210     "APPLICATION_VERSION"
1211     "INTERNAL_IP6_ADDRESS",
1212     "INTERNAL_IP6_NETMASK",
1213     "INTERNAL_IP6_DNS",
1214     "INTERNAL_IP6_NBNS",
1215     "INTERNAL_IP6_DHCP",
1216   }; 
1217   if(ident < NUM_ATTR_DEFINED)
1218     return msgs[ident];
1219   if(ident < 16383)
1220     return "Future use";
1221   switch(ident) {
1222   case 16520: return "XAUTH_TYPE";
1223   case 16521: return "XAUTH_USER_NAME";
1224   case 16522: return "XAUTH_USER_PASSWORD";
1225   case 16523: return "XAUTH_PASSCODE";
1226   case 16524: return "XAUTH_MESSAGE";
1227   case 16525: return "XAUTH_CHALLANGE";
1228   case 16526: return "XAUTH_DOMAIN";
1229   case 16527: return "XAUTH_STATUS";
1230   case 16528: return "XAUTH_NEXT_PIN";
1231   case 16529: return "XAUTH_ANSWER";
1232   default: return "Private use";
1233   }
1234 }
1235
1236 static const char *
1237 certtype2str(guint8 type) {
1238 #define NUM_CERTTYPE 11
1239   static const char *msgs[NUM_CERTTYPE] = {
1240     "NONE",
1241     "PKCS #7 wrapped X.509 certificate",
1242     "PGP Certificate",
1243     "DNS Signed Key",
1244     "X.509 Certificate - Signature",
1245     "X.509 Certificate - Key Exchange",
1246     "Kerberos Tokens",
1247     "Certificate Revocation List (CRL)",
1248     "Authority Revocation List (ARL)",
1249     "SPKI Certificate",
1250     "X.509 Certificate - Attribute",
1251   };
1252   if(type > NUM_CERTTYPE)
1253     return "RESERVED";
1254   return msgs[type];
1255 }
1256
1257 static gboolean
1258 get_num(tvbuff_t *tvb, int offset, guint16 len, guint32 *num_p) {
1259
1260   switch (len) {
1261   case 1:
1262     *num_p = tvb_get_guint8(tvb, offset);
1263     break;
1264   case 2:
1265     *num_p = tvb_get_ntohs(tvb, offset);
1266     break;
1267   case 3:
1268     *num_p = tvb_get_ntoh24(tvb, offset);
1269     break;
1270   case 4:
1271     *num_p = tvb_get_ntohl(tvb, offset);
1272     break;
1273   default:
1274     return FALSE;
1275   }
1276
1277   return TRUE;
1278 }
1279
1280 void
1281 proto_register_isakmp(void)
1282 {
1283 /*  static hf_register_info hf[] = {
1284     { &variable,
1285     { "Name",           "isakmp.abbreviation", TYPE, VALS_POINTER }},
1286   };*/
1287   static gint *ett[] = {
1288     &ett_isakmp,
1289     &ett_isakmp_flags,
1290     &ett_isakmp_payload,
1291   };
1292
1293   proto_isakmp = proto_register_protocol("Internet Security Association and Key Management Protocol",
1294                                                "ISAKMP", "isakmp");
1295 /*  proto_register_field_array(proto_isakmp, hf, array_length(hf));*/
1296   proto_register_subtree_array(ett, array_length(ett));
1297 }
1298
1299 void
1300 proto_reg_handoff_isakmp(void)
1301 {
1302   dissector_handle_t isakmp_handle;
1303
1304   /*
1305    * Get handle for the AH & ESP dissectors.
1306    */
1307   esp_handle = find_dissector("esp");
1308   ah_handle = find_dissector("ah");
1309
1310   isakmp_handle = create_dissector_handle(dissect_isakmp, proto_isakmp);
1311   dissector_add("udp.port", UDP_PORT_ISAKMP, isakmp_handle);
1312   dissector_add("tcp.port", TCP_PORT_ISAKMP, isakmp_handle);
1313 }