xref: /netbsd-src/crypto/dist/ipsec-tools/src/racoon/isakmp_cfg.c (revision e5548b402ae4c44fb816de42c7bba9581ce23ef5)
1 /*	$NetBSD: isakmp_cfg.c,v 1.9 2005/11/21 14:20:29 manu Exp $	*/
2 
3 /* Id: isakmp_cfg.c,v 1.26.2.6 2005/09/23 14:29:45 manubsd Exp */
4 
5 /*
6  * Copyright (C) 2004 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 <netinet/in.h>
42 #include <arpa/inet.h>
43 
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include <errno.h>
48 #if TIME_WITH_SYS_TIME
49 # include <sys/time.h>
50 # include <time.h>
51 #else
52 # if HAVE_SYS_TIME_H
53 #  include <sys/time.h>
54 # else
55 #  include <time.h>
56 # endif
57 #endif
58 #include <netdb.h>
59 #ifdef HAVE_UNISTD_H
60 #include <unistd.h>
61 #endif
62 #include <ctype.h>
63 
64 #ifdef HAVE_LIBRADIUS
65 #include <sys/utsname.h>
66 #include <radlib.h>
67 #endif
68 
69 #include "var.h"
70 #include "misc.h"
71 #include "vmbuf.h"
72 #include "plog.h"
73 #include "sockmisc.h"
74 #include "schedule.h"
75 #include "debug.h"
76 
77 #include "isakmp_var.h"
78 #include "isakmp.h"
79 #include "handler.h"
80 #include "evt.h"
81 #include "throttle.h"
82 #include "remoteconf.h"
83 #include "crypto_openssl.h"
84 #include "isakmp_inf.h"
85 #include "isakmp_xauth.h"
86 #include "isakmp_unity.h"
87 #include "isakmp_cfg.h"
88 #include "strnames.h"
89 #include "admin.h"
90 #include "privsep.h"
91 
92 struct isakmp_cfg_config isakmp_cfg_config = {
93 	0x00000000, 	/* network4 */
94 	0x00000000,	/* netmask4 */
95 	0x00000000,	/* dns4 */
96 	0x00000000,	/* nbns4 */
97 	NULL,		/* pool */
98 	ISAKMP_CFG_AUTH_SYSTEM,		/* authsource */
99 	ISAKMP_CFG_CONF_LOCAL,		/* confsource */
100 	ISAKMP_CFG_ACCT_NONE,		/* accounting */
101 	ISAKMP_CFG_MAX_CNX,		/* pool_size */
102 	THROTTLE_PENALTY,		/* auth_throttle */
103 	ISAKMP_CFG_MOTD,		/* motd */
104 	0,				/* pfs_group */
105 	0,				/* save_passwd */
106 };
107 
108 static vchar_t *buffer_cat(vchar_t *s, vchar_t *append);
109 static vchar_t *isakmp_cfg_net(struct ph1handle *, struct isakmp_data *);
110 #if 0
111 static vchar_t *isakmp_cfg_void(struct ph1handle *, struct isakmp_data *);
112 #endif
113 static vchar_t *isakmp_cfg_addr4(struct ph1handle *,
114 				 struct isakmp_data *, in_addr_t *);
115 static void isakmp_cfg_getaddr4(struct isakmp_data *, struct in_addr *);
116 
117 #define ISAKMP_CFG_LOGIN	1
118 #define ISAKMP_CFG_LOGOUT	2
119 static int isakmp_cfg_accounting(struct ph1handle *, int);
120 #ifdef HAVE_LIBRADIUS
121 static int isakmp_cfg_accounting_radius(struct ph1handle *, int);
122 #endif
123 
124 /*
125  * Handle an ISAKMP config mode packet
126  * We expect HDR, HASH, ATTR
127  */
128 void
129 isakmp_cfg_r(iph1, msg)
130 	struct ph1handle *iph1;
131 	vchar_t *msg;
132 {
133 	struct isakmp *packet;
134 	struct isakmp_gen *ph;
135 	int tlen;
136 	char *npp;
137 	int np;
138 	vchar_t *dmsg;
139 	struct isakmp_ivm *ivm;
140 
141 	/* Check that the packet is long enough to have a header */
142 	if (msg->l < sizeof(*packet)) {
143 	     plog(LLV_ERROR, LOCATION, NULL, "Unexpected short packet\n");
144 	     return;
145 	}
146 
147 	packet = (struct isakmp *)msg->v;
148 
149 	/* Is it encrypted? It should be encrypted */
150 	if ((packet->flags & ISAKMP_FLAG_E) == 0) {
151 		plog(LLV_ERROR, LOCATION, NULL,
152 		    "User credentials sent in cleartext!\n");
153 		return;
154 	}
155 
156 	/*
157 	 * Decrypt the packet. If this is the beginning of a new
158 	 * exchange, reinitialize the IV
159 	 */
160 	if (iph1->mode_cfg->ivm == NULL)
161 		iph1->mode_cfg->ivm =
162 		    isakmp_cfg_newiv(iph1, packet->msgid);
163 	ivm = iph1->mode_cfg->ivm;
164 
165 	dmsg = oakley_do_decrypt(iph1, msg, ivm->iv, ivm->ive);
166 	if (dmsg == NULL) {
167 		plog(LLV_ERROR, LOCATION, NULL,
168 		    "failed to decrypt message\n");
169 		return;
170 	}
171 
172 	plog(LLV_DEBUG, LOCATION, NULL, "MODE_CFG packet\n");
173 	plogdump(LLV_DEBUG, dmsg->v, dmsg->l);
174 
175 	/* Now work with the decrypted packet */
176 	packet = (struct isakmp *)dmsg->v;
177 	tlen = dmsg->l - sizeof(*packet);
178 	ph = (struct isakmp_gen *)(packet + 1);
179 
180 	np = packet->np;
181 	while ((tlen > 0) && (np != ISAKMP_NPTYPE_NONE)) {
182 		/* Check that the payload header fits in the packet */
183 		if (tlen < sizeof(*ph)) {
184 			 plog(LLV_WARNING, LOCATION, NULL,
185 			      "Short payload header\n");
186 			 goto out;
187 		}
188 
189 		/* Check that the payload fits in the packet */
190 		if (tlen < ntohs(ph->len)) {
191 			plog(LLV_WARNING, LOCATION, NULL,
192 			      "Short payload\n");
193 			goto out;
194 		}
195 
196 		plog(LLV_DEBUG, LOCATION, NULL, "Seen payload %d\n", np);
197 		plogdump(LLV_DEBUG, ph, ntohs(ph->len));
198 
199 		switch(np) {
200 		case ISAKMP_NPTYPE_HASH: {
201 			vchar_t *check;
202 			vchar_t *payload;
203 			size_t plen;
204 			struct isakmp_gen *nph;
205 
206 			plen = ntohs(ph->len);
207 			nph = (struct isakmp_gen *)((char *)ph + plen);
208 			plen = ntohs(nph->len);
209 
210 			if ((payload = vmalloc(plen)) == NULL) {
211 				plog(LLV_ERROR, LOCATION, NULL,
212 				    "Cannot allocate memory\n");
213 				goto out;
214 			}
215 			memcpy(payload->v, nph, plen);
216 
217 			if ((check = oakley_compute_hash1(iph1,
218 			    packet->msgid, payload)) == NULL) {
219 				plog(LLV_ERROR, LOCATION, NULL,
220 				    "Cannot compute hash\n");
221 				vfree(payload);
222 				goto out;
223 			}
224 
225 			if (memcmp(ph + 1, check->v, check->l) != 0) {
226 				plog(LLV_ERROR, LOCATION, NULL,
227 				    "Hash verification failed\n");
228 				vfree(payload);
229 				vfree(check);
230 				goto out;
231 			}
232 			vfree(payload);
233 			vfree(check);
234 			break;
235 		}
236 		case ISAKMP_NPTYPE_ATTR: {
237 			struct isakmp_pl_attr *attrpl;
238 
239 			attrpl = (struct isakmp_pl_attr *)ph;
240 			isakmp_cfg_attr_r(iph1, packet->msgid, attrpl);
241 
242 			break;
243 		}
244 		default:
245 			 plog(LLV_WARNING, LOCATION, NULL,
246 			      "Unexpected next payload %d\n", np);
247 			 /* Skip to the next payload */
248 			 break;
249 		}
250 
251 		/* Move to the next payload */
252 		np = ph->np;
253 		tlen -= ntohs(ph->len);
254 		npp = (char *)ph;
255 		ph = (struct isakmp_gen *)(npp + ntohs(ph->len));
256 	}
257 
258 out:
259 	vfree(dmsg);
260 }
261 
262 int
263 isakmp_cfg_attr_r(iph1, msgid, attrpl)
264 	struct ph1handle *iph1;
265 	u_int32_t msgid;
266 	struct isakmp_pl_attr *attrpl;
267 {
268 	int type = attrpl->type;
269 
270 	switch (type) {
271 	case ISAKMP_CFG_ACK:
272 		/* ignore, but this is the time to reinit the IV */
273 		oakley_delivm(iph1->mode_cfg->ivm);
274 		iph1->mode_cfg->ivm = NULL;
275 		return 0;
276 		break;
277 
278 	case ISAKMP_CFG_REPLY:
279 		return isakmp_cfg_reply(iph1, attrpl);
280 		break;
281 
282 	case ISAKMP_CFG_REQUEST:
283 		iph1->msgid = msgid;
284 		return isakmp_cfg_request(iph1, attrpl);
285 		break;
286 
287 	case ISAKMP_CFG_SET:
288 		iph1->msgid = msgid;
289 		return isakmp_cfg_set(iph1, attrpl);
290 		break;
291 
292 	default:
293 		plog(LLV_WARNING, LOCATION, NULL,
294 		     "Unepected configuration exchange type %d\n", type);
295 		return -1;
296 		break;
297 	}
298 
299 	return 0;
300 }
301 
302 int
303 isakmp_cfg_reply(iph1, attrpl)
304 	struct ph1handle *iph1;
305 	struct isakmp_pl_attr *attrpl;
306 {
307 	struct isakmp_data *attr;
308 	int tlen;
309 	size_t alen;
310 	char *npp;
311 	int type;
312 	struct sockaddr_in *sin;
313 
314 	tlen = ntohs(attrpl->h.len);
315 	attr = (struct isakmp_data *)(attrpl + 1);
316 	tlen -= sizeof(*attrpl);
317 
318 	while (tlen > 0) {
319 		type = ntohs(attr->type);
320 
321 		/* Handle short attributes */
322 		if ((type & ISAKMP_GEN_MASK) == ISAKMP_GEN_TV) {
323 			type &= ~ISAKMP_GEN_MASK;
324 
325 			plog(LLV_DEBUG, LOCATION, NULL,
326 			     "Short attribute %d = %d\n",
327 			     type, ntohs(attr->lorv));
328 
329 			switch (type) {
330 			case XAUTH_TYPE:
331 				xauth_attr_reply(iph1, attr, ntohs(attrpl->id));
332 				break;
333 
334 			default:
335 				plog(LLV_WARNING, LOCATION, NULL,
336 				     "Ignored short attribute %d\n", type);
337 				break;
338 			}
339 
340 			tlen -= sizeof(*attr);
341 			attr++;
342 			continue;
343 		}
344 
345 		type = ntohs(attr->type);
346 		alen = ntohs(attr->lorv);
347 
348 		/* Check that the attribute fit in the packet */
349 		if (tlen < alen) {
350 			plog(LLV_ERROR, LOCATION, NULL,
351 			     "Short attribute %d\n", type);
352 			return -1;
353 		}
354 
355 		plog(LLV_DEBUG, LOCATION, NULL,
356 		     "Attribute %d, len %zu\n", type, alen);
357 
358 		switch(type) {
359 		case XAUTH_TYPE:
360 		case XAUTH_USER_NAME:
361 		case XAUTH_USER_PASSWORD:
362 		case XAUTH_PASSCODE:
363 		case XAUTH_MESSAGE:
364 		case XAUTH_CHALLENGE:
365 		case XAUTH_DOMAIN:
366 		case XAUTH_STATUS:
367 		case XAUTH_NEXT_PIN:
368 		case XAUTH_ANSWER:
369 			xauth_attr_reply(iph1, attr, ntohs(attrpl->id));
370 			break;
371 		case INTERNAL_IP4_ADDRESS:
372 			isakmp_cfg_getaddr4(attr, &iph1->mode_cfg->addr4);
373 			iph1->mode_cfg->flags |= ISAKMP_CFG_GOT_ADDR4;
374 			break;
375 		case INTERNAL_IP4_NETMASK:
376 			isakmp_cfg_getaddr4(attr, &iph1->mode_cfg->mask4);
377 			iph1->mode_cfg->flags |= ISAKMP_CFG_GOT_MASK4;
378 			break;
379 		case INTERNAL_IP4_DNS:
380 			isakmp_cfg_getaddr4(attr, &iph1->mode_cfg->dns4);
381 			iph1->mode_cfg->flags |= ISAKMP_CFG_GOT_DNS4;
382 			break;
383 		case INTERNAL_IP4_NBNS:
384 			isakmp_cfg_getaddr4(attr, &iph1->mode_cfg->wins4);
385 			iph1->mode_cfg->flags |= ISAKMP_CFG_GOT_WINS4;
386 			break;
387 		case INTERNAL_IP4_SUBNET:
388 		case INTERNAL_ADDRESS_EXPIRY:
389 		case UNITY_BANNER:
390 		case UNITY_SAVE_PASSWD:
391 		case UNITY_DEF_DOMAIN:
392 		case UNITY_SPLITDNS_NAME:
393 		case UNITY_SPLIT_INCLUDE:
394 		case UNITY_NATT_PORT:
395 		case UNITY_PFS:
396 		case UNITY_FW_TYPE:
397 		case UNITY_BACKUP_SERVERS:
398 		case UNITY_DDNS_HOSTNAME:
399 		default:
400 			plog(LLV_WARNING, LOCATION, NULL,
401 			     "Ignored attribute %d\n", type);
402 			break;
403 		}
404 
405 		npp = (char *)attr;
406 		attr = (struct isakmp_data *)(npp + sizeof(*attr) + alen);
407 		tlen -= (sizeof(*attr) + alen);
408 	}
409 
410 	/*
411 	 * Call the SA up script hook now that we have the configuration
412 	 * It is done at the end of phase 1 if ISAKMP mode config is not
413 	 * requested.
414 	 */
415 	if ((iph1->status == PHASE1ST_ESTABLISHED) &&
416 	    iph1->rmconf->mode_cfg)
417 		script_hook(iph1, SCRIPT_PHASE1_UP);
418 
419 #ifdef ENABLE_ADMINPORT
420 	{
421 		vchar_t *buf;
422 
423 		alen = ntohs(attrpl->h.len) - sizeof(*attrpl);
424 		if ((buf = vmalloc(alen)) == NULL) {
425 			plog(LLV_WARNING, LOCATION, NULL,
426 			    "Cannot allocate memory: %s\n", strerror(errno));
427 		} else {
428 			memcpy(buf->v, attrpl + 1, buf->l);
429 			EVT_PUSH(iph1->local, iph1->remote,
430 			    EVTT_ISAKMP_CFG_DONE, buf);
431 			vfree(buf);
432 		}
433 	}
434 #endif
435 
436 	return 0;
437 }
438 
439 int
440 isakmp_cfg_request(iph1, attrpl)
441 	struct ph1handle *iph1;
442 	struct isakmp_pl_attr *attrpl;
443 {
444 	struct isakmp_data *attr;
445 	int tlen;
446 	size_t alen;
447 	char *npp;
448 	vchar_t *payload;
449 	struct isakmp_pl_attr *reply;
450 	vchar_t *reply_attr;
451 	int type;
452 	int error = -1;
453 
454 	if ((payload = vmalloc(sizeof(*reply))) == NULL) {
455 		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
456 		return -1;
457 	}
458 	memset(payload->v, 0, sizeof(*reply));
459 
460 	tlen = ntohs(attrpl->h.len);
461 	attr = (struct isakmp_data *)(attrpl + 1);
462 	tlen -= sizeof(*attrpl);
463 
464 	while (tlen > 0) {
465 		reply_attr = NULL;
466 		type = ntohs(attr->type);
467 
468 		/* Handle short attributes */
469 		if ((type & ISAKMP_GEN_MASK) == ISAKMP_GEN_TV) {
470 			type &= ~ISAKMP_GEN_MASK;
471 
472 			plog(LLV_DEBUG, LOCATION, NULL,
473 			     "Short attribute %d = %d\n",
474 			     type, ntohs(attr->lorv));
475 
476 			switch (type) {
477 			case XAUTH_TYPE:
478 				reply_attr = isakmp_xauth_req(iph1, attr);
479 				break;
480 			default:
481 				plog(LLV_WARNING, LOCATION, NULL,
482 				     "Ignored short attribute %d\n", type);
483 				break;
484 			}
485 
486 			tlen -= sizeof(*attr);
487 			attr++;
488 
489 			if (reply_attr != NULL) {
490 				payload = buffer_cat(payload, reply_attr);
491 				vfree(reply_attr);
492 			}
493 
494 			continue;
495 		}
496 
497 		type = ntohs(attr->type);
498 		alen = ntohs(attr->lorv);
499 
500 		/* Check that the attribute fit in the packet */
501 		if (tlen < alen) {
502 			plog(LLV_ERROR, LOCATION, NULL,
503 			     "Short attribute %d\n", type);
504 			goto end;
505 		}
506 
507 		plog(LLV_DEBUG, LOCATION, NULL,
508 		     "Attribute %d, len %zu\n", type, alen);
509 
510 		switch(type) {
511 		case INTERNAL_IP4_ADDRESS:
512 		case INTERNAL_IP4_NETMASK:
513 		case INTERNAL_IP4_DNS:
514 		case INTERNAL_IP4_NBNS:
515 		case INTERNAL_IP4_SUBNET:
516 			reply_attr = isakmp_cfg_net(iph1, attr);
517 			break;
518 
519 		case XAUTH_TYPE:
520 		case XAUTH_USER_NAME:
521 		case XAUTH_USER_PASSWORD:
522 		case XAUTH_PASSCODE:
523 		case XAUTH_MESSAGE:
524 		case XAUTH_CHALLENGE:
525 		case XAUTH_DOMAIN:
526 		case XAUTH_STATUS:
527 		case XAUTH_NEXT_PIN:
528 		case XAUTH_ANSWER:
529 			reply_attr = isakmp_xauth_req(iph1, attr);
530 			break;
531 
532 		case APPLICATION_VERSION:
533 			reply_attr = isakmp_cfg_string(iph1,
534 			    attr, ISAKMP_CFG_RACOON_VERSION);
535 			break;
536 
537 		case UNITY_BANNER:
538 		case UNITY_PFS:
539 		case UNITY_SAVE_PASSWD:
540 		case UNITY_DEF_DOMAIN:
541 		case UNITY_DDNS_HOSTNAME:
542 		case UNITY_FW_TYPE:
543 		case UNITY_SPLITDNS_NAME:
544 		case UNITY_SPLIT_INCLUDE:
545 		case UNITY_NATT_PORT:
546 		case UNITY_BACKUP_SERVERS:
547 			reply_attr = isakmp_unity_req(iph1, attr);
548 			break;
549 
550 		case INTERNAL_ADDRESS_EXPIRY:
551 		default:
552 			plog(LLV_WARNING, LOCATION, NULL,
553 			     "Ignored attribute %d\n", type);
554 			break;
555 		}
556 
557 		npp = (char *)attr;
558 		attr = (struct isakmp_data *)(npp + sizeof(*attr) + alen);
559 		tlen -= (sizeof(*attr) + alen);
560 
561 		if (reply_attr != NULL) {
562 			payload = buffer_cat(payload, reply_attr);
563 			vfree(reply_attr);
564 		}
565 
566 	}
567 
568 	reply = (struct isakmp_pl_attr *)payload->v;
569 	reply->h.len = htons(payload->l);
570 	reply->type = ISAKMP_CFG_REPLY;
571 	reply->id = attrpl->id;
572 
573 	error = isakmp_cfg_send(iph1, payload,
574 	    ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 0);
575 
576 	/* Reinit the IV */
577 	oakley_delivm(iph1->mode_cfg->ivm);
578 	iph1->mode_cfg->ivm = NULL;
579 end:
580 	vfree(payload);
581 
582 	return error;
583 }
584 
585 int
586 isakmp_cfg_set(iph1, attrpl)
587 	struct ph1handle *iph1;
588 	struct isakmp_pl_attr *attrpl;
589 {
590 	struct isakmp_data *attr;
591 	int tlen;
592 	size_t alen;
593 	char *npp;
594 	vchar_t *payload;
595 	struct isakmp_pl_attr *reply;
596 	vchar_t *reply_attr;
597 	int type;
598 	int error = -1;
599 
600 	if ((payload = vmalloc(sizeof(*reply))) == NULL) {
601 		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
602 		return -1;
603 	}
604 	memset(payload->v, 0, sizeof(*reply));
605 
606 	tlen = ntohs(attrpl->h.len);
607 	attr = (struct isakmp_data *)(attrpl + 1);
608 	tlen -= sizeof(*attrpl);
609 
610 	/*
611 	 * We should send ack for the attributes we accepted
612 	 */
613 	while (tlen > 0) {
614 		reply_attr = NULL;
615 		type = ntohs(attr->type);
616 
617 		switch (type & ~ISAKMP_GEN_MASK) {
618 		case XAUTH_STATUS:
619 			reply_attr = isakmp_xauth_set(iph1, attr);
620 			break;
621 		default:
622 			plog(LLV_DEBUG, LOCATION, NULL,
623 			     "Unexpected SET attribute %d\n",
624 				 type & ~ISAKMP_GEN_MASK);
625 			break;
626 		}
627 
628 		if ((reply_attr = vmalloc(sizeof(*reply_attr))) != NULL) {
629 			payload = buffer_cat(payload, reply_attr);
630 			vfree(reply_attr);
631 		}
632 
633 		/*
634 		 * Move to next attribute. If we run out of the packet,
635 		 * tlen becomes negative and we exit.
636 		 */
637 		if ((type & ISAKMP_GEN_MASK) == ISAKMP_GEN_TV) {
638 			tlen -= sizeof(*attr);
639 			attr++;
640 		} else {
641 			alen = ntohs(attr->lorv);
642 			tlen -= (sizeof(*attr) + alen);
643 			npp = (char *)attr;
644 			attr = (struct isakmp_data *)
645 			    (npp + sizeof(*attr) + alen);
646 		}
647 	}
648 
649 	reply = (struct isakmp_pl_attr *)payload->v;
650 	reply->h.len = htons(payload->l);
651 	reply->type = ISAKMP_CFG_ACK;
652 	reply->id = attrpl->id;
653 
654 	error = isakmp_cfg_send(iph1, payload,
655 	    ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 0);
656 
657 	if (iph1->mode_cfg->flags & ISAKMP_CFG_DELETE_PH1) {
658 		if (iph1->status == PHASE1ST_ESTABLISHED)
659 			isakmp_info_send_d1(iph1);
660 		remph1(iph1);
661 		delph1(iph1);
662 	}
663 end:
664 	vfree(payload);
665 
666 	/*
667 	 * If required, request ISAKMP mode config information
668 	 */
669 	if ((iph1->rmconf->mode_cfg) && (error == 0))
670 		error = isakmp_cfg_getconfig(iph1);
671 
672 	return error;
673 }
674 
675 
676 static vchar_t *
677 buffer_cat(s, append)
678 	vchar_t *s;
679 	vchar_t *append;
680 {
681 	vchar_t *new;
682 
683 	new = vmalloc(s->l + append->l);
684 	if (new == NULL) {
685 		plog(LLV_ERROR, LOCATION, NULL,
686 		    "Cannot allocate memory\n");
687 		return s;
688 	}
689 
690 	memcpy(new->v, s->v, s->l);
691 	memcpy(new->v + s->l, append->v, append->l);
692 
693 	vfree(s);
694 	return new;
695 }
696 
697 static vchar_t *
698 isakmp_cfg_net(iph1, attr)
699 	struct ph1handle *iph1;
700 	struct isakmp_data *attr;
701 {
702 	int type;
703 	in_addr_t addr4;
704 
705 	type = ntohs(attr->type);
706 
707 	/*
708 	 * Don't give an address to a peer that did not succeed Xauth
709 	 */
710 	if (xauth_check(iph1) != 0) {
711 		plog(LLV_ERROR, LOCATION, NULL,
712 		    "Attempt to start phase config whereas Xauth failed\n");
713 		return NULL;
714 	}
715 
716 	switch(type) {
717 	case INTERNAL_IP4_ADDRESS:
718 		switch(isakmp_cfg_config.confsource) {
719 #ifdef HAVE_LIBRADIUS
720 		case ISAKMP_CFG_CONF_RADIUS:
721 			if ((iph1->mode_cfg->flags & ISAKMP_CFG_ADDR4_RADIUS)
722 			    && (iph1->mode_cfg->addr4.s_addr != htonl(-2)))
723 			    /*
724 			     * -2 is 255.255.255.254, RADIUS uses that
725 			     * to instruct the NAS to use a local pool
726 			     */
727 			    break;
728 			plog(LLV_INFO, LOCATION, NULL,
729 			    "No IP from RADIUS, using local pool\n");
730 			/* FALLTHROUGH */
731 #endif
732 		case ISAKMP_CFG_CONF_LOCAL:
733 			if (isakmp_cfg_getport(iph1) == -1) {
734 				plog(LLV_ERROR, LOCATION, NULL,
735 				    "Port pool depleted\n");
736 				break;
737 			}
738 
739 			iph1->mode_cfg->addr4.s_addr =
740 			    htonl(ntohl(isakmp_cfg_config.network4)
741 			    + iph1->mode_cfg->port);
742 			iph1->mode_cfg->flags |= ISAKMP_CFG_ADDR4_LOCAL;
743 			break;
744 
745 		default:
746 			plog(LLV_ERROR, LOCATION, NULL,
747 			    "Unexpected confsource\n");
748 		}
749 
750 		if (isakmp_cfg_accounting(iph1, ISAKMP_CFG_LOGIN) != 0)
751 			plog(LLV_ERROR, LOCATION, NULL, "Accounting failed\n");
752 
753 		return isakmp_cfg_addr4(iph1,
754 		    attr, &iph1->mode_cfg->addr4.s_addr);
755 		break;
756 
757 	case INTERNAL_IP4_NETMASK:
758 		switch(isakmp_cfg_config.confsource) {
759 #ifdef HAVE_LIBRADIUS
760 		case ISAKMP_CFG_CONF_RADIUS:
761 			if (iph1->mode_cfg->flags & ISAKMP_CFG_MASK4_RADIUS)
762 				break;
763 			plog(LLV_INFO, LOCATION, NULL,
764 			    "No mask from RADIUS, using local pool\n");
765 			/* FALLTHROUGH */
766 #endif
767 		case ISAKMP_CFG_CONF_LOCAL:
768 			iph1->mode_cfg->mask4.s_addr
769 			    = isakmp_cfg_config.netmask4;
770 			iph1->mode_cfg->flags |= ISAKMP_CFG_MASK4_LOCAL;
771 			break;
772 
773 		default:
774 			plog(LLV_ERROR, LOCATION, NULL,
775 			    "Unexpected confsource\n");
776 		}
777 		return isakmp_cfg_addr4(iph1, attr,
778 		    &iph1->mode_cfg->mask4.s_addr);
779 		break;
780 
781 	case INTERNAL_IP4_DNS:
782 		return isakmp_cfg_addr4(iph1,
783 		    attr, &isakmp_cfg_config.dns4);
784 		break;
785 
786 	case INTERNAL_IP4_NBNS:
787 		return isakmp_cfg_addr4(iph1,
788 		    attr, &isakmp_cfg_config.nbns4);
789 		break;
790 
791 	case INTERNAL_IP4_SUBNET:
792 		return isakmp_cfg_addr4(iph1,
793 		    attr, &isakmp_cfg_config.network4);
794 		break;
795 
796 	default:
797 		plog(LLV_ERROR, LOCATION, NULL, "Unexpected type %d\n", type);
798 		break;
799 	}
800 
801 	return NULL;
802 }
803 
804 #if 0
805 static vchar_t *
806 isakmp_cfg_void(iph1, attr)
807 	struct ph1handle *iph1;
808 	struct isakmp_data *attr;
809 {
810 	vchar_t *buffer;
811 	struct isakmp_data *new;
812 
813 	if ((buffer = vmalloc(sizeof(*attr))) == NULL) {
814 		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
815 		return NULL;
816 	}
817 
818 	new = (struct isakmp_data *)buffer->v;
819 
820 	new->type = attr->type;
821 	new->lorv = htons(0);
822 
823 	return buffer;
824 }
825 #endif
826 
827 vchar_t *
828 isakmp_cfg_copy(iph1, attr)
829 	struct ph1handle *iph1;
830 	struct isakmp_data *attr;
831 {
832 	vchar_t *buffer;
833 	size_t len = 0;
834 
835 	if ((ntohs(attr->type) & ISAKMP_GEN_MASK) == ISAKMP_GEN_TLV)
836 		len = ntohs(attr->lorv);
837 
838 	if ((buffer = vmalloc(sizeof(*attr) + len)) == NULL) {
839 		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
840 		return NULL;
841 	}
842 
843 	memcpy(buffer->v, attr, sizeof(*attr) + ntohs(attr->lorv));
844 
845 	return buffer;
846 }
847 
848 vchar_t *
849 isakmp_cfg_short(iph1, attr, value)
850 	struct ph1handle *iph1;
851 	struct isakmp_data *attr;
852 	int value;
853 {
854 	vchar_t *buffer;
855 	struct isakmp_data *new;
856 	int type;
857 
858 	if ((buffer = vmalloc(sizeof(*attr))) == NULL) {
859 		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
860 		return NULL;
861 	}
862 
863 	new = (struct isakmp_data *)buffer->v;
864 	type = ntohs(attr->type) & ~ISAKMP_GEN_MASK;
865 
866 	new->type = htons(type | ISAKMP_GEN_TV);
867 	new->lorv = htons(value);
868 
869 	return buffer;
870 }
871 
872 vchar_t *
873 isakmp_cfg_string(iph1, attr, string)
874 	struct ph1handle *iph1;
875 	struct isakmp_data *attr;
876 	char *string;
877 {
878 	vchar_t *buffer;
879 	struct isakmp_data *new;
880 	size_t len;
881 	char *data;
882 
883 	len = strlen(string);
884 	if ((buffer = vmalloc(sizeof(*attr) + len)) == NULL) {
885 		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
886 		return NULL;
887 	}
888 
889 	new = (struct isakmp_data *)buffer->v;
890 
891 	new->type = attr->type;
892 	new->lorv = htons(len);
893 	data = (char *)(new + 1);
894 
895 	memcpy(data, string, len);
896 
897 	return buffer;
898 }
899 
900 static vchar_t *
901 isakmp_cfg_addr4(iph1, attr, addr)
902 	struct ph1handle *iph1;
903 	struct isakmp_data *attr;
904 	in_addr_t *addr;
905 {
906 	vchar_t *buffer;
907 	struct isakmp_data *new;
908 	size_t len;
909 
910 	len = sizeof(*addr);
911 	if ((buffer = vmalloc(sizeof(*attr) + len)) == NULL) {
912 		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
913 		return NULL;
914 	}
915 
916 	new = (struct isakmp_data *)buffer->v;
917 
918 	new->type = attr->type;
919 	new->lorv = htons(len);
920 	memcpy(new + 1, addr, len);
921 
922 	return buffer;
923 }
924 
925 struct isakmp_ivm *
926 isakmp_cfg_newiv(iph1, msgid)
927 	struct ph1handle *iph1;
928 	u_int32_t msgid;
929 {
930 	struct isakmp_cfg_state *ics = iph1->mode_cfg;
931 
932 	if (ics == NULL) {
933 		plog(LLV_ERROR, LOCATION, NULL,
934 		    "isakmp_cfg_newiv called without mode config state\n");
935 		return NULL;
936 	}
937 
938 	if (ics->ivm != NULL)
939 		oakley_delivm(ics->ivm);
940 
941 	ics->ivm = oakley_newiv2(iph1, msgid);
942 
943 	return ics->ivm;
944 }
945 
946 /* Derived from isakmp_info_send_common */
947 int
948 isakmp_cfg_send(iph1, payload, np, flags, new_exchange)
949 	struct ph1handle *iph1;
950 	vchar_t *payload;
951 	u_int32_t np;
952 	int flags;
953 	int new_exchange;
954 {
955 	struct ph2handle *iph2 = NULL;
956 	vchar_t *hash = NULL;
957 	struct isakmp *isakmp;
958 	struct isakmp_gen *gen;
959 	char *p;
960 	int tlen;
961 	int error = -1;
962 	struct isakmp_cfg_state *ics = iph1->mode_cfg;
963 
964 	/* Check if phase 1 is established */
965 	if ((iph1->status != PHASE1ST_ESTABLISHED) ||
966 	    (iph1->local == NULL) ||
967 	    (iph1->remote == NULL)) {
968 		plog(LLV_ERROR, LOCATION, NULL,
969 		    "ISAKMP mode config exchange with immature phase 1\n");
970 		goto end;
971 	}
972 
973 	/* add new entry to isakmp status table */
974 	iph2 = newph2();
975 	if (iph2 == NULL)
976 		goto end;
977 
978 	iph2->dst = dupsaddr(iph1->remote);
979 	iph2->src = dupsaddr(iph1->local);
980 	switch (iph1->remote->sa_family) {
981 	case AF_INET:
982 #ifndef ENABLE_NATT
983 		((struct sockaddr_in *)iph2->dst)->sin_port = 0;
984 		((struct sockaddr_in *)iph2->src)->sin_port = 0;
985 #endif
986 		break;
987 #ifdef INET6
988 	case AF_INET6:
989 		((struct sockaddr_in6 *)iph2->dst)->sin6_port = 0;
990 		((struct sockaddr_in6 *)iph2->src)->sin6_port = 0;
991 		break;
992 #endif
993 	default:
994 		plog(LLV_ERROR, LOCATION, NULL,
995 			"invalid family: %d\n", iph1->remote->sa_family);
996 		delph2(iph2);
997 		goto end;
998 	}
999 	iph2->ph1 = iph1;
1000 	iph2->side = INITIATOR;
1001 	iph2->status = PHASE2ST_START;
1002 
1003 	if (new_exchange)
1004 		iph2->msgid = isakmp_newmsgid2(iph1);
1005 	else
1006 		iph2->msgid = iph1->msgid;
1007 
1008 	/* get IV and HASH(1) if skeyid_a was generated. */
1009 	if (iph1->skeyid_a != NULL) {
1010 		if (new_exchange) {
1011 			if (isakmp_cfg_newiv(iph1, iph2->msgid) == NULL) {
1012 				delph2(iph2);
1013 				goto end;
1014 			}
1015 		}
1016 
1017 		/* generate HASH(1) */
1018 		hash = oakley_compute_hash1(iph2->ph1, iph2->msgid, payload);
1019 		if (hash == NULL) {
1020 			delph2(iph2);
1021 			goto end;
1022 		}
1023 
1024 		/* initialized total buffer length */
1025 		tlen = hash->l;
1026 		tlen += sizeof(*gen);
1027 	} else {
1028 		/* IKE-SA is not established */
1029 		hash = NULL;
1030 
1031 		/* initialized total buffer length */
1032 		tlen = 0;
1033 	}
1034 	if ((flags & ISAKMP_FLAG_A) == 0)
1035 		iph2->flags = (hash == NULL ? 0 : ISAKMP_FLAG_E);
1036 	else
1037 		iph2->flags = (hash == NULL ? 0 : ISAKMP_FLAG_A);
1038 
1039 	insph2(iph2);
1040 	bindph12(iph1, iph2);
1041 
1042 	tlen += sizeof(*isakmp) + payload->l;
1043 
1044 	/* create buffer for isakmp payload */
1045 	iph2->sendbuf = vmalloc(tlen);
1046 	if (iph2->sendbuf == NULL) {
1047 		plog(LLV_ERROR, LOCATION, NULL,
1048 			"failed to get buffer to send.\n");
1049 		goto err;
1050 	}
1051 
1052 	/* create isakmp header */
1053 	isakmp = (struct isakmp *)iph2->sendbuf->v;
1054 	memcpy(&isakmp->i_ck, &iph1->index.i_ck, sizeof(cookie_t));
1055 	memcpy(&isakmp->r_ck, &iph1->index.r_ck, sizeof(cookie_t));
1056 	isakmp->np = hash == NULL ? (np & 0xff) : ISAKMP_NPTYPE_HASH;
1057 	isakmp->v = iph1->version;
1058 	isakmp->etype = ISAKMP_ETYPE_CFG;
1059 	isakmp->flags = iph2->flags;
1060 	memcpy(&isakmp->msgid, &iph2->msgid, sizeof(isakmp->msgid));
1061 	isakmp->len = htonl(tlen);
1062 	p = (char *)(isakmp + 1);
1063 
1064 	/* create HASH payload */
1065 	if (hash != NULL) {
1066 		gen = (struct isakmp_gen *)p;
1067 		gen->np = np & 0xff;
1068 		gen->len = htons(sizeof(*gen) + hash->l);
1069 		p += sizeof(*gen);
1070 		memcpy(p, hash->v, hash->l);
1071 		p += hash->l;
1072 	}
1073 
1074 	/* add payload */
1075 	memcpy(p, payload->v, payload->l);
1076 	p += payload->l;
1077 
1078 #ifdef HAVE_PRINT_ISAKMP_C
1079 	isakmp_printpacket(iph2->sendbuf, iph1->local, iph1->remote, 1);
1080 #endif
1081 
1082 	/* encoding */
1083 	if (ISSET(isakmp->flags, ISAKMP_FLAG_E)) {
1084 		vchar_t *tmp;
1085 
1086 		tmp = oakley_do_encrypt(iph2->ph1, iph2->sendbuf,
1087 			ics->ivm->ive, ics->ivm->iv);
1088 		VPTRINIT(iph2->sendbuf);
1089 		if (tmp == NULL)
1090 			goto err;
1091 		iph2->sendbuf = tmp;
1092 	}
1093 
1094 	/* HDR*, HASH(1), ATTR */
1095 	if (isakmp_send(iph2->ph1, iph2->sendbuf) < 0) {
1096 		VPTRINIT(iph2->sendbuf);
1097 		goto err;
1098 	}
1099 
1100 	plog(LLV_DEBUG, LOCATION, NULL,
1101 		"sendto mode config %s.\n", s_isakmp_nptype(np));
1102 
1103 	/*
1104 	 * XXX We might need to resend the message...
1105 	 */
1106 
1107 	error = 0;
1108 	VPTRINIT(iph2->sendbuf);
1109 
1110 err:
1111 	if (iph2->sendbuf != NULL)
1112 		vfree(iph2->sendbuf);
1113 
1114 	unbindph12(iph2);
1115 	remph2(iph2);
1116 	delph2(iph2);
1117 end:
1118 	if (hash)
1119 		vfree(hash);
1120 	return error;
1121 }
1122 
1123 
1124 void
1125 isakmp_cfg_rmstate(iph1)
1126 	struct ph1handle *iph1;
1127 {
1128 	struct isakmp_cfg_state *state = iph1->mode_cfg;
1129 
1130 	if (isakmp_cfg_accounting(iph1, ISAKMP_CFG_LOGOUT) != 0)
1131 		plog(LLV_ERROR, LOCATION, NULL, "Accounting failed\n");
1132 
1133 	if (state->flags & ISAKMP_CFG_PORT_ALLOCATED)
1134 		isakmp_cfg_putport(iph1, state->port);
1135 
1136 	xauth_rmstate(&state->xauth);
1137 
1138 	racoon_free(state);
1139 	iph1->mode_cfg = NULL;
1140 
1141 	return;
1142 }
1143 
1144 struct isakmp_cfg_state *
1145 isakmp_cfg_mkstate(void)
1146 {
1147 	struct isakmp_cfg_state *state;
1148 
1149 	if ((state = racoon_malloc(sizeof(*state))) == NULL) {
1150 		plog(LLV_ERROR, LOCATION, NULL,
1151 		    "Cannot allocate memory for mode config state\n");
1152 		return NULL;
1153 	}
1154 	memset(state, 0, sizeof(*state));
1155 
1156 	return state;
1157 }
1158 
1159 int
1160 isakmp_cfg_getport(iph1)
1161 	struct ph1handle *iph1;
1162 {
1163 	unsigned int i;
1164 	size_t size = isakmp_cfg_config.pool_size;
1165 
1166 	if (iph1->mode_cfg->flags & ISAKMP_CFG_PORT_ALLOCATED)
1167 		return iph1->mode_cfg->port;
1168 
1169 	if (isakmp_cfg_config.port_pool == NULL) {
1170 		plog(LLV_ERROR, LOCATION, NULL,
1171 		    "isakmp_cfg_config.port_pool == NULL\n");
1172 		return -1;
1173 	}
1174 
1175 	for (i = 0; i < size; i++) {
1176 		if (isakmp_cfg_config.port_pool[i].used == 0)
1177 			break;
1178 	}
1179 
1180 	if (i == size) {
1181 		plog(LLV_ERROR, LOCATION, NULL,
1182 		    "No more addresses available\n");
1183 			return -1;
1184 	}
1185 
1186 	isakmp_cfg_config.port_pool[i].used = 1;
1187 
1188 	plog(LLV_INFO, LOCATION, NULL, "Using port %d\n", i);
1189 
1190 	iph1->mode_cfg->flags |= ISAKMP_CFG_PORT_ALLOCATED;
1191 	iph1->mode_cfg->port = i;
1192 
1193 	return i;
1194 }
1195 
1196 int
1197 isakmp_cfg_putport(iph1, index)
1198 	struct ph1handle *iph1;
1199 	unsigned int index;
1200 {
1201 	if (isakmp_cfg_config.port_pool == NULL) {
1202 		plog(LLV_ERROR, LOCATION, NULL,
1203 		    "isakmp_cfg_config.port_pool == NULL\n");
1204 		return -1;
1205 	}
1206 
1207 	if (isakmp_cfg_config.port_pool[index].used == 0) {
1208 		plog(LLV_ERROR, LOCATION, NULL,
1209 		    "Attempt to release an unallocated address (port %d)\n",
1210 		    index);
1211 		return -1;
1212 	}
1213 
1214 #ifdef HAVE_LIBPAM
1215 	/* Cleanup PAM status associated with the port */
1216 	if (isakmp_cfg_config.authsource == ISAKMP_CFG_AUTH_PAM)
1217 		privsep_cleanup_pam(index);
1218 #endif
1219 	isakmp_cfg_config.port_pool[index].used = 0;
1220 	iph1->mode_cfg->flags &= ISAKMP_CFG_PORT_ALLOCATED;
1221 
1222 	plog(LLV_INFO, LOCATION, NULL, "Released port %d\n", index);
1223 
1224 	return 0;
1225 }
1226 
1227 #ifdef HAVE_LIBPAM
1228 void
1229 cleanup_pam(port)
1230 	int port;
1231 {
1232 	if (isakmp_cfg_config.port_pool[port].pam != NULL) {
1233 		pam_end(isakmp_cfg_config.port_pool[port].pam, PAM_SUCCESS);
1234 		isakmp_cfg_config.port_pool[port].pam = NULL;
1235 	}
1236 
1237 	return;
1238 }
1239 #endif
1240 
1241 /* Accounting, only for RADIUS or PAM */
1242 static int
1243 isakmp_cfg_accounting(iph1, inout)
1244 	struct ph1handle *iph1;
1245 	int inout;
1246 {
1247 #ifdef HAVE_LIBPAM
1248 	if (isakmp_cfg_config.accounting == ISAKMP_CFG_ACCT_PAM)
1249 		return privsep_accounting_pam(iph1->mode_cfg->port,
1250 		    inout);
1251 #endif
1252 #ifdef HAVE_LIBRADIUS
1253 	if (isakmp_cfg_config.accounting == ISAKMP_CFG_ACCT_RADIUS)
1254 		return isakmp_cfg_accounting_radius(iph1, inout);
1255 #endif
1256 	return 0;
1257 }
1258 
1259 #ifdef HAVE_LIBPAM
1260 int
1261 isakmp_cfg_accounting_pam(port, inout)
1262 	int port;
1263 	int inout;
1264 {
1265 	int error = 0;
1266 	pam_handle_t *pam;
1267 
1268 	if (isakmp_cfg_config.port_pool == NULL) {
1269 		plog(LLV_ERROR, LOCATION, NULL,
1270 		    "isakmp_cfg_config.port_pool == NULL\n");
1271 		return -1;
1272 	}
1273 
1274 	pam = isakmp_cfg_config.port_pool[port].pam;
1275 	if (pam == NULL) {
1276 		plog(LLV_ERROR, LOCATION, NULL, "pam handle is NULL\n");
1277 		return -1;
1278 	}
1279 
1280 	switch (inout) {
1281 	case ISAKMP_CFG_LOGIN:
1282 		error = pam_open_session(pam, 0);
1283 		break;
1284 	case ISAKMP_CFG_LOGOUT:
1285 		error = pam_close_session(pam, 0);
1286 		pam_end(pam, error);
1287 		isakmp_cfg_config.port_pool[port].pam = NULL;
1288 		break;
1289 	default:
1290 		plog(LLV_ERROR, LOCATION, NULL, "Unepected inout\n");
1291 		break;
1292 	}
1293 
1294 	if (error != 0) {
1295 		plog(LLV_ERROR, LOCATION, NULL,
1296 		    "pam_open_session/pam_close_session failed: %s\n",
1297 		    pam_strerror(pam, error));
1298 		return -1;
1299         }
1300 
1301 	return 0;
1302 }
1303 #endif /* HAVE_LIBPAM */
1304 
1305 #ifdef HAVE_LIBRADIUS
1306 static int
1307 isakmp_cfg_accounting_radius(iph1, inout)
1308 	struct ph1handle *iph1;
1309 	int inout;
1310 {
1311 	/* For first time use, initialize Radius */
1312 	if (radius_acct_state == NULL) {
1313 		if ((radius_acct_state = rad_acct_open()) == NULL) {
1314 			plog(LLV_ERROR, LOCATION, NULL,
1315 			    "Cannot init librradius\n");
1316 			return -1;
1317 		}
1318 
1319 		if (rad_config(radius_acct_state, NULL) != 0) {
1320 			 plog(LLV_ERROR, LOCATION, NULL,
1321 			     "Cannot open librarius config file: %s\n",
1322 			     rad_strerror(radius_acct_state));
1323 			  rad_close(radius_acct_state);
1324 			  radius_acct_state = NULL;
1325 			  return -1;
1326 		}
1327 	}
1328 
1329 	if (rad_create_request(radius_acct_state,
1330 	    RAD_ACCOUNTING_REQUEST) != 0) {
1331 		plog(LLV_ERROR, LOCATION, NULL,
1332 		    "rad_create_request failed: %s\n",
1333 		    rad_strerror(radius_acct_state));
1334 		return -1;
1335 	}
1336 
1337 	if (rad_put_string(radius_acct_state, RAD_USER_NAME,
1338 	    iph1->mode_cfg->login) != 0) {
1339 		plog(LLV_ERROR, LOCATION, NULL,
1340 		    "rad_put_string failed: %s\n",
1341 		    rad_strerror(radius_acct_state));
1342 		return -1;
1343 	}
1344 
1345 	switch (inout) {
1346 	case ISAKMP_CFG_LOGIN:
1347 		inout = RAD_START;
1348 		break;
1349 	case ISAKMP_CFG_LOGOUT:
1350 		inout = RAD_STOP;
1351 		break;
1352 	default:
1353 		plog(LLV_ERROR, LOCATION, NULL, "Unepected inout\n");
1354 		break;
1355 	}
1356 
1357 	if (rad_put_addr(radius_acct_state,
1358 	    RAD_FRAMED_IP_ADDRESS, iph1->mode_cfg->addr4) != 0) {
1359 		plog(LLV_ERROR, LOCATION, NULL,
1360 		    "rad_put_addr failed: %s\n",
1361 		    rad_strerror(radius_acct_state));
1362 		return -1;
1363 	}
1364 
1365 	if (rad_put_addr(radius_acct_state,
1366 	    RAD_LOGIN_IP_HOST, iph1->mode_cfg->addr4) != 0) {
1367 		plog(LLV_ERROR, LOCATION, NULL,
1368 		    "rad_put_addr failed: %s\n",
1369 		    rad_strerror(radius_acct_state));
1370 		return -1;
1371 	}
1372 
1373 	if (rad_put_int(radius_acct_state, RAD_ACCT_STATUS_TYPE, inout) != 0) {
1374 		plog(LLV_ERROR, LOCATION, NULL,
1375 		    "rad_put_int failed: %s\n",
1376 		    rad_strerror(radius_acct_state));
1377 		return -1;
1378 	}
1379 
1380 	if (isakmp_cfg_radius_common(radius_acct_state,
1381 	    iph1->mode_cfg->port) != 0)
1382 		return -1;
1383 
1384 	if (rad_send_request(radius_acct_state) != RAD_ACCOUNTING_RESPONSE) {
1385 		plog(LLV_ERROR, LOCATION, NULL,
1386 		    "rad_send_request failed: %s\n",
1387 		    rad_strerror(radius_acct_state));
1388 		return -1;
1389 	}
1390 
1391 	return 0;
1392 }
1393 #endif /* HAVE_LIBRADIUS */
1394 
1395 /*
1396  * Attributes common to all RADIUS requests
1397  */
1398 #ifdef HAVE_LIBRADIUS
1399 int
1400 isakmp_cfg_radius_common(radius_state, port)
1401 	struct rad_handle *radius_state;
1402 	int port;
1403 {
1404 	struct utsname name;
1405 	static struct hostent *host = NULL;
1406 	struct in_addr nas_addr;
1407 
1408 	/*
1409 	 * Find our own IP by resolving our nodename
1410 	 */
1411 	if (host == NULL) {
1412 		if (uname(&name) != 0) {
1413 			plog(LLV_ERROR, LOCATION, NULL,
1414 			    "uname failed: %s\n", strerror(errno));
1415 			return -1;
1416 		}
1417 
1418 		if ((host = gethostbyname(name.nodename)) == NULL) {
1419 			plog(LLV_ERROR, LOCATION, NULL,
1420 			    "gethostbyname failed: %s\n", strerror(errno));
1421 			return -1;
1422 		}
1423 	}
1424 
1425 	memcpy(&nas_addr, host->h_addr, sizeof(nas_addr));
1426 	if (rad_put_addr(radius_state, RAD_NAS_IP_ADDRESS, nas_addr) != 0) {
1427 		plog(LLV_ERROR, LOCATION, NULL,
1428 		    "rad_put_addr failed: %s\n",
1429 		    rad_strerror(radius_state));
1430 		return -1;
1431 	}
1432 
1433 	if (rad_put_int(radius_state, RAD_NAS_PORT, port) != 0) {
1434 		plog(LLV_ERROR, LOCATION, NULL,
1435 		    "rad_put_int failed: %s\n",
1436 		    rad_strerror(radius_state));
1437 		return -1;
1438 	}
1439 
1440 	if (rad_put_int(radius_state, RAD_NAS_PORT_TYPE, RAD_VIRTUAL) != 0) {
1441 		plog(LLV_ERROR, LOCATION, NULL,
1442 		    "rad_put_int failed: %s\n",
1443 		    rad_strerror(radius_state));
1444 		return -1;
1445 	}
1446 
1447 	if (rad_put_int(radius_state, RAD_SERVICE_TYPE, RAD_FRAMED) != 0) {
1448 		plog(LLV_ERROR, LOCATION, NULL,
1449 		    "rad_put_int failed: %s\n",
1450 		    rad_strerror(radius_state));
1451 		return -1;
1452 	}
1453 
1454 	return 0;
1455 }
1456 #endif
1457 
1458 int
1459 isakmp_cfg_getconfig(iph1)
1460 	struct ph1handle *iph1;
1461 {
1462 	vchar_t *buffer;
1463 	struct isakmp_pl_attr *attrpl;
1464 	struct isakmp_data *attr;
1465 	size_t len;
1466 	int error;
1467 	int attrcount;
1468 	int i;
1469 	int attrlist[] = {
1470 		INTERNAL_IP4_ADDRESS,
1471 		INTERNAL_IP4_NETMASK,
1472 		INTERNAL_IP4_DNS,
1473 		INTERNAL_IP4_NBNS,
1474 		UNITY_BANNER,
1475 		APPLICATION_VERSION,
1476 	};
1477 
1478 	attrcount = sizeof(attrlist) / sizeof(*attrlist);
1479 	len = sizeof(*attrpl) + sizeof(*attr) * attrcount;
1480 
1481 	if ((buffer = vmalloc(len)) == NULL) {
1482 		plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
1483 		return -1;
1484 	}
1485 
1486 	attrpl = (struct isakmp_pl_attr *)buffer->v;
1487 	attrpl->h.len = htons(len);
1488 	attrpl->type = ISAKMP_CFG_REQUEST;
1489 	attrpl->id = htons((u_int16_t)(eay_random() & 0xffff));
1490 
1491 	attr = (struct isakmp_data *)(attrpl + 1);
1492 
1493 	for (i = 0; i < attrcount; i++) {
1494 		attr->type = htons(attrlist[i]);
1495 		attr->lorv = htons(0);
1496 		attr++;
1497 	}
1498 
1499 	error = isakmp_cfg_send(iph1, buffer,
1500 	    ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 1);
1501 
1502 	vfree(buffer);
1503 
1504 	return error;
1505 }
1506 
1507 static void
1508 isakmp_cfg_getaddr4(attr, ip)
1509 	struct isakmp_data *attr;
1510 	struct in_addr *ip;
1511 {
1512 	size_t alen = ntohs(attr->lorv);
1513 	in_addr_t *addr;
1514 
1515 	if (alen != sizeof(*ip)) {
1516 		plog(LLV_ERROR, LOCATION, NULL, "Bad IPv4 address len\n");
1517 		return;
1518 	}
1519 
1520 	addr = (in_addr_t *)(attr + 1);
1521 	ip->s_addr = *addr;
1522 
1523 	return;
1524 }
1525 
1526 int
1527 isakmp_cfg_setenv(iph1, envp, envc)
1528 	struct ph1handle *iph1;
1529 	char ***envp;
1530 	int *envc;
1531 {
1532 #define IP_MAX 40
1533 	char addrstr[IP_MAX];
1534 
1535 	/*
1536 	 * Internal IPv4 address, either if
1537 	 * we are a client or a server.
1538 	 */
1539 	if ((iph1->mode_cfg->flags & ISAKMP_CFG_GOT_ADDR4) ||
1540 #ifdef HAVE_LIBRADIUS
1541 	    (iph1->mode_cfg->flags & ISAKMP_CFG_ADDR4_RADIUS) ||
1542 #endif
1543 	    (iph1->mode_cfg->flags & ISAKMP_CFG_ADDR4_LOCAL)) {
1544 		inet_ntop(AF_INET, &iph1->mode_cfg->addr4,
1545 		    addrstr, IP_MAX);
1546 	} else
1547 		addrstr[0] = '\0';
1548 
1549 	if (script_env_append(envp, envc, "INTERNAL_ADDR4", addrstr) != 0) {
1550 		plog(LLV_ERROR, LOCATION, NULL, "Cannot set INTERNAL_ADDR4\n");
1551 		return -1;
1552 	}
1553 
1554 	/* Internal IPv4 mask */
1555 	if (iph1->mode_cfg->flags & ISAKMP_CFG_GOT_MASK4)
1556 		inet_ntop(AF_INET, &iph1->mode_cfg->mask4,
1557 		    addrstr, IP_MAX);
1558 	else
1559 		addrstr[0] = '\0';
1560 
1561 	if (script_env_append(envp, envc, "INTERNAL_MASK4", addrstr) != 0) {
1562 		plog(LLV_ERROR, LOCATION, NULL, "Cannot set INTERNAL_MASK4\n");
1563 		return -1;
1564 	}
1565 
1566 	/* Internal IPv4 DNS */
1567 	if (iph1->mode_cfg->flags & ISAKMP_CFG_GOT_DNS4)
1568 		inet_ntop(AF_INET, &iph1->mode_cfg->dns4,
1569 		    addrstr, IP_MAX);
1570 	else
1571 		addrstr[0] = '\0';
1572 
1573 	if (script_env_append(envp, envc, "INTERNAL_DNS4", addrstr) != 0) {
1574 		plog(LLV_ERROR, LOCATION, NULL, "Cannot set INTERNAL_DNS4\n");
1575 		return -1;
1576 	}
1577 
1578 	/* Internal IPv4 WINS */
1579 	if (iph1->mode_cfg->flags & ISAKMP_CFG_GOT_WINS4)
1580 		inet_ntop(AF_INET, &iph1->mode_cfg->wins4,
1581 		    addrstr, IP_MAX);
1582 	else
1583 		addrstr[0] = '\0';
1584 
1585 	if (script_env_append(envp, envc, "INTERNAL_WINS4", addrstr) != 0) {
1586 		plog(LLV_ERROR, LOCATION, NULL, "Cannot set INTERNAL_WINS4\n");
1587 		return -1;
1588 	}
1589 
1590 	return 0;
1591 }
1592