1/*	$NetBSD: isakmp_cfg.c,v 1.12.6.4 2008/11/27 15:25:20 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#ifndef ANDROID_PATCHED
42#include <utmp.h>
43#endif
44#if defined(__APPLE__) && defined(__MACH__)
45#include <util.h>
46#endif
47
48#ifdef __FreeBSD__
49# include <libutil.h>
50#endif
51#ifdef __NetBSD__
52#  include <util.h>
53#endif
54
55#include <netinet/in.h>
56#include <arpa/inet.h>
57
58#include <stdlib.h>
59#include <stdio.h>
60#include <string.h>
61#include <errno.h>
62#if TIME_WITH_SYS_TIME
63# include <sys/time.h>
64# include <time.h>
65#else
66# if HAVE_SYS_TIME_H
67#  include <sys/time.h>
68# else
69#  include <time.h>
70# endif
71#endif
72#include <netdb.h>
73#ifdef HAVE_UNISTD_H
74#include <unistd.h>
75#endif
76#if HAVE_STDINT_H
77#include <stdint.h>
78#endif
79#include <ctype.h>
80#include <resolv.h>
81
82#ifdef HAVE_LIBRADIUS
83#include <sys/utsname.h>
84#include <radlib.h>
85#endif
86
87#include "var.h"
88#include "misc.h"
89#include "vmbuf.h"
90#include "plog.h"
91#include "sockmisc.h"
92#include "schedule.h"
93#include "debug.h"
94
95#include "isakmp_var.h"
96#include "isakmp.h"
97#include "handler.h"
98#include "evt.h"
99#include "throttle.h"
100#include "remoteconf.h"
101#include "crypto_openssl.h"
102#include "isakmp_inf.h"
103#include "isakmp_xauth.h"
104#include "isakmp_unity.h"
105#include "isakmp_cfg.h"
106#include "strnames.h"
107#include "admin.h"
108#include "privsep.h"
109
110struct isakmp_cfg_config isakmp_cfg_config;
111
112static vchar_t *buffer_cat(vchar_t *s, vchar_t *append);
113static vchar_t *isakmp_cfg_net(struct ph1handle *, struct isakmp_data *);
114#if 0
115static vchar_t *isakmp_cfg_void(struct ph1handle *, struct isakmp_data *);
116#endif
117static vchar_t *isakmp_cfg_addr4(struct ph1handle *,
118				 struct isakmp_data *, 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 (AUTHMETHOD(iph1)) {
452		case FICTIVE_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_PUSH(iph1->local, iph1->remote,
479			    EVTT_ISAKMP_CFG_DONE, buf);
480			vfree(buf);
481		}
482	}
483#endif
484
485	return 0;
486}
487
488int
489isakmp_cfg_request(iph1, attrpl)
490	struct ph1handle *iph1;
491	struct isakmp_pl_attr *attrpl;
492{
493	struct isakmp_data *attr;
494	int tlen;
495	size_t alen;
496	char *npp;
497	vchar_t *payload;
498	struct isakmp_pl_attr *reply;
499	vchar_t *reply_attr;
500	int type;
501	int error = -1;
502
503	if ((payload = vmalloc(sizeof(*reply))) == NULL) {
504		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
505		return -1;
506	}
507	memset(payload->v, 0, sizeof(*reply));
508
509	tlen = ntohs(attrpl->h.len);
510	attr = (struct isakmp_data *)(attrpl + 1);
511	tlen -= sizeof(*attrpl);
512
513	while (tlen > 0) {
514		reply_attr = NULL;
515		type = ntohs(attr->type);
516
517		/* Handle short attributes */
518		if ((type & ISAKMP_GEN_MASK) == ISAKMP_GEN_TV) {
519			type &= ~ISAKMP_GEN_MASK;
520
521			plog(LLV_DEBUG, LOCATION, NULL,
522			     "Short attribute %s = %d\n",
523			     s_isakmp_cfg_type(type), ntohs(attr->lorv));
524
525			switch (type) {
526			case XAUTH_TYPE:
527				reply_attr = isakmp_xauth_req(iph1, attr);
528				break;
529			default:
530				plog(LLV_WARNING, LOCATION, NULL,
531				     "Ignored short attribute %s\n",
532				     s_isakmp_cfg_type(type));
533				break;
534			}
535
536			tlen -= sizeof(*attr);
537			attr++;
538
539			if (reply_attr != NULL) {
540				payload = buffer_cat(payload, reply_attr);
541				vfree(reply_attr);
542			}
543
544			continue;
545		}
546
547		type = ntohs(attr->type);
548		alen = ntohs(attr->lorv);
549
550		/* Check that the attribute fit in the packet */
551		if (tlen < alen) {
552			plog(LLV_ERROR, LOCATION, NULL,
553			     "Short attribute %s\n",
554			     s_isakmp_cfg_type(type));
555			goto end;
556		}
557
558		plog(LLV_DEBUG, LOCATION, NULL,
559		     "Attribute %s, len %zu\n",
560		     s_isakmp_cfg_type(type), alen);
561
562		switch(type) {
563		case INTERNAL_IP4_ADDRESS:
564		case INTERNAL_IP4_NETMASK:
565		case INTERNAL_IP4_DNS:
566		case INTERNAL_IP4_NBNS:
567		case INTERNAL_IP4_SUBNET:
568			reply_attr = isakmp_cfg_net(iph1, attr);
569			break;
570
571		case XAUTH_TYPE:
572		case XAUTH_USER_NAME:
573		case XAUTH_USER_PASSWORD:
574		case XAUTH_PASSCODE:
575		case XAUTH_MESSAGE:
576		case XAUTH_CHALLENGE:
577		case XAUTH_DOMAIN:
578		case XAUTH_STATUS:
579		case XAUTH_NEXT_PIN:
580		case XAUTH_ANSWER:
581			reply_attr = isakmp_xauth_req(iph1, attr);
582			break;
583
584		case APPLICATION_VERSION:
585			reply_attr = isakmp_cfg_string(iph1,
586			    attr, ISAKMP_CFG_RACOON_VERSION);
587			break;
588
589		case UNITY_BANNER:
590		case UNITY_PFS:
591		case UNITY_SAVE_PASSWD:
592		case UNITY_DEF_DOMAIN:
593		case UNITY_DDNS_HOSTNAME:
594		case UNITY_FW_TYPE:
595		case UNITY_SPLITDNS_NAME:
596		case UNITY_SPLIT_INCLUDE:
597		case UNITY_LOCAL_LAN:
598		case UNITY_NATT_PORT:
599		case UNITY_BACKUP_SERVERS:
600			reply_attr = isakmp_unity_req(iph1, attr);
601			break;
602
603		case INTERNAL_ADDRESS_EXPIRY:
604		default:
605			plog(LLV_WARNING, LOCATION, NULL,
606			     "Ignored attribute %s\n",
607			     s_isakmp_cfg_type(type));
608			break;
609		}
610
611		npp = (char *)attr;
612		attr = (struct isakmp_data *)(npp + sizeof(*attr) + alen);
613		tlen -= (sizeof(*attr) + alen);
614
615		if (reply_attr != NULL) {
616			payload = buffer_cat(payload, reply_attr);
617			vfree(reply_attr);
618		}
619
620	}
621
622	reply = (struct isakmp_pl_attr *)payload->v;
623	reply->h.len = htons(payload->l);
624	reply->type = ISAKMP_CFG_REPLY;
625	reply->id = attrpl->id;
626
627	plog(LLV_DEBUG, LOCATION, NULL,
628		    "Sending MODE_CFG REPLY\n");
629
630	error = isakmp_cfg_send(iph1, payload,
631	    ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 0);
632
633	if (iph1->status == PHASE1ST_ESTABLISHED) {
634		switch (AUTHMETHOD(iph1)) {
635		case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
636		case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
637		/* Unimplemented */
638		case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
639		case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
640		case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
641		case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
642		case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
643			script_hook(iph1, SCRIPT_PHASE1_UP);
644			break;
645		default:
646			break;
647		}
648	}
649
650end:
651	vfree(payload);
652
653	return error;
654}
655
656int
657isakmp_cfg_set(iph1, attrpl)
658	struct ph1handle *iph1;
659	struct isakmp_pl_attr *attrpl;
660{
661	struct isakmp_data *attr;
662	int tlen;
663	size_t alen;
664	char *npp;
665	vchar_t *payload;
666	struct isakmp_pl_attr *reply;
667	vchar_t *reply_attr;
668	int type;
669	int error = -1;
670
671	if ((payload = vmalloc(sizeof(*reply))) == NULL) {
672		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
673		return -1;
674	}
675	memset(payload->v, 0, sizeof(*reply));
676
677	tlen = ntohs(attrpl->h.len);
678	attr = (struct isakmp_data *)(attrpl + 1);
679	tlen -= sizeof(*attrpl);
680
681	/*
682	 * We should send ack for the attributes we accepted
683	 */
684	while (tlen > 0) {
685		reply_attr = NULL;
686		type = ntohs(attr->type);
687
688		plog(LLV_DEBUG, LOCATION, NULL,
689		     "Attribute %s\n",
690		     s_isakmp_cfg_type(type & ~ISAKMP_GEN_MASK));
691
692		switch (type & ~ISAKMP_GEN_MASK) {
693		case XAUTH_STATUS:
694			reply_attr = isakmp_xauth_set(iph1, attr);
695			break;
696		default:
697			plog(LLV_DEBUG, LOCATION, NULL,
698			     "Unexpected SET attribute %s\n",
699		     	     s_isakmp_cfg_type(type & ~ISAKMP_GEN_MASK));
700			break;
701		}
702
703		if (reply_attr != NULL) {
704			payload = buffer_cat(payload, reply_attr);
705			vfree(reply_attr);
706		}
707
708		/*
709		 * Move to next attribute. If we run out of the packet,
710		 * tlen becomes negative and we exit.
711		 */
712		if ((type & ISAKMP_GEN_MASK) == ISAKMP_GEN_TV) {
713			tlen -= sizeof(*attr);
714			attr++;
715		} else {
716			alen = ntohs(attr->lorv);
717			tlen -= (sizeof(*attr) + alen);
718			npp = (char *)attr;
719			attr = (struct isakmp_data *)
720			    (npp + sizeof(*attr) + alen);
721		}
722	}
723
724	reply = (struct isakmp_pl_attr *)payload->v;
725	reply->h.len = htons(payload->l);
726	reply->type = ISAKMP_CFG_ACK;
727	reply->id = attrpl->id;
728
729	plog(LLV_DEBUG, LOCATION, NULL,
730		     "Sending MODE_CFG ACK\n");
731
732	error = isakmp_cfg_send(iph1, payload,
733	    ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 0);
734
735	if (iph1->mode_cfg->flags & ISAKMP_CFG_DELETE_PH1) {
736		if (iph1->status == PHASE1ST_ESTABLISHED)
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		return isakmp_cfg_addr4(iph1,
907		    attr, &isakmp_cfg_config.network4);
908		break;
909
910	default:
911		plog(LLV_ERROR, LOCATION, NULL, "Unexpected type %d\n", type);
912		break;
913	}
914	return NULL;
915}
916
917#if 0
918static vchar_t *
919isakmp_cfg_void(iph1, attr)
920	struct ph1handle *iph1;
921	struct isakmp_data *attr;
922{
923	vchar_t *buffer;
924	struct isakmp_data *new;
925
926	if ((buffer = vmalloc(sizeof(*attr))) == NULL) {
927		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
928		return NULL;
929	}
930
931	new = (struct isakmp_data *)buffer->v;
932
933	new->type = attr->type;
934	new->lorv = htons(0);
935
936	return buffer;
937}
938#endif
939
940vchar_t *
941isakmp_cfg_copy(iph1, attr)
942	struct ph1handle *iph1;
943	struct isakmp_data *attr;
944{
945	vchar_t *buffer;
946	size_t len = 0;
947
948	if ((ntohs(attr->type) & ISAKMP_GEN_MASK) == ISAKMP_GEN_TLV)
949		len = ntohs(attr->lorv);
950
951	if ((buffer = vmalloc(sizeof(*attr) + len)) == NULL) {
952		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
953		return NULL;
954	}
955
956	memcpy(buffer->v, attr, sizeof(*attr) + ntohs(attr->lorv));
957
958	return buffer;
959}
960
961vchar_t *
962isakmp_cfg_short(iph1, attr, value)
963	struct ph1handle *iph1;
964	struct isakmp_data *attr;
965	int value;
966{
967	vchar_t *buffer;
968	struct isakmp_data *new;
969	int type;
970
971	if ((buffer = vmalloc(sizeof(*attr))) == NULL) {
972		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
973		return NULL;
974	}
975
976	new = (struct isakmp_data *)buffer->v;
977	type = ntohs(attr->type) & ~ISAKMP_GEN_MASK;
978
979	new->type = htons(type | ISAKMP_GEN_TV);
980	new->lorv = htons(value);
981
982	return buffer;
983}
984
985vchar_t *
986isakmp_cfg_varlen(iph1, attr, string, len)
987	struct ph1handle *iph1;
988	struct isakmp_data *attr;
989	char *string;
990	size_t len;
991{
992	vchar_t *buffer;
993	struct isakmp_data *new;
994	char *data;
995
996	if ((buffer = vmalloc(sizeof(*attr) + len)) == NULL) {
997		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
998		return NULL;
999	}
1000
1001	new = (struct isakmp_data *)buffer->v;
1002
1003	new->type = attr->type;
1004	new->lorv = htons(len);
1005	data = (char *)(new + 1);
1006
1007	memcpy(data, string, len);
1008
1009	return buffer;
1010}
1011vchar_t *
1012isakmp_cfg_string(iph1, attr, string)
1013	struct ph1handle *iph1;
1014	struct isakmp_data *attr;
1015	char *string;
1016{
1017	size_t len = strlen(string);
1018	return isakmp_cfg_varlen(iph1, attr, string, len);
1019}
1020
1021static vchar_t *
1022isakmp_cfg_addr4(iph1, attr, addr)
1023	struct ph1handle *iph1;
1024	struct isakmp_data *attr;
1025	in_addr_t *addr;
1026{
1027	vchar_t *buffer;
1028	struct isakmp_data *new;
1029	size_t len;
1030
1031	len = sizeof(*addr);
1032	if ((buffer = vmalloc(sizeof(*attr) + len)) == NULL) {
1033		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
1034		return NULL;
1035	}
1036
1037	new = (struct isakmp_data *)buffer->v;
1038
1039	new->type = attr->type;
1040	new->lorv = htons(len);
1041	memcpy(new + 1, addr, len);
1042
1043	return buffer;
1044}
1045
1046static vchar_t *
1047isakmp_cfg_addr4_list(iph1, attr, addr, nbr)
1048	struct ph1handle *iph1;
1049	struct isakmp_data *attr;
1050	in_addr_t *addr;
1051	int nbr;
1052{
1053	int error = -1;
1054	vchar_t *buffer = NULL;
1055	vchar_t *bufone = NULL;
1056	struct isakmp_data *new;
1057	size_t len;
1058	int i;
1059
1060	len = sizeof(*addr);
1061	if ((buffer = vmalloc(0)) == NULL) {
1062		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
1063		goto out;
1064	}
1065	for(i = 0; i < nbr; i++) {
1066		if ((bufone = vmalloc(sizeof(*attr) + len)) == NULL) {
1067			plog(LLV_ERROR, LOCATION, NULL,
1068			    "Cannot allocate memory\n");
1069			goto out;
1070		}
1071		new = (struct isakmp_data *)bufone->v;
1072		new->type = attr->type;
1073		new->lorv = htons(len);
1074		memcpy(new + 1, &addr[i], len);
1075		new += (len + sizeof(*attr));
1076		buffer = buffer_cat(buffer, bufone);
1077		vfree(bufone);
1078	}
1079
1080	error = 0;
1081
1082out:
1083	if ((error != 0) && (buffer != NULL)) {
1084		vfree(buffer);
1085		buffer = NULL;
1086	}
1087
1088	return buffer;
1089}
1090
1091struct isakmp_ivm *
1092isakmp_cfg_newiv(iph1, msgid)
1093	struct ph1handle *iph1;
1094	u_int32_t msgid;
1095{
1096	struct isakmp_cfg_state *ics = iph1->mode_cfg;
1097
1098	if (ics == NULL) {
1099		plog(LLV_ERROR, LOCATION, NULL,
1100		    "isakmp_cfg_newiv called without mode config state\n");
1101		return NULL;
1102	}
1103
1104	if (ics->ivm != NULL)
1105		oakley_delivm(ics->ivm);
1106
1107	ics->ivm = oakley_newiv2(iph1, msgid);
1108	ics->last_msgid = msgid;
1109
1110	return ics->ivm;
1111}
1112
1113/* Derived from isakmp_info_send_common */
1114int
1115isakmp_cfg_send(iph1, payload, np, flags, new_exchange)
1116	struct ph1handle *iph1;
1117	vchar_t *payload;
1118	u_int32_t np;
1119	int flags;
1120	int new_exchange;
1121{
1122	struct ph2handle *iph2 = NULL;
1123	vchar_t *hash = NULL;
1124	struct isakmp *isakmp;
1125	struct isakmp_gen *gen;
1126	char *p;
1127	int tlen;
1128	int error = -1;
1129	struct isakmp_cfg_state *ics = iph1->mode_cfg;
1130
1131	/* Check if phase 1 is established */
1132	if ((iph1->status != PHASE1ST_ESTABLISHED) ||
1133	    (iph1->local == NULL) ||
1134	    (iph1->remote == NULL)) {
1135		plog(LLV_ERROR, LOCATION, NULL,
1136		    "ISAKMP mode config exchange with immature phase 1\n");
1137		goto end;
1138	}
1139
1140	/* add new entry to isakmp status table */
1141	iph2 = newph2();
1142	if (iph2 == NULL)
1143		goto end;
1144
1145	iph2->dst = dupsaddr(iph1->remote);
1146	if (iph2->dst == NULL) {
1147		delph2(iph2);
1148		goto end;
1149	}
1150	iph2->src = dupsaddr(iph1->local);
1151	if (iph2->src == NULL) {
1152		delph2(iph2);
1153		goto end;
1154	}
1155
1156#if (!defined(ENABLE_NATT)) || (defined(BROKEN_NATT))
1157	if (set_port(iph2->dst, 0) == NULL ||
1158	    set_port(iph2->src, 0) == NULL) {
1159		plog(LLV_ERROR, LOCATION, NULL,
1160		     "invalid family: %d\n", iph1->remote->sa_family);
1161		delph2(iph2);
1162		goto end;
1163	}
1164#endif
1165	iph2->ph1 = iph1;
1166	iph2->side = INITIATOR;
1167	iph2->status = PHASE2ST_START;
1168
1169	if (new_exchange)
1170		iph2->msgid = isakmp_newmsgid2(iph1);
1171	else
1172		iph2->msgid = iph1->msgid;
1173
1174	/* get IV and HASH(1) if skeyid_a was generated. */
1175	if (iph1->skeyid_a != NULL) {
1176		if (new_exchange) {
1177			if (isakmp_cfg_newiv(iph1, iph2->msgid) == NULL) {
1178				delph2(iph2);
1179				goto end;
1180			}
1181		}
1182
1183		/* generate HASH(1) */
1184		hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, payload);
1185		if (hash == NULL) {
1186			delph2(iph2);
1187			goto end;
1188		}
1189
1190		/* initialized total buffer length */
1191		tlen = hash->l;
1192		tlen += sizeof(*gen);
1193	} else {
1194		/* IKE-SA is not established */
1195		hash = NULL;
1196
1197		/* initialized total buffer length */
1198		tlen = 0;
1199	}
1200	if ((flags & ISAKMP_FLAG_A) == 0)
1201		iph2->flags = (hash == NULL ? 0 : ISAKMP_FLAG_E);
1202	else
1203		iph2->flags = (hash == NULL ? 0 : ISAKMP_FLAG_A);
1204
1205	insph2(iph2);
1206	bindph12(iph1, iph2);
1207
1208	tlen += sizeof(*isakmp) + payload->l;
1209
1210	/* create buffer for isakmp payload */
1211	iph2->sendbuf = vmalloc(tlen);
1212	if (iph2->sendbuf == NULL) {
1213		plog(LLV_ERROR, LOCATION, NULL,
1214			"failed to get buffer to send.\n");
1215		goto err;
1216	}
1217
1218	/* create isakmp header */
1219	isakmp = (struct isakmp *)iph2->sendbuf->v;
1220	memcpy(&isakmp->i_ck, &iph1->index.i_ck, sizeof(cookie_t));
1221	memcpy(&isakmp->r_ck, &iph1->index.r_ck, sizeof(cookie_t));
1222	isakmp->np = hash == NULL ? (np & 0xff) : ISAKMP_NPTYPE_HASH;
1223	isakmp->v = iph1->version;
1224	isakmp->etype = ISAKMP_ETYPE_CFG;
1225	isakmp->flags = iph2->flags;
1226	memcpy(&isakmp->msgid, &iph2->msgid, sizeof(isakmp->msgid));
1227	isakmp->len = htonl(tlen);
1228	p = (char *)(isakmp + 1);
1229
1230	/* create HASH payload */
1231	if (hash != NULL) {
1232		gen = (struct isakmp_gen *)p;
1233		gen->np = np & 0xff;
1234		gen->len = htons(sizeof(*gen) + hash->l);
1235		p += sizeof(*gen);
1236		memcpy(p, hash->v, hash->l);
1237		p += hash->l;
1238	}
1239
1240	/* add payload */
1241	memcpy(p, payload->v, payload->l);
1242	p += payload->l;
1243
1244#ifdef HAVE_PRINT_ISAKMP_C
1245	isakmp_printpacket(iph2->sendbuf, iph1->local, iph1->remote, 1);
1246#endif
1247
1248	plog(LLV_DEBUG, LOCATION, NULL, "MODE_CFG packet to send\n");
1249	plogdump(LLV_DEBUG, iph2->sendbuf->v, iph2->sendbuf->l);
1250
1251	/* encoding */
1252	if (ISSET(isakmp->flags, ISAKMP_FLAG_E)) {
1253		vchar_t *tmp;
1254
1255		tmp = oakley_do_encrypt(iph2->ph1, iph2->sendbuf,
1256			ics->ivm->ive, ics->ivm->iv);
1257		VPTRINIT(iph2->sendbuf);
1258		if (tmp == NULL)
1259			goto err;
1260		iph2->sendbuf = tmp;
1261	}
1262
1263	/* HDR*, HASH(1), ATTR */
1264	if (isakmp_send(iph2->ph1, iph2->sendbuf) < 0) {
1265		VPTRINIT(iph2->sendbuf);
1266		goto err;
1267	}
1268
1269	plog(LLV_DEBUG, LOCATION, NULL,
1270		"sendto mode config %s.\n", s_isakmp_nptype(np));
1271
1272	/*
1273	 * XXX We might need to resend the message...
1274	 */
1275
1276	error = 0;
1277	VPTRINIT(iph2->sendbuf);
1278
1279err:
1280	if (iph2->sendbuf != NULL)
1281		vfree(iph2->sendbuf);
1282
1283	unbindph12(iph2);
1284	remph2(iph2);
1285	delph2(iph2);
1286end:
1287	if (hash)
1288		vfree(hash);
1289	return error;
1290}
1291
1292
1293void
1294isakmp_cfg_rmstate(iph1)
1295	struct ph1handle *iph1;
1296{
1297	struct isakmp_cfg_state *state = iph1->mode_cfg;
1298
1299	if (isakmp_cfg_accounting(iph1, ISAKMP_CFG_LOGOUT) != 0)
1300		plog(LLV_ERROR, LOCATION, NULL, "Accounting failed\n");
1301
1302	if (state->flags & ISAKMP_CFG_PORT_ALLOCATED)
1303		isakmp_cfg_putport(iph1, state->port);
1304
1305	/* Delete the IV if it's still there */
1306	if(iph1->mode_cfg->ivm) {
1307		oakley_delivm(iph1->mode_cfg->ivm);
1308		iph1->mode_cfg->ivm = NULL;
1309	}
1310
1311	/* Free any allocated splitnet lists */
1312	if(iph1->mode_cfg->split_include != NULL)
1313		splitnet_list_free(iph1->mode_cfg->split_include,
1314			&iph1->mode_cfg->include_count);
1315	if(iph1->mode_cfg->split_local != NULL)
1316		splitnet_list_free(iph1->mode_cfg->split_local,
1317			&iph1->mode_cfg->local_count);
1318
1319	xauth_rmstate(&state->xauth);
1320
1321	racoon_free(state);
1322	iph1->mode_cfg = NULL;
1323
1324	return;
1325}
1326
1327struct isakmp_cfg_state *
1328isakmp_cfg_mkstate(void)
1329{
1330	struct isakmp_cfg_state *state;
1331
1332	if ((state = racoon_malloc(sizeof(*state))) == NULL) {
1333		plog(LLV_ERROR, LOCATION, NULL,
1334		    "Cannot allocate memory for mode config state\n");
1335		return NULL;
1336	}
1337	memset(state, 0, sizeof(*state));
1338
1339	return state;
1340}
1341
1342int
1343isakmp_cfg_getport(iph1)
1344	struct ph1handle *iph1;
1345{
1346	unsigned int i;
1347	size_t size = isakmp_cfg_config.pool_size;
1348
1349	if (iph1->mode_cfg->flags & ISAKMP_CFG_PORT_ALLOCATED)
1350		return iph1->mode_cfg->port;
1351
1352	if (isakmp_cfg_config.port_pool == NULL) {
1353		plog(LLV_ERROR, LOCATION, NULL,
1354		    "isakmp_cfg_config.port_pool == NULL\n");
1355		return -1;
1356	}
1357
1358	for (i = 0; i < size; i++) {
1359		if (isakmp_cfg_config.port_pool[i].used == 0)
1360			break;
1361	}
1362
1363	if (i == size) {
1364		plog(LLV_ERROR, LOCATION, NULL,
1365		    "No more addresses available\n");
1366			return -1;
1367	}
1368
1369	isakmp_cfg_config.port_pool[i].used = 1;
1370
1371	plog(LLV_INFO, LOCATION, NULL, "Using port %d\n", i);
1372
1373	iph1->mode_cfg->flags |= ISAKMP_CFG_PORT_ALLOCATED;
1374	iph1->mode_cfg->port = i;
1375
1376	return i;
1377}
1378
1379int
1380isakmp_cfg_putport(iph1, index)
1381	struct ph1handle *iph1;
1382	unsigned int index;
1383{
1384	if (isakmp_cfg_config.port_pool == NULL) {
1385		plog(LLV_ERROR, LOCATION, NULL,
1386		    "isakmp_cfg_config.port_pool == NULL\n");
1387		return -1;
1388	}
1389
1390	if (isakmp_cfg_config.port_pool[index].used == 0) {
1391		plog(LLV_ERROR, LOCATION, NULL,
1392		    "Attempt to release an unallocated address (port %d)\n",
1393		    index);
1394		return -1;
1395	}
1396
1397#ifdef HAVE_LIBPAM
1398	/* Cleanup PAM status associated with the port */
1399	if (isakmp_cfg_config.authsource == ISAKMP_CFG_AUTH_PAM)
1400		privsep_cleanup_pam(index);
1401#endif
1402	isakmp_cfg_config.port_pool[index].used = 0;
1403	iph1->mode_cfg->flags &= ISAKMP_CFG_PORT_ALLOCATED;
1404
1405	plog(LLV_INFO, LOCATION, NULL, "Released port %d\n", index);
1406
1407	return 0;
1408}
1409
1410#ifdef HAVE_LIBPAM
1411void
1412cleanup_pam(port)
1413	int port;
1414{
1415	if (isakmp_cfg_config.port_pool[port].pam != NULL) {
1416		pam_end(isakmp_cfg_config.port_pool[port].pam, PAM_SUCCESS);
1417		isakmp_cfg_config.port_pool[port].pam = NULL;
1418	}
1419
1420	return;
1421}
1422#endif
1423
1424/* Accounting, only for RADIUS or PAM */
1425static int
1426isakmp_cfg_accounting(iph1, inout)
1427	struct ph1handle *iph1;
1428	int inout;
1429{
1430#ifdef HAVE_LIBPAM
1431	if (isakmp_cfg_config.accounting == ISAKMP_CFG_ACCT_PAM)
1432		return privsep_accounting_pam(iph1->mode_cfg->port,
1433		    inout);
1434#endif
1435#ifdef HAVE_LIBRADIUS
1436	if (isakmp_cfg_config.accounting == ISAKMP_CFG_ACCT_RADIUS)
1437		return isakmp_cfg_accounting_radius(iph1, inout);
1438#endif
1439	if (isakmp_cfg_config.accounting == ISAKMP_CFG_ACCT_SYSTEM)
1440		return privsep_accounting_system(iph1->mode_cfg->port,
1441			iph1->remote, iph1->mode_cfg->login, inout);
1442	return 0;
1443}
1444
1445#ifdef HAVE_LIBPAM
1446int
1447isakmp_cfg_accounting_pam(port, inout)
1448	int port;
1449	int inout;
1450{
1451	int error = 0;
1452	pam_handle_t *pam;
1453
1454	if (isakmp_cfg_config.port_pool == NULL) {
1455		plog(LLV_ERROR, LOCATION, NULL,
1456		    "isakmp_cfg_config.port_pool == NULL\n");
1457		return -1;
1458	}
1459
1460	pam = isakmp_cfg_config.port_pool[port].pam;
1461	if (pam == NULL) {
1462		plog(LLV_ERROR, LOCATION, NULL, "pam handle is NULL\n");
1463		return -1;
1464	}
1465
1466	switch (inout) {
1467	case ISAKMP_CFG_LOGIN:
1468		error = pam_open_session(pam, 0);
1469		break;
1470	case ISAKMP_CFG_LOGOUT:
1471		error = pam_close_session(pam, 0);
1472		pam_end(pam, error);
1473		isakmp_cfg_config.port_pool[port].pam = NULL;
1474		break;
1475	default:
1476		plog(LLV_ERROR, LOCATION, NULL, "Unepected inout\n");
1477		break;
1478	}
1479
1480	if (error != 0) {
1481		plog(LLV_ERROR, LOCATION, NULL,
1482		    "pam_open_session/pam_close_session failed: %s\n",
1483		    pam_strerror(pam, error));
1484		return -1;
1485        }
1486
1487	return 0;
1488}
1489#endif /* HAVE_LIBPAM */
1490
1491#ifdef HAVE_LIBRADIUS
1492static int
1493isakmp_cfg_accounting_radius(iph1, inout)
1494	struct ph1handle *iph1;
1495	int inout;
1496{
1497	/* For first time use, initialize Radius */
1498	if (radius_acct_state == NULL) {
1499		if ((radius_acct_state = rad_acct_open()) == NULL) {
1500			plog(LLV_ERROR, LOCATION, NULL,
1501			    "Cannot init librradius\n");
1502			return -1;
1503		}
1504
1505		if (rad_config(radius_acct_state, NULL) != 0) {
1506			 plog(LLV_ERROR, LOCATION, NULL,
1507			     "Cannot open librarius config file: %s\n",
1508			     rad_strerror(radius_acct_state));
1509			  rad_close(radius_acct_state);
1510			  radius_acct_state = NULL;
1511			  return -1;
1512		}
1513	}
1514
1515	if (rad_create_request(radius_acct_state,
1516	    RAD_ACCOUNTING_REQUEST) != 0) {
1517		plog(LLV_ERROR, LOCATION, NULL,
1518		    "rad_create_request failed: %s\n",
1519		    rad_strerror(radius_acct_state));
1520		return -1;
1521	}
1522
1523	if (rad_put_string(radius_acct_state, RAD_USER_NAME,
1524	    iph1->mode_cfg->login) != 0) {
1525		plog(LLV_ERROR, LOCATION, NULL,
1526		    "rad_put_string failed: %s\n",
1527		    rad_strerror(radius_acct_state));
1528		return -1;
1529	}
1530
1531	switch (inout) {
1532	case ISAKMP_CFG_LOGIN:
1533		inout = RAD_START;
1534		break;
1535	case ISAKMP_CFG_LOGOUT:
1536		inout = RAD_STOP;
1537		break;
1538	default:
1539		plog(LLV_ERROR, LOCATION, NULL, "Unepected inout\n");
1540		break;
1541	}
1542
1543	if (rad_put_addr(radius_acct_state,
1544	    RAD_FRAMED_IP_ADDRESS, iph1->mode_cfg->addr4) != 0) {
1545		plog(LLV_ERROR, LOCATION, NULL,
1546		    "rad_put_addr failed: %s\n",
1547		    rad_strerror(radius_acct_state));
1548		return -1;
1549	}
1550
1551	if (rad_put_addr(radius_acct_state,
1552	    RAD_LOGIN_IP_HOST, 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_int(radius_acct_state, RAD_ACCT_STATUS_TYPE, inout) != 0) {
1560		plog(LLV_ERROR, LOCATION, NULL,
1561		    "rad_put_int failed: %s\n",
1562		    rad_strerror(radius_acct_state));
1563		return -1;
1564	}
1565
1566	if (isakmp_cfg_radius_common(radius_acct_state,
1567	    iph1->mode_cfg->port) != 0)
1568		return -1;
1569
1570	if (rad_send_request(radius_acct_state) != RAD_ACCOUNTING_RESPONSE) {
1571		plog(LLV_ERROR, LOCATION, NULL,
1572		    "rad_send_request failed: %s\n",
1573		    rad_strerror(radius_acct_state));
1574		return -1;
1575	}
1576
1577	return 0;
1578}
1579#endif /* HAVE_LIBRADIUS */
1580
1581/*
1582 * Attributes common to all RADIUS requests
1583 */
1584#ifdef HAVE_LIBRADIUS
1585int
1586isakmp_cfg_radius_common(radius_state, port)
1587	struct rad_handle *radius_state;
1588	int port;
1589{
1590	struct utsname name;
1591	static struct hostent *host = NULL;
1592	struct in_addr nas_addr;
1593
1594	/*
1595	 * Find our own IP by resolving our nodename
1596	 */
1597	if (host == NULL) {
1598		if (uname(&name) != 0) {
1599			plog(LLV_ERROR, LOCATION, NULL,
1600			    "uname failed: %s\n", strerror(errno));
1601			return -1;
1602		}
1603
1604		if ((host = gethostbyname(name.nodename)) == NULL) {
1605			plog(LLV_ERROR, LOCATION, NULL,
1606			    "gethostbyname failed: %s\n", strerror(errno));
1607			return -1;
1608		}
1609	}
1610
1611	memcpy(&nas_addr, host->h_addr, sizeof(nas_addr));
1612	if (rad_put_addr(radius_state, RAD_NAS_IP_ADDRESS, nas_addr) != 0) {
1613		plog(LLV_ERROR, LOCATION, NULL,
1614		    "rad_put_addr failed: %s\n",
1615		    rad_strerror(radius_state));
1616		return -1;
1617	}
1618
1619	if (rad_put_int(radius_state, RAD_NAS_PORT, port) != 0) {
1620		plog(LLV_ERROR, LOCATION, NULL,
1621		    "rad_put_int failed: %s\n",
1622		    rad_strerror(radius_state));
1623		return -1;
1624	}
1625
1626	if (rad_put_int(radius_state, RAD_NAS_PORT_TYPE, RAD_VIRTUAL) != 0) {
1627		plog(LLV_ERROR, LOCATION, NULL,
1628		    "rad_put_int failed: %s\n",
1629		    rad_strerror(radius_state));
1630		return -1;
1631	}
1632
1633	if (rad_put_int(radius_state, RAD_SERVICE_TYPE, RAD_FRAMED) != 0) {
1634		plog(LLV_ERROR, LOCATION, NULL,
1635		    "rad_put_int failed: %s\n",
1636		    rad_strerror(radius_state));
1637		return -1;
1638	}
1639
1640	return 0;
1641}
1642#endif
1643
1644#ifndef ANDROID_PATCHED
1645
1646/*
1647	Logs the user into the utmp system files.
1648*/
1649
1650int
1651isakmp_cfg_accounting_system(port, raddr, usr, inout)
1652	int port;
1653	struct sockaddr *raddr;
1654	char *usr;
1655	int inout;
1656{
1657	int error = 0;
1658	struct utmp ut;
1659	char term[UT_LINESIZE];
1660	char addr[NI_MAXHOST];
1661
1662	if (usr == NULL || usr[0]=='\0') {
1663		plog(LLV_ERROR, LOCATION, NULL,
1664			"system accounting : no login found\n");
1665		return -1;
1666	}
1667
1668	sprintf(term, TERMSPEC, port);
1669
1670	switch (inout) {
1671	case ISAKMP_CFG_LOGIN:
1672		strncpy(ut.ut_name, usr, UT_NAMESIZE);
1673		ut.ut_name[UT_NAMESIZE - 1] = '\0';
1674
1675		strncpy(ut.ut_line, term, UT_LINESIZE);
1676		ut.ut_line[UT_LINESIZE - 1] = '\0';
1677
1678		GETNAMEINFO_NULL(raddr, addr);
1679		strncpy(ut.ut_host, addr, UT_HOSTSIZE);
1680		ut.ut_host[UT_HOSTSIZE - 1] = '\0';
1681
1682		ut.ut_time = time(NULL);
1683
1684		plog(LLV_INFO, LOCATION, NULL,
1685			"Accounting : '%s' logging on '%s' from %s.\n",
1686			ut.ut_name, ut.ut_line, ut.ut_host);
1687
1688		login(&ut);
1689
1690		break;
1691	case ISAKMP_CFG_LOGOUT:
1692
1693		plog(LLV_INFO, LOCATION, NULL,
1694			"Accounting : '%s' unlogging from '%s'.\n",
1695			usr, term);
1696
1697		logout(term);
1698
1699		break;
1700	default:
1701		plog(LLV_ERROR, LOCATION, NULL, "Unepected inout\n");
1702		break;
1703	}
1704
1705	return 0;
1706}
1707
1708#endif
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