summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/db/sysdb.h1
-rw-r--r--src/db/sysdb_selinux.c34
-rw-r--r--src/providers/ipa/ipa_session.c36
-rw-r--r--src/util/sss_selinux.c40
-rw-r--r--src/util/sss_selinux.h11
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);