summaryrefslogtreecommitdiffstats
path: root/src/responder/pam/pamsrv_cmd.c
diff options
context:
space:
mode:
authorPavel Reichl <preichl@redhat.com>2014-09-25 14:52:31 +0100
committerJakub Hrozek <jhrozek@redhat.com>2014-09-29 18:27:07 +0200
commit830ded27453015080a54d6ba85fd4999ee7e9af1 (patch)
tree2dcdecd4d211c25e7e1dd909e062e534348227db /src/responder/pam/pamsrv_cmd.c
parentcb7644495e76ffa3e19ba10efb4a0f5f3817ba33 (diff)
downloadsssd-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.c80
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);
}