From b6cf6e179a2ad028bcbfee2588b0e0a318f47daa Mon Sep 17 00:00:00 2001
From: Stanislav Laznicka <slaznick@redhat.com>
Date: Wed, 2 Sep 2015 11:36:50 +0200
Subject: [PATCH 5/6] IPA: Tests for HBAC time policies.

https://fedorahosted.org/freeipa/ticket/547
---
 src/tests/ipa_hbac-tests.c | 159 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 159 insertions(+)

diff --git a/src/tests/ipa_hbac-tests.c b/src/tests/ipa_hbac-tests.c
index cf4788ac23c24b05b0085f2266029d5ded0b57c0..9b2247369963eca51c706770951e74772043dfec 100644
--- a/src/tests/ipa_hbac-tests.c
+++ b/src/tests/ipa_hbac-tests.c
@@ -25,6 +25,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <talloc.h>
+#include <time.h>
 
 #include "tests/common_check.h"
 #include "providers/ipa/ipa_hbac.h"
@@ -826,6 +827,163 @@ START_TEST(ipa_hbac_test_allow_srchostgroup)
 }
 END_TEST
 
+START_TEST(ipa_hbac_test_allow_time)
+{
+    enum hbac_eval_result result;
+    TALLOC_CTX *test_ctx;
+    struct hbac_rule **rules;
+    struct hbac_eval_req *eval_req;
+    struct hbac_info *info = NULL;
+    bool is_valid;
+    uint32_t missing_attrs;
+
+    time_t tstamp;
+    struct tm *now;
+    char *rule_str, *noallow_rule_str;
+    char *noallow_rpt_rule_str;
+
+    test_ctx = talloc_new(global_talloc_context);
+
+    /* Create a request */
+    eval_req = talloc_zero(test_ctx, struct hbac_eval_req);
+    fail_if(eval_req == NULL);
+
+    tstamp = time(NULL);
+    fail_if(tstamp == -1);
+
+    eval_req->request_time = tstamp;
+
+    get_test_user(eval_req, &eval_req->user);
+    get_test_service(eval_req, &eval_req->service);
+    get_test_srchost(eval_req, &eval_req->srchost);
+
+    /* Rules array for evaluation */
+    rules = talloc_array(test_ctx, struct hbac_rule *, 2);
+    fail_if (rules == NULL);
+
+    /* Will use only one rule */
+    rules[1] = NULL;
+
+    get_allow_all_rule(rules, &rules[0]);
+
+    /* Prepare the non-matching and matching time rule strings */
+    now = localtime(&tstamp);
+    noallow_rule_str = talloc_asprintf(test_ctx,
+                                       "dayofmonth=%d monthofyear=%d year=%d",
+                                       now->tm_mday == 1 ? now->tm_mday + 1 : now->tm_mday -1,
+                                       now->tm_mon + 1, now->tm_year + 1900
+                                      );
+    fail_if(noallow_rule_str == NULL);
+
+    noallow_rpt_rule_str = talloc_asprintf(test_ctx, "repeat=%d%02d%02d+3y",
+                                          (now->tm_year - 1970) % 3 ? 1970 : 1971,
+                                          now->tm_mon+1, now->tm_mday);
+
+    rule_str = talloc_asprintf(test_ctx,
+                               "dayofmonth=%d monthofyear=%d year=%d" \
+                               "repeat=19700101+1d",
+                               now->tm_mday, now->tm_mon + 1, now->tm_year + 1900
+                              );
+
+    fail_if(rule_str == NULL);
+
+    /* Modify the rule to let users in only at a certain time (today) */
+    rules[0]->name = talloc_strdup(rules[0], "Allow timerule");
+    fail_if(rules[0]->name == NULL);
+
+    rules[0]->timerules = talloc_zero(rules[0], struct hbac_time_rules);
+    fail_if(rules[0]->timerules == NULL);
+
+    rules[0]->timerules->timezone = talloc_strdup(rules[0]->timerules, "host");
+    fail_if(rules[0]->timerules->timezone == NULL);
+
+    rules[0]->timerules->accesstimes = talloc_array(rules[0]->timerules,
+                                       const char *, 4);
+    fail_if(rules[0]->timerules->accesstimes == NULL);
+
+    rules[0]->timerules->accesstimes[0] = talloc_strdup(rules[0]->timerules->accesstimes,
+                                                        noallow_rule_str);
+    fail_if(rules[0]->timerules->accesstimes[0] == NULL);
+
+    rules[0]->timerules->accesstimes[1] = talloc_strdup(rules[0]->timerules->accesstimes,
+                                                        noallow_rpt_rule_str);
+    fail_if(rules[0]->timerules->accesstimes[1] == NULL);
+
+    rules[0]->timerules->accesstimes[2] = talloc_strdup(rules[0]->timerules->accesstimes,
+                                                        rule_str);
+    fail_if(rules[0]->timerules->accesstimes[2] == NULL);
+
+    rules[0]->timerules->accesstimes[3] = NULL;
+
+    /* Validate the rule */
+    is_valid = hbac_rule_is_complete(rules[0], &missing_attrs);
+    fail_unless(is_valid);
+    fail_unless(missing_attrs == 0);
+
+    /* Evaluate the rule */
+    result = hbac_evaluate(rules, eval_req, &info);
+    fail_unless(result == HBAC_EVAL_ALLOW,
+                "Expected [%s], got [%s]; "
+                "Error: [%s]",
+                hbac_result_string(HBAC_EVAL_ALLOW),
+                hbac_result_string(result),
+                info ? hbac_error_string(info->code):"Unknown");
+    hbac_free_info(info);
+    info = NULL;
+
+    /* Negative test - Add exceptions */
+    rules[0]->timerules->exceptions = rules[0]->timerules->accesstimes;
+
+    /* Validate the rule */
+    is_valid = hbac_rule_is_complete(rules[0], &missing_attrs);
+    fail_unless(is_valid);
+    fail_unless(missing_attrs == 0);
+
+    result = hbac_evaluate(rules, eval_req, &info);
+    fail_unless(result == HBAC_EVAL_DENY,
+                "Expected [%s], got [%s]; "
+                "Error: [%s]",
+                hbac_result_string(HBAC_EVAL_DENY),
+                hbac_result_string(result),
+                info ? hbac_error_string(info->code):"Unknown");
+    hbac_free_info(info);
+    info = NULL;
+
+    /* Negative test - Wrong syntax */
+    rules[0]->timerules->exceptions = NULL;
+
+    rule_str[0] = 'e';
+    rules[0]->timerules->accesstimes[1] = talloc_strdup(rules[0]->timerules,
+                                                        rule_str);
+    fail_if(rules[0]->timerules->accesstimes[1] == NULL);
+
+    result = hbac_evaluate(rules, eval_req, &info);
+    fail_unless(result == HBAC_EVAL_ERROR,
+                "Expected [%s], got [%s]; "
+                "Error: [%s]",
+                hbac_result_string(HBAC_EVAL_ERROR),
+                hbac_result_string(result),
+                info ? hbac_error_string(info->code):"Unknown");
+    hbac_free_info(info);
+    info = NULL;
+
+    /* Negative test - No matching time */
+    rules[0]->timerules->accesstimes[1] = NULL;
+
+    result = hbac_evaluate(rules, eval_req, &info);
+    fail_unless(result == HBAC_EVAL_DENY,
+                "Expected [%s], got [%s]; "
+                "Error: [%s]",
+                hbac_result_string(HBAC_EVAL_DENY),
+                hbac_result_string(result),
+                info ? hbac_error_string(info->code):"Unknown");
+    hbac_free_info(info);
+    info = NULL;
+
+    talloc_free(test_ctx);
+}
+END_TEST
+
 START_TEST(ipa_hbac_test_incomplete)
 {
     TALLOC_CTX *test_ctx;
@@ -865,6 +1023,7 @@ Suite *hbac_test_suite (void)
     tcase_add_test(tc_hbac, ipa_hbac_test_allow_svcgroup);
     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_time);
     tcase_add_test(tc_hbac, ipa_hbac_test_allow_utf8);
     tcase_add_test(tc_hbac, ipa_hbac_test_incomplete);
 
-- 
2.4.3

