summaryrefslogtreecommitdiffstats
path: root/src/responder/pam
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
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')
-rw-r--r--src/responder/pam/pamsrv.c94
-rw-r--r--src/responder/pam/pamsrv.h7
-rw-r--r--src/responder/pam/pamsrv_cmd.c80
3 files changed, 178 insertions, 3 deletions
diff --git a/src/responder/pam/pamsrv.c b/src/responder/pam/pamsrv.c
index c0841d2bd..428b252ac 100644
--- a/src/responder/pam/pamsrv.c
+++ b/src/responder/pam/pamsrv.c
@@ -46,6 +46,10 @@
#include "responder/common/responder_sbus.h"
#define DEFAULT_PAM_FD_LIMIT 8192
+#define ALL_UIDS_ALLOWED "all"
+#define ALL_DOMAIMS_ARE_PUBLIC "all"
+#define NO_DOMAIMS_ARE_PUBLIC "none"
+#define DEFAULT_ALLOWED_UIDS ALL_UIDS_ALLOWED
struct mon_cli_iface monitor_pam_methods = {
{ &mon_cli_iface_meta, 0 },
@@ -99,6 +103,82 @@ static void pam_dp_reconnect_init(struct sbus_connection *conn, int status, void
/* pam_shutdown(rctx); */
}
+static errno_t get_trusted_uids(struct pam_ctx *pctx)
+{
+ char *uid_str;
+ errno_t ret;
+
+ ret = confdb_get_string(pctx->rctx->cdb, pctx->rctx,
+ CONFDB_PAM_CONF_ENTRY, CONFDB_PAM_TRUSTED_USERS,
+ DEFAULT_ALLOWED_UIDS, &uid_str);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_FATAL_FAILURE, "Failed to get allowed UIDs.\n");
+ goto done;
+ }
+
+ if (strcmp(uid_str, ALL_UIDS_ALLOWED) == 0) {
+ DEBUG(SSSDBG_TRACE_FUNC, "All UIDs are allowed.\n");
+ pctx->trusted_uids_count = 0;
+ } else {
+ ret = csv_string_to_uid_array(pctx->rctx, uid_str, true,
+ &pctx->trusted_uids_count,
+ &pctx->trusted_uids);
+ }
+
+ talloc_free(uid_str);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_FATAL_FAILURE, "Failed to set allowed UIDs.\n");
+ goto done;
+ }
+
+done:
+ return ret;
+}
+
+static errno_t get_public_domains(TALLOC_CTX *mem_ctx, struct pam_ctx *pctx)
+{
+ char *domains_str = NULL;
+ errno_t ret;
+
+ ret = confdb_get_string(pctx->rctx->cdb, pctx->rctx,
+ CONFDB_PAM_CONF_ENTRY, CONFDB_PAM_PUBLIC_DOMAINS,
+ NO_DOMAIMS_ARE_PUBLIC, &domains_str);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_FATAL_FAILURE, "Failed to get allowed UIDs.\n");
+ goto done;
+ }
+
+ if (strcmp(domains_str, ALL_DOMAIMS_ARE_PUBLIC) == 0) { /* all */
+ /* copy all domains */
+ ret = get_dom_names(mem_ctx,
+ pctx->rctx->domains,
+ &pctx->public_domains,
+ &pctx->public_domains_count);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_FATAL_FAILURE, "get_dom_names failed.\n");
+ goto done;
+ }
+ } else if (strcmp(domains_str, NO_DOMAIMS_ARE_PUBLIC) == 0) { /* none */
+ pctx->public_domains = NULL;
+ pctx->public_domains_count = 0;
+ } else {
+ ret = split_on_separator(mem_ctx, domains_str, ',', true, false,
+ &pctx->public_domains,
+ &pctx->public_domains_count);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "split_on_separator failed [%d][%s].\n",
+ ret, strerror(ret));
+ goto done;
+ }
+ }
+
+ ret = EOK;
+
+done:
+ talloc_free(domains_str);
+ return ret;
+}
+
static int pam_process_init(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct confdb_ctx *cdb)
@@ -136,6 +216,20 @@ static int pam_process_init(TALLOC_CTX *mem_ctx,
pctx->rctx = rctx;
pctx->rctx->pvt_ctx = pctx;
+ ret = get_trusted_uids(pctx);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_FATAL_FAILURE, "get_trusted_uids failed: %d:[%s].\n",
+ ret, sss_strerror(ret));
+ goto done;
+ }
+
+ ret = get_public_domains(pctx, pctx);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_FATAL_FAILURE, "get_public_domains failed: %d:[%s].\n",
+ ret, sss_strerror(ret));
+ goto done;
+ }
+
/* Enable automatic reconnection to the Data Provider */
/* FIXME: "retries" is too generic, either get it from a global config
diff --git a/src/responder/pam/pamsrv.h b/src/responder/pam/pamsrv.h
index 1e37a77a1..f92e7f7db 100644
--- a/src/responder/pam/pamsrv.h
+++ b/src/responder/pam/pamsrv.h
@@ -37,6 +37,13 @@ struct pam_ctx {
int neg_timeout;
time_t id_timeout;
hash_table_t *id_table;
+ size_t trusted_uids_count;
+ uid_t *trusted_uids;
+ bool is_uid_trusted;
+
+ /* List of domains that are accessible even for untrusted users. */
+ char **public_domains;
+ int public_domains_count;
};
struct pam_auth_dp_req {
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);
}