]> git.saurik.com Git - apple/ipsec.git/blob - ipsec-tools/racoon/admin.c
ipsec-93.13.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[LOGINLEN+1];
320 int found = 0, len = com->ac_len - sizeof(com);
321
322 if (len > LOGINLEN) {
323 plog(LLV_ERROR, LOCATION, NULL,
324 "malformed message (login too long)\n");
325 break;
326 }
327
328 memcpy(user, (char *)(com + 1), len);
329 user[len] = 0;
330
331 found = purgeph1bylogin(user);
332 plog(LLV_INFO, LOCATION, NULL,
333 "deleted %d SA for user \"%s\"\n", found, user);
334
335 break;
336 }
337 #endif
338
339 case ADMIN_DELETE_ALL_SA_DST: {
340 struct ph1handle *iph1;
341 struct sockaddr *dst;
342 char *loc, *rem;
343
344 dst = (struct sockaddr *)
345 &((struct admin_com_indexes *)
346 ((caddr_t)com + sizeof(*com)))->dst;
347
348 rem = racoon_strdup(saddrwop2str(dst));
349 STRDUP_FATAL(rem);
350
351 plog(LLV_INFO, LOCATION, NULL,
352 "Flushing all SAs for peer %s\n", rem);
353
354 while ((iph1 = getph1bydstaddrwop(dst)) != NULL) {
355 loc = racoon_strdup(saddrwop2str(iph1->local));
356 STRDUP_FATAL(loc);
357
358 if (iph1->status == PHASE1ST_ESTABLISHED)
359 isakmp_info_send_d1(iph1);
360 purge_remote(iph1);
361
362 racoon_free(loc);
363 }
364
365 racoon_free(rem);
366
367 break;
368 }
369
370 //%%%%%% test code
371 case ADMIN_ESTABLISH_SA_VPNCONTROL:
372 {
373 struct admin_com_psk *acp;
374 char *data;
375 struct sockaddr *dst;
376 struct bound_addr *target;
377
378 com->ac_errno = -1;
379
380 acp = (struct admin_com_psk *)
381 ((char *)com + sizeof(*com) +
382 sizeof(struct admin_com_indexes));
383
384 target = (struct bound_addr *)racoon_malloc(sizeof(struct bound_addr));
385 if (target == NULL) {
386 plog(LLV_ERROR, LOCATION, NULL,
387 "cannot allocate memory: %s\n",
388 strerror(errno));
389 break;
390 }
391
392 if ((id = vmalloc(acp->id_len)) == NULL) {
393 plog(LLV_ERROR, LOCATION, NULL,
394 "cannot allocate memory: %s\n",
395 strerror(errno));
396 goto outofhere;
397 }
398 data = (char *)(acp + 1);
399 memcpy(id->v, data, id->l);
400
401 if ((key = vmalloc(acp->key_len)) == NULL) {
402 plog(LLV_ERROR, LOCATION, NULL,
403 "cannot allocate memory: %s\n",
404 strerror(errno));
405 vfree(id);
406 id = NULL;
407 goto outofhere;
408 }
409 data = (char *)(data + acp->id_len);
410 memcpy(key->v, data, key->l);
411
412 dst = (struct sockaddr *)
413 &((struct admin_com_indexes *)
414 ((caddr_t)com + sizeof(*com)))->dst;
415
416 // assume IPv4
417 target->address = ((struct sockaddr_in *)dst)->sin_addr.s_addr;
418
419 #ifdef ENABLE_HYBRID
420 /* Set the id and key */
421 if (id && key) {
422
423 target->user_id = id;
424 target->user_pw = key;
425 }
426 #endif
427 vpn_connect(target);
428 com->ac_errno = 0;
429 outofhere:
430 if (target->user_id != NULL)
431 vfree(target->user_id);
432 if (target->user_pw != NULL)
433 vfree(target->user_pw);
434 if (target != NULL)
435 racoon_free(target);
436 break;
437 }
438
439 case ADMIN_ESTABLISH_SA_PSK: {
440 struct admin_com_psk *acp;
441 char *data;
442
443 com->ac_cmd = ADMIN_ESTABLISH_SA;
444
445 acp = (struct admin_com_psk *)
446 ((char *)com + sizeof(*com) +
447 sizeof(struct admin_com_indexes));
448
449 idtype = acp->id_type;
450
451 if ((id = vmalloc(acp->id_len)) == NULL) {
452 plog(LLV_ERROR, LOCATION, NULL,
453 "cannot allocate memory: %s\n",
454 strerror(errno));
455 break;
456 }
457 data = (char *)(acp + 1);
458 memcpy(id->v, data, id->l);
459
460 if ((key = vmalloc(acp->key_len)) == NULL) {
461 plog(LLV_ERROR, LOCATION, NULL,
462 "cannot allocate memory: %s\n",
463 strerror(errno));
464 vfree(id);
465 id = NULL;
466 break;
467 }
468 data = (char *)(data + acp->id_len);
469 memcpy(key->v, data, key->l);
470 }
471 /* FALLTHROUGH */
472 case ADMIN_ESTABLISH_SA:
473 {
474 struct sockaddr *dst;
475 struct sockaddr *src;
476 src = (struct sockaddr *)
477 &((struct admin_com_indexes *)
478 ((caddr_t)com + sizeof(*com)))->src;
479 dst = (struct sockaddr *)
480 &((struct admin_com_indexes *)
481 ((caddr_t)com + sizeof(*com)))->dst;
482
483 switch (com->ac_proto) {
484 case ADMIN_PROTO_ISAKMP: {
485 struct remoteconf *rmconf;
486 struct sockaddr *remote = NULL;
487 struct sockaddr *local = NULL;
488 u_int16_t port;
489
490 com->ac_errno = -1;
491
492 /* search appropreate configuration */
493 rmconf = getrmconf(dst);
494 if (rmconf == NULL) {
495 plog(LLV_ERROR, LOCATION, NULL,
496 "no configuration found "
497 "for %s\n", saddrwop2str(dst));
498 goto out1;
499 }
500
501 /* get remote IP address and port number. */
502 if ((remote = dupsaddr(dst)) == NULL)
503 goto out1;
504
505 switch (remote->sa_family) {
506 case AF_INET:
507 ((struct sockaddr_in *)remote)->sin_port =
508 ((struct sockaddr_in *)rmconf->remote)->sin_port;
509 break;
510 #ifdef INET6
511 case AF_INET6:
512 ((struct sockaddr_in6 *)remote)->sin6_port =
513 ((struct sockaddr_in6 *)rmconf->remote)->sin6_port;
514 break;
515 #endif
516 default:
517 plog(LLV_ERROR, LOCATION, NULL,
518 "invalid family: %d\n",
519 remote->sa_family);
520 com->ac_errno = -1;
521 break;
522 }
523
524 // port = extract_port(rmconf->remote);
525 // if (set_port(remote, port) == NULL)
526 // goto out1;
527
528 /* get local address */
529 if ((local = dupsaddr(src)) == NULL)
530 goto out1;
531
532 port = ntohs(getmyaddrsport(local));
533 if (set_port(local, port) == NULL)
534 goto out1;
535
536 #ifdef ENABLE_HYBRID
537 /* Set the id and key */
538 if (id && key) {
539 if (xauth_rmconf_used(&rmconf->xauth) == -1)
540 goto out1;
541
542 if (rmconf->xauth->login != NULL) {
543 vfree(rmconf->xauth->login);
544 rmconf->xauth->login = NULL;
545 }
546 if (rmconf->xauth->pass != NULL) {
547 vfree(rmconf->xauth->pass);
548 rmconf->xauth->pass = NULL;
549 }
550
551 rmconf->xauth->login = id;
552 rmconf->xauth->pass = key;
553 }
554 #endif
555
556 plog(LLV_INFO, LOCATION, NULL,
557 "accept a request to establish IKE-SA: "
558 "%s\n", saddrwop2str(remote));
559
560 /* begin ident mode */
561 if (isakmp_ph1begin_i(rmconf, remote, local, 0) < 0)
562 goto out1;
563
564 com->ac_errno = 0;
565 out1:
566 if (local != NULL)
567 racoon_free(local);
568 if (remote != NULL)
569 racoon_free(remote);
570 break;
571 }
572 case ADMIN_PROTO_AH:
573 case ADMIN_PROTO_ESP:
574 break;
575 default:
576 /* ignore */
577 com->ac_errno = -1;
578 }
579 }
580 break;
581
582 default:
583 plog(LLV_ERROR, LOCATION, NULL,
584 "invalid command: %d\n", com->ac_cmd);
585 com->ac_errno = -1;
586 }
587
588 if ((error = admin_reply(so2, com, buf)) != 0)
589 goto out;
590
591 error = 0;
592 out:
593 if (buf != NULL)
594 vfree(buf);
595
596 return error;
597 }
598
599 static int
600 admin_reply(so, combuf, buf)
601 int so;
602 struct admin_com *combuf;
603 vchar_t *buf;
604 {
605 int tlen;
606 char *retbuf = NULL;
607
608 if (buf != NULL)
609 tlen = sizeof(*combuf) + buf->l;
610 else
611 tlen = sizeof(*combuf);
612
613 retbuf = racoon_calloc(1, tlen);
614 if (retbuf == NULL) {
615 plog(LLV_ERROR, LOCATION, NULL,
616 "failed to allocate admin buffer\n");
617 return -1;
618 }
619
620 memcpy(retbuf, combuf, sizeof(*combuf));
621 ((struct admin_com *)retbuf)->ac_len = tlen;
622
623 if (buf != NULL)
624 memcpy(retbuf + sizeof(*combuf), buf->v, buf->l);
625
626 tlen = send(so, retbuf, tlen, 0);
627 racoon_free(retbuf);
628 if (tlen < 0) {
629 plog(LLV_ERROR, LOCATION, NULL,
630 "failed to send admin command: %s\n",
631 strerror(errno));
632 return -1;
633 }
634
635 return 0;
636 }
637
638 /* ADMIN_PROTO -> SADB_SATYPE */
639 int
640 admin2pfkey_proto(proto)
641 u_int proto;
642 {
643 switch (proto) {
644 case ADMIN_PROTO_IPSEC:
645 return SADB_SATYPE_UNSPEC;
646 case ADMIN_PROTO_AH:
647 return SADB_SATYPE_AH;
648 case ADMIN_PROTO_ESP:
649 return SADB_SATYPE_ESP;
650 default:
651 plog(LLV_ERROR, LOCATION, NULL,
652 "unsupported proto for admin: %d\n", proto);
653 return -1;
654 }
655 /*NOTREACHED*/
656 }
657
658 int
659 admin_init()
660 {
661 if (adminsock_path == NULL) {
662 lcconf->sock_admin = -1;
663 return 0;
664 }
665
666 memset(&sunaddr, 0, sizeof(sunaddr));
667 sunaddr.sun_family = AF_UNIX;
668 snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path),
669 "%s", adminsock_path);
670
671 lcconf->sock_admin = socket(AF_UNIX, SOCK_STREAM, 0);
672 if (lcconf->sock_admin == -1) {
673 plog(LLV_ERROR, LOCATION, NULL,
674 "socket: %s\n", strerror(errno));
675 return -1;
676 }
677
678 unlink(sunaddr.sun_path);
679 if (bind(lcconf->sock_admin, (struct sockaddr *)&sunaddr,
680 sizeof(sunaddr)) != 0) {
681 plog(LLV_ERROR, LOCATION, NULL,
682 "bind(sockname:%s): %s\n",
683 sunaddr.sun_path, strerror(errno));
684 (void)close(lcconf->sock_admin);
685 return -1;
686 }
687
688 if (chown(sunaddr.sun_path, adminsock_owner, adminsock_group) != 0) {
689 plog(LLV_ERROR, LOCATION, NULL,
690 "chown(%s, %d, %d): %s\n",
691 sunaddr.sun_path, adminsock_owner,
692 adminsock_group, strerror(errno));
693 (void)close(lcconf->sock_admin);
694 return -1;
695 }
696
697 if (chmod(sunaddr.sun_path, adminsock_mode) != 0) {
698 plog(LLV_ERROR, LOCATION, NULL,
699 "chmod(%s, 0%03o): %s\n",
700 sunaddr.sun_path, adminsock_mode, strerror(errno));
701 (void)close(lcconf->sock_admin);
702 return -1;
703 }
704
705 if (listen(lcconf->sock_admin, 5) != 0) {
706 plog(LLV_ERROR, LOCATION, NULL,
707 "listen(sockname:%s): %s\n",
708 sunaddr.sun_path, strerror(errno));
709 (void)close(lcconf->sock_admin);
710 return -1;
711 }
712 plog(LLV_DEBUG, LOCATION, NULL,
713 "open %s as racoon management.\n", sunaddr.sun_path);
714
715 return 0;
716 }
717
718 int
719 admin_close()
720 {
721 close(lcconf->sock_admin);
722 return 0;
723 }
724 #endif