summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/responder/pac/pacsrv.h16
-rw-r--r--src/responder/pac/pacsrv_utils.c156
-rw-r--r--src/tests/pac_responder-tests.c109
3 files changed, 279 insertions, 2 deletions
diff --git a/src/responder/pac/pacsrv.h b/src/responder/pac/pacsrv.h
index e088e212a..c0a13a332 100644
--- a/src/responder/pac/pacsrv.h
+++ b/src/responder/pac/pacsrv.h
@@ -67,6 +67,12 @@ struct local_mapping_ranges {
struct range secondary_rids;
};
+struct grp_info {
+ gid_t gid;
+ char *orig_dn;
+ struct ldb_dn *dn;
+};
+
int pac_cmd_execute(struct cli_ctx *cctx);
struct sss_cmd_table *get_pac_cmds(void);
@@ -106,4 +112,14 @@ errno_t get_pwd_from_pac(TALLOC_CTX *mem_ctx,
struct PAC_LOGON_INFO *logon_info,
struct passwd **_pwd,
struct sysdb_attrs **_attrs);
+
+errno_t diff_gid_lists(TALLOC_CTX *mem_ctx,
+ size_t cur_grp_num,
+ struct grp_info *cur_gid_list,
+ size_t new_gid_num,
+ gid_t *new_gid_list,
+ size_t *_add_gid_num,
+ gid_t **_add_gid_list,
+ size_t *_del_gid_num,
+ struct grp_info ***_del_gid_list);
#endif /* __PACSRV_H__ */
diff --git a/src/responder/pac/pacsrv_utils.c b/src/responder/pac/pacsrv_utils.c
index 101960f01..c9551c998 100644
--- a/src/responder/pac/pacsrv_utils.c
+++ b/src/responder/pac/pacsrv_utils.c
@@ -616,3 +616,159 @@ done:
return ret;
}
+
+errno_t diff_gid_lists(TALLOC_CTX *mem_ctx,
+ size_t cur_grp_num,
+ struct grp_info *cur_grp_list,
+ size_t new_gid_num,
+ gid_t *new_gid_list,
+ size_t *_add_gid_num,
+ gid_t **_add_gid_list,
+ size_t *_del_grp_num,
+ struct grp_info ***_del_grp_list)
+{
+ int ret;
+ size_t c;
+ hash_table_t *table;
+ hash_key_t key;
+ hash_value_t value;
+ size_t add_gid_num = 0;
+ gid_t *add_gid_list = NULL;
+ size_t del_grp_num = 0;
+ struct grp_info **del_grp_list = NULL;
+ TALLOC_CTX *tmp_ctx = NULL;
+ unsigned long value_count;
+ hash_value_t *values;
+
+ if ((cur_grp_num != 0 && cur_grp_list == NULL) ||
+ (new_gid_num != 0 && new_gid_list == NULL)) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Missing group array.\n"));
+ return EINVAL;
+ }
+
+ if (cur_grp_num == 0 && new_gid_num == 0) {
+ ret = EOK;
+ goto done;
+ }
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("talloc_new failed.\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+
+ if (cur_grp_num == 0 && new_gid_num != 0) {
+ add_gid_num = new_gid_num;
+ add_gid_list = talloc_array(tmp_ctx, gid_t, add_gid_num);
+ if (add_gid_list == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("talloc_array failed.\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+
+ for (c = 0; c < add_gid_num; c++) {
+ add_gid_list[c] = new_gid_list[c];
+ }
+
+ ret = EOK;
+ goto done;
+ }
+
+ if (cur_grp_num != 0 && new_gid_num == 0) {
+ del_grp_num = cur_grp_num;
+ del_grp_list = talloc_array(tmp_ctx, struct grp_info *, del_grp_num);
+ if (del_grp_list == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("talloc_array failed.\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+
+ for (c = 0; c < del_grp_num; c++) {
+ del_grp_list[c] = &cur_grp_list[c];
+ }
+
+ ret = EOK;
+ goto done;
+ }
+
+ /* Add all current GIDs to a hash and then compare with the new ones in a
+ * single loop */
+ ret = sss_hash_create(tmp_ctx, cur_grp_num, &table);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("sss_hash_create failed.\n"));
+ goto done;
+ }
+
+ key.type = HASH_KEY_ULONG;
+ value.type = HASH_VALUE_PTR;
+ for (c = 0; c < cur_grp_num; c++) {
+ key.ul = (unsigned long) cur_grp_list[c].gid;
+ value.ptr = &cur_grp_list[c];
+
+ ret = hash_enter(table, &key, &value);
+ if (ret != HASH_SUCCESS) {
+ DEBUG(SSSDBG_OP_FAILURE, ("hash_enter failed.\n"));
+ ret = EIO;
+ goto done;
+ }
+ }
+
+ for (c = 0; c < new_gid_num; c++) {
+ key.ul = (unsigned long) new_gid_list[c];
+
+ ret = hash_delete(table, &key);
+ if (ret == HASH_ERROR_KEY_NOT_FOUND) {
+ /* gid not found, must be added */
+ add_gid_num++;
+ add_gid_list = talloc_realloc(tmp_ctx, add_gid_list, gid_t, add_gid_num);
+ if (add_gid_list == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("talloc_realloc failed.\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+
+ add_gid_list[add_gid_num - 1] = new_gid_list[c];
+ } else if (ret != HASH_SUCCESS) {
+ DEBUG(SSSDBG_OP_FAILURE, ("hash_delete failed.\n"));
+ ret = EIO;
+ goto done;
+ }
+ }
+
+ /* the remaining entries in the hash are not in the new list anymore and
+ * must be deleted */
+ ret = hash_values(table, &value_count, &values);
+ if (ret != HASH_SUCCESS) {
+ DEBUG(SSSDBG_OP_FAILURE, ("hash_keys failed.\n"));
+ ret = EIO;
+ goto done;
+ }
+
+ del_grp_num = value_count;
+ del_grp_list = talloc_array(tmp_ctx, struct grp_info *, del_grp_num);
+ if (del_grp_list == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("talloc_array failed.\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+
+ for (c = 0; c < del_grp_num; c++) {
+ del_grp_list[c] = (struct grp_info *) values[c].ptr;
+ }
+
+ ret = EOK;
+
+done:
+
+ if (ret == EOK) {
+ *_add_gid_num = add_gid_num;
+ *_add_gid_list = talloc_steal(mem_ctx, add_gid_list);
+ *_del_grp_num = del_grp_num;
+ *_del_grp_list = talloc_steal(mem_ctx, del_grp_list);
+ }
+
+ talloc_free(tmp_ctx);
+
+ return ret;
+}
diff --git a/src/tests/pac_responder-tests.c b/src/tests/pac_responder-tests.c
index 720793cc6..02cc242a4 100644
--- a/src/tests/pac_responder-tests.c
+++ b/src/tests/pac_responder-tests.c
@@ -70,18 +70,123 @@ START_TEST(pac_test_seondary_local_sid_to_id)
}
END_TEST
+START_TEST(pac_test_get_gids_to_add_and_remove)
+{
+ TALLOC_CTX *mem_ctx;
+ int ret;
+ size_t c;
+ size_t add_gid_count = 0;
+ gid_t *add_gids = NULL;
+ size_t del_gid_count = 0;
+ struct grp_info **del_gids = NULL;
+
+ gid_t gid_list_2[] = {2};
+ gid_t gid_list_3[] = {3};
+ gid_t gid_list_23[] = {2, 3};
+
+ struct grp_info grp_info_1 = {1, NULL, NULL};
+ struct grp_info grp_info_2 = {2, NULL, NULL};
+ struct grp_info grp_list_1[] = {grp_info_1};
+ struct grp_info grp_list_12[] = {grp_info_1, grp_info_2};
+
+ struct a_and_r_data {
+ size_t cur_gid_count;
+ struct grp_info *cur_gids;
+ size_t gid_count;
+ gid_t *gids;
+ int exp_ret;
+ size_t exp_add_gid_count;
+ gid_t *exp_add_gids;
+ size_t exp_del_gid_count;
+ struct grp_info *exp_del_gids;
+ } a_and_r_data[] = {
+ {1, grp_list_1, 1, gid_list_2, EOK, 1, gid_list_2, 1, grp_list_1},
+ {1, grp_list_1, 0, NULL, EOK, 0, NULL, 1, grp_list_1},
+ {0, NULL, 1, gid_list_2, EOK, 1, gid_list_2, 0, NULL},
+ {2, grp_list_12, 1, gid_list_2, EOK, 0, NULL, 1, grp_list_1},
+ {2, grp_list_12, 2, gid_list_23, EOK, 1, gid_list_3, 1, grp_list_1},
+ {0, NULL, 0, NULL, 0, 0, NULL, 0, NULL}
+ };
+
+ mem_ctx = talloc_new(NULL);
+ fail_unless(mem_ctx != NULL, "talloc_new failed.");
+
+ ret = diff_gid_lists(mem_ctx, 0, NULL, 0, NULL,
+ &add_gid_count, &add_gids,
+ &del_gid_count, &del_gids);
+ fail_unless(ret == EOK, "get_gids_to_add_and_remove failed with empty " \
+ "groups.");
+
+ ret = diff_gid_lists(mem_ctx, 1, NULL, 0, NULL,
+ &add_gid_count, &add_gids,
+ &del_gid_count, &del_gids);
+ fail_unless(ret == EINVAL, "get_gids_to_add_and_remove failed with " \
+ "invalid current groups.");
+
+ ret = diff_gid_lists(mem_ctx, 0, NULL, 1, NULL,
+ &add_gid_count, &add_gids,
+ &del_gid_count, &del_gids);
+ fail_unless(ret == EINVAL, "get_gids_to_add_and_remove failed with " \
+ "invalid new groups.");
+
+ for (c = 0; a_and_r_data[c].cur_gids != NULL ||
+ a_and_r_data[c].gids != NULL; c++) {
+ ret = diff_gid_lists(mem_ctx,
+ a_and_r_data[c].cur_gid_count,
+ a_and_r_data[c].cur_gids,
+ a_and_r_data[c].gid_count,
+ a_and_r_data[c].gids,
+ &add_gid_count, &add_gids,
+ &del_gid_count, &del_gids);
+ fail_unless(ret == a_and_r_data[c].exp_ret,
+ "Unexpected return value for test data #%d, " \
+ "expected [%d], got [%d]",
+ c, a_and_r_data[c].exp_ret, ret);
+ fail_unless(add_gid_count == a_and_r_data[c].exp_add_gid_count,
+ "Unexpected numer of groups to add for test data #%d, " \
+ "expected [%d], got [%d]",
+ c, a_and_r_data[c].exp_add_gid_count, add_gid_count);
+ fail_unless(del_gid_count == a_and_r_data[c].exp_del_gid_count,
+ "Unexpected numer of groups to delete for test data #%d, " \
+ "expected [%d], got [%d]",
+ c, a_and_r_data[c].exp_del_gid_count, del_gid_count);
+
+ /* The lists might be returned in any order, to make tests simple we
+ * only look at lists with 1 element. TODO: add code to compare lists
+ * with more than 1 member. */
+ if (add_gid_count == 1) {
+ fail_unless(add_gids[0] == a_and_r_data[c].exp_add_gids[0],
+ "Unexpected gid to add for test data #%d, " \
+ "expected [%d], got [%d]",
+ c, a_and_r_data[c].exp_add_gids[0], add_gids[0]);
+ }
+
+ if (del_gid_count == 1) {
+ fail_unless(del_gids[0]->gid == a_and_r_data[c].exp_del_gids[0].gid,
+ "Unexpected gid to delete for test data #%d, " \
+ "expected [%d], got [%d]",
+ c, a_and_r_data[c].exp_del_gids[0].gid,
+ del_gids[0]->gid);
+ }
+ }
+
+ talloc_free(mem_ctx);
+}
+END_TEST
+
Suite *idmap_test_suite (void)
{
Suite *s = suite_create ("PAC responder");
TCase *tc_pac = tcase_create("PAC responder tests");
- /*tcase_add_checked_fixture(tc_init,
+ tcase_add_checked_fixture(tc_pac,
leak_check_setup,
- leak_check_teardown);*/
+ leak_check_teardown);
tcase_add_test(tc_pac, pac_test_local_sid_to_id);
tcase_add_test(tc_pac, pac_test_seondary_local_sid_to_id);
+ tcase_add_test(tc_pac, pac_test_get_gids_to_add_and_remove);
suite_add_tcase(s, tc_pac);