1 /****************************************************************************
2 **
3 ** File: isakmp.c
4 **
5 ** Extensions and additions by: Stuart Stock (stuart@ins.com)
6 ** Original Author: Mike Borella
7 **
8 ** Comments: Dump ISAKMP headers under IPSec DOI
9 **
10 ** See RFC 2408 "Internet Security Association and Key Management Protocol"
11 ** and RFC 2407 "The Internet IP Security Domain Interpretation for ISAKMP"
12 **
13 ** and when you can't find the value anywhere else, look in:
14 ** draft-ietf-ipsec-ike-01 "The Internet Key Exchange (IKE)"
15 **
16 ** $Id: isakmp.c,v 1.11 2007/06/25 13:03:00 farooq-i-azam Exp $
17 **
18 ** This program is free software; you can redistribute it and/or modify
19 ** it under the terms of the GNU General Public License as published by
20 ** the Free Software Foundation; either version 2 of the License, or
21 ** (at your option) any later version.
22 **
23 ** This program is distributed in the hope that it will be useful,
24 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
25 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26 ** GNU Library General Public License for more details.
27 **
28 ** You should have received a copy of the GNU General Public License
29 ** along with this program; if not, write to the Free Software
30 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 **
32 *****************************************************************************/
33 
34 #include "isakmp.h"
35 #include "payload.h"
36 
37 extern strmap_t ipproto_map[];
38 extern struct arg_t * my_args;
39 
40 #define ISAKMP_DOI_IPSEC         1
41 
42 /*
43  * Static part of ISAKMP header
44  */
45 
46 typedef struct isakmp
47 {
48   char i_cookie[8];
49   char r_cookie[8];
50 #if defined(WORDS_BIGENDIAN)
51   u_int16_t maj_version:4,
52             min_version:4,
53             next_payload:8;
54 #else
55   u_int16_t next_payload:8,
56             min_version:4,
57             maj_version:4;
58 #endif
59   u_int8_t  exchange_type;
60   u_int8_t  flags;
61   u_int32_t msg_id;
62   u_int32_t length;
63 } isakmp_t;
64 
65 
66 /*
67  * ISAKMP Generic Payload Header
68  */
69 
70 typedef struct isakmpgeneric
71 {
72   u_int8_t  next_payload;
73   u_int8_t  reserved;
74   u_int16_t length;
75 } isakmpgeneric_t;
76 
77 /*
78  * ISAKMP proposal payload (partial)
79  */
80 
81 typedef struct isakmpproposal
82 {
83   u_int8_t  number;
84   u_int8_t  protocol_id;
85   u_int8_t  spi_size;
86   u_int8_t  num_transforms;
87 } isakmpproposal_t;
88 
89 
90 /*
91  * ISAKMP transform payload (partial)
92  */
93 
94 typedef struct isakmptransform
95 {
96   u_int8_t  number;
97   u_int8_t  id;
98   u_int16_t reserved;
99 } isakmptransform_t;
100 
101 /*
102  * ISAKMP flags
103  */
104 
105 #define ISAKMP_FLAG_ENCRYPTION 0x01
106 #define ISAKMP_FLAG_COMMIT     0x02
107 #define ISAKMP_FLAG_AUTHONLY   0x04
108 
109 /*
110  * ISAKMP payload types
111  */
112 
113 #define ISAKMP_PAYLOAD_NONE             0
114 #define ISAKMP_PAYLOAD_SA               1
115 #define ISAKMP_PAYLOAD_PROPOSAL         2
116 #define ISAKMP_PAYLOAD_TRANSFORM        3
117 #define ISAKMP_PAYLOAD_KEYEXCHANGE      4
118 #define ISAKMP_PAYLOAD_IDENTIFICATION   5
119 #define ISAKMP_PAYLOAD_CERTIFICATE      6
120 #define ISAKMP_PAYLOAD_CERTIFICATEREQ   7
121 #define ISAKMP_PAYLOAD_HASH             8
122 #define ISAKMP_PAYLOAD_SIGNATURE        9
123 #define ISAKMP_PAYLOAD_NONCE            10
124 #define ISAKMP_PAYLOAD_NOTIFICATION     11
125 #define ISAKMP_PAYLOAD_DELETE           12
126 #define ISAKMP_PAYLOAD_VENDORID         13
127 
128 /*
129  * ISAKMP payload map
130  */
131 
132 strmap_t isakmp_payload_map[] =
133 {
134   { ISAKMP_PAYLOAD_NONE,           "none" },
135   { ISAKMP_PAYLOAD_SA,             "security association" },
136   { ISAKMP_PAYLOAD_PROPOSAL,       "proposal" },
137   { ISAKMP_PAYLOAD_TRANSFORM,      "transform" },
138   { ISAKMP_PAYLOAD_KEYEXCHANGE,    "key exchange" },
139   { ISAKMP_PAYLOAD_IDENTIFICATION, "identification" },
140   { ISAKMP_PAYLOAD_CERTIFICATE,    "certificate" },
141   { ISAKMP_PAYLOAD_CERTIFICATEREQ, "certificate request" },
142   { ISAKMP_PAYLOAD_HASH,           "hash" },
143   { ISAKMP_PAYLOAD_SIGNATURE,      "signature" },
144   { ISAKMP_PAYLOAD_NONCE,          "nonce" },
145   { ISAKMP_PAYLOAD_NOTIFICATION,   "notification" },
146   { ISAKMP_PAYLOAD_DELETE,         "delete" },
147   { ISAKMP_PAYLOAD_VENDORID,       "vendor id" },
148   { 0, "" }
149 };
150 
151 
152 /*
153  * ISAKMP exchange types
154  */
155 
156 #define ISAKMP_EXCHANGE_NONE             0
157 #define ISAKMP_EXCHANGE_BASE             1
158 #define ISAKMP_EXCHANGE_IDPROTECT        2
159 #define ISAKMP_EXCHANGE_AUTHONLY         3
160 #define ISAKMP_EXCHANGE_AGGRESSIVE       4
161 #define ISAKMP_EXCHANGE_INFORMATIONAL    5
162 
163 /*
164  * ISAKMP exchange map
165  */
166 
167 strmap_t isakmp_exchange_map[] =
168 {
169   { ISAKMP_EXCHANGE_NONE,           "none" },
170   { ISAKMP_EXCHANGE_BASE,           "base" },
171   { ISAKMP_EXCHANGE_IDPROTECT,      "identity protection" },
172   { ISAKMP_EXCHANGE_AUTHONLY,       "authentication only" },
173   { ISAKMP_EXCHANGE_AGGRESSIVE,     "aggressive" },
174   { ISAKMP_EXCHANGE_INFORMATIONAL,  "informational" },
175   { 0, "" }
176 };
177 
178 
179 /*
180  * Situation definitions for IPSEC DOI
181  */
182 
183 #define ISAKMP_SIT_IDENTITYONLY  0x01
184 #define ISAKMP_SIT_SECRECY       0x02
185 #define ISAKMP_SIT_INTEGRITY     0x04
186 
187 /*
188  * IPSEC DOI situation map
189  */
190 
191 strmap_t isakmp_doisituation_map[] =
192 {
193   { ISAKMP_SIT_IDENTITYONLY,        "identity only" },
194   { ISAKMP_SIT_SECRECY,             "secrecy" },
195   { ISAKMP_SIT_INTEGRITY,           "integrity" },
196   { 0, "" }
197 };
198 
199 /*
200  * Protocol ID definitions
201  */
202 
203 #define ISAKMP_PROTOCOLID_RESERVED     0
204 #define ISAKMP_PROTOCOLID_ISAKMP       1
205 #define ISAKMP_PROTOCOLID_IPSECAH      2
206 #define ISAKMP_PROTOCOLID_IPSECESP     3
207 #define ISAKMP_PROTOCOLID_IPCOMP       4
208 
209 /*
210  * Protocol ID map
211  */
212 
213 strmap_t isakmp_protocolid_map[] =
214 {
215   { ISAKMP_PROTOCOLID_RESERVED,     "reserved" },
216   { ISAKMP_PROTOCOLID_ISAKMP,       "ISAKMP" },
217   { ISAKMP_PROTOCOLID_IPSECAH,      "IPSEC AH" },
218   { ISAKMP_PROTOCOLID_IPSECESP,     "IPSEC ESP" },
219   { ISAKMP_PROTOCOLID_IPCOMP,       "IPCOMP" },
220   { 0, "" }
221 };
222 
223 /*
224  * Transform definitions
225  */
226 
227 #define ISAKMP_TRANSFORM_RESERVED   0
228 #define ISAKMP_TRANSFORM_KEYIKE     1
229 
230 /*
231  * Transform map
232  */
233 
234 strmap_t isakmp_transform_map[] =
235 {
236   { ISAKMP_TRANSFORM_RESERVED,     "reserved" },
237   { ISAKMP_TRANSFORM_KEYIKE,       "KEY_IKE" },
238   { 0, "" }
239 };
240 
241 /*
242  * Attribute types
243  */
244 
245 #define ISAKMP_ATTR_ENCRALG          1
246 #define ISAKMP_ATTR_HASHALG          2
247 #define ISAKMP_ATTR_AUTHMETHOD       3
248 #define ISAKMP_ATTR_GROUPDESC        4
249 #define ISAKMP_ATTR_GROUPTYPE        5
250 #define ISAKMP_ATTR_GROUPPRIME       6
251 #define ISAKMP_ATTR_GROUPGEN1        7
252 #define ISAKMP_ATTR_GROUPGEN2        8
253 #define ISAKMP_ATTR_GROUPCURVEA      9
254 #define ISAKMP_ATTR_GROUPCURVEB      10
255 #define ISAKMP_ATTR_LIFETYPE         11
256 #define ISAKMP_ATTR_LIFEDURATION     12
257 #define ISAKMP_ATTR_PRF              13
258 #define ISAKMP_ATTR_KEYLENGTH        14
259 #define ISAKMP_ATTR_FIELDSIZE        15
260 #define ISAKMP_ATTR_GROUPORDER       16
261 
262 /*
263  * Attribute type map
264  */
265 
266 strmap_t isakmp_attr_map[] =
267 {
268   { ISAKMP_ATTR_ENCRALG,      "encryption algorithm" },
269   { ISAKMP_ATTR_HASHALG,      "hash algorithm" },
270   { ISAKMP_ATTR_AUTHMETHOD,   "authentication method" },
271   { ISAKMP_ATTR_GROUPDESC,    "group description" },
272   { ISAKMP_ATTR_GROUPTYPE,    "group type" },
273   { ISAKMP_ATTR_GROUPPRIME,   "group prime" },
274   { ISAKMP_ATTR_GROUPGEN1,    "group generator 1" },
275   { ISAKMP_ATTR_GROUPGEN2,    "group generator 2" },
276   { ISAKMP_ATTR_GROUPCURVEA,  "group curve A" },
277   { ISAKMP_ATTR_GROUPCURVEB,  "group curve B" },
278   { ISAKMP_ATTR_LIFETYPE,     "life type" },
279   { ISAKMP_ATTR_LIFEDURATION, "life duration" },
280   { ISAKMP_ATTR_PRF,          "PRF" },
281   { ISAKMP_ATTR_KEYLENGTH,    "key length" },
282   { ISAKMP_ATTR_FIELDSIZE,    "field size" },
283   { ISAKMP_ATTR_GROUPORDER,   "group order" },
284   { 0, "" }
285 };
286 
287 /*
288  * Encryption algorithm attribute types
289  */
290 
291 #define ISAKMP_ATTR_ENCRALG_DESCBC           1
292 #define ISAKMP_ATTR_ENCRALG_IDEACBC          2
293 #define ISAKMP_ATTR_ENCRALG_BLOWFISHCBC      3
294 #define ISAKMP_ATTR_ENCRALG_RC5R16B64CBC     4
295 #define ISAKMP_ATTR_ENCRALG_3DESCBC          5
296 #define ISAKMP_ATTR_ENCRALG_CASTCBC          6
297 
298 /*
299  * Encryption algorithm attribute map
300  */
301 
302 strmap_t isakmp_attr_encralg_map[] =
303 {
304   { ISAKMP_ATTR_ENCRALG_DESCBC,       "DES-CBC" },
305   { ISAKMP_ATTR_ENCRALG_IDEACBC,      "IDEA-CBC" },
306   { ISAKMP_ATTR_ENCRALG_BLOWFISHCBC,  "blowfish-CBC" },
307   { ISAKMP_ATTR_ENCRALG_RC5R16B64CBC, "RC5-R16-B64-CBC" },
308   { ISAKMP_ATTR_ENCRALG_3DESCBC,      "3DES-CBC" },
309   { ISAKMP_ATTR_ENCRALG_CASTCBC,      "CAST-CBC" },
310   { 0, "" }
311 };
312 
313 /*
314  * Hash algorithm attribute types
315  */
316 
317 #define ISAKMP_ATTR_HASHALG_MD5               1
318 #define ISAKMP_ATTR_HASHALG_SHA               2
319 #define ISAKMP_ATTR_HASHALG_TIGER             3
320 
321 /*
322  * Hash algorithm attribute map
323  */
324 
325 strmap_t isakmp_attr_hashalg_map[] =
326 {
327   { ISAKMP_ATTR_HASHALG_MD5,          "MD5" },
328   { ISAKMP_ATTR_HASHALG_SHA,          "SHA" },
329   { ISAKMP_ATTR_HASHALG_TIGER,        "Tiger" },
330   { 0, "" }
331 };
332 
333 /*
334  * Authentication method attribute types
335  */
336 
337 #define ISAKMP_ATTR_AUTHMETHOD_PRESHAREDKEY    1
338 #define ISAKMP_ATTR_AUTHMETHOD_DSSSIG          2
339 #define ISAKMP_ATTR_AUTHMETHOD_RSASIG          3
340 #define ISAKMP_ATTR_AUTHMETHOD_ENCRRSA         4
341 #define ISAKMP_ATTR_AUTHMETHOD_REVENCRRSA      5
342 
343 /*
344  * Authentication method attribute map
345  */
346 
347 strmap_t isakmp_attr_authmethod_map[] =
348 {
349   { ISAKMP_ATTR_AUTHMETHOD_PRESHAREDKEY,      "pre-shared key" },
350   { ISAKMP_ATTR_AUTHMETHOD_DSSSIG,            "DSS signatures" },
351   { ISAKMP_ATTR_AUTHMETHOD_RSASIG,            "RSA signatures" },
352   { ISAKMP_ATTR_AUTHMETHOD_ENCRRSA,           "encryption with RSA" },
353   { ISAKMP_ATTR_AUTHMETHOD_REVENCRRSA,        "revised encryption with RSA" },
354   { 0, "" }
355 };
356 
357 
358 /*
359  * Group description attribute types
360  */
361 
362 #define ISAKMP_ATTR_GROUPDESC_MODP768          1
363 #define ISAKMP_ATTR_GROUPDESC_MODP1024         2
364 #define ISAKMP_ATTR_GROUPDESC_EC2N155          3
365 #define ISAKMP_ATTR_GROUPDESC_EC2N185          4
366 
367 /*
368  * Group description attribute map
369  */
370 
371 strmap_t isakmp_attr_groupdesc_map[] =
372 {
373   { ISAKMP_ATTR_GROUPDESC_MODP768,        "768-bit MODP group" },
374   { ISAKMP_ATTR_GROUPDESC_MODP1024,       "1024-bit MODP group" },
375   { ISAKMP_ATTR_GROUPDESC_EC2N155,        "EC2N group on GP[2^155]" },
376   { ISAKMP_ATTR_GROUPDESC_EC2N185,        "EC2N group on GP[2^185]" },
377   { 0, "" }
378 };
379 
380 /*
381  * Group type attribute types
382  */
383 
384 #define ISAKMP_ATTR_GROUPTYPE_MODP             1
385 #define ISAKMP_ATTR_GROUPTYPE_ECP              2
386 #define ISAKMP_ATTR_GROUPTYPE_EC2N             3
387 
388 /*
389  * Group type attribute map
390  */
391 
392 strmap_t isakmp_attr_grouptype_map[] =
393 {
394   { ISAKMP_ATTR_GROUPTYPE_MODP,        "modular exponentiation" },
395   { ISAKMP_ATTR_GROUPTYPE_ECP,         "elliptical curve over GF[P]" },
396   { ISAKMP_ATTR_GROUPTYPE_EC2N,        "elliptical curve over GF[2^N]" },
397   { 0, "" }
398 };
399 
400 /*
401  * Life type attribute types
402  */
403 
404 #define ISAKMP_ATTR_LIFETYPE_SECONDS    1
405 #define ISAKMP_ATTR_LIFETYPE_KILOBYTES  2
406 
407 /*
408  * Life type attribute map
409  */
410 
411 strmap_t isakmp_attr_lifetype_map[] =
412 {
413   { ISAKMP_ATTR_LIFETYPE_SECONDS,        "seconds" },
414   { ISAKMP_ATTR_LIFETYPE_KILOBYTES,      "kilobytes" },
415   { 0, "" }
416 };
417 
418 void isakmp_next_payload(packet_t *, u_int8_t);
419 
420 /*----------------------------------------------------------------------------
421 **
422 ** dump_isakmp_attributes()
423 **
424 ** Parse an ISAKMP attribute set and interpret it.  This is for IKE with
425 ** the IPSEC DOI only!
426 **
427 **----------------------------------------------------------------------------
428 */
429 
dump_isakmp_attributes(u_int8_t * attr,int len)430 void dump_isakmp_attributes(u_int8_t *attr, int len)
431 {
432   u_int8_t * p;
433   u_int16_t  type;
434   u_int16_t  length;
435   u_int8_t * value;
436 
437   p = attr;
438 
439   while (1)
440     {
441       /* get the type */
442       if (p+2 > attr+len)
443 	return;
444       memcpy((void *) &type, (void * ) p, 2);
445       type = ntohs(type);
446       p = p + 2;
447       if (type >= 0x8000)
448 	{
449 	  u_int16_t temp;
450 
451 	  temp = type - 0x8000;
452 	  display_strmap("Attribute", temp, isakmp_attr_map);
453 	}
454       else
455 	display_strmap("Attribute", type, isakmp_attr_map);
456 
457 
458       /* determine whether we have a length field or not */
459       if (type < 0x8000)
460 	{
461 	  /* get length field */
462 	  if (p+2 > attr+len)
463 	    return;
464 	  memcpy((void *) &length, (void *) p, 2);
465 	  length = ntohs(length);
466 	  p = p + 2;
467 	  display("  Length", (u_int8_t *) &length, 2, DISP_DEC);
468 	}
469       else
470 	length = 2;
471 
472       /*
473        * Get the value.  Values without a length field should be 2 bytes.
474        * It must say that in some RFC but I just can't find it...
475        */
476 
477       if (p+length > attr+len)
478 	return;
479       value = my_malloc(length);
480       memcpy((void *) value, (void *) p, length);
481       reverse_byte_order(value, length);
482       p = p + length;
483 
484       /* display the value, based on its type */
485       switch(type & 0x7fff)
486 	{
487 	case ISAKMP_ATTR_ENCRALG:
488 	  display_strmap("  Value", (u_int16_t) *value,
489 			 isakmp_attr_encralg_map);
490 	  break;
491 
492 	case ISAKMP_ATTR_HASHALG:
493 	  display_strmap("  Value", (u_int16_t) *value,
494 			 isakmp_attr_hashalg_map);
495 	  break;
496 
497 	case ISAKMP_ATTR_AUTHMETHOD:
498 	  display_strmap("  Value", (u_int16_t) *value,
499 			 isakmp_attr_authmethod_map);
500 	  break;
501 
502 	case ISAKMP_ATTR_GROUPDESC:
503 	  display_strmap("  Value", (u_int16_t) *value,
504 			 isakmp_attr_groupdesc_map);
505 	  break;
506 
507 	case ISAKMP_ATTR_GROUPTYPE:
508 	  display_strmap("  Value", (u_int16_t) *value,
509 			 isakmp_attr_grouptype_map);
510 	  break;
511 
512 	case ISAKMP_ATTR_LIFETYPE:
513 	  display_strmap("  Value", (u_int16_t) *value,
514 			 isakmp_attr_lifetype_map);
515 	  break;
516 
517 	default:
518 	  display("  Value", (u_int8_t *) value, length, DISP_DEC);
519 	  break;
520 	}
521 
522       my_free(value);
523     }
524 }
525 
526 /*----------------------------------------------------------------------------
527 **
528 ** dump_isakmp_transform()
529 **
530 ** Parse ISAKMP transform payload
531 **
532 **----------------------------------------------------------------------------
533 */
534 
dump_isakmp_transform(packet_t * pkt)535 void dump_isakmp_transform(packet_t * pkt)
536 {
537   isakmpgeneric_t   hdr;
538   isakmptransform_t transform;
539   u_int8_t *        sa_attributes = NULL;
540   int               sa_attributes_len;
541 
542   /* get the generic header */
543   if (get_packet_bytes((u_int8_t *) &hdr, pkt, sizeof(hdr)) == 0)
544     return;
545 
546   /* conversions */
547   hdr.length = ntohs(hdr.length);
548 
549   if (my_args->m)
550     {
551       /* nothing to do here... */
552     }
553   else
554     {
555       display_header_banner("ISAKMP/IKE transform");
556       display_strmap("Next payload", hdr.next_payload, isakmp_payload_map);
557       display("Reserved", (u_int8_t *) &hdr.reserved, 1, DISP_DEC);
558       display("Payload length", (u_int8_t *) &hdr.length, 2, DISP_DEC);
559     }
560 
561   /* Get the fixed transform payload, then the SA attributes field */
562   if (get_packet_bytes((u_int8_t *) &transform, pkt,
563 		       sizeof(isakmptransform_t)) == 0)
564     return;
565   sa_attributes_len = hdr.length - 8;
566   if (sa_attributes_len > 0)
567     {
568       sa_attributes = (u_int8_t *) my_malloc(sa_attributes_len);
569       if (get_packet_bytes(sa_attributes, pkt, sa_attributes_len) == 0)
570 	{
571 	  my_free(sa_attributes);
572 	  return;
573 	}
574     }
575 
576   /* conversion */
577   transform.reserved = ntohs(transform.reserved);
578 
579   if (my_args->m)
580     {
581       /* nothing to do here... */
582     }
583   else
584     {
585       display("Transform #", (u_int8_t *) &transform.number, 1, DISP_DEC);
586       display_strmap("Transform ID", transform.id, isakmp_transform_map);
587       display("Reserved", (u_int8_t *) &transform.reserved, 2, DISP_DEC);
588       if (sa_attributes_len > 0)
589 	dump_isakmp_attributes(sa_attributes, sa_attributes_len);
590     }
591 
592   /* Dump the hex buffer */
593   hexbuffer_flush();
594 
595   /* free the sa_attrinutes memory */
596   if (sa_attributes_len > 0)
597     my_free(sa_attributes);
598 }
599 
600 /*----------------------------------------------------------------------------
601 **
602 ** dump_isakmp_proposal()
603 **
604 ** Parse ISAKMP proposal payload
605 **
606 **----------------------------------------------------------------------------
607 */
608 
dump_isakmp_proposal(packet_t * pkt)609 void dump_isakmp_proposal(packet_t * pkt)
610 {
611   isakmpgeneric_t  hdr;
612   isakmpproposal_t proposal;
613   u_int8_t *       spi = NULL;
614   int              i;
615 
616   /* get the generic header */
617   if (get_packet_bytes((u_int8_t *) &hdr, pkt, sizeof(hdr)) == 0)
618     return;
619 
620   /* conversions */
621   hdr.length = ntohs(hdr.length);
622 
623   if (my_args->m)
624     {
625       /* nothing to do here... */
626     }
627   else
628     {
629       display_header_banner("ISAKMP/IKE proposal");
630       display_strmap("Next payload", hdr.next_payload, isakmp_payload_map);
631       display("Reserved", (u_int8_t *) &hdr.reserved, 1, DISP_DEC);
632       display("Payload length", (u_int8_t *) &hdr.length, 2, DISP_DEC);
633     }
634 
635   /* get the proposal, then the SPI */
636   if (get_packet_bytes((u_int8_t *) &proposal, pkt, sizeof(proposal)) == 0)
637     return;
638   if (proposal.spi_size > 0)
639     {
640       spi = my_malloc(proposal.spi_size);
641       if (get_packet_bytes((u_int8_t *) &spi, pkt, proposal.spi_size) == 0)
642 	{
643 	  my_free(spi);
644 	  return;
645 	}
646     }
647 
648   if (my_args->m)
649     {
650       /* nothing to do here... */
651     }
652   else
653     {
654       display("Proposal #", (u_int8_t *) &proposal.number, 1, DISP_DEC);
655       display_strmap("Protocol ID", proposal.protocol_id,
656 		     isakmp_protocolid_map);
657       display("SPI size", (u_int8_t *) &proposal.spi_size, 1, DISP_DEC);
658       display("Number of transforms", (u_int8_t *) &proposal.num_transforms,
659 	      1, DISP_DEC);
660       if (proposal.spi_size > 0)
661 	display("SPI", (u_int8_t *) &spi, proposal.spi_size, DISP_HEX);
662     }
663 
664   /* Dump the hex buffer */
665   hexbuffer_flush();
666 
667   /* free the spi memory */
668   if (proposal.spi_size > 0)
669     my_free(spi);
670 
671   /* Do each of the transform headers */
672   i = 0;
673   while (i < proposal.num_transforms)
674     {
675       dump_isakmp_transform(pkt);
676       i++;
677     }
678 
679 }
680 
681 /*----------------------------------------------------------------------------
682 **
683 ** dump_isakmp_sa()
684 **
685 ** Parse ISAKMP SA payload
686 **
687 **----------------------------------------------------------------------------
688 */
689 
dump_isakmp_sa(packet_t * pkt)690 void dump_isakmp_sa(packet_t * pkt)
691 {
692   isakmpgeneric_t hdr;
693   u_int32_t       doi;
694   u_int32_t       situation;
695 
696   /* get the generic header */
697   if (get_packet_bytes((u_int8_t *) &hdr, pkt, sizeof(hdr)) == 0)
698     return;
699 
700   /* conversions */
701   hdr.length = ntohs(hdr.length);
702 
703   if (my_args->m)
704     {
705       /* nothing to do here... */
706     }
707   else
708     {
709       display_header_banner("ISAKMP/IKE SA");
710       display_strmap("Next payload", hdr.next_payload, isakmp_payload_map);
711       display("Reserved", (u_int8_t *) &hdr.reserved, 1, DISP_DEC);
712       display("Payload length", (u_int8_t *) &hdr.length, 2, DISP_DEC);
713     }
714 
715   /*
716    * The next 4 bytes is the DOI.  We need to get it now in order to figure
717    * out what the situation is...
718    */
719 
720   if (get_packet_bytes((u_int8_t *) &doi, pkt, 4) == 0)
721     return;
722 
723   /* conversion */
724   doi = ntohl(doi);
725 
726   if (!my_args->m)
727     display("DOI", (u_int8_t *) &doi, 4, DISP_DEC);
728 
729   /* get the situation based on the DOI.  The IPSEC DOI situation is 4 bytes */
730   if (doi != ISAKMP_DOI_IPSEC)
731     return;
732   if (get_packet_bytes((u_int8_t *) &situation, pkt, 4) == 0)
733     return;
734 
735   /* conversion */
736   situation = ntohl(situation);
737 
738   if (!my_args->m)
739     display_strmap("Situation", situation, isakmp_doisituation_map);
740 
741 
742   /* Dump the hex buffer */
743   hexbuffer_flush();
744 
745   /*
746    * Since an SA payload is always followed by a number of
747    * proposal / transform payload sets, we parse then next, automatically,
748    * then we do the given "next payload".  How annoying...
749    */
750 
751   dump_isakmp_proposal(pkt);
752 
753   /* determine the next payload and parse it */
754   isakmp_next_payload(pkt, hdr.next_payload);
755 }
756 
757 /*----------------------------------------------------------------------------
758 **
759 ** dump_isakmp_vendorid()
760 **
761 ** Parse ISAKMP vendorid payload
762 **
763 **----------------------------------------------------------------------------
764 */
765 
dump_isakmp_vendorid(packet_t * pkt)766 void dump_isakmp_vendorid(packet_t * pkt)
767 {
768   isakmpgeneric_t hdr;
769   u_int8_t *      vendorid;
770   int             len;
771 
772   /* get the generic header */
773   if (get_packet_bytes((u_int8_t *) &hdr, pkt, sizeof(hdr)) == 0)
774     return;
775 
776   /* conversions */
777   hdr.length = ntohs(hdr.length);
778 
779   if (my_args->m)
780     {
781       /* nothing to do here... */
782     }
783   else
784     {
785       display_header_banner("ISAKMP/IKE vendor ID");
786       display_strmap("Next payload", hdr.next_payload, isakmp_payload_map);
787       display("Reserved", (u_int8_t *) &hdr.reserved, 1, DISP_DEC);
788       display("Payload length", (u_int8_t *) &hdr.length, 2, DISP_DEC);
789     }
790 
791   /*
792    * This payload contains a vendor ID hash that is hdr.length - 4 bytes
793    * First allocate memory and grab it
794    */
795 
796   len = hdr.length - sizeof(isakmpgeneric_t);
797   vendorid = (u_int8_t *) my_malloc(len);
798   if (get_packet_bytes(vendorid, pkt, len) == 0)
799     {
800       my_free(vendorid);
801       return;
802     }
803 
804   display("Vendor ID (hash)", vendorid, len, DISP_HEX_MULTILINE);
805 
806   /* free memory */
807   my_free(vendorid);
808 
809   /* determine the next payload and parse it */
810   isakmp_next_payload(pkt, hdr.next_payload);
811 }
812 
813 /*----------------------------------------------------------------------------
814 **
815 ** dump_isakmp_delete()
816 **
817 ** Parse ISAKMP delete payload
818 **
819 **----------------------------------------------------------------------------
820 */
821 
dump_isakmp_delete(packet_t * pkt)822 void dump_isakmp_delete(packet_t * pkt)
823 {
824   isakmpgeneric_t hdr;
825 
826   /* get the generic header */
827   if (get_packet_bytes((u_int8_t *) &hdr, pkt, sizeof(hdr)) == 0)
828     return;
829 
830   /* conversions */
831   hdr.length = ntohs(hdr.length);
832 
833   if (my_args->m)
834     {
835       /* nothing to do here... */
836     }
837   else
838     {
839       display_header_banner("ISAKMP/IKE delete");
840       display_strmap("Next payload", hdr.next_payload, isakmp_payload_map);
841       display("Reserved", (u_int8_t *) &hdr.reserved, 1, DISP_DEC);
842       display("Payload length", (u_int8_t *) &hdr.length, 2, DISP_DEC);
843     }
844 
845 }
846 
847 /*----------------------------------------------------------------------------
848 **
849 ** isakmp_next_payload()
850 **
851 ** Call the proper payload parser based on the given next payload field
852 **
853 **----------------------------------------------------------------------------
854 */
855 
isakmp_next_payload(packet_t * pkt,u_int8_t next)856 void isakmp_next_payload(packet_t * pkt, u_int8_t next)
857 {
858   switch (next)
859     {
860     case ISAKMP_PAYLOAD_DELETE:
861       dump_isakmp_delete(pkt);
862       break;
863 
864     case ISAKMP_PAYLOAD_SA:
865       dump_isakmp_sa(pkt);
866       break;
867 
868     case ISAKMP_PAYLOAD_VENDORID:
869       dump_isakmp_vendorid(pkt);
870       break;
871 
872     default:
873       /* unrecognized payload, so we'll fall through and stop */
874       break;
875     }
876 }
877 
878 /*----------------------------------------------------------------------------
879 **
880 ** dump_isakmp()
881 **
882 ** Parse ISAKMP packet and dump fields.
883 **
884 **----------------------------------------------------------------------------
885 */
886 
dump_isakmp(packet_t * pkt)887 void dump_isakmp(packet_t * pkt)
888 {
889   isakmp_t isakmp;
890   u_int8_t major;
891   u_int8_t minor;
892   u_int8_t next;
893   u_int8_t e_flag, c_flag, a_flag;
894 
895   /* Set the layer */
896   set_layer(LAYER_APPLICATION);
897 
898   /*
899    * Get the main ISAKMP header
900    */
901 
902   if (get_packet_bytes((u_int8_t *) &isakmp, pkt, sizeof(isakmp_t)) == 0)
903     return;
904 
905   /*
906    * Conversions
907    */
908 
909   isakmp.msg_id = ntohl(isakmp.msg_id);
910   isakmp.length = ntohl(isakmp.length);
911   next = isakmp.next_payload;
912   major = isakmp.maj_version;
913   minor = isakmp.min_version;
914   e_flag = isakmp.flags & ISAKMP_FLAG_ENCRYPTION;
915   c_flag = isakmp.flags & ISAKMP_FLAG_COMMIT >> 1;
916   a_flag = isakmp.flags & ISAKMP_FLAG_AUTHONLY >> 2;
917 
918   /*
919    * Dump header
920    */
921 
922   if (my_args->m)
923     {
924       /* do something here */
925     }
926   else
927     {
928       display_header_banner("ISAKMP/IKE Header");
929 
930       display("Initiatior cookie", (u_int8_t *) &isakmp.i_cookie, 8, DISP_HEX);
931       display("Responder cookie", (u_int8_t *) &isakmp.r_cookie, 8, DISP_HEX);
932       display_strmap("Next payload", next, isakmp_payload_map);
933       display("Major version", (u_int8_t *) &major, 1, DISP_DEC);
934       display("Minor version", (u_int8_t *) &minor, 1, DISP_DEC);
935       display_strmap("Exchange type", isakmp.exchange_type,
936 		     isakmp_exchange_map);
937       display("Encryption flag", (u_int8_t *) &e_flag, 1, DISP_DEC);
938       display("Commit flag", (u_int8_t *) &c_flag, 1, DISP_DEC);
939       display("Auth only flag", (u_int8_t *) &a_flag, 1, DISP_DEC);
940       display("Message ID", (u_int8_t *) &isakmp.msg_id, 4, DISP_DEC);
941       display("Length", (u_int8_t *) &isakmp.length, 4, DISP_DEC);
942     }
943 
944   /*
945    * Dump the hex buffer
946    */
947 
948   hexbuffer_flush();
949 
950   /*
951    * Short circuit processing if this is the only header or encryption
952    * bit is set
953    */
954 
955   if (next == ISAKMP_PAYLOAD_NONE || e_flag)
956     {
957       return;
958     }
959 
960   /* determine the next payload and parse it */
961   isakmp_next_payload(pkt, next);
962 
963 }
964