Example #1
0
static gboolean
tf_getent_group(gchar *key, gchar *member_name, GString *result)
{
  struct group grp;
  struct group *res;
  char *buf;
  long bufsize;
  int s;
  gint64 d;
  gboolean is_num, r;

  bufsize = 16384;

  buf = g_malloc(bufsize);

  if ((is_num = parse_dec_number(key, &d)) == TRUE)
    s = getgrgid_r((gid_t)d, &grp, buf, bufsize, &res);
  else
    s = getgrnam_r(key, &grp, buf, bufsize, &res);

  if (res == NULL && s != 0)
    {
      msg_error("$(getent group) failed",
                evt_tag_str("key", key),
                evt_tag_error("errno"));
      g_free(buf);
      return FALSE;
    }

  if (member_name == NULL)
    {
      if (is_num)
        member_name = "name";
      else
        member_name = "gid";
    }

  if (res == NULL)
    {
      g_free(buf);
      return FALSE;
    }

  s = _find_formatter(group_field_map, member_name);

  if (s == -1)
    {
      msg_error("$(getent group): unknown member",
                evt_tag_str("key", key),
                evt_tag_str("member", member_name));
      g_free(buf);
      return FALSE;
    }

  r = group_field_map[s].format(member_name,
                                ((uint8_t *)res) + group_field_map[s].offset,
                                result);
  g_free(buf);
  return r;
}
Example #2
0
/**
 * g_process_enable_cap:
 * @capability: capability to turn on
 *
 * This function modifies the current permitted set of capabilities by
 * enabling the capability specified in @capability.
 *
 * Returns: whether the operation was successful.
 **/
gboolean
g_process_enable_cap(const gchar *cap_name)
{
  if (!g_process_is_cap_enabled())
    return TRUE;

  cap_value_t capability;

  cap_result_type ret = _check_and_get_cap_from_text(cap_name, &capability);
  if (CAP_SUPPORTED != ret)
    return FALSE;

  /*
   * if libcap or kernel doesn't support cap_syslog, then resort to
   * cap_sys_admin
   */
  if (capability == cap_syslog && !have_capsyslog)
    {
      ret = _check_and_get_cap_from_text("cap_sys_admin", &capability);
      if (ret != CAP_SUPPORTED)
        return FALSE;
    }

  cap_t caps = cap_get_proc();
  if (!caps)
    return FALSE;

  if (cap_set_flag(caps, CAP_EFFECTIVE, 1, &capability, CAP_SET) == -1)
    {
      goto error;
    }

  if (cap_set_proc(caps) == -1)
    {
      goto error;
    }

  cap_free(caps);
  return TRUE;

error:

  msg_error("Error managing capability set",
            evt_tag_cap_t("caps", caps),
            evt_tag_error("error"));

  cap_free(caps);
  return FALSE;
}
Example #3
0
/**
 * cap_restore:
 * @r: capability set saved by cap_save()
 *
 * Restore the set of current capabilities specified by @r.
 *
 * Returns: whether the operation was successful.
 **/
void
g_process_cap_restore(cap_t r)
{
  gboolean rc;

  if (!g_process_is_cap_enabled())
    return;

  rc = cap_set_proc(r) != -1;
  if (!rc)
    {
      msg_error("Error managing capability set, cap_set_proc returned an error",
                evt_tag_cap_t("caps", r),
                evt_tag_error("error"));
    }
  cap_free(r);
}
Example #4
0
static gboolean
_setup_reuseport(gint fd)
{
#ifdef SO_REUSEPORT
  gint on = 1;
  if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)) < 0)
    {
      msg_error("The kernel refused our SO_REUSEPORT setting, which should be supported by Linux 3.9+",
                evt_tag_error("error"));
      return FALSE;
    }
  return TRUE;
#else
  msg_error("You enabled so-reuseport(), but your platform does not support SO_REUSEPORT socket option, which should be supported on Linux 3.9+");
  return FALSE;
