]> git.ipfire.org Git - people/ms/strongswan.git/blame - src/libcharon/sa/ikev2/tasks/ike_vendor.c
ike: Fix prefix length and data of vendor ID Cisco VPN Concentrator
[people/ms/strongswan.git] / src / libcharon / sa / ikev2 / tasks / ike_vendor.c
CommitLineData
a5a0bcaa
MW
1/*
2 * Copyright (C) 2009 Martin Willi
1b671669 3 * HSR Hochschule fuer Technik Rapperswil
a5a0bcaa
MW
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
78233939
TE
16/*
17 * Copyright (C) 2016 secunet Security Networks AG
18 * Copyright (C) 2016 Thomas Egerer
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
a5a0bcaa
MW
39#include "ike_vendor.h"
40
41#include <daemon.h>
42#include <encoding/payloads/vendor_id_payload.h>
43
44typedef struct private_ike_vendor_t private_ike_vendor_t;
45
46/**
47 * Private data of an ike_vendor_t object.
48 */
49struct private_ike_vendor_t {
50
51 /**
52 * Public ike_vendor_t interface.
53 */
54 ike_vendor_t public;
55
56 /**
57 * Associated IKE_SA
58 */
59 ike_sa_t *ike_sa;
60
61 /**
784d96e0 62 * Are we the initiator of this task
a5a0bcaa
MW
63 */
64 bool initiator;
65};
66
67/**
a8d8e631 68 * Vendor ID database entry
a5a0bcaa 69 */
a8d8e631
MW
70typedef struct {
71 /* Description */
72 char *desc;
73 /* extension flag negotiated with vendor ID, if any */
74 ike_extension_t extension;
78233939
TE
75 /* Value from strongswan.conf, whether to send vendor ID */
76 char *setting;
6c49ddfb
NK
77 /* Prefix matching only */
78 bool prefix;
a8d8e631
MW
79 /* length of vendor ID string, 0 for NULL terminated */
80 int len;
81 /* vendor ID string */
82 char *id;
83} vid_data_t;
84
85/**
86 * Get the data of a vendor ID as a chunk
87 */
6c49ddfb 88static inline chunk_t get_vid_data(vid_data_t *data)
a8d8e631
MW
89{
90 return chunk_create(data->id, data->len ?: strlen(data->id));
91}
92
93/**
94 * IKEv2 Vendor ID database entry
95 */
96static vid_data_t vids[] = {
97 /* strongSwan MD5("strongSwan") */
6c49ddfb 98 { "strongSwan", EXT_STRONGSWAN, "send_vendor_id", FALSE, 16,
a8d8e631 99 "\x88\x2f\xe5\x6d\x6f\xd2\x0d\xbc\x22\x51\x61\x3b\x2e\xbe\x5b\xeb"},
6c49ddfb 100 { "Cisco Delete Reason", 0, NULL, FALSE, 0,
f84d1cb2 101 "CISCO-DELETE-REASON" },
6c49ddfb 102 { "Cisco FlexVPN Supported", 0, "cisco_flexvpn", FALSE, 0,
7f86b0f6 103 "FLEXVPN-SUPPORTED" },
6c49ddfb 104 { "Cisco Copyright (c) 2009", 0, NULL, FALSE, 0,
2c6d204b 105 "CISCO(COPYRIGHT)&Copyright (c) 2009 Cisco Systems, Inc." },
6c49ddfb 106 { "FRAGMENTATION", 0, NULL, FALSE, 16,
c7c2e24a 107 "\x40\x48\xb7\xd5\x6e\xbc\xe8\x85\x25\xe7\xde\x7f\x00\xd6\xc2\xd3"},
6c49ddfb 108 { "MS NT5 ISAKMPOAKLEY v7", 0, NULL, FALSE, 20,
c5a41c91 109 "\x1e\x2b\x51\x69\x05\x99\x1c\x7d\x7c\x96\xfc\xbf\xb5\x87\xe4\x61\x00\x00\x00\x07"},
6c49ddfb 110 { "MS NT5 ISAKMPOAKLEY v8", 0, NULL, FALSE, 20,
c5a41c91 111 "\x1e\x2b\x51\x69\x05\x99\x1c\x7d\x7c\x96\xfc\xbf\xb5\x87\xe4\x61\x00\x00\x00\x08"},
6c49ddfb 112 { "MS NT5 ISAKMPOAKLEY v9", 0, NULL, FALSE, 20,
c5a41c91 113 "\x1e\x2b\x51\x69\x05\x99\x1c\x7d\x7c\x96\xfc\xbf\xb5\x87\xe4\x61\x00\x00\x00\x09"},
6c49ddfb 114 { "MS-Negotiation Discovery Capable", 0, NULL, FALSE, 16,
c5a41c91 115 "\xfb\x1d\xe3\xcd\xf3\x41\xb7\xea\x16\xb7\xe5\xbe\x08\x55\xf1\x20"},
6c49ddfb 116 { "Vid-Initial-Contact", 0, NULL, FALSE, 16,
c5a41c91 117 "\x26\x24\x4d\x38\xed\xdb\x61\xb3\x17\x2a\x36\xe3\xd0\xcf\xb8\x19"},
9747376c
VR
118 /* Truncated MD5("ALTIGA GATEWAY") plus two version bytes */
119 { "Cisco VPN Concentrator", 0, NULL, TRUE, 14,
120 "\x1f\x07\xf7\x0e\xaa\x65\x14\xd3\xb0\xfa\x96\x54\x2a\x50\x00\x00"},
6c49ddfb
NK
121 { "Cisco VPN 3000 client", 0, NULL, FALSE, 20,
122 "\xf6\xf7\xef\xc7\xf5\xae\xb8\xcb\x15\x8c\xb9\xd0\x94\xba\x69\xe7"},
123 { "ZyXEL ZyWALL Router", 0, NULL, FALSE, 20,
124 "\xb8\x58\xd1\xad\xdd\x08\xc1\xe8\xad\xaf\xea\x15\x06\x08\xaa\x44\x97\xaa\x6c\xc8"},
125 { "ZyXEL ZyWALL USG 100", 0, NULL, FALSE, 14,
126 "\xf7\x58\xf2\x26\x68\x75\x0f\x03\xb0\x8d\xf6\xeb\xe1\xd0"},
127 { "ZyXEL ZyWALL", 0, NULL, FALSE, 20,
128 "\x62\x50\x27\x74\x9d\x5a\xb9\x7f\x56\x16\xc1\x60\x27\x65\xcf\x48\x0a\x3b\x7d\x0b"},
129 { "Sonicwall 7", 0, NULL, TRUE, 8,
130 "\x5b\x36\x2b\xc8\x20\xf6\x00\x07"},
131 { "Sonicwall 8", 0, NULL, TRUE, 8,
132 "\x5b\x36\x2b\xc8\x20\xf6\x00\x08"},
133 { "Sonicwall a", 0, NULL, TRUE, 8,
134 "\x40\x4b\xf4\x39\x52\x2c\xa3\xf6"},
135 { "Sonicwall b", 0, NULL, TRUE, 8,
136 "\xda\x8e\x93\x78\x80\x01\x00\x00"},
137 { "Sonicwall c", 0, NULL, TRUE, 8,
138 "\x5b\x36\x2b\xc8\x20\xf7\x00\x01"},
139 { "Fortigate", 0, NULL, FALSE, 16,
140 "\x1d\x6e\x17\x8f\x6c\x2c\x0b\xe2\x84\x98\x54\x65\x45\x0f\xe9\xd4"},
141 { "Checkpoint Firewall", 0, NULL, TRUE, 20,
142 "\xf4\xed\x19\xe0\xc1\x14\xeb\x51\x6f\xaa\xac\x0e\xe3\x7d\xaf\x28\x07\xb4\x38\x1f"},
143 { "NetScreen Technologies", 0, NULL, TRUE, 20,
144 "\x69\x93\x69\x22\x87\x41\xc6\xd4\xca\x09\x4c\x93\xe2\x42\xc9\xde\x19\xe7\xb7\xc6"},
145 { "Juniper SRX", 0, NULL, FALSE, 20,
146 "\xfd\x80\x88\x04\xdf\x73\xb1\x51\x50\x70\x9d\x87\x80\x44\xcd\xe0\xac\x1e\xfc\xde"},
a8d8e631 147};
a5a0bcaa
MW
148
149METHOD(task_t, build, status_t,
150 private_ike_vendor_t *this, message_t *message)
151{
a8d8e631 152 vendor_id_payload_t *vid;
78233939 153 bool send_vid;
a8d8e631 154 int i;
a5a0bcaa 155
a8d8e631
MW
156 for (i = 0; i < countof(vids); i++)
157 {
78233939
TE
158 send_vid = FALSE;
159
160 if (vids[i].setting)
161 {
162 send_vid = lib->settings->get_bool(lib->settings, "%s.%s", send_vid,
163 lib->ns, vids[i].setting);
164 }
165 if (send_vid)
a8d8e631
MW
166 {
167 DBG2(DBG_IKE, "sending %s vendor ID", vids[i].desc);
3ecfc83c 168 vid = vendor_id_payload_create_data(PLV2_VENDOR_ID,
a8d8e631
MW
169 chunk_clone(get_vid_data(&vids[i])));
170 message->add_payload(message, &vid->payload_interface);
171 }
a5a0bcaa
MW
172 }
173
174 return this->initiator ? NEED_MORE : SUCCESS;
175}
176
6c49ddfb
NK
177/**
178 * Check if the given known vendor ID matches a received VID or its prefix
179 */
180static inline bool known_vid(vid_data_t *vid, chunk_t data)
181{
182 chunk_t known = get_vid_data(vid);
183
184 if (vid->prefix)
185 {
186 data.len = min(data.len, known.len);
187 }
188 return chunk_equals(known, data);
189}
190
a5a0bcaa
MW
191METHOD(task_t, process, status_t,
192 private_ike_vendor_t *this, message_t *message)
193{
194 enumerator_t *enumerator;
195 payload_t *payload;
a8d8e631 196 int i;
a5a0bcaa
MW
197
198 enumerator = message->create_payload_enumerator(message);
199 while (enumerator->enumerate(enumerator, &payload))
200 {
3ecfc83c 201 if (payload->get_type(payload) == PLV2_VENDOR_ID)
a5a0bcaa
MW
202 {
203 vendor_id_payload_t *vid;
204 chunk_t data;
a8d8e631 205 bool found = FALSE;
a5a0bcaa
MW
206
207 vid = (vendor_id_payload_t*)payload;
208 data = vid->get_data(vid);
209
a8d8e631 210 for (i = 0; i < countof(vids); i++)
a5a0bcaa 211 {
6c49ddfb 212 if (known_vid(&vids[i], data))
a8d8e631
MW
213 {
214 DBG1(DBG_IKE, "received %s vendor ID", vids[i].desc);
215 if (vids[i].extension)
216 {
217 this->ike_sa->enable_extension(this->ike_sa,
218 vids[i].extension);
219 }
220 found = TRUE;
221 break;
222 }
a5a0bcaa 223 }
a8d8e631 224 if (!found)
a5a0bcaa 225 {
f7cd1cde 226 DBG1(DBG_ENC, "received unknown vendor ID: %#B", &data);
a5a0bcaa
MW
227 }
228 }
229 }
230 enumerator->destroy(enumerator);
231
232 return this->initiator ? SUCCESS : NEED_MORE;
233}
234
235METHOD(task_t, migrate, void,
236 private_ike_vendor_t *this, ike_sa_t *ike_sa)
237{
238 this->ike_sa = ike_sa;
239}
240
241METHOD(task_t, get_type, task_type_t,
242 private_ike_vendor_t *this)
243{
a09972df 244 return TASK_IKE_VENDOR;
a5a0bcaa
MW
245}
246
247METHOD(task_t, destroy, void,
248 private_ike_vendor_t *this)
249{
250 free(this);
251}
252
253/**
254 * See header
255 */
256ike_vendor_t *ike_vendor_create(ike_sa_t *ike_sa, bool initiator)
257{
258 private_ike_vendor_t *this;
259
260 INIT(this,
ba31fe1f
MW
261 .public = {
262 .task = {
263 .build = _build,
264 .process = _process,
265 .migrate = _migrate,
266 .get_type = _get_type,
267 .destroy = _destroy,
268 },
a5a0bcaa
MW
269 },
270 .initiator = initiator,
271 .ike_sa = ike_sa,
272 );
273
274 return &this->public;
275}