Beispiel #1
0
static int
ln_lock(
    char *	res, /* name of resource to lock */
    int		op)  /* true to lock; false to unlock */
{
    long mypid;
    char *lockfile = NULL;
    char *tlockfile = NULL;
    char *mres = NULL;
    int rc;
    char pid_str[NUM_STR_SIZE];

    mypid = (long)getpid();

    lockfile = g_strjoin(NULL, _lnlock_dir, "/am", res, ".lock", NULL);

    if (!op) {
        /* unlock the resource */
        assert(read_lock(lockfile) == mypid);

        (void)delete_lock(lockfile);
        amfree(lockfile);
        return 0;
    }

    /* lock the resource */

    g_snprintf(pid_str, sizeof(pid_str), "%ld", mypid);
    tlockfile = g_strjoin(NULL, _lnlock_dir, "/am", res, ".", pid_str, NULL);

    (void)create_lock(tlockfile, mypid);

    mres = stralloc2(res, ".");

    while(1) {
        rc = link_lock(lockfile, tlockfile);
        if (rc == -1) break;
        if (rc == 0) break;

        rc = steal_lock(lockfile, mypid, mres);
        if (rc == -1) break;
        if (rc == 0) continue;
        sleep(1);
    }

    (void) delete_lock(tlockfile);

    amfree(mres);
    amfree(tlockfile);
    amfree(lockfile);

    return rc;
}
Beispiel #2
0
/* leave pluto, with status.
 * Once child is launched, parent must not exit this way because
 * the lock would be released.
 *
 *  0 OK
 *  1 general discomfort
 * 10 lock file exists
 */
void exit_pluto(int status)
{
	reset_globals();    /* needed because we may be called in odd state */
	free_preshared_secrets();
	free_remembered_public_keys();
	close_ha_iface();
	delete_every_connection();
	whack_attribute_finalize(); /* free in-memory pools */
	fetch_finalize();           /* stop fetching thread */
	free_crl_fetch();           /* free chain of crl fetch requests */
	free_ocsp_fetch();          /* free chain of ocsp fetch requests */
	free_authcerts();           /* free chain of X.509 authority certificates */
	free_crls();                /* free chain of X.509 CRLs */
	free_ca_infos();            /* free chain of X.509 CA information records */
	free_ocsp();                /* free ocsp cache */
	free_ifaces();
	ac_finalize();              /* free X.509 attribute certificates */
	scx_finalize();             /* finalize and unload PKCS #11 module */
	stop_adns();
	free_md_pool();
	free_crypto();
	free_myid();                /* free myids */
	free_events();              /* free remaining events */
	free_vendorid();            /* free all vendor id records */
	free_builder();
	delete_lock();
	options->destroy(options);
	pluto_deinit();
	lib->plugins->unload(lib->plugins);
	libhydra_deinit();
	library_deinit();
	close_log();
	exit(status);
}
Beispiel #3
0
/** Unlock a lock (user interface).
 * \verbatim
 * This implements @unlock.
 * \endverbatim
 * \param player the enactor.
 * \param name name of object to unlock.
 * \param type type of lock to unlock.
 */
