diff options
-rw-r--r-- | ChangeLog.txt | 9 | ||||
-rwxr-xr-x | configure | 6 | ||||
-rw-r--r-- | pseudo.h | 2 | ||||
-rw-r--r-- | pseudo_client.c | 68 | ||||
-rw-r--r-- | pseudo_util.c | 4 |
5 files changed, 83 insertions, 6 deletions
diff --git a/ChangeLog.txt b/ChangeLog.txt index ba44239..940e781 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,3 +1,12 @@ +2015-01-14: + * (seebs) Merge pabigot's fix for a missing antimagic() in + etc_file code. + * (seebs) Make configure reject a "prefix" of the current + directory. It fails in strange ways and is easy to detect. + * (seebs) handle colon-separated lists in PSEUDO_PASSWD. + Derived in part from contribution from pabigot. + * (seebs) change allocation order in password file locking. + 2015-01-05: * (seebs) First try at handling trailing slashes in path names correctly. (Which is to say, a trailing slash on a file name @@ -2,7 +2,7 @@ # # configure, simulation of autoconf script, much simplified # -# Copyright (c) 2008-2013 Wind River Systems, Inc. +# Copyright (c) 2008-2014 Wind River Systems, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the Lesser GNU General Public License version 2.1 as @@ -69,6 +69,10 @@ do --) shift; break ;; --prefix=*) opt_prefix=${arg#--prefix=} + if [ "$(cd "$opt_prefix"; pwd)" == "$(pwd)" ]; then + echo >&2 "ERROR: Prefix is current directory. That doesn't work." + exit 1 + fi ;; --libdir=*) opt_libdir=${arg#--libdir=} @@ -86,7 +86,7 @@ extern int pseudo_logfile(char *defname); extern ssize_t pseudo_sys_path_max(void); extern ssize_t pseudo_path_max(void); #define PSEUDO_PWD_MAX 4096 -extern int pseudo_etc_file(const char *filename, char *realname, int flags, char *path[], int dircount); +extern int pseudo_etc_file(const char *filename, char *realname, int flags, const char **search_dirs, int dircount); extern void pseudo_stat32_from64(struct stat *, const struct stat64 *); extern void pseudo_stat64_from32(struct stat64 *, const struct stat *); diff --git a/pseudo_client.c b/pseudo_client.c index 8deaa1b..e4be07e 100644 --- a/pseudo_client.c +++ b/pseudo_client.c @@ -75,6 +75,8 @@ int pseudo_umask = 022; static char **fd_paths = NULL; static int nfds = 0; +static const char **passwd_paths = NULL; +static int npasswd_paths = 0; static int messages = 0; static struct timeval message_time = { .tv_sec = 0 }; static int pseudo_inited = 0; @@ -93,7 +95,7 @@ gid_t pseudo_egid; gid_t pseudo_sgid; gid_t pseudo_fgid; -#define PSEUDO_ETC_FILE(filename, realname, flags) pseudo_etc_file(filename, realname, flags, (char *[]) { pseudo_chroot, pseudo_passwd, PSEUDO_PASSWD_FALLBACK }, PSEUDO_PASSWD_FALLBACK ? 3 : 2) +#define PSEUDO_ETC_FILE(filename, realname, flags) pseudo_etc_file(filename, realname, flags, passwd_paths, npasswd_paths) /* helper function to make a directory, just like mkdir -p. * Can't use system() because the child shell would end up trying @@ -117,6 +119,61 @@ mkdir_p(char *path) { (void) mkdir(path, 0755); } +static int +build_passwd_paths(void) +{ + int np = 0; + + /* determine how many we need */ + if (pseudo_chroot) { + ++np; + } + if (pseudo_passwd) { + ++np; + for (int i = 0; pseudo_passwd[i]; ++i) + if (pseudo_passwd[i] == ':') + ++np; + } + if (PSEUDO_PASSWD_FALLBACK) { + ++np; + } + + npasswd_paths = np; + passwd_paths = malloc((np + 1) * sizeof(*passwd_paths)); + if (!passwd_paths) { + pseudo_diag("couldn't allocate storage for password paths.\n"); + exit(1); + } + np = 0; +#define SHOW_PATH pseudo_debug(PDBGF_CHROOT | PDBGF_VERBOSE, "passwd_paths[%d]: '%s'\n", (np - 1), (passwd_paths[np - 1])) + if (pseudo_chroot) { + passwd_paths[np++] = pseudo_chroot; + SHOW_PATH; + } + if (pseudo_passwd) { + passwd_paths[np++] = pseudo_passwd; + SHOW_PATH; + for (int i = 0; pseudo_passwd[i]; ++i) { + if (pseudo_passwd[i] == ':') { + pseudo_passwd[i] = '\0'; + passwd_paths[np++] = pseudo_passwd + i + 1; + SHOW_PATH; + } + } + } + if (PSEUDO_PASSWD_FALLBACK) { + passwd_paths[np++] = PSEUDO_PASSWD_FALLBACK; + SHOW_PATH; + } + passwd_paths[np] = NULL; + if (np != npasswd_paths) { + pseudo_diag("uh-oh, expected %d path(s) for passwd files, found %d.\n", + npasswd_paths, np); + } + + return np; +} + void pseudo_init_client(void) { char *env; @@ -325,9 +382,12 @@ pseudo_init_client(void) { env = pseudo_get_value("PSEUDO_PASSWD"); if (env) { + /* note: this means that pseudo_passwd is a + * string we're allowed to modify... */ pseudo_passwd = strdup(env); } free(env); + build_passwd_paths(); pseudo_inited = 1; } @@ -408,6 +468,7 @@ pseudo_file_open(char *name, int *fd, FILE **fp) { */ int pseudo_pwd_lck_open(void) { + pseudo_pwd_lck_close(); if (!pseudo_pwd_lck_name) { pseudo_pwd_lck_name = malloc(pseudo_path_max()); if (!pseudo_pwd_lck_name) { @@ -415,21 +476,24 @@ pseudo_pwd_lck_open(void) { return -1; } } - pseudo_pwd_lck_close(); + pseudo_antimagic(); pseudo_pwd_lck_fd = PSEUDO_ETC_FILE(".pwd.lock", pseudo_pwd_lck_name, O_RDWR | O_CREAT); + pseudo_magic(); return pseudo_pwd_lck_fd; } int pseudo_pwd_lck_close(void) { if (pseudo_pwd_lck_fd != -1) { + pseudo_antimagic(); close(pseudo_pwd_lck_fd); if (pseudo_pwd_lck_name) { unlink(pseudo_pwd_lck_name); free(pseudo_pwd_lck_name); pseudo_pwd_lck_name = 0; } + pseudo_magic(); pseudo_pwd_lck_fd = -1; return 0; } else { diff --git a/pseudo_util.c b/pseudo_util.c index 9ff2587..d15373b 100644 --- a/pseudo_util.c +++ b/pseudo_util.c @@ -1269,7 +1269,7 @@ FILE *pseudo_host_etc_group_file = &pseudo_fake_group_file; #endif int -pseudo_etc_file(const char *file, char *realname, int flags, char *search_dirs[], int dircount) { +pseudo_etc_file(const char *file, char *realname, int flags, const char **search_dirs, int dircount) { char filename[pseudo_path_max()]; int rc = -1; @@ -1285,7 +1285,7 @@ pseudo_etc_file(const char *file, char *realname, int flags, char *search_dirs[] return -1; } for (i = 0; i < dircount; ++i) { - char *s = search_dirs[i]; + const char *s = search_dirs[i]; if (!s) continue; #if PSEUDO_PORT_DARWIN |