diff options
author | Pavel Reichl <preichl@redhat.com> | 2014-09-25 14:52:31 +0100 |
---|---|---|
committer | Jakub Hrozek <jhrozek@redhat.com> | 2014-09-29 18:27:07 +0200 |
commit | 830ded27453015080a54d6ba85fd4999ee7e9af1 (patch) | |
tree | 2dcdecd4d211c25e7e1dd909e062e534348227db /src/responder/pam/pamsrv_cmd.c | |
parent | cb7644495e76ffa3e19ba10efb4a0f5f3817ba33 (diff) | |
download | sssd-830ded27453015080a54d6ba85fd4999ee7e9af1.tar.gz sssd-830ded27453015080a54d6ba85fd4999ee7e9af1.tar.xz sssd-830ded27453015080a54d6ba85fd4999ee7e9af1.zip |
PAM: new options pam_trusted_users & pam_public_domains
pam_public_domains option is a list of numerical UIDs or user names
that are trusted.
pam_public_domains option is a list of domains accessible even for
untrusted users.
Based on:
https://fedorahosted.org/sssd/wiki/DesignDocs/RestrictDomainsInPAM
Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
Diffstat (limited to 'src/responder/pam/pamsrv_cmd.c')
-rw-r--r-- | src/responder/pam/pamsrv_cmd.c | 80 |
1 files changed, 77 insertions, 3 deletions
diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c index 561bd3d96..eb6953a74 100644 --- a/src/responder/pam/pamsrv_cmd.c +++ b/src/responder/pam/pamsrv_cmd.c @@ -762,6 +762,45 @@ static int pam_auth_req_destructor(struct pam_auth_req *preq) return 0; } +static bool is_uid_trusted(uint32_t uid, + size_t trusted_uids_count, + uid_t *trusted_uids) +{ + size_t i; + + /* root is always trusted */ + if (uid == 0) { + return true; + } + + /* All uids are allowed */ + if (trusted_uids_count == 0) { + return true; + } + + for(i = 0; i < trusted_uids_count; i++) { + if (trusted_uids[i] == uid) { + return true; + } + } + + return false; +} + +static bool is_domain_public(char *name, + char **public_dom_names, + size_t public_dom_names_count) +{ + size_t i; + + for(i=0; i < public_dom_names_count; i++) { + if (strcmp(name, public_dom_names[i]) == 0) { + return true; + } + } + return false; +} + static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd) { struct sss_domain_info *dom; @@ -773,6 +812,15 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd) talloc_get_type(cctx->rctx->pvt_ctx, struct pam_ctx); struct tevent_req *req; + pctx->is_uid_trusted = is_uid_trusted(cctx->client_euid, + pctx->trusted_uids_count, + pctx->trusted_uids); + + if (!pctx->is_uid_trusted) { + DEBUG(SSSDBG_MINOR_FAILURE, "uid %"PRIu32" is not trusted.\n", + cctx->client_euid); + } + preq = talloc_zero(cctx, struct pam_auth_req); if (!preq) { return ENOMEM; @@ -813,6 +861,17 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd) goto done; } + /* Untrusted users can access only public domains. */ + if (!pctx->is_uid_trusted && + !is_domain_public(pd->domain, pctx->public_domains, + pctx->public_domains_count)) { + DEBUG(SSSDBG_MINOR_FAILURE, + "Untrusted user %"PRIu32" cannot access unpublic domain %s.\n", + cctx->client_euid, pd->domain); + ret = EPERM; + goto done; + } + ncret = sss_ncache_check_user(pctx->ncache, pctx->neg_timeout, preq->domain, pd->user); if (ncret == EEXIST) { @@ -826,6 +885,17 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd) dom = get_next_domain(dom, false)) { if (dom->fqnames) continue; + /* Untrusted users can access only public domains. */ + if (!pctx->is_uid_trusted && + !is_domain_public(dom->name, pctx->public_domains, + pctx->public_domains_count)) { + DEBUG(SSSDBG_MINOR_FAILURE, + "Untrusted user %"PRIu32" cannot access unpublic domain %s." + " Trying next domain.\n", + cctx->client_euid, dom->name); + continue; + } + ncret = sss_ncache_check_user(pctx->ncache, pctx->neg_timeout, dom, pd->user); if (ncret == ENOENT) { @@ -920,7 +990,6 @@ done: } static void pam_dp_send_acct_req_done(struct tevent_req *req); - static int pam_check_user_search(struct pam_auth_req *preq) { struct sss_domain_info *dom = preq->domain; @@ -936,9 +1005,14 @@ static int pam_check_user_search(struct pam_auth_req *preq) while (dom) { /* if it is a domainless search, skip domains that require fully - * qualified names instead */ + * qualified names instead, also untrusted users can access only + * public domains */ while (dom && !preq->pd->domain && !preq->pd->name_is_upn - && dom->fqnames) { + && (dom->fqnames || + (!pctx->is_uid_trusted && + !is_domain_public(dom->name, + pctx->public_domains, + pctx->public_domains_count)))) { dom = get_next_domain(dom, false); } |