]>
Commit | Line | Data |
---|---|---|
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 | ||
44 | typedef struct private_ike_vendor_t private_ike_vendor_t; | |
45 | ||
46 | /** | |
47 | * Private data of an ike_vendor_t object. | |
48 | */ | |
49 | struct 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 |
70 | typedef 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 | 88 | static 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 | */ | |
96 | static 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 | |
149 | METHOD(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 | */ | |
180 | static 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 |
191 | METHOD(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 | ||
235 | METHOD(task_t, migrate, void, | |
236 | private_ike_vendor_t *this, ike_sa_t *ike_sa) | |
237 | { | |
238 | this->ike_sa = ike_sa; | |
239 | } | |
240 | ||
241 | METHOD(task_t, get_type, task_type_t, | |
242 | private_ike_vendor_t *this) | |
243 | { | |
a09972df | 244 | return TASK_IKE_VENDOR; |
a5a0bcaa MW |
245 | } |
246 | ||
247 | METHOD(task_t, destroy, void, | |
248 | private_ike_vendor_t *this) | |
249 | { | |
250 | free(this); | |
251 | } | |
252 | ||
253 | /** | |
254 | * See header | |
255 | */ | |
256 | ike_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 | } |