1 /* ISAKMP packing and unpacking routines.
2 Copyright (C) 2002 Geoffrey Keating
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include "isakmp-pkt.h"
29 void *xallocc(size_t x
)
32 result
= calloc(1, x
);
34 error(1, errno
, "malloc of %lu bytes failed", (unsigned long)x
);
44 static uint8_t *flow_reserve_p(struct flow
*f
, size_t sz
)
46 size_t l
= f
->end
- f
->base
;
47 if (l
+ sz
> f
->len
) {
48 size_t new_len
= f
->len
== 0 ? 128 : f
->len
;
49 while (l
+ sz
>= new_len
)
53 f
->base
= malloc(new_len
);
55 f
->base
= realloc(f
->base
, new_len
);
57 error(1, errno
, "alloc of %lud bytes failed", (unsigned long)new_len
);
58 memset(f
->base
+ f
->len
, 0, new_len
- f
->len
);
66 static size_t flow_reserve(struct flow
*f
, size_t sz
)
68 uint8_t *p
= flow_reserve_p(f
, sz
);
72 static void flow_x(struct flow
*f
, uint8_t * data
, size_t data_len
)
74 memcpy(flow_reserve_p(f
, data_len
), data
, data_len
);
77 static void flow_1(struct flow
*f
, uint8_t d
)
79 flow_reserve_p(f
, 1)[0] = d
;
82 static void flow_2(struct flow
*f
, uint16_t d
)
87 flow_x(f
, dd
, sizeof(dd
));
90 static void flow_4(struct flow
*f
, uint32_t d
)
97 flow_x(f
, dd
, sizeof(dd
));
100 static void init_flow(struct flow
*f
)
102 memset(f
, 0, sizeof(*f
));
105 static void flow_attribute(struct flow
*f
, struct isakmp_attribute
*p
)
107 for (; p
; p
= p
->next
)
109 case isakmp_attr_lots
:
111 flow_2(f
, p
->u
.lots
.length
);
112 flow_x(f
, p
->u
.lots
.data
, p
->u
.lots
.length
);
115 flow_2(f
, p
->type
| 0x8000);
116 flow_2(f
, p
->u
.attr_16
);
118 case isakmp_attr_2x8
:
119 flow_2(f
, p
->type
| 0x8000);
120 flow_x(f
, p
->u
.attr_2x8
, 2);
127 static void flow_payload(struct flow
*f
, struct isakmp_payload
*p
)
135 baselen
= f
->end
- f
->base
;
139 flow_1(f
, p
->next
->type
);
141 lpos
= flow_reserve(f
, 2);
143 case ISAKMP_PAYLOAD_SA
:
144 flow_4(f
, p
->u
.sa
.doi
);
145 flow_4(f
, p
->u
.sa
.situation
);
146 flow_payload(f
, p
->u
.sa
.proposals
);
148 case ISAKMP_PAYLOAD_P
:
149 flow_1(f
, p
->u
.p
.number
);
150 flow_1(f
, p
->u
.p
.prot_id
);
151 flow_1(f
, p
->u
.p
.spi_size
);
153 uint8_t num_xform
= 0;
154 struct isakmp_payload
*xform
;
155 for (xform
= p
->u
.p
.transforms
; xform
; xform
= xform
->next
)
157 flow_1(f
, num_xform
);
159 flow_x(f
, p
->u
.p
.spi
, p
->u
.p
.spi_size
);
160 flow_payload(f
, p
->u
.p
.transforms
);
162 case ISAKMP_PAYLOAD_T
:
163 flow_1(f
, p
->u
.t
.number
);
164 flow_1(f
, p
->u
.t
.id
);
166 flow_attribute(f
, p
->u
.t
.attributes
);
168 case ISAKMP_PAYLOAD_KE
:
169 case ISAKMP_PAYLOAD_HASH
:
170 case ISAKMP_PAYLOAD_SIG
:
171 case ISAKMP_PAYLOAD_NONCE
:
172 case ISAKMP_PAYLOAD_VID
:
173 case ISAKMP_PAYLOAD_NAT_D
:
174 case ISAKMP_PAYLOAD_NAT_D_OLD
:
175 flow_x(f
, p
->u
.ke
.data
, p
->u
.ke
.length
);
177 case ISAKMP_PAYLOAD_ID
:
178 flow_1(f
, p
->u
.id
.type
);
179 flow_1(f
, p
->u
.id
.protocol
);
180 flow_2(f
, p
->u
.id
.port
);
181 flow_x(f
, p
->u
.id
.data
, p
->u
.id
.length
);
183 case ISAKMP_PAYLOAD_CERT
:
184 case ISAKMP_PAYLOAD_CR
:
185 flow_1(f
, p
->u
.cert
.encoding
);
186 flow_x(f
, p
->u
.cert
.data
, p
->u
.cert
.length
);
188 case ISAKMP_PAYLOAD_N
:
189 flow_4(f
, p
->u
.n
.doi
);
190 flow_1(f
, p
->u
.n
.protocol
);
191 flow_1(f
, p
->u
.n
.spi_length
);
192 flow_2(f
, p
->u
.n
.type
);
193 flow_x(f
, p
->u
.n
.spi
, p
->u
.n
.spi_length
);
194 flow_x(f
, p
->u
.n
.data
, p
->u
.n
.data_length
);
196 case ISAKMP_PAYLOAD_D
:
197 flow_4(f
, p
->u
.d
.doi
);
198 flow_1(f
, p
->u
.d
.protocol
);
199 flow_1(f
, p
->u
.d
.spi_length
);
200 flow_2(f
, p
->u
.d
.num_spi
);
201 if (p
->u
.d
.spi_length
> 0) {
203 for (i
= 0; i
< p
->u
.d
.num_spi
; i
++)
204 flow_x(f
, p
->u
.d
.spi
[i
], p
->u
.d
.spi_length
);
207 case ISAKMP_PAYLOAD_MODECFG_ATTR
:
208 flow_1(f
, p
->u
.modecfg
.type
);
210 flow_2(f
, p
->u
.modecfg
.id
);
211 flow_attribute(f
, p
->u
.modecfg
.attributes
);
216 f
->base
[lpos
] = (f
->end
- f
->base
- baselen
) >> 8;
217 f
->base
[lpos
+ 1] = (f
->end
- f
->base
- baselen
);
218 flow_payload(f
, p
->next
);
221 void flatten_isakmp_payload(struct isakmp_payload
*p
, uint8_t ** result
, size_t * size
)
227 *size
= f
.end
- f
.base
;
230 void flatten_isakmp_packet(struct isakmp_packet
*p
, uint8_t ** result
, size_t * size
, size_t blksz
)
233 size_t lpos
, sz
, padding
;
236 flow_x(&f
, p
->i_cookie
, ISAKMP_COOKIE_LENGTH
);
237 flow_x(&f
, p
->r_cookie
, ISAKMP_COOKIE_LENGTH
);
238 if (p
->payload
== NULL
)
241 flow_1(&f
, p
->payload
->type
);
242 flow_1(&f
, p
->isakmp_version
);
243 flow_1(&f
, p
->exchange_type
);
244 flow_1(&f
, p
->flags
);
245 flow_4(&f
, p
->message_id
);
246 lpos
= flow_reserve(&f
, 4);
247 flow_payload(&f
, p
->payload
);
248 if (p
->flags
& ISAKMP_FLAG_E
) {
250 sz
= (f
.end
- f
.base
) - ISAKMP_PAYLOAD_O
;
251 padding
= blksz
- (sz
% blksz
);
252 if (padding
== blksz
)
254 DEBUG(3, printf("size = %ld, blksz = %ld, padding = %ld\n",
255 (long)sz
, (long)blksz
, (long)padding
));
256 flow_reserve(&f
, padding
);
258 f
.base
[lpos
] = (f
.end
- f
.base
) >> 24;
259 f
.base
[lpos
+ 1] = (f
.end
- f
.base
) >> 16;
260 f
.base
[lpos
+ 2] = (f
.end
- f
.base
) >> 8;
261 f
.base
[lpos
+ 3] = (f
.end
- f
.base
);
263 *size
= f
.end
- f
.base
;
264 /*DUMP*/ if (opt_debug
>= 3) {
265 printf("\n sending: ========================>\n");
266 free_isakmp_packet(parse_isakmp_packet(f
.base
, f
.end
- f
.base
, NULL
));
270 struct isakmp_attribute
*new_isakmp_attribute(uint16_t type
, struct isakmp_attribute
*next
)
272 struct isakmp_attribute
*r
= xallocc(sizeof(struct isakmp_attribute
));
278 struct isakmp_attribute
*new_isakmp_attribute_16(uint16_t type
, uint16_t data
,
279 struct isakmp_attribute
*next
)
281 struct isakmp_attribute
*r
= xallocc(sizeof(struct isakmp_attribute
));
284 r
->af
= isakmp_attr_16
;
289 struct isakmp_packet
*new_isakmp_packet(void)
291 return xallocc(sizeof(struct isakmp_packet
));
294 struct isakmp_payload
*new_isakmp_payload(uint8_t type
)
296 struct isakmp_payload
*result
= xallocc(sizeof(struct isakmp_packet
));
301 struct isakmp_payload
*new_isakmp_data_payload(uint8_t type
, const void *data
, size_t data_length
)
303 struct isakmp_payload
*result
= xallocc(sizeof(struct isakmp_packet
));
305 if (type
!= ISAKMP_PAYLOAD_KE
&& type
!= ISAKMP_PAYLOAD_HASH
306 && type
!= ISAKMP_PAYLOAD_SIG
&& type
!= ISAKMP_PAYLOAD_NONCE
307 && type
!= ISAKMP_PAYLOAD_VID
&& type
!= ISAKMP_PAYLOAD_NAT_D
308 && type
!= ISAKMP_PAYLOAD_NAT_D_OLD
)
310 if (data_length
>= 16384)
314 result
->u
.ke
.length
= data_length
;
315 result
->u
.ke
.data
= xallocc(data_length
);
316 memcpy(result
->u
.ke
.data
, data
, data_length
);
320 void free_isakmp_payload(struct isakmp_payload
*p
)
322 struct isakmp_payload
*nxt
;
328 case ISAKMP_PAYLOAD_SA
:
329 free_isakmp_payload(p
->u
.sa
.proposals
);
331 case ISAKMP_PAYLOAD_P
:
332 free_isakmp_payload(p
->u
.p
.transforms
);
334 case ISAKMP_PAYLOAD_T
:
336 struct isakmp_attribute
*att
, *natt
;
337 for (att
= p
->u
.t
.attributes
; att
; att
= natt
) {
339 if (att
->af
== isakmp_attr_lots
)
340 free(att
->u
.lots
.data
);
345 case ISAKMP_PAYLOAD_KE
:
346 case ISAKMP_PAYLOAD_HASH
:
347 case ISAKMP_PAYLOAD_SIG
:
348 case ISAKMP_PAYLOAD_NONCE
:
349 case ISAKMP_PAYLOAD_VID
:
350 case ISAKMP_PAYLOAD_NAT_D
:
351 case ISAKMP_PAYLOAD_NAT_D_OLD
:
354 case ISAKMP_PAYLOAD_ID
:
357 case ISAKMP_PAYLOAD_CERT
:
358 case ISAKMP_PAYLOAD_CR
:
359 free(p
->u
.cert
.data
);
361 case ISAKMP_PAYLOAD_N
:
365 case ISAKMP_PAYLOAD_D
:
368 for (i
= 0; i
< p
->u
.d
.num_spi
; i
++)
373 case ISAKMP_PAYLOAD_MODECFG_ATTR
:
375 struct isakmp_attribute
*att
, *natt
;
376 for (att
= p
->u
.modecfg
.attributes
; att
; att
= natt
) {
378 if (att
->af
== isakmp_attr_lots
)
379 free(att
->u
.lots
.data
);
390 free_isakmp_payload(nxt
);
393 void free_isakmp_packet(struct isakmp_packet
*p
)
397 free_isakmp_payload(p
->payload
);
402 (data += 4, data_len -= 4, \
403 (uint32_t)(data[-4]) << 24 | (uint32_t)(data[-3]) << 16 \
404 | (uint32_t)(data[-2]) << 8 | data[-1])
406 (data += 2, data_len -= 2, \
407 (uint16_t)(data[-2]) << 8 | data[-1])
408 #define fetch1() (data_len--, *data++)
409 #define fetchn(d,n) \
410 (memcpy ((d), data, (n)), data += (n), data_len -= (n))
412 static struct isakmp_attribute
*parse_isakmp_attributes(const uint8_t ** data_p
,
413 size_t data_len
, int * reject
)
415 const uint8_t *data
= *data_p
;
416 struct isakmp_attribute
*r
;
417 uint16_t type
, length
;
422 r
= new_isakmp_attribute(0, NULL
);
426 r
->type
= type
& ~0x8000;
427 hex_dump("t.attributes.type", &r
->type
, UINT16
);
428 r
->af
= isakmp_attr_16
;
429 r
->u
.attr_16
= length
;
430 if ((ISAKMP_XAUTH_ATTRIB_TYPE
<= r
->type
)
431 && (r
->type
<= ISAKMP_XAUTH_ATTRIB_ANSWER
)
433 DEBUG(3, printf("(not dumping xauth data)\n"));
435 hex_dump("t.attributes.u.attr_16", &r
->u
.attr_16
, UINT16
);
438 hex_dump("t.attributes.type", &r
->type
, UINT16
);
439 r
->af
= isakmp_attr_lots
;
440 r
->u
.lots
.length
= length
;
441 if ((ISAKMP_XAUTH_ATTRIB_TYPE
<= r
->type
) && (r
->type
<= ISAKMP_XAUTH_ATTRIB_ANSWER
)
443 DEBUG(3, printf("(not dumping xauth data length)\n"));
445 hex_dump("t.attributes.u.lots.length", &r
->u
.lots
.length
, UINT16
);
446 if (data_len
< length
) {
447 *reject
= ISAKMP_N_PAYLOAD_MALFORMED
;
450 r
->u
.lots
.data
= xallocc(length
);
451 fetchn(r
->u
.lots
.data
, length
);
452 if ((ISAKMP_XAUTH_ATTRIB_TYPE
<= type
) && (type
<= ISAKMP_XAUTH_ATTRIB_ANSWER
)
454 DEBUG(3, printf("(not dumping xauth data)\n"));
456 hex_dump("t.attributes.u.lots.data", r
->u
.lots
.data
, r
->u
.lots
.length
);
458 r
->next
= parse_isakmp_attributes(&data
, data_len
, reject
);
463 static struct isakmp_payload
*parse_isakmp_payload(uint8_t type
,
464 const uint8_t ** data_p
, size_t * data_len_p
, int * reject
)
466 const uint8_t *data
= *data_p
;
467 size_t data_len
= *data_len_p
;
468 struct isakmp_payload
*r
;
470 size_t length
, olength
;
472 static const uint16_t min_payload_len
[ISAKMP_PAYLOAD_MODECFG_ATTR
+ 1] = {
473 4, 12, 8, 8, 4, 8, 5, 5, 4, 4, 4, 12, 12, 4, 8
476 hex_dump("PARSING PAYLOAD type", &type
, UINT8
);
479 if (type
<= ISAKMP_PAYLOAD_MODECFG_ATTR
) {
480 if (data_len
< min_payload_len
[type
]) {
481 *reject
= ISAKMP_N_PAYLOAD_MALFORMED
;
484 } else if (data_len
< 4) {
485 *reject
= ISAKMP_N_PAYLOAD_MALFORMED
;
489 r
= new_isakmp_payload(type
);
490 next_type
= fetch1();
491 hex_dump("next_type", &next_type
, UINT8
);
493 *reject
= ISAKMP_N_PAYLOAD_MALFORMED
;
497 hex_dump("length", &length
, UINT16
);
498 if (length
> data_len
+ 4
499 || ((type
<= ISAKMP_PAYLOAD_MODECFG_ATTR
)&&(length
< min_payload_len
[type
]))
501 *reject
= ISAKMP_N_PAYLOAD_MALFORMED
;
506 case ISAKMP_PAYLOAD_SA
:
507 r
->u
.sa
.doi
= fetch4();
508 hex_dump("sa.doi", &r
->u
.sa
.doi
, UINT32
);
509 if (r
->u
.sa
.doi
!= ISAKMP_DOI_IPSEC
) {
510 *reject
= ISAKMP_N_DOI_NOT_SUPPORTED
;
513 r
->u
.sa
.situation
= fetch4();
514 hex_dump("sa.situation", &r
->u
.sa
.situation
, UINT32
);
515 if (r
->u
.sa
.situation
!= ISAKMP_IPSEC_SIT_IDENTITY_ONLY
) {
516 *reject
= ISAKMP_N_SITUATION_NOT_SUPPORTED
;
521 r
->u
.sa
.proposals
= parse_isakmp_payload(ISAKMP_PAYLOAD_P
, &data
, &length
, reject
);
524 /* Allow trailing garbage at end of payload. */
525 data_len
-= olength
- 12;
528 case ISAKMP_PAYLOAD_P
:
529 if (next_type
!= ISAKMP_PAYLOAD_P
&& next_type
!= 0) {
530 *reject
= ISAKMP_N_INVALID_PAYLOAD_TYPE
;
535 struct isakmp_payload
*xform
;
537 r
->u
.p
.number
= fetch1();
538 hex_dump("p.number", &r
->u
.p
.number
, UINT8
);
539 r
->u
.p
.prot_id
= fetch1();
540 hex_dump("p.prot_id", &r
->u
.p
.prot_id
, UINT8
);
541 r
->u
.p
.spi_size
= fetch1();
542 hex_dump("p.spi_size", &r
->u
.p
.spi_size
, UINT8
);
543 num_xform
= fetch1();
544 hex_dump("length", &num_xform
, UINT8
);
546 if (data_len
< r
->u
.p
.spi_size
) {
547 *reject
= ISAKMP_N_PAYLOAD_MALFORMED
;
550 r
->u
.p
.spi
= xallocc(r
->u
.p
.spi_size
);
551 fetchn(r
->u
.p
.spi
, r
->u
.p
.spi_size
);
552 hex_dump("p.spi", r
->u
.p
.spi
, r
->u
.p
.spi_size
);
553 length
-= 8 + r
->u
.p
.spi_size
;
554 r
->u
.p
.transforms
= parse_isakmp_payload(ISAKMP_PAYLOAD_T
,
555 &data
, &length
, reject
);
556 for (xform
= r
->u
.p
.transforms
; xform
; xform
= xform
->next
)
557 if (num_xform
-- == 0)
559 if (num_xform
!= 0) {
560 *reject
= ISAKMP_N_BAD_PROPOSAL_SYNTAX
;
564 /* Allow trailing garbage at end of payload. */
565 data_len
-= olength
- 8 - r
->u
.p
.spi_size
;
569 case ISAKMP_PAYLOAD_T
:
570 if (next_type
!= ISAKMP_PAYLOAD_T
&& next_type
!= 0) {
571 *reject
= ISAKMP_N_INVALID_PAYLOAD_TYPE
;
574 r
->u
.t
.number
= fetch1();
575 hex_dump("t.number", &r
->u
.t
.number
, UINT8
);
576 r
->u
.t
.id
= fetch1();
577 hex_dump("t.id", &r
->u
.t
.id
, UINT8
);
579 *reject
= ISAKMP_N_BAD_PROPOSAL_SYNTAX
;
583 r
->u
.t
.attributes
= parse_isakmp_attributes(&data
, length
, reject
);
584 data_len
-= olength
- 8;
587 case ISAKMP_PAYLOAD_KE
:
588 case ISAKMP_PAYLOAD_HASH
:
589 case ISAKMP_PAYLOAD_SIG
:
590 case ISAKMP_PAYLOAD_NONCE
:
591 case ISAKMP_PAYLOAD_VID
:
592 case ISAKMP_PAYLOAD_NAT_D
:
593 case ISAKMP_PAYLOAD_NAT_D_OLD
:
594 r
->u
.ke
.length
= length
- 4;
595 r
->u
.ke
.data
= xallocc(r
->u
.ke
.length
);
596 fetchn(r
->u
.ke
.data
, r
->u
.ke
.length
);
597 hex_dump("ke.data", r
->u
.ke
.data
, r
->u
.ke
.length
);
599 case ISAKMP_PAYLOAD_ID
:
600 r
->u
.id
.type
= fetch1();
601 hex_dump("id.type", &r
->u
.id
.type
, UINT8
);
602 r
->u
.id
.protocol
= fetch1();
603 hex_dump("id.protocol", &r
->u
.id
.protocol
, UINT8
);
604 r
->u
.id
.port
= fetch2();
605 hex_dump("id.port", &r
->u
.id
.port
, sizeof(r
->u
.id
.port
));
606 r
->u
.id
.length
= length
- 8;
607 r
->u
.id
.data
= xallocc(r
->u
.id
.length
);
608 fetchn(r
->u
.id
.data
, r
->u
.id
.length
);
609 hex_dump("id.data", r
->u
.id
.data
, r
->u
.id
.length
);
611 case ISAKMP_PAYLOAD_CERT
:
612 case ISAKMP_PAYLOAD_CR
:
613 r
->u
.cert
.encoding
= fetch1();
614 hex_dump("cert.encoding", &r
->u
.cert
.encoding
, UINT8
);
615 r
->u
.cert
.length
= length
- 5;
616 fetchn(r
->u
.cert
.data
, r
->u
.cert
.length
);
617 hex_dump("cert.data", r
->u
.cert
.data
, r
->u
.cert
.length
);
619 case ISAKMP_PAYLOAD_N
:
620 r
->u
.n
.doi
= fetch4();
621 hex_dump("n.doi", &r
->u
.n
.doi
, UINT32
);
622 r
->u
.n
.protocol
= fetch1();
623 hex_dump("n.protocol", &r
->u
.n
.protocol
, UINT8
);
624 r
->u
.n
.spi_length
= fetch1();
625 hex_dump("n.spi_length", &r
->u
.n
.spi_length
, UINT8
);
626 r
->u
.n
.type
= fetch2();
627 hex_dump("n.type", &r
->u
.n
.type
, UINT16
);
628 if (r
->u
.n
.spi_length
+ 12u > length
) {
629 *reject
= ISAKMP_N_PAYLOAD_MALFORMED
;
632 r
->u
.n
.spi
= xallocc(r
->u
.n
.spi_length
);
633 fetchn(r
->u
.n
.spi
, r
->u
.n
.spi_length
);
634 hex_dump("n.spi", r
->u
.n
.spi
, r
->u
.n
.spi_length
);
635 r
->u
.n
.data_length
= length
- 12 - r
->u
.n
.spi_length
;
636 r
->u
.n
.data
= xallocc(r
->u
.n
.data_length
);
637 fetchn(r
->u
.n
.data
, r
->u
.n
.data_length
);
638 hex_dump("n.data", r
->u
.n
.data
, r
->u
.n
.data_length
);
640 case ISAKMP_PAYLOAD_D
:
641 r
->u
.n
.doi
= fetch4(); /*FIXME: huuuh? */
642 hex_dump("n.doi", &r
->u
.n
.doi
, UINT32
);
643 r
->u
.n
.protocol
= fetch1();
644 hex_dump("n.protocol", &r
->u
.n
.protocol
, UINT8
);
645 r
->u
.n
.spi_length
= fetch1();
646 hex_dump("n.spi_length", &r
->u
.n
.spi_length
, UINT8
);
647 r
->u
.d
.num_spi
= fetch2();
648 hex_dump("d.num_spi", &r
->u
.d
.num_spi
, UINT16
);
649 if (r
->u
.d
.num_spi
* r
->u
.n
.spi_length
+ 12u != length
) {
650 *reject
= ISAKMP_N_PAYLOAD_MALFORMED
;
653 r
->u
.d
.spi
= xallocc(sizeof(uint8_t *) * r
->u
.d
.num_spi
);
656 for (i
= 0; i
< r
->u
.d
.num_spi
; i
++) {
657 r
->u
.d
.spi
[i
] = xallocc(r
->u
.d
.spi_length
);
658 fetchn(r
->u
.d
.spi
[i
], r
->u
.d
.spi_length
);
659 hex_dump("d.spi", r
->u
.d
.spi
[i
], r
->u
.d
.spi_length
);
663 case ISAKMP_PAYLOAD_MODECFG_ATTR
:
664 r
->u
.modecfg
.type
= fetch1();
665 hex_dump("modecfg.type", &r
->u
.modecfg
.type
, UINT8
);
667 *reject
= ISAKMP_N_PAYLOAD_MALFORMED
;
670 r
->u
.t
.id
= fetch2();
671 hex_dump("t.id", &r
->u
.t
.id
, UINT16
);
673 r
->u
.t
.attributes
= parse_isakmp_attributes(&data
, length
, reject
);
674 data_len
-= olength
- 8;
678 r
->u
.ke
.length
= length
- 4;
679 r
->u
.ke
.data
= xallocc(r
->u
.ke
.length
);
680 fetchn(r
->u
.ke
.data
, r
->u
.ke
.length
);
681 hex_dump("UNKNOWN.data", r
->u
.ke
.data
, r
->u
.ke
.length
);
685 *data_len_p
= data_len
;
686 hex_dump("DONE PARSING PAYLOAD type", &type
, UINT8
);
687 r
->next
= parse_isakmp_payload(next_type
, data_p
, data_len_p
, reject
);
691 struct isakmp_packet
*parse_isakmp_packet(const uint8_t * data
, size_t data_len
, int * reject
)
695 struct isakmp_packet
*r
= new_isakmp_packet();
696 size_t o_data_len
= data_len
;
697 size_t isakmp_data_len
;
699 if (data_len
< ISAKMP_PAYLOAD_O
) {
700 DEBUG(2, printf("packet to short: len = %d < min = %d\n", data_len
, ISAKMP_PAYLOAD_O
));
701 reason
= ISAKMP_N_UNEQUAL_PAYLOAD_LENGTHS
;
705 DEBUG(3, printf("\nBEGIN_PARSE\n"));
706 fetchn(r
->i_cookie
, ISAKMP_COOKIE_LENGTH
);
707 hex_dump("i_cookie", r
->i_cookie
, ISAKMP_COOKIE_LENGTH
);
708 fetchn(r
->r_cookie
, ISAKMP_COOKIE_LENGTH
);
709 hex_dump("r_cookie", r
->r_cookie
, ISAKMP_COOKIE_LENGTH
);
711 hex_dump("payload", &payload
, UINT8
);
713 r
->isakmp_version
= fetch1();
714 hex_dump("isakmp_version", &r
->isakmp_version
, UINT8
);
715 if (r
->isakmp_version
> ISAKMP_VERSION
) {
716 if ((r
->isakmp_version
& 0xF0) >= (ISAKMP_VERSION
& 0xF0))
717 reason
= ISAKMP_N_INVALID_MAJOR_VERSION
;
719 reason
= ISAKMP_N_INVALID_MINOR_VERSION
;
723 r
->exchange_type
= fetch1();
724 hex_dump("exchange_type", &r
->exchange_type
, UINT8
);
726 hex_dump("flags", &r
->flags
, UINT8
);
727 r
->message_id
= fetch4();
728 hex_dump("message_id", &r
->message_id
, sizeof(r
->message_id
));
730 isakmp_data_len
= fetch4();
731 hex_dump("len", &isakmp_data_len
, UINT32
);
732 if (o_data_len
!= isakmp_data_len
) {
733 DEBUG(2, printf("isakmp length does not match packet length: isakmp = %d != datalen = %d\n",
734 isakmp_data_len
, o_data_len
));
735 reason
= ISAKMP_N_UNEQUAL_PAYLOAD_LENGTHS
;
739 r
->payload
= parse_isakmp_payload(payload
, &data
, &data_len
, &reason
);
743 DEBUG(3, printf("PARSE_OK\n\n"));
747 free_isakmp_packet(r
);
753 const char *isakmp_notify_to_error(uint16_t notify
)
755 static const struct {
759 { ISAKMP_N_INVALID_PAYLOAD_TYPE
, "INVALID_PAYLOAD_TYPE"},
760 { ISAKMP_N_DOI_NOT_SUPPORTED
, "DOI_NOT_SUPPORTED"},
761 { ISAKMP_N_SITUATION_NOT_SUPPORTED
, "SITUATION_NOT_SUPPORTED"},
762 { ISAKMP_N_INVALID_COOKIE
, "INVALID_COOKIE"},
763 { ISAKMP_N_INVALID_MAJOR_VERSION
, "INVALID_MAJOR_VERSION"},
764 { ISAKMP_N_INVALID_MINOR_VERSION
, "INVALID_MINOR_VERSION"},
765 { ISAKMP_N_INVALID_EXCHANGE_TYPE
, "INVALID_EXCHANGE_TYPE"},
766 { ISAKMP_N_INVALID_FLAGS
, "INVALID_FLAGS"},
767 { ISAKMP_N_INVALID_MESSAGE_ID
, "INVALID_MESSAGE_ID"},
768 { ISAKMP_N_INVALID_PROTOCOL_ID
, "INVALID_PROTOCOL_ID"},
769 { ISAKMP_N_INVALID_SPI
, "INVALID_SPI"},
770 { ISAKMP_N_INVALID_TRANSFORM_ID
, "INVALID_TRANSFORM_ID"},
771 { ISAKMP_N_ATTRIBUTES_NOT_SUPPORTED
, "ATTRIBUTES_NOT_SUPPORTED"},
772 { ISAKMP_N_NO_PROPOSAL_CHOSEN
, "NO_PROPOSAL_CHOSEN"},
773 { ISAKMP_N_BAD_PROPOSAL_SYNTAX
, "BAD_PROPOSAL_SYNTAX"},
774 { ISAKMP_N_PAYLOAD_MALFORMED
, "PAYLOAD_MALFORMED"},
775 { ISAKMP_N_INVALID_KEY_INFORMATION
, "INVALID_KEY_INFORMATION"},
776 { ISAKMP_N_INVALID_ID_INFORMATION
, "INVALID_ID_INFORMATION"},
777 { ISAKMP_N_INVALID_CERT_ENCODING
, "INVALID_CERT_ENCODING"},
778 { ISAKMP_N_INVALID_CERTIFICATE
, "INVALID_CERTIFICATE"},
779 { ISAKMP_N_CERT_TYPE_UNSUPPORTED
, "CERT_TYPE_UNSUPPORTED"},
780 { ISAKMP_N_INVALID_CERT_AUTHORITY
, "INVALID_CERT_AUTHORITY"},
781 { ISAKMP_N_INVALID_HASH_INFORMATION
, "INVALID_HASH_INFORMATION"},
782 { ISAKMP_N_AUTHENTICATION_FAILED
, "AUTHENTICATION_FAILED"},
783 { ISAKMP_N_INVALID_SIGNATURE
, "INVALID_SIGNATURE"},
784 { ISAKMP_N_ADDRESS_NOTIFICATION
, "ADDRESS_NOTIFICATION"},
785 { ISAKMP_N_NOTIFY_SA_LIFETIME
, "NOTIFY_SA_LIFETIME"},
786 { ISAKMP_N_CERTIFICATE_UNAVAILABLE
, "CERTIFICATE_UNAVAILABLE"},
787 { ISAKMP_N_UNSUPPORTED_EXCHANGE_TYPE
, "UNSUPPORTED_EXCHANGE_TYPE"},
788 { ISAKMP_N_UNEQUAL_PAYLOAD_LENGTHS
, "UNEQUAL_PAYLOAD_LENGTHS"}
791 static char number
[10];
793 for (i
= 0; i
< sizeof(data
) / sizeof(data
[0]); i
++)
794 if (data
[i
].id
== notify
)
796 sprintf(number
, "%d", notify
);
800 void test_pack_unpack(void)
802 static const uint8_t pack
[] = {
803 0x7f, 0xba, 0x51, 0x29, 0x11, 0x9e, 0x76, 0xf7, 0x9a, 0x71, 0xee, 0x70,
804 0xaa, 0x82, 0xb9, 0x7f, 0x01, 0x10, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
805 0x00, 0x00, 0x01, 0x4c, 0x04, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x01,
806 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x01, 0x01, 0x00, 0x01,
807 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x05,
808 0x80, 0x02, 0x00, 0x01, 0x80, 0x04, 0x00, 0x02, 0x80, 0x03, 0x00, 0x01,
809 0x0a, 0x00, 0x00, 0x84, 0x1b, 0x1d, 0x4b, 0x29, 0x0e, 0x29, 0xb9, 0x6f,
810 0x18, 0x34, 0xd1, 0x2d, 0xba, 0x92, 0x7c, 0x53, 0x35, 0x76, 0x0e, 0x3b,
811 0x25, 0x92, 0x4f, 0x7c, 0x1e, 0x31, 0x41, 0x8c, 0xb9, 0xe3, 0xda, 0xf7,
812 0x53, 0xd3, 0x22, 0x8e, 0xff, 0xeb, 0xed, 0x5b, 0x95, 0x56, 0x8d, 0xba,
813 0xa8, 0xe3, 0x2a, 0x9b, 0xb4, 0x04, 0x5c, 0x90, 0xf0, 0xfe, 0x92, 0xc8,
814 0x57, 0xa2, 0xc6, 0x0c, 0x85, 0xbb, 0x56, 0xe8, 0x1c, 0xa7, 0x2c, 0x57,
815 0x04, 0xb6, 0xe0, 0x43, 0x82, 0xe1, 0x9f, 0x0b, 0xa6, 0x8b, 0xce, 0x7f,
816 0x9b, 0x75, 0xbb, 0xd3, 0xff, 0x0e, 0x89, 0x19, 0xaf, 0xc6, 0x2e, 0xf6,
817 0x92, 0x06, 0x46, 0x4f, 0xc7, 0x97, 0x22, 0xf4, 0xa6, 0xf9, 0x26, 0x34,
818 0x04, 0x33, 0x89, 0x34, 0xa9, 0x2f, 0x81, 0x92, 0xd3, 0x21, 0x4f, 0x45,
819 0xbe, 0x38, 0x12, 0x26, 0xec, 0x87, 0x45, 0xdd, 0x10, 0x1c, 0xd6, 0x16,
820 0x05, 0x00, 0x00, 0x18, 0x77, 0xdf, 0x37, 0x3c, 0x03, 0x02, 0xe2, 0xc8,
821 0xe1, 0x2f, 0x92, 0xf0, 0x2e, 0xa2, 0xa6, 0x00, 0x17, 0x8f, 0xdf, 0xb4,
822 0x08, 0x00, 0x00, 0x0c, 0x01, 0x11, 0x01, 0xf4, 0xcd, 0xb4, 0x53, 0x6d,
823 0x0d, 0x00, 0x00, 0x14, 0x07, 0x47, 0x8d, 0xa7, 0x0b, 0xd6, 0xd1, 0x66,
824 0x7a, 0xaf, 0x2e, 0x61, 0x2a, 0x91, 0x80, 0x94, 0x0d, 0x00, 0x00, 0x14,
825 0x12, 0xf5, 0xf2, 0x8c, 0x45, 0x71, 0x68, 0xa9, 0x70, 0x2d, 0x9f, 0xe2,
826 0x74, 0xcc, 0x01, 0x00, 0x0d, 0x00, 0x00, 0x0c, 0x09, 0x00, 0x26, 0x89,
827 0xdf, 0xd6, 0xb7, 0x12, 0x0d, 0x00, 0x00, 0x14, 0xaf, 0xca, 0xd7, 0x13,
828 0x68, 0xa1, 0xf1, 0xc9, 0x6b, 0x86, 0x96, 0xfc, 0x77, 0x57, 0x01, 0x00,
829 0x00, 0x00, 0x00, 0x14, 0x1f, 0x07, 0xf7, 0x0e, 0xaa, 0x65, 0x14, 0xd3,
830 0xb0, 0xfa, 0x96, 0x54, 0x2a, 0x50, 0x03, 0x05
834 struct isakmp_packet
*p
;
837 p
= parse_isakmp_packet(pack
, sizeof(pack
), &reject
);
838 flatten_isakmp_packet(p
, &unpack
, &unpack_len
, 8);
839 if (unpack_len
!= sizeof(pack
)
840 || memcmp(unpack
, pack
, sizeof(pack
)) != 0)
843 free_isakmp_packet(p
);