diff options
-rw-r--r-- | src/db/sysdb.h | 1 | ||||
-rw-r--r-- | src/db/sysdb_selinux.c | 34 | ||||
-rw-r--r-- | src/providers/ipa/ipa_session.c | 36 | ||||
-rw-r--r-- | src/util/sss_selinux.c | 40 | ||||
-rw-r--r-- | src/util/sss_selinux.h | 11 |
5 files changed, 113 insertions, 9 deletions
diff --git a/src/db/sysdb.h b/src/db/sysdb.h index 5baac98b3..3c6166cf4 100644 --- a/src/db/sysdb.h +++ b/src/db/sysdb.h @@ -120,6 +120,7 @@ #define SYSDB_SELINUX_SEEALSO "seeAlso" #define SYSDB_SELINUX_USER "selinuxUser" #define SYSDB_SELINUX_ENABLED "enabled" +#define SYSDB_SELINUX_HOST_PRIORITY "hostPriority" #define SYSDB_CACHEDPWD "cachedPassword" diff --git a/src/db/sysdb_selinux.c b/src/db/sysdb_selinux.c index e9f2da11b..8e69cd3e2 100644 --- a/src/db/sysdb_selinux.c +++ b/src/db/sysdb_selinux.c @@ -341,6 +341,7 @@ errno_t sysdb_search_selinux_usermap_by_username(TALLOC_CTX *mem_ctx, SYSDB_HOST_CATEGORY, SYSDB_ORIG_MEMBER_USER, SYSDB_ORIG_MEMBER_HOST, + SYSDB_SELINUX_HOST_PRIORITY, SYSDB_SELINUX_USER, NULL }; struct ldb_message **msgs = NULL; @@ -351,6 +352,9 @@ errno_t sysdb_search_selinux_usermap_by_username(TALLOC_CTX *mem_ctx, struct ldb_dn *basedn; size_t msgs_count = 0; size_t usermaps_cnt; + uint32_t priority = 0; + uint32_t host_priority = 0; + uint32_t top_priority = 0; char *filter; errno_t ret; int i; @@ -405,7 +409,35 @@ errno_t sysdb_search_selinux_usermap_by_username(TALLOC_CTX *mem_ctx, tmp_attrs->a = msgs[i]->elements; tmp_attrs->num = msgs[i]->num_elements; - if (sss_selinux_match(tmp_attrs, user, NULL)) { + if (sss_selinux_match(tmp_attrs, user, NULL, &priority)) { + priority &= ~(SELINUX_PRIORITY_HOST_NAME | + SELINUX_PRIORITY_HOST_GROUP | + SELINUX_PRIORITY_HOST_CAT); + + /* Now figure out host priority */ + ret = sysdb_attrs_get_uint32_t(tmp_attrs, + SYSDB_SELINUX_HOST_PRIORITY, + &host_priority); + if (ret != EOK) { + continue; + } + + priority += host_priority; + if (priority < top_priority) { + /* This rule has lower priority than what we already have, + * skip it */ + continue; + } else if (priority > top_priority) { + /* If the rule has higher priority, drop what we already + * have */ + while (usermaps_cnt > 0) { + usermaps_cnt--; + talloc_zfree(usermaps[usermaps_cnt]); + } + top_priority = priority; + } + + usermaps[usermaps_cnt] = talloc_steal(usermaps, msgs[i]); usermaps_cnt++; } else { diff --git a/src/providers/ipa/ipa_session.c b/src/providers/ipa/ipa_session.c index 238acdde7..12e807297 100644 --- a/src/providers/ipa/ipa_session.c +++ b/src/providers/ipa/ipa_session.c @@ -326,6 +326,7 @@ static void ipa_get_selinux_maps_done(struct tevent_req *subreq) const char *tmp_str; size_t conf_cnt = 0; size_t pos_cnt = 0; + uint32_t priority = 0; errno_t ret; int i; @@ -358,7 +359,17 @@ static void ipa_get_selinux_maps_done(struct tevent_req *subreq) } for (i = 0; i < count; i++) { - if (sss_selinux_match(results[i], state->user, state->host)) { + if (sss_selinux_match(results[i], state->user, state->host, &priority)) { + priority &= ~(SELINUX_PRIORITY_USER_NAME | + SELINUX_PRIORITY_USER_GROUP | + SELINUX_PRIORITY_USER_CAT); + ret = sysdb_attrs_add_uint32(results[i], + SYSDB_SELINUX_HOST_PRIORITY, + priority); + if (ret != EOK) { + goto done; + } + state->confirmed_match[conf_cnt] = talloc_steal(state->confirmed_match, results[i]); conf_cnt++; @@ -445,6 +456,7 @@ static void ipa_get_selinux_hbac_done(struct tevent_req *subreq) size_t rule_count; size_t conf_cnt; size_t pos_cnt; + uint32_t priority = 0; errno_t ret; int i, j; @@ -458,7 +470,7 @@ static void ipa_get_selinux_hbac_done(struct tevent_req *subreq) for (pos_cnt = 0 ; state->possible_match[pos_cnt]; pos_cnt++) ; for (i = 0; i < rule_count; i++) { - if (!sss_selinux_match(rules[i], state->user, state->host)) { + if (!sss_selinux_match(rules[i], state->user, state->host, &priority)) { continue; } @@ -480,6 +492,26 @@ static void ipa_get_selinux_hbac_done(struct tevent_req *subreq) } if (strcasecmp(hbac_dn, seealso_dn) == 0) { + 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; + } + state->confirmed_match[conf_cnt++] = talloc_steal( state->confirmed_match, usermap); diff --git a/src/util/sss_selinux.c b/src/util/sss_selinux.c index bdb117951..7b2417bbe 100644 --- a/src/util/sss_selinux.c +++ b/src/util/sss_selinux.c @@ -49,7 +49,8 @@ static bool match_entity(struct ldb_message_element *values, bool sss_selinux_match(struct sysdb_attrs *usermap, struct sysdb_attrs *user, - struct sysdb_attrs *host) + struct sysdb_attrs *host, + uint32_t *_priority) { struct ldb_message_element *users_el = NULL; struct ldb_message_element *usercat = NULL; @@ -58,6 +59,9 @@ bool sss_selinux_match(struct sysdb_attrs *usermap, struct ldb_message_element *dn; struct ldb_message_element *memberof; int i; + uint32_t priority = 0; + bool matched_name; + bool matched_group; errno_t ret; if (usermap == NULL) { @@ -90,10 +94,21 @@ bool sss_selinux_match(struct sysdb_attrs *usermap, */ if (usercat == NULL || usercat->num_values == 0 || strcasecmp((char *)usercat->values[0].data, "all") != 0) { - if (users_el == NULL || (!match_entity(users_el, dn) && - !match_entity(users_el, memberof))) { + if (users_el == NULL) { return false; + } else { + matched_name = match_entity(users_el, dn); + matched_group = match_entity(users_el, memberof); + if (matched_name) { + priority |= SELINUX_PRIORITY_USER_NAME; + } else if (matched_group) { + priority |= SELINUX_PRIORITY_USER_GROUP; + } else { + return false; + } } + } else { + priority |= SELINUX_PRIORITY_USER_CAT; } } @@ -109,11 +124,26 @@ bool sss_selinux_match(struct sysdb_attrs *usermap, */ if (hostcat == NULL || hostcat->num_values == 0 || strcasecmp((char *)hostcat->values[0].data, "all") != 0) { - if (hosts_el == NULL || (!match_entity(hosts_el, dn) && - !match_entity(hosts_el, memberof))) { + if (hosts_el == NULL) { return false; + } else { + matched_name = match_entity(hosts_el, dn); + matched_group = match_entity(hosts_el, memberof); + if (matched_name) { + priority |= SELINUX_PRIORITY_HOST_NAME; + } else if (matched_group) { + priority |= SELINUX_PRIORITY_HOST_GROUP; + } else { + return false; + } } } + } else { + priority |= SELINUX_PRIORITY_HOST_CAT; + } + + if (_priority != NULL) { + *_priority = priority; } return true; diff --git a/src/util/sss_selinux.h b/src/util/sss_selinux.h index 11a5445e6..def389400 100644 --- a/src/util/sss_selinux.h +++ b/src/util/sss_selinux.h @@ -30,6 +30,14 @@ #include <db/sysdb.h> +#define SELINUX_PRIORITY_USER_CAT 1 +#define SELINUX_PRIORITY_USER_GROUP 2 +#define SELINUX_PRIORITY_USER_NAME 4 +/* According to specification, host has higher priority */ +#define SELINUX_PRIORITY_HOST_CAT 8 +#define SELINUX_PRIORITY_HOST_GROUP 16 +#define SELINUX_PRIORITY_HOST_NAME 32 + errno_t sss_selinux_extract_user(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb, @@ -38,7 +46,8 @@ sss_selinux_extract_user(TALLOC_CTX *mem_ctx, bool sss_selinux_match(struct sysdb_attrs *usermap, struct sysdb_attrs *user, - struct sysdb_attrs *host); + struct sysdb_attrs *host, + uint32_t *_priority); const char *sss_selinux_map_get_seuser(struct ldb_message *usermap); |