1 /* $OpenBSD: isakmpd.c,v 1.37 2001/10/26 11:37:16 ho Exp $ */ 2 /* $EOM: isakmpd.c,v 1.54 2000/10/05 09:28:22 niklas Exp $ */ 3 4 /* 5 * Copyright (c) 1998, 1999, 2000, 2001 Niklas Hallqvist. All rights reserved. 6 * Copyright (c) 1999, 2000 Angelos D. Keromytis. All rights reserved. 7 * Copyright (c) 1999, 2000, 2001 H�kan Olsson. 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. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by Ericsson Radio Systems. 20 * 4. The name of the author may not be used to endorse or promote products 21 * derived from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 /* 36 * This code was written under funding by Ericsson Radio Systems. 37 */ 38 39 #include <errno.h> 40 #include <sys/param.h> 41 #include <sys/types.h> 42 #include <sys/stat.h> 43 #include <signal.h> 44 #include <stdio.h> 45 #include <stdlib.h> 46 #include <string.h> 47 #include <unistd.h> 48 49 #include "sysdep.h" 50 51 #include "app.h" 52 #include "conf.h" 53 #include "connection.h" 54 #include "init.h" 55 #include "libcrypto.h" 56 #include "log.h" 57 #include "sa.h" 58 #include "timer.h" 59 #include "transport.h" 60 #include "udp.h" 61 #include "ui.h" 62 #include "util.h" 63 #include "cert.h" 64 65 #ifdef USE_POLICY 66 #include "policy.h" 67 #endif 68 69 static void usage (void); 70 71 /* 72 * Set if -d is given, currently just for running in the foreground and log 73 * to stderr instead of syslog. 74 */ 75 int debug = 0; 76 77 /* 78 * If we receive a SIGHUP signal, this flag gets set to show we need to 79 * reconfigure ASAP. 80 */ 81 static int sighupped = 0; 82 83 /* 84 * If we receive a USR1 signal, this flag gets set to show we need to dump 85 * a report over our internal state ASAP. The file to report to is settable 86 * via the -R parameter. 87 */ 88 static int sigusr1ed = 0; 89 static char *report_file = "/var/run/isakmpd.report"; 90 91 /* 92 * If we receive a USR2 signal, this flag gets set to show we need to 93 * rehash our SA soft expiration timers to a uniform distribution. 94 * XXX Perhaps this is a really bad idea? 95 */ 96 static int sigusr2ed = 0; 97 98 /* 99 * If we recieve a TERM signal, perform a "clean shutdown" of the daemon. 100 * This includes to send DELETE notifications for all our active SAs. 101 */ 102 static int sigtermed = 0; 103 void daemon_shutdown_now (int); 104 105 /* The default path of the PID file. */ 106 static char *pid_file = "/var/run/isakmpd.pid"; 107 108 #ifdef USE_DEBUG 109 /* The path of the IKE packet capture log file. */ 110 static char *pcap_file = 0; 111 #endif 112 113 static void 114 usage (void) 115 { 116 fprintf (stderr, 117 "usage: %s [-c config-file] [-d] [-D class=level] [-f fifo]\n" 118 " [-i pid-file] [-n] [-p listen-port] [-P local-port]\n" 119 " [-L] [-l packetlog-file] [-r seed] [-R report-file]\n", 120 sysdep_progname ()); 121 exit (1); 122 } 123 124 static void 125 parse_args (int argc, char *argv[]) 126 { 127 int ch; 128 char *ep; 129 #ifdef USE_DEBUG 130 int cls, level; 131 int do_packetlog = 0; 132 #endif 133 134 while ((ch = getopt (argc, argv, "c:dD:f:i:np:P:Ll:r:R:")) != -1) { 135 switch (ch) { 136 case 'c': 137 conf_path = optarg; 138 break; 139 140 case 'd': 141 debug++; 142 break; 143 144 #ifdef USE_DEBUG 145 case 'D': 146 if (sscanf (optarg, "%d=%d", &cls, &level) != 2) 147 { 148 if (sscanf (optarg, "A=%d", &level) == 1) 149 { 150 for (cls = 0; cls < LOG_ENDCLASS; cls++) 151 log_debug_cmd (cls, level); 152 } 153 else 154 log_print ("parse_args: -D argument unparseable: %s", optarg); 155 } 156 else 157 log_debug_cmd (cls, level); 158 break; 159 #endif /* USE_DEBUG */ 160 161 case 'f': 162 ui_fifo = optarg; 163 break; 164 165 case 'i': 166 pid_file = optarg; 167 break; 168 169 case 'n': 170 app_none++; 171 break; 172 173 case 'p': 174 udp_default_port = optarg; 175 break; 176 177 case 'P': 178 udp_bind_port = optarg; 179 break; 180 181 #ifdef USE_DEBUG 182 case 'l': 183 pcap_file = optarg; 184 /* Fallthrough intended. */ 185 186 case 'L': 187 do_packetlog++; 188 break; 189 #endif /* USE_DEBUG */ 190 191 case 'r': 192 seed = strtoul (optarg, &ep, 0); 193 srandom (seed); 194 if (*ep != '\0') 195 log_fatal ("parse_args: invalid numeric arg to -r (%s)", optarg); 196 regrand = 1; 197 break; 198 199 case 'R': 200 report_file = optarg; 201 break; 202 203 case '?': 204 default: 205 usage (); 206 } 207 } 208 argc -= optind; 209 argv += optind; 210 211 #ifdef USE_DEBUG 212 if (do_packetlog && !pcap_file) 213 pcap_file = PCAP_FILE_DEFAULT; 214 #endif 215 } 216 217 /* Reinitialize after a SIGHUP reception. */ 218 static void 219 reinit (void) 220 { 221 log_print ("SIGHUP received, reinitializing daemon."); 222 223 /* 224 * XXX Remove all(/some?) pending exchange timers? - they may not be 225 * possible to complete after we've re-read the config file. 226 * User-initiated SIGHUP's maybe "authorizes" a wait until 227 * next connection-check. 228 * XXX This means we discard exchange->last_msg, is this really ok? 229 */ 230 231 /* Reinitialize PRNG if we are in deterministic mode. */ 232 if (regrand) 233 srandom (seed); 234 235 /* Reread config file. */ 236 conf_reinit (); 237 238 /* Try again to link in libcrypto (good if we started without /usr). */ 239 libcrypto_init (); 240 241 /* Set timezone */ 242 tzset (); 243 244 #ifdef USE_POLICY 245 /* Reread the policies. */ 246 policy_init (); 247 #endif 248 249 /* Reinitialize certificates */ 250 cert_init (); 251 252 /* Reinitialize our connection list. */ 253 connection_reinit (); 254 255 /* 256 * Rescan interfaces. 257 */ 258 transport_reinit (); 259 260 /* 261 * XXX "These" (non-existant) reinitializations should not be done. 262 * cookie_reinit (); 263 * ui_reinit (); 264 * sa_reinit (); 265 */ 266 267 sighupped = 0; 268 } 269 270 static void 271 sighup (int sig) 272 { 273 sighupped = 1; 274 } 275 276 /* Report internal state on SIGUSR1. */ 277 static void 278 report (void) 279 { 280 FILE *report, *old; 281 mode_t old_umask; 282 283 old_umask = umask (S_IRWXG | S_IRWXO); 284 report = fopen (report_file, "w"); 285 umask (old_umask); 286 287 if (!report) 288 { 289 log_error ("fopen (\"%s\", \"w\") failed", report_file); 290 return; 291 } 292 293 /* Divert the log channel to the report file during the report. */ 294 old = log_current (); 295 log_to (report); 296 ui_report ("r"); 297 log_to (old); 298 fclose (report); 299 300 sigusr1ed = 0; 301 } 302 303 static void 304 sigusr1 (int sig) 305 { 306 sigusr1ed = 1; 307 } 308 309 /* Rehash soft expiration timers on SIGUSR2. */ 310 static void 311 rehash_timers (void) 312 { 313 #if 0 314 /* XXX - not yet */ 315 log_print ("SIGUSR2 received, rehasing soft expiration timers."); 316 317 timer_rehash_timers (); 318 #endif 319 320 sigusr2ed = 0; 321 } 322 323 static void 324 sigusr2 (int sig) 325 { 326 sigusr2ed = 1; 327 } 328 329 static int 330 phase2_sa_check (struct sa *sa, void *arg) 331 { 332 return sa->phase == 2; 333 } 334 335 static void 336 daemon_shutdown (void) 337 { 338 /* Perform a (protocol-wise) clean shutdown of the daemon. */ 339 struct sa *sa; 340 341 if (sigtermed == 1) 342 { 343 log_print ("isakmpd: shutting down..."); 344 345 /* Delete all active phase 2 SAs. */ 346 while ((sa = sa_find (phase2_sa_check, NULL))) 347 { 348 /* Each DELETE is another (outgoing) message. */ 349 sa_delete (sa, 1); 350 } 351 sigtermed++; 352 } 353 else if (transport_prio_sendqs_empty ()) 354 { 355 /* 356 * When the prioritized transport sendq:s are empty, i.e all 357 * the DELETE notifications have been sent, we can shutdown. 358 */ 359 360 #ifdef USE_DEBUG 361 log_packet_stop (); 362 #endif 363 log_print ("isakmpd: exit"); 364 exit (0); 365 } 366 } 367 368 /* called on SIGTERM */ 369 void 370 daemon_shutdown_now (int sig) 371 { 372 sigtermed = 1; 373 } 374 375 /* Write pid file. */ 376 static void 377 write_pid_file (void) 378 { 379 FILE *fp; 380 381 /* Ignore errors. */ 382 unlink (pid_file); 383 384 fp = fopen (pid_file, "w"); 385 if (fp != NULL) 386 { 387 /* XXX Error checking! */ 388 fprintf (fp, "%d\n", getpid ()); 389 fclose (fp); 390 } 391 else 392 log_fatal ("main: fopen (\"%s\", \"w\") failed", pid_file); 393 } 394 395 int 396 main (int argc, char *argv[]) 397 { 398 fd_set *rfds, *wfds; 399 int n, m; 400 size_t mask_size; 401 struct timeval tv, *timeout; 402 403 parse_args (argc, argv); 404 init (); 405 if (!debug) 406 { 407 if (daemon (0, 0)) 408 log_fatal ("main: daemon (0, 0) failed"); 409 /* Switch to syslog. */ 410 log_to (0); 411 } 412 413 write_pid_file (); 414 415 /* Reinitialize on HUP reception. */ 416 signal (SIGHUP, sighup); 417 418 /* Report state on USR1 reception. */ 419 signal (SIGUSR1, sigusr1); 420 421 /* Rehash soft expiration timers on USR2 reception. */ 422 signal (SIGUSR2, sigusr2); 423 424 /* Do a clean daemon shutdown on TERM reception. */ 425 signal (SIGTERM, daemon_shutdown_now); 426 427 #ifdef USE_DEBUG 428 /* If we wanted IKE packet capture to file, initialize it now. */ 429 if (pcap_file != 0) 430 log_packet_init (pcap_file); 431 #endif 432 433 /* Allocate the file descriptor sets just big enough. */ 434 n = getdtablesize (); 435 mask_size = howmany (n, NFDBITS) * sizeof (fd_mask); 436 rfds = (fd_set *)malloc (mask_size); 437 if (!rfds) 438 log_fatal ("main: malloc (%d) failed", mask_size); 439 wfds = (fd_set *)malloc (mask_size); 440 if (!wfds) 441 log_fatal ("main: malloc (%d) failed", mask_size); 442 443 while (1) 444 { 445 /* If someone has sent SIGHUP to us, reconfigure. */ 446 if (sighupped) 447 reinit (); 448 449 /* and if someone sent SIGUSR1, do a state report. */ 450 if (sigusr1ed) 451 report (); 452 453 /* and if someone sent SIGUSR2, do a timer rehash. */ 454 if (sigusr2ed) 455 rehash_timers (); 456 457 /* 458 * and if someone set 'sigtermed' (SIGTERM or via the UI), this 459 * indicated we should start a shutdown of the daemon. 460 * 461 * Note: Since _one_ message is sent per iteration of this enclosing 462 * while-loop, and we want to send a number of DELETE notifications, 463 * we must loop atleast this number of times. The daemon_shutdown() 464 * function starts by queueing the DELETEs, all other calls just 465 * increments the 'sigtermed' variable until it reaches a "safe" 466 * value, and the daemon exits. 467 */ 468 if (sigtermed) 469 daemon_shutdown (); 470 471 /* Setup the descriptors to look for incoming messages at. */ 472 memset (rfds, 0, mask_size); 473 n = transport_fd_set (rfds); 474 FD_SET (ui_socket, rfds); 475 if (ui_socket + 1 > n) 476 n = ui_socket + 1; 477 478 /* 479 * XXX Some day we might want to deal with an abstract application 480 * class instead, with many instantiations possible. 481 */ 482 if (!app_none && app_socket >= 0) 483 { 484 FD_SET (app_socket, rfds); 485 if (app_socket + 1 > n) 486 n = app_socket + 1; 487 } 488 489 /* Setup the descriptors that have pending messages to send. */ 490 memset (wfds, 0, mask_size); 491 m = transport_pending_wfd_set (wfds); 492 if (m > n) 493 n = m; 494 495 /* Find out when the next timed event is. */ 496 timeout = &tv; 497 timer_next_event (&timeout); 498 499 n = select (n, rfds, wfds, 0, timeout); 500 if (n == -1) 501 { 502 if (errno != EINTR) 503 { 504 log_error ("select"); 505 506 /* 507 * In order to give the unexpected error condition time to 508 * resolve without letting this process eat up all available CPU 509 * we sleep for a short while. 510 */ 511 sleep (1); 512 } 513 } 514 else if (n) 515 { 516 transport_handle_messages (rfds); 517 transport_send_messages (wfds); 518 if (FD_ISSET (ui_socket, rfds)) 519 ui_handler (); 520 if (!app_none && app_socket >= 0 && FD_ISSET (app_socket, rfds)) 521 app_handler (); 522 } 523 timer_handle_expirations (); 524 } 525 } 526