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