1 /* ISAKMP packing and unpacking routines.
2    Copyright (C) 2002  Geoffrey Keating
3    Copyright (C) 2003-2005 Maurice Massar
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9 
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 
19    $Id: isakmp-pkt.c 312 2008-06-15 18:09:42Z Joerg Mayer $
20 */
21 
22 #include <assert.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <stdio.h>
27 
28 #include "sysdep.h"
29 #include "config.h"
30 #include "isakmp-pkt.h"
31 #include "math_group.h"
32 #include "vpnc.h"
33 
xallocc(size_t x)34 void *xallocc(size_t x)
35 {
36 	void *result;
37 	result = calloc(1, x);
38 	if (result == NULL)
39 		error(1, errno, "malloc of %lu bytes failed", (unsigned long)x);
40 	return result;
41 }
42 
43 struct flow {
44 	size_t len;
45 	uint8_t *base;
46 	uint8_t *end;
47 };
48 
flow_reserve_p(struct flow * f,size_t sz)49 static uint8_t *flow_reserve_p(struct flow *f, size_t sz)
50 {
51 	size_t l = f->end - f->base;
52 	if (l + sz > f->len) {
53 		size_t new_len = f->len == 0 ? 128 : f->len;
54 		while (l + sz >= new_len)
55 			new_len *= 2;
56 
57 		if (f->base == NULL)
58 			f->base = malloc(new_len);
59 		else
60 			f->base = realloc(f->base, new_len);
61 		if (f->base == NULL)
62 			error(1, errno, "alloc of %lud bytes failed", (unsigned long)new_len);
63 		memset(f->base + f->len, 0, new_len - f->len);
64 		f->end = f->base + l;
65 		f->len = new_len;
66 	}
67 	f->end += sz;
68 	return f->end - sz;
69 }
70 
flow_reserve(struct flow * f,size_t sz)71 static size_t flow_reserve(struct flow *f, size_t sz)
72 {
73 	uint8_t *p = flow_reserve_p(f, sz);
74 	return p - f->base;
75 }
76 
flow_x(struct flow * f,uint8_t * data,size_t data_len)77 static void flow_x(struct flow *f, uint8_t * data, size_t data_len)
78 {
79 	memcpy(flow_reserve_p(f, data_len), data, data_len);
80 }
81 
flow_1(struct flow * f,uint8_t d)82 static void flow_1(struct flow *f, uint8_t d)
83 {
84 	flow_reserve_p(f, 1)[0] = d;
85 }
86 
flow_2(struct flow * f,uint16_t d)87 static void flow_2(struct flow *f, uint16_t d)
88 {
89 	uint8_t dd[2];
90 	dd[0] = d >> 8;
91 	dd[1] = d;
92 	flow_x(f, dd, sizeof(dd));
93 }
94 
flow_4(struct flow * f,uint32_t d)95 static void flow_4(struct flow *f, uint32_t d)
96 {
97 	uint8_t dd[4];
98 	dd[0] = d >> 24;
99 	dd[1] = d >> 16;
100 	dd[2] = d >> 8;
101 	dd[3] = d;
102 	flow_x(f, dd, sizeof(dd));
103 }
104 
init_flow(struct flow * f)105 static void init_flow(struct flow *f)
106 {
107 	memset(f, 0, sizeof(*f));
108 }
109 
flow_attribute(struct flow * f,struct isakmp_attribute * p)110 static void flow_attribute(struct flow *f, struct isakmp_attribute *p)
111 {
112 	for (; p; p = p->next)
113 		switch (p->af) {
114 		case isakmp_attr_lots:
115 			flow_2(f, p->type);
116 			flow_2(f, p->u.lots.length);
117 			flow_x(f, p->u.lots.data, p->u.lots.length);
118 			break;
119 		case isakmp_attr_16:
120 			flow_2(f, p->type | 0x8000);
121 			flow_2(f, p->u.attr_16);
122 			break;
123 		case isakmp_attr_2x8:
124 			flow_2(f, p->type | 0x8000);
125 			flow_x(f, p->u.attr_2x8, 2);
126 			break;
127 		default:
128 			abort();
129 		}
130 }
131 
flow_payload(struct flow * f,struct isakmp_payload * p)132 static void flow_payload(struct flow *f, struct isakmp_payload *p)
133 {
134 	size_t lpos;
135 	size_t baselen;
136 
137 	if (p == NULL)
138 		return;
139 
140 	baselen = f->end - f->base;
141 	if (p->next == NULL)
142 		flow_1(f, 0);
143 	else
144 		flow_1(f, p->next->type);
145 	flow_1(f, 0);
146 	lpos = flow_reserve(f, 2);
147 	switch (p->type) {
148 	case ISAKMP_PAYLOAD_SA:
149 		flow_4(f, p->u.sa.doi);
150 		flow_4(f, p->u.sa.situation);
151 		flow_payload(f, p->u.sa.proposals);
152 		break;
153 	case ISAKMP_PAYLOAD_P:
154 		flow_1(f, p->u.p.number);
155 		flow_1(f, p->u.p.prot_id);
156 		flow_1(f, p->u.p.spi_size);
157 		{
158 			uint8_t num_xform = 0;
159 			struct isakmp_payload *xform;
160 			for (xform = p->u.p.transforms; xform; xform = xform->next)
161 				num_xform++;
162 			flow_1(f, num_xform);
163 		}
164 		flow_x(f, p->u.p.spi, p->u.p.spi_size);
165 		flow_payload(f, p->u.p.transforms);
166 		break;
167 	case ISAKMP_PAYLOAD_T:
168 		flow_1(f, p->u.t.number);
169 		flow_1(f, p->u.t.id);
170 		flow_2(f, 0);
171 		flow_attribute(f, p->u.t.attributes);
172 		break;
173 	case ISAKMP_PAYLOAD_KE:
174 	case ISAKMP_PAYLOAD_HASH:
175 	case ISAKMP_PAYLOAD_SIG:
176 	case ISAKMP_PAYLOAD_NONCE:
177 	case ISAKMP_PAYLOAD_VID:
178 	case ISAKMP_PAYLOAD_NAT_D:
179 	case ISAKMP_PAYLOAD_NAT_D_OLD:
180 		flow_x(f, p->u.ke.data, p->u.ke.length);
181 		break;
182 	case ISAKMP_PAYLOAD_ID:
183 		flow_1(f, p->u.id.type);
184 		flow_1(f, p->u.id.protocol);
185 		flow_2(f, p->u.id.port);
186 		flow_x(f, p->u.id.data, p->u.id.length);
187 		break;
188 	case ISAKMP_PAYLOAD_CERT:
189 	case ISAKMP_PAYLOAD_CR:
190 		flow_1(f, p->u.cert.encoding);
191 		flow_x(f, p->u.cert.data, p->u.cert.length);
192 		break;
193 	case ISAKMP_PAYLOAD_N:
194 		flow_4(f, p->u.n.doi);
195 		flow_1(f, p->u.n.protocol);
196 		flow_1(f, p->u.n.spi_length);
197 		flow_2(f, p->u.n.type);
198 		flow_x(f, p->u.n.spi, p->u.n.spi_length);
199 		flow_x(f, p->u.n.data, p->u.n.data_length);
200 		break;
201 	case ISAKMP_PAYLOAD_D:
202 		flow_4(f, p->u.d.doi);
203 		flow_1(f, p->u.d.protocol);
204 		flow_1(f, p->u.d.spi_length);
205 		flow_2(f, p->u.d.num_spi);
206 		if (p->u.d.spi_length > 0) {
207 			int i;
208 			for (i = 0; i < p->u.d.num_spi; i++)
209 				flow_x(f, p->u.d.spi[i], p->u.d.spi_length);
210 		}
211 		break;
212 	case ISAKMP_PAYLOAD_MODECFG_ATTR:
213 		flow_1(f, p->u.modecfg.type);
214 		flow_1(f, 0);
215 		flow_2(f, p->u.modecfg.id);
216 		flow_attribute(f, p->u.modecfg.attributes);
217 		break;
218 	default:
219 		abort();
220 	}
221 	f->base[lpos] = (f->end - f->base - baselen) >> 8;
222 	f->base[lpos + 1] = (f->end - f->base - baselen);
223 	flow_payload(f, p->next);
224 }
225 
flatten_isakmp_payloads(struct isakmp_payload * p,uint8_t ** result,size_t * size)226 void flatten_isakmp_payloads(struct isakmp_payload *p, uint8_t ** result, size_t * size)
227 {
228 	struct flow f;
229 	init_flow(&f);
230 	flow_payload(&f, p);
231 	*result = f.base;
232 	*size = f.end - f.base;
233 }
234 
flatten_isakmp_payload(struct isakmp_payload * p,uint8_t ** result,size_t * size)235 void flatten_isakmp_payload(struct isakmp_payload *p, uint8_t ** result, size_t * size)
236 {
237 	struct isakmp_payload *next;
238 	next = p->next;
239 	p->next = NULL;
240 	flatten_isakmp_payloads(p, result, size);
241 	p->next = next;
242 }
243 
flatten_isakmp_packet(struct isakmp_packet * p,uint8_t ** result,size_t * size,size_t blksz)244 void flatten_isakmp_packet(struct isakmp_packet *p, uint8_t ** result, size_t * size, size_t blksz)
245 {
246 	struct flow f;
247 	size_t lpos, sz, padding;
248 
249 	init_flow(&f);
250 	flow_x(&f, p->i_cookie, ISAKMP_COOKIE_LENGTH);
251 	flow_x(&f, p->r_cookie, ISAKMP_COOKIE_LENGTH);
252 	if (p->payload == NULL)
253 		flow_1(&f, 0);
254 	else
255 		flow_1(&f, p->payload->type);
256 	flow_1(&f, p->isakmp_version);
257 	flow_1(&f, p->exchange_type);
258 	flow_1(&f, p->flags);
259 	flow_4(&f, p->message_id);
260 	lpos = flow_reserve(&f, 4);
261 	flow_payload(&f, p->payload);
262 	if (p->flags & ISAKMP_FLAG_E) {
263 		assert(blksz != 0);
264 		sz = (f.end - f.base) - ISAKMP_PAYLOAD_O;
265 		padding = blksz - (sz % blksz);
266 		if (padding == blksz)
267 			padding = 0;
268 		DEBUG(3, printf("size = %ld, blksz = %ld, padding = %ld\n",
269 				(long)sz, (long)blksz, (long)padding));
270 		flow_reserve(&f, padding);
271 	}
272 	f.base[lpos] = (f.end - f.base) >> 24;
273 	f.base[lpos + 1] = (f.end - f.base) >> 16;
274 	f.base[lpos + 2] = (f.end - f.base) >> 8;
275 	f.base[lpos + 3] = (f.end - f.base);
276 	*result = f.base;
277 	*size = f.end - f.base;
278 	 /*DUMP*/ if (opt_debug >= 3) {
279 		printf("\n sending: ========================>\n");
280 		free_isakmp_packet(parse_isakmp_packet(f.base, f.end - f.base, NULL));
281 	}
282 }
283 
new_isakmp_attribute(uint16_t type,struct isakmp_attribute * next)284 struct isakmp_attribute *new_isakmp_attribute(uint16_t type, struct isakmp_attribute *next)
285 {
286 	struct isakmp_attribute *r = xallocc(sizeof(struct isakmp_attribute));
287 	r->type = type;
288 	r->next = next;
289 	return r;
290 }
291 
new_isakmp_attribute_16(uint16_t type,uint16_t data,struct isakmp_attribute * next)292 struct isakmp_attribute *new_isakmp_attribute_16(uint16_t type, uint16_t data,
293 	struct isakmp_attribute *next)
294 {
295 	struct isakmp_attribute *r = xallocc(sizeof(struct isakmp_attribute));
296 	r->next = next;
297 	r->type = type;
298 	r->af = isakmp_attr_16;
299 	r->u.attr_16 = data;
300 	return r;
301 }
302 
new_isakmp_packet(void)303 struct isakmp_packet *new_isakmp_packet(void)
304 {
305 	return xallocc(sizeof(struct isakmp_packet));
306 }
307 
new_isakmp_payload(uint8_t type)308 struct isakmp_payload *new_isakmp_payload(uint8_t type)
309 {
310 	struct isakmp_payload *result = xallocc(sizeof(struct isakmp_payload));
311 	result->type = type;
312 	return result;
313 }
314 
new_isakmp_data_payload(uint8_t type,const void * data,size_t data_length)315 struct isakmp_payload *new_isakmp_data_payload(uint8_t type, const void *data, size_t data_length)
316 {
317 	struct isakmp_payload *result = xallocc(sizeof(struct isakmp_payload));
318 
319 	if (type != ISAKMP_PAYLOAD_KE && type != ISAKMP_PAYLOAD_HASH
320 		&& type != ISAKMP_PAYLOAD_SIG && type != ISAKMP_PAYLOAD_NONCE
321 		&& type != ISAKMP_PAYLOAD_VID && type != ISAKMP_PAYLOAD_NAT_D
322 		&& type != ISAKMP_PAYLOAD_NAT_D_OLD)
323 		abort();
324 	if (data_length >= 16384)
325 		abort();
326 
327 	result->type = type;
328 	result->u.ke.length = data_length;
329 	result->u.ke.data = xallocc(data_length);
330 	memcpy(result->u.ke.data, data, data_length);
331 	return result;
332 }
333 
free_isakmp_payload(struct isakmp_payload * p)334 static void free_isakmp_payload(struct isakmp_payload *p)
335 {
336 	struct isakmp_payload *nxt;
337 
338 	if (p == NULL)
339 		return;
340 
341 	switch (p->type) {
342 	case ISAKMP_PAYLOAD_SA:
343 		free_isakmp_payload(p->u.sa.proposals);
344 		break;
345 	case ISAKMP_PAYLOAD_P:
346 		free(p->u.p.spi);
347 		free_isakmp_payload(p->u.p.transforms);
348 		break;
349 	case ISAKMP_PAYLOAD_T:
350 		{
351 			struct isakmp_attribute *att, *natt;
352 			for (att = p->u.t.attributes; att; att = natt) {
353 				natt = att->next;
354 				if (att->af == isakmp_attr_lots)
355 					free(att->u.lots.data);
356 				free(att);
357 			}
358 		}
359 		break;
360 	case ISAKMP_PAYLOAD_KE:
361 	case ISAKMP_PAYLOAD_HASH:
362 	case ISAKMP_PAYLOAD_SIG:
363 	case ISAKMP_PAYLOAD_NONCE:
364 	case ISAKMP_PAYLOAD_VID:
365 	case ISAKMP_PAYLOAD_NAT_D:
366 	case ISAKMP_PAYLOAD_NAT_D_OLD:
367 		free(p->u.ke.data);
368 		break;
369 	case ISAKMP_PAYLOAD_ID:
370 		free(p->u.id.data);
371 		break;
372 	case ISAKMP_PAYLOAD_CERT:
373 	case ISAKMP_PAYLOAD_CR:
374 		free(p->u.cert.data);
375 		break;
376 	case ISAKMP_PAYLOAD_N:
377 		free(p->u.n.spi);
378 		free(p->u.n.data);
379 		break;
380 	case ISAKMP_PAYLOAD_D:
381 		if (p->u.d.spi) {
382 			int i;
383 			for (i = 0; i < p->u.d.num_spi; i++)
384 				free(p->u.d.spi[i]);
385 			free(p->u.d.spi);
386 		}
387 		break;
388 	case ISAKMP_PAYLOAD_MODECFG_ATTR:
389 		{
390 			struct isakmp_attribute *att, *natt;
391 			for (att = p->u.modecfg.attributes; att; att = natt) {
392 				natt = att->next;
393 				if (att->af == isakmp_attr_lots)
394 					free(att->u.lots.data);
395 				if (att->af == isakmp_attr_acl)
396 					free(att->u.acl.acl_ent);
397 				free(att);
398 			}
399 		}
400 		break;
401 	default:
402 		abort();
403 
404 	}
405 	nxt = p->next;
406 	free(p);
407 	free_isakmp_payload(nxt);
408 }
409 
free_isakmp_packet(struct isakmp_packet * p)410 void free_isakmp_packet(struct isakmp_packet *p)
411 {
412 	if (p == NULL)
413 		return;
414 	free_isakmp_payload(p->payload);
415 	free(p);
416 }
417 
transform_id_to_debug_strings(enum isakmp_ipsec_proto_enum decode_proto)418 static const struct debug_strings *transform_id_to_debug_strings(enum isakmp_ipsec_proto_enum decode_proto)
419 {
420 	switch (decode_proto) {
421 	case ISAKMP_IPSEC_PROTO_ISAKMP:
422 		return isakmp_ipsec_key_enum_array;
423 	case ISAKMP_IPSEC_PROTO_IPSEC_AH:
424 		return isakmp_ipsec_ah_enum_array;
425 	case ISAKMP_IPSEC_PROTO_IPSEC_ESP:
426 		return isakmp_ipsec_esp_enum_array;
427 	case ISAKMP_IPSEC_PROTO_IPCOMP:
428 		return isakmp_ipsec_ipcomp_enum_array;
429 	default:
430 		return NULL;
431 	}
432 }
433 
attr_type_to_debug_strings(enum isakmp_ipsec_proto_enum decode_proto)434 static const struct debug_strings *attr_type_to_debug_strings(enum isakmp_ipsec_proto_enum decode_proto)
435 {
436 	switch (decode_proto) {
437 	case ISAKMP_IPSEC_PROTO_ISAKMP:
438 		return ike_attr_enum_array;
439 	case ISAKMP_IPSEC_PROTO_IPSEC_AH:
440 	case ISAKMP_IPSEC_PROTO_IPSEC_ESP:
441 		return isakmp_ipsec_attr_enum_array;
442 	case ISAKMP_IPSEC_PROTO_MODECFG:
443 		return isakmp_modecfg_attrib_enum_array;
444 	default:
445 		return NULL;
446 	}
447 }
448 
attr_val_to_debug_strings(enum isakmp_ipsec_proto_enum decode_proto,uint16_t type)449 static const struct debug_strings *attr_val_to_debug_strings(enum isakmp_ipsec_proto_enum decode_proto, uint16_t type)
450 {
451 	switch (decode_proto) {
452 	case ISAKMP_IPSEC_PROTO_ISAKMP:
453 		switch (type) {
454 		case IKE_ATTRIB_ENC:         return ike_enc_enum_array;
455 		case IKE_ATTRIB_HASH:        return ike_hash_enum_array;
456 		case IKE_ATTRIB_AUTH_METHOD: return ike_auth_enum_array;
457 		case IKE_ATTRIB_GROUP_DESC:  return ike_group_enum_array;
458 		case IKE_ATTRIB_GROUP_TYPE:  return ike_group_type_enum_array;
459 		case IKE_ATTRIB_LIFE_TYPE:   return ike_life_enum_array;
460 		default:  return NULL;
461 		}
462 	case ISAKMP_IPSEC_PROTO_IPSEC_AH:
463 	case ISAKMP_IPSEC_PROTO_IPSEC_ESP:
464 		switch (type) {
465 		case ISAKMP_IPSEC_ATTRIB_SA_LIFE_TYPE: return ipsec_life_enum_array;
466 		case ISAKMP_IPSEC_ATTRIB_ENCAP_MODE:   return ipsec_encap_enum_array;
467 		case ISAKMP_IPSEC_ATTRIB_AUTH_ALG:     return ipsec_auth_enum_array;
468 		default:  return NULL;
469 		}
470 	default:
471 		return NULL;
472 	}
473 }
474 
475 #define fetch4()  					\
476   (data += 4, data_len -= 4,				\
477    (uint32_t)(data[-4]) << 24 | (uint32_t)(data[-3]) << 16	\
478    | (uint32_t)(data[-2]) << 8 | data[-1])
479 #define fetch2()				\
480   (data += 2, data_len -= 2,			\
481    (uint16_t)(data[-2]) << 8 | data[-1])
482 #define fetch1() (data_len--, *data++)
483 #define fetchn(d,n)  \
484   (memcpy ((d), data, (n)), data += (n), data_len -= (n))
485 
parse_isakmp_attributes(const uint8_t ** data_p,size_t data_len,int * reject,enum isakmp_ipsec_proto_enum decode_proto)486 static struct isakmp_attribute *parse_isakmp_attributes(const uint8_t ** data_p,
487 	size_t data_len, int * reject, enum isakmp_ipsec_proto_enum decode_proto)
488 {
489 	const uint8_t *data = *data_p;
490 	struct isakmp_attribute *r;
491 	uint16_t type, length;
492 	int i;
493 
494 	if (data_len < 4)
495 		return NULL;
496 
497 	r = new_isakmp_attribute(0, NULL);
498 	type = fetch2();
499 	length = fetch2();
500 	if (type & 0x8000) {
501 		r->type = type & ~0x8000;
502 		hex_dump("t.attributes.type", &r->type, DUMP_UINT16, attr_type_to_debug_strings(decode_proto));
503 		r->af = isakmp_attr_16;
504 		r->u.attr_16 = length;
505 		if ((ISAKMP_XAUTH_06_ATTRIB_TYPE <= r->type)
506 			&& (r->type <= ISAKMP_XAUTH_06_ATTRIB_ANSWER)
507 			&& (r->type != ISAKMP_XAUTH_06_ATTRIB_STATUS)
508 			&& (length > 0)
509 			&& (opt_debug < 99))
510 			DEBUG(3, printf("(not dumping xauth data)\n"));
511 		else
512 			hex_dump("t.attributes.u.attr_16", &r->u.attr_16, DUMP_UINT16,
513 				attr_val_to_debug_strings(decode_proto, r->type));
514 	} else {
515 		r->type = type;
516 		hex_dump("t.attributes.type", &r->type, DUMP_UINT16, attr_type_to_debug_strings(decode_proto));
517 		r->af = isakmp_attr_lots;
518 		r->u.lots.length = length;
519 		if ((ISAKMP_XAUTH_06_ATTRIB_TYPE <= r->type)
520 			&& (r->type <= ISAKMP_XAUTH_06_ATTRIB_ANSWER)
521 			&& (r->type != ISAKMP_XAUTH_06_ATTRIB_STATUS)
522 			&& (length > 0)
523 			&& (opt_debug < 99))
524 			DEBUG(3, printf("(not dumping xauth data length)\n"));
525 		else
526 			hex_dump("t.attributes.u.lots.length", &r->u.lots.length, DUMP_UINT16, NULL);
527 		if (data_len < length) {
528 			*reject = ISAKMP_N_PAYLOAD_MALFORMED;
529 			return r;
530 		}
531 		if (r->type == ISAKMP_MODECFG_ATTRIB_CISCO_SPLIT_INC) {
532 			r->af = isakmp_attr_acl;
533 			r->u.acl.count = length / (4+4+2+2+2);
534 			if (r->u.acl.count * (4+4+2+2+2) != length) {
535 				*reject = ISAKMP_N_PAYLOAD_MALFORMED;
536 				return r;
537 			}
538 			r->u.acl.acl_ent = xallocc(r->u.acl.count * sizeof(struct acl_ent_s));
539 
540 			for (i = 0; i < r->u.acl.count; i++) {
541 				fetchn(&r->u.acl.acl_ent[i].addr.s_addr, 4);
542 				fetchn(&r->u.acl.acl_ent[i].mask.s_addr, 4);
543 				r->u.acl.acl_ent[i].protocol = fetch2();
544 				r->u.acl.acl_ent[i].sport = fetch2();
545 				r->u.acl.acl_ent[i].dport = fetch2();
546 				hex_dump("t.attributes.u.acl.addr", &r->u.acl.acl_ent[i].addr.s_addr, 4, NULL);
547 				hex_dump("t.attributes.u.acl.mask", &r->u.acl.acl_ent[i].mask.s_addr, 4, NULL);
548 				hex_dump("t.attributes.u.acl.protocol", &r->u.acl.acl_ent[i].protocol, DUMP_UINT16, NULL);
549 				hex_dump("t.attributes.u.acl.sport", &r->u.acl.acl_ent[i].sport, DUMP_UINT16, NULL);
550 				hex_dump("t.attributes.u.acl.dport", &r->u.acl.acl_ent[i].dport, DUMP_UINT16, NULL);
551 			}
552 		} else {
553 			r->u.lots.data = xallocc(length);
554 			fetchn(r->u.lots.data, length);
555 			if ((ISAKMP_XAUTH_06_ATTRIB_TYPE <= type)
556 				&& (type <= ISAKMP_XAUTH_06_ATTRIB_ANSWER)
557 				&& (r->type != ISAKMP_XAUTH_06_ATTRIB_STATUS)
558 				&& (length > 0)
559 				&& (opt_debug < 99))
560 				DEBUG(3, printf("(not dumping xauth data)\n"));
561 			else
562 				hex_dump("t.attributes.u.lots.data", r->u.lots.data, r->u.lots.length, NULL);
563 		}
564 	}
565 	r->next = parse_isakmp_attributes(&data, data_len, reject, decode_proto);
566 	*data_p = data;
567 	return r;
568 }
569 
parse_isakmp_payload(uint8_t type,const uint8_t ** data_p,size_t * data_len_p,int * reject,enum isakmp_ipsec_proto_enum decode_proto)570 static struct isakmp_payload *parse_isakmp_payload(uint8_t type,
571 	const uint8_t ** data_p, size_t * data_len_p, int * reject, enum isakmp_ipsec_proto_enum decode_proto)
572 {
573 	const uint8_t *data = *data_p, *tmpdata;
574 	size_t data_len = *data_len_p;
575 	struct isakmp_payload *r;
576 	uint8_t next_type;
577 	size_t length, olength;
578 
579 	static const uint16_t min_payload_len[ISAKMP_PAYLOAD_MODECFG_ATTR + 1] = {
580 		4, 12, 8, 8, 4, 8, 5, 5, 4, 4, 4, 12, 12, 4, 8
581 	};
582 
583 	DEBUG(3, printf("\n"));
584 	hex_dump("PARSING PAYLOAD type", &type, DUMP_UINT8, isakmp_payload_enum_array);
585 	if (type == 0)
586 		return NULL;
587 	if (type <= ISAKMP_PAYLOAD_MODECFG_ATTR) {
588 		if (data_len < min_payload_len[type]) {
589 			*reject = ISAKMP_N_PAYLOAD_MALFORMED;
590 			return NULL;
591 		}
592 	} else if (data_len < 4) {
593 		*reject = ISAKMP_N_PAYLOAD_MALFORMED;
594 		return NULL;
595 	}
596 
597 	r = new_isakmp_payload(type);
598 	next_type = fetch1();
599 	hex_dump("next_type", &next_type, DUMP_UINT8, isakmp_payload_enum_array);
600 	if (fetch1() != 0) {
601 		*reject = ISAKMP_N_PAYLOAD_MALFORMED;
602 		return r;
603 	}
604 	length = fetch2();
605 	hex_dump("length", &length, DUMP_UINT16, NULL);
606 	if (length > data_len + 4
607 		|| ((type <= ISAKMP_PAYLOAD_MODECFG_ATTR)&&(length < min_payload_len[type]))
608 		|| (length < 4)) {
609 		*reject = ISAKMP_N_PAYLOAD_MALFORMED;
610 		return r;
611 	}
612 	olength = length;
613 	switch (type) {
614 	case ISAKMP_PAYLOAD_SA:
615 		r->u.sa.doi = fetch4();
616 		hex_dump("sa.doi", &r->u.sa.doi, DUMP_UINT32, isakmp_doi_enum_array);
617 		if (r->u.sa.doi != ISAKMP_DOI_IPSEC) {
618 			*reject = ISAKMP_N_DOI_NOT_SUPPORTED;
619 			return r;
620 		}
621 		r->u.sa.situation = fetch4();
622 		hex_dump("sa.situation", &r->u.sa.situation, DUMP_UINT32, isakmp_ipsec_sit_enum_array);
623 		if (r->u.sa.situation != ISAKMP_IPSEC_SIT_IDENTITY_ONLY) {
624 			*reject = ISAKMP_N_SITUATION_NOT_SUPPORTED;
625 			return r;
626 		}
627 		*reject = 0;
628 		length -= 12;
629 		r->u.sa.proposals = parse_isakmp_payload(ISAKMP_PAYLOAD_P, &data, &length, reject, decode_proto);
630 		if (*reject != 0)
631 			return r;
632 		/* Allow trailing garbage at end of payload.  */
633 		data_len -= olength - 12;
634 		break;
635 
636 	case ISAKMP_PAYLOAD_P:
637 		if (next_type != ISAKMP_PAYLOAD_P && next_type != 0) {
638 			*reject = ISAKMP_N_INVALID_PAYLOAD_TYPE;
639 			return r;
640 		}
641 		{
642 			uint8_t num_xform;
643 			struct isakmp_payload *xform;
644 
645 			r->u.p.number = fetch1();
646 			hex_dump("p.number", &r->u.p.number, DUMP_UINT8, NULL);
647 			r->u.p.prot_id = fetch1();
648 			hex_dump("p.prot_id", &r->u.p.prot_id, DUMP_UINT8, isakmp_ipsec_proto_enum_array);
649 			r->u.p.spi_size = fetch1();
650 			hex_dump("p.spi_size", &r->u.p.spi_size, DUMP_UINT8, NULL);
651 			num_xform = fetch1();
652 			hex_dump("length", &num_xform, DUMP_UINT8, NULL);
653 
654 			if (data_len < r->u.p.spi_size) {
655 				*reject = ISAKMP_N_PAYLOAD_MALFORMED;
656 				return r;
657 			}
658 			r->u.p.spi = xallocc(r->u.p.spi_size);
659 			fetchn(r->u.p.spi, r->u.p.spi_size);
660 			hex_dump("p.spi", r->u.p.spi, r->u.p.spi_size, NULL);
661 			length -= 8 + r->u.p.spi_size;
662 			r->u.p.transforms = parse_isakmp_payload(ISAKMP_PAYLOAD_T,
663 				&data, &length, reject, r->u.p.prot_id);
664 			for (xform = r->u.p.transforms; xform; xform = xform->next)
665 				if (num_xform-- == 0)
666 					break;
667 			if (num_xform != 0) {
668 				*reject = ISAKMP_N_BAD_PROPOSAL_SYNTAX;
669 				return r;
670 			}
671 
672 			/* Allow trailing garbage at end of payload.  */
673 			data_len -= olength - 8 - r->u.p.spi_size;
674 		}
675 		break;
676 
677 	case ISAKMP_PAYLOAD_T:
678 		if (next_type != ISAKMP_PAYLOAD_T && next_type != 0) {
679 			*reject = ISAKMP_N_INVALID_PAYLOAD_TYPE;
680 			return r;
681 		}
682 		r->u.t.number = fetch1();
683 		hex_dump("t.number", &r->u.t.number, DUMP_UINT8, NULL);
684 		r->u.t.id = fetch1();
685 		hex_dump("t.id", &r->u.t.id, DUMP_UINT8, transform_id_to_debug_strings(decode_proto));
686 		if (fetch2() != 0) {
687 			*reject = ISAKMP_N_BAD_PROPOSAL_SYNTAX;
688 			return r;
689 		}
690 		length -= 8;
691 		r->u.t.attributes = parse_isakmp_attributes(&data, length, reject, decode_proto);
692 		data_len -= olength - 8;
693 		break;
694 
695 	case ISAKMP_PAYLOAD_KE:
696 	case ISAKMP_PAYLOAD_HASH:
697 	case ISAKMP_PAYLOAD_SIG:
698 	case ISAKMP_PAYLOAD_NONCE:
699 	case ISAKMP_PAYLOAD_VID:
700 	case ISAKMP_PAYLOAD_NAT_D:
701 	case ISAKMP_PAYLOAD_NAT_D_OLD:
702 		r->u.ke.length = length - 4;
703 		r->u.ke.data = xallocc(r->u.ke.length);
704 		fetchn(r->u.ke.data, r->u.ke.length);
705 		hex_dump("ke.data", r->u.ke.data, r->u.ke.length, NULL);
706 		if (type == ISAKMP_PAYLOAD_VID)
707 			print_vid(r->u.ke.data, r->u.ke.length);
708 		break;
709 	case ISAKMP_PAYLOAD_ID:
710 		r->u.id.type = fetch1();
711 		hex_dump("id.type", &r->u.id.type, DUMP_UINT8, isakmp_ipsec_id_enum_array);
712 		r->u.id.protocol = fetch1();
713 		hex_dump("id.protocol", &r->u.id.protocol, DUMP_UINT8, NULL); /* IP protocol nr */
714 		r->u.id.port = fetch2();
715 		hex_dump("id.port", &r->u.id.port, DUMP_UINT16, NULL);
716 		r->u.id.length = length - 8;
717 		r->u.id.data = xallocc(r->u.id.length);
718 		fetchn(r->u.id.data, r->u.id.length);
719 		hex_dump("id.data", r->u.id.data, r->u.id.length, NULL);
720 		break;
721 	case ISAKMP_PAYLOAD_CERT:
722 	case ISAKMP_PAYLOAD_CR:
723 		r->u.cert.encoding = fetch1();
724 		hex_dump("cert.encoding", &r->u.cert.encoding, DUMP_UINT8, NULL);
725 		r->u.cert.length = length - 5;
726 		r->u.cert.data = xallocc(r->u.cert.length);
727 		fetchn(r->u.cert.data, r->u.cert.length);
728 		hex_dump("cert.data", r->u.cert.data, r->u.cert.length, NULL);
729 		break;
730 	case ISAKMP_PAYLOAD_N:
731 		r->u.n.doi = fetch4();
732 		hex_dump("n.doi", &r->u.n.doi, DUMP_UINT32, isakmp_doi_enum_array);
733 		r->u.n.protocol = fetch1();
734 		hex_dump("n.protocol", &r->u.n.protocol, DUMP_UINT8, isakmp_ipsec_proto_enum_array);
735 		r->u.n.spi_length = fetch1();
736 		hex_dump("n.spi_length", &r->u.n.spi_length, DUMP_UINT8, NULL);
737 		r->u.n.type = fetch2();
738 		hex_dump("n.type", &r->u.n.type, DUMP_UINT16, isakmp_notify_enum_array);
739 		if (r->u.n.spi_length + 12u > length) {
740 			*reject = ISAKMP_N_PAYLOAD_MALFORMED;
741 			return r;
742 		}
743 		r->u.n.spi = xallocc(r->u.n.spi_length);
744 		fetchn(r->u.n.spi, r->u.n.spi_length);
745 		hex_dump("n.spi", r->u.n.spi, r->u.n.spi_length, NULL);
746 		r->u.n.data_length = length - 12 - r->u.n.spi_length;
747 		r->u.n.data = xallocc(r->u.n.data_length);
748 		fetchn(r->u.n.data, r->u.n.data_length);
749 		hex_dump("n.data", r->u.n.data, r->u.n.data_length, NULL);
750 		if ((r->u.n.doi == ISAKMP_DOI_IPSEC)&&(r->u.n.type == ISAKMP_N_IPSEC_RESPONDER_LIFETIME)) {
751 			tmpdata = r->u.n.data;
752 			r->u.n.attributes = parse_isakmp_attributes(&tmpdata, r->u.n.data_length, reject,
753 				r->u.n.protocol);
754 		}
755 		break;
756 	case ISAKMP_PAYLOAD_D:
757 		r->u.d.doi = fetch4();
758 		hex_dump("d.doi", &r->u.d.doi, DUMP_UINT32, isakmp_doi_enum_array);
759 		r->u.d.protocol = fetch1();
760 		hex_dump("d.protocol", &r->u.d.protocol, DUMP_UINT8, isakmp_ipsec_proto_enum_array);
761 		r->u.d.spi_length = fetch1();
762 		hex_dump("d.spi_length", &r->u.d.spi_length, DUMP_UINT8, NULL);
763 		r->u.d.num_spi = fetch2();
764 		hex_dump("d.num_spi", &r->u.d.num_spi, DUMP_UINT16, NULL);
765 		if (r->u.d.num_spi * r->u.d.spi_length + 12u != length) {
766 			*reject = ISAKMP_N_PAYLOAD_MALFORMED;
767 			return r;
768 		}
769 		r->u.d.spi = xallocc(sizeof(uint8_t *) * r->u.d.num_spi);
770 		{
771 			int i;
772 			for (i = 0; i < r->u.d.num_spi; i++) {
773 				r->u.d.spi[i] = xallocc(r->u.d.spi_length);
774 				fetchn(r->u.d.spi[i], r->u.d.spi_length);
775 				hex_dump("d.spi", r->u.d.spi[i], r->u.d.spi_length, NULL);
776 			}
777 		}
778 		break;
779 	case ISAKMP_PAYLOAD_MODECFG_ATTR:
780 		r->u.modecfg.type = fetch1();
781 		hex_dump("modecfg.type", &r->u.modecfg.type, DUMP_UINT8, isakmp_modecfg_cfg_enum_array);
782 		if (fetch1() != 0) {
783 			*reject = ISAKMP_N_PAYLOAD_MALFORMED;
784 			return r;
785 		}
786 		r->u.modecfg.id = fetch2();
787 		hex_dump("modecfg.id", &r->u.modecfg.id, DUMP_UINT16, NULL);
788 		length -= 8;
789 		r->u.modecfg.attributes = parse_isakmp_attributes(&data, length, reject,
790 			ISAKMP_IPSEC_PROTO_MODECFG); /* this "proto" is a hack for simplicity */
791 		data_len -= olength - 8;
792 		break;
793 
794 	default:
795 		r->u.ke.length = length - 4;
796 		r->u.ke.data = xallocc(r->u.ke.length);
797 		fetchn(r->u.ke.data, r->u.ke.length);
798 		hex_dump("UNKNOWN.data", r->u.ke.data, r->u.ke.length, NULL);
799 		break;
800 	}
801 	*data_p = data;
802 	*data_len_p = data_len;
803 	hex_dump("DONE PARSING PAYLOAD type", &type, DUMP_UINT8, isakmp_payload_enum_array);
804 	r->next = parse_isakmp_payload(next_type, data_p, data_len_p, reject, decode_proto);
805 	return r;
806 }
807 
parse_isakmp_packet(const uint8_t * data,size_t data_len,int * reject)808 struct isakmp_packet *parse_isakmp_packet(const uint8_t * data, size_t data_len, int * reject)
809 {
810 	int reason = 0;
811 	uint8_t payload;
812 	struct isakmp_packet *r = new_isakmp_packet();
813 	size_t o_data_len = data_len;
814 	size_t isakmp_data_len;
815 
816 	if (data_len < ISAKMP_PAYLOAD_O) {
817 		DEBUG(2, printf("packet to short: len = %lld < min = %lld\n", (long long) data_len, (long long)ISAKMP_PAYLOAD_O));
818 		reason = ISAKMP_N_UNEQUAL_PAYLOAD_LENGTHS;
819 		goto error;
820 	}
821 
822 	DEBUG(3, printf("BEGIN_PARSE\n"));
823 	DEBUG(3, printf("Recieved Packet Len: %d\n", data_len));
824 	fetchn(r->i_cookie, ISAKMP_COOKIE_LENGTH);
825 	hex_dump("i_cookie", r->i_cookie, ISAKMP_COOKIE_LENGTH, NULL);
826 	fetchn(r->r_cookie, ISAKMP_COOKIE_LENGTH);
827 	hex_dump("r_cookie", r->r_cookie, ISAKMP_COOKIE_LENGTH, NULL);
828 	payload = fetch1();
829 	hex_dump("payload", &payload, DUMP_UINT8, isakmp_payload_enum_array);
830 
831 	r->isakmp_version = fetch1();
832 	hex_dump("isakmp_version", &r->isakmp_version, DUMP_UINT8, NULL);
833 	if (r->isakmp_version > ISAKMP_VERSION) {
834 		if ((r->isakmp_version & 0xF0) >= (ISAKMP_VERSION & 0xF0))
835 			reason = ISAKMP_N_INVALID_MAJOR_VERSION;
836 		else
837 			reason = ISAKMP_N_INVALID_MINOR_VERSION;
838 		goto error;
839 	}
840 
841 	r->exchange_type = fetch1();
842 	hex_dump("exchange_type", &r->exchange_type, DUMP_UINT8, isakmp_exchange_enum_array);
843 	r->flags = fetch1();
844 	hex_dump("flags", &r->flags, DUMP_UINT8, NULL);
845 	r->message_id = fetch4();
846 	hex_dump("message_id", &r->message_id, sizeof(r->message_id), NULL);
847 
848 	isakmp_data_len = fetch4();
849 	hex_dump("len", &isakmp_data_len, DUMP_UINT32, NULL);
850 	if (o_data_len != isakmp_data_len) {
851 		DEBUG(2, printf("isakmp length does not match packet length: isakmp = %lld != datalen = %lld\n",
852 			(long long)isakmp_data_len, (long long)o_data_len));
853 		reason = ISAKMP_N_UNEQUAL_PAYLOAD_LENGTHS;
854 		goto error;
855 	}
856 
857 	r->payload = parse_isakmp_payload(payload, &data, &data_len, &reason, 0);
858 	if (reason != 0)
859 		goto error;
860 
861 	DEBUG(3, printf("PARSE_OK\n"));
862 	return r;
863 
864       error:
865 	free_isakmp_packet(r);
866 	if (reject)
867 		*reject = reason;
868 	return NULL;
869 }
870 
test_pack_unpack(void)871 void test_pack_unpack(void)
872 {
873 	static const uint8_t pack[] = {
874 		0x7f, 0xba, 0x51, 0x29, 0x11, 0x9e, 0x76, 0xf7, 0x9a, 0x71, 0xee, 0x70,
875 		0xaa, 0x82, 0xb9, 0x7f, 0x01, 0x10, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
876 		0x00, 0x00, 0x01, 0x4c, 0x04, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x01,
877 		0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x01, 0x01, 0x00, 0x01,
878 		0x00, 0x00, 0x00, 0x18, 0x00, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x05,
879 		0x80, 0x02, 0x00, 0x01, 0x80, 0x04, 0x00, 0x02, 0x80, 0x03, 0x00, 0x01,
880 		0x0a, 0x00, 0x00, 0x84, 0x1b, 0x1d, 0x4b, 0x29, 0x0e, 0x29, 0xb9, 0x6f,
881 		0x18, 0x34, 0xd1, 0x2d, 0xba, 0x92, 0x7c, 0x53, 0x35, 0x76, 0x0e, 0x3b,
882 		0x25, 0x92, 0x4f, 0x7c, 0x1e, 0x31, 0x41, 0x8c, 0xb9, 0xe3, 0xda, 0xf7,
883 		0x53, 0xd3, 0x22, 0x8e, 0xff, 0xeb, 0xed, 0x5b, 0x95, 0x56, 0x8d, 0xba,
884 		0xa8, 0xe3, 0x2a, 0x9b, 0xb4, 0x04, 0x5c, 0x90, 0xf0, 0xfe, 0x92, 0xc8,
885 		0x57, 0xa2, 0xc6, 0x0c, 0x85, 0xbb, 0x56, 0xe8, 0x1c, 0xa7, 0x2c, 0x57,
886 		0x04, 0xb6, 0xe0, 0x43, 0x82, 0xe1, 0x9f, 0x0b, 0xa6, 0x8b, 0xce, 0x7f,
887 		0x9b, 0x75, 0xbb, 0xd3, 0xff, 0x0e, 0x89, 0x19, 0xaf, 0xc6, 0x2e, 0xf6,
888 		0x92, 0x06, 0x46, 0x4f, 0xc7, 0x97, 0x22, 0xf4, 0xa6, 0xf9, 0x26, 0x34,
889 		0x04, 0x33, 0x89, 0x34, 0xa9, 0x2f, 0x81, 0x92, 0xd3, 0x21, 0x4f, 0x45,
890 		0xbe, 0x38, 0x12, 0x26, 0xec, 0x87, 0x45, 0xdd, 0x10, 0x1c, 0xd6, 0x16,
891 		0x05, 0x00, 0x00, 0x18, 0x77, 0xdf, 0x37, 0x3c, 0x03, 0x02, 0xe2, 0xc8,
892 		0xe1, 0x2f, 0x92, 0xf0, 0x2e, 0xa2, 0xa6, 0x00, 0x17, 0x8f, 0xdf, 0xb4,
893 		0x08, 0x00, 0x00, 0x0c, 0x01, 0x11, 0x01, 0xf4, 0xcd, 0xb4, 0x53, 0x6d,
894 		0x0d, 0x00, 0x00, 0x14, 0x07, 0x47, 0x8d, 0xa7, 0x0b, 0xd6, 0xd1, 0x66,
895 		0x7a, 0xaf, 0x2e, 0x61, 0x2a, 0x91, 0x80, 0x94, 0x0d, 0x00, 0x00, 0x14,
896 		0x12, 0xf5, 0xf2, 0x8c, 0x45, 0x71, 0x68, 0xa9, 0x70, 0x2d, 0x9f, 0xe2,
897 		0x74, 0xcc, 0x01, 0x00, 0x0d, 0x00, 0x00, 0x0c, 0x09, 0x00, 0x26, 0x89,
898 		0xdf, 0xd6, 0xb7, 0x12, 0x0d, 0x00, 0x00, 0x14, 0xaf, 0xca, 0xd7, 0x13,
899 		0x68, 0xa1, 0xf1, 0xc9, 0x6b, 0x86, 0x96, 0xfc, 0x77, 0x57, 0x01, 0x00,
900 		0x00, 0x00, 0x00, 0x14, 0x1f, 0x07, 0xf7, 0x0e, 0xaa, 0x65, 0x14, 0xd3,
901 		0xb0, 0xfa, 0x96, 0x54, 0x2a, 0x50, 0x03, 0x05
902 	};
903 	uint8_t *unpack;
904 	size_t unpack_len;
905 	struct isakmp_packet *p;
906 	int reject;
907 
908 	p = parse_isakmp_packet(pack, sizeof(pack), &reject);
909 	flatten_isakmp_packet(p, &unpack, &unpack_len, 8);
910 	if (unpack_len != sizeof(pack)
911 		|| memcmp(unpack, pack, sizeof(pack)) != 0)
912 		abort();
913 	free(unpack);
914 	free_isakmp_packet(p);
915 }
916