void
do_unlock(dbref player, const char *name, lock_type type)
{
  dbref thing;
  char *sp;
  lock_type real_type;

  /* check for '@unlock <object>/<atr>'  */
  sp = strchr(name, '/');
  if (sp) {
    notify(player, "Use @atrlock.");
    return;
  }
  if ((thing = match_controlled(player, name)) != NOTHING) {
    if ((real_type = check_lock_type(player, thing, type)) != NULL) {
      if (getlock(thing, real_type) == TRUE_BOOLEXP) {
        if (!AreQuiet(player, thing))
          notify_format(player, T("%s(%s) - %s (already) unlocked."),
                        Name(thing), unparse_dbref(thing), real_type);
      } else if (delete_lock(player, thing, real_type)) {
        if (!AreQuiet(player, thing))
          notify_format(player, T("%s(%s) - %s unlocked."), Name(thing),
                        unparse_dbref(thing), real_type);
        if (!IsPlayer(thing)) {
          char lmbuf[1024];
          ModTime(thing) = mudtime;
          snprintf(lmbuf, 1023, "%s lock[#%d]", real_type, player);
          lmbuf[strlen(lmbuf)+1] = '\0';
          set_lmod(thing, lmbuf);
        }
      } else
        notify(player, T("Permission denied."));
    }
  }
}
Beispiel #4
0
/* Create a lock file.
*/
static int
create_lock(
    char *fn,
    long pid)
{
    int fd;
    FILE *f;
    int mask;

    (void)delete_lock(fn);			/* that's MY file! */

    mask = umask(0027);
    fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0640);
    umask(mask);
    if (fd == -1) return -1;

    if((f = fdopen(fd, "w")) == NULL) {
        aclose(fd);
        return -1;
    }
    g_fprintf(f, "%ld\n", pid);
    if (fclose(f) == EOF)
        return -1;
    return 0;
}
Beispiel #5
0
/* leave pluto, with status.
 * Once child is launched, parent must not exit this way because
 * the lock would be released.
 *
 *  0 OK
 *  1 general discomfort
 * 10 lock file exists
 */
void
exit_pluto(int status)
{
    reset_globals();	/* needed because we may be called in odd state */
    free_preshared_secrets();
    free_remembered_public_keys();
    delete_every_connection();

    /* free memory allocated by initialization routines.  Please don't
       forget to do this. */

#ifdef HAVE_THREADS
    free_crl_fetch();          /* free chain of crl fetch requests */
#endif
#ifdef HAVE_OCSP
    free_ocsp_fetch();         /* free chain of ocsp fetch requests */
#endif
    free_authcerts();          /* free chain of X.509 authority certificates */
    free_crls();               /* free chain of X.509 CRLs */
    free_acerts();             /* free chain of X.509 attribute certificates */
    free_ocsp();               /* free ocsp cache */

    free_ifaces();          /* free interface list from memory */
    stop_adns();            /* Stop async DNS process (if running) */
    free_md_pool();         /* free the md pool */
    delete_lock();          /* delete any lock files */
#ifdef LEAK_DETECTIVE
    report_leaks();         /* report memory leaks now, after all free()s */
#endif /* LEAK_DETECTIVE */
    close_log();            /* close the logfiles */
    exit(status);           /* exit, with our error code */
}
Beispiel #6
0
/** Unlock a lock (user interface).
 * \verbatim
 * This implements @unlock.
 * \endverbatim
 * \param player the enactor.
 * \param name name of object to unlock.
 * \param type type of lock to unlock.
 */
