Annotation of embedaddon/strongswan/src/libcharon/sa/ikev1/tasks/isakmp_vendor.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2012-2013 Tobias Brunner
3: * Copyright (C) 2009 Martin Willi
4: * HSR Hochschule fuer Technik Rapperswil
5: *
6: * This program is free software; you can redistribute it and/or modify it
7: * under the terms of the GNU General Public License as published by the
8: * Free Software Foundation; either version 2 of the License, or (at your
9: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10: *
11: * This program is distributed in the hope that it will be useful, but
12: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14: * for more details.
15: */
16:
17: /*
18: * Copyright (C) 2012-2014 Volker RĂ¼melin
19: *
20: * Permission is hereby granted, free of charge, to any person obtaining a copy
21: * of this software and associated documentation files (the "Software"), to deal
22: * in the Software without restriction, including without limitation the rights
23: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
24: * copies of the Software, and to permit persons to whom the Software is
25: * furnished to do so, subject to the following conditions:
26: *
27: * The above copyright notice and this permission notice shall be included in
28: * all copies or substantial portions of the Software.
29: *
30: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
33: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
34: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
35: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
36: * THE SOFTWARE.
37: */
38:
39: #include "isakmp_vendor.h"
40:
41: #include <daemon.h>
42: #include <encoding/payloads/vendor_id_payload.h>
43:
44: typedef struct private_isakmp_vendor_t private_isakmp_vendor_t;
45:
46: /**
47: * Private data of an isakmp_vendor_t object.
48: */
49: struct private_isakmp_vendor_t {
50:
51: /**
52: * Public isakmp_vendor_t interface.
53: */
54: isakmp_vendor_t public;
55:
56: /**
57: * Associated IKE_SA
58: */
59: ike_sa_t *ike_sa;
60:
61: /**
62: * Are we the initiator of this task
63: */
64: bool initiator;
65:
66: /**
67: * Index of best nat traversal VID found
68: */
69: int best_natt_ext;
70:
71: /**
72: * Number of times we have been invoked
73: */
74: int count;
75: };
76:
77: /**
78: * IKEv1 Vendor ID database
79: */
80: static struct {
81: /* Description */
82: char *desc;
83: /* extension flag negotiated with vendor ID, if any */
84: ike_extension_t extension;
85: /* send yourself? */
86: bool send;
87: /* length of vendor ID string */
88: int len;
89: /* vendor ID string */
90: char *id;
91: } vendor_ids[] = {
92:
93: /* strongSwan MD5("strongSwan") */
94: { "strongSwan", EXT_STRONGSWAN, FALSE, 16,
95: "\x88\x2f\xe5\x6d\x6f\xd2\x0d\xbc\x22\x51\x61\x3b\x2e\xbe\x5b\xeb"},
96:
97: /* XAuth, MD5("draft-ietf-ipsra-isakmp-xauth-06.txt") */
98: { "XAuth", EXT_XAUTH, TRUE, 8,
99: "\x09\x00\x26\x89\xdf\xd6\xb7\x12"},
100:
101: /* Dead peer detection, RFC 3706 */
102: { "DPD", EXT_DPD, TRUE, 16,
103: "\xaf\xca\xd7\x13\x68\xa1\xf1\xc9\x6b\x86\x96\xfc\x77\x57\x01\x00"},
104:
105: /* CISCO-UNITY, similar to DPD the last two bytes indicate the version */
106: { "Cisco Unity", EXT_CISCO_UNITY, FALSE, 16,
107: "\x12\xf5\xf2\x8c\x45\x71\x68\xa9\x70\x2d\x9f\xe2\x74\xcc\x01\x00"},
108:
109: /* Proprietary IKE fragmentation extension. Capabilities are handled
110: * specially on receipt of this VID. Windows peers send this VID
111: * without capabilities, but accept it with and without capabilities. */
112: { "FRAGMENTATION", EXT_IKE_FRAGMENTATION, FALSE, 20,
113: "\x40\x48\xb7\xd5\x6e\xbc\xe8\x85\x25\xe7\xde\x7f\x00\xd6\xc2\xd3\x80\x00\x00\x00"},
114:
115: /* Windows peers send this VID and a version number */
116: { "MS NT5 ISAKMPOAKLEY", EXT_MS_WINDOWS, FALSE, 20,
117: "\x1e\x2b\x51\x69\x05\x99\x1c\x7d\x7c\x96\xfc\xbf\xb5\x87\xe4\x61\x00\x00\x00\x00"},
118:
119: }, vendor_natt_ids[] = {
120:
121: /* NAT-Traversal VIDs ordered by preference */
122:
123: /* NAT-Traversal, MD5("RFC 3947") */
124: { "NAT-T (RFC 3947)", EXT_NATT, TRUE, 16,
125: "\x4a\x13\x1c\x81\x07\x03\x58\x45\x5c\x57\x28\xf2\x0e\x95\x45\x2f"},
126:
127: { "draft-ietf-ipsec-nat-t-ike-03", EXT_NATT | EXT_NATT_DRAFT_02_03,
128: FALSE, 16,
129: "\x7d\x94\x19\xa6\x53\x10\xca\x6f\x2c\x17\x9d\x92\x15\x52\x9d\x56"},
130:
131: { "draft-ietf-ipsec-nat-t-ike-02", EXT_NATT | EXT_NATT_DRAFT_02_03,
132: FALSE, 16,
133: "\xcd\x60\x46\x43\x35\xdf\x21\xf8\x7c\xfd\xb2\xfc\x68\xb6\xa4\x48"},
134:
135: { "draft-ietf-ipsec-nat-t-ike-02\\n", EXT_NATT | EXT_NATT_DRAFT_02_03,
136: TRUE, 16,
137: "\x90\xcb\x80\x91\x3e\xbb\x69\x6e\x08\x63\x81\xb5\xec\x42\x7b\x1f"},
138:
139: { "draft-ietf-ipsec-nat-t-ike-08", 0, FALSE, 16,
140: "\x8f\x8d\x83\x82\x6d\x24\x6b\x6f\xc7\xa8\xa6\xa4\x28\xc1\x1d\xe8"},
141:
142: { "draft-ietf-ipsec-nat-t-ike-07", 0, FALSE, 16,
143: "\x43\x9b\x59\xf8\xba\x67\x6c\x4c\x77\x37\xae\x22\xea\xb8\xf5\x82"},
144:
145: { "draft-ietf-ipsec-nat-t-ike-06", 0, FALSE, 16,
146: "\x4d\x1e\x0e\x13\x6d\xea\xfa\x34\xc4\xf3\xea\x9f\x02\xec\x72\x85"},
147:
148: { "draft-ietf-ipsec-nat-t-ike-05", 0, FALSE, 16,
149: "\x80\xd0\xbb\x3d\xef\x54\x56\x5e\xe8\x46\x45\xd4\xc8\x5c\xe3\xee"},
150:
151: { "draft-ietf-ipsec-nat-t-ike-04", 0, FALSE, 16,
152: "\x99\x09\xb6\x4e\xed\x93\x7c\x65\x73\xde\x52\xac\xe9\x52\xfa\x6b"},
153:
154: { "draft-ietf-ipsec-nat-t-ike-00", 0, FALSE, 16,
155: "\x44\x85\x15\x2d\x18\xb6\xbb\xcd\x0b\xe8\xa8\x46\x95\x79\xdd\xcc"},
156:
157: { "draft-ietf-ipsec-nat-t-ike", 0, FALSE, 16,
158: "\x4d\xf3\x79\x28\xe9\xfc\x4f\xd1\xb3\x26\x21\x70\xd5\x15\xc6\x62"},
159:
160: { "draft-stenberg-ipsec-nat-traversal-02", 0, FALSE, 16,
161: "\x61\x05\xc4\x22\xe7\x68\x47\xe4\x3f\x96\x84\x80\x12\x92\xae\xcd"},
162:
163: { "draft-stenberg-ipsec-nat-traversal-01", 0, FALSE, 16,
164: "\x27\xba\xb5\xdc\x01\xea\x07\x60\xea\x4e\x31\x90\xac\x27\xc0\xd0"},
165:
166: };
167:
168: /**
169: * According to racoon 0x80000000 seems to indicate support for fragmentation
170: * of Aggressive and Main mode messages. 0x40000000 seems to indicate support
171: * for fragmentation of base ISAKMP messages (Cisco adds that and thus sends
172: * 0xc0000000)
173: */
174: static const uint32_t fragmentation_ike = 0x80000000;
175:
176: static bool is_known_vid(chunk_t data, int i)
177: {
178: switch (vendor_ids[i].extension)
179: {
180: case EXT_IKE_FRAGMENTATION:
181: if (data.len >= 16 && memeq(data.ptr, vendor_ids[i].id, 16))
182: {
183: switch (data.len)
184: {
185: case 16:
186: return TRUE;
187: case 20:
188: return untoh32(&data.ptr[16]) & fragmentation_ike;
189: }
190: }
191: break;
192: case EXT_MS_WINDOWS:
193: return data.len == 20 && memeq(data.ptr, vendor_ids[i].id, 16);
194: case EXT_CISCO_UNITY:
195: return data.len == 16 && memeq(data.ptr, vendor_ids[i].id, 14);
196: default:
197: return chunk_equals(data, chunk_create(vendor_ids[i].id,
198: vendor_ids[i].len));
199: }
200: return FALSE;
201: }
202:
203: /**
204: * Add supported vendor ID payloads
205: */
206: static void build(private_isakmp_vendor_t *this, message_t *message)
207: {
208: vendor_id_payload_t *vid_payload;
209: bool strongswan, cisco_unity, fragmentation;
210: ike_cfg_t *ike_cfg;
211: int i;
212:
213: strongswan = lib->settings->get_bool(lib->settings,
214: "%s.send_vendor_id", FALSE, lib->ns);
215: cisco_unity = lib->settings->get_bool(lib->settings,
216: "%s.cisco_unity", FALSE, lib->ns);
217: ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
218: fragmentation = ike_cfg->fragmentation(ike_cfg) != FRAGMENTATION_NO;
219: if (!this->initiator && fragmentation)
220: {
221: fragmentation = this->ike_sa->supports_extension(this->ike_sa,
222: EXT_IKE_FRAGMENTATION);
223: }
224: for (i = 0; i < countof(vendor_ids); i++)
225: {
226: if (vendor_ids[i].send ||
227: (vendor_ids[i].extension == EXT_STRONGSWAN && strongswan) ||
228: (vendor_ids[i].extension == EXT_CISCO_UNITY && cisco_unity) ||
229: (vendor_ids[i].extension == EXT_IKE_FRAGMENTATION && fragmentation))
230: {
231: DBG2(DBG_IKE, "sending %s vendor ID", vendor_ids[i].desc);
232: vid_payload = vendor_id_payload_create_data(PLV1_VENDOR_ID,
233: chunk_clone(chunk_create(vendor_ids[i].id, vendor_ids[i].len)));
234: message->add_payload(message, &vid_payload->payload_interface);
235: }
236: }
237: for (i = 0; i < countof(vendor_natt_ids); i++)
238: {
239: if ((this->initiator && vendor_natt_ids[i].send) ||
240: this->best_natt_ext == i)
241: {
242: DBG2(DBG_IKE, "sending %s vendor ID", vendor_natt_ids[i].desc);
243: vid_payload = vendor_id_payload_create_data(PLV1_VENDOR_ID,
244: chunk_clone(chunk_create(vendor_natt_ids[i].id,
245: vendor_natt_ids[i].len)));
246: message->add_payload(message, &vid_payload->payload_interface);
247: }
248: }
249: }
250:
251: /**
252: * Process vendor ID payloads
253: */
254: static void process(private_isakmp_vendor_t *this, message_t *message)
255: {
256: enumerator_t *enumerator;
257: payload_t *payload;
258: int i;
259:
260: enumerator = message->create_payload_enumerator(message);
261: while (enumerator->enumerate(enumerator, &payload))
262: {
263: if (payload->get_type(payload) == PLV1_VENDOR_ID)
264: {
265: vendor_id_payload_t *vid;
266: bool found = FALSE;
267: chunk_t data;
268:
269: vid = (vendor_id_payload_t*)payload;
270: data = vid->get_data(vid);
271:
272: for (i = 0; i < countof(vendor_ids); i++)
273: {
274: if (is_known_vid(data, i))
275: {
276: DBG1(DBG_IKE, "received %s vendor ID", vendor_ids[i].desc);
277: if (vendor_ids[i].extension)
278: {
279: this->ike_sa->enable_extension(this->ike_sa,
280: vendor_ids[i].extension);
281: }
282: found = TRUE;
283: break;
284: }
285: }
286: if (!found)
287: {
288: for (i = 0; i < countof(vendor_natt_ids); i++)
289: {
290: if (chunk_equals(data, chunk_create(vendor_natt_ids[i].id,
291: vendor_natt_ids[i].len)))
292: {
293: DBG1(DBG_IKE, "received %s vendor ID",
294: vendor_natt_ids[i].desc);
295: if (vendor_natt_ids[i].extension &&
296: (i < this->best_natt_ext || this->best_natt_ext < 0))
297: {
298: this->best_natt_ext = i;
299: }
300: found = TRUE;
301: break;
302: }
303: }
304: }
305: if (!found)
306: {
307: DBG1(DBG_ENC, "received unknown vendor ID: %#B", &data);
308: }
309: }
310: }
311: enumerator->destroy(enumerator);
312:
313: if (this->best_natt_ext >= 0)
314: {
315: this->ike_sa->enable_extension(this->ike_sa,
316: vendor_natt_ids[this->best_natt_ext].extension);
317: }
318: }
319:
320: METHOD(task_t, build_i, status_t,
321: private_isakmp_vendor_t *this, message_t *message)
322: {
323: if (this->count++ == 0)
324: {
325: build(this, message);
326: }
327: if (message->get_exchange_type(message) == AGGRESSIVE && this->count > 1)
328: {
329: return SUCCESS;
330: }
331: return NEED_MORE;
332: }
333:
334: METHOD(task_t, process_r, status_t,
335: private_isakmp_vendor_t *this, message_t *message)
336: {
337: this->count++;
338: process(this, message);
339: if (message->get_exchange_type(message) == AGGRESSIVE && this->count > 1)
340: {
341: return SUCCESS;
342: }
343: return NEED_MORE;
344: }
345:
346: METHOD(task_t, build_r, status_t,
347: private_isakmp_vendor_t *this, message_t *message)
348: {
349: if (this->count == 1)
350: {
351: build(this, message);
352: }
353: if (message->get_exchange_type(message) == ID_PROT && this->count > 2)
354: {
355: return SUCCESS;
356: }
357: return NEED_MORE;
358: }
359:
360: METHOD(task_t, process_i, status_t,
361: private_isakmp_vendor_t *this, message_t *message)
362: {
363: process(this, message);
364: if (message->get_exchange_type(message) == ID_PROT && this->count > 2)
365: {
366: return SUCCESS;
367: }
368: return NEED_MORE;
369: }
370:
371: METHOD(task_t, migrate, void,
372: private_isakmp_vendor_t *this, ike_sa_t *ike_sa)
373: {
374: this->ike_sa = ike_sa;
375: this->count = 0;
376: }
377:
378: METHOD(task_t, get_type, task_type_t,
379: private_isakmp_vendor_t *this)
380: {
381: return TASK_ISAKMP_VENDOR;
382: }
383:
384: METHOD(task_t, destroy, void,
385: private_isakmp_vendor_t *this)
386: {
387: free(this);
388: }
389:
390: /**
391: * See header
392: */
393: isakmp_vendor_t *isakmp_vendor_create(ike_sa_t *ike_sa, bool initiator)
394: {
395: private_isakmp_vendor_t *this;
396:
397: INIT(this,
398: .public = {
399: .task = {
400: .migrate = _migrate,
401: .get_type = _get_type,
402: .destroy = _destroy,
403: },
404: },
405: .initiator = initiator,
406: .ike_sa = ike_sa,
407: .best_natt_ext = -1,
408: );
409:
410: if (initiator)
411: {
412: this->public.task.build = _build_i;
413: this->public.task.process = _process_i;
414: }
415: else
416: {
417: this->public.task.build = _build_r;
418: this->public.task.process = _process_r;
419: }
420:
421: return &this->public;
422: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>