The branch, master has been updated via 04f0c45475d s3:gencache: Allow to open gencache as read-only via a15bd5493b6 lib:util: Add test for path_expand_tilde() via 15457254be0 lib:util: Add path_expand_tilde() from 8b5e7644130 selftest: add python S4U2Self tests including unkeyed checksums
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 04f0c45475de383a0be4ca355ab9aa7784e61c27 Author: Andreas Schneider <a...@samba.org> Date: Wed May 6 17:10:51 2020 +0200 s3:gencache: Allow to open gencache as read-only This allows client tools to access the cache for ready-only operations as a normal user. Example: net ads status BUG: https://bugzilla.samba.org/show_bug.cgi?id=14370 Signed-off-by: Andreas Schneider <a...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> Autobuild-User(master): Andreas Schneider <a...@cryptomilk.org> Autobuild-Date(master): Fri May 15 14:40:32 UTC 2020 on sn-devel-184 commit a15bd5493b696c66c6803d8ca65bc13f1cfcdf0a Author: Andreas Schneider <a...@samba.org> Date: Mon May 11 12:50:11 2020 +0200 lib:util: Add test for path_expand_tilde() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14370 Signed-off-by: Andreas Schneider <a...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> commit 15457254be0ab1235c327bd305dfeee19b2ea7a1 Author: Andreas Schneider <a...@samba.org> Date: Thu May 7 12:25:24 2020 +0200 lib:util: Add path_expand_tilde() BUG: https://bugzilla.samba.org/show_bug.cgi?id=14370 Signed-off-by: Andreas Schneider <a...@samba.org> Reviewed-by: Stefan Metzmacher <me...@samba.org> ----------------------------------------------------------------------- Summary of changes: lib/util/tests/test_util_paths.c | 127 +++++++++++++++++++++++++++++++++++++++ lib/util/util_paths.c | 72 ++++++++++++++++++++++ lib/util/util_paths.h | 9 +++ lib/util/wscript_build | 6 ++ selftest/tests.py | 2 + source3/lib/gencache.c | 63 ++++++++++++++++++- 6 files changed, 276 insertions(+), 3 deletions(-) create mode 100644 lib/util/tests/test_util_paths.c Changeset truncated at 500 lines: diff --git a/lib/util/tests/test_util_paths.c b/lib/util/tests/test_util_paths.c new file mode 100644 index 00000000000..b89abf0aea1 --- /dev/null +++ b/lib/util/tests/test_util_paths.c @@ -0,0 +1,127 @@ +/* + * Unix SMB/CIFS implementation. + * + * Copyright (C) 2020 Andreas Schneider <a...@samba.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdarg.h> +#include <stddef.h> +#include <stdint.h> +#include <setjmp.h> +#include <cmocka.h> + +#include <talloc.h> + +#include "lib/replace/replace.h" +#include "lib/util/util_paths.c" + +static int setup(void **state) +{ + TALLOC_CTX *mem_ctx = talloc_new(NULL); + + assert_non_null(mem_ctx); + *state = mem_ctx; + + return 0; +} + +static int teardown(void **state) +{ + TALLOC_CTX *mem_ctx = *state; + TALLOC_FREE(mem_ctx); + + return 0; +} + +static void test_get_user_home_dir(void **state) +{ + TALLOC_CTX *mem_ctx = *state; + struct passwd *pwd = getpwuid(getuid()); + char *user; + + user = get_user_home_dir(mem_ctx); + assert_non_null(user); + assert_string_equal(user, pwd->pw_dir); + + TALLOC_FREE(user); +} + +static void test_path_expand_tilde(void **state) +{ + TALLOC_CTX *mem_ctx = *state; + char h[256] = {0}; + char *d = NULL; + const char *user = NULL; + char *home = NULL; + + user = getenv("USER"); + if (user == NULL){ + user = getenv("LOGNAME"); + } + + /* In certain CIs there no such variables */ + if (user == NULL) { + struct passwd *pw = getpwuid(getuid()); + if (pw){ + user = pw->pw_name; + } + } + + home = getenv("HOME"); + assert_non_null(home); + snprintf(h, sizeof(h), "%s/.cache", home); + + d = path_expand_tilde(mem_ctx, "~/.cache"); + assert_non_null(d); + assert_string_equal(d, h); + TALLOC_FREE(d); + + snprintf(h, sizeof(h), "%s/.cache/X~", home); + d = path_expand_tilde(mem_ctx, "~/.cache/X~"); + assert_string_equal(d, h); + TALLOC_FREE(d); + + d = path_expand_tilde(mem_ctx, "/guru/meditation"); + assert_non_null(d); + assert_string_equal(d, "/guru/meditation"); + TALLOC_FREE(d); + + snprintf(h, sizeof(h), "~%s/.cache", user); + d = path_expand_tilde(mem_ctx, h); + assert_non_null(d); + + snprintf(h, sizeof(h), "%s/.cache", home); + assert_string_equal(d, h); + TALLOC_FREE(d); +} + +int main(int argc, char *argv[]) +{ + int rc; + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_get_user_home_dir), + cmocka_unit_test(test_path_expand_tilde), + }; + + if (argc == 2) { + cmocka_set_test_filter(argv[1]); + } + cmocka_set_message_output(CM_OUTPUT_SUBUNIT); + + rc = cmocka_run_group_tests(tests, setup, teardown); + + return rc; +} diff --git a/lib/util/util_paths.c b/lib/util/util_paths.c index 0473557dfc6..c05246a7407 100644 --- a/lib/util/util_paths.c +++ b/lib/util/util_paths.c @@ -6,6 +6,7 @@ Copyright (C) Simo Sorce 2001 Copyright (C) Jim McDonough <j...@us.ibm.com> 2003 Copyright (C) James Peach 2006 + Copyright (c) 2020 Andreas Schneider <a...@samba.org> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,6 +25,7 @@ #include "includes.h" #include "dynconfig/dynconfig.h" #include "lib/util/util_paths.h" +#include "system/passwd.h" /** * @brief Returns an absolute path to a file in the Samba modules directory. @@ -62,3 +64,73 @@ const char *shlib_ext(void) return get_dyn_SHLIBEXT(); } +static char *get_user_home_dir(TALLOC_CTX *mem_ctx) +{ + struct passwd pwd = {0}; + struct passwd *pwdbuf = NULL; + char buf[NSS_BUFLEN_PASSWD] = {0}; + int rc; + + rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf); + if (rc != 0 || pwdbuf == NULL ) { + const char *szPath = getenv("HOME"); + if (szPath == NULL) { + return NULL; + } + snprintf(buf, sizeof(buf), "%s", szPath); + + return talloc_strdup(mem_ctx, buf); + } + + return talloc_strdup(mem_ctx, pwd.pw_dir); +} + +char *path_expand_tilde(TALLOC_CTX *mem_ctx, const char *d) +{ + char *h = NULL, *r = NULL; + const char *p = NULL; + struct stat sb = {0}; + int rc; + + if (d[0] != '~') { + return talloc_strdup(mem_ctx, d); + } + d++; + + /* handle ~user/path */ + p = strchr(d, '/'); + if (p != NULL && p > d) { + struct passwd *pw; + size_t s = p - d; + char u[128]; + + if (s >= sizeof(u)) { + return NULL; + } + memcpy(u, d, s); + u[s] = '\0'; + + pw = getpwnam(u); + if (pw == NULL) { + return NULL; + } + h = talloc_strdup(mem_ctx, pw->pw_dir); + } else { + p = d; + h = get_user_home_dir(mem_ctx); + } + if (h == NULL) { + return NULL; + } + + rc = stat(h, &sb); + if (rc != 0) { + TALLOC_FREE(h); + return NULL; + } + + r = talloc_asprintf(mem_ctx, "%s%s", h, p); + TALLOC_FREE(h); + + return r; +} diff --git a/lib/util/util_paths.h b/lib/util/util_paths.h index 80e8aaac6e9..cf34f691e5f 100644 --- a/lib/util/util_paths.h +++ b/lib/util/util_paths.h @@ -51,4 +51,13 @@ char *data_path(TALLOC_CTX *mem_ctx, const char *name); **/ const char *shlib_ext(void); +/** + * @brief Expand a directory starting with a tilde '~' + * + * @param[in] d The directory to expand. + * + * @return The expanded directory, NULL on error. + */ +char *path_expand_tilde(TALLOC_CTX *mem_ctx, const char *d); + #endif diff --git a/lib/util/wscript_build b/lib/util/wscript_build index fc760ff81aa..807c62636fd 100644 --- a/lib/util/wscript_build +++ b/lib/util/wscript_build @@ -299,3 +299,9 @@ else: deps='cmocka replace samba-util', local_include=False, for_selftest=True) + + bld.SAMBA_BINARY('test_util_paths', + source='tests/test_util_paths.c', + deps='cmocka replace talloc samba-util', + local_include=False, + for_selftest=True) diff --git a/selftest/tests.py b/selftest/tests.py index e5fc25f7cec..73932cd28be 100644 --- a/selftest/tests.py +++ b/selftest/tests.py @@ -393,6 +393,8 @@ plantestsuite("samba.unittests.bytearray", "none", [os.path.join(bindir(), "default/lib/util/test_bytearray")]) plantestsuite("samba.unittests.byteorder_verify", "none", [os.path.join(bindir(), "default/lib/util/test_byteorder_verify")]) +plantestsuite("samba.unittests.util_paths", "none", + [os.path.join(bindir(), "default/lib/util/test_util_paths")]) plantestsuite("samba.unittests.ntlm_check", "none", [os.path.join(bindir(), "default/libcli/auth/test_ntlm_check")]) plantestsuite("samba.unittests.gnutls", "none", diff --git a/source3/lib/gencache.c b/source3/lib/gencache.c index 9ad85bbf55f..896bf50cbd7 100644 --- a/source3/lib/gencache.c +++ b/source3/lib/gencache.c @@ -29,10 +29,13 @@ #include "tdb_wrap/tdb_wrap.h" #include "zlib.h" #include "lib/util/strv.h" +#include "lib/util/util_paths.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_TDB +#define GENCACHE_USER_PATH "~/.cache/samba/gencache.tdb" + static struct tdb_wrap *cache; /** @@ -68,6 +71,7 @@ static bool gencache_init(void) { char* cache_fname = NULL; int open_flags = O_RDWR|O_CREAT; + int tdb_flags = TDB_INCOMPATIBLE_HASH|TDB_NOSYNC|TDB_MUTEX_LOCKING; int hash_size; /* skip file open if it's already opened */ @@ -85,10 +89,63 @@ static bool gencache_init(void) DEBUG(5, ("Opening cache file at %s\n", cache_fname)); cache = tdb_wrap_open(NULL, cache_fname, hash_size, - TDB_INCOMPATIBLE_HASH| - TDB_NOSYNC| - TDB_MUTEX_LOCKING, + tdb_flags, open_flags, 0644); + /* + * Allow client tools to create a gencache in the home directory + * as a normal user. + */ + if (cache == NULL && errno == EACCES && geteuid() != 0) { + char *cache_dname = NULL, *tmp = NULL; + bool ok; + + TALLOC_FREE(cache_fname); + + cache_fname = path_expand_tilde(talloc_tos(), + GENCACHE_USER_PATH); + if (cache_fname == NULL) { + DBG_ERR("Failed to expand path: %s\n", + GENCACHE_USER_PATH); + return false; + } + + tmp = talloc_strdup(talloc_tos(), cache_fname); + if (tmp == NULL) { + DBG_ERR("No memory!\n"); + TALLOC_FREE(cache_fname); + return false; + } + + cache_dname = dirname(tmp); + if (cache_dname == NULL) { + DBG_ERR("Invalid path: %s\n", cache_fname); + TALLOC_FREE(tmp); + TALLOC_FREE(cache_fname); + return false; + } + + ok = directory_create_or_exist(cache_dname, 0700); + if (!ok) { + DBG_ERR("Failed to create directory: %s - %s\n", + cache_dname, strerror(errno)); + TALLOC_FREE(tmp); + TALLOC_FREE(cache_fname); + return false; + } + TALLOC_FREE(tmp); + + cache = tdb_wrap_open(NULL, + cache_fname, + hash_size, + tdb_flags, + open_flags, + 0644); + if (cache != NULL) { + DBG_INFO("Opening user cache file %s.\n", + cache_fname); + } + } + if (cache == NULL) { DEBUG(5, ("Opening %s failed: %s\n", cache_fname, strerror(errno))); -- Samba Shared Repository