]> git.saurik.com Git - apple/ipsec.git/blob - ipsec-tools/racoon/vpn_control.c
ipsec-292.40.4.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 //#define LION_TEST 1
55
56
57 #include "config.h"
58
59 #include <sys/types.h>
60 #include <sys/param.h>
61 #include <sys/socket.h>
62 #include <sys/signal.h>
63 #include <sys/stat.h>
64 #include <sys/un.h>
65
66 #include <net/pfkeyv2.h>
67
68 #include <netinet/in.h>
69 #ifndef HAVE_NETINET6_IPSEC
70 #include <netinet/ipsec.h>
71 #else
72 #include <netinet6/ipsec.h>
73 #endif
74
75
76 #include <stdlib.h>
77 #include <stdio.h>
78 #include <string.h>
79 #include <errno.h>
80 #include <netdb.h>
81 #ifdef HAVE_UNISTD_H
82 #include <unistd.h>
83 #endif
84 #include <launch.h>
85 #ifndef LION_TEST
86 #include <launch_priv.h>
87 #endif
88 #include <fcntl.h>
89
90 #include "var.h"
91 #include "misc.h"
92 #include "vmbuf.h"
93 #include "plog.h"
94 #include "sockmisc.h"
95 #include "debug.h"
96
97 #include "schedule.h"
98 #include "localconf.h"
99 #include "remoteconf.h"
100 #include "grabmyaddr.h"
101 #include "isakmp_var.h"
102 #include "isakmp.h"
103 #include "oakley.h"
104 #include "handler.h"
105 #include "pfkey.h"
106 #include "ipsec_doi.h"
107 #include "vpn_control.h"
108 #include "vpn_control_var.h"
109 #include "isakmp_inf.h"
110 #include "session.h"
111 #include "gcmalloc.h"
112 #include "isakmp_cfg.h"
113 #include "sainfo.h"
114
115 #ifdef ENABLE_VPNCONTROL_PORT
116 char *vpncontrolsock_path = VPNCONTROLSOCK_PATH;
117 uid_t vpncontrolsock_owner = 0;
118 gid_t vpncontrolsock_group = 0;
119 mode_t vpncontrolsock_mode = 0600;
120
121 static struct sockaddr_un sunaddr;
122 static int vpncontrol_process (struct vpnctl_socket_elem *, char *);
123 static int vpncontrol_reply (int, char *);
124 static void vpncontrol_close_comm (struct vpnctl_socket_elem *);
125 static int checklaunchd (void);
126 extern int vpn_get_config (phase1_handle_t *, struct vpnctl_status_phase_change **, size_t *);
127 extern int vpn_xauth_reply (u_int32_t, void *, size_t);
128
129
130 int
131 checklaunchd()
132 {
133 launch_data_t checkin_response = NULL;
134 #ifdef LION_TEST
135 launch_data_t checkin_request = NULL;
136 #endif
137 launch_data_t sockets_dict, listening_fd_array;
138 launch_data_t listening_fd;
139 struct sockaddr_storage fdsockaddr;
140 socklen_t fdsockaddrlen = sizeof(fdsockaddr);
141 int socketct;
142 int i;
143 int listenerct;
144 int returnval = 0;
145 int fd;
146
147 /* check in with launchd */
148 #ifdef LION_TEST
149 if ((checkin_request = launch_data_new_string(LAUNCH_KEY_CHECKIN)) == NULL) {
150 #else
151 if ((checkin_response = launch_socket_service_check_in()) == NULL) {
152 #endif
153 plog(ASL_LEVEL_ERR,
154 "failed to launch_socket_service_check_in.\n");
155 goto done;
156 }
157 #ifdef LION_TEST
158 if ((checkin_response = launch_msg(checkin_request)) == NULL) {
159 plog(ASL_LEVEL_ERR, "failed to launch_msg.\n");
160 goto done;
161 }
162 #endif
163 if (LAUNCH_DATA_ERRNO == launch_data_get_type(checkin_response)) {
164 plog(ASL_LEVEL_ERR,
165 "launch_data_get_type error %d\n",
166 launch_data_get_errno(checkin_response));
167 goto done;
168 }
169 if ( (sockets_dict = launch_data_dict_lookup(checkin_response, LAUNCH_JOBKEY_SOCKETS)) == NULL){
170 plog(ASL_LEVEL_ERR,
171 "failed to launch_data_dict_lookup.\n");
172 goto done;
173 }
174 if ( !(socketct = launch_data_dict_get_count(sockets_dict))){
175 plog(ASL_LEVEL_ERR,
176 "launch_data_dict_get_count returns no socket defined.\n");
177 goto done;
178 }
179
180 if ( (listening_fd_array = launch_data_dict_lookup(sockets_dict, "Listeners")) == NULL ){
181 plog(ASL_LEVEL_ERR,
182 "failed to launch_data_dict_lookup.\n");
183 goto done;
184 }
185 listenerct = launch_data_array_get_count(listening_fd_array);
186 for (i = 0; i < listenerct; i++) {
187 listening_fd = launch_data_array_get_index(listening_fd_array, i);
188 fd = launch_data_get_fd( listening_fd );
189 if ( getsockname( fd , (struct sockaddr *)&fdsockaddr, &fdsockaddrlen)){
190 continue;
191 }
192
193 /* Is this the VPN control socket? */
194 if ( fdsockaddr.ss_family == AF_UNIX &&
195 (!(strcmp(vpncontrolsock_path, ((struct sockaddr_un *)&fdsockaddr)->sun_path))))
196 {
197 plog(ASL_LEVEL_INFO,
198 "found launchd socket.\n");
199 returnval = fd;
200 break;
201 }
202 }
203 // TODO: check if we have any leaked fd
204 if ( listenerct == i){
205 plog(ASL_LEVEL_ERR,
206 "failed to find launchd socket\n");
207 returnval = 0;
208 }
209
210 done:
211 if (checkin_response)
212 launch_data_free(checkin_response);
213 return(returnval);
214 }
215
216
217 void
218 vpncontrol_handler(void *unused)
219 {
220 struct sockaddr_storage from;
221 socklen_t fromlen = sizeof(from);
222 int sock;
223
224 struct vpnctl_socket_elem *sock_elem;
225
226
227 sock_elem = racoon_malloc(sizeof(struct vpnctl_socket_elem));
228 if (sock_elem == NULL) {
229 plog(ASL_LEVEL_ERR,
230 "memory error: %s\n", strerror(errno));
231 return; //%%%%%% terminate
232 }
233 LIST_INIT(&sock_elem->bound_addresses);
234
235 sock_elem->sock = accept(lcconf->sock_vpncontrol, (struct sockaddr *)&from, &fromlen);
236 if (sock_elem->sock < 0) {
237 plog(ASL_LEVEL_ERR,
238 "failed to accept vpn_control command: %s\n", strerror(errno));
239 racoon_free(sock_elem);
240 return; //%%%%% terminate
241 }
242 LIST_INSERT_HEAD(&lcconf->vpnctl_comm_socks, sock_elem, chain);
243
244 sock_elem->source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, sock_elem->sock, 0, dispatch_get_main_queue());
245 if (sock_elem->source == NULL) {
246 plog(ASL_LEVEL_ERR, "could not create comm socket source.");
247 racoon_free(sock_elem);
248 return; //%%%%% terminate
249 }
250 dispatch_source_set_event_handler(sock_elem->source,
251 ^{
252 vpncontrol_comm_handler(sock_elem);
253 });
254 sock = sock_elem->sock;
255
256 dispatch_source_t the_source = sock_elem->source;
257 dispatch_source_set_cancel_handler(sock_elem->source,
258 ^{
259 close(sock);
260 dispatch_release(the_source); /* Release the source on cancel */
261 });
262 dispatch_resume(sock_elem->source);
263
264 plog(ASL_LEVEL_NOTICE,
265 "accepted connection on vpn control socket.\n");
266 check_auto_exit();
267
268 return;
269 }
270
271 void
272 vpncontrol_comm_handler(struct vpnctl_socket_elem *elem)
273 {
274 struct vpnctl_hdr hdr;
275 char *combuf = NULL;
276 ssize_t len;
277
278 /* get buffer length */
279 while ((len = recv(elem->sock, (char *)&hdr, sizeof(hdr), MSG_PEEK)) < 0) {
280 if (errno == EINTR)
281 continue;
282 plog(ASL_LEVEL_ERR,
283 "failed to recv vpn_control command: %s\n", strerror(errno));
284 goto end;
285 }
286 if (len == 0) {
287 plog(ASL_LEVEL_DEBUG,
288 "vpn_control socket closed by peer.\n");
289 /* kill all related connections */
290 vpncontrol_disconnect_all(elem, ike_session_stopped_by_controller_comm_lost);
291 vpncontrol_close_comm(elem);
292 return; // %%%%%% terminate
293 }
294
295 /* sanity check */
296 if (len < sizeof(hdr)) {
297 plog(ASL_LEVEL_ERR,
298 "invalid header length of vpn_control command - len=%ld - expected %ld\n", len, sizeof(hdr));
299 goto end;
300 }
301
302 /* get buffer to receive */
303 if ((combuf = racoon_malloc(ntohs(hdr.len) + sizeof(hdr))) == 0) {
304 plog(ASL_LEVEL_ERR,
305 "failed to alloc buffer for vpn_control command\n");
306 goto end;
307 }
308
309 /* get real data */
310 while ((len = recv(elem->sock, combuf, ntohs(hdr.len) + sizeof(hdr), 0)) < 0) {
311 if (errno == EINTR)
312 continue;
313 plog(ASL_LEVEL_ERR,
314 "failed to recv vpn_control command: %s\n",
315 strerror(errno));
316 goto end;
317 }
318
319 (void)vpncontrol_process(elem, combuf);
320
321 end:
322 if (combuf)
323 racoon_free(combuf);
324 return;
325 }
326
327 static int
328 vpncontrol_process(struct vpnctl_socket_elem *elem, char *combuf)
329 {
330 u_int16_t error = 0;
331 struct vpnctl_hdr *hdr = ALIGNED_CAST(struct vpnctl_hdr *)combuf;
332
333 switch (ntohs(hdr->msg_type)) {
334
335 case VPNCTL_CMD_BIND:
336 {
337 struct vpnctl_cmd_bind *pkt = ALIGNED_CAST(struct vpnctl_cmd_bind *)combuf;
338 struct bound_addr *addr;
339
340 plog(ASL_LEVEL_DEBUG,
341 "received bind command on vpn control socket.\n");
342 addr = racoon_calloc(1, sizeof(struct bound_addr));
343 if (addr == NULL) {
344 plog(ASL_LEVEL_ERR,
345 "memory error: %s\n", strerror(errno));
346 error = -1;
347 break;
348 }
349 if (ntohs(pkt->vers_len)) {
350 addr->version = vmalloc(ntohs(pkt->vers_len));
351 if (addr->version == NULL) {
352 plog(ASL_LEVEL_ERR,
353 "memory error: %s\n", strerror(errno));
354 error = -1;
355 break;
356 }
357 memcpy(addr->version->v, pkt + 1, ntohs(pkt->vers_len));
358 }
359 addr->address = pkt->address;
360 LIST_INSERT_HEAD(&elem->bound_addresses, addr, chain);
361 lcconf->auto_exit_state |= LC_AUTOEXITSTATE_CLIENT; /* client side */
362 }
363 break;
364
365 case VPNCTL_CMD_UNBIND:
366 {
367 struct vpnctl_cmd_unbind *pkt = ALIGNED_CAST(struct vpnctl_cmd_unbind *)combuf;
368 struct bound_addr *addr;
369 struct bound_addr *t_addr;
370
371 plog(ASL_LEVEL_DEBUG,
372 "received unbind command on vpn control socket.\n");
373 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
374 if (pkt->address == 0xFFFFFFFF ||
375 pkt->address == addr->address) {
376 flushsainfo_dynamic(addr->address);
377 LIST_REMOVE(addr, chain);
378 if (addr->version)
379 vfree(addr->version);
380 racoon_free(addr);
381 }
382 }
383 }
384 break;
385
386 case VPNCTL_CMD_REDIRECT:
387 {
388 struct vpnctl_cmd_redirect *redirect_msg = ALIGNED_CAST(struct vpnctl_cmd_redirect *)combuf;
389 struct redirect *raddr;
390 struct redirect *t_raddr;
391 int found = 0;
392
393 plog(ASL_LEVEL_DEBUG,
394 "received redirect command on vpn control socket - address = %x.\n", ntohl(redirect_msg->redirect_address));
395
396 LIST_FOREACH_SAFE(raddr, &lcconf->redirect_addresses, chain, t_raddr) {
397 if (raddr->cluster_address == redirect_msg->address) {
398 if (redirect_msg->redirect_address == 0) {
399 LIST_REMOVE(raddr, chain);
400 racoon_free(raddr);
401 } else {
402 raddr->redirect_address = redirect_msg->redirect_address;
403 raddr->force = ntohs(redirect_msg->force);
404 }
405 found = 1;
406 break;
407 }
408 }
409 if (!found) {
410 raddr = racoon_malloc(sizeof(struct redirect));
411 if (raddr == NULL) {
412 plog(ASL_LEVEL_DEBUG,
413 "cannot allcoate memory for redirect address.\n");
414 error = -1;
415 break;
416 }
417 raddr->cluster_address = redirect_msg->address;
418 raddr->redirect_address = redirect_msg->redirect_address;
419 raddr->force = ntohs(redirect_msg->force);
420 LIST_INSERT_HEAD(&lcconf->redirect_addresses, raddr, chain);
421
422 }
423 }
424 break;
425
426 case VPNCTL_CMD_PING:
427 break; /* just reply for now */
428
429 case VPNCTL_CMD_XAUTH_INFO:
430 {
431 struct vpnctl_cmd_xauth_info *pkt = ALIGNED_CAST(struct vpnctl_cmd_xauth_info *)combuf;
432 struct bound_addr *addr;
433 struct bound_addr *t_addr;
434 void *attr_list;
435
436 plog(ASL_LEVEL_DEBUG,
437 "received xauth info command vpn control socket.\n");
438 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
439 if (pkt->address == addr->address) {
440 /* reply to the last xauth request */
441 attr_list = pkt + 1;
442 error = vpn_xauth_reply(pkt->address, attr_list, ntohs(pkt->hdr.len) - sizeof(u_int32_t));
443 break;
444 }
445 }
446 }
447 break;
448
449 case VPNCTL_CMD_SET_NAT64_PREFIX:
450 {
451 struct vpnctl_cmd_set_nat64_prefix *pkt = ALIGNED_CAST(struct vpnctl_cmd_set_nat64_prefix *)combuf;
452 struct bound_addr *addr;
453 struct bound_addr *t_addr;
454
455 plog(ASL_LEVEL_DEBUG,
456 "received set v6 prefix of len %u command on vpn control socket, adding to all addresses.\n", pkt->nat64_prefix.length);
457 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
458 memcpy(&addr->nat64_prefix, &pkt->nat64_prefix, sizeof(addr->nat64_prefix));
459 }
460 }
461 break;
462
463 case VPNCTL_CMD_CONNECT:
464 {
465 struct vpnctl_cmd_connect *pkt = ALIGNED_CAST(struct vpnctl_cmd_connect *)combuf;
466 struct bound_addr *addr;
467 struct bound_addr *t_addr;
468
469 plog(ASL_LEVEL_DEBUG,
470 "received connect command on vpn control socket.\n");
471 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
472 if (pkt->address == addr->address) {
473 /* start the connection */
474 error = vpn_connect(addr, VPN_STARTED_BY_API);
475 break;
476 }
477 }
478 }
479 break;
480
481 case VPNCTL_CMD_DISCONNECT:
482 {
483 struct vpnctl_cmd_connect *pkt = ALIGNED_CAST(struct vpnctl_cmd_connect *)combuf;
484 struct bound_addr *addr;
485 struct bound_addr *t_addr;
486
487 plog(ASL_LEVEL_DEBUG,
488 "received disconnect command on vpn control socket.\n");
489 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
490 if (pkt->address == addr->address) {
491 /* stop the connection */
492 error = vpn_disconnect(addr, ike_session_stopped_by_vpn_disconnect);
493 break;
494 }
495 }
496 }
497 break;
498
499 case VPNCTL_CMD_START_PH2:
500 {
501 struct vpnctl_cmd_start_ph2 *pkt = ALIGNED_CAST(struct vpnctl_cmd_start_ph2 *)combuf;
502 struct bound_addr *addr;
503 struct bound_addr *t_addr;
504
505 plog(ASL_LEVEL_DEBUG, "received start_ph2 command on vpn control socket.\n");
506 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
507 if (pkt->address == addr->address) {
508 /* start the connection */
509 error = vpn_start_ph2(addr, pkt);
510 break;
511 }
512 }
513 }
514 break;
515
516 case VPNCTL_CMD_START_DPD:
517 {
518 struct vpnctl_cmd_start_dpd *pkt = ALIGNED_CAST(struct vpnctl_cmd_start_dpd *)combuf;
519 struct bound_addr *srv;
520 struct bound_addr *t_addr;
521
522 plog(ASL_LEVEL_DEBUG,
523 "received start_dpd command on vpn control socket.\n");
524 LIST_FOREACH_SAFE(srv, &elem->bound_addresses, chain, t_addr) {
525 if (pkt->address == srv->address) {
526 union { // Wcast-align fix - force alignment
527 struct sockaddr_storage ss;
528 struct sockaddr_in addr_in;
529 } daddr;
530
531 bzero(&daddr, sizeof(struct sockaddr_in));
532 daddr.addr_in.sin_len = sizeof(struct sockaddr_in);
533 daddr.addr_in.sin_addr.s_addr = srv->address;
534 daddr.addr_in.sin_port = 0;
535 daddr.addr_in.sin_family = AF_INET;
536
537 /* start the dpd */
538 error = ike_session_ph1_force_dpd(&daddr.ss);
539 break;
540 }
541 }
542 }
543 break;
544
545 case VPNCTL_CMD_ASSERT:
546 {
547 struct vpnctl_cmd_assert *pkt = ALIGNED_CAST(struct vpnctl_cmd_assert *)combuf;
548 // struct bound_addr *addr;
549 // struct bound_addr *t_addr;
550 struct sockaddr_in saddr;
551 struct sockaddr_in daddr;
552
553 plogdump(ASL_LEVEL_DEBUG, pkt, ntohs(hdr->len) + sizeof(struct vpnctl_hdr), "received assert command on vpn control socket.\n");
554 // LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
555 // if (pkt->dst_address == addr->address) {
556 bzero(&saddr, sizeof(saddr));
557 saddr.sin_len = sizeof(saddr);
558 saddr.sin_addr.s_addr = pkt->src_address;
559 saddr.sin_port = 0;
560 saddr.sin_family = AF_INET;
561 bzero(&daddr, sizeof(daddr));
562 daddr.sin_len = sizeof(daddr);
563 daddr.sin_addr.s_addr = pkt->dst_address;
564 daddr.sin_port = 0;
565 daddr.sin_family = AF_INET;
566
567 error = vpn_assert(ALIGNED_CAST(struct sockaddr_storage *)&saddr, ALIGNED_CAST(struct sockaddr_storage *)&daddr);
568 break;
569 // }
570 // }
571 }
572 break;
573
574 case VPNCTL_CMD_RECONNECT:
575 {
576 struct vpnctl_cmd_connect *pkt = ALIGNED_CAST(struct vpnctl_cmd_connect *)combuf;
577 struct bound_addr *addr;
578 struct bound_addr *t_addr;
579
580 plog(ASL_LEVEL_DEBUG,
581 "received reconnect command on vpn control socket.\n");
582 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
583 if (pkt->address == addr->address) {
584 /* start the connection */
585 error = vpn_connect(addr, VPN_RESTARTED_BY_API);
586 break;
587 }
588 }
589 }
590 break;
591
592 default:
593 plog(ASL_LEVEL_ERR,
594 "invalid command: %d\n", ntohs(hdr->msg_type));
595 error = -1; // for now
596 break;
597 }
598
599 hdr->len = 0;
600 hdr->result = htons(error);
601 if (vpncontrol_reply(elem->sock, combuf) < 0)
602 return -1;
603
604 return 0;
605
606 }
607
608 static int
609 vpncontrol_reply(int so, char *combuf)
610 {
611 ssize_t tlen;
612
613 tlen = send(so, combuf, sizeof(struct vpnctl_hdr), 0);
614 if (tlen < 0) {
615 plog(ASL_LEVEL_ERR,
616 "failed to send vpn_control message: %s\n", strerror(errno));
617 return -1;
618 }
619
620 return 0;
621 }
622
623 bool
624 vpncontrol_set_nat64_prefix(nw_nat64_prefix_t *prefix)
625 {
626 struct vpnctl_socket_elem *sock_elem;
627 struct bound_addr *bound_addr;
628
629 LIST_FOREACH(sock_elem, &lcconf->vpnctl_comm_socks, chain) {
630 LIST_FOREACH(bound_addr, &sock_elem->bound_addresses, chain) {
631 if (bound_addr->nat64_prefix.length != 0) {
632 memcpy(prefix, &bound_addr->nat64_prefix, sizeof(*prefix));
633 return true;
634 }
635 }
636 }
637 return false;
638 }
639
640 int
641 vpncontrol_notify_need_authinfo(phase1_handle_t *iph1, void* attr_list, size_t attr_len)
642 {
643 struct vpnctl_status_need_authinfo *msg = NULL;
644 struct vpnctl_socket_elem *sock_elem;
645 struct bound_addr *bound_addr;
646 size_t msg_size;
647 ssize_t tlen;
648 u_int32_t address;
649 void *ptr;
650
651 if (!iph1)
652 goto end;
653
654 plog(ASL_LEVEL_DEBUG,
655 "sending vpn_control xauth need info status\n");
656
657 msg = (struct vpnctl_status_need_authinfo *)racoon_malloc(msg_size = sizeof(struct vpnctl_status_need_authinfo) + attr_len);
658 if (msg == NULL) {
659 plog(ASL_LEVEL_ERR,
660 "unable to allocate space for vpn control message.\n");
661 return -1;
662 }
663 msg->hdr.flags = 0;
664
665 address = iph1_get_remote_v4_address(iph1);
666 if (address == 0) {
667 goto end;
668 }
669
670 msg->hdr.cookie = msg->hdr.reserved = msg->hdr.result = 0;
671 msg->hdr.len = htons((msg_size) - sizeof(struct vpnctl_hdr));
672 if (!ike_session_is_client_ph1_rekey(iph1)) {
673 msg->hdr.msg_type = htons(VPNCTL_STATUS_NEED_AUTHINFO);
674 } else {
675 msg->hdr.msg_type = htons(VPNCTL_STATUS_NEED_REAUTHINFO);
676 }
677 msg->address = iph1_get_remote_v4_address(iph1);
678 ptr = msg + 1;
679 memcpy(ptr, attr_list, attr_len);
680
681 LIST_FOREACH(sock_elem, &lcconf->vpnctl_comm_socks, chain) {
682 LIST_FOREACH(bound_addr, &sock_elem->bound_addresses, chain) {
683 if (bound_addr->address == 0xFFFFFFFF ||
684 bound_addr->address == address) {
685 plog(ASL_LEVEL_DEBUG, "vpn control writing %zu bytes\n", msg_size);
686 tlen = send(sock_elem->sock, msg, msg_size, 0);
687 if (tlen < 0) {
688 plog(ASL_LEVEL_ERR,
689 "failed to send vpn_control need authinfo status: %s\n", strerror(errno));
690 }
691 break;
692 }
693 }
694 }
695
696 end:
697 if (msg)
698 racoon_free(msg);
699 return 0;
700 }
701
702 int
703 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)
704 {
705 struct vpnctl_status_failed *msg = NULL;
706 struct vpnctl_socket_elem *sock_elem;
707 struct bound_addr *bound_addr;
708 size_t len;
709 ssize_t tlen;
710
711 len = sizeof(struct vpnctl_status_failed) + data_len;
712
713 msg = (struct vpnctl_status_failed *)racoon_malloc(len);
714 if (msg == NULL) {
715 plog(ASL_LEVEL_DEBUG,
716 "unable to allcate memory for vpn control status message.\n");
717 return -1;
718 }
719
720 msg->hdr.msg_type = htons(VPNCTL_STATUS_IKE_FAILED);
721 msg->hdr.flags = msg->hdr.cookie = msg->hdr.reserved = msg->hdr.result = 0;
722 msg->hdr.len = htons(len - sizeof(struct vpnctl_hdr));
723 msg->address = address;
724 msg->ike_code = htons(notify_code);
725 msg->from = htons(from);
726 if (data_len > 0)
727 memcpy(msg->data, data, data_len);
728 plog(ASL_LEVEL_DEBUG,
729 "sending vpn_control ike failed message - code=%d from=%s.\n", notify_code,
730 (from == FROM_LOCAL ? "local" : "remote"));
731
732 LIST_FOREACH(sock_elem, &lcconf->vpnctl_comm_socks, chain) {
733 LIST_FOREACH(bound_addr, &sock_elem->bound_addresses, chain) {
734 if (bound_addr->address == 0xFFFFFFFF ||
735 bound_addr->address == address) {
736 tlen = send(sock_elem->sock, msg, len, 0);
737 if (tlen < 0) {
738 plog(ASL_LEVEL_ERR,
739 "Unable to send vpn_control ike notify failed: %s\n", strerror(errno));
740 }
741 break;
742 }
743 }
744 }
745
746 if (msg)
747 racoon_free(msg);
748 return 0;
749 }
750
751 char *
752 vpncontrol_status_2_str(u_int16_t msg_type)
753 {
754 switch (msg_type) {
755 case VPNCTL_STATUS_IKE_FAILED:
756 return "IKE failed";
757 case VPNCTL_STATUS_PH1_START_US:
758 return "Phase 1 started by us";
759 case VPNCTL_STATUS_PH1_START_PEER:
760 return "Phase 1 started by peer";
761 case VPNCTL_STATUS_PH1_ESTABLISHED:
762 return "Phase 1 established";
763 case VPNCTL_STATUS_PH2_START:
764 return "Phase 2 started";
765 case VPNCTL_STATUS_PH2_ESTABLISHED:
766 return "Phase 2 established";
767 case VPNCTL_STATUS_NEED_AUTHINFO:
768 return "Need authentication info";
769 case VPNCTL_STATUS_NEED_REAUTHINFO:
770 return "Need re-authentication info";
771 default:
772 return "";
773 }
774 }
775
776
777 int
778 vpncontrol_notify_phase_change(int start, u_int16_t from, phase1_handle_t *iph1, phase2_handle_t *iph2)
779 {
780 struct vpnctl_status_phase_change *msg;
781 struct vpnctl_socket_elem *sock_elem;
782 struct bound_addr *bound_addr;
783 ssize_t tlen;
784 size_t msg_size;
785 u_int32_t address;
786
787 if (iph1 && !start && iph1->mode_cfg && iph1->mode_cfg->xauth.status != XAUTHST_OK) {
788 if (vpn_get_config(iph1, &msg, &msg_size) == 1)
789 return 0; /* mode config not finished yet */
790 } else {
791 msg = racoon_malloc(msg_size = sizeof(struct vpnctl_status_phase_change));
792 msg->hdr.flags = 0;
793 }
794
795 if (msg == NULL) {
796 plog(ASL_LEVEL_ERR,
797 "unable to allocate space for vpn control message.\n");
798 return -1;
799 }
800 if (iph1) {
801 address = iph1_get_remote_v4_address(iph1);
802 if (address == 0) {
803 plog(ASL_LEVEL_ERR, "bad address for ph1 status change.\n");
804 goto end;
805 }
806 msg->hdr.msg_type = htons(start ?
807 (from == FROM_LOCAL ? VPNCTL_STATUS_PH1_START_US : VPNCTL_STATUS_PH1_START_PEER)
808 : VPNCTL_STATUS_PH1_ESTABLISHED);
809 // TODO: indicate version
810 } else {
811 address = iph2_get_remote_v4_address(iph2);
812 if (address == 0) {
813 plog(ASL_LEVEL_ERR, "bad address for ph2 status change.\n");
814 goto end;
815 }
816 msg->hdr.msg_type = htons(start ? VPNCTL_STATUS_PH2_START : VPNCTL_STATUS_PH2_ESTABLISHED);
817 // TODO: indicate version
818 }
819 plog(ASL_LEVEL_NOTICE,
820 ">>>>> phase change status = %s\n", vpncontrol_status_2_str(ntohs(msg->hdr.msg_type)));
821
822 msg->hdr.cookie = msg->hdr.reserved = msg->hdr.result = 0;
823 msg->hdr.len = htons((msg_size) - sizeof(struct vpnctl_hdr));
824 msg->address = address;
825
826 LIST_FOREACH(sock_elem, &lcconf->vpnctl_comm_socks, chain) {
827 LIST_FOREACH(bound_addr, &sock_elem->bound_addresses, chain) {
828 if (bound_addr->address == 0xFFFFFFFF ||
829 bound_addr->address == address) {
830 plog(ASL_LEVEL_DEBUG, "vpn control writing %zu bytes\n", msg_size);
831 tlen = send(sock_elem->sock, msg, msg_size, 0);
832 if (tlen < 0) {
833 plog(ASL_LEVEL_ERR,
834 "failed to send vpn_control phase change status: %s\n", strerror(errno));
835 }
836 break;
837 }
838 }
839 }
840
841 end:
842 if (msg)
843 racoon_free(msg);
844 return 0;
845 }
846
847 static int
848 vpncontrol_notify_peer_resp (u_int16_t notify_code, u_int32_t address)
849 {
850 struct vpnctl_status_peer_resp msg;
851 struct vpnctl_socket_elem *sock_elem;
852 struct bound_addr *bound_addr;
853 ssize_t tlen;
854 int rc = -1;
855
856 bzero(&msg, sizeof(msg));
857 msg.hdr.msg_type = htons(VPNCTL_STATUS_PEER_RESP);
858 msg.hdr.cookie = msg.hdr.reserved = msg.hdr.result = 0;
859 msg.hdr.len = htons(sizeof(msg) - sizeof(msg.hdr));
860 msg.address = address;
861 msg.ike_code = notify_code;
862 plog(ASL_LEVEL_DEBUG,
863 "sending vpn_control status (peer response) message - code=%d addr=%x.\n", notify_code, address);
864
865 LIST_FOREACH(sock_elem, &lcconf->vpnctl_comm_socks, chain) {
866 LIST_FOREACH(bound_addr, &sock_elem->bound_addresses, chain) {
867 if (bound_addr->address == 0xFFFFFFFF ||
868 bound_addr->address == address) {
869 tlen = send(sock_elem->sock, &msg, sizeof(msg), 0);
870 if (tlen < 0) {
871 plog(ASL_LEVEL_ERR,
872 "unable to send vpn_control status (peer response): %s\n", strerror(errno));
873 } else {
874 rc = 0;
875 }
876 break;
877 }
878 }
879 }
880
881 return rc;
882 }
883
884 int
885 vpncontrol_notify_peer_resp_ph1 (u_int16_t notify_code, phase1_handle_t *iph1)
886 {
887 if (iph1 && iph1->parent_session && iph1->parent_session->controller_awaiting_peer_resp) {
888 int rc;
889 if ((rc = vpncontrol_notify_peer_resp(notify_code, iph1_get_remote_v4_address(iph1))) == 0) {
890 iph1->parent_session->controller_awaiting_peer_resp = 0;
891 }
892 return rc;
893 } else {
894 return 0;
895 }
896 }
897
898 int
899 vpncontrol_notify_peer_resp_ph2 (u_int16_t notify_code, phase2_handle_t *iph2)
900 {
901 if (iph2 && iph2->parent_session && iph2->parent_session->controller_awaiting_peer_resp) {
902 int rc;
903 if ((rc = vpncontrol_notify_peer_resp(notify_code, iph2_get_remote_v4_address(iph2))) == 0) {
904 iph2->parent_session->controller_awaiting_peer_resp = 0;
905 }
906 return rc;
907 } else {
908 return 0;
909 }
910 }
911
912 int
913 vpncontrol_init(void)
914 {
915 int sock;
916
917 if (vpncontrolsock_path == NULL) {
918 lcconf->sock_vpncontrol = -1;
919 return 0;
920 }
921
922 if ( (lcconf->sock_vpncontrol = checklaunchd()) == 0 ) {
923 memset(&sunaddr, 0, sizeof(sunaddr));
924 sunaddr.sun_family = AF_UNIX;
925 snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path),
926 "%s", vpncontrolsock_path);
927
928 lcconf->sock_vpncontrol = socket(AF_UNIX, SOCK_STREAM, 0);
929 if (lcconf->sock_vpncontrol == -1) {
930 plog(ASL_LEVEL_ERR,
931 "socket: %s\n", strerror(errno));
932 return -1;
933 }
934
935 if (fcntl(lcconf->sock_vpncontrol, F_SETFL, O_NONBLOCK) == -1) {
936 plog(ASL_LEVEL_ERR, "failed to put VPN-Control socket in non-blocking mode\n");
937 }
938
939 unlink(sunaddr.sun_path);
940 if (bind(lcconf->sock_vpncontrol, (struct sockaddr *)&sunaddr,
941 sizeof(sunaddr)) != 0) {
942 plog(ASL_LEVEL_ERR,
943 "bind(sockname:%s): %s\n",
944 sunaddr.sun_path, strerror(errno));
945 (void)close(lcconf->sock_vpncontrol);
946 return -1;
947 }
948
949 if (chown(sunaddr.sun_path, vpncontrolsock_owner, vpncontrolsock_group) != 0) {
950 plog(ASL_LEVEL_ERR,
951 "chown(%s, %d, %d): %s\n",
952 sunaddr.sun_path, vpncontrolsock_owner,
953 vpncontrolsock_group, strerror(errno));
954 (void)close(lcconf->sock_vpncontrol);
955 return -1;
956 }
957
958 if (chmod(sunaddr.sun_path, vpncontrolsock_mode) != 0) {
959 plog(ASL_LEVEL_ERR,
960 "chmod(%s, 0%03o): %s\n",
961 sunaddr.sun_path, vpncontrolsock_mode, strerror(errno));
962 (void)close(lcconf->sock_vpncontrol);
963 return -1;
964 }
965
966 if (listen(lcconf->sock_vpncontrol, 5) != 0) {
967 plog(ASL_LEVEL_ERR,
968 "listen(sockname:%s): %s\n",
969 sunaddr.sun_path, strerror(errno));
970 (void)close(lcconf->sock_vpncontrol);
971 return -1;
972 }
973 plog(ASL_LEVEL_DEBUG,
974 "opened %s as racoon management.\n", sunaddr.sun_path);
975 }
976 lcconf->vpncontrol_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, lcconf->sock_vpncontrol, 0, dispatch_get_main_queue());
977 if (lcconf->vpncontrol_source == NULL) {
978 plog(ASL_LEVEL_ERR, "could not create vpncontrol socket source.");
979 return -1;
980 }
981 dispatch_source_set_event_handler_f(lcconf->vpncontrol_source, vpncontrol_handler);
982 sock = lcconf->sock_vpncontrol;
983 dispatch_source_set_cancel_handler(lcconf->vpncontrol_source,
984 ^{
985 close(sock);
986 });
987 dispatch_resume(lcconf->vpncontrol_source);
988 return 0;
989 }
990
991 void
992 vpncontrol_disconnect_all(struct vpnctl_socket_elem *elem, const char *reason)
993 {
994 struct bound_addr *addr;
995 struct bound_addr *t_addr;
996
997 plog(ASL_LEVEL_DEBUG,
998 "received disconnect all command.\n");
999
1000 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
1001 /* stop any connections */
1002 vpn_disconnect(addr, reason);
1003 }
1004 }
1005
1006 void
1007 vpncontrol_close()
1008 {
1009 struct vpnctl_socket_elem *elem;
1010 struct vpnctl_socket_elem *t_elem;
1011
1012 plog(ASL_LEVEL_DEBUG,
1013 "vpncontrol_close.\n");
1014
1015 dispatch_source_cancel(lcconf->vpncontrol_source);
1016 lcconf->vpncontrol_source = NULL;
1017
1018 lcconf->sock_vpncontrol = -1;
1019 LIST_FOREACH_SAFE(elem, &lcconf->vpnctl_comm_socks, chain, t_elem)
1020 vpncontrol_close_comm(elem);
1021 }
1022
1023 static void
1024 vpncontrol_close_comm(struct vpnctl_socket_elem *elem)
1025 {
1026 struct bound_addr *addr;
1027 struct bound_addr *t_addr;
1028
1029 plog(ASL_LEVEL_DEBUG,
1030 "vpncontrol_close_comm.\n");
1031
1032 LIST_REMOVE(elem, chain);
1033 if (elem->sock != -1)
1034 dispatch_source_cancel(elem->source);
1035 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
1036 flushsainfo_dynamic(addr->address);
1037 LIST_REMOVE(addr, chain);
1038 if (addr->version)
1039 vfree(addr->version);
1040 racoon_free(addr);
1041 }
1042 racoon_free(elem);
1043 check_auto_exit();
1044
1045 }
1046
1047 int
1048 vpn_control_connected(void)
1049 {
1050 if (LIST_EMPTY(&lcconf->vpnctl_comm_socks))
1051 return 0;
1052 else
1053 return 1;
1054 }
1055
1056 #endif