xref: /openbsd/sbin/isakmpd/isakmp_cfg.c (revision 2f1aa25b)
1 /* $OpenBSD: isakmp_cfg.c,v 1.41 2018/01/15 09:54:48 mpi Exp $	 */
2 
3 /*
4  * Copyright (c) 2001 Niklas Hallqvist.  All rights reserved.
5  * Copyright (c) 2002 H�kan Olsson.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 /*
29  * This code was written under funding by Gatespace
30  * (http://www.gatespace.com/).
31  */
32 
33 #include <sys/types.h>
34 #include <stdlib.h>
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
37 #include <string.h>
38 #include <bitstring.h>
39 
40 #include "attribute.h"
41 #include "conf.h"
42 #include "exchange.h"
43 #include "hash.h"
44 #include "ipsec.h"
45 #include "isakmp_fld.h"
46 #include "isakmp_num.h"
47 #include "log.h"
48 #include "message.h"
49 #include "prf.h"
50 #include "sa.h"
51 #include "transport.h"
52 #include "util.h"
53 
54 /*
55  * Validation script used to test messages for correct content of
56  * payloads depending on the exchange type.
57  */
58 int16_t script_transaction[] = {
59 	ISAKMP_PAYLOAD_ATTRIBUTE,	/* Initiator -> responder.  */
60 	EXCHANGE_SCRIPT_SWITCH,
61 	ISAKMP_PAYLOAD_ATTRIBUTE,	/* Responder -> initiator.  */
62 	EXCHANGE_SCRIPT_END
63 };
64 
65 static int      cfg_decode_attribute(u_int16_t, u_int8_t *, u_int16_t, void *);
66 static int	cfg_encode_attributes(struct isakmp_cfg_attr_head *, u_int32_t,
67     u_int32_t, char *, u_int8_t **, u_int16_t *);
68 static int      cfg_initiator_send_ATTR(struct message *);
69 static int      cfg_initiator_recv_ATTR(struct message *);
70 static int      cfg_responder_recv_ATTR(struct message *);
71 static int      cfg_responder_send_ATTR(struct message *);
72 
73 u_int8_t       *cfg_add_hash(struct message *);
74 int		cfg_finalize_hash(struct message *, u_int8_t *, u_int8_t *,
75     u_int16_t);
76 int             cfg_verify_hash(struct message *);
77 
78 /* Server: SET/ACK    Client; REQ/REPLY */
79 int (*isakmp_cfg_initiator[]) (struct message *) = {
80 	cfg_initiator_send_ATTR,
81 	cfg_initiator_recv_ATTR
82 };
83 
84 /* Server: REQ/REPLY  Client: SET/ACK */
85 int (*isakmp_cfg_responder[]) (struct message *) = {
86 	cfg_responder_recv_ATTR,
87 	cfg_responder_send_ATTR
88 };
89 
90 /*
91  * When we are "the server", this starts SET/ACK mode
92  * When we are "the client", this starts REQ/REPLY mode
93  */
94 static int
cfg_initiator_send_ATTR(struct message * msg)95 cfg_initiator_send_ATTR(struct message *msg)
96 {
97 	struct sa      *isakmp_sa = msg->isakmp_sa;
98 	struct ipsec_exch *ie = msg->exchange->data;
99 	u_int8_t       *hashp = 0, *attrp, *attr;
100 	size_t          attrlen, off;
101 	char           *id_string, *cfg_mode, *field;
102 	struct sockaddr *sa;
103 #define CFG_ATTR_BIT_MAX ISAKMP_CFG_ATTR_FUTURE_MIN	/* XXX */
104 	bitstr_t        bit_decl(attrbits, CFG_ATTR_BIT_MAX);
105 	u_int16_t       bit, length;
106 	u_int32_t       life;
107 
108 	if (msg->exchange->phase == 2) {
109 		hashp = cfg_add_hash(msg);
110 		if (!hashp)
111 			return -1;
112 	}
113 	/* We initiated this exchange, check isakmp_sa for other side.  */
114 	if (isakmp_sa->initiator)
115 		id_string = ipsec_id_string(isakmp_sa->id_r,
116 		    isakmp_sa->id_r_len);
117 	else
118 		id_string = ipsec_id_string(isakmp_sa->id_i,
119 		    isakmp_sa->id_i_len);
120 	if (!id_string) {
121 		log_print("cfg_initiator_send_ATTR: cannot parse ID");
122 		goto fail;
123 	}
124 	/* Check for attribute list to send to the other side */
125 	attrlen = 0;
126 	bit_nclear(attrbits, 0, CFG_ATTR_BIT_MAX - 1);
127 
128 	cfg_mode = conf_get_str(id_string, "Mode");
129 	if (!cfg_mode || strcmp(cfg_mode, "SET") == 0) {
130 		/* SET/ACK mode */
131 		ie->cfg_type = ISAKMP_CFG_SET;
132 
133 		LOG_DBG((LOG_NEGOTIATION, 10,
134 		    "cfg_initiator_send_ATTR: SET/ACK mode"));
135 
136 #define ATTRFIND(STR,ATTR4,LEN4,ATTR6,LEN6) do				\
137 	{								\
138 		if ((sa = conf_get_address (id_string, STR)) != NULL)	\
139 			switch (sa->sa_family) {			\
140 			case AF_INET:					\
141 				bit_set (attrbits, ATTR4);		\
142 				attrlen += ISAKMP_ATTR_SZ + LEN4;	\
143 				break;					\
144 			case AF_INET6:					\
145 				bit_set (attrbits, ATTR6);		\
146 				attrlen += ISAKMP_ATTR_SZ + LEN6;	\
147 				break;					\
148 			default:					\
149 				break;					\
150 			}						\
151 		free (sa);						\
152 	} while (0)
153 
154 		/*
155 		 * XXX We don't simultaneously support IPv4 and IPv6
156 		 * addresses.
157 		 */
158 		ATTRFIND("Address", ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS, 4,
159 		    ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS, 16);
160 		ATTRFIND("Netmask", ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK, 4,
161 		    ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK, 16);
162 		ATTRFIND("Nameserver", ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS, 4,
163 		    ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS, 16);
164 		ATTRFIND("WINS-server", ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS, 4,
165 		    ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS, 16);
166 		ATTRFIND("DHCP-server", ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP, 4,
167 		    ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP, 16);
168 #ifdef notyet
169 		ATTRFIND("Network", ISAKMP_CFG_ATTR_INTERNAL_IP4_SUBNET, 8,
170 		    ISAKMP_CFG_ATTR_INTERNAL_IP6_SUBNET, 17);
171 #endif
172 #undef ATTRFIND
173 
174 		if (conf_get_str(id_string, "Lifetime")) {
175 			bit_set(attrbits,
176 			    ISAKMP_CFG_ATTR_INTERNAL_ADDRESS_EXPIRY);
177 			attrlen += ISAKMP_ATTR_SZ + 4;
178 		}
179 	} else {
180 		struct conf_list *alist;
181 		struct conf_list_node *anode;
182 
183 		ie->cfg_type = ISAKMP_CFG_REQUEST;
184 
185 		LOG_DBG((LOG_NEGOTIATION, 10,
186 		    "cfg_initiator_send_ATTR: REQ/REPLY mode"));
187 
188 		alist = conf_get_list(id_string, "Attributes");
189 		if (alist) {
190 			for (anode = TAILQ_FIRST(&alist->fields); anode;
191 			    anode = TAILQ_NEXT(anode, link)) {
192 				if (strcasecmp(anode->field, "Address") == 0) {
193 					bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS);
194 					bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS);
195 					attrlen += ISAKMP_ATTR_SZ * 2;
196 				} else if (strcasecmp(anode->field, "Netmask")
197 				    == 0) {
198 					bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK);
199 					bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK);
200 					attrlen += ISAKMP_ATTR_SZ * 2;
201 				} else if (strcasecmp(anode->field,
202 				    "Nameserver") == 0) {
203 					bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS);
204 					bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS);
205 					attrlen += ISAKMP_ATTR_SZ * 2;
206 				} else if (strcasecmp(anode->field,
207 				    "WINS-server") == 0) {
208 					bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS);
209 					bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS);
210 					attrlen += ISAKMP_ATTR_SZ * 2;
211 				} else if (strcasecmp(anode->field,
212 				    "DHCP-server") == 0) {
213 					bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP);
214 					bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP);
215 					attrlen += ISAKMP_ATTR_SZ * 2;
216 				} else if (strcasecmp(anode->field,
217 				    "Lifetime") == 0) {
218 					bit_set(attrbits, ISAKMP_CFG_ATTR_INTERNAL_ADDRESS_EXPIRY);
219 					attrlen += ISAKMP_ATTR_SZ;
220 				} else {
221 					log_print("cfg_initiator_send_ATTR: "
222 					    "unknown attribute %.20s in "
223 					    "section [%s]", anode->field,
224 					    id_string);
225 				}
226 			}
227 
228 			conf_free_list(alist);
229 		}
230 	}
231 
232 	if (attrlen == 0) {
233 		/* No data found.  */
234 		log_print("cfg_initiator_send_ATTR: no IKECFG attributes "
235 		    "found for [%s]", id_string);
236 
237 		/*
238 		 * We can continue, but this indicates a configuration error
239 		 * that the user probably will want to correct.
240 		 */
241 		free(id_string);
242 		return 0;
243 	}
244 	attrlen += ISAKMP_ATTRIBUTE_SZ;
245 	attrp = calloc(1, attrlen);
246 	if (!attrp) {
247 		log_error("cfg_initiator_send_ATTR: calloc (1, %lu) failed",
248 		    (unsigned long)attrlen);
249 		goto fail;
250 	}
251 	if (message_add_payload(msg, ISAKMP_PAYLOAD_ATTRIBUTE, attrp, attrlen,
252 	    1)) {
253 		free(attrp);
254 		goto fail;
255 	}
256 	SET_ISAKMP_ATTRIBUTE_TYPE(attrp, ie->cfg_type);
257 	arc4random_buf((u_int8_t *) & ie->cfg_id, sizeof ie->cfg_id);
258 	SET_ISAKMP_ATTRIBUTE_ID(attrp, ie->cfg_id);
259 
260 	off = ISAKMP_ATTRIBUTE_SZ;
261 
262 	/*
263 	 * Use the bitstring built previously to collect the right
264 	 * parameters for attrp.
265 	 */
266 	for (bit = 0; bit < CFG_ATTR_BIT_MAX; bit++)
267 		if (bit_test(attrbits, bit)) {
268 			attr = attrp + off;
269 			SET_ISAKMP_ATTR_TYPE(attr, bit);
270 
271 			if (ie->cfg_type == ISAKMP_CFG_REQUEST) {
272 				off += ISAKMP_ATTR_SZ;
273 				continue;
274 			}
275 			/* All the other are similar, this is the odd one.  */
276 			if (bit == ISAKMP_CFG_ATTR_INTERNAL_ADDRESS_EXPIRY) {
277 				life = conf_get_num(id_string, "Lifetime",
278 				    1200);
279 				SET_ISAKMP_ATTR_LENGTH_VALUE(attr, 4);
280 				encode_32(attr + ISAKMP_ATTR_VALUE_OFF, life);
281 				off += ISAKMP_ATTR_SZ + 4;
282 				continue;
283 			}
284 			switch (bit) {
285 			case ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS:
286 			case ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK:
287 			case ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS:
288 			case ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP:
289 			case ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS:
290 				length = 4;
291 				break;
292 
293 			case ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS:
294 			case ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK:
295 			case ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS:
296 			case ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP:
297 			case ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS:
298 				length = 16;
299 				break;
300 
301 			default:
302 				length = 0;	/* Silence gcc.  */
303 			}
304 
305 			switch (bit) {
306 			case ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS:
307 			case ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS:
308 				field = "Address";
309 				break;
310 			case ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK:
311 			case ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK:
312 				field = "Netmask";
313 				break;
314 			case ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS:
315 			case ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS:
316 				field = "Nameserver";
317 				break;
318 			case ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP:
319 			case ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP:
320 				field = "DHCP-server";
321 				break;
322 			case ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS:
323 			case ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS:
324 				field = "WINS-server";
325 				break;
326 			default:
327 				field = 0;	/* Silence gcc.  */
328 			}
329 
330 			sa = conf_get_address(id_string, field);
331 
332 			SET_ISAKMP_ATTR_LENGTH_VALUE(attr, length);
333 			memcpy(attr + ISAKMP_ATTR_VALUE_OFF,
334 			    sockaddr_addrdata(sa), length);
335 
336 			free(sa);
337 
338 			off += ISAKMP_ATTR_SZ + length;
339 		}
340 	if (msg->exchange->phase == 2)
341 		if (cfg_finalize_hash(msg, hashp, attrp, attrlen))
342 			goto fail;
343 
344 	return 0;
345 
346 fail:
347 	free(id_string);
348 	return -1;
349 }
350 
351 /*
352  * As "the server", this ends SET/ACK.
353  * As "the client", this ends REQ/REPLY.
354  */
355 static int
cfg_initiator_recv_ATTR(struct message * msg)356 cfg_initiator_recv_ATTR(struct message *msg)
357 {
358 	struct payload *attrp = payload_first(msg, ISAKMP_PAYLOAD_ATTRIBUTE);
359 	struct ipsec_exch *ie = msg->exchange->data;
360 	struct sa      *isakmp_sa = msg->isakmp_sa;
361 	struct isakmp_cfg_attr *attr;
362 	struct sockaddr *sa;
363 	const char     *uk_addr = "<unknown>";
364 	char           *addr;
365 
366 	if (msg->exchange->phase == 2)
367 		if (cfg_verify_hash(msg))
368 			return -1;
369 
370 	/* Sanity.  */
371 	if (ie->cfg_id != GET_ISAKMP_ATTRIBUTE_ID(attrp->p)) {
372 		log_print("cfg_initiator_recv_ATTR: "
373 		    "cfg packet ID does not match!");
374 		message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0);
375 		return -1;
376 	}
377 	switch (attrp->p[ISAKMP_ATTRIBUTE_TYPE_OFF]) {
378 	case ISAKMP_CFG_ACK:
379 		if (ie->cfg_type != ISAKMP_CFG_SET) {
380 			log_print("cfg_initiator_recv_ATTR: "
381 			    "bad packet type ACK");
382 			message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED,
383 			    0, 1, 0);
384 			return -1;
385 		}
386 		break;
387 	case ISAKMP_CFG_REPLY:
388 		if (ie->cfg_type != ISAKMP_CFG_REQUEST) {
389 			log_print("cfg_initiator_recv_ATTR: "
390 			    "bad packet type REPLY");
391 			message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED,
392 			    0, 1, 0);
393 			return -1;
394 		}
395 		break;
396 
397 	default:
398 		log_print("cfg_initiator_recv_ATTR: unexpected configuration "
399 		    "message type %d", attrp->p[ISAKMP_ATTRIBUTE_TYPE_OFF]);
400 		message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0);
401 		return -1;
402 	}
403 
404 	attribute_map(attrp->p + ISAKMP_ATTRIBUTE_ATTRS_OFF,
405 	    GET_ISAKMP_GEN_LENGTH(attrp->p) - ISAKMP_TRANSFORM_SA_ATTRS_OFF,
406 	    cfg_decode_attribute, ie);
407 
408 	switch (ie->cfg_type) {
409 	case ISAKMP_CFG_ACK: {
410 			/* SET/ACK -- Server side (ACK from client) */
411 			msg->transport->vtbl->get_src(isakmp_sa->transport,
412 			    &sa);
413 			if (sockaddr2text(sa, &addr, 0) < 0)
414 				addr = (char *) uk_addr;
415 
416 			for (attr = LIST_FIRST(&ie->attrs); attr;
417 			    attr = LIST_NEXT(attr, link))
418 				LOG_DBG((LOG_NEGOTIATION, 50,
419 				    "cfg_initiator_recv_ATTR: "
420 				    "client %s ACKs attribute %s", addr,
421 				    constant_name(isakmp_cfg_attr_cst,
422 					attr->type)));
423 
424 			if (addr != uk_addr)
425 				free(addr);
426 		}
427 		break;
428 
429 	case ISAKMP_CFG_REPLY: {
430 			/*
431 			 * REQ/REPLY: effect attributes we've gotten
432 			 * responses on.
433 			 */
434 			msg->transport->vtbl->get_src(isakmp_sa->transport,
435 			    &sa);
436 			if (sockaddr2text(sa, &addr, 0) < 0)
437 				addr = (char *) uk_addr;
438 
439 			for (attr = LIST_FIRST(&ie->attrs); attr;
440 			    attr = LIST_NEXT(attr, link))
441 				LOG_DBG((LOG_NEGOTIATION, 50,
442 				    "cfg_initiator_recv_ATTR: "
443 				    "server %s replied with attribute %s",
444 				    addr, constant_name(isakmp_cfg_attr_cst,
445 					attr->type)));
446 
447 			if (addr != uk_addr)
448 				free(addr);
449 		}
450 		break;
451 
452 	default:
453 		break;
454 	}
455 
456 	attrp->flags |= PL_MARK;
457 	return 0;
458 }
459 
460 /*
461  * As "the server", this starts REQ/REPLY (initiated by the client).
462  * As "the client", this starts SET/ACK (initiated by the server).
463  */
464 static int
cfg_responder_recv_ATTR(struct message * msg)465 cfg_responder_recv_ATTR(struct message *msg)
466 {
467 	struct payload *attrp = payload_first(msg, ISAKMP_PAYLOAD_ATTRIBUTE);
468 	struct ipsec_exch *ie = msg->exchange->data;
469 	struct sa      *isakmp_sa = msg->isakmp_sa;
470 	struct isakmp_cfg_attr *attr;
471 	struct sockaddr *sa;
472 	char           *addr;
473 
474 	if (msg->exchange->phase == 2)
475 		if (cfg_verify_hash(msg))
476 			return -1;
477 
478 	ie->cfg_id = GET_ISAKMP_ATTRIBUTE_ID(attrp->p);
479 	ie->cfg_type = attrp->p[ISAKMP_ATTRIBUTE_TYPE_OFF];
480 
481 	switch (ie->cfg_type) {
482 	case ISAKMP_CFG_REQUEST:
483 	case ISAKMP_CFG_SET:
484 		break;
485 
486 	default:
487 		message_drop(msg, ISAKMP_NOTIFY_PAYLOAD_MALFORMED, 0, 1, 0);
488 		log_print("cfg_responder_recv_ATTR: "
489 		    "unexpected configuration message type %d", ie->cfg_type);
490 		return -1;
491 	}
492 
493 	attribute_map(attrp->p + ISAKMP_ATTRIBUTE_ATTRS_OFF,
494 	    GET_ISAKMP_GEN_LENGTH(attrp->p) - ISAKMP_TRANSFORM_SA_ATTRS_OFF,
495 	    cfg_decode_attribute, ie);
496 
497 	switch (ie->cfg_type) {
498 	case ISAKMP_CFG_REQUEST:
499 		/* We're done.  */
500 		break;
501 
502 	case ISAKMP_CFG_SET: {
503 			/* SET/ACK -- Client side (SET from server) */
504 			const char     *uk_addr = "<unknown>";
505 
506 			msg->transport->vtbl->get_dst(isakmp_sa->transport,
507 			    &sa);
508 			if (sockaddr2text(sa, &addr, 0) < 0)
509 				addr = (char *) uk_addr;
510 
511 			for (attr = LIST_FIRST(&ie->attrs); attr;
512 			    attr = LIST_NEXT(attr, link))
513 				LOG_DBG((LOG_NEGOTIATION, 50,
514 				    "cfg_responder_recv_ATTR: "
515 				    "server %s asks us to SET attribute %s",
516 				    addr, constant_name(isakmp_cfg_attr_cst,
517 					attr->type)));
518 
519 			/*
520 			 * XXX Here's the place to add code to walk through
521 			 * XXX each attribute and send them along to dhclient
522 			 * XXX or whatever. Each attribute that we act upon
523 			 * XXX (such as setting a netmask), should be marked
524 			 * XXX like this for us to send the proper ACK
525 			 * XXX response: attr->attr_used++;
526 			 */
527 
528 			if (addr != uk_addr)
529 				free(addr);
530 		}
531 		break;
532 
533 	default:
534 		break;
535 	}
536 
537 	attrp->flags |= PL_MARK;
538 	return 0;
539 }
540 
541 /*
542  * As "the server", this ends REQ/REPLY mode.
543  * As "the client", this ends SET/ACK mode.
544  */
545 static int
cfg_responder_send_ATTR(struct message * msg)546 cfg_responder_send_ATTR(struct message *msg)
547 {
548 	struct ipsec_exch *ie = msg->exchange->data;
549 	struct sa      *isakmp_sa = msg->isakmp_sa;
550 	u_int8_t       *hashp = 0, *attrp;
551 	u_int16_t       attrlen;
552 	char           *id_string;
553 
554 	if (msg->exchange->phase == 2) {
555 		hashp = cfg_add_hash(msg);
556 		if (!hashp)
557 			return -1;
558 	}
559 	/* We are responder, check isakmp_sa for other side.  */
560 	if (isakmp_sa->initiator ^ (ie->cfg_type == ISAKMP_CFG_REQUEST))
561 		id_string = ipsec_id_string(isakmp_sa->id_i,
562 		    isakmp_sa->id_i_len);
563 	else
564 		id_string = ipsec_id_string(isakmp_sa->id_r,
565 		    isakmp_sa->id_r_len);
566 	if (!id_string) {
567 		log_print("cfg_responder_send_ATTR: cannot parse client's ID");
568 		return -1;
569 	}
570 	if (cfg_encode_attributes(&ie->attrs, (ie->cfg_type == ISAKMP_CFG_SET ?
571 	    ISAKMP_CFG_ACK : ISAKMP_CFG_REPLY), ie->cfg_id, id_string, &attrp,
572 	    &attrlen)) {
573 		free(id_string);
574 		return -1;
575 	}
576 	free(id_string);
577 
578 	if (message_add_payload(msg, ISAKMP_PAYLOAD_ATTRIBUTE, attrp, attrlen,
579 	    1)) {
580 		free(attrp);
581 		return -1;
582 	}
583 	if (msg->exchange->phase == 2)
584 		if (cfg_finalize_hash(msg, hashp, attrp, attrlen))
585 			return -1;
586 
587 	return 0;
588 }
589 
590 u_int8_t *
cfg_add_hash(struct message * msg)591 cfg_add_hash(struct message *msg)
592 {
593 	struct ipsec_sa *isa = msg->isakmp_sa->data;
594 	struct hash    *hash = hash_get(isa->hash);
595 	u_int8_t       *hashp;
596 
597 	hashp = malloc(ISAKMP_HASH_SZ + hash->hashsize);
598 	if (!hashp) {
599 		log_error("cfg_add_hash: malloc (%lu) failed",
600 		    ISAKMP_HASH_SZ + (unsigned long)hash->hashsize);
601 		return 0;
602 	}
603 	if (message_add_payload(msg, ISAKMP_PAYLOAD_HASH, hashp,
604 	    ISAKMP_HASH_SZ + hash->hashsize, 1)) {
605 		free(hashp);
606 		return 0;
607 	}
608 	return hashp;
609 }
610 
611 int
cfg_finalize_hash(struct message * msg,u_int8_t * hashp,u_int8_t * data,u_int16_t length)612 cfg_finalize_hash(struct message *msg, u_int8_t *hashp, u_int8_t *data,
613     u_int16_t length)
614 {
615 	struct ipsec_sa *isa = msg->isakmp_sa->data;
616 	struct prf     *prf;
617 
618 	prf = prf_alloc(isa->prf_type, isa->hash, isa->skeyid_a,
619 	    isa->skeyid_len);
620 	if (!prf)
621 		return -1;
622 
623 	prf->Init(prf->prfctx);
624 	prf->Update(prf->prfctx, msg->exchange->message_id,
625 	    ISAKMP_HDR_MESSAGE_ID_LEN);
626 	prf->Update(prf->prfctx, data, length);
627 	prf->Final(hashp + ISAKMP_GEN_SZ, prf->prfctx);
628 	prf_free(prf);
629 	return 0;
630 }
631 
632 int
cfg_verify_hash(struct message * msg)633 cfg_verify_hash(struct message *msg)
634 {
635 	struct payload *hashp = payload_first(msg, ISAKMP_PAYLOAD_HASH);
636 	struct ipsec_sa *isa = msg->isakmp_sa->data;
637 	struct prf     *prf;
638 	u_int8_t       *hash, *comp_hash;
639 	size_t          hash_len;
640 
641 	if (!hashp) {
642 		log_print("cfg_verify_hash: phase 2 message missing HASH");
643 		message_drop(msg, ISAKMP_NOTIFY_INVALID_HASH_INFORMATION,
644 		    0, 1, 0);
645 		return -1;
646 	}
647 	hash = hashp->p;
648 	hash_len = GET_ISAKMP_GEN_LENGTH(hash);
649 	comp_hash = malloc(hash_len - ISAKMP_GEN_SZ);
650 	if (!comp_hash) {
651 		log_error("cfg_verify_hash: malloc (%lu) failed",
652 		    (unsigned long)hash_len - ISAKMP_GEN_SZ);
653 		return -1;
654 	}
655 	/* Verify hash.  */
656 	prf = prf_alloc(isa->prf_type, isa->hash, isa->skeyid_a,
657 	    isa->skeyid_len);
658 	if (!prf) {
659 		free(comp_hash);
660 		return -1;
661 	}
662 	prf->Init(prf->prfctx);
663 	prf->Update(prf->prfctx, msg->exchange->message_id,
664 	    ISAKMP_HDR_MESSAGE_ID_LEN);
665 	prf->Update(prf->prfctx, hash + hash_len,
666 	    msg->iov[0].iov_len - ISAKMP_HDR_SZ - hash_len);
667 	prf->Final(comp_hash, prf->prfctx);
668 	prf_free(prf);
669 
670 	if (memcmp(hash + ISAKMP_GEN_SZ, comp_hash, hash_len - ISAKMP_GEN_SZ)
671 	    != 0) {
672 		message_drop(msg, ISAKMP_NOTIFY_INVALID_HASH_INFORMATION,
673 		    0, 1, 0);
674 		free(comp_hash);
675 		return -1;
676 	}
677 	free(comp_hash);
678 
679 	/* Mark the HASH as handled.  */
680 	hashp->flags |= PL_MARK;
681 
682 	/* Mark message authenticated. */
683 	msg->flags |= MSG_AUTHENTICATED;
684 
685 	return 0;
686 }
687 
688 /*
689  * Decode the attribute of type TYPE with a LEN length value pointed to by
690  * VALUE.  VIE is a pointer to the IPsec exchange context holding the
691  * attributes indexed by type for easy retrieval.
692  */
693 static int
cfg_decode_attribute(u_int16_t type,u_int8_t * value,u_int16_t len,void * vie)694 cfg_decode_attribute(u_int16_t type, u_int8_t * value, u_int16_t len,
695     void *vie)
696 {
697 	struct ipsec_exch *ie = vie;
698 	struct isakmp_cfg_attr *attr;
699 
700 	if (type >= ISAKMP_CFG_ATTR_PRIVATE_MIN &&
701 	    type <= ISAKMP_CFG_ATTR_PRIVATE_MAX)
702 		return 0;
703 	if (type == 0 || type >= ISAKMP_CFG_ATTR_FUTURE_MIN) {
704 		LOG_DBG((LOG_NEGOTIATION, 30,
705 		    "cfg_decode_attribute: invalid attr type %u", type));
706 		return -1;
707 	}
708 	attr = calloc(1, sizeof *attr);
709 	if (!attr) {
710 		log_error("cfg_decode_attribute: calloc (1, %lu) failed",
711 		    (unsigned long)sizeof *attr);
712 		return -1;
713 	}
714 	attr->type = type;
715 	attr->length = len;
716 	if (len) {
717 		attr->value = malloc(len);
718 		if (!attr->value) {
719 			log_error("cfg_decode_attribute: malloc (%d) failed",
720 			    len);
721 			free(attr);
722 			/* Should we also deallocate all other values?  */
723 			return -1;
724 		}
725 		memcpy(attr->value, value, len);
726 	}
727 	LIST_INSERT_HEAD(&ie->attrs, attr, link);
728 	return 0;
729 }
730 
731 /*
732  * Encode list of attributes from ie->attrs into a attribute payload.
733  */
734 static int
cfg_encode_attributes(struct isakmp_cfg_attr_head * attrs,u_int32_t type,u_int32_t cfg_id,char * id_string,u_int8_t ** attrp,u_int16_t * len)735 cfg_encode_attributes(struct isakmp_cfg_attr_head *attrs, u_int32_t type,
736     u_int32_t cfg_id, char *id_string, u_int8_t **attrp, u_int16_t *len)
737 {
738 	struct isakmp_cfg_attr *attr;
739 	struct sockaddr *sa;
740 	sa_family_t     family;
741 	u_int32_t       value;
742 	u_int16_t       off;
743 	char           *field;
744 
745 	/* Compute length */
746 	*len = ISAKMP_ATTRIBUTE_SZ;
747 	for (attr = LIST_FIRST(attrs); attr; attr = LIST_NEXT(attr, link)) {
748 		/* With ACK we only include the attrs we've actually used.  */
749 		if (type == ISAKMP_CFG_ACK && attr->attr_used == 0)
750 			continue;
751 
752 		switch (attr->type) {
753 		case ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS:
754 		case ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK:
755 		case ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP:
756 		case ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS:
757 		case ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS:
758 		case ISAKMP_CFG_ATTR_INTERNAL_ADDRESS_EXPIRY:
759 			attr->length = 4;
760 			break;
761 
762 		case ISAKMP_CFG_ATTR_INTERNAL_IP4_SUBNET:
763 			attr->length = 8;
764 			break;
765 
766 		case ISAKMP_CFG_ATTR_APPLICATION_VERSION:
767 			/* XXX So far no version identifier of isakmpd here. */
768 			attr->length = 0;
769 			break;
770 
771 		case ISAKMP_CFG_ATTR_SUPPORTED_ATTRIBUTES:
772 			attr->length = 2 * 15;
773 			break;
774 
775 		case ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS:
776 		case ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK:
777 		case ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP:
778 		case ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS:
779 		case ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS:
780 			attr->length = 16;
781 			break;
782 
783 		case ISAKMP_CFG_ATTR_INTERNAL_IP6_SUBNET:
784 			attr->length = 17;
785 			break;
786 
787 		default:
788 			attr->ignore++;
789 			/* XXX Log!  */
790 		}
791 		*len += ISAKMP_ATTR_SZ + attr->length;
792 	}
793 
794 	/* Allocate enough space for the payload */
795 	*attrp = calloc(1, *len);
796 	if (!*attrp) {
797 		log_error("cfg_encode_attributes: calloc (1, %lu) failed",
798 		    (unsigned long)*len);
799 		return -1;
800 	}
801 	SET_ISAKMP_ATTRIBUTE_TYPE(*attrp, type);
802 	SET_ISAKMP_ATTRIBUTE_ID(*attrp, cfg_id);
803 
804 	off = ISAKMP_ATTRIBUTE_SZ;
805 	for (attr = LIST_FIRST(attrs); attr; attr = LIST_NEXT(attr, link)) {
806 		/* With ACK we only include the attrs we've actually used.  */
807 		if (type == ISAKMP_CFG_ACK && attr->attr_used == 0)
808 			continue;
809 
810 		switch (attr->type) {
811 		case ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS:
812 		case ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK:
813 		case ISAKMP_CFG_ATTR_INTERNAL_IP4_SUBNET:
814 		case ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP:
815 		case ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS:
816 		case ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS:
817 			family = AF_INET;
818 			break;
819 
820 		case ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS:
821 		case ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK:
822 		case ISAKMP_CFG_ATTR_INTERNAL_IP6_SUBNET:
823 		case ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP:
824 		case ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS:
825 		case ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS:
826 			family = AF_INET6;
827 			break;
828 
829 		default:
830 			family = 0;
831 			break;
832 		}
833 
834 		switch (attr->type) {
835 		case ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS:
836 		case ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS:
837 			field = "Address";
838 			break;
839 
840 		case ISAKMP_CFG_ATTR_INTERNAL_IP4_SUBNET:
841 		case ISAKMP_CFG_ATTR_INTERNAL_IP6_SUBNET:
842 			field = "Network";	/* XXX or just "Address" */
843 			break;
844 
845 		case ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK:
846 		case ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK:
847 			field = "Netmask";
848 			break;
849 
850 		case ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP:
851 		case ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP:
852 			field = "DHCP-server";
853 			break;
854 
855 		case ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS:
856 		case ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS:
857 			field = "Nameserver";
858 			break;
859 
860 		case ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS:
861 		case ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS:
862 			field = "WINS-server";
863 			break;
864 
865 		default:
866 			field = 0;
867 		}
868 
869 		switch (attr->type) {
870 		case ISAKMP_CFG_ATTR_INTERNAL_IP4_ADDRESS:
871 		case ISAKMP_CFG_ATTR_INTERNAL_IP6_ADDRESS:
872 		case ISAKMP_CFG_ATTR_INTERNAL_IP4_NETMASK:
873 		case ISAKMP_CFG_ATTR_INTERNAL_IP6_NETMASK:
874 		case ISAKMP_CFG_ATTR_INTERNAL_IP4_DHCP:
875 		case ISAKMP_CFG_ATTR_INTERNAL_IP6_DHCP:
876 		case ISAKMP_CFG_ATTR_INTERNAL_IP4_DNS:
877 		case ISAKMP_CFG_ATTR_INTERNAL_IP6_DNS:
878 		case ISAKMP_CFG_ATTR_INTERNAL_IP4_NBNS:
879 		case ISAKMP_CFG_ATTR_INTERNAL_IP6_NBNS:
880 			sa = conf_get_address(id_string, field);
881 			if (!sa) {
882 				LOG_DBG((LOG_NEGOTIATION, 10,
883 				    "cfg_responder_send_ATTR: "
884 				    "attribute not found: %s", field));
885 				attr->length = 0;
886 				break;
887 			}
888 			if (sa->sa_family != family) {
889 				log_print("cfg_responder_send_ATTR: "
890 				    "attribute %s - expected %s got %s data",
891 				    field,
892 				    (family == AF_INET ? "IPv4" : "IPv6"),
893 				    (sa->sa_family ==
894 					AF_INET ? "IPv4" : "IPv6"));
895 				free(sa);
896 				attr->length = 0;
897 				break;
898 			}
899 			/* Temporary limit length for the _SUBNET types. */
900 			if (attr->type == ISAKMP_CFG_ATTR_INTERNAL_IP4_SUBNET)
901 				attr->length = 4;
902 			else if (attr->type ==
903 			    ISAKMP_CFG_ATTR_INTERNAL_IP6_SUBNET)
904 				attr->length = 16;
905 
906 			memcpy(*attrp + off + ISAKMP_ATTR_VALUE_OFF,
907 			    sockaddr_addrdata(sa), attr->length);
908 			free(sa);
909 
910 			/* _SUBNET types need some extra work. */
911 			if (attr->type ==
912 			    ISAKMP_CFG_ATTR_INTERNAL_IP4_SUBNET) {
913 				sa = conf_get_address(id_string, "Netmask");
914 				if (!sa) {
915 					LOG_DBG((LOG_NEGOTIATION, 10,
916 					    "cfg_responder_send_ATTR: "
917 					   "attribute not found: Netmask"));
918 					attr->length = 0;
919 					break;
920 				}
921 				if (sa->sa_family != AF_INET) {
922 					log_print("cfg_responder_send_ATTR: "
923 					    "attribute Netmask - expected "
924 					    "IPv4 got IPv6 data");
925 					free(sa);
926 					attr->length = 0;
927 					break;
928 				}
929 				memcpy(*attrp + off + ISAKMP_ATTR_VALUE_OFF +
930 				    attr->length, sockaddr_addrdata(sa),
931 				    attr->length);
932 				attr->length = 8;
933 				free(sa);
934 			} else if (attr->type ==
935 			    ISAKMP_CFG_ATTR_INTERNAL_IP6_SUBNET) {
936 				int prefix = conf_get_num(id_string, "Prefix",
937 				    -1);
938 
939 				if (prefix == -1) {
940 					log_print("cfg_responder_send_ATTR: "
941 					    "attribute not found: Prefix");
942 					attr->length = 0;
943 					break;
944 				} else if (prefix < -1 || prefix > 128) {
945 					log_print("cfg_responder_send_ATTR: "
946 					    "attribute Prefix - invalid "
947 					    "value %d", prefix);
948 					attr->length = 0;
949 					break;
950 				}
951 				*(*attrp + off + ISAKMP_ATTR_VALUE_OFF + 16) =
952 				    (u_int8_t)prefix;
953 				attr->length = 17;
954 			}
955 			break;
956 
957 		case ISAKMP_CFG_ATTR_INTERNAL_ADDRESS_EXPIRY:
958 			value = conf_get_num(id_string, "Lifetime", 1200);
959 			encode_32(*attrp + off + ISAKMP_ATTR_VALUE_OFF, value);
960 			break;
961 
962 		case ISAKMP_CFG_ATTR_APPLICATION_VERSION:
963 			/* XXX So far no version identifier of isakmpd here. */
964 			break;
965 
966 		case ISAKMP_CFG_ATTR_SUPPORTED_ATTRIBUTES:
967 			break;
968 
969 		default:
970 			break;
971 		}
972 
973 		SET_ISAKMP_ATTR_TYPE(*attrp + off, attr->type);
974 		SET_ISAKMP_ATTR_LENGTH_VALUE(*attrp + off, attr->length);
975 		off += ISAKMP_ATTR_VALUE_OFF + attr->length;
976 	}
977 
978 	return 0;
979 }
980