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>
74 #include "localconf.h"
75 #include "remoteconf.h"
76 #include "grabmyaddr.h"
77 #include "isakmp_var.h"
83 #include "ipsec_doi.h"
85 #include "admin_var.h"
86 #include "isakmp_inf.h"
88 #include "isakmp_cfg.h"
93 #include "vpn_control_var.h"
96 #ifdef ENABLE_ADMINPORT
97 char *adminsock_path
= ADMINSOCK_PATH
;
98 uid_t adminsock_owner
= 0;
99 gid_t adminsock_group
= 0;
100 mode_t adminsock_mode
= 0600;
102 static struct sockaddr_un sunaddr
;
103 static int admin_process
__P((int, char *));
104 static int admin_reply
__P((int, struct admin_com
*, vchar_t
*));
110 struct sockaddr_storage from
;
111 socklen_t fromlen
= sizeof(from
);
112 struct admin_com com
;
116 so2
= accept(lcconf
->sock_admin
, (struct sockaddr_storage
*)&from
, &fromlen
);
118 plog(LLV_ERROR
, LOCATION
, NULL
,
119 "failed to accept admin command: %s\n",
124 /* get buffer length */
125 while ((len
= recv(so2
, (char *)&com
, sizeof(com
), MSG_PEEK
)) < 0) {
128 plog(LLV_ERROR
, LOCATION
, NULL
,
129 "failed to recv admin command: %s\n",
135 if (len
< sizeof(com
)) {
136 plog(LLV_ERROR
, LOCATION
, NULL
,
137 "invalid header length of admin command\n");
141 /* get buffer to receive */
142 if ((combuf
= racoon_malloc(com
.ac_len
)) == 0) {
143 plog(LLV_ERROR
, LOCATION
, NULL
,
144 "failed to alloc buffer for admin command\n");
149 while ((len
= recv(so2
, combuf
, com
.ac_len
, 0)) < 0) {
152 plog(LLV_ERROR
, LOCATION
, NULL
,
153 "failed to recv admin command: %s\n",
158 if (com
.ac_cmd
== ADMIN_RELOAD_CONF
) {
160 bzero(&sigi
, sizeof(sigi
));
161 sigi
.si_signo
= SIGUSR1
;
162 sigi
.si_pid
= getpid();
163 sigi
.si_uid
= getuid();
164 /* reload does not work at all! */
165 signal_handler(SIGUSR1
, &sigi
, (void *)NULL
);
169 error
= admin_process(so2
, combuf
);
180 * main child's process.
183 admin_process(so2
, combuf
)
187 struct admin_com
*com
= (struct admin_com
*)combuf
;
196 switch (com
->ac_cmd
) {
197 case ADMIN_RELOAD_CONF
:
198 /* don't entered because of proccessing it in other place. */
199 plog(LLV_ERROR
, LOCATION
, NULL
, "should never reach here\n");
202 case ADMIN_SHOW_SCHED
:
209 if (sched_dump(&p
, &len
) == -1)
212 if ((buf
= vmalloc(len
)) == NULL
)
215 memcpy(buf
->v
, p
, len
);
224 /* It's not really an error, don't force racoonctl to quit */
225 if ((buf
= evt_dump()) == NULL
)
232 switch (com
->ac_proto
) {
233 case ADMIN_PROTO_ISAKMP
:
234 switch (com
->ac_cmd
) {
245 case ADMIN_PROTO_IPSEC
:
247 case ADMIN_PROTO_ESP
:
248 switch (com
->ac_cmd
) {
252 p
= admin2pfkey_proto(com
->ac_proto
);
255 buf
= pfkey_dump_sadb(p
);
261 pfkey_flush_sadb(com
->ac_proto
);
266 case ADMIN_PROTO_INTERNAL
:
267 switch (com
->ac_cmd
) {
269 buf
= NULL
; /*XXX dumpph2(&error);*/
271 com
->ac_errno
= error
;
274 /*XXX flushph2(false);*/
287 case ADMIN_DELETE_SA
: {
288 struct ph1handle
*iph1
;
289 struct sockaddr_storage
*dst
;
290 struct sockaddr_storage
*src
;
293 src
= (struct sockaddr_storage
*)
294 &((struct admin_com_indexes
*)
295 ((caddr_t
)com
+ sizeof(*com
)))->src
;
296 dst
= (struct sockaddr_storage
*)
297 &((struct admin_com_indexes
*)
298 ((caddr_t
)com
+ sizeof(*com
)))->dst
;
300 loc
= racoon_strdup(saddrwop2str(src
));
301 rem
= racoon_strdup(saddrwop2str(dst
));
305 if ((iph1
= getph1byaddrwop(src
, dst
)) == NULL
) {
306 plog(LLV_ERROR
, LOCATION
, NULL
,
307 "phase 1 for %s -> %s not found\n", loc
, rem
);
309 if (iph1
->status
== PHASE1ST_ESTABLISHED
)
310 isakmp_info_send_d1(iph1
);
321 case ADMIN_LOGOUT_USER
: {
322 struct ph1handle
*iph1
;
323 char user
[LOGINLEN
+1];
324 int found
= 0, len
= com
->ac_len
- sizeof(com
);
326 if (len
> LOGINLEN
) {
327 plog(LLV_ERROR
, LOCATION
, NULL
,
328 "malformed message (login too long)\n");
332 memcpy(user
, (char *)(com
+ 1), len
);
335 found
= purgeph1bylogin(user
);
336 plog(LLV_INFO
, LOCATION
, NULL
,
337 "deleted %d SA for user \"%s\"\n", found
, user
);
343 case ADMIN_DELETE_ALL_SA_DST
: {
344 struct ph1handle
*iph1
;
345 struct sockaddr_storage
*dst
;
348 dst
= (struct sockaddr_storage
*)
349 &((struct admin_com_indexes
*)
350 ((caddr_t
)com
+ sizeof(*com
)))->dst
;
352 rem
= racoon_strdup(saddrwop2str(dst
));
355 plog(LLV_INFO
, LOCATION
, NULL
,
356 "Flushing all SAs for peer %s\n", rem
);
358 while ((iph1
= getph1bydstaddrwop(dst
)) != NULL
) {
359 loc
= racoon_strdup(saddrwop2str(iph1
->local
));
362 if (iph1
->status
== PHASE1ST_ESTABLISHED
)
363 isakmp_info_send_d1(iph1
);
375 case ADMIN_ESTABLISH_SA_VPNCONTROL
:
377 struct admin_com_psk
*acp
;
379 struct sockaddr_storage
*dst
;
380 struct bound_addr
*target
;
384 acp
= (struct admin_com_psk
*)
385 ((char *)com
+ sizeof(*com
) +
386 sizeof(struct admin_com_indexes
));
388 target
= (struct bound_addr
*)racoon_malloc(sizeof(struct bound_addr
));
389 if (target
== NULL
) {
390 plog(LLV_ERROR
, LOCATION
, NULL
,
391 "cannot allocate memory: %s\n",
396 if ((id
= vmalloc(acp
->id_len
)) == NULL
) {
397 plog(LLV_ERROR
, LOCATION
, NULL
,
398 "cannot allocate memory: %s\n",
402 data
= (char *)(acp
+ 1);
403 memcpy(id
->v
, data
, id
->l
);
405 if ((key
= vmalloc(acp
->key_len
)) == NULL
) {
406 plog(LLV_ERROR
, LOCATION
, NULL
,
407 "cannot allocate memory: %s\n",
413 data
= (char *)(data
+ acp
->id_len
);
414 memcpy(key
->v
, data
, key
->l
);
416 dst
= (struct sockaddr_storage
*)
417 &((struct admin_com_indexes
*)
418 ((caddr_t
)com
+ sizeof(*com
)))->dst
;
421 target
->address
= ((struct sockaddr_in
*)dst
)->sin_addr
.s_addr
;
424 /* Set the id and key */
427 target
->user_id
= id
;
428 target
->user_pw
= key
;
431 vpn_connect(target
, VPN_STARTED_BY_ADMIN
);
434 if (target
->user_id
!= NULL
)
435 vfree(target
->user_id
);
436 if (target
->user_pw
!= NULL
)
437 vfree(target
->user_pw
);
443 case ADMIN_ESTABLISH_SA_PSK
: {
444 struct admin_com_psk
*acp
;
447 com
->ac_cmd
= ADMIN_ESTABLISH_SA
;
449 acp
= (struct admin_com_psk
*)
450 ((char *)com
+ sizeof(*com
) +
451 sizeof(struct admin_com_indexes
));
453 idtype
= acp
->id_type
;
455 if ((id
= vmalloc(acp
->id_len
)) == NULL
) {
456 plog(LLV_ERROR
, LOCATION
, NULL
,
457 "cannot allocate memory: %s\n",
461 data
= (char *)(acp
+ 1);
462 memcpy(id
->v
, data
, id
->l
);
464 if ((key
= vmalloc(acp
->key_len
)) == NULL
) {
465 plog(LLV_ERROR
, LOCATION
, NULL
,
466 "cannot allocate memory: %s\n",
472 data
= (char *)(data
+ acp
->id_len
);
473 memcpy(key
->v
, data
, key
->l
);
476 case ADMIN_ESTABLISH_SA
:
478 struct sockaddr_storage
*dst
;
479 struct sockaddr_storage
*src
;
480 src
= (struct sockaddr_storage
*)
481 &((struct admin_com_indexes
*)
482 ((caddr_t
)com
+ sizeof(*com
)))->src
;
483 dst
= (struct sockaddr_storage
*)
484 &((struct admin_com_indexes
*)
485 ((caddr_t
)com
+ sizeof(*com
)))->dst
;
487 switch (com
->ac_proto
) {
488 case ADMIN_PROTO_ISAKMP
: {
489 struct remoteconf
*rmconf
;
490 struct sockaddr_storage
*remote
= NULL
;
491 struct sockaddr_storage
*local
= NULL
;
496 /* search appropreate configuration */
497 rmconf
= getrmconf(dst
);
498 if (rmconf
== NULL
) {
499 plog(LLV_ERROR
, LOCATION
, NULL
,
500 "no configuration found "
501 "for %s\n", saddrwop2str(dst
));
505 /* get remote IP address and port number. */
506 if ((remote
= dupsaddr(dst
)) == NULL
)
509 switch (remote
->ss_family
) {
511 ((struct sockaddr_in
*)remote
)->sin_port
=
512 ((struct sockaddr_in
*)rmconf
->remote
)->sin_port
;
516 ((struct sockaddr_in6
*)remote
)->sin6_port
=
517 ((struct sockaddr_in6
*)rmconf
->remote
)->sin6_port
;
521 plog(LLV_ERROR
, LOCATION
, NULL
,
522 "invalid family: %d\n",
528 // port = extract_port(rmconf->remote);
529 // if (set_port(remote, port) == NULL)
532 /* get local address */
533 if ((local
= dupsaddr(src
)) == NULL
)
536 port
= ntohs(getmyaddrsport(local
));
537 if (set_port(local
, port
) == NULL
)
541 /* Set the id and key */
543 if (xauth_rmconf_used(&rmconf
->xauth
) == -1)
546 if (rmconf
->xauth
->login
!= NULL
) {
547 vfree(rmconf
->xauth
->login
);
548 rmconf
->xauth
->login
= NULL
;
550 if (rmconf
->xauth
->pass
!= NULL
) {
551 vfree(rmconf
->xauth
->pass
);
552 rmconf
->xauth
->pass
= NULL
;
555 rmconf
->xauth
->login
= id
;
556 rmconf
->xauth
->pass
= key
;
560 plog(LLV_INFO
, LOCATION
, NULL
,
561 "accept a request to establish IKE-SA: "
562 "%s\n", saddrwop2str(remote
));
564 /* begin ident mode */
565 if (isakmp_ph1begin_i(rmconf
, remote
, local
, 0) < 0)
577 case ADMIN_PROTO_ESP
:
587 plog(LLV_ERROR
, LOCATION
, NULL
,
588 "invalid command: %d\n", com
->ac_cmd
);
592 if ((error
= admin_reply(so2
, com
, buf
)) != 0)
604 admin_reply(so
, combuf
, buf
)
606 struct admin_com
*combuf
;
613 tlen
= sizeof(*combuf
) + buf
->l
;
615 tlen
= sizeof(*combuf
);
617 retbuf
= racoon_calloc(1, tlen
);
618 if (retbuf
== NULL
) {
619 plog(LLV_ERROR
, LOCATION
, NULL
,
620 "failed to allocate admin buffer\n");
624 memcpy(retbuf
, combuf
, sizeof(*combuf
));
625 ((struct admin_com
*)retbuf
)->ac_len
= tlen
;
628 memcpy(retbuf
+ sizeof(*combuf
), buf
->v
, buf
->l
);
630 tlen
= send(so
, retbuf
, tlen
, 0);
633 plog(LLV_ERROR
, LOCATION
, NULL
,
634 "failed to send admin command: %s\n",
642 /* ADMIN_PROTO -> SADB_SATYPE */
644 admin2pfkey_proto(proto
)
648 case ADMIN_PROTO_IPSEC
:
649 return SADB_SATYPE_UNSPEC
;
651 return SADB_SATYPE_AH
;
652 case ADMIN_PROTO_ESP
:
653 return SADB_SATYPE_ESP
;
655 plog(LLV_ERROR
, LOCATION
, NULL
,
656 "unsupported proto for admin: %d\n", proto
);
665 if (adminsock_path
== NULL
) {
666 lcconf
->sock_admin
= -1;
670 memset(&sunaddr
, 0, sizeof(sunaddr
));
671 sunaddr
.sun_family
= AF_UNIX
;
672 snprintf(sunaddr
.sun_path
, sizeof(sunaddr
.sun_path
),
673 "%s", adminsock_path
);
675 lcconf
->sock_admin
= socket(AF_UNIX
, SOCK_STREAM
, 0);
676 if (lcconf
->sock_admin
== -1) {
677 plog(LLV_ERROR
, LOCATION
, NULL
,
678 "socket: %s\n", strerror(errno
));
682 if (fcntl(lcconf
->sock_admin
, F_SETFL
, O_NONBLOCK
) == -1) {
683 plog(LLV_ERROR
, LOCATION
, NULL
,
684 "failed to put admin socket in non-blocking mode\n");
687 unlink(sunaddr
.sun_path
);
688 if (bind(lcconf
->sock_admin
, (struct sockaddr_storage
*)&sunaddr
,
689 sizeof(sunaddr
)) != 0) {
690 plog(LLV_ERROR
, LOCATION
, NULL
,
691 "bind(sockname:%s): %s\n",
692 sunaddr
.sun_path
, strerror(errno
));
693 (void)close(lcconf
->sock_admin
);
697 if (chown(sunaddr
.sun_path
, adminsock_owner
, adminsock_group
) != 0) {
698 plog(LLV_ERROR
, LOCATION
, NULL
,
699 "chown(%s, %d, %d): %s\n",
700 sunaddr
.sun_path
, adminsock_owner
,
701 adminsock_group
, strerror(errno
));
702 (void)close(lcconf
->sock_admin
);
706 if (chmod(sunaddr
.sun_path
, adminsock_mode
) != 0) {
707 plog(LLV_ERROR
, LOCATION
, NULL
,
708 "chmod(%s, 0%03o): %s\n",
709 sunaddr
.sun_path
, adminsock_mode
, strerror(errno
));
710 (void)close(lcconf
->sock_admin
);
714 if (listen(lcconf
->sock_admin
, 5) != 0) {
715 plog(LLV_ERROR
, LOCATION
, NULL
,
716 "listen(sockname:%s): %s\n",
717 sunaddr
.sun_path
, strerror(errno
));
718 (void)close(lcconf
->sock_admin
);
721 plog(LLV_DEBUG
, LOCATION
, NULL
,
722 "open %s as racoon management.\n", sunaddr
.sun_path
);
730 close(lcconf
->sock_admin
);