]> git.saurik.com Git - apple/ipsec.git/blob - ipsec-tools/racoon/admin.c
03d095c0abccafd6beb4fb3c36733ff73a2efb8b
[apple/ipsec.git] / ipsec-tools / racoon / admin.c
1 /* $NetBSD: admin.c,v 1.17.6.1 2007/08/01 11:52:19 vanhu Exp $ */
2
3 /* Id: admin.c,v 1.25 2006/04/06 14:31:04 manubsd Exp */
4
5 /*
6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #include "config.h"
35
36 #include <sys/types.h>
37 #include <sys/param.h>
38 #include <sys/socket.h>
39 #include <sys/signal.h>
40 #include <sys/stat.h>
41 #include <sys/un.h>
42
43 #include <System/net/pfkeyv2.h>
44
45 #include <netinet/in.h>
46 #ifndef HAVE_NETINET6_IPSEC
47 #include <netinet/ipsec.h>
48 #else
49 #include <netinet6/ipsec.h>
50 #endif
51
52
53 #include <stdlib.h>
54 #include <stdio.h>
55 #include <string.h>
56 #include <errno.h>
57 #include <netdb.h>
58 #ifdef HAVE_UNISTD_H
59 #include <unistd.h>
60 #endif
61 #ifdef ENABLE_HYBRID
62 #include <resolv.h>
63 #endif
64 #include <fcntl.h>
65
66 #include "var.h"
67 #include "misc.h"
68 #include "vmbuf.h"
69 #include "plog.h"
70 #include "sockmisc.h"
71 #include "debug.h"
72
73 #include "schedule.h"
74 #include "localconf.h"
75 #include "remoteconf.h"
76 #include "grabmyaddr.h"
77 #include "isakmp_var.h"
78 #include "isakmp.h"
79 #include "oakley.h"
80 #include "handler.h"
81 #include "evt.h"
82 #include "pfkey.h"
83 #include "ipsec_doi.h"
84 #include "admin.h"
85 #include "admin_var.h"
86 #include "isakmp_inf.h"
87 #ifdef ENABLE_HYBRID
88 #include "isakmp_cfg.h"
89 #endif
90 #include "session.h"
91 #include "gcmalloc.h"
92 #include "vpn.h"
93 #include "vpn_control_var.h"
94
95
96 #ifdef ENABLE_ADMINPORT
97 char *adminsock_path = ADMINSOCK_PATH;
98 uid_t adminsock_owner = 0;
99 gid_t adminsock_group = 0;
100 mode_t adminsock_mode = 0600;
101
102 static struct sockaddr_un sunaddr;
103 static int admin_process __P((int, char *));
104 static int admin_reply __P((int, struct admin_com *, vchar_t *));
105
106 int
107 admin_handler()
108 {
109 int so2;
110 struct sockaddr_storage from;
111 socklen_t fromlen = sizeof(from);
112 struct admin_com com;
113 char *combuf = NULL;
114 int len, error = -1;
115
116 so2 = accept(lcconf->sock_admin, (struct sockaddr_storage *)&from, &fromlen);
117 if (so2 < 0) {
118 plog(LLV_ERROR, LOCATION, NULL,
119 "failed to accept admin command: %s\n",
120 strerror(errno));
121 return -1;
122 }
123
124 /* get buffer length */
125 while ((len = recv(so2, (char *)&com, sizeof(com), MSG_PEEK)) < 0) {
126 if (errno == EINTR)
127 continue;
128 plog(LLV_ERROR, LOCATION, NULL,
129 "failed to recv admin command: %s\n",
130 strerror(errno));
131 goto end;
132 }
133
134 /* sanity check */
135 if (len < sizeof(com)) {
136 plog(LLV_ERROR, LOCATION, NULL,
137 "invalid header length of admin command\n");
138 goto end;
139 }
140
141 /* get buffer to receive */
142 if ((combuf = racoon_malloc(com.ac_len)) == 0) {
143 plog(LLV_ERROR, LOCATION, NULL,
144 "failed to alloc buffer for admin command\n");
145 goto end;
146 }
147
148 /* get real data */
149 while ((len = recv(so2, combuf, com.ac_len, 0)) < 0) {
150 if (errno == EINTR)
151 continue;
152 plog(LLV_ERROR, LOCATION, NULL,
153 "failed to recv admin command: %s\n",
154 strerror(errno));
155 goto end;
156 }
157
158 if (com.ac_cmd == ADMIN_RELOAD_CONF) {
159 siginfo_t sigi;
160 bzero(&sigi, sizeof(sigi));
161 sigi.si_signo = SIGUSR1;
162 sigi.si_pid = getpid();
163 sigi.si_uid = getuid();
164 /* reload does not work at all! */
165 signal_handler(SIGUSR1, &sigi, (void *)NULL);
166 goto end;
167 }
168
169 error = admin_process(so2, combuf);
170
171 end:
172 (void)close(so2);
173 if (combuf)
174 racoon_free(combuf);
175
176 return error;
177 }
178
179 /*
180 * main child's process.
181 */
182 static int
183 admin_process(so2, combuf)
184 int so2;
185 char *combuf;
186 {
187 struct admin_com *com = (struct admin_com *)combuf;
188 vchar_t *buf = NULL;
189 vchar_t *id = NULL;
190 vchar_t *key = NULL;
191 int idtype = 0;
192 int error = -1;
193
194 com->ac_errno = 0;
195
196 switch (com->ac_cmd) {
197 case ADMIN_RELOAD_CONF:
198 /* don't entered because of proccessing it in other place. */
199 plog(LLV_ERROR, LOCATION, NULL, "should never reach here\n");
200 goto out;
201
202 case ADMIN_SHOW_SCHED:
203 {
204 caddr_t p = NULL;
205 int len;
206
207 com->ac_errno = -1;
208
209 if (sched_dump(&p, &len) == -1)
210 goto out2;
211
212 if ((buf = vmalloc(len)) == NULL)
213 goto out2;
214
215 memcpy(buf->v, p, len);
216
217 com->ac_errno = 0;
218 out2:
219 racoon_free(p);
220 break;
221 }
222
223 case ADMIN_SHOW_EVT:
224 /* It's not really an error, don't force racoonctl to quit */
225 if ((buf = evt_dump()) == NULL)
226 com->ac_errno = 0;
227 break;
228
229 case ADMIN_SHOW_SA:
230 case ADMIN_FLUSH_SA:
231 {
232 switch (com->ac_proto) {
233 case ADMIN_PROTO_ISAKMP:
234 switch (com->ac_cmd) {
235 case ADMIN_SHOW_SA:
236 buf = dumpph1();
237 if (buf == NULL)
238 com->ac_errno = -1;
239 break;
240 case ADMIN_FLUSH_SA:
241 flushph1(false);
242 break;
243 }
244 break;
245 case ADMIN_PROTO_IPSEC:
246 case ADMIN_PROTO_AH:
247 case ADMIN_PROTO_ESP:
248 switch (com->ac_cmd) {
249 case ADMIN_SHOW_SA:
250 {
251 u_int p;
252 p = admin2pfkey_proto(com->ac_proto);
253 if (p == -1)
254 goto out;
255 buf = pfkey_dump_sadb(p);
256 if (buf == NULL)
257 com->ac_errno = -1;
258 }
259 break;
260 case ADMIN_FLUSH_SA:
261 pfkey_flush_sadb(com->ac_proto);
262 break;
263 }
264 break;
265
266 case ADMIN_PROTO_INTERNAL:
267 switch (com->ac_cmd) {
268 case ADMIN_SHOW_SA:
269 buf = NULL; /*XXX dumpph2(&error);*/
270 if (buf == NULL)
271 com->ac_errno = error;
272 break;
273 case ADMIN_FLUSH_SA:
274 /*XXX flushph2(false);*/
275 com->ac_errno = 0;
276 break;
277 }
278 break;
279
280 default:
281 /* ignore */
282 com->ac_errno = -1;
283 }
284 }
285 break;
286
287 case ADMIN_DELETE_SA: {
288 struct ph1handle *iph1;
289 struct sockaddr_storage *dst;
290 struct sockaddr_storage *src;
291 char *loc, *rem;
292
293 src = (struct sockaddr_storage *)
294 &((struct admin_com_indexes *)
295 ((caddr_t)com + sizeof(*com)))->src;
296 dst = (struct sockaddr_storage *)
297 &((struct admin_com_indexes *)
298 ((caddr_t)com + sizeof(*com)))->dst;
299
300 loc = racoon_strdup(saddrwop2str(src));
301 rem = racoon_strdup(saddrwop2str(dst));
302 STRDUP_FATAL(loc);
303 STRDUP_FATAL(rem);
304
305 if ((iph1 = getph1byaddrwop(src, dst)) == NULL) {
306 plog(LLV_ERROR, LOCATION, NULL,
307 "phase 1 for %s -> %s not found\n", loc, rem);
308 } else {
309 if (iph1->status == PHASE1ST_ESTABLISHED)
310 isakmp_info_send_d1(iph1);
311 purge_remote(iph1);
312 }
313
314 racoon_free(loc);
315 racoon_free(rem);
316
317 break;
318 }
319
320 #ifdef ENABLE_HYBRID
321 case ADMIN_LOGOUT_USER: {
322 struct ph1handle *iph1;
323 char user[LOGINLEN+1];
324 int found = 0, len = com->ac_len - sizeof(com);
325
326 if (len > LOGINLEN) {
327 plog(LLV_ERROR, LOCATION, NULL,
328 "malformed message (login too long)\n");
329 break;
330 }
331
332 memcpy(user, (char *)(com + 1), len);
333 user[len] = 0;
334
335 found = purgeph1bylogin(user);
336 plog(LLV_INFO, LOCATION, NULL,
337 "deleted %d SA for user \"%s\"\n", found, user);
338
339 break;
340 }
341 #endif
342
343 case ADMIN_DELETE_ALL_SA_DST: {
344 struct ph1handle *iph1;
345 struct sockaddr_storage *dst;
346 char *loc, *rem;
347
348 dst = (struct sockaddr_storage *)
349 &((struct admin_com_indexes *)
350 ((caddr_t)com + sizeof(*com)))->dst;
351
352 rem = racoon_strdup(saddrwop2str(dst));
353 STRDUP_FATAL(rem);
354
355 plog(LLV_INFO, LOCATION, NULL,
356 "Flushing all SAs for peer %s\n", rem);
357
358 while ((iph1 = getph1bydstaddrwop(dst)) != NULL) {
359 loc = racoon_strdup(saddrwop2str(iph1->local));
360 STRDUP_FATAL(loc);
361
362 if (iph1->status == PHASE1ST_ESTABLISHED)
363 isakmp_info_send_d1(iph1);
364 purge_remote(iph1);
365
366 racoon_free(loc);
367 }
368
369 racoon_free(rem);
370
371 break;
372 }
373
374 //%%%%%% test code
375 case ADMIN_ESTABLISH_SA_VPNCONTROL:
376 {
377 struct admin_com_psk *acp;
378 char *data;
379 struct sockaddr_storage *dst;
380 struct bound_addr *target;
381
382 com->ac_errno = -1;
383
384 acp = (struct admin_com_psk *)
385 ((char *)com + sizeof(*com) +
386 sizeof(struct admin_com_indexes));
387
388 target = (struct bound_addr *)racoon_malloc(sizeof(struct bound_addr));
389 if (target == NULL) {
390 plog(LLV_ERROR, LOCATION, NULL,
391 "cannot allocate memory: %s\n",
392 strerror(errno));
393 break;
394 }
395
396 if ((id = vmalloc(acp->id_len)) == NULL) {
397 plog(LLV_ERROR, LOCATION, NULL,
398 "cannot allocate memory: %s\n",
399 strerror(errno));
400 goto outofhere;
401 }
402 data = (char *)(acp + 1);
403 memcpy(id->v, data, id->l);
404
405 if ((key = vmalloc(acp->key_len)) == NULL) {
406 plog(LLV_ERROR, LOCATION, NULL,
407 "cannot allocate memory: %s\n",
408 strerror(errno));
409 vfree(id);
410 id = NULL;
411 goto outofhere;
412 }
413 data = (char *)(data + acp->id_len);
414 memcpy(key->v, data, key->l);
415
416 dst = (struct sockaddr_storage *)
417 &((struct admin_com_indexes *)
418 ((caddr_t)com + sizeof(*com)))->dst;
419
420 // assume IPv4
421 target->address = ((struct sockaddr_in *)dst)->sin_addr.s_addr;
422
423 #ifdef ENABLE_HYBRID
424 /* Set the id and key */
425 if (id && key) {
426
427 target->user_id = id;
428 target->user_pw = key;
429 }
430 #endif
431 vpn_connect(target, VPN_STARTED_BY_ADMIN);
432 com->ac_errno = 0;
433 outofhere:
434 if (target->user_id != NULL)
435 vfree(target->user_id);
436 if (target->user_pw != NULL)
437 vfree(target->user_pw);
438 if (target != NULL)
439 racoon_free(target);
440 break;
441 }
442
443 case ADMIN_ESTABLISH_SA_PSK: {
444 struct admin_com_psk *acp;
445 char *data;
446
447 com->ac_cmd = ADMIN_ESTABLISH_SA;
448
449 acp = (struct admin_com_psk *)
450 ((char *)com + sizeof(*com) +
451 sizeof(struct admin_com_indexes));
452
453 idtype = acp->id_type;
454
455 if ((id = vmalloc(acp->id_len)) == NULL) {
456 plog(LLV_ERROR, LOCATION, NULL,
457 "cannot allocate memory: %s\n",
458 strerror(errno));
459 break;
460 }
461 data = (char *)(acp + 1);
462 memcpy(id->v, data, id->l);
463
464 if ((key = vmalloc(acp->key_len)) == NULL) {
465 plog(LLV_ERROR, LOCATION, NULL,
466 "cannot allocate memory: %s\n",
467 strerror(errno));
468 vfree(id);
469 id = NULL;
470 break;
471 }
472 data = (char *)(data + acp->id_len);
473 memcpy(key->v, data, key->l);
474 }
475 /* FALLTHROUGH */
476 case ADMIN_ESTABLISH_SA:
477 {
478 struct sockaddr_storage *dst;
479 struct sockaddr_storage *src;
480 src = (struct sockaddr_storage *)
481 &((struct admin_com_indexes *)
482 ((caddr_t)com + sizeof(*com)))->src;
483 dst = (struct sockaddr_storage *)
484 &((struct admin_com_indexes *)
485 ((caddr_t)com + sizeof(*com)))->dst;
486
487 switch (com->ac_proto) {
488 case ADMIN_PROTO_ISAKMP: {
489 struct remoteconf *rmconf;
490 struct sockaddr_storage *remote = NULL;
491 struct sockaddr_storage *local = NULL;
492 u_int16_t port;
493
494 com->ac_errno = -1;
495
496 /* search appropreate configuration */
497 rmconf = getrmconf(dst);
498 if (rmconf == NULL) {
499 plog(LLV_ERROR, LOCATION, NULL,
500 "no configuration found "
501 "for %s\n", saddrwop2str(dst));
502 goto out1;
503 }
504
505 /* get remote IP address and port number. */
506 if ((remote = dupsaddr(dst)) == NULL)
507 goto out1;
508
509 switch (remote->ss_family) {
510 case AF_INET:
511 ((struct sockaddr_in *)remote)->sin_port =
512 ((struct sockaddr_in *)rmconf->remote)->sin_port;
513 break;
514 #ifdef INET6
515 case AF_INET6:
516 ((struct sockaddr_in6 *)remote)->sin6_port =
517 ((struct sockaddr_in6 *)rmconf->remote)->sin6_port;
518 break;
519 #endif
520 default:
521 plog(LLV_ERROR, LOCATION, NULL,
522 "invalid family: %d\n",
523 remote->ss_family);
524 com->ac_errno = -1;
525 break;
526 }
527
528 // port = extract_port(rmconf->remote);
529 // if (set_port(remote, port) == NULL)
530 // goto out1;
531
532 /* get local address */
533 if ((local = dupsaddr(src)) == NULL)
534 goto out1;
535
536 port = ntohs(getmyaddrsport(local));
537 if (set_port(local, port) == NULL)
538 goto out1;
539
540 #ifdef ENABLE_HYBRID
541 /* Set the id and key */
542 if (id && key) {
543 if (xauth_rmconf_used(&rmconf->xauth) == -1)
544 goto out1;
545
546 if (rmconf->xauth->login != NULL) {
547 vfree(rmconf->xauth->login);
548 rmconf->xauth->login = NULL;
549 }
550 if (rmconf->xauth->pass != NULL) {
551 vfree(rmconf->xauth->pass);
552 rmconf->xauth->pass = NULL;
553 }
554
555 rmconf->xauth->login = id;
556 rmconf->xauth->pass = key;
557 }
558 #endif
559
560 plog(LLV_INFO, LOCATION, NULL,
561 "accept a request to establish IKE-SA: "
562 "%s\n", saddrwop2str(remote));
563
564 /* begin ident mode */
565 if (isakmp_ph1begin_i(rmconf, remote, local, 0) < 0)
566 goto out1;
567
568 com->ac_errno = 0;
569 out1:
570 if (local != NULL)
571 racoon_free(local);
572 if (remote != NULL)
573 racoon_free(remote);
574 break;
575 }
576 case ADMIN_PROTO_AH:
577 case ADMIN_PROTO_ESP:
578 break;
579 default:
580 /* ignore */
581 com->ac_errno = -1;
582 }
583 }
584 break;
585
586 default:
587 plog(LLV_ERROR, LOCATION, NULL,
588 "invalid command: %d\n", com->ac_cmd);
589 com->ac_errno = -1;
590 }
591
592 if ((error = admin_reply(so2, com, buf)) != 0)
593 goto out;
594
595 error = 0;
596 out:
597 if (buf != NULL)
598 vfree(buf);
599
600 return error;
601 }
602
603 static int
604 admin_reply(so, combuf, buf)
605 int so;
606 struct admin_com *combuf;
607 vchar_t *buf;
608 {
609 int tlen;
610 char *retbuf = NULL;
611
612 if (buf != NULL)
613 tlen = sizeof(*combuf) + buf->l;
614 else
615 tlen = sizeof(*combuf);
616
617 retbuf = racoon_calloc(1, tlen);
618 if (retbuf == NULL) {
619 plog(LLV_ERROR, LOCATION, NULL,
620 "failed to allocate admin buffer\n");
621 return -1;
622 }
623
624 memcpy(retbuf, combuf, sizeof(*combuf));
625 ((struct admin_com *)retbuf)->ac_len = tlen;
626
627 if (buf != NULL)
628 memcpy(retbuf + sizeof(*combuf), buf->v, buf->l);
629
630 tlen = send(so, retbuf, tlen, 0);
631 racoon_free(retbuf);
632 if (tlen < 0) {
633 plog(LLV_ERROR, LOCATION, NULL,
634 "failed to send admin command: %s\n",
635 strerror(errno));
636 return -1;
637 }
638
639 return 0;
640 }
641
642 /* ADMIN_PROTO -> SADB_SATYPE */
643 int
644 admin2pfkey_proto(proto)
645 u_int proto;
646 {
647 switch (proto) {
648 case ADMIN_PROTO_IPSEC:
649 return SADB_SATYPE_UNSPEC;
650 case ADMIN_PROTO_AH:
651 return SADB_SATYPE_AH;
652 case ADMIN_PROTO_ESP:
653 return SADB_SATYPE_ESP;
654 default:
655 plog(LLV_ERROR, LOCATION, NULL,
656 "unsupported proto for admin: %d\n", proto);
657 return -1;
658 }
659 /*NOTREACHED*/
660 }
661
662 int
663 admin_init()
664 {
665 if (adminsock_path == NULL) {
666 lcconf->sock_admin = -1;
667 return 0;
668 }
669
670 memset(&sunaddr, 0, sizeof(sunaddr));
671 sunaddr.sun_family = AF_UNIX;
672 snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path),
673 "%s", adminsock_path);
674
675 lcconf->sock_admin = socket(AF_UNIX, SOCK_STREAM, 0);
676 if (lcconf->sock_admin == -1) {
677 plog(LLV_ERROR, LOCATION, NULL,
678 "socket: %s\n", strerror(errno));
679 return -1;
680 }
681
682 if (fcntl(lcconf->sock_admin, F_SETFL, O_NONBLOCK) == -1) {
683 plog(LLV_ERROR, LOCATION, NULL,
684 "failed to put admin socket in non-blocking mode\n");
685 }
686
687 unlink(sunaddr.sun_path);
688 if (bind(lcconf->sock_admin, (struct sockaddr_storage *)&sunaddr,
689 sizeof(sunaddr)) != 0) {
690 plog(LLV_ERROR, LOCATION, NULL,
691 "bind(sockname:%s): %s\n",
692 sunaddr.sun_path, strerror(errno));
693 (void)close(lcconf->sock_admin);
694 return -1;
695 }
696
697 if (chown(sunaddr.sun_path, adminsock_owner, adminsock_group) != 0) {
698 plog(LLV_ERROR, LOCATION, NULL,
699 "chown(%s, %d, %d): %s\n",
700 sunaddr.sun_path, adminsock_owner,
701 adminsock_group, strerror(errno));
702 (void)close(lcconf->sock_admin);
703 return -1;
704 }
705
706 if (chmod(sunaddr.sun_path, adminsock_mode) != 0) {
707 plog(LLV_ERROR, LOCATION, NULL,
708 "chmod(%s, 0%03o): %s\n",
709 sunaddr.sun_path, adminsock_mode, strerror(errno));
710 (void)close(lcconf->sock_admin);
711 return -1;
712 }
713
714 if (listen(lcconf->sock_admin, 5) != 0) {
715 plog(LLV_ERROR, LOCATION, NULL,
716 "listen(sockname:%s): %s\n",
717 sunaddr.sun_path, strerror(errno));
718 (void)close(lcconf->sock_admin);
719 return -1;
720 }
721 plog(LLV_DEBUG, LOCATION, NULL,
722 "open %s as racoon management.\n", sunaddr.sun_path);
723
724 return 0;
725 }
726
727 int
728 admin_close()
729 {
730 close(lcconf->sock_admin);
731 return 0;
732 }
733 #endif