/* usage: ModulePath path */ MODRET set_modulepath(cmd_rec *cmd) { int res; struct stat st; CHECK_ARGS(cmd, 1); CHECK_CONF(cmd, CONF_ROOT); if (pr_fs_valid_path(cmd->argv[1]) < 0) CONF_ERROR(cmd, "must be an absolute path"); /* Make sure that the configured path is not world-writeable. */ res = pr_fsio_stat(cmd->argv[1], &st); if (res < 0) CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "error checking '", cmd->argv[1], "': ", strerror(errno), NULL)); if (!S_ISDIR(st.st_mode)) CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, cmd->argv[1], " is not a directory", NULL)); if (st.st_mode & S_IWOTH) CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, cmd->argv[1], " is world-writable", NULL)); if (lt_dlsetsearchpath(cmd->argv[1]) < 0) CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "error setting module path: ", lt_dlerror(), NULL)); dso_module_path = pstrdup(dso_pool, cmd->argv[1]); return PR_HANDLED(cmd); }
/* usage: CounterLog path|"none" */ MODRET set_counterlog(cmd_rec *cmd) { CHECK_ARGS(cmd, 1); CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL); if (pr_fs_valid_path(cmd->argv[1]) < 0) { CONF_ERROR(cmd, "must be an absolute path"); } add_config_param_str(cmd->argv[0], 1, cmd->argv[1]); return PR_HANDLED(cmd); }
/* usage: LoadFile path */ MODRET set_loadfile(cmd_rec *cmd) { CHECK_ARGS(cmd, 1); CHECK_CONF(cmd, CONF_ROOT); if (pr_fs_valid_path(cmd->argv[1]) < 0) CONF_ERROR(cmd, "must be an absolute path"); if (dso_load_file(cmd->argv[1]) < 0) CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "error loading '", cmd->argv[1], "': ", strerror(errno), NULL)); return PR_HANDLED(cmd); }
int parse_config_path2(pool *p, const char *path, unsigned int depth) { struct stat st; int have_glob; void *dirh; struct dirent *dent; array_header *file_list; char *dup_path, *ptr; pool *tmp_pool; if (p == NULL || path == NULL || (depth > PR_PARSER_INCLUDE_MAX_DEPTH)) { errno = EINVAL; return -1; } if (pr_fs_valid_path(path) < 0) { errno = EINVAL; return -1; } have_glob = pr_str_is_fnmatch(path); if (have_glob) { /* Even though the path may be valid, it also may not be a filesystem * path; consider custom FSIO modules. Thus if the path does not start * with a slash, it should not be treated as having globs. */ if (*path != '/') { have_glob = FALSE; } } pr_fs_clear_cache2(path); if (have_glob) { pr_trace_msg(trace_channel, 19, "parsing '%s' as a globbed path", path); } if (!have_glob && pr_fsio_lstat(path, &st) < 0) { return -1; } /* If path is not a glob pattern, and is a symlink OR is not a directory, * then use the normal parsing function for the file. */ if (have_glob == FALSE && (S_ISLNK(st.st_mode) || !S_ISDIR(st.st_mode))) { int res, xerrno; PRIVS_ROOT res = pr_parser_parse_file(p, path, NULL, 0); xerrno = errno; PRIVS_RELINQUISH errno = xerrno; return res; } tmp_pool = make_sub_pool(p); pr_pool_tag(tmp_pool, "Include sub-pool"); /* Handle the glob/directory. */ dup_path = pstrdup(tmp_pool, path); ptr = strrchr(dup_path, '/'); if (have_glob) { int have_glob_dir; /* Note that we know, by definition, that ptr CANNOT be null here; dup_path * is a duplicate of path, and the first character (if nothing else) of * path MUST be a slash, per earlier checks. */ *ptr = '\0'; /* We just changed ptr, thus we DO need to check whether the now-modified * path contains fnmatch(3) characters again. */ have_glob_dir = pr_str_is_fnmatch(dup_path); if (have_glob_dir) { const char *glob_dir; if (parser_include_opts & PR_PARSER_INCLUDE_OPT_IGNORE_WILDCARDS) { pr_log_pri(PR_LOG_WARNING, "error: wildcard patterns not allowed in " "configuration directory name '%s'", dup_path); destroy_pool(tmp_pool); errno = EINVAL; return -1; } *ptr = '/'; glob_dir = pstrdup(p, dup_path); destroy_pool(tmp_pool); return parse_wildcard_config_path(p, glob_dir, depth); } ptr++; /* Check the directory component. */ pr_fs_clear_cache2(dup_path); if (pr_fsio_lstat(dup_path, &st) < 0) { int xerrno = errno; pr_log_pri(PR_LOG_WARNING, "error: failed to check configuration path '%s': %s", dup_path, strerror(xerrno)); destroy_pool(tmp_pool); errno = xerrno; return -1; } if (S_ISLNK(st.st_mode) && !(parser_include_opts & PR_PARSER_INCLUDE_OPT_ALLOW_SYMLINKS)) { pr_log_pri(PR_LOG_WARNING, "error: cannot read configuration path '%s': Symbolic link", path); destroy_pool(tmp_pool); errno = ENOTDIR; return -1; } if (have_glob_dir == FALSE && pr_str_is_fnmatch(ptr) == FALSE) { pr_log_pri(PR_LOG_WARNING, "error: wildcard pattern required for file '%s'", ptr); destroy_pool(tmp_pool); errno = EINVAL; return -1; } } pr_log_pri(PR_LOG_DEBUG, "processing configuration directory '%s'", dup_path); dirh = pr_fsio_opendir(dup_path); if (dirh == NULL) { pr_log_pri(PR_LOG_WARNING, "error: unable to open configuration directory '%s': %s", dup_path, strerror(errno)); destroy_pool(tmp_pool); errno = EINVAL; return -1; } file_list = make_array(tmp_pool, 0, sizeof(char *)); while ((dent = pr_fsio_readdir(dirh)) != NULL) { pr_signals_handle(); if (strncmp(dent->d_name, ".", 2) == 0 || strncmp(dent->d_name, "..", 3) == 0) { continue; } if (parser_include_opts & PR_PARSER_INCLUDE_OPT_IGNORE_TMP_FILES) { if (is_tmp_file(dent->d_name) == TRUE) { pr_trace_msg(trace_channel, 19, "ignoring temporary file '%s' found in directory '%s'", dent->d_name, dup_path); continue; } } if (have_glob == FALSE || (ptr != NULL && pr_fnmatch(ptr, dent->d_name, PR_FNM_PERIOD) == 0)) { *((char **) push_array(file_list)) = pdircat(tmp_pool, dup_path, dent->d_name, NULL); } } pr_fsio_closedir(dirh); if (file_list->nelts) { register unsigned int i; qsort((void *) file_list->elts, file_list->nelts, sizeof(char *), config_filename_cmp); for (i = 0; i < file_list->nelts; i++) { int res, xerrno; char *file; file = ((char **) file_list->elts)[i]; /* Make sure we always parse the files with root privs. The * previously parsed file might have had root privs relinquished * (e.g. by its directive handlers), but when we first start up, * we have root privs. See Bug#3855. */ PRIVS_ROOT res = pr_parser_parse_file(tmp_pool, file, NULL, 0); xerrno = errno; PRIVS_RELINQUISH if (res < 0) { pr_log_pri(PR_LOG_WARNING, "error: unable to open parse file '%s': %s", file, strerror(xerrno)); } } } destroy_pool(tmp_pool); return 0; }