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