|
|
3f51ca |
From 8a80363e07b5c9309d785bf3b41f506f32a750a5 Mon Sep 17 00:00:00 2001
|
|
|
3f51ca |
From: Alexander Bokovoy <abokovoy@redhat.com>
|
|
|
3f51ca |
Date: Tue, 14 Nov 2017 12:44:02 +0200
|
|
|
3f51ca |
Subject: [PATCH] ipa-extdom-extop: refactor nsswitch operations
|
|
|
3f51ca |
|
|
|
3f51ca |
Refactor nsswitch operations in ipa-extdom-extop plugin to allow use
|
|
|
3f51ca |
of timeout-enabled nsswitch calls provided by libsss_nss_idmap.
|
|
|
3f51ca |
|
|
|
3f51ca |
Standard POSIX nsswitch API has no way to cancel requests which may
|
|
|
3f51ca |
cause ipa-extdom-extop requests to hang far too long and potentially
|
|
|
3f51ca |
exhaust LDAP server workers. In addition, glibc nsswitch API iterates
|
|
|
3f51ca |
through all nsswitch modules one by one and with multiple parallel
|
|
|
3f51ca |
requests a lock up may happen in an unrelated nsswitch module like
|
|
|
3f51ca |
nss_files.so.2.
|
|
|
3f51ca |
|
|
|
3f51ca |
A solution to the latter issue is to directly load nss_sss.so.2 plugin
|
|
|
3f51ca |
and utilize it. This, however, does not solve a problem with lack of
|
|
|
3f51ca |
cancellable API.
|
|
|
3f51ca |
|
|
|
3f51ca |
With SSSD 1.16.1, libsss_nss_idmap provides a timeout-enabled variant of
|
|
|
3f51ca |
nsswitch API that is directly integrated with SSSD client side machinery
|
|
|
3f51ca |
used by nss_sss.so.2. As result, this API can be used instead of loading
|
|
|
3f51ca |
nss_sss.so.2 directly.
|
|
|
3f51ca |
|
|
|
3f51ca |
To support older SSSD version, both direct loading of nss_sss.so.2 and
|
|
|
3f51ca |
new timeout-enabled API are supported by this changeset. An API to
|
|
|
3f51ca |
abstract both is designed to be a mix between internal glibc nsswitch
|
|
|
3f51ca |
API and external nsswitch API that libsss_nss_idmap mimics. API does not
|
|
|
3f51ca |
expose per-call timeout. Instead, it allows to set a timeout per
|
|
|
3f51ca |
nsswitch operation context to reduce requirements on information
|
|
|
3f51ca |
a caller has to maintain.
|
|
|
3f51ca |
|
|
|
3f51ca |
A choice which API to use is made at configure time.
|
|
|
3f51ca |
|
|
|
3f51ca |
In order to test the API, a cmocka test is updated to explicitly load
|
|
|
3f51ca |
nss_files.so.2 as a backend. Since use of nss_sss.so.2 would always
|
|
|
3f51ca |
depend on availablility of SSSD, predictable testing would not be
|
|
|
3f51ca |
possible without it otherwise. Also, cmocka test does not use
|
|
|
3f51ca |
nss_wrapper anymore because nss_wrapper overrides higher level glibc
|
|
|
3f51ca |
nsswitch API while we are loading an individual nsswitch module
|
|
|
3f51ca |
directly.
|
|
|
3f51ca |
|
|
|
3f51ca |
As result, cmocka test overrides fopen() call used by nss_files.so.2 to
|
|
|
3f51ca |
load /etc/passwd and /etc/group. An overridden version changes paths to
|
|
|
3f51ca |
/etc/passwd and /etc/group to a local test_data/passwd and
|
|
|
3f51ca |
test_data/group. This way we can continue testing a backend API for
|
|
|
3f51ca |
ipa-extdom-extop with the same data as with nss_wrapper.
|
|
|
3f51ca |
|
|
|
3f51ca |
Fixes https://pagure.io/freeipa/issue/5464
|
|
|
3f51ca |
|
|
|
3f51ca |
Reviewed-By: Christian Heimes <cheimes@redhat.com>
|
|
|
3f51ca |
Reviewed-By: Simo Sorce <ssorce@redhat.com>
|
|
|
3f51ca |
Reviewed-By: Robbie Harwood <rharwood@redhat.com>
|
|
|
3f51ca |
---
|
|
|
3f51ca |
configure.ac | 25 +-
|
|
|
3f51ca |
.../ipa-slapi-plugins/ipa-extdom-extop/Makefile.am | 17 +-
|
|
|
3f51ca |
.../ipa-extdom-extop/back_extdom.h | 79 ++++++
|
|
|
3f51ca |
.../ipa-extdom-extop/back_extdom_nss_sss.c | 276 +++++++++++++++++++++
|
|
|
3f51ca |
.../ipa-extdom-extop/back_extdom_sss_idmap.c | 260 +++++++++++++++++++
|
|
|
3f51ca |
.../ipa-extdom-extop/ipa_extdom.h | 13 +-
|
|
|
3f51ca |
.../ipa-extdom-extop/ipa_extdom_cmocka_tests.c | 241 +++++++++++++++---
|
|
|
3f51ca |
.../ipa-extdom-extop/ipa_extdom_common.c | 242 +++++++++---------
|
|
|
3f51ca |
.../ipa-extdom-extop/ipa_extdom_extop.c | 17 ++
|
|
|
3f51ca |
.../ipa-extdom-extop/test_data/test_setup.sh | 3 -
|
|
|
3f51ca |
freeipa.spec.in | 1 -
|
|
|
3f51ca |
server.m4 | 10 +
|
|
|
3f51ca |
12 files changed, 994 insertions(+), 190 deletions(-)
|
|
|
3f51ca |
create mode 100644 daemons/ipa-slapi-plugins/ipa-extdom-extop/back_extdom.h
|
|
|
3f51ca |
create mode 100644 daemons/ipa-slapi-plugins/ipa-extdom-extop/back_extdom_nss_sss.c
|
|
|
3f51ca |
create mode 100644 daemons/ipa-slapi-plugins/ipa-extdom-extop/back_extdom_sss_idmap.c
|
|
|
3f51ca |
delete mode 100644 daemons/ipa-slapi-plugins/ipa-extdom-extop/test_data/test_setup.sh
|
|
|
3f51ca |
|
|
|
3f51ca |
diff --git a/configure.ac b/configure.ac
|
|
|
3f51ca |
index e7a8b11153209fdfb4903cd3876e21a871a92f03..8a99b028886790aca211ddf164772920221f3ec7 100644
|
|
|
3f51ca |
--- a/configure.ac
|
|
|
3f51ca |
+++ b/configure.ac
|
|
|
3f51ca |
@@ -140,30 +140,6 @@ PKG_CHECK_EXISTS(cmocka,
|
|
|
3f51ca |
)
|
|
|
3f51ca |
AM_CONDITIONAL([HAVE_CMOCKA], [test x$have_cmocka = xyes])
|
|
|
3f51ca |
|
|
|
3f51ca |
-dnl A macro to check presence of a cwrap (http://cwrap.org) wrapper on the system
|
|
|
3f51ca |
-dnl Usage:
|
|
|
3f51ca |
-dnl AM_CHECK_WRAPPER(name, conditional)
|
|
|
3f51ca |
-dnl If the cwrap library is found, sets the HAVE_$name conditional
|
|
|
3f51ca |
-AC_DEFUN([AM_CHECK_WRAPPER],
|
|
|
3f51ca |
-[
|
|
|
3f51ca |
- FOUND_WRAPPER=0
|
|
|
3f51ca |
-
|
|
|
3f51ca |
- AC_MSG_CHECKING([for $1])
|
|
|
3f51ca |
- PKG_CHECK_EXISTS([$1],
|
|
|
3f51ca |
- [
|
|
|
3f51ca |
- AC_MSG_RESULT([yes])
|
|
|
3f51ca |
- FOUND_WRAPPER=1
|
|
|
3f51ca |
- ],
|
|
|
3f51ca |
- [
|
|
|
3f51ca |
- AC_MSG_RESULT([no])
|
|
|
3f51ca |
- AC_MSG_WARN([cwrap library $1 not found, some tests will not run])
|
|
|
3f51ca |
- ])
|
|
|
3f51ca |
-
|
|
|
3f51ca |
- AM_CONDITIONAL($2, [ test x$FOUND_WRAPPER = x1])
|
|
|
3f51ca |
-])
|
|
|
3f51ca |
-
|
|
|
3f51ca |
-AM_CHECK_WRAPPER(nss_wrapper, HAVE_NSS_WRAPPER)
|
|
|
3f51ca |
-
|
|
|
3f51ca |
dnl ---------------------------------------------------------------------------
|
|
|
3f51ca |
dnl - Check for POPT
|
|
|
3f51ca |
dnl ---------------------------------------------------------------------------
|
|
|
3f51ca |
@@ -235,6 +211,7 @@ dnl ---------------------------------------------------------------------------
|
|
|
3f51ca |
AM_COND_IF([ENABLE_SERVER], [
|
|
|
3f51ca |
m4_include(server.m4)
|
|
|
3f51ca |
])
|
|
|
3f51ca |
+AM_CONDITIONAL([USE_SSS_NSS_TIMEOUT], [test "x$ac_cv_have_decl_sss_nss_getpwnam_timeout" = xyes])
|
|
|
3f51ca |
|
|
|
3f51ca |
dnl ---------------------------------------------------------------------------
|
|
|
3f51ca |
dnl - Check if IPA certauth plugin can be build
|
|
|
3f51ca |
diff --git a/daemons/ipa-slapi-plugins/ipa-extdom-extop/Makefile.am b/daemons/ipa-slapi-plugins/ipa-extdom-extop/Makefile.am
|
|
|
3f51ca |
index 1213965c96607bf14c6c92ce592585aed1a125db..cbdd570eabeb12b95fdc26213a64749f9ba9fdde 100644
|
|
|
3f51ca |
--- a/daemons/ipa-slapi-plugins/ipa-extdom-extop/Makefile.am
|
|
|
3f51ca |
+++ b/daemons/ipa-slapi-plugins/ipa-extdom-extop/Makefile.am
|
|
|
3f51ca |
@@ -25,6 +25,7 @@ libipa_extdom_extop_la_SOURCES = \
|
|
|
3f51ca |
ipa_extdom.h \
|
|
|
3f51ca |
ipa_extdom_extop.c \
|
|
|
3f51ca |
ipa_extdom_common.c \
|
|
|
3f51ca |
+ back_extdom.h \
|
|
|
3f51ca |
$(NULL)
|
|
|
3f51ca |
|
|
|
3f51ca |
libipa_extdom_extop_la_LDFLAGS = -avoid-version
|
|
|
3f51ca |
@@ -34,20 +35,29 @@ libipa_extdom_extop_la_LIBADD = \
|
|
|
3f51ca |
$(SSSNSSIDMAP_LIBS) \
|
|
|
3f51ca |
$(NULL)
|
|
|
3f51ca |
|
|
|
3f51ca |
+# We have two backends for nss operations:
|
|
|
3f51ca |
+# (1) directly loading nss_sss.so.2
|
|
|
3f51ca |
+# (2) using timeout-enabled API from libsss_nss_idmap
|
|
|
3f51ca |
+# We prefer (2) if available
|
|
|
3f51ca |
+if USE_SSS_NSS_TIMEOUT
|
|
|
3f51ca |
+libipa_extdom_extop_la_SOURCES += back_extdom_sss_idmap.c
|
|
|
3f51ca |
+else
|
|
|
3f51ca |
+libipa_extdom_extop_la_SOURCES += back_extdom_nss_sss.c
|
|
|
3f51ca |
+endif
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+
|
|
|
3f51ca |
TESTS =
|
|
|
3f51ca |
check_PROGRAMS =
|
|
|
3f51ca |
|
|
|
3f51ca |
if HAVE_CMOCKA
|
|
|
3f51ca |
-if HAVE_NSS_WRAPPER
|
|
|
3f51ca |
-TESTS_ENVIRONMENT = . ./test_data/test_setup.sh;
|
|
|
3f51ca |
TESTS += extdom_cmocka_tests
|
|
|
3f51ca |
check_PROGRAMS += extdom_cmocka_tests
|
|
|
3f51ca |
endif
|
|
|
3f51ca |
-endif
|
|
|
3f51ca |
|
|
|
3f51ca |
extdom_cmocka_tests_SOURCES = \
|
|
|
3f51ca |
ipa_extdom_cmocka_tests.c \
|
|
|
3f51ca |
ipa_extdom_common.c \
|
|
|
3f51ca |
+ back_extdom_nss_sss.c \
|
|
|
3f51ca |
$(NULL)
|
|
|
3f51ca |
extdom_cmocka_tests_CFLAGS = $(CMOCKA_CFLAGS)
|
|
|
3f51ca |
extdom_cmocka_tests_LDFLAGS = \
|
|
|
3f51ca |
@@ -58,6 +68,7 @@ extdom_cmocka_tests_LDADD = \
|
|
|
3f51ca |
$(LDAP_LIBS) \
|
|
|
3f51ca |
$(DIRSRV_LIBS) \
|
|
|
3f51ca |
$(SSSNSSIDMAP_LIBS) \
|
|
|
3f51ca |
+ -ldl \
|
|
|
3f51ca |
$(NULL)
|
|
|
3f51ca |
|
|
|
3f51ca |
|
|
|
3f51ca |
diff --git a/daemons/ipa-slapi-plugins/ipa-extdom-extop/back_extdom.h b/daemons/ipa-slapi-plugins/ipa-extdom-extop/back_extdom.h
|
|
|
3f51ca |
new file mode 100644
|
|
|
3f51ca |
index 0000000000000000000000000000000000000000..d2937c8c8ecf8b960b5b31e9449c719bfda86de4
|
|
|
3f51ca |
--- /dev/null
|
|
|
3f51ca |
+++ b/daemons/ipa-slapi-plugins/ipa-extdom-extop/back_extdom.h
|
|
|
3f51ca |
@@ -0,0 +1,79 @@
|
|
|
3f51ca |
+/*
|
|
|
3f51ca |
+ * Copyright 2017 Red Hat, Inc.
|
|
|
3f51ca |
+ *
|
|
|
3f51ca |
+ * This Program is free software; you can redistribute it and/or modify
|
|
|
3f51ca |
+ * it under the terms of the GNU General Public License as published by
|
|
|
3f51ca |
+ * the Free Software Foundation; version 2 of the License.
|
|
|
3f51ca |
+ *
|
|
|
3f51ca |
+ * This Program is distributed in the hope that it will be useful, but
|
|
|
3f51ca |
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
3f51ca |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
3f51ca |
+ * General Public License for more details.
|
|
|
3f51ca |
+ *
|
|
|
3f51ca |
+ * You should have received a copy of the GNU General Public License
|
|
|
3f51ca |
+ * along with this Program; if not, write to the
|
|
|
3f51ca |
+ *
|
|
|
3f51ca |
+ * Free Software Foundation, Inc.
|
|
|
3f51ca |
+ * 59 Temple Place, Suite 330
|
|
|
3f51ca |
+ * Boston, MA 02111-1307 USA
|
|
|
3f51ca |
+ *
|
|
|
3f51ca |
+ */
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+#ifndef BACK_EXTDOM_H
|
|
|
3f51ca |
+#define BACK_EXTDOM_H
|
|
|
3f51ca |
+#include <unistd.h>
|
|
|
3f51ca |
+#include <pwd.h>
|
|
|
3f51ca |
+#include <grp.h>
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+/* Possible results of lookup using a nss_* function.
|
|
|
3f51ca |
+ * Note: don't include nss.h as its path gets overriden by NSS library */
|
|
|
3f51ca |
+enum nss_status {
|
|
|
3f51ca |
+ NSS_STATUS_TRYAGAIN = -2,
|
|
|
3f51ca |
+ NSS_STATUS_UNAVAIL,
|
|
|
3f51ca |
+ NSS_STATUS_NOTFOUND,
|
|
|
3f51ca |
+ NSS_STATUS_SUCCESS,
|
|
|
3f51ca |
+ NSS_STATUS_RETURN
|
|
|
3f51ca |
+};
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+/* NSS backend operations implemented using either nss_sss.so.2 or libsss_nss_idmap API */
|
|
|
3f51ca |
+struct nss_ops_ctx;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+int back_extdom_init_context(struct nss_ops_ctx **nss_context);
|
|
|
3f51ca |
+void back_extdom_free_context(struct nss_ops_ctx **nss_context);
|
|
|
3f51ca |
+void back_extdom_set_timeout(struct nss_ops_ctx *nss_context,
|
|
|
3f51ca |
+ unsigned int timeout);
|
|
|
3f51ca |
+void back_extdom_evict_user(struct nss_ops_ctx *nss_context,
|
|
|
3f51ca |
+ const char *name);
|
|
|
3f51ca |
+void back_extdom_evict_group(struct nss_ops_ctx *nss_context,
|
|
|
3f51ca |
+ const char *name);
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+enum nss_status back_extdom_getpwnam(struct nss_ops_ctx *nss_context,
|
|
|
3f51ca |
+ const char *name, struct passwd *pwd,
|
|
|
3f51ca |
+ char *buffer, size_t buflen,
|
|
|
3f51ca |
+ struct passwd **result,
|
|
|
3f51ca |
+ int *lerrno);
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+enum nss_status back_extdom_getpwuid(struct nss_ops_ctx *nss_context,
|
|
|
3f51ca |
+ uid_t uid, struct passwd *pwd,
|
|
|
3f51ca |
+ char *buffer, size_t buflen,
|
|
|
3f51ca |
+ struct passwd **result,
|
|
|
3f51ca |
+ int *lerrno);
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+enum nss_status back_extdom_getgrnam(struct nss_ops_ctx *nss_context,
|
|
|
3f51ca |
+ const char *name, struct group *grp,
|
|
|
3f51ca |
+ char *buffer, size_t buflen,
|
|
|
3f51ca |
+ struct group **result,
|
|
|
3f51ca |
+ int *lerrno);
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+enum nss_status back_extdom_getgrgid(struct nss_ops_ctx *nss_context,
|
|
|
3f51ca |
+ gid_t gid, struct group *grp,
|
|
|
3f51ca |
+ char *buffer, size_t buflen,
|
|
|
3f51ca |
+ struct group **result,
|
|
|
3f51ca |
+ int *lerrno);
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+enum nss_status back_extdom_getgrouplist(struct nss_ops_ctx *nss_context,
|
|
|
3f51ca |
+ const char *name, gid_t group,
|
|
|
3f51ca |
+ gid_t *groups, int *ngroups,
|
|
|
3f51ca |
+ int *lerrno);
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+#endif /* BACK_EXTDOM_H */
|
|
|
3f51ca |
diff --git a/daemons/ipa-slapi-plugins/ipa-extdom-extop/back_extdom_nss_sss.c b/daemons/ipa-slapi-plugins/ipa-extdom-extop/back_extdom_nss_sss.c
|
|
|
3f51ca |
new file mode 100644
|
|
|
3f51ca |
index 0000000000000000000000000000000000000000..346c7d4301a607c7bc07ca5a9c53fe84618ac8ad
|
|
|
3f51ca |
--- /dev/null
|
|
|
3f51ca |
+++ b/daemons/ipa-slapi-plugins/ipa-extdom-extop/back_extdom_nss_sss.c
|
|
|
3f51ca |
@@ -0,0 +1,276 @@
|
|
|
3f51ca |
+/*
|
|
|
3f51ca |
+ * Copyright 2013-2017 Red Hat, Inc.
|
|
|
3f51ca |
+ *
|
|
|
3f51ca |
+ * This Program is free software; you can redistribute it and/or modify
|
|
|
3f51ca |
+ * it under the terms of the GNU General Public License as published by
|
|
|
3f51ca |
+ * the Free Software Foundation; version 2 of the License.
|
|
|
3f51ca |
+ *
|
|
|
3f51ca |
+ * This Program is distributed in the hope that it will be useful, but
|
|
|
3f51ca |
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
3f51ca |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
3f51ca |
+ * General Public License for more details.
|
|
|
3f51ca |
+ *
|
|
|
3f51ca |
+ * You should have received a copy of the GNU General Public License
|
|
|
3f51ca |
+ * along with this Program; if not, write to the
|
|
|
3f51ca |
+ *
|
|
|
3f51ca |
+ * Free Software Foundation, Inc.
|
|
|
3f51ca |
+ * 59 Temple Place, Suite 330
|
|
|
3f51ca |
+ * Boston, MA 02111-1307 USA
|
|
|
3f51ca |
+ *
|
|
|
3f51ca |
+ */
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+#ifdef HAVE_CONFIG_H
|
|
|
3f51ca |
+#include "config.h"
|
|
|
3f51ca |
+#endif
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+#include <sys/types.h>
|
|
|
3f51ca |
+#include <stdlib.h>
|
|
|
3f51ca |
+#include <string.h>
|
|
|
3f51ca |
+#include <time.h>
|
|
|
3f51ca |
+#include <unistd.h>
|
|
|
3f51ca |
+#include <dlfcn.h>
|
|
|
3f51ca |
+#include <errno.h>
|
|
|
3f51ca |
+#include <pwd.h>
|
|
|
3f51ca |
+#include <grp.h>
|
|
|
3f51ca |
+#include <sys/param.h>
|
|
|
3f51ca |
+#include "back_extdom.h"
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+struct nss_ops_ctx {
|
|
|
3f51ca |
+ void *dl_handle;
|
|
|
3f51ca |
+ long int initgroups_start;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ enum nss_status (*getpwnam_r)(const char *name, struct passwd *result,
|
|
|
3f51ca |
+ char *buffer, size_t buflen, int *errnop);
|
|
|
3f51ca |
+ enum nss_status (*getpwuid_r)(uid_t uid, struct passwd *result,
|
|
|
3f51ca |
+ char *buffer, size_t buflen, int *errnop);
|
|
|
3f51ca |
+ enum nss_status (*getgrnam_r)(const char *name, struct group *result,
|
|
|
3f51ca |
+ char *buffer, size_t buflen, int *errnop);
|
|
|
3f51ca |
+ enum nss_status (*getgrgid_r)(gid_t gid, struct group *result,
|
|
|
3f51ca |
+ char *buffer, size_t buflen, int *errnop);
|
|
|
3f51ca |
+ enum nss_status (*initgroups_dyn)(const char *user, gid_t group,
|
|
|
3f51ca |
+ long int *start, long int *size,
|
|
|
3f51ca |
+ gid_t **groups, long int limit,
|
|
|
3f51ca |
+ int *errnop);
|
|
|
3f51ca |
+};
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+void back_extdom_free_context(struct nss_ops_ctx **nss_context)
|
|
|
3f51ca |
+{
|
|
|
3f51ca |
+ if ((nss_context == NULL) || (*nss_context == NULL)) {
|
|
|
3f51ca |
+ return;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ if ((*nss_context)->dl_handle != NULL) {
|
|
|
3f51ca |
+ dlclose((*nss_context)->dl_handle);
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ free((*nss_context));
|
|
|
3f51ca |
+ *nss_context = NULL;
|
|
|
3f51ca |
+}
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+int back_extdom_init_context(struct nss_ops_ctx **nss_context)
|
|
|
3f51ca |
+{
|
|
|
3f51ca |
+ struct nss_ops_ctx *ctx = NULL;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ if (nss_context == NULL) {
|
|
|
3f51ca |
+ return EINVAL;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ ctx = calloc(1, sizeof(struct nss_ops_ctx));
|
|
|
3f51ca |
+ if (ctx == NULL) {
|
|
|
3f51ca |
+ return ENOMEM;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+ *nss_context = ctx;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ ctx->dl_handle = dlopen("libnss_sss.so.2", RTLD_NOW);
|
|
|
3f51ca |
+ if (ctx->dl_handle == NULL) {
|
|
|
3f51ca |
+ goto fail;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ ctx->getpwnam_r = dlsym(ctx->dl_handle, "_nss_sss_getpwnam_r");
|
|
|
3f51ca |
+ if (ctx->getpwnam_r == NULL) {
|
|
|
3f51ca |
+ goto fail;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ ctx->getpwuid_r = dlsym(ctx->dl_handle, "_nss_sss_getpwuid_r");
|
|
|
3f51ca |
+ if (ctx->getpwuid_r == NULL) {
|
|
|
3f51ca |
+ goto fail;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ ctx->getgrnam_r = dlsym(ctx->dl_handle, "_nss_sss_getgrnam_r");
|
|
|
3f51ca |
+ if (ctx->getgrnam_r == NULL) {
|
|
|
3f51ca |
+ goto fail;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ ctx->getgrgid_r = dlsym(ctx->dl_handle, "_nss_sss_getgrgid_r");
|
|
|
3f51ca |
+ if (ctx->getgrgid_r == NULL) {
|
|
|
3f51ca |
+ goto fail;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ ctx->initgroups_dyn = dlsym(ctx->dl_handle, "_nss_sss_initgroups_dyn");
|
|
|
3f51ca |
+ if (ctx->initgroups_dyn == NULL) {
|
|
|
3f51ca |
+ goto fail;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ return 0;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+fail:
|
|
|
3f51ca |
+ back_extdom_free_context(nss_context);
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ return EINVAL;
|
|
|
3f51ca |
+}
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+/* Following three functions cannot be implemented with nss_sss.so.2
|
|
|
3f51ca |
+ * As result, we simply do nothing here */
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+void back_extdom_set_timeout(struct nss_ops_ctx *nss_context,
|
|
|
3f51ca |
+ unsigned int timeout) {
|
|
|
3f51ca |
+ /* no operation */
|
|
|
3f51ca |
+}
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+void back_extdom_evict_user(struct nss_ops_ctx *nss_context,
|
|
|
3f51ca |
+ const char *name) {
|
|
|
3f51ca |
+ /* no operation */
|
|
|
3f51ca |
+}
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+void back_extdom_evict_group(struct nss_ops_ctx *nss_context,
|
|
|
3f51ca |
+ const char *name) {
|
|
|
3f51ca |
+ /* no operation */
|
|
|
3f51ca |
+}
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+enum nss_status back_extdom_getpwnam(struct nss_ops_ctx *nss_context,
|
|
|
3f51ca |
+ const char *name, struct passwd *pwd,
|
|
|
3f51ca |
+ char *buffer, size_t buflen,
|
|
|
3f51ca |
+ struct passwd **result,
|
|
|
3f51ca |
+ int *lerrno) {
|
|
|
3f51ca |
+ enum nss_status ret;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ if (nss_context == NULL) {
|
|
|
3f51ca |
+ return NSS_STATUS_UNAVAIL;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ ret = nss_context->getpwnam_r(name, pwd,
|
|
|
3f51ca |
+ buffer, buflen,
|
|
|
3f51ca |
+ lerrno);
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ if ((ret == NSS_STATUS_SUCCESS) && (result != NULL)) {
|
|
|
3f51ca |
+ *result = pwd;
|
|
|
3f51ca |
+ *lerrno = 0;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ return ret;
|
|
|
3f51ca |
+}
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+enum nss_status back_extdom_getpwuid(struct nss_ops_ctx *nss_context,
|
|
|
3f51ca |
+ uid_t uid, struct passwd *pwd,
|
|
|
3f51ca |
+ char *buffer, size_t buflen,
|
|
|
3f51ca |
+ struct passwd **result,
|
|
|
3f51ca |
+ int *lerrno) {
|
|
|
3f51ca |
+ enum nss_status ret;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ if (nss_context == NULL) {
|
|
|
3f51ca |
+ return NSS_STATUS_UNAVAIL;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ ret = nss_context->getpwuid_r(uid, pwd,
|
|
|
3f51ca |
+ buffer, buflen,
|
|
|
3f51ca |
+ lerrno);
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ if ((ret == NSS_STATUS_SUCCESS) && (result != NULL)) {
|
|
|
3f51ca |
+ *result = pwd;
|
|
|
3f51ca |
+ *lerrno = 0;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ return ret;
|
|
|
3f51ca |
+}
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+enum nss_status back_extdom_getgrnam(struct nss_ops_ctx *nss_context,
|
|
|
3f51ca |
+ const char *name, struct group *grp,
|
|
|
3f51ca |
+ char *buffer, size_t buflen,
|
|
|
3f51ca |
+ struct group **result,
|
|
|
3f51ca |
+ int *lerrno) {
|
|
|
3f51ca |
+ enum nss_status ret;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ if (nss_context == NULL) {
|
|
|
3f51ca |
+ return NSS_STATUS_UNAVAIL;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ ret = nss_context->getgrnam_r(name, grp,
|
|
|
3f51ca |
+ buffer, buflen,
|
|
|
3f51ca |
+ lerrno);
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ if ((ret == NSS_STATUS_SUCCESS) && (result != NULL)) {
|
|
|
3f51ca |
+ *result = grp;
|
|
|
3f51ca |
+ *lerrno = 0;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ return ret;
|
|
|
3f51ca |
+}
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+enum nss_status back_extdom_getgrgid(struct nss_ops_ctx *nss_context,
|
|
|
3f51ca |
+ gid_t gid, struct group *grp,
|
|
|
3f51ca |
+ char *buffer, size_t buflen,
|
|
|
3f51ca |
+ struct group **result,
|
|
|
3f51ca |
+ int *lerrno) {
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ enum nss_status ret;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ if (nss_context == NULL) {
|
|
|
3f51ca |
+ return NSS_STATUS_UNAVAIL;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ ret = nss_context->getgrgid_r(gid, grp,
|
|
|
3f51ca |
+ buffer, buflen,
|
|
|
3f51ca |
+ lerrno);
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ if ((ret == NSS_STATUS_SUCCESS) && (result != NULL)) {
|
|
|
3f51ca |
+ *result = grp;
|
|
|
3f51ca |
+ *lerrno = 0;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ return ret;
|
|
|
3f51ca |
+}
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+enum nss_status back_extdom_getgrouplist(struct nss_ops_ctx *nss_context,
|
|
|
3f51ca |
+ const char *name, gid_t group,
|
|
|
3f51ca |
+ gid_t *groups, int *ngroups,
|
|
|
3f51ca |
+ int *lerrno) {
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ enum nss_status ret = NSS_STATUS_UNAVAIL;
|
|
|
3f51ca |
+ long int tsize = MAX (1, *ngroups);
|
|
|
3f51ca |
+ gid_t *newgroups = NULL;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ if (nss_context == NULL) {
|
|
|
3f51ca |
+ return NSS_STATUS_UNAVAIL;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ newgroups = (gid_t *) calloc (tsize, sizeof (gid_t));
|
|
|
3f51ca |
+ if (newgroups == NULL) {
|
|
|
3f51ca |
+ *lerrno = ENOMEM;
|
|
|
3f51ca |
+ return NSS_STATUS_TRYAGAIN;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ newgroups[0] = group;
|
|
|
3f51ca |
+ nss_context->initgroups_start = 1;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ ret = nss_context->initgroups_dyn(name, group,
|
|
|
3f51ca |
+ &nss_context->initgroups_start,
|
|
|
3f51ca |
+ &tsize, &newgroups,
|
|
|
3f51ca |
+ -1, lerrno);
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ (void) memcpy(groups, newgroups,
|
|
|
3f51ca |
+ MIN(*ngroups, nss_context->initgroups_start) * sizeof(gid_t));
|
|
|
3f51ca |
+ free(newgroups);
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ if (*ngroups < nss_context->initgroups_start) {
|
|
|
3f51ca |
+ ret = NSS_STATUS_TRYAGAIN;
|
|
|
3f51ca |
+ *lerrno = ERANGE;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ *ngroups = (int) nss_context->initgroups_start;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ nss_context->initgroups_start = 0;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ return ret;
|
|
|
3f51ca |
+}
|
|
|
3f51ca |
+
|
|
|
3f51ca |
diff --git a/daemons/ipa-slapi-plugins/ipa-extdom-extop/back_extdom_sss_idmap.c b/daemons/ipa-slapi-plugins/ipa-extdom-extop/back_extdom_sss_idmap.c
|
|
|
3f51ca |
new file mode 100644
|
|
|
3f51ca |
index 0000000000000000000000000000000000000000..89c58ca2de333b26954d916836b57aed5d7e18fb
|
|
|
3f51ca |
--- /dev/null
|
|
|
3f51ca |
+++ b/daemons/ipa-slapi-plugins/ipa-extdom-extop/back_extdom_sss_idmap.c
|
|
|
3f51ca |
@@ -0,0 +1,260 @@
|
|
|
3f51ca |
+/*
|
|
|
3f51ca |
+ * Copyright 2013-2017 Red Hat, Inc.
|
|
|
3f51ca |
+ *
|
|
|
3f51ca |
+ * This Program is free software; you can redistribute it and/or modify
|
|
|
3f51ca |
+ * it under the terms of the GNU General Public License as published by
|
|
|
3f51ca |
+ * the Free Software Foundation; version 2 of the License.
|
|
|
3f51ca |
+ *
|
|
|
3f51ca |
+ * This Program is distributed in the hope that it will be useful, but
|
|
|
3f51ca |
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
3f51ca |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
3f51ca |
+ * General Public License for more details.
|
|
|
3f51ca |
+ *
|
|
|
3f51ca |
+ * You should have received a copy of the GNU General Public License
|
|
|
3f51ca |
+ * along with this Program; if not, write to the
|
|
|
3f51ca |
+ *
|
|
|
3f51ca |
+ * Free Software Foundation, Inc.
|
|
|
3f51ca |
+ * 59 Temple Place, Suite 330
|
|
|
3f51ca |
+ * Boston, MA 02111-1307 USA
|
|
|
3f51ca |
+ *
|
|
|
3f51ca |
+ */
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+#ifdef HAVE_CONFIG_H
|
|
|
3f51ca |
+#include "config.h"
|
|
|
3f51ca |
+#endif
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+#include <sys/types.h>
|
|
|
3f51ca |
+#include <stdlib.h>
|
|
|
3f51ca |
+#include <string.h>
|
|
|
3f51ca |
+#include <time.h>
|
|
|
3f51ca |
+#include <unistd.h>
|
|
|
3f51ca |
+#include <errno.h>
|
|
|
3f51ca |
+#include <pwd.h>
|
|
|
3f51ca |
+#include <grp.h>
|
|
|
3f51ca |
+#include "back_extdom.h"
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+/* SSSD only exposes *_timeout() variants if the following symbol is defined */
|
|
|
3f51ca |
+#define IPA_389DS_PLUGIN_HELPER_CALLS
|
|
|
3f51ca |
+#include <sss_nss_idmap.h>
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+struct nss_ops_ctx {
|
|
|
3f51ca |
+ unsigned int timeout;
|
|
|
3f51ca |
+};
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+static enum nss_status __convert_sss_nss2nss_status(int errcode) {
|
|
|
3f51ca |
+ switch(errcode) {
|
|
|
3f51ca |
+ case 0:
|
|
|
3f51ca |
+ return NSS_STATUS_SUCCESS;
|
|
|
3f51ca |
+ case ENOENT:
|
|
|
3f51ca |
+ return NSS_STATUS_NOTFOUND;
|
|
|
3f51ca |
+ case ETIME:
|
|
|
3f51ca |
+ /* fall-through */
|
|
|
3f51ca |
+ case ERANGE:
|
|
|
3f51ca |
+ return NSS_STATUS_TRYAGAIN;
|
|
|
3f51ca |
+ case ETIMEDOUT:
|
|
|
3f51ca |
+ /* fall-through */
|
|
|
3f51ca |
+ default:
|
|
|
3f51ca |
+ return NSS_STATUS_UNAVAIL;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+ return NSS_STATUS_UNAVAIL;
|
|
|
3f51ca |
+}
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+int back_extdom_init_context(struct nss_ops_ctx **nss_context)
|
|
|
3f51ca |
+{
|
|
|
3f51ca |
+ struct nss_ops_ctx *ctx = NULL;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ if (nss_context == NULL) {
|
|
|
3f51ca |
+ return EINVAL;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ ctx = calloc(1, sizeof(struct nss_ops_ctx));
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ if (ctx == NULL) {
|
|
|
3f51ca |
+ return ENOMEM;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+ *nss_context = ctx;
|
|
|
3f51ca |
+ return 0;
|
|
|
3f51ca |
+}
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+void back_extdom_free_context(struct nss_ops_ctx **nss_context)
|
|
|
3f51ca |
+{
|
|
|
3f51ca |
+ if ((nss_context == NULL) || (*nss_context == NULL)) {
|
|
|
3f51ca |
+ return;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ free((*nss_context));
|
|
|
3f51ca |
+ *nss_context = NULL;
|
|
|
3f51ca |
+}
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+void back_extdom_set_timeout(struct nss_ops_ctx *nss_context,
|
|
|
3f51ca |
+ unsigned int timeout) {
|
|
|
3f51ca |
+ if (nss_context == NULL) {
|
|
|
3f51ca |
+ return;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ nss_context->timeout = timeout;
|
|
|
3f51ca |
+}
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+void back_extdom_evict_user(struct nss_ops_ctx *nss_context,
|
|
|
3f51ca |
+ const char *name) {
|
|
|
3f51ca |
+ if (nss_context == NULL) {
|
|
|
3f51ca |
+ return;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ (void) sss_nss_getpwnam_timeout(name, NULL,
|
|
|
3f51ca |
+ NULL, 0,
|
|
|
3f51ca |
+ NULL,
|
|
|
3f51ca |
+ SSS_NSS_EX_FLAG_INVALIDATE_CACHE,
|
|
|
3f51ca |
+ nss_context->timeout);
|
|
|
3f51ca |
+}
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+void back_extdom_evict_group(struct nss_ops_ctx *nss_context,
|
|
|
3f51ca |
+ const char *name) {
|
|
|
3f51ca |
+ if (nss_context == NULL) {
|
|
|
3f51ca |
+ return;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ (void) sss_nss_getgrnam_timeout(name, NULL,
|
|
|
3f51ca |
+ NULL, 0,
|
|
|
3f51ca |
+ NULL,
|
|
|
3f51ca |
+ SSS_NSS_EX_FLAG_INVALIDATE_CACHE,
|
|
|
3f51ca |
+ nss_context->timeout);
|
|
|
3f51ca |
+}
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+enum nss_status back_extdom_getpwnam(struct nss_ops_ctx *nss_context,
|
|
|
3f51ca |
+ const char *name, struct passwd *pwd,
|
|
|
3f51ca |
+ char *buffer, size_t buflen,
|
|
|
3f51ca |
+ struct passwd **result,
|
|
|
3f51ca |
+ int *lerrno) {
|
|
|
3f51ca |
+ int ret = 0;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ if (nss_context == NULL) {
|
|
|
3f51ca |
+ return NSS_STATUS_UNAVAIL;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ ret = sss_nss_getpwnam_timeout(name, pwd,
|
|
|
3f51ca |
+ buffer, buflen,
|
|
|
3f51ca |
+ result,
|
|
|
3f51ca |
+ SSS_NSS_EX_FLAG_NO_FLAGS,
|
|
|
3f51ca |
+ nss_context->timeout);
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ /* SSSD uses the same infrastructure to handle sss_nss_get* calls
|
|
|
3f51ca |
+ * as nss_sss.so.2 module where 'int *errno' is passed to the helper
|
|
|
3f51ca |
+ * but writes down errno into return code so we propagate it in case
|
|
|
3f51ca |
+ * of error and translate the return code */
|
|
|
3f51ca |
+ if (lerrno != NULL) {
|
|
|
3f51ca |
+ *lerrno = ret;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+ return __convert_sss_nss2nss_status(ret);
|
|
|
3f51ca |
+}
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+enum nss_status back_extdom_getpwuid(struct nss_ops_ctx *nss_context,
|
|
|
3f51ca |
+ uid_t uid, struct passwd *pwd,
|
|
|
3f51ca |
+ char *buffer, size_t buflen,
|
|
|
3f51ca |
+ struct passwd **result,
|
|
|
3f51ca |
+ int *lerrno) {
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ int ret = 0;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ if (nss_context == NULL) {
|
|
|
3f51ca |
+ return NSS_STATUS_UNAVAIL;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ ret = sss_nss_getpwuid_timeout(uid, pwd,
|
|
|
3f51ca |
+ buffer, buflen,
|
|
|
3f51ca |
+ result,
|
|
|
3f51ca |
+ SSS_NSS_EX_FLAG_NO_FLAGS,
|
|
|
3f51ca |
+ nss_context->timeout);
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ /* SSSD uses the same infrastructure to handle sss_nss_get* calls
|
|
|
3f51ca |
+ * as nss_sss.so.2 module where 'int *errno' is passed to the helper
|
|
|
3f51ca |
+ * but writes down errno into return code so we propagate it in case
|
|
|
3f51ca |
+ * of error and translate the return code */
|
|
|
3f51ca |
+ if (lerrno != NULL) {
|
|
|
3f51ca |
+ *lerrno = ret;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+ return __convert_sss_nss2nss_status(ret);
|
|
|
3f51ca |
+}
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+enum nss_status back_extdom_getgrnam(struct nss_ops_ctx *nss_context,
|
|
|
3f51ca |
+ const char *name, struct group *grp,
|
|
|
3f51ca |
+ char *buffer, size_t buflen,
|
|
|
3f51ca |
+ struct group **result,
|
|
|
3f51ca |
+ int *lerrno) {
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ int ret = 0;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ if (nss_context == NULL) {
|
|
|
3f51ca |
+ return NSS_STATUS_UNAVAIL;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ ret = sss_nss_getgrnam_timeout(name, grp,
|
|
|
3f51ca |
+ buffer, buflen,
|
|
|
3f51ca |
+ result,
|
|
|
3f51ca |
+ SSS_NSS_EX_FLAG_NO_FLAGS,
|
|
|
3f51ca |
+ nss_context->timeout);
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ /* SSSD uses the same infrastructure to handle sss_nss_get* calls
|
|
|
3f51ca |
+ * as nss_sss.so.2 module where 'int *errno' is passed to the helper
|
|
|
3f51ca |
+ * but writes down errno into return code so we propagate it in case
|
|
|
3f51ca |
+ * of error and translate the return code */
|
|
|
3f51ca |
+ if (lerrno != NULL) {
|
|
|
3f51ca |
+ *lerrno = ret;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+ return __convert_sss_nss2nss_status(ret);
|
|
|
3f51ca |
+}
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+enum nss_status back_extdom_getgrgid(struct nss_ops_ctx *nss_context,
|
|
|
3f51ca |
+ gid_t gid, struct group *grp,
|
|
|
3f51ca |
+ char *buffer, size_t buflen,
|
|
|
3f51ca |
+ struct group **result,
|
|
|
3f51ca |
+ int *lerrno) {
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ int ret = 0;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ if (nss_context == NULL) {
|
|
|
3f51ca |
+ return NSS_STATUS_UNAVAIL;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ ret = sss_nss_getgrgid_timeout(gid, grp,
|
|
|
3f51ca |
+ buffer, buflen,
|
|
|
3f51ca |
+ result,
|
|
|
3f51ca |
+ SSS_NSS_EX_FLAG_NO_FLAGS,
|
|
|
3f51ca |
+ nss_context->timeout);
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ /* SSSD uses the same infrastructure to handle sss_nss_get* calls
|
|
|
3f51ca |
+ * as nss_sss.so.2 module where 'int *errno' is passed to the helper
|
|
|
3f51ca |
+ * but writes down errno into return code so we propagate it in case
|
|
|
3f51ca |
+ * of error and translate the return code */
|
|
|
3f51ca |
+ if (lerrno != NULL) {
|
|
|
3f51ca |
+ *lerrno = ret;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+ return __convert_sss_nss2nss_status(ret);
|
|
|
3f51ca |
+}
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+enum nss_status back_extdom_getgrouplist(struct nss_ops_ctx *nss_context,
|
|
|
3f51ca |
+ const char *name, gid_t group,
|
|
|
3f51ca |
+ gid_t *groups, int *ngroups,
|
|
|
3f51ca |
+ int *lerrno) {
|
|
|
3f51ca |
+ int ret = 0;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ if (nss_context == NULL) {
|
|
|
3f51ca |
+ return NSS_STATUS_UNAVAIL;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ ret = sss_nss_getgrouplist_timeout(name, group,
|
|
|
3f51ca |
+ groups, ngroups,
|
|
|
3f51ca |
+ SSS_NSS_EX_FLAG_NO_FLAGS,
|
|
|
3f51ca |
+ nss_context->timeout);
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ /* SSSD uses the same infrastructure to handle sss_nss_get* calls
|
|
|
3f51ca |
+ * as nss_sss.so.2 module where 'int *errno' is passed to the helper
|
|
|
3f51ca |
+ * but writes down errno into return code so we propagate it in case
|
|
|
3f51ca |
+ * of error and translate the return code */
|
|
|
3f51ca |
+ if (lerrno != NULL) {
|
|
|
3f51ca |
+ *lerrno = ret;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+ return __convert_sss_nss2nss_status(ret);
|
|
|
3f51ca |
+}
|
|
|
3f51ca |
+
|
|
|
3f51ca |
diff --git a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom.h b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom.h
|
|
|
3f51ca |
index bc29f069816b0ce13578c9ae14c61edb832d44e4..bbc574747e8bbe045dfc9882198cb34b0bb8cab9 100644
|
|
|
3f51ca |
--- a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom.h
|
|
|
3f51ca |
+++ b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom.h
|
|
|
3f51ca |
@@ -150,10 +150,13 @@ struct extdom_res {
|
|
|
3f51ca |
} data;
|
|
|
3f51ca |
};
|
|
|
3f51ca |
|
|
|
3f51ca |
+struct nss_ops_ctx;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
struct ipa_extdom_ctx {
|
|
|
3f51ca |
Slapi_ComponentId *plugin_id;
|
|
|
3f51ca |
char *base_dn;
|
|
|
3f51ca |
size_t max_nss_buf_size;
|
|
|
3f51ca |
+ struct nss_ops_ctx *nss_ctx;
|
|
|
3f51ca |
};
|
|
|
3f51ca |
|
|
|
3f51ca |
struct domain_info {
|
|
|
3f51ca |
@@ -179,15 +182,15 @@ int handle_request(struct ipa_extdom_ctx *ctx, struct extdom_req *req,
|
|
|
3f51ca |
struct berval **berval);
|
|
|
3f51ca |
int pack_response(struct extdom_res *res, struct berval **ret_val);
|
|
|
3f51ca |
int get_buffer(size_t *_buf_len, char **_buf);
|
|
|
3f51ca |
-int getpwnam_r_wrapper(size_t buf_max, const char *name,
|
|
|
3f51ca |
+int getpwnam_r_wrapper(struct ipa_extdom_ctx *ctx, const char *name,
|
|
|
3f51ca |
struct passwd *pwd, char **_buf, size_t *_buf_len);
|
|
|
3f51ca |
-int getpwuid_r_wrapper(size_t buf_max, uid_t uid,
|
|
|
3f51ca |
+int getpwuid_r_wrapper(struct ipa_extdom_ctx *ctx, uid_t uid,
|
|
|
3f51ca |
struct passwd *pwd, char **_buf, size_t *_buf_len);
|
|
|
3f51ca |
-int getgrnam_r_wrapper(size_t buf_max, const char *name,
|
|
|
3f51ca |
+int getgrnam_r_wrapper(struct ipa_extdom_ctx *ctx, const char *name,
|
|
|
3f51ca |
struct group *grp, char **_buf, size_t *_buf_len);
|
|
|
3f51ca |
-int getgrgid_r_wrapper(size_t buf_max, gid_t gid,
|
|
|
3f51ca |
+int getgrgid_r_wrapper(struct ipa_extdom_ctx *ctx, gid_t gid,
|
|
|
3f51ca |
struct group *grp, char **_buf, size_t *_buf_len);
|
|
|
3f51ca |
-int get_user_grouplist(const char *name, gid_t gid,
|
|
|
3f51ca |
+int get_user_grouplist(struct ipa_extdom_ctx *ctx, const char *name, gid_t gid,
|
|
|
3f51ca |
size_t *_ngroups, gid_t **_groups);
|
|
|
3f51ca |
int pack_ber_sid(const char *sid, struct berval **berval);
|
|
|
3f51ca |
int pack_ber_name(const char *domain_name, const char *name,
|
|
|
3f51ca |
diff --git a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_cmocka_tests.c b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_cmocka_tests.c
|
|
|
3f51ca |
index 526f903d2416e62ee5781909c234bd5ee2d89183..29699cfa390f5469d7c009388b90e68616cbf984 100644
|
|
|
3f51ca |
--- a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_cmocka_tests.c
|
|
|
3f51ca |
+++ b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_cmocka_tests.c
|
|
|
3f51ca |
@@ -19,6 +19,7 @@
|
|
|
3f51ca |
You should have received a copy of the GNU General Public License
|
|
|
3f51ca |
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
3f51ca |
*/
|
|
|
3f51ca |
+#define _GNU_SOURCE
|
|
|
3f51ca |
|
|
|
3f51ca |
#include <errno.h>
|
|
|
3f51ca |
#include <stdarg.h>
|
|
|
3f51ca |
@@ -31,24 +32,166 @@
|
|
|
3f51ca |
|
|
|
3f51ca |
|
|
|
3f51ca |
#include "ipa_extdom.h"
|
|
|
3f51ca |
+#include "back_extdom.h"
|
|
|
3f51ca |
+#include <stdio.h>
|
|
|
3f51ca |
+#include <dlfcn.h>
|
|
|
3f51ca |
|
|
|
3f51ca |
#define MAX_BUF (1024*1024*1024)
|
|
|
3f51ca |
+struct test_data {
|
|
|
3f51ca |
+ struct extdom_req *req;
|
|
|
3f51ca |
+ struct ipa_extdom_ctx *ctx;
|
|
|
3f51ca |
+};
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+/*
|
|
|
3f51ca |
+ * redefine logging for mocks
|
|
|
3f51ca |
+ */
|
|
|
3f51ca |
+#ifdef __GNUC__
|
|
|
3f51ca |
+ __attribute__((format(printf, 3, 4)))
|
|
|
3f51ca |
+#endif
|
|
|
3f51ca |
+int slapi_log_error(int loglevel, char *subsystem, char *fmt, ...)
|
|
|
3f51ca |
+{
|
|
|
3f51ca |
+ va_list ap;
|
|
|
3f51ca |
+ va_start(ap, fmt);
|
|
|
3f51ca |
+ vprint_error(fmt, ap);
|
|
|
3f51ca |
+ va_end(ap);
|
|
|
3f51ca |
+ return 0;
|
|
|
3f51ca |
+}
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+/*
|
|
|
3f51ca |
+ * We cannot run cmocka tests against SSSD as that would require to set up SSSD
|
|
|
3f51ca |
+ * and the rest of environment. Instead, we compile cmocka tests against
|
|
|
3f51ca |
+ * back_extdom_nss_sss.c and re-define context initialization to use
|
|
|
3f51ca |
+ * nsswrapper with our test data.
|
|
|
3f51ca |
+ *
|
|
|
3f51ca |
+ * This means we have to keep struct nss_ops_ctx definition in sync with tests!
|
|
|
3f51ca |
+ */
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+struct nss_ops_ctx {
|
|
|
3f51ca |
+ void *dl_handle;
|
|
|
3f51ca |
+ long int initgroups_start;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ enum nss_status (*getpwnam_r)(const char *name, struct passwd *result,
|
|
|
3f51ca |
+ char *buffer, size_t buflen, int *errnop);
|
|
|
3f51ca |
+ enum nss_status (*getpwuid_r)(uid_t uid, struct passwd *result,
|
|
|
3f51ca |
+ char *buffer, size_t buflen, int *errnop);
|
|
|
3f51ca |
+ enum nss_status (*getgrnam_r)(const char *name, struct group *result,
|
|
|
3f51ca |
+ char *buffer, size_t buflen, int *errnop);
|
|
|
3f51ca |
+ enum nss_status (*getgrgid_r)(gid_t gid, struct group *result,
|
|
|
3f51ca |
+ char *buffer, size_t buflen, int *errnop);
|
|
|
3f51ca |
+ enum nss_status (*initgroups_dyn)(const char *user, gid_t group,
|
|
|
3f51ca |
+ long int *start, long int *size,
|
|
|
3f51ca |
+ gid_t **groups, long int limit,
|
|
|
3f51ca |
+ int *errnop);
|
|
|
3f51ca |
+};
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+int cmocka_extdom_init_context(struct nss_ops_ctx **nss_context)
|
|
|
3f51ca |
+{
|
|
|
3f51ca |
+ struct nss_ops_ctx *ctx = NULL;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ if (nss_context == NULL) {
|
|
|
3f51ca |
+ return -1;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ ctx = calloc(1, sizeof(struct nss_ops_ctx));
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ if (ctx == NULL) {
|
|
|
3f51ca |
+ return ENOMEM;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+ *nss_context = ctx;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ ctx->dl_handle = dlopen("libnss_files.so.2", RTLD_NOW);
|
|
|
3f51ca |
+ if (ctx->dl_handle == NULL) {
|
|
|
3f51ca |
+ goto fail;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ ctx->getpwnam_r = dlsym(ctx->dl_handle, "_nss_files_getpwnam_r");
|
|
|
3f51ca |
+ if (ctx->getpwnam_r == NULL) {
|
|
|
3f51ca |
+ goto fail;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ ctx->getpwuid_r = dlsym(ctx->dl_handle, "_nss_files_getpwuid_r");
|
|
|
3f51ca |
+ if (ctx->getpwuid_r == NULL) {
|
|
|
3f51ca |
+ goto fail;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ ctx->getgrnam_r = dlsym(ctx->dl_handle, "_nss_files_getgrnam_r");
|
|
|
3f51ca |
+ if (ctx->getgrnam_r == NULL) {
|
|
|
3f51ca |
+ goto fail;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ ctx->getgrgid_r = dlsym(ctx->dl_handle, "_nss_files_getgrgid_r");
|
|
|
3f51ca |
+ if (ctx->getgrgid_r == NULL) {
|
|
|
3f51ca |
+ goto fail;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ ctx->initgroups_dyn = dlsym(ctx->dl_handle, "_nss_files_initgroups_dyn");
|
|
|
3f51ca |
+ if (ctx->initgroups_dyn == NULL) {
|
|
|
3f51ca |
+ goto fail;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ return 0;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+fail:
|
|
|
3f51ca |
+ back_extdom_free_context(nss_context);
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ return -1;
|
|
|
3f51ca |
+}
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+struct {
|
|
|
3f51ca |
+ const char *o, *n;
|
|
|
3f51ca |
+} path_table[] = {
|
|
|
3f51ca |
+ { .o = "/etc/passwd", .n = "./test_data/passwd"},
|
|
|
3f51ca |
+ { .o = "/etc/group", .n = "./test_data/group"},
|
|
|
3f51ca |
+ { .o = NULL, .n = NULL}};
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+FILE *(*original_fopen)(const char*, const char*) = NULL;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+FILE *fopen(const char *path, const char *mode) {
|
|
|
3f51ca |
+ const char *_path = NULL;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ /* Do not handle before-main() cases */
|
|
|
3f51ca |
+ if (original_fopen == NULL) {
|
|
|
3f51ca |
+ return NULL;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+ for(int i=0; path_table[i].o != NULL; i++) {
|
|
|
3f51ca |
+ if (strcmp(path, path_table[i].o) == 0) {
|
|
|
3f51ca |
+ _path = path_table[i].n;
|
|
|
3f51ca |
+ break;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+ return (*original_fopen)(_path ? _path : path, mode);
|
|
|
3f51ca |
+}
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+/* Attempt to initialize original_fopen before main()
|
|
|
3f51ca |
+ * There is no explicit order when all initializers are called,
|
|
|
3f51ca |
+ * so we might still be late here compared to a code in a shared
|
|
|
3f51ca |
+ * library initializer, like libselinux */
|
|
|
3f51ca |
+void redefined_fopen_ctor (void) __attribute__ ((constructor));
|
|
|
3f51ca |
+void redefined_fopen_ctor(void) {
|
|
|
3f51ca |
+ original_fopen = dlsym(RTLD_NEXT, "fopen");
|
|
|
3f51ca |
+}
|
|
|
3f51ca |
|
|
|
3f51ca |
void test_getpwnam_r_wrapper(void **state)
|
|
|
3f51ca |
{
|
|
|
3f51ca |
int ret;
|
|
|
3f51ca |
struct passwd pwd;
|
|
|
3f51ca |
char *buf;
|
|
|
3f51ca |
- size_t buf_len;
|
|
|
3f51ca |
+ size_t buf_len, max_big_buf_len;
|
|
|
3f51ca |
+ struct test_data *test_data;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ test_data = (struct test_data *) *state;
|
|
|
3f51ca |
|
|
|
3f51ca |
ret = get_buffer(&buf_len, &buf;;
|
|
|
3f51ca |
assert_int_equal(ret, 0);
|
|
|
3f51ca |
|
|
|
3f51ca |
- ret = getpwnam_r_wrapper(MAX_BUF, "non_exisiting_user", &pwd, &buf,
|
|
|
3f51ca |
- &buf_len);
|
|
|
3f51ca |
+ ret = getpwnam_r_wrapper(test_data->ctx,
|
|
|
3f51ca |
+ "non_exisiting_user", &pwd,
|
|
|
3f51ca |
+ &buf, &buf_len);
|
|
|
3f51ca |
assert_int_equal(ret, ENOENT);
|
|
|
3f51ca |
|
|
|
3f51ca |
- ret = getpwnam_r_wrapper(MAX_BUF, "user", &pwd, &buf, &buf_len);
|
|
|
3f51ca |
+ ret = getpwnam_r_wrapper(test_data->ctx,
|
|
|
3f51ca |
+ "user", &pwd, &buf, &buf_len);
|
|
|
3f51ca |
assert_int_equal(ret, 0);
|
|
|
3f51ca |
assert_string_equal(pwd.pw_name, "user");
|
|
|
3f51ca |
assert_string_equal(pwd.pw_passwd, "x");
|
|
|
3f51ca |
@@ -62,7 +205,8 @@ void test_getpwnam_r_wrapper(void **state)
|
|
|
3f51ca |
ret = get_buffer(&buf_len, &buf;;
|
|
|
3f51ca |
assert_int_equal(ret, 0);
|
|
|
3f51ca |
|
|
|
3f51ca |
- ret = getpwnam_r_wrapper(MAX_BUF, "user_big", &pwd, &buf, &buf_len);
|
|
|
3f51ca |
+ ret = getpwnam_r_wrapper(test_data->ctx,
|
|
|
3f51ca |
+ "user_big", &pwd, &buf, &buf_len);
|
|
|
3f51ca |
assert_int_equal(ret, 0);
|
|
|
3f51ca |
assert_string_equal(pwd.pw_name, "user_big");
|
|
|
3f51ca |
assert_string_equal(pwd.pw_passwd, "x");
|
|
|
3f51ca |
@@ -76,7 +220,11 @@ void test_getpwnam_r_wrapper(void **state)
|
|
|
3f51ca |
ret = get_buffer(&buf_len, &buf;;
|
|
|
3f51ca |
assert_int_equal(ret, 0);
|
|
|
3f51ca |
|
|
|
3f51ca |
- ret = getpwnam_r_wrapper(1024, "user_big", &pwd, &buf, &buf_len);
|
|
|
3f51ca |
+ max_big_buf_len = test_data->ctx->max_nss_buf_size;
|
|
|
3f51ca |
+ test_data->ctx->max_nss_buf_size = 1024;
|
|
|
3f51ca |
+ ret = getpwnam_r_wrapper(test_data->ctx,
|
|
|
3f51ca |
+ "user_big", &pwd, &buf, &buf_len);
|
|
|
3f51ca |
+ test_data->ctx->max_nss_buf_size = max_big_buf_len;
|
|
|
3f51ca |
assert_int_equal(ret, ERANGE);
|
|
|
3f51ca |
free(buf);
|
|
|
3f51ca |
}
|
|
|
3f51ca |
@@ -86,15 +234,18 @@ void test_getpwuid_r_wrapper(void **state)
|
|
|
3f51ca |
int ret;
|
|
|
3f51ca |
struct passwd pwd;
|
|
|
3f51ca |
char *buf;
|
|
|
3f51ca |
- size_t buf_len;
|
|
|
3f51ca |
+ size_t buf_len, max_big_buf_len;
|
|
|
3f51ca |
+ struct test_data *test_data;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ test_data = (struct test_data *) *state;
|
|
|
3f51ca |
|
|
|
3f51ca |
ret = get_buffer(&buf_len, &buf;;
|
|
|
3f51ca |
assert_int_equal(ret, 0);
|
|
|
3f51ca |
|
|
|
3f51ca |
- ret = getpwuid_r_wrapper(MAX_BUF, 99999, &pwd, &buf, &buf_len);
|
|
|
3f51ca |
+ ret = getpwuid_r_wrapper(test_data->ctx, 99999, &pwd, &buf, &buf_len);
|
|
|
3f51ca |
assert_int_equal(ret, ENOENT);
|
|
|
3f51ca |
|
|
|
3f51ca |
- ret = getpwuid_r_wrapper(MAX_BUF, 12345, &pwd, &buf, &buf_len);
|
|
|
3f51ca |
+ ret = getpwuid_r_wrapper(test_data->ctx, 12345, &pwd, &buf, &buf_len);
|
|
|
3f51ca |
assert_int_equal(ret, 0);
|
|
|
3f51ca |
assert_string_equal(pwd.pw_name, "user");
|
|
|
3f51ca |
assert_string_equal(pwd.pw_passwd, "x");
|
|
|
3f51ca |
@@ -108,7 +259,7 @@ void test_getpwuid_r_wrapper(void **state)
|
|
|
3f51ca |
ret = get_buffer(&buf_len, &buf;;
|
|
|
3f51ca |
assert_int_equal(ret, 0);
|
|
|
3f51ca |
|
|
|
3f51ca |
- ret = getpwuid_r_wrapper(MAX_BUF, 12346, &pwd, &buf, &buf_len);
|
|
|
3f51ca |
+ ret = getpwuid_r_wrapper(test_data->ctx, 12346, &pwd, &buf, &buf_len);
|
|
|
3f51ca |
assert_int_equal(ret, 0);
|
|
|
3f51ca |
assert_string_equal(pwd.pw_name, "user_big");
|
|
|
3f51ca |
assert_string_equal(pwd.pw_passwd, "x");
|
|
|
3f51ca |
@@ -122,7 +273,10 @@ void test_getpwuid_r_wrapper(void **state)
|
|
|
3f51ca |
ret = get_buffer(&buf_len, &buf;;
|
|
|
3f51ca |
assert_int_equal(ret, 0);
|
|
|
3f51ca |
|
|
|
3f51ca |
- ret = getpwuid_r_wrapper(1024, 12346, &pwd, &buf, &buf_len);
|
|
|
3f51ca |
+ max_big_buf_len = test_data->ctx->max_nss_buf_size;
|
|
|
3f51ca |
+ test_data->ctx->max_nss_buf_size = 1024;
|
|
|
3f51ca |
+ ret = getpwuid_r_wrapper(test_data->ctx, 12346, &pwd, &buf, &buf_len);
|
|
|
3f51ca |
+ test_data->ctx->max_nss_buf_size = max_big_buf_len;
|
|
|
3f51ca |
assert_int_equal(ret, ERANGE);
|
|
|
3f51ca |
free(buf);
|
|
|
3f51ca |
}
|
|
|
3f51ca |
@@ -132,15 +286,19 @@ void test_getgrnam_r_wrapper(void **state)
|
|
|
3f51ca |
int ret;
|
|
|
3f51ca |
struct group grp;
|
|
|
3f51ca |
char *buf;
|
|
|
3f51ca |
- size_t buf_len;
|
|
|
3f51ca |
+ size_t buf_len, max_big_buf_len;
|
|
|
3f51ca |
+ struct test_data *test_data;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ test_data = (struct test_data *) *state;
|
|
|
3f51ca |
|
|
|
3f51ca |
ret = get_buffer(&buf_len, &buf;;
|
|
|
3f51ca |
assert_int_equal(ret, 0);
|
|
|
3f51ca |
|
|
|
3f51ca |
- ret = getgrnam_r_wrapper(MAX_BUF, "non_exisiting_group", &grp, &buf, &buf_len);
|
|
|
3f51ca |
+ ret = getgrnam_r_wrapper(test_data->ctx,
|
|
|
3f51ca |
+ "non_exisiting_group", &grp, &buf, &buf_len);
|
|
|
3f51ca |
assert_int_equal(ret, ENOENT);
|
|
|
3f51ca |
|
|
|
3f51ca |
- ret = getgrnam_r_wrapper(MAX_BUF, "group", &grp, &buf, &buf_len);
|
|
|
3f51ca |
+ ret = getgrnam_r_wrapper(test_data->ctx, "group", &grp, &buf, &buf_len);
|
|
|
3f51ca |
assert_int_equal(ret, 0);
|
|
|
3f51ca |
assert_string_equal(grp.gr_name, "group");
|
|
|
3f51ca |
assert_string_equal(grp.gr_passwd, "x");
|
|
|
3f51ca |
@@ -153,7 +311,7 @@ void test_getgrnam_r_wrapper(void **state)
|
|
|
3f51ca |
ret = get_buffer(&buf_len, &buf;;
|
|
|
3f51ca |
assert_int_equal(ret, 0);
|
|
|
3f51ca |
|
|
|
3f51ca |
- ret = getgrnam_r_wrapper(MAX_BUF, "group_big", &grp, &buf, &buf_len);
|
|
|
3f51ca |
+ ret = getgrnam_r_wrapper(test_data->ctx, "group_big", &grp, &buf, &buf_len);
|
|
|
3f51ca |
assert_int_equal(ret, 0);
|
|
|
3f51ca |
assert_string_equal(grp.gr_name, "group_big");
|
|
|
3f51ca |
assert_string_equal(grp.gr_passwd, "x");
|
|
|
3f51ca |
@@ -165,7 +323,10 @@ void test_getgrnam_r_wrapper(void **state)
|
|
|
3f51ca |
ret = get_buffer(&buf_len, &buf;;
|
|
|
3f51ca |
assert_int_equal(ret, 0);
|
|
|
3f51ca |
|
|
|
3f51ca |
- ret = getgrnam_r_wrapper(1024, "group_big", &grp, &buf, &buf_len);
|
|
|
3f51ca |
+ max_big_buf_len = test_data->ctx->max_nss_buf_size;
|
|
|
3f51ca |
+ test_data->ctx->max_nss_buf_size = 1024;
|
|
|
3f51ca |
+ ret = getgrnam_r_wrapper(test_data->ctx, "group_big", &grp, &buf, &buf_len);
|
|
|
3f51ca |
+ test_data->ctx->max_nss_buf_size = max_big_buf_len;
|
|
|
3f51ca |
assert_int_equal(ret, ERANGE);
|
|
|
3f51ca |
free(buf);
|
|
|
3f51ca |
}
|
|
|
3f51ca |
@@ -175,15 +336,18 @@ void test_getgrgid_r_wrapper(void **state)
|
|
|
3f51ca |
int ret;
|
|
|
3f51ca |
struct group grp;
|
|
|
3f51ca |
char *buf;
|
|
|
3f51ca |
- size_t buf_len;
|
|
|
3f51ca |
+ size_t buf_len, max_big_buf_len;
|
|
|
3f51ca |
+ struct test_data *test_data;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ test_data = (struct test_data *) *state;
|
|
|
3f51ca |
|
|
|
3f51ca |
ret = get_buffer(&buf_len, &buf;;
|
|
|
3f51ca |
assert_int_equal(ret, 0);
|
|
|
3f51ca |
|
|
|
3f51ca |
- ret = getgrgid_r_wrapper(MAX_BUF, 99999, &grp, &buf, &buf_len);
|
|
|
3f51ca |
+ ret = getgrgid_r_wrapper(test_data->ctx, 99999, &grp, &buf, &buf_len);
|
|
|
3f51ca |
assert_int_equal(ret, ENOENT);
|
|
|
3f51ca |
|
|
|
3f51ca |
- ret = getgrgid_r_wrapper(MAX_BUF, 11111, &grp, &buf, &buf_len);
|
|
|
3f51ca |
+ ret = getgrgid_r_wrapper(test_data->ctx, 11111, &grp, &buf, &buf_len);
|
|
|
3f51ca |
assert_int_equal(ret, 0);
|
|
|
3f51ca |
assert_string_equal(grp.gr_name, "group");
|
|
|
3f51ca |
assert_string_equal(grp.gr_passwd, "x");
|
|
|
3f51ca |
@@ -196,7 +360,7 @@ void test_getgrgid_r_wrapper(void **state)
|
|
|
3f51ca |
ret = get_buffer(&buf_len, &buf;;
|
|
|
3f51ca |
assert_int_equal(ret, 0);
|
|
|
3f51ca |
|
|
|
3f51ca |
- ret = getgrgid_r_wrapper(MAX_BUF, 22222, &grp, &buf, &buf_len);
|
|
|
3f51ca |
+ ret = getgrgid_r_wrapper(test_data->ctx, 22222, &grp, &buf, &buf_len);
|
|
|
3f51ca |
assert_int_equal(ret, 0);
|
|
|
3f51ca |
assert_string_equal(grp.gr_name, "group_big");
|
|
|
3f51ca |
assert_string_equal(grp.gr_passwd, "x");
|
|
|
3f51ca |
@@ -208,7 +372,10 @@ void test_getgrgid_r_wrapper(void **state)
|
|
|
3f51ca |
ret = get_buffer(&buf_len, &buf;;
|
|
|
3f51ca |
assert_int_equal(ret, 0);
|
|
|
3f51ca |
|
|
|
3f51ca |
- ret = getgrgid_r_wrapper(1024, 22222, &grp, &buf, &buf_len);
|
|
|
3f51ca |
+ max_big_buf_len = test_data->ctx->max_nss_buf_size;
|
|
|
3f51ca |
+ test_data->ctx->max_nss_buf_size = 1024;
|
|
|
3f51ca |
+ ret = getgrgid_r_wrapper(test_data->ctx, 22222, &grp, &buf, &buf_len);
|
|
|
3f51ca |
+ test_data->ctx->max_nss_buf_size = max_big_buf_len;
|
|
|
3f51ca |
assert_int_equal(ret, ERANGE);
|
|
|
3f51ca |
free(buf);
|
|
|
3f51ca |
}
|
|
|
3f51ca |
@@ -219,16 +386,21 @@ void test_get_user_grouplist(void **state)
|
|
|
3f51ca |
size_t ngroups;
|
|
|
3f51ca |
gid_t *groups;
|
|
|
3f51ca |
size_t c;
|
|
|
3f51ca |
+ struct test_data *test_data;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ test_data = (struct test_data *) *state;
|
|
|
3f51ca |
|
|
|
3f51ca |
/* This is a bit odd behaviour of getgrouplist() it does not check if the
|
|
|
3f51ca |
* user exists, only if memberships of the user can be found. */
|
|
|
3f51ca |
- ret = get_user_grouplist("non_exisiting_user", 23456, &ngroups, &groups);
|
|
|
3f51ca |
+ ret = get_user_grouplist(test_data->ctx,
|
|
|
3f51ca |
+ "non_exisiting_user", 23456, &ngroups, &groups);
|
|
|
3f51ca |
assert_int_equal(ret, LDAP_SUCCESS);
|
|
|
3f51ca |
assert_int_equal(ngroups, 1);
|
|
|
3f51ca |
assert_int_equal(groups[0], 23456);
|
|
|
3f51ca |
free(groups);
|
|
|
3f51ca |
|
|
|
3f51ca |
- ret = get_user_grouplist("member0001", 23456, &ngroups, &groups);
|
|
|
3f51ca |
+ ret = get_user_grouplist(test_data->ctx,
|
|
|
3f51ca |
+ "member0001", 23456, &ngroups, &groups);
|
|
|
3f51ca |
assert_int_equal(ret, LDAP_SUCCESS);
|
|
|
3f51ca |
assert_int_equal(ngroups, 3);
|
|
|
3f51ca |
assert_int_equal(groups[0], 23456);
|
|
|
3f51ca |
@@ -236,14 +408,16 @@ void test_get_user_grouplist(void **state)
|
|
|
3f51ca |
assert_int_equal(groups[2], 22222);
|
|
|
3f51ca |
free(groups);
|
|
|
3f51ca |
|
|
|
3f51ca |
- ret = get_user_grouplist("member0003", 23456, &ngroups, &groups);
|
|
|
3f51ca |
+ ret = get_user_grouplist(test_data->ctx,
|
|
|
3f51ca |
+ "member0003", 23456, &ngroups, &groups);
|
|
|
3f51ca |
assert_int_equal(ret, LDAP_SUCCESS);
|
|
|
3f51ca |
assert_int_equal(ngroups, 2);
|
|
|
3f51ca |
assert_int_equal(groups[0], 23456);
|
|
|
3f51ca |
assert_int_equal(groups[1], 22222);
|
|
|
3f51ca |
free(groups);
|
|
|
3f51ca |
|
|
|
3f51ca |
- ret = get_user_grouplist("user_big", 23456, &ngroups, &groups);
|
|
|
3f51ca |
+ ret = get_user_grouplist(test_data->ctx,
|
|
|
3f51ca |
+ "user_big", 23456, &ngroups, &groups);
|
|
|
3f51ca |
assert_int_equal(ret, LDAP_SUCCESS);
|
|
|
3f51ca |
assert_int_equal(ngroups, 1001);
|
|
|
3f51ca |
assert_int_equal(groups[0], 23456);
|
|
|
3f51ca |
@@ -253,11 +427,6 @@ void test_get_user_grouplist(void **state)
|
|
|
3f51ca |
free(groups);
|
|
|
3f51ca |
}
|
|
|
3f51ca |
|
|
|
3f51ca |
-struct test_data {
|
|
|
3f51ca |
- struct extdom_req *req;
|
|
|
3f51ca |
- struct ipa_extdom_ctx *ctx;
|
|
|
3f51ca |
-};
|
|
|
3f51ca |
-
|
|
|
3f51ca |
static int extdom_req_setup(void **state)
|
|
|
3f51ca |
{
|
|
|
3f51ca |
struct test_data *test_data;
|
|
|
3f51ca |
@@ -269,8 +438,14 @@ static int extdom_req_setup(void **state)
|
|
|
3f51ca |
assert_non_null(test_data->req);
|
|
|
3f51ca |
|
|
|
3f51ca |
test_data->ctx = calloc(sizeof(struct ipa_extdom_ctx), 1);
|
|
|
3f51ca |
- assert_non_null(test_data->req);
|
|
|
3f51ca |
+ assert_non_null(test_data->ctx);
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ test_data->ctx->max_nss_buf_size = MAX_BUF;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ assert_int_equal(cmocka_extdom_init_context(&test_data->ctx->nss_ctx), 0);
|
|
|
3f51ca |
+ assert_non_null(test_data->ctx->nss_ctx);
|
|
|
3f51ca |
|
|
|
3f51ca |
+ back_extdom_set_timeout(test_data->ctx->nss_ctx, 10000);
|
|
|
3f51ca |
*state = test_data;
|
|
|
3f51ca |
|
|
|
3f51ca |
return 0;
|
|
|
3f51ca |
@@ -283,6 +458,7 @@ static int extdom_req_teardown(void **state)
|
|
|
3f51ca |
test_data = (struct test_data *) *state;
|
|
|
3f51ca |
|
|
|
3f51ca |
free_req_data(test_data->req);
|
|
|
3f51ca |
+ back_extdom_free_context(&test_data->ctx->nss_ctx);
|
|
|
3f51ca |
free(test_data->ctx);
|
|
|
3f51ca |
free(test_data);
|
|
|
3f51ca |
|
|
|
3f51ca |
@@ -450,5 +626,6 @@ int main(int argc, const char *argv[])
|
|
|
3f51ca |
cmocka_unit_test(test_decode),
|
|
|
3f51ca |
};
|
|
|
3f51ca |
|
|
|
3f51ca |
- return cmocka_run_group_tests(tests, NULL, NULL);
|
|
|
3f51ca |
+ assert_non_null(original_fopen);
|
|
|
3f51ca |
+ return cmocka_run_group_tests(tests, extdom_req_setup, extdom_req_teardown);
|
|
|
3f51ca |
}
|
|
|
3f51ca |
diff --git a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c
|
|
|
3f51ca |
index fe225fa86669a6728bec5014be41d80275f10717..86c6638ba73c2f59aff29191e3e68dc5c85d50fc 100644
|
|
|
3f51ca |
--- a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c
|
|
|
3f51ca |
+++ b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_common.c
|
|
|
3f51ca |
@@ -43,11 +43,12 @@
|
|
|
3f51ca |
|
|
|
3f51ca |
#include <errno.h>
|
|
|
3f51ca |
#include <stdio.h>
|
|
|
3f51ca |
+#include <sys/param.h>
|
|
|
3f51ca |
|
|
|
3f51ca |
#include "ipa_extdom.h"
|
|
|
3f51ca |
+#include "back_extdom.h"
|
|
|
3f51ca |
#include "util.h"
|
|
|
3f51ca |
|
|
|
3f51ca |
-#define MAX(a,b) (((a)>(b))?(a):(b))
|
|
|
3f51ca |
#define SSSD_DOMAIN_SEPARATOR '@'
|
|
|
3f51ca |
|
|
|
3f51ca |
int get_buffer(size_t *_buf_len, char **_buf)
|
|
|
3f51ca |
@@ -97,134 +98,137 @@ static int inc_buffer(size_t buf_max, size_t *_buf_len, char **_buf)
|
|
|
3f51ca |
return 0;
|
|
|
3f51ca |
}
|
|
|
3f51ca |
|
|
|
3f51ca |
-int getpwnam_r_wrapper(size_t buf_max, const char *name,
|
|
|
3f51ca |
- struct passwd *pwd, char **_buf, size_t *_buf_len)
|
|
|
3f51ca |
+int __nss_to_err(enum nss_status errcode)
|
|
|
3f51ca |
{
|
|
|
3f51ca |
- char *buf = NULL;
|
|
|
3f51ca |
- size_t buf_len = 0;
|
|
|
3f51ca |
- int ret;
|
|
|
3f51ca |
- struct passwd *result = NULL;
|
|
|
3f51ca |
+ switch(errcode) {
|
|
|
3f51ca |
+ case NSS_STATUS_SUCCESS:
|
|
|
3f51ca |
+ return 0;
|
|
|
3f51ca |
+ case NSS_STATUS_NOTFOUND:
|
|
|
3f51ca |
+ return ENOENT;
|
|
|
3f51ca |
+ case NSS_STATUS_TRYAGAIN:
|
|
|
3f51ca |
+ return ERANGE;
|
|
|
3f51ca |
+ case NSS_STATUS_UNAVAIL:
|
|
|
3f51ca |
+ return ETIMEDOUT;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
|
|
|
3f51ca |
- buf = *_buf;
|
|
|
3f51ca |
- buf_len = *_buf_len;
|
|
|
3f51ca |
+ return -1;
|
|
|
3f51ca |
+}
|
|
|
3f51ca |
|
|
|
3f51ca |
- while (buf != NULL
|
|
|
3f51ca |
- && (ret = getpwnam_r(name, pwd, buf, buf_len, &result)) == ERANGE) {
|
|
|
3f51ca |
- ret = inc_buffer(buf_max, &buf_len, &buf;;
|
|
|
3f51ca |
- if (ret != 0) {
|
|
|
3f51ca |
- if (ret == ERANGE) {
|
|
|
3f51ca |
- LOG("Buffer too small, increase ipaExtdomMaxNssBufSize.\n");
|
|
|
3f51ca |
- }
|
|
|
3f51ca |
- goto done;
|
|
|
3f51ca |
+int getpwnam_r_wrapper(struct ipa_extdom_ctx *ctx, const char *name,
|
|
|
3f51ca |
+ struct passwd *pwd, char **buf, size_t *buf_len)
|
|
|
3f51ca |
+{
|
|
|
3f51ca |
+ int ret, lerrno = 0;
|
|
|
3f51ca |
+ struct passwd *result = NULL;
|
|
|
3f51ca |
+ enum nss_status rc;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ for(rc = NSS_STATUS_TRYAGAIN; rc == NSS_STATUS_TRYAGAIN;) {
|
|
|
3f51ca |
+ rc = back_extdom_getpwnam(ctx->nss_ctx, name, pwd, *buf, *buf_len, &result, &lerrno);
|
|
|
3f51ca |
+ ret = __nss_to_err(rc);
|
|
|
3f51ca |
+ if (ret == ERANGE) {
|
|
|
3f51ca |
+ ret = inc_buffer(ctx->max_nss_buf_size, buf_len, buf);
|
|
|
3f51ca |
+ if (ret != 0) goto done;
|
|
|
3f51ca |
}
|
|
|
3f51ca |
}
|
|
|
3f51ca |
|
|
|
3f51ca |
- if (ret == 0 && result == NULL) {
|
|
|
3f51ca |
- ret = ENOENT;
|
|
|
3f51ca |
- }
|
|
|
3f51ca |
-
|
|
|
3f51ca |
done:
|
|
|
3f51ca |
- *_buf = buf;
|
|
|
3f51ca |
- *_buf_len = buf_len;
|
|
|
3f51ca |
-
|
|
|
3f51ca |
+ switch(ret) {
|
|
|
3f51ca |
+ case 0:
|
|
|
3f51ca |
+ if (result == NULL) ret = ENOENT;
|
|
|
3f51ca |
+ break;
|
|
|
3f51ca |
+ case ERANGE:
|
|
|
3f51ca |
+ LOG("Buffer too small, increase ipaExtdomMaxNssBufSize.\n");
|
|
|
3f51ca |
+ default:
|
|
|
3f51ca |
+ break;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
return ret;
|
|
|
3f51ca |
}
|
|
|
3f51ca |
|
|
|
3f51ca |
-int getpwuid_r_wrapper(size_t buf_max, uid_t uid,
|
|
|
3f51ca |
- struct passwd *pwd, char **_buf, size_t *_buf_len)
|
|
|
3f51ca |
+int getpwuid_r_wrapper(struct ipa_extdom_ctx *ctx, uid_t uid,
|
|
|
3f51ca |
+ struct passwd *pwd, char **buf, size_t *buf_len)
|
|
|
3f51ca |
{
|
|
|
3f51ca |
- char *buf = NULL;
|
|
|
3f51ca |
- size_t buf_len = 0;
|
|
|
3f51ca |
- int ret;
|
|
|
3f51ca |
+ int ret, lerrno;
|
|
|
3f51ca |
struct passwd *result = NULL;
|
|
|
3f51ca |
-
|
|
|
3f51ca |
- buf = *_buf;
|
|
|
3f51ca |
- buf_len = *_buf_len;
|
|
|
3f51ca |
-
|
|
|
3f51ca |
- while (buf != NULL
|
|
|
3f51ca |
- && (ret = getpwuid_r(uid, pwd, buf, buf_len, &result)) == ERANGE) {
|
|
|
3f51ca |
- ret = inc_buffer(buf_max, &buf_len, &buf;;
|
|
|
3f51ca |
- if (ret != 0) {
|
|
|
3f51ca |
- if (ret == ERANGE) {
|
|
|
3f51ca |
- LOG("Buffer too small, increase ipaExtdomMaxNssBufSize.\n");
|
|
|
3f51ca |
- }
|
|
|
3f51ca |
- goto done;
|
|
|
3f51ca |
+ enum nss_status rc;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ for(rc = NSS_STATUS_TRYAGAIN; rc == NSS_STATUS_TRYAGAIN;) {
|
|
|
3f51ca |
+ rc = back_extdom_getpwuid(ctx->nss_ctx, uid, pwd, *buf, *buf_len, &result, &lerrno);
|
|
|
3f51ca |
+ ret = __nss_to_err(rc);
|
|
|
3f51ca |
+ if (ret == ERANGE) {
|
|
|
3f51ca |
+ ret = inc_buffer(ctx->max_nss_buf_size, buf_len, buf);
|
|
|
3f51ca |
+ if (ret != 0) goto done;
|
|
|
3f51ca |
}
|
|
|
3f51ca |
}
|
|
|
3f51ca |
|
|
|
3f51ca |
- if (ret == 0 && result == NULL) {
|
|
|
3f51ca |
- ret = ENOENT;
|
|
|
3f51ca |
- }
|
|
|
3f51ca |
-
|
|
|
3f51ca |
done:
|
|
|
3f51ca |
- *_buf = buf;
|
|
|
3f51ca |
- *_buf_len = buf_len;
|
|
|
3f51ca |
+ switch(ret) {
|
|
|
3f51ca |
+ case 0:
|
|
|
3f51ca |
+ if (result == NULL) ret = ENOENT;
|
|
|
3f51ca |
+ break;
|
|
|
3f51ca |
+ case ERANGE:
|
|
|
3f51ca |
+ LOG("Buffer too small, increase ipaExtdomMaxNssBufSize.\n");
|
|
|
3f51ca |
+ default:
|
|
|
3f51ca |
+ break;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
|
|
|
3f51ca |
return ret;
|
|
|
3f51ca |
}
|
|
|
3f51ca |
|
|
|
3f51ca |
-int getgrnam_r_wrapper(size_t buf_max, const char *name,
|
|
|
3f51ca |
- struct group *grp, char **_buf, size_t *_buf_len)
|
|
|
3f51ca |
+int getgrnam_r_wrapper(struct ipa_extdom_ctx *ctx, const char *name,
|
|
|
3f51ca |
+ struct group *grp, char **buf, size_t *buf_len)
|
|
|
3f51ca |
{
|
|
|
3f51ca |
- char *buf = NULL;
|
|
|
3f51ca |
- size_t buf_len = 0;
|
|
|
3f51ca |
- int ret;
|
|
|
3f51ca |
+ int ret, lerrno;
|
|
|
3f51ca |
struct group *result = NULL;
|
|
|
3f51ca |
-
|
|
|
3f51ca |
- buf = *_buf;
|
|
|
3f51ca |
- buf_len = *_buf_len;
|
|
|
3f51ca |
-
|
|
|
3f51ca |
- while (buf != NULL
|
|
|
3f51ca |
- && (ret = getgrnam_r(name, grp, buf, buf_len, &result)) == ERANGE) {
|
|
|
3f51ca |
- ret = inc_buffer(buf_max, &buf_len, &buf;;
|
|
|
3f51ca |
- if (ret != 0) {
|
|
|
3f51ca |
- if (ret == ERANGE) {
|
|
|
3f51ca |
- LOG("Buffer too small, increase ipaExtdomMaxNssBufSize.\n");
|
|
|
3f51ca |
- }
|
|
|
3f51ca |
- goto done;
|
|
|
3f51ca |
+ enum nss_status rc;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ for(rc = NSS_STATUS_TRYAGAIN; rc == NSS_STATUS_TRYAGAIN;) {
|
|
|
3f51ca |
+ rc = back_extdom_getgrnam(ctx->nss_ctx, name, grp, *buf, *buf_len, &result, &lerrno);
|
|
|
3f51ca |
+ ret = __nss_to_err(rc);
|
|
|
3f51ca |
+ if (ret == ERANGE) {
|
|
|
3f51ca |
+ ret = inc_buffer(ctx->max_nss_buf_size, buf_len, buf);
|
|
|
3f51ca |
+ if (ret != 0) goto done;
|
|
|
3f51ca |
}
|
|
|
3f51ca |
}
|
|
|
3f51ca |
|
|
|
3f51ca |
- if (ret == 0 && result == NULL) {
|
|
|
3f51ca |
- ret = ENOENT;
|
|
|
3f51ca |
- }
|
|
|
3f51ca |
-
|
|
|
3f51ca |
done:
|
|
|
3f51ca |
- *_buf = buf;
|
|
|
3f51ca |
- *_buf_len = buf_len;
|
|
|
3f51ca |
+ switch(ret) {
|
|
|
3f51ca |
+ case 0:
|
|
|
3f51ca |
+ if (result == NULL) ret = ENOENT;
|
|
|
3f51ca |
+ break;
|
|
|
3f51ca |
+ case ERANGE:
|
|
|
3f51ca |
+ LOG("Buffer too small, increase ipaExtdomMaxNssBufSize.\n");
|
|
|
3f51ca |
+ default:
|
|
|
3f51ca |
+ break;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
|
|
|
3f51ca |
return ret;
|
|
|
3f51ca |
}
|
|
|
3f51ca |
|
|
|
3f51ca |
-int getgrgid_r_wrapper(size_t buf_max, gid_t gid,
|
|
|
3f51ca |
- struct group *grp, char **_buf, size_t *_buf_len)
|
|
|
3f51ca |
+int getgrgid_r_wrapper(struct ipa_extdom_ctx *ctx, gid_t gid,
|
|
|
3f51ca |
+ struct group *grp, char **buf, size_t *buf_len)
|
|
|
3f51ca |
{
|
|
|
3f51ca |
- char *buf = NULL;
|
|
|
3f51ca |
- size_t buf_len = 0;
|
|
|
3f51ca |
- int ret;
|
|
|
3f51ca |
+ int ret, lerrno;
|
|
|
3f51ca |
struct group *result = NULL;
|
|
|
3f51ca |
-
|
|
|
3f51ca |
- buf = *_buf;
|
|
|
3f51ca |
- buf_len = *_buf_len;
|
|
|
3f51ca |
-
|
|
|
3f51ca |
- while (buf != NULL
|
|
|
3f51ca |
- && (ret = getgrgid_r(gid, grp, buf, buf_len, &result)) == ERANGE) {
|
|
|
3f51ca |
- ret = inc_buffer(buf_max, &buf_len, &buf;;
|
|
|
3f51ca |
- if (ret != 0) {
|
|
|
3f51ca |
- if (ret == ERANGE) {
|
|
|
3f51ca |
- LOG("Buffer too small, increase ipaExtdomMaxNssBufSize.\n");
|
|
|
3f51ca |
- }
|
|
|
3f51ca |
- goto done;
|
|
|
3f51ca |
+ enum nss_status rc;
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ for(rc = NSS_STATUS_TRYAGAIN; rc == NSS_STATUS_TRYAGAIN;) {
|
|
|
3f51ca |
+ rc = back_extdom_getgrgid(ctx->nss_ctx, gid, grp, *buf, *buf_len, &result, &lerrno);
|
|
|
3f51ca |
+ ret = __nss_to_err(rc);
|
|
|
3f51ca |
+ if (ret == ERANGE) {
|
|
|
3f51ca |
+ ret = inc_buffer(ctx->max_nss_buf_size, buf_len, buf);
|
|
|
3f51ca |
+ if (ret != 0) goto done;
|
|
|
3f51ca |
}
|
|
|
3f51ca |
}
|
|
|
3f51ca |
|
|
|
3f51ca |
- if (ret == 0 && result == NULL) {
|
|
|
3f51ca |
- ret = ENOENT;
|
|
|
3f51ca |
- }
|
|
|
3f51ca |
-
|
|
|
3f51ca |
done:
|
|
|
3f51ca |
- *_buf = buf;
|
|
|
3f51ca |
- *_buf_len = buf_len;
|
|
|
3f51ca |
+ switch(ret) {
|
|
|
3f51ca |
+ case 0:
|
|
|
3f51ca |
+ if (result == NULL) ret = ENOENT;
|
|
|
3f51ca |
+ break;
|
|
|
3f51ca |
+ case ERANGE:
|
|
|
3f51ca |
+ LOG("Buffer too small, increase ipaExtdomMaxNssBufSize.\n");
|
|
|
3f51ca |
+ default:
|
|
|
3f51ca |
+ break;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
|
|
|
3f51ca |
return ret;
|
|
|
3f51ca |
}
|
|
|
3f51ca |
@@ -406,13 +410,14 @@ int check_request(struct extdom_req *req, enum extdom_version version)
|
|
|
3f51ca |
return LDAP_SUCCESS;
|
|
|
3f51ca |
}
|
|
|
3f51ca |
|
|
|
3f51ca |
-int get_user_grouplist(const char *name, gid_t gid,
|
|
|
3f51ca |
+int get_user_grouplist(struct ipa_extdom_ctx *ctx, const char *name, gid_t gid,
|
|
|
3f51ca |
size_t *_ngroups, gid_t **_groups)
|
|
|
3f51ca |
{
|
|
|
3f51ca |
- int ret;
|
|
|
3f51ca |
+ int lerrno;
|
|
|
3f51ca |
int ngroups;
|
|
|
3f51ca |
gid_t *groups;
|
|
|
3f51ca |
gid_t *new_groups;
|
|
|
3f51ca |
+ enum nss_status rc;
|
|
|
3f51ca |
|
|
|
3f51ca |
ngroups = 128;
|
|
|
3f51ca |
groups = malloc(ngroups * sizeof(gid_t));
|
|
|
3f51ca |
@@ -420,19 +425,18 @@ int get_user_grouplist(const char *name, gid_t gid,
|
|
|
3f51ca |
return LDAP_OPERATIONS_ERROR;
|
|
|
3f51ca |
}
|
|
|
3f51ca |
|
|
|
3f51ca |
- ret = getgrouplist(name, gid, groups, &ngroups);
|
|
|
3f51ca |
- if (ret == -1) {
|
|
|
3f51ca |
- new_groups = realloc(groups, ngroups * sizeof(gid_t));
|
|
|
3f51ca |
- if (new_groups == NULL) {
|
|
|
3f51ca |
- free(groups);
|
|
|
3f51ca |
- return LDAP_OPERATIONS_ERROR;
|
|
|
3f51ca |
- }
|
|
|
3f51ca |
- groups = new_groups;
|
|
|
3f51ca |
-
|
|
|
3f51ca |
- ret = getgrouplist(name, gid, groups, &ngroups);
|
|
|
3f51ca |
- if (ret == -1) {
|
|
|
3f51ca |
- free(groups);
|
|
|
3f51ca |
- return LDAP_OPERATIONS_ERROR;
|
|
|
3f51ca |
+ for(rc = NSS_STATUS_TRYAGAIN; rc == NSS_STATUS_TRYAGAIN;) {
|
|
|
3f51ca |
+ rc = back_extdom_getgrouplist(ctx->nss_ctx, name, gid, groups, &ngroups, &lerrno);
|
|
|
3f51ca |
+ if (rc == NSS_STATUS_TRYAGAIN) {
|
|
|
3f51ca |
+ new_groups = NULL;
|
|
|
3f51ca |
+ if (lerrno == ERANGE) {
|
|
|
3f51ca |
+ new_groups = realloc(groups, ngroups * sizeof(gid_t));
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+ if ((new_groups == NULL) || (lerrno == ENOMEM)) {
|
|
|
3f51ca |
+ free(groups);
|
|
|
3f51ca |
+ return LDAP_OPERATIONS_ERROR;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+ groups = new_groups;
|
|
|
3f51ca |
}
|
|
|
3f51ca |
}
|
|
|
3f51ca |
|
|
|
3f51ca |
@@ -538,7 +542,7 @@ int pack_ber_user(struct ipa_extdom_ctx *ctx,
|
|
|
3f51ca |
}
|
|
|
3f51ca |
|
|
|
3f51ca |
if (response_type == RESP_USER_GROUPLIST) {
|
|
|
3f51ca |
- ret = get_user_grouplist(user_name, gid, &ngroups, &groups);
|
|
|
3f51ca |
+ ret = get_user_grouplist(ctx, user_name, gid, &ngroups, &groups);
|
|
|
3f51ca |
if (ret != LDAP_SUCCESS) {
|
|
|
3f51ca |
goto done;
|
|
|
3f51ca |
}
|
|
|
3f51ca |
@@ -561,7 +565,7 @@ int pack_ber_user(struct ipa_extdom_ctx *ctx,
|
|
|
3f51ca |
}
|
|
|
3f51ca |
|
|
|
3f51ca |
for (c = 0; c < ngroups; c++) {
|
|
|
3f51ca |
- ret = getgrgid_r_wrapper(ctx->max_nss_buf_size,
|
|
|
3f51ca |
+ ret = getgrgid_r_wrapper(ctx,
|
|
|
3f51ca |
groups[c], &grp, &buf, &buf_len);
|
|
|
3f51ca |
if (ret != 0) {
|
|
|
3f51ca |
if (ret == ENOMEM || ret == ERANGE) {
|
|
|
3f51ca |
@@ -841,8 +845,7 @@ static int handle_uid_request(struct ipa_extdom_ctx *ctx,
|
|
|
3f51ca |
|
|
|
3f51ca |
ret = pack_ber_sid(sid_str, berval);
|
|
|
3f51ca |
} else {
|
|
|
3f51ca |
- ret = getpwuid_r_wrapper(ctx->max_nss_buf_size, uid, &pwd, &buf,
|
|
|
3f51ca |
- &buf_len);
|
|
|
3f51ca |
+ ret = getpwuid_r_wrapper(ctx, uid, &pwd, &buf, &buf_len);
|
|
|
3f51ca |
if (ret != 0) {
|
|
|
3f51ca |
if (ret == ENOMEM || ret == ERANGE) {
|
|
|
3f51ca |
ret = LDAP_OPERATIONS_ERROR;
|
|
|
3f51ca |
@@ -913,8 +916,7 @@ static int handle_gid_request(struct ipa_extdom_ctx *ctx,
|
|
|
3f51ca |
|
|
|
3f51ca |
ret = pack_ber_sid(sid_str, berval);
|
|
|
3f51ca |
} else {
|
|
|
3f51ca |
- ret = getgrgid_r_wrapper(ctx->max_nss_buf_size, gid, &grp, &buf,
|
|
|
3f51ca |
- &buf_len);
|
|
|
3f51ca |
+ ret = getgrgid_r_wrapper(ctx, gid, &grp, &buf, &buf_len);
|
|
|
3f51ca |
if (ret != 0) {
|
|
|
3f51ca |
if (ret == ENOMEM || ret == ERANGE) {
|
|
|
3f51ca |
ret = LDAP_OPERATIONS_ERROR;
|
|
|
3f51ca |
@@ -1053,8 +1055,7 @@ static int handle_sid_request(struct ipa_extdom_ctx *ctx,
|
|
|
3f51ca |
switch(id_type) {
|
|
|
3f51ca |
case SSS_ID_TYPE_UID:
|
|
|
3f51ca |
case SSS_ID_TYPE_BOTH:
|
|
|
3f51ca |
- ret = getpwnam_r_wrapper(ctx->max_nss_buf_size, fq_name, &pwd, &buf,
|
|
|
3f51ca |
- &buf_len);
|
|
|
3f51ca |
+ ret = getpwnam_r_wrapper(ctx, fq_name, &pwd, &buf, &buf_len);
|
|
|
3f51ca |
if (ret != 0) {
|
|
|
3f51ca |
if (ret == ENOMEM || ret == ERANGE) {
|
|
|
3f51ca |
ret = LDAP_OPERATIONS_ERROR;
|
|
|
3f51ca |
@@ -1086,8 +1087,7 @@ static int handle_sid_request(struct ipa_extdom_ctx *ctx,
|
|
|
3f51ca |
pwd.pw_shell, kv_list, berval);
|
|
|
3f51ca |
break;
|
|
|
3f51ca |
case SSS_ID_TYPE_GID:
|
|
|
3f51ca |
- ret = getgrnam_r_wrapper(ctx->max_nss_buf_size, fq_name, &grp, &buf,
|
|
|
3f51ca |
- &buf_len);
|
|
|
3f51ca |
+ ret = getgrnam_r_wrapper(ctx, fq_name, &grp, &buf, &buf_len);
|
|
|
3f51ca |
if (ret != 0) {
|
|
|
3f51ca |
if (ret == ENOMEM || ret == ERANGE) {
|
|
|
3f51ca |
ret = LDAP_OPERATIONS_ERROR;
|
|
|
3f51ca |
@@ -1181,8 +1181,7 @@ static int handle_name_request(struct ipa_extdom_ctx *ctx,
|
|
|
3f51ca |
goto done;
|
|
|
3f51ca |
}
|
|
|
3f51ca |
|
|
|
3f51ca |
- ret = getpwnam_r_wrapper(ctx->max_nss_buf_size, fq_name, &pwd, &buf,
|
|
|
3f51ca |
- &buf_len);
|
|
|
3f51ca |
+ ret = getpwnam_r_wrapper(ctx, fq_name, &pwd, &buf, &buf_len);
|
|
|
3f51ca |
if (ret == 0) {
|
|
|
3f51ca |
if (request_type == REQ_FULL_WITH_GROUPS) {
|
|
|
3f51ca |
ret = sss_nss_getorigbyname(pwd.pw_name, &kv_list, &id_type);
|
|
|
3f51ca |
@@ -1211,8 +1210,7 @@ static int handle_name_request(struct ipa_extdom_ctx *ctx,
|
|
|
3f51ca |
* error codes which can indicate that the user was not found. To
|
|
|
3f51ca |
* be on the safe side we fail back to the group lookup on all
|
|
|
3f51ca |
* errors. */
|
|
|
3f51ca |
- ret = getgrnam_r_wrapper(ctx->max_nss_buf_size, fq_name, &grp, &buf,
|
|
|
3f51ca |
- &buf_len);
|
|
|
3f51ca |
+ ret = getgrnam_r_wrapper(ctx, fq_name, &grp, &buf, &buf_len);
|
|
|
3f51ca |
if (ret != 0) {
|
|
|
3f51ca |
if (ret == ENOMEM || ret == ERANGE) {
|
|
|
3f51ca |
ret = LDAP_OPERATIONS_ERROR;
|
|
|
3f51ca |
diff --git a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_extop.c b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_extop.c
|
|
|
3f51ca |
index 5bc8c2f571e311c5ae4cc56e2e1ae7d4e2f77ee6..83c30e7e6aad72af603c0b4ed1c49b80fa57560f 100644
|
|
|
3f51ca |
--- a/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_extop.c
|
|
|
3f51ca |
+++ b/daemons/ipa-slapi-plugins/ipa-extdom-extop/ipa_extdom_extop.c
|
|
|
3f51ca |
@@ -38,9 +38,11 @@
|
|
|
3f51ca |
* END COPYRIGHT BLOCK **/
|
|
|
3f51ca |
|
|
|
3f51ca |
#include "ipa_extdom.h"
|
|
|
3f51ca |
+#include "back_extdom.h"
|
|
|
3f51ca |
#include "util.h"
|
|
|
3f51ca |
|
|
|
3f51ca |
#define DEFAULT_MAX_NSS_BUFFER (128*1024*1024)
|
|
|
3f51ca |
+#define DEFAULT_MAX_NSS_TIMEOUT (10*1000)
|
|
|
3f51ca |
|
|
|
3f51ca |
Slapi_PluginDesc ipa_extdom_plugin_desc = {
|
|
|
3f51ca |
IPA_EXTDOM_FEATURE_DESC,
|
|
|
3f51ca |
@@ -166,6 +168,7 @@ static int ipa_extdom_init_ctx(Slapi_PBlock *pb, struct ipa_extdom_ctx **_ctx)
|
|
|
3f51ca |
struct ipa_extdom_ctx *ctx;
|
|
|
3f51ca |
Slapi_Entry *e;
|
|
|
3f51ca |
int ret;
|
|
|
3f51ca |
+ unsigned int timeout;
|
|
|
3f51ca |
|
|
|
3f51ca |
ctx = calloc(1, sizeof(struct ipa_extdom_ctx));
|
|
|
3f51ca |
if (!ctx) {
|
|
|
3f51ca |
@@ -202,6 +205,20 @@ static int ipa_extdom_init_ctx(Slapi_PBlock *pb, struct ipa_extdom_ctx **_ctx)
|
|
|
3f51ca |
}
|
|
|
3f51ca |
LOG("Maximal nss buffer size set to [%zu]!\n", ctx->max_nss_buf_size);
|
|
|
3f51ca |
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ ret = back_extdom_init_context(&ctx->nss_ctx);
|
|
|
3f51ca |
+ if (ret != 0) {
|
|
|
3f51ca |
+ LOG("Unable to initialize nss interface: returned [%d]!\n", ret);
|
|
|
3f51ca |
+ goto done;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+ timeout = slapi_entry_attr_get_uint(e, "ipaExtdomMaxNssTimeout");
|
|
|
3f51ca |
+ if (timeout == 0) {
|
|
|
3f51ca |
+ timeout = DEFAULT_MAX_NSS_TIMEOUT;
|
|
|
3f51ca |
+ }
|
|
|
3f51ca |
+ back_extdom_set_timeout(ctx->nss_ctx, timeout);
|
|
|
3f51ca |
+ LOG("Maximal nss timeout (in ms) set to [%u]!\n", timeout);
|
|
|
3f51ca |
+
|
|
|
3f51ca |
ret = 0;
|
|
|
3f51ca |
|
|
|
3f51ca |
done:
|
|
|
3f51ca |
diff --git a/daemons/ipa-slapi-plugins/ipa-extdom-extop/test_data/test_setup.sh b/daemons/ipa-slapi-plugins/ipa-extdom-extop/test_data/test_setup.sh
|
|
|
3f51ca |
deleted file mode 100644
|
|
|
3f51ca |
index ad839f340efe989a91cd6902f59c9a41483f68e0..0000000000000000000000000000000000000000
|
|
|
3f51ca |
--- a/daemons/ipa-slapi-plugins/ipa-extdom-extop/test_data/test_setup.sh
|
|
|
3f51ca |
+++ /dev/null
|
|
|
3f51ca |
@@ -1,3 +0,0 @@
|
|
|
3f51ca |
-export LD_PRELOAD=$(pkg-config --libs nss_wrapper)
|
|
|
3f51ca |
-export NSS_WRAPPER_PASSWD=./test_data/passwd
|
|
|
3f51ca |
-export NSS_WRAPPER_GROUP=./test_data/group
|
|
|
3f51ca |
diff --git a/freeipa.spec.in b/freeipa.spec.in
|
|
|
3f51ca |
index a8b5ce81fcf9bdb61cd3707e6b68b6f2196e0776..80ae98c5515f64a8df8d981ad5e91b05c84e31c1 100644
|
|
|
3f51ca |
--- a/freeipa.spec.in
|
|
|
3f51ca |
+++ b/freeipa.spec.in
|
|
|
3f51ca |
@@ -246,7 +246,6 @@ BuildRequires: python3-augeas
|
|
|
3f51ca |
#
|
|
|
3f51ca |
%if ! %{ONLY_CLIENT}
|
|
|
3f51ca |
BuildRequires: libcmocka-devel
|
|
|
3f51ca |
-BuildRequires: nss_wrapper
|
|
|
3f51ca |
# Required by ipa_kdb_tests
|
|
|
3f51ca |
BuildRequires: %{_libdir}/krb5/plugins/kdb/db2.so
|
|
|
3f51ca |
%endif # ONLY_CLIENT
|
|
|
3f51ca |
diff --git a/server.m4 b/server.m4
|
|
|
3f51ca |
index a9670c87372bb7b92d08dad634c0bda123a02597..f0a8bbcc778596dade89d9332abb2939b8a44143 100644
|
|
|
3f51ca |
--- a/server.m4
|
|
|
3f51ca |
+++ b/server.m4
|
|
|
3f51ca |
@@ -35,6 +35,16 @@ AC_CHECK_LIB([sss_nss_idmap],
|
|
|
3f51ca |
[AC_MSG_ERROR([Required sss_nss_getlistbycert symbol in sss_nss_idmap not found])],
|
|
|
3f51ca |
[])
|
|
|
3f51ca |
|
|
|
3f51ca |
+dnl --- if sss_nss_idmap provides _timeout() API, use it
|
|
|
3f51ca |
+bck_cflags="$CFLAGS"
|
|
|
3f51ca |
+CFLAGS="$CFLAGS -DIPA_389DS_PLUGIN_HELPER_CALLS"
|
|
|
3f51ca |
+AC_CHECK_DECLS([sss_nss_getpwnam_timeout], [], [], [[#include <sss_nss_idmap.h>]])
|
|
|
3f51ca |
+CFLAGS="$bck_cflags"
|
|
|
3f51ca |
+
|
|
|
3f51ca |
+if test "x$ac_cv_have_decl_sss_nss_getpwnam_timeout" = xyes ; then
|
|
|
3f51ca |
+ AC_DEFINE(USE_SSS_NSS_TIMEOUT,1,[Use extended NSS API provided by SSSD])
|
|
|
3f51ca |
+fi
|
|
|
3f51ca |
+
|
|
|
3f51ca |
dnl -- sss_certmap and certauth.h are needed by the IPA KDB certauth plugin --
|
|
|
3f51ca |
PKG_CHECK_EXISTS([sss_certmap],
|
|
|
3f51ca |
[PKG_CHECK_MODULES([SSSCERTMAP], [sss_certmap])],
|
|
|
3f51ca |
--
|
|
|
3f51ca |
2.14.3
|
|
|
3f51ca |
|