File: | src/sbin/iked/ikev2.c |
Warning: | line 7028, column 9 Dereference of null pointer |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: ikev2.c,v 1.344 2021/12/09 13:49:45 tobhe Exp $ */ | |||
2 | ||||
3 | /* | |||
4 | * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de> | |||
5 | * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org> | |||
6 | * | |||
7 | * Permission to use, copy, modify, and distribute this software for any | |||
8 | * purpose with or without fee is hereby granted, provided that the above | |||
9 | * copyright notice and this permission notice appear in all copies. | |||
10 | * | |||
11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |||
12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |||
13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |||
14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |||
15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |||
16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |||
17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||
18 | */ | |||
19 | ||||
20 | #include <sys/types.h> | |||
21 | #include <sys/queue.h> | |||
22 | #include <sys/socket.h> | |||
23 | #include <sys/uio.h> | |||
24 | ||||
25 | #include <netinet/in.h> | |||
26 | #include <netinet/ip_ipsp.h> | |||
27 | #include <arpa/inet.h> | |||
28 | ||||
29 | #include <stdlib.h> | |||
30 | #include <stdio.h> | |||
31 | #include <syslog.h> | |||
32 | #include <unistd.h> | |||
33 | #include <string.h> | |||
34 | #include <signal.h> | |||
35 | #include <errno(*__errno()).h> | |||
36 | #include <err.h> | |||
37 | #include <event.h> | |||
38 | ||||
39 | #include <openssl/sha.h> | |||
40 | #include <openssl/evp.h> | |||
41 | #include <openssl/x509.h> | |||
42 | ||||
43 | #include "iked.h" | |||
44 | #include "ikev2.h" | |||
45 | #include "eap.h" | |||
46 | #include "dh.h" | |||
47 | #include "chap_ms.h" | |||
48 | ||||
49 | void ikev2_info(struct iked *, int); | |||
50 | void ikev2_info_sa(struct iked *, int, const char *, struct iked_sa *); | |||
51 | void ikev2_info_csa(struct iked *, int, const char *, struct iked_childsa *); | |||
52 | void ikev2_info_flow(struct iked *, int, const char *, struct iked_flow *); | |||
53 | void ikev2_log_established(struct iked_sa *); | |||
54 | void ikev2_log_proposal(struct iked_sa *, struct iked_proposals *); | |||
55 | void ikev2_log_cert_info(const char *, struct iked_id *); | |||
56 | ||||
57 | void ikev2_run(struct privsep *, struct privsep_proc *, void *); | |||
58 | void ikev2_shutdown(struct privsep_proc *); | |||
59 | int ikev2_dispatch_parent(int, struct privsep_proc *, struct imsg *); | |||
60 | int ikev2_dispatch_cert(int, struct privsep_proc *, struct imsg *); | |||
61 | int ikev2_dispatch_control(int, struct privsep_proc *, struct imsg *); | |||
62 | ||||
63 | struct iked_sa * | |||
64 | ikev2_getimsgdata(struct iked *, struct imsg *, struct iked_sahdr *, | |||
65 | uint8_t *, uint8_t **, size_t *); | |||
66 | ||||
67 | void ikev2_recv(struct iked *, struct iked_message *); | |||
68 | int ikev2_ike_auth_compatible(struct iked_sa *, uint8_t, uint8_t); | |||
69 | int ikev2_ike_auth_recv(struct iked *, struct iked_sa *, | |||
70 | struct iked_message *); | |||
71 | int ikev2_ike_auth(struct iked *, struct iked_sa *); | |||
72 | int ikev2_auth_verify(struct iked *, struct iked_sa *); | |||
73 | ||||
74 | void ikev2_init_recv(struct iked *, struct iked_message *, | |||
75 | struct ike_header *); | |||
76 | void ikev2_init_ike_sa_timeout(struct iked *, void *); | |||
77 | int ikev2_init_ike_sa_peer(struct iked *, struct iked_policy *, | |||
78 | struct iked_addr *, struct iked_message *); | |||
79 | int ikev2_init_ike_auth(struct iked *, struct iked_sa *); | |||
80 | int ikev2_init_auth(struct iked *, struct iked_message *); | |||
81 | int ikev2_init_done(struct iked *, struct iked_sa *); | |||
82 | ||||
83 | int ikev2_record_dstid(struct iked *, struct iked_sa *); | |||
84 | ||||
85 | void ikev2_enable_timer(struct iked *, struct iked_sa *); | |||
86 | void ikev2_disable_timer(struct iked *, struct iked_sa *); | |||
87 | ||||
88 | void ikev2_resp_recv(struct iked *, struct iked_message *, | |||
89 | struct ike_header *); | |||
90 | int ikev2_resp_ike_sa_init(struct iked *, struct iked_message *); | |||
91 | int ikev2_resp_ike_eap(struct iked *, struct iked_sa *, | |||
92 | struct iked_message *); | |||
93 | int ikev2_resp_ike_eap_mschap(struct iked *, struct iked_sa *, | |||
94 | struct iked_message *); | |||
95 | int ikev2_resp_ike_auth(struct iked *, struct iked_sa *); | |||
96 | int ikev2_send_auth_failed(struct iked *, struct iked_sa *); | |||
97 | int ikev2_send_error(struct iked *, struct iked_sa *, | |||
98 | struct iked_message *, uint8_t); | |||
99 | int ikev2_send_init_error(struct iked *, struct iked_message *); | |||
100 | ||||
101 | int ikev2_handle_certreq(struct iked*, struct iked_message *); | |||
102 | ssize_t ikev2_handle_delete(struct iked *, struct iked_message *, | |||
103 | struct ibuf *, struct ikev2_payload **, uint8_t *); | |||
104 | ||||
105 | int ikev2_send_create_child_sa(struct iked *, struct iked_sa *, | |||
106 | struct iked_spi *, uint8_t, uint16_t); | |||
107 | int ikev2_ikesa_enable(struct iked *, struct iked_sa *, struct iked_sa *); | |||
108 | void ikev2_ikesa_delete(struct iked *, struct iked_sa *, int); | |||
109 | int ikev2_nonce_cmp(struct ibuf *, struct ibuf *); | |||
110 | int ikev2_init_create_child_sa(struct iked *, struct iked_message *); | |||
111 | int ikev2_resp_create_child_sa(struct iked *, struct iked_message *); | |||
112 | void ikev2_ike_sa_rekey(struct iked *, void *); | |||
113 | void ikev2_ike_sa_rekey_timeout(struct iked *, void *); | |||
114 | void ikev2_ike_sa_rekey_schedule(struct iked *, struct iked_sa *); | |||
115 | void ikev2_ike_sa_rekey_schedule_fast(struct iked *, struct iked_sa *); | |||
116 | void ikev2_ike_sa_alive(struct iked *, void *); | |||
117 | void ikev2_ike_sa_keepalive(struct iked *, void *); | |||
118 | ||||
119 | int ikev2_sa_negotiate_common(struct iked *, struct iked_sa *, struct iked_message *); | |||
120 | int ikev2_sa_initiator(struct iked *, struct iked_sa *, | |||
121 | struct iked_sa *, struct iked_message *); | |||
122 | int ikev2_sa_responder(struct iked *, struct iked_sa *, struct iked_sa *, | |||
123 | struct iked_message *); | |||
124 | int ikev2_sa_initiator_dh(struct iked_sa *, struct iked_message *, | |||
125 | unsigned int, struct iked_sa *); | |||
126 | int ikev2_sa_responder_dh(struct iked_kex *, struct iked_proposals *, | |||
127 | struct iked_message *, unsigned int); | |||
128 | void ikev2_sa_cleanup_dh(struct iked_sa *); | |||
129 | int ikev2_sa_keys(struct iked *, struct iked_sa *, struct ibuf *); | |||
130 | int ikev2_sa_tag(struct iked_sa *, struct iked_id *); | |||
131 | int ikev2_set_sa_proposal(struct iked_sa *, struct iked_policy *, | |||
132 | unsigned int); | |||
133 | ||||
134 | int ikev2_childsa_negotiate(struct iked *, struct iked_sa *, | |||
135 | struct iked_kex *, struct iked_proposals *, int, int); | |||
136 | int ikev2_childsa_delete_proposed(struct iked *, struct iked_sa *, | |||
137 | struct iked_proposals *); | |||
138 | int ikev2_valid_proposal(struct iked_proposal *, | |||
139 | struct iked_transform **, struct iked_transform **, int *); | |||
140 | ||||
141 | int ikev2_handle_notifies(struct iked *, struct iked_message *); | |||
142 | ||||
143 | ssize_t ikev2_add_proposals(struct iked *, struct iked_sa *, struct ibuf *, | |||
144 | struct iked_proposals *, uint8_t, int, int, int); | |||
145 | ssize_t ikev2_add_cp(struct iked *, struct iked_sa *, int, struct ibuf *); | |||
146 | ssize_t ikev2_init_add_cp(struct iked *, struct iked_sa *, struct ibuf *); | |||
147 | ssize_t ikev2_resp_add_cp(struct iked *, struct iked_sa *, struct ibuf *); | |||
148 | ssize_t ikev2_add_transform(struct ibuf *, | |||
149 | uint8_t, uint8_t, uint16_t, uint16_t); | |||
150 | ssize_t ikev2_add_ts(struct ibuf *, struct ikev2_payload **, ssize_t, | |||
151 | struct iked_sa *, int); | |||
152 | ssize_t ikev2_add_certreq(struct ibuf *, struct ikev2_payload **, ssize_t, | |||
153 | struct ibuf *, uint8_t); | |||
154 | ssize_t ikev2_add_ipcompnotify(struct iked *, struct ibuf *, | |||
155 | struct ikev2_payload **, ssize_t, struct iked_sa *, int); | |||
156 | ssize_t ikev2_add_ts_payload(struct ibuf *, unsigned int, struct iked_sa *); | |||
157 | ssize_t ikev2_add_error(struct iked *, struct ibuf *, struct iked_message *); | |||
158 | int ikev2_add_data(struct ibuf *, void *, size_t); | |||
159 | int ikev2_add_buf(struct ibuf *buf, struct ibuf *); | |||
160 | ||||
161 | int ikev2_cp_setaddr(struct iked *, struct iked_sa *, sa_family_t); | |||
162 | int ikev2_cp_setaddr_pool(struct iked *, struct iked_sa *, | |||
163 | struct iked_cfg *, const char **, sa_family_t); | |||
164 | int ikev2_cp_fixaddr(struct iked_sa *, struct iked_addr *, | |||
165 | struct iked_addr *); | |||
166 | int ikev2_cp_fixflow(struct iked_sa *, struct iked_flow *, | |||
167 | struct iked_flow *); | |||
168 | int ikev2_cp_request_configured(struct iked_sa *); | |||
169 | ||||
170 | ssize_t ikev2_add_sighashnotify(struct ibuf *, struct ikev2_payload **, | |||
171 | ssize_t); | |||
172 | ssize_t ikev2_add_nat_detection(struct iked *, struct ibuf *, | |||
173 | struct ikev2_payload **, struct iked_message *, ssize_t); | |||
174 | ssize_t ikev2_add_notify(struct ibuf *, struct ikev2_payload **, ssize_t, | |||
175 | uint16_t); | |||
176 | ssize_t ikev2_add_mobike(struct ibuf *, struct ikev2_payload **, ssize_t); | |||
177 | ssize_t ikev2_add_fragmentation(struct ibuf *, struct ikev2_payload **, | |||
178 | ssize_t); | |||
179 | ssize_t ikev2_add_transport_mode(struct iked *, struct ibuf *, | |||
180 | struct ikev2_payload **, ssize_t, struct iked_sa *); | |||
181 | int ikev2_update_sa_addresses(struct iked *, struct iked_sa *); | |||
182 | int ikev2_resp_informational(struct iked *, struct iked_sa *, | |||
183 | struct iked_message *); | |||
184 | ||||
185 | void ikev2_ctl_reset_id(struct iked *, struct imsg *, unsigned int); | |||
186 | void ikev2_ctl_show_sa(struct iked *); | |||
187 | ||||
188 | static struct privsep_proc procs[] = { | |||
189 | { "parent", PROC_PARENT, ikev2_dispatch_parent }, | |||
190 | { "certstore", PROC_CERT, ikev2_dispatch_cert }, | |||
191 | { "control", PROC_CONTROL, ikev2_dispatch_control } | |||
192 | }; | |||
193 | ||||
194 | pid_t | |||
195 | ikev2(struct privsep *ps, struct privsep_proc *p) | |||
196 | { | |||
197 | return (proc_run(ps, p, procs, nitems(procs)(sizeof((procs)) / sizeof((procs)[0])), ikev2_run, NULL((void*)0))); | |||
198 | } | |||
199 | ||||
200 | void | |||
201 | ikev2_run(struct privsep *ps, struct privsep_proc *p, void *arg) | |||
202 | { | |||
203 | /* | |||
204 | * pledge in the ikev2 process: | |||
205 | * stdio - for malloc and basic I/O including events. | |||
206 | * inet - for sendto with specified peer address. | |||
207 | * recvfd - for PFKEYv2 and the listening UDP sockets. | |||
208 | * In theory, recvfd could be dropped after getting the fds once. | |||
209 | */ | |||
210 | p->p_shutdown = ikev2_shutdown; | |||
211 | if (pledge("stdio inet recvfd", NULL((void*)0)) == -1) | |||
212 | fatal("pledge"); | |||
213 | } | |||
214 | ||||
215 | void | |||
216 | ikev2_shutdown(struct privsep_proc *p) | |||
217 | { | |||
218 | struct iked *env = p->p_env; | |||
219 | ||||
220 | ibuf_release(env->sc_certreq); | |||
221 | env->sc_certreq = NULL((void*)0); | |||
222 | config_doreset(env, RESET_ALL); | |||
223 | } | |||
224 | ||||
225 | int | |||
226 | ikev2_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg) | |||
227 | { | |||
228 | struct iked *env = p->p_env; | |||
229 | struct iked_sa *sa; | |||
230 | struct iked_policy *pol, *old; | |||
231 | ||||
232 | switch (imsg->hdr.type) { | |||
233 | case IMSG_CTL_RESET: | |||
234 | return (config_getreset(env, imsg)); | |||
235 | case IMSG_CTL_COUPLE: | |||
236 | case IMSG_CTL_DECOUPLE: | |||
237 | return (config_getcoupled(env, imsg->hdr.type)); | |||
238 | case IMSG_CTL_ACTIVE: | |||
239 | case IMSG_CTL_PASSIVE: | |||
240 | if (config_getmode(env, imsg->hdr.type) == -1) | |||
241 | return (0); /* ignore error */ | |||
242 | timer_del(env, &env->sc_inittmr); | |||
243 | TAILQ_FOREACH(pol, &env->sc_policies, pol_entry)for((pol) = ((&env->sc_policies)->tqh_first); (pol) != ((void*)0); (pol) = ((pol)->pol_entry.tqe_next)) { | |||
244 | if (policy_generate_ts(pol) == -1) | |||
245 | fatalx("%s: too many traffic selectors", __func__); | |||
246 | } | |||
247 | /* Find new policies for dangling SAs */ | |||
248 | RB_FOREACH(sa, iked_sas, &env->sc_sas)for ((sa) = iked_sas_RB_MINMAX(&env->sc_sas, -1); (sa) != ((void*)0); (sa) = iked_sas_RB_NEXT(sa)) { | |||
249 | if (sa->sa_state != IKEV2_STATE_ESTABLISHED9) { | |||
250 | sa_state(env, sa, IKEV2_STATE_CLOSING10); | |||
251 | ikev2_ike_sa_setreason(sa, "reload"); | |||
252 | sa_free(env, sa); | |||
253 | continue; | |||
254 | } | |||
255 | ||||
256 | old = sa->sa_policy; | |||
257 | if (policy_lookup_sa(env, sa) == -1) { | |||
258 | log_info("%s: No matching Policy found, terminating SA.", | |||
259 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
260 | ikev2_ike_sa_setreason(sa, "Policy no longer exists"); | |||
261 | ikev2_ikesa_delete(env, sa, sa->sa_hdr.sh_initiator); | |||
262 | } | |||
263 | if (old != sa->sa_policy) { | |||
264 | /* Cleanup old policy */ | |||
265 | TAILQ_REMOVE(&old->pol_sapeers, sa, sa_peer_entry)do { if (((sa)->sa_peer_entry.tqe_next) != ((void*)0)) (sa )->sa_peer_entry.tqe_next->sa_peer_entry.tqe_prev = (sa )->sa_peer_entry.tqe_prev; else (&old->pol_sapeers) ->tqh_last = (sa)->sa_peer_entry.tqe_prev; *(sa)->sa_peer_entry .tqe_prev = (sa)->sa_peer_entry.tqe_next; ; ; } while (0); | |||
266 | if (old->pol_flags & IKED_POLICY_REFCNT0x04) | |||
267 | policy_unref(env, old); | |||
268 | ||||
269 | if (sa->sa_policy->pol_flags & IKED_POLICY_REFCNT0x04) { | |||
270 | log_info("%s: sa %p old pol %p pol_refcnt %d", | |||
271 | __func__, sa, sa->sa_policy, sa->sa_policy->pol_refcnt); | |||
272 | policy_ref(env, sa->sa_policy); | |||
273 | } | |||
274 | TAILQ_INSERT_TAIL(&sa->sa_policy->pol_sapeers, sa, sa_peer_entry)do { (sa)->sa_peer_entry.tqe_next = ((void*)0); (sa)->sa_peer_entry .tqe_prev = (&sa->sa_policy->pol_sapeers)->tqh_last ; *(&sa->sa_policy->pol_sapeers)->tqh_last = (sa ); (&sa->sa_policy->pol_sapeers)->tqh_last = & (sa)->sa_peer_entry.tqe_next; } while (0); | |||
275 | } | |||
276 | } | |||
277 | if (!env->sc_passive) { | |||
278 | timer_set(env, &env->sc_inittmr, ikev2_init_ike_sa, | |||
279 | NULL((void*)0)); | |||
280 | timer_add(env, &env->sc_inittmr, | |||
281 | IKED_INITIATOR_INITIAL2); | |||
282 | } | |||
283 | return (0); | |||
284 | case IMSG_UDP_SOCKET: | |||
285 | return (config_getsocket(env, imsg, ikev2_msg_cb)); | |||
286 | case IMSG_PFKEY_SOCKET: | |||
287 | return (config_getpfkey(env, imsg)); | |||
288 | case IMSG_CFG_POLICY: | |||
289 | return (config_getpolicy(env, imsg)); | |||
290 | case IMSG_CFG_FLOW: | |||
291 | return (config_getflow(env, imsg)); | |||
292 | case IMSG_CFG_USER: | |||
293 | return (config_getuser(env, imsg)); | |||
294 | case IMSG_COMPILE: | |||
295 | return (config_getcompile(env)); | |||
296 | case IMSG_CTL_STATIC: | |||
297 | return (config_getstatic(env, imsg)); | |||
298 | case IMSG_CERT_PARTIAL_CHAIN: | |||
299 | return(config_getcertpartialchain(env, imsg)); | |||
300 | default: | |||
301 | break; | |||
302 | } | |||
303 | ||||
304 | return (-1); | |||
305 | } | |||
306 | ||||
307 | int | |||
308 | ikev2_dispatch_cert(int fd, struct privsep_proc *p, struct imsg *imsg) | |||
309 | { | |||
310 | struct iked *env = p->p_env; | |||
311 | struct iked_sahdr sh; | |||
312 | struct iked_sa *sa; | |||
313 | uint8_t type; | |||
314 | uint8_t *ptr; | |||
315 | size_t len; | |||
316 | struct iked_id *id = NULL((void*)0); | |||
317 | int ignore = 0; | |||
318 | ||||
319 | switch (imsg->hdr.type) { | |||
320 | case IMSG_CERTREQ: | |||
321 | IMSG_SIZE_CHECK(imsg, &type)do { if (((imsg)->hdr.len - sizeof(struct imsg_hdr)) < sizeof (*&type)) fatalx("bad length imsg received"); } while (0); | |||
322 | ||||
323 | ptr = imsg->data; | |||
324 | memcpy(&type, ptr, sizeof(type)); | |||
325 | ptr += sizeof(type); | |||
326 | ||||
327 | ibuf_release(env->sc_certreq); | |||
328 | env->sc_certreqtype = type; | |||
329 | env->sc_certreq = ibuf_new(ptr, | |||
330 | IMSG_DATA_SIZE(imsg)((imsg)->hdr.len - sizeof(struct imsg_hdr)) - sizeof(type)); | |||
331 | ||||
332 | log_debug("%s: updated local CERTREQ type %s length %zu", | |||
333 | __func__, print_map(type, ikev2_cert_map), | |||
334 | ibuf_length(env->sc_certreq)); | |||
335 | ||||
336 | break; | |||
337 | case IMSG_CERTVALID: | |||
338 | case IMSG_CERTINVALID: | |||
339 | /* Ignore invalid or unauthenticated SAs */ | |||
340 | if ((sa = ikev2_getimsgdata(env, imsg, | |||
341 | &sh, &type, &ptr, &len)) == NULL((void*)0) || | |||
342 | sa->sa_state < IKEV2_STATE_EAP3) | |||
343 | break; | |||
344 | ||||
345 | if (sh.sh_initiator) | |||
346 | id = &sa->sa_rcert; | |||
347 | else | |||
348 | id = &sa->sa_icert; | |||
349 | ||||
350 | id->id_type = type; | |||
351 | id->id_offset = 0; | |||
352 | ibuf_release(id->id_buf); | |||
353 | id->id_buf = NULL((void*)0); | |||
354 | ||||
355 | if (len > 0 && (id->id_buf = ibuf_new(ptr, len)) == NULL((void*)0)) { | |||
356 | log_debug("%s: failed to get cert payload", | |||
357 | __func__); | |||
358 | break; | |||
359 | } | |||
360 | ||||
361 | if (imsg->hdr.type == IMSG_CERTVALID) { | |||
362 | if (sa->sa_peerauth.id_type && ikev2_auth_verify(env, sa)) | |||
363 | break; | |||
364 | ||||
365 | log_debug("%s: peer certificate is valid", __func__); | |||
366 | sa_stateflags(sa, IKED_REQ_CERTVALID0x0002); | |||
367 | ||||
368 | if (ikev2_ike_auth(env, sa) != 0) | |||
369 | log_debug("%s: failed to send ike auth", __func__); | |||
370 | } else { | |||
371 | log_warnx("%s: peer certificate is invalid", | |||
372 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
373 | ikev2_send_auth_failed(env, sa); | |||
374 | } | |||
375 | break; | |||
376 | case IMSG_CERT: | |||
377 | if ((sa = ikev2_getimsgdata(env, imsg, | |||
378 | &sh, &type, &ptr, &len)) == NULL((void*)0)) { | |||
379 | log_debug("%s: invalid cert reply", __func__); | |||
380 | break; | |||
381 | } | |||
382 | ||||
383 | /* | |||
384 | * Ignore the message if we already got a valid certificate. | |||
385 | * This might happen if the peer sent multiple CERTREQs. | |||
386 | */ | |||
387 | if (sa->sa_stateflags & IKED_REQ_CERT0x0001 || | |||
388 | type == IKEV2_CERT_NONE0) | |||
389 | ignore = 1; | |||
390 | ||||
391 | log_debug("%s: cert type %s length %zu, %s", __func__, | |||
392 | print_map(type, ikev2_cert_map), len, | |||
393 | ignore ? "ignored" : "ok"); | |||
394 | ||||
395 | if (ignore) | |||
396 | break; | |||
397 | ||||
398 | if (sh.sh_initiator) | |||
399 | id = &sa->sa_icert; | |||
400 | else | |||
401 | id = &sa->sa_rcert; | |||
402 | ||||
403 | id->id_type = type; | |||
404 | id->id_offset = 0; | |||
405 | ibuf_release(id->id_buf); | |||
406 | id->id_buf = NULL((void*)0); | |||
407 | ||||
408 | if (len <= 0 || (id->id_buf = ibuf_new(ptr, len)) == NULL((void*)0)) { | |||
409 | log_debug("%s: failed to get cert payload", | |||
410 | __func__); | |||
411 | break; | |||
412 | } | |||
413 | ||||
414 | sa_stateflags(sa, IKED_REQ_CERT0x0001); | |||
415 | ||||
416 | if (ikev2_ike_auth(env, sa) != 0) | |||
417 | log_debug("%s: failed to send ike auth", __func__); | |||
418 | break; | |||
419 | case IMSG_AUTH: | |||
420 | if ((sa = ikev2_getimsgdata(env, imsg, | |||
421 | &sh, &type, &ptr, &len)) == NULL((void*)0)) { | |||
422 | log_debug("%s: invalid auth reply", __func__); | |||
423 | break; | |||
424 | } | |||
425 | if (sa_stateok(sa, IKEV2_STATE_VALID7)) { | |||
426 | log_warnx("%s: ignoring AUTH in state %s", | |||
427 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
428 | print_map(sa->sa_state, ikev2_state_map)); | |||
429 | break; | |||
430 | } | |||
431 | ||||
432 | log_debug("%s: AUTH type %d len %zu", __func__, type, len); | |||
433 | ||||
434 | id = &sa->sa_localauth; | |||
435 | id->id_type = type; | |||
436 | id->id_offset = 0; | |||
437 | ibuf_release(id->id_buf); | |||
438 | id->id_buf = NULL((void*)0); | |||
439 | ||||
440 | if (type != IKEV2_AUTH_NONE0) { | |||
441 | if (len <= 0 || | |||
442 | (id->id_buf = ibuf_new(ptr, len)) == NULL((void*)0)) { | |||
443 | log_debug("%s: failed to get auth payload", | |||
444 | __func__); | |||
445 | break; | |||
446 | } | |||
447 | } | |||
448 | ||||
449 | sa_stateflags(sa, IKED_REQ_AUTH0x0008); | |||
450 | ||||
451 | if (ikev2_ike_auth(env, sa) != 0) | |||
452 | log_debug("%s: failed to send ike auth", __func__); | |||
453 | break; | |||
454 | default: | |||
455 | return (-1); | |||
456 | } | |||
457 | ||||
458 | return (0); | |||
459 | } | |||
460 | ||||
461 | int | |||
462 | ikev2_dispatch_control(int fd, struct privsep_proc *p, struct imsg *imsg) | |||
463 | { | |||
464 | struct iked *env = p->p_env; | |||
465 | ||||
466 | switch (imsg->hdr.type) { | |||
467 | case IMSG_CTL_RESET_ID: | |||
468 | ikev2_ctl_reset_id(env, imsg, imsg->hdr.type); | |||
469 | break; | |||
470 | case IMSG_CTL_SHOW_SA: | |||
471 | ikev2_ctl_show_sa(env); | |||
472 | break; | |||
473 | default: | |||
474 | return (-1); | |||
475 | } | |||
476 | ||||
477 | return (0); | |||
478 | } | |||
479 | ||||
480 | /* try to delete established SA if no other exchange is active */ | |||
481 | int | |||
482 | ikev2_ike_sa_delete(struct iked *env, struct iked_sa *sa) | |||
483 | { | |||
484 | if (sa->sa_state != IKEV2_STATE_ESTABLISHED9) | |||
485 | return (-1); | |||
486 | if (sa->sa_stateflags & (IKED_REQ_CHILDSA0x0080|IKED_REQ_INF0x0100)) | |||
487 | return (-1); | |||
488 | ikev2_disable_timer(env, sa); | |||
489 | ikev2_ike_sa_setreason(sa, "reset sa control message"); | |||
490 | ikev2_ikesa_delete(env, sa, 1); | |||
491 | timer_add(env, &sa->sa_timer, 0); | |||
492 | return (0); | |||
493 | } | |||
494 | ||||
495 | void | |||
496 | ikev2_ctl_reset_id(struct iked *env, struct imsg *imsg, unsigned int type) | |||
497 | { | |||
498 | struct iked_sa *sa; | |||
499 | char *reset_id = NULL((void*)0); | |||
500 | char sa_id[IKED_ID_SIZE1024]; | |||
501 | ||||
502 | if ((reset_id = get_string(imsg->data, IMSG_DATA_SIZE(imsg)((imsg)->hdr.len - sizeof(struct imsg_hdr)))) == NULL((void*)0)) | |||
503 | return; | |||
504 | ||||
505 | log_debug("%s: %s %d", __func__, reset_id, type); | |||
506 | RB_FOREACH(sa, iked_sas, &env->sc_sas)for ((sa) = iked_sas_RB_MINMAX(&env->sc_sas, -1); (sa) != ((void*)0); (sa) = iked_sas_RB_NEXT(sa)) { | |||
507 | if (ikev2_print_id(IKESA_DSTID(sa)((sa)->sa_hdr.sh_initiator ? &(sa)->sa_rid : &( sa)->sa_iid), sa_id, sizeof(sa_id)) == -1) | |||
508 | continue; | |||
509 | if (strcmp(reset_id, sa_id) != 0) | |||
510 | continue; | |||
511 | if (sa->sa_state == IKEV2_STATE_CLOSED11) | |||
512 | continue; | |||
513 | if (sa->sa_state == IKEV2_STATE_ESTABLISHED9) | |||
514 | ikev2_disable_timer(env, sa); | |||
515 | log_info("%s: IKE SA %p id %s ispi %s rspi %s", __func__, | |||
516 | sa, sa_id, | |||
517 | print_spi(sa->sa_hdr.sh_ispi, 8), | |||
518 | print_spi(sa->sa_hdr.sh_rspi, 8)); | |||
519 | ikev2_ike_sa_setreason(sa, "reset control message"); | |||
520 | ikev2_ikesa_delete(env, sa, 1); | |||
521 | /* default IKED_IKE_SA_DELETE_TIMEOUT is 120s, so switch to 6s */ | |||
522 | timer_add(env, &sa->sa_timer, 3 * IKED_RETRANSMIT_TIMEOUT2); | |||
523 | } | |||
524 | free(reset_id); | |||
525 | } | |||
526 | ||||
527 | void | |||
528 | ikev2_ctl_show_sa(struct iked *env) | |||
529 | { | |||
530 | ikev2_info(env, 0); | |||
531 | } | |||
532 | ||||
533 | struct iked_sa * | |||
534 | ikev2_getimsgdata(struct iked *env, struct imsg *imsg, struct iked_sahdr *sh, | |||
535 | uint8_t *type, uint8_t **buf, size_t *size) | |||
536 | { | |||
537 | uint8_t *ptr; | |||
538 | size_t len; | |||
539 | struct iked_sa *sa; | |||
540 | ||||
541 | ptr = imsg->data; | |||
542 | len = IMSG_DATA_SIZE(imsg)((imsg)->hdr.len - sizeof(struct imsg_hdr)); | |||
543 | if (len < sizeof(*sh)) | |||
544 | fatalx("ikev2_getimsgdata: length too small for sh"); | |||
545 | memcpy(sh, ptr, sizeof(*sh)); | |||
546 | len -= sizeof(*sh); | |||
547 | ptr += sizeof(*sh); | |||
548 | if (len < sizeof(*type)) | |||
549 | fatalx("ikev2_getimsgdata: length too small for type"); | |||
550 | memcpy(type, ptr, sizeof(*type)); | |||
551 | len -= sizeof(*type); | |||
552 | ptr += sizeof(*type); | |||
553 | ||||
554 | sa = sa_lookup(env, sh->sh_ispi, sh->sh_rspi, sh->sh_initiator); | |||
555 | ||||
556 | log_debug("%s: imsg %d rspi %s ispi %s initiator %d sa %s" | |||
557 | " type %d data length %zd", | |||
558 | __func__, imsg->hdr.type, | |||
559 | print_spi(sh->sh_rspi, 8), | |||
560 | print_spi(sh->sh_ispi, 8), | |||
561 | sh->sh_initiator, | |||
562 | sa == NULL((void*)0) ? "invalid" : "valid", *type, len); | |||
563 | ||||
564 | if (sa == NULL((void*)0)) | |||
565 | return (NULL((void*)0)); | |||
566 | ||||
567 | *buf = ptr; | |||
568 | *size = len; | |||
569 | ||||
570 | return (sa); | |||
571 | } | |||
572 | ||||
573 | static time_t | |||
574 | gettime(void) | |||
575 | { | |||
576 | struct timeval tv; | |||
577 | gettimeofday(&tv, NULL((void*)0)); | |||
578 | return tv.tv_sec; | |||
579 | } | |||
580 | ||||
581 | void | |||
582 | ikev2_recv(struct iked *env, struct iked_message *msg) | |||
583 | { | |||
584 | struct ike_header *hdr; | |||
585 | struct iked_sa *sa; | |||
586 | unsigned int initiator, flag = 0; | |||
587 | int r; | |||
588 | ||||
589 | hdr = ibuf_seek(msg->msg_data, msg->msg_offset, sizeof(*hdr)); | |||
590 | ||||
591 | if (hdr == NULL((void*)0) || ibuf_size(msg->msg_data) < | |||
592 | (betoh32(hdr->ike_length)(__uint32_t)(__builtin_constant_p(hdr->ike_length) ? (__uint32_t )(((__uint32_t)(hdr->ike_length) & 0xff) << 24 | ((__uint32_t)(hdr->ike_length) & 0xff00) << 8 | ((__uint32_t)(hdr->ike_length) & 0xff0000) >> 8 | ((__uint32_t)(hdr->ike_length) & 0xff000000) >> 24) : __swap32md(hdr->ike_length)) - msg->msg_offset)) | |||
593 | return; | |||
594 | ||||
595 | initiator = (hdr->ike_flags & IKEV2_FLAG_INITIATOR0x08) ? 0 : 1; | |||
596 | msg->msg_response = (hdr->ike_flags & IKEV2_FLAG_RESPONSE0x20) ? 1 : 0; | |||
597 | msg->msg_exchange = hdr->ike_exchange; | |||
598 | msg->msg_sa = sa_lookup(env, | |||
599 | betoh64(hdr->ike_ispi)(__uint64_t)(__builtin_constant_p(hdr->ike_ispi) ? (__uint64_t )((((__uint64_t)(hdr->ike_ispi) & 0xff) << 56) | ((__uint64_t)(hdr->ike_ispi) & 0xff00ULL) << 40 | ((__uint64_t)(hdr->ike_ispi) & 0xff0000ULL) << 24 | ((__uint64_t)(hdr->ike_ispi) & 0xff000000ULL) << 8 | ((__uint64_t)(hdr->ike_ispi) & 0xff00000000ULL) >> 8 | ((__uint64_t)(hdr->ike_ispi) & 0xff0000000000ULL) >> 24 | ((__uint64_t)(hdr->ike_ispi) & 0xff000000000000ULL ) >> 40 | ((__uint64_t)(hdr->ike_ispi) & 0xff00000000000000ULL ) >> 56) : __swap64md(hdr->ike_ispi)), betoh64(hdr->ike_rspi)(__uint64_t)(__builtin_constant_p(hdr->ike_rspi) ? (__uint64_t )((((__uint64_t)(hdr->ike_rspi) & 0xff) << 56) | ((__uint64_t)(hdr->ike_rspi) & 0xff00ULL) << 40 | ((__uint64_t)(hdr->ike_rspi) & 0xff0000ULL) << 24 | ((__uint64_t)(hdr->ike_rspi) & 0xff000000ULL) << 8 | ((__uint64_t)(hdr->ike_rspi) & 0xff00000000ULL) >> 8 | ((__uint64_t)(hdr->ike_rspi) & 0xff0000000000ULL) >> 24 | ((__uint64_t)(hdr->ike_rspi) & 0xff000000000000ULL ) >> 40 | ((__uint64_t)(hdr->ike_rspi) & 0xff00000000000000ULL ) >> 56) : __swap64md(hdr->ike_rspi)), | |||
600 | initiator); | |||
601 | msg->msg_msgid = betoh32(hdr->ike_msgid)(__uint32_t)(__builtin_constant_p(hdr->ike_msgid) ? (__uint32_t )(((__uint32_t)(hdr->ike_msgid) & 0xff) << 24 | ( (__uint32_t)(hdr->ike_msgid) & 0xff00) << 8 | (( __uint32_t)(hdr->ike_msgid) & 0xff0000) >> 8 | ( (__uint32_t)(hdr->ike_msgid) & 0xff000000) >> 24 ) : __swap32md(hdr->ike_msgid)); | |||
602 | if (policy_lookup(env, msg, NULL((void*)0), NULL((void*)0), 0) != 0) | |||
603 | return; | |||
604 | ||||
605 | logit(hdr->ike_exchange == IKEV2_EXCHANGE_INFORMATIONAL37 ? | |||
606 | LOG_DEBUG7 : LOG_INFO6, | |||
607 | "%srecv %s %s %u peer %s local %s, %ld bytes, policy '%s'", | |||
608 | SPI_IH(hdr)ikev2_ikesa_info((__uint64_t)(__builtin_constant_p((hdr)-> ike_ispi) ? (__uint64_t)((((__uint64_t)((hdr)->ike_ispi) & 0xff) << 56) | ((__uint64_t)((hdr)->ike_ispi) & 0xff00ULL) << 40 | ((__uint64_t)((hdr)->ike_ispi) & 0xff0000ULL) << 24 | ((__uint64_t)((hdr)->ike_ispi) & 0xff000000ULL) << 8 | ((__uint64_t)((hdr)->ike_ispi ) & 0xff00000000ULL) >> 8 | ((__uint64_t)((hdr)-> ike_ispi) & 0xff0000000000ULL) >> 24 | ((__uint64_t )((hdr)->ike_ispi) & 0xff000000000000ULL) >> 40 | ((__uint64_t)((hdr)->ike_ispi) & 0xff00000000000000ULL ) >> 56) : __swap64md((hdr)->ike_ispi)), ((void*)0)), | |||
609 | print_map(hdr->ike_exchange, ikev2_exchange_map), | |||
610 | msg->msg_response ? "res" : "req", | |||
611 | msg->msg_msgid, | |||
612 | print_host((struct sockaddr *)&msg->msg_peer, NULL((void*)0), 0), | |||
613 | print_host((struct sockaddr *)&msg->msg_local, NULL((void*)0), 0), | |||
614 | ibuf_length(msg->msg_data), | |||
615 | msg->msg_policy->pol_name); | |||
616 | log_debug("%s: ispi %s rspi %s", __func__, | |||
617 | print_spi(betoh64(hdr->ike_ispi)(__uint64_t)(__builtin_constant_p(hdr->ike_ispi) ? (__uint64_t )((((__uint64_t)(hdr->ike_ispi) & 0xff) << 56) | ((__uint64_t)(hdr->ike_ispi) & 0xff00ULL) << 40 | ((__uint64_t)(hdr->ike_ispi) & 0xff0000ULL) << 24 | ((__uint64_t)(hdr->ike_ispi) & 0xff000000ULL) << 8 | ((__uint64_t)(hdr->ike_ispi) & 0xff00000000ULL) >> 8 | ((__uint64_t)(hdr->ike_ispi) & 0xff0000000000ULL) >> 24 | ((__uint64_t)(hdr->ike_ispi) & 0xff000000000000ULL ) >> 40 | ((__uint64_t)(hdr->ike_ispi) & 0xff00000000000000ULL ) >> 56) : __swap64md(hdr->ike_ispi)), 8), | |||
618 | print_spi(betoh64(hdr->ike_rspi)(__uint64_t)(__builtin_constant_p(hdr->ike_rspi) ? (__uint64_t )((((__uint64_t)(hdr->ike_rspi) & 0xff) << 56) | ((__uint64_t)(hdr->ike_rspi) & 0xff00ULL) << 40 | ((__uint64_t)(hdr->ike_rspi) & 0xff0000ULL) << 24 | ((__uint64_t)(hdr->ike_rspi) & 0xff000000ULL) << 8 | ((__uint64_t)(hdr->ike_rspi) & 0xff00000000ULL) >> 8 | ((__uint64_t)(hdr->ike_rspi) & 0xff0000000000ULL) >> 24 | ((__uint64_t)(hdr->ike_rspi) & 0xff000000000000ULL ) >> 40 | ((__uint64_t)(hdr->ike_rspi) & 0xff00000000000000ULL ) >> 56) : __swap64md(hdr->ike_rspi)), 8)); | |||
619 | ||||
620 | if ((sa = msg->msg_sa) == NULL((void*)0)) | |||
621 | goto done; | |||
622 | ||||
623 | sa->sa_last_recvd = gettime(); | |||
624 | ||||
625 | if (hdr->ike_exchange == IKEV2_EXCHANGE_CREATE_CHILD_SA36) | |||
626 | flag = IKED_REQ_CHILDSA0x0080; | |||
627 | if (hdr->ike_exchange == IKEV2_EXCHANGE_INFORMATIONAL37) | |||
628 | flag = IKED_REQ_INF0x0100; | |||
629 | ||||
630 | if (hdr->ike_exchange != IKEV2_EXCHANGE_IKE_SA_INIT34 && | |||
631 | hdr->ike_nextpayload != IKEV2_PAYLOAD_SK46 && | |||
632 | hdr->ike_nextpayload != IKEV2_PAYLOAD_SKF53) | |||
633 | return; | |||
634 | ||||
635 | if (msg->msg_response) { | |||
636 | if (msg->msg_msgid > sa->sa_reqid) | |||
637 | return; | |||
638 | if (hdr->ike_exchange != IKEV2_EXCHANGE_INFORMATIONAL37 && | |||
639 | !ikev2_msg_lookup(env, &sa->sa_requests, msg, hdr) && | |||
640 | sa->sa_fragments.frag_count == 0) | |||
641 | return; | |||
642 | if (flag) { | |||
643 | if ((sa->sa_stateflags & flag) == 0) | |||
644 | return; | |||
645 | /* | |||
646 | * We have initiated this exchange, even if | |||
647 | * we are not the initiator of the IKE SA. | |||
648 | */ | |||
649 | initiator = 1; | |||
650 | } | |||
651 | /* | |||
652 | * There's no need to keep the request (fragments) around | |||
653 | */ | |||
654 | ikev2_msg_lookup_dispose_all(env, &sa->sa_requests, msg, hdr); | |||
655 | } else { | |||
656 | /* | |||
657 | * IKE_SA_INIT is special since it always uses the message id 0. | |||
658 | * Even when the message was rejected, and the new message has | |||
659 | * different proposals, the id will be the same. To discern | |||
660 | * retransmits and new messages, the RFC suggests to compare the | |||
661 | * the messages. | |||
662 | */ | |||
663 | if (sa->sa_state == IKEV2_STATE_CLOSED11 && sa->sa_1stmsg && | |||
664 | hdr->ike_exchange == IKEV2_EXCHANGE_IKE_SA_INIT34 && | |||
665 | msg->msg_msgid == 0 && | |||
666 | (ibuf_length(msg->msg_data) != ibuf_length(sa->sa_1stmsg) || | |||
667 | memcmp(ibuf_data(msg->msg_data), ibuf_data(sa->sa_1stmsg), | |||
668 | ibuf_length(sa->sa_1stmsg)) != 0)) { | |||
669 | ikev2_ike_sa_setreason(sa, NULL((void*)0)); | |||
670 | sa_free(env, sa); | |||
671 | msg->msg_sa = sa = NULL((void*)0); | |||
672 | goto done; | |||
673 | } | |||
674 | if (msg->msg_msgid < sa->sa_msgid) | |||
675 | return; | |||
676 | if (flag) | |||
677 | initiator = 0; | |||
678 | /* | |||
679 | * See if we have responded to this request before | |||
680 | */ | |||
681 | if ((r = ikev2_msg_lookup_retransmit_all(env, &sa->sa_responses, | |||
682 | msg, hdr, sa)) != 0) { | |||
683 | if (r == -1) { | |||
684 | log_warn("%s: failed to retransmit a " | |||
685 | "response", __func__); | |||
686 | ikev2_ike_sa_setreason(sa, | |||
687 | "retransmitting response failed"); | |||
688 | sa_free(env, sa); | |||
689 | } | |||
690 | return; | |||
691 | } else if (sa->sa_msgid_set && msg->msg_msgid == sa->sa_msgid) { | |||
692 | /* | |||
693 | * Response is being worked on, most likely we're | |||
694 | * waiting for the CA process to get back to us | |||
695 | */ | |||
696 | return; | |||
697 | } | |||
698 | sa->sa_msgid_current = msg->msg_msgid; | |||
699 | } | |||
700 | ||||
701 | if (sa_address(sa, &sa->sa_peer, (struct sockaddr *)&msg->msg_peer) | |||
702 | == -1 || | |||
703 | sa_address(sa, &sa->sa_local, (struct sockaddr *)&msg->msg_local) | |||
704 | == -1) | |||
705 | return; | |||
706 | ||||
707 | sa->sa_fd = msg->msg_fd; | |||
708 | ||||
709 | log_debug("%s: updated SA to peer %s local %s", __func__, | |||
710 | print_host((struct sockaddr *)&sa->sa_peer.addr, NULL((void*)0), 0), | |||
711 | print_host((struct sockaddr *)&sa->sa_local.addr, NULL((void*)0), 0)); | |||
712 | ||||
713 | done: | |||
714 | if (initiator) | |||
715 | ikev2_init_recv(env, msg, hdr); | |||
716 | else | |||
717 | ikev2_resp_recv(env, msg, hdr); | |||
718 | ||||
719 | if (sa != NULL((void*)0) && !msg->msg_response && msg->msg_valid) { | |||
720 | /* | |||
721 | * If it's a valid request, make sure to update the peer's | |||
722 | * message ID and dispose of all previous responses. | |||
723 | * We need to set sa_msgid_set in order to distinguish between | |||
724 | * "last msgid was 0" and "msgid not set yet". | |||
725 | */ | |||
726 | sa->sa_msgid = sa->sa_msgid_current; | |||
727 | sa->sa_msgid_set = 1; | |||
728 | ikev2_msg_prevail(env, &sa->sa_responses, msg); | |||
729 | } | |||
730 | ||||
731 | if (sa != NULL((void*)0) && sa->sa_state == IKEV2_STATE_CLOSED11) { | |||
732 | log_debug("%s: closing SA", __func__); | |||
733 | ikev2_ike_sa_setreason(sa, "closed"); | |||
734 | sa_free(env, sa); | |||
735 | } | |||
736 | } | |||
737 | ||||
738 | int | |||
739 | ikev2_ike_auth_compatible(struct iked_sa *sa, uint8_t policy, uint8_t wire) | |||
740 | { | |||
741 | if (wire == IKEV2_AUTH_SIG_ANY255) /* internal, not on wire */ | |||
742 | return (-1); | |||
743 | if (policy == wire || policy == IKEV2_AUTH_NONE0) | |||
744 | return (0); | |||
745 | switch (policy) { | |||
746 | case IKEV2_AUTH_SIG_ANY255: | |||
747 | switch (wire) { | |||
748 | case IKEV2_AUTH_SIG14: | |||
749 | case IKEV2_AUTH_RSA_SIG1: | |||
750 | case IKEV2_AUTH_ECDSA_2569: | |||
751 | case IKEV2_AUTH_ECDSA_38410: | |||
752 | case IKEV2_AUTH_ECDSA_52111: | |||
753 | return (0); | |||
754 | } | |||
755 | break; | |||
756 | case IKEV2_AUTH_SIG14: | |||
757 | case IKEV2_AUTH_RSA_SIG1: | |||
758 | case IKEV2_AUTH_ECDSA_2569: | |||
759 | case IKEV2_AUTH_ECDSA_38410: | |||
760 | case IKEV2_AUTH_ECDSA_52111: | |||
761 | switch (wire) { | |||
762 | /* | |||
763 | * XXX Maybe we need an indication saying: | |||
764 | * XXX Accept AUTH_SIG as long as its DSA? | |||
765 | */ | |||
766 | case IKEV2_AUTH_SIG14: | |||
767 | if (sa->sa_sigsha2) | |||
768 | return (0); | |||
769 | } | |||
770 | break; | |||
771 | } | |||
772 | return (-1); | |||
773 | } | |||
774 | ||||
775 | int | |||
776 | ikev2_auth_verify(struct iked *env, struct iked_sa *sa) | |||
777 | { | |||
778 | struct iked_auth ikeauth; | |||
779 | struct ibuf *authmsg; | |||
780 | int ret; | |||
781 | ||||
782 | memcpy(&ikeauth, &sa->sa_policy->pol_auth, | |||
783 | sizeof(ikeauth)); | |||
784 | ||||
785 | if (sa->sa_policy->pol_auth.auth_eap && | |||
786 | sa->sa_eapmsk != NULL((void*)0)) { | |||
787 | /* | |||
788 | * The initiator EAP auth is a PSK derived | |||
789 | * from the EAP-specific MSK | |||
790 | */ | |||
791 | ikeauth.auth_method = IKEV2_AUTH_SHARED_KEY_MIC2; | |||
792 | ||||
793 | /* Copy session key as PSK */ | |||
794 | memcpy(ikeauth.auth_data, | |||
795 | ibuf_data(sa->sa_eapmsk), | |||
796 | ibuf_size(sa->sa_eapmsk)); | |||
797 | ikeauth.auth_length = ibuf_size(sa->sa_eapmsk); | |||
798 | } | |||
799 | ||||
800 | if (ikev2_ike_auth_compatible(sa, | |||
801 | ikeauth.auth_method, sa->sa_peerauth.id_type) < 0) { | |||
802 | log_warnx("%s: unexpected auth method %s, was " | |||
803 | "expecting %s", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
804 | print_map(sa->sa_peerauth.id_type, | |||
805 | ikev2_auth_map), | |||
806 | print_map(ikeauth.auth_method, | |||
807 | ikev2_auth_map)); | |||
808 | ikev2_send_auth_failed(env, sa); | |||
809 | explicit_bzero(&ikeauth, sizeof(ikeauth)); | |||
810 | return (-1); | |||
811 | } | |||
812 | ikeauth.auth_method = sa->sa_peerauth.id_type; | |||
813 | ||||
814 | if ((authmsg = ikev2_msg_auth(env, sa, | |||
815 | sa->sa_hdr.sh_initiator)) == NULL((void*)0)) { | |||
816 | log_debug("%s: failed to get auth data", | |||
817 | __func__); | |||
818 | ikev2_send_auth_failed(env, sa); | |||
819 | explicit_bzero(&ikeauth, sizeof(ikeauth)); | |||
820 | return (-1); | |||
821 | } | |||
822 | ||||
823 | ret = ikev2_msg_authverify(env, sa, &ikeauth, | |||
824 | ibuf_data(sa->sa_peerauth.id_buf), | |||
825 | ibuf_length(sa->sa_peerauth.id_buf), | |||
826 | authmsg); | |||
827 | ibuf_release(authmsg); | |||
828 | if (ret != 0) { | |||
829 | log_info("%s: ikev2_msg_authverify failed", | |||
830 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
831 | ikev2_send_auth_failed(env, sa); | |||
832 | explicit_bzero(&ikeauth, sizeof(ikeauth)); | |||
833 | return (-1); | |||
834 | } | |||
835 | if (sa->sa_eapmsk != NULL((void*)0)) { | |||
836 | if ((authmsg = ikev2_msg_auth(env, sa, | |||
837 | !sa->sa_hdr.sh_initiator)) == NULL((void*)0)) { | |||
838 | log_debug("%s: failed to get auth data", | |||
839 | __func__); | |||
840 | explicit_bzero(&ikeauth, sizeof(ikeauth)); | |||
841 | return (-1); | |||
842 | } | |||
843 | ||||
844 | /* XXX 2nd AUTH for EAP messages */ | |||
845 | ret = ikev2_msg_authsign(env, sa, &ikeauth, authmsg); | |||
846 | ibuf_release(authmsg); | |||
847 | if (ret != 0) { | |||
848 | ikev2_send_auth_failed(env, sa); | |||
849 | explicit_bzero(&ikeauth, sizeof(ikeauth)); | |||
850 | return (-1); | |||
851 | } | |||
852 | ||||
853 | /* ikev2_msg_authverify verified AUTH */ | |||
854 | sa_stateflags(sa, IKED_REQ_AUTHVALID0x0010); | |||
855 | sa_stateflags(sa, IKED_REQ_EAPVALID0x0040); | |||
856 | sa_state(env, sa, IKEV2_STATE_EAP_SUCCESS4); | |||
857 | } | |||
858 | ||||
859 | explicit_bzero(&ikeauth, sizeof(ikeauth)); | |||
860 | return (0); | |||
861 | } | |||
862 | ||||
863 | int | |||
864 | ikev2_ike_auth_recv(struct iked *env, struct iked_sa *sa, | |||
865 | struct iked_message *msg) | |||
866 | { | |||
867 | struct iked_id *id; | |||
868 | struct ibuf *authmsg; | |||
869 | struct iked_policy *old; | |||
870 | uint8_t *cert = NULL((void*)0); | |||
871 | size_t certlen = 0; | |||
872 | int certtype = IKEV2_CERT_NONE0; | |||
873 | ||||
874 | /* The AUTH payload indicates if the responder wants EAP or not */ | |||
875 | if (msg->msg_auth.id_type != IKEV2_AUTH_NONE0 && | |||
876 | !sa_stateok(sa, IKEV2_STATE_EAP3)) | |||
877 | sa_state(env, sa, IKEV2_STATE_AUTH_REQUEST5); | |||
878 | ||||
879 | if (!sa->sa_hdr.sh_initiator && | |||
880 | !sa_stateok(sa, IKEV2_STATE_AUTH_REQUEST5) && | |||
881 | sa->sa_policy->pol_auth.auth_eap) | |||
882 | sa_state(env, sa, IKEV2_STATE_EAP3); | |||
883 | ||||
884 | if (sa->sa_hdr.sh_initiator) | |||
885 | id = &sa->sa_rid; | |||
886 | else | |||
887 | id = &sa->sa_iid; | |||
888 | ||||
889 | /* try to relookup the policy based on the peerid */ | |||
890 | if (msg->msg_peerid.id_type && !sa->sa_hdr.sh_initiator) { | |||
891 | old = sa->sa_policy; | |||
892 | ||||
893 | sa->sa_policy = NULL((void*)0); | |||
894 | if (policy_lookup(env, msg, &sa->sa_proposals, NULL((void*)0), 0) != 0 || | |||
895 | msg->msg_policy == NULL((void*)0)) { | |||
896 | log_info("%s: no compatible policy found", | |||
897 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
898 | ikev2_send_auth_failed(env, sa); | |||
899 | TAILQ_REMOVE(&old->pol_sapeers, sa, sa_peer_entry)do { if (((sa)->sa_peer_entry.tqe_next) != ((void*)0)) (sa )->sa_peer_entry.tqe_next->sa_peer_entry.tqe_prev = (sa )->sa_peer_entry.tqe_prev; else (&old->pol_sapeers) ->tqh_last = (sa)->sa_peer_entry.tqe_prev; *(sa)->sa_peer_entry .tqe_prev = (sa)->sa_peer_entry.tqe_next; ; ; } while (0); | |||
900 | if (old->pol_flags & IKED_POLICY_REFCNT0x04) | |||
901 | policy_unref(env, old); | |||
902 | return (-1); | |||
903 | } | |||
904 | if (msg->msg_policy != old) { | |||
905 | /* Clean up old policy */ | |||
906 | TAILQ_REMOVE(&old->pol_sapeers, sa, sa_peer_entry)do { if (((sa)->sa_peer_entry.tqe_next) != ((void*)0)) (sa )->sa_peer_entry.tqe_next->sa_peer_entry.tqe_prev = (sa )->sa_peer_entry.tqe_prev; else (&old->pol_sapeers) ->tqh_last = (sa)->sa_peer_entry.tqe_prev; *(sa)->sa_peer_entry .tqe_prev = (sa)->sa_peer_entry.tqe_next; ; ; } while (0); | |||
907 | if (old->pol_flags & IKED_POLICY_REFCNT0x04) | |||
908 | policy_unref(env, old); | |||
909 | ||||
910 | /* Update SA with new policy*/ | |||
911 | if (sa_new(env, sa->sa_hdr.sh_ispi, | |||
912 | sa->sa_hdr.sh_rspi, 0, msg->msg_policy) != sa) { | |||
913 | log_warnx("%s: failed to update SA", | |||
914 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
915 | ikev2_send_auth_failed(env, sa); | |||
916 | return (-1); | |||
917 | } | |||
918 | } else { | |||
919 | /* restore */ | |||
920 | msg->msg_policy = sa->sa_policy = old; | |||
921 | } | |||
922 | if (ikev2_handle_certreq(env, msg) != 0) | |||
923 | return (-1); | |||
924 | } else if (sa->sa_hdr.sh_initiator) { | |||
925 | old = sa->sa_policy; | |||
926 | ||||
927 | /* verify policy on initiator */ | |||
928 | sa->sa_policy = NULL((void*)0); | |||
929 | if (policy_lookup(env, msg, &sa->sa_proposals, &old->pol_flows, | |||
930 | old->pol_nflows) != 0 || msg->msg_policy != old) { | |||
931 | ||||
932 | /* get dstid */ | |||
933 | if (msg->msg_peerid.id_type) { | |||
934 | memcpy(id, &msg->msg_peerid, sizeof(*id)); | |||
935 | bzero(&msg->msg_peerid, sizeof(msg->msg_peerid)); | |||
936 | } | |||
937 | log_warnx("%s: policy mismatch", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
938 | ikev2_send_auth_failed(env, sa); | |||
939 | TAILQ_REMOVE(&old->pol_sapeers, sa, sa_peer_entry)do { if (((sa)->sa_peer_entry.tqe_next) != ((void*)0)) (sa )->sa_peer_entry.tqe_next->sa_peer_entry.tqe_prev = (sa )->sa_peer_entry.tqe_prev; else (&old->pol_sapeers) ->tqh_last = (sa)->sa_peer_entry.tqe_prev; *(sa)->sa_peer_entry .tqe_prev = (sa)->sa_peer_entry.tqe_next; ; ; } while (0); | |||
940 | if (old->pol_flags & IKED_POLICY_REFCNT0x04) | |||
941 | policy_unref(env, old); | |||
942 | return (-1); | |||
943 | } | |||
944 | /* restore */ | |||
945 | msg->msg_policy = sa->sa_policy = old; | |||
946 | } | |||
947 | ||||
948 | /* AUTH payload is required for non-EAP */ | |||
949 | if (!msg->msg_auth.id_type && | |||
950 | !sa->sa_policy->pol_auth.auth_eap) { | |||
951 | /* get dstid */ | |||
952 | if (msg->msg_peerid.id_type) { | |||
953 | memcpy(id, &msg->msg_peerid, sizeof(*id)); | |||
954 | bzero(&msg->msg_peerid, sizeof(msg->msg_peerid)); | |||
955 | } | |||
956 | log_debug("%s: missing auth payload", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
957 | ikev2_send_auth_failed(env, sa); | |||
958 | return (-1); | |||
959 | } | |||
960 | ||||
961 | if (msg->msg_peerid.id_type) { | |||
962 | memcpy(id, &msg->msg_peerid, sizeof(*id)); | |||
963 | bzero(&msg->msg_peerid, sizeof(msg->msg_peerid)); | |||
964 | ||||
965 | if (!sa->sa_hdr.sh_initiator) { | |||
966 | if ((authmsg = ikev2_msg_auth(env, sa, | |||
967 | !sa->sa_hdr.sh_initiator)) == NULL((void*)0)) { | |||
968 | log_debug("%s: failed to get response " | |||
969 | "auth data", __func__); | |||
970 | return (-1); | |||
971 | } | |||
972 | ||||
973 | ca_setauth(env, sa, authmsg, PROC_CERT); | |||
974 | ibuf_release(authmsg); | |||
975 | } | |||
976 | } | |||
977 | ||||
978 | if (!TAILQ_EMPTY(&msg->msg_proposals)(((&msg->msg_proposals)->tqh_first) == ((void*)0))) { | |||
979 | if (proposals_negotiate(&sa->sa_proposals, | |||
980 | &sa->sa_policy->pol_proposals, &msg->msg_proposals, | |||
981 | 0, -1) != 0) { | |||
982 | log_info("%s: no proposal chosen", __func__); | |||
983 | msg->msg_error = IKEV2_N_NO_PROPOSAL_CHOSEN14; | |||
984 | return (-1); | |||
985 | } else | |||
986 | sa_stateflags(sa, IKED_REQ_SA0x0020); | |||
987 | } | |||
988 | ||||
989 | if (msg->msg_auth.id_type) { | |||
990 | memcpy(&sa->sa_peerauth, &msg->msg_auth, sizeof(sa->sa_peerauth)); | |||
991 | bzero(&msg->msg_auth, sizeof(msg->msg_auth)); | |||
992 | } | |||
993 | ||||
994 | if (msg->msg_cp) { | |||
995 | if (msg->msg_cp_addr) { | |||
996 | sa->sa_cp_addr = msg->msg_cp_addr; | |||
997 | msg->msg_cp_addr = NULL((void*)0); | |||
998 | } | |||
999 | if (msg->msg_cp_addr6) { | |||
1000 | sa->sa_cp_addr6 = msg->msg_cp_addr6; | |||
1001 | msg->msg_cp_addr6 = NULL((void*)0); | |||
1002 | } | |||
1003 | if (msg->msg_cp_dns) { | |||
1004 | sa->sa_cp_dns = msg->msg_cp_dns; | |||
1005 | msg->msg_cp_dns = NULL((void*)0); | |||
1006 | } | |||
1007 | sa->sa_cp = msg->msg_cp; | |||
1008 | } | |||
1009 | ||||
1010 | /* For EAP and PSK AUTH can be verified without the CA process*/ | |||
1011 | if ((sa->sa_policy->pol_auth.auth_eap && | |||
1012 | sa->sa_eapmsk != NULL((void*)0)) || | |||
1013 | sa->sa_policy->pol_auth.auth_method == IKEV2_AUTH_SHARED_KEY_MIC2) | |||
1014 | ikev2_auth_verify(env, sa); | |||
1015 | /* For CERT and Pubkey AUTH the CA process must find a matching key */ | |||
1016 | else if (sa->sa_peerauth.id_type) { | |||
1017 | if (msg->msg_cert.id_type) { | |||
1018 | certtype = msg->msg_cert.id_type; | |||
1019 | cert = ibuf_data(msg->msg_cert.id_buf); | |||
1020 | certlen = ibuf_length(msg->msg_cert.id_buf); | |||
1021 | } | |||
1022 | sa->sa_stateflags &= ~IKED_REQ_CERTVALID0x0002; | |||
1023 | if (ca_setcert(env, &sa->sa_hdr, id, certtype, cert, certlen, PROC_CERT) == -1) | |||
1024 | return (-1); | |||
1025 | } | |||
1026 | ||||
1027 | if (sa->sa_cp == IKEV2_CP_REPLY2) { | |||
1028 | if (sa->sa_cp_addr) | |||
1029 | log_info("%s: obtained lease: %s", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
1030 | print_host((struct sockaddr *)&sa->sa_cp_addr->addr, | |||
1031 | NULL((void*)0), 0)); | |||
1032 | if (sa->sa_cp_addr6) | |||
1033 | log_info("%s: obtained lease: %s", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
1034 | print_host((struct sockaddr *)&sa->sa_cp_addr6->addr, | |||
1035 | NULL((void*)0), 0)); | |||
1036 | if (sa->sa_cp_dns) | |||
1037 | log_info("%s: obtained DNS: %s", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
1038 | print_host((struct sockaddr *)&sa->sa_cp_dns->addr, | |||
1039 | NULL((void*)0), 0)); | |||
1040 | } | |||
1041 | ||||
1042 | return ikev2_ike_auth(env, sa); | |||
1043 | } | |||
1044 | ||||
1045 | int | |||
1046 | ikev2_ike_auth(struct iked *env, struct iked_sa *sa) | |||
1047 | { | |||
1048 | /* Attempt state transition */ | |||
1049 | if (sa->sa_state == IKEV2_STATE_EAP_SUCCESS4) | |||
1050 | sa_state(env, sa, IKEV2_STATE_EAP_VALID8); | |||
1051 | else if (sa->sa_state == IKEV2_STATE_AUTH_SUCCESS6) | |||
1052 | sa_state(env, sa, IKEV2_STATE_VALID7); | |||
1053 | ||||
1054 | if (sa->sa_hdr.sh_initiator) { | |||
1055 | if (sa_stateok(sa, IKEV2_STATE_AUTH_SUCCESS6)) | |||
1056 | return (ikev2_init_done(env, sa)); | |||
1057 | /* AUTH exchange is awaiting response from CA process, ignore */ | |||
1058 | else if (sa_stateok(sa, IKEV2_STATE_AUTH_REQUEST5)) | |||
1059 | return (0); | |||
1060 | else | |||
1061 | return (ikev2_init_ike_auth(env, sa)); | |||
1062 | } | |||
1063 | return (ikev2_resp_ike_auth(env, sa)); | |||
1064 | } | |||
1065 | ||||
1066 | void | |||
1067 | ikev2_init_recv(struct iked *env, struct iked_message *msg, | |||
1068 | struct ike_header *hdr) | |||
1069 | { | |||
1070 | struct iked_sa *sa; | |||
1071 | struct iked_policy *pol; | |||
1072 | ||||
1073 | if (ikev2_msg_valid_ike_sa(env, hdr, msg) == -1) { | |||
1074 | log_debug("%s: unknown SA", __func__); | |||
1075 | return; | |||
1076 | } | |||
1077 | sa = msg->msg_sa; | |||
1078 | ||||
1079 | switch (hdr->ike_exchange) { | |||
1080 | case IKEV2_EXCHANGE_IKE_SA_INIT34: | |||
1081 | /* Update the SPIs */ | |||
1082 | if ((sa = sa_new(env, | |||
1083 | betoh64(hdr->ike_ispi)(__uint64_t)(__builtin_constant_p(hdr->ike_ispi) ? (__uint64_t )((((__uint64_t)(hdr->ike_ispi) & 0xff) << 56) | ((__uint64_t)(hdr->ike_ispi) & 0xff00ULL) << 40 | ((__uint64_t)(hdr->ike_ispi) & 0xff0000ULL) << 24 | ((__uint64_t)(hdr->ike_ispi) & 0xff000000ULL) << 8 | ((__uint64_t)(hdr->ike_ispi) & 0xff00000000ULL) >> 8 | ((__uint64_t)(hdr->ike_ispi) & 0xff0000000000ULL) >> 24 | ((__uint64_t)(hdr->ike_ispi) & 0xff000000000000ULL ) >> 40 | ((__uint64_t)(hdr->ike_ispi) & 0xff00000000000000ULL ) >> 56) : __swap64md(hdr->ike_ispi)), betoh64(hdr->ike_rspi)(__uint64_t)(__builtin_constant_p(hdr->ike_rspi) ? (__uint64_t )((((__uint64_t)(hdr->ike_rspi) & 0xff) << 56) | ((__uint64_t)(hdr->ike_rspi) & 0xff00ULL) << 40 | ((__uint64_t)(hdr->ike_rspi) & 0xff0000ULL) << 24 | ((__uint64_t)(hdr->ike_rspi) & 0xff000000ULL) << 8 | ((__uint64_t)(hdr->ike_rspi) & 0xff00000000ULL) >> 8 | ((__uint64_t)(hdr->ike_rspi) & 0xff0000000000ULL) >> 24 | ((__uint64_t)(hdr->ike_rspi) & 0xff000000000000ULL ) >> 40 | ((__uint64_t)(hdr->ike_rspi) & 0xff00000000000000ULL ) >> 56) : __swap64md(hdr->ike_rspi)), 1, | |||
1084 | NULL((void*)0))) == NULL((void*)0) || sa != msg->msg_sa) { | |||
1085 | log_debug("%s: invalid new SA", __func__); | |||
1086 | if (sa) { | |||
1087 | ikev2_ike_sa_setreason(sa, "invalid new SA"); | |||
1088 | sa_free(env, sa); | |||
1089 | } | |||
1090 | return; | |||
1091 | } | |||
1092 | break; | |||
1093 | case IKEV2_EXCHANGE_IKE_AUTH35: | |||
1094 | case IKEV2_EXCHANGE_CREATE_CHILD_SA36: | |||
1095 | case IKEV2_EXCHANGE_INFORMATIONAL37: | |||
1096 | break; | |||
1097 | default: | |||
1098 | log_debug("%s: unsupported exchange: %s", __func__, | |||
1099 | print_map(hdr->ike_exchange, ikev2_exchange_map)); | |||
1100 | return; | |||
1101 | } | |||
1102 | ||||
1103 | if (ikev2_pld_parse(env, hdr, msg, msg->msg_offset) != 0) { | |||
1104 | log_debug("%s: failed to parse message", __func__); | |||
1105 | return; | |||
1106 | } | |||
1107 | ||||
1108 | if (sa->sa_fragments.frag_count != 0) | |||
1109 | return; | |||
1110 | ||||
1111 | if (!ikev2_msg_frompeer(msg)) | |||
1112 | return; | |||
1113 | ||||
1114 | if (ikev2_handle_notifies(env, msg) != 0) | |||
1115 | return; | |||
1116 | ||||
1117 | if (msg->msg_nat_detected && sa->sa_natt == 0) | |||
1118 | ikev2_enable_natt(env, sa, msg, 1); | |||
1119 | ||||
1120 | switch (hdr->ike_exchange) { | |||
1121 | case IKEV2_EXCHANGE_IKE_SA_INIT34: | |||
1122 | if (ibuf_length(msg->msg_cookie)) { | |||
1123 | pol = sa->sa_policy; | |||
1124 | if (ikev2_init_ike_sa_peer(env, pol, | |||
1125 | &pol->pol_peer, msg) != 0) | |||
1126 | log_warnx("%s: failed to initiate a " | |||
1127 | "IKE_SA_INIT exchange", SPI_SA(sa,ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))) | |||
1128 | __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
1129 | break; | |||
1130 | } | |||
1131 | if (msg->msg_flags & IKED_MSG_FLAGS_NO_PROPOSAL_CHOSEN0x0400) { | |||
1132 | log_info("%s: failed to negotiate IKE SA", | |||
1133 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
1134 | ikev2_ike_sa_setreason(sa, "no proposal chosen"); | |||
1135 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
1136 | msg->msg_sa = NULL((void*)0); | |||
1137 | return; | |||
1138 | } | |||
1139 | if (ikev2_handle_certreq(env, msg) != 0) | |||
1140 | return; | |||
1141 | ||||
1142 | if (ikev2_init_auth(env, msg) != 0) { | |||
1143 | ikev2_ike_sa_setreason(sa, | |||
1144 | "failed to initiate IKE_AUTH exchange"); | |||
1145 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
1146 | msg->msg_sa = NULL((void*)0); | |||
1147 | return; | |||
1148 | } | |||
1149 | break; | |||
1150 | case IKEV2_EXCHANGE_IKE_AUTH35: | |||
1151 | if (msg->msg_flags & IKED_MSG_FLAGS_AUTHENTICATION_FAILED0x0020) { | |||
1152 | log_debug("%s: AUTHENTICATION_FAILED, closing SA", | |||
1153 | __func__); | |||
1154 | ikev2_log_cert_info(SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
1155 | sa->sa_hdr.sh_initiator ? &sa->sa_rcert | |||
1156 | : &sa->sa_icert); | |||
1157 | ikev2_ike_sa_setreason(sa, | |||
1158 | "authentication failed notification from peer"); | |||
1159 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
1160 | msg->msg_sa = NULL((void*)0); | |||
1161 | return; | |||
1162 | } | |||
1163 | if (msg->msg_flags & IKED_MSG_FLAGS_NO_PROPOSAL_CHOSEN0x0400) { | |||
1164 | log_info("%s: failed to negotiate IKE SA", | |||
1165 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
1166 | ikev2_ike_sa_setreason(sa, "no proposal chosen (IKE SA)"); | |||
1167 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
1168 | msg->msg_sa = NULL((void*)0); | |||
1169 | return; | |||
1170 | } | |||
1171 | ||||
1172 | (void)ikev2_ike_auth_recv(env, sa, msg); | |||
1173 | break; | |||
1174 | case IKEV2_EXCHANGE_CREATE_CHILD_SA36: | |||
1175 | if (msg->msg_flags & IKED_MSG_FLAGS_NO_PROPOSAL_CHOSEN0x0400) { | |||
1176 | log_info("%s: CREATE_CHILD_SA failed", | |||
1177 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
1178 | ikev2_ike_sa_setreason(sa, "no proposal chosen (CHILD SA)"); | |||
1179 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
1180 | msg->msg_sa = NULL((void*)0); | |||
1181 | return; | |||
1182 | } | |||
1183 | (void)ikev2_init_create_child_sa(env, msg); | |||
1184 | break; | |||
1185 | case IKEV2_EXCHANGE_INFORMATIONAL37: | |||
1186 | sa->sa_stateflags &= ~IKED_REQ_INF0x0100; | |||
1187 | break; | |||
1188 | default: | |||
1189 | log_debug("%s: exchange %s not implemented", __func__, | |||
1190 | print_map(hdr->ike_exchange, ikev2_exchange_map)); | |||
1191 | break; | |||
1192 | } | |||
1193 | } | |||
1194 | ||||
1195 | void | |||
1196 | ikev2_enable_natt(struct iked *env, struct iked_sa *sa, | |||
1197 | struct iked_message *msg, int udpencap) | |||
1198 | { | |||
1199 | struct iked_socket *sock; | |||
1200 | in_port_t port; | |||
1201 | ||||
1202 | sock = ikev2_msg_getsocket(env, sa->sa_local.addr_af, 1); | |||
1203 | if (sock == NULL((void*)0)) | |||
1204 | return; | |||
1205 | ||||
1206 | /* | |||
1207 | * Update address information and use the NAT-T | |||
1208 | * port and socket, if available. | |||
1209 | */ | |||
1210 | port = htons(socket_getport((__uint16_t)(__builtin_constant_p(socket_getport( (struct sockaddr *)&sock->sock_addr)) ? (__uint16_t)(((__uint16_t)(socket_getport ( (struct sockaddr *)&sock->sock_addr)) & 0xffU) << 8 | ((__uint16_t)(socket_getport( (struct sockaddr *)&sock ->sock_addr)) & 0xff00U) >> 8) : __swap16md(socket_getport ( (struct sockaddr *)&sock->sock_addr))) | |||
1211 | (struct sockaddr *)&sock->sock_addr))(__uint16_t)(__builtin_constant_p(socket_getport( (struct sockaddr *)&sock->sock_addr)) ? (__uint16_t)(((__uint16_t)(socket_getport ( (struct sockaddr *)&sock->sock_addr)) & 0xffU) << 8 | ((__uint16_t)(socket_getport( (struct sockaddr *)&sock ->sock_addr)) & 0xff00U) >> 8) : __swap16md(socket_getport ( (struct sockaddr *)&sock->sock_addr))); | |||
1212 | sa->sa_local.addr_port = port; | |||
1213 | sa->sa_peer.addr_port = port; | |||
1214 | (void)socket_af((struct sockaddr *)&sa->sa_local.addr, port); | |||
1215 | (void)socket_af((struct sockaddr *)&sa->sa_peer.addr, port); | |||
1216 | ||||
1217 | msg->msg_fd = sa->sa_fd = sock->sock_fd; | |||
1218 | msg->msg_sock = sock; | |||
1219 | sa->sa_natt = 1; | |||
1220 | if (udpencap) | |||
1221 | sa->sa_udpencap = 1; | |||
1222 | ||||
1223 | log_debug("%s: detected NAT, enabling UDP encapsulation," | |||
1224 | " updated SA to peer %s local %s", __func__, | |||
1225 | print_host((struct sockaddr *)&sa->sa_peer.addr, NULL((void*)0), 0), | |||
1226 | print_host((struct sockaddr *)&sa->sa_local.addr, NULL((void*)0), 0)); | |||
1227 | } | |||
1228 | ||||
1229 | void | |||
1230 | ikev2_init_ike_sa(struct iked *env, void *arg) | |||
1231 | { | |||
1232 | struct iked_policy *pol; | |||
1233 | ||||
1234 | TAILQ_FOREACH(pol, &env->sc_policies, pol_entry)for((pol) = ((&env->sc_policies)->tqh_first); (pol) != ((void*)0); (pol) = ((pol)->pol_entry.tqe_next)) { | |||
1235 | if ((pol->pol_flags & IKED_POLICY_ACTIVE0x02) == 0) | |||
1236 | continue; | |||
1237 | if (!TAILQ_EMPTY(&pol->pol_sapeers)(((&pol->pol_sapeers)->tqh_first) == ((void*)0))) { | |||
1238 | log_debug("%s: \"%s\" is already active", | |||
1239 | __func__, pol->pol_name); | |||
1240 | continue; | |||
1241 | } | |||
1242 | ||||
1243 | log_info("%s: initiating \"%s\"", __func__, pol->pol_name); | |||
1244 | ||||
1245 | if (ikev2_init_ike_sa_peer(env, pol, &pol->pol_peer, NULL((void*)0))) | |||
1246 | log_debug("%s: failed to initiate with peer %s", | |||
1247 | __func__, | |||
1248 | print_host((struct sockaddr *)&pol->pol_peer.addr, | |||
1249 | NULL((void*)0), 0)); | |||
1250 | } | |||
1251 | ||||
1252 | timer_set(env, &env->sc_inittmr, ikev2_init_ike_sa, NULL((void*)0)); | |||
1253 | timer_add(env, &env->sc_inittmr, IKED_INITIATOR_INTERVAL60); | |||
1254 | } | |||
1255 | ||||
1256 | void | |||
1257 | ikev2_init_ike_sa_timeout(struct iked *env, void *arg) | |||
1258 | { | |||
1259 | struct iked_sa *sa = arg; | |||
1260 | ||||
1261 | log_debug("%s: ispi %s rspi %s", __func__, | |||
1262 | print_spi(sa->sa_hdr.sh_ispi, 8), | |||
1263 | print_spi(sa->sa_hdr.sh_rspi, 8)); | |||
1264 | ||||
1265 | ikev2_ike_sa_setreason(sa, "SA_INIT timeout"); | |||
1266 | sa_free(env, sa); | |||
1267 | } | |||
1268 | ||||
1269 | int | |||
1270 | ikev2_init_ike_sa_peer(struct iked *env, struct iked_policy *pol, | |||
1271 | struct iked_addr *peer, struct iked_message *retry) | |||
1272 | { | |||
1273 | struct sockaddr_storage ss; | |||
1274 | struct iked_message req; | |||
1275 | struct ike_header *hdr; | |||
1276 | struct ikev2_payload *pld; | |||
1277 | struct ikev2_keyexchange *ke; | |||
1278 | struct ikev2_notify *n; | |||
1279 | struct iked_sa *sa = NULL((void*)0); | |||
1280 | struct ibuf *buf, *cookie = NULL((void*)0); | |||
1281 | struct dh_group *group; | |||
1282 | ssize_t len; | |||
1283 | int ret = -1; | |||
1284 | struct iked_socket *sock; | |||
1285 | in_port_t port; | |||
1286 | ||||
1287 | if ((sock = ikev2_msg_getsocket(env, peer->addr_af, 0)) == NULL((void*)0)) | |||
1288 | return (-1); | |||
1289 | ||||
1290 | if (retry != NULL((void*)0)) { | |||
1291 | sa = retry->msg_sa; | |||
1292 | cookie = retry->msg_cookie; | |||
1293 | sa_state(env, sa, IKEV2_STATE_INIT0); | |||
1294 | } | |||
1295 | ||||
1296 | /* Create a new initiator SA */ | |||
1297 | if (sa == NULL((void*)0) && | |||
1298 | (sa = sa_new(env, 0, 0, 1, pol)) == NULL((void*)0)) | |||
1299 | return (-1); | |||
1300 | ||||
1301 | /* Pick peer's DH group if asked */ | |||
1302 | if (pol->pol_peerdh > 0 && sa->sa_dhgroupsa_kex.kex_dhgroup == NULL((void*)0) && | |||
1303 | (sa->sa_dhgroupsa_kex.kex_dhgroup = group_get(pol->pol_peerdh)) == NULL((void*)0)) { | |||
1304 | log_warnx("%s: invalid peer DH group %u", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
1305 | pol->pol_peerdh); | |||
1306 | goto closeonly; | |||
1307 | } | |||
1308 | sa->sa_reqid = 0; | |||
1309 | ||||
1310 | if (ikev2_sa_initiator(env, sa, NULL((void*)0), NULL((void*)0)) == -1) | |||
1311 | goto closeonly; | |||
1312 | ||||
1313 | if (pol->pol_local.addr.ss_family == AF_UNSPEC0) { | |||
1314 | if (socket_getaddr(sock->sock_fd, &ss) == -1) | |||
1315 | goto closeonly; | |||
1316 | } else | |||
1317 | memcpy(&ss, &pol->pol_local.addr, pol->pol_local.addr.ss_len); | |||
1318 | ||||
1319 | if ((buf = ikev2_msg_init(env, &req, &peer->addr, peer->addr.ss_len, | |||
1320 | &ss, ss.ss_len, 0)) == NULL((void*)0)) | |||
1321 | goto done; | |||
1322 | ||||
1323 | /* Inherit the port from the 1st send socket */ | |||
1324 | port = htons(socket_getport((struct sockaddr *)&sock->sock_addr))(__uint16_t)(__builtin_constant_p(socket_getport((struct sockaddr *)&sock->sock_addr)) ? (__uint16_t)(((__uint16_t)(socket_getport ((struct sockaddr *)&sock->sock_addr)) & 0xffU) << 8 | ((__uint16_t)(socket_getport((struct sockaddr *)&sock ->sock_addr)) & 0xff00U) >> 8) : __swap16md(socket_getport ((struct sockaddr *)&sock->sock_addr))); | |||
1325 | (void)socket_af((struct sockaddr *)&req.msg_local, port); | |||
1326 | (void)socket_af((struct sockaddr *)&req.msg_peer, port); | |||
1327 | ||||
1328 | req.msg_fd = sock->sock_fd; | |||
1329 | req.msg_sa = sa; | |||
1330 | req.msg_sock = sock; | |||
1331 | req.msg_msgid = ikev2_msg_id(env, sa); | |||
1332 | ||||
1333 | /* IKE header */ | |||
1334 | if ((hdr = ikev2_add_header(buf, sa, req.msg_msgid, | |||
1335 | cookie == NULL((void*)0) ? IKEV2_PAYLOAD_SA33 : IKEV2_PAYLOAD_NOTIFY41, | |||
1336 | IKEV2_EXCHANGE_IKE_SA_INIT34, 0)) == NULL((void*)0)) | |||
1337 | goto done; | |||
1338 | ||||
1339 | /* Reflect COOKIE */ | |||
1340 | if (cookie) { | |||
1341 | if ((pld = ikev2_add_payload(buf)) == NULL((void*)0)) | |||
1342 | goto done; | |||
1343 | if ((n = ibuf_advance(buf, sizeof(*n))) == NULL((void*)0)) | |||
1344 | goto done; | |||
1345 | n->n_protoid = IKEV2_SAPROTO_NONE0; | |||
1346 | n->n_spisize = 0; | |||
1347 | n->n_type = htobe16(IKEV2_N_COOKIE)(__uint16_t)(__builtin_constant_p(16390) ? (__uint16_t)(((__uint16_t )(16390) & 0xffU) << 8 | ((__uint16_t)(16390) & 0xff00U) >> 8) : __swap16md(16390)); | |||
1348 | if (ikev2_add_buf(buf, cookie) == -1) | |||
1349 | goto done; | |||
1350 | len = sizeof(*n) + ibuf_size(cookie); | |||
1351 | ||||
1352 | log_debug("%s: added cookie, len %zu", __func__, | |||
1353 | ibuf_size(cookie)); | |||
1354 | print_hex(ibuf_data(cookie), 0, ibuf_size(cookie)); | |||
1355 | ||||
1356 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_SA33) == -1) | |||
1357 | goto done; | |||
1358 | } | |||
1359 | ||||
1360 | /* SA payload */ | |||
1361 | if ((pld = ikev2_add_payload(buf)) == NULL((void*)0)) | |||
1362 | goto done; | |||
1363 | if ((len = ikev2_add_proposals(env, sa, buf, &pol->pol_proposals, | |||
1364 | IKEV2_SAPROTO_IKE1, sa->sa_hdr.sh_initiator, 0, 0)) == -1) | |||
1365 | goto done; | |||
1366 | ||||
1367 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_KE34) == -1) | |||
1368 | goto done; | |||
1369 | ||||
1370 | /* KE payload */ | |||
1371 | if ((pld = ikev2_add_payload(buf)) == NULL((void*)0)) | |||
1372 | goto done; | |||
1373 | if ((ke = ibuf_advance(buf, sizeof(*ke))) == NULL((void*)0)) | |||
1374 | goto done; | |||
1375 | if ((group = sa->sa_dhgroupsa_kex.kex_dhgroup) == NULL((void*)0)) { | |||
1376 | log_debug("%s: invalid dh", __func__); | |||
1377 | goto done; | |||
1378 | } | |||
1379 | ke->kex_dhgroup = htobe16(group->id)(__uint16_t)(__builtin_constant_p(group->id) ? (__uint16_t )(((__uint16_t)(group->id) & 0xffU) << 8 | ((__uint16_t )(group->id) & 0xff00U) >> 8) : __swap16md(group ->id)); | |||
1380 | if (ikev2_add_buf(buf, sa->sa_dhiexchangesa_kex.kex_dhiexchange) == -1) | |||
1381 | goto done; | |||
1382 | len = sizeof(*ke) + ibuf_length(sa->sa_dhiexchangesa_kex.kex_dhiexchange); | |||
1383 | ||||
1384 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONCE40) == -1) | |||
1385 | goto done; | |||
1386 | ||||
1387 | /* NONCE payload */ | |||
1388 | if ((pld = ikev2_add_payload(buf)) == NULL((void*)0)) | |||
1389 | goto done; | |||
1390 | if (ikev2_add_buf(buf, sa->sa_inoncesa_kex.kex_inonce) == -1) | |||
1391 | goto done; | |||
1392 | len = ibuf_size(sa->sa_inoncesa_kex.kex_inonce); | |||
1393 | ||||
1394 | /* Fragmentation Notify */ | |||
1395 | if (env->sc_fragsc_static.st_frag) { | |||
1396 | if ((len = ikev2_add_fragmentation(buf, &pld, len)) | |||
1397 | == -1) | |||
1398 | goto done; | |||
1399 | } | |||
1400 | ||||
1401 | if (env->sc_nattmode != NATT_DISABLE) { | |||
1402 | if (ntohs(port)(__uint16_t)(__builtin_constant_p(port) ? (__uint16_t)(((__uint16_t )(port) & 0xffU) << 8 | ((__uint16_t)(port) & 0xff00U ) >> 8) : __swap16md(port)) == env->sc_nattportsc_static.st_nattport) { | |||
1403 | /* Enforce NAT-T on the initiator side */ | |||
1404 | log_debug("%s: enforcing NAT-T", __func__); | |||
1405 | req.msg_natt = sa->sa_natt = sa->sa_udpencap = 1; | |||
1406 | } | |||
1407 | if ((len = ikev2_add_nat_detection(env, buf, &pld, &req, len)) | |||
1408 | == -1) | |||
1409 | goto done; | |||
1410 | } | |||
1411 | ||||
1412 | if ((len = ikev2_add_sighashnotify(buf, &pld, len)) == -1) | |||
1413 | goto done; | |||
1414 | ||||
1415 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONE0) == -1) | |||
1416 | goto done; | |||
1417 | ||||
1418 | if (ikev2_set_header(hdr, ibuf_size(buf) - sizeof(*hdr)) == -1) | |||
1419 | goto done; | |||
1420 | ||||
1421 | (void)ikev2_pld_parse(env, hdr, &req, 0); | |||
1422 | ||||
1423 | ibuf_release(sa->sa_1stmsg); | |||
1424 | if ((sa->sa_1stmsg = ibuf_dup(buf)) == NULL((void*)0)) { | |||
1425 | log_debug("%s: failed to copy 1st message", __func__); | |||
1426 | goto done; | |||
1427 | } | |||
1428 | ||||
1429 | if ((ret = ikev2_msg_send(env, &req)) == 0) | |||
1430 | sa_state(env, sa, IKEV2_STATE_SA_INIT2); | |||
1431 | ||||
1432 | /* Setup exchange timeout. */ | |||
1433 | timer_set(env, &sa->sa_timer, ikev2_init_ike_sa_timeout, sa); | |||
1434 | timer_add(env, &sa->sa_timer, IKED_IKE_SA_EXCHANGE_TIMEOUT300); | |||
1435 | ||||
1436 | done: | |||
1437 | ikev2_msg_cleanup(env, &req); | |||
1438 | closeonly: | |||
1439 | if (ret == -1) { | |||
1440 | log_debug("%s: closing SA", __func__); | |||
1441 | ikev2_ike_sa_setreason(sa, "failed to send SA_INIT"); | |||
1442 | sa_free(env, sa); | |||
1443 | } | |||
1444 | ||||
1445 | return (ret); | |||
1446 | } | |||
1447 | ||||
1448 | int | |||
1449 | ikev2_init_auth(struct iked *env, struct iked_message *msg) | |||
1450 | { | |||
1451 | struct iked_sa *sa = msg->msg_sa; | |||
1452 | struct ibuf *authmsg; | |||
1453 | ||||
1454 | if (sa == NULL((void*)0)) | |||
1455 | return (-1); | |||
1456 | ||||
1457 | if (ikev2_sa_initiator(env, sa, NULL((void*)0), msg) == -1) { | |||
1458 | log_info("%s: failed to get IKE keys", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
1459 | return (-1); | |||
1460 | } | |||
1461 | ||||
1462 | if ((authmsg = ikev2_msg_auth(env, sa, | |||
1463 | !sa->sa_hdr.sh_initiator)) == NULL((void*)0)) { | |||
1464 | log_info("%s: failed to get auth data", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
1465 | return (-1); | |||
1466 | } | |||
1467 | ||||
1468 | if (ca_setauth(env, sa, authmsg, PROC_CERT) == -1) { | |||
1469 | log_info("%s: failed to get cert", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
1470 | ibuf_release(authmsg); | |||
1471 | return (-1); | |||
1472 | } | |||
1473 | ibuf_release(authmsg); | |||
1474 | ||||
1475 | return (ikev2_init_ike_auth(env, sa)); | |||
1476 | } | |||
1477 | ||||
1478 | int | |||
1479 | ikev2_init_ike_auth(struct iked *env, struct iked_sa *sa) | |||
1480 | { | |||
1481 | struct iked_policy *pol = sa->sa_policy; | |||
1482 | struct ikev2_payload *pld; | |||
1483 | struct ikev2_cert *cert; | |||
1484 | struct ikev2_auth *auth; | |||
1485 | struct iked_id *id, *certid, peerid; | |||
1486 | struct ibuf *e = NULL((void*)0); | |||
1487 | uint8_t firstpayload; | |||
1488 | int ret = -1; | |||
1489 | ssize_t len; | |||
1490 | ||||
1491 | if (!sa_stateok(sa, IKEV2_STATE_SA_INIT2)) | |||
1492 | return (0); | |||
1493 | ||||
1494 | if (!sa->sa_localauth.id_type) { | |||
1495 | log_debug("%s: no local auth", __func__); | |||
1496 | return (0); | |||
1497 | } | |||
1498 | ||||
1499 | /* New encrypted message buffer */ | |||
1500 | if ((e = ibuf_static()) == NULL((void*)0)) | |||
1501 | goto done; | |||
1502 | ||||
1503 | id = &sa->sa_iid; | |||
1504 | certid = &sa->sa_icert; | |||
1505 | ||||
1506 | /* ID payloads */ | |||
1507 | if ((pld = ikev2_add_payload(e)) == NULL((void*)0)) | |||
1508 | goto done; | |||
1509 | firstpayload = IKEV2_PAYLOAD_IDi35; | |||
1510 | if (ibuf_cat(e, id->id_buf) != 0) | |||
1511 | goto done; | |||
1512 | len = ibuf_size(id->id_buf); | |||
1513 | ||||
1514 | if (pol->pol_peerid.id_type) { | |||
1515 | bzero(&peerid, sizeof(peerid)); | |||
1516 | if (ikev2_policy2id(&pol->pol_peerid, &peerid, 0) != 0) { | |||
1517 | log_debug("%s: failed to get remote id", __func__); | |||
1518 | goto done; | |||
1519 | } | |||
1520 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_IDr36) == -1) | |||
1521 | goto done; | |||
1522 | if ((pld = ikev2_add_payload(e)) == NULL((void*)0)) | |||
1523 | goto done; | |||
1524 | if (ibuf_cat(e, peerid.id_buf) != 0) | |||
1525 | goto done; | |||
1526 | len = ibuf_size(peerid.id_buf); | |||
1527 | } | |||
1528 | ||||
1529 | /* CERT payload */ | |||
1530 | if ((sa->sa_stateinit & IKED_REQ_CERT0x0001) && | |||
1531 | (certid->id_type != IKEV2_CERT_NONE0)) { | |||
1532 | if (ikev2_next_payload(pld, len, | |||
1533 | IKEV2_PAYLOAD_CERT37) == -1) | |||
1534 | goto done; | |||
1535 | if ((pld = ikev2_add_payload(e)) == NULL((void*)0)) | |||
1536 | goto done; | |||
1537 | if ((cert = ibuf_advance(e, sizeof(*cert))) == NULL((void*)0)) | |||
1538 | goto done; | |||
1539 | cert->cert_type = certid->id_type; | |||
1540 | if (ibuf_cat(e, certid->id_buf) != 0) | |||
1541 | goto done; | |||
1542 | len = ibuf_size(certid->id_buf) + sizeof(*cert); | |||
1543 | ||||
1544 | /* CERTREQ payload(s) */ | |||
1545 | if ((len = ikev2_add_certreq(e, &pld, | |||
1546 | len, env->sc_certreq, env->sc_certreqtype)) == -1) | |||
1547 | goto done; | |||
1548 | ||||
1549 | if (env->sc_certreqtype != pol->pol_certreqtype && | |||
1550 | (len = ikev2_add_certreq(e, &pld, | |||
1551 | len, NULL((void*)0), pol->pol_certreqtype)) == -1) | |||
1552 | goto done; | |||
1553 | } | |||
1554 | ||||
1555 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_AUTH39) == -1) | |||
1556 | goto done; | |||
1557 | ||||
1558 | /* AUTH payload */ | |||
1559 | if ((pld = ikev2_add_payload(e)) == NULL((void*)0)) | |||
1560 | goto done; | |||
1561 | if ((auth = ibuf_advance(e, sizeof(*auth))) == NULL((void*)0)) | |||
1562 | goto done; | |||
1563 | auth->auth_method = sa->sa_localauth.id_type; | |||
1564 | if (ibuf_cat(e, sa->sa_localauth.id_buf) != 0) | |||
1565 | goto done; | |||
1566 | len = ibuf_size(sa->sa_localauth.id_buf) + sizeof(*auth); | |||
1567 | ||||
1568 | /* CP payload */ | |||
1569 | if (ikev2_cp_request_configured(sa)) { | |||
1570 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_CP47) == -1) | |||
1571 | goto done; | |||
1572 | if ((pld = ikev2_add_payload(e)) == NULL((void*)0)) | |||
1573 | goto done; | |||
1574 | if ((len = ikev2_init_add_cp(env, sa, e)) == -1) | |||
1575 | goto done; | |||
1576 | } | |||
1577 | ||||
1578 | if ((pol->pol_flags & IKED_POLICY_IPCOMP0x20) && | |||
1579 | (len = ikev2_add_ipcompnotify(env, e, &pld, len, sa, 1)) == -1) | |||
1580 | goto done; | |||
1581 | if ((pol->pol_flags & IKED_POLICY_TRANSPORT0x40) && | |||
1582 | (len = ikev2_add_transport_mode(env, e, &pld, len, sa)) == -1) | |||
1583 | goto done; | |||
1584 | ||||
1585 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_SA33) == -1) | |||
1586 | goto done; | |||
1587 | ||||
1588 | /* SA payload */ | |||
1589 | if ((pld = ikev2_add_payload(e)) == NULL((void*)0)) | |||
1590 | goto done; | |||
1591 | if ((len = ikev2_add_proposals(env, sa, e, &pol->pol_proposals, 0, | |||
1592 | sa->sa_hdr.sh_initiator, 0, 1)) == -1) | |||
1593 | goto done; | |||
1594 | ||||
1595 | if ((len = ikev2_add_ts(e, &pld, len, sa, 0)) == -1) | |||
1596 | goto done; | |||
1597 | ||||
1598 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONE0) == -1) | |||
1599 | goto done; | |||
1600 | ||||
1601 | ret = ikev2_msg_send_encrypt(env, sa, &e, | |||
1602 | IKEV2_EXCHANGE_IKE_AUTH35, firstpayload, 0); | |||
1603 | ||||
1604 | done: | |||
1605 | ibuf_release(e); | |||
1606 | ||||
1607 | return (ret); | |||
1608 | } | |||
1609 | ||||
1610 | void | |||
1611 | ikev2_enable_timer(struct iked *env, struct iked_sa *sa) | |||
1612 | { | |||
1613 | sa->sa_last_recvd = gettime(); | |||
1614 | timer_set(env, &sa->sa_timer, ikev2_ike_sa_alive, sa); | |||
1615 | if (env->sc_alive_timeoutsc_static.st_alive_timeout > 0) | |||
1616 | timer_add(env, &sa->sa_timer, env->sc_alive_timeoutsc_static.st_alive_timeout); | |||
1617 | timer_set(env, &sa->sa_keepalive, ikev2_ike_sa_keepalive, sa); | |||
1618 | if (sa->sa_usekeepalive) | |||
1619 | timer_add(env, &sa->sa_keepalive, | |||
1620 | IKED_IKE_SA_KEEPALIVE_TIMEOUT20); | |||
1621 | timer_set(env, &sa->sa_rekey, ikev2_ike_sa_rekey, sa); | |||
1622 | if (sa->sa_policy->pol_rekey) | |||
1623 | ikev2_ike_sa_rekey_schedule(env, sa); | |||
1624 | } | |||
1625 | ||||
1626 | void | |||
1627 | ikev2_reset_alive_timer(struct iked *env) | |||
1628 | { | |||
1629 | struct iked_sa *sa; | |||
1630 | ||||
1631 | RB_FOREACH(sa, iked_sas, &env->sc_sas)for ((sa) = iked_sas_RB_MINMAX(&env->sc_sas, -1); (sa) != ((void*)0); (sa) = iked_sas_RB_NEXT(sa)) { | |||
1632 | if (sa->sa_state != IKEV2_STATE_ESTABLISHED9) | |||
1633 | continue; | |||
1634 | timer_del(env, &sa->sa_timer); | |||
1635 | if (env->sc_alive_timeoutsc_static.st_alive_timeout > 0) | |||
1636 | timer_add(env, &sa->sa_timer, env->sc_alive_timeoutsc_static.st_alive_timeout); | |||
1637 | } | |||
1638 | } | |||
1639 | ||||
1640 | void | |||
1641 | ikev2_disable_timer(struct iked *env, struct iked_sa *sa) | |||
1642 | { | |||
1643 | timer_del(env, &sa->sa_timer); | |||
1644 | timer_del(env, &sa->sa_keepalive); | |||
1645 | timer_del(env, &sa->sa_rekey); | |||
1646 | } | |||
1647 | ||||
1648 | int | |||
1649 | ikev2_init_done(struct iked *env, struct iked_sa *sa) | |||
1650 | { | |||
1651 | int ret; | |||
1652 | ||||
1653 | if (!sa_stateok(sa, IKEV2_STATE_VALID7)) | |||
1654 | return (0); /* ignored */ | |||
1655 | ||||
1656 | ret = ikev2_childsa_negotiate(env, sa, &sa->sa_kex, &sa->sa_proposals, | |||
1657 | sa->sa_hdr.sh_initiator, 0); | |||
1658 | if (ret == 0) | |||
1659 | ret = ikev2_childsa_enable(env, sa); | |||
1660 | if (ret == 0) { | |||
1661 | sa_state(env, sa, IKEV2_STATE_ESTABLISHED9); | |||
1662 | /* Delete exchange timeout. */ | |||
1663 | timer_del(env, &sa->sa_timer); | |||
1664 | ikev2_enable_timer(env, sa); | |||
1665 | ikev2_log_established(sa); | |||
1666 | ikev2_record_dstid(env, sa); | |||
1667 | sa_configure_iface(env, sa, 1); | |||
1668 | } | |||
1669 | ||||
1670 | if (ret) | |||
1671 | ikev2_childsa_delete(env, sa, 0, 0, NULL((void*)0), 1); | |||
1672 | return (ret); | |||
1673 | } | |||
1674 | ||||
1675 | int | |||
1676 | ikev2_policy2id(struct iked_static_id *polid, struct iked_id *id, int srcid) | |||
1677 | { | |||
1678 | struct ikev2_id hdr; | |||
1679 | struct iked_static_id localpid; | |||
1680 | char idstr[IKED_ID_SIZE1024]; | |||
1681 | struct in_addr in4; | |||
1682 | struct in6_addr in6; | |||
1683 | X509_NAME *name = NULL((void*)0); | |||
1684 | uint8_t *p; | |||
1685 | int len; | |||
1686 | ||||
1687 | /* Fixup the local Id if not specified */ | |||
1688 | if (srcid && polid->id_type == 0) { | |||
1689 | polid = &localpid; | |||
1690 | bzero(polid, sizeof(*polid)); | |||
1691 | ||||
1692 | /* Create a default local ID based on our FQDN */ | |||
1693 | polid->id_type = IKEV2_ID_FQDN2; | |||
1694 | if (gethostname((char *)polid->id_data, | |||
1695 | sizeof(polid->id_data)) != 0) | |||
1696 | return (-1); | |||
1697 | polid->id_offset = 0; | |||
1698 | polid->id_length = | |||
1699 | strlen((char *)polid->id_data); /* excluding NUL */ | |||
1700 | } | |||
1701 | ||||
1702 | if (!polid->id_length) | |||
1703 | return (-1); | |||
1704 | ||||
1705 | /* Create an IKEv2 ID payload */ | |||
1706 | bzero(&hdr, sizeof(hdr)); | |||
1707 | hdr.id_type = id->id_type = polid->id_type; | |||
1708 | id->id_offset = sizeof(hdr); | |||
1709 | ||||
1710 | ibuf_free(id->id_buf); | |||
1711 | if ((id->id_buf = ibuf_new(&hdr, sizeof(hdr))) == NULL((void*)0)) | |||
1712 | return (-1); | |||
1713 | ||||
1714 | switch (id->id_type) { | |||
1715 | case IKEV2_ID_IPV41: | |||
1716 | if (inet_pton(AF_INET2, (char *)polid->id_data, &in4) != 1 || | |||
1717 | ibuf_add(id->id_buf, &in4, sizeof(in4)) != 0) { | |||
1718 | ibuf_release(id->id_buf); | |||
1719 | id->id_buf = NULL((void*)0); | |||
1720 | return (-1); | |||
1721 | } | |||
1722 | break; | |||
1723 | case IKEV2_ID_IPV65: | |||
1724 | if (inet_pton(AF_INET624, (char *)polid->id_data, &in6) != 1 || | |||
1725 | ibuf_add(id->id_buf, &in6, sizeof(in6)) != 0) { | |||
1726 | ibuf_release(id->id_buf); | |||
1727 | id->id_buf = NULL((void*)0); | |||
1728 | return (-1); | |||
1729 | } | |||
1730 | break; | |||
1731 | case IKEV2_ID_ASN1_DN9: | |||
1732 | /* policy has ID in string-format, convert to ASN1 */ | |||
1733 | if ((name = ca_x509_name_parse(polid->id_data)) == NULL((void*)0) || | |||
1734 | (len = i2d_X509_NAME(name, NULL((void*)0))) < 0 || | |||
1735 | (p = ibuf_reserve(id->id_buf, len)) == NULL((void*)0) || | |||
1736 | (i2d_X509_NAME(name, &p)) < 0) { | |||
1737 | if (name) | |||
1738 | X509_NAME_free(name); | |||
1739 | ibuf_release(id->id_buf); | |||
1740 | id->id_buf = NULL((void*)0); | |||
1741 | return (-1); | |||
1742 | } | |||
1743 | X509_NAME_free(name); | |||
1744 | break; | |||
1745 | default: | |||
1746 | if (ibuf_add(id->id_buf, | |||
1747 | polid->id_data, polid->id_length) != 0) { | |||
1748 | ibuf_release(id->id_buf); | |||
1749 | id->id_buf = NULL((void*)0); | |||
1750 | return (-1); | |||
1751 | } | |||
1752 | break; | |||
1753 | } | |||
1754 | ||||
1755 | if (ikev2_print_id(id, idstr, sizeof(idstr)) == -1) | |||
1756 | return (-1); | |||
1757 | ||||
1758 | log_debug("%s: %s %s length %zu", __func__, | |||
1759 | srcid ? "srcid" : "dstid", | |||
1760 | idstr, ibuf_size(id->id_buf)); | |||
1761 | ||||
1762 | return (0); | |||
1763 | } | |||
1764 | ||||
1765 | struct ike_header * | |||
1766 | ikev2_add_header(struct ibuf *buf, struct iked_sa *sa, | |||
1767 | uint32_t msgid, uint8_t nextpayload, | |||
1768 | uint8_t exchange, uint8_t flags) | |||
1769 | { | |||
1770 | struct ike_header *hdr; | |||
1771 | ||||
1772 | if ((hdr = ibuf_advance(buf, sizeof(*hdr))) == NULL((void*)0)) { | |||
1773 | log_debug("%s: failed to add header", __func__); | |||
1774 | return (NULL((void*)0)); | |||
1775 | } | |||
1776 | ||||
1777 | hdr->ike_ispi = htobe64(sa->sa_hdr.sh_ispi)(__uint64_t)(__builtin_constant_p(sa->sa_hdr.sh_ispi) ? (__uint64_t )((((__uint64_t)(sa->sa_hdr.sh_ispi) & 0xff) << 56 ) | ((__uint64_t)(sa->sa_hdr.sh_ispi) & 0xff00ULL) << 40 | ((__uint64_t)(sa->sa_hdr.sh_ispi) & 0xff0000ULL) << 24 | ((__uint64_t)(sa->sa_hdr.sh_ispi) & 0xff000000ULL ) << 8 | ((__uint64_t)(sa->sa_hdr.sh_ispi) & 0xff00000000ULL ) >> 8 | ((__uint64_t)(sa->sa_hdr.sh_ispi) & 0xff0000000000ULL ) >> 24 | ((__uint64_t)(sa->sa_hdr.sh_ispi) & 0xff000000000000ULL ) >> 40 | ((__uint64_t)(sa->sa_hdr.sh_ispi) & 0xff00000000000000ULL ) >> 56) : __swap64md(sa->sa_hdr.sh_ispi)); | |||
1778 | hdr->ike_rspi = htobe64(sa->sa_hdr.sh_rspi)(__uint64_t)(__builtin_constant_p(sa->sa_hdr.sh_rspi) ? (__uint64_t )((((__uint64_t)(sa->sa_hdr.sh_rspi) & 0xff) << 56 ) | ((__uint64_t)(sa->sa_hdr.sh_rspi) & 0xff00ULL) << 40 | ((__uint64_t)(sa->sa_hdr.sh_rspi) & 0xff0000ULL) << 24 | ((__uint64_t)(sa->sa_hdr.sh_rspi) & 0xff000000ULL ) << 8 | ((__uint64_t)(sa->sa_hdr.sh_rspi) & 0xff00000000ULL ) >> 8 | ((__uint64_t)(sa->sa_hdr.sh_rspi) & 0xff0000000000ULL ) >> 24 | ((__uint64_t)(sa->sa_hdr.sh_rspi) & 0xff000000000000ULL ) >> 40 | ((__uint64_t)(sa->sa_hdr.sh_rspi) & 0xff00000000000000ULL ) >> 56) : __swap64md(sa->sa_hdr.sh_rspi)); | |||
1779 | hdr->ike_nextpayload = nextpayload; | |||
1780 | hdr->ike_version = IKEV2_VERSION0x20; | |||
1781 | hdr->ike_exchange = exchange; | |||
1782 | hdr->ike_msgid = htobe32(msgid)(__uint32_t)(__builtin_constant_p(msgid) ? (__uint32_t)(((__uint32_t )(msgid) & 0xff) << 24 | ((__uint32_t)(msgid) & 0xff00) << 8 | ((__uint32_t)(msgid) & 0xff0000) >> 8 | ((__uint32_t)(msgid) & 0xff000000) >> 24) : __swap32md (msgid)); | |||
1783 | hdr->ike_length = htobe32(sizeof(*hdr))(__uint32_t)(__builtin_constant_p(sizeof(*hdr)) ? (__uint32_t )(((__uint32_t)(sizeof(*hdr)) & 0xff) << 24 | ((__uint32_t )(sizeof(*hdr)) & 0xff00) << 8 | ((__uint32_t)(sizeof (*hdr)) & 0xff0000) >> 8 | ((__uint32_t)(sizeof(*hdr )) & 0xff000000) >> 24) : __swap32md(sizeof(*hdr))); | |||
1784 | hdr->ike_flags = flags; | |||
1785 | ||||
1786 | if (sa->sa_hdr.sh_initiator) | |||
1787 | hdr->ike_flags |= IKEV2_FLAG_INITIATOR0x08; | |||
1788 | ||||
1789 | return (hdr); | |||
1790 | } | |||
1791 | ||||
1792 | int | |||
1793 | ikev2_set_header(struct ike_header *hdr, size_t length) | |||
1794 | { | |||
1795 | uint32_t hdrlength = sizeof(*hdr) + length; | |||
1796 | ||||
1797 | if (hdrlength > UINT32_MAX0xffffffffU) { | |||
1798 | log_debug("%s: message too long", __func__); | |||
1799 | return (-1); | |||
1800 | } | |||
1801 | ||||
1802 | hdr->ike_length = htobe32(sizeof(*hdr) + length)(__uint32_t)(__builtin_constant_p(sizeof(*hdr) + length) ? (__uint32_t )(((__uint32_t)(sizeof(*hdr) + length) & 0xff) << 24 | ((__uint32_t)(sizeof(*hdr) + length) & 0xff00) << 8 | ((__uint32_t)(sizeof(*hdr) + length) & 0xff0000) >> 8 | ((__uint32_t)(sizeof(*hdr) + length) & 0xff000000) >> 24) : __swap32md(sizeof(*hdr) + length)); | |||
1803 | ||||
1804 | return (0); | |||
1805 | } | |||
1806 | ||||
1807 | struct ikev2_payload * | |||
1808 | ikev2_add_payload(struct ibuf *buf) | |||
1809 | { | |||
1810 | struct ikev2_payload *pld; | |||
1811 | ||||
1812 | if ((pld = ibuf_advance(buf, sizeof(*pld))) == NULL((void*)0)) { | |||
1813 | log_debug("%s: failed to add payload", __func__); | |||
1814 | return (NULL((void*)0)); | |||
1815 | } | |||
1816 | ||||
1817 | pld->pld_nextpayload = IKEV2_PAYLOAD_NONE0; | |||
1818 | pld->pld_length = sizeof(*pld); | |||
1819 | ||||
1820 | return (pld); | |||
1821 | } | |||
1822 | ||||
1823 | ssize_t | |||
1824 | ikev2_add_ts_payload(struct ibuf *buf, unsigned int type, struct iked_sa *sa) | |||
1825 | { | |||
1826 | struct iked_policy *pol = sa->sa_policy; | |||
1827 | struct ikev2_tsp *tsp; | |||
1828 | struct ikev2_ts *ts; | |||
1829 | struct iked_addr *addr; | |||
1830 | struct iked_addr pooladdr; | |||
1831 | uint8_t *ptr; | |||
1832 | size_t len = 0; | |||
1833 | uint32_t av[4], bv[4], mv[4]; | |||
1834 | struct sockaddr_in *in4; | |||
1835 | struct sockaddr_in6 *in6; | |||
1836 | struct iked_tss *tss; | |||
1837 | struct iked_ts *tsi; | |||
1838 | ||||
1839 | bzero(&pooladdr, sizeof(pooladdr)); | |||
1840 | ||||
1841 | if ((tsp = ibuf_advance(buf, sizeof(*tsp))) == NULL((void*)0)) | |||
1842 | return (-1); | |||
1843 | len = sizeof(*tsp); | |||
1844 | ||||
1845 | if (type == IKEV2_PAYLOAD_TSi44) { | |||
1846 | if (sa->sa_hdr.sh_initiator) { | |||
1847 | tss = &pol->pol_tssrc; | |||
1848 | tsp->tsp_count = pol->pol_tssrc_count; | |||
1849 | } else { | |||
1850 | tss = &pol->pol_tsdst; | |||
1851 | tsp->tsp_count = pol->pol_tsdst_count; | |||
1852 | } | |||
1853 | } else if (type == IKEV2_PAYLOAD_TSr45) { | |||
1854 | if (sa->sa_hdr.sh_initiator) { | |||
1855 | tss = &pol->pol_tsdst; | |||
1856 | tsp->tsp_count = pol->pol_tsdst_count; | |||
1857 | } else { | |||
1858 | tss = &pol->pol_tssrc; | |||
1859 | tsp->tsp_count = pol->pol_tssrc_count; | |||
1860 | } | |||
1861 | } else | |||
1862 | return (-1); | |||
1863 | ||||
1864 | TAILQ_FOREACH(tsi, tss, ts_entry)for((tsi) = ((tss)->tqh_first); (tsi) != ((void*)0); (tsi) = ((tsi)->ts_entry.tqe_next)) { | |||
1865 | if ((ts = ibuf_advance(buf, sizeof(*ts))) == NULL((void*)0)) | |||
1866 | return (-1); | |||
1867 | ||||
1868 | addr = &tsi->ts_addr; | |||
1869 | ||||
1870 | /* patch remote address (if configured to 0.0.0.0) */ | |||
1871 | if ((type == IKEV2_PAYLOAD_TSi44 && !sa->sa_hdr.sh_initiator) || | |||
1872 | (type == IKEV2_PAYLOAD_TSr45 && sa->sa_hdr.sh_initiator)) { | |||
1873 | if (ikev2_cp_fixaddr(sa, addr, &pooladdr) == 0) | |||
1874 | addr = &pooladdr; | |||
1875 | } | |||
1876 | ||||
1877 | ts->ts_protoid = tsi->ts_ipproto; | |||
1878 | ||||
1879 | if (addr->addr_port) { | |||
1880 | ts->ts_startport = addr->addr_port; | |||
1881 | ts->ts_endport = addr->addr_port; | |||
1882 | } else { | |||
1883 | ts->ts_startport = 0; | |||
1884 | ts->ts_endport = 0xffff; | |||
1885 | } | |||
1886 | ||||
1887 | switch (addr->addr_af) { | |||
1888 | case AF_INET2: | |||
1889 | ts->ts_type = IKEV2_TS_IPV4_ADDR_RANGE7; | |||
1890 | ts->ts_length = htobe16(sizeof(*ts) + 8)(__uint16_t)(__builtin_constant_p(sizeof(*ts) + 8) ? (__uint16_t )(((__uint16_t)(sizeof(*ts) + 8) & 0xffU) << 8 | (( __uint16_t)(sizeof(*ts) + 8) & 0xff00U) >> 8) : __swap16md (sizeof(*ts) + 8)); | |||
1891 | ||||
1892 | if ((ptr = ibuf_advance(buf, 8)) == NULL((void*)0)) | |||
1893 | return (-1); | |||
1894 | ||||
1895 | in4 = (struct sockaddr_in *)&addr->addr; | |||
1896 | if (addr->addr_net) { | |||
1897 | /* Convert IPv4 network to address range */ | |||
1898 | mv[0] = prefixlen2mask(addr->addr_mask); | |||
1899 | av[0] = in4->sin_addr.s_addr & mv[0]; | |||
1900 | bv[0] = in4->sin_addr.s_addr | ~mv[0]; | |||
1901 | } else | |||
1902 | av[0] = bv[0] = in4->sin_addr.s_addr; | |||
1903 | ||||
1904 | memcpy(ptr, &av[0], 4); | |||
1905 | memcpy(ptr + 4, &bv[0], 4); | |||
1906 | break; | |||
1907 | case AF_INET624: | |||
1908 | ts->ts_type = IKEV2_TS_IPV6_ADDR_RANGE8; | |||
1909 | ts->ts_length = htobe16(sizeof(*ts) + 32)(__uint16_t)(__builtin_constant_p(sizeof(*ts) + 32) ? (__uint16_t )(((__uint16_t)(sizeof(*ts) + 32) & 0xffU) << 8 | ( (__uint16_t)(sizeof(*ts) + 32) & 0xff00U) >> 8) : __swap16md (sizeof(*ts) + 32)); | |||
1910 | ||||
1911 | if ((ptr = ibuf_advance(buf, 32)) == NULL((void*)0)) | |||
1912 | return (-1); | |||
1913 | ||||
1914 | in6 = (struct sockaddr_in6 *)&addr->addr; | |||
1915 | ||||
1916 | memcpy(&av, &in6->sin6_addr.s6_addr__u6_addr.__u6_addr8, 16); | |||
1917 | memcpy(&bv, &in6->sin6_addr.s6_addr__u6_addr.__u6_addr8, 16); | |||
1918 | if (addr->addr_net) { | |||
1919 | /* Convert IPv6 network to address range */ | |||
1920 | prefixlen2mask6(addr->addr_mask, mv); | |||
1921 | av[0] &= mv[0]; | |||
1922 | av[1] &= mv[1]; | |||
1923 | av[2] &= mv[2]; | |||
1924 | av[3] &= mv[3]; | |||
1925 | bv[0] |= ~mv[0]; | |||
1926 | bv[1] |= ~mv[1]; | |||
1927 | bv[2] |= ~mv[2]; | |||
1928 | bv[3] |= ~mv[3]; | |||
1929 | } | |||
1930 | ||||
1931 | memcpy(ptr, &av, 16); | |||
1932 | memcpy(ptr + 16, &bv, 16); | |||
1933 | break; | |||
1934 | } | |||
1935 | ||||
1936 | len += betoh16(ts->ts_length)(__uint16_t)(__builtin_constant_p(ts->ts_length) ? (__uint16_t )(((__uint16_t)(ts->ts_length) & 0xffU) << 8 | ( (__uint16_t)(ts->ts_length) & 0xff00U) >> 8) : __swap16md (ts->ts_length)); | |||
1937 | } | |||
1938 | ||||
1939 | return (len); | |||
1940 | } | |||
1941 | ||||
1942 | ssize_t | |||
1943 | ikev2_add_ts(struct ibuf *e, struct ikev2_payload **pld, ssize_t len, | |||
1944 | struct iked_sa *sa, int reverse) | |||
1945 | { | |||
1946 | if (ikev2_next_payload(*pld, len, IKEV2_PAYLOAD_TSi44) == -1) | |||
1947 | return (-1); | |||
1948 | ||||
1949 | /* TSi payload */ | |||
1950 | if ((*pld = ikev2_add_payload(e)) == NULL((void*)0)) | |||
1951 | return (-1); | |||
1952 | if ((len = ikev2_add_ts_payload(e, reverse ? IKEV2_PAYLOAD_TSr45 : | |||
1953 | IKEV2_PAYLOAD_TSi44, sa)) == -1) | |||
1954 | return (-1); | |||
1955 | ||||
1956 | if (ikev2_next_payload(*pld, len, IKEV2_PAYLOAD_TSr45) == -1) | |||
1957 | return (-1); | |||
1958 | ||||
1959 | /* TSr payload */ | |||
1960 | if ((*pld = ikev2_add_payload(e)) == NULL((void*)0)) | |||
1961 | return (-1); | |||
1962 | if ((len = ikev2_add_ts_payload(e, reverse ? IKEV2_PAYLOAD_TSi44 : | |||
1963 | IKEV2_PAYLOAD_TSr45, sa)) == -1) | |||
1964 | return (-1); | |||
1965 | ||||
1966 | return (len); | |||
1967 | } | |||
1968 | ||||
1969 | ||||
1970 | ssize_t | |||
1971 | ikev2_add_certreq(struct ibuf *e, struct ikev2_payload **pld, ssize_t len, | |||
1972 | struct ibuf *certreq, uint8_t type) | |||
1973 | { | |||
1974 | struct ikev2_cert *cert; | |||
1975 | ||||
1976 | if (type == IKEV2_CERT_NONE0) | |||
1977 | return (len); | |||
1978 | ||||
1979 | if (ikev2_next_payload(*pld, len, IKEV2_PAYLOAD_CERTREQ38) == -1) | |||
1980 | return (-1); | |||
1981 | ||||
1982 | /* CERTREQ payload */ | |||
1983 | if ((*pld = ikev2_add_payload(e)) == NULL((void*)0)) | |||
1984 | return (-1); | |||
1985 | ||||
1986 | if ((cert = ibuf_advance(e, sizeof(*cert))) == NULL((void*)0)) | |||
1987 | return (-1); | |||
1988 | ||||
1989 | cert->cert_type = type; | |||
1990 | len = sizeof(*cert); | |||
1991 | ||||
1992 | if (certreq != NULL((void*)0) && cert->cert_type == IKEV2_CERT_X509_CERT4) { | |||
1993 | if (ikev2_add_buf(e, certreq) == -1) | |||
1994 | return (-1); | |||
1995 | len += ibuf_size(certreq); | |||
1996 | } | |||
1997 | ||||
1998 | log_debug("%s: type %s length %zd", __func__, | |||
1999 | print_map(type, ikev2_cert_map), len); | |||
2000 | ||||
2001 | return (len); | |||
2002 | } | |||
2003 | ||||
2004 | ssize_t | |||
2005 | ikev2_add_ipcompnotify(struct iked *env, struct ibuf *e, | |||
2006 | struct ikev2_payload **pld, ssize_t len, struct iked_sa *sa, | |||
2007 | int initiator) | |||
2008 | { | |||
2009 | struct iked_childsa csa; | |||
2010 | struct iked_ipcomp *ic; | |||
2011 | struct ikev2_notify *n; | |||
2012 | uint8_t *ptr; | |||
2013 | uint16_t cpi; | |||
2014 | uint32_t spi; | |||
2015 | uint8_t transform; | |||
2016 | ||||
2017 | /* we only support deflate */ | |||
2018 | transform = IKEV2_IPCOMP_DEFLATE2; | |||
2019 | ic = initiator ? &sa->sa_ipcompi : &sa->sa_ipcompr; | |||
2020 | ||||
2021 | if (initiator) { | |||
2022 | bzero(&csa, sizeof(csa)); | |||
2023 | csa.csa_saproto = IKEV2_SAPROTO_IPCOMP204; | |||
2024 | csa.csa_ikesa = sa; | |||
2025 | csa.csa_local = &sa->sa_peer; | |||
2026 | csa.csa_peer = &sa->sa_local; | |||
2027 | if (pfkey_sa_init(env, &csa, &spi) == -1) | |||
2028 | return (-1); | |||
2029 | ic->ic_cpi_in = spi; | |||
2030 | } else { | |||
2031 | spi = ic->ic_cpi_in; | |||
2032 | /* make sure IPCOMP CPIs are not reused */ | |||
2033 | ic->ic_transform = 0; | |||
2034 | ic->ic_cpi_in = 0; | |||
2035 | ic->ic_cpi_out = 0; | |||
2036 | } | |||
2037 | log_debug("%s: ic_cpi_in 0x%04x", __func__, spi); | |||
2038 | ||||
2039 | /* | |||
2040 | * We get spi == 0 if the kernel does not support IPcomp, | |||
2041 | * so just return the length of the current payload. | |||
2042 | */ | |||
2043 | if (spi == 0) | |||
2044 | return (len); | |||
2045 | cpi = htobe16((uint16_t)spi)(__uint16_t)(__builtin_constant_p((uint16_t)spi) ? (__uint16_t )(((__uint16_t)((uint16_t)spi) & 0xffU) << 8 | ((__uint16_t )((uint16_t)spi) & 0xff00U) >> 8) : __swap16md((uint16_t )spi)); | |||
2046 | if (*pld) | |||
2047 | if (ikev2_next_payload(*pld, len, IKEV2_PAYLOAD_NOTIFY41) == -1) | |||
2048 | return (-1); | |||
2049 | if ((*pld = ikev2_add_payload(e)) == NULL((void*)0)) | |||
2050 | return (-1); | |||
2051 | len = sizeof(*n) + sizeof(cpi) + sizeof(transform); | |||
2052 | if ((ptr = ibuf_advance(e, len)) == NULL((void*)0)) | |||
2053 | return (-1); | |||
2054 | n = (struct ikev2_notify *)ptr; | |||
2055 | n->n_protoid = 0; | |||
2056 | n->n_spisize = 0; | |||
2057 | n->n_type = htobe16(IKEV2_N_IPCOMP_SUPPORTED)(__uint16_t)(__builtin_constant_p(16387) ? (__uint16_t)(((__uint16_t )(16387) & 0xffU) << 8 | ((__uint16_t)(16387) & 0xff00U) >> 8) : __swap16md(16387)); | |||
2058 | ptr += sizeof(*n); | |||
2059 | memcpy(ptr, &cpi, sizeof(cpi)); | |||
2060 | ptr += sizeof(cpi); | |||
2061 | memcpy(ptr, &transform, sizeof(transform)); | |||
2062 | ||||
2063 | return (len); | |||
2064 | } | |||
2065 | ||||
2066 | ssize_t | |||
2067 | ikev2_add_notify(struct ibuf *e, struct ikev2_payload **pld, ssize_t len, | |||
2068 | uint16_t notify) | |||
2069 | { | |||
2070 | struct ikev2_notify *n; | |||
2071 | ||||
2072 | if (*pld) | |||
2073 | if (ikev2_next_payload(*pld, len, IKEV2_PAYLOAD_NOTIFY41) == -1) | |||
2074 | return (-1); | |||
2075 | if ((*pld = ikev2_add_payload(e)) == NULL((void*)0)) | |||
2076 | return (-1); | |||
2077 | len = sizeof(*n); | |||
2078 | if ((n = ibuf_advance(e, len)) == NULL((void*)0)) | |||
2079 | return (-1); | |||
2080 | n->n_protoid = 0; | |||
2081 | n->n_spisize = 0; | |||
2082 | n->n_type = htobe16(notify)(__uint16_t)(__builtin_constant_p(notify) ? (__uint16_t)(((__uint16_t )(notify) & 0xffU) << 8 | ((__uint16_t)(notify) & 0xff00U) >> 8) : __swap16md(notify)); | |||
2083 | log_debug("%s: done", __func__); | |||
2084 | ||||
2085 | return (len); | |||
2086 | } | |||
2087 | ||||
2088 | ssize_t | |||
2089 | ikev2_add_mobike(struct ibuf *e, struct ikev2_payload **pld, ssize_t len) | |||
2090 | { | |||
2091 | return ikev2_add_notify(e, pld, len, IKEV2_N_MOBIKE_SUPPORTED16396); | |||
2092 | } | |||
2093 | ||||
2094 | ssize_t | |||
2095 | ikev2_add_fragmentation(struct ibuf *buf, struct ikev2_payload **pld, | |||
2096 | ssize_t len) | |||
2097 | { | |||
2098 | return ikev2_add_notify(buf, pld, len, IKEV2_N_FRAGMENTATION_SUPPORTED16430); | |||
2099 | } | |||
2100 | ||||
2101 | ssize_t | |||
2102 | ikev2_add_sighashnotify(struct ibuf *e, struct ikev2_payload **pld, | |||
2103 | ssize_t len) | |||
2104 | { | |||
2105 | struct ikev2_notify *n; | |||
2106 | uint8_t *ptr; | |||
2107 | size_t i; | |||
2108 | uint16_t hash, signature_hashes[] = { | |||
2109 | IKEV2_SIGHASH_SHA2_2562, | |||
2110 | IKEV2_SIGHASH_SHA2_3843, | |||
2111 | IKEV2_SIGHASH_SHA2_5124 | |||
2112 | }; | |||
2113 | ||||
2114 | if (ikev2_next_payload(*pld, len, IKEV2_PAYLOAD_NOTIFY41) == -1) | |||
2115 | return (-1); | |||
2116 | ||||
2117 | /* XXX signature_hashes are hardcoded for now */ | |||
2118 | len = sizeof(*n) + nitems(signature_hashes)(sizeof((signature_hashes)) / sizeof((signature_hashes)[0])) * sizeof(hash); | |||
2119 | ||||
2120 | /* NOTIFY payload */ | |||
2121 | if ((*pld = ikev2_add_payload(e)) == NULL((void*)0)) | |||
2122 | return (-1); | |||
2123 | if ((ptr = ibuf_advance(e, len)) == NULL((void*)0)) | |||
2124 | return (-1); | |||
2125 | ||||
2126 | n = (struct ikev2_notify *)ptr; | |||
2127 | n->n_protoid = 0; | |||
2128 | n->n_spisize = 0; | |||
2129 | n->n_type = htobe16(IKEV2_N_SIGNATURE_HASH_ALGORITHMS)(__uint16_t)(__builtin_constant_p(16431) ? (__uint16_t)(((__uint16_t )(16431) & 0xffU) << 8 | ((__uint16_t)(16431) & 0xff00U) >> 8) : __swap16md(16431)); | |||
2130 | ptr += sizeof(*n); | |||
2131 | ||||
2132 | for (i = 0; i < nitems(signature_hashes)(sizeof((signature_hashes)) / sizeof((signature_hashes)[0])); i++) { | |||
2133 | hash = htobe16(signature_hashes[i])(__uint16_t)(__builtin_constant_p(signature_hashes[i]) ? (__uint16_t )(((__uint16_t)(signature_hashes[i]) & 0xffU) << 8 | ((__uint16_t)(signature_hashes[i]) & 0xff00U) >> 8 ) : __swap16md(signature_hashes[i])); | |||
2134 | memcpy(ptr, &hash, sizeof(hash)); | |||
2135 | ptr += sizeof(hash); | |||
2136 | } | |||
2137 | ||||
2138 | return (len); | |||
2139 | } | |||
2140 | ||||
2141 | ssize_t | |||
2142 | ikev2_add_transport_mode(struct iked *env, struct ibuf *e, | |||
2143 | struct ikev2_payload **pld, ssize_t len, struct iked_sa *sa) | |||
2144 | { | |||
2145 | return ikev2_add_notify(e, pld, len, IKEV2_N_USE_TRANSPORT_MODE16391); | |||
2146 | } | |||
2147 | ||||
2148 | int | |||
2149 | ikev2_next_payload(struct ikev2_payload *pld, size_t length, | |||
2150 | uint8_t nextpayload) | |||
2151 | { | |||
2152 | size_t pldlength = sizeof(*pld) + length; | |||
2153 | ||||
2154 | if (pldlength > UINT16_MAX0xffff) { | |||
2155 | log_debug("%s: payload too long", __func__); | |||
2156 | return (-1); | |||
2157 | } | |||
2158 | ||||
2159 | log_debug("%s: length %zu nextpayload %s", | |||
2160 | __func__, pldlength, print_map(nextpayload, ikev2_payload_map)); | |||
2161 | ||||
2162 | pld->pld_length = htobe16(pldlength)(__uint16_t)(__builtin_constant_p(pldlength) ? (__uint16_t)(( (__uint16_t)(pldlength) & 0xffU) << 8 | ((__uint16_t )(pldlength) & 0xff00U) >> 8) : __swap16md(pldlength )); | |||
2163 | pld->pld_nextpayload = nextpayload; | |||
2164 | ||||
2165 | return (0); | |||
2166 | } | |||
2167 | ||||
2168 | ssize_t | |||
2169 | ikev2_nat_detection(struct iked *env, struct iked_message *msg, | |||
2170 | void *ptr, size_t len, unsigned int type, int frompeer) | |||
2171 | { | |||
2172 | EVP_MD_CTX *ctx; | |||
2173 | struct ike_header *hdr; | |||
2174 | uint8_t md[SHA_DIGEST_LENGTH20]; | |||
2175 | unsigned int mdlen = sizeof(md); | |||
2176 | struct iked_sa *sa = msg->msg_sa; | |||
2177 | struct sockaddr_in *in4; | |||
2178 | struct sockaddr_in6 *in6; | |||
2179 | ssize_t ret = -1; | |||
2180 | struct sockaddr *src, *dst, *ss; | |||
2181 | uint64_t rspi, ispi; | |||
2182 | struct ibuf *buf; | |||
2183 | uint32_t rnd; | |||
2184 | ||||
2185 | if (ptr == NULL((void*)0)) | |||
2186 | return (mdlen); | |||
2187 | ||||
2188 | if (frompeer) { | |||
2189 | buf = msg->msg_parent->msg_data; | |||
2190 | if ((hdr = ibuf_seek(buf, 0, sizeof(*hdr))) == NULL((void*)0)) | |||
2191 | return (-1); | |||
2192 | ispi = hdr->ike_ispi; | |||
2193 | rspi = hdr->ike_rspi; | |||
2194 | src = (struct sockaddr *)&msg->msg_peer; | |||
2195 | dst = (struct sockaddr *)&msg->msg_local; | |||
2196 | } else { | |||
2197 | ispi = htobe64(sa->sa_hdr.sh_ispi)(__uint64_t)(__builtin_constant_p(sa->sa_hdr.sh_ispi) ? (__uint64_t )((((__uint64_t)(sa->sa_hdr.sh_ispi) & 0xff) << 56 ) | ((__uint64_t)(sa->sa_hdr.sh_ispi) & 0xff00ULL) << 40 | ((__uint64_t)(sa->sa_hdr.sh_ispi) & 0xff0000ULL) << 24 | ((__uint64_t)(sa->sa_hdr.sh_ispi) & 0xff000000ULL ) << 8 | ((__uint64_t)(sa->sa_hdr.sh_ispi) & 0xff00000000ULL ) >> 8 | ((__uint64_t)(sa->sa_hdr.sh_ispi) & 0xff0000000000ULL ) >> 24 | ((__uint64_t)(sa->sa_hdr.sh_ispi) & 0xff000000000000ULL ) >> 40 | ((__uint64_t)(sa->sa_hdr.sh_ispi) & 0xff00000000000000ULL ) >> 56) : __swap64md(sa->sa_hdr.sh_ispi)); | |||
2198 | rspi = htobe64(sa->sa_hdr.sh_rspi)(__uint64_t)(__builtin_constant_p(sa->sa_hdr.sh_rspi) ? (__uint64_t )((((__uint64_t)(sa->sa_hdr.sh_rspi) & 0xff) << 56 ) | ((__uint64_t)(sa->sa_hdr.sh_rspi) & 0xff00ULL) << 40 | ((__uint64_t)(sa->sa_hdr.sh_rspi) & 0xff0000ULL) << 24 | ((__uint64_t)(sa->sa_hdr.sh_rspi) & 0xff000000ULL ) << 8 | ((__uint64_t)(sa->sa_hdr.sh_rspi) & 0xff00000000ULL ) >> 8 | ((__uint64_t)(sa->sa_hdr.sh_rspi) & 0xff0000000000ULL ) >> 24 | ((__uint64_t)(sa->sa_hdr.sh_rspi) & 0xff000000000000ULL ) >> 40 | ((__uint64_t)(sa->sa_hdr.sh_rspi) & 0xff00000000000000ULL ) >> 56) : __swap64md(sa->sa_hdr.sh_rspi)); | |||
2199 | src = (struct sockaddr *)&msg->msg_local; | |||
2200 | dst = (struct sockaddr *)&msg->msg_peer; | |||
2201 | } | |||
2202 | ||||
2203 | ctx = EVP_MD_CTX_new(); | |||
2204 | if (ctx == NULL((void*)0)) | |||
2205 | return (-1); | |||
2206 | EVP_DigestInit_ex(ctx, EVP_sha1(), NULL((void*)0)); | |||
2207 | ||||
2208 | switch (type) { | |||
2209 | case IKEV2_N_NAT_DETECTION_SOURCE_IP16388: | |||
2210 | log_debug("%s: %s source %s %s %s", __func__, | |||
2211 | frompeer ? "peer" : "local", | |||
2212 | print_spi(betoh64(ispi)(__uint64_t)(__builtin_constant_p(ispi) ? (__uint64_t)((((__uint64_t )(ispi) & 0xff) << 56) | ((__uint64_t)(ispi) & 0xff00ULL ) << 40 | ((__uint64_t)(ispi) & 0xff0000ULL) << 24 | ((__uint64_t)(ispi) & 0xff000000ULL) << 8 | ( (__uint64_t)(ispi) & 0xff00000000ULL) >> 8 | ((__uint64_t )(ispi) & 0xff0000000000ULL) >> 24 | ((__uint64_t)( ispi) & 0xff000000000000ULL) >> 40 | ((__uint64_t)( ispi) & 0xff00000000000000ULL) >> 56) : __swap64md( ispi)), 8), | |||
2213 | print_spi(betoh64(rspi)(__uint64_t)(__builtin_constant_p(rspi) ? (__uint64_t)((((__uint64_t )(rspi) & 0xff) << 56) | ((__uint64_t)(rspi) & 0xff00ULL ) << 40 | ((__uint64_t)(rspi) & 0xff0000ULL) << 24 | ((__uint64_t)(rspi) & 0xff000000ULL) << 8 | ( (__uint64_t)(rspi) & 0xff00000000ULL) >> 8 | ((__uint64_t )(rspi) & 0xff0000000000ULL) >> 24 | ((__uint64_t)( rspi) & 0xff000000000000ULL) >> 40 | ((__uint64_t)( rspi) & 0xff00000000000000ULL) >> 56) : __swap64md( rspi)), 8), | |||
2214 | print_host(src, NULL((void*)0), 0)); | |||
2215 | ss = src; | |||
2216 | break; | |||
2217 | case IKEV2_N_NAT_DETECTION_DESTINATION_IP16389: | |||
2218 | log_debug("%s: %s destination %s %s %s", __func__, | |||
2219 | frompeer ? "peer" : "local", | |||
2220 | print_spi(betoh64(ispi)(__uint64_t)(__builtin_constant_p(ispi) ? (__uint64_t)((((__uint64_t )(ispi) & 0xff) << 56) | ((__uint64_t)(ispi) & 0xff00ULL ) << 40 | ((__uint64_t)(ispi) & 0xff0000ULL) << 24 | ((__uint64_t)(ispi) & 0xff000000ULL) << 8 | ( (__uint64_t)(ispi) & 0xff00000000ULL) >> 8 | ((__uint64_t )(ispi) & 0xff0000000000ULL) >> 24 | ((__uint64_t)( ispi) & 0xff000000000000ULL) >> 40 | ((__uint64_t)( ispi) & 0xff00000000000000ULL) >> 56) : __swap64md( ispi)), 8), | |||
2221 | print_spi(betoh64(rspi)(__uint64_t)(__builtin_constant_p(rspi) ? (__uint64_t)((((__uint64_t )(rspi) & 0xff) << 56) | ((__uint64_t)(rspi) & 0xff00ULL ) << 40 | ((__uint64_t)(rspi) & 0xff0000ULL) << 24 | ((__uint64_t)(rspi) & 0xff000000ULL) << 8 | ( (__uint64_t)(rspi) & 0xff00000000ULL) >> 8 | ((__uint64_t )(rspi) & 0xff0000000000ULL) >> 24 | ((__uint64_t)( rspi) & 0xff000000000000ULL) >> 40 | ((__uint64_t)( rspi) & 0xff00000000000000ULL) >> 56) : __swap64md( rspi)), 8), | |||
2222 | print_host(dst, NULL((void*)0), 0)); | |||
2223 | ss = dst; | |||
2224 | break; | |||
2225 | default: | |||
2226 | goto done; | |||
2227 | } | |||
2228 | ||||
2229 | EVP_DigestUpdate(ctx, &ispi, sizeof(ispi)); | |||
2230 | EVP_DigestUpdate(ctx, &rspi, sizeof(rspi)); | |||
2231 | ||||
2232 | switch (ss->sa_family) { | |||
2233 | case AF_INET2: | |||
2234 | in4 = (struct sockaddr_in *)ss; | |||
2235 | EVP_DigestUpdate(ctx, &in4->sin_addr.s_addr, | |||
2236 | sizeof(in4->sin_addr.s_addr)); | |||
2237 | EVP_DigestUpdate(ctx, &in4->sin_port, | |||
2238 | sizeof(in4->sin_port)); | |||
2239 | break; | |||
2240 | case AF_INET624: | |||
2241 | in6 = (struct sockaddr_in6 *)ss; | |||
2242 | EVP_DigestUpdate(ctx, &in6->sin6_addr.s6_addr__u6_addr.__u6_addr8, | |||
2243 | sizeof(in6->sin6_addr.s6_addr__u6_addr.__u6_addr8)); | |||
2244 | EVP_DigestUpdate(ctx, &in6->sin6_port, | |||
2245 | sizeof(in6->sin6_port)); | |||
2246 | break; | |||
2247 | default: | |||
2248 | goto done; | |||
2249 | } | |||
2250 | ||||
2251 | if (env->sc_nattmode == NATT_FORCE) { | |||
2252 | /* Enforce NAT-T/UDP-encapsulation by distorting the digest */ | |||
2253 | rnd = arc4random(); | |||
2254 | EVP_DigestUpdate(ctx, &rnd, sizeof(rnd)); | |||
2255 | } | |||
2256 | ||||
2257 | EVP_DigestFinal_ex(ctx, md, &mdlen); | |||
2258 | ||||
2259 | if (len < mdlen) | |||
2260 | goto done; | |||
2261 | ||||
2262 | memcpy(ptr, md, mdlen); | |||
2263 | ret = mdlen; | |||
2264 | done: | |||
2265 | EVP_MD_CTX_free(ctx); | |||
2266 | ||||
2267 | return (ret); | |||
2268 | } | |||
2269 | ||||
2270 | ssize_t | |||
2271 | ikev2_add_nat_detection(struct iked *env, struct ibuf *buf, | |||
2272 | struct ikev2_payload **pld, struct iked_message *msg, ssize_t len) | |||
2273 | { | |||
2274 | struct ikev2_notify *n; | |||
2275 | uint8_t *ptr; | |||
2276 | ||||
2277 | /* *pld is NULL if there is no previous payload */ | |||
2278 | if (*pld != NULL((void*)0)) { | |||
2279 | if (ikev2_next_payload(*pld, len, IKEV2_PAYLOAD_NOTIFY41) == -1) | |||
2280 | return (-1); | |||
2281 | } | |||
2282 | /* NAT-T notify payloads */ | |||
2283 | if ((*pld = ikev2_add_payload(buf)) == NULL((void*)0)) | |||
2284 | return (-1); | |||
2285 | if ((n = ibuf_advance(buf, sizeof(*n))) == NULL((void*)0)) | |||
2286 | return (-1); | |||
2287 | n->n_type = htobe16(IKEV2_N_NAT_DETECTION_SOURCE_IP)(__uint16_t)(__builtin_constant_p(16388) ? (__uint16_t)(((__uint16_t )(16388) & 0xffU) << 8 | ((__uint16_t)(16388) & 0xff00U) >> 8) : __swap16md(16388)); | |||
2288 | len = ikev2_nat_detection(env, msg, NULL((void*)0), 0, 0, 0); | |||
2289 | if ((ptr = ibuf_advance(buf, len)) == NULL((void*)0)) | |||
2290 | return (-1); | |||
2291 | if ((len = ikev2_nat_detection(env, msg, ptr, len, | |||
2292 | betoh16(n->n_type)(__uint16_t)(__builtin_constant_p(n->n_type) ? (__uint16_t )(((__uint16_t)(n->n_type) & 0xffU) << 8 | ((__uint16_t )(n->n_type) & 0xff00U) >> 8) : __swap16md(n-> n_type)), 0)) == -1) | |||
2293 | return (-1); | |||
2294 | len += sizeof(*n); | |||
2295 | ||||
2296 | if (ikev2_next_payload(*pld, len, IKEV2_PAYLOAD_NOTIFY41) == -1) | |||
2297 | return (-1); | |||
2298 | ||||
2299 | if ((*pld = ikev2_add_payload(buf)) == NULL((void*)0)) | |||
2300 | return (-1); | |||
2301 | if ((n = ibuf_advance(buf, sizeof(*n))) == NULL((void*)0)) | |||
2302 | return (-1); | |||
2303 | n->n_type = htobe16(IKEV2_N_NAT_DETECTION_DESTINATION_IP)(__uint16_t)(__builtin_constant_p(16389) ? (__uint16_t)(((__uint16_t )(16389) & 0xffU) << 8 | ((__uint16_t)(16389) & 0xff00U) >> 8) : __swap16md(16389)); | |||
2304 | len = ikev2_nat_detection(env, msg, NULL((void*)0), 0, 0, 0); | |||
2305 | if ((ptr = ibuf_advance(buf, len)) == NULL((void*)0)) | |||
2306 | return (-1); | |||
2307 | if ((len = ikev2_nat_detection(env, msg, ptr, len, | |||
2308 | betoh16(n->n_type)(__uint16_t)(__builtin_constant_p(n->n_type) ? (__uint16_t )(((__uint16_t)(n->n_type) & 0xffU) << 8 | ((__uint16_t )(n->n_type) & 0xff00U) >> 8) : __swap16md(n-> n_type)), 0)) == -1) | |||
2309 | return (-1); | |||
2310 | len += sizeof(*n); | |||
2311 | return (len); | |||
2312 | } | |||
2313 | ||||
2314 | ssize_t | |||
2315 | ikev2_add_cp(struct iked *env, struct iked_sa *sa, int type, struct ibuf *buf) | |||
2316 | { | |||
2317 | struct iked_policy *pol = sa->sa_policy; | |||
2318 | struct ikev2_cp *cp; | |||
2319 | struct ikev2_cfg *cfg; | |||
2320 | struct iked_cfg *ikecfg; | |||
2321 | unsigned int i; | |||
2322 | uint32_t mask4; | |||
2323 | size_t len; | |||
2324 | struct sockaddr_in *in4; | |||
2325 | struct sockaddr_in6 *in6; | |||
2326 | uint8_t prefixlen; | |||
2327 | int sent_addr4 = 0, sent_addr6 = 0; | |||
2328 | int have_mask4 = 0, sent_mask4 = 0; | |||
2329 | ||||
2330 | if ((cp = ibuf_advance(buf, sizeof(*cp))) == NULL((void*)0)) | |||
2331 | return (-1); | |||
2332 | len = sizeof(*cp); | |||
2333 | ||||
2334 | switch (type) { | |||
2335 | case IKEV2_CP_REQUEST1: | |||
2336 | case IKEV2_CP_REPLY2: | |||
2337 | cp->cp_type = type; | |||
2338 | break; | |||
2339 | default: | |||
2340 | /* Not yet supported */ | |||
2341 | return (-1); | |||
2342 | } | |||
2343 | ||||
2344 | for (i = 0; i < pol->pol_ncfg; i++) { | |||
2345 | ikecfg = &pol->pol_cfg[i]; | |||
2346 | if (ikecfg->cfg_action != cp->cp_type) | |||
2347 | continue; | |||
2348 | /* only return one address in case of multiple pools */ | |||
2349 | if (type == IKEV2_CP_REPLY2) { | |||
2350 | switch (ikecfg->cfg_type) { | |||
2351 | case IKEV2_CFG_INTERNAL_IP4_ADDRESS1: | |||
2352 | if (sent_addr4) | |||
2353 | continue; | |||
2354 | break; | |||
2355 | case IKEV2_CFG_INTERNAL_IP6_ADDRESS8: | |||
2356 | if (sent_addr6) | |||
2357 | continue; | |||
2358 | break; | |||
2359 | } | |||
2360 | } | |||
2361 | ||||
2362 | if ((cfg = ibuf_advance(buf, sizeof(*cfg))) == NULL((void*)0)) | |||
2363 | return (-1); | |||
2364 | ||||
2365 | cfg->cfg_type = htobe16(ikecfg->cfg_type)(__uint16_t)(__builtin_constant_p(ikecfg->cfg_type) ? (__uint16_t )(((__uint16_t)(ikecfg->cfg_type) & 0xffU) << 8 | ((__uint16_t)(ikecfg->cfg_type) & 0xff00U) >> 8 ) : __swap16md(ikecfg->cfg_type)); | |||
2366 | len += sizeof(*cfg); | |||
2367 | ||||
2368 | switch (ikecfg->cfg_type) { | |||
2369 | case IKEV2_CFG_INTERNAL_IP4_ADDRESS1: | |||
2370 | case IKEV2_CFG_INTERNAL_IP4_NETMASK2: | |||
2371 | case IKEV2_CFG_INTERNAL_IP4_DNS3: | |||
2372 | case IKEV2_CFG_INTERNAL_IP4_NBNS4: | |||
2373 | case IKEV2_CFG_INTERNAL_IP4_DHCP6: | |||
2374 | case IKEV2_CFG_INTERNAL_IP4_SERVER23456: | |||
2375 | /* 4 bytes IPv4 address */ | |||
2376 | in4 = ((ikecfg->cfg_type == | |||
2377 | IKEV2_CFG_INTERNAL_IP4_ADDRESS1) && | |||
2378 | sa->sa_addrpool && | |||
2379 | sa->sa_addrpool->addr_af == AF_INET2) ? | |||
2380 | (struct sockaddr_in *)&sa->sa_addrpool->addr : | |||
2381 | (struct sockaddr_in *)&ikecfg->cfg.address.addr; | |||
2382 | /* don't include unspecified address in request */ | |||
2383 | if (type == IKEV2_CP_REQUEST1 && | |||
2384 | !in4->sin_addr.s_addr) | |||
2385 | break; | |||
2386 | cfg->cfg_length = htobe16(4)(__uint16_t)(__builtin_constant_p(4) ? (__uint16_t)(((__uint16_t )(4) & 0xffU) << 8 | ((__uint16_t)(4) & 0xff00U ) >> 8) : __swap16md(4)); | |||
2387 | if (ibuf_add(buf, &in4->sin_addr.s_addr, 4) == -1) | |||
2388 | return (-1); | |||
2389 | len += 4; | |||
2390 | if (ikecfg->cfg_type == IKEV2_CFG_INTERNAL_IP4_ADDRESS1) { | |||
2391 | sent_addr4 = 1; | |||
2392 | if (sa->sa_addrpool && | |||
2393 | sa->sa_addrpool->addr_af == AF_INET2 && | |||
2394 | sa->sa_addrpool->addr_mask != 0) | |||
2395 | have_mask4 = 1; | |||
2396 | } | |||
2397 | if (ikecfg->cfg_type == IKEV2_CFG_INTERNAL_IP4_NETMASK2) | |||
2398 | sent_mask4 = 1; | |||
2399 | break; | |||
2400 | case IKEV2_CFG_INTERNAL_IP4_SUBNET13: | |||
2401 | /* 4 bytes IPv4 address + 4 bytes IPv4 mask + */ | |||
2402 | in4 = (struct sockaddr_in *)&ikecfg->cfg.address.addr; | |||
2403 | mask4 = prefixlen2mask(ikecfg->cfg.address.addr_mask); | |||
2404 | cfg->cfg_length = htobe16(8)(__uint16_t)(__builtin_constant_p(8) ? (__uint16_t)(((__uint16_t )(8) & 0xffU) << 8 | ((__uint16_t)(8) & 0xff00U ) >> 8) : __swap16md(8)); | |||
2405 | if (ibuf_add(buf, &in4->sin_addr.s_addr, 4) == -1) | |||
2406 | return (-1); | |||
2407 | if (ibuf_add(buf, &mask4, 4) == -1) | |||
2408 | return (-1); | |||
2409 | len += 8; | |||
2410 | break; | |||
2411 | case IKEV2_CFG_INTERNAL_IP6_DNS10: | |||
2412 | case IKEV2_CFG_INTERNAL_IP6_NBNS11: | |||
2413 | case IKEV2_CFG_INTERNAL_IP6_DHCP12: | |||
2414 | case IKEV2_CFG_INTERNAL_IP6_SERVER23457: | |||
2415 | /* 16 bytes IPv6 address */ | |||
2416 | in6 = (struct sockaddr_in6 *)&ikecfg->cfg.address.addr; | |||
2417 | cfg->cfg_length = htobe16(16)(__uint16_t)(__builtin_constant_p(16) ? (__uint16_t)(((__uint16_t )(16) & 0xffU) << 8 | ((__uint16_t)(16) & 0xff00U ) >> 8) : __swap16md(16)); | |||
2418 | if (ibuf_add(buf, &in6->sin6_addr.s6_addr__u6_addr.__u6_addr8, 16) == -1) | |||
2419 | return (-1); | |||
2420 | len += 16; | |||
2421 | break; | |||
2422 | case IKEV2_CFG_INTERNAL_IP6_ADDRESS8: | |||
2423 | case IKEV2_CFG_INTERNAL_IP6_SUBNET15: | |||
2424 | /* 16 bytes IPv6 address + 1 byte prefix length */ | |||
2425 | in6 = ((ikecfg->cfg_type == | |||
2426 | IKEV2_CFG_INTERNAL_IP6_ADDRESS8) && | |||
2427 | sa->sa_addrpool6 && | |||
2428 | sa->sa_addrpool6->addr_af == AF_INET624) ? | |||
2429 | (struct sockaddr_in6 *)&sa->sa_addrpool6->addr : | |||
2430 | (struct sockaddr_in6 *)&ikecfg->cfg.address.addr; | |||
2431 | /* don't include unspecified address in request */ | |||
2432 | if (type == IKEV2_CP_REQUEST1 && | |||
2433 | IN6_IS_ADDR_UNSPECIFIED(&in6->sin6_addr)((*(const u_int32_t *)(const void *)(&(&in6->sin6_addr )->__u6_addr.__u6_addr8[0]) == 0) && (*(const u_int32_t *)(const void *)(&(&in6->sin6_addr)->__u6_addr .__u6_addr8[4]) == 0) && (*(const u_int32_t *)(const void *)(&(&in6->sin6_addr)->__u6_addr.__u6_addr8[8] ) == 0) && (*(const u_int32_t *)(const void *)(&( &in6->sin6_addr)->__u6_addr.__u6_addr8[12]) == 0))) | |||
2434 | break; | |||
2435 | cfg->cfg_length = htobe16(17)(__uint16_t)(__builtin_constant_p(17) ? (__uint16_t)(((__uint16_t )(17) & 0xffU) << 8 | ((__uint16_t)(17) & 0xff00U ) >> 8) : __swap16md(17)); | |||
2436 | if (ibuf_add(buf, &in6->sin6_addr.s6_addr__u6_addr.__u6_addr8, 16) == -1) | |||
2437 | return (-1); | |||
2438 | if (ikecfg->cfg.address.addr_net) | |||
2439 | prefixlen = ikecfg->cfg.address.addr_mask; | |||
2440 | else | |||
2441 | prefixlen = 128; | |||
2442 | if (ibuf_add(buf, &prefixlen, 1) == -1) | |||
2443 | return (-1); | |||
2444 | len += 16 + 1; | |||
2445 | if (ikecfg->cfg_type == IKEV2_CFG_INTERNAL_IP6_ADDRESS8) | |||
2446 | sent_addr6 = 1; | |||
2447 | break; | |||
2448 | case IKEV2_CFG_APPLICATION_VERSION7: | |||
2449 | /* Reply with an empty string (non-NUL terminated) */ | |||
2450 | cfg->cfg_length = 0; | |||
2451 | break; | |||
2452 | } | |||
2453 | } | |||
2454 | ||||
2455 | /* derive netmask from pool */ | |||
2456 | if (type == IKEV2_CP_REPLY2 && have_mask4 && !sent_mask4) { | |||
2457 | if ((cfg = ibuf_advance(buf, sizeof(*cfg))) == NULL((void*)0)) | |||
2458 | return (-1); | |||
2459 | cfg->cfg_type = htobe16(IKEV2_CFG_INTERNAL_IP4_NETMASK)(__uint16_t)(__builtin_constant_p(2) ? (__uint16_t)(((__uint16_t )(2) & 0xffU) << 8 | ((__uint16_t)(2) & 0xff00U ) >> 8) : __swap16md(2)); | |||
2460 | len += sizeof(*cfg); | |||
2461 | mask4 = prefixlen2mask(sa->sa_addrpool->addr_mask); | |||
2462 | cfg->cfg_length = htobe16(4)(__uint16_t)(__builtin_constant_p(4) ? (__uint16_t)(((__uint16_t )(4) & 0xffU) << 8 | ((__uint16_t)(4) & 0xff00U ) >> 8) : __swap16md(4)); | |||
2463 | if (ibuf_add(buf, &mask4, 4) == -1) | |||
2464 | return (-1); | |||
2465 | len += 4; | |||
2466 | } | |||
2467 | ||||
2468 | return (len); | |||
2469 | } | |||
2470 | ||||
2471 | ssize_t | |||
2472 | ikev2_init_add_cp(struct iked *env, struct iked_sa *sa, struct ibuf *buf) | |||
2473 | { | |||
2474 | return (ikev2_add_cp(env, sa, IKEV2_CP_REQUEST1, buf)); | |||
2475 | } | |||
2476 | ||||
2477 | ssize_t | |||
2478 | ikev2_resp_add_cp(struct iked *env, struct iked_sa *sa, struct ibuf *buf) | |||
2479 | { | |||
2480 | int ret; | |||
2481 | ||||
2482 | switch (sa->sa_cp) { | |||
2483 | case IKEV2_CP_REQUEST1: | |||
2484 | ret = ikev2_add_cp(env, sa, IKEV2_CP_REPLY2, buf); | |||
2485 | break; | |||
2486 | case IKEV2_CP_REPLY2: | |||
2487 | case IKEV2_CP_SET3: | |||
2488 | case IKEV2_CP_ACK4: | |||
2489 | default: | |||
2490 | /* Not yet supported */ | |||
2491 | ret = -1; | |||
2492 | } | |||
2493 | return (ret); | |||
2494 | } | |||
2495 | ||||
2496 | ssize_t | |||
2497 | ikev2_add_proposals(struct iked *env, struct iked_sa *sa, struct ibuf *buf, | |||
2498 | struct iked_proposals *proposals, uint8_t protoid, int initiator, | |||
2499 | int sendikespi, int skipdh) | |||
2500 | { | |||
2501 | struct ikev2_sa_proposal *sap = NULL((void*)0); | |||
2502 | struct iked_transform *xform; | |||
2503 | struct iked_proposal *prop; | |||
2504 | struct iked_childsa csa; | |||
2505 | ssize_t length = 0, saplength, xflen; | |||
2506 | uint64_t spi64; | |||
2507 | uint32_t spi32, spi = 0; | |||
2508 | unsigned int i, xfi, nxforms; | |||
2509 | int prop_skipdh; | |||
2510 | ||||
2511 | TAILQ_FOREACH(prop, proposals, prop_entry)for((prop) = ((proposals)->tqh_first); (prop) != ((void*)0 ); (prop) = ((prop)->prop_entry.tqe_next)) { | |||
2512 | if ((protoid && prop->prop_protoid != protoid) || | |||
2513 | (!protoid && prop->prop_protoid == IKEV2_SAPROTO_IKE1)) | |||
2514 | continue; | |||
2515 | ||||
2516 | prop_skipdh = skipdh; | |||
2517 | ||||
2518 | if (protoid != IKEV2_SAPROTO_IKE1 && initiator) { | |||
2519 | if (spi == 0) { | |||
2520 | bzero(&csa, sizeof(csa)); | |||
2521 | csa.csa_ikesa = sa; | |||
2522 | csa.csa_saproto = prop->prop_protoid; | |||
2523 | csa.csa_local = &sa->sa_peer; | |||
2524 | csa.csa_peer = &sa->sa_local; | |||
2525 | ||||
2526 | if (pfkey_sa_init(env, &csa, &spi) == -1) | |||
2527 | return (-1); | |||
2528 | } | |||
2529 | ||||
2530 | prop->prop_localspi.spi = spi; | |||
2531 | prop->prop_localspi.spi_size = 4; | |||
2532 | prop->prop_localspi.spi_protoid = prop->prop_protoid; | |||
2533 | } | |||
2534 | ||||
2535 | if ((sap = ibuf_advance(buf, sizeof(*sap))) == NULL((void*)0)) { | |||
2536 | log_debug("%s: failed to add proposal", __func__); | |||
2537 | return (-1); | |||
2538 | } | |||
2539 | ||||
2540 | if (sendikespi) { | |||
2541 | /* Special case for IKE SA rekeying */ | |||
2542 | prop->prop_localspi.spi = initiator ? | |||
2543 | sa->sa_hdr.sh_ispi : sa->sa_hdr.sh_rspi; | |||
2544 | prop->prop_localspi.spi_size = 8; | |||
2545 | prop->prop_localspi.spi_protoid = IKEV2_SAPROTO_IKE1; | |||
2546 | } | |||
2547 | ||||
2548 | /* | |||
2549 | * A single DH transform of type NONE is equivalent with | |||
2550 | * not sending a DH transform at all. | |||
2551 | * Prefer the latter for downwards compatibility. | |||
2552 | */ | |||
2553 | if (protoid != IKEV2_SAPROTO_IKE1) { | |||
2554 | for (i = 0; i < prop->prop_nxforms; i++) { | |||
2555 | xform = prop->prop_xforms + i; | |||
2556 | if (xform->xform_type == IKEV2_XFORMTYPE_DH4 && | |||
2557 | xform->xform_id != IKEV2_XFORMDH_NONE0) | |||
2558 | break; | |||
2559 | } | |||
2560 | if (i == prop->prop_nxforms) | |||
2561 | prop_skipdh = 1; | |||
2562 | } | |||
2563 | ||||
2564 | /* | |||
2565 | * RFC 7296: 1.2. The Initial Exchanges | |||
2566 | * IKE_AUTH messages do not contain KE/N payloads, thus | |||
2567 | * SA payloads cannot contain groups. | |||
2568 | */ | |||
2569 | if (prop_skipdh) { | |||
2570 | nxforms = 0; | |||
2571 | for (i = 0; i < prop->prop_nxforms; i++) { | |||
2572 | xform = prop->prop_xforms + i; | |||
2573 | if (xform->xform_type == IKEV2_XFORMTYPE_DH4) | |||
2574 | continue; | |||
2575 | nxforms++; | |||
2576 | } | |||
2577 | } else | |||
2578 | nxforms = prop->prop_nxforms; | |||
2579 | ||||
2580 | sap->sap_more = IKEV1_PAYLOAD_PROPOSAL2; | |||
2581 | sap->sap_proposalnr = prop->prop_id; | |||
2582 | sap->sap_protoid = prop->prop_protoid; | |||
2583 | sap->sap_spisize = prop->prop_localspi.spi_size; | |||
2584 | sap->sap_transforms = nxforms; | |||
2585 | saplength = sizeof(*sap); | |||
2586 | ||||
2587 | switch (prop->prop_localspi.spi_size) { | |||
2588 | case 4: | |||
2589 | spi32 = htobe32(prop->prop_localspi.spi)(__uint32_t)(__builtin_constant_p(prop->prop_localspi.spi) ? (__uint32_t)(((__uint32_t)(prop->prop_localspi.spi) & 0xff) << 24 | ((__uint32_t)(prop->prop_localspi.spi ) & 0xff00) << 8 | ((__uint32_t)(prop->prop_localspi .spi) & 0xff0000) >> 8 | ((__uint32_t)(prop->prop_localspi .spi) & 0xff000000) >> 24) : __swap32md(prop->prop_localspi .spi)); | |||
2590 | if (ibuf_add(buf, &spi32, sizeof(spi32)) != 0) | |||
2591 | return (-1); | |||
2592 | saplength += 4; | |||
2593 | break; | |||
2594 | case 8: | |||
2595 | spi64 = htobe64(prop->prop_localspi.spi)(__uint64_t)(__builtin_constant_p(prop->prop_localspi.spi) ? (__uint64_t)((((__uint64_t)(prop->prop_localspi.spi) & 0xff) << 56) | ((__uint64_t)(prop->prop_localspi.spi ) & 0xff00ULL) << 40 | ((__uint64_t)(prop->prop_localspi .spi) & 0xff0000ULL) << 24 | ((__uint64_t)(prop-> prop_localspi.spi) & 0xff000000ULL) << 8 | ((__uint64_t )(prop->prop_localspi.spi) & 0xff00000000ULL) >> 8 | ((__uint64_t)(prop->prop_localspi.spi) & 0xff0000000000ULL ) >> 24 | ((__uint64_t)(prop->prop_localspi.spi) & 0xff000000000000ULL) >> 40 | ((__uint64_t)(prop->prop_localspi .spi) & 0xff00000000000000ULL) >> 56) : __swap64md( prop->prop_localspi.spi)); | |||
2596 | if (ibuf_add(buf, &spi64, sizeof(spi64)) != 0) | |||
2597 | return (-1); | |||
2598 | saplength += 8; | |||
2599 | break; | |||
2600 | default: | |||
2601 | break; | |||
2602 | } | |||
2603 | ||||
2604 | for (i = 0, xfi = 0; i < prop->prop_nxforms; i++) { | |||
2605 | xform = prop->prop_xforms + i; | |||
2606 | ||||
2607 | if (prop_skipdh && xform->xform_type == IKEV2_XFORMTYPE_DH4) | |||
2608 | continue; | |||
2609 | ||||
2610 | if ((xflen = ikev2_add_transform(buf, | |||
2611 | xfi == nxforms - 1 ? | |||
2612 | IKEV2_XFORM_LAST0 : IKEV2_XFORM_MORE3, | |||
2613 | xform->xform_type, xform->xform_id, | |||
2614 | xform->xform_length)) == -1) | |||
2615 | return (-1); | |||
2616 | ||||
2617 | xfi++; | |||
2618 | saplength += xflen; | |||
2619 | } | |||
2620 | ||||
2621 | sap->sap_length = htobe16(saplength)(__uint16_t)(__builtin_constant_p(saplength) ? (__uint16_t)(( (__uint16_t)(saplength) & 0xffU) << 8 | ((__uint16_t )(saplength) & 0xff00U) >> 8) : __swap16md(saplength )); | |||
2622 | length += saplength; | |||
2623 | } | |||
2624 | if (sap != NULL((void*)0)) | |||
2625 | sap->sap_more = IKEV1_PAYLOAD_NONE0; | |||
2626 | ||||
2627 | log_debug("%s: length %zd", __func__, length); | |||
2628 | ||||
2629 | return (length); | |||
2630 | } | |||
2631 | ||||
2632 | ssize_t | |||
2633 | ikev2_add_transform(struct ibuf *buf, | |||
2634 | uint8_t more, uint8_t type, uint16_t id, uint16_t length) | |||
2635 | { | |||
2636 | struct ikev2_transform *xfrm; | |||
2637 | struct ikev2_attribute *attr; | |||
2638 | ||||
2639 | if ((xfrm = ibuf_advance(buf, sizeof(*xfrm))) == NULL((void*)0)) { | |||
2640 | log_debug("%s: failed to add transform", __func__); | |||
2641 | return (-1); | |||
2642 | } | |||
2643 | xfrm->xfrm_more = more; | |||
2644 | xfrm->xfrm_type = type; | |||
2645 | xfrm->xfrm_id = htobe16(id)(__uint16_t)(__builtin_constant_p(id) ? (__uint16_t)(((__uint16_t )(id) & 0xffU) << 8 | ((__uint16_t)(id) & 0xff00U ) >> 8) : __swap16md(id)); | |||
2646 | ||||
2647 | if (length) { | |||
2648 | xfrm->xfrm_length = htobe16(sizeof(*xfrm) + sizeof(*attr))(__uint16_t)(__builtin_constant_p(sizeof(*xfrm) + sizeof(*attr )) ? (__uint16_t)(((__uint16_t)(sizeof(*xfrm) + sizeof(*attr) ) & 0xffU) << 8 | ((__uint16_t)(sizeof(*xfrm) + sizeof (*attr)) & 0xff00U) >> 8) : __swap16md(sizeof(*xfrm ) + sizeof(*attr))); | |||
2649 | ||||
2650 | if ((attr = ibuf_advance(buf, sizeof(*attr))) == NULL((void*)0)) { | |||
2651 | log_debug("%s: failed to add attribute", __func__); | |||
2652 | return (-1); | |||
2653 | } | |||
2654 | attr->attr_type = htobe16(IKEV2_ATTRAF_TV |(__uint16_t)(__builtin_constant_p(0x8000 | 14) ? (__uint16_t) (((__uint16_t)(0x8000 | 14) & 0xffU) << 8 | ((__uint16_t )(0x8000 | 14) & 0xff00U) >> 8) : __swap16md(0x8000 | 14)) | |||
2655 | IKEV2_ATTRTYPE_KEY_LENGTH)(__uint16_t)(__builtin_constant_p(0x8000 | 14) ? (__uint16_t) (((__uint16_t)(0x8000 | 14) & 0xffU) << 8 | ((__uint16_t )(0x8000 | 14) & 0xff00U) >> 8) : __swap16md(0x8000 | 14)); | |||
2656 | attr->attr_length = htobe16(length)(__uint16_t)(__builtin_constant_p(length) ? (__uint16_t)(((__uint16_t )(length) & 0xffU) << 8 | ((__uint16_t)(length) & 0xff00U) >> 8) : __swap16md(length)); | |||
2657 | } else | |||
2658 | xfrm->xfrm_length = htobe16(sizeof(*xfrm))(__uint16_t)(__builtin_constant_p(sizeof(*xfrm)) ? (__uint16_t )(((__uint16_t)(sizeof(*xfrm)) & 0xffU) << 8 | ((__uint16_t )(sizeof(*xfrm)) & 0xff00U) >> 8) : __swap16md(sizeof (*xfrm))); | |||
2659 | ||||
2660 | return (betoh16(xfrm->xfrm_length)(__uint16_t)(__builtin_constant_p(xfrm->xfrm_length) ? (__uint16_t )(((__uint16_t)(xfrm->xfrm_length) & 0xffU) << 8 | ((__uint16_t)(xfrm->xfrm_length) & 0xff00U) >> 8) : __swap16md(xfrm->xfrm_length))); | |||
2661 | } | |||
2662 | ||||
2663 | int | |||
2664 | ikev2_add_data(struct ibuf *buf, void *data, size_t length) | |||
2665 | { | |||
2666 | void *msgbuf; | |||
2667 | ||||
2668 | if ((msgbuf = ibuf_advance(buf, length)) == NULL((void*)0)) { | |||
2669 | log_debug("%s: failed", __func__); | |||
2670 | return (-1); | |||
2671 | } | |||
2672 | memcpy(msgbuf, data, length); | |||
2673 | ||||
2674 | return (0); | |||
2675 | } | |||
2676 | ||||
2677 | int | |||
2678 | ikev2_add_buf(struct ibuf *buf, struct ibuf *data) | |||
2679 | { | |||
2680 | void *msgbuf; | |||
2681 | ||||
2682 | if ((msgbuf = ibuf_advance(buf, ibuf_size(data))) == NULL((void*)0)) { | |||
2683 | log_debug("%s: failed", __func__); | |||
2684 | return (-1); | |||
2685 | } | |||
2686 | memcpy(msgbuf, ibuf_data(data), ibuf_size(data)); | |||
2687 | ||||
2688 | return (0); | |||
2689 | } | |||
2690 | ||||
2691 | int | |||
2692 | ikev2_resp_informational(struct iked *env, struct iked_sa *sa, | |||
2693 | struct iked_message *msg) | |||
2694 | { | |||
2695 | struct ikev2_notify *n; | |||
2696 | struct ikev2_payload *pld = NULL((void*)0); | |||
2697 | struct ibuf *buf = NULL((void*)0); | |||
2698 | ssize_t len = 0; | |||
2699 | int ret = -1; | |||
2700 | uint8_t firstpayload = IKEV2_PAYLOAD_NONE0; | |||
2701 | ||||
2702 | if (!sa_stateok(sa, IKEV2_STATE_AUTH_REQUEST5) || | |||
2703 | msg->msg_responded || msg->msg_error) | |||
2704 | goto done; | |||
2705 | ||||
2706 | if ((buf = ibuf_static()) == NULL((void*)0)) | |||
2707 | goto done; | |||
2708 | ||||
2709 | if ((len = ikev2_handle_delete(env, msg, buf, &pld, | |||
2710 | &firstpayload)) == -1) | |||
2711 | goto done; | |||
2712 | ||||
2713 | /* | |||
2714 | * Include NAT_DETECTION notification on UPDATE_SA_ADDRESSES or if | |||
2715 | * the peer did include them, too (RFC 4555, 3.8). | |||
2716 | */ | |||
2717 | if (sa->sa_mobike && | |||
2718 | (msg->msg_update_sa_addresses || msg->msg_natt_rcvd)) { | |||
2719 | /* NAT-T notify payloads */ | |||
2720 | len = ikev2_add_nat_detection(env, buf, &pld, msg, len); | |||
2721 | if (len == -1) | |||
2722 | goto done; | |||
2723 | firstpayload = IKEV2_PAYLOAD_NOTIFY41; | |||
2724 | } | |||
2725 | /* Reflect COOKIE2 */ | |||
2726 | if (msg->msg_cookie2) { | |||
2727 | /* *pld is NULL if there is no previous payload */ | |||
2728 | if (pld != NULL((void*)0)) { | |||
2729 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NOTIFY41) == -1) | |||
2730 | goto done; | |||
2731 | } | |||
2732 | if ((pld = ikev2_add_payload(buf)) == NULL((void*)0)) | |||
2733 | goto done; | |||
2734 | if ((n = ibuf_advance(buf, sizeof(*n))) == NULL((void*)0)) | |||
2735 | goto done; | |||
2736 | n->n_protoid = IKEV2_SAPROTO_IKE1; | |||
2737 | n->n_spisize = 0; | |||
2738 | n->n_type = htobe16(IKEV2_N_COOKIE2)(__uint16_t)(__builtin_constant_p(16401) ? (__uint16_t)(((__uint16_t )(16401) & 0xffU) << 8 | ((__uint16_t)(16401) & 0xff00U) >> 8) : __swap16md(16401)); | |||
2739 | if (ikev2_add_buf(buf, msg->msg_cookie2) == -1) | |||
2740 | goto done; | |||
2741 | len = sizeof(*n) + ibuf_size(msg->msg_cookie2); | |||
2742 | log_debug("%s: added cookie2", __func__); | |||
2743 | if (firstpayload == IKEV2_PAYLOAD_NONE0) | |||
2744 | firstpayload = IKEV2_PAYLOAD_NOTIFY41; | |||
2745 | } | |||
2746 | /* add terminator, if there is already a payload */ | |||
2747 | if (firstpayload != IKEV2_PAYLOAD_NONE0) | |||
2748 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONE0) == -1) | |||
2749 | goto done; | |||
2750 | ret = ikev2_msg_send_encrypt(env, sa, &buf, | |||
2751 | IKEV2_EXCHANGE_INFORMATIONAL37, firstpayload, 1); | |||
2752 | if (ret != -1) | |||
2753 | msg->msg_responded = 1; | |||
2754 | if (msg->msg_flags & IKED_MSG_FLAGS_AUTHENTICATION_FAILED0x0020) { | |||
2755 | log_debug("%s: AUTHENTICATION_FAILED, closing SA", | |||
2756 | __func__); | |||
2757 | ikev2_log_cert_info(SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
2758 | sa->sa_hdr.sh_initiator ? &sa->sa_rcert : &sa->sa_icert); | |||
2759 | ikev2_ike_sa_setreason(sa, | |||
2760 | "authentication failed notification from peer"); | |||
2761 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
2762 | } | |||
2763 | done: | |||
2764 | ibuf_release(buf); | |||
2765 | return (ret); | |||
2766 | } | |||
2767 | ||||
2768 | void | |||
2769 | ikev2_resp_recv(struct iked *env, struct iked_message *msg, | |||
2770 | struct ike_header *hdr) | |||
2771 | { | |||
2772 | struct iked_sa *sa; | |||
2773 | ||||
2774 | switch (hdr->ike_exchange) { | |||
2775 | case IKEV2_EXCHANGE_IKE_SA_INIT34: | |||
2776 | if (msg->msg_sa != NULL((void*)0)) { | |||
2777 | log_debug("%s: SA already exists", __func__); | |||
2778 | return; | |||
2779 | } | |||
2780 | if ((msg->msg_sa = sa_new(env, | |||
2781 | betoh64(hdr->ike_ispi)(__uint64_t)(__builtin_constant_p(hdr->ike_ispi) ? (__uint64_t )((((__uint64_t)(hdr->ike_ispi) & 0xff) << 56) | ((__uint64_t)(hdr->ike_ispi) & 0xff00ULL) << 40 | ((__uint64_t)(hdr->ike_ispi) & 0xff0000ULL) << 24 | ((__uint64_t)(hdr->ike_ispi) & 0xff000000ULL) << 8 | ((__uint64_t)(hdr->ike_ispi) & 0xff00000000ULL) >> 8 | ((__uint64_t)(hdr->ike_ispi) & 0xff0000000000ULL) >> 24 | ((__uint64_t)(hdr->ike_ispi) & 0xff000000000000ULL ) >> 40 | ((__uint64_t)(hdr->ike_ispi) & 0xff00000000000000ULL ) >> 56) : __swap64md(hdr->ike_ispi)), betoh64(hdr->ike_rspi)(__uint64_t)(__builtin_constant_p(hdr->ike_rspi) ? (__uint64_t )((((__uint64_t)(hdr->ike_rspi) & 0xff) << 56) | ((__uint64_t)(hdr->ike_rspi) & 0xff00ULL) << 40 | ((__uint64_t)(hdr->ike_rspi) & 0xff0000ULL) << 24 | ((__uint64_t)(hdr->ike_rspi) & 0xff000000ULL) << 8 | ((__uint64_t)(hdr->ike_rspi) & 0xff00000000ULL) >> 8 | ((__uint64_t)(hdr->ike_rspi) & 0xff0000000000ULL) >> 24 | ((__uint64_t)(hdr->ike_rspi) & 0xff000000000000ULL ) >> 40 | ((__uint64_t)(hdr->ike_rspi) & 0xff00000000000000ULL ) >> 56) : __swap64md(hdr->ike_rspi)), | |||
2782 | 0, msg->msg_policy)) == NULL((void*)0)) { | |||
2783 | log_debug("%s: failed to get new SA", __func__); | |||
2784 | return; | |||
2785 | } | |||
2786 | /* Setup exchange timeout. */ | |||
2787 | timer_set(env, &msg->msg_sa->sa_timer, | |||
2788 | ikev2_init_ike_sa_timeout, msg->msg_sa); | |||
2789 | timer_add(env, &msg->msg_sa->sa_timer, | |||
2790 | IKED_IKE_SA_EXCHANGE_TIMEOUT300); | |||
2791 | break; | |||
2792 | case IKEV2_EXCHANGE_IKE_AUTH35: | |||
2793 | if (ikev2_msg_valid_ike_sa(env, hdr, msg) == -1) | |||
2794 | return; | |||
2795 | if (sa_stateok(msg->msg_sa, IKEV2_STATE_VALID7)) { | |||
2796 | log_debug("%s: already authenticated", __func__); | |||
2797 | return; | |||
2798 | } | |||
2799 | break; | |||
2800 | case IKEV2_EXCHANGE_CREATE_CHILD_SA36: | |||
2801 | case IKEV2_EXCHANGE_INFORMATIONAL37: | |||
2802 | if (ikev2_msg_valid_ike_sa(env, hdr, msg) == -1) | |||
2803 | return; | |||
2804 | break; | |||
2805 | default: | |||
2806 | log_debug("%s: unsupported exchange: %s", __func__, | |||
2807 | print_map(hdr->ike_exchange, ikev2_exchange_map)); | |||
2808 | return; | |||
2809 | } | |||
2810 | ||||
2811 | if (ikev2_pld_parse(env, hdr, msg, msg->msg_offset) != 0) { | |||
2812 | log_info("%s: failed to parse message", | |||
2813 | SPI_SA(msg->msg_sa, __func__)ikev2_ikesa_info((&(msg->msg_sa)->sa_hdr)->sh_ispi , ((__func__)))); | |||
2814 | return; | |||
2815 | } | |||
2816 | ||||
2817 | if (!ikev2_msg_frompeer(msg)) | |||
2818 | return; | |||
2819 | ||||
2820 | if (ikev2_handle_notifies(env, msg) != 0) | |||
2821 | return; | |||
2822 | ||||
2823 | if ((sa = msg->msg_sa) == NULL((void*)0)) | |||
2824 | return; | |||
2825 | ||||
2826 | if (sa->sa_fragments.frag_count != 0) | |||
2827 | return; | |||
2828 | ||||
2829 | msg->msg_valid = 1; | |||
2830 | ||||
2831 | if (msg->msg_natt && sa->sa_natt == 0) { | |||
2832 | log_debug("%s: NAT-T message received, updated SA", __func__); | |||
2833 | sa->sa_natt = 1; | |||
2834 | } | |||
2835 | ||||
2836 | switch (hdr->ike_exchange) { | |||
2837 | case IKEV2_EXCHANGE_IKE_SA_INIT34: | |||
2838 | if (ikev2_sa_responder(env, sa, NULL((void*)0), msg) != 0) { | |||
2839 | log_info("%s: failed to negotiate IKE SA", | |||
2840 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
2841 | if (msg->msg_error == 0) | |||
2842 | msg->msg_error = IKEV2_N_NO_PROPOSAL_CHOSEN14; | |||
2843 | ikev2_send_init_error(env, msg); | |||
2844 | ikev2_ike_sa_setreason(sa, "no proposal chosen"); | |||
2845 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
2846 | return; | |||
2847 | } | |||
2848 | if (ikev2_resp_ike_sa_init(env, msg) != 0) { | |||
2849 | log_debug("%s: failed to send init response", __func__); | |||
2850 | ikev2_ike_sa_setreason(sa, "SA_INIT response failed"); | |||
2851 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
2852 | return; | |||
2853 | } | |||
2854 | break; | |||
2855 | case IKEV2_EXCHANGE_IKE_AUTH35: | |||
2856 | if (!sa_stateok(sa, IKEV2_STATE_SA_INIT2)) { | |||
2857 | log_debug("%s: state mismatch", __func__); | |||
2858 | ikev2_ike_sa_setreason(sa, "state mismatch IKE_AUTH"); | |||
2859 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
2860 | return; | |||
2861 | } | |||
2862 | ||||
2863 | /* Handle EAP authentication */ | |||
2864 | if (msg->msg_eap.eam_found) { | |||
2865 | if (ikev2_resp_ike_eap(env, sa, msg)) { | |||
2866 | log_info("%s: failed eap response", | |||
2867 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
2868 | ikev2_ike_sa_setreason(sa, "EAP failed"); | |||
2869 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
2870 | return; | |||
2871 | } | |||
2872 | return; | |||
2873 | } | |||
2874 | ||||
2875 | if (ikev2_ike_auth_recv(env, sa, msg) != 0) { | |||
2876 | log_debug("%s: failed to send auth response", __func__); | |||
2877 | ikev2_send_error(env, sa, msg, hdr->ike_exchange); | |||
2878 | ikev2_ike_sa_setreason(sa, "IKE_AUTH failed"); | |||
2879 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
2880 | return; | |||
2881 | } | |||
2882 | break; | |||
2883 | case IKEV2_EXCHANGE_CREATE_CHILD_SA36: | |||
2884 | if (ikev2_resp_create_child_sa(env, msg) != 0) { | |||
2885 | if (msg->msg_error == 0) | |||
2886 | msg->msg_error = IKEV2_N_NO_PROPOSAL_CHOSEN14; | |||
2887 | ikev2_send_error(env, sa, msg, hdr->ike_exchange); | |||
2888 | } | |||
2889 | break; | |||
2890 | case IKEV2_EXCHANGE_INFORMATIONAL37: | |||
2891 | if (msg->msg_update_sa_addresses) | |||
2892 | ikev2_update_sa_addresses(env, sa); | |||
2893 | (void)ikev2_resp_informational(env, sa, msg); | |||
2894 | break; | |||
2895 | default: | |||
2896 | break; | |||
2897 | } | |||
2898 | } | |||
2899 | ||||
2900 | ssize_t | |||
2901 | ikev2_handle_delete(struct iked *env, struct iked_message *msg, | |||
2902 | struct ibuf *resp, struct ikev2_payload **pld, uint8_t *firstpayload) | |||
2903 | { | |||
2904 | struct iked_childsa **peersas = NULL((void*)0); | |||
2905 | struct iked_sa *sa = msg->msg_sa; | |||
2906 | struct ikev2_delete *localdel; | |||
2907 | struct ibuf *spibuf = NULL((void*)0); | |||
2908 | uint64_t *localspi = NULL((void*)0); | |||
2909 | uint64_t spi64, spi = 0; | |||
2910 | uint32_t spi32; | |||
2911 | uint8_t *buf; | |||
2912 | size_t found = 0, failed = 0; | |||
2913 | int ret = -1; | |||
2914 | size_t i, sz, cnt, len; | |||
2915 | ||||
2916 | if (!msg->msg_del_protoid) | |||
2917 | return (0); | |||
2918 | ||||
2919 | sz = msg->msg_del_spisize; | |||
2920 | ||||
2921 | switch (sz) { | |||
2922 | case 4: | |||
2923 | case 8: | |||
2924 | break; | |||
2925 | case 0: | |||
2926 | if (msg->msg_del_protoid != IKEV2_SAPROTO_IKE1) { | |||
2927 | log_debug("%s: invalid SPI size", __func__); | |||
2928 | goto done; | |||
2929 | } | |||
2930 | ikev2_ikesa_recv_delete(env, sa); | |||
2931 | return (0); | |||
2932 | default: | |||
2933 | log_info("%s: error: invalid SPI size", __func__); | |||
2934 | goto done; | |||
2935 | } | |||
2936 | ||||
2937 | cnt = msg->msg_del_cnt; | |||
2938 | len = ibuf_length(msg->msg_del_buf); | |||
2939 | ||||
2940 | if ((len / sz) != cnt) { | |||
2941 | log_debug("%s: invalid payload length %zu/%zu != %zu", | |||
2942 | __func__, len, sz, cnt); | |||
2943 | return (-1); | |||
2944 | } | |||
2945 | ||||
2946 | if (((peersas = calloc(cnt, sizeof(struct iked_childsa *))) == NULL((void*)0) || | |||
2947 | (localspi = calloc(cnt, sizeof(uint64_t))) == NULL((void*)0))) { | |||
2948 | log_warn("%s", __func__); | |||
2949 | goto done; | |||
2950 | } | |||
2951 | ||||
2952 | buf = ibuf_data(msg->msg_del_buf); | |||
2953 | for (i = 0; i < cnt; i++) { | |||
2954 | switch (sz) { | |||
2955 | case 4: | |||
2956 | memcpy(&spi32, buf + (i * sz), sizeof(spi32)); | |||
2957 | spi = betoh32(spi32)(__uint32_t)(__builtin_constant_p(spi32) ? (__uint32_t)(((__uint32_t )(spi32) & 0xff) << 24 | ((__uint32_t)(spi32) & 0xff00) << 8 | ((__uint32_t)(spi32) & 0xff0000) >> 8 | ((__uint32_t)(spi32) & 0xff000000) >> 24) : __swap32md (spi32)); | |||
2958 | break; | |||
2959 | case 8: | |||
2960 | memcpy(&spi64, buf + (i * sz), sizeof(spi64)); | |||
2961 | spi = betoh64(spi64)(__uint64_t)(__builtin_constant_p(spi64) ? (__uint64_t)((((__uint64_t )(spi64) & 0xff) << 56) | ((__uint64_t)(spi64) & 0xff00ULL) << 40 | ((__uint64_t)(spi64) & 0xff0000ULL ) << 24 | ((__uint64_t)(spi64) & 0xff000000ULL) << 8 | ((__uint64_t)(spi64) & 0xff00000000ULL) >> 8 | ((__uint64_t)(spi64) & 0xff0000000000ULL) >> 24 | ( (__uint64_t)(spi64) & 0xff000000000000ULL) >> 40 | ( (__uint64_t)(spi64) & 0xff00000000000000ULL) >> 56) : __swap64md(spi64)); | |||
2962 | break; | |||
2963 | } | |||
2964 | ||||
2965 | log_debug("%s: spi %s", __func__, print_spi(spi, sz)); | |||
2966 | ||||
2967 | if (peersas == NULL((void*)0) || sa == NULL((void*)0)) | |||
2968 | continue; | |||
2969 | ||||
2970 | if ((peersas[i] = childsa_lookup(sa, spi, | |||
2971 | msg->msg_del_protoid)) == NULL((void*)0)) { | |||
2972 | log_warnx("%s: CHILD SA doesn't exist for spi %s", | |||
2973 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
2974 | print_spi(spi, sz)); | |||
2975 | continue; | |||
2976 | } | |||
2977 | ||||
2978 | if (ikev2_childsa_delete(env, sa, msg->msg_del_protoid, spi, | |||
2979 | &localspi[i], 0) == -1) | |||
2980 | failed++; | |||
2981 | else { | |||
2982 | found++; | |||
2983 | ||||
2984 | /* append SPI to log buffer */ | |||
2985 | if (ibuf_strlen(spibuf)) | |||
2986 | ibuf_strcat(&spibuf, ", "); | |||
2987 | ibuf_strcat(&spibuf, print_spi(spi, sz)); | |||
2988 | } | |||
2989 | ||||
2990 | /* | |||
2991 | * Flows are left in the require mode so that it would be | |||
2992 | * possible to quickly negotiate a new Child SA | |||
2993 | */ | |||
2994 | } | |||
2995 | ||||
2996 | if (resp == NULL((void*)0)) { | |||
2997 | ret = 0; | |||
2998 | goto done; | |||
2999 | } | |||
3000 | ||||
3001 | /* Response to the INFORMATIONAL with Delete payload */ | |||
3002 | if (found) { | |||
3003 | if ((*pld = ikev2_add_payload(resp)) == NULL((void*)0)) | |||
3004 | goto done; | |||
3005 | *firstpayload = IKEV2_PAYLOAD_DELETE42; | |||
3006 | ||||
3007 | if ((localdel = ibuf_advance(resp, sizeof(*localdel))) == NULL((void*)0)) | |||
3008 | goto done; | |||
3009 | ||||
3010 | localdel->del_protoid = msg->msg_del_protoid; | |||
3011 | localdel->del_spisize = sz; | |||
3012 | localdel->del_nspi = htobe16(found)(__uint16_t)(__builtin_constant_p(found) ? (__uint16_t)(((__uint16_t )(found) & 0xffU) << 8 | ((__uint16_t)(found) & 0xff00U) >> 8) : __swap16md(found)); | |||
3013 | ret = sizeof(*localdel); | |||
3014 | ||||
3015 | for (i = 0; i < cnt; i++) { | |||
3016 | if (localspi[i] == 0) /* happens if found < cnt */ | |||
3017 | continue; | |||
3018 | switch (sz) { | |||
3019 | case 4: | |||
3020 | spi32 = htobe32(localspi[i])(__uint32_t)(__builtin_constant_p(localspi[i]) ? (__uint32_t) (((__uint32_t)(localspi[i]) & 0xff) << 24 | ((__uint32_t )(localspi[i]) & 0xff00) << 8 | ((__uint32_t)(localspi [i]) & 0xff0000) >> 8 | ((__uint32_t)(localspi[i]) & 0xff000000) >> 24) : __swap32md(localspi[i])); | |||
3021 | if (ibuf_add(resp, &spi32, sizeof(spi32)) != 0) | |||
3022 | goto done; | |||
3023 | ret += sizeof(spi32); | |||
3024 | break; | |||
3025 | case 8: | |||
3026 | spi64 = htobe64(localspi[i])(__uint64_t)(__builtin_constant_p(localspi[i]) ? (__uint64_t) ((((__uint64_t)(localspi[i]) & 0xff) << 56) | ((__uint64_t )(localspi[i]) & 0xff00ULL) << 40 | ((__uint64_t)(localspi [i]) & 0xff0000ULL) << 24 | ((__uint64_t)(localspi[ i]) & 0xff000000ULL) << 8 | ((__uint64_t)(localspi[ i]) & 0xff00000000ULL) >> 8 | ((__uint64_t)(localspi [i]) & 0xff0000000000ULL) >> 24 | ((__uint64_t)(localspi [i]) & 0xff000000000000ULL) >> 40 | ((__uint64_t)(localspi [i]) & 0xff00000000000000ULL) >> 56) : __swap64md(localspi [i])); | |||
3027 | if (ibuf_add(resp, &spi64, sizeof(spi64)) != 0) | |||
3028 | goto done; | |||
3029 | ret += sizeof(spi64); | |||
3030 | break; | |||
3031 | } | |||
3032 | } | |||
3033 | log_info("%sdeleted %zu SPI%s: %.*s", | |||
3034 | SPI_SA(sa, NULL)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((((void *)0)))), found, | |||
3035 | found == 1 ? "" : "s", | |||
3036 | spibuf ? ibuf_strlen(spibuf) : 0, | |||
3037 | spibuf ? (char *)ibuf_data(spibuf) : ""); | |||
3038 | } else { | |||
3039 | /* XXX should we send an INVALID_SPI notification? */ | |||
3040 | ret = 0; | |||
3041 | } | |||
3042 | ||||
3043 | done: | |||
3044 | free(localspi); | |||
3045 | free(peersas); | |||
3046 | ibuf_release(spibuf); | |||
3047 | ||||
3048 | return (ret); | |||
3049 | } | |||
3050 | ||||
3051 | int | |||
3052 | ikev2_handle_notifies(struct iked *env, struct iked_message *msg) | |||
3053 | { | |||
3054 | struct iked_ipcomp *ic; | |||
3055 | struct iked_sa *sa; | |||
3056 | struct iked_spi rekey; | |||
3057 | struct dh_group *group; | |||
3058 | uint16_t groupid; | |||
3059 | unsigned int protoid; | |||
3060 | ||||
3061 | if ((sa = msg->msg_sa) == NULL((void*)0)) | |||
3062 | return (-1); | |||
3063 | ||||
3064 | if (msg->msg_flags & IKED_MSG_FLAGS_CHILD_SA_NOT_FOUND0x0008) | |||
3065 | sa->sa_stateflags &= ~IKED_REQ_CHILDSA0x0080; | |||
3066 | ||||
3067 | if ((msg->msg_flags & IKED_MSG_FLAGS_FRAGMENTATION0x0001) && env->sc_fragsc_static.st_frag) { | |||
3068 | log_debug("%s: fragmentation enabled", __func__); | |||
3069 | sa->sa_frag = 1; | |||
3070 | } | |||
3071 | ||||
3072 | if ((msg->msg_flags & IKED_MSG_FLAGS_MOBIKE0x0002) && env->sc_mobikesc_static.st_mobike) { | |||
3073 | log_debug("%s: mobike enabled", __func__); | |||
3074 | sa->sa_mobike = 1; | |||
3075 | /* enforce natt */ | |||
3076 | if (sa->sa_natt == 0 && sa->sa_udpencap == 0) | |||
3077 | ikev2_enable_natt(env, sa, msg, 0); | |||
3078 | } | |||
3079 | ||||
3080 | if ((msg->msg_flags & IKED_MSG_FLAGS_NO_ADDITIONAL_SAS0x0010) | |||
3081 | && sa->sa_stateflags & IKED_REQ_CHILDSA0x0080) { | |||
3082 | /* This makes sense for Child SAs only atm */ | |||
3083 | ikev2_disable_rekeying(env, sa); | |||
3084 | sa->sa_stateflags &= ~IKED_REQ_CHILDSA0x0080; | |||
3085 | } | |||
3086 | ||||
3087 | if (msg->msg_flags & IKED_MSG_FLAGS_INVALID_KE0x0040) { | |||
3088 | groupid = betoh16(msg->msg_group)(__uint16_t)(__builtin_constant_p(msg->msg_group) ? (__uint16_t )(((__uint16_t)(msg->msg_group) & 0xffU) << 8 | ( (__uint16_t)(msg->msg_group) & 0xff00U) >> 8) : __swap16md (msg->msg_group)); | |||
3089 | if (group_getid(groupid) == NULL((void*)0)) { | |||
3090 | log_debug("%s: unable to select DH group %u", | |||
3091 | __func__, groupid); | |||
3092 | ikev2_ike_sa_setreason(sa, | |||
3093 | "unable to select DH group"); | |||
3094 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
3095 | msg->msg_sa = NULL((void*)0); | |||
3096 | return (-1); | |||
3097 | } | |||
3098 | log_debug("%s: responder selected DH group %u", __func__, | |||
3099 | groupid); | |||
3100 | switch (msg->msg_exchange) { | |||
3101 | case IKEV2_EXCHANGE_IKE_SA_INIT34: | |||
3102 | protoid = IKEV2_SAPROTO_IKE1; | |||
3103 | if (!sa->sa_hdr.sh_initiator) { | |||
3104 | log_debug("%s: not an initiator", __func__); | |||
3105 | ikev2_ike_sa_setreason(sa, | |||
3106 | "received invalid KE as responder"); | |||
3107 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
3108 | msg->msg_sa = NULL((void*)0); | |||
3109 | return (-1); | |||
3110 | } | |||
3111 | if (config_findtransform_ext(&msg->msg_policy->pol_proposals, | |||
3112 | IKEV2_XFORMTYPE_DH4, groupid, protoid) == NULL((void*)0)) { | |||
3113 | log_debug("%s: DH group %u denied by policy", | |||
3114 | __func__, groupid); | |||
3115 | ikev2_ike_sa_setreason(sa, | |||
3116 | "unsupported group in INVALID_KE message"); | |||
3117 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
3118 | msg->msg_sa = NULL((void*)0); | |||
3119 | return (-1); | |||
3120 | } | |||
3121 | ikev2_ike_sa_setreason(sa, | |||
3122 | "reinitiating with new DH group"); | |||
3123 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
3124 | msg->msg_sa = NULL((void*)0); | |||
3125 | msg->msg_policy->pol_peerdh = groupid; | |||
3126 | timer_set(env, &env->sc_inittmr, ikev2_init_ike_sa, NULL((void*)0)); | |||
3127 | timer_add(env, &env->sc_inittmr, IKED_INITIATOR_INITIAL2); | |||
3128 | return (-1); | |||
3129 | case IKEV2_EXCHANGE_CREATE_CHILD_SA36: | |||
3130 | if (!(sa->sa_stateflags & IKED_REQ_CHILDSA0x0080)) { | |||
3131 | log_debug("%s: IKED_REQ_CHILDSA missing", | |||
3132 | __func__); | |||
3133 | return (-1); | |||
3134 | } | |||
3135 | sa->sa_stateflags &= ~IKED_REQ_CHILDSA0x0080; | |||
3136 | protoid = sa->sa_rekeyspi ? | |||
3137 | IKEV2_SAPROTO_ESP3 : IKEV2_SAPROTO_IKE1; | |||
3138 | if (config_findtransform_ext(&msg->msg_policy->pol_proposals, | |||
3139 | IKEV2_XFORMTYPE_DH4, groupid, protoid) == NULL((void*)0)) { | |||
3140 | log_debug("%s: DH group %u denied by policy", | |||
3141 | __func__, groupid); | |||
3142 | ikev2_ike_sa_setreason(sa, | |||
3143 | "unsupported group in INVALID_KE message"); | |||
3144 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
3145 | msg->msg_sa = NULL((void*)0); | |||
3146 | return (-1); | |||
3147 | } | |||
3148 | if (protoid == IKEV2_SAPROTO_ESP3) { | |||
3149 | /* CHILDSA */ | |||
3150 | rekey.spi = sa->sa_rekeyspi; | |||
3151 | rekey.spi_size = 4; | |||
3152 | rekey.spi_protoid = protoid; | |||
3153 | (void)ikev2_send_create_child_sa(env, sa, | |||
3154 | &rekey, rekey.spi_protoid, groupid); | |||
3155 | } else { | |||
3156 | /* IKESA */ | |||
3157 | if ((group = group_get(groupid)) == NULL((void*)0)) | |||
3158 | return -1; | |||
3159 | group_free(sa->sa_dhgroupsa_kex.kex_dhgroup); | |||
3160 | sa->sa_dhgroupsa_kex.kex_dhgroup = group; | |||
3161 | timer_set(env, &sa->sa_rekey, | |||
3162 | ikev2_ike_sa_rekey, sa); | |||
3163 | timer_add(env, &sa->sa_rekey, 0); | |||
3164 | } | |||
3165 | return (-1); | |||
3166 | } | |||
3167 | } | |||
3168 | ||||
3169 | if (msg->msg_flags & IKED_MSG_FLAGS_IPCOMP_SUPPORTED0x0080) { | |||
3170 | /* we only support deflate */ | |||
3171 | if ((msg->msg_policy->pol_flags & IKED_POLICY_IPCOMP0x20) && | |||
3172 | (msg->msg_transform == IKEV2_IPCOMP_DEFLATE2)) { | |||
3173 | ic = msg->msg_response ? | |||
3174 | &sa->sa_ipcompi : | |||
3175 | &sa->sa_ipcompr; | |||
3176 | ic->ic_transform = msg->msg_transform; | |||
3177 | ic->ic_cpi_out = betoh16(msg->msg_cpi)(__uint16_t)(__builtin_constant_p(msg->msg_cpi) ? (__uint16_t )(((__uint16_t)(msg->msg_cpi) & 0xffU) << 8 | (( __uint16_t)(msg->msg_cpi) & 0xff00U) >> 8) : __swap16md (msg->msg_cpi)); | |||
3178 | } | |||
3179 | } | |||
3180 | ||||
3181 | if (msg->msg_nat_detected & IKED_MSG_NAT_DST_IP0x02) { | |||
3182 | /* Send keepalive, since we are behind a NAT-gw */ | |||
3183 | sa->sa_usekeepalive = 1; | |||
3184 | } | |||
3185 | ||||
3186 | /* Signature hash algorithm */ | |||
3187 | if (msg->msg_flags & IKED_MSG_FLAGS_SIGSHA20x0004) | |||
3188 | sa->sa_sigsha2 = 1; | |||
3189 | ||||
3190 | if (msg->msg_flags & IKED_MSG_FLAGS_USE_TRANSPORT0x0100) | |||
3191 | sa->sa_use_transport_mode = 1; | |||
3192 | ||||
3193 | if ((msg->msg_flags & IKED_MSG_FLAGS_TEMPORARY_FAILURE0x0200) | |||
3194 | && sa->sa_nexti != NULL((void*)0)) | |||
3195 | sa->sa_tmpfail = 1; | |||
3196 | ||||
3197 | return (0); | |||
3198 | } | |||
3199 | ||||
3200 | int | |||
3201 | ikev2_resp_ike_sa_init(struct iked *env, struct iked_message *msg) | |||
3202 | { | |||
3203 | struct iked_message resp; | |||
3204 | struct ike_header *hdr; | |||
3205 | struct ikev2_payload *pld; | |||
3206 | struct ikev2_keyexchange *ke; | |||
3207 | struct iked_sa *sa = msg->msg_sa; | |||
3208 | struct ibuf *buf; | |||
3209 | struct dh_group *group; | |||
3210 | ssize_t len; | |||
3211 | int ret = -1; | |||
3212 | ||||
3213 | if (sa->sa_hdr.sh_initiator) { | |||
3214 | log_debug("%s: called by initiator", __func__); | |||
3215 | return (-1); | |||
3216 | } | |||
3217 | if (msg->msg_nat_detected && sa->sa_udpencap == 0) { | |||
3218 | log_debug("%s: detected NAT, enabling UDP encapsulation", | |||
3219 | __func__); | |||
3220 | sa->sa_udpencap = 1; | |||
3221 | } | |||
3222 | ||||
3223 | if ((buf = ikev2_msg_init(env, &resp, | |||
3224 | &msg->msg_peer, msg->msg_peerlen, | |||
3225 | &msg->msg_local, msg->msg_locallen, 1)) == NULL((void*)0)) | |||
3226 | goto done; | |||
3227 | ||||
3228 | resp.msg_sa = sa; | |||
3229 | resp.msg_fd = msg->msg_fd; | |||
3230 | resp.msg_natt = msg->msg_natt; | |||
3231 | resp.msg_msgid = 0; | |||
3232 | ||||
3233 | /* IKE header */ | |||
3234 | if ((hdr = ikev2_add_header(buf, sa, resp.msg_msgid, | |||
3235 | IKEV2_PAYLOAD_SA33, IKEV2_EXCHANGE_IKE_SA_INIT34, | |||
3236 | IKEV2_FLAG_RESPONSE0x20)) == NULL((void*)0)) | |||
3237 | goto done; | |||
3238 | ||||
3239 | /* SA payload */ | |||
3240 | if ((pld = ikev2_add_payload(buf)) == NULL((void*)0)) | |||
3241 | goto done; | |||
3242 | if ((len = ikev2_add_proposals(env, sa, buf, &sa->sa_proposals, | |||
3243 | IKEV2_SAPROTO_IKE1, sa->sa_hdr.sh_initiator, 0, 0)) == -1) | |||
3244 | goto done; | |||
3245 | ||||
3246 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_KE34) == -1) | |||
3247 | goto done; | |||
3248 | ||||
3249 | /* KE payload */ | |||
3250 | if ((pld = ikev2_add_payload(buf)) == NULL((void*)0)) | |||
3251 | goto done; | |||
3252 | if ((ke = ibuf_advance(buf, sizeof(*ke))) == NULL((void*)0)) | |||
3253 | goto done; | |||
3254 | if ((group = sa->sa_dhgroupsa_kex.kex_dhgroup) == NULL((void*)0)) { | |||
3255 | log_debug("%s: invalid dh", __func__); | |||
3256 | goto done; | |||
3257 | } | |||
3258 | ke->kex_dhgroup = htobe16(group->id)(__uint16_t)(__builtin_constant_p(group->id) ? (__uint16_t )(((__uint16_t)(group->id) & 0xffU) << 8 | ((__uint16_t )(group->id) & 0xff00U) >> 8) : __swap16md(group ->id)); | |||
3259 | if (ikev2_add_buf(buf, sa->sa_dhrexchangesa_kex.kex_dhrexchange) == -1) | |||
3260 | goto done; | |||
3261 | len = sizeof(*ke) + ibuf_size(sa->sa_dhrexchangesa_kex.kex_dhrexchange); | |||
3262 | ||||
3263 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONCE40) == -1) | |||
3264 | goto done; | |||
3265 | ||||
3266 | /* NONCE payload */ | |||
3267 | if ((pld = ikev2_add_payload(buf)) == NULL((void*)0)) | |||
3268 | goto done; | |||
3269 | if (ikev2_add_buf(buf, sa->sa_rnoncesa_kex.kex_rnonce) == -1) | |||
3270 | goto done; | |||
3271 | len = ibuf_size(sa->sa_rnoncesa_kex.kex_rnonce); | |||
3272 | ||||
3273 | /* Fragmentation Notify*/ | |||
3274 | if (sa->sa_frag) { | |||
3275 | if ((len = ikev2_add_fragmentation(buf, &pld, len)) | |||
3276 | == -1) | |||
3277 | goto done; | |||
3278 | } | |||
3279 | ||||
3280 | if ((env->sc_nattmode != NATT_DISABLE) && | |||
3281 | msg->msg_local.ss_family != AF_UNSPEC0) { | |||
3282 | if ((len = ikev2_add_nat_detection(env, buf, &pld, &resp, len)) | |||
3283 | == -1) | |||
3284 | goto done; | |||
3285 | } | |||
3286 | if (sa->sa_statevalid & IKED_REQ_CERT0x0001) { | |||
3287 | /* CERTREQ payload(s) */ | |||
3288 | if ((len = ikev2_add_certreq(buf, &pld, | |||
3289 | len, env->sc_certreq, env->sc_certreqtype)) == -1) | |||
3290 | goto done; | |||
3291 | ||||
3292 | if (env->sc_certreqtype != sa->sa_policy->pol_certreqtype && | |||
3293 | (len = ikev2_add_certreq(buf, &pld, | |||
3294 | len, NULL((void*)0), sa->sa_policy->pol_certreqtype)) == -1) | |||
3295 | goto done; | |||
3296 | } | |||
3297 | ||||
3298 | if (sa->sa_sigsha2 && | |||
3299 | (len = ikev2_add_sighashnotify(buf, &pld, len)) == -1) | |||
3300 | goto done; | |||
3301 | ||||
3302 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONE0) == -1) | |||
3303 | goto done; | |||
3304 | ||||
3305 | if (ikev2_set_header(hdr, ibuf_size(buf) - sizeof(*hdr)) == -1) | |||
3306 | goto done; | |||
3307 | ||||
3308 | (void)ikev2_pld_parse(env, hdr, &resp, 0); | |||
3309 | ||||
3310 | ibuf_release(sa->sa_2ndmsg); | |||
3311 | if ((sa->sa_2ndmsg = ibuf_dup(buf)) == NULL((void*)0)) { | |||
3312 | log_debug("%s: failed to copy 2nd message", __func__); | |||
3313 | goto done; | |||
3314 | } | |||
3315 | ||||
3316 | ret = ikev2_msg_send(env, &resp); | |||
3317 | ||||
3318 | done: | |||
3319 | ikev2_msg_cleanup(env, &resp); | |||
3320 | ||||
3321 | return (ret); | |||
3322 | } | |||
3323 | ||||
3324 | int | |||
3325 | ikev2_send_auth_failed(struct iked *env, struct iked_sa *sa) | |||
3326 | { | |||
3327 | char dstid[IKED_ID_SIZE1024]; | |||
3328 | struct ikev2_notify *n; | |||
3329 | struct ibuf *buf = NULL((void*)0); | |||
3330 | int ret = -1, exchange, response; | |||
3331 | ||||
3332 | if (ikev2_print_id(IKESA_DSTID(sa)((sa)->sa_hdr.sh_initiator ? &(sa)->sa_rid : &( sa)->sa_iid), dstid, sizeof(dstid)) == -1) | |||
3333 | bzero(dstid, sizeof(dstid)); | |||
3334 | log_info("%s: authentication failed for %s", | |||
3335 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), dstid); | |||
3336 | ||||
3337 | /* Log certificate information */ | |||
3338 | ikev2_log_cert_info(SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
3339 | sa->sa_hdr.sh_initiator ? &sa->sa_rcert : &sa->sa_icert); | |||
3340 | ||||
3341 | /* Notify payload */ | |||
3342 | if ((buf = ibuf_static()) == NULL((void*)0)) | |||
3343 | goto done; | |||
3344 | if ((n = ibuf_advance(buf, sizeof(*n))) == NULL((void*)0)) | |||
3345 | goto done; | |||
3346 | n->n_protoid = IKEV2_SAPROTO_IKE1; | |||
3347 | n->n_spisize = 0; | |||
3348 | n->n_type = htobe16(IKEV2_N_AUTHENTICATION_FAILED)(__uint16_t)(__builtin_constant_p(24) ? (__uint16_t)(((__uint16_t )(24) & 0xffU) << 8 | ((__uint16_t)(24) & 0xff00U ) >> 8) : __swap16md(24)); | |||
3349 | if (sa->sa_hdr.sh_initiator) { | |||
3350 | exchange = IKEV2_EXCHANGE_INFORMATIONAL37; | |||
3351 | response = 0; | |||
3352 | } else { | |||
3353 | exchange = IKEV2_EXCHANGE_IKE_AUTH35; | |||
3354 | response = 1; | |||
3355 | } | |||
3356 | ret = ikev2_send_ike_e(env, sa, buf, IKEV2_PAYLOAD_NOTIFY41, | |||
3357 | exchange, response); | |||
3358 | if (exchange == IKEV2_EXCHANGE_INFORMATIONAL37) | |||
3359 | sa->sa_stateflags |= IKED_REQ_INF0x0100; | |||
3360 | done: | |||
3361 | ibuf_release(buf); | |||
3362 | ||||
3363 | /* cleanup SA after timeout */ | |||
3364 | sa_state(env, sa, IKEV2_STATE_CLOSING10); | |||
3365 | timer_del(env, &sa->sa_timer); | |||
3366 | timer_set(env, &sa->sa_timer, ikev2_ike_sa_timeout, sa); | |||
3367 | timer_add(env, &sa->sa_timer, IKED_IKE_SA_DELETE_TIMEOUT120); | |||
3368 | config_free_fragments(&sa->sa_fragments); | |||
3369 | ikev2_ike_sa_setreason(sa, "authentication failed"); | |||
3370 | ||||
3371 | return (ret); | |||
3372 | } | |||
3373 | ||||
3374 | ssize_t | |||
3375 | ikev2_add_error(struct iked *env, struct ibuf *buf, struct iked_message *msg) | |||
3376 | { | |||
3377 | struct ikev2_notify *n; | |||
3378 | struct iked_spi *rekey; | |||
3379 | uint16_t group; | |||
3380 | uint32_t spi32; | |||
3381 | uint64_t spi64; | |||
3382 | size_t len; | |||
3383 | uint8_t *ptr; | |||
3384 | ||||
3385 | switch (msg->msg_error) { | |||
3386 | case IKEV2_N_CHILD_SA_NOT_FOUND44: | |||
3387 | break; | |||
3388 | case IKEV2_N_NO_PROPOSAL_CHOSEN14: | |||
3389 | ikev2_log_proposal(msg->msg_sa, &msg->msg_proposals); | |||
3390 | break; | |||
3391 | case IKEV2_N_INVALID_KE_PAYLOAD17: | |||
3392 | break; | |||
3393 | default: | |||
3394 | return (-1); | |||
3395 | } | |||
3396 | log_info("%s: %s", SPI_SA(msg->msg_sa, __func__)ikev2_ikesa_info((&(msg->msg_sa)->sa_hdr)->sh_ispi , ((__func__))), | |||
3397 | print_map(msg->msg_error, ikev2_n_map)); | |||
3398 | len = sizeof(*n); | |||
3399 | if ((ptr = ibuf_advance(buf, len)) == NULL((void*)0)) | |||
3400 | return (-1); | |||
3401 | n = (struct ikev2_notify *)ptr; | |||
3402 | n->n_type = htobe16(msg->msg_error)(__uint16_t)(__builtin_constant_p(msg->msg_error) ? (__uint16_t )(((__uint16_t)(msg->msg_error) & 0xffU) << 8 | ( (__uint16_t)(msg->msg_error) & 0xff00U) >> 8) : __swap16md (msg->msg_error)); | |||
3403 | switch (msg->msg_error) { | |||
3404 | case IKEV2_N_CHILD_SA_NOT_FOUND44: | |||
3405 | rekey = &msg->msg_rekey; | |||
3406 | switch (rekey->spi_size) { | |||
3407 | case 4: | |||
3408 | spi32 = htobe32(rekey->spi)(__uint32_t)(__builtin_constant_p(rekey->spi) ? (__uint32_t )(((__uint32_t)(rekey->spi) & 0xff) << 24 | ((__uint32_t )(rekey->spi) & 0xff00) << 8 | ((__uint32_t)(rekey ->spi) & 0xff0000) >> 8 | ((__uint32_t)(rekey-> spi) & 0xff000000) >> 24) : __swap32md(rekey->spi )); | |||
3409 | if (ibuf_add(buf, &spi32, sizeof(spi32)) != 0) | |||
3410 | return (-1); | |||
3411 | len += sizeof(spi32); | |||
3412 | break; | |||
3413 | case 8: | |||
3414 | spi64 = htobe64(rekey->spi)(__uint64_t)(__builtin_constant_p(rekey->spi) ? (__uint64_t )((((__uint64_t)(rekey->spi) & 0xff) << 56) | (( __uint64_t)(rekey->spi) & 0xff00ULL) << 40 | ((__uint64_t )(rekey->spi) & 0xff0000ULL) << 24 | ((__uint64_t )(rekey->spi) & 0xff000000ULL) << 8 | ((__uint64_t )(rekey->spi) & 0xff00000000ULL) >> 8 | ((__uint64_t )(rekey->spi) & 0xff0000000000ULL) >> 24 | ((__uint64_t )(rekey->spi) & 0xff000000000000ULL) >> 40 | ((__uint64_t )(rekey->spi) & 0xff00000000000000ULL) >> 56) : __swap64md (rekey->spi)); | |||
3415 | if (ibuf_add(buf, &spi64, sizeof(spi64)) != 0) | |||
3416 | return (-1); | |||
3417 | len += sizeof(spi64); | |||
3418 | break; | |||
3419 | default: | |||
3420 | log_debug("%s: invalid SPI size %d", __func__, | |||
3421 | rekey->spi_size); | |||
3422 | return (-1); | |||
3423 | } | |||
3424 | n->n_protoid = rekey->spi_protoid; | |||
3425 | n->n_spisize = rekey->spi_size; | |||
3426 | break; | |||
3427 | case IKEV2_N_INVALID_KE_PAYLOAD17: | |||
3428 | group = htobe16(msg->msg_dhgroup)(__uint16_t)(__builtin_constant_p(msg->msg_dhgroup) ? (__uint16_t )(((__uint16_t)(msg->msg_dhgroup) & 0xffU) << 8 | ((__uint16_t)(msg->msg_dhgroup) & 0xff00U) >> 8 ) : __swap16md(msg->msg_dhgroup)); | |||
3429 | if (ibuf_add(buf, &group, sizeof(group)) != 0) | |||
3430 | return (-1); | |||
3431 | len += sizeof(group); | |||
3432 | n->n_protoid = 0; | |||
3433 | n->n_spisize = 0; | |||
3434 | break; | |||
3435 | default: | |||
3436 | n->n_protoid = 0; | |||
3437 | n->n_spisize = 0; | |||
3438 | break; | |||
3439 | } | |||
3440 | log_debug("%s: done", __func__); | |||
3441 | ||||
3442 | return (len); | |||
3443 | } | |||
3444 | ||||
3445 | int | |||
3446 | ikev2_record_dstid(struct iked *env, struct iked_sa *sa) | |||
3447 | { | |||
3448 | struct iked_sa *osa; | |||
3449 | ||||
3450 | osa = sa_dstid_lookup(env, sa); | |||
3451 | if (osa == sa) | |||
3452 | return (0); | |||
3453 | if (osa != NULL((void*)0)) { | |||
3454 | sa_dstid_remove(env, osa); | |||
3455 | if (env->sc_enforcesingleikesasc_static.st_enforcesingleikesa && | |||
3456 | osa->sa_state < IKEV2_STATE_CLOSING10) { | |||
3457 | log_info("%sreplaced by IKESA %s (identical DSTID)", | |||
3458 | SPI_SA(osa, NULL)ikev2_ikesa_info((&(osa)->sa_hdr)->sh_ispi, ((((void *)0)))), | |||
3459 | print_spi(sa->sa_hdr.sh_ispi, 8)); | |||
3460 | if (osa->sa_state == IKEV2_STATE_ESTABLISHED9) | |||
3461 | ikev2_disable_timer(env, osa); | |||
3462 | ikev2_ike_sa_setreason(osa, "sa replaced"); | |||
3463 | ikev2_ikesa_delete(env, osa, 0); | |||
3464 | timer_add(env, &osa->sa_timer, | |||
3465 | 3 * IKED_RETRANSMIT_TIMEOUT2); | |||
3466 | } | |||
3467 | } | |||
3468 | osa = sa_dstid_insert(env, sa); | |||
3469 | if (osa != NULL((void*)0)) { | |||
3470 | /* XXX how can this fail */ | |||
3471 | log_info("%s: could not replace old IKESA %s", | |||
3472 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
3473 | print_spi(osa->sa_hdr.sh_ispi, 8)); | |||
3474 | return (-1); | |||
3475 | } | |||
3476 | return (0); | |||
3477 | } | |||
3478 | ||||
3479 | int | |||
3480 | ikev2_send_error(struct iked *env, struct iked_sa *sa, | |||
3481 | struct iked_message *msg, uint8_t exchange) | |||
3482 | { | |||
3483 | struct ibuf *buf = NULL((void*)0); | |||
3484 | int ret = -1; | |||
3485 | ||||
3486 | if (msg->msg_error == 0) | |||
3487 | return (0); | |||
3488 | if ((buf = ibuf_static()) == NULL((void*)0)) | |||
3489 | goto done; | |||
3490 | if (ikev2_add_error(env, buf, msg) == 0) | |||
3491 | goto done; | |||
3492 | ret = ikev2_send_ike_e(env, sa, buf, IKEV2_PAYLOAD_NOTIFY41, | |||
3493 | exchange, 1); | |||
3494 | done: | |||
3495 | ibuf_release(buf); | |||
3496 | return (ret); | |||
3497 | } | |||
3498 | ||||
3499 | /* | |||
3500 | * Variant of ikev2_send_error() that can be used before encryption | |||
3501 | * is enabled. Based on ikev2_resp_ike_sa_init() code. | |||
3502 | */ | |||
3503 | int | |||
3504 | ikev2_send_init_error(struct iked *env, struct iked_message *msg) | |||
3505 | { | |||
3506 | struct iked_message resp; | |||
3507 | struct ike_header *hdr; | |||
3508 | struct ikev2_payload *pld; | |||
3509 | struct iked_sa *sa = msg->msg_sa; | |||
3510 | struct ibuf *buf; | |||
3511 | ssize_t len = 0; | |||
3512 | int ret = -1; | |||
3513 | ||||
3514 | if (sa->sa_hdr.sh_initiator) { | |||
3515 | log_debug("%s: called by initiator", __func__); | |||
3516 | return (-1); | |||
3517 | } | |||
3518 | if (msg->msg_error == 0) | |||
3519 | return (0); | |||
3520 | ||||
3521 | if ((buf = ikev2_msg_init(env, &resp, | |||
3522 | &msg->msg_peer, msg->msg_peerlen, | |||
3523 | &msg->msg_local, msg->msg_locallen, 1)) == NULL((void*)0)) | |||
3524 | goto done; | |||
3525 | ||||
3526 | resp.msg_sa = sa; | |||
3527 | resp.msg_fd = msg->msg_fd; | |||
3528 | resp.msg_natt = msg->msg_natt; | |||
3529 | resp.msg_msgid = 0; | |||
3530 | ||||
3531 | /* IKE header */ | |||
3532 | if ((hdr = ikev2_add_header(buf, sa, resp.msg_msgid, | |||
3533 | IKEV2_PAYLOAD_NOTIFY41, IKEV2_EXCHANGE_IKE_SA_INIT34, | |||
3534 | IKEV2_FLAG_RESPONSE0x20)) == NULL((void*)0)) | |||
3535 | goto done; | |||
3536 | ||||
3537 | /* NOTIFY payload */ | |||
3538 | if ((pld = ikev2_add_payload(buf)) == NULL((void*)0)) | |||
3539 | goto done; | |||
3540 | if ((len = ikev2_add_error(env, buf, msg)) == 0) | |||
3541 | goto done; | |||
3542 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONE0) == -1) | |||
3543 | goto done; | |||
3544 | if (ikev2_set_header(hdr, ibuf_size(buf) - sizeof(*hdr)) == -1) | |||
3545 | goto done; | |||
3546 | ||||
3547 | (void)ikev2_pld_parse(env, hdr, &resp, 0); | |||
3548 | ret = ikev2_msg_send(env, &resp); | |||
3549 | ||||
3550 | done: | |||
3551 | ikev2_msg_cleanup(env, &resp); | |||
3552 | ||||
3553 | return (ret); | |||
3554 | } | |||
3555 | ||||
3556 | int | |||
3557 | ikev2_handle_certreq(struct iked* env, struct iked_message *msg) | |||
3558 | { | |||
3559 | struct iked_certreq *cr; | |||
3560 | struct iked_sa *sa; | |||
3561 | uint8_t crtype; | |||
3562 | uint8_t more; | |||
3563 | ||||
3564 | if ((sa = msg->msg_sa) == NULL((void*)0)) | |||
3565 | return (-1); | |||
3566 | ||||
3567 | /* Ignore CERTREQ when policy uses PSK authentication */ | |||
3568 | if (sa->sa_policy->pol_auth.auth_method == IKEV2_AUTH_SHARED_KEY_MIC2) | |||
3569 | return (0); | |||
3570 | ||||
3571 | if (sa->sa_hdr.sh_initiator) | |||
3572 | sa->sa_stateinit |= IKED_REQ_CERT0x0001; | |||
3573 | else | |||
3574 | sa->sa_statevalid |= IKED_REQ_CERT0x0001; | |||
3575 | ||||
3576 | /* | |||
3577 | * If we have to send a local certificate but did not receive an | |||
3578 | * optional CERTREQ, use our own certreq to find a local certificate. | |||
3579 | * We could alternatively extract the CA from the peer certificate | |||
3580 | * to find a matching local one. | |||
3581 | */ | |||
3582 | if (SIMPLEQ_EMPTY(&msg->msg_certreqs)(((&msg->msg_certreqs)->sqh_first) == ((void*)0))) { | |||
3583 | if (sa->sa_policy->pol_certreqtype) | |||
3584 | crtype = sa->sa_policy->pol_certreqtype; | |||
3585 | else | |||
3586 | crtype = env->sc_certreqtype; | |||
3587 | ca_setreq(env, sa, &sa->sa_policy->pol_localid, | |||
3588 | crtype, 0, ibuf_data(env->sc_certreq), | |||
3589 | ibuf_size(env->sc_certreq), PROC_CERT); | |||
3590 | } else { | |||
3591 | while ((cr = SIMPLEQ_FIRST(&msg->msg_certreqs)((&msg->msg_certreqs)->sqh_first))) { | |||
3592 | if (SIMPLEQ_NEXT(cr, cr_entry)((cr)->cr_entry.sqe_next) != NULL((void*)0)) | |||
3593 | more = 1; | |||
3594 | else | |||
3595 | more = 0; | |||
3596 | ||||
3597 | ca_setreq(env, sa, &sa->sa_policy->pol_localid, | |||
3598 | cr->cr_type, more, ibuf_data(cr->cr_data), | |||
3599 | ibuf_length(cr->cr_data), | |||
3600 | PROC_CERT); | |||
3601 | ||||
3602 | ibuf_release(cr->cr_data); | |||
3603 | SIMPLEQ_REMOVE_HEAD(&msg->msg_certreqs, cr_entry)do { if (((&msg->msg_certreqs)->sqh_first = (&msg ->msg_certreqs)->sqh_first->cr_entry.sqe_next) == (( void*)0)) (&msg->msg_certreqs)->sqh_last = &(& msg->msg_certreqs)->sqh_first; } while (0); | |||
3604 | free(cr); | |||
3605 | } | |||
3606 | } | |||
3607 | ||||
3608 | return (0); | |||
3609 | } | |||
3610 | ||||
3611 | int | |||
3612 | ikev2_resp_ike_eap_mschap(struct iked *env, struct iked_sa *sa, | |||
3613 | struct iked_message *msg) | |||
3614 | { | |||
3615 | uint8_t successmsg[EAP_MSCHAP_SUCCESS_SZ42]; | |||
3616 | uint8_t ntresponse[EAP_MSCHAP_NTRESPONSE_SZ24]; | |||
3617 | struct eap_msg *eap = &msg->msg_eap; | |||
3618 | struct iked_user *usr; | |||
3619 | uint8_t *pass; | |||
3620 | char *name = NULL((void*)0); | |||
3621 | size_t passlen; | |||
3622 | int ret; | |||
3623 | ||||
3624 | switch (eap->eam_state) { | |||
3625 | case EAP_STATE_IDENTITY(1): | |||
3626 | sa->sa_eapid = eap->eam_identity; | |||
3627 | return (eap_challenge_request(env, sa, eap->eam_id)); | |||
3628 | case EAP_STATE_MSCHAPV2_CHALLENGE(2): | |||
3629 | if (eap->eam_user) { | |||
3630 | name = eap->eam_user; | |||
3631 | } else if (sa->sa_eapid) { | |||
3632 | name = sa->sa_eapid; | |||
3633 | } | |||
3634 | if (name == NULL((void*)0)) { | |||
3635 | log_info("%s: invalid response name", | |||
3636 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
3637 | return (-1); | |||
3638 | } | |||
3639 | if ((usr = user_lookup(env, name)) == NULL((void*)0)) { | |||
3640 | log_info("%s: unknown user '%s'", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
3641 | name); | |||
3642 | return (-1); | |||
3643 | } | |||
3644 | ||||
3645 | if ((pass = string2unicode(usr->usr_pass, &passlen)) == NULL((void*)0)) | |||
3646 | return (-1); | |||
3647 | ||||
3648 | mschap_nt_response(ibuf_data(sa->sa_eap.id_buf), | |||
3649 | eap->eam_challenge, usr->usr_name, strlen(usr->usr_name), | |||
3650 | pass, passlen, ntresponse); | |||
3651 | ||||
3652 | if (memcmp(ntresponse, eap->eam_ntresponse, | |||
3653 | sizeof(ntresponse)) != 0) { | |||
3654 | log_info("%s: '%s' authentication failed", | |||
3655 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), usr->usr_name); | |||
3656 | freezero(pass, passlen); | |||
3657 | ||||
3658 | /* XXX should we send an EAP failure packet? */ | |||
3659 | return (-1); | |||
3660 | } | |||
3661 | ||||
3662 | bzero(&successmsg, sizeof(successmsg)); | |||
3663 | ||||
3664 | mschap_auth_response(pass, passlen, | |||
3665 | ntresponse, ibuf_data(sa->sa_eap.id_buf), | |||
3666 | eap->eam_challenge, usr->usr_name, strlen(usr->usr_name), | |||
3667 | successmsg); | |||
3668 | if ((sa->sa_eapmsk = ibuf_new(NULL((void*)0), MSCHAP_MSK_SZ64)) == NULL((void*)0)) { | |||
3669 | log_info("%s: failed to get MSK", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
3670 | freezero(pass, passlen); | |||
3671 | return (-1); | |||
3672 | } | |||
3673 | mschap_msk(pass, passlen, ntresponse, | |||
3674 | ibuf_data(sa->sa_eapmsk)); | |||
3675 | freezero(pass, passlen); | |||
3676 | ||||
3677 | log_info("%s: '%s' authenticated", __func__, usr->usr_name); | |||
3678 | ||||
3679 | ret = eap_mschap_challenge(env, sa, eap->eam_id, eap->eam_msrid, | |||
3680 | successmsg, EAP_MSCHAP_SUCCESS_SZ42); | |||
3681 | if (ret == 0) | |||
3682 | sa_state(env, sa, IKEV2_STATE_AUTH_SUCCESS6); | |||
3683 | break; | |||
3684 | case EAP_STATE_MSCHAPV2_SUCCESS(3): | |||
3685 | return (eap_mschap_success(env, sa, eap->eam_id)); | |||
3686 | case EAP_STATE_SUCCESS(4): | |||
3687 | if (!sa_stateok(sa, IKEV2_STATE_AUTH_SUCCESS6)) | |||
3688 | return (-1); | |||
3689 | return (eap_success(env, sa, msg->msg_eap.eam_id)); | |||
3690 | default: | |||
3691 | log_info("%s: eap ignored.", __func__); | |||
3692 | break; | |||
3693 | } | |||
3694 | return 0; | |||
3695 | } | |||
3696 | ||||
3697 | int | |||
3698 | ikev2_resp_ike_eap(struct iked *env, struct iked_sa *sa, | |||
3699 | struct iked_message *msg) | |||
3700 | { | |||
3701 | if (!sa_stateok(sa, IKEV2_STATE_EAP3)) | |||
3702 | return (-1); | |||
3703 | ||||
3704 | switch (sa->sa_policy->pol_auth.auth_eap) { | |||
3705 | case EAP_TYPE_MSCHAP_V226: | |||
3706 | return ikev2_resp_ike_eap_mschap(env, sa, msg); | |||
3707 | } | |||
3708 | return -1; | |||
3709 | } | |||
3710 | ||||
3711 | int | |||
3712 | ikev2_resp_ike_auth(struct iked *env, struct iked_sa *sa) | |||
3713 | { | |||
3714 | struct ikev2_payload *pld; | |||
3715 | struct ikev2_cert *cert; | |||
3716 | struct ikev2_auth *auth; | |||
3717 | struct iked_id *id, *certid; | |||
3718 | struct ibuf *e = NULL((void*)0); | |||
3719 | uint8_t firstpayload; | |||
3720 | int ret = -1; | |||
3721 | ssize_t len; | |||
3722 | ||||
3723 | if (sa == NULL((void*)0)) | |||
3724 | return (-1); | |||
3725 | ||||
3726 | if (sa->sa_state == IKEV2_STATE_EAP3) | |||
3727 | return (eap_identity_request(env, sa)); | |||
3728 | ||||
3729 | if (!sa_stateok(sa, IKEV2_STATE_VALID7)) | |||
3730 | return (0); /* ignore */ | |||
3731 | ||||
3732 | if (ikev2_cp_setaddr(env, sa, AF_INET2) < 0 || | |||
3733 | ikev2_cp_setaddr(env, sa, AF_INET624) < 0) | |||
3734 | return (-1); | |||
3735 | ||||
3736 | if (ikev2_childsa_negotiate(env, sa, &sa->sa_kex, &sa->sa_proposals, | |||
3737 | sa->sa_hdr.sh_initiator, 0) < 0) | |||
3738 | return (-1); | |||
3739 | ||||
3740 | /* New encrypted message buffer */ | |||
3741 | if ((e = ibuf_static()) == NULL((void*)0)) | |||
3742 | goto done; | |||
3743 | ||||
3744 | if (!sa->sa_localauth.id_type) { | |||
3745 | /* Downgrade the state */ | |||
3746 | sa_state(env, sa, IKEV2_STATE_AUTH_SUCCESS6); | |||
3747 | } | |||
3748 | ||||
3749 | if (sa->sa_hdr.sh_initiator) { | |||
3750 | id = &sa->sa_iid; | |||
3751 | certid = &sa->sa_icert; | |||
3752 | } else { | |||
3753 | id = &sa->sa_rid; | |||
3754 | certid = &sa->sa_rcert; | |||
3755 | } | |||
3756 | ||||
3757 | if (sa->sa_state != IKEV2_STATE_EAP_VALID8) { | |||
3758 | /* ID payload */ | |||
3759 | if ((pld = ikev2_add_payload(e)) == NULL((void*)0)) | |||
3760 | goto done; | |||
3761 | firstpayload = IKEV2_PAYLOAD_IDr36; | |||
3762 | if (ibuf_cat(e, id->id_buf) != 0) | |||
3763 | goto done; | |||
3764 | len = ibuf_size(id->id_buf); | |||
3765 | ||||
3766 | /* CERT payload */ | |||
3767 | if ((sa->sa_statevalid & IKED_REQ_CERT0x0001) && | |||
3768 | (certid->id_type != IKEV2_CERT_NONE0)) { | |||
3769 | if (ikev2_next_payload(pld, len, | |||
3770 | IKEV2_PAYLOAD_CERT37) == -1) | |||
3771 | goto done; | |||
3772 | ||||
3773 | if ((pld = ikev2_add_payload(e)) == NULL((void*)0)) | |||
3774 | goto done; | |||
3775 | if ((cert = ibuf_advance(e, sizeof(*cert))) == NULL((void*)0)) | |||
3776 | goto done; | |||
3777 | cert->cert_type = certid->id_type; | |||
3778 | if (ibuf_cat(e, certid->id_buf) != 0) | |||
3779 | goto done; | |||
3780 | len = ibuf_size(certid->id_buf) + sizeof(*cert); | |||
3781 | } | |||
3782 | ||||
3783 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_AUTH39) == -1) | |||
3784 | goto done; | |||
3785 | } else | |||
3786 | firstpayload = IKEV2_PAYLOAD_AUTH39; | |||
3787 | ||||
3788 | /* AUTH payload */ | |||
3789 | if ((pld = ikev2_add_payload(e)) == NULL((void*)0)) | |||
3790 | goto done; | |||
3791 | if ((auth = ibuf_advance(e, sizeof(*auth))) == NULL((void*)0)) | |||
3792 | goto done; | |||
3793 | auth->auth_method = sa->sa_localauth.id_type; | |||
3794 | if (ibuf_cat(e, sa->sa_localauth.id_buf) != 0) | |||
3795 | goto done; | |||
3796 | len = ibuf_size(sa->sa_localauth.id_buf) + sizeof(*auth); | |||
3797 | ||||
3798 | /* CP payload */ | |||
3799 | if (sa->sa_cp) { | |||
3800 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_CP47) == -1) | |||
3801 | goto done; | |||
3802 | if ((pld = ikev2_add_payload(e)) == NULL((void*)0)) | |||
3803 | goto done; | |||
3804 | if ((len = ikev2_resp_add_cp(env, sa, e)) == -1) | |||
3805 | goto done; | |||
3806 | } | |||
3807 | ||||
3808 | if (sa->sa_ipcompr.ic_transform && | |||
3809 | (len = ikev2_add_ipcompnotify(env, e, &pld, len, sa, 0)) == -1) | |||
3810 | goto done; | |||
3811 | if (sa->sa_used_transport_mode && | |||
3812 | (len = ikev2_add_transport_mode(env, e, &pld, len, sa)) == -1) | |||
3813 | goto done; | |||
3814 | ||||
3815 | /* MOBIKE */ | |||
3816 | if (sa->sa_mobike && | |||
3817 | (len = ikev2_add_mobike(e, &pld, len)) == -1) | |||
3818 | goto done; | |||
3819 | ||||
3820 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_SA33) == -1) | |||
3821 | goto done; | |||
3822 | ||||
3823 | /* SA payload */ | |||
3824 | if ((pld = ikev2_add_payload(e)) == NULL((void*)0)) | |||
3825 | goto done; | |||
3826 | if ((len = ikev2_add_proposals(env, sa, e, &sa->sa_proposals, 0, | |||
3827 | sa->sa_hdr.sh_initiator, 0, 1)) == -1) | |||
3828 | goto done; | |||
3829 | ||||
3830 | if ((len = ikev2_add_ts(e, &pld, len, sa, 0)) == -1) | |||
3831 | goto done; | |||
3832 | ||||
3833 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONE0) == -1) | |||
3834 | goto done; | |||
3835 | ||||
3836 | ret = ikev2_msg_send_encrypt(env, sa, &e, | |||
3837 | IKEV2_EXCHANGE_IKE_AUTH35, firstpayload, 1); | |||
3838 | if (ret == 0) | |||
3839 | ret = ikev2_childsa_enable(env, sa); | |||
3840 | if (ret == 0) { | |||
3841 | sa_state(env, sa, IKEV2_STATE_ESTABLISHED9); | |||
3842 | /* Delete exchange timeout. */ | |||
3843 | timer_del(env, &sa->sa_timer); | |||
3844 | ikev2_enable_timer(env, sa); | |||
3845 | ikev2_log_established(sa); | |||
3846 | ikev2_record_dstid(env, sa); | |||
3847 | } | |||
3848 | ||||
3849 | done: | |||
3850 | if (ret) | |||
3851 | ikev2_childsa_delete(env, sa, 0, 0, NULL((void*)0), 1); | |||
3852 | ibuf_release(e); | |||
3853 | return (ret); | |||
3854 | } | |||
3855 | ||||
3856 | int | |||
3857 | ikev2_send_ike_e(struct iked *env, struct iked_sa *sa, struct ibuf *buf, | |||
3858 | uint8_t firstpayload, uint8_t exchange, int response) | |||
3859 | { | |||
3860 | struct ikev2_payload *pld; | |||
3861 | struct ibuf *e = NULL((void*)0); | |||
3862 | int ret = -1; | |||
3863 | ||||
3864 | /* New encrypted message buffer */ | |||
3865 | if ((e = ibuf_static()) == NULL((void*)0)) | |||
3866 | goto done; | |||
3867 | ||||
3868 | if ((pld = ikev2_add_payload(e)) == NULL((void*)0)) | |||
3869 | goto done; | |||
3870 | ||||
3871 | if (buf) { | |||
3872 | if (ibuf_cat(e, buf) != 0) | |||
3873 | goto done; | |||
3874 | ||||
3875 | if (ikev2_next_payload(pld, ibuf_size(buf), | |||
3876 | IKEV2_PAYLOAD_NONE0) == -1) | |||
3877 | goto done; | |||
3878 | } | |||
3879 | ||||
3880 | ret = ikev2_msg_send_encrypt(env, sa, &e, exchange, firstpayload, | |||
3881 | response); | |||
3882 | ||||
3883 | done: | |||
3884 | ibuf_release(e); | |||
3885 | ||||
3886 | return (ret); | |||
3887 | } | |||
3888 | ||||
3889 | int | |||
3890 | ikev2_set_sa_proposal(struct iked_sa *sa, struct iked_policy *pol, | |||
3891 | unsigned int proto) | |||
3892 | { | |||
3893 | struct iked_proposal *prop, *copy; | |||
3894 | struct iked_transform *xform; | |||
3895 | unsigned int i; | |||
3896 | ||||
3897 | /* create copy of the policy proposals */ | |||
3898 | config_free_proposals(&sa->sa_proposals, proto); | |||
3899 | TAILQ_FOREACH(prop, &pol->pol_proposals, prop_entry)for((prop) = ((&pol->pol_proposals)->tqh_first); (prop ) != ((void*)0); (prop) = ((prop)->prop_entry.tqe_next)) { | |||
3900 | if (proto != 0 && prop->prop_protoid != proto) | |||
3901 | continue; | |||
3902 | if ((copy = config_add_proposal(&sa->sa_proposals, | |||
3903 | prop->prop_id, prop->prop_protoid)) == NULL((void*)0)) | |||
3904 | return (-1); | |||
3905 | for (i = 0; i < prop->prop_nxforms; i++) { | |||
3906 | xform = &prop->prop_xforms[i]; | |||
3907 | if (config_add_transform(copy, xform->xform_type, | |||
3908 | xform->xform_id, xform->xform_length, | |||
3909 | xform->xform_keylength) != 0) | |||
3910 | return (-1); | |||
3911 | } | |||
3912 | } | |||
3913 | return (0); | |||
3914 | } | |||
3915 | ||||
3916 | int | |||
3917 | ikev2_send_create_child_sa(struct iked *env, struct iked_sa *sa, | |||
3918 | struct iked_spi *rekey, uint8_t protoid, uint16_t proposed_group) | |||
3919 | { | |||
3920 | struct iked_policy *pol = sa->sa_policy; | |||
3921 | struct iked_childsa *csa = NULL((void*)0), *csb = NULL((void*)0); | |||
3922 | struct iked_transform *xform; | |||
3923 | struct ikev2_notify *n; | |||
3924 | struct ikev2_payload *pld = NULL((void*)0); | |||
3925 | struct ikev2_keyexchange *ke; | |||
3926 | struct dh_group *group; | |||
3927 | struct ibuf *e = NULL((void*)0), *nonce = NULL((void*)0); | |||
3928 | uint8_t *ptr; | |||
3929 | uint8_t firstpayload; | |||
3930 | uint32_t spi; | |||
3931 | ssize_t len = 0; | |||
3932 | int initiator, ret = -1; | |||
3933 | ||||
3934 | if (rekey) | |||
3935 | log_debug("%s: rekeying %s spi %s", __func__, | |||
3936 | print_map(rekey->spi_protoid, ikev2_saproto_map), | |||
3937 | print_spi(rekey->spi, rekey->spi_size)); | |||
3938 | else | |||
3939 | log_debug("%s: creating new CHILD SAs", __func__); | |||
3940 | ||||
3941 | /* XXX cannot initiate multiple concurrent CREATE_CHILD_SA exchanges */ | |||
3942 | if (sa->sa_stateflags & (IKED_REQ_CHILDSA0x0080|IKED_REQ_INF0x0100)) { | |||
3943 | log_debug("%s: another exchange already active", | |||
3944 | __func__); | |||
3945 | return (-1); | |||
3946 | } | |||
3947 | ||||
3948 | ibuf_release(sa->sa_simult); | |||
3949 | sa->sa_simult = NULL((void*)0); | |||
3950 | sa->sa_rekeyspi = 0; /* clear rekey spi */ | |||
3951 | initiator = sa->sa_hdr.sh_initiator ? 1 : 0; | |||
3952 | ||||
3953 | if (rekey && | |||
3954 | ((csa = childsa_lookup(sa, rekey->spi, | |||
3955 | rekey->spi_protoid)) == NULL((void*)0) || | |||
3956 | (csb = csa->csa_peersa) == NULL((void*)0))) { | |||
3957 | log_debug("%s: CHILD SA %s wasn't found", __func__, | |||
3958 | print_spi(rekey->spi, rekey->spi_size)); | |||
3959 | goto done; | |||
3960 | } | |||
3961 | ||||
3962 | /* Generate new nonce */ | |||
3963 | if ((nonce = ibuf_random(IKED_NONCE_SIZE32)) == NULL((void*)0)) | |||
3964 | goto done; | |||
3965 | ||||
3966 | /* Update initiator nonce */ | |||
3967 | ibuf_release(sa->sa_inoncesa_kex.kex_inonce); | |||
3968 | sa->sa_inoncesa_kex.kex_inonce = nonce; | |||
3969 | ||||
3970 | if ((e = ibuf_static()) == NULL((void*)0)) | |||
3971 | goto done; | |||
3972 | ||||
3973 | if ((pol->pol_flags & IKED_POLICY_IPCOMP0x20) && | |||
3974 | (len = ikev2_add_ipcompnotify(env, e, &pld, 0, sa, 1)) == -1) | |||
3975 | goto done; | |||
3976 | if ((pol->pol_flags & IKED_POLICY_TRANSPORT0x40) && | |||
3977 | (len = ikev2_add_transport_mode(env, e, &pld, len, sa)) == -1) | |||
3978 | goto done; | |||
3979 | ||||
3980 | if (pld) { | |||
3981 | firstpayload = IKEV2_PAYLOAD_NOTIFY41; | |||
3982 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_SA33) == -1) | |||
3983 | goto done; | |||
3984 | } else | |||
3985 | firstpayload = IKEV2_PAYLOAD_SA33; | |||
3986 | ||||
3987 | /* SA payload */ | |||
3988 | if ((pld = ikev2_add_payload(e)) == NULL((void*)0)) | |||
3989 | goto done; | |||
3990 | ||||
3991 | /* | |||
3992 | * We need to reset the sa_proposal. Otherwise it would be | |||
3993 | * left over from the IKE_AUTH exchange and would not contain | |||
3994 | * any DH groups (e.g. for ESP child SAs). | |||
3995 | */ | |||
3996 | if (ikev2_set_sa_proposal(sa, pol, protoid) < 0) { | |||
3997 | log_debug("%s: ikev2_set_sa_proposal failed", __func__); | |||
3998 | goto done; | |||
3999 | } | |||
4000 | ||||
4001 | if ((len = ikev2_add_proposals(env, sa, e, &sa->sa_proposals, | |||
4002 | protoid, 1, 0, 0)) == -1) | |||
4003 | goto done; | |||
4004 | ||||
4005 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONCE40) == -1) | |||
4006 | goto done; | |||
4007 | ||||
4008 | /* NONCE payload */ | |||
4009 | if ((pld = ikev2_add_payload(e)) == NULL((void*)0)) | |||
4010 | goto done; | |||
4011 | if (ikev2_add_buf(e, nonce) == -1) | |||
4012 | goto done; | |||
4013 | len = ibuf_size(nonce); | |||
4014 | ||||
4015 | if ((xform = config_findtransform(&pol->pol_proposals, IKEV2_XFORMTYPE_DH4, | |||
4016 | protoid)) && group_get(xform->xform_id) != IKEV2_XFORMDH_NONE0) { | |||
4017 | log_debug("%s: enable PFS", __func__); | |||
4018 | ikev2_sa_cleanup_dh(sa); | |||
4019 | if (proposed_group) { | |||
4020 | if ((sa->sa_dhgroupsa_kex.kex_dhgroup = | |||
4021 | group_get(proposed_group)) == NULL((void*)0)) { | |||
4022 | log_debug("%s: failed to get group", __func__); | |||
4023 | goto done; | |||
4024 | } | |||
4025 | } | |||
4026 | if (ikev2_sa_initiator_dh(sa, NULL((void*)0), protoid, NULL((void*)0)) < 0) { | |||
4027 | log_debug("%s: failed to setup DH", __func__); | |||
4028 | goto done; | |||
4029 | } | |||
4030 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_KE34) == -1) | |||
4031 | goto done; | |||
4032 | ||||
4033 | /* KE payload */ | |||
4034 | if ((pld = ikev2_add_payload(e)) == NULL((void*)0)) | |||
4035 | goto done; | |||
4036 | if ((ke = ibuf_advance(e, sizeof(*ke))) == NULL((void*)0)) | |||
4037 | goto done; | |||
4038 | if ((group = sa->sa_dhgroupsa_kex.kex_dhgroup) == NULL((void*)0)) { | |||
4039 | log_debug("%s: invalid dh", __func__); | |||
4040 | goto done; | |||
4041 | } | |||
4042 | ke->kex_dhgroup = htobe16(group->id)(__uint16_t)(__builtin_constant_p(group->id) ? (__uint16_t )(((__uint16_t)(group->id) & 0xffU) << 8 | ((__uint16_t )(group->id) & 0xff00U) >> 8) : __swap16md(group ->id)); | |||
4043 | if (ikev2_add_buf(e, sa->sa_dhiexchangesa_kex.kex_dhiexchange) == -1) | |||
4044 | goto done; | |||
4045 | len = sizeof(*ke) + ibuf_length(sa->sa_dhiexchangesa_kex.kex_dhiexchange); | |||
4046 | } | |||
4047 | ||||
4048 | if ((len = ikev2_add_ts(e, &pld, len, sa, !initiator)) == -1) | |||
4049 | goto done; | |||
4050 | ||||
4051 | if (rekey) { | |||
4052 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NOTIFY41) == -1) | |||
4053 | goto done; | |||
4054 | ||||
4055 | /* REKEY_SA notification */ | |||
4056 | if ((pld = ikev2_add_payload(e)) == NULL((void*)0)) | |||
4057 | goto done; | |||
4058 | if ((n = ibuf_advance(e, sizeof(*n))) == NULL((void*)0)) | |||
4059 | goto done; | |||
4060 | n->n_type = htobe16(IKEV2_N_REKEY_SA)(__uint16_t)(__builtin_constant_p(16393) ? (__uint16_t)(((__uint16_t )(16393) & 0xffU) << 8 | ((__uint16_t)(16393) & 0xff00U) >> 8) : __swap16md(16393)); | |||
4061 | n->n_protoid = rekey->spi_protoid; | |||
4062 | n->n_spisize = rekey->spi_size; | |||
4063 | if ((ptr = ibuf_advance(e, rekey->spi_size)) == NULL((void*)0)) | |||
4064 | goto done; | |||
4065 | len = rekey->spi_size; | |||
4066 | spi = htobe32((uint32_t)csa->csa_peerspi)(__uint32_t)(__builtin_constant_p((uint32_t)csa->csa_peerspi ) ? (__uint32_t)(((__uint32_t)((uint32_t)csa->csa_peerspi) & 0xff) << 24 | ((__uint32_t)((uint32_t)csa->csa_peerspi ) & 0xff00) << 8 | ((__uint32_t)((uint32_t)csa-> csa_peerspi) & 0xff0000) >> 8 | ((__uint32_t)((uint32_t )csa->csa_peerspi) & 0xff000000) >> 24) : __swap32md ((uint32_t)csa->csa_peerspi)); | |||
4067 | memcpy(ptr, &spi, rekey->spi_size); | |||
4068 | len += sizeof(*n); | |||
4069 | } | |||
4070 | ||||
4071 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONE0) == -1) | |||
4072 | goto done; | |||
4073 | ||||
4074 | ret = ikev2_msg_send_encrypt(env, sa, &e, | |||
4075 | IKEV2_EXCHANGE_CREATE_CHILD_SA36, firstpayload, 0); | |||
4076 | if (ret == 0) { | |||
4077 | if (rekey) { | |||
4078 | csa->csa_rekey = 1; | |||
4079 | csb->csa_rekey = 1; | |||
4080 | /* | |||
4081 | * Remember the peer spi of the rekeyed | |||
4082 | * SA for ikev2_init_create_child_sa(). | |||
4083 | */ | |||
4084 | sa->sa_rekeyspi = csa->csa_peerspi; | |||
4085 | } | |||
4086 | sa->sa_stateflags |= IKED_REQ_CHILDSA0x0080; | |||
4087 | } | |||
4088 | ||||
4089 | done: | |||
4090 | ibuf_release(e); | |||
4091 | return (ret); | |||
4092 | } | |||
4093 | ||||
4094 | void | |||
4095 | ikev2_ike_sa_rekey(struct iked *env, void *arg) | |||
4096 | { | |||
4097 | struct iked_sa *sa = arg; | |||
4098 | struct iked_sa *nsa = NULL((void*)0); | |||
4099 | struct ikev2_payload *pld = NULL((void*)0); | |||
4100 | struct ikev2_keyexchange *ke; | |||
4101 | struct dh_group *group; | |||
4102 | struct ibuf *e = NULL((void*)0), *nonce = NULL((void*)0); | |||
4103 | ssize_t len = 0; | |||
4104 | int ret = -1; | |||
4105 | ||||
4106 | log_debug("%s: IKE SA %p ispi %s rspi %s", __func__, sa, | |||
4107 | print_spi(sa->sa_hdr.sh_ispi, 8), | |||
4108 | print_spi(sa->sa_hdr.sh_rspi, 8)); | |||
4109 | ||||
4110 | if (sa->sa_nexti) { | |||
4111 | log_debug("%s: already rekeying", __func__); | |||
4112 | goto done; | |||
4113 | } | |||
4114 | ||||
4115 | if (sa->sa_stateflags & (IKED_REQ_CHILDSA0x0080|IKED_REQ_INF0x0100)) { | |||
4116 | /* | |||
4117 | * We cannot initiate multiple concurrent CREATE_CHILD_SA | |||
4118 | * exchanges, so retry again fast. | |||
4119 | */ | |||
4120 | log_info("%s: busy, delaying rekey", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
4121 | ikev2_ike_sa_rekey_schedule_fast(env, sa); | |||
4122 | return; | |||
4123 | } | |||
4124 | ||||
4125 | /* We need to make sure the rekeying finishes in time */ | |||
4126 | timer_set(env, &sa->sa_rekey, ikev2_ike_sa_rekey_timeout, sa); | |||
4127 | timer_add(env, &sa->sa_rekey, IKED_IKE_SA_REKEY_TIMEOUT120); | |||
4128 | ||||
4129 | if ((nsa = sa_new(env, 0, 0, 1, sa->sa_policy)) == NULL((void*)0)) { | |||
4130 | log_debug("%s: failed to get new SA", __func__); | |||
4131 | goto done; | |||
4132 | } | |||
4133 | ||||
4134 | if (ikev2_sa_initiator(env, nsa, sa, NULL((void*)0))) { | |||
4135 | log_debug("%s: failed to setup DH", __func__); | |||
4136 | goto done; | |||
4137 | } | |||
4138 | sa_state(env, nsa, IKEV2_STATE_AUTH_SUCCESS6); | |||
4139 | nonce = nsa->sa_inoncesa_kex.kex_inonce; | |||
4140 | ||||
4141 | if ((e = ibuf_static()) == NULL((void*)0)) | |||
4142 | goto done; | |||
4143 | ||||
4144 | /* SA payload */ | |||
4145 | if ((pld = ikev2_add_payload(e)) == NULL((void*)0)) | |||
4146 | goto done; | |||
4147 | ||||
4148 | /* just reuse the old IKE SA proposals */ | |||
4149 | if ((len = ikev2_add_proposals(env, nsa, e, &sa->sa_proposals, | |||
4150 | IKEV2_SAPROTO_IKE1, 1, 1, 0)) == -1) | |||
4151 | goto done; | |||
4152 | ||||
4153 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONCE40) == -1) | |||
4154 | goto done; | |||
4155 | ||||
4156 | /* NONCE payload */ | |||
4157 | if ((pld = ikev2_add_payload(e)) == NULL((void*)0)) | |||
4158 | goto done; | |||
4159 | if (ikev2_add_buf(e, nonce) == -1) | |||
4160 | goto done; | |||
4161 | len = ibuf_size(nonce); | |||
4162 | ||||
4163 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_KE34) == -1) | |||
4164 | goto done; | |||
4165 | ||||
4166 | /* KE payload */ | |||
4167 | if ((pld = ikev2_add_payload(e)) == NULL((void*)0)) | |||
4168 | goto done; | |||
4169 | if ((ke = ibuf_advance(e, sizeof(*ke))) == NULL((void*)0)) | |||
4170 | goto done; | |||
4171 | if ((group = nsa->sa_dhgroupsa_kex.kex_dhgroup) == NULL((void*)0)) { | |||
4172 | log_debug("%s: invalid dh", __func__); | |||
4173 | goto done; | |||
4174 | } | |||
4175 | ke->kex_dhgroup = htobe16(group->id)(__uint16_t)(__builtin_constant_p(group->id) ? (__uint16_t )(((__uint16_t)(group->id) & 0xffU) << 8 | ((__uint16_t )(group->id) & 0xff00U) >> 8) : __swap16md(group ->id)); | |||
4176 | if (ikev2_add_buf(e, nsa->sa_dhiexchangesa_kex.kex_dhiexchange) == -1) | |||
4177 | goto done; | |||
4178 | len = sizeof(*ke) + ibuf_length(nsa->sa_dhiexchangesa_kex.kex_dhiexchange); | |||
4179 | ||||
4180 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONE0) == -1) | |||
4181 | goto done; | |||
4182 | ||||
4183 | ret = ikev2_msg_send_encrypt(env, sa, &e, | |||
4184 | IKEV2_EXCHANGE_CREATE_CHILD_SA36, IKEV2_PAYLOAD_SA33, 0); | |||
4185 | if (ret == 0) { | |||
4186 | sa->sa_stateflags |= IKED_REQ_CHILDSA0x0080; | |||
4187 | sa->sa_nexti = nsa; | |||
4188 | nsa->sa_previ = sa; | |||
4189 | sa->sa_tmpfail = 0; | |||
4190 | nsa = NULL((void*)0); | |||
4191 | } | |||
4192 | done: | |||
4193 | if (nsa) { | |||
4194 | ikev2_ike_sa_setreason(nsa, "failed to send CREATE_CHILD_SA"); | |||
4195 | sa_free(env, nsa); | |||
4196 | } | |||
4197 | ibuf_release(e); | |||
4198 | ||||
4199 | if (ret == 0) | |||
4200 | log_debug("%s: create child SA sent", __func__); | |||
4201 | else | |||
4202 | log_debug("%s: could not send create child SA", __func__); | |||
4203 | /* XXX should we try again in case of ret != 0 ? */ | |||
4204 | } | |||
4205 | ||||
4206 | int | |||
4207 | ikev2_nonce_cmp(struct ibuf *a, struct ibuf *b) | |||
4208 | { | |||
4209 | size_t alen, blen, len; | |||
4210 | int ret; | |||
4211 | ||||
4212 | alen = ibuf_length(a); | |||
4213 | blen = ibuf_length(b); | |||
4214 | len = MINIMUM(alen, blen)(((alen)<(blen))?(alen):(blen)); | |||
4215 | ret = memcmp(ibuf_data(a), ibuf_data(b), len); | |||
4216 | if (ret == 0) | |||
4217 | ret = (alen < blen ? -1 : 1); | |||
4218 | return (ret); | |||
4219 | } | |||
4220 | ||||
4221 | int | |||
4222 | ikev2_init_create_child_sa(struct iked *env, struct iked_message *msg) | |||
4223 | { | |||
4224 | struct iked_childsa *csa = NULL((void*)0); | |||
4225 | struct iked_proposal *prop; | |||
4226 | struct iked_sa *sa = msg->msg_sa; | |||
4227 | struct iked_sa *nsa, *dsa; | |||
4228 | struct iked_spi *spi; | |||
4229 | struct ikev2_delete *del; | |||
4230 | struct ibuf *buf = NULL((void*)0); | |||
4231 | struct ibuf *ni, *nr; | |||
4232 | uint32_t spi32; | |||
4233 | int pfs = 0, ret = -1; | |||
4234 | ||||
4235 | if (!ikev2_msg_frompeer(msg) || | |||
4236 | (sa->sa_stateflags & (IKED_REQ_CHILDSA0x0080|IKED_REQ_INF0x0100)) == 0) | |||
4237 | return (0); | |||
4238 | ||||
4239 | if (sa->sa_nexti != NULL((void*)0) && sa->sa_tmpfail) { | |||
4240 | sa->sa_stateflags &= ~IKED_REQ_CHILDSA0x0080; | |||
4241 | ikev2_ike_sa_setreason(sa->sa_nexti, "tmpfail"); | |||
4242 | sa_free(env, sa->sa_nexti); | |||
4243 | sa->sa_nexti = NULL((void*)0); | |||
4244 | timer_set(env, &sa->sa_rekey, ikev2_ike_sa_rekey, sa); | |||
4245 | ikev2_ike_sa_rekey_schedule_fast(env, sa); | |||
4246 | log_info("%s: IKESA rekey delayed", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
4247 | return (0); | |||
4248 | } | |||
4249 | ||||
4250 | if (msg->msg_prop == NULL((void*)0) || | |||
4251 | TAILQ_EMPTY(&msg->msg_proposals)(((&msg->msg_proposals)->tqh_first) == ((void*)0))) { | |||
4252 | log_info("%s: no proposal specified", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
4253 | return (-1); | |||
4254 | } | |||
4255 | ||||
4256 | if (proposals_negotiate(&sa->sa_proposals, &sa->sa_proposals, | |||
4257 | &msg->msg_proposals, 1, -1) != 0) { | |||
4258 | log_info("%s: no proposal chosen", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
4259 | return (-1); | |||
4260 | } | |||
4261 | ||||
4262 | TAILQ_FOREACH(prop, &sa->sa_proposals, prop_entry)for((prop) = ((&sa->sa_proposals)->tqh_first); (prop ) != ((void*)0); (prop) = ((prop)->prop_entry.tqe_next)) { | |||
4263 | if (prop->prop_protoid == msg->msg_prop->prop_protoid) | |||
4264 | break; | |||
4265 | } | |||
4266 | if (prop == NULL((void*)0)) { | |||
4267 | log_info("%s: failed to find %s proposals", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
4268 | print_map(msg->msg_prop->prop_protoid, ikev2_saproto_map)); | |||
4269 | return (-1); | |||
4270 | } | |||
4271 | ||||
4272 | /* IKE SA rekeying */ | |||
4273 | if (prop->prop_protoid == IKEV2_SAPROTO_IKE1) { | |||
4274 | if (sa->sa_nexti == NULL((void*)0)) { | |||
4275 | log_info("%s: missing IKE SA for rekeying", | |||
4276 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
4277 | return (-1); | |||
4278 | } | |||
4279 | /* Update the responder SPI */ | |||
4280 | /* XXX sa_new() is just a lookup, so nsa == sa->sa_nexti */ | |||
4281 | spi = &msg->msg_prop->prop_peerspi; | |||
4282 | if ((nsa = sa_new(env, sa->sa_nexti->sa_hdr.sh_ispi, | |||
4283 | spi->spi, 1, NULL((void*)0))) == NULL((void*)0) || nsa != sa->sa_nexti) { | |||
4284 | log_info("%s: invalid rekey SA", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
4285 | if (nsa) { | |||
4286 | ikev2_ike_sa_setreason(nsa, | |||
4287 | "invalid SA for rekey"); | |||
4288 | sa_free(env, nsa); | |||
4289 | } | |||
4290 | ikev2_ike_sa_setreason(sa->sa_nexti, "invalid SA nexti"); | |||
4291 | sa_free(env, sa->sa_nexti); | |||
4292 | sa->sa_nexti = NULL((void*)0); /* reset by sa_free */ | |||
4293 | return (-1); | |||
4294 | } | |||
4295 | if (ikev2_sa_initiator(env, nsa, sa, msg) == -1) { | |||
4296 | log_info("%s: failed to get IKE keys", | |||
4297 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
4298 | return (-1); | |||
4299 | } | |||
4300 | sa->sa_stateflags &= ~IKED_REQ_CHILDSA0x0080; | |||
4301 | if (sa->sa_nextr) { | |||
4302 | /* | |||
4303 | * Resolve simultaneous IKE SA rekeying by | |||
4304 | * deleting the SA with the lowest NONCE. | |||
4305 | */ | |||
4306 | log_info("%s: resolving simultaneous IKE SA rekeying", | |||
4307 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
4308 | /* ni: minimum nonce of sa_nexti */ | |||
4309 | if (ikev2_nonce_cmp(sa->sa_nexti->sa_inoncesa_kex.kex_inonce, | |||
4310 | sa->sa_nexti->sa_rnoncesa_kex.kex_rnonce) < 0) | |||
4311 | ni = sa->sa_nexti->sa_inoncesa_kex.kex_inonce; | |||
4312 | else | |||
4313 | ni = sa->sa_nexti->sa_rnoncesa_kex.kex_rnonce; | |||
4314 | /* nr: minimum nonce of sa_nextr */ | |||
4315 | if (ikev2_nonce_cmp(sa->sa_nextr->sa_inoncesa_kex.kex_inonce, | |||
4316 | sa->sa_nextr->sa_rnoncesa_kex.kex_rnonce) < 0) | |||
4317 | nr = sa->sa_nextr->sa_inoncesa_kex.kex_inonce; | |||
4318 | else | |||
4319 | nr = sa->sa_nextr->sa_rnoncesa_kex.kex_rnonce; | |||
4320 | /* delete SA with minumum nonce */ | |||
4321 | if (ikev2_nonce_cmp(ni, nr) < 0) { | |||
4322 | dsa = sa->sa_nexti; | |||
4323 | nsa = sa->sa_nextr; | |||
4324 | } else { | |||
4325 | dsa = sa->sa_nextr; | |||
4326 | nsa = sa->sa_nexti; | |||
4327 | } | |||
4328 | /* unlink sa_nextr */ | |||
4329 | sa->sa_nextr->sa_prevr = NULL((void*)0); | |||
4330 | sa->sa_nextr = NULL((void*)0); | |||
4331 | /* Setup address, socket and NAT information */ | |||
4332 | sa_address(dsa, &dsa->sa_peer, | |||
4333 | (struct sockaddr *)&sa->sa_peer.addr); | |||
4334 | sa_address(dsa, &dsa->sa_local, | |||
4335 | (struct sockaddr *)&sa->sa_local.addr); | |||
4336 | dsa->sa_fd = sa->sa_fd; | |||
4337 | dsa->sa_natt = sa->sa_natt; | |||
4338 | dsa->sa_udpencap = sa->sa_udpencap; | |||
4339 | ikev2_ike_sa_setreason(dsa, | |||
4340 | "resolving simultaneous rekeying"); | |||
4341 | ikev2_ikesa_delete(env, dsa, dsa->sa_hdr.sh_initiator); | |||
4342 | } | |||
4343 | /* unlink sa_nexti */ | |||
4344 | sa->sa_nexti->sa_previ = NULL((void*)0); | |||
4345 | sa->sa_nexti = NULL((void*)0); | |||
4346 | return (ikev2_ikesa_enable(env, sa, nsa)); | |||
4347 | } | |||
4348 | ||||
4349 | /* Child SA rekeying */ | |||
4350 | if (sa->sa_rekeyspi && | |||
4351 | (csa = childsa_lookup(sa, sa->sa_rekeyspi, prop->prop_protoid)) | |||
4352 | != NULL((void*)0)) { | |||
4353 | log_info("%s: rekeying CHILD SA old %s spi %s", | |||
4354 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
4355 | print_spi(csa->csa_spi.spi, csa->csa_spi.spi_size), | |||
4356 | print_spi(prop->prop_peerspi.spi, | |||
4357 | prop->prop_peerspi.spi_size)); | |||
4358 | } | |||
4359 | ||||
4360 | /* check KE payload for PFS */ | |||
4361 | if (ibuf_length(msg->msg_ke)) { | |||
4362 | log_debug("%s: using PFS", __func__); | |||
4363 | if (ikev2_sa_initiator_dh(sa, msg, prop->prop_protoid, NULL((void*)0)) < 0) { | |||
4364 | log_info("%s: failed to setup DH", | |||
4365 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
4366 | return (ret); | |||
4367 | } | |||
4368 | if (sa->sa_dhpeersa_kex.kex_dhpeer == NULL((void*)0)) { | |||
4369 | log_info("%s: no peer DH", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
4370 | return (ret); | |||
4371 | } | |||
4372 | pfs = 1; | |||
4373 | /* XXX check group against policy ? */ | |||
4374 | /* XXX should proposals_negotiate do this? */ | |||
4375 | } | |||
4376 | ||||
4377 | /* Update responder's nonce */ | |||
4378 | if (!ibuf_length(msg->msg_nonce)) { | |||
4379 | log_info("%s: responder didn't send nonce", | |||
4380 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
4381 | return (-1); | |||
4382 | } | |||
4383 | ibuf_release(sa->sa_rnoncesa_kex.kex_rnonce); | |||
4384 | sa->sa_rnoncesa_kex.kex_rnonce = msg->msg_nonce; | |||
4385 | msg->msg_nonce = NULL((void*)0); | |||
4386 | ||||
4387 | if (csa && (ni = sa->sa_simult) != NULL((void*)0)) { | |||
4388 | log_info("%s: resolving simultaneous CHILD SA rekeying", | |||
4389 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
4390 | /* set nr to minimum nonce for exchange initiated by peer */ | |||
4391 | if (ikev2_nonce_cmp(sa->sa_inoncesa_kex.kex_inonce, sa->sa_rnoncesa_kex.kex_rnonce) < 0) | |||
4392 | nr = sa->sa_inoncesa_kex.kex_inonce; | |||
4393 | else | |||
4394 | nr = sa->sa_rnoncesa_kex.kex_rnonce; | |||
4395 | /* | |||
4396 | * If the exchange initated by us has smaller nonce, | |||
4397 | * then we have to delete our SAs. | |||
4398 | */ | |||
4399 | if (ikev2_nonce_cmp(ni, nr) < 0) { | |||
4400 | ret = ikev2_childsa_delete_proposed(env, sa, | |||
4401 | &sa->sa_proposals); | |||
4402 | goto done; | |||
4403 | } | |||
4404 | } | |||
4405 | ||||
4406 | if (ikev2_childsa_negotiate(env, sa, &sa->sa_kex, &sa->sa_proposals, 1, | |||
4407 | pfs)) { | |||
4408 | log_info("%s: failed to get CHILD SAs", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
4409 | return (-1); | |||
4410 | } | |||
4411 | ||||
4412 | if (csa) { | |||
4413 | /* Child SA rekeying */ | |||
4414 | ||||
4415 | if ((buf = ibuf_static()) == NULL((void*)0)) | |||
4416 | goto done; | |||
4417 | ||||
4418 | if ((del = ibuf_advance(buf, sizeof(*del))) == NULL((void*)0)) | |||
4419 | goto done; | |||
4420 | ||||
4421 | del->del_protoid = prop->prop_protoid; | |||
4422 | del->del_spisize = sizeof(spi32); | |||
4423 | del->del_nspi = htobe16(1)(__uint16_t)(__builtin_constant_p(1) ? (__uint16_t)(((__uint16_t )(1) & 0xffU) << 8 | ((__uint16_t)(1) & 0xff00U ) >> 8) : __swap16md(1)); | |||
4424 | ||||
4425 | spi32 = htobe32(csa->csa_spi.spi)(__uint32_t)(__builtin_constant_p(csa->csa_spi.spi) ? (__uint32_t )(((__uint32_t)(csa->csa_spi.spi) & 0xff) << 24 | ((__uint32_t)(csa->csa_spi.spi) & 0xff00) << 8 | ((__uint32_t)(csa->csa_spi.spi) & 0xff0000) >> 8 | ((__uint32_t)(csa->csa_spi.spi) & 0xff000000) >> 24) : __swap32md(csa->csa_spi.spi)); | |||
4426 | if (ibuf_add(buf, &spi32, sizeof(spi32))) | |||
4427 | goto done; | |||
4428 | ||||
4429 | if (ikev2_send_ike_e(env, sa, buf, IKEV2_PAYLOAD_DELETE42, | |||
4430 | IKEV2_EXCHANGE_INFORMATIONAL37, 0)) | |||
4431 | goto done; | |||
4432 | ||||
4433 | sa->sa_stateflags |= IKED_REQ_INF0x0100; | |||
4434 | } | |||
4435 | ||||
4436 | ret = ikev2_childsa_enable(env, sa); | |||
4437 | ||||
4438 | done: | |||
4439 | sa->sa_stateflags &= ~IKED_REQ_CHILDSA0x0080; | |||
4440 | ||||
4441 | if (ret) | |||
4442 | ikev2_childsa_delete(env, sa, 0, 0, NULL((void*)0), 1); | |||
4443 | else if (csa) { | |||
4444 | /* delete the rekeyed SA pair */ | |||
4445 | ikev2_childsa_delete(env, sa, csa->csa_saproto, | |||
4446 | csa->csa_peerspi, NULL((void*)0), 0); | |||
4447 | } | |||
4448 | ibuf_release(buf); | |||
4449 | return (ret); | |||
4450 | } | |||
4451 | ||||
4452 | int | |||
4453 | ikev2_ikesa_enable(struct iked *env, struct iked_sa *sa, struct iked_sa *nsa) | |||
4454 | { | |||
4455 | struct iked_childsa *csa, *csatmp, *ipcomp; | |||
4456 | struct iked_flow *flow, *flowtmp; | |||
4457 | struct iked_proposal *prop, *proptmp; | |||
4458 | ||||
4459 | log_debug("%s: IKE SA %p ispi %s rspi %s replaced" | |||
4460 | " by SA %p ispi %s rspi %s ", | |||
4461 | __func__, sa, | |||
4462 | print_spi(sa->sa_hdr.sh_ispi, 8), | |||
4463 | print_spi(sa->sa_hdr.sh_rspi, 8), | |||
4464 | nsa, | |||
4465 | print_spi(nsa->sa_hdr.sh_ispi, 8), | |||
4466 | print_spi(nsa->sa_hdr.sh_rspi, 8)); | |||
4467 | ||||
4468 | /* Transfer socket and NAT information */ | |||
4469 | nsa->sa_fd = sa->sa_fd; | |||
4470 | nsa->sa_natt = sa->sa_natt; | |||
4471 | nsa->sa_udpencap = sa->sa_udpencap; | |||
4472 | nsa->sa_usekeepalive = sa->sa_usekeepalive; | |||
4473 | nsa->sa_mobike = sa->sa_mobike; | |||
4474 | nsa->sa_frag = sa->sa_frag; | |||
4475 | ||||
4476 | /* Transfer old addresses */ | |||
4477 | memcpy(&nsa->sa_local, &sa->sa_local, sizeof(nsa->sa_local)); | |||
4478 | memcpy(&nsa->sa_peer, &sa->sa_peer, sizeof(nsa->sa_peer)); | |||
4479 | memcpy(&nsa->sa_peer_loaded, &sa->sa_peer_loaded, | |||
4480 | sizeof(nsa->sa_peer_loaded)); | |||
4481 | ||||
4482 | /* Transfer all Child SAs and flows from the old IKE SA */ | |||
4483 | TAILQ_FOREACH_SAFE(flow, &sa->sa_flows, flow_entry, flowtmp)for ((flow) = ((&sa->sa_flows)->tqh_first); (flow) != ((void*)0) && ((flowtmp) = ((flow)->flow_entry.tqe_next ), 1); (flow) = (flowtmp)) { | |||
4484 | TAILQ_REMOVE(&sa->sa_flows, flow, flow_entry)do { if (((flow)->flow_entry.tqe_next) != ((void*)0)) (flow )->flow_entry.tqe_next->flow_entry.tqe_prev = (flow)-> flow_entry.tqe_prev; else (&sa->sa_flows)->tqh_last = (flow)->flow_entry.tqe_prev; *(flow)->flow_entry.tqe_prev = (flow)->flow_entry.tqe_next; ; ; } while (0); | |||
4485 | TAILQ_INSERT_TAIL(&nsa->sa_flows, flow,do { (flow)->flow_entry.tqe_next = ((void*)0); (flow)-> flow_entry.tqe_prev = (&nsa->sa_flows)->tqh_last; * (&nsa->sa_flows)->tqh_last = (flow); (&nsa-> sa_flows)->tqh_last = &(flow)->flow_entry.tqe_next; } while (0) | |||
4486 | flow_entry)do { (flow)->flow_entry.tqe_next = ((void*)0); (flow)-> flow_entry.tqe_prev = (&nsa->sa_flows)->tqh_last; * (&nsa->sa_flows)->tqh_last = (flow); (&nsa-> sa_flows)->tqh_last = &(flow)->flow_entry.tqe_next; } while (0); | |||
4487 | flow->flow_ikesa = nsa; | |||
4488 | flow->flow_local = &nsa->sa_local; | |||
4489 | flow->flow_peer = &nsa->sa_peer; | |||
4490 | } | |||
4491 | TAILQ_FOREACH_SAFE(csa, &sa->sa_childsas, csa_entry, csatmp)for ((csa) = ((&sa->sa_childsas)->tqh_first); (csa) != ((void*)0) && ((csatmp) = ((csa)->csa_entry.tqe_next ), 1); (csa) = (csatmp)) { | |||
4492 | TAILQ_REMOVE(&sa->sa_childsas, csa, csa_entry)do { if (((csa)->csa_entry.tqe_next) != ((void*)0)) (csa)-> csa_entry.tqe_next->csa_entry.tqe_prev = (csa)->csa_entry .tqe_prev; else (&sa->sa_childsas)->tqh_last = (csa )->csa_entry.tqe_prev; *(csa)->csa_entry.tqe_prev = (csa )->csa_entry.tqe_next; ; ; } while (0); | |||
4493 | TAILQ_INSERT_TAIL(&nsa->sa_childsas, csa,do { (csa)->csa_entry.tqe_next = ((void*)0); (csa)->csa_entry .tqe_prev = (&nsa->sa_childsas)->tqh_last; *(&nsa ->sa_childsas)->tqh_last = (csa); (&nsa->sa_childsas )->tqh_last = &(csa)->csa_entry.tqe_next; } while ( 0) | |||
4494 | csa_entry)do { (csa)->csa_entry.tqe_next = ((void*)0); (csa)->csa_entry .tqe_prev = (&nsa->sa_childsas)->tqh_last; *(&nsa ->sa_childsas)->tqh_last = (csa); (&nsa->sa_childsas )->tqh_last = &(csa)->csa_entry.tqe_next; } while ( 0); | |||
4495 | csa->csa_ikesa = nsa; | |||
4496 | if (csa->csa_dir == IPSP_DIRECTION_IN0x1) { | |||
4497 | csa->csa_local = &nsa->sa_peer; | |||
4498 | csa->csa_peer = &nsa->sa_local; | |||
4499 | } else { | |||
4500 | csa->csa_local = &nsa->sa_local; | |||
4501 | csa->csa_peer = &nsa->sa_peer; | |||
4502 | } | |||
4503 | if ((ipcomp = csa->csa_bundled) != NULL((void*)0)) { | |||
4504 | ipcomp->csa_ikesa = nsa; | |||
4505 | ipcomp->csa_local = csa->csa_local; | |||
4506 | ipcomp->csa_peer = csa->csa_peer; | |||
4507 | } | |||
4508 | } | |||
4509 | /* Transfer all non-IKE proposals */ | |||
4510 | TAILQ_FOREACH_SAFE(prop, &sa->sa_proposals, prop_entry, proptmp)for ((prop) = ((&sa->sa_proposals)->tqh_first); (prop ) != ((void*)0) && ((proptmp) = ((prop)->prop_entry .tqe_next), 1); (prop) = (proptmp)) { | |||
4511 | if (prop->prop_protoid == IKEV2_SAPROTO_IKE1) | |||
4512 | continue; | |||
4513 | TAILQ_REMOVE(&sa->sa_proposals, prop, prop_entry)do { if (((prop)->prop_entry.tqe_next) != ((void*)0)) (prop )->prop_entry.tqe_next->prop_entry.tqe_prev = (prop)-> prop_entry.tqe_prev; else (&sa->sa_proposals)->tqh_last = (prop)->prop_entry.tqe_prev; *(prop)->prop_entry.tqe_prev = (prop)->prop_entry.tqe_next; ; ; } while (0); | |||
4514 | TAILQ_INSERT_TAIL(&nsa->sa_proposals, prop,do { (prop)->prop_entry.tqe_next = ((void*)0); (prop)-> prop_entry.tqe_prev = (&nsa->sa_proposals)->tqh_last ; *(&nsa->sa_proposals)->tqh_last = (prop); (&nsa ->sa_proposals)->tqh_last = &(prop)->prop_entry. tqe_next; } while (0) | |||
4515 | prop_entry)do { (prop)->prop_entry.tqe_next = ((void*)0); (prop)-> prop_entry.tqe_prev = (&nsa->sa_proposals)->tqh_last ; *(&nsa->sa_proposals)->tqh_last = (prop); (&nsa ->sa_proposals)->tqh_last = &(prop)->prop_entry. tqe_next; } while (0); | |||
4516 | } | |||
4517 | ||||
4518 | /* Preserve ID information */ | |||
4519 | ibuf_release(nsa->sa_iid.id_buf); | |||
4520 | ibuf_release(nsa->sa_rid.id_buf); | |||
4521 | ibuf_release(nsa->sa_icert.id_buf); | |||
4522 | ibuf_release(nsa->sa_rcert.id_buf); | |||
4523 | if (sa->sa_hdr.sh_initiator == nsa->sa_hdr.sh_initiator) { | |||
4524 | nsa->sa_iid = sa->sa_iid; | |||
4525 | nsa->sa_rid = sa->sa_rid; | |||
4526 | nsa->sa_icert = sa->sa_icert; | |||
4527 | nsa->sa_rcert = sa->sa_rcert; | |||
4528 | } else { | |||
4529 | /* initiator and responder role swapped */ | |||
4530 | nsa->sa_iid = sa->sa_rid; | |||
4531 | nsa->sa_rid = sa->sa_iid; | |||
4532 | nsa->sa_icert = sa->sa_rcert; | |||
4533 | nsa->sa_rcert = sa->sa_icert; | |||
4534 | } | |||
4535 | /* duplicate the actual buffer */ | |||
4536 | nsa->sa_iid.id_buf = ibuf_dup(nsa->sa_iid.id_buf); | |||
4537 | nsa->sa_rid.id_buf = ibuf_dup(nsa->sa_rid.id_buf); | |||
4538 | nsa->sa_icert.id_buf = ibuf_dup(nsa->sa_icert.id_buf); | |||
4539 | nsa->sa_rcert.id_buf = ibuf_dup(nsa->sa_rcert.id_buf); | |||
4540 | ||||
4541 | /* Transfer sa_addrpool address */ | |||
4542 | if (sa->sa_addrpool) { | |||
4543 | RB_REMOVE(iked_addrpool, &env->sc_addrpool, sa)iked_addrpool_RB_REMOVE(&env->sc_addrpool, sa); | |||
4544 | nsa->sa_addrpool = sa->sa_addrpool; | |||
4545 | sa->sa_addrpool = NULL((void*)0); | |||
4546 | RB_INSERT(iked_addrpool, &env->sc_addrpool, nsa)iked_addrpool_RB_INSERT(&env->sc_addrpool, nsa); | |||
4547 | } | |||
4548 | if (sa->sa_addrpool6) { | |||
4549 | RB_REMOVE(iked_addrpool6, &env->sc_addrpool6, sa)iked_addrpool6_RB_REMOVE(&env->sc_addrpool6, sa); | |||
4550 | nsa->sa_addrpool6 = sa->sa_addrpool6; | |||
4551 | sa->sa_addrpool6 = NULL((void*)0); | |||
4552 | RB_INSERT(iked_addrpool6, &env->sc_addrpool6, nsa)iked_addrpool6_RB_INSERT(&env->sc_addrpool6, nsa); | |||
4553 | } | |||
4554 | nsa->sa_cp = sa->sa_cp; | |||
4555 | nsa->sa_cp_addr = sa->sa_cp_addr; | |||
4556 | sa->sa_cp_addr = NULL((void*)0); | |||
4557 | nsa->sa_cp_addr6 = sa->sa_cp_addr6; | |||
4558 | sa->sa_cp_addr6 = NULL((void*)0); | |||
4559 | nsa->sa_cp_dns = sa->sa_cp_dns; | |||
4560 | sa->sa_cp_dns = NULL((void*)0); | |||
4561 | /* Transfer other attributes */ | |||
4562 | if (sa->sa_dstid_entry_valid) { | |||
4563 | sa_dstid_remove(env, sa); | |||
4564 | sa_dstid_insert(env, nsa); | |||
4565 | } | |||
4566 | if (sa->sa_tag) { | |||
4567 | nsa->sa_tag = sa->sa_tag; | |||
4568 | sa->sa_tag = NULL((void*)0); | |||
4569 | } | |||
4570 | if (sa->sa_eapid) { | |||
4571 | nsa->sa_eapid = sa->sa_eapid; | |||
4572 | sa->sa_eapid = NULL((void*)0); | |||
4573 | } | |||
4574 | log_info("%srekeyed as new IKESA %s (enc %s%s%s group %s prf %s)", | |||
4575 | SPI_SA(sa, NULL)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((((void *)0)))), print_spi(nsa->sa_hdr.sh_ispi, 8), | |||
4576 | print_xf(nsa->sa_encr->encr_id, cipher_keylength(nsa->sa_encr) - | |||
4577 | nsa->sa_encr->encr_saltlength, ikeencxfs), | |||
4578 | nsa->sa_encr->encr_authid ? "" : " auth ", | |||
4579 | nsa->sa_encr->encr_authid ? "" : print_xf(nsa->sa_integr->hash_id, | |||
4580 | hash_keylength(nsa->sa_integr), authxfs), | |||
4581 | print_xf(nsa->sa_dhgroupsa_kex.kex_dhgroup->id, 0, groupxfs), | |||
4582 | print_xf(nsa->sa_prf->hash_id, hash_keylength(sa->sa_prf), prfxfs)); | |||
4583 | sa_state(env, nsa, IKEV2_STATE_ESTABLISHED9); | |||
4584 | ikev2_enable_timer(env, nsa); | |||
4585 | ||||
4586 | nsa->sa_stateflags = nsa->sa_statevalid; /* XXX */ | |||
4587 | ||||
4588 | /* unregister DPD keep alive timer & rekey first */ | |||
4589 | if (sa->sa_state == IKEV2_STATE_ESTABLISHED9) | |||
4590 | ikev2_disable_timer(env, sa); | |||
4591 | ||||
4592 | ikev2_ike_sa_setreason(sa, "SA rekeyed"); | |||
4593 | ikev2_ikesa_delete(env, sa, nsa->sa_hdr.sh_initiator); | |||
4594 | return (0); | |||
4595 | } | |||
4596 | ||||
4597 | void | |||
4598 | ikev2_ikesa_delete(struct iked *env, struct iked_sa *sa, int initiator) | |||
4599 | { | |||
4600 | struct ibuf *buf = NULL((void*)0); | |||
4601 | struct ikev2_delete *del; | |||
4602 | ||||
4603 | if (initiator) { | |||
4604 | /* XXX: Can not have simultaneous INFORMATIONAL exchanges */ | |||
4605 | if (sa->sa_stateflags & IKED_REQ_INF0x0100) | |||
4606 | goto done; | |||
4607 | /* Send PAYLOAD_DELETE */ | |||
4608 | if ((buf = ibuf_static()) == NULL((void*)0)) | |||
4609 | goto done; | |||
4610 | if ((del = ibuf_advance(buf, sizeof(*del))) == NULL((void*)0)) | |||
4611 | goto done; | |||
4612 | del->del_protoid = IKEV2_SAPROTO_IKE1; | |||
4613 | del->del_spisize = 0; | |||
4614 | del->del_nspi = 0; | |||
4615 | if (ikev2_send_ike_e(env, sa, buf, IKEV2_PAYLOAD_DELETE42, | |||
4616 | IKEV2_EXCHANGE_INFORMATIONAL37, 0) == -1) | |||
4617 | goto done; | |||
4618 | sa->sa_stateflags |= IKED_REQ_INF0x0100; | |||
4619 | log_info("%s: sent delete, closing SA", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
4620 | done: | |||
4621 | ibuf_release(buf); | |||
4622 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
4623 | } else { | |||
4624 | sa_state(env, sa, IKEV2_STATE_CLOSING10); | |||
4625 | } | |||
4626 | ||||
4627 | /* Remove IKE-SA after timeout, e.g. if we don't get a delete */ | |||
4628 | timer_set(env, &sa->sa_timer, ikev2_ike_sa_timeout, sa); | |||
4629 | timer_add(env, &sa->sa_timer, IKED_IKE_SA_DELETE_TIMEOUT120); | |||
4630 | ikev2_ike_sa_setreason(sa, "deleting SA"); | |||
4631 | } | |||
4632 | ||||
4633 | void | |||
4634 | ikev2_ikesa_recv_delete(struct iked *env, struct iked_sa *sa) | |||
4635 | { | |||
4636 | log_info("%s: received delete", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
4637 | if (sa->sa_nexti) { | |||
4638 | /* | |||
4639 | * We initiated rekeying, but since sa_nexti is still set | |||
4640 | * we have to assume that the the peer did not receive our | |||
4641 | * rekey message. So remove the initiated SA and -- if | |||
4642 | * sa_nextr is set -- keep the responder SA instead. | |||
4643 | */ | |||
4644 | if (sa->sa_nextr) { | |||
4645 | log_debug("%s: resolving simultaneous IKE SA rekeying", | |||
4646 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
4647 | ikev2_ikesa_enable(env, sa, sa->sa_nextr); | |||
4648 | /* unlink sa_nextr */ | |||
4649 | sa->sa_nextr->sa_prevr = NULL((void*)0); | |||
4650 | sa->sa_nextr = NULL((void*)0); | |||
4651 | } | |||
4652 | ikev2_ike_sa_setreason(sa->sa_nexti, | |||
4653 | "received delete (simultaneous rekeying)"); | |||
4654 | sa_free(env, sa->sa_nexti); | |||
4655 | sa->sa_nexti = NULL((void*)0); /* reset by sa_free */ | |||
4656 | } | |||
4657 | ikev2_ike_sa_setreason(sa, "received delete"); | |||
4658 | if (env->sc_stickyaddresssc_static.st_stickyaddress) { | |||
4659 | /* delay deletion if client reconnects soon */ | |||
4660 | sa_state(env, sa, IKEV2_STATE_CLOSING10); | |||
4661 | timer_del(env, &sa->sa_timer); | |||
4662 | timer_set(env, &sa->sa_timer, ikev2_ike_sa_timeout, sa); | |||
4663 | timer_add(env, &sa->sa_timer, 3 * IKED_RETRANSMIT_TIMEOUT2); | |||
4664 | } else { | |||
4665 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
4666 | } | |||
4667 | } | |||
4668 | ||||
4669 | int | |||
4670 | ikev2_resp_create_child_sa(struct iked *env, struct iked_message *msg) | |||
4671 | { | |||
4672 | struct iked_childsa *csa = NULL((void*)0); | |||
4673 | struct iked_proposal *prop; | |||
4674 | struct iked_proposals proposals; | |||
4675 | struct iked_kex *kex, *kextmp = NULL((void*)0); | |||
4676 | struct iked_sa *nsa = NULL((void*)0), *sa = msg->msg_sa; | |||
4677 | struct iked_spi *spi, *rekey = &msg->msg_rekey; | |||
4678 | struct iked_transform *xform; | |||
4679 | struct ikev2_keyexchange *ke; | |||
4680 | struct ikev2_payload *pld = NULL((void*)0); | |||
4681 | struct ibuf *e = NULL((void*)0), *nonce = NULL((void*)0); | |||
4682 | uint8_t firstpayload; | |||
4683 | ssize_t len = 0; | |||
4684 | int initiator, protoid, rekeying = 1; | |||
4685 | int ret = -1; | |||
4686 | int pfs = 0; | |||
4687 | ||||
4688 | initiator = sa->sa_hdr.sh_initiator ? 1 : 0; | |||
4689 | ||||
4690 | if (!ikev2_msg_frompeer(msg) || msg->msg_prop == NULL((void*)0)) | |||
4691 | return (0); | |||
4692 | ||||
4693 | TAILQ_INIT(&proposals)do { (&proposals)->tqh_first = ((void*)0); (&proposals )->tqh_last = &(&proposals)->tqh_first; } while (0); | |||
4694 | ||||
4695 | if ((protoid = rekey->spi_protoid) == 0) { | |||
4696 | /* | |||
4697 | * If REKEY_SA notification is not present, then it's either | |||
4698 | * IKE SA rekeying or the client wants to create additional | |||
4699 | * CHILD SAs | |||
4700 | */ | |||
4701 | if (msg->msg_prop->prop_protoid == IKEV2_SAPROTO_IKE1) { | |||
4702 | protoid = rekey->spi_protoid = IKEV2_SAPROTO_IKE1; | |||
4703 | if (sa->sa_hdr.sh_initiator) | |||
4704 | rekey->spi = sa->sa_hdr.sh_rspi; | |||
4705 | else | |||
4706 | rekey->spi = sa->sa_hdr.sh_ispi; | |||
4707 | rekey->spi_size = 8; | |||
4708 | } else { | |||
4709 | protoid = msg->msg_prop->prop_protoid; | |||
4710 | rekeying = 0; | |||
4711 | } | |||
4712 | } | |||
4713 | ||||
4714 | if (rekeying) | |||
4715 | log_debug("%s: rekey %s spi %s", __func__, | |||
4716 | print_map(rekey->spi_protoid, ikev2_saproto_map), | |||
4717 | print_spi(rekey->spi, rekey->spi_size)); | |||
4718 | else | |||
4719 | log_debug("%s: creating new %s SA", __func__, | |||
4720 | print_map(protoid, ikev2_saproto_map)); | |||
4721 | ||||
4722 | if (protoid == IKEV2_SAPROTO_IKE1) { | |||
4723 | if ((sa->sa_stateflags & IKED_REQ_CHILDSA0x0080) | |||
4724 | && !(sa->sa_nexti)) { | |||
4725 | log_debug("%s: Ignore IKE SA rekey: waiting for Child " | |||
4726 | "SA response.", __func__); | |||
4727 | /* Ignore, don't send error */ | |||
4728 | msg->msg_valid = 0; | |||
4729 | return (0); | |||
4730 | } | |||
4731 | ||||
4732 | /* IKE SA rekeying */ | |||
4733 | spi = &msg->msg_prop->prop_peerspi; | |||
4734 | ||||
4735 | if ((nsa = sa_new(env, spi->spi, 0, 0, | |||
4736 | msg->msg_policy)) == NULL((void*)0)) { | |||
4737 | log_debug("%s: failed to get new SA", __func__); | |||
4738 | return (ret); | |||
4739 | } | |||
4740 | ||||
4741 | if (ikev2_sa_responder(env, nsa, sa, msg)) { | |||
4742 | log_debug("%s: failed to get IKE SA keys", __func__); | |||
4743 | return (ret); | |||
4744 | } | |||
4745 | ||||
4746 | sa_state(env, nsa, IKEV2_STATE_AUTH_SUCCESS6); | |||
4747 | ||||
4748 | nonce = nsa->sa_rnoncesa_kex.kex_rnonce; | |||
4749 | kex = &nsa->sa_kex; | |||
4750 | } else { | |||
4751 | /* Child SA creating/rekeying */ | |||
4752 | ||||
4753 | if ((kex = kextmp = calloc(1, sizeof(*kextmp))) == NULL((void*)0)) { | |||
4754 | log_debug("%s: calloc kex", __func__); | |||
4755 | goto fail; | |||
4756 | } | |||
4757 | ||||
4758 | if (proposals_negotiate(&proposals, | |||
4759 | &sa->sa_policy->pol_proposals, &msg->msg_proposals, | |||
4760 | 1, msg->msg_dhgroup) != 0) { | |||
4761 | log_info("%s: no proposal chosen", __func__); | |||
4762 | msg->msg_error = IKEV2_N_NO_PROPOSAL_CHOSEN14; | |||
4763 | goto fail; | |||
4764 | } | |||
4765 | ||||
4766 | /* Check KE payload for PFS, ignore if DH transform is NONE */ | |||
4767 | if (((xform = config_findtransform(&proposals, | |||
4768 | IKEV2_XFORMTYPE_DH4, protoid)) != NULL((void*)0)) && | |||
4769 | xform->xform_id != IKEV2_XFORMDH_NONE0 && | |||
4770 | ibuf_length(msg->msg_ke)) { | |||
4771 | log_debug("%s: using PFS", __func__); | |||
4772 | if (ikev2_sa_responder_dh(kex, &proposals, | |||
4773 | msg, protoid) < 0) { | |||
4774 | log_debug("%s: failed to setup DH", __func__); | |||
4775 | goto fail; | |||
4776 | } | |||
4777 | pfs = 1; | |||
4778 | /* XXX check group against policy ? */ | |||
4779 | } | |||
4780 | ||||
4781 | /* Update peer SPI */ | |||
4782 | TAILQ_FOREACH(prop, &proposals, prop_entry)for((prop) = ((&proposals)->tqh_first); (prop) != ((void *)0); (prop) = ((prop)->prop_entry.tqe_next)) { | |||
4783 | if (prop->prop_protoid == protoid) | |||
4784 | break; | |||
4785 | } | |||
4786 | if (prop == NULL((void*)0)) { | |||
4787 | log_debug("%s: failed to find %s proposals", __func__, | |||
4788 | print_map(protoid, ikev2_saproto_map)); | |||
4789 | goto fail; | |||
4790 | } else | |||
4791 | prop->prop_peerspi = msg->msg_prop->prop_peerspi; | |||
4792 | ||||
4793 | /* Set rekeying flags on Child SAs */ | |||
4794 | if (rekeying) { | |||
4795 | if ((csa = childsa_lookup(sa, rekey->spi, | |||
4796 | rekey->spi_protoid)) == NULL((void*)0)) { | |||
4797 | log_info("%s: CHILD SA %s wasn't found", | |||
4798 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
4799 | print_spi(rekey->spi, rekey->spi_size)); | |||
4800 | msg->msg_error = IKEV2_N_CHILD_SA_NOT_FOUND44; | |||
4801 | goto fail; | |||
4802 | } | |||
4803 | if (!csa->csa_loaded || !csa->csa_peersa || | |||
4804 | !csa->csa_peersa->csa_loaded) { | |||
4805 | log_info("%s: CHILD SA %s is not loaded" | |||
4806 | " or no peer SA", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
4807 | print_spi(rekey->spi, rekey->spi_size)); | |||
4808 | msg->msg_error = IKEV2_N_CHILD_SA_NOT_FOUND44; | |||
4809 | goto fail; | |||
4810 | } | |||
4811 | csa->csa_rekey = 1; | |||
4812 | csa->csa_peersa->csa_rekey = 1; | |||
4813 | } | |||
4814 | ||||
4815 | /* Update initiator's nonce */ | |||
4816 | if (!ibuf_length(msg->msg_nonce)) { | |||
4817 | log_debug("%s: initiator didn't send nonce", __func__); | |||
4818 | goto fail; | |||
4819 | } | |||
4820 | ibuf_release(kex->kex_inonce); | |||
4821 | kex->kex_inonce = msg->msg_nonce; | |||
4822 | msg->msg_nonce = NULL((void*)0); | |||
4823 | ||||
4824 | /* Generate new responder's nonce */ | |||
4825 | if ((nonce = ibuf_random(IKED_NONCE_SIZE32)) == NULL((void*)0)) | |||
4826 | goto fail; | |||
4827 | ||||
4828 | /* Update responder's nonce */ | |||
4829 | ibuf_release(kex->kex_rnonce); | |||
4830 | kex->kex_rnonce = nonce; | |||
4831 | ||||
4832 | if (ikev2_childsa_negotiate(env, sa, kex, &proposals, 0, pfs)) { | |||
4833 | log_debug("%s: failed to get CHILD SAs", __func__); | |||
4834 | goto fail; | |||
4835 | } | |||
4836 | ||||
4837 | if (rekeying && (sa->sa_stateflags & IKED_REQ_CHILDSA0x0080) && | |||
4838 | csa && (sa->sa_rekeyspi == csa->csa_peerspi)) { | |||
4839 | log_info("%s: simultaneous rekeying for CHILD SA %s/%s", | |||
4840 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
4841 | print_spi(rekey->spi, rekey->spi_size), | |||
4842 | print_spi(sa->sa_rekeyspi, rekey->spi_size)); | |||
4843 | ibuf_release(sa->sa_simult); | |||
4844 | if (ikev2_nonce_cmp(kex->kex_inonce, nonce) < 0) | |||
4845 | sa->sa_simult = ibuf_dup(kex->kex_inonce); | |||
4846 | else | |||
4847 | sa->sa_simult = ibuf_dup(nonce); | |||
4848 | } | |||
4849 | } | |||
4850 | ||||
4851 | if ((e = ibuf_static()) == NULL((void*)0)) | |||
4852 | goto done; | |||
4853 | ||||
4854 | if (!nsa && sa->sa_ipcompr.ic_transform && | |||
4855 | (len = ikev2_add_ipcompnotify(env, e, &pld, 0, sa, 0)) == -1) | |||
4856 | goto done; | |||
4857 | if (!nsa && sa->sa_used_transport_mode && | |||
4858 | (len = ikev2_add_transport_mode(env, e, &pld, len, sa)) == -1) | |||
4859 | goto done; | |||
4860 | ||||
4861 | if (pld) { | |||
4862 | firstpayload = IKEV2_PAYLOAD_NOTIFY41; | |||
4863 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_SA33) == -1) | |||
4864 | goto done; | |||
4865 | } else | |||
4866 | firstpayload = IKEV2_PAYLOAD_SA33; | |||
4867 | ||||
4868 | /* SA payload */ | |||
4869 | if ((pld = ikev2_add_payload(e)) == NULL((void*)0)) | |||
4870 | goto done; | |||
4871 | ||||
4872 | if ((len = ikev2_add_proposals(env, nsa ? nsa : sa, e, | |||
4873 | nsa ? &nsa->sa_proposals : &proposals, | |||
4874 | protoid, 0, nsa ? 1 : 0, 0)) == -1) | |||
4875 | goto done; | |||
4876 | ||||
4877 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONCE40) == -1) | |||
4878 | goto done; | |||
4879 | ||||
4880 | /* NONCE payload */ | |||
4881 | if ((pld = ikev2_add_payload(e)) == NULL((void*)0)) | |||
4882 | goto done; | |||
4883 | if (ikev2_add_buf(e, nonce) == -1) | |||
4884 | goto done; | |||
4885 | len = ibuf_size(nonce); | |||
4886 | ||||
4887 | if (protoid == IKEV2_SAPROTO_IKE1 || pfs) { | |||
4888 | ||||
4889 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_KE34) == -1) | |||
4890 | goto done; | |||
4891 | ||||
4892 | /* KE payload */ | |||
4893 | if ((pld = ikev2_add_payload(e)) == NULL((void*)0)) | |||
4894 | goto done; | |||
4895 | if ((ke = ibuf_advance(e, sizeof(*ke))) == NULL((void*)0)) | |||
4896 | goto done; | |||
4897 | if (kex->kex_dhgroup == NULL((void*)0)) { | |||
4898 | log_debug("%s: invalid dh", __func__); | |||
4899 | goto done; | |||
4900 | } | |||
4901 | ke->kex_dhgroup = htobe16(kex->kex_dhgroup->id)(__uint16_t)(__builtin_constant_p(kex->kex_dhgroup->id) ? (__uint16_t)(((__uint16_t)(kex->kex_dhgroup->id) & 0xffU) << 8 | ((__uint16_t)(kex->kex_dhgroup->id ) & 0xff00U) >> 8) : __swap16md(kex->kex_dhgroup ->id)); | |||
4902 | if (ikev2_add_buf(e, kex->kex_dhrexchange) == -1) | |||
4903 | goto done; | |||
4904 | len = sizeof(*ke) + ibuf_length(kex->kex_dhrexchange); | |||
4905 | } | |||
4906 | ||||
4907 | if (protoid != IKEV2_SAPROTO_IKE1) | |||
4908 | if ((len = ikev2_add_ts(e, &pld, len, sa, initiator)) == -1) | |||
4909 | goto done; | |||
4910 | ||||
4911 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONE0) == -1) | |||
4912 | goto done; | |||
4913 | ||||
4914 | if ((ret = ikev2_msg_send_encrypt(env, sa, &e, | |||
4915 | IKEV2_EXCHANGE_CREATE_CHILD_SA36, firstpayload, 1)) == -1) | |||
4916 | goto done; | |||
4917 | ||||
4918 | if (protoid == IKEV2_SAPROTO_IKE1) { | |||
4919 | /* | |||
4920 | * If we also have initiated rekeying for this IKE SA, then | |||
4921 | * sa_nexti is already set. In this case don't enable the new SA | |||
4922 | * immediately, but record it in sa_nextr, until the exchange | |||
4923 | * for sa_nexti completes in ikev2_init_create_child_sa() and | |||
4924 | * the 'winner' can be selected by comparing nonces. | |||
4925 | */ | |||
4926 | if (sa->sa_nexti) { | |||
4927 | log_info("%s: simultaneous IKE SA rekeying", | |||
4928 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
4929 | sa->sa_nextr = nsa; | |||
4930 | nsa->sa_prevr = sa; /* backpointer */ | |||
4931 | ret = 0; | |||
4932 | } else | |||
4933 | ret = ikev2_ikesa_enable(env, sa, nsa); | |||
4934 | } else | |||
4935 | ret = ikev2_childsa_enable(env, sa); | |||
4936 | ||||
4937 | done: | |||
4938 | if (ret && protoid != IKEV2_SAPROTO_IKE1) | |||
4939 | ikev2_childsa_delete(env, sa, 0, 0, NULL((void*)0), 1); | |||
4940 | ibuf_release(e); | |||
4941 | config_free_proposals(&proposals, 0); | |||
4942 | config_free_kex(kextmp); | |||
4943 | return (ret); | |||
4944 | ||||
4945 | fail: | |||
4946 | config_free_proposals(&proposals, 0); | |||
4947 | config_free_kex(kextmp); | |||
4948 | return (-1); | |||
4949 | } | |||
4950 | ||||
4951 | void | |||
4952 | ikev2_ike_sa_setreason(struct iked_sa *sa, char *reason) | |||
4953 | { | |||
4954 | /* allow update only if reason is reset to NULL */ | |||
4955 | if (reason == NULL((void*)0) || sa->sa_reason == NULL((void*)0)) | |||
4956 | sa->sa_reason = reason; | |||
4957 | } | |||
4958 | ||||
4959 | void | |||
4960 | ikev2_ike_sa_timeout(struct iked *env, void *arg) | |||
4961 | { | |||
4962 | struct iked_sa *sa = arg; | |||
4963 | ||||
4964 | log_debug("%s: closing SA", __func__); | |||
4965 | ikev2_ike_sa_setreason(sa, "timeout"); | |||
4966 | sa_free(env, sa); | |||
4967 | } | |||
4968 | ||||
4969 | void | |||
4970 | ikev2_ike_sa_rekey_timeout(struct iked *env, void *arg) | |||
4971 | { | |||
4972 | struct iked_sa *sa = arg; | |||
4973 | ||||
4974 | log_debug("%s: closing SA", __func__); | |||
4975 | ikev2_ike_sa_setreason(sa, "rekey timeout"); | |||
4976 | sa_free(env, sa); | |||
4977 | } | |||
4978 | ||||
4979 | void | |||
4980 | ikev2_ike_sa_rekey_schedule(struct iked *env, struct iked_sa *sa) | |||
4981 | { | |||
4982 | timer_add(env, &sa->sa_rekey, (sa->sa_policy->pol_rekey * 850 + | |||
4983 | arc4random_uniform(100)) / 1000); | |||
4984 | } | |||
4985 | ||||
4986 | /* rekey delayed, so re-try after short delay (1% of configured) */ | |||
4987 | void | |||
4988 | ikev2_ike_sa_rekey_schedule_fast(struct iked *env, struct iked_sa *sa) | |||
4989 | { | |||
4990 | int timeout = sa->sa_policy->pol_rekey / 100; /* 1% */ | |||
4991 | ||||
4992 | if (timeout > 60) | |||
4993 | timeout = 60; /* max */ | |||
4994 | else if (timeout < 4) | |||
4995 | timeout = 4; /* min */ | |||
4996 | timer_add(env, &sa->sa_rekey, timeout); | |||
4997 | } | |||
4998 | ||||
4999 | void | |||
5000 | ikev2_ike_sa_alive(struct iked *env, void *arg) | |||
5001 | { | |||
5002 | struct iked_sa *sa = arg; | |||
5003 | struct iked_childsa *csa = NULL((void*)0); | |||
5004 | uint64_t last_used, diff; | |||
5005 | int foundin = 0, foundout = 0; | |||
5006 | int ikeidle = 0; | |||
5007 | ||||
5008 | if (env->sc_alive_timeoutsc_static.st_alive_timeout == 0) | |||
5009 | return; | |||
5010 | ||||
5011 | /* check for incoming traffic on any child SA */ | |||
5012 | TAILQ_FOREACH(csa, &sa->sa_childsas, csa_entry)for((csa) = ((&sa->sa_childsas)->tqh_first); (csa) != ((void*)0); (csa) = ((csa)->csa_entry.tqe_next)) { | |||
5013 | if (!csa->csa_loaded) | |||
5014 | continue; | |||
5015 | if (pfkey_sa_last_used(env, csa, &last_used) != 0) | |||
5016 | continue; | |||
5017 | diff = (uint32_t)(gettime() - last_used); | |||
5018 | log_debug("%s: %s CHILD SA spi %s last used %llu second(s) ago", | |||
5019 | __func__, | |||
5020 | csa->csa_dir == IPSP_DIRECTION_IN0x1 ? "incoming" : "outgoing", | |||
5021 | print_spi(csa->csa_spi.spi, csa->csa_spi.spi_size), diff); | |||
5022 | if (diff < env->sc_alive_timeoutsc_static.st_alive_timeout) { | |||
5023 | if (csa->csa_dir == IPSP_DIRECTION_IN0x1) { | |||
5024 | foundin = 1; | |||
5025 | break; | |||
5026 | } else { | |||
5027 | foundout = 1; | |||
5028 | } | |||
5029 | } | |||
5030 | } | |||
5031 | ||||
5032 | diff = (uint32_t)(gettime() - sa->sa_last_recvd); | |||
5033 | if (diff >= IKED_IKE_SA_LAST_RECVD_TIMEOUT300) { | |||
5034 | ikeidle = 1; | |||
5035 | log_debug("%s: IKE SA %p ispi %s rspi %s last received %llu" | |||
5036 | " second(s) ago", __func__, sa, | |||
5037 | print_spi(sa->sa_hdr.sh_ispi, 8), | |||
5038 | print_spi(sa->sa_hdr.sh_rspi, 8), diff); | |||
5039 | } | |||
5040 | ||||
5041 | /* | |||
5042 | * send probe if any outgoing SA has been used, but no incoming | |||
5043 | * SA, or if we haven't received an IKE message. but only if we | |||
5044 | * are not already waiting for an answer. | |||
5045 | */ | |||
5046 | if (((!foundin && foundout) || ikeidle) && | |||
5047 | (sa->sa_stateflags & (IKED_REQ_CHILDSA0x0080|IKED_REQ_INF0x0100)) == 0) { | |||
5048 | log_debug("%s: sending alive check", __func__); | |||
5049 | ikev2_send_ike_e(env, sa, NULL((void*)0), IKEV2_PAYLOAD_NONE0, | |||
5050 | IKEV2_EXCHANGE_INFORMATIONAL37, 0); | |||
5051 | sa->sa_stateflags |= IKED_REQ_INF0x0100; | |||
5052 | } | |||
5053 | ||||
5054 | /* re-register */ | |||
5055 | timer_add(env, &sa->sa_timer, env->sc_alive_timeoutsc_static.st_alive_timeout); | |||
5056 | } | |||
5057 | ||||
5058 | void | |||
5059 | ikev2_ike_sa_keepalive(struct iked *env, void *arg) | |||
5060 | { | |||
5061 | struct iked_sa *sa = arg; | |||
5062 | uint8_t marker = 0xff; | |||
5063 | ||||
5064 | if (sendtofrom(sa->sa_fd, &marker, sizeof(marker), 0, | |||
5065 | (struct sockaddr *)&sa->sa_peer.addr, sa->sa_peer.addr.ss_len, | |||
5066 | (struct sockaddr *)&sa->sa_local.addr, sa->sa_local.addr.ss_len) | |||
5067 | == -1) | |||
5068 | log_warn("%s: sendtofrom: peer %s local %s", __func__, | |||
5069 | print_host((struct sockaddr *)&sa->sa_peer.addr, NULL((void*)0), 0), | |||
5070 | print_host((struct sockaddr *)&sa->sa_local.addr, NULL((void*)0), 0)); | |||
5071 | else | |||
5072 | log_debug("%s: peer %s local %s", __func__, | |||
5073 | print_host((struct sockaddr *)&sa->sa_peer.addr, NULL((void*)0), 0), | |||
5074 | print_host((struct sockaddr *)&sa->sa_local.addr, NULL((void*)0), 0)); | |||
5075 | timer_add(env, &sa->sa_keepalive, IKED_IKE_SA_KEEPALIVE_TIMEOUT20); | |||
5076 | } | |||
5077 | ||||
5078 | int | |||
5079 | ikev2_send_informational(struct iked *env, struct iked_message *msg) | |||
5080 | { | |||
5081 | struct iked_message resp; | |||
5082 | struct ike_header *hdr; | |||
5083 | struct ikev2_payload *pld; | |||
5084 | struct ikev2_notify *n; | |||
5085 | struct iked_sa *sa = msg->msg_sa, sah; | |||
5086 | struct ibuf *buf, *e = NULL((void*)0); | |||
5087 | int ret = -1; | |||
5088 | ||||
5089 | if (msg->msg_error == 0) | |||
5090 | return (0); | |||
5091 | ||||
5092 | if ((buf = ikev2_msg_init(env, &resp, | |||
5093 | &msg->msg_peer, msg->msg_peerlen, | |||
5094 | &msg->msg_local, msg->msg_locallen, 0)) == NULL((void*)0)) | |||
5095 | goto done; | |||
5096 | ||||
5097 | /* New encrypted message buffer */ | |||
5098 | if ((e = ibuf_static()) == NULL((void*)0)) | |||
5099 | goto done; | |||
5100 | ||||
5101 | /* NOTIFY payload */ | |||
5102 | if ((pld = ikev2_add_payload(e)) == NULL((void*)0)) | |||
5103 | goto done; | |||
5104 | ||||
5105 | if ((n = ibuf_advance(e, sizeof(*n))) == NULL((void*)0)) | |||
5106 | goto done; | |||
5107 | n->n_protoid = IKEV2_SAPROTO_IKE1; /* XXX ESP etc. */ | |||
5108 | n->n_spisize = 0; | |||
5109 | n->n_type = htobe16(msg->msg_error)(__uint16_t)(__builtin_constant_p(msg->msg_error) ? (__uint16_t )(((__uint16_t)(msg->msg_error) & 0xffU) << 8 | ( (__uint16_t)(msg->msg_error) & 0xff00U) >> 8) : __swap16md (msg->msg_error)); | |||
5110 | ||||
5111 | switch (msg->msg_error) { | |||
5112 | case IKEV2_N_INVALID_IKE_SPI4: | |||
5113 | break; | |||
5114 | case IKEV2_N_NO_PROPOSAL_CHOSEN14: | |||
5115 | ikev2_log_proposal(msg->msg_sa, &msg->msg_proposals); | |||
5116 | break; | |||
5117 | default: | |||
5118 | log_warnx("%s: unsupported notification %s", SPI_SA(sa,ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))) | |||
5119 | __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), print_map(msg->msg_error, ikev2_n_map)); | |||
5120 | goto done; | |||
5121 | } | |||
5122 | log_info("%s: %s", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
5123 | print_map(msg->msg_error, ikev2_n_map)); | |||
5124 | ||||
5125 | if (ikev2_next_payload(pld, sizeof(*n), IKEV2_PAYLOAD_NONE0) == -1) | |||
5126 | goto done; | |||
5127 | ||||
5128 | if (sa != NULL((void*)0) && msg->msg_e) { | |||
5129 | resp.msg_msgid = ikev2_msg_id(env, sa); | |||
5130 | ||||
5131 | /* IKE header */ | |||
5132 | if ((hdr = ikev2_add_header(buf, sa, resp.msg_msgid, | |||
5133 | IKEV2_PAYLOAD_SK46, IKEV2_EXCHANGE_INFORMATIONAL37, | |||
5134 | 0)) == NULL((void*)0)) | |||
5135 | goto done; | |||
5136 | ||||
5137 | if ((pld = ikev2_add_payload(buf)) == NULL((void*)0)) | |||
5138 | goto done; | |||
5139 | ||||
5140 | /* Encrypt message and add as an E payload */ | |||
5141 | if ((e = ikev2_msg_encrypt(env, sa, e, buf)) == NULL((void*)0)) { | |||
5142 | log_debug("%s: encryption failed", __func__); | |||
5143 | goto done; | |||
5144 | } | |||
5145 | if (ibuf_cat(buf, e) != 0) | |||
5146 | goto done; | |||
5147 | if (ikev2_next_payload(pld, ibuf_size(e), | |||
5148 | IKEV2_PAYLOAD_NOTIFY41) == -1) | |||
5149 | goto done; | |||
5150 | ||||
5151 | if (ikev2_set_header(hdr, ibuf_size(buf) - sizeof(*hdr)) == -1) | |||
5152 | goto done; | |||
5153 | ||||
5154 | /* Add integrity checksum (HMAC) */ | |||
5155 | if (ikev2_msg_integr(env, sa, buf) != 0) { | |||
5156 | log_debug("%s: integrity checksum failed", __func__); | |||
5157 | goto done; | |||
5158 | } | |||
5159 | } else { | |||
5160 | if ((hdr = ibuf_seek(msg->msg_data, 0, sizeof(*hdr))) == NULL((void*)0)) | |||
5161 | goto done; | |||
5162 | ||||
5163 | bzero(&sah, sizeof(sah)); | |||
5164 | sah.sa_hdr.sh_rspi = betoh64(hdr->ike_rspi)(__uint64_t)(__builtin_constant_p(hdr->ike_rspi) ? (__uint64_t )((((__uint64_t)(hdr->ike_rspi) & 0xff) << 56) | ((__uint64_t)(hdr->ike_rspi) & 0xff00ULL) << 40 | ((__uint64_t)(hdr->ike_rspi) & 0xff0000ULL) << 24 | ((__uint64_t)(hdr->ike_rspi) & 0xff000000ULL) << 8 | ((__uint64_t)(hdr->ike_rspi) & 0xff00000000ULL) >> 8 | ((__uint64_t)(hdr->ike_rspi) & 0xff0000000000ULL) >> 24 | ((__uint64_t)(hdr->ike_rspi) & 0xff000000000000ULL ) >> 40 | ((__uint64_t)(hdr->ike_rspi) & 0xff00000000000000ULL ) >> 56) : __swap64md(hdr->ike_rspi)); | |||
5165 | sah.sa_hdr.sh_ispi = betoh64(hdr->ike_ispi)(__uint64_t)(__builtin_constant_p(hdr->ike_ispi) ? (__uint64_t )((((__uint64_t)(hdr->ike_ispi) & 0xff) << 56) | ((__uint64_t)(hdr->ike_ispi) & 0xff00ULL) << 40 | ((__uint64_t)(hdr->ike_ispi) & 0xff0000ULL) << 24 | ((__uint64_t)(hdr->ike_ispi) & 0xff000000ULL) << 8 | ((__uint64_t)(hdr->ike_ispi) & 0xff00000000ULL) >> 8 | ((__uint64_t)(hdr->ike_ispi) & 0xff0000000000ULL) >> 24 | ((__uint64_t)(hdr->ike_ispi) & 0xff000000000000ULL ) >> 40 | ((__uint64_t)(hdr->ike_ispi) & 0xff00000000000000ULL ) >> 56) : __swap64md(hdr->ike_ispi)); | |||
5166 | sah.sa_hdr.sh_initiator = | |||
5167 | hdr->ike_flags & IKEV2_FLAG_INITIATOR0x08 ? 0 : 1; | |||
5168 | ||||
5169 | resp.msg_msgid = ikev2_msg_id(env, &sah); | |||
5170 | ||||
5171 | /* IKE header */ | |||
5172 | if ((hdr = ikev2_add_header(buf, &sah, resp.msg_msgid, | |||
5173 | IKEV2_PAYLOAD_NOTIFY41, IKEV2_EXCHANGE_INFORMATIONAL37, | |||
5174 | 0)) == NULL((void*)0)) | |||
5175 | goto done; | |||
5176 | if (ibuf_cat(buf, e) != 0) | |||
5177 | goto done; | |||
5178 | if (ikev2_set_header(hdr, ibuf_size(buf) - sizeof(*hdr)) == -1) | |||
5179 | goto done; | |||
5180 | } | |||
5181 | ||||
5182 | resp.msg_data = buf; | |||
5183 | resp.msg_fd = msg->msg_fd; | |||
5184 | TAILQ_INIT(&resp.msg_proposals)do { (&resp.msg_proposals)->tqh_first = ((void*)0); (& resp.msg_proposals)->tqh_last = &(&resp.msg_proposals )->tqh_first; } while (0); | |||
5185 | ||||
5186 | ret = ikev2_msg_send(env, &resp); | |||
5187 | ||||
5188 | done: | |||
5189 | ibuf_release(e); | |||
5190 | ikev2_msg_cleanup(env, &resp); | |||
5191 | ||||
5192 | return (ret); | |||
5193 | } | |||
5194 | ||||
5195 | ssize_t | |||
5196 | ikev2_psk(struct iked_sa *sa, uint8_t *data, size_t length, | |||
5197 | uint8_t **pskptr) | |||
5198 | { | |||
5199 | uint8_t *psk; | |||
5200 | size_t psklen = -1; | |||
5201 | ||||
5202 | if (hash_setkey(sa->sa_prf, data, length) == NULL((void*)0)) | |||
5203 | return (-1); | |||
5204 | ||||
5205 | if ((psk = calloc(1, hash_keylength(sa->sa_prf))) == NULL((void*)0)) | |||
5206 | return (-1); | |||
5207 | ||||
5208 | hash_init(sa->sa_prf); | |||
5209 | hash_update(sa->sa_prf, IKEV2_KEYPAD"Key Pad for IKEv2", strlen(IKEV2_KEYPAD"Key Pad for IKEv2")); | |||
5210 | hash_final(sa->sa_prf, psk, &psklen); | |||
5211 | ||||
5212 | *pskptr = psk; | |||
5213 | return (psklen); | |||
5214 | } | |||
5215 | ||||
5216 | int | |||
5217 | ikev2_sa_initiator_dh(struct iked_sa *sa, struct iked_message *msg, | |||
5218 | unsigned int proto, struct iked_sa *osa) | |||
5219 | { | |||
5220 | struct iked_policy *pol = sa->sa_policy; | |||
5221 | struct iked_transform *xform; | |||
5222 | struct iked_proposals *proposals; | |||
5223 | ||||
5224 | proposals = osa ? &osa->sa_proposals : &pol->pol_proposals; | |||
5225 | ||||
5226 | if (sa->sa_dhgroupsa_kex.kex_dhgroup == NULL((void*)0)) { | |||
5227 | if ((xform = config_findtransform(proposals, | |||
5228 | IKEV2_XFORMTYPE_DH4, proto)) == NULL((void*)0)) { | |||
5229 | log_debug("%s: did not find dh transform", __func__); | |||
5230 | return (-1); | |||
5231 | } | |||
5232 | if ((sa->sa_dhgroupsa_kex.kex_dhgroup = | |||
5233 | group_get(xform->xform_id)) == NULL((void*)0)) { | |||
5234 | log_debug("%s: invalid dh %d", __func__, | |||
5235 | xform->xform_id); | |||
5236 | return (-1); | |||
5237 | } | |||
5238 | } | |||
5239 | ||||
5240 | if (!ibuf_length(sa->sa_dhiexchangesa_kex.kex_dhiexchange)) { | |||
5241 | if (dh_create_exchange(sa->sa_dhgroupsa_kex.kex_dhgroup, | |||
5242 | &sa->sa_dhiexchangesa_kex.kex_dhiexchange, NULL((void*)0)) == -1) { | |||
5243 | log_debug("%s: failed to get dh exchange", __func__); | |||
5244 | return (-1); | |||
5245 | } | |||
5246 | } | |||
5247 | ||||
5248 | /* Initial message */ | |||
5249 | if (msg == NULL((void*)0)) | |||
5250 | return (0); | |||
5251 | ||||
5252 | if (!ibuf_length(sa->sa_dhrexchangesa_kex.kex_dhrexchange)) { | |||
5253 | if (!ibuf_length(msg->msg_ke)) { | |||
5254 | log_debug("%s: invalid peer dh exchange", __func__); | |||
5255 | return (-1); | |||
5256 | } | |||
5257 | sa->sa_dhrexchangesa_kex.kex_dhrexchange = msg->msg_ke; | |||
5258 | msg->msg_ke = NULL((void*)0); | |||
5259 | } | |||
5260 | ||||
5261 | /* Set a pointer to the peer exchange */ | |||
5262 | sa->sa_dhpeersa_kex.kex_dhpeer = sa->sa_dhrexchangesa_kex.kex_dhrexchange; | |||
5263 | return (0); | |||
5264 | } | |||
5265 | ||||
5266 | int | |||
5267 | ikev2_sa_negotiate_common(struct iked *env, struct iked_sa *sa, struct iked_message *msg) | |||
5268 | { | |||
5269 | struct iked_transform *xform; | |||
5270 | ||||
5271 | /* XXX we need a better way to get this */ | |||
5272 | if (proposals_negotiate(&sa->sa_proposals, | |||
5273 | &msg->msg_policy->pol_proposals, &msg->msg_proposals, 0, -1) != 0) { | |||
5274 | log_info("%s: proposals_negotiate", __func__); | |||
5275 | return (-1); | |||
5276 | } | |||
5277 | if (sa_stateok(sa, IKEV2_STATE_SA_INIT2)) | |||
5278 | sa_stateflags(sa, IKED_REQ_SA0x0020); | |||
5279 | ||||
5280 | if (sa->sa_encr == NULL((void*)0)) { | |||
5281 | if ((xform = config_findtransform(&sa->sa_proposals, | |||
5282 | IKEV2_XFORMTYPE_ENCR1, 0)) == NULL((void*)0)) { | |||
5283 | log_info("%s: did not find encr transform", | |||
5284 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5285 | return (-1); | |||
5286 | } | |||
5287 | if ((sa->sa_encr = cipher_new(xform->xform_type, | |||
5288 | xform->xform_id, xform->xform_length)) == NULL((void*)0)) { | |||
5289 | log_info("%s: failed to get encr", | |||
5290 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5291 | return (-1); | |||
5292 | } | |||
5293 | } | |||
5294 | ||||
5295 | /* For AEAD ciphers integrity is implicit */ | |||
5296 | if (sa->sa_encr->encr_authid && sa->sa_integr == NULL((void*)0)) { | |||
5297 | if ((sa->sa_integr = hash_new(IKEV2_XFORMTYPE_INTEGR3, | |||
5298 | sa->sa_encr->encr_authid)) == NULL((void*)0)) { | |||
5299 | log_info("%s: failed to get AEAD integr", | |||
5300 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5301 | return (-1); | |||
5302 | } | |||
5303 | } | |||
5304 | ||||
5305 | if (sa->sa_prf == NULL((void*)0)) { | |||
5306 | if ((xform = config_findtransform(&sa->sa_proposals, | |||
5307 | IKEV2_XFORMTYPE_PRF2, 0)) == NULL((void*)0)) { | |||
5308 | log_info("%s: did not find prf transform", | |||
5309 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5310 | return (-1); | |||
5311 | } | |||
5312 | if ((sa->sa_prf = | |||
5313 | hash_new(xform->xform_type, xform->xform_id)) == NULL((void*)0)) { | |||
5314 | log_info("%s: failed to get prf", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5315 | return (-1); | |||
5316 | } | |||
5317 | } | |||
5318 | ||||
5319 | if (sa->sa_integr == NULL((void*)0)) { | |||
5320 | if ((xform = config_findtransform(&sa->sa_proposals, | |||
5321 | IKEV2_XFORMTYPE_INTEGR3, 0)) == NULL((void*)0)) { | |||
5322 | log_info("%s: did not find integr transform", | |||
5323 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5324 | return (-1); | |||
5325 | } | |||
5326 | if ((sa->sa_integr = | |||
5327 | hash_new(xform->xform_type, xform->xform_id)) == NULL((void*)0)) { | |||
5328 | log_info("%s: failed to get integr", | |||
5329 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5330 | return (-1); | |||
5331 | } | |||
5332 | } | |||
5333 | ||||
5334 | return (0); | |||
5335 | } | |||
5336 | ||||
5337 | int | |||
5338 | ikev2_sa_initiator(struct iked *env, struct iked_sa *sa, | |||
5339 | struct iked_sa *osa, struct iked_message *msg) | |||
5340 | { | |||
5341 | if (ikev2_sa_initiator_dh(sa, msg, 0, osa) < 0) | |||
5342 | return (-1); | |||
5343 | ||||
5344 | if (!ibuf_length(sa->sa_inoncesa_kex.kex_inonce)) { | |||
5345 | if ((sa->sa_inoncesa_kex.kex_inonce = ibuf_random(IKED_NONCE_SIZE32)) == NULL((void*)0)) { | |||
5346 | log_info("%s: failed to get local nonce", | |||
5347 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5348 | return (-1); | |||
5349 | } | |||
5350 | } | |||
5351 | ||||
5352 | /* Initial message */ | |||
5353 | if (msg == NULL((void*)0)) | |||
5354 | return (0); | |||
5355 | ||||
5356 | if (!ibuf_length(sa->sa_rnoncesa_kex.kex_rnonce)) { | |||
5357 | if (!ibuf_length(msg->msg_nonce)) { | |||
5358 | log_info("%s: invalid peer nonce", | |||
5359 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5360 | return (-1); | |||
5361 | } | |||
5362 | sa->sa_rnoncesa_kex.kex_rnonce = msg->msg_nonce; | |||
5363 | msg->msg_nonce = NULL((void*)0); | |||
5364 | } | |||
5365 | ||||
5366 | if (ikev2_sa_negotiate_common(env, sa, msg) != 0) | |||
5367 | return (-1); | |||
5368 | ||||
5369 | ibuf_release(sa->sa_2ndmsg); | |||
5370 | if ((sa->sa_2ndmsg = ibuf_dup(msg->msg_data)) == NULL((void*)0)) { | |||
5371 | log_info("%s: failed to copy 2nd message", | |||
5372 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5373 | return (-1); | |||
5374 | } | |||
5375 | ||||
5376 | return (ikev2_sa_keys(env, sa, osa ? osa->sa_key_d : NULL((void*)0))); | |||
5377 | } | |||
5378 | ||||
5379 | int | |||
5380 | ikev2_sa_responder_dh(struct iked_kex *kex, struct iked_proposals *proposals, | |||
5381 | struct iked_message *msg, unsigned int proto) | |||
5382 | { | |||
5383 | struct iked_transform *xform; | |||
5384 | ||||
5385 | if (kex->kex_dhgroup == NULL((void*)0)) { | |||
5386 | if ((xform = config_findtransform(proposals, | |||
5387 | IKEV2_XFORMTYPE_DH4, proto)) == NULL((void*)0)) { | |||
5388 | log_info("%s: did not find dh transform", | |||
5389 | SPI_SA(msg->msg_sa, __func__)ikev2_ikesa_info((&(msg->msg_sa)->sa_hdr)->sh_ispi , ((__func__)))); | |||
5390 | return (-1); | |||
5391 | } | |||
5392 | if ((kex->kex_dhgroup = | |||
5393 | group_get(xform->xform_id)) == NULL((void*)0)) { | |||
5394 | log_debug("%s: invalid dh %d", | |||
5395 | SPI_SA(msg->msg_sa, __func__)ikev2_ikesa_info((&(msg->msg_sa)->sa_hdr)->sh_ispi , ((__func__))), xform->xform_id); | |||
5396 | return (-1); | |||
5397 | } | |||
5398 | } | |||
5399 | ||||
5400 | /* Look for dhgroup mismatch during an IKE SA negotiation */ | |||
5401 | if (msg->msg_dhgroup != kex->kex_dhgroup->id) { | |||
5402 | log_info("%s: want dh %s, KE has %s", | |||
5403 | SPI_SA(msg->msg_sa, __func__)ikev2_ikesa_info((&(msg->msg_sa)->sa_hdr)->sh_ispi , ((__func__))), | |||
5404 | print_map(kex->kex_dhgroup->id, ikev2_xformdh_map), | |||
5405 | print_map(msg->msg_dhgroup, ikev2_xformdh_map)); | |||
5406 | msg->msg_error = IKEV2_N_INVALID_KE_PAYLOAD17; | |||
5407 | msg->msg_dhgroup = kex->kex_dhgroup->id; | |||
5408 | return (-1); | |||
5409 | } | |||
5410 | ||||
5411 | if (!ibuf_length(kex->kex_dhiexchange)) { | |||
5412 | kex->kex_dhiexchange = msg->msg_ke; | |||
5413 | msg->msg_ke = NULL((void*)0); | |||
5414 | } | |||
5415 | ||||
5416 | if (!ibuf_length(kex->kex_dhrexchange)) { | |||
5417 | if (dh_create_exchange(kex->kex_dhgroup, | |||
5418 | &kex->kex_dhrexchange, kex->kex_dhiexchange) == -1) { | |||
5419 | log_info("%s: failed to get dh exchange", | |||
5420 | SPI_SA(msg->msg_sa, __func__)ikev2_ikesa_info((&(msg->msg_sa)->sa_hdr)->sh_ispi , ((__func__)))); | |||
5421 | return (-1); | |||
5422 | } | |||
5423 | } | |||
5424 | ||||
5425 | /* Set a pointer to the peer exchange */ | |||
5426 | kex->kex_dhpeer = kex->kex_dhiexchange; | |||
5427 | return (0); | |||
5428 | } | |||
5429 | ||||
5430 | int | |||
5431 | ikev2_sa_responder(struct iked *env, struct iked_sa *sa, struct iked_sa *osa, | |||
5432 | struct iked_message *msg) | |||
5433 | { | |||
5434 | struct iked_policy *old; | |||
5435 | ||||
5436 | /* re-lookup policy based on 'msg' (unless IKESA is rekeyed) */ | |||
5437 | if (osa == NULL((void*)0)) { | |||
5438 | old = sa->sa_policy; | |||
5439 | sa->sa_policy = NULL((void*)0); | |||
5440 | if (policy_lookup(env, msg, &msg->msg_proposals, | |||
5441 | NULL((void*)0), 0) != 0 || msg->msg_policy == NULL((void*)0)) { | |||
5442 | sa->sa_policy = old; | |||
5443 | log_info("%s: no proposal chosen", __func__); | |||
5444 | msg->msg_error = IKEV2_N_NO_PROPOSAL_CHOSEN14; | |||
5445 | return (-1); | |||
5446 | } | |||
5447 | /* move sa to new policy */ | |||
5448 | sa->sa_policy = msg->msg_policy; | |||
5449 | TAILQ_REMOVE(&old->pol_sapeers, sa, sa_peer_entry)do { if (((sa)->sa_peer_entry.tqe_next) != ((void*)0)) (sa )->sa_peer_entry.tqe_next->sa_peer_entry.tqe_prev = (sa )->sa_peer_entry.tqe_prev; else (&old->pol_sapeers) ->tqh_last = (sa)->sa_peer_entry.tqe_prev; *(sa)->sa_peer_entry .tqe_prev = (sa)->sa_peer_entry.tqe_next; ; ; } while (0); | |||
5450 | TAILQ_INSERT_TAIL(&sa->sa_policy->pol_sapeers,do { (sa)->sa_peer_entry.tqe_next = ((void*)0); (sa)->sa_peer_entry .tqe_prev = (&sa->sa_policy->pol_sapeers)->tqh_last ; *(&sa->sa_policy->pol_sapeers)->tqh_last = (sa ); (&sa->sa_policy->pol_sapeers)->tqh_last = & (sa)->sa_peer_entry.tqe_next; } while (0) | |||
5451 | sa, sa_peer_entry)do { (sa)->sa_peer_entry.tqe_next = ((void*)0); (sa)->sa_peer_entry .tqe_prev = (&sa->sa_policy->pol_sapeers)->tqh_last ; *(&sa->sa_policy->pol_sapeers)->tqh_last = (sa ); (&sa->sa_policy->pol_sapeers)->tqh_last = & (sa)->sa_peer_entry.tqe_next; } while (0); | |||
5452 | if (old->pol_flags & IKED_POLICY_REFCNT0x04) | |||
5453 | policy_unref(env, old); | |||
5454 | if (sa->sa_policy->pol_flags & IKED_POLICY_REFCNT0x04) | |||
5455 | policy_ref(env, sa->sa_policy); | |||
5456 | } | |||
5457 | ||||
5458 | sa_state(env, sa, IKEV2_STATE_SA_INIT2); | |||
5459 | ||||
5460 | ibuf_release(sa->sa_1stmsg); | |||
5461 | if ((sa->sa_1stmsg = ibuf_dup(msg->msg_data)) == NULL((void*)0)) { | |||
5462 | log_debug("%s: failed to copy 1st message", __func__); | |||
5463 | return (-1); | |||
5464 | } | |||
5465 | ||||
5466 | if (!ibuf_length(sa->sa_rnoncesa_kex.kex_rnonce) && | |||
5467 | (sa->sa_rnoncesa_kex.kex_rnonce = ibuf_random(IKED_NONCE_SIZE32)) == NULL((void*)0)) { | |||
5468 | log_debug("%s: failed to get local nonce", __func__); | |||
5469 | return (-1); | |||
5470 | } | |||
5471 | ||||
5472 | if (!ibuf_length(sa->sa_inoncesa_kex.kex_inonce) && | |||
5473 | (ibuf_length(msg->msg_nonce) < IKED_NONCE_MIN16)) { | |||
5474 | log_debug("%s: failed to get peer nonce", __func__); | |||
5475 | return (-1); | |||
5476 | } | |||
5477 | sa->sa_inoncesa_kex.kex_inonce = msg->msg_nonce; | |||
5478 | msg->msg_nonce = NULL((void*)0); | |||
5479 | ||||
5480 | if (ikev2_sa_negotiate_common(env, sa, msg) != 0) | |||
5481 | return (-1); | |||
5482 | ||||
5483 | if (ikev2_sa_responder_dh(&sa->sa_kex, &sa->sa_proposals, msg, 0) < 0) | |||
5484 | return (-1); | |||
5485 | ||||
5486 | return (ikev2_sa_keys(env, sa, osa ? osa->sa_key_d : NULL((void*)0))); | |||
5487 | } | |||
5488 | ||||
5489 | int | |||
5490 | ikev2_sa_keys(struct iked *env, struct iked_sa *sa, struct ibuf *key) | |||
5491 | { | |||
5492 | struct iked_hash *prf, *integr; | |||
5493 | struct iked_cipher *encr; | |||
5494 | struct dh_group *group; | |||
5495 | struct ibuf *ninr, *dhsecret, *skeyseed, *s, *t; | |||
5496 | size_t nonceminlen, ilen, rlen, tmplen; | |||
5497 | uint64_t ispi, rspi; | |||
5498 | int ret = -1; | |||
5499 | int isaead = 0; | |||
5500 | ||||
5501 | ninr = dhsecret = skeyseed = s = t = NULL((void*)0); | |||
5502 | ||||
5503 | if ((encr = sa->sa_encr) == NULL((void*)0) || | |||
5504 | (prf = sa->sa_prf) == NULL((void*)0) || | |||
5505 | (integr = sa->sa_integr) == NULL((void*)0) || | |||
5506 | (group = sa->sa_dhgroupsa_kex.kex_dhgroup) == NULL((void*)0)) { | |||
5507 | log_info("%s: failed to get key input data", | |||
5508 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5509 | return (-1); | |||
5510 | } | |||
5511 | ||||
5512 | /* For AEADs no auth keys are required (see RFC 5282) */ | |||
5513 | isaead = !!integr->hash_isaead; | |||
5514 | ||||
5515 | if (prf->hash_fixedkey) | |||
5516 | nonceminlen = prf->hash_fixedkey; | |||
5517 | else | |||
5518 | nonceminlen = IKED_NONCE_MIN16; | |||
5519 | ||||
5520 | /* Nonces need a minimal size and should have an even length */ | |||
5521 | if (ibuf_length(sa->sa_inoncesa_kex.kex_inonce) < nonceminlen || | |||
5522 | (ibuf_length(sa->sa_inoncesa_kex.kex_inonce) % 2) != 0 || | |||
5523 | ibuf_length(sa->sa_rnoncesa_kex.kex_rnonce) < nonceminlen || | |||
5524 | (ibuf_length(sa->sa_rnoncesa_kex.kex_rnonce) % 2) != 0) { | |||
5525 | log_info("%s: invalid nonces", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5526 | return (-1); | |||
5527 | } | |||
5528 | ||||
5529 | if (prf->hash_fixedkey) { | |||
5530 | /* Half of the key bits must come from Ni, and half from Nr */ | |||
5531 | ilen = prf->hash_fixedkey / 2; | |||
5532 | rlen = prf->hash_fixedkey / 2; | |||
5533 | } else { | |||
5534 | /* Most PRF functions accept a variable-length key */ | |||
5535 | ilen = ibuf_length(sa->sa_inoncesa_kex.kex_inonce); | |||
5536 | rlen = ibuf_length(sa->sa_rnoncesa_kex.kex_rnonce); | |||
5537 | } | |||
5538 | ||||
5539 | /* | |||
5540 | * Depending on whether we're generating new keying material | |||
5541 | * or rekeying existing SA the algorithm is different. If the | |||
5542 | * "key" argument is not specified a concatenation of nonces | |||
5543 | * (Ni | Nr) is used as a PRF key, otherwise a "key" buffer | |||
5544 | * is used and PRF is performed on the concatenation of DH | |||
5545 | * exchange result and nonces (g^ir | Ni | Nr). See sections | |||
5546 | * 2.14 and 2.18 of RFC7296 for more information. | |||
5547 | */ | |||
5548 | ||||
5549 | /* | |||
5550 | * Generate g^ir | |||
5551 | */ | |||
5552 | if (dh_create_shared(group, &dhsecret, sa->sa_dhpeersa_kex.kex_dhpeer) == -1) { | |||
5553 | log_info("%s: failed to get dh secret" | |||
5554 | " group %d secret %zu exchange %zu", | |||
5555 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
5556 | group->id, ibuf_length(dhsecret), | |||
5557 | ibuf_length(sa->sa_dhpeersa_kex.kex_dhpeer)); | |||
5558 | goto done; | |||
5559 | } | |||
5560 | ||||
5561 | log_debug("%s: DHSECRET with %zu bytes", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
5562 | ibuf_length(dhsecret)); | |||
5563 | print_hex(dhsecret->buf, 0, ibuf_length(dhsecret)); | |||
5564 | ||||
5565 | if (!key) { | |||
5566 | /* | |||
5567 | * Set PRF key to generate SKEEYSEED = prf(Ni | Nr, g^ir) | |||
5568 | */ | |||
5569 | if ((ninr = ibuf_new(sa->sa_inoncesa_kex.kex_inonce->buf, ilen)) == NULL((void*)0) || | |||
5570 | ibuf_add(ninr, sa->sa_rnoncesa_kex.kex_rnonce->buf, rlen) != 0) { | |||
5571 | log_info("%s: failed to get nonce key buffer", | |||
5572 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5573 | goto done; | |||
5574 | } | |||
5575 | key = ninr; | |||
5576 | } else { | |||
5577 | /* | |||
5578 | * Set PRF key to generate SKEEYSEED = prf(key, g^ir | Ni | Nr) | |||
5579 | */ | |||
5580 | if (ibuf_add(dhsecret, sa->sa_inoncesa_kex.kex_inonce->buf, ilen) != 0 || | |||
5581 | ibuf_add(dhsecret, sa->sa_rnoncesa_kex.kex_rnonce->buf, rlen) != 0) { | |||
5582 | log_info("%s: failed to get nonce key buffer", | |||
5583 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5584 | goto done; | |||
5585 | } | |||
5586 | } | |||
5587 | ||||
5588 | if ((hash_setkey(prf, key->buf, ibuf_length(key))) == NULL((void*)0)) { | |||
5589 | log_info("%s: failed to set prf key", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5590 | goto done; | |||
5591 | } | |||
5592 | ||||
5593 | if ((skeyseed = ibuf_new(NULL((void*)0), hash_keylength(prf))) == NULL((void*)0)) { | |||
5594 | log_info("%s: failed to get SKEYSEED buffer", | |||
5595 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5596 | goto done; | |||
5597 | } | |||
5598 | ||||
5599 | tmplen = 0; | |||
5600 | hash_init(prf); | |||
5601 | hash_update(prf, dhsecret->buf, ibuf_length(dhsecret)); | |||
5602 | hash_final(prf, skeyseed->buf, &tmplen); | |||
5603 | ||||
5604 | log_debug("%s: SKEYSEED with %zu bytes", __func__, tmplen); | |||
5605 | print_hex(skeyseed->buf, 0, tmplen); | |||
5606 | ||||
5607 | if (ibuf_setsize(skeyseed, tmplen) == -1) { | |||
5608 | log_info("%s: failed to set keymaterial length", | |||
5609 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5610 | goto done; | |||
5611 | } | |||
5612 | ||||
5613 | /* | |||
5614 | * Now generate the key material | |||
5615 | * | |||
5616 | * S = Ni | Nr | SPIi | SPIr | |||
5617 | */ | |||
5618 | ||||
5619 | /* S = Ni | Nr | SPIi | SPIr */ | |||
5620 | ilen = ibuf_length(sa->sa_inoncesa_kex.kex_inonce); | |||
5621 | rlen = ibuf_length(sa->sa_rnoncesa_kex.kex_rnonce); | |||
5622 | ispi = htobe64(sa->sa_hdr.sh_ispi)(__uint64_t)(__builtin_constant_p(sa->sa_hdr.sh_ispi) ? (__uint64_t )((((__uint64_t)(sa->sa_hdr.sh_ispi) & 0xff) << 56 ) | ((__uint64_t)(sa->sa_hdr.sh_ispi) & 0xff00ULL) << 40 | ((__uint64_t)(sa->sa_hdr.sh_ispi) & 0xff0000ULL) << 24 | ((__uint64_t)(sa->sa_hdr.sh_ispi) & 0xff000000ULL ) << 8 | ((__uint64_t)(sa->sa_hdr.sh_ispi) & 0xff00000000ULL ) >> 8 | ((__uint64_t)(sa->sa_hdr.sh_ispi) & 0xff0000000000ULL ) >> 24 | ((__uint64_t)(sa->sa_hdr.sh_ispi) & 0xff000000000000ULL ) >> 40 | ((__uint64_t)(sa->sa_hdr.sh_ispi) & 0xff00000000000000ULL ) >> 56) : __swap64md(sa->sa_hdr.sh_ispi)); | |||
5623 | rspi = htobe64(sa->sa_hdr.sh_rspi)(__uint64_t)(__builtin_constant_p(sa->sa_hdr.sh_rspi) ? (__uint64_t )((((__uint64_t)(sa->sa_hdr.sh_rspi) & 0xff) << 56 ) | ((__uint64_t)(sa->sa_hdr.sh_rspi) & 0xff00ULL) << 40 | ((__uint64_t)(sa->sa_hdr.sh_rspi) & 0xff0000ULL) << 24 | ((__uint64_t)(sa->sa_hdr.sh_rspi) & 0xff000000ULL ) << 8 | ((__uint64_t)(sa->sa_hdr.sh_rspi) & 0xff00000000ULL ) >> 8 | ((__uint64_t)(sa->sa_hdr.sh_rspi) & 0xff0000000000ULL ) >> 24 | ((__uint64_t)(sa->sa_hdr.sh_rspi) & 0xff000000000000ULL ) >> 40 | ((__uint64_t)(sa->sa_hdr.sh_rspi) & 0xff00000000000000ULL ) >> 56) : __swap64md(sa->sa_hdr.sh_rspi)); | |||
5624 | ||||
5625 | if ((s = ibuf_new(sa->sa_inoncesa_kex.kex_inonce->buf, ilen)) == NULL((void*)0) || | |||
5626 | ibuf_add(s, sa->sa_rnoncesa_kex.kex_rnonce->buf, rlen) != 0 || | |||
5627 | ibuf_add(s, &ispi, sizeof(ispi)) != 0 || | |||
5628 | ibuf_add(s, &rspi, sizeof(rspi)) != 0) { | |||
5629 | log_info("%s: failed to set S buffer", | |||
5630 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5631 | goto done; | |||
5632 | } | |||
5633 | ||||
5634 | log_debug("%s: S with %zu bytes", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), ibuf_length(s)); | |||
5635 | print_hex(s->buf, 0, ibuf_length(s)); | |||
5636 | ||||
5637 | /* | |||
5638 | * Get the size of the key material we need and the number | |||
5639 | * of rounds we need to run the prf+ function. | |||
5640 | */ | |||
5641 | ilen = hash_length(prf) + /* SK_d */ | |||
5642 | (isaead ? 0 : hash_keylength(integr)) + /* SK_ai */ | |||
5643 | (isaead ? 0 : hash_keylength(integr)) + /* SK_ar */ | |||
5644 | cipher_keylength(encr) + /* SK_ei */ | |||
5645 | cipher_keylength(encr) + /* SK_er */ | |||
5646 | hash_keylength(prf) + /* SK_pi */ | |||
5647 | hash_keylength(prf); /* SK_pr */ | |||
5648 | ||||
5649 | if ((t = ikev2_prfplus(prf, skeyseed, s, ilen)) == NULL((void*)0)) { | |||
5650 | log_info("%s: failed to get IKE SA key material", | |||
5651 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5652 | goto done; | |||
5653 | } | |||
5654 | ||||
5655 | /* ibuf_get() returns a new buffer from the next read offset */ | |||
5656 | if ((sa->sa_key_d = ibuf_get(t, hash_length(prf))) == NULL((void*)0) || | |||
5657 | (!isaead && | |||
5658 | (sa->sa_key_iauth = ibuf_get(t, hash_keylength(integr))) == NULL((void*)0)) || | |||
5659 | (!isaead && | |||
5660 | (sa->sa_key_rauth = ibuf_get(t, hash_keylength(integr))) == NULL((void*)0)) || | |||
5661 | (sa->sa_key_iencr = ibuf_get(t, cipher_keylength(encr))) == NULL((void*)0) || | |||
5662 | (sa->sa_key_rencr = ibuf_get(t, cipher_keylength(encr))) == NULL((void*)0) || | |||
5663 | (sa->sa_key_iprf = ibuf_get(t, hash_length(prf))) == NULL((void*)0) || | |||
5664 | (sa->sa_key_rprf = ibuf_get(t, hash_length(prf))) == NULL((void*)0)) { | |||
5665 | log_debug("%s: failed to get SA keys", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5666 | goto done; | |||
5667 | } | |||
5668 | ||||
5669 | log_debug("%s: SK_d with %zu bytes", __func__, | |||
5670 | ibuf_length(sa->sa_key_d)); | |||
5671 | print_hex(sa->sa_key_d->buf, 0, ibuf_length(sa->sa_key_d)); | |||
5672 | if (!isaead) { | |||
5673 | log_debug("%s: SK_ai with %zu bytes", __func__, | |||
5674 | ibuf_length(sa->sa_key_iauth)); | |||
5675 | print_hex(sa->sa_key_iauth->buf, 0, | |||
5676 | ibuf_length(sa->sa_key_iauth)); | |||
5677 | log_debug("%s: SK_ar with %zu bytes", __func__, | |||
5678 | ibuf_length(sa->sa_key_rauth)); | |||
5679 | print_hex(sa->sa_key_rauth->buf, 0, | |||
5680 | ibuf_length(sa->sa_key_rauth)); | |||
5681 | } | |||
5682 | log_debug("%s: SK_ei with %zu bytes", __func__, | |||
5683 | ibuf_length(sa->sa_key_iencr)); | |||
5684 | print_hex(sa->sa_key_iencr->buf, 0, ibuf_length(sa->sa_key_iencr)); | |||
5685 | log_debug("%s: SK_er with %zu bytes", __func__, | |||
5686 | ibuf_length(sa->sa_key_rencr)); | |||
5687 | print_hex(sa->sa_key_rencr->buf, 0, ibuf_length(sa->sa_key_rencr)); | |||
5688 | log_debug("%s: SK_pi with %zu bytes", __func__, | |||
5689 | ibuf_length(sa->sa_key_iprf)); | |||
5690 | print_hex(sa->sa_key_iprf->buf, 0, ibuf_length(sa->sa_key_iprf)); | |||
5691 | log_debug("%s: SK_pr with %zu bytes", __func__, | |||
5692 | ibuf_length(sa->sa_key_rprf)); | |||
5693 | print_hex(sa->sa_key_rprf->buf, 0, ibuf_length(sa->sa_key_rprf)); | |||
5694 | ||||
5695 | ret = 0; | |||
5696 | ||||
5697 | done: | |||
5698 | ibuf_release(ninr); | |||
5699 | ibuf_release(dhsecret); | |||
5700 | ibuf_release(skeyseed); | |||
5701 | ibuf_release(s); | |||
5702 | ibuf_release(t); | |||
5703 | ||||
5704 | return (ret); | |||
5705 | } | |||
5706 | ||||
5707 | void | |||
5708 | ikev2_sa_cleanup_dh(struct iked_sa *sa) | |||
5709 | { | |||
5710 | ibuf_release(sa->sa_dhiexchangesa_kex.kex_dhiexchange); | |||
5711 | ibuf_release(sa->sa_dhrexchangesa_kex.kex_dhrexchange); | |||
5712 | group_free(sa->sa_dhgroupsa_kex.kex_dhgroup); | |||
5713 | sa->sa_dhiexchangesa_kex.kex_dhiexchange = NULL((void*)0); | |||
5714 | sa->sa_dhrexchangesa_kex.kex_dhrexchange = NULL((void*)0); | |||
5715 | sa->sa_dhgroupsa_kex.kex_dhgroup = NULL((void*)0); | |||
5716 | } | |||
5717 | ||||
5718 | struct ibuf * | |||
5719 | ikev2_prfplus(struct iked_hash *prf, struct ibuf *key, struct ibuf *seed, | |||
5720 | size_t keymatlen) | |||
5721 | { | |||
5722 | struct ibuf *t = NULL((void*)0), *t1 = NULL((void*)0), *t2 = NULL((void*)0); | |||
5723 | size_t rlen, i, hashlen = 0; | |||
5724 | uint8_t pad = 0; | |||
5725 | ||||
5726 | /* | |||
5727 | * prf+ (K, S) = T1 | T2 | T3 | T4 | ... | |||
5728 | * | |||
5729 | * T1 = prf (K, S | 0x01) | |||
5730 | * T2 = prf (K, T1 | S | 0x02) | |||
5731 | * T3 = prf (K, T2 | S | 0x03) | |||
5732 | * T4 = prf (K, T3 | S | 0x04) | |||
5733 | */ | |||
5734 | ||||
5735 | if ((hash_setkey(prf, ibuf_data(key), ibuf_size(key))) == NULL((void*)0)) { | |||
5736 | log_debug("%s: failed to set prf+ key", __func__); | |||
5737 | goto fail; | |||
5738 | } | |||
5739 | ||||
5740 | if ((t = ibuf_new(NULL((void*)0), 0)) == NULL((void*)0)) { | |||
5741 | log_debug("%s: failed to get T buffer", __func__); | |||
5742 | goto fail; | |||
5743 | } | |||
5744 | ||||
5745 | rlen = roundup(keymatlen, hash_length(prf))((((keymatlen)+((hash_length(prf))-1))/(hash_length(prf)))*(hash_length (prf))) / hash_length(prf); | |||
5746 | if (rlen > 255) | |||
5747 | fatalx("ikev2_prfplus: key material too large"); | |||
5748 | ||||
5749 | for (i = 0; i < rlen; i++) { | |||
5750 | if (t1 != NULL((void*)0)) { | |||
5751 | t2 = ibuf_new(t1->buf, ibuf_length(t1)); | |||
5752 | ibuf_release(t1); | |||
5753 | } else | |||
5754 | t2 = ibuf_new(NULL((void*)0), 0); | |||
5755 | t1 = ibuf_new(NULL((void*)0), hash_keylength(prf)); | |||
5756 | ||||
5757 | ibuf_add(t2, seed->buf, ibuf_length(seed)); | |||
5758 | pad = i + 1; | |||
5759 | ibuf_add(t2, &pad, 1); | |||
5760 | ||||
5761 | hash_init(prf); | |||
5762 | hash_update(prf, t2->buf, ibuf_length(t2)); | |||
5763 | hash_final(prf, t1->buf, &hashlen); | |||
5764 | ||||
5765 | if (hashlen != hash_length(prf)) | |||
5766 | fatalx("ikev2_prfplus: hash length mismatch"); | |||
5767 | ||||
5768 | ibuf_release(t2); | |||
5769 | ibuf_add(t, t1->buf, ibuf_length(t1)); | |||
5770 | ||||
5771 | log_debug("%s: T%d with %zu bytes", __func__, | |||
5772 | pad, ibuf_length(t1)); | |||
5773 | print_hex(t1->buf, 0, ibuf_length(t1)); | |||
5774 | } | |||
5775 | ||||
5776 | log_debug("%s: Tn with %zu bytes", __func__, ibuf_length(t)); | |||
5777 | print_hex(t->buf, 0, ibuf_length(t)); | |||
5778 | ||||
5779 | ibuf_release(t1); | |||
5780 | ||||
5781 | return (t); | |||
5782 | ||||
5783 | fail: | |||
5784 | ibuf_release(t1); | |||
5785 | ibuf_release(t); | |||
5786 | ||||
5787 | return (NULL((void*)0)); | |||
5788 | } | |||
5789 | ||||
5790 | int | |||
5791 | ikev2_sa_tag(struct iked_sa *sa, struct iked_id *id) | |||
5792 | { | |||
5793 | char *format, *domain = NULL((void*)0), *idrepl = NULL((void*)0); | |||
5794 | char idstr[IKED_ID_SIZE1024]; | |||
5795 | int ret = -1; | |||
5796 | size_t len; | |||
5797 | ||||
5798 | free(sa->sa_tag); | |||
5799 | sa->sa_tag = NULL((void*)0); | |||
5800 | format = sa->sa_policy->pol_tag; | |||
5801 | ||||
5802 | len = IKED_TAG_SIZE64; | |||
5803 | if ((sa->sa_tag = calloc(1, len)) == NULL((void*)0)) { | |||
5804 | log_debug("%s: calloc", __func__); | |||
5805 | goto fail; | |||
5806 | } | |||
5807 | if (strlcpy(sa->sa_tag, format, len) >= len) { | |||
5808 | log_debug("%s: tag too long", __func__); | |||
5809 | goto fail; | |||
5810 | } | |||
5811 | ||||
5812 | if (ikev2_print_id(id, idstr, sizeof(idstr)) == -1) { | |||
5813 | log_debug("%s: invalid id", __func__); | |||
5814 | goto fail; | |||
5815 | } | |||
5816 | ||||
5817 | /* ASN.1 DER IDs are too long, use the CN part instead */ | |||
5818 | if ((id->id_type == IKEV2_ID_ASN1_DN9) && | |||
5819 | (idrepl = strstr(idstr, "CN=")) != NULL((void*)0)) { | |||
5820 | domain = strstr(idrepl, "emailAddress="); | |||
5821 | idrepl[strcspn(idrepl, "/")] = '\0'; | |||
5822 | } else | |||
5823 | idrepl = idstr; | |||
5824 | ||||
5825 | if (strstr(format, "$id") != NULL((void*)0)) { | |||
5826 | if (expand_string(sa->sa_tag, len, "$id", idrepl) != 0) { | |||
5827 | log_debug("%s: failed to expand tag", __func__); | |||
5828 | goto fail; | |||
5829 | } | |||
5830 | } | |||
5831 | ||||
5832 | if (strstr(format, "$eapid") != NULL((void*)0) && sa->sa_eapid != NULL((void*)0)) { | |||
5833 | if (expand_string(sa->sa_tag, len, "$eapid", | |||
5834 | sa->sa_eapid) != 0) { | |||
5835 | log_debug("%s: failed to expand tag", __func__); | |||
5836 | goto fail; | |||
5837 | } | |||
5838 | } | |||
5839 | ||||
5840 | if (strstr(format, "$name") != NULL((void*)0)) { | |||
5841 | if (expand_string(sa->sa_tag, len, "$name", | |||
5842 | sa->sa_policy->pol_name) != 0) { | |||
5843 | log_debug("%s: failed to expand tag", __func__); | |||
5844 | goto fail; | |||
5845 | } | |||
5846 | } | |||
5847 | ||||
5848 | if (strstr(format, "$domain") != NULL((void*)0)) { | |||
5849 | if (id->id_type == IKEV2_ID_FQDN2) | |||
5850 | domain = strchr(idrepl, '.'); | |||
5851 | else if (id->id_type == IKEV2_ID_UFQDN3) | |||
5852 | domain = strchr(idrepl, '@'); | |||
5853 | else if (*idstr == '/' && domain != NULL((void*)0)) | |||
5854 | domain = strchr(domain, '@'); | |||
5855 | else | |||
5856 | domain = NULL((void*)0); | |||
5857 | if (domain == NULL((void*)0) || strlen(domain) < 2) { | |||
5858 | log_debug("%s: no valid domain in ID %s", | |||
5859 | __func__, idstr); | |||
5860 | goto fail; | |||
5861 | } | |||
5862 | domain++; | |||
5863 | if (expand_string(sa->sa_tag, len, "$domain", domain) != 0) { | |||
5864 | log_debug("%s: failed to expand tag", __func__); | |||
5865 | goto fail; | |||
5866 | } | |||
5867 | } | |||
5868 | ||||
5869 | log_debug("%s: %s (%zu)", __func__, sa->sa_tag, strlen(sa->sa_tag)); | |||
5870 | ||||
5871 | ret = 0; | |||
5872 | fail: | |||
5873 | if (ret != 0) { | |||
5874 | free(sa->sa_tag); | |||
5875 | sa->sa_tag = NULL((void*)0); | |||
5876 | } | |||
5877 | ||||
5878 | return (ret); | |||
5879 | } | |||
5880 | ||||
5881 | int | |||
5882 | ikev2_childsa_delete_proposed(struct iked *env, struct iked_sa *sa, | |||
5883 | struct iked_proposals *proposals) | |||
5884 | { | |||
5885 | struct ibuf *buf = NULL((void*)0); | |||
5886 | struct iked_proposal *prop; | |||
5887 | struct ikev2_delete *del; | |||
5888 | uint32_t spi32; | |||
5889 | uint8_t protoid = 0; | |||
5890 | int ret = -1, count; | |||
5891 | ||||
5892 | if (!sa_stateok(sa, IKEV2_STATE_VALID7)) | |||
5893 | return (-1); | |||
5894 | ||||
5895 | count = 0; | |||
5896 | TAILQ_FOREACH(prop, proposals, prop_entry)for((prop) = ((proposals)->tqh_first); (prop) != ((void*)0 ); (prop) = ((prop)->prop_entry.tqe_next)) { | |||
5897 | if (ikev2_valid_proposal(prop, NULL((void*)0), NULL((void*)0), NULL((void*)0)) != 0) | |||
5898 | continue; | |||
5899 | protoid = prop->prop_protoid; | |||
5900 | count++; | |||
5901 | } | |||
5902 | if (count == 0) | |||
5903 | return (0); | |||
5904 | if ((buf = ibuf_static()) == NULL((void*)0)) | |||
5905 | return (-1); | |||
5906 | if ((del = ibuf_advance(buf, sizeof(*del))) == NULL((void*)0)) | |||
5907 | goto done; | |||
5908 | /* XXX we assume all have the same protoid */ | |||
5909 | del->del_protoid = protoid; | |||
5910 | del->del_spisize = 4; | |||
5911 | del->del_nspi = htobe16(count)(__uint16_t)(__builtin_constant_p(count) ? (__uint16_t)(((__uint16_t )(count) & 0xffU) << 8 | ((__uint16_t)(count) & 0xff00U) >> 8) : __swap16md(count)); | |||
5912 | ||||
5913 | TAILQ_FOREACH(prop, proposals, prop_entry)for((prop) = ((proposals)->tqh_first); (prop) != ((void*)0 ); (prop) = ((prop)->prop_entry.tqe_next)) { | |||
5914 | if (ikev2_valid_proposal(prop, NULL((void*)0), NULL((void*)0), NULL((void*)0)) != 0) | |||
5915 | continue; | |||
5916 | spi32 = htobe32(prop->prop_localspi.spi)(__uint32_t)(__builtin_constant_p(prop->prop_localspi.spi) ? (__uint32_t)(((__uint32_t)(prop->prop_localspi.spi) & 0xff) << 24 | ((__uint32_t)(prop->prop_localspi.spi ) & 0xff00) << 8 | ((__uint32_t)(prop->prop_localspi .spi) & 0xff0000) >> 8 | ((__uint32_t)(prop->prop_localspi .spi) & 0xff000000) >> 24) : __swap32md(prop->prop_localspi .spi)); | |||
5917 | if (ibuf_add(buf, &spi32, sizeof(spi32))) | |||
5918 | goto done; | |||
5919 | } | |||
5920 | ||||
5921 | if (ikev2_send_ike_e(env, sa, buf, IKEV2_PAYLOAD_DELETE42, | |||
5922 | IKEV2_EXCHANGE_INFORMATIONAL37, 0) == -1) | |||
5923 | goto done; | |||
5924 | sa->sa_stateflags |= IKED_REQ_INF0x0100; | |||
5925 | ret = 0; | |||
5926 | done: | |||
5927 | ibuf_release(buf); | |||
5928 | ||||
5929 | return (ret); | |||
5930 | } | |||
5931 | ||||
5932 | int | |||
5933 | ikev2_childsa_negotiate(struct iked *env, struct iked_sa *sa, | |||
5934 | struct iked_kex *kex, struct iked_proposals *proposals, int initiator, | |||
5935 | int pfs) | |||
5936 | { | |||
5937 | struct iked_proposal *prop; | |||
5938 | struct iked_transform *xform, *encrxf = NULL((void*)0), *integrxf = NULL((void*)0); | |||
5939 | struct iked_childsa *csa = NULL((void*)0), *csb = NULL((void*)0); | |||
5940 | struct iked_childsa *csa2 = NULL((void*)0), *csb2 = NULL((void*)0); | |||
5941 | struct iked_flow *flow, *saflow, *flowa, *flowb; | |||
5942 | struct iked_ipcomp *ic; | |||
5943 | struct ibuf *keymat = NULL((void*)0), *seed = NULL((void*)0), *dhsecret = NULL((void*)0); | |||
5944 | struct dh_group *group = NULL((void*)0); | |||
5945 | uint32_t spi = 0; | |||
5946 | unsigned int i; | |||
5947 | size_t ilen = 0; | |||
5948 | int esn, skip, ret = -1; | |||
5949 | ||||
5950 | if (!sa_stateok(sa, IKEV2_STATE_VALID7)) | |||
5951 | return (-1); | |||
5952 | ||||
5953 | if (ikev2_sa_tag(sa, IKESA_DSTID(sa)((sa)->sa_hdr.sh_initiator ? &(sa)->sa_rid : &( sa)->sa_iid)) == -1) | |||
5954 | return (-1); | |||
5955 | ||||
5956 | ic = initiator ? &sa->sa_ipcompi : &sa->sa_ipcompr; | |||
5957 | if (ic->ic_transform == 0 || ic->ic_cpi_out == 0 || | |||
5958 | (initiator && ic->ic_cpi_in == 0)) | |||
5959 | ic = NULL((void*)0); | |||
5960 | ||||
5961 | /* reset state */ | |||
5962 | sa->sa_used_transport_mode = 0; | |||
5963 | ||||
5964 | /* We need to determine the key material length first */ | |||
5965 | TAILQ_FOREACH(prop, proposals, prop_entry)for((prop) = ((proposals)->tqh_first); (prop) != ((void*)0 ); (prop) = ((prop)->prop_entry.tqe_next)) { | |||
5966 | if (prop->prop_protoid == IKEV2_SAPROTO_IKE1) | |||
5967 | continue; | |||
5968 | log_debug("%s: proposal %d", __func__, prop->prop_id); | |||
5969 | for (i = 0; i < prop->prop_nxforms; i++) { | |||
5970 | xform = prop->prop_xforms + i; | |||
5971 | xform->xform_keylength = | |||
5972 | keylength_xf(prop->prop_protoid, | |||
5973 | xform->xform_type, xform->xform_id); | |||
5974 | ||||
5975 | switch (xform->xform_type) { | |||
5976 | case IKEV2_XFORMTYPE_ENCR1: | |||
5977 | case IKEV2_XFORMTYPE_INTEGR3: | |||
5978 | if (xform->xform_length) | |||
5979 | xform->xform_keylength = | |||
5980 | xform->xform_length; | |||
5981 | xform->xform_keylength += | |||
5982 | noncelength_xf(xform->xform_type, | |||
5983 | xform->xform_id); | |||
5984 | ilen += xform->xform_keylength / 8; | |||
5985 | break; | |||
5986 | } | |||
5987 | } | |||
5988 | } | |||
5989 | ||||
5990 | /* double key material length for inbound/outbound */ | |||
5991 | ilen *= 2; | |||
5992 | ||||
5993 | log_debug("%s: key material length %zu", __func__, ilen); | |||
5994 | ||||
5995 | if ((seed = ibuf_new(NULL((void*)0), 0)) == NULL((void*)0)) { | |||
5996 | log_debug("%s: failed to setup IKE SA key material", __func__); | |||
5997 | goto done; | |||
5998 | } | |||
5999 | if (pfs) { | |||
6000 | log_debug("%s: using PFS", __func__); | |||
6001 | if (kex->kex_dhpeer == NULL((void*)0) || | |||
6002 | ibuf_length(kex->kex_dhpeer) == 0 || | |||
6003 | (group = kex->kex_dhgroup) == NULL((void*)0)) { | |||
6004 | log_debug("%s: no dh group for pfs", __func__); | |||
6005 | goto done; | |||
6006 | } | |||
6007 | if (dh_create_shared(group, &dhsecret, kex->kex_dhpeer) == -1) { | |||
6008 | log_debug("%s: failed to get dh secret" | |||
6009 | " group %d secret %zu exchange %zu", | |||
6010 | __func__, group->id, ibuf_length(dhsecret), | |||
6011 | ibuf_length(kex->kex_dhpeer)); | |||
6012 | goto done; | |||
6013 | } | |||
6014 | if (ibuf_cat(seed, dhsecret) != 0) { | |||
6015 | log_debug("%s: failed to set dh secret", __func__); | |||
6016 | goto done; | |||
6017 | } | |||
6018 | } | |||
6019 | if (ibuf_cat(seed, kex->kex_inonce) != 0 || | |||
6020 | ibuf_cat(seed, kex->kex_rnonce) != 0 || | |||
6021 | (keymat = ikev2_prfplus(sa->sa_prf, | |||
6022 | sa->sa_key_d, seed, ilen)) == NULL((void*)0)) { | |||
6023 | log_debug("%s: failed to get IKE SA key material", __func__); | |||
6024 | goto done; | |||
6025 | } | |||
6026 | ||||
6027 | /* Create the new flows */ | |||
6028 | TAILQ_FOREACH(prop, proposals, prop_entry)for((prop) = ((proposals)->tqh_first); (prop) != ((void*)0 ); (prop) = ((prop)->prop_entry.tqe_next)) { | |||
6029 | if (ikev2_valid_proposal(prop, NULL((void*)0), NULL((void*)0), NULL((void*)0)) != 0) | |||
6030 | continue; | |||
6031 | ||||
6032 | RB_FOREACH(flow, iked_flows, &sa->sa_policy->pol_flows)for ((flow) = iked_flows_RB_MINMAX(&sa->sa_policy-> pol_flows, -1); (flow) != ((void*)0); (flow) = iked_flows_RB_NEXT (flow)) { | |||
6033 | ||||
6034 | if ((flowa = calloc(1, sizeof(*flowa))) == NULL((void*)0)) { | |||
6035 | log_debug("%s: failed to get flow", __func__); | |||
6036 | goto done; | |||
6037 | } | |||
6038 | ||||
6039 | memcpy(flowa, flow, sizeof(*flow)); | |||
6040 | flowa->flow_dir = IPSP_DIRECTION_OUT0x2; | |||
6041 | flowa->flow_saproto = ic ? IKEV2_SAPROTO_IPCOMP204 : | |||
6042 | prop->prop_protoid; | |||
6043 | flowa->flow_rdomain = sa->sa_policy->pol_rdomain; | |||
6044 | flowa->flow_local = &sa->sa_local; | |||
6045 | flowa->flow_peer = &sa->sa_peer; | |||
6046 | flowa->flow_ikesa = sa; | |||
6047 | if (ikev2_cp_fixflow(sa, flow, flowa) == -1) { | |||
6048 | flow_free(flowa); | |||
6049 | continue; | |||
6050 | } | |||
6051 | ||||
6052 | skip = 0; | |||
6053 | TAILQ_FOREACH(saflow, &sa->sa_flows, flow_entry)for((saflow) = ((&sa->sa_flows)->tqh_first); (saflow ) != ((void*)0); (saflow) = ((saflow)->flow_entry.tqe_next )) { | |||
6054 | if (flow_equal(saflow, flowa)) { | |||
6055 | skip = 1; | |||
6056 | break; | |||
6057 | } | |||
6058 | } | |||
6059 | if (skip) { | |||
6060 | flow_free(flowa); | |||
6061 | continue; | |||
6062 | } | |||
6063 | ||||
6064 | if ((flowb = calloc(1, sizeof(*flowb))) == NULL((void*)0)) { | |||
6065 | log_debug("%s: failed to get flow", __func__); | |||
6066 | flow_free(flowa); | |||
6067 | goto done; | |||
6068 | } | |||
6069 | ||||
6070 | memcpy(flowb, flowa, sizeof(*flow)); | |||
6071 | ||||
6072 | flowb->flow_dir = IPSP_DIRECTION_IN0x1; | |||
6073 | memcpy(&flowb->flow_src, &flow->flow_dst, | |||
6074 | sizeof(flow->flow_dst)); | |||
6075 | memcpy(&flowb->flow_dst, &flow->flow_src, | |||
6076 | sizeof(flow->flow_src)); | |||
6077 | if (ikev2_cp_fixflow(sa, flow, flowb) == -1) { | |||
6078 | flow_free(flowa); | |||
6079 | flow_free(flowb); | |||
6080 | continue; | |||
6081 | } | |||
6082 | ||||
6083 | TAILQ_INSERT_TAIL(&sa->sa_flows, flowa, flow_entry)do { (flowa)->flow_entry.tqe_next = ((void*)0); (flowa)-> flow_entry.tqe_prev = (&sa->sa_flows)->tqh_last; *( &sa->sa_flows)->tqh_last = (flowa); (&sa->sa_flows )->tqh_last = &(flowa)->flow_entry.tqe_next; } while (0); | |||
6084 | TAILQ_INSERT_TAIL(&sa->sa_flows, flowb, flow_entry)do { (flowb)->flow_entry.tqe_next = ((void*)0); (flowb)-> flow_entry.tqe_prev = (&sa->sa_flows)->tqh_last; *( &sa->sa_flows)->tqh_last = (flowb); (&sa->sa_flows )->tqh_last = &(flowb)->flow_entry.tqe_next; } while (0); | |||
6085 | } | |||
6086 | } | |||
6087 | ||||
6088 | /* create the CHILD SAs using the key material */ | |||
6089 | TAILQ_FOREACH(prop, proposals, prop_entry)for((prop) = ((proposals)->tqh_first); (prop) != ((void*)0 ); (prop) = ((prop)->prop_entry.tqe_next)) { | |||
6090 | if (ikev2_valid_proposal(prop, &encrxf, &integrxf, &esn) != 0) | |||
6091 | continue; | |||
6092 | ||||
6093 | spi = 0; | |||
6094 | ||||
6095 | if ((csa = calloc(1, sizeof(*csa))) == NULL((void*)0)) { | |||
6096 | log_debug("%s: failed to get CHILD SA", __func__); | |||
6097 | goto done; | |||
6098 | } | |||
6099 | ||||
6100 | csa->csa_saproto = prop->prop_protoid; | |||
6101 | csa->csa_ikesa = sa; | |||
6102 | csa->csa_spi.spi_protoid = prop->prop_protoid; | |||
6103 | csa->csa_esn = esn; | |||
6104 | csa->csa_transport = sa->sa_use_transport_mode; | |||
6105 | sa->sa_used_transport_mode = sa->sa_use_transport_mode; | |||
6106 | ||||
6107 | if (pfs && group) | |||
6108 | csa->csa_pfsgrpid = group->id; | |||
6109 | ||||
6110 | /* Set up responder's SPIs */ | |||
6111 | if (initiator) { | |||
6112 | csa->csa_dir = IPSP_DIRECTION_OUT0x2; | |||
6113 | csa->csa_local = &sa->sa_local; | |||
6114 | csa->csa_peer = &sa->sa_peer; | |||
6115 | csa->csa_peerspi = prop->prop_localspi.spi; | |||
6116 | csa->csa_spi.spi = prop->prop_peerspi.spi; | |||
6117 | csa->csa_spi.spi_size = prop->prop_peerspi.spi_size; | |||
6118 | } else { | |||
6119 | csa->csa_dir = IPSP_DIRECTION_IN0x1; | |||
6120 | csa->csa_local = &sa->sa_peer; | |||
6121 | csa->csa_peer = &sa->sa_local; | |||
6122 | ||||
6123 | if ((ret = pfkey_sa_init(env, csa, | |||
6124 | &spi)) != 0) | |||
6125 | goto done; | |||
6126 | csa->csa_allocated = 1; | |||
6127 | ||||
6128 | csa->csa_peerspi = prop->prop_peerspi.spi; | |||
6129 | csa->csa_spi.spi = prop->prop_localspi.spi = spi; | |||
6130 | csa->csa_spi.spi_size = 4; | |||
6131 | } | |||
6132 | ||||
6133 | if (encrxf && (csa->csa_encrkey = ibuf_get(keymat, | |||
6134 | encrxf->xform_keylength / 8)) == NULL((void*)0)) { | |||
6135 | log_debug("%s: failed to get CHILD SA encryption key", | |||
6136 | __func__); | |||
6137 | goto done; | |||
6138 | } | |||
6139 | if (integrxf && (csa->csa_integrkey = ibuf_get(keymat, | |||
6140 | integrxf->xform_keylength / 8)) == NULL((void*)0)) { | |||
6141 | log_debug("%s: failed to get CHILD SA integrity key", | |||
6142 | __func__); | |||
6143 | goto done; | |||
6144 | } | |||
6145 | if (encrxf) | |||
6146 | csa->csa_encrid = encrxf->xform_id; | |||
6147 | if (integrxf) | |||
6148 | csa->csa_integrid = integrxf->xform_id; | |||
6149 | ||||
6150 | if ((csb = calloc(1, sizeof(*csb))) == NULL((void*)0)) { | |||
6151 | log_debug("%s: failed to get CHILD SA", __func__); | |||
6152 | goto done; | |||
6153 | } | |||
6154 | ||||
6155 | memcpy(csb, csa, sizeof(*csb)); | |||
6156 | ||||
6157 | /* Set up initiator's SPIs */ | |||
6158 | csb->csa_spi.spi = csa->csa_peerspi; | |||
6159 | csb->csa_peerspi = csa->csa_spi.spi; | |||
6160 | csb->csa_allocated = csa->csa_allocated ? 0 : 1; | |||
6161 | csb->csa_dir = csa->csa_dir == IPSP_DIRECTION_IN0x1 ? | |||
6162 | IPSP_DIRECTION_OUT0x2 : IPSP_DIRECTION_IN0x1; | |||
6163 | csb->csa_local = csa->csa_peer; | |||
6164 | csb->csa_peer = csa->csa_local; | |||
6165 | ||||
6166 | if (encrxf && (csb->csa_encrkey = ibuf_get(keymat, | |||
6167 | encrxf->xform_keylength / 8)) == NULL((void*)0)) { | |||
6168 | log_debug("%s: failed to get CHILD SA encryption key", | |||
6169 | __func__); | |||
6170 | goto done; | |||
6171 | } | |||
6172 | if (integrxf && (csb->csa_integrkey = ibuf_get(keymat, | |||
6173 | integrxf->xform_keylength / 8)) == NULL((void*)0)) { | |||
6174 | log_debug("%s: failed to get CHILD SA integrity key", | |||
6175 | __func__); | |||
6176 | goto done; | |||
6177 | } | |||
6178 | ||||
6179 | if (ic && prop->prop_protoid == IKEV2_SAPROTO_ESP3) { | |||
6180 | /* add IPCOMP SAs */ | |||
6181 | if ((csa2 = calloc(1, sizeof(*csa2))) == NULL((void*)0)) { | |||
6182 | log_debug("%s: failed to get CHILD SA", __func__); | |||
6183 | goto done; | |||
6184 | } | |||
6185 | if ((csb2 = calloc(1, sizeof(*csb2))) == NULL((void*)0)) { | |||
6186 | log_debug("%s: failed to get CHILD SA", __func__); | |||
6187 | goto done; | |||
6188 | } | |||
6189 | ||||
6190 | csa2->csa_saproto = IKEV2_SAPROTO_IPCOMP204; | |||
6191 | csa2->csa_ikesa = csa->csa_ikesa; | |||
6192 | csa2->csa_dir = csa->csa_dir; | |||
6193 | csa2->csa_local = csa->csa_local; | |||
6194 | csa2->csa_peer = csa->csa_peer; | |||
6195 | if (initiator) { | |||
6196 | csa2->csa_spi.spi = ic->ic_cpi_out; | |||
6197 | csa2->csa_peerspi = ic->ic_cpi_in; | |||
6198 | csa2->csa_allocated = 0; | |||
6199 | /* make sure IPCOMP CPIs are not reused */ | |||
6200 | ic->ic_transform = 0; | |||
6201 | ic->ic_cpi_in = ic->ic_cpi_out = 0; | |||
6202 | } else { | |||
6203 | if ((ret = pfkey_sa_init(env, csa2, | |||
6204 | &spi)) != 0) | |||
6205 | goto done; | |||
6206 | ic->ic_cpi_in = spi; | |||
6207 | csa2->csa_spi.spi = ic->ic_cpi_in; | |||
6208 | csa2->csa_peerspi = ic->ic_cpi_out; | |||
6209 | csa2->csa_allocated = 1; | |||
6210 | } | |||
6211 | csa2->csa_spi.spi_size = 2; | |||
6212 | ||||
6213 | memcpy(csb2, csa2, sizeof(*csb2)); | |||
6214 | csb2->csa_spi.spi = csa2->csa_peerspi; | |||
6215 | csb2->csa_peerspi = csa2->csa_spi.spi; | |||
6216 | csb2->csa_allocated = csa2->csa_allocated ? 0 : 1; | |||
6217 | csb2->csa_dir = csa2->csa_dir == IPSP_DIRECTION_IN0x1 ? | |||
6218 | IPSP_DIRECTION_OUT0x2 : IPSP_DIRECTION_IN0x1; | |||
6219 | csb2->csa_local = csa2->csa_peer; | |||
6220 | csb2->csa_peer = csa2->csa_local; | |||
6221 | ||||
6222 | /* link IPComp and ESP SAs, switch ESP to transport */ | |||
6223 | csa->csa_transport = 1; | |||
6224 | csa->csa_bundled = csa2; | |||
6225 | csa2->csa_bundled = csa; | |||
6226 | csb->csa_transport = 1; | |||
6227 | csb->csa_bundled = csb2; | |||
6228 | csb2->csa_bundled = csb; | |||
6229 | csa2 = NULL((void*)0); | |||
6230 | csb2 = NULL((void*)0); | |||
6231 | ||||
6232 | ic = NULL((void*)0); | |||
6233 | } | |||
6234 | ||||
6235 | TAILQ_INSERT_TAIL(&sa->sa_childsas, csa, csa_entry)do { (csa)->csa_entry.tqe_next = ((void*)0); (csa)->csa_entry .tqe_prev = (&sa->sa_childsas)->tqh_last; *(&sa ->sa_childsas)->tqh_last = (csa); (&sa->sa_childsas )->tqh_last = &(csa)->csa_entry.tqe_next; } while ( 0); | |||
6236 | TAILQ_INSERT_TAIL(&sa->sa_childsas, csb, csa_entry)do { (csb)->csa_entry.tqe_next = ((void*)0); (csb)->csa_entry .tqe_prev = (&sa->sa_childsas)->tqh_last; *(&sa ->sa_childsas)->tqh_last = (csb); (&sa->sa_childsas )->tqh_last = &(csb)->csa_entry.tqe_next; } while ( 0); | |||
6237 | ||||
6238 | csa->csa_peersa = csb; | |||
6239 | csb->csa_peersa = csa; | |||
6240 | csa = NULL((void*)0); | |||
6241 | csb = NULL((void*)0); | |||
6242 | } | |||
6243 | ||||
6244 | ret = 0; | |||
6245 | done: | |||
6246 | sa->sa_use_transport_mode = 0; /* reset state after use */ | |||
6247 | ibuf_release(dhsecret); | |||
6248 | ibuf_release(keymat); | |||
6249 | ibuf_release(seed); | |||
6250 | childsa_free(csa); | |||
6251 | childsa_free(csb); | |||
6252 | childsa_free(csa2); | |||
6253 | childsa_free(csb2); | |||
6254 | ||||
6255 | return (ret); | |||
6256 | } | |||
6257 | ||||
6258 | int | |||
6259 | ikev2_childsa_enable(struct iked *env, struct iked_sa *sa) | |||
6260 | { | |||
6261 | struct iked_childsa *csa, *ocsa, *ipcomp; | |||
6262 | struct iked_flow *flow, *oflow; | |||
6263 | int peer_changed, reload; | |||
6264 | struct ibuf *spibuf = NULL((void*)0); | |||
6265 | struct ibuf *flowbuf = NULL((void*)0); | |||
6266 | char *buf; | |||
6267 | uint16_t encrid = 0, integrid = 0, groupid = 0; | |||
6268 | size_t encrlen = 0, integrlen = 0; | |||
6269 | int esn = 0; | |||
6270 | ||||
6271 | TAILQ_FOREACH(csa, &sa->sa_childsas, csa_entry)for((csa) = ((&sa->sa_childsas)->tqh_first); (csa) != ((void*)0); (csa) = ((csa)->csa_entry.tqe_next)) { | |||
6272 | if (csa->csa_rekey || csa->csa_loaded) | |||
6273 | continue; | |||
6274 | ||||
6275 | ipcomp = csa->csa_bundled; | |||
6276 | if (ipcomp && ipcomp->csa_loaded) { | |||
6277 | log_info("%s: IPCOMP SA for CHILD SA spi %s" | |||
6278 | " already loaded", __func__, | |||
6279 | print_spi(csa->csa_spi.spi, csa->csa_spi.spi_size)); | |||
6280 | continue; | |||
6281 | } | |||
6282 | ||||
6283 | if (pfkey_sa_add(env, csa, NULL((void*)0)) != 0) { | |||
6284 | log_debug("%s: failed to load CHILD SA spi %s", | |||
6285 | __func__, print_spi(csa->csa_spi.spi, | |||
6286 | csa->csa_spi.spi_size)); | |||
6287 | return (-1); | |||
6288 | } | |||
6289 | if (ipcomp) { | |||
6290 | if (pfkey_sa_add(env, ipcomp, csa) != 0) { | |||
6291 | log_debug("%s: failed to load IPCOMP spi %s", | |||
6292 | __func__, print_spi(ipcomp->csa_spi.spi, | |||
6293 | ipcomp->csa_spi.spi_size)); | |||
6294 | ipcomp = NULL((void*)0); | |||
6295 | } | |||
6296 | } | |||
6297 | ||||
6298 | if ((ocsa = RB_FIND(iked_activesas, &env->sc_activesas, csa)iked_activesas_RB_FIND(&env->sc_activesas, csa)) | |||
6299 | != NULL((void*)0)) { | |||
6300 | log_debug("%s: replaced CHILD SA %p with %p spi %s", | |||
6301 | __func__, ocsa, csa, print_spi(ocsa->csa_spi.spi, | |||
6302 | ocsa->csa_spi.spi_size)); | |||
6303 | ocsa->csa_loaded = 0; | |||
6304 | ocsa->csa_rekey = 1; /* prevent re-loading */ | |||
6305 | RB_REMOVE(iked_activesas, &env->sc_activesas, ocsa)iked_activesas_RB_REMOVE(&env->sc_activesas, ocsa); | |||
6306 | } | |||
6307 | ||||
6308 | RB_INSERT(iked_activesas, &env->sc_activesas, csa)iked_activesas_RB_INSERT(&env->sc_activesas, csa); | |||
6309 | ||||
6310 | log_debug("%s: loaded CHILD SA spi %s", __func__, | |||
6311 | print_spi(csa->csa_spi.spi, csa->csa_spi.spi_size)); | |||
6312 | ||||
6313 | /* append SPI to log buffer */ | |||
6314 | if (ibuf_strlen(spibuf)) | |||
6315 | ibuf_strcat(&spibuf, ", "); | |||
6316 | ibuf_strcat(&spibuf, print_spi(csa->csa_spi.spi, | |||
6317 | csa->csa_spi.spi_size)); | |||
6318 | if (ipcomp) { | |||
6319 | ibuf_strcat(&spibuf, "("); | |||
6320 | ibuf_strcat(&spibuf, print_spi(ipcomp->csa_spi.spi, | |||
6321 | ipcomp->csa_spi.spi_size)); | |||
6322 | ibuf_strcat(&spibuf, ")"); | |||
6323 | } | |||
6324 | if (!encrid) { | |||
6325 | encrid = csa->csa_encrid; | |||
6326 | encrlen = ibuf_length(csa->csa_encrkey); | |||
6327 | switch (encrid) { | |||
6328 | case IKEV2_XFORMENCR_AES_GCM_1620: | |||
6329 | case IKEV2_XFORMENCR_AES_GCM_1219: | |||
6330 | encrlen -= 4; | |||
6331 | break; | |||
6332 | default: | |||
6333 | if (!csa->csa_integrid) | |||
6334 | break; | |||
6335 | integrid = csa->csa_integrid; | |||
6336 | integrlen = ibuf_length(csa->csa_integrkey); | |||
6337 | } | |||
6338 | groupid = csa->csa_pfsgrpid; | |||
6339 | esn = csa->csa_esn; | |||
6340 | } | |||
6341 | } | |||
6342 | ||||
6343 | peer_changed = (memcmp(&sa->sa_peer_loaded, &sa->sa_peer, | |||
6344 | sizeof(sa->sa_peer_loaded)) != 0); | |||
6345 | ||||
6346 | TAILQ_FOREACH(flow, &sa->sa_flows, flow_entry)for((flow) = ((&sa->sa_flows)->tqh_first); (flow) != ((void*)0); (flow) = ((flow)->flow_entry.tqe_next)) { | |||
6347 | /* re-load the flow if the peer for the flow has changed */ | |||
6348 | reload = 0; | |||
6349 | if (flow->flow_loaded) { | |||
6350 | if (!peer_changed) { | |||
6351 | log_debug("%s: flow already loaded %p", | |||
6352 | __func__, flow); | |||
6353 | continue; | |||
6354 | } | |||
6355 | RB_REMOVE(iked_flows, &env->sc_activeflows, flow)iked_flows_RB_REMOVE(&env->sc_activeflows, flow); | |||
6356 | (void)pfkey_flow_delete(env, flow); | |||
6357 | flow->flow_loaded = 0; /* we did RB_REMOVE */ | |||
6358 | reload = 1; | |||
6359 | } | |||
6360 | ||||
6361 | if (pfkey_flow_add(env, flow) != 0) { | |||
6362 | log_debug("%s: failed to load flow", __func__); | |||
6363 | return (-1); | |||
6364 | } | |||
6365 | ||||
6366 | if ((oflow = RB_FIND(iked_flows, &env->sc_activeflows, flow)iked_flows_RB_FIND(&env->sc_activeflows, flow)) | |||
6367 | != NULL((void*)0)) { | |||
6368 | log_debug("%s: replaced old flow %p with %p", | |||
6369 | __func__, oflow, flow); | |||
6370 | oflow->flow_loaded = 0; | |||
6371 | RB_REMOVE(iked_flows, &env->sc_activeflows, oflow)iked_flows_RB_REMOVE(&env->sc_activeflows, oflow); | |||
6372 | } | |||
6373 | ||||
6374 | RB_INSERT(iked_flows, &env->sc_activeflows, flow)iked_flows_RB_INSERT(&env->sc_activeflows, flow); | |||
6375 | ||||
6376 | log_debug("%s: %sloaded flow %p", __func__, | |||
6377 | reload ? "re" : "", flow); | |||
6378 | ||||
6379 | /* append flow to log buffer */ | |||
6380 | if (flow->flow_dir == IPSP_DIRECTION_OUT0x2 && | |||
6381 | asprintf(&buf, "%s-%s/%d=%s/%d(%u)%s", | |||
6382 | print_map(flow->flow_saproto, ikev2_saproto_map), | |||
6383 | print_host((struct sockaddr *)&flow->flow_src.addr, NULL((void*)0), 0), | |||
6384 | flow->flow_src.addr_mask, | |||
6385 | print_host((struct sockaddr *)&flow->flow_dst.addr, NULL((void*)0), 0), | |||
6386 | flow->flow_dst.addr_mask, | |||
6387 | flow->flow_ipproto, | |||
6388 | reload ? "-R" : "") != -1) { | |||
6389 | if (ibuf_strlen(flowbuf)) | |||
6390 | ibuf_strcat(&flowbuf, ", "); | |||
6391 | ibuf_strcat(&flowbuf, buf); | |||
6392 | free(buf); | |||
6393 | } | |||
6394 | } | |||
6395 | ||||
6396 | /* remember the current address for ikev2_update_sa_addresses() */ | |||
6397 | if (peer_changed) { | |||
6398 | memcpy(&sa->sa_peer_loaded, &sa->sa_peer, | |||
6399 | sizeof(sa->sa_peer_loaded)); | |||
6400 | log_debug("%s: remember SA peer %s", __func__, | |||
6401 | print_host((struct sockaddr *)&sa->sa_peer_loaded.addr, | |||
6402 | NULL((void*)0), 0)); | |||
6403 | } | |||
6404 | ||||
6405 | if (ibuf_strlen(spibuf)) { | |||
6406 | log_info("%s: loaded SPIs: %.*s (enc %s%s%s%s%s%s)", | |||
6407 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
6408 | ibuf_strlen(spibuf), ibuf_data(spibuf), | |||
6409 | print_xf(encrid, encrlen, ipsecencxfs), | |||
6410 | integrid ? " auth " : "", | |||
6411 | integrid ? print_xf(integrid, integrlen, authxfs) : "", | |||
6412 | groupid ? " group " : "", | |||
6413 | groupid ? print_xf(groupid, 0, groupxfs) : "", | |||
6414 | esn ? " esn" : ""); | |||
6415 | } | |||
6416 | if (ibuf_strlen(flowbuf)) | |||
6417 | log_info("%s: loaded flows: %.*s", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
6418 | ibuf_strlen(flowbuf), ibuf_data(flowbuf)); | |||
6419 | ibuf_release(spibuf); | |||
6420 | ibuf_release(flowbuf); | |||
6421 | return (0); | |||
6422 | } | |||
6423 | ||||
6424 | int | |||
6425 | ikev2_childsa_delete(struct iked *env, struct iked_sa *sa, uint8_t saproto, | |||
6426 | uint64_t spi, uint64_t *spiptr, int cleanup) | |||
6427 | { | |||
6428 | struct iked_childsa *csa, *csatmp = NULL((void*)0), *ipcomp; | |||
6429 | uint64_t peerspi = 0; | |||
6430 | int found = 0; | |||
6431 | ||||
6432 | TAILQ_FOREACH_SAFE(csa, &sa->sa_childsas, csa_entry, csatmp)for ((csa) = ((&sa->sa_childsas)->tqh_first); (csa) != ((void*)0) && ((csatmp) = ((csa)->csa_entry.tqe_next ), 1); (csa) = (csatmp)) { | |||
6433 | if ((saproto && csa->csa_saproto != saproto) || | |||
6434 | (spi && (csa->csa_spi.spi != spi && | |||
6435 | csa->csa_peerspi != spi)) || | |||
6436 | (cleanup && csa->csa_loaded)) | |||
6437 | continue; | |||
6438 | ||||
6439 | if (csa->csa_loaded) | |||
6440 | RB_REMOVE(iked_activesas, &env->sc_activesas, csa)iked_activesas_RB_REMOVE(&env->sc_activesas, csa); | |||
6441 | ||||
6442 | if (pfkey_sa_delete(env, csa) != 0) | |||
6443 | log_info("%s: failed to delete CHILD SA spi %s", | |||
6444 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), print_spi(csa->csa_spi.spi, | |||
6445 | csa->csa_spi.spi_size)); | |||
6446 | else | |||
6447 | log_debug("%s: deleted CHILD SA spi %s", | |||
6448 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), print_spi(csa->csa_spi.spi, | |||
6449 | csa->csa_spi.spi_size)); | |||
6450 | found++; | |||
6451 | ||||
6452 | if (spi && csa->csa_spi.spi == spi) | |||
6453 | peerspi = csa->csa_peerspi; | |||
6454 | ||||
6455 | ipcomp = csa->csa_bundled; | |||
6456 | if (ipcomp) { | |||
6457 | if (ipcomp->csa_loaded) { | |||
6458 | if (pfkey_sa_delete(env, ipcomp) != 0) | |||
6459 | log_info("%s: failed to delete IPCOMP" | |||
6460 | " SA spi %s", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
6461 | print_spi(ipcomp->csa_spi.spi, | |||
6462 | ipcomp->csa_spi.spi_size)); | |||
6463 | else | |||
6464 | log_debug("%s: deleted IPCOMP SA spi %s", | |||
6465 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
6466 | print_spi(ipcomp->csa_spi.spi, | |||
6467 | ipcomp->csa_spi.spi_size)); | |||
6468 | } | |||
6469 | childsa_free(ipcomp); | |||
6470 | } | |||
6471 | TAILQ_REMOVE(&sa->sa_childsas, csa, csa_entry)do { if (((csa)->csa_entry.tqe_next) != ((void*)0)) (csa)-> csa_entry.tqe_next->csa_entry.tqe_prev = (csa)->csa_entry .tqe_prev; else (&sa->sa_childsas)->tqh_last = (csa )->csa_entry.tqe_prev; *(csa)->csa_entry.tqe_prev = (csa )->csa_entry.tqe_next; ; ; } while (0); | |||
6472 | childsa_free(csa); | |||
6473 | } | |||
6474 | ||||
6475 | if (spiptr) | |||
6476 | *spiptr = peerspi; | |||
6477 | ||||
6478 | return (found ? 0 : -1); | |||
6479 | } | |||
6480 | ||||
6481 | int | |||
6482 | ikev2_valid_proposal(struct iked_proposal *prop, | |||
6483 | struct iked_transform **exf, struct iked_transform **ixf, int *esn) | |||
6484 | { | |||
6485 | struct iked_transform *xform, *encrxf, *integrxf; | |||
6486 | unsigned int i, doesn = 0; | |||
6487 | ||||
6488 | switch (prop->prop_protoid) { | |||
6489 | case IKEV2_SAPROTO_ESP3: | |||
6490 | case IKEV2_SAPROTO_AH2: | |||
6491 | break; | |||
6492 | default: | |||
6493 | return (-1); | |||
6494 | } | |||
6495 | ||||
6496 | encrxf = integrxf = NULL((void*)0); | |||
6497 | for (i = 0; i < prop->prop_nxforms; i++) { | |||
6498 | xform = prop->prop_xforms + i; | |||
6499 | if (xform->xform_type == IKEV2_XFORMTYPE_ENCR1) | |||
6500 | encrxf = xform; | |||
6501 | else if (xform->xform_type == IKEV2_XFORMTYPE_INTEGR3) | |||
6502 | integrxf = xform; | |||
6503 | else if (xform->xform_type == IKEV2_XFORMTYPE_ESN5 && | |||
6504 | xform->xform_id == IKEV2_XFORMESN_ESN1) | |||
6505 | doesn = 1; | |||
6506 | } | |||
6507 | ||||
6508 | if (prop->prop_protoid == IKEV2_SAPROTO_IKE1) { | |||
6509 | if (encrxf == NULL((void*)0) || integrxf == NULL((void*)0)) | |||
6510 | return (-1); | |||
6511 | } else if (prop->prop_protoid == IKEV2_SAPROTO_AH2) { | |||
6512 | if (integrxf == NULL((void*)0)) | |||
6513 | return (-1); | |||
6514 | } else if (prop->prop_protoid == IKEV2_SAPROTO_ESP3) { | |||
6515 | if (encrxf == NULL((void*)0)) | |||
6516 | return (-1); | |||
6517 | } | |||
6518 | ||||
6519 | if (exf) | |||
6520 | *exf = encrxf; | |||
6521 | if (ixf) | |||
6522 | *ixf = integrxf; | |||
6523 | if (esn) | |||
6524 | *esn = doesn; | |||
6525 | ||||
6526 | return (0); | |||
6527 | } | |||
6528 | ||||
6529 | /* return 0 if processed, -1 if busy */ | |||
6530 | int | |||
6531 | ikev2_child_sa_acquire(struct iked *env, struct iked_flow *acquire) | |||
6532 | { | |||
6533 | struct iked_flow *flow; | |||
6534 | struct iked_sa *sa; | |||
6535 | struct iked_policy pol, *p = NULL((void*)0); | |||
6536 | ||||
6537 | if (env->sc_passive) | |||
6538 | return (0); | |||
6539 | ||||
6540 | /* First try to find an active flow with IKE SA */ | |||
6541 | flow = RB_FIND(iked_flows, &env->sc_activeflows, acquire)iked_flows_RB_FIND(&env->sc_activeflows, acquire); | |||
6542 | if (!flow) { | |||
6543 | /* Otherwise try to find a matching policy */ | |||
6544 | bzero(&pol, sizeof(pol)); | |||
6545 | pol.pol_af = acquire->flow_peer->addr_af; | |||
6546 | memcpy(&pol.pol_peer, acquire->flow_peer, | |||
6547 | sizeof(pol.pol_peer)); | |||
6548 | ||||
6549 | RB_INIT(&pol.pol_flows)do { (&pol.pol_flows)->rbh_root = ((void*)0); } while ( 0); | |||
6550 | RB_INSERT(iked_flows, &pol.pol_flows, acquire)iked_flows_RB_INSERT(&pol.pol_flows, acquire); | |||
6551 | pol.pol_nflows = 1; | |||
6552 | ||||
6553 | if ((p = policy_test(env, &pol)) == NULL((void*)0)) { | |||
6554 | log_warnx("%s: flow wasn't found", __func__); | |||
6555 | return (0); | |||
6556 | } | |||
6557 | ||||
6558 | log_debug("%s: found matching policy '%s'", __func__, | |||
6559 | p->pol_name); | |||
6560 | ||||
6561 | if (ikev2_init_ike_sa_peer(env, p, | |||
6562 | &p->pol_peer, NULL((void*)0)) != 0) | |||
6563 | log_warnx("%s: failed to initiate a " | |||
6564 | "IKE_SA_INIT exchange for policy '%s'", | |||
6565 | __func__, p->pol_name); | |||
6566 | } else { | |||
6567 | log_debug("%s: found active flow", __func__); | |||
6568 | ||||
6569 | if ((sa = flow->flow_ikesa) == NULL((void*)0)) { | |||
6570 | log_warnx("%s: flow without SA", __func__); | |||
6571 | return (0); | |||
6572 | } | |||
6573 | if (sa->sa_stateflags & (IKED_REQ_CHILDSA0x0080|IKED_REQ_INF0x0100)) | |||
6574 | return (-1); /* busy, retry later */ | |||
6575 | if (ikev2_send_create_child_sa(env, sa, NULL((void*)0), | |||
6576 | flow->flow_saproto, 0) != 0) | |||
6577 | log_warnx("%s: failed to initiate a " | |||
6578 | "CREATE_CHILD_SA exchange", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
6579 | } | |||
6580 | return (0); | |||
6581 | } | |||
6582 | ||||
6583 | void | |||
6584 | ikev2_disable_rekeying(struct iked *env, struct iked_sa *sa) | |||
6585 | { | |||
6586 | struct iked_childsa *csa; | |||
6587 | ||||
6588 | TAILQ_FOREACH(csa, &sa->sa_childsas, csa_entry)for((csa) = ((&sa->sa_childsas)->tqh_first); (csa) != ((void*)0); (csa) = ((csa)->csa_entry.tqe_next)) { | |||
6589 | csa->csa_persistent = 1; | |||
6590 | csa->csa_rekey = 0; | |||
6591 | } | |||
6592 | ||||
6593 | (void)ikev2_childsa_delete(env, sa, 0, 0, NULL((void*)0), 1); | |||
6594 | } | |||
6595 | ||||
6596 | /* return 0 if processed, -1 if busy */ | |||
6597 | int | |||
6598 | ikev2_child_sa_rekey(struct iked *env, struct iked_spi *rekey) | |||
6599 | { | |||
6600 | struct iked_childsa *csa, key; | |||
6601 | struct iked_sa *sa; | |||
6602 | ||||
6603 | key.csa_spi = *rekey; | |||
6604 | csa = RB_FIND(iked_activesas, &env->sc_activesas, &key)iked_activesas_RB_FIND(&env->sc_activesas, &key); | |||
6605 | if (!csa) | |||
6606 | return (0); | |||
6607 | ||||
6608 | if (csa->csa_rekey) /* See if it's already taken care of */ | |||
6609 | return (0); | |||
6610 | if ((sa = csa->csa_ikesa) == NULL((void*)0)) { | |||
6611 | log_warnx("%s: SA %s doesn't have a parent SA", __func__, | |||
6612 | print_spi(rekey->spi, rekey->spi_size)); | |||
6613 | return (0); | |||
6614 | } | |||
6615 | if (!sa_stateok(sa, IKEV2_STATE_ESTABLISHED9)) { | |||
6616 | log_warnx("%s: not established, SPI %s", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
6617 | print_spi(rekey->spi, rekey->spi_size)); | |||
6618 | return (0); | |||
6619 | } | |||
6620 | if (sa->sa_stateflags & (IKED_REQ_CHILDSA0x0080|IKED_REQ_INF0x0100)) { | |||
6621 | log_info("%s: busy, retrying, SPI %s", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
6622 | print_spi(rekey->spi, rekey->spi_size)); | |||
6623 | return (-1); /* busy, retry later */ | |||
6624 | } | |||
6625 | if (sa->sa_tmpfail) { | |||
6626 | log_info("%s: peer busy, retrying, SPI %s", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
6627 | print_spi(rekey->spi, rekey->spi_size)); | |||
6628 | return (-1); /* peer is busy, retry later */ | |||
6629 | } | |||
6630 | if (csa->csa_allocated) /* Peer SPI died first, get the local one */ | |||
6631 | rekey->spi = csa->csa_peerspi; | |||
6632 | if (ikev2_send_create_child_sa(env, sa, rekey, rekey->spi_protoid, 0)) | |||
6633 | log_warnx("%s: failed to initiate a CREATE_CHILD_SA exchange", | |||
6634 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
6635 | return (0); | |||
6636 | } | |||
6637 | ||||
6638 | /* return 0 if processed, -1 if busy */ | |||
6639 | int | |||
6640 | ikev2_child_sa_drop(struct iked *env, struct iked_spi *drop) | |||
6641 | { | |||
6642 | struct ibuf *buf = NULL((void*)0); | |||
6643 | struct iked_childsa *csa, key; | |||
6644 | struct iked_sa *sa; | |||
6645 | struct ikev2_delete *del; | |||
6646 | uint32_t spi32; | |||
6647 | ||||
6648 | key.csa_spi = *drop; | |||
6649 | csa = RB_FIND(iked_activesas, &env->sc_activesas, &key)iked_activesas_RB_FIND(&env->sc_activesas, &key); | |||
6650 | if (!csa || csa->csa_rekey) | |||
6651 | return (0); | |||
6652 | ||||
6653 | sa = csa->csa_ikesa; | |||
6654 | if (sa && (sa->sa_stateflags & (IKED_REQ_CHILDSA0x0080|IKED_REQ_INF0x0100))) { | |||
6655 | /* XXXX might loop, should we add a counter? */ | |||
6656 | log_debug("%s: parent SA busy", __func__); | |||
6657 | return (-1); /* busy, retry later */ | |||
6658 | } | |||
6659 | ||||
6660 | RB_REMOVE(iked_activesas, &env->sc_activesas, csa)iked_activesas_RB_REMOVE(&env->sc_activesas, csa); | |||
6661 | csa->csa_loaded = 0; | |||
6662 | csa->csa_rekey = 1; /* prevent re-loading */ | |||
6663 | if (sa == NULL((void*)0)) { | |||
6664 | log_debug("%s: failed to find a parent SA", __func__); | |||
6665 | return (0); | |||
6666 | } | |||
6667 | ||||
6668 | if (csa->csa_allocated) | |||
6669 | spi32 = htobe32(csa->csa_spi.spi)(__uint32_t)(__builtin_constant_p(csa->csa_spi.spi) ? (__uint32_t )(((__uint32_t)(csa->csa_spi.spi) & 0xff) << 24 | ((__uint32_t)(csa->csa_spi.spi) & 0xff00) << 8 | ((__uint32_t)(csa->csa_spi.spi) & 0xff0000) >> 8 | ((__uint32_t)(csa->csa_spi.spi) & 0xff000000) >> 24) : __swap32md(csa->csa_spi.spi)); | |||
6670 | else | |||
6671 | spi32 = htobe32(csa->csa_peerspi)(__uint32_t)(__builtin_constant_p(csa->csa_peerspi) ? (__uint32_t )(((__uint32_t)(csa->csa_peerspi) & 0xff) << 24 | ((__uint32_t)(csa->csa_peerspi) & 0xff00) << 8 | ((__uint32_t)(csa->csa_peerspi) & 0xff0000) >> 8 | ((__uint32_t)(csa->csa_peerspi) & 0xff000000) >> 24) : __swap32md(csa->csa_peerspi)); | |||
6672 | ||||
6673 | if (ikev2_childsa_delete(env, sa, csa->csa_saproto, | |||
6674 | csa->csa_peerspi, NULL((void*)0), 0)) | |||
6675 | log_debug("%s: failed to delete CHILD SA %s", __func__, | |||
6676 | print_spi(csa->csa_peerspi, drop->spi_size)); | |||
6677 | ||||
6678 | /* Send PAYLOAD_DELETE */ | |||
6679 | ||||
6680 | if ((buf = ibuf_static()) == NULL((void*)0)) | |||
6681 | return (0); | |||
6682 | if ((del = ibuf_advance(buf, sizeof(*del))) == NULL((void*)0)) | |||
6683 | goto done; | |||
6684 | del->del_protoid = drop->spi_protoid; | |||
6685 | del->del_spisize = 4; | |||
6686 | del->del_nspi = htobe16(1)(__uint16_t)(__builtin_constant_p(1) ? (__uint16_t)(((__uint16_t )(1) & 0xffU) << 8 | ((__uint16_t)(1) & 0xff00U ) >> 8) : __swap16md(1)); | |||
6687 | if (ibuf_add(buf, &spi32, sizeof(spi32))) | |||
6688 | goto done; | |||
6689 | ||||
6690 | if (ikev2_send_ike_e(env, sa, buf, IKEV2_PAYLOAD_DELETE42, | |||
6691 | IKEV2_EXCHANGE_INFORMATIONAL37, 0) == -1) | |||
6692 | goto done; | |||
6693 | ||||
6694 | sa->sa_stateflags |= IKED_REQ_INF0x0100; | |||
6695 | ||||
6696 | done: | |||
6697 | ibuf_release(buf); | |||
6698 | return (0); | |||
6699 | } | |||
6700 | ||||
6701 | int | |||
6702 | ikev2_print_static_id(struct iked_static_id *id, char *idstr, size_t idstrlen) | |||
6703 | { | |||
6704 | struct iked_id idp; | |||
6705 | int ret = -1; | |||
6706 | ||||
6707 | bzero(&idp, sizeof(idp)); | |||
6708 | if ((idp.id_buf = ibuf_new(id->id_data, id->id_length)) == NULL((void*)0)) { | |||
6709 | bzero(idstr, idstrlen); | |||
6710 | return (-1); | |||
6711 | } | |||
6712 | idp.id_type = id->id_type; | |||
6713 | idp.id_offset = id->id_offset; | |||
6714 | if (ikev2_print_id(&idp, idstr, idstrlen) == -1) { | |||
6715 | bzero(idstr, idstrlen); | |||
6716 | goto done; | |||
6717 | } | |||
6718 | ret = 0; | |||
6719 | done: | |||
6720 | ibuf_release(idp.id_buf); | |||
6721 | return (ret); | |||
6722 | } | |||
6723 | ||||
6724 | int | |||
6725 | ikev2_print_id(struct iked_id *id, char *idstr, size_t idstrlen) | |||
6726 | { | |||
6727 | uint8_t buf[BUFSIZ1024], *ptr; | |||
6728 | struct sockaddr_in *s4; | |||
6729 | struct sockaddr_in6 *s6; | |||
6730 | char *str; | |||
6731 | ssize_t len; | |||
6732 | int i; | |||
6733 | const char *type; | |||
6734 | ||||
6735 | bzero(buf, sizeof(buf)); | |||
6736 | bzero(idstr, idstrlen); | |||
6737 | ||||
6738 | if (id->id_buf == NULL((void*)0)) | |||
6739 | return (-1); | |||
6740 | ||||
6741 | len = ibuf_size(id->id_buf); | |||
6742 | ptr = ibuf_data(id->id_buf); | |||
6743 | ||||
6744 | if (len <= id->id_offset) | |||
6745 | return (-1); | |||
6746 | ||||
6747 | len -= id->id_offset; | |||
6748 | ptr += id->id_offset; | |||
6749 | ||||
6750 | type = print_map(id->id_type, ikev2_id_map); | |||
6751 | ||||
6752 | if (strlcpy(idstr, type, idstrlen) >= idstrlen || | |||
6753 | strlcat(idstr, "/", idstrlen) >= idstrlen) | |||
6754 | return (-1); | |||
6755 | ||||
6756 | idstr += strlen(idstr); | |||
6757 | idstrlen -= strlen(idstr); | |||
6758 | ||||
6759 | switch (id->id_type) { | |||
6760 | case IKEV2_ID_IPV41: | |||
6761 | s4 = (struct sockaddr_in *)buf; | |||
6762 | s4->sin_family = AF_INET2; | |||
6763 | s4->sin_len = sizeof(*s4); | |||
6764 | memcpy(&s4->sin_addr.s_addr, ptr, len); | |||
6765 | ||||
6766 | if (print_host((struct sockaddr *)s4, | |||
6767 | idstr, idstrlen) == NULL((void*)0)) | |||
6768 | return (-1); | |||
6769 | break; | |||
6770 | case IKEV2_ID_FQDN2: | |||
6771 | case IKEV2_ID_UFQDN3: | |||
6772 | if (len >= (ssize_t)sizeof(buf)) | |||
6773 | return (-1); | |||
6774 | ||||
6775 | if ((str = get_string(ptr, len)) == NULL((void*)0)) | |||
6776 | return (-1); | |||
6777 | ||||
6778 | if (strlcpy(idstr, str, idstrlen) >= idstrlen) { | |||
6779 | free(str); | |||
6780 | return (-1); | |||
6781 | } | |||
6782 | free(str); | |||
6783 | break; | |||
6784 | case IKEV2_ID_IPV65: | |||
6785 | s6 = (struct sockaddr_in6 *)buf; | |||
6786 | s6->sin6_family = AF_INET624; | |||
6787 | s6->sin6_len = sizeof(*s6); | |||
6788 | memcpy(&s6->sin6_addr, ptr, len); | |||
6789 | ||||
6790 | if (print_host((struct sockaddr *)s6, | |||
6791 | idstr, idstrlen) == NULL((void*)0)) | |||
6792 | return (-1); | |||
6793 | break; | |||
6794 | case IKEV2_ID_ASN1_DN9: | |||
6795 | if ((str = ca_asn1_name(ptr, len)) == NULL((void*)0)) | |||
6796 | return (-1); | |||
6797 | if (strlcpy(idstr, str, idstrlen) >= idstrlen) { | |||
6798 | free(str); | |||
6799 | return (-1); | |||
6800 | } | |||
6801 | free(str); | |||
6802 | break; | |||
6803 | default: | |||
6804 | /* XXX test */ | |||
6805 | for (i = 0; i < ((ssize_t)idstrlen - 1) && i < len; i++) | |||
6806 | snprintf(idstr + i, idstrlen - i, | |||
6807 | "%02x", ptr[i]); | |||
6808 | break; | |||
6809 | } | |||
6810 | ||||
6811 | return (0); | |||
6812 | } | |||
6813 | ||||
6814 | /* | |||
6815 | * If we have an IKEV2_CP_REQUEST for IKEV2_CFG_INTERNAL_IP4_ADDRESS and | |||
6816 | * if a network(pool) is configured, then select an address from that pool | |||
6817 | * and remember it in the sa_addrpool attribute. | |||
6818 | */ | |||
6819 | int | |||
6820 | ikev2_cp_setaddr(struct iked *env, struct iked_sa *sa, sa_family_t family) | |||
6821 | { | |||
6822 | struct iked_policy *pol = sa->sa_policy; | |||
6823 | struct iked_cfg *ikecfg = NULL((void*)0); | |||
6824 | const char *errstr = NULL((void*)0); | |||
6825 | int ret, pass, passes; | |||
6826 | size_t i; | |||
6827 | ||||
6828 | switch (family) { | |||
6829 | case AF_INET2: | |||
6830 | if (sa->sa_addrpool) | |||
6831 | return (0); | |||
6832 | break; | |||
6833 | case AF_INET624: | |||
6834 | if (sa->sa_addrpool6) | |||
6835 | return (0); | |||
6836 | break; | |||
6837 | default: | |||
6838 | return (-1); | |||
6839 | } | |||
6840 | if (pol->pol_ncfg == 0) | |||
6841 | return (0); | |||
6842 | /* default if no pool configured */ | |||
6843 | ret = 0; | |||
6844 | /* two passes if client requests from specific pool */ | |||
6845 | passes = (sa->sa_cp_addr != NULL((void*)0) || sa->sa_cp_addr6 != NULL((void*)0)) ? 2 : 1; | |||
6846 | for (pass = 0; pass < passes; pass++) { | |||
6847 | /* loop over all address pool configs (addr_net) */ | |||
6848 | for (i = 0; i < pol->pol_ncfg; i++) { | |||
6849 | ikecfg = &pol->pol_cfg[i]; | |||
6850 | if (!ikecfg->cfg.address.addr_net) | |||
6851 | continue; | |||
6852 | if ((family == AF_INET2 && ikecfg->cfg_type == | |||
6853 | IKEV2_CFG_INTERNAL_IP4_ADDRESS1) || | |||
6854 | (family == AF_INET624 && ikecfg->cfg_type == | |||
6855 | IKEV2_CFG_INTERNAL_IP6_ADDRESS8)) { | |||
6856 | if ((ret = ikev2_cp_setaddr_pool(env, sa, | |||
6857 | ikecfg, &errstr, family)) == 0) | |||
6858 | return (0); | |||
6859 | } | |||
6860 | } | |||
6861 | if (sa->sa_cp_addr != NULL((void*)0)) { | |||
6862 | free(sa->sa_cp_addr); | |||
6863 | sa->sa_cp_addr = NULL((void*)0); | |||
6864 | } | |||
6865 | if (sa->sa_cp_addr6 != NULL((void*)0)) { | |||
6866 | free(sa->sa_cp_addr6); | |||
6867 | sa->sa_cp_addr6 = NULL((void*)0); | |||
6868 | } | |||
6869 | } | |||
6870 | ||||
6871 | if (errstr != NULL((void*)0)) | |||
6872 | log_warnx("%s: %s", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), errstr); | |||
6873 | return (ret); | |||
6874 | } | |||
6875 | ||||
6876 | int | |||
6877 | ikev2_cp_setaddr_pool(struct iked *env, struct iked_sa *sa, | |||
6878 | struct iked_cfg *ikecfg, const char **errstr, sa_family_t family) | |||
6879 | { | |||
6880 | struct sockaddr_in *in4 = NULL((void*)0), *cfg4 = NULL((void*)0); | |||
| ||||
6881 | struct sockaddr_in6 *in6 = NULL((void*)0), *cfg6 = NULL((void*)0); | |||
6882 | struct iked_sa key; | |||
6883 | struct iked_sa *osa; | |||
6884 | char idstr[IKED_ID_SIZE1024]; | |||
6885 | struct iked_addr addr; | |||
6886 | uint32_t mask, host, lower, upper, start, nhost; | |||
6887 | int requested = 0; | |||
6888 | ||||
6889 | /* | |||
6890 | * failure: pool configured, but not requested. | |||
6891 | * If we continue, we might end up with flows where 0.0.0.0 is NOT | |||
6892 | * replaced with an address from the pool with ikev2_cp_fixaddr(). | |||
6893 | */ | |||
6894 | if (sa->sa_cp != IKEV2_CP_REQUEST1) { | |||
6895 | log_debug("%s: pool configured, but IKEV2_CP_REQUEST missing", | |||
6896 | __func__); | |||
6897 | return (-1); | |||
6898 | } | |||
6899 | bzero(&addr, sizeof(addr)); | |||
6900 | addr.addr_af = family; | |||
6901 | ||||
6902 | /* check if old IKESA for same DSTID already exists and transfer IPs */ | |||
6903 | if (env->sc_stickyaddresssc_static.st_stickyaddress && | |||
6904 | (osa = sa_dstid_lookup(env, sa)) != NULL((void*)0) && | |||
6905 | ((family == AF_INET2 && osa->sa_addrpool) || | |||
6906 | (family == AF_INET624 && osa->sa_addrpool6))) { | |||
6907 | /* we have to transfer both, even if we just need one */ | |||
6908 | if (osa->sa_addrpool) { | |||
6909 | if (RB_REMOVE(iked_addrpool, &env->sc_addrpool, osa)iked_addrpool_RB_REMOVE(&env->sc_addrpool, osa) | |||
6910 | != osa) { | |||
6911 | log_info("%s: addrpool error", | |||
6912 | SPI_SA(osa, __func__)ikev2_ikesa_info((&(osa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
6913 | return (-1); | |||
6914 | } | |||
6915 | } | |||
6916 | if (osa->sa_addrpool6) { | |||
6917 | if (RB_REMOVE(iked_addrpool6, &env->sc_addrpool6, osa)iked_addrpool6_RB_REMOVE(&env->sc_addrpool6, osa) | |||
6918 | != osa) { | |||
6919 | log_info("%s: addrpool6 error", | |||
6920 | SPI_SA(osa, __func__)ikev2_ikesa_info((&(osa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
6921 | return (-1); | |||
6922 | } | |||
6923 | } | |||
6924 | sa_dstid_remove(env, osa); | |||
6925 | sa->sa_addrpool = osa->sa_addrpool; | |||
6926 | osa->sa_addrpool = NULL((void*)0); | |||
6927 | sa->sa_addrpool6 = osa->sa_addrpool6; | |||
6928 | osa->sa_addrpool6 = NULL((void*)0); | |||
6929 | if (osa->sa_state < IKEV2_STATE_CLOSING10) { | |||
6930 | if (osa->sa_state == IKEV2_STATE_ESTABLISHED9) | |||
6931 | ikev2_disable_timer(env, osa); | |||
6932 | ikev2_ike_sa_setreason(osa, | |||
6933 | "address re-use (identical dstid)"); | |||
6934 | ikev2_ikesa_delete(env, osa, 1); | |||
6935 | timer_add(env, &osa->sa_timer, | |||
6936 | 3 * IKED_RETRANSMIT_TIMEOUT2); | |||
6937 | } | |||
6938 | if (sa->sa_addrpool) { | |||
6939 | RB_INSERT(iked_addrpool, &env->sc_addrpool, sa)iked_addrpool_RB_INSERT(&env->sc_addrpool, sa); | |||
6940 | log_info( | |||
6941 | "%s: giving up assigned address %s to IKESA %s", | |||
6942 | SPI_SA(osa, __func__)ikev2_ikesa_info((&(osa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
6943 | print_host((struct sockaddr *) | |||
6944 | &sa->sa_addrpool->addr, NULL((void*)0), 0), | |||
6945 | print_spi(sa->sa_hdr.sh_ispi, 8)); | |||
6946 | } | |||
6947 | if (sa->sa_addrpool6) { | |||
6948 | RB_INSERT(iked_addrpool6, &env->sc_addrpool6, sa)iked_addrpool6_RB_INSERT(&env->sc_addrpool6, sa); | |||
6949 | log_info( | |||
6950 | "%s: giving up assigned v6 address %s to IKESA %s", | |||
6951 | SPI_SA(osa, __func__)ikev2_ikesa_info((&(osa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
6952 | print_host((struct sockaddr *) | |||
6953 | &sa->sa_addrpool6->addr, NULL((void*)0), 0), | |||
6954 | print_spi(sa->sa_hdr.sh_ispi, 8)); | |||
6955 | } | |||
6956 | if (family == AF_INET2 && sa->sa_addrpool != NULL((void*)0)) | |||
6957 | memcpy(&addr, sa->sa_addrpool, sizeof(addr)); | |||
6958 | else if (family == AF_INET624 && sa->sa_addrpool6 != NULL((void*)0)) | |||
6959 | memcpy(&addr, sa->sa_addrpool6, sizeof(addr)); | |||
6960 | goto done; | |||
6961 | } | |||
6962 | switch (addr.addr_af) { | |||
6963 | case AF_INET2: | |||
6964 | cfg4 = (struct sockaddr_in *)&ikecfg->cfg.address.addr; | |||
6965 | mask = prefixlen2mask(ikecfg->cfg.address.addr_mask); | |||
6966 | if (sa->sa_cp_addr != NULL((void*)0)) { | |||
6967 | memcpy(&addr, sa->sa_cp_addr, sizeof(addr)); | |||
6968 | key.sa_addrpool = &addr; | |||
6969 | in4 = (struct sockaddr_in *)&addr.addr; | |||
6970 | if ((in4->sin_addr.s_addr & mask) != | |||
6971 | (cfg4->sin_addr.s_addr & mask)) { | |||
6972 | *errstr = "requested addr out of range"; | |||
6973 | return (-1); | |||
6974 | } | |||
6975 | if (RB_FIND(iked_addrpool, &env->sc_addrpool,iked_addrpool_RB_FIND(&env->sc_addrpool, &key) | |||
6976 | &key)iked_addrpool_RB_FIND(&env->sc_addrpool, &key)) { | |||
6977 | *errstr = "requested addr in use"; | |||
6978 | return (-1); | |||
6979 | } | |||
6980 | sa->sa_addrpool = sa->sa_cp_addr; | |||
6981 | sa->sa_cp_addr = NULL((void*)0); | |||
6982 | RB_INSERT(iked_addrpool, &env->sc_addrpool, sa)iked_addrpool_RB_INSERT(&env->sc_addrpool, sa); | |||
6983 | requested = 1; | |||
6984 | goto done; | |||
6985 | } | |||
6986 | in4 = (struct sockaddr_in *)&addr.addr; | |||
6987 | in4->sin_family = AF_INET2; | |||
6988 | in4->sin_len = sizeof(*in4); | |||
6989 | lower = ntohl(cfg4->sin_addr.s_addr & ~mask)(__uint32_t)(__builtin_constant_p(cfg4->sin_addr.s_addr & ~mask) ? (__uint32_t)(((__uint32_t)(cfg4->sin_addr.s_addr & ~mask) & 0xff) << 24 | ((__uint32_t)(cfg4-> sin_addr.s_addr & ~mask) & 0xff00) << 8 | ((__uint32_t )(cfg4->sin_addr.s_addr & ~mask) & 0xff0000) >> 8 | ((__uint32_t)(cfg4->sin_addr.s_addr & ~mask) & 0xff000000) >> 24) : __swap32md(cfg4->sin_addr.s_addr & ~mask)); | |||
6990 | key.sa_addrpool = &addr; | |||
6991 | break; | |||
6992 | case AF_INET624: | |||
6993 | cfg6 = (struct sockaddr_in6 *)&ikecfg->cfg.address.addr; | |||
6994 | in6 = (struct sockaddr_in6 *)&addr.addr; | |||
6995 | if (sa->sa_cp_addr6 != NULL((void*)0)) { | |||
6996 | /* XXX not yet supported */ | |||
6997 | } | |||
6998 | in6->sin6_family = AF_INET624; | |||
6999 | in6->sin6_len = sizeof(*in6); | |||
7000 | /* truncate prefixlen to get a 32-bit space */ | |||
7001 | mask = (ikecfg->cfg.address.addr_mask >= 96) | |||
7002 | ? prefixlen2mask(ikecfg->cfg.address.addr_mask - 96) | |||
7003 | : prefixlen2mask(0); | |||
7004 | memcpy(&lower, &cfg6->sin6_addr.s6_addr__u6_addr.__u6_addr8[12], sizeof(uint32_t)); | |||
7005 | lower = ntohl(lower & ~mask)(__uint32_t)(__builtin_constant_p(lower & ~mask) ? (__uint32_t )(((__uint32_t)(lower & ~mask) & 0xff) << 24 | ( (__uint32_t)(lower & ~mask) & 0xff00) << 8 | (( __uint32_t)(lower & ~mask) & 0xff0000) >> 8 | ( (__uint32_t)(lower & ~mask) & 0xff000000) >> 24 ) : __swap32md(lower & ~mask)); | |||
7006 | key.sa_addrpool6 = &addr; | |||
7007 | break; | |||
7008 | default: | |||
7009 | return (-1); | |||
7010 | } | |||
7011 | ||||
7012 | /* Note that start, upper and host are in HOST byte order */ | |||
7013 | upper = ntohl(~mask)(__uint32_t)(__builtin_constant_p(~mask) ? (__uint32_t)(((__uint32_t )(~mask) & 0xff) << 24 | ((__uint32_t)(~mask) & 0xff00) << 8 | ((__uint32_t)(~mask) & 0xff0000) >> 8 | ((__uint32_t)(~mask) & 0xff000000) >> 24) : __swap32md (~mask)); | |||
7014 | /* skip .0 address if possible */ | |||
7015 | if (lower < upper && lower == 0) | |||
7016 | lower = 1; | |||
7017 | if (upper < lower) | |||
7018 | upper = lower; | |||
7019 | /* Randomly select start from [lower, upper-1] */ | |||
7020 | start = arc4random_uniform(upper - lower) + lower; | |||
7021 | ||||
7022 | for (host = start;;) { | |||
7023 | log_debug("%s: mask %x start %x lower %x host %x upper %x", | |||
7024 | __func__, mask, start, lower, host, upper); | |||
7025 | switch (addr.addr_af) { | |||
7026 | case AF_INET2: | |||
7027 | in4->sin_addr.s_addr = | |||
7028 | (cfg4->sin_addr.s_addr & mask) | htonl(host)(__uint32_t)(__builtin_constant_p(host) ? (__uint32_t)(((__uint32_t )(host) & 0xff) << 24 | ((__uint32_t)(host) & 0xff00 ) << 8 | ((__uint32_t)(host) & 0xff0000) >> 8 | ((__uint32_t)(host) & 0xff000000) >> 24) : __swap32md (host)); | |||
| ||||
7029 | break; | |||
7030 | case AF_INET624: | |||
7031 | memcpy(in6, cfg6, sizeof(*in6)); | |||
7032 | memcpy(&nhost, &cfg6->sin6_addr.s6_addr__u6_addr.__u6_addr8[12], | |||
7033 | sizeof(uint32_t)); | |||
7034 | nhost = (nhost & mask) | htonl(host)(__uint32_t)(__builtin_constant_p(host) ? (__uint32_t)(((__uint32_t )(host) & 0xff) << 24 | ((__uint32_t)(host) & 0xff00 ) << 8 | ((__uint32_t)(host) & 0xff0000) >> 8 | ((__uint32_t)(host) & 0xff000000) >> 24) : __swap32md (host)); | |||
7035 | memcpy(&in6->sin6_addr.s6_addr__u6_addr.__u6_addr8[12], &nhost, | |||
7036 | sizeof(uint32_t)); | |||
7037 | break; | |||
7038 | default: | |||
7039 | return (-1); | |||
7040 | } | |||
7041 | if ((addr.addr_af == AF_INET2 && | |||
7042 | !RB_FIND(iked_addrpool, &env->sc_addrpool, &key)iked_addrpool_RB_FIND(&env->sc_addrpool, &key)) || | |||
7043 | (addr.addr_af == AF_INET624 && | |||
7044 | !RB_FIND(iked_addrpool6, &env->sc_addrpool6, &key)iked_addrpool6_RB_FIND(&env->sc_addrpool6, &key))) | |||
7045 | break; | |||
7046 | /* try next address */ | |||
7047 | host++; | |||
7048 | /* but skip broadcast and network address */ | |||
7049 | if (host >= upper || host < lower) | |||
7050 | host = lower; | |||
7051 | if (host == start) { | |||
7052 | *errstr = "address pool exhausted"; | |||
7053 | return (-1); /* exhausted */ | |||
7054 | } | |||
7055 | } | |||
7056 | ||||
7057 | addr.addr_mask = ikecfg->cfg.address.addr_mask; | |||
7058 | switch (addr.addr_af) { | |||
7059 | case AF_INET2: | |||
7060 | if (!key.sa_addrpool) | |||
7061 | return (-1); /* cannot happen? */ | |||
7062 | if ((sa->sa_addrpool = calloc(1, sizeof(addr))) == NULL((void*)0)) | |||
7063 | return (-1); | |||
7064 | memcpy(sa->sa_addrpool, &addr, sizeof(addr)); | |||
7065 | RB_INSERT(iked_addrpool, &env->sc_addrpool, sa)iked_addrpool_RB_INSERT(&env->sc_addrpool, sa); | |||
7066 | break; | |||
7067 | case AF_INET624: | |||
7068 | if (!key.sa_addrpool6) | |||
7069 | return (-1); /* cannot happen? */ | |||
7070 | if ((sa->sa_addrpool6 = calloc(1, sizeof(addr))) == NULL((void*)0)) | |||
7071 | return (-1); | |||
7072 | memcpy(sa->sa_addrpool6, &addr, sizeof(addr)); | |||
7073 | RB_INSERT(iked_addrpool6, &env->sc_addrpool6, sa)iked_addrpool6_RB_INSERT(&env->sc_addrpool6, sa); | |||
7074 | break; | |||
7075 | default: | |||
7076 | return (-1); | |||
7077 | } | |||
7078 | done: | |||
7079 | if (ikev2_print_id(IKESA_DSTID(sa)((sa)->sa_hdr.sh_initiator ? &(sa)->sa_rid : &( sa)->sa_iid), idstr, sizeof(idstr)) == -1) | |||
7080 | bzero(idstr, sizeof(idstr)); | |||
7081 | log_info("%sassigned address %s to %s%s", SPI_SA(sa, NULL)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((((void *)0)))), | |||
7082 | print_host((struct sockaddr *)&addr.addr, NULL((void*)0), 0), | |||
7083 | idstr, requested ? " (requested by peer)" : ""); | |||
7084 | return (0); | |||
7085 | } | |||
7086 | ||||
7087 | int | |||
7088 | ikev2_cp_request_configured(struct iked_sa *sa) | |||
7089 | { | |||
7090 | struct iked_policy *pol = sa->sa_policy; | |||
7091 | struct iked_cfg *ikecfg; | |||
7092 | unsigned int i; | |||
7093 | ||||
7094 | for (i = 0; i < pol->pol_ncfg; i++) { | |||
7095 | ikecfg = &pol->pol_cfg[i]; | |||
7096 | if (ikecfg->cfg_action == IKEV2_CP_REQUEST1) { | |||
7097 | log_debug("%s: yes", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
7098 | return 1; | |||
7099 | } | |||
7100 | } | |||
7101 | log_debug("%s: no", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
7102 | return 0; | |||
7103 | } | |||
7104 | ||||
7105 | /* | |||
7106 | * if 'addr' is 'UNSPECIFIED' replace it with sa_addrpool from | |||
7107 | * the ip-pool or the sa_cp_addr received from peer and store the | |||
7108 | * result in 'patched'. | |||
7109 | */ | |||
7110 | int | |||
7111 | ikev2_cp_fixaddr(struct iked_sa *sa, struct iked_addr *addr, | |||
7112 | struct iked_addr *patched) | |||
7113 | { | |||
7114 | struct sockaddr_in *in4; | |||
7115 | struct sockaddr_in6 *in6; | |||
7116 | struct iked_addr *naddr; | |||
7117 | ||||
7118 | if (addr->addr_net) | |||
7119 | return (-2); | |||
7120 | if (sa->sa_cp == 0) | |||
7121 | return (-1); | |||
7122 | switch (addr->addr_af) { | |||
7123 | case AF_INET2: | |||
7124 | in4 = (struct sockaddr_in *)&addr->addr; | |||
7125 | if (in4->sin_addr.s_addr) | |||
7126 | return (-2); | |||
7127 | naddr = (sa->sa_cp == IKEV2_CP_REQUEST1) ? | |||
7128 | sa->sa_addrpool : sa->sa_cp_addr; | |||
7129 | if (naddr == NULL((void*)0)) | |||
7130 | return (-1); | |||
7131 | memcpy(patched, naddr, sizeof(*patched)); | |||
7132 | patched->addr_net = 0; | |||
7133 | patched->addr_mask = 32; | |||
7134 | break; | |||
7135 | case AF_INET624: | |||
7136 | in6 = (struct sockaddr_in6 *)&addr->addr; | |||
7137 | if (!IN6_IS_ADDR_UNSPECIFIED(&in6->sin6_addr)((*(const u_int32_t *)(const void *)(&(&in6->sin6_addr )->__u6_addr.__u6_addr8[0]) == 0) && (*(const u_int32_t *)(const void *)(&(&in6->sin6_addr)->__u6_addr .__u6_addr8[4]) == 0) && (*(const u_int32_t *)(const void *)(&(&in6->sin6_addr)->__u6_addr.__u6_addr8[8] ) == 0) && (*(const u_int32_t *)(const void *)(&( &in6->sin6_addr)->__u6_addr.__u6_addr8[12]) == 0))) | |||
7138 | return (-2); | |||
7139 | naddr = (sa->sa_cp == IKEV2_CP_REQUEST1) ? | |||
7140 | sa->sa_addrpool6 : sa->sa_cp_addr6; | |||
7141 | if (naddr == NULL((void*)0)) | |||
7142 | return (-1); | |||
7143 | memcpy(patched, naddr, sizeof(*patched)); | |||
7144 | patched->addr_net = 0; | |||
7145 | patched->addr_mask = 128; | |||
7146 | break; | |||
7147 | } | |||
7148 | return (0); | |||
7149 | } | |||
7150 | ||||
7151 | /* replace unspecified address in flow with requested address */ | |||
7152 | int | |||
7153 | ikev2_cp_fixflow(struct iked_sa *sa, struct iked_flow *flow, | |||
7154 | struct iked_flow *patched) | |||
7155 | { | |||
7156 | switch (sa->sa_cp) { | |||
7157 | case IKEV2_CP_REQUEST1: | |||
7158 | if (patched->flow_dir == IPSP_DIRECTION_IN0x1) | |||
7159 | return (ikev2_cp_fixaddr(sa, &flow->flow_dst, | |||
7160 | &patched->flow_src)); | |||
7161 | else | |||
7162 | return (ikev2_cp_fixaddr(sa, &flow->flow_dst, | |||
7163 | &patched->flow_dst)); | |||
7164 | case IKEV2_CP_REPLY2: | |||
7165 | if (patched->flow_dir == IPSP_DIRECTION_IN0x1) | |||
7166 | return (ikev2_cp_fixaddr(sa, &flow->flow_src, | |||
7167 | &patched->flow_dst)); | |||
7168 | else | |||
7169 | return (ikev2_cp_fixaddr(sa, &flow->flow_src, | |||
7170 | &patched->flow_src)); | |||
7171 | default: | |||
7172 | return (0); | |||
7173 | } | |||
7174 | } | |||
7175 | ||||
7176 | int | |||
7177 | ikev2_update_sa_addresses(struct iked *env, struct iked_sa *sa) | |||
7178 | { | |||
7179 | struct iked_childsa *csa, *ipcomp; | |||
7180 | struct iked_flow *flow, *oflow; | |||
7181 | struct iked_message *msg; | |||
7182 | ||||
7183 | if (!sa_stateok(sa, IKEV2_STATE_ESTABLISHED9)) | |||
7184 | return -1; | |||
7185 | ||||
7186 | log_info("%s: old %s new %s", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
7187 | print_host((struct sockaddr *)&sa->sa_peer_loaded.addr, NULL((void*)0), 0), | |||
7188 | print_host((struct sockaddr *)&sa->sa_peer.addr, NULL((void*)0), 0)); | |||
7189 | ||||
7190 | TAILQ_FOREACH(csa, &sa->sa_childsas, csa_entry)for((csa) = ((&sa->sa_childsas)->tqh_first); (csa) != ((void*)0); (csa) = ((csa)->csa_entry.tqe_next)) { | |||
7191 | if (!csa->csa_loaded) | |||
7192 | continue; | |||
7193 | if (pfkey_sa_update_addresses(env, csa) != 0) | |||
7194 | log_debug("%s: failed to update sa", __func__); | |||
7195 | if ((ipcomp = csa->csa_bundled) != NULL((void*)0) && | |||
7196 | ipcomp->csa_loaded) | |||
7197 | if (pfkey_sa_update_addresses(env, ipcomp) | |||
7198 | != 0) | |||
7199 | log_debug("%s: failed to update sa", __func__); | |||
7200 | } | |||
7201 | ||||
7202 | /* delete and re-add flows */ | |||
7203 | TAILQ_FOREACH(flow, &sa->sa_flows, flow_entry)for((flow) = ((&sa->sa_flows)->tqh_first); (flow) != ((void*)0); (flow) = ((flow)->flow_entry.tqe_next)) { | |||
7204 | if (flow->flow_loaded) { | |||
7205 | RB_REMOVE(iked_flows, &env->sc_activeflows, flow)iked_flows_RB_REMOVE(&env->sc_activeflows, flow); | |||
7206 | (void)pfkey_flow_delete(env, flow); | |||
7207 | flow->flow_loaded = 0; | |||
7208 | } | |||
7209 | if (pfkey_flow_add(env, flow) != 0) | |||
7210 | log_debug("%s: failed to add flow %p", __func__, flow); | |||
7211 | if (!flow->flow_loaded) | |||
7212 | continue; | |||
7213 | if ((oflow = RB_FIND(iked_flows, &env->sc_activeflows, flow)iked_flows_RB_FIND(&env->sc_activeflows, flow)) | |||
7214 | != NULL((void*)0)) { | |||
7215 | log_debug("%s: replaced old flow %p with %p", | |||
7216 | __func__, oflow, flow); | |||
7217 | oflow->flow_loaded = 0; | |||
7218 | RB_REMOVE(iked_flows, &env->sc_activeflows, oflow)iked_flows_RB_REMOVE(&env->sc_activeflows, oflow); | |||
7219 | } | |||
7220 | RB_INSERT(iked_flows, &env->sc_activeflows, flow)iked_flows_RB_INSERT(&env->sc_activeflows, flow); | |||
7221 | } | |||
7222 | ||||
7223 | /* update pending requests and responses */ | |||
7224 | TAILQ_FOREACH(msg, &sa->sa_requests, msg_entry)for((msg) = ((&sa->sa_requests)->tqh_first); (msg) != ((void*)0); (msg) = ((msg)->msg_entry.tqe_next)) { | |||
7225 | msg->msg_local = sa->sa_local.addr; | |||
7226 | msg->msg_locallen = sa->sa_local.addr.ss_len; | |||
7227 | msg->msg_peer = sa->sa_peer.addr; | |||
7228 | msg->msg_peerlen = sa->sa_peer.addr.ss_len; | |||
7229 | } | |||
7230 | TAILQ_FOREACH(msg, &sa->sa_responses, msg_entry)for((msg) = ((&sa->sa_responses)->tqh_first); (msg) != ((void*)0); (msg) = ((msg)->msg_entry.tqe_next)) { | |||
7231 | msg->msg_local = sa->sa_local.addr; | |||
7232 | msg->msg_locallen = sa->sa_local.addr.ss_len; | |||
7233 | msg->msg_peer = sa->sa_peer.addr; | |||
7234 | msg->msg_peerlen = sa->sa_peer.addr.ss_len; | |||
7235 | } | |||
7236 | ||||
7237 | /* Update sa_peer_loaded, to match in-kernel information */ | |||
7238 | memcpy(&sa->sa_peer_loaded, &sa->sa_peer, sizeof(sa->sa_peer_loaded)); | |||
7239 | ||||
7240 | return 0; | |||
7241 | } | |||
7242 | ||||
7243 | void | |||
7244 | ikev2_info_sa(struct iked *env, int dolog, const char *msg, struct iked_sa *sa) | |||
7245 | { | |||
7246 | char idstr[IKED_ID_SIZE1024]; | |||
7247 | char *buf; | |||
7248 | int buflen; | |||
7249 | ||||
7250 | if (ikev2_print_id(IKESA_DSTID(sa)((sa)->sa_hdr.sh_initiator ? &(sa)->sa_rid : &( sa)->sa_iid), idstr, sizeof(idstr)) == -1) | |||
7251 | bzero(idstr, sizeof(idstr)); | |||
7252 | ||||
7253 | buflen = asprintf(&buf, | |||
7254 | "%s: %p rspi %s ispi %s %s->%s<%s>[%s] %s %c%s%s nexti %p pol %p\n", | |||
7255 | msg, sa, | |||
7256 | print_spi(sa->sa_hdr.sh_rspi, 8), | |||
7257 | print_spi(sa->sa_hdr.sh_ispi, 8), | |||
7258 | print_host((struct sockaddr *)&sa->sa_local.addr, NULL((void*)0), 0), | |||
7259 | print_host((struct sockaddr *)&sa->sa_peer.addr, NULL((void*)0), 0), | |||
7260 | idstr, | |||
7261 | sa->sa_addrpool ? | |||
7262 | print_host((struct sockaddr *)&sa->sa_addrpool->addr, NULL((void*)0), 0) : "", | |||
7263 | print_map(sa->sa_state, ikev2_state_map), | |||
7264 | sa->sa_hdr.sh_initiator ? 'i' : 'r', | |||
7265 | sa->sa_natt ? " natt" : "", | |||
7266 | sa->sa_udpencap ? " udpecap" : "", | |||
7267 | sa->sa_nexti, sa->sa_policy); | |||
7268 | ||||
7269 | if (buflen == -1 || buf == NULL((void*)0)) | |||
7270 | return; | |||
7271 | ||||
7272 | if (dolog) { | |||
7273 | if (buflen > 1) | |||
7274 | buf[buflen - 1] = '\0'; | |||
7275 | log_debug("%s", buf); | |||
7276 | } else | |||
7277 | proc_compose(&env->sc_ps, PROC_CONTROL, IMSG_CTL_SHOW_SA, | |||
7278 | buf, buflen + 1); | |||
7279 | free(buf); | |||
7280 | } | |||
7281 | ||||
7282 | void | |||
7283 | ikev2_info_csa(struct iked *env, int dolog, const char *msg, struct iked_childsa *csa) | |||
7284 | { | |||
7285 | char *buf; | |||
7286 | int buflen; | |||
7287 | ||||
7288 | buflen = asprintf(&buf, | |||
7289 | "%s: %p %s %s %s %s -> %s (%s%s%s%s) B=%p P=%p @%p\n", msg, csa, | |||
7290 | print_map(csa->csa_saproto, ikev2_saproto_map), | |||
7291 | print_spi(csa->csa_spi.spi, csa->csa_spi.spi_size), | |||
7292 | csa->csa_dir == IPSP_DIRECTION_IN0x1 ? "in" : "out", | |||
7293 | print_host((struct sockaddr *)&csa->csa_local->addr, NULL((void*)0), 0), | |||
7294 | print_host((struct sockaddr *)&csa->csa_peer->addr, NULL((void*)0), 0), | |||
7295 | csa->csa_loaded ? "L" : "", | |||
7296 | csa->csa_rekey ? "R" : "", | |||
7297 | csa->csa_allocated ? "A" : "", | |||
7298 | csa->csa_persistent ? "P" : "", | |||
7299 | csa->csa_bundled, | |||
7300 | csa->csa_peersa, | |||
7301 | csa->csa_ikesa); | |||
7302 | ||||
7303 | if (buflen == -1 || buf == NULL((void*)0)) | |||
7304 | return; | |||
7305 | ||||
7306 | if (dolog) { | |||
7307 | if (buflen > 1) | |||
7308 | buf[buflen - 1] = '\0'; | |||
7309 | log_debug("%s", buf); | |||
7310 | } else | |||
7311 | proc_compose(&env->sc_ps, PROC_CONTROL, IMSG_CTL_SHOW_SA, | |||
7312 | buf, buflen + 1); | |||
7313 | free(buf); | |||
7314 | } | |||
7315 | ||||
7316 | void | |||
7317 | ikev2_info_flow(struct iked *env, int dolog, const char *msg, struct iked_flow *flow) | |||
7318 | { | |||
7319 | char *buf; | |||
7320 | int buflen; | |||
7321 | ||||
7322 | buflen = asprintf(&buf, | |||
7323 | "%s: %p %s %s %s/%d -> %s/%d [%u]@%d (%s) @%p\n", msg, flow, | |||
7324 | print_map(flow->flow_saproto, ikev2_saproto_map), | |||
7325 | flow->flow_dir == IPSP_DIRECTION_IN0x1 ? "in" : "out", | |||
7326 | print_host((struct sockaddr *)&flow->flow_src.addr, NULL((void*)0), 0), | |||
7327 | flow->flow_src.addr_mask, | |||
7328 | print_host((struct sockaddr *)&flow->flow_dst.addr, NULL((void*)0), 0), | |||
7329 | flow->flow_dst.addr_mask, | |||
7330 | flow->flow_ipproto, | |||
7331 | flow->flow_rdomain, | |||
7332 | flow->flow_loaded ? "L" : "", | |||
7333 | flow->flow_ikesa); | |||
7334 | ||||
7335 | if (buflen == -1 || buf == NULL((void*)0)) | |||
7336 | return; | |||
7337 | ||||
7338 | if (dolog) { | |||
7339 | if (buflen > 1) | |||
7340 | buf[buflen - 1] = '\0'; | |||
7341 | log_debug("%s", buf); | |||
7342 | } else | |||
7343 | proc_compose(&env->sc_ps, PROC_CONTROL, IMSG_CTL_SHOW_SA, | |||
7344 | buf, buflen + 1); | |||
7345 | free(buf); | |||
7346 | } | |||
7347 | ||||
7348 | void | |||
7349 | ikev2_info(struct iked *env, int dolog) | |||
7350 | { | |||
7351 | struct iked_sa *sa; | |||
7352 | struct iked_childsa *csa, *ipcomp; | |||
7353 | struct iked_flow *flow; | |||
7354 | ||||
7355 | log_debug("%s: called", __func__); | |||
7356 | ||||
7357 | RB_FOREACH(sa, iked_sas, &env->sc_sas)for ((sa) = iked_sas_RB_MINMAX(&env->sc_sas, -1); (sa) != ((void*)0); (sa) = iked_sas_RB_NEXT(sa)) { | |||
7358 | ikev2_info_sa(env, dolog, "iked_sas", sa); | |||
7359 | TAILQ_FOREACH(csa, &sa->sa_childsas, csa_entry)for((csa) = ((&sa->sa_childsas)->tqh_first); (csa) != ((void*)0); (csa) = ((csa)->csa_entry.tqe_next)) { | |||
7360 | ikev2_info_csa(env, dolog, " sa_childsas", csa); | |||
7361 | if ((ipcomp = csa->csa_bundled) != NULL((void*)0)) | |||
7362 | ikev2_info_csa(env, dolog, " ", | |||
7363 | ipcomp); | |||
7364 | } | |||
7365 | TAILQ_FOREACH(flow, &sa->sa_flows, flow_entry)for((flow) = ((&sa->sa_flows)->tqh_first); (flow) != ((void*)0); (flow) = ((flow)->flow_entry.tqe_next)) { | |||
7366 | ikev2_info_flow(env, dolog, " sa_flows", flow); | |||
7367 | } | |||
7368 | } | |||
7369 | RB_FOREACH(csa, iked_activesas, &env->sc_activesas)for ((csa) = iked_activesas_RB_MINMAX(&env->sc_activesas , -1); (csa) != ((void*)0); (csa) = iked_activesas_RB_NEXT(csa )) { | |||
7370 | ikev2_info_csa(env, dolog, "iked_activesas", csa); | |||
7371 | if ((ipcomp = csa->csa_bundled) != NULL((void*)0)) | |||
7372 | ikev2_info_csa(env, dolog, " ", ipcomp); | |||
7373 | } | |||
7374 | RB_FOREACH(flow, iked_flows, &env->sc_activeflows)for ((flow) = iked_flows_RB_MINMAX(&env->sc_activeflows , -1); (flow) != ((void*)0); (flow) = iked_flows_RB_NEXT(flow )) { | |||
7375 | ikev2_info_flow(env, dolog, "iked_flows", flow); | |||
7376 | } | |||
7377 | RB_FOREACH(sa, iked_dstid_sas, &env->sc_dstid_sas)for ((sa) = iked_dstid_sas_RB_MINMAX(&env->sc_dstid_sas , -1); (sa) != ((void*)0); (sa) = iked_dstid_sas_RB_NEXT(sa)) { | |||
7378 | ikev2_info_sa(env, dolog, "iked_dstid_sas", sa); | |||
7379 | } | |||
7380 | if (dolog) | |||
7381 | return; | |||
7382 | /* Send empty reply to indicate end of information. */ | |||
7383 | proc_compose(&env->sc_ps, PROC_CONTROL, IMSG_CTL_SHOW_SA, NULL((void*)0), 0); | |||
7384 | } | |||
7385 | ||||
7386 | const char * | |||
7387 | ikev2_ikesa_info(uint64_t spi, const char *msg) | |||
7388 | { | |||
7389 | static char buf[1024]; | |||
7390 | const char *spistr; | |||
7391 | ||||
7392 | spistr = print_spi(spi, 8); | |||
7393 | if (msg) | |||
7394 | snprintf(buf, sizeof(buf), "spi=%s: %s", spistr, msg); | |||
7395 | else | |||
7396 | snprintf(buf, sizeof(buf), "spi=%s: ", spistr); | |||
7397 | return buf; | |||
7398 | } | |||
7399 | ||||
7400 | void | |||
7401 | ikev2_log_established(struct iked_sa *sa) | |||
7402 | { | |||
7403 | char dstid[IKED_ID_SIZE1024], srcid[IKED_ID_SIZE1024]; | |||
7404 | ||||
7405 | if (ikev2_print_id(IKESA_DSTID(sa)((sa)->sa_hdr.sh_initiator ? &(sa)->sa_rid : &( sa)->sa_iid), dstid, sizeof(dstid)) == -1) | |||
7406 | bzero(dstid, sizeof(dstid)); | |||
7407 | if (ikev2_print_id(IKESA_SRCID(sa)((sa)->sa_hdr.sh_initiator ? &(sa)->sa_iid : &( sa)->sa_rid), srcid, sizeof(srcid)) == -1) | |||
7408 | bzero(srcid, sizeof(srcid)); | |||
7409 | log_info( | |||
7410 | "%sestablished peer %s[%s] local %s[%s]%s%s%s%s policy '%s'%s" | |||
7411 | " (enc %s%s%s group %s prf %s)", SPI_SA(sa, NULL)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((((void *)0)))), | |||
7412 | print_host((struct sockaddr *)&sa->sa_peer.addr, NULL((void*)0), 0), dstid, | |||
7413 | print_host((struct sockaddr *)&sa->sa_local.addr, NULL((void*)0), 0), srcid, | |||
7414 | sa->sa_addrpool ? " assigned " : "", | |||
7415 | sa->sa_addrpool ? | |||
7416 | print_host((struct sockaddr *)&sa->sa_addrpool->addr, NULL((void*)0), 0) : "", | |||
7417 | sa->sa_addrpool6 ? " assigned " : "", | |||
7418 | sa->sa_addrpool6 ? | |||
7419 | print_host((struct sockaddr *)&sa->sa_addrpool6->addr, NULL((void*)0), 0) : "", | |||
7420 | sa->sa_policy ? sa->sa_policy->pol_name : "", | |||
7421 | sa->sa_hdr.sh_initiator ? " as initiator" : " as responder", | |||
7422 | print_xf(sa->sa_encr->encr_id, cipher_keylength(sa->sa_encr) - | |||
7423 | sa->sa_encr->encr_saltlength, ikeencxfs), | |||
7424 | sa->sa_encr->encr_authid ? "" : " auth ", | |||
7425 | sa->sa_encr->encr_authid ? "" : print_xf(sa->sa_integr->hash_id, | |||
7426 | hash_keylength(sa->sa_integr), authxfs), | |||
7427 | print_xf(sa->sa_dhgroupsa_kex.kex_dhgroup->id, 0, groupxfs), | |||
7428 | print_xf(sa->sa_prf->hash_id, hash_keylength(sa->sa_prf), prfxfs)); | |||
7429 | } | |||
7430 | ||||
7431 | void | |||
7432 | ikev2_log_cert_info(const char *msg, struct iked_id *certid) | |||
7433 | { | |||
7434 | X509 *cert = NULL((void*)0); | |||
7435 | BIO *rawcert = NULL((void*)0); | |||
7436 | ||||
7437 | if (certid->id_type != IKEV2_CERT_X509_CERT4 || | |||
7438 | certid->id_buf == NULL((void*)0)) | |||
7439 | return; | |||
7440 | if ((rawcert = BIO_new_mem_buf(ibuf_data(certid->id_buf), | |||
7441 | ibuf_length(certid->id_buf))) == NULL((void*)0) || | |||
7442 | (cert = d2i_X509_bio(rawcert, NULL((void*)0))) == NULL((void*)0)) | |||
7443 | goto out; | |||
7444 | ca_cert_info(msg, cert); | |||
7445 | out: | |||
7446 | if (cert) | |||
7447 | X509_free(cert); | |||
7448 | if (rawcert) | |||
7449 | BIO_free(rawcert); | |||
7450 | } | |||
7451 | ||||
7452 | void | |||
7453 | ikev2_log_proposal(struct iked_sa *sa, struct iked_proposals *proposals) | |||
7454 | { | |||
7455 | struct iked_proposal *prop; | |||
7456 | struct iked_transform *xform; | |||
7457 | unsigned int i; | |||
7458 | char lenstr[20]; | |||
7459 | ||||
7460 | TAILQ_FOREACH(prop, proposals, prop_entry)for((prop) = ((proposals)->tqh_first); (prop) != ((void*)0 ); (prop) = ((prop)->prop_entry.tqe_next)) { | |||
7461 | for (i = 0; i < prop->prop_nxforms; i++) { | |||
7462 | xform = &prop->prop_xforms[i]; | |||
7463 | if (xform->xform_keylength) | |||
7464 | snprintf(lenstr, sizeof(lenstr), "-%u", | |||
7465 | xform->xform_keylength); | |||
7466 | else | |||
7467 | lenstr[0] = '\0'; | |||
7468 | log_info("%s: %s #%u %s=%s%s", | |||
7469 | sa ? SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))) : __func__, | |||
7470 | print_map(prop->prop_protoid, ikev2_saproto_map), | |||
7471 | prop->prop_id, | |||
7472 | print_map(xform->xform_type, ikev2_xformtype_map), | |||
7473 | xform->xform_map ? | |||
7474 | print_map(xform->xform_id, xform->xform_map) | |||
7475 | : "UNKNOWN", | |||
7476 | lenstr); | |||
7477 | } | |||
7478 | } | |||
7479 | } |