URL: https://github.com/SSSD/sssd/pull/786 Author: alexey-tikhonov Title: #786: Issue 3964 Action: synchronized
To pull the PR as Git branch: git remote add ghsssd https://github.com/SSSD/sssd git fetch ghsssd pull/786/head:pr786 git checkout pr786
From 7670ff42a3ae64525b786ef3f72d7a890a48583b Mon Sep 17 00:00:00 2001 From: Alexey Tikhonov <atikh...@redhat.com> Date: Fri, 22 Mar 2019 15:33:22 +0100 Subject: [PATCH 1/4] Util: added facility to load nss lib syms Factored out (from proxy provider code) utility to load NSS symbols from shared library. Related: https://pagure.io/SSSD/sssd/issue/3964 --- Makefile.am | 2 + src/providers/proxy/proxy.h | 54 +--------- src/providers/proxy/proxy_init.c | 163 ++++++++++++------------------- src/util/nss_dl_load.c | 107 ++++++++++++++++++++ src/util/nss_dl_load.h | 82 ++++++++++++++++ 5 files changed, 257 insertions(+), 151 deletions(-) create mode 100644 src/util/nss_dl_load.c create mode 100644 src/util/nss_dl_load.h diff --git a/Makefile.am b/Makefile.am index fdd0215551..bd446e96b5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -686,6 +686,7 @@ dist_noinst_HEADERS = \ src/util/tev_curl.h \ src/util/secrets/secrets.h \ src/util/secrets/sec_pvt.h \ + src/util/nss_dl_load.h \ src/monitor/monitor.h \ src/responder/common/responder.h \ src/responder/common/responder_packet.h \ @@ -4262,6 +4263,7 @@ libsss_proxy_la_SOURCES = \ src/providers/proxy/proxy_netgroup.c \ src/providers/proxy/proxy_services.c \ src/providers/proxy/proxy_auth.c \ + src//util/nss_dl_load.c \ $(NULL) libsss_proxy_la_CFLAGS = \ $(AM_CFLAGS) diff --git a/src/providers/proxy/proxy.h b/src/providers/proxy/proxy.h index 56ad5d4512..1353eb8fab 100644 --- a/src/providers/proxy/proxy.h +++ b/src/providers/proxy/proxy.h @@ -25,11 +25,7 @@ #ifndef __PROXY_H__ #define __PROXY_H__ -#include <nss.h> #include <errno.h> -#include <pwd.h> -#include <grp.h> -#include <dlfcn.h> #include <sys/types.h> #include <sys/wait.h> @@ -37,59 +33,14 @@ #include <security/pam_modules.h> #include "util/util.h" +#include "util/nss_dl_load.h" #include "providers/backend.h" #include "db/sysdb.h" -#include "sss_client/nss_compat.h" #include <dhash.h> #include "sss_iface/sss_iface_async.h" #define PROXY_CHILD_PATH "/org/freedesktop/sssd/proxychild" -struct proxy_nss_ops { - enum nss_status (*getpwnam_r)(const char *name, struct passwd *result, - char *buffer, size_t buflen, int *errnop); - enum nss_status (*getpwuid_r)(uid_t uid, struct passwd *result, - char *buffer, size_t buflen, int *errnop); - enum nss_status (*setpwent)(void); - enum nss_status (*getpwent_r)(struct passwd *result, - char *buffer, size_t buflen, int *errnop); - enum nss_status (*endpwent)(void); - - enum nss_status (*getgrnam_r)(const char *name, struct group *result, - char *buffer, size_t buflen, int *errnop); - enum nss_status (*getgrgid_r)(gid_t gid, struct group *result, - char *buffer, size_t buflen, int *errnop); - enum nss_status (*setgrent)(void); - enum nss_status (*getgrent_r)(struct group *result, - char *buffer, size_t buflen, int *errnop); - enum nss_status (*endgrent)(void); - enum nss_status (*initgroups_dyn)(const char *user, gid_t group, - long int *start, long int *size, - gid_t **groups, long int limit, - int *errnop); - enum nss_status (*setnetgrent)(const char *netgroup, - struct __netgrent *result); - enum nss_status (*getnetgrent_r)(struct __netgrent *result, char *buffer, - size_t buflen, int *errnop); - enum nss_status (*endnetgrent)(struct __netgrent *result); - - /* Services */ - enum nss_status (*getservbyname_r)(const char *name, - const char *protocol, - struct servent *result, - char *buffer, size_t buflen, - int *errnop); - enum nss_status (*getservbyport_r)(int port, const char *protocol, - struct servent *result, - char *buffer, size_t buflen, - int *errnop); - enum nss_status (*setservent)(void); - enum nss_status (*getservent_r)(struct servent *result, - char *buffer, size_t buflen, - int *errnop); - enum nss_status (*endservent)(void); -}; - struct authtok_conv { struct sss_auth_token *authtok; struct sss_auth_token *newauthtok; @@ -100,8 +51,7 @@ struct authtok_conv { struct proxy_id_ctx { struct be_ctx *be; bool fast_alias; - struct proxy_nss_ops ops; - void *handle; + struct sss_nss_ops ops; }; struct proxy_auth_ctx { diff --git a/src/providers/proxy/proxy_init.c b/src/providers/proxy/proxy_init.c index 32343a3bf5..c7c67ff6e5 100644 --- a/src/providers/proxy/proxy_init.c +++ b/src/providers/proxy/proxy_init.c @@ -27,44 +27,15 @@ #include "util/sss_format.h" #include "providers/proxy/proxy.h" -#define NSS_FN_NAME "_nss_%s_%s" - #define OPT_MAX_CHILDREN_DEFAULT 10 -#define ERROR_INITGR "The '%s' library does not provides the " \ - "_nss_XXX_initgroups_dyn function!\n" \ - "initgroups will be slow as it will require " \ - "full groups enumeration!\n" -#define ERROR_NETGR "The '%s' library does not support netgroups.\n" -#define ERROR_SERV "The '%s' library does not support services.\n" - -static void *proxy_dlsym(void *handle, - const char *name, - const char *libname) -{ - char *funcname; - void *funcptr; - - funcname = talloc_asprintf(NULL, NSS_FN_NAME, libname, name); - if (funcname == NULL) { - return NULL; - } - - funcptr = dlsym(handle, funcname); - talloc_free(funcname); - - return funcptr; -} - static errno_t proxy_id_conf(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, char **_libname, - char **_libpath, bool *_fast_alias) { TALLOC_CTX *tmp_ctx; char *libname; - char *libpath; bool fast_alias; errno_t ret; @@ -94,15 +65,7 @@ static errno_t proxy_id_conf(TALLOC_CTX *mem_ctx, goto done; } - libpath = talloc_asprintf(tmp_ctx, "libnss_%s.so.2", libname); - if (libpath == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf() failed\n"); - ret = ENOMEM; - goto done; - } - *_libname = talloc_steal(mem_ctx, libname); - *_libpath = talloc_steal(mem_ctx, libpath); *_fast_alias = fast_alias; ret = EOK; @@ -113,57 +76,6 @@ static errno_t proxy_id_conf(TALLOC_CTX *mem_ctx, return ret; } -static errno_t proxy_id_load_symbols(struct proxy_nss_ops *ops, - const char *libname, - void *handle) -{ - int i; - struct {void **dest; - const char *name; - const char *custom_error; - bool is_fatal; - } symbols[] = { - {(void**)&ops->getpwnam_r, "getpwnam_r", NULL, true}, - {(void**)&ops->getpwuid_r, "getpwuid_r", NULL, true}, - {(void**)&ops->setpwent, "setpwent", NULL, true}, - {(void**)&ops->getpwent_r, "getpwent_r", NULL, true}, - {(void**)&ops->endpwent, "endpwent", NULL, true}, - {(void**)&ops->getgrnam_r, "getgrnam_r", NULL, true}, - {(void**)&ops->getgrgid_r, "getgrgid_r", NULL, true}, - {(void**)&ops->setgrent, "setgrent", NULL, true}, - {(void**)&ops->getgrent_r, "getgrent_r", NULL, true}, - {(void**)&ops->endgrent, "endgrent", NULL, true}, - {(void**)&ops->initgroups_dyn, "initgroups_dyn", ERROR_INITGR, false}, - {(void**)&ops->setnetgrent, "setnetgrent", ERROR_NETGR, false}, - {(void**)&ops->getnetgrent_r, "getnetgrent_r", ERROR_NETGR, false}, - {(void**)&ops->endnetgrent, "endnetgrent", ERROR_NETGR, false}, - {(void**)&ops->getservbyname_r, "getservbyname_r", ERROR_SERV, false}, - {(void**)&ops->getservbyport_r, "getservbyport_r", ERROR_SERV, false}, - {(void**)&ops->setservent, "setservent", ERROR_SERV, false}, - {(void**)&ops->getservent_r, "getservent_r", ERROR_SERV, false}, - {(void**)&ops->endservent, "endservent", ERROR_SERV, false}, - {NULL, NULL, NULL, false} - }; - - for (i = 0; symbols[i].dest != NULL; i++) { - *symbols[i].dest = proxy_dlsym(handle, symbols[i].name, libname); - if (*symbols[i].dest == NULL) { - DEBUG(SSSDBG_FATAL_FAILURE, "Failed to load _nss_%s_%s, " - "error: %s.\n", libname, symbols[i].name, dlerror()); - - if (symbols[i].custom_error != NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, symbols[i].custom_error, libname); - } - - if (symbols[i].is_fatal) { - return ELIBBAD; - } - } - } - - return EOK; -} - static errno_t proxy_auth_conf(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, char **_pam_target) @@ -286,6 +198,68 @@ errno_t sssm_proxy_init(TALLOC_CTX *mem_ctx, return EOK; } + +#define ERROR_INITGR "The '%s' library does not provides the " \ + "_nss_XXX_initgroups_dyn function!\n" \ + "initgroups will be slow as it will require " \ + "full groups enumeration!\n" +#define ERROR_NETGR "The '%s' library does not support netgroups.\n" +#define ERROR_SERV "The '%s' library does not support services.\n" + +static errno_t proxy_load_nss_symbols(struct sss_nss_ops *ops, + const char *libname) +{ + errno_t ret; + size_t i; + + ret = sss_load_nss_symbols(ops, libname); + if (ret != EOK) { + return ret; + } + + struct { + void *fptr; + const char* custom_error; + } optional_syms[] = { + {(void*)ops->initgroups_dyn, ERROR_INITGR}, + {(void*)ops->setnetgrent, ERROR_NETGR}, + {(void*)ops->getnetgrent_r, ERROR_NETGR}, + {(void*)ops->endnetgrent, ERROR_NETGR}, + {(void*)ops->getservbyname_r, ERROR_SERV}, + {(void*)ops->getservbyport_r, ERROR_SERV}, + {(void*)ops->setservent, ERROR_SERV}, + {(void*)ops->getservent_r, ERROR_SERV}, + {(void*)ops->endservent, ERROR_SERV}, + }; + for (i = 0; i < sizeof(optional_syms) / sizeof(optional_syms[0]); ++i) { + if (!optional_syms[i].fptr) { + DEBUG(SSSDBG_CRIT_FAILURE, optional_syms[i].custom_error, libname); + } + } + + void *mandatory_syms[] = { + (void*)ops->getpwnam_r, + (void*)ops->getpwuid_r, + (void*)ops->setpwent, + (void*)ops->getpwent_r, + (void*)ops->endpwent, + (void*)ops->getgrnam_r, + (void*)ops->getgrgid_r, + (void*)ops->setgrent, + (void*)ops->getgrent_r, + (void*)ops->endgrent, + }; + for (i = 0; i < sizeof(mandatory_syms)/sizeof(mandatory_syms[0]); ++i) { + if (!mandatory_syms[i]) { + DEBUG(SSSDBG_CRIT_FAILURE, "The '%s' library does not provide mandatory function", libname); + return ELIBBAD; + } + } + + return EOK; +} + + errno_t sssm_proxy_id_init(TALLOC_CTX *mem_ctx, struct be_ctx *be_ctx, void *module_data, @@ -293,7 +267,6 @@ errno_t sssm_proxy_id_init(TALLOC_CTX *mem_ctx, { struct proxy_id_ctx *ctx; char *libname; - char *libpath; errno_t ret; ctx = talloc_zero(mem_ctx, struct proxy_id_ctx); @@ -303,20 +276,12 @@ errno_t sssm_proxy_id_init(TALLOC_CTX *mem_ctx, ctx->be = be_ctx; - ret = proxy_id_conf(ctx, be_ctx, &libname, &libpath, &ctx->fast_alias); + ret = proxy_id_conf(ctx, be_ctx, &libname, &ctx->fast_alias); if (ret != EOK) { goto done; } - ctx->handle = dlopen(libpath, RTLD_NOW); - if (ctx->handle == NULL) { - DEBUG(SSSDBG_FATAL_FAILURE, "Unable to load %s module, " - "error: %s\n", libpath, dlerror()); - ret = ELIBACC; - goto done; - } - - ret = proxy_id_load_symbols(&ctx->ops, libname, ctx->handle); + ret = proxy_load_nss_symbols(&ctx->ops, libname); if (ret != EOK) { DEBUG(SSSDBG_FATAL_FAILURE, "Unable to load NSS symbols [%d]: %s\n", ret, sss_strerror(ret)); diff --git a/src/util/nss_dl_load.c b/src/util/nss_dl_load.c new file mode 100644 index 0000000000..e6edc1699a --- /dev/null +++ b/src/util/nss_dl_load.c @@ -0,0 +1,107 @@ +/* + Copyright (C) 2019 Red Hat + + 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 <dlfcn.h> +#include <talloc.h> +#include <stdbool.h> +#include <errno.h> + +#include "util/util_errors.h" +#include "util/debug.h" +#include "nss_dl_load.h" + + +#define NSS_FN_NAME "_nss_%s_%s" + + +static void *proxy_dlsym(void *handle, + const char *name, + const char *libname) +{ + char *funcname; + void *funcptr; + + funcname = talloc_asprintf(NULL, NSS_FN_NAME, libname, name); + if (funcname == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf() failed\n"); + return NULL; + } + + funcptr = dlsym(handle, funcname); + talloc_free(funcname); + + return funcptr; +} + + +errno_t sss_load_nss_symbols(struct sss_nss_ops *ops, const char *libname) +{ + char *libpath; + size_t i; + struct { + void **dest; + const char *name; + } symbols[] = { + {(void**)&ops->getpwnam_r, "getpwnam_r"}, + {(void**)&ops->getpwuid_r, "getpwuid_r"}, + {(void**)&ops->setpwent, "setpwent"}, + {(void**)&ops->getpwent_r, "getpwent_r"}, + {(void**)&ops->endpwent, "endpwent"}, + {(void**)&ops->getgrnam_r, "getgrnam_r"}, + {(void**)&ops->getgrgid_r, "getgrgid_r"}, + {(void**)&ops->setgrent, "setgrent"}, + {(void**)&ops->getgrent_r, "getgrent_r"}, + {(void**)&ops->endgrent, "endgrent"}, + {(void**)&ops->initgroups_dyn, "initgroups_dyn"}, + {(void**)&ops->setnetgrent, "setnetgrent"}, + {(void**)&ops->getnetgrent_r, "getnetgrent_r"}, + {(void**)&ops->endnetgrent, "endnetgrent"}, + {(void**)&ops->getservbyname_r, "getservbyname_r"}, + {(void**)&ops->getservbyport_r, "getservbyport_r"}, + {(void**)&ops->setservent, "setservent"}, + {(void**)&ops->getservent_r, "getservent_r"}, + {(void**)&ops->endservent, "endservent"} + }; + + libpath = talloc_asprintf(NULL, "libnss_%s.so.2", libname); + if (libpath == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf() failed\n"); + return ENOMEM; + } + + ops->dl_handle = dlopen(libpath, RTLD_NOW); + if (ops->dl_handle == NULL) { + DEBUG(SSSDBG_FATAL_FAILURE, "Unable to load %s module, " + "error: %s\n", libpath, dlerror()); + talloc_free(libpath); + return ELIBACC; + } + talloc_free(libpath); + + for (i = 0; i < sizeof(symbols)/sizeof(symbols[0]); ++i) { + *symbols[i].dest = proxy_dlsym(ops->dl_handle, symbols[i].name, + libname); + if (*symbols[i].dest == NULL) { + DEBUG(SSSDBG_FATAL_FAILURE, "Failed to load "NSS_FN_NAME", " + "error: %s.\n", libname, symbols[i].name, dlerror()); + } + } + + return EOK; +} + diff --git a/src/util/nss_dl_load.h b/src/util/nss_dl_load.h new file mode 100644 index 0000000000..5d014202f1 --- /dev/null +++ b/src/util/nss_dl_load.h @@ -0,0 +1,82 @@ +/* + Copyright (C) 2019 Red Hat + + 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/>. +*/ + +#ifndef __SSSD_NSS_DL_LOAD_H__ +#define __SSSD_NSS_DL_LOAD_H__ + + +#include <nss.h> +#include <pwd.h> +#include <grp.h> +#include <netdb.h> +#include "util/util_errors.h" +#include "sss_client/nss_compat.h" + + +struct sss_nss_ops { + enum nss_status (*getpwnam_r)(const char *name, struct passwd *result, + char *buffer, size_t buflen, int *errnop); + enum nss_status (*getpwuid_r)(uid_t uid, struct passwd *result, + char *buffer, size_t buflen, int *errnop); + enum nss_status (*setpwent)(void); + enum nss_status (*getpwent_r)(struct passwd *result, + char *buffer, size_t buflen, int *errnop); + enum nss_status (*endpwent)(void); + + enum nss_status (*getgrnam_r)(const char *name, struct group *result, + char *buffer, size_t buflen, int *errnop); + enum nss_status (*getgrgid_r)(gid_t gid, struct group *result, + char *buffer, size_t buflen, int *errnop); + enum nss_status (*setgrent)(void); + enum nss_status (*getgrent_r)(struct group *result, + char *buffer, size_t buflen, int *errnop); + enum nss_status (*endgrent)(void); + enum nss_status (*initgroups_dyn)(const char *user, gid_t group, + long int *start, long int *size, + gid_t **groups, long int limit, + int *errnop); + enum nss_status (*setnetgrent)(const char *netgroup, + struct __netgrent *result); + enum nss_status (*getnetgrent_r)(struct __netgrent *result, char *buffer, + size_t buflen, int *errnop); + enum nss_status (*endnetgrent)(struct __netgrent *result); + + /* Services */ + enum nss_status (*getservbyname_r)(const char *name, + const char *protocol, + struct servent *result, + char *buffer, size_t buflen, + int *errnop); + enum nss_status (*getservbyport_r)(int port, const char *protocol, + struct servent *result, + char *buffer, size_t buflen, + int *errnop); + enum nss_status (*setservent)(void); + enum nss_status (*getservent_r)(struct servent *result, + char *buffer, size_t buflen, + int *errnop); + enum nss_status (*endservent)(void); + + void *dl_handle; +}; + + +errno_t sss_load_nss_symbols(struct sss_nss_ops *ops, const char *libname); + + +#endif /* __SSSD_NSS_DL_LOAD_H__ */ + From e2b88625c4fc0605a1d2643cc584cd45614957e6 Mon Sep 17 00:00:00 2001 From: Alexey Tikhonov <atikh...@redhat.com> Date: Fri, 22 Mar 2019 16:06:49 +0100 Subject: [PATCH 2/4] responder/negcache: avoid calling nsswitch NSS API Changed "negcache_files.c::is_*_local_by_*()" to use functions from "libnss_files" directly to check users (instead of calling glibc NSS API). Changed affected tests to avoid using NSS-wrapper and to use real local user&group (otherwise tests were broken). Resolves: https://pagure.io/SSSD/sssd/issue/3964 --- Makefile.am | 20 +++++ src/responder/common/negcache.c | 53 ++++++++++-- src/responder/common/negcache_files.c | 74 ++++++++--------- src/responder/common/negcache_files.h | 12 ++- src/tests/cwrap/Makefile.am | 4 + src/tests/cwrap/test_negcache.c | 83 +++++++++++++------ src/tests/intg/test_ldap.py | 114 ++++++++++++-------------- 7 files changed, 225 insertions(+), 135 deletions(-) diff --git a/Makefile.am b/Makefile.am index bd446e96b5..747187aa83 100644 --- a/Makefile.am +++ b/Makefile.am @@ -565,6 +565,7 @@ SSSD_RESPONDER_IFACE_OBJ = \ SSSD_RESPONDER_OBJ = \ src/responder/common/negcache_files.c \ src/responder/common/negcache.c \ + src/util/nss_dl_load.c \ src/responder/common/responder_cmd.c \ src/responder/common/responder_common.c \ src/responder/common/responder_dp.c \ @@ -1569,6 +1570,7 @@ sssd_nss_SOURCES = \ src/responder/nss/nsssrv_mmap_cache.c \ $(SSSD_RESPONDER_OBJ) sssd_nss_LDADD = \ + $(LIBADD_DL) \ $(TDB_LIBS) \ $(SSSD_LIBS) \ libsss_idmap.la \ @@ -1588,6 +1590,7 @@ sssd_pam_SOURCES = \ src/responder/pam/pam_helpers.c \ $(SSSD_RESPONDER_OBJ) sssd_pam_LDADD = \ + $(LIBADD_DL) \ $(TDB_LIBS) \ $(SSSD_LIBS) \ $(SELINUX_LIBS) \ @@ -1608,6 +1611,7 @@ sssd_sudo_SOURCES = \ src/responder/sudo/sudosrv_dp.c \ $(SSSD_RESPONDER_OBJ) sssd_sudo_LDADD = \ + $(LIBADD_DL) \ $(SSSD_LIBS) \ $(SYSTEMD_DAEMON_LIBS) \ $(SSSD_INTERNAL_LTLIBS) \ @@ -1622,6 +1626,7 @@ sssd_autofs_SOURCES = \ src/responder/autofs/autofssrv_cmd.c \ $(SSSD_RESPONDER_OBJ) sssd_autofs_LDADD = \ + $(LIBADD_DL) \ $(SSSD_LIBS) \ $(SYSTEMD_DAEMON_LIBS) \ $(SSSD_INTERNAL_LTLIBS) \ @@ -1640,6 +1645,7 @@ sssd_ssh_SOURCES = \ $(SSSD_RESPONDER_OBJ) \ $(NULL) sssd_ssh_LDADD = \ + $(LIBADD_DL) \ $(SSSD_LIBS) \ $(SSSD_INTERNAL_LTLIBS) \ $(SYSTEMD_DAEMON_LIBS) \ @@ -1658,6 +1664,7 @@ sssd_pac_CFLAGS = \ $(AM_CFLAGS) \ $(NDR_KRB5PAC_CFLAGS) sssd_pac_LDADD = \ + $(LIBADD_DL) \ $(NDR_KRB5PAC_LIBS) \ $(TDB_LIBS) \ $(SSSD_LIBS) \ @@ -1737,6 +1744,7 @@ sssd_ifp_SOURCES = \ sssd_ifp_CFLAGS = \ $(AM_CFLAGS) sssd_ifp_LDADD = \ + $(LIBADD_DL) \ $(SSSD_LIBS) \ $(SYSTEMD_DAEMON_LIBS) \ $(SSSD_INTERNAL_LTLIBS) \ @@ -1785,6 +1793,7 @@ sssd_secrets_SOURCES = \ $(SSSD_RESPONDER_OBJ) \ $(NULL) sssd_secrets_LDADD = \ + $(LIBADD_DL) \ $(HTTP_PARSER_LIBS) \ $(JANSSON_LIBS) \ $(TDB_LIBS) \ @@ -1821,6 +1830,7 @@ sssd_kcm_CFLAGS = \ $(JANSSON_CFLAGS) \ $(NULL) sssd_kcm_LDADD = \ + $(LIBADD_DL) \ $(KRB5_LIBS) \ $(JANSSON_LIBS) \ $(SSSD_LIBS) \ @@ -2529,6 +2539,7 @@ responder_socket_access_tests_SOURCES = \ src/tests/responder_socket_access-tests.c \ src/responder/common/negcache_files.c \ src/responder/common/negcache.c \ + src/util/nss_dl_load.c \ src/responder/common/responder_common.c \ src/responder/common/responder_packet.c \ src/responder/common/responder_cmd.c \ @@ -2540,6 +2551,7 @@ responder_socket_access_tests_CFLAGS = \ $(AM_CFLAGS) \ $(CHECK_CFLAGS) responder_socket_access_tests_LDADD = \ + $(LIBADD_DL) \ $(CHECK_LIBS) \ $(SSSD_LIBS) \ $(SSSD_INTERNAL_LTLIBS) \ @@ -2632,6 +2644,7 @@ TEST_MOCK_RESP_OBJ = \ src/responder/common/responder_cmd.c \ src/responder/common/negcache_files.c \ src/responder/common/negcache.c \ + src/util/nss_dl_load.c \ src/responder/common/responder_common.c \ src/responder/common/responder_utils.c \ src/util/session_recording.c \ @@ -2681,6 +2694,7 @@ nss_srv_tests_LDFLAGS = \ -Wl,-wrap,sss_cmd_send_empty \ -Wl,-wrap,sss_cmd_done nss_srv_tests_LDADD = \ + $(LIBADD_DL) \ $(CMOCKA_LIBS) \ $(SSSD_LIBS) \ $(SSSD_INTERNAL_LTLIBS) \ @@ -2719,6 +2733,7 @@ pam_srv_tests_LDFLAGS = \ -Wl,-wrap,pam_dp_send_req \ $(NULL) pam_srv_tests_LDADD = \ + $(LIBADD_DL) \ $(CMOCKA_LIBS) \ $(PAM_LIBS) \ $(SSSD_LIBS) \ @@ -2757,6 +2772,7 @@ ssh_srv_tests_LDFLAGS = \ -Wl,-wrap,ssh_dp_send_req \ $(NULL) ssh_srv_tests_LDADD = \ + $(LIBADD_DL) \ $(CMOCKA_LIBS) \ $(SSSD_LIBS) \ $(SSSD_INTERNAL_LTLIBS) \ @@ -2778,6 +2794,7 @@ responder_get_domains_tests_LDFLAGS = \ -Wl,-wrap,sss_parse_name_for_domains \ -Wl,-wrap,sss_ncache_reset_repopulate_permanent responder_get_domains_tests_LDADD = \ + $(LIBADD_DL) \ $(CMOCKA_LIBS) \ $(SSSD_LIBS) \ $(SSSD_INTERNAL_LTLIBS) \ @@ -2839,6 +2856,7 @@ test_negcache_CFLAGS = \ $(TALLOC_CFLAGS) \ $(DHASH_CFLAGS) test_negcache_LDADD = \ + $(LIBADD_DL) \ $(CMOCKA_LIBS) \ $(SSSD_LIBS) \ $(SYSTEMD_DAEMON_LIBS) \ @@ -3199,6 +3217,7 @@ ifp_tests_SOURCES = \ ifp_tests_CFLAGS = \ $(AM_CFLAGS) ifp_tests_LDADD = \ + $(LIBADD_DL) \ $(CMOCKA_LIBS) \ $(SSSD_LIBS) \ $(SSSD_INTERNAL_LTLIBS) \ @@ -3458,6 +3477,7 @@ responder_cache_req_tests_LDFLAGS = \ -Wl,-wrap,sss_dp_get_account_send \ $(NULL) responder_cache_req_tests_LDADD = \ + $(LIBADD_DL) \ $(CMOCKA_LIBS) \ $(SSSD_LIBS) \ $(SSSD_INTERNAL_LTLIBS) \ diff --git a/src/responder/common/negcache.c b/src/responder/common/negcache.c index f9034d1647..44bea358d4 100644 --- a/src/responder/common/negcache.c +++ b/src/responder/common/negcache.c @@ -19,14 +19,16 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <fcntl.h> +#include <time.h> +#include "tdb.h" #include "util/util.h" +#include "util/nss_dl_load.h" #include "confdb/confdb.h" #include "responder/common/negcache_files.h" #include "responder/common/responder.h" #include "responder/common/negcache.h" -#include <fcntl.h> -#include <time.h> -#include "tdb.h" + #define NC_ENTRY_PREFIX "NCE/" #define NC_USER_PREFIX NC_ENTRY_PREFIX"USER" @@ -44,6 +46,7 @@ struct sss_nc_ctx { struct tdb_context *tdb; uint32_t timeout; uint32_t local_timeout; + struct sss_nss_ops ops; }; typedef int (*ncache_set_byname_fn_t)(struct sss_nc_ctx *, bool, @@ -63,14 +66,50 @@ static int string_to_tdb_data(char *str, TDB_DATA *ret) return EOK; } +static errno_t ncache_load_nss_symbols(struct sss_nss_ops *ops) +{ + errno_t ret; + size_t i; + + ret = sss_load_nss_symbols(ops, "files"); + if (ret != EOK) + { + return ret; + } + + void *mandatory_syms[] = { + (void*)ops->getpwnam_r, + (void*)ops->getpwuid_r, + (void*)ops->getgrnam_r, + (void*)ops->getgrgid_r + }; + for (i = 0; i < sizeof(mandatory_syms)/sizeof(mandatory_syms[0]); ++i) { + if (!mandatory_syms[i]) { + DEBUG(SSSDBG_CRIT_FAILURE, "The 'files' library does not provide mandatory function"); + return ELIBBAD; + } + } + + return EOK; +} + int sss_ncache_init(TALLOC_CTX *memctx, uint32_t timeout, uint32_t local_timeout, struct sss_nc_ctx **_ctx) { + errno_t ret; struct sss_nc_ctx *ctx; ctx = talloc_zero(memctx, struct sss_nc_ctx); if (!ctx) return ENOMEM; + ret = ncache_load_nss_symbols(&ctx->ops); + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, "Unable to load NSS symbols [%d]: %s\n", + ret, sss_strerror(ret)); + talloc_free(ctx); + return ret; + } + errno = 0; /* open a memory only tdb with default hash size */ ctx->tdb = tdb_open("memcache", 0, TDB_INTERNAL, O_RDWR|O_CREAT, 0); @@ -488,7 +527,7 @@ static int sss_ncache_set_user_int(struct sss_nc_ctx *ctx, bool permanent, if (!str) return ENOMEM; if ((!permanent) && (ctx->local_timeout > 0)) { - use_local_negative = is_user_local_by_name(name); + use_local_negative = is_user_local_by_name(&ctx->ops, name); } ret = sss_ncache_set_str(ctx, str, permanent, use_local_negative); @@ -509,7 +548,7 @@ static int sss_ncache_set_group_int(struct sss_nc_ctx *ctx, bool permanent, if (!str) return ENOMEM; if ((!permanent) && (ctx->local_timeout > 0)) { - use_local_negative = is_group_local_by_name(name); + use_local_negative = is_group_local_by_name(&ctx->ops, name); } ret = sss_ncache_set_str(ctx, str, permanent, use_local_negative); @@ -606,7 +645,7 @@ int sss_ncache_set_uid(struct sss_nc_ctx *ctx, bool permanent, if (!str) return ENOMEM; if ((!permanent) && (ctx->local_timeout > 0)) { - use_local_negative = is_user_local_by_uid(uid); + use_local_negative = is_user_local_by_uid(&ctx->ops, uid); } ret = sss_ncache_set_str(ctx, str, permanent, use_local_negative); @@ -630,7 +669,7 @@ int sss_ncache_set_gid(struct sss_nc_ctx *ctx, bool permanent, if (!str) return ENOMEM; if ((!permanent) && (ctx->local_timeout > 0)) { - use_local_negative = is_group_local_by_gid(gid); + use_local_negative = is_group_local_by_gid(&ctx->ops, gid); } ret = sss_ncache_set_str(ctx, str, permanent, use_local_negative); diff --git a/src/responder/common/negcache_files.c b/src/responder/common/negcache_files.c index 4256186d93..85a7065a48 100644 --- a/src/responder/common/negcache_files.c +++ b/src/responder/common/negcache_files.c @@ -19,94 +19,90 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <sys/types.h> -#include <pwd.h> -#include <grp.h> #include "util/util.h" +#include "util/nss_dl_load.h" #include "responder/common/negcache_files.h" #define BUFFER_SIZE 16384 -bool is_user_local_by_name(const char *name) +bool is_user_local_by_name(const struct sss_nss_ops *ops, const char *name) { struct passwd pwd = { 0 }; - struct passwd *pwd_result; + int errnop; char buffer[BUFFER_SIZE]; - bool is_local = false; - int ret; + enum nss_status ret; char *shortname = NULL; + int parse_ret; - ret = sss_parse_internal_fqname(NULL, name, &shortname, NULL); - if (ret != EOK) { + parse_ret = sss_parse_internal_fqname(NULL, name, &shortname, NULL); + if (parse_ret != EOK) { return false; } - ret = getpwnam_r(shortname, &pwd, buffer, BUFFER_SIZE, &pwd_result); + ret = ops->getpwnam_r(shortname, &pwd, buffer, BUFFER_SIZE, &errnop); talloc_free(shortname); - if (ret == EOK && pwd_result != NULL) { + if (ret == NSS_STATUS_SUCCESS) { DEBUG(SSSDBG_TRACE_FUNC, "User %s is a local user\n", name); - is_local = true; + return true; } - return is_local; + return false; } -bool is_user_local_by_uid(uid_t uid) +bool is_user_local_by_uid(const struct sss_nss_ops *ops, uid_t uid) { struct passwd pwd = { 0 }; - struct passwd *pwd_result; + int errnop; char buffer[BUFFER_SIZE]; - bool is_local = false; - int ret; + enum nss_status ret; - ret = getpwuid_r(uid, &pwd, buffer, BUFFER_SIZE, &pwd_result); - if (ret == EOK && pwd_result != NULL) { + ret = ops->getpwuid_r(uid, &pwd, buffer, BUFFER_SIZE, &errnop); + if (ret == NSS_STATUS_SUCCESS) { DEBUG(SSSDBG_TRACE_FUNC, "User with UID %"SPRIuid" is a local user\n", uid); - is_local = true; + return true; } - return is_local; + return false; } -bool is_group_local_by_name(const char *name) +bool is_group_local_by_name(const struct sss_nss_ops *ops, const char *name) { struct group grp = { 0 }; - struct group *grp_result; + int errnop; char buffer[BUFFER_SIZE]; - bool is_local = false; - int ret; + enum nss_status ret; char *shortname = NULL; + int parse_ret; - ret = sss_parse_internal_fqname(NULL, name, &shortname, NULL); - if (ret != EOK) { + parse_ret = sss_parse_internal_fqname(NULL, name, &shortname, NULL); + if (parse_ret != EOK) { return false; } - ret = getgrnam_r(shortname, &grp, buffer, BUFFER_SIZE, &grp_result); + ret = ops->getgrnam_r(shortname, &grp, buffer, BUFFER_SIZE, &errnop); talloc_free(shortname); - if (ret == EOK && grp_result != NULL) { + if (ret == NSS_STATUS_SUCCESS) { DEBUG(SSSDBG_TRACE_FUNC, "Group %s is a local group\n", name); - is_local = true; + return true; } - return is_local; + return false; } -bool is_group_local_by_gid(uid_t gid) +bool is_group_local_by_gid(const struct sss_nss_ops *ops, uid_t gid) { struct group grp = { 0 }; - struct group *grp_result; + int errnop; char buffer[BUFFER_SIZE]; - bool is_local = false; - int ret; + enum nss_status ret; - ret = getgrgid_r(gid, &grp, buffer, BUFFER_SIZE, &grp_result); - if (ret == EOK && grp_result != NULL) { + ret = ops->getgrgid_r(gid, &grp, buffer, BUFFER_SIZE, &errnop); + if (ret == NSS_STATUS_SUCCESS) { DEBUG(SSSDBG_TRACE_FUNC, "Group with GID %"SPRIgid" is a local group\n", gid); - is_local = true; + return true; } - return is_local; + return false; } diff --git a/src/responder/common/negcache_files.h b/src/responder/common/negcache_files.h index 01d9f08280..a3e18deb0e 100644 --- a/src/responder/common/negcache_files.h +++ b/src/responder/common/negcache_files.h @@ -22,10 +22,14 @@ #ifndef _NEGCACHE_FILES_H_ #define _NEGCACHE_FILES_H_ -bool is_user_local_by_name(const char *name); -bool is_user_local_by_uid(uid_t uid); +#include <stdbool.h> -bool is_group_local_by_name(const char *name); -bool is_group_local_by_gid(uid_t gid); +struct sss_nss_ops; + +bool is_user_local_by_name(const struct sss_nss_ops *ops, const char *name); +bool is_user_local_by_uid(const struct sss_nss_ops *ops, uid_t uid); + +bool is_group_local_by_name(const struct sss_nss_ops *ops, const char *name); +bool is_group_local_by_gid(const struct sss_nss_ops *ops, uid_t gid); #endif /* _NEGCACHE_FILES_H_ */ diff --git a/src/tests/cwrap/Makefile.am b/src/tests/cwrap/Makefile.am index b63c695fd7..2454e4750f 100644 --- a/src/tests/cwrap/Makefile.am +++ b/src/tests/cwrap/Makefile.am @@ -72,6 +72,7 @@ SSSD_RESPONDER_IFACE_OBJ = \ SSSD_RESPONDER_OBJ = \ ../../../src/responder/common/negcache_files.c \ + ../../../src/util/nss_dl_load.c \ ../../../src/responder/common/negcache.c \ ../../../src/responder/common/responder_cmd.c \ ../../../src/responder/common/responder_common.c \ @@ -165,6 +166,7 @@ responder_common_tests_SOURCES =\ test_responder_common.c \ $(SSSD_RESPONDER_IFACE_OBJ) \ ../../../src/responder/common/negcache_files.c \ + ../../../src/util/nss_dl_load.c \ ../../../src/responder/common/negcache.c \ ../../../src/responder/common/responder_common.c \ ../../../src/responder/common/responder_packet.c \ @@ -177,6 +179,7 @@ responder_common_tests_CFLAGS = \ $(AM_CFLAGS) \ $(NULL) responder_common_tests_LDADD = \ + $(LIBADD_DL) \ $(CMOCKA_LIBS) \ $(SSSD_LIBS) \ $(SELINUX_LIBS) \ @@ -197,6 +200,7 @@ negcache_tests_CFLAGS = \ -DBASE_FILE_STEM=\"$(*F)\" \ $(NULL) negcache_tests_LDADD = \ + $(LIBADD_DL) \ $(CMOCKA_LIBS) \ $(SSSD_LIBS) \ $(SELINUX_LIBS) \ diff --git a/src/tests/cwrap/test_negcache.c b/src/tests/cwrap/test_negcache.c index c4f601b344..b2f5c7159b 100644 --- a/src/tests/cwrap/test_negcache.c +++ b/src/tests/cwrap/test_negcache.c @@ -18,6 +18,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <stdio.h> +#include <sys/types.h> +#include <pwd.h> + #include <stdarg.h> #include <stddef.h> #include <setjmp.h> @@ -35,18 +39,6 @@ #define TEST_CONF_DB "test_negcache_confdb.ldb" #define TEST_DOM_NAME "test_domain.test" -#define TEST_LOCAL_USER_NAME_1 "foobar" -#define TEST_LOCAL_USER_NAME_2 "sssd" - -#define TEST_LOCAL_USER_UID_1 10001 -#define TEST_LOCAL_USER_UID_2 123 - -#define TEST_LOCAL_GROUP_NAME_1 "foogroup" -#define TEST_LOCAL_GROUP_NAME_2 "sssd" - -#define TEST_LOCAL_GID_1 10001 -#define TEST_LOCAL_GID_2 123 - struct test_user { const char *name; uid_t uid; @@ -83,6 +75,10 @@ struct test_group { struct ncache_test_ctx { struct sss_test_ctx *tctx; struct sss_nc_ctx *ncache; + char *local_user_name[2]; + uid_t local_uid[2]; + char *local_group_name[2]; + gid_t local_gid[2]; }; static void create_groups(TALLOC_CTX *mem_ctx, @@ -119,12 +115,51 @@ struct cli_protocol_version *register_cli_protocol_version(void) static int test_ncache_setup(void **state) { struct ncache_test_ctx *test_ctx; + FILE *passwd_file; + FILE *group_file; + const struct passwd *pwd; + const struct group *grp; + int i; + + passwd_file = fopen("/etc/passwd", "r"); + assert_non_null(passwd_file); + + group_file = fopen("/etc/group", "r"); + assert_non_null(group_file); assert_true(leak_check_setup()); test_ctx = talloc_zero(global_talloc_context, struct ncache_test_ctx); assert_non_null(test_ctx); + for (i = 0; i < 2; /*no-op*/) { + pwd = fgetpwent(passwd_file); + assert_non_null(pwd); + if (pwd->pw_uid == 0) { + /* skip root */ + continue; + } + test_ctx->local_uid[i] = pwd->pw_uid; + test_ctx->local_user_name[i] = talloc_strdup(test_ctx, pwd->pw_name); + assert_non_null(test_ctx->local_user_name[i]); + ++i; + } + fclose(passwd_file); + + for (i = 0; i < 2; /* no-op */) { + grp = fgetgrent(group_file); + assert_non_null(grp); + if (grp->gr_gid == 0) { + /* skip root */ + continue; + } + test_ctx->local_gid[i] = grp->gr_gid; + test_ctx->local_group_name[i] = talloc_strdup(test_ctx, grp->gr_name); + assert_non_null(test_ctx->local_group_name[i]); + ++i; + } + fclose(group_file); + test_dom_suite_setup(TESTS_PATH); test_ctx->tctx = create_dom_test_ctx(test_ctx, TESTS_PATH, TEST_CONF_DB, @@ -217,7 +252,7 @@ static void set_users(struct ncache_test_ctx *test_ctx) assert_int_equal(ret, EOK); ret = set_user_in_ncache(test_ctx->ncache, false, test_ctx->tctx->dom, - TEST_LOCAL_USER_NAME_1); + test_ctx->local_user_name[0]); assert_int_equal(ret, EOK); } @@ -235,11 +270,11 @@ static void check_users(struct ncache_test_ctx *test_ctx, assert_int_equal(ret, case_b); ret = check_user_in_ncache(test_ctx->ncache, test_ctx->tctx->dom, - TEST_LOCAL_USER_NAME_1); + test_ctx->local_user_name[0]); assert_int_equal(ret, case_c); ret = check_user_in_ncache(test_ctx->ncache, test_ctx->tctx->dom, - TEST_LOCAL_USER_NAME_2); + test_ctx->local_user_name[1]); assert_int_equal(ret, case_d); } @@ -328,7 +363,7 @@ static void set_uids(struct ncache_test_ctx *test_ctx) assert_int_equal(ret, EOK); ret = sss_ncache_set_uid(test_ctx->ncache, false, test_ctx->tctx->dom, - TEST_LOCAL_USER_UID_1); + test_ctx->local_uid[0]); assert_int_equal(ret, EOK); } @@ -346,11 +381,11 @@ static void check_uids(struct ncache_test_ctx *test_ctx, assert_int_equal(ret, case_b); ret = sss_ncache_check_uid(test_ctx->ncache, test_ctx->tctx->dom, - TEST_LOCAL_USER_UID_1); + test_ctx->local_uid[0]); assert_int_equal(ret, case_c); ret = sss_ncache_check_uid(test_ctx->ncache, test_ctx->tctx->dom, - TEST_LOCAL_USER_UID_2); + test_ctx->local_uid[1]); assert_int_equal(ret, case_d); } @@ -439,7 +474,7 @@ static void set_groups(struct ncache_test_ctx *test_ctx) assert_int_equal(ret, EOK); ret = set_group_in_ncache(test_ctx->ncache, false, test_ctx->tctx->dom, - TEST_LOCAL_GROUP_NAME_1); + test_ctx->local_group_name[0]); assert_int_equal(ret, EOK); } @@ -457,11 +492,11 @@ static void check_groups(struct ncache_test_ctx *test_ctx, assert_int_equal(ret, case_b); ret = check_group_in_ncache(test_ctx->ncache, test_ctx->tctx->dom, - TEST_LOCAL_GROUP_NAME_1); + test_ctx->local_group_name[0]); assert_int_equal(ret, case_c); ret = check_group_in_ncache(test_ctx->ncache, test_ctx->tctx->dom, - TEST_LOCAL_GROUP_NAME_2); + test_ctx->local_group_name[1]); assert_int_equal(ret, case_d); } @@ -550,7 +585,7 @@ static void set_gids(struct ncache_test_ctx *test_ctx) assert_int_equal(ret, EOK); ret = sss_ncache_set_gid(test_ctx->ncache, false, test_ctx->tctx->dom, - TEST_LOCAL_GID_1); + test_ctx->local_gid[0]); assert_int_equal(ret, EOK); } @@ -568,11 +603,11 @@ static void check_gids(struct ncache_test_ctx *test_ctx, assert_int_equal(ret, case_b); ret = sss_ncache_check_gid(test_ctx->ncache, test_ctx->tctx->dom, - TEST_LOCAL_GID_1); + test_ctx->local_gid[0]); assert_int_equal(ret, case_c); ret = sss_ncache_check_gid(test_ctx->ncache, test_ctx->tctx->dom, - TEST_LOCAL_GID_2); + test_ctx->local_gid[1]); assert_int_equal(ret, case_d); } diff --git a/src/tests/intg/test_ldap.py b/src/tests/intg/test_ldap.py index 63f6ea4eda..787255f92d 100644 --- a/src/tests/intg/test_ldap.py +++ b/src/tests/intg/test_ldap.py @@ -43,15 +43,6 @@ LDAP_BASE_DN = "dc=example,dc=com" INTERACTIVE_TIMEOUT = 4 -PASSWD_USER = dict(name='passwduser', passwd='x', uid=100000, gid=2000, - gecos='User for tests', - dir='/home/passwduser', - shell='/bin/bash') - -PASSWD_GROUP = dict(name='passwdgroup', - gid=200000, - mem=['passwduser']) - @pytest.fixture(scope="module") def ds_inst(request): @@ -1860,14 +1851,32 @@ def test_rename_incomplete_group_rdn_changed(ldap_conn, rename_setup_cleanup): @pytest.fixture -def user_and_group_rfc2307_lcl(passwd_ops_setup, group_ops_setup, - user_and_group_rfc2307): - pwd_ops = passwd_ops_setup - pwd_ops.useradd(**PASSWD_USER) - grp_ops = group_ops_setup - grp_ops.groupadd(**PASSWD_GROUP) +def find_local_user_and_group(): + f = open("/etc/passwd") + for line in f: + passwd_user = line.split(':') + passwd_user[2] = int(passwd_user[2]) + if passwd_user[2] != 0: + break + f.close() + assert passwd_user[2] != 0 + + f = open("/etc/group") + for line in f: + passwd_group = line.split(':') + passwd_group[2] = int(passwd_group[2]) + if passwd_group[2] != 0: + break + f.close() + assert passwd_group[2] != 0 + + return (passwd_user, passwd_group) - return user_and_group_rfc2307 + +@pytest.fixture +def user_and_group_rfc2307_lcl(find_local_user_and_group, + user_and_group_rfc2307): + return find_local_user_and_group def test_local_negative_timeout_enabled_by_default(ldap_conn, @@ -1879,64 +1888,53 @@ def test_local_negative_timeout_enabled_by_default(ldap_conn, # sanity check - try resolving an LDAP user ent.assert_passwd_by_name("user", dict(name="user", uid=1001, gid=2000)) + passwd_user, passwd_group = user_and_group_rfc2307_lcl + # resolve a user who is not in LDAP, but exists locally - res, _ = call_sssd_getpwnam("passwduser") + res, _ = call_sssd_getpwnam(passwd_user[0]) assert res == NssReturnCode.NOTFOUND - res = pwd.getpwnam("passwduser") - assert res is not None # Do the same by UID - res, _ = call_sssd_getpwuid(100000) + res, _ = call_sssd_getpwuid(passwd_user[2]) assert res == NssReturnCode.NOTFOUND - res = pwd.getpwuid(100000) - assert res is not None # Do the same for a group both by name and by ID - res, _ = call_sssd_getgrnam("passwdgroup") + res, _ = call_sssd_getgrnam(passwd_group[0]) assert res == NssReturnCode.NOTFOUND - res = grp.getgrnam("passwdgroup") - assert res is not None - res, _ = call_sssd_getgrgid(200000) + res, _ = call_sssd_getgrgid(passwd_group[2]) assert res == NssReturnCode.NOTFOUND - res = grp.getgrgid(200000) - assert res is not None # add the user and the group to LDAP ent_list = ldap_ent.List(ldap_conn.ds_inst.base_dn) - ent_list.add_user("passwduser", 100000, 2000) - ent_list.add_group("passwdgroup", 200000) + ent_list.add_user(passwd_user[0], passwd_user[2], 2000) + ent_list.add_group(passwd_group[0], passwd_group[2]) create_ldap_entries(ldap_conn, ent_list) - # Make sure the negative cache expired + # Make sure the negative cache would expire if global timeout was used time.sleep(2) # The user is now negatively cached and can't be resolved by either # name or UID - res, _ = call_sssd_getpwnam("passwduser") + res, _ = call_sssd_getpwnam(passwd_group[0]) assert res == NssReturnCode.NOTFOUND - res, _ = call_sssd_getpwuid(100000) + res, _ = call_sssd_getpwuid(passwd_group[2]) assert res == NssReturnCode.NOTFOUND - res, _ = call_sssd_getgrnam("passwdgroup") + res, _ = call_sssd_getgrnam(passwd_group[0]) assert res == NssReturnCode.NOTFOUND - res, _ = call_sssd_getgrgid(200000) + res, _ = call_sssd_getgrgid(passwd_group[2]) assert res == NssReturnCode.NOTFOUND cleanup_ldap_entries(ldap_conn, ent_list) @pytest.fixture -def usr_and_grp_rfc2307_no_local_ncache(request, passwd_ops_setup, - group_ops_setup, ldap_conn): +def usr_and_grp_rfc2307_no_local_ncache(request, find_local_user_and_group, + ldap_conn): """ Create an RFC2307 directory fixture with interactive SSSD conf, one user and one group but with the local negative timeout disabled """ - pwd_ops = passwd_ops_setup - pwd_ops.useradd(**PASSWD_USER) - grp_ops = group_ops_setup - grp_ops.groupadd(**PASSWD_GROUP) - ent_list = ldap_ent.List(ldap_conn.ds_inst.base_dn) ent_list.add_user("user", 1001, 2000) ent_list.add_group("group", 2001) @@ -1948,7 +1946,7 @@ def usr_and_grp_rfc2307_no_local_ncache(request, passwd_ops_setup, """) create_conf_fixture(request, conf) create_sssd_fixture(request) - return None + return find_local_user_and_group def test_local_negative_timeout_disabled(ldap_conn, @@ -1960,46 +1958,40 @@ def test_local_negative_timeout_disabled(ldap_conn, # sanity check - try resolving an LDAP user ent.assert_passwd_by_name("user", dict(name="user", uid=1001, gid=2000)) + passwd_user, passwd_group = usr_and_grp_rfc2307_no_local_ncache + # resolve a user who is not in LDAP, but exists locally - res, _ = call_sssd_getpwnam("passwduser") + res, _ = call_sssd_getpwnam(passwd_user[0]) assert res == NssReturnCode.NOTFOUND - res = pwd.getpwnam("passwduser") - assert res is not None # Do the same by UID - res, _ = call_sssd_getpwuid(100000) + res, _ = call_sssd_getpwuid(passwd_user[2]) assert res == NssReturnCode.NOTFOUND - res = pwd.getpwuid(100000) - assert res is not None # Do the same for a group both by name and by ID - res, _ = call_sssd_getgrnam("passwdgroup") + res, _ = call_sssd_getgrnam(passwd_group[0]) assert res == NssReturnCode.NOTFOUND - res = grp.getgrnam("passwdgroup") - assert res is not None - res, _ = call_sssd_getgrgid(200000) + res, _ = call_sssd_getgrgid(passwd_group[2]) assert res == NssReturnCode.NOTFOUND - res = grp.getgrgid(200000) - assert res is not None # add the user and the group to LDAP ent_list = ldap_ent.List(ldap_conn.ds_inst.base_dn) - ent_list.add_user("passwduser", 100000, 2000) - ent_list.add_group("passwdgroup", 200000) + ent_list.add_user(passwd_user[0], passwd_user[2], 2000) + ent_list.add_group(passwd_group[0], passwd_group[2]) create_ldap_entries(ldap_conn, ent_list) # Make sure the negative cache expired time.sleep(2) # The user can now be resolved - res, _ = call_sssd_getpwnam("passwduser") + res, _ = call_sssd_getpwnam(passwd_user[0]) assert res == NssReturnCode.SUCCESS # Do the same by UID - res, _ = call_sssd_getpwuid(100000) + res, _ = call_sssd_getpwuid(passwd_user[2]) assert res == NssReturnCode.SUCCESS - res, _ = call_sssd_getgrnam("passwdgroup") + res, _ = call_sssd_getgrnam(passwd_group[0]) assert res == NssReturnCode.SUCCESS - res, _ = call_sssd_getgrgid(200000) + res, _ = call_sssd_getgrgid(passwd_group[2]) assert res == NssReturnCode.SUCCESS cleanup_ldap_entries(ldap_conn, ent_list) From 5d184088f21f13ef3aa098268dab245d358b82c4 Mon Sep 17 00:00:00 2001 From: Alexey Tikhonov <atikh...@redhat.com> Date: Fri, 22 Mar 2019 14:21:00 +0100 Subject: [PATCH 3/4] negcache_files: got rid of large array on stack Removed large buffer from function stack. It is safe to use single (static) global buffer since: 1) Responders are single threaded 2) Code doesn't use content of this buffer anyway --- src/responder/common/negcache_files.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/responder/common/negcache_files.c b/src/responder/common/negcache_files.c index 85a7065a48..f22796a0cd 100644 --- a/src/responder/common/negcache_files.c +++ b/src/responder/common/negcache_files.c @@ -24,12 +24,12 @@ #include "responder/common/negcache_files.h" #define BUFFER_SIZE 16384 +static char s_nss_buffer[BUFFER_SIZE]; bool is_user_local_by_name(const struct sss_nss_ops *ops, const char *name) { struct passwd pwd = { 0 }; int errnop; - char buffer[BUFFER_SIZE]; enum nss_status ret; char *shortname = NULL; int parse_ret; @@ -39,7 +39,7 @@ bool is_user_local_by_name(const struct sss_nss_ops *ops, const char *name) return false; } - ret = ops->getpwnam_r(shortname, &pwd, buffer, BUFFER_SIZE, &errnop); + ret = ops->getpwnam_r(shortname, &pwd, s_nss_buffer, BUFFER_SIZE, &errnop); talloc_free(shortname); if (ret == NSS_STATUS_SUCCESS) { DEBUG(SSSDBG_TRACE_FUNC, "User %s is a local user\n", name); @@ -53,10 +53,9 @@ bool is_user_local_by_uid(const struct sss_nss_ops *ops, uid_t uid) { struct passwd pwd = { 0 }; int errnop; - char buffer[BUFFER_SIZE]; enum nss_status ret; - ret = ops->getpwuid_r(uid, &pwd, buffer, BUFFER_SIZE, &errnop); + ret = ops->getpwuid_r(uid, &pwd, s_nss_buffer, BUFFER_SIZE, &errnop); if (ret == NSS_STATUS_SUCCESS) { DEBUG(SSSDBG_TRACE_FUNC, "User with UID %"SPRIuid" is a local user\n", uid); @@ -70,7 +69,6 @@ bool is_group_local_by_name(const struct sss_nss_ops *ops, const char *name) { struct group grp = { 0 }; int errnop; - char buffer[BUFFER_SIZE]; enum nss_status ret; char *shortname = NULL; int parse_ret; @@ -80,7 +78,7 @@ bool is_group_local_by_name(const struct sss_nss_ops *ops, const char *name) return false; } - ret = ops->getgrnam_r(shortname, &grp, buffer, BUFFER_SIZE, &errnop); + ret = ops->getgrnam_r(shortname, &grp, s_nss_buffer, BUFFER_SIZE, &errnop); talloc_free(shortname); if (ret == NSS_STATUS_SUCCESS) { DEBUG(SSSDBG_TRACE_FUNC, "Group %s is a local group\n", name); @@ -94,10 +92,9 @@ bool is_group_local_by_gid(const struct sss_nss_ops *ops, uid_t gid) { struct group grp = { 0 }; int errnop; - char buffer[BUFFER_SIZE]; enum nss_status ret; - ret = ops->getgrgid_r(gid, &grp, buffer, BUFFER_SIZE, &errnop); + ret = ops->getgrgid_r(gid, &grp, s_nss_buffer, BUFFER_SIZE, &errnop); if (ret == NSS_STATUS_SUCCESS) { DEBUG(SSSDBG_TRACE_FUNC, "Group with GID %"SPRIgid" is a local group\n", gid); From 6143a4410fafab9c8aa6d9c40fce0377beea9ed1 Mon Sep 17 00:00:00 2001 From: Alexey Tikhonov <atikh...@redhat.com> Date: Fri, 22 Mar 2019 16:33:14 +0100 Subject: [PATCH 4/4] TESTS: moved cwrap/test_negcache to cmocka tests Moved cwrap/test_negcache.c to cmocka tests since it doesn't use cwrap tools anymore. --- Makefile.am | 21 ++++++++++ .../test_negcache_2.c} | 0 src/tests/cwrap/Makefile.am | 38 ------------------- 3 files changed, 21 insertions(+), 38 deletions(-) rename src/tests/{cwrap/test_negcache.c => cmocka/test_negcache_2.c} (100%) diff --git a/Makefile.am b/Makefile.am index 747187aa83..5317516668 100644 --- a/Makefile.am +++ b/Makefile.am @@ -239,6 +239,7 @@ if HAVE_CMOCKA test-find-uid \ test-io \ test-negcache \ + negcache_2-tests \ test-authtok \ sss_nss_idmap-tests \ deskprofile_utils-tests \ @@ -2867,6 +2868,26 @@ test_negcache_LDADD = \ libsss_sbus.la \ $(NULL) +negcache_2_tests_SOURCES =\ + $(SSSD_RESPONDER_OBJ) \ + src/tests/cmocka/test_negcache_2.c \ + $(NULL) +negcache_2_tests_CFLAGS = \ + $(AM_CFLAGS) \ + -DBASE_FILE_STEM=\"$(*F)\" \ + $(NULL) +negcache_2_tests_LDADD = \ + $(LIBADD_DL) \ + $(CMOCKA_LIBS) \ + $(SSSD_LIBS) \ + $(SYSTEMD_DAEMON_LIBS) \ + libsss_util.la \ + libsss_iface.la \ + libsss_test_common.la \ + libsss_debug.la \ + libsss_sbus.la \ + $(NULL) + test_authtok_SOURCES = \ src/tests/cmocka/test_authtok.c \ src/util/authtok.c \ diff --git a/src/tests/cwrap/test_negcache.c b/src/tests/cmocka/test_negcache_2.c similarity index 100% rename from src/tests/cwrap/test_negcache.c rename to src/tests/cmocka/test_negcache_2.c diff --git a/src/tests/cwrap/Makefile.am b/src/tests/cwrap/Makefile.am index 2454e4750f..50695ceb16 100644 --- a/src/tests/cwrap/Makefile.am +++ b/src/tests/cwrap/Makefile.am @@ -70,22 +70,6 @@ SSSD_RESPONDER_IFACE_OBJ = \ ../../../src/responder/common/responder_iface.c \ $(NULL) -SSSD_RESPONDER_OBJ = \ - ../../../src/responder/common/negcache_files.c \ - ../../../src/util/nss_dl_load.c \ - ../../../src/responder/common/negcache.c \ - ../../../src/responder/common/responder_cmd.c \ - ../../../src/responder/common/responder_common.c \ - ../../../src/responder/common/responder_dp.c \ - ../../../src/responder/common/responder_packet.c \ - ../../../src/responder/common/responder_get_domains.c \ - ../../../src/responder/common/responder_utils.c \ - ../../../src/providers/data_provider_req.c \ - ../../../src/util/session_recording.c \ - $(SSSD_RESPONDER_IFACE_OBJ) \ - $(SSSD_CACHE_REQ_OBJ) \ - $(NULL) - dist_noinst_DATA = \ group \ passwd \ @@ -100,7 +84,6 @@ check_PROGRAMS += \ server-tests \ usertools-tests \ responder_common-tests \ - negcache-tests \ $(NULL) endif # HAVE_UID_WRAPPER endif # HAVE_NSS_WRAPPER @@ -191,25 +174,4 @@ responder_common_tests_LDADD = \ $(abs_top_builddir)/libsss_sbus.la \ $(NULL) -negcache_tests_SOURCES =\ - $(SSSD_RESPONDER_OBJ) \ - test_negcache.c \ - $(NULL) -negcache_tests_CFLAGS = \ - $(AM_CFLAGS) \ - -DBASE_FILE_STEM=\"$(*F)\" \ - $(NULL) -negcache_tests_LDADD = \ - $(LIBADD_DL) \ - $(CMOCKA_LIBS) \ - $(SSSD_LIBS) \ - $(SELINUX_LIBS) \ - $(SYSTEMD_DAEMON_LIBS) \ - $(abs_top_builddir)/libsss_util.la \ - $(abs_top_builddir)/libsss_debug.la \ - $(abs_top_builddir)/libsss_test_common.la \ - $(abs_top_builddir)/libsss_iface.la \ - $(abs_top_builddir)/libsss_sbus.la \ - $(NULL) - tests: $(check_PROGRAMS)
_______________________________________________ sssd-devel mailing list -- sssd-devel@lists.fedorahosted.org To unsubscribe send an email to sssd-devel-le...@lists.fedorahosted.org Fedora Code of Conduct: https://getfedora.org/code-of-conduct.html List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedorahosted.org/archives/list/sssd-devel@lists.fedorahosted.org