summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetr Cech <pcech@redhat.com>2016-05-05 11:16:14 -0400
committerLukas Slebodnik <lslebodn@redhat.com>2016-06-10 18:42:25 +0200
commite7ccfb139388c947ec2dee16cfe3005f5643b90d (patch)
treeadf642cd84332a6afafa90a70919117ecefbb5f0
parentacf7cee13f07b368b0ccae69776309f7f69cbca1 (diff)
downloadsssd-e7ccfb139388c947ec2dee16cfe3005f5643b90d.tar.gz
sssd-e7ccfb139388c947ec2dee16cfe3005f5643b90d.tar.xz
sssd-e7ccfb139388c947ec2dee16cfe3005f5643b90d.zip
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 Reviewed-by: Pavel Březina <pbrezina@redhat.com>
-rw-r--r--Makefile.am4
-rw-r--r--src/confdb/confdb.h1
-rw-r--r--src/config/SSSDConfig/__init__.py.in1
-rw-r--r--src/config/etc/sssd.api.conf1
-rw-r--r--src/man/sssd.conf.5.xml13
-rw-r--r--src/responder/common/negcache.c45
-rw-r--r--src/responder/common/negcache.h2
-rw-r--r--src/responder/common/negcache_files.c98
-rw-r--r--src/responder/common/negcache_files.h31
-rw-r--r--src/responder/common/responder_common.c22
-rw-r--r--src/tests/cmocka/common_mock_resp.c2
-rw-r--r--src/tests/cmocka/test_negcache.c4
-rw-r--r--src/tests/cmocka/test_responder_cache_req.c4
-rw-r--r--src/tests/cwrap/Makefile.am1
14 files changed, 209 insertions, 20 deletions
diff --git a/Makefile.am b/Makefile.am
index 25130b105..ee8f698d6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -457,6 +457,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 \
@@ -582,6 +583,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.h \
src/responder/common/negcache.h \
src/responder/sudo/sudosrv_private.h \
src/responder/autofs/autofs_private.h \
@@ -1852,6 +1854,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 \
@@ -1949,6 +1952,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 a9b1c4362..3ed82ca0a 100644
--- a/src/confdb/confdb.h
+++ b/src/confdb/confdb.h
@@ -85,6 +85,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_LOCAL_NEG_TIMEOUT "local_negative_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 e7bf43dfd..abbf5dca8 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)'),
+ 'local_negative_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 a0a82543f..fef55364d 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
+local_negative_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 6cff0dc87..b82e94156 100644
--- a/src/man/sssd.conf.5.xml
+++ b/src/man/sssd.conf.5.xml
@@ -613,6 +613,19 @@
</listitem>
</varlistentry>
<varlistentry>
+ <term>local_negative_timeout (integer)</term>
+ <listitem>
+ <para>
+ Specifies for how many seconds nss_sss should keep
+ local users and groups in negative cache before
+ trying to look it up in the back end again.
+ </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 1488c12a8..025455238 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 local_timeout;
};
typedef int (*ncache_set_byname_fn_t)(struct sss_nc_ctx *, bool,
@@ -59,8 +61,8 @@ static int string_to_tdb_data(char *str, TDB_DATA *ret)
return EOK;
}
-int sss_ncache_init(TALLOC_CTX *memctx, uint32_t timeout,
- struct sss_nc_ctx **_ctx)
+int sss_ncache_init(TALLOC_CTX *memctx, uint32_t timeout,
+ uint32_t local_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->local_timeout = local_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 is_local)
{
TDB_DATA key;
TDB_DATA data;
@@ -154,7 +157,15 @@ 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 (is_local == true && ctx->local_timeout > 0) {
+ timell = (unsigned long long int)time(NULL) + ctx->local_timeout;
+ } else {
+ if (ctx->timeout > 0) {
+ timell = (unsigned long long int)time(NULL) + ctx->timeout;
+ } else {
+ return EOK;
+ }
+ }
timest = talloc_asprintf(ctx, "%llu", timell);
}
if (!timest) return ENOMEM;
@@ -300,7 +311,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 +457,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 is_local;
char *str;
int ret;
@@ -454,7 +466,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);
+ is_local = is_user_local_by_name(name);
+ ret = sss_ncache_set_str(ctx, str, permanent, is_local);
talloc_free(str);
return ret;
@@ -463,6 +476,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 is_local;
char *str;
int ret;
@@ -471,7 +485,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);
+ is_local = is_group_local_by_name(name);
+ ret = sss_ncache_set_str(ctx, str, permanent, is_local);
talloc_free(str);
return ret;
@@ -488,7 +503,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 +550,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 is_local;
char *str;
int ret;
@@ -546,7 +562,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);
+ is_local = is_user_local_by_uid(uid);
+ ret = sss_ncache_set_str(ctx, str, permanent, is_local);
talloc_free(str);
return ret;
@@ -555,6 +572,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 is_local;
char *str;
int ret;
@@ -566,7 +584,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);
+ is_local = is_group_local_by_gid(gid);
+ ret = sss_ncache_set_str(ctx, str, permanent, is_local);
talloc_free(str);
return ret;
@@ -580,7 +599,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 +614,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 572c723cc..377f97c8b 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 local_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 000000000..1b9a4be43
--- /dev/null
+++ b/src/responder/common/negcache_files.c
@@ -0,0 +1,98 @@
+/*
+ SSSD
+
+ NSS Responder
+
+ Copyright (C) Petr Čech <pcech@redhat.com> 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) {
+ DEBUG(SSSDBG_TRACE_FUNC, "User %s is a local user\n", name);
+ 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) {
+ DEBUG(SSSDBG_TRACE_FUNC,
+ "User with UID %"SPRIuid" is a local user\n", uid);
+ 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) {
+ DEBUG(SSSDBG_TRACE_FUNC, "Group %s is a local group\n", name);
+ 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) {
+ DEBUG(SSSDBG_TRACE_FUNC,
+ "Group with GID %"SPRIgid" is a local group\n", gid);
+ 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 000000000..01d9f0828
--- /dev/null
+++ b/src/responder/common/negcache_files.h
@@ -0,0 +1,31 @@
+/*
+ SSSD
+
+ NSS Responder
+
+ Copyright (C) Petr Čech <pcech@redhat.com> 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 883b22a65..f0ddde9c0 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;
+ /* local_timeout */
+ ret = confdb_get_int(cdb, CONFDB_NSS_CONF_ENTRY,
+ CONFDB_RESPONDER_LOCAL_NEG_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 8bcf18b80..ce73d1b45 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 e309ce645..8911774e3 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 6c13500ce..f30f1eaad 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 abf50a56f..8f4d9f7ea 100644
--- a/src/tests/cwrap/Makefile.am
+++ b/src/tests/cwrap/Makefile.am
@@ -112,6 +112,7 @@ endif
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 \