admin.c revision 1.1
1/* $Id: admin.c,v 1.1 2005/02/12 11:11:38 manu 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#include <net/pfkeyv2.h> 42 43#include <netinet/in.h> 44#ifndef HAVE_NETINET6_IPSEC 45#include <netinet/ipsec.h> 46#else 47#include <netinet6/ipsec.h> 48#endif 49 50 51#include <stdlib.h> 52#include <stdio.h> 53#include <string.h> 54#include <errno.h> 55#include <netdb.h> 56#ifdef HAVE_UNISTD_H 57#include <unistd.h> 58#endif 59 60#include "var.h" 61#include "misc.h" 62#include "vmbuf.h" 63#include "plog.h" 64#include "sockmisc.h" 65#include "debug.h" 66 67#include "schedule.h" 68#include "localconf.h" 69#include "remoteconf.h" 70#include "grabmyaddr.h" 71#include "isakmp_var.h" 72#include "isakmp.h" 73#include "oakley.h" 74#include "handler.h" 75#include "evt.h" 76#include "pfkey.h" 77#include "ipsec_doi.h" 78#include "admin.h" 79#include "admin_var.h" 80#include "isakmp_inf.h" 81#include "session.h" 82#include "gcmalloc.h" 83 84#ifdef ENABLE_ADMINPORT 85char *adminsock_path = ADMINSOCK_PATH; 86uid_t adminsock_owner = 0; 87gid_t adminsock_group = 0; 88mode_t adminsock_mode = 0600; 89 90static struct sockaddr_un sunaddr; 91static int admin_process __P((int, char *)); 92static int admin_reply __P((int, struct admin_com *, vchar_t *)); 93static void isakmp_flush_sa __P((struct ph1handle *, char *, char *)); 94 95int 96admin_handler() 97{ 98 int so2; 99 struct sockaddr_storage from; 100 int fromlen = sizeof(from); 101 struct admin_com com; 102 char *combuf = NULL; 103 pid_t pid = -1; 104 int len, error = -1; 105 106 so2 = accept(lcconf->sock_admin, (struct sockaddr *)&from, &fromlen); 107 if (so2 < 0) { 108 plog(LLV_ERROR, LOCATION, NULL, 109 "failed to accept admin command: %s\n", 110 strerror(errno)); 111 return -1; 112 } 113 114 /* get buffer length */ 115 while ((len = recv(so2, (char *)&com, sizeof(com), MSG_PEEK)) < 0) { 116 if (errno == EINTR) 117 continue; 118 plog(LLV_ERROR, LOCATION, NULL, 119 "failed to recv admin command: %s\n", 120 strerror(errno)); 121 goto end; 122 } 123 124 /* sanity check */ 125 if (len < sizeof(com)) { 126 plog(LLV_ERROR, LOCATION, NULL, 127 "invalid header length of admin command\n"); 128 goto end; 129 } 130 131 /* get buffer to receive */ 132 if ((combuf = racoon_malloc(com.ac_len)) == 0) { 133 plog(LLV_ERROR, LOCATION, NULL, 134 "failed to alloc buffer for admin command\n"); 135 goto end; 136 } 137 138 /* get real data */ 139 while ((len = recv(so2, combuf, com.ac_len, 0)) < 0) { 140 if (errno == EINTR) 141 continue; 142 plog(LLV_ERROR, LOCATION, NULL, 143 "failed to recv admin command: %s\n", 144 strerror(errno)); 145 goto end; 146 } 147 148 if (com.ac_cmd == ADMIN_RELOAD_CONF) { 149 /* reload does not work at all! */ 150 signal_handler(SIGHUP); 151 goto end; 152 } 153 154 error = admin_process(so2, combuf); 155 156 end: 157 (void)close(so2); 158 if (combuf) 159 racoon_free(combuf); 160 161 /* exit if child's process. */ 162 if (pid == 0 && !f_foreground) 163 exit(error); 164 165 return error; 166} 167 168/* 169 * main child's process. 170 */ 171static int 172admin_process(so2, combuf) 173 int so2; 174 char *combuf; 175{ 176 struct admin_com *com = (struct admin_com *)combuf; 177 vchar_t *buf = NULL; 178 vchar_t *id = NULL; 179 vchar_t *key = NULL; 180 int idtype = 0; 181 int error = 0; 182 183 com->ac_errno = 0; 184 185 switch (com->ac_cmd) { 186 case ADMIN_RELOAD_CONF: 187 /* don't entered because of proccessing it in other place. */ 188 plog(LLV_ERROR, LOCATION, NULL, "should never reach here\n"); 189 goto bad; 190 191 case ADMIN_SHOW_SCHED: 192 { 193 caddr_t p; 194 int len; 195 if (sched_dump(&p, &len) == -1) 196 com->ac_errno = -1; 197 buf = vmalloc(len); 198 if (buf == NULL) 199 com->ac_errno = -1; 200 else 201 memcpy(buf->v, p, len); 202 } 203 break; 204 205 case ADMIN_SHOW_EVT: 206 /* It's not really an error, don't force racoonctl to quit */ 207 if ((buf = evt_dump()) == NULL) 208 com->ac_errno = 0; 209 break; 210 211 case ADMIN_SHOW_SA: 212 case ADMIN_FLUSH_SA: 213 { 214 switch (com->ac_proto) { 215 case ADMIN_PROTO_ISAKMP: 216 switch (com->ac_cmd) { 217 case ADMIN_SHOW_SA: 218 buf = dumpph1(); 219 if (buf == NULL) 220 com->ac_errno = -1; 221 break; 222 case ADMIN_FLUSH_SA: 223 flushph1(); 224 break; 225 } 226 break; 227 case ADMIN_PROTO_IPSEC: 228 case ADMIN_PROTO_AH: 229 case ADMIN_PROTO_ESP: 230 switch (com->ac_cmd) { 231 case ADMIN_SHOW_SA: 232 { 233 u_int p; 234 p = admin2pfkey_proto(com->ac_proto); 235 if (p == -1) 236 goto bad; 237 buf = pfkey_dump_sadb(p); 238 if (buf == NULL) 239 com->ac_errno = -1; 240 } 241 break; 242 case ADMIN_FLUSH_SA: 243 pfkey_flush_sadb(com->ac_proto); 244 break; 245 } 246 break; 247 248 case ADMIN_PROTO_INTERNAL: 249 switch (com->ac_cmd) { 250 case ADMIN_SHOW_SA: 251 buf = NULL; /*XXX dumpph2(&error);*/ 252 if (buf == NULL) 253 com->ac_errno = error; 254 break; 255 case ADMIN_FLUSH_SA: 256 /*XXX flushph2();*/ 257 com->ac_errno = 0; 258 break; 259 } 260 break; 261 262 default: 263 /* ignore */ 264 com->ac_errno = -1; 265 } 266 } 267 break; 268 269 case ADMIN_DELETE_SA: { 270 struct ph1handle *iph1; 271 struct sockaddr *dst; 272 struct sockaddr *src; 273 char *loc, *rem; 274 275 src = (struct sockaddr *) 276 &((struct admin_com_indexes *) 277 ((caddr_t)com + sizeof(*com)))->src; 278 dst = (struct sockaddr *) 279 &((struct admin_com_indexes *) 280 ((caddr_t)com + sizeof(*com)))->dst; 281 282 if ((loc = strdup(saddrwop2str(src))) == NULL) { 283 plog(LLV_ERROR, LOCATION, NULL, 284 "cannot allocate memory\n"); 285 break; 286 } 287 if ((rem = strdup(saddrwop2str(dst))) == NULL) { 288 plog(LLV_ERROR, LOCATION, NULL, 289 "cannot allocate memory\n"); 290 break; 291 } 292 293 if ((iph1 = getph1byaddr(src, dst)) == NULL) { 294 plog(LLV_ERROR, LOCATION, NULL, 295 "phase 1 for %s -> %s not found\n", loc, rem); 296 } else { 297 isakmp_flush_sa(iph1, loc, rem); 298 } 299 300 racoon_free(loc); 301 racoon_free(rem); 302 303 break; 304 } 305 306 case ADMIN_DELETE_ALL_SA_DST: { 307 struct ph1handle *iph1; 308 struct sockaddr *dst; 309 char *loc, *rem; 310 311 dst = (struct sockaddr *) 312 &((struct admin_com_indexes *) 313 ((caddr_t)com + sizeof(*com)))->dst; 314 315 if ((rem = strdup(saddrwop2str(dst))) == NULL) { 316 plog(LLV_ERROR, LOCATION, NULL, 317 "cannot allocate memory\n"); 318 break; 319 } 320 321 plog(LLV_INFO, LOCATION, NULL, 322 "Flushing all SA for peer %s\n", rem); 323 324 while ((iph1 = getph1bydstaddr(dst)) != NULL) { 325 if ((loc = strdup(saddrwop2str(iph1->local))) == NULL) { 326 plog(LLV_ERROR, LOCATION, NULL, 327 "cannot allocate memory\n"); 328 break; 329 } 330 331 isakmp_flush_sa(iph1, loc, rem); 332 333 racoon_free(loc); 334 } 335 336 racoon_free(rem); 337 338 break; 339 } 340 341 case ADMIN_ESTABLISH_SA_PSK: { 342 struct admin_com_psk *acp; 343 char *data; 344 345 com->ac_cmd = ADMIN_ESTABLISH_SA; 346 347 acp = (struct admin_com_psk *) 348 ((char *)com + sizeof(*com) + 349 sizeof(struct admin_com_indexes)); 350 351 idtype = acp->id_type; 352 353 if ((id = vmalloc(acp->id_len)) == NULL) { 354 plog(LLV_ERROR, LOCATION, NULL, 355 "cannot allocate memory: %s\n", 356 strerror(errno)); 357 break; 358 } 359 data = (char *)(acp + 1); 360 memcpy(id->v, data, id->l); 361 362 if ((key = vmalloc(acp->key_len)) == NULL) { 363 plog(LLV_ERROR, LOCATION, NULL, 364 "cannot allocate memory: %s\n", 365 strerror(errno)); 366 vfree(id); 367 break; 368 } 369 data = (char *)(data + acp->id_len); 370 memcpy(key->v, data, key->l); 371 } 372 /* FALLTHROUGH */ 373 case ADMIN_ESTABLISH_SA: 374 { 375 struct sockaddr *dst; 376 struct sockaddr *src; 377 src = (struct sockaddr *) 378 &((struct admin_com_indexes *) 379 ((caddr_t)com + sizeof(*com)))->src; 380 dst = (struct sockaddr *) 381 &((struct admin_com_indexes *) 382 ((caddr_t)com + sizeof(*com)))->dst; 383 384 switch (com->ac_proto) { 385 case ADMIN_PROTO_ISAKMP: 386 { 387 struct remoteconf *rmconf; 388 struct sockaddr *remote; 389 struct sockaddr *local; 390 391 /* search appropreate configuration */ 392 rmconf = getrmconf(dst); 393 if (rmconf == NULL) { 394 plog(LLV_ERROR, LOCATION, NULL, 395 "no configuration found " 396 "for %s\n", saddrwop2str(dst)); 397 com->ac_errno = -1; 398 break; 399 } 400 401 /* get remote IP address and port number. */ 402 remote = dupsaddr(dst); 403 if (remote == NULL) { 404 com->ac_errno = -1; 405 break; 406 } 407 switch (remote->sa_family) { 408 case AF_INET: 409 ((struct sockaddr_in *)remote)->sin_port = 410 ((struct sockaddr_in *)rmconf->remote)->sin_port; 411 break; 412#ifdef INET6 413 case AF_INET6: 414 ((struct sockaddr_in6 *)remote)->sin6_port = 415 ((struct sockaddr_in6 *)rmconf->remote)->sin6_port; 416 break; 417#endif 418 default: 419 plog(LLV_ERROR, LOCATION, NULL, 420 "invalid family: %d\n", 421 remote->sa_family); 422 com->ac_errno = -1; 423 break; 424 } 425 426 /* get local address */ 427 local = dupsaddr(src); 428 if (local == NULL) { 429 com->ac_errno = -1; 430 break; 431 } 432 switch (local->sa_family) { 433 case AF_INET: 434 ((struct sockaddr_in *)local)->sin_port = 435 getmyaddrsport(local); 436 break; 437#ifdef INET6 438 case AF_INET6: 439 ((struct sockaddr_in6 *)local)->sin6_port = 440 getmyaddrsport(local); 441 break; 442#endif 443 default: 444 plog(LLV_ERROR, LOCATION, NULL, 445 "invalid family: %d\n", 446 local->sa_family); 447 com->ac_errno = -1; 448 break; 449 } 450 451 /* Set the id and key */ 452 if (id && key) { 453 if (rmconf->idv != NULL) { 454 vfree(rmconf->idv); 455 rmconf->idv = NULL; 456 } 457 if (rmconf->key != NULL) { 458 vfree(rmconf->key); 459 rmconf->key = NULL; 460 } 461 462 rmconf->idvtype = idtype; 463 rmconf->idv = id; 464 rmconf->key = key; 465 } 466 467 plog(LLV_INFO, LOCATION, NULL, 468 "accept a request to establish IKE-SA: " 469 "%s\n", saddrwop2str(remote)); 470 471 /* begin ident mode */ 472 if (isakmp_ph1begin_i(rmconf, remote, local) < 0) { 473 com->ac_errno = -1; 474 break; 475 } 476 } 477 break; 478 case ADMIN_PROTO_AH: 479 case ADMIN_PROTO_ESP: 480 break; 481 default: 482 /* ignore */ 483 com->ac_errno = -1; 484 } 485 } 486 break; 487 488 default: 489 plog(LLV_ERROR, LOCATION, NULL, 490 "invalid command: %d\n", com->ac_cmd); 491 com->ac_errno = -1; 492 } 493 494 if (admin_reply(so2, com, buf) < 0) 495 goto bad; 496 497 if (buf != NULL) 498 vfree(buf); 499 500 return 0; 501 502 bad: 503 if (buf != NULL) 504 vfree(buf); 505 return -1; 506} 507 508static int 509admin_reply(so, combuf, buf) 510 int so; 511 struct admin_com *combuf; 512 vchar_t *buf; 513{ 514 int tlen; 515 char *retbuf = NULL; 516 517 if (buf != NULL) 518 tlen = sizeof(*combuf) + buf->l; 519 else 520 tlen = sizeof(*combuf); 521 522 retbuf = racoon_calloc(1, tlen); 523 if (retbuf == NULL) { 524 plog(LLV_ERROR, LOCATION, NULL, 525 "failed to allocate admin buffer\n"); 526 return -1; 527 } 528 529 memcpy(retbuf, combuf, sizeof(*combuf)); 530 ((struct admin_com *)retbuf)->ac_len = tlen; 531 532 if (buf != NULL) 533 memcpy(retbuf + sizeof(*combuf), buf->v, buf->l); 534 535 tlen = send(so, retbuf, tlen, 0); 536 racoon_free(retbuf); 537 if (tlen < 0) { 538 plog(LLV_ERROR, LOCATION, NULL, 539 "failed to send admin command: %s\n", 540 strerror(errno)); 541 return -1; 542 } 543 544 return 0; 545} 546 547/* ADMIN_PROTO -> SADB_SATYPE */ 548int 549admin2pfkey_proto(proto) 550 u_int proto; 551{ 552 switch (proto) { 553 case ADMIN_PROTO_IPSEC: 554 return SADB_SATYPE_UNSPEC; 555 case ADMIN_PROTO_AH: 556 return SADB_SATYPE_AH; 557 case ADMIN_PROTO_ESP: 558 return SADB_SATYPE_ESP; 559 default: 560 plog(LLV_ERROR, LOCATION, NULL, 561 "unsupported proto for admin: %d\n", proto); 562 return -1; 563 } 564 /*NOTREACHED*/ 565} 566 567int 568admin_init() 569{ 570 if (adminsock_path == NULL) 571 return 0; 572 573 memset(&sunaddr, 0, sizeof(sunaddr)); 574 sunaddr.sun_family = AF_UNIX; 575 snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path), 576 "%s", adminsock_path); 577 578 lcconf->sock_admin = socket(AF_UNIX, SOCK_STREAM, 0); 579 if (lcconf->sock_admin == -1) { 580 plog(LLV_ERROR, LOCATION, NULL, 581 "socket: %s\n", strerror(errno)); 582 return -1; 583 } 584 585 unlink(sunaddr.sun_path); 586 if (bind(lcconf->sock_admin, (struct sockaddr *)&sunaddr, 587 sizeof(sunaddr)) != 0) { 588 plog(LLV_ERROR, LOCATION, NULL, 589 "bind(sockname:%s): %s\n", 590 sunaddr.sun_path, strerror(errno)); 591 (void)close(lcconf->sock_admin); 592 return -1; 593 } 594 595 if (chown(sunaddr.sun_path, adminsock_owner, adminsock_group) != 0) { 596 plog(LLV_ERROR, LOCATION, NULL, 597 "chown(%s, %d, %d): %s\n", 598 sunaddr.sun_path, adminsock_owner, 599 adminsock_group, strerror(errno)); 600 (void)close(lcconf->sock_admin); 601 return -1; 602 } 603 604 if (chmod(sunaddr.sun_path, adminsock_mode) != 0) { 605 plog(LLV_ERROR, LOCATION, NULL, 606 "chmod(%s, 0%03o): %s\n", 607 sunaddr.sun_path, adminsock_mode, strerror(errno)); 608 (void)close(lcconf->sock_admin); 609 return -1; 610 } 611 612 if (listen(lcconf->sock_admin, 5) != 0) { 613 plog(LLV_ERROR, LOCATION, NULL, 614 "listen(sockname:%s): %s\n", 615 sunaddr.sun_path, strerror(errno)); 616 (void)close(lcconf->sock_admin); 617 return -1; 618 } 619 plog(LLV_DEBUG, LOCATION, NULL, 620 "open %s as racoon management.\n", sunaddr.sun_path); 621 622 return 0; 623} 624 625int 626admin_close() 627{ 628 close(lcconf->sock_admin); 629 return 0; 630} 631#endif 632 633static void 634isakmp_flush_sa(iph1, loc, rem) 635 struct ph1handle *iph1; 636 char *loc; 637 char *rem; 638{ 639 plog(LLV_INFO, LOCATION, NULL, 640 "Flushing SA for %s -> %s\n", loc, rem); 641 642 if (iph1->status == PHASE1ST_ESTABLISHED) 643 isakmp_info_send_d1(iph1); 644 645 remph1(iph1); 646 delph1(iph1); 647 648 return; 649} 650