File: | src/sbin/iked/ikev2.c |
Warning: | line 7227, column 9 Dereference of null pointer |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: ikev2.c,v 1.380 2023/11/24 14:43:00 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 <endian.h> | |||
36 | #include <errno(*__errno()).h> | |||
37 | #include <err.h> | |||
38 | #include <event.h> | |||
39 | ||||
40 | #include <openssl/sha.h> | |||
41 | #include <openssl/evp.h> | |||
42 | #include <openssl/x509.h> | |||
43 | ||||
44 | #include "iked.h" | |||
45 | #include "ikev2.h" | |||
46 | #include "eap.h" | |||
47 | #include "dh.h" | |||
48 | #include "chap_ms.h" | |||
49 | #include "version.h" | |||
50 | ||||
51 | void ikev2_info(struct iked *, int); | |||
52 | void ikev2_info_sa(struct iked *, int, const char *, struct iked_sa *); | |||
53 | void ikev2_info_csa(struct iked *, int, const char *, struct iked_childsa *); | |||
54 | void ikev2_info_flow(struct iked *, int, const char *, struct iked_flow *); | |||
55 | void ikev2_log_established(struct iked_sa *); | |||
56 | void ikev2_log_proposal(struct iked_sa *, struct iked_proposals *); | |||
57 | void ikev2_log_cert_info(const char *, struct iked_id *); | |||
58 | ||||
59 | void ikev2_run(struct privsep *, struct privsep_proc *, void *); | |||
60 | void ikev2_shutdown(void); | |||
61 | int ikev2_dispatch_parent(int, struct privsep_proc *, struct imsg *); | |||
62 | int ikev2_dispatch_cert(int, struct privsep_proc *, struct imsg *); | |||
63 | int ikev2_dispatch_control(int, struct privsep_proc *, struct imsg *); | |||
64 | ||||
65 | struct iked_sa * | |||
66 | ikev2_getimsgdata(struct iked *, struct imsg *, struct iked_sahdr *, | |||
67 | uint8_t *, uint8_t **, size_t *); | |||
68 | ||||
69 | void ikev2_recv(struct iked *, struct iked_message *); | |||
70 | int ikev2_ike_auth_compatible(struct iked_sa *, uint8_t, uint8_t); | |||
71 | int ikev2_ike_auth_recv(struct iked *, struct iked_sa *, | |||
72 | struct iked_message *); | |||
73 | int ikev2_ike_auth(struct iked *, struct iked_sa *); | |||
74 | int ikev2_auth_verify(struct iked *, struct iked_sa *); | |||
75 | ||||
76 | void ikev2_init_recv(struct iked *, struct iked_message *, | |||
77 | struct ike_header *); | |||
78 | void ikev2_init_ike_sa_timeout(struct iked *, void *); | |||
79 | int ikev2_init_ike_sa_peer(struct iked *, struct iked_policy *, | |||
80 | struct iked_addr *, struct iked_message *); | |||
81 | int ikev2_init_ike_auth(struct iked *, struct iked_sa *); | |||
82 | int ikev2_init_auth(struct iked *, struct iked_message *); | |||
83 | int ikev2_init_done(struct iked *, struct iked_sa *); | |||
84 | ||||
85 | int ikev2_record_dstid(struct iked *, struct iked_sa *); | |||
86 | ||||
87 | void ikev2_enable_timer(struct iked *, struct iked_sa *); | |||
88 | void ikev2_disable_timer(struct iked *, struct iked_sa *); | |||
89 | ||||
90 | void ikev2_resp_recv(struct iked *, struct iked_message *, | |||
91 | struct ike_header *); | |||
92 | int ikev2_resp_ike_sa_init(struct iked *, struct iked_message *); | |||
93 | int ikev2_resp_ike_eap(struct iked *, struct iked_sa *, | |||
94 | struct iked_message *); | |||
95 | int ikev2_resp_ike_eap_mschap(struct iked *, struct iked_sa *, | |||
96 | struct iked_message *); | |||
97 | int ikev2_resp_ike_auth(struct iked *, struct iked_sa *); | |||
98 | int ikev2_send_auth_failed(struct iked *, struct iked_sa *); | |||
99 | int ikev2_send_error(struct iked *, struct iked_sa *, | |||
100 | struct iked_message *, uint8_t); | |||
101 | int ikev2_send_init_error(struct iked *, struct iked_message *); | |||
102 | ||||
103 | int ikev2_handle_certreq(struct iked*, struct iked_message *); | |||
104 | ssize_t ikev2_handle_delete(struct iked *, struct iked_message *, | |||
105 | struct ibuf *, struct ikev2_payload **, uint8_t *); | |||
106 | ||||
107 | int ikev2_send_create_child_sa(struct iked *, struct iked_sa *, | |||
108 | struct iked_spi *, uint8_t, uint16_t); | |||
109 | int ikev2_ikesa_enable(struct iked *, struct iked_sa *, struct iked_sa *); | |||
110 | void ikev2_ikesa_delete(struct iked *, struct iked_sa *, int); | |||
111 | int ikev2_nonce_cmp(struct ibuf *, struct ibuf *); | |||
112 | int ikev2_init_create_child_sa(struct iked *, struct iked_message *); | |||
113 | int ikev2_resp_create_child_sa(struct iked *, struct iked_message *); | |||
114 | void ikev2_ike_sa_rekey(struct iked *, void *); | |||
115 | void ikev2_ike_sa_rekey_timeout(struct iked *, void *); | |||
116 | void ikev2_ike_sa_rekey_schedule(struct iked *, struct iked_sa *); | |||
117 | void ikev2_ike_sa_rekey_schedule_fast(struct iked *, struct iked_sa *); | |||
118 | void ikev2_ike_sa_alive(struct iked *, void *); | |||
119 | void ikev2_ike_sa_keepalive(struct iked *, void *); | |||
120 | ||||
121 | int ikev2_sa_negotiate_common(struct iked *, struct iked_sa *, | |||
122 | struct iked_message *, int); | |||
123 | int ikev2_sa_initiator(struct iked *, struct iked_sa *, | |||
124 | struct iked_sa *, struct iked_message *); | |||
125 | int ikev2_sa_responder(struct iked *, struct iked_sa *, struct iked_sa *, | |||
126 | struct iked_message *); | |||
127 | int ikev2_sa_initiator_dh(struct iked_sa *, struct iked_message *, | |||
128 | unsigned int, struct iked_sa *); | |||
129 | int ikev2_sa_responder_dh(struct iked_kex *, struct iked_proposals *, | |||
130 | struct iked_message *, unsigned int); | |||
131 | void ikev2_sa_cleanup_dh(struct iked_sa *); | |||
132 | int ikev2_sa_keys(struct iked *, struct iked_sa *, struct ibuf *); | |||
133 | int ikev2_sa_tag(struct iked_sa *, struct iked_id *); | |||
134 | int ikev2_set_sa_proposal(struct iked_sa *, struct iked_policy *, | |||
135 | unsigned int); | |||
136 | ||||
137 | int ikev2_childsa_negotiate(struct iked *, struct iked_sa *, | |||
138 | struct iked_kex *, struct iked_proposals *, int, int); | |||
139 | int ikev2_childsa_delete_proposed(struct iked *, struct iked_sa *, | |||
140 | struct iked_proposals *); | |||
141 | int ikev2_valid_proposal(struct iked_proposal *, | |||
142 | struct iked_transform **, struct iked_transform **, int *); | |||
143 | ||||
144 | int ikev2_handle_notifies(struct iked *, struct iked_message *); | |||
145 | ||||
146 | ssize_t ikev2_add_proposals(struct iked *, struct iked_sa *, struct ibuf *, | |||
147 | struct iked_proposals *, uint8_t, int, int, int); | |||
148 | ssize_t ikev2_add_cp(struct iked *, struct iked_sa *, int, struct ibuf *); | |||
149 | ssize_t ikev2_init_add_cp(struct iked *, struct iked_sa *, struct ibuf *); | |||
150 | ssize_t ikev2_resp_add_cp(struct iked *, struct iked_sa *, struct ibuf *); | |||
151 | ssize_t ikev2_add_transform(struct ibuf *, | |||
152 | uint8_t, uint8_t, uint16_t, uint16_t); | |||
153 | ssize_t ikev2_add_ts(struct ibuf *, struct ikev2_payload **, ssize_t, | |||
154 | struct iked_sa *, int); | |||
155 | ssize_t ikev2_add_certreq(struct ibuf *, struct ikev2_payload **, ssize_t, | |||
156 | struct ibuf *, uint8_t); | |||
157 | ssize_t ikev2_add_ipcompnotify(struct iked *, struct ibuf *, | |||
158 | struct ikev2_payload **, ssize_t, struct iked_sa *, int); | |||
159 | ssize_t ikev2_add_ts_payload(struct ibuf *, unsigned int, struct iked_sa *); | |||
160 | ssize_t ikev2_add_error(struct iked *, struct ibuf *, struct iked_message *); | |||
161 | int ikev2_add_data(struct ibuf *, void *, size_t); | |||
162 | int ikev2_add_buf(struct ibuf *buf, struct ibuf *); | |||
163 | ||||
164 | int ikev2_cp_setaddr(struct iked *, struct iked_sa *, sa_family_t); | |||
165 | int ikev2_cp_setaddr_pool(struct iked *, struct iked_sa *, | |||
166 | struct iked_cfg *, const char **, sa_family_t); | |||
167 | int ikev2_cp_fixaddr(struct iked_sa *, struct iked_addr *, | |||
168 | struct iked_addr *); | |||
169 | int ikev2_cp_fixflow(struct iked_sa *, struct iked_flow *, | |||
170 | struct iked_flow *); | |||
171 | int ikev2_cp_request_configured(struct iked_sa *); | |||
172 | ||||
173 | ssize_t ikev2_add_sighashnotify(struct ibuf *, struct ikev2_payload **, | |||
174 | ssize_t); | |||
175 | ssize_t ikev2_add_nat_detection(struct iked *, struct ibuf *, | |||
176 | struct ikev2_payload **, struct iked_message *, ssize_t); | |||
177 | ssize_t ikev2_add_vendor_id(struct ibuf *, struct ikev2_payload **, | |||
178 | ssize_t, struct ibuf *); | |||
179 | ssize_t ikev2_add_notify(struct ibuf *, struct ikev2_payload **, ssize_t, | |||
180 | uint16_t); | |||
181 | ssize_t ikev2_add_mobike(struct ibuf *, struct ikev2_payload **, ssize_t); | |||
182 | ssize_t ikev2_add_fragmentation(struct ibuf *, struct ikev2_payload **, | |||
183 | ssize_t); | |||
184 | ssize_t ikev2_add_transport_mode(struct iked *, struct ibuf *, | |||
185 | struct ikev2_payload **, ssize_t, struct iked_sa *); | |||
186 | int ikev2_update_sa_addresses(struct iked *, struct iked_sa *); | |||
187 | int ikev2_resp_informational(struct iked *, struct iked_sa *, | |||
188 | struct iked_message *); | |||
189 | ||||
190 | void ikev2_ctl_reset_id(struct iked *, struct imsg *, unsigned int); | |||
191 | void ikev2_ctl_show_sa(struct iked *); | |||
192 | void ikev2_ctl_show_stats(struct iked *); | |||
193 | ||||
194 | static struct privsep_proc procs[] = { | |||
195 | { "parent", PROC_PARENT, ikev2_dispatch_parent }, | |||
196 | { "certstore", PROC_CERT, ikev2_dispatch_cert }, | |||
197 | { "control", PROC_CONTROL, ikev2_dispatch_control } | |||
198 | }; | |||
199 | ||||
200 | void | |||
201 | ikev2(struct privsep *ps, struct privsep_proc *p) | |||
202 | { | |||
203 | proc_run(ps, p, procs, nitems(procs)(sizeof((procs)) / sizeof((procs)[0])), ikev2_run, NULL((void *)0)); | |||
204 | } | |||
205 | ||||
206 | void | |||
207 | ikev2_run(struct privsep *ps, struct privsep_proc *p, void *arg) | |||
208 | { | |||
209 | /* | |||
210 | * pledge in the ikev2 process: | |||
211 | * stdio - for malloc and basic I/O including events. | |||
212 | * inet - for sendto with specified peer address. | |||
213 | * recvfd - for PFKEYv2 and the listening UDP sockets. | |||
214 | * In theory, recvfd could be dropped after getting the fds once. | |||
215 | */ | |||
216 | p->p_shutdown = ikev2_shutdown; | |||
217 | if (pledge("stdio inet recvfd", NULL((void *)0)) == -1) | |||
218 | fatal("pledge"); | |||
219 | } | |||
220 | ||||
221 | void | |||
222 | ikev2_shutdown(void) | |||
223 | { | |||
224 | struct iked *env = iked_env; | |||
225 | ||||
226 | ibuf_free(env->sc_certreq); | |||
227 | env->sc_certreq = NULL((void *)0); | |||
228 | config_doreset(env, RESET_ALL); | |||
229 | } | |||
230 | ||||
231 | int | |||
232 | ikev2_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg) | |||
233 | { | |||
234 | struct iked *env = iked_env; | |||
235 | struct iked_sa *sa, *satmp; | |||
236 | struct iked_policy *pol, *old; | |||
237 | ||||
238 | switch (imsg->hdr.type) { | |||
239 | case IMSG_CTL_RESET: | |||
240 | return (config_getreset(env, imsg)); | |||
241 | case IMSG_CTL_COUPLE: | |||
242 | case IMSG_CTL_DECOUPLE: | |||
243 | return (config_getcoupled(env, imsg->hdr.type)); | |||
244 | case IMSG_CTL_ACTIVE: | |||
245 | case IMSG_CTL_PASSIVE: | |||
246 | if (config_getmode(env, imsg->hdr.type) == -1) | |||
247 | return (0); /* ignore error */ | |||
248 | timer_del(env, &env->sc_inittmr); | |||
249 | TAILQ_FOREACH(pol, &env->sc_policies, pol_entry)for((pol) = ((&env->sc_policies)->tqh_first); (pol) != ((void *)0); (pol) = ((pol)->pol_entry.tqe_next)) { | |||
250 | if (policy_generate_ts(pol) == -1) | |||
251 | fatalx("%s: too many traffic selectors", __func__); | |||
252 | } | |||
253 | /* Find new policies for dangling SAs */ | |||
254 | RB_FOREACH_SAFE(sa, iked_sas, &env->sc_sas, satmp)for ((sa) = iked_sas_RB_MINMAX(&env->sc_sas, -1); ((sa ) != ((void *)0)) && ((satmp) = iked_sas_RB_NEXT(sa), 1); (sa) = (satmp)) { | |||
255 | if (sa->sa_state != IKEV2_STATE_ESTABLISHED9) { | |||
256 | sa_state(env, sa, IKEV2_STATE_CLOSING10); | |||
257 | ikev2_ike_sa_setreason(sa, "reload"); | |||
258 | sa_free(env, sa); | |||
259 | continue; | |||
260 | } | |||
261 | ||||
262 | old = sa->sa_policy; | |||
263 | if (policy_lookup_sa(env, sa) == -1) { | |||
264 | log_info("%s: No matching Policy found, terminating SA.", | |||
265 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
266 | ikev2_ike_sa_setreason(sa, "Policy no longer exists"); | |||
267 | ikev2_ikesa_delete(env, sa, sa->sa_hdr.sh_initiator); | |||
268 | } | |||
269 | if (old != sa->sa_policy) { | |||
270 | /* Cleanup old policy */ | |||
271 | 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); | |||
272 | policy_unref(env, old); | |||
273 | policy_ref(env, sa->sa_policy); | |||
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 = iked_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 | int i; | |||
319 | ||||
320 | switch (imsg->hdr.type) { | |||
321 | case IMSG_CERTREQ: | |||
322 | IMSG_SIZE_CHECK(imsg, &type)do { if (((imsg)->hdr.len - sizeof(struct imsg_hdr)) < sizeof (*&type)) fatalx("bad length imsg received"); } while (0); | |||
323 | ||||
324 | ptr = imsg->data; | |||
325 | memcpy(&type, ptr, sizeof(type)); | |||
326 | ptr += sizeof(type); | |||
327 | ||||
328 | ibuf_free(env->sc_certreq); | |||
329 | env->sc_certreqtype = type; | |||
330 | env->sc_certreq = ibuf_new(ptr, | |||
331 | IMSG_DATA_SIZE(imsg)((imsg)->hdr.len - sizeof(struct imsg_hdr)) - sizeof(type)); | |||
332 | ||||
333 | log_debug("%s: updated local CERTREQ type %s length %zu", | |||
334 | __func__, print_map(type, ikev2_cert_map), | |||
335 | ibuf_length(env->sc_certreq)); | |||
336 | ||||
337 | break; | |||
338 | case IMSG_CERTVALID: | |||
339 | case IMSG_CERTINVALID: | |||
340 | /* Ignore invalid or unauthenticated SAs */ | |||
341 | if ((sa = ikev2_getimsgdata(env, imsg, | |||
342 | &sh, &type, &ptr, &len)) == NULL((void *)0) || | |||
343 | sa->sa_state < IKEV2_STATE_EAP3) | |||
344 | break; | |||
345 | ||||
346 | if (sh.sh_initiator) | |||
347 | id = &sa->sa_rcert; | |||
348 | else | |||
349 | id = &sa->sa_icert; | |||
350 | ||||
351 | id->id_type = type; | |||
352 | id->id_offset = 0; | |||
353 | ibuf_free(id->id_buf); | |||
354 | id->id_buf = NULL((void *)0); | |||
355 | ||||
356 | if (len > 0 && (id->id_buf = ibuf_new(ptr, len)) == NULL((void *)0)) { | |||
357 | log_debug("%s: failed to get cert payload", | |||
358 | __func__); | |||
359 | break; | |||
360 | } | |||
361 | ||||
362 | if (imsg->hdr.type == IMSG_CERTVALID) { | |||
363 | if (sa->sa_peerauth.id_type && ikev2_auth_verify(env, sa)) | |||
364 | break; | |||
365 | ||||
366 | log_debug("%s: peer certificate is valid", __func__); | |||
367 | sa_stateflags(sa, IKED_REQ_CERTVALID0x0002); | |||
368 | ||||
369 | if (ikev2_ike_auth(env, sa) != 0) | |||
370 | log_debug("%s: failed to send ike auth", __func__); | |||
371 | } else { | |||
372 | log_warnx("%s: peer certificate is invalid", | |||
373 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
374 | ikev2_send_auth_failed(env, sa); | |||
375 | } | |||
376 | break; | |||
377 | case IMSG_CERT: | |||
378 | if ((sa = ikev2_getimsgdata(env, imsg, | |||
379 | &sh, &type, &ptr, &len)) == NULL((void *)0)) { | |||
380 | log_debug("%s: invalid cert reply", __func__); | |||
381 | break; | |||
382 | } | |||
383 | ||||
384 | /* | |||
385 | * Ignore the message if we already got a valid certificate. | |||
386 | * This might happen if the peer sent multiple CERTREQs. | |||
387 | */ | |||
388 | if (sa->sa_stateflags & IKED_REQ_CERT0x0001 || | |||
389 | type == IKEV2_CERT_NONE0) | |||
390 | ignore = 1; | |||
391 | ||||
392 | log_debug("%s: cert type %s length %zu, %s", __func__, | |||
393 | print_map(type, ikev2_cert_map), len, | |||
394 | ignore ? "ignored" : "ok"); | |||
395 | ||||
396 | if (ignore) | |||
397 | break; | |||
398 | ||||
399 | if (sh.sh_initiator) | |||
400 | id = &sa->sa_icert; | |||
401 | else | |||
402 | id = &sa->sa_rcert; | |||
403 | ||||
404 | id->id_type = type; | |||
405 | id->id_offset = 0; | |||
406 | ibuf_free(id->id_buf); | |||
407 | id->id_buf = NULL((void *)0); | |||
408 | ||||
409 | if (len <= 0 || (id->id_buf = ibuf_new(ptr, len)) == NULL((void *)0)) { | |||
410 | log_debug("%s: failed to get cert payload", | |||
411 | __func__); | |||
412 | break; | |||
413 | } | |||
414 | ||||
415 | sa_stateflags(sa, IKED_REQ_CERT0x0001); | |||
416 | ||||
417 | if (ikev2_ike_auth(env, sa) != 0) | |||
418 | log_debug("%s: failed to send ike auth", __func__); | |||
419 | break; | |||
420 | case IMSG_SCERT: | |||
421 | if ((sa = ikev2_getimsgdata(env, imsg, | |||
422 | &sh, &type, &ptr, &len)) == NULL((void *)0)) { | |||
423 | log_debug("%s: invalid supplemental cert reply", | |||
424 | __func__); | |||
425 | break; | |||
426 | } | |||
427 | ||||
428 | if (sa->sa_stateflags & IKED_REQ_CERT0x0001 || | |||
429 | type == IKEV2_CERT_NONE0) | |||
430 | ignore = 1; | |||
431 | ||||
432 | log_debug("%s: supplemental cert type %s length %zu, %s", | |||
433 | __func__, | |||
434 | print_map(type, ikev2_cert_map), len, | |||
435 | ignore ? "ignored" : "ok"); | |||
436 | ||||
437 | if (ignore) | |||
438 | break; | |||
439 | ||||
440 | for (i = 0; i < IKED_SCERT_MAX3; i++) { | |||
441 | id = &sa->sa_scert[i]; | |||
442 | if (id->id_type == IKEV2_CERT_NONE0) | |||
443 | break; | |||
444 | id = NULL((void *)0); | |||
445 | } | |||
446 | ||||
447 | if (id == NULL((void *)0)) { | |||
448 | log_debug("%s: too many supplemental cert. ignored", | |||
449 | __func__); | |||
450 | break; | |||
451 | } | |||
452 | ||||
453 | id->id_type = type; | |||
454 | id->id_offset = 0; | |||
455 | ibuf_free(id->id_buf); | |||
456 | id->id_buf = NULL((void *)0); | |||
457 | ||||
458 | if (len <= 0 || (id->id_buf = ibuf_new(ptr, len)) == NULL((void *)0)) { | |||
459 | log_debug("%s: failed to get supplemental cert payload", | |||
460 | __func__); | |||
461 | break; | |||
462 | } | |||
463 | ||||
464 | break; | |||
465 | case IMSG_AUTH: | |||
466 | if ((sa = ikev2_getimsgdata(env, imsg, | |||
467 | &sh, &type, &ptr, &len)) == NULL((void *)0)) { | |||
468 | log_debug("%s: invalid auth reply", __func__); | |||
469 | break; | |||
470 | } | |||
471 | if (sa_stateok(sa, IKEV2_STATE_VALID7)) { | |||
472 | log_warnx("%s: ignoring AUTH in state %s", | |||
473 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
474 | print_map(sa->sa_state, ikev2_state_map)); | |||
475 | break; | |||
476 | } | |||
477 | ||||
478 | log_debug("%s: AUTH type %d len %zu", __func__, type, len); | |||
479 | ||||
480 | id = &sa->sa_localauth; | |||
481 | id->id_type = type; | |||
482 | id->id_offset = 0; | |||
483 | ibuf_free(id->id_buf); | |||
484 | id->id_buf = NULL((void *)0); | |||
485 | ||||
486 | if (type != IKEV2_AUTH_NONE0) { | |||
487 | if (len <= 0 || | |||
488 | (id->id_buf = ibuf_new(ptr, len)) == NULL((void *)0)) { | |||
489 | log_debug("%s: failed to get auth payload", | |||
490 | __func__); | |||
491 | break; | |||
492 | } | |||
493 | } | |||
494 | ||||
495 | sa_stateflags(sa, IKED_REQ_AUTH0x0008); | |||
496 | ||||
497 | if (ikev2_ike_auth(env, sa) != 0) | |||
498 | log_debug("%s: failed to send ike auth", __func__); | |||
499 | break; | |||
500 | default: | |||
501 | return (-1); | |||
502 | } | |||
503 | ||||
504 | return (0); | |||
505 | } | |||
506 | ||||
507 | int | |||
508 | ikev2_dispatch_control(int fd, struct privsep_proc *p, struct imsg *imsg) | |||
509 | { | |||
510 | struct iked *env = iked_env; | |||
511 | ||||
512 | switch (imsg->hdr.type) { | |||
513 | case IMSG_CTL_RESET_ID: | |||
514 | ikev2_ctl_reset_id(env, imsg, imsg->hdr.type); | |||
515 | break; | |||
516 | case IMSG_CTL_SHOW_SA: | |||
517 | ikev2_ctl_show_sa(env); | |||
518 | break; | |||
519 | case IMSG_CTL_SHOW_STATS: | |||
520 | ikev2_ctl_show_stats(env); | |||
521 | break; | |||
522 | default: | |||
523 | return (-1); | |||
524 | } | |||
525 | ||||
526 | return (0); | |||
527 | } | |||
528 | ||||
529 | /* try to delete established SA if no other exchange is active */ | |||
530 | int | |||
531 | ikev2_ike_sa_delete(struct iked *env, struct iked_sa *sa) | |||
532 | { | |||
533 | if (sa->sa_state != IKEV2_STATE_ESTABLISHED9) | |||
534 | return (-1); | |||
535 | if (sa->sa_stateflags & (IKED_REQ_CHILDSA0x0080|IKED_REQ_INF0x0100)) | |||
536 | return (-1); | |||
537 | ikev2_disable_timer(env, sa); | |||
538 | ikev2_ike_sa_setreason(sa, "reset sa control message"); | |||
539 | ikev2_ikesa_delete(env, sa, 1); | |||
540 | timer_add(env, &sa->sa_timer, 0); | |||
541 | return (0); | |||
542 | } | |||
543 | ||||
544 | void | |||
545 | ikev2_ctl_reset_id(struct iked *env, struct imsg *imsg, unsigned int type) | |||
546 | { | |||
547 | struct iked_sa *sa; | |||
548 | char *reset_id = NULL((void *)0); | |||
549 | char sa_id[IKED_ID_SIZE1024]; | |||
550 | ||||
551 | if ((reset_id = get_string(imsg->data, IMSG_DATA_SIZE(imsg)((imsg)->hdr.len - sizeof(struct imsg_hdr)))) == NULL((void *)0)) | |||
552 | return; | |||
553 | ||||
554 | log_debug("%s: %s %d", __func__, reset_id, type); | |||
555 | 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)) { | |||
556 | if (ikev2_print_id(IKESA_DSTID(sa)((sa)->sa_hdr.sh_initiator ? &(sa)->sa_rid : &( sa)->sa_iid), sa_id, sizeof(sa_id)) == -1) | |||
557 | continue; | |||
558 | if (strcmp(reset_id, sa_id) != 0) | |||
559 | continue; | |||
560 | if (sa->sa_state == IKEV2_STATE_CLOSED11) | |||
561 | continue; | |||
562 | if (sa->sa_state == IKEV2_STATE_ESTABLISHED9) | |||
563 | ikev2_disable_timer(env, sa); | |||
564 | log_info("%s: IKE SA %p id %s ispi %s rspi %s", __func__, | |||
565 | sa, sa_id, | |||
566 | print_spi(sa->sa_hdr.sh_ispi, 8), | |||
567 | print_spi(sa->sa_hdr.sh_rspi, 8)); | |||
568 | ikev2_ike_sa_setreason(sa, "reset control message"); | |||
569 | ikev2_ikesa_delete(env, sa, 1); | |||
570 | /* default IKED_IKE_SA_DELETE_TIMEOUT is 120s, so switch to 6s */ | |||
571 | timer_add(env, &sa->sa_timer, 3 * IKED_RETRANSMIT_TIMEOUT2); | |||
572 | } | |||
573 | free(reset_id); | |||
574 | } | |||
575 | ||||
576 | void | |||
577 | ikev2_ctl_show_sa(struct iked *env) | |||
578 | { | |||
579 | ikev2_info(env, 0); | |||
580 | } | |||
581 | ||||
582 | void | |||
583 | ikev2_ctl_show_stats(struct iked *env) | |||
584 | { | |||
585 | proc_compose(&env->sc_ps, PROC_CONTROL, IMSG_CTL_SHOW_STATS, | |||
586 | &env->sc_stats, sizeof(env->sc_stats)); | |||
587 | } | |||
588 | ||||
589 | struct iked_sa * | |||
590 | ikev2_getimsgdata(struct iked *env, struct imsg *imsg, struct iked_sahdr *sh, | |||
591 | uint8_t *type, uint8_t **buf, size_t *size) | |||
592 | { | |||
593 | uint8_t *ptr; | |||
594 | size_t len; | |||
595 | struct iked_sa *sa; | |||
596 | ||||
597 | ptr = imsg->data; | |||
598 | len = IMSG_DATA_SIZE(imsg)((imsg)->hdr.len - sizeof(struct imsg_hdr)); | |||
599 | if (len < sizeof(*sh)) | |||
600 | fatalx("ikev2_getimsgdata: length too small for sh"); | |||
601 | memcpy(sh, ptr, sizeof(*sh)); | |||
602 | len -= sizeof(*sh); | |||
603 | ptr += sizeof(*sh); | |||
604 | if (len < sizeof(*type)) | |||
605 | fatalx("ikev2_getimsgdata: length too small for type"); | |||
606 | memcpy(type, ptr, sizeof(*type)); | |||
607 | len -= sizeof(*type); | |||
608 | ptr += sizeof(*type); | |||
609 | ||||
610 | sa = sa_lookup(env, sh->sh_ispi, sh->sh_rspi, sh->sh_initiator); | |||
611 | ||||
612 | log_debug("%s: imsg %d rspi %s ispi %s initiator %d sa %s" | |||
613 | " type %d data length %zd", | |||
614 | __func__, imsg->hdr.type, | |||
615 | print_spi(sh->sh_rspi, 8), | |||
616 | print_spi(sh->sh_ispi, 8), | |||
617 | sh->sh_initiator, | |||
618 | sa == NULL((void *)0) ? "invalid" : "valid", *type, len); | |||
619 | ||||
620 | if (sa == NULL((void *)0)) | |||
621 | return (NULL((void *)0)); | |||
622 | ||||
623 | *buf = ptr; | |||
624 | *size = len; | |||
625 | ||||
626 | return (sa); | |||
627 | } | |||
628 | ||||
629 | static time_t | |||
630 | gettime(void) | |||
631 | { | |||
632 | struct timeval tv; | |||
633 | gettimeofday(&tv, NULL((void *)0)); | |||
634 | return tv.tv_sec; | |||
635 | } | |||
636 | ||||
637 | void | |||
638 | ikev2_recv(struct iked *env, struct iked_message *msg) | |||
639 | { | |||
640 | struct ike_header *hdr; | |||
641 | struct iked_sa *sa; | |||
642 | struct iked_msg_retransmit *mr; | |||
643 | unsigned int initiator, flag = 0; | |||
644 | int r; | |||
645 | ||||
646 | hdr = ibuf_seek(msg->msg_data, msg->msg_offset, sizeof(*hdr)); | |||
647 | ||||
648 | if (hdr == NULL((void *)0) || ibuf_size(msg->msg_data) < | |||
649 | (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)) | |||
650 | return; | |||
651 | ||||
652 | ikestat_inc(env, ikes_msg_rcvd)do { env->sc_stats.ikes_msg_rcvd += (1); } while(0); | |||
653 | ||||
654 | initiator = (hdr->ike_flags & IKEV2_FLAG_INITIATOR0x08) ? 0 : 1; | |||
655 | msg->msg_response = (hdr->ike_flags & IKEV2_FLAG_RESPONSE0x20) ? 1 : 0; | |||
656 | msg->msg_exchange = hdr->ike_exchange; | |||
657 | msg->msg_sa = sa_lookup(env, | |||
658 | 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)), | |||
659 | initiator); | |||
660 | 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)); | |||
661 | if (policy_lookup(env, msg, NULL((void *)0), NULL((void *)0), 0) != 0) { | |||
662 | ikestat_inc(env, ikes_msg_rcvd_dropped)do { env->sc_stats.ikes_msg_rcvd_dropped += (1); } while(0 ); | |||
663 | return; | |||
664 | } | |||
665 | ||||
666 | logit(hdr->ike_exchange == IKEV2_EXCHANGE_INFORMATIONAL37 ? | |||
667 | LOG_DEBUG7 : LOG_INFO6, | |||
668 | "%srecv %s %s %u peer %s local %s, %zu bytes, policy '%s'", | |||
669 | 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) ), | |||
670 | print_map(hdr->ike_exchange, ikev2_exchange_map), | |||
671 | msg->msg_response ? "res" : "req", | |||
672 | msg->msg_msgid, | |||
673 | print_addr(&msg->msg_peer), | |||
674 | print_addr(&msg->msg_local), | |||
675 | ibuf_size(msg->msg_data), | |||
676 | msg->msg_policy->pol_name); | |||
677 | log_debug("%s: ispi %s rspi %s", __func__, | |||
678 | 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), | |||
679 | 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)); | |||
680 | ||||
681 | if ((sa = msg->msg_sa) == NULL((void *)0)) | |||
682 | goto done; | |||
683 | ||||
684 | sa->sa_last_recvd = gettime(); | |||
685 | ||||
686 | if (hdr->ike_exchange == IKEV2_EXCHANGE_CREATE_CHILD_SA36) | |||
687 | flag = IKED_REQ_CHILDSA0x0080; | |||
688 | if (hdr->ike_exchange == IKEV2_EXCHANGE_INFORMATIONAL37) | |||
689 | flag = IKED_REQ_INF0x0100; | |||
690 | ||||
691 | if (hdr->ike_exchange != IKEV2_EXCHANGE_IKE_SA_INIT34 && | |||
692 | hdr->ike_nextpayload != IKEV2_PAYLOAD_SK46 && | |||
693 | hdr->ike_nextpayload != IKEV2_PAYLOAD_SKF53) { | |||
694 | ikestat_inc(env, ikes_msg_rcvd_dropped)do { env->sc_stats.ikes_msg_rcvd_dropped += (1); } while(0 ); | |||
695 | return; | |||
696 | } | |||
697 | ||||
698 | if (msg->msg_response) { | |||
699 | if (msg->msg_msgid > sa->sa_reqid) { | |||
700 | ikestat_inc(env, ikes_msg_rcvd_dropped)do { env->sc_stats.ikes_msg_rcvd_dropped += (1); } while(0 ); | |||
701 | return; | |||
702 | } | |||
703 | mr = ikev2_msg_lookup(env, &sa->sa_requests, msg, | |||
704 | hdr->ike_exchange); | |||
705 | if (hdr->ike_exchange != IKEV2_EXCHANGE_INFORMATIONAL37 && | |||
706 | mr == NULL((void *)0) && sa->sa_fragments.frag_count == 0) { | |||
707 | ikestat_inc(env, ikes_msg_rcvd_dropped)do { env->sc_stats.ikes_msg_rcvd_dropped += (1); } while(0 ); | |||
708 | return; | |||
709 | } | |||
710 | if (flag) { | |||
711 | if ((sa->sa_stateflags & flag) == 0) { | |||
712 | ikestat_inc(env, ikes_msg_rcvd_dropped)do { env->sc_stats.ikes_msg_rcvd_dropped += (1); } while(0 ); | |||
713 | return; | |||
714 | } | |||
715 | /* | |||
716 | * We have initiated this exchange, even if | |||
717 | * we are not the initiator of the IKE SA. | |||
718 | */ | |||
719 | initiator = 1; | |||
720 | } | |||
721 | /* | |||
722 | * There's no need to keep the request (fragments) around | |||
723 | */ | |||
724 | if (mr != NULL((void *)0) && hdr->ike_nextpayload != IKEV2_PAYLOAD_SKF53) | |||
725 | ikev2_msg_dispose(env, &sa->sa_requests, mr); | |||
726 | } else { | |||
727 | /* | |||
728 | * IKE_SA_INIT is special since it always uses the message id 0. | |||
729 | * Even when the message was rejected, and the new message has | |||
730 | * different proposals, the id will be the same. To discern | |||
731 | * retransmits and new messages, the RFC suggests to compare the | |||
732 | * the messages. | |||
733 | */ | |||
734 | if (sa->sa_state == IKEV2_STATE_CLOSED11 && sa->sa_1stmsg && | |||
735 | hdr->ike_exchange == IKEV2_EXCHANGE_IKE_SA_INIT34 && | |||
736 | msg->msg_msgid == 0 && | |||
737 | (ibuf_size(msg->msg_data) != ibuf_size(sa->sa_1stmsg) || | |||
738 | memcmp(ibuf_data(msg->msg_data), ibuf_data(sa->sa_1stmsg), | |||
739 | ibuf_size(sa->sa_1stmsg)) != 0)) { | |||
740 | ikev2_ike_sa_setreason(sa, NULL((void *)0)); | |||
741 | sa_free(env, sa); | |||
742 | msg->msg_sa = sa = NULL((void *)0); | |||
743 | goto done; | |||
744 | } | |||
745 | if (msg->msg_msgid < sa->sa_msgid) { | |||
746 | ikestat_inc(env, ikes_msg_rcvd_dropped)do { env->sc_stats.ikes_msg_rcvd_dropped += (1); } while(0 ); | |||
747 | return; | |||
748 | } | |||
749 | if (flag) | |||
750 | initiator = 0; | |||
751 | /* | |||
752 | * See if we have responded to this request before | |||
753 | * For return values 0 and -1 we have. | |||
754 | */ | |||
755 | if ((r = ikev2_msg_retransmit_response(env, sa, msg, | |||
756 | hdr->ike_exchange)) != -2) { | |||
757 | if (r == -1) { | |||
758 | log_warn("%s: failed to retransmit a " | |||
759 | "response", __func__); | |||
760 | ikev2_ike_sa_setreason(sa, | |||
761 | "retransmitting response failed"); | |||
762 | sa_free(env, sa); | |||
763 | } | |||
764 | return; | |||
765 | } else if (sa->sa_msgid_set && msg->msg_msgid == sa->sa_msgid) { | |||
766 | /* | |||
767 | * Response is being worked on, most likely we're | |||
768 | * waiting for the CA process to get back to us | |||
769 | */ | |||
770 | ikestat_inc(env, ikes_msg_rcvd_busy)do { env->sc_stats.ikes_msg_rcvd_busy += (1); } while(0); | |||
771 | return; | |||
772 | } | |||
773 | sa->sa_msgid_current = msg->msg_msgid; | |||
774 | } | |||
775 | ||||
776 | if (sa_address(sa, &sa->sa_peer, (struct sockaddr *)&msg->msg_peer) | |||
777 | == -1 || | |||
778 | sa_address(sa, &sa->sa_local, (struct sockaddr *)&msg->msg_local) | |||
779 | == -1) { | |||
780 | ikestat_inc(env, ikes_msg_rcvd_dropped)do { env->sc_stats.ikes_msg_rcvd_dropped += (1); } while(0 ); | |||
781 | return; | |||
782 | } | |||
783 | ||||
784 | sa->sa_fd = msg->msg_fd; | |||
785 | ||||
786 | log_debug("%s: updated SA to peer %s local %s", __func__, | |||
787 | print_addr(&sa->sa_peer.addr), print_addr(&sa->sa_local.addr)); | |||
788 | ||||
789 | done: | |||
790 | if (initiator) | |||
791 | ikev2_init_recv(env, msg, hdr); | |||
792 | else | |||
793 | ikev2_resp_recv(env, msg, hdr); | |||
794 | ||||
795 | if (sa != NULL((void *)0) && !msg->msg_response && msg->msg_valid) { | |||
796 | /* | |||
797 | * If it's a valid request, make sure to update the peer's | |||
798 | * message ID and dispose of all previous responses. | |||
799 | * We need to set sa_msgid_set in order to distinguish between | |||
800 | * "last msgid was 0" and "msgid not set yet". | |||
801 | */ | |||
802 | sa->sa_msgid = sa->sa_msgid_current; | |||
803 | sa->sa_msgid_set = 1; | |||
804 | ikev2_msg_prevail(env, &sa->sa_responses, msg); | |||
805 | } | |||
806 | ||||
807 | if (sa != NULL((void *)0) && sa->sa_state == IKEV2_STATE_CLOSED11) { | |||
808 | log_debug("%s: closing SA", __func__); | |||
809 | ikev2_ike_sa_setreason(sa, "closed"); | |||
810 | sa_free(env, sa); | |||
811 | } | |||
812 | } | |||
813 | ||||
814 | int | |||
815 | ikev2_ike_auth_compatible(struct iked_sa *sa, uint8_t policy, uint8_t wire) | |||
816 | { | |||
817 | if (wire == IKEV2_AUTH_SIG_ANY255) /* internal, not on wire */ | |||
818 | return (-1); | |||
819 | if (policy == wire || policy == IKEV2_AUTH_NONE0) | |||
820 | return (0); | |||
821 | switch (policy) { | |||
822 | case IKEV2_AUTH_SIG_ANY255: | |||
823 | switch (wire) { | |||
824 | case IKEV2_AUTH_SIG14: | |||
825 | case IKEV2_AUTH_RSA_SIG1: | |||
826 | case IKEV2_AUTH_ECDSA_2569: | |||
827 | case IKEV2_AUTH_ECDSA_38410: | |||
828 | case IKEV2_AUTH_ECDSA_52111: | |||
829 | return (0); | |||
830 | } | |||
831 | break; | |||
832 | case IKEV2_AUTH_SIG14: | |||
833 | case IKEV2_AUTH_RSA_SIG1: | |||
834 | case IKEV2_AUTH_ECDSA_2569: | |||
835 | case IKEV2_AUTH_ECDSA_38410: | |||
836 | case IKEV2_AUTH_ECDSA_52111: | |||
837 | switch (wire) { | |||
838 | /* | |||
839 | * XXX Maybe we need an indication saying: | |||
840 | * XXX Accept AUTH_SIG as long as its DSA? | |||
841 | */ | |||
842 | case IKEV2_AUTH_SIG14: | |||
843 | if (sa->sa_sigsha2) | |||
844 | return (0); | |||
845 | } | |||
846 | break; | |||
847 | } | |||
848 | return (-1); | |||
849 | } | |||
850 | ||||
851 | int | |||
852 | ikev2_auth_verify(struct iked *env, struct iked_sa *sa) | |||
853 | { | |||
854 | struct iked_auth ikeauth; | |||
855 | struct ibuf *authmsg; | |||
856 | int ret; | |||
857 | ||||
858 | memcpy(&ikeauth, &sa->sa_policy->pol_auth, | |||
859 | sizeof(ikeauth)); | |||
860 | ||||
861 | if (sa->sa_policy->pol_auth.auth_eap && | |||
862 | sa->sa_eapmsk != NULL((void *)0)) { | |||
863 | /* | |||
864 | * The initiator EAP auth is a PSK derived | |||
865 | * from the EAP-specific MSK | |||
866 | */ | |||
867 | ikeauth.auth_method = IKEV2_AUTH_SHARED_KEY_MIC2; | |||
868 | ||||
869 | /* Copy session key as PSK */ | |||
870 | memcpy(ikeauth.auth_data, | |||
871 | ibuf_data(sa->sa_eapmsk), | |||
872 | ibuf_size(sa->sa_eapmsk)); | |||
873 | ikeauth.auth_length = ibuf_size(sa->sa_eapmsk); | |||
874 | } | |||
875 | ||||
876 | if (ikev2_ike_auth_compatible(sa, | |||
877 | ikeauth.auth_method, sa->sa_peerauth.id_type) < 0) { | |||
878 | log_warnx("%s: unexpected auth method %s, was " | |||
879 | "expecting %s", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
880 | print_map(sa->sa_peerauth.id_type, | |||
881 | ikev2_auth_map), | |||
882 | print_map(ikeauth.auth_method, | |||
883 | ikev2_auth_map)); | |||
884 | ikev2_send_auth_failed(env, sa); | |||
885 | explicit_bzero(&ikeauth, sizeof(ikeauth)); | |||
886 | return (-1); | |||
887 | } | |||
888 | ikeauth.auth_method = sa->sa_peerauth.id_type; | |||
889 | ||||
890 | if ((authmsg = ikev2_msg_auth(env, sa, | |||
891 | sa->sa_hdr.sh_initiator)) == NULL((void *)0)) { | |||
892 | log_debug("%s: failed to get auth data", | |||
893 | __func__); | |||
894 | ikev2_send_auth_failed(env, sa); | |||
895 | explicit_bzero(&ikeauth, sizeof(ikeauth)); | |||
896 | return (-1); | |||
897 | } | |||
898 | ||||
899 | ret = ikev2_msg_authverify(env, sa, &ikeauth, | |||
900 | ibuf_data(sa->sa_peerauth.id_buf), | |||
901 | ibuf_size(sa->sa_peerauth.id_buf), | |||
902 | authmsg); | |||
903 | ibuf_free(authmsg); | |||
904 | if (ret != 0) { | |||
905 | log_info("%s: ikev2_msg_authverify failed", | |||
906 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
907 | ikev2_send_auth_failed(env, sa); | |||
908 | explicit_bzero(&ikeauth, sizeof(ikeauth)); | |||
909 | return (-1); | |||
910 | } | |||
911 | if (sa->sa_eapmsk != NULL((void *)0)) { | |||
912 | if ((authmsg = ikev2_msg_auth(env, sa, | |||
913 | !sa->sa_hdr.sh_initiator)) == NULL((void *)0)) { | |||
914 | log_debug("%s: failed to get auth data", | |||
915 | __func__); | |||
916 | explicit_bzero(&ikeauth, sizeof(ikeauth)); | |||
917 | return (-1); | |||
918 | } | |||
919 | ||||
920 | /* XXX 2nd AUTH for EAP messages */ | |||
921 | ret = ikev2_msg_authsign(env, sa, &ikeauth, authmsg); | |||
922 | ibuf_free(authmsg); | |||
923 | if (ret != 0) { | |||
924 | ikev2_send_auth_failed(env, sa); | |||
925 | explicit_bzero(&ikeauth, sizeof(ikeauth)); | |||
926 | return (-1); | |||
927 | } | |||
928 | ||||
929 | /* ikev2_msg_authverify verified AUTH */ | |||
930 | sa_stateflags(sa, IKED_REQ_AUTHVALID0x0010); | |||
931 | sa_stateflags(sa, IKED_REQ_EAPVALID0x0040); | |||
932 | sa_state(env, sa, IKEV2_STATE_EAP_SUCCESS4); | |||
933 | } | |||
934 | ||||
935 | explicit_bzero(&ikeauth, sizeof(ikeauth)); | |||
936 | return (0); | |||
937 | } | |||
938 | ||||
939 | int | |||
940 | ikev2_ike_auth_recv(struct iked *env, struct iked_sa *sa, | |||
941 | struct iked_message *msg) | |||
942 | { | |||
943 | struct iked_id *id; | |||
944 | struct ibuf *authmsg, *buf; | |||
945 | struct iked_policy *old; | |||
946 | uint8_t *cert = NULL((void *)0); | |||
947 | size_t certlen = 0; | |||
948 | int certtype = IKEV2_CERT_NONE0; | |||
949 | int i; | |||
950 | ||||
951 | /* The AUTH payload indicates if the responder wants EAP or not */ | |||
952 | if (msg->msg_auth.id_type != IKEV2_AUTH_NONE0 && | |||
953 | !sa_stateok(sa, IKEV2_STATE_EAP3)) | |||
954 | sa_state(env, sa, IKEV2_STATE_AUTH_REQUEST5); | |||
955 | ||||
956 | if (!sa->sa_hdr.sh_initiator && | |||
957 | !sa_stateok(sa, IKEV2_STATE_AUTH_REQUEST5) && | |||
958 | sa->sa_policy->pol_auth.auth_eap) | |||
959 | sa_state(env, sa, IKEV2_STATE_EAP3); | |||
960 | ||||
961 | if (sa->sa_hdr.sh_initiator) | |||
962 | id = &sa->sa_rid; | |||
963 | else | |||
964 | id = &sa->sa_iid; | |||
965 | ||||
966 | /* try to relookup the policy based on the peerid */ | |||
967 | if (msg->msg_peerid.id_type && !sa->sa_hdr.sh_initiator) { | |||
968 | old = sa->sa_policy; | |||
969 | ||||
970 | sa->sa_policy = NULL((void *)0); | |||
971 | if (policy_lookup(env, msg, &sa->sa_proposals, NULL((void *)0), 0) != 0 || | |||
972 | msg->msg_policy == NULL((void *)0)) { | |||
973 | log_info("%s: no compatible policy found", | |||
974 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
975 | ikev2_send_auth_failed(env, sa); | |||
976 | 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); | |||
977 | policy_unref(env, old); | |||
978 | return (-1); | |||
979 | } | |||
980 | if (msg->msg_policy != old) { | |||
981 | /* Clean up old policy */ | |||
982 | 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); | |||
983 | policy_unref(env, old); | |||
984 | ||||
985 | /* Update SA with new policy*/ | |||
986 | if (sa_new(env, sa->sa_hdr.sh_ispi, | |||
987 | sa->sa_hdr.sh_rspi, 0, msg->msg_policy) != sa) { | |||
988 | log_warnx("%s: failed to update SA", | |||
989 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
990 | ikev2_send_auth_failed(env, sa); | |||
991 | return (-1); | |||
992 | } | |||
993 | } else { | |||
994 | /* restore */ | |||
995 | msg->msg_policy = sa->sa_policy = old; | |||
996 | } | |||
997 | if (ikev2_handle_certreq(env, msg) != 0) | |||
998 | return (-1); | |||
999 | } else if (sa->sa_hdr.sh_initiator) { | |||
1000 | old = sa->sa_policy; | |||
1001 | ||||
1002 | /* verify policy on initiator */ | |||
1003 | sa->sa_policy = NULL((void *)0); | |||
1004 | if (policy_lookup(env, msg, &sa->sa_proposals, &old->pol_flows, | |||
1005 | old->pol_nflows) != 0 || msg->msg_policy != old) { | |||
1006 | ||||
1007 | /* get dstid */ | |||
1008 | if (msg->msg_peerid.id_type) { | |||
1009 | memcpy(id, &msg->msg_peerid, sizeof(*id)); | |||
1010 | bzero(&msg->msg_peerid, sizeof(msg->msg_peerid)); | |||
1011 | } | |||
1012 | log_warnx("%s: policy mismatch", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
1013 | ikev2_send_auth_failed(env, sa); | |||
1014 | 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); | |||
1015 | policy_unref(env, old); | |||
1016 | return (-1); | |||
1017 | } | |||
1018 | /* restore */ | |||
1019 | msg->msg_policy = sa->sa_policy = old; | |||
1020 | } | |||
1021 | ||||
1022 | /* AUTH payload is required for non-EAP */ | |||
1023 | if (!msg->msg_auth.id_type && | |||
1024 | !sa->sa_policy->pol_auth.auth_eap) { | |||
1025 | /* get dstid */ | |||
1026 | if (msg->msg_peerid.id_type) { | |||
1027 | memcpy(id, &msg->msg_peerid, sizeof(*id)); | |||
1028 | bzero(&msg->msg_peerid, sizeof(msg->msg_peerid)); | |||
1029 | } | |||
1030 | log_debug("%s: missing auth payload", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
1031 | ikev2_send_auth_failed(env, sa); | |||
1032 | return (-1); | |||
1033 | } | |||
1034 | ||||
1035 | if (msg->msg_peerid.id_type) { | |||
1036 | memcpy(id, &msg->msg_peerid, sizeof(*id)); | |||
1037 | bzero(&msg->msg_peerid, sizeof(msg->msg_peerid)); | |||
1038 | ||||
1039 | if (!sa->sa_hdr.sh_initiator) { | |||
1040 | if ((authmsg = ikev2_msg_auth(env, sa, | |||
1041 | !sa->sa_hdr.sh_initiator)) == NULL((void *)0)) { | |||
1042 | log_debug("%s: failed to get response " | |||
1043 | "auth data", __func__); | |||
1044 | return (-1); | |||
1045 | } | |||
1046 | ||||
1047 | ca_setauth(env, sa, authmsg, PROC_CERT); | |||
1048 | ibuf_free(authmsg); | |||
1049 | } | |||
1050 | } | |||
1051 | ||||
1052 | /* Encode all received certs as single blob */ | |||
1053 | if (msg->msg_cert.id_type != IKEV2_CERT_BUNDLE254 && | |||
1054 | msg->msg_scert[0].id_type != IKEV2_CERT_NONE0) { | |||
1055 | if ((buf = ibuf_new(NULL((void *)0), 0)) == NULL((void *)0)) | |||
1056 | return (-1); | |||
1057 | /* begin with certificate */ | |||
1058 | if (ca_certbundle_add(buf, &msg->msg_cert) != 0) { | |||
1059 | ibuf_free(buf); | |||
1060 | return (-1); | |||
1061 | } | |||
1062 | /* add intermediate CAs */ | |||
1063 | for (i = 0; i < IKED_SCERT_MAX3; i++) { | |||
1064 | if (msg->msg_scert[i].id_type == IKEV2_CERT_NONE0) | |||
1065 | break; | |||
1066 | if (ca_certbundle_add(buf, &msg->msg_scert[i]) != 0) { | |||
1067 | ibuf_free(buf); | |||
1068 | return (-1); | |||
1069 | } | |||
1070 | } | |||
1071 | ibuf_free(msg->msg_cert.id_buf); | |||
1072 | msg->msg_cert.id_buf = buf; | |||
1073 | msg->msg_cert.id_type = IKEV2_CERT_BUNDLE254; | |||
1074 | } | |||
1075 | ||||
1076 | if (!TAILQ_EMPTY(&msg->msg_proposals)(((&msg->msg_proposals)->tqh_first) == ((void *)0))) { | |||
1077 | if (proposals_negotiate(&sa->sa_proposals, | |||
1078 | &sa->sa_policy->pol_proposals, &msg->msg_proposals, | |||
1079 | 0, -1) != 0) { | |||
1080 | log_info("%s: no proposal chosen", __func__); | |||
1081 | msg->msg_error = IKEV2_N_NO_PROPOSAL_CHOSEN14; | |||
1082 | ikestat_inc(env, ikes_sa_proposals_negotiate_failures)do { env->sc_stats.ikes_sa_proposals_negotiate_failures += (1); } while(0); | |||
1083 | return (-1); | |||
1084 | } else | |||
1085 | sa_stateflags(sa, IKED_REQ_SA0x0020); | |||
1086 | } | |||
1087 | ||||
1088 | if (msg->msg_auth.id_type) { | |||
1089 | memcpy(&sa->sa_peerauth, &msg->msg_auth, sizeof(sa->sa_peerauth)); | |||
1090 | bzero(&msg->msg_auth, sizeof(msg->msg_auth)); | |||
1091 | } | |||
1092 | ||||
1093 | if (msg->msg_cp) { | |||
1094 | if (msg->msg_cp_addr) { | |||
1095 | sa->sa_cp_addr = msg->msg_cp_addr; | |||
1096 | msg->msg_cp_addr = NULL((void *)0); | |||
1097 | } | |||
1098 | if (msg->msg_cp_addr6) { | |||
1099 | sa->sa_cp_addr6 = msg->msg_cp_addr6; | |||
1100 | msg->msg_cp_addr6 = NULL((void *)0); | |||
1101 | } | |||
1102 | if (msg->msg_cp_dns) { | |||
1103 | sa->sa_cp_dns = msg->msg_cp_dns; | |||
1104 | msg->msg_cp_dns = NULL((void *)0); | |||
1105 | } | |||
1106 | sa->sa_cp = msg->msg_cp; | |||
1107 | } | |||
1108 | ||||
1109 | /* For EAP and PSK AUTH can be verified without the CA process*/ | |||
1110 | if ((sa->sa_policy->pol_auth.auth_eap && | |||
1111 | sa->sa_eapmsk != NULL((void *)0)) || | |||
1112 | sa->sa_policy->pol_auth.auth_method == IKEV2_AUTH_SHARED_KEY_MIC2) | |||
1113 | ikev2_auth_verify(env, sa); | |||
1114 | /* For CERT and Pubkey AUTH the CA process must find a matching key */ | |||
1115 | else if (sa->sa_peerauth.id_type) { | |||
1116 | if (msg->msg_cert.id_type) { | |||
1117 | certtype = msg->msg_cert.id_type; | |||
1118 | cert = ibuf_data(msg->msg_cert.id_buf); | |||
1119 | certlen = ibuf_size(msg->msg_cert.id_buf); | |||
1120 | } | |||
1121 | sa->sa_stateflags &= ~IKED_REQ_CERTVALID0x0002; | |||
1122 | if (ca_setcert(env, &sa->sa_hdr, id, certtype, cert, certlen, PROC_CERT) == -1) | |||
1123 | return (-1); | |||
1124 | } | |||
1125 | ||||
1126 | if (sa->sa_cp == IKEV2_CP_REPLY2) { | |||
1127 | if (sa->sa_cp_addr) | |||
1128 | log_info("%s: obtained lease: %s", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
1129 | print_addr(&sa->sa_cp_addr->addr)); | |||
1130 | if (sa->sa_cp_addr6) | |||
1131 | log_info("%s: obtained lease: %s", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
1132 | print_addr(&sa->sa_cp_addr6->addr)); | |||
1133 | if (sa->sa_cp_dns) | |||
1134 | log_info("%s: obtained DNS: %s", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
1135 | print_addr(&sa->sa_cp_dns->addr)); | |||
1136 | } | |||
1137 | ||||
1138 | return ikev2_ike_auth(env, sa); | |||
1139 | } | |||
1140 | ||||
1141 | int | |||
1142 | ikev2_ike_auth(struct iked *env, struct iked_sa *sa) | |||
1143 | { | |||
1144 | /* Attempt state transition */ | |||
1145 | if (sa->sa_state == IKEV2_STATE_EAP_SUCCESS4) | |||
1146 | sa_state(env, sa, IKEV2_STATE_EAP_VALID8); | |||
1147 | else if (sa->sa_state == IKEV2_STATE_AUTH_SUCCESS6) | |||
1148 | sa_state(env, sa, IKEV2_STATE_VALID7); | |||
1149 | ||||
1150 | if (sa->sa_hdr.sh_initiator) { | |||
1151 | if (sa_stateok(sa, IKEV2_STATE_AUTH_SUCCESS6)) | |||
1152 | return (ikev2_init_done(env, sa)); | |||
1153 | /* AUTH exchange is awaiting response from CA process, ignore */ | |||
1154 | else if (sa_stateok(sa, IKEV2_STATE_AUTH_REQUEST5)) | |||
1155 | return (0); | |||
1156 | else | |||
1157 | return (ikev2_init_ike_auth(env, sa)); | |||
1158 | } | |||
1159 | return (ikev2_resp_ike_auth(env, sa)); | |||
1160 | } | |||
1161 | ||||
1162 | void | |||
1163 | ikev2_init_recv(struct iked *env, struct iked_message *msg, | |||
1164 | struct ike_header *hdr) | |||
1165 | { | |||
1166 | struct iked_sa *sa; | |||
1167 | struct iked_policy *pol; | |||
1168 | ||||
1169 | if (ikev2_msg_valid_ike_sa(env, hdr, msg) == -1) { | |||
1170 | log_debug("%s: unknown SA", __func__); | |||
1171 | return; | |||
1172 | } | |||
1173 | sa = msg->msg_sa; | |||
1174 | ||||
1175 | switch (hdr->ike_exchange) { | |||
1176 | case IKEV2_EXCHANGE_IKE_SA_INIT34: | |||
1177 | /* Update the SPIs */ | |||
1178 | if ((sa = sa_new(env, | |||
1179 | 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, | |||
1180 | NULL((void *)0))) == NULL((void *)0) || sa != msg->msg_sa) { | |||
1181 | log_debug("%s: invalid new SA", __func__); | |||
1182 | if (sa) { | |||
1183 | ikev2_ike_sa_setreason(sa, "invalid new SA"); | |||
1184 | sa_free(env, sa); | |||
1185 | } | |||
1186 | return; | |||
1187 | } | |||
1188 | break; | |||
1189 | case IKEV2_EXCHANGE_IKE_AUTH35: | |||
1190 | case IKEV2_EXCHANGE_CREATE_CHILD_SA36: | |||
1191 | case IKEV2_EXCHANGE_INFORMATIONAL37: | |||
1192 | break; | |||
1193 | default: | |||
1194 | log_debug("%s: unsupported exchange: %s", __func__, | |||
1195 | print_map(hdr->ike_exchange, ikev2_exchange_map)); | |||
1196 | return; | |||
1197 | } | |||
1198 | ||||
1199 | if (ikev2_pld_parse(env, hdr, msg, msg->msg_offset) != 0) { | |||
1200 | log_debug("%s: failed to parse message", __func__); | |||
1201 | return; | |||
1202 | } | |||
1203 | ||||
1204 | if (sa->sa_fragments.frag_count != 0) | |||
1205 | return; | |||
1206 | ||||
1207 | if (!ikev2_msg_frompeer(msg)) | |||
1208 | return; | |||
1209 | ||||
1210 | if (ikev2_handle_notifies(env, msg) != 0) | |||
1211 | return; | |||
1212 | ||||
1213 | if (msg->msg_nat_detected && sa->sa_natt == 0) | |||
1214 | ikev2_enable_natt(env, sa, msg, 1); | |||
1215 | ||||
1216 | switch (hdr->ike_exchange) { | |||
1217 | case IKEV2_EXCHANGE_IKE_SA_INIT34: | |||
1218 | if (ibuf_length(msg->msg_cookie)) { | |||
1219 | pol = sa->sa_policy; | |||
1220 | if (ikev2_init_ike_sa_peer(env, pol, | |||
1221 | &pol->pol_peer, msg) != 0) | |||
1222 | log_warnx("%s: failed to initiate a " | |||
1223 | "IKE_SA_INIT exchange", SPI_SA(sa,ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))) | |||
1224 | __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
1225 | break; | |||
1226 | } | |||
1227 | if (msg->msg_flags & IKED_MSG_FLAGS_NO_PROPOSAL_CHOSEN0x0400) { | |||
1228 | log_info("%s: failed to negotiate IKE SA", | |||
1229 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
1230 | ikev2_ike_sa_setreason(sa, "no proposal chosen"); | |||
1231 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
1232 | msg->msg_sa = NULL((void *)0); | |||
1233 | return; | |||
1234 | } | |||
1235 | if (ikev2_handle_certreq(env, msg) != 0) | |||
1236 | return; | |||
1237 | ||||
1238 | if (ikev2_init_auth(env, msg) != 0) { | |||
1239 | ikev2_ike_sa_setreason(sa, | |||
1240 | "failed to initiate IKE_AUTH exchange"); | |||
1241 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
1242 | msg->msg_sa = NULL((void *)0); | |||
1243 | return; | |||
1244 | } | |||
1245 | break; | |||
1246 | case IKEV2_EXCHANGE_IKE_AUTH35: | |||
1247 | if (msg->msg_flags & IKED_MSG_FLAGS_AUTHENTICATION_FAILED0x0020) { | |||
1248 | log_debug("%s: AUTHENTICATION_FAILED, closing SA", | |||
1249 | __func__); | |||
1250 | ikev2_log_cert_info(SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
1251 | sa->sa_hdr.sh_initiator ? &sa->sa_rcert | |||
1252 | : &sa->sa_icert); | |||
1253 | ikev2_ike_sa_setreason(sa, | |||
1254 | "authentication failed notification from peer"); | |||
1255 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
1256 | msg->msg_sa = NULL((void *)0); | |||
1257 | return; | |||
1258 | } | |||
1259 | if (msg->msg_flags & IKED_MSG_FLAGS_NO_PROPOSAL_CHOSEN0x0400) { | |||
1260 | log_info("%s: failed to negotiate IKE SA", | |||
1261 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
1262 | ikev2_ike_sa_setreason(sa, "no proposal chosen (IKE SA)"); | |||
1263 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
1264 | msg->msg_sa = NULL((void *)0); | |||
1265 | return; | |||
1266 | } | |||
1267 | ||||
1268 | (void)ikev2_ike_auth_recv(env, sa, msg); | |||
1269 | break; | |||
1270 | case IKEV2_EXCHANGE_CREATE_CHILD_SA36: | |||
1271 | if (msg->msg_flags & IKED_MSG_FLAGS_NO_PROPOSAL_CHOSEN0x0400) { | |||
1272 | log_info("%s: CREATE_CHILD_SA failed", | |||
1273 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
1274 | ikev2_ike_sa_setreason(sa, "no proposal chosen (CHILD SA)"); | |||
1275 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
1276 | msg->msg_sa = NULL((void *)0); | |||
1277 | return; | |||
1278 | } | |||
1279 | (void)ikev2_init_create_child_sa(env, msg); | |||
1280 | break; | |||
1281 | case IKEV2_EXCHANGE_INFORMATIONAL37: | |||
1282 | sa->sa_stateflags &= ~IKED_REQ_INF0x0100; | |||
1283 | break; | |||
1284 | default: | |||
1285 | log_debug("%s: exchange %s not implemented", __func__, | |||
1286 | print_map(hdr->ike_exchange, ikev2_exchange_map)); | |||
1287 | break; | |||
1288 | } | |||
1289 | } | |||
1290 | ||||
1291 | void | |||
1292 | ikev2_enable_natt(struct iked *env, struct iked_sa *sa, | |||
1293 | struct iked_message *msg, int udpencap) | |||
1294 | { | |||
1295 | struct iked_socket *sock; | |||
1296 | in_port_t port; | |||
1297 | ||||
1298 | sock = ikev2_msg_getsocket(env, sa->sa_local.addr_af, 1); | |||
1299 | if (sock == NULL((void *)0)) | |||
1300 | return; | |||
1301 | ||||
1302 | /* | |||
1303 | * Update address information and use the NAT-T | |||
1304 | * port and socket, if available. | |||
1305 | */ | |||
1306 | 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))) | |||
1307 | (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))); | |||
1308 | sa->sa_local.addr_port = port; | |||
1309 | sa->sa_peer.addr_port = port; | |||
1310 | (void)socket_af((struct sockaddr *)&sa->sa_local.addr, port); | |||
1311 | (void)socket_af((struct sockaddr *)&sa->sa_peer.addr, port); | |||
1312 | ||||
1313 | msg->msg_fd = sa->sa_fd = sock->sock_fd; | |||
1314 | msg->msg_sock = sock; | |||
1315 | sa->sa_natt = 1; | |||
1316 | if (udpencap) | |||
1317 | sa->sa_udpencap = 1; | |||
1318 | ||||
1319 | log_debug("%s: detected NAT, enabling UDP encapsulation," | |||
1320 | " updated SA to peer %s local %s", __func__, | |||
1321 | print_addr(&sa->sa_peer.addr), print_addr(&sa->sa_local.addr)); | |||
1322 | } | |||
1323 | ||||
1324 | void | |||
1325 | ikev2_init_ike_sa(struct iked *env, void *arg) | |||
1326 | { | |||
1327 | struct iked_policy *pol; | |||
1328 | ||||
1329 | TAILQ_FOREACH(pol, &env->sc_policies, pol_entry)for((pol) = ((&env->sc_policies)->tqh_first); (pol) != ((void *)0); (pol) = ((pol)->pol_entry.tqe_next)) { | |||
1330 | if ((pol->pol_flags & IKED_POLICY_ACTIVE0x02) == 0) | |||
1331 | continue; | |||
1332 | if (!TAILQ_EMPTY(&pol->pol_sapeers)(((&pol->pol_sapeers)->tqh_first) == ((void *)0))) { | |||
1333 | log_debug("%s: \"%s\" is already active", | |||
1334 | __func__, pol->pol_name); | |||
1335 | continue; | |||
1336 | } | |||
1337 | ||||
1338 | log_info("%s: initiating \"%s\"", __func__, pol->pol_name); | |||
1339 | ||||
1340 | if (ikev2_init_ike_sa_peer(env, pol, &pol->pol_peer, NULL((void *)0))) | |||
1341 | log_debug("%s: failed to initiate with peer %s", | |||
1342 | __func__, print_addr(&pol->pol_peer.addr)); | |||
1343 | } | |||
1344 | ||||
1345 | timer_set(env, &env->sc_inittmr, ikev2_init_ike_sa, NULL((void *)0)); | |||
1346 | timer_add(env, &env->sc_inittmr, IKED_INITIATOR_INTERVAL60); | |||
1347 | } | |||
1348 | ||||
1349 | void | |||
1350 | ikev2_init_ike_sa_timeout(struct iked *env, void *arg) | |||
1351 | { | |||
1352 | struct iked_sa *sa = arg; | |||
1353 | ||||
1354 | log_debug("%s: ispi %s rspi %s", __func__, | |||
1355 | print_spi(sa->sa_hdr.sh_ispi, 8), | |||
1356 | print_spi(sa->sa_hdr.sh_rspi, 8)); | |||
1357 | ||||
1358 | ikev2_ike_sa_setreason(sa, "SA_INIT timeout"); | |||
1359 | sa_free(env, sa); | |||
1360 | } | |||
1361 | ||||
1362 | int | |||
1363 | ikev2_init_ike_sa_peer(struct iked *env, struct iked_policy *pol, | |||
1364 | struct iked_addr *peer, struct iked_message *retry) | |||
1365 | { | |||
1366 | struct sockaddr_storage ss; | |||
1367 | struct iked_message req; | |||
1368 | struct ike_header *hdr; | |||
1369 | struct ikev2_payload *pld; | |||
1370 | struct ikev2_keyexchange *ke; | |||
1371 | struct ikev2_notify *n; | |||
1372 | struct iked_sa *sa = NULL((void *)0); | |||
1373 | struct ibuf *buf, *cookie = NULL((void *)0), *vendor_id = NULL((void *)0); | |||
1374 | struct dh_group *group; | |||
1375 | ssize_t len; | |||
1376 | int ret = -1; | |||
1377 | struct iked_socket *sock; | |||
1378 | in_port_t port; | |||
1379 | ||||
1380 | if ((sock = ikev2_msg_getsocket(env, peer->addr_af, 0)) == NULL((void *)0)) | |||
1381 | return (-1); | |||
1382 | ||||
1383 | if (retry != NULL((void *)0)) { | |||
1384 | sa = retry->msg_sa; | |||
1385 | cookie = retry->msg_cookie; | |||
1386 | sa_state(env, sa, IKEV2_STATE_INIT0); | |||
1387 | } | |||
1388 | ||||
1389 | /* Create a new initiator SA */ | |||
1390 | if (sa == NULL((void *)0) && | |||
1391 | (sa = sa_new(env, 0, 0, 1, pol)) == NULL((void *)0)) | |||
1392 | return (-1); | |||
1393 | ||||
1394 | /* Pick peer's DH group if asked */ | |||
1395 | if (pol->pol_peerdh > 0 && sa->sa_dhgroupsa_kex.kex_dhgroup == NULL((void *)0) && | |||
1396 | (sa->sa_dhgroupsa_kex.kex_dhgroup = group_get(pol->pol_peerdh)) == NULL((void *)0)) { | |||
1397 | log_warnx("%s: invalid peer DH group %u", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
1398 | pol->pol_peerdh); | |||
1399 | goto closeonly; | |||
1400 | } | |||
1401 | sa->sa_reqid = 0; | |||
1402 | ||||
1403 | if (ikev2_sa_initiator(env, sa, NULL((void *)0), NULL((void *)0)) == -1) | |||
1404 | goto closeonly; | |||
1405 | ||||
1406 | if (pol->pol_local.addr.ss_family == AF_UNSPEC0) { | |||
1407 | if (socket_getaddr(sock->sock_fd, &ss) == -1) | |||
1408 | goto closeonly; | |||
1409 | } else | |||
1410 | memcpy(&ss, &pol->pol_local.addr, pol->pol_local.addr.ss_len); | |||
1411 | ||||
1412 | if ((buf = ikev2_msg_init(env, &req, &peer->addr, peer->addr.ss_len, | |||
1413 | &ss, ss.ss_len, 0)) == NULL((void *)0)) | |||
1414 | goto done; | |||
1415 | ||||
1416 | /* Inherit the port from the 1st send socket */ | |||
1417 | 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))); | |||
1418 | (void)socket_af((struct sockaddr *)&req.msg_local, port); | |||
1419 | (void)socket_af((struct sockaddr *)&req.msg_peer, port); | |||
1420 | ||||
1421 | req.msg_fd = sock->sock_fd; | |||
1422 | req.msg_sa = sa; | |||
1423 | req.msg_sock = sock; | |||
1424 | req.msg_msgid = ikev2_msg_id(env, sa); | |||
1425 | ||||
1426 | /* IKE header */ | |||
1427 | if ((hdr = ikev2_add_header(buf, sa, req.msg_msgid, | |||
1428 | cookie == NULL((void *)0) ? IKEV2_PAYLOAD_SA33 : IKEV2_PAYLOAD_NOTIFY41, | |||
1429 | IKEV2_EXCHANGE_IKE_SA_INIT34, 0)) == NULL((void *)0)) | |||
1430 | goto done; | |||
1431 | ||||
1432 | /* Reflect COOKIE */ | |||
1433 | if (cookie) { | |||
1434 | if ((pld = ikev2_add_payload(buf)) == NULL((void *)0)) | |||
1435 | goto done; | |||
1436 | if ((n = ibuf_reserve(buf, sizeof(*n))) == NULL((void *)0)) | |||
1437 | goto done; | |||
1438 | n->n_protoid = IKEV2_SAPROTO_NONE0; | |||
1439 | n->n_spisize = 0; | |||
1440 | 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)); | |||
1441 | if (ikev2_add_buf(buf, cookie) == -1) | |||
1442 | goto done; | |||
1443 | len = sizeof(*n) + ibuf_size(cookie); | |||
1444 | ||||
1445 | log_debug("%s: added cookie, len %zu", __func__, | |||
1446 | ibuf_size(cookie)); | |||
1447 | print_hexbuf(cookie); | |||
1448 | ||||
1449 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_SA33) == -1) | |||
1450 | goto done; | |||
1451 | } | |||
1452 | ||||
1453 | /* SA payload */ | |||
1454 | if ((pld = ikev2_add_payload(buf)) == NULL((void *)0)) | |||
1455 | goto done; | |||
1456 | if ((len = ikev2_add_proposals(env, sa, buf, &pol->pol_proposals, | |||
1457 | IKEV2_SAPROTO_IKE1, sa->sa_hdr.sh_initiator, 0, 0)) == -1) | |||
1458 | goto done; | |||
1459 | ||||
1460 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_KE34) == -1) | |||
1461 | goto done; | |||
1462 | ||||
1463 | /* KE payload */ | |||
1464 | if ((pld = ikev2_add_payload(buf)) == NULL((void *)0)) | |||
1465 | goto done; | |||
1466 | if ((ke = ibuf_reserve(buf, sizeof(*ke))) == NULL((void *)0)) | |||
1467 | goto done; | |||
1468 | if ((group = sa->sa_dhgroupsa_kex.kex_dhgroup) == NULL((void *)0)) { | |||
1469 | log_debug("%s: invalid dh", __func__); | |||
1470 | goto done; | |||
1471 | } | |||
1472 | 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)); | |||
1473 | if (ikev2_add_buf(buf, sa->sa_dhiexchangesa_kex.kex_dhiexchange) == -1) | |||
1474 | goto done; | |||
1475 | len = sizeof(*ke) + ibuf_size(sa->sa_dhiexchangesa_kex.kex_dhiexchange); | |||
1476 | ||||
1477 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONCE40) == -1) | |||
1478 | goto done; | |||
1479 | ||||
1480 | /* NONCE payload */ | |||
1481 | if ((pld = ikev2_add_payload(buf)) == NULL((void *)0)) | |||
1482 | goto done; | |||
1483 | if (ikev2_add_buf(buf, sa->sa_inoncesa_kex.kex_inonce) == -1) | |||
1484 | goto done; | |||
1485 | len = ibuf_size(sa->sa_inoncesa_kex.kex_inonce); | |||
1486 | ||||
1487 | if (env->sc_vendoridsc_static.st_vendorid != 0) { | |||
1488 | vendor_id = ibuf_new(IKED_VENDOR_ID"OpenIKED-", strlen(IKED_VENDOR_ID"OpenIKED-")); | |||
1489 | ibuf_add(vendor_id, IKED_VERSION"7.2", strlen(IKED_VERSION"7.2")); | |||
1490 | if ((len = ikev2_add_vendor_id(buf, &pld, len, vendor_id)) | |||
1491 | == -1) | |||
1492 | goto done; | |||
1493 | } | |||
1494 | ||||
1495 | /* Fragmentation Notify */ | |||
1496 | if (env->sc_fragsc_static.st_frag) { | |||
1497 | if ((len = ikev2_add_fragmentation(buf, &pld, len)) | |||
1498 | == -1) | |||
1499 | goto done; | |||
1500 | } | |||
1501 | ||||
1502 | if (env->sc_nattmode != NATT_DISABLE) { | |||
1503 | 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) { | |||
1504 | /* Enforce NAT-T on the initiator side */ | |||
1505 | log_debug("%s: enforcing NAT-T", __func__); | |||
1506 | req.msg_natt = sa->sa_natt = sa->sa_udpencap = 1; | |||
1507 | } | |||
1508 | if ((len = ikev2_add_nat_detection(env, buf, &pld, &req, len)) | |||
1509 | == -1) | |||
1510 | goto done; | |||
1511 | } | |||
1512 | ||||
1513 | if ((len = ikev2_add_sighashnotify(buf, &pld, len)) == -1) | |||
1514 | goto done; | |||
1515 | ||||
1516 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONE0) == -1) | |||
1517 | goto done; | |||
1518 | ||||
1519 | if (ikev2_set_header(hdr, ibuf_size(buf) - sizeof(*hdr)) == -1) | |||
1520 | goto done; | |||
1521 | ||||
1522 | (void)ikev2_pld_parse(env, hdr, &req, 0); | |||
1523 | ||||
1524 | ibuf_free(sa->sa_1stmsg); | |||
1525 | if ((sa->sa_1stmsg = ibuf_dup(buf)) == NULL((void *)0)) { | |||
1526 | log_debug("%s: failed to copy 1st message", __func__); | |||
1527 | goto done; | |||
1528 | } | |||
1529 | ||||
1530 | if ((ret = ikev2_msg_send(env, &req)) == 0) | |||
1531 | sa_state(env, sa, IKEV2_STATE_SA_INIT2); | |||
1532 | ||||
1533 | /* Setup exchange timeout. */ | |||
1534 | timer_set(env, &sa->sa_timer, ikev2_init_ike_sa_timeout, sa); | |||
1535 | timer_add(env, &sa->sa_timer, IKED_IKE_SA_EXCHANGE_TIMEOUT300); | |||
1536 | ||||
1537 | done: | |||
1538 | ikev2_msg_cleanup(env, &req); | |||
1539 | closeonly: | |||
1540 | if (ret == -1) { | |||
1541 | log_debug("%s: closing SA", __func__); | |||
1542 | ikev2_ike_sa_setreason(sa, "failed to send SA_INIT"); | |||
1543 | sa_free(env, sa); | |||
1544 | } | |||
1545 | ibuf_free(vendor_id); | |||
1546 | ||||
1547 | return (ret); | |||
1548 | } | |||
1549 | ||||
1550 | int | |||
1551 | ikev2_init_auth(struct iked *env, struct iked_message *msg) | |||
1552 | { | |||
1553 | struct iked_sa *sa = msg->msg_sa; | |||
1554 | struct ibuf *authmsg; | |||
1555 | ||||
1556 | if (sa == NULL((void *)0)) | |||
1557 | return (-1); | |||
1558 | ||||
1559 | if (ikev2_sa_initiator(env, sa, NULL((void *)0), msg) == -1) { | |||
1560 | log_info("%s: failed to get IKE keys", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
1561 | return (-1); | |||
1562 | } | |||
1563 | ||||
1564 | if ((authmsg = ikev2_msg_auth(env, sa, | |||
1565 | !sa->sa_hdr.sh_initiator)) == NULL((void *)0)) { | |||
1566 | log_info("%s: failed to get auth data", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
1567 | return (-1); | |||
1568 | } | |||
1569 | ||||
1570 | if (ca_setauth(env, sa, authmsg, PROC_CERT) == -1) { | |||
1571 | log_info("%s: failed to get cert", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
1572 | ibuf_free(authmsg); | |||
1573 | return (-1); | |||
1574 | } | |||
1575 | ibuf_free(authmsg); | |||
1576 | ||||
1577 | return (ikev2_init_ike_auth(env, sa)); | |||
1578 | } | |||
1579 | ||||
1580 | int | |||
1581 | ikev2_init_ike_auth(struct iked *env, struct iked_sa *sa) | |||
1582 | { | |||
1583 | struct iked_policy *pol = sa->sa_policy; | |||
1584 | struct ikev2_payload *pld; | |||
1585 | struct ikev2_cert *cert; | |||
1586 | struct ikev2_auth *auth; | |||
1587 | struct iked_id *id, *certid, peerid; | |||
1588 | struct ibuf *e = NULL((void *)0); | |||
1589 | uint8_t firstpayload; | |||
1590 | int ret = -1; | |||
1591 | ssize_t len; | |||
1592 | int i; | |||
1593 | ||||
1594 | if (!sa_stateok(sa, IKEV2_STATE_SA_INIT2)) | |||
1595 | return (0); | |||
1596 | ||||
1597 | if (!sa->sa_localauth.id_type) { | |||
1598 | log_debug("%s: no local auth", __func__); | |||
1599 | return (0); | |||
1600 | } | |||
1601 | ||||
1602 | /* New encrypted message buffer */ | |||
1603 | if ((e = ibuf_static()) == NULL((void *)0)) | |||
1604 | goto done; | |||
1605 | ||||
1606 | id = &sa->sa_iid; | |||
1607 | certid = &sa->sa_icert; | |||
1608 | ||||
1609 | /* ID payloads */ | |||
1610 | if ((pld = ikev2_add_payload(e)) == NULL((void *)0)) | |||
1611 | goto done; | |||
1612 | firstpayload = IKEV2_PAYLOAD_IDi35; | |||
1613 | if (ibuf_add_buf(e, id->id_buf) != 0) | |||
1614 | goto done; | |||
1615 | len = ibuf_size(id->id_buf); | |||
1616 | ||||
1617 | if (pol->pol_peerid.id_type) { | |||
1618 | bzero(&peerid, sizeof(peerid)); | |||
1619 | if (ikev2_policy2id(&pol->pol_peerid, &peerid, 0) != 0) { | |||
1620 | log_debug("%s: failed to get remote id", __func__); | |||
1621 | goto done; | |||
1622 | } | |||
1623 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_IDr36) == -1) | |||
1624 | goto done; | |||
1625 | if ((pld = ikev2_add_payload(e)) == NULL((void *)0)) | |||
1626 | goto done; | |||
1627 | if (ibuf_add_buf(e, peerid.id_buf) != 0) | |||
1628 | goto done; | |||
1629 | len = ibuf_size(peerid.id_buf); | |||
1630 | } | |||
1631 | ||||
1632 | /* CERT payload */ | |||
1633 | if ((sa->sa_stateinit & IKED_REQ_CERT0x0001) && | |||
1634 | (certid->id_type != IKEV2_CERT_NONE0)) { | |||
1635 | if (ikev2_next_payload(pld, len, | |||
1636 | IKEV2_PAYLOAD_CERT37) == -1) | |||
1637 | goto done; | |||
1638 | if ((pld = ikev2_add_payload(e)) == NULL((void *)0)) | |||
1639 | goto done; | |||
1640 | if ((cert = ibuf_reserve(e, sizeof(*cert))) == NULL((void *)0)) | |||
1641 | goto done; | |||
1642 | cert->cert_type = certid->id_type; | |||
1643 | if (ibuf_add_buf(e, certid->id_buf) != 0) | |||
1644 | goto done; | |||
1645 | len = ibuf_size(certid->id_buf) + sizeof(*cert); | |||
1646 | ||||
1647 | for (i = 0; i < IKED_SCERT_MAX3; i++) { | |||
1648 | if (sa->sa_scert[i].id_type == IKEV2_CERT_NONE0) | |||
1649 | break; | |||
1650 | if (ikev2_next_payload(pld, len, | |||
1651 | IKEV2_PAYLOAD_CERT37) == -1) | |||
1652 | goto done; | |||
1653 | if ((pld = ikev2_add_payload(e)) == NULL((void *)0)) | |||
1654 | goto done; | |||
1655 | if ((cert = ibuf_reserve(e, sizeof(*cert))) == NULL((void *)0)) | |||
1656 | goto done; | |||
1657 | cert->cert_type = sa->sa_scert[i].id_type; | |||
1658 | if (ibuf_add_buf(e, sa->sa_scert[i].id_buf) != 0) | |||
1659 | goto done; | |||
1660 | len = ibuf_size(sa->sa_scert[i].id_buf) + sizeof(*cert); | |||
1661 | } | |||
1662 | ||||
1663 | /* CERTREQ payload(s) */ | |||
1664 | if ((len = ikev2_add_certreq(e, &pld, | |||
1665 | len, env->sc_certreq, env->sc_certreqtype)) == -1) | |||
1666 | goto done; | |||
1667 | ||||
1668 | if (env->sc_certreqtype != pol->pol_certreqtype && | |||
1669 | (len = ikev2_add_certreq(e, &pld, | |||
1670 | len, NULL((void *)0), pol->pol_certreqtype)) == -1) | |||
1671 | goto done; | |||
1672 | } | |||
1673 | ||||
1674 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_AUTH39) == -1) | |||
1675 | goto done; | |||
1676 | ||||
1677 | /* AUTH payload */ | |||
1678 | if ((pld = ikev2_add_payload(e)) == NULL((void *)0)) | |||
1679 | goto done; | |||
1680 | if ((auth = ibuf_reserve(e, sizeof(*auth))) == NULL((void *)0)) | |||
1681 | goto done; | |||
1682 | auth->auth_method = sa->sa_localauth.id_type; | |||
1683 | if (ibuf_add_buf(e, sa->sa_localauth.id_buf) != 0) | |||
1684 | goto done; | |||
1685 | len = ibuf_size(sa->sa_localauth.id_buf) + sizeof(*auth); | |||
1686 | ||||
1687 | /* CP payload */ | |||
1688 | if (ikev2_cp_request_configured(sa)) { | |||
1689 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_CP47) == -1) | |||
1690 | goto done; | |||
1691 | if ((pld = ikev2_add_payload(e)) == NULL((void *)0)) | |||
1692 | goto done; | |||
1693 | if ((len = ikev2_init_add_cp(env, sa, e)) == -1) | |||
1694 | goto done; | |||
1695 | } | |||
1696 | ||||
1697 | if ((pol->pol_flags & IKED_POLICY_IPCOMP0x20) && | |||
1698 | (len = ikev2_add_ipcompnotify(env, e, &pld, len, sa, 1)) == -1) | |||
1699 | goto done; | |||
1700 | if ((pol->pol_flags & IKED_POLICY_TRANSPORT0x40) && | |||
1701 | (len = ikev2_add_transport_mode(env, e, &pld, len, sa)) == -1) | |||
1702 | goto done; | |||
1703 | ||||
1704 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_SA33) == -1) | |||
1705 | goto done; | |||
1706 | ||||
1707 | /* SA payload */ | |||
1708 | if ((pld = ikev2_add_payload(e)) == NULL((void *)0)) | |||
1709 | goto done; | |||
1710 | if ((len = ikev2_add_proposals(env, sa, e, &pol->pol_proposals, 0, | |||
1711 | sa->sa_hdr.sh_initiator, 0, 1)) == -1) | |||
1712 | goto done; | |||
1713 | ||||
1714 | if ((len = ikev2_add_ts(e, &pld, len, sa, 0)) == -1) | |||
1715 | goto done; | |||
1716 | ||||
1717 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONE0) == -1) | |||
1718 | goto done; | |||
1719 | ||||
1720 | ret = ikev2_msg_send_encrypt(env, sa, &e, | |||
1721 | IKEV2_EXCHANGE_IKE_AUTH35, firstpayload, 0); | |||
1722 | ||||
1723 | done: | |||
1724 | ibuf_free(e); | |||
1725 | ||||
1726 | return (ret); | |||
1727 | } | |||
1728 | ||||
1729 | void | |||
1730 | ikev2_enable_timer(struct iked *env, struct iked_sa *sa) | |||
1731 | { | |||
1732 | sa->sa_last_recvd = gettime(); | |||
1733 | timer_set(env, &sa->sa_timer, ikev2_ike_sa_alive, sa); | |||
1734 | if (env->sc_alive_timeoutsc_static.st_alive_timeout > 0) | |||
1735 | timer_add(env, &sa->sa_timer, env->sc_alive_timeoutsc_static.st_alive_timeout); | |||
1736 | timer_set(env, &sa->sa_keepalive, ikev2_ike_sa_keepalive, sa); | |||
1737 | if (sa->sa_usekeepalive) | |||
1738 | timer_add(env, &sa->sa_keepalive, | |||
1739 | IKED_IKE_SA_KEEPALIVE_TIMEOUT20); | |||
1740 | timer_set(env, &sa->sa_rekey, ikev2_ike_sa_rekey, sa); | |||
1741 | if (sa->sa_policy->pol_rekey) | |||
1742 | ikev2_ike_sa_rekey_schedule(env, sa); | |||
1743 | } | |||
1744 | ||||
1745 | void | |||
1746 | ikev2_reset_alive_timer(struct iked *env) | |||
1747 | { | |||
1748 | struct iked_sa *sa; | |||
1749 | ||||
1750 | 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)) { | |||
1751 | if (sa->sa_state != IKEV2_STATE_ESTABLISHED9) | |||
1752 | continue; | |||
1753 | timer_del(env, &sa->sa_timer); | |||
1754 | if (env->sc_alive_timeoutsc_static.st_alive_timeout > 0) | |||
1755 | timer_add(env, &sa->sa_timer, env->sc_alive_timeoutsc_static.st_alive_timeout); | |||
1756 | } | |||
1757 | } | |||
1758 | ||||
1759 | void | |||
1760 | ikev2_disable_timer(struct iked *env, struct iked_sa *sa) | |||
1761 | { | |||
1762 | timer_del(env, &sa->sa_timer); | |||
1763 | timer_del(env, &sa->sa_keepalive); | |||
1764 | timer_del(env, &sa->sa_rekey); | |||
1765 | } | |||
1766 | ||||
1767 | int | |||
1768 | ikev2_init_done(struct iked *env, struct iked_sa *sa) | |||
1769 | { | |||
1770 | int ret; | |||
1771 | ||||
1772 | if (!sa_stateok(sa, IKEV2_STATE_VALID7)) | |||
1773 | return (0); /* ignored */ | |||
1774 | ||||
1775 | ret = ikev2_childsa_negotiate(env, sa, &sa->sa_kex, &sa->sa_proposals, | |||
1776 | sa->sa_hdr.sh_initiator, 0); | |||
1777 | if (ret == 0) | |||
1778 | ret = ikev2_childsa_enable(env, sa); | |||
1779 | if (ret == 0) { | |||
1780 | sa_state(env, sa, IKEV2_STATE_ESTABLISHED9); | |||
1781 | /* Delete exchange timeout. */ | |||
1782 | timer_del(env, &sa->sa_timer); | |||
1783 | ikev2_enable_timer(env, sa); | |||
1784 | ikev2_log_established(sa); | |||
1785 | ikev2_record_dstid(env, sa); | |||
1786 | sa_configure_iface(env, sa, 1); | |||
1787 | } | |||
1788 | ||||
1789 | if (ret) | |||
1790 | ikev2_childsa_delete(env, sa, 0, 0, NULL((void *)0), 1); | |||
1791 | return (ret); | |||
1792 | } | |||
1793 | ||||
1794 | int | |||
1795 | ikev2_policy2id(struct iked_static_id *polid, struct iked_id *id, int srcid) | |||
1796 | { | |||
1797 | struct ikev2_id hdr; | |||
1798 | struct iked_static_id localpid; | |||
1799 | char idstr[IKED_ID_SIZE1024]; | |||
1800 | struct in_addr in4; | |||
1801 | struct in6_addr in6; | |||
1802 | X509_NAME *name = NULL((void *)0); | |||
1803 | uint8_t *p; | |||
1804 | int len; | |||
1805 | ||||
1806 | /* Fixup the local Id if not specified */ | |||
1807 | if (srcid && polid->id_type == 0) { | |||
1808 | polid = &localpid; | |||
1809 | bzero(polid, sizeof(*polid)); | |||
1810 | ||||
1811 | /* Create a default local ID based on our FQDN */ | |||
1812 | polid->id_type = IKEV2_ID_FQDN2; | |||
1813 | if (gethostname((char *)polid->id_data, | |||
1814 | sizeof(polid->id_data)) != 0) | |||
1815 | return (-1); | |||
1816 | polid->id_offset = 0; | |||
1817 | polid->id_length = | |||
1818 | strlen((char *)polid->id_data); /* excluding NUL */ | |||
1819 | } | |||
1820 | ||||
1821 | if (!polid->id_length) | |||
1822 | return (-1); | |||
1823 | ||||
1824 | /* Create an IKEv2 ID payload */ | |||
1825 | bzero(&hdr, sizeof(hdr)); | |||
1826 | hdr.id_type = id->id_type = polid->id_type; | |||
1827 | id->id_offset = sizeof(hdr); | |||
1828 | ||||
1829 | ibuf_free(id->id_buf); | |||
1830 | if ((id->id_buf = ibuf_new(&hdr, sizeof(hdr))) == NULL((void *)0)) | |||
1831 | return (-1); | |||
1832 | ||||
1833 | switch (id->id_type) { | |||
1834 | case IKEV2_ID_IPV41: | |||
1835 | if (inet_pton(AF_INET2, (char *)polid->id_data, &in4) != 1 || | |||
1836 | ibuf_add(id->id_buf, &in4, sizeof(in4)) != 0) { | |||
1837 | ibuf_free(id->id_buf); | |||
1838 | id->id_buf = NULL((void *)0); | |||
1839 | return (-1); | |||
1840 | } | |||
1841 | break; | |||
1842 | case IKEV2_ID_IPV65: | |||
1843 | if (inet_pton(AF_INET624, (char *)polid->id_data, &in6) != 1 || | |||
1844 | ibuf_add(id->id_buf, &in6, sizeof(in6)) != 0) { | |||
1845 | ibuf_free(id->id_buf); | |||
1846 | id->id_buf = NULL((void *)0); | |||
1847 | return (-1); | |||
1848 | } | |||
1849 | break; | |||
1850 | case IKEV2_ID_ASN1_DN9: | |||
1851 | /* policy has ID in string-format, convert to ASN1 */ | |||
1852 | if ((name = ca_x509_name_parse(polid->id_data)) == NULL((void *)0) || | |||
1853 | (len = i2d_X509_NAME(name, NULL((void *)0))) < 0 || | |||
1854 | (p = ibuf_reserve(id->id_buf, len)) == NULL((void *)0) || | |||
1855 | (i2d_X509_NAME(name, &p)) < 0) { | |||
1856 | if (name) | |||
1857 | X509_NAME_free(name); | |||
1858 | ibuf_free(id->id_buf); | |||
1859 | id->id_buf = NULL((void *)0); | |||
1860 | return (-1); | |||
1861 | } | |||
1862 | X509_NAME_free(name); | |||
1863 | break; | |||
1864 | default: | |||
1865 | if (ibuf_add(id->id_buf, | |||
1866 | polid->id_data, polid->id_length) != 0) { | |||
1867 | ibuf_free(id->id_buf); | |||
1868 | id->id_buf = NULL((void *)0); | |||
1869 | return (-1); | |||
1870 | } | |||
1871 | break; | |||
1872 | } | |||
1873 | ||||
1874 | if (ikev2_print_id(id, idstr, sizeof(idstr)) == -1) | |||
1875 | return (-1); | |||
1876 | ||||
1877 | log_debug("%s: %s %s length %zu", __func__, | |||
1878 | srcid ? "srcid" : "dstid", | |||
1879 | idstr, ibuf_size(id->id_buf)); | |||
1880 | ||||
1881 | return (0); | |||
1882 | } | |||
1883 | ||||
1884 | struct ike_header * | |||
1885 | ikev2_add_header(struct ibuf *buf, struct iked_sa *sa, | |||
1886 | uint32_t msgid, uint8_t nextpayload, | |||
1887 | uint8_t exchange, uint8_t flags) | |||
1888 | { | |||
1889 | struct ike_header *hdr; | |||
1890 | ||||
1891 | if ((hdr = ibuf_reserve(buf, sizeof(*hdr))) == NULL((void *)0)) { | |||
1892 | log_debug("%s: failed to add header", __func__); | |||
1893 | return (NULL((void *)0)); | |||
1894 | } | |||
1895 | ||||
1896 | 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)); | |||
1897 | 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)); | |||
1898 | hdr->ike_nextpayload = nextpayload; | |||
1899 | hdr->ike_version = IKEV2_VERSION0x20; | |||
1900 | hdr->ike_exchange = exchange; | |||
1901 | 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)); | |||
1902 | 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))); | |||
1903 | hdr->ike_flags = flags; | |||
1904 | ||||
1905 | if (sa->sa_hdr.sh_initiator) | |||
1906 | hdr->ike_flags |= IKEV2_FLAG_INITIATOR0x08; | |||
1907 | ||||
1908 | return (hdr); | |||
1909 | } | |||
1910 | ||||
1911 | int | |||
1912 | ikev2_set_header(struct ike_header *hdr, size_t length) | |||
1913 | { | |||
1914 | uint32_t hdrlength = sizeof(*hdr) + length; | |||
1915 | ||||
1916 | if (hdrlength > UINT32_MAX0xffffffffU) { | |||
1917 | log_debug("%s: message too long", __func__); | |||
1918 | return (-1); | |||
1919 | } | |||
1920 | ||||
1921 | 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)); | |||
1922 | ||||
1923 | return (0); | |||
1924 | } | |||
1925 | ||||
1926 | struct ikev2_payload * | |||
1927 | ikev2_add_payload(struct ibuf *buf) | |||
1928 | { | |||
1929 | struct ikev2_payload *pld; | |||
1930 | ||||
1931 | if ((pld = ibuf_reserve(buf, sizeof(*pld))) == NULL((void *)0)) { | |||
1932 | log_debug("%s: failed to add payload", __func__); | |||
1933 | return (NULL((void *)0)); | |||
1934 | } | |||
1935 | ||||
1936 | pld->pld_nextpayload = IKEV2_PAYLOAD_NONE0; | |||
1937 | pld->pld_length = sizeof(*pld); | |||
1938 | ||||
1939 | return (pld); | |||
1940 | } | |||
1941 | ||||
1942 | ssize_t | |||
1943 | ikev2_add_ts_payload(struct ibuf *buf, unsigned int type, struct iked_sa *sa) | |||
1944 | { | |||
1945 | struct iked_policy *pol = sa->sa_policy; | |||
1946 | struct ikev2_tsp *tsp; | |||
1947 | struct ikev2_ts *ts; | |||
1948 | struct iked_addr *addr; | |||
1949 | struct iked_addr pooladdr; | |||
1950 | uint8_t *ptr; | |||
1951 | size_t len = 0; | |||
1952 | uint32_t av[4], bv[4], mv[4]; | |||
1953 | struct sockaddr_in *in4; | |||
1954 | struct sockaddr_in6 *in6; | |||
1955 | struct iked_tss *tss; | |||
1956 | struct iked_ts *tsi; | |||
1957 | ||||
1958 | bzero(&pooladdr, sizeof(pooladdr)); | |||
1959 | ||||
1960 | if ((tsp = ibuf_reserve(buf, sizeof(*tsp))) == NULL((void *)0)) | |||
1961 | return (-1); | |||
1962 | len = sizeof(*tsp); | |||
1963 | ||||
1964 | if (type == IKEV2_PAYLOAD_TSi44) { | |||
1965 | if (sa->sa_hdr.sh_initiator) { | |||
1966 | tss = &pol->pol_tssrc; | |||
1967 | tsp->tsp_count = pol->pol_tssrc_count; | |||
1968 | } else { | |||
1969 | tss = &pol->pol_tsdst; | |||
1970 | tsp->tsp_count = pol->pol_tsdst_count; | |||
1971 | } | |||
1972 | } else if (type == IKEV2_PAYLOAD_TSr45) { | |||
1973 | if (sa->sa_hdr.sh_initiator) { | |||
1974 | tss = &pol->pol_tsdst; | |||
1975 | tsp->tsp_count = pol->pol_tsdst_count; | |||
1976 | } else { | |||
1977 | tss = &pol->pol_tssrc; | |||
1978 | tsp->tsp_count = pol->pol_tssrc_count; | |||
1979 | } | |||
1980 | } else | |||
1981 | return (-1); | |||
1982 | ||||
1983 | TAILQ_FOREACH(tsi, tss, ts_entry)for((tsi) = ((tss)->tqh_first); (tsi) != ((void *)0); (tsi ) = ((tsi)->ts_entry.tqe_next)) { | |||
1984 | if ((ts = ibuf_reserve(buf, sizeof(*ts))) == NULL((void *)0)) | |||
1985 | return (-1); | |||
1986 | ||||
1987 | addr = &tsi->ts_addr; | |||
1988 | ||||
1989 | /* patch remote address (if configured to 0.0.0.0) */ | |||
1990 | if ((type == IKEV2_PAYLOAD_TSi44 && !sa->sa_hdr.sh_initiator) || | |||
1991 | (type == IKEV2_PAYLOAD_TSr45 && sa->sa_hdr.sh_initiator)) { | |||
1992 | if (ikev2_cp_fixaddr(sa, addr, &pooladdr) == 0) | |||
1993 | addr = &pooladdr; | |||
1994 | } | |||
1995 | ||||
1996 | ts->ts_protoid = tsi->ts_ipproto; | |||
1997 | ||||
1998 | if (addr->addr_port) { | |||
1999 | ts->ts_startport = addr->addr_port; | |||
2000 | ts->ts_endport = addr->addr_port; | |||
2001 | } else { | |||
2002 | ts->ts_startport = 0; | |||
2003 | ts->ts_endport = 0xffff; | |||
2004 | } | |||
2005 | ||||
2006 | switch (addr->addr_af) { | |||
2007 | case AF_INET2: | |||
2008 | ts->ts_type = IKEV2_TS_IPV4_ADDR_RANGE7; | |||
2009 | 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)); | |||
2010 | ||||
2011 | if ((ptr = ibuf_reserve(buf, 8)) == NULL((void *)0)) | |||
2012 | return (-1); | |||
2013 | ||||
2014 | in4 = (struct sockaddr_in *)&addr->addr; | |||
2015 | if (addr->addr_net) { | |||
2016 | /* Convert IPv4 network to address range */ | |||
2017 | mv[0] = prefixlen2mask(addr->addr_mask); | |||
2018 | av[0] = in4->sin_addr.s_addr & mv[0]; | |||
2019 | bv[0] = in4->sin_addr.s_addr | ~mv[0]; | |||
2020 | } else | |||
2021 | av[0] = bv[0] = in4->sin_addr.s_addr; | |||
2022 | ||||
2023 | memcpy(ptr, &av[0], 4); | |||
2024 | memcpy(ptr + 4, &bv[0], 4); | |||
2025 | break; | |||
2026 | case AF_INET624: | |||
2027 | ts->ts_type = IKEV2_TS_IPV6_ADDR_RANGE8; | |||
2028 | 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)); | |||
2029 | ||||
2030 | if ((ptr = ibuf_reserve(buf, 32)) == NULL((void *)0)) | |||
2031 | return (-1); | |||
2032 | ||||
2033 | in6 = (struct sockaddr_in6 *)&addr->addr; | |||
2034 | ||||
2035 | memcpy(&av, &in6->sin6_addr.s6_addr__u6_addr.__u6_addr8, 16); | |||
2036 | memcpy(&bv, &in6->sin6_addr.s6_addr__u6_addr.__u6_addr8, 16); | |||
2037 | if (addr->addr_net) { | |||
2038 | /* Convert IPv6 network to address range */ | |||
2039 | prefixlen2mask6(addr->addr_mask, mv); | |||
2040 | av[0] &= mv[0]; | |||
2041 | av[1] &= mv[1]; | |||
2042 | av[2] &= mv[2]; | |||
2043 | av[3] &= mv[3]; | |||
2044 | bv[0] |= ~mv[0]; | |||
2045 | bv[1] |= ~mv[1]; | |||
2046 | bv[2] |= ~mv[2]; | |||
2047 | bv[3] |= ~mv[3]; | |||
2048 | } | |||
2049 | ||||
2050 | memcpy(ptr, &av, 16); | |||
2051 | memcpy(ptr + 16, &bv, 16); | |||
2052 | break; | |||
2053 | } | |||
2054 | ||||
2055 | 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)); | |||
2056 | } | |||
2057 | ||||
2058 | return (len); | |||
2059 | } | |||
2060 | ||||
2061 | ssize_t | |||
2062 | ikev2_add_ts(struct ibuf *e, struct ikev2_payload **pld, ssize_t len, | |||
2063 | struct iked_sa *sa, int reverse) | |||
2064 | { | |||
2065 | if (ikev2_next_payload(*pld, len, IKEV2_PAYLOAD_TSi44) == -1) | |||
2066 | return (-1); | |||
2067 | ||||
2068 | /* TSi payload */ | |||
2069 | if ((*pld = ikev2_add_payload(e)) == NULL((void *)0)) | |||
2070 | return (-1); | |||
2071 | if ((len = ikev2_add_ts_payload(e, reverse ? IKEV2_PAYLOAD_TSr45 : | |||
2072 | IKEV2_PAYLOAD_TSi44, sa)) == -1) | |||
2073 | return (-1); | |||
2074 | ||||
2075 | if (ikev2_next_payload(*pld, len, IKEV2_PAYLOAD_TSr45) == -1) | |||
2076 | return (-1); | |||
2077 | ||||
2078 | /* TSr payload */ | |||
2079 | if ((*pld = ikev2_add_payload(e)) == NULL((void *)0)) | |||
2080 | return (-1); | |||
2081 | if ((len = ikev2_add_ts_payload(e, reverse ? IKEV2_PAYLOAD_TSi44 : | |||
2082 | IKEV2_PAYLOAD_TSr45, sa)) == -1) | |||
2083 | return (-1); | |||
2084 | ||||
2085 | return (len); | |||
2086 | } | |||
2087 | ||||
2088 | ||||
2089 | ssize_t | |||
2090 | ikev2_add_certreq(struct ibuf *e, struct ikev2_payload **pld, ssize_t len, | |||
2091 | struct ibuf *certreq, uint8_t type) | |||
2092 | { | |||
2093 | struct ikev2_cert *cert; | |||
2094 | ||||
2095 | if (type == IKEV2_CERT_NONE0) | |||
2096 | return (len); | |||
2097 | ||||
2098 | if (ikev2_next_payload(*pld, len, IKEV2_PAYLOAD_CERTREQ38) == -1) | |||
2099 | return (-1); | |||
2100 | ||||
2101 | /* CERTREQ payload */ | |||
2102 | if ((*pld = ikev2_add_payload(e)) == NULL((void *)0)) | |||
2103 | return (-1); | |||
2104 | ||||
2105 | if ((cert = ibuf_reserve(e, sizeof(*cert))) == NULL((void *)0)) | |||
2106 | return (-1); | |||
2107 | ||||
2108 | cert->cert_type = type; | |||
2109 | len = sizeof(*cert); | |||
2110 | ||||
2111 | if (certreq != NULL((void *)0) && cert->cert_type == IKEV2_CERT_X509_CERT4) { | |||
2112 | if (ikev2_add_buf(e, certreq) == -1) | |||
2113 | return (-1); | |||
2114 | len += ibuf_size(certreq); | |||
2115 | } | |||
2116 | ||||
2117 | log_debug("%s: type %s length %zd", __func__, | |||
2118 | print_map(type, ikev2_cert_map), len); | |||
2119 | ||||
2120 | return (len); | |||
2121 | } | |||
2122 | ||||
2123 | ssize_t | |||
2124 | ikev2_add_ipcompnotify(struct iked *env, struct ibuf *e, | |||
2125 | struct ikev2_payload **pld, ssize_t len, struct iked_sa *sa, | |||
2126 | int initiator) | |||
2127 | { | |||
2128 | struct iked_childsa csa; | |||
2129 | struct iked_ipcomp *ic; | |||
2130 | struct ikev2_notify *n; | |||
2131 | uint8_t *ptr; | |||
2132 | uint16_t cpi; | |||
2133 | uint32_t spi; | |||
2134 | uint8_t transform; | |||
2135 | ||||
2136 | /* we only support deflate */ | |||
2137 | transform = IKEV2_IPCOMP_DEFLATE2; | |||
2138 | ic = initiator ? &sa->sa_ipcompi : &sa->sa_ipcompr; | |||
2139 | ||||
2140 | if (initiator) { | |||
2141 | bzero(&csa, sizeof(csa)); | |||
2142 | csa.csa_saproto = IKEV2_SAPROTO_IPCOMP204; | |||
2143 | csa.csa_ikesa = sa; | |||
2144 | csa.csa_local = &sa->sa_peer; | |||
2145 | csa.csa_peer = &sa->sa_local; | |||
2146 | if (pfkey_sa_init(env, &csa, &spi) == -1) | |||
2147 | return (-1); | |||
2148 | ic->ic_cpi_in = spi; | |||
2149 | } else { | |||
2150 | spi = ic->ic_cpi_in; | |||
2151 | /* make sure IPCOMP CPIs are not reused */ | |||
2152 | ic->ic_transform = 0; | |||
2153 | ic->ic_cpi_in = 0; | |||
2154 | ic->ic_cpi_out = 0; | |||
2155 | } | |||
2156 | log_debug("%s: ic_cpi_in 0x%04x", __func__, spi); | |||
2157 | ||||
2158 | /* | |||
2159 | * We get spi == 0 if the kernel does not support IPcomp, | |||
2160 | * so just return the length of the current payload. | |||
2161 | */ | |||
2162 | if (spi == 0) | |||
2163 | return (len); | |||
2164 | 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)); | |||
2165 | if (*pld) | |||
2166 | if (ikev2_next_payload(*pld, len, IKEV2_PAYLOAD_NOTIFY41) == -1) | |||
2167 | return (-1); | |||
2168 | if ((*pld = ikev2_add_payload(e)) == NULL((void *)0)) | |||
2169 | return (-1); | |||
2170 | len = sizeof(*n) + sizeof(cpi) + sizeof(transform); | |||
2171 | if ((ptr = ibuf_reserve(e, len)) == NULL((void *)0)) | |||
2172 | return (-1); | |||
2173 | n = (struct ikev2_notify *)ptr; | |||
2174 | n->n_protoid = 0; | |||
2175 | n->n_spisize = 0; | |||
2176 | 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)); | |||
2177 | ptr += sizeof(*n); | |||
2178 | memcpy(ptr, &cpi, sizeof(cpi)); | |||
2179 | ptr += sizeof(cpi); | |||
2180 | memcpy(ptr, &transform, sizeof(transform)); | |||
2181 | ||||
2182 | return (len); | |||
2183 | } | |||
2184 | ||||
2185 | ssize_t | |||
2186 | ikev2_add_notify(struct ibuf *e, struct ikev2_payload **pld, ssize_t len, | |||
2187 | uint16_t notify) | |||
2188 | { | |||
2189 | struct ikev2_notify *n; | |||
2190 | ||||
2191 | if (*pld) | |||
2192 | if (ikev2_next_payload(*pld, len, IKEV2_PAYLOAD_NOTIFY41) == -1) | |||
2193 | return (-1); | |||
2194 | if ((*pld = ikev2_add_payload(e)) == NULL((void *)0)) | |||
2195 | return (-1); | |||
2196 | len = sizeof(*n); | |||
2197 | if ((n = ibuf_reserve(e, len)) == NULL((void *)0)) | |||
2198 | return (-1); | |||
2199 | n->n_protoid = 0; | |||
2200 | n->n_spisize = 0; | |||
2201 | 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)); | |||
2202 | log_debug("%s: done", __func__); | |||
2203 | ||||
2204 | return (len); | |||
2205 | } | |||
2206 | ||||
2207 | ssize_t | |||
2208 | ikev2_add_vendor_id(struct ibuf *e, struct ikev2_payload **pld, | |||
2209 | ssize_t len, struct ibuf *id) | |||
2210 | { | |||
2211 | if (*pld) | |||
2212 | if (ikev2_next_payload(*pld, len, IKEV2_PAYLOAD_VENDOR43) == -1) | |||
2213 | return (-1); | |||
2214 | if ((*pld = ikev2_add_payload(e)) == NULL((void *)0)) | |||
2215 | return (-1); | |||
2216 | if (ibuf_add_buf(e, id) == -1) | |||
2217 | return (-1); | |||
2218 | ||||
2219 | return (ibuf_size(id)); | |||
2220 | } | |||
2221 | ||||
2222 | ssize_t | |||
2223 | ikev2_add_mobike(struct ibuf *e, struct ikev2_payload **pld, ssize_t len) | |||
2224 | { | |||
2225 | return ikev2_add_notify(e, pld, len, IKEV2_N_MOBIKE_SUPPORTED16396); | |||
2226 | } | |||
2227 | ||||
2228 | ssize_t | |||
2229 | ikev2_add_fragmentation(struct ibuf *buf, struct ikev2_payload **pld, | |||
2230 | ssize_t len) | |||
2231 | { | |||
2232 | return ikev2_add_notify(buf, pld, len, IKEV2_N_FRAGMENTATION_SUPPORTED16430); | |||
2233 | } | |||
2234 | ||||
2235 | ssize_t | |||
2236 | ikev2_add_sighashnotify(struct ibuf *e, struct ikev2_payload **pld, | |||
2237 | ssize_t len) | |||
2238 | { | |||
2239 | struct ikev2_notify *n; | |||
2240 | uint8_t *ptr; | |||
2241 | size_t i; | |||
2242 | uint16_t hash, signature_hashes[] = { | |||
2243 | IKEV2_SIGHASH_SHA2_2562, | |||
2244 | IKEV2_SIGHASH_SHA2_3843, | |||
2245 | IKEV2_SIGHASH_SHA2_5124 | |||
2246 | }; | |||
2247 | ||||
2248 | if (ikev2_next_payload(*pld, len, IKEV2_PAYLOAD_NOTIFY41) == -1) | |||
2249 | return (-1); | |||
2250 | ||||
2251 | /* XXX signature_hashes are hardcoded for now */ | |||
2252 | len = sizeof(*n) + nitems(signature_hashes)(sizeof((signature_hashes)) / sizeof((signature_hashes)[0])) * sizeof(hash); | |||
2253 | ||||
2254 | /* NOTIFY payload */ | |||
2255 | if ((*pld = ikev2_add_payload(e)) == NULL((void *)0)) | |||
2256 | return (-1); | |||
2257 | if ((ptr = ibuf_reserve(e, len)) == NULL((void *)0)) | |||
2258 | return (-1); | |||
2259 | ||||
2260 | n = (struct ikev2_notify *)ptr; | |||
2261 | n->n_protoid = 0; | |||
2262 | n->n_spisize = 0; | |||
2263 | 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)); | |||
2264 | ptr += sizeof(*n); | |||
2265 | ||||
2266 | for (i = 0; i < nitems(signature_hashes)(sizeof((signature_hashes)) / sizeof((signature_hashes)[0])); i++) { | |||
2267 | 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])); | |||
2268 | memcpy(ptr, &hash, sizeof(hash)); | |||
2269 | ptr += sizeof(hash); | |||
2270 | } | |||
2271 | ||||
2272 | return (len); | |||
2273 | } | |||
2274 | ||||
2275 | ssize_t | |||
2276 | ikev2_add_transport_mode(struct iked *env, struct ibuf *e, | |||
2277 | struct ikev2_payload **pld, ssize_t len, struct iked_sa *sa) | |||
2278 | { | |||
2279 | return ikev2_add_notify(e, pld, len, IKEV2_N_USE_TRANSPORT_MODE16391); | |||
2280 | } | |||
2281 | ||||
2282 | int | |||
2283 | ikev2_next_payload(struct ikev2_payload *pld, size_t length, | |||
2284 | uint8_t nextpayload) | |||
2285 | { | |||
2286 | size_t pldlength = sizeof(*pld) + length; | |||
2287 | ||||
2288 | if (pldlength > UINT16_MAX0xffff) { | |||
2289 | log_debug("%s: payload too long", __func__); | |||
2290 | return (-1); | |||
2291 | } | |||
2292 | ||||
2293 | log_debug("%s: length %zu nextpayload %s", | |||
2294 | __func__, pldlength, print_map(nextpayload, ikev2_payload_map)); | |||
2295 | ||||
2296 | 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 )); | |||
2297 | pld->pld_nextpayload = nextpayload; | |||
2298 | ||||
2299 | return (0); | |||
2300 | } | |||
2301 | ||||
2302 | ssize_t | |||
2303 | ikev2_nat_detection(struct iked *env, struct iked_message *msg, | |||
2304 | void *ptr, size_t len, unsigned int type, int frompeer) | |||
2305 | { | |||
2306 | EVP_MD_CTX *ctx; | |||
2307 | struct ike_header *hdr; | |||
2308 | uint8_t md[SHA_DIGEST_LENGTH20]; | |||
2309 | unsigned int mdlen = sizeof(md); | |||
2310 | struct iked_sa *sa = msg->msg_sa; | |||
2311 | struct sockaddr_in *in4; | |||
2312 | struct sockaddr_in6 *in6; | |||
2313 | ssize_t ret = -1; | |||
2314 | struct sockaddr_storage *src, *dst, *ss; | |||
2315 | uint64_t rspi, ispi; | |||
2316 | struct ibuf *buf; | |||
2317 | uint32_t rnd; | |||
2318 | ||||
2319 | if (ptr == NULL((void *)0)) | |||
2320 | return (mdlen); | |||
2321 | ||||
2322 | if (frompeer) { | |||
2323 | buf = msg->msg_parent->msg_data; | |||
2324 | if ((hdr = ibuf_seek(buf, 0, sizeof(*hdr))) == NULL((void *)0)) | |||
2325 | return (-1); | |||
2326 | ispi = hdr->ike_ispi; | |||
2327 | rspi = hdr->ike_rspi; | |||
2328 | src = &msg->msg_peer; | |||
2329 | dst = &msg->msg_local; | |||
2330 | } else { | |||
2331 | 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)); | |||
2332 | 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)); | |||
2333 | src = &msg->msg_local; | |||
2334 | dst = &msg->msg_peer; | |||
2335 | } | |||
2336 | ||||
2337 | ctx = EVP_MD_CTX_new(); | |||
2338 | if (ctx == NULL((void *)0)) | |||
2339 | return (-1); | |||
2340 | EVP_DigestInit_ex(ctx, EVP_sha1(), NULL((void *)0)); | |||
2341 | ||||
2342 | switch (type) { | |||
2343 | case IKEV2_N_NAT_DETECTION_SOURCE_IP16388: | |||
2344 | log_debug("%s: %s source %s %s %s", __func__, | |||
2345 | frompeer ? "peer" : "local", | |||
2346 | 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), | |||
2347 | 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), | |||
2348 | print_addr(src)); | |||
2349 | ss = src; | |||
2350 | break; | |||
2351 | case IKEV2_N_NAT_DETECTION_DESTINATION_IP16389: | |||
2352 | log_debug("%s: %s destination %s %s %s", __func__, | |||
2353 | frompeer ? "peer" : "local", | |||
2354 | 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), | |||
2355 | 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), | |||
2356 | print_addr(dst)); | |||
2357 | ss = dst; | |||
2358 | break; | |||
2359 | default: | |||
2360 | goto done; | |||
2361 | } | |||
2362 | ||||
2363 | EVP_DigestUpdate(ctx, &ispi, sizeof(ispi)); | |||
2364 | EVP_DigestUpdate(ctx, &rspi, sizeof(rspi)); | |||
2365 | ||||
2366 | switch (ss->ss_family) { | |||
2367 | case AF_INET2: | |||
2368 | in4 = (struct sockaddr_in *)ss; | |||
2369 | EVP_DigestUpdate(ctx, &in4->sin_addr.s_addr, | |||
2370 | sizeof(in4->sin_addr.s_addr)); | |||
2371 | EVP_DigestUpdate(ctx, &in4->sin_port, | |||
2372 | sizeof(in4->sin_port)); | |||
2373 | break; | |||
2374 | case AF_INET624: | |||
2375 | in6 = (struct sockaddr_in6 *)ss; | |||
2376 | EVP_DigestUpdate(ctx, &in6->sin6_addr.s6_addr__u6_addr.__u6_addr8, | |||
2377 | sizeof(in6->sin6_addr.s6_addr__u6_addr.__u6_addr8)); | |||
2378 | EVP_DigestUpdate(ctx, &in6->sin6_port, | |||
2379 | sizeof(in6->sin6_port)); | |||
2380 | break; | |||
2381 | default: | |||
2382 | goto done; | |||
2383 | } | |||
2384 | ||||
2385 | if (env->sc_nattmode == NATT_FORCE) { | |||
2386 | /* Enforce NAT-T/UDP-encapsulation by distorting the digest */ | |||
2387 | rnd = arc4random(); | |||
2388 | EVP_DigestUpdate(ctx, &rnd, sizeof(rnd)); | |||
2389 | } | |||
2390 | ||||
2391 | EVP_DigestFinal_ex(ctx, md, &mdlen); | |||
2392 | ||||
2393 | if (len < mdlen) | |||
2394 | goto done; | |||
2395 | ||||
2396 | memcpy(ptr, md, mdlen); | |||
2397 | ret = mdlen; | |||
2398 | done: | |||
2399 | EVP_MD_CTX_free(ctx); | |||
2400 | ||||
2401 | return (ret); | |||
2402 | } | |||
2403 | ||||
2404 | ssize_t | |||
2405 | ikev2_add_nat_detection(struct iked *env, struct ibuf *buf, | |||
2406 | struct ikev2_payload **pld, struct iked_message *msg, ssize_t len) | |||
2407 | { | |||
2408 | struct ikev2_notify *n; | |||
2409 | uint8_t *ptr; | |||
2410 | ||||
2411 | /* *pld is NULL if there is no previous payload */ | |||
2412 | if (*pld != NULL((void *)0)) { | |||
2413 | if (ikev2_next_payload(*pld, len, IKEV2_PAYLOAD_NOTIFY41) == -1) | |||
2414 | return (-1); | |||
2415 | } | |||
2416 | /* NAT-T notify payloads */ | |||
2417 | if ((*pld = ikev2_add_payload(buf)) == NULL((void *)0)) | |||
2418 | return (-1); | |||
2419 | if ((n = ibuf_reserve(buf, sizeof(*n))) == NULL((void *)0)) | |||
2420 | return (-1); | |||
2421 | 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)); | |||
2422 | len = ikev2_nat_detection(env, msg, NULL((void *)0), 0, 0, 0); | |||
2423 | if ((ptr = ibuf_reserve(buf, len)) == NULL((void *)0)) | |||
2424 | return (-1); | |||
2425 | if ((len = ikev2_nat_detection(env, msg, ptr, len, | |||
2426 | 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) | |||
2427 | return (-1); | |||
2428 | len += sizeof(*n); | |||
2429 | ||||
2430 | if (ikev2_next_payload(*pld, len, IKEV2_PAYLOAD_NOTIFY41) == -1) | |||
2431 | return (-1); | |||
2432 | ||||
2433 | if ((*pld = ikev2_add_payload(buf)) == NULL((void *)0)) | |||
2434 | return (-1); | |||
2435 | if ((n = ibuf_reserve(buf, sizeof(*n))) == NULL((void *)0)) | |||
2436 | return (-1); | |||
2437 | 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)); | |||
2438 | len = ikev2_nat_detection(env, msg, NULL((void *)0), 0, 0, 0); | |||
2439 | if ((ptr = ibuf_reserve(buf, len)) == NULL((void *)0)) | |||
2440 | return (-1); | |||
2441 | if ((len = ikev2_nat_detection(env, msg, ptr, len, | |||
2442 | 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) | |||
2443 | return (-1); | |||
2444 | len += sizeof(*n); | |||
2445 | return (len); | |||
2446 | } | |||
2447 | ||||
2448 | ssize_t | |||
2449 | ikev2_add_cp(struct iked *env, struct iked_sa *sa, int type, struct ibuf *buf) | |||
2450 | { | |||
2451 | struct iked_policy *pol = sa->sa_policy; | |||
2452 | struct ikev2_cp *cp; | |||
2453 | struct ikev2_cfg *cfg; | |||
2454 | struct iked_cfg *ikecfg; | |||
2455 | unsigned int i; | |||
2456 | uint32_t mask4; | |||
2457 | size_t len; | |||
2458 | struct sockaddr_in *in4; | |||
2459 | struct sockaddr_in6 *in6; | |||
2460 | uint8_t prefixlen; | |||
2461 | int sent_addr4 = 0, sent_addr6 = 0; | |||
2462 | int have_mask4 = 0, sent_mask4 = 0; | |||
2463 | ||||
2464 | if ((cp = ibuf_reserve(buf, sizeof(*cp))) == NULL((void *)0)) | |||
2465 | return (-1); | |||
2466 | len = sizeof(*cp); | |||
2467 | ||||
2468 | switch (type) { | |||
2469 | case IKEV2_CP_REQUEST1: | |||
2470 | case IKEV2_CP_REPLY2: | |||
2471 | cp->cp_type = type; | |||
2472 | break; | |||
2473 | default: | |||
2474 | /* Not yet supported */ | |||
2475 | return (-1); | |||
2476 | } | |||
2477 | ||||
2478 | for (i = 0; i < pol->pol_ncfg; i++) { | |||
2479 | ikecfg = &pol->pol_cfg[i]; | |||
2480 | if (ikecfg->cfg_action != cp->cp_type) | |||
2481 | continue; | |||
2482 | /* only return one address in case of multiple pools */ | |||
2483 | if (type == IKEV2_CP_REPLY2) { | |||
2484 | switch (ikecfg->cfg_type) { | |||
2485 | case IKEV2_CFG_INTERNAL_IP4_ADDRESS1: | |||
2486 | if (sent_addr4) | |||
2487 | continue; | |||
2488 | break; | |||
2489 | case IKEV2_CFG_INTERNAL_IP6_ADDRESS8: | |||
2490 | if (sent_addr6) | |||
2491 | continue; | |||
2492 | break; | |||
2493 | } | |||
2494 | } | |||
2495 | ||||
2496 | if ((cfg = ibuf_reserve(buf, sizeof(*cfg))) == NULL((void *)0)) | |||
2497 | return (-1); | |||
2498 | ||||
2499 | 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)); | |||
2500 | len += sizeof(*cfg); | |||
2501 | ||||
2502 | switch (ikecfg->cfg_type) { | |||
2503 | case IKEV2_CFG_INTERNAL_IP4_ADDRESS1: | |||
2504 | case IKEV2_CFG_INTERNAL_IP4_NETMASK2: | |||
2505 | case IKEV2_CFG_INTERNAL_IP4_DNS3: | |||
2506 | case IKEV2_CFG_INTERNAL_IP4_NBNS4: | |||
2507 | case IKEV2_CFG_INTERNAL_IP4_DHCP6: | |||
2508 | case IKEV2_CFG_INTERNAL_IP4_SERVER23456: | |||
2509 | /* 4 bytes IPv4 address */ | |||
2510 | in4 = ((ikecfg->cfg_type == | |||
2511 | IKEV2_CFG_INTERNAL_IP4_ADDRESS1) && | |||
2512 | sa->sa_addrpool && | |||
2513 | sa->sa_addrpool->addr_af == AF_INET2) ? | |||
2514 | (struct sockaddr_in *)&sa->sa_addrpool->addr : | |||
2515 | (struct sockaddr_in *)&ikecfg->cfg.address.addr; | |||
2516 | /* don't include unspecified address in request */ | |||
2517 | if (type == IKEV2_CP_REQUEST1 && | |||
2518 | !in4->sin_addr.s_addr) | |||
2519 | break; | |||
2520 | 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)); | |||
2521 | if (ibuf_add(buf, &in4->sin_addr.s_addr, 4) == -1) | |||
2522 | return (-1); | |||
2523 | len += 4; | |||
2524 | if (ikecfg->cfg_type == IKEV2_CFG_INTERNAL_IP4_ADDRESS1) { | |||
2525 | sent_addr4 = 1; | |||
2526 | if (sa->sa_addrpool && | |||
2527 | sa->sa_addrpool->addr_af == AF_INET2 && | |||
2528 | sa->sa_addrpool->addr_mask != 0) | |||
2529 | have_mask4 = 1; | |||
2530 | } | |||
2531 | if (ikecfg->cfg_type == IKEV2_CFG_INTERNAL_IP4_NETMASK2) | |||
2532 | sent_mask4 = 1; | |||
2533 | break; | |||
2534 | case IKEV2_CFG_INTERNAL_IP4_SUBNET13: | |||
2535 | /* 4 bytes IPv4 address + 4 bytes IPv4 mask + */ | |||
2536 | in4 = (struct sockaddr_in *)&ikecfg->cfg.address.addr; | |||
2537 | mask4 = prefixlen2mask(ikecfg->cfg.address.addr_mask); | |||
2538 | 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)); | |||
2539 | if (ibuf_add(buf, &in4->sin_addr.s_addr, 4) == -1) | |||
2540 | return (-1); | |||
2541 | if (ibuf_add(buf, &mask4, 4) == -1) | |||
2542 | return (-1); | |||
2543 | len += 8; | |||
2544 | break; | |||
2545 | case IKEV2_CFG_INTERNAL_IP6_DNS10: | |||
2546 | case IKEV2_CFG_INTERNAL_IP6_NBNS11: | |||
2547 | case IKEV2_CFG_INTERNAL_IP6_DHCP12: | |||
2548 | case IKEV2_CFG_INTERNAL_IP6_SERVER23457: | |||
2549 | /* 16 bytes IPv6 address */ | |||
2550 | in6 = (struct sockaddr_in6 *)&ikecfg->cfg.address.addr; | |||
2551 | 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)); | |||
2552 | if (ibuf_add(buf, &in6->sin6_addr.s6_addr__u6_addr.__u6_addr8, 16) == -1) | |||
2553 | return (-1); | |||
2554 | len += 16; | |||
2555 | break; | |||
2556 | case IKEV2_CFG_INTERNAL_IP6_ADDRESS8: | |||
2557 | case IKEV2_CFG_INTERNAL_IP6_SUBNET15: | |||
2558 | /* 16 bytes IPv6 address + 1 byte prefix length */ | |||
2559 | in6 = ((ikecfg->cfg_type == | |||
2560 | IKEV2_CFG_INTERNAL_IP6_ADDRESS8) && | |||
2561 | sa->sa_addrpool6 && | |||
2562 | sa->sa_addrpool6->addr_af == AF_INET624) ? | |||
2563 | (struct sockaddr_in6 *)&sa->sa_addrpool6->addr : | |||
2564 | (struct sockaddr_in6 *)&ikecfg->cfg.address.addr; | |||
2565 | /* don't include unspecified address in request */ | |||
2566 | if (type == IKEV2_CP_REQUEST1 && | |||
2567 | 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))) | |||
2568 | break; | |||
2569 | 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)); | |||
2570 | if (ibuf_add(buf, &in6->sin6_addr.s6_addr__u6_addr.__u6_addr8, 16) == -1) | |||
2571 | return (-1); | |||
2572 | if (ikecfg->cfg.address.addr_net) | |||
2573 | prefixlen = ikecfg->cfg.address.addr_mask; | |||
2574 | else | |||
2575 | prefixlen = 128; | |||
2576 | if (ibuf_add(buf, &prefixlen, 1) == -1) | |||
2577 | return (-1); | |||
2578 | len += 16 + 1; | |||
2579 | if (ikecfg->cfg_type == IKEV2_CFG_INTERNAL_IP6_ADDRESS8) | |||
2580 | sent_addr6 = 1; | |||
2581 | break; | |||
2582 | case IKEV2_CFG_APPLICATION_VERSION7: | |||
2583 | /* Reply with an empty string (non-NUL terminated) */ | |||
2584 | cfg->cfg_length = 0; | |||
2585 | break; | |||
2586 | } | |||
2587 | } | |||
2588 | ||||
2589 | /* derive netmask from pool */ | |||
2590 | if (type == IKEV2_CP_REPLY2 && have_mask4 && !sent_mask4) { | |||
2591 | if ((cfg = ibuf_reserve(buf, sizeof(*cfg))) == NULL((void *)0)) | |||
2592 | return (-1); | |||
2593 | 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)); | |||
2594 | len += sizeof(*cfg); | |||
2595 | mask4 = prefixlen2mask(sa->sa_addrpool->addr_mask); | |||
2596 | 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)); | |||
2597 | if (ibuf_add(buf, &mask4, 4) == -1) | |||
2598 | return (-1); | |||
2599 | len += 4; | |||
2600 | } | |||
2601 | ||||
2602 | return (len); | |||
2603 | } | |||
2604 | ||||
2605 | ssize_t | |||
2606 | ikev2_init_add_cp(struct iked *env, struct iked_sa *sa, struct ibuf *buf) | |||
2607 | { | |||
2608 | return (ikev2_add_cp(env, sa, IKEV2_CP_REQUEST1, buf)); | |||
2609 | } | |||
2610 | ||||
2611 | ssize_t | |||
2612 | ikev2_resp_add_cp(struct iked *env, struct iked_sa *sa, struct ibuf *buf) | |||
2613 | { | |||
2614 | int ret; | |||
2615 | ||||
2616 | switch (sa->sa_cp) { | |||
2617 | case IKEV2_CP_REQUEST1: | |||
2618 | ret = ikev2_add_cp(env, sa, IKEV2_CP_REPLY2, buf); | |||
2619 | break; | |||
2620 | case IKEV2_CP_REPLY2: | |||
2621 | case IKEV2_CP_SET3: | |||
2622 | case IKEV2_CP_ACK4: | |||
2623 | default: | |||
2624 | /* Not yet supported */ | |||
2625 | ret = -1; | |||
2626 | } | |||
2627 | return (ret); | |||
2628 | } | |||
2629 | ||||
2630 | ssize_t | |||
2631 | ikev2_add_proposals(struct iked *env, struct iked_sa *sa, struct ibuf *buf, | |||
2632 | struct iked_proposals *proposals, uint8_t protoid, int initiator, | |||
2633 | int sendikespi, int skipdh) | |||
2634 | { | |||
2635 | struct ikev2_sa_proposal *sap = NULL((void *)0); | |||
2636 | struct iked_transform *xform; | |||
2637 | struct iked_proposal *prop; | |||
2638 | struct iked_childsa csa; | |||
2639 | ssize_t length = 0, saplength, xflen; | |||
2640 | uint64_t spi64; | |||
2641 | uint32_t spi32, spi = 0; | |||
2642 | unsigned int i, xfi, nxforms; | |||
2643 | int prop_skipdh; | |||
2644 | ||||
2645 | TAILQ_FOREACH(prop, proposals, prop_entry)for((prop) = ((proposals)->tqh_first); (prop) != ((void *) 0); (prop) = ((prop)->prop_entry.tqe_next)) { | |||
2646 | if ((protoid && prop->prop_protoid != protoid) || | |||
2647 | (!protoid && prop->prop_protoid == IKEV2_SAPROTO_IKE1)) | |||
2648 | continue; | |||
2649 | ||||
2650 | prop_skipdh = skipdh; | |||
2651 | ||||
2652 | if (protoid != IKEV2_SAPROTO_IKE1 && initiator) { | |||
2653 | if (spi == 0) { | |||
2654 | bzero(&csa, sizeof(csa)); | |||
2655 | csa.csa_ikesa = sa; | |||
2656 | csa.csa_saproto = prop->prop_protoid; | |||
2657 | csa.csa_local = &sa->sa_peer; | |||
2658 | csa.csa_peer = &sa->sa_local; | |||
2659 | ||||
2660 | if (pfkey_sa_init(env, &csa, &spi) == -1) | |||
2661 | return (-1); | |||
2662 | } | |||
2663 | ||||
2664 | prop->prop_localspi.spi = spi; | |||
2665 | prop->prop_localspi.spi_size = 4; | |||
2666 | prop->prop_localspi.spi_protoid = prop->prop_protoid; | |||
2667 | } | |||
2668 | ||||
2669 | if ((sap = ibuf_reserve(buf, sizeof(*sap))) == NULL((void *)0)) { | |||
2670 | log_debug("%s: failed to add proposal", __func__); | |||
2671 | return (-1); | |||
2672 | } | |||
2673 | ||||
2674 | if (sendikespi) { | |||
2675 | /* Special case for IKE SA rekeying */ | |||
2676 | prop->prop_localspi.spi = initiator ? | |||
2677 | sa->sa_hdr.sh_ispi : sa->sa_hdr.sh_rspi; | |||
2678 | prop->prop_localspi.spi_size = 8; | |||
2679 | prop->prop_localspi.spi_protoid = IKEV2_SAPROTO_IKE1; | |||
2680 | } | |||
2681 | ||||
2682 | /* | |||
2683 | * A single DH transform of type NONE is equivalent with | |||
2684 | * not sending a DH transform at all. | |||
2685 | * Prefer the latter for downwards compatibility. | |||
2686 | */ | |||
2687 | if (protoid != IKEV2_SAPROTO_IKE1) { | |||
2688 | for (i = 0; i < prop->prop_nxforms; i++) { | |||
2689 | xform = prop->prop_xforms + i; | |||
2690 | if (xform->xform_type == IKEV2_XFORMTYPE_DH4 && | |||
2691 | xform->xform_id != IKEV2_XFORMDH_NONE0) | |||
2692 | break; | |||
2693 | } | |||
2694 | if (i == prop->prop_nxforms) | |||
2695 | prop_skipdh = 1; | |||
2696 | } | |||
2697 | ||||
2698 | /* | |||
2699 | * RFC 7296: 1.2. The Initial Exchanges | |||
2700 | * IKE_AUTH messages do not contain KE/N payloads, thus | |||
2701 | * SA payloads cannot contain groups. | |||
2702 | */ | |||
2703 | if (prop_skipdh) { | |||
2704 | nxforms = 0; | |||
2705 | for (i = 0; i < prop->prop_nxforms; i++) { | |||
2706 | xform = prop->prop_xforms + i; | |||
2707 | if (xform->xform_type == IKEV2_XFORMTYPE_DH4) | |||
2708 | continue; | |||
2709 | nxforms++; | |||
2710 | } | |||
2711 | } else | |||
2712 | nxforms = prop->prop_nxforms; | |||
2713 | ||||
2714 | sap->sap_more = IKEV1_PAYLOAD_PROPOSAL2; | |||
2715 | sap->sap_proposalnr = prop->prop_id; | |||
2716 | sap->sap_protoid = prop->prop_protoid; | |||
2717 | sap->sap_spisize = prop->prop_localspi.spi_size; | |||
2718 | sap->sap_transforms = nxforms; | |||
2719 | saplength = sizeof(*sap); | |||
2720 | ||||
2721 | switch (prop->prop_localspi.spi_size) { | |||
2722 | case 4: | |||
2723 | 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)); | |||
2724 | if (ibuf_add(buf, &spi32, sizeof(spi32)) != 0) | |||
2725 | return (-1); | |||
2726 | saplength += 4; | |||
2727 | break; | |||
2728 | case 8: | |||
2729 | 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)); | |||
2730 | if (ibuf_add(buf, &spi64, sizeof(spi64)) != 0) | |||
2731 | return (-1); | |||
2732 | saplength += 8; | |||
2733 | break; | |||
2734 | default: | |||
2735 | break; | |||
2736 | } | |||
2737 | ||||
2738 | for (i = 0, xfi = 0; i < prop->prop_nxforms; i++) { | |||
2739 | xform = prop->prop_xforms + i; | |||
2740 | ||||
2741 | if (prop_skipdh && xform->xform_type == IKEV2_XFORMTYPE_DH4) | |||
2742 | continue; | |||
2743 | ||||
2744 | if ((xflen = ikev2_add_transform(buf, | |||
2745 | xfi == nxforms - 1 ? | |||
2746 | IKEV2_XFORM_LAST0 : IKEV2_XFORM_MORE3, | |||
2747 | xform->xform_type, xform->xform_id, | |||
2748 | xform->xform_length)) == -1) | |||
2749 | return (-1); | |||
2750 | ||||
2751 | xfi++; | |||
2752 | saplength += xflen; | |||
2753 | } | |||
2754 | ||||
2755 | 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 )); | |||
2756 | length += saplength; | |||
2757 | } | |||
2758 | if (sap != NULL((void *)0)) | |||
2759 | sap->sap_more = IKEV1_PAYLOAD_NONE0; | |||
2760 | ||||
2761 | log_debug("%s: length %zd", __func__, length); | |||
2762 | ||||
2763 | return (length); | |||
2764 | } | |||
2765 | ||||
2766 | ssize_t | |||
2767 | ikev2_add_transform(struct ibuf *buf, | |||
2768 | uint8_t more, uint8_t type, uint16_t id, uint16_t length) | |||
2769 | { | |||
2770 | struct ikev2_transform *xfrm; | |||
2771 | struct ikev2_attribute *attr; | |||
2772 | ||||
2773 | if ((xfrm = ibuf_reserve(buf, sizeof(*xfrm))) == NULL((void *)0)) { | |||
2774 | log_debug("%s: failed to add transform", __func__); | |||
2775 | return (-1); | |||
2776 | } | |||
2777 | xfrm->xfrm_more = more; | |||
2778 | xfrm->xfrm_type = type; | |||
2779 | 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)); | |||
2780 | ||||
2781 | if (length) { | |||
2782 | 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))); | |||
2783 | ||||
2784 | if ((attr = ibuf_reserve(buf, sizeof(*attr))) == NULL((void *)0)) { | |||
2785 | log_debug("%s: failed to add attribute", __func__); | |||
2786 | return (-1); | |||
2787 | } | |||
2788 | 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)) | |||
2789 | 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)); | |||
2790 | 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)); | |||
2791 | } else | |||
2792 | 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))); | |||
2793 | ||||
2794 | 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))); | |||
2795 | } | |||
2796 | ||||
2797 | int | |||
2798 | ikev2_add_data(struct ibuf *buf, void *data, size_t length) | |||
2799 | { | |||
2800 | void *msgbuf; | |||
2801 | ||||
2802 | if ((msgbuf = ibuf_reserve(buf, length)) == NULL((void *)0)) { | |||
2803 | log_debug("%s: failed", __func__); | |||
2804 | return (-1); | |||
2805 | } | |||
2806 | memcpy(msgbuf, data, length); | |||
2807 | ||||
2808 | return (0); | |||
2809 | } | |||
2810 | ||||
2811 | int | |||
2812 | ikev2_add_buf(struct ibuf *buf, struct ibuf *data) | |||
2813 | { | |||
2814 | void *msgbuf; | |||
2815 | ||||
2816 | if ((msgbuf = ibuf_reserve(buf, ibuf_size(data))) == NULL((void *)0)) { | |||
2817 | log_debug("%s: failed", __func__); | |||
2818 | return (-1); | |||
2819 | } | |||
2820 | memcpy(msgbuf, ibuf_data(data), ibuf_size(data)); | |||
2821 | ||||
2822 | return (0); | |||
2823 | } | |||
2824 | ||||
2825 | int | |||
2826 | ikev2_resp_informational(struct iked *env, struct iked_sa *sa, | |||
2827 | struct iked_message *msg) | |||
2828 | { | |||
2829 | struct ikev2_notify *n; | |||
2830 | struct ikev2_payload *pld = NULL((void *)0); | |||
2831 | struct ibuf *buf = NULL((void *)0); | |||
2832 | ssize_t len = 0; | |||
2833 | int ret = -1; | |||
2834 | uint8_t firstpayload = IKEV2_PAYLOAD_NONE0; | |||
2835 | ||||
2836 | if (!sa_stateok(sa, IKEV2_STATE_AUTH_REQUEST5) || | |||
2837 | msg->msg_responded || msg->msg_error) | |||
2838 | goto done; | |||
2839 | ||||
2840 | if ((buf = ibuf_static()) == NULL((void *)0)) | |||
2841 | goto done; | |||
2842 | ||||
2843 | if ((len = ikev2_handle_delete(env, msg, buf, &pld, | |||
2844 | &firstpayload)) == -1) | |||
2845 | goto done; | |||
2846 | ||||
2847 | /* | |||
2848 | * Include NAT_DETECTION notification on UPDATE_SA_ADDRESSES or if | |||
2849 | * the peer did include them, too (RFC 4555, 3.8). | |||
2850 | */ | |||
2851 | if (sa->sa_mobike && | |||
2852 | (msg->msg_update_sa_addresses || msg->msg_natt_rcvd)) { | |||
2853 | /* NAT-T notify payloads */ | |||
2854 | len = ikev2_add_nat_detection(env, buf, &pld, msg, len); | |||
2855 | if (len == -1) | |||
2856 | goto done; | |||
2857 | firstpayload = IKEV2_PAYLOAD_NOTIFY41; | |||
2858 | } | |||
2859 | /* Reflect COOKIE2 */ | |||
2860 | if (msg->msg_cookie2) { | |||
2861 | /* *pld is NULL if there is no previous payload */ | |||
2862 | if (pld != NULL((void *)0)) { | |||
2863 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NOTIFY41) == -1) | |||
2864 | goto done; | |||
2865 | } | |||
2866 | if ((pld = ikev2_add_payload(buf)) == NULL((void *)0)) | |||
2867 | goto done; | |||
2868 | if ((n = ibuf_reserve(buf, sizeof(*n))) == NULL((void *)0)) | |||
2869 | goto done; | |||
2870 | n->n_protoid = IKEV2_SAPROTO_IKE1; | |||
2871 | n->n_spisize = 0; | |||
2872 | 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)); | |||
2873 | if (ikev2_add_buf(buf, msg->msg_cookie2) == -1) | |||
2874 | goto done; | |||
2875 | len = sizeof(*n) + ibuf_size(msg->msg_cookie2); | |||
2876 | log_debug("%s: added cookie2", __func__); | |||
2877 | if (firstpayload == IKEV2_PAYLOAD_NONE0) | |||
2878 | firstpayload = IKEV2_PAYLOAD_NOTIFY41; | |||
2879 | } | |||
2880 | /* add terminator, if there is already a payload */ | |||
2881 | if (firstpayload != IKEV2_PAYLOAD_NONE0) | |||
2882 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONE0) == -1) | |||
2883 | goto done; | |||
2884 | ret = ikev2_msg_send_encrypt(env, sa, &buf, | |||
2885 | IKEV2_EXCHANGE_INFORMATIONAL37, firstpayload, 1); | |||
2886 | if (ret != -1) | |||
2887 | msg->msg_responded = 1; | |||
2888 | if (msg->msg_flags & IKED_MSG_FLAGS_AUTHENTICATION_FAILED0x0020) { | |||
2889 | log_debug("%s: AUTHENTICATION_FAILED, closing SA", | |||
2890 | __func__); | |||
2891 | ikev2_log_cert_info(SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
2892 | sa->sa_hdr.sh_initiator ? &sa->sa_rcert : &sa->sa_icert); | |||
2893 | ikev2_ike_sa_setreason(sa, | |||
2894 | "authentication failed notification from peer"); | |||
2895 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
2896 | } | |||
2897 | done: | |||
2898 | ibuf_free(buf); | |||
2899 | return (ret); | |||
2900 | } | |||
2901 | ||||
2902 | void | |||
2903 | ikev2_resp_recv(struct iked *env, struct iked_message *msg, | |||
2904 | struct ike_header *hdr) | |||
2905 | { | |||
2906 | struct iked_sa *sa; | |||
2907 | ||||
2908 | switch (hdr->ike_exchange) { | |||
2909 | case IKEV2_EXCHANGE_IKE_SA_INIT34: | |||
2910 | if (msg->msg_sa != NULL((void *)0)) { | |||
2911 | log_debug("%s: SA already exists", __func__); | |||
2912 | return; | |||
2913 | } | |||
2914 | if ((msg->msg_sa = sa_new(env, | |||
2915 | 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)), | |||
2916 | 0, msg->msg_policy)) == NULL((void *)0)) { | |||
2917 | log_debug("%s: failed to get new SA", __func__); | |||
2918 | return; | |||
2919 | } | |||
2920 | /* Setup exchange timeout. */ | |||
2921 | timer_set(env, &msg->msg_sa->sa_timer, | |||
2922 | ikev2_init_ike_sa_timeout, msg->msg_sa); | |||
2923 | timer_add(env, &msg->msg_sa->sa_timer, | |||
2924 | IKED_IKE_SA_EXCHANGE_TIMEOUT300); | |||
2925 | break; | |||
2926 | case IKEV2_EXCHANGE_IKE_AUTH35: | |||
2927 | if (ikev2_msg_valid_ike_sa(env, hdr, msg) == -1) | |||
2928 | return; | |||
2929 | if (sa_stateok(msg->msg_sa, IKEV2_STATE_VALID7)) { | |||
2930 | log_debug("%s: already authenticated", __func__); | |||
2931 | return; | |||
2932 | } | |||
2933 | break; | |||
2934 | case IKEV2_EXCHANGE_CREATE_CHILD_SA36: | |||
2935 | case IKEV2_EXCHANGE_INFORMATIONAL37: | |||
2936 | if (ikev2_msg_valid_ike_sa(env, hdr, msg) == -1) | |||
2937 | return; | |||
2938 | break; | |||
2939 | default: | |||
2940 | log_debug("%s: unsupported exchange: %s", __func__, | |||
2941 | print_map(hdr->ike_exchange, ikev2_exchange_map)); | |||
2942 | return; | |||
2943 | } | |||
2944 | ||||
2945 | if (ikev2_pld_parse(env, hdr, msg, msg->msg_offset) != 0) { | |||
2946 | log_info("%s: failed to parse message", | |||
2947 | SPI_SA(msg->msg_sa, __func__)ikev2_ikesa_info((&(msg->msg_sa)->sa_hdr)->sh_ispi , ((__func__)))); | |||
2948 | return; | |||
2949 | } | |||
2950 | ||||
2951 | if (!ikev2_msg_frompeer(msg)) | |||
2952 | return; | |||
2953 | ||||
2954 | if (ikev2_handle_notifies(env, msg) != 0) | |||
2955 | return; | |||
2956 | ||||
2957 | if ((sa = msg->msg_sa) == NULL((void *)0)) | |||
2958 | return; | |||
2959 | ||||
2960 | if (sa->sa_fragments.frag_count != 0) | |||
2961 | return; | |||
2962 | ||||
2963 | msg->msg_valid = 1; | |||
2964 | ||||
2965 | if (msg->msg_natt && sa->sa_natt == 0) { | |||
2966 | log_debug("%s: NAT-T message received, updated SA", __func__); | |||
2967 | sa->sa_natt = 1; | |||
2968 | } | |||
2969 | ||||
2970 | switch (hdr->ike_exchange) { | |||
2971 | case IKEV2_EXCHANGE_IKE_SA_INIT34: | |||
2972 | if (ikev2_sa_responder(env, sa, NULL((void *)0), msg) != 0) { | |||
2973 | log_info("%s: failed to negotiate IKE SA", | |||
2974 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
2975 | if (msg->msg_error == 0) | |||
2976 | msg->msg_error = IKEV2_N_NO_PROPOSAL_CHOSEN14; | |||
2977 | ikev2_send_init_error(env, msg); | |||
2978 | ikev2_ike_sa_setreason(sa, "no proposal chosen"); | |||
2979 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
2980 | return; | |||
2981 | } | |||
2982 | if (ikev2_resp_ike_sa_init(env, msg) != 0) { | |||
2983 | log_debug("%s: failed to send init response", __func__); | |||
2984 | ikev2_ike_sa_setreason(sa, "SA_INIT response failed"); | |||
2985 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
2986 | return; | |||
2987 | } | |||
2988 | break; | |||
2989 | case IKEV2_EXCHANGE_IKE_AUTH35: | |||
2990 | if (!sa_stateok(sa, IKEV2_STATE_SA_INIT2)) { | |||
2991 | log_debug("%s: state mismatch", __func__); | |||
2992 | ikev2_ike_sa_setreason(sa, "state mismatch IKE_AUTH"); | |||
2993 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
2994 | return; | |||
2995 | } | |||
2996 | ||||
2997 | /* Handle EAP authentication */ | |||
2998 | if (msg->msg_eap.eam_found) { | |||
2999 | if (ikev2_resp_ike_eap(env, sa, msg)) { | |||
3000 | log_info("%s: failed eap response", | |||
3001 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
3002 | ikev2_ike_sa_setreason(sa, "EAP failed"); | |||
3003 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
3004 | return; | |||
3005 | } | |||
3006 | return; | |||
3007 | } | |||
3008 | ||||
3009 | if (ikev2_ike_auth_recv(env, sa, msg) != 0) { | |||
3010 | log_debug("%s: failed to send auth response", __func__); | |||
3011 | ikev2_send_error(env, sa, msg, hdr->ike_exchange); | |||
3012 | ikev2_ike_sa_setreason(sa, "IKE_AUTH failed"); | |||
3013 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
3014 | return; | |||
3015 | } | |||
3016 | break; | |||
3017 | case IKEV2_EXCHANGE_CREATE_CHILD_SA36: | |||
3018 | if (ikev2_resp_create_child_sa(env, msg) != 0) { | |||
3019 | if (msg->msg_error == 0) | |||
3020 | msg->msg_error = IKEV2_N_NO_PROPOSAL_CHOSEN14; | |||
3021 | ikev2_send_error(env, sa, msg, hdr->ike_exchange); | |||
3022 | } | |||
3023 | break; | |||
3024 | case IKEV2_EXCHANGE_INFORMATIONAL37: | |||
3025 | if (msg->msg_update_sa_addresses) | |||
3026 | ikev2_update_sa_addresses(env, sa); | |||
3027 | (void)ikev2_resp_informational(env, sa, msg); | |||
3028 | break; | |||
3029 | default: | |||
3030 | break; | |||
3031 | } | |||
3032 | } | |||
3033 | ||||
3034 | ssize_t | |||
3035 | ikev2_handle_delete(struct iked *env, struct iked_message *msg, | |||
3036 | struct ibuf *resp, struct ikev2_payload **pld, uint8_t *firstpayload) | |||
3037 | { | |||
3038 | struct iked_childsa **peersas = NULL((void *)0); | |||
3039 | struct iked_sa *sa = msg->msg_sa; | |||
3040 | struct ikev2_delete *localdel; | |||
3041 | FILE *spif; | |||
3042 | char *spibuf = NULL((void *)0); | |||
3043 | uint64_t *localspi = NULL((void *)0); | |||
3044 | uint64_t spi64, spi = 0; | |||
3045 | uint32_t spi32; | |||
3046 | uint8_t *buf; | |||
3047 | size_t found = 0; | |||
3048 | int ret = -1; | |||
3049 | size_t i, sz, cnt, len, dummy; | |||
3050 | ||||
3051 | if (!msg->msg_del_protoid) | |||
3052 | return (0); | |||
3053 | ||||
3054 | if ((spif = open_memstream(&spibuf, &dummy)) == NULL((void *)0)) { | |||
3055 | log_warn("%s", __func__); | |||
3056 | return (0); | |||
3057 | } | |||
3058 | ||||
3059 | sz = msg->msg_del_spisize; | |||
3060 | ||||
3061 | switch (sz) { | |||
3062 | case 4: | |||
3063 | case 8: | |||
3064 | break; | |||
3065 | case 0: | |||
3066 | if (msg->msg_del_protoid != IKEV2_SAPROTO_IKE1) { | |||
3067 | log_debug("%s: invalid SPI size", __func__); | |||
3068 | goto done; | |||
3069 | } | |||
3070 | ikev2_ikesa_recv_delete(env, sa); | |||
3071 | return (0); | |||
3072 | default: | |||
3073 | log_info("%s: error: invalid SPI size", __func__); | |||
3074 | goto done; | |||
3075 | } | |||
3076 | ||||
3077 | cnt = msg->msg_del_cnt; | |||
3078 | len = ibuf_length(msg->msg_del_buf); | |||
3079 | ||||
3080 | if ((len / sz) != cnt) { | |||
3081 | log_debug("%s: invalid payload length %zu/%zu != %zu", | |||
3082 | __func__, len, sz, cnt); | |||
3083 | return (-1); | |||
3084 | } | |||
3085 | ||||
3086 | if (((peersas = calloc(cnt, sizeof(struct iked_childsa *))) == NULL((void *)0) || | |||
3087 | (localspi = calloc(cnt, sizeof(uint64_t))) == NULL((void *)0))) { | |||
3088 | log_warn("%s", __func__); | |||
3089 | goto done; | |||
3090 | } | |||
3091 | ||||
3092 | buf = ibuf_data(msg->msg_del_buf); | |||
3093 | for (i = 0; i < cnt; i++) { | |||
3094 | switch (sz) { | |||
3095 | case 4: | |||
3096 | memcpy(&spi32, buf + (i * sz), sizeof(spi32)); | |||
3097 | 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)); | |||
3098 | break; | |||
3099 | case 8: | |||
3100 | memcpy(&spi64, buf + (i * sz), sizeof(spi64)); | |||
3101 | 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)); | |||
3102 | break; | |||
3103 | } | |||
3104 | ||||
3105 | log_debug("%s: spi %s", __func__, print_spi(spi, sz)); | |||
3106 | ||||
3107 | if (peersas == NULL((void *)0) || sa == NULL((void *)0)) | |||
3108 | continue; | |||
3109 | ||||
3110 | if ((peersas[i] = childsa_lookup(sa, spi, | |||
3111 | msg->msg_del_protoid)) == NULL((void *)0)) { | |||
3112 | log_warnx("%s: CHILD SA doesn't exist for spi %s", | |||
3113 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
3114 | print_spi(spi, sz)); | |||
3115 | continue; | |||
3116 | } | |||
3117 | ||||
3118 | if (ikev2_childsa_delete(env, sa, msg->msg_del_protoid, spi, | |||
3119 | &localspi[i], 0) != -1) { | |||
3120 | found++; | |||
3121 | /* append SPI to log buffer */ | |||
3122 | if (ftello(spif) > 0) | |||
3123 | fputs(", ", spif); | |||
3124 | fputs(print_spi(spi, sz), spif); | |||
3125 | } | |||
3126 | ||||
3127 | /* | |||
3128 | * Flows are left in the require mode so that it would be | |||
3129 | * possible to quickly negotiate a new Child SA | |||
3130 | */ | |||
3131 | } | |||
3132 | ||||
3133 | if (resp == NULL((void *)0)) { | |||
3134 | ret = 0; | |||
3135 | goto done; | |||
3136 | } | |||
3137 | ||||
3138 | /* Response to the INFORMATIONAL with Delete payload */ | |||
3139 | if (found) { | |||
3140 | if ((*pld = ikev2_add_payload(resp)) == NULL((void *)0)) | |||
3141 | goto done; | |||
3142 | *firstpayload = IKEV2_PAYLOAD_DELETE42; | |||
3143 | ||||
3144 | if ((localdel = ibuf_reserve(resp, sizeof(*localdel))) == NULL((void *)0)) | |||
3145 | goto done; | |||
3146 | ||||
3147 | localdel->del_protoid = msg->msg_del_protoid; | |||
3148 | localdel->del_spisize = sz; | |||
3149 | 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)); | |||
3150 | ret = sizeof(*localdel); | |||
3151 | ||||
3152 | for (i = 0; i < cnt; i++) { | |||
3153 | if (localspi[i] == 0) /* happens if found < cnt */ | |||
3154 | continue; | |||
3155 | switch (sz) { | |||
3156 | case 4: | |||
3157 | 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])); | |||
3158 | if (ibuf_add(resp, &spi32, sizeof(spi32)) != 0) | |||
3159 | goto done; | |||
3160 | ret += sizeof(spi32); | |||
3161 | break; | |||
3162 | case 8: | |||
3163 | 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])); | |||
3164 | if (ibuf_add(resp, &spi64, sizeof(spi64)) != 0) | |||
3165 | goto done; | |||
3166 | ret += sizeof(spi64); | |||
3167 | break; | |||
3168 | } | |||
3169 | } | |||
3170 | fflush(spif); | |||
3171 | if (!ferror(spif)(!__isthreaded ? (((spif)->_flags & 0x0040) != 0) : (ferror )(spif))) { | |||
3172 | log_info("%sdeleted %zu SPI%s: %s", | |||
3173 | SPI_SA(sa, NULL)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((((void *)0)))), found, found == 1 ? "" : "s", | |||
3174 | spibuf); | |||
3175 | } | |||
3176 | } else { | |||
3177 | /* XXX should we send an INVALID_SPI notification? */ | |||
3178 | ret = 0; | |||
3179 | } | |||
3180 | ||||
3181 | done: | |||
3182 | free(localspi); | |||
3183 | free(peersas); | |||
3184 | fclose(spif); | |||
3185 | free(spibuf); | |||
3186 | ||||
3187 | return (ret); | |||
3188 | } | |||
3189 | ||||
3190 | int | |||
3191 | ikev2_handle_notifies(struct iked *env, struct iked_message *msg) | |||
3192 | { | |||
3193 | struct iked_ipcomp *ic; | |||
3194 | struct iked_sa *sa; | |||
3195 | struct iked_spi rekey; | |||
3196 | struct dh_group *group; | |||
3197 | uint16_t groupid; | |||
3198 | unsigned int protoid; | |||
3199 | ||||
3200 | if ((sa = msg->msg_sa) == NULL((void *)0)) | |||
3201 | return (-1); | |||
3202 | ||||
3203 | if (msg->msg_flags & IKED_MSG_FLAGS_CHILD_SA_NOT_FOUND0x0008) | |||
3204 | sa->sa_stateflags &= ~IKED_REQ_CHILDSA0x0080; | |||
3205 | ||||
3206 | if ((msg->msg_flags & IKED_MSG_FLAGS_FRAGMENTATION0x0001) && env->sc_fragsc_static.st_frag) { | |||
3207 | log_debug("%s: fragmentation enabled", __func__); | |||
3208 | sa->sa_frag = 1; | |||
3209 | } | |||
3210 | ||||
3211 | if ((msg->msg_flags & IKED_MSG_FLAGS_MOBIKE0x0002) && env->sc_mobikesc_static.st_mobike) { | |||
3212 | log_debug("%s: mobike enabled", __func__); | |||
3213 | sa->sa_mobike = 1; | |||
3214 | /* enforce natt */ | |||
3215 | if (sa->sa_natt == 0 && sa->sa_udpencap == 0) | |||
3216 | ikev2_enable_natt(env, sa, msg, 0); | |||
3217 | } | |||
3218 | ||||
3219 | if ((msg->msg_flags & IKED_MSG_FLAGS_NO_ADDITIONAL_SAS0x0010) | |||
3220 | && sa->sa_stateflags & IKED_REQ_CHILDSA0x0080) { | |||
3221 | /* This makes sense for Child SAs only atm */ | |||
3222 | ikev2_disable_rekeying(env, sa); | |||
3223 | sa->sa_stateflags &= ~IKED_REQ_CHILDSA0x0080; | |||
3224 | } | |||
3225 | ||||
3226 | if (msg->msg_flags & IKED_MSG_FLAGS_INVALID_KE0x0040) { | |||
3227 | 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)); | |||
3228 | if (group_getid(groupid) == NULL((void *)0)) { | |||
3229 | log_debug("%s: unable to select DH group %u", | |||
3230 | __func__, groupid); | |||
3231 | ikev2_ike_sa_setreason(sa, | |||
3232 | "unable to select DH group"); | |||
3233 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
3234 | msg->msg_sa = NULL((void *)0); | |||
3235 | return (-1); | |||
3236 | } | |||
3237 | log_debug("%s: responder selected DH group %u", __func__, | |||
3238 | groupid); | |||
3239 | switch (msg->msg_exchange) { | |||
3240 | case IKEV2_EXCHANGE_IKE_SA_INIT34: | |||
3241 | protoid = IKEV2_SAPROTO_IKE1; | |||
3242 | if (!sa->sa_hdr.sh_initiator) { | |||
3243 | log_debug("%s: not an initiator", __func__); | |||
3244 | ikev2_ike_sa_setreason(sa, | |||
3245 | "received invalid KE as responder"); | |||
3246 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
3247 | msg->msg_sa = NULL((void *)0); | |||
3248 | return (-1); | |||
3249 | } | |||
3250 | if (config_findtransform_ext(&msg->msg_policy->pol_proposals, | |||
3251 | IKEV2_XFORMTYPE_DH4, groupid, protoid) == NULL((void *)0)) { | |||
3252 | log_debug("%s: DH group %u denied by policy", | |||
3253 | __func__, groupid); | |||
3254 | ikev2_ike_sa_setreason(sa, | |||
3255 | "unsupported group in INVALID_KE message"); | |||
3256 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
3257 | msg->msg_sa = NULL((void *)0); | |||
3258 | return (-1); | |||
3259 | } | |||
3260 | ikev2_ike_sa_setreason(sa, | |||
3261 | "reinitiating with new DH group"); | |||
3262 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
3263 | msg->msg_sa = NULL((void *)0); | |||
3264 | msg->msg_policy->pol_peerdh = groupid; | |||
3265 | timer_set(env, &env->sc_inittmr, ikev2_init_ike_sa, NULL((void *)0)); | |||
3266 | timer_add(env, &env->sc_inittmr, IKED_INITIATOR_INITIAL2); | |||
3267 | return (-1); | |||
3268 | case IKEV2_EXCHANGE_CREATE_CHILD_SA36: | |||
3269 | if (!(sa->sa_stateflags & IKED_REQ_CHILDSA0x0080)) { | |||
3270 | log_debug("%s: IKED_REQ_CHILDSA missing", | |||
3271 | __func__); | |||
3272 | return (-1); | |||
3273 | } | |||
3274 | sa->sa_stateflags &= ~IKED_REQ_CHILDSA0x0080; | |||
3275 | protoid = sa->sa_rekeyspi ? | |||
3276 | IKEV2_SAPROTO_ESP3 : IKEV2_SAPROTO_IKE1; | |||
3277 | if (config_findtransform_ext(&msg->msg_policy->pol_proposals, | |||
3278 | IKEV2_XFORMTYPE_DH4, groupid, protoid) == NULL((void *)0)) { | |||
3279 | log_debug("%s: DH group %u denied by policy", | |||
3280 | __func__, groupid); | |||
3281 | ikev2_ike_sa_setreason(sa, | |||
3282 | "unsupported group in INVALID_KE message"); | |||
3283 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
3284 | msg->msg_sa = NULL((void *)0); | |||
3285 | return (-1); | |||
3286 | } | |||
3287 | if (protoid == IKEV2_SAPROTO_ESP3) { | |||
3288 | /* CHILDSA */ | |||
3289 | rekey.spi = sa->sa_rekeyspi; | |||
3290 | rekey.spi_size = 4; | |||
3291 | rekey.spi_protoid = protoid; | |||
3292 | (void)ikev2_send_create_child_sa(env, sa, | |||
3293 | &rekey, rekey.spi_protoid, groupid); | |||
3294 | } else { | |||
3295 | /* IKESA */ | |||
3296 | if ((group = group_get(groupid)) == NULL((void *)0)) | |||
3297 | return -1; | |||
3298 | group_free(sa->sa_dhgroupsa_kex.kex_dhgroup); | |||
3299 | sa->sa_dhgroupsa_kex.kex_dhgroup = group; | |||
3300 | timer_set(env, &sa->sa_rekey, | |||
3301 | ikev2_ike_sa_rekey, sa); | |||
3302 | timer_add(env, &sa->sa_rekey, 0); | |||
3303 | } | |||
3304 | return (-1); | |||
3305 | } | |||
3306 | } | |||
3307 | ||||
3308 | if (msg->msg_flags & IKED_MSG_FLAGS_IPCOMP_SUPPORTED0x0080) { | |||
3309 | /* we only support deflate */ | |||
3310 | if ((msg->msg_policy->pol_flags & IKED_POLICY_IPCOMP0x20) && | |||
3311 | (msg->msg_transform == IKEV2_IPCOMP_DEFLATE2)) { | |||
3312 | ic = msg->msg_response ? | |||
3313 | &sa->sa_ipcompi : | |||
3314 | &sa->sa_ipcompr; | |||
3315 | ic->ic_transform = msg->msg_transform; | |||
3316 | 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)); | |||
3317 | } | |||
3318 | } | |||
3319 | ||||
3320 | if (msg->msg_nat_detected & IKED_MSG_NAT_DST_IP0x02) { | |||
3321 | /* Send keepalive, since we are behind a NAT-gw */ | |||
3322 | sa->sa_usekeepalive = 1; | |||
3323 | } | |||
3324 | ||||
3325 | /* Signature hash algorithm */ | |||
3326 | if (msg->msg_flags & IKED_MSG_FLAGS_SIGSHA20x0004) | |||
3327 | sa->sa_sigsha2 = 1; | |||
3328 | ||||
3329 | if (msg->msg_flags & IKED_MSG_FLAGS_USE_TRANSPORT0x0100) | |||
3330 | sa->sa_use_transport_mode = 1; | |||
3331 | ||||
3332 | if ((msg->msg_flags & IKED_MSG_FLAGS_TEMPORARY_FAILURE0x0200) | |||
3333 | && sa->sa_nexti != NULL((void *)0)) | |||
3334 | sa->sa_tmpfail = 1; | |||
3335 | ||||
3336 | return (0); | |||
3337 | } | |||
3338 | ||||
3339 | int | |||
3340 | ikev2_resp_ike_sa_init(struct iked *env, struct iked_message *msg) | |||
3341 | { | |||
3342 | struct iked_message resp; | |||
3343 | struct ike_header *hdr; | |||
3344 | struct ikev2_payload *pld; | |||
3345 | struct ikev2_keyexchange *ke; | |||
3346 | struct iked_sa *sa = msg->msg_sa; | |||
3347 | struct ibuf *buf; | |||
3348 | struct ibuf *vendor_id = NULL((void *)0); | |||
3349 | struct dh_group *group; | |||
3350 | ssize_t len; | |||
3351 | int ret = -1; | |||
3352 | ||||
3353 | if (sa->sa_hdr.sh_initiator) { | |||
3354 | log_debug("%s: called by initiator", __func__); | |||
3355 | return (-1); | |||
3356 | } | |||
3357 | if (msg->msg_nat_detected && sa->sa_udpencap == 0) { | |||
3358 | log_debug("%s: detected NAT, enabling UDP encapsulation", | |||
3359 | __func__); | |||
3360 | sa->sa_udpencap = 1; | |||
3361 | } | |||
3362 | ||||
3363 | if ((buf = ikev2_msg_init(env, &resp, | |||
3364 | &msg->msg_peer, msg->msg_peerlen, | |||
3365 | &msg->msg_local, msg->msg_locallen, 1)) == NULL((void *)0)) | |||
3366 | goto done; | |||
3367 | ||||
3368 | resp.msg_sa = sa; | |||
3369 | resp.msg_fd = msg->msg_fd; | |||
3370 | resp.msg_natt = msg->msg_natt; | |||
3371 | resp.msg_msgid = 0; | |||
3372 | ||||
3373 | /* IKE header */ | |||
3374 | if ((hdr = ikev2_add_header(buf, sa, resp.msg_msgid, | |||
3375 | IKEV2_PAYLOAD_SA33, IKEV2_EXCHANGE_IKE_SA_INIT34, | |||
3376 | IKEV2_FLAG_RESPONSE0x20)) == NULL((void *)0)) | |||
3377 | goto done; | |||
3378 | ||||
3379 | /* SA payload */ | |||
3380 | if ((pld = ikev2_add_payload(buf)) == NULL((void *)0)) | |||
3381 | goto done; | |||
3382 | if ((len = ikev2_add_proposals(env, sa, buf, &sa->sa_proposals, | |||
3383 | IKEV2_SAPROTO_IKE1, sa->sa_hdr.sh_initiator, 0, 0)) == -1) | |||
3384 | goto done; | |||
3385 | ||||
3386 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_KE34) == -1) | |||
3387 | goto done; | |||
3388 | ||||
3389 | /* KE payload */ | |||
3390 | if ((pld = ikev2_add_payload(buf)) == NULL((void *)0)) | |||
3391 | goto done; | |||
3392 | if ((ke = ibuf_reserve(buf, sizeof(*ke))) == NULL((void *)0)) | |||
3393 | goto done; | |||
3394 | if ((group = sa->sa_dhgroupsa_kex.kex_dhgroup) == NULL((void *)0)) { | |||
3395 | log_debug("%s: invalid dh", __func__); | |||
3396 | goto done; | |||
3397 | } | |||
3398 | 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)); | |||
3399 | if (ikev2_add_buf(buf, sa->sa_dhrexchangesa_kex.kex_dhrexchange) == -1) | |||
3400 | goto done; | |||
3401 | len = sizeof(*ke) + ibuf_size(sa->sa_dhrexchangesa_kex.kex_dhrexchange); | |||
3402 | ||||
3403 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONCE40) == -1) | |||
3404 | goto done; | |||
3405 | ||||
3406 | /* NONCE payload */ | |||
3407 | if ((pld = ikev2_add_payload(buf)) == NULL((void *)0)) | |||
3408 | goto done; | |||
3409 | if (ikev2_add_buf(buf, sa->sa_rnoncesa_kex.kex_rnonce) == -1) | |||
3410 | goto done; | |||
3411 | len = ibuf_size(sa->sa_rnoncesa_kex.kex_rnonce); | |||
3412 | ||||
3413 | if (env->sc_vendoridsc_static.st_vendorid != 0) { | |||
3414 | vendor_id = ibuf_new(IKED_VENDOR_ID"OpenIKED-", strlen(IKED_VENDOR_ID"OpenIKED-")); | |||
3415 | ibuf_add(vendor_id, IKED_VERSION"7.2", strlen(IKED_VERSION"7.2")); | |||
3416 | if ((len = ikev2_add_vendor_id(buf, &pld, len, vendor_id)) | |||
3417 | == -1) | |||
3418 | goto done; | |||
3419 | } | |||
3420 | ||||
3421 | /* Fragmentation Notify*/ | |||
3422 | if (sa->sa_frag) { | |||
3423 | if ((len = ikev2_add_fragmentation(buf, &pld, len)) | |||
3424 | == -1) | |||
3425 | goto done; | |||
3426 | } | |||
3427 | ||||
3428 | if ((env->sc_nattmode != NATT_DISABLE) && | |||
3429 | msg->msg_local.ss_family != AF_UNSPEC0) { | |||
3430 | if ((len = ikev2_add_nat_detection(env, buf, &pld, &resp, len)) | |||
3431 | == -1) | |||
3432 | goto done; | |||
3433 | } | |||
3434 | if (sa->sa_statevalid & IKED_REQ_CERT0x0001) { | |||
3435 | /* CERTREQ payload(s) */ | |||
3436 | if ((len = ikev2_add_certreq(buf, &pld, | |||
3437 | len, env->sc_certreq, env->sc_certreqtype)) == -1) | |||
3438 | goto done; | |||
3439 | ||||
3440 | if (env->sc_certreqtype != sa->sa_policy->pol_certreqtype && | |||
3441 | (len = ikev2_add_certreq(buf, &pld, | |||
3442 | len, NULL((void *)0), sa->sa_policy->pol_certreqtype)) == -1) | |||
3443 | goto done; | |||
3444 | } | |||
3445 | ||||
3446 | if (sa->sa_sigsha2 && | |||
3447 | (len = ikev2_add_sighashnotify(buf, &pld, len)) == -1) | |||
3448 | goto done; | |||
3449 | ||||
3450 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONE0) == -1) | |||
3451 | goto done; | |||
3452 | ||||
3453 | if (ikev2_set_header(hdr, ibuf_size(buf) - sizeof(*hdr)) == -1) | |||
3454 | goto done; | |||
3455 | ||||
3456 | (void)ikev2_pld_parse(env, hdr, &resp, 0); | |||
3457 | ||||
3458 | ibuf_free(sa->sa_2ndmsg); | |||
3459 | if ((sa->sa_2ndmsg = ibuf_dup(buf)) == NULL((void *)0)) { | |||
3460 | log_debug("%s: failed to copy 2nd message", __func__); | |||
3461 | goto done; | |||
3462 | } | |||
3463 | ||||
3464 | ret = ikev2_msg_send(env, &resp); | |||
3465 | ||||
3466 | done: | |||
3467 | ibuf_free(vendor_id); | |||
3468 | ikev2_msg_cleanup(env, &resp); | |||
3469 | ||||
3470 | return (ret); | |||
3471 | } | |||
3472 | ||||
3473 | int | |||
3474 | ikev2_send_auth_failed(struct iked *env, struct iked_sa *sa) | |||
3475 | { | |||
3476 | char dstid[IKED_ID_SIZE1024]; | |||
3477 | struct ikev2_notify *n; | |||
3478 | struct ibuf *buf = NULL((void *)0); | |||
3479 | int ret = -1, exchange, response; | |||
3480 | ||||
3481 | if (ikev2_print_id(IKESA_DSTID(sa)((sa)->sa_hdr.sh_initiator ? &(sa)->sa_rid : &( sa)->sa_iid), dstid, sizeof(dstid)) == -1) | |||
3482 | bzero(dstid, sizeof(dstid)); | |||
3483 | log_info("%s: authentication failed for %s", | |||
3484 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), dstid); | |||
3485 | ||||
3486 | /* Log certificate information */ | |||
3487 | ikev2_log_cert_info(SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
3488 | sa->sa_hdr.sh_initiator ? &sa->sa_rcert : &sa->sa_icert); | |||
3489 | ||||
3490 | /* Notify payload */ | |||
3491 | if ((buf = ibuf_static()) == NULL((void *)0)) | |||
3492 | goto done; | |||
3493 | if ((n = ibuf_reserve(buf, sizeof(*n))) == NULL((void *)0)) | |||
3494 | goto done; | |||
3495 | n->n_protoid = IKEV2_SAPROTO_IKE1; | |||
3496 | n->n_spisize = 0; | |||
3497 | 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)); | |||
3498 | if (sa->sa_hdr.sh_initiator) { | |||
3499 | exchange = IKEV2_EXCHANGE_INFORMATIONAL37; | |||
3500 | response = 0; | |||
3501 | } else { | |||
3502 | exchange = IKEV2_EXCHANGE_IKE_AUTH35; | |||
3503 | response = 1; | |||
3504 | } | |||
3505 | ret = ikev2_send_ike_e(env, sa, buf, IKEV2_PAYLOAD_NOTIFY41, | |||
3506 | exchange, response); | |||
3507 | if (exchange == IKEV2_EXCHANGE_INFORMATIONAL37) | |||
3508 | sa->sa_stateflags |= IKED_REQ_INF0x0100; | |||
3509 | done: | |||
3510 | ibuf_free(buf); | |||
3511 | ||||
3512 | /* cleanup SA after timeout */ | |||
3513 | sa_state(env, sa, IKEV2_STATE_CLOSING10); | |||
3514 | timer_del(env, &sa->sa_timer); | |||
3515 | timer_set(env, &sa->sa_timer, ikev2_ike_sa_timeout, sa); | |||
3516 | timer_add(env, &sa->sa_timer, IKED_IKE_SA_DELETE_TIMEOUT120); | |||
3517 | config_free_fragments(&sa->sa_fragments); | |||
3518 | ikev2_ike_sa_setreason(sa, "authentication failed"); | |||
3519 | ||||
3520 | return (ret); | |||
3521 | } | |||
3522 | ||||
3523 | ssize_t | |||
3524 | ikev2_add_error(struct iked *env, struct ibuf *buf, struct iked_message *msg) | |||
3525 | { | |||
3526 | struct ikev2_notify *n; | |||
3527 | struct iked_spi *rekey; | |||
3528 | uint16_t group; | |||
3529 | uint32_t spi32; | |||
3530 | uint64_t spi64; | |||
3531 | size_t len; | |||
3532 | uint8_t *ptr; | |||
3533 | ||||
3534 | switch (msg->msg_error) { | |||
3535 | case IKEV2_N_CHILD_SA_NOT_FOUND44: | |||
3536 | break; | |||
3537 | case IKEV2_N_NO_PROPOSAL_CHOSEN14: | |||
3538 | ikev2_log_proposal(msg->msg_sa, &msg->msg_proposals); | |||
3539 | break; | |||
3540 | case IKEV2_N_INVALID_KE_PAYLOAD17: | |||
3541 | break; | |||
3542 | default: | |||
3543 | return (-1); | |||
3544 | } | |||
3545 | log_info("%s: %s", SPI_SA(msg->msg_sa, __func__)ikev2_ikesa_info((&(msg->msg_sa)->sa_hdr)->sh_ispi , ((__func__))), | |||
3546 | print_map(msg->msg_error, ikev2_n_map)); | |||
3547 | len = sizeof(*n); | |||
3548 | if ((ptr = ibuf_reserve(buf, len)) == NULL((void *)0)) | |||
3549 | return (-1); | |||
3550 | n = (struct ikev2_notify *)ptr; | |||
3551 | 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)); | |||
3552 | switch (msg->msg_error) { | |||
3553 | case IKEV2_N_CHILD_SA_NOT_FOUND44: | |||
3554 | rekey = &msg->msg_rekey; | |||
3555 | switch (rekey->spi_size) { | |||
3556 | case 4: | |||
3557 | 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 )); | |||
3558 | if (ibuf_add(buf, &spi32, sizeof(spi32)) != 0) | |||
3559 | return (-1); | |||
3560 | len += sizeof(spi32); | |||
3561 | break; | |||
3562 | case 8: | |||
3563 | 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)); | |||
3564 | if (ibuf_add(buf, &spi64, sizeof(spi64)) != 0) | |||
3565 | return (-1); | |||
3566 | len += sizeof(spi64); | |||
3567 | break; | |||
3568 | default: | |||
3569 | log_debug("%s: invalid SPI size %d", __func__, | |||
3570 | rekey->spi_size); | |||
3571 | return (-1); | |||
3572 | } | |||
3573 | n->n_protoid = rekey->spi_protoid; | |||
3574 | n->n_spisize = rekey->spi_size; | |||
3575 | break; | |||
3576 | case IKEV2_N_INVALID_KE_PAYLOAD17: | |||
3577 | 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)); | |||
3578 | if (ibuf_add(buf, &group, sizeof(group)) != 0) | |||
3579 | return (-1); | |||
3580 | len += sizeof(group); | |||
3581 | n->n_protoid = 0; | |||
3582 | n->n_spisize = 0; | |||
3583 | break; | |||
3584 | default: | |||
3585 | n->n_protoid = 0; | |||
3586 | n->n_spisize = 0; | |||
3587 | break; | |||
3588 | } | |||
3589 | log_debug("%s: done", __func__); | |||
3590 | ||||
3591 | return (len); | |||
3592 | } | |||
3593 | ||||
3594 | int | |||
3595 | ikev2_record_dstid(struct iked *env, struct iked_sa *sa) | |||
3596 | { | |||
3597 | struct iked_sa *osa; | |||
3598 | ||||
3599 | osa = sa_dstid_lookup(env, sa); | |||
3600 | if (osa == sa) | |||
3601 | return (0); | |||
3602 | if (osa != NULL((void *)0)) { | |||
3603 | sa_dstid_remove(env, osa); | |||
3604 | if (env->sc_enforcesingleikesasc_static.st_enforcesingleikesa && | |||
3605 | osa->sa_state < IKEV2_STATE_CLOSING10) { | |||
3606 | log_info("%sreplaced by IKESA %s (identical DSTID)", | |||
3607 | SPI_SA(osa, NULL)ikev2_ikesa_info((&(osa)->sa_hdr)->sh_ispi, ((((void *)0)))), | |||
3608 | print_spi(sa->sa_hdr.sh_ispi, 8)); | |||
3609 | if (osa->sa_state == IKEV2_STATE_ESTABLISHED9) | |||
3610 | ikev2_disable_timer(env, osa); | |||
3611 | ikev2_ike_sa_setreason(osa, "sa replaced"); | |||
3612 | ikev2_ikesa_delete(env, osa, 0); | |||
3613 | timer_add(env, &osa->sa_timer, | |||
3614 | 3 * IKED_RETRANSMIT_TIMEOUT2); | |||
3615 | } | |||
3616 | } | |||
3617 | osa = sa_dstid_insert(env, sa); | |||
3618 | if (osa != NULL((void *)0)) { | |||
3619 | /* XXX how can this fail */ | |||
3620 | log_info("%s: could not replace old IKESA %s", | |||
3621 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
3622 | print_spi(osa->sa_hdr.sh_ispi, 8)); | |||
3623 | return (-1); | |||
3624 | } | |||
3625 | return (0); | |||
3626 | } | |||
3627 | ||||
3628 | int | |||
3629 | ikev2_send_error(struct iked *env, struct iked_sa *sa, | |||
3630 | struct iked_message *msg, uint8_t exchange) | |||
3631 | { | |||
3632 | struct ibuf *buf = NULL((void *)0); | |||
3633 | int ret = -1; | |||
3634 | ||||
3635 | if (msg->msg_error == 0) | |||
3636 | return (0); | |||
3637 | if ((buf = ibuf_static()) == NULL((void *)0)) | |||
3638 | goto done; | |||
3639 | if (ikev2_add_error(env, buf, msg) == 0) | |||
3640 | goto done; | |||
3641 | ret = ikev2_send_ike_e(env, sa, buf, IKEV2_PAYLOAD_NOTIFY41, | |||
3642 | exchange, 1); | |||
3643 | done: | |||
3644 | ibuf_free(buf); | |||
3645 | return (ret); | |||
3646 | } | |||
3647 | ||||
3648 | /* | |||
3649 | * Variant of ikev2_send_error() that can be used before encryption | |||
3650 | * is enabled. Based on ikev2_resp_ike_sa_init() code. | |||
3651 | */ | |||
3652 | int | |||
3653 | ikev2_send_init_error(struct iked *env, struct iked_message *msg) | |||
3654 | { | |||
3655 | struct iked_message resp; | |||
3656 | struct ike_header *hdr; | |||
3657 | struct ikev2_payload *pld; | |||
3658 | struct iked_sa *sa = msg->msg_sa; | |||
3659 | struct ibuf *buf; | |||
3660 | ssize_t len = 0; | |||
3661 | int ret = -1; | |||
3662 | ||||
3663 | if (sa->sa_hdr.sh_initiator) { | |||
3664 | log_debug("%s: called by initiator", __func__); | |||
3665 | return (-1); | |||
3666 | } | |||
3667 | if (msg->msg_error == 0) | |||
3668 | return (0); | |||
3669 | ||||
3670 | if ((buf = ikev2_msg_init(env, &resp, | |||
3671 | &msg->msg_peer, msg->msg_peerlen, | |||
3672 | &msg->msg_local, msg->msg_locallen, 1)) == NULL((void *)0)) | |||
3673 | goto done; | |||
3674 | ||||
3675 | resp.msg_sa = sa; | |||
3676 | resp.msg_fd = msg->msg_fd; | |||
3677 | resp.msg_natt = msg->msg_natt; | |||
3678 | resp.msg_msgid = 0; | |||
3679 | ||||
3680 | /* IKE header */ | |||
3681 | if ((hdr = ikev2_add_header(buf, sa, resp.msg_msgid, | |||
3682 | IKEV2_PAYLOAD_NOTIFY41, IKEV2_EXCHANGE_IKE_SA_INIT34, | |||
3683 | IKEV2_FLAG_RESPONSE0x20)) == NULL((void *)0)) | |||
3684 | goto done; | |||
3685 | ||||
3686 | /* NOTIFY payload */ | |||
3687 | if ((pld = ikev2_add_payload(buf)) == NULL((void *)0)) | |||
3688 | goto done; | |||
3689 | if ((len = ikev2_add_error(env, buf, msg)) == 0) | |||
3690 | goto done; | |||
3691 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONE0) == -1) | |||
3692 | goto done; | |||
3693 | if (ikev2_set_header(hdr, ibuf_size(buf) - sizeof(*hdr)) == -1) | |||
3694 | goto done; | |||
3695 | ||||
3696 | (void)ikev2_pld_parse(env, hdr, &resp, 0); | |||
3697 | ret = ikev2_msg_send(env, &resp); | |||
3698 | ||||
3699 | done: | |||
3700 | ikev2_msg_cleanup(env, &resp); | |||
3701 | ||||
3702 | return (ret); | |||
3703 | } | |||
3704 | ||||
3705 | int | |||
3706 | ikev2_handle_certreq(struct iked* env, struct iked_message *msg) | |||
3707 | { | |||
3708 | struct iked_certreq *cr; | |||
3709 | struct iked_sa *sa; | |||
3710 | uint8_t crtype; | |||
3711 | uint8_t more; | |||
3712 | ||||
3713 | if ((sa = msg->msg_sa) == NULL((void *)0)) | |||
3714 | return (-1); | |||
3715 | ||||
3716 | /* Ignore CERTREQ when policy uses PSK authentication */ | |||
3717 | if (sa->sa_policy->pol_auth.auth_method == IKEV2_AUTH_SHARED_KEY_MIC2) | |||
3718 | return (0); | |||
3719 | ||||
3720 | if (sa->sa_hdr.sh_initiator) | |||
3721 | sa->sa_stateinit |= IKED_REQ_CERT0x0001; | |||
3722 | else | |||
3723 | sa->sa_statevalid |= IKED_REQ_CERT0x0001; | |||
3724 | ||||
3725 | /* | |||
3726 | * If we have to send a local certificate but did not receive an | |||
3727 | * optional CERTREQ, use our own certreq to find a local certificate. | |||
3728 | * We could alternatively extract the CA from the peer certificate | |||
3729 | * to find a matching local one. | |||
3730 | */ | |||
3731 | if (SIMPLEQ_EMPTY(&msg->msg_certreqs)(((&msg->msg_certreqs)->sqh_first) == ((void *)0))) { | |||
3732 | if (sa->sa_policy->pol_certreqtype) | |||
3733 | crtype = sa->sa_policy->pol_certreqtype; | |||
3734 | else | |||
3735 | crtype = env->sc_certreqtype; | |||
3736 | ca_setreq(env, sa, &sa->sa_policy->pol_localid, | |||
3737 | crtype, 0, ibuf_data(env->sc_certreq), | |||
3738 | ibuf_size(env->sc_certreq), PROC_CERT); | |||
3739 | } else { | |||
3740 | while ((cr = SIMPLEQ_FIRST(&msg->msg_certreqs)((&msg->msg_certreqs)->sqh_first))) { | |||
3741 | if (SIMPLEQ_NEXT(cr, cr_entry)((cr)->cr_entry.sqe_next) != NULL((void *)0)) | |||
3742 | more = 1; | |||
3743 | else | |||
3744 | more = 0; | |||
3745 | ||||
3746 | ca_setreq(env, sa, &sa->sa_policy->pol_localid, | |||
3747 | cr->cr_type, more, ibuf_data(cr->cr_data), | |||
3748 | ibuf_size(cr->cr_data), | |||
3749 | PROC_CERT); | |||
3750 | ||||
3751 | ibuf_free(cr->cr_data); | |||
3752 | 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); | |||
3753 | free(cr); | |||
3754 | } | |||
3755 | } | |||
3756 | ||||
3757 | return (0); | |||
3758 | } | |||
3759 | ||||
3760 | int | |||
3761 | ikev2_resp_ike_eap_mschap(struct iked *env, struct iked_sa *sa, | |||
3762 | struct iked_message *msg) | |||
3763 | { | |||
3764 | uint8_t successmsg[EAP_MSCHAP_SUCCESS_SZ42]; | |||
3765 | uint8_t ntresponse[EAP_MSCHAP_NTRESPONSE_SZ24]; | |||
3766 | struct eap_msg *eap = &msg->msg_eap; | |||
3767 | struct iked_user *usr; | |||
3768 | uint8_t *pass; | |||
3769 | char *name = NULL((void *)0); | |||
3770 | size_t passlen; | |||
3771 | int ret; | |||
3772 | ||||
3773 | switch (eap->eam_state) { | |||
3774 | case EAP_STATE_IDENTITY(1): | |||
3775 | sa->sa_eapid = eap->eam_identity; | |||
3776 | return (eap_challenge_request(env, sa, eap->eam_id)); | |||
3777 | case EAP_STATE_MSCHAPV2_CHALLENGE(2): | |||
3778 | if (eap->eam_user) { | |||
3779 | name = eap->eam_user; | |||
3780 | } else if (sa->sa_eapid) { | |||
3781 | name = sa->sa_eapid; | |||
3782 | } | |||
3783 | if (name == NULL((void *)0)) { | |||
3784 | log_info("%s: invalid response name", | |||
3785 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
3786 | return (-1); | |||
3787 | } | |||
3788 | if ((usr = user_lookup(env, name)) == NULL((void *)0)) { | |||
3789 | log_info("%s: unknown user '%s'", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
3790 | name); | |||
3791 | return (-1); | |||
3792 | } | |||
3793 | ||||
3794 | if ((pass = string2unicode(usr->usr_pass, &passlen)) == NULL((void *)0)) | |||
3795 | return (-1); | |||
3796 | ||||
3797 | mschap_nt_response(ibuf_data(sa->sa_eap.id_buf), | |||
3798 | eap->eam_challenge, usr->usr_name, strlen(usr->usr_name), | |||
3799 | pass, passlen, ntresponse); | |||
3800 | ||||
3801 | if (memcmp(ntresponse, eap->eam_ntresponse, | |||
3802 | sizeof(ntresponse)) != 0) { | |||
3803 | log_info("%s: '%s' authentication failed", | |||
3804 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), usr->usr_name); | |||
3805 | freezero(pass, passlen); | |||
3806 | ||||
3807 | /* XXX should we send an EAP failure packet? */ | |||
3808 | return (-1); | |||
3809 | } | |||
3810 | ||||
3811 | bzero(&successmsg, sizeof(successmsg)); | |||
3812 | ||||
3813 | mschap_auth_response(pass, passlen, | |||
3814 | ntresponse, ibuf_data(sa->sa_eap.id_buf), | |||
3815 | eap->eam_challenge, usr->usr_name, strlen(usr->usr_name), | |||
3816 | successmsg); | |||
3817 | if ((sa->sa_eapmsk = ibuf_new(NULL((void *)0), MSCHAP_MSK_SZ64)) == NULL((void *)0)) { | |||
3818 | log_info("%s: failed to get MSK", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
3819 | freezero(pass, passlen); | |||
3820 | return (-1); | |||
3821 | } | |||
3822 | mschap_msk(pass, passlen, ntresponse, | |||
3823 | ibuf_data(sa->sa_eapmsk)); | |||
3824 | freezero(pass, passlen); | |||
3825 | ||||
3826 | log_info("%s: '%s' authenticated", __func__, usr->usr_name); | |||
3827 | ||||
3828 | ret = eap_mschap_challenge(env, sa, eap->eam_id, eap->eam_msrid, | |||
3829 | successmsg, EAP_MSCHAP_SUCCESS_SZ42); | |||
3830 | if (ret == 0) | |||
3831 | sa_state(env, sa, IKEV2_STATE_AUTH_SUCCESS6); | |||
3832 | break; | |||
3833 | case EAP_STATE_MSCHAPV2_SUCCESS(3): | |||
3834 | return (eap_mschap_success(env, sa, eap->eam_id)); | |||
3835 | case EAP_STATE_SUCCESS(4): | |||
3836 | if (!sa_stateok(sa, IKEV2_STATE_AUTH_SUCCESS6)) | |||
3837 | return (-1); | |||
3838 | return (eap_success(env, sa, msg->msg_eap.eam_id)); | |||
3839 | default: | |||
3840 | log_info("%s: eap ignored.", __func__); | |||
3841 | break; | |||
3842 | } | |||
3843 | return 0; | |||
3844 | } | |||
3845 | ||||
3846 | int | |||
3847 | ikev2_resp_ike_eap(struct iked *env, struct iked_sa *sa, | |||
3848 | struct iked_message *msg) | |||
3849 | { | |||
3850 | if (!sa_stateok(sa, IKEV2_STATE_EAP3)) | |||
3851 | return (-1); | |||
3852 | ||||
3853 | switch (sa->sa_policy->pol_auth.auth_eap) { | |||
3854 | case EAP_TYPE_MSCHAP_V226: | |||
3855 | return ikev2_resp_ike_eap_mschap(env, sa, msg); | |||
3856 | } | |||
3857 | return -1; | |||
3858 | } | |||
3859 | ||||
3860 | int | |||
3861 | ikev2_resp_ike_auth(struct iked *env, struct iked_sa *sa) | |||
3862 | { | |||
3863 | struct ikev2_payload *pld; | |||
3864 | struct ikev2_cert *cert; | |||
3865 | struct ikev2_auth *auth; | |||
3866 | struct iked_id *id, *certid; | |||
3867 | struct ibuf *e = NULL((void *)0); | |||
3868 | uint8_t firstpayload; | |||
3869 | int ret = -1; | |||
3870 | ssize_t len; | |||
3871 | int i; | |||
3872 | ||||
3873 | if (sa == NULL((void *)0)) | |||
3874 | return (-1); | |||
3875 | ||||
3876 | if (sa->sa_state == IKEV2_STATE_EAP3) | |||
3877 | return (eap_identity_request(env, sa)); | |||
3878 | ||||
3879 | if (!sa_stateok(sa, IKEV2_STATE_VALID7)) | |||
3880 | return (0); /* ignore */ | |||
3881 | ||||
3882 | if (ikev2_cp_setaddr(env, sa, AF_INET2) < 0 || | |||
3883 | ikev2_cp_setaddr(env, sa, AF_INET624) < 0) | |||
3884 | return (-1); | |||
3885 | ||||
3886 | if (ikev2_childsa_negotiate(env, sa, &sa->sa_kex, &sa->sa_proposals, | |||
3887 | sa->sa_hdr.sh_initiator, 0) < 0) | |||
3888 | return (-1); | |||
3889 | ||||
3890 | /* New encrypted message buffer */ | |||
3891 | if ((e = ibuf_static()) == NULL((void *)0)) | |||
3892 | goto done; | |||
3893 | ||||
3894 | if (!sa->sa_localauth.id_type) { | |||
3895 | /* Downgrade the state */ | |||
3896 | sa_state(env, sa, IKEV2_STATE_AUTH_SUCCESS6); | |||
3897 | } | |||
3898 | ||||
3899 | if (sa->sa_hdr.sh_initiator) { | |||
3900 | id = &sa->sa_iid; | |||
3901 | certid = &sa->sa_icert; | |||
3902 | } else { | |||
3903 | id = &sa->sa_rid; | |||
3904 | certid = &sa->sa_rcert; | |||
3905 | } | |||
3906 | ||||
3907 | if (sa->sa_state != IKEV2_STATE_EAP_VALID8) { | |||
3908 | /* ID payload */ | |||
3909 | if ((pld = ikev2_add_payload(e)) == NULL((void *)0)) | |||
3910 | goto done; | |||
3911 | firstpayload = IKEV2_PAYLOAD_IDr36; | |||
3912 | if (ibuf_add_buf(e, id->id_buf) != 0) | |||
3913 | goto done; | |||
3914 | len = ibuf_size(id->id_buf); | |||
3915 | ||||
3916 | /* CERT payload */ | |||
3917 | if ((sa->sa_statevalid & IKED_REQ_CERT0x0001) && | |||
3918 | (certid->id_type != IKEV2_CERT_NONE0)) { | |||
3919 | if (ikev2_next_payload(pld, len, | |||
3920 | IKEV2_PAYLOAD_CERT37) == -1) | |||
3921 | goto done; | |||
3922 | ||||
3923 | if ((pld = ikev2_add_payload(e)) == NULL((void *)0)) | |||
3924 | goto done; | |||
3925 | if ((cert = ibuf_reserve(e, sizeof(*cert))) == NULL((void *)0)) | |||
3926 | goto done; | |||
3927 | cert->cert_type = certid->id_type; | |||
3928 | if (ibuf_add_buf(e, certid->id_buf) != 0) | |||
3929 | goto done; | |||
3930 | len = ibuf_size(certid->id_buf) + sizeof(*cert); | |||
3931 | ||||
3932 | for (i = 0; i < IKED_SCERT_MAX3; i++) { | |||
3933 | if (sa->sa_scert[i].id_type == IKEV2_CERT_NONE0) | |||
3934 | break; | |||
3935 | if (ikev2_next_payload(pld, len, | |||
3936 | IKEV2_PAYLOAD_CERT37) == -1) | |||
3937 | goto done; | |||
3938 | if ((pld = ikev2_add_payload(e)) == NULL((void *)0)) | |||
3939 | goto done; | |||
3940 | if ((cert = ibuf_reserve(e, | |||
3941 | sizeof(*cert))) == NULL((void *)0)) | |||
3942 | goto done; | |||
3943 | cert->cert_type = sa->sa_scert[i].id_type; | |||
3944 | if (ibuf_add_buf(e, sa->sa_scert[i].id_buf) != | |||
3945 | 0) | |||
3946 | goto done; | |||
3947 | len = ibuf_size(sa->sa_scert[i].id_buf) | |||
3948 | + sizeof(*cert); | |||
3949 | } | |||
3950 | } | |||
3951 | ||||
3952 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_AUTH39) == -1) | |||
3953 | goto done; | |||
3954 | } else | |||
3955 | firstpayload = IKEV2_PAYLOAD_AUTH39; | |||
3956 | ||||
3957 | /* AUTH payload */ | |||
3958 | if ((pld = ikev2_add_payload(e)) == NULL((void *)0)) | |||
3959 | goto done; | |||
3960 | if ((auth = ibuf_reserve(e, sizeof(*auth))) == NULL((void *)0)) | |||
3961 | goto done; | |||
3962 | auth->auth_method = sa->sa_localauth.id_type; | |||
3963 | if (ibuf_add_buf(e, sa->sa_localauth.id_buf) != 0) | |||
3964 | goto done; | |||
3965 | len = ibuf_size(sa->sa_localauth.id_buf) + sizeof(*auth); | |||
3966 | ||||
3967 | /* CP payload */ | |||
3968 | if (sa->sa_cp) { | |||
3969 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_CP47) == -1) | |||
3970 | goto done; | |||
3971 | if ((pld = ikev2_add_payload(e)) == NULL((void *)0)) | |||
3972 | goto done; | |||
3973 | if ((len = ikev2_resp_add_cp(env, sa, e)) == -1) | |||
3974 | goto done; | |||
3975 | } | |||
3976 | ||||
3977 | if (sa->sa_ipcompr.ic_transform && | |||
3978 | (len = ikev2_add_ipcompnotify(env, e, &pld, len, sa, 0)) == -1) | |||
3979 | goto done; | |||
3980 | if (sa->sa_used_transport_mode && | |||
3981 | (len = ikev2_add_transport_mode(env, e, &pld, len, sa)) == -1) | |||
3982 | goto done; | |||
3983 | ||||
3984 | /* MOBIKE */ | |||
3985 | if (sa->sa_mobike && | |||
3986 | (len = ikev2_add_mobike(e, &pld, len)) == -1) | |||
3987 | goto done; | |||
3988 | ||||
3989 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_SA33) == -1) | |||
3990 | goto done; | |||
3991 | ||||
3992 | /* SA payload */ | |||
3993 | if ((pld = ikev2_add_payload(e)) == NULL((void *)0)) | |||
3994 | goto done; | |||
3995 | if ((len = ikev2_add_proposals(env, sa, e, &sa->sa_proposals, 0, | |||
3996 | sa->sa_hdr.sh_initiator, 0, 1)) == -1) | |||
3997 | goto done; | |||
3998 | ||||
3999 | if ((len = ikev2_add_ts(e, &pld, len, sa, 0)) == -1) | |||
4000 | goto done; | |||
4001 | ||||
4002 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONE0) == -1) | |||
4003 | goto done; | |||
4004 | ||||
4005 | ret = ikev2_msg_send_encrypt(env, sa, &e, | |||
4006 | IKEV2_EXCHANGE_IKE_AUTH35, firstpayload, 1); | |||
4007 | if (ret == 0) | |||
4008 | ret = ikev2_childsa_enable(env, sa); | |||
4009 | if (ret == 0) { | |||
4010 | sa_state(env, sa, IKEV2_STATE_ESTABLISHED9); | |||
4011 | /* Delete exchange timeout. */ | |||
4012 | timer_del(env, &sa->sa_timer); | |||
4013 | ikev2_enable_timer(env, sa); | |||
4014 | ikev2_log_established(sa); | |||
4015 | ikev2_record_dstid(env, sa); | |||
4016 | } | |||
4017 | ||||
4018 | done: | |||
4019 | if (ret) | |||
4020 | ikev2_childsa_delete(env, sa, 0, 0, NULL((void *)0), 1); | |||
4021 | ibuf_free(e); | |||
4022 | return (ret); | |||
4023 | } | |||
4024 | ||||
4025 | int | |||
4026 | ikev2_send_ike_e(struct iked *env, struct iked_sa *sa, struct ibuf *buf, | |||
4027 | uint8_t firstpayload, uint8_t exchange, int response) | |||
4028 | { | |||
4029 | struct ikev2_payload *pld; | |||
4030 | struct ibuf *e = NULL((void *)0); | |||
4031 | int ret = -1; | |||
4032 | ||||
4033 | /* New encrypted message buffer */ | |||
4034 | if ((e = ibuf_static()) == NULL((void *)0)) | |||
4035 | goto done; | |||
4036 | ||||
4037 | if (buf) { | |||
4038 | if ((pld = ikev2_add_payload(e)) == NULL((void *)0)) | |||
4039 | goto done; | |||
4040 | ||||
4041 | if (ibuf_add_buf(e, buf) != 0) | |||
4042 | goto done; | |||
4043 | ||||
4044 | if (ikev2_next_payload(pld, ibuf_size(buf), | |||
4045 | IKEV2_PAYLOAD_NONE0) == -1) | |||
4046 | goto done; | |||
4047 | } | |||
4048 | ||||
4049 | ret = ikev2_msg_send_encrypt(env, sa, &e, exchange, firstpayload, | |||
4050 | response); | |||
4051 | ||||
4052 | done: | |||
4053 | ibuf_free(e); | |||
4054 | ||||
4055 | return (ret); | |||
4056 | } | |||
4057 | ||||
4058 | int | |||
4059 | ikev2_set_sa_proposal(struct iked_sa *sa, struct iked_policy *pol, | |||
4060 | unsigned int proto) | |||
4061 | { | |||
4062 | struct iked_proposal *prop, *copy; | |||
4063 | struct iked_transform *xform; | |||
4064 | unsigned int i; | |||
4065 | ||||
4066 | /* create copy of the policy proposals */ | |||
4067 | config_free_proposals(&sa->sa_proposals, proto); | |||
4068 | TAILQ_FOREACH(prop, &pol->pol_proposals, prop_entry)for((prop) = ((&pol->pol_proposals)->tqh_first); (prop ) != ((void *)0); (prop) = ((prop)->prop_entry.tqe_next)) { | |||
4069 | if (proto != 0 && prop->prop_protoid != proto) | |||
4070 | continue; | |||
4071 | if ((copy = config_add_proposal(&sa->sa_proposals, | |||
4072 | prop->prop_id, prop->prop_protoid)) == NULL((void *)0)) | |||
4073 | return (-1); | |||
4074 | for (i = 0; i < prop->prop_nxforms; i++) { | |||
4075 | xform = &prop->prop_xforms[i]; | |||
4076 | if (config_add_transform(copy, xform->xform_type, | |||
4077 | xform->xform_id, xform->xform_length, | |||
4078 | xform->xform_keylength) != 0) | |||
4079 | return (-1); | |||
4080 | } | |||
4081 | } | |||
4082 | return (0); | |||
4083 | } | |||
4084 | ||||
4085 | int | |||
4086 | ikev2_send_create_child_sa(struct iked *env, struct iked_sa *sa, | |||
4087 | struct iked_spi *rekey, uint8_t protoid, uint16_t proposed_group) | |||
4088 | { | |||
4089 | struct iked_policy *pol = sa->sa_policy; | |||
4090 | struct iked_childsa *csa = NULL((void *)0), *csb = NULL((void *)0); | |||
4091 | struct iked_transform *xform; | |||
4092 | struct ikev2_notify *n; | |||
4093 | struct ikev2_payload *pld = NULL((void *)0); | |||
4094 | struct ikev2_keyexchange *ke; | |||
4095 | struct dh_group *group; | |||
4096 | struct ibuf *e = NULL((void *)0), *nonce = NULL((void *)0); | |||
4097 | uint8_t *ptr; | |||
4098 | uint8_t firstpayload; | |||
4099 | uint32_t spi; | |||
4100 | ssize_t len = 0; | |||
4101 | int initiator, ret = -1; | |||
4102 | ||||
4103 | if (rekey) | |||
4104 | log_debug("%s: rekeying %s spi %s", __func__, | |||
4105 | print_map(rekey->spi_protoid, ikev2_saproto_map), | |||
4106 | print_spi(rekey->spi, rekey->spi_size)); | |||
4107 | else | |||
4108 | log_debug("%s: creating new CHILD SAs", __func__); | |||
4109 | ||||
4110 | /* XXX cannot initiate multiple concurrent CREATE_CHILD_SA exchanges */ | |||
4111 | if (sa->sa_stateflags & (IKED_REQ_CHILDSA0x0080|IKED_REQ_INF0x0100)) { | |||
4112 | log_debug("%s: another exchange already active", | |||
4113 | __func__); | |||
4114 | return (-1); | |||
4115 | } | |||
4116 | ||||
4117 | ibuf_free(sa->sa_simult); | |||
4118 | sa->sa_simult = NULL((void *)0); | |||
4119 | sa->sa_rekeyspi = 0; /* clear rekey spi */ | |||
4120 | initiator = sa->sa_hdr.sh_initiator ? 1 : 0; | |||
4121 | ||||
4122 | if (rekey && | |||
4123 | ((csa = childsa_lookup(sa, rekey->spi, | |||
4124 | rekey->spi_protoid)) == NULL((void *)0) || | |||
4125 | (csb = csa->csa_peersa) == NULL((void *)0))) { | |||
4126 | log_debug("%s: CHILD SA %s wasn't found", __func__, | |||
4127 | print_spi(rekey->spi, rekey->spi_size)); | |||
4128 | goto done; | |||
4129 | } | |||
4130 | ||||
4131 | /* Generate new nonce */ | |||
4132 | if ((nonce = ibuf_random(IKED_NONCE_SIZE32)) == NULL((void *)0)) | |||
4133 | goto done; | |||
4134 | ||||
4135 | /* Update initiator nonce */ | |||
4136 | ibuf_free(sa->sa_inoncesa_kex.kex_inonce); | |||
4137 | sa->sa_inoncesa_kex.kex_inonce = nonce; | |||
4138 | ||||
4139 | if ((e = ibuf_static()) == NULL((void *)0)) | |||
4140 | goto done; | |||
4141 | ||||
4142 | if ((pol->pol_flags & IKED_POLICY_IPCOMP0x20) && | |||
4143 | (len = ikev2_add_ipcompnotify(env, e, &pld, 0, sa, 1)) == -1) | |||
4144 | goto done; | |||
4145 | if ((pol->pol_flags & IKED_POLICY_TRANSPORT0x40) && | |||
4146 | (len = ikev2_add_transport_mode(env, e, &pld, len, sa)) == -1) | |||
4147 | goto done; | |||
4148 | ||||
4149 | if (pld) { | |||
4150 | firstpayload = IKEV2_PAYLOAD_NOTIFY41; | |||
4151 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_SA33) == -1) | |||
4152 | goto done; | |||
4153 | } else | |||
4154 | firstpayload = IKEV2_PAYLOAD_SA33; | |||
4155 | ||||
4156 | /* SA payload */ | |||
4157 | if ((pld = ikev2_add_payload(e)) == NULL((void *)0)) | |||
4158 | goto done; | |||
4159 | ||||
4160 | /* | |||
4161 | * We need to reset the sa_proposal. Otherwise it would be | |||
4162 | * left over from the IKE_AUTH exchange and would not contain | |||
4163 | * any DH groups (e.g. for ESP child SAs). | |||
4164 | */ | |||
4165 | if (ikev2_set_sa_proposal(sa, pol, protoid) < 0) { | |||
4166 | log_debug("%s: ikev2_set_sa_proposal failed", __func__); | |||
4167 | goto done; | |||
4168 | } | |||
4169 | ||||
4170 | if ((len = ikev2_add_proposals(env, sa, e, &sa->sa_proposals, | |||
4171 | protoid, 1, 0, 0)) == -1) | |||
4172 | goto done; | |||
4173 | ||||
4174 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONCE40) == -1) | |||
4175 | goto done; | |||
4176 | ||||
4177 | /* NONCE payload */ | |||
4178 | if ((pld = ikev2_add_payload(e)) == NULL((void *)0)) | |||
4179 | goto done; | |||
4180 | if (ikev2_add_buf(e, nonce) == -1) | |||
4181 | goto done; | |||
4182 | len = ibuf_size(nonce); | |||
4183 | ||||
4184 | if ((xform = config_findtransform(&pol->pol_proposals, IKEV2_XFORMTYPE_DH4, | |||
4185 | protoid)) && xform->xform_id != IKEV2_XFORMDH_NONE0) { | |||
4186 | log_debug("%s: enable PFS", __func__); | |||
4187 | ikev2_sa_cleanup_dh(sa); | |||
4188 | if (proposed_group) { | |||
4189 | if ((sa->sa_dhgroupsa_kex.kex_dhgroup = | |||
4190 | group_get(proposed_group)) == NULL((void *)0)) { | |||
4191 | log_debug("%s: failed to get group", __func__); | |||
4192 | goto done; | |||
4193 | } | |||
4194 | } | |||
4195 | if (ikev2_sa_initiator_dh(sa, NULL((void *)0), protoid, NULL((void *)0)) < 0) { | |||
4196 | log_debug("%s: failed to setup DH", __func__); | |||
4197 | goto done; | |||
4198 | } | |||
4199 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_KE34) == -1) | |||
4200 | goto done; | |||
4201 | ||||
4202 | /* KE payload */ | |||
4203 | if ((pld = ikev2_add_payload(e)) == NULL((void *)0)) | |||
4204 | goto done; | |||
4205 | if ((ke = ibuf_reserve(e, sizeof(*ke))) == NULL((void *)0)) | |||
4206 | goto done; | |||
4207 | if ((group = sa->sa_dhgroupsa_kex.kex_dhgroup) == NULL((void *)0)) { | |||
4208 | log_debug("%s: invalid dh", __func__); | |||
4209 | goto done; | |||
4210 | } | |||
4211 | 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)); | |||
4212 | if (ikev2_add_buf(e, sa->sa_dhiexchangesa_kex.kex_dhiexchange) == -1) | |||
4213 | goto done; | |||
4214 | len = sizeof(*ke) + ibuf_size(sa->sa_dhiexchangesa_kex.kex_dhiexchange); | |||
4215 | } | |||
4216 | ||||
4217 | if ((len = ikev2_add_ts(e, &pld, len, sa, !initiator)) == -1) | |||
4218 | goto done; | |||
4219 | ||||
4220 | if (rekey) { | |||
4221 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NOTIFY41) == -1) | |||
4222 | goto done; | |||
4223 | ||||
4224 | /* REKEY_SA notification */ | |||
4225 | if ((pld = ikev2_add_payload(e)) == NULL((void *)0)) | |||
4226 | goto done; | |||
4227 | if ((n = ibuf_reserve(e, sizeof(*n))) == NULL((void *)0)) | |||
4228 | goto done; | |||
4229 | 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)); | |||
4230 | n->n_protoid = rekey->spi_protoid; | |||
4231 | n->n_spisize = rekey->spi_size; | |||
4232 | if ((ptr = ibuf_reserve(e, rekey->spi_size)) == NULL((void *)0)) | |||
4233 | goto done; | |||
4234 | len = rekey->spi_size; | |||
4235 | 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)); | |||
4236 | memcpy(ptr, &spi, rekey->spi_size); | |||
4237 | len += sizeof(*n); | |||
4238 | } | |||
4239 | ||||
4240 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONE0) == -1) | |||
4241 | goto done; | |||
4242 | ||||
4243 | ret = ikev2_msg_send_encrypt(env, sa, &e, | |||
4244 | IKEV2_EXCHANGE_CREATE_CHILD_SA36, firstpayload, 0); | |||
4245 | if (ret == 0) { | |||
4246 | if (rekey) { | |||
4247 | csa->csa_rekey = 1; | |||
4248 | csb->csa_rekey = 1; | |||
4249 | /* | |||
4250 | * Remember the peer spi of the rekeyed | |||
4251 | * SA for ikev2_init_create_child_sa(). | |||
4252 | */ | |||
4253 | sa->sa_rekeyspi = csa->csa_peerspi; | |||
4254 | } | |||
4255 | sa->sa_stateflags |= IKED_REQ_CHILDSA0x0080; | |||
4256 | } | |||
4257 | ||||
4258 | done: | |||
4259 | ibuf_free(e); | |||
4260 | return (ret); | |||
4261 | } | |||
4262 | ||||
4263 | void | |||
4264 | ikev2_ike_sa_rekey(struct iked *env, void *arg) | |||
4265 | { | |||
4266 | struct iked_sa *sa = arg; | |||
4267 | struct iked_sa *nsa = NULL((void *)0); | |||
4268 | struct ikev2_payload *pld = NULL((void *)0); | |||
4269 | struct ikev2_keyexchange *ke; | |||
4270 | struct dh_group *group; | |||
4271 | struct ibuf *e = NULL((void *)0), *nonce = NULL((void *)0); | |||
4272 | ssize_t len = 0; | |||
4273 | int ret = -1; | |||
4274 | ||||
4275 | log_debug("%s: IKE SA %p ispi %s rspi %s", __func__, sa, | |||
4276 | print_spi(sa->sa_hdr.sh_ispi, 8), | |||
4277 | print_spi(sa->sa_hdr.sh_rspi, 8)); | |||
4278 | ||||
4279 | if (sa->sa_nexti) { | |||
4280 | log_debug("%s: already rekeying", __func__); | |||
4281 | goto done; | |||
4282 | } | |||
4283 | ||||
4284 | if (sa->sa_stateflags & (IKED_REQ_CHILDSA0x0080|IKED_REQ_INF0x0100)) { | |||
4285 | /* | |||
4286 | * We cannot initiate multiple concurrent CREATE_CHILD_SA | |||
4287 | * exchanges, so retry again fast. | |||
4288 | */ | |||
4289 | log_info("%s: busy, delaying rekey", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
4290 | ikev2_ike_sa_rekey_schedule_fast(env, sa); | |||
4291 | return; | |||
4292 | } | |||
4293 | ||||
4294 | /* We need to make sure the rekeying finishes in time */ | |||
4295 | timer_set(env, &sa->sa_rekey, ikev2_ike_sa_rekey_timeout, sa); | |||
4296 | timer_add(env, &sa->sa_rekey, IKED_IKE_SA_REKEY_TIMEOUT120); | |||
4297 | ||||
4298 | if ((nsa = sa_new(env, 0, 0, 1, sa->sa_policy)) == NULL((void *)0)) { | |||
4299 | log_debug("%s: failed to get new SA", __func__); | |||
4300 | goto done; | |||
4301 | } | |||
4302 | ||||
4303 | if (ikev2_sa_initiator(env, nsa, sa, NULL((void *)0))) { | |||
4304 | log_debug("%s: failed to setup DH", __func__); | |||
4305 | goto done; | |||
4306 | } | |||
4307 | sa_state(env, nsa, IKEV2_STATE_AUTH_SUCCESS6); | |||
4308 | nonce = nsa->sa_inoncesa_kex.kex_inonce; | |||
4309 | ||||
4310 | if ((e = ibuf_static()) == NULL((void *)0)) | |||
4311 | goto done; | |||
4312 | ||||
4313 | /* SA payload */ | |||
4314 | if ((pld = ikev2_add_payload(e)) == NULL((void *)0)) | |||
4315 | goto done; | |||
4316 | ||||
4317 | /* just reuse the old IKE SA proposals */ | |||
4318 | if ((len = ikev2_add_proposals(env, nsa, e, &sa->sa_proposals, | |||
4319 | IKEV2_SAPROTO_IKE1, 1, 1, 0)) == -1) | |||
4320 | goto done; | |||
4321 | ||||
4322 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONCE40) == -1) | |||
4323 | goto done; | |||
4324 | ||||
4325 | /* NONCE payload */ | |||
4326 | if ((pld = ikev2_add_payload(e)) == NULL((void *)0)) | |||
4327 | goto done; | |||
4328 | if (ikev2_add_buf(e, nonce) == -1) | |||
4329 | goto done; | |||
4330 | len = ibuf_size(nonce); | |||
4331 | ||||
4332 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_KE34) == -1) | |||
4333 | goto done; | |||
4334 | ||||
4335 | /* KE payload */ | |||
4336 | if ((pld = ikev2_add_payload(e)) == NULL((void *)0)) | |||
4337 | goto done; | |||
4338 | if ((ke = ibuf_reserve(e, sizeof(*ke))) == NULL((void *)0)) | |||
4339 | goto done; | |||
4340 | if ((group = nsa->sa_dhgroupsa_kex.kex_dhgroup) == NULL((void *)0)) { | |||
4341 | log_debug("%s: invalid dh", __func__); | |||
4342 | goto done; | |||
4343 | } | |||
4344 | 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)); | |||
4345 | if (ikev2_add_buf(e, nsa->sa_dhiexchangesa_kex.kex_dhiexchange) == -1) | |||
4346 | goto done; | |||
4347 | len = sizeof(*ke) + ibuf_size(nsa->sa_dhiexchangesa_kex.kex_dhiexchange); | |||
4348 | ||||
4349 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONE0) == -1) | |||
4350 | goto done; | |||
4351 | ||||
4352 | ret = ikev2_msg_send_encrypt(env, sa, &e, | |||
4353 | IKEV2_EXCHANGE_CREATE_CHILD_SA36, IKEV2_PAYLOAD_SA33, 0); | |||
4354 | if (ret == 0) { | |||
4355 | sa->sa_stateflags |= IKED_REQ_CHILDSA0x0080; | |||
4356 | sa->sa_nexti = nsa; | |||
4357 | nsa->sa_previ = sa; | |||
4358 | sa->sa_tmpfail = 0; | |||
4359 | nsa = NULL((void *)0); | |||
4360 | } | |||
4361 | done: | |||
4362 | if (nsa) { | |||
4363 | ikev2_ike_sa_setreason(nsa, "failed to send CREATE_CHILD_SA"); | |||
4364 | sa_free(env, nsa); | |||
4365 | } | |||
4366 | ibuf_free(e); | |||
4367 | ||||
4368 | if (ret == 0) | |||
4369 | log_debug("%s: create child SA sent", __func__); | |||
4370 | else | |||
4371 | log_debug("%s: could not send create child SA", __func__); | |||
4372 | /* XXX should we try again in case of ret != 0 ? */ | |||
4373 | } | |||
4374 | ||||
4375 | int | |||
4376 | ikev2_nonce_cmp(struct ibuf *a, struct ibuf *b) | |||
4377 | { | |||
4378 | size_t alen, blen, len; | |||
4379 | int ret; | |||
4380 | ||||
4381 | alen = ibuf_size(a); | |||
4382 | blen = ibuf_size(b); | |||
4383 | len = MINIMUM(alen, blen)(((alen)<(blen))?(alen):(blen)); | |||
4384 | ret = memcmp(ibuf_data(a), ibuf_data(b), len); | |||
4385 | if (ret == 0) | |||
4386 | ret = (alen < blen ? -1 : 1); | |||
4387 | return (ret); | |||
4388 | } | |||
4389 | ||||
4390 | int | |||
4391 | ikev2_init_create_child_sa(struct iked *env, struct iked_message *msg) | |||
4392 | { | |||
4393 | struct iked_childsa *csa = NULL((void *)0); | |||
4394 | struct iked_proposal *prop; | |||
4395 | struct iked_sa *sa = msg->msg_sa; | |||
4396 | struct iked_sa *nsa, *dsa; | |||
4397 | struct iked_spi *spi; | |||
4398 | struct ikev2_delete *del; | |||
4399 | struct ibuf *buf = NULL((void *)0); | |||
4400 | struct ibuf *ni, *nr; | |||
4401 | uint32_t spi32; | |||
4402 | int pfs = 0, ret = -1; | |||
4403 | ||||
4404 | if (!ikev2_msg_frompeer(msg) || | |||
4405 | (sa->sa_stateflags & (IKED_REQ_CHILDSA0x0080|IKED_REQ_INF0x0100)) == 0) | |||
4406 | return (0); | |||
4407 | ||||
4408 | if (sa->sa_nexti != NULL((void *)0) && sa->sa_tmpfail) { | |||
4409 | sa->sa_stateflags &= ~IKED_REQ_CHILDSA0x0080; | |||
4410 | ikev2_ike_sa_setreason(sa->sa_nexti, "tmpfail"); | |||
4411 | sa_free(env, sa->sa_nexti); | |||
4412 | sa->sa_nexti = NULL((void *)0); | |||
4413 | timer_set(env, &sa->sa_rekey, ikev2_ike_sa_rekey, sa); | |||
4414 | ikev2_ike_sa_rekey_schedule_fast(env, sa); | |||
4415 | log_info("%s: IKESA rekey delayed", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
4416 | return (0); | |||
4417 | } | |||
4418 | ||||
4419 | if (msg->msg_prop == NULL((void *)0) || | |||
4420 | TAILQ_EMPTY(&msg->msg_proposals)(((&msg->msg_proposals)->tqh_first) == ((void *)0))) { | |||
4421 | log_info("%s: no proposal specified", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
4422 | return (-1); | |||
4423 | } | |||
4424 | ||||
4425 | if (proposals_negotiate(&sa->sa_proposals, &sa->sa_proposals, | |||
4426 | &msg->msg_proposals, 1, -1) != 0) { | |||
4427 | log_info("%s: no proposal chosen", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
4428 | ikestat_inc(env, ikes_sa_proposals_negotiate_failures)do { env->sc_stats.ikes_sa_proposals_negotiate_failures += (1); } while(0); | |||
4429 | return (-1); | |||
4430 | } | |||
4431 | ||||
4432 | TAILQ_FOREACH(prop, &sa->sa_proposals, prop_entry)for((prop) = ((&sa->sa_proposals)->tqh_first); (prop ) != ((void *)0); (prop) = ((prop)->prop_entry.tqe_next)) { | |||
4433 | if (prop->prop_protoid == msg->msg_prop->prop_protoid) | |||
4434 | break; | |||
4435 | } | |||
4436 | if (prop == NULL((void *)0)) { | |||
4437 | log_info("%s: failed to find %s proposals", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
4438 | print_map(msg->msg_prop->prop_protoid, ikev2_saproto_map)); | |||
4439 | return (-1); | |||
4440 | } | |||
4441 | ||||
4442 | /* IKE SA rekeying */ | |||
4443 | if (prop->prop_protoid == IKEV2_SAPROTO_IKE1) { | |||
4444 | if (sa->sa_nexti == NULL((void *)0)) { | |||
4445 | log_info("%s: missing IKE SA for rekeying", | |||
4446 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
4447 | return (-1); | |||
4448 | } | |||
4449 | /* Update the responder SPI */ | |||
4450 | /* XXX sa_new() is just a lookup, so nsa == sa->sa_nexti */ | |||
4451 | spi = &msg->msg_prop->prop_peerspi; | |||
4452 | if ((nsa = sa_new(env, sa->sa_nexti->sa_hdr.sh_ispi, | |||
4453 | spi->spi, 1, NULL((void *)0))) == NULL((void *)0) || nsa != sa->sa_nexti) { | |||
4454 | log_info("%s: invalid rekey SA", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
4455 | if (nsa) { | |||
4456 | ikev2_ike_sa_setreason(nsa, | |||
4457 | "invalid SA for rekey"); | |||
4458 | sa_free(env, nsa); | |||
4459 | } | |||
4460 | ikev2_ike_sa_setreason(sa->sa_nexti, "invalid SA nexti"); | |||
4461 | sa_free(env, sa->sa_nexti); | |||
4462 | sa->sa_nexti = NULL((void *)0); /* reset by sa_free */ | |||
4463 | return (-1); | |||
4464 | } | |||
4465 | if (ikev2_sa_initiator(env, nsa, sa, msg) == -1) { | |||
4466 | log_info("%s: failed to get IKE keys", | |||
4467 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
4468 | return (-1); | |||
4469 | } | |||
4470 | sa->sa_stateflags &= ~IKED_REQ_CHILDSA0x0080; | |||
4471 | if (sa->sa_nextr) { | |||
4472 | /* | |||
4473 | * Resolve simultaneous IKE SA rekeying by | |||
4474 | * deleting the SA with the lowest NONCE. | |||
4475 | */ | |||
4476 | log_info("%s: resolving simultaneous IKE SA rekeying", | |||
4477 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
4478 | /* ni: minimum nonce of sa_nexti */ | |||
4479 | if (ikev2_nonce_cmp(sa->sa_nexti->sa_inoncesa_kex.kex_inonce, | |||
4480 | sa->sa_nexti->sa_rnoncesa_kex.kex_rnonce) < 0) | |||
4481 | ni = sa->sa_nexti->sa_inoncesa_kex.kex_inonce; | |||
4482 | else | |||
4483 | ni = sa->sa_nexti->sa_rnoncesa_kex.kex_rnonce; | |||
4484 | /* nr: minimum nonce of sa_nextr */ | |||
4485 | if (ikev2_nonce_cmp(sa->sa_nextr->sa_inoncesa_kex.kex_inonce, | |||
4486 | sa->sa_nextr->sa_rnoncesa_kex.kex_rnonce) < 0) | |||
4487 | nr = sa->sa_nextr->sa_inoncesa_kex.kex_inonce; | |||
4488 | else | |||
4489 | nr = sa->sa_nextr->sa_rnoncesa_kex.kex_rnonce; | |||
4490 | /* delete SA with minumum nonce */ | |||
4491 | if (ikev2_nonce_cmp(ni, nr) < 0) { | |||
4492 | dsa = sa->sa_nexti; | |||
4493 | nsa = sa->sa_nextr; | |||
4494 | } else { | |||
4495 | dsa = sa->sa_nextr; | |||
4496 | nsa = sa->sa_nexti; | |||
4497 | } | |||
4498 | /* unlink sa_nextr */ | |||
4499 | sa->sa_nextr->sa_prevr = NULL((void *)0); | |||
4500 | sa->sa_nextr = NULL((void *)0); | |||
4501 | /* Setup address, socket and NAT information */ | |||
4502 | sa_address(dsa, &dsa->sa_peer, | |||
4503 | (struct sockaddr *)&sa->sa_peer.addr); | |||
4504 | sa_address(dsa, &dsa->sa_local, | |||
4505 | (struct sockaddr *)&sa->sa_local.addr); | |||
4506 | dsa->sa_fd = sa->sa_fd; | |||
4507 | dsa->sa_natt = sa->sa_natt; | |||
4508 | dsa->sa_udpencap = sa->sa_udpencap; | |||
4509 | ikev2_ike_sa_setreason(dsa, | |||
4510 | "resolving simultaneous rekeying"); | |||
4511 | ikev2_ikesa_delete(env, dsa, dsa->sa_hdr.sh_initiator); | |||
4512 | } | |||
4513 | /* unlink sa_nexti */ | |||
4514 | sa->sa_nexti->sa_previ = NULL((void *)0); | |||
4515 | sa->sa_nexti = NULL((void *)0); | |||
4516 | return (ikev2_ikesa_enable(env, sa, nsa)); | |||
4517 | } | |||
4518 | ||||
4519 | /* Child SA rekeying */ | |||
4520 | if (sa->sa_rekeyspi && | |||
4521 | (csa = childsa_lookup(sa, sa->sa_rekeyspi, prop->prop_protoid)) | |||
4522 | != NULL((void *)0)) { | |||
4523 | log_info("%s: rekeying CHILD SA old %s spi %s", | |||
4524 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
4525 | print_spi(csa->csa_spi.spi, csa->csa_spi.spi_size), | |||
4526 | print_spi(prop->prop_peerspi.spi, | |||
4527 | prop->prop_peerspi.spi_size)); | |||
4528 | } | |||
4529 | ||||
4530 | /* check KE payload for PFS */ | |||
4531 | if (ibuf_length(msg->msg_ke)) { | |||
4532 | log_debug("%s: using PFS", __func__); | |||
4533 | if (ikev2_sa_initiator_dh(sa, msg, prop->prop_protoid, NULL((void *)0)) < 0) { | |||
4534 | log_info("%s: failed to setup DH", | |||
4535 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
4536 | return (ret); | |||
4537 | } | |||
4538 | if (sa->sa_dhpeersa_kex.kex_dhpeer == NULL((void *)0)) { | |||
4539 | log_info("%s: no peer DH", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
4540 | return (ret); | |||
4541 | } | |||
4542 | pfs = 1; | |||
4543 | /* XXX check group against policy ? */ | |||
4544 | /* XXX should proposals_negotiate do this? */ | |||
4545 | } | |||
4546 | ||||
4547 | /* Update responder's nonce */ | |||
4548 | if (!ibuf_length(msg->msg_nonce)) { | |||
4549 | log_info("%s: responder didn't send nonce", | |||
4550 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
4551 | return (-1); | |||
4552 | } | |||
4553 | ibuf_free(sa->sa_rnoncesa_kex.kex_rnonce); | |||
4554 | sa->sa_rnoncesa_kex.kex_rnonce = msg->msg_nonce; | |||
4555 | msg->msg_nonce = NULL((void *)0); | |||
4556 | ||||
4557 | if (csa && (nr = sa->sa_simult) != NULL((void *)0)) { | |||
4558 | log_info("%s: resolving simultaneous CHILD SA rekeying", | |||
4559 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
4560 | /* set ni to minimum nonce for exchange initiated by us */ | |||
4561 | if (ikev2_nonce_cmp(sa->sa_inoncesa_kex.kex_inonce, sa->sa_rnoncesa_kex.kex_rnonce) < 0) | |||
4562 | ni = sa->sa_inoncesa_kex.kex_inonce; | |||
4563 | else | |||
4564 | ni = sa->sa_rnoncesa_kex.kex_rnonce; | |||
4565 | /* | |||
4566 | * If the exchange initated by us has smaller nonce, | |||
4567 | * then we have to delete our SAs. | |||
4568 | */ | |||
4569 | if (ikev2_nonce_cmp(ni, nr) < 0) { | |||
4570 | ret = ikev2_childsa_delete_proposed(env, sa, | |||
4571 | &sa->sa_proposals); | |||
4572 | goto done; | |||
4573 | } | |||
4574 | } | |||
4575 | ||||
4576 | if (ikev2_childsa_negotiate(env, sa, &sa->sa_kex, &sa->sa_proposals, 1, | |||
4577 | pfs)) { | |||
4578 | log_info("%s: failed to get CHILD SAs", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
4579 | return (-1); | |||
4580 | } | |||
4581 | ||||
4582 | if (csa) { | |||
4583 | /* Child SA rekeying */ | |||
4584 | ||||
4585 | if ((buf = ibuf_static()) == NULL((void *)0)) | |||
4586 | goto done; | |||
4587 | ||||
4588 | if ((del = ibuf_reserve(buf, sizeof(*del))) == NULL((void *)0)) | |||
4589 | goto done; | |||
4590 | ||||
4591 | del->del_protoid = prop->prop_protoid; | |||
4592 | del->del_spisize = sizeof(spi32); | |||
4593 | 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)); | |||
4594 | ||||
4595 | 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)); | |||
4596 | if (ibuf_add(buf, &spi32, sizeof(spi32))) | |||
4597 | goto done; | |||
4598 | ||||
4599 | if (ikev2_send_ike_e(env, sa, buf, IKEV2_PAYLOAD_DELETE42, | |||
4600 | IKEV2_EXCHANGE_INFORMATIONAL37, 0)) | |||
4601 | goto done; | |||
4602 | ||||
4603 | sa->sa_stateflags |= IKED_REQ_INF0x0100; | |||
4604 | } | |||
4605 | ||||
4606 | ret = ikev2_childsa_enable(env, sa); | |||
4607 | ||||
4608 | done: | |||
4609 | sa->sa_stateflags &= ~IKED_REQ_CHILDSA0x0080; | |||
4610 | ||||
4611 | if (ret) | |||
4612 | ikev2_childsa_delete(env, sa, 0, 0, NULL((void *)0), 1); | |||
4613 | else if (csa) { | |||
4614 | /* delete the rekeyed SA pair */ | |||
4615 | ikev2_childsa_delete(env, sa, csa->csa_saproto, | |||
4616 | csa->csa_peerspi, NULL((void *)0), 0); | |||
4617 | } | |||
4618 | ibuf_free(buf); | |||
4619 | return (ret); | |||
4620 | } | |||
4621 | ||||
4622 | int | |||
4623 | ikev2_ikesa_enable(struct iked *env, struct iked_sa *sa, struct iked_sa *nsa) | |||
4624 | { | |||
4625 | struct iked_childsa *csa, *csatmp, *ipcomp; | |||
4626 | struct iked_flow *flow, *flowtmp; | |||
4627 | struct iked_proposal *prop, *proptmp; | |||
4628 | int i; | |||
4629 | ||||
4630 | log_debug("%s: IKE SA %p ispi %s rspi %s replaced" | |||
4631 | " by SA %p ispi %s rspi %s ", | |||
4632 | __func__, sa, | |||
4633 | print_spi(sa->sa_hdr.sh_ispi, 8), | |||
4634 | print_spi(sa->sa_hdr.sh_rspi, 8), | |||
4635 | nsa, | |||
4636 | print_spi(nsa->sa_hdr.sh_ispi, 8), | |||
4637 | print_spi(nsa->sa_hdr.sh_rspi, 8)); | |||
4638 | ||||
4639 | /* Transfer socket and NAT information */ | |||
4640 | nsa->sa_fd = sa->sa_fd; | |||
4641 | nsa->sa_natt = sa->sa_natt; | |||
4642 | nsa->sa_udpencap = sa->sa_udpencap; | |||
4643 | nsa->sa_usekeepalive = sa->sa_usekeepalive; | |||
4644 | nsa->sa_mobike = sa->sa_mobike; | |||
4645 | nsa->sa_frag = sa->sa_frag; | |||
4646 | ||||
4647 | /* Transfer old addresses */ | |||
4648 | memcpy(&nsa->sa_local, &sa->sa_local, sizeof(nsa->sa_local)); | |||
4649 | memcpy(&nsa->sa_peer, &sa->sa_peer, sizeof(nsa->sa_peer)); | |||
4650 | memcpy(&nsa->sa_peer_loaded, &sa->sa_peer_loaded, | |||
4651 | sizeof(nsa->sa_peer_loaded)); | |||
4652 | ||||
4653 | /* Transfer all Child SAs and flows from the old IKE SA */ | |||
4654 | 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)) { | |||
4655 | 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); | |||
4656 | 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) | |||
4657 | 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); | |||
4658 | flow->flow_ikesa = nsa; | |||
4659 | flow->flow_local = &nsa->sa_local; | |||
4660 | flow->flow_peer = &nsa->sa_peer; | |||
4661 | } | |||
4662 | 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)) { | |||
4663 | 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); | |||
4664 | 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) | |||
4665 | 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); | |||
4666 | csa->csa_ikesa = nsa; | |||
4667 | if (csa->csa_dir == IPSP_DIRECTION_IN0x1) { | |||
4668 | csa->csa_local = &nsa->sa_peer; | |||
4669 | csa->csa_peer = &nsa->sa_local; | |||
4670 | } else { | |||
4671 | csa->csa_local = &nsa->sa_local; | |||
4672 | csa->csa_peer = &nsa->sa_peer; | |||
4673 | } | |||
4674 | if ((ipcomp = csa->csa_bundled) != NULL((void *)0)) { | |||
4675 | ipcomp->csa_ikesa = nsa; | |||
4676 | ipcomp->csa_local = csa->csa_local; | |||
4677 | ipcomp->csa_peer = csa->csa_peer; | |||
4678 | } | |||
4679 | } | |||
4680 | /* Transfer all non-IKE proposals */ | |||
4681 | 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)) { | |||
4682 | if (prop->prop_protoid == IKEV2_SAPROTO_IKE1) | |||
4683 | continue; | |||
4684 | 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); | |||
4685 | 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) | |||
4686 | 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); | |||
4687 | } | |||
4688 | ||||
4689 | /* Preserve ID information */ | |||
4690 | ibuf_free(nsa->sa_iid.id_buf); | |||
4691 | ibuf_free(nsa->sa_rid.id_buf); | |||
4692 | ibuf_free(nsa->sa_icert.id_buf); | |||
4693 | ibuf_free(nsa->sa_rcert.id_buf); | |||
4694 | if (sa->sa_hdr.sh_initiator == nsa->sa_hdr.sh_initiator) { | |||
4695 | nsa->sa_iid = sa->sa_iid; | |||
4696 | nsa->sa_rid = sa->sa_rid; | |||
4697 | nsa->sa_icert = sa->sa_icert; | |||
4698 | nsa->sa_rcert = sa->sa_rcert; | |||
4699 | } else { | |||
4700 | /* initiator and responder role swapped */ | |||
4701 | nsa->sa_iid = sa->sa_rid; | |||
4702 | nsa->sa_rid = sa->sa_iid; | |||
4703 | nsa->sa_icert = sa->sa_rcert; | |||
4704 | nsa->sa_rcert = sa->sa_icert; | |||
4705 | } | |||
4706 | for (i = 0; i < IKED_SCERT_MAX3; i++) | |||
4707 | nsa->sa_scert[i] = sa->sa_scert[i]; | |||
4708 | /* duplicate the actual buffer */ | |||
4709 | nsa->sa_iid.id_buf = ibuf_dup(nsa->sa_iid.id_buf); | |||
4710 | nsa->sa_rid.id_buf = ibuf_dup(nsa->sa_rid.id_buf); | |||
4711 | nsa->sa_icert.id_buf = ibuf_dup(nsa->sa_icert.id_buf); | |||
4712 | nsa->sa_rcert.id_buf = ibuf_dup(nsa->sa_rcert.id_buf); | |||
4713 | for (i = 0; i < IKED_SCERT_MAX3; i++) | |||
4714 | nsa->sa_scert[i].id_buf = ibuf_dup(nsa->sa_scert[i].id_buf); | |||
4715 | ||||
4716 | /* Transfer sa_addrpool address */ | |||
4717 | if (sa->sa_addrpool) { | |||
4718 | RB_REMOVE(iked_addrpool, &env->sc_addrpool, sa)iked_addrpool_RB_REMOVE(&env->sc_addrpool, sa); | |||
4719 | nsa->sa_addrpool = sa->sa_addrpool; | |||
4720 | sa->sa_addrpool = NULL((void *)0); | |||
4721 | RB_INSERT(iked_addrpool, &env->sc_addrpool, nsa)iked_addrpool_RB_INSERT(&env->sc_addrpool, nsa); | |||
4722 | } | |||
4723 | if (sa->sa_addrpool6) { | |||
4724 | RB_REMOVE(iked_addrpool6, &env->sc_addrpool6, sa)iked_addrpool6_RB_REMOVE(&env->sc_addrpool6, sa); | |||
4725 | nsa->sa_addrpool6 = sa->sa_addrpool6; | |||
4726 | sa->sa_addrpool6 = NULL((void *)0); | |||
4727 | RB_INSERT(iked_addrpool6, &env->sc_addrpool6, nsa)iked_addrpool6_RB_INSERT(&env->sc_addrpool6, nsa); | |||
4728 | } | |||
4729 | nsa->sa_cp = sa->sa_cp; | |||
4730 | nsa->sa_cp_addr = sa->sa_cp_addr; | |||
4731 | sa->sa_cp_addr = NULL((void *)0); | |||
4732 | nsa->sa_cp_addr6 = sa->sa_cp_addr6; | |||
4733 | sa->sa_cp_addr6 = NULL((void *)0); | |||
4734 | nsa->sa_cp_dns = sa->sa_cp_dns; | |||
4735 | sa->sa_cp_dns = NULL((void *)0); | |||
4736 | /* Transfer other attributes */ | |||
4737 | if (sa->sa_dstid_entry_valid) { | |||
4738 | sa_dstid_remove(env, sa); | |||
4739 | sa_dstid_insert(env, nsa); | |||
4740 | } | |||
4741 | if (sa->sa_tag) { | |||
4742 | nsa->sa_tag = sa->sa_tag; | |||
4743 | sa->sa_tag = NULL((void *)0); | |||
4744 | } | |||
4745 | if (sa->sa_eapid) { | |||
4746 | nsa->sa_eapid = sa->sa_eapid; | |||
4747 | sa->sa_eapid = NULL((void *)0); | |||
4748 | } | |||
4749 | log_info("%srekeyed as new IKESA %s (enc %s%s%s group %s prf %s)", | |||
4750 | SPI_SA(sa, NULL)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((((void *)0)))), print_spi(nsa->sa_hdr.sh_ispi, 8), | |||
4751 | print_xf(nsa->sa_encr->encr_id, cipher_keylength(nsa->sa_encr) - | |||
4752 | nsa->sa_encr->encr_saltlength, ikeencxfs), | |||
4753 | nsa->sa_encr->encr_authid ? "" : " auth ", | |||
4754 | nsa->sa_encr->encr_authid ? "" : print_xf(nsa->sa_integr->hash_id, | |||
4755 | hash_keylength(nsa->sa_integr), authxfs), | |||
4756 | print_xf(nsa->sa_dhgroupsa_kex.kex_dhgroup->id, 0, groupxfs), | |||
4757 | print_xf(nsa->sa_prf->hash_id, hash_keylength(sa->sa_prf), prfxfs)); | |||
4758 | sa_state(env, nsa, IKEV2_STATE_ESTABLISHED9); | |||
4759 | ikev2_enable_timer(env, nsa); | |||
4760 | ||||
4761 | ikestat_inc(env, ikes_sa_rekeyed)do { env->sc_stats.ikes_sa_rekeyed += (1); } while(0); | |||
4762 | ||||
4763 | nsa->sa_stateflags = nsa->sa_statevalid; /* XXX */ | |||
4764 | ||||
4765 | /* unregister DPD keep alive timer & rekey first */ | |||
4766 | if (sa->sa_state == IKEV2_STATE_ESTABLISHED9) | |||
4767 | ikev2_disable_timer(env, sa); | |||
4768 | ||||
4769 | ikev2_ike_sa_setreason(sa, "SA rekeyed"); | |||
4770 | ikev2_ikesa_delete(env, sa, nsa->sa_hdr.sh_initiator); | |||
4771 | return (0); | |||
4772 | } | |||
4773 | ||||
4774 | void | |||
4775 | ikev2_ikesa_delete(struct iked *env, struct iked_sa *sa, int initiator) | |||
4776 | { | |||
4777 | struct ibuf *buf = NULL((void *)0); | |||
4778 | struct ikev2_delete *del; | |||
4779 | ||||
4780 | if (initiator) { | |||
4781 | /* XXX: Can not have simultaneous INFORMATIONAL exchanges */ | |||
4782 | if (sa->sa_stateflags & IKED_REQ_INF0x0100) | |||
4783 | goto done; | |||
4784 | /* Send PAYLOAD_DELETE */ | |||
4785 | if ((buf = ibuf_static()) == NULL((void *)0)) | |||
4786 | goto done; | |||
4787 | if ((del = ibuf_reserve(buf, sizeof(*del))) == NULL((void *)0)) | |||
4788 | goto done; | |||
4789 | del->del_protoid = IKEV2_SAPROTO_IKE1; | |||
4790 | del->del_spisize = 0; | |||
4791 | del->del_nspi = 0; | |||
4792 | if (ikev2_send_ike_e(env, sa, buf, IKEV2_PAYLOAD_DELETE42, | |||
4793 | IKEV2_EXCHANGE_INFORMATIONAL37, 0) == -1) | |||
4794 | goto done; | |||
4795 | sa->sa_stateflags |= IKED_REQ_INF0x0100; | |||
4796 | log_info("%s: sent delete, closing SA", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
4797 | done: | |||
4798 | ibuf_free(buf); | |||
4799 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
4800 | } else { | |||
4801 | sa_state(env, sa, IKEV2_STATE_CLOSING10); | |||
4802 | } | |||
4803 | ||||
4804 | /* Remove IKE-SA after timeout, e.g. if we don't get a delete */ | |||
4805 | timer_set(env, &sa->sa_timer, ikev2_ike_sa_timeout, sa); | |||
4806 | timer_add(env, &sa->sa_timer, IKED_IKE_SA_DELETE_TIMEOUT120); | |||
4807 | ikev2_ike_sa_setreason(sa, "deleting SA"); | |||
4808 | } | |||
4809 | ||||
4810 | void | |||
4811 | ikev2_ikesa_recv_delete(struct iked *env, struct iked_sa *sa) | |||
4812 | { | |||
4813 | log_info("%s: received delete", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
4814 | if (sa->sa_nexti) { | |||
4815 | /* | |||
4816 | * We initiated rekeying, but since sa_nexti is still set | |||
4817 | * we have to assume that the the peer did not receive our | |||
4818 | * rekey message. So remove the initiated SA and -- if | |||
4819 | * sa_nextr is set -- keep the responder SA instead. | |||
4820 | */ | |||
4821 | if (sa->sa_nextr) { | |||
4822 | log_debug("%s: resolving simultaneous IKE SA rekeying", | |||
4823 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
4824 | ikev2_ikesa_enable(env, sa, sa->sa_nextr); | |||
4825 | /* unlink sa_nextr */ | |||
4826 | sa->sa_nextr->sa_prevr = NULL((void *)0); | |||
4827 | sa->sa_nextr = NULL((void *)0); | |||
4828 | } | |||
4829 | ikev2_ike_sa_setreason(sa->sa_nexti, | |||
4830 | "received delete (simultaneous rekeying)"); | |||
4831 | sa_free(env, sa->sa_nexti); | |||
4832 | sa->sa_nexti = NULL((void *)0); /* reset by sa_free */ | |||
4833 | } | |||
4834 | ikev2_ike_sa_setreason(sa, "received delete"); | |||
4835 | if (env->sc_stickyaddresssc_static.st_stickyaddress) { | |||
4836 | /* delay deletion if client reconnects soon */ | |||
4837 | sa_state(env, sa, IKEV2_STATE_CLOSING10); | |||
4838 | timer_del(env, &sa->sa_timer); | |||
4839 | timer_set(env, &sa->sa_timer, ikev2_ike_sa_timeout, sa); | |||
4840 | timer_add(env, &sa->sa_timer, 3 * IKED_RETRANSMIT_TIMEOUT2); | |||
4841 | } else { | |||
4842 | sa_state(env, sa, IKEV2_STATE_CLOSED11); | |||
4843 | } | |||
4844 | } | |||
4845 | ||||
4846 | int | |||
4847 | ikev2_resp_create_child_sa(struct iked *env, struct iked_message *msg) | |||
4848 | { | |||
4849 | struct iked_childsa *csa = NULL((void *)0); | |||
4850 | struct iked_proposal *prop; | |||
4851 | struct iked_proposals proposals; | |||
4852 | struct iked_kex *kex, *kextmp = NULL((void *)0); | |||
4853 | struct iked_sa *nsa = NULL((void *)0), *sa = msg->msg_sa; | |||
4854 | struct iked_spi *spi, *rekey = &msg->msg_rekey; | |||
4855 | struct iked_transform *xform; | |||
4856 | struct ikev2_keyexchange *ke; | |||
4857 | struct ikev2_payload *pld = NULL((void *)0); | |||
4858 | struct ibuf *e = NULL((void *)0), *nonce = NULL((void *)0); | |||
4859 | uint8_t firstpayload; | |||
4860 | ssize_t len = 0; | |||
4861 | int initiator, protoid, rekeying = 1; | |||
4862 | int ret = -1; | |||
4863 | int pfs = 0; | |||
4864 | ||||
4865 | initiator = sa->sa_hdr.sh_initiator ? 1 : 0; | |||
4866 | ||||
4867 | if (!ikev2_msg_frompeer(msg) || msg->msg_prop == NULL((void *)0)) | |||
4868 | return (0); | |||
4869 | ||||
4870 | TAILQ_INIT(&proposals)do { (&proposals)->tqh_first = ((void *)0); (&proposals )->tqh_last = &(&proposals)->tqh_first; } while (0); | |||
4871 | ||||
4872 | if ((protoid = rekey->spi_protoid) == 0) { | |||
4873 | /* | |||
4874 | * If REKEY_SA notification is not present, then it's either | |||
4875 | * IKE SA rekeying or the client wants to create additional | |||
4876 | * CHILD SAs | |||
4877 | */ | |||
4878 | if (msg->msg_prop->prop_protoid == IKEV2_SAPROTO_IKE1) { | |||
4879 | protoid = rekey->spi_protoid = IKEV2_SAPROTO_IKE1; | |||
4880 | if (sa->sa_hdr.sh_initiator) | |||
4881 | rekey->spi = sa->sa_hdr.sh_rspi; | |||
4882 | else | |||
4883 | rekey->spi = sa->sa_hdr.sh_ispi; | |||
4884 | rekey->spi_size = 8; | |||
4885 | } else { | |||
4886 | protoid = msg->msg_prop->prop_protoid; | |||
4887 | rekeying = 0; | |||
4888 | } | |||
4889 | } | |||
4890 | ||||
4891 | if (rekeying) | |||
4892 | log_debug("%s: rekey %s spi %s", __func__, | |||
4893 | print_map(rekey->spi_protoid, ikev2_saproto_map), | |||
4894 | print_spi(rekey->spi, rekey->spi_size)); | |||
4895 | else | |||
4896 | log_debug("%s: creating new %s SA", __func__, | |||
4897 | print_map(protoid, ikev2_saproto_map)); | |||
4898 | ||||
4899 | if (protoid == IKEV2_SAPROTO_IKE1) { | |||
4900 | if ((sa->sa_stateflags & IKED_REQ_CHILDSA0x0080) | |||
4901 | && !(sa->sa_nexti)) { | |||
4902 | log_debug("%s: Ignore IKE SA rekey: waiting for Child " | |||
4903 | "SA response.", __func__); | |||
4904 | /* Ignore, don't send error */ | |||
4905 | msg->msg_valid = 0; | |||
4906 | return (0); | |||
4907 | } | |||
4908 | ||||
4909 | /* IKE SA rekeying */ | |||
4910 | spi = &msg->msg_prop->prop_peerspi; | |||
4911 | ||||
4912 | if ((nsa = sa_new(env, spi->spi, 0, 0, | |||
4913 | msg->msg_policy)) == NULL((void *)0)) { | |||
4914 | log_debug("%s: failed to get new SA", __func__); | |||
4915 | return (ret); | |||
4916 | } | |||
4917 | ||||
4918 | if (ikev2_sa_responder(env, nsa, sa, msg)) { | |||
4919 | log_debug("%s: failed to get IKE SA keys", __func__); | |||
4920 | return (ret); | |||
4921 | } | |||
4922 | ||||
4923 | sa_state(env, nsa, IKEV2_STATE_AUTH_SUCCESS6); | |||
4924 | ||||
4925 | nonce = nsa->sa_rnoncesa_kex.kex_rnonce; | |||
4926 | kex = &nsa->sa_kex; | |||
4927 | } else { | |||
4928 | /* Child SA creating/rekeying */ | |||
4929 | ||||
4930 | if ((kex = kextmp = calloc(1, sizeof(*kextmp))) == NULL((void *)0)) { | |||
4931 | log_debug("%s: calloc kex", __func__); | |||
4932 | goto fail; | |||
4933 | } | |||
4934 | ||||
4935 | if (proposals_negotiate(&proposals, | |||
4936 | &sa->sa_policy->pol_proposals, &msg->msg_proposals, | |||
4937 | 1, msg->msg_dhgroup) != 0) { | |||
4938 | log_info("%s: no proposal chosen", __func__); | |||
4939 | msg->msg_error = IKEV2_N_NO_PROPOSAL_CHOSEN14; | |||
4940 | ikestat_inc(env, ikes_sa_proposals_negotiate_failures)do { env->sc_stats.ikes_sa_proposals_negotiate_failures += (1); } while(0); | |||
4941 | goto fail; | |||
4942 | } | |||
4943 | ||||
4944 | /* Check KE payload for PFS, ignore if DH transform is NONE */ | |||
4945 | if (((xform = config_findtransform(&proposals, | |||
4946 | IKEV2_XFORMTYPE_DH4, protoid)) != NULL((void *)0)) && | |||
4947 | xform->xform_id != IKEV2_XFORMDH_NONE0 && | |||
4948 | ibuf_length(msg->msg_ke)) { | |||
4949 | log_debug("%s: using PFS", __func__); | |||
4950 | if (ikev2_sa_responder_dh(kex, &proposals, | |||
4951 | msg, protoid) < 0) { | |||
4952 | log_debug("%s: failed to setup DH", __func__); | |||
4953 | goto fail; | |||
4954 | } | |||
4955 | pfs = 1; | |||
4956 | /* XXX check group against policy ? */ | |||
4957 | } | |||
4958 | ||||
4959 | /* Update peer SPI */ | |||
4960 | TAILQ_FOREACH(prop, &proposals, prop_entry)for((prop) = ((&proposals)->tqh_first); (prop) != ((void *)0); (prop) = ((prop)->prop_entry.tqe_next)) { | |||
4961 | if (prop->prop_protoid == protoid) | |||
4962 | break; | |||
4963 | } | |||
4964 | if (prop == NULL((void *)0)) { | |||
4965 | log_debug("%s: failed to find %s proposals", __func__, | |||
4966 | print_map(protoid, ikev2_saproto_map)); | |||
4967 | goto fail; | |||
4968 | } else | |||
4969 | prop->prop_peerspi = msg->msg_prop->prop_peerspi; | |||
4970 | ||||
4971 | /* Set rekeying flags on Child SAs */ | |||
4972 | if (rekeying) { | |||
4973 | if ((csa = childsa_lookup(sa, rekey->spi, | |||
4974 | rekey->spi_protoid)) == NULL((void *)0)) { | |||
4975 | log_info("%s: CHILD SA %s wasn't found", | |||
4976 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
4977 | print_spi(rekey->spi, rekey->spi_size)); | |||
4978 | msg->msg_error = IKEV2_N_CHILD_SA_NOT_FOUND44; | |||
4979 | goto fail; | |||
4980 | } | |||
4981 | if (!csa->csa_loaded || !csa->csa_peersa || | |||
4982 | !csa->csa_peersa->csa_loaded) { | |||
4983 | log_info("%s: CHILD SA %s is not loaded" | |||
4984 | " or no peer SA", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
4985 | print_spi(rekey->spi, rekey->spi_size)); | |||
4986 | msg->msg_error = IKEV2_N_CHILD_SA_NOT_FOUND44; | |||
4987 | goto fail; | |||
4988 | } | |||
4989 | csa->csa_rekey = 1; | |||
4990 | csa->csa_peersa->csa_rekey = 1; | |||
4991 | } | |||
4992 | ||||
4993 | /* Update initiator's nonce */ | |||
4994 | if (!ibuf_length(msg->msg_nonce)) { | |||
4995 | log_debug("%s: initiator didn't send nonce", __func__); | |||
4996 | goto fail; | |||
4997 | } | |||
4998 | ibuf_free(kex->kex_inonce); | |||
4999 | kex->kex_inonce = msg->msg_nonce; | |||
5000 | msg->msg_nonce = NULL((void *)0); | |||
5001 | ||||
5002 | /* Generate new responder's nonce */ | |||
5003 | if ((nonce = ibuf_random(IKED_NONCE_SIZE32)) == NULL((void *)0)) | |||
5004 | goto fail; | |||
5005 | ||||
5006 | /* Update responder's nonce */ | |||
5007 | ibuf_free(kex->kex_rnonce); | |||
5008 | kex->kex_rnonce = nonce; | |||
5009 | ||||
5010 | if (ikev2_childsa_negotiate(env, sa, kex, &proposals, 0, pfs)) { | |||
5011 | log_debug("%s: failed to get CHILD SAs", __func__); | |||
5012 | goto fail; | |||
5013 | } | |||
5014 | ||||
5015 | if (rekeying && (sa->sa_stateflags & IKED_REQ_CHILDSA0x0080) && | |||
5016 | csa && (sa->sa_rekeyspi == csa->csa_peerspi)) { | |||
5017 | log_info("%s: simultaneous rekeying for CHILD SA %s/%s", | |||
5018 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
5019 | print_spi(rekey->spi, rekey->spi_size), | |||
5020 | print_spi(sa->sa_rekeyspi, rekey->spi_size)); | |||
5021 | ibuf_free(sa->sa_simult); | |||
5022 | if (ikev2_nonce_cmp(kex->kex_inonce, nonce) < 0) | |||
5023 | sa->sa_simult = ibuf_dup(kex->kex_inonce); | |||
5024 | else | |||
5025 | sa->sa_simult = ibuf_dup(nonce); | |||
5026 | } | |||
5027 | } | |||
5028 | ||||
5029 | if ((e = ibuf_static()) == NULL((void *)0)) | |||
5030 | goto done; | |||
5031 | ||||
5032 | if (!nsa && sa->sa_ipcompr.ic_transform && | |||
5033 | (len = ikev2_add_ipcompnotify(env, e, &pld, 0, sa, 0)) == -1) | |||
5034 | goto done; | |||
5035 | if (!nsa && sa->sa_used_transport_mode && | |||
5036 | (len = ikev2_add_transport_mode(env, e, &pld, len, sa)) == -1) | |||
5037 | goto done; | |||
5038 | ||||
5039 | if (pld) { | |||
5040 | firstpayload = IKEV2_PAYLOAD_NOTIFY41; | |||
5041 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_SA33) == -1) | |||
5042 | goto done; | |||
5043 | } else | |||
5044 | firstpayload = IKEV2_PAYLOAD_SA33; | |||
5045 | ||||
5046 | /* SA payload */ | |||
5047 | if ((pld = ikev2_add_payload(e)) == NULL((void *)0)) | |||
5048 | goto done; | |||
5049 | ||||
5050 | if ((len = ikev2_add_proposals(env, nsa ? nsa : sa, e, | |||
5051 | nsa ? &nsa->sa_proposals : &proposals, | |||
5052 | protoid, 0, nsa ? 1 : 0, 0)) == -1) | |||
5053 | goto done; | |||
5054 | ||||
5055 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONCE40) == -1) | |||
5056 | goto done; | |||
5057 | ||||
5058 | /* NONCE payload */ | |||
5059 | if ((pld = ikev2_add_payload(e)) == NULL((void *)0)) | |||
5060 | goto done; | |||
5061 | if (ikev2_add_buf(e, nonce) == -1) | |||
5062 | goto done; | |||
5063 | len = ibuf_size(nonce); | |||
5064 | ||||
5065 | if (protoid == IKEV2_SAPROTO_IKE1 || pfs) { | |||
5066 | ||||
5067 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_KE34) == -1) | |||
5068 | goto done; | |||
5069 | ||||
5070 | /* KE payload */ | |||
5071 | if ((pld = ikev2_add_payload(e)) == NULL((void *)0)) | |||
5072 | goto done; | |||
5073 | if ((ke = ibuf_reserve(e, sizeof(*ke))) == NULL((void *)0)) | |||
5074 | goto done; | |||
5075 | if (kex->kex_dhgroup == NULL((void *)0)) { | |||
5076 | log_debug("%s: invalid dh", __func__); | |||
5077 | goto done; | |||
5078 | } | |||
5079 | 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)); | |||
5080 | if (ikev2_add_buf(e, kex->kex_dhrexchange) == -1) | |||
5081 | goto done; | |||
5082 | len = sizeof(*ke) + ibuf_size(kex->kex_dhrexchange); | |||
5083 | } | |||
5084 | ||||
5085 | if (protoid != IKEV2_SAPROTO_IKE1) | |||
5086 | if ((len = ikev2_add_ts(e, &pld, len, sa, initiator)) == -1) | |||
5087 | goto done; | |||
5088 | ||||
5089 | if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_NONE0) == -1) | |||
5090 | goto done; | |||
5091 | ||||
5092 | if ((ret = ikev2_msg_send_encrypt(env, sa, &e, | |||
5093 | IKEV2_EXCHANGE_CREATE_CHILD_SA36, firstpayload, 1)) == -1) | |||
5094 | goto done; | |||
5095 | ||||
5096 | if (protoid == IKEV2_SAPROTO_IKE1) { | |||
5097 | /* | |||
5098 | * If we also have initiated rekeying for this IKE SA, then | |||
5099 | * sa_nexti is already set. In this case don't enable the new SA | |||
5100 | * immediately, but record it in sa_nextr, until the exchange | |||
5101 | * for sa_nexti completes in ikev2_init_create_child_sa() and | |||
5102 | * the 'winner' can be selected by comparing nonces. | |||
5103 | */ | |||
5104 | if (sa->sa_nexti) { | |||
5105 | log_info("%s: simultaneous IKE SA rekeying", | |||
5106 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5107 | sa->sa_nextr = nsa; | |||
5108 | nsa->sa_prevr = sa; /* backpointer */ | |||
5109 | ret = 0; | |||
5110 | } else | |||
5111 | ret = ikev2_ikesa_enable(env, sa, nsa); | |||
5112 | } else | |||
5113 | ret = ikev2_childsa_enable(env, sa); | |||
5114 | ||||
5115 | done: | |||
5116 | if (ret && protoid != IKEV2_SAPROTO_IKE1) | |||
5117 | ikev2_childsa_delete(env, sa, 0, 0, NULL((void *)0), 1); | |||
5118 | ibuf_free(e); | |||
5119 | config_free_proposals(&proposals, 0); | |||
5120 | config_free_kex(kextmp); | |||
5121 | return (ret); | |||
5122 | ||||
5123 | fail: | |||
5124 | config_free_proposals(&proposals, 0); | |||
5125 | config_free_kex(kextmp); | |||
5126 | return (-1); | |||
5127 | } | |||
5128 | ||||
5129 | void | |||
5130 | ikev2_ike_sa_setreason(struct iked_sa *sa, char *reason) | |||
5131 | { | |||
5132 | /* allow update only if reason is reset to NULL */ | |||
5133 | if (reason == NULL((void *)0) || sa->sa_reason == NULL((void *)0)) | |||
5134 | sa->sa_reason = reason; | |||
5135 | } | |||
5136 | ||||
5137 | void | |||
5138 | ikev2_ike_sa_timeout(struct iked *env, void *arg) | |||
5139 | { | |||
5140 | struct iked_sa *sa = arg; | |||
5141 | ||||
5142 | log_debug("%s: closing SA", __func__); | |||
5143 | ikev2_ike_sa_setreason(sa, "timeout"); | |||
5144 | sa_free(env, sa); | |||
5145 | } | |||
5146 | ||||
5147 | void | |||
5148 | ikev2_ike_sa_rekey_timeout(struct iked *env, void *arg) | |||
5149 | { | |||
5150 | struct iked_sa *sa = arg; | |||
5151 | ||||
5152 | log_debug("%s: closing SA", __func__); | |||
5153 | ikev2_ike_sa_setreason(sa, "rekey timeout"); | |||
5154 | sa_free(env, sa); | |||
5155 | } | |||
5156 | ||||
5157 | void | |||
5158 | ikev2_ike_sa_rekey_schedule(struct iked *env, struct iked_sa *sa) | |||
5159 | { | |||
5160 | timer_add(env, &sa->sa_rekey, (sa->sa_policy->pol_rekey * 850 + | |||
5161 | arc4random_uniform(100)) / 1000); | |||
5162 | } | |||
5163 | ||||
5164 | /* rekey delayed, so re-try after short delay (1% of configured) */ | |||
5165 | void | |||
5166 | ikev2_ike_sa_rekey_schedule_fast(struct iked *env, struct iked_sa *sa) | |||
5167 | { | |||
5168 | int timeout = sa->sa_policy->pol_rekey / 100; /* 1% */ | |||
5169 | ||||
5170 | if (timeout > 60) | |||
5171 | timeout = 60; /* max */ | |||
5172 | else if (timeout < 4) | |||
5173 | timeout = 4; /* min */ | |||
5174 | timer_add(env, &sa->sa_rekey, timeout); | |||
5175 | } | |||
5176 | ||||
5177 | void | |||
5178 | ikev2_ike_sa_alive(struct iked *env, void *arg) | |||
5179 | { | |||
5180 | struct iked_sa *sa = arg; | |||
5181 | struct iked_childsa *csa = NULL((void *)0); | |||
5182 | uint64_t last_used, diff; | |||
5183 | int foundin = 0, foundout = 0; | |||
5184 | int ikeidle = 0; | |||
5185 | ||||
5186 | if (env->sc_alive_timeoutsc_static.st_alive_timeout == 0) | |||
5187 | return; | |||
5188 | ||||
5189 | /* check for incoming traffic on any child SA */ | |||
5190 | TAILQ_FOREACH(csa, &sa->sa_childsas, csa_entry)for((csa) = ((&sa->sa_childsas)->tqh_first); (csa) != ((void *)0); (csa) = ((csa)->csa_entry.tqe_next)) { | |||
5191 | if (!csa->csa_loaded) | |||
5192 | continue; | |||
5193 | if (pfkey_sa_last_used(env, csa, &last_used) != 0) | |||
5194 | continue; | |||
5195 | diff = (uint32_t)(gettime() - last_used); | |||
5196 | log_debug("%s: %s CHILD SA spi %s last used %llu second(s) ago", | |||
5197 | __func__, | |||
5198 | csa->csa_dir == IPSP_DIRECTION_IN0x1 ? "incoming" : "outgoing", | |||
5199 | print_spi(csa->csa_spi.spi, csa->csa_spi.spi_size), diff); | |||
5200 | if (diff < env->sc_alive_timeoutsc_static.st_alive_timeout) { | |||
5201 | if (csa->csa_dir == IPSP_DIRECTION_IN0x1) { | |||
5202 | foundin = 1; | |||
5203 | break; | |||
5204 | } else { | |||
5205 | foundout = 1; | |||
5206 | } | |||
5207 | } | |||
5208 | } | |||
5209 | ||||
5210 | diff = (uint32_t)(gettime() - sa->sa_last_recvd); | |||
5211 | if (diff >= IKED_IKE_SA_LAST_RECVD_TIMEOUT300) { | |||
5212 | ikeidle = 1; | |||
5213 | log_debug("%s: IKE SA %p ispi %s rspi %s last received %llu" | |||
5214 | " second(s) ago", __func__, sa, | |||
5215 | print_spi(sa->sa_hdr.sh_ispi, 8), | |||
5216 | print_spi(sa->sa_hdr.sh_rspi, 8), diff); | |||
5217 | } | |||
5218 | ||||
5219 | /* | |||
5220 | * send probe if any outgoing SA has been used, but no incoming | |||
5221 | * SA, or if we haven't received an IKE message. but only if we | |||
5222 | * are not already waiting for an answer. | |||
5223 | */ | |||
5224 | if (((!foundin && foundout) || ikeidle) && | |||
5225 | (sa->sa_stateflags & (IKED_REQ_CHILDSA0x0080|IKED_REQ_INF0x0100)) == 0) { | |||
5226 | log_debug("%s: sending alive check", __func__); | |||
5227 | ikev2_send_ike_e(env, sa, NULL((void *)0), IKEV2_PAYLOAD_NONE0, | |||
5228 | IKEV2_EXCHANGE_INFORMATIONAL37, 0); | |||
5229 | sa->sa_stateflags |= IKED_REQ_INF0x0100; | |||
5230 | ikestat_inc(env, ikes_dpd_sent)do { env->sc_stats.ikes_dpd_sent += (1); } while(0); | |||
5231 | } | |||
5232 | ||||
5233 | /* re-register */ | |||
5234 | timer_add(env, &sa->sa_timer, env->sc_alive_timeoutsc_static.st_alive_timeout); | |||
5235 | } | |||
5236 | ||||
5237 | void | |||
5238 | ikev2_ike_sa_keepalive(struct iked *env, void *arg) | |||
5239 | { | |||
5240 | struct iked_sa *sa = arg; | |||
5241 | uint8_t marker = 0xff; | |||
5242 | ||||
5243 | if (sendtofrom(sa->sa_fd, &marker, sizeof(marker), 0, | |||
5244 | (struct sockaddr *)&sa->sa_peer.addr, sa->sa_peer.addr.ss_len, | |||
5245 | (struct sockaddr *)&sa->sa_local.addr, sa->sa_local.addr.ss_len) | |||
5246 | == -1) | |||
5247 | log_warn("%s: sendtofrom: peer %s local %s", __func__, | |||
5248 | print_addr(&sa->sa_peer.addr), | |||
5249 | print_addr(&sa->sa_local.addr)); | |||
5250 | else | |||
5251 | log_debug("%s: peer %s local %s", __func__, | |||
5252 | print_addr(&sa->sa_peer.addr), | |||
5253 | print_addr(&sa->sa_local.addr)); | |||
5254 | ikestat_inc(env, ikes_keepalive_sent)do { env->sc_stats.ikes_keepalive_sent += (1); } while(0); | |||
5255 | timer_add(env, &sa->sa_keepalive, IKED_IKE_SA_KEEPALIVE_TIMEOUT20); | |||
5256 | } | |||
5257 | ||||
5258 | int | |||
5259 | ikev2_send_informational(struct iked *env, struct iked_message *msg) | |||
5260 | { | |||
5261 | struct iked_message resp; | |||
5262 | struct ike_header *hdr; | |||
5263 | struct ikev2_payload *pld; | |||
5264 | struct ikev2_notify *n; | |||
5265 | struct iked_sa *sa = msg->msg_sa, sah; | |||
5266 | struct ibuf *buf, *e = NULL((void *)0); | |||
5267 | int ret = -1; | |||
5268 | ||||
5269 | if (msg->msg_error == 0) | |||
5270 | return (0); | |||
5271 | ||||
5272 | if ((buf = ikev2_msg_init(env, &resp, | |||
5273 | &msg->msg_peer, msg->msg_peerlen, | |||
5274 | &msg->msg_local, msg->msg_locallen, 0)) == NULL((void *)0)) | |||
5275 | goto done; | |||
5276 | ||||
5277 | /* New encrypted message buffer */ | |||
5278 | if ((e = ibuf_static()) == NULL((void *)0)) | |||
5279 | goto done; | |||
5280 | ||||
5281 | /* NOTIFY payload */ | |||
5282 | if ((pld = ikev2_add_payload(e)) == NULL((void *)0)) | |||
5283 | goto done; | |||
5284 | ||||
5285 | if ((n = ibuf_reserve(e, sizeof(*n))) == NULL((void *)0)) | |||
5286 | goto done; | |||
5287 | n->n_protoid = IKEV2_SAPROTO_IKE1; /* XXX ESP etc. */ | |||
5288 | n->n_spisize = 0; | |||
5289 | 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)); | |||
5290 | ||||
5291 | switch (msg->msg_error) { | |||
5292 | case IKEV2_N_INVALID_IKE_SPI4: | |||
5293 | break; | |||
5294 | case IKEV2_N_NO_PROPOSAL_CHOSEN14: | |||
5295 | ikev2_log_proposal(msg->msg_sa, &msg->msg_proposals); | |||
5296 | break; | |||
5297 | default: | |||
5298 | log_warnx("%s: unsupported notification %s", SPI_SA(sa,ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))) | |||
5299 | __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), print_map(msg->msg_error, ikev2_n_map)); | |||
5300 | goto done; | |||
5301 | } | |||
5302 | log_info("%s: %s", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
5303 | print_map(msg->msg_error, ikev2_n_map)); | |||
5304 | ||||
5305 | if (ikev2_next_payload(pld, sizeof(*n), IKEV2_PAYLOAD_NONE0) == -1) | |||
5306 | goto done; | |||
5307 | ||||
5308 | if (sa != NULL((void *)0) && msg->msg_e) { | |||
5309 | resp.msg_msgid = ikev2_msg_id(env, sa); | |||
5310 | ||||
5311 | /* IKE header */ | |||
5312 | if ((hdr = ikev2_add_header(buf, sa, resp.msg_msgid, | |||
5313 | IKEV2_PAYLOAD_SK46, IKEV2_EXCHANGE_INFORMATIONAL37, | |||
5314 | 0)) == NULL((void *)0)) | |||
5315 | goto done; | |||
5316 | ||||
5317 | if ((pld = ikev2_add_payload(buf)) == NULL((void *)0)) | |||
5318 | goto done; | |||
5319 | ||||
5320 | /* Encrypt message and add as an E payload */ | |||
5321 | if ((e = ikev2_msg_encrypt(env, sa, e, buf)) == NULL((void *)0)) { | |||
5322 | log_debug("%s: encryption failed", __func__); | |||
5323 | goto done; | |||
5324 | } | |||
5325 | if (ibuf_add_buf(buf, e) != 0) | |||
5326 | goto done; | |||
5327 | if (ikev2_next_payload(pld, ibuf_size(e), | |||
5328 | IKEV2_PAYLOAD_NOTIFY41) == -1) | |||
5329 | goto done; | |||
5330 | ||||
5331 | if (ikev2_set_header(hdr, ibuf_size(buf) - sizeof(*hdr)) == -1) | |||
5332 | goto done; | |||
5333 | ||||
5334 | /* Add integrity checksum (HMAC) */ | |||
5335 | if (ikev2_msg_integr(env, sa, buf) != 0) { | |||
5336 | log_debug("%s: integrity checksum failed", __func__); | |||
5337 | goto done; | |||
5338 | } | |||
5339 | } else { | |||
5340 | if ((hdr = ibuf_seek(msg->msg_data, 0, sizeof(*hdr))) == NULL((void *)0)) | |||
5341 | goto done; | |||
5342 | ||||
5343 | bzero(&sah, sizeof(sah)); | |||
5344 | 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)); | |||
5345 | 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)); | |||
5346 | sah.sa_hdr.sh_initiator = | |||
5347 | hdr->ike_flags & IKEV2_FLAG_INITIATOR0x08 ? 0 : 1; | |||
5348 | ||||
5349 | resp.msg_msgid = ikev2_msg_id(env, &sah); | |||
5350 | ||||
5351 | /* IKE header */ | |||
5352 | if ((hdr = ikev2_add_header(buf, &sah, resp.msg_msgid, | |||
5353 | IKEV2_PAYLOAD_NOTIFY41, IKEV2_EXCHANGE_INFORMATIONAL37, | |||
5354 | 0)) == NULL((void *)0)) | |||
5355 | goto done; | |||
5356 | if (ibuf_add_buf(buf, e) != 0) | |||
5357 | goto done; | |||
5358 | if (ikev2_set_header(hdr, ibuf_size(buf) - sizeof(*hdr)) == -1) | |||
5359 | goto done; | |||
5360 | } | |||
5361 | ||||
5362 | resp.msg_data = buf; | |||
5363 | resp.msg_fd = msg->msg_fd; | |||
5364 | 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); | |||
5365 | ||||
5366 | ret = ikev2_msg_send(env, &resp); | |||
5367 | ||||
5368 | done: | |||
5369 | ibuf_free(e); | |||
5370 | ikev2_msg_cleanup(env, &resp); | |||
5371 | ||||
5372 | return (ret); | |||
5373 | } | |||
5374 | ||||
5375 | ssize_t | |||
5376 | ikev2_psk(struct iked_sa *sa, uint8_t *data, size_t length, | |||
5377 | uint8_t **pskptr) | |||
5378 | { | |||
5379 | uint8_t *psk; | |||
5380 | size_t psklen = -1; | |||
5381 | ||||
5382 | if (hash_setkey(sa->sa_prf, data, length) == NULL((void *)0)) | |||
5383 | return (-1); | |||
5384 | ||||
5385 | if ((psk = calloc(1, hash_keylength(sa->sa_prf))) == NULL((void *)0)) | |||
5386 | return (-1); | |||
5387 | ||||
5388 | hash_init(sa->sa_prf); | |||
5389 | hash_update(sa->sa_prf, IKEV2_KEYPAD"Key Pad for IKEv2", strlen(IKEV2_KEYPAD"Key Pad for IKEv2")); | |||
5390 | hash_final(sa->sa_prf, psk, &psklen); | |||
5391 | ||||
5392 | *pskptr = psk; | |||
5393 | return (psklen); | |||
5394 | } | |||
5395 | ||||
5396 | int | |||
5397 | ikev2_sa_initiator_dh(struct iked_sa *sa, struct iked_message *msg, | |||
5398 | unsigned int proto, struct iked_sa *osa) | |||
5399 | { | |||
5400 | struct iked_policy *pol = sa->sa_policy; | |||
5401 | struct iked_transform *xform; | |||
5402 | struct iked_proposals *proposals; | |||
5403 | ||||
5404 | proposals = osa ? &osa->sa_proposals : &pol->pol_proposals; | |||
5405 | ||||
5406 | if (sa->sa_dhgroupsa_kex.kex_dhgroup == NULL((void *)0)) { | |||
5407 | if ((xform = config_findtransform(proposals, | |||
5408 | IKEV2_XFORMTYPE_DH4, proto)) == NULL((void *)0)) { | |||
5409 | log_debug("%s: did not find dh transform", __func__); | |||
5410 | return (-1); | |||
5411 | } | |||
5412 | if ((sa->sa_dhgroupsa_kex.kex_dhgroup = | |||
5413 | group_get(xform->xform_id)) == NULL((void *)0)) { | |||
5414 | log_debug("%s: invalid dh %d", __func__, | |||
5415 | xform->xform_id); | |||
5416 | return (-1); | |||
5417 | } | |||
5418 | } | |||
5419 | ||||
5420 | if (!ibuf_length(sa->sa_dhiexchangesa_kex.kex_dhiexchange)) { | |||
5421 | if (dh_create_exchange(sa->sa_dhgroupsa_kex.kex_dhgroup, | |||
5422 | &sa->sa_dhiexchangesa_kex.kex_dhiexchange, NULL((void *)0)) == -1) { | |||
5423 | log_debug("%s: failed to get dh exchange", __func__); | |||
5424 | return (-1); | |||
5425 | } | |||
5426 | } | |||
5427 | ||||
5428 | /* Initial message */ | |||
5429 | if (msg == NULL((void *)0)) | |||
5430 | return (0); | |||
5431 | ||||
5432 | if (!ibuf_length(sa->sa_dhrexchangesa_kex.kex_dhrexchange)) { | |||
5433 | if (!ibuf_length(msg->msg_ke)) { | |||
5434 | log_debug("%s: invalid peer dh exchange", __func__); | |||
5435 | return (-1); | |||
5436 | } | |||
5437 | sa->sa_dhrexchangesa_kex.kex_dhrexchange = msg->msg_ke; | |||
5438 | msg->msg_ke = NULL((void *)0); | |||
5439 | } | |||
5440 | ||||
5441 | /* Set a pointer to the peer exchange */ | |||
5442 | sa->sa_dhpeersa_kex.kex_dhpeer = sa->sa_dhrexchangesa_kex.kex_dhrexchange; | |||
5443 | return (0); | |||
5444 | } | |||
5445 | ||||
5446 | int | |||
5447 | ikev2_sa_negotiate_common(struct iked *env, struct iked_sa *sa, | |||
5448 | struct iked_message *msg, int groupid) | |||
5449 | { | |||
5450 | struct iked_transform *xform; | |||
5451 | ||||
5452 | /* XXX we need a better way to get this */ | |||
5453 | if (proposals_negotiate(&sa->sa_proposals, | |||
5454 | &msg->msg_policy->pol_proposals, &msg->msg_proposals, 0, groupid) != 0) { | |||
5455 | log_info("%s: proposals_negotiate", __func__); | |||
5456 | ikestat_inc(env, ikes_sa_proposals_negotiate_failures)do { env->sc_stats.ikes_sa_proposals_negotiate_failures += (1); } while(0); | |||
5457 | return (-1); | |||
5458 | } | |||
5459 | if (sa_stateok(sa, IKEV2_STATE_SA_INIT2)) | |||
5460 | sa_stateflags(sa, IKED_REQ_SA0x0020); | |||
5461 | ||||
5462 | if (sa->sa_encr == NULL((void *)0)) { | |||
5463 | if ((xform = config_findtransform(&sa->sa_proposals, | |||
5464 | IKEV2_XFORMTYPE_ENCR1, 0)) == NULL((void *)0)) { | |||
5465 | log_info("%s: did not find encr transform", | |||
5466 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5467 | return (-1); | |||
5468 | } | |||
5469 | if ((sa->sa_encr = cipher_new(xform->xform_type, | |||
5470 | xform->xform_id, xform->xform_length)) == NULL((void *)0)) { | |||
5471 | log_info("%s: failed to get encr", | |||
5472 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5473 | return (-1); | |||
5474 | } | |||
5475 | } | |||
5476 | ||||
5477 | /* For AEAD ciphers integrity is implicit */ | |||
5478 | if (sa->sa_encr->encr_authid && sa->sa_integr == NULL((void *)0)) { | |||
5479 | if ((sa->sa_integr = hash_new(IKEV2_XFORMTYPE_INTEGR3, | |||
5480 | sa->sa_encr->encr_authid)) == NULL((void *)0)) { | |||
5481 | log_info("%s: failed to get AEAD integr", | |||
5482 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5483 | return (-1); | |||
5484 | } | |||
5485 | } | |||
5486 | ||||
5487 | if (sa->sa_prf == NULL((void *)0)) { | |||
5488 | if ((xform = config_findtransform(&sa->sa_proposals, | |||
5489 | IKEV2_XFORMTYPE_PRF2, 0)) == NULL((void *)0)) { | |||
5490 | log_info("%s: did not find prf transform", | |||
5491 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5492 | return (-1); | |||
5493 | } | |||
5494 | if ((sa->sa_prf = | |||
5495 | hash_new(xform->xform_type, xform->xform_id)) == NULL((void *)0)) { | |||
5496 | log_info("%s: failed to get prf", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5497 | return (-1); | |||
5498 | } | |||
5499 | } | |||
5500 | ||||
5501 | if (sa->sa_integr == NULL((void *)0)) { | |||
5502 | if ((xform = config_findtransform(&sa->sa_proposals, | |||
5503 | IKEV2_XFORMTYPE_INTEGR3, 0)) == NULL((void *)0)) { | |||
5504 | log_info("%s: did not find integr transform", | |||
5505 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5506 | return (-1); | |||
5507 | } | |||
5508 | if ((sa->sa_integr = | |||
5509 | hash_new(xform->xform_type, xform->xform_id)) == NULL((void *)0)) { | |||
5510 | log_info("%s: failed to get integr", | |||
5511 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5512 | return (-1); | |||
5513 | } | |||
5514 | } | |||
5515 | ||||
5516 | return (0); | |||
5517 | } | |||
5518 | ||||
5519 | int | |||
5520 | ikev2_sa_initiator(struct iked *env, struct iked_sa *sa, | |||
5521 | struct iked_sa *osa, struct iked_message *msg) | |||
5522 | { | |||
5523 | if (ikev2_sa_initiator_dh(sa, msg, 0, osa) < 0) | |||
5524 | return (-1); | |||
5525 | ||||
5526 | if (!ibuf_length(sa->sa_inoncesa_kex.kex_inonce)) { | |||
5527 | if ((sa->sa_inoncesa_kex.kex_inonce = ibuf_random(IKED_NONCE_SIZE32)) == NULL((void *)0)) { | |||
5528 | log_info("%s: failed to get local nonce", | |||
5529 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5530 | return (-1); | |||
5531 | } | |||
5532 | } | |||
5533 | ||||
5534 | /* Initial message */ | |||
5535 | if (msg == NULL((void *)0)) | |||
5536 | return (0); | |||
5537 | ||||
5538 | if (!ibuf_length(sa->sa_rnoncesa_kex.kex_rnonce)) { | |||
5539 | if (!ibuf_length(msg->msg_nonce)) { | |||
5540 | log_info("%s: invalid peer nonce", | |||
5541 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5542 | return (-1); | |||
5543 | } | |||
5544 | sa->sa_rnoncesa_kex.kex_rnonce = msg->msg_nonce; | |||
5545 | msg->msg_nonce = NULL((void *)0); | |||
5546 | } | |||
5547 | ||||
5548 | if (ikev2_sa_negotiate_common(env, sa, msg, -1) != 0) | |||
5549 | return (-1); | |||
5550 | ||||
5551 | ibuf_free(sa->sa_2ndmsg); | |||
5552 | if ((sa->sa_2ndmsg = ibuf_dup(msg->msg_data)) == NULL((void *)0)) { | |||
5553 | log_info("%s: failed to copy 2nd message", | |||
5554 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5555 | return (-1); | |||
5556 | } | |||
5557 | ||||
5558 | return (ikev2_sa_keys(env, sa, osa ? osa->sa_key_d : NULL((void *)0))); | |||
5559 | } | |||
5560 | ||||
5561 | int | |||
5562 | ikev2_sa_responder_dh(struct iked_kex *kex, struct iked_proposals *proposals, | |||
5563 | struct iked_message *msg, unsigned int proto) | |||
5564 | { | |||
5565 | struct iked_transform *xform; | |||
5566 | ||||
5567 | if (kex->kex_dhgroup == NULL((void *)0)) { | |||
5568 | if ((xform = config_findtransform(proposals, | |||
5569 | IKEV2_XFORMTYPE_DH4, proto)) == NULL((void *)0)) { | |||
5570 | log_info("%s: did not find dh transform", | |||
5571 | SPI_SA(msg->msg_sa, __func__)ikev2_ikesa_info((&(msg->msg_sa)->sa_hdr)->sh_ispi , ((__func__)))); | |||
5572 | return (-1); | |||
5573 | } | |||
5574 | if ((kex->kex_dhgroup = | |||
5575 | group_get(xform->xform_id)) == NULL((void *)0)) { | |||
5576 | log_debug("%s: invalid dh %d", | |||
5577 | SPI_SA(msg->msg_sa, __func__)ikev2_ikesa_info((&(msg->msg_sa)->sa_hdr)->sh_ispi , ((__func__))), xform->xform_id); | |||
5578 | return (-1); | |||
5579 | } | |||
5580 | } | |||
5581 | ||||
5582 | /* Look for dhgroup mismatch during an IKE SA negotiation */ | |||
5583 | if (msg->msg_dhgroup != kex->kex_dhgroup->id) { | |||
5584 | log_info("%s: want dh %s, KE has %s", | |||
5585 | SPI_SA(msg->msg_sa, __func__)ikev2_ikesa_info((&(msg->msg_sa)->sa_hdr)->sh_ispi , ((__func__))), | |||
5586 | print_map(kex->kex_dhgroup->id, ikev2_xformdh_map), | |||
5587 | print_map(msg->msg_dhgroup, ikev2_xformdh_map)); | |||
5588 | msg->msg_error = IKEV2_N_INVALID_KE_PAYLOAD17; | |||
5589 | msg->msg_dhgroup = kex->kex_dhgroup->id; | |||
5590 | return (-1); | |||
5591 | } | |||
5592 | ||||
5593 | if (!ibuf_length(kex->kex_dhiexchange)) { | |||
5594 | kex->kex_dhiexchange = msg->msg_ke; | |||
5595 | msg->msg_ke = NULL((void *)0); | |||
5596 | } | |||
5597 | ||||
5598 | if (!ibuf_length(kex->kex_dhrexchange)) { | |||
5599 | if (dh_create_exchange(kex->kex_dhgroup, | |||
5600 | &kex->kex_dhrexchange, kex->kex_dhiexchange) == -1) { | |||
5601 | log_info("%s: failed to get dh exchange", | |||
5602 | SPI_SA(msg->msg_sa, __func__)ikev2_ikesa_info((&(msg->msg_sa)->sa_hdr)->sh_ispi , ((__func__)))); | |||
5603 | return (-1); | |||
5604 | } | |||
5605 | } | |||
5606 | ||||
5607 | /* Set a pointer to the peer exchange */ | |||
5608 | kex->kex_dhpeer = kex->kex_dhiexchange; | |||
5609 | return (0); | |||
5610 | } | |||
5611 | ||||
5612 | int | |||
5613 | ikev2_sa_responder(struct iked *env, struct iked_sa *sa, struct iked_sa *osa, | |||
5614 | struct iked_message *msg) | |||
5615 | { | |||
5616 | struct iked_policy *old; | |||
5617 | ||||
5618 | /* re-lookup policy based on 'msg' (unless IKESA is rekeyed) */ | |||
5619 | if (osa == NULL((void *)0)) { | |||
5620 | old = sa->sa_policy; | |||
5621 | sa->sa_policy = NULL((void *)0); | |||
5622 | if (policy_lookup(env, msg, &msg->msg_proposals, | |||
5623 | NULL((void *)0), 0) != 0 || msg->msg_policy == NULL((void *)0)) { | |||
5624 | sa->sa_policy = old; | |||
5625 | log_info("%s: no proposal chosen", __func__); | |||
5626 | msg->msg_error = IKEV2_N_NO_PROPOSAL_CHOSEN14; | |||
5627 | return (-1); | |||
5628 | } | |||
5629 | /* move sa to new policy */ | |||
5630 | sa->sa_policy = msg->msg_policy; | |||
5631 | 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); | |||
5632 | 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) | |||
5633 | 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); | |||
5634 | policy_unref(env, old); | |||
5635 | policy_ref(env, sa->sa_policy); | |||
5636 | } | |||
5637 | ||||
5638 | sa_state(env, sa, IKEV2_STATE_SA_INIT2); | |||
5639 | ||||
5640 | ibuf_free(sa->sa_1stmsg); | |||
5641 | if ((sa->sa_1stmsg = ibuf_dup(msg->msg_data)) == NULL((void *)0)) { | |||
5642 | log_debug("%s: failed to copy 1st message", __func__); | |||
5643 | return (-1); | |||
5644 | } | |||
5645 | ||||
5646 | if (sa->sa_rnoncesa_kex.kex_rnonce == NULL((void *)0) && | |||
5647 | (sa->sa_rnoncesa_kex.kex_rnonce = ibuf_random(IKED_NONCE_SIZE32)) == NULL((void *)0)) { | |||
5648 | log_debug("%s: failed to get local nonce", __func__); | |||
5649 | return (-1); | |||
5650 | } | |||
5651 | ||||
5652 | if (!ibuf_length(sa->sa_inoncesa_kex.kex_inonce) && | |||
5653 | (ibuf_length(msg->msg_nonce) < IKED_NONCE_MIN16)) { | |||
5654 | log_debug("%s: failed to get peer nonce", __func__); | |||
5655 | return (-1); | |||
5656 | } | |||
5657 | sa->sa_inoncesa_kex.kex_inonce = msg->msg_nonce; | |||
5658 | msg->msg_nonce = NULL((void *)0); | |||
5659 | ||||
5660 | if (ikev2_sa_negotiate_common(env, sa, msg, msg->msg_dhgroup) != 0) | |||
5661 | return (-1); | |||
5662 | ||||
5663 | if (ikev2_sa_responder_dh(&sa->sa_kex, &sa->sa_proposals, msg, 0) < 0) | |||
5664 | return (-1); | |||
5665 | ||||
5666 | return (ikev2_sa_keys(env, sa, osa ? osa->sa_key_d : NULL((void *)0))); | |||
5667 | } | |||
5668 | ||||
5669 | int | |||
5670 | ikev2_sa_keys(struct iked *env, struct iked_sa *sa, struct ibuf *key) | |||
5671 | { | |||
5672 | struct iked_hash *prf, *integr; | |||
5673 | struct iked_cipher *encr; | |||
5674 | struct dh_group *group; | |||
5675 | struct ibuf *ninr, *dhsecret, *skeyseed, *s, *t; | |||
5676 | size_t nonceminlen, ilen, rlen, tmplen; | |||
5677 | uint64_t ispi, rspi; | |||
5678 | int ret = -1; | |||
5679 | int isaead = 0; | |||
5680 | ||||
5681 | ninr = dhsecret = skeyseed = s = t = NULL((void *)0); | |||
5682 | ||||
5683 | if ((encr = sa->sa_encr) == NULL((void *)0) || | |||
5684 | (prf = sa->sa_prf) == NULL((void *)0) || | |||
5685 | (integr = sa->sa_integr) == NULL((void *)0) || | |||
5686 | (group = sa->sa_dhgroupsa_kex.kex_dhgroup) == NULL((void *)0)) { | |||
5687 | log_info("%s: failed to get key input data", | |||
5688 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5689 | return (-1); | |||
5690 | } | |||
5691 | ||||
5692 | /* For AEADs no auth keys are required (see RFC 5282) */ | |||
5693 | isaead = !!integr->hash_isaead; | |||
5694 | ||||
5695 | if (prf->hash_fixedkey) | |||
5696 | nonceminlen = prf->hash_fixedkey; | |||
5697 | else | |||
5698 | nonceminlen = IKED_NONCE_MIN16; | |||
5699 | ||||
5700 | /* Nonces need a minimal size and should have an even length */ | |||
5701 | if (ibuf_length(sa->sa_inoncesa_kex.kex_inonce) < nonceminlen || | |||
5702 | (ibuf_length(sa->sa_inoncesa_kex.kex_inonce) % 2) != 0 || | |||
5703 | ibuf_length(sa->sa_rnoncesa_kex.kex_rnonce) < nonceminlen || | |||
5704 | (ibuf_length(sa->sa_rnoncesa_kex.kex_rnonce) % 2) != 0) { | |||
5705 | log_info("%s: invalid nonces", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5706 | return (-1); | |||
5707 | } | |||
5708 | ||||
5709 | if (prf->hash_fixedkey) { | |||
5710 | /* Half of the key bits must come from Ni, and half from Nr */ | |||
5711 | ilen = prf->hash_fixedkey / 2; | |||
5712 | rlen = prf->hash_fixedkey / 2; | |||
5713 | } else { | |||
5714 | /* Most PRF functions accept a variable-length key */ | |||
5715 | ilen = ibuf_length(sa->sa_inoncesa_kex.kex_inonce); | |||
5716 | rlen = ibuf_length(sa->sa_rnoncesa_kex.kex_rnonce); | |||
5717 | } | |||
5718 | ||||
5719 | /* | |||
5720 | * Depending on whether we're generating new keying material | |||
5721 | * or rekeying existing SA the algorithm is different. If the | |||
5722 | * "key" argument is not specified a concatenation of nonces | |||
5723 | * (Ni | Nr) is used as a PRF key, otherwise a "key" buffer | |||
5724 | * is used and PRF is performed on the concatenation of DH | |||
5725 | * exchange result and nonces (g^ir | Ni | Nr). See sections | |||
5726 | * 2.14 and 2.18 of RFC7296 for more information. | |||
5727 | */ | |||
5728 | ||||
5729 | /* | |||
5730 | * Generate g^ir | |||
5731 | */ | |||
5732 | if (dh_create_shared(group, &dhsecret, sa->sa_dhpeersa_kex.kex_dhpeer) == -1) { | |||
5733 | log_info("%s: failed to get dh secret" | |||
5734 | " group %d secret %zu exchange %zu", | |||
5735 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
5736 | group->id, ibuf_length(dhsecret), | |||
5737 | ibuf_length(sa->sa_dhpeersa_kex.kex_dhpeer)); | |||
5738 | goto done; | |||
5739 | } | |||
5740 | ||||
5741 | log_debug("%s: DHSECRET with %zu bytes", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
5742 | ibuf_size(dhsecret)); | |||
5743 | print_hexbuf(dhsecret); | |||
5744 | ||||
5745 | if (!key) { | |||
5746 | /* | |||
5747 | * Set PRF key to generate SKEYSEED = prf(Ni | Nr, g^ir) | |||
5748 | */ | |||
5749 | if ((ninr = ibuf_new(ibuf_data(sa->sa_inoncesa_kex.kex_inonce), ilen)) == NULL((void *)0) || | |||
5750 | ibuf_add(ninr, ibuf_data(sa->sa_rnoncesa_kex.kex_rnonce), rlen) != 0) { | |||
5751 | log_info("%s: failed to get nonce key buffer", | |||
5752 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5753 | goto done; | |||
5754 | } | |||
5755 | key = ninr; | |||
5756 | } else { | |||
5757 | /* | |||
5758 | * Set PRF key to generate SKEYSEED = prf(key, g^ir | Ni | Nr) | |||
5759 | */ | |||
5760 | if (ibuf_add(dhsecret, ibuf_data(sa->sa_inoncesa_kex.kex_inonce), ilen) != 0 || | |||
5761 | ibuf_add(dhsecret, ibuf_data(sa->sa_rnoncesa_kex.kex_rnonce), rlen) != 0) { | |||
5762 | log_info("%s: failed to get nonce key buffer", | |||
5763 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5764 | goto done; | |||
5765 | } | |||
5766 | } | |||
5767 | ||||
5768 | if ((hash_setkey(prf, ibuf_data(key), ibuf_size(key))) == NULL((void *)0)) { | |||
5769 | log_info("%s: failed to set prf key", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5770 | goto done; | |||
5771 | } | |||
5772 | ||||
5773 | if ((skeyseed = ibuf_new(NULL((void *)0), hash_keylength(prf))) == NULL((void *)0)) { | |||
5774 | log_info("%s: failed to get SKEYSEED buffer", | |||
5775 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5776 | goto done; | |||
5777 | } | |||
5778 | ||||
5779 | tmplen = 0; | |||
5780 | hash_init(prf); | |||
5781 | hash_update(prf, ibuf_data(dhsecret), ibuf_size(dhsecret)); | |||
5782 | hash_final(prf, ibuf_data(skeyseed), &tmplen); | |||
5783 | ||||
5784 | log_debug("%s: SKEYSEED with %zu bytes", __func__, tmplen); | |||
5785 | print_hex(ibuf_data(skeyseed), 0, tmplen); | |||
5786 | ||||
5787 | if (ibuf_setsize(skeyseed, tmplen) == -1) { | |||
5788 | log_info("%s: failed to set keymaterial length", | |||
5789 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5790 | goto done; | |||
5791 | } | |||
5792 | ||||
5793 | /* | |||
5794 | * Now generate the key material | |||
5795 | * | |||
5796 | * S = Ni | Nr | SPIi | SPIr | |||
5797 | */ | |||
5798 | ||||
5799 | /* S = Ni | Nr | SPIi | SPIr */ | |||
5800 | ilen = ibuf_length(sa->sa_inoncesa_kex.kex_inonce); | |||
5801 | rlen = ibuf_length(sa->sa_rnoncesa_kex.kex_rnonce); | |||
5802 | 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)); | |||
5803 | 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)); | |||
5804 | ||||
5805 | if ((s = ibuf_new(ibuf_data(sa->sa_inoncesa_kex.kex_inonce), ilen)) == NULL((void *)0) || | |||
5806 | ibuf_add(s, ibuf_data(sa->sa_rnoncesa_kex.kex_rnonce), rlen) != 0 || | |||
5807 | ibuf_add(s, &ispi, sizeof(ispi)) != 0 || | |||
5808 | ibuf_add(s, &rspi, sizeof(rspi)) != 0) { | |||
5809 | log_info("%s: failed to set S buffer", | |||
5810 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5811 | goto done; | |||
5812 | } | |||
5813 | ||||
5814 | log_debug("%s: S with %zu bytes", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), ibuf_size(s)); | |||
5815 | print_hexbuf(s); | |||
5816 | ||||
5817 | /* | |||
5818 | * Get the size of the key material we need and the number | |||
5819 | * of rounds we need to run the prf+ function. | |||
5820 | */ | |||
5821 | ilen = hash_length(prf) + /* SK_d */ | |||
5822 | (isaead ? 0 : hash_keylength(integr)) + /* SK_ai */ | |||
5823 | (isaead ? 0 : hash_keylength(integr)) + /* SK_ar */ | |||
5824 | cipher_keylength(encr) + /* SK_ei */ | |||
5825 | cipher_keylength(encr) + /* SK_er */ | |||
5826 | hash_keylength(prf) + /* SK_pi */ | |||
5827 | hash_keylength(prf); /* SK_pr */ | |||
5828 | ||||
5829 | if ((t = ikev2_prfplus(prf, skeyseed, s, ilen)) == NULL((void *)0)) { | |||
5830 | log_info("%s: failed to get IKE SA key material", | |||
5831 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5832 | goto done; | |||
5833 | } | |||
5834 | ||||
5835 | /* ibuf_getdata() returns a new buffer from the next read offset */ | |||
5836 | if ((sa->sa_key_d = ibuf_getdata(t, hash_length(prf))) == NULL((void *)0) || | |||
5837 | (!isaead && | |||
5838 | (sa->sa_key_iauth = ibuf_getdata(t, hash_keylength(integr))) == | |||
5839 | NULL((void *)0)) || | |||
5840 | (!isaead && | |||
5841 | (sa->sa_key_rauth = ibuf_getdata(t, hash_keylength(integr))) == | |||
5842 | NULL((void *)0)) || | |||
5843 | (sa->sa_key_iencr = ibuf_getdata(t, cipher_keylength(encr))) == | |||
5844 | NULL((void *)0) || | |||
5845 | (sa->sa_key_rencr = ibuf_getdata(t, cipher_keylength(encr))) == | |||
5846 | NULL((void *)0) || | |||
5847 | (sa->sa_key_iprf = ibuf_getdata(t, hash_length(prf))) == NULL((void *)0) || | |||
5848 | (sa->sa_key_rprf = ibuf_getdata(t, hash_length(prf))) == NULL((void *)0)) { | |||
5849 | log_debug("%s: failed to get SA keys", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
5850 | goto done; | |||
5851 | } | |||
5852 | ||||
5853 | log_debug("%s: SK_d with %zu bytes", __func__, ibuf_size(sa->sa_key_d)); | |||
5854 | print_hexbuf(sa->sa_key_d); | |||
5855 | if (!isaead) { | |||
5856 | log_debug("%s: SK_ai with %zu bytes", __func__, | |||
5857 | ibuf_size(sa->sa_key_iauth)); | |||
5858 | print_hexbuf(sa->sa_key_iauth); | |||
5859 | log_debug("%s: SK_ar with %zu bytes", __func__, | |||
5860 | ibuf_size(sa->sa_key_rauth)); | |||
5861 | print_hexbuf(sa->sa_key_rauth); | |||
5862 | } | |||
5863 | log_debug("%s: SK_ei with %zu bytes", __func__, | |||
5864 | ibuf_size(sa->sa_key_iencr)); | |||
5865 | print_hexbuf(sa->sa_key_iencr); | |||
5866 | log_debug("%s: SK_er with %zu bytes", __func__, | |||
5867 | ibuf_size(sa->sa_key_rencr)); | |||
5868 | print_hexbuf(sa->sa_key_rencr); | |||
5869 | log_debug("%s: SK_pi with %zu bytes", __func__, | |||
5870 | ibuf_size(sa->sa_key_iprf)); | |||
5871 | print_hexbuf(sa->sa_key_iprf); | |||
5872 | log_debug("%s: SK_pr with %zu bytes", __func__, | |||
5873 | ibuf_size(sa->sa_key_rprf)); | |||
5874 | print_hexbuf(sa->sa_key_rprf); | |||
5875 | ||||
5876 | ret = 0; | |||
5877 | ||||
5878 | done: | |||
5879 | ibuf_free(ninr); | |||
5880 | ibuf_free(dhsecret); | |||
5881 | ibuf_free(skeyseed); | |||
5882 | ibuf_free(s); | |||
5883 | ibuf_free(t); | |||
5884 | ||||
5885 | return (ret); | |||
5886 | } | |||
5887 | ||||
5888 | void | |||
5889 | ikev2_sa_cleanup_dh(struct iked_sa *sa) | |||
5890 | { | |||
5891 | ibuf_free(sa->sa_dhiexchangesa_kex.kex_dhiexchange); | |||
5892 | ibuf_free(sa->sa_dhrexchangesa_kex.kex_dhrexchange); | |||
5893 | group_free(sa->sa_dhgroupsa_kex.kex_dhgroup); | |||
5894 | sa->sa_dhiexchangesa_kex.kex_dhiexchange = NULL((void *)0); | |||
5895 | sa->sa_dhrexchangesa_kex.kex_dhrexchange = NULL((void *)0); | |||
5896 | sa->sa_dhgroupsa_kex.kex_dhgroup = NULL((void *)0); | |||
5897 | } | |||
5898 | ||||
5899 | struct ibuf * | |||
5900 | ikev2_prfplus(struct iked_hash *prf, struct ibuf *key, struct ibuf *seed, | |||
5901 | size_t keymatlen) | |||
5902 | { | |||
5903 | struct ibuf *t = NULL((void *)0), *t1 = NULL((void *)0), *t2 = NULL((void *)0); | |||
5904 | size_t rlen, i, hashlen = 0; | |||
5905 | uint8_t pad = 0; | |||
5906 | ||||
5907 | /* | |||
5908 | * prf+ (K, S) = T1 | T2 | T3 | T4 | ... | |||
5909 | * | |||
5910 | * T1 = prf (K, S | 0x01) | |||
5911 | * T2 = prf (K, T1 | S | 0x02) | |||
5912 | * T3 = prf (K, T2 | S | 0x03) | |||
5913 | * T4 = prf (K, T3 | S | 0x04) | |||
5914 | */ | |||
5915 | ||||
5916 | if ((hash_setkey(prf, ibuf_data(key), ibuf_size(key))) == NULL((void *)0)) { | |||
5917 | log_debug("%s: failed to set prf+ key", __func__); | |||
5918 | goto fail; | |||
5919 | } | |||
5920 | ||||
5921 | if ((t = ibuf_new(NULL((void *)0), 0)) == NULL((void *)0)) { | |||
5922 | log_debug("%s: failed to get T buffer", __func__); | |||
5923 | goto fail; | |||
5924 | } | |||
5925 | ||||
5926 | rlen = roundup(keymatlen, hash_length(prf))((((keymatlen)+((hash_length(prf))-1))/(hash_length(prf)))*(hash_length (prf))) / hash_length(prf); | |||
5927 | if (rlen > 255) | |||
5928 | fatalx("ikev2_prfplus: key material too large"); | |||
5929 | ||||
5930 | for (i = 0; i < rlen; i++) { | |||
5931 | if (t1 != NULL((void *)0)) { | |||
5932 | t2 = ibuf_new(ibuf_data(t1), ibuf_size(t1)); | |||
5933 | ibuf_free(t1); | |||
5934 | } else | |||
5935 | t2 = ibuf_new(NULL((void *)0), 0); | |||
5936 | t1 = ibuf_new(NULL((void *)0), hash_keylength(prf)); | |||
5937 | ||||
5938 | ibuf_add_buf(t2, seed); | |||
5939 | pad = i + 1; | |||
5940 | ibuf_add(t2, &pad, 1); | |||
5941 | ||||
5942 | hash_init(prf); | |||
5943 | hash_update(prf, ibuf_data(t2), ibuf_size(t2)); | |||
5944 | hash_final(prf, ibuf_data(t1), &hashlen); | |||
5945 | ||||
5946 | if (hashlen != hash_length(prf)) | |||
5947 | fatalx("ikev2_prfplus: hash length mismatch"); | |||
5948 | ||||
5949 | ibuf_free(t2); | |||
5950 | ibuf_add_buf(t, t1); | |||
5951 | ||||
5952 | log_debug("%s: T%d with %zu bytes", __func__, | |||
5953 | pad, ibuf_size(t1)); | |||
5954 | print_hexbuf(t1); | |||
5955 | } | |||
5956 | ||||
5957 | log_debug("%s: Tn with %zu bytes", __func__, ibuf_size(t)); | |||
5958 | print_hexbuf(t); | |||
5959 | ||||
5960 | ibuf_free(t1); | |||
5961 | ||||
5962 | return (t); | |||
5963 | ||||
5964 | fail: | |||
5965 | ibuf_free(t1); | |||
5966 | ibuf_free(t); | |||
5967 | ||||
5968 | return (NULL((void *)0)); | |||
5969 | } | |||
5970 | ||||
5971 | int | |||
5972 | ikev2_sa_tag(struct iked_sa *sa, struct iked_id *id) | |||
5973 | { | |||
5974 | char *format, *domain = NULL((void *)0), *idrepl = NULL((void *)0); | |||
5975 | char idstr[IKED_ID_SIZE1024]; | |||
5976 | int ret = -1; | |||
5977 | size_t len; | |||
5978 | ||||
5979 | free(sa->sa_tag); | |||
5980 | sa->sa_tag = NULL((void *)0); | |||
5981 | format = sa->sa_policy->pol_tag; | |||
5982 | ||||
5983 | len = IKED_TAG_SIZE64; | |||
5984 | if ((sa->sa_tag = calloc(1, len)) == NULL((void *)0)) { | |||
5985 | log_debug("%s: calloc", __func__); | |||
5986 | goto fail; | |||
5987 | } | |||
5988 | if (strlcpy(sa->sa_tag, format, len) >= len) { | |||
5989 | log_debug("%s: tag too long", __func__); | |||
5990 | goto fail; | |||
5991 | } | |||
5992 | ||||
5993 | if (ikev2_print_id(id, idstr, sizeof(idstr)) == -1) { | |||
5994 | log_debug("%s: invalid id", __func__); | |||
5995 | goto fail; | |||
5996 | } | |||
5997 | ||||
5998 | /* ASN.1 DER IDs are too long, use the CN part instead */ | |||
5999 | if ((id->id_type == IKEV2_ID_ASN1_DN9) && | |||
6000 | (idrepl = strstr(idstr, "CN=")) != NULL((void *)0)) { | |||
6001 | domain = strstr(idrepl, "emailAddress="); | |||
6002 | idrepl[strcspn(idrepl, "/")] = '\0'; | |||
6003 | } else | |||
6004 | idrepl = idstr; | |||
6005 | ||||
6006 | if (strstr(format, "$id") != NULL((void *)0)) { | |||
6007 | if (expand_string(sa->sa_tag, len, "$id", idrepl) != 0) { | |||
6008 | log_debug("%s: failed to expand tag", __func__); | |||
6009 | goto fail; | |||
6010 | } | |||
6011 | } | |||
6012 | ||||
6013 | if (strstr(format, "$eapid") != NULL((void *)0) && sa->sa_eapid != NULL((void *)0)) { | |||
6014 | if (expand_string(sa->sa_tag, len, "$eapid", | |||
6015 | sa->sa_eapid) != 0) { | |||
6016 | log_debug("%s: failed to expand tag", __func__); | |||
6017 | goto fail; | |||
6018 | } | |||
6019 | } | |||
6020 | ||||
6021 | if (strstr(format, "$name") != NULL((void *)0)) { | |||
6022 | if (expand_string(sa->sa_tag, len, "$name", | |||
6023 | sa->sa_policy->pol_name) != 0) { | |||
6024 | log_debug("%s: failed to expand tag", __func__); | |||
6025 | goto fail; | |||
6026 | } | |||
6027 | } | |||
6028 | ||||
6029 | if (strstr(format, "$domain") != NULL((void *)0)) { | |||
6030 | if (id->id_type == IKEV2_ID_FQDN2) | |||
6031 | domain = strchr(idrepl, '.'); | |||
6032 | else if (id->id_type == IKEV2_ID_UFQDN3) | |||
6033 | domain = strchr(idrepl, '@'); | |||
6034 | else if (*idstr == '/' && domain != NULL((void *)0)) | |||
6035 | domain = strchr(domain, '@'); | |||
6036 | else | |||
6037 | domain = NULL((void *)0); | |||
6038 | if (domain == NULL((void *)0) || strlen(domain) < 2) { | |||
6039 | log_debug("%s: no valid domain in ID %s", | |||
6040 | __func__, idstr); | |||
6041 | goto fail; | |||
6042 | } | |||
6043 | domain++; | |||
6044 | if (expand_string(sa->sa_tag, len, "$domain", domain) != 0) { | |||
6045 | log_debug("%s: failed to expand tag", __func__); | |||
6046 | goto fail; | |||
6047 | } | |||
6048 | } | |||
6049 | ||||
6050 | log_debug("%s: %s (%zu)", __func__, sa->sa_tag, strlen(sa->sa_tag)); | |||
6051 | ||||
6052 | ret = 0; | |||
6053 | fail: | |||
6054 | if (ret != 0) { | |||
6055 | free(sa->sa_tag); | |||
6056 | sa->sa_tag = NULL((void *)0); | |||
6057 | } | |||
6058 | ||||
6059 | return (ret); | |||
6060 | } | |||
6061 | ||||
6062 | int | |||
6063 | ikev2_childsa_delete_proposed(struct iked *env, struct iked_sa *sa, | |||
6064 | struct iked_proposals *proposals) | |||
6065 | { | |||
6066 | struct ibuf *buf = NULL((void *)0); | |||
6067 | struct iked_proposal *prop; | |||
6068 | struct ikev2_delete *del; | |||
6069 | uint32_t spi32; | |||
6070 | uint8_t protoid = 0; | |||
6071 | int ret = -1, count; | |||
6072 | ||||
6073 | if (!sa_stateok(sa, IKEV2_STATE_VALID7)) | |||
6074 | return (-1); | |||
6075 | ||||
6076 | count = 0; | |||
6077 | TAILQ_FOREACH(prop, proposals, prop_entry)for((prop) = ((proposals)->tqh_first); (prop) != ((void *) 0); (prop) = ((prop)->prop_entry.tqe_next)) { | |||
6078 | if (ikev2_valid_proposal(prop, NULL((void *)0), NULL((void *)0), NULL((void *)0)) != 0) | |||
6079 | continue; | |||
6080 | protoid = prop->prop_protoid; | |||
6081 | count++; | |||
6082 | } | |||
6083 | if (count == 0) | |||
6084 | return (0); | |||
6085 | if ((buf = ibuf_static()) == NULL((void *)0)) | |||
6086 | return (-1); | |||
6087 | if ((del = ibuf_reserve(buf, sizeof(*del))) == NULL((void *)0)) | |||
6088 | goto done; | |||
6089 | /* XXX we assume all have the same protoid */ | |||
6090 | del->del_protoid = protoid; | |||
6091 | del->del_spisize = 4; | |||
6092 | 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)); | |||
6093 | ||||
6094 | TAILQ_FOREACH(prop, proposals, prop_entry)for((prop) = ((proposals)->tqh_first); (prop) != ((void *) 0); (prop) = ((prop)->prop_entry.tqe_next)) { | |||
6095 | if (ikev2_valid_proposal(prop, NULL((void *)0), NULL((void *)0), NULL((void *)0)) != 0) | |||
6096 | continue; | |||
6097 | 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)); | |||
6098 | if (ibuf_add(buf, &spi32, sizeof(spi32))) | |||
6099 | goto done; | |||
6100 | } | |||
6101 | ||||
6102 | if (ikev2_send_ike_e(env, sa, buf, IKEV2_PAYLOAD_DELETE42, | |||
6103 | IKEV2_EXCHANGE_INFORMATIONAL37, 0) == -1) | |||
6104 | goto done; | |||
6105 | sa->sa_stateflags |= IKED_REQ_INF0x0100; | |||
6106 | ret = 0; | |||
6107 | done: | |||
6108 | ibuf_free(buf); | |||
6109 | ||||
6110 | return (ret); | |||
6111 | } | |||
6112 | ||||
6113 | int | |||
6114 | ikev2_childsa_negotiate(struct iked *env, struct iked_sa *sa, | |||
6115 | struct iked_kex *kex, struct iked_proposals *proposals, int initiator, | |||
6116 | int pfs) | |||
6117 | { | |||
6118 | struct iked_proposal *prop; | |||
6119 | struct iked_transform *xform, *encrxf = NULL((void *)0), *integrxf = NULL((void *)0); | |||
6120 | struct iked_childsa *csa = NULL((void *)0), *csb = NULL((void *)0); | |||
6121 | struct iked_childsa *csa2 = NULL((void *)0), *csb2 = NULL((void *)0); | |||
6122 | struct iked_flow *flow, *saflow, *flowa, *flowb; | |||
6123 | struct iked_ipcomp *ic; | |||
6124 | struct ibuf *keymat = NULL((void *)0), *seed = NULL((void *)0), *dhsecret = NULL((void *)0); | |||
6125 | struct dh_group *group = NULL((void *)0); | |||
6126 | uint32_t spi = 0; | |||
6127 | unsigned int i; | |||
6128 | size_t ilen = 0; | |||
6129 | int esn, skip, ret = -1; | |||
6130 | ||||
6131 | if (!sa_stateok(sa, IKEV2_STATE_VALID7)) | |||
6132 | return (-1); | |||
6133 | ||||
6134 | if (ikev2_sa_tag(sa, IKESA_DSTID(sa)((sa)->sa_hdr.sh_initiator ? &(sa)->sa_rid : &( sa)->sa_iid)) == -1) | |||
6135 | return (-1); | |||
6136 | ||||
6137 | ic = initiator ? &sa->sa_ipcompi : &sa->sa_ipcompr; | |||
6138 | if (ic->ic_transform == 0 || ic->ic_cpi_out == 0 || | |||
6139 | (initiator && ic->ic_cpi_in == 0)) | |||
6140 | ic = NULL((void *)0); | |||
6141 | ||||
6142 | /* reset state */ | |||
6143 | sa->sa_used_transport_mode = 0; | |||
6144 | ||||
6145 | /* We need to determine the key material length first */ | |||
6146 | TAILQ_FOREACH(prop, proposals, prop_entry)for((prop) = ((proposals)->tqh_first); (prop) != ((void *) 0); (prop) = ((prop)->prop_entry.tqe_next)) { | |||
6147 | if (prop->prop_protoid == IKEV2_SAPROTO_IKE1) | |||
6148 | continue; | |||
6149 | log_debug("%s: proposal %d", __func__, prop->prop_id); | |||
6150 | for (i = 0; i < prop->prop_nxforms; i++) { | |||
6151 | xform = prop->prop_xforms + i; | |||
6152 | xform->xform_keylength = | |||
6153 | keylength_xf(prop->prop_protoid, | |||
6154 | xform->xform_type, xform->xform_id); | |||
6155 | ||||
6156 | switch (xform->xform_type) { | |||
6157 | case IKEV2_XFORMTYPE_ENCR1: | |||
6158 | case IKEV2_XFORMTYPE_INTEGR3: | |||
6159 | if (xform->xform_length) | |||
6160 | xform->xform_keylength = | |||
6161 | xform->xform_length; | |||
6162 | xform->xform_keylength += | |||
6163 | noncelength_xf(xform->xform_type, | |||
6164 | xform->xform_id); | |||
6165 | ilen += xform->xform_keylength / 8; | |||
6166 | break; | |||
6167 | } | |||
6168 | } | |||
6169 | } | |||
6170 | ||||
6171 | /* double key material length for inbound/outbound */ | |||
6172 | ilen *= 2; | |||
6173 | ||||
6174 | log_debug("%s: key material length %zu", __func__, ilen); | |||
6175 | ||||
6176 | if ((seed = ibuf_new(NULL((void *)0), 0)) == NULL((void *)0)) { | |||
6177 | log_debug("%s: failed to setup IKE SA key material", __func__); | |||
6178 | goto done; | |||
6179 | } | |||
6180 | if (pfs) { | |||
6181 | log_debug("%s: using PFS", __func__); | |||
6182 | if (kex->kex_dhpeer == NULL((void *)0) || | |||
6183 | ibuf_size(kex->kex_dhpeer) == 0 || | |||
6184 | (group = kex->kex_dhgroup) == NULL((void *)0)) { | |||
6185 | log_debug("%s: no dh group for pfs", __func__); | |||
6186 | goto done; | |||
6187 | } | |||
6188 | if (dh_create_shared(group, &dhsecret, kex->kex_dhpeer) == -1) { | |||
6189 | log_debug("%s: failed to get dh secret" | |||
6190 | " group %d secret %zu exchange %zu", | |||
6191 | __func__, group->id, ibuf_length(dhsecret), | |||
6192 | ibuf_length(kex->kex_dhpeer)); | |||
6193 | goto done; | |||
6194 | } | |||
6195 | if (ibuf_add_buf(seed, dhsecret) != 0) { | |||
6196 | log_debug("%s: failed to set dh secret", __func__); | |||
6197 | goto done; | |||
6198 | } | |||
6199 | } | |||
6200 | if (ibuf_add_buf(seed, kex->kex_inonce) != 0 || | |||
6201 | ibuf_add_buf(seed, kex->kex_rnonce) != 0 || | |||
6202 | (keymat = ikev2_prfplus(sa->sa_prf, | |||
6203 | sa->sa_key_d, seed, ilen)) == NULL((void *)0)) { | |||
6204 | log_debug("%s: failed to get IKE SA key material", __func__); | |||
6205 | goto done; | |||
6206 | } | |||
6207 | ||||
6208 | /* Create the new flows */ | |||
6209 | TAILQ_FOREACH(prop, proposals, prop_entry)for((prop) = ((proposals)->tqh_first); (prop) != ((void *) 0); (prop) = ((prop)->prop_entry.tqe_next)) { | |||
6210 | if (ikev2_valid_proposal(prop, NULL((void *)0), NULL((void *)0), NULL((void *)0)) != 0) | |||
6211 | continue; | |||
6212 | ||||
6213 | 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)) { | |||
6214 | ||||
6215 | if ((flowa = calloc(1, sizeof(*flowa))) == NULL((void *)0)) { | |||
6216 | log_debug("%s: failed to get flow", __func__); | |||
6217 | goto done; | |||
6218 | } | |||
6219 | ||||
6220 | memcpy(flowa, flow, sizeof(*flow)); | |||
6221 | flowa->flow_dir = IPSP_DIRECTION_OUT0x2; | |||
6222 | flowa->flow_saproto = ic ? IKEV2_SAPROTO_IPCOMP204 : | |||
6223 | prop->prop_protoid; | |||
6224 | flowa->flow_rdomain = sa->sa_policy->pol_rdomain; | |||
6225 | flowa->flow_local = &sa->sa_local; | |||
6226 | flowa->flow_peer = &sa->sa_peer; | |||
6227 | flowa->flow_ikesa = sa; | |||
6228 | if (ikev2_cp_fixflow(sa, flow, flowa) == -1) { | |||
6229 | flow_free(flowa); | |||
6230 | continue; | |||
6231 | } | |||
6232 | ||||
6233 | skip = 0; | |||
6234 | TAILQ_FOREACH(saflow, &sa->sa_flows, flow_entry)for((saflow) = ((&sa->sa_flows)->tqh_first); (saflow ) != ((void *)0); (saflow) = ((saflow)->flow_entry.tqe_next )) { | |||
6235 | if (flow_equal(saflow, flowa)) { | |||
6236 | skip = 1; | |||
6237 | break; | |||
6238 | } | |||
6239 | } | |||
6240 | if (skip) { | |||
6241 | flow_free(flowa); | |||
6242 | continue; | |||
6243 | } | |||
6244 | ||||
6245 | if ((flowb = calloc(1, sizeof(*flowb))) == NULL((void *)0)) { | |||
6246 | log_debug("%s: failed to get flow", __func__); | |||
6247 | flow_free(flowa); | |||
6248 | goto done; | |||
6249 | } | |||
6250 | ||||
6251 | memcpy(flowb, flowa, sizeof(*flow)); | |||
6252 | ||||
6253 | flowb->flow_dir = IPSP_DIRECTION_IN0x1; | |||
6254 | memcpy(&flowb->flow_src, &flow->flow_dst, | |||
6255 | sizeof(flow->flow_dst)); | |||
6256 | memcpy(&flowb->flow_dst, &flow->flow_src, | |||
6257 | sizeof(flow->flow_src)); | |||
6258 | if (ikev2_cp_fixflow(sa, flow, flowb) == -1) { | |||
6259 | flow_free(flowa); | |||
6260 | flow_free(flowb); | |||
6261 | continue; | |||
6262 | } | |||
6263 | ||||
6264 | 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); | |||
6265 | 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); | |||
6266 | } | |||
6267 | } | |||
6268 | ||||
6269 | /* create the CHILD SAs using the key material */ | |||
6270 | TAILQ_FOREACH(prop, proposals, prop_entry)for((prop) = ((proposals)->tqh_first); (prop) != ((void *) 0); (prop) = ((prop)->prop_entry.tqe_next)) { | |||
6271 | if (ikev2_valid_proposal(prop, &encrxf, &integrxf, &esn) != 0) | |||
6272 | continue; | |||
6273 | ||||
6274 | spi = 0; | |||
6275 | ||||
6276 | if ((csa = calloc(1, sizeof(*csa))) == NULL((void *)0)) { | |||
6277 | log_debug("%s: failed to get CHILD SA", __func__); | |||
6278 | goto done; | |||
6279 | } | |||
6280 | ||||
6281 | csa->csa_saproto = prop->prop_protoid; | |||
6282 | csa->csa_ikesa = sa; | |||
6283 | csa->csa_spi.spi_protoid = prop->prop_protoid; | |||
6284 | csa->csa_esn = esn; | |||
6285 | csa->csa_transport = sa->sa_use_transport_mode; | |||
6286 | sa->sa_used_transport_mode = sa->sa_use_transport_mode; | |||
6287 | ||||
6288 | if (pfs && group) | |||
6289 | csa->csa_pfsgrpid = group->id; | |||
6290 | ||||
6291 | /* Set up responder's SPIs */ | |||
6292 | if (initiator) { | |||
6293 | csa->csa_dir = IPSP_DIRECTION_OUT0x2; | |||
6294 | csa->csa_local = &sa->sa_local; | |||
6295 | csa->csa_peer = &sa->sa_peer; | |||
6296 | csa->csa_peerspi = prop->prop_localspi.spi; | |||
6297 | csa->csa_spi.spi = prop->prop_peerspi.spi; | |||
6298 | csa->csa_spi.spi_size = prop->prop_peerspi.spi_size; | |||
6299 | } else { | |||
6300 | csa->csa_dir = IPSP_DIRECTION_IN0x1; | |||
6301 | csa->csa_local = &sa->sa_peer; | |||
6302 | csa->csa_peer = &sa->sa_local; | |||
6303 | ||||
6304 | if ((ret = pfkey_sa_init(env, csa, | |||
6305 | &spi)) != 0) | |||
6306 | goto done; | |||
6307 | csa->csa_allocated = 1; | |||
6308 | ||||
6309 | csa->csa_peerspi = prop->prop_peerspi.spi; | |||
6310 | csa->csa_spi.spi = prop->prop_localspi.spi = spi; | |||
6311 | csa->csa_spi.spi_size = 4; | |||
6312 | } | |||
6313 | ||||
6314 | if (encrxf && (csa->csa_encrkey = ibuf_getdata(keymat, | |||
6315 | encrxf->xform_keylength / 8)) == NULL((void *)0)) { | |||
6316 | log_debug("%s: failed to get CHILD SA encryption key", | |||
6317 | __func__); | |||
6318 | goto done; | |||
6319 | } | |||
6320 | if (integrxf && (csa->csa_integrkey = ibuf_getdata(keymat, | |||
6321 | integrxf->xform_keylength / 8)) == NULL((void *)0)) { | |||
6322 | log_debug("%s: failed to get CHILD SA integrity key", | |||
6323 | __func__); | |||
6324 | goto done; | |||
6325 | } | |||
6326 | if (encrxf) | |||
6327 | csa->csa_encrid = encrxf->xform_id; | |||
6328 | if (integrxf) | |||
6329 | csa->csa_integrid = integrxf->xform_id; | |||
6330 | ||||
6331 | if ((csb = calloc(1, sizeof(*csb))) == NULL((void *)0)) { | |||
6332 | log_debug("%s: failed to get CHILD SA", __func__); | |||
6333 | goto done; | |||
6334 | } | |||
6335 | ||||
6336 | memcpy(csb, csa, sizeof(*csb)); | |||
6337 | ||||
6338 | /* Set up initiator's SPIs */ | |||
6339 | csb->csa_spi.spi = csa->csa_peerspi; | |||
6340 | csb->csa_peerspi = csa->csa_spi.spi; | |||
6341 | csb->csa_allocated = csa->csa_allocated ? 0 : 1; | |||
6342 | csb->csa_dir = csa->csa_dir == IPSP_DIRECTION_IN0x1 ? | |||
6343 | IPSP_DIRECTION_OUT0x2 : IPSP_DIRECTION_IN0x1; | |||
6344 | csb->csa_local = csa->csa_peer; | |||
6345 | csb->csa_peer = csa->csa_local; | |||
6346 | ||||
6347 | if (encrxf && (csb->csa_encrkey = ibuf_getdata(keymat, | |||
6348 | encrxf->xform_keylength / 8)) == NULL((void *)0)) { | |||
6349 | log_debug("%s: failed to get CHILD SA encryption key", | |||
6350 | __func__); | |||
6351 | goto done; | |||
6352 | } | |||
6353 | if (integrxf && (csb->csa_integrkey = ibuf_getdata(keymat, | |||
6354 | integrxf->xform_keylength / 8)) == NULL((void *)0)) { | |||
6355 | log_debug("%s: failed to get CHILD SA integrity key", | |||
6356 | __func__); | |||
6357 | goto done; | |||
6358 | } | |||
6359 | ||||
6360 | if (ic && prop->prop_protoid == IKEV2_SAPROTO_ESP3) { | |||
6361 | /* add IPCOMP SAs */ | |||
6362 | if ((csa2 = calloc(1, sizeof(*csa2))) == NULL((void *)0)) { | |||
6363 | log_debug("%s: failed to get CHILD SA", __func__); | |||
6364 | goto done; | |||
6365 | } | |||
6366 | if ((csb2 = calloc(1, sizeof(*csb2))) == NULL((void *)0)) { | |||
6367 | log_debug("%s: failed to get CHILD SA", __func__); | |||
6368 | goto done; | |||
6369 | } | |||
6370 | ||||
6371 | csa2->csa_saproto = IKEV2_SAPROTO_IPCOMP204; | |||
6372 | csa2->csa_ikesa = csa->csa_ikesa; | |||
6373 | csa2->csa_dir = csa->csa_dir; | |||
6374 | csa2->csa_local = csa->csa_local; | |||
6375 | csa2->csa_peer = csa->csa_peer; | |||
6376 | if (initiator) { | |||
6377 | csa2->csa_spi.spi = ic->ic_cpi_out; | |||
6378 | csa2->csa_peerspi = ic->ic_cpi_in; | |||
6379 | csa2->csa_allocated = 0; | |||
6380 | /* make sure IPCOMP CPIs are not reused */ | |||
6381 | ic->ic_transform = 0; | |||
6382 | ic->ic_cpi_in = ic->ic_cpi_out = 0; | |||
6383 | } else { | |||
6384 | if ((ret = pfkey_sa_init(env, csa2, | |||
6385 | &spi)) != 0) | |||
6386 | goto done; | |||
6387 | ic->ic_cpi_in = spi; | |||
6388 | csa2->csa_spi.spi = ic->ic_cpi_in; | |||
6389 | csa2->csa_peerspi = ic->ic_cpi_out; | |||
6390 | csa2->csa_allocated = 1; | |||
6391 | } | |||
6392 | csa2->csa_spi.spi_size = 2; | |||
6393 | ||||
6394 | memcpy(csb2, csa2, sizeof(*csb2)); | |||
6395 | csb2->csa_spi.spi = csa2->csa_peerspi; | |||
6396 | csb2->csa_peerspi = csa2->csa_spi.spi; | |||
6397 | csb2->csa_allocated = csa2->csa_allocated ? 0 : 1; | |||
6398 | csb2->csa_dir = csa2->csa_dir == IPSP_DIRECTION_IN0x1 ? | |||
6399 | IPSP_DIRECTION_OUT0x2 : IPSP_DIRECTION_IN0x1; | |||
6400 | csb2->csa_local = csa2->csa_peer; | |||
6401 | csb2->csa_peer = csa2->csa_local; | |||
6402 | ||||
6403 | /* link IPComp and ESP SAs, switch ESP to transport */ | |||
6404 | csa->csa_transport = 1; | |||
6405 | csa->csa_bundled = csa2; | |||
6406 | csa2->csa_bundled = csa; | |||
6407 | csb->csa_transport = 1; | |||
6408 | csb->csa_bundled = csb2; | |||
6409 | csb2->csa_bundled = csb; | |||
6410 | csa2 = NULL((void *)0); | |||
6411 | csb2 = NULL((void *)0); | |||
6412 | ||||
6413 | ic = NULL((void *)0); | |||
6414 | } | |||
6415 | ||||
6416 | 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); | |||
6417 | 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); | |||
6418 | ikestat_add(env, ikes_csa_created, 2)do { env->sc_stats.ikes_csa_created += (2); } while(0); | |||
6419 | ||||
6420 | csa->csa_peersa = csb; | |||
6421 | csb->csa_peersa = csa; | |||
6422 | csa = NULL((void *)0); | |||
6423 | csb = NULL((void *)0); | |||
6424 | } | |||
6425 | ||||
6426 | ret = 0; | |||
6427 | done: | |||
6428 | sa->sa_use_transport_mode = 0; /* reset state after use */ | |||
6429 | ibuf_free(dhsecret); | |||
6430 | ibuf_free(keymat); | |||
6431 | ibuf_free(seed); | |||
6432 | childsa_free(csa); | |||
6433 | childsa_free(csb); | |||
6434 | childsa_free(csa2); | |||
6435 | childsa_free(csb2); | |||
6436 | ||||
6437 | return (ret); | |||
6438 | } | |||
6439 | ||||
6440 | int | |||
6441 | ikev2_childsa_enable(struct iked *env, struct iked_sa *sa) | |||
6442 | { | |||
6443 | struct iked_childsa *csa, *ocsa, *ipcomp; | |||
6444 | struct iked_flow *flow, *oflow; | |||
6445 | int peer_changed, reload; | |||
6446 | FILE *spif, *flowf; | |||
6447 | char *spibuf = NULL((void *)0), *flowbuf = NULL((void *)0); | |||
6448 | char prenat_mask[10]; | |||
6449 | uint16_t encrid = 0, integrid = 0, groupid = 0; | |||
6450 | size_t encrlen = 0, integrlen = 0, spisz, flowsz; | |||
6451 | int esn = 0; | |||
6452 | int ret = -1; | |||
6453 | ||||
6454 | spif = open_memstream(&spibuf, &spisz); | |||
6455 | if (spif == NULL((void *)0)) { | |||
6456 | log_warn("%s", __func__); | |||
6457 | return (ret); | |||
6458 | } | |||
6459 | flowf = open_memstream(&flowbuf, &flowsz); | |||
6460 | if (flowf == NULL((void *)0)) { | |||
6461 | log_warn("%s", __func__); | |||
6462 | fclose(spif); | |||
6463 | return (ret); | |||
6464 | } | |||
6465 | ||||
6466 | TAILQ_FOREACH(csa, &sa->sa_childsas, csa_entry)for((csa) = ((&sa->sa_childsas)->tqh_first); (csa) != ((void *)0); (csa) = ((csa)->csa_entry.tqe_next)) { | |||
6467 | if (csa->csa_rekey || csa->csa_loaded) | |||
6468 | continue; | |||
6469 | ||||
6470 | ipcomp = csa->csa_bundled; | |||
6471 | if (ipcomp && ipcomp->csa_loaded) { | |||
6472 | log_info("%s: IPCOMP SA for CHILD SA spi %s" | |||
6473 | " already loaded", __func__, | |||
6474 | print_spi(csa->csa_spi.spi, csa->csa_spi.spi_size)); | |||
6475 | continue; | |||
6476 | } | |||
6477 | ||||
6478 | if (pfkey_sa_add(env, csa, NULL((void *)0)) != 0) { | |||
6479 | log_debug("%s: failed to load CHILD SA spi %s", | |||
6480 | __func__, print_spi(csa->csa_spi.spi, | |||
6481 | csa->csa_spi.spi_size)); | |||
6482 | goto done; | |||
6483 | } | |||
6484 | if (ipcomp) { | |||
6485 | if (pfkey_sa_add(env, ipcomp, csa) != 0) { | |||
6486 | log_debug("%s: failed to load IPCOMP spi %s", | |||
6487 | __func__, print_spi(ipcomp->csa_spi.spi, | |||
6488 | ipcomp->csa_spi.spi_size)); | |||
6489 | ipcomp = NULL((void *)0); | |||
6490 | } | |||
6491 | } | |||
6492 | ||||
6493 | if ((ocsa = RB_FIND(iked_activesas, &env->sc_activesas, csa)iked_activesas_RB_FIND(&env->sc_activesas, csa)) | |||
6494 | != NULL((void *)0)) { | |||
6495 | log_debug("%s: replaced CHILD SA %p with %p spi %s", | |||
6496 | __func__, ocsa, csa, print_spi(ocsa->csa_spi.spi, | |||
6497 | ocsa->csa_spi.spi_size)); | |||
6498 | ocsa->csa_loaded = 0; | |||
6499 | ocsa->csa_rekey = 1; /* prevent re-loading */ | |||
6500 | RB_REMOVE(iked_activesas, &env->sc_activesas, ocsa)iked_activesas_RB_REMOVE(&env->sc_activesas, ocsa); | |||
6501 | } | |||
6502 | ||||
6503 | RB_INSERT(iked_activesas, &env->sc_activesas, csa)iked_activesas_RB_INSERT(&env->sc_activesas, csa); | |||
6504 | ||||
6505 | log_debug("%s: loaded CHILD SA spi %s", __func__, | |||
6506 | print_spi(csa->csa_spi.spi, csa->csa_spi.spi_size)); | |||
6507 | ||||
6508 | /* append SPI to log buffer */ | |||
6509 | if (ftello(spif) > 0) | |||
6510 | fputs(", ", spif); | |||
6511 | fputs(print_spi(csa->csa_spi.spi, csa->csa_spi.spi_size), spif); | |||
6512 | if (ipcomp) | |||
6513 | fprintf(spif, "(%s)", print_spi(ipcomp->csa_spi.spi, | |||
6514 | ipcomp->csa_spi.spi_size)); | |||
6515 | if (!encrid) { | |||
6516 | encrid = csa->csa_encrid; | |||
6517 | encrlen = ibuf_length(csa->csa_encrkey); | |||
6518 | switch (encrid) { | |||
6519 | case IKEV2_XFORMENCR_AES_GCM_1620: | |||
6520 | case IKEV2_XFORMENCR_AES_GCM_1219: | |||
6521 | encrlen -= 4; | |||
6522 | break; | |||
6523 | default: | |||
6524 | if (!csa->csa_integrid) | |||
6525 | break; | |||
6526 | integrid = csa->csa_integrid; | |||
6527 | integrlen = ibuf_length(csa->csa_integrkey); | |||
6528 | } | |||
6529 | groupid = csa->csa_pfsgrpid; | |||
6530 | esn = csa->csa_esn; | |||
6531 | } | |||
6532 | } | |||
6533 | ||||
6534 | peer_changed = (memcmp(&sa->sa_peer_loaded, &sa->sa_peer, | |||
6535 | sizeof(sa->sa_peer_loaded)) != 0); | |||
6536 | ||||
6537 | if (!(sa->sa_policy->pol_flags & IKED_POLICY_ROUTING0x80)) { | |||
6538 | TAILQ_FOREACH(flow, &sa->sa_flows, flow_entry)for((flow) = ((&sa->sa_flows)->tqh_first); (flow) != ((void *)0); (flow) = ((flow)->flow_entry.tqe_next)) { | |||
6539 | /* re-load the flow if the peer for the flow has changed */ | |||
6540 | reload = 0; | |||
6541 | if (flow->flow_loaded) { | |||
6542 | if (!peer_changed) { | |||
6543 | log_debug("%s: flow already loaded %p", | |||
6544 | __func__, flow); | |||
6545 | continue; | |||
6546 | } | |||
6547 | RB_REMOVE(iked_flows, &env->sc_activeflows, flow)iked_flows_RB_REMOVE(&env->sc_activeflows, flow); | |||
6548 | (void)pfkey_flow_delete(env, flow); | |||
6549 | flow->flow_loaded = 0; /* we did RB_REMOVE */ | |||
6550 | reload = 1; | |||
6551 | } | |||
6552 | ||||
6553 | if (pfkey_flow_add(env, flow) != 0) { | |||
6554 | log_debug("%s: failed to load flow", __func__); | |||
6555 | goto done; | |||
6556 | } | |||
6557 | ||||
6558 | if ((oflow = RB_FIND(iked_flows, &env->sc_activeflows, flow)iked_flows_RB_FIND(&env->sc_activeflows, flow)) | |||
6559 | != NULL((void *)0)) { | |||
6560 | log_debug("%s: replaced old flow %p with %p", | |||
6561 | __func__, oflow, flow); | |||
6562 | oflow->flow_loaded = 0; | |||
6563 | RB_REMOVE(iked_flows, &env->sc_activeflows, oflow)iked_flows_RB_REMOVE(&env->sc_activeflows, oflow); | |||
6564 | } | |||
6565 | ||||
6566 | RB_INSERT(iked_flows, &env->sc_activeflows, flow)iked_flows_RB_INSERT(&env->sc_activeflows, flow); | |||
6567 | ||||
6568 | log_debug("%s: %sloaded flow %p", __func__, | |||
6569 | reload ? "re" : "", flow); | |||
6570 | ||||
6571 | /* append flow to log buffer */ | |||
6572 | if (flow->flow_dir == IPSP_DIRECTION_OUT0x2 && | |||
6573 | flow->flow_prenat.addr_af != 0) | |||
6574 | snprintf(prenat_mask, sizeof(prenat_mask), "%d", | |||
6575 | flow->flow_prenat.addr_mask); | |||
6576 | else | |||
6577 | prenat_mask[0] = '\0'; | |||
6578 | if (flow->flow_dir == IPSP_DIRECTION_OUT0x2) { | |||
6579 | if (ftello(flowf) > 0) | |||
6580 | fputs(", ", flowf); | |||
6581 | fprintf(flowf, "%s-%s/%d%s%s%s%s%s=%s/%d(%u)%s", | |||
6582 | print_map(flow->flow_saproto, ikev2_saproto_map), | |||
6583 | print_addr(&flow->flow_src.addr), | |||
6584 | flow->flow_src.addr_mask, | |||
6585 | flow->flow_prenat.addr_af != 0 ? "[": "", | |||
6586 | flow->flow_prenat.addr_af != 0 ? | |||
6587 | print_addr(&flow->flow_prenat.addr) : "", | |||
6588 | flow->flow_prenat.addr_af != 0 ? "/" : "", | |||
6589 | flow->flow_prenat.addr_af != 0 ? prenat_mask : "", | |||
6590 | flow->flow_prenat.addr_af != 0 ? "]": "", | |||
6591 | print_addr(&flow->flow_dst.addr), | |||
6592 | flow->flow_dst.addr_mask, | |||
6593 | flow->flow_ipproto, | |||
6594 | reload ? "-R" : ""); | |||
6595 | } | |||
6596 | } | |||
6597 | } | |||
6598 | ||||
6599 | /* remember the current address for ikev2_update_sa_addresses() */ | |||
6600 | if (peer_changed) { | |||
6601 | memcpy(&sa->sa_peer_loaded, &sa->sa_peer, | |||
6602 | sizeof(sa->sa_peer_loaded)); | |||
6603 | log_debug("%s: remember SA peer %s", __func__, | |||
6604 | print_addr(&sa->sa_peer_loaded.addr)); | |||
6605 | } | |||
6606 | ||||
6607 | fflush(spif); | |||
6608 | if (ftello(spif) > 0 && !ferror(spif)(!__isthreaded ? (((spif)->_flags & 0x0040) != 0) : (ferror )(spif))) { | |||
6609 | log_info("%s: loaded SPIs: %s (enc %s%s%s%s%s%s)", | |||
6610 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), spibuf, | |||
6611 | print_xf(encrid, encrlen, ipsecencxfs), | |||
6612 | integrid ? " auth " : "", | |||
6613 | integrid ? print_xf(integrid, integrlen, authxfs) : "", | |||
6614 | groupid ? " group " : "", | |||
6615 | groupid ? print_xf(groupid, 0, groupxfs) : "", | |||
6616 | esn ? " esn" : ""); | |||
6617 | } | |||
6618 | fflush(flowf); | |||
6619 | if (ftello(flowf) > 0 && !ferror(flowf)(!__isthreaded ? (((flowf)->_flags & 0x0040) != 0) : ( ferror)(flowf))) { | |||
6620 | log_info("%s: loaded flows: %s", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), flowbuf); | |||
6621 | } | |||
6622 | ||||
6623 | ret = 0; | |||
6624 | done: | |||
6625 | fclose(spif); | |||
6626 | fclose(flowf); | |||
6627 | free(spibuf); | |||
6628 | free(flowbuf); | |||
6629 | return (ret); | |||
6630 | } | |||
6631 | ||||
6632 | int | |||
6633 | ikev2_childsa_delete(struct iked *env, struct iked_sa *sa, uint8_t saproto, | |||
6634 | uint64_t spi, uint64_t *spiptr, int cleanup) | |||
6635 | { | |||
6636 | struct iked_childsa *csa, *csatmp = NULL((void *)0), *ipcomp; | |||
6637 | uint64_t peerspi = 0; | |||
6638 | int found = 0; | |||
6639 | ||||
6640 | 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)) { | |||
6641 | if ((saproto && csa->csa_saproto != saproto) || | |||
6642 | (spi && (csa->csa_spi.spi != spi && | |||
6643 | csa->csa_peerspi != spi)) || | |||
6644 | (cleanup && csa->csa_loaded)) | |||
6645 | continue; | |||
6646 | ||||
6647 | if (csa->csa_loaded) | |||
6648 | RB_REMOVE(iked_activesas, &env->sc_activesas, csa)iked_activesas_RB_REMOVE(&env->sc_activesas, csa); | |||
6649 | ||||
6650 | if (pfkey_sa_delete(env, csa) != 0) | |||
6651 | log_info("%s: failed to delete CHILD SA spi %s", | |||
6652 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), print_spi(csa->csa_spi.spi, | |||
6653 | csa->csa_spi.spi_size)); | |||
6654 | else | |||
6655 | log_debug("%s: deleted CHILD SA spi %s", | |||
6656 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), print_spi(csa->csa_spi.spi, | |||
6657 | csa->csa_spi.spi_size)); | |||
6658 | found++; | |||
6659 | ||||
6660 | if (spi && csa->csa_spi.spi == spi) | |||
6661 | peerspi = csa->csa_peerspi; | |||
6662 | ||||
6663 | ipcomp = csa->csa_bundled; | |||
6664 | if (ipcomp) { | |||
6665 | if (ipcomp->csa_loaded) { | |||
6666 | if (pfkey_sa_delete(env, ipcomp) != 0) | |||
6667 | log_info("%s: failed to delete IPCOMP" | |||
6668 | " SA spi %s", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
6669 | print_spi(ipcomp->csa_spi.spi, | |||
6670 | ipcomp->csa_spi.spi_size)); | |||
6671 | else | |||
6672 | log_debug("%s: deleted IPCOMP SA spi %s", | |||
6673 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
6674 | print_spi(ipcomp->csa_spi.spi, | |||
6675 | ipcomp->csa_spi.spi_size)); | |||
6676 | } | |||
6677 | childsa_free(ipcomp); | |||
6678 | } | |||
6679 | 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); | |||
6680 | ikestat_inc(env, ikes_csa_removed)do { env->sc_stats.ikes_csa_removed += (1); } while(0); | |||
6681 | childsa_free(csa); | |||
6682 | } | |||
6683 | ||||
6684 | if (spiptr) | |||
6685 | *spiptr = peerspi; | |||
6686 | ||||
6687 | return (found ? 0 : -1); | |||
6688 | } | |||
6689 | ||||
6690 | int | |||
6691 | ikev2_valid_proposal(struct iked_proposal *prop, | |||
6692 | struct iked_transform **exf, struct iked_transform **ixf, int *esn) | |||
6693 | { | |||
6694 | struct iked_transform *xform, *encrxf, *integrxf; | |||
6695 | unsigned int i, doesn = 0; | |||
6696 | ||||
6697 | switch (prop->prop_protoid) { | |||
6698 | case IKEV2_SAPROTO_ESP3: | |||
6699 | case IKEV2_SAPROTO_AH2: | |||
6700 | break; | |||
6701 | default: | |||
6702 | return (-1); | |||
6703 | } | |||
6704 | ||||
6705 | encrxf = integrxf = NULL((void *)0); | |||
6706 | for (i = 0; i < prop->prop_nxforms; i++) { | |||
6707 | xform = prop->prop_xforms + i; | |||
6708 | if (xform->xform_type == IKEV2_XFORMTYPE_ENCR1) | |||
6709 | encrxf = xform; | |||
6710 | else if (xform->xform_type == IKEV2_XFORMTYPE_INTEGR3) | |||
6711 | integrxf = xform; | |||
6712 | else if (xform->xform_type == IKEV2_XFORMTYPE_ESN5 && | |||
6713 | xform->xform_id == IKEV2_XFORMESN_ESN1) | |||
6714 | doesn = 1; | |||
6715 | } | |||
6716 | ||||
6717 | if (prop->prop_protoid == IKEV2_SAPROTO_IKE1) { | |||
6718 | if (encrxf == NULL((void *)0) || integrxf == NULL((void *)0)) | |||
6719 | return (-1); | |||
6720 | } else if (prop->prop_protoid == IKEV2_SAPROTO_AH2) { | |||
6721 | if (integrxf == NULL((void *)0)) | |||
6722 | return (-1); | |||
6723 | } else if (prop->prop_protoid == IKEV2_SAPROTO_ESP3) { | |||
6724 | if (encrxf == NULL((void *)0)) | |||
6725 | return (-1); | |||
6726 | } | |||
6727 | ||||
6728 | if (exf) | |||
6729 | *exf = encrxf; | |||
6730 | if (ixf) | |||
6731 | *ixf = integrxf; | |||
6732 | if (esn) | |||
6733 | *esn = doesn; | |||
6734 | ||||
6735 | return (0); | |||
6736 | } | |||
6737 | ||||
6738 | /* return 0 if processed, -1 if busy */ | |||
6739 | int | |||
6740 | ikev2_child_sa_acquire(struct iked *env, struct iked_flow *acquire) | |||
6741 | { | |||
6742 | struct iked_flow *flow; | |||
6743 | struct iked_sa *sa; | |||
6744 | struct iked_policy pol, *p = NULL((void *)0); | |||
6745 | ||||
6746 | if (env->sc_passive) | |||
6747 | return (0); | |||
6748 | ||||
6749 | /* First try to find an active flow with IKE SA */ | |||
6750 | flow = RB_FIND(iked_flows, &env->sc_activeflows, acquire)iked_flows_RB_FIND(&env->sc_activeflows, acquire); | |||
6751 | if (!flow) { | |||
6752 | /* Otherwise try to find a matching policy */ | |||
6753 | bzero(&pol, sizeof(pol)); | |||
6754 | pol.pol_af = acquire->flow_peer->addr_af; | |||
6755 | memcpy(&pol.pol_peer, acquire->flow_peer, | |||
6756 | sizeof(pol.pol_peer)); | |||
6757 | ||||
6758 | RB_INIT(&pol.pol_flows)do { (&pol.pol_flows)->rbh_root = ((void *)0); } while (0); | |||
6759 | RB_INSERT(iked_flows, &pol.pol_flows, acquire)iked_flows_RB_INSERT(&pol.pol_flows, acquire); | |||
6760 | pol.pol_nflows = 1; | |||
6761 | ||||
6762 | if ((p = policy_test(env, &pol)) == NULL((void *)0)) { | |||
6763 | log_warnx("%s: flow wasn't found", __func__); | |||
6764 | return (0); | |||
6765 | } | |||
6766 | ||||
6767 | log_debug("%s: found matching policy '%s'", __func__, | |||
6768 | p->pol_name); | |||
6769 | ||||
6770 | if (ikev2_init_ike_sa_peer(env, p, | |||
6771 | &p->pol_peer, NULL((void *)0)) != 0) | |||
6772 | log_warnx("%s: failed to initiate a " | |||
6773 | "IKE_SA_INIT exchange for policy '%s'", | |||
6774 | __func__, p->pol_name); | |||
6775 | } else { | |||
6776 | log_debug("%s: found active flow", __func__); | |||
6777 | ||||
6778 | if ((sa = flow->flow_ikesa) == NULL((void *)0)) { | |||
6779 | log_warnx("%s: flow without SA", __func__); | |||
6780 | return (0); | |||
6781 | } | |||
6782 | if (sa->sa_stateflags & (IKED_REQ_CHILDSA0x0080|IKED_REQ_INF0x0100)) | |||
6783 | return (-1); /* busy, retry later */ | |||
6784 | if (ikev2_send_create_child_sa(env, sa, NULL((void *)0), | |||
6785 | flow->flow_saproto, 0) != 0) | |||
6786 | log_warnx("%s: failed to initiate a " | |||
6787 | "CREATE_CHILD_SA exchange", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
6788 | } | |||
6789 | return (0); | |||
6790 | } | |||
6791 | ||||
6792 | void | |||
6793 | ikev2_disable_rekeying(struct iked *env, struct iked_sa *sa) | |||
6794 | { | |||
6795 | struct iked_childsa *csa; | |||
6796 | ||||
6797 | TAILQ_FOREACH(csa, &sa->sa_childsas, csa_entry)for((csa) = ((&sa->sa_childsas)->tqh_first); (csa) != ((void *)0); (csa) = ((csa)->csa_entry.tqe_next)) { | |||
6798 | csa->csa_persistent = 1; | |||
6799 | csa->csa_rekey = 0; | |||
6800 | } | |||
6801 | ||||
6802 | (void)ikev2_childsa_delete(env, sa, 0, 0, NULL((void *)0), 1); | |||
6803 | } | |||
6804 | ||||
6805 | /* return 0 if processed, -1 if busy */ | |||
6806 | int | |||
6807 | ikev2_child_sa_rekey(struct iked *env, struct iked_spi *rekey) | |||
6808 | { | |||
6809 | struct iked_childsa *csa, key; | |||
6810 | struct iked_sa *sa; | |||
6811 | ||||
6812 | key.csa_spi = *rekey; | |||
6813 | csa = RB_FIND(iked_activesas, &env->sc_activesas, &key)iked_activesas_RB_FIND(&env->sc_activesas, &key); | |||
6814 | if (!csa) | |||
6815 | return (0); | |||
6816 | ||||
6817 | if (csa->csa_rekey) /* See if it's already taken care of */ | |||
6818 | return (0); | |||
6819 | if ((sa = csa->csa_ikesa) == NULL((void *)0)) { | |||
6820 | log_warnx("%s: SA %s doesn't have a parent SA", __func__, | |||
6821 | print_spi(rekey->spi, rekey->spi_size)); | |||
6822 | return (0); | |||
6823 | } | |||
6824 | if (!sa_stateok(sa, IKEV2_STATE_ESTABLISHED9)) { | |||
6825 | log_warnx("%s: not established, SPI %s", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
6826 | print_spi(rekey->spi, rekey->spi_size)); | |||
6827 | return (0); | |||
6828 | } | |||
6829 | if (sa->sa_stateflags & (IKED_REQ_CHILDSA0x0080|IKED_REQ_INF0x0100)) { | |||
6830 | log_info("%s: busy, retrying, SPI %s", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
6831 | print_spi(rekey->spi, rekey->spi_size)); | |||
6832 | return (-1); /* busy, retry later */ | |||
6833 | } | |||
6834 | if (sa->sa_tmpfail) { | |||
6835 | log_info("%s: peer busy, retrying, SPI %s", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
6836 | print_spi(rekey->spi, rekey->spi_size)); | |||
6837 | return (-1); /* peer is busy, retry later */ | |||
6838 | } | |||
6839 | if (csa->csa_allocated) /* Peer SPI died first, get the local one */ | |||
6840 | rekey->spi = csa->csa_peerspi; | |||
6841 | if (ikev2_send_create_child_sa(env, sa, rekey, rekey->spi_protoid, 0)) | |||
6842 | log_warnx("%s: failed to initiate a CREATE_CHILD_SA exchange", | |||
6843 | SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
6844 | return (0); | |||
6845 | } | |||
6846 | ||||
6847 | /* return 0 if processed, -1 if busy */ | |||
6848 | int | |||
6849 | ikev2_child_sa_drop(struct iked *env, struct iked_spi *drop) | |||
6850 | { | |||
6851 | struct ibuf *buf = NULL((void *)0); | |||
6852 | struct iked_childsa *csa, key; | |||
6853 | struct iked_sa *sa; | |||
6854 | struct ikev2_delete *del; | |||
6855 | uint32_t spi32; | |||
6856 | ||||
6857 | key.csa_spi = *drop; | |||
6858 | csa = RB_FIND(iked_activesas, &env->sc_activesas, &key)iked_activesas_RB_FIND(&env->sc_activesas, &key); | |||
6859 | if (!csa || csa->csa_rekey) | |||
6860 | return (0); | |||
6861 | ||||
6862 | sa = csa->csa_ikesa; | |||
6863 | if (sa && (sa->sa_stateflags & (IKED_REQ_CHILDSA0x0080|IKED_REQ_INF0x0100))) { | |||
6864 | /* XXXX might loop, should we add a counter? */ | |||
6865 | log_debug("%s: parent SA busy", __func__); | |||
6866 | return (-1); /* busy, retry later */ | |||
6867 | } | |||
6868 | ||||
6869 | RB_REMOVE(iked_activesas, &env->sc_activesas, csa)iked_activesas_RB_REMOVE(&env->sc_activesas, csa); | |||
6870 | csa->csa_loaded = 0; | |||
6871 | csa->csa_rekey = 1; /* prevent re-loading */ | |||
6872 | if (sa == NULL((void *)0)) { | |||
6873 | log_debug("%s: failed to find a parent SA", __func__); | |||
6874 | return (0); | |||
6875 | } | |||
6876 | ||||
6877 | if (csa->csa_allocated) | |||
6878 | 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)); | |||
6879 | else | |||
6880 | 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)); | |||
6881 | ||||
6882 | if (ikev2_childsa_delete(env, sa, csa->csa_saproto, | |||
6883 | csa->csa_peerspi, NULL((void *)0), 0)) | |||
6884 | log_debug("%s: failed to delete CHILD SA %s", __func__, | |||
6885 | print_spi(csa->csa_peerspi, drop->spi_size)); | |||
6886 | ||||
6887 | /* Send PAYLOAD_DELETE */ | |||
6888 | ||||
6889 | if ((buf = ibuf_static()) == NULL((void *)0)) | |||
6890 | return (0); | |||
6891 | if ((del = ibuf_reserve(buf, sizeof(*del))) == NULL((void *)0)) | |||
6892 | goto done; | |||
6893 | del->del_protoid = drop->spi_protoid; | |||
6894 | del->del_spisize = 4; | |||
6895 | 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)); | |||
6896 | if (ibuf_add(buf, &spi32, sizeof(spi32))) | |||
6897 | goto done; | |||
6898 | ||||
6899 | if (ikev2_send_ike_e(env, sa, buf, IKEV2_PAYLOAD_DELETE42, | |||
6900 | IKEV2_EXCHANGE_INFORMATIONAL37, 0) == -1) | |||
6901 | goto done; | |||
6902 | ||||
6903 | sa->sa_stateflags |= IKED_REQ_INF0x0100; | |||
6904 | ||||
6905 | done: | |||
6906 | ibuf_free(buf); | |||
6907 | return (0); | |||
6908 | } | |||
6909 | ||||
6910 | int | |||
6911 | ikev2_print_static_id(struct iked_static_id *id, char *idstr, size_t idstrlen) | |||
6912 | { | |||
6913 | struct iked_id idp; | |||
6914 | int ret = -1; | |||
6915 | ||||
6916 | bzero(&idp, sizeof(idp)); | |||
6917 | if ((idp.id_buf = ibuf_new(id->id_data, id->id_length)) == NULL((void *)0)) { | |||
6918 | bzero(idstr, idstrlen); | |||
6919 | return (-1); | |||
6920 | } | |||
6921 | idp.id_type = id->id_type; | |||
6922 | idp.id_offset = id->id_offset; | |||
6923 | if (ikev2_print_id(&idp, idstr, idstrlen) == -1) { | |||
6924 | bzero(idstr, idstrlen); | |||
6925 | goto done; | |||
6926 | } | |||
6927 | ret = 0; | |||
6928 | done: | |||
6929 | ibuf_free(idp.id_buf); | |||
6930 | return (ret); | |||
6931 | } | |||
6932 | ||||
6933 | int | |||
6934 | ikev2_print_id(struct iked_id *id, char *idstr, size_t idstrlen) | |||
6935 | { | |||
6936 | uint8_t *ptr; | |||
6937 | struct sockaddr_in s4 = { 0 }; | |||
6938 | struct sockaddr_in6 s6 = { 0 }; | |||
6939 | char *str; | |||
6940 | ssize_t len; | |||
6941 | int i; | |||
6942 | const char *type; | |||
6943 | ||||
6944 | bzero(idstr, idstrlen); | |||
6945 | ||||
6946 | if (id->id_buf == NULL((void *)0)) | |||
6947 | return (-1); | |||
6948 | ||||
6949 | len = ibuf_size(id->id_buf); | |||
6950 | ptr = ibuf_data(id->id_buf); | |||
6951 | ||||
6952 | if (len <= id->id_offset) | |||
6953 | return (-1); | |||
6954 | ||||
6955 | len -= id->id_offset; | |||
6956 | ptr += id->id_offset; | |||
6957 | ||||
6958 | type = print_map(id->id_type, ikev2_id_map); | |||
6959 | ||||
6960 | if (strlcpy(idstr, type, idstrlen) >= idstrlen || | |||
6961 | strlcat(idstr, "/", idstrlen) >= idstrlen) | |||
6962 | return (-1); | |||
6963 | ||||
6964 | switch (id->id_type) { | |||
6965 | case IKEV2_ID_IPV41: | |||
6966 | s4.sin_family = AF_INET2; | |||
6967 | s4.sin_len = sizeof(s4); | |||
6968 | memcpy(&s4.sin_addr.s_addr, ptr, len); | |||
6969 | ||||
6970 | if (strlcat(idstr, print_addr(&s4), idstrlen) >= idstrlen) | |||
6971 | return (-1); | |||
6972 | break; | |||
6973 | case IKEV2_ID_FQDN2: | |||
6974 | case IKEV2_ID_UFQDN3: | |||
6975 | if ((str = get_string(ptr, len)) == NULL((void *)0)) | |||
6976 | return (-1); | |||
6977 | ||||
6978 | if (strlcat(idstr, str, idstrlen) >= idstrlen) { | |||
6979 | free(str); | |||
6980 | return (-1); | |||
6981 | } | |||
6982 | free(str); | |||
6983 | break; | |||
6984 | case IKEV2_ID_IPV65: | |||
6985 | s6.sin6_family = AF_INET624; | |||
6986 | s6.sin6_len = sizeof(s6); | |||
6987 | memcpy(&s6.sin6_addr, ptr, len); | |||
6988 | ||||
6989 | if (strlcat(idstr, print_addr(&s6), idstrlen) >= idstrlen) | |||
6990 | return (-1); | |||
6991 | break; | |||
6992 | case IKEV2_ID_ASN1_DN9: | |||
6993 | if ((str = ca_asn1_name(ptr, len)) == NULL((void *)0)) | |||
6994 | return (-1); | |||
6995 | if (strlcat(idstr, str, idstrlen) >= idstrlen) { | |||
6996 | OPENSSL_free(str)CRYPTO_free(str); | |||
6997 | return (-1); | |||
6998 | } | |||
6999 | OPENSSL_free(str)CRYPTO_free(str); | |||
7000 | break; | |||
7001 | default: | |||
7002 | /* XXX test */ | |||
7003 | for (i = 0; i < len; i++) { | |||
7004 | char buf[3]; | |||
7005 | snprintf(buf, sizeof(buf), "%02x", ptr[i]); | |||
7006 | if (strlcat(idstr, buf, idstrlen) >= idstrlen) | |||
7007 | break; | |||
7008 | } | |||
7009 | break; | |||
7010 | } | |||
7011 | ||||
7012 | return (0); | |||
7013 | } | |||
7014 | ||||
7015 | /* | |||
7016 | * If we have an IKEV2_CP_REQUEST for IKEV2_CFG_INTERNAL_IP4_ADDRESS and | |||
7017 | * if a network(pool) is configured, then select an address from that pool | |||
7018 | * and remember it in the sa_addrpool attribute. | |||
7019 | */ | |||
7020 | int | |||
7021 | ikev2_cp_setaddr(struct iked *env, struct iked_sa *sa, sa_family_t family) | |||
7022 | { | |||
7023 | struct iked_policy *pol = sa->sa_policy; | |||
7024 | struct iked_cfg *ikecfg = NULL((void *)0); | |||
7025 | const char *errstr = NULL((void *)0); | |||
7026 | int ret, pass, passes; | |||
7027 | size_t i; | |||
7028 | ||||
7029 | switch (family) { | |||
7030 | case AF_INET2: | |||
7031 | if (sa->sa_addrpool) | |||
7032 | return (0); | |||
7033 | break; | |||
7034 | case AF_INET624: | |||
7035 | if (sa->sa_addrpool6) | |||
7036 | return (0); | |||
7037 | break; | |||
7038 | default: | |||
7039 | return (-1); | |||
7040 | } | |||
7041 | if (pol->pol_ncfg == 0) | |||
7042 | return (0); | |||
7043 | /* default if no pool configured */ | |||
7044 | ret = 0; | |||
7045 | /* two passes if client requests from specific pool */ | |||
7046 | passes = (sa->sa_cp_addr != NULL((void *)0) || sa->sa_cp_addr6 != NULL((void *)0)) ? 2 : 1; | |||
7047 | for (pass = 0; pass < passes; pass++) { | |||
7048 | /* loop over all address pool configs (addr_net) */ | |||
7049 | for (i = 0; i < pol->pol_ncfg; i++) { | |||
7050 | ikecfg = &pol->pol_cfg[i]; | |||
7051 | if (!ikecfg->cfg.address.addr_net) | |||
7052 | continue; | |||
7053 | if ((family == AF_INET2 && ikecfg->cfg_type == | |||
7054 | IKEV2_CFG_INTERNAL_IP4_ADDRESS1) || | |||
7055 | (family == AF_INET624 && ikecfg->cfg_type == | |||
7056 | IKEV2_CFG_INTERNAL_IP6_ADDRESS8)) { | |||
7057 | if ((ret = ikev2_cp_setaddr_pool(env, sa, | |||
7058 | ikecfg, &errstr, family)) == 0) | |||
7059 | return (0); | |||
7060 | } | |||
7061 | } | |||
7062 | if (sa->sa_cp_addr != NULL((void *)0)) { | |||
7063 | free(sa->sa_cp_addr); | |||
7064 | sa->sa_cp_addr = NULL((void *)0); | |||
7065 | } | |||
7066 | if (sa->sa_cp_addr6 != NULL((void *)0)) { | |||
7067 | free(sa->sa_cp_addr6); | |||
7068 | sa->sa_cp_addr6 = NULL((void *)0); | |||
7069 | } | |||
7070 | } | |||
7071 | ||||
7072 | if (errstr != NULL((void *)0)) | |||
7073 | log_warnx("%s: %s", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), errstr); | |||
7074 | return (ret); | |||
7075 | } | |||
7076 | ||||
7077 | int | |||
7078 | ikev2_cp_setaddr_pool(struct iked *env, struct iked_sa *sa, | |||
7079 | struct iked_cfg *ikecfg, const char **errstr, sa_family_t family) | |||
7080 | { | |||
7081 | struct sockaddr_in *in4 = NULL((void *)0), *cfg4 = NULL((void *)0); | |||
| ||||
7082 | struct sockaddr_in6 *in6 = NULL((void *)0), *cfg6 = NULL((void *)0); | |||
7083 | struct iked_sa key; | |||
7084 | struct iked_sa *osa; | |||
7085 | char idstr[IKED_ID_SIZE1024]; | |||
7086 | struct iked_addr addr; | |||
7087 | uint32_t mask, host, lower, upper, start, nhost; | |||
7088 | int requested = 0; | |||
7089 | ||||
7090 | /* | |||
7091 | * failure: pool configured, but not requested. | |||
7092 | * If we continue, we might end up with flows where 0.0.0.0 is NOT | |||
7093 | * replaced with an address from the pool with ikev2_cp_fixaddr(). | |||
7094 | */ | |||
7095 | if (sa->sa_cp != IKEV2_CP_REQUEST1) { | |||
7096 | log_debug("%s: pool configured, but IKEV2_CP_REQUEST missing", | |||
7097 | __func__); | |||
7098 | return (-1); | |||
7099 | } | |||
7100 | bzero(&addr, sizeof(addr)); | |||
7101 | addr.addr_af = family; | |||
7102 | ||||
7103 | /* check if old IKESA for same DSTID already exists and transfer IPs */ | |||
7104 | if (env->sc_stickyaddresssc_static.st_stickyaddress && | |||
7105 | (osa = sa_dstid_lookup(env, sa)) != NULL((void *)0) && | |||
7106 | ((family == AF_INET2 && osa->sa_addrpool) || | |||
7107 | (family == AF_INET624 && osa->sa_addrpool6))) { | |||
7108 | /* we have to transfer both, even if we just need one */ | |||
7109 | if (osa->sa_addrpool) { | |||
7110 | if (RB_REMOVE(iked_addrpool, &env->sc_addrpool, osa)iked_addrpool_RB_REMOVE(&env->sc_addrpool, osa) | |||
7111 | != osa) { | |||
7112 | log_info("%s: addrpool error", | |||
7113 | SPI_SA(osa, __func__)ikev2_ikesa_info((&(osa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
7114 | return (-1); | |||
7115 | } | |||
7116 | } | |||
7117 | if (osa->sa_addrpool6) { | |||
7118 | if (RB_REMOVE(iked_addrpool6, &env->sc_addrpool6, osa)iked_addrpool6_RB_REMOVE(&env->sc_addrpool6, osa) | |||
7119 | != osa) { | |||
7120 | log_info("%s: addrpool6 error", | |||
7121 | SPI_SA(osa, __func__)ikev2_ikesa_info((&(osa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
7122 | return (-1); | |||
7123 | } | |||
7124 | } | |||
7125 | sa_dstid_remove(env, osa); | |||
7126 | sa->sa_addrpool = osa->sa_addrpool; | |||
7127 | osa->sa_addrpool = NULL((void *)0); | |||
7128 | sa->sa_addrpool6 = osa->sa_addrpool6; | |||
7129 | osa->sa_addrpool6 = NULL((void *)0); | |||
7130 | if (osa->sa_state < IKEV2_STATE_CLOSING10) { | |||
7131 | if (osa->sa_state == IKEV2_STATE_ESTABLISHED9) | |||
7132 | ikev2_disable_timer(env, osa); | |||
7133 | ikev2_ike_sa_setreason(osa, | |||
7134 | "address re-use (identical dstid)"); | |||
7135 | ikev2_ikesa_delete(env, osa, 1); | |||
7136 | timer_add(env, &osa->sa_timer, | |||
7137 | 3 * IKED_RETRANSMIT_TIMEOUT2); | |||
7138 | } | |||
7139 | if (sa->sa_addrpool) { | |||
7140 | RB_INSERT(iked_addrpool, &env->sc_addrpool, sa)iked_addrpool_RB_INSERT(&env->sc_addrpool, sa); | |||
7141 | log_info( | |||
7142 | "%s: giving up assigned address %s to IKESA %s", | |||
7143 | SPI_SA(osa, __func__)ikev2_ikesa_info((&(osa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
7144 | print_addr(&sa->sa_addrpool->addr), | |||
7145 | print_spi(sa->sa_hdr.sh_ispi, 8)); | |||
7146 | } | |||
7147 | if (sa->sa_addrpool6) { | |||
7148 | RB_INSERT(iked_addrpool6, &env->sc_addrpool6, sa)iked_addrpool6_RB_INSERT(&env->sc_addrpool6, sa); | |||
7149 | log_info( | |||
7150 | "%s: giving up assigned v6 address %s to IKESA %s", | |||
7151 | SPI_SA(osa, __func__)ikev2_ikesa_info((&(osa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
7152 | print_addr(&sa->sa_addrpool6->addr), | |||
7153 | print_spi(sa->sa_hdr.sh_ispi, 8)); | |||
7154 | } | |||
7155 | if (family == AF_INET2 && sa->sa_addrpool != NULL((void *)0)) | |||
7156 | memcpy(&addr, sa->sa_addrpool, sizeof(addr)); | |||
7157 | else if (family == AF_INET624 && sa->sa_addrpool6 != NULL((void *)0)) | |||
7158 | memcpy(&addr, sa->sa_addrpool6, sizeof(addr)); | |||
7159 | goto done; | |||
7160 | } | |||
7161 | switch (addr.addr_af) { | |||
7162 | case AF_INET2: | |||
7163 | cfg4 = (struct sockaddr_in *)&ikecfg->cfg.address.addr; | |||
7164 | mask = prefixlen2mask(ikecfg->cfg.address.addr_mask); | |||
7165 | if (sa->sa_cp_addr != NULL((void *)0)) { | |||
7166 | memcpy(&addr, sa->sa_cp_addr, sizeof(addr)); | |||
7167 | key.sa_addrpool = &addr; | |||
7168 | in4 = (struct sockaddr_in *)&addr.addr; | |||
7169 | if ((in4->sin_addr.s_addr & mask) != | |||
7170 | (cfg4->sin_addr.s_addr & mask)) { | |||
7171 | *errstr = "requested addr out of range"; | |||
7172 | return (-1); | |||
7173 | } | |||
7174 | if (RB_FIND(iked_addrpool, &env->sc_addrpool,iked_addrpool_RB_FIND(&env->sc_addrpool, &key) | |||
7175 | &key)iked_addrpool_RB_FIND(&env->sc_addrpool, &key)) { | |||
7176 | *errstr = "requested addr in use"; | |||
7177 | return (-1); | |||
7178 | } | |||
7179 | sa->sa_addrpool = sa->sa_cp_addr; | |||
7180 | sa->sa_cp_addr = NULL((void *)0); | |||
7181 | RB_INSERT(iked_addrpool, &env->sc_addrpool, sa)iked_addrpool_RB_INSERT(&env->sc_addrpool, sa); | |||
7182 | requested = 1; | |||
7183 | goto done; | |||
7184 | } | |||
7185 | in4 = (struct sockaddr_in *)&addr.addr; | |||
7186 | in4->sin_family = AF_INET2; | |||
7187 | in4->sin_len = sizeof(*in4); | |||
7188 | 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)); | |||
7189 | key.sa_addrpool = &addr; | |||
7190 | break; | |||
7191 | case AF_INET624: | |||
7192 | cfg6 = (struct sockaddr_in6 *)&ikecfg->cfg.address.addr; | |||
7193 | in6 = (struct sockaddr_in6 *)&addr.addr; | |||
7194 | if (sa->sa_cp_addr6 != NULL((void *)0)) { | |||
7195 | /* XXX not yet supported */ | |||
7196 | } | |||
7197 | in6->sin6_family = AF_INET624; | |||
7198 | in6->sin6_len = sizeof(*in6); | |||
7199 | /* truncate prefixlen to get a 32-bit space */ | |||
7200 | mask = (ikecfg->cfg.address.addr_mask >= 96) | |||
7201 | ? prefixlen2mask(ikecfg->cfg.address.addr_mask - 96) | |||
7202 | : prefixlen2mask(0); | |||
7203 | memcpy(&lower, &cfg6->sin6_addr.s6_addr__u6_addr.__u6_addr8[12], sizeof(uint32_t)); | |||
7204 | 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)); | |||
7205 | key.sa_addrpool6 = &addr; | |||
7206 | break; | |||
7207 | default: | |||
7208 | return (-1); | |||
7209 | } | |||
7210 | ||||
7211 | /* Note that start, upper and host are in HOST byte order */ | |||
7212 | 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)); | |||
7213 | /* skip .0 address if possible */ | |||
7214 | if (lower < upper && lower == 0) | |||
7215 | lower = 1; | |||
7216 | if (upper < lower) | |||
7217 | upper = lower; | |||
7218 | /* Randomly select start from [lower, upper-1] */ | |||
7219 | start = arc4random_uniform(upper - lower) + lower; | |||
7220 | ||||
7221 | for (host = start;;) { | |||
7222 | log_debug("%s: mask %x start %x lower %x host %x upper %x", | |||
7223 | __func__, mask, start, lower, host, upper); | |||
7224 | switch (addr.addr_af) { | |||
7225 | case AF_INET2: | |||
7226 | in4->sin_addr.s_addr = | |||
7227 | (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)); | |||
| ||||
7228 | break; | |||
7229 | case AF_INET624: | |||
7230 | memcpy(in6, cfg6, sizeof(*in6)); | |||
7231 | memcpy(&nhost, &cfg6->sin6_addr.s6_addr__u6_addr.__u6_addr8[12], | |||
7232 | sizeof(uint32_t)); | |||
7233 | 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)); | |||
7234 | memcpy(&in6->sin6_addr.s6_addr__u6_addr.__u6_addr8[12], &nhost, | |||
7235 | sizeof(uint32_t)); | |||
7236 | break; | |||
7237 | default: | |||
7238 | return (-1); | |||
7239 | } | |||
7240 | if ((addr.addr_af == AF_INET2 && | |||
7241 | !RB_FIND(iked_addrpool, &env->sc_addrpool, &key)iked_addrpool_RB_FIND(&env->sc_addrpool, &key)) || | |||
7242 | (addr.addr_af == AF_INET624 && | |||
7243 | !RB_FIND(iked_addrpool6, &env->sc_addrpool6, &key)iked_addrpool6_RB_FIND(&env->sc_addrpool6, &key))) | |||
7244 | break; | |||
7245 | /* try next address */ | |||
7246 | host++; | |||
7247 | /* but skip broadcast and network address */ | |||
7248 | if (host >= upper || host < lower) | |||
7249 | host = lower; | |||
7250 | if (host == start) { | |||
7251 | *errstr = "address pool exhausted"; | |||
7252 | return (-1); /* exhausted */ | |||
7253 | } | |||
7254 | } | |||
7255 | ||||
7256 | addr.addr_mask = ikecfg->cfg.address.addr_mask; | |||
7257 | switch (addr.addr_af) { | |||
7258 | case AF_INET2: | |||
7259 | if (!key.sa_addrpool) | |||
7260 | return (-1); /* cannot happen? */ | |||
7261 | if ((sa->sa_addrpool = calloc(1, sizeof(addr))) == NULL((void *)0)) | |||
7262 | return (-1); | |||
7263 | memcpy(sa->sa_addrpool, &addr, sizeof(addr)); | |||
7264 | RB_INSERT(iked_addrpool, &env->sc_addrpool, sa)iked_addrpool_RB_INSERT(&env->sc_addrpool, sa); | |||
7265 | break; | |||
7266 | case AF_INET624: | |||
7267 | if (!key.sa_addrpool6) | |||
7268 | return (-1); /* cannot happen? */ | |||
7269 | if ((sa->sa_addrpool6 = calloc(1, sizeof(addr))) == NULL((void *)0)) | |||
7270 | return (-1); | |||
7271 | memcpy(sa->sa_addrpool6, &addr, sizeof(addr)); | |||
7272 | RB_INSERT(iked_addrpool6, &env->sc_addrpool6, sa)iked_addrpool6_RB_INSERT(&env->sc_addrpool6, sa); | |||
7273 | break; | |||
7274 | default: | |||
7275 | return (-1); | |||
7276 | } | |||
7277 | done: | |||
7278 | if (ikev2_print_id(IKESA_DSTID(sa)((sa)->sa_hdr.sh_initiator ? &(sa)->sa_rid : &( sa)->sa_iid), idstr, sizeof(idstr)) == -1) | |||
7279 | bzero(idstr, sizeof(idstr)); | |||
7280 | log_info("%sassigned address %s to %s%s", SPI_SA(sa, NULL)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((((void *)0)))), | |||
7281 | print_addr(&addr.addr), | |||
7282 | idstr, requested ? " (requested by peer)" : ""); | |||
7283 | return (0); | |||
7284 | } | |||
7285 | ||||
7286 | int | |||
7287 | ikev2_cp_request_configured(struct iked_sa *sa) | |||
7288 | { | |||
7289 | struct iked_policy *pol = sa->sa_policy; | |||
7290 | struct iked_cfg *ikecfg; | |||
7291 | unsigned int i; | |||
7292 | ||||
7293 | for (i = 0; i < pol->pol_ncfg; i++) { | |||
7294 | ikecfg = &pol->pol_cfg[i]; | |||
7295 | if (ikecfg->cfg_action == IKEV2_CP_REQUEST1) { | |||
7296 | log_debug("%s: yes", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
7297 | return 1; | |||
7298 | } | |||
7299 | } | |||
7300 | log_debug("%s: no", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ )))); | |||
7301 | return 0; | |||
7302 | } | |||
7303 | ||||
7304 | /* | |||
7305 | * if 'addr' is 'UNSPECIFIED' replace it with sa_addrpool from | |||
7306 | * the ip-pool or the sa_cp_addr received from peer and store the | |||
7307 | * result in 'patched'. | |||
7308 | */ | |||
7309 | int | |||
7310 | ikev2_cp_fixaddr(struct iked_sa *sa, struct iked_addr *addr, | |||
7311 | struct iked_addr *patched) | |||
7312 | { | |||
7313 | struct sockaddr_in *in4; | |||
7314 | struct sockaddr_in6 *in6; | |||
7315 | struct iked_addr *naddr; | |||
7316 | ||||
7317 | if (addr->addr_net) | |||
7318 | return (-2); | |||
7319 | if (sa->sa_cp == 0) | |||
7320 | return (-1); | |||
7321 | switch (addr->addr_af) { | |||
7322 | case AF_INET2: | |||
7323 | in4 = (struct sockaddr_in *)&addr->addr; | |||
7324 | if (in4->sin_addr.s_addr) | |||
7325 | return (-2); | |||
7326 | naddr = (sa->sa_cp == IKEV2_CP_REQUEST1) ? | |||
7327 | sa->sa_addrpool : sa->sa_cp_addr; | |||
7328 | if (naddr == NULL((void *)0)) | |||
7329 | return (-1); | |||
7330 | memcpy(patched, naddr, sizeof(*patched)); | |||
7331 | patched->addr_net = 0; | |||
7332 | patched->addr_mask = 32; | |||
7333 | break; | |||
7334 | case AF_INET624: | |||
7335 | in6 = (struct sockaddr_in6 *)&addr->addr; | |||
7336 | 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))) | |||
7337 | return (-2); | |||
7338 | naddr = (sa->sa_cp == IKEV2_CP_REQUEST1) ? | |||
7339 | sa->sa_addrpool6 : sa->sa_cp_addr6; | |||
7340 | if (naddr == NULL((void *)0)) | |||
7341 | return (-1); | |||
7342 | memcpy(patched, naddr, sizeof(*patched)); | |||
7343 | patched->addr_net = 0; | |||
7344 | patched->addr_mask = 128; | |||
7345 | break; | |||
7346 | } | |||
7347 | return (0); | |||
7348 | } | |||
7349 | ||||
7350 | /* replace unspecified address in flow with requested address */ | |||
7351 | int | |||
7352 | ikev2_cp_fixflow(struct iked_sa *sa, struct iked_flow *flow, | |||
7353 | struct iked_flow *patched) | |||
7354 | { | |||
7355 | switch (sa->sa_cp) { | |||
7356 | case IKEV2_CP_REQUEST1: | |||
7357 | if (patched->flow_dir == IPSP_DIRECTION_IN0x1) | |||
7358 | return (ikev2_cp_fixaddr(sa, &flow->flow_dst, | |||
7359 | &patched->flow_src)); | |||
7360 | else | |||
7361 | return (ikev2_cp_fixaddr(sa, &flow->flow_dst, | |||
7362 | &patched->flow_dst)); | |||
7363 | case IKEV2_CP_REPLY2: | |||
7364 | if (patched->flow_dir == IPSP_DIRECTION_IN0x1) | |||
7365 | return (ikev2_cp_fixaddr(sa, &flow->flow_src, | |||
7366 | &patched->flow_dst)); | |||
7367 | else | |||
7368 | return (ikev2_cp_fixaddr(sa, &flow->flow_src, | |||
7369 | &patched->flow_src)); | |||
7370 | default: | |||
7371 | return (0); | |||
7372 | } | |||
7373 | } | |||
7374 | ||||
7375 | int | |||
7376 | ikev2_update_sa_addresses(struct iked *env, struct iked_sa *sa) | |||
7377 | { | |||
7378 | struct iked_childsa *csa, *ipcomp; | |||
7379 | struct iked_flow *flow, *oflow; | |||
7380 | struct iked_message *msg; | |||
7381 | struct iked_msg_retransmit *mr; | |||
7382 | ||||
7383 | if (!sa_stateok(sa, IKEV2_STATE_ESTABLISHED9)) | |||
7384 | return -1; | |||
7385 | ||||
7386 | log_info("%s: old %s new %s", SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))), | |||
7387 | print_addr(&sa->sa_peer_loaded.addr), | |||
7388 | print_addr(&sa->sa_peer.addr)); | |||
7389 | ||||
7390 | TAILQ_FOREACH(csa, &sa->sa_childsas, csa_entry)for((csa) = ((&sa->sa_childsas)->tqh_first); (csa) != ((void *)0); (csa) = ((csa)->csa_entry.tqe_next)) { | |||
7391 | if (!csa->csa_loaded) | |||
7392 | continue; | |||
7393 | if (pfkey_sa_update_addresses(env, csa) != 0) | |||
7394 | log_debug("%s: failed to update sa", __func__); | |||
7395 | if ((ipcomp = csa->csa_bundled) != NULL((void *)0) && | |||
7396 | ipcomp->csa_loaded) | |||
7397 | if (pfkey_sa_update_addresses(env, ipcomp) | |||
7398 | != 0) | |||
7399 | log_debug("%s: failed to update sa", __func__); | |||
7400 | } | |||
7401 | ||||
7402 | /* delete and re-add flows */ | |||
7403 | TAILQ_FOREACH(flow, &sa->sa_flows, flow_entry)for((flow) = ((&sa->sa_flows)->tqh_first); (flow) != ((void *)0); (flow) = ((flow)->flow_entry.tqe_next)) { | |||
7404 | if (flow->flow_loaded) { | |||
7405 | RB_REMOVE(iked_flows, &env->sc_activeflows, flow)iked_flows_RB_REMOVE(&env->sc_activeflows, flow); | |||
7406 | (void)pfkey_flow_delete(env, flow); | |||
7407 | flow->flow_loaded = 0; | |||
7408 | } | |||
7409 | if (pfkey_flow_add(env, flow) != 0) | |||
7410 | log_debug("%s: failed to add flow %p", __func__, flow); | |||
7411 | if (!flow->flow_loaded) | |||
7412 | continue; | |||
7413 | if ((oflow = RB_FIND(iked_flows, &env->sc_activeflows, flow)iked_flows_RB_FIND(&env->sc_activeflows, flow)) | |||
7414 | != NULL((void *)0)) { | |||
7415 | log_debug("%s: replaced old flow %p with %p", | |||
7416 | __func__, oflow, flow); | |||
7417 | oflow->flow_loaded = 0; | |||
7418 | RB_REMOVE(iked_flows, &env->sc_activeflows, oflow)iked_flows_RB_REMOVE(&env->sc_activeflows, oflow); | |||
7419 | } | |||
7420 | RB_INSERT(iked_flows, &env->sc_activeflows, flow)iked_flows_RB_INSERT(&env->sc_activeflows, flow); | |||
7421 | } | |||
7422 | ||||
7423 | /* update pending requests and responses */ | |||
7424 | TAILQ_FOREACH(mr, &sa->sa_requests, mrt_entry)for((mr) = ((&sa->sa_requests)->tqh_first); (mr) != ((void *)0); (mr) = ((mr)->mrt_entry.tqe_next)) { | |||
7425 | TAILQ_FOREACH(msg, &mr->mrt_frags, msg_entry)for((msg) = ((&mr->mrt_frags)->tqh_first); (msg) != ((void *)0); (msg) = ((msg)->msg_entry.tqe_next)) { | |||
7426 | msg->msg_local = sa->sa_local.addr; | |||
7427 | msg->msg_locallen = sa->sa_local.addr.ss_len; | |||
7428 | msg->msg_peer = sa->sa_peer.addr; | |||
7429 | msg->msg_peerlen = sa->sa_peer.addr.ss_len; | |||
7430 | } | |||
7431 | } | |||
7432 | TAILQ_FOREACH(mr, &sa->sa_responses, mrt_entry)for((mr) = ((&sa->sa_responses)->tqh_first); (mr) != ((void *)0); (mr) = ((mr)->mrt_entry.tqe_next)) { | |||
7433 | TAILQ_FOREACH(msg, &mr->mrt_frags, msg_entry)for((msg) = ((&mr->mrt_frags)->tqh_first); (msg) != ((void *)0); (msg) = ((msg)->msg_entry.tqe_next)) { | |||
7434 | msg->msg_local = sa->sa_local.addr; | |||
7435 | msg->msg_locallen = sa->sa_local.addr.ss_len; | |||
7436 | msg->msg_peer = sa->sa_peer.addr; | |||
7437 | msg->msg_peerlen = sa->sa_peer.addr.ss_len; | |||
7438 | } | |||
7439 | } | |||
7440 | ||||
7441 | /* Update sa_peer_loaded, to match in-kernel information */ | |||
7442 | memcpy(&sa->sa_peer_loaded, &sa->sa_peer, sizeof(sa->sa_peer_loaded)); | |||
7443 | ||||
7444 | return 0; | |||
7445 | } | |||
7446 | ||||
7447 | void | |||
7448 | ikev2_info_sa(struct iked *env, int dolog, const char *msg, struct iked_sa *sa) | |||
7449 | { | |||
7450 | char idstr[IKED_ID_SIZE1024]; | |||
7451 | char *buf; | |||
7452 | int buflen; | |||
7453 | ||||
7454 | if (ikev2_print_id(IKESA_DSTID(sa)((sa)->sa_hdr.sh_initiator ? &(sa)->sa_rid : &( sa)->sa_iid), idstr, sizeof(idstr)) == -1) | |||
7455 | bzero(idstr, sizeof(idstr)); | |||
7456 | ||||
7457 | buflen = asprintf(&buf, | |||
7458 | "%s: %p rspi %s ispi %s %s->%s<%s>[%s] %s %c%s%s nexti %p pol %p\n", | |||
7459 | msg, sa, | |||
7460 | print_spi(sa->sa_hdr.sh_rspi, 8), | |||
7461 | print_spi(sa->sa_hdr.sh_ispi, 8), | |||
7462 | print_addr(&sa->sa_local.addr), | |||
7463 | print_addr(&sa->sa_peer.addr), | |||
7464 | idstr, | |||
7465 | sa->sa_addrpool ? print_addr(&sa->sa_addrpool->addr) : "", | |||
7466 | print_map(sa->sa_state, ikev2_state_map), | |||
7467 | sa->sa_hdr.sh_initiator ? 'i' : 'r', | |||
7468 | sa->sa_natt ? " natt" : "", | |||
7469 | sa->sa_udpencap ? " udpecap" : "", | |||
7470 | sa->sa_nexti, sa->sa_policy); | |||
7471 | ||||
7472 | if (buflen == -1 || buf == NULL((void *)0)) | |||
7473 | return; | |||
7474 | ||||
7475 | if (dolog) { | |||
7476 | if (buflen > 1) | |||
7477 | buf[buflen - 1] = '\0'; | |||
7478 | log_debug("%s", buf); | |||
7479 | } else | |||
7480 | proc_compose(&env->sc_ps, PROC_CONTROL, IMSG_CTL_SHOW_SA, | |||
7481 | buf, buflen + 1); | |||
7482 | free(buf); | |||
7483 | } | |||
7484 | ||||
7485 | void | |||
7486 | ikev2_info_csa(struct iked *env, int dolog, const char *msg, struct iked_childsa *csa) | |||
7487 | { | |||
7488 | char *buf; | |||
7489 | int buflen; | |||
7490 | ||||
7491 | buflen = asprintf(&buf, | |||
7492 | "%s: %p %s %s %s %s -> %s (%s%s%s%s) B=%p P=%p @%p\n", msg, csa, | |||
7493 | print_map(csa->csa_saproto, ikev2_saproto_map), | |||
7494 | print_spi(csa->csa_spi.spi, csa->csa_spi.spi_size), | |||
7495 | csa->csa_dir == IPSP_DIRECTION_IN0x1 ? "in" : "out", | |||
7496 | print_addr(&csa->csa_local->addr), | |||
7497 | print_addr(&csa->csa_peer->addr), | |||
7498 | csa->csa_loaded ? "L" : "", | |||
7499 | csa->csa_rekey ? "R" : "", | |||
7500 | csa->csa_allocated ? "A" : "", | |||
7501 | csa->csa_persistent ? "P" : "", | |||
7502 | csa->csa_bundled, | |||
7503 | csa->csa_peersa, | |||
7504 | csa->csa_ikesa); | |||
7505 | ||||
7506 | if (buflen == -1 || buf == NULL((void *)0)) | |||
7507 | return; | |||
7508 | ||||
7509 | if (dolog) { | |||
7510 | if (buflen > 1) | |||
7511 | buf[buflen - 1] = '\0'; | |||
7512 | log_debug("%s", buf); | |||
7513 | } else | |||
7514 | proc_compose(&env->sc_ps, PROC_CONTROL, IMSG_CTL_SHOW_SA, | |||
7515 | buf, buflen + 1); | |||
7516 | free(buf); | |||
7517 | } | |||
7518 | ||||
7519 | void | |||
7520 | ikev2_info_flow(struct iked *env, int dolog, const char *msg, struct iked_flow *flow) | |||
7521 | { | |||
7522 | char prenat_mask[10]; | |||
7523 | char *buf; | |||
7524 | int buflen; | |||
7525 | ||||
7526 | if (flow->flow_prenat.addr_af != 0) | |||
7527 | snprintf(prenat_mask, sizeof(prenat_mask), "%d", | |||
7528 | flow->flow_prenat.addr_mask); | |||
7529 | else | |||
7530 | prenat_mask[0] = '\0'; | |||
7531 | ||||
7532 | buflen = asprintf(&buf, | |||
7533 | "%s: %p %s %s %s/%d -> %s/%d %s%s%s%s%s[%u]@%d (%s) @%p\n", msg, flow, | |||
7534 | print_map(flow->flow_saproto, ikev2_saproto_map), | |||
7535 | flow->flow_dir == IPSP_DIRECTION_IN0x1 ? "in" : "out", | |||
7536 | print_addr(&flow->flow_src.addr), | |||
7537 | flow->flow_src.addr_mask, | |||
7538 | print_addr(&flow->flow_dst.addr), | |||
7539 | flow->flow_dst.addr_mask, | |||
7540 | flow->flow_prenat.addr_af != 0 ? "[": "", | |||
7541 | flow->flow_prenat.addr_af != 0 ? | |||
7542 | print_addr(&flow->flow_prenat.addr) : "", | |||
7543 | flow->flow_prenat.addr_af != 0 ? "/" : "", | |||
7544 | flow->flow_prenat.addr_af != 0 ? prenat_mask : "", | |||
7545 | flow->flow_prenat.addr_af != 0 ? "] ": "", | |||
7546 | flow->flow_ipproto, | |||
7547 | flow->flow_rdomain, | |||
7548 | flow->flow_loaded ? "L" : "", | |||
7549 | flow->flow_ikesa); | |||
7550 | ||||
7551 | if (buflen == -1 || buf == NULL((void *)0)) | |||
7552 | return; | |||
7553 | ||||
7554 | if (dolog) { | |||
7555 | if (buflen > 1) | |||
7556 | buf[buflen - 1] = '\0'; | |||
7557 | log_debug("%s", buf); | |||
7558 | } else | |||
7559 | proc_compose(&env->sc_ps, PROC_CONTROL, IMSG_CTL_SHOW_SA, | |||
7560 | buf, buflen + 1); | |||
7561 | free(buf); | |||
7562 | } | |||
7563 | ||||
7564 | void | |||
7565 | ikev2_info(struct iked *env, int dolog) | |||
7566 | { | |||
7567 | struct iked_sa *sa; | |||
7568 | struct iked_childsa *csa, *ipcomp; | |||
7569 | struct iked_flow *flow; | |||
7570 | ||||
7571 | log_debug("%s: called", __func__); | |||
7572 | ||||
7573 | 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)) { | |||
7574 | ikev2_info_sa(env, dolog, "iked_sas", sa); | |||
7575 | TAILQ_FOREACH(csa, &sa->sa_childsas, csa_entry)for((csa) = ((&sa->sa_childsas)->tqh_first); (csa) != ((void *)0); (csa) = ((csa)->csa_entry.tqe_next)) { | |||
7576 | ikev2_info_csa(env, dolog, " sa_childsas", csa); | |||
7577 | if ((ipcomp = csa->csa_bundled) != NULL((void *)0)) | |||
7578 | ikev2_info_csa(env, dolog, " ", | |||
7579 | ipcomp); | |||
7580 | } | |||
7581 | TAILQ_FOREACH(flow, &sa->sa_flows, flow_entry)for((flow) = ((&sa->sa_flows)->tqh_first); (flow) != ((void *)0); (flow) = ((flow)->flow_entry.tqe_next)) { | |||
7582 | ikev2_info_flow(env, dolog, " sa_flows", flow); | |||
7583 | } | |||
7584 | } | |||
7585 | 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 )) { | |||
7586 | ikev2_info_csa(env, dolog, "iked_activesas", csa); | |||
7587 | if ((ipcomp = csa->csa_bundled) != NULL((void *)0)) | |||
7588 | ikev2_info_csa(env, dolog, " ", ipcomp); | |||
7589 | } | |||
7590 | 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 )) { | |||
7591 | ikev2_info_flow(env, dolog, "iked_flows", flow); | |||
7592 | } | |||
7593 | 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) ) { | |||
7594 | ikev2_info_sa(env, dolog, "iked_dstid_sas", sa); | |||
7595 | } | |||
7596 | if (dolog) | |||
7597 | return; | |||
7598 | /* Send empty reply to indicate end of information. */ | |||
7599 | proc_compose(&env->sc_ps, PROC_CONTROL, IMSG_CTL_SHOW_SA, NULL((void *)0), 0); | |||
7600 | } | |||
7601 | ||||
7602 | const char * | |||
7603 | ikev2_ikesa_info(uint64_t spi, const char *msg) | |||
7604 | { | |||
7605 | static char buf[1024]; | |||
7606 | const char *spistr; | |||
7607 | ||||
7608 | spistr = print_spi(spi, 8); | |||
7609 | if (msg) | |||
7610 | snprintf(buf, sizeof(buf), "spi=%s: %s", spistr, msg); | |||
7611 | else | |||
7612 | snprintf(buf, sizeof(buf), "spi=%s: ", spistr); | |||
7613 | return buf; | |||
7614 | } | |||
7615 | ||||
7616 | void | |||
7617 | ikev2_log_established(struct iked_sa *sa) | |||
7618 | { | |||
7619 | char dstid[IKED_ID_SIZE1024], srcid[IKED_ID_SIZE1024]; | |||
7620 | ||||
7621 | if (ikev2_print_id(IKESA_DSTID(sa)((sa)->sa_hdr.sh_initiator ? &(sa)->sa_rid : &( sa)->sa_iid), dstid, sizeof(dstid)) == -1) | |||
7622 | bzero(dstid, sizeof(dstid)); | |||
7623 | if (ikev2_print_id(IKESA_SRCID(sa)((sa)->sa_hdr.sh_initiator ? &(sa)->sa_iid : &( sa)->sa_rid), srcid, sizeof(srcid)) == -1) | |||
7624 | bzero(srcid, sizeof(srcid)); | |||
7625 | log_info( | |||
7626 | "%sestablished peer %s[%s] local %s[%s]%s%s%s%s policy '%s'%s" | |||
7627 | " (enc %s%s%s group %s prf %s)", SPI_SA(sa, NULL)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((((void *)0)))), | |||
7628 | print_addr(&sa->sa_peer.addr), dstid, | |||
7629 | print_addr(&sa->sa_local.addr), srcid, | |||
7630 | sa->sa_addrpool ? " assigned " : "", | |||
7631 | sa->sa_addrpool ? print_addr(&sa->sa_addrpool->addr) : "", | |||
7632 | sa->sa_addrpool6 ? " assigned " : "", | |||
7633 | sa->sa_addrpool6 ? print_addr(&sa->sa_addrpool6->addr) : "", | |||
7634 | sa->sa_policy ? sa->sa_policy->pol_name : "", | |||
7635 | sa->sa_hdr.sh_initiator ? " as initiator" : " as responder", | |||
7636 | print_xf(sa->sa_encr->encr_id, cipher_keylength(sa->sa_encr) - | |||
7637 | sa->sa_encr->encr_saltlength, ikeencxfs), | |||
7638 | sa->sa_encr->encr_authid ? "" : " auth ", | |||
7639 | sa->sa_encr->encr_authid ? "" : print_xf(sa->sa_integr->hash_id, | |||
7640 | hash_keylength(sa->sa_integr), authxfs), | |||
7641 | print_xf(sa->sa_dhgroupsa_kex.kex_dhgroup->id, 0, groupxfs), | |||
7642 | print_xf(sa->sa_prf->hash_id, hash_keylength(sa->sa_prf), prfxfs)); | |||
7643 | } | |||
7644 | ||||
7645 | void | |||
7646 | ikev2_log_cert_info(const char *msg, struct iked_id *certid) | |||
7647 | { | |||
7648 | X509 *cert = NULL((void *)0); | |||
7649 | BIO *rawcert = NULL((void *)0); | |||
7650 | ||||
7651 | if (certid->id_type != IKEV2_CERT_X509_CERT4 || | |||
7652 | certid->id_buf == NULL((void *)0)) | |||
7653 | return; | |||
7654 | if ((rawcert = BIO_new_mem_buf(ibuf_data(certid->id_buf), | |||
7655 | ibuf_size(certid->id_buf))) == NULL((void *)0) || | |||
7656 | (cert = d2i_X509_bio(rawcert, NULL((void *)0))) == NULL((void *)0)) | |||
7657 | goto out; | |||
7658 | ca_cert_info(msg, cert); | |||
7659 | out: | |||
7660 | if (cert) | |||
7661 | X509_free(cert); | |||
7662 | if (rawcert) | |||
7663 | BIO_free(rawcert); | |||
7664 | } | |||
7665 | ||||
7666 | void | |||
7667 | ikev2_log_proposal(struct iked_sa *sa, struct iked_proposals *proposals) | |||
7668 | { | |||
7669 | struct iked_proposal *prop; | |||
7670 | struct iked_transform *xform; | |||
7671 | unsigned int i; | |||
7672 | char lenstr[20]; | |||
7673 | ||||
7674 | TAILQ_FOREACH(prop, proposals, prop_entry)for((prop) = ((proposals)->tqh_first); (prop) != ((void *) 0); (prop) = ((prop)->prop_entry.tqe_next)) { | |||
7675 | for (i = 0; i < prop->prop_nxforms; i++) { | |||
7676 | xform = &prop->prop_xforms[i]; | |||
7677 | if (xform->xform_keylength) | |||
7678 | snprintf(lenstr, sizeof(lenstr), "-%u", | |||
7679 | xform->xform_keylength); | |||
7680 | else | |||
7681 | lenstr[0] = '\0'; | |||
7682 | log_info("%s: %s #%u %s=%s%s", | |||
7683 | sa ? SPI_SA(sa, __func__)ikev2_ikesa_info((&(sa)->sa_hdr)->sh_ispi, ((__func__ ))) : __func__, | |||
7684 | print_map(prop->prop_protoid, ikev2_saproto_map), | |||
7685 | prop->prop_id, | |||
7686 | print_map(xform->xform_type, ikev2_xformtype_map), | |||
7687 | xform->xform_map ? | |||
7688 | print_map(xform->xform_id, xform->xform_map) | |||
7689 | : "UNKNOWN", | |||
7690 | lenstr); | |||
7691 | } | |||
7692 | } | |||
7693 | } |