Annotation of embedaddon/ipsec-tools/src/racoon/isakmp_cfg.c, revision 1.1
1.1 ! misho 1: /* $NetBSD: isakmp_cfg.c,v 1.24 2010/09/21 13:14:17 vanhu Exp $ */
! 2:
! 3: /* Id: isakmp_cfg.c,v 1.55 2006/08/22 18:17:17 manubsd Exp */
! 4:
! 5: /*
! 6: * Copyright (C) 2004-2006 Emmanuel Dreyfus
! 7: * All rights reserved.
! 8: *
! 9: * Redistribution and use in source and binary forms, with or without
! 10: * modification, are permitted provided that the following conditions
! 11: * are met:
! 12: * 1. Redistributions of source code must retain the above copyright
! 13: * notice, this list of conditions and the following disclaimer.
! 14: * 2. Redistributions in binary form must reproduce the above copyright
! 15: * notice, this list of conditions and the following disclaimer in the
! 16: * documentation and/or other materials provided with the distribution.
! 17: * 3. Neither the name of the project nor the names of its contributors
! 18: * may be used to endorse or promote products derived from this software
! 19: * without specific prior written permission.
! 20: *
! 21: * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 31: * SUCH DAMAGE.
! 32: */
! 33:
! 34: #include "config.h"
! 35:
! 36: #include <sys/types.h>
! 37: #include <sys/param.h>
! 38: #include <sys/socket.h>
! 39: #include <sys/queue.h>
! 40:
! 41: #include <utmpx.h>
! 42: #if defined(__APPLE__) && defined(__MACH__)
! 43: #include <util.h>
! 44: #endif
! 45:
! 46: #ifdef __FreeBSD__
! 47: # include <libutil.h>
! 48: #endif
! 49: #ifdef __NetBSD__
! 50: # include <util.h>
! 51: #endif
! 52:
! 53: #include <netinet/in.h>
! 54: #include <arpa/inet.h>
! 55:
! 56: #include <stdlib.h>
! 57: #include <stdio.h>
! 58: #include <string.h>
! 59: #include <errno.h>
! 60: #if TIME_WITH_SYS_TIME
! 61: # include <sys/time.h>
! 62: # include <time.h>
! 63: #else
! 64: # if HAVE_SYS_TIME_H
! 65: # include <sys/time.h>
! 66: # else
! 67: # include <time.h>
! 68: # endif
! 69: #endif
! 70: #include <netdb.h>
! 71: #ifdef HAVE_UNISTD_H
! 72: #include <unistd.h>
! 73: #endif
! 74: #if HAVE_STDINT_H
! 75: #include <stdint.h>
! 76: #endif
! 77: #include <ctype.h>
! 78: #include <resolv.h>
! 79:
! 80: #ifdef HAVE_LIBRADIUS
! 81: #include <sys/utsname.h>
! 82: #include <radlib.h>
! 83: #endif
! 84:
! 85: #include "var.h"
! 86: #include "misc.h"
! 87: #include "vmbuf.h"
! 88: #include "plog.h"
! 89: #include "sockmisc.h"
! 90: #include "schedule.h"
! 91: #include "debug.h"
! 92:
! 93: #include "isakmp_var.h"
! 94: #include "isakmp.h"
! 95: #include "handler.h"
! 96: #include "evt.h"
! 97: #include "throttle.h"
! 98: #include "remoteconf.h"
! 99: #include "crypto_openssl.h"
! 100: #include "isakmp_inf.h"
! 101: #include "isakmp_xauth.h"
! 102: #include "isakmp_unity.h"
! 103: #include "isakmp_cfg.h"
! 104: #include "strnames.h"
! 105: #include "admin.h"
! 106: #include "privsep.h"
! 107:
! 108: struct isakmp_cfg_config isakmp_cfg_config;
! 109:
! 110: static vchar_t *buffer_cat(vchar_t *s, vchar_t *append);
! 111: static vchar_t *isakmp_cfg_net(struct ph1handle *, struct isakmp_data *);
! 112: #if 0
! 113: static vchar_t *isakmp_cfg_void(struct ph1handle *, struct isakmp_data *);
! 114: #endif
! 115: static vchar_t *isakmp_cfg_addr4(struct ph1handle *,
! 116: struct isakmp_data *, in_addr_t *);
! 117: static vchar_t *isakmp_cfg_addrnet4(struct ph1handle *,
! 118: struct isakmp_data *, in_addr_t *, in_addr_t *);
! 119: static void isakmp_cfg_getaddr4(struct isakmp_data *, struct in_addr *);
! 120: static vchar_t *isakmp_cfg_addr4_list(struct ph1handle *,
! 121: struct isakmp_data *, in_addr_t *, int);
! 122: static void isakmp_cfg_appendaddr4(struct isakmp_data *,
! 123: struct in_addr *, int *, int);
! 124: static void isakmp_cfg_getstring(struct isakmp_data *,char *);
! 125: void isakmp_cfg_iplist_to_str(char *, int, void *, int);
! 126:
! 127: #define ISAKMP_CFG_LOGIN 1
! 128: #define ISAKMP_CFG_LOGOUT 2
! 129: static int isakmp_cfg_accounting(struct ph1handle *, int);
! 130: #ifdef HAVE_LIBRADIUS
! 131: static 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: */
! 138: void
! 139: isakmp_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:
! 269: out:
! 270: vfree(dmsg);
! 271: }
! 272:
! 273: int
! 274: isakmp_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:
! 315: int
! 316: isakmp_cfg_reply(iph1, attrpl)
! 317: struct ph1handle *iph1;
! 318: struct isakmp_pl_attr *attrpl;
! 319: {
! 320: struct isakmp_data *attr;
! 321: int tlen;
! 322: size_t alen;
! 323: char *npp;
! 324: int type;
! 325: struct sockaddr_in *sin;
! 326: int error;
! 327:
! 328: tlen = ntohs(attrpl->h.len);
! 329: attr = (struct isakmp_data *)(attrpl + 1);
! 330: tlen -= sizeof(*attrpl);
! 331:
! 332: while (tlen > 0) {
! 333: type = ntohs(attr->type);
! 334:
! 335: /* Handle short attributes */
! 336: if ((type & ISAKMP_GEN_MASK) == ISAKMP_GEN_TV) {
! 337: type &= ~ISAKMP_GEN_MASK;
! 338:
! 339: plog(LLV_DEBUG, LOCATION, NULL,
! 340: "Short attribute %s = %d\n",
! 341: s_isakmp_cfg_type(type), ntohs(attr->lorv));
! 342:
! 343: switch (type) {
! 344: case XAUTH_TYPE:
! 345: if ((error = xauth_attr_reply(iph1,
! 346: attr, ntohs(attrpl->id))) != 0)
! 347: return error;
! 348: break;
! 349:
! 350: default:
! 351: plog(LLV_WARNING, LOCATION, NULL,
! 352: "Ignored short attribute %s\n",
! 353: s_isakmp_cfg_type(type));
! 354: break;
! 355: }
! 356:
! 357: tlen -= sizeof(*attr);
! 358: attr++;
! 359: continue;
! 360: }
! 361:
! 362: type = ntohs(attr->type);
! 363: alen = ntohs(attr->lorv);
! 364:
! 365: /* Check that the attribute fit in the packet */
! 366: if (tlen < alen) {
! 367: plog(LLV_ERROR, LOCATION, NULL,
! 368: "Short attribute %s\n",
! 369: s_isakmp_cfg_type(type));
! 370: return -1;
! 371: }
! 372:
! 373: plog(LLV_DEBUG, LOCATION, NULL,
! 374: "Attribute %s, len %zu\n",
! 375: s_isakmp_cfg_type(type), alen);
! 376:
! 377: switch(type) {
! 378: case XAUTH_TYPE:
! 379: case XAUTH_USER_NAME:
! 380: case XAUTH_USER_PASSWORD:
! 381: case XAUTH_PASSCODE:
! 382: case XAUTH_MESSAGE:
! 383: case XAUTH_CHALLENGE:
! 384: case XAUTH_DOMAIN:
! 385: case XAUTH_STATUS:
! 386: case XAUTH_NEXT_PIN:
! 387: case XAUTH_ANSWER:
! 388: if ((error = xauth_attr_reply(iph1,
! 389: attr, ntohs(attrpl->id))) != 0)
! 390: return error;
! 391: break;
! 392: case INTERNAL_IP4_ADDRESS:
! 393: isakmp_cfg_getaddr4(attr, &iph1->mode_cfg->addr4);
! 394: iph1->mode_cfg->flags |= ISAKMP_CFG_GOT_ADDR4;
! 395: break;
! 396: case INTERNAL_IP4_NETMASK:
! 397: isakmp_cfg_getaddr4(attr, &iph1->mode_cfg->mask4);
! 398: iph1->mode_cfg->flags |= ISAKMP_CFG_GOT_MASK4;
! 399: break;
! 400: case INTERNAL_IP4_DNS:
! 401: isakmp_cfg_appendaddr4(attr,
! 402: &iph1->mode_cfg->dns4[iph1->mode_cfg->dns4_index],
! 403: &iph1->mode_cfg->dns4_index, MAXNS);
! 404: iph1->mode_cfg->flags |= ISAKMP_CFG_GOT_DNS4;
! 405: break;
! 406: case INTERNAL_IP4_NBNS:
! 407: isakmp_cfg_appendaddr4(attr,
! 408: &iph1->mode_cfg->wins4[iph1->mode_cfg->wins4_index],
! 409: &iph1->mode_cfg->wins4_index, MAXNS);
! 410: iph1->mode_cfg->flags |= ISAKMP_CFG_GOT_WINS4;
! 411: break;
! 412: case UNITY_DEF_DOMAIN:
! 413: isakmp_cfg_getstring(attr,
! 414: iph1->mode_cfg->default_domain);
! 415: iph1->mode_cfg->flags |= ISAKMP_CFG_GOT_DEFAULT_DOMAIN;
! 416: break;
! 417: case UNITY_SPLIT_INCLUDE:
! 418: case UNITY_LOCAL_LAN:
! 419: case UNITY_SPLITDNS_NAME:
! 420: case UNITY_BANNER:
! 421: case UNITY_SAVE_PASSWD:
! 422: case UNITY_NATT_PORT:
! 423: case UNITY_PFS:
! 424: case UNITY_FW_TYPE:
! 425: case UNITY_BACKUP_SERVERS:
! 426: case UNITY_DDNS_HOSTNAME:
! 427: isakmp_unity_reply(iph1, attr);
! 428: break;
! 429: case INTERNAL_IP4_SUBNET:
! 430: case INTERNAL_ADDRESS_EXPIRY:
! 431: default:
! 432: plog(LLV_WARNING, LOCATION, NULL,
! 433: "Ignored attribute %s\n",
! 434: s_isakmp_cfg_type(type));
! 435: break;
! 436: }
! 437:
! 438: npp = (char *)attr;
! 439: attr = (struct isakmp_data *)(npp + sizeof(*attr) + alen);
! 440: tlen -= (sizeof(*attr) + alen);
! 441: }
! 442:
! 443: /*
! 444: * Call the SA up script hook now that we have the configuration
! 445: * It is done at the end of phase 1 if ISAKMP mode config is not
! 446: * requested.
! 447: */
! 448:
! 449: if ((iph1->status == PHASE1ST_ESTABLISHED) &&
! 450: iph1->rmconf->mode_cfg) {
! 451: switch (iph1->approval->authmethod) {
! 452: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I:
! 453: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
! 454: /* Unimplemented */
! 455: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
! 456: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
! 457: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
! 458: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
! 459: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
! 460: script_hook(iph1, SCRIPT_PHASE1_UP);
! 461: break;
! 462: default:
! 463: break;
! 464: }
! 465: }
! 466:
! 467:
! 468: #ifdef ENABLE_ADMINPORT
! 469: {
! 470: vchar_t *buf;
! 471:
! 472: alen = ntohs(attrpl->h.len) - sizeof(*attrpl);
! 473: if ((buf = vmalloc(alen)) == NULL) {
! 474: plog(LLV_WARNING, LOCATION, NULL,
! 475: "Cannot allocate memory: %s\n", strerror(errno));
! 476: } else {
! 477: memcpy(buf->v, attrpl + 1, buf->l);
! 478: evt_phase1(iph1, EVT_PHASE1_MODE_CFG, buf);
! 479: vfree(buf);
! 480: }
! 481: }
! 482: #endif
! 483:
! 484: return 0;
! 485: }
! 486:
! 487: int
! 488: isakmp_cfg_request(iph1, attrpl)
! 489: struct ph1handle *iph1;
! 490: struct isakmp_pl_attr *attrpl;
! 491: {
! 492: struct isakmp_data *attr;
! 493: int tlen;
! 494: size_t alen;
! 495: char *npp;
! 496: vchar_t *payload;
! 497: struct isakmp_pl_attr *reply;
! 498: vchar_t *reply_attr;
! 499: int type;
! 500: int error = -1;
! 501:
! 502: if ((payload = vmalloc(sizeof(*reply))) == NULL) {
! 503: plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
! 504: return -1;
! 505: }
! 506: memset(payload->v, 0, sizeof(*reply));
! 507:
! 508: tlen = ntohs(attrpl->h.len);
! 509: attr = (struct isakmp_data *)(attrpl + 1);
! 510: tlen -= sizeof(*attrpl);
! 511:
! 512: while (tlen > 0) {
! 513: reply_attr = NULL;
! 514: type = ntohs(attr->type);
! 515:
! 516: /* Handle short attributes */
! 517: if ((type & ISAKMP_GEN_MASK) == ISAKMP_GEN_TV) {
! 518: type &= ~ISAKMP_GEN_MASK;
! 519:
! 520: plog(LLV_DEBUG, LOCATION, NULL,
! 521: "Short attribute %s = %d\n",
! 522: s_isakmp_cfg_type(type), ntohs(attr->lorv));
! 523:
! 524: switch (type) {
! 525: case XAUTH_TYPE:
! 526: reply_attr = isakmp_xauth_req(iph1, attr);
! 527: break;
! 528: default:
! 529: plog(LLV_WARNING, LOCATION, NULL,
! 530: "Ignored short attribute %s\n",
! 531: s_isakmp_cfg_type(type));
! 532: break;
! 533: }
! 534:
! 535: tlen -= sizeof(*attr);
! 536: attr++;
! 537:
! 538: if (reply_attr != NULL) {
! 539: payload = buffer_cat(payload, reply_attr);
! 540: vfree(reply_attr);
! 541: }
! 542:
! 543: continue;
! 544: }
! 545:
! 546: type = ntohs(attr->type);
! 547: alen = ntohs(attr->lorv);
! 548:
! 549: /* Check that the attribute fit in the packet */
! 550: if (tlen < alen) {
! 551: plog(LLV_ERROR, LOCATION, NULL,
! 552: "Short attribute %s\n",
! 553: s_isakmp_cfg_type(type));
! 554: goto end;
! 555: }
! 556:
! 557: plog(LLV_DEBUG, LOCATION, NULL,
! 558: "Attribute %s, len %zu\n",
! 559: s_isakmp_cfg_type(type), alen);
! 560:
! 561: switch(type) {
! 562: case INTERNAL_IP4_ADDRESS:
! 563: case INTERNAL_IP4_NETMASK:
! 564: case INTERNAL_IP4_DNS:
! 565: case INTERNAL_IP4_NBNS:
! 566: case INTERNAL_IP4_SUBNET:
! 567: reply_attr = isakmp_cfg_net(iph1, attr);
! 568: break;
! 569:
! 570: case XAUTH_TYPE:
! 571: case XAUTH_USER_NAME:
! 572: case XAUTH_USER_PASSWORD:
! 573: case XAUTH_PASSCODE:
! 574: case XAUTH_MESSAGE:
! 575: case XAUTH_CHALLENGE:
! 576: case XAUTH_DOMAIN:
! 577: case XAUTH_STATUS:
! 578: case XAUTH_NEXT_PIN:
! 579: case XAUTH_ANSWER:
! 580: reply_attr = isakmp_xauth_req(iph1, attr);
! 581: break;
! 582:
! 583: case APPLICATION_VERSION:
! 584: reply_attr = isakmp_cfg_string(iph1,
! 585: attr, ISAKMP_CFG_RACOON_VERSION);
! 586: break;
! 587:
! 588: case UNITY_BANNER:
! 589: case UNITY_PFS:
! 590: case UNITY_SAVE_PASSWD:
! 591: case UNITY_DEF_DOMAIN:
! 592: case UNITY_DDNS_HOSTNAME:
! 593: case UNITY_FW_TYPE:
! 594: case UNITY_SPLITDNS_NAME:
! 595: case UNITY_SPLIT_INCLUDE:
! 596: case UNITY_LOCAL_LAN:
! 597: case UNITY_NATT_PORT:
! 598: case UNITY_BACKUP_SERVERS:
! 599: reply_attr = isakmp_unity_req(iph1, attr);
! 600: break;
! 601:
! 602: case INTERNAL_ADDRESS_EXPIRY:
! 603: default:
! 604: plog(LLV_WARNING, LOCATION, NULL,
! 605: "Ignored attribute %s\n",
! 606: s_isakmp_cfg_type(type));
! 607: break;
! 608: }
! 609:
! 610: npp = (char *)attr;
! 611: attr = (struct isakmp_data *)(npp + sizeof(*attr) + alen);
! 612: tlen -= (sizeof(*attr) + alen);
! 613:
! 614: if (reply_attr != NULL) {
! 615: payload = buffer_cat(payload, reply_attr);
! 616: vfree(reply_attr);
! 617: }
! 618:
! 619: }
! 620:
! 621: reply = (struct isakmp_pl_attr *)payload->v;
! 622: reply->h.len = htons(payload->l);
! 623: reply->type = ISAKMP_CFG_REPLY;
! 624: reply->id = attrpl->id;
! 625:
! 626: plog(LLV_DEBUG, LOCATION, NULL,
! 627: "Sending MODE_CFG REPLY\n");
! 628:
! 629: error = isakmp_cfg_send(iph1, payload,
! 630: ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 0);
! 631:
! 632: if (iph1->status == PHASE1ST_ESTABLISHED) {
! 633: switch (iph1->approval->authmethod) {
! 634: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
! 635: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
! 636: /* Unimplemented */
! 637: case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
! 638: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
! 639: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
! 640: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
! 641: case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
! 642: script_hook(iph1, SCRIPT_PHASE1_UP);
! 643: break;
! 644: default:
! 645: break;
! 646: }
! 647: }
! 648:
! 649: end:
! 650: vfree(payload);
! 651:
! 652: return error;
! 653: }
! 654:
! 655: int
! 656: isakmp_cfg_set(iph1, attrpl)
! 657: struct ph1handle *iph1;
! 658: struct isakmp_pl_attr *attrpl;
! 659: {
! 660: struct isakmp_data *attr;
! 661: int tlen;
! 662: size_t alen;
! 663: char *npp;
! 664: vchar_t *payload;
! 665: struct isakmp_pl_attr *reply;
! 666: vchar_t *reply_attr;
! 667: int type;
! 668: int error = -1;
! 669:
! 670: if ((payload = vmalloc(sizeof(*reply))) == NULL) {
! 671: plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
! 672: return -1;
! 673: }
! 674: memset(payload->v, 0, sizeof(*reply));
! 675:
! 676: tlen = ntohs(attrpl->h.len);
! 677: attr = (struct isakmp_data *)(attrpl + 1);
! 678: tlen -= sizeof(*attrpl);
! 679:
! 680: /*
! 681: * We should send ack for the attributes we accepted
! 682: */
! 683: while (tlen > 0) {
! 684: reply_attr = NULL;
! 685: type = ntohs(attr->type);
! 686:
! 687: plog(LLV_DEBUG, LOCATION, NULL,
! 688: "Attribute %s\n",
! 689: s_isakmp_cfg_type(type & ~ISAKMP_GEN_MASK));
! 690:
! 691: switch (type & ~ISAKMP_GEN_MASK) {
! 692: case XAUTH_STATUS:
! 693: reply_attr = isakmp_xauth_set(iph1, attr);
! 694: break;
! 695: default:
! 696: plog(LLV_DEBUG, LOCATION, NULL,
! 697: "Unexpected SET attribute %s\n",
! 698: s_isakmp_cfg_type(type & ~ISAKMP_GEN_MASK));
! 699: break;
! 700: }
! 701:
! 702: if (reply_attr != NULL) {
! 703: payload = buffer_cat(payload, reply_attr);
! 704: vfree(reply_attr);
! 705: }
! 706:
! 707: /*
! 708: * Move to next attribute. If we run out of the packet,
! 709: * tlen becomes negative and we exit.
! 710: */
! 711: if ((type & ISAKMP_GEN_MASK) == ISAKMP_GEN_TV) {
! 712: tlen -= sizeof(*attr);
! 713: attr++;
! 714: } else {
! 715: alen = ntohs(attr->lorv);
! 716: tlen -= (sizeof(*attr) + alen);
! 717: npp = (char *)attr;
! 718: attr = (struct isakmp_data *)
! 719: (npp + sizeof(*attr) + alen);
! 720: }
! 721: }
! 722:
! 723: reply = (struct isakmp_pl_attr *)payload->v;
! 724: reply->h.len = htons(payload->l);
! 725: reply->type = ISAKMP_CFG_ACK;
! 726: reply->id = attrpl->id;
! 727:
! 728: plog(LLV_DEBUG, LOCATION, NULL,
! 729: "Sending MODE_CFG ACK\n");
! 730:
! 731: error = isakmp_cfg_send(iph1, payload,
! 732: ISAKMP_NPTYPE_ATTR, ISAKMP_FLAG_E, 0);
! 733:
! 734: if (iph1->mode_cfg->flags & ISAKMP_CFG_DELETE_PH1) {
! 735: if (iph1->status == PHASE1ST_ESTABLISHED ||
! 736: iph1->status == PHASE1ST_DYING)
! 737: isakmp_info_send_d1(iph1);
! 738: remph1(iph1);
! 739: delph1(iph1);
! 740: iph1 = NULL;
! 741: }
! 742: end:
! 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:
! 755: static vchar_t *
! 756: buffer_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:
! 776: static vchar_t *
! 777: isakmp_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: */
! 802: retry_source:
! 803:
! 804: switch(type) {
! 805: case INTERNAL_IP4_ADDRESS:
! 806: switch(confsource) {
! 807: #ifdef HAVE_LIBLDAP
! 808: case ISAKMP_CFG_CONF_LDAP:
! 809: if (iph1->mode_cfg->flags & ISAKMP_CFG_ADDR4_EXTERN)
! 810: break;
! 811: plog(LLV_INFO, LOCATION, NULL,
! 812: "No IP from LDAP, using local pool\n");
! 813: /* FALLTHROUGH */
! 814: confsource = ISAKMP_CFG_CONF_LOCAL;
! 815: goto retry_source;
! 816: #endif
! 817: #ifdef HAVE_LIBRADIUS
! 818: case ISAKMP_CFG_CONF_RADIUS:
! 819: if ((iph1->mode_cfg->flags & ISAKMP_CFG_ADDR4_EXTERN)
! 820: && (iph1->mode_cfg->addr4.s_addr != htonl(-2)))
! 821: /*
! 822: * -2 is 255.255.255.254, RADIUS uses that
! 823: * to instruct the NAS to use a local pool
! 824: */
! 825: break;
! 826: plog(LLV_INFO, LOCATION, NULL,
! 827: "No IP from RADIUS, using local pool\n");
! 828: /* FALLTHROUGH */
! 829: confsource = ISAKMP_CFG_CONF_LOCAL;
! 830: goto retry_source;
! 831: #endif
! 832: case ISAKMP_CFG_CONF_LOCAL:
! 833: if (isakmp_cfg_getport(iph1) == -1) {
! 834: plog(LLV_ERROR, LOCATION, NULL,
! 835: "Port pool depleted\n");
! 836: break;
! 837: }
! 838:
! 839: iph1->mode_cfg->addr4.s_addr =
! 840: htonl(ntohl(isakmp_cfg_config.network4)
! 841: + iph1->mode_cfg->port);
! 842: iph1->mode_cfg->flags |= ISAKMP_CFG_ADDR4_LOCAL;
! 843: break;
! 844:
! 845: default:
! 846: plog(LLV_ERROR, LOCATION, NULL,
! 847: "Unexpected confsource\n");
! 848: }
! 849:
! 850: if (isakmp_cfg_accounting(iph1, ISAKMP_CFG_LOGIN) != 0)
! 851: plog(LLV_ERROR, LOCATION, NULL, "Accounting failed\n");
! 852:
! 853: return isakmp_cfg_addr4(iph1,
! 854: attr, &iph1->mode_cfg->addr4.s_addr);
! 855: break;
! 856:
! 857: case INTERNAL_IP4_NETMASK:
! 858: switch(confsource) {
! 859: #ifdef HAVE_LIBLDAP
! 860: case ISAKMP_CFG_CONF_LDAP:
! 861: if (iph1->mode_cfg->flags & ISAKMP_CFG_MASK4_EXTERN)
! 862: break;
! 863: plog(LLV_INFO, LOCATION, NULL,
! 864: "No mask from LDAP, using local pool\n");
! 865: /* FALLTHROUGH */
! 866: confsource = ISAKMP_CFG_CONF_LOCAL;
! 867: goto retry_source;
! 868: #endif
! 869: #ifdef HAVE_LIBRADIUS
! 870: case ISAKMP_CFG_CONF_RADIUS:
! 871: if (iph1->mode_cfg->flags & ISAKMP_CFG_MASK4_EXTERN)
! 872: break;
! 873: plog(LLV_INFO, LOCATION, NULL,
! 874: "No mask from RADIUS, using local pool\n");
! 875: /* FALLTHROUGH */
! 876: confsource = ISAKMP_CFG_CONF_LOCAL;
! 877: goto retry_source;
! 878: #endif
! 879: case ISAKMP_CFG_CONF_LOCAL:
! 880: iph1->mode_cfg->mask4.s_addr
! 881: = isakmp_cfg_config.netmask4;
! 882: iph1->mode_cfg->flags |= ISAKMP_CFG_MASK4_LOCAL;
! 883: break;
! 884:
! 885: default:
! 886: plog(LLV_ERROR, LOCATION, NULL,
! 887: "Unexpected confsource\n");
! 888: }
! 889: return isakmp_cfg_addr4(iph1, attr,
! 890: &iph1->mode_cfg->mask4.s_addr);
! 891: break;
! 892:
! 893: case INTERNAL_IP4_DNS:
! 894: return isakmp_cfg_addr4_list(iph1,
! 895: attr, &isakmp_cfg_config.dns4[0],
! 896: isakmp_cfg_config.dns4_index);
! 897: break;
! 898:
! 899: case INTERNAL_IP4_NBNS:
! 900: return isakmp_cfg_addr4_list(iph1,
! 901: attr, &isakmp_cfg_config.nbns4[0],
! 902: isakmp_cfg_config.nbns4_index);
! 903: break;
! 904:
! 905: case INTERNAL_IP4_SUBNET:
! 906: if(isakmp_cfg_config.splitnet_count > 0){
! 907: return isakmp_cfg_addrnet4(iph1, attr,
! 908: &isakmp_cfg_config.splitnet_list->network.addr4.s_addr,
! 909: &isakmp_cfg_config.splitnet_list->network.mask4.s_addr);
! 910: }else{
! 911: plog(LLV_INFO, LOCATION, NULL,
! 912: "%s requested but no splitnet in configuration\n",
! 913: s_isakmp_cfg_type(type));
! 914: }
! 915: break;
! 916:
! 917: default:
! 918: plog(LLV_ERROR, LOCATION, NULL, "Unexpected type %d\n", type);
! 919: break;
! 920: }
! 921: return NULL;
! 922: }
! 923:
! 924: #if 0
! 925: static vchar_t *
! 926: isakmp_cfg_void(iph1, attr)
! 927: struct ph1handle *iph1;
! 928: struct isakmp_data *attr;
! 929: {
! 930: vchar_t *buffer;
! 931: struct isakmp_data *new;
! 932:
! 933: if ((buffer = vmalloc(sizeof(*attr))) == NULL) {
! 934: plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
! 935: return NULL;
! 936: }
! 937:
! 938: new = (struct isakmp_data *)buffer->v;
! 939:
! 940: new->type = attr->type;
! 941: new->lorv = htons(0);
! 942:
! 943: return buffer;
! 944: }
! 945: #endif
! 946:
! 947: vchar_t *
! 948: isakmp_cfg_copy(iph1, attr)
! 949: struct ph1handle *iph1;
! 950: struct isakmp_data *attr;
! 951: {
! 952: vchar_t *buffer;
! 953: size_t len = 0;
! 954:
! 955: if ((ntohs(attr->type) & ISAKMP_GEN_MASK) == ISAKMP_GEN_TLV)
! 956: len = ntohs(attr->lorv);
! 957:
! 958: if ((buffer = vmalloc(sizeof(*attr) + len)) == NULL) {
! 959: plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
! 960: return NULL;
! 961: }
! 962:
! 963: memcpy(buffer->v, attr, sizeof(*attr) + ntohs(attr->lorv));
! 964:
! 965: return buffer;
! 966: }
! 967:
! 968: vchar_t *
! 969: isakmp_cfg_short(iph1, attr, value)
! 970: struct ph1handle *iph1;
! 971: struct isakmp_data *attr;
! 972: int value;
! 973: {
! 974: vchar_t *buffer;
! 975: struct isakmp_data *new;
! 976: int type;
! 977:
! 978: if ((buffer = vmalloc(sizeof(*attr))) == NULL) {
! 979: plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
! 980: return NULL;
! 981: }
! 982:
! 983: new = (struct isakmp_data *)buffer->v;
! 984: type = ntohs(attr->type) & ~ISAKMP_GEN_MASK;
! 985:
! 986: new->type = htons(type | ISAKMP_GEN_TV);
! 987: new->lorv = htons(value);
! 988:
! 989: return buffer;
! 990: }
! 991:
! 992: vchar_t *
! 993: isakmp_cfg_varlen(iph1, attr, string, len)
! 994: struct ph1handle *iph1;
! 995: struct isakmp_data *attr;
! 996: char *string;
! 997: size_t len;
! 998: {
! 999: vchar_t *buffer;
! 1000: struct isakmp_data *new;
! 1001: char *data;
! 1002:
! 1003: if ((buffer = vmalloc(sizeof(*attr) + len)) == NULL) {
! 1004: plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
! 1005: return NULL;
! 1006: }
! 1007:
! 1008: new = (struct isakmp_data *)buffer->v;
! 1009:
! 1010: new->type = attr->type;
! 1011: new->lorv = htons(len);
! 1012: data = (char *)(new + 1);
! 1013:
! 1014: memcpy(data, string, len);
! 1015:
! 1016: return buffer;
! 1017: }
! 1018: vchar_t *
! 1019: isakmp_cfg_string(iph1, attr, string)
! 1020: struct ph1handle *iph1;
! 1021: struct isakmp_data *attr;
! 1022: char *string;
! 1023: {
! 1024: size_t len = strlen(string);
! 1025: return isakmp_cfg_varlen(iph1, attr, string, len);
! 1026: }
! 1027:
! 1028: static vchar_t *
! 1029: isakmp_cfg_addr4(iph1, attr, addr)
! 1030: struct ph1handle *iph1;
! 1031: struct isakmp_data *attr;
! 1032: in_addr_t *addr;
! 1033: {
! 1034: vchar_t *buffer;
! 1035: struct isakmp_data *new;
! 1036: size_t len;
! 1037:
! 1038: len = sizeof(*addr);
! 1039: if ((buffer = vmalloc(sizeof(*attr) + len)) == NULL) {
! 1040: plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
! 1041: return NULL;
! 1042: }
! 1043:
! 1044: new = (struct isakmp_data *)buffer->v;
! 1045:
! 1046: new->type = attr->type;
! 1047: new->lorv = htons(len);
! 1048: memcpy(new + 1, addr, len);
! 1049:
! 1050: return buffer;
! 1051: }
! 1052:
! 1053: static vchar_t *
! 1054: isakmp_cfg_addrnet4(iph1, attr, addr, mask)
! 1055: struct ph1handle *iph1;
! 1056: struct isakmp_data *attr;
! 1057: in_addr_t *addr;
! 1058: in_addr_t *mask;
! 1059: {
! 1060: vchar_t *buffer;
! 1061: struct isakmp_data *new;
! 1062: size_t len;
! 1063: in_addr_t netbuff[2];
! 1064:
! 1065: len = sizeof(netbuff);
! 1066: if ((buffer = vmalloc(sizeof(*attr) + len)) == NULL) {
! 1067: plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
! 1068: return NULL;
! 1069: }
! 1070:
! 1071: new = (struct isakmp_data *)buffer->v;
! 1072:
! 1073: new->type = attr->type;
! 1074: new->lorv = htons(len);
! 1075: netbuff[0]=*addr;
! 1076: netbuff[1]=*mask;
! 1077: memcpy(new + 1, netbuff, len);
! 1078:
! 1079: return buffer;
! 1080: }
! 1081:
! 1082:
! 1083: static vchar_t *
! 1084: isakmp_cfg_addr4_list(iph1, attr, addr, nbr)
! 1085: struct ph1handle *iph1;
! 1086: struct isakmp_data *attr;
! 1087: in_addr_t *addr;
! 1088: int nbr;
! 1089: {
! 1090: int error = -1;
! 1091: vchar_t *buffer = NULL;
! 1092: vchar_t *bufone = NULL;
! 1093: struct isakmp_data *new;
! 1094: size_t len;
! 1095: int i;
! 1096:
! 1097: len = sizeof(*addr);
! 1098: if ((buffer = vmalloc(0)) == NULL) {
! 1099: plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
! 1100: goto out;
! 1101: }
! 1102: for(i = 0; i < nbr; i++) {
! 1103: if ((bufone = vmalloc(sizeof(*attr) + len)) == NULL) {
! 1104: plog(LLV_ERROR, LOCATION, NULL,
! 1105: "Cannot allocate memory\n");
! 1106: goto out;
! 1107: }
! 1108: new = (struct isakmp_data *)bufone->v;
! 1109: new->type = attr->type;
! 1110: new->lorv = htons(len);
! 1111: memcpy(new + 1, &addr[i], len);
! 1112: new += (len + sizeof(*attr));
! 1113: buffer = buffer_cat(buffer, bufone);
! 1114: vfree(bufone);
! 1115: }
! 1116:
! 1117: error = 0;
! 1118:
! 1119: out:
! 1120: if ((error != 0) && (buffer != NULL)) {
! 1121: vfree(buffer);
! 1122: buffer = NULL;
! 1123: }
! 1124:
! 1125: return buffer;
! 1126: }
! 1127:
! 1128: struct isakmp_ivm *
! 1129: isakmp_cfg_newiv(iph1, msgid)
! 1130: struct ph1handle *iph1;
! 1131: u_int32_t msgid;
! 1132: {
! 1133: struct isakmp_cfg_state *ics = iph1->mode_cfg;
! 1134:
! 1135: if (ics == NULL) {
! 1136: plog(LLV_ERROR, LOCATION, NULL,
! 1137: "isakmp_cfg_newiv called without mode config state\n");
! 1138: return NULL;
! 1139: }
! 1140:
! 1141: if (ics->ivm != NULL)
! 1142: oakley_delivm(ics->ivm);
! 1143:
! 1144: ics->ivm = oakley_newiv2(iph1, msgid);
! 1145: ics->last_msgid = msgid;
! 1146:
! 1147: return ics->ivm;
! 1148: }
! 1149:
! 1150: /* Derived from isakmp_info_send_common */
! 1151: int
! 1152: isakmp_cfg_send(iph1, payload, np, flags, new_exchange)
! 1153: struct ph1handle *iph1;
! 1154: vchar_t *payload;
! 1155: u_int32_t np;
! 1156: int flags;
! 1157: int new_exchange;
! 1158: {
! 1159: struct ph2handle *iph2 = NULL;
! 1160: vchar_t *hash = NULL;
! 1161: struct isakmp *isakmp;
! 1162: struct isakmp_gen *gen;
! 1163: char *p;
! 1164: int tlen;
! 1165: int error = -1;
! 1166: struct isakmp_cfg_state *ics = iph1->mode_cfg;
! 1167:
! 1168: /* Check if phase 1 is established */
! 1169: if ((iph1->status < PHASE1ST_ESTABLISHED) ||
! 1170: (iph1->local == NULL) ||
! 1171: (iph1->remote == NULL)) {
! 1172: plog(LLV_ERROR, LOCATION, NULL,
! 1173: "ISAKMP mode config exchange with immature phase 1\n");
! 1174: goto end;
! 1175: }
! 1176:
! 1177: /* add new entry to isakmp status table */
! 1178: iph2 = newph2();
! 1179: if (iph2 == NULL)
! 1180: goto end;
! 1181:
! 1182: iph2->dst = dupsaddr(iph1->remote);
! 1183: if (iph2->dst == NULL) {
! 1184: delph2(iph2);
! 1185: goto end;
! 1186: }
! 1187: iph2->src = dupsaddr(iph1->local);
! 1188: if (iph2->src == NULL) {
! 1189: delph2(iph2);
! 1190: goto end;
! 1191: }
! 1192:
! 1193: iph2->side = INITIATOR;
! 1194: iph2->status = PHASE2ST_START;
! 1195:
! 1196: if (new_exchange)
! 1197: iph2->msgid = isakmp_newmsgid2(iph1);
! 1198: else
! 1199: iph2->msgid = iph1->msgid;
! 1200:
! 1201: /* get IV and HASH(1) if skeyid_a was generated. */
! 1202: if (iph1->skeyid_a != NULL) {
! 1203: if (new_exchange) {
! 1204: if (isakmp_cfg_newiv(iph1, iph2->msgid) == NULL) {
! 1205: delph2(iph2);
! 1206: goto end;
! 1207: }
! 1208: }
! 1209:
! 1210: /* generate HASH(1) */
! 1211: hash = oakley_compute_hash1(iph1, iph2->msgid, payload);
! 1212: if (hash == NULL) {
! 1213: delph2(iph2);
! 1214: goto end;
! 1215: }
! 1216:
! 1217: /* initialized total buffer length */
! 1218: tlen = hash->l;
! 1219: tlen += sizeof(*gen);
! 1220: } else {
! 1221: /* IKE-SA is not established */
! 1222: hash = NULL;
! 1223:
! 1224: /* initialized total buffer length */
! 1225: tlen = 0;
! 1226: }
! 1227: if ((flags & ISAKMP_FLAG_A) == 0)
! 1228: iph2->flags = (hash == NULL ? 0 : ISAKMP_FLAG_E);
! 1229: else
! 1230: iph2->flags = (hash == NULL ? 0 : ISAKMP_FLAG_A);
! 1231:
! 1232: insph2(iph2);
! 1233: bindph12(iph1, iph2);
! 1234:
! 1235: tlen += sizeof(*isakmp) + payload->l;
! 1236:
! 1237: /* create buffer for isakmp payload */
! 1238: iph2->sendbuf = vmalloc(tlen);
! 1239: if (iph2->sendbuf == NULL) {
! 1240: plog(LLV_ERROR, LOCATION, NULL,
! 1241: "failed to get buffer to send.\n");
! 1242: goto err;
! 1243: }
! 1244:
! 1245: /* create isakmp header */
! 1246: isakmp = (struct isakmp *)iph2->sendbuf->v;
! 1247: memcpy(&isakmp->i_ck, &iph1->index.i_ck, sizeof(cookie_t));
! 1248: memcpy(&isakmp->r_ck, &iph1->index.r_ck, sizeof(cookie_t));
! 1249: isakmp->np = hash == NULL ? (np & 0xff) : ISAKMP_NPTYPE_HASH;
! 1250: isakmp->v = iph1->version;
! 1251: isakmp->etype = ISAKMP_ETYPE_CFG;
! 1252: isakmp->flags = iph2->flags;
! 1253: memcpy(&isakmp->msgid, &iph2->msgid, sizeof(isakmp->msgid));
! 1254: isakmp->len = htonl(tlen);
! 1255: p = (char *)(isakmp + 1);
! 1256:
! 1257: /* create HASH payload */
! 1258: if (hash != NULL) {
! 1259: gen = (struct isakmp_gen *)p;
! 1260: gen->np = np & 0xff;
! 1261: gen->len = htons(sizeof(*gen) + hash->l);
! 1262: p += sizeof(*gen);
! 1263: memcpy(p, hash->v, hash->l);
! 1264: p += hash->l;
! 1265: }
! 1266:
! 1267: /* add payload */
! 1268: memcpy(p, payload->v, payload->l);
! 1269: p += payload->l;
! 1270:
! 1271: #ifdef HAVE_PRINT_ISAKMP_C
! 1272: isakmp_printpacket(iph2->sendbuf, iph1->local, iph1->remote, 1);
! 1273: #endif
! 1274:
! 1275: plog(LLV_DEBUG, LOCATION, NULL, "MODE_CFG packet to send\n");
! 1276: plogdump(LLV_DEBUG, iph2->sendbuf->v, iph2->sendbuf->l);
! 1277:
! 1278: /* encoding */
! 1279: if (ISSET(isakmp->flags, ISAKMP_FLAG_E)) {
! 1280: vchar_t *tmp;
! 1281:
! 1282: tmp = oakley_do_encrypt(iph2->ph1, iph2->sendbuf,
! 1283: ics->ivm->ive, ics->ivm->iv);
! 1284: VPTRINIT(iph2->sendbuf);
! 1285: if (tmp == NULL)
! 1286: goto err;
! 1287: iph2->sendbuf = tmp;
! 1288: }
! 1289:
! 1290: /* HDR*, HASH(1), ATTR */
! 1291: if (isakmp_send(iph2->ph1, iph2->sendbuf) < 0) {
! 1292: VPTRINIT(iph2->sendbuf);
! 1293: goto err;
! 1294: }
! 1295:
! 1296: plog(LLV_DEBUG, LOCATION, NULL,
! 1297: "sendto mode config %s.\n", s_isakmp_nptype(np));
! 1298:
! 1299: /*
! 1300: * XXX We might need to resend the message...
! 1301: */
! 1302:
! 1303: error = 0;
! 1304: VPTRINIT(iph2->sendbuf);
! 1305:
! 1306: err:
! 1307: if (iph2->sendbuf != NULL)
! 1308: vfree(iph2->sendbuf);
! 1309:
! 1310: remph2(iph2);
! 1311: delph2(iph2);
! 1312: end:
! 1313: if (hash)
! 1314: vfree(hash);
! 1315: return error;
! 1316: }
! 1317:
! 1318:
! 1319: void
! 1320: isakmp_cfg_rmstate(iph1)
! 1321: struct ph1handle *iph1;
! 1322: {
! 1323: struct isakmp_cfg_state *state = iph1->mode_cfg;
! 1324:
! 1325: if (isakmp_cfg_accounting(iph1, ISAKMP_CFG_LOGOUT) != 0)
! 1326: plog(LLV_ERROR, LOCATION, NULL, "Accounting failed\n");
! 1327:
! 1328: if (state->flags & ISAKMP_CFG_PORT_ALLOCATED)
! 1329: isakmp_cfg_putport(iph1, state->port);
! 1330:
! 1331: /* Delete the IV if it's still there */
! 1332: if(iph1->mode_cfg->ivm) {
! 1333: oakley_delivm(iph1->mode_cfg->ivm);
! 1334: iph1->mode_cfg->ivm = NULL;
! 1335: }
! 1336:
! 1337: /* Free any allocated splitnet lists */
! 1338: if(iph1->mode_cfg->split_include != NULL)
! 1339: splitnet_list_free(iph1->mode_cfg->split_include,
! 1340: &iph1->mode_cfg->include_count);
! 1341: if(iph1->mode_cfg->split_local != NULL)
! 1342: splitnet_list_free(iph1->mode_cfg->split_local,
! 1343: &iph1->mode_cfg->local_count);
! 1344:
! 1345: xauth_rmstate(&state->xauth);
! 1346:
! 1347: racoon_free(state);
! 1348: iph1->mode_cfg = NULL;
! 1349:
! 1350: return;
! 1351: }
! 1352:
! 1353: struct isakmp_cfg_state *
! 1354: isakmp_cfg_mkstate(void)
! 1355: {
! 1356: struct isakmp_cfg_state *state;
! 1357:
! 1358: if ((state = racoon_malloc(sizeof(*state))) == NULL) {
! 1359: plog(LLV_ERROR, LOCATION, NULL,
! 1360: "Cannot allocate memory for mode config state\n");
! 1361: return NULL;
! 1362: }
! 1363: memset(state, 0, sizeof(*state));
! 1364:
! 1365: return state;
! 1366: }
! 1367:
! 1368: int
! 1369: isakmp_cfg_getport(iph1)
! 1370: struct ph1handle *iph1;
! 1371: {
! 1372: unsigned int i;
! 1373: size_t size = isakmp_cfg_config.pool_size;
! 1374:
! 1375: if (iph1->mode_cfg->flags & ISAKMP_CFG_PORT_ALLOCATED)
! 1376: return iph1->mode_cfg->port;
! 1377:
! 1378: if (isakmp_cfg_config.port_pool == NULL) {
! 1379: plog(LLV_ERROR, LOCATION, NULL,
! 1380: "isakmp_cfg_config.port_pool == NULL\n");
! 1381: return -1;
! 1382: }
! 1383:
! 1384: for (i = 0; i < size; i++) {
! 1385: if (isakmp_cfg_config.port_pool[i].used == 0)
! 1386: break;
! 1387: }
! 1388:
! 1389: if (i == size) {
! 1390: plog(LLV_ERROR, LOCATION, NULL,
! 1391: "No more addresses available\n");
! 1392: return -1;
! 1393: }
! 1394:
! 1395: isakmp_cfg_config.port_pool[i].used = 1;
! 1396:
! 1397: plog(LLV_INFO, LOCATION, NULL, "Using port %d\n", i);
! 1398:
! 1399: iph1->mode_cfg->flags |= ISAKMP_CFG_PORT_ALLOCATED;
! 1400: iph1->mode_cfg->port = i;
! 1401:
! 1402: return i;
! 1403: }
! 1404:
! 1405: int
! 1406: isakmp_cfg_putport(iph1, index)
! 1407: struct ph1handle *iph1;
! 1408: unsigned int index;
! 1409: {
! 1410: if (isakmp_cfg_config.port_pool == NULL) {
! 1411: plog(LLV_ERROR, LOCATION, NULL,
! 1412: "isakmp_cfg_config.port_pool == NULL\n");
! 1413: return -1;
! 1414: }
! 1415:
! 1416: if (isakmp_cfg_config.port_pool[index].used == 0) {
! 1417: plog(LLV_ERROR, LOCATION, NULL,
! 1418: "Attempt to release an unallocated address (port %d)\n",
! 1419: index);
! 1420: return -1;
! 1421: }
! 1422:
! 1423: #ifdef HAVE_LIBPAM
! 1424: /* Cleanup PAM status associated with the port */
! 1425: if (isakmp_cfg_config.authsource == ISAKMP_CFG_AUTH_PAM)
! 1426: privsep_cleanup_pam(index);
! 1427: #endif
! 1428: isakmp_cfg_config.port_pool[index].used = 0;
! 1429: iph1->mode_cfg->flags &= ISAKMP_CFG_PORT_ALLOCATED;
! 1430:
! 1431: plog(LLV_INFO, LOCATION, NULL, "Released port %d\n", index);
! 1432:
! 1433: return 0;
! 1434: }
! 1435:
! 1436: #ifdef HAVE_LIBPAM
! 1437: void
! 1438: cleanup_pam(port)
! 1439: int port;
! 1440: {
! 1441: if (isakmp_cfg_config.port_pool[port].pam != NULL) {
! 1442: pam_end(isakmp_cfg_config.port_pool[port].pam, PAM_SUCCESS);
! 1443: isakmp_cfg_config.port_pool[port].pam = NULL;
! 1444: }
! 1445:
! 1446: return;
! 1447: }
! 1448: #endif
! 1449:
! 1450: /* Accounting, only for RADIUS or PAM */
! 1451: static int
! 1452: isakmp_cfg_accounting(iph1, inout)
! 1453: struct ph1handle *iph1;
! 1454: int inout;
! 1455: {
! 1456: #ifdef HAVE_LIBPAM
! 1457: if (isakmp_cfg_config.accounting == ISAKMP_CFG_ACCT_PAM)
! 1458: return privsep_accounting_pam(iph1->mode_cfg->port,
! 1459: inout);
! 1460: #endif
! 1461: #ifdef HAVE_LIBRADIUS
! 1462: if (isakmp_cfg_config.accounting == ISAKMP_CFG_ACCT_RADIUS)
! 1463: return isakmp_cfg_accounting_radius(iph1, inout);
! 1464: #endif
! 1465: if (isakmp_cfg_config.accounting == ISAKMP_CFG_ACCT_SYSTEM)
! 1466: return privsep_accounting_system(iph1->mode_cfg->port,
! 1467: iph1->remote, iph1->mode_cfg->login, inout);
! 1468: return 0;
! 1469: }
! 1470:
! 1471: #ifdef HAVE_LIBPAM
! 1472: int
! 1473: isakmp_cfg_accounting_pam(port, inout)
! 1474: int port;
! 1475: int inout;
! 1476: {
! 1477: int error = 0;
! 1478: pam_handle_t *pam;
! 1479:
! 1480: if (isakmp_cfg_config.port_pool == NULL) {
! 1481: plog(LLV_ERROR, LOCATION, NULL,
! 1482: "isakmp_cfg_config.port_pool == NULL\n");
! 1483: return -1;
! 1484: }
! 1485:
! 1486: pam = isakmp_cfg_config.port_pool[port].pam;
! 1487: if (pam == NULL) {
! 1488: plog(LLV_ERROR, LOCATION, NULL, "pam handle is NULL\n");
! 1489: return -1;
! 1490: }
! 1491:
! 1492: switch (inout) {
! 1493: case ISAKMP_CFG_LOGIN:
! 1494: error = pam_open_session(pam, 0);
! 1495: break;
! 1496: case ISAKMP_CFG_LOGOUT:
! 1497: error = pam_close_session(pam, 0);
! 1498: pam_end(pam, error);
! 1499: isakmp_cfg_config.port_pool[port].pam = NULL;
! 1500: break;
! 1501: default:
! 1502: plog(LLV_ERROR, LOCATION, NULL, "Unepected inout\n");
! 1503: break;
! 1504: }
! 1505:
! 1506: if (error != 0) {
! 1507: plog(LLV_ERROR, LOCATION, NULL,
! 1508: "pam_open_session/pam_close_session failed: %s\n",
! 1509: pam_strerror(pam, error));
! 1510: return -1;
! 1511: }
! 1512:
! 1513: return 0;
! 1514: }
! 1515: #endif /* HAVE_LIBPAM */
! 1516:
! 1517: #ifdef HAVE_LIBRADIUS
! 1518: static int
! 1519: isakmp_cfg_accounting_radius(iph1, inout)
! 1520: struct ph1handle *iph1;
! 1521: int inout;
! 1522: {
! 1523: if (rad_create_request(radius_acct_state,
! 1524: RAD_ACCOUNTING_REQUEST) != 0) {
! 1525: plog(LLV_ERROR, LOCATION, NULL,
! 1526: "rad_create_request failed: %s\n",
! 1527: rad_strerror(radius_acct_state));
! 1528: return -1;
! 1529: }
! 1530:
! 1531: if (rad_put_string(radius_acct_state, RAD_USER_NAME,
! 1532: iph1->mode_cfg->login) != 0) {
! 1533: plog(LLV_ERROR, LOCATION, NULL,
! 1534: "rad_put_string failed: %s\n",
! 1535: rad_strerror(radius_acct_state));
! 1536: return -1;
! 1537: }
! 1538:
! 1539: switch (inout) {
! 1540: case ISAKMP_CFG_LOGIN:
! 1541: inout = RAD_START;
! 1542: break;
! 1543: case ISAKMP_CFG_LOGOUT:
! 1544: inout = RAD_STOP;
! 1545: break;
! 1546: default:
! 1547: plog(LLV_ERROR, LOCATION, NULL, "Unepected inout\n");
! 1548: break;
! 1549: }
! 1550:
! 1551: if (rad_put_addr(radius_acct_state,
! 1552: RAD_FRAMED_IP_ADDRESS, iph1->mode_cfg->addr4) != 0) {
! 1553: plog(LLV_ERROR, LOCATION, NULL,
! 1554: "rad_put_addr failed: %s\n",
! 1555: rad_strerror(radius_acct_state));
! 1556: return -1;
! 1557: }
! 1558:
! 1559: if (rad_put_addr(radius_acct_state,
! 1560: RAD_LOGIN_IP_HOST, iph1->mode_cfg->addr4) != 0) {
! 1561: plog(LLV_ERROR, LOCATION, NULL,
! 1562: "rad_put_addr failed: %s\n",
! 1563: rad_strerror(radius_acct_state));
! 1564: return -1;
! 1565: }
! 1566:
! 1567: if (rad_put_int(radius_acct_state, RAD_ACCT_STATUS_TYPE, inout) != 0) {
! 1568: plog(LLV_ERROR, LOCATION, NULL,
! 1569: "rad_put_int failed: %s\n",
! 1570: rad_strerror(radius_acct_state));
! 1571: return -1;
! 1572: }
! 1573:
! 1574: if (isakmp_cfg_radius_common(radius_acct_state,
! 1575: iph1->mode_cfg->port) != 0)
! 1576: return -1;
! 1577:
! 1578: if (rad_send_request(radius_acct_state) != RAD_ACCOUNTING_RESPONSE) {
! 1579: plog(LLV_ERROR, LOCATION, NULL,
! 1580: "rad_send_request failed: %s\n",
! 1581: rad_strerror(radius_acct_state));
! 1582: return -1;
! 1583: }
! 1584:
! 1585: return 0;
! 1586: }
! 1587: #endif /* HAVE_LIBRADIUS */
! 1588:
! 1589: /*
! 1590: * Attributes common to all RADIUS requests
! 1591: */
! 1592: #ifdef HAVE_LIBRADIUS
! 1593: int
! 1594: isakmp_cfg_radius_common(radius_state, port)
! 1595: struct rad_handle *radius_state;
! 1596: int port;
! 1597: {
! 1598: struct utsname name;
! 1599: static struct hostent *host = NULL;
! 1600: struct in_addr nas_addr;
! 1601:
! 1602: /*
! 1603: * Find our own IP by resolving our nodename
! 1604: */
! 1605: if (host == NULL) {
! 1606: if (uname(&name) != 0) {
! 1607: plog(LLV_ERROR, LOCATION, NULL,
! 1608: "uname failed: %s\n", strerror(errno));
! 1609: return -1;
! 1610: }
! 1611:
! 1612: if ((host = gethostbyname(name.nodename)) == NULL) {
! 1613: plog(LLV_ERROR, LOCATION, NULL,
! 1614: "gethostbyname failed: %s\n", strerror(errno));
! 1615: return -1;
! 1616: }
! 1617: }
! 1618:
! 1619: memcpy(&nas_addr, host->h_addr, sizeof(nas_addr));
! 1620: if (rad_put_addr(radius_state, RAD_NAS_IP_ADDRESS, nas_addr) != 0) {
! 1621: plog(LLV_ERROR, LOCATION, NULL,
! 1622: "rad_put_addr failed: %s\n",
! 1623: rad_strerror(radius_state));
! 1624: return -1;
! 1625: }
! 1626:
! 1627: if (rad_put_int(radius_state, RAD_NAS_PORT, port) != 0) {
! 1628: plog(LLV_ERROR, LOCATION, NULL,
! 1629: "rad_put_int failed: %s\n",
! 1630: rad_strerror(radius_state));
! 1631: return -1;
! 1632: }
! 1633:
! 1634: if (rad_put_int(radius_state, RAD_NAS_PORT_TYPE, RAD_VIRTUAL) != 0) {
! 1635: plog(LLV_ERROR, LOCATION, NULL,
! 1636: "rad_put_int failed: %s\n",
! 1637: rad_strerror(radius_state));
! 1638: return -1;
! 1639: }
! 1640:
! 1641: if (rad_put_int(radius_state, RAD_SERVICE_TYPE, RAD_FRAMED) != 0) {
! 1642: plog(LLV_ERROR, LOCATION, NULL,
! 1643: "rad_put_int failed: %s\n",
! 1644: rad_strerror(radius_state));
! 1645: return -1;
! 1646: }
! 1647:
! 1648: return 0;
! 1649: }
! 1650: #endif
! 1651:
! 1652: /*
! 1653: Logs the user into the utmp system files.
! 1654: */
! 1655:
! 1656: int
! 1657: isakmp_cfg_accounting_system(port, raddr, usr, inout)
! 1658: int port;
! 1659: struct sockaddr *raddr;
! 1660: char *usr;
! 1661: int inout;
! 1662: {
! 1663: int error = 0;
! 1664: struct utmpx ut;
! 1665: char addr[NI_MAXHOST];
! 1666:
! 1667: if (usr == NULL || usr[0]=='\0') {
! 1668: plog(LLV_ERROR, LOCATION, NULL,
! 1669: "system accounting : no login found\n");
! 1670: return -1;
! 1671: }
! 1672:
! 1673: memset(&ut, 0, sizeof ut);
! 1674: gettimeofday((struct timeval *)&ut.ut_tv, NULL);
! 1675: snprintf(ut.ut_id, sizeof ut.ut_id, TERMSPEC, port);
! 1676:
! 1677: switch (inout) {
! 1678: case ISAKMP_CFG_LOGIN:
! 1679: ut.ut_type = USER_PROCESS;
! 1680: strncpy(ut.ut_user, usr, sizeof ut.ut_user);
! 1681:
! 1682: GETNAMEINFO_NULL(raddr, addr);
! 1683: strncpy(ut.ut_host, addr, sizeof ut.ut_host);
! 1684:
! 1685: plog(LLV_INFO, LOCATION, NULL,
! 1686: "Accounting : '%s' logging on '%s' from %s.\n",
! 1687: ut.ut_user, ut.ut_id, addr);
! 1688:
! 1689: pututxline(&ut);
! 1690:
! 1691: break;
! 1692: case ISAKMP_CFG_LOGOUT:
! 1693: ut.ut_type = DEAD_PROCESS;
! 1694:
! 1695: plog(LLV_INFO, LOCATION, NULL,
! 1696: "Accounting : '%s' unlogging from '%s'.\n",
! 1697: usr, ut.ut_id);
! 1698:
! 1699: pututxline(&ut);
! 1700:
! 1701: break;
! 1702: default:
! 1703: plog(LLV_ERROR, LOCATION, NULL, "Unepected inout\n");
! 1704: break;
! 1705: }
! 1706:
! 1707: return 0;
! 1708: }
! 1709:
! 1710: int
! 1711: isakmp_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:
! 1766: static void
! 1767: isakmp_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:
! 1785: static void
! 1786: isakmp_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:
! 1811: static void
! 1812: isakmp_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:
! 1827: void
! 1828: isakmp_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:
! 1865: int
! 1866: isakmp_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:
! 2070: int
! 2071: isakmp_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:
! 2127: int
! 2128: isakmp_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:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>