void
do_unlock(dbref player, const char *name, lock_type type)
{
  dbref thing;
  lock_type real_type;

  /* check for '@unlock <object>/<atr>'  */
  if (strchr(name, '/')) {
    do_atrlock(player, name, "off");
    return;
  }
  if ((thing = match_controlled(player, name)) != NOTHING) {
    if ((real_type = check_lock_type(player, thing, type)) != NULL) {
      if (getlock(thing, real_type) == TRUE_BOOLEXP) {
        if (!AreQuiet(player, thing))
          notify_format(player, T("%s(%s) - %s (already) unlocked."),
                        AName(thing, AN_SYS, NULL), unparse_dbref(thing),
                        real_type);
      } else if (delete_lock(player, thing, real_type)) {
        if (!AreQuiet(player, thing))
          notify_format(player, T("%s(%s) - %s unlocked."),
                        AName(thing, AN_SYS, NULL), unparse_dbref(thing),
                        real_type);
        if (!IsPlayer(thing))
          ModTime(thing) = mudtime;
      } else
        notify(player, T("Permission denied."));
    }
  }
}
Beispiel #7
0
/* Delete all F_UNLCK locks */
static void
delete_unlck_locks (pl_inode_t *inode)
{
  posix_lock_t *l = inode->locks;
  while (l) {
    if (l->fl_type == F_UNLCK) {
      delete_lock (inode, l);
      destroy_lock (l);
    }

    l = l->next;
  }
}
Beispiel #8
0
/* Steal a lock if we can.
**   0=done; 1=still in use; -1 = error.
*/
static int
steal_lock(
    char *	fn,	/* name of lock file to steal */
    long	mypid,	/* my process id */
    char *	sres)	/* name of steal-resource to lock */
{
    long pid;
    int rc;

    /* prevent a race with another stealer */
    rc = ln_lock(sres, 1);
    if (rc != 0) goto error;

    pid = read_lock(fn);
    if (pid == -1) {
        if (errno == ENOENT) goto done;
        goto error;
    }

    if (pid == mypid) goto steal; /* i'm the locker! */

    /* are they still there ? */
    rc = kill((pid_t)pid, 0);
    if (rc != 0) {
        if (errno == ESRCH) goto steal; /* locker has gone */
        goto error;
    }

    rc = ln_lock(sres, 0);
    if (rc != 0) goto error;

    return 1;

steal:
    rc = delete_lock(fn);
    if (rc != 0) goto error;

done:
    rc = ln_lock(sres, 0);
    if (rc != 0) goto error;

    return 0;

error:
    rc = ln_lock(sres, 0);

    return -1;
}
Beispiel #9
0
/* leave pluto, with status.
 * Once child is launched, parent must not exit this way because
 * the lock would be released.
 *
 *  0 OK
 *  1 general discomfort
 * 10 lock file exists
 */
void
exit_pluto(int status)
{
    reset_globals();	/* needed because we may be called in odd state */
    free_preshared_secrets();
    free_remembered_public_keys();
    delete_every_connection();
    free_cacerts();	/* free chain of CA certificates */
    free_crls();	/* free chain of CRLS */
    free_mycert();	/* free default certificate (deprecated for X.509) */
    free_ifaces();
    stop_adns();
    free_md_pool();
    delete_lock();
#ifdef LEAK_DETECTIVE
    report_leaks();
#endif /* LEAK_DETECTIVE */
    close_log();
    exit(status);
}
Beispiel #10
0
/*
 * leave pluto, with status.
 * Once child is launched, parent must not exit this way because
 * the lock would be released.
 *
 *  0 OK
 *  1 general discomfort
 * 10 lock file exists
 */
void exit_pluto(int status)
{
	/* needed because we may be called in odd state */
	reset_globals();
 #ifdef USE_SYSTEMD_WATCHDOG
	pluto_sd(PLUTO_SD_STOPPING, status);
 #endif
	free_preshared_secrets();
	free_remembered_public_keys();
	delete_every_connection();

	/*
	 * free memory allocated by initialization routines.  Please don't
	 * forget to do this.
	 */

#if defined(LIBCURL) || defined(LDAP_VER)
	free_crl_fetch();	/* free chain of crl fetch requests */
#endif

	lsw_conf_free_oco();	/* free global_oco containing path names */

	free_myFQDN();	/* free myid FQDN */

	free_ifaces();	/* free interface list from memory */
	free_md_pool();	/* free the md pool */
	lsw_nss_shutdown();
	delete_lock();	/* delete any lock files */
	free_virtual_ip();	/* virtual_private= */
	free_kernelfd();	/* stop listening to kernel FD, remove event */
	free_pluto_main();	/* our static chars */

	/* report memory leaks now, after all free_* calls */
	if (leak_detective)
		report_leaks();
	close_log();	/* close the logfiles */
#ifdef USE_SYSTEMD_WATCHDOG
	pluto_sd(PLUTO_SD_EXIT,status);
#endif
	exit(status);	/* exit, with our error code */
}
Beispiel #11
0
/* leave pluto, with status.
 * Once child is launched, parent must not exit this way because
 * the lock would be released.
 *
 *  0 OK
 *  1 general discomfort
 * 10 lock file exists
 */
