Move io_mkdir_parents() to its own file and use it in ts_mkdirs().

This commit is contained in:
Todd C. Miller
2016-10-29 12:45:57 -06:00
parent 271a07ff00
commit bf62530acf
6 changed files with 124 additions and 104 deletions

View File

@@ -111,7 +111,6 @@ lib/util/parseln.c
lib/util/progname.c
lib/util/pw_dup.c
lib/util/reallocarray.c
lib/util/vsyslog.c
lib/util/regress/atofoo/atofoo_test.c
lib/util/regress/fnmatch/fnm_test.c
lib/util/regress/fnmatch/fnm_test.in
@@ -176,6 +175,7 @@ lib/util/term.c
lib/util/ttysize.c
lib/util/util.exp.in
lib/util/utimens.c
lib/util/vsyslog.c
lib/zlib/Makefile.in
lib/zlib/adler32.c
lib/zlib/compress.c
@@ -291,6 +291,7 @@ plugins/sudoers/logwrap.c
plugins/sudoers/match.c
plugins/sudoers/match_addr.c
plugins/sudoers/mkdefaults
plugins/sudoers/mkdir_parents.c
plugins/sudoers/parse.c
plugins/sudoers/parse.h
plugins/sudoers/po/README

View File

@@ -153,9 +153,9 @@ LIBPARSESUDOERS_OBJS = alias.lo audit.lo base64.lo defaults.lo hexchar.lo \
SUDOERS_OBJS = $(AUTH_OBJS) boottime.lo check.lo editor.lo env.lo find_path.lo \
gc.lo goodpath.lo group_plugin.lo interfaces.lo iolog.lo \
iolog_path.lo locale.lo logging.lo logwrap.lo parse.lo \
policy.lo prompt.lo set_perms.lo sudo_nss.lo sudoers.lo \
timestamp.lo @SUDOERS_OBJS@
iolog_path.lo locale.lo logging.lo logwrap.lo mkdir_parents.lo \
parse.lo policy.lo prompt.lo set_perms.lo sudo_nss.lo \
sudoers.lo timestamp.lo @SUDOERS_OBJS@
VISUDO_OBJS = editor.o find_path.o goodpath.o locale.o sudo_printf.o visudo.o \
visudo_json.o
@@ -836,6 +836,16 @@ match_addr.lo: $(srcdir)/match_addr.c $(devdir)/def_data.h \
$(top_builddir)/config.h $(top_builddir)/pathnames.h
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/match_addr.c
match_addr.o: match_addr.lo
mkdir_parents.lo: $(srcdir)/mkdir_parents.c $(devdir)/def_data.h \
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
$(incdir)/sudo_conf.h $(incdir)/sudo_debug.h \
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
$(incdir)/sudo_plugin.h $(incdir)/sudo_queue.h \
$(incdir)/sudo_util.h $(srcdir)/defaults.h \
$(srcdir)/logging.h $(srcdir)/sudo_nss.h $(srcdir)/sudoers.h \
$(srcdir)/sudoers_debug.h $(top_builddir)/config.h \
$(top_builddir)/pathnames.h
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/mkdir_parents.c
net_ifs.o: $(top_srcdir)/src/net_ifs.c $(incdir)/compat/stdbool.h \
$(incdir)/sudo_compat.h $(incdir)/sudo_conf.h \
$(incdir)/sudo_debug.h $(incdir)/sudo_fatal.h \

View File

