Beispiel #1
0
static wrap2_table_t *filetab_open_cb(pool *parent_pool, const char *srcinfo) {
  struct stat st;
  wrap2_table_t *tab = NULL;
  pool *tab_pool = make_sub_pool(parent_pool);

  /* Do not allow relative paths. */
  if (*srcinfo != '/' &&
      *srcinfo != '~') {
    wrap2_log("error: table relative paths are forbidden: '%s'", srcinfo);
    destroy_pool(tab_pool);
    errno = EINVAL;
    return NULL;
  }

  /* If the path starts with a tilde, expand it out. */
  if (srcinfo[0] == '~' &&
      srcinfo[1] == '/') {
    char *path = NULL;

    PRIVS_USER
    path = dir_realpath(tab_pool, srcinfo);
    PRIVS_RELINQUISH

    if (path) {
      srcinfo = path;
      wrap2_log("resolved tilde: path now '%s'", srcinfo);
    }
  }
Beispiel #2
0
static array_header *sqltab_fetch_clients_cb(wrap2_table_t *sqltab,
    const char *name) {
  pool *tmp_pool = NULL;
  cmdtable *sql_cmdtab = NULL;
  cmd_rec *sql_cmd = NULL;
  modret_t *sql_res = NULL;
  array_header *sql_data = NULL;
  char *query = NULL, **vals = NULL;
  array_header *clients_list = NULL;

  /* Allocate a temporary pool for the duration of this read. */
  tmp_pool = make_sub_pool(sqltab->tab_pool);

  query = ((char **) sqltab->tab_data)[0];

  /* Find the cmdtable for the sql_lookup command. */
  sql_cmdtab = pr_stash_get_symbol(PR_SYM_HOOK, "sql_lookup", NULL, NULL);
  if (sql_cmdtab == NULL) {
    wrap2_log("error: unable to find SQL hook symbol 'sql_lookup'");
    destroy_pool(tmp_pool);
    return NULL;
  }

  /* Prepare the SELECT query. */
  sql_cmd = sql_cmd_create(tmp_pool, 3, "sql_lookup", query, name);

  /* Call the handler. */
  sql_res = call_module(sql_cmdtab->m, sql_cmdtab->handler, sql_cmd);

  /* Check the results. */
  if (!sql_res) {
    wrap2_log("NamedQuery '%s' returned no data", query);
    destroy_pool(tmp_pool);
    return NULL;
  }

  if (MODRET_ISERROR(sql_res)) {
    wrap2_log("error processing NamedQuery '%s'", query);
    destroy_pool(tmp_pool);
    return NULL;
  }

  /* Construct a single string, concatenating the returned client tokens
   * together.
   */
  sql_data = (array_header *) sql_res->data;
  vals = (char **) sql_data->elts;

  if (sql_data->nelts < 1) {
    wrap2_log("NamedQuery '%s' returned no data", query);
    destroy_pool(tmp_pool);
    return NULL;
  }

  clients_list = make_array(sqltab->tab_pool, sql_data->nelts, sizeof(char *));
  *((char **) push_array(clients_list)) = pstrdup(sqltab->tab_pool, vals[0]);

  if (sql_data->nelts > 1) {
    register unsigned int i = 0;

    for (i = 1; i < sql_data->nelts; i++) {
      *((char **) push_array(clients_list)) = pstrdup(sqltab->tab_pool,
        vals[i]);
    }
  }

  destroy_pool(tmp_pool);
  return clients_list;
}
Beispiel #3
0
static wrap2_table_t *sqltab_open_cb(pool *parent_pool, char *srcinfo) {
  wrap2_table_t *tab = NULL;
  pool *tab_pool = make_sub_pool(parent_pool),
    *tmp_pool = make_sub_pool(parent_pool);
  config_rec *c = NULL;
  char *start = NULL, *finish = NULL, *query = NULL, *clients_query = NULL,
    *options_query = NULL;

  tab = (wrap2_table_t *) pcalloc(tab_pool, sizeof(wrap2_table_t));
  tab->tab_pool = tab_pool;

  /* Parse the SELECT query name out of the srcinfo string.  Lookup and
   * store the query in the tab_data area, so that it need not be looked
   * up later.
   *
   * The srcinfo string for this case should look like:
   *  "/<clients-named-query>[/<options-named-query>]"
   */

  start = strchr(srcinfo, '/');
  if (start == NULL) {
    wrap2_log("error: badly formatted source info '%s'", srcinfo);
    destroy_pool(tab_pool);
    destroy_pool(tmp_pool);
    errno = EINVAL;
    return NULL;
  }

  /* Find the next slash. */
  finish = strchr(++start, '/');

  if (finish)
    *finish = '\0';

  clients_query = pstrdup(tab->tab_pool, start);

  /* Verify that the named query has indeed been defined.  This is
   * base on how mod_sql creates its config_rec names.
   */
  query = pstrcat(tmp_pool, "SQLNamedQuery_", clients_query, NULL);

  c = find_config(main_server->conf, CONF_PARAM, query, FALSE);
  if (c == NULL) {
    wrap2_log("error: unable to resolve SQLNamedQuery name '%s'",
      clients_query);
    destroy_pool(tab_pool);
    destroy_pool(tmp_pool);
    errno = EINVAL;
    return NULL;
  }

  /* Handle the options-query, if present. */
  if (finish) {
    options_query = pstrdup(tab->tab_pool, ++finish);

    query = pstrcat(tmp_pool, "SQLNamedQuery_", options_query, NULL);

    c = find_config(main_server->conf, CONF_PARAM, query, FALSE);
    if (c == NULL) {
      wrap2_log("error: unable to resolve SQLNamedQuery name '%s'",
        options_query);
      destroy_pool(tab_pool);
      destroy_pool(tmp_pool);
      errno = EINVAL;
      return NULL;
    }
  }

  tab->tab_name = pstrcat(tab->tab_pool, "SQL(", srcinfo, ")", NULL);

  tab->tab_data = pcalloc(tab->tab_pool, 2 * sizeof(char));
  ((char **) tab->tab_data)[0] = pstrdup(tab->tab_pool, clients_query);

  ((char **) tab->tab_data)[1] =
    (options_query ? pstrdup(tab->tab_pool, options_query) : NULL);

  /* Set the necessary callbacks. */
  tab->tab_close = sqltab_close_cb;
  tab->tab_fetch_clients = sqltab_fetch_clients_cb;
  tab->tab_fetch_daemons = sqltab_fetch_daemons_cb;
  tab->tab_fetch_options = sqltab_fetch_options_cb;

  destroy_pool(tmp_pool);
  return tab;
}
Beispiel #4
0
static void filetab_parse_table(wrap2_table_t *filetab) {
  unsigned int lineno = 0;
  char buf[MOD_WRAP2_FILE_BUFFER_SIZE] = {'\0'};

  while (pr_fsio_getline(buf, sizeof(buf), (pr_fh_t *) filetab->tab_handle,
      &lineno) != NULL) {
    char *ptr, *res = NULL, *service = NULL;
    size_t buflen = strlen(buf);

    if (buf[buflen-1] != '\n') {
      wrap2_log("file '%s': missing newline or line too long (%u) at line %u",
        filetab->tab_name, (unsigned int) buflen, lineno);
      continue;
    } 

    if (buf[0] == '#' || buf[strspn(buf, " \t\r\n")] == 0) {
      continue;
    }

    buf[buflen-1] = '\0';

    /* The list of daemons is from the start of the line to a ':' delimiter.
     * This list is assumed to be space-delimited; failure to match this
     * syntax will result in lack of desired results when doing the access
     * checks.
     */
    ptr = strchr(buf, ':');
    if (ptr == NULL) {
      wrap2_log("file '%s': badly formatted list of daemon/service names at "
        "line %u", filetab->tab_name, lineno);
      continue;
    }

    service = pstrndup(filetab->tab_pool, buf, (ptr - buf));

    if (filetab_service_name &&
        (strcasecmp(filetab_service_name, service) == 0 ||
         strncasecmp("ALL", service, 4) == 0)) {
      if (filetab_daemons_list == NULL) {
        filetab_daemons_list = make_array(filetab->tab_pool, 0, sizeof(char *));
      }

      *((char **) push_array(filetab_daemons_list)) = service;

      res = wrap2_strsplit(buf, ':');
      if (res == NULL) {
        wrap2_log("file '%s': missing \":\" separator at %u",
          filetab->tab_name, lineno);
        continue;
      }

      if (filetab_clients_list == NULL) {
        filetab_clients_list = make_array(filetab->tab_pool, 0, sizeof(char *));
      }

      /* Check for another ':' delimiter.  If present, anything following that
       * delimiter is an option/shell command (as per the hosts_access(5) man
       * page syntax description).
       *
       * If there are commas or whitespace in the line, parse them as separate
       * client names.  Otherwise, a comma- or space-delimited list of names
       * will be treated as a single name, and violate the principle of least
       * surprise for the site admin.
       *
       * NOTE: Disable support for options in the file syntax if IPv6 addresses
       * are present, since the parsing code below is not sufficient for
       * handling both IPv6 addresses AND options, e.g.:
       *
       *  proftpd: [::1] [::2]: <options>
       */

      ptr = strchr(res, ':');
      if (ptr != NULL) {
        char *clients;
        size_t clients_len;

        clients_len = (ptr - res);
        clients = pstrndup(filetab->tab_pool, res, clients_len);

        if (strcspn(clients, "[]") == clients_len) {
          ptr = wrap2_strsplit(res, ':');

          if (filetab_options_list == NULL) {
            filetab_options_list = make_array(filetab->tab_pool, 0, 
              sizeof(char *));
          }

          /* Skip redundant whitespaces */
          while (*ptr == ' ' ||
                 *ptr == '\t') {
            pr_signals_handle();
            ptr++;
          }

          *((char **) push_array(filetab_options_list)) =
            pstrdup(filetab->tab_pool, ptr);

        } else {
          /* Ignoring options and IPv6 addresses (Bug#4090) for now. */
        }

      } else {
        /* No options present. */
        ptr = res;
      }

      ptr = strpbrk(res, ", \t");
      if (ptr != NULL) {
        char *dup_opts, *word;

        dup_opts = pstrdup(filetab->tab_pool, res);
        while ((word = pr_str_get_token(&dup_opts, ", \t")) != NULL) {
          size_t wordlen;

          pr_signals_handle();

          wordlen = strlen(word);
          if (wordlen == 0) {
            continue;
          }

          /* Remove any trailing comma */
          if (word[wordlen-1] == ',') {
            word[wordlen-1] = '\0';
            wordlen--;
          }

          *((char **) push_array(filetab_clients_list)) = word;

          /* Skip redundant whitespaces */
          while (*dup_opts == ' ' ||
                 *dup_opts == '\t') {
            pr_signals_handle();
            dup_opts++;
          }
        }

      } else {
        *((char **) push_array(filetab_clients_list)) =
          pstrdup(filetab->tab_pool, res);
      }
 
    } else {
      wrap2_log("file '%s': skipping irrevelant daemon/service ('%s') line %u",
        filetab->tab_name, service, lineno);
    }
  }

  return;
}