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>
44 #include <System/net/pfkeyv2.h>
46 #include <net/pfkeyv2.h>
49 #include <netinet/in.h>
50 #ifndef HAVE_NETINET6_IPSEC
51 #include <netinet/ipsec.h>
53 #include <netinet6/ipsec.h>
77 #include "localconf.h"
78 #include "remoteconf.h"
79 #include "grabmyaddr.h"
80 #include "isakmp_var.h"
86 #include "ipsec_doi.h"
88 #include "admin_var.h"
89 #include "isakmp_inf.h"
91 #include "isakmp_cfg.h"
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;
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
*));
111 struct sockaddr_storage from
;
112 socklen_t fromlen
= sizeof(from
);
113 struct admin_com com
;
117 so2
= accept(lcconf
->sock_admin
, (struct sockaddr
*)&from
, &fromlen
);
119 plog(LLV_ERROR
, LOCATION
, NULL
,
120 "failed to accept admin command: %s\n",
125 /* get buffer length */
126 while ((len
= recv(so2
, (char *)&com
, sizeof(com
), MSG_PEEK
)) < 0) {
129 plog(LLV_ERROR
, LOCATION
, NULL
,
130 "failed to recv admin command: %s\n",
136 if (len
< sizeof(com
)) {
137 plog(LLV_ERROR
, LOCATION
, NULL
,
138 "invalid header length of admin command\n");
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");
150 while ((len
= recv(so2
, combuf
, com
.ac_len
, 0)) < 0) {
153 plog(LLV_ERROR
, LOCATION
, NULL
,
154 "failed to recv admin command: %s\n",
159 if (com
.ac_cmd
== ADMIN_RELOAD_CONF
) {
160 /* reload does not work at all! */
161 signal_handler(SIGUSR1
);
165 error
= admin_process(so2
, combuf
);
176 * main child's process.
179 admin_process(so2
, combuf
)
183 struct admin_com
*com
= (struct admin_com
*)combuf
;
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");
198 case ADMIN_SHOW_SCHED
:
205 if (sched_dump(&p
, &len
) == -1)
208 if ((buf
= vmalloc(len
)) == NULL
)
211 memcpy(buf
->v
, p
, len
);
220 /* It's not really an error, don't force racoonctl to quit */
221 if ((buf
= evt_dump()) == NULL
)
228 switch (com
->ac_proto
) {
229 case ADMIN_PROTO_ISAKMP
:
230 switch (com
->ac_cmd
) {
241 case ADMIN_PROTO_IPSEC
:
243 case ADMIN_PROTO_ESP
:
244 switch (com
->ac_cmd
) {
248 p
= admin2pfkey_proto(com
->ac_proto
);
251 buf
= pfkey_dump_sadb(p
);
257 pfkey_flush_sadb(com
->ac_proto
);
262 case ADMIN_PROTO_INTERNAL
:
263 switch (com
->ac_cmd
) {
265 buf
= NULL
; /*XXX dumpph2(&error);*/
267 com
->ac_errno
= error
;
270 /*XXX flushph2(false);*/
283 case ADMIN_DELETE_SA
: {
284 struct ph1handle
*iph1
;
285 struct sockaddr
*dst
;
286 struct sockaddr
*src
;
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
;
296 loc
= racoon_strdup(saddrwop2str(src
));
297 rem
= racoon_strdup(saddrwop2str(dst
));
301 if ((iph1
= getph1byaddrwop(src
, dst
)) == NULL
) {
302 plog(LLV_ERROR
, LOCATION
, NULL
,
303 "phase 1 for %s -> %s not found\n", loc
, rem
);
305 if (iph1
->status
== PHASE1ST_ESTABLISHED
)
306 isakmp_info_send_d1(iph1
);
317 case ADMIN_LOGOUT_USER
: {
318 struct ph1handle
*iph1
;
319 char user
[LOGINLEN
+1];
320 int found
= 0, len
= com
->ac_len
- sizeof(com
);
322 if (len
> LOGINLEN
) {
323 plog(LLV_ERROR
, LOCATION
, NULL
,
324 "malformed message (login too long)\n");
328 memcpy(user
, (char *)(com
+ 1), len
);
331 found
= purgeph1bylogin(user
);
332 plog(LLV_INFO
, LOCATION
, NULL
,
333 "deleted %d SA for user \"%s\"\n", found
, user
);
339 case ADMIN_DELETE_ALL_SA_DST
: {
340 struct ph1handle
*iph1
;
341 struct sockaddr
*dst
;
344 dst
= (struct sockaddr
*)
345 &((struct admin_com_indexes
*)
346 ((caddr_t
)com
+ sizeof(*com
)))->dst
;
348 rem
= racoon_strdup(saddrwop2str(dst
));
351 plog(LLV_INFO
, LOCATION
, NULL
,
352 "Flushing all SAs for peer %s\n", rem
);
354 while ((iph1
= getph1bydstaddrwop(dst
)) != NULL
) {
355 loc
= racoon_strdup(saddrwop2str(iph1
->local
));
358 if (iph1
->status
== PHASE1ST_ESTABLISHED
)
359 isakmp_info_send_d1(iph1
);
371 case ADMIN_ESTABLISH_SA_VPNCONTROL
:
373 struct admin_com_psk
*acp
;
375 struct sockaddr
*dst
;
376 struct bound_addr
*target
;
380 acp
= (struct admin_com_psk
*)
381 ((char *)com
+ sizeof(*com
) +
382 sizeof(struct admin_com_indexes
));
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",
392 if ((id
= vmalloc(acp
->id_len
)) == NULL
) {
393 plog(LLV_ERROR
, LOCATION
, NULL
,
394 "cannot allocate memory: %s\n",
398 data
= (char *)(acp
+ 1);
399 memcpy(id
->v
, data
, id
->l
);
401 if ((key
= vmalloc(acp
->key_len
)) == NULL
) {
402 plog(LLV_ERROR
, LOCATION
, NULL
,
403 "cannot allocate memory: %s\n",
409 data
= (char *)(data
+ acp
->id_len
);
410 memcpy(key
->v
, data
, key
->l
);
412 dst
= (struct sockaddr
*)
413 &((struct admin_com_indexes
*)
414 ((caddr_t
)com
+ sizeof(*com
)))->dst
;
417 target
->address
= ((struct sockaddr_in
*)dst
)->sin_addr
.s_addr
;
420 /* Set the id and key */
423 target
->user_id
= id
;
424 target
->user_pw
= key
;
430 if (target
->user_id
!= NULL
)
431 vfree(target
->user_id
);
432 if (target
->user_pw
!= NULL
)
433 vfree(target
->user_pw
);
439 case ADMIN_ESTABLISH_SA_PSK
: {
440 struct admin_com_psk
*acp
;
443 com
->ac_cmd
= ADMIN_ESTABLISH_SA
;
445 acp
= (struct admin_com_psk
*)
446 ((char *)com
+ sizeof(*com
) +
447 sizeof(struct admin_com_indexes
));
449 idtype
= acp
->id_type
;
451 if ((id
= vmalloc(acp
->id_len
)) == NULL
) {
452 plog(LLV_ERROR
, LOCATION
, NULL
,
453 "cannot allocate memory: %s\n",
457 data
= (char *)(acp
+ 1);
458 memcpy(id
->v
, data
, id
->l
);
460 if ((key
= vmalloc(acp
->key_len
)) == NULL
) {
461 plog(LLV_ERROR
, LOCATION
, NULL
,
462 "cannot allocate memory: %s\n",
468 data
= (char *)(data
+ acp
->id_len
);
469 memcpy(key
->v
, data
, key
->l
);
472 case ADMIN_ESTABLISH_SA
:
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
;
483 switch (com
->ac_proto
) {
484 case ADMIN_PROTO_ISAKMP
: {
485 struct remoteconf
*rmconf
;
486 struct sockaddr
*remote
= NULL
;
487 struct sockaddr
*local
= NULL
;
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
));
501 /* get remote IP address and port number. */
502 if ((remote
= dupsaddr(dst
)) == NULL
)
505 switch (remote
->sa_family
) {
507 ((struct sockaddr_in
*)remote
)->sin_port
=
508 ((struct sockaddr_in
*)rmconf
->remote
)->sin_port
;
512 ((struct sockaddr_in6
*)remote
)->sin6_port
=
513 ((struct sockaddr_in6
*)rmconf
->remote
)->sin6_port
;
517 plog(LLV_ERROR
, LOCATION
, NULL
,
518 "invalid family: %d\n",
524 // port = extract_port(rmconf->remote);
525 // if (set_port(remote, port) == NULL)
528 /* get local address */
529 if ((local
= dupsaddr(src
)) == NULL
)
532 port
= ntohs(getmyaddrsport(local
));
533 if (set_port(local
, port
) == NULL
)
537 /* Set the id and key */
539 if (xauth_rmconf_used(&rmconf
->xauth
) == -1)
542 if (rmconf
->xauth
->login
!= NULL
) {
543 vfree(rmconf
->xauth
->login
);
544 rmconf
->xauth
->login
= NULL
;
546 if (rmconf
->xauth
->pass
!= NULL
) {
547 vfree(rmconf
->xauth
->pass
);
548 rmconf
->xauth
->pass
= NULL
;
551 rmconf
->xauth
->login
= id
;
552 rmconf
->xauth
->pass
= key
;
556 plog(LLV_INFO
, LOCATION
, NULL
,
557 "accept a request to establish IKE-SA: "
558 "%s\n", saddrwop2str(remote
));
560 /* begin ident mode */
561 if (isakmp_ph1begin_i(rmconf
, remote
, local
, 0) < 0)
573 case ADMIN_PROTO_ESP
:
583 plog(LLV_ERROR
, LOCATION
, NULL
,
584 "invalid command: %d\n", com
->ac_cmd
);
588 if ((error
= admin_reply(so2
, com
, buf
)) != 0)
600 admin_reply(so
, combuf
, buf
)
602 struct admin_com
*combuf
;
609 tlen
= sizeof(*combuf
) + buf
->l
;
611 tlen
= sizeof(*combuf
);
613 retbuf
= racoon_calloc(1, tlen
);
614 if (retbuf
== NULL
) {
615 plog(LLV_ERROR
, LOCATION
, NULL
,
616 "failed to allocate admin buffer\n");
620 memcpy(retbuf
, combuf
, sizeof(*combuf
));
621 ((struct admin_com
*)retbuf
)->ac_len
= tlen
;
624 memcpy(retbuf
+ sizeof(*combuf
), buf
->v
, buf
->l
);
626 tlen
= send(so
, retbuf
, tlen
, 0);
629 plog(LLV_ERROR
, LOCATION
, NULL
,
630 "failed to send admin command: %s\n",
638 /* ADMIN_PROTO -> SADB_SATYPE */
640 admin2pfkey_proto(proto
)
644 case ADMIN_PROTO_IPSEC
:
645 return SADB_SATYPE_UNSPEC
;
647 return SADB_SATYPE_AH
;
648 case ADMIN_PROTO_ESP
:
649 return SADB_SATYPE_ESP
;
651 plog(LLV_ERROR
, LOCATION
, NULL
,
652 "unsupported proto for admin: %d\n", proto
);
661 if (adminsock_path
== NULL
) {
662 lcconf
->sock_admin
= -1;
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
);
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
));
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
);
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
);
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
);
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
);
712 plog(LLV_DEBUG
, LOCATION
, NULL
,
713 "open %s as racoon management.\n", sunaddr
.sun_path
);
721 close(lcconf
->sock_admin
);