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