]> git.saurik.com Git - apple/ipsec.git/blob - ipsec-tools/racoon/admin.c
ipsec-34.0.1.tar.gz
[apple/ipsec.git] / ipsec-tools / racoon / admin.c
1 /* $Id: admin.c,v 1.17.2.4 2005/07/12 11:49:44 manubsd Exp $ */
2
3 /*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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.
18 *
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
29 * SUCH DAMAGE.
30 */
31
32 #include "config.h"
33
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/socket.h>
37 #include <sys/signal.h>
38 #include <sys/stat.h>
39 #include <sys/un.h>
40
41 #ifdef __APPLE__
42 #include <System/net/pfkeyv2.h>
43 #else
44 #include <net/pfkeyv2.h>
45 #endif
46
47 #include <netinet/in.h>
48 #ifndef HAVE_NETINET6_IPSEC
49 #include <netinet/ipsec.h>
50 #else
51 #include <netinet6/ipsec.h>
52 #endif
53
54
55 #include <stdlib.h>
56 #include <stdio.h>
57 #include <string.h>
58 #include <errno.h>
59 #include <netdb.h>
60 #ifdef HAVE_UNISTD_H
61 #include <unistd.h>
62 #endif
63
64 #include "var.h"
65 #include "misc.h"
66 #include "vmbuf.h"
67 #include "plog.h"
68 #include "sockmisc.h"
69 #include "debug.h"
70
71 #include "schedule.h"
72 #include "localconf.h"
73 #include "remoteconf.h"
74 #include "grabmyaddr.h"
75 #include "isakmp_var.h"
76 #include "isakmp.h"
77 #include "oakley.h"
78 #include "handler.h"
79 #include "evt.h"
80 #include "pfkey.h"
81 #include "ipsec_doi.h"
82 #include "admin.h"
83 #include "admin_var.h"
84 #include "isakmp_inf.h"
85 #include "session.h"
86 #include "gcmalloc.h"
87
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;
93
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 *));
97
98 int
99 admin_handler()
100 {
101 int so2;
102 struct sockaddr_storage from;
103 socklen_t fromlen = sizeof(from);
104 struct admin_com com;
105 char *combuf = NULL;
106 pid_t pid = -1;
107 int len, error = -1;
108
109 so2 = accept(lcconf->sock_admin, (struct sockaddr *)&from, &fromlen);
110 if (so2 < 0) {
111 plog(LLV_ERROR, LOCATION, NULL,
112 "failed to accept admin command: %s\n",
113 strerror(errno));
114 return -1;
115 }
116
117 /* get buffer length */
118 while ((len = recv(so2, (char *)&com, sizeof(com), MSG_PEEK)) < 0) {
119 if (errno == EINTR)
120 continue;
121 plog(LLV_ERROR, LOCATION, NULL,
122 "failed to recv admin command: %s\n",
123 strerror(errno));
124 goto end;
125 }
126
127 /* sanity check */
128 if (len < sizeof(com)) {
129 plog(LLV_ERROR, LOCATION, NULL,
130 "invalid header length of admin command\n");
131 goto end;
132 }
133
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");
138 goto end;
139 }
140
141 /* get real data */
142 while ((len = recv(so2, combuf, com.ac_len, 0)) < 0) {
143 if (errno == EINTR)
144 continue;
145 plog(LLV_ERROR, LOCATION, NULL,
146 "failed to recv admin command: %s\n",
147 strerror(errno));
148 goto end;
149 }
150
151 if (com.ac_cmd == ADMIN_RELOAD_CONF) {
152 /* reload does not work at all! */
153 signal_handler(SIGHUP);
154 goto end;
155 }
156
157 error = admin_process(so2, combuf);
158
159 end:
160 (void)close(so2);
161 if (combuf)
162 racoon_free(combuf);
163
164 /* exit if child's process. */
165 if (pid == 0 && !f_foreground)
166 exit(error);
167
168 return error;
169 }
170
171 /*
172 * main child's process.
173 */
174 static int
175 admin_process(so2, combuf)
176 int so2;
177 char *combuf;
178 {
179 struct admin_com *com = (struct admin_com *)combuf;
180 vchar_t *buf = NULL;
181 vchar_t *id = NULL;
182 vchar_t *key = NULL;
183 int idtype = 0;
184 int error = 0;
185
186 com->ac_errno = 0;
187
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");
192 goto bad;
193
194 case ADMIN_SHOW_SCHED:
195 {
196 caddr_t p;
197 int len;
198 if (sched_dump(&p, &len) == -1)
199 com->ac_errno = -1;
200 buf = vmalloc(len);
201 if (buf == NULL)
202 com->ac_errno = -1;
203 else
204 memcpy(buf->v, p, len);
205 }
206 break;
207
208 case ADMIN_SHOW_EVT:
209 /* It's not really an error, don't force racoonctl to quit */
210 if ((buf = evt_dump()) == NULL)
211 com->ac_errno = 0;
212 break;
213
214 case ADMIN_SHOW_SA:
215 case ADMIN_FLUSH_SA:
216 {
217 switch (com->ac_proto) {
218 case ADMIN_PROTO_ISAKMP:
219 switch (com->ac_cmd) {
220 case ADMIN_SHOW_SA:
221 buf = dumpph1();
222 if (buf == NULL)
223 com->ac_errno = -1;
224 break;
225 case ADMIN_FLUSH_SA:
226 flushph1();
227 break;
228 }
229 break;
230 case ADMIN_PROTO_IPSEC:
231 case ADMIN_PROTO_AH:
232 case ADMIN_PROTO_ESP:
233 switch (com->ac_cmd) {
234 case ADMIN_SHOW_SA:
235 {
236 u_int p;
237 p = admin2pfkey_proto(com->ac_proto);
238 if (p == -1)
239 goto bad;
240 buf = pfkey_dump_sadb(p);
241 if (buf == NULL)
242 com->ac_errno = -1;
243 }
244 break;
245 case ADMIN_FLUSH_SA:
246 pfkey_flush_sadb(com->ac_proto);
247 break;
248 }
249 break;
250
251 case ADMIN_PROTO_INTERNAL:
252 switch (com->ac_cmd) {
253 case ADMIN_SHOW_SA:
254 buf = NULL; /*XXX dumpph2(&error);*/
255 if (buf == NULL)
256 com->ac_errno = error;
257 break;
258 case ADMIN_FLUSH_SA:
259 /*XXX flushph2();*/
260 com->ac_errno = 0;
261 break;
262 }
263 break;
264
265 default:
266 /* ignore */
267 com->ac_errno = -1;
268 }
269 }
270 break;
271
272 case ADMIN_DELETE_SA: {
273 struct ph1handle *iph1;
274 struct sockaddr *dst;
275 struct sockaddr *src;
276 char *loc, *rem;
277
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;
284
285 if ((loc = strdup(saddrwop2str(src))) == NULL) {
286 plog(LLV_ERROR, LOCATION, NULL,
287 "cannot allocate memory\n");
288 break;
289 }
290 if ((rem = strdup(saddrwop2str(dst))) == NULL) {
291 plog(LLV_ERROR, LOCATION, NULL,
292 "cannot allocate memory\n");
293 break;
294 }
295
296 if ((iph1 = getph1byaddrwop(src, dst)) == NULL) {
297 plog(LLV_ERROR, LOCATION, NULL,
298 "phase 1 for %s -> %s not found\n", loc, rem);
299 } else {
300 if (iph1->status == PHASE1ST_ESTABLISHED)
301 isakmp_info_send_d1(iph1);
302 purge_remote(iph1);
303 }
304
305 racoon_free(loc);
306 racoon_free(rem);
307
308 break;
309 }
310
311 case ADMIN_DELETE_ALL_SA_DST: {
312 struct ph1handle *iph1;
313 struct sockaddr *dst;
314 char *loc, *rem;
315
316 dst = (struct sockaddr *)
317 &((struct admin_com_indexes *)
318 ((caddr_t)com + sizeof(*com)))->dst;
319
320 if ((rem = strdup(saddrwop2str(dst))) == NULL) {
321 plog(LLV_ERROR, LOCATION, NULL,
322 "cannot allocate memory\n");
323 break;
324 }
325
326 plog(LLV_INFO, LOCATION, NULL,
327 "Flushing all SAs for peer %s\n", rem);
328
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");
333 break;
334 }
335
336 if (iph1->status == PHASE1ST_ESTABLISHED)
337 isakmp_info_send_d1(iph1);
338 purge_remote(iph1);
339
340 racoon_free(loc);
341 }
342
343 racoon_free(rem);
344
345 break;
346 }
347
348 case ADMIN_ESTABLISH_SA_PSK: {
349 struct admin_com_psk *acp;
350 char *data;
351
352 com->ac_cmd = ADMIN_ESTABLISH_SA;
353
354 acp = (struct admin_com_psk *)
355 ((char *)com + sizeof(*com) +
356 sizeof(struct admin_com_indexes));
357
358 idtype = acp->id_type;
359
360 if ((id = vmalloc(acp->id_len)) == NULL) {
361 plog(LLV_ERROR, LOCATION, NULL,
362 "cannot allocate memory: %s\n",
363 strerror(errno));
364 break;
365 }
366 data = (char *)(acp + 1);
367 memcpy(id->v, data, id->l);
368
369 if ((key = vmalloc(acp->key_len)) == NULL) {
370 plog(LLV_ERROR, LOCATION, NULL,
371 "cannot allocate memory: %s\n",
372 strerror(errno));
373 vfree(id);
374 break;
375 }
376 data = (char *)(data + acp->id_len);
377 memcpy(key->v, data, key->l);
378 }
379 /* FALLTHROUGH */
380 case ADMIN_ESTABLISH_SA:
381 {
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;
390
391 switch (com->ac_proto) {
392 case ADMIN_PROTO_ISAKMP:
393 {
394 struct remoteconf *rmconf;
395 struct sockaddr *remote;
396 struct sockaddr *local;
397
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));
404 com->ac_errno = -1;
405 break;
406 }
407
408 /* get remote IP address and port number. */
409 remote = dupsaddr(dst);
410 if (remote == NULL) {
411 com->ac_errno = -1;
412 break;
413 }
414 switch (remote->sa_family) {
415 case AF_INET:
416 ((struct sockaddr_in *)remote)->sin_port =
417 ((struct sockaddr_in *)rmconf->remote)->sin_port;
418 break;
419 #ifdef INET6
420 case AF_INET6:
421 ((struct sockaddr_in6 *)remote)->sin6_port =
422 ((struct sockaddr_in6 *)rmconf->remote)->sin6_port;
423 break;
424 #endif
425 default:
426 plog(LLV_ERROR, LOCATION, NULL,
427 "invalid family: %d\n",
428 remote->sa_family);
429 com->ac_errno = -1;
430 break;
431 }
432
433 /* get local address */
434 local = dupsaddr(src);
435 if (local == NULL) {
436 com->ac_errno = -1;
437 break;
438 }
439 switch (local->sa_family) {
440 case AF_INET:
441 ((struct sockaddr_in *)local)->sin_port =
442 getmyaddrsport(local);
443 break;
444 #ifdef INET6
445 case AF_INET6:
446 ((struct sockaddr_in6 *)local)->sin6_port =
447 getmyaddrsport(local);
448 break;
449 #endif
450 default:
451 plog(LLV_ERROR, LOCATION, NULL,
452 "invalid family: %d\n",
453 local->sa_family);
454 com->ac_errno = -1;
455 break;
456 }
457
458 /* Set the id and key */
459 if (id && key) {
460 if (rmconf->idv != NULL) {
461 vfree(rmconf->idv);
462 rmconf->idv = NULL;
463 }
464 if (rmconf->key != NULL) {
465 vfree(rmconf->key);
466 rmconf->key = NULL;
467 }
468
469 rmconf->idvtype = idtype;
470 rmconf->idv = id;
471 rmconf->key = key;
472 }
473
474 plog(LLV_INFO, LOCATION, NULL,
475 "accept a request to establish IKE-SA: "
476 "%s\n", saddrwop2str(remote));
477
478 /* begin ident mode */
479 if (isakmp_ph1begin_i(rmconf, remote, local) < 0) {
480 com->ac_errno = -1;
481 break;
482 }
483 }
484 break;
485 case ADMIN_PROTO_AH:
486 case ADMIN_PROTO_ESP:
487 break;
488 default:
489 /* ignore */
490 com->ac_errno = -1;
491 }
492 }
493 break;
494
495 default:
496 plog(LLV_ERROR, LOCATION, NULL,
497 "invalid command: %d\n", com->ac_cmd);
498 com->ac_errno = -1;
499 }
500
501 if (admin_reply(so2, com, buf) < 0)
502 goto bad;
503
504 if (buf != NULL)
505 vfree(buf);
506
507 return 0;
508
509 bad:
510 if (buf != NULL)
511 vfree(buf);
512 return -1;
513 }
514
515 static int
516 admin_reply(so, combuf, buf)
517 int so;
518 struct admin_com *combuf;
519 vchar_t *buf;
520 {
521 int tlen;
522 char *retbuf = NULL;
523
524 if (buf != NULL)
525 tlen = sizeof(*combuf) + buf->l;
526 else
527 tlen = sizeof(*combuf);
528
529 retbuf = racoon_calloc(1, tlen);
530 if (retbuf == NULL) {
531 plog(LLV_ERROR, LOCATION, NULL,
532 "failed to allocate admin buffer\n");
533 return -1;
534 }
535
536 memcpy(retbuf, combuf, sizeof(*combuf));
537 ((struct admin_com *)retbuf)->ac_len = tlen;
538
539 if (buf != NULL)
540 memcpy(retbuf + sizeof(*combuf), buf->v, buf->l);
541
542 tlen = send(so, retbuf, tlen, 0);
543 racoon_free(retbuf);
544 if (tlen < 0) {
545 plog(LLV_ERROR, LOCATION, NULL,
546 "failed to send admin command: %s\n",
547 strerror(errno));
548 return -1;
549 }
550
551 return 0;
552 }
553
554 /* ADMIN_PROTO -> SADB_SATYPE */
555 int
556 admin2pfkey_proto(proto)
557 u_int proto;
558 {
559 switch (proto) {
560 case ADMIN_PROTO_IPSEC:
561 return SADB_SATYPE_UNSPEC;
562 case ADMIN_PROTO_AH:
563 return SADB_SATYPE_AH;
564 case ADMIN_PROTO_ESP:
565 return SADB_SATYPE_ESP;
566 default:
567 plog(LLV_ERROR, LOCATION, NULL,
568 "unsupported proto for admin: %d\n", proto);
569 return -1;
570 }
571 /*NOTREACHED*/
572 }
573
574 int
575 admin_init()
576 {
577 if (adminsock_path == NULL) {
578 lcconf->sock_admin = -1;
579 return 0;
580 }
581
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);
586
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));
591 return -1;
592 }
593
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);
601 return -1;
602 }
603
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);
610 return -1;
611 }
612
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);
618 return -1;
619 }
620
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);
626 return -1;
627 }
628 plog(LLV_DEBUG, LOCATION, NULL,
629 "open %s as racoon management.\n", sunaddr.sun_path);
630
631 return 0;
632 }
633
634 int
635 admin_close()
636 {
637 close(lcconf->sock_admin);
638 return 0;
639 }
640 #endif