#include "validator/validator.h"
#include "services/localzone.h"
#include <pwd.h>
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
/** Give checkconf usage, and exit (1). */
static void
}
}
+/** true if fname is a file */
+static int
+is_file(const char* fname)
+{
+ struct stat buf;
+ if(stat(fname, &buf) < 0) {
+ if(errno==EACCES) {
+ printf("warning: no search permission for one of the directories in path: %s\n", fname);
+ return 1;
+ }
+ perror(fname);
+ return 0;
+ }
+ if(S_ISDIR(buf.st_mode)) {
+ printf("%s is not a file\n", fname);
+ return 0;
+ }
+ return 1;
+}
+
+/** true if fname is a directory */
+static int
+is_dir(const char* fname)
+{
+ struct stat buf;
+ if(stat(fname, &buf) < 0) {
+ if(errno==EACCES) {
+ printf("warning: no search permission for one of the directories in path: %s\n", fname);
+ return 1;
+ }
+ perror(fname);
+ return 0;
+ }
+ if(!(S_ISDIR(buf.st_mode))) {
+ printf("%s is not a directory\n", fname);
+ return 0;
+ }
+ return 1;
+}
+
+/** convert a filename to full pathname in original filesys. return static */
+static char*
+fname_after_chroot(const char* fname, struct config_file* cfg, int use_chdir)
+{
+ static char buf[1024];
+ int slashit = 0;
+ buf[0] = 0;
+ if(cfg->chrootdir && cfg->chrootdir[0] &&
+ strncmp(cfg->chrootdir, fname, strlen(cfg->chrootdir)) == 0) {
+ /* already full pathname, return it */
+ strncpy(buf, fname, sizeof(buf)-1);
+ buf[sizeof(buf)-1] = 0;
+ return buf;
+ }
+ /* chroot */
+ if(cfg->chrootdir && cfg->chrootdir[0]) {
+ /* start with chrootdir */
+ strncpy(buf, cfg->chrootdir, sizeof(buf)-1);
+ slashit = 1;
+ }
+ /* chdir */
+ if(fname[0] == '/' || !use_chdir) {
+ /* full path, no chdir */
+ } else if(cfg->directory && cfg->directory[0]) {
+ /* prepend chdir */
+ if(slashit && cfg->directory[0] != '/')
+ strncat(buf, "/", sizeof(buf)-1);
+ if(strncmp(cfg->chrootdir, cfg->directory,
+ strlen(cfg->chrootdir)) == 0)
+ strncat(buf, cfg->directory+strlen(cfg->chrootdir),
+ sizeof(buf)-1);
+ else strncat(buf, cfg->directory, sizeof(buf)-1);
+ slashit = 1;
+ }
+ /* fname */
+ if(slashit && fname[0] != '/')
+ strncat(buf, "/", sizeof(buf)-1);
+ strncat(buf, fname, sizeof(buf)-1);
+ buf[sizeof(buf)-1] = 0;
+ return buf;
+}
+
+/** get base dir of a fname */
+static char*
+basedir(const char* fname, struct config_file* cfg)
+{
+ char* d = fname_after_chroot(fname, cfg, 1);
+ char* rev = strrchr(d, '/');
+ if(!rev) return NULL;
+ if(d == rev) return NULL;
+ rev[0] = 0;
+ return d;
+}
+
/** check file list, every file must be inside the chroot location */
static void
check_chroot_filelist(const char* desc, struct config_strlist* list,
- const char* chrootdir)
+ const char* chrootdir, struct config_file* cfg)
{
struct config_strlist* p;
- if(!chrootdir) return;
+ char* old;
for(p=list; p; p=p->next) {
- if(p->str && p->str[0] && strncmp(chrootdir, p->str,
- strlen(chrootdir)) != 0) {
- fatal_exit("%s: \"%s\" not in chrootdir %s",
- desc, p->str, chrootdir);
+ if(p->str && p->str[0]) {
+ if(!is_file(fname_after_chroot(p->str, cfg, 1))) {
+ fatal_exit("%s: \"%s\" does not exist in chrootdir %s",
+ desc, p->str, chrootdir);
+ }
+ old = p->str;
+ /* put in a new full path for continued checking */
+ p->str = strdup(fname_after_chroot(p->str, cfg, 1));
+ free(old);
}
}
}
cfg->chrootdir[strlen(cfg->chrootdir)-1] == '/')
fatal_exit("chootdir %s has trailing slash '/' please remove.",
cfg->chrootdir);
- if(cfg->chrootdir && strncmp(cfg->chrootdir, cfg->directory,
- strlen(cfg->chrootdir)) != 0)
- fatal_exit("working directory %s not in chrootdir %s",
- cfg->directory, cfg->chrootdir);
- if(cfg->chrootdir && cfg->pidfile && cfg->pidfile[0] &&
- strncmp(cfg->chrootdir, cfg->pidfile,
- strlen(cfg->chrootdir)) != 0)
- fatal_exit("pid file %s not in chrootdir %s",
- cfg->pidfile, cfg->chrootdir);
- if(cfg->chrootdir && cfg->logfile && cfg->logfile[0] &&
- strncmp(cfg->chrootdir, cfg->logfile,
- strlen(cfg->chrootdir)) != 0)
- fatal_exit("log file %s not in chrootdir %s",
- cfg->logfile, cfg->chrootdir);
+ if(cfg->chrootdir && cfg->chrootdir[0] &&
+ !is_dir(cfg->chrootdir)) {
+ fatal_exit("bad chroot directory");
+ }
+ if(cfg->directory && cfg->directory[0] &&
+ !is_dir(fname_after_chroot(cfg->directory, cfg, 0))) {
+ fatal_exit("bad chdir directory");
+ }
+ if( (cfg->chrootdir && cfg->chrootdir[0]) ||
+ (cfg->directory && cfg->directory[0])) {
+ if(cfg->pidfile && cfg->pidfile[0] &&
+ basedir(cfg->pidfile, cfg) &&
+ !is_dir(basedir(cfg->pidfile, cfg))) {
+ fatal_exit("pidfile directory does not exist");
+ }
+ if(cfg->logfile && cfg->logfile[0] &&
+ basedir(cfg->logfile, cfg) &&
+ !is_dir(basedir(cfg->logfile, cfg))) {
+ fatal_exit("pidfile directory does not exist");
+ }
+ }
+
check_chroot_filelist("file with root-hints",
- cfg->root_hints, cfg->chrootdir);
+ cfg->root_hints, cfg->chrootdir, cfg);
check_chroot_filelist("trust-anchor-file",
- cfg->trust_anchor_file_list, cfg->chrootdir);
+ cfg->trust_anchor_file_list, cfg->chrootdir, cfg);
check_chroot_filelist("trusted-keys-file",
- cfg->trusted_keys_file_list, cfg->chrootdir);
+ cfg->trusted_keys_file_list, cfg->chrootdir, cfg);
+ /* remove chroot setting so that modules are not stripping pathnames*/
+ free(cfg->chrootdir);
+ cfg->chrootdir = NULL;
if(strcmp(cfg->module_conf, "iterator") != 0 &&
strcmp(cfg->module_conf, "validator iterator") != 0) {