Imported Debian patch 4.8.10-2
This commit is contained in:
committed by
Mario Fetka
parent
8bc559c5a1
commit
358acdd85f
@@ -50,9 +50,11 @@ TESTS =
|
||||
check_PROGRAMS =
|
||||
|
||||
if HAVE_CMOCKA
|
||||
if HAVE_UNSHARE
|
||||
TESTS += extdom_cmocka_tests
|
||||
check_PROGRAMS += extdom_cmocka_tests
|
||||
endif
|
||||
endif
|
||||
|
||||
extdom_cmocka_tests_SOURCES = \
|
||||
ipa_extdom_cmocka_tests.c \
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Makefile.in generated by automake 1.16.1 from Makefile.am.
|
||||
# Makefile.in generated by automake 1.16.2 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994-2018 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1994-2020 Free Software Foundation, Inc.
|
||||
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
@@ -98,8 +98,8 @@ host_triplet = @host@
|
||||
@USE_SSS_NSS_TIMEOUT_FALSE@am__append_2 = back_extdom_nss_sss.c
|
||||
TESTS = $(am__EXEEXT_1)
|
||||
check_PROGRAMS = $(am__EXEEXT_1)
|
||||
@HAVE_CMOCKA_TRUE@am__append_3 = extdom_cmocka_tests
|
||||
@HAVE_CMOCKA_TRUE@am__append_4 = extdom_cmocka_tests
|
||||
@HAVE_CMOCKA_TRUE@@HAVE_UNSHARE_TRUE@am__append_3 = extdom_cmocka_tests
|
||||
@HAVE_CMOCKA_TRUE@@HAVE_UNSHARE_TRUE@am__append_4 = extdom_cmocka_tests
|
||||
subdir = daemons/ipa-slapi-plugins/ipa-extdom-extop
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \
|
||||
@@ -118,7 +118,7 @@ mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
@HAVE_CMOCKA_TRUE@am__EXEEXT_1 = extdom_cmocka_tests$(EXEEXT)
|
||||
@HAVE_CMOCKA_TRUE@@HAVE_UNSHARE_TRUE@am__EXEEXT_1 = extdom_cmocka_tests$(EXEEXT)
|
||||
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||
am__vpath_adj = case $$p in \
|
||||
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
@@ -489,6 +489,8 @@ JSLINT = @JSLINT@
|
||||
KRAD_LIBS = @KRAD_LIBS@
|
||||
KRB5KDC_SERVICE = @KRB5KDC_SERVICE@
|
||||
KRB5_CFLAGS = @KRB5_CFLAGS@
|
||||
KRB5_GSSAPI_CFLAGS = @KRB5_GSSAPI_CFLAGS@
|
||||
KRB5_GSSAPI_LIBS = @KRB5_GSSAPI_LIBS@
|
||||
KRB5_LIBS = @KRB5_LIBS@
|
||||
LD = @LD@
|
||||
LDAP_CFLAGS = @LDAP_CFLAGS@
|
||||
@@ -531,11 +533,10 @@ NM = @NM@
|
||||
NMEDIT = @NMEDIT@
|
||||
NSPR_CFLAGS = @NSPR_CFLAGS@
|
||||
NSPR_LIBS = @NSPR_LIBS@
|
||||
NSS_CFLAGS = @NSS_CFLAGS@
|
||||
NSS_LIBS = @NSS_LIBS@
|
||||
NUM_VERSION = @NUM_VERSION@
|
||||
OBJDUMP = @OBJDUMP@
|
||||
OBJEXT = @OBJEXT@
|
||||
ODS_GROUP = @ODS_GROUP@
|
||||
ODS_USER = @ODS_USER@
|
||||
OTOOL = @OTOOL@
|
||||
OTOOL64 = @OTOOL64@
|
||||
@@ -556,8 +557,6 @@ POPT_LIBS = @POPT_LIBS@
|
||||
POSUB = @POSUB@
|
||||
PYLINT = @PYLINT@
|
||||
PYTHON = @PYTHON@
|
||||
PYTHON2 = @PYTHON2@
|
||||
PYTHON3 = @PYTHON3@
|
||||
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
|
||||
PYTHON_INSTALL_EXTRA_OPTIONS = @PYTHON_INSTALL_EXTRA_OPTIONS@
|
||||
PYTHON_PLATFORM = @PYTHON_PLATFORM@
|
||||
@@ -645,7 +644,9 @@ program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
pyexecdir = @pyexecdir@
|
||||
pythondir = @pythondir@
|
||||
runstatedir = @runstatedir@
|
||||
sbindir = @sbindir@
|
||||
selinux_makefile = @selinux_makefile@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
sysconfdir = @sysconfdir@
|
||||
|
||||
@@ -35,6 +35,9 @@ enum nss_status {
|
||||
NSS_STATUS_RETURN
|
||||
};
|
||||
|
||||
/* default NSS operation timeout 10s (ipaExtdomMaxNssTimeout) */
|
||||
#define DEFAULT_MAX_NSS_TIMEOUT (10*1000)
|
||||
|
||||
/* NSS backend operations implemented using either nss_sss.so.2 or libsss_nss_idmap API */
|
||||
struct nss_ops_ctx;
|
||||
|
||||
@@ -42,6 +45,7 @@ int back_extdom_init_context(struct nss_ops_ctx **nss_context);
|
||||
void back_extdom_free_context(struct nss_ops_ctx **nss_context);
|
||||
void back_extdom_set_timeout(struct nss_ops_ctx *nss_context,
|
||||
unsigned int timeout);
|
||||
unsigned int back_extdom_get_timeout(struct nss_ops_ctx *nss_context);
|
||||
void back_extdom_evict_user(struct nss_ops_ctx *nss_context,
|
||||
const char *name);
|
||||
void back_extdom_evict_group(struct nss_ops_ctx *nss_context,
|
||||
|
||||
@@ -135,7 +135,7 @@ fail:
|
||||
}
|
||||
|
||||
|
||||
/* Following three functions cannot be implemented with nss_sss.so.2
|
||||
/* Following four functions cannot be implemented with nss_sss.so.2
|
||||
* As result, we simply do nothing here */
|
||||
|
||||
void back_extdom_set_timeout(struct nss_ops_ctx *nss_context,
|
||||
@@ -143,6 +143,10 @@ void back_extdom_set_timeout(struct nss_ops_ctx *nss_context,
|
||||
/* no operation */
|
||||
}
|
||||
|
||||
unsigned int back_extdom_get_timeout(struct nss_ops_ctx *nss_context) {
|
||||
return DEFAULT_MAX_NSS_TIMEOUT;
|
||||
}
|
||||
|
||||
void back_extdom_evict_user(struct nss_ops_ctx *nss_context,
|
||||
const char *name) {
|
||||
/* no operation */
|
||||
@@ -288,4 +292,3 @@ enum nss_status back_extdom_getgrouplist(struct nss_ops_ctx *nss_context,
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -62,10 +62,10 @@ static enum nss_status __convert_sss_nss2nss_status(int errcode) {
|
||||
return NSS_STATUS_SUCCESS;
|
||||
case ENOENT:
|
||||
return NSS_STATUS_NOTFOUND;
|
||||
case ETIME:
|
||||
/* fall-through */
|
||||
case ERANGE:
|
||||
return NSS_STATUS_TRYAGAIN;
|
||||
case ETIME:
|
||||
/* fall-through */
|
||||
case ETIMEDOUT:
|
||||
/* fall-through */
|
||||
default:
|
||||
@@ -111,6 +111,14 @@ void back_extdom_set_timeout(struct nss_ops_ctx *nss_context,
|
||||
nss_context->timeout = timeout;
|
||||
}
|
||||
|
||||
unsigned int back_extdom_get_timeout(struct nss_ops_ctx *nss_context) {
|
||||
if (nss_context == NULL) {
|
||||
return DEFAULT_MAX_NSS_TIMEOUT;
|
||||
}
|
||||
|
||||
return nss_context->timeout;
|
||||
}
|
||||
|
||||
void back_extdom_evict_user(struct nss_ops_ctx *nss_context,
|
||||
const char *name) {
|
||||
if (nss_context == NULL) {
|
||||
@@ -272,4 +280,3 @@ enum nss_status back_extdom_getgrouplist(struct nss_ops_ctx *nss_context,
|
||||
}
|
||||
return __convert_sss_nss2nss_status(ret);
|
||||
}
|
||||
|
||||
|
||||
@@ -59,10 +59,12 @@
|
||||
#include <lber.h>
|
||||
#include <time.h>
|
||||
|
||||
#define IPA_389DS_PLUGIN_HELPER_CALLS
|
||||
#include <sss_nss_idmap.h>
|
||||
|
||||
#define EXOP_EXTDOM_OID "2.16.840.1.113730.3.8.10.4"
|
||||
#define EXOP_EXTDOM_V1_OID "2.16.840.1.113730.3.8.10.4.1"
|
||||
#define EXOP_EXTDOM_V2_OID "2.16.840.1.113730.3.8.10.4.2"
|
||||
|
||||
#define IPA_EXTDOM_PLUGIN_NAME "ipa-extdom-extop"
|
||||
#define IPA_EXTDOM_FEATURE_DESC "IPA trusted domain ID mapper"
|
||||
@@ -72,7 +74,8 @@
|
||||
|
||||
enum extdom_version {
|
||||
EXTDOM_V0 = 0,
|
||||
EXTDOM_V1
|
||||
EXTDOM_V1,
|
||||
EXTDOM_V2
|
||||
};
|
||||
|
||||
enum input_types {
|
||||
@@ -80,7 +83,9 @@ enum input_types {
|
||||
INP_NAME,
|
||||
INP_POSIX_UID,
|
||||
INP_POSIX_GID,
|
||||
INP_CERT
|
||||
INP_CERT,
|
||||
INP_USERNAME,
|
||||
INP_GROUPNAME
|
||||
};
|
||||
|
||||
enum request_types {
|
||||
@@ -157,6 +162,8 @@ struct ipa_extdom_ctx {
|
||||
char *base_dn;
|
||||
size_t max_nss_buf_size;
|
||||
struct nss_ops_ctx *nss_ctx;
|
||||
Slapi_Counter *extdom_instance_counter;
|
||||
size_t extdom_max_instances;
|
||||
};
|
||||
|
||||
struct domain_info {
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <sched.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
@@ -36,10 +37,13 @@
|
||||
#include <stdio.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
static bool skip_tests = false;
|
||||
|
||||
#define MAX_BUF (1024*1024*1024)
|
||||
struct test_data {
|
||||
struct extdom_req *req;
|
||||
struct ipa_extdom_ctx *ctx;
|
||||
bool skip_test;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -138,40 +142,6 @@ fail:
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct {
|
||||
const char *o, *n;
|
||||
} path_table[] = {
|
||||
{ .o = "/etc/passwd", .n = "./test_data/passwd"},
|
||||
{ .o = "/etc/group", .n = "./test_data/group"},
|
||||
{ .o = NULL, .n = NULL}};
|
||||
|
||||
FILE *(*original_fopen)(const char*, const char*) = NULL;
|
||||
|
||||
FILE *fopen(const char *path, const char *mode) {
|
||||
const char *_path = NULL;
|
||||
|
||||
/* Do not handle before-main() cases */
|
||||
if (original_fopen == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
for(int i=0; path_table[i].o != NULL; i++) {
|
||||
if (strcmp(path, path_table[i].o) == 0) {
|
||||
_path = path_table[i].n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (*original_fopen)(_path ? _path : path, mode);
|
||||
}
|
||||
|
||||
/* Attempt to initialize original_fopen before main()
|
||||
* There is no explicit order when all initializers are called,
|
||||
* so we might still be late here compared to a code in a shared
|
||||
* library initializer, like libselinux */
|
||||
void redefined_fopen_ctor (void) __attribute__ ((constructor));
|
||||
void redefined_fopen_ctor(void) {
|
||||
original_fopen = dlsym(RTLD_NEXT, "fopen");
|
||||
}
|
||||
|
||||
void test_getpwnam_r_wrapper(void **state)
|
||||
{
|
||||
int ret;
|
||||
@@ -181,6 +151,9 @@ void test_getpwnam_r_wrapper(void **state)
|
||||
struct test_data *test_data;
|
||||
|
||||
test_data = (struct test_data *) *state;
|
||||
if (test_data->skip_test) {
|
||||
skip();
|
||||
}
|
||||
|
||||
ret = get_buffer(&buf_len, &buf);
|
||||
assert_int_equal(ret, 0);
|
||||
@@ -238,6 +211,9 @@ void test_getpwuid_r_wrapper(void **state)
|
||||
struct test_data *test_data;
|
||||
|
||||
test_data = (struct test_data *) *state;
|
||||
if (test_data->skip_test) {
|
||||
skip();
|
||||
}
|
||||
|
||||
ret = get_buffer(&buf_len, &buf);
|
||||
assert_int_equal(ret, 0);
|
||||
@@ -290,6 +266,9 @@ void test_getgrnam_r_wrapper(void **state)
|
||||
struct test_data *test_data;
|
||||
|
||||
test_data = (struct test_data *) *state;
|
||||
if (test_data->skip_test) {
|
||||
skip();
|
||||
}
|
||||
|
||||
ret = get_buffer(&buf_len, &buf);
|
||||
assert_int_equal(ret, 0);
|
||||
@@ -340,6 +319,9 @@ void test_getgrgid_r_wrapper(void **state)
|
||||
struct test_data *test_data;
|
||||
|
||||
test_data = (struct test_data *) *state;
|
||||
if (test_data->skip_test) {
|
||||
skip();
|
||||
}
|
||||
|
||||
ret = get_buffer(&buf_len, &buf);
|
||||
assert_int_equal(ret, 0);
|
||||
@@ -389,6 +371,9 @@ void test_get_user_grouplist(void **state)
|
||||
struct test_data *test_data;
|
||||
|
||||
test_data = (struct test_data *) *state;
|
||||
if (test_data->skip_test) {
|
||||
skip();
|
||||
}
|
||||
|
||||
/* This is a bit odd behaviour of getgrouplist() it does not check if the
|
||||
* user exists, only if memberships of the user can be found. */
|
||||
@@ -446,6 +431,11 @@ static int extdom_req_setup(void **state)
|
||||
assert_non_null(test_data->ctx->nss_ctx);
|
||||
|
||||
back_extdom_set_timeout(test_data->ctx->nss_ctx, 10000);
|
||||
|
||||
test_data->skip_test = skip_tests;
|
||||
if (chroot("test_data") != 0) {
|
||||
test_data->skip_test = true;
|
||||
}
|
||||
*state = test_data;
|
||||
|
||||
return 0;
|
||||
@@ -493,6 +483,34 @@ void test_set_err_msg(void **state)
|
||||
#define TEST_SID "S-1-2-3-4"
|
||||
#define TEST_DOMAIN_NAME "DOMAIN"
|
||||
|
||||
/* Always time out for test */
|
||||
static
|
||||
enum nss_status getgrgid_r_timeout(gid_t gid, struct group *result,
|
||||
char *buffer, size_t buflen, int *errnop) {
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
|
||||
void test_pack_ber_user_timeout(void **state)
|
||||
{
|
||||
int ret;
|
||||
struct berval *resp_val = NULL;
|
||||
struct test_data *test_data;
|
||||
enum nss_status (*oldgetgrgid_r)(gid_t gid, struct group *result,
|
||||
char *buffer, size_t buflen, int *errnop);
|
||||
|
||||
test_data = (struct test_data *) *state;
|
||||
|
||||
oldgetgrgid_r = test_data->ctx->nss_ctx->getgrgid_r;
|
||||
test_data->ctx->nss_ctx->getgrgid_r = getgrgid_r_timeout;
|
||||
|
||||
ret = pack_ber_user(test_data->ctx, RESP_USER_GROUPLIST,
|
||||
TEST_DOMAIN_NAME, "member001", 12345, 54321,
|
||||
"gecos", "homedir", "shell", NULL, &resp_val);
|
||||
test_data->ctx->nss_ctx->getgrgid_r = oldgetgrgid_r;
|
||||
assert_int_equal(ret, LDAP_TIMELIMIT_EXCEEDED);
|
||||
ber_bvfree(resp_val);
|
||||
}
|
||||
|
||||
char res_sid[] = {0x30, 0x0e, 0x0a, 0x01, 0x01, 0x04, 0x09, 0x53, 0x2d, 0x31, \
|
||||
0x2d, 0x32, 0x2d, 0x33, 0x2d, 0x34};
|
||||
char res_nam[] = {0x30, 0x13, 0x0a, 0x01, 0x02, 0x30, 0x0e, 0x04, 0x06, 0x44, \
|
||||
@@ -614,6 +632,7 @@ void test_decode(void **state)
|
||||
int main(int argc, const char *argv[])
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test(test_pack_ber_user_timeout),
|
||||
cmocka_unit_test(test_getpwnam_r_wrapper),
|
||||
cmocka_unit_test(test_getpwuid_r_wrapper),
|
||||
cmocka_unit_test(test_getgrnam_r_wrapper),
|
||||
@@ -626,6 +645,6 @@ int main(int argc, const char *argv[])
|
||||
cmocka_unit_test(test_decode),
|
||||
};
|
||||
|
||||
assert_non_null(original_fopen);
|
||||
skip_tests = (unshare(CLONE_NEWUSER) == -1);
|
||||
return cmocka_run_group_tests(tests, extdom_req_setup, extdom_req_teardown);
|
||||
}
|
||||
|
||||
@@ -114,6 +114,13 @@ int __nss_to_err(enum nss_status errcode)
|
||||
}
|
||||
}
|
||||
|
||||
static int get_timeout(struct ipa_extdom_ctx *ctx) {
|
||||
if (ctx == NULL || ctx->nss_ctx == NULL) {
|
||||
return DEFAULT_MAX_NSS_TIMEOUT;
|
||||
}
|
||||
return back_extdom_get_timeout(ctx->nss_ctx);
|
||||
}
|
||||
|
||||
int getpwnam_r_wrapper(struct ipa_extdom_ctx *ctx, const char *name,
|
||||
struct passwd *pwd, char **buf, size_t *buf_len)
|
||||
{
|
||||
@@ -271,7 +278,9 @@ int parse_request_data(struct berval *req_val, struct extdom_req **_req)
|
||||
* sid (1),
|
||||
* name (2),
|
||||
* posix uid (3),
|
||||
* posix gid (3)
|
||||
* posix gid (4),
|
||||
* username (5),
|
||||
* groupname (6)
|
||||
* },
|
||||
* requestType ENUMERATED {
|
||||
* simple (1),
|
||||
@@ -337,6 +346,8 @@ int parse_request_data(struct berval *req_val, struct extdom_req **_req)
|
||||
|
||||
switch (req->input_type) {
|
||||
case INP_NAME:
|
||||
case INP_USERNAME:
|
||||
case INP_GROUPNAME:
|
||||
tag = ber_scanf(ber, "{aa}}", &req->data.name.domain_name,
|
||||
&req->data.name.object_name);
|
||||
break;
|
||||
@@ -378,6 +389,8 @@ void free_req_data(struct extdom_req *req)
|
||||
|
||||
switch (req->input_type) {
|
||||
case INP_NAME:
|
||||
case INP_USERNAME:
|
||||
case INP_GROUPNAME:
|
||||
ber_memfree(req->data.name.domain_name);
|
||||
ber_memfree(req->data.name.object_name);
|
||||
break;
|
||||
@@ -407,6 +420,12 @@ int check_request(struct extdom_req *req, enum extdom_version version)
|
||||
}
|
||||
}
|
||||
|
||||
if (version == EXTDOM_V0 || version == EXTDOM_V1) {
|
||||
if (req->input_type == INP_USERNAME || req->input_type == INP_GROUPNAME) {
|
||||
return LDAP_PROTOCOL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -523,7 +542,7 @@ int pack_ber_user(struct ipa_extdom_ctx *ctx,
|
||||
if (strcasecmp(locat+1, domain_name) == 0 ) {
|
||||
locat[0] = '\0';
|
||||
} else {
|
||||
ret = LDAP_NO_SUCH_OBJECT;
|
||||
ret = LDAP_INVALID_SYNTAX;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
@@ -568,10 +587,12 @@ int pack_ber_user(struct ipa_extdom_ctx *ctx,
|
||||
ret = getgrgid_r_wrapper(ctx,
|
||||
groups[c], &grp, &buf, &buf_len);
|
||||
if (ret != 0) {
|
||||
if (ret == ENOMEM || ret == ERANGE) {
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
} else {
|
||||
if (ret == ENOENT) {
|
||||
ret = LDAP_NO_SUCH_OBJECT;
|
||||
} else if (ret == ETIMEDOUT) {
|
||||
ret = LDAP_TIMELIMIT_EXCEEDED;
|
||||
} else {
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
@@ -634,7 +655,7 @@ int pack_ber_group(enum response_types response_type,
|
||||
if (strcasecmp(locat+1, domain_name) == 0 ) {
|
||||
locat[0] = '\0';
|
||||
} else {
|
||||
ret = LDAP_NO_SUCH_OBJECT;
|
||||
ret = LDAP_INVALID_SYNTAX;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
@@ -831,11 +852,14 @@ static int handle_uid_request(struct ipa_extdom_ctx *ctx,
|
||||
}
|
||||
|
||||
if (request_type == REQ_SIMPLE) {
|
||||
ret = sss_nss_getsidbyid(uid, &sid_str, &id_type);
|
||||
ret = sss_nss_getsidbyid_timeout(uid, get_timeout(ctx),
|
||||
&sid_str, &id_type);
|
||||
if (ret != 0 || !(id_type == SSS_ID_TYPE_UID
|
||||
|| id_type == SSS_ID_TYPE_BOTH)) {
|
||||
if (ret == ENOENT) {
|
||||
ret = LDAP_NO_SUCH_OBJECT;
|
||||
} else if (ret == ETIMEDOUT || ret == ETIME) {
|
||||
ret = LDAP_TIMELIMIT_EXCEEDED;
|
||||
} else {
|
||||
set_err_msg(req, "Failed to lookup SID by UID");
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
@@ -847,21 +871,26 @@ static int handle_uid_request(struct ipa_extdom_ctx *ctx,
|
||||
} else {
|
||||
ret = getpwuid_r_wrapper(ctx, uid, &pwd, &buf, &buf_len);
|
||||
if (ret != 0) {
|
||||
if (ret == ENOMEM || ret == ERANGE) {
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
} else {
|
||||
if (ret == ENOENT) {
|
||||
ret = LDAP_NO_SUCH_OBJECT;
|
||||
} else if (ret == ETIMEDOUT) {
|
||||
ret = LDAP_TIMELIMIT_EXCEEDED;
|
||||
} else {
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (request_type == REQ_FULL_WITH_GROUPS) {
|
||||
ret = sss_nss_getorigbyname(pwd.pw_name, &kv_list, &id_type);
|
||||
ret = sss_nss_getorigbyname_timeout(pwd.pw_name, get_timeout(ctx),
|
||||
&kv_list, &id_type);
|
||||
if (ret != 0 || !(id_type == SSS_ID_TYPE_UID
|
||||
|| id_type == SSS_ID_TYPE_BOTH)) {
|
||||
set_err_msg(req, "Failed to read original data");
|
||||
if (ret == ENOENT) {
|
||||
ret = LDAP_NO_SUCH_OBJECT;
|
||||
} else if (ret == ETIMEDOUT || ret == ETIME) {
|
||||
ret = LDAP_TIMELIMIT_EXCEEDED;
|
||||
} else {
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
}
|
||||
@@ -903,10 +932,13 @@ static int handle_gid_request(struct ipa_extdom_ctx *ctx,
|
||||
}
|
||||
|
||||
if (request_type == REQ_SIMPLE) {
|
||||
ret = sss_nss_getsidbyid(gid, &sid_str, &id_type);
|
||||
ret = sss_nss_getsidbyid_timeout(gid, get_timeout(ctx),
|
||||
&sid_str, &id_type);
|
||||
if (ret != 0 || id_type != SSS_ID_TYPE_GID) {
|
||||
if (ret == ENOENT) {
|
||||
ret = LDAP_NO_SUCH_OBJECT;
|
||||
} else if (ret == ETIMEDOUT || ret == ETIME) {
|
||||
ret = LDAP_TIMELIMIT_EXCEEDED;
|
||||
} else {
|
||||
set_err_msg(req, "Failed to lookup SID by GID");
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
@@ -918,21 +950,26 @@ static int handle_gid_request(struct ipa_extdom_ctx *ctx,
|
||||
} else {
|
||||
ret = getgrgid_r_wrapper(ctx, gid, &grp, &buf, &buf_len);
|
||||
if (ret != 0) {
|
||||
if (ret == ENOMEM || ret == ERANGE) {
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
} else {
|
||||
if (ret == ENOENT) {
|
||||
ret = LDAP_NO_SUCH_OBJECT;
|
||||
} else if (ret == ETIMEDOUT) {
|
||||
ret = LDAP_TIMELIMIT_EXCEEDED;
|
||||
} else {
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (request_type == REQ_FULL_WITH_GROUPS) {
|
||||
ret = sss_nss_getorigbyname(grp.gr_name, &kv_list, &id_type);
|
||||
ret = sss_nss_getorigbyname_timeout(grp.gr_name, get_timeout(ctx),
|
||||
&kv_list, &id_type);
|
||||
if (ret != 0 || !(id_type == SSS_ID_TYPE_GID
|
||||
|| id_type == SSS_ID_TYPE_BOTH)) {
|
||||
set_err_msg(req, "Failed to read original data");
|
||||
if (ret == ENOENT) {
|
||||
ret = LDAP_NO_SUCH_OBJECT;
|
||||
} else if (ret == ETIMEDOUT || ret == ETIME) {
|
||||
ret = LDAP_TIMELIMIT_EXCEEDED;
|
||||
} else {
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
}
|
||||
@@ -972,10 +1009,13 @@ static int handle_cert_request(struct ipa_extdom_ctx *ctx,
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = sss_nss_getlistbycert(input, &fq_names, &id_types);
|
||||
ret = sss_nss_getlistbycert_timeout(input, get_timeout(ctx),
|
||||
&fq_names, &id_types);
|
||||
if (ret != 0) {
|
||||
if (ret == ENOENT) {
|
||||
ret = LDAP_NO_SUCH_OBJECT;
|
||||
} else if (ret == ETIMEDOUT || ret == ETIME) {
|
||||
ret = LDAP_TIMELIMIT_EXCEEDED;
|
||||
} else {
|
||||
set_err_msg(req, "Failed to lookup name by certificate");
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
@@ -1016,10 +1056,13 @@ static int handle_sid_request(struct ipa_extdom_ctx *ctx,
|
||||
enum sss_id_type id_type;
|
||||
struct sss_nss_kv *kv_list = NULL;
|
||||
|
||||
ret = sss_nss_getnamebysid(input, &fq_name, &id_type);
|
||||
ret = sss_nss_getnamebysid_timeout(input, get_timeout(ctx),
|
||||
&fq_name, &id_type);
|
||||
if (ret != 0) {
|
||||
if (ret == ENOENT) {
|
||||
ret = LDAP_NO_SUCH_OBJECT;
|
||||
} else if (ret == ETIMEDOUT || ret == ETIME) {
|
||||
ret = LDAP_TIMELIMIT_EXCEEDED;
|
||||
} else {
|
||||
set_err_msg(req, "Failed to lookup name by SID");
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
@@ -1057,21 +1100,26 @@ static int handle_sid_request(struct ipa_extdom_ctx *ctx,
|
||||
case SSS_ID_TYPE_BOTH:
|
||||
ret = getpwnam_r_wrapper(ctx, fq_name, &pwd, &buf, &buf_len);
|
||||
if (ret != 0) {
|
||||
if (ret == ENOMEM || ret == ERANGE) {
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
} else {
|
||||
if (ret == ENOENT) {
|
||||
ret = LDAP_NO_SUCH_OBJECT;
|
||||
} else if (ret == ETIMEDOUT) {
|
||||
ret = LDAP_TIMELIMIT_EXCEEDED;
|
||||
} else {
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (request_type == REQ_FULL_WITH_GROUPS) {
|
||||
ret = sss_nss_getorigbyname(pwd.pw_name, &kv_list, &id_type);
|
||||
ret = sss_nss_getorigbyname_timeout(pwd.pw_name, get_timeout(ctx),
|
||||
&kv_list, &id_type);
|
||||
if (ret != 0 || !(id_type == SSS_ID_TYPE_UID
|
||||
|| id_type == SSS_ID_TYPE_BOTH)) {
|
||||
set_err_msg(req, "Failed to read original data");
|
||||
if (ret == ENOENT) {
|
||||
ret = LDAP_NO_SUCH_OBJECT;
|
||||
} else if (ret == ETIMEDOUT || ret == ETIME) {
|
||||
ret = LDAP_TIMELIMIT_EXCEEDED;
|
||||
} else {
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
}
|
||||
@@ -1089,21 +1137,26 @@ static int handle_sid_request(struct ipa_extdom_ctx *ctx,
|
||||
case SSS_ID_TYPE_GID:
|
||||
ret = getgrnam_r_wrapper(ctx, fq_name, &grp, &buf, &buf_len);
|
||||
if (ret != 0) {
|
||||
if (ret == ENOMEM || ret == ERANGE) {
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
} else {
|
||||
if (ret == ENOENT) {
|
||||
ret = LDAP_NO_SUCH_OBJECT;
|
||||
} else if (ret == ETIMEDOUT) {
|
||||
ret = LDAP_TIMELIMIT_EXCEEDED;
|
||||
} else {
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (request_type == REQ_FULL_WITH_GROUPS) {
|
||||
ret = sss_nss_getorigbyname(grp.gr_name, &kv_list, &id_type);
|
||||
ret = sss_nss_getorigbyname_timeout(grp.gr_name, get_timeout(ctx),
|
||||
&kv_list, &id_type);
|
||||
if (ret != 0 || !(id_type == SSS_ID_TYPE_GID
|
||||
|| id_type == SSS_ID_TYPE_BOTH)) {
|
||||
set_err_msg(req, "Failed to read original data");
|
||||
if (ret == ENOENT) {
|
||||
ret = LDAP_NO_SUCH_OBJECT;
|
||||
} else if (ret == ETIMEDOUT || ret == ETIME) {
|
||||
ret = LDAP_TIMELIMIT_EXCEEDED;
|
||||
} else {
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
}
|
||||
@@ -1131,17 +1184,48 @@ done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int handle_name_request(struct ipa_extdom_ctx *ctx,
|
||||
struct extdom_req *req,
|
||||
enum request_types request_type,
|
||||
const char *name, const char *domain_name,
|
||||
struct berval **berval)
|
||||
|
||||
static int handle_simple_request(struct ipa_extdom_ctx *ctx,
|
||||
struct extdom_req *req,
|
||||
const char *fq_name,
|
||||
struct berval **berval)
|
||||
{
|
||||
int ret;
|
||||
char *sid_str = NULL;
|
||||
enum sss_id_type id_type;
|
||||
|
||||
ret = sss_nss_getsidbyname_timeout(fq_name, get_timeout(ctx),
|
||||
&sid_str, &id_type);
|
||||
switch(ret) {
|
||||
case 0:
|
||||
ret = pack_ber_sid(sid_str, berval);
|
||||
break;
|
||||
case ENOENT:
|
||||
ret = LDAP_NO_SUCH_OBJECT;
|
||||
break;
|
||||
case ETIMEDOUT:
|
||||
case ETIME:
|
||||
ret = LDAP_TIMELIMIT_EXCEEDED;
|
||||
break;
|
||||
default:
|
||||
set_err_msg(req, "Failed to lookup SID by name");
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
free(sid_str);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int handle_username_request(struct ipa_extdom_ctx *ctx,
|
||||
struct extdom_req *req,
|
||||
enum request_types request_type,
|
||||
const char *name, const char *domain_name,
|
||||
struct berval **berval)
|
||||
{
|
||||
int ret;
|
||||
char *fq_name = NULL;
|
||||
struct passwd pwd;
|
||||
struct group grp;
|
||||
char *sid_str = NULL;
|
||||
enum sss_id_type id_type;
|
||||
size_t buf_len;
|
||||
char *buf = NULL;
|
||||
@@ -1163,93 +1247,159 @@ static int handle_name_request(struct ipa_extdom_ctx *ctx,
|
||||
}
|
||||
|
||||
if (request_type == REQ_SIMPLE) {
|
||||
ret = sss_nss_getsidbyname(fq_name, &sid_str, &id_type);
|
||||
if (ret != 0) {
|
||||
if (ret == ENOENT) {
|
||||
ret = LDAP_NO_SUCH_OBJECT;
|
||||
} else {
|
||||
set_err_msg(req, "Failed to lookup SID by name");
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
/* REQ_SIMPLE */
|
||||
ret = handle_simple_request(ctx, req, fq_name, berval);
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = pack_ber_sid(sid_str, berval);
|
||||
} else {
|
||||
ret = get_buffer(&buf_len, &buf);
|
||||
if (ret != LDAP_SUCCESS) {
|
||||
goto done;
|
||||
}
|
||||
/* REQ_FULL || REQ_FULL_WITH_GROUPS */
|
||||
ret = get_buffer(&buf_len, &buf);
|
||||
if (ret != LDAP_SUCCESS) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = getpwnam_r_wrapper(ctx, fq_name, &pwd, &buf, &buf_len);
|
||||
if (ret == 0) {
|
||||
if (request_type == REQ_FULL_WITH_GROUPS) {
|
||||
ret = sss_nss_getorigbyname(pwd.pw_name, &kv_list, &id_type);
|
||||
if (ret != 0 || !(id_type == SSS_ID_TYPE_UID
|
||||
|| id_type == SSS_ID_TYPE_BOTH)) {
|
||||
set_err_msg(req, "Failed to read original data");
|
||||
if (ret == ENOENT) {
|
||||
ret = LDAP_NO_SUCH_OBJECT;
|
||||
} else {
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
ret = pack_ber_user(ctx,
|
||||
(request_type == REQ_FULL ? RESP_USER
|
||||
: RESP_USER_GROUPLIST),
|
||||
domain_name, pwd.pw_name, pwd.pw_uid,
|
||||
pwd.pw_gid, pwd.pw_gecos, pwd.pw_dir,
|
||||
pwd.pw_shell, kv_list, berval);
|
||||
} else if (ret == ENOMEM || ret == ERANGE) {
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
goto done;
|
||||
} else { /* no user entry found */
|
||||
/* according to the getpwnam() man page there are a couple of
|
||||
* error codes which can indicate that the user was not found. To
|
||||
* be on the safe side we fail back to the group lookup on all
|
||||
* errors. */
|
||||
ret = getgrnam_r_wrapper(ctx, fq_name, &grp, &buf, &buf_len);
|
||||
if (ret != 0) {
|
||||
if (ret == ENOMEM || ret == ERANGE) {
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
} else {
|
||||
ret = getpwnam_r_wrapper(ctx, fq_name, &pwd, &buf, &buf_len);
|
||||
switch(ret) {
|
||||
case 0:
|
||||
if (request_type == REQ_FULL_WITH_GROUPS) {
|
||||
ret = sss_nss_getorigbyname_timeout(pwd.pw_name,
|
||||
get_timeout(ctx),
|
||||
&kv_list, &id_type);
|
||||
if (ret != 0 || !(id_type == SSS_ID_TYPE_UID
|
||||
|| id_type == SSS_ID_TYPE_BOTH)) {
|
||||
set_err_msg(req, "Failed to read original data");
|
||||
if (ret == ENOENT) {
|
||||
ret = LDAP_NO_SUCH_OBJECT;
|
||||
} else if (ret == ETIMEDOUT || ret == ETIME) {
|
||||
ret = LDAP_TIMELIMIT_EXCEEDED;
|
||||
} else {
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (request_type == REQ_FULL_WITH_GROUPS) {
|
||||
ret = sss_nss_getorigbyname(grp.gr_name, &kv_list, &id_type);
|
||||
if (ret != 0 || !(id_type == SSS_ID_TYPE_GID
|
||||
|| id_type == SSS_ID_TYPE_BOTH)) {
|
||||
if (ret == ENOENT) {
|
||||
ret = LDAP_NO_SUCH_OBJECT;
|
||||
} else {
|
||||
set_err_msg(req, "Failed to read original data");
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
ret = pack_ber_group((request_type == REQ_FULL ? RESP_GROUP
|
||||
: RESP_GROUP_MEMBERS),
|
||||
domain_name, grp.gr_name, grp.gr_gid,
|
||||
grp.gr_mem, kv_list, berval);
|
||||
}
|
||||
ret = pack_ber_user(ctx,
|
||||
(request_type == REQ_FULL ? RESP_USER
|
||||
: RESP_USER_GROUPLIST),
|
||||
domain_name, pwd.pw_name, pwd.pw_uid,
|
||||
pwd.pw_gid, pwd.pw_gecos, pwd.pw_dir,
|
||||
pwd.pw_shell, kv_list, berval);
|
||||
break;
|
||||
case ENOMEM:
|
||||
case ERANGE:
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
break;
|
||||
case ETIMEDOUT:
|
||||
ret = LDAP_TIMELIMIT_EXCEEDED;
|
||||
break;
|
||||
default:
|
||||
ret = LDAP_NO_SUCH_OBJECT;
|
||||
break;
|
||||
}
|
||||
|
||||
done:
|
||||
sss_nss_free_kv(kv_list);
|
||||
free(fq_name);
|
||||
free(sid_str);
|
||||
free(buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int handle_groupname_request(struct ipa_extdom_ctx *ctx,
|
||||
struct extdom_req *req,
|
||||
enum request_types request_type,
|
||||
const char *name, const char *domain_name,
|
||||
struct berval **berval)
|
||||
{
|
||||
int ret;
|
||||
char *fq_name = NULL;
|
||||
struct group grp;
|
||||
enum sss_id_type id_type;
|
||||
size_t buf_len;
|
||||
char *buf = NULL;
|
||||
struct sss_nss_kv *kv_list = NULL;
|
||||
|
||||
/* with groups we can be sure that name doesn't contain the domain_name */
|
||||
ret = asprintf(&fq_name, "%s%c%s", name, SSSD_DOMAIN_SEPARATOR,
|
||||
domain_name);
|
||||
if (ret == -1) {
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
set_err_msg(req, "Failed to create fully qualified name");
|
||||
fq_name = NULL; /* content is undefined according to
|
||||
asprintf(3) */
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (request_type == REQ_SIMPLE) {
|
||||
/* REQ_SIMPLE */
|
||||
ret = handle_simple_request(ctx, req, fq_name, berval);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* REQ_FULL || REQ_FULL_WITH_GROUPS */
|
||||
ret = get_buffer(&buf_len, &buf);
|
||||
if (ret != LDAP_SUCCESS) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = getgrnam_r_wrapper(ctx, fq_name, &grp, &buf, &buf_len);
|
||||
if (ret != 0) {
|
||||
if (ret == ENOMEM || ret == ERANGE) {
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
} else {
|
||||
ret = LDAP_NO_SUCH_OBJECT;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (request_type == REQ_FULL_WITH_GROUPS) {
|
||||
ret = sss_nss_getorigbyname_timeout(grp.gr_name, get_timeout(ctx),
|
||||
&kv_list, &id_type);
|
||||
if (ret != 0 || !(id_type == SSS_ID_TYPE_GID
|
||||
|| id_type == SSS_ID_TYPE_BOTH)) {
|
||||
if (ret == ENOENT) {
|
||||
ret = LDAP_NO_SUCH_OBJECT;
|
||||
} else {
|
||||
set_err_msg(req, "Failed to read original data");
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
ret = pack_ber_group((request_type == REQ_FULL ? RESP_GROUP
|
||||
: RESP_GROUP_MEMBERS),
|
||||
domain_name, grp.gr_name, grp.gr_gid,
|
||||
grp.gr_mem, kv_list, berval);
|
||||
|
||||
done:
|
||||
sss_nss_free_kv(kv_list);
|
||||
free(fq_name);
|
||||
free(buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int handle_name_request(struct ipa_extdom_ctx *ctx,
|
||||
struct extdom_req *req,
|
||||
enum request_types request_type,
|
||||
const char *name, const char *domain_name,
|
||||
struct berval **berval)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
||||
ret = handle_username_request(ctx, req, request_type,
|
||||
name, domain_name, berval);
|
||||
if (ret == LDAP_NO_SUCH_OBJECT) {
|
||||
ret = handle_groupname_request(ctx, req, request_type,
|
||||
name, domain_name, berval);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int handle_request(struct ipa_extdom_ctx *ctx, struct extdom_req *req,
|
||||
struct berval **berval)
|
||||
{
|
||||
@@ -1281,6 +1431,18 @@ int handle_request(struct ipa_extdom_ctx *ctx, struct extdom_req *req,
|
||||
req->data.name.object_name,
|
||||
req->data.name.domain_name, berval);
|
||||
|
||||
break;
|
||||
case INP_GROUPNAME:
|
||||
ret = handle_groupname_request(ctx, req, req->request_type,
|
||||
req->data.name.object_name,
|
||||
req->data.name.domain_name, berval);
|
||||
|
||||
break;
|
||||
case INP_USERNAME:
|
||||
ret = handle_username_request(ctx, req, req->request_type,
|
||||
req->data.name.object_name,
|
||||
req->data.name.domain_name, berval);
|
||||
|
||||
break;
|
||||
default:
|
||||
set_err_msg(req, "Unknown input type");
|
||||
|
||||
@@ -42,7 +42,6 @@
|
||||
#include "util.h"
|
||||
|
||||
#define DEFAULT_MAX_NSS_BUFFER (128*1024*1024)
|
||||
#define DEFAULT_MAX_NSS_TIMEOUT (10*1000)
|
||||
|
||||
Slapi_PluginDesc ipa_extdom_plugin_desc = {
|
||||
IPA_EXTDOM_FEATURE_DESC,
|
||||
@@ -54,6 +53,7 @@ Slapi_PluginDesc ipa_extdom_plugin_desc = {
|
||||
static char *ipa_extdom_oid_list[] = {
|
||||
EXOP_EXTDOM_OID,
|
||||
EXOP_EXTDOM_V1_OID,
|
||||
EXOP_EXTDOM_V2_OID,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -62,8 +62,112 @@ static char *ipa_extdom_name_list[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
#define NSSLAPD_THREADNUMBER "nsslapd-threadnumber"
|
||||
static int ipa_get_threadnumber(Slapi_ComponentId *plugin_id, size_t *threadnumber)
|
||||
{
|
||||
Slapi_PBlock *search_pb = NULL;
|
||||
int search_result;
|
||||
Slapi_Entry **search_entries = NULL;
|
||||
int ret;
|
||||
char *attrs[] = { NSSLAPD_THREADNUMBER, NULL };
|
||||
|
||||
search_pb = slapi_pblock_new();
|
||||
if (search_pb == NULL) {
|
||||
LOG_FATAL("Failed to create new pblock.\n");
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
slapi_search_internal_set_pb(search_pb, "cn=config",
|
||||
LDAP_SCOPE_BASE, "objectclass=*",
|
||||
attrs, 0, NULL, NULL, plugin_id, 0);
|
||||
|
||||
ret = slapi_search_internal_pb(search_pb);
|
||||
if (ret != 0) {
|
||||
LOG_FATAL("Starting internal search failed.\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT,
|
||||
&search_result);
|
||||
if (ret != 0 || search_result != LDAP_SUCCESS) {
|
||||
LOG_FATAL("Internal search failed [%d][%d].\n", ret, search_result);
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,
|
||||
&search_entries);
|
||||
if (ret != 0) {
|
||||
LOG_FATAL("Failed to read searched entries.\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (search_entries == NULL || search_entries[0] == NULL) {
|
||||
LOG("No existing entries.\n");
|
||||
ret = LDAP_NO_SUCH_OBJECT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (search_entries[1] != NULL) {
|
||||
LOG("Too many results found.\n");
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
*threadnumber = slapi_entry_attr_get_uint(search_entries[0],
|
||||
NSSLAPD_THREADNUMBER);
|
||||
|
||||
if (*threadnumber <= 0) {
|
||||
LOG_FATAL("No thread number found.\n");
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
LOG("Found thread number [%zu].\n", *threadnumber);
|
||||
ret = 0;
|
||||
|
||||
done:
|
||||
slapi_free_search_results_internal(search_pb);
|
||||
slapi_pblock_destroy(search_pb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ipa_extdom_start(Slapi_PBlock *pb)
|
||||
{
|
||||
int ret;
|
||||
struct ipa_extdom_ctx *ctx;
|
||||
size_t threadnumber;
|
||||
|
||||
ret = slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &ctx);
|
||||
if (ret != 0) {
|
||||
return LDAP_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
ret = ipa_get_threadnumber(ctx->plugin_id, &threadnumber);
|
||||
if (ret != 0) {
|
||||
LOG("Unable to get thread number [%d]!\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ctx->extdom_max_instances >= threadnumber) {
|
||||
LOG("Option ipaExtdomMaxInstances [%zu] is larger or equal the number "
|
||||
"of worker threads [%zu], using defaults.\n",
|
||||
ctx->extdom_max_instances, threadnumber);
|
||||
ctx->extdom_max_instances = 0;
|
||||
}
|
||||
|
||||
if (ctx->extdom_max_instances == 0) {
|
||||
ctx->extdom_max_instances = (size_t)(threadnumber * 0.8);
|
||||
if (ctx->extdom_max_instances == 0) {
|
||||
ctx->extdom_max_instances = 1;
|
||||
}
|
||||
}
|
||||
|
||||
LOG("Using maximal [%zu] extdom instances for [%zu] threads.\n",
|
||||
ctx->extdom_max_instances, threadnumber);
|
||||
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -78,6 +182,7 @@ static int ipa_extdom_extop(Slapi_PBlock *pb)
|
||||
struct extdom_req *req = NULL;
|
||||
struct ipa_extdom_ctx *ctx;
|
||||
enum extdom_version version;
|
||||
bool counter_set = false;
|
||||
|
||||
ret = slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_OID, &oid);
|
||||
if (ret != 0) {
|
||||
@@ -91,6 +196,8 @@ static int ipa_extdom_extop(Slapi_PBlock *pb)
|
||||
version = EXTDOM_V0;
|
||||
} else if (strcasecmp(oid, EXOP_EXTDOM_V1_OID) == 0) {
|
||||
version = EXTDOM_V1;
|
||||
} else if (strcasecmp(oid, EXOP_EXTDOM_V2_OID) == 0) {
|
||||
version = EXTDOM_V2;
|
||||
} else {
|
||||
return SLAPI_PLUGIN_EXTENDED_NOT_HANDLED;
|
||||
}
|
||||
@@ -109,6 +216,16 @@ static int ipa_extdom_extop(Slapi_PBlock *pb)
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (slapi_counter_get_value(ctx->extdom_instance_counter)
|
||||
> ctx->extdom_max_instances) {
|
||||
rc = LDAP_BUSY;
|
||||
err_msg = "Too many extdom instances running.\n";
|
||||
goto done;
|
||||
}
|
||||
|
||||
slapi_counter_increment(ctx->extdom_instance_counter);
|
||||
counter_set = true;
|
||||
|
||||
ret = parse_request_data(req_val, &req);
|
||||
if (ret != LDAP_SUCCESS) {
|
||||
rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
@@ -127,6 +244,8 @@ static int ipa_extdom_extop(Slapi_PBlock *pb)
|
||||
if (ret != LDAP_SUCCESS) {
|
||||
if (ret == LDAP_NO_SUCH_OBJECT) {
|
||||
rc = LDAP_NO_SUCH_OBJECT;
|
||||
} else if (ret == LDAP_TIMELIMIT_EXCEEDED) {
|
||||
rc = LDAP_TIMELIMIT_EXCEEDED;
|
||||
} else {
|
||||
rc = LDAP_OPERATIONS_ERROR;
|
||||
err_msg = "Failed to handle the request.\n";
|
||||
@@ -151,6 +270,14 @@ static int ipa_extdom_extop(Slapi_PBlock *pb)
|
||||
rc = LDAP_SUCCESS;
|
||||
|
||||
done:
|
||||
if (counter_set) {
|
||||
if (slapi_counter_get_value(ctx->extdom_instance_counter) == 0) {
|
||||
LOG("Instance counter already 0, this is unexpected.\n");
|
||||
} else {
|
||||
slapi_counter_decrement(ctx->extdom_instance_counter);
|
||||
}
|
||||
}
|
||||
|
||||
if ((req != NULL) && (req->err_msg != NULL)) {
|
||||
err_msg = req->err_msg;
|
||||
}
|
||||
@@ -219,6 +346,16 @@ static int ipa_extdom_init_ctx(Slapi_PBlock *pb, struct ipa_extdom_ctx **_ctx)
|
||||
back_extdom_set_timeout(ctx->nss_ctx, timeout);
|
||||
LOG("Maximal nss timeout (in ms) set to [%u]!\n", timeout);
|
||||
|
||||
ctx->extdom_max_instances = slapi_entry_attr_get_uint(e, "ipaExtdomMaxInstances");
|
||||
LOG("Maximal instances from config [%zu]!\n", ctx->extdom_max_instances);
|
||||
|
||||
ctx->extdom_instance_counter = slapi_counter_new();
|
||||
if (ctx->extdom_instance_counter == NULL) {
|
||||
LOG("Unable to initialize instance counter!\n");
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
done:
|
||||
|
||||
Reference in New Issue
Block a user