URL: https://github.com/SSSD/sssd/pull/795
Author: alexey-tikhonov
 Title: #795: WIP: Issue 3964 (sssd-1-16 backport)
Action: synchronized

To pull the PR as Git branch:
git remote add ghsssd https://github.com/SSSD/sssd
git fetch ghsssd pull/795/head:pr795
git checkout pr795
From ca712c08e519ced1d525e401dc026754b5d43934 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/5] 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

Reviewed-by: Jakub Hrozek <jhro...@redhat.com>
(cherry picked from commit 6a6aad282e56a5f0bf52f20b98c1764d43abbbaf)
---
 Makefile.am                      |   2 +
 src/providers/proxy/proxy.h      |  54 +---------
 src/providers/proxy/proxy_init.c | 163 ++++++++++++-------------------
 src/util/nss_dl_load.c           | 106 ++++++++++++++++++++
 src/util/nss_dl_load.h           |  81 +++++++++++++++
 5 files changed, 255 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 4475b3d12e..05f5f4e266 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -677,6 +677,7 @@ dist_noinst_HEADERS = \
     src/util/inotify.h \
     src/util/sss_iobuf.h \
     src/util/tev_curl.h \
+    src/util/nss_dl_load.h \
     src/monitor/monitor.h \
     src/monitor/monitor_interfaces.h \
     src/monitor/monitor_iface_generated.h \
@@ -3996,6 +3997,7 @@ libsss_proxy_la_SOURCES = \
     src/providers/proxy/proxy_services.c \
     src/providers/proxy/proxy_auth.c \
     src/providers/proxy/proxy_iface_generated.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 3b0475d080..6debd49532 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,58 +33,13 @@
 #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>
 
 #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;
@@ -99,8 +50,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 7d997cb16e..e3273d9a76 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_setup_sbus(TALLOC_CTX *mem_ctx,
                                 struct proxy_auth_ctx *ctx,
                                 struct be_ctx *be_ctx)
