Backport extended NSS API from upstream master branch

This commit is contained in:
Jakub Hrozek 2017-11-17 18:06:26 +01:00
parent b5c435b10b
commit 7781c9e992
11 changed files with 3598 additions and 1 deletions

View File

@ -0,0 +1,142 @@
From 7449b236523409cc8766fb957d6cba051fdfb483 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Fri, 29 Sep 2017 21:38:54 +0200
Subject: [PATCH 02/11] sss_client: create nss_common.h
This patch makes sss_nss_getpw_readrep() and sss_nss_getgr_readrep()
calls which parse SSSD's replies for user and group requests available
to other components.
Related to https://pagure.io/SSSD/sssd/issue/2478
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
---
Makefile.am | 1 +
src/sss_client/nss_common.h | 43 +++++++++++++++++++++++++++++++++++++++++++
src/sss_client/nss_group.c | 10 +++-------
src/sss_client/nss_passwd.c | 11 +++--------
4 files changed, 50 insertions(+), 15 deletions(-)
create mode 100644 src/sss_client/nss_common.h
diff --git a/Makefile.am b/Makefile.am
index 5483375167d99568e8313c9a0488900419be6ec3..dc2f4b1857ce5bd376544488348731be29b6b293 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -3623,6 +3623,7 @@ libnss_sss_la_SOURCES = \
src/sss_client/nss_services.c \
src/sss_client/sss_cli.h \
src/sss_client/nss_compat.h \
+ src/sss_client/nss_common.h \
src/sss_client/nss_mc_common.c \
src/util/io.c \
src/util/murmurhash3.c \
diff --git a/src/sss_client/nss_common.h b/src/sss_client/nss_common.h
new file mode 100644
index 0000000000000000000000000000000000000000..e83b4f95a3136b5aa711194a4d37389eebfb607a
--- /dev/null
+++ b/src/sss_client/nss_common.h
@@ -0,0 +1,43 @@
+/*
+ SSSD
+
+ Common routines for classical and enhanced NSS interface
+
+ Authors:
+ Sumit Bose <sbose@redhat.com>
+
+ Copyright (C) Red Hat, Inc 2007
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+
+
+struct sss_nss_pw_rep {
+ struct passwd *result;
+ char *buffer;
+ size_t buflen;
+};
+
+int sss_nss_getpw_readrep(struct sss_nss_pw_rep *pr,
+ uint8_t *buf, size_t *len);
+
+struct sss_nss_gr_rep {
+ struct group *result;
+ char *buffer;
+ size_t buflen;
+};
+
+int sss_nss_getgr_readrep(struct sss_nss_gr_rep *pr,
+ uint8_t *buf, size_t *len);
diff --git a/src/sss_client/nss_group.c b/src/sss_client/nss_group.c
index 0e686af43aeb84a5938315e3922e9fcf2fef4e83..42fba6242d23fc1d52cfd7be10cf10383010f091 100644
--- a/src/sss_client/nss_group.c
+++ b/src/sss_client/nss_group.c
@@ -29,6 +29,7 @@
#include <stdbool.h>
#include "sss_cli.h"
#include "nss_mc.h"
+#include "nss_common.h"
static struct sss_nss_getgrent_data {
size_t len;
@@ -190,14 +191,9 @@ done:
*
* FIXME: do we need to pad so that each result is 32 bit aligned ?
*/
-struct sss_nss_gr_rep {
- struct group *result;
- char *buffer;
- size_t buflen;
-};
-static int sss_nss_getgr_readrep(struct sss_nss_gr_rep *pr,
- uint8_t *buf, size_t *len)
+int sss_nss_getgr_readrep(struct sss_nss_gr_rep *pr,
+ uint8_t *buf, size_t *len)
{
errno_t ret;
size_t i, l, slen, ptmem, pad, dlen, glen;
diff --git a/src/sss_client/nss_passwd.c b/src/sss_client/nss_passwd.c
index c43f9bc50f43599b541e97f5a5aa60de036a5cdf..61e2a567e684fbc7664b5d425e81cfa28a98e845 100644
--- a/src/sss_client/nss_passwd.c
+++ b/src/sss_client/nss_passwd.c
@@ -28,6 +28,7 @@
#include <string.h>
#include "sss_cli.h"
#include "nss_mc.h"
+#include "nss_common.h"
static struct sss_nss_getpwent_data {
size_t len;
@@ -63,14 +64,8 @@ static void sss_nss_getpwent_data_clean(void) {
* 8-X: sequence of 5, 0 terminated, strings (name, passwd, gecos, dir, shell)
*/
-struct sss_nss_pw_rep {
- struct passwd *result;
- char *buffer;
- size_t buflen;
-};
-
-static int sss_nss_getpw_readrep(struct sss_nss_pw_rep *pr,
- uint8_t *buf, size_t *len)
+int sss_nss_getpw_readrep(struct sss_nss_pw_rep *pr,
+ uint8_t *buf, size_t *len)
{
errno_t ret;
size_t i, slen, dlen;
--
2.14.3

View File

@ -0,0 +1,900 @@
From 5e6622722e84d594298a8324f3685a1bda2b5868 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Fri, 29 Sep 2017 16:16:01 +0200
Subject: [PATCH 03/11] nss-idmap: add nss like calls with timeout and flags
This patch adds new calls to libsss_nss_idmap to get NSS like user and
group information directly from SSSD without using the system's NSS
interfaces.
Additionally a timeout and a flags options are added which are not
available for system's NSS.
Related to https://pagure.io/SSSD/sssd/issue/2478
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
---
Makefile.am | 22 +-
configure.ac | 13 +
src/sss_client/common.c | 9 +-
src/sss_client/common_private.h | 41 +++
src/sss_client/idmap/common_ex.c | 105 +++++++
src/sss_client/idmap/sss_nss_ex.c | 402 +++++++++++++++++++++++++++
src/sss_client/idmap/sss_nss_idmap.exports | 10 +
src/sss_client/idmap/sss_nss_idmap.h | 135 +++++++++
src/sss_client/idmap/sss_nss_idmap_private.h | 30 ++
9 files changed, 757 insertions(+), 10 deletions(-)
create mode 100644 src/sss_client/common_private.h
create mode 100644 src/sss_client/idmap/common_ex.c
create mode 100644 src/sss_client/idmap/sss_nss_ex.c
create mode 100644 src/sss_client/idmap/sss_nss_idmap_private.h
diff --git a/Makefile.am b/Makefile.am
index dc2f4b1857ce5bd376544488348731be29b6b293..dd25d1f7ea1be66388aa1b393bac290c4d7501a2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1159,13 +1159,28 @@ pkgconfig_DATA += src/sss_client/idmap/sss_nss_idmap.pc
libsss_nss_idmap_la_DEPENDENCIES = src/sss_client/idmap/sss_nss_idmap.exports
libsss_nss_idmap_la_SOURCES = \
src/sss_client/idmap/sss_nss_idmap.c \
+ src/sss_client/idmap/sss_nss_ex.c \
+ src/sss_client/idmap/sss_nss_idmap_private.h \
src/sss_client/common.c \
- src/util/strtonum.c
+ src/sss_client/idmap/common_ex.c \
+ src/sss_client/nss_mc_passwd.c \
+ src/sss_client/nss_passwd.c \
+ src/sss_client/nss_mc_group.c \
+ src/sss_client/nss_group.c \
+ src/sss_client/nss_mc_initgr.c \
+ src/sss_client/nss_mc_common.c \
+ src/util/strtonum.c \
+ src/util/murmurhash3.c \
+ src/util/io.c \
+ $(NULL)
libsss_nss_idmap_la_LIBADD = \
- $(CLIENT_LIBS)
+ $(LIBCLOCK_GETTIME) \
+ $(CLIENT_LIBS) \
+ -lpthread \
+ $(NULL)
libsss_nss_idmap_la_LDFLAGS = \
-Wl,--version-script,$(srcdir)/src/sss_client/idmap/sss_nss_idmap.exports \
- -version-info 3:0:3
+ -version-info 4:0:4
dist_noinst_DATA += src/sss_client/idmap/sss_nss_idmap.exports
@@ -3624,6 +3639,7 @@ libnss_sss_la_SOURCES = \
src/sss_client/sss_cli.h \
src/sss_client/nss_compat.h \
src/sss_client/nss_common.h \
+ src/sss_client/common_private.h \
src/sss_client/nss_mc_common.c \
src/util/io.c \
src/util/murmurhash3.c \
diff --git a/configure.ac b/configure.ac
index 7037927b5f7045b29d3774c85758e00e35e6def6..7e699d33e342c70d210d3f320c8a29a99e0c78a6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -75,6 +75,19 @@ AC_SEARCH_LIBS([timer_create], [rt posix4],
AC_SUBST([LIBADD_TIMER])
LIBS=$SAVE_LIBS
+# Check library for the clock_gettime function
+SAVE_LIBS=$LIBS
+LIBS=
+LIBCLOCK_GETTIME=
+AC_SEARCH_LIBS([clock_gettime], [rt posix4],
+ [AC_DEFINE([HAVE_LIBRT], [1],
+ [Define if you have the librt library or equivalent.])
+ LIBCLOCK_GETTIME="$LIBS"],
+ [AC_MSG_ERROR([unable to find library for the clock_gettime() function])])
+
+AC_SUBST([LIBCLOCK_GETTIME])
+LIBS=$SAVE_LIBS
+
# Check for presence of modern functions for setting file timestamps
AC_CHECK_FUNCS([ utimensat \
futimens ])
diff --git a/src/sss_client/common.c b/src/sss_client/common.c
index e5e0cbf854e4c977c03f9b1ca1ac90bfd8cbdb77..40252a35281dc4e94c712c3e7f8253af8b19b35a 100644
--- a/src/sss_client/common.c
+++ b/src/sss_client/common.c
@@ -43,6 +43,7 @@
#include <libintl.h>
#define _(STRING) dgettext (PACKAGE, STRING)
#include "sss_cli.h"
+#include "common_private.h"
#if HAVE_PTHREAD
#include <pthread.h>
@@ -1113,13 +1114,7 @@ errno_t sss_strnlen(const char *str, size_t maxlen, size_t *len)
#if HAVE_PTHREAD
typedef void (*sss_mutex_init)(void);
-struct sss_mutex {
- pthread_mutex_t mtx;
-
- int old_cancel_state;
-};
-
-static struct sss_mutex sss_nss_mtx = { .mtx = PTHREAD_MUTEX_INITIALIZER };
+struct sss_mutex sss_nss_mtx = { .mtx = PTHREAD_MUTEX_INITIALIZER };
static struct sss_mutex sss_pam_mtx = { .mtx = PTHREAD_MUTEX_INITIALIZER };
diff --git a/src/sss_client/common_private.h b/src/sss_client/common_private.h
new file mode 100644
index 0000000000000000000000000000000000000000..a98d2c062caeecdbab02ecdaa6ae44d688a791bb
--- /dev/null
+++ b/src/sss_client/common_private.h
@@ -0,0 +1,41 @@
+/*
+ SSSD
+
+ SSS client - private calls
+
+ Authors:
+ Sumit Bose <sbose@redhat.com>
+
+ Copyright (C) 2017 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 COMMON_PRIVATE_H_
+#define COMMON_PRIVATE_H_
+
+#include "config.h"
+
+#if HAVE_PTHREAD
+#include <pthread.h>
+
+struct sss_mutex {
+ pthread_mutex_t mtx;
+
+ int old_cancel_state;
+};
+
+#endif /* HAVE_PTHREAD */
+
+#endif /* COMMON_PRIVATE_H_ */
diff --git a/src/sss_client/idmap/common_ex.c b/src/sss_client/idmap/common_ex.c
new file mode 100644
index 0000000000000000000000000000000000000000..5efe9fabed7896ce674615472dbb256c4eae2144
--- /dev/null
+++ b/src/sss_client/idmap/common_ex.c
@@ -0,0 +1,105 @@
+/*
+ Authors:
+ Sumit Bose <sbose@redhat.com>
+
+ Copyright (C) 2017 Red Hat
+
+ SSSD's enhanced NSS API
+
+ 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 <time.h>
+#include <errno.h>
+
+#include "sss_cli.h"
+#include "common_private.h"
+
+extern struct sss_mutex sss_nss_mtx;
+
+#define SEC_FROM_MSEC(ms) ((ms) / 1000)
+#define NSEC_FROM_MSEC(ms) (((ms) % 1000) * 1000 * 1000)
+
+/* adopted from timersub() defined in /usr/include/sys/time.h */
+#define TIMESPECSUB(a, b, result) \
+ do { \
+ (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
+ (result)->tv_nsec = (a)->tv_nsec - (b)->tv_nsec; \
+ if ((result)->tv_nsec < 0) { \
+ --(result)->tv_sec; \
+ (result)->tv_nsec += 1000000000; \
+ } \
+ } while (0)
+
+#define TIMESPEC_TO_MS(ts) ( ((ts)->tv_sec * 1000) \
+ + ((ts)->tv_nsec) / (1000 * 1000) )
+
+static int sss_mt_timedlock(struct sss_mutex *m, struct timespec *endtime)
+{
+ int ret;
+
+ ret = pthread_mutex_timedlock(&m->mtx, endtime);
+ if (ret != 0) {
+ return ret;
+ }
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &m->old_cancel_state);
+
+ return 0;
+}
+
+int sss_nss_timedlock(unsigned int timeout_ms, int *time_left_ms)
+{
+ int ret;
+ int left;
+ struct timespec starttime;
+ struct timespec endtime;
+ struct timespec diff;
+
+ /* make sure there is no overrun when calculating the time left */
+ if (timeout_ms > INT_MAX) {
+ timeout_ms = INT_MAX;
+ }
+
+ ret = clock_gettime(CLOCK_REALTIME, &starttime);
+ if (ret != 0) {
+ return ret;
+ }
+ endtime.tv_sec = starttime.tv_sec + SEC_FROM_MSEC(timeout_ms);
+ endtime.tv_nsec = starttime.tv_nsec + NSEC_FROM_MSEC(timeout_ms);
+
+ ret = sss_mt_timedlock(&sss_nss_mtx, &endtime);
+
+ if (ret == 0) {
+ ret = clock_gettime(CLOCK_REALTIME, &endtime);
+ if (ret != 0) {
+ return ret;
+ }
+
+ if (timeout_ms == 0) {
+ *time_left_ms = 0;
+ } else {
+ TIMESPECSUB(&endtime, &starttime, &diff);
+ left = timeout_ms - TIMESPEC_TO_MS(&diff);
+ if (left <= 0) {
+ return EIO;
+ } else if (left > SSS_CLI_SOCKET_TIMEOUT) {
+ *time_left_ms = SSS_CLI_SOCKET_TIMEOUT;
+ } else {
+ *time_left_ms = left;
+ }
+ }
+ }
+
+ return ret;
+}
diff --git a/src/sss_client/idmap/sss_nss_ex.c b/src/sss_client/idmap/sss_nss_ex.c
new file mode 100644
index 0000000000000000000000000000000000000000..582d1373ec35305cf128e04fd3d705457d304789
--- /dev/null
+++ b/src/sss_client/idmap/sss_nss_ex.c
@@ -0,0 +1,402 @@
+/*
+ SSSD
+
+ Extended NSS Responder Interface
+
+ Authors:
+ Sumit Bose <sbose@redhat.com>
+
+ Copyright (C) 2017 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 <stdlib.h>
+#include <errno.h>
+
+#include <sys/param.h> /* for MIN() */
+
+#include "sss_client/sss_cli.h"
+#include "sss_client/nss_mc.h"
+#include "sss_client/nss_common.h"
+#include "sss_client/idmap/sss_nss_idmap.h"
+#include "sss_client/idmap/sss_nss_idmap_private.h"
+
+#ifndef discard_const
+#define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
+#endif
+
+struct sss_nss_initgr_rep {
+ gid_t *groups;
+ long int *ngroups;
+ long int *start;
+};
+
+struct nss_input {
+ union {
+ const char *name;
+ uid_t uid;
+ gid_t gid;
+ } input;
+ struct sss_cli_req_data rd;
+ enum sss_cli_command cmd;
+ union {
+ struct sss_nss_pw_rep pwrep;
+ struct sss_nss_gr_rep grrep;
+ struct sss_nss_initgr_rep initgrrep;
+ } result;
+};
+
+errno_t sss_nss_mc_get(struct nss_input *inp)
+{
+ switch(inp->cmd) {
+ case SSS_NSS_GETPWNAM:
+ return sss_nss_mc_getpwnam(inp->input.name, (inp->rd.len - 1),
+ inp->result.pwrep.result,
+ inp->result.pwrep.buffer,
+ inp->result.pwrep.buflen);
+ break;
+ case SSS_NSS_GETPWUID:
+ return sss_nss_mc_getpwuid(inp->input.uid,
+ inp->result.pwrep.result,
+ inp->result.pwrep.buffer,
+ inp->result.pwrep.buflen);
+ break;
+ case SSS_NSS_GETGRNAM:
+ return sss_nss_mc_getgrnam(inp->input.name, (inp->rd.len - 1),
+ inp->result.grrep.result,
+ inp->result.grrep.buffer,
+ inp->result.grrep.buflen);
+ break;
+ case SSS_NSS_GETGRGID:
+ return sss_nss_mc_getgrgid(inp->input.gid,
+ inp->result.grrep.result,
+ inp->result.grrep.buffer,
+ inp->result.grrep.buflen);
+ break;
+ case SSS_NSS_INITGR:
+ return sss_nss_mc_initgroups_dyn(inp->input.name, (inp->rd.len - 1),
+ -1 /* currently ignored */,
+ inp->result.initgrrep.start,
+ inp->result.initgrrep.ngroups,
+ &(inp->result.initgrrep.groups),
+ *(inp->result.initgrrep.ngroups));
+ break;
+ default:
+ return EINVAL;
+ }
+}
+
+int sss_get_ex(struct nss_input *inp, uint32_t flags, unsigned int timeout)
+{
+ uint8_t *repbuf = NULL;
+ size_t replen;
+ size_t len;
+ uint32_t num_results;
+ int ret;
+ int time_left;
+ int errnop;
+ size_t c;
+ gid_t *new_groups;
+ size_t idx;
+
+ ret = sss_nss_mc_get(inp);
+ switch (ret) {
+ case 0:
+ return 0;
+ case ERANGE:
+ return ERANGE;
+ case ENOENT:
+ /* fall through, we need to actively ask the parent
+ * if no entry is found */
+ break;
+ default:
+ /* if using the mmaped cache failed,
+ * fall back to socket based comms */
+ break;
+ }
+
+ sss_nss_timedlock(timeout, &time_left);
+
+ /* previous thread might already initialize entry in mmap cache */
+ ret = sss_nss_mc_get(inp);
+ switch (ret) {
+ case 0:
+ ret = 0;
+ goto out;
+ case ERANGE:
+ ret = ERANGE;
+ goto out;
+ case ENOENT:
+ /* fall through, we need to actively ask the parent
+ * if no entry is found */
+ break;
+ default:
+ /* if using the mmaped cache failed,
+ * fall back to socket based comms */
+ break;
+ }
+
+ ret = sss_nss_make_request_timeout(inp->cmd, &inp->rd, time_left,
+ &repbuf, &replen, &errnop);
+ if (ret != NSS_STATUS_SUCCESS) {
+ ret = errnop != 0 ? errnop : EIO;
+ goto out;
+ }
+
+ /* Get number of results from repbuf. */
+ SAFEALIGN_COPY_UINT32(&num_results, repbuf, NULL);
+
+ /* no results if not found */
+ if (num_results == 0) {
+ ret = ENOENT;
+ goto out;
+ }
+
+ if (inp->cmd == SSS_NSS_INITGR) {
+ if ((*(inp->result.initgrrep.ngroups) - *(inp->result.initgrrep.start))
+ < num_results) {
+ new_groups = realloc(inp->result.initgrrep.groups,
+ (num_results + *(inp->result.initgrrep.start))
+ * sizeof(gid_t));
+ if (new_groups == NULL) {
+ ret = ENOMEM;
+ goto out;
+ }
+
+ inp->result.initgrrep.groups = new_groups;
+ }
+ *(inp->result.initgrrep.ngroups) = num_results
+ + *(inp->result.initgrrep.start);
+
+ idx = 2 * sizeof(uint32_t);
+ for (c = 0; c < num_results; c++) {
+ SAFEALIGN_COPY_UINT32(
+ &(inp->result.initgrrep.groups[*(inp->result.initgrrep.start)]),
+ repbuf + idx, &idx);
+ *(inp->result.initgrrep.start) += 1;
+ }
+
+ ret = 0;
+ goto out;
+ }
+
+ /* only 1 result is accepted for this function */
+ if (num_results != 1) {
+ ret = EBADMSG;
+ goto out;
+ }
+
+ len = replen - 8;
+ if (inp->cmd == SSS_NSS_GETPWNAM || inp->cmd == SSS_NSS_GETPWUID) {
+ ret = sss_nss_getpw_readrep(&(inp->result.pwrep), repbuf+8, &len);
+ } else if (inp->cmd == SSS_NSS_GETGRNAM || inp->cmd == SSS_NSS_GETGRGID) {
+ ret = sss_nss_getgr_readrep(&(inp->result.grrep), repbuf+8, &len);
+ } else {
+ ret = EINVAL;
+ goto out;
+ }
+ if (ret) {
+ goto out;
+ }
+
+ if (len == 0) {
+ /* no extra data */
+ ret = 0;
+ goto out;
+ }
+
+out:
+ free(repbuf);
+
+ sss_nss_unlock();
+ return ret;
+}
+
+int sss_nss_getpwnam_timeout(const char *name, struct passwd *pwd,
+ char *buffer, size_t buflen,
+ struct passwd **result,
+ uint32_t flags, unsigned int timeout)
+{
+ int ret;
+ struct nss_input inp = {
+ .input.name = name,
+ .cmd = SSS_NSS_GETPWNAM,
+ .rd.data = name,
+ .result.pwrep.result = pwd,
+ .result.pwrep.buffer = buffer,
+ .result.pwrep.buflen = buflen};
+
+ if (buffer == NULL || buflen == 0) {
+ return ERANGE;
+ }
+
+ ret = sss_strnlen(name, SSS_NAME_MAX, &inp.rd.len);
+ if (ret != 0) {
+ return EINVAL;
+ }
+ inp.rd.len++;
+
+ *result = NULL;
+
+ ret = sss_get_ex(&inp, flags, timeout);
+ if (ret == 0) {
+ *result = inp.result.pwrep.result;
+ }
+ return ret;
+}
+
+int sss_nss_getpwuid_timeout(uid_t uid, struct passwd *pwd,
+ char *buffer, size_t buflen,
+ struct passwd **result,
+ uint32_t flags, unsigned int timeout)
+{
+ int ret;
+ uint32_t user_uid = uid;
+ struct nss_input inp = {
+ .input.uid = uid,
+ .cmd = SSS_NSS_GETPWUID,
+ .rd.len = sizeof(uint32_t),
+ .rd.data = &user_uid,
+ .result.pwrep.result = pwd,
+ .result.pwrep.buffer = buffer,
+ .result.pwrep.buflen = buflen};
+
+ if (buffer == NULL || buflen == 0) {
+ return ERANGE;
+ }
+
+ *result = NULL;
+
+ ret = sss_get_ex(&inp, flags, timeout);
+ if (ret == 0) {
+ *result = inp.result.pwrep.result;
+ }
+ return ret;
+}
+
+int sss_nss_getgrnam_timeout(const char *name, struct group *grp,
+ char *buffer, size_t buflen, struct group **result,
+ uint32_t flags, unsigned int timeout)
+{
+ int ret;
+ struct nss_input inp = {
+ .input.name = name,
+ .cmd = SSS_NSS_GETGRNAM,
+ .rd.data = name,
+ .result.grrep.result = grp,
+ .result.grrep.buffer = buffer,
+ .result.grrep.buflen = buflen};
+
+ if (buffer == NULL || buflen == 0) {
+ return ERANGE;
+ }
+
+ ret = sss_strnlen(name, SSS_NAME_MAX, &inp.rd.len);
+ if (ret != 0) {
+ return EINVAL;
+ }
+ inp.rd.len++;
+
+ *result = NULL;
+
+ ret = sss_get_ex(&inp, flags, timeout);
+ if (ret == 0) {
+ *result = inp.result.grrep.result;
+ }
+ return ret;
+}
+
+int sss_nss_getgrgid_timeout(gid_t gid, struct group *grp,
+ char *buffer, size_t buflen, struct group **result,
+ uint32_t flags, unsigned int timeout)
+{
+ int ret;
+ uint32_t group_gid = gid;
+ struct nss_input inp = {
+ .input.gid = gid,
+ .cmd = SSS_NSS_GETGRGID,
+ .rd.len = sizeof(uint32_t),
+ .rd.data = &group_gid,
+ .result.grrep.result = grp,
+ .result.grrep.buffer = buffer,
+ .result.grrep.buflen = buflen};
+
+ if (buffer == NULL || buflen == 0) {
+ return ERANGE;
+ }
+
+ *result = NULL;
+
+ ret = sss_get_ex(&inp, flags, timeout);
+ if (ret == 0) {
+ *result = inp.result.grrep.result;
+ }
+ return ret;
+}
+
+int sss_nss_getgrouplist_timeout(const char *name, gid_t group,
+ gid_t *groups, int *ngroups,
+ uint32_t flags, unsigned int timeout)
+{
+ int ret;
+ gid_t *new_groups;
+ long int new_ngroups;
+ long int start = 1;
+ struct nss_input inp = {
+ .input.name = name,
+ .cmd = SSS_NSS_INITGR,
+ .rd.data = name};
+
+ if (groups == NULL || ngroups == NULL || *ngroups == 0) {
+ return EINVAL;
+ }
+
+ ret = sss_strnlen(name, SSS_NAME_MAX, &inp.rd.len);
+ if (ret != 0) {
+ return ret;
+ }
+ inp.rd.len++;
+
+ new_ngroups = MAX(1, *ngroups);
+ new_groups = malloc(new_ngroups * sizeof(gid_t));
+ if (new_groups == NULL) {
+ free(discard_const(inp.rd.data));
+ return ENOMEM;
+ }
+ new_groups[0] = group;
+
+ inp.result.initgrrep.groups = new_groups,
+ inp.result.initgrrep.ngroups = &new_ngroups;
+ inp.result.initgrrep.start = &start;
+
+
+ ret = sss_get_ex(&inp, flags, timeout);
+ free(discard_const(inp.rd.data));
+ if (ret != 0) {
+ free(new_groups);
+ return ret;
+ }
+
+ memcpy(groups, new_groups, MIN(*ngroups, start) * sizeof(gid_t));
+ free(new_groups);
+
+ if (start > *ngroups) {
+ ret = ERANGE;
+ } else {
+ ret = 0;
+ }
+ *ngroups = start;
+
+ return ret;
+}
diff --git a/src/sss_client/idmap/sss_nss_idmap.exports b/src/sss_client/idmap/sss_nss_idmap.exports
index 49dac6fc9351b0ca98cd46e83b85ec8ef0075a0d..788d05ecc3bd56fa88e68a98b9c8096cf7140a09 100644
--- a/src/sss_client/idmap/sss_nss_idmap.exports
+++ b/src/sss_client/idmap/sss_nss_idmap.exports
@@ -31,3 +31,13 @@ SSS_NSS_IDMAP_0.3.0 {
global:
sss_nss_getlistbycert;
} SSS_NSS_IDMAP_0.2.0;
+
+SSS_NSS_IDMAP_0.4.0 {
+ # public functions
+ global:
+ sss_nss_getpwnam_timeout;
+ sss_nss_getpwuid_timeout;
+ sss_nss_getgrnam_timeout;
+ sss_nss_getgrgid_timeout;
+ sss_nss_getgrouplist_timeout;
+} SSS_NSS_IDMAP_0.3.0;
diff --git a/src/sss_client/idmap/sss_nss_idmap.h b/src/sss_client/idmap/sss_nss_idmap.h
index cbf19479ff9ec6e0d6e07e1f7e48a1571e147740..2334b6cb3fb8ef62e4ce3a7187c7affaeaa034e7 100644
--- a/src/sss_client/idmap/sss_nss_idmap.h
+++ b/src/sss_client/idmap/sss_nss_idmap.h
@@ -26,6 +26,9 @@
#define SSS_NSS_IDMAP_H_
#include <stdint.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
/**
* Object types
@@ -159,4 +162,136 @@ int sss_nss_getlistbycert(const char *cert, char ***fq_name,
* @param[in] kv_list Key-value list returned by sss_nss_getorigbyname().
*/
void sss_nss_free_kv(struct sss_nss_kv *kv_list);
+
+/**
+ * Flags to control the behavior and the results for sss_*_ex() calls
+ */
+
+#define SSS_NSS_EX_FLAG_NO_FLAGS 0
+
+#ifdef IPA_389DS_PLUGIN_HELPER_CALLS
+
+/**
+ * @brief Return user information based on the user name
+ *
+ * @param[in] name same as for getpwnam_r(3)
+ * @param[in] pwd same as for getpwnam_r(3)
+ * @param[in] buffer same as for getpwnam_r(3)
+ * @param[in] buflen same as for getpwnam_r(3)
+ * @param[out] result same as for getpwnam_r(3)
+ * @param[in] flags flags to control the behavior and the results of the
+ * call
+ * @param[in] timeout timeout in milliseconds
+ *
+ * @return
+ * - 0:
+ * - ENOENT: no user with the given name found
+ * - ERANGE: Insufficient buffer space supplied
+ * - ETIME: request timed out but was send to SSSD
+ * - ETIMEDOUT: request timed out but was not send to SSSD
+ */
+int sss_nss_getpwnam_timeout(const char *name, struct passwd *pwd,
+ char *buffer, size_t buflen,
+ struct passwd **result,
+ uint32_t flags, unsigned int timeout);
+
+/**
+ * @brief Return user information based on the user uid
+ *
+ * @param[in] uid same as for getpwuid_r(3)
+ * @param[in] pwd same as for getpwuid_r(3)
+ * @param[in] buffer same as for getpwuid_r(3)
+ * @param[in] buflen same as for getpwuid_r(3)
+ * @param[out] result same as for getpwuid_r(3)
+ * @param[in] flags flags to control the behavior and the results of the
+ * call
+ * @param[in] timeout timeout in milliseconds
+ *
+ * @return
+ * - 0:
+ * - ENOENT: no user with the given uid found
+ * - ERANGE: Insufficient buffer space supplied
+ * - ETIME: request timed out but was send to SSSD
+ * - ETIMEDOUT: request timed out but was not send to SSSD
+ */
+int sss_nss_getpwuid_timeout(uid_t uid, struct passwd *pwd,
+ char *buffer, size_t buflen,
+ struct passwd **result,
+ uint32_t flags, unsigned int timeout);
+
+/**
+ * @brief Return group information based on the group name
+ *
+ * @param[in] name same as for getgrnam_r(3)
+ * @param[in] pwd same as for getgrnam_r(3)
+ * @param[in] buffer same as for getgrnam_r(3)
+ * @param[in] buflen same as for getgrnam_r(3)
+ * @param[out] result same as for getgrnam_r(3)
+ * @param[in] flags flags to control the behavior and the results of the
+ * call
+ * @param[in] timeout timeout in milliseconds
+ *
+ * @return
+ * - 0:
+ * - ENOENT: no group with the given name found
+ * - ERANGE: Insufficient buffer space supplied
+ * - ETIME: request timed out but was send to SSSD
+ * - ETIMEDOUT: request timed out but was not send to SSSD
+ */
+int sss_nss_getgrnam_timeout(const char *name, struct group *grp,
+ char *buffer, size_t buflen, struct group **result,
+ uint32_t flags, unsigned int timeout);
+
+/**
+ * @brief Return group information based on the group gid
+ *
+ * @param[in] gid same as for getgrgid_r(3)
+ * @param[in] pwd same as for getgrgid_r(3)
+ * @param[in] buffer same as for getgrgid_r(3)
+ * @param[in] buflen same as for getgrgid_r(3)
+ * @param[out] result same as for getgrgid_r(3)
+ * @param[in] flags flags to control the behavior and the results of the
+ * call
+ * @param[in] timeout timeout in milliseconds
+ *
+ * @return
+ * - 0:
+ * - ENOENT: no group with the given gid found
+ * - ERANGE: Insufficient buffer space supplied
+ * - ETIME: request timed out but was send to SSSD
+ * - ETIMEDOUT: request timed out but was not send to SSSD
+ */
+int sss_nss_getgrgid_timeout(gid_t gid, struct group *grp,
+ char *buffer, size_t buflen, struct group **result,
+ uint32_t flags, unsigned int timeout);
+
+/**
+ * @brief Return a list of groups to which a user belongs
+ *
+ * @param[in] name name of the user
+ * @param[in] group same as second argument of getgrouplist(3)
+ * @param[in] groups array of gid_t of size ngroups, will be filled
+ * with GIDs of groups the user belongs to
+ * @param[in,out] ngroups size of the groups array on input. On output it
+ * will contain the actual number of groups the
+ * user belongs to. With a return value of 0 the
+ * groups array was large enough to hold all group.
+ * With a return valu of ERANGE the array was not
+ * large enough and ngroups will have the needed
+ * size.
+ * @param[in] flags flags to control the behavior and the results of
+ * the call
+ * @param[in] timeout timeout in milliseconds
+ *
+ * @return
+ * - 0: success
+ * - ENOENT: no user with the given name found
+ * - ERANGE: Insufficient buffer space supplied
+ * - ETIME: request timed out but was send to SSSD
+ * - ETIMEDOUT: request timed out but was not send to SSSD
+ */
+int sss_nss_getgrouplist_timeout(const char *name, gid_t group,
+ gid_t *groups, int *ngroups,
+ uint32_t flags, unsigned int timeout);
+#endif /* IPA_389DS_PLUGIN_HELPER_CALLS */
#endif /* SSS_NSS_IDMAP_H_ */
diff --git a/src/sss_client/idmap/sss_nss_idmap_private.h b/src/sss_client/idmap/sss_nss_idmap_private.h
new file mode 100644
index 0000000000000000000000000000000000000000..afcd8e355981b9a2dc29a62bab143756b39ed654
--- /dev/null
+++ b/src/sss_client/idmap/sss_nss_idmap_private.h
@@ -0,0 +1,30 @@
+/*
+ SSSD
+
+ NSS Responder ID-mapping interface - private calls
+
+ Authors:
+ Sumit Bose <sbose@redhat.com>
+
+ Copyright (C) 2017 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 SSS_NSS_IDMAP_PRIVATE_H_
+#define SSS_NSS_IDMAP_PRIVATE_H_
+
+int sss_nss_timedlock(unsigned int timeout_ms, int *time_left_ms);
+
+#endif /* SSS_NSS_IDMAP_PRIVATE_H_ */
--
2.14.3

View File

@ -0,0 +1,605 @@
From cf93f7c2f2031078bbbff095dae01eb4f8deff85 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Wed, 11 Oct 2017 14:54:54 +0200
Subject: [PATCH 04/11] NSS: add *_EX version of some requests
To be able to send the flags to the SSSD responder new request types
with an _EX postfix are added which expect and additional 32bit flag
field after the name or the id of the requested object.
Related to https://pagure.io/SSSD/sssd/issue/2478
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
---
src/responder/nss/nss_cmd.c | 76 +++++++++++++++++++++-----
src/responder/nss/nss_protocol.c | 81 ++++++++++++++++++++++++++++
src/responder/nss/nss_protocol.h | 8 +++
src/sss_client/idmap/sss_nss_ex.c | 110 +++++++++++++++++++++++++++-----------
src/sss_client/sss_cli.h | 7 +++
5 files changed, 237 insertions(+), 45 deletions(-)
diff --git a/src/responder/nss/nss_cmd.c b/src/responder/nss/nss_cmd.c
index ebf66dfe0444b83aed20d58d36ddf70d2f4fa1f9..974eaccc93cea3a330007735676da69eb9b84141 100644
--- a/src/responder/nss/nss_cmd.c
+++ b/src/responder/nss/nss_cmd.c
@@ -54,6 +54,7 @@ static void nss_getby_done(struct tevent_req *subreq);
static void nss_getlistby_done(struct tevent_req *subreq);
static errno_t nss_getby_name(struct cli_ctx *cli_ctx,
+ bool ex_version,
enum cache_req_type type,
const char **attrs,
enum sss_mc_type memcache,
@@ -64,6 +65,7 @@ static errno_t nss_getby_name(struct cli_ctx *cli_ctx,
struct tevent_req *subreq;
const char *rawname;
errno_t ret;
+ uint32_t flags = 0;
cmd_ctx = nss_cmd_ctx_create(cli_ctx, cli_ctx, type, fill_fn);
if (cmd_ctx == NULL) {
@@ -71,7 +73,11 @@ static errno_t nss_getby_name(struct cli_ctx *cli_ctx,
goto done;
}
- ret = nss_protocol_parse_name(cli_ctx, &rawname);
+ if (ex_version) {
+ ret = nss_protocol_parse_name_ex(cli_ctx, &rawname, &flags);
+ } else {
+ ret = nss_protocol_parse_name(cli_ctx, &rawname);
+ }
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "Invalid request message!\n");
goto done;
@@ -108,6 +114,7 @@ done:
}
static errno_t nss_getby_id(struct cli_ctx *cli_ctx,
+ bool ex_version,
enum cache_req_type type,
const char **attrs,
enum sss_mc_type memcache,
@@ -118,6 +125,7 @@ static errno_t nss_getby_id(struct cli_ctx *cli_ctx,
struct tevent_req *subreq;
uint32_t id;
errno_t ret;
+ uint32_t flags = 0;
cmd_ctx = nss_cmd_ctx_create(cli_ctx, cli_ctx, type, fill_fn);
if (cmd_ctx == NULL) {
@@ -125,7 +133,11 @@ static errno_t nss_getby_id(struct cli_ctx *cli_ctx,
goto done;
}
- ret = nss_protocol_parse_id(cli_ctx, &id);
+ if (ex_version) {
+ ret = nss_protocol_parse_id_ex(cli_ctx, &id, &flags);
+ } else {
+ ret = nss_protocol_parse_id(cli_ctx, &id);
+ }
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "Invalid request message!\n");
goto done;
@@ -766,14 +778,26 @@ static errno_t nss_endent(struct cli_ctx *cli_ctx,
static errno_t nss_cmd_getpwnam(struct cli_ctx *cli_ctx)
{
- return nss_getby_name(cli_ctx, CACHE_REQ_USER_BY_NAME, NULL, SSS_MC_PASSWD,
- nss_protocol_fill_pwent);
+ return nss_getby_name(cli_ctx, false, CACHE_REQ_USER_BY_NAME, NULL,
+ SSS_MC_PASSWD, nss_protocol_fill_pwent);
}
static errno_t nss_cmd_getpwuid(struct cli_ctx *cli_ctx)
{
- return nss_getby_id(cli_ctx, CACHE_REQ_USER_BY_ID, NULL, SSS_MC_PASSWD,
- nss_protocol_fill_pwent);
+ return nss_getby_id(cli_ctx, false, CACHE_REQ_USER_BY_ID, NULL,
+ SSS_MC_PASSWD, nss_protocol_fill_pwent);
+}
+
+static errno_t nss_cmd_getpwnam_ex(struct cli_ctx *cli_ctx)
+{
+ return nss_getby_name(cli_ctx, true, CACHE_REQ_USER_BY_NAME, NULL,
+ SSS_MC_PASSWD, nss_protocol_fill_pwent);
+}
+
+static errno_t nss_cmd_getpwuid_ex(struct cli_ctx *cli_ctx)
+{
+ return nss_getby_id(cli_ctx, true, CACHE_REQ_USER_BY_ID, NULL,
+ SSS_MC_PASSWD, nss_protocol_fill_pwent);
}
static errno_t nss_cmd_setpwent(struct cli_ctx *cli_ctx)
@@ -809,16 +833,29 @@ static errno_t nss_cmd_endpwent(struct cli_ctx *cli_ctx)
static errno_t nss_cmd_getgrnam(struct cli_ctx *cli_ctx)
{
- return nss_getby_name(cli_ctx, CACHE_REQ_GROUP_BY_NAME, NULL, SSS_MC_GROUP,
- nss_protocol_fill_grent);
+ return nss_getby_name(cli_ctx, false, CACHE_REQ_GROUP_BY_NAME, NULL,
+ SSS_MC_GROUP, nss_protocol_fill_grent);
}
static errno_t nss_cmd_getgrgid(struct cli_ctx *cli_ctx)
{
- return nss_getby_id(cli_ctx, CACHE_REQ_GROUP_BY_ID, NULL, SSS_MC_GROUP,
- nss_protocol_fill_grent);
+ return nss_getby_id(cli_ctx, false, CACHE_REQ_GROUP_BY_ID, NULL,
+ SSS_MC_GROUP, nss_protocol_fill_grent);
}
+static errno_t nss_cmd_getgrnam_ex(struct cli_ctx *cli_ctx)
+{
+ return nss_getby_name(cli_ctx, true, CACHE_REQ_GROUP_BY_NAME, NULL,
+ SSS_MC_GROUP, nss_protocol_fill_grent);
+}
+
+static errno_t nss_cmd_getgrgid_ex(struct cli_ctx *cli_ctx)
+{
+ return nss_getby_id(cli_ctx, true, CACHE_REQ_GROUP_BY_ID, NULL,
+ SSS_MC_GROUP, nss_protocol_fill_grent);
+}
+
+
static errno_t nss_cmd_setgrent(struct cli_ctx *cli_ctx)
{
struct nss_ctx *nss_ctx;
@@ -852,7 +889,13 @@ static errno_t nss_cmd_endgrent(struct cli_ctx *cli_ctx)
static errno_t nss_cmd_initgroups(struct cli_ctx *cli_ctx)
{
- return nss_getby_name(cli_ctx, CACHE_REQ_INITGROUPS, NULL,
+ return nss_getby_name(cli_ctx, false, CACHE_REQ_INITGROUPS, NULL,
+ SSS_MC_INITGROUPS, nss_protocol_fill_initgr);
+}
+
+static errno_t nss_cmd_initgroups_ex(struct cli_ctx *cli_ctx)
+{
+ return nss_getby_name(cli_ctx, true, CACHE_REQ_INITGROUPS, NULL,
SSS_MC_INITGROUPS, nss_protocol_fill_initgr);
}
@@ -943,7 +986,7 @@ static errno_t nss_cmd_getsidbyname(struct cli_ctx *cli_ctx)
{
const char *attrs[] = { SYSDB_SID_STR, NULL };
- return nss_getby_name(cli_ctx, CACHE_REQ_OBJECT_BY_NAME, attrs,
+ return nss_getby_name(cli_ctx, false, CACHE_REQ_OBJECT_BY_NAME, attrs,
SSS_MC_NONE, nss_protocol_fill_sid);
}
@@ -951,7 +994,7 @@ static errno_t nss_cmd_getsidbyid(struct cli_ctx *cli_ctx)
{
const char *attrs[] = { SYSDB_SID_STR, NULL };
- return nss_getby_id(cli_ctx, CACHE_REQ_OBJECT_BY_ID, attrs,
+ return nss_getby_id(cli_ctx, false, CACHE_REQ_OBJECT_BY_ID, attrs,
SSS_MC_NONE, nss_protocol_fill_sid);
}
@@ -1006,7 +1049,7 @@ static errno_t nss_cmd_getorigbyname(struct cli_ctx *cli_ctx)
attrs = defattrs;
}
- return nss_getby_name(cli_ctx, CACHE_REQ_OBJECT_BY_NAME, attrs,
+ return nss_getby_name(cli_ctx, false, CACHE_REQ_OBJECT_BY_NAME, attrs,
SSS_MC_NONE, nss_protocol_fill_orig);
}
@@ -1051,6 +1094,11 @@ struct sss_cmd_table *get_nss_cmds(void)
{ SSS_NSS_GETORIGBYNAME, nss_cmd_getorigbyname },
{ SSS_NSS_GETNAMEBYCERT, nss_cmd_getnamebycert },
{ SSS_NSS_GETLISTBYCERT, nss_cmd_getlistbycert },
+ { SSS_NSS_GETPWNAM_EX, nss_cmd_getpwnam_ex },
+ { SSS_NSS_GETPWUID_EX, nss_cmd_getpwuid_ex },
+ { SSS_NSS_GETGRNAM_EX, nss_cmd_getgrnam_ex },
+ { SSS_NSS_GETGRGID_EX, nss_cmd_getgrgid_ex },
+ { SSS_NSS_INITGR_EX, nss_cmd_initgroups_ex },
{ SSS_CLI_NULL, NULL }
};
diff --git a/src/responder/nss/nss_protocol.c b/src/responder/nss/nss_protocol.c
index 06fc4d00a7877a7990402f4f2633ddc0bd640b41..17bfc4f4e71960a72e9e04622eac95b94a865ec7 100644
--- a/src/responder/nss/nss_protocol.c
+++ b/src/responder/nss/nss_protocol.c
@@ -133,6 +133,61 @@ nss_protocol_parse_name(struct cli_ctx *cli_ctx, const char **_rawname)
return EOK;
}
+errno_t
+nss_protocol_parse_name_ex(struct cli_ctx *cli_ctx, const char **_rawname,
+ uint32_t *_flags)
+{
+ struct cli_protocol *pctx;
+ const char *rawname;
+ uint8_t *body;
+ size_t blen;
+ uint8_t *p;
+ uint32_t flags;
+
+ pctx = talloc_get_type(cli_ctx->protocol_ctx, struct cli_protocol);
+
+ sss_packet_get_body(pctx->creq->in, &body, &blen);
+
+ if (blen < 1 + sizeof(uint32_t)) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Body too short!\n");
+ return EINVAL;
+ }
+
+ /* If first argument not terminated fail. */
+ if (body[blen - 1 - sizeof(uint32_t)] != '\0') {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Body is not null terminated!\n");
+ return EINVAL;
+ }
+
+ p = memchr(body, '\0', blen);
+
+ /* If the body isn't valid UTF-8, fail */
+ if (!sss_utf8_check(body, (p - body))) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "First argument is not UTF-8 string!\n");
+ return EINVAL;
+ }
+
+ rawname = (const char *)body;
+ if (rawname[0] == '\0') {
+ DEBUG(SSSDBG_CRIT_FAILURE, "An empty name was provided!\n");
+ return EINVAL;
+ }
+
+ p++;
+ if ((p - body) + sizeof(uint32_t) != blen) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Body has unexpected size!\n");
+ return EINVAL;
+ }
+
+ SAFEALIGN_COPY_UINT32(&flags, p, NULL);
+ p += sizeof(uint32_t);
+
+ *_rawname = rawname;
+ *_flags = flags;
+
+ return EOK;
+}
+
errno_t
nss_protocol_parse_id(struct cli_ctx *cli_ctx, uint32_t *_id)
{
@@ -156,6 +211,32 @@ nss_protocol_parse_id(struct cli_ctx *cli_ctx, uint32_t *_id)
return EOK;
}
+errno_t
+nss_protocol_parse_id_ex(struct cli_ctx *cli_ctx, uint32_t *_id,
+ uint32_t *_flags)
+{
+ struct cli_protocol *pctx;
+ uint8_t *body;
+ size_t blen;
+ uint32_t id;
+ uint32_t flags;
+
+ pctx = talloc_get_type(cli_ctx->protocol_ctx, struct cli_protocol);
+
+ sss_packet_get_body(pctx->creq->in, &body, &blen);
+
+ if (blen != 2 * sizeof(uint32_t)) {
+ return EINVAL;
+ }
+
+ SAFEALIGN_COPY_UINT32(&id, body, NULL);
+ SAFEALIGN_COPY_UINT32(&flags, body + sizeof(uint32_t), NULL);
+
+ *_id = id;
+
+ return EOK;
+}
+
errno_t
nss_protocol_parse_limit(struct cli_ctx *cli_ctx, uint32_t *_limit)
{
diff --git a/src/responder/nss/nss_protocol.h b/src/responder/nss/nss_protocol.h
index 417b0891615dcb8771d49f7b2f4d276342ca3150..ca5b040237dc18acdca9a7a3a7a7dbb64265aa95 100644
--- a/src/responder/nss/nss_protocol.h
+++ b/src/responder/nss/nss_protocol.h
@@ -88,9 +88,17 @@ void nss_protocol_reply(struct cli_ctx *cli_ctx,
errno_t
nss_protocol_parse_name(struct cli_ctx *cli_ctx, const char **_rawname);
+errno_t
+nss_protocol_parse_name_ex(struct cli_ctx *cli_ctx, const char **_rawname,
+ uint32_t *_flags);
+
errno_t
nss_protocol_parse_id(struct cli_ctx *cli_ctx, uint32_t *_id);
+errno_t
+nss_protocol_parse_id_ex(struct cli_ctx *cli_ctx, uint32_t *_id,
+ uint32_t *_flags);
+
errno_t
nss_protocol_parse_limit(struct cli_ctx *cli_ctx, uint32_t *_limit);
diff --git a/src/sss_client/idmap/sss_nss_ex.c b/src/sss_client/idmap/sss_nss_ex.c
index 582d1373ec35305cf128e04fd3d705457d304789..dc7610a4e528b5126f0d25d84cd3c1a22f683b75 100644
--- a/src/sss_client/idmap/sss_nss_ex.c
+++ b/src/sss_client/idmap/sss_nss_ex.c
@@ -61,31 +61,37 @@ errno_t sss_nss_mc_get(struct nss_input *inp)
{
switch(inp->cmd) {
case SSS_NSS_GETPWNAM:
- return sss_nss_mc_getpwnam(inp->input.name, (inp->rd.len - 1),
+ case SSS_NSS_GETPWNAM_EX:
+ return sss_nss_mc_getpwnam(inp->input.name, strlen(inp->input.name),
inp->result.pwrep.result,
inp->result.pwrep.buffer,
inp->result.pwrep.buflen);
break;
case SSS_NSS_GETPWUID:
+ case SSS_NSS_GETPWUID_EX:
return sss_nss_mc_getpwuid(inp->input.uid,
inp->result.pwrep.result,
inp->result.pwrep.buffer,
inp->result.pwrep.buflen);
break;
case SSS_NSS_GETGRNAM:
- return sss_nss_mc_getgrnam(inp->input.name, (inp->rd.len - 1),
+ case SSS_NSS_GETGRNAM_EX:
+ return sss_nss_mc_getgrnam(inp->input.name, strlen(inp->input.name),
inp->result.grrep.result,
inp->result.grrep.buffer,
inp->result.grrep.buflen);
break;
case SSS_NSS_GETGRGID:
+ case SSS_NSS_GETGRGID_EX:
return sss_nss_mc_getgrgid(inp->input.gid,
inp->result.grrep.result,
inp->result.grrep.buffer,
inp->result.grrep.buflen);
break;
case SSS_NSS_INITGR:
- return sss_nss_mc_initgroups_dyn(inp->input.name, (inp->rd.len - 1),
+ case SSS_NSS_INITGR_EX:
+ return sss_nss_mc_initgroups_dyn(inp->input.name,
+ strlen(inp->input.name),
-1 /* currently ignored */,
inp->result.initgrrep.start,
inp->result.initgrrep.ngroups,
@@ -163,7 +169,7 @@ int sss_get_ex(struct nss_input *inp, uint32_t flags, unsigned int timeout)
goto out;
}
- if (inp->cmd == SSS_NSS_INITGR) {
+ if (inp->cmd == SSS_NSS_INITGR || inp->cmd == SSS_NSS_INITGR_EX) {
if ((*(inp->result.initgrrep.ngroups) - *(inp->result.initgrrep.start))
< num_results) {
new_groups = realloc(inp->result.initgrrep.groups,
@@ -198,15 +204,24 @@ int sss_get_ex(struct nss_input *inp, uint32_t flags, unsigned int timeout)
}
len = replen - 8;
- if (inp->cmd == SSS_NSS_GETPWNAM || inp->cmd == SSS_NSS_GETPWUID) {
+
+ switch(inp->cmd) {
+ case SSS_NSS_GETPWNAM:
+ case SSS_NSS_GETPWUID:
+ case SSS_NSS_GETPWNAM_EX:
+ case SSS_NSS_GETPWUID_EX:
ret = sss_nss_getpw_readrep(&(inp->result.pwrep), repbuf+8, &len);
- } else if (inp->cmd == SSS_NSS_GETGRNAM || inp->cmd == SSS_NSS_GETGRGID) {
+ break;
+ case SSS_NSS_GETGRNAM:
+ case SSS_NSS_GETGRGID:
+ case SSS_NSS_GETGRNAM_EX:
+ case SSS_NSS_GETGRGID_EX:
ret = sss_nss_getgr_readrep(&(inp->result.grrep), repbuf+8, &len);
- } else {
+ break;
+ default:
ret = EINVAL;
- goto out;
}
- if (ret) {
+ if (ret != 0) {
goto out;
}
@@ -223,6 +238,39 @@ out:
return ret;
}
+static int make_name_flag_req_data(const char *name, uint32_t flags,
+ struct sss_cli_req_data *rd)
+{
+ size_t len;
+ size_t name_len;
+ uint8_t *data;
+ int ret;
+
+ if (name == NULL) {
+ return EINVAL;
+ }
+
+ ret = sss_strnlen(name, SSS_NAME_MAX, &name_len);
+ if (ret != 0) {
+ return ret;
+ }
+ name_len++;
+
+ len = name_len + sizeof(uint32_t);
+ data = malloc(len);
+ if (data == NULL) {
+ return ENOMEM;
+ }
+
+ memcpy(data, name, name_len);
+ SAFEALIGN_COPY_UINT32(data + name_len, &flags, NULL);
+
+ rd->len = len;
+ rd->data = data;
+
+ return 0;
+}
+
int sss_nss_getpwnam_timeout(const char *name, struct passwd *pwd,
char *buffer, size_t buflen,
struct passwd **result,
@@ -231,8 +279,7 @@ int sss_nss_getpwnam_timeout(const char *name, struct passwd *pwd,
int ret;
struct nss_input inp = {
.input.name = name,
- .cmd = SSS_NSS_GETPWNAM,
- .rd.data = name,
+ .cmd = SSS_NSS_GETPWNAM_EX,
.result.pwrep.result = pwd,
.result.pwrep.buffer = buffer,
.result.pwrep.buflen = buflen};
@@ -241,15 +288,15 @@ int sss_nss_getpwnam_timeout(const char *name, struct passwd *pwd,
return ERANGE;
}
- ret = sss_strnlen(name, SSS_NAME_MAX, &inp.rd.len);
+ ret = make_name_flag_req_data(name, flags, &inp.rd);
if (ret != 0) {
- return EINVAL;
+ return ret;
}
- inp.rd.len++;
*result = NULL;
ret = sss_get_ex(&inp, flags, timeout);
+ free(discard_const(inp.rd.data));
if (ret == 0) {
*result = inp.result.pwrep.result;
}
@@ -262,12 +309,12 @@ int sss_nss_getpwuid_timeout(uid_t uid, struct passwd *pwd,
uint32_t flags, unsigned int timeout)
{
int ret;
- uint32_t user_uid = uid;
+ uint32_t req_data[2];
struct nss_input inp = {
.input.uid = uid,
- .cmd = SSS_NSS_GETPWUID,
- .rd.len = sizeof(uint32_t),
- .rd.data = &user_uid,
+ .cmd = SSS_NSS_GETPWUID_EX,
+ .rd.len = 2 * sizeof(uint32_t),
+ .rd.data = &req_data,
.result.pwrep.result = pwd,
.result.pwrep.buffer = buffer,
.result.pwrep.buflen = buflen};
@@ -276,6 +323,8 @@ int sss_nss_getpwuid_timeout(uid_t uid, struct passwd *pwd,
return ERANGE;
}
+ SAFEALIGN_COPY_UINT32(&req_data[0], &uid, NULL);
+ SAFEALIGN_COPY_UINT32(&req_data[1], &flags, NULL);
*result = NULL;
ret = sss_get_ex(&inp, flags, timeout);
@@ -292,8 +341,7 @@ int sss_nss_getgrnam_timeout(const char *name, struct group *grp,
int ret;
struct nss_input inp = {
.input.name = name,
- .cmd = SSS_NSS_GETGRNAM,
- .rd.data = name,
+ .cmd = SSS_NSS_GETGRNAM_EX,
.result.grrep.result = grp,
.result.grrep.buffer = buffer,
.result.grrep.buflen = buflen};
@@ -302,15 +350,15 @@ int sss_nss_getgrnam_timeout(const char *name, struct group *grp,
return ERANGE;
}
- ret = sss_strnlen(name, SSS_NAME_MAX, &inp.rd.len);
+ ret = make_name_flag_req_data(name, flags, &inp.rd);
if (ret != 0) {
- return EINVAL;
+ return ret;
}
- inp.rd.len++;
*result = NULL;
ret = sss_get_ex(&inp, flags, timeout);
+ free(discard_const(inp.rd.data));
if (ret == 0) {
*result = inp.result.grrep.result;
}
@@ -322,12 +370,12 @@ int sss_nss_getgrgid_timeout(gid_t gid, struct group *grp,
uint32_t flags, unsigned int timeout)
{
int ret;
- uint32_t group_gid = gid;
+ uint32_t req_data[2];
struct nss_input inp = {
.input.gid = gid,
- .cmd = SSS_NSS_GETGRGID,
- .rd.len = sizeof(uint32_t),
- .rd.data = &group_gid,
+ .cmd = SSS_NSS_GETGRGID_EX,
+ .rd.len = 2 * sizeof(uint32_t),
+ .rd.data = &req_data,
.result.grrep.result = grp,
.result.grrep.buffer = buffer,
.result.grrep.buflen = buflen};
@@ -336,6 +384,8 @@ int sss_nss_getgrgid_timeout(gid_t gid, struct group *grp,
return ERANGE;
}
+ SAFEALIGN_COPY_UINT32(&req_data[0], &gid, NULL);
+ SAFEALIGN_COPY_UINT32(&req_data[1], &flags, NULL);
*result = NULL;
ret = sss_get_ex(&inp, flags, timeout);
@@ -355,18 +405,16 @@ int sss_nss_getgrouplist_timeout(const char *name, gid_t group,
long int start = 1;
struct nss_input inp = {
.input.name = name,
- .cmd = SSS_NSS_INITGR,
- .rd.data = name};
+ .cmd = SSS_NSS_INITGR_EX};
if (groups == NULL || ngroups == NULL || *ngroups == 0) {
return EINVAL;
}
- ret = sss_strnlen(name, SSS_NAME_MAX, &inp.rd.len);
+ ret = make_name_flag_req_data(name, flags, &inp.rd);
if (ret != 0) {
return ret;
}
- inp.rd.len++;
new_ngroups = MAX(1, *ngroups);
new_groups = malloc(new_ngroups * sizeof(gid_t));
diff --git a/src/sss_client/sss_cli.h b/src/sss_client/sss_cli.h
index 5329651a9385d138b8ea7237cb5cf4e2b8e5f371..9d2cc00c9957f5680548461129e3e6b777da5091 100644
--- a/src/sss_client/sss_cli.h
+++ b/src/sss_client/sss_cli.h
@@ -79,6 +79,9 @@ enum sss_cli_command {
SSS_NSS_GETPWENT = 0x0014,
SSS_NSS_ENDPWENT = 0x0015,
+ SSS_NSS_GETPWNAM_EX = 0x0019,
+ SSS_NSS_GETPWUID_EX = 0x001A,
+
/* group */
SSS_NSS_GETGRNAM = 0x0021,
@@ -88,6 +91,10 @@ enum sss_cli_command {
SSS_NSS_ENDGRENT = 0x0025,
SSS_NSS_INITGR = 0x0026,
+ SSS_NSS_GETGRNAM_EX = 0x0029,
+ SSS_NSS_GETGRGID_EX = 0x002A,
+ SSS_NSS_INITGR_EX = 0x002E,
+
#if 0
/* aliases */
--
2.14.3

View File

@ -0,0 +1,148 @@
From ac6b267ff3df6d0417062a128ec16b184ea2c1b7 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Thu, 12 Oct 2017 10:42:41 +0200
Subject: [PATCH 05/11] NSS: add support for SSS_NSS_EX_FLAG_NO_CACHE
If SSS_NSS_EX_FLAG_NO_CACHE is set the object is refresh by directly
looking it up in the backend.
Related to https://pagure.io/SSSD/sssd/issue/2478
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
---
src/responder/nss/nss_cmd.c | 8 ++++
src/sss_client/idmap/sss_nss_ex.c | 71 ++++++++++++++++++++----------------
src/sss_client/idmap/sss_nss_idmap.h | 4 ++
3 files changed, 52 insertions(+), 31 deletions(-)
diff --git a/src/responder/nss/nss_cmd.c b/src/responder/nss/nss_cmd.c
index 974eaccc93cea3a330007735676da69eb9b84141..c5ddd2f2cc2122cd169ea991b94a14eb5bad095f 100644
--- a/src/responder/nss/nss_cmd.c
+++ b/src/responder/nss/nss_cmd.c
@@ -92,6 +92,10 @@ static errno_t nss_getby_name(struct cli_ctx *cli_ctx,
goto done;
}
+ if ((flags & SSS_NSS_EX_FLAG_NO_CACHE) != 0) {
+ cache_req_data_set_bypass_cache(data, true);
+ }
+
subreq = nss_get_object_send(cmd_ctx, cli_ctx->ev, cli_ctx,
data, memcache, rawname, 0);
if (subreq == NULL) {
@@ -152,6 +156,10 @@ static errno_t nss_getby_id(struct cli_ctx *cli_ctx,
goto done;
}
+ if ((flags & SSS_NSS_EX_FLAG_NO_CACHE) != 0) {
+ cache_req_data_set_bypass_cache(data, true);
+ }
+
subreq = nss_get_object_send(cmd_ctx, cli_ctx->ev, cli_ctx,
data, memcache, NULL, id);
if (subreq == NULL) {
diff --git a/src/sss_client/idmap/sss_nss_ex.c b/src/sss_client/idmap/sss_nss_ex.c
index dc7610a4e528b5126f0d25d84cd3c1a22f683b75..edb3ea652ef7032b76c8f815b9f83fe185a669ea 100644
--- a/src/sss_client/idmap/sss_nss_ex.c
+++ b/src/sss_client/idmap/sss_nss_ex.c
@@ -115,42 +115,51 @@ int sss_get_ex(struct nss_input *inp, uint32_t flags, unsigned int timeout)
size_t c;
gid_t *new_groups;
size_t idx;
+ bool skip_mc = false;
- ret = sss_nss_mc_get(inp);
- switch (ret) {
- case 0:
- return 0;
- case ERANGE:
- return ERANGE;
- case ENOENT:
- /* fall through, we need to actively ask the parent
- * if no entry is found */
- break;
- default:
- /* if using the mmaped cache failed,
- * fall back to socket based comms */
- break;
+ if ((flags & SSS_NSS_EX_FLAG_NO_CACHE) != 0) {
+ skip_mc = true;
+ }
+
+ if (!skip_mc) {
+ ret = sss_nss_mc_get(inp);
+ switch (ret) {
+ case 0:
+ return 0;
+ case ERANGE:
+ return ERANGE;
+ case ENOENT:
+ /* fall through, we need to actively ask the parent
+ * if no entry is found */
+ break;
+ default:
+ /* if using the mmaped cache failed,
+ * fall back to socket based comms */
+ break;
+ }
}
sss_nss_timedlock(timeout, &time_left);
- /* previous thread might already initialize entry in mmap cache */
- ret = sss_nss_mc_get(inp);
- switch (ret) {
- case 0:
- ret = 0;
- goto out;
- case ERANGE:
- ret = ERANGE;
- goto out;
- case ENOENT:
- /* fall through, we need to actively ask the parent
- * if no entry is found */
- break;
- default:
- /* if using the mmaped cache failed,
- * fall back to socket based comms */
- break;
+ if (!skip_mc) {
+ /* previous thread might already initialize entry in mmap cache */
+ ret = sss_nss_mc_get(inp);
+ switch (ret) {
+ case 0:
+ ret = 0;
+ goto out;
+ case ERANGE:
+ ret = ERANGE;
+ goto out;
+ case ENOENT:
+ /* fall through, we need to actively ask the parent
+ * if no entry is found */
+ break;
+ default:
+ /* if using the mmaped cache failed,
+ * fall back to socket based comms */
+ break;
+ }
}
ret = sss_nss_make_request_timeout(inp->cmd, &inp->rd, time_left,
diff --git a/src/sss_client/idmap/sss_nss_idmap.h b/src/sss_client/idmap/sss_nss_idmap.h
index 2334b6cb3fb8ef62e4ce3a7187c7affaeaa034e7..1649830afbb80c617fd339f054aef8bc8e585fb9 100644
--- a/src/sss_client/idmap/sss_nss_idmap.h
+++ b/src/sss_client/idmap/sss_nss_idmap.h
@@ -169,6 +169,10 @@ void sss_nss_free_kv(struct sss_nss_kv *kv_list);
#define SSS_NSS_EX_FLAG_NO_FLAGS 0
+/** Always request data from the server side, client must be privileged to do
+ * so, see nss_trusted_users option in man sssd.conf for details */
+#define SSS_NSS_EX_FLAG_NO_CACHE (1 << 0)
+
#ifdef IPA_389DS_PLUGIN_HELPER_CALLS
/**
--
2.14.3

View File

@ -0,0 +1,111 @@
From 52e675ec4b160720515c81ae8c0e5a95feb50c57 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Mon, 23 Oct 2017 18:26:55 +0200
Subject: [PATCH 06/11] CACHE_REQ: Add cache_req_data_set_bypass_dp()
Similar to cache_req_data_set_bypass_cache()
cache_req_data_set_bypass_dp() can be used to control how the cache_req
framework performs the lookup. If cache_req_data_set_bypass_dp() is used
with 'true' only a cache lookup is performed and no request is send to
the backend even if no entry was found.
Related to https://pagure.io/SSSD/sssd/issue/2478
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
---
src/responder/common/cache_req/cache_req.c | 15 +++++++++++++++
src/responder/common/cache_req/cache_req.h | 3 +++
src/responder/common/cache_req/cache_req_data.c | 12 ++++++++++++
src/responder/common/cache_req/cache_req_private.h | 2 ++
4 files changed, 32 insertions(+)
diff --git a/src/responder/common/cache_req/cache_req.c b/src/responder/common/cache_req/cache_req.c
index 5fed7a2ab8beded2fee91f679a12f9a0ff6013ec..110df561101be538e3f0496addfa2e14e42ea918 100644
--- a/src/responder/common/cache_req/cache_req.c
+++ b/src/responder/common/cache_req/cache_req.c
@@ -142,6 +142,13 @@ cache_req_create(TALLOC_CTX *mem_ctx,
cr->cache_first = rctx->cache_first;
cr->bypass_cache = cr->plugin->bypass_cache || cr->data->bypass_cache;
+ cr->bypass_dp = cr->data->bypass_dp;
+ if (cr->bypass_cache && cr->bypass_dp) {
+ CACHE_REQ_DEBUG(SSSDBG_CRIT_FAILURE, cr,
+ "Cannot bypass cache and dp at the same time!");
+ talloc_free(cr);
+ return NULL;
+ }
return cr;
}
@@ -658,6 +665,14 @@ static bool cache_req_search_schema(struct cache_req *cr,
bypass_cache = true;
bypass_dp = false;
+ if (!first_iteration) {
+ return false;
+ }
+ } else if (cr->bypass_dp) {
+ /* The caller wants to lookup only in the cache */
+ bypass_cache = false;
+ bypass_dp = true;
+
if (!first_iteration) {
return false;
}
diff --git a/src/responder/common/cache_req/cache_req.h b/src/responder/common/cache_req/cache_req.h
index c04b2fba6f0445dcfcc9cfe1b5963ac975c39118..2c88853887fc816bba2182d9d9beaa32fa384158 100644
--- a/src/responder/common/cache_req/cache_req.h
+++ b/src/responder/common/cache_req/cache_req.h
@@ -127,6 +127,9 @@ void
cache_req_data_set_bypass_cache(struct cache_req_data *data,
bool bypass_cache);
+void
+cache_req_data_set_bypass_dp(struct cache_req_data *data,
+ bool bypass_dp);
/* Output data. */
struct cache_req_result {
diff --git a/src/responder/common/cache_req/cache_req_data.c b/src/responder/common/cache_req/cache_req_data.c
index 48264a321dc603f9708ba71c44542363b11a71ba..ed378274a9a0a68ede8ac99805f3ea4a041382e6 100644
--- a/src/responder/common/cache_req/cache_req_data.c
+++ b/src/responder/common/cache_req/cache_req_data.c
@@ -365,3 +365,15 @@ cache_req_data_set_bypass_cache(struct cache_req_data *data,
data->bypass_cache = bypass_cache;
}
+
+void
+cache_req_data_set_bypass_dp(struct cache_req_data *data,
+ bool bypass_dp)
+{
+ if (data == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "cache_req_data should never be NULL\n");
+ return;
+ }
+
+ data->bypass_dp = bypass_dp;
+}
diff --git a/src/responder/common/cache_req/cache_req_private.h b/src/responder/common/cache_req/cache_req_private.h
index 9b706ff7d678f543effb77089857a7e8a42a9c51..0f630542d38a277d1819063fa4134bd7d2525c90 100644
--- a/src/responder/common/cache_req/cache_req_private.h
+++ b/src/responder/common/cache_req/cache_req_private.h
@@ -42,6 +42,7 @@ struct cache_req {
struct sss_domain_info *domain;
bool cache_first;
bool bypass_cache;
+ bool bypass_dp;
/* Only contact domains with this type */
enum cache_req_dom_type req_dom_type;
@@ -90,6 +91,7 @@ struct cache_req_data {
} svc;
bool bypass_cache;
+ bool bypass_dp;
};
struct tevent_req *
--
2.14.3

View File

@ -0,0 +1,48 @@
From a7d6ca275d6b2e5d396cbefb18d0ee880011e271 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Tue, 24 Oct 2017 12:50:43 +0200
Subject: [PATCH 07/11] nss: make memcache_delete_entry() public
Related to https://pagure.io/SSSD/sssd/issue/2478
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
---
src/responder/nss/nss_get_object.c | 2 +-
src/responder/nss/nss_private.h | 8 ++++++++
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/src/responder/nss/nss_get_object.c b/src/responder/nss/nss_get_object.c
index e56480af5e3369963d2e8bb17d74d1603af8e014..15faced006f754134415e766284377f0c86af0ac 100644
--- a/src/responder/nss/nss_get_object.c
+++ b/src/responder/nss/nss_get_object.c
@@ -86,7 +86,7 @@ memcache_delete_entry_by_id(struct nss_ctx *nss_ctx,
return ret;
}
-static errno_t
+errno_t
memcache_delete_entry(struct nss_ctx *nss_ctx,
struct resp_ctx *rctx,
struct sss_domain_info *domain,
diff --git a/src/responder/nss/nss_private.h b/src/responder/nss/nss_private.h
index a0b573d6ecba2d8ba6f55db0adcd7ee29cbec991..5fc19d26be9adda4d967086e7b239e49a78866ee 100644
--- a/src/responder/nss/nss_private.h
+++ b/src/responder/nss/nss_private.h
@@ -92,6 +92,14 @@ struct sss_cmd_table *get_nss_cmds(void);
int nss_connection_setup(struct cli_ctx *cli_ctx);
+errno_t
+memcache_delete_entry(struct nss_ctx *nss_ctx,
+ struct resp_ctx *rctx,
+ struct sss_domain_info *domain,
+ const char *name,
+ uint32_t id,
+ enum sss_mc_type type);
+
struct tevent_req *
nss_get_object_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
--
2.14.3

View File

@ -0,0 +1,364 @@
From 55f7d8034d783c01789d76a2b9ffc901045e8af8 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Tue, 24 Oct 2017 14:10:53 +0200
Subject: [PATCH 08/11] NSS: add support for SSS_NSS_EX_FLAG_INVALIDATE_CACHE
The patch adds support for the SSS_NSS_EX_FLAG_INVALIDATE_CACHE flag and
makes the existing code more flexible and handle additional flags.
If SSS_NSS_EX_FLAG_INVALIDATE_CACHE is set the requested object is only
looked up in the cache and if it was found on-disk and memory cache
entries will be invalidated.
Related to https://pagure.io/SSSD/sssd/issue/2478
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
---
src/responder/nss/nss_cmd.c | 141 +++++++++++++++++++++++++++++++--
src/responder/nss/nss_protocol.c | 1 +
src/responder/nss/nss_protocol.h | 1 +
src/responder/nss/nss_protocol_grent.c | 9 ++-
src/responder/nss/nss_protocol_pwent.c | 6 +-
src/sss_client/idmap/sss_nss_ex.c | 20 ++++-
src/sss_client/idmap/sss_nss_idmap.h | 8 +-
7 files changed, 171 insertions(+), 15 deletions(-)
diff --git a/src/responder/nss/nss_cmd.c b/src/responder/nss/nss_cmd.c
index c5ddd2f2cc2122cd169ea991b94a14eb5bad095f..545257a0be7e91e9de767a57848bb77c5791db4e 100644
--- a/src/responder/nss/nss_cmd.c
+++ b/src/responder/nss/nss_cmd.c
@@ -50,6 +50,26 @@ nss_cmd_ctx_create(TALLOC_CTX *mem_ctx,
return cmd_ctx;
}
+static errno_t eval_flags(struct nss_cmd_ctx *cmd_ctx,
+ struct cache_req_data *data)
+{
+ if ((cmd_ctx->flags & SSS_NSS_EX_FLAG_NO_CACHE) != 0
+ && (cmd_ctx->flags & SSS_NSS_EX_FLAG_INVALIDATE_CACHE) != 0) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Flags SSS_NSS_EX_FLAG_NO_CACHE and "
+ "SSS_NSS_EX_FLAG_INVALIDATE_CACHE are "
+ "mutually exclusive.\n");
+ return EINVAL;
+ }
+
+ if ((cmd_ctx->flags & SSS_NSS_EX_FLAG_NO_CACHE) != 0) {
+ cache_req_data_set_bypass_cache(data, true);
+ } else if ((cmd_ctx->flags & SSS_NSS_EX_FLAG_INVALIDATE_CACHE) != 0) {
+ cache_req_data_set_bypass_dp(data, true);
+ }
+
+ return EOK;
+}
+
static void nss_getby_done(struct tevent_req *subreq);
static void nss_getlistby_done(struct tevent_req *subreq);
@@ -65,7 +85,6 @@ static errno_t nss_getby_name(struct cli_ctx *cli_ctx,
struct tevent_req *subreq;
const char *rawname;
errno_t ret;
- uint32_t flags = 0;
cmd_ctx = nss_cmd_ctx_create(cli_ctx, cli_ctx, type, fill_fn);
if (cmd_ctx == NULL) {
@@ -73,8 +92,9 @@ static errno_t nss_getby_name(struct cli_ctx *cli_ctx,
goto done;
}
+ cmd_ctx->flags = 0;
if (ex_version) {
- ret = nss_protocol_parse_name_ex(cli_ctx, &rawname, &flags);
+ ret = nss_protocol_parse_name_ex(cli_ctx, &rawname, &cmd_ctx->flags);
} else {
ret = nss_protocol_parse_name(cli_ctx, &rawname);
}
@@ -92,8 +112,10 @@ static errno_t nss_getby_name(struct cli_ctx *cli_ctx,
goto done;
}
- if ((flags & SSS_NSS_EX_FLAG_NO_CACHE) != 0) {
- cache_req_data_set_bypass_cache(data, true);
+ ret = eval_flags(cmd_ctx, data);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "eval_flags failed.\n");
+ goto done;
}
subreq = nss_get_object_send(cmd_ctx, cli_ctx->ev, cli_ctx,
@@ -129,7 +151,6 @@ static errno_t nss_getby_id(struct cli_ctx *cli_ctx,
struct tevent_req *subreq;
uint32_t id;
errno_t ret;
- uint32_t flags = 0;
cmd_ctx = nss_cmd_ctx_create(cli_ctx, cli_ctx, type, fill_fn);
if (cmd_ctx == NULL) {
@@ -138,7 +159,7 @@ static errno_t nss_getby_id(struct cli_ctx *cli_ctx,
}
if (ex_version) {
- ret = nss_protocol_parse_id_ex(cli_ctx, &id, &flags);
+ ret = nss_protocol_parse_id_ex(cli_ctx, &id, &cmd_ctx->flags);
} else {
ret = nss_protocol_parse_id(cli_ctx, &id);
}
@@ -156,8 +177,10 @@ static errno_t nss_getby_id(struct cli_ctx *cli_ctx,
goto done;
}
- if ((flags & SSS_NSS_EX_FLAG_NO_CACHE) != 0) {
- cache_req_data_set_bypass_cache(data, true);
+ ret = eval_flags(cmd_ctx, data);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "eval_flags failed.\n");
+ goto done;
}
subreq = nss_get_object_send(cmd_ctx, cli_ctx->ev, cli_ctx,
@@ -425,6 +448,98 @@ done:
return EOK;
}
+static errno_t invalidate_cache(struct nss_cmd_ctx *cmd_ctx,
+ struct cache_req_result *result)
+{
+ int ret;
+ enum sss_mc_type memcache_type;
+ const char *name;
+ char *output_name = NULL;
+ bool is_user;
+ struct sysdb_attrs *attrs = NULL;
+
+ switch (cmd_ctx->type) {
+ case CACHE_REQ_INITGROUPS:
+ case CACHE_REQ_INITGROUPS_BY_UPN:
+ memcache_type = SSS_MC_INITGROUPS;
+ is_user = true;
+ break;
+ case CACHE_REQ_USER_BY_NAME:
+ case CACHE_REQ_USER_BY_ID:
+ memcache_type = SSS_MC_PASSWD;
+ is_user = true;
+ break;
+ case CACHE_REQ_GROUP_BY_NAME:
+ case CACHE_REQ_GROUP_BY_ID:
+ memcache_type = SSS_MC_GROUP;
+ is_user = false;
+ break;
+ default:
+ /* nothing to do */
+ return EOK;
+ }
+
+ /* Find output name to invalidate memory cache entry*/
+ name = sss_get_name_from_msg(result->domain, result->msgs[0]);
+ if (name == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Found object has no name.\n");
+ return EINVAL;
+ }
+ ret = sss_output_fqname(cmd_ctx, result->domain, name,
+ cmd_ctx->nss_ctx->rctx->override_space,
+ &output_name);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "sss_output_fqname failed.\n");
+ return ret;
+ }
+
+ memcache_delete_entry(cmd_ctx->nss_ctx, cmd_ctx->nss_ctx->rctx, NULL,
+ output_name, 0, memcache_type);
+ if (memcache_type == SSS_MC_INITGROUPS) {
+ /* Invalidate the passwd data as well */
+ memcache_delete_entry(cmd_ctx->nss_ctx, cmd_ctx->nss_ctx->rctx,
+ result->domain, output_name, 0, SSS_MC_PASSWD);
+ }
+ talloc_free(output_name);
+
+ /* Use sysdb name to invalidate disk cache entry */
+ name = ldb_msg_find_attr_as_string(result->msgs[0], SYSDB_NAME, NULL);
+ if (name == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Found object has no name.\n");
+ return EINVAL;
+ }
+
+ if (memcache_type == SSS_MC_INITGROUPS) {
+ attrs = sysdb_new_attrs(cmd_ctx);
+ if (attrs == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_new_attrs failed.\n");
+ return ENOMEM;
+ }
+
+ ret = sysdb_attrs_add_time_t(attrs, SYSDB_INITGR_EXPIRE, 1);
+ if (ret != EOK) {
+ talloc_free(attrs);
+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_time_t failed.\n");
+ return ret;
+ }
+
+ ret = sysdb_set_user_attr(result->domain, name, attrs, SYSDB_MOD_REP);
+ talloc_free(attrs);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_set_user_attr failed.\n");
+ return ret;
+ }
+ }
+
+ ret = sysdb_invalidate_cache_entry(result->domain, name, is_user);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "sysdb_invalidate_cache_entry failed.\n");
+ return ret;
+ }
+
+ return EOK;
+}
+
static void nss_getby_done(struct tevent_req *subreq)
{
struct cache_req_result *result;
@@ -440,6 +555,16 @@ static void nss_getby_done(struct tevent_req *subreq)
goto done;
}
+ if ((cmd_ctx->flags & SSS_NSS_EX_FLAG_INVALIDATE_CACHE) != 0) {
+ ret = invalidate_cache(cmd_ctx, result);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "Failed to invalidate cache for [%s].\n",
+ cmd_ctx->rawname);
+ nss_protocol_done(cmd_ctx->cli_ctx, ret);
+ goto done;
+ }
+ }
+
nss_protocol_reply(cmd_ctx->cli_ctx, cmd_ctx->nss_ctx, cmd_ctx,
result, cmd_ctx->fill_fn);
diff --git a/src/responder/nss/nss_protocol.c b/src/responder/nss/nss_protocol.c
index 17bfc4f4e71960a72e9e04622eac95b94a865ec7..2655386498754c46fbb363bdd1f976f9ded6a434 100644
--- a/src/responder/nss/nss_protocol.c
+++ b/src/responder/nss/nss_protocol.c
@@ -233,6 +233,7 @@ nss_protocol_parse_id_ex(struct cli_ctx *cli_ctx, uint32_t *_id,
SAFEALIGN_COPY_UINT32(&flags, body + sizeof(uint32_t), NULL);
*_id = id;
+ *_flags = flags;
return EOK;
}
diff --git a/src/responder/nss/nss_protocol.h b/src/responder/nss/nss_protocol.h
index ca5b040237dc18acdca9a7a3a7a7dbb64265aa95..76724d2b2db7b11c9147fa927e39abab731328b2 100644
--- a/src/responder/nss/nss_protocol.h
+++ b/src/responder/nss/nss_protocol.h
@@ -50,6 +50,7 @@ struct nss_cmd_ctx {
struct nss_ctx *nss_ctx;
struct nss_state_ctx *state_ctx;
nss_protocol_fill_packet_fn fill_fn;
+ uint32_t flags;
/* For initgroups- */
const char *rawname;
diff --git a/src/responder/nss/nss_protocol_grent.c b/src/responder/nss/nss_protocol_grent.c
index ee228c722a153a1ba7aa8a1b30a1e551108424bb..6f6ae57dd97b000ad3cf174b0f649d46981563e2 100644
--- a/src/responder/nss/nss_protocol_grent.c
+++ b/src/responder/nss/nss_protocol_grent.c
@@ -274,8 +274,10 @@ nss_protocol_fill_grent(struct nss_ctx *nss_ctx,
num_results++;
- /* Do not store entry in memory cache during enumeration. */
- if (!cmd_ctx->enumeration) {
+ /* Do not store entry in memory cache during enumeration or when
+ * requested. */
+ if (!cmd_ctx->enumeration
+ && (cmd_ctx->flags & SSS_NSS_EX_FLAG_INVALIDATE_CACHE) == 0) {
members = (char *)&body[rp_members];
members_size = body_len - rp_members;
ret = sss_mmap_cache_gr_store(&nss_ctx->grp_mc_ctx, name, &pwfield,
@@ -390,7 +392,8 @@ nss_protocol_fill_initgr(struct nss_ctx *nss_ctx,
num_results++;
}
- if (nss_ctx->initgr_mc_ctx) {
+ if (nss_ctx->initgr_mc_ctx
+ && (cmd_ctx->flags & SSS_NSS_EX_FLAG_INVALIDATE_CACHE) == 0) {
to_sized_string(&rawname, cmd_ctx->rawname);
to_sized_string(&unique_name, result->lookup_name);
diff --git a/src/responder/nss/nss_protocol_pwent.c b/src/responder/nss/nss_protocol_pwent.c
index db5c071e2ff172a2267c08c9817fecfbcc7cabc3..f449ec69b6a86a6db2aaed368e217c1a791faaa2 100644
--- a/src/responder/nss/nss_protocol_pwent.c
+++ b/src/responder/nss/nss_protocol_pwent.c
@@ -295,8 +295,10 @@ nss_protocol_fill_pwent(struct nss_ctx *nss_ctx,
num_results++;
- /* Do not store entry in memory cache during enumeration. */
- if (!cmd_ctx->enumeration) {
+ /* Do not store entry in memory cache during enumeration or when
+ * requested. */
+ if (!cmd_ctx->enumeration
+ && (cmd_ctx->flags & SSS_NSS_EX_FLAG_INVALIDATE_CACHE) == 0) {
ret = sss_mmap_cache_pw_store(&nss_ctx->pwd_mc_ctx, name, &pwfield,
uid, gid, &gecos, &homedir, &shell);
if (ret != EOK) {
diff --git a/src/sss_client/idmap/sss_nss_ex.c b/src/sss_client/idmap/sss_nss_ex.c
index edb3ea652ef7032b76c8f815b9f83fe185a669ea..148eb7b35ec236b6272dd203a0035399cfdef73d 100644
--- a/src/sss_client/idmap/sss_nss_ex.c
+++ b/src/sss_client/idmap/sss_nss_ex.c
@@ -103,6 +103,18 @@ errno_t sss_nss_mc_get(struct nss_input *inp)
}
}
+static int check_flags(uint32_t flags)
+{
+ /* SSS_NSS_EX_FLAG_NO_CACHE and SSS_NSS_EX_FLAG_INVALIDATE_CACHE are
+ * mutually exclusive */
+ if ((flags & SSS_NSS_EX_FLAG_NO_CACHE) != 0
+ && (flags & SSS_NSS_EX_FLAG_INVALIDATE_CACHE) != 0) {
+ return EINVAL;
+ }
+
+ return 0;
+}
+
int sss_get_ex(struct nss_input *inp, uint32_t flags, unsigned int timeout)
{
uint8_t *repbuf = NULL;
@@ -117,7 +129,13 @@ int sss_get_ex(struct nss_input *inp, uint32_t flags, unsigned int timeout)
size_t idx;
bool skip_mc = false;
- if ((flags & SSS_NSS_EX_FLAG_NO_CACHE) != 0) {
+ ret = check_flags(flags);
+ if (ret != 0) {
+ return ret;
+ }
+
+ if ((flags & SSS_NSS_EX_FLAG_NO_CACHE) != 0
+ || (flags & SSS_NSS_EX_FLAG_INVALIDATE_CACHE) != 0) {
skip_mc = true;
}
diff --git a/src/sss_client/idmap/sss_nss_idmap.h b/src/sss_client/idmap/sss_nss_idmap.h
index 1649830afbb80c617fd339f054aef8bc8e585fb9..3755643312f05a31d1cf1aa76dfc22848ef1e3ec 100644
--- a/src/sss_client/idmap/sss_nss_idmap.h
+++ b/src/sss_client/idmap/sss_nss_idmap.h
@@ -170,9 +170,15 @@ void sss_nss_free_kv(struct sss_nss_kv *kv_list);
#define SSS_NSS_EX_FLAG_NO_FLAGS 0
/** Always request data from the server side, client must be privileged to do
- * so, see nss_trusted_users option in man sssd.conf for details */
+ * so, see nss_trusted_users option in man sssd.conf for details.
+ * This flag cannot be used together with SSS_NSS_EX_FLAG_INVALIDATE_CACHE */
#define SSS_NSS_EX_FLAG_NO_CACHE (1 << 0)
+/** Invalidate the data in the caches, client must be privileged to do
+ * so, see nss_trusted_users option in man sssd.conf for details.
+ * This flag cannot be used together with SSS_NSS_EX_FLAG_NO_CACHE */
+#define SSS_NSS_EX_FLAG_INVALIDATE_CACHE (1 << 1)
+
#ifdef IPA_389DS_PLUGIN_HELPER_CALLS
/**
--
2.14.3

View File

@ -0,0 +1,589 @@
From 85da8a5e90bffc8b0fef5e0ea364a8d3cb50de86 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Wed, 25 Oct 2017 21:31:54 +0200
Subject: [PATCH 09/11] NSS/TESTS: add unit tests for *_EX requests
The patch adds unit tests for the new *_EX requests with different input
types and flags.
Related to https://pagure.io/SSSD/sssd/issue/2478
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
---
src/tests/cmocka/test_nss_srv.c | 539 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 539 insertions(+)
diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c
index ccedf96beaecfaa4232bbe456d5e5a8394098483..6aa726153183b5a871a75d398727ea7132358ca6 100644
--- a/src/tests/cmocka/test_nss_srv.c
+++ b/src/tests/cmocka/test_nss_srv.c
@@ -255,6 +255,45 @@ static void mock_input_user_or_group(const char *input)
mock_parse_inp(shortname, domname, EOK);
}
+static void mock_input_user_or_group_ex(bool do_parse_inp, const char *input,
+ uint32_t flags)
+{
+ const char *copy;
+ const char *shortname;
+ const char *domname;
+ char *separator;
+ uint8_t *data;
+ size_t len;
+
+ len = strlen(input);
+ len++;
+ data = talloc_size(nss_test_ctx, len + sizeof(uint32_t));
+ assert_non_null(data);
+ memcpy(data, input, len);
+ SAFEALIGN_COPY_UINT32(data + len, &flags, NULL);
+
+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_WRAPPER);
+ will_return(__wrap_sss_packet_get_body, data);
+ will_return(__wrap_sss_packet_get_body, len + sizeof(uint32_t));
+
+ if (do_parse_inp) {
+ copy = talloc_strdup(nss_test_ctx, input);
+ assert_non_null(copy);
+
+ separator = strrchr(copy, '@');
+ if (separator == NULL) {
+ shortname = input;
+ domname = NULL;
+ } else {
+ *separator = '\0';
+ shortname = copy;
+ domname = separator + 1;
+ }
+
+ mock_parse_inp(shortname, domname, EOK);
+ }
+}
+
static void mock_input_upn(const char *upn)
{
will_return(__wrap_sss_packet_get_body, WRAP_CALL_WRAPPER);
@@ -291,6 +330,20 @@ static void mock_input_id(TALLOC_CTX *mem_ctx, uint32_t id)
will_return(__wrap_sss_packet_get_body, sizeof(uint32_t));
}
+static void mock_input_id_ex(TALLOC_CTX *mem_ctx, uint32_t id, uint32_t flags)
+{
+ uint8_t *body;
+
+ body = talloc_zero_array(mem_ctx, uint8_t, 8);
+ if (body == NULL) return;
+
+ SAFEALIGN_SETMEM_UINT32(body, id, NULL);
+ SAFEALIGN_SETMEM_UINT32(body + sizeof(uint32_t), flags, NULL);
+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_WRAPPER);
+ will_return(__wrap_sss_packet_get_body, body);
+ will_return(__wrap_sss_packet_get_body, 2 * sizeof(uint32_t));
+}
+
static void mock_fill_user(void)
{
/* One packet for the entry and one for num entries */
@@ -4143,6 +4196,482 @@ void test_nss_getsidbyname_neg(void **state)
assert_int_equal(ret, ENOENT);
}
+static int test_nss_EINVAL_check(uint32_t status, uint8_t *body, size_t blen)
+{
+ assert_int_equal(status, EINVAL);
+ assert_int_equal(blen, 0);
+
+ return EOK;
+}
+
+#define RESET_TCTX do { \
+ nss_test_ctx->tctx->done = false; \
+ nss_test_ctx->tctx->error = EIO; \
+} while (0)
+
+void test_nss_getpwnam_ex(void **state)
+{
+ errno_t ret;
+
+ ret = store_user(nss_test_ctx, nss_test_ctx->tctx->dom,
+ &getpwnam_usr, NULL, 0);
+ assert_int_equal(ret, EOK);
+
+ mock_input_user_or_group_ex(true, "testuser", 0);
+ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWNAM_EX);
+ mock_fill_user();
+
+ /* Query for that user, call a callback when command finishes */
+ set_cmd_cb(test_nss_getpwnam_check);
+ ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETPWNAM_EX,
+ nss_test_ctx->nss_cmds);
+ assert_int_equal(ret, EOK);
+
+ /* Wait until the test finishes with EOK */
+ ret = test_ev_loop(nss_test_ctx->tctx);
+ assert_int_equal(ret, EOK);
+ RESET_TCTX;
+
+ /* Use old input format, expect EINVAL */
+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_WRAPPER);
+ will_return(__wrap_sss_packet_get_body, "testuser");
+ will_return(__wrap_sss_packet_get_body, 0);
+ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWNAM_EX);
+
+ set_cmd_cb(test_nss_EINVAL_check);
+ ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETPWNAM_EX,
+ nss_test_ctx->nss_cmds);
+ assert_int_equal(ret, EOK);
+
+ ret = test_ev_loop(nss_test_ctx->tctx);
+ assert_int_equal(ret, EOK);
+ RESET_TCTX;
+
+ /* Use unsupported flag combination, expect EINVAL */
+ mock_input_user_or_group_ex(false, "testuser",
+ SSS_NSS_EX_FLAG_NO_CACHE
+ |SSS_NSS_EX_FLAG_INVALIDATE_CACHE);
+ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWNAM_EX);
+
+ set_cmd_cb(test_nss_EINVAL_check);
+ ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETPWNAM_EX,
+ nss_test_ctx->nss_cmds);
+ assert_int_equal(ret, EOK);
+
+ /* Wait until the test finishes with EOK */
+ ret = test_ev_loop(nss_test_ctx->tctx);
+ assert_int_equal(ret, EOK);
+ RESET_TCTX;
+
+ /* Use flag SSS_NSS_EX_FLAG_NO_CACHE,
+ * will cause a backend lookup -> mock_account_recv_simple() */
+ mock_input_user_or_group_ex(true, "testuser", SSS_NSS_EX_FLAG_NO_CACHE);
+ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWNAM_EX);
+ mock_fill_user();
+ mock_account_recv_simple();
+
+ set_cmd_cb(test_nss_getpwnam_check);
+ ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETPWNAM_EX,
+ nss_test_ctx->nss_cmds);
+ assert_int_equal(ret, EOK);
+
+ /* Wait until the test finishes with EOK */
+ ret = test_ev_loop(nss_test_ctx->tctx);
+ assert_int_equal(ret, EOK);
+ RESET_TCTX;
+
+ /* Use flag SSS_NSS_EX_FLAG_INVALIDATE_CACHE */
+ mock_input_user_or_group_ex(true, "testuser",
+ SSS_NSS_EX_FLAG_INVALIDATE_CACHE);
+ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWNAM_EX);
+ mock_fill_user();
+
+ set_cmd_cb(test_nss_getpwnam_check);
+ ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETPWNAM_EX,
+ nss_test_ctx->nss_cmds);
+ assert_int_equal(ret, EOK);
+
+ /* Wait until the test finishes with EOK */
+ ret = test_ev_loop(nss_test_ctx->tctx);
+ assert_int_equal(ret, EOK);
+}
+
+void test_nss_getpwuid_ex(void **state)
+{
+ errno_t ret;
+ uint32_t id = 101;
+
+ /* Prime the cache with a valid user */
+ ret = store_user(nss_test_ctx, nss_test_ctx->tctx->dom,
+ &getpwuid_usr, NULL, 0);
+ assert_int_equal(ret, EOK);
+
+ mock_input_id_ex(nss_test_ctx, id, 0);
+ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWUID_EX);
+ mock_fill_user();
+
+ /* Query for that id, call a callback when command finishes */
+ set_cmd_cb(test_nss_getpwuid_check);
+ ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETPWUID_EX,
+ nss_test_ctx->nss_cmds);
+ assert_int_equal(ret, EOK);
+
+ /* Wait until the test finishes with EOK */
+ ret = test_ev_loop(nss_test_ctx->tctx);
+ assert_int_equal(ret, EOK);
+ RESET_TCTX;
+
+ /* Use old input format, expect failure */
+ mock_input_id(nss_test_ctx, id);
+ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWUID_EX);
+
+ set_cmd_cb(test_nss_EINVAL_check);
+ ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETPWUID_EX,
+ nss_test_ctx->nss_cmds);
+ assert_int_equal(ret, EOK);
+
+ /* Wait until the test finishes with EOK */
+ ret = test_ev_loop(nss_test_ctx->tctx);
+ assert_int_equal(ret, EOK);
+ RESET_TCTX;
+
+ /* Use unsupported flag combination, expect EINVAL */
+ mock_input_id_ex(nss_test_ctx, id, SSS_NSS_EX_FLAG_NO_CACHE
+ |SSS_NSS_EX_FLAG_INVALIDATE_CACHE);
+ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWUID_EX);
+
+ set_cmd_cb(test_nss_EINVAL_check);
+ ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETPWUID_EX,
+ nss_test_ctx->nss_cmds);
+ assert_int_equal(ret, EOK);
+
+ /* Wait until the test finishes with EOK */
+ ret = test_ev_loop(nss_test_ctx->tctx);
+ assert_int_equal(ret, EOK);
+ RESET_TCTX;
+
+ /* Use flag SSS_NSS_EX_FLAG_NO_CACHE,
+ * will cause a backend lookup -> mock_account_recv_simple() */
+ mock_input_id_ex(nss_test_ctx, id, SSS_NSS_EX_FLAG_NO_CACHE);
+ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWUID_EX);
+ mock_fill_user();
+ mock_account_recv_simple();
+
+ set_cmd_cb(test_nss_getpwuid_check);
+ ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETPWUID_EX,
+ nss_test_ctx->nss_cmds);
+ assert_int_equal(ret, EOK);
+
+ /* Wait until the test finishes with EOK */
+ ret = test_ev_loop(nss_test_ctx->tctx);
+ assert_int_equal(ret, EOK);
+ RESET_TCTX;
+
+ /* Use flag SSS_NSS_EX_FLAG_INVALIDATE_CACHE */
+ mock_input_id_ex(nss_test_ctx, id, SSS_NSS_EX_FLAG_INVALIDATE_CACHE);
+ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETPWUID_EX);
+ mock_fill_user();
+
+ set_cmd_cb(test_nss_getpwuid_check);
+ ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETPWUID_EX,
+ nss_test_ctx->nss_cmds);
+ assert_int_equal(ret, EOK);
+
+ /* Wait until the test finishes with EOK */
+ ret = test_ev_loop(nss_test_ctx->tctx);
+ assert_int_equal(ret, EOK);
+}
+
+void test_nss_getgrnam_ex_no_members(void **state)
+{
+ errno_t ret;
+
+ /* Test group is still in the cache */
+
+ mock_input_user_or_group_ex(true, getgrnam_no_members.gr_name, 0);
+ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETGRNAM_EX);
+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
+
+ /* Query for that group, call a callback when command finishes */
+ set_cmd_cb(test_nss_getgrnam_no_members_check);
+ ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETGRNAM_EX,
+ nss_test_ctx->nss_cmds);
+ assert_int_equal(ret, EOK);
+
+ /* Wait until the test finishes with EOK */
+ ret = test_ev_loop(nss_test_ctx->tctx);
+ assert_int_equal(ret, EOK);
+ RESET_TCTX;
+
+ /* Use old input format, expect failure */
+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_WRAPPER);
+ will_return(__wrap_sss_packet_get_body, "testgroup");
+ will_return(__wrap_sss_packet_get_body, 0);
+ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETGRNAM_EX);
+
+ set_cmd_cb(test_nss_EINVAL_check);
+ ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETGRNAM_EX,
+ nss_test_ctx->nss_cmds);
+ assert_int_equal(ret, EOK);
+
+ ret = test_ev_loop(nss_test_ctx->tctx);
+ assert_int_equal(ret, EOK);
+ RESET_TCTX;
+
+ /* Use unsupported flag combination, expect EINVAL */
+ mock_input_user_or_group_ex(false, getgrnam_no_members.gr_name,
+ SSS_NSS_EX_FLAG_NO_CACHE
+ |SSS_NSS_EX_FLAG_INVALIDATE_CACHE);
+ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETGRNAM_EX);
+
+ set_cmd_cb(test_nss_EINVAL_check);
+ ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETGRNAM_EX,
+ nss_test_ctx->nss_cmds);
+ assert_int_equal(ret, EOK);
+
+ /* Wait until the test finishes with EOK */
+ ret = test_ev_loop(nss_test_ctx->tctx);
+ assert_int_equal(ret, EOK);
+ RESET_TCTX;
+
+ /* Use flag SSS_NSS_EX_FLAG_NO_CACHE,
+ * will cause a backend lookup -> mock_account_recv_simple() */
+ mock_input_user_or_group_ex(true, getgrnam_no_members.gr_name,
+ SSS_NSS_EX_FLAG_NO_CACHE);
+ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETGRNAM_EX);
+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
+ mock_account_recv_simple();
+
+ set_cmd_cb(test_nss_getgrnam_no_members_check);
+ ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETGRNAM_EX,
+ nss_test_ctx->nss_cmds);
+ assert_int_equal(ret, EOK);
+
+ /* Wait until the test finishes with EOK */
+ ret = test_ev_loop(nss_test_ctx->tctx);
+ assert_int_equal(ret, EOK);
+ RESET_TCTX;
+
+ /* Use flag SSS_NSS_EX_FLAG_INVALIDATE_CACHE */
+ mock_input_user_or_group_ex(true, getgrnam_no_members.gr_name,
+ SSS_NSS_EX_FLAG_INVALIDATE_CACHE);
+ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETGRNAM_EX);
+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
+
+ set_cmd_cb(test_nss_getgrnam_no_members_check);
+ ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETGRNAM_EX,
+ nss_test_ctx->nss_cmds);
+ assert_int_equal(ret, EOK);
+
+ /* Wait until the test finishes with EOK */
+ ret = test_ev_loop(nss_test_ctx->tctx);
+ assert_int_equal(ret, EOK);
+}
+
+void test_nss_getgrgid_ex_no_members(void **state)
+{
+ errno_t ret;
+
+ /* Test group is still in the cache */
+
+ mock_input_id_ex(nss_test_ctx, getgrnam_no_members.gr_gid, 0);
+ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETGRGID_EX);
+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
+ mock_account_recv_simple();
+
+ /* Query for that group, call a callback when command finishes */
+ set_cmd_cb(test_nss_getgrnam_no_members_check);
+ ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETGRGID_EX,
+ nss_test_ctx->nss_cmds);
+ assert_int_equal(ret, EOK);
+
+ /* Wait until the test finishes with EOK */
+ ret = test_ev_loop(nss_test_ctx->tctx);
+ assert_int_equal(ret, EOK);
+ RESET_TCTX;
+
+ /* Use old input format, expect failure */
+ mock_input_id(nss_test_ctx, getgrnam_no_members.gr_gid);
+ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETGRGID_EX);
+
+ set_cmd_cb(test_nss_EINVAL_check);
+ ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETGRGID_EX,
+ nss_test_ctx->nss_cmds);
+ assert_int_equal(ret, EOK);
+
+ /* Wait until the test finishes with EOK */
+ ret = test_ev_loop(nss_test_ctx->tctx);
+ assert_int_equal(ret, EOK);
+ RESET_TCTX;
+
+ /* Use unsupported flag combination, expect EINVAL */
+ mock_input_id_ex(nss_test_ctx, getgrnam_no_members.gr_gid,
+ SSS_NSS_EX_FLAG_NO_CACHE
+ |SSS_NSS_EX_FLAG_INVALIDATE_CACHE);
+ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETGRGID_EX);
+
+ set_cmd_cb(test_nss_EINVAL_check);
+ ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETGRGID_EX,
+ nss_test_ctx->nss_cmds);
+ assert_int_equal(ret, EOK);
+
+ /* Wait until the test finishes with EOK */
+ ret = test_ev_loop(nss_test_ctx->tctx);
+ assert_int_equal(ret, EOK);
+ RESET_TCTX;
+
+ /* Use flag SSS_NSS_EX_FLAG_NO_CACHE,
+ * will cause a backend lookup -> mock_account_recv_simple() */
+ mock_input_id_ex(nss_test_ctx, getgrnam_no_members.gr_gid,
+ SSS_NSS_EX_FLAG_NO_CACHE);
+ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETGRGID_EX);
+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
+ mock_account_recv_simple();
+ mock_account_recv_simple();
+
+ set_cmd_cb(test_nss_getgrnam_no_members_check);
+ ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETGRGID_EX,
+ nss_test_ctx->nss_cmds);
+ assert_int_equal(ret, EOK);
+
+ /* Wait until the test finishes with EOK */
+ ret = test_ev_loop(nss_test_ctx->tctx);
+ assert_int_equal(ret, EOK);
+ RESET_TCTX;
+
+ /* Use flag SSS_NSS_EX_FLAG_INVALIDATE_CACHE */
+ mock_input_id_ex(nss_test_ctx, getgrnam_no_members.gr_gid,
+ SSS_NSS_EX_FLAG_INVALIDATE_CACHE);
+ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETGRGID_EX);
+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
+
+ set_cmd_cb(test_nss_getgrnam_no_members_check);
+ ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETGRGID_EX,
+ nss_test_ctx->nss_cmds);
+ assert_int_equal(ret, EOK);
+
+ /* Wait until the test finishes with EOK */
+ ret = test_ev_loop(nss_test_ctx->tctx);
+ assert_int_equal(ret, EOK);
+}
+
+void test_nss_initgroups_ex(void **state)
+{
+ errno_t ret;
+ struct sysdb_attrs *attrs;
+
+ attrs = sysdb_new_attrs(nss_test_ctx);
+ assert_non_null(attrs);
+
+ ret = sysdb_attrs_add_time_t(attrs, SYSDB_INITGR_EXPIRE,
+ time(NULL) + 300);
+ assert_int_equal(ret, EOK);
+
+ ret = sysdb_attrs_add_string(attrs, SYSDB_UPN, "upninitgr@upndomain.test");
+ assert_int_equal(ret, EOK);
+
+ ret = store_user(nss_test_ctx, nss_test_ctx->tctx->dom,
+ &testinitgr_usr, attrs, 0);
+ assert_int_equal(ret, EOK);
+
+ mock_input_user_or_group_ex(true, "testinitgr", 0);
+ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_INITGR_EX);
+ mock_fill_user();
+
+ /* Query for that user, call a callback when command finishes */
+ set_cmd_cb(test_nss_initgr_check);
+ ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_INITGR_EX,
+ nss_test_ctx->nss_cmds);
+ assert_int_equal(ret, EOK);
+
+ /* Wait until the test finishes with EOK */
+ ret = test_ev_loop(nss_test_ctx->tctx);
+ assert_int_equal(ret, EOK);
+ RESET_TCTX;
+
+ /* Use old input format, expect failure */
+ will_return(__wrap_sss_packet_get_body, WRAP_CALL_WRAPPER);
+ will_return(__wrap_sss_packet_get_body, "testinitgr");
+ will_return(__wrap_sss_packet_get_body, 0);
+ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_INITGR_EX);
+
+ set_cmd_cb(test_nss_EINVAL_check);
+ ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_INITGR_EX,
+ nss_test_ctx->nss_cmds);
+ assert_int_equal(ret, EOK);
+
+ ret = test_ev_loop(nss_test_ctx->tctx);
+ assert_int_equal(ret, EOK);
+ RESET_TCTX;
+
+ /* Use unsupported flag combination, expect EINVAL */
+ mock_input_user_or_group_ex(false, "testinitgr",
+ SSS_NSS_EX_FLAG_NO_CACHE
+ |SSS_NSS_EX_FLAG_INVALIDATE_CACHE);
+ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_INITGR_EX);
+
+ set_cmd_cb(test_nss_EINVAL_check);
+ ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_INITGR_EX,
+ nss_test_ctx->nss_cmds);
+ assert_int_equal(ret, EOK);
+
+ /* Wait until the test finishes with EOK */
+ ret = test_ev_loop(nss_test_ctx->tctx);
+ assert_int_equal(ret, EOK);
+ RESET_TCTX;
+
+ /* Use flag SSS_NSS_EX_FLAG_NO_CACHE,
+ * will cause a backend lookup -> mock_account_recv_simple() */
+ mock_input_user_or_group_ex(true, "testinitgr",
+ SSS_NSS_EX_FLAG_NO_CACHE);
+ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_INITGR_EX);
+ mock_fill_user();
+ mock_account_recv_simple();
+
+ set_cmd_cb(test_nss_initgr_check);
+ ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_INITGR_EX,
+ nss_test_ctx->nss_cmds);
+ assert_int_equal(ret, EOK);
+
+ /* Wait until the test finishes with EOK */
+ ret = test_ev_loop(nss_test_ctx->tctx);
+ assert_int_equal(ret, EOK);
+ RESET_TCTX;
+
+ /* Use flag SSS_NSS_EX_FLAG_INVALIDATE_CACHE */
+ mock_input_user_or_group_ex(true, "testinitgr",
+ SSS_NSS_EX_FLAG_INVALIDATE_CACHE);
+ will_return(__wrap_sss_packet_get_cmd, SSS_NSS_INITGR_EX);
+ mock_fill_user();
+
+ set_cmd_cb(test_nss_initgr_check);
+ ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_INITGR_EX,
+ nss_test_ctx->nss_cmds);
+ assert_int_equal(ret, EOK);
+
+ /* Wait until the test finishes with EOK */
+ ret = test_ev_loop(nss_test_ctx->tctx);
+ assert_int_equal(ret, EOK);
+}
+
int main(int argc, const char *argv[])
{
int rv;
@@ -4288,6 +4817,16 @@ int main(int argc, const char *argv[])
nss_test_setup, nss_test_teardown),
cmocka_unit_test_setup_teardown(test_nss_getsidbyname_neg,
nss_test_setup, nss_test_teardown),
+ cmocka_unit_test_setup_teardown(test_nss_getpwnam_ex,
+ nss_test_setup, nss_test_teardown),
+ cmocka_unit_test_setup_teardown(test_nss_getpwuid_ex,
+ nss_test_setup, nss_test_teardown),
+ cmocka_unit_test_setup_teardown(test_nss_getgrnam_ex_no_members,
+ nss_test_setup, nss_test_teardown),
+ cmocka_unit_test_setup_teardown(test_nss_getgrgid_ex_no_members,
+ nss_test_setup, nss_test_teardown),
+ cmocka_unit_test_setup_teardown(test_nss_initgroups_ex,
+ nss_test_setup, nss_test_teardown),
};
/* Set debug level to invalid value so we can deside if -d 0 was used. */
--
2.14.3

