Annotation of embedaddon/ipsec-tools/src/racoon/isakmp_unity.c, revision 1.1

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: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>