]>
git.saurik.com Git - apple/ipsec.git/blob - ipsec-tools/racoon/admin.c
1 /* $Id: admin.c,v 1.17.2.4 2005/07/12 11:49:44 manubsd Exp $ */
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/socket.h>
37 #include <sys/signal.h>
42 #include <System/net/pfkeyv2.h>
44 #include <net/pfkeyv2.h>
47 #include <netinet/in.h>
48 #ifndef HAVE_NETINET6_IPSEC
49 #include <netinet/ipsec.h>
51 #include <netinet6/ipsec.h>
72 #include "localconf.h"
73 #include "remoteconf.h"
74 #include "grabmyaddr.h"
75 #include "isakmp_var.h"
81 #include "ipsec_doi.h"
83 #include "admin_var.h"
84 #include "isakmp_inf.h"
88 #ifdef ENABLE_ADMINPORT
89 char *adminsock_path
= ADMINSOCK_PATH
;
90 uid_t adminsock_owner
= 0;
91 gid_t adminsock_group
= 0;
92 mode_t adminsock_mode
= 0600;
94 static struct sockaddr_un sunaddr
;
95 static int admin_process
__P((int, char *));
96 static int admin_reply
__P((int, struct admin_com
*, vchar_t
*));
102 struct sockaddr_storage from
;
103 socklen_t fromlen
= sizeof(from
);
104 struct admin_com com
;
109 so2
= accept(lcconf
->sock_admin
, (struct sockaddr
*)&from
, &fromlen
);
111 plog(LLV_ERROR
, LOCATION
, NULL
,
112 "failed to accept admin command: %s\n",
117 /* get buffer length */
118 while ((len
= recv(so2
, (char *)&com
, sizeof(com
), MSG_PEEK
)) < 0) {
121 plog(LLV_ERROR
, LOCATION
, NULL
,
122 "failed to recv admin command: %s\n",
128 if (len
< sizeof(com
)) {
129 plog(LLV_ERROR
, LOCATION
, NULL
,
130 "invalid header length of admin command\n");
134 /* get buffer to receive */
135 if ((combuf
= racoon_malloc(com
.ac_len
)) == 0) {
136 plog(LLV_ERROR
, LOCATION
, NULL
,
137 "failed to alloc buffer for admin command\n");
142 while ((len
= recv(so2
, combuf
, com
.ac_len
, 0)) < 0) {
145 plog(LLV_ERROR
, LOCATION
, NULL
,
146 "failed to recv admin command: %s\n",
151 if (com
.ac_cmd
== ADMIN_RELOAD_CONF
) {
152 /* reload does not work at all! */
153 signal_handler(SIGHUP
);
157 error
= admin_process(so2
, combuf
);
164 /* exit if child's process. */
165 if (pid
== 0 && !f_foreground
)
172 * main child's process.
175 admin_process(so2
, combuf
)
179 struct admin_com
*com
= (struct admin_com
*)combuf
;
188 switch (com
->ac_cmd
) {
189 case ADMIN_RELOAD_CONF
:
190 /* don't entered because of proccessing it in other place. */
191 plog(LLV_ERROR
, LOCATION
, NULL
, "should never reach here\n");
194 case ADMIN_SHOW_SCHED
:
198 if (sched_dump(&p
, &len
) == -1)
204 memcpy(buf
->v
, p
, len
);
209 /* It's not really an error, don't force racoonctl to quit */
210 if ((buf
= evt_dump()) == NULL
)
217 switch (com
->ac_proto
) {
218 case ADMIN_PROTO_ISAKMP
:
219 switch (com
->ac_cmd
) {
230 case ADMIN_PROTO_IPSEC
:
232 case ADMIN_PROTO_ESP
:
233 switch (com
->ac_cmd
) {
237 p
= admin2pfkey_proto(com
->ac_proto
);
240 buf
= pfkey_dump_sadb(p
);
246 pfkey_flush_sadb(com
->ac_proto
);
251 case ADMIN_PROTO_INTERNAL
:
252 switch (com
->ac_cmd
) {
254 buf
= NULL
; /*XXX dumpph2(&error);*/
256 com
->ac_errno
= error
;
272 case ADMIN_DELETE_SA
: {
273 struct ph1handle
*iph1
;
274 struct sockaddr
*dst
;
275 struct sockaddr
*src
;
278 src
= (struct sockaddr
*)
279 &((struct admin_com_indexes
*)
280 ((caddr_t
)com
+ sizeof(*com
)))->src
;
281 dst
= (struct sockaddr
*)
282 &((struct admin_com_indexes
*)
283 ((caddr_t
)com
+ sizeof(*com
)))->dst
;
285 if ((loc
= strdup(saddrwop2str(src
))) == NULL
) {
286 plog(LLV_ERROR
, LOCATION
, NULL
,
287 "cannot allocate memory\n");
290 if ((rem
= strdup(saddrwop2str(dst
))) == NULL
) {
291 plog(LLV_ERROR
, LOCATION
, NULL
,
292 "cannot allocate memory\n");
296 if ((iph1
= getph1byaddrwop(src
, dst
)) == NULL
) {
297 plog(LLV_ERROR
, LOCATION
, NULL
,
298 "phase 1 for %s -> %s not found\n", loc
, rem
);
300 if (iph1
->status
== PHASE1ST_ESTABLISHED
)
301 isakmp_info_send_d1(iph1
);
311 case ADMIN_DELETE_ALL_SA_DST
: {
312 struct ph1handle
*iph1
;
313 struct sockaddr
*dst
;
316 dst
= (struct sockaddr
*)
317 &((struct admin_com_indexes
*)
318 ((caddr_t
)com
+ sizeof(*com
)))->dst
;
320 if ((rem
= strdup(saddrwop2str(dst
))) == NULL
) {
321 plog(LLV_ERROR
, LOCATION
, NULL
,
322 "cannot allocate memory\n");
326 plog(LLV_INFO
, LOCATION
, NULL
,
327 "Flushing all SAs for peer %s\n", rem
);
329 while ((iph1
= getph1bydstaddrwop(dst
)) != NULL
) {
330 if ((loc
= strdup(saddrwop2str(iph1
->local
))) == NULL
) {
331 plog(LLV_ERROR
, LOCATION
, NULL
,
332 "cannot allocate memory\n");
336 if (iph1
->status
== PHASE1ST_ESTABLISHED
)
337 isakmp_info_send_d1(iph1
);
348 case ADMIN_ESTABLISH_SA_PSK
: {
349 struct admin_com_psk
*acp
;
352 com
->ac_cmd
= ADMIN_ESTABLISH_SA
;
354 acp
= (struct admin_com_psk
*)
355 ((char *)com
+ sizeof(*com
) +
356 sizeof(struct admin_com_indexes
));
358 idtype
= acp
->id_type
;
360 if ((id
= vmalloc(acp
->id_len
)) == NULL
) {
361 plog(LLV_ERROR
, LOCATION
, NULL
,
362 "cannot allocate memory: %s\n",
366 data
= (char *)(acp
+ 1);
367 memcpy(id
->v
, data
, id
->l
);
369 if ((key
= vmalloc(acp
->key_len
)) == NULL
) {
370 plog(LLV_ERROR
, LOCATION
, NULL
,
371 "cannot allocate memory: %s\n",
376 data
= (char *)(data
+ acp
->id_len
);
377 memcpy(key
->v
, data
, key
->l
);
380 case ADMIN_ESTABLISH_SA
:
382 struct sockaddr
*dst
;
383 struct sockaddr
*src
;
384 src
= (struct sockaddr
*)
385 &((struct admin_com_indexes
*)
386 ((caddr_t
)com
+ sizeof(*com
)))->src
;
387 dst
= (struct sockaddr
*)
388 &((struct admin_com_indexes
*)
389 ((caddr_t
)com
+ sizeof(*com
)))->dst
;
391 switch (com
->ac_proto
) {
392 case ADMIN_PROTO_ISAKMP
:
394 struct remoteconf
*rmconf
;
395 struct sockaddr
*remote
;
396 struct sockaddr
*local
;
398 /* search appropreate configuration */
399 rmconf
= getrmconf(dst
);
400 if (rmconf
== NULL
) {
401 plog(LLV_ERROR
, LOCATION
, NULL
,
402 "no configuration found "
403 "for %s\n", saddrwop2str(dst
));
408 /* get remote IP address and port number. */
409 remote
= dupsaddr(dst
);
410 if (remote
== NULL
) {
414 switch (remote
->sa_family
) {
416 ((struct sockaddr_in
*)remote
)->sin_port
=
417 ((struct sockaddr_in
*)rmconf
->remote
)->sin_port
;
421 ((struct sockaddr_in6
*)remote
)->sin6_port
=
422 ((struct sockaddr_in6
*)rmconf
->remote
)->sin6_port
;
426 plog(LLV_ERROR
, LOCATION
, NULL
,
427 "invalid family: %d\n",
433 /* get local address */
434 local
= dupsaddr(src
);
439 switch (local
->sa_family
) {
441 ((struct sockaddr_in
*)local
)->sin_port
=
442 getmyaddrsport(local
);
446 ((struct sockaddr_in6
*)local
)->sin6_port
=
447 getmyaddrsport(local
);
451 plog(LLV_ERROR
, LOCATION
, NULL
,
452 "invalid family: %d\n",
458 /* Set the id and key */
460 if (rmconf
->idv
!= NULL
) {
464 if (rmconf
->key
!= NULL
) {
469 rmconf
->idvtype
= idtype
;
474 plog(LLV_INFO
, LOCATION
, NULL
,
475 "accept a request to establish IKE-SA: "
476 "%s\n", saddrwop2str(remote
));
478 /* begin ident mode */
479 if (isakmp_ph1begin_i(rmconf
, remote
, local
) < 0) {
486 case ADMIN_PROTO_ESP
:
496 plog(LLV_ERROR
, LOCATION
, NULL
,
497 "invalid command: %d\n", com
->ac_cmd
);
501 if (admin_reply(so2
, com
, buf
) < 0)
516 admin_reply(so
, combuf
, buf
)
518 struct admin_com
*combuf
;
525 tlen
= sizeof(*combuf
) + buf
->l
;
527 tlen
= sizeof(*combuf
);
529 retbuf
= racoon_calloc(1, tlen
);
530 if (retbuf
== NULL
) {
531 plog(LLV_ERROR
, LOCATION
, NULL
,
532 "failed to allocate admin buffer\n");
536 memcpy(retbuf
, combuf
, sizeof(*combuf
));
537 ((struct admin_com
*)retbuf
)->ac_len
= tlen
;
540 memcpy(retbuf
+ sizeof(*combuf
), buf
->v
, buf
->l
);
542 tlen
= send(so
, retbuf
, tlen
, 0);
545 plog(LLV_ERROR
, LOCATION
, NULL
,
546 "failed to send admin command: %s\n",
554 /* ADMIN_PROTO -> SADB_SATYPE */
556 admin2pfkey_proto(proto
)
560 case ADMIN_PROTO_IPSEC
:
561 return SADB_SATYPE_UNSPEC
;
563 return SADB_SATYPE_AH
;
564 case ADMIN_PROTO_ESP
:
565 return SADB_SATYPE_ESP
;
567 plog(LLV_ERROR
, LOCATION
, NULL
,
568 "unsupported proto for admin: %d\n", proto
);
577 if (adminsock_path
== NULL
) {
578 lcconf
->sock_admin
= -1;
582 memset(&sunaddr
, 0, sizeof(sunaddr
));
583 sunaddr
.sun_family
= AF_UNIX
;
584 snprintf(sunaddr
.sun_path
, sizeof(sunaddr
.sun_path
),
585 "%s", adminsock_path
);
587 lcconf
->sock_admin
= socket(AF_UNIX
, SOCK_STREAM
, 0);
588 if (lcconf
->sock_admin
== -1) {
589 plog(LLV_ERROR
, LOCATION
, NULL
,
590 "socket: %s\n", strerror(errno
));
594 unlink(sunaddr
.sun_path
);
595 if (bind(lcconf
->sock_admin
, (struct sockaddr
*)&sunaddr
,
596 sizeof(sunaddr
)) != 0) {
597 plog(LLV_ERROR
, LOCATION
, NULL
,
598 "bind(sockname:%s): %s\n",
599 sunaddr
.sun_path
, strerror(errno
));
600 (void)close(lcconf
->sock_admin
);
604 if (chown(sunaddr
.sun_path
, adminsock_owner
, adminsock_group
) != 0) {
605 plog(LLV_ERROR
, LOCATION
, NULL
,
606 "chown(%s, %d, %d): %s\n",
607 sunaddr
.sun_path
, adminsock_owner
,
608 adminsock_group
, strerror(errno
));
609 (void)close(lcconf
->sock_admin
);
613 if (chmod(sunaddr
.sun_path
, adminsock_mode
) != 0) {
614 plog(LLV_ERROR
, LOCATION
, NULL
,
615 "chmod(%s, 0%03o): %s\n",
616 sunaddr
.sun_path
, adminsock_mode
, strerror(errno
));
617 (void)close(lcconf
->sock_admin
);
621 if (listen(lcconf
->sock_admin
, 5) != 0) {
622 plog(LLV_ERROR
, LOCATION
, NULL
,
623 "listen(sockname:%s): %s\n",
624 sunaddr
.sun_path
, strerror(errno
));
625 (void)close(lcconf
->sock_admin
);
628 plog(LLV_DEBUG
, LOCATION
, NULL
,
629 "open %s as racoon management.\n", sunaddr
.sun_path
);
637 close(lcconf
->sock_admin
);