Пример #1
0
/*
 * @brief Reloads the scanner if a reload was requested.
 */
static void
check_and_reload ()
{
  if (reload != 0)
    {
      proctitle_set ("openvassd: Reloading");
      reload_openvassd ();
      proctitle_set ("openvassd: Waiting for incoming connections");
    }
}
Пример #2
0
/*
 * @brief Starts a process to handle client requests while the scanner is
 * loading.
 *
 * @return process id of loading handler.
 */
static pid_t
loading_handler_start ()
{
  pid_t child_pid;

  init_loading_shm ();
  child_pid = fork ();
  if (child_pid != 0)
    return child_pid;
  proctitle_set ("openvassd (Loading Handler)");
  openvas_signal (SIGTERM, sighand_loading_handler);
  /*
   * Forked process will handle client requests until parent stops it with
   * loading_handler_stop ().
   */
  while (1)
    {
      unsigned int lg_address;
      struct sockaddr_in6 address6;
      int soc;

      if (loading_stop)
        break;
      lg_address = sizeof (struct sockaddr_in6);
      soc = accept (global_iana_socket, (struct sockaddr *) (&address6),
                    &lg_address);
      loading_client_handle (soc);
    }
  exit (0);
}
Пример #3
0
static void
main_loop ()
{
  log_write ("openvassd %s started\n", OPENVASSD_VERSION);
  proctitle_set ("openvassd: Waiting for incoming connections");
  for (;;)
    {
      int soc;
      int family;
      unsigned int lg_address;
      struct sockaddr_in6 address6;
      struct sockaddr_in6 *p_addr;
      struct arglist *globals;
      struct addrinfo *ai;

      check_and_reload ();
      wait_for_children1 ();
      ai = arg_get_value (g_options, "addr");
      lg_address = sizeof (struct sockaddr_in6);
      soc = accept (global_iana_socket, (struct sockaddr *) (&address6),
                    &lg_address);
      if (soc == -1)
        continue;

      /*
       * MA: you cannot share an open SSL connection through fork/multithread
       * The SSL connection shall be open _after_ the fork */
      globals = emalloc (sizeof (struct arglist));
      arg_add_value (globals, "global_socket", ARG_INT, -1,
                     GSIZE_TO_POINTER (soc));

      arg_add_value (globals, "plugins", ARG_ARGLIST, -1, global_plugins);
      arg_add_value (globals, "preferences", ARG_ARGLIST, -1, global_preferences);

      p_addr = emalloc (sizeof (struct sockaddr_in6));
      family = ai->ai_family;
      memcpy (p_addr, &address6, sizeof (address6));
      arg_add_value (globals, "client_address", ARG_PTR, -1, p_addr);
      arg_add_value (globals, "family", ARG_INT, -1, GSIZE_TO_POINTER (family));

      /* we do not want to create an io thread, yet so the last argument is -1 */
      if (create_process ((process_func_t) scanner_thread, globals) < 0)
        {
          log_write ("Could not fork - client won't be served");
          sleep (2);
        }
      close (soc);
      arg_free (globals);
    }
}
Пример #4
0
static void
monitor_daemon(pid_t daemon_pid)
{
    /* XXX Should log daemon's stderr output at startup time. */
    time_t last_restart;
    char *status_msg;
    int crashes;

    set_subprogram_name("monitor");
    status_msg = xstrdup("healthy");
    last_restart = TIME_MIN;
    crashes = 0;
    for (;;) {
        int retval;
        int status;

        proctitle_set("monitoring pid %lu (%s)",
                      (unsigned long int) daemon_pid, status_msg);

        do {
            retval = waitpid(daemon_pid, &status, 0);
        } while (retval == -1 && errno == EINTR);

        if (retval == -1) {
            VLOG_FATAL("waitpid failed (%s)", ovs_strerror(errno));
        } else if (retval == daemon_pid) {
            char *s = process_status_msg(status);
            if (should_restart(status)) {
                free(status_msg);
                status_msg = xasprintf("%d crashes: pid %lu died, %s",
                                       ++crashes,
                                       (unsigned long int) daemon_pid, s);
                free(s);

                if (WCOREDUMP(status)) {
                    /* Disable further core dumps to save disk space. */
                    struct rlimit r;

                    r.rlim_cur = 0;
                    r.rlim_max = 0;
                    if (setrlimit(RLIMIT_CORE, &r) == -1) {
                        VLOG_WARN("failed to disable core dumps: %s",
                                  ovs_strerror(errno));
                    }
                }

                /* Throttle restarts to no more than once every 10 seconds. */
                if (time(NULL) < last_restart + 10) {
                    VLOG_WARN("%s, waiting until 10 seconds since last "
                              "restart", status_msg);
                    for (;;) {
                        time_t now = time(NULL);
                        time_t wakeup = last_restart + 10;
                        if (now >= wakeup) {
                            break;
                        }
                        xsleep(wakeup - now);
                    }
                }
                last_restart = time(NULL);

                VLOG_ERR("%s, restarting", status_msg);
                daemon_pid = fork_and_wait_for_startup(&daemonize_fd);
                if (!daemon_pid) {
                    break;
                }
            } else {
                VLOG_INFO("pid %lu died, %s, exiting",
                          (unsigned long int) daemon_pid, s);
                free(s);
                exit(0);
            }
        }
    }
    free(status_msg);

    /* Running in new daemon process. */
    proctitle_restore();
    set_subprogram_name("");
}
Пример #5
0
/**
 * @brief Attack one host.
 */
