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