Annotation of embedaddon/ipsec-tools/src/racoon/isakmp_frag.c, revision 1.1.1.1

1.1       misho       1: /*     $NetBSD: isakmp_frag.c,v 1.5 2009/04/22 11:24:20 tteras Exp $   */
                      2: 
                      3: /* Id: isakmp_frag.c,v 1.4 2004/11/13 17:31:36 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 <openssl/md5.h> 
                     45: 
                     46: #include <stdlib.h>
                     47: #include <stdio.h>
                     48: #include <fcntl.h>
                     49: #include <string.h>
                     50: #include <errno.h>
                     51: #if TIME_WITH_SYS_TIME
                     52: # include <sys/time.h>
                     53: # include <time.h>
                     54: #else
                     55: # if HAVE_SYS_TIME_H
                     56: #  include <sys/time.h>
                     57: # else
                     58: #  include <time.h>
                     59: # endif
                     60: #endif
                     61: #include <netdb.h>
                     62: #ifdef HAVE_UNISTD_H
                     63: #include <unistd.h>
                     64: #endif
                     65: #include <ctype.h>
                     66: 
                     67: #include "var.h"
                     68: #include "misc.h"
                     69: #include "vmbuf.h"
                     70: #include "plog.h"
                     71: #include "sockmisc.h"
                     72: #include "schedule.h"
                     73: #include "debug.h"
                     74: 
                     75: #include "isakmp_var.h"
                     76: #include "isakmp.h"
                     77: #include "handler.h"
                     78: #include "isakmp_frag.h"
                     79: #include "strnames.h"
                     80: 
                     81: int
                     82: isakmp_sendfrags(iph1, buf) 
                     83:        struct ph1handle *iph1;
                     84:        vchar_t *buf;
                     85: {
                     86:        struct isakmp *hdr;
                     87:        struct isakmp_frag *fraghdr;
                     88:        caddr_t data;
                     89:        caddr_t sdata;
                     90:        size_t datalen;
                     91:        size_t max_datalen;
                     92:        size_t fraglen;
                     93:        vchar_t *frag;
                     94:        unsigned int trailer;
                     95:        unsigned int fragnum = 0;
                     96:        size_t len;
                     97:        int etype;
                     98: 
                     99:        /*
                    100:         * Catch the exchange type for later: the fragments and the
                    101:         * fragmented packet must have the same exchange type.
                    102:         */
                    103:        hdr = (struct isakmp *)buf->v;
                    104:        etype = hdr->etype;
                    105: 
                    106:        /*
                    107:         * We want to send a a packet smaller than ISAKMP_FRAG_MAXLEN
                    108:         * First compute the maximum data length that will fit in it
                    109:         */
                    110:        max_datalen = ISAKMP_FRAG_MAXLEN - 
                    111:            (sizeof(*hdr) + sizeof(*fraghdr) + sizeof(trailer));
                    112: 
                    113:        sdata = buf->v;
                    114:        len = buf->l;
                    115: 
                    116:        while (len > 0) {
                    117:                fragnum++;
                    118: 
                    119:                if (len > max_datalen)
                    120:                        datalen = max_datalen;
                    121:                else
                    122:                        datalen = len;
                    123: 
                    124:                fraglen = sizeof(*hdr) 
                    125:                        + sizeof(*fraghdr) 
                    126:                        + datalen;
                    127: 
                    128:                if ((frag = vmalloc(fraglen)) == NULL) {
                    129:                        plog(LLV_ERROR, LOCATION, NULL, 
                    130:                            "Cannot allocate memory\n");
                    131:                        return -1;
                    132:                }
                    133: 
                    134:                set_isakmp_header1(frag, iph1, ISAKMP_NPTYPE_FRAG);
                    135:                hdr = (struct isakmp *)frag->v;
                    136:                hdr->etype = etype;
                    137: 
                    138:                fraghdr = (struct isakmp_frag *)(hdr + 1);
                    139:                fraghdr->unknown0 = htons(0);
                    140:                fraghdr->len = htons(fraglen - sizeof(*hdr));
                    141:                fraghdr->unknown1 = htons(1);
                    142:                fraghdr->index = fragnum;
                    143:                if (len == datalen)
                    144:                        fraghdr->flags = ISAKMP_FRAG_LAST;
                    145:                else
                    146:                        fraghdr->flags = 0;
                    147: 
                    148:                data = (caddr_t)(fraghdr + 1);
                    149:                memcpy(data, sdata, datalen);
                    150: 
                    151:                if (isakmp_send(iph1, frag) < 0) {
                    152:                        plog(LLV_ERROR, LOCATION, NULL, "isakmp_send failed\n");
                    153:                        return -1;
                    154:                }
                    155: 
                    156:                vfree(frag);
                    157: 
                    158:                len -= datalen;
                    159:                sdata += datalen;
                    160:        }
                    161:                
                    162:        return fragnum;
                    163: }
                    164: 
                    165: unsigned int 
                    166: vendorid_frag_cap(gen)
                    167:        struct isakmp_gen *gen;
                    168: {
                    169:        int *hp;
                    170: 
                    171:        hp = (int *)(gen + 1);
                    172: 
                    173:        return ntohl(hp[MD5_DIGEST_LENGTH / sizeof(*hp)]);
                    174: }
                    175: 
                    176: int 
                    177: isakmp_frag_extract(iph1, msg)
                    178:        struct ph1handle *iph1;
                    179:        vchar_t *msg;
                    180: {
                    181:        struct isakmp *isakmp;
                    182:        struct isakmp_frag *frag;
                    183:        struct isakmp_frag_item *item;
                    184:        vchar_t *buf;
                    185:        size_t len;
                    186:        int last_frag = 0;
                    187:        char *data;
                    188:        int i;
                    189: 
                    190:        if (msg->l < sizeof(*isakmp) + sizeof(*frag)) {
                    191:                plog(LLV_ERROR, LOCATION, NULL, "Message too short\n");
                    192:                return -1;
                    193:        }
                    194: 
                    195:        isakmp = (struct isakmp *)msg->v;
                    196:        frag = (struct isakmp_frag *)(isakmp + 1);
                    197: 
                    198:        /* 
                    199:         * frag->len is the frag payload data plus the frag payload header,
                    200:         * whose size is sizeof(*frag) 
                    201:         */
                    202:        if (msg->l < sizeof(*isakmp) + ntohs(frag->len) ||
                    203:            ntohs(frag->len) < sizeof(*frag) + 1) {
                    204:                plog(LLV_ERROR, LOCATION, NULL, "Fragment too short\n");
                    205:                return -1;
                    206:        }
                    207: 
                    208:        if ((buf = vmalloc(ntohs(frag->len) - sizeof(*frag))) == NULL) {
                    209:                plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
                    210:                return -1;
                    211:        }
                    212: 
                    213:        if ((item = racoon_malloc(sizeof(*item))) == NULL) {
                    214:                plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
                    215:                vfree(buf);
                    216:                return -1;
                    217:        }
                    218: 
                    219:        data = (char *)(frag + 1);
                    220:        memcpy(buf->v, data, buf->l);
                    221: 
                    222:        item->frag_num = frag->index;
                    223:        item->frag_last = (frag->flags & ISAKMP_FRAG_LAST);
                    224:        item->frag_next = NULL;
                    225:        item->frag_packet = buf;
                    226: 
                    227:        /* Look for the last frag while inserting the new item in the chain */
                    228:        if (item->frag_last)
                    229:                last_frag = item->frag_num;
                    230: 
                    231:        if (iph1->frag_chain == NULL) {
                    232:                iph1->frag_chain = item;
                    233:        } else {
                    234:                struct isakmp_frag_item *current;
                    235: 
                    236:                current = iph1->frag_chain;
                    237:                while (current->frag_next) {
                    238:                        if (current->frag_last)
                    239:                                last_frag = item->frag_num;
                    240:                        current = current->frag_next;
                    241:                }
                    242:                current->frag_next = item;
                    243:        }
                    244: 
                    245:        /* If we saw the last frag, check if the chain is complete */
                    246:        if (last_frag != 0) {
                    247:                for (i = 1; i <= last_frag; i++) {
                    248:                        item = iph1->frag_chain;
                    249:                        do {
                    250:                                if (item->frag_num == i)
                    251:                                        break;
                    252:                                item = item->frag_next;
                    253:                        } while (item != NULL);
                    254: 
                    255:                        if (item == NULL) /* Not found */
                    256:                                break;
                    257:                }
                    258: 
                    259:                if (item != NULL) /* It is complete */
                    260:                        return 1;
                    261:        }
                    262:                
                    263:        return 0;
                    264: }
                    265: 
                    266: vchar_t *
                    267: isakmp_frag_reassembly(iph1)
                    268:        struct ph1handle *iph1;
                    269: {
                    270:        struct isakmp_frag_item *item;
                    271:        size_t len = 0;
                    272:        vchar_t *buf = NULL;
                    273:        int frag_count = 0;
                    274:        int i;
                    275:        char *data;
                    276: 
                    277:        if ((item = iph1->frag_chain) == NULL) {
                    278:                plog(LLV_ERROR, LOCATION, NULL, "No fragment to reassemble\n");
                    279:                goto out;
                    280:        }
                    281: 
                    282:        do {
                    283:                frag_count++;
                    284:                len += item->frag_packet->l;
                    285:                item = item->frag_next;
                    286:        } while (item != NULL);
                    287:        
                    288:        if ((buf = vmalloc(len)) == NULL) {
                    289:                plog(LLV_ERROR, LOCATION, NULL, "Cannot allocate memory\n");
                    290:                goto out;
                    291:        }
                    292:        data = buf->v;
                    293: 
                    294:        for (i = 1; i <= frag_count; i++) {
                    295:                item = iph1->frag_chain;
                    296:                do {
                    297:                        if (item->frag_num == i)
                    298:                                break;
                    299:                        item = item->frag_next;
                    300:                } while (item != NULL);
                    301: 
                    302:                if (item == NULL) {
                    303:                        plog(LLV_ERROR, LOCATION, NULL, 
                    304:                            "Missing fragment #%d\n", i);
                    305:                        vfree(buf);
                    306:                        buf = NULL;
                    307:                        goto out;
                    308:                }
                    309:                memcpy(data, item->frag_packet->v, item->frag_packet->l);
                    310:                data += item->frag_packet->l;
                    311:        }
                    312: 
                    313: out:
                    314:        item = iph1->frag_chain;                
                    315:        do {
                    316:                struct isakmp_frag_item *next_item;
                    317: 
                    318:                next_item = item->frag_next;
                    319: 
                    320:                vfree(item->frag_packet);
                    321:                racoon_free(item);
                    322: 
                    323:                item = next_item;
                    324:        } while (item != NULL);
                    325: 
                    326:        iph1->frag_chain = NULL;
                    327: 
                    328:        return buf;
                    329: }
                    330: 
                    331: vchar_t *
                    332: isakmp_frag_addcap(buf, cap)
                    333:        vchar_t *buf;
                    334:        int cap;
                    335: {
                    336:        int *capp;
                    337:        size_t len;
                    338: 
                    339:        /* If the capability has not been added, add room now */
                    340:        len = buf->l;
                    341:        if (len == MD5_DIGEST_LENGTH) {
                    342:                if ((buf = vrealloc(buf, len + sizeof(cap))) == NULL) {
                    343:                        plog(LLV_ERROR, LOCATION, NULL, 
                    344:                            "Cannot allocate memory\n");
                    345:                        return NULL;
                    346:                }
                    347:                capp = (int *)(buf->v + len);
                    348:                *capp = htonl(0);
                    349:        }
                    350: 
                    351:        capp = (int *)(buf->v + MD5_DIGEST_LENGTH);
                    352:        *capp |= htonl(cap);
                    353: 
                    354:        return buf;
                    355: }
                    356: 

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