From a72e9289fe001c85a17acd667ca31d692fd99605 Mon Sep 17 00:00:00 2001 From: Stephen Gallagher Date: Fri, 29 Jul 2011 15:03:14 -0400 Subject: Add rule validator to libipa_hbac https://fedorahosted.org/sssd/ticket/943 --- Makefile.am | 2 +- src/providers/ipa/hbac_evaluator.c | 51 ++++++++++++++++ src/providers/ipa/ipa_hbac.h | 23 ++++++++ src/tests/ipa_hbac-tests.c | 115 +++++++++++++++++++++++++++++++++++++ 4 files changed, 190 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 6647528c8..1df6d985f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -378,7 +378,7 @@ dist_pkgconfig_DATA += src/providers/ipa/ipa_hbac.pc libipa_hbac_la_SOURCES = \ src/providers/ipa/hbac_evaluator.c libipa_hbac_la_LDFLAGS = \ - -version 0:1:0 \ + -version 1:0:1 \ -lunistring include_HEADERS = \ diff --git a/src/providers/ipa/hbac_evaluator.c b/src/providers/ipa/hbac_evaluator.c index ee39a09ae..476ad6482 100644 --- a/src/providers/ipa/hbac_evaluator.c +++ b/src/providers/ipa/hbac_evaluator.c @@ -52,6 +52,57 @@ enum hbac_eval_result_int { HBAC_EVAL_UNMATCHED }; +static bool hbac_rule_element_is_complete(struct hbac_rule_element *el) +{ + if (el == NULL) return false; + if (el->category == HBAC_CATEGORY_ALL) return true; + + if (el->names == NULL && el->groups == NULL) return false; + + if ((el->names && el->names[0] != NULL) + || (el->groups && el->groups[0] != NULL)) + return true; + + /* If other categories are added, handle them here */ + + return false; +} + +bool hbac_rule_is_complete(struct hbac_rule *rule, uint32_t *missing_attrs) +{ + bool complete = true; + + *missing_attrs = 0; + + if (rule == NULL) { + /* No rule passed in? */ + return false; + } + + /* Make sure we have all elements */ + if (!hbac_rule_element_is_complete(rule->users)) { + complete = false; + *missing_attrs |= HBAC_RULE_ELEMENT_USERS; + } + + if (!hbac_rule_element_is_complete(rule->services)) { + complete = false; + *missing_attrs |= HBAC_RULE_ELEMENT_SERVICES; + } + + if (!hbac_rule_element_is_complete(rule->targethosts)) { + complete = false; + *missing_attrs |= HBAC_RULE_ELEMENT_TARGETHOSTS; + } + + if (!hbac_rule_element_is_complete(rule->srchosts)) { + complete = false; + *missing_attrs |= HBAC_RULE_ELEMENT_SOURCEHOSTS; + } + + return complete; +} + enum hbac_eval_result_int hbac_evaluate_rule(struct hbac_rule *rule, struct hbac_eval_req *hbac_req, enum hbac_error_code *error); diff --git a/src/providers/ipa/ipa_hbac.h b/src/providers/ipa/ipa_hbac.h index a1d513785..7de49d1ff 100644 --- a/src/providers/ipa/ipa_hbac.h +++ b/src/providers/ipa/ipa_hbac.h @@ -151,4 +151,27 @@ const char *hbac_error_string(enum hbac_error_code code); void hbac_free_info(struct hbac_info *info); + +#define HBAC_RULE_ELEMENT_USERS 0x01 +#define HBAC_RULE_ELEMENT_SERVICES 0x02 +#define HBAC_RULE_ELEMENT_TARGETHOSTS 0x04 +#define HBAC_RULE_ELEMENT_SOURCEHOSTS 0x08 + +/** + * @brief Evaluate whether an HBAC rule contains all necessary elements + * + * @param[in] rule An HBAC rule to evaluate + * @param[out] missing_attrs A list of attributes missing from the rule + * This is a bitmask that may contain one or more + * of HBAC_RULE_ELEMENT_USERS, + * HBAC_RULE_ELEMENT_SERVICES, + * HBAC_RULE_ELEMENT_TARGETHOSTS and + * HBAC_RULE_ELEMENT_SOURCEHOSTS + * + * @return True if the rule contains all mandatory attributes + * + * @note This function does not care if the rule is enabled or disabled + */ +bool hbac_rule_is_complete(struct hbac_rule *rule, uint32_t *missing_attrs); + #endif /* IPA_HBAC_H_ */ diff --git a/src/tests/ipa_hbac-tests.c b/src/tests/ipa_hbac-tests.c index d3d803875..330e49e7c 100644 --- a/src/tests/ipa_hbac-tests.c +++ b/src/tests/ipa_hbac-tests.c @@ -188,6 +188,8 @@ START_TEST(ipa_hbac_test_allow_all) struct hbac_rule **rules; struct hbac_eval_req *eval_req; struct hbac_info *info; + bool is_valid; + uint32_t missing_attrs; test_ctx = talloc_new(global_talloc_context); @@ -208,6 +210,11 @@ START_TEST(ipa_hbac_test_allow_all) fail_if(rules[0]->name == NULL); rules[1] = NULL; + /* Validate this rule */ + is_valid = hbac_rule_is_complete(rules[0], &missing_attrs); + fail_unless(is_valid); + fail_unless(missing_attrs == 0); + /* Evaluate the rules */ result = hbac_evaluate(rules, eval_req, &info); fail_unless(result == HBAC_EVAL_ALLOW, @@ -228,6 +235,8 @@ START_TEST(ipa_hbac_test_allow_user) struct hbac_rule **rules; struct hbac_eval_req *eval_req; struct hbac_info *info; + bool is_valid; + uint32_t missing_attrs; test_ctx = talloc_new(global_talloc_context); @@ -258,6 +267,11 @@ START_TEST(ipa_hbac_test_allow_user) rules[1] = NULL; + /* Validate this rule */ + is_valid = hbac_rule_is_complete(rules[0], &missing_attrs); + fail_unless(is_valid); + fail_unless(missing_attrs == 0); + /* Evaluate the rules */ result = hbac_evaluate(rules, eval_req, &info); fail_unless(result == HBAC_EVAL_ALLOW, @@ -270,6 +284,11 @@ START_TEST(ipa_hbac_test_allow_user) /* Negative test */ rules[0]->users->names[0] = HBAC_TEST_INVALID_USER; + /* Validate this rule */ + is_valid = hbac_rule_is_complete(rules[0], &missing_attrs); + fail_unless(is_valid); + fail_unless(missing_attrs == 0); + /* Evaluate the rules */ result = hbac_evaluate(rules, eval_req, &info); fail_unless(result == HBAC_EVAL_DENY, @@ -290,6 +309,8 @@ START_TEST(ipa_hbac_test_allow_utf8) struct hbac_rule **rules; struct hbac_eval_req *eval_req; struct hbac_info *info; + bool is_valid; + uint32_t missing_attrs; test_ctx = talloc_new(global_talloc_context); @@ -343,6 +364,11 @@ START_TEST(ipa_hbac_test_allow_utf8) rules[1] = NULL; + /* Validate this rule */ + is_valid = hbac_rule_is_complete(rules[0], &missing_attrs); + fail_unless(is_valid); + fail_unless(missing_attrs == 0); + /* Evaluate the rules */ result = hbac_evaluate(rules, eval_req, &info); fail_unless(result == HBAC_EVAL_ALLOW, @@ -369,6 +395,11 @@ START_TEST(ipa_hbac_test_allow_utf8) eval_req->user->name = (const char *) &user_lowcase_tr; rules[0]->users->names[0] = (const char *) &user_upcase_tr; + /* Validate this rule */ + is_valid = hbac_rule_is_complete(rules[0], &missing_attrs); + fail_unless(is_valid); + fail_unless(missing_attrs == 0); + /* Evaluate the rules */ result = hbac_evaluate(rules, eval_req, &info); fail_unless(result == HBAC_EVAL_DENY, @@ -389,6 +420,8 @@ START_TEST(ipa_hbac_test_allow_group) struct hbac_rule **rules; struct hbac_eval_req *eval_req; struct hbac_info *info; + bool is_valid; + uint32_t missing_attrs; test_ctx = talloc_new(global_talloc_context); @@ -420,6 +453,11 @@ START_TEST(ipa_hbac_test_allow_group) rules[1] = NULL; + /* Validate this rule */ + is_valid = hbac_rule_is_complete(rules[0], &missing_attrs); + fail_unless(is_valid); + fail_unless(missing_attrs == 0); + /* Evaluate the rules */ result = hbac_evaluate(rules, eval_req, &info); fail_unless(result == HBAC_EVAL_ALLOW, @@ -432,6 +470,11 @@ START_TEST(ipa_hbac_test_allow_group) /* Negative test */ rules[0]->users->groups[0] = HBAC_TEST_INVALID_GROUP; + /* Validate this rule */ + is_valid = hbac_rule_is_complete(rules[0], &missing_attrs); + fail_unless(is_valid); + fail_unless(missing_attrs == 0); + /* Evaluate the rules */ result = hbac_evaluate(rules, eval_req, &info); fail_unless(result == HBAC_EVAL_DENY, @@ -452,6 +495,8 @@ START_TEST(ipa_hbac_test_allow_svc) struct hbac_rule **rules; struct hbac_eval_req *eval_req; struct hbac_info *info; + bool is_valid; + uint32_t missing_attrs; test_ctx = talloc_new(global_talloc_context); @@ -482,6 +527,11 @@ START_TEST(ipa_hbac_test_allow_svc) rules[1] = NULL; + /* Validate this rule */ + is_valid = hbac_rule_is_complete(rules[0], &missing_attrs); + fail_unless(is_valid); + fail_unless(missing_attrs == 0); + /* Evaluate the rules */ result = hbac_evaluate(rules, eval_req, &info); fail_unless(result == HBAC_EVAL_ALLOW, @@ -494,6 +544,11 @@ START_TEST(ipa_hbac_test_allow_svc) /* Negative test */ rules[0]->services->names[0] = HBAC_TEST_INVALID_SERVICE; + /* Validate this rule */ + is_valid = hbac_rule_is_complete(rules[0], &missing_attrs); + fail_unless(is_valid); + fail_unless(missing_attrs == 0); + /* Evaluate the rules */ result = hbac_evaluate(rules, eval_req, &info); fail_unless(result == HBAC_EVAL_DENY, @@ -514,6 +569,8 @@ START_TEST(ipa_hbac_test_allow_svcgroup) struct hbac_rule **rules; struct hbac_eval_req *eval_req; struct hbac_info *info; + bool is_valid; + uint32_t missing_attrs; test_ctx = talloc_new(global_talloc_context); @@ -545,6 +602,11 @@ START_TEST(ipa_hbac_test_allow_svcgroup) rules[1] = NULL; + /* Validate this rule */ + is_valid = hbac_rule_is_complete(rules[0], &missing_attrs); + fail_unless(is_valid); + fail_unless(missing_attrs == 0); + /* Evaluate the rules */ result = hbac_evaluate(rules, eval_req, &info); fail_unless(result == HBAC_EVAL_ALLOW, @@ -557,6 +619,11 @@ START_TEST(ipa_hbac_test_allow_svcgroup) /* Negative test */ rules[0]->services->groups[0] = HBAC_TEST_INVALID_SERVICEGROUP; + /* Validate this rule */ + is_valid = hbac_rule_is_complete(rules[0], &missing_attrs); + fail_unless(is_valid); + fail_unless(missing_attrs == 0); + /* Evaluate the rules */ result = hbac_evaluate(rules, eval_req, &info); fail_unless(result == HBAC_EVAL_DENY, @@ -577,6 +644,8 @@ START_TEST(ipa_hbac_test_allow_srchost) struct hbac_rule **rules; struct hbac_eval_req *eval_req; struct hbac_info *info; + bool is_valid; + uint32_t missing_attrs; test_ctx = talloc_new(global_talloc_context); @@ -607,6 +676,11 @@ START_TEST(ipa_hbac_test_allow_srchost) rules[1] = NULL; + /* Validate this rule */ + is_valid = hbac_rule_is_complete(rules[0], &missing_attrs); + fail_unless(is_valid); + fail_unless(missing_attrs == 0); + /* Evaluate the rules */ result = hbac_evaluate(rules, eval_req, &info); fail_unless(result == HBAC_EVAL_ALLOW, @@ -619,6 +693,11 @@ START_TEST(ipa_hbac_test_allow_srchost) /* Negative test */ rules[0]->srchosts->names[0] = HBAC_TEST_INVALID_SRCHOST; + /* Validate this rule */ + is_valid = hbac_rule_is_complete(rules[0], &missing_attrs); + fail_unless(is_valid); + fail_unless(missing_attrs == 0); + /* Evaluate the rules */ result = hbac_evaluate(rules, eval_req, &info); fail_unless(result == HBAC_EVAL_DENY, @@ -639,6 +718,8 @@ START_TEST(ipa_hbac_test_allow_srchostgroup) struct hbac_rule **rules; struct hbac_eval_req *eval_req; struct hbac_info *info; + bool is_valid; + uint32_t missing_attrs; test_ctx = talloc_new(global_talloc_context); @@ -670,6 +751,11 @@ START_TEST(ipa_hbac_test_allow_srchostgroup) rules[1] = NULL; + /* Validate this rule */ + is_valid = hbac_rule_is_complete(rules[0], &missing_attrs); + fail_unless(is_valid); + fail_unless(missing_attrs == 0); + /* Evaluate the rules */ result = hbac_evaluate(rules, eval_req, &info); fail_unless(result == HBAC_EVAL_ALLOW, @@ -682,6 +768,11 @@ START_TEST(ipa_hbac_test_allow_srchostgroup) /* Negative test */ rules[0]->srchosts->groups[0] = HBAC_TEST_INVALID_SRCHOSTGROUP; + /* Validate this rule */ + is_valid = hbac_rule_is_complete(rules[0], &missing_attrs); + fail_unless(is_valid); + fail_unless(missing_attrs == 0); + /* Evaluate the rules */ result = hbac_evaluate(rules, eval_req, &info); fail_unless(result == HBAC_EVAL_DENY, @@ -695,6 +786,29 @@ START_TEST(ipa_hbac_test_allow_srchostgroup) } END_TEST +START_TEST(ipa_hbac_test_incomplete) +{ + TALLOC_CTX *test_ctx; + struct hbac_rule *rule; + bool is_valid; + uint32_t missing_attrs; + + test_ctx = talloc_new(global_talloc_context); + + rule = talloc_zero(test_ctx, struct hbac_rule); + + /* Validate this rule */ + is_valid = hbac_rule_is_complete(rule, &missing_attrs); + fail_if(is_valid); + fail_unless(missing_attrs | HBAC_RULE_ELEMENT_USERS); + fail_unless(missing_attrs | HBAC_RULE_ELEMENT_SERVICES); + fail_unless(missing_attrs | HBAC_RULE_ELEMENT_TARGETHOSTS); + fail_unless(missing_attrs | HBAC_RULE_ELEMENT_SOURCEHOSTS); + + talloc_free(test_ctx); +} +END_TEST + Suite *hbac_test_suite (void) { Suite *s = suite_create ("HBAC"); @@ -712,6 +826,7 @@ Suite *hbac_test_suite (void) tcase_add_test(tc_hbac, ipa_hbac_test_allow_srchost); tcase_add_test(tc_hbac, ipa_hbac_test_allow_srchostgroup); tcase_add_test(tc_hbac, ipa_hbac_test_allow_utf8); + tcase_add_test(tc_hbac, ipa_hbac_test_incomplete); suite_add_tcase(s, tc_hbac); return s; -- cgit