properly initialize buffer when printing loaded plugins.
[strongswan.git] / src / pluto / plutomain.c
1 /* Pluto main program
2 * Copyright (C) 1997 Angelos D. Keromytis.
3 * Copyright (C) 1998-2001 D. Hugh Redelmeier.
4 * Copyright (C) 2009 Andreas Steffen
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <ctype.h>
21 #include <errno.h>
22 #include <string.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <sys/un.h>
26 #include <fcntl.h>
27 #include <getopt.h>
28 #include <resolv.h>
29 #include <arpa/nameser.h> /* missing from <resolv.h> on old systems */
30 #include <sys/queue.h>
31 #include <sys/prctl.h>
32 #include <pwd.h>
33 #include <grp.h>
34
35 #ifdef CAPABILITIES
36 #include <sys/capability.h>
37 #endif /* CAPABILITIES */
38
39 #include <freeswan.h>
40 #include <library.h>
41 #include <debug.h>
42 #include <utils/enumerator.h>
43
44 #include <pfkeyv2.h>
45 #include <pfkey.h>
46
47 #include "constants.h"
48 #include "defs.h"
49 #include "id.h"
50 #include "ca.h"
51 #include "certs.h"
52 #include "ac.h"
53 #include "connections.h"
54 #include "foodgroups.h"
55 #include "packet.h"
56 #include "demux.h" /* needs packet.h */
57 #include "server.h"
58 #include "kernel.h"
59 #include "log.h"
60 #include "keys.h"
61 #include "adns.h" /* needs <resolv.h> */
62 #include "dnskey.h" /* needs keys.h and adns.h */
63 #include "state.h"
64 #include "ipsec_doi.h" /* needs demux.h and state.h */
65 #include "ocsp.h"
66 #include "crl.h"
67 #include "fetch.h"
68 #include "xauth.h"
69 #include "crypto.h"
70 #include "nat_traversal.h"
71 #include "virtual.h"
72 #include "timer.h"
73 #include "vendor.h"
74
75 static void usage(const char *mess)
76 {
77 if (mess != NULL && *mess != '\0')
78 fprintf(stderr, "%s\n", mess);
79 fprintf(stderr
80 , "Usage: pluto"
81 " [--help]"
82 " [--version]"
83 " [--optionsfrom <filename>]"
84 " \\\n\t"
85 "[--nofork]"
86 " [--stderrlog]"
87 " [--noklips]"
88 " [--nocrsend]"
89 " \\\n\t"
90 "[--strictcrlpolicy]"
91 " [--crlcheckinterval <interval>]"
92 " [--cachecrls]"
93 " [--uniqueids]"
94 " \\\n\t"
95 "[--interface <ifname>]"
96 " [--ikeport <port-number>]"
97 " \\\n\t"
98 "[--ctlbase <path>]"
99 " \\\n\t"
100 "[--perpeerlogbase <path>] [--perpeerlog]"
101 " \\\n\t"
102 "[--secretsfile <secrets-file>]"
103 " [--policygroupsdir <policygroups-dir>]"
104 " \\\n\t"
105 "[--adns <pathname>]"
106 "[--pkcs11module <path>]"
107 "[--pkcs11keepstate]"
108 "[--pkcs11initargs <string>]"
109 #ifdef DEBUG
110 " \\\n\t"
111 "[--debug-none]"
112 " [--debug-all]"
113 " \\\n\t"
114 "[--debug-raw]"
115 " [--debug-crypt]"
116 " [--debug-parsing]"
117 " [--debug-emitting]"
118 " \\\n\t"
119 "[--debug-control]"
120 " [--debug-lifecycle]"
121 " [--debug-klips]"
122 " [--debug-dns]"
123 " \\\n\t"
124 "[--debug-oppo]"
125 " [--debug-controlmore]"
126 " [--debug-private]"
127 " [--debug-natt]"
128 #endif
129 " \\\n\t"
130 "[--nat_traversal] [--keep_alive <delay_sec>]"
131 " \\\n\t"
132 "[--force_keepalive] [--disable_port_floating]"
133 " \\\n\t"
134 "[--virtual_private <network_list>]"
135 "\n"
136 "strongSwan %s\n"
137 , ipsec_version_code());
138 exit_pluto(mess == NULL? 0 : 1);
139 }
140
141
142 /* lock file support
143 * - provides convenient way for scripts to find Pluto's pid
144 * - prevents multiple Plutos competing for the same port
145 * - same basename as unix domain control socket
146 * NOTE: will not take account of sharing LOCK_DIR with other systems.
147 */
148
149 static char pluto_lock[sizeof(ctl_addr.sun_path)] = DEFAULT_CTLBASE LOCK_SUFFIX;
150 static bool pluto_lock_created = FALSE;
151
152 /* create lockfile, or die in the attempt */
153 static int create_lock(void)
154 {
155 int fd = open(pluto_lock, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC
156 , S_IRUSR | S_IRGRP | S_IROTH);
157
158 if (fd < 0)
159 {
160 if (errno == EEXIST)
161 {
162 fprintf(stderr, "pluto: lock file \"%s\" already exists\n"
163 , pluto_lock);
164 exit_pluto(10);
165 }
166 else
167 {
168 fprintf(stderr
169 , "pluto: unable to create lock file \"%s\" (%d %s)\n"
170 , pluto_lock, errno, strerror(errno));
171 exit_pluto(1);
172 }
173 }
174 pluto_lock_created = TRUE;
175 return fd;
176 }
177
178 static bool fill_lock(int lockfd, pid_t pid)
179 {
180 char buf[30]; /* holds "<pid>\n" */
181 int len = snprintf(buf, sizeof(buf), "%u\n", (unsigned int) pid);
182 bool ok = len > 0 && write(lockfd, buf, len) == len;
183
184 close(lockfd);
185 return ok;
186 }
187
188 static void delete_lock(void)
189 {
190 if (pluto_lock_created)
191 {
192 delete_ctl_socket();
193 unlink(pluto_lock); /* is noting failure useful? */
194 }
195 }
196
197
198 /* by default pluto sends certificate requests to its peers */
199 bool no_cr_send = FALSE;
200
201 /* by default the CRL policy is lenient */
202 bool strict_crl_policy = FALSE;
203
204 /* by default CRLs are cached locally as files */
205 bool cache_crls = FALSE;
206
207 /* by default pluto does not check crls dynamically */
208 long crl_check_interval = 0;
209
210 /* path to the PKCS#11 module */
211 char *pkcs11_module_path = NULL;
212
213 /* by default pluto logs out after every smartcard use */
214 bool pkcs11_keep_state = FALSE;
215
216 /* by default pluto does not allow pkcs11 proxy access via whack */
217 bool pkcs11_proxy = FALSE;
218
219 /* argument string to pass to PKCS#11 module.
220 * Not used for compliant modules, just for NSS softoken
221 */
222 static const char *pkcs11_init_args = NULL;
223
224 /**
225 * Log loaded plugins
226 */
227 static void print_plugins()
228 {
229 char buf[BUF_LEN], *plugin;
230 int len = 0;
231 enumerator_t *enumerator;
232
233 buf[0] = '\0';
234 enumerator = lib->plugins->create_plugin_enumerator(lib->plugins);
235 while (len < BUF_LEN && enumerator->enumerate(enumerator, &plugin))
236 {
237 len += snprintf(&buf[len], BUF_LEN-len, "%s ", plugin);
238 }
239 enumerator->destroy(enumerator);
240 DBG1("loaded plugins: %s", buf);
241 }
242
243 int main(int argc, char **argv)
244 {
245 bool fork_desired = TRUE;
246 bool log_to_stderr_desired = FALSE;
247 bool nat_traversal = FALSE;
248 bool nat_t_spf = TRUE; /* support port floating */
249 unsigned int keep_alive = 0;
250 bool force_keepalive = FALSE;
251 char *virtual_private = NULL;
252 int lockfd;
253 #ifdef CAPABILITIES
254 cap_t caps;
255 int keep[] = { CAP_NET_ADMIN, CAP_NET_BIND_SERVICE };
256 #endif /* CAPABILITIES */
257
258 library_init(STRONGSWAN_CONF);
259
260 /* handle arguments */
261 for (;;)
262 {
263 # define DBG_OFFSET 256
264 static const struct option long_opts[] = {
265 /* name, has_arg, flag, val */
266 { "help", no_argument, NULL, 'h' },
267 { "version", no_argument, NULL, 'v' },
268 { "optionsfrom", required_argument, NULL, '+' },
269 { "nofork", no_argument, NULL, 'd' },
270 { "stderrlog", no_argument, NULL, 'e' },
271 { "noklips", no_argument, NULL, 'n' },
272 { "nocrsend", no_argument, NULL, 'c' },
273 { "strictcrlpolicy", no_argument, NULL, 'r' },
274 { "crlcheckinterval", required_argument, NULL, 'x'},
275 { "cachecrls", no_argument, NULL, 'C' },
276 { "uniqueids", no_argument, NULL, 'u' },
277 { "interface", required_argument, NULL, 'i' },
278 { "ikeport", required_argument, NULL, 'p' },
279 { "ctlbase", required_argument, NULL, 'b' },
280 { "secretsfile", required_argument, NULL, 's' },
281 { "foodgroupsdir", required_argument, NULL, 'f' },
282 { "perpeerlogbase", required_argument, NULL, 'P' },
283 { "perpeerlog", no_argument, NULL, 'l' },
284 { "policygroupsdir", required_argument, NULL, 'f' },
285 #ifdef USE_LWRES
286 { "lwdnsq", required_argument, NULL, 'a' },
287 #else /* !USE_LWRES */
288 { "adns", required_argument, NULL, 'a' },
289 #endif /* !USE_LWRES */
290 { "pkcs11module", required_argument, NULL, 'm' },
291 { "pkcs11keepstate", no_argument, NULL, 'k' },
292 { "pkcs11initargs", required_argument, NULL, 'z' },
293 { "pkcs11proxy", no_argument, NULL, 'y' },
294 { "nat_traversal", no_argument, NULL, '1' },
295 { "keep_alive", required_argument, NULL, '2' },
296 { "force_keepalive", no_argument, NULL, '3' },
297 { "disable_port_floating", no_argument, NULL, '4' },
298 { "debug-natt", no_argument, NULL, '5' },
299 { "virtual_private", required_argument, NULL, '6' },
300 #ifdef DEBUG
301 { "debug-none", no_argument, NULL, 'N' },
302 { "debug-all", no_argument, NULL, 'A' },
303 { "debug-raw", no_argument, NULL, DBG_RAW + DBG_OFFSET },
304 { "debug-crypt", no_argument, NULL, DBG_CRYPT + DBG_OFFSET },
305 { "debug-parsing", no_argument, NULL, DBG_PARSING + DBG_OFFSET },
306 { "debug-emitting", no_argument, NULL, DBG_EMITTING + DBG_OFFSET },
307 { "debug-control", no_argument, NULL, DBG_CONTROL + DBG_OFFSET },
308 { "debug-lifecycle", no_argument, NULL, DBG_LIFECYCLE + DBG_OFFSET },
309 { "debug-klips", no_argument, NULL, DBG_KLIPS + DBG_OFFSET },
310 { "debug-dns", no_argument, NULL, DBG_DNS + DBG_OFFSET },
311 { "debug-oppo", no_argument, NULL, DBG_OPPO + DBG_OFFSET },
312 { "debug-controlmore", no_argument, NULL, DBG_CONTROLMORE + DBG_OFFSET },
313 { "debug-private", no_argument, NULL, DBG_PRIVATE + DBG_OFFSET },
314
315 { "impair-delay-adns-key-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_KEY_ANSWER + DBG_OFFSET },
316 { "impair-delay-adns-txt-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_TXT_ANSWER + DBG_OFFSET },
317 { "impair-bust-mi2", no_argument, NULL, IMPAIR_BUST_MI2 + DBG_OFFSET },
318 { "impair-bust-mr2", no_argument, NULL, IMPAIR_BUST_MR2 + DBG_OFFSET },
319 #endif
320 { 0,0,0,0 }
321 };
322 /* Note: we don't like the way short options get parsed
323 * by getopt_long, so we simply pass an empty string as
324 * the list. It could be "hvdenp:l:s:" "NARXPECK".
325 */
326 int c = getopt_long(argc, argv, "", long_opts, NULL);
327
328 /* Note: "breaking" from case terminates loop */
329 switch (c)
330 {
331 case EOF: /* end of flags */
332 break;
333
334 case 0: /* long option already handled */
335 continue;
336
337 case ':': /* diagnostic already printed by getopt_long */
338 case '?': /* diagnostic already printed by getopt_long */
339 usage("");
340 break; /* not actually reached */
341
342 case 'h': /* --help */
343 usage(NULL);
344 break; /* not actually reached */
345
346 case 'v': /* --version */
347 {
348 const char **sp = ipsec_copyright_notice();
349
350 printf("%s%s\n", ipsec_version_string(),
351 compile_time_interop_options);
352 for (; *sp != NULL; sp++)
353 puts(*sp);
354 }
355 exit_pluto(0);
356 break; /* not actually reached */
357
358 case '+': /* --optionsfrom <filename> */
359 optionsfrom(optarg, &argc, &argv, optind, stderr);
360 /* does not return on error */
361 continue;
362
363 case 'd': /* --nofork*/
364 fork_desired = FALSE;
365 continue;
366
367 case 'e': /* --stderrlog */
368 log_to_stderr_desired = TRUE;
369 continue;
370
371 case 'n': /* --noklips */
372 no_klips = TRUE;
373 continue;
374
375 case 'c': /* --nocrsend */
376 no_cr_send = TRUE;
377 continue;
378
379 case 'r': /* --strictcrlpolicy */
380 strict_crl_policy = TRUE;
381 continue;
382
383 case 'x': /* --crlcheckinterval <time>*/
384 if (optarg == NULL || !isdigit(optarg[0]))
385 usage("missing interval time");
386
387 {
388 char *endptr;
389 long interval = strtol(optarg, &endptr, 0);
390
391 if (*endptr != '\0' || endptr == optarg
392 || interval <= 0)
393 usage("<interval-time> must be a positive number");
394 crl_check_interval = interval;
395 }
396 continue;
397
398 case 'C': /* --cachecrls */
399 cache_crls = TRUE;
400 continue;
401
402 case 'u': /* --uniqueids */
403 uniqueIDs = TRUE;
404 continue;
405
406 case 'i': /* --interface <ifname> */
407 if (!use_interface(optarg))
408 usage("too many --interface specifications");
409 continue;
410
411 case 'p': /* --port <portnumber> */
412 if (optarg == NULL || !isdigit(optarg[0]))
413 usage("missing port number");
414
415 {
416 char *endptr;
417 long port = strtol(optarg, &endptr, 0);
418
419 if (*endptr != '\0' || endptr == optarg
420 || port <= 0 || port > 0x10000)
421 usage("<port-number> must be a number between 1 and 65535");
422 pluto_port = port;
423 }
424 continue;
425
426 case 'b': /* --ctlbase <path> */
427 if (snprintf(ctl_addr.sun_path, sizeof(ctl_addr.sun_path)
428 , "%s%s", optarg, CTL_SUFFIX) == -1)
429 usage("<path>" CTL_SUFFIX " too long for sun_path");
430 if (snprintf(info_addr.sun_path, sizeof(info_addr.sun_path)
431 , "%s%s", optarg, INFO_SUFFIX) == -1)
432 usage("<path>" INFO_SUFFIX " too long for sun_path");
433 if (snprintf(pluto_lock, sizeof(pluto_lock)
434 , "%s%s", optarg, LOCK_SUFFIX) == -1)
435 usage("<path>" LOCK_SUFFIX " must fit");
436 continue;
437
438 case 's': /* --secretsfile <secrets-file> */
439 shared_secrets_file = optarg;
440 continue;
441
442 case 'f': /* --policygroupsdir <policygroups-dir> */
443 policygroups_dir = optarg;
444 continue;
445
446 case 'a': /* --adns <pathname> */
447 pluto_adns_option = optarg;
448 continue;
449
450 case 'm': /* --pkcs11module <pathname> */
451 pkcs11_module_path = optarg;
452 continue;
453
454 case 'k': /* --pkcs11keepstate */
455 pkcs11_keep_state = TRUE;
456 continue;
457
458 case 'y': /* --pkcs11proxy */
459 pkcs11_proxy = TRUE;
460 continue;
461
462 case 'z': /* --pkcs11initargs */
463 pkcs11_init_args = optarg;
464 continue;
465
466 #ifdef DEBUG
467 case 'N': /* --debug-none */
468 base_debugging = DBG_NONE;
469 continue;
470
471 case 'A': /* --debug-all */
472 base_debugging = DBG_ALL;
473 continue;
474 #endif
475
476 case 'P': /* --perpeerlogbase */
477 base_perpeer_logdir = optarg;
478 continue;
479
480 case 'l':
481 log_to_perpeer = TRUE;
482 continue;
483
484 case '1': /* --nat_traversal */
485 nat_traversal = TRUE;
486 continue;
487 case '2': /* --keep_alive */
488 keep_alive = atoi(optarg);
489 continue;
490 case '3': /* --force_keepalive */
491 force_keepalive = TRUE;
492 continue;
493 case '4': /* --disable_port_floating */
494 nat_t_spf = FALSE;
495 continue;
496 case '5': /* --debug-nat_t */
497 base_debugging |= DBG_NATT;
498 continue;
499 case '6': /* --virtual_private */
500 virtual_private = optarg;
501 continue;
502
503 default:
504 #ifdef DEBUG
505 if (c >= DBG_OFFSET)
506 {
507 base_debugging |= c - DBG_OFFSET;
508 continue;
509 }
510 # undef DBG_OFFSET
511 #endif
512 bad_case(c);
513 }
514 break;
515 }
516 if (optind != argc)
517 usage("unexpected argument");
518 reset_debugging();
519 lockfd = create_lock();
520
521 /* select between logging methods */
522
523 if (log_to_stderr_desired)
524 {
525 log_to_syslog = FALSE;
526 }
527 else
528 {
529 log_to_stderr = FALSE;
530 }
531
532 /* set the logging function of pfkey debugging */
533 #ifdef DEBUG
534 pfkey_debug_func = DBG_log;
535 #else
536 pfkey_debug_func = NULL;
537 #endif
538
539 /* create control socket.
540 * We must create it before the parent process returns so that
541 * there will be no race condition in using it. The easiest
542 * place to do this is before the daemon fork.
543 */
544 {
545 err_t ugh = init_ctl_socket();
546
547 if (ugh != NULL)
548 {
549 fprintf(stderr, "pluto: %s", ugh);
550 exit_pluto(1);
551 }
552 }
553
554 /* If not suppressed, do daemon fork */
555
556 if (fork_desired)
557 {
558 {
559 pid_t pid = fork();
560
561 if (pid < 0)
562 {
563 int e = errno;
564
565 fprintf(stderr, "pluto: fork failed (%d %s)\n",
566 errno, strerror(e));
567 exit_pluto(1);
568 }
569
570 if (pid != 0)
571 {
572 /* parent: die, after filling PID into lock file.
573 * must not use exit_pluto: lock would be removed!
574 */
575 exit(fill_lock(lockfd, pid)? 0 : 1);
576 }
577 }
578
579 if (setsid() < 0)
580 {
581 int e = errno;
582
583 fprintf(stderr, "setsid() failed in main(). Errno %d: %s\n",
584 errno, strerror(e));
585 exit_pluto(1);
586 }
587 }
588 else
589 {
590 /* no daemon fork: we have to fill in lock file */
591 (void) fill_lock(lockfd, getpid());
592 fprintf(stdout, "Pluto initialized\n");
593 fflush(stdout);
594 }
595
596 /* Close everything but ctl_fd and (if needed) stderr.
597 * There is some danger that a library that we don't know
598 * about is using some fd that we don't know about.
599 * I guess we'll soon find out.
600 */
601 {
602 int i;
603
604 for (i = getdtablesize() - 1; i >= 0; i--) /* Bad hack */
605 {
606 if ((!log_to_stderr || i != 2) && i != ctl_fd)
607 close(i);
608 }
609
610 /* make sure that stdin, stdout, stderr are reserved */
611 if (open("/dev/null", O_RDONLY) != 0)
612 abort();
613 if (dup2(0, 1) != 1)
614 abort();
615 if (!log_to_stderr && dup2(0, 2) != 2)
616 abort();
617 }
618
619 init_constants();
620 init_log("pluto");
621
622 /* Note: some scripts may look for this exact message -- don't change
623 * ipsec barf was one, but it no longer does.
624 */
625 plog("Starting Pluto (strongSwan Version %s%s)"
626 , ipsec_version_code()
627 , compile_time_interop_options);
628
629 /* load plugins, further infrastructure may need it */
630 lib->plugins->load(lib->plugins, IPSEC_PLUGINDIR,
631 lib->settings->get_str(lib->settings, "pluto.load", PLUGINS));
632 print_plugins();
633
634 init_nat_traversal(nat_traversal, keep_alive, force_keepalive, nat_t_spf);
635 init_virtual_ip(virtual_private);
636 scx_init(pkcs11_module_path, pkcs11_init_args);
637 xauth_init();
638 init_secret();
639 init_states();
640 init_crypto();
641 init_demux();
642 init_kernel();
643 init_adns();
644 init_id();
645 init_fetch();
646
647 /* drop unneeded capabilities and change UID/GID */
648 prctl(PR_SET_KEEPCAPS, 1);
649
650 #ifdef IPSEC_GROUP
651 {
652 struct group group, *grp;
653 char buf[1024];
654
655 if (getgrnam_r(IPSEC_GROUP, &group, buf, sizeof(buf), &grp) != 0 ||
656 grp == NULL || setgid(grp->gr_gid) != 0)
657 {
658 plog("unable to change daemon group");
659 abort();
660 }
661 }
662 #endif
663 #ifdef IPSEC_USER
664 {
665 struct passwd passwd, *pwp;
666 char buf[1024];
667
668 if (getpwnam_r(IPSEC_USER, &passwd, buf, sizeof(buf), &pwp) != 0 ||
669 pwp == NULL || setuid(pwp->pw_uid) != 0)
670 {
671 plog("unable to change daemon user");
672 abort();
673 }
674 }
675 #endif
676
677 #ifdef CAPABILITIES
678 caps = cap_init();
679 cap_set_flag(caps, CAP_EFFECTIVE, 2, keep, CAP_SET);
680 cap_set_flag(caps, CAP_INHERITABLE, 2, keep, CAP_SET);
681 cap_set_flag(caps, CAP_PERMITTED, 2, keep, CAP_SET);
682 if (cap_set_proc(caps) != 0)
683 {
684 plog("unable to drop daemon capabilities");
685 abort();
686 }
687 cap_free(caps);
688 #endif /* CAPABILITIES */
689
690 /* loading X.509 CA certificates */
691 load_authcerts("CA cert", CA_CERT_PATH, AUTH_CA);
692 /* loading X.509 AA certificates */
693 load_authcerts("AA cert", AA_CERT_PATH, AUTH_AA);
694 /* loading X.509 OCSP certificates */
695 load_authcerts("OCSP cert", OCSP_CERT_PATH, AUTH_OCSP);
696 /* loading X.509 CRLs */
697 load_crls();
698 /* loading attribute certificates (experimental) */
699 load_acerts();
700
701 daily_log_event();
702 call_server();
703 return -1; /* Shouldn't ever reach this */
704 }
705
706 /* leave pluto, with status.
707 * Once child is launched, parent must not exit this way because
708 * the lock would be released.
709 *
710 * 0 OK
711 * 1 general discomfort
712 * 10 lock file exists
713 */
714 void exit_pluto(int status)
715 {
716 reset_globals(); /* needed because we may be called in odd state */
717 free_preshared_secrets();
718 free_remembered_public_keys();
719 delete_every_connection();
720 free_crl_fetch(); /* free chain of crl fetch requests */
721 free_ocsp_fetch(); /* free chain of ocsp fetch requests */
722 free_authcerts(); /* free chain of X.509 authority certificates */
723 free_crls(); /* free chain of X.509 CRLs */
724 free_acerts(); /* free chain of X.509 attribute certificates */
725 free_ca_infos(); /* free chain of X.509 CA information records */
726 free_ocsp(); /* free ocsp cache */
727 free_ifaces();
728 scx_finalize(); /* finalize and unload PKCS #11 module */
729 xauth_finalize(); /* finalize and unload XAUTH module */
730 stop_adns();
731 free_md_pool();
732 free_crypto();
733 free_id(); /* free myids */
734 free_events(); /* free remaining events */
735 free_vendorid(); /* free all vendor id records */
736 delete_lock();
737 library_deinit();
738 close_log();
739 exit(status);
740 }
741
742 /*
743 * Local Variables:
744 * c-basic-offset:4
745 * c-style: pluto
746 * End:
747 */