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>