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
, uint16_t * 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
, uint16_t * 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
, uint16_t * reject
)
695 struct isakmp_packet
*r
= new_isakmp_packet();
696 size_t o_data_len
= data_len
;
698 if (data_len
< ISAKMP_PAYLOAD_O
) {
699 reason
= ISAKMP_N_UNEQUAL_PAYLOAD_LENGTHS
;
703 DEBUG(3, printf("\nBEGIN_PARSE\n"));
704 fetchn(r
->i_cookie
, ISAKMP_COOKIE_LENGTH
);
705 hex_dump("i_cookie", r
->i_cookie
, ISAKMP_COOKIE_LENGTH
);
706 fetchn(r
->r_cookie
, ISAKMP_COOKIE_LENGTH
);
707 hex_dump("r_cookie", r
->r_cookie
, ISAKMP_COOKIE_LENGTH
);
709 hex_dump("payload", &payload
, UINT8
);
711 r
->isakmp_version
= fetch1();
712 hex_dump("isakmp_version", &r
->isakmp_version
, UINT8
);
713 if (r
->isakmp_version
> ISAKMP_VERSION
) {
714 if ((r
->isakmp_version
& 0xF0) >= (ISAKMP_VERSION
& 0xF0))
715 reason
= ISAKMP_N_INVALID_MAJOR_VERSION
;
717 reason
= ISAKMP_N_INVALID_MINOR_VERSION
;
721 r
->exchange_type
= fetch1();
722 hex_dump("exchange_type", &r
->exchange_type
, UINT8
);
724 hex_dump("flags", &r
->flags
, UINT8
);
725 r
->message_id
= fetch4();
726 hex_dump("message_id", &r
->message_id
, sizeof(r
->message_id
));
728 if (fetch4() != o_data_len
) {
729 reason
= ISAKMP_N_UNEQUAL_PAYLOAD_LENGTHS
;
732 hex_dump("len", &o_data_len
, UINT32
);
734 r
->payload
= parse_isakmp_payload(payload
, &data
, &data_len
, &reason
);
738 DEBUG(3, printf("PARSE_OK\n\n"));
742 free_isakmp_packet(r
);
748 const char *isakmp_notify_to_error(uint16_t notify
)
750 static const struct {
754 { ISAKMP_N_INVALID_PAYLOAD_TYPE
, "INVALID_PAYLOAD_TYPE"},
755 { ISAKMP_N_DOI_NOT_SUPPORTED
, "DOI_NOT_SUPPORTED"},
756 { ISAKMP_N_SITUATION_NOT_SUPPORTED
, "SITUATION_NOT_SUPPORTED"},
757 { ISAKMP_N_INVALID_COOKIE
, "INVALID_COOKIE"},
758 { ISAKMP_N_INVALID_MAJOR_VERSION
, "INVALID_MAJOR_VERSION"},
759 { ISAKMP_N_INVALID_MINOR_VERSION
, "INVALID_MINOR_VERSION"},
760 { ISAKMP_N_INVALID_EXCHANGE_TYPE
, "INVALID_EXCHANGE_TYPE"},
761 { ISAKMP_N_INVALID_FLAGS
, "INVALID_FLAGS"},
762 { ISAKMP_N_INVALID_MESSAGE_ID
, "INVALID_MESSAGE_ID"},
763 { ISAKMP_N_INVALID_PROTOCOL_ID
, "INVALID_PROTOCOL_ID"},
764 { ISAKMP_N_INVALID_SPI
, "INVALID_SPI"},
765 { ISAKMP_N_INVALID_TRANSFORM_ID
, "INVALID_TRANSFORM_ID"},
766 { ISAKMP_N_ATTRIBUTES_NOT_SUPPORTED
, "ATTRIBUTES_NOT_SUPPORTED"},
767 { ISAKMP_N_NO_PROPOSAL_CHOSEN
, "NO_PROPOSAL_CHOSEN"},
768 { ISAKMP_N_BAD_PROPOSAL_SYNTAX
, "BAD_PROPOSAL_SYNTAX"},
769 { ISAKMP_N_PAYLOAD_MALFORMED
, "PAYLOAD_MALFORMED"},
770 { ISAKMP_N_INVALID_KEY_INFORMATION
, "INVALID_KEY_INFORMATION"},
771 { ISAKMP_N_INVALID_ID_INFORMATION
, "INVALID_ID_INFORMATION"},
772 { ISAKMP_N_INVALID_CERT_ENCODING
, "INVALID_CERT_ENCODING"},
773 { ISAKMP_N_INVALID_CERTIFICATE
, "INVALID_CERTIFICATE"},
774 { ISAKMP_N_CERT_TYPE_UNSUPPORTED
, "CERT_TYPE_UNSUPPORTED"},
775 { ISAKMP_N_INVALID_CERT_AUTHORITY
, "INVALID_CERT_AUTHORITY"},
776 { ISAKMP_N_INVALID_HASH_INFORMATION
, "INVALID_HASH_INFORMATION"},
777 { ISAKMP_N_AUTHENTICATION_FAILED
, "AUTHENTICATION_FAILED"},
778 { ISAKMP_N_INVALID_SIGNATURE
, "INVALID_SIGNATURE"},
779 { ISAKMP_N_ADDRESS_NOTIFICATION
, "ADDRESS_NOTIFICATION"},
780 { ISAKMP_N_NOTIFY_SA_LIFETIME
, "NOTIFY_SA_LIFETIME"},
781 { ISAKMP_N_CERTIFICATE_UNAVAILABLE
, "CERTIFICATE_UNAVAILABLE"},
782 { ISAKMP_N_UNSUPPORTED_EXCHANGE_TYPE
, "UNSUPPORTED_EXCHANGE_TYPE"},
783 { ISAKMP_N_UNEQUAL_PAYLOAD_LENGTHS
, "UNEQUAL_PAYLOAD_LENGTHS"}
786 static char number
[10];
788 for (i
= 0; i
< sizeof(data
) / sizeof(data
[0]); i
++)
789 if (data
[i
].id
== notify
)
791 sprintf(number
, "%d", notify
);
795 void test_pack_unpack(void)
797 static const uint8_t pack
[] = {
798 0x7f, 0xba, 0x51, 0x29, 0x11, 0x9e, 0x76, 0xf7, 0x9a, 0x71, 0xee, 0x70,
799 0xaa, 0x82, 0xb9, 0x7f, 0x01, 0x10, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
800 0x00, 0x00, 0x01, 0x4c, 0x04, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x01,
801 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x01, 0x01, 0x00, 0x01,
802 0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x05,
803 0x80, 0x02, 0x00, 0x01, 0x80, 0x04, 0x00, 0x02, 0x80, 0x03, 0x00, 0x01,
804 0x0a, 0x00, 0x00, 0x84, 0x1b, 0x1d, 0x4b, 0x29, 0x0e, 0x29, 0xb9, 0x6f,
805 0x18, 0x34, 0xd1, 0x2d, 0xba, 0x92, 0x7c, 0x53, 0x35, 0x76, 0x0e, 0x3b,
806 0x25, 0x92, 0x4f, 0x7c, 0x1e, 0x31, 0x41, 0x8c, 0xb9, 0xe3, 0xda, 0xf7,
807 0x53, 0xd3, 0x22, 0x8e, 0xff, 0xeb, 0xed, 0x5b, 0x95, 0x56, 0x8d, 0xba,
808 0xa8, 0xe3, 0x2a, 0x9b, 0xb4, 0x04, 0x5c, 0x90, 0xf0, 0xfe, 0x92, 0xc8,
809 0x57, 0xa2, 0xc6, 0x0c, 0x85, 0xbb, 0x56, 0xe8, 0x1c, 0xa7, 0x2c, 0x57,
810 0x04, 0xb6, 0xe0, 0x43, 0x82, 0xe1, 0x9f, 0x0b, 0xa6, 0x8b, 0xce, 0x7f,
811 0x9b, 0x75, 0xbb, 0xd3, 0xff, 0x0e, 0x89, 0x19, 0xaf, 0xc6, 0x2e, 0xf6,
812 0x92, 0x06, 0x46, 0x4f, 0xc7, 0x97, 0x22, 0xf4, 0xa6, 0xf9, 0x26, 0x34,
813 0x04, 0x33, 0x89, 0x34, 0xa9, 0x2f, 0x81, 0x92, 0xd3, 0x21, 0x4f, 0x45,
814 0xbe, 0x38, 0x12, 0x26, 0xec, 0x87, 0x45, 0xdd, 0x10, 0x1c, 0xd6, 0x16,
815 0x05, 0x00, 0x00, 0x18, 0x77, 0xdf, 0x37, 0x3c, 0x03, 0x02, 0xe2, 0xc8,
816 0xe1, 0x2f, 0x92, 0xf0, 0x2e, 0xa2, 0xa6, 0x00, 0x17, 0x8f, 0xdf, 0xb4,
817 0x08, 0x00, 0x00, 0x0c, 0x01, 0x11, 0x01, 0xf4, 0xcd, 0xb4, 0x53, 0x6d,
818 0x0d, 0x00, 0x00, 0x14, 0x07, 0x47, 0x8d, 0xa7, 0x0b, 0xd6, 0xd1, 0x66,
819 0x7a, 0xaf, 0x2e, 0x61, 0x2a, 0x91, 0x80, 0x94, 0x0d, 0x00, 0x00, 0x14,
820 0x12, 0xf5, 0xf2, 0x8c, 0x45, 0x71, 0x68, 0xa9, 0x70, 0x2d, 0x9f, 0xe2,
821 0x74, 0xcc, 0x01, 0x00, 0x0d, 0x00, 0x00, 0x0c, 0x09, 0x00, 0x26, 0x89,
822 0xdf, 0xd6, 0xb7, 0x12, 0x0d, 0x00, 0x00, 0x14, 0xaf, 0xca, 0xd7, 0x13,
823 0x68, 0xa1, 0xf1, 0xc9, 0x6b, 0x86, 0x96, 0xfc, 0x77, 0x57, 0x01, 0x00,
824 0x00, 0x00, 0x00, 0x14, 0x1f, 0x07, 0xf7, 0x0e, 0xaa, 0x65, 0x14, 0xd3,
825 0xb0, 0xfa, 0x96, 0x54, 0x2a, 0x50, 0x03, 0x05
829 struct isakmp_packet
*p
;
832 p
= parse_isakmp_packet(pack
, sizeof(pack
), &reject
);
833 flatten_isakmp_packet(p
, &unpack
, &unpack_len
, 8);
834 if (unpack_len
!= sizeof(pack
)
835 || memcmp(unpack
, pack
, sizeof(pack
)) != 0)
838 free_isakmp_packet(p
);