void
exit_pluto(int status)
{
    reset_globals();	/* needed because we may be called in odd state */
    free_preshared_secrets();
    free_remembered_public_keys();
    delete_every_connection();

    /* free memory allocated by initialization routines.  Please don't
       forget to do this. */

#ifdef TPM
    free_tpm();
#endif

#if defined(LIBCURL) || defined(LDAP_VER)
    free_crl_fetch();          /* free chain of crl fetch requests */
#endif
    free_authcerts();          /* free chain of X.509 authority certificates */
    free_crls();               /* free chain of X.509 CRLs */
    free_acerts();             /* free chain of X.509 attribute certificates */

    lsw_conf_free_oco();	/* free global_oco containing path names */

    free_myFQDN();	    /* free myid FQDN */

    free_ifaces();          /* free interface list from memory */
    stop_adns();            /* Stop async DNS process (if running) */
    free_md_pool();         /* free the md pool */
    NSS_Shutdown();
    delete_lock();          /* delete any lock files */
#ifdef LEAK_DETECTIVE
    report_leaks();         /* report memory leaks now, after all free()s */
#endif /* LEAK_DETECTIVE */
    close_log();            /* close the logfiles */
    exit(status);           /* exit, with our error code */
}
int main(int argc, char **argv)
{
	bool fork_desired = TRUE;
	bool log_to_stderr_desired = FALSE;
	bool nat_traversal = FALSE;
	bool nat_t_spf = TRUE;  /* support port floating */
	unsigned int keep_alive = 0;
	bool force_keepalive = FALSE;
	char *virtual_private = NULL;
	int lockfd;
#ifdef CAPABILITIES
	int keep[] = { CAP_NET_ADMIN, CAP_NET_BIND_SERVICE };
#endif /* CAPABILITIES */

	/* initialize library and optionsfrom */
	if (!library_init(NULL))
	{
		library_deinit();
		exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
	}
	if (!libhydra_init("pluto"))
	{
		libhydra_deinit();
		library_deinit();
		exit(SS_RC_INITIALIZATION_FAILED);
	}
	if (!pluto_init(argv[0]))
	{
		pluto_deinit();
		libhydra_deinit();
		library_deinit();
		exit(SS_RC_DAEMON_INTEGRITY);
	}
	options = options_create();

	/* handle arguments */
	for (;;)
	{
#       define DBG_OFFSET 256
		static const struct option long_opts[] = {
			/* name, has_arg, flag, val */
			{ "help", no_argument, NULL, 'h' },
			{ "version", no_argument, NULL, 'v' },
			{ "optionsfrom", required_argument, NULL, '+' },
			{ "nofork", no_argument, NULL, 'd' },
			{ "stderrlog", no_argument, NULL, 'e' },
			{ "nocrsend", no_argument, NULL, 'c' },
			{ "strictcrlpolicy", no_argument, NULL, 'r' },
			{ "crlcheckinterval", required_argument, NULL, 'x'},
			{ "cachecrls", no_argument, NULL, 'C' },
			{ "uniqueids", no_argument, NULL, 'u' },
      { "disableuniqreqids", no_argument, NULL, 'Z'},			
			{ "interface", required_argument, NULL, 'i' },
			{ "ikeport", required_argument, NULL, 'p' },
			{ "ctlbase", required_argument, NULL, 'b' },
			{ "secretsfile", required_argument, NULL, 's' },
			{ "foodgroupsdir", required_argument, NULL, 'f' },
			{ "perpeerlogbase", required_argument, NULL, 'P' },
			{ "perpeerlog", no_argument, NULL, 'l' },
			{ "policygroupsdir", required_argument, NULL, 'f' },
#ifdef USE_LWRES
			{ "lwdnsq", required_argument, NULL, 'a' },
#else /* !USE_LWRES */
			{ "adns", required_argument, NULL, 'a' },
#endif /* !USE_LWRES */
			{ "pkcs11module", required_argument, NULL, 'm' },
			{ "pkcs11keepstate", no_argument, NULL, 'k' },
			{ "pkcs11initargs", required_argument, NULL, 'z' },
			{ "pkcs11proxy", no_argument, NULL, 'y' },
			{ "nat_traversal", no_argument, NULL, '1' },
			{ "keep_alive", required_argument, NULL, '2' },
			{ "force_keepalive", no_argument, NULL, '3' },
			{ "disable_port_floating", no_argument, NULL, '4' },
			{ "debug-natt", no_argument, NULL, '5' },
			{ "virtual_private", required_argument, NULL, '6' },
#ifdef DEBUG
			{ "debug-none", no_argument, NULL, 'N' },
			{ "debug-all", no_argument, NULL, 'A' },
			{ "debug-raw", no_argument, NULL, DBG_RAW + DBG_OFFSET },
			{ "debug-crypt", no_argument, NULL, DBG_CRYPT + DBG_OFFSET },
			{ "debug-parsing", no_argument, NULL, DBG_PARSING + DBG_OFFSET },
			{ "debug-emitting", no_argument, NULL, DBG_EMITTING + DBG_OFFSET },
			{ "debug-control", no_argument, NULL, DBG_CONTROL + DBG_OFFSET },
			{ "debug-lifecycle", no_argument, NULL, DBG_LIFECYCLE + DBG_OFFSET },
			{ "debug-klips", no_argument, NULL, DBG_KERNEL + DBG_OFFSET },
			{ "debug-kernel", no_argument, NULL, DBG_KERNEL + DBG_OFFSET },
			{ "debug-dns", no_argument, NULL, DBG_DNS + DBG_OFFSET },
			{ "debug-oppo", no_argument, NULL, DBG_OPPO + DBG_OFFSET },
			{ "debug-controlmore", no_argument, NULL, DBG_CONTROLMORE + DBG_OFFSET },
			{ "debug-private", no_argument, NULL, DBG_PRIVATE + DBG_OFFSET },

			{ "impair-delay-adns-key-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_KEY_ANSWER + DBG_OFFSET },
			{ "impair-delay-adns-txt-answer", no_argument, NULL, IMPAIR_DELAY_ADNS_TXT_ANSWER + DBG_OFFSET },
			{ "impair-bust-mi2", no_argument, NULL, IMPAIR_BUST_MI2 + DBG_OFFSET },
			{ "impair-bust-mr2", no_argument, NULL, IMPAIR_BUST_MR2 + DBG_OFFSET },
#endif
			{ 0,0,0,0 }
			};
		/* Note: we don't like the way short options get parsed
		 * by getopt_long, so we simply pass an empty string as
		 * the list.  It could be "hvdenp:l:s:" "NARXPECK".
		 */
		int c = getopt_long(argc, argv, "", long_opts, NULL);

		/* Note: "breaking" from case terminates loop */
		switch (c)
		{
		case EOF:       /* end of flags */
			break;

		case 0: /* long option already handled */
			continue;

		case ':':       /* diagnostic already printed by getopt_long */
		case '?':       /* diagnostic already printed by getopt_long */
			usage("");
			break;   /* not actually reached */

		case 'h':       /* --help */
			usage(NULL);
			break;      /* not actually reached */

		case 'v':       /* --version */
			{
				const char **sp = ipsec_copyright_notice();

				printf("strongSwan "VERSION"%s\n", compile_time_interop_options);
				for (; *sp != NULL; sp++)
					puts(*sp);
			}
			exit_pluto(0);
			break;      /* not actually reached */

		case '+':       /* --optionsfrom <filename> */
			if (!options->from(options, optarg, &argc, &argv, optind))
			{
				exit_pluto(1);
			}
			continue;

		case 'd':       /* --nofork*/
			fork_desired = FALSE;
			continue;

		case 'e':       /* --stderrlog */
			log_to_stderr_desired = TRUE;
			continue;

		case 'c':       /* --nocrsend */
			no_cr_send = TRUE;
			continue;

		case 'r':       /* --strictcrlpolicy */
			strict_crl_policy = TRUE;
			continue;

		case 'x':       /* --crlcheckinterval <time>*/
			if (optarg == NULL || !isdigit(optarg[0]))
				usage("missing interval time");

			{
				char *endptr;
				long interval = strtol(optarg, &endptr, 0);

				if (*endptr != '\0' || endptr == optarg
				|| interval <= 0)
					usage("<interval-time> must be a positive number");
				crl_check_interval = interval;
			}
			continue;

		case 'C':       /* --cachecrls */
			cache_crls = TRUE;
			continue;

		case 'u':       /* --uniqueids */
			uniqueIDs = TRUE;
			continue;
	
	  case 'Z':       /* --disableuniqreqids */
	    disable_uniqreqids = TRUE;
	    continue;

		case 'i':       /* --interface <ifname> */
			if (!use_interface(optarg))
				usage("too many --interface specifications");
			continue;

		case 'p':       /* --port <portnumber> */
			if (optarg == NULL || !isdigit(optarg[0]))
				usage("missing port number");

			{
				char *endptr;
				long port = strtol(optarg, &endptr, 0);

				if (*endptr != '\0' || endptr == optarg
				|| port <= 0 || port > 0x10000)
					usage("<port-number> must be a number between 1 and 65535");
				pluto_port = port;
			}
			continue;

		case 'b':       /* --ctlbase <path> */
			if (snprintf(ctl_addr.sun_path, sizeof(ctl_addr.sun_path)
			, "%s%s", optarg, CTL_SUFFIX) == -1)
				usage("<path>" CTL_SUFFIX " too long for sun_path");
			if (snprintf(info_addr.sun_path, sizeof(info_addr.sun_path)
			, "%s%s", optarg, INFO_SUFFIX) == -1)
				usage("<path>" INFO_SUFFIX " too long for sun_path");
			if (snprintf(pluto_lock, sizeof(pluto_lock)
			, "%s%s", optarg, LOCK_SUFFIX) == -1)
				usage("<path>" LOCK_SUFFIX " must fit");
			continue;

		case 's':       /* --secretsfile <secrets-file> */
			shared_secrets_file = optarg;
			continue;

		case 'f':       /* --policygroupsdir <policygroups-dir> */
			policygroups_dir = optarg;
			continue;

		case 'a':       /* --adns <pathname> */
			pluto_adns_option = optarg;
			continue;

		case 'm':       /* --pkcs11module <pathname> */
			pkcs11_module_path = optarg;
			continue;

		case 'k':       /* --pkcs11keepstate */
			pkcs11_keep_state = TRUE;
			continue;

		case 'y':       /* --pkcs11proxy */
			pkcs11_proxy = TRUE;
			continue;

		case 'z':       /* --pkcs11initargs */
			pkcs11_init_args = optarg;
			continue;

#ifdef DEBUG
		case 'N':       /* --debug-none */
			base_debugging = DBG_NONE;
			continue;

		case 'A':       /* --debug-all */
			base_debugging = DBG_ALL;
			continue;
#endif

		case 'P':       /* --perpeerlogbase */
			base_perpeer_logdir = optarg;
			continue;

		case 'l':
			log_to_perpeer = TRUE;
			continue;

		case '1':       /* --nat_traversal */
			nat_traversal = TRUE;
			continue;
		case '2':       /* --keep_alive */
			keep_alive = atoi(optarg);
			continue;
		case '3':       /* --force_keepalive */
			force_keepalive = TRUE;
			continue;
		case '4':       /* --disable_port_floating */
			nat_t_spf = FALSE;
			continue;
		case '5':       /* --debug-nat_t */
			base_debugging |= DBG_NATT;
			continue;
		case '6':       /* --virtual_private */
			virtual_private = optarg;
			continue;

		default:
#ifdef DEBUG
			if (c >= DBG_OFFSET)
			{
				base_debugging |= c - DBG_OFFSET;
				continue;
			}
#       undef DBG_OFFSET
#endif
			bad_case(c);
		}
		break;
	}
	if (optind != argc)
		usage("unexpected argument");
	reset_debugging();
	lockfd = create_lock();

	/* select between logging methods */

	if (log_to_stderr_desired)
	{
		log_to_syslog = FALSE;
	}
	else
	{
		log_to_stderr = FALSE;
	}

	/* set the logging function of pfkey debugging */
#ifdef DEBUG
	pfkey_debug_func = DBG_log;
#else
	pfkey_debug_func = NULL;
#endif

	/* create control socket.
	 * We must create it before the parent process returns so that
	 * there will be no race condition in using it.  The easiest
	 * place to do this is before the daemon fork.
	 */
	{
		err_t ugh = init_ctl_socket();

		if (ugh != NULL)
		{
			fprintf(stderr, "pluto: %s", ugh);
			exit_pluto(1);
		}
	}

	/* If not suppressed, do daemon fork */

	if (fork_desired)
	{
		{
			pid_t pid = fork();

			if (pid < 0)
			{
				int e = errno;

				fprintf(stderr, "pluto: fork failed (%d %s)\n",
					errno, strerror(e));
				exit_pluto(1);
			}

			if (pid != 0)
			{
				/* parent: die, after filling PID into lock file.
				 * must not use exit_pluto: lock would be removed!
				 */
				exit(fill_lock(lockfd, pid)? 0 : 1);
			}
		}

		if (setsid() < 0)
		{
			int e = errno;

			fprintf(stderr, "setsid() failed in main(). Errno %d: %s\n",
				errno, strerror(e));
			exit_pluto(1);
		}
	}
	else
	{
		/* no daemon fork: we have to fill in lock file */
		(void) fill_lock(lockfd, getpid());
		fprintf(stdout, "Pluto initialized\n");
		fflush(stdout);
	}

	/* Redirect stdin, stdout and stderr to /dev/null
	 */
	{
		int fd;
		if ((fd = open("/dev/null", O_RDWR)) == -1)
			abort();
		if (dup2(fd, 0) != 0)
			abort();
		if (dup2(fd, 1) != 1)
			abort();
		if (!log_to_stderr && dup2(fd, 2) != 2)
			abort();
		close(fd);
	}

	init_constants();
	init_log("pluto");

	/* Note: some scripts may look for this exact message -- don't change
	 * ipsec barf was one, but it no longer does.
	 */
	plog("Starting IKEv1 pluto daemon (strongSwan "VERSION")%s",
		 compile_time_interop_options);

	if (lib->integrity)
	{
		plog("integrity tests enabled:");
		plog("lib    'libstrongswan': passed file and segment integrity tests");
		plog("lib    'libhydra': passed file and segment integrity tests");
		plog("daemon 'pluto': passed file integrity test");
	}

	/* load plugins, further infrastructure may need it */
	if (!lib->plugins->load(lib->plugins, NULL,
			lib->settings->get_str(lib->settings, "pluto.load", PLUGINS)))
	{
		exit(SS_RC_INITIALIZATION_FAILED);
	}
	print_plugins();

	init_builder();
	if (!init_secret() || !init_crypto())
	{
		plog("initialization failed - aborting pluto");
		exit_pluto(SS_RC_INITIALIZATION_FAILED);
	}
	init_nat_traversal(nat_traversal, keep_alive, force_keepalive, nat_t_spf);
	init_virtual_ip(virtual_private);
	scx_init(pkcs11_module_path, pkcs11_init_args);
	init_states();
	init_demux();
	init_kernel();
	init_adns();
	init_myid();
	fetch_initialize();
	ac_initialize();
	whack_attribute_initialize();

	/* drop unneeded capabilities and change UID/GID */
	prctl(PR_SET_KEEPCAPS, 1);

#ifdef IPSEC_GROUP
	{
		struct group group, *grp;
	char buf[1024];

		if (getgrnam_r(IPSEC_GROUP, &group, buf, sizeof(buf), &grp) != 0 ||
				grp == NULL || setgid(grp->gr_gid) != 0)
		{
			plog("unable to change daemon group");
			abort();
		}
	}
#endif
#ifdef IPSEC_USER
	{
		struct passwd passwd, *pwp;
	char buf[1024];

		if (getpwnam_r(IPSEC_USER, &passwd, buf, sizeof(buf), &pwp) != 0 ||
				pwp == NULL || setuid(pwp->pw_uid) != 0)
		{
			plog("unable to change daemon user");
			abort();
		}
		}
#endif

#ifdef CAPABILITIES_LIBCAP
	{
		cap_t caps;
		caps = cap_init();
		cap_set_flag(caps, CAP_EFFECTIVE, countof(keep), keep, CAP_SET);
		cap_set_flag(caps, CAP_INHERITABLE, countof(keep), keep, CAP_SET);
		cap_set_flag(caps, CAP_PERMITTED, countof(keep), keep, CAP_SET);
		if (cap_set_proc(caps) != 0)
		{
			plog("unable to drop daemon capabilities");
			abort();
		}
		cap_free(caps);
	}
#endif /* CAPABILITIES_LIBCAP */
#ifdef CAPABILITIES_NATIVE
	{
		struct __user_cap_data_struct caps = { .effective = 0 };
		struct __user_cap_header_struct header = {
			.version = _LINUX_CAPABILITY_VERSION,
		};
		int i;
		for (i = 0; i < countof(keep); i++)
		{
			caps.effective |= 1 << keep[i];
			caps.permitted |= 1 << keep[i];
			caps.inheritable |= 1 << keep[i];
		}
		if (capset(&header, &caps) != 0)
		{
			plog("unable to drop daemon capabilities");
			abort();
		}
	}
#endif /* CAPABILITIES_NATIVE */

	/* loading X.509 CA certificates */
	load_authcerts("ca", CA_CERT_PATH, X509_CA);
	/* loading X.509 AA certificates */
	load_authcerts("aa", AA_CERT_PATH, X509_AA);
	/* loading X.509 OCSP certificates */
	load_authcerts("ocsp", OCSP_CERT_PATH, X509_OCSP_SIGNER);
	/* loading X.509 CRLs */
	load_crls();
	/* loading attribute certificates (experimental) */
	ac_load_certs();

	lib->processor->set_threads(lib->processor,
			lib->settings->get_int(lib->settings, "pluto.threads",
								   DEFAULT_THREADS));

	daily_log_event();
	call_server();
	return -1;  /* Shouldn't ever reach this */
}

/* leave pluto, with status.
 * Once child is launched, parent must not exit this way because
 * the lock would be released.
 *
 *  0 OK
 *  1 general discomfort
 * 10 lock file exists
 */
void exit_pluto(int status)
{
	lib->processor->set_threads(lib->processor, 0);
	reset_globals();    /* needed because we may be called in odd state */
	free_preshared_secrets();
	free_remembered_public_keys();
	delete_every_connection();
	whack_attribute_finalize(); /* free in-memory pools */
	kernel_finalize();
	fetch_finalize();           /* stop fetching thread */
	free_crl_fetch();           /* free chain of crl fetch requests */
	free_ocsp_fetch();          /* free chain of ocsp fetch requests */
	free_authcerts();           /* free chain of X.509 authority certificates */
	free_crls();                /* free chain of X.509 CRLs */
	free_ca_infos();            /* free chain of X.509 CA information records */
	free_ocsp();                /* free ocsp cache */
	free_ifaces();
	ac_finalize();              /* free X.509 attribute certificates */
	scx_finalize();             /* finalize and unload PKCS #11 module */
	stop_adns();
	free_md_pool();
	free_crypto();
	free_myid();                /* free myids */
	free_events();              /* free remaining events */
	free_vendorid();            /* free all vendor id records */
	free_builder();
	delete_lock();
	options->destroy(options);
	pluto_deinit();
	lib->plugins->unload(lib->plugins);
	libhydra_deinit();
	library_deinit();
	close_log();
	exit(status);
}