Return to isakmp_cfg.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / ipsec-tools / src / racoon |
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: