summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJakub Hrozek <jhrozek@redhat.com>2013-01-06 23:52:19 +0100
committerJakub Hrozek <jhrozek@redhat.com>2013-01-08 20:15:55 +0100
commit7018d58ff66f41b95cd40afc7a0ad2afab10f1e7 (patch)
tree4e245714f27bf1487aee9f547a2a4d5eca68fde1 /src
parent2a0019b4c443da41cbb95627f3615f0743b40c3e (diff)
downloadsssd-7018d58ff66f41b95cd40afc7a0ad2afab10f1e7.tar.gz
sssd-7018d58ff66f41b95cd40afc7a0ad2afab10f1e7.tar.xz
sssd-7018d58ff66f41b95cd40afc7a0ad2afab10f1e7.zip
SELINUX: Process maps even when offline
Changes the ipa_get_selinux{send,recv} request so that it only delivers data and moves processing to the IPA selinux handler.
Diffstat (limited to 'src')
-rw-r--r--src/providers/ipa/ipa_selinux.c655
1 files changed, 429 insertions, 226 deletions
diff --git a/src/providers/ipa/ipa_selinux.c b/src/providers/ipa/ipa_selinux.c
index b64de90b1..909ef056c 100644
--- a/src/providers/ipa/ipa_selinux.c
+++ b/src/providers/ipa/ipa_selinux.c
@@ -37,52 +37,53 @@
#include "providers/ipa/ipa_selinux_common.h"
#include "providers/ipa/ipa_selinux_maps.h"
-struct ipa_get_selinux_state {
- struct be_req *be_req;
- struct pam_data *pd;
- struct ipa_selinux_ctx *selinux_ctx;
- struct sdap_id_op *op;
-
- const char *hostname;
- struct sysdb_attrs *host;
- struct sysdb_attrs *user;
-
- struct sysdb_attrs *defaults;
- struct sysdb_attrs **selinuxmaps;
- size_t nmaps;
-
- struct sysdb_attrs **possible_match;
- size_t possible_matches;
-};
-
-static struct
-tevent_req *ipa_get_selinux_send(struct be_req *breq,
- struct pam_data *pd,
- struct ipa_selinux_ctx *selinux_ctx);
-static void ipa_selinux_handler_done(struct tevent_req *subreq);
+static struct tevent_req *
+ipa_get_selinux_send(struct be_req *breq,
+ struct sysdb_attrs *user,
+ struct sysdb_attrs *host,
+ struct ipa_selinux_ctx *selinux_ctx);
static errno_t ipa_get_selinux_recv(struct tevent_req *req,
TALLOC_CTX *mem_ctx,
size_t *count,
struct sysdb_attrs ***maps,
+ size_t *hbac_count,
+ struct sysdb_attrs ***hbac_rules,
char **default_user,
char **map_order);
+static struct ipa_selinux_op_ctx *
+ipa_selinux_create_op_ctx(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb,
+ struct be_req *be_req, const char *username,
+ const char *hostname);
+static void ipa_selinux_handler_done(struct tevent_req *subreq);
+
static void ipa_get_selinux_connect_done(struct tevent_req *subreq);
static void ipa_get_selinux_hosts_done(struct tevent_req *subreq);
static void ipa_get_config_step(struct tevent_req *req);
static void ipa_get_selinux_config_done(struct tevent_req *subreq);
static void ipa_get_selinux_maps_done(struct tevent_req *subreq);
static void ipa_get_selinux_hbac_done(struct tevent_req *subreq);
-static int
-ipa_get_selinux_hbac_process(struct ipa_get_selinux_state *state,
- struct sysdb_attrs **rules,
- size_t rule_count);
+static errno_t ipa_selinux_process_maps(struct sysdb_attrs *user,
+ struct sysdb_attrs *host,
+ struct sysdb_attrs **selinux_maps,
+ size_t selinux_map_count,
+ struct sysdb_attrs **hbac_rules,
+ size_t hbac_rule_count);
+
+struct ipa_selinux_op_ctx {
+ struct be_req *be_req;
+
+ struct sysdb_attrs *user;
+ struct sysdb_attrs *host;
+};
void ipa_selinux_handler(struct be_req *be_req)
{
struct ipa_selinux_ctx *selinux_ctx;
+ struct ipa_selinux_op_ctx *op_ctx;
struct tevent_req *req;
struct pam_data *pd;
+ const char *hostname;
pd = talloc_get_type(be_req->req_data, struct pam_data);
@@ -90,23 +91,96 @@ void ipa_selinux_handler(struct be_req *be_req)
be_req->be_ctx->bet_info[BET_SELINUX].pvt_bet_data,
struct ipa_selinux_ctx);
+ hostname = dp_opt_get_string(selinux_ctx->id_ctx->ipa_options->basic,
+ IPA_HOSTNAME);
+ if (!hostname) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Cannot determine this machine's host name\n"));
+ goto fail;
+ }
- req = ipa_get_selinux_send(be_req, pd, selinux_ctx);
- if (req == NULL) {
+ op_ctx = ipa_selinux_create_op_ctx(be_req, be_req->sysdb, be_req,
+ pd->user, hostname);
+ if (op_ctx == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Cannot create op context\n"));
goto fail;
}
- tevent_req_set_callback(req, ipa_selinux_handler_done, be_req);
+ req = ipa_get_selinux_send(be_req, op_ctx->user, op_ctx->host, selinux_ctx);
+ if (req == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Cannot initiate the search\n"));
+ goto fail;
+ }
+ tevent_req_set_callback(req, ipa_selinux_handler_done, op_ctx);
return;
fail:
be_req->fn(be_req, DP_ERR_FATAL, PAM_SYSTEM_ERR, NULL);
}
+static struct ipa_selinux_op_ctx *
+ipa_selinux_create_op_ctx(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb,
+ struct be_req *be_req, const char *username,
+ const char *hostname)
+{
+ struct ipa_selinux_op_ctx *op_ctx;
+ struct ldb_dn *host_dn;
+ const char *attrs[] = { SYSDB_ORIG_DN,
+ SYSDB_ORIG_MEMBEROF,
+ NULL };
+ size_t count;
+ struct ldb_message **msgs;
+ struct sysdb_attrs **hosts;
+ errno_t ret;
+
+ op_ctx = talloc_zero(mem_ctx, struct ipa_selinux_op_ctx);
+ if (op_ctx == NULL) {
+ return NULL;
+ }
+ op_ctx->be_req = be_req;
+
+ ret = sss_selinux_extract_user(op_ctx, sysdb, username, &op_ctx->user);
+ if (ret != EOK) {
+ goto fail;
+ }
+
+ host_dn = sysdb_custom_dn(sysdb, op_ctx, hostname, HBAC_HOSTS_SUBDIR);
+ if (host_dn == NULL) {
+ goto fail;
+ }
+
+ /* Look up the host to get its originalMemberOf entries */
+ ret = sysdb_search_entry(op_ctx, sysdb, host_dn,
+ LDB_SCOPE_BASE, NULL,
+ attrs, &count, &msgs);
+ if (ret == ENOENT || count == 0) {
+ op_ctx->host = NULL;
+ return op_ctx;
+ } else if (ret != EOK) {
+ goto fail;
+ } else if (count > 1) {
+ DEBUG(SSSDBG_OP_FAILURE, ("More than one result for a BASE search!\n"));
+ goto fail;
+ }
+
+ ret = sysdb_msg2attrs(op_ctx, count, msgs, &hosts);
+ talloc_free(msgs);
+ if (ret != EOK) {
+ goto fail;
+ }
+
+ op_ctx->host = hosts[0];
+ return op_ctx;
+
+fail:
+ talloc_free(op_ctx);
+ return NULL;
+}
+
static void ipa_selinux_handler_done(struct tevent_req *req)
{
- struct be_req *breq = tevent_req_callback_data(req, struct be_req);
+ struct ipa_selinux_op_ctx *op_ctx = tevent_req_callback_data(req, struct ipa_selinux_op_ctx);
+ struct be_req *breq = op_ctx->be_req;
struct sysdb_ctx *sysdb = breq->be_ctx->sysdb;
errno_t ret, sret;
size_t map_count = 0;
@@ -115,13 +189,23 @@ static void ipa_selinux_handler_done(struct tevent_req *req)
char *default_user = NULL;
struct pam_data *pd = talloc_get_type(breq->req_data, struct pam_data);
char *map_order = NULL;
+ size_t hbac_count = 0;
+ struct sysdb_attrs **hbac_rules = 0;
ret = ipa_get_selinux_recv(req, breq, &map_count, &maps,
+ &hbac_count, &hbac_rules,
&default_user, &map_order);
if (ret != EOK) {
goto fail;
}
+ ret = ipa_selinux_process_maps(op_ctx->user, op_ctx->host,
+ maps, map_count,
+ hbac_rules, hbac_count);
+ if (ret != EOK) {
+ goto fail;
+ }
+
ret = sysdb_transaction_start(sysdb);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to start transaction\n"));
@@ -153,11 +237,8 @@ static void ipa_selinux_handler_done(struct tevent_req *req)
DEBUG(SSSDBG_OP_FAILURE, ("Could not commit transaction\n"));
goto fail;
}
-
- /* Just in case more code will follow after this place in the future */
in_transaction = false;
-
pd->pam_status = PAM_SUCCESS;
breq->fn(breq, DP_ERR_OK, EOK, "Success");
return;
@@ -176,9 +257,195 @@ fail:
}
}
-static struct tevent_req *ipa_get_selinux_send(struct be_req *breq,
- struct pam_data *pd,
- struct ipa_selinux_ctx *selinux_ctx)
+static errno_t
+ipa_selinux_process_seealso_maps(struct sysdb_attrs *user,
+ struct sysdb_attrs *host,
+ struct sysdb_attrs **seealso_rules,
+ size_t seealso_rules_count,
+ struct sysdb_attrs **hbac_rules,
+ size_t hbac_rule_count);
+static errno_t
+ipa_selinux_process_maps(struct sysdb_attrs *user,
+ struct sysdb_attrs *host,
+ struct sysdb_attrs **selinux_maps,
+ size_t selinux_map_count,
+ struct sysdb_attrs **hbac_rules,
+ size_t hbac_rule_count)
+{
+ TALLOC_CTX *tmp_ctx;
+ int i;
+ errno_t ret;
+ uint32_t priority = 0;
+ struct sysdb_attrs **seealso_rules;
+ size_t num_seealso_rules;
+ const char *seealso_str;
+
+ tmp_ctx = talloc_new(NULL);
+ if (!tmp_ctx) {
+ return ENOMEM;
+ }
+
+ seealso_rules = talloc_zero_array(tmp_ctx, struct sysdb_attrs *,
+ selinux_map_count + 1);
+ if (seealso_rules == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ num_seealso_rules = 0;
+
+ for (i = 0; i < selinux_map_count; i++) {
+ if (sss_selinux_match(selinux_maps[i], user,
+ host, &priority)) {
+ priority &= ~(SELINUX_PRIORITY_USER_NAME |
+ SELINUX_PRIORITY_USER_GROUP |
+ SELINUX_PRIORITY_USER_CAT);
+ ret = sysdb_attrs_add_uint32(selinux_maps[i],
+ SYSDB_SELINUX_HOST_PRIORITY,
+ priority);
+ if (ret != EOK) {
+ goto done;
+ }
+ continue;
+ }
+
+ ret = sysdb_attrs_get_string(selinux_maps[i],
+ SYSDB_SELINUX_SEEALSO, &seealso_str);
+ if (ret == ENOENT) {
+ continue;
+ } else if (ret != EOK) {
+ goto done;
+ }
+
+ seealso_rules[num_seealso_rules] = selinux_maps[i];
+ num_seealso_rules++;
+ }
+
+ ret = ipa_selinux_process_seealso_maps(user, host,
+ seealso_rules, num_seealso_rules,
+ hbac_rules, hbac_rule_count);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ ret = EOK;
+done:
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+static errno_t
+ipa_selinux_process_seealso_maps(struct sysdb_attrs *user,
+ struct sysdb_attrs *host,
+ struct sysdb_attrs **seealso_rules,
+ size_t seealso_rules_count,
+ struct sysdb_attrs **hbac_rules,
+ size_t hbac_rule_count)
+{
+ int i, j;
+ errno_t ret;
+ struct ldb_message_element *el;
+ uint32_t priority = 0;
+ struct sysdb_attrs *usermap;
+ const char *seealso_dn;
+ const char *hbac_dn;
+
+ for (i = 0; i < hbac_rule_count; i++) {
+ ret = sysdb_attrs_get_string(hbac_rules[i], SYSDB_ORIG_DN, &hbac_dn);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ /* We need to do this translation for further processing. We have to
+ * do it manually because no map was used to retrieve HBAC rules.
+ */
+ ret = sysdb_attrs_get_el(hbac_rules[i], IPA_MEMBER_HOST, &el);
+ if (ret != EOK) return ret;
+ el->name = SYSDB_ORIG_MEMBER_HOST;
+
+ ret = sysdb_attrs_get_el(hbac_rules[i], IPA_MEMBER_USER, &el);
+ if (ret != EOK) return ret;
+ el->name = SYSDB_ORIG_MEMBER_USER;
+
+ DEBUG(SSSDBG_TRACE_ALL,
+ ("Matching HBAC rule %s with SELinux mappings\n", hbac_dn));
+
+ if (!sss_selinux_match(hbac_rules[i], user, host, &priority)) {
+ DEBUG(SSSDBG_TRACE_ALL, ("Rule did not match\n"));
+ continue;
+ }
+
+ /* HBAC rule matched, find if it is in the "possible" list */
+ for (j = 0; j < seealso_rules_count; j++) {
+ usermap = seealso_rules[j];
+ if (usermap == NULL) {
+ continue;
+ }
+
+ ret = sysdb_attrs_get_string(usermap, SYSDB_SELINUX_SEEALSO, &seealso_dn);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ if (strcasecmp(hbac_dn, seealso_dn) == 0) {
+ DEBUG(SSSDBG_TRACE_FUNC, ("HBAC rule [%s] matched, copying its"
+ "attributes to SELinux user map [%s]\n",
+ hbac_dn, seealso_dn));
+ priority &= ~(SELINUX_PRIORITY_USER_NAME |
+ SELINUX_PRIORITY_USER_GROUP |
+ SELINUX_PRIORITY_USER_CAT);
+ ret = sysdb_attrs_add_uint32(usermap,
+ SYSDB_SELINUX_HOST_PRIORITY,
+ priority);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ ret = sysdb_attrs_copy_values(hbac_rules[i], usermap, SYSDB_ORIG_MEMBER_USER);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ ret = sysdb_attrs_copy_values(hbac_rules[i], usermap, SYSDB_USER_CATEGORY);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ /* Speed up the next iteration */
+ seealso_rules[j] = NULL;
+ }
+ }
+ }
+
+ return EOK;
+}
+
+/* A more generic request to gather all SELinux and HBAC rules. Updates
+ * cache if necessary
+ */
+struct ipa_get_selinux_state {
+ struct be_req *be_req;
+ struct ipa_selinux_ctx *selinux_ctx;
+ struct sdap_id_op *op;
+
+ struct sysdb_attrs *host;
+ struct sysdb_attrs *user;
+
+ struct sysdb_attrs *defaults;
+ struct sysdb_attrs **selinuxmaps;
+ size_t nmaps;
+
+ struct sysdb_attrs **hbac_rules;
+ size_t hbac_rule_count;
+};
+
+static errno_t
+ipa_get_selinux_maps_offline(struct tevent_req *req);
+
+static struct tevent_req *
+ipa_get_selinux_send(struct be_req *breq,
+ struct sysdb_attrs *user,
+ struct sysdb_attrs *host,
+ struct ipa_selinux_ctx *selinux_ctx)
{
struct tevent_req *req;
struct tevent_req *subreq;
@@ -194,8 +461,9 @@ static struct tevent_req *ipa_get_selinux_send(struct be_req *breq,
}
state->be_req = breq;
- state->pd = pd;
state->selinux_ctx = selinux_ctx;
+ state->user = user;
+ state->host = host;
offline = be_is_offline(bctx);
DEBUG(SSSDBG_TRACE_INTERNAL, ("Connection status is [%s].\n",
@@ -219,7 +487,7 @@ static struct tevent_req *ipa_get_selinux_send(struct be_req *breq,
tevent_req_set_callback(subreq, ipa_get_selinux_connect_done, req);
} else {
- ret = EAGAIN;
+ ret = ipa_get_selinux_maps_offline(req);
goto immediate;
}
@@ -248,67 +516,45 @@ static void ipa_get_selinux_connect_done(struct tevent_req *subreq)
const char *access_name;
const char *selinux_name;
- struct ldb_dn *host_dn;
- const char *attrs[] = { SYSDB_ORIG_DN,
- SYSDB_ORIG_MEMBEROF,
- NULL };
- size_t count;
- struct ldb_message **msgs;
- struct sysdb_attrs **hosts;
+ const char *hostname;
ret = sdap_id_op_connect_recv(subreq, &dp_error);
talloc_zfree(subreq);
if (dp_error == DP_ERR_OFFLINE) {
talloc_zfree(state->op);
- ret = EAGAIN;
+ ret = ipa_get_selinux_maps_offline(req);
+ if (ret == EOK) {
+ tevent_req_done(req);
+ return;
+ }
+ goto fail;
}
if (ret != EOK) {
goto fail;
}
- state->hostname = dp_opt_get_string(state->selinux_ctx->id_ctx->ipa_options->basic,
- IPA_HOSTNAME);
-
access_name = state->be_req->be_ctx->bet_info[BET_ACCESS].mod_name;
selinux_name = state->be_req->be_ctx->bet_info[BET_SELINUX].mod_name;
- if (strcasecmp(access_name, selinux_name) == 0) {
- host_dn = sysdb_custom_dn(bctx->sysdb, state, state->hostname, HBAC_HOSTS_SUBDIR);
- if (host_dn == NULL) {
- ret = ENOMEM;
- goto fail;
- }
-
- /* Look up the host to get its originalMemberOf entries */
- ret = sysdb_search_entry(state, bctx->sysdb, host_dn,
- LDB_SCOPE_BASE, NULL,
- attrs, &count, &msgs);
- if (ret == ENOENT || count == 0) {
- /* We need to query the server */
- goto server;
- } else if (ret != EOK) {
- goto fail;
- } else if (count > 1) {
- DEBUG(SSSDBG_OP_FAILURE, ("More than one result for a BASE search!\n"));
- ret = EIO;
- goto fail;
- }
-
- ret = sysdb_msg2attrs(state, count, msgs, &hosts);
- if (ret != EOK) {
- goto fail;
- }
-
- state->host = hosts[0];
+ if (strcasecmp(access_name, selinux_name) == 0 && state->host != NULL) {
+ /* If the access control module is the same as the selinux module
+ * and the access control had already discovered the host
+ */
return ipa_get_config_step(req);
}
-server:
+ hostname = dp_opt_get_string(state->selinux_ctx->id_ctx->ipa_options->basic,
+ IPA_HOSTNAME);
+ if (hostname == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot determine the host name\n"));
+ goto fail;
+ }
+
subreq = ipa_host_info_send(state, bctx->ev, bctx->sysdb,
sdap_id_op_handle(state->op),
id_ctx->sdap_id_ctx->opts,
- state->hostname,
+ hostname,
id_ctx->ipa_options->host_map,
NULL,
state->selinux_ctx->host_search_bases);
@@ -318,13 +564,92 @@ server:
}
tevent_req_set_callback(subreq, ipa_get_selinux_hosts_done, req);
-
return;
fail:
tevent_req_error(req, ret);
}
+static errno_t
+ipa_get_selinux_maps_offline(struct tevent_req *req)
+{
+ errno_t ret;
+ size_t nmaps;
+ struct ldb_message **maps;
+ struct ldb_message *defaults;
+ const char *attrs[] = { SYSDB_NAME,
+ SYSDB_USER_CATEGORY,
+ SYSDB_HOST_CATEGORY,
+ SYSDB_ORIG_MEMBER_USER,
+ SYSDB_ORIG_MEMBER_HOST,
+ SYSDB_SELINUX_SEEALSO,
+ SYSDB_SELINUX_USER,
+ NULL };
+ const char *default_user;
+ const char *order;
+
+ struct ipa_get_selinux_state *state = tevent_req_data(req,
+ struct ipa_get_selinux_state);
+
+ /* read the config entry */
+ ret = sysdb_search_selinux_config(state, state->be_req->be_ctx->sysdb,
+ NULL, &defaults);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("sysdb_search_selinux_config failed [%d]: %s\n",
+ ret, strerror(ret)));
+ return ret;
+ }
+
+ default_user = ldb_msg_find_attr_as_string(defaults,
+ SYSDB_SELINUX_DEFAULT_USER,
+ NULL);
+ order = ldb_msg_find_attr_as_string(defaults, SYSDB_SELINUX_DEFAULT_ORDER,
+ NULL);
+
+ state->defaults = sysdb_new_attrs(state);
+ if (state->defaults == NULL) {
+ return ENOMEM;
+ }
+
+ ret = sysdb_attrs_add_string(state->defaults,
+ IPA_CONFIG_SELINUX_DEFAULT_MAP, default_user);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ ret = sysdb_attrs_add_string(state->defaults,
+ IPA_CONFIG_SELINUX_MAP_ORDER, order);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ /* read all the SELinux rules */
+ ret = sysdb_get_selinux_usermaps(state, state->be_req->be_ctx->sysdb,
+ attrs, &nmaps, &maps);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("sysdb_get_selinux_usermaps failed [%d]: %s\n",
+ ret, strerror(ret)));
+ return ret;
+ }
+
+ ret = sysdb_msg2attrs(state, nmaps, maps, &state->selinuxmaps);
+ if (ret != EOK) {
+ return ret;
+ }
+ state->nmaps = nmaps;
+
+ /* read all the HBAC rules */
+ ret = hbac_get_cached_rules(state, state->be_req->be_ctx->sysdb,
+ &state->hbac_rule_count, &state->hbac_rules);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("hbac_get_cached_rules failed [%d]: %s\n",
+ ret, strerror(ret)));
+ return ret;
+ }
+
+ return EOK;
+}
+
static void ipa_get_selinux_hosts_done(struct tevent_req *subreq)
{
errno_t ret;
@@ -354,7 +679,6 @@ done:
static void ipa_get_config_step(struct tevent_req *req)
{
- errno_t ret;
const char *domain;
struct tevent_req *subreq;
struct ipa_get_selinux_state *state = tevent_req_data(req,
@@ -362,13 +686,6 @@ static void ipa_get_config_step(struct tevent_req *req)
struct be_ctx *bctx = state->be_req->be_ctx;
struct ipa_id_ctx *id_ctx = state->selinux_ctx->id_ctx;
- ret = sss_selinux_extract_user(state, bctx->sysdb,
- state->pd->user, &state->user);
- if (ret != EOK) {
- tevent_req_error(req, ret);
- return;
- }
-
domain = dp_opt_get_string(state->selinux_ctx->id_ctx->ipa_options->basic,
IPA_KRB5_REALM);
subreq = ipa_get_config_send(state, bctx->ev,
@@ -428,11 +745,9 @@ static void ipa_get_selinux_maps_done(struct tevent_req *subreq)
char *selinux_name;
char *access_name;
- struct sysdb_attrs **rules;
- size_t rule_count;
const char *tmp_str;
- uint32_t priority = 0;
+ bool check_hbac;
errno_t ret;
int i;
@@ -456,54 +771,29 @@ static void ipa_get_selinux_maps_done(struct tevent_req *subreq)
DEBUG(SSSDBG_TRACE_FUNC,
("Found %d SELinux user maps\n", state->nmaps));
- state->possible_match = talloc_zero_array(state, struct sysdb_attrs *,
- state->nmaps + 1);
- if (state->possible_match == NULL) {
- ret = ENOMEM;
- goto done;
- }
+ check_hbac = false;
for (i = 0; i < state->nmaps; i++) {
- if (sss_selinux_match(state->selinuxmaps[i], state->user,
- state->host, &priority)) {
- priority &= ~(SELINUX_PRIORITY_USER_NAME |
- SELINUX_PRIORITY_USER_GROUP |
- SELINUX_PRIORITY_USER_CAT);
- ret = sysdb_attrs_add_uint32(state->selinuxmaps[i],
- SYSDB_SELINUX_HOST_PRIORITY,
- priority);
- if (ret != EOK) {
- goto done;
- }
- continue;
- }
-
ret = sysdb_attrs_get_string(state->selinuxmaps[i],
SYSDB_SELINUX_SEEALSO, &tmp_str);
- if (ret == ENOENT) {
- continue;
+ if (ret == EOK) {
+ check_hbac = true;
+ break;
}
-
- state->possible_match[state->possible_matches] = state->selinuxmaps[i];
- state->possible_matches++;
}
- if (state->possible_matches) {
+ if (check_hbac) {
access_name = state->be_req->be_ctx->bet_info[BET_ACCESS].mod_name;
selinux_name = state->be_req->be_ctx->bet_info[BET_SELINUX].mod_name;
if (strcasecmp(access_name, selinux_name) == 0) {
ret = hbac_get_cached_rules(state, state->be_req->be_ctx->sysdb,
- &rule_count, &rules);
- if (ret != EOK) {
- goto done;
- }
-
- ret = ipa_get_selinux_hbac_process(state, rules, rule_count);
+ &state->hbac_rule_count, &state->hbac_rules);
+ /* Terminates the request */
goto done;
}
- DEBUG(SSSDBG_TRACE_FUNC, ("%d SELinux maps referenced an HBAC rule. "
- "Need to refresh HBAC rules\n", state->possible_matches));
+ DEBUG(SSSDBG_TRACE_FUNC, ("SELinux maps referenced an HBAC rule. "
+ "Need to refresh HBAC rules\n"));
subreq = ipa_hbac_rule_info_send(state, false, bctx->ev,
sdap_id_op_handle(state->op),
id_ctx->sdap_id_ctx->opts,
@@ -533,22 +823,14 @@ static void ipa_get_selinux_hbac_done(struct tevent_req *subreq)
struct tevent_req);
struct ipa_get_selinux_state *state = tevent_req_data(req,
struct ipa_get_selinux_state);
- struct sysdb_attrs **rules;
- size_t rule_count;
errno_t ret;
- ret = ipa_hbac_rule_info_recv(subreq, state, &rule_count,
- &rules);
+ ret = ipa_hbac_rule_info_recv(subreq, state, &state->hbac_rule_count,
+ &state->hbac_rules);
DEBUG(SSSDBG_TRACE_INTERNAL,
- ("Received %d HBAC rules\n", rule_count));
+ ("Received %d HBAC rules\n", state->hbac_rule_count));
talloc_free(subreq);
- if (ret != EOK) {
- goto done;
- }
-
- ret = ipa_get_selinux_hbac_process(state, rules, rule_count);
-done:
if (ret != EOK) {
tevent_req_error(req, ret);
} else {
@@ -556,100 +838,13 @@ done:
}
}
-static int
-ipa_get_selinux_hbac_process(struct ipa_get_selinux_state *state,
- struct sysdb_attrs **rules,
- size_t rule_count)
-{
- int i, j;
- errno_t ret;
- uint32_t priority = 0;
- const char *hbac_dn;
- const char *seealso_dn;
- struct sysdb_attrs *usermap;
- struct ldb_message_element *el;
-
- for (i = 0; i < rule_count; i++) {
- ret = sysdb_attrs_get_string(rules[i], SYSDB_ORIG_DN, &hbac_dn);
- if (ret != EOK) {
- goto done;
- }
-
- /* We need to do this translation for further processing. We have to
- * do it manually because no map was used to retrieve HBAC rules.
- */
- ret = sysdb_attrs_get_el(rules[i], IPA_MEMBER_HOST, &el);
- if (ret != EOK) goto done;
- el->name = SYSDB_ORIG_MEMBER_HOST;
-
- ret = sysdb_attrs_get_el(rules[i], IPA_MEMBER_USER, &el);
- if (ret != EOK) goto done;
- el->name = SYSDB_ORIG_MEMBER_USER;
-
- DEBUG(SSSDBG_TRACE_ALL,
- ("Matching HBAC rule %s with SELinux mappings\n", hbac_dn));
-
- if (!sss_selinux_match(rules[i], state->user, state->host, &priority)) {
- DEBUG(SSSDBG_TRACE_ALL, ("Rule did not match\n"));
- continue;
- }
-
-
- /* HBAC rule matched, find if it is in the "possible" list */
- for (j = 0; j < state->possible_matches; j++) {
- usermap = state->possible_match[j];
- if (usermap == NULL) {
- continue;
- }
-
- ret = sysdb_attrs_get_string(usermap, SYSDB_SELINUX_SEEALSO, &seealso_dn);
- if (ret != EOK) {
- goto done;
- }
-
- if (strcasecmp(hbac_dn, seealso_dn) == 0) {
- DEBUG(SSSDBG_TRACE_FUNC, ("HBAC rule [%s] matched, copying its"
- "attributes to SELinux user map [%s]\n",
- hbac_dn, seealso_dn));
- priority &= ~(SELINUX_PRIORITY_USER_NAME |
- SELINUX_PRIORITY_USER_GROUP |
- SELINUX_PRIORITY_USER_CAT);
- ret = sysdb_attrs_add_uint32(usermap,
- SYSDB_SELINUX_HOST_PRIORITY,
- priority);
- if (ret != EOK) {
- goto done;
- }
-
- ret = sysdb_attrs_copy_values(rules[i], usermap, SYSDB_ORIG_MEMBER_USER);
- if (ret != EOK) {
- goto done;
- }
-
- ret = sysdb_attrs_copy_values(rules[i], usermap, SYSDB_USER_CATEGORY);
- if (ret != EOK) {
- goto done;
- }
-
- /* Just to boost the following lookup */
- state->possible_match[j] = NULL;
- }
- }
- }
-
- /* Now we can dispose all possible rules, since they aren't possible any more */
- talloc_zfree(state->possible_match);
-
- ret = EOK;
-done:
- return ret;
-}
-
static errno_t
ipa_get_selinux_recv(struct tevent_req *req,
TALLOC_CTX *mem_ctx,
size_t *count,
struct sysdb_attrs ***maps,
+ size_t *hbac_count,
+ struct sysdb_attrs ***hbac_rules,
char **default_user,
char **map_order)
{
@@ -698,5 +893,13 @@ ipa_get_selinux_recv(struct tevent_req *req,
*maps = NULL;
}
+ if (state->hbac_rules != NULL) {
+ *hbac_count = state->hbac_rule_count;
+ *hbac_rules = talloc_steal(mem_ctx, state->hbac_rules);
+ } else {
+ *hbac_count = 0;
+ *hbac_rules = NULL;
+ }
+
return EOK;
}