2 * Copyright (C) 1997 Angelos D. Keromytis.
3 * Copyright (C) 1998-2001 D. Hugh Redelmeier.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * RCSID $Id: plutomain.c,v 1.16 2005/09/25 21:30:52 as Exp $
24 #include <sys/types.h>
30 #include <arpa/nameser.h> /* missing from <resolv.h> on old systems */
31 #include <sys/queue.h>
38 #include "constants.h"
44 #include "connections.h"
45 #include "foodgroups.h"
47 #include "demux.h" /* needs packet.h */
52 #include "adns.h" /* needs <resolv.h> */
53 #include "dnskey.h" /* needs keys.h and adns.h */
56 #include "ipsec_doi.h" /* needs demux.h and state.h */
62 #include "crypto.h" /* requires sha1.h and md5.h */
63 #include "nat_traversal.h"
67 usage(const char *mess
)
69 if (mess
!= NULL
&& *mess
!= '\0')
70 fprintf(stderr
, "%s\n", mess
);
75 " [--optionsfrom <filename>]"
83 " [--crlcheckinterval]"
87 "[--interface <ifname>]"
88 " [--ikeport <port-number>]"
92 "[--perpeerlogbase <path>] [--perpeerlog]"
94 "[--secretsfile <secrets-file>]"
95 " [--policygroupsdir <policygroups-dir>]"
98 "[--pkcs11module <path>]"
108 " [--debug-emitting]"
111 " [--debug-lifecycle]"
116 " [--debug-controlmore]"
121 "[--nat_traversal] [--keep_alive <delay_sec>]"
123 "[--force_keepalive] [--disable_port_floating]"
125 "[--virtual_private <network_list>]"
128 , ipsec_version_code());
129 exit_pluto(mess
== NULL?
0 : 1);
134 * - provides convenient way for scripts to find Pluto's pid
135 * - prevents multiple Plutos competing for the same port
136 * - same basename as unix domain control socket
137 * NOTE: will not take account of sharing LOCK_DIR with other systems.
140 static char pluto_lock
[sizeof(ctl_addr
.sun_path
)] = DEFAULT_CTLBASE LOCK_SUFFIX
;
141 static bool pluto_lock_created
= FALSE
;
143 /* create lockfile, or die in the attempt */
147 int fd
= open(pluto_lock
, O_WRONLY
| O_CREAT
| O_EXCL
| O_TRUNC
148 , S_IRUSR
| S_IRGRP
| S_IROTH
);
154 fprintf(stderr
, "pluto: lock file \"%s\" already exists\n"
161 , "pluto: unable to create lock file \"%s\" (%d %s)\n"
162 , pluto_lock
, errno
, strerror(errno
));
166 pluto_lock_created
= TRUE
;
171 fill_lock(int lockfd
, pid_t pid
)
173 char buf
[30]; /* holds "<pid>\n" */
174 int len
= snprintf(buf
, sizeof(buf
), "%u\n", (unsigned int) pid
);
175 bool ok
= len
> 0 && write(lockfd
, buf
, len
) == len
;
184 if (pluto_lock_created
)
187 unlink(pluto_lock
); /* is noting failure useful? */
191 /* by default pluto sends certificate requests to its peers */
192 bool no_cr_send
= FALSE
;
194 /* by default the CRL policy is lenient */
195 bool strict_crl_policy
= FALSE
;
197 /* by default CRLs are cached locally as files */
198 bool cache_crls
= FALSE
;
200 /* by default pluto does not check crls dynamically */
201 long crl_check_interval
= 0;
203 /* path to the PKCS#11 module */
204 char *pkcs11_module_path
= NULL
;
206 /* by default pluto logs out after every smartcard use */
207 bool pkcs11_keep_state
= FALSE
;
209 /* by default pluto does not allow pkcs11 proxy access via whack */
210 bool pkcs11_proxy
= FALSE
;
213 main(int argc
, char **argv
)
215 bool fork_desired
= TRUE
;
216 bool log_to_stderr_desired
= FALSE
;
217 bool nat_traversal
= FALSE
;
218 bool nat_t_spf
= TRUE
; /* support port floating */
219 unsigned int keep_alive
= 0;
220 bool force_keepalive
= FALSE
;
221 char *virtual_private
= NULL
;
224 /* handle arguments */
227 # define DBG_OFFSET 256
228 static const struct option long_opts
[] = {
229 /* name, has_arg, flag, val */
230 { "help", no_argument
, NULL
, 'h' },
231 { "version", no_argument
, NULL
, 'v' },
232 { "optionsfrom", required_argument
, NULL
, '+' },
233 { "nofork", no_argument
, NULL
, 'd' },
234 { "stderrlog", no_argument
, NULL
, 'e' },
235 { "noklips", no_argument
, NULL
, 'n' },
236 { "nocrsend", no_argument
, NULL
, 'c' },
237 { "strictcrlpolicy", no_argument
, NULL
, 'r' },
238 { "crlcheckinterval", required_argument
, NULL
, 'x'},
239 { "cachecrls", no_argument
, NULL
, 'C' },
240 { "uniqueids", no_argument
, NULL
, 'u' },
241 { "interface", required_argument
, NULL
, 'i' },
242 { "ikeport", required_argument
, NULL
, 'p' },
243 { "ctlbase", required_argument
, NULL
, 'b' },
244 { "secretsfile", required_argument
, NULL
, 's' },
245 { "foodgroupsdir", required_argument
, NULL
, 'f' },
246 { "perpeerlogbase", required_argument
, NULL
, 'P' },
247 { "perpeerlog", no_argument
, NULL
, 'l' },
248 { "policygroupsdir", required_argument
, NULL
, 'f' },
250 { "lwdnsq", required_argument
, NULL
, 'a' },
251 #else /* !USE_LWRES */
252 { "adns", required_argument
, NULL
, 'a' },
253 #endif /* !USE_LWRES */
254 { "pkcs11module", required_argument
, NULL
, 'm' },
255 { "pkcs11keepstate", no_argument
, NULL
, 'k' },
256 { "pkcs11proxy", no_argument
, NULL
, 'y' },
257 { "nat_traversal", no_argument
, NULL
, '1' },
258 { "keep_alive", required_argument
, NULL
, '2' },
259 { "force_keepalive", no_argument
, NULL
, '3' },
260 { "disable_port_floating", no_argument
, NULL
, '4' },
261 { "debug-natt", no_argument
, NULL
, '5' },
262 { "virtual_private", required_argument
, NULL
, '6' },
264 { "debug-none", no_argument
, NULL
, 'N' },
265 { "debug-all", no_argument
, NULL
, 'A' },
266 { "debug-raw", no_argument
, NULL
, DBG_RAW
+ DBG_OFFSET
},
267 { "debug-crypt", no_argument
, NULL
, DBG_CRYPT
+ DBG_OFFSET
},
268 { "debug-parsing", no_argument
, NULL
, DBG_PARSING
+ DBG_OFFSET
},
269 { "debug-emitting", no_argument
, NULL
, DBG_EMITTING
+ DBG_OFFSET
},
270 { "debug-control", no_argument
, NULL
, DBG_CONTROL
+ DBG_OFFSET
},
271 { "debug-lifecycle", no_argument
, NULL
, DBG_LIFECYCLE
+ DBG_OFFSET
},
272 { "debug-klips", no_argument
, NULL
, DBG_KLIPS
+ DBG_OFFSET
},
273 { "debug-dns", no_argument
, NULL
, DBG_DNS
+ DBG_OFFSET
},
274 { "debug-oppo", no_argument
, NULL
, DBG_OPPO
+ DBG_OFFSET
},
275 { "debug-controlmore", no_argument
, NULL
, DBG_CONTROLMORE
+ DBG_OFFSET
},
276 { "debug-private", no_argument
, NULL
, DBG_PRIVATE
+ DBG_OFFSET
},
278 { "impair-delay-adns-key-answer", no_argument
, NULL
, IMPAIR_DELAY_ADNS_KEY_ANSWER
+ DBG_OFFSET
},
279 { "impair-delay-adns-txt-answer", no_argument
, NULL
, IMPAIR_DELAY_ADNS_TXT_ANSWER
+ DBG_OFFSET
},
280 { "impair-bust-mi2", no_argument
, NULL
, IMPAIR_BUST_MI2
+ DBG_OFFSET
},
281 { "impair-bust-mr2", no_argument
, NULL
, IMPAIR_BUST_MR2
+ DBG_OFFSET
},
285 /* Note: we don't like the way short options get parsed
286 * by getopt_long, so we simply pass an empty string as
287 * the list. It could be "hvdenp:l:s:" "NARXPECK".
289 int c
= getopt_long(argc
, argv
, "", long_opts
, NULL
);
291 /* Note: "breaking" from case terminates loop */
294 case EOF
: /* end of flags */
297 case 0: /* long option already handled */
300 case ':': /* diagnostic already printed by getopt_long */
301 case '?': /* diagnostic already printed by getopt_long */
303 break; /* not actually reached */
305 case 'h': /* --help */
307 break; /* not actually reached */
309 case 'v': /* --version */
311 const char **sp
= ipsec_copyright_notice();
313 printf("%s%s\n", ipsec_version_string(),
314 compile_time_interop_options
);
315 for (; *sp
!= NULL
; sp
++)
319 break; /* not actually reached */
321 case '+': /* --optionsfrom <filename> */
322 optionsfrom(optarg
, &argc
, &argv
, optind
, stderr
);
323 /* does not return on error */
326 case 'd': /* --nofork*/
327 fork_desired
= FALSE
;
330 case 'e': /* --stderrlog */
331 log_to_stderr_desired
= TRUE
;
334 case 'n': /* --noklips */
338 case 'c': /* --nocrsend */
342 case 'r': /* --strictcrlpolicy */
343 strict_crl_policy
= TRUE
;
346 case 'x': /* --crlcheckinterval <time>*/
347 if (optarg
== NULL
|| !isdigit(optarg
[0]))
348 usage("missing interval time");
352 long interval
= strtol(optarg
, &endptr
, 0);
354 if (*endptr
!= '\0' || endptr
== optarg
356 usage("<interval-time> must be a positive number");
357 crl_check_interval
= interval
;
361 case 'C': /* --cachecrls */
365 case 'u': /* --uniqueids */
369 case 'i': /* --interface <ifname> */
370 if (!use_interface(optarg
))
371 usage("too many --interface specifications");
374 case 'p': /* --port <portnumber> */
375 if (optarg
== NULL
|| !isdigit(optarg
[0]))
376 usage("missing port number");
380 long port
= strtol(optarg
, &endptr
, 0);
382 if (*endptr
!= '\0' || endptr
== optarg
383 || port
<= 0 || port
> 0x10000)
384 usage("<port-number> must be a number between 1 and 65535");
389 case 'b': /* --ctlbase <path> */
390 if (snprintf(ctl_addr
.sun_path
, sizeof(ctl_addr
.sun_path
)
391 , "%s%s", optarg
, CTL_SUFFIX
) == -1)
392 usage("<path>" CTL_SUFFIX
" too long for sun_path");
393 if (snprintf(info_addr
.sun_path
, sizeof(info_addr
.sun_path
)
394 , "%s%s", optarg
, INFO_SUFFIX
) == -1)
395 usage("<path>" INFO_SUFFIX
" too long for sun_path");
396 if (snprintf(pluto_lock
, sizeof(pluto_lock
)
397 , "%s%s", optarg
, LOCK_SUFFIX
) == -1)
398 usage("<path>" LOCK_SUFFIX
" must fit");
401 case 's': /* --secretsfile <secrets-file> */
402 shared_secrets_file
= optarg
;
405 case 'f': /* --policygroupsdir <policygroups-dir> */
406 policygroups_dir
= optarg
;
409 case 'a': /* --adns <pathname> */
410 pluto_adns_option
= optarg
;
413 case 'm': /* --pkcs11module <pathname> */
414 pkcs11_module_path
= optarg
;
417 case 'k': /* --pkcs11keepstate */
418 pkcs11_keep_state
= TRUE
;
421 case 'y': /* --pkcs11proxy */
426 case 'N': /* --debug-none */
427 base_debugging
= DBG_NONE
;
430 case 'A': /* --debug-all */
431 base_debugging
= DBG_ALL
;
435 case 'P': /* --perpeerlogbase */
436 base_perpeer_logdir
= optarg
;
440 log_to_perpeer
= TRUE
;
443 case '1': /* --nat_traversal */
444 nat_traversal
= TRUE
;
446 case '2': /* --keep_alive */
447 keep_alive
= atoi(optarg
);
449 case '3': /* --force_keepalive */
450 force_keepalive
= TRUE
;
452 case '4': /* --disable_port_floating */
455 case '5': /* --debug-nat_t */
456 base_debugging
|= DBG_NATT
;
458 case '6': /* --virtual_private */
459 virtual_private
= optarg
;
466 base_debugging
|= c
- DBG_OFFSET
;
476 usage("unexpected argument");
478 lockfd
= create_lock();
480 /* select between logging methods */
482 if (log_to_stderr_desired
)
483 log_to_syslog
= FALSE
;
485 log_to_stderr
= FALSE
;
487 /* set the logging function of pfkey debugging */
489 pfkey_debug_func
= DBG_log
;
491 pfkey_debug_func
= NULL
;
494 /* create control socket.
495 * We must create it before the parent process returns so that
496 * there will be no race condition in using it. The easiest
497 * place to do this is before the daemon fork.
500 err_t ugh
= init_ctl_socket();
504 fprintf(stderr
, "pluto: %s", ugh
);
510 /* create info socket. */
512 err_t ugh
= init_info_socket();
516 fprintf(stderr
, "pluto: %s", ugh
);
522 /* If not suppressed, do daemon fork */
533 fprintf(stderr
, "pluto: fork failed (%d %s)\n",
540 /* parent: die, after filling PID into lock file.
541 * must not use exit_pluto: lock would be removed!
543 exit(fill_lock(lockfd
, pid
)?
0 : 1);
551 fprintf(stderr
, "setsid() failed in main(). Errno %d: %s\n",
558 /* no daemon fork: we have to fill in lock file */
559 (void) fill_lock(lockfd
, getpid());
560 fprintf(stdout
, "Pluto initialized\n");
564 /* Close everything but ctl_fd and (if needed) stderr.
565 * There is some danger that a library that we don't know
566 * about is using some fd that we don't know about.
567 * I guess we'll soon find out.
572 for (i
= getdtablesize() - 1; i
>= 0; i
--) /* Bad hack */
573 if ((!log_to_stderr
|| i
!= 2)
580 /* make sure that stdin, stdout, stderr are reserved */
581 if (open("/dev/null", O_RDONLY
) != 0)
585 if (!log_to_stderr
&& dup2(0, 2) != 2)
592 /* Note: some scripts may look for this exact message -- don't change
593 * ipsec barf was one, but it no longer does.
595 plog("Starting Pluto (strongSwan Version %s%s)"
596 , ipsec_version_code()
597 , compile_time_interop_options
);
599 init_nat_traversal(nat_traversal
, keep_alive
, force_keepalive
, nat_t_spf
);
600 init_virtual_ip(virtual_private
);
601 scx_init(pkcs11_module_path
); /* load and initialize PKCS #11 module */
602 xauth_init(); /* load and initialize XAUTH module */
613 /* loading X.509 CA certificates */
614 load_authcerts("CA cert", CA_CERT_PATH
, AUTH_CA
);
615 /* loading X.509 AA certificates */
616 load_authcerts("AA cert", AA_CERT_PATH
, AUTH_AA
);
617 /* loading X.509 OCSP certificates */
618 load_authcerts("OCSP cert", OCSP_CERT_PATH
, AUTH_OCSP
);
619 /* loading X.509 CRLs */
621 /* loading attribute certificates (experimental) */
626 return -1; /* Shouldn't ever reach this */
629 /* leave pluto, with status.
630 * Once child is launched, parent must not exit this way because
631 * the lock would be released.
634 * 1 general discomfort
635 * 10 lock file exists
638 exit_pluto(int status
)
640 reset_globals(); /* needed because we may be called in odd state */
641 free_preshared_secrets();
642 free_remembered_public_keys();
643 delete_every_connection();
644 free_crl_fetch(); /* free chain of crl fetch requests */
645 free_ocsp_fetch(); /* free chain of ocsp fetch requests */
646 free_authcerts(); /* free chain of X.509 authority certificates */
647 free_crls(); /* free chain of X.509 CRLs */
648 free_acerts(); /* free chain of X.509 attribute certificates */
649 free_ca_infos(); /* free chain of X.509 CA information records */
650 free_ocsp(); /* free ocsp cache */
652 scx_finalize(); /* finalize and unload PKCS #11 module */
653 xauth_finalize(); /* finalize and unload XAUTH module */
657 #ifdef LEAK_DETECTIVE
659 #endif /* LEAK_DETECTIVE */