File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ipsec-tools / src / racoon / isakmp_frag.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 22:39:10 2012 UTC (12 years, 4 months ago) by misho
Branches: ipsec-tools, MAIN
CVS tags: v0_8_2p2, v0_8_1p0, v0_8_1, v0_8_0p0, v0_8_0, HEAD
ipsec-tools

    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>