1/*	$NetBSD: isakmp_cfg.c,v 1.12.6.1 2007/06/07 20:06:34 manu Exp $	*/
2
3/* Id: isakmp_cfg.c,v 1.55 2006/08/22 18:17:17 manubsd Exp */
4
5/*
6 * Copyright (C) 2004-2006 Emmanuel Dreyfus
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include "config.h"
35
36#include <sys/types.h>
37#include <sys/param.h>
38#include <sys/socket.h>
39#include <sys/queue.h>
40
41#include <utmpx.h>
42#include <util.h>
43
44
45#ifdef __FreeBSD__
46# include <libutil.h>
47#endif
48#ifdef __NetBSD__
49#  include <util.h>
50#endif
51
52#include <netinet/in.h>
53#include <arpa/inet.h>
54
55#include <stdlib.h>
56#include <stdio.h>
57#include <string.h>
58#include <errno.h>
59#if TIME_WITH_SYS_TIME
60# include <sys/time.h>
61# include <time.h>
62#else
63# if HAVE_SYS_TIME_H
64#  include <sys/time.h>
65# else
66#  include <time.h>
67# endif
68#endif
69#include <netdb.h>
70#ifdef HAVE_UNISTD_H
71#include <unistd.h>
72#endif
73#if HAVE_STDINT_H
74#include <stdint.h>
75#endif
76#include <ctype.h>
77#include <resolv.h>
78
79#include "var.h"
80#include "misc.h"
81#include "vmbuf.h"
82#include "plog.h"
83#include "sockmisc.h"
84#include "schedule.h"
85#include "debug.h"
86#include "fsm.h"
87
88#include "isakmp_var.h"
89#include "isakmp.h"
90#include "handler.h"
91#include "throttle.h"
92#include "remoteconf.h"
93#include "localconf.h"
94#include "crypto_openssl.h"
95#include "isakmp_inf.h"
96#include "isakmp_xauth.h"
97#include "isakmp_unity.h"
98#include "isakmp_cfg.h"
99#include "strnames.h"
100#include "vpn_control.h"
101#include "vpn_control_var.h"
102#include "ike_session.h"
103#include "ipsecSessionTracer.h"
104#include "ipsecMessageTracer.h"
105#include "nattraversal.h"
106
107struct isakmp_cfg_config isakmp_cfg_config;
108
109static vchar_t *buffer_cat (vchar_t *s, vchar_t *append);
110static vchar_t *isakmp_cfg_net (phase1_handle_t *, struct isakmp_data *);
111#if 0
112static vchar_t *isakmp_cfg_void (phase1_handle_t *, struct isakmp_data *);
113#endif
114static vchar_t *isakmp_cfg_addr4 (phase1_handle_t *,
115				 struct isakmp_data *, in_addr_t *);
116static void isakmp_cfg_getaddr4 (struct isakmp_data *, struct in_addr *);
117static vchar_t *isakmp_cfg_addr4_list (phase1_handle_t *,
118				      struct isakmp_data *, in_addr_t *, int);
119static void isakmp_cfg_appendaddr4 (struct isakmp_data *,
120				   struct in_addr *, int *, int);
121static void isakmp_cfg_getstring (struct isakmp_data *,char *);
122void isakmp_cfg_iplist_to_str (char *, int, void *, int);
123
124#define ISAKMP_CFG_LOGIN	1
125#define ISAKMP_CFG_LOGOUT	2
126
127/*
128 * Handle an ISAKMP config mode packet
129 * We expect HDR, HASH, ATTR
130 */
131void
132isakmp_cfg_r(iph1, msg)
133	phase1_handle_t *iph1;
134	vchar_t *msg;
135{
136	struct isakmp *packet;
137	struct isakmp_gen *ph;
138	int tlen;
139	char *npp;
140	int np;
141	vchar_t *dmsg;
142	struct isakmp_ivm *ivm;
143	phase2_handle_t *iph2;
144	int               error = -1;
145
146	/* Check that the packet is long enough to have a header */
147	if (msg->l < sizeof(*packet)) {
148		IPSECSESSIONTRACEREVENT(iph1->parent_session,
149								IPSECSESSIONEVENTCODE_IKE_PACKET_RX_FAIL,
150								CONSTSTR("MODE-Config. Unexpected short packet"),
151								CONSTSTR("Failed to process short MODE-Config packet"));
152		plog(ASL_LEVEL_ERR, "Unexpected short packet\n");
153		return;
154	}
155
156	packet = (struct isakmp *)msg->v;
157
158	/* Is it encrypted? It should be encrypted */
159	if ((packet->flags & ISAKMP_FLAG_E) == 0) {
160		IPSECSESSIONTRACEREVENT(iph1->parent_session,
161								IPSECSESSIONEVENTCODE_IKE_PACKET_RX_FAIL,
162								CONSTSTR("MODE-Config. User credentials sent in cleartext"),
163								CONSTSTR("Dropped cleattext User credentials"));
164		plog(ASL_LEVEL_ERR,
165		    "User credentials sent in cleartext!\n");
166		return;
167	}
168
169	/*
170	 * Decrypt the packet. If this is the beginning of a new
171	 * exchange, reinitialize the IV
172	 */
173	if (iph1->mode_cfg->ivm == NULL ||
174	    iph1->mode_cfg->last_msgid != packet->msgid )
175		iph1->mode_cfg->ivm =
176		    isakmp_cfg_newiv(iph1, packet->msgid);
177	ivm = iph1->mode_cfg->ivm;
178
179	dmsg = oakley_do_decrypt(iph1, msg, ivm->iv, ivm->ive);
180	if (dmsg == NULL) {
181		IPSECSESSIONTRACEREVENT(iph1->parent_session,
182								IPSECSESSIONEVENTCODE_IKE_PACKET_RX_FAIL,
183								CONSTSTR("MODE-Config. Failed to decrypt packet"),
184								CONSTSTR("Failed to decrypt MODE-Config packet"));
185		plog(ASL_LEVEL_ERR,
186		    "failed to decrypt message\n");
187		return;
188	}
189
190	plog(ASL_LEVEL_DEBUG, "MODE_CFG packet\n");
191
192	/* Now work with the decrypted packet */
193	packet = (struct isakmp *)dmsg->v;
194	tlen = dmsg->l - sizeof(*packet);
195	ph = (struct isakmp_gen *)(packet + 1);
196
197	np = packet->np;
198	while ((tlen > 0) && (np != ISAKMP_NPTYPE_NONE)) {
199		/* Check that the payload header fits in the packet */
200		if (tlen < sizeof(*ph)) {
201			 plog(ASL_LEVEL_WARNING,
202			      "Short payload header\n");
203			 goto out;
204		}
205
206		/* Check that the payload fits in the packet */
207		if (tlen < ntohs(ph->len)) {
208			plog(ASL_LEVEL_WARNING,
209			      "Short payload\n");
210			goto out;
211		}
212
213		plog(ASL_LEVEL_DEBUG, "Seen payload %d\n", np);
214
215		switch(np) {
216		case ISAKMP_NPTYPE_HASH: {
217			vchar_t *check;
218			vchar_t *payload;
219			size_t plen;
220			struct isakmp_gen *nph;
221
222			plen = ntohs(ph->len);
223			nph = (struct isakmp_gen *)((char *)ph + plen);
224			plen = ntohs(nph->len);
225            /* Check that the hash payload fits in the packet */
226			if (tlen < (plen + ntohs(ph->len))) {
227				plog(ASL_LEVEL_WARNING,
228					 "Invalid Hash payload. len %d, overall-len %d\n",
229					 ntohs(nph->len),
230					 (int)plen);
231				goto out;
232			}
233
234			if ((payload = vmalloc(plen)) == NULL) {
235				plog(ASL_LEVEL_ERR,
236				    "Cannot allocate memory\n");
237				goto out;
238			}
239			memcpy(payload->v, nph, plen);
240
241			if ((check = oakley_compute_hash1(iph1,
242			    packet->msgid, payload)) == NULL) {
243				plog(ASL_LEVEL_ERR,
244				    "Cannot compute hash\n");
245				vfree(payload);
246				goto out;
247			}
248
249			if (memcmp(ph + 1, check->v, check->l) != 0) {
250				plog(ASL_LEVEL_ERR,
251				    "Hash verification failed\n");
252				vfree(payload);
253				vfree(check);
254				goto out;
255			}
256			vfree(payload);
257			vfree(check);
258			break;
259		}
260		case ISAKMP_NPTYPE_ATTR: {
261			struct isakmp_pl_attr *attrpl;
262
263			attrpl = (struct isakmp_pl_attr *)ph;
264			isakmp_cfg_attr_r(iph1, packet->msgid, attrpl, msg);
265
266			break;
267		}
268		default:
269			 plog(ASL_LEVEL_WARNING,
270			      "Unexpected next payload %d\n", np);
271			 /* Skip to the next payload */
272			 break;
273		}
274
275		/* Move to the next payload */
276		np = ph->np;
277		tlen -= ntohs(ph->len);
278		npp = (char *)ph;
279		ph = (struct isakmp_gen *)(npp + ntohs(ph->len));
280	}
281
282	error = 0;
283	/* find phase 2 in case pkt scheduled for resend */
284	iph2 = ike_session_getph2bymsgid(iph1, packet->msgid);
285	if (iph2 == NULL)
286		goto out;		/* no resend scheduled */
287	SCHED_KILL(iph2->scr);	/* turn off schedule */
288	ike_session_unlink_phase2(iph2);
289
290	IPSECSESSIONTRACEREVENT(iph1->parent_session,
291							IPSECSESSIONEVENTCODE_IKE_PACKET_RX_SUCC,
292							CONSTSTR("MODE-Config"),
293							CONSTSTR(NULL));
294out:
295	if (error) {
296		IPSECSESSIONTRACEREVENT(iph1->parent_session,
297								IPSECSESSIONEVENTCODE_IKE_PACKET_RX_FAIL,
298								CONSTSTR("MODE-Config"),
299								CONSTSTR("Failed to process Mode-Config packet"));
300	}
301	vfree(dmsg);
302}
303
304int
305isakmp_cfg_attr_r(iph1, msgid, attrpl, msg)
306	phase1_handle_t *iph1;
307	u_int32_t msgid;
308	struct isakmp_pl_attr *attrpl;
309       vchar_t *msg;
310{
311	int type = attrpl->type;
312
313	plog(ASL_LEVEL_DEBUG,
314	     "Configuration exchange type %s\n", s_isakmp_cfg_ptype(type));
315	switch (type) {
316	case ISAKMP_CFG_ACK:
317		/* ignore, but this is the time to reinit the IV */
318		oakley_delivm(iph1->mode_cfg->ivm);
319		iph1->mode_cfg->ivm = NULL;
320		return 0;
321		break;
322
323	case ISAKMP_CFG_REPLY:
324		return isakmp_cfg_reply(iph1, attrpl);
325		break;
326
327	case ISAKMP_CFG_REQUEST:
328		iph1->msgid = msgid;
329		return isakmp_cfg_request(iph1, attrpl, msg);
330		break;
331
332	case ISAKMP_CFG_SET:
333		iph1->msgid = msgid;
334		return isakmp_cfg_set(iph1, attrpl, msg);
335		break;
336
337	default:
338		plog(ASL_LEVEL_WARNING,
339		     "Unepected configuration exchange type %d\n", type);
340		return -1;
341		break;
342	}
343
344	return 0;
345}
346
347int
348isakmp_cfg_reply(iph1, attrpl)
349	phase1_handle_t *iph1;
350	struct isakmp_pl_attr *attrpl;
351{
352	struct isakmp_data *attr;
353	int tlen;
354	size_t alen;
355	char *npp;
356	int type;
357	int error;
358
359	if (iph1->mode_cfg->flags & ISAKMP_CFG_GOT_REPLY)
360		return 0;	/* already received this - duplicate packet */
361
362	tlen = ntohs(attrpl->h.len);
363	attr = (struct isakmp_data *)(attrpl + 1);
364	tlen -= sizeof(*attrpl);
365
366	while (tlen > 0) {
367		type = ntohs(attr->type);
368
369		/* Handle short attributes */
370		if ((type & ISAKMP_GEN_MASK) == ISAKMP_GEN_TV) {
371			type &= ~ISAKMP_GEN_MASK;
372
373			plog(ASL_LEVEL_DEBUG,
374			     "Short attribute %s = %d\n",
375			     s_isakmp_cfg_type(type), ntohs(attr->lorv));
376
377			switch (type) {
378			case XAUTH_TYPE:
379				if ((error = xauth_attr_reply(iph1,
380				    attr, ntohs(attrpl->id))) != 0)
381					return error;
382				break;
383
384				break;
385
386			default:
387				plog(ASL_LEVEL_WARNING,
388				     "Ignored short attribute %s\n",
389				     s_isakmp_cfg_type(type));
390				break;
391			}
392
393			tlen -= sizeof(*attr);
394			attr++;
395			continue;
396		}
397
398		type = ntohs(attr->type);
399		alen = ntohs(attr->lorv);
400
401		/* Check that the attribute fit in the packet */
402		if (tlen < alen) {
403			plog(ASL_LEVEL_ERR,
404			     "Short attribute %s\n",
405			     s_isakmp_cfg_type(type));
406			return -1;
407		}
408
409		plog(ASL_LEVEL_DEBUG,
410		     "Attribute %s, len %zu\n",
411		     s_isakmp_cfg_type(type), alen);
412
413		switch(type) {
414		case XAUTH_TYPE:
415		case XAUTH_USER_NAME:
416		case XAUTH_USER_PASSWORD:
417		case XAUTH_PASSCODE:
418		case XAUTH_MESSAGE:
419		case XAUTH_CHALLENGE:
420		case XAUTH_DOMAIN:
421		case XAUTH_STATUS:
422		case XAUTH_NEXT_PIN:
423		case XAUTH_ANSWER:
424			if ((error = xauth_attr_reply(iph1,
425			    attr, ntohs(attrpl->id))) != 0)
426				return error;
427			break;
428		case INTERNAL_IP4_ADDRESS:
429			if ((iph1->mode_cfg->flags & ISAKMP_CFG_GOT_ADDR4) == 0) {
430				isakmp_cfg_getaddr4(attr, &iph1->mode_cfg->addr4);
431				iph1->mode_cfg->flags |= ISAKMP_CFG_GOT_ADDR4;
432			}
433			break;
434		case INTERNAL_IP4_NETMASK:
435			if ((iph1->mode_cfg->flags & ISAKMP_CFG_GOT_MASK4) == 0) {
436				isakmp_cfg_getaddr4(attr, &iph1->mode_cfg->mask4);
437				iph1->mode_cfg->flags |= ISAKMP_CFG_GOT_MASK4;
438			}
439			break;
440		case INTERNAL_IP4_DNS:
441			if ((iph1->mode_cfg->flags & ISAKMP_CFG_GOT_DNS4) == 0) {
442				isakmp_cfg_appendaddr4(attr,
443					&iph1->mode_cfg->dns4[iph1->mode_cfg->dns4_index],
444					&iph1->mode_cfg->dns4_index, MAXNS);
445				iph1->mode_cfg->flags |= ISAKMP_CFG_GOT_DNS4;
446			}
447			break;
448		case INTERNAL_IP4_NBNS:
449			if ((iph1->mode_cfg->flags & ISAKMP_CFG_GOT_WINS4) == 0) {
450				isakmp_cfg_appendaddr4(attr,
451					&iph1->mode_cfg->wins4[iph1->mode_cfg->wins4_index],
452					&iph1->mode_cfg->wins4_index, MAXNS);
453				iph1->mode_cfg->flags |= ISAKMP_CFG_GOT_WINS4;
454			}
455			break;
456		case UNITY_DEF_DOMAIN:
457			if ((iph1->mode_cfg->flags & ISAKMP_CFG_GOT_DEFAULT_DOMAIN) == 0) {
458				isakmp_cfg_getstring(attr,
459					iph1->mode_cfg->default_domain);
460				iph1->mode_cfg->flags |= ISAKMP_CFG_GOT_DEFAULT_DOMAIN;
461			}
462			break;
463		case UNITY_SPLIT_INCLUDE:
464		case UNITY_LOCAL_LAN:
465		case UNITY_SPLITDNS_NAME:
466		case UNITY_BANNER:
467		case UNITY_SAVE_PASSWD:
468		case UNITY_NATT_PORT:
469		case UNITY_FW_TYPE:
470		case UNITY_BACKUP_SERVERS:
471		case UNITY_DDNS_HOSTNAME:
472		case APPLICATION_VERSION:
473		case UNITY_PFS:
474			isakmp_unity_reply(iph1, attr);
475			break;
476		case INTERNAL_IP4_SUBNET:
477		case INTERNAL_ADDRESS_EXPIRY:
478			if (iph1->started_by_api)
479				break;	/* not actually ignored - don't fall thru */
480			// else fall thru
481		default:
482			plog(ASL_LEVEL_WARNING,
483			     "Ignored attribute %s\n",
484			     s_isakmp_cfg_type(type));
485			break;
486		}
487
488		npp = (char *)attr;
489		attr = (struct isakmp_data *)(npp + sizeof(*attr) + alen);
490		tlen -= (sizeof(*attr) + alen);
491	}
492	iph1->mode_cfg->flags |= ISAKMP_CFG_GOT_REPLY;
493
494	if (iph1->started_by_api || (iph1->is_rekey && iph1->parent_session && iph1->parent_session->is_client)) {
495		/* connection was started by API - save attr list for passing to VPN controller */
496		if (iph1->mode_cfg->attr_list != NULL)	/* shouldn't happen */
497			vfree(iph1->mode_cfg->attr_list);
498		if (ntohs(attrpl->h.len) < sizeof(*attrpl)) {
499			plog(ASL_LEVEL_ERR,
500				 "invalid cfg-attr-list, attr-len %d\n",
501				 ntohs(attrpl->h.len));
502			return -1;
503		}
504		alen = ntohs(attrpl->h.len) - sizeof(*attrpl);
505		if ((iph1->mode_cfg->attr_list = vmalloc(alen)) == NULL) {
506			plog(ASL_LEVEL_ERR,
507			     "Cannot allocate memory for mode-cfg attribute list\n");
508			return -1;
509		}
510		memcpy(iph1->mode_cfg->attr_list->v, attrpl + 1, alen);
511	}
512
513
514#ifdef ENABLE_VPNCONTROL_PORT
515	if (FSM_STATE_IS_ESTABLISHED(iph1->status))
516		vpncontrol_notify_phase_change(0, FROM_LOCAL, iph1, NULL);
517#endif
518
519	return 0;
520}
521
522int
523isakmp_cfg_request(iph1, attrpl, msg)
524	phase1_handle_t *iph1;
525	struct isakmp_pl_attr *attrpl;
526       vchar_t *msg;
527{
528	struct isakmp_data *attr;
529	int tlen;
530	size_t alen;
531	char *npp;
532	vchar_t *payload = NULL;
533	struct isakmp_pl_attr *reply;
534	vchar_t *reply_attr;
535	int type;
536	int error = -1;
537
538	tlen = ntohs(attrpl->h.len);
539	attr = (struct isakmp_data *)(attrpl + 1);
540	tlen -= sizeof(*attrpl);
541
542	/*
543	 * if started_by_api then we are a VPN client and if we receive
544	 * a mode-cfg request it needs to go to the VPN controller to
545	 * retrieve the appropriate data (name, pw, pin, etc.)
546	 */
547	if (iph1->started_by_api || ike_session_is_client_ph1_rekey(iph1)) {
548		/*
549		 * if we already received this one - ignore it
550		 * we are waiting for a reply from the vpn control socket
551		 */
552		if (iph1->xauth_awaiting_userinput)
553			return 0;
554
555		/* otherwise - save the msg id and call and send the status notification */
556		iph1->pended_xauth_id = attrpl->id;		/* network byte order */
557		if (vpncontrol_notify_need_authinfo(iph1, attrpl + 1, tlen))
558			goto end;
559		iph1->xauth_awaiting_userinput = 1;
560               iph1->xauth_awaiting_userinput_msg = vdup(msg); // dup the message for later
561		ike_session_start_xauth_timer(iph1);
562
563		IPSECLOGASLMSG("IPSec Extended Authentication requested.\n");
564
565		return 0;
566	}
567
568	if ((payload = vmalloc(sizeof(*reply))) == NULL) {
569		plog(ASL_LEVEL_ERR, "Cannot allocate memory\n");
570		return -1;
571	}
572	memset(payload->v, 0, sizeof(*reply));
573
574	while (tlen > 0) {
575		reply_attr = NULL;
576		type = ntohs(attr->type);
577
578		/* Handle short attributes */
579		if ((type & ISAKMP_GEN_MASK) == ISAKMP_GEN_TV) {
580			type &= ~ISAKMP_GEN_MASK;
581
582			plog(ASL_LEVEL_DEBUG,
583			     "Short attribute %s = %d\n",
584			     s_isakmp_cfg_type(type), ntohs(attr->lorv));
585
586			switch (type) {
587			case XAUTH_TYPE:
588				reply_attr = isakmp_xauth_req(iph1, attr);
589				break;
590			default:
591				plog(ASL_LEVEL_WARNING,
592				     "Ignored short attribute %s\n",
593				     s_isakmp_cfg_type(type));
594				break;
595			}
596
597			tlen -= sizeof(*attr);
598			attr++;
599
600			if (reply_attr != NULL) {
601				payload = buffer_cat(payload, reply_attr);
602				vfree(reply_attr);
603			}
604
605			continue;
606		}
607
608		type = ntohs(attr->type);
609		alen = ntohs(attr->lorv);
610
611		/* Check that the attribute fit in the packet */
612		if (tlen < alen) {
613			plog(ASL_LEVEL_ERR,
614			     "Short attribute %s\n",
615			     s_isakmp_cfg_type(type));
616			goto end;
617		}
618
619		plog(ASL_LEVEL_DEBUG,
620		     "Attribute %s, len %zu\n",
621		     s_isakmp_cfg_type(type), alen);
622
623		switch(type) {
624		case INTERNAL_IP4_ADDRESS:
625		case INTERNAL_IP4_NETMASK:
626		case INTERNAL_IP4_DNS:
627		case INTERNAL_IP4_NBNS:
628		case INTERNAL_IP4_SUBNET:
629			reply_attr = isakmp_cfg_net(iph1, attr);
630			break;
631
632		case XAUTH_TYPE:
633		case XAUTH_USER_NAME:
634		case XAUTH_USER_PASSWORD:
635		case XAUTH_PASSCODE:
636		case XAUTH_MESSAGE:
637		case XAUTH_CHALLENGE:
638		case XAUTH_DOMAIN:
639		case XAUTH_STATUS:
640		case XAUTH_NEXT_PIN:
641		case XAUTH_ANSWER:
642			reply_attr = isakmp_xauth_req(iph1, attr);
643			break;
644
645		case APPLICATION_VERSION:
646			reply_attr = isakmp_cfg_string(iph1,
647			    attr, ISAKMP_CFG_RACOON_VERSION);
648			break;
649
650		case UNITY_BANNER:
651		case UNITY_PFS:
652		case UNITY_SAVE_PASSWD:
653		case UNITY_DEF_DOMAIN:
654		case UNITY_DDNS_HOSTNAME:
655		case UNITY_FW_TYPE:
656		case UNITY_SPLITDNS_NAME:
657		case UNITY_SPLIT_INCLUDE:
658		case UNITY_LOCAL_LAN:
659		case UNITY_NATT_PORT:
660		case UNITY_BACKUP_SERVERS:
661			reply_attr = isakmp_unity_req(iph1, attr);
662			break;
663
664		case INTERNAL_ADDRESS_EXPIRY:
665		default:
666			plog(ASL_LEVEL_WARNING,
667			     "Ignored attribute %s\n",
668			     s_isakmp_cfg_type(type));
669			break;
670		}
671
672		npp = (char *)attr;
673		attr = (struct isakmp_data *)(npp + sizeof(*attr) + alen);
674		tlen -= (sizeof(*attr) + alen);
675
676		if (reply_attr != NULL) {
677			payload = buffer_cat(payload, reply_attr);
678			vfree(reply_attr);
679		}
680	}
681
682	reply = (struct isakmp_pl_attr *)payload->v;
683	reply->h.len = htons(payload->l);
684	reply->type = ISAKMP_CFG_REPLY;
685	reply->id = attrpl->id;
686
687	plog(ASL_LEVEL_DEBUG,
688		    "Sending MODE_CFG REPLY\n");
689
690	error = isakmp_cfg_send(iph1, payload,
691	    ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 0, 0, msg);
692
693
694end:
695	vfree(payload);
696
697	return error;
698}
699
700int
701isakmp_cfg_set(iph1, attrpl, msg)
702	phase1_handle_t *iph1;
703	struct isakmp_pl_attr *attrpl;
704    vchar_t *msg;
705{
706	struct isakmp_data *attr;
707	int tlen;
708	size_t alen;
709	char *npp;
710	vchar_t *payload;
711	struct isakmp_pl_attr *reply;
712	vchar_t *reply_attr;
713	int type;
714	int error = -1;
715
716	if ((payload = vmalloc(sizeof(*reply))) == NULL) {
717		plog(ASL_LEVEL_ERR, "Cannot allocate memory\n");
718		return -1;
719	}
720	memset(payload->v, 0, sizeof(*reply));
721
722	tlen = ntohs(attrpl->h.len);
723	attr = (struct isakmp_data *)(attrpl + 1);
724	tlen -= sizeof(*attrpl);
725
726	/*
727	 * We should send ack for the attributes we accepted
728	 */
729	while (tlen > 0) {
730		reply_attr = NULL;
731		type = ntohs(attr->type);
732
733		plog(ASL_LEVEL_DEBUG,
734		     "Attribute %s\n",
735		     s_isakmp_cfg_type(type & ~ISAKMP_GEN_MASK));
736
737		switch (type & ~ISAKMP_GEN_MASK) {
738		case XAUTH_STATUS:
739			reply_attr = isakmp_xauth_set(iph1, attr);
740			break;
741		default:
742			plog(ASL_LEVEL_DEBUG,
743			     "Unexpected SET attribute %s\n",
744		     	     s_isakmp_cfg_type(type & ~ISAKMP_GEN_MASK));
745			break;
746		}
747
748		if (reply_attr != NULL) {
749			payload = buffer_cat(payload, reply_attr);
750			vfree(reply_attr);
751		}
752
753		/*
754		 * Move to next attribute. If we run out of the packet,
755		 * tlen becomes negative and we exit.
756		 */
757		if ((type & ISAKMP_GEN_MASK) == ISAKMP_GEN_TV) {
758			tlen -= sizeof(*attr);
759			attr++;
760		} else {
761			alen = ntohs(attr->lorv);
762			tlen -= (sizeof(*attr) + alen);
763			npp = (char *)attr;
764			attr = (struct isakmp_data *)
765			    (npp + sizeof(*attr) + alen);
766		}
767	}
768
769	reply = (struct isakmp_pl_attr *)payload->v;
770	reply->h.len = htons(payload->l);
771	reply->type = ISAKMP_CFG_ACK;
772	reply->id = attrpl->id;
773
774	plog(ASL_LEVEL_DEBUG,
775		     "Sending MODE_CFG ACK\n");
776
777	error = isakmp_cfg_send(iph1, payload,
778	    ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 0, 0, msg);
779
780	if (iph1->mode_cfg->flags & ISAKMP_CFG_DELETE_PH1) {
781		if (FSM_STATE_IS_ESTABLISHED(iph1->status))
782			isakmp_info_send_d1(iph1);
783		isakmp_ph1expire(iph1);
784		iph1 = NULL;
785	}
786	vfree(payload);
787
788	/*
789	 * If required, request ISAKMP mode config information: ignore rekeys
790	 */
791	if ((iph1 != NULL) && (!iph1->is_rekey) && (iph1->rmconf->mode_cfg) && (error == 0))
792		error = isakmp_cfg_getconfig(iph1);
793
794	return error;
795}
796
797
798static vchar_t *
799buffer_cat(s, append)
800	vchar_t *s;
801	vchar_t *append;
802{
803	vchar_t *new;
804
805	new = vmalloc(s->l + append->l);
806	if (new == NULL) {
807		plog(ASL_LEVEL_ERR,
808		    "Cannot allocate memory\n");
809		return s;
810	}
811
812	memcpy(new->v, s->v, s->l);
813	memcpy(new->v + s->l, append->v, append->l);
814
815	vfree(s);
816	return new;
817}
818
819static vchar_t *
820isakmp_cfg_net(iph1, attr)
821	phase1_handle_t *iph1;
822	struct isakmp_data *attr;
823{
824	int type;
825	int confsource;
826
827	type = ntohs(attr->type);
828
829	/*
830	 * Don't give an address to a peer that did not succeed Xauth
831	 */
832	if (xauth_check(iph1) != 0) {
833		plog(ASL_LEVEL_ERR,
834		    "Attempt to start phase config whereas Xauth failed\n");
835		return NULL;
836	}
837
838	confsource = isakmp_cfg_config.confsource;
839	/*
840	 * If we have to fall back to a local
841	 * configuration source, we will jump
842	 * back to this point.
843	 */
844
845	switch(type) {
846	case INTERNAL_IP4_ADDRESS:
847		switch(confsource) {
848		case ISAKMP_CFG_CONF_LOCAL:
849			if (isakmp_cfg_getport(iph1) == -1) {
850				plog(ASL_LEVEL_ERR,
851				    "Port pool depleted\n");
852				break;
853			}
854
855			iph1->mode_cfg->addr4.s_addr =
856			    htonl(ntohl(isakmp_cfg_config.network4)
857			    + iph1->mode_cfg->port);
858			iph1->mode_cfg->flags |= ISAKMP_CFG_ADDR4_LOCAL;
859			break;
860
861		default:
862			plog(ASL_LEVEL_ERR,
863			    "Unexpected confsource\n");
864		}
865
866		return isakmp_cfg_addr4(iph1,
867		    attr, &iph1->mode_cfg->addr4.s_addr);
868		break;
869
870	case INTERNAL_IP4_NETMASK:
871		switch(confsource) {
872		case ISAKMP_CFG_CONF_LOCAL:
873			iph1->mode_cfg->mask4.s_addr
874			    = isakmp_cfg_config.netmask4;
875			iph1->mode_cfg->flags |= ISAKMP_CFG_MASK4_LOCAL;
876			break;
877
878		default:
879			plog(ASL_LEVEL_ERR,
880			    "Unexpected confsource\n");
881		}
882		return isakmp_cfg_addr4(iph1, attr,
883		    &iph1->mode_cfg->mask4.s_addr);
884		break;
885
886	case INTERNAL_IP4_DNS:
887		return isakmp_cfg_addr4_list(iph1,
888		    attr, &isakmp_cfg_config.dns4[0],
889		    isakmp_cfg_config.dns4_index);
890		break;
891
892	case INTERNAL_IP4_NBNS:
893		return isakmp_cfg_addr4_list(iph1,
894		    attr, &isakmp_cfg_config.nbns4[0],
895		    isakmp_cfg_config.nbns4_index);
896		break;
897
898	case INTERNAL_IP4_SUBNET:
899		return isakmp_cfg_addr4(iph1,
900		    attr, &isakmp_cfg_config.network4);
901		break;
902
903	default:
904		plog(ASL_LEVEL_ERR, "Unexpected type %d\n", type);
905		break;
906	}
907	return NULL;
908}
909
910#if 0
911static vchar_t *
912isakmp_cfg_void(iph1, attr)
913	phase1_handle_t *iph1;
914	struct isakmp_data *attr;
915{
916	vchar_t *buffer;
917	struct isakmp_data *new;
918
919	if ((buffer = vmalloc(sizeof(*attr))) == NULL) {
920		plog(ASL_LEVEL_ERR, "Cannot allocate memory\n");
921		return NULL;
922	}
923
924	new = (struct isakmp_data *)buffer->v;
925
926	new->type = attr->type;
927	new->lorv = htons(0);
928
929	return buffer;
930}
931#endif
932
933vchar_t *
934isakmp_cfg_copy(iph1, attr)
935	phase1_handle_t *iph1;
936	struct isakmp_data *attr;
937{
938	vchar_t *buffer;
939	size_t len = 0;
940
941	if ((ntohs(attr->type) & ISAKMP_GEN_MASK) == ISAKMP_GEN_TLV)
942		len = ntohs(attr->lorv);
943
944	if ((buffer = vmalloc(sizeof(*attr) + len)) == NULL) {
945		plog(ASL_LEVEL_ERR, "Cannot allocate memory\n");
946		return NULL;
947	}
948
949	memcpy(buffer->v, attr, sizeof(*attr) + ntohs(attr->lorv));
950
951	return buffer;
952}
953
954vchar_t *
955isakmp_cfg_short(iph1, attr, value)
956	phase1_handle_t *iph1;
957	struct isakmp_data *attr;
958	int value;
959{
960	vchar_t *buffer;
961	struct isakmp_data *new;
962	int type;
963
964	if ((buffer = vmalloc(sizeof(*attr))) == NULL) {
965		plog(ASL_LEVEL_ERR, "Cannot allocate memory\n");
966		return NULL;
967	}
968
969	new = (struct isakmp_data *)buffer->v;
970	type = ntohs(attr->type) & ~ISAKMP_GEN_MASK;
971
972	new->type = htons(type | ISAKMP_GEN_TV);
973	new->lorv = htons(value);
974
975	return buffer;
976}
977
978vchar_t *
979isakmp_cfg_varlen(iph1, attr, string, len)
980	phase1_handle_t *iph1;
981	struct isakmp_data *attr;
982	char *string;
983	size_t len;
984{
985	vchar_t *buffer;
986	struct isakmp_data *new;
987	char *data;
988
989	if ((buffer = vmalloc(sizeof(*attr) + len)) == NULL) {
990		plog(ASL_LEVEL_ERR, "Cannot allocate memory\n");
991		return NULL;
992	}
993
994	new = (struct isakmp_data *)buffer->v;
995
996	new->type = attr->type;
997	new->lorv = htons(len);
998	data = (char *)(new + 1);
999
1000	memcpy(data, string, len);
1001
1002	return buffer;
1003}
1004vchar_t *
1005isakmp_cfg_string(iph1, attr, string)
1006	phase1_handle_t *iph1;
1007	struct isakmp_data *attr;
1008	char *string;
1009{
1010	size_t len = strlen(string);
1011	return isakmp_cfg_varlen(iph1, attr, string, len);
1012}
1013
1014static vchar_t *
1015isakmp_cfg_addr4(iph1, attr, addr)
1016	phase1_handle_t *iph1;
1017	struct isakmp_data *attr;
1018	in_addr_t *addr;
1019{
1020	vchar_t *buffer;
1021	struct isakmp_data *new;
1022	size_t len;
1023
1024	len = sizeof(*addr);
1025	if ((buffer = vmalloc(sizeof(*attr) + len)) == NULL) {
1026		plog(ASL_LEVEL_ERR, "Cannot allocate memory\n");
1027		return NULL;
1028	}
1029
1030	new = (struct isakmp_data *)buffer->v;
1031
1032	new->type = attr->type;
1033	new->lorv = htons(len);
1034	memcpy(new + 1, addr, len);
1035
1036	return buffer;
1037}
1038
1039static vchar_t *
1040isakmp_cfg_addr4_list(iph1, attr, addr, nbr)
1041	phase1_handle_t *iph1;
1042	struct isakmp_data *attr;
1043	in_addr_t *addr;
1044	int nbr;
1045{
1046	int error = -1;
1047	vchar_t *buffer = NULL;
1048	vchar_t *bufone = NULL;
1049	struct isakmp_data *new;
1050	size_t len;
1051	int i;
1052
1053	len = sizeof(*addr);
1054	if ((buffer = vmalloc(0)) == NULL) {
1055		plog(ASL_LEVEL_ERR, "Cannot allocate memory\n");
1056		goto out;
1057	}
1058	for(i = 0; i < nbr; i++) {
1059		if ((bufone = vmalloc(sizeof(*attr) + len)) == NULL) {
1060			plog(ASL_LEVEL_ERR,
1061			    "Cannot allocate memory\n");
1062			goto out;
1063		}
1064		new = (struct isakmp_data *)bufone->v;
1065		new->type = attr->type;
1066		new->lorv = htons(len);
1067		memcpy(new + 1, &addr[i], len);
1068		new += (len + sizeof(*attr));
1069		buffer = buffer_cat(buffer, bufone);
1070		vfree(bufone);
1071	}
1072
1073	error = 0;
1074
1075out:
1076	if ((error != 0) && (buffer != NULL)) {
1077		vfree(buffer);
1078		buffer = NULL;
1079	}
1080
1081	return buffer;
1082}
1083
1084struct isakmp_ivm *
1085isakmp_cfg_newiv(iph1, msgid)
1086	phase1_handle_t *iph1;
1087	u_int32_t msgid;
1088{
1089	struct isakmp_cfg_state *ics = iph1->mode_cfg;
1090
1091	if (ics == NULL) {
1092		plog(ASL_LEVEL_ERR,
1093		    "isakmp_cfg_newiv called without mode config state\n");
1094		return NULL;
1095	}
1096
1097	if (ics->ivm != NULL)
1098		oakley_delivm(ics->ivm);
1099
1100	ics->ivm = oakley_newiv2(iph1, msgid);
1101	ics->last_msgid = msgid;
1102
1103	return ics->ivm;
1104}
1105
1106/* Derived from isakmp_info_send_common */
1107int
1108isakmp_cfg_send(iph1, payload, np, flags, new_exchange, retry_count, msg)
1109	phase1_handle_t *iph1;
1110	vchar_t *payload;
1111	u_int32_t np;
1112	int flags;
1113	int new_exchange;
1114	int retry_count;
1115    vchar_t *msg;
1116{
1117	phase2_handle_t *iph2 = NULL;
1118	vchar_t *hash = NULL;
1119	struct isakmp *isakmp;
1120	struct isakmp_gen *gen;
1121	char *p;
1122	int tlen;
1123	int error = -1;
1124	struct isakmp_cfg_state *ics = iph1->mode_cfg;
1125
1126	/* Check if phase 1 is established */
1127	if ((!FSM_STATE_IS_ESTABLISHED(iph1->status)) ||
1128	    (iph1->local == NULL) ||
1129	    (iph1->remote == NULL)) {
1130		plog(ASL_LEVEL_ERR,
1131		    "ISAKMP mode config exchange with immature phase 1\n");
1132		goto end;
1133	}
1134
1135	/* add new entry to isakmp status table */
1136	iph2 = ike_session_newph2(ISAKMP_VERSION_NUMBER_IKEV1, PHASE2_TYPE_CFG);
1137	if (iph2 == NULL) {
1138		plog(ASL_LEVEL_ERR,
1139			 "failed to allocate ph2");
1140		goto end;
1141	}
1142
1143	iph2->dst = dupsaddr(iph1->remote);
1144	if (iph2->dst == NULL) {
1145		plog(ASL_LEVEL_ERR,
1146			 "failed to duplicate remote address");
1147		ike_session_delph2(iph2);
1148		goto end;
1149	}
1150	iph2->src = dupsaddr(iph1->local);
1151	if (iph2->src == NULL) {
1152		plog(ASL_LEVEL_ERR,
1153			 "failed to duplicate local address");
1154		ike_session_delph2(iph2);
1155		goto end;
1156	}
1157
1158	switch (iph1->remote->ss_family) {
1159	case AF_INET:
1160#if (!defined(ENABLE_NATT)) || (defined(BROKEN_NATT))
1161		((struct sockaddr_in *)iph2->dst)->sin_port = 0;
1162		((struct sockaddr_in *)iph2->src)->sin_port = 0;
1163#endif
1164		break;
1165#ifdef INET6
1166	case AF_INET6:
1167#if (!defined(ENABLE_NATT)) || (defined(BROKEN_NATT))
1168		((struct sockaddr_in6 *)iph2->dst)->sin6_port = 0;
1169		((struct sockaddr_in6 *)iph2->src)->sin6_port = 0;
1170#endif
1171		break;
1172#endif
1173	default:
1174		plog(ASL_LEVEL_ERR,
1175			"invalid family: %d\n", iph1->remote->ss_family);
1176		ike_session_delph2(iph2);
1177		goto end;
1178	}
1179	iph2->side = INITIATOR;
1180	fsm_set_state(&iph2->status, IKEV1_STATE_INFO);
1181
1182	if (new_exchange)
1183		iph2->msgid = isakmp_newmsgid2(iph1);
1184	else
1185		iph2->msgid = iph1->msgid;
1186
1187	/* get IV and HASH(1) if skeyid_a was generated. */
1188	if (iph1->skeyid_a != NULL) {
1189		if (new_exchange) {
1190			if (isakmp_cfg_newiv(iph1, iph2->msgid) == NULL) {
1191				plog(ASL_LEVEL_ERR,
1192					 "failed to generate IV");
1193				ike_session_delph2(iph2);
1194				goto end;
1195			}
1196		}
1197
1198		/* generate HASH(1) */
1199		hash = oakley_compute_hash1(iph1, iph2->msgid, payload);
1200		if (hash == NULL) {
1201			plog(ASL_LEVEL_ERR,
1202				 "failed to generate HASH");
1203			ike_session_delph2(iph2);
1204			goto end;
1205		}
1206
1207		/* initialized total buffer length */
1208		tlen = hash->l;
1209		tlen += sizeof(*gen);
1210	} else {
1211		/* IKE-SA is not established */
1212		hash = NULL;
1213
1214		/* initialized total buffer length */
1215		tlen = 0;
1216	}
1217	if ((flags & ISAKMP_FLAG_A) == 0)
1218		iph2->flags = (hash == NULL ? 0 : ISAKMP_FLAG_E);
1219	else
1220		iph2->flags = (hash == NULL ? 0 : ISAKMP_FLAG_A);
1221
1222	ike_session_link_ph2_to_ph1(iph1, iph2);
1223
1224	tlen += sizeof(*isakmp) + payload->l;
1225
1226	/* create buffer for isakmp payload */
1227	iph2->sendbuf = vmalloc(tlen);
1228	if (iph2->sendbuf == NULL) {
1229		plog(ASL_LEVEL_ERR,
1230			"failed to get buffer to send.\n");
1231		goto err;
1232	}
1233
1234	/* create isakmp header */
1235	isakmp = (struct isakmp *)iph2->sendbuf->v;
1236	memcpy(&isakmp->i_ck, &iph1->index.i_ck, sizeof(cookie_t));
1237	memcpy(&isakmp->r_ck, &iph1->index.r_ck, sizeof(cookie_t));
1238	isakmp->np = hash == NULL ? (np & 0xff) : ISAKMP_NPTYPE_HASH;
1239	isakmp->v = iph1->version;
1240	isakmp->etype = ISAKMP_ETYPE_CFG;
1241	isakmp->flags = iph2->flags;
1242	memcpy(&isakmp->msgid, &iph2->msgid, sizeof(isakmp->msgid));
1243	isakmp->len = htonl(tlen);
1244	p = (char *)(isakmp + 1);
1245
1246	/* create HASH payload */
1247	if (hash != NULL) {
1248		gen = (struct isakmp_gen *)p;
1249		gen->np = np & 0xff;
1250		gen->len = htons(sizeof(*gen) + hash->l);
1251		p += sizeof(*gen);
1252		memcpy(p, hash->v, hash->l);
1253		p += hash->l;
1254	}
1255
1256	/* add payload */
1257	memcpy(p, payload->v, payload->l);
1258	p += payload->l;
1259
1260#ifdef HAVE_PRINT_ISAKMP_C
1261	isakmp_printpacket(iph2->sendbuf, iph1->local, iph1->remote, 1);
1262#endif
1263
1264	plog(ASL_LEVEL_DEBUG, "MODE_CFG packet to send\n");
1265
1266	/* encoding */
1267	if (ISSET(isakmp->flags, ISAKMP_FLAG_E)) {
1268		vchar_t *tmp;
1269
1270		tmp = oakley_do_encrypt(iph1, iph2->sendbuf,
1271			ics->ivm->ive, ics->ivm->iv);
1272		VPTRINIT(iph2->sendbuf);
1273		if (tmp == NULL) {
1274			plog(ASL_LEVEL_ERR,
1275				 "failed to encrypt packet");
1276			goto err;
1277		}
1278		iph2->sendbuf = tmp;
1279	}
1280
1281	/* HDR*, HASH(1), ATTR */
1282
1283	if (retry_count > 0) {
1284		iph2->retry_counter = retry_count;
1285		if (isakmp_ph2resend(iph2) < 0) {
1286			plog(ASL_LEVEL_ERR,
1287				 "failed to resend packet");
1288			VPTRINIT(iph2->sendbuf);
1289			goto err;
1290		}
1291		IPSECSESSIONTRACEREVENT(iph1->parent_session,
1292								IPSECSESSIONEVENTCODE_IKEV1_CFG_RETRANSMIT,
1293								CONSTSTR("Mode-Config retransmit"),
1294								CONSTSTR(NULL));
1295		error = 0;
1296		goto end;
1297	}
1298
1299	if (isakmp_send(iph2->ph1, iph2->sendbuf) < 0) {
1300		plog(ASL_LEVEL_ERR,
1301			 "failed to send packet");
1302		VPTRINIT(iph2->sendbuf);
1303		goto err;
1304	}
1305       if (msg) {
1306               /* the sending message is added to the received-list. */
1307               if (ike_session_add_recvdpkt(iph1->remote, iph1->local, iph2->sendbuf, msg,
1308                                PH2_NON_ESP_EXTRA_LEN(iph2, iph2->sendbuf), PH1_FRAG_FLAGS(iph1)) == -1) {
1309                       plog(ASL_LEVEL_ERR ,
1310                            "failed to add a response packet to the tree.\n");
1311               }
1312       }
1313
1314	plog(ASL_LEVEL_DEBUG,
1315		"sendto mode config %s.\n", s_isakmp_nptype(np));
1316
1317	/*
1318	 * XXX We might need to resend the message...
1319	 */
1320
1321	error = 0;
1322	VPTRINIT(iph2->sendbuf);
1323
1324	IPSECSESSIONTRACEREVENT(iph1->parent_session,
1325							IPSECSESSIONEVENTCODE_IKE_PACKET_TX_SUCC,
1326							CONSTSTR("Mode-Config message"),
1327							CONSTSTR(NULL));
1328
1329err:
1330	if (error) {
1331		IPSECSESSIONTRACEREVENT(iph1->parent_session,
1332								IPSECSESSIONEVENTCODE_IKE_PACKET_TX_FAIL,
1333								CONSTSTR("Mode-Config message"),
1334								CONSTSTR("Failed to transmit Mode-Config message"));
1335	}
1336	ike_session_unlink_phase2(iph2);
1337end:
1338	if (hash)
1339		vfree(hash);
1340	return error;
1341}
1342
1343
1344void
1345isakmp_cfg_rmstate(phase1_handle_t *iph1)
1346{
1347	struct isakmp_cfg_state **state = &iph1->mode_cfg;
1348
1349
1350    if (*state == NULL)
1351        return;
1352
1353	if ((*state)->flags & ISAKMP_CFG_PORT_ALLOCATED)
1354		isakmp_cfg_putport(iph1, (*state)->port);
1355
1356	/* Delete the IV if it's still there */
1357	if((*state)->ivm) {
1358		oakley_delivm((*state)->ivm);
1359		(*state)->ivm = NULL;
1360	}
1361
1362	/* Free any allocated splitnet lists */
1363	if((*state)->split_include != NULL)
1364		splitnet_list_free((*state)->split_include,
1365                           &(*state)->include_count);
1366	if((*state)->split_local != NULL)
1367		splitnet_list_free((*state)->split_local,
1368                           &(*state)->local_count);
1369
1370	xauth_rmstate(&(*state)->xauth);
1371
1372	if ((*state)->attr_list)
1373		vfree((*state)->attr_list);
1374
1375	racoon_free((*state));
1376	(*state) = NULL;
1377
1378	return;
1379}
1380
1381struct isakmp_cfg_state *
1382isakmp_cfg_mkstate(void)
1383{
1384	struct isakmp_cfg_state *state;
1385
1386	if ((state = racoon_malloc(sizeof(*state))) == NULL) {
1387		plog(ASL_LEVEL_ERR,
1388		    "Cannot allocate memory for mode config state\n");
1389		return NULL;
1390	}
1391	memset(state, 0, sizeof(*state));
1392
1393	return state;
1394}
1395
1396int
1397isakmp_cfg_getport(iph1)
1398	phase1_handle_t *iph1;
1399{
1400	unsigned int i;
1401	size_t size = isakmp_cfg_config.pool_size;
1402
1403	if (iph1->mode_cfg->flags & ISAKMP_CFG_PORT_ALLOCATED)
1404		return iph1->mode_cfg->port;
1405
1406	if (isakmp_cfg_config.port_pool == NULL) {
1407		plog(ASL_LEVEL_ERR,
1408		    "isakmp_cfg_config.port_pool == NULL\n");
1409		return -1;
1410	}
1411
1412	for (i = 0; i < size; i++) {
1413		if (isakmp_cfg_config.port_pool[i].used == 0)
1414			break;
1415	}
1416
1417	if (i == size) {
1418		plog(ASL_LEVEL_ERR,
1419		    "No more addresses available\n");
1420			return -1;
1421	}
1422
1423	isakmp_cfg_config.port_pool[i].used = 1;
1424
1425	plog(ASL_LEVEL_INFO, "Using port %d\n", i);
1426
1427	iph1->mode_cfg->flags |= ISAKMP_CFG_PORT_ALLOCATED;
1428	iph1->mode_cfg->port = i;
1429
1430	return i;
1431}
1432
1433int
1434isakmp_cfg_putport(iph1, index)
1435	phase1_handle_t *iph1;
1436	unsigned int index;
1437{
1438	if (isakmp_cfg_config.port_pool == NULL) {
1439		plog(ASL_LEVEL_ERR,
1440		    "isakmp_cfg_config.port_pool == NULL\n");
1441		return -1;
1442	}
1443
1444	if (isakmp_cfg_config.port_pool[index].used == 0) {
1445		plog(ASL_LEVEL_ERR,
1446		    "Attempt to release an unallocated address (port %d)\n",
1447		    index);
1448		return -1;
1449	}
1450
1451	isakmp_cfg_config.port_pool[index].used = 0;
1452	iph1->mode_cfg->flags &= ISAKMP_CFG_PORT_ALLOCATED;
1453
1454	plog(ASL_LEVEL_INFO, "Released port %d\n", index);
1455
1456	return 0;
1457}
1458
1459
1460int
1461isakmp_cfg_getconfig(iph1)
1462	phase1_handle_t *iph1;
1463{
1464	vchar_t *buffer;
1465	struct isakmp_pl_attr *attrpl;
1466	struct isakmp_data *attr;
1467	size_t len;
1468	vchar_t *version = NULL;
1469	int error;
1470	int attrcount;
1471	int i;
1472	int attrlist[] = {
1473		INTERNAL_IP4_ADDRESS,
1474		INTERNAL_IP4_NETMASK,
1475		INTERNAL_IP4_DNS,
1476		INTERNAL_IP4_NBNS,
1477		INTERNAL_ADDRESS_EXPIRY,
1478		APPLICATION_VERSION,
1479		UNITY_BANNER,
1480		UNITY_DEF_DOMAIN,
1481		UNITY_SPLITDNS_NAME,
1482		UNITY_SPLIT_INCLUDE,
1483		UNITY_LOCAL_LAN,
1484	};
1485
1486	attrcount = sizeof(attrlist) / sizeof(*attrlist);
1487	len = sizeof(*attrpl) + sizeof(*attr) * attrcount;
1488
1489	if (iph1->started_by_api) {
1490		if (iph1->remote->ss_family == AF_INET) {
1491			struct vpnctl_socket_elem *sock_elem;
1492			struct bound_addr *bound_addr;
1493			u_int32_t address;
1494
1495			address = ((struct sockaddr_in *)iph1->remote)->sin_addr.s_addr;
1496			LIST_FOREACH(sock_elem, &lcconf->vpnctl_comm_socks, chain) {
1497				LIST_FOREACH(bound_addr, &sock_elem->bound_addresses, chain) {
1498					if (bound_addr->address == address) {
1499						if ((version = bound_addr->version))
1500							len += bound_addr->version->l;
1501						break;
1502					}
1503				}
1504			}
1505		}
1506	}
1507
1508	if ((buffer = vmalloc(len)) == NULL) {
1509		plog(ASL_LEVEL_ERR, "Cannot allocate memory\n");
1510		return -1;
1511	}
1512
1513	attrpl = (struct isakmp_pl_attr *)buffer->v;
1514	attrpl->h.len = htons(len);
1515	attrpl->type = ISAKMP_CFG_REQUEST;
1516	attrpl->id = htons((u_int16_t)(eay_random() & 0xffff));
1517
1518	attr = (struct isakmp_data *)(attrpl + 1);
1519
1520	for (i = 0; i < attrcount; i++) {
1521		switch (attrlist[i]) {
1522			case APPLICATION_VERSION:
1523				if (version) {
1524					attr->type = htons(attrlist[i]);
1525					attr->lorv = htons(version->l);
1526					memcpy(attr + 1, version->v, version->l);
1527					attr = (struct isakmp_data *)(((char *)(attr + 1)) + version->l);
1528					break;
1529				} else /* fall thru */;
1530			default:
1531				attr->type = htons(attrlist[i]);
1532				attr->lorv = htons(0);
1533				attr++;
1534				break;
1535		}
1536	}
1537
1538	plog(ASL_LEVEL_DEBUG,
1539		    "Sending MODE_CFG REQUEST\n");
1540
1541	error = isakmp_cfg_send(iph1, buffer,
1542	    ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 1, iph1->rmconf->retry_counter, NULL);
1543
1544	vfree(buffer);
1545
1546	IPSECLOGASLMSG("IPSec Network Configuration requested.\n");
1547
1548	return error;
1549}
1550
1551static void
1552isakmp_cfg_getaddr4(attr, ip)
1553	struct isakmp_data *attr;
1554	struct in_addr *ip;
1555{
1556	size_t alen = ntohs(attr->lorv);
1557	in_addr_t *addr;
1558
1559	if (alen != sizeof(*ip)) {
1560		plog(ASL_LEVEL_ERR, "Bad IPv4 address len\n");
1561		return;
1562	}
1563
1564	addr = ALIGNED_CAST(in_addr_t *)(attr + 1);     // Wcast-align fix (void*) - attr comes from packet data in a vchar_t
1565	ip->s_addr = *addr;
1566
1567	return;
1568}
1569
1570static void
1571isakmp_cfg_appendaddr4(attr, ip, num, max)
1572	struct isakmp_data *attr;
1573	struct in_addr *ip;
1574	int *num;
1575	int max;
1576{
1577	size_t alen = ntohs(attr->lorv);
1578	in_addr_t *addr;
1579
1580	if (alen != sizeof(*ip)) {
1581		plog(ASL_LEVEL_ERR, "Bad IPv4 address len\n");
1582		return;
1583	}
1584	if (*num == max) {
1585		plog(ASL_LEVEL_ERR, "Too many addresses given\n");
1586		return;
1587	}
1588
1589	addr = ALIGNED_CAST(in_addr_t *)(attr + 1);      // Wcast-align fix (void*) - attr comes from packet data in a vchar_t
1590	ip->s_addr = *addr;
1591	(*num)++;
1592
1593	return;
1594}
1595
1596static void
1597isakmp_cfg_getstring(attr, str)
1598	struct isakmp_data *attr;
1599	char *str;
1600{
1601	size_t alen = ntohs(attr->lorv);
1602	char *src;
1603	src = (char *)(attr + 1);
1604
1605	memcpy(str, src, (alen > MAXPATHLEN ? MAXPATHLEN : alen));
1606
1607	return;
1608}
1609
1610#define IP_MAX 40
1611
1612void
1613isakmp_cfg_iplist_to_str(dest, count, addr, withmask)
1614	char *dest;
1615	int count;
1616	void *addr;
1617	int withmask;
1618{
1619	int i;
1620	int p;
1621	int l;
1622	struct unity_network tmp;
1623	for(i = 0, p = 0; i < count; i++) {
1624		if(withmask == 1)
1625			l = sizeof(struct unity_network);
1626		else
1627			l = sizeof(struct in_addr);
1628		memcpy(&tmp, addr, l);
1629		addr += l;
1630		if((uint32_t)tmp.addr4.s_addr == 0)
1631			break;
1632
1633		inet_ntop(AF_INET, &tmp.addr4, dest + p, IP_MAX);
1634		p += strlen(dest + p);
1635		if(withmask == 1) {
1636			dest[p] = '/';
1637			p++;
1638			inet_ntop(AF_INET, &tmp.mask4, dest + p, IP_MAX);
1639			p += strlen(dest + p);
1640		}
1641		dest[p] = ' ';
1642		p++;
1643	}
1644	if(p > 0)
1645		dest[p-1] = '\0';
1646	else
1647		dest[0] = '\0';
1648}
1649
1650int
1651isakmp_cfg_resize_pool(size)
1652	int size;
1653{
1654	struct isakmp_cfg_port *new_pool;
1655	size_t len;
1656	int i;
1657
1658	if (size == isakmp_cfg_config.pool_size)
1659		return 0;
1660
1661	plog(ASL_LEVEL_INFO,
1662	    "Resize address pool from %zu to %d\n",
1663	    isakmp_cfg_config.pool_size, size);
1664
1665	/* If a pool already exists, check if we can shrink it */
1666	if ((isakmp_cfg_config.port_pool != NULL) &&
1667	    (size < isakmp_cfg_config.pool_size)) {
1668		for (i = isakmp_cfg_config.pool_size-1; i >= size; --i) {
1669			if (isakmp_cfg_config.port_pool[i].used) {
1670				plog(ASL_LEVEL_ERR,
1671				    "resize pool from %zu to %d impossible "
1672				    "port %d is in use\n",
1673				    isakmp_cfg_config.pool_size, size, i);
1674				size = i;
1675				break;
1676			}
1677		}
1678	}
1679
1680	len = size * sizeof(*isakmp_cfg_config.port_pool);
1681	new_pool = racoon_realloc(isakmp_cfg_config.port_pool, len);
1682	if (new_pool == NULL) {
1683		plog(ASL_LEVEL_ERR,
1684		    "resize pool from %zu to %d impossible: %s",
1685		    isakmp_cfg_config.pool_size, size, strerror(errno));
1686		return -1;
1687	}
1688
1689	/* If size increase, intialize correctly the new records */
1690	if (size > isakmp_cfg_config.pool_size) {
1691		size_t unit;
1692		size_t old_size;
1693
1694		unit =  sizeof(*isakmp_cfg_config.port_pool);
1695		old_size = isakmp_cfg_config.pool_size;
1696
1697		bzero((char *)new_pool + (old_size * unit),
1698		    (size - old_size) * unit);
1699	}
1700
1701	isakmp_cfg_config.port_pool = new_pool;
1702	isakmp_cfg_config.pool_size = size;
1703
1704	return 0;
1705}
1706
1707int
1708isakmp_cfg_init(cold)
1709	int cold;
1710{
1711	int i;
1712#if 0
1713	int error;
1714#endif
1715
1716	isakmp_cfg_config.network4 = (in_addr_t)0x00000000;
1717	isakmp_cfg_config.netmask4 = (in_addr_t)0x00000000;
1718	for (i = 0; i < MAXNS; i++)
1719		isakmp_cfg_config.dns4[i] = (in_addr_t)0x00000000;
1720	isakmp_cfg_config.dns4_index = 0;
1721	for (i = 0; i < MAXWINS; i++)
1722		isakmp_cfg_config.nbns4[i] = (in_addr_t)0x00000000;
1723	isakmp_cfg_config.nbns4_index = 0;
1724	if (cold != ISAKMP_CFG_INIT_COLD) {
1725		if (isakmp_cfg_config.port_pool) {
1726			racoon_free(isakmp_cfg_config.port_pool);
1727		}
1728	}
1729	isakmp_cfg_config.port_pool = NULL;
1730	isakmp_cfg_config.pool_size = 0;
1731	isakmp_cfg_config.authsource = ISAKMP_CFG_AUTH_SYSTEM;
1732	isakmp_cfg_config.groupsource = ISAKMP_CFG_GROUP_SYSTEM;
1733	if (cold != ISAKMP_CFG_INIT_COLD) {
1734		if (isakmp_cfg_config.grouplist != NULL) {
1735			for (i = 0; i < isakmp_cfg_config.groupcount; i++)
1736				racoon_free(isakmp_cfg_config.grouplist[i]);
1737			racoon_free(isakmp_cfg_config.grouplist);
1738		}
1739	}
1740	isakmp_cfg_config.grouplist = NULL;
1741	isakmp_cfg_config.groupcount = 0;
1742	isakmp_cfg_config.confsource = ISAKMP_CFG_CONF_LOCAL;
1743	isakmp_cfg_config.accounting = ISAKMP_CFG_ACCT_NONE;
1744	isakmp_cfg_config.auth_throttle = THROTTLE_PENALTY;
1745	strlcpy(isakmp_cfg_config.default_domain, ISAKMP_CFG_DEFAULT_DOMAIN,
1746	    sizeof(isakmp_cfg_config.default_domain));
1747	strlcpy(isakmp_cfg_config.motd, ISAKMP_CFG_MOTD, sizeof(isakmp_cfg_config.motd));
1748
1749	if (cold != ISAKMP_CFG_INIT_COLD )
1750		if (isakmp_cfg_config.splitnet_list != NULL)
1751			splitnet_list_free(isakmp_cfg_config.splitnet_list,
1752				&isakmp_cfg_config.splitnet_count);
1753	isakmp_cfg_config.splitnet_list = NULL;
1754	isakmp_cfg_config.splitnet_count = 0;
1755	isakmp_cfg_config.splitnet_type = 0;
1756
1757	isakmp_cfg_config.pfs_group = 0;
1758	isakmp_cfg_config.save_passwd = 0;
1759
1760	if (cold != ISAKMP_CFG_INIT_COLD )
1761		if (isakmp_cfg_config.splitdns_list != NULL)
1762			racoon_free(isakmp_cfg_config.splitdns_list);
1763	isakmp_cfg_config.splitdns_list = NULL;
1764	isakmp_cfg_config.splitdns_len = 0;
1765
1766#if 0
1767	if (cold == ISAKMP_CFG_INIT_COLD) {
1768		if ((error = isakmp_cfg_resize_pool(ISAKMP_CFG_MAX_CNX)) != 0)
1769			return error;
1770	}
1771#endif
1772
1773	return 0;
1774}
1775
1776