summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/providers/data_provider.h1
-rw-r--r--src/responder/nss/nsssrv_cmd.c142
-rw-r--r--src/responder/nss/nsssrv_private.h1
-rw-r--r--src/responder/pam/pamsrv_cmd.c47
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");