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 */
6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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
36 #include <sys/types.h>
37 #include <sys/param.h>
38 #include <sys/socket.h>
39 #include <sys/signal.h>
43 #include <net/pfkeyv2.h>
45 #include <netinet/in.h>
69 #include "localconf.h"
70 #include "remoteconf.h"
71 #include "grabmyaddr.h"
72 #include "isakmp_var.h"
78 #include "ipsec_doi.h"
81 #include "admin_var.h"
82 #include "isakmp_inf.h"
84 #include "isakmp_cfg.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
*));
100 admin_handler(ctx
, fd
)
105 struct sockaddr_storage from
;
106 socklen_t fromlen
= sizeof(from
);
107 struct admin_com com
;
111 so2
= accept(lcconf
->sock_admin
, (struct sockaddr
*)&from
, &fromlen
);
113 plog(LLV_ERROR
, LOCATION
, NULL
,
114 "failed to accept admin command: %s\n",
120 /* get buffer length */
121 while ((len
= recv(so2
, (char *)&com
, sizeof(com
), MSG_PEEK
)) < 0) {
124 plog(LLV_ERROR
, LOCATION
, NULL
,
125 "failed to recv admin command: %s\n",
131 if (len
< sizeof(com
)) {
132 plog(LLV_ERROR
, LOCATION
, NULL
,
133 "invalid header length of admin command\n");
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");
145 while ((len
= recv(so2
, combuf
, com
.ac_len
, 0)) < 0) {
148 plog(LLV_ERROR
, LOCATION
, NULL
,
149 "failed to recv admin command: %s\n",
154 error
= admin_process(so2
, combuf
);
158 plog(LLV_DEBUG
, LOCATION
, NULL
,
159 "[%d] admin connection established\n", so2
);
170 static int admin_ph1_delete_sa(struct ph1handle
*iph1
, void *arg
)
172 if (iph1
->status
>= PHASE1ST_ESTABLISHED
)
173 isakmp_info_send_d1(iph1
);
179 * main child's process.
182 admin_process(so2
, combuf
)
186 struct admin_com
*com
= (struct admin_com
*)combuf
;
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
;
199 switch (com
->ac_cmd
) {
200 case ADMIN_RELOAD_CONF
:
201 signal_handler(SIGHUP
);
204 case ADMIN_SHOW_SCHED
: {
208 if (sched_dump(&p
, &len
) != -1) {
211 memcpy(buf
->v
, p
, len
);
221 if (com
->ac_version
== 0) {
228 switch (com
->ac_proto
) {
229 case ADMIN_PROTO_ISAKMP
:
234 case ADMIN_PROTO_IPSEC
:
236 case ADMIN_PROTO_ESP
: {
238 p
= admin2pfkey_proto(com
->ac_proto
);
240 buf
= pfkey_dump_sadb(p
);
247 case ADMIN_PROTO_INTERNAL
:
249 l_ac_errno
= ENOTSUP
;
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
;
268 iph1
= getph1byaddr(src
, dst
, 0);
274 if (iph1
->cert_p
!= NULL
) {
276 tmp
.v
= iph1
->cert_p
->v
+ 1;
277 tmp
.l
= iph1
->cert_p
->l
- 1;
284 switch (com
->ac_proto
) {
285 case ADMIN_PROTO_ISAKMP
:
288 case ADMIN_PROTO_IPSEC
:
290 case ADMIN_PROTO_ESP
:
291 pfkey_flush_sadb(com
->ac_proto
);
293 case ADMIN_PROTO_INTERNAL
:
296 l_ac_errno
= ENOTSUP
;
301 case ADMIN_DELETE_SA
: {
302 struct ph1handle
*iph1
;
303 struct ph1selector sel
;
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
));
319 plog(LLV_INFO
, LOCATION
, NULL
,
320 "admin delete-sa %s %s\n", loc
, rem
);
321 enumph1(&sel
, admin_ph1_delete_sa
, NULL
);
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");
340 memcpy(user
, (char *)(com
+ 1), len
);
343 found
= purgeph1bylogin(user
);
344 plog(LLV_INFO
, LOCATION
, NULL
,
345 "deleted %d SA for user \"%s\"\n", found
, user
);
351 case ADMIN_DELETE_ALL_SA_DST
: {
352 struct ph1handle
*iph1
;
353 struct sockaddr
*dst
;
356 dst
= (struct sockaddr
*)
357 &((struct admin_com_indexes
*)
358 ((caddr_t
)com
+ sizeof(*com
)))->dst
;
360 rem
= racoon_strdup(saddrwop2str(dst
));
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
));
370 if (iph1
->status
>= PHASE1ST_ESTABLISHED
)
371 isakmp_info_send_d1(iph1
);
381 case ADMIN_ESTABLISH_SA_PSK
: {
382 struct admin_com_psk
*acp
;
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",
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",
408 data
= (char *)(data
+ acp
->id_len
);
409 memcpy(key
->v
, data
, key
->l
);
412 case ADMIN_ESTABLISH_SA
: {
413 struct admin_com_indexes
*ndx
;
414 struct sockaddr
*dst
;
415 struct sockaddr
*src
;
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
;
434 /* connected already? */
435 ph1
= getph1byaddr(src
, dst
, 0);
437 event_list
= &ph1
->evt_listeners
;
438 if (ph1
->status
== PHASE1ST_ESTABLISHED
)
445 /* search appropreate configuration */
447 rmconf
= getrmconf(dst
, 0);
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
));
458 /* XXX This overwrites rmconf information globally. */
459 /* Set the id and key */
461 if (xauth_rmconf_used(&rmconf
->xauth
) == -1)
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
;
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
);
487 event_list
= &ph1
->evt_listeners
;
492 case ADMIN_PROTO_ESP
: {
493 struct ph2handle
*iph2
;
494 struct secpolicy
*sp_out
= NULL
, *sp_in
= NULL
;
495 struct policyindex spidx
;
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
);
510 plog(LLV_DEBUG
, LOCATION
, NULL
,
511 "suitable outbound SP found: %s.\n",
512 spidx2str(&sp_out
->spidx
));
515 plog(LLV_NOTIFY
, LOCATION
, NULL
,
516 "no outbound policy found: %s\n",
521 iph2
= getph2byid(src
, dst
, sp_out
->id
);
523 event_list
= &iph2
->evt_listeners
;
524 if (iph2
->status
== PHASE2ST_ESTABLISHED
)
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
);
542 plog(LLV_DEBUG
, LOCATION
, NULL
,
543 "suitable inbound SP found: %s.\n",
544 spidx2str(&sp_in
->spidx
));
547 plog(LLV_NOTIFY
, LOCATION
, NULL
,
548 "no inbound policy found: %s\n",
553 /* allocate a phase 2 */
556 plog(LLV_ERROR
, LOCATION
, NULL
,
557 "failed to allocate phase2 entry.\n");
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
) {
574 if (isakmp_get_sainfo(iph2
, sp_out
, sp_in
) < 0) {
580 if (isakmp_post_acquire(iph2
, NULL
) < 0) {
586 event_list
= &iph2
->evt_listeners
;
592 l_ac_errno
= ENOTSUP
;
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)
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
);
619 admin_reply(so
, req
, l_ac_errno
, buf
)
621 struct admin_com
*req
;
625 struct admin_com
*combuf
;
629 tlen
= sizeof(*combuf
) + buf
->l
;
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");
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
;
647 memcpy(retbuf
+ sizeof(*combuf
), buf
->v
, buf
->l
);
649 tlen
= send(so
, retbuf
, tlen
, 0);
652 plog(LLV_ERROR
, LOCATION
, NULL
,
653 "failed to send admin command: %s\n",
661 /* ADMIN_PROTO -> SADB_SATYPE */
663 admin2pfkey_proto(proto
)
667 case ADMIN_PROTO_IPSEC
:
668 return SADB_SATYPE_UNSPEC
;
670 return SADB_SATYPE_AH
;
671 case ADMIN_PROTO_ESP
:
672 return SADB_SATYPE_ESP
;
674 plog(LLV_ERROR
, LOCATION
, NULL
,
675 "unsupported proto for admin: %d\n", proto
);
684 if (adminsock_path
== NULL
) {
685 lcconf
->sock_admin
= -1;
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
));
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
);
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
);
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
);
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
);
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
);
747 unmonitor_fd(lcconf
->sock_admin
);
748 close(lcconf
->sock_admin
);