Return to isakmp_unity.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / ipsec-tools / src / racoon |
1.1 ! misho 1: /* $NetBSD: isakmp_unity.c,v 1.9 2007/10/19 03:37:19 manu Exp $ */ ! 2: ! 3: /* Id: isakmp_unity.c,v 1.10 2006/07/31 04:49:23 manubsd Exp */ ! 4: ! 5: /* ! 6: * Copyright (C) 2004 Emmanuel Dreyfus ! 7: * All rights reserved. ! 8: * ! 9: * Redistribution and use in source and binary forms, with or without ! 10: * modification, are permitted provided that the following conditions ! 11: * are met: ! 12: * 1. Redistributions of source code must retain the above copyright ! 13: * notice, this list of conditions and the following disclaimer. ! 14: * 2. Redistributions in binary form must reproduce the above copyright ! 15: * notice, this list of conditions and the following disclaimer in the ! 16: * documentation and/or other materials provided with the distribution. ! 17: * 3. Neither the name of the project nor the names of its contributors ! 18: * may be used to endorse or promote products derived from this software ! 19: * without specific prior written permission. ! 20: * ! 21: * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND ! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE ! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 31: * SUCH DAMAGE. ! 32: */ ! 33: ! 34: #include "config.h" ! 35: ! 36: #include <sys/types.h> ! 37: #include <sys/param.h> ! 38: #include <sys/socket.h> ! 39: #include <sys/queue.h> ! 40: ! 41: #include <netinet/in.h> ! 42: #include <arpa/inet.h> ! 43: ! 44: #include <stdlib.h> ! 45: #include <stdio.h> ! 46: #include <fcntl.h> ! 47: #include <string.h> ! 48: #include <errno.h> ! 49: #if TIME_WITH_SYS_TIME ! 50: # include <sys/time.h> ! 51: # include <time.h> ! 52: #else ! 53: # if HAVE_SYS_TIME_H ! 54: # include <sys/time.h> ! 55: # else ! 56: # include <time.h> ! 57: # endif ! 58: #endif ! 59: #include <netdb.h> ! 60: #ifdef HAVE_UNISTD_H ! 61: #include <unistd.h> ! 62: #endif ! 63: #include <ctype.h> ! 64: #include <resolv.h> ! 65: ! 66: #include "var.h" ! 67: #include "misc.h" ! 68: #include "vmbuf.h" ! 69: #include "plog.h" ! 70: #include "sockmisc.h" ! 71: #include "schedule.h" ! 72: #include "debug.h" ! 73: ! 74: #include "isakmp_var.h" ! 75: #include "isakmp.h" ! 76: #include "handler.h" ! 77: #include "isakmp_xauth.h" ! 78: #include "isakmp_unity.h" ! 79: #include "isakmp_cfg.h" ! 80: #include "strnames.h" ! 81: ! 82: static vchar_t *isakmp_cfg_split(struct ph1handle *, ! 83: struct isakmp_data *, struct unity_netentry*,int); ! 84: ! 85: vchar_t * ! 86: isakmp_unity_req(iph1, attr) ! 87: struct ph1handle *iph1; ! 88: struct isakmp_data *attr; ! 89: { ! 90: int type; ! 91: vchar_t *reply_attr = NULL; ! 92: ! 93: if ((iph1->mode_cfg->flags & ISAKMP_CFG_VENDORID_UNITY) == 0) { ! 94: plog(LLV_ERROR, LOCATION, NULL, ! 95: "Unity mode config request but the peer " ! 96: "did not declare itself as unity compliant\n"); ! 97: return NULL; ! 98: } ! 99: ! 100: type = ntohs(attr->type); ! 101: ! 102: /* Handle short attributes */ ! 103: if ((type & ISAKMP_GEN_MASK) == ISAKMP_GEN_TV) { ! 104: type &= ~ISAKMP_GEN_MASK; ! 105: ! 106: plog(LLV_DEBUG, LOCATION, NULL, ! 107: "Short attribute %s = %d\n", ! 108: s_isakmp_cfg_type(type), ntohs(attr->lorv)); ! 109: ! 110: switch (type) { ! 111: default: ! 112: plog(LLV_DEBUG, LOCATION, NULL, ! 113: "Ignored short attribute %s\n", ! 114: s_isakmp_cfg_type(type)); ! 115: break; ! 116: } ! 117: ! 118: return reply_attr; ! 119: } ! 120: ! 121: switch(type) { ! 122: case UNITY_BANNER: { ! 123: #define MAXMOTD 65536 ! 124: char buf[MAXMOTD + 1]; ! 125: int fd; ! 126: char *filename = &isakmp_cfg_config.motd[0]; ! 127: int len; ! 128: ! 129: if ((fd = open(filename, O_RDONLY, 0)) == -1) { ! 130: plog(LLV_ERROR, LOCATION, NULL, ! 131: "Cannot open \"%s\"\n", filename); ! 132: return NULL; ! 133: } ! 134: ! 135: if ((len = read(fd, buf, MAXMOTD)) == -1) { ! 136: plog(LLV_ERROR, LOCATION, NULL, ! 137: "Cannot read \"%s\"\n", filename); ! 138: close(fd); ! 139: return NULL; ! 140: } ! 141: close(fd); ! 142: ! 143: buf[len] = '\0'; ! 144: reply_attr = isakmp_cfg_string(iph1, attr, buf); ! 145: ! 146: break; ! 147: } ! 148: ! 149: case UNITY_PFS: ! 150: reply_attr = isakmp_cfg_short(iph1, attr, ! 151: isakmp_cfg_config.pfs_group); ! 152: break; ! 153: ! 154: case UNITY_SAVE_PASSWD: ! 155: reply_attr = isakmp_cfg_short(iph1, attr, ! 156: isakmp_cfg_config.save_passwd); ! 157: break; ! 158: ! 159: case UNITY_DDNS_HOSTNAME: ! 160: reply_attr = isakmp_cfg_copy(iph1, attr); ! 161: break; ! 162: ! 163: case UNITY_DEF_DOMAIN: ! 164: reply_attr = isakmp_cfg_string(iph1, ! 165: attr, isakmp_cfg_config.default_domain); ! 166: break; ! 167: ! 168: case UNITY_SPLIT_INCLUDE: ! 169: if(isakmp_cfg_config.splitnet_type == UNITY_SPLIT_INCLUDE) ! 170: reply_attr = isakmp_cfg_split(iph1, attr, ! 171: isakmp_cfg_config.splitnet_list, ! 172: isakmp_cfg_config.splitnet_count); ! 173: else ! 174: return NULL; ! 175: break; ! 176: case UNITY_LOCAL_LAN: ! 177: if(isakmp_cfg_config.splitnet_type == UNITY_LOCAL_LAN) ! 178: reply_attr = isakmp_cfg_split(iph1, attr, ! 179: isakmp_cfg_config.splitnet_list, ! 180: isakmp_cfg_config.splitnet_count); ! 181: else ! 182: return NULL; ! 183: break; ! 184: case UNITY_SPLITDNS_NAME: ! 185: reply_attr = isakmp_cfg_varlen(iph1, attr, ! 186: isakmp_cfg_config.splitdns_list, ! 187: isakmp_cfg_config.splitdns_len); ! 188: break; ! 189: case UNITY_FW_TYPE: ! 190: case UNITY_NATT_PORT: ! 191: case UNITY_BACKUP_SERVERS: ! 192: default: ! 193: plog(LLV_DEBUG, LOCATION, NULL, ! 194: "Ignored attribute %s\n", s_isakmp_cfg_type(type)); ! 195: return NULL; ! 196: break; ! 197: } ! 198: ! 199: return reply_attr; ! 200: } ! 201: ! 202: void ! 203: isakmp_unity_reply(iph1, attr) ! 204: struct ph1handle *iph1; ! 205: struct isakmp_data *attr; ! 206: { ! 207: int type = ntohs(attr->type); ! 208: int alen = ntohs(attr->lorv); ! 209: ! 210: struct unity_network *network = (struct unity_network *)(attr + 1); ! 211: int index = 0; ! 212: int count = 0; ! 213: ! 214: switch(type) { ! 215: case UNITY_SPLIT_INCLUDE: ! 216: { ! 217: if (alen) ! 218: count = alen / sizeof(struct unity_network); ! 219: ! 220: for(;index < count; index++) ! 221: splitnet_list_add( ! 222: &iph1->mode_cfg->split_include, ! 223: &network[index], ! 224: &iph1->mode_cfg->include_count); ! 225: ! 226: iph1->mode_cfg->flags |= ISAKMP_CFG_GOT_SPLIT_INCLUDE; ! 227: break; ! 228: } ! 229: case UNITY_LOCAL_LAN: ! 230: { ! 231: if (alen) ! 232: count = alen / sizeof(struct unity_network); ! 233: ! 234: for(;index < count; index++) ! 235: splitnet_list_add( ! 236: &iph1->mode_cfg->split_local, ! 237: &network[index], ! 238: &iph1->mode_cfg->local_count); ! 239: ! 240: iph1->mode_cfg->flags |= ISAKMP_CFG_GOT_SPLIT_LOCAL; ! 241: break; ! 242: } ! 243: case UNITY_SPLITDNS_NAME: ! 244: case UNITY_BANNER: ! 245: case UNITY_SAVE_PASSWD: ! 246: case UNITY_NATT_PORT: ! 247: case UNITY_PFS: ! 248: case UNITY_FW_TYPE: ! 249: case UNITY_BACKUP_SERVERS: ! 250: case UNITY_DDNS_HOSTNAME: ! 251: default: ! 252: plog(LLV_WARNING, LOCATION, NULL, ! 253: "Ignored attribute %s\n", ! 254: s_isakmp_cfg_type(type)); ! 255: break; ! 256: } ! 257: return; ! 258: } ! 259: ! 260: static vchar_t * ! 261: isakmp_cfg_split(iph1, attr, netentry, count) ! 262: struct ph1handle *iph1; ! 263: struct isakmp_data *attr; ! 264: struct unity_netentry *netentry; ! 265: int count; ! 266: { ! 267: vchar_t *buffer; ! 268: struct isakmp_data *new; ! 269: struct unity_network * network; ! 270: size_t len; ! 271: int index = 0; ! 272: ! 273: char tmp1[40]; ! 274: char tmp2[40]; ! 275: ! 276: len = sizeof(struct unity_network) * count; ! 277: if ((buffer = vmalloc(sizeof(*attr) + len)) == NULL) { ! 278: plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n"); ! 279: return NULL; ! 280: } ! 281: ! 282: new = (struct isakmp_data *)buffer->v; ! 283: new->type = attr->type; ! 284: new->lorv = htons(len); ! 285: ! 286: network = (struct unity_network *)(new + 1); ! 287: for (; index < count; index++) { ! 288: ! 289: memcpy(&network[index], ! 290: &netentry->network, ! 291: sizeof(struct unity_network)); ! 292: ! 293: inet_ntop(AF_INET, &netentry->network.addr4, tmp1, 40); ! 294: inet_ntop(AF_INET, &netentry->network.mask4, tmp2, 40); ! 295: plog(LLV_DEBUG, LOCATION, NULL, "splitnet: %s/%s\n", tmp1, tmp2); ! 296: ! 297: netentry = netentry->next; ! 298: } ! 299: ! 300: return buffer; ! 301: } ! 302: ! 303: int splitnet_list_add(list, network, count) ! 304: struct unity_netentry ** list; ! 305: struct unity_network * network; ! 306: int *count; ! 307: { ! 308: struct unity_netentry * nentry; ! 309: ! 310: /* ! 311: * search for network in current list ! 312: * to avoid adding duplicates ! 313: */ ! 314: for (nentry = *list; nentry != NULL; nentry = nentry->next) ! 315: if (memcmp(&nentry->network, network, ! 316: sizeof(struct unity_network)) == 0) ! 317: return 0; /* it's a dupe */ ! 318: ! 319: /* ! 320: * allocate new netentry and copy ! 321: * new splitnet network data ! 322: */ ! 323: nentry = (struct unity_netentry *) ! 324: racoon_malloc(sizeof(struct unity_netentry)); ! 325: if (nentry == NULL) ! 326: return -1; ! 327: ! 328: memcpy(&nentry->network,network, ! 329: sizeof(struct unity_network)); ! 330: nentry->next = NULL; ! 331: ! 332: /* ! 333: * locate the last netentry in our ! 334: * splitnet list and add our entry ! 335: */ ! 336: if (*list == NULL) ! 337: *list = nentry; ! 338: else { ! 339: struct unity_netentry * tmpentry = *list; ! 340: while (tmpentry->next != NULL) ! 341: tmpentry = tmpentry->next; ! 342: tmpentry->next = nentry; ! 343: } ! 344: ! 345: (*count)++; ! 346: ! 347: return 0; ! 348: } ! 349: ! 350: void splitnet_list_free(list, count) ! 351: struct unity_netentry * list; ! 352: int *count; ! 353: { ! 354: struct unity_netentry * netentry = list; ! 355: struct unity_netentry * delentry; ! 356: ! 357: *count = 0; ! 358: ! 359: while (netentry != NULL) { ! 360: delentry = netentry; ! 361: netentry = netentry->next; ! 362: racoon_free(delentry); ! 363: } ! 364: } ! 365: ! 366: char * splitnet_list_2str(list, splitnet_ipaddr) ! 367: struct unity_netentry * list; ! 368: enum splinet_ipaddr splitnet_ipaddr; ! 369: { ! 370: struct unity_netentry * netentry; ! 371: char tmp1[40]; ! 372: char tmp2[40]; ! 373: char * str; ! 374: int len; ! 375: ! 376: /* determine string length */ ! 377: len = 0; ! 378: netentry = list; ! 379: while (netentry != NULL) { ! 380: ! 381: inet_ntop(AF_INET, &netentry->network.addr4, tmp1, 40); ! 382: inet_ntop(AF_INET, &netentry->network.mask4, tmp2, 40); ! 383: len += strlen(tmp1); ! 384: len += strlen(tmp2); ! 385: len += 2; ! 386: ! 387: netentry = netentry->next; ! 388: } ! 389: ! 390: /* allocate network list string */ ! 391: str = racoon_malloc(len); ! 392: if (str == NULL) ! 393: return NULL; ! 394: ! 395: /* create network list string */ ! 396: len = 0; ! 397: netentry = list; ! 398: while (netentry != NULL) { ! 399: ! 400: inet_ntop(AF_INET, &netentry->network.addr4, tmp1, 40); ! 401: inet_ntop(AF_INET, &netentry->network.mask4, tmp2, 40); ! 402: if (splitnet_ipaddr == CIDR) { ! 403: uint32_t tmp3; ! 404: int cidrmask; ! 405: ! 406: tmp3 = ntohl(netentry->network.mask4.s_addr); ! 407: for (cidrmask = 0; tmp3 != 0; cidrmask++) ! 408: tmp3 <<= 1; ! 409: len += sprintf(str+len, "%s/%d ", tmp1, cidrmask); ! 410: } else { ! 411: len += sprintf(str+len, "%s/%s ", tmp1, tmp2); ! 412: } ! 413: ! 414: netentry = netentry->next; ! 415: } ! 416: ! 417: str[len-1]=0; ! 418: ! 419: return str; ! 420: }