]> git.saurik.com Git - apple/ipsec.git/blob - ipsec-tools/racoon/vpn_control.c
ipsec-332.100.1.tar.gz
[apple/ipsec.git] / ipsec-tools / racoon / vpn_control.c
1 /* $Id: vpn_control.c,v 1.17.2.4 2005/07/12 11:49:44 manubsd Exp $ */
2
3 /*
4 * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
5 *
6 * @APPLE_LICENSE_HEADER_START@
7 *
8 * The contents of this file constitute Original Code as defined in and
9 * are subject to the Apple Public Source License Version 1.1 (the
10 * "License"). You may not use this file except in compliance with the
11 * License. Please obtain a copy of the License at
12 * http://www.apple.com/publicsource and read it before using this file.
13 *
14 * This Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25 /*
26 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
27 * All rights reserved.
28 *
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
31 * are met:
32 * 1. Redistributions of source code must retain the above copyright
33 * notice, this list of conditions and the following disclaimer.
34 * 2. Redistributions in binary form must reproduce the above copyright
35 * notice, this list of conditions and the following disclaimer in the
36 * documentation and/or other materials provided with the distribution.
37 * 3. Neither the name of the project nor the names of its contributors
38 * may be used to endorse or promote products derived from this software
39 * without specific prior written permission.
40 *
41 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * SUCH DAMAGE.
52 */
53
54 #include "config.h"
55
56 #include <sys/types.h>
57 #include <sys/param.h>
58 #include <sys/socket.h>
59 #include <sys/signal.h>
60 #include <sys/stat.h>
61 #include <sys/un.h>
62
63 #include <net/pfkeyv2.h>
64
65 #include <netinet/in.h>
66 #ifndef HAVE_NETINET6_IPSEC
67 #include <netinet/ipsec.h>
68 #else
69 #include <netinet6/ipsec.h>
70 #endif
71
72
73 #include <stdlib.h>
74 #include <stdio.h>
75 #include <string.h>
76 #include <errno.h>
77 #include <netdb.h>
78 #ifdef HAVE_UNISTD_H
79 #include <unistd.h>
80 #endif
81 #include <launch.h>
82 #include <fcntl.h>
83
84 #include "var.h"
85 #include "misc.h"
86 #include "vmbuf.h"
87 #include "plog.h"
88 #include "sockmisc.h"
89 #include "debug.h"
90
91 #include "schedule.h"
92 #include "localconf.h"
93 #include "remoteconf.h"
94 #include "grabmyaddr.h"
95 #include "isakmp_var.h"
96 #include "isakmp.h"
97 #include "oakley.h"
98 #include "handler.h"
99 #include "pfkey.h"
100 #include "ipsec_doi.h"
101 #include "vpn_control.h"
102 #include "vpn_control_var.h"
103 #include "isakmp_inf.h"
104 #include "session.h"
105 #include "gcmalloc.h"
106 #include "isakmp_cfg.h"
107 #include "sainfo.h"
108
109 #ifdef ENABLE_VPNCONTROL_PORT
110 char *vpncontrolsock_path = VPNCONTROLSOCK_PATH;
111 uid_t vpncontrolsock_owner = 0;
112 gid_t vpncontrolsock_group = 0;
113 mode_t vpncontrolsock_mode = 0600;
114
115 static struct sockaddr_un sunaddr;
116 static int vpncontrol_process (struct vpnctl_socket_elem *, char *, size_t);
117 static int vpncontrol_reply (int, char *);
118 static void vpncontrol_close_comm (struct vpnctl_socket_elem *);
119 static int checklaunchd (void);
120 extern int vpn_get_config (phase1_handle_t *, struct vpnctl_status_phase_change **, size_t *);
121 extern int vpn_xauth_reply (u_int32_t, void *, size_t);
122
123
124 int
125 checklaunchd()
126 {
127 int returnval = 0;
128 int *listening_fd_array = NULL;
129 size_t fd_count = 0;
130
131 int result = launch_activate_socket("Listeners", &listening_fd_array, &fd_count);
132 if (result != 0) {
133 plog(ASL_LEVEL_ERR, "failed to launch_activate_socket with error %s.\n", strerror(result));
134 return returnval;
135 }
136
137 if (listening_fd_array != NULL) {
138 if (fd_count > 0) {
139 returnval = listening_fd_array[0];
140 }
141 free(listening_fd_array);
142 listening_fd_array = NULL;
143 }
144
145 return returnval;
146 }
147
148
149 void
150 vpncontrol_handler(void *unused)
151 {
152 struct sockaddr_storage from;
153 socklen_t fromlen = sizeof(from);
154 int sock;
155
156 struct vpnctl_socket_elem *sock_elem;
157
158
159 sock_elem = racoon_calloc(1, sizeof(struct vpnctl_socket_elem));
160 if (sock_elem == NULL) {
161 plog(ASL_LEVEL_ERR,
162 "memory error: %s\n", strerror(errno));
163 return; //%%%%%% terminate
164 }
165 LIST_INIT(&sock_elem->bound_addresses);
166
167 sock_elem->sock = accept(lcconf->sock_vpncontrol, (struct sockaddr *)&from, &fromlen);
168 if (sock_elem->sock < 0) {
169 plog(ASL_LEVEL_ERR,
170 "failed to accept vpn_control command: %s\n", strerror(errno));
171 racoon_free(sock_elem);
172 return; //%%%%% terminate
173 }
174 LIST_INSERT_HEAD(&lcconf->vpnctl_comm_socks, sock_elem, chain);
175
176 sock_elem->source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, sock_elem->sock, 0, dispatch_get_main_queue());
177 if (sock_elem->source == NULL) {
178 plog(ASL_LEVEL_ERR, "could not create comm socket source.");
179 racoon_free(sock_elem);
180 return; //%%%%% terminate
181 }
182 dispatch_source_set_event_handler(sock_elem->source,
183 ^{
184 vpncontrol_comm_handler(sock_elem);
185 });
186 sock = sock_elem->sock;
187
188 dispatch_source_t the_source = sock_elem->source;
189 dispatch_source_set_cancel_handler(sock_elem->source,
190 ^{
191 close(sock);
192 dispatch_release(the_source); /* Release the source on cancel */
193 });
194 dispatch_resume(sock_elem->source);
195
196 plog(ASL_LEVEL_NOTICE,
197 "accepted connection on vpn control socket.\n");
198 check_auto_exit();
199
200 return;
201 }
202
203 void
204 vpncontrol_comm_handler(struct vpnctl_socket_elem *elem)
205 {
206 struct vpnctl_hdr hdr;
207 ssize_t len;
208
209 /* get buffer length */
210 if (elem->buffer == NULL) {
211 while ((len = recv(elem->sock, (char *)&hdr, sizeof(hdr), MSG_PEEK)) < 0) {
212 if (errno == EINTR)
213 continue;
214 plog(ASL_LEVEL_ERR, "failed to recv vpn_control command: %s\n", strerror(errno));
215 return;
216 }
217 if (len == 0) {
218 plog(ASL_LEVEL_NOTICE, "vpn_control socket closed by peer.\n");
219 /* kill all related connections */
220 vpncontrol_disconnect_all(elem, ike_session_stopped_by_controller_comm_lost);
221 vpncontrol_close_comm(elem);
222 return; // %%%%%% terminate
223 }
224
225 /* sanity check */
226 if (len < sizeof(hdr)) {
227 plog(ASL_LEVEL_ERR,
228 "invalid header length of vpn_control command - len=%ld - expected %ld\n", len, sizeof(hdr));
229 return;
230 }
231
232 elem->read_bytes_len = 0; // Sanity
233 elem->pending_bytes_len = ntohs(hdr.len) + sizeof(hdr);
234
235 /* get buffer to receive */
236 elem->buffer = racoon_malloc(elem->pending_bytes_len);
237 if (elem->buffer == NULL) {
238 plog(ASL_LEVEL_ERR,
239 "failed to alloc buffer for vpn_control command\n");
240 return;
241 }
242 }
243
244 /* get real data */
245 while ((len = recv(elem->sock, elem->buffer + elem->read_bytes_len, elem->pending_bytes_len, 0)) < 0) {
246 if (errno == EINTR)
247 continue;
248 plog(ASL_LEVEL_ERR, "failed to recv vpn_control command: %s\n",
249 strerror(errno));
250 return;
251 }
252
253 if (len == 0) {
254 plog(ASL_LEVEL_NOTICE, "vpn_control socket closed by peer while reading packet\n");
255 /* kill all related connections */
256 vpncontrol_disconnect_all(elem, ike_session_stopped_by_controller_comm_lost);
257 vpncontrol_close_comm(elem);
258 return;
259 }
260
261 elem->read_bytes_len += len;
262
263 if (len < elem->pending_bytes_len) {
264 plog(ASL_LEVEL_NOTICE,
265 "received partial vpn_control command - len=%ld - expected %u\n", len, elem->pending_bytes_len);
266 elem->pending_bytes_len -= len;
267 return;
268 } else {
269 (void)vpncontrol_process(elem, elem->buffer, elem->read_bytes_len);
270 free(elem->buffer);
271 elem->buffer = NULL;
272 elem->read_bytes_len = 0;
273 elem->pending_bytes_len = 0;
274 }
275 }
276
277 static int
278 vpncontrol_process(struct vpnctl_socket_elem *elem, char *combuf, size_t combuf_len)
279 {
280 u_int16_t error = 0;
281 struct vpnctl_hdr *hdr = ALIGNED_CAST(struct vpnctl_hdr *)combuf;
282
283 switch (ntohs(hdr->msg_type)) {
284
285 case VPNCTL_CMD_BIND:
286 {
287 if (combuf_len < sizeof(struct vpnctl_cmd_bind)) {
288 plog(ASL_LEVEL_ERR, "invalid header length for vpnctl bind cmd - len=%ld - expected %ld\n", combuf_len, sizeof(struct vpnctl_cmd_bind));
289 error = -1;
290 break;
291 }
292
293 struct vpnctl_cmd_bind *pkt = ALIGNED_CAST(struct vpnctl_cmd_bind *)combuf;
294 struct bound_addr *addr;
295
296 if (combuf_len < (sizeof(struct vpnctl_cmd_bind) + ntohs(pkt->vers_len))) {
297 plog(ASL_LEVEL_ERR, "invalid length for vpnctl bind cmd - len=%ld - expected %ld\n", combuf_len, (sizeof(struct vpnctl_cmd_bind) + ntohs(pkt->vers_len)));
298 error = -1;
299 break;
300 }
301
302 plog(ASL_LEVEL_NOTICE,
303 "received bind command on vpn control socket.\n");
304 addr = racoon_calloc(1, sizeof(struct bound_addr));
305 if (addr == NULL) {
306 plog(ASL_LEVEL_ERR,
307 "memory error: %s\n", strerror(errno));
308 error = -1;
309 break;
310 }
311 if (ntohs(pkt->vers_len)) {
312 addr->version = vmalloc(ntohs(pkt->vers_len));
313 if (addr->version == NULL) {
314 plog(ASL_LEVEL_ERR,
315 "memory error: %s\n", strerror(errno));
316 error = -1;
317 racoon_free(addr);
318 break;
319 }
320 memcpy(addr->version->v, pkt + 1, ntohs(pkt->vers_len));
321 }
322 addr->address = pkt->address;
323 LIST_INSERT_HEAD(&elem->bound_addresses, addr, chain);
324 lcconf->auto_exit_state |= LC_AUTOEXITSTATE_CLIENT; /* client side */
325 }
326 break;
327
328 case VPNCTL_CMD_UNBIND:
329 {
330 if (combuf_len < sizeof(struct vpnctl_cmd_unbind)) {
331 plog(ASL_LEVEL_ERR, "invalid header length for vpnctl unbind cmd - len=%ld - expected %ld\n", combuf_len, sizeof(struct vpnctl_cmd_unbind));
332 error = -1;
333 break;
334 }
335
336 struct vpnctl_cmd_unbind *pkt = ALIGNED_CAST(struct vpnctl_cmd_unbind *)combuf;
337 struct bound_addr *addr;
338 struct bound_addr *t_addr;
339
340 plog(ASL_LEVEL_NOTICE,
341 "received unbind command on vpn control socket.\n");
342 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
343 if (pkt->address == 0xFFFFFFFF ||
344 pkt->address == addr->address) {
345 flushsainfo_dynamic(addr->address);
346 LIST_REMOVE(addr, chain);
347 if (addr->version)
348 vfree(addr->version);
349 racoon_free(addr);
350 }
351 }
352 }
353 break;
354
355 case VPNCTL_CMD_REDIRECT:
356 {
357 if (combuf_len < sizeof(struct vpnctl_cmd_redirect)) {
358 plog(ASL_LEVEL_ERR, "invalid header length for vpnctl redirect cmd - len=%ld - expected %ld\n", combuf_len, sizeof(struct vpnctl_cmd_redirect));
359 error = -1;
360 break;
361 }
362
363 struct vpnctl_cmd_redirect *redirect_msg = ALIGNED_CAST(struct vpnctl_cmd_redirect *)combuf;
364 struct redirect *raddr;
365 struct redirect *t_raddr;
366 int found = 0;
367
368 plog(ASL_LEVEL_NOTICE,
369 "received redirect command on vpn control socket - address = %x.\n", ntohl(redirect_msg->redirect_address));
370
371 LIST_FOREACH_SAFE(raddr, &lcconf->redirect_addresses, chain, t_raddr) {
372 if (raddr->cluster_address == redirect_msg->address) {
373 if (redirect_msg->redirect_address == 0) {
374 LIST_REMOVE(raddr, chain);
375 racoon_free(raddr);
376 } else {
377 raddr->redirect_address = redirect_msg->redirect_address;
378 raddr->force = ntohs(redirect_msg->force);
379 }
380 found = 1;
381 break;
382 }
383 }
384 if (!found) {
385 raddr = racoon_malloc(sizeof(struct redirect));
386 if (raddr == NULL) {
387 plog(ASL_LEVEL_ERR,
388 "cannot allcoate memory for redirect address.\n");
389 error = -1;
390 break;
391 }
392 raddr->cluster_address = redirect_msg->address;
393 raddr->redirect_address = redirect_msg->redirect_address;
394 raddr->force = ntohs(redirect_msg->force);
395 LIST_INSERT_HEAD(&lcconf->redirect_addresses, raddr, chain);
396
397 }
398 }
399 break;
400
401 case VPNCTL_CMD_PING:
402 break; /* just reply for now */
403
404 case VPNCTL_CMD_XAUTH_INFO:
405 {
406 if (combuf_len < sizeof(struct vpnctl_cmd_xauth_info)) {
407 plog(ASL_LEVEL_ERR, "invalid header length for vpnctl xauth info cmd - len=%ld - expected %ld\n", combuf_len, sizeof(struct vpnctl_cmd_xauth_info));
408 error = -1;
409 break;
410 }
411
412 struct vpnctl_cmd_xauth_info *pkt = ALIGNED_CAST(struct vpnctl_cmd_xauth_info *)combuf;
413 struct bound_addr *addr;
414 struct bound_addr *t_addr;
415 void *attr_list;
416
417 if (combuf_len < (sizeof(struct vpnctl_cmd_xauth_info) + ntohs(pkt->hdr.len) - sizeof(u_int32_t))) {
418 plog(ASL_LEVEL_ERR, "invalid length for vpnctl xauth info cmd - len=%ld - expected %ld\n", combuf_len, (sizeof(struct vpnctl_cmd_xauth_info) + ntohs(pkt->hdr.len) - sizeof(u_int32_t)));
419 error = -1;
420 break;
421 }
422
423 plog(ASL_LEVEL_NOTICE,
424 "received xauth info command vpn control socket.\n");
425 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
426 if (pkt->address == addr->address) {
427 /* reply to the last xauth request */
428 attr_list = pkt + 1;
429 error = vpn_xauth_reply(pkt->address, attr_list, ntohs(pkt->hdr.len) - sizeof(u_int32_t));
430 break;
431 }
432 }
433 }
434 break;
435
436 case VPNCTL_CMD_SET_NAT64_PREFIX:
437 {
438 if (combuf_len < sizeof(struct vpnctl_cmd_set_nat64_prefix)) {
439 plog(ASL_LEVEL_ERR, "invalid header length for vpnctl nat64 prefix cmd - len=%ld - expected %ld\n", combuf_len, sizeof(struct vpnctl_cmd_set_nat64_prefix));
440 error = -1;
441 break;
442 }
443
444 struct vpnctl_cmd_set_nat64_prefix *pkt = ALIGNED_CAST(struct vpnctl_cmd_set_nat64_prefix *)combuf;
445 struct bound_addr *addr;
446 struct bound_addr *t_addr;
447
448 plog(ASL_LEVEL_NOTICE,
449 "received set v6 prefix of len %u command on vpn control socket, adding to all addresses.\n", pkt->nat64_prefix.length);
450 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
451 memcpy(&addr->nat64_prefix, &pkt->nat64_prefix, sizeof(addr->nat64_prefix));
452 }
453 }
454 break;
455
456 case VPNCTL_CMD_CONNECT:
457 {
458 if (combuf_len < sizeof(struct vpnctl_cmd_connect)) {
459 plog(ASL_LEVEL_ERR, "invalid header length for vpnctl connect cmd - len=%ld - expected %ld\n", combuf_len, sizeof(struct vpnctl_cmd_connect));
460 error = -1;
461 break;
462 }
463
464 struct vpnctl_cmd_connect *pkt = ALIGNED_CAST(struct vpnctl_cmd_connect *)combuf;
465 struct bound_addr *addr;
466 struct bound_addr *t_addr;
467
468 if (pending_signal_handle) {
469 /*
470 * This check is done to ensure that a SIGUSR1 signal to re-read the configuration file
471 * is completed before calling a connect. This is to fix the issue seen in (rdar://problem/25641686)
472 */
473 check_sigreq();
474 pending_signal_handle = 0;
475 }
476
477 plog(ASL_LEVEL_NOTICE,
478 "received connect command on vpn control socket.\n");
479 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
480 if (pkt->address == addr->address) {
481 /* start the connection */
482 error = vpn_connect(addr, VPN_STARTED_BY_API);
483 break;
484 }
485 }
486 }
487 break;
488
489 case VPNCTL_CMD_DISCONNECT:
490 {
491 if (combuf_len < sizeof(struct vpnctl_cmd_connect)) {
492 plog(ASL_LEVEL_ERR, "invalid header length for vpnctl disconnect cmd - len=%ld - expected %ld\n", combuf_len, sizeof(struct vpnctl_cmd_connect));
493 error = -1;
494 break;
495 }
496
497 struct vpnctl_cmd_connect *pkt = ALIGNED_CAST(struct vpnctl_cmd_connect *)combuf;
498 struct bound_addr *addr;
499 struct bound_addr *t_addr;
500
501 plog(ASL_LEVEL_NOTICE,
502 "received disconnect command on vpn control socket.\n");
503 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
504 if (pkt->address == addr->address) {
505 /* stop the connection */
506 error = vpn_disconnect(addr, ike_session_stopped_by_vpn_disconnect);
507 break;
508 }
509 }
510 }
511 break;
512
513 case VPNCTL_CMD_START_PH2:
514 {
515 if (combuf_len < sizeof(struct vpnctl_cmd_start_ph2)) {
516 plog(ASL_LEVEL_ERR, "invalid header length for vpnctl start ph2 cmd - len=%ld - expected %ld\n", combuf_len, sizeof(struct vpnctl_cmd_start_ph2));
517 error = -1;
518 break;
519 }
520
521 struct vpnctl_cmd_start_ph2 *pkt = ALIGNED_CAST(struct vpnctl_cmd_start_ph2 *)combuf;
522 struct bound_addr *addr;
523 struct bound_addr *t_addr;
524
525 plog(ASL_LEVEL_NOTICE, "received start_ph2 command on vpn control socket.\n");
526 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
527 if (pkt->address == addr->address) {
528 /* start the connection */
529 error = vpn_start_ph2(addr, pkt, combuf_len);
530 break;
531 }
532 }
533 }
534 break;
535
536 case VPNCTL_CMD_START_DPD:
537 {
538 if (combuf_len < sizeof(struct vpnctl_cmd_start_dpd)) {
539 plog(ASL_LEVEL_ERR, "invalid header length for vpnctl start dpd cmd - len=%ld - expected %ld\n", combuf_len, sizeof(struct vpnctl_cmd_start_dpd));
540 error = -1;
541 break;
542 }
543
544 struct vpnctl_cmd_start_dpd *pkt = ALIGNED_CAST(struct vpnctl_cmd_start_dpd *)combuf;
545 struct bound_addr *srv;
546 struct bound_addr *t_addr;
547
548 plog(ASL_LEVEL_NOTICE,
549 "received start_dpd command on vpn control socket.\n");
550 LIST_FOREACH_SAFE(srv, &elem->bound_addresses, chain, t_addr) {
551 if (pkt->address == srv->address) {
552 union { // Wcast-align fix - force alignment
553 struct sockaddr_storage ss;
554 struct sockaddr_in addr_in;
555 } daddr;
556
557 bzero(&daddr, sizeof(struct sockaddr_in));
558 daddr.addr_in.sin_len = sizeof(struct sockaddr_in);
559 daddr.addr_in.sin_addr.s_addr = srv->address;
560 daddr.addr_in.sin_port = 0;
561 daddr.addr_in.sin_family = AF_INET;
562
563 /* start the dpd */
564 error = ike_session_ph1_force_dpd(&daddr.ss);
565 break;
566 }
567 }
568 }
569 break;
570
571 case VPNCTL_CMD_ASSERT:
572 {
573 if (combuf_len < sizeof(struct vpnctl_cmd_assert)) {
574 plog(ASL_LEVEL_ERR, "invalid header length for vpnctl assert cmd - len=%ld - expected %ld\n", combuf_len, sizeof(struct vpnctl_cmd_assert));
575 error = -1;
576 break;
577 }
578
579 struct vpnctl_cmd_assert *pkt = ALIGNED_CAST(struct vpnctl_cmd_assert *)combuf;
580 // struct bound_addr *addr;
581 // struct bound_addr *t_addr;
582 struct sockaddr_in saddr;
583 struct sockaddr_in daddr;
584
585 plogdump(ASL_LEVEL_NOTICE, pkt, ntohs(hdr->len) + sizeof(struct vpnctl_hdr), "received assert command on vpn control socket.\n");
586 // LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
587 // if (pkt->dst_address == addr->address) {
588 bzero(&saddr, sizeof(saddr));
589 saddr.sin_len = sizeof(saddr);
590 saddr.sin_addr.s_addr = pkt->src_address;
591 saddr.sin_port = 0;
592 saddr.sin_family = AF_INET;
593 bzero(&daddr, sizeof(daddr));
594 daddr.sin_len = sizeof(daddr);
595 daddr.sin_addr.s_addr = pkt->dst_address;
596 daddr.sin_port = 0;
597 daddr.sin_family = AF_INET;
598
599 error = vpn_assert(ALIGNED_CAST(struct sockaddr_storage *)&saddr, ALIGNED_CAST(struct sockaddr_storage *)&daddr);
600 break;
601 // }
602 // }
603 }
604 break;
605
606 case VPNCTL_CMD_RECONNECT:
607 {
608 if (combuf_len < sizeof(struct vpnctl_cmd_connect)) {
609 plog(ASL_LEVEL_ERR, "invalid header length for vpnctl reconnect cmd - len=%ld - expected %ld\n", combuf_len, sizeof(struct vpnctl_cmd_connect));
610 error = -1;
611 break;
612 }
613
614 struct vpnctl_cmd_connect *pkt = ALIGNED_CAST(struct vpnctl_cmd_connect *)combuf;
615 struct bound_addr *addr;
616 struct bound_addr *t_addr;
617
618 plog(ASL_LEVEL_NOTICE,
619 "received reconnect command on vpn control socket.\n");
620 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
621 if (pkt->address == addr->address) {
622 /* start the connection */
623 error = vpn_connect(addr, VPN_RESTARTED_BY_API);
624 break;
625 }
626 }
627 }
628 break;
629
630 default:
631 plog(ASL_LEVEL_ERR,
632 "invalid command: %d\n", ntohs(hdr->msg_type));
633 error = -1; // for now
634 break;
635 }
636
637 hdr->len = 0;
638 hdr->result = htons(error);
639 if (vpncontrol_reply(elem->sock, combuf) < 0)
640 return -1;
641
642 return 0;
643
644 }
645
646 static int
647 vpncontrol_reply(int so, char *combuf)
648 {
649 ssize_t tlen;
650
651 tlen = send(so, combuf, sizeof(struct vpnctl_hdr), 0);
652 if (tlen < 0) {
653 plog(ASL_LEVEL_ERR,
654 "failed to send vpn_control message: %s\n", strerror(errno));
655 return -1;
656 }
657
658 return 0;
659 }
660
661 bool
662 vpncontrol_set_nat64_prefix(nw_nat64_prefix_t *prefix)
663 {
664 struct vpnctl_socket_elem *sock_elem;
665 struct bound_addr *bound_addr;
666
667 LIST_FOREACH(sock_elem, &lcconf->vpnctl_comm_socks, chain) {
668 LIST_FOREACH(bound_addr, &sock_elem->bound_addresses, chain) {
669 if (bound_addr->nat64_prefix.length != 0) {
670 memcpy(prefix, &bound_addr->nat64_prefix, sizeof(*prefix));
671 return true;
672 }
673 }
674 }
675 return false;
676 }
677
678 int
679 vpncontrol_notify_need_authinfo(phase1_handle_t *iph1, void* attr_list, size_t attr_len)
680 {
681 struct vpnctl_status_need_authinfo *msg = NULL;
682 struct vpnctl_socket_elem *sock_elem;
683 struct bound_addr *bound_addr;
684 size_t msg_size;
685 ssize_t tlen;
686 u_int32_t address;
687 void *ptr;
688
689 if (!iph1)
690 goto end;
691
692 plog(ASL_LEVEL_NOTICE,
693 "sending vpn_control xauth need info status\n");
694
695 msg = (struct vpnctl_status_need_authinfo *)racoon_malloc(msg_size = sizeof(struct vpnctl_status_need_authinfo) + attr_len);
696 if (msg == NULL) {
697 plog(ASL_LEVEL_ERR,
698 "unable to allocate space for vpn control message.\n");
699 return -1;
700 }
701 msg->hdr.flags = 0;
702
703 address = iph1_get_remote_v4_address(iph1);
704 if (address == 0) {
705 goto end;
706 }
707
708 msg->hdr.cookie = msg->hdr.reserved = msg->hdr.result = 0;
709 msg->hdr.len = htons((msg_size) - sizeof(struct vpnctl_hdr));
710 if (!ike_session_is_client_ph1_rekey(iph1)) {
711 msg->hdr.msg_type = htons(VPNCTL_STATUS_NEED_AUTHINFO);
712 } else {
713 msg->hdr.msg_type = htons(VPNCTL_STATUS_NEED_REAUTHINFO);
714 }
715 msg->address = iph1_get_remote_v4_address(iph1);
716 ptr = msg + 1;
717 memcpy(ptr, attr_list, attr_len);
718
719 LIST_FOREACH(sock_elem, &lcconf->vpnctl_comm_socks, chain) {
720 LIST_FOREACH(bound_addr, &sock_elem->bound_addresses, chain) {
721 if (bound_addr->address == 0xFFFFFFFF ||
722 bound_addr->address == address) {
723 plog(ASL_LEVEL_DEBUG, "vpn control writing %zu bytes\n", msg_size);
724 tlen = send(sock_elem->sock, msg, msg_size, 0);
725 if (tlen < 0) {
726 plog(ASL_LEVEL_ERR,
727 "failed to send vpn_control need authinfo status: %s\n", strerror(errno));
728 }
729 break;
730 }
731 }
732 }
733
734 end:
735 if (msg)
736 racoon_free(msg);
737 return 0;
738 }
739
740 int
741 vpncontrol_notify_ike_failed(u_int16_t notify_code, u_int16_t from, u_int32_t address, u_int16_t data_len, u_int8_t *data)
742 {
743 struct vpnctl_status_failed *msg = NULL;
744 struct vpnctl_socket_elem *sock_elem;
745 struct bound_addr *bound_addr;
746 size_t len;
747 ssize_t tlen;
748
749 len = sizeof(struct vpnctl_status_failed) + data_len;
750
751 msg = (struct vpnctl_status_failed *)racoon_malloc(len);
752 if (msg == NULL) {
753 plog(ASL_LEVEL_ERR,
754 "unable to allcate memory for vpn control status message.\n");
755 return -1;
756 }
757
758 msg->hdr.msg_type = htons(VPNCTL_STATUS_IKE_FAILED);
759 msg->hdr.flags = msg->hdr.cookie = msg->hdr.reserved = msg->hdr.result = 0;
760 msg->hdr.len = htons(len - sizeof(struct vpnctl_hdr));
761 msg->address = address;
762 msg->ike_code = htons(notify_code);
763 msg->from = htons(from);
764 if (data_len > 0)
765 memcpy(msg->data, data, data_len);
766 plog(ASL_LEVEL_ERR,
767 "sending vpn_control ike failed message - code=%d from=%s.\n", notify_code,
768 (from == FROM_LOCAL ? "local" : "remote"));
769
770 LIST_FOREACH(sock_elem, &lcconf->vpnctl_comm_socks, chain) {
771 LIST_FOREACH(bound_addr, &sock_elem->bound_addresses, chain) {
772 if (bound_addr->address == 0xFFFFFFFF ||
773 bound_addr->address == address) {
774 tlen = send(sock_elem->sock, msg, len, 0);
775 if (tlen < 0) {
776 plog(ASL_LEVEL_ERR,
777 "Unable to send vpn_control ike notify failed: %s\n", strerror(errno));
778 } else {
779 plog(ASL_LEVEL_DEBUG,
780 "Sent %zd/%zu bytes\n", tlen, len);
781 }
782 break;
783 }
784 }
785 }
786
787 if (msg)
788 racoon_free(msg);
789 return 0;
790 }
791
792 char *
793 vpncontrol_status_2_str(u_int16_t msg_type)
794 {
795 switch (msg_type) {
796 case VPNCTL_STATUS_IKE_FAILED:
797 return "IKE failed";
798 case VPNCTL_STATUS_PH1_START_US:
799 return "Phase 1 started by us";
800 case VPNCTL_STATUS_PH1_START_PEER:
801 return "Phase 1 started by peer";
802 case VPNCTL_STATUS_PH1_ESTABLISHED:
803 return "Phase 1 established";
804 case VPNCTL_STATUS_PH2_START:
805 return "Phase 2 started";
806 case VPNCTL_STATUS_PH2_ESTABLISHED:
807 return "Phase 2 established";
808 case VPNCTL_STATUS_NEED_AUTHINFO:
809 return "Need authentication info";
810 case VPNCTL_STATUS_NEED_REAUTHINFO:
811 return "Need re-authentication info";
812 default:
813 return "";
814 }
815 }
816
817
818 int
819 vpncontrol_notify_phase_change(int start, u_int16_t from, phase1_handle_t *iph1, phase2_handle_t *iph2)
820 {
821 struct vpnctl_status_phase_change *msg;
822 struct vpnctl_socket_elem *sock_elem;
823 struct bound_addr *bound_addr;
824 ssize_t tlen;
825 size_t msg_size;
826 u_int32_t address;
827
828 if (iph1 && !start && iph1->mode_cfg && iph1->mode_cfg->xauth.status != XAUTHST_OK) {
829 if (vpn_get_config(iph1, &msg, &msg_size) == 1)
830 return 0; /* mode config not finished yet */
831 } else {
832 msg = racoon_malloc(msg_size = sizeof(struct vpnctl_status_phase_change));
833 msg->hdr.flags = 0;
834 }
835
836 if (msg == NULL) {
837 plog(ASL_LEVEL_ERR,
838 "unable to allocate space for vpn control message.\n");
839 return -1;
840 }
841 if (iph1) {
842 address = iph1_get_remote_v4_address(iph1);
843 if (address == 0) {
844 plog(ASL_LEVEL_ERR, "bad address for ph1 status change.\n");
845 goto end;
846 }
847 msg->hdr.msg_type = htons(start ?
848 (from == FROM_LOCAL ? VPNCTL_STATUS_PH1_START_US : VPNCTL_STATUS_PH1_START_PEER)
849 : VPNCTL_STATUS_PH1_ESTABLISHED);
850 // TODO: indicate version
851 } else {
852 address = iph2_get_remote_v4_address(iph2);
853 if (address == 0) {
854 plog(ASL_LEVEL_ERR, "bad address for ph2 status change.\n");
855 goto end;
856 }
857 msg->hdr.msg_type = htons(start ? VPNCTL_STATUS_PH2_START : VPNCTL_STATUS_PH2_ESTABLISHED);
858 // TODO: indicate version
859 }
860 plog(ASL_LEVEL_NOTICE,
861 ">>>>> phase change status = %s\n", vpncontrol_status_2_str(ntohs(msg->hdr.msg_type)));
862
863 msg->hdr.cookie = msg->hdr.reserved = msg->hdr.result = 0;
864 msg->hdr.len = htons((msg_size) - sizeof(struct vpnctl_hdr));
865 msg->address = address;
866
867 LIST_FOREACH(sock_elem, &lcconf->vpnctl_comm_socks, chain) {
868 LIST_FOREACH(bound_addr, &sock_elem->bound_addresses, chain) {
869 if (bound_addr->address == 0xFFFFFFFF ||
870 bound_addr->address == address) {
871 plog(ASL_LEVEL_DEBUG, "vpn control writing %zu bytes\n", msg_size);
872 tlen = send(sock_elem->sock, msg, msg_size, 0);
873 if (tlen < 0) {
874 plog(ASL_LEVEL_ERR,
875 "failed to send vpn_control phase change status: %s\n", strerror(errno));
876 }
877 break;
878 }
879 }
880 }
881
882 end:
883 if (msg)
884 racoon_free(msg);
885 return 0;
886 }
887
888 static int
889 vpncontrol_notify_peer_resp (u_int16_t notify_code, u_int32_t address)
890 {
891 struct vpnctl_status_peer_resp msg;
892 struct vpnctl_socket_elem *sock_elem;
893 struct bound_addr *bound_addr;
894 ssize_t tlen;
895 int rc = -1;
896
897 bzero(&msg, sizeof(msg));
898 msg.hdr.msg_type = htons(VPNCTL_STATUS_PEER_RESP);
899 msg.hdr.cookie = msg.hdr.reserved = msg.hdr.result = 0;
900 msg.hdr.len = htons(sizeof(msg) - sizeof(msg.hdr));
901 msg.address = address;
902 msg.ike_code = notify_code;
903 plog(ASL_LEVEL_NOTICE,
904 "sending vpn_control status (peer response) message - code=%d addr=%x.\n", notify_code, address);
905
906 LIST_FOREACH(sock_elem, &lcconf->vpnctl_comm_socks, chain) {
907 LIST_FOREACH(bound_addr, &sock_elem->bound_addresses, chain) {
908 if (bound_addr->address == 0xFFFFFFFF ||
909 bound_addr->address == address) {
910 tlen = send(sock_elem->sock, &msg, sizeof(msg), 0);
911 if (tlen < 0) {
912 plog(ASL_LEVEL_ERR,
913 "unable to send vpn_control status (peer response): %s\n", strerror(errno));
914 } else {
915 rc = 0;
916 }
917 break;
918 }
919 }
920 }
921
922 return rc;
923 }
924
925 int
926 vpncontrol_notify_peer_resp_ph1 (u_int16_t notify_code, phase1_handle_t *iph1)
927 {
928 if (iph1 && iph1->parent_session && iph1->parent_session->controller_awaiting_peer_resp) {
929 int rc;
930 if ((rc = vpncontrol_notify_peer_resp(notify_code, iph1_get_remote_v4_address(iph1))) == 0) {
931 iph1->parent_session->controller_awaiting_peer_resp = 0;
932 }
933 return rc;
934 } else {
935 return 0;
936 }
937 }
938
939 int
940 vpncontrol_notify_peer_resp_ph2 (u_int16_t notify_code, phase2_handle_t *iph2)
941 {
942 if (iph2 && iph2->parent_session && iph2->parent_session->controller_awaiting_peer_resp) {
943 int rc;
944 if ((rc = vpncontrol_notify_peer_resp(notify_code, iph2_get_remote_v4_address(iph2))) == 0) {
945 iph2->parent_session->controller_awaiting_peer_resp = 0;
946 }
947 return rc;
948 } else {
949 return 0;
950 }
951 }
952
953 int
954 vpncontrol_init(void)
955 {
956 int sock;
957
958 if (vpncontrolsock_path == NULL) {
959 lcconf->sock_vpncontrol = -1;
960 return 0;
961 }
962
963 if ( (lcconf->sock_vpncontrol = checklaunchd()) == 0 ) {
964 memset(&sunaddr, 0, sizeof(sunaddr));
965 sunaddr.sun_family = AF_UNIX;
966 snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path),
967 "%s", vpncontrolsock_path);
968
969 lcconf->sock_vpncontrol = socket(AF_UNIX, SOCK_STREAM, 0);
970 if (lcconf->sock_vpncontrol == -1) {
971 plog(ASL_LEVEL_ERR,
972 "socket: %s\n", strerror(errno));
973 return -1;
974 }
975
976 if (fcntl(lcconf->sock_vpncontrol, F_SETFL, O_NONBLOCK) == -1) {
977 plog(ASL_LEVEL_ERR, "failed to put VPN-Control socket in non-blocking mode\n");
978 }
979
980 unlink(sunaddr.sun_path);
981 if (bind(lcconf->sock_vpncontrol, (struct sockaddr *)&sunaddr,
982 sizeof(sunaddr)) != 0) {
983 plog(ASL_LEVEL_ERR,
984 "bind(sockname:%s): %s\n",
985 sunaddr.sun_path, strerror(errno));
986 (void)close(lcconf->sock_vpncontrol);
987 return -1;
988 }
989
990 if (chown(sunaddr.sun_path, vpncontrolsock_owner, vpncontrolsock_group) != 0) {
991 plog(ASL_LEVEL_ERR,
992 "chown(%s, %d, %d): %s\n",
993 sunaddr.sun_path, vpncontrolsock_owner,
994 vpncontrolsock_group, strerror(errno));
995 (void)close(lcconf->sock_vpncontrol);
996 return -1;
997 }
998
999 if (chmod(sunaddr.sun_path, vpncontrolsock_mode) != 0) {
1000 plog(ASL_LEVEL_ERR,
1001 "chmod(%s, 0%03o): %s\n",
1002 sunaddr.sun_path, vpncontrolsock_mode, strerror(errno));
1003 (void)close(lcconf->sock_vpncontrol);
1004 return -1;
1005 }
1006
1007 if (listen(lcconf->sock_vpncontrol, 5) != 0) {
1008 plog(ASL_LEVEL_ERR,
1009 "listen(sockname:%s): %s\n",
1010 sunaddr.sun_path, strerror(errno));
1011 (void)close(lcconf->sock_vpncontrol);
1012 return -1;
1013 }
1014 plog(ASL_LEVEL_NOTICE,
1015 "opened %s as racoon management.\n", sunaddr.sun_path);
1016 }
1017 lcconf->vpncontrol_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, lcconf->sock_vpncontrol, 0, dispatch_get_main_queue());
1018 if (lcconf->vpncontrol_source == NULL) {
1019 plog(ASL_LEVEL_ERR, "could not create vpncontrol socket source.");
1020 return -1;
1021 }
1022 dispatch_source_set_event_handler_f(lcconf->vpncontrol_source, vpncontrol_handler);
1023 sock = lcconf->sock_vpncontrol;
1024 dispatch_source_set_cancel_handler(lcconf->vpncontrol_source,
1025 ^{
1026 close(sock);
1027 });
1028 dispatch_resume(lcconf->vpncontrol_source);
1029 return 0;
1030 }
1031
1032 void
1033 vpncontrol_disconnect_all(struct vpnctl_socket_elem *elem, const char *reason)
1034 {
1035 struct bound_addr *addr;
1036 struct bound_addr *t_addr;
1037
1038 plog(ASL_LEVEL_NOTICE,
1039 "received disconnect all command.\n");
1040
1041 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
1042 /* stop any connections */
1043 vpn_disconnect(addr, reason);
1044 }
1045 }
1046
1047 void
1048 vpncontrol_close()
1049 {
1050 struct vpnctl_socket_elem *elem;
1051 struct vpnctl_socket_elem *t_elem;
1052
1053 plog(ASL_LEVEL_NOTICE,
1054 "vpncontrol_close.\n");
1055
1056 dispatch_source_cancel(lcconf->vpncontrol_source);
1057 lcconf->vpncontrol_source = NULL;
1058
1059 lcconf->sock_vpncontrol = -1;
1060 LIST_FOREACH_SAFE(elem, &lcconf->vpnctl_comm_socks, chain, t_elem)
1061 vpncontrol_close_comm(elem);
1062 }
1063
1064 static void
1065 vpncontrol_close_comm(struct vpnctl_socket_elem *elem)
1066 {
1067 struct bound_addr *addr;
1068 struct bound_addr *t_addr;
1069
1070 plog(ASL_LEVEL_NOTICE,
1071 "vpncontrol_close_comm.\n");
1072
1073 LIST_REMOVE(elem, chain);
1074 if (elem->sock != -1) {
1075 dispatch_source_cancel(elem->source);
1076 elem->sock = -1;
1077 }
1078 if (elem->buffer != NULL) {
1079 free(elem->buffer);
1080 elem->buffer = NULL;
1081 elem->pending_bytes_len = 0;
1082 elem->read_bytes_len = 0;
1083 }
1084 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
1085 flushsainfo_dynamic(addr->address);
1086 LIST_REMOVE(addr, chain);
1087 if (addr->version)
1088 vfree(addr->version);
1089 racoon_free(addr);
1090 }
1091 racoon_free(elem);
1092 check_auto_exit();
1093
1094 }
1095
1096 int
1097 vpn_control_connected(void)
1098 {
1099 if (LIST_EMPTY(&lcconf->vpnctl_comm_socks))
1100 return 0;
1101 else
1102 return 1;
1103 }
1104
1105 #endif