View File

@ -0,0 +1,493 @@
From e54db68cbb9c12d8a6867f2c7766fb2115ab0997 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Thu, 2 Nov 2017 10:32:41 +0100
Subject: [PATCH 10/11] nss-idmap: add timeout version of old sss_nss_* calls
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
---
Makefile.am | 2 +-
src/sss_client/idmap/sss_nss_idmap.c | 126 ++++++++++++++++++--------
src/sss_client/idmap/sss_nss_idmap.exports | 7 ++
src/sss_client/idmap/sss_nss_idmap.h | 124 +++++++++++++++++++++++++
src/sss_client/idmap/sss_nss_idmap.unit_tests | 2 +-
src/tests/cmocka/sss_nss_idmap-tests.c | 13 +--
6 files changed, 229 insertions(+), 45 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index dd25d1f7ea1be66388aa1b393bac290c4d7501a2..286ba47e3c421864362717be5258de960efca9f2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2974,7 +2974,6 @@ test_sysdb_domain_resolution_order_LDADD = \
test_wbc_calls_SOURCES = \
src/tests/cmocka/test_wbc_calls.c \
- src/sss_client/idmap/sss_nss_idmap.c \
src/sss_client/libwbclient/wbc_sid_sssd.c \
src/sss_client/libwbclient/wbclient_common.c \
src/sss_client/libwbclient/wbc_sid_common.c \
@@ -2993,6 +2992,7 @@ test_wbc_calls_LDADD = \
$(TALLOC_LIBS) \
$(SSSD_INTERNAL_LTLIBS) \
libsss_test_common.la \
+ libsss_nss_idmap.la \
$(NULL)
test_be_ptask_SOURCES = \
diff --git a/src/sss_client/idmap/sss_nss_idmap.c b/src/sss_client/idmap/sss_nss_idmap.c
index 6f3af267a1e763e7dce77e3862be377ae2bfe984..6e7685d2b1d80956b6a6668e9bbb146abd9e86ed 100644
--- a/src/sss_client/idmap/sss_nss_idmap.c
+++ b/src/sss_client/idmap/sss_nss_idmap.c
@@ -28,10 +28,13 @@
#include "sss_client/sss_cli.h"
#include "sss_client/idmap/sss_nss_idmap.h"
+#include "sss_client/idmap/sss_nss_idmap_private.h"
#include "util/strtonum.h"
#define DATA_START (3 * sizeof(uint32_t))
#define LIST_START (2 * sizeof(uint32_t))
+#define NO_TIMEOUT ((unsigned int) -1)
+
union input {
const char *str;
uint32_t id;
@@ -198,8 +201,8 @@ done:
return ret;
}
-static int sss_nss_getyyybyxxx(union input inp, enum sss_cli_command cmd ,
- struct output *out)
+static int sss_nss_getyyybyxxx(union input inp, enum sss_cli_command cmd,
+ unsigned int timeout, struct output *out)
{
int ret;
size_t inp_len;
@@ -215,6 +218,7 @@ static int sss_nss_getyyybyxxx(union input inp, enum sss_cli_command cmd ,
struct sss_nss_kv *kv_list;
char **names;
enum sss_id_type *types;
+ int time_left = SSS_CLI_SOCKET_TIMEOUT;
switch (cmd) {
case SSS_NSS_GETSIDBYNAME:
@@ -250,9 +254,14 @@ static int sss_nss_getyyybyxxx(union input inp, enum sss_cli_command cmd ,
return EINVAL;
}
- sss_nss_lock();
+ if (timeout == NO_TIMEOUT) {
+ sss_nss_lock();
+ } else {
+ sss_nss_timedlock(timeout, &time_left);
+ }
- nret = sss_nss_make_request(cmd, &rd, &repbuf, &replen, &errnop);
+ nret = sss_nss_make_request_timeout(cmd, &rd, time_left, &repbuf, &replen,
+ &errnop);
if (nret != NSS_STATUS_SUCCESS) {
ret = nss_status_to_errno(nret);
goto done;
@@ -347,8 +356,8 @@ done:
return ret;
}
-int sss_nss_getsidbyname(const char *fq_name, char **sid,
- enum sss_id_type *type)
+int sss_nss_getsidbyname_timeout(const char *fq_name, unsigned int timeout,
+ char **sid, enum sss_id_type *type)
{
int ret;
union input inp;
@@ -360,7 +369,7 @@ int sss_nss_getsidbyname(const char *fq_name, char **sid,
inp.str = fq_name;
- ret = sss_nss_getyyybyxxx(inp, SSS_NSS_GETSIDBYNAME, &out);
+ ret = sss_nss_getyyybyxxx(inp, SSS_NSS_GETSIDBYNAME, timeout, &out);
if (ret == EOK) {
*sid = out.d.str;
*type = out.type;
@@ -369,7 +378,14 @@ int sss_nss_getsidbyname(const char *fq_name, char **sid,
return ret;
}
-int sss_nss_getsidbyid(uint32_t id, char **sid, enum sss_id_type *type)
+int sss_nss_getsidbyname(const char *fq_name, char **sid,
+ enum sss_id_type *type)
+{
+ return sss_nss_getsidbyname_timeout(fq_name, NO_TIMEOUT, sid, type);
+}
+
+int sss_nss_getsidbyid_timeout(uint32_t id, unsigned int timeout,
+ char **sid, enum sss_id_type *type)
{
int ret;
union input inp;
@@ -381,7 +397,7 @@ int sss_nss_getsidbyid(uint32_t id, char **sid, enum sss_id_type *type)
inp.id = id;
- ret = sss_nss_getyyybyxxx(inp, SSS_NSS_GETSIDBYID, &out);
+ ret = sss_nss_getyyybyxxx(inp, SSS_NSS_GETSIDBYID, timeout, &out);
if (ret == EOK) {
*sid = out.d.str;
*type = out.type;
@@ -390,8 +406,13 @@ int sss_nss_getsidbyid(uint32_t id, char **sid, enum sss_id_type *type)
return ret;
}
-int sss_nss_getnamebysid(const char *sid, char **fq_name,
- enum sss_id_type *type)
+int sss_nss_getsidbyid(uint32_t id, char **sid, enum sss_id_type *type)
+{
+ return sss_nss_getsidbyid_timeout(id, NO_TIMEOUT, sid, type);
+}
+
+int sss_nss_getnamebysid_timeout(const char *sid, unsigned int timeout,
+ char **fq_name, enum sss_id_type *type)
{
int ret;
union input inp;
@@ -403,7 +424,7 @@ int sss_nss_getnamebysid(const char *sid, char **fq_name,
inp.str = sid;
- ret = sss_nss_getyyybyxxx(inp, SSS_NSS_GETNAMEBYSID, &out);
+ ret = sss_nss_getyyybyxxx(inp, SSS_NSS_GETNAMEBYSID, timeout, &out);
if (ret == EOK) {
*fq_name = out.d.str;
*type = out.type;
@@ -412,7 +433,14 @@ int sss_nss_getnamebysid(const char *sid, char **fq_name,
return ret;
}
-int sss_nss_getidbysid(const char *sid, uint32_t *id, enum sss_id_type *id_type)
+int sss_nss_getnamebysid(const char *sid, char **fq_name,
+ enum sss_id_type *type)
+{
+ return sss_nss_getnamebysid_timeout(sid, NO_TIMEOUT, fq_name, type);
+}
+
+int sss_nss_getidbysid_timeout(const char *sid, unsigned int timeout,
+ uint32_t *id, enum sss_id_type *id_type)
{
int ret;
union input inp;
@@ -424,7 +452,7 @@ int sss_nss_getidbysid(const char *sid, uint32_t *id, enum sss_id_type *id_type)
inp.str = sid;
- ret = sss_nss_getyyybyxxx(inp, SSS_NSS_GETIDBYSID, &out);
+ ret = sss_nss_getyyybyxxx(inp, SSS_NSS_GETIDBYSID, timeout, &out);
if (ret == EOK) {
*id = out.d.id;
*id_type = out.type;
@@ -433,8 +461,14 @@ int sss_nss_getidbysid(const char *sid, uint32_t *id, enum sss_id_type *id_type)
return ret;
}
-int sss_nss_getorigbyname(const char *fq_name, struct sss_nss_kv **kv_list,
- enum sss_id_type *type)
+int sss_nss_getidbysid(const char *sid, uint32_t *id, enum sss_id_type *id_type)
+{
+ return sss_nss_getidbysid_timeout(sid, NO_TIMEOUT, id, id_type);
+}
+
+int sss_nss_getorigbyname_timeout(const char *fq_name, unsigned int timeout,
+ struct sss_nss_kv **kv_list,
+ enum sss_id_type *type)
{
int ret;
union input inp;
@@ -446,7 +480,7 @@ int sss_nss_getorigbyname(const char *fq_name, struct sss_nss_kv **kv_list,
inp.str = fq_name;
- ret = sss_nss_getyyybyxxx(inp, SSS_NSS_GETORIGBYNAME, &out);
+ ret = sss_nss_getyyybyxxx(inp, SSS_NSS_GETORIGBYNAME, timeout, &out);
if (ret == EOK) {
*kv_list = out.d.kv_list;
*type = out.type;
@@ -455,30 +489,42 @@ int sss_nss_getorigbyname(const char *fq_name, struct sss_nss_kv **kv_list,
return ret;
}
+int sss_nss_getorigbyname(const char *fq_name, struct sss_nss_kv **kv_list,
+ enum sss_id_type *type)
+{
+ return sss_nss_getorigbyname_timeout(fq_name, NO_TIMEOUT, kv_list, type);
+}
+
+int sss_nss_getnamebycert_timeout(const char *cert, unsigned int timeout,
+ char **fq_name, enum sss_id_type *type)
+{
+ int ret;
+ union input inp;
+ struct output out;
+
+ if (fq_name == NULL || cert == NULL || *cert == '\0') {
+ return EINVAL;
+ }
+
+ inp.str = cert;
+
+ ret = sss_nss_getyyybyxxx(inp, SSS_NSS_GETNAMEBYCERT, timeout, &out);
+ if (ret == EOK) {
+ *fq_name = out.d.str;
+ *type = out.type;
+ }
+
+ return ret;
+}
+
int sss_nss_getnamebycert(const char *cert, char **fq_name,
enum sss_id_type *type)
{
- int ret;
- union input inp;
- struct output out;
-
- if (fq_name == NULL || cert == NULL || *cert == '\0') {
- return EINVAL;
- }
-
- inp.str = cert;
-
- ret = sss_nss_getyyybyxxx(inp, SSS_NSS_GETNAMEBYCERT, &out);
- if (ret == EOK) {
- *fq_name = out.d.str;
- *type = out.type;
- }
-
- return ret;
+ return sss_nss_getnamebycert_timeout(cert, NO_TIMEOUT, fq_name, type);
}
-int sss_nss_getlistbycert(const char *cert, char ***fq_name,
- enum sss_id_type **type)
+int sss_nss_getlistbycert_timeout(const char *cert, unsigned int timeout,
+ char ***fq_name, enum sss_id_type **type)
{
int ret;
union input inp;
@@ -490,7 +536,7 @@ int sss_nss_getlistbycert(const char *cert, char ***fq_name,
inp.str = cert;
- ret = sss_nss_getyyybyxxx(inp, SSS_NSS_GETLISTBYCERT, &out);
+ ret = sss_nss_getyyybyxxx(inp, SSS_NSS_GETLISTBYCERT, timeout, &out);
if (ret == EOK) {
*fq_name = out.d.names;
*type = out.types;
@@ -498,3 +544,9 @@ int sss_nss_getlistbycert(const char *cert, char ***fq_name,
return ret;
}
+
+int sss_nss_getlistbycert(const char *cert, char ***fq_name,
+ enum sss_id_type **type)
+{
+ return sss_nss_getlistbycert_timeout(cert, NO_TIMEOUT, fq_name, type);
+}
diff --git a/src/sss_client/idmap/sss_nss_idmap.exports b/src/sss_client/idmap/sss_nss_idmap.exports
index 788d05ecc3bd56fa88e68a98b9c8096cf7140a09..8d0a24f42aa3fb3dd9c2ed125bf79e2c7792993f 100644
--- a/src/sss_client/idmap/sss_nss_idmap.exports
+++ b/src/sss_client/idmap/sss_nss_idmap.exports
@@ -40,4 +40,11 @@ SSS_NSS_IDMAP_0.4.0 {
sss_nss_getgrnam_timeout;
sss_nss_getgrgid_timeout;
sss_nss_getgrouplist_timeout;
+ sss_nss_getsidbyname_timeout;
+ sss_nss_getsidbyid_timeout;
+ sss_nss_getnamebysid_timeout;
+ sss_nss_getidbysid_timeout;
+ sss_nss_getorigbyname_timeout;
+ sss_nss_getnamebycert_timeout;
+ sss_nss_getlistbycert_timeout;
} SSS_NSS_IDMAP_0.3.0;
diff --git a/src/sss_client/idmap/sss_nss_idmap.h b/src/sss_client/idmap/sss_nss_idmap.h
index 3755643312f05a31d1cf1aa76dfc22848ef1e3ec..125e72a6486f5916f90d37f27e1743d181bfa3e5 100644
--- a/src/sss_client/idmap/sss_nss_idmap.h
+++ b/src/sss_client/idmap/sss_nss_idmap.h
@@ -303,5 +303,129 @@ int sss_nss_getgrgid_timeout(gid_t gid, struct group *grp,
int sss_nss_getgrouplist_timeout(const char *name, gid_t group,
gid_t *groups, int *ngroups,
uint32_t flags, unsigned int timeout);
+/**
+ * @brief Find SID by fully qualified name with timeout
+ *
+ * @param[in] fq_name Fully qualified name of a user or a group
+ * @param[in] timeout timeout in milliseconds
+ * @param[out] sid String representation of the SID of the requested user
+ * or group, must be freed by the caller
+ * @param[out] type Type of the object related to the given name
+ *
+ * @return
+ * - 0 (EOK): success, sid contains the requested SID
+ * - ENOENT: requested object was not found in the domain extracted from the given name
+ * - ENETUNREACH: SSSD does not know how to handle the domain extracted from the given name
+ * - ENOSYS: this call is not supported by the configured provider
+ * - EINVAL: input cannot be parsed
+ * - EIO: remote servers cannot be reached
+ * - EFAULT: any other error
+ * - ETIME: request timed out but was send to SSSD
+ * - ETIMEDOUT: request timed out but was not send to SSSD
+ */
+int sss_nss_getsidbyname_timeout(const char *fq_name, unsigned int timeout,
+ char **sid, enum sss_id_type *type);
+
+/**
+ * @brief Find SID by a POSIX UID or GID with timeout
+ *
+ * @param[in] id POSIX UID or GID
+ * @param[in] timeout timeout in milliseconds
+ * @param[out] sid String representation of the SID of the requested user
+ * or group, must be freed by the caller
+ * @param[out] type Type of the object related to the given ID
+ *
+ * @return
+ * - see #sss_nss_getsidbyname_timeout
+ */
+int sss_nss_getsidbyid_timeout(uint32_t id, unsigned int timeout,
+ char **sid, enum sss_id_type *type);
+
+/**
+ * @brief Return the fully qualified name for the given SID with timeout
+ *
+ * @param[in] sid String representation of the SID
+ * @param[in] timeout timeout in milliseconds
+ * @param[out] fq_name Fully qualified name of a user or a group,
+ * must be freed by the caller
+ * @param[out] type Type of the object related to the SID
+ *
+ * @return
+ * - see #sss_nss_getsidbyname_timeout
+ */
+int sss_nss_getnamebysid_timeout(const char *sid, unsigned int timeout,
+ char **fq_name, enum sss_id_type *type);
+
+/**
+ * @brief Return the POSIX ID for the given SID with timeout
+ *
+ * @param[in] sid String representation of the SID
+ * @param[in] timeout timeout in milliseconds
+ * @param[out] id POSIX ID related to the SID
+ * @param[out] id_type Type of the object related to the SID
+ *
+ * @return
+ * - see #sss_nss_getsidbyname_timeout
+ */
+int sss_nss_getidbysid_timeout(const char *sid, unsigned int timeout,
+ uint32_t *id, enum sss_id_type *id_type);
+
+/**
+ * @brief Find original data by fully qualified name with timeout
+ *
+ * @param[in] fq_name Fully qualified name of a user or a group
+ * @param[in] timeout timeout in milliseconds
+ * @param[out] kv_list A NULL terminate list of key-value pairs where the key
+ * is the attribute name in the cache of SSSD,
+ * must be freed by the caller with sss_nss_free_kv()
+ * @param[out] type Type of the object related to the given name
+ *
+ * @return
+ * - 0 (EOK): success, sid contains the requested SID
+ * - ENOENT: requested object was not found in the domain extracted from the given name
+ * - ENETUNREACH: SSSD does not know how to handle the domain extracted from the given name
+ * - ENOSYS: this call is not supported by the configured provider
+ * - EINVAL: input cannot be parsed
+ * - EIO: remote servers cannot be reached
+ * - EFAULT: any other error
+ * - ETIME: request timed out but was send to SSSD
+ * - ETIMEDOUT: request timed out but was not send to SSSD
+ */
+int sss_nss_getorigbyname_timeout(const char *fq_name, unsigned int timeout,
+ struct sss_nss_kv **kv_list,
+ enum sss_id_type *type);
+
+/**
+ * @brief Return the fully qualified name for the given base64 encoded
+ * X.509 certificate in DER format with timeout
+ *
+ * @param[in] cert base64 encoded certificate
+ * @param[in] timeout timeout in milliseconds
+ * @param[out] fq_name Fully qualified name of a user or a group,
+ * must be freed by the caller
+ * @param[out] type Type of the object related to the cert
+ *
+ * @return
+ * - see #sss_nss_getsidbyname_timeout
+ */
+int sss_nss_getnamebycert_timeout(const char *cert, unsigned int timeout,
+ char **fq_name, enum sss_id_type *type);
+
+/**
+ * @brief Return a list of fully qualified names for the given base64 encoded
+ * X.509 certificate in DER format with timeout
+ *
+ * @param[in] cert base64 encoded certificate
+ * @param[in] timeout timeout in milliseconds
+ * @param[out] fq_name List of fully qualified name of users or groups,
+ * must be freed by the caller
+ * @param[out] type List of types of the objects related to the cert
+ *
+ * @return
+ * - see #sss_nss_getsidbyname_timeout
+ */
+int sss_nss_getlistbycert_timeout(const char *cert, unsigned int timeout,
+ char ***fq_name, enum sss_id_type **type);
+
#endif /* IPA_389DS_PLUGIN_HELPER_CALLS */
#endif /* SSS_NSS_IDMAP_H_ */
diff --git a/src/sss_client/idmap/sss_nss_idmap.unit_tests b/src/sss_client/idmap/sss_nss_idmap.unit_tests
index 361cc3b134ead52cf458afe27c055739d6728441..05c474f008e1d59aae5976acfd81613c3c3e6540 100644
--- a/src/sss_client/idmap/sss_nss_idmap.unit_tests
+++ b/src/sss_client/idmap/sss_nss_idmap.unit_tests
@@ -2,5 +2,5 @@
UNIT_TEST_ONLY {
# should not be part of installed library
global:
- sss_nss_make_request;
+ sss_nss_make_request_timeout;
};
diff --git a/src/tests/cmocka/sss_nss_idmap-tests.c b/src/tests/cmocka/sss_nss_idmap-tests.c
index 8807eca619d7b07d919168e5629042cf38f654ac..2e37040d2d3523bea157804706685fa0b36df16a 100644
--- a/src/tests/cmocka/sss_nss_idmap-tests.c
+++ b/src/tests/cmocka/sss_nss_idmap-tests.c
@@ -61,10 +61,11 @@ uint8_t buf_orig1[] = {0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0
#error "unknow endianess"
#endif
-enum nss_status sss_nss_make_request(enum sss_cli_command cmd,
- struct sss_cli_req_data *rd,
- uint8_t **repbuf, size_t *replen,
- int *errnop)
+enum nss_status sss_nss_make_request_timeout(enum sss_cli_command cmd,
+ struct sss_cli_req_data *rd,
+ int timeout,
+ uint8_t **repbuf, size_t *replen,
+ int *errnop)
{
struct sss_nss_make_request_test_data *d;
@@ -114,7 +115,7 @@ void test_getsidbyname(void **state)
sid = NULL;
for (c = 0; d[c].d.repbuf != NULL; c++) {
- will_return(sss_nss_make_request, &d[0].d);
+ will_return(sss_nss_make_request_timeout, &d[0].d);
ret = sss_nss_getsidbyname("test", &sid, &type);
assert_int_equal(ret, d[0].ret);
@@ -134,7 +135,7 @@ void test_getorigbyname(void **state)
enum sss_id_type type;
struct sss_nss_make_request_test_data d = {buf_orig1, sizeof(buf_orig1), 0, NSS_STATUS_SUCCESS};
- will_return(sss_nss_make_request, &d);
+ will_return(sss_nss_make_request_timeout, &d);
ret = sss_nss_getorigbyname("test", &kv_list, &type);
assert_int_equal(ret, EOK);
assert_int_equal(type, SSS_ID_TYPE_UID);
--
2.14.3

View File

@ -0,0 +1,183 @@
From 859bddc2bf51dc426a3dc56bd9f365e9c5722b65 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Thu, 2 Nov 2017 11:09:20 +0100
Subject: [PATCH 11/11] nss-idmap: allow empty buffer with
SSS_NSS_EX_FLAG_INVALIDATE_CACHE
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
---
src/sss_client/idmap/sss_nss_ex.c | 89 ++++++++++++++++++++++++++-------------
1 file changed, 60 insertions(+), 29 deletions(-)
diff --git a/src/sss_client/idmap/sss_nss_ex.c b/src/sss_client/idmap/sss_nss_ex.c
index 148eb7b35ec236b6272dd203a0035399cfdef73d..dcd9619a8b07ced7498f61b7e809fa46ebffe09e 100644
--- a/src/sss_client/idmap/sss_nss_ex.c
+++ b/src/sss_client/idmap/sss_nss_ex.c
@@ -103,8 +103,11 @@ errno_t sss_nss_mc_get(struct nss_input *inp)
}
}
-static int check_flags(uint32_t flags)
+static int check_flags(struct nss_input *inp, uint32_t flags,
+ bool *skip_mc, bool *skip_data)
{
+ bool no_data = false;
+
/* SSS_NSS_EX_FLAG_NO_CACHE and SSS_NSS_EX_FLAG_INVALIDATE_CACHE are
* mutually exclusive */
if ((flags & SSS_NSS_EX_FLAG_NO_CACHE) != 0
@@ -112,6 +115,52 @@ static int check_flags(uint32_t flags)
return EINVAL;
}
+ *skip_mc = false;
+ if ((flags & SSS_NSS_EX_FLAG_NO_CACHE) != 0
+ || (flags & SSS_NSS_EX_FLAG_INVALIDATE_CACHE) != 0) {
+ *skip_mc = true;
+ }
+
+ switch(inp->cmd) {
+ case SSS_NSS_GETPWNAM:
+ case SSS_NSS_GETPWNAM_EX:
+ case SSS_NSS_GETPWUID:
+ case SSS_NSS_GETPWUID_EX:
+ if (inp->result.pwrep.buffer == NULL
+ || inp->result.pwrep.buflen == 0) {
+ no_data = true;
+ }
+ break;
+ case SSS_NSS_GETGRNAM:
+ case SSS_NSS_GETGRNAM_EX:
+ case SSS_NSS_GETGRGID:
+ case SSS_NSS_GETGRGID_EX:
+ if (inp->result.grrep.buffer == NULL
+ || inp->result.grrep.buflen == 0) {
+ no_data = true;
+ }
+ break;
+ case SSS_NSS_INITGR:
+ case SSS_NSS_INITGR_EX:
+ if (inp->result.initgrrep.ngroups == 0
+ || inp->result.initgrrep.groups == NULL) {
+ return EINVAL;
+ }
+ break;
+ default:
+ return EINVAL;
+ }
+
+ *skip_data = false;
+ /* Allow empty buffer with SSS_NSS_EX_FLAG_INVALIDATE_CACHE */
+ if (no_data) {
+ if ((flags & SSS_NSS_EX_FLAG_INVALIDATE_CACHE) != 0) {
+ *skip_data = true;
+ } else {
+ return ERANGE;
+ }
+ }
+
return 0;
}
@@ -128,18 +177,14 @@ int sss_get_ex(struct nss_input *inp, uint32_t flags, unsigned int timeout)
gid_t *new_groups;
size_t idx;
bool skip_mc = false;
+ bool skip_data = false;
- ret = check_flags(flags);
+ ret = check_flags(inp, flags, &skip_mc, &skip_data);
if (ret != 0) {
return ret;
}
- if ((flags & SSS_NSS_EX_FLAG_NO_CACHE) != 0
- || (flags & SSS_NSS_EX_FLAG_INVALIDATE_CACHE) != 0) {
- skip_mc = true;
- }
-
- if (!skip_mc) {
+ if (!skip_mc && !skip_data) {
ret = sss_nss_mc_get(inp);
switch (ret) {
case 0:
@@ -159,7 +204,7 @@ int sss_get_ex(struct nss_input *inp, uint32_t flags, unsigned int timeout)
sss_nss_timedlock(timeout, &time_left);
- if (!skip_mc) {
+ if (!skip_mc && !skip_data) {
/* previous thread might already initialize entry in mmap cache */
ret = sss_nss_mc_get(inp);
switch (ret) {
@@ -196,6 +241,12 @@ int sss_get_ex(struct nss_input *inp, uint32_t flags, unsigned int timeout)
goto out;
}
+ if (skip_data) {
+ /* No data requested, just return the return code */
+ ret = 0;
+ goto out;
+ }
+
if (inp->cmd == SSS_NSS_INITGR || inp->cmd == SSS_NSS_INITGR_EX) {
if ((*(inp->result.initgrrep.ngroups) - *(inp->result.initgrrep.start))
< num_results) {
@@ -311,10 +362,6 @@ int sss_nss_getpwnam_timeout(const char *name, struct passwd *pwd,
.result.pwrep.buffer = buffer,
.result.pwrep.buflen = buflen};
- if (buffer == NULL || buflen == 0) {
- return ERANGE;
- }
-
ret = make_name_flag_req_data(name, flags, &inp.rd);
if (ret != 0) {
return ret;
@@ -346,10 +393,6 @@ int sss_nss_getpwuid_timeout(uid_t uid, struct passwd *pwd,
.result.pwrep.buffer = buffer,
.result.pwrep.buflen = buflen};
- if (buffer == NULL || buflen == 0) {
- return ERANGE;
- }
-
SAFEALIGN_COPY_UINT32(&req_data[0], &uid, NULL);
SAFEALIGN_COPY_UINT32(&req_data[1], &flags, NULL);
*result = NULL;
@@ -373,10 +416,6 @@ int sss_nss_getgrnam_timeout(const char *name, struct group *grp,
.result.grrep.buffer = buffer,
.result.grrep.buflen = buflen};
- if (buffer == NULL || buflen == 0) {
- return ERANGE;
- }
-
ret = make_name_flag_req_data(name, flags, &inp.rd);
if (ret != 0) {
return ret;
@@ -407,10 +446,6 @@ int sss_nss_getgrgid_timeout(gid_t gid, struct group *grp,
.result.grrep.buffer = buffer,
.result.grrep.buflen = buflen};
- if (buffer == NULL || buflen == 0) {
- return ERANGE;
- }
-
SAFEALIGN_COPY_UINT32(&req_data[0], &gid, NULL);
SAFEALIGN_COPY_UINT32(&req_data[1], &flags, NULL);
*result = NULL;
@@ -434,10 +469,6 @@ int sss_nss_getgrouplist_timeout(const char *name, gid_t group,
.input.name = name,
.cmd = SSS_NSS_INITGR_EX};
- if (groups == NULL || ngroups == NULL || *ngroups == 0) {
- return EINVAL;
- }
-
ret = make_name_flag_req_data(name, flags, &inp.rd);
if (ret != 0) {
return ret;
--
2.14.3

View File

@ -29,7 +29,7 @@
Name: sssd
Version: 1.16.0
Release: 2%{?dist}
Release: 3%{?dist}
Group: Applications/System
Summary: System Security Services Daemon
License: GPLv3+
@ -39,6 +39,17 @@ BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
### Patches ###
Patch0001: 0001-KCM-Fix-restart-during-after-upgrade.patch
Patch0002: 0002-sss_client-create-nss_common.h.patch
Patch0003: 0003-nss-idmap-add-nss-like-calls-with-timeout-and-flags.patch
Patch0004: 0004-NSS-add-_EX-version-of-some-requests.patch
Patch0005: 0005-NSS-add-support-for-SSS_NSS_EX_FLAG_NO_CACHE.patch
Patch0006: 0006-CACHE_REQ-Add-cache_req_data_set_bypass_dp.patch
Patch0007: 0007-nss-make-memcache_delete_entry-public.patch
Patch0008: 0008-NSS-add-support-for-SSS_NSS_EX_FLAG_INVALIDATE_CACHE.patch
Patch0009: 0009-NSS-TESTS-add-unit-tests-for-_EX-requests.patch
Patch0010: 0010-nss-idmap-add-timeout-version-of-old-sss_nss_-calls.patch
Patch0011: 0011-nss-idmap-allow-empty-buffer-with-SSS_NSS_EX_FLAG_IN.patch
Patch0502: 0502-SYSTEMD-Use-capabilities.patch
Patch0503: 0503-Disable-stopping-idle-socket-activated-responders.patch
Patch0600: 0600-tests-cmocka-Fix-unit-tests-with-libldb-1.3.0.patch
@ -1251,6 +1262,9 @@ fi
%{_libdir}/%{name}/modules/libwbclient.so
%changelog
* Fri Nov 17 2017 Jakub Hrozek <jhrozek@redhat.com> - 1.16.0-3
- Backport extended NSS API from upstream master branch
* Fri Nov 03 2017 Lukas Slebodnik <lslebodn@fedoraproject.org> - 1.16.0-2
- Resolves: upstream#3529 - sssd-kcm Fix restart during/after upgrade