Skip to content

Commit

Permalink
Improve realpath-related error handling for logs
Browse files Browse the repository at this point in the history
  • Loading branch information
droe committed Oct 25, 2018
1 parent 85780a4 commit a628ab6
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 20 deletions.
64 changes: 44 additions & 20 deletions opts.c
Original file line number Diff line number Diff line change
Expand Up @@ -956,7 +956,7 @@ opts_set_jaildir(opts_t *opts, const char *argv0, const char *optarg)
free(opts->jaildir);
opts->jaildir = realpath(optarg, NULL);
if (!opts->jaildir) {
fprintf(stderr, "%s: Failed to canonicalize '%s': %s (%i)\n",
fprintf(stderr, "%s: Failed to realpath '%s': %s (%i)\n",
argv0, optarg, strerror(errno), errno);
exit(EXIT_FAILURE);
}
Expand All @@ -983,10 +983,16 @@ opts_set_connectlog(opts_t *opts, const char *argv0, const char *optarg)
{
if (opts->connectlog)
free(opts->connectlog);
if (!(opts->connectlog = realpath(optarg, NULL))) {
fprintf(stderr, "Failed to realpath '%s': %s (%i)\n",
optarg, strerror(errno), errno);
oom_die(argv0);
if (!(opts->connectlog = sys_realdir(optarg))) {
if (errno == ENOENT) {
fprintf(stderr, "Directory part of '%s' does not "
"exist\n", optarg);
exit(EXIT_FAILURE);
} else {
fprintf(stderr, "Failed to realpath '%s': %s (%i)\n",
optarg, strerror(errno), errno);
oom_die(argv0);
}
}
#ifdef DEBUG_OPTS
log_dbg_printf("ConnectLog: %s\n", opts->connectlog);
Expand All @@ -998,10 +1004,16 @@ opts_set_contentlog(opts_t *opts, const char *argv0, const char *optarg)
{
if (opts->contentlog)
free(opts->contentlog);
if (!(opts->contentlog = realpath(optarg, NULL))) {
fprintf(stderr, "Failed to realpath '%s': %s (%i)\n",
optarg, strerror(errno), errno);
oom_die(argv0);
if (!(opts->contentlog = sys_realdir(optarg))) {
if (errno == ENOENT) {
fprintf(stderr, "Directory part of '%s' does not "
"exist\n", optarg);
exit(EXIT_FAILURE);
} else {
fprintf(stderr, "Failed to realpath '%s': %s (%i)\n",
optarg, strerror(errno), errno);
oom_die(argv0);
}
}
opts->contentlog_isdir = 0;
opts->contentlog_isspec = 0;
Expand All @@ -1021,7 +1033,7 @@ opts_set_contentlogdir(opts_t *opts, const char *argv0, const char *optarg)
free(opts->contentlog);
opts->contentlog = realpath(optarg, NULL);
if (!opts->contentlog) {
fprintf(stderr, "%s: Failed to canonicalize '%s': %s (%i)\n",
fprintf(stderr, "%s: Failed to realpath '%s': %s (%i)\n",
argv0, optarg, strerror(errno), errno);
exit(EXIT_FAILURE);
}
Expand Down Expand Up @@ -1064,7 +1076,7 @@ opts_set_logbasedir(const char *argv0, const char *optarg,
}
*basedir = realpath(lhs, NULL);
if (!*basedir) {
fprintf(stderr, "%s: Failed to canonicalize '%s': %s (%i)\n",
fprintf(stderr, "%s: Failed to realpath '%s': %s (%i)\n",
argv0, lhs, strerror(errno), errno);
exit(EXIT_FAILURE);
}
Expand Down Expand Up @@ -1127,10 +1139,16 @@ opts_set_masterkeylog(opts_t *opts, const char *argv0, const char *optarg)
{
if (opts->masterkeylog)
free(opts->masterkeylog);
if (!(opts->masterkeylog = realpath(optarg, NULL))) {
fprintf(stderr, "Failed to realpath '%s': %s (%i)\n",
optarg, strerror(errno), errno);
oom_die(argv0);
if (!(opts->masterkeylog = sys_realdir(optarg))) {
if (errno == ENOENT) {
fprintf(stderr, "Directory part of '%s' does not "
"exist\n", optarg);
exit(EXIT_FAILURE);
} else {
fprintf(stderr, "Failed to realpath '%s': %s (%i)\n",
optarg, strerror(errno), errno);
oom_die(argv0);
}
}
#ifdef DEBUG_OPTS
log_dbg_printf("MasterKeyLog: %s\n", opts->masterkeylog);
Expand All @@ -1142,10 +1160,16 @@ opts_set_pcaplog(opts_t *opts, const char *argv0, const char *optarg)
{
if (opts->pcaplog)
free(opts->pcaplog);
if (!(opts->pcaplog = realpath(optarg, NULL))) {
fprintf(stderr, "Failed to realpath '%s': %s (%i)\n",
optarg, strerror(errno), errno);
oom_die(argv0);
if (!(opts->pcaplog = sys_realdir(optarg))) {
if (errno == ENOENT) {
fprintf(stderr, "Directory part of '%s' does not "
"exist\n", optarg);
exit(EXIT_FAILURE);
} else {
fprintf(stderr, "Failed to realpath '%s': %s (%i)\n",
optarg, strerror(errno), errno);
oom_die(argv0);
}
}
opts->pcaplog_isdir = 0;
opts->pcaplog_isspec = 0;
Expand All @@ -1165,7 +1189,7 @@ opts_set_pcaplogdir(opts_t *opts, const char *argv0, const char *optarg)
free(opts->pcaplog);
opts->pcaplog = realpath(optarg, NULL);
if (!opts->pcaplog) {
fprintf(stderr, "%s: Failed to canonicalize '%s': %s (%i)\n",
fprintf(stderr, "%s: Failed to realpath '%s': %s (%i)\n",
argv0, optarg, strerror(errno), errno);
exit(EXIT_FAILURE);
}
Expand Down
46 changes: 46 additions & 0 deletions sys.c
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,52 @@ sys_mkpath(const char *path, mode_t mode)
return 0;
}

/*
* Return realpath(dirname(path)) + / + basename(path) in a newly allocated
* string. Returns NULL on failure and sets errno to ENOENT if the directory
* part does not exist.
*/
char *
sys_realdir(const char *path)
{
char *sep, *udir, *rdir, *p;
int rerrno;

if (path[0] == '\0') {
errno = EINVAL;
return NULL;
}

udir = strdup(path);
if (!udir)
return NULL;

sep = strrchr(udir, '/');
if (!sep) {
free(udir);
(void)asprintf(&udir, "./%s", path);
if (!udir)
return NULL;
sep = udir + 1;
} else if (sep == udir) {
return udir;
}
*sep = '\0';
rdir = realpath(udir, NULL);
if (!rdir) {
rerrno = errno;
free(udir);
errno = rerrno;
return NULL;
}
(void)asprintf(&p, "%s/%s", rdir, sep + 1);
rerrno = errno;
free(rdir);
free(udir);
errno = rerrno;
return p;
}

/*
* Iterate over all files in a directory hierarchy, calling the callback
* cb for each file, passing the filename and arg as arguments. Files and
Expand Down
1 change: 1 addition & 0 deletions sys.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ size_t sys_get_mtu(const char *);

int sys_isdir(const char *) NONNULL(1) WUNRES;
int sys_mkpath(const char *, mode_t) NONNULL(1) WUNRES;
char * sys_realdir(const char *) NONNULL(1) MALLOC;

typedef int (*sys_dir_eachfile_cb_t)(const char *, void *) NONNULL(1) WUNRES;
int sys_dir_eachfile(const char *, sys_dir_eachfile_cb_t, void *) NONNULL(1,2) WUNRES;
Expand Down
50 changes: 50 additions & 0 deletions sys.t.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,49 @@ START_TEST(sys_mkpath_01)
}
END_TEST

START_TEST(sys_realdir_01)
{
char *rd;

rd = sys_realdir("./extra/../sys.t.c");
fail_unless(!!rd, "sys_realdir failed");
fail_unless(!!strstr(rd, "/sys.t.c"), "filename not found");
fail_unless(!strstr(rd, "/extra/"), "extra in path");
fail_unless(!strstr(rd, "/../"), "dot-dot in path");
free(rd);
}
END_TEST

START_TEST(sys_realdir_02)
{
char *rd;

rd = sys_realdir("/foo/bar/baz");
fail_unless(!rd, "sys_realdir did not fail");
fail_unless(errno == ENOENT, "errno not ENOENT");
}
END_TEST

START_TEST(sys_realdir_03)
{
char *rd;

rd = sys_realdir("foobarbaz");
fail_unless(!!rd, "sys_realdir failed");
fail_unless(!!strstr(rd, "/foobarbaz"), "filename not found or dir");
free(rd);
}
END_TEST

START_TEST(sys_realdir_04)
{
char *rd;

rd = sys_realdir("");
fail_unless(!rd, "sys_realdir did not fail");
}
END_TEST

int
sys_dir_eachfile_cb(UNUSED const char *fn, void *arg)
{
Expand Down Expand Up @@ -294,6 +337,13 @@ sys_suite(void)
tcase_add_test(tc, sys_mkpath_01);
suite_add_tcase(s, tc);

tc = tcase_create("sys_realdir");
tcase_add_test(tc, sys_realdir_01);
tcase_add_test(tc, sys_realdir_02);
tcase_add_test(tc, sys_realdir_03);
tcase_add_test(tc, sys_realdir_04);
suite_add_tcase(s, tc);

tc = tcase_create("sys_dir_eachfile");
tcase_add_test(tc, sys_dir_eachfile_01);
suite_add_tcase(s, tc);
Expand Down

0 comments on commit a628ab6

Please sign in to comment.