1/*	$NetBSD: isakmp_cfg.c,v 1.24 2010/09/21 13:14:17 vanhu 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#if defined(__APPLE__) && defined(__MACH__)
43#include <util.h>
44#endif
45
46#ifdef __FreeBSD__
47# include <libutil.h>
48#endif
49#ifdef __NetBSD__
50#  include <util.h>
51#endif
52
53#include <netinet/in.h>
54#include <arpa/inet.h>
55
56#include <stdlib.h>
57#include <stdio.h>
58#include <string.h>
59#include <errno.h>
60#if TIME_WITH_SYS_TIME
61# include <sys/time.h>
62# include <time.h>
63#else
64# if HAVE_SYS_TIME_H
65#  include <sys/time.h>
66# else
67#  include <time.h>
68# endif
69#endif
70#include <netdb.h>
71#ifdef HAVE_UNISTD_H
72#include <unistd.h>
73#endif
74#if HAVE_STDINT_H
75#include <stdint.h>
76#endif
77#include <ctype.h>
78#include <resolv.h>
79
80#ifdef HAVE_LIBRADIUS
81#include <sys/utsname.h>
82#include <radlib.h>
83#endif
84
85#include "var.h"
86#include "misc.h"
87#include "vmbuf.h"
88#include "plog.h"
89#include "sockmisc.h"
90#include "schedule.h"
91#include "debug.h"
92
93#include "isakmp_var.h"
94#include "isakmp.h"
95#include "handler.h"
96#include "evt.h"
97#include "throttle.h"
98#include "remoteconf.h"
99#include "crypto_openssl.h"
100#include "isakmp_inf.h"
101#include "isakmp_xauth.h"
102#include "isakmp_unity.h"
103#include "isakmp_cfg.h"
104#include "strnames.h"
105#include "admin.h"
106#include "privsep.h"
107
108struct isakmp_cfg_config isakmp_cfg_config;
109
110static vchar_t *buffer_cat(vchar_t *s, vchar_t *append);
111static vchar_t *isakmp_cfg_net(struct ph1handle *, struct isakmp_data *);
112#if 0
113static vchar_t *isakmp_cfg_void(struct ph1handle *, struct isakmp_data *);
114#endif
115static vchar_t *isakmp_cfg_addr4(struct ph1handle *,
116				 struct isakmp_data *, in_addr_t *);
117static vchar_t *isakmp_cfg_addrnet4(struct ph1handle *,
118				 struct isakmp_data *, in_addr_t *, in_addr_t *);
119static void isakmp_cfg_getaddr4(struct isakmp_data *, struct in_addr *);
120static vchar_t *isakmp_cfg_addr4_list(struct ph1handle *,
121				      struct isakmp_data *, in_addr_t *, int);
122static void isakmp_cfg_appendaddr4(struct isakmp_data *,
123				   struct in_addr *, int *, int);
124static void isakmp_cfg_getstring(struct isakmp_data *,char *);
125void isakmp_cfg_iplist_to_str(char *, int, void *, int);
126
127#define ISAKMP_CFG_LOGIN	1
128#define ISAKMP_CFG_LOGOUT	2
129static int isakmp_cfg_accounting(struct ph1handle *, int);
130#ifdef HAVE_LIBRADIUS
131static int isakmp_cfg_accounting_radius(struct ph1handle *, int);
132#endif
133
134/*
135 * Handle an ISAKMP config mode packet
136 * We expect HDR, HASH, ATTR
137 */
138void
139isakmp_cfg_r(iph1, msg)
140	struct ph1handle *iph1;
141	vchar_t *msg;
142{
143	struct isakmp *packet;
144	struct isakmp_gen *ph;
145	int tlen;
146	char *npp;
147	int np;
148	vchar_t *dmsg;
149	struct isakmp_ivm *ivm;
150
151	/* Check that the packet is long enough to have a header */
152	if (msg->l < sizeof(*packet)) {
153	     plog(LLV_ERROR, LOCATION, NULL, "Unexpected short packet\n");
154	     return;
155	}
156
157	packet = (struct isakmp *)msg->v;
158
159	/* Is it encrypted? It should be encrypted */
160	if ((packet->flags & ISAKMP_FLAG_E) == 0) {
161		plog(LLV_ERROR, LOCATION, NULL,
162		    "User credentials sent in cleartext!\n");
163		return;
164	}
165
166	/*
167	 * Decrypt the packet. If this is the beginning of a new
168	 * exchange, reinitialize the IV
169	 */
170	if (iph1->mode_cfg->ivm == NULL ||
171	    iph1->mode_cfg->last_msgid != packet->msgid )
172		iph1->mode_cfg->ivm =
173		    isakmp_cfg_newiv(iph1, packet->msgid);
174	ivm = iph1->mode_cfg->ivm;
175
176	dmsg = oakley_do_decrypt(iph1, msg, ivm->iv, ivm->ive);
177	if (dmsg == NULL) {
178		plog(LLV_ERROR, LOCATION, NULL,
179		    "failed to decrypt message\n");
180		return;
181	}
182
183	plog(LLV_DEBUG, LOCATION, NULL, "MODE_CFG packet\n");
184	plogdump(LLV_DEBUG, dmsg->v, dmsg->l);
185
186	/* Now work with the decrypted packet */
187	packet = (struct isakmp *)dmsg->v;
188	tlen = dmsg->l - sizeof(*packet);
189	ph = (struct isakmp_gen *)(packet + 1);
190
191	np = packet->np;
192	while ((tlen > 0) && (np != ISAKMP_NPTYPE_NONE)) {
193		/* Check that the payload header fits in the packet */
194		if (tlen < sizeof(*ph)) {
195			 plog(LLV_WARNING, LOCATION, NULL,
196			      "Short payload header\n");
197			 goto out;
198		}
199
200		/* Check that the payload fits in the packet */
201		if (tlen < ntohs(ph->len)) {
202			plog(LLV_WARNING, LOCATION, NULL,
203			      "Short payload\n");
204			goto out;
205		}
206
207		plog(LLV_DEBUG, LOCATION, NULL, "Seen payload %d\n", np);
208		plogdump(LLV_DEBUG, ph, ntohs(ph->len));
209
210		switch(np) {
211		case ISAKMP_NPTYPE_HASH: {
212			vchar_t *check;
213			vchar_t *payload;
214			size_t plen;
215			struct isakmp_gen *nph;
216
217			plen = ntohs(ph->len);
218			nph = (struct isakmp_gen *)((char *)ph + plen);
219			plen = ntohs(nph->len);
220
221			if ((payload = vmalloc(plen)) == NULL) {
222				plog(LLV_ERROR, LOCATION, NULL,
223				    "Cannot allocate memory\n");
224				goto out;
225			}
226			memcpy(payload->v, nph, plen);
227
228			if ((check = oakley_compute_hash1(iph1,
229			    packet->msgid, payload)) == NULL) {
230				plog(LLV_ERROR, LOCATION, NULL,
231				    "Cannot compute hash\n");
232				vfree(payload);
233				goto out;
234			}
235
236			if (memcmp(ph + 1, check->v, check->l) != 0) {
237				plog(LLV_ERROR, LOCATION, NULL,
238				    "Hash verification failed\n");
239				vfree(payload);
240				vfree(check);
241				goto out;
242			}
243			vfree(payload);
244			vfree(check);
245			break;
246		}
247		case ISAKMP_NPTYPE_ATTR: {
248			struct isakmp_pl_attr *attrpl;
249
250			attrpl = (struct isakmp_pl_attr *)ph;
251			isakmp_cfg_attr_r(iph1, packet->msgid, attrpl);
252
253			break;
254		}
255		default:
256			 plog(LLV_WARNING, LOCATION, NULL,
257			      "Unexpected next payload %d\n", np);
258			 /* Skip to the next payload */
259			 break;
260		}
261
262		/* Move to the next payload */
263		np = ph->np;
264		tlen -= ntohs(ph->len);
265		npp = (char *)ph;
266		ph = (struct isakmp_gen *)(npp + ntohs(ph->len));
267	}
268
269out:
270	vfree(dmsg);
271}
272
273int
274isakmp_cfg_attr_r(iph1, msgid, attrpl)
275	struct ph1handle *iph1;
276	u_int32_t msgid;
277	struct isakmp_pl_attr *attrpl;
278{
279	int type = attrpl->type;
280
281	plog(LLV_DEBUG, LOCATION, NULL,
282	     "Configuration exchange type %s\n", s_isakmp_cfg_ptype(type));
283	switch (type) {
284	case ISAKMP_CFG_ACK:
285		/* ignore, but this is the time to reinit the IV */
286		oakley_delivm(iph1->mode_cfg->ivm);
287		iph1->mode_cfg->ivm = NULL;
288		return 0;
289		break;
290
291	case ISAKMP_CFG_REPLY:
292		return isakmp_cfg_reply(iph1, attrpl);
293		break;
294
295	case ISAKMP_CFG_REQUEST:
296		iph1->msgid = msgid;
297		return isakmp_cfg_request(iph1, attrpl);
298		break;
299
300	case ISAKMP_CFG_SET:
301		iph1->msgid = msgid;
302		return isakmp_cfg_set(iph1, attrpl);
303		break;
304
305	default:
306		plog(LLV_WARNING, LOCATION, NULL,
307		     "Unepected configuration exchange type %d\n", type);
308		return -1;
309		break;
310	}
311
312	return 0;
313}
314
315int
316isakmp_cfg_reply(iph1, attrpl)
317	struct ph1handle *iph1;
318	struct isakmp_pl_attr *attrpl;
319{
320	struct isakmp_data *attr;
321	int tlen;
322	size_t alen;
323	char *npp;
324	int type;
325	struct sockaddr_in *sin;
326	int error;
327
328	tlen = ntohs(attrpl->h.len);
329	attr = (struct isakmp_data *)(attrpl + 1);
330	tlen -= sizeof(*attrpl);
331
332	while (tlen > 0) {
333		type = ntohs(attr->type);
334
335		/* Handle short attributes */
336		if ((type & ISAKMP_GEN_MASK) == ISAKMP_GEN_TV) {
337			type &= ~ISAKMP_GEN_MASK;
338
339			plog(LLV_DEBUG, LOCATION, NULL,
340			     "Short attribute %s = %d\n",
341			     s_isakmp_cfg_type(type), ntohs(attr->lorv));
342
343			switch (type) {
344			case XAUTH_TYPE:
345				if ((error = xauth_attr_reply(iph1,
346				    attr, ntohs(attrpl->id))) != 0)
347					return error;
348				break;
349
350			default:
351				plog(LLV_WARNING, LOCATION, NULL,
352				     "Ignored short attribute %s\n",
353				     s_isakmp_cfg_type(type));
354				break;
355			}
356
357			tlen -= sizeof(*attr);
358			attr++;
359			continue;
360		}
361
362		type = ntohs(attr->type);
363		alen = ntohs(attr->lorv);
364
365		/* Check that the attribute fit in the packet */
366		if (tlen < alen) {
367			plog(LLV_ERROR, LOCATION, NULL,
368			     "Short attribute %s\n",
369			     s_isakmp_cfg_type(type));
370			return -1;
371		}
372
373		plog(LLV_DEBUG, LOCATION, NULL,
374		     "Attribute %s, len %zu\n",
375		     s_isakmp_cfg_type(type), alen);
376
377		switch(type) {
378		case XAUTH_TYPE:
379		case XAUTH_USER_NAME:
380		case XAUTH_USER_PASSWORD:
381		case XAUTH_PASSCODE:
382		case XAUTH_MESSAGE:
383		case XAUTH_CHALLENGE:
384		case XAUTH_DOMAIN:
385		case XAUTH_STATUS:
386		case XAUTH_NEXT_PIN:
387		case XAUTH_ANSWER:
388			if ((error = xauth_attr_reply(iph1,
389			    attr, ntohs(attrpl->id))) != 0)
390				return error;
391			break;
392		case INTERNAL_IP4_ADDRESS:
393			isakmp_cfg_getaddr4(attr, &iph1->mode_cfg->addr4);
394			iph1->mode_cfg->flags |= ISAKMP_CFG_GOT_ADDR4;
395			break;
396		case INTERNAL_IP4_NETMASK:
397			isakmp_cfg_getaddr4(attr, &iph1->mode_cfg->mask4);
398			iph1->mode_cfg->flags |= ISAKMP_CFG_GOT_MASK4;
399			break;
400		case INTERNAL_IP4_DNS:
401			isakmp_cfg_appendaddr4(attr,
402			    &iph1->mode_cfg->dns4[iph1->mode_cfg->dns4_index],
403			    &iph1->mode_cfg->dns4_index, MAXNS);
404			iph1->mode_cfg->flags |= ISAKMP_CFG_GOT_DNS4;
405			break;
406		case INTERNAL_IP4_NBNS:
407			isakmp_cfg_appendaddr4(attr,
408			    &iph1->mode_cfg->wins4[iph1->mode_cfg->wins4_index],
409			    &iph1->mode_cfg->wins4_index, MAXNS);
410			iph1->mode_cfg->flags |= ISAKMP_CFG_GOT_WINS4;
411			break;
412		case UNITY_DEF_DOMAIN:
413			isakmp_cfg_getstring(attr,
414			    iph1->mode_cfg->default_domain);
415			iph1->mode_cfg->flags |= ISAKMP_CFG_GOT_DEFAULT_DOMAIN;
416			break;
417		case UNITY_SPLIT_INCLUDE:
418		case UNITY_LOCAL_LAN:
419		case UNITY_SPLITDNS_NAME:
420		case UNITY_BANNER:
421		case UNITY_SAVE_PASSWD:
422		case UNITY_NATT_PORT:
423		case UNITY_PFS:
424		case UNITY_FW_TYPE:
425		case UNITY_BACKUP_SERVERS:
426		case UNITY_DDNS_HOSTNAME:
427			isakmp_unity_reply(iph1, attr);
428			break;
429		case INTERNAL_IP4_SUBNET:
430		case INTERNAL_ADDRESS_EXPIRY:
431		default:
432			plog(LLV_WARNING, LOCATION, NULL,
433			     "Ignored attribute %s\n",
434			     s_isakmp_cfg_type(type));
435			break;
436		}
437
438		npp = (char *)attr;
439		attr = (struct isakmp_data *)(npp + sizeof(*attr) + alen);
440		tlen -= (sizeof(*attr) + alen);
441	}
442
443	/*
444	 * Call the SA up script hook now that we have the configuration
445	 * It is done at the end of phase 1 if ISAKMP mode config is not
446	 * requested.
447	 */
448
449	if ((iph1->status == PHASE1ST_ESTABLISHED) &&
450	    iph1->rmconf->mode_cfg) {
451		switch (iph1->approval->authmethod) {
452		case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I:
453		case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
454		/* Unimplemented */
455		case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
456		case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
457		case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
458		case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
459		case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
460			script_hook(iph1, SCRIPT_PHASE1_UP);
461			break;
462		default:
463			break;
464		}
465	}
466
467
468#ifdef ENABLE_ADMINPORT
469	{
470		vchar_t *buf;
471
472		alen = ntohs(attrpl->h.len) - sizeof(*attrpl);
473		if ((buf = vmalloc(alen)) == NULL) {
474			plog(LLV_WARNING, LOCATION, NULL,
475			    "Cannot allocate memory: %s\n", strerror(errno));
476		} else {
477			memcpy(buf->v, attrpl + 1, buf->l);
478			evt_phase1(iph1, EVT_PHASE1_MODE_CFG, buf);
479			vfree(buf);
480		}
481	}
482#endif
483
484	return 0;
485}
486
487int
488isakmp_cfg_request(iph1, attrpl)
489	struct ph1handle *iph1;
490	struct isakmp_pl_attr *attrpl;
491{
492	struct isakmp_data *attr;
493	int tlen;
494	size_t alen;
495	char *npp;
496	vchar_t *payload;
497	struct isakmp_pl_attr *reply;
498	vchar_t *reply_attr;
499	int type;
500	int error = -1;
501
502	if ((payload = vmalloc(sizeof(*reply))) == NULL) {
503		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
504		return -1;
505	}
506	memset(payload->v, 0, sizeof(*reply));
507
508	tlen = ntohs(attrpl->h.len);
509	attr = (struct isakmp_data *)(attrpl + 1);
510	tlen -= sizeof(*attrpl);
511
512	while (tlen > 0) {
513		reply_attr = NULL;
514		type = ntohs(attr->type);
515
516		/* Handle short attributes */
517		if ((type & ISAKMP_GEN_MASK) == ISAKMP_GEN_TV) {
518			type &= ~ISAKMP_GEN_MASK;
519
520			plog(LLV_DEBUG, LOCATION, NULL,
521			     "Short attribute %s = %d\n",
522			     s_isakmp_cfg_type(type), ntohs(attr->lorv));
523
524			switch (type) {
525			case XAUTH_TYPE:
526				reply_attr = isakmp_xauth_req(iph1, attr);
527				break;
528			default:
529				plog(LLV_WARNING, LOCATION, NULL,
530				     "Ignored short attribute %s\n",
531				     s_isakmp_cfg_type(type));
532				break;
533			}
534
535			tlen -= sizeof(*attr);
536			attr++;
537
538			if (reply_attr != NULL) {
539				payload = buffer_cat(payload, reply_attr);
540				vfree(reply_attr);
541			}
542
543			continue;
544		}
545
546		type = ntohs(attr->type);
547		alen = ntohs(attr->lorv);
548
549		/* Check that the attribute fit in the packet */
550		if (tlen < alen) {
551			plog(LLV_ERROR, LOCATION, NULL,
552			     "Short attribute %s\n",
553			     s_isakmp_cfg_type(type));
554			goto end;
555		}
556
557		plog(LLV_DEBUG, LOCATION, NULL,
558		     "Attribute %s, len %zu\n",
559		     s_isakmp_cfg_type(type), alen);
560
561		switch(type) {
562		case INTERNAL_IP4_ADDRESS:
563		case INTERNAL_IP4_NETMASK:
564		case INTERNAL_IP4_DNS:
565		case INTERNAL_IP4_NBNS:
566		case INTERNAL_IP4_SUBNET:
567			reply_attr = isakmp_cfg_net(iph1, attr);
568			break;
569
570		case XAUTH_TYPE:
571		case XAUTH_USER_NAME:
572		case XAUTH_USER_PASSWORD:
573		case XAUTH_PASSCODE:
574		case XAUTH_MESSAGE:
575		case XAUTH_CHALLENGE:
576		case XAUTH_DOMAIN:
577		case XAUTH_STATUS:
578		case XAUTH_NEXT_PIN:
579		case XAUTH_ANSWER:
580			reply_attr = isakmp_xauth_req(iph1, attr);
581			break;
582
583		case APPLICATION_VERSION:
584			reply_attr = isakmp_cfg_string(iph1,
585			    attr, ISAKMP_CFG_RACOON_VERSION);
586			break;
587
588		case UNITY_BANNER:
589		case UNITY_PFS:
590		case UNITY_SAVE_PASSWD:
591		case UNITY_DEF_DOMAIN:
592		case UNITY_DDNS_HOSTNAME:
593		case UNITY_FW_TYPE:
594		case UNITY_SPLITDNS_NAME:
595		case UNITY_SPLIT_INCLUDE:
596		case UNITY_LOCAL_LAN:
597		case UNITY_NATT_PORT:
598		case UNITY_BACKUP_SERVERS:
599			reply_attr = isakmp_unity_req(iph1, attr);
600			break;
601
602		case INTERNAL_ADDRESS_EXPIRY:
603		default:
604			plog(LLV_WARNING, LOCATION, NULL,
605			     "Ignored attribute %s\n",
606			     s_isakmp_cfg_type(type));
607			break;
608		}
609
610		npp = (char *)attr;
611		attr = (struct isakmp_data *)(npp + sizeof(*attr) + alen);
612		tlen -= (sizeof(*attr) + alen);
613
614		if (reply_attr != NULL) {
615			payload = buffer_cat(payload, reply_attr);
616			vfree(reply_attr);
617		}
618
619	}
620
621	reply = (struct isakmp_pl_attr *)payload->v;
622	reply->h.len = htons(payload->l);
623	reply->type = ISAKMP_CFG_REPLY;
624	reply->id = attrpl->id;
625
626	plog(LLV_DEBUG, LOCATION, NULL,
627		    "Sending MODE_CFG REPLY\n");
628
629	error = isakmp_cfg_send(iph1, payload,
630	    ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 0);
631
632	if (iph1->status == PHASE1ST_ESTABLISHED) {
633		switch (iph1->approval->authmethod) {
634		case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
635		case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
636		/* Unimplemented */
637		case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
638		case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
639		case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
640		case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
641		case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
642			script_hook(iph1, SCRIPT_PHASE1_UP);
643			break;
644		default:
645			break;
646		}
647	}
648
649end:
650	vfree(payload);
651
652	return error;
653}
654
655int
656isakmp_cfg_set(iph1, attrpl)
657	struct ph1handle *iph1;
658	struct isakmp_pl_attr *attrpl;
659{
660	struct isakmp_data *attr;
661	int tlen;
662	size_t alen;
663	char *npp;
664	vchar_t *payload;
665	struct isakmp_pl_attr *reply;
666	vchar_t *reply_attr;
667	int type;
668	int error = -1;
669
670	if ((payload = vmalloc(sizeof(*reply))) == NULL) {
671		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
672		return -1;
673	}
674	memset(payload->v, 0, sizeof(*reply));
675
676	tlen = ntohs(attrpl->h.len);
677	attr = (struct isakmp_data *)(attrpl + 1);
678	tlen -= sizeof(*attrpl);
679
680	/*
681	 * We should send ack for the attributes we accepted
682	 */
683	while (tlen > 0) {
684		reply_attr = NULL;
685		type = ntohs(attr->type);
686
687		plog(LLV_DEBUG, LOCATION, NULL,
688		     "Attribute %s\n",
689		     s_isakmp_cfg_type(type & ~ISAKMP_GEN_MASK));
690
691		switch (type & ~ISAKMP_GEN_MASK) {
692		case XAUTH_STATUS:
693			reply_attr = isakmp_xauth_set(iph1, attr);
694			break;
695		default:
696			plog(LLV_DEBUG, LOCATION, NULL,
697			     "Unexpected SET attribute %s\n",
698		     	     s_isakmp_cfg_type(type & ~ISAKMP_GEN_MASK));
699			break;
700		}
701
702		if (reply_attr != NULL) {
703			payload = buffer_cat(payload, reply_attr);
704			vfree(reply_attr);
705		}
706
707		/*
708		 * Move to next attribute. If we run out of the packet,
709		 * tlen becomes negative and we exit.
710		 */
711		if ((type & ISAKMP_GEN_MASK) == ISAKMP_GEN_TV) {
712			tlen -= sizeof(*attr);
713			attr++;
714		} else {
715			alen = ntohs(attr->lorv);
716			tlen -= (sizeof(*attr) + alen);
717			npp = (char *)attr;
718			attr = (struct isakmp_data *)
719			    (npp + sizeof(*attr) + alen);
720		}
721	}
722
723	reply = (struct isakmp_pl_attr *)payload->v;
724	reply->h.len = htons(payload->l);
725	reply->type = ISAKMP_CFG_ACK;
726	reply->id = attrpl->id;
727
728	plog(LLV_DEBUG, LOCATION, NULL,
729		     "Sending MODE_CFG ACK\n");
730
731	error = isakmp_cfg_send(iph1, payload,
732	    ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 0);
733
734	if (iph1->mode_cfg->flags & ISAKMP_CFG_DELETE_PH1) {
735		if (iph1->status == PHASE1ST_ESTABLISHED ||
736		    iph1->status == PHASE1ST_DYING)
737			isakmp_info_send_d1(iph1);
738		remph1(iph1);
739		delph1(iph1);
740		iph1 = NULL;
741	}
742end:
743	vfree(payload);
744
745	/*
746	 * If required, request ISAKMP mode config information
747	 */
748	if ((iph1 != NULL) && (iph1->rmconf->mode_cfg) && (error == 0))
749		error = isakmp_cfg_getconfig(iph1);
750
751	return error;
752}
753
754
755static vchar_t *
756buffer_cat(s, append)
757	vchar_t *s;
758	vchar_t *append;
759{
760	vchar_t *new;
761
762	new = vmalloc(s->l + append->l);
763	if (new == NULL) {
764		plog(LLV_ERROR, LOCATION, NULL,
765		    "Cannot allocate memory\n");
766		return s;
767	}
768
769	memcpy(new->v, s->v, s->l);
770	memcpy(new->v + s->l, append->v, append->l);
771
772	vfree(s);
773	return new;
774}
775
776static vchar_t *
777isakmp_cfg_net(iph1, attr)
778	struct ph1handle *iph1;
779	struct isakmp_data *attr;
780{
781	int type;
782	int confsource;
783	in_addr_t addr4;
784
785	type = ntohs(attr->type);
786
787	/*
788	 * Don't give an address to a peer that did not succeed Xauth
789	 */
790	if (xauth_check(iph1) != 0) {
791		plog(LLV_ERROR, LOCATION, NULL,
792		    "Attempt to start phase config whereas Xauth failed\n");
793		return NULL;
794	}
795
796	confsource = isakmp_cfg_config.confsource;
797	/*
798	 * If we have to fall back to a local
799	 * configuration source, we will jump
800	 * back to this point.
801	 */
802retry_source:
803
804	switch(type) {
805	case INTERNAL_IP4_ADDRESS:
806		switch(confsource) {
807#ifdef HAVE_LIBLDAP
808		case ISAKMP_CFG_CONF_LDAP:
809			if (iph1->mode_cfg->flags & ISAKMP_CFG_ADDR4_EXTERN)
810			    break;
811			plog(LLV_INFO, LOCATION, NULL,
812			    "No IP from LDAP, using local pool\n");
813			/* FALLTHROUGH */
814			confsource = ISAKMP_CFG_CONF_LOCAL;
815			goto retry_source;
816#endif
817#ifdef HAVE_LIBRADIUS
818		case ISAKMP_CFG_CONF_RADIUS:
819			if ((iph1->mode_cfg->flags & ISAKMP_CFG_ADDR4_EXTERN)
820			    && (iph1->mode_cfg->addr4.s_addr != htonl(-2)))
821			    /*
822			     * -2 is 255.255.255.254, RADIUS uses that
823			     * to instruct the NAS to use a local pool
824			     */
825			    break;
826			plog(LLV_INFO, LOCATION, NULL,
827			    "No IP from RADIUS, using local pool\n");
828			/* FALLTHROUGH */
829			confsource = ISAKMP_CFG_CONF_LOCAL;
830			goto retry_source;
831#endif
832		case ISAKMP_CFG_CONF_LOCAL:
833			if (isakmp_cfg_getport(iph1) == -1) {
834				plog(LLV_ERROR, LOCATION, NULL,
835				    "Port pool depleted\n");
836				break;
837			}
838
839			iph1->mode_cfg->addr4.s_addr =
840			    htonl(ntohl(isakmp_cfg_config.network4)
841			    + iph1->mode_cfg->port);
842			iph1->mode_cfg->flags |= ISAKMP_CFG_ADDR4_LOCAL;
843			break;
844
845		default:
846			plog(LLV_ERROR, LOCATION, NULL,
847			    "Unexpected confsource\n");
848		}
849
850		if (isakmp_cfg_accounting(iph1, ISAKMP_CFG_LOGIN) != 0)
851			plog(LLV_ERROR, LOCATION, NULL, "Accounting failed\n");
852
853		return isakmp_cfg_addr4(iph1,
854		    attr, &iph1->mode_cfg->addr4.s_addr);
855		break;
856
857	case INTERNAL_IP4_NETMASK:
858		switch(confsource) {
859#ifdef HAVE_LIBLDAP
860		case ISAKMP_CFG_CONF_LDAP:
861			if (iph1->mode_cfg->flags & ISAKMP_CFG_MASK4_EXTERN)
862				break;
863			plog(LLV_INFO, LOCATION, NULL,
864			    "No mask from LDAP, using local pool\n");
865			/* FALLTHROUGH */
866			confsource = ISAKMP_CFG_CONF_LOCAL;
867			goto retry_source;
868#endif
869#ifdef HAVE_LIBRADIUS
870		case ISAKMP_CFG_CONF_RADIUS:
871			if (iph1->mode_cfg->flags & ISAKMP_CFG_MASK4_EXTERN)
872				break;
873			plog(LLV_INFO, LOCATION, NULL,
874			    "No mask from RADIUS, using local pool\n");
875			/* FALLTHROUGH */
876			confsource = ISAKMP_CFG_CONF_LOCAL;
877			goto retry_source;
878#endif
879		case ISAKMP_CFG_CONF_LOCAL:
880			iph1->mode_cfg->mask4.s_addr
881			    = isakmp_cfg_config.netmask4;
882			iph1->mode_cfg->flags |= ISAKMP_CFG_MASK4_LOCAL;
883			break;
884
885		default:
886			plog(LLV_ERROR, LOCATION, NULL,
887			    "Unexpected confsource\n");
888		}
889		return isakmp_cfg_addr4(iph1, attr,
890		    &iph1->mode_cfg->mask4.s_addr);
891		break;
892
893	case INTERNAL_IP4_DNS:
894		return isakmp_cfg_addr4_list(iph1,
895		    attr, &isakmp_cfg_config.dns4[0],
896		    isakmp_cfg_config.dns4_index);
897		break;
898
899	case INTERNAL_IP4_NBNS:
900		return isakmp_cfg_addr4_list(iph1,
901		    attr, &isakmp_cfg_config.nbns4[0],
902		    isakmp_cfg_config.nbns4_index);
903		break;
904
905	case INTERNAL_IP4_SUBNET:
906		if(isakmp_cfg_config.splitnet_count > 0){
907			return isakmp_cfg_addrnet4(iph1, attr,
908						    &isakmp_cfg_config.splitnet_list->network.addr4.s_addr,
909						    &isakmp_cfg_config.splitnet_list->network.mask4.s_addr);
910		}else{
911			plog(LLV_INFO, LOCATION, NULL,
912			     "%s requested but no splitnet in configuration\n",
913			     s_isakmp_cfg_type(type));
914		}
915		break;
916
917	default:
918		plog(LLV_ERROR, LOCATION, NULL, "Unexpected type %d\n", type);
919		break;
920	}
921	return NULL;
922}
923
924#if 0
925static vchar_t *
926isakmp_cfg_void(iph1, attr)
927	struct ph1handle *iph1;
928	struct isakmp_data *attr;
929{
930	vchar_t *buffer;
931	struct isakmp_data *new;
932
933	if ((buffer = vmalloc(sizeof(*attr))) == NULL) {
934		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
935		return NULL;
936	}
937
938	new = (struct isakmp_data *)buffer->v;
939
940	new->type = attr->type;
941	new->lorv = htons(0);
942
943	return buffer;
944}
945#endif
946
947vchar_t *
948isakmp_cfg_copy(iph1, attr)
949	struct ph1handle *iph1;
950	struct isakmp_data *attr;
951{
952	vchar_t *buffer;
953	size_t len = 0;
954
955	if ((ntohs(attr->type) & ISAKMP_GEN_MASK) == ISAKMP_GEN_TLV)
956		len = ntohs(attr->lorv);
957
958	if ((buffer = vmalloc(sizeof(*attr) + len)) == NULL) {
959		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
960		return NULL;
961	}
962
963	memcpy(buffer->v, attr, sizeof(*attr) + ntohs(attr->lorv));
964
965	return buffer;
966}
967
968vchar_t *
969isakmp_cfg_short(iph1, attr, value)
970	struct ph1handle *iph1;
971	struct isakmp_data *attr;
972	int value;
973{
974	vchar_t *buffer;
975	struct isakmp_data *new;
976	int type;
977
978	if ((buffer = vmalloc(sizeof(*attr))) == NULL) {
979		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
980		return NULL;
981	}
982
983	new = (struct isakmp_data *)buffer->v;
984	type = ntohs(attr->type) & ~ISAKMP_GEN_MASK;
985
986	new->type = htons(type | ISAKMP_GEN_TV);
987	new->lorv = htons(value);
988
989	return buffer;
990}
991
992vchar_t *
993isakmp_cfg_varlen(iph1, attr, string, len)
994	struct ph1handle *iph1;
995	struct isakmp_data *attr;
996	char *string;
997	size_t len;
998{
999	vchar_t *buffer;
1000	struct isakmp_data *new;
1001	char *data;
1002
1003	if ((buffer = vmalloc(sizeof(*attr) + len)) == NULL) {
1004		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
1005		return NULL;
1006	}
1007
1008	new = (struct isakmp_data *)buffer->v;
1009
1010	new->type = attr->type;
1011	new->lorv = htons(len);
1012	data = (char *)(new + 1);
1013
1014	memcpy(data, string, len);
1015
1016	return buffer;
1017}
1018vchar_t *
1019isakmp_cfg_string(iph1, attr, string)
1020	struct ph1handle *iph1;
1021	struct isakmp_data *attr;
1022	char *string;
1023{
1024	size_t len = strlen(string);
1025	return isakmp_cfg_varlen(iph1, attr, string, len);
1026}
1027
1028static vchar_t *
1029isakmp_cfg_addr4(iph1, attr, addr)
1030	struct ph1handle *iph1;
1031	struct isakmp_data *attr;
1032	in_addr_t *addr;
1033{
1034	vchar_t *buffer;
1035	struct isakmp_data *new;
1036	size_t len;
1037
1038	len = sizeof(*addr);
1039	if ((buffer = vmalloc(sizeof(*attr) + len)) == NULL) {
1040		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
1041		return NULL;
1042	}
1043
1044	new = (struct isakmp_data *)buffer->v;
1045
1046	new->type = attr->type;
1047	new->lorv = htons(len);
1048	memcpy(new + 1, addr, len);
1049
1050	return buffer;
1051}
1052
1053static vchar_t *
1054isakmp_cfg_addrnet4(iph1, attr, addr, mask)
1055	struct ph1handle *iph1;
1056	struct isakmp_data *attr;
1057	in_addr_t *addr;
1058	in_addr_t *mask;
1059{
1060	vchar_t *buffer;
1061	struct isakmp_data *new;
1062	size_t len;
1063	in_addr_t netbuff[2];
1064
1065	len = sizeof(netbuff);
1066	if ((buffer = vmalloc(sizeof(*attr) + len)) == NULL) {
1067		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
1068		return NULL;
1069	}
1070
1071	new = (struct isakmp_data *)buffer->v;
1072
1073	new->type = attr->type;
1074	new->lorv = htons(len);
1075	netbuff[0]=*addr;
1076	netbuff[1]=*mask;
1077	memcpy(new + 1, netbuff, len);
1078
1079	return buffer;
1080}
1081
1082
1083static vchar_t *
1084isakmp_cfg_addr4_list(iph1, attr, addr, nbr)
1085	struct ph1handle *iph1;
1086	struct isakmp_data *attr;
1087	in_addr_t *addr;
1088	int nbr;
1089{
1090	int error = -1;
1091	vchar_t *buffer = NULL;
1092	vchar_t *bufone = NULL;
1093	struct isakmp_data *new;
1094	size_t len;
1095	int i;
1096
1097	len = sizeof(*addr);
1098	if ((buffer = vmalloc(0)) == NULL) {
1099		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
1100		goto out;
1101	}
1102	for(i = 0; i < nbr; i++) {
1103		if ((bufone = vmalloc(sizeof(*attr) + len)) == NULL) {
1104			plog(LLV_ERROR, LOCATION, NULL,
1105			    "Cannot allocate memory\n");
1106			goto out;
1107		}
1108		new = (struct isakmp_data *)bufone->v;
1109		new->type = attr->type;
1110		new->lorv = htons(len);
1111		memcpy(new + 1, &addr[i], len);
1112		new += (len + sizeof(*attr));
1113		buffer = buffer_cat(buffer, bufone);
1114		vfree(bufone);
1115	}
1116
1117	error = 0;
1118
1119out:
1120	if ((error != 0) && (buffer != NULL)) {
1121		vfree(buffer);
1122		buffer = NULL;
1123	}
1124
1125	return buffer;
1126}
1127
1128struct isakmp_ivm *
1129isakmp_cfg_newiv(iph1, msgid)
1130	struct ph1handle *iph1;
1131	u_int32_t msgid;
1132{
1133	struct isakmp_cfg_state *ics = iph1->mode_cfg;
1134
1135	if (ics == NULL) {
1136		plog(LLV_ERROR, LOCATION, NULL,
1137		    "isakmp_cfg_newiv called without mode config state\n");
1138		return NULL;
1139	}
1140
1141	if (ics->ivm != NULL)
1142		oakley_delivm(ics->ivm);
1143
1144	ics->ivm = oakley_newiv2(iph1, msgid);
1145	ics->last_msgid = msgid;
1146
1147	return ics->ivm;
1148}
1149
1150/* Derived from isakmp_info_send_common */
1151int
1152isakmp_cfg_send(iph1, payload, np, flags, new_exchange)
1153	struct ph1handle *iph1;
1154	vchar_t *payload;
1155	u_int32_t np;
1156	int flags;
1157	int new_exchange;
1158{
1159	struct ph2handle *iph2 = NULL;
1160	vchar_t *hash = NULL;
1161	struct isakmp *isakmp;
1162	struct isakmp_gen *gen;
1163	char *p;
1164	int tlen;
1165	int error = -1;
1166	struct isakmp_cfg_state *ics = iph1->mode_cfg;
1167
1168	/* Check if phase 1 is established */
1169	if ((iph1->status < PHASE1ST_ESTABLISHED) ||
1170	    (iph1->local == NULL) ||
1171	    (iph1->remote == NULL)) {
1172		plog(LLV_ERROR, LOCATION, NULL,
1173		    "ISAKMP mode config exchange with immature phase 1\n");
1174		goto end;
1175	}
1176
1177	/* add new entry to isakmp status table */
1178	iph2 = newph2();
1179	if (iph2 == NULL)
1180		goto end;
1181
1182	iph2->dst = dupsaddr(iph1->remote);
1183	if (iph2->dst == NULL) {
1184		delph2(iph2);
1185		goto end;
1186	}
1187	iph2->src = dupsaddr(iph1->local);
1188	if (iph2->src == NULL) {
1189		delph2(iph2);
1190		goto end;
1191	}
1192
1193	iph2->side = INITIATOR;
1194	iph2->status = PHASE2ST_START;
1195
1196	if (new_exchange)
1197		iph2->msgid = isakmp_newmsgid2(iph1);
1198	else
1199		iph2->msgid = iph1->msgid;
1200
1201	/* get IV and HASH(1) if skeyid_a was generated. */
1202	if (iph1->skeyid_a != NULL) {
1203		if (new_exchange) {
1204			if (isakmp_cfg_newiv(iph1, iph2->msgid) == NULL) {
1205				delph2(iph2);
1206				goto end;
1207			}
1208		}
1209
1210		/* generate HASH(1) */
1211		hash = oakley_compute_hash1(iph1, iph2->msgid, payload);
1212		if (hash == NULL) {
1213			delph2(iph2);
1214			goto end;
1215		}
1216
1217		/* initialized total buffer length */
1218		tlen = hash->l;
1219		tlen += sizeof(*gen);
1220	} else {
1221		/* IKE-SA is not established */
1222		hash = NULL;
1223
1224		/* initialized total buffer length */
1225		tlen = 0;
1226	}
1227	if ((flags & ISAKMP_FLAG_A) == 0)
1228		iph2->flags = (hash == NULL ? 0 : ISAKMP_FLAG_E);
1229	else
1230		iph2->flags = (hash == NULL ? 0 : ISAKMP_FLAG_A);
1231
1232	insph2(iph2);
1233	bindph12(iph1, iph2);
1234
1235	tlen += sizeof(*isakmp) + payload->l;
1236
1237	/* create buffer for isakmp payload */
1238	iph2->sendbuf = vmalloc(tlen);
1239	if (iph2->sendbuf == NULL) {
1240		plog(LLV_ERROR, LOCATION, NULL,
1241			"failed to get buffer to send.\n");
1242		goto err;
1243	}
1244
1245	/* create isakmp header */
1246	isakmp = (struct isakmp *)iph2->sendbuf->v;
1247	memcpy(&isakmp->i_ck, &iph1->index.i_ck, sizeof(cookie_t));
1248	memcpy(&isakmp->r_ck, &iph1->index.r_ck, sizeof(cookie_t));
1249	isakmp->np = hash == NULL ? (np & 0xff) : ISAKMP_NPTYPE_HASH;
1250	isakmp->v = iph1->version;
1251	isakmp->etype = ISAKMP_ETYPE_CFG;
1252	isakmp->flags = iph2->flags;
1253	memcpy(&isakmp->msgid, &iph2->msgid, sizeof(isakmp->msgid));
1254	isakmp->len = htonl(tlen);
1255	p = (char *)(isakmp + 1);
1256
1257	/* create HASH payload */
1258	if (hash != NULL) {
1259		gen = (struct isakmp_gen *)p;
1260		gen->np = np & 0xff;
1261		gen->len = htons(sizeof(*gen) + hash->l);
1262		p += sizeof(*gen);
1263		memcpy(p, hash->v, hash->l);
1264		p += hash->l;
1265	}
1266
1267	/* add payload */
1268	memcpy(p, payload->v, payload->l);
1269	p += payload->l;
1270
1271#ifdef HAVE_PRINT_ISAKMP_C
1272	isakmp_printpacket(iph2->sendbuf, iph1->local, iph1->remote, 1);
1273#endif
1274
1275	plog(LLV_DEBUG, LOCATION, NULL, "MODE_CFG packet to send\n");
1276	plogdump(LLV_DEBUG, iph2->sendbuf->v, iph2->sendbuf->l);
1277
1278	/* encoding */
1279	if (ISSET(isakmp->flags, ISAKMP_FLAG_E)) {
1280		vchar_t *tmp;
1281
1282		tmp = oakley_do_encrypt(iph2->ph1, iph2->sendbuf,
1283			ics->ivm->ive, ics->ivm->iv);
1284		VPTRINIT(iph2->sendbuf);
1285		if (tmp == NULL)
1286			goto err;
1287		iph2->sendbuf = tmp;
1288	}
1289
1290	/* HDR*, HASH(1), ATTR */
1291	if (isakmp_send(iph2->ph1, iph2->sendbuf) < 0) {
1292		VPTRINIT(iph2->sendbuf);
1293		goto err;
1294	}
1295
1296	plog(LLV_DEBUG, LOCATION, NULL,
1297		"sendto mode config %s.\n", s_isakmp_nptype(np));
1298
1299	/*
1300	 * XXX We might need to resend the message...
1301	 */
1302
1303	error = 0;
1304	VPTRINIT(iph2->sendbuf);
1305
1306err:
1307	if (iph2->sendbuf != NULL)
1308		vfree(iph2->sendbuf);
1309
1310	remph2(iph2);
1311	delph2(iph2);
1312end:
1313	if (hash)
1314		vfree(hash);
1315	return error;
1316}
1317
1318
1319void
1320isakmp_cfg_rmstate(iph1)
1321	struct ph1handle *iph1;
1322{
1323	struct isakmp_cfg_state *state = iph1->mode_cfg;
1324
1325	if (isakmp_cfg_accounting(iph1, ISAKMP_CFG_LOGOUT) != 0)
1326		plog(LLV_ERROR, LOCATION, NULL, "Accounting failed\n");
1327
1328	if (state->flags & ISAKMP_CFG_PORT_ALLOCATED)
1329		isakmp_cfg_putport(iph1, state->port);
1330
1331	/* Delete the IV if it's still there */
1332	if(iph1->mode_cfg->ivm) {
1333		oakley_delivm(iph1->mode_cfg->ivm);
1334		iph1->mode_cfg->ivm = NULL;
1335	}
1336
1337	/* Free any allocated splitnet lists */
1338	if(iph1->mode_cfg->split_include != NULL)
1339		splitnet_list_free(iph1->mode_cfg->split_include,
1340			&iph1->mode_cfg->include_count);
1341	if(iph1->mode_cfg->split_local != NULL)
1342		splitnet_list_free(iph1->mode_cfg->split_local,
1343			&iph1->mode_cfg->local_count);
1344
1345	xauth_rmstate(&state->xauth);
1346
1347	racoon_free(state);
1348	iph1->mode_cfg = NULL;
1349
1350	return;
1351}
1352
1353struct isakmp_cfg_state *
1354isakmp_cfg_mkstate(void)
1355{
1356	struct isakmp_cfg_state *state;
1357
1358	if ((state = racoon_malloc(sizeof(*state))) == NULL) {
1359		plog(LLV_ERROR, LOCATION, NULL,
1360		    "Cannot allocate memory for mode config state\n");
1361		return NULL;
1362	}
1363	memset(state, 0, sizeof(*state));
1364
1365	return state;
1366}
1367
1368int
1369isakmp_cfg_getport(iph1)
1370	struct ph1handle *iph1;
1371{
1372	unsigned int i;
1373	size_t size = isakmp_cfg_config.pool_size;
1374
1375	if (iph1->mode_cfg->flags & ISAKMP_CFG_PORT_ALLOCATED)
1376		return iph1->mode_cfg->port;
1377
1378	if (isakmp_cfg_config.port_pool == NULL) {
1379		plog(LLV_ERROR, LOCATION, NULL,
1380		    "isakmp_cfg_config.port_pool == NULL\n");
1381		return -1;
1382	}
1383
1384	for (i = 0; i < size; i++) {
1385		if (isakmp_cfg_config.port_pool[i].used == 0)
1386			break;
1387	}
1388
1389	if (i == size) {
1390		plog(LLV_ERROR, LOCATION, NULL,
1391		    "No more addresses available\n");
1392			return -1;
1393	}
1394
1395	isakmp_cfg_config.port_pool[i].used = 1;
1396
1397	plog(LLV_INFO, LOCATION, NULL, "Using port %d\n", i);
1398
1399	iph1->mode_cfg->flags |= ISAKMP_CFG_PORT_ALLOCATED;
1400	iph1->mode_cfg->port = i;
1401
1402	return i;
1403}
1404
1405int
1406isakmp_cfg_putport(iph1, index)
1407	struct ph1handle *iph1;
1408	unsigned int index;
1409{
1410	if (isakmp_cfg_config.port_pool == NULL) {
1411		plog(LLV_ERROR, LOCATION, NULL,
1412		    "isakmp_cfg_config.port_pool == NULL\n");
1413		return -1;
1414	}
1415
1416	if (isakmp_cfg_config.port_pool[index].used == 0) {
1417		plog(LLV_ERROR, LOCATION, NULL,
1418		    "Attempt to release an unallocated address (port %d)\n",
1419		    index);
1420		return -1;
1421	}
1422
1423#ifdef HAVE_LIBPAM
1424	/* Cleanup PAM status associated with the port */
1425	if (isakmp_cfg_config.authsource == ISAKMP_CFG_AUTH_PAM)
1426		privsep_cleanup_pam(index);
1427#endif
1428	isakmp_cfg_config.port_pool[index].used = 0;
1429	iph1->mode_cfg->flags &= ISAKMP_CFG_PORT_ALLOCATED;
1430
1431	plog(LLV_INFO, LOCATION, NULL, "Released port %d\n", index);
1432
1433	return 0;
1434}
1435
1436#ifdef HAVE_LIBPAM
1437void
1438cleanup_pam(port)
1439	int port;
1440{
1441	if (isakmp_cfg_config.port_pool[port].pam != NULL) {
1442		pam_end(isakmp_cfg_config.port_pool[port].pam, PAM_SUCCESS);
1443		isakmp_cfg_config.port_pool[port].pam = NULL;
1444	}
1445
1446	return;
1447}
1448#endif
1449
1450/* Accounting, only for RADIUS or PAM */
1451static int
1452isakmp_cfg_accounting(iph1, inout)
1453	struct ph1handle *iph1;
1454	int inout;
1455{
1456#ifdef HAVE_LIBPAM
1457	if (isakmp_cfg_config.accounting == ISAKMP_CFG_ACCT_PAM)
1458		return privsep_accounting_pam(iph1->mode_cfg->port,
1459		    inout);
1460#endif
1461#ifdef HAVE_LIBRADIUS
1462	if (isakmp_cfg_config.accounting == ISAKMP_CFG_ACCT_RADIUS)
1463		return isakmp_cfg_accounting_radius(iph1, inout);
1464#endif
1465	if (isakmp_cfg_config.accounting == ISAKMP_CFG_ACCT_SYSTEM)
1466		return privsep_accounting_system(iph1->mode_cfg->port,
1467			iph1->remote, iph1->mode_cfg->login, inout);
1468	return 0;
1469}
1470
1471#ifdef HAVE_LIBPAM
1472int
1473isakmp_cfg_accounting_pam(port, inout)
1474	int port;
1475	int inout;
1476{
1477	int error = 0;
1478	pam_handle_t *pam;
1479
1480	if (isakmp_cfg_config.port_pool == NULL) {
1481		plog(LLV_ERROR, LOCATION, NULL,
1482		    "isakmp_cfg_config.port_pool == NULL\n");
1483		return -1;
1484	}
1485
1486	pam = isakmp_cfg_config.port_pool[port].pam;
1487	if (pam == NULL) {
1488		plog(LLV_ERROR, LOCATION, NULL, "pam handle is NULL\n");
1489		return -1;
1490	}
1491
1492	switch (inout) {
1493	case ISAKMP_CFG_LOGIN:
1494		error = pam_open_session(pam, 0);
1495		break;
1496	case ISAKMP_CFG_LOGOUT:
1497		error = pam_close_session(pam, 0);
1498		pam_end(pam, error);
1499		isakmp_cfg_config.port_pool[port].pam = NULL;
1500		break;
1501	default:
1502		plog(LLV_ERROR, LOCATION, NULL, "Unepected inout\n");
1503		break;
1504	}
1505
1506	if (error != 0) {
1507		plog(LLV_ERROR, LOCATION, NULL,
1508		    "pam_open_session/pam_close_session failed: %s\n",
1509		    pam_strerror(pam, error));
1510		return -1;
1511        }
1512
1513	return 0;
1514}
1515#endif /* HAVE_LIBPAM */
1516
1517#ifdef HAVE_LIBRADIUS
1518static int
1519isakmp_cfg_accounting_radius(iph1, inout)
1520	struct ph1handle *iph1;
1521	int inout;
1522{
1523	if (rad_create_request(radius_acct_state,
1524	    RAD_ACCOUNTING_REQUEST) != 0) {
1525		plog(LLV_ERROR, LOCATION, NULL,
1526		    "rad_create_request failed: %s\n",
1527		    rad_strerror(radius_acct_state));
1528		return -1;
1529	}
1530
1531	if (rad_put_string(radius_acct_state, RAD_USER_NAME,
1532	    iph1->mode_cfg->login) != 0) {
1533		plog(LLV_ERROR, LOCATION, NULL,
1534		    "rad_put_string failed: %s\n",
1535		    rad_strerror(radius_acct_state));
1536		return -1;
1537	}
1538
1539	switch (inout) {
1540	case ISAKMP_CFG_LOGIN:
1541		inout = RAD_START;
1542		break;
1543	case ISAKMP_CFG_LOGOUT:
1544		inout = RAD_STOP;
1545		break;
1546	default:
1547		plog(LLV_ERROR, LOCATION, NULL, "Unepected inout\n");
1548		break;
1549	}
1550
1551	if (rad_put_addr(radius_acct_state,
1552	    RAD_FRAMED_IP_ADDRESS, iph1->mode_cfg->addr4) != 0) {
1553		plog(LLV_ERROR, LOCATION, NULL,
1554		    "rad_put_addr failed: %s\n",
1555		    rad_strerror(radius_acct_state));
1556		return -1;
1557	}
1558
1559	if (rad_put_addr(radius_acct_state,
1560	    RAD_LOGIN_IP_HOST, iph1->mode_cfg->addr4) != 0) {
1561		plog(LLV_ERROR, LOCATION, NULL,
1562		    "rad_put_addr failed: %s\n",
1563		    rad_strerror(radius_acct_state));
1564		return -1;
1565	}
1566
1567	if (rad_put_int(radius_acct_state, RAD_ACCT_STATUS_TYPE, inout) != 0) {
1568		plog(LLV_ERROR, LOCATION, NULL,
1569		    "rad_put_int failed: %s\n",
1570		    rad_strerror(radius_acct_state));
1571		return -1;
1572	}
1573
1574	if (isakmp_cfg_radius_common(radius_acct_state,
1575	    iph1->mode_cfg->port) != 0)
1576		return -1;
1577
1578	if (rad_send_request(radius_acct_state) != RAD_ACCOUNTING_RESPONSE) {
1579		plog(LLV_ERROR, LOCATION, NULL,
1580		    "rad_send_request failed: %s\n",
1581		    rad_strerror(radius_acct_state));
1582		return -1;
1583	}
1584
1585	return 0;
1586}
1587#endif /* HAVE_LIBRADIUS */
1588
1589/*
1590 * Attributes common to all RADIUS requests
1591 */
1592#ifdef HAVE_LIBRADIUS
1593int
1594isakmp_cfg_radius_common(radius_state, port)
1595	struct rad_handle *radius_state;
1596	int port;
1597{
1598	struct utsname name;
1599	static struct hostent *host = NULL;
1600	struct in_addr nas_addr;
1601
1602	/*
1603	 * Find our own IP by resolving our nodename
1604	 */
1605	if (host == NULL) {
1606		if (uname(&name) != 0) {
1607			plog(LLV_ERROR, LOCATION, NULL,
1608			    "uname failed: %s\n", strerror(errno));
1609			return -1;
1610		}
1611
1612		if ((host = gethostbyname(name.nodename)) == NULL) {
1613			plog(LLV_ERROR, LOCATION, NULL,
1614			    "gethostbyname failed: %s\n", strerror(errno));
1615			return -1;
1616		}
1617	}
1618
1619	memcpy(&nas_addr, host->h_addr, sizeof(nas_addr));
1620	if (rad_put_addr(radius_state, RAD_NAS_IP_ADDRESS, nas_addr) != 0) {
1621		plog(LLV_ERROR, LOCATION, NULL,
1622		    "rad_put_addr failed: %s\n",
1623		    rad_strerror(radius_state));
1624		return -1;
1625	}
1626
1627	if (rad_put_int(radius_state, RAD_NAS_PORT, port) != 0) {
1628		plog(LLV_ERROR, LOCATION, NULL,
1629		    "rad_put_int failed: %s\n",
1630		    rad_strerror(radius_state));
1631		return -1;
1632	}
1633
1634	if (rad_put_int(radius_state, RAD_NAS_PORT_TYPE, RAD_VIRTUAL) != 0) {
1635		plog(LLV_ERROR, LOCATION, NULL,
1636		    "rad_put_int failed: %s\n",
1637		    rad_strerror(radius_state));
1638		return -1;
1639	}
1640
1641	if (rad_put_int(radius_state, RAD_SERVICE_TYPE, RAD_FRAMED) != 0) {
1642		plog(LLV_ERROR, LOCATION, NULL,
1643		    "rad_put_int failed: %s\n",
1644		    rad_strerror(radius_state));
1645		return -1;
1646	}
1647
1648	return 0;
1649}
1650#endif
1651
1652/*
1653	Logs the user into the utmp system files.
1654*/
1655
1656int
1657isakmp_cfg_accounting_system(port, raddr, usr, inout)
1658	int port;
1659	struct sockaddr *raddr;
1660	char *usr;
1661	int inout;
1662{
1663	int error = 0;
1664	struct utmpx ut;
1665	char addr[NI_MAXHOST];
1666
1667	if (usr == NULL || usr[0]=='\0') {
1668		plog(LLV_ERROR, LOCATION, NULL,
1669			"system accounting : no login found\n");
1670		return -1;
1671	}
1672
1673	memset(&ut, 0, sizeof ut);
1674	gettimeofday((struct timeval *)&ut.ut_tv, NULL);
1675	snprintf(ut.ut_id, sizeof ut.ut_id, TERMSPEC, port);
1676
1677	switch (inout) {
1678	case ISAKMP_CFG_LOGIN:
1679		ut.ut_type = USER_PROCESS;
1680		strncpy(ut.ut_user, usr, sizeof ut.ut_user);
1681
1682		GETNAMEINFO_NULL(raddr, addr);
1683		strncpy(ut.ut_host, addr, sizeof ut.ut_host);
1684
1685		plog(LLV_INFO, LOCATION, NULL,
1686			"Accounting : '%s' logging on '%s' from %s.\n",
1687			ut.ut_user, ut.ut_id, addr);
1688
1689		pututxline(&ut);
1690
1691		break;
1692	case ISAKMP_CFG_LOGOUT:
1693		ut.ut_type = DEAD_PROCESS;
1694
1695		plog(LLV_INFO, LOCATION, NULL,
1696			"Accounting : '%s' unlogging from '%s'.\n",
1697			usr, ut.ut_id);
1698
1699		pututxline(&ut);
1700
1701		break;
1702	default:
1703		plog(LLV_ERROR, LOCATION, NULL, "Unepected inout\n");
1704		break;
1705	}
1706
1707	return 0;
1708}
1709
1710int
1711isakmp_cfg_getconfig(iph1)
1712	struct ph1handle *iph1;
1713{
1714	vchar_t *buffer;
1715	struct isakmp_pl_attr *attrpl;
1716	struct isakmp_data *attr;
1717	size_t len;
1718	int error;
1719	int attrcount;
1720	int i;
1721	int attrlist[] = {
1722		INTERNAL_IP4_ADDRESS,
1723		INTERNAL_IP4_NETMASK,
1724		INTERNAL_IP4_DNS,
1725		INTERNAL_IP4_NBNS,
1726		UNITY_BANNER,
1727		UNITY_DEF_DOMAIN,
1728		UNITY_SPLITDNS_NAME,
1729		UNITY_SPLIT_INCLUDE,
1730		UNITY_LOCAL_LAN,
1731		APPLICATION_VERSION,
1732	};
1733
1734	attrcount = sizeof(attrlist) / sizeof(*attrlist);
1735	len = sizeof(*attrpl) + sizeof(*attr) * attrcount;
1736
1737	if ((buffer = vmalloc(len)) == NULL) {
1738		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
1739		return -1;
1740	}
1741
1742	attrpl = (struct isakmp_pl_attr *)buffer->v;
1743	attrpl->h.len = htons(len);
1744	attrpl->type = ISAKMP_CFG_REQUEST;
1745	attrpl->id = htons((u_int16_t)(eay_random() & 0xffff));
1746
1747	attr = (struct isakmp_data *)(attrpl + 1);
1748
1749	for (i = 0; i < attrcount; i++) {
1750		attr->type = htons(attrlist[i]);
1751		attr->lorv = htons(0);
1752		attr++;
1753	}
1754
1755	plog(LLV_DEBUG, LOCATION, NULL,
1756		    "Sending MODE_CFG REQUEST\n");
1757
1758	error = isakmp_cfg_send(iph1, buffer,
1759	    ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 1);
1760
1761	vfree(buffer);
1762
1763	return error;
1764}
1765
1766static void
1767isakmp_cfg_getaddr4(attr, ip)
1768	struct isakmp_data *attr;
1769	struct in_addr *ip;
1770{
1771	size_t alen = ntohs(attr->lorv);
1772	in_addr_t *addr;
1773
1774	if (alen != sizeof(*ip)) {
1775		plog(LLV_ERROR, LOCATION, NULL, "Bad IPv4 address len\n");
1776		return;
1777	}
1778
1779	addr = (in_addr_t *)(attr + 1);
1780	ip->s_addr = *addr;
1781
1782	return;
1783}
1784
1785static void
1786isakmp_cfg_appendaddr4(attr, ip, num, max)
1787	struct isakmp_data *attr;
1788	struct in_addr *ip;
1789	int *num;
1790	int max;
1791{
1792	size_t alen = ntohs(attr->lorv);
1793	in_addr_t *addr;
1794
1795	if (alen != sizeof(*ip)) {
1796		plog(LLV_ERROR, LOCATION, NULL, "Bad IPv4 address len\n");
1797		return;
1798	}
1799	if (*num == max) {
1800		plog(LLV_ERROR, LOCATION, NULL, "Too many addresses given\n");
1801		return;
1802	}
1803
1804	addr = (in_addr_t *)(attr + 1);
1805	ip->s_addr = *addr;
1806	(*num)++;
1807
1808	return;
1809}
1810
1811static void
1812isakmp_cfg_getstring(attr, str)
1813	struct isakmp_data *attr;
1814	char *str;
1815{
1816	size_t alen = ntohs(attr->lorv);
1817	char *src;
1818	src = (char *)(attr + 1);
1819
1820	memcpy(str, src, (alen > MAXPATHLEN ? MAXPATHLEN : alen));
1821
1822	return;
1823}
1824
1825#define IP_MAX 40
1826
1827void
1828isakmp_cfg_iplist_to_str(dest, count, addr, withmask)
1829	char *dest;
1830	int count;
1831	void *addr;
1832	int withmask;
1833{
1834	int i;
1835	int p;
1836	int l;
1837	struct unity_network tmp;
1838	for(i = 0, p = 0; i < count; i++) {
1839		if(withmask == 1)
1840			l = sizeof(struct unity_network);
1841		else
1842			l = sizeof(struct in_addr);
1843		memcpy(&tmp, addr, l);
1844		addr += l;
1845		if((uint32_t)tmp.addr4.s_addr == 0)
1846			break;
1847
1848		inet_ntop(AF_INET, &tmp.addr4, dest + p, IP_MAX);
1849		p += strlen(dest + p);
1850		if(withmask == 1) {
1851			dest[p] = '/';
1852			p++;
1853			inet_ntop(AF_INET, &tmp.mask4, dest + p, IP_MAX);
1854			p += strlen(dest + p);
1855		}
1856		dest[p] = ' ';
1857		p++;
1858	}
1859	if(p > 0)
1860		dest[p-1] = '\0';
1861	else
1862		dest[0] = '\0';
1863}
1864
1865int
1866isakmp_cfg_setenv(iph1, envp, envc)
1867	struct ph1handle *iph1;
1868	char ***envp;
1869	int *envc;
1870{
1871	char addrstr[IP_MAX];
1872	char addrlist[IP_MAX * MAXNS + MAXNS];
1873	char *splitlist = addrlist;
1874	char *splitlist_cidr;
1875	char defdom[MAXPATHLEN + 1];
1876	int cidr, tmp;
1877	char cidrstr[4];
1878	int i, p;
1879	int test;
1880
1881	plog(LLV_DEBUG, LOCATION, NULL, "Starting a script.\n");
1882
1883	/*
1884	 * Internal IPv4 address, either if
1885	 * we are a client or a server.
1886	 */
1887	if ((iph1->mode_cfg->flags & ISAKMP_CFG_GOT_ADDR4) ||
1888#ifdef HAVE_LIBLDAP
1889	    (iph1->mode_cfg->flags & ISAKMP_CFG_ADDR4_EXTERN) ||
1890#endif
1891#ifdef HAVE_LIBRADIUS
1892	    (iph1->mode_cfg->flags & ISAKMP_CFG_ADDR4_EXTERN) ||
1893#endif
1894	    (iph1->mode_cfg->flags & ISAKMP_CFG_ADDR4_LOCAL)) {
1895		inet_ntop(AF_INET, &iph1->mode_cfg->addr4,
1896		    addrstr, IP_MAX);
1897	} else
1898		addrstr[0] = '\0';
1899
1900	if (script_env_append(envp, envc, "INTERNAL_ADDR4", addrstr) != 0) {
1901		plog(LLV_ERROR, LOCATION, NULL, "Cannot set INTERNAL_ADDR4\n");
1902		return -1;
1903	}
1904
1905	if (iph1->mode_cfg->xauth.authdata.generic.usr != NULL) {
1906		if (script_env_append(envp, envc, "XAUTH_USER",
1907		    iph1->mode_cfg->xauth.authdata.generic.usr) != 0) {
1908			plog(LLV_ERROR, LOCATION, NULL,
1909			    "Cannot set XAUTH_USER\n");
1910			return -1;
1911		}
1912	}
1913
1914	/* Internal IPv4 mask */
1915	if (iph1->mode_cfg->flags & ISAKMP_CFG_GOT_MASK4)
1916		inet_ntop(AF_INET, &iph1->mode_cfg->mask4,
1917		    addrstr, IP_MAX);
1918	else
1919		addrstr[0] = '\0';
1920
1921	/*
1922	 * During several releases, documentation adverised INTERNAL_NETMASK4
1923	 * while code was using INTERNAL_MASK4. We now do both.
1924	 */
1925
1926	if (script_env_append(envp, envc, "INTERNAL_MASK4", addrstr) != 0) {
1927		plog(LLV_ERROR, LOCATION, NULL, "Cannot set INTERNAL_MASK4\n");
1928		return -1;
1929	}
1930
1931	if (script_env_append(envp, envc, "INTERNAL_NETMASK4", addrstr) != 0) {
1932		plog(LLV_ERROR, LOCATION, NULL,
1933		    "Cannot set INTERNAL_NETMASK4\n");
1934		return -1;
1935	}
1936
1937	tmp = ntohl(iph1->mode_cfg->mask4.s_addr);
1938	for (cidr = 0; tmp != 0; cidr++)
1939		tmp <<= 1;
1940	snprintf(cidrstr, 3, "%d", cidr);
1941
1942	if (script_env_append(envp, envc, "INTERNAL_CIDR4", cidrstr) != 0) {
1943		plog(LLV_ERROR, LOCATION, NULL, "Cannot set INTERNAL_CIDR4\n");
1944		return -1;
1945	}
1946
1947	/* Internal IPv4 DNS */
1948	if (iph1->mode_cfg->flags & ISAKMP_CFG_GOT_DNS4) {
1949		/* First Internal IPv4 DNS (for compatibilty with older code */
1950		inet_ntop(AF_INET, &iph1->mode_cfg->dns4[0],
1951		    addrstr, IP_MAX);
1952
1953		/* Internal IPv4 DNS - all */
1954		isakmp_cfg_iplist_to_str(addrlist, iph1->mode_cfg->dns4_index,
1955			(void *)iph1->mode_cfg->dns4, 0);
1956	} else {
1957		addrstr[0] = '\0';
1958		addrlist[0] = '\0';
1959	}
1960
1961	if (script_env_append(envp, envc, "INTERNAL_DNS4", addrstr) != 0) {
1962		plog(LLV_ERROR, LOCATION, NULL, "Cannot set INTERNAL_DNS4\n");
1963		return -1;
1964	}
1965	if (script_env_append(envp, envc, "INTERNAL_DNS4_LIST", addrlist) != 0) {
1966		plog(LLV_ERROR, LOCATION, NULL,
1967		    "Cannot set INTERNAL_DNS4_LIST\n");
1968		return -1;
1969	}
1970
1971	/* Internal IPv4 WINS */
1972	if (iph1->mode_cfg->flags & ISAKMP_CFG_GOT_WINS4) {
1973		/*
1974		 * First Internal IPv4 WINS
1975		 * (for compatibilty with older code
1976		 */
1977		inet_ntop(AF_INET, &iph1->mode_cfg->wins4[0],
1978		    addrstr, IP_MAX);
1979
1980		/* Internal IPv4 WINS - all */
1981		isakmp_cfg_iplist_to_str(addrlist, iph1->mode_cfg->wins4_index,
1982			(void *)iph1->mode_cfg->wins4, 0);
1983	} else {
1984		addrstr[0] = '\0';
1985		addrlist[0] = '\0';
1986	}
1987
1988	if (script_env_append(envp, envc, "INTERNAL_WINS4", addrstr) != 0) {
1989		plog(LLV_ERROR, LOCATION, NULL,
1990		    "Cannot set INTERNAL_WINS4\n");
1991		return -1;
1992	}
1993	if (script_env_append(envp, envc,
1994	    "INTERNAL_WINS4_LIST", addrlist) != 0) {
1995		plog(LLV_ERROR, LOCATION, NULL,
1996		    "Cannot set INTERNAL_WINS4_LIST\n");
1997		return -1;
1998	}
1999
2000	/* Deault domain */
2001	if(iph1->mode_cfg->flags & ISAKMP_CFG_GOT_DEFAULT_DOMAIN)
2002		strncpy(defdom,
2003		    iph1->mode_cfg->default_domain,
2004		    MAXPATHLEN + 1);
2005	else
2006		defdom[0] = '\0';
2007
2008	if (script_env_append(envp, envc, "DEFAULT_DOMAIN", defdom) != 0) {
2009		plog(LLV_ERROR, LOCATION, NULL,
2010		    "Cannot set DEFAULT_DOMAIN\n");
2011		return -1;
2012	}
2013
2014	/* Split networks */
2015	if (iph1->mode_cfg->flags & ISAKMP_CFG_GOT_SPLIT_INCLUDE) {
2016		splitlist =
2017		    splitnet_list_2str(iph1->mode_cfg->split_include, NETMASK);
2018		splitlist_cidr =
2019		    splitnet_list_2str(iph1->mode_cfg->split_include, CIDR);
2020	} else {
2021		splitlist = addrlist;
2022		splitlist_cidr = addrlist;
2023		addrlist[0] = '\0';
2024	}
2025
2026	if (script_env_append(envp, envc, "SPLIT_INCLUDE", splitlist) != 0) {
2027		plog(LLV_ERROR, LOCATION, NULL, "Cannot set SPLIT_INCLUDE\n");
2028		return -1;
2029	}
2030	if (script_env_append(envp, envc,
2031	    "SPLIT_INCLUDE_CIDR", splitlist_cidr) != 0) {
2032		plog(LLV_ERROR, LOCATION, NULL,
2033		     "Cannot set SPLIT_INCLUDE_CIDR\n");
2034		return -1;
2035	}
2036	if (splitlist != addrlist)
2037		racoon_free(splitlist);
2038	if (splitlist_cidr != addrlist)
2039		racoon_free(splitlist_cidr);
2040
2041	if (iph1->mode_cfg->flags & ISAKMP_CFG_GOT_SPLIT_LOCAL) {
2042		splitlist =
2043		    splitnet_list_2str(iph1->mode_cfg->split_local, NETMASK);
2044		splitlist_cidr =
2045		    splitnet_list_2str(iph1->mode_cfg->split_local, CIDR);
2046	} else {
2047		splitlist = addrlist;
2048		splitlist_cidr = addrlist;
2049		addrlist[0] = '\0';
2050	}
2051
2052	if (script_env_append(envp, envc, "SPLIT_LOCAL", splitlist) != 0) {
2053		plog(LLV_ERROR, LOCATION, NULL, "Cannot set SPLIT_LOCAL\n");
2054		return -1;
2055	}
2056	if (script_env_append(envp, envc,
2057	    "SPLIT_LOCAL_CIDR", splitlist_cidr) != 0) {
2058		plog(LLV_ERROR, LOCATION, NULL,
2059		     "Cannot set SPLIT_LOCAL_CIDR\n");
2060		return -1;
2061	}
2062	if (splitlist != addrlist)
2063		racoon_free(splitlist);
2064	if (splitlist_cidr != addrlist)
2065		racoon_free(splitlist_cidr);
2066
2067	return 0;
2068}
2069
2070int
2071isakmp_cfg_resize_pool(size)
2072	int size;
2073{
2074	struct isakmp_cfg_port *new_pool;
2075	size_t len;
2076	int i;
2077
2078	if (size == isakmp_cfg_config.pool_size)
2079		return 0;
2080
2081	plog(LLV_INFO, LOCATION, NULL,
2082	    "Resize address pool from %zu to %d\n",
2083	    isakmp_cfg_config.pool_size, size);
2084
2085	/* If a pool already exists, check if we can shrink it */
2086	if ((isakmp_cfg_config.port_pool != NULL) &&
2087	    (size < isakmp_cfg_config.pool_size)) {
2088		for (i = isakmp_cfg_config.pool_size-1; i >= size; --i) {
2089			if (isakmp_cfg_config.port_pool[i].used) {
2090				plog(LLV_ERROR, LOCATION, NULL,
2091				    "resize pool from %zu to %d impossible "
2092				    "port %d is in use\n",
2093				    isakmp_cfg_config.pool_size, size, i);
2094				size = i;
2095				break;
2096			}
2097		}
2098	}
2099
2100	len = size * sizeof(*isakmp_cfg_config.port_pool);
2101	new_pool = racoon_realloc(isakmp_cfg_config.port_pool, len);
2102	if (new_pool == NULL) {
2103		plog(LLV_ERROR, LOCATION, NULL,
2104		    "resize pool from %zu to %d impossible: %s",
2105		    isakmp_cfg_config.pool_size, size, strerror(errno));
2106		return -1;
2107	}
2108
2109	/* If size increase, intialize correctly the new records */
2110	if (size > isakmp_cfg_config.pool_size) {
2111		size_t unit;
2112		size_t old_size;
2113
2114		unit =  sizeof(*isakmp_cfg_config.port_pool);
2115		old_size = isakmp_cfg_config.pool_size;
2116
2117		bzero((char *)new_pool + (old_size * unit),
2118		    (size - old_size) * unit);
2119	}
2120
2121	isakmp_cfg_config.port_pool = new_pool;
2122	isakmp_cfg_config.pool_size = size;
2123
2124	return 0;
2125}
2126
2127int
2128isakmp_cfg_init(cold)
2129	int cold;
2130{
2131	int i;
2132	int error;
2133
2134	isakmp_cfg_config.network4 = (in_addr_t)0x00000000;
2135	isakmp_cfg_config.netmask4 = (in_addr_t)0x00000000;
2136	for (i = 0; i < MAXNS; i++)
2137		isakmp_cfg_config.dns4[i] = (in_addr_t)0x00000000;
2138	isakmp_cfg_config.dns4_index = 0;
2139	for (i = 0; i < MAXWINS; i++)
2140		isakmp_cfg_config.nbns4[i] = (in_addr_t)0x00000000;
2141	isakmp_cfg_config.nbns4_index = 0;
2142	if (cold == ISAKMP_CFG_INIT_COLD)
2143		isakmp_cfg_config.port_pool = NULL;
2144	isakmp_cfg_config.authsource = ISAKMP_CFG_AUTH_SYSTEM;
2145	isakmp_cfg_config.groupsource = ISAKMP_CFG_GROUP_SYSTEM;
2146	if (cold == ISAKMP_CFG_INIT_COLD) {
2147		if (isakmp_cfg_config.grouplist != NULL) {
2148			for (i = 0; i < isakmp_cfg_config.groupcount; i++)
2149				racoon_free(isakmp_cfg_config.grouplist[i]);
2150			racoon_free(isakmp_cfg_config.grouplist);
2151		}
2152	}
2153	isakmp_cfg_config.grouplist = NULL;
2154	isakmp_cfg_config.groupcount = 0;
2155	isakmp_cfg_config.confsource = ISAKMP_CFG_CONF_LOCAL;
2156	isakmp_cfg_config.accounting = ISAKMP_CFG_ACCT_NONE;
2157	if (cold == ISAKMP_CFG_INIT_COLD)
2158		isakmp_cfg_config.pool_size = 0;
2159	isakmp_cfg_config.auth_throttle = THROTTLE_PENALTY;
2160	strlcpy(isakmp_cfg_config.default_domain, ISAKMP_CFG_DEFAULT_DOMAIN,
2161	    MAXPATHLEN);
2162	strlcpy(isakmp_cfg_config.motd, ISAKMP_CFG_MOTD, MAXPATHLEN);
2163
2164	if (cold != ISAKMP_CFG_INIT_COLD )
2165		if (isakmp_cfg_config.splitnet_list != NULL)
2166			splitnet_list_free(isakmp_cfg_config.splitnet_list,
2167				&isakmp_cfg_config.splitnet_count);
2168	isakmp_cfg_config.splitnet_list = NULL;
2169	isakmp_cfg_config.splitnet_count = 0;
2170	isakmp_cfg_config.splitnet_type = 0;
2171
2172	isakmp_cfg_config.pfs_group = 0;
2173	isakmp_cfg_config.save_passwd = 0;
2174
2175	if (cold != ISAKMP_CFG_INIT_COLD )
2176		if (isakmp_cfg_config.splitdns_list != NULL)
2177			racoon_free(isakmp_cfg_config.splitdns_list);
2178	isakmp_cfg_config.splitdns_list = NULL;
2179	isakmp_cfg_config.splitdns_len = 0;
2180
2181#if 0
2182	if (cold == ISAKMP_CFG_INIT_COLD) {
2183		if ((error = isakmp_cfg_resize_pool(ISAKMP_CFG_MAX_CNX)) != 0)
2184			return error;
2185	}
2186#endif
2187
2188	return 0;
2189}
2190
2191