Imported Debian patch 4.8.10-2

This commit is contained in:
Timo Aaltonen
2020-11-23 20:48:56 +02:00
committed by Mario Fetka
parent 8bc559c5a1
commit 358acdd85f
917 changed files with 1185414 additions and 1069733 deletions

View File

@@ -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 \

View File

@@ -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@

View File

@@ -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,

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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 {

View File

@@ -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);
}

View File

@@ -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");

View File

@@ -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: