From 15d7f1aeb541615314b914b6be1149f6e289d3e2 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Fri, 29 Sep 2017 16:16:01 +0200
Subject: [PATCH 23/31] 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>
(cherry picked from commit 5e6622722e84d594298a8324f3685a1bda2b5868)
---
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.13.6