diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/providers/data_provider.h | 1 | ||||
-rw-r--r-- | src/responder/nss/nsssrv_cmd.c | 142 | ||||
-rw-r--r-- | src/responder/nss/nsssrv_private.h | 1 | ||||
-rw-r--r-- | src/responder/pam/pamsrv_cmd.c | 47 |
4 files changed, 168 insertions, 23 deletions
diff --git a/src/providers/data_provider.h b/src/providers/data_provider.h index 742fcca57..b1279852e 100644 --- a/src/providers/data_provider.h +++ b/src/providers/data_provider.h @@ -176,6 +176,7 @@ struct pam_data { struct sss_auth_token *newauthtok; uint32_t cli_pid; char *logon_name; + bool name_is_upn; int pam_status; int response_delay; 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) { diff --git a/src/responder/nss/nsssrv_private.h b/src/responder/nss/nsssrv_private.h index 23bb6a8d3..e5f3bde50 100644 --- a/src/responder/nss/nsssrv_private.h +++ b/src/responder/nss/nsssrv_private.h @@ -31,6 +31,7 @@ struct nss_cmd_ctx { struct cli_ctx *cctx; enum sss_cli_command cmd; char *name; + bool name_is_upn; uint32_t id; char *secid; diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c index eae17341a..561bd3d96 100644 --- a/src/responder/pam/pamsrv_cmd.c +++ b/src/responder/pam/pamsrv_cmd.c @@ -882,7 +882,22 @@ static void pam_forwarder_cb(struct tevent_req *req) pd = preq->pd; ret = pam_forwarder_parse_data(cctx, pd); - if (ret != EOK) { + if (ret == EAGAIN) { + if (strchr(preq->pd->logon_name, '@') == NULL) { + goto done; + } + /* Assuming Kerberos principal */ + preq->domain = preq->cctx->rctx->domains; + preq->check_provider = NEED_CHECK_PROVIDER(preq->domain->provider); + preq->pd->user = talloc_strdup(preq->pd, preq->pd->logon_name); + if (preq->pd->user == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); + ret = ENOMEM; + goto done; + } + preq->pd->name_is_upn = true; + preq->pd->domain = NULL; + } else if (ret != EOK) { ret = EINVAL; goto done; } @@ -916,12 +931,14 @@ static int pam_check_user_search(struct pam_auth_req *preq) struct dp_callback_ctx *cb_ctx; struct pam_ctx *pctx = talloc_get_type(preq->cctx->rctx->pvt_ctx, struct pam_ctx); - struct ldb_result *res; + static const char *user_attrs[] = SYSDB_PW_ATTRS; + struct ldb_message *msg; while (dom) { /* if it is a domainless search, skip domains that require fully * qualified names instead */ - while (dom && !preq->pd->domain && dom->fqnames) { + while (dom && !preq->pd->domain && !preq->pd->name_is_upn + && dom->fqnames) { dom = get_next_domain(dom, false); } @@ -979,20 +996,18 @@ static int pam_check_user_search(struct pam_auth_req *preq) return EFAULT; } - ret = sysdb_getpwnam(preq, dom, name, &res); - if (ret != EOK) { + if (preq->pd->name_is_upn) { + ret = sysdb_search_user_by_upn(preq, dom, name, user_attrs, &msg); + } else { + ret = sysdb_search_user_by_name(preq, dom, name, user_attrs, &msg); + } + if (ret != EOK && ret != ENOENT) { DEBUG(SSSDBG_CRIT_FAILURE, "Failed to make request to our cache!\n"); return EIO; } - if (res->count > 1) { - DEBUG(SSSDBG_FATAL_FAILURE, - "getpwnam call returned more than one result !?!\n"); - return ENOENT; - } - - if (res->count == 0) { + if (ret == ENOENT) { if (preq->check_provider == false) { /* set negative cache only if not result of cache check */ ret = sss_ncache_set_user(pctx->ncache, false, dom, name); @@ -1021,7 +1036,7 @@ static int pam_check_user_search(struct pam_auth_req *preq) /* if we need to check the remote account go on */ if (preq->check_provider) { - cacheExpire = ldb_msg_find_attr_as_uint64(res->msgs[0], + cacheExpire = ldb_msg_find_attr_as_uint64(msg, SYSDB_CACHE_EXPIRE, 0); if (cacheExpire < time(NULL)) { break; @@ -1032,7 +1047,7 @@ static int pam_check_user_search(struct pam_auth_req *preq) "Returning info for user [%s@%s]\n", name, dom->name); /* We might have searched by alias. Pass on the primary name */ - ret = pd_set_primary_name(res->msgs[0], preq->pd); + ret = pd_set_primary_name(msg, preq->pd); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Could not canonicalize username\n"); return ret; @@ -1054,8 +1069,8 @@ static int pam_check_user_search(struct pam_auth_req *preq) preq->check_provider = false; dpreq = sss_dp_get_account_send(preq, preq->cctx->rctx, - dom, false, SSS_DP_INITGROUPS, - name, 0, NULL); + dom, false, SSS_DP_INITGROUPS, name, 0, + preq->pd->name_is_upn ? EXTRA_NAME_IS_UPN : NULL); if (!dpreq) { DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory sending data provider request\n"); |