@@ -310,6 +222,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,
@@ -317,7 +291,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);
@@ -327,20 +300,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..60df333765
--- /dev/null
+++ b/src/util/nss_dl_load.c
@@ -0,0 +1,106 @@
+/*
+    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..5097acacda
--- /dev/null
+++ b/src/util/nss_dl_load.h
@@ -0,0 +1,81 @@
+/*
+    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 bd35ff1476e61deb7165bed7c447818d611cd3e6 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/5] 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

Reviewed-by: Jakub Hrozek <jhro...@redhat.com>
(cherry picked from commit 2b564f849a20289a857cf19bbfaa5c6eb8670bad)
---
 Makefile.am                           |  20 +++
 src/responder/common/negcache.c       |  52 +++++-
 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       | 227 +++++++++++++++++++-------
 src/tests/intg/test_ldap.py           | 114 ++++++-------
 7 files changed, 333 insertions(+), 170 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 05f5f4e266..6a67dc7b14 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -569,6 +569,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 \
@@ -1380,6 +1381,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 \
@@ -1396,6 +1398,7 @@ sssd_pam_SOURCES = \
     src/responder/pam/pam_helpers.c \
     $(SSSD_RESPONDER_OBJ)
 sssd_pam_LDADD = \
+    $(LIBADD_DL) \
     $(TDB_LIBS) \
     $(SSSD_LIBS) \
     $(SELINUX_LIBS) \
@@ -1414,6 +1417,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)
@@ -1426,6 +1430,7 @@ sssd_autofs_SOURCES = \
     src/responder/autofs/autofssrv_dp.c \
     $(SSSD_RESPONDER_OBJ)
 sssd_autofs_LDADD = \
+    $(LIBADD_DL) \
     $(SSSD_LIBS) \
     $(SYSTEMD_DAEMON_LIBS) \
     $(SSSD_INTERNAL_LTLIBS)
@@ -1441,6 +1446,7 @@ sssd_ssh_SOURCES = \
     $(SSSD_RESPONDER_OBJ) \
     $(NULL)
 sssd_ssh_LDADD = \
+    $(LIBADD_DL) \
     $(SSSD_LIBS) \
     $(SSSD_INTERNAL_LTLIBS) \
     $(SYSTEMD_DAEMON_LIBS) \
@@ -1457,6 +1463,7 @@ sssd_pac_CFLAGS = \
     $(AM_CFLAGS) \
     $(NDR_KRB5PAC_CFLAGS)
 sssd_pac_LDADD = \
+    $(LIBADD_DL) \
     $(NDR_KRB5PAC_LIBS) \
     $(TDB_LIBS) \
     $(SSSD_LIBS) \
@@ -1481,6 +1488,7 @@ sssd_ifp_SOURCES = \
 sssd_ifp_CFLAGS = \
     $(AM_CFLAGS)
 sssd_ifp_LDADD = \
+    $(LIBADD_DL) \
     $(SSSD_LIBS) \
     $(SYSTEMD_DAEMON_LIBS) \
     $(SSSD_INTERNAL_LTLIBS) \
@@ -1525,6 +1533,7 @@ sssd_secrets_SOURCES = \
     $(SSSD_RESPONDER_OBJ) \
     $(NULL)
 sssd_secrets_LDADD = \
+    $(LIBADD_DL) \
     $(HTTP_PARSER_LIBS) \
     $(JANSSON_LIBS) \
     $(TDB_LIBS) \
@@ -1559,6 +1568,7 @@ sssd_kcm_CFLAGS = \
     $(JANSSON_CFLAGS) \
     $(NULL)
 sssd_kcm_LDADD = \
+    $(LIBADD_DL) \
     $(KRB5_LIBS) \
     $(CURL_LIBS) \
     $(JANSSON_LIBS) \
@@ -2254,6 +2264,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 \
@@ -2267,6 +2278,7 @@ responder_socket_access_tests_CFLAGS = \
     $(AM_CFLAGS) \
     $(CHECK_CFLAGS)
 responder_socket_access_tests_LDADD = \
+    $(LIBADD_DL) \
     $(CHECK_LIBS) \
     $(SSSD_LIBS) \
     $(SSSD_INTERNAL_LTLIBS) \
@@ -2358,6 +2370,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/data_provider/rdp_message.c \
      src/responder/common/data_provider/rdp_client.c \
@@ -2409,6 +2422,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) \
@@ -2444,6 +2458,7 @@ pam_srv_tests_LDFLAGS = \
     -Wl,-wrap,pam_dp_send_req \
     $(NULL)
 pam_srv_tests_LDADD = \
+    $(LIBADD_DL) \
     $(CMOCKA_LIBS) \
     $(PAM_LIBS) \
     $(SSSD_LIBS) \
@@ -2480,6 +2495,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) \
@@ -2499,6 +2515,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) \
@@ -2578,6 +2595,7 @@ test_negcache_CFLAGS = \
     $(TALLOC_CFLAGS) \
     $(DHASH_CFLAGS)
 test_negcache_LDADD = \
+    $(LIBADD_DL) \
     $(CMOCKA_LIBS) \
     $(SSSD_LIBS) \
     $(SYSTEMD_DAEMON_LIBS) \
@@ -2922,6 +2940,7 @@ ifp_tests_SOURCES = \
 ifp_tests_CFLAGS = \
     $(AM_CFLAGS)
 ifp_tests_LDADD = \
+    $(LIBADD_DL) \
     $(CMOCKA_LIBS) \
     $(SSSD_LIBS) \
     $(SSSD_INTERNAL_LTLIBS) \
@@ -3178,6 +3197,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..d6f72d8160 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,49 @@ 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 +526,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 +547,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 +644,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 +668,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 a559abe9e1..bfc4933959 100644
--- a/src/tests/cwrap/Makefile.am
+++ b/src/tests/cwrap/Makefile.am
@@ -75,6 +75,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 \
@@ -175,6 +176,7 @@ responder_common_tests_SOURCES =\
     ../../../src/responder/common/iface/responder_ncache.c \
     ../../../src/responder/common/iface/responder_iface_generated.c \
     ../../../src/responder/common/negcache_files.c \
+    ../../../src/util/nss_dl_load.c \
     ../../../src/responder/common/negcache.c \
     ../../../src/responder/common/data_provider/rdp_message.c \
     ../../../src/responder/common/data_provider/rdp_client.c \
@@ -189,6 +191,7 @@ responder_common_tests_CFLAGS = \
     $(AM_CFLAGS) \
     $(NULL)
 responder_common_tests_LDADD = \
+    $(LIBADD_DL) \
     $(CMOCKA_LIBS) \
     $(SSSD_LIBS) \
     $(SELINUX_LIBS) \
@@ -207,6 +210,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..690e797e2d 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,38 +39,40 @@
 #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 {
+struct user_descriptor_t {
     const char *name;
     uid_t uid;
+};
+
+struct group_descriptor_t {
+    const char *name;
     gid_t gid;
-} users[] = { { "test_user1", 1001, 50001 },
-              { "test_user2", 1002, 50002 } };
+};
 
-static void create_users(TALLOC_CTX *mem_ctx,
-                         struct sss_domain_info *domain)
+struct ncache_test_ctx {
+    struct sss_test_ctx *tctx;
+    struct sss_nc_ctx *ncache;
+    struct user_descriptor_t local_users[2];
+    struct user_descriptor_t non_local_users[2];
+    struct group_descriptor_t local_groups[2];
+    struct group_descriptor_t non_local_groups[2];
+};
+
+static void create_users(struct ncache_test_ctx *test_ctx)
 {
     errno_t ret;
     char *fqname;
+    struct sss_domain_info *domain = test_ctx->tctx->dom;
+    const struct user_descriptor_t *users = test_ctx->non_local_users;
+    const struct group_descriptor_t *groups = test_ctx->non_local_groups;
 
     for (int i = 0; i < 2; i++) {
-        fqname = sss_create_internal_fqname(mem_ctx,
+        fqname = sss_create_internal_fqname(test_ctx,
                                             users[i].name,
                                             domain->name);
         assert_non_null(fqname);
 
-        ret = sysdb_add_user(domain, users[i].name, users[i].uid, users[i].gid,
+        ret = sysdb_add_user(domain, users[i].name, users[i].uid, groups[i].gid,
                              fqname, NULL, "/bin/bash", domain->name,
                              NULL, 30, time(NULL));
         talloc_free(fqname);
@@ -74,25 +80,15 @@ static void create_users(TALLOC_CTX *mem_ctx,
     }
 }
 
-struct test_group {
-    const char *name;
-    gid_t gid;
-} groups[] = { { "test_group1", 50001 },
-               { "test_group2", 50002 } };
-
-struct ncache_test_ctx {
-    struct sss_test_ctx *tctx;
-    struct sss_nc_ctx *ncache;
-};
-
-static void create_groups(TALLOC_CTX *mem_ctx,
-                          struct sss_domain_info *domain)
+static void create_groups(struct ncache_test_ctx *test_ctx)
 {
     errno_t ret;
     char *fqname;
+    struct sss_domain_info *domain = test_ctx->tctx->dom;
+    const struct group_descriptor_t *groups = test_ctx->non_local_groups;
 
     for (int i = 0; i < 2; i++) {
-        fqname = sss_create_internal_fqname(mem_ctx,
+        fqname = sss_create_internal_fqname(test_ctx,
                                             groups[i].name,
                                             domain->name);
         assert_non_null(fqname);
@@ -116,6 +112,114 @@ struct cli_protocol_version *register_cli_protocol_version(void)
     return responder_test_cli_protocol_version;
 }
 
+static void find_local_users(struct ncache_test_ctx *test_ctx)
+{
+    int i;
+    FILE *passwd_file;
+    const struct passwd *pwd;
+
+    passwd_file = fopen("/etc/passwd", "r");
+    assert_non_null(passwd_file);
+
+    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_users[i].uid = pwd->pw_uid;
+        test_ctx->local_users[i].name = talloc_strdup(test_ctx, pwd->pw_name);
+        assert_non_null(test_ctx->local_users[i].name);
+        ++i;
+    }
+
+    fclose(passwd_file);
+}
+
+static void find_local_groups(struct ncache_test_ctx *test_ctx)
+{
+    int i;
+    FILE *group_file;
+    const struct group *grp;
+
+    group_file = fopen("/etc/group", "r");
+    assert_non_null(group_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_groups[i].gid = grp->gr_gid;
+        test_ctx->local_groups[i].name = talloc_strdup(test_ctx, grp->gr_name);
+        assert_non_null(test_ctx->local_groups[i].name);
+        ++i;
+    }
+
+    fclose(group_file);
+}
+
+static void find_non_local_users(struct ncache_test_ctx *test_ctx)
+{
+    int i;
+    int k;
+    uid_t uid;
+    char *name;
+
+    for (i = 0, k = 1; (k < 100) && (i < 2); ++k) {
+        uid = 65534-k;
+        if (getpwuid(uid)) {
+            continue;
+        }
+        test_ctx->non_local_users[i].uid = uid;
+        ++i;
+    }
+    assert_int_equal(i, 2);
+
+    for (i = 0, k = 0; (k < 100) && (i < 2); ++k) {
+        name = talloc_asprintf(test_ctx, "nctestuser%d", k);
+        if (getpwnam(name)) {
+            talloc_free(name);
+            continue;
+        }
+        test_ctx->non_local_users[i].name = name;
+        ++i;
+    }
+    assert_int_equal(i, 2);
+}
+
+static void find_non_local_groups(struct ncache_test_ctx *test_ctx)
+{
+    int i = 0;
+    int k;
+    gid_t gid;
+    char *name;
+
+    for (i = 0, k = 1; (k < 100) && (i < 2); ++k) {
+        gid = 65534-k;
+        if (getgrgid(gid)) {
+            continue;
+        }
+        test_ctx->non_local_groups[i].gid = gid;
+        ++i;
+    }
+    assert_int_equal(i, 2);
+
+    for (i = 0, k = 0; (k < 100) && (i < 2); ++k) {
+        name = talloc_asprintf(test_ctx, "nctestgroup%d", k);
+        if (getgrnam(name)) {
+            talloc_free(name);
+            continue;
+        }
+        test_ctx->non_local_groups[i].name = name;
+        ++i;
+    }
+    assert_int_equal(i, 2);
+}
+
 static int test_ncache_setup(void **state)
 {
     struct ncache_test_ctx *test_ctx;
@@ -125,14 +229,19 @@ static int test_ncache_setup(void **state)
     test_ctx = talloc_zero(global_talloc_context, struct ncache_test_ctx);
     assert_non_null(test_ctx);
 
+    find_local_users(test_ctx);
+    find_local_groups(test_ctx);
+    find_non_local_users(test_ctx);
+    find_non_local_groups(test_ctx);
+
     test_dom_suite_setup(TESTS_PATH);
 
     test_ctx->tctx = create_dom_test_ctx(test_ctx, TESTS_PATH, TEST_CONF_DB,
                                          TEST_DOM_NAME, "ipa", NULL);
     assert_non_null(test_ctx->tctx);
 
-    create_groups(test_ctx, test_ctx->tctx->dom);
-    create_users(test_ctx, test_ctx->tctx->dom);
+    create_groups(test_ctx);
+    create_users(test_ctx);
 
     check_leaks_push(test_ctx);
 
@@ -213,11 +322,11 @@ static void set_users(struct ncache_test_ctx *test_ctx)
     int ret;
 
     ret = set_user_in_ncache(test_ctx->ncache, false, test_ctx->tctx->dom,
-                              users[0].name);
+                             test_ctx->non_local_users[0].name);
     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_users[0].name);
     assert_int_equal(ret, EOK);
 }
 
@@ -227,19 +336,19 @@ static void check_users(struct ncache_test_ctx *test_ctx,
     int ret;
 
     ret = check_user_in_ncache(test_ctx->ncache, test_ctx->tctx->dom,
-                                users[0].name);
+                                test_ctx->non_local_users[0].name);
     assert_int_equal(ret, case_a);
 
     ret = check_user_in_ncache(test_ctx->ncache, test_ctx->tctx->dom,
-                                users[1].name);
+                                test_ctx->non_local_users[1].name);
     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_users[0].name);
     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_users[1].name);
     assert_int_equal(ret, case_d);
 }
 
@@ -324,11 +433,11 @@ static void set_uids(struct ncache_test_ctx *test_ctx)
     int ret;
 
     ret = sss_ncache_set_uid(test_ctx->ncache, false, test_ctx->tctx->dom,
-                             users[0].uid);
+                             test_ctx->non_local_users[0].uid);
     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_users[0].uid);
     assert_int_equal(ret, EOK);
 }
 
@@ -338,19 +447,19 @@ static void check_uids(struct ncache_test_ctx *test_ctx,
     int ret;
 
     ret = sss_ncache_check_uid(test_ctx->ncache, test_ctx->tctx->dom,
-                               users[0].uid);
+                               test_ctx->non_local_users[0].uid);
     assert_int_equal(ret, case_a);
 
     ret = sss_ncache_check_uid(test_ctx->ncache, test_ctx->tctx->dom,
-                               users[1].uid);
+                               test_ctx->non_local_users[1].uid);
     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_users[0].uid);
     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_users[1].uid);
     assert_int_equal(ret, case_d);
 }
 
@@ -435,11 +544,11 @@ static void set_groups(struct ncache_test_ctx *test_ctx)
     int ret;
 
     ret = set_group_in_ncache(test_ctx->ncache, false, test_ctx->tctx->dom,
-                              groups[0].name);
+                              test_ctx->non_local_groups[0].name);
     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_groups[0].name);
     assert_int_equal(ret, EOK);
 }
 
@@ -449,19 +558,19 @@ static void check_groups(struct ncache_test_ctx *test_ctx,
     int ret;
 
     ret = check_group_in_ncache(test_ctx->ncache, test_ctx->tctx->dom,
-                                groups[0].name);
+                                test_ctx->non_local_groups[0].name);
     assert_int_equal(ret, case_a);
 
     ret = check_group_in_ncache(test_ctx->ncache, test_ctx->tctx->dom,
-                                groups[1].name);
+                                test_ctx->non_local_groups[1].name);
     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_groups[0].name);
     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_groups[1].name);
     assert_int_equal(ret, case_d);
 }
 
@@ -546,11 +655,11 @@ static void set_gids(struct ncache_test_ctx *test_ctx)
     int ret;
 
     ret = sss_ncache_set_gid(test_ctx->ncache, false, test_ctx->tctx->dom,
-                             users[0].gid);
+                             test_ctx->non_local_groups[0].gid);
     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_groups[0].gid);
     assert_int_equal(ret, EOK);
 }
 
@@ -560,19 +669,19 @@ static void check_gids(struct ncache_test_ctx *test_ctx,
     int ret;
 
     ret = sss_ncache_check_gid(test_ctx->ncache, test_ctx->tctx->dom,
-                               users[0].gid);
+                               test_ctx->non_local_groups[0].gid);
     assert_int_equal(ret, case_a);
 
     ret = sss_ncache_check_gid(test_ctx->ncache, test_ctx->tctx->dom,
-                               users[1].gid);
+                               test_ctx->non_local_groups[1].gid);
     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_groups[0].gid);
     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_groups[1].gid);
     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 e9b09fd53f0e567a49e8c15f94429f6038696793 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/5] 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

Reviewed-by: Jakub Hrozek <jhro...@redhat.com>
(cherry picked from commit 8e6656c974ac05bb52607014bb4c30b87f4abd8b)
---
 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 7c8a21f677e97e7044986e4782cf1f26c167feb2 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/5] TESTS: moved cwrap/test_negcache to cmocka tests

Moved cwrap/test_negcache.c to cmocka tests since it doesn't use
cwrap tools anymore.

Reviewed-by: Jakub Hrozek <jhro...@redhat.com>
(cherry picked from commit 137b684d0a01afa02618b07ba46a44dad017b5b9)
---
 Makefile.am                                   | 19 +++++++++
 .../test_negcache_2.c}                        |  0
 src/tests/cwrap/Makefile.am                   | 40 -------------------
 3 files changed, 19 insertions(+), 40 deletions(-)
 rename src/tests/{cwrap/test_negcache.c => cmocka/test_negcache_2.c} (100%)

diff --git a/Makefile.am b/Makefile.am
index 6a67dc7b14..d09f50aa28 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 \
@@ -2603,6 +2604,24 @@ test_negcache_LDADD = \
     libsss_test_common.la \
     libsss_idmap.la
 
+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_test_common.la \
+    libsss_debug.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 bfc4933959..1edefc6788 100644
--- a/src/tests/cwrap/Makefile.am
+++ b/src/tests/cwrap/Makefile.am
@@ -73,26 +73,6 @@ SSSD_RESPONDER_IFACE_OBJ = \
     ../../../src/responder/common/iface/responder_iface_generated.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_dp_ssh.c \
-    ../../../src/responder/common/responder_packet.c \
-    ../../../src/responder/common/responder_get_domains.c \
-    ../../../src/responder/common/responder_utils.c \
-    ../../../src/responder/common/data_provider/rdp_message.c \
-    ../../../src/responder/common/data_provider/rdp_client.c \
-    ../../../src/monitor/monitor_iface_generated.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 \
@@ -107,7 +87,6 @@ check_PROGRAMS += \
     server-tests \
     usertools-tests \
     responder_common-tests \
-    negcache-tests \
     $(NULL)
 endif # HAVE_UID_WRAPPER
 endif # HAVE_NSS_WRAPPER
@@ -201,23 +180,4 @@ responder_common_tests_LDADD = \
     $(abs_top_builddir)/libsss_test_common.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 \
-    $(NULL)
-
 tests: $(check_PROGRAMS)

From f420b55cf737d54d05b686aa23f86fde1c2f6dc2 Mon Sep 17 00:00:00 2001
From: Alexey Tikhonov <atikh...@redhat.com>
Date: Mon, 1 Apr 2019 16:44:26 +0200
Subject: [PATCH 5/5] ci/sssd.supp: getpwuid() leak suppression

Supresses following error:
 4,096 bytes in 1 blocks are definitely lost in loss record 67 of 83
    at 0x4C2CDCB: malloc (vg_replace_malloc.c:299)
    by 0xB8F8627: ???
    by 0xB91EF3F: ???
    by 0xB90E112: ???
    by 0x9992974: getpwuid_r@@GLIBC_2.2.5 (in /usr/lib64/libc-2.26.so)
    by 0x99920D7: getpwuid (in /usr/lib64/libc-2.26.so)

This https://sourceware.org/bugzilla/show_bug.cgi?id=2314#c8 might
be related.

This problem seems to be afecting Fedora < F28
---
 contrib/ci/sssd.supp | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/contrib/ci/sssd.supp b/contrib/ci/sssd.supp
index 4303eed22e..ce2ab4cfbb 100644
--- a/contrib/ci/sssd.supp
+++ b/contrib/ci/sssd.supp
@@ -221,3 +221,17 @@
    fun:set_default_locale
    fun:main
 }
+
+# glibc nsswitch (getpwuid) leak
+# Seems to be affecting Fedora < F28
+{
+   glibc-nss-getpwuid
+   Memcheck:Leak
+   match-leak-kinds: definite
+   fun:malloc
+   ...
+   fun:getpwuid_r@@GLIBC_2.2.5
+   fun:getpwuid
+   ...
+   fun:main
+}
_______________________________________________
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

Reply via email to