]> git.saurik.com Git - apple/ipsec.git/blob - ipsec-tools/racoon/vpn_control.c
c26b310c8ac3bb554338157c6e87b7388edf68c9
[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_CONNECT:
450 {
451 struct vpnctl_cmd_connect *pkt = ALIGNED_CAST(struct vpnctl_cmd_connect *)combuf;
452 struct bound_addr *addr;
453 struct bound_addr *t_addr;
454
455 plog(ASL_LEVEL_DEBUG,
456 "received connect command on vpn control socket.\n");
457 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
458 if (pkt->address == addr->address) {
459 /* start the connection */
460 error = vpn_connect(addr, VPN_STARTED_BY_API);
461 break;
462 }
463 }
464 }
465 break;
466
467 case VPNCTL_CMD_DISCONNECT:
468 {
469 struct vpnctl_cmd_connect *pkt = ALIGNED_CAST(struct vpnctl_cmd_connect *)combuf;
470 struct bound_addr *addr;
471 struct bound_addr *t_addr;
472
473 plog(ASL_LEVEL_DEBUG,
474 "received disconnect command on vpn control socket.\n");
475 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
476 if (pkt->address == addr->address) {
477 /* stop the connection */
478 error = vpn_disconnect(addr, ike_session_stopped_by_vpn_disconnect);
479 break;
480 }
481 }
482 }
483 break;
484
485 case VPNCTL_CMD_START_PH2:
486 {
487 struct vpnctl_cmd_start_ph2 *pkt = ALIGNED_CAST(struct vpnctl_cmd_start_ph2 *)combuf;
488 struct bound_addr *addr;
489 struct bound_addr *t_addr;
490
491 plog(ASL_LEVEL_DEBUG, "received start_ph2 command on vpn control socket.\n");
492 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
493 if (pkt->address == addr->address) {
494 /* start the connection */
495 error = vpn_start_ph2(addr, pkt);
496 break;
497 }
498 }
499 }
500 break;
501
502 case VPNCTL_CMD_START_DPD:
503 {
504 struct vpnctl_cmd_start_dpd *pkt = ALIGNED_CAST(struct vpnctl_cmd_start_dpd *)combuf;
505 struct bound_addr *srv;
506 struct bound_addr *t_addr;
507
508 plog(ASL_LEVEL_DEBUG,
509 "received start_dpd command on vpn control socket.\n");
510 LIST_FOREACH_SAFE(srv, &elem->bound_addresses, chain, t_addr) {
511 if (pkt->address == srv->address) {
512 union { // Wcast-align fix - force alignment
513 struct sockaddr_storage ss;
514 struct sockaddr_in addr_in;
515 } daddr;
516
517 bzero(&daddr, sizeof(struct sockaddr_in));
518 daddr.addr_in.sin_len = sizeof(struct sockaddr_in);
519 daddr.addr_in.sin_addr.s_addr = srv->address;
520 daddr.addr_in.sin_port = 0;
521 daddr.addr_in.sin_family = AF_INET;
522
523 /* start the dpd */
524 error = ike_session_ph1_force_dpd(&daddr.ss);
525 break;
526 }
527 }
528 }
529 break;
530
531 case VPNCTL_CMD_ASSERT:
532 {
533 struct vpnctl_cmd_assert *pkt = ALIGNED_CAST(struct vpnctl_cmd_assert *)combuf;
534 // struct bound_addr *addr;
535 // struct bound_addr *t_addr;
536 struct sockaddr_in saddr;
537 struct sockaddr_in daddr;
538
539 plogdump(ASL_LEVEL_DEBUG, pkt, ntohs(hdr->len) + sizeof(struct vpnctl_hdr), "received assert command on vpn control socket.\n");
540 // LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
541 // if (pkt->dst_address == addr->address) {
542 bzero(&saddr, sizeof(saddr));
543 saddr.sin_len = sizeof(saddr);
544 saddr.sin_addr.s_addr = pkt->src_address;
545 saddr.sin_port = 0;
546 saddr.sin_family = AF_INET;
547 bzero(&daddr, sizeof(daddr));
548 daddr.sin_len = sizeof(daddr);
549 daddr.sin_addr.s_addr = pkt->dst_address;
550 daddr.sin_port = 0;
551 daddr.sin_family = AF_INET;
552
553 error = vpn_assert((struct sockaddr_storage *)&saddr, (struct sockaddr_storage *)&daddr);
554 break;
555 // }
556 // }
557 }
558 break;
559
560 case VPNCTL_CMD_RECONNECT:
561 {
562 struct vpnctl_cmd_connect *pkt = ALIGNED_CAST(struct vpnctl_cmd_connect *)combuf;
563 struct bound_addr *addr;
564 struct bound_addr *t_addr;
565
566 plog(ASL_LEVEL_DEBUG,
567 "received reconnect command on vpn control socket.\n");
568 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
569 if (pkt->address == addr->address) {
570 /* start the connection */
571 error = vpn_connect(addr, VPN_RESTARTED_BY_API);
572 break;
573 }
574 }
575 }
576 break;
577
578 default:
579 plog(ASL_LEVEL_ERR,
580 "invalid command: %d\n", ntohs(hdr->msg_type));
581 error = -1; // for now
582 break;
583 }
584
585 hdr->len = 0;
586 hdr->result = htons(error);
587 if (vpncontrol_reply(elem->sock, combuf) < 0)
588 return -1;
589
590 return 0;
591
592 }
593
594 static int
595 vpncontrol_reply(int so, char *combuf)
596 {
597 ssize_t tlen;
598
599 tlen = send(so, combuf, sizeof(struct vpnctl_hdr), 0);
600 if (tlen < 0) {
601 plog(ASL_LEVEL_ERR,
602 "failed to send vpn_control message: %s\n", strerror(errno));
603 return -1;
604 }
605
606 return 0;
607 }
608
609 int
610 vpncontrol_notify_need_authinfo(phase1_handle_t *iph1, void* attr_list, size_t attr_len)
611 {
612 struct vpnctl_status_need_authinfo *msg = NULL;
613 struct vpnctl_socket_elem *sock_elem;
614 struct bound_addr *bound_addr;
615 size_t msg_size;
616 ssize_t tlen;
617 u_int32_t address;
618 void *ptr;
619
620 if (!iph1)
621 goto end;
622
623 plog(ASL_LEVEL_DEBUG,
624 "sending vpn_control xauth need info status\n");
625
626 msg = (struct vpnctl_status_need_authinfo *)racoon_malloc(msg_size = sizeof(struct vpnctl_status_need_authinfo) + attr_len);
627 if (msg == NULL) {
628 plog(ASL_LEVEL_ERR,
629 "unable to allocate space for vpn control message.\n");
630 return -1;
631 }
632 msg->hdr.flags = 0;
633
634 if (iph1->remote->ss_family == AF_INET)
635 address = ((struct sockaddr_in *)iph1->remote)->sin_addr.s_addr;
636 else
637 goto end; // for now
638
639 msg->hdr.cookie = msg->hdr.reserved = msg->hdr.result = 0;
640 msg->hdr.len = htons((msg_size) - sizeof(struct vpnctl_hdr));
641 if (!ike_session_is_client_ph1_rekey(iph1)) {
642 msg->hdr.msg_type = htons(VPNCTL_STATUS_NEED_AUTHINFO);
643 } else {
644 msg->hdr.msg_type = htons(VPNCTL_STATUS_NEED_REAUTHINFO);
645 }
646 msg->address = address;
647 ptr = msg + 1;
648 memcpy(ptr, attr_list, attr_len);
649
650 LIST_FOREACH(sock_elem, &lcconf->vpnctl_comm_socks, chain) {
651 LIST_FOREACH(bound_addr, &sock_elem->bound_addresses, chain) {
652 if (bound_addr->address == 0xFFFFFFFF ||
653 bound_addr->address == address) {
654 plog(ASL_LEVEL_DEBUG, "vpn control writing %zu bytes\n", msg_size);
655 tlen = send(sock_elem->sock, msg, msg_size, 0);
656 if (tlen < 0) {
657 plog(ASL_LEVEL_ERR,
658 "failed to send vpn_control need authinfo status: %s\n", strerror(errno));
659 }
660 break;
661 }
662 }
663 }
664
665 end:
666 if (msg)
667 racoon_free(msg);
668 return 0;
669 }
670
671 int
672 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)
673 {
674 struct vpnctl_status_failed *msg = NULL;
675 struct vpnctl_socket_elem *sock_elem;
676 struct bound_addr *bound_addr;
677 size_t len;
678 ssize_t tlen;
679
680 len = sizeof(struct vpnctl_status_failed) + data_len;
681
682 msg = (struct vpnctl_status_failed *)racoon_malloc(len);
683 if (msg == NULL) {
684 plog(ASL_LEVEL_DEBUG,
685 "unable to allcate memory for vpn control status message.\n");
686 return -1;
687 }
688
689 msg->hdr.msg_type = htons(VPNCTL_STATUS_IKE_FAILED);
690 msg->hdr.flags = msg->hdr.cookie = msg->hdr.reserved = msg->hdr.result = 0;
691 msg->hdr.len = htons(len - sizeof(struct vpnctl_hdr));
692 msg->address = address;
693 msg->ike_code = htons(notify_code);
694 msg->from = htons(from);
695 if (data_len > 0)
696 memcpy(msg->data, data, data_len);
697 plog(ASL_LEVEL_DEBUG,
698 "sending vpn_control ike failed message - code=%d from=%s.\n", notify_code,
699 (from == FROM_LOCAL ? "local" : "remote"));
700
701 LIST_FOREACH(sock_elem, &lcconf->vpnctl_comm_socks, chain) {
702 LIST_FOREACH(bound_addr, &sock_elem->bound_addresses, chain) {
703 if (bound_addr->address == 0xFFFFFFFF ||
704 bound_addr->address == address) {
705 tlen = send(sock_elem->sock, msg, len, 0);
706 if (tlen < 0) {
707 plog(ASL_LEVEL_ERR,
708 "Unable to send vpn_control ike notify failed: %s\n", strerror(errno));
709 }
710 break;
711 }
712 }
713 }
714
715 if (msg)
716 racoon_free(msg);
717 return 0;
718 }
719
720 char *
721 vpncontrol_status_2_str(u_int16_t msg_type)
722 {
723 switch (msg_type) {
724 case VPNCTL_STATUS_IKE_FAILED:
725 return "IKE failed";
726 case VPNCTL_STATUS_PH1_START_US:
727 return "Phase 1 started by us";
728 case VPNCTL_STATUS_PH1_START_PEER:
729 return "Phase 1 started by peer";
730 case VPNCTL_STATUS_PH1_ESTABLISHED:
731 return "Phase 1 established";
732 case VPNCTL_STATUS_PH2_START:
733 return "Phase 2 started";
734 case VPNCTL_STATUS_PH2_ESTABLISHED:
735 return "Phase 2 established";
736 case VPNCTL_STATUS_NEED_AUTHINFO:
737 return "Need authentication info";
738 case VPNCTL_STATUS_NEED_REAUTHINFO:
739 return "Need re-authentication info";
740 default:
741 return "";
742 }
743 }
744
745
746 int
747 vpncontrol_notify_phase_change(int start, u_int16_t from, phase1_handle_t *iph1, phase2_handle_t *iph2)
748 {
749 struct vpnctl_status_phase_change *msg;
750 struct vpnctl_socket_elem *sock_elem;
751 struct bound_addr *bound_addr;
752 ssize_t tlen;
753 size_t msg_size;
754 u_int32_t address;
755
756 if (iph1 && !start && iph1->mode_cfg && iph1->mode_cfg->xauth.status != XAUTHST_OK) {
757 if (vpn_get_config(iph1, &msg, &msg_size) == 1)
758 return 0; /* mode config not finished yet */
759 } else {
760 msg = racoon_malloc(msg_size = sizeof(struct vpnctl_status_phase_change));
761 msg->hdr.flags = 0;
762 }
763
764 if (msg == NULL) {
765 plog(ASL_LEVEL_ERR,
766 "unable to allocate space for vpn control message.\n");
767 return -1;
768 }
769 if (iph1) {
770 if (iph1->remote->ss_family == AF_INET)
771 address = ((struct sockaddr_in *)iph1->remote)->sin_addr.s_addr;
772 else
773 goto end; // for now
774 msg->hdr.msg_type = htons(start ?
775 (from == FROM_LOCAL ? VPNCTL_STATUS_PH1_START_US : VPNCTL_STATUS_PH1_START_PEER)
776 : VPNCTL_STATUS_PH1_ESTABLISHED);
777 // TODO: indicate version
778 } else {
779 if (iph2->dst->ss_family == AF_INET)
780 address = ((struct sockaddr_in *)iph2->dst)->sin_addr.s_addr;
781 else
782 goto end; // for now
783 msg->hdr.msg_type = htons(start ? VPNCTL_STATUS_PH2_START : VPNCTL_STATUS_PH2_ESTABLISHED);
784 // TODO: indicate version
785 }
786 plog(ASL_LEVEL_NOTICE,
787 ">>>>> phase change status = %s\n", vpncontrol_status_2_str(ntohs(msg->hdr.msg_type)));
788
789 msg->hdr.cookie = msg->hdr.reserved = msg->hdr.result = 0;
790 msg->hdr.len = htons((msg_size) - sizeof(struct vpnctl_hdr));
791 msg->address = address;
792
793 LIST_FOREACH(sock_elem, &lcconf->vpnctl_comm_socks, chain) {
794 LIST_FOREACH(bound_addr, &sock_elem->bound_addresses, chain) {
795 if (bound_addr->address == 0xFFFFFFFF ||
796 bound_addr->address == address) {
797 plog(ASL_LEVEL_DEBUG, "vpn control writing %zu bytes\n", msg_size);
798 tlen = send(sock_elem->sock, msg, msg_size, 0);
799 if (tlen < 0) {
800 plog(ASL_LEVEL_ERR,
801 "failed to send vpn_control phase change status: %s\n", strerror(errno));
802 }
803 break;
804 }
805 }
806 }
807
808 end:
809 if (msg)
810 racoon_free(msg);
811 return 0;
812 }
813
814 static int
815 vpncontrol_notify_peer_resp (u_int16_t notify_code, u_int32_t address)
816 {
817 struct vpnctl_status_peer_resp msg;
818 struct vpnctl_socket_elem *sock_elem;
819 struct bound_addr *bound_addr;
820 ssize_t tlen;
821 int rc = -1;
822
823 bzero(&msg, sizeof(msg));
824 msg.hdr.msg_type = htons(VPNCTL_STATUS_PEER_RESP);
825 msg.hdr.cookie = msg.hdr.reserved = msg.hdr.result = 0;
826 msg.hdr.len = htons(sizeof(msg) - sizeof(msg.hdr));
827 msg.address = address;
828 msg.ike_code = notify_code;
829 plog(ASL_LEVEL_DEBUG,
830 "sending vpn_control status (peer response) message - code=%d addr=%x.\n", notify_code, address);
831
832 LIST_FOREACH(sock_elem, &lcconf->vpnctl_comm_socks, chain) {
833 LIST_FOREACH(bound_addr, &sock_elem->bound_addresses, chain) {
834 if (bound_addr->address == 0xFFFFFFFF ||
835 bound_addr->address == address) {
836 tlen = send(sock_elem->sock, &msg, sizeof(msg), 0);
837 if (tlen < 0) {
838 plog(ASL_LEVEL_ERR,
839 "unable to send vpn_control status (peer response): %s\n", strerror(errno));
840 } else {
841 rc = 0;
842 }
843 break;
844 }
845 }
846 }
847
848 return rc;
849 }
850
851 int
852 vpncontrol_notify_peer_resp_ph1 (u_int16_t notify_code, phase1_handle_t *iph1)
853 {
854 u_int32_t address;
855 int rc;
856
857 if (iph1 && iph1->parent_session && iph1->parent_session->controller_awaiting_peer_resp) {
858 if (iph1->remote->ss_family == AF_INET)
859 address = ((struct sockaddr_in *)iph1->remote)->sin_addr.s_addr;
860 else
861 address = 0;
862 } else {
863 return 0;
864 }
865
866 if ((rc = vpncontrol_notify_peer_resp(notify_code, address)) == 0) {
867 iph1->parent_session->controller_awaiting_peer_resp = 0;
868 }
869 return rc;
870 }
871
872 int
873 vpncontrol_notify_peer_resp_ph2 (u_int16_t notify_code, phase2_handle_t *iph2)
874 {
875 u_int32_t address;
876 int rc;
877
878 if (iph2 && iph2->parent_session && iph2->parent_session->controller_awaiting_peer_resp) {
879 if (iph2->dst->ss_family == AF_INET)
880 address = ((struct sockaddr_in *)iph2->dst)->sin_addr.s_addr;
881 else
882 address = 0;
883 } else {
884 return 0;
885 }
886
887 if ((rc = vpncontrol_notify_peer_resp(notify_code, address)) == 0) {
888 iph2->parent_session->controller_awaiting_peer_resp = 0;
889 }
890 return rc;
891 }
892
893 int
894 vpncontrol_init(void)
895 {
896 int sock;
897
898 if (vpncontrolsock_path == NULL) {
899 lcconf->sock_vpncontrol = -1;
900 return 0;
901 }
902
903 if ( (lcconf->sock_vpncontrol = checklaunchd()) == 0 ) {
904 memset(&sunaddr, 0, sizeof(sunaddr));
905 sunaddr.sun_family = AF_UNIX;
906 snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path),
907 "%s", vpncontrolsock_path);
908
909 lcconf->sock_vpncontrol = socket(AF_UNIX, SOCK_STREAM, 0);
910 if (lcconf->sock_vpncontrol == -1) {
911 plog(ASL_LEVEL_ERR,
912 "socket: %s\n", strerror(errno));
913 return -1;
914 }
915
916 if (fcntl(lcconf->sock_vpncontrol, F_SETFL, O_NONBLOCK) == -1) {
917 plog(ASL_LEVEL_ERR, "failed to put VPN-Control socket in non-blocking mode\n");
918 }
919
920 unlink(sunaddr.sun_path);
921 if (bind(lcconf->sock_vpncontrol, (struct sockaddr *)&sunaddr,
922 sizeof(sunaddr)) != 0) {
923 plog(ASL_LEVEL_ERR,
924 "bind(sockname:%s): %s\n",
925 sunaddr.sun_path, strerror(errno));
926 (void)close(lcconf->sock_vpncontrol);
927 return -1;
928 }
929
930 if (chown(sunaddr.sun_path, vpncontrolsock_owner, vpncontrolsock_group) != 0) {
931 plog(ASL_LEVEL_ERR,
932 "chown(%s, %d, %d): %s\n",
933 sunaddr.sun_path, vpncontrolsock_owner,
934 vpncontrolsock_group, strerror(errno));
935 (void)close(lcconf->sock_vpncontrol);
936 return -1;
937 }
938
939 if (chmod(sunaddr.sun_path, vpncontrolsock_mode) != 0) {
940 plog(ASL_LEVEL_ERR,
941 "chmod(%s, 0%03o): %s\n",
942 sunaddr.sun_path, vpncontrolsock_mode, strerror(errno));
943 (void)close(lcconf->sock_vpncontrol);
944 return -1;
945 }
946
947 if (listen(lcconf->sock_vpncontrol, 5) != 0) {
948 plog(ASL_LEVEL_ERR,
949 "listen(sockname:%s): %s\n",
950 sunaddr.sun_path, strerror(errno));
951 (void)close(lcconf->sock_vpncontrol);
952 return -1;
953 }
954 plog(ASL_LEVEL_DEBUG,
955 "opened %s as racoon management.\n", sunaddr.sun_path);
956 }
957 lcconf->vpncontrol_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, lcconf->sock_vpncontrol, 0, dispatch_get_main_queue());
958 if (lcconf->vpncontrol_source == NULL) {
959 plog(ASL_LEVEL_ERR, "could not create vpncontrol socket source.");
960 return -1;
961 }
962 dispatch_source_set_event_handler_f(lcconf->vpncontrol_source, vpncontrol_handler);
963 sock = lcconf->sock_vpncontrol;
964 dispatch_source_set_cancel_handler(lcconf->vpncontrol_source,
965 ^{
966 close(sock);
967 });
968 dispatch_resume(lcconf->vpncontrol_source);
969 return 0;
970 }
971
972 void
973 vpncontrol_disconnect_all(struct vpnctl_socket_elem *elem, const char *reason)
974 {
975 struct bound_addr *addr;
976 struct bound_addr *t_addr;
977
978 plog(ASL_LEVEL_DEBUG,
979 "received disconnect all command.\n");
980
981 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
982 /* stop any connections */
983 vpn_disconnect(addr, reason);
984 }
985 }
986
987 void
988 vpncontrol_close()
989 {
990 struct vpnctl_socket_elem *elem;
991 struct vpnctl_socket_elem *t_elem;
992
993 plog(ASL_LEVEL_DEBUG,
994 "vpncontrol_close.\n");
995
996 dispatch_source_cancel(lcconf->vpncontrol_source);
997 lcconf->vpncontrol_source = NULL;
998
999 lcconf->sock_vpncontrol = -1;
1000 LIST_FOREACH_SAFE(elem, &lcconf->vpnctl_comm_socks, chain, t_elem)
1001 vpncontrol_close_comm(elem);
1002 }
1003
1004 static void
1005 vpncontrol_close_comm(struct vpnctl_socket_elem *elem)
1006 {
1007 struct bound_addr *addr;
1008 struct bound_addr *t_addr;
1009
1010 plog(ASL_LEVEL_DEBUG,
1011 "vpncontrol_close_comm.\n");
1012
1013 LIST_REMOVE(elem, chain);
1014 if (elem->sock != -1)
1015 dispatch_source_cancel(elem->source);
1016 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
1017 flushsainfo_dynamic(addr->address);
1018 LIST_REMOVE(addr, chain);
1019 if (addr->version)
1020 vfree(addr->version);
1021 racoon_free(addr);
1022 }
1023 racoon_free(elem);
1024 check_auto_exit();
1025
1026 }
1027
1028 int
1029 vpn_control_connected(void)
1030 {
1031 if (LIST_EMPTY(&lcconf->vpnctl_comm_socks))
1032 return 0;
1033 else
1034 return 1;
1035 }
1036
1037 #endif