]>
Commit | Line | Data |
---|---|---|
1adaa02b | 1 | /* |
668e84d9 | 2 | * Copyright (C) 2008-2010 Tobias Brunner |
c6362858 | 3 | * Copyright (C) 2008 Andreas Steffen |
1adaa02b TB |
4 | * 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. | |
1adaa02b TB |
15 | */ |
16 | ||
17 | #include <sys/types.h> | |
18 | #include <sys/socket.h> | |
d24a74c5 | 19 | |
79ff6141 TB |
20 | #ifdef __FreeBSD__ |
21 | #include <limits.h> /* for LONG_MAX */ | |
22 | #endif | |
23 | ||
d24a74c5 TB |
24 | #ifdef HAVE_NET_PFKEYV2_H |
25 | #include <net/pfkeyv2.h> | |
26 | #else | |
1adaa02b | 27 | #include <stdint.h> |
1adaa02b | 28 | #include <linux/pfkeyv2.h> |
d24a74c5 TB |
29 | #endif |
30 | ||
31 | #ifdef SADB_X_EXT_NAT_T_TYPE | |
32 | #define HAVE_NATT | |
33 | #endif | |
34 | ||
35 | #ifdef HAVE_NETIPSEC_IPSEC_H | |
36 | #include <netipsec/ipsec.h> | |
9f090745 TB |
37 | #elif defined(HAVE_NETINET6_IPSEC_H) |
38 | #include <netinet6/ipsec.h> | |
d24a74c5 TB |
39 | #else |
40 | #include <linux/ipsec.h> | |
41 | #endif | |
42 | ||
43 | #ifdef HAVE_NATT | |
1e7b4b00 | 44 | #ifdef HAVE_LINUX_UDP_H |
1adaa02b | 45 | #include <linux/udp.h> |
1e7b4b00 TB |
46 | #else |
47 | #include <netinet/udp.h> | |
48 | #endif /*HAVE_LINUX_UDP_H*/ | |
d24a74c5 TB |
49 | #endif /*HAVE_NATT*/ |
50 | ||
1adaa02b | 51 | #include <unistd.h> |
4a5a5dd2 | 52 | #include <time.h> |
1adaa02b TB |
53 | #include <errno.h> |
54 | ||
55 | #include "kernel_pfkey_ipsec.h" | |
56 | ||
57 | #include <daemon.h> | |
e526d228 | 58 | #include <utils/host.h> |
4a5a5dd2 | 59 | #include <threading/thread.h> |
eba64cef | 60 | #include <threading/mutex.h> |
1adaa02b TB |
61 | #include <processing/jobs/callback_job.h> |
62 | #include <processing/jobs/acquire_job.h> | |
ef6d339c | 63 | #include <processing/jobs/migrate_job.h> |
1adaa02b TB |
64 | #include <processing/jobs/rekey_child_sa_job.h> |
65 | #include <processing/jobs/delete_child_sa_job.h> | |
66 | #include <processing/jobs/update_sa_job.h> | |
67 | ||
d24a74c5 TB |
68 | /** non linux specific */ |
69 | #ifndef IPPROTO_COMP | |
b7900d32 | 70 | #ifdef IPPROTO_IPCOMP |
d24a74c5 TB |
71 | #define IPPROTO_COMP IPPROTO_IPCOMP |
72 | #endif | |
b7900d32 | 73 | #endif |
d24a74c5 TB |
74 | |
75 | #ifndef SADB_X_AALG_SHA2_256HMAC | |
76 | #define SADB_X_AALG_SHA2_256HMAC SADB_X_AALG_SHA2_256 | |
77 | #define SADB_X_AALG_SHA2_384HMAC SADB_X_AALG_SHA2_384 | |
78 | #define SADB_X_AALG_SHA2_512HMAC SADB_X_AALG_SHA2_512 | |
79 | #endif | |
80 | ||
81 | #ifndef SADB_X_EALG_AESCBC | |
82 | #define SADB_X_EALG_AESCBC SADB_X_EALG_AES | |
83 | #endif | |
84 | ||
85 | #ifndef SADB_X_EALG_CASTCBC | |
86 | #define SADB_X_EALG_CASTCBC SADB_X_EALG_CAST128CBC | |
87 | #endif | |
88 | ||
89 | #ifndef SOL_IP | |
90 | #define SOL_IP IPPROTO_IP | |
91 | #define SOL_IPV6 IPPROTO_IPV6 | |
92 | #endif | |
93 | ||
ea625fab TB |
94 | /** from linux/in.h */ |
95 | #ifndef IP_IPSEC_POLICY | |
96 | #define IP_IPSEC_POLICY 16 | |
97 | #endif | |
98 | ||
e20bd8b6 | 99 | /** missing on uclibc */ |
addfea95 MW |
100 | #ifndef IPV6_IPSEC_POLICY |
101 | #define IPV6_IPSEC_POLICY 34 | |
d24a74c5 | 102 | #endif |
addfea95 | 103 | |
1adaa02b TB |
104 | /** default priority of installed policies */ |
105 | #define PRIO_LOW 3000 | |
106 | #define PRIO_HIGH 2000 | |
107 | ||
e20bd8b6 TB |
108 | #ifdef __APPLE__ |
109 | /** from xnu/bsd/net/pfkeyv2.h */ | |
110 | #define SADB_X_EXT_NATT 0x002 | |
111 | struct sadb_sa_2 { | |
112 | struct sadb_sa sa; | |
113 | u_int16_t sadb_sa_natt_port; | |
114 | u_int16_t sadb_reserved0; | |
115 | u_int32_t sadb_reserved1; | |
116 | }; | |
117 | #endif | |
118 | ||
1adaa02b | 119 | /** buffer size for PF_KEY messages */ |
e526d228 | 120 | #define PFKEY_BUFFER_SIZE 4096 |
1adaa02b TB |
121 | |
122 | /** PF_KEY messages are 64 bit aligned */ | |
123 | #define PFKEY_ALIGNMENT 8 | |
124 | /** aligns len to 64 bits */ | |
125 | #define PFKEY_ALIGN(len) (((len) + PFKEY_ALIGNMENT - 1) & ~(PFKEY_ALIGNMENT - 1)) | |
126 | /** calculates the properly padded length in 64 bit chunks */ | |
127 | #define PFKEY_LEN(len) ((PFKEY_ALIGN(len) / PFKEY_ALIGNMENT)) | |
128 | /** calculates user mode length i.e. in bytes */ | |
129 | #define PFKEY_USER_LEN(len) ((len) * PFKEY_ALIGNMENT) | |
130 | ||
131 | /** given a PF_KEY message header and an extension this updates the length in the header */ | |
132 | #define PFKEY_EXT_ADD(msg, ext) ((msg)->sadb_msg_len += ((struct sadb_ext*)ext)->sadb_ext_len) | |
133 | /** given a PF_KEY message header this returns a pointer to the next extension */ | |
134 | #define PFKEY_EXT_ADD_NEXT(msg) ((struct sadb_ext*)(((char*)(msg)) + PFKEY_USER_LEN((msg)->sadb_msg_len))) | |
135 | /** copy an extension and append it to a PF_KEY message */ | |
136 | #define PFKEY_EXT_COPY(msg, ext) (PFKEY_EXT_ADD(msg, memcpy(PFKEY_EXT_ADD_NEXT(msg), ext, PFKEY_USER_LEN(((struct sadb_ext*)ext)->sadb_ext_len)))) | |
137 | /** given a PF_KEY extension this returns a pointer to the next extension */ | |
138 | #define PFKEY_EXT_NEXT(ext) ((struct sadb_ext*)(((char*)(ext)) + PFKEY_USER_LEN(((struct sadb_ext*)ext)->sadb_ext_len))) | |
139 | /** given a PF_KEY extension this returns a pointer to the next extension also updates len (len in 64 bit words) */ | |
140 | #define PFKEY_EXT_NEXT_LEN(ext,len) ((len) -= (ext)->sadb_ext_len, PFKEY_EXT_NEXT(ext)) | |
141 | /** true if ext has a valid length and len is large enough to contain ext (assuming len in 64 bit words) */ | |
142 | #define PFKEY_EXT_OK(ext,len) ((len) >= PFKEY_LEN(sizeof(struct sadb_ext)) && \ | |
143 | (ext)->sadb_ext_len >= PFKEY_LEN(sizeof(struct sadb_ext)) && \ | |
144 | (ext)->sadb_ext_len <= (len)) | |
145 | ||
146 | typedef struct private_kernel_pfkey_ipsec_t private_kernel_pfkey_ipsec_t; | |
147 | ||
148 | /** | |
149 | * Private variables and functions of kernel_pfkey class. | |
150 | */ | |
151 | struct private_kernel_pfkey_ipsec_t | |
152 | { | |
153 | /** | |
154 | * Public part of the kernel_pfkey_t object. | |
155 | */ | |
156 | kernel_pfkey_ipsec_t public; | |
7daf5226 | 157 | |
1adaa02b TB |
158 | /** |
159 | * mutex to lock access to various lists | |
160 | */ | |
3ac5a0db | 161 | mutex_t *mutex; |
7daf5226 | 162 | |
1adaa02b TB |
163 | /** |
164 | * List of installed policies (policy_entry_t) | |
165 | */ | |
166 | linked_list_t *policies; | |
7daf5226 | 167 | |
1adaa02b TB |
168 | /** |
169 | * whether to install routes along policies | |
170 | */ | |
171 | bool install_routes; | |
7daf5226 | 172 | |
1adaa02b TB |
173 | /** |
174 | * job receiving PF_KEY events | |
175 | */ | |
176 | callback_job_t *job; | |
7daf5226 | 177 | |
1adaa02b TB |
178 | /** |
179 | * mutex to lock access to the PF_KEY socket | |
180 | */ | |
3ac5a0db | 181 | mutex_t *mutex_pfkey; |
7daf5226 | 182 | |
1adaa02b TB |
183 | /** |
184 | * PF_KEY socket to communicate with the kernel | |
185 | */ | |
186 | int socket; | |
7daf5226 | 187 | |
1adaa02b TB |
188 | /** |
189 | * PF_KEY socket to receive acquire and expire events | |
190 | */ | |
191 | int socket_events; | |
7daf5226 | 192 | |
1adaa02b TB |
193 | /** |
194 | * sequence number for messages sent to the kernel | |
195 | */ | |
196 | int seq; | |
197 | }; | |
198 | ||
199 | typedef struct route_entry_t route_entry_t; | |
200 | ||
201 | /** | |
202 | * installed routing entry | |
203 | */ | |
204 | struct route_entry_t { | |
205 | /** Name of the interface the route is bound to */ | |
206 | char *if_name; | |
7daf5226 | 207 | |
1adaa02b TB |
208 | /** Source ip of the route */ |
209 | host_t *src_ip; | |
7daf5226 | 210 | |
1adaa02b TB |
211 | /** gateway for this route */ |
212 | host_t *gateway; | |
213 | ||
214 | /** Destination net */ | |
215 | chunk_t dst_net; | |
216 | ||
217 | /** Destination net prefixlen */ | |
218 | u_int8_t prefixlen; | |
219 | }; | |
220 | ||
221 | /** | |
222 | * destroy an route_entry_t object | |
223 | */ | |
224 | static void route_entry_destroy(route_entry_t *this) | |
225 | { | |
226 | free(this->if_name); | |
d24a74c5 TB |
227 | DESTROY_IF(this->src_ip); |
228 | DESTROY_IF(this->gateway); | |
1adaa02b TB |
229 | chunk_free(&this->dst_net); |
230 | free(this); | |
231 | } | |
232 | ||
233 | typedef struct policy_entry_t policy_entry_t; | |
234 | ||
235 | /** | |
236 | * installed kernel policy. | |
237 | */ | |
238 | struct policy_entry_t { | |
7daf5226 | 239 | |
1adaa02b TB |
240 | /** reqid of this policy */ |
241 | u_int32_t reqid; | |
7daf5226 | 242 | |
1adaa02b TB |
243 | /** index assigned by the kernel */ |
244 | u_int32_t index; | |
7daf5226 | 245 | |
1adaa02b TB |
246 | /** direction of this policy: in, out, forward */ |
247 | u_int8_t direction; | |
7daf5226 | 248 | |
1adaa02b TB |
249 | /** parameters of installed policy */ |
250 | struct { | |
251 | /** subnet and port */ | |
252 | host_t *net; | |
253 | /** subnet mask */ | |
254 | u_int8_t mask; | |
255 | /** protocol */ | |
256 | u_int8_t proto; | |
257 | } src, dst; | |
7daf5226 | 258 | |
1adaa02b TB |
259 | /** associated route installed for this policy */ |
260 | route_entry_t *route; | |
7daf5226 | 261 | |
1adaa02b TB |
262 | /** by how many CHILD_SA's this policy is used */ |
263 | u_int refcount; | |
264 | }; | |
265 | ||
266 | /** | |
267 | * create a policy_entry_t object | |
268 | */ | |
269 | static policy_entry_t *create_policy_entry(traffic_selector_t *src_ts, | |
270 | traffic_selector_t *dst_ts, policy_dir_t dir, u_int32_t reqid) | |
271 | { | |
272 | policy_entry_t *policy = malloc_thing(policy_entry_t); | |
273 | policy->reqid = reqid; | |
274 | policy->index = 0; | |
275 | policy->direction = dir; | |
276 | policy->route = NULL; | |
277 | policy->refcount = 0; | |
7daf5226 | 278 | |
1adaa02b TB |
279 | src_ts->to_subnet(src_ts, &policy->src.net, &policy->src.mask); |
280 | dst_ts->to_subnet(dst_ts, &policy->dst.net, &policy->dst.mask); | |
7daf5226 | 281 | |
1adaa02b TB |
282 | /* src or dest proto may be "any" (0), use more restrictive one */ |
283 | policy->src.proto = max(src_ts->get_protocol(src_ts), dst_ts->get_protocol(dst_ts)); | |
d24a74c5 | 284 | policy->src.proto = policy->src.proto ? policy->src.proto : IPSEC_PROTO_ANY; |
1adaa02b | 285 | policy->dst.proto = policy->src.proto; |
7daf5226 | 286 | |
1adaa02b TB |
287 | return policy; |
288 | } | |
289 | ||
290 | /** | |
291 | * destroy a policy_entry_t object | |
292 | */ | |
293 | static void policy_entry_destroy(policy_entry_t *this) | |
294 | { | |
295 | DESTROY_IF(this->src.net); | |
296 | DESTROY_IF(this->dst.net); | |
297 | if (this->route) | |
298 | { | |
299 | route_entry_destroy(this->route); | |
300 | } | |
301 | free(this); | |
302 | } | |
303 | ||
304 | /** | |
305 | * compares two policy_entry_t | |
306 | */ | |
307 | static inline bool policy_entry_equals(policy_entry_t *current, policy_entry_t *policy) | |
308 | { | |
309 | return current->direction == policy->direction && | |
310 | current->src.proto == policy->src.proto && | |
311 | current->dst.proto == policy->dst.proto && | |
312 | current->src.mask == policy->src.mask && | |
313 | current->dst.mask == policy->dst.mask && | |
314 | current->src.net->equals(current->src.net, policy->src.net) && | |
315 | current->dst.net->equals(current->dst.net, policy->dst.net); | |
316 | } | |
317 | ||
318 | /** | |
319 | * compare the given kernel index with that of a policy | |
320 | */ | |
321 | static inline bool policy_entry_match_byindex(policy_entry_t *current, u_int32_t *index) | |
322 | { | |
323 | return current->index == *index; | |
324 | } | |
325 | ||
326 | typedef struct pfkey_msg_t pfkey_msg_t; | |
327 | ||
328 | struct pfkey_msg_t | |
329 | { | |
330 | /** | |
331 | * PF_KEY message base | |
332 | */ | |
333 | struct sadb_msg *msg; | |
7daf5226 | 334 | |
1adaa02b TB |
335 | /** |
336 | * PF_KEY message extensions | |
337 | */ | |
338 | union { | |
339 | struct sadb_ext *ext[SADB_EXT_MAX + 1]; | |
340 | struct { | |
341 | struct sadb_ext *reserved; /* SADB_EXT_RESERVED */ | |
342 | struct sadb_sa *sa; /* SADB_EXT_SA */ | |
343 | struct sadb_lifetime *lft_current; /* SADB_EXT_LIFETIME_CURRENT */ | |
344 | struct sadb_lifetime *lft_hard; /* SADB_EXT_LIFETIME_HARD */ | |
345 | struct sadb_lifetime *lft_soft; /* SADB_EXT_LIFETIME_SOFT */ | |
346 | struct sadb_address *src; /* SADB_EXT_ADDRESS_SRC */ | |
347 | struct sadb_address *dst; /* SADB_EXT_ADDRESS_DST */ | |
348 | struct sadb_address *proxy; /* SADB_EXT_ADDRESS_PROXY */ | |
349 | struct sadb_key *key_auth; /* SADB_EXT_KEY_AUTH */ | |
350 | struct sadb_key *key_encr; /* SADB_EXT_KEY_ENCRYPT */ | |
351 | struct sadb_ident *id_src; /* SADB_EXT_IDENTITY_SRC */ | |
352 | struct sadb_ident *id_dst; /* SADB_EXT_IDENTITY_DST */ | |
353 | struct sadb_sens *sensitivity; /* SADB_EXT_SENSITIVITY */ | |
354 | struct sadb_prop *proposal; /* SADB_EXT_PROPOSAL */ | |
355 | struct sadb_supported *supported_auth; /* SADB_EXT_SUPPORTED_AUTH */ | |
356 | struct sadb_supported *supported_encr; /* SADB_EXT_SUPPORTED_ENCRYPT */ | |
357 | struct sadb_spirange *spirange; /* SADB_EXT_SPIRANGE */ | |
358 | struct sadb_x_kmprivate *x_kmprivate; /* SADB_X_EXT_KMPRIVATE */ | |
359 | struct sadb_x_policy *x_policy; /* SADB_X_EXT_POLICY */ | |
360 | struct sadb_x_sa2 *x_sa2; /* SADB_X_EXT_SA2 */ | |
361 | struct sadb_x_nat_t_type *x_natt_type; /* SADB_X_EXT_NAT_T_TYPE */ | |
362 | struct sadb_x_nat_t_port *x_natt_sport; /* SADB_X_EXT_NAT_T_SPORT */ | |
363 | struct sadb_x_nat_t_port *x_natt_dport; /* SADB_X_EXT_NAT_T_DPORT */ | |
364 | struct sadb_address *x_natt_oa; /* SADB_X_EXT_NAT_T_OA */ | |
365 | struct sadb_x_sec_ctx *x_sec_ctx; /* SADB_X_EXT_SEC_CTX */ | |
e526d228 | 366 | struct sadb_x_kmaddress *x_kmaddress; /* SADB_X_EXT_KMADDRESS */ |
1adaa02b TB |
367 | } __attribute__((__packed__)); |
368 | }; | |
369 | }; | |
370 | ||
d24a74c5 | 371 | ENUM(sadb_ext_type_names, SADB_EXT_RESERVED, SADB_EXT_MAX, |
e526d228 AS |
372 | "SADB_EXT_RESERVED", |
373 | "SADB_EXT_SA", | |
374 | "SADB_EXT_LIFETIME_CURRENT", | |
375 | "SADB_EXT_LIFETIME_HARD", | |
376 | "SADB_EXT_LIFETIME_SOFT", | |
377 | "SADB_EXT_ADDRESS_SRC", | |
378 | "SADB_EXT_ADDRESS_DST", | |
379 | "SADB_EXT_ADDRESS_PROXY", | |
380 | "SADB_EXT_KEY_AUTH", | |
381 | "SADB_EXT_KEY_ENCRYPT", | |
382 | "SADB_EXT_IDENTITY_SRC", | |
383 | "SADB_EXT_IDENTITY_DST", | |
384 | "SADB_EXT_SENSITIVITY", | |
385 | "SADB_EXT_PROPOSAL", | |
386 | "SADB_EXT_SUPPORTED_AUTH", | |
387 | "SADB_EXT_SUPPORTED_ENCRYPT", | |
388 | "SADB_EXT_SPIRANGE", | |
389 | "SADB_X_EXT_KMPRIVATE", | |
390 | "SADB_X_EXT_POLICY", | |
391 | "SADB_X_EXT_SA2", | |
392 | "SADB_X_EXT_NAT_T_TYPE", | |
393 | "SADB_X_EXT_NAT_T_SPORT", | |
394 | "SADB_X_EXT_NAT_T_DPORT", | |
395 | "SADB_X_EXT_NAT_T_OA", | |
396 | "SADB_X_EXT_SEC_CTX", | |
397 | "SADB_X_EXT_KMADDRESS" | |
398 | ); | |
d24a74c5 | 399 | |
1adaa02b TB |
400 | /** |
401 | * convert a IKEv2 specific protocol identifier to the PF_KEY sa type | |
402 | */ | |
403 | static u_int8_t proto_ike2satype(protocol_id_t proto) | |
404 | { | |
405 | switch (proto) | |
406 | { | |
407 | case PROTO_ESP: | |
408 | return SADB_SATYPE_ESP; | |
409 | case PROTO_AH: | |
410 | return SADB_SATYPE_AH; | |
411 | case IPPROTO_COMP: | |
412 | return SADB_X_SATYPE_IPCOMP; | |
413 | default: | |
414 | return proto; | |
415 | } | |
416 | } | |
417 | ||
418 | /** | |
419 | * convert a PF_KEY sa type to a IKEv2 specific protocol identifier | |
420 | */ | |
421 | static protocol_id_t proto_satype2ike(u_int8_t proto) | |
422 | { | |
423 | switch (proto) | |
424 | { | |
425 | case SADB_SATYPE_ESP: | |
426 | return PROTO_ESP; | |
427 | case SADB_SATYPE_AH: | |
428 | return PROTO_AH; | |
429 | case SADB_X_SATYPE_IPCOMP: | |
430 | return IPPROTO_COMP; | |
431 | default: | |
432 | return proto; | |
433 | } | |
434 | } | |
435 | ||
436 | /** | |
437 | * convert a IKEv2 specific protocol identifier to the IP protocol identifier | |
438 | */ | |
439 | static u_int8_t proto_ike2ip(protocol_id_t proto) | |
440 | { | |
441 | switch (proto) | |
442 | { | |
443 | case PROTO_ESP: | |
444 | return IPPROTO_ESP; | |
445 | case PROTO_AH: | |
446 | return IPPROTO_AH; | |
447 | default: | |
448 | return proto; | |
449 | } | |
450 | } | |
451 | ||
452 | /** | |
453 | * convert the general ipsec mode to the one defined in ipsec.h | |
454 | */ | |
455 | static u_int8_t mode2kernel(ipsec_mode_t mode) | |
456 | { | |
457 | switch (mode) | |
458 | { | |
459 | case MODE_TRANSPORT: | |
460 | return IPSEC_MODE_TRANSPORT; | |
461 | case MODE_TUNNEL: | |
462 | return IPSEC_MODE_TUNNEL; | |
617e59b7 | 463 | #ifdef HAVE_IPSEC_MODE_BEET |
1adaa02b TB |
464 | case MODE_BEET: |
465 | return IPSEC_MODE_BEET; | |
d24a74c5 | 466 | #endif |
1adaa02b TB |
467 | default: |
468 | return mode; | |
469 | } | |
470 | } | |
471 | ||
472 | /** | |
473 | * convert the general policy direction to the one defined in ipsec.h | |
474 | */ | |
475 | static u_int8_t dir2kernel(policy_dir_t dir) | |
476 | { | |
477 | switch (dir) | |
478 | { | |
479 | case POLICY_IN: | |
480 | return IPSEC_DIR_INBOUND; | |
481 | case POLICY_OUT: | |
482 | return IPSEC_DIR_OUTBOUND; | |
617e59b7 | 483 | #ifdef HAVE_IPSEC_DIR_FWD |
1adaa02b TB |
484 | case POLICY_FWD: |
485 | return IPSEC_DIR_FWD; | |
d24a74c5 | 486 | #endif |
1adaa02b | 487 | default: |
eab05274 | 488 | return IPSEC_DIR_INVALID; |
1adaa02b TB |
489 | } |
490 | } | |
491 | ||
d24a74c5 | 492 | #ifdef SADB_X_MIGRATE |
5145ae48 AS |
493 | /** |
494 | * convert the policy direction in ipsec.h to the general one. | |
495 | */ | |
496 | static policy_dir_t kernel2dir(u_int8_t dir) | |
497 | { | |
498 | switch (dir) | |
499 | { | |
500 | case IPSEC_DIR_INBOUND: | |
501 | return POLICY_IN; | |
502 | case IPSEC_DIR_OUTBOUND: | |
503 | return POLICY_OUT; | |
617e59b7 | 504 | #ifdef HAVE_IPSEC_DIR_FWD |
5145ae48 AS |
505 | case IPSEC_DIR_FWD: |
506 | return POLICY_FWD; | |
d24a74c5 | 507 | #endif |
5145ae48 AS |
508 | default: |
509 | return dir; | |
510 | } | |
511 | } | |
d24a74c5 TB |
512 | #endif /*SADB_X_MIGRATE*/ |
513 | ||
1adaa02b TB |
514 | typedef struct kernel_algorithm_t kernel_algorithm_t; |
515 | ||
516 | /** | |
e517b4b1 | 517 | * Mapping of IKEv2 algorithms to PF_KEY algorithms |
1adaa02b TB |
518 | */ |
519 | struct kernel_algorithm_t { | |
520 | /** | |
521 | * Identifier specified in IKEv2 | |
522 | */ | |
e517b4b1 | 523 | int ikev2; |
7daf5226 | 524 | |
1adaa02b TB |
525 | /** |
526 | * Identifier as defined in pfkeyv2.h | |
527 | */ | |
e517b4b1 | 528 | int kernel; |
1adaa02b TB |
529 | }; |
530 | ||
531 | #define END_OF_LIST -1 | |
532 | ||
533 | /** | |
534 | * Algorithms for encryption | |
535 | */ | |
536 | static kernel_algorithm_t encryption_algs[] = { | |
d24a74c5 TB |
537 | /* {ENCR_DES_IV64, 0 }, */ |
538 | {ENCR_DES, SADB_EALG_DESCBC }, | |
539 | {ENCR_3DES, SADB_EALG_3DESCBC }, | |
540 | /* {ENCR_RC5, 0 }, */ | |
541 | /* {ENCR_IDEA, 0 }, */ | |
542 | {ENCR_CAST, SADB_X_EALG_CASTCBC }, | |
543 | {ENCR_BLOWFISH, SADB_X_EALG_BLOWFISHCBC }, | |
544 | /* {ENCR_3IDEA, 0 }, */ | |
545 | /* {ENCR_DES_IV32, 0 }, */ | |
546 | {ENCR_NULL, SADB_EALG_NULL }, | |
547 | {ENCR_AES_CBC, SADB_X_EALG_AESCBC }, | |
548 | /* {ENCR_AES_CTR, SADB_X_EALG_AESCTR }, */ | |
e526d228 AS |
549 | /* {ENCR_AES_CCM_ICV8, SADB_X_EALG_AES_CCM_ICV8 }, */ |
550 | /* {ENCR_AES_CCM_ICV12, SADB_X_EALG_AES_CCM_ICV12 }, */ | |
551 | /* {ENCR_AES_CCM_ICV16, SADB_X_EALG_AES_CCM_ICV16 }, */ | |
552 | /* {ENCR_AES_GCM_ICV8, SADB_X_EALG_AES_GCM_ICV8 }, */ | |
553 | /* {ENCR_AES_GCM_ICV12, SADB_X_EALG_AES_GCM_ICV12 }, */ | |
554 | /* {ENCR_AES_GCM_ICV16, SADB_X_EALG_AES_GCM_ICV16 }, */ | |
d24a74c5 | 555 | {END_OF_LIST, 0 }, |
1adaa02b TB |
556 | }; |
557 | ||
558 | /** | |
559 | * Algorithms for integrity protection | |
560 | */ | |
561 | static kernel_algorithm_t integrity_algs[] = { | |
d24a74c5 | 562 | {AUTH_HMAC_MD5_96, SADB_AALG_MD5HMAC }, |
e517b4b1 MW |
563 | {AUTH_HMAC_SHA1_96, SADB_AALG_SHA1HMAC }, |
564 | {AUTH_HMAC_SHA2_256_128, SADB_X_AALG_SHA2_256HMAC }, | |
565 | {AUTH_HMAC_SHA2_384_192, SADB_X_AALG_SHA2_384HMAC }, | |
566 | {AUTH_HMAC_SHA2_512_256, SADB_X_AALG_SHA2_512HMAC }, | |
567 | /* {AUTH_DES_MAC, 0, }, */ | |
568 | /* {AUTH_KPDK_MD5, 0, }, */ | |
7cdb1ddf | 569 | #ifdef SADB_X_AALG_AES_XCBC_MAC |
e517b4b1 | 570 | {AUTH_AES_XCBC_96, SADB_X_AALG_AES_XCBC_MAC, }, |
7cdb1ddf | 571 | #endif |
d24a74c5 | 572 | {END_OF_LIST, 0, }, |
1adaa02b TB |
573 | }; |
574 | ||
3d2dbebd | 575 | #if 0 |
1adaa02b | 576 | /** |
3d2dbebd | 577 | * Algorithms for IPComp, unused yet |
1adaa02b TB |
578 | */ |
579 | static kernel_algorithm_t compression_algs[] = { | |
d24a74c5 | 580 | /* {IPCOMP_OUI, 0 }, */ |
e517b4b1 MW |
581 | {IPCOMP_DEFLATE, SADB_X_CALG_DEFLATE }, |
582 | {IPCOMP_LZS, SADB_X_CALG_LZS }, | |
583 | {IPCOMP_LZJH, SADB_X_CALG_LZJH }, | |
d24a74c5 | 584 | {END_OF_LIST, 0 }, |
1adaa02b | 585 | }; |
3d2dbebd | 586 | #endif |
1adaa02b TB |
587 | |
588 | /** | |
589 | * Look up a kernel algorithm ID and its key size | |
590 | */ | |
e517b4b1 | 591 | static int lookup_algorithm(kernel_algorithm_t *list, int ikev2) |
1adaa02b | 592 | { |
e517b4b1 | 593 | while (list->ikev2 != END_OF_LIST) |
1adaa02b | 594 | { |
e517b4b1 | 595 | if (ikev2 == list->ikev2) |
1adaa02b | 596 | { |
e517b4b1 | 597 | return list->kernel; |
1adaa02b | 598 | } |
e517b4b1 | 599 | list++; |
1adaa02b TB |
600 | } |
601 | return 0; | |
602 | } | |
603 | ||
604 | /** | |
668e84d9 TB |
605 | * Copy a host_t as sockaddr_t to the given memory location. Ports are |
606 | * reset to zero as per RFC 2367. | |
607 | * @return the number of bytes copied | |
1adaa02b | 608 | */ |
668e84d9 | 609 | static size_t hostcpy(void *dest, host_t *host) |
1adaa02b | 610 | { |
668e84d9 | 611 | sockaddr_t *addr = host->get_sockaddr(host), *dest_addr = dest; |
1adaa02b | 612 | socklen_t *len = host->get_sockaddr_len(host); |
668e84d9 | 613 | memcpy(dest, addr, *len); |
d24a74c5 | 614 | #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN |
668e84d9 | 615 | dest_addr->sa_len = *len; |
d24a74c5 | 616 | #endif |
668e84d9 TB |
617 | switch (dest_addr->sa_family) |
618 | { | |
619 | case AF_INET: | |
620 | { | |
621 | struct sockaddr_in *sin = dest; | |
622 | sin->sin_port = 0; | |
623 | break; | |
624 | } | |
625 | case AF_INET6: | |
626 | { | |
627 | struct sockaddr_in6 *sin6 = dest; | |
628 | sin6->sin6_port = 0; | |
629 | break; | |
630 | } | |
631 | } | |
632 | return *len; | |
633 | } | |
634 | ||
635 | /** | |
636 | * add a host behind an sadb_address extension | |
637 | */ | |
638 | static void host2ext(host_t *host, struct sadb_address *ext) | |
639 | { | |
640 | size_t len = hostcpy(ext + 1, host); | |
641 | ext->sadb_address_len = PFKEY_LEN(sizeof(*ext) + len); | |
1adaa02b TB |
642 | } |
643 | ||
f55a7a76 TB |
644 | /** |
645 | * add a host to the given sadb_msg | |
646 | */ | |
647 | static void add_addr_ext(struct sadb_msg *msg, host_t *host, u_int16_t type, | |
648 | u_int8_t proto, u_int8_t prefixlen) | |
649 | { | |
650 | struct sadb_address *addr = (struct sadb_address*)PFKEY_EXT_ADD_NEXT(msg); | |
651 | addr->sadb_address_exttype = type; | |
652 | addr->sadb_address_proto = proto; | |
653 | addr->sadb_address_prefixlen = prefixlen; | |
654 | host2ext(host, addr); | |
655 | PFKEY_EXT_ADD(msg, addr); | |
656 | } | |
657 | ||
658 | /** | |
659 | * adds an empty address extension to the given sadb_msg | |
660 | */ | |
661 | static void add_anyaddr_ext(struct sadb_msg *msg, int family, u_int8_t type) | |
662 | { | |
663 | socklen_t len = (family == AF_INET) ? sizeof(struct sockaddr_in) : | |
664 | sizeof(struct sockaddr_in6); | |
665 | struct sadb_address *addr = (struct sadb_address*)PFKEY_EXT_ADD_NEXT(msg); | |
666 | addr->sadb_address_exttype = type; | |
667 | sockaddr_t *saddr = (sockaddr_t*)(addr + 1); | |
668 | saddr->sa_family = family; | |
d24a74c5 TB |
669 | #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN |
670 | saddr->sa_len = len; | |
671 | #endif | |
672 | addr->sadb_address_len = PFKEY_LEN(sizeof(*addr) + len); | |
f55a7a76 TB |
673 | PFKEY_EXT_ADD(msg, addr); |
674 | } | |
675 | ||
d24a74c5 | 676 | #ifdef HAVE_NATT |
1adaa02b TB |
677 | /** |
678 | * add udp encap extensions to a sadb_msg | |
679 | */ | |
680 | static void add_encap_ext(struct sadb_msg *msg, host_t *src, host_t *dst) | |
681 | { | |
682 | struct sadb_x_nat_t_type* nat_type; | |
683 | struct sadb_x_nat_t_port* nat_port; | |
7daf5226 | 684 | |
1adaa02b TB |
685 | nat_type = (struct sadb_x_nat_t_type*)PFKEY_EXT_ADD_NEXT(msg); |
686 | nat_type->sadb_x_nat_t_type_exttype = SADB_X_EXT_NAT_T_TYPE; | |
687 | nat_type->sadb_x_nat_t_type_len = PFKEY_LEN(sizeof(struct sadb_x_nat_t_type)); | |
688 | nat_type->sadb_x_nat_t_type_type = UDP_ENCAP_ESPINUDP; | |
689 | PFKEY_EXT_ADD(msg, nat_type); | |
7daf5226 | 690 | |
1adaa02b TB |
691 | nat_port = (struct sadb_x_nat_t_port*)PFKEY_EXT_ADD_NEXT(msg); |
692 | nat_port->sadb_x_nat_t_port_exttype = SADB_X_EXT_NAT_T_SPORT; | |
693 | nat_port->sadb_x_nat_t_port_len = PFKEY_LEN(sizeof(struct sadb_x_nat_t_port)); | |
694 | nat_port->sadb_x_nat_t_port_port = htons(src->get_port(src)); | |
695 | PFKEY_EXT_ADD(msg, nat_port); | |
7daf5226 | 696 | |
1adaa02b TB |
697 | nat_port = (struct sadb_x_nat_t_port*)PFKEY_EXT_ADD_NEXT(msg); |
698 | nat_port->sadb_x_nat_t_port_exttype = SADB_X_EXT_NAT_T_DPORT; | |
699 | nat_port->sadb_x_nat_t_port_len = PFKEY_LEN(sizeof(struct sadb_x_nat_t_port)); | |
700 | nat_port->sadb_x_nat_t_port_port = htons(dst->get_port(dst)); | |
701 | PFKEY_EXT_ADD(msg, nat_port); | |
702 | } | |
d24a74c5 | 703 | #endif /*HAVE_NATT*/ |
1adaa02b | 704 | |
e526d228 AS |
705 | /** |
706 | * Convert a sadb_address to a traffic_selector | |
707 | */ | |
708 | static traffic_selector_t* sadb_address2ts(struct sadb_address *address) | |
709 | { | |
710 | traffic_selector_t *ts; | |
e526d228 | 711 | host_t *host; |
e526d228 AS |
712 | |
713 | /* The Linux 2.6 kernel does not set the protocol and port information | |
323f9f99 MW |
714 | * in the src and dst sadb_address extensions of the SADB_ACQUIRE message. |
715 | */ | |
e526d228 | 716 | host = host_create_from_sockaddr((sockaddr_t*)&address[1]) ; |
5145ae48 | 717 | ts = traffic_selector_create_from_subnet(host, address->sadb_address_prefixlen, |
d24a74c5 | 718 | address->sadb_address_proto, host->get_port(host)); |
e526d228 AS |
719 | return ts; |
720 | } | |
721 | ||
1adaa02b TB |
722 | /** |
723 | * Parses a pfkey message received from the kernel | |
724 | */ | |
725 | static status_t parse_pfkey_message(struct sadb_msg *msg, pfkey_msg_t *out) | |
726 | { | |
727 | struct sadb_ext* ext; | |
728 | size_t len; | |
7daf5226 | 729 | |
1adaa02b TB |
730 | memset(out, 0, sizeof(pfkey_msg_t)); |
731 | out->msg = msg; | |
7daf5226 | 732 | |
1adaa02b TB |
733 | len = msg->sadb_msg_len; |
734 | len -= PFKEY_LEN(sizeof(struct sadb_msg)); | |
7daf5226 | 735 | |
1adaa02b | 736 | ext = (struct sadb_ext*)(((char*)msg) + sizeof(struct sadb_msg)); |
7daf5226 | 737 | |
1adaa02b TB |
738 | while (len >= PFKEY_LEN(sizeof(struct sadb_ext))) |
739 | { | |
bfca7aa5 | 740 | DBG3(DBG_KNL, " %N", sadb_ext_type_names, ext->sadb_ext_type); |
1adaa02b TB |
741 | if (ext->sadb_ext_len < PFKEY_LEN(sizeof(struct sadb_ext)) || |
742 | ext->sadb_ext_len > len) | |
743 | { | |
e526d228 AS |
744 | DBG1(DBG_KNL, "length of %N extension is invalid", |
745 | sadb_ext_type_names, ext->sadb_ext_type); | |
1adaa02b TB |
746 | break; |
747 | } | |
7daf5226 | 748 | |
1adaa02b TB |
749 | if ((ext->sadb_ext_type > SADB_EXT_MAX) || (!ext->sadb_ext_type)) |
750 | { | |
751 | DBG1(DBG_KNL, "type of PF_KEY extension (%d) is invalid", ext->sadb_ext_type); | |
752 | break; | |
753 | } | |
7daf5226 | 754 | |
1adaa02b TB |
755 | if (out->ext[ext->sadb_ext_type]) |
756 | { | |
d24a74c5 | 757 | DBG1(DBG_KNL, "duplicate %N extension", |
e526d228 | 758 | sadb_ext_type_names, ext->sadb_ext_type); |
1adaa02b TB |
759 | break; |
760 | } | |
7daf5226 | 761 | |
1adaa02b TB |
762 | out->ext[ext->sadb_ext_type] = ext; |
763 | ext = PFKEY_EXT_NEXT_LEN(ext, len); | |
764 | } | |
765 | ||
766 | if (len) | |
767 | { | |
768 | DBG1(DBG_KNL, "PF_KEY message length is invalid"); | |
769 | return FAILED; | |
770 | } | |
7daf5226 | 771 | |
1adaa02b TB |
772 | return SUCCESS; |
773 | } | |
774 | ||
775 | /** | |
776 | * Send a message to a specific PF_KEY socket and handle the response. | |
777 | */ | |
778 | static status_t pfkey_send_socket(private_kernel_pfkey_ipsec_t *this, int socket, | |
779 | struct sadb_msg *in, struct sadb_msg **out, size_t *out_len) | |
780 | { | |
781 | unsigned char buf[PFKEY_BUFFER_SIZE]; | |
782 | struct sadb_msg *msg; | |
783 | int in_len, len; | |
7daf5226 | 784 | |
3ac5a0db | 785 | this->mutex_pfkey->lock(this->mutex_pfkey); |
1adaa02b | 786 | |
56ee8fcc TB |
787 | /* FIXME: our usage of sequence numbers is probably wrong. check RFC 2367, |
788 | * in particular the behavior in response to an SADB_ACQUIRE. */ | |
1adaa02b TB |
789 | in->sadb_msg_seq = ++this->seq; |
790 | in->sadb_msg_pid = getpid(); | |
791 | ||
792 | in_len = PFKEY_USER_LEN(in->sadb_msg_len); | |
793 | ||
794 | while (TRUE) | |
795 | { | |
796 | len = send(socket, in, in_len, 0); | |
797 | ||
798 | if (len != in_len) | |
799 | { | |
800 | if (errno == EINTR) | |
801 | { | |
802 | /* interrupted, try again */ | |
803 | continue; | |
804 | } | |
3ac5a0db | 805 | this->mutex_pfkey->unlock(this->mutex_pfkey); |
1adaa02b TB |
806 | DBG1(DBG_KNL, "error sending to PF_KEY socket: %s", strerror(errno)); |
807 | return FAILED; | |
808 | } | |
809 | break; | |
810 | } | |
7daf5226 | 811 | |
1adaa02b | 812 | while (TRUE) |
d24a74c5 | 813 | { |
1adaa02b | 814 | msg = (struct sadb_msg*)buf; |
7daf5226 | 815 | |
1adaa02b | 816 | len = recv(socket, buf, sizeof(buf), 0); |
7daf5226 | 817 | |
1adaa02b TB |
818 | if (len < 0) |
819 | { | |
820 | if (errno == EINTR) | |
821 | { | |
822 | DBG1(DBG_KNL, "got interrupted"); | |
823 | /* interrupted, try again */ | |
824 | continue; | |
825 | } | |
826 | DBG1(DBG_KNL, "error reading from PF_KEY socket: %s", strerror(errno)); | |
3ac5a0db | 827 | this->mutex_pfkey->unlock(this->mutex_pfkey); |
1adaa02b TB |
828 | return FAILED; |
829 | } | |
830 | if (len < sizeof(struct sadb_msg) || | |
831 | msg->sadb_msg_len < PFKEY_LEN(sizeof(struct sadb_msg))) | |
832 | { | |
833 | DBG1(DBG_KNL, "received corrupted PF_KEY message"); | |
3ac5a0db | 834 | this->mutex_pfkey->unlock(this->mutex_pfkey); |
1adaa02b TB |
835 | return FAILED; |
836 | } | |
837 | if (msg->sadb_msg_len > len / PFKEY_ALIGNMENT) | |
838 | { | |
839 | DBG1(DBG_KNL, "buffer was too small to receive the complete PF_KEY message"); | |
3ac5a0db | 840 | this->mutex_pfkey->unlock(this->mutex_pfkey); |
1adaa02b TB |
841 | return FAILED; |
842 | } | |
843 | if (msg->sadb_msg_pid != in->sadb_msg_pid) | |
844 | { | |
845 | DBG2(DBG_KNL, "received PF_KEY message is not intended for us"); | |
846 | continue; | |
847 | } | |
848 | if (msg->sadb_msg_seq != this->seq) | |
849 | { | |
56ee8fcc TB |
850 | DBG1(DBG_KNL, "received PF_KEY message with unexpected sequence " |
851 | "number, was %d expected %d", msg->sadb_msg_seq, this->seq); | |
852 | if (msg->sadb_msg_seq == 0) | |
853 | { | |
854 | /* FreeBSD and Mac OS X do this for the response to | |
855 | * SADB_X_SPDGET (but not for the response to SADB_GET). | |
856 | * FreeBSD: 'key_spdget' in /usr/src/sys/netipsec/key.c. */ | |
857 | } | |
858 | else if (msg->sadb_msg_seq < this->seq) | |
1adaa02b TB |
859 | { |
860 | continue; | |
861 | } | |
56ee8fcc TB |
862 | else |
863 | { | |
864 | this->mutex_pfkey->unlock(this->mutex_pfkey); | |
865 | return FAILED; | |
866 | } | |
1adaa02b TB |
867 | } |
868 | if (msg->sadb_msg_type != in->sadb_msg_type) | |
869 | { | |
870 | DBG2(DBG_KNL, "received PF_KEY message of wrong type, " | |
871 | "was %d expected %d, ignoring", | |
872 | msg->sadb_msg_type, in->sadb_msg_type); | |
873 | } | |
874 | break; | |
875 | } | |
7daf5226 | 876 | |
1adaa02b TB |
877 | *out_len = len; |
878 | *out = (struct sadb_msg*)malloc(len); | |
879 | memcpy(*out, buf, len); | |
7daf5226 | 880 | |
3ac5a0db | 881 | this->mutex_pfkey->unlock(this->mutex_pfkey); |
7daf5226 | 882 | |
1adaa02b TB |
883 | return SUCCESS; |
884 | } | |
885 | ||
886 | /** | |
887 | * Send a message to the default PF_KEY socket and handle the response. | |
888 | */ | |
889 | static status_t pfkey_send(private_kernel_pfkey_ipsec_t *this, | |
890 | struct sadb_msg *in, struct sadb_msg **out, size_t *out_len) | |
891 | { | |
892 | return pfkey_send_socket(this, this->socket, in, out, out_len); | |
893 | } | |
894 | ||
895 | /** | |
896 | * Process a SADB_ACQUIRE message from the kernel | |
897 | */ | |
898 | static void process_acquire(private_kernel_pfkey_ipsec_t *this, struct sadb_msg* msg) | |
899 | { | |
900 | pfkey_msg_t response; | |
e526d228 AS |
901 | u_int32_t index, reqid = 0; |
902 | traffic_selector_t *src_ts, *dst_ts; | |
1adaa02b TB |
903 | policy_entry_t *policy; |
904 | job_t *job; | |
7daf5226 | 905 | |
1adaa02b TB |
906 | switch (msg->sadb_msg_satype) |
907 | { | |
908 | case SADB_SATYPE_UNSPEC: | |
909 | case SADB_SATYPE_ESP: | |
910 | case SADB_SATYPE_AH: | |
911 | break; | |
912 | default: | |
913 | /* acquire for AH/ESP only */ | |
914 | return; | |
915 | } | |
e526d228 | 916 | DBG2(DBG_KNL, "received an SADB_ACQUIRE"); |
7daf5226 | 917 | |
1adaa02b TB |
918 | if (parse_pfkey_message(msg, &response) != SUCCESS) |
919 | { | |
920 | DBG1(DBG_KNL, "parsing SADB_ACQUIRE from kernel failed"); | |
921 | return; | |
922 | } | |
7daf5226 | 923 | |
1adaa02b | 924 | index = response.x_policy->sadb_x_policy_id; |
3ac5a0db | 925 | this->mutex->lock(this->mutex); |
1adaa02b | 926 | if (this->policies->find_first(this->policies, |
e526d228 | 927 | (linked_list_match_t)policy_entry_match_byindex, (void**)&policy, &index) == SUCCESS) |
1adaa02b | 928 | { |
e526d228 AS |
929 | reqid = policy->reqid; |
930 | } | |
931 | else | |
932 | { | |
933 | DBG1(DBG_KNL, "received an SADB_ACQUIRE with policy id %d but no matching policy found", | |
934 | index); | |
1adaa02b | 935 | } |
e526d228 AS |
936 | src_ts = sadb_address2ts(response.src); |
937 | dst_ts = sadb_address2ts(response.dst); | |
3ac5a0db | 938 | this->mutex->unlock(this->mutex); |
7daf5226 | 939 | |
ef6d339c AS |
940 | DBG1(DBG_KNL, "creating acquire job for policy %R === %R with reqid {%u}", |
941 | src_ts, dst_ts, reqid); | |
e526d228 | 942 | job = (job_t*)acquire_job_create(reqid, src_ts, dst_ts); |
1adaa02b TB |
943 | charon->processor->queue_job(charon->processor, job); |
944 | } | |
945 | ||
946 | /** | |
947 | * Process a SADB_EXPIRE message from the kernel | |
948 | */ | |
949 | static void process_expire(private_kernel_pfkey_ipsec_t *this, struct sadb_msg* msg) | |
950 | { | |
951 | pfkey_msg_t response; | |
952 | protocol_id_t protocol; | |
953 | u_int32_t spi, reqid; | |
954 | bool hard; | |
955 | job_t *job; | |
7daf5226 | 956 | |
1adaa02b | 957 | DBG2(DBG_KNL, "received an SADB_EXPIRE"); |
7daf5226 | 958 | |
1adaa02b TB |
959 | if (parse_pfkey_message(msg, &response) != SUCCESS) |
960 | { | |
961 | DBG1(DBG_KNL, "parsing SADB_EXPIRE from kernel failed"); | |
962 | return; | |
963 | } | |
7daf5226 | 964 | |
1adaa02b TB |
965 | protocol = proto_satype2ike(msg->sadb_msg_satype); |
966 | spi = response.sa->sadb_sa_spi; | |
967 | reqid = response.x_sa2->sadb_x_sa2_reqid; | |
968 | hard = response.lft_hard != NULL; | |
7daf5226 | 969 | |
1adaa02b TB |
970 | if (protocol != PROTO_ESP && protocol != PROTO_AH) |
971 | { | |
ef6d339c | 972 | DBG2(DBG_KNL, "ignoring SADB_EXPIRE for SA with SPI %.8x and reqid {%u} " |
1adaa02b TB |
973 | "which is not a CHILD_SA", ntohl(spi), reqid); |
974 | return; | |
975 | } | |
7daf5226 | 976 | |
ef6d339c | 977 | DBG1(DBG_KNL, "creating %s job for %N CHILD_SA with SPI %.8x and reqid {%u}", |
1adaa02b TB |
978 | hard ? "delete" : "rekey", protocol_id_names, |
979 | protocol, ntohl(spi), reqid); | |
980 | if (hard) | |
981 | { | |
982 | job = (job_t*)delete_child_sa_job_create(reqid, protocol, spi); | |
983 | } | |
984 | else | |
985 | { | |
986 | job = (job_t*)rekey_child_sa_job_create(reqid, protocol, spi); | |
987 | } | |
988 | charon->processor->queue_job(charon->processor, job); | |
989 | } | |
990 | ||
d24a74c5 | 991 | #ifdef SADB_X_MIGRATE |
e526d228 | 992 | /** |
d24a74c5 | 993 | * Process a SADB_X_MIGRATE message from the kernel |
e526d228 AS |
994 | */ |
995 | static void process_migrate(private_kernel_pfkey_ipsec_t *this, struct sadb_msg* msg) | |
996 | { | |
997 | pfkey_msg_t response; | |
5145ae48 AS |
998 | traffic_selector_t *src_ts, *dst_ts; |
999 | policy_dir_t dir; | |
f11a54bc AS |
1000 | u_int32_t reqid = 0; |
1001 | host_t *local = NULL, *remote = NULL; | |
ef6d339c | 1002 | job_t *job; |
e526d228 AS |
1003 | |
1004 | DBG2(DBG_KNL, "received an SADB_X_MIGRATE"); | |
1005 | ||
1006 | if (parse_pfkey_message(msg, &response) != SUCCESS) | |
1007 | { | |
1008 | DBG1(DBG_KNL, "parsing SADB_X_MIGRATE from kernel failed"); | |
1009 | return; | |
1010 | } | |
5145ae48 AS |
1011 | src_ts = sadb_address2ts(response.src); |
1012 | dst_ts = sadb_address2ts(response.dst); | |
5145ae48 AS |
1013 | dir = kernel2dir(response.x_policy->sadb_x_policy_dir); |
1014 | DBG2(DBG_KNL, " policy %R === %R %N, id %u", src_ts, dst_ts, | |
7a915d62 | 1015 | policy_dir_names, dir); |
7daf5226 | 1016 | |
d24a74c5 | 1017 | /* SADB_X_EXT_KMADDRESS is not present in unpatched kernels < 2.6.28 */ |
f11a54bc AS |
1018 | if (response.x_kmaddress) |
1019 | { | |
1020 | sockaddr_t *local_addr, *remote_addr; | |
1021 | u_int32_t local_len; | |
1022 | ||
1023 | local_addr = (sockaddr_t*)&response.x_kmaddress[1]; | |
1024 | local = host_create_from_sockaddr(local_addr); | |
1025 | local_len = (local_addr->sa_family == AF_INET6)? | |
1026 | sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in); | |
1027 | remote_addr = (sockaddr_t*)((u_int8_t*)local_addr + local_len); | |
1028 | remote = host_create_from_sockaddr(remote_addr); | |
1029 | DBG2(DBG_KNL, " kmaddress: %H...%H", local, remote); | |
1030 | } | |
7daf5226 | 1031 | |
7a915d62 | 1032 | if (src_ts && dst_ts && local && remote) |
ef6d339c | 1033 | { |
bab075b1 | 1034 | DBG1(DBG_KNL, "creating migrate job for policy %R === %R %N with reqid {%u}", |
ef6d339c | 1035 | src_ts, dst_ts, policy_dir_names, dir, reqid, local); |
bab075b1 | 1036 | job = (job_t*)migrate_job_create(reqid, src_ts, dst_ts, dir, |
2c815393 | 1037 | local, remote); |
ef6d339c AS |
1038 | charon->processor->queue_job(charon->processor, job); |
1039 | } | |
1040 | else | |
1041 | { | |
1042 | DESTROY_IF(src_ts); | |
1043 | DESTROY_IF(dst_ts); | |
1044 | DESTROY_IF(local); | |
2c815393 | 1045 | DESTROY_IF(remote); |
ef6d339c | 1046 | } |
e526d228 | 1047 | } |
d24a74c5 | 1048 | #endif /*SADB_X_MIGRATE*/ |
e526d228 | 1049 | |
ed76b216 | 1050 | #ifdef SADB_X_NAT_T_NEW_MAPPING |
1adaa02b TB |
1051 | /** |
1052 | * Process a SADB_X_NAT_T_NEW_MAPPING message from the kernel | |
1053 | */ | |
1054 | static void process_mapping(private_kernel_pfkey_ipsec_t *this, struct sadb_msg* msg) | |
1055 | { | |
1056 | pfkey_msg_t response; | |
1057 | u_int32_t spi, reqid; | |
1058 | host_t *host; | |
1059 | job_t *job; | |
7daf5226 | 1060 | |
1adaa02b | 1061 | DBG2(DBG_KNL, "received an SADB_X_NAT_T_NEW_MAPPING"); |
7daf5226 | 1062 | |
1adaa02b TB |
1063 | if (parse_pfkey_message(msg, &response) != SUCCESS) |
1064 | { | |
1065 | DBG1(DBG_KNL, "parsing SADB_X_NAT_T_NEW_MAPPING from kernel failed"); | |
1066 | return; | |
1067 | } | |
7daf5226 | 1068 | |
1adaa02b TB |
1069 | if (!response.x_sa2) |
1070 | { | |
1071 | DBG1(DBG_KNL, "received SADB_X_NAT_T_NEW_MAPPING is missing required information"); | |
1072 | return; | |
1073 | } | |
7daf5226 | 1074 | |
1adaa02b TB |
1075 | spi = response.sa->sadb_sa_spi; |
1076 | reqid = response.x_sa2->sadb_x_sa2_reqid; | |
7daf5226 | 1077 | |
1adaa02b TB |
1078 | if (proto_satype2ike(msg->sadb_msg_satype) == PROTO_ESP) |
1079 | { | |
1080 | sockaddr_t *sa = (sockaddr_t*)(response.dst + 1); | |
1081 | switch (sa->sa_family) | |
1082 | { | |
1083 | case AF_INET: | |
1084 | { | |
1085 | struct sockaddr_in *sin = (struct sockaddr_in*)sa; | |
ea625fab | 1086 | sin->sin_port = htons(response.x_natt_dport->sadb_x_nat_t_port_port); |
1adaa02b TB |
1087 | } |
1088 | case AF_INET6: | |
1089 | { | |
1090 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)sa; | |
ea625fab | 1091 | sin6->sin6_port = htons(response.x_natt_dport->sadb_x_nat_t_port_port); |
1adaa02b TB |
1092 | } |
1093 | default: | |
1094 | break; | |
1095 | } | |
1096 | host = host_create_from_sockaddr(sa); | |
1097 | if (host) | |
1098 | { | |
1099 | DBG1(DBG_KNL, "NAT mappings of ESP CHILD_SA with SPI %.8x and " | |
ef6d339c | 1100 | "reqid {%u} changed, queuing update job", ntohl(spi), reqid); |
1adaa02b TB |
1101 | job = (job_t*)update_sa_job_create(reqid, host); |
1102 | charon->processor->queue_job(charon->processor, job); | |
1103 | } | |
1104 | } | |
1105 | } | |
ed76b216 | 1106 | #endif /*SADB_X_NAT_T_NEW_MAPPING*/ |
1adaa02b TB |
1107 | |
1108 | /** | |
1109 | * Receives events from kernel | |
1110 | */ | |
1111 | static job_requeue_t receive_events(private_kernel_pfkey_ipsec_t *this) | |
1112 | { | |
1113 | unsigned char buf[PFKEY_BUFFER_SIZE]; | |
1114 | struct sadb_msg *msg = (struct sadb_msg*)buf; | |
4a5a5dd2 TB |
1115 | int len; |
1116 | bool oldstate; | |
7daf5226 | 1117 | |
4a5a5dd2 | 1118 | oldstate = thread_cancelability(TRUE); |
d24a74c5 | 1119 | len = recvfrom(this->socket_events, buf, sizeof(buf), 0, NULL, 0); |
4a5a5dd2 | 1120 | thread_cancelability(oldstate); |
7daf5226 | 1121 | |
1adaa02b TB |
1122 | if (len < 0) |
1123 | { | |
1124 | switch (errno) | |
1125 | { | |
1126 | case EINTR: | |
1127 | /* interrupted, try again */ | |
1128 | return JOB_REQUEUE_DIRECT; | |
1129 | case EAGAIN: | |
1130 | /* no data ready, select again */ | |
1131 | return JOB_REQUEUE_DIRECT; | |
1132 | default: | |
1133 | DBG1(DBG_KNL, "unable to receive from PF_KEY event socket"); | |
1134 | sleep(1); | |
1135 | return JOB_REQUEUE_FAIR; | |
1136 | } | |
1137 | } | |
7daf5226 | 1138 | |
1adaa02b TB |
1139 | if (len < sizeof(struct sadb_msg) || |
1140 | msg->sadb_msg_len < PFKEY_LEN(sizeof(struct sadb_msg))) | |
1141 | { | |
1142 | DBG2(DBG_KNL, "received corrupted PF_KEY message"); | |
1143 | return JOB_REQUEUE_DIRECT; | |
1144 | } | |
1145 | if (msg->sadb_msg_pid != 0) | |
1146 | { /* not from kernel. not interested, try another one */ | |
1147 | return JOB_REQUEUE_DIRECT; | |
1148 | } | |
1149 | if (msg->sadb_msg_len > len / PFKEY_ALIGNMENT) | |
1150 | { | |
1151 | DBG1(DBG_KNL, "buffer was too small to receive the complete PF_KEY message"); | |
1152 | return JOB_REQUEUE_DIRECT; | |
1153 | } | |
7daf5226 | 1154 | |
1adaa02b TB |
1155 | switch (msg->sadb_msg_type) |
1156 | { | |
1157 | case SADB_ACQUIRE: | |
1158 | process_acquire(this, msg); | |
1159 | break; | |
1160 | case SADB_EXPIRE: | |
1161 | process_expire(this, msg); | |
1162 | break; | |
d24a74c5 | 1163 | #ifdef SADB_X_MIGRATE |
e526d228 AS |
1164 | case SADB_X_MIGRATE: |
1165 | process_migrate(this, msg); | |
1166 | break; | |
d24a74c5 | 1167 | #endif /*SADB_X_MIGRATE*/ |
ed76b216 | 1168 | #ifdef SADB_X_NAT_T_NEW_MAPPING |
1adaa02b TB |
1169 | case SADB_X_NAT_T_NEW_MAPPING: |
1170 | process_mapping(this, msg); | |
1171 | break; | |
ed76b216 | 1172 | #endif /*SADB_X_NAT_T_NEW_MAPPING*/ |
1adaa02b TB |
1173 | default: |
1174 | break; | |
1175 | } | |
7daf5226 | 1176 | |
1adaa02b TB |
1177 | return JOB_REQUEUE_DIRECT; |
1178 | } | |
1179 | ||
44791b75 MW |
1180 | METHOD(kernel_ipsec_t, get_spi, status_t, |
1181 | private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst, | |
1182 | protocol_id_t protocol, u_int32_t reqid, u_int32_t *spi) | |
1adaa02b TB |
1183 | { |
1184 | unsigned char request[PFKEY_BUFFER_SIZE]; | |
1185 | struct sadb_msg *msg, *out; | |
1adaa02b | 1186 | struct sadb_x_sa2 *sa2; |
1adaa02b TB |
1187 | struct sadb_spirange *range; |
1188 | pfkey_msg_t response; | |
1189 | u_int32_t received_spi = 0; | |
1190 | size_t len; | |
7daf5226 | 1191 | |
1adaa02b | 1192 | memset(&request, 0, sizeof(request)); |
7daf5226 | 1193 | |
1adaa02b TB |
1194 | msg = (struct sadb_msg*)request; |
1195 | msg->sadb_msg_version = PF_KEY_V2; | |
1196 | msg->sadb_msg_type = SADB_GETSPI; | |
1197 | msg->sadb_msg_satype = proto_ike2satype(protocol); | |
1198 | msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg)); | |
7daf5226 | 1199 | |
1adaa02b TB |
1200 | sa2 = (struct sadb_x_sa2*)PFKEY_EXT_ADD_NEXT(msg); |
1201 | sa2->sadb_x_sa2_exttype = SADB_X_EXT_SA2; | |
1202 | sa2->sadb_x_sa2_len = PFKEY_LEN(sizeof(struct sadb_spirange)); | |
1203 | sa2->sadb_x_sa2_reqid = reqid; | |
1204 | PFKEY_EXT_ADD(msg, sa2); | |
7daf5226 | 1205 | |
f55a7a76 TB |
1206 | add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0); |
1207 | add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0); | |
7daf5226 | 1208 | |
1adaa02b TB |
1209 | range = (struct sadb_spirange*)PFKEY_EXT_ADD_NEXT(msg); |
1210 | range->sadb_spirange_exttype = SADB_EXT_SPIRANGE; | |
1211 | range->sadb_spirange_len = PFKEY_LEN(sizeof(struct sadb_spirange)); | |
1212 | range->sadb_spirange_min = 0xc0000000; | |
1213 | range->sadb_spirange_max = 0xcFFFFFFF; | |
1214 | PFKEY_EXT_ADD(msg, range); | |
7daf5226 | 1215 | |
1adaa02b TB |
1216 | if (pfkey_send(this, msg, &out, &len) == SUCCESS) |
1217 | { | |
1218 | if (out->sadb_msg_errno) | |
1219 | { | |
1220 | DBG1(DBG_KNL, "allocating SPI failed: %s (%d)", | |
1221 | strerror(out->sadb_msg_errno), out->sadb_msg_errno); | |
1222 | } | |
1223 | else if (parse_pfkey_message(out, &response) == SUCCESS) | |
1224 | { | |
1225 | received_spi = response.sa->sadb_sa_spi; | |
1226 | } | |
d24a74c5 | 1227 | free(out); |
1adaa02b | 1228 | } |
7daf5226 | 1229 | |
1adaa02b TB |
1230 | if (received_spi == 0) |
1231 | { | |
1232 | return FAILED; | |
1233 | } | |
7daf5226 | 1234 | |
1adaa02b TB |
1235 | *spi = received_spi; |
1236 | return SUCCESS; | |
1237 | } | |
1238 | ||
44791b75 MW |
1239 | METHOD(kernel_ipsec_t, get_cpi, status_t, |
1240 | private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst, | |
1241 | u_int32_t reqid, u_int16_t *cpi) | |
1adaa02b TB |
1242 | { |
1243 | return FAILED; | |
1244 | } | |
1245 | ||
44791b75 MW |
1246 | METHOD(kernel_ipsec_t, add_sa, status_t, |
1247 | private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst, u_int32_t spi, | |
ee26c537 AS |
1248 | protocol_id_t protocol, u_int32_t reqid, mark_t mark, |
1249 | lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key, | |
1250 | u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, | |
1251 | u_int16_t ipcomp, u_int16_t cpi, bool encap, bool inbound, | |
1252 | traffic_selector_t *src_ts, traffic_selector_t *dst_ts) | |
1adaa02b TB |
1253 | { |
1254 | unsigned char request[PFKEY_BUFFER_SIZE]; | |
1255 | struct sadb_msg *msg, *out; | |
1256 | struct sadb_sa *sa; | |
1257 | struct sadb_x_sa2 *sa2; | |
1adaa02b TB |
1258 | struct sadb_lifetime *lft; |
1259 | struct sadb_key *key; | |
1260 | size_t len; | |
7daf5226 | 1261 | |
1adaa02b | 1262 | memset(&request, 0, sizeof(request)); |
7daf5226 | 1263 | |
ef6d339c | 1264 | DBG2(DBG_KNL, "adding SAD entry with SPI %.8x and reqid {%u}", ntohl(spi), reqid); |
7daf5226 | 1265 | |
1adaa02b TB |
1266 | msg = (struct sadb_msg*)request; |
1267 | msg->sadb_msg_version = PF_KEY_V2; | |
ea625fab | 1268 | msg->sadb_msg_type = inbound ? SADB_UPDATE : SADB_ADD; |
1adaa02b TB |
1269 | msg->sadb_msg_satype = proto_ike2satype(protocol); |
1270 | msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg)); | |
e20bd8b6 TB |
1271 | |
1272 | #ifdef __APPLE__ | |
1273 | if (encap) | |
1274 | { | |
1275 | struct sadb_sa_2 *sa_2; | |
1276 | sa_2 = (struct sadb_sa_2*)PFKEY_EXT_ADD_NEXT(msg); | |
1277 | sa_2->sadb_sa_natt_port = dst->get_port(dst); | |
1278 | sa = &sa_2->sa; | |
1279 | sa->sadb_sa_flags |= SADB_X_EXT_NATT; | |
1280 | len = sizeof(struct sadb_sa_2); | |
1281 | } | |
1282 | else | |
1283 | #endif | |
1284 | { | |
1285 | sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg); | |
1286 | len = sizeof(struct sadb_sa); | |
1287 | } | |
1adaa02b | 1288 | sa->sadb_sa_exttype = SADB_EXT_SA; |
e20bd8b6 | 1289 | sa->sadb_sa_len = PFKEY_LEN(len); |
1adaa02b TB |
1290 | sa->sadb_sa_spi = spi; |
1291 | sa->sadb_sa_replay = (protocol == IPPROTO_COMP) ? 0 : 32; | |
e517b4b1 MW |
1292 | sa->sadb_sa_auth = lookup_algorithm(integrity_algs, int_alg); |
1293 | sa->sadb_sa_encrypt = lookup_algorithm(encryption_algs, enc_alg); | |
1adaa02b | 1294 | PFKEY_EXT_ADD(msg, sa); |
7daf5226 | 1295 | |
1adaa02b TB |
1296 | sa2 = (struct sadb_x_sa2*)PFKEY_EXT_ADD_NEXT(msg); |
1297 | sa2->sadb_x_sa2_exttype = SADB_X_EXT_SA2; | |
1298 | sa2->sadb_x_sa2_len = PFKEY_LEN(sizeof(struct sadb_spirange)); | |
1299 | sa2->sadb_x_sa2_mode = mode2kernel(mode); | |
1300 | sa2->sadb_x_sa2_reqid = reqid; | |
1301 | PFKEY_EXT_ADD(msg, sa2); | |
7daf5226 | 1302 | |
f55a7a76 TB |
1303 | add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0); |
1304 | add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0); | |
7daf5226 | 1305 | |
1adaa02b TB |
1306 | lft = (struct sadb_lifetime*)PFKEY_EXT_ADD_NEXT(msg); |
1307 | lft->sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT; | |
1308 | lft->sadb_lifetime_len = PFKEY_LEN(sizeof(struct sadb_lifetime)); | |
e75f4237 TB |
1309 | lft->sadb_lifetime_allocations = lifetime->packets.rekey; |
1310 | lft->sadb_lifetime_bytes = lifetime->bytes.rekey; | |
1311 | lft->sadb_lifetime_addtime = lifetime->time.rekey; | |
1087b9ce | 1312 | lft->sadb_lifetime_usetime = 0; /* we only use addtime */ |
1adaa02b | 1313 | PFKEY_EXT_ADD(msg, lft); |
7daf5226 | 1314 | |
1adaa02b TB |
1315 | lft = (struct sadb_lifetime*)PFKEY_EXT_ADD_NEXT(msg); |
1316 | lft->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD; | |
1317 | lft->sadb_lifetime_len = PFKEY_LEN(sizeof(struct sadb_lifetime)); | |
e75f4237 TB |
1318 | lft->sadb_lifetime_allocations = lifetime->packets.life; |
1319 | lft->sadb_lifetime_bytes = lifetime->bytes.life; | |
1320 | lft->sadb_lifetime_addtime = lifetime->time.life; | |
1087b9ce | 1321 | lft->sadb_lifetime_usetime = 0; /* we only use addtime */ |
1adaa02b | 1322 | PFKEY_EXT_ADD(msg, lft); |
7daf5226 | 1323 | |
1adaa02b TB |
1324 | if (enc_alg != ENCR_UNDEFINED) |
1325 | { | |
1326 | if (!sa->sadb_sa_encrypt) | |
1327 | { | |
1328 | DBG1(DBG_KNL, "algorithm %N not supported by kernel!", | |
e517b4b1 | 1329 | encryption_algorithm_names, enc_alg); |
1adaa02b TB |
1330 | return FAILED; |
1331 | } | |
1332 | DBG2(DBG_KNL, " using encryption algorithm %N with key size %d", | |
e517b4b1 | 1333 | encryption_algorithm_names, enc_alg, enc_key.len * 8); |
7daf5226 | 1334 | |
1adaa02b TB |
1335 | key = (struct sadb_key*)PFKEY_EXT_ADD_NEXT(msg); |
1336 | key->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT; | |
e517b4b1 MW |
1337 | key->sadb_key_bits = enc_key.len * 8; |
1338 | key->sadb_key_len = PFKEY_LEN(sizeof(struct sadb_key) + enc_key.len); | |
1339 | memcpy(key + 1, enc_key.ptr, enc_key.len); | |
7daf5226 | 1340 | |
1adaa02b TB |
1341 | PFKEY_EXT_ADD(msg, key); |
1342 | } | |
7daf5226 | 1343 | |
1adaa02b TB |
1344 | if (int_alg != AUTH_UNDEFINED) |
1345 | { | |
1346 | if (!sa->sadb_sa_auth) | |
1347 | { | |
1348 | DBG1(DBG_KNL, "algorithm %N not supported by kernel!", | |
1349 | integrity_algorithm_names, int_alg); | |
1350 | return FAILED; | |
1351 | } | |
1352 | DBG2(DBG_KNL, " using integrity algorithm %N with key size %d", | |
e517b4b1 | 1353 | integrity_algorithm_names, int_alg, int_key.len * 8); |
7daf5226 | 1354 | |
1adaa02b TB |
1355 | key = (struct sadb_key*)PFKEY_EXT_ADD_NEXT(msg); |
1356 | key->sadb_key_exttype = SADB_EXT_KEY_AUTH; | |
e517b4b1 MW |
1357 | key->sadb_key_bits = int_key.len * 8; |
1358 | key->sadb_key_len = PFKEY_LEN(sizeof(struct sadb_key) + int_key.len); | |
1359 | memcpy(key + 1, int_key.ptr, int_key.len); | |
7daf5226 | 1360 | |
1adaa02b TB |
1361 | PFKEY_EXT_ADD(msg, key); |
1362 | } | |
7daf5226 | 1363 | |
1adaa02b TB |
1364 | if (ipcomp != IPCOMP_NONE) |
1365 | { | |
1366 | /*TODO*/ | |
1367 | } | |
d24a74c5 TB |
1368 | |
1369 | #ifdef HAVE_NATT | |
1adaa02b TB |
1370 | if (encap) |
1371 | { | |
1372 | add_encap_ext(msg, src, dst); | |
1373 | } | |
d24a74c5 | 1374 | #endif /*HAVE_NATT*/ |
7daf5226 | 1375 | |
1adaa02b TB |
1376 | if (pfkey_send(this, msg, &out, &len) != SUCCESS) |
1377 | { | |
1378 | DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x", ntohl(spi)); | |
1379 | return FAILED; | |
1380 | } | |
1381 | else if (out->sadb_msg_errno) | |
1382 | { | |
1383 | DBG1(DBG_KNL, "unable to add SAD entry with SPI %.8x: %s (%d)", | |
1384 | ntohl(spi), strerror(out->sadb_msg_errno), out->sadb_msg_errno); | |
1385 | free(out); | |
1386 | return FAILED; | |
1387 | } | |
7daf5226 | 1388 | |
1adaa02b TB |
1389 | free(out); |
1390 | return SUCCESS; | |
1391 | } | |
1392 | ||
44791b75 MW |
1393 | METHOD(kernel_ipsec_t, update_sa, status_t, |
1394 | private_kernel_pfkey_ipsec_t *this, u_int32_t spi, protocol_id_t protocol, | |
1395 | u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst, | |
ee26c537 | 1396 | bool encap, bool new_encap, mark_t mark) |
1adaa02b TB |
1397 | { |
1398 | unsigned char request[PFKEY_BUFFER_SIZE]; | |
1399 | struct sadb_msg *msg, *out; | |
1400 | struct sadb_sa *sa; | |
1adaa02b TB |
1401 | pfkey_msg_t response; |
1402 | size_t len; | |
7daf5226 | 1403 | |
ea625fab TB |
1404 | /* we can't update the SA if any of the ip addresses have changed. |
1405 | * that's because we can't use SADB_UPDATE and by deleting and readding the | |
1406 | * SA the sequence numbers would get lost */ | |
1407 | if (!src->ip_equals(src, new_src) || | |
1408 | !dst->ip_equals(dst, new_dst)) | |
1409 | { | |
1410 | DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x: address changes" | |
1411 | " are not supported", ntohl(spi)); | |
1412 | return NOT_SUPPORTED; | |
1413 | } | |
7daf5226 | 1414 | |
1adaa02b | 1415 | memset(&request, 0, sizeof(request)); |
7daf5226 | 1416 | |
1adaa02b | 1417 | DBG2(DBG_KNL, "querying SAD entry with SPI %.8x", ntohl(spi)); |
7daf5226 | 1418 | |
1adaa02b TB |
1419 | msg = (struct sadb_msg*)request; |
1420 | msg->sadb_msg_version = PF_KEY_V2; | |
1421 | msg->sadb_msg_type = SADB_GET; | |
1422 | msg->sadb_msg_satype = proto_ike2satype(protocol); | |
1423 | msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg)); | |
7daf5226 | 1424 | |
1adaa02b TB |
1425 | sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg); |
1426 | sa->sadb_sa_exttype = SADB_EXT_SA; | |
1427 | sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa)); | |
1428 | sa->sadb_sa_spi = spi; | |
1429 | PFKEY_EXT_ADD(msg, sa); | |
7daf5226 | 1430 | |
1adaa02b | 1431 | /* the kernel wants a SADB_EXT_ADDRESS_SRC to be present even though |
f55a7a76 TB |
1432 | * it is not used for anything. */ |
1433 | add_anyaddr_ext(msg, dst->get_family(dst), SADB_EXT_ADDRESS_SRC); | |
1434 | add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0); | |
7daf5226 | 1435 | |
1adaa02b TB |
1436 | if (pfkey_send(this, msg, &out, &len) != SUCCESS) |
1437 | { | |
1438 | DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x", | |
1439 | ntohl(spi)); | |
1440 | return FAILED; | |
1441 | } | |
1442 | else if (out->sadb_msg_errno) | |
1443 | { | |
1444 | DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x: %s (%d)", | |
1445 | ntohl(spi), strerror(out->sadb_msg_errno), out->sadb_msg_errno); | |
1446 | free(out); | |
1447 | return FAILED; | |
1448 | } | |
1449 | else if (parse_pfkey_message(out, &response) != SUCCESS) | |
1450 | { | |
1451 | DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x: parsing response " | |
1452 | "from kernel failed", ntohl(spi)); | |
1453 | free(out); | |
1454 | return FAILED; | |
1455 | } | |
7daf5226 | 1456 | |
1adaa02b TB |
1457 | DBG2(DBG_KNL, "updating SAD entry with SPI %.8x from %#H..%#H to %#H..%#H", |
1458 | ntohl(spi), src, dst, new_src, new_dst); | |
7daf5226 | 1459 | |
1adaa02b | 1460 | memset(&request, 0, sizeof(request)); |
7daf5226 | 1461 | |
1adaa02b TB |
1462 | msg = (struct sadb_msg*)request; |
1463 | msg->sadb_msg_version = PF_KEY_V2; | |
ea625fab | 1464 | msg->sadb_msg_type = SADB_UPDATE; |
1adaa02b TB |
1465 | msg->sadb_msg_satype = proto_ike2satype(protocol); |
1466 | msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg)); | |
7daf5226 | 1467 | |
e20bd8b6 TB |
1468 | #ifdef __APPLE__ |
1469 | { | |
1470 | struct sadb_sa_2 *sa_2; | |
1471 | sa_2 = (struct sadb_sa_2*)PFKEY_EXT_ADD_NEXT(msg); | |
1472 | sa_2->sa.sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa_2)); | |
1473 | memcpy(&sa_2->sa, response.sa, sizeof(struct sadb_sa)); | |
1474 | if (encap) | |
1475 | { | |
1476 | sa_2->sadb_sa_natt_port = new_dst->get_port(new_dst); | |
1477 | sa_2->sa.sadb_sa_flags |= SADB_X_EXT_NATT; | |
1478 | } | |
1479 | } | |
1480 | #else | |
1adaa02b | 1481 | PFKEY_EXT_COPY(msg, response.sa); |
e20bd8b6 | 1482 | #endif |
1adaa02b | 1483 | PFKEY_EXT_COPY(msg, response.x_sa2); |
7daf5226 | 1484 | |
ea625fab TB |
1485 | PFKEY_EXT_COPY(msg, response.src); |
1486 | PFKEY_EXT_COPY(msg, response.dst); | |
7daf5226 | 1487 | |
1adaa02b TB |
1488 | PFKEY_EXT_COPY(msg, response.lft_soft); |
1489 | PFKEY_EXT_COPY(msg, response.lft_hard); | |
7daf5226 | 1490 | |
1adaa02b TB |
1491 | if (response.key_encr) |
1492 | { | |
1493 | PFKEY_EXT_COPY(msg, response.key_encr); | |
1494 | } | |
7daf5226 | 1495 | |
1adaa02b TB |
1496 | if (response.key_auth) |
1497 | { | |
1498 | PFKEY_EXT_COPY(msg, response.key_auth); | |
1499 | } | |
7daf5226 | 1500 | |
d24a74c5 | 1501 | #ifdef HAVE_NATT |
8d50c198 | 1502 | if (new_encap) |
1adaa02b TB |
1503 | { |
1504 | add_encap_ext(msg, new_src, new_dst); | |
1505 | } | |
d24a74c5 | 1506 | #endif /*HAVE_NATT*/ |
7daf5226 | 1507 | |
1adaa02b | 1508 | free(out); |
7daf5226 | 1509 | |
1adaa02b TB |
1510 | if (pfkey_send(this, msg, &out, &len) != SUCCESS) |
1511 | { | |
1512 | DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x", ntohl(spi)); | |
1513 | return FAILED; | |
1514 | } | |
1515 | else if (out->sadb_msg_errno) | |
1516 | { | |
1517 | DBG1(DBG_KNL, "unable to update SAD entry with SPI %.8x: %s (%d)", | |
1518 | ntohl(spi), strerror(out->sadb_msg_errno), out->sadb_msg_errno); | |
1519 | free(out); | |
1520 | return FAILED; | |
1521 | } | |
1522 | free(out); | |
7daf5226 | 1523 | |
1adaa02b TB |
1524 | return SUCCESS; |
1525 | } | |
1526 | ||
44791b75 MW |
1527 | METHOD(kernel_ipsec_t, query_sa, status_t, |
1528 | private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst, | |
ee26c537 | 1529 | u_int32_t spi, protocol_id_t protocol, mark_t mark, u_int64_t *bytes) |
2ad51539 | 1530 | { |
f35f229f AS |
1531 | unsigned char request[PFKEY_BUFFER_SIZE]; |
1532 | struct sadb_msg *msg, *out; | |
1533 | struct sadb_sa *sa; | |
1534 | pfkey_msg_t response; | |
1535 | size_t len; | |
7daf5226 | 1536 | |
f35f229f | 1537 | memset(&request, 0, sizeof(request)); |
7daf5226 | 1538 | |
f35f229f | 1539 | DBG2(DBG_KNL, "querying SAD entry with SPI %.8x", ntohl(spi)); |
7daf5226 | 1540 | |
f35f229f AS |
1541 | msg = (struct sadb_msg*)request; |
1542 | msg->sadb_msg_version = PF_KEY_V2; | |
1543 | msg->sadb_msg_type = SADB_GET; | |
1544 | msg->sadb_msg_satype = proto_ike2satype(protocol); | |
1545 | msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg)); | |
7daf5226 | 1546 | |
f35f229f AS |
1547 | sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg); |
1548 | sa->sadb_sa_exttype = SADB_EXT_SA; | |
1549 | sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa)); | |
1550 | sa->sadb_sa_spi = spi; | |
1551 | PFKEY_EXT_ADD(msg, sa); | |
7daf5226 | 1552 | |
f35f229f AS |
1553 | /* the Linux Kernel doesn't care for the src address, but other systems do |
1554 | * (e.g. FreeBSD) | |
1555 | */ | |
1556 | add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0); | |
1557 | add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0); | |
7daf5226 | 1558 | |
f35f229f AS |
1559 | if (pfkey_send(this, msg, &out, &len) != SUCCESS) |
1560 | { | |
1561 | DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x", ntohl(spi)); | |
1562 | return FAILED; | |
1563 | } | |
1564 | else if (out->sadb_msg_errno) | |
1565 | { | |
1566 | DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x: %s (%d)", | |
1567 | ntohl(spi), strerror(out->sadb_msg_errno), out->sadb_msg_errno); | |
1568 | free(out); | |
1569 | return FAILED; | |
1570 | } | |
1571 | else if (parse_pfkey_message(out, &response) != SUCCESS) | |
1572 | { | |
1573 | DBG1(DBG_KNL, "unable to query SAD entry with SPI %.8x", ntohl(spi)); | |
1574 | free(out); | |
1575 | return FAILED; | |
1576 | } | |
1577 | *bytes = response.lft_current->sadb_lifetime_bytes; | |
1578 | ||
1579 | free(out); | |
1580 | return SUCCESS; | |
2ad51539 AS |
1581 | } |
1582 | ||
44791b75 MW |
1583 | METHOD(kernel_ipsec_t, del_sa, status_t, |
1584 | private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst, | |
ee26c537 | 1585 | u_int32_t spi, protocol_id_t protocol, u_int16_t cpi, mark_t mark) |
1adaa02b TB |
1586 | { |
1587 | unsigned char request[PFKEY_BUFFER_SIZE]; | |
1588 | struct sadb_msg *msg, *out; | |
1589 | struct sadb_sa *sa; | |
1adaa02b | 1590 | size_t len; |
7daf5226 | 1591 | |
1adaa02b | 1592 | memset(&request, 0, sizeof(request)); |
7daf5226 | 1593 | |
1adaa02b | 1594 | DBG2(DBG_KNL, "deleting SAD entry with SPI %.8x", ntohl(spi)); |
7daf5226 | 1595 | |
1adaa02b TB |
1596 | msg = (struct sadb_msg*)request; |
1597 | msg->sadb_msg_version = PF_KEY_V2; | |
1598 | msg->sadb_msg_type = SADB_DELETE; | |
1599 | msg->sadb_msg_satype = proto_ike2satype(protocol); | |
1600 | msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg)); | |
7daf5226 | 1601 | |
1adaa02b TB |
1602 | sa = (struct sadb_sa*)PFKEY_EXT_ADD_NEXT(msg); |
1603 | sa->sadb_sa_exttype = SADB_EXT_SA; | |
1604 | sa->sadb_sa_len = PFKEY_LEN(sizeof(struct sadb_sa)); | |
1605 | sa->sadb_sa_spi = spi; | |
1606 | PFKEY_EXT_ADD(msg, sa); | |
7daf5226 | 1607 | |
f35f229f AS |
1608 | /* the Linux Kernel doesn't care for the src address, but other systems do |
1609 | * (e.g. FreeBSD) | |
1610 | */ | |
d24a74c5 | 1611 | add_addr_ext(msg, src, SADB_EXT_ADDRESS_SRC, 0, 0); |
f55a7a76 | 1612 | add_addr_ext(msg, dst, SADB_EXT_ADDRESS_DST, 0, 0); |
7daf5226 | 1613 | |
1adaa02b TB |
1614 | if (pfkey_send(this, msg, &out, &len) != SUCCESS) |
1615 | { | |
1616 | DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x", ntohl(spi)); | |
1617 | return FAILED; | |
1618 | } | |
1619 | else if (out->sadb_msg_errno) | |
1620 | { | |
1621 | DBG1(DBG_KNL, "unable to delete SAD entry with SPI %.8x: %s (%d)", | |
1622 | ntohl(spi), strerror(out->sadb_msg_errno), out->sadb_msg_errno); | |
1623 | free(out); | |
1624 | return FAILED; | |
1625 | } | |
7daf5226 | 1626 | |
1adaa02b TB |
1627 | DBG2(DBG_KNL, "deleted SAD entry with SPI %.8x", ntohl(spi)); |
1628 | free(out); | |
1629 | return SUCCESS; | |
1630 | } | |
1631 | ||
44791b75 MW |
1632 | METHOD(kernel_ipsec_t, add_policy, status_t, |
1633 | private_kernel_pfkey_ipsec_t *this, host_t *src, host_t *dst, | |
1634 | traffic_selector_t *src_ts, traffic_selector_t *dst_ts, | |
1635 | policy_dir_t direction, u_int32_t spi, protocol_id_t protocol, | |
ee26c537 AS |
1636 | u_int32_t reqid, mark_t mark, ipsec_mode_t mode, u_int16_t ipcomp, |
1637 | u_int16_t cpi, bool routed) | |
1adaa02b TB |
1638 | { |
1639 | unsigned char request[PFKEY_BUFFER_SIZE]; | |
1640 | struct sadb_msg *msg, *out; | |
1641 | struct sadb_x_policy *pol; | |
1adaa02b TB |
1642 | struct sadb_x_ipsecrequest *req; |
1643 | policy_entry_t *policy, *found = NULL; | |
1644 | pfkey_msg_t response; | |
1645 | size_t len; | |
7daf5226 | 1646 | |
eab05274 TB |
1647 | if (dir2kernel(direction) == IPSEC_DIR_INVALID) |
1648 | { | |
1649 | /* FWD policies are not supported on all platforms */ | |
1650 | return SUCCESS; | |
1651 | } | |
7daf5226 | 1652 | |
1adaa02b TB |
1653 | /* create a policy */ |
1654 | policy = create_policy_entry(src_ts, dst_ts, direction, reqid); | |
7daf5226 | 1655 | |
1adaa02b | 1656 | /* find a matching policy */ |
3ac5a0db | 1657 | this->mutex->lock(this->mutex); |
1adaa02b TB |
1658 | if (this->policies->find_first(this->policies, |
1659 | (linked_list_match_t)policy_entry_equals, (void**)&found, policy) == SUCCESS) | |
1660 | { | |
1661 | /* use existing policy */ | |
1662 | found->refcount++; | |
1663 | DBG2(DBG_KNL, "policy %R === %R %N already exists, increasing " | |
1664 | "refcount", src_ts, dst_ts, | |
1665 | policy_dir_names, direction); | |
1666 | policy_entry_destroy(policy); | |
1667 | policy = found; | |
1668 | } | |
1669 | else | |
1670 | { | |
1671 | /* apply the new one, if we have no such policy */ | |
1672 | this->policies->insert_last(this->policies, policy); | |
1673 | policy->refcount = 1; | |
1674 | } | |
7daf5226 | 1675 | |
1adaa02b | 1676 | memset(&request, 0, sizeof(request)); |
7daf5226 | 1677 | |
1adaa02b TB |
1678 | DBG2(DBG_KNL, "adding policy %R === %R %N", src_ts, dst_ts, |
1679 | policy_dir_names, direction); | |
7daf5226 | 1680 | |
1adaa02b TB |
1681 | msg = (struct sadb_msg*)request; |
1682 | msg->sadb_msg_version = PF_KEY_V2; | |
1683 | msg->sadb_msg_type = found ? SADB_X_SPDUPDATE : SADB_X_SPDADD; | |
1684 | msg->sadb_msg_satype = 0; | |
1685 | msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg)); | |
7daf5226 | 1686 | |
1adaa02b TB |
1687 | pol = (struct sadb_x_policy*)PFKEY_EXT_ADD_NEXT(msg); |
1688 | pol->sadb_x_policy_exttype = SADB_X_EXT_POLICY; | |
1689 | pol->sadb_x_policy_len = PFKEY_LEN(sizeof(struct sadb_x_policy)); | |
1690 | pol->sadb_x_policy_id = 0; | |
1691 | pol->sadb_x_policy_dir = dir2kernel(direction); | |
d24a74c5 TB |
1692 | pol->sadb_x_policy_type = IPSEC_POLICY_IPSEC; |
1693 | #ifdef HAVE_STRUCT_SADB_X_POLICY_SADB_X_POLICY_PRIORITY | |
1adaa02b | 1694 | /* calculate priority based on source selector size, small size = high prio */ |
ea625fab | 1695 | pol->sadb_x_policy_priority = routed ? PRIO_LOW : PRIO_HIGH; |
1adaa02b TB |
1696 | pol->sadb_x_policy_priority -= policy->src.mask * 10; |
1697 | pol->sadb_x_policy_priority -= policy->src.proto != IPSEC_PROTO_ANY ? 2 : 0; | |
1698 | pol->sadb_x_policy_priority -= policy->src.net->get_port(policy->src.net) ? 1 : 0; | |
d24a74c5 | 1699 | #endif |
7daf5226 | 1700 | |
1adaa02b TB |
1701 | /* one or more sadb_x_ipsecrequest extensions are added to the sadb_x_policy extension */ |
1702 | req = (struct sadb_x_ipsecrequest*)(pol + 1); | |
1703 | req->sadb_x_ipsecrequest_proto = proto_ike2ip(protocol); | |
1704 | /* !!! the length of this struct MUST be in octets instead of 64 bit words */ | |
1705 | req->sadb_x_ipsecrequest_len = sizeof(struct sadb_x_ipsecrequest); | |
1706 | req->sadb_x_ipsecrequest_mode = mode2kernel(mode); | |
1707 | req->sadb_x_ipsecrequest_reqid = reqid; | |
1708 | req->sadb_x_ipsecrequest_level = IPSEC_LEVEL_UNIQUE; | |
1709 | if (mode == MODE_TUNNEL) | |
1710 | { | |
668e84d9 TB |
1711 | len = hostcpy(req + 1, src); |
1712 | req->sadb_x_ipsecrequest_len += len; | |
1713 | len = hostcpy((char*)(req + 1) + len, dst); | |
1714 | req->sadb_x_ipsecrequest_len += len; | |
1adaa02b | 1715 | } |
7daf5226 | 1716 | |
1adaa02b TB |
1717 | pol->sadb_x_policy_len += PFKEY_LEN(req->sadb_x_ipsecrequest_len); |
1718 | PFKEY_EXT_ADD(msg, pol); | |
7daf5226 | 1719 | |
f55a7a76 TB |
1720 | add_addr_ext(msg, policy->src.net, SADB_EXT_ADDRESS_SRC, policy->src.proto, |
1721 | policy->src.mask); | |
1722 | add_addr_ext(msg, policy->dst.net, SADB_EXT_ADDRESS_DST, policy->dst.proto, | |
1723 | policy->dst.mask); | |
7daf5226 | 1724 | |
bfca7aa5 TB |
1725 | #ifdef __FreeBSD__ |
1726 | { /* on FreeBSD a lifetime has to be defined to be able to later query | |
1727 | * the current use time. */ | |
1728 | struct sadb_lifetime *lft; | |
1729 | lft = (struct sadb_lifetime*)PFKEY_EXT_ADD_NEXT(msg); | |
1730 | lft->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD; | |
1731 | lft->sadb_lifetime_len = PFKEY_LEN(sizeof(struct sadb_lifetime)); | |
79ff6141 | 1732 | lft->sadb_lifetime_addtime = LONG_MAX; |
bfca7aa5 TB |
1733 | PFKEY_EXT_ADD(msg, lft); |
1734 | } | |
1735 | #endif | |
7daf5226 | 1736 | |
3ac5a0db | 1737 | this->mutex->unlock(this->mutex); |
7daf5226 | 1738 | |
1adaa02b TB |
1739 | if (pfkey_send(this, msg, &out, &len) != SUCCESS) |
1740 | { | |
1741 | DBG1(DBG_KNL, "unable to add policy %R === %R %N", src_ts, dst_ts, | |
1742 | policy_dir_names, direction); | |
1743 | return FAILED; | |
1744 | } | |
1745 | else if (out->sadb_msg_errno) | |
1746 | { | |
1747 | DBG1(DBG_KNL, "unable to add policy %R === %R %N: %s (%d)", src_ts, dst_ts, | |
1748 | policy_dir_names, direction, | |
1749 | strerror(out->sadb_msg_errno), out->sadb_msg_errno); | |
1750 | free(out); | |
1751 | return FAILED; | |
1752 | } | |
1753 | else if (parse_pfkey_message(out, &response) != SUCCESS) | |
1754 | { | |
1755 | DBG1(DBG_KNL, "unable to add policy %R === %R %N: parsing response " | |
1756 | "from kernel failed", src_ts, dst_ts, policy_dir_names, direction); | |
1757 | free(out); | |
1758 | return FAILED; | |
1759 | } | |
7daf5226 | 1760 | |
3ac5a0db | 1761 | this->mutex->lock(this->mutex); |
7daf5226 | 1762 | |
1adaa02b TB |
1763 | /* we try to find the policy again and update the kernel index */ |
1764 | if (this->policies->find_last(this->policies, NULL, (void**)&policy) != SUCCESS) | |
1765 | { | |
1766 | DBG2(DBG_KNL, "unable to update index, the policy %R === %R %N is " | |
1767 | "already gone, ignoring", src_ts, dst_ts, policy_dir_names, direction); | |
3ac5a0db | 1768 | this->mutex->unlock(this->mutex); |
1adaa02b TB |
1769 | free(out); |
1770 | return SUCCESS; | |
1771 | } | |
1772 | policy->index = response.x_policy->sadb_x_policy_id; | |
1773 | free(out); | |
7daf5226 | 1774 | |
1adaa02b TB |
1775 | /* install a route, if: |
1776 | * - we are NOT updating a policy | |
1777 | * - this is a forward policy (to just get one for each child) | |
1778 | * - we are in tunnel mode | |
1779 | * - we are not using IPv6 (does not work correctly yet!) | |
1780 | * - routing is not disabled via strongswan.conf | |
1781 | */ | |
1782 | if (policy->route == NULL && direction == POLICY_FWD && | |
1783 | mode != MODE_TRANSPORT && src->get_family(src) != AF_INET6 && | |
1784 | this->install_routes) | |
1785 | { | |
1786 | route_entry_t *route = malloc_thing(route_entry_t); | |
7daf5226 | 1787 | |
1adaa02b TB |
1788 | if (charon->kernel_interface->get_address_by_ts(charon->kernel_interface, |
1789 | dst_ts, &route->src_ip) == SUCCESS) | |
1790 | { | |
1791 | /* get the nexthop to src (src as we are in POLICY_FWD).*/ | |
1792 | route->gateway = charon->kernel_interface->get_nexthop( | |
1793 | charon->kernel_interface, src); | |
1794 | route->if_name = charon->kernel_interface->get_interface( | |
1795 | charon->kernel_interface, dst); | |
1796 | route->dst_net = chunk_clone(policy->src.net->get_address(policy->src.net)); | |
1797 | route->prefixlen = policy->src.mask; | |
7daf5226 | 1798 | |
9eb7f46b | 1799 | if (route->if_name) |
1adaa02b | 1800 | { |
9eb7f46b TB |
1801 | switch (charon->kernel_interface->add_route( |
1802 | charon->kernel_interface, route->dst_net, | |
1803 | route->prefixlen, route->gateway, | |
1804 | route->src_ip, route->if_name)) | |
1805 | { | |
1806 | default: | |
1807 | DBG1(DBG_KNL, "unable to install source route for %H", | |
1808 | route->src_ip); | |
1809 | /* FALL */ | |
1810 | case ALREADY_DONE: | |
1811 | /* route exists, do not uninstall */ | |
1812 | route_entry_destroy(route); | |
1813 | break; | |
1814 | case SUCCESS: | |
1815 | /* cache the installed route */ | |
1816 | policy->route = route; | |
1817 | break; | |
1818 | } | |
1819 | } | |
1820 | else | |
1821 | { | |
1822 | route_entry_destroy(route); | |
1adaa02b TB |
1823 | } |
1824 | } | |
1825 | else | |
1826 | { | |
1827 | free(route); | |
1828 | } | |
d24a74c5 | 1829 | } |
7daf5226 | 1830 | |
d24a74c5 | 1831 | this->mutex->unlock(this->mutex); |
7daf5226 | 1832 | |
1adaa02b TB |
1833 | return SUCCESS; |
1834 | } | |
1835 | ||
44791b75 MW |
1836 | METHOD(kernel_ipsec_t, query_policy, status_t, |
1837 | private_kernel_pfkey_ipsec_t *this, traffic_selector_t *src_ts, | |
ee26c537 AS |
1838 | traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark, |
1839 | u_int32_t *use_time) | |
1adaa02b TB |
1840 | { |
1841 | unsigned char request[PFKEY_BUFFER_SIZE]; | |
1842 | struct sadb_msg *msg, *out; | |
1843 | struct sadb_x_policy *pol; | |
1adaa02b TB |
1844 | policy_entry_t *policy, *found = NULL; |
1845 | pfkey_msg_t response; | |
1846 | size_t len; | |
7daf5226 | 1847 | |
eab05274 TB |
1848 | if (dir2kernel(direction) == IPSEC_DIR_INVALID) |
1849 | { | |
1850 | /* FWD policies are not supported on all platforms */ | |
1851 | return NOT_FOUND; | |
1852 | } | |
7daf5226 | 1853 | |
1adaa02b TB |
1854 | DBG2(DBG_KNL, "querying policy %R === %R %N", src_ts, dst_ts, |
1855 | policy_dir_names, direction); | |
1856 | ||
1857 | /* create a policy */ | |
1858 | policy = create_policy_entry(src_ts, dst_ts, direction, 0); | |
7daf5226 | 1859 | |
1adaa02b | 1860 | /* find a matching policy */ |
3ac5a0db | 1861 | this->mutex->lock(this->mutex); |
1adaa02b TB |
1862 | if (this->policies->find_first(this->policies, |
1863 | (linked_list_match_t)policy_entry_equals, (void**)&found, policy) != SUCCESS) | |
1864 | { | |
1865 | DBG1(DBG_KNL, "querying policy %R === %R %N failed, not found", src_ts, | |
1866 | dst_ts, policy_dir_names, direction); | |
1867 | policy_entry_destroy(policy); | |
3ac5a0db | 1868 | this->mutex->unlock(this->mutex); |
1adaa02b TB |
1869 | return NOT_FOUND; |
1870 | } | |
1871 | policy_entry_destroy(policy); | |
1872 | policy = found; | |
7daf5226 | 1873 | |
1adaa02b | 1874 | memset(&request, 0, sizeof(request)); |
7daf5226 | 1875 | |
1adaa02b TB |
1876 | msg = (struct sadb_msg*)request; |
1877 | msg->sadb_msg_version = PF_KEY_V2; | |
1878 | msg->sadb_msg_type = SADB_X_SPDGET; | |
1879 | msg->sadb_msg_satype = 0; | |
1880 | msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg)); | |
7daf5226 | 1881 | |
1adaa02b TB |
1882 | pol = (struct sadb_x_policy*)PFKEY_EXT_ADD_NEXT(msg); |
1883 | pol->sadb_x_policy_exttype = SADB_X_EXT_POLICY; | |
1884 | pol->sadb_x_policy_id = policy->index; | |
1885 | pol->sadb_x_policy_len = PFKEY_LEN(sizeof(struct sadb_x_policy)); | |
1886 | pol->sadb_x_policy_dir = dir2kernel(direction); | |
1887 | pol->sadb_x_policy_type = IPSEC_POLICY_IPSEC; | |
1888 | PFKEY_EXT_ADD(msg, pol); | |
7daf5226 | 1889 | |
f55a7a76 TB |
1890 | add_addr_ext(msg, policy->src.net, SADB_EXT_ADDRESS_SRC, policy->src.proto, |
1891 | policy->src.mask); | |
1892 | add_addr_ext(msg, policy->dst.net, SADB_EXT_ADDRESS_DST, policy->dst.proto, | |
1893 | policy->dst.mask); | |
7daf5226 | 1894 | |
3ac5a0db | 1895 | this->mutex->unlock(this->mutex); |
7daf5226 | 1896 | |
1adaa02b TB |
1897 | if (pfkey_send(this, msg, &out, &len) != SUCCESS) |
1898 | { | |
1899 | DBG1(DBG_KNL, "unable to query policy %R === %R %N", src_ts, dst_ts, | |
1900 | policy_dir_names, direction); | |
1901 | return FAILED; | |
1902 | } | |
1903 | else if (out->sadb_msg_errno) | |
1904 | { | |
1905 | DBG1(DBG_KNL, "unable to query policy %R === %R %N: %s (%d)", src_ts, | |
1906 | dst_ts, policy_dir_names, direction, | |
1907 | strerror(out->sadb_msg_errno), out->sadb_msg_errno); | |
1908 | free(out); | |
1909 | return FAILED; | |
1910 | } | |
1911 | else if (parse_pfkey_message(out, &response) != SUCCESS) | |
1912 | { | |
1913 | DBG1(DBG_KNL, "unable to query policy %R === %R %N: parsing response " | |
1914 | "from kernel failed", src_ts, dst_ts, policy_dir_names, direction); | |
1915 | free(out); | |
1916 | return FAILED; | |
1917 | } | |
524f9ac4 TB |
1918 | else if (response.lft_current == NULL) |
1919 | { | |
1920 | DBG1(DBG_KNL, "unable to query policy %R === %R %N: kernel reports no " | |
1921 | "use time", src_ts, dst_ts, policy_dir_names, direction); | |
1922 | free(out); | |
1923 | return FAILED; | |
1924 | } | |
6180a558 MW |
1925 | /* we need the monotonic time, but the kernel returns system time. */ |
1926 | if (response.lft_current->sadb_lifetime_usetime) | |
1927 | { | |
1928 | *use_time = time_monotonic(NULL) - | |
1929 | (time(NULL) - response.lft_current->sadb_lifetime_usetime); | |
1930 | } | |
1931 | else | |
1932 | { | |
1933 | *use_time = 0; | |
1934 | } | |
1adaa02b | 1935 | free(out); |
7daf5226 | 1936 | |
1adaa02b TB |
1937 | return SUCCESS; |
1938 | } | |
1939 | ||
44791b75 MW |
1940 | METHOD(kernel_ipsec_t, del_policy, status_t, |
1941 | private_kernel_pfkey_ipsec_t *this, traffic_selector_t *src_ts, | |
ee26c537 AS |
1942 | traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark, |
1943 | bool unrouted) | |
1adaa02b TB |
1944 | { |
1945 | unsigned char request[PFKEY_BUFFER_SIZE]; | |
1946 | struct sadb_msg *msg, *out; | |
1947 | struct sadb_x_policy *pol; | |
1adaa02b TB |
1948 | policy_entry_t *policy, *found = NULL; |
1949 | route_entry_t *route; | |
1950 | size_t len; | |
7daf5226 | 1951 | |
eab05274 TB |
1952 | if (dir2kernel(direction) == IPSEC_DIR_INVALID) |
1953 | { | |
1954 | /* FWD policies are not supported on all platforms */ | |
1955 | return SUCCESS; | |
1956 | } | |
7daf5226 | 1957 | |
1adaa02b TB |
1958 | DBG2(DBG_KNL, "deleting policy %R === %R %N", src_ts, dst_ts, |
1959 | policy_dir_names, direction); | |
7daf5226 | 1960 | |
1adaa02b TB |
1961 | /* create a policy */ |
1962 | policy = create_policy_entry(src_ts, dst_ts, direction, 0); | |
7daf5226 | 1963 | |
1adaa02b | 1964 | /* find a matching policy */ |
3ac5a0db | 1965 | this->mutex->lock(this->mutex); |
1adaa02b TB |
1966 | if (this->policies->find_first(this->policies, |
1967 | (linked_list_match_t)policy_entry_equals, (void**)&found, policy) == SUCCESS) | |
1968 | { | |
1969 | if (--found->refcount > 0) | |
1970 | { | |
1971 | /* is used by more SAs, keep in kernel */ | |
d24a74c5 | 1972 | DBG2(DBG_KNL, "policy still used by another CHILD_SA, not removed"); |
1adaa02b | 1973 | policy_entry_destroy(policy); |
3ac5a0db | 1974 | this->mutex->unlock(this->mutex); |
1adaa02b TB |
1975 | return SUCCESS; |
1976 | } | |
1977 | /* remove if last reference */ | |
1978 | this->policies->remove(this->policies, found, NULL); | |
1979 | policy_entry_destroy(policy); | |
1980 | policy = found; | |
1981 | } | |
1982 | else | |
1983 | { | |
1984 | DBG1(DBG_KNL, "deleting policy %R === %R %N failed, not found", src_ts, | |
1985 | dst_ts, policy_dir_names, direction); | |
1986 | policy_entry_destroy(policy); | |
3ac5a0db | 1987 | this->mutex->unlock(this->mutex); |
1adaa02b TB |
1988 | return NOT_FOUND; |
1989 | } | |
3ac5a0db | 1990 | this->mutex->unlock(this->mutex); |
7daf5226 | 1991 | |
1adaa02b | 1992 | memset(&request, 0, sizeof(request)); |
7daf5226 | 1993 | |
1adaa02b TB |
1994 | msg = (struct sadb_msg*)request; |
1995 | msg->sadb_msg_version = PF_KEY_V2; | |
1996 | msg->sadb_msg_type = SADB_X_SPDDELETE; | |
1997 | msg->sadb_msg_satype = 0; | |
1998 | msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg)); | |
7daf5226 | 1999 | |
1adaa02b TB |
2000 | pol = (struct sadb_x_policy*)PFKEY_EXT_ADD_NEXT(msg); |
2001 | pol->sadb_x_policy_exttype = SADB_X_EXT_POLICY; | |
2002 | pol->sadb_x_policy_len = PFKEY_LEN(sizeof(struct sadb_x_policy)); | |
2003 | pol->sadb_x_policy_dir = dir2kernel(direction); | |
2004 | pol->sadb_x_policy_type = IPSEC_POLICY_IPSEC; | |
2005 | PFKEY_EXT_ADD(msg, pol); | |
7daf5226 | 2006 | |
f55a7a76 TB |
2007 | add_addr_ext(msg, policy->src.net, SADB_EXT_ADDRESS_SRC, policy->src.proto, |
2008 | policy->src.mask); | |
2009 | add_addr_ext(msg, policy->dst.net, SADB_EXT_ADDRESS_DST, policy->dst.proto, | |
2010 | policy->dst.mask); | |
7daf5226 | 2011 | |
1adaa02b TB |
2012 | route = policy->route; |
2013 | policy->route = NULL; | |
2014 | policy_entry_destroy(policy); | |
7daf5226 | 2015 | |
1adaa02b TB |
2016 | if (pfkey_send(this, msg, &out, &len) != SUCCESS) |
2017 | { | |
2018 | DBG1(DBG_KNL, "unable to delete policy %R === %R %N", src_ts, dst_ts, | |
2019 | policy_dir_names, direction); | |
2020 | return FAILED; | |
2021 | } | |
2022 | else if (out->sadb_msg_errno) | |
2023 | { | |
2024 | DBG1(DBG_KNL, "unable to delete policy %R === %R %N: %s (%d)", src_ts, | |
2025 | dst_ts, policy_dir_names, direction, | |
2026 | strerror(out->sadb_msg_errno), out->sadb_msg_errno); | |
2027 | free(out); | |
2028 | return FAILED; | |
2029 | } | |
2030 | free(out); | |
7daf5226 | 2031 | |
1adaa02b TB |
2032 | if (route) |
2033 | { | |
2034 | if (charon->kernel_interface->del_route(charon->kernel_interface, | |
2035 | route->dst_net, route->prefixlen, route->gateway, | |
2036 | route->src_ip, route->if_name) != SUCCESS) | |
2037 | { | |
2038 | DBG1(DBG_KNL, "error uninstalling route installed with " | |
2039 | "policy %R === %R %N", src_ts, dst_ts, | |
2040 | policy_dir_names, direction); | |
d24a74c5 | 2041 | } |
1adaa02b TB |
2042 | route_entry_destroy(route); |
2043 | } | |
7daf5226 | 2044 | |
1adaa02b TB |
2045 | return SUCCESS; |
2046 | } | |
2047 | ||
2048 | /** | |
2049 | * Register a socket for AQUIRE/EXPIRE messages | |
2050 | */ | |
44791b75 MW |
2051 | static status_t register_pfkey_socket(private_kernel_pfkey_ipsec_t *this, |
2052 | u_int8_t satype) | |
1adaa02b TB |
2053 | { |
2054 | unsigned char request[PFKEY_BUFFER_SIZE]; | |
2055 | struct sadb_msg *msg, *out; | |
1adaa02b | 2056 | size_t len; |
7daf5226 | 2057 | |
1adaa02b | 2058 | memset(&request, 0, sizeof(request)); |
7daf5226 | 2059 | |
1adaa02b TB |
2060 | msg = (struct sadb_msg*)request; |
2061 | msg->sadb_msg_version = PF_KEY_V2; | |
2062 | msg->sadb_msg_type = SADB_REGISTER; | |
2063 | msg->sadb_msg_satype = satype; | |
2064 | msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg)); | |
7daf5226 | 2065 | |
1adaa02b TB |
2066 | if (pfkey_send_socket(this, this->socket_events, msg, &out, &len) != SUCCESS) |
2067 | { | |
2068 | DBG1(DBG_KNL, "unable to register PF_KEY socket"); | |
2069 | return FAILED; | |
2070 | } | |
2071 | else if (out->sadb_msg_errno) | |
2072 | { | |
2073 | DBG1(DBG_KNL, "unable to register PF_KEY socket: %s (%d)", | |
2074 | strerror(out->sadb_msg_errno), out->sadb_msg_errno); | |
2075 | free(out); | |
2076 | return FAILED; | |
2077 | } | |
2078 | free(out); | |
2079 | return SUCCESS; | |
2080 | } | |
2081 | ||
54f81859 MW |
2082 | METHOD(kernel_ipsec_t, bypass_socket, bool, |
2083 | private_kernel_pfkey_ipsec_t *this, int fd, int family) | |
ea625fab | 2084 | { |
54f81859 MW |
2085 | struct sadb_x_policy policy; |
2086 | u_int sol, ipsec_policy; | |
7daf5226 | 2087 | |
54f81859 | 2088 | switch (family) |
ea625fab | 2089 | { |
54f81859 | 2090 | case AF_INET: |
ea625fab | 2091 | { |
54f81859 MW |
2092 | sol = SOL_IP; |
2093 | ipsec_policy = IP_IPSEC_POLICY; | |
e7c27b4f | 2094 | break; |
ea625fab | 2095 | } |
54f81859 | 2096 | case AF_INET6: |
ea625fab | 2097 | { |
54f81859 MW |
2098 | sol = SOL_IPV6; |
2099 | ipsec_policy = IPV6_IPSEC_POLICY; | |
e7c27b4f | 2100 | break; |
ea625fab | 2101 | } |
54f81859 MW |
2102 | default: |
2103 | return FALSE; | |
ea625fab | 2104 | } |
54f81859 MW |
2105 | |
2106 | memset(&policy, 0, sizeof(policy)); | |
2107 | policy.sadb_x_policy_len = sizeof(policy) / sizeof(u_int64_t); | |
2108 | policy.sadb_x_policy_exttype = SADB_X_EXT_POLICY; | |
2109 | policy.sadb_x_policy_type = IPSEC_POLICY_BYPASS; | |
2110 | ||
2111 | policy.sadb_x_policy_dir = IPSEC_DIR_OUTBOUND; | |
2112 | if (setsockopt(fd, sol, ipsec_policy, &policy, sizeof(policy)) < 0) | |
2113 | { | |
2114 | DBG1(DBG_KNL, "unable to set IPSEC_POLICY on socket: %s", | |
2115 | strerror(errno)); | |
2116 | return FALSE; | |
2117 | } | |
2118 | policy.sadb_x_policy_dir = IPSEC_DIR_INBOUND; | |
2119 | if (setsockopt(fd, sol, ipsec_policy, &policy, sizeof(policy)) < 0) | |
2120 | { | |
2121 | DBG1(DBG_KNL, "unable to set IPSEC_POLICY on socket: %s", | |
2122 | strerror(errno)); | |
2123 | return FALSE; | |
2124 | } | |
2125 | return TRUE; | |
2126 | } | |
2127 | ||
2128 | METHOD(kernel_ipsec_t, destroy, void, | |
2129 | private_kernel_pfkey_ipsec_t *this) | |
2130 | { | |
d6a27ec6 MW |
2131 | if (this->job) |
2132 | { | |
2133 | this->job->cancel(this->job); | |
2134 | } | |
2135 | if (this->socket > 0) | |
2136 | { | |
2137 | close(this->socket); | |
2138 | } | |
2139 | if (this->socket_events > 0) | |
2140 | { | |
2141 | close(this->socket_events); | |
2142 | } | |
54f81859 MW |
2143 | this->policies->destroy_function(this->policies, (void*)policy_entry_destroy); |
2144 | this->mutex->destroy(this->mutex); | |
2145 | this->mutex_pfkey->destroy(this->mutex_pfkey); | |
2146 | free(this); | |
ea625fab TB |
2147 | } |
2148 | ||
1adaa02b TB |
2149 | /* |
2150 | * Described in header. | |
2151 | */ | |
2152 | kernel_pfkey_ipsec_t *kernel_pfkey_ipsec_create() | |
2153 | { | |
44791b75 MW |
2154 | private_kernel_pfkey_ipsec_t *this; |
2155 | ||
2156 | INIT(this, | |
2157 | .public.interface = { | |
2158 | .get_spi = _get_spi, | |
2159 | .get_cpi = _get_cpi, | |
2160 | .add_sa = _add_sa, | |
2161 | .update_sa = _update_sa, | |
2162 | .query_sa = _query_sa, | |
2163 | .del_sa = _del_sa, | |
2164 | .add_policy = _add_policy, | |
2165 | .query_policy = _query_policy, | |
2166 | .del_policy = _del_policy, | |
54f81859 | 2167 | .bypass_socket = _bypass_socket, |
44791b75 MW |
2168 | .destroy = _destroy, |
2169 | }, | |
2170 | .policies = linked_list_create(), | |
2171 | .mutex = mutex_create(MUTEX_TYPE_DEFAULT), | |
2172 | .mutex_pfkey = mutex_create(MUTEX_TYPE_DEFAULT), | |
2173 | .install_routes = lib->settings->get_bool(lib->settings, | |
2174 | "charon.install_routes", TRUE), | |
2175 | ); | |
7daf5226 | 2176 | |
1adaa02b TB |
2177 | /* create a PF_KEY socket to communicate with the kernel */ |
2178 | this->socket = socket(PF_KEY, SOCK_RAW, PF_KEY_V2); | |
2179 | if (this->socket <= 0) | |
2180 | { | |
d6a27ec6 MW |
2181 | DBG1(DBG_KNL, "unable to create PF_KEY socket"); |
2182 | destroy(this); | |
2183 | return NULL; | |
1adaa02b | 2184 | } |
7daf5226 | 2185 | |
1adaa02b TB |
2186 | /* create a PF_KEY socket for ACQUIRE & EXPIRE */ |
2187 | this->socket_events = socket(PF_KEY, SOCK_RAW, PF_KEY_V2); | |
2188 | if (this->socket_events <= 0) | |
2189 | { | |
d6a27ec6 MW |
2190 | DBG1(DBG_KNL, "unable to create PF_KEY event socket"); |
2191 | destroy(this); | |
2192 | return NULL; | |
1adaa02b | 2193 | } |
7daf5226 | 2194 | |
1adaa02b TB |
2195 | /* register the event socket */ |
2196 | if (register_pfkey_socket(this, SADB_SATYPE_ESP) != SUCCESS || | |
2197 | register_pfkey_socket(this, SADB_SATYPE_AH) != SUCCESS) | |
2198 | { | |
d6a27ec6 MW |
2199 | DBG1(DBG_KNL, "unable to register PF_KEY event socket"); |
2200 | destroy(this); | |
2201 | return NULL; | |
1adaa02b | 2202 | } |
7daf5226 | 2203 | |
1adaa02b TB |
2204 | this->job = callback_job_create((callback_job_cb_t)receive_events, |
2205 | this, NULL, NULL); | |
2206 | charon->processor->queue_job(charon->processor, (job_t*)this->job); | |
7daf5226 | 2207 | |
1adaa02b TB |
2208 | return &this->public; |
2209 | } | |
44791b75 | 2210 |