Esempio n. 1
0
/* Takes ownership of startup */
static gboolean
infinoted_main_run(InfinotedStartup* startup,
                   GError** error)
{
  InfinotedRun* run;
  InfinotedSignal* sig;

#ifdef LIBINFINITY_HAVE_LIBDAEMON
  mode_t prev_umask;
  pid_t pid;
  int saved_errno;
#endif

  /* infinoted_run_new() takes ownership of startup */
  run = infinoted_run_new(startup, error);
  if(run == NULL)
  {
    infinoted_startup_free(startup);
    return FALSE;
  }

#ifdef LIBINFINITY_HAVE_LIBDAEMON
  if(startup->options->daemonize)
  {
    prev_umask = umask(0777);

    if(daemon_retval_init() == -1)
    {
      infinoted_run_free(run);
      return FALSE; /* libdaemon already wrote an error message */
    }

    pid = daemon_fork();
    if(pid < 0)
    {
      /* Translators: fork as in "fork into the background" */
      infinoted_util_set_errno_error(error, errno, _("Failed to fork"));
      infinoted_run_free(run);
      daemon_retval_done();
      return FALSE;
    }
    else if(pid > 0)
    {
      infinoted_run_free(run);
      saved_errno = daemon_retval_wait(5);
      if(saved_errno == 0)
      {
        return TRUE;
      }
      if(saved_errno == -1)
      {
        infinoted_util_set_errno_error(error, errno,
          _("Failed to wait for daemonized child's return value"));
        return FALSE;
      }
      else
      {
        /* on -1, the child process would have subtracted one from
         * errno before passing it back to us. */
        if(saved_errno < 0) ++saved_errno;
        infinoted_util_set_errno_error(
          error, saved_errno, _("Failed to create PID file"));
        return FALSE;
      }
    }
    else
    {
      infinoted_util_daemon_set_global_pid_file_proc();
      if(daemon_pid_file_create() != 0)
      {
        infinoted_util_daemon_set_local_pid_file_proc();
        if(daemon_pid_file_create() != 0)
        {
          if(daemon_pid_file_create() != 0)
          {
            saved_errno = errno;
            infinoted_util_set_errno_error(
              error,
              saved_errno,
              _("Failed to create PID file")
            );
            if(saved_errno < 0) --saved_errno;
            daemon_retval_send(saved_errno);

            infinoted_run_free(run);
            return FALSE;
          }
        }
      }

      daemon_retval_send(0);
    }

    /* libdaemon sets the umask to either 0777 (< 0.14) or 0077 (>= 0.14).
     * We don't want either of that, to make sure the directory tree is
     * always readable by us and potentially by others (for example, a
     * webserver providing read access to the documents). Therefore, reset
     * the umask here to what it previously was, so the system administrator
     * can define the umask by setting it before launching infinoted.
     * See also http://gobby.0x539.de/trac/ticket/617.  */
    umask(prev_umask);
  }
#endif

  sig = infinoted_signal_register(run);

  /* Now start the server. It can later be stopped by signals. */
  infinoted_run_start(run);

  infinoted_signal_unregister(sig);

#ifdef LIBINFINITY_HAVE_LIBDAEMON
  /* startup might be invalid at this point in case a config reload happened,
   * so use run->startup instead (which is revalidated by config reload). */
  if(run->startup->options->daemonize)
    daemon_pid_file_remove();
#endif

  infinoted_run_free(run);
  return TRUE;
}
Esempio n. 2
0
static gboolean
infinoted_options_load(InfinotedOptions* options,
                       const gchar* const* config_files,
                       int* argc,
                       char*** argv,
                       GError** error)
{
  const gchar* const* file;

  gchar* security_policy;
  gint port_number;
  gboolean display_version;
#ifdef LIBINFINITY_HAVE_LIBDAEMON
  gboolean kill_daemon;
#endif
  gint autosave_interval;
  gint sync_interval;
  guint i;

  gboolean result;

  GOptionContext *context;
  gchar* desc;

  GOptionEntry entries[] = {
    { "key-file", 'k', 0,
      G_OPTION_ARG_FILENAME, NULL,
      N_("The server's private key"), N_("KEY-FILE") },
    { "certificate-file", 'c', 0,
      G_OPTION_ARG_FILENAME, NULL,
      N_("The server's certificate"), N_("CERTIFICATE-FILE") },
    { "certificate-chain", 0, 0,
      G_OPTION_ARG_FILENAME, NULL,
      N_("The certificates chain down to the root certificate"), NULL },
    { "create-key", 0, G_OPTION_FLAG_NO_CONFIG_FILE,
      G_OPTION_ARG_NONE, NULL,
      N_("Creates a new random private key"), NULL },
    { "create-certificate", 0, G_OPTION_FLAG_NO_CONFIG_FILE,
      G_OPTION_ARG_NONE, NULL,
      N_("Creates a new self-signed certificate using the given key"), NULL },
    { "port-number", 'p', 0,
      G_OPTION_ARG_INT, NULL,
      N_("The port number to listen on"), N_("PORT") },
    { "security-policy", 0, 0,
      G_OPTION_ARG_STRING, NULL,
      N_("How to decide whether to use TLS"), "no-tls|allow-tls|require-tls" },
    { "root-directory", 'r', 0,
      G_OPTION_ARG_FILENAME, NULL,
      N_("The directory to store documents into"), N_("DIRECTORY") },
    { "autosave-interval", 0, 0,
      G_OPTION_ARG_INT, NULL,
      N_("Interval within which to save documents, in seconds, or 0 to "
         "disable autosave"), N_("INTERVAL") },
    { "password", 'P', 0,
      G_OPTION_ARG_STRING, NULL,
      N_("Require given password on connections"), N_("PASSWORD") },
#ifdef LIBINFINITY_HAVE_PAM
    { "pam-service", 0, 0,
      G_OPTION_ARG_STRING, NULL,
      N_("Authenticate clients against given pam service on connection"),
      N_("SERVICE") },
    { "allow-user", 0, 0,
      G_OPTION_ARG_STRING_ARRAY, NULL,
      N_("User allowed to connect after pam authentication"),
      N_("USER") },
    { "allow-group", 0, 0,
      G_OPTION_ARG_STRING_ARRAY, NULL,
      N_("Group allowed to connect after pam authentication"),
      N_("GROUP") },
#endif /* LIBINFINITY_HAVE_PAM */
    { "sync-directory", 0, 0,
      G_OPTION_ARG_FILENAME, NULL,
      N_("A directory into which to periodically store a copy of the "
         "document tree"), N_("DIRECTORY") },
    { "sync-interval", 0, 0,
      G_OPTION_ARG_INT, NULL,
      N_("Interval within which to store documents to the specified "
         "sync-directory, or 0 to disable directory synchronization"),
         N_("INTERVAL") },
#ifdef LIBINFINITY_HAVE_LIBDAEMON
    { "daemonize", 'd', 0,
      G_OPTION_ARG_NONE, NULL,
      N_("Daemonize the server"), NULL },
    { "kill-daemon", 'D', 0,
      G_OPTION_ARG_NONE, NULL,
      N_("Kill a running daemon"), NULL },
#endif
    { "version", 'v', G_OPTION_FLAG_NO_CONFIG_FILE,
      G_OPTION_ARG_NONE, NULL,
      N_("Display version information and exit"), NULL },
    { NULL, 0, 0, G_OPTION_ARG_NONE,
      NULL,
      NULL, 0 }
  };

  /* C90 does not allow non-compile-time-constant initializers for structs */
  i = 0;
  entries[i++].arg_data = &options->key_file;
  entries[i++].arg_data = &options->certificate_file;
  entries[i++].arg_data = &options->certificate_chain_file;
  entries[i++].arg_data = &options->create_key;
  entries[i++].arg_data = &options->create_certificate;
  entries[i++].arg_data = &port_number;
  entries[i++].arg_data = &security_policy;
  entries[i++].arg_data = &options->root_directory;
  entries[i++].arg_data = &autosave_interval;
  entries[i++].arg_data = &options->password;
#ifdef LIBINFINITY_HAVE_PAM
  entries[i++].arg_data = &options->pam_service;
  entries[i++].arg_data = &options->pam_allowed_users;
  entries[i++].arg_data = &options->pam_allowed_groups;
#endif /* LIBINFINITY_HAVE_PAM */
  entries[i++].arg_data = &options->sync_directory;
  entries[i++].arg_data = &sync_interval;
#ifdef LIBINFINITY_HAVE_LIBDAEMON
  entries[i++].arg_data = &options->daemonize;
  entries[i++].arg_data = &kill_daemon;
#endif
  entries[i++].arg_data = &display_version;

  display_version = FALSE;
#ifdef LIBINFINITY_HAVE_LIBDAEMON
  kill_daemon = FALSE;
#endif
  security_policy = NULL;
  port_number = infinoted_options_port_to_integer(options->port);
  autosave_interval = options->autosave_interval;
  sync_interval = options->sync_interval;

  if(config_files)
  {
    for(file = config_files; *file != NULL; ++ file)
    {
      if(infinoted_options_load_file(entries, *file, error) == FALSE)
      {
        g_prefix_error(error, "%s: ", *file);
        g_free(security_policy);
        return FALSE;
      }
    }
  }

  if(argc != NULL && argv != NULL)
  {
    desc = g_strdup_printf("- %s", _("infinote dedicated server"));
    context = g_option_context_new(desc);
    g_free(desc);
    g_option_context_add_main_entries(context, entries, GETTEXT_PACKAGE);

    if(g_option_context_parse(context, argc, argv, error) == FALSE)
    {
      g_option_context_free(context);
      g_free(security_policy);
      return FALSE;
    }

    if(display_version)
    {
      printf("infinoted %s\n", PACKAGE_VERSION);
      exit(0);
    }

#ifdef LIBINFINITY_HAVE_LIBDAEMON
    if(kill_daemon)
    {
      g_free(security_policy);

      infinoted_util_daemon_set_global_pid_file_proc();
      if(infinoted_util_daemon_pid_file_kill(SIGTERM) != 0)
      {
        infinoted_util_daemon_set_local_pid_file_proc();
        if(infinoted_util_daemon_pid_file_kill(SIGTERM) != 0)
        {
          infinoted_util_set_errno_error(error, errno,
            _("Could not kill daemon"));
          return FALSE;
        }
      }

      exit(0);
    }
#endif

    g_option_context_free(context);
  }

  if(security_policy != NULL)
  {
    result = infinoted_options_policy_from_string(
      security_policy,
      &options->security_policy,
      error
    );

    g_free(security_policy);
    if(!result) return FALSE;
  }

  /* TODO: Do we leak security_policy at this point? */

  result = infinoted_options_port_from_integer(
    port_number,
    &options->port,
    error
  );
  if(!result) return FALSE;

  result = infinoted_options_interval_from_integer(
    autosave_interval,
    &options->autosave_interval,
    error
  );
  if(!result) return FALSE;

  result = infinoted_options_interval_from_integer(
    sync_interval,
    &options->sync_interval,
    error
  );
  if(!result) return FALSE;

  if(options->password != NULL && strcmp(options->password, "") == 0)
  {
    g_free(options->password);
    options->password = NULL;
  }

#ifdef LIBINFINITY_HAVE_PAM
  if(options->pam_service != NULL && strcmp(options->pam_service, "") == 0)
  {
    g_free(options->pam_service);
    options->pam_service = NULL;
  }

  /* treat it as undefining the option if only one entry, which is empty,
   * is given */
  if(options->pam_allowed_users != NULL
     && strcmp(options->pam_allowed_users[0], "") == 0
     && options->pam_allowed_users[1] == NULL) {
    g_free(options->pam_allowed_users[0]);
    g_free(options->pam_allowed_users);
  }

  if(options->pam_allowed_groups != NULL
     && strcmp(options->pam_allowed_groups[0], "") == 0
     && options->pam_allowed_groups[1] == NULL) {
    g_free(options->pam_allowed_groups[0]);
    g_free(options->pam_allowed_groups);
  }
#endif /* LIBINFINITY_HAVE_PAM */

  if(options->sync_directory != NULL &&
     strcmp(options->sync_directory, "") == 0)
  {
    g_free(options->sync_directory);
    options->sync_directory = NULL;
  }

  return infinoted_options_validate(options, error);
}