>From 00e447db2df1ae7f2f205908113379447a201b3e Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Thu, 12 Apr 2012 18:21:48 +0200 Subject: [PATCH 2/2] proxy: new option proxy_fast_alias --- src/confdb/confdb.h | 1 + src/config/SSSDConfig.py | 1 + src/config/etc/sssd.api.d/sssd-proxy.conf | 1 + src/man/sssd.conf.5.xml | 17 +++ src/providers/proxy/proxy.h | 1 + src/providers/proxy/proxy_id.c | 163 +++++++++++++++++++++-------- src/providers/proxy/proxy_init.c | 4 + 7 files changed, 144 insertions(+), 44 deletions(-) diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h index aebf5d888002aa30af709ec57d3663de9f554a10..83a0fea90f4e2da8837a7bbb3643d520a74583ac 100644 --- a/src/confdb/confdb.h +++ b/src/confdb/confdb.h @@ -158,6 +158,7 @@ /* Proxy Provider */ #define CONFDB_PROXY_LIBNAME "proxy_lib_name" #define CONFDB_PROXY_PAM_TARGET "proxy_pam_target" +#define CONFDB_PROXY_FAST_ALIAS "proxy_fast_alias" struct confdb_ctx; struct config_file_ctx; diff --git a/src/config/SSSDConfig.py b/src/config/SSSDConfig.py index 488220a67fa94be7c96dc1a02487700ebfe89a40..f4987997248dfadc1383537b981d4797104affe1 100644 --- a/src/config/SSSDConfig.py +++ b/src/config/SSSDConfig.py @@ -300,6 +300,7 @@ option_strings = { # [provider/proxy/id] 'proxy_lib_name' : _('The name of the NSS library to use'), + 'proxy_fast_alias' : _('Whether to look up canonical group name from cache if possible'), # [provider/proxy/auth] 'proxy_pam_target' : _('PAM stack to use') diff --git a/src/config/etc/sssd.api.d/sssd-proxy.conf b/src/config/etc/sssd.api.d/sssd-proxy.conf index 7ecf6b33b66be979c06393de99f93df142552df2..39f6a63cdec8d5ac5b84e93b16bdd8b668cf7623 100644 --- a/src/config/etc/sssd.api.d/sssd-proxy.conf +++ b/src/config/etc/sssd.api.d/sssd-proxy.conf @@ -2,6 +2,7 @@ [provider/proxy/id] proxy_lib_name = str, None, true +proxy_fast_alias = bool, None, true [provider/proxy/auth] proxy_pam_target = str, None, true diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml index 63e396a545f04b28b1bfb0ccc69b454aa83686e9..ed3c3574379d6847a4a5e93f035158715a73dc34 100644 --- a/src/man/sssd.conf.5.xml +++ b/src/man/sssd.conf.5.xml @@ -1180,6 +1180,23 @@ + + + proxy_fast_alias (boolean) + + + When a user or group is looked up by name in + the proxy provider, a second lookup by ID is + performed to "canonicalize" the name in case + the requested name was an alias. Setting this + option to true would cause the SSSD to perform + the ID lookup from cache for performance reasons. + + + Default: false + + + diff --git a/src/providers/proxy/proxy.h b/src/providers/proxy/proxy.h index 3641d6ee544c69982d23e1f675c40da69b8de604..cea03382517231cdf2b96069ab93dfb7967b46a6 100644 --- a/src/providers/proxy/proxy.h +++ b/src/providers/proxy/proxy.h @@ -100,6 +100,7 @@ struct authtok_conv { struct proxy_id_ctx { struct be_ctx *be; + bool fast_alias; struct proxy_nss_ops ops; void *handle; }; diff --git a/src/providers/proxy/proxy_id.c b/src/providers/proxy/proxy_id.c index d92fc4eacfc6f3801a19d6577e39d1b202b53bd0..b7f1ee4d7657dababeb37146d18aa8e131a794b6 100644 --- a/src/providers/proxy/proxy_id.c +++ b/src/providers/proxy/proxy_id.c @@ -28,8 +28,8 @@ /* =Getpwnam-wrapper======================================================*/ static int save_user(struct sysdb_ctx *sysdb, bool lowercase, - struct passwd *pwd, const char *alias, - uint64_t cache_timeout); + struct passwd *pwd, const char *real_name, + const char *alias, uint64_t cache_timeout); static int handle_getpw_result(enum nss_status status, struct passwd *pwd, @@ -49,6 +49,8 @@ static int get_pw_name(TALLOC_CTX *mem_ctx, int ret; uid_t uid; bool del_user; + struct ldb_result *cached_pwd = NULL; + const char *real_name = NULL; DEBUG(SSSDBG_TRACE_FUNC, ("Searching user by name (%s)\n", name)); @@ -91,15 +93,38 @@ static int get_pw_name(TALLOC_CTX *mem_ctx, } uid = pwd->pw_uid; - memset(buffer, 0, buflen); /* Canonicalize the username in case it was actually an alias */ - status = ctx->ops.getpwuid_r(uid, pwd, buffer, buflen, &ret); - ret = handle_getpw_result(status, pwd, dom, &del_user); - if (ret) { - DEBUG(SSSDBG_OP_FAILURE, - ("getpwuid failed [%d]: %s\n", ret, strerror(ret))); - goto done; + + if (ctx->fast_alias == true) { + ret = sysdb_getpwuid(tmpctx, sysdb, uid, &cached_pwd); + if (ret != EOK) { + /* Non-fatal, attempt to canonicalize online */ + DEBUG(SSSDBG_MINOR_FAILURE, ("Request to cache failed [%d]: %s\n", + ret, strerror(ret))); + } + + if (ret == EOK && cached_pwd->count == 1) { + real_name = ldb_msg_find_attr_as_string(cached_pwd->msgs[0], + SYSDB_NAME, NULL); + if (!real_name) { + DEBUG(SSSDBG_MINOR_FAILURE, ("Cached user has no name?\n")); + } + } + } + + if (real_name == NULL) { + memset(buffer, 0, buflen); + + status = ctx->ops.getpwuid_r(uid, pwd, buffer, buflen, &ret); + ret = handle_getpw_result(status, pwd, dom, &del_user); + if (ret) { + DEBUG(SSSDBG_OP_FAILURE, + ("getpwuid failed [%d]: %s\n", ret, strerror(ret))); + goto done; + } + + real_name = pwd->pw_name; } if (del_user) { @@ -112,7 +137,7 @@ static int get_pw_name(TALLOC_CTX *mem_ctx, /* Both lookups went fine, we can save the user now */ ret = save_user(sysdb, !dom->case_sensitive, pwd, - name, dom->user_timeout); + real_name, name, dom->user_timeout); done: talloc_zfree(tmpctx); @@ -175,8 +200,8 @@ handle_getpw_result(enum nss_status status, struct passwd *pwd, } static int save_user(struct sysdb_ctx *sysdb, bool lowercase, - struct passwd *pwd, const char *alias, - uint64_t cache_timeout) + struct passwd *pwd, const char *real_name, + const char *alias, uint64_t cache_timeout) { const char *shell; char *lower; @@ -230,7 +255,7 @@ static int save_user(struct sysdb_ctx *sysdb, bool lowercase, } ret = sysdb_store_user(sysdb, - pwd->pw_name, + real_name, pwd->pw_passwd, pwd->pw_uid, pwd->pw_gid, @@ -303,7 +328,7 @@ static int get_pw_uid(TALLOC_CTX *mem_ctx, } ret = save_user(sysdb, !dom->case_sensitive, pwd, - NULL, dom->user_timeout); + pwd->pw_name, NULL, dom->user_timeout); done: talloc_zfree(tmpctx); @@ -412,7 +437,7 @@ again: } ret = save_user(sysdb, !dom->case_sensitive, pwd, - NULL, dom->user_timeout); + pwd->pw_name, NULL, dom->user_timeout); if (ret) { /* Do not fail completely on errors. * Just report the failure to save and go on */ @@ -466,8 +491,8 @@ static errno_t proxy_process_missing_users(struct sysdb_ctx *sysdb, struct group *grp, time_t now); static int save_group(struct sysdb_ctx *sysdb, struct sss_domain_info *dom, - struct group *grp, const char *alias, - uint64_t cache_timeout) + struct group *grp, const char *real_name, + const char *alias, uint64_t cache_timeout) { errno_t ret, sret; struct sysdb_attrs *attrs = NULL; @@ -555,7 +580,7 @@ static int save_group(struct sysdb_ctx *sysdb, struct sss_domain_info *dom, } ret = sysdb_store_group(sysdb, - grp->gr_name, + real_name, grp->gr_gid, attrs, cache_timeout, @@ -718,6 +743,8 @@ static int get_gr_name(TALLOC_CTX *mem_ctx, bool delete_group = false; int ret; gid_t gid; + struct ldb_result *cached_grp = NULL; + const char *real_name = NULL; DEBUG(SSSDBG_FUNC_DATA, ("Searching group by name (%s)\n", name)); @@ -756,27 +783,49 @@ static int get_gr_name(TALLOC_CTX *mem_ctx, } gid = grp->gr_gid; - talloc_zfree(buffer); - buflen = 0; /* Canonicalize the group name in case it was actually an alias */ - do { - memset(grp, 0, sizeof(struct group)); - buffer = grow_group_buffer(tmpctx, &buffer, &buflen); - if (!buffer) { - ret = ENOMEM; + if (ctx->fast_alias == true) { + ret = sysdb_getgrgid(tmpctx, sysdb, gid, &cached_grp); + if (ret != EOK) { + /* Non-fatal, attempt to canonicalize online */ + DEBUG(SSSDBG_MINOR_FAILURE, ("Request to cache failed [%d]: %s\n", + ret, strerror(ret))); + } + + if (ret == EOK && cached_grp->count == 1) { + real_name = ldb_msg_find_attr_as_string(cached_grp->msgs[0], + SYSDB_NAME, NULL); + if (!real_name) { + DEBUG(SSSDBG_MINOR_FAILURE, ("Cached group has no name?\n")); + } + } + } + + if (real_name == NULL) { + talloc_zfree(buffer); + buflen = 0; + + do { + memset(grp, 0, sizeof(struct group)); + buffer = grow_group_buffer(tmpctx, &buffer, &buflen); + if (!buffer) { + ret = ENOMEM; + goto done; + } + + status = ctx->ops.getgrgid_r(gid, grp, buffer, buflen, &ret); + + ret = handle_getgr_result(status, grp, dom, &delete_group); + } while (ret == EAGAIN); + + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + ("getgrgid failed [%d]: %s\n", ret, strerror(ret))); goto done; } - status = ctx->ops.getgrgid_r(gid, grp, buffer, buflen, &ret); - - ret = handle_getgr_result(status, grp, dom, &delete_group); - } while(ret == EAGAIN); - - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, - ("getgrgid failed [%d]: %s\n", ret, strerror(ret))); - goto done; + real_name = grp->gr_name; } if (delete_group) { @@ -788,7 +837,7 @@ static int get_gr_name(TALLOC_CTX *mem_ctx, goto done; } - ret = save_group(sysdb, dom, grp, name, dom->group_timeout); + ret = save_group(sysdb, dom, grp, real_name, name, dom->group_timeout); if (ret) { DEBUG(SSSDBG_OP_FAILURE, ("Cannot save group [%d]: %s\n", ret, strerror(ret))); @@ -857,7 +906,7 @@ static int get_gr_gid(TALLOC_CTX *mem_ctx, goto done; } - ret = save_group(sysdb, dom, grp, NULL, dom->group_timeout); + ret = save_group(sysdb, dom, grp, grp->gr_name, NULL, dom->group_timeout); if (ret) { DEBUG(SSSDBG_OP_FAILURE, ("Cannot save user [%d]: %s\n", ret, strerror(ret))); @@ -970,7 +1019,8 @@ again: goto again; /* skip */ } - ret = save_group(sysdb, dom, grp, NULL, dom->group_timeout); + ret = save_group(sysdb, dom, grp, grp->gr_name, + NULL, dom->group_timeout); if (ret) { /* Do not fail completely on errors. * Just report the failure to save and go on */ @@ -1023,6 +1073,8 @@ static int get_initgr(TALLOC_CTX *mem_ctx, int ret; bool del_user; uid_t uid; + struct ldb_result *cached_pwd = NULL; + const char *real_name = NULL; tmpctx = talloc_new(mem_ctx); if (!tmpctx) { @@ -1074,12 +1126,35 @@ static int get_initgr(TALLOC_CTX *mem_ctx, memset(buffer, 0, buflen); /* Canonicalize the username in case it was actually an alias */ - status = ctx->ops.getpwuid_r(uid, pwd, buffer, buflen, &ret); - ret = handle_getpw_result(status, pwd, dom, &del_user); - if (ret) { - DEBUG(SSSDBG_OP_FAILURE, - ("getpwuid failed [%d]: %s\n", ret, strerror(ret))); - goto fail; + if (ctx->fast_alias == true) { + ret = sysdb_getpwuid(tmpctx, sysdb, uid, &cached_pwd); + if (ret != EOK) { + /* Non-fatal, attempt to canonicalize online */ + DEBUG(SSSDBG_MINOR_FAILURE, ("Request to cache failed [%d]: %s\n", + ret, strerror(ret))); + } + + if (ret == EOK && cached_pwd->count == 1) { + real_name = ldb_msg_find_attr_as_string(cached_pwd->msgs[0], + SYSDB_NAME, NULL); + if (!real_name) { + DEBUG(SSSDBG_MINOR_FAILURE, ("Cached user has no name?\n")); + } + } + } + + if (real_name == NULL) { + memset(buffer, 0, buflen); + + status = ctx->ops.getpwuid_r(uid, pwd, buffer, buflen, &ret); + ret = handle_getpw_result(status, pwd, dom, &del_user); + if (ret) { + DEBUG(SSSDBG_OP_FAILURE, + ("getpwuid failed [%d]: %s\n", ret, strerror(ret))); + goto done; + } + + real_name = pwd->pw_name; } if (del_user) { @@ -1095,7 +1170,7 @@ static int get_initgr(TALLOC_CTX *mem_ctx, } ret = save_user(sysdb, !dom->case_sensitive, pwd, - name, dom->user_timeout); + real_name, name, dom->user_timeout); if (ret) { DEBUG(SSSDBG_OP_FAILURE, ("Could not save user\n")); goto fail; diff --git a/src/providers/proxy/proxy_init.c b/src/providers/proxy/proxy_init.c index 46b2e7c36e5515b737c1f0e4e887ad5897b8d332..de4d7b615aabb1d151a55c5eb6ac620be1f244cf 100644 --- a/src/providers/proxy/proxy_init.c +++ b/src/providers/proxy/proxy_init.c @@ -109,6 +109,10 @@ int sssm_proxy_id_init(struct be_ctx *bectx, goto done; } + ret = confdb_get_bool(bectx->cdb, bectx->conf_path, + CONFDB_PROXY_FAST_ALIAS, false, &ctx->fast_alias); + if (ret != EOK) goto done; + libpath = talloc_asprintf(ctx, "libnss_%s.so.2", libname); if (!libpath) { ret = ENOMEM; -- 1.7.7.6