static void
attack_host (struct arglist *globals, struct arglist *hostinfos, char *hostname,
             plugins_scheduler_t sched)
{
  /* Used for the status */
  int num_plugs = 0;
  int cur_plug = 1;

  kb_t kb;
  gboolean new_kb = FALSE;
  int forks_retry = 0;
  struct arglist *plugins = arg_get_value (globals, "plugins");
  struct arglist *tmp;

  proctitle_set ("openvassd: testing %s", arg_get_value (hostinfos, "NAME"));

  kb = init_host_kb (globals, hostname, hostinfos, &new_kb);

  num_plugs = get_active_plugins_number (plugins);

  tmp = emalloc (sizeof (struct arglist));
  arg_add_value (tmp, "HOSTNAME", ARG_ARGLIST, -1, hostinfos);

  /* launch the plugins */
  pluginlaunch_init (globals);

  for (;;)
    {
      struct scheduler_plugin *plugin;
      pid_t parent;

      /* Check that our father is still alive */
      parent = getppid ();
      if (parent <= 1 || process_alive (parent) == 0)
        {
          pluginlaunch_stop ();
          return;
        }

      /* Idle if the scan has been paused. */
      if (pause_whole_test)
        {
          /* Let the running NVTs complete. */
          pluginlaunch_wait ();

          /* Send the PAUSE status to the client. */
          if (comm_send_status (globals, hostname, "pause", cur_plug, num_plugs)
              < 0)
            {
              pluginlaunch_stop ();
              goto host_died;
            }

          /* Wait for resume. */
          while (pause_whole_test)
            sleep (1);

          /* Send the RESUME status to the client. */
          if (comm_send_status (globals, hostname, "resume", cur_plug,
                                num_plugs) < 0)
            {
              pluginlaunch_stop ();
              goto host_died;
            }
        }

      plugin = plugins_scheduler_next (sched);
      if (plugin != NULL && plugin != PLUG_RUNNING)
        {
          int e;

        again:
          e = launch_plugin (globals, sched, plugin, hostname, &cur_plug,
                             num_plugs, hostinfos, kb, new_kb);
          if (e < 0)
            {
              /*
               * Remote host died
               */
              if (e == ERR_HOST_DEAD)
                goto host_died;
              else if (e == ERR_CANT_FORK)
                {
                  if (forks_retry < MAX_FORK_RETRIES)
                    {
                      forks_retry++;
                      log_write ("fork() failed - sleeping %d seconds (%s)",
                                 forks_retry, strerror (errno));
                      fork_sleep (forks_retry);
                      goto again;
                    }
                  else
                    {
                      log_write ("fork() failed too many times - aborting");
                      goto host_died;
                    }
                }
            }
        }
      else if (plugin == NULL)
        break;
      else
        pluginlaunch_wait_for_free_process ();
    }

  pluginlaunch_wait ();

host_died:
  comm_send_status (globals, hostname, "attack", num_plugs, num_plugs);
  arg_free (tmp);
  pluginlaunch_stop ();
  plugins_scheduler_free (sched);

  gchar *network_scan_status = arg_get_value (globals, "network_scan_status");
  if (network_scan_status != NULL)
    {
      if (g_ascii_strcasecmp (network_scan_status, "busy") == 0)
        {
          save_kb_close (globals, "network");
        }
    }
  else
    if (new_kb == TRUE)
      save_kb_close (globals, hostname);

}
Пример #6
0
static void
scanner_thread (struct arglist *globals)
{
  struct arglist *prefs = arg_get_value (globals, "preferences");
  char asciiaddr[INET6_ADDRSTRLEN], x509_dname[512] = { '\0' };
  int opt = 1, soc2 = -1, nice_retval, family, soc;
  void *addr = arg_get_value (globals, "client_address");
  struct sockaddr_in *saddr = NULL;
  struct sockaddr_in6 *s6addr = NULL;

  family = GPOINTER_TO_SIZE (arg_get_value (globals, "family"));
  soc = GPOINTER_TO_SIZE (arg_get_value (globals, "global_socket"));
  if (family == AF_INET)
    {
      saddr = (struct sockaddr_in *) addr;
      inet_ntop (AF_INET,  &saddr->sin_addr, asciiaddr, sizeof(asciiaddr));
    }
  else
    {
      s6addr = (struct sockaddr_in6 *) addr;
      inet_ntop (AF_INET6, &s6addr->sin6_addr, asciiaddr, sizeof (asciiaddr));
    }
  proctitle_set ("openvassd: Serving %s", asciiaddr);

  /* Everyone runs with a nicelevel of 10 */
  if (preferences_benice (prefs))
    {
      errno = 0;
      nice_retval = nice (10);
      if (nice_retval == -1 && errno != 0)
        {
          log_write ("Unable to renice process: %d", errno);
        }
    }

  /* Close the scanner thread - it is useless for us now */
  close (global_iana_socket);

  soc2 = ovas_scanner_context_attach (ovas_scanner_ctx, soc);
  if (soc2 < 0)
    goto shutdown_and_exit;

  /* FIXME: The pre-gnutls code optionally printed information about
   * the peer's certificate at this point.
   */

  setsockopt (soc, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof (opt));
  /* arg_set_value *replaces* an existing value, but it shouldn't fail here */
  (void) arg_set_value (globals, "global_socket", -1, GSIZE_TO_POINTER (soc2));

  if (comm_init (soc2) < 0)
    {
      close_stream_connection (soc);
      exit (0);
    }

  /* Get X.509 cert subject name */
  if (get_x509_dname (soc2, x509_dname, sizeof (x509_dname)) != 0)
    goto shutdown_and_exit;

  if (!check_client (x509_dname))
    {
      auth_printf (globals, "Bad login attempt !\n");
      log_write ("bad login attempt from %s\n", asciiaddr);
      goto shutdown_and_exit;
    }
  handle_client (globals);

shutdown_and_exit:
  if (soc2 >= 0)
    close_stream_connection (soc2);
  else
    {
      shutdown (soc, 2);
      close (soc);
    }

  /* Kill left overs */
  end_daemon_mode ();
  exit (0);
}