1 /* $NetBSD: admin.c,v 1.17.6.1 2007/08/01 11:52:19 vanhu 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 <System/net/pfkeyv2.h>
45 #include <netinet/in.h>
46 #ifndef HAVE_NETINET6_IPSEC
47 #include <netinet/ipsec.h>
49 #include <netinet6/ipsec.h>
73 #include "localconf.h"
74 #include "remoteconf.h"
75 #include "grabmyaddr.h"
76 #include "isakmp_var.h"
82 #include "ipsec_doi.h"
84 #include "admin_var.h"
85 #include "isakmp_inf.h"
87 #include "isakmp_cfg.h"
92 #include "vpn_control_var.h"
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;
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
*));
109 struct sockaddr_storage from
;
110 socklen_t fromlen
= sizeof(from
);
111 struct admin_com com
;
115 so2
= accept(lcconf
->sock_admin
, (struct sockaddr
*)&from
, &fromlen
);
117 plog(LLV_ERROR
, LOCATION
, NULL
,
118 "failed to accept admin command: %s\n",
123 /* get buffer length */
124 while ((len
= recv(so2
, (char *)&com
, sizeof(com
), MSG_PEEK
)) < 0) {
127 plog(LLV_ERROR
, LOCATION
, NULL
,
128 "failed to recv admin command: %s\n",
134 if (len
< sizeof(com
)) {
135 plog(LLV_ERROR
, LOCATION
, NULL
,
136 "invalid header length of admin command\n");
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");
148 while ((len
= recv(so2
, combuf
, com
.ac_len
, 0)) < 0) {
151 plog(LLV_ERROR
, LOCATION
, NULL
,
152 "failed to recv admin command: %s\n",
157 if (com
.ac_cmd
== ADMIN_RELOAD_CONF
) {
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
);
168 error
= admin_process(so2
, combuf
);
179 * main child's process.
182 admin_process(so2
, combuf
)
186 struct admin_com
*com
= (struct admin_com
*)combuf
;
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");
201 case ADMIN_SHOW_SCHED
:
208 if (sched_dump(&p
, &len
) == -1)
211 if ((buf
= vmalloc(len
)) == NULL
)
214 memcpy(buf
->v
, p
, len
);
223 /* It's not really an error, don't force racoonctl to quit */
224 if ((buf
= evt_dump()) == NULL
)
231 switch (com
->ac_proto
) {
232 case ADMIN_PROTO_ISAKMP
:
233 switch (com
->ac_cmd
) {
244 case ADMIN_PROTO_IPSEC
:
246 case ADMIN_PROTO_ESP
:
247 switch (com
->ac_cmd
) {
251 p
= admin2pfkey_proto(com
->ac_proto
);
254 buf
= pfkey_dump_sadb(p
);
260 pfkey_flush_sadb(com
->ac_proto
);
265 case ADMIN_PROTO_INTERNAL
:
266 switch (com
->ac_cmd
) {
268 buf
= NULL
; /*XXX dumpph2(&error);*/
270 com
->ac_errno
= error
;
273 /*XXX flushph2(false);*/
286 case ADMIN_DELETE_SA
: {
287 struct ph1handle
*iph1
;
288 struct sockaddr
*dst
;
289 struct sockaddr
*src
;
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
;
299 loc
= racoon_strdup(saddrwop2str(src
));
300 rem
= racoon_strdup(saddrwop2str(dst
));
304 if ((iph1
= getph1byaddrwop(src
, dst
)) == NULL
) {
305 plog(LLV_ERROR
, LOCATION
, NULL
,
306 "phase 1 for %s -> %s not found\n", loc
, rem
);
308 if (iph1
->status
== PHASE1ST_ESTABLISHED
)
309 isakmp_info_send_d1(iph1
);
320 case ADMIN_LOGOUT_USER
: {
321 struct ph1handle
*iph1
;
322 char user
[LOGINLEN
+1];
323 int found
= 0, len
= com
->ac_len
- sizeof(com
);
325 if (len
> LOGINLEN
) {
326 plog(LLV_ERROR
, LOCATION
, NULL
,
327 "malformed message (login too long)\n");
331 memcpy(user
, (char *)(com
+ 1), len
);
334 found
= purgeph1bylogin(user
);
335 plog(LLV_INFO
, LOCATION
, NULL
,
336 "deleted %d SA for user \"%s\"\n", found
, user
);
342 case ADMIN_DELETE_ALL_SA_DST
: {
343 struct ph1handle
*iph1
;
344 struct sockaddr
*dst
;
347 dst
= (struct sockaddr
*)
348 &((struct admin_com_indexes
*)
349 ((caddr_t
)com
+ sizeof(*com
)))->dst
;
351 rem
= racoon_strdup(saddrwop2str(dst
));
354 plog(LLV_INFO
, LOCATION
, NULL
,
355 "Flushing all SAs for peer %s\n", rem
);
357 while ((iph1
= getph1bydstaddrwop(dst
)) != NULL
) {
358 loc
= racoon_strdup(saddrwop2str(iph1
->local
));
361 if (iph1
->status
== PHASE1ST_ESTABLISHED
)
362 isakmp_info_send_d1(iph1
);
374 case ADMIN_ESTABLISH_SA_VPNCONTROL
:
376 struct admin_com_psk
*acp
;
378 struct sockaddr
*dst
;
379 struct bound_addr
*target
;
383 acp
= (struct admin_com_psk
*)
384 ((char *)com
+ sizeof(*com
) +
385 sizeof(struct admin_com_indexes
));
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",
395 if ((id
= vmalloc(acp
->id_len
)) == NULL
) {
396 plog(LLV_ERROR
, LOCATION
, NULL
,
397 "cannot allocate memory: %s\n",
401 data
= (char *)(acp
+ 1);
402 memcpy(id
->v
, data
, id
->l
);
404 if ((key
= vmalloc(acp
->key_len
)) == NULL
) {
405 plog(LLV_ERROR
, LOCATION
, NULL
,
406 "cannot allocate memory: %s\n",
412 data
= (char *)(data
+ acp
->id_len
);
413 memcpy(key
->v
, data
, key
->l
);
415 dst
= (struct sockaddr
*)
416 &((struct admin_com_indexes
*)
417 ((caddr_t
)com
+ sizeof(*com
)))->dst
;
420 target
->address
= ((struct sockaddr_in
*)dst
)->sin_addr
.s_addr
;
423 /* Set the id and key */
426 target
->user_id
= id
;
427 target
->user_pw
= key
;
430 vpn_connect(target
, VPN_STARTED_BY_ADMIN
);
433 if (target
->user_id
!= NULL
)
434 vfree(target
->user_id
);
435 if (target
->user_pw
!= NULL
)
436 vfree(target
->user_pw
);
442 case ADMIN_ESTABLISH_SA_PSK
: {
443 struct admin_com_psk
*acp
;
446 com
->ac_cmd
= ADMIN_ESTABLISH_SA
;
448 acp
= (struct admin_com_psk
*)
449 ((char *)com
+ sizeof(*com
) +
450 sizeof(struct admin_com_indexes
));
452 idtype
= acp
->id_type
;
454 if ((id
= vmalloc(acp
->id_len
)) == NULL
) {
455 plog(LLV_ERROR
, LOCATION
, NULL
,
456 "cannot allocate memory: %s\n",
460 data
= (char *)(acp
+ 1);
461 memcpy(id
->v
, data
, id
->l
);
463 if ((key
= vmalloc(acp
->key_len
)) == NULL
) {
464 plog(LLV_ERROR
, LOCATION
, NULL
,
465 "cannot allocate memory: %s\n",
471 data
= (char *)(data
+ acp
->id_len
);
472 memcpy(key
->v
, data
, key
->l
);
475 case ADMIN_ESTABLISH_SA
:
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
;
486 switch (com
->ac_proto
) {
487 case ADMIN_PROTO_ISAKMP
: {
488 struct remoteconf
*rmconf
;
489 struct sockaddr
*remote
= NULL
;
490 struct sockaddr
*local
= NULL
;
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
));
504 /* get remote IP address and port number. */
505 if ((remote
= dupsaddr(dst
)) == NULL
)
508 switch (remote
->sa_family
) {
510 ((struct sockaddr_in
*)remote
)->sin_port
=
511 ((struct sockaddr_in
*)rmconf
->remote
)->sin_port
;
515 ((struct sockaddr_in6
*)remote
)->sin6_port
=
516 ((struct sockaddr_in6
*)rmconf
->remote
)->sin6_port
;
520 plog(LLV_ERROR
, LOCATION
, NULL
,
521 "invalid family: %d\n",
527 // port = extract_port(rmconf->remote);
528 // if (set_port(remote, port) == NULL)
531 /* get local address */
532 if ((local
= dupsaddr(src
)) == NULL
)
535 port
= ntohs(getmyaddrsport(local
));
536 if (set_port(local
, port
) == NULL
)
540 /* Set the id and key */
542 if (xauth_rmconf_used(&rmconf
->xauth
) == -1)
545 if (rmconf
->xauth
->login
!= NULL
) {
546 vfree(rmconf
->xauth
->login
);
547 rmconf
->xauth
->login
= NULL
;
549 if (rmconf
->xauth
->pass
!= NULL
) {
550 vfree(rmconf
->xauth
->pass
);
551 rmconf
->xauth
->pass
= NULL
;
554 rmconf
->xauth
->login
= id
;
555 rmconf
->xauth
->pass
= key
;
559 plog(LLV_INFO
, LOCATION
, NULL
,
560 "accept a request to establish IKE-SA: "
561 "%s\n", saddrwop2str(remote
));
563 /* begin ident mode */
564 if (isakmp_ph1begin_i(rmconf
, remote
, local
, 0) < 0)
576 case ADMIN_PROTO_ESP
:
586 plog(LLV_ERROR
, LOCATION
, NULL
,
587 "invalid command: %d\n", com
->ac_cmd
);
591 if ((error
= admin_reply(so2
, com
, buf
)) != 0)
603 admin_reply(so
, combuf
, buf
)
605 struct admin_com
*combuf
;
612 tlen
= sizeof(*combuf
) + buf
->l
;
614 tlen
= sizeof(*combuf
);
616 retbuf
= racoon_calloc(1, tlen
);
617 if (retbuf
== NULL
) {
618 plog(LLV_ERROR
, LOCATION
, NULL
,
619 "failed to allocate admin buffer\n");
623 memcpy(retbuf
, combuf
, sizeof(*combuf
));
624 ((struct admin_com
*)retbuf
)->ac_len
= tlen
;
627 memcpy(retbuf
+ sizeof(*combuf
), buf
->v
, buf
->l
);
629 tlen
= send(so
, retbuf
, tlen
, 0);
632 plog(LLV_ERROR
, LOCATION
, NULL
,
633 "failed to send admin command: %s\n",
641 /* ADMIN_PROTO -> SADB_SATYPE */
643 admin2pfkey_proto(proto
)
647 case ADMIN_PROTO_IPSEC
:
648 return SADB_SATYPE_UNSPEC
;
650 return SADB_SATYPE_AH
;
651 case ADMIN_PROTO_ESP
:
652 return SADB_SATYPE_ESP
;
654 plog(LLV_ERROR
, LOCATION
, NULL
,
655 "unsupported proto for admin: %d\n", proto
);
664 if (adminsock_path
== NULL
) {
665 lcconf
->sock_admin
= -1;
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
);
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
));
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
);
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
);
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
);
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
);
715 plog(LLV_DEBUG
, LOCATION
, NULL
,
716 "open %s as racoon management.\n", sunaddr
.sun_path
);
724 close(lcconf
->sock_admin
);