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    if (*state == NULL)
1350        return;
1351
1352	if ((*state)->flags & ISAKMP_CFG_PORT_ALLOCATED)
1353		isakmp_cfg_putport(iph1, (*state)->port);
1354
1355	/* Delete the IV if it's still there */
1356	if((*state)->ivm) {
1357		oakley_delivm((*state)->ivm);
1358		(*state)->ivm = NULL;
1359	}
1360
1361	/* Free any allocated splitnet lists */
1362	if((*state)->split_include != NULL)
1363		splitnet_list_free((*state)->split_include,
1364                           &(*state)->include_count);
1365	if((*state)->split_local != NULL)
1366		splitnet_list_free((*state)->split_local,
1367                           &(*state)->local_count);
1368
1369	xauth_rmstate(&(*state)->xauth);
1370
1371	if ((*state)->attr_list)
1372		vfree((*state)->attr_list);
1373
1374	racoon_free((*state));
1375	(*state) = NULL;
1376
1377	return;
1378}
1379
1380struct isakmp_cfg_state *
1381isakmp_cfg_mkstate(void)
1382{
1383	struct isakmp_cfg_state *state;
1384
1385	if ((state = racoon_malloc(sizeof(*state))) == NULL) {
1386		plog(ASL_LEVEL_ERR,
1387		    "Cannot allocate memory for mode config state\n");
1388		return NULL;
1389	}
1390	memset(state, 0, sizeof(*state));
1391
1392	return state;
1393}
1394
1395int
1396isakmp_cfg_getport(iph1)
1397	phase1_handle_t *iph1;
1398{
1399	unsigned int i;
1400	size_t size = isakmp_cfg_config.pool_size;
1401
1402	if (iph1->mode_cfg->flags & ISAKMP_CFG_PORT_ALLOCATED)
1403		return iph1->mode_cfg->port;
1404
1405	if (isakmp_cfg_config.port_pool == NULL) {
1406		plog(ASL_LEVEL_ERR,
1407		    "isakmp_cfg_config.port_pool == NULL\n");
1408		return -1;
1409	}
1410
1411	for (i = 0; i < size; i++) {
1412		if (isakmp_cfg_config.port_pool[i].used == 0)
1413			break;
1414	}
1415
1416	if (i == size) {
1417		plog(ASL_LEVEL_ERR,
1418		    "No more addresses available\n");
1419			return -1;
1420	}
1421
1422	isakmp_cfg_config.port_pool[i].used = 1;
1423
1424	plog(ASL_LEVEL_INFO, "Using port %d\n", i);
1425
1426	iph1->mode_cfg->flags |= ISAKMP_CFG_PORT_ALLOCATED;
1427	iph1->mode_cfg->port = i;
1428
1429	return i;
1430}
1431
1432int
1433isakmp_cfg_putport(iph1, index)
1434	phase1_handle_t *iph1;
1435	unsigned int index;
1436{
1437	if (isakmp_cfg_config.port_pool == NULL) {
1438		plog(ASL_LEVEL_ERR,
1439		    "isakmp_cfg_config.port_pool == NULL\n");
1440		return -1;
1441	}
1442
1443	if (isakmp_cfg_config.port_pool[index].used == 0) {
1444		plog(ASL_LEVEL_ERR,
1445		    "Attempt to release an unallocated address (port %d)\n",
1446		    index);
1447		return -1;
1448	}
1449
1450	isakmp_cfg_config.port_pool[index].used = 0;
1451	iph1->mode_cfg->flags &= ISAKMP_CFG_PORT_ALLOCATED;
1452
1453	plog(ASL_LEVEL_INFO, "Released port %d\n", index);
1454
1455	return 0;
1456}
1457
1458
1459int
1460isakmp_cfg_getconfig(iph1)
1461	phase1_handle_t *iph1;
1462{
1463	vchar_t *buffer;
1464	struct isakmp_pl_attr *attrpl;
1465	struct isakmp_data *attr;
1466	size_t len;
1467	vchar_t *version = NULL;
1468	int error;
1469	int attrcount;
1470	int i;
1471	int attrlist[] = {
1472		INTERNAL_IP4_ADDRESS,
1473		INTERNAL_IP4_NETMASK,
1474		INTERNAL_IP4_DNS,
1475		INTERNAL_IP4_NBNS,
1476		INTERNAL_ADDRESS_EXPIRY,
1477		APPLICATION_VERSION,
1478		UNITY_BANNER,
1479		UNITY_DEF_DOMAIN,
1480		UNITY_SPLITDNS_NAME,
1481		UNITY_SPLIT_INCLUDE,
1482		UNITY_LOCAL_LAN,
1483	};
1484
1485	attrcount = sizeof(attrlist) / sizeof(*attrlist);
1486	len = sizeof(*attrpl) + sizeof(*attr) * attrcount;
1487
1488	if (iph1->started_by_api) {
1489		if (iph1->remote->ss_family == AF_INET) {
1490			struct vpnctl_socket_elem *sock_elem;
1491			struct bound_addr *bound_addr;
1492			u_int32_t address;
1493
1494			address = ((struct sockaddr_in *)iph1->remote)->sin_addr.s_addr;
1495			LIST_FOREACH(sock_elem, &lcconf->vpnctl_comm_socks, chain) {
1496				LIST_FOREACH(bound_addr, &sock_elem->bound_addresses, chain) {
1497					if (bound_addr->address == address) {
1498						if ((version = bound_addr->version))
1499							len += bound_addr->version->l;
1500						break;
1501					}
1502				}
1503			}
1504		}
1505	}
1506
1507	if ((buffer = vmalloc(len)) == NULL) {
1508		plog(ASL_LEVEL_ERR, "Cannot allocate memory\n");
1509		return -1;
1510	}
1511
1512	attrpl = (struct isakmp_pl_attr *)buffer->v;
1513	attrpl->h.len = htons(len);
1514	attrpl->type = ISAKMP_CFG_REQUEST;
1515	attrpl->id = htons((u_int16_t)(eay_random() & 0xffff));
1516
1517	attr = (struct isakmp_data *)(attrpl + 1);
1518
1519	for (i = 0; i < attrcount; i++) {
1520		switch (attrlist[i]) {
1521			case APPLICATION_VERSION:
1522				if (version) {
1523					attr->type = htons(attrlist[i]);
1524					attr->lorv = htons(version->l);
1525					memcpy(attr + 1, version->v, version->l);
1526					attr = (struct isakmp_data *)(((char *)(attr + 1)) + version->l);
1527					break;
1528				} else /* fall thru */;
1529			default:
1530				attr->type = htons(attrlist[i]);
1531				attr->lorv = htons(0);
1532				attr++;
1533				break;
1534		}
1535	}
1536
1537	plog(ASL_LEVEL_DEBUG,
1538		    "Sending MODE_CFG REQUEST\n");
1539
1540	error = isakmp_cfg_send(iph1, buffer,
1541	    ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 1, iph1->rmconf->retry_counter, NULL);
1542
1543	vfree(buffer);
1544
1545	IPSECLOGASLMSG("IPSec Network Configuration requested.\n");
1546
1547	return error;
1548}
1549
1550static void
1551isakmp_cfg_getaddr4(attr, ip)
1552	struct isakmp_data *attr;
1553	struct in_addr *ip;
1554{
1555	size_t alen = ntohs(attr->lorv);
1556	in_addr_t *addr;
1557
1558	if (alen != sizeof(*ip)) {
1559		plog(ASL_LEVEL_ERR, "Bad IPv4 address len\n");
1560		return;
1561	}
1562
1563	addr = ALIGNED_CAST(in_addr_t *)(attr + 1);     // Wcast-align fix (void*) - attr comes from packet data in a vchar_t
1564	ip->s_addr = *addr;
1565
1566	return;
1567}
1568
1569static void
1570isakmp_cfg_appendaddr4(attr, ip, num, max)
1571	struct isakmp_data *attr;
1572	struct in_addr *ip;
1573	int *num;
1574	int max;
1575{
1576	size_t alen = ntohs(attr->lorv);
1577	in_addr_t *addr;
1578
1579	if (alen != sizeof(*ip)) {
1580		plog(ASL_LEVEL_ERR, "Bad IPv4 address len\n");
1581		return;
1582	}
1583	if (*num == max) {
1584		plog(ASL_LEVEL_ERR, "Too many addresses given\n");
1585		return;
1586	}
1587
1588	addr = ALIGNED_CAST(in_addr_t *)(attr + 1);      // Wcast-align fix (void*) - attr comes from packet data in a vchar_t
1589	ip->s_addr = *addr;
1590	(*num)++;
1591
1592	return;
1593}
1594
1595static void
1596isakmp_cfg_getstring(attr, str)
1597	struct isakmp_data *attr;
1598	char *str;
1599{
1600	size_t alen = ntohs(attr->lorv);
1601	char *src;
1602	src = (char *)(attr + 1);
1603
1604	memcpy(str, src, (alen > MAXPATHLEN ? MAXPATHLEN : alen));
1605
1606	return;
1607}
1608
1609#define IP_MAX 40
1610
1611void
1612isakmp_cfg_iplist_to_str(dest, count, addr, withmask)
1613	char *dest;
1614	int count;
1615	void *addr;
1616	int withmask;
1617{
1618	int i;
1619	int p;
1620	int l;
1621	struct unity_network tmp;
1622	for(i = 0, p = 0; i < count; i++) {
1623		if(withmask == 1)
1624			l = sizeof(struct unity_network);
1625		else
1626			l = sizeof(struct in_addr);
1627		memcpy(&tmp, addr, l);
1628		addr += l;
1629		if((uint32_t)tmp.addr4.s_addr == 0)
1630			break;
1631
1632		inet_ntop(AF_INET, &tmp.addr4, dest + p, IP_MAX);
1633		p += strlen(dest + p);
1634		if(withmask == 1) {
1635			dest[p] = '/';
1636			p++;
1637			inet_ntop(AF_INET, &tmp.mask4, dest + p, IP_MAX);
1638			p += strlen(dest + p);
1639		}
1640		dest[p] = ' ';
1641		p++;
1642	}
1643	if(p > 0)
1644		dest[p-1] = '\0';
1645	else
1646		dest[0] = '\0';
1647}
1648
1649int
1650isakmp_cfg_resize_pool(size)
1651	int size;
1652{
1653	struct isakmp_cfg_port *new_pool;
1654	size_t len;
1655	int i;
1656
1657	if (size == isakmp_cfg_config.pool_size)
1658		return 0;
1659
1660	plog(ASL_LEVEL_INFO,
1661	    "Resize address pool from %zu to %d\n",
1662	    isakmp_cfg_config.pool_size, size);
1663
1664	/* If a pool already exists, check if we can shrink it */
1665	if ((isakmp_cfg_config.port_pool != NULL) &&
1666	    (size < isakmp_cfg_config.pool_size)) {
1667		for (i = isakmp_cfg_config.pool_size-1; i >= size; --i) {
1668			if (isakmp_cfg_config.port_pool[i].used) {
1669				plog(ASL_LEVEL_ERR,
1670				    "resize pool from %zu to %d impossible "
1671				    "port %d is in use\n",
1672				    isakmp_cfg_config.pool_size, size, i);
1673				size = i;
1674				break;
1675			}
1676		}
1677	}
1678
1679	len = size * sizeof(*isakmp_cfg_config.port_pool);
1680	new_pool = racoon_realloc(isakmp_cfg_config.port_pool, len);
1681	if (new_pool == NULL) {
1682		plog(ASL_LEVEL_ERR,
1683		    "resize pool from %zu to %d impossible: %s",
1684		    isakmp_cfg_config.pool_size, size, strerror(errno));
1685		return -1;
1686	}
1687
1688	/* If size increase, intialize correctly the new records */
1689	if (size > isakmp_cfg_config.pool_size) {
1690		size_t unit;
1691		size_t old_size;
1692
1693		unit =  sizeof(*isakmp_cfg_config.port_pool);
1694		old_size = isakmp_cfg_config.pool_size;
1695
1696		bzero((char *)new_pool + (old_size * unit),
1697		    (size - old_size) * unit);
1698	}
1699
1700	isakmp_cfg_config.port_pool = new_pool;
1701	isakmp_cfg_config.pool_size = size;
1702
1703	return 0;
1704}
1705
1706int
1707isakmp_cfg_init(cold)
1708	int cold;
1709{
1710	int i;
1711#if 0
1712	int error;
1713#endif
1714
1715	isakmp_cfg_config.network4 = (in_addr_t)0x00000000;
1716	isakmp_cfg_config.netmask4 = (in_addr_t)0x00000000;
1717	for (i = 0; i < MAXNS; i++)
1718		isakmp_cfg_config.dns4[i] = (in_addr_t)0x00000000;
1719	isakmp_cfg_config.dns4_index = 0;
1720	for (i = 0; i < MAXWINS; i++)
1721		isakmp_cfg_config.nbns4[i] = (in_addr_t)0x00000000;
1722	isakmp_cfg_config.nbns4_index = 0;
1723	if (cold != ISAKMP_CFG_INIT_COLD) {
1724		if (isakmp_cfg_config.port_pool) {
1725			racoon_free(isakmp_cfg_config.port_pool);
1726		}
1727	}
1728	isakmp_cfg_config.port_pool = NULL;
1729	isakmp_cfg_config.pool_size = 0;
1730	isakmp_cfg_config.authsource = ISAKMP_CFG_AUTH_SYSTEM;
1731	isakmp_cfg_config.groupsource = ISAKMP_CFG_GROUP_SYSTEM;
1732	if (cold != ISAKMP_CFG_INIT_COLD) {
1733		if (isakmp_cfg_config.grouplist != NULL) {
1734			for (i = 0; i < isakmp_cfg_config.groupcount; i++)
1735				racoon_free(isakmp_cfg_config.grouplist[i]);
1736			racoon_free(isakmp_cfg_config.grouplist);
1737		}
1738	}
1739	isakmp_cfg_config.grouplist = NULL;
1740	isakmp_cfg_config.groupcount = 0;
1741	isakmp_cfg_config.confsource = ISAKMP_CFG_CONF_LOCAL;
1742	isakmp_cfg_config.accounting = ISAKMP_CFG_ACCT_NONE;
1743	isakmp_cfg_config.auth_throttle = THROTTLE_PENALTY;
1744	strlcpy(isakmp_cfg_config.default_domain, ISAKMP_CFG_DEFAULT_DOMAIN,
1745	    sizeof(isakmp_cfg_config.default_domain));
1746	strlcpy(isakmp_cfg_config.motd, ISAKMP_CFG_MOTD, sizeof(isakmp_cfg_config.motd));
1747
1748	if (cold != ISAKMP_CFG_INIT_COLD )
1749		if (isakmp_cfg_config.splitnet_list != NULL)
1750			splitnet_list_free(isakmp_cfg_config.splitnet_list,
1751				&isakmp_cfg_config.splitnet_count);
1752	isakmp_cfg_config.splitnet_list = NULL;
1753	isakmp_cfg_config.splitnet_count = 0;
1754	isakmp_cfg_config.splitnet_type = 0;
1755
1756	isakmp_cfg_config.pfs_group = 0;
1757	isakmp_cfg_config.save_passwd = 0;
1758
1759	if (cold != ISAKMP_CFG_INIT_COLD )
1760		if (isakmp_cfg_config.splitdns_list != NULL)
1761			racoon_free(isakmp_cfg_config.splitdns_list);
1762	isakmp_cfg_config.splitdns_list = NULL;
1763	isakmp_cfg_config.splitdns_len = 0;
1764
1765#if 0
1766	if (cold == ISAKMP_CFG_INIT_COLD) {
1767		if ((error = isakmp_cfg_resize_pool(ISAKMP_CFG_MAX_CNX)) != 0)
1768			return error;
1769	}
1770#endif
1771
1772	return 0;
1773}
1774
1775