No empty .Rs/.Re
[netbsd-mini2440.git] / crypto / dist / ipsec-tools / src / racoon / admin.c
blob58817d213fd39d292d083f738d328d94f501d95c
1 /* $NetBSD: admin.c,v 1.31 2009/07/03 06:41:46 tteras Exp $ */
3 /* Id: admin.c,v 1.25 2006/04/06 14:31:04 manubsd Exp */
5 /*
6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * All rights reserved.
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.
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.
34 #include "config.h"
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>
43 #include <net/pfkeyv2.h>
45 #include <netinet/in.h>
46 #include PATH_IPSEC_H
49 #include <stdlib.h>
50 #include <stdio.h>
51 #include <string.h>
52 #include <errno.h>
53 #include <netdb.h>
54 #ifdef HAVE_UNISTD_H
55 #include <unistd.h>
56 #endif
57 #ifdef ENABLE_HYBRID
58 #include <resolv.h>
59 #endif
61 #include "var.h"
62 #include "misc.h"
63 #include "vmbuf.h"
64 #include "plog.h"
65 #include "sockmisc.h"
66 #include "debug.h"
68 #include "schedule.h"
69 #include "localconf.h"
70 #include "remoteconf.h"
71 #include "grabmyaddr.h"
72 #include "isakmp_var.h"
73 #include "isakmp.h"
74 #include "oakley.h"
75 #include "handler.h"
76 #include "evt.h"
77 #include "pfkey.h"
78 #include "ipsec_doi.h"
79 #include "policy.h"
80 #include "admin.h"
81 #include "admin_var.h"
82 #include "isakmp_inf.h"
83 #ifdef ENABLE_HYBRID
84 #include "isakmp_cfg.h"
85 #endif
86 #include "session.h"
87 #include "gcmalloc.h"
89 #ifdef ENABLE_ADMINPORT
90 char *adminsock_path = ADMINSOCK_PATH;
91 uid_t adminsock_owner = 0;
92 gid_t adminsock_group = 0;
93 mode_t adminsock_mode = 0600;
95 static struct sockaddr_un sunaddr;
96 static int admin_process __P((int, char *));
97 static int admin_reply __P((int, struct admin_com *, int, vchar_t *));
99 static int
100 admin_handler(ctx, fd)
101 void *ctx;
102 int fd;
104 int so2;
105 struct sockaddr_storage from;
106 socklen_t fromlen = sizeof(from);
107 struct admin_com com;
108 char *combuf = NULL;
109 int len, error = -1;
111 so2 = accept(lcconf->sock_admin, (struct sockaddr *)&from, &fromlen);
112 if (so2 < 0) {
113 plog(LLV_ERROR, LOCATION, NULL,
114 "failed to accept admin command: %s\n",
115 strerror(errno));
116 return -1;
118 close_on_exec(so2);
120 /* get buffer length */
121 while ((len = recv(so2, (char *)&com, sizeof(com), MSG_PEEK)) < 0) {
122 if (errno == EINTR)
123 continue;
124 plog(LLV_ERROR, LOCATION, NULL,
125 "failed to recv admin command: %s\n",
126 strerror(errno));
127 goto end;
130 /* sanity check */
131 if (len < sizeof(com)) {
132 plog(LLV_ERROR, LOCATION, NULL,
133 "invalid header length of admin command\n");
134 goto end;
137 /* get buffer to receive */
138 if ((combuf = racoon_malloc(com.ac_len)) == 0) {
139 plog(LLV_ERROR, LOCATION, NULL,
140 "failed to alloc buffer for admin command\n");
141 goto end;
144 /* get real data */
145 while ((len = recv(so2, combuf, com.ac_len, 0)) < 0) {
146 if (errno == EINTR)
147 continue;
148 plog(LLV_ERROR, LOCATION, NULL,
149 "failed to recv admin command: %s\n",
150 strerror(errno));
151 goto end;
154 error = admin_process(so2, combuf);
156 end:
157 if (error == -2) {
158 plog(LLV_DEBUG, LOCATION, NULL,
159 "[%d] admin connection established\n", so2);
160 } else {
161 (void)close(so2);
164 if (combuf)
165 racoon_free(combuf);
167 return error;
170 static int admin_ph1_delete_sa(struct ph1handle *iph1, void *arg)
172 if (iph1->status >= PHASE1ST_ESTABLISHED)
173 isakmp_info_send_d1(iph1);
174 purge_remote(iph1);
175 return 0;
179 * main child's process.
181 static int
182 admin_process(so2, combuf)
183 int so2;
184 char *combuf;
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 = 0, l_ac_errno = 0;
192 struct evt_listener_list *event_list = NULL;
194 if (com->ac_cmd & ADMIN_FLAG_VERSION)
195 com->ac_cmd &= ~ADMIN_FLAG_VERSION;
196 else
197 com->ac_version = 0;
199 switch (com->ac_cmd) {
200 case ADMIN_RELOAD_CONF:
201 signal_handler(SIGHUP);
202 break;
204 case ADMIN_SHOW_SCHED: {
205 caddr_t p = NULL;
206 int len;
208 if (sched_dump(&p, &len) != -1) {
209 buf = vmalloc(len);
210 if (buf != NULL)
211 memcpy(buf->v, p, len);
212 else
213 l_ac_errno = ENOMEM;
214 racoon_free(p);
215 } else
216 l_ac_errno = ENOMEM;
217 break;
220 case ADMIN_SHOW_EVT:
221 if (com->ac_version == 0) {
222 buf = evt_dump();
223 l_ac_errno = 0;
225 break;
227 case ADMIN_SHOW_SA:
228 switch (com->ac_proto) {
229 case ADMIN_PROTO_ISAKMP:
230 buf = dumpph1();
231 if (buf == NULL)
232 l_ac_errno = ENOMEM;
233 break;
234 case ADMIN_PROTO_IPSEC:
235 case ADMIN_PROTO_AH:
236 case ADMIN_PROTO_ESP: {
237 u_int p;
238 p = admin2pfkey_proto(com->ac_proto);
239 if (p != -1) {
240 buf = pfkey_dump_sadb(p);
241 if (buf == NULL)
242 l_ac_errno = ENOMEM;
243 } else
244 l_ac_errno = EINVAL;
245 break;
247 case ADMIN_PROTO_INTERNAL:
248 default:
249 l_ac_errno = ENOTSUP;
250 break;
252 break;
254 case ADMIN_GET_SA_CERT: {
255 struct admin_com_indexes *ndx;
256 struct sockaddr *src, *dst;
257 struct ph1handle *iph1;
259 ndx = (struct admin_com_indexes *) ((caddr_t)com + sizeof(*com));
260 src = (struct sockaddr *) &ndx->src;
261 dst = (struct sockaddr *) &ndx->dst;
263 if (com->ac_proto != ADMIN_PROTO_ISAKMP) {
264 l_ac_errno = ENOTSUP;
265 break;
268 iph1 = getph1byaddr(src, dst, 0);
269 if (iph1 == NULL) {
270 l_ac_errno = ENOENT;
271 break;
274 if (iph1->cert_p != NULL) {
275 vchar_t tmp;
276 tmp.v = iph1->cert_p->v + 1;
277 tmp.l = iph1->cert_p->l - 1;
278 buf = vdup(&tmp);
280 break;
283 case ADMIN_FLUSH_SA:
284 switch (com->ac_proto) {
285 case ADMIN_PROTO_ISAKMP:
286 flushph1();
287 break;
288 case ADMIN_PROTO_IPSEC:
289 case ADMIN_PROTO_AH:
290 case ADMIN_PROTO_ESP:
291 pfkey_flush_sadb(com->ac_proto);
292 break;
293 case ADMIN_PROTO_INTERNAL:
294 /*XXX flushph2();*/
295 default:
296 l_ac_errno = ENOTSUP;
297 break;
299 break;
301 case ADMIN_DELETE_SA: {
302 struct ph1handle *iph1;
303 struct ph1selector sel;
304 char *loc, *rem;
306 memset(&sel, 0, sizeof(sel));
307 sel.local = (struct sockaddr *)
308 &((struct admin_com_indexes *)
309 ((caddr_t)com + sizeof(*com)))->src;
310 sel.remote = (struct sockaddr *)
311 &((struct admin_com_indexes *)
312 ((caddr_t)com + sizeof(*com)))->dst;
314 loc = racoon_strdup(saddr2str(sel.local));
315 rem = racoon_strdup(saddr2str(sel.remote));
316 STRDUP_FATAL(loc);
317 STRDUP_FATAL(rem);
319 plog(LLV_INFO, LOCATION, NULL,
320 "admin delete-sa %s %s\n", loc, rem);
321 enumph1(&sel, admin_ph1_delete_sa, NULL);
323 racoon_free(loc);
324 racoon_free(rem);
325 break;
328 #ifdef ENABLE_HYBRID
329 case ADMIN_LOGOUT_USER: {
330 struct ph1handle *iph1;
331 char user[LOGINLEN+1];
332 int found = 0, len = com->ac_len - sizeof(com);
334 if (len > LOGINLEN) {
335 plog(LLV_ERROR, LOCATION, NULL,
336 "malformed message (login too long)\n");
337 break;
340 memcpy(user, (char *)(com + 1), len);
341 user[len] = 0;
343 found = purgeph1bylogin(user);
344 plog(LLV_INFO, LOCATION, NULL,
345 "deleted %d SA for user \"%s\"\n", found, user);
347 break;
349 #endif
351 case ADMIN_DELETE_ALL_SA_DST: {
352 struct ph1handle *iph1;
353 struct sockaddr *dst;
354 char *loc, *rem;
356 dst = (struct sockaddr *)
357 &((struct admin_com_indexes *)
358 ((caddr_t)com + sizeof(*com)))->dst;
360 rem = racoon_strdup(saddrwop2str(dst));
361 STRDUP_FATAL(rem);
363 plog(LLV_INFO, LOCATION, NULL,
364 "Flushing all SAs for peer %s\n", rem);
366 while ((iph1 = getph1bydstaddr(dst)) != NULL) {
367 loc = racoon_strdup(saddrwop2str(iph1->local));
368 STRDUP_FATAL(loc);
370 if (iph1->status >= PHASE1ST_ESTABLISHED)
371 isakmp_info_send_d1(iph1);
372 purge_remote(iph1);
374 racoon_free(loc);
377 racoon_free(rem);
378 break;
381 case ADMIN_ESTABLISH_SA_PSK: {
382 struct admin_com_psk *acp;
383 char *data;
385 acp = (struct admin_com_psk *)
386 ((char *)com + sizeof(*com) +
387 sizeof(struct admin_com_indexes));
389 idtype = acp->id_type;
391 if ((id = vmalloc(acp->id_len)) == NULL) {
392 plog(LLV_ERROR, LOCATION, NULL,
393 "cannot allocate memory: %s\n",
394 strerror(errno));
395 break;
397 data = (char *)(acp + 1);
398 memcpy(id->v, data, id->l);
400 if ((key = vmalloc(acp->key_len)) == NULL) {
401 plog(LLV_ERROR, LOCATION, NULL,
402 "cannot allocate memory: %s\n",
403 strerror(errno));
404 vfree(id);
405 id = NULL;
406 break;
408 data = (char *)(data + acp->id_len);
409 memcpy(key->v, data, key->l);
411 /* FALLTHROUGH */
412 case ADMIN_ESTABLISH_SA: {
413 struct admin_com_indexes *ndx;
414 struct sockaddr *dst;
415 struct sockaddr *src;
416 char *name = NULL;
418 ndx = (struct admin_com_indexes *) ((caddr_t)com + sizeof(*com));
419 src = (struct sockaddr *) &ndx->src;
420 dst = (struct sockaddr *) &ndx->dst;
422 if (com->ac_cmd == ADMIN_ESTABLISH_SA &&
423 com->ac_len > sizeof(*com) + sizeof(*ndx))
424 name = (char *) ((caddr_t) ndx + sizeof(*ndx));
426 switch (com->ac_proto) {
427 case ADMIN_PROTO_ISAKMP: {
428 struct ph1handle *ph1;
429 struct remoteconf *rmconf;
430 u_int16_t port;
432 l_ac_errno = -1;
434 /* connected already? */
435 ph1 = getph1byaddr(src, dst, 0);
436 if (ph1 != NULL) {
437 event_list = &ph1->evt_listeners;
438 if (ph1->status == PHASE1ST_ESTABLISHED)
439 l_ac_errno = EEXIST;
440 else
441 l_ac_errno = 0;
442 break;
445 /* search appropreate configuration */
446 if (name == NULL)
447 rmconf = getrmconf(dst, 0);
448 else
449 rmconf = getrmconf_by_name(name);
450 if (rmconf == NULL) {
451 plog(LLV_ERROR, LOCATION, NULL,
452 "no configuration found "
453 "for %s\n", saddrwop2str(dst));
454 break;
457 #ifdef ENABLE_HYBRID
458 /* XXX This overwrites rmconf information globally. */
459 /* Set the id and key */
460 if (id && key) {
461 if (xauth_rmconf_used(&rmconf->xauth) == -1)
462 break;
464 if (rmconf->xauth->login != NULL) {
465 vfree(rmconf->xauth->login);
466 rmconf->xauth->login = NULL;
468 if (rmconf->xauth->pass != NULL) {
469 vfree(rmconf->xauth->pass);
470 rmconf->xauth->pass = NULL;
473 rmconf->xauth->login = id;
474 rmconf->xauth->pass = key;
476 #endif
478 plog(LLV_INFO, LOCATION, NULL,
479 "accept a request to establish IKE-SA: "
480 "%s\n", saddrwop2str(dst));
482 /* begin ident mode */
483 ph1 = isakmp_ph1begin_i(rmconf, dst, src);
484 if (ph1 == NULL)
485 break;
487 event_list = &ph1->evt_listeners;
488 l_ac_errno = 0;
489 break;
491 case ADMIN_PROTO_AH:
492 case ADMIN_PROTO_ESP: {
493 struct ph2handle *iph2;
494 struct secpolicy *sp_out = NULL, *sp_in = NULL;
495 struct policyindex spidx;
497 l_ac_errno = -1;
499 /* got outbound policy */
500 memset(&spidx, 0, sizeof(spidx));
501 spidx.dir = IPSEC_DIR_OUTBOUND;
502 memcpy(&spidx.src, src, sizeof(spidx.src));
503 memcpy(&spidx.dst, dst, sizeof(spidx.dst));
504 spidx.prefs = ndx->prefs;
505 spidx.prefd = ndx->prefd;
506 spidx.ul_proto = ndx->ul_proto;
508 sp_out = getsp_r(&spidx);
509 if (sp_out) {
510 plog(LLV_DEBUG, LOCATION, NULL,
511 "suitable outbound SP found: %s.\n",
512 spidx2str(&sp_out->spidx));
513 } else {
514 l_ac_errno = ENOENT;
515 plog(LLV_NOTIFY, LOCATION, NULL,
516 "no outbound policy found: %s\n",
517 spidx2str(&spidx));
518 break;
521 iph2 = getph2byid(src, dst, sp_out->id);
522 if (iph2 != NULL) {
523 event_list = &iph2->evt_listeners;
524 if (iph2->status == PHASE2ST_ESTABLISHED)
525 l_ac_errno = EEXIST;
526 else
527 l_ac_errno = 0;
528 break;
531 /* get inbound policy */
532 memset(&spidx, 0, sizeof(spidx));
533 spidx.dir = IPSEC_DIR_INBOUND;
534 memcpy(&spidx.src, dst, sizeof(spidx.src));
535 memcpy(&spidx.dst, src, sizeof(spidx.dst));
536 spidx.prefs = ndx->prefd;
537 spidx.prefd = ndx->prefs;
538 spidx.ul_proto = ndx->ul_proto;
540 sp_in = getsp_r(&spidx);
541 if (sp_in) {
542 plog(LLV_DEBUG, LOCATION, NULL,
543 "suitable inbound SP found: %s.\n",
544 spidx2str(&sp_in->spidx));
545 } else {
546 l_ac_errno = ENOENT;
547 plog(LLV_NOTIFY, LOCATION, NULL,
548 "no inbound policy found: %s\n",
549 spidx2str(&spidx));
550 break;
553 /* allocate a phase 2 */
554 iph2 = newph2();
555 if (iph2 == NULL) {
556 plog(LLV_ERROR, LOCATION, NULL,
557 "failed to allocate phase2 entry.\n");
558 break;
560 iph2->side = INITIATOR;
561 iph2->satype = admin2pfkey_proto(com->ac_proto);
562 iph2->spid = sp_out->id;
563 iph2->seq = pk_getseq();
564 iph2->status = PHASE2ST_STATUS2;
566 /* set end addresses of SA */
567 iph2->dst = dupsaddr(dst);
568 iph2->src = dupsaddr(src);
569 if (iph2->dst == NULL || iph2->src == NULL) {
570 delph2(iph2);
571 break;
574 if (isakmp_get_sainfo(iph2, sp_out, sp_in) < 0) {
575 delph2(iph2);
576 break;
579 insph2(iph2);
580 if (isakmp_post_acquire(iph2, NULL) < 0) {
581 remph2(iph2);
582 delph2(iph2);
583 break;
586 event_list = &iph2->evt_listeners;
587 l_ac_errno = 0;
588 break;
590 default:
591 /* ignore */
592 l_ac_errno = ENOTSUP;
594 break;
597 default:
598 plog(LLV_ERROR, LOCATION, NULL,
599 "invalid command: %d\n", com->ac_cmd);
600 l_ac_errno = ENOTSUP;
603 if ((error = admin_reply(so2, com, l_ac_errno, buf)) != 0)
604 goto out;
606 /* start pushing events if so requested */
607 if ((l_ac_errno == 0) &&
608 (com->ac_version >= 1) &&
609 (com->ac_cmd == ADMIN_SHOW_EVT || event_list != NULL))
610 error = evt_subscribe(event_list, so2);
611 out:
612 if (buf != NULL)
613 vfree(buf);
615 return error;
618 static int
619 admin_reply(so, req, l_ac_errno, buf)
620 int so, l_ac_errno;
621 struct admin_com *req;
622 vchar_t *buf;
624 int tlen;
625 struct admin_com *combuf;
626 char *retbuf = NULL;
628 if (buf != NULL)
629 tlen = sizeof(*combuf) + buf->l;
630 else
631 tlen = sizeof(*combuf);
633 retbuf = racoon_calloc(1, tlen);
634 if (retbuf == NULL) {
635 plog(LLV_ERROR, LOCATION, NULL,
636 "failed to allocate admin buffer\n");
637 return -1;
640 combuf = (struct admin_com *) retbuf;
641 combuf->ac_len = tlen;
642 combuf->ac_cmd = req->ac_cmd & ~ADMIN_FLAG_VERSION;
643 combuf->ac_errno = l_ac_errno;
644 combuf->ac_proto = req->ac_proto;
646 if (buf != NULL)
647 memcpy(retbuf + sizeof(*combuf), buf->v, buf->l);
649 tlen = send(so, retbuf, tlen, 0);
650 racoon_free(retbuf);
651 if (tlen < 0) {
652 plog(LLV_ERROR, LOCATION, NULL,
653 "failed to send admin command: %s\n",
654 strerror(errno));
655 return -1;
658 return 0;
661 /* ADMIN_PROTO -> SADB_SATYPE */
663 admin2pfkey_proto(proto)
664 u_int proto;
666 switch (proto) {
667 case ADMIN_PROTO_IPSEC:
668 return SADB_SATYPE_UNSPEC;
669 case ADMIN_PROTO_AH:
670 return SADB_SATYPE_AH;
671 case ADMIN_PROTO_ESP:
672 return SADB_SATYPE_ESP;
673 default:
674 plog(LLV_ERROR, LOCATION, NULL,
675 "unsupported proto for admin: %d\n", proto);
676 return -1;
678 /*NOTREACHED*/
682 admin_init()
684 if (adminsock_path == NULL) {
685 lcconf->sock_admin = -1;
686 return 0;
689 memset(&sunaddr, 0, sizeof(sunaddr));
690 sunaddr.sun_family = AF_UNIX;
691 snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path),
692 "%s", adminsock_path);
694 lcconf->sock_admin = socket(AF_UNIX, SOCK_STREAM, 0);
695 if (lcconf->sock_admin == -1) {
696 plog(LLV_ERROR, LOCATION, NULL,
697 "socket: %s\n", strerror(errno));
698 return -1;
700 close_on_exec(lcconf->sock_admin);
702 unlink(sunaddr.sun_path);
703 if (bind(lcconf->sock_admin, (struct sockaddr *)&sunaddr,
704 sizeof(sunaddr)) != 0) {
705 plog(LLV_ERROR, LOCATION, NULL,
706 "bind(sockname:%s): %s\n",
707 sunaddr.sun_path, strerror(errno));
708 (void)close(lcconf->sock_admin);
709 return -1;
712 if (chown(sunaddr.sun_path, adminsock_owner, adminsock_group) != 0) {
713 plog(LLV_ERROR, LOCATION, NULL,
714 "chown(%s, %d, %d): %s\n",
715 sunaddr.sun_path, adminsock_owner,
716 adminsock_group, strerror(errno));
717 (void)close(lcconf->sock_admin);
718 return -1;
721 if (chmod(sunaddr.sun_path, adminsock_mode) != 0) {
722 plog(LLV_ERROR, LOCATION, NULL,
723 "chmod(%s, 0%03o): %s\n",
724 sunaddr.sun_path, adminsock_mode, strerror(errno));
725 (void)close(lcconf->sock_admin);
726 return -1;
729 if (listen(lcconf->sock_admin, 5) != 0) {
730 plog(LLV_ERROR, LOCATION, NULL,
731 "listen(sockname:%s): %s\n",
732 sunaddr.sun_path, strerror(errno));
733 (void)close(lcconf->sock_admin);
734 return -1;
737 monitor_fd(lcconf->sock_admin, admin_handler, NULL);
738 plog(LLV_DEBUG, LOCATION, NULL,
739 "open %s as racoon management.\n", sunaddr.sun_path);
741 return 0;
745 admin_close()
747 unmonitor_fd(lcconf->sock_admin);
748 close(lcconf->sock_admin);
749 return 0;
752 #endif