diff options
-rw-r--r-- | src/confdb/confdb.h | 1 | ||||
-rw-r--r-- | src/config/SSSDConfig.py | 1 | ||||
-rw-r--r-- | src/config/etc/sssd.api.d/sssd-proxy.conf | 1 | ||||
-rw-r--r-- | src/man/sssd.conf.5.xml | 17 | ||||
-rw-r--r-- | src/providers/proxy/proxy.h | 1 | ||||
-rw-r--r-- | src/providers/proxy/proxy_id.c | 161 | ||||
-rw-r--r-- | src/providers/proxy/proxy_init.c | 4 |
7 files changed, 143 insertions, 43 deletions
diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h index aebf5d88..83a0fea9 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 488220a6..f4987997 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 7ecf6b33..39f6a63c 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 1a8ae2bb..c164d121 100644 --- a/src/man/sssd.conf.5.xml +++ b/src/man/sssd.conf.5.xml @@ -1190,6 +1190,23 @@ </para> </listitem> </varlistentry> + + <varlistentry> + <term>proxy_fast_alias (boolean)</term> + <listitem> + <para> + 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. + </para> + <para> + Default: false + </para> + </listitem> + </varlistentry> </variablelist> </para> diff --git a/src/providers/proxy/proxy.h b/src/providers/proxy/proxy.h index 3641d6ee..cea03382 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 d92fc4ea..e1325b74 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_TRACE_FUNC, ("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; - goto done; + if (ctx->fast_alias == true) { + ret = sysdb_getgrgid(tmpctx, sysdb, gid, &cached_grp); + if (ret != EOK) { + /* Non-fatal, attempt to canonicalize online */ + DEBUG(SSSDBG_TRACE_FUNC, ("Request to cache failed [%d]: %s\n", + ret, strerror(ret))); } - status = ctx->ops.getgrgid_r(gid, grp, buffer, buflen, &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")); + } + } + } - ret = handle_getgr_result(status, grp, dom, &delete_group); - } while(ret == EAGAIN); + if (real_name == NULL) { + talloc_zfree(buffer); + buflen = 0; - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, - ("getgrgid failed [%d]: %s\n", ret, strerror(ret))); - goto done; + 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; + } + + 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_TRACE_FUNC, ("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 46b2e7c3..de4d7b61 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; |