From bf62530acfca1c98f0b7ba0d2b2ec1d71d5b1457 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Sat, 29 Oct 2016 12:45:57 -0600 Subject: [PATCH] Move io_mkdir_parents() to its own file and use it in ts_mkdirs(). --- MANIFEST | 3 +- plugins/sudoers/Makefile.in | 16 ++++-- plugins/sudoers/iolog.c | 64 ++---------------------- plugins/sudoers/mkdir_parents.c | 89 +++++++++++++++++++++++++++++++++ plugins/sudoers/sudoers.h | 3 ++ plugins/sudoers/timestamp.c | 53 +++++--------------- 6 files changed, 124 insertions(+), 104 deletions(-) create mode 100644 plugins/sudoers/mkdir_parents.c diff --git a/MANIFEST b/MANIFEST index b84839a38..411a4cf21 100644 --- a/MANIFEST +++ b/MANIFEST @@ -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 diff --git a/plugins/sudoers/Makefile.in b/plugins/sudoers/Makefile.in index 6b1a3b15d..2a035a5b5 100644 --- a/plugins/sudoers/Makefile.in +++ b/plugins/sudoers/Makefile.in @@ -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 \ diff --git a/plugins/sudoers/iolog.c b/plugins/sudoers/iolog.c index d652fcfea..5ca346ab0 100644 --- a/plugins/sudoers/iolog.c +++ b/plugins/sudoers/iolog.c @@ -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)); diff --git a/plugins/sudoers/mkdir_parents.c b/plugins/sudoers/mkdir_parents.c new file mode 100644 index 000000000..e2a7ca1ac --- /dev/null +++ b/plugins/sudoers/mkdir_parents.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2009-2016 Todd C. Miller + * + * 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 + +#include +#include +#include +#include +#ifdef HAVE_STRING_H +# include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include +#endif /* HAVE_STRINGS_H */ +#include +#include +#include +#include + +#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); +} diff --git a/plugins/sudoers/sudoers.h b/plugins/sudoers/sudoers.h index 9baea0aee..73bf5cc88 100644 --- a/plugins/sudoers/sudoers.h +++ b/plugins/sudoers/sudoers.h @@ -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, diff --git a/plugins/sudoers/timestamp.c b/plugins/sudoers/timestamp.c index 20bb1e6e1..f2f6a9e05 100644 --- a/plugins/sudoers/timestamp.c +++ b/plugins/sudoers/timestamp.c @@ -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); } -- 2.40.0