#endif
}
Example #5
0
gboolean
confgen_exec_generate(CfgBlockGenerator *s, GlobalConfig *cfg, CfgArgs *args, GString *result, const gchar *reference)
{
  ConfgenExec *self = (ConfgenExec *) s;
  FILE *out;
  gchar buf[256];
  gint res;

  g_snprintf(buf, sizeof(buf), "%s confgen %s", cfg_lexer_lookup_context_name_by_type(self->super.context),
             self->super.name);

  cfg_args_foreach(args, confgen_set_args_as_env, NULL);
  out = popen(self->exec, "r");
  cfg_args_foreach(args, confgen_unset_args_from_env, NULL);

  if (!out)
    {
      msg_error("confgen: Error executing generator program",
                evt_tag_str("reference", reference),
                evt_tag_str("context", cfg_lexer_lookup_context_name_by_type(self->super.context)),
                evt_tag_str("block", self->super.name),
                evt_tag_str("exec", self->exec),
                evt_tag_error("error"));
      return FALSE;
    }

  _read_program_output(out, result);
  res = pclose(out);
  if (res != 0)
    {
      msg_error("confgen: Generator program returned with non-zero exit code",
                evt_tag_str("reference", reference),
                evt_tag_str("context", cfg_lexer_lookup_context_name_by_type(self->super.context)),
                evt_tag_str("block", self->super.name),
                evt_tag_str("exec", self->exec),
                evt_tag_int("rc", res));
      return FALSE;
    }
  msg_debug("confgen: output from the executed program to be included is",
            evt_tag_printf("block", "%.*s", (gint) result->len, result->str));
  return TRUE;
}
Example #6
0
gboolean
cfg_lexer_include_file(CfgLexer *self, const gchar *filename_)
{
  struct stat st;
  gchar *filename;

  if (self->include_depth >= MAX_INCLUDE_DEPTH - 1)
    {
      msg_error("Include file depth is too deep, increase MAX_INCLUDE_DEPTH and recompile",
                evt_tag_str("filename", filename_),
                evt_tag_int("depth", self->include_depth));
      return FALSE;
    }

  filename = find_file_in_path(_get_include_path(self), filename_, G_FILE_TEST_EXISTS);
  if (!filename || stat(filename, &st) < 0)
    {
      if (filename)
        g_free(filename);

      if (cfg_lexer_include_file_glob(self, filename_))
        return TRUE;

      msg_error("Include file/directory not found",
                evt_tag_str("filename", filename_),
                evt_tag_str("include-path", _get_include_path(self)),
                evt_tag_error("error"));
      return FALSE;
    }
  else
    {
      gboolean result;

      result = cfg_lexer_include_file_simple(self, filename);
      g_free(filename);
      return result;
    }
}
Example #7
0
static void
control_connection_io_output(gpointer s)
{
  ControlConnection *self = (ControlConnection *) s;
  gint rc;

  rc = self->write(self, self->output_buffer->str + self->pos, self->output_buffer->len - self->pos);
  if (rc < 0)
    {
      if (errno != EAGAIN)
        {
          msg_error("Error writing control channel",
                    evt_tag_error("error"));
          control_server_connection_closed(self->server, self);
          return;
        }
    }
  else
    {
      self->pos += rc;
    }
  control_connection_update_watches(self);
}
Example #8
0
static void
control_connection_io_input(void *s)
{
  ControlConnection *self = (ControlConnection *) s;
  GString *command = NULL;
  gchar *nl;
  gint rc;
  gint orig_len;
  GList *iter;

  if (self->input_buffer->len > MAX_CONTROL_LINE_LENGTH)
    {
      /* too much data in input, drop the connection */
      msg_error("Too much data in the control socket input buffer");
      control_server_connection_closed(self->server, self);
      return;
    }

  orig_len = self->input_buffer->len;

  /* NOTE: plus one for the terminating NUL */
  g_string_set_size(self->input_buffer, self->input_buffer->len + 128 + 1);
  rc = self->read(self, self->input_buffer->str + orig_len, 128);
  if (rc < 0)
    {
      if (errno != EAGAIN)
        {
          msg_error("Error reading command on control channel, closing control channel",
                    evt_tag_error("error"));
          goto destroy_connection;
        }
      /* EAGAIN, should try again when data comes */
      control_connection_update_watches(self);
      return;
    }
  else if (rc == 0)
    {
      msg_debug("EOF on control channel, closing connection");
      goto destroy_connection;
    }
  else
    {
      self->input_buffer->len = orig_len + rc;
      self->input_buffer->str[self->input_buffer->len] = 0;
    }

  /* here we have finished reading the input, check if there's a newline somewhere */
  nl = strchr(self->input_buffer->str, '\n');
  if (nl)
    {
      command = g_string_sized_new(128);
      /* command doesn't contain NL */
      g_string_assign_len(command, self->input_buffer->str, nl - self->input_buffer->str);
      secret_storage_wipe(self->input_buffer->str, nl - self->input_buffer->str);
      /* strip NL */
      /*g_string_erase(self->input_buffer, 0, command->len + 1);*/
      g_string_truncate(self->input_buffer, 0);
    }
  else
    {
      /* no EOL in the input buffer, wait for more data */
      control_connection_update_watches(self);
      return;
    }

  iter = g_list_find_custom(get_control_command_list(), command->str,
                            (GCompareFunc)control_command_start_with_command);
  if (iter == NULL)
    {
      msg_error("Unknown command read on control channel, closing control channel",
                evt_tag_str("command", command->str));
      g_string_free(command, TRUE);
      goto destroy_connection;
    }
  ControlCommand *cmd_desc = (ControlCommand *) iter->data;

  cmd_desc->func(self, command, cmd_desc->user_data);
  control_connection_wait_for_output(self);

  secret_storage_wipe(command->str, command->len);
  g_string_free(command, TRUE);
  return;
destroy_connection:
  control_server_connection_closed(self->server, self);
}