diff options
Diffstat (limited to 'src/responder/nss/nsssrv_cmd.c')
-rw-r--r-- | src/responder/nss/nsssrv_cmd.c | 142 |
1 files changed, 135 insertions, 7 deletions
diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c index 04ff2d654..bf578f394 100644 --- a/src/responder/nss/nsssrv_cmd.c +++ b/src/responder/nss/nsssrv_cmd.c @@ -27,6 +27,7 @@ #include "responder/nss/nsssrv_services.h" #include "responder/nss/nsssrv_mmap_cache.h" #include "responder/common/negcache.h" +#include "providers/data_provider.h" #include "confdb/confdb.h" #include "db/sysdb.h" #include "sss_client/idmap/sss_nss_idmap.h" @@ -728,13 +729,16 @@ static int nss_cmd_getpwnam_search(struct nss_dom_ctx *dctx) char *name = NULL; struct nss_ctx *nctx; int ret; + static const char *user_attrs[] = SYSDB_PW_ATTRS; + struct ldb_message *msg; nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx); while (dom) { /* if it is a domainless search, skip domains that require fully * qualified names instead */ - while (dom && cmdctx->check_next && dom->fqnames) { + while (dom && cmdctx->check_next && dom->fqnames + && !cmdctx->name_is_upn) { dom = get_next_domain(dom, false); } @@ -791,7 +795,37 @@ static int nss_cmd_getpwnam_search(struct nss_dom_ctx *dctx) return EIO; } - ret = sysdb_getpwnam(cmdctx, dom, name, &dctx->res); + if (cmdctx->name_is_upn) { + ret = sysdb_search_user_by_upn(cmdctx, dom, name, user_attrs, &msg); + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_search_user_by_upn failed.\n"); + return ret; + } + + dctx->res = talloc_zero(cmdctx, struct ldb_result); + if (dctx->res == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n"); + return ENOMEM; + } + + if (ret == ENOENT) { + dctx->res->count = 0; + dctx->res->msgs = NULL; + ret = EOK; + } else { + dctx->res->count = 1; + dctx->res->msgs = talloc_array(dctx->res, + struct ldb_message *, 1); + if (dctx->res->msgs == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n"); + return ENOMEM; + } + + dctx->res->msgs[0] = talloc_steal(dctx->res->msgs, msg); + } + } else { + ret = sysdb_getpwnam(cmdctx, dom, name, &dctx->res); + } if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Failed to make request to our cache!\n"); @@ -835,7 +869,8 @@ static int nss_cmd_getpwnam_search(struct nss_dom_ctx *dctx) * yet) then verify that the cache is uptodate */ if (dctx->check_provider) { ret = check_cache(dctx, nctx, dctx->res, - SSS_DP_USER, name, 0, NULL, + SSS_DP_USER, name, 0, + cmdctx->name_is_upn ? EXTRA_NAME_IS_UPN : NULL, nss_cmd_getby_dp_callback, dctx); if (ret != EOK) { @@ -868,6 +903,44 @@ static errno_t nss_cmd_getbysid_search(struct nss_dom_ctx *dctx); static errno_t nss_cmd_getbysid_send_reply(struct nss_dom_ctx *dctx); static errno_t nss_cmd_getsidby_search(struct nss_dom_ctx *dctx); +static int nss_cmd_assume_upn(struct nss_dom_ctx *dctx) +{ + int ret; + + if (dctx->domain == NULL) { + dctx->domain = dctx->cmdctx->cctx->rctx->domains; + dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider); + dctx->cmdctx->check_next = true; + dctx->cmdctx->name = talloc_strdup(dctx->cmdctx, dctx->rawname); + dctx->cmdctx->name_is_upn = true; + if (dctx->cmdctx->name == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); + return ENOMEM; + } + } + + switch (dctx->cmdctx->cmd) { + case SSS_NSS_GETPWNAM: + ret = nss_cmd_getpwnam_search(dctx); + if (ret == EOK) { + ret = nss_cmd_getpw_send_reply(dctx, false); + } + break; + case SSS_NSS_INITGR: + ret = nss_cmd_initgroups_search(dctx); + if (ret == EOK) { + ret = nss_cmd_initgr_send_reply(dctx); + } + break; + default: + DEBUG(SSSDBG_CRIT_FAILURE, "Invalid command [%d].\n", + dctx->cmdctx->cmd); + ret = EINVAL; + } + + return ret; +} + static void nss_cmd_getby_dp_callback(uint16_t err_maj, uint32_t err_min, const char *err_msg, void *ptr) { @@ -1006,6 +1079,14 @@ static void nss_cmd_getby_dp_callback(uint16_t err_maj, uint32_t err_min, } done: + if (ret == ENOENT + && (dctx->cmdctx->cmd == SSS_NSS_GETPWNAM + || dctx->cmdctx->cmd == SSS_NSS_INITGR) + && dctx->rawname != NULL && strchr(dctx->rawname, '@') != NULL) { + /* assume Kerberos principal */ + ret = nss_cmd_assume_upn(dctx); + } + ret = nss_cmd_done(cmdctx, ret); if (ret) { NSS_CMD_FATAL_ERROR(cctx); @@ -1211,6 +1292,11 @@ static int nss_cmd_getbynam(enum sss_cli_command cmd, struct cli_ctx *cctx) if (ret == EOK) { /* we have results to return */ ret = nss_cmd_getpw_send_reply(dctx, false); + } else if (ret == ENOENT + && dctx->rawname != NULL + && strchr(dctx->rawname, '@') != NULL) { + /* assume Kerberos principal */ + ret = nss_cmd_assume_upn(dctx); } break; case SSS_NSS_GETGRNAM: @@ -1225,6 +1311,11 @@ static int nss_cmd_getbynam(enum sss_cli_command cmd, struct cli_ctx *cctx) if (ret == EOK) { /* we have results to return */ ret = nss_cmd_initgr_send_reply(dctx); + } else if (ret == ENOENT + && dctx->rawname != NULL + && strchr(dctx->rawname, '@') != NULL) { + /* assume Kerberos principal */ + ret = nss_cmd_assume_upn(dctx); } break; case SSS_NSS_GETSIDBYNAME: @@ -1261,7 +1352,12 @@ static void nss_cmd_getbynam_done(struct tevent_req *req) ret = sss_parse_name_for_domains(cmdctx, cctx->rctx->domains, cctx->rctx->default_domain, rawname, &domname, &cmdctx->name); - if (ret != EOK) { + if (ret == EAGAIN && (dctx->cmdctx->cmd == SSS_NSS_GETPWNAM + || dctx->cmdctx->cmd == SSS_NSS_INITGR)) { + /* assume Kerberos principal */ + ret = nss_cmd_assume_upn(dctx); + goto done; + } else if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Invalid name received [%s]\n", rawname); ret = ENOENT; goto done; @@ -1291,6 +1387,11 @@ static void nss_cmd_getbynam_done(struct tevent_req *req) if (ret == EOK) { /* we have results to return */ ret = nss_cmd_getpw_send_reply(dctx, false); + } else if (ret == ENOENT + && dctx->rawname != NULL + && strchr(dctx->rawname, '@') != NULL) { + /* assume Kerberos principal */ + ret = nss_cmd_assume_upn(dctx); } break; case SSS_NSS_GETGRNAM: @@ -1305,6 +1406,11 @@ static void nss_cmd_getbynam_done(struct tevent_req *req) if (ret == EOK) { /* we have results to return */ ret = nss_cmd_initgr_send_reply(dctx); + } else if (ret == ENOENT + && dctx->rawname != NULL + && strchr(dctx->rawname, '@') != NULL) { + /* assume Kerberos principal */ + ret = nss_cmd_assume_upn(dctx); } break; case SSS_NSS_GETSIDBYNAME: @@ -3734,13 +3840,17 @@ static int nss_cmd_initgroups_search(struct nss_dom_ctx *dctx) char *name = NULL; struct nss_ctx *nctx; int ret; + static const char *user_attrs[] = SYSDB_PW_ATTRS; + struct ldb_message *msg; + const char *sysdb_name; nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx); while (dom) { /* if it is a domainless search, skip domains that require fully * qualified names instead */ - while (dom && cmdctx->check_next && dom->fqnames) { + while (dom && cmdctx->check_next && dom->fqnames + && !cmdctx->name_is_upn) { dom = get_next_domain(dom, false); } @@ -3797,7 +3907,24 @@ static int nss_cmd_initgroups_search(struct nss_dom_ctx *dctx) return EIO; } - ret = sysdb_initgroups(cmdctx, dom, name, &dctx->res); + if (cmdctx->name_is_upn) { + ret = sysdb_search_user_by_upn(cmdctx, dom, name, user_attrs, &msg); + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_search_user_by_upn failed.\n"); + return ret; + } + + sysdb_name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL); + if (sysdb_name == NULL) { + DEBUG(SSSDBG_OP_FAILURE, + "Sysdb entry does not have a name.\n"); + return EINVAL; + } + + ret = sysdb_initgroups(cmdctx, dom, sysdb_name, &dctx->res); + } else { + ret = sysdb_initgroups(cmdctx, dom, name, &dctx->res); + } if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Failed to make request to our cache! [%d][%s]\n", @@ -3828,7 +3955,8 @@ static int nss_cmd_initgroups_search(struct nss_dom_ctx *dctx) * yet) then verify that the cache is uptodate */ if (dctx->check_provider) { ret = check_cache(dctx, nctx, dctx->res, - SSS_DP_INITGROUPS, name, 0, NULL, + SSS_DP_INITGROUPS, name, 0, + cmdctx->name_is_upn ? EXTRA_NAME_IS_UPN : NULL, nss_cmd_getby_dp_callback, dctx); if (ret != EOK) { |