Annotation of embedaddon/ipsec-tools/src/racoon/isakmp_unity.c, revision 1.1.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>