summaryrefslogtreecommitdiffstats
path: root/src/responder/pam/pamsrv_cmd.c
diff options
context:
space:
mode:
authorSumit Bose <sbose@redhat.com>2014-06-24 18:30:01 +0200
committerJakub Hrozek <jhrozek@redhat.com>2014-09-01 13:56:57 +0200
commit899d1bdc048cd74518170d7d9535d76d3f46d4af (patch)
tree289feefa466ed4d844afacdc94b9446aba480cad /src/responder/pam/pamsrv_cmd.c
parent7d2437adc312d3322d36043ff458fafdb4b7f2cf (diff)
downloadsssd-899d1bdc048cd74518170d7d9535d76d3f46d4af.tar.gz
sssd-899d1bdc048cd74518170d7d9535d76d3f46d4af.tar.xz
sssd-899d1bdc048cd74518170d7d9535d76d3f46d4af.zip
PAM, NSS: allow UPN login names
With this patch the NSS and PAM responders can handle user principal names besides the fully qualified user names. User principal names are build from a user name and a domain suffix separated by an '@' sign. But the domain suffix does not necessarily has to be the same as the configured domain name in sssd.conf of the dynamically discovered DNS domain name of a domain. The typical use case is an Active Directory forest with lots of different domains. To not force the users to remember the name of the individual domain they belong to the AD administrator can set a common domain suffix for all users from all domains in the forest. This is typically the domain name used for emails to make it even more easy to the users to remember it. Since SSSD splits name and domain part at the '@' sign and the common domain suffix might not be resolvable by DNS or the given user is not a member of that domain (e.g. in the case where the forest root is used as common domain suffix) SSSD might fail to look up the user. With this patch the NSS and PAM responder will do an extra lookup for a UPN if the domain part of the given name is not known or the user was not found and the login name contained the '@' sign. Resolves https://fedorahosted.org/sssd/ticket/1749
Diffstat (limited to 'src/responder/pam/pamsrv_cmd.c')
-rw-r--r--src/responder/pam/pamsrv_cmd.c47
1 files changed, 31 insertions, 16 deletions
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");