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