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); } }
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; }
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; }
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; }