@@ -78,59 +78,6 @@ static mode_t iolog_dirmode = S_IRWXU;
/* sudoers_io is declared at the end of this file. */
extern __dso_public struct io_plugin sudoers_io;
/*
* Create path and any parent directories as needed.
*/
static bool
io_mkdir_parents(char *path, uid_t uid, gid_t *gidp, mode_t mode)
{
struct stat sb;
gid_t parent_gid;
char *slash = path;
bool rval = true;
debug_decl(io_mkdir_parents, SUDOERS_DEBUG_UTIL)
/* Create parent directories as needed. */
parent_gid = *gidp != (gid_t)-1 ? *gidp : 0;
while ((slash = strchr(slash + 1, '/')) != NULL) {
*slash = '\0';
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
"mkdir %s, mode 0%o, uid %d, gid %d", path, mode,
(int)uid, (int)parent_gid);
if (mkdir(path, mode) == 0) {
ignore_result(chown(path, uid, parent_gid));
} else {
if (errno != EEXIST) {
log_warning(SLOG_SEND_MAIL, N_("unable to mkdir %s"), path);
rval = false;
break;
}
/* Already exists, make sure it is a directory. */
if (stat(path, &sb) != 0) {
log_warning(SLOG_SEND_MAIL, N_("unable to mkdir %s"), path);
rval = false;
break;
}
if (!S_ISDIR(sb.st_mode)) {
log_warningx(SLOG_SEND_MAIL,
N_("%s exists but is not a directory (0%o)"),
path, (unsigned int) sb.st_mode);
rval = false;
break;
}
/* Inherit gid of parent dir for ownership. */
if (*gidp == (gid_t)-1)
parent_gid = sb.st_gid;
}
*slash = '/';
}
/* Return parent gid if none was specified by caller. */
if (rval && *gidp == (gid_t)-1)
*gidp = parent_gid;
debug_return_bool(rval);
}
/*
* Create directory and any parent directories as needed.
*/
@@ -148,8 +95,7 @@ io_mkdirs(char *path, uid_t uid, gid_t *gidp, mode_t mode, bool set_intermediate
if (S_ISDIR(sb.st_mode)) {
parent_gid = sb.st_gid;
} else {
log_warningx(SLOG_SEND_MAIL,
N_("%s exists but is not a directory (0%o)"),
sudo_warnx(U_("%s exists but is not a directory (0%o)"),
path, (unsigned int) sb.st_mode);
ok = false;
}
@@ -167,7 +113,7 @@ io_mkdirs(char *path, uid_t uid, gid_t *gidp, mode_t mode, bool set_intermediate
parent_gid = *gidp;
}
ok = io_mkdir_parents(path, parent_uid, &parent_gid, parent_mode);
ok = sudo_mkdir_parents(path, parent_uid, &parent_gid, parent_mode, false);
if (ok) {
/* Use group ID if specified, else parent gid. */
gid_t gid = *gidp != (gid_t)-1 ? *gidp : parent_gid;
@@ -176,7 +122,7 @@ io_mkdirs(char *path, uid_t uid, gid_t *gidp, mode_t mode, bool set_intermediate
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
"mkdir %s, mode 0%o", path, (unsigned int) mode);
if (mkdir(path, mode) != 0 && errno != EEXIST) {
log_warning(SLOG_SEND_MAIL, N_("unable to mkdir %s"), path);
sudo_warnx(U_("unable to mkdir %s"), path);
ok = false;
} else {
ignore_result(chown(path, uid, gid));
@@ -211,7 +157,7 @@ io_mkdtemp(char *path, uid_t uid, gid_t *gidp, mode_t mode, bool set_intermediat
parent_gid = *gidp;
}
ok = io_mkdir_parents(path, parent_uid, &parent_gid, parent_mode);
ok = sudo_mkdir_parents(path, parent_uid, &parent_gid, parent_mode, false);
if (ok) {
/* Use group ID if specified, else parent gid. */
gid_t gid = *gidp != (gid_t)-1 ? *gidp : parent_gid;
@@ -220,7 +166,7 @@ io_mkdtemp(char *path, uid_t uid, gid_t *gidp, mode_t mode, bool set_intermediat
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
"mkdtemp %s", path);
if (mkdtemp(path) == NULL) {
log_warning(SLOG_SEND_MAIL, N_("unable to mkdir %s"), path);
sudo_warn(U_("unable to mkdir %s"), path);
ok = false;
} else {
ignore_result(chown(path, uid, gid));

View File

@@ -0,0 +1,89 @@
/*
* Copyright (c) 2009-2016 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <config.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_STRING_H
# include <string.h>
#endif /* HAVE_STRING_H */
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif /* HAVE_STRINGS_H */
#include <unistd.h>
#include <errno.h>
#include <pwd.h>
#include <grp.h>
#include "sudoers.h"
/*
* Create any parent directories needed by path (but not path itself).
*/
bool
sudo_mkdir_parents(char *path, uid_t uid, gid_t *gidp, mode_t mode, bool quiet)
{
struct stat sb;
gid_t parent_gid;
char *slash = path;
bool rval = true;
debug_decl(sudo_mkdir_parents, SUDOERS_DEBUG_UTIL)
/* Create parent directories as needed. */
parent_gid = *gidp != (gid_t)-1 ? *gidp : 0;
while ((slash = strchr(slash + 1, '/')) != NULL) {
*slash = '\0';
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
"mkdir %s, mode 0%o, uid %d, gid %d", path, (unsigned int)mode,
(int)uid, (int)parent_gid);
if (mkdir(path, mode) == 0) {
ignore_result(chown(path, uid, parent_gid));
} else {
if (errno != EEXIST) {
if (!quiet)
sudo_warn(U_("unable to mkdir %s"), path);
rval = false;
break;
}
/* Already exists, make sure it is a directory. */
if (stat(path, &sb) != 0) {
if (!quiet)
sudo_warn(U_("unable to stat %s"), path);
rval = false;
break;
}
if (!S_ISDIR(sb.st_mode)) {
if (!quiet)
sudo_warnx(U_("%s exists but is not a directory (0%o)"),
path, (unsigned int) sb.st_mode);
rval = false;
break;
}
/* Inherit gid of parent dir for ownership. */
if (*gidp == (gid_t)-1)
parent_gid = sb.st_gid;
}
*slash = '/';
}
/* Return parent gid if none was specified by caller. */
if (rval && *gidp == (gid_t)-1)
*gidp = parent_gid;
debug_return_bool(rval);
}

View File

@@ -390,6 +390,9 @@ extern const char *path_plugin_dir;
char *resolve_editor(const char *ed, size_t edlen, int nfiles, char **files,
int *argc_out, char ***argv_out, char * const *whitelist);
/* mkdir_parents.c */
bool sudo_mkdir_parents(char *path, uid_t uid, gid_t *gidp, mode_t mode, bool quiet);
/* gc.c */
enum sudoers_gc_types {
GC_UNKNOWN,

View File

@@ -152,53 +152,24 @@ ts_find_record(int fd, struct timestamp_entry *key, struct timestamp_entry *entr
static bool
ts_mkdirs(char *path, uid_t owner, mode_t mode, mode_t parent_mode, bool quiet)
{
struct stat sb;
gid_t parent_gid = 0;
char *slash = path;
bool ret = false;
gid_t parent_gid = (gid_t)-1;
bool ret;
debug_decl(ts_mkdirs, SUDOERS_DEBUG_AUTH)
while ((slash = strchr(slash + 1, '/')) != NULL) {
*slash = '\0';
ret = sudo_mkdir_parents(path, owner, &parent_gid, parent_mode, quiet);
if (ret) {
/* Create final path component. */
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
"mkdir %s, mode 0%o", path, (unsigned int) parent_mode);
if (mkdir(path, parent_mode) == 0) {
ignore_result(chown(path, (uid_t)-1, parent_gid));
"mkdir %s, mode 0%o, uid %d, gid %d", path, mode,
(int)owner, (int)parent_gid);
if (mkdir(path, mode) != 0 && errno != EEXIST) {
if (!quiet)
sudo_warn(U_("unable to mkdir %s"), path);
ret = false;
} else {
if (errno != EEXIST) {
if (!quiet)
sudo_warn(U_("unable to mkdir %s"), path);
goto done;
}
/* Already exists, make sure it is a directory. */
if (stat(path, &sb) != 0) {
if (!quiet)
sudo_warn(U_("unable to stat %s"), path);
goto done;
}
if (!S_ISDIR(sb.st_mode)) {
if (!quiet) {
sudo_warnx(U_("%s exists but is not a directory (0%o)"),
path, (unsigned int) sb.st_mode);
}
goto done;
}
/* Inherit gid of parent dir for ownership. */
parent_gid = sb.st_gid;
ignore_result(chown(path, owner, parent_gid));
}
*slash = '/';
}
/* Create final path component. */
sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
"mkdir %s, mode 0%o", path, (unsigned int) mode);
if (mkdir(path, mode) != 0 && errno != EEXIST) {
if (!quiet)
sudo_warn(U_("unable to mkdir %s"), path);
goto done;
}
ignore_result(chown(path, owner, parent_gid));
ret = true;
done:
debug_return_bool(ret);
}