Hello,
this patch resolves [1]. This adds new behaviour of negative caching of
locals, so it needs new tests. I will send patch with tests soon, but
not today.
It is applicable after
RESPONDERS: Negcache in resp_ctx [2].
For clarity, there is branch with all negative cache's patches [3].
Links:
[1] https://fedorahosted.org/sssd/ticket/2928
[2]
https://www.mail-archive.com/[email protected]/msg26580.html
[3] https://github.com/celestian/sssd/commits/ncache_v2
Regards
--
Petr^4 Čech
>From 2368e9f56e1bba55d38d6dfb06b1dc6057e37a90 Mon Sep 17 00:00:00 2001
From: Petr Cech <[email protected]>
Date: Thu, 5 May 2016 11:16:14 -0400
Subject: [PATCH] RESPONDERS: Negative caching of local users
This patch adds new option 'neg_cache_locals_timeout' into section
of NSS responder. It allows negative caching of local groups and
users. Default value is 0 which means no caching.
Resolves:
https://fedorahosted.org/sssd/ticket/2928
---
Makefile.am | 4 ++
src/confdb/confdb.h | 1 +
src/config/SSSDConfig/__init__.py.in | 1 +
src/config/etc/sssd.api.conf | 1 +
src/man/sssd.conf.5.xml | 13 ++++
src/responder/common/negcache.c | 39 ++++++++----
src/responder/common/negcache.h | 2 +-
src/responder/common/negcache_files.c | 93 +++++++++++++++++++++++++++++
src/responder/common/negcache_files.h | 32 ++++++++++
src/responder/common/responder_common.c | 22 ++++++-
src/tests/cmocka/common_mock_resp.c | 2 +-
src/tests/cmocka/test_negcache.c | 4 +-
src/tests/cmocka/test_responder_cache_req.c | 4 +-
src/tests/cwrap/Makefile.am | 1 +
14 files changed, 200 insertions(+), 19 deletions(-)
create mode 100644 src/responder/common/negcache_files.c
create mode 100644 src/responder/common/negcache_files.h
diff --git a/Makefile.am b/Makefile.am
index dc477249be0dab29cef490cf4fb558b5e8b16d3c..2079fe5639dac3d0a4600831dc5d1ac0d8814cdc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -449,6 +449,7 @@ AM_CPPFLAGS = \
EXTRA_DIST =
SSSD_RESPONDER_OBJ = \
+ src/responder/common/negcache_files.c \
src/responder/common/negcache.c \
src/responder/common/responder_cmd.c \
src/responder/common/responder_common.c \
@@ -574,6 +575,7 @@ dist_noinst_HEADERS = \
src/responder/nss/nsssrv_services.h \
src/responder/nss/nsssrv_mmap_cache.h \
src/responder/pac/pacsrv.h \
+ src/responder/common/negcache_files.c \
src/responder/common/negcache.h \
src/responder/sudo/sudosrv_private.h \
src/responder/autofs/autofs_private.h \
@@ -1790,6 +1792,7 @@ sss_idmap_tests_LDADD = \
responder_socket_access_tests_SOURCES = \
src/tests/responder_socket_access-tests.c \
+ src/responder/common/negcache_files.c \
src/responder/common/negcache.c \
src/responder/common/responder_common.c \
src/responder/common/responder_packet.c \
@@ -1887,6 +1890,7 @@ TEST_MOCK_RESP_OBJ = \
src/tests/cmocka/common_mock_resp_dp.c \
src/responder/common/responder_packet.c \
src/responder/common/responder_cmd.c \
+ src/responder/common/negcache_files.c \
src/responder/common/negcache.c \
src/responder/common/responder_common.c \
src/responder/common/responder_cache_req.c
diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
index c478ef0978b2d1ce302a86a3d536f0447c27fefa..e22fce06981411da04f4c40438948cf0418b4130 100644
--- a/src/confdb/confdb.h
+++ b/src/confdb/confdb.h
@@ -84,6 +84,7 @@
#define CONFDB_RESPONDER_GET_DOMAINS_TIMEOUT "get_domains_timeout"
#define CONFDB_RESPONDER_CLI_IDLE_TIMEOUT "client_idle_timeout"
#define CONFDB_RESPONDER_CLI_IDLE_DEFAULT_TIMEOUT 60
+#define CONFDB_RESPONDER_NEG_CACHE_LOCALS_TIMEOUT "neg_cache_locals_timeout"
/* NSS */
#define CONFDB_NSS_CONF_ENTRY "config/nss"
diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in
index 1a0893cbc180394d994b9d97fc0fa863da656549..9b5736a5719a6ac843bd3428236b67741c5caddc 100644
--- a/src/config/SSSDConfig/__init__.py.in
+++ b/src/config/SSSDConfig/__init__.py.in
@@ -67,6 +67,7 @@ option_strings = {
'enum_cache_timeout' : _('Enumeration cache timeout length (seconds)'),
'entry_cache_no_wait_timeout' : _('Entry cache background update timeout length (seconds)'),
'entry_negative_timeout' : _('Negative cache timeout length (seconds)'),
+ 'neg_cache_locals_timeout' : _('Files negative cache timeout length (seconds)'),
'filter_users' : _('Users that SSSD should explicitly ignore'),
'filter_groups' : _('Groups that SSSD should explicitly ignore'),
'filter_users_in_groups' : _('Should filtered users appear in groups'),
diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf
index a15f2bd05c3046f8d76b13b3d8f28f9001d8fded..5af34ffff27ac46340d796028080a6433baf2004 100644
--- a/src/config/etc/sssd.api.conf
+++ b/src/config/etc/sssd.api.conf
@@ -33,6 +33,7 @@ certificate_verification = str, None, false
enum_cache_timeout = int, None, false
entry_cache_nowait_percentage = int, None, false
entry_negative_timeout = int, None, false
+neg_cache_locals_timeout = int, None, false
filter_users = list, str, false
filter_groups = list, str, false
filter_users_in_groups = bool, None, false
diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
index 09db9cd32673c911991b335e986692e3d8d856d0..5534c8f6ce60dd23131f529b9af05ab7b2b2cb7b 100644
--- a/src/man/sssd.conf.5.xml
+++ b/src/man/sssd.conf.5.xml
@@ -577,6 +577,19 @@
</listitem>
</varlistentry>
<varlistentry>
+ <term>neg_cache_locals_timeout (integer)</term>
+ <listitem>
+ <para>
+ Specifies for how many seconds nss_sss should
+ negatively cache local users and groups. That means
+ the period during which the back end is not asking.
+ </para>
+ <para>
+ Default: 0
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
<term>filter_users, filter_groups (string)</term>
<listitem>
<para>
diff --git a/src/responder/common/negcache.c b/src/responder/common/negcache.c
index 1488c12a89e35b06bf00b60a2034ca7f9b64580b..9d40e5ff6513a0a080a7198474c845147c7579c8 100644
--- a/src/responder/common/negcache.c
+++ b/src/responder/common/negcache.c
@@ -21,6 +21,7 @@
#include "util/util.h"
#include "confdb/confdb.h"
+#include "responder/common/negcache_files.h"
#include "responder/common/responder.h"
#include "responder/common/negcache.h"
#include <fcntl.h>
@@ -40,6 +41,7 @@
struct sss_nc_ctx {
struct tdb_context *tdb;
uint32_t timeout;
+ uint32_t locals_timeout;
};
typedef int (*ncache_set_byname_fn_t)(struct sss_nc_ctx *, bool,
@@ -60,7 +62,7 @@ static int string_to_tdb_data(char *str, TDB_DATA *ret)
}
int sss_ncache_init(TALLOC_CTX *memctx, uint32_t timeout,
- struct sss_nc_ctx **_ctx)
+ uint32_t locals_timeout, struct sss_nc_ctx **_ctx)
{
struct sss_nc_ctx *ctx;
@@ -73,6 +75,7 @@ int sss_ncache_init(TALLOC_CTX *memctx, uint32_t timeout,
if (!ctx->tdb) return errno;
ctx->timeout = timeout;
+ ctx->locals_timeout = locals_timeout;
*_ctx = ctx;
return EOK;
@@ -139,8 +142,8 @@ done:
return ret;
}
-static int sss_ncache_set_str(struct sss_nc_ctx *ctx,
- char *str, bool permanent)
+static int sss_ncache_set_str(struct sss_nc_ctx *ctx, char *str,
+ bool permanent, bool locals)
{
TDB_DATA key;
TDB_DATA data;
@@ -154,7 +157,11 @@ static int sss_ncache_set_str(struct sss_nc_ctx *ctx,
if (permanent) {
timest = talloc_strdup(ctx, "0");
} else {
- timell = (unsigned long long int)time(NULL) + ctx->timeout;
+ if (locals == true && ctx->locals_timeout > 0) {
+ timell = (unsigned long long int)time(NULL) + ctx->locals_timeout;
+ } else {
+ timell = (unsigned long long int)time(NULL) + ctx->timeout;
+ }
timest = talloc_asprintf(ctx, "%llu", timell);
}
if (!timest) return ENOMEM;
@@ -300,7 +307,7 @@ static int sss_ncache_set_service_int(struct sss_nc_ctx *ctx, bool permanent,
str = talloc_asprintf(ctx, "%s/%s/%s", NC_SERVICE_PREFIX, domain, name);
if (!str) return ENOMEM;
- ret = sss_ncache_set_str(ctx, str, permanent);
+ ret = sss_ncache_set_str(ctx, str, permanent, false);
talloc_free(str);
return ret;
@@ -446,6 +453,7 @@ int sss_ncache_check_cert(struct sss_nc_ctx *ctx, const char *cert)
static int sss_ncache_set_user_int(struct sss_nc_ctx *ctx, bool permanent,
const char *domain, const char *name)
{
+ bool locals;
char *str;
int ret;
@@ -454,7 +462,8 @@ static int sss_ncache_set_user_int(struct sss_nc_ctx *ctx, bool permanent,
str = talloc_asprintf(ctx, "%s/%s/%s", NC_USER_PREFIX, domain, name);
if (!str) return ENOMEM;
- ret = sss_ncache_set_str(ctx, str, permanent);
+ locals = is_user_local_by_name(name);
+ ret = sss_ncache_set_str(ctx, str, permanent, locals);
talloc_free(str);
return ret;
@@ -463,6 +472,7 @@ static int sss_ncache_set_user_int(struct sss_nc_ctx *ctx, bool permanent,
static int sss_ncache_set_group_int(struct sss_nc_ctx *ctx, bool permanent,
const char *domain, const char *name)
{
+ bool locals;
char *str;
int ret;
@@ -471,7 +481,8 @@ static int sss_ncache_set_group_int(struct sss_nc_ctx *ctx, bool permanent,
str = talloc_asprintf(ctx, "%s/%s/%s", NC_GROUP_PREFIX, domain, name);
if (!str) return ENOMEM;
- ret = sss_ncache_set_str(ctx, str, permanent);
+ locals = is_group_local_by_name(name);
+ ret = sss_ncache_set_str(ctx, str, permanent, locals);
talloc_free(str);
return ret;
@@ -488,7 +499,7 @@ static int sss_ncache_set_netgr_int(struct sss_nc_ctx *ctx, bool permanent,
str = talloc_asprintf(ctx, "%s/%s/%s", NC_NETGROUP_PREFIX, domain, name);
if (!str) return ENOMEM;
- ret = sss_ncache_set_str(ctx, str, permanent);
+ ret = sss_ncache_set_str(ctx, str, permanent, false);
talloc_free(str);
return ret;
@@ -535,6 +546,7 @@ int sss_ncache_set_netgr(struct sss_nc_ctx *ctx, bool permanent,
int sss_ncache_set_uid(struct sss_nc_ctx *ctx, bool permanent,
struct sss_domain_info *dom, uid_t uid)
{
+ bool locals;
char *str;
int ret;
@@ -546,7 +558,8 @@ int sss_ncache_set_uid(struct sss_nc_ctx *ctx, bool permanent,
}
if (!str) return ENOMEM;
- ret = sss_ncache_set_str(ctx, str, permanent);
+ locals = is_user_local_by_uid(uid);
+ ret = sss_ncache_set_str(ctx, str, permanent, locals);
talloc_free(str);
return ret;
@@ -555,6 +568,7 @@ int sss_ncache_set_uid(struct sss_nc_ctx *ctx, bool permanent,
int sss_ncache_set_gid(struct sss_nc_ctx *ctx, bool permanent,
struct sss_domain_info *dom, gid_t gid)
{
+ bool locals;
char *str;
int ret;
@@ -566,7 +580,8 @@ int sss_ncache_set_gid(struct sss_nc_ctx *ctx, bool permanent,
}
if (!str) return ENOMEM;
- ret = sss_ncache_set_str(ctx, str, permanent);
+ locals = is_group_local_by_gid(gid);
+ ret = sss_ncache_set_str(ctx, str, permanent, locals);
talloc_free(str);
return ret;
@@ -580,7 +595,7 @@ int sss_ncache_set_sid(struct sss_nc_ctx *ctx, bool permanent, const char *sid)
str = talloc_asprintf(ctx, "%s/%s", NC_SID_PREFIX, sid);
if (!str) return ENOMEM;
- ret = sss_ncache_set_str(ctx, str, permanent);
+ ret = sss_ncache_set_str(ctx, str, permanent, false);
talloc_free(str);
return ret;
@@ -595,7 +610,7 @@ int sss_ncache_set_cert(struct sss_nc_ctx *ctx, bool permanent,
str = talloc_asprintf(ctx, "%s/%s", NC_CERT_PREFIX, cert);
if (!str) return ENOMEM;
- ret = sss_ncache_set_str(ctx, str, permanent);
+ ret = sss_ncache_set_str(ctx, str, permanent, false);
talloc_free(str);
return ret;
diff --git a/src/responder/common/negcache.h b/src/responder/common/negcache.h
index 572c723cc5202dac26671458920cb85cdc208fd2..c8b0858872b53aebf7094b6ba6865c0b3c11cb77 100644
--- a/src/responder/common/negcache.h
+++ b/src/responder/common/negcache.h
@@ -26,7 +26,7 @@ struct sss_nc_ctx;
/* init the in memory negative cache */
int sss_ncache_init(TALLOC_CTX *memctx, uint32_t timeout,
- struct sss_nc_ctx **_ctx);
+ uint32_t locals_timeout, struct sss_nc_ctx **_ctx);
uint32_t sss_ncache_get_timeout(struct sss_nc_ctx *ctx);
diff --git a/src/responder/common/negcache_files.c b/src/responder/common/negcache_files.c
new file mode 100644
index 0000000000000000000000000000000000000000..995630e7328f79368dd983aeee7bc96eb38c142e
--- /dev/null
+++ b/src/responder/common/negcache_files.c
@@ -0,0 +1,93 @@
+/*
+ SSSD
+
+ NSS Responder
+
+ Copyright (C) Petr Äech <[email protected]> 2016
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+#include "util/util.h"
+#include "responder/common/negcache_files.h"
+
+#define BUFFER_SIZE 16384
+
+bool is_user_local_by_name(const char *name)
+{
+ struct passwd pwd = {0};
+ struct passwd *pwd_result;
+ char buffer[BUFFER_SIZE];
+ bool is_local = false;
+ int ret;
+
+ ret = getpwnam_r(name, &pwd, buffer, BUFFER_SIZE, &pwd_result);
+ if (ret == EOK && pwd_result != NULL) {
+ is_local = true;
+ }
+
+ return is_local;
+}
+
+bool is_user_local_by_uid(uid_t uid)
+{
+ struct passwd pwd = {0};
+ struct passwd *pwd_result;
+ char buffer[BUFFER_SIZE];
+ bool is_local = false;
+ int ret;
+
+ ret = getpwuid_r(uid, &pwd, buffer, BUFFER_SIZE, &pwd_result);
+ if (ret == EOK && pwd_result != NULL) {
+ is_local = true;
+ }
+
+ return is_local;
+}
+
+bool is_group_local_by_name(const char *name)
+{
+ struct group grp = {0};
+ struct group *grp_result;
+ char buffer[BUFFER_SIZE];
+ bool is_local = false;
+ int ret;
+
+ ret = getgrnam_r(name, &grp, buffer, BUFFER_SIZE, &grp_result);
+ if (ret == EOK && grp_result != NULL) {
+ is_local = true;
+ }
+
+ return is_local;
+}
+
+bool is_group_local_by_gid(uid_t gid)
+{
+ struct group grp = {0};
+ struct group *grp_result;
+ char buffer[BUFFER_SIZE];
+ bool is_local = false;
+ int ret;
+
+ ret = getgrgid_r(gid, &grp, buffer, BUFFER_SIZE, &grp_result);
+ if (ret == EOK && grp_result != NULL) {
+ is_local = true;
+ }
+
+ return is_local;
+}
+
diff --git a/src/responder/common/negcache_files.h b/src/responder/common/negcache_files.h
new file mode 100644
index 0000000000000000000000000000000000000000..bd9c79b8ce574f78506b6ea1eb5ee215a8efbe0a
--- /dev/null
+++ b/src/responder/common/negcache_files.h
@@ -0,0 +1,32 @@
+/*
+ SSSD
+
+ NSS Responder
+
+ Copyright (C) Petr Äech <[email protected]> 2016
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _NEGCACHE_FILES_H_
+#define _NEGCACHE_FILES_H_
+
+bool is_user_local_by_name(const char *name);
+bool is_user_local_by_uid(uid_t uid);
+
+bool is_group_local_by_name(const char *name);
+bool is_group_local_by_gid(uid_t gid);
+
+#endif /* _NEGCACHE_FILES_H_ */
+
diff --git a/src/responder/common/responder_common.c b/src/responder/common/responder_common.c
index 883b22a6548c29738f23a5ccf6747969f4e7146c..d231f19725de054264a8957ca3050f7ad9600d4c 100644
--- a/src/responder/common/responder_common.c
+++ b/src/responder/common/responder_common.c
@@ -761,6 +761,7 @@ static errno_t responder_init_ncache(TALLOC_CTX *mem_ctx,
struct sss_nc_ctx **ncache)
{
uint32_t neg_timeout;
+ uint32_t locals_timeout;
int tmp_value;
int ret;
@@ -783,8 +784,27 @@ static errno_t responder_init_ncache(TALLOC_CTX *mem_ctx,
neg_timeout = tmp_value;
ret = EOK;
+ /* locals_timeout */
+ ret = confdb_get_int(cdb, CONFDB_NSS_CONF_ENTRY,
+ CONFDB_RESPONDER_NEG_CACHE_LOCALS_TIMEOUT,
+ 0, &tmp_value);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_FATAL_FAILURE,
+ "Fatal failure of setup negative cache timeout.\n");
+ ret = ENOENT;
+ goto done;
+ }
+
+ if (tmp_value < 0) {
+ ret = EINVAL;
+ goto done;
+ }
+
+ locals_timeout = tmp_value;
+ ret = EOK;
+
/* negative cache init */
- ret = sss_ncache_init(mem_ctx, neg_timeout, ncache);
+ ret = sss_ncache_init(mem_ctx, neg_timeout, locals_timeout, ncache);
if (ret != EOK) {
DEBUG(SSSDBG_FATAL_FAILURE,
"Fatal failure of initializing negative cache.\n");
diff --git a/src/tests/cmocka/common_mock_resp.c b/src/tests/cmocka/common_mock_resp.c
index 8bcf18b800d8f64d5ddff9b6524eb209aa88f213..ce73d1b4542946f41003833d81e0f68086fd13e3 100644
--- a/src/tests/cmocka/common_mock_resp.c
+++ b/src/tests/cmocka/common_mock_resp.c
@@ -42,7 +42,7 @@ mock_rctx(TALLOC_CTX *mem_ctx,
return NULL;
}
- ret = sss_ncache_init(rctx, 10, &rctx->ncache);
+ ret = sss_ncache_init(rctx, 10, 0, &rctx->ncache);
if (ret != EOK) {
talloc_free(rctx);
return NULL;
diff --git a/src/tests/cmocka/test_negcache.c b/src/tests/cmocka/test_negcache.c
index e309ce6456ddaa425568d263964e7a01a653eaf5..a78341c89cda49fc205e8b48b068f2df1a36229e 100644
--- a/src/tests/cmocka/test_negcache.c
+++ b/src/tests/cmocka/test_negcache.c
@@ -104,7 +104,7 @@ static int setup(void **state)
ts = talloc(NULL, struct test_state);
assert_non_null(ts);
- ret = sss_ncache_init(ts, SHORTSPAN, &ts->ctx);
+ ret = sss_ncache_init(ts, SHORTSPAN, 0, &ts->ctx);
assert_int_equal(ret, EOK);
assert_non_null(ts->ctx);
@@ -128,7 +128,7 @@ static void test_sss_ncache_init(void **state)
memctx = talloc_new(NULL);
assert_non_null(memctx);
- ret = sss_ncache_init(memctx, SHORTSPAN, &ctx );
+ ret = sss_ncache_init(memctx, SHORTSPAN, 0, &ctx );
assert_int_equal(ret, EOK);
assert_non_null(ctx);
diff --git a/src/tests/cmocka/test_responder_cache_req.c b/src/tests/cmocka/test_responder_cache_req.c
index 6c13500cef9ec82dde9d97f97f7fb492fe0e3b8f..f30f1eaaddb653a1a5ad325b2838847b1dec1c22 100644
--- a/src/tests/cmocka/test_responder_cache_req.c
+++ b/src/tests/cmocka/test_responder_cache_req.c
@@ -434,7 +434,7 @@ static int test_single_domain_setup(void **state)
test_ctx->tctx->dom, NULL);
assert_non_null(test_ctx->rctx);
- ret = sss_ncache_init(test_ctx, 10, &test_ctx->ncache);
+ ret = sss_ncache_init(test_ctx, 10, 0, &test_ctx->ncache);
assert_int_equal(ret, EOK);
check_leaks_push(test_ctx);
@@ -480,7 +480,7 @@ static int test_multi_domain_setup(void **state)
test_ctx->tctx->dom, NULL);
assert_non_null(test_ctx->rctx);
- ret = sss_ncache_init(test_ctx, 10, &test_ctx->ncache);
+ ret = sss_ncache_init(test_ctx, 10, 0, &test_ctx->ncache);
assert_int_equal(ret, EOK);
check_leaks_push(test_ctx);
diff --git a/src/tests/cwrap/Makefile.am b/src/tests/cwrap/Makefile.am
index a5afb8c020ee00b680aac0680bcf6f6495dd8222..ba30bab6ecc1afbf451707c2af777480cfe6fd0d 100644
--- a/src/tests/cwrap/Makefile.am
+++ b/src/tests/cwrap/Makefile.am
@@ -106,6 +106,7 @@ usertools_tests_LDADD = \
responder_common_tests_SOURCES =\
test_responder_common.c \
+ ../../../src/responder/common/negcache_files.c \
../../../src/responder/common/negcache.c \
../../../src/responder/common/responder_common.c \
../../../src/responder/common/responder_packet.c \
--
2.5.5
_______________________________________________
sssd-devel mailing list
[email protected]
https://lists.fedorahosted.org/admin/lists/[email protected]