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