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