summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJan Zeleny <jzeleny@redhat.com>2012-06-15 14:19:34 -0400
committerStephen Gallagher <sgallagh@redhat.com>2012-06-21 17:03:02 -0400
commit065771c9859df9c4137daa5187be3aa5633b3cd5 (patch)
treed6dffe5599b5ef7717c25afdc394319e102d6144 /src
parent4b0b0bc3f9c4966b9f1a7433803a37c36fcaf285 (diff)
downloadsssd-065771c9859df9c4137daa5187be3aa5633b3cd5.tar.gz
sssd-065771c9859df9c4137daa5187be3aa5633b3cd5.tar.xz
sssd-065771c9859df9c4137daa5187be3aa5633b3cd5.zip
Fix re_expression matching with subdomains
This patch fixes an issue which resulted in a need to initialize responder with data from local domain, otherwise it would not correctly detect requests for subdomains. Similar situation can occur if new subdomain is added at runtime. The solution is to ask for a list of subdomains in case there is a candidate domain identified in the process of matching re_expressions with given name.
Diffstat (limited to 'src')
-rw-r--r--src/responder/nss/nsssrv_cmd.c134
-rw-r--r--src/responder/nss/nsssrv_private.h2
-rw-r--r--src/responder/pam/pamsrv_cmd.c88
-rw-r--r--src/util/usertools.c34
4 files changed, 173 insertions, 85 deletions
diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
index fc504700c..5c5f8060b 100644
--- a/src/responder/nss/nsssrv_cmd.c
+++ b/src/responder/nss/nsssrv_cmd.c
@@ -798,8 +798,18 @@ static int nss_cmd_getpwnam(struct cli_ctx *cctx)
domname = NULL;
ret = sss_parse_name_for_domains(cmdctx, cctx->rctx->domains, rawname,
&domname, &cmdctx->name);
- if (ret != EOK) {
- DEBUG(2, ("Invalid name received [%s]\n", rawname));
+ if (ret == EAGAIN) {
+ req = sss_dp_get_domains_send(cctx->rctx, cctx->rctx, true, domname);
+ if (req == NULL) {
+ ret = ENOMEM;
+ } else {
+ dctx->rawname = rawname;
+ tevent_req_set_callback(req, nss_cmd_getpwnam_cb, dctx);
+ ret = EAGAIN;
+ }
+ goto done;
+ } if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Invalid name received [%s]\n", rawname));
ret = ENOENT;
goto done;
}
@@ -810,18 +820,12 @@ static int nss_cmd_getpwnam(struct cli_ctx *cctx)
if (domname) {
dctx->domain = responder_get_domain(dctx, cctx->rctx, domname);
if (!dctx->domain) {
- req = sss_dp_get_domains_send(cctx->rctx, cctx->rctx, true, domname);
- if (req == NULL) {
- ret = ENOMEM;
- } else {
- dctx->domname = domname;
- tevent_req_set_callback(req, nss_cmd_getpwnam_cb, dctx);
- ret = EAGAIN;
- }
+ ret = ENOENT;
goto done;
}
} else {
/* this is a multidomain search */
+ dctx->rawname = rawname;
dctx->domain = cctx->rctx->domains;
cmdctx->check_next = true;
if (cctx->rctx->get_domains_last_call.tv_sec == 0) {
@@ -854,6 +858,8 @@ static void nss_cmd_getpwnam_cb(struct tevent_req *req)
struct nss_dom_ctx *dctx = tevent_req_callback_data(req, struct nss_dom_ctx);
struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
struct cli_ctx *cctx = cmdctx->cctx;
+ char *domname = NULL;
+ const char *rawname = dctx->rawname;
errno_t ret;
ret = sss_dp_get_domains_recv(req);
@@ -862,12 +868,27 @@ static void nss_cmd_getpwnam_cb(struct tevent_req *req)
goto done;
}
- if (dctx->domname) {
- dctx->domain = responder_get_domain(dctx, cctx->rctx, dctx->domname);
+ ret = sss_parse_name_for_domains(cmdctx, cctx->rctx->domains, rawname,
+ &domname, &cmdctx->name);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Invalid name received [%s]\n", rawname));
+ ret = ENOENT;
+ goto done;
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC, ("Requesting info for [%s] from [%s]\n",
+ cmdctx->name, domname?domname:"<ALL>"));
+
+ if (domname) {
+ dctx->domain = responder_get_domain(dctx, cctx->rctx, domname);
if (dctx->domain == NULL) {
ret = ENOENT;
goto done;
}
+ } else {
+ /* this is a multidomain search */
+ dctx->domain = cctx->rctx->domains;
+ cmdctx->check_next = true;
}
dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
@@ -2264,7 +2285,17 @@ static int nss_cmd_getgrnam(struct cli_ctx *cctx)
domname = NULL;
ret = sss_parse_name_for_domains(cmdctx, cctx->rctx->domains, rawname,
&domname, &cmdctx->name);
- if (ret != EOK) {
+ if (ret == EAGAIN) {
+ req = sss_dp_get_domains_send(cctx->rctx, cctx->rctx, true, domname);
+ if (req == NULL) {
+ ret = ENOMEM;
+ } else {
+ dctx->rawname = rawname;
+ tevent_req_set_callback(req, nss_cmd_getgrnam_cb, dctx);
+ ret = EAGAIN;
+ }
+ goto done;
+ } else if (ret != EOK) {
DEBUG(2, ("Invalid name received [%s]\n", rawname));
ret = ENOENT;
goto done;
@@ -2276,18 +2307,12 @@ static int nss_cmd_getgrnam(struct cli_ctx *cctx)
if (domname) {
dctx->domain = responder_get_domain(dctx, cctx->rctx, domname);
if (!dctx->domain) {
- req = sss_dp_get_domains_send(cctx->rctx, cctx->rctx, true, domname);
- if (req == NULL) {
- ret = ENOMEM;
- } else {
- dctx->domname = domname;
- tevent_req_set_callback(req, nss_cmd_getgrnam_cb, dctx);
- ret = EAGAIN;
- }
+ ret = ENOENT;
goto done;
}
} else {
/* this is a multidomain search */
+ dctx->rawname = rawname;
dctx->domain = cctx->rctx->domains;
cmdctx->check_next = true;
if (cctx->rctx->get_domains_last_call.tv_sec == 0) {
@@ -2320,6 +2345,8 @@ static void nss_cmd_getgrnam_cb(struct tevent_req *req)
struct nss_dom_ctx *dctx = tevent_req_callback_data(req, struct nss_dom_ctx);
struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
struct cli_ctx *cctx = cmdctx->cctx;
+ char *domname = NULL;
+ const char *rawname = dctx->rawname;
errno_t ret;
ret = sss_dp_get_domains_recv(req);
@@ -2328,12 +2355,26 @@ static void nss_cmd_getgrnam_cb(struct tevent_req *req)
goto done;
}
- if (dctx->domname) {
- dctx->domain = responder_get_domain(dctx, cctx->rctx, dctx->domname);
- if (dctx->domain == NULL) {
+ ret = sss_parse_name_for_domains(cmdctx, cctx->rctx->domains, rawname,
+ &domname, &cmdctx->name);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Invalid name received [%s]\n", rawname));
+ ret = ENOENT;
+ goto done;
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC, ("Requesting info for [%s] from [%s]\n",
+ cmdctx->name, domname?domname:"<ALL>"));
+ if (domname) {
+ dctx->domain = responder_get_domain(dctx, cctx->rctx, domname);
+ if (!dctx->domain) {
ret = ENOENT;
goto done;
}
+ } else {
+ /* this is a multidomain search */
+ dctx->domain = cctx->rctx->domains;
+ cmdctx->check_next = true;
}
dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
@@ -3374,7 +3415,17 @@ static int nss_cmd_initgroups(struct cli_ctx *cctx)
domname = NULL;
ret = sss_parse_name_for_domains(cmdctx, cctx->rctx->domains, rawname,
&domname, &cmdctx->name);
- if (ret != EOK) {
+ if (ret == EAGAIN) {
+ req = sss_dp_get_domains_send(cctx->rctx, cctx->rctx, true, domname);
+ if (req == NULL) {
+ ret = ENOMEM;
+ } else {
+ dctx->rawname = rawname;
+ tevent_req_set_callback(req, nss_cmd_initgroups_cb, dctx);
+ ret = EAGAIN;
+ }
+ goto done;
+ } else if (ret != EOK) {
DEBUG(2, ("Invalid name received [%s]\n", rawname));
ret = ENOENT;
goto done;
@@ -3386,18 +3437,12 @@ static int nss_cmd_initgroups(struct cli_ctx *cctx)
if (domname) {
dctx->domain = responder_get_domain(dctx, cctx->rctx, domname);
if (!dctx->domain) {
- req = sss_dp_get_domains_send(cctx->rctx, cctx->rctx, true, domname);
- if (req == NULL) {
- ret = ENOMEM;
- } else {
- dctx->domname = domname;
- tevent_req_set_callback(req, nss_cmd_initgroups_cb, dctx);
- ret = EAGAIN;
- }
+ ret = ENOENT;
goto done;
}
} else {
/* this is a multidomain search */
+ dctx->rawname = rawname;
dctx->domain = cctx->rctx->domains;
cmdctx->check_next = true;
if (cctx->rctx->get_domains_last_call.tv_sec == 0) {
@@ -3430,6 +3475,8 @@ static void nss_cmd_initgroups_cb(struct tevent_req *req)
struct nss_dom_ctx *dctx = tevent_req_callback_data(req, struct nss_dom_ctx);
struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
struct cli_ctx *cctx = cmdctx->cctx;
+ char *domname = NULL;
+ const char *rawname = dctx->rawname;
errno_t ret;
ret = sss_dp_get_domains_recv(req);
@@ -3438,12 +3485,27 @@ static void nss_cmd_initgroups_cb(struct tevent_req *req)
goto done;
}
- if (dctx->domname) {
- dctx->domain = responder_get_domain(dctx, cctx->rctx, dctx->domname);
- if (dctx->domain == NULL) {
+ ret = sss_parse_name_for_domains(cmdctx, cctx->rctx->domains, rawname,
+ &domname, &cmdctx->name);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Invalid name received [%s]\n", rawname));
+ ret = ENOENT;
+ goto done;
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC, ("Requesting info for [%s] from [%s]\n",
+ cmdctx->name, domname?domname:"<ALL>"));
+
+ if (domname) {
+ dctx->domain = responder_get_domain(dctx, cctx->rctx, domname);
+ if (!dctx->domain) {
ret = ENOENT;
goto done;
}
+ } else {
+ /* this is a multidomain search */
+ dctx->domain = cctx->rctx->domains;
+ cmdctx->check_next = true;
}
dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
diff --git a/src/responder/nss/nsssrv_private.h b/src/responder/nss/nsssrv_private.h
index 57975943b..f1d47c3bc 100644
--- a/src/responder/nss/nsssrv_private.h
+++ b/src/responder/nss/nsssrv_private.h
@@ -64,7 +64,7 @@ struct nss_dom_ctx {
struct sss_domain_info *domain;
/* For a case when we are discovering subdomains */
- const char *domname;
+ const char *rawname;
bool check_provider;
diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c
index f6c1e8350..2d0324e5b 100644
--- a/src/responder/pam/pamsrv_cmd.c
+++ b/src/responder/pam/pamsrv_cmd.c
@@ -851,32 +851,12 @@ static void pam_dom_forwarder(struct pam_auth_req *preq);
* PAM_ENVIRONMENT, so that we can save performing some calls and cache
* data. */
-static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd)
+errno_t pam_forwarder_parse_data(struct cli_ctx *cctx, struct pam_data *pd)
{
- struct sss_domain_info *dom;
- struct pam_auth_req *preq;
- struct pam_data *pd;
uint8_t *body;
size_t blen;
- int ret;
- errno_t ncret;
- struct pam_ctx *pctx =
- talloc_get_type(cctx->rctx->pvt_ctx, struct pam_ctx);
+ errno_t ret;
uint32_t terminator = SSS_END_OF_PAM_REQUEST;
- struct tevent_req *req;
-
- preq = talloc_zero(cctx, struct pam_auth_req);
- if (!preq) {
- return ENOMEM;
- }
- preq->cctx = cctx;
-
- preq->pd = talloc_zero(preq, struct pam_data);
- if (!preq->pd) {
- talloc_free(preq);
- return ENOMEM;
- }
- pd = preq->pd;
sss_packet_get_body(cctx->creq->in, &body, &blen);
if (blen >= sizeof(uint32_t) &&
@@ -886,9 +866,6 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd)
goto done;
}
- pd->cmd = pam_cmd;
- pd->priv = cctx->priv;
-
switch (cctx->cli_protocol_version->version) {
case 1:
ret = pam_parse_in_data(cctx->rctx->domains, pd, body, blen);
@@ -904,7 +881,49 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd)
cctx->cli_protocol_version->version));
ret = EINVAL;
}
- if (ret != EOK) {
+
+done:
+ return ret;
+}
+
+static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd)
+{
+ struct sss_domain_info *dom;
+ struct pam_auth_req *preq;
+ struct pam_data *pd;
+ int ret;
+ errno_t ncret;
+ struct pam_ctx *pctx =
+ talloc_get_type(cctx->rctx->pvt_ctx, struct pam_ctx);
+ struct tevent_req *req;
+
+ preq = talloc_zero(cctx, struct pam_auth_req);
+ if (!preq) {
+ return ENOMEM;
+ }
+ preq->cctx = cctx;
+
+ preq->pd = talloc_zero(preq, struct pam_data);
+ if (!preq->pd) {
+ talloc_free(preq);
+ return ENOMEM;
+ }
+ pd = preq->pd;
+
+ pd->cmd = pam_cmd;
+ pd->priv = cctx->priv;
+
+ ret = pam_forwarder_parse_data(cctx, pd);
+ if (ret == EAGAIN) {
+ req = sss_dp_get_domains_send(cctx->rctx, cctx->rctx, true, pd->domain);
+ if (req == NULL) {
+ ret = ENOMEM;
+ } else {
+ tevent_req_set_callback(req, pam_forwarder_cb, preq);
+ ret = EAGAIN;
+ }
+ goto done;
+ } else if (ret != EOK) {
ret = EINVAL;
goto done;
}
@@ -913,13 +932,7 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd)
if (pd->domain) {
preq->domain = responder_get_domain(preq, cctx->rctx, pd->domain);
if (!preq->domain) {
- req = sss_dp_get_domains_send(cctx->rctx, cctx->rctx, true, pd->domain);
- if (req == NULL) {
- ret = ENOMEM;
- } else {
- tevent_req_set_callback(req, pam_forwarder_cb, preq);
- ret = EAGAIN;
- }
+ ret = ENOENT;
goto done;
}
} else {
@@ -969,6 +982,7 @@ static void pam_forwarder_cb(struct tevent_req *req)
struct pam_auth_req *preq = tevent_req_callback_data(req,
struct pam_auth_req);
struct cli_ctx *cctx = preq->cctx;
+ struct pam_data *pd;
errno_t ret = EOK;
ret = sss_dp_get_domains_recv(req);
@@ -977,6 +991,14 @@ static void pam_forwarder_cb(struct tevent_req *req)
goto done;
}
+ pd = preq->pd;
+
+ ret = pam_forwarder_parse_data(cctx, pd);
+ if (ret != EOK) {
+ ret = EINVAL;
+ goto done;
+ }
+
if (preq->pd->domain) {
preq->domain = responder_get_domain(preq, cctx->rctx, preq->pd->domain);
if (preq->domain == NULL) {
diff --git a/src/util/usertools.c b/src/util/usertools.c
index 3b23b6a7e..36641d49f 100644
--- a/src/util/usertools.c
+++ b/src/util/usertools.c
@@ -230,9 +230,9 @@ int sss_parse_name_for_domains(TALLOC_CTX *memctx,
struct sss_domain_info *dom, *match;
char *rdomain, *rname;
char *dmatch, *nmatch;
- char *only_name = NULL;
- bool only_name_seen = false;
- bool only_name_mismatch = false;
+ char *candidate_name = NULL;
+ char *candidate_domain = NULL;
+ bool name_mismatch = false;
TALLOC_CTX *tmp_ctx;
int code;
@@ -252,13 +252,11 @@ int sss_parse_name_for_domains(TALLOC_CTX *memctx,
* name.
*/
if (dmatch == NULL) {
- if (!only_name_seen) {
- only_name = nmatch;
- } else if (nmatch == NULL || only_name == NULL ||
- strcasecmp(only_name, nmatch) != 0) {
- only_name_mismatch = true;
+ if (candidate_name == NULL) {
+ candidate_name = nmatch;
+ } else if (strcasecmp(candidate_name, nmatch) != 0) {
+ name_mismatch = true;
}
- only_name_seen = true;
/*
* If a domain was returned, then it must match the name of the
@@ -274,6 +272,8 @@ int sss_parse_name_for_domains(TALLOC_CTX *memctx,
rdomain = dmatch;
rname = nmatch;
break;
+ } else if (candidate_name == NULL) {
+ candidate_domain = dmatch;
}
}
@@ -284,12 +284,16 @@ int sss_parse_name_for_domains(TALLOC_CTX *memctx,
}
}
- if (rdomain == NULL && rname == NULL &&
- only_name_seen && !only_name_mismatch && only_name != NULL) {
- DEBUG(SSSDBG_FUNC_DATA,
- ("name '%s' matched without domain, user is %s\n", orig, nmatch));
- rdomain = NULL;
- rname = only_name;
+ if (rdomain == NULL && rname == NULL) {
+ if (candidate_name && !name_mismatch) {
+ DEBUG(SSSDBG_FUNC_DATA,
+ ("name '%s' matched without domain, user is %s\n", orig, nmatch));
+ rdomain = NULL;
+ rname = candidate_name;
+ } else if (candidate_domain) {
+ *domain = talloc_steal(memctx, candidate_domain);
+ return EAGAIN;
+ }
}
if (rdomain == NULL && rname == NULL) {