summaryrefslogtreecommitdiff
path: root/src/responder/pac/pacsrv_cmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/responder/pac/pacsrv_cmd.c')
-rw-r--r--src/responder/pac/pacsrv_cmd.c588
1 files changed, 455 insertions, 133 deletions
diff --git a/src/responder/pac/pacsrv_cmd.c b/src/responder/pac/pacsrv_cmd.c
index 8f5617c7..c3f1115e 100644
--- a/src/responder/pac/pacsrv_cmd.c
+++ b/src/responder/pac/pacsrv_cmd.c
@@ -53,31 +53,39 @@ struct pac_req_ctx {
struct pac_ctx *pac_ctx;
const char *domain_name;
const char *user_name;
- char *fq_name;
struct sss_domain_info *dom;
struct PAC_LOGON_INFO *logon_info;
struct dom_sid2 *domain_sid;
- size_t gid_count;
- struct pac_dom_grps *gids;
-
- size_t current_grp_count;
- struct grp_info *current_grp_list;
+ size_t del_grp_count;
+ struct grp_info *del_grp_list;
- size_t add_gid_count;
- struct pac_dom_grps *add_gids;
+ size_t add_sid_count;
+ char **add_sids;
- size_t del_grp_count;
- struct grp_info **del_grp_list;
+ hash_table_t *sid_table;
+ char *user_sid_str;
+ char *user_dom_sid_str;
+ char *primary_group_sid_str;
};
-static errno_t pac_add_user_next(struct pac_req_ctx *pr_ctx);
+static errno_t pac_resolve_sids_next(struct pac_req_ctx *pr_ctx);
+static void pac_lookup_sids_done(struct tevent_req *req);
+static struct tevent_req *pac_lookup_sids_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct pac_req_ctx *pr_ctx,
+ struct pac_ctx *pac_ctx,
+ hash_table_t *sid_table);
+static errno_t pac_lookup_sids_recv(struct tevent_req *req);
+static void pac_add_user_next(struct pac_req_ctx *pr_ctx);
static void pac_get_domains_done(struct tevent_req *req);
static errno_t pac_user_get_grp_info(TALLOC_CTX *mem_ctx,
struct pac_req_ctx *pr_ctx,
- size_t *_current_grp_count,
- struct grp_info **_current_grp_list);
+ size_t *_del_grp_count,
+ struct grp_info **_del_grp_list,
+ size_t *_add_sid_count,
+ char ***_add_sids);
static errno_t save_pac_user(struct pac_req_ctx *pr_ctx);
static void pac_get_group_done(struct tevent_req *subreq);
static errno_t pac_save_memberships_next(struct tevent_req *req);
@@ -96,6 +104,7 @@ static errno_t pac_add_pac_user(struct cli_ctx *cctx)
size_t blen;
struct pac_req_ctx *pr_ctx;
struct tevent_req *req;
+ enum idmap_error_code err;
sss_packet_get_body(cctx->creq->in, &body, &blen);
@@ -143,8 +152,18 @@ static errno_t pac_add_pac_user(struct cli_ctx *cctx)
goto done;
}
- pr_ctx->dom = responder_get_domain(cctx->rctx, pr_ctx->domain_name);
- if (pr_ctx->dom == NULL) {
+ err = sss_idmap_smb_sid_to_sid(pr_ctx->pac_ctx->idmap_ctx,
+ pr_ctx->logon_info->info3.base.domain_sid,
+ &pr_ctx->user_dom_sid_str);
+ if (err != IDMAP_SUCCESS) {
+ DEBUG(SSSDBG_OP_FAILURE, ("sss_idmap_smb_sid_to_sid failed.\n"));
+ ret = EFAULT;
+ goto done;
+ }
+
+ ret = responder_get_domain_by_id(cctx->rctx, pr_ctx->user_dom_sid_str,
+ &pr_ctx->dom);
+ if (ret == EAGAIN || ret == ENOENT) {
req = sss_dp_get_domains_send(cctx->rctx, cctx->rctx, true,
pr_ctx->domain_name);
if (req == NULL) {
@@ -154,9 +173,12 @@ static errno_t pac_add_pac_user(struct cli_ctx *cctx)
ret = EAGAIN;
}
goto done;
+ } else if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("responder_get_domain_by_id failed.\n"));
+ goto done;
}
- ret = pac_add_user_next(pr_ctx);
+ ret = pac_resolve_sids_next(pr_ctx);
done:
if (ret != EAGAIN) {
@@ -178,15 +200,16 @@ static void pac_get_domains_done(struct tevent_req *req)
goto done;
}
- pr_ctx->dom = responder_get_domain(cctx->rctx, pr_ctx->domain_name);
- if (pr_ctx->dom == NULL) {
+ ret = responder_get_domain_by_id(cctx->rctx, pr_ctx->user_dom_sid_str,
+ &pr_ctx->dom);
+ if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, ("Corresponding domain [%s] has not been "
- "found\n", pr_ctx->domain_name));
+ "found\n", pr_ctx->user_dom_sid_str));
ret = ENOENT;
goto done;
}
- ret = pac_add_user_next(pr_ctx);
+ ret = pac_resolve_sids_next(pr_ctx);
done:
if (ret != EAGAIN) {
@@ -195,58 +218,140 @@ done:
pac_cmd_done(cctx, ret);
}
-static errno_t pac_add_user_next(struct pac_req_ctx *pr_ctx)
+static errno_t pac_resolve_sids_next(struct pac_req_ctx *pr_ctx)
{
int ret;
struct tevent_req *req;
- struct dom_sid *my_dom_sid;
- struct local_mapping_ranges *my_range_map;
-
- /* this is a subdomain so we need to search for the fully qualified
- * name in the database */
- pr_ctx->fq_name= sss_tc_fqname(pr_ctx, pr_ctx->dom->names,
- pr_ctx->dom, pr_ctx->user_name);
- if (!pr_ctx->fq_name) {
- ret = ENOMEM;
- DEBUG(SSSDBG_OP_FAILURE, ("talloc_sprintf failed.\n"));
- goto done;
+
+ ret = get_sids_from_pac(pr_ctx, pr_ctx->pac_ctx, pr_ctx->logon_info,
+ &pr_ctx->user_sid_str,
+ &pr_ctx->primary_group_sid_str,
+ &pr_ctx->sid_table);
+ if (ret != 0) {
+ DEBUG(SSSDBG_OP_FAILURE, ("get_sids_from_pac failed.\n"));
+ return ret;
}
- ret = save_pac_user(pr_ctx);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, ("save_pac_user failed.\n"));
- goto done;
+ req = pac_lookup_sids_send(pr_ctx, pr_ctx->cctx->ev, pr_ctx,
+ pr_ctx->pac_ctx, pr_ctx->sid_table);
+ if (req == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("pac_lookup_sids_send failed.\n"));
+ return ENOMEM;
}
- ret = pac_user_get_grp_info(pr_ctx, pr_ctx, &pr_ctx->current_grp_count,
- &pr_ctx->current_grp_list);
+ tevent_req_set_callback(req, pac_lookup_sids_done, pr_ctx);
+
+ ret = EAGAIN;
+
+
+ return ret;
+}
+
+static void pac_lookup_sids_done(struct tevent_req *req)
+{
+ struct pac_req_ctx *pr_ctx = tevent_req_callback_data(req, struct pac_req_ctx);
+ struct cli_ctx *cctx = pr_ctx->cctx;
+ errno_t ret;
+ unsigned long count;
+ hash_entry_t *entries;
+ hash_key_t key;
+ hash_value_t value;
+ size_t c;
+ struct sss_domain_info *dom;
+ uint64_t id;
+ struct ldb_result *msg;
+
+ ret = pac_lookup_sids_recv(req);
+ talloc_zfree(req);
+
if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, ("pac_user_get_grp_info failed.\n"));
- goto done;
+ talloc_free(pr_ctx);
+ pac_cmd_done(cctx, ret);
+ return;
}
- ret = get_parent_domain_data(pr_ctx->pac_ctx, pr_ctx->dom,
- &my_dom_sid, &my_range_map);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, ("get_parent_domain_data failed.\n"));
- goto done;
+ key.type = HASH_KEY_STRING;
+ value.type = HASH_VALUE_ULONG;
+
+ ret = hash_entries(pr_ctx->sid_table, &count, &entries);
+ for (c = 0; c < count; c++) {
+ if (entries[c].value.ul == 0) {
+ ret =responder_get_domain_by_id(cctx->rctx,
+ entries[c].key.str, &dom);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("No domain found for SID [%s].\n",
+ entries[c].key.str));
+ continue;
+ }
+
+ msg = NULL;
+ ret = sysdb_search_object_by_sid(pr_ctx, dom->sysdb, dom,
+ entries[c].key.str, NULL, &msg);
+ if (ret != EOK) {
+ if (ret == ENOENT) {
+ DEBUG(SSSDBG_OP_FAILURE, ("No entry found for SID [%s].\n",
+ entries[c].key.str));
+ } else {
+ DEBUG(SSSDBG_OP_FAILURE, ("sysdb_search_object_by_sid " \
+ "failed.\n"));
+ }
+ continue;
+ }
+ if (msg->count > 1) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("More then one result returned " \
+ "for SID [%s].\n",
+ entries[c].key.str));
+ talloc_free(msg);
+ pac_cmd_done(cctx, EINVAL);
+ return;
+ }
+
+ id = ldb_msg_find_attr_as_uint64(msg->msgs[0],
+ SYSDB_UIDNUM, 0);
+ if (id == 0) {
+ id = ldb_msg_find_attr_as_uint64(msg->msgs[0],
+ SYSDB_GIDNUM, 0);
+ }
+
+ if (id == 0) {
+ DEBUG(SSSDBG_OP_FAILURE, ("No ID found in entry.\n"));
+ talloc_free(msg);
+ continue;
+ }
+
+ key.str = entries[c].key.str;
+ value.ul = id;
+
+ ret = hash_enter(pr_ctx->sid_table, &key, &value);
+ if (ret != HASH_SUCCESS) {
+ DEBUG(SSSDBG_OP_FAILURE, ("hash_enter failed [%d][%s].\n",
+ ret, hash_error_string(ret)));
+ continue;
+ }
+ talloc_free(msg);
+ }
}
- ret = get_gids_from_pac(pr_ctx, pr_ctx->pac_ctx,
- my_range_map, my_dom_sid, pr_ctx->logon_info,
- &pr_ctx->gid_count, &pr_ctx->gids);
+ pac_add_user_next(pr_ctx);
+}
+
+static void pac_add_user_next(struct pac_req_ctx *pr_ctx)
+{
+ int ret;
+ struct tevent_req *req;
+ struct cli_ctx *cctx = pr_ctx->cctx;
+
+ ret = save_pac_user(pr_ctx);
if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, ("get_gids_from_pac failed.\n"));
+ DEBUG(SSSDBG_OP_FAILURE, ("save_pac_user failed.\n"));
goto done;
}
- ret = diff_gid_lists(pr_ctx,
- pr_ctx->current_grp_count, pr_ctx->current_grp_list,
- pr_ctx->gid_count, pr_ctx->gids,
- &pr_ctx->add_gid_count, &pr_ctx->add_gids,
- &pr_ctx->del_grp_count, &pr_ctx->del_grp_list);
+ ret = pac_user_get_grp_info(pr_ctx, pr_ctx, &pr_ctx->del_grp_count,
+ &pr_ctx->del_grp_list,
+ &pr_ctx->add_sid_count, &pr_ctx->add_sids);
if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, ("diff_gid_lists failed.\n"));
+ DEBUG(SSSDBG_OP_FAILURE, ("pac_user_get_grp_info failed.\n"));
goto done;
}
@@ -261,23 +366,40 @@ static errno_t pac_add_user_next(struct pac_req_ctx *pr_ctx)
ret = EAGAIN;
done:
- return ret;
+ if (ret != EAGAIN) {
+ talloc_free(pr_ctx);
+ }
+ pac_cmd_done(cctx, ret);
}
static errno_t pac_user_get_grp_info(TALLOC_CTX *mem_ctx,
struct pac_req_ctx *pr_ctx,
- size_t *_current_grp_count,
- struct grp_info **_current_grp_list)
+ size_t *_del_grp_count,
+ struct grp_info **_del_grp_list,
+ size_t *_add_sid_count,
+ char ***_add_sids)
{
struct sysdb_ctx *sysdb;
int ret;
TALLOC_CTX *tmp_ctx = NULL;
struct ldb_result *res = NULL;
- struct grp_info *current_grp_list = NULL;
- size_t current_grp_count = 0;
size_t c;
const char *tmp_str;
+ size_t add_sid_count = 0;
+ char **add_sids = NULL;
+
+ size_t del_idx;
+ size_t del_grp_count = 0;
+ struct grp_info *del_grp_list = NULL;
+
+ const char *cur_sid;
+ hash_key_t key;
+ hash_value_t value;
+
+ struct hash_iter_context_t *iter = NULL;
+ hash_entry_t *entry;
+
sysdb = pr_ctx->dom->sysdb;
if (sysdb == NULL) {
ret = EINVAL;
@@ -299,55 +421,118 @@ static errno_t pac_user_get_grp_info(TALLOC_CTX *mem_ctx,
goto done;
}
+ if (res->count == 0) {
+ DEBUG(SSSDBG_OP_FAILURE, ("sysdb_initgroups did not found [%s].\n",
+ pr_ctx->user_name));
+ ret = ENOENT;
+ goto done;
+ }
+
/* First result is the user entry then the groups follow */
if (res->count > 1) {
- current_grp_count = res->count - 1;
- current_grp_list = talloc_array(tmp_ctx, struct grp_info,
- current_grp_count);
- if (current_grp_list == NULL) {
+ del_grp_count = res->count - 1;
+ del_grp_list = talloc_zero_array(tmp_ctx, struct grp_info,
+ del_grp_count);
+ if (del_grp_list == NULL) {
DEBUG(SSSDBG_OP_FAILURE, ("talloc_array failed.\n"));
ret = ENOMEM;
goto done;
}
+ del_idx = 0;
- for (c = 0; c < current_grp_count; c++) {
- current_grp_list[c].gid =
- ldb_msg_find_attr_as_uint64(res->msgs[c + 1],
- SYSDB_GIDNUM, 0);
- if (current_grp_list[c].gid == 0) {
- DEBUG(SSSDBG_OP_FAILURE, ("Missing GID.\n"));
+ key.type = HASH_KEY_STRING;
+
+ for (c = 0; c < (res->count - 1); c++) {
+ cur_sid = ldb_msg_find_attr_as_string(res->msgs[c + 1],
+ SYSDB_SID_STR, NULL);
+ if (cur_sid == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Missing SID in group entry.\n"));
ret = EINVAL;
goto done;
}
- tmp_str = ldb_msg_find_attr_as_string(res->msgs[c + 1],
- SYSDB_ORIG_DN, NULL);
- if (tmp_str != NULL) {
- current_grp_list[c].orig_dn = talloc_strdup(current_grp_list,
- tmp_str);
- if (current_grp_list[c].orig_dn == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n"));
+ key.str = discard_const(cur_sid);
+ ret = hash_lookup(pr_ctx->sid_table, &key, &value);
+ if (ret == HASH_SUCCESS) {
+ /* user is already member of the group */
+ ret = hash_delete(pr_ctx->sid_table, &key);
+ if (ret != HASH_SUCCESS) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Failed to remove hash entry.\n"));
+ ret = EIO;
+ goto done;
+ }
+ } else if (ret == HASH_ERROR_KEY_NOT_FOUND) {
+ /* group is not in the PAC anymore, membership must be removed */
+ del_grp_list[del_idx].gid =
+ ldb_msg_find_attr_as_uint64(res->msgs[c + 1],
+ SYSDB_GIDNUM, 0);
+ if (del_grp_list[del_idx].gid == 0) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Missing GID.\n"));
+ ret = EINVAL;
+ goto done;
+ }
+
+ tmp_str = ldb_msg_find_attr_as_string(res->msgs[c + 1],
+ SYSDB_ORIG_DN, NULL);
+ if (tmp_str != NULL) {
+ del_grp_list[del_idx].orig_dn = talloc_strdup(del_grp_list,
+ tmp_str);
+ if (del_grp_list[del_idx].orig_dn == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+
+ del_grp_list[del_idx].dn = ldb_dn_copy(del_grp_list,
+ res->msgs[c + 1]->dn);
+ if (del_grp_list[del_idx].dn == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("ldb_dn_copy failed.\n"));
ret = ENOMEM;
goto done;
}
+
+ del_idx++;
}
+ }
+ del_grp_count = del_idx;
+ }
- current_grp_list[c].dn = ldb_dn_copy(current_grp_list,
- res->msgs[c + 1]->dn);
- if (current_grp_list[c].dn == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("ldb_dn_copy failed.\n"));
- ret = ENOMEM;
- goto done;
+ add_sid_count = hash_count(pr_ctx->sid_table);
+ if (add_sid_count > 0) {
+ add_sids = talloc_array(tmp_ctx, char *, add_sid_count);
+ if (add_sids == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("talloc_array failed.\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+
+ iter = new_hash_iter_context(pr_ctx->sid_table);
+ c = 0;
+ while ((entry = iter->next(iter)) != NULL) {
+ if (strcmp(entry->key.str, pr_ctx->user_sid_str) != 0) {
+ add_sids[c] = talloc_strdup(add_sids, entry->key.str);
+ if (add_sids[c] == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+ c++;
}
}
+ add_sid_count = c;
}
- *_current_grp_count = current_grp_count;
- *_current_grp_list = talloc_steal(mem_ctx, current_grp_list);
+
+ *_del_grp_count = del_grp_count;
+ *_del_grp_list = talloc_steal(mem_ctx, del_grp_list);
+ *_add_sid_count = add_sid_count;
+ *_add_sids = talloc_steal(mem_ctx, add_sids);
ret = EOK;
done:
+ talloc_free(iter);
talloc_free(tmp_ctx);
return ret;
@@ -357,7 +542,9 @@ static errno_t save_pac_user(struct pac_req_ctx *pr_ctx)
{
struct sysdb_ctx *sysdb;
int ret;
- const char *attrs[] = {SYSDB_NAME, SYSDB_UIDNUM, SYSDB_GIDNUM, NULL};
+ const char *attrs[] = {SYSDB_NAME, SYSDB_NAME_ALIAS, SYSDB_UIDNUM,
+ SYSDB_GIDNUM, SYSDB_GECOS, SYSDB_HOMEDIR,
+ SYSDB_SHELL, NULL};
struct ldb_message *msg;
struct passwd *pwd = NULL;
TALLOC_CTX *tmp_ctx = NULL;
@@ -377,7 +564,8 @@ static errno_t save_pac_user(struct pac_req_ctx *pr_ctx)
goto done;
}
- ret = get_pwd_from_pac(tmp_ctx, pr_ctx->pac_ctx, pr_ctx->dom,
+ ret = get_pwd_from_pac(tmp_ctx, pr_ctx->dom, pr_ctx->user_sid_str,
+ pr_ctx->primary_group_sid_str, pr_ctx->sid_table,
pr_ctx->logon_info, &pwd, &user_attrs);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, ("get_pwd_from_pac failed.\n"));
@@ -420,12 +608,10 @@ done:
}
struct pac_save_memberships_state {
- size_t gid_iter;
- size_t dom_iter;
+ size_t sid_iter;
struct ldb_dn *user_dn;
struct pac_req_ctx *pr_ctx;
- struct sss_domain_info *group_dom;
};
static errno_t
@@ -437,28 +623,34 @@ struct tevent_req *pac_save_memberships_send(struct pac_req_ctx *pr_ctx)
struct sss_domain_info *dom = pr_ctx->dom;
struct tevent_req *req;
errno_t ret;
+ char *fq_name = NULL;
req = tevent_req_create(pr_ctx, &state, struct pac_save_memberships_state);
if (req == NULL) {
return NULL;
}
- state->gid_iter = 0;
- state->dom_iter = 0;
- state->user_dn = sysdb_user_dn(dom->sysdb, state, dom, pr_ctx->fq_name);
+ state->sid_iter = 0;
+ if (IS_SUBDOMAIN(dom)) {
+ fq_name = sss_tc_fqname(pr_ctx, pr_ctx->dom->names, pr_ctx->dom,
+ pr_ctx->user_name);
+ if (fq_name == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("talloc_sprintf failed.\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+
+ state->user_dn = sysdb_user_dn(dom->sysdb, state, dom, fq_name);
+ } else {
+ state->user_dn = sysdb_user_dn(dom->sysdb, state, dom,
+ pr_ctx->user_name);
+ }
if (state->user_dn == NULL) {
ret = ENOMEM;
goto done;
}
state->pr_ctx = pr_ctx;
- /* Remote users are members of local groups */
- if (IS_SUBDOMAIN(pr_ctx->dom)) {
- state->group_dom = pr_ctx->dom->parent;
- } else {
- state->group_dom = pr_ctx->dom;
- }
-
ret = pac_save_memberships_delete(state);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, ("pac_save_memberships_delete failed.\n"));
@@ -472,6 +664,7 @@ struct tevent_req *pac_save_memberships_send(struct pac_req_ctx *pr_ctx)
}
done:
+ talloc_free(fq_name);
if (ret != EOK && ret != EAGAIN) {
tevent_req_error(req, ret);
tevent_req_post(req, pr_ctx->cctx->ev);
@@ -515,7 +708,7 @@ pac_save_memberships_delete(struct pac_save_memberships_state *state)
goto done;
}
- ret = sysdb_transaction_start(state->group_dom->sysdb);
+ ret = sysdb_transaction_start(pr_ctx->dom->sysdb);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, ("sysdb_transaction_start failed.\n"));
goto done;
@@ -523,17 +716,17 @@ pac_save_memberships_delete(struct pac_save_memberships_state *state)
in_transaction = true;
for (c = 0; c < pr_ctx->del_grp_count; c++) {
- ret = sysdb_mod_group_member(state->group_dom->sysdb, state->user_dn,
- pr_ctx->del_grp_list[c]->dn,
+ ret = sysdb_mod_group_member(pr_ctx->dom->sysdb, state->user_dn,
+ pr_ctx->del_grp_list[c].dn,
LDB_FLAG_MOD_DELETE);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, ("sysdb_mod_group_member failed.\n"));
goto done;
}
- if (pr_ctx->del_grp_list[c]->orig_dn != NULL) {
+ if (pr_ctx->del_grp_list[c].orig_dn != NULL) {
ret = sysdb_attrs_add_string(user_attrs, SYSDB_ORIG_MEMBEROF,
- pr_ctx->del_grp_list[c]->orig_dn);
+ pr_ctx->del_grp_list[c].orig_dn);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_add_string failed.\n"));
goto done;
@@ -548,7 +741,7 @@ pac_save_memberships_delete(struct pac_save_memberships_state *state)
goto done;
}
- ret = sysdb_transaction_commit(state->group_dom->sysdb);
+ ret = sysdb_transaction_commit(pr_ctx->dom->sysdb);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, ("sysdb_transaction_commit failed.\n"));
goto done;
@@ -558,7 +751,7 @@ pac_save_memberships_delete(struct pac_save_memberships_state *state)
ret = EOK;
done:
if (in_transaction) {
- sret = sysdb_transaction_cancel(state->group_dom->sysdb);
+ sret = sysdb_transaction_cancel(pr_ctx->dom->sysdb);
if (sret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, ("sysdb_transaction_cancel failed.\n"));
}
@@ -573,43 +766,46 @@ static errno_t pac_save_memberships_next(struct tevent_req *req)
{
errno_t ret;
uint32_t gid;
+ char *sid;
struct sss_domain_info *grp_dom;
struct tevent_req *subreq;
struct pac_save_memberships_state *state;
struct pac_req_ctx *pr_ctx;
+ hash_key_t key;
+ hash_value_t value;
+
+ key.type = HASH_KEY_STRING;
state = tevent_req_data(req, struct pac_save_memberships_state);
pr_ctx = state->pr_ctx;
- if (pr_ctx->add_gid_count == 0) {
+ if (pr_ctx->add_sid_count == 0) {
return EOK;
}
- if (pr_ctx->add_gids == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("Missing group list.\n"));
+ if (pr_ctx->add_sids == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Missing list of SIDs.\n"));
return EINVAL;
}
- while (pr_ctx->add_gids[state->dom_iter].grp_dom != NULL) {
-
- if (pr_ctx->add_gids[state->dom_iter].gids == NULL ||
- pr_ctx->add_gids[state->dom_iter].gid_count == 0) {
- state->dom_iter++;
- state->gid_iter = 0;
- continue;
+ while (state->sid_iter < pr_ctx->add_sid_count) {
+ sid = pr_ctx->add_sids[state->sid_iter];
+ ret = responder_get_domain_by_id(pr_ctx->pac_ctx->rctx, sid, &grp_dom);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("responder_get_domain_by_id failed.\n"));
+ return ret;
}
-
-
- gid = pr_ctx->add_gids[state->dom_iter].gids[state->gid_iter];
- grp_dom = pr_ctx->add_gids[state->dom_iter].grp_dom;
+ key.str = sid;
+ ret = hash_lookup(pr_ctx->sid_table, &key, &value);
+ if (ret != HASH_SUCCESS) {
+ DEBUG(SSSDBG_OP_FAILURE, ("hash_lookup failed.\n"));
+ return EIO;
+ }
+ gid = value.ul;
ret = pac_store_membership(state->pr_ctx, state->user_dn, gid, grp_dom);
if (ret == EOK) {
- state->gid_iter++;
- if (state->gid_iter >= pr_ctx->add_gids[state->dom_iter].gid_count) {
- state->dom_iter++;
- state->gid_iter = 0;
- }
+ state->sid_iter++;
continue;
} else if (ret == ENOENT) {
subreq = sss_dp_get_account_send(state, pr_ctx->cctx->rctx,
@@ -646,8 +842,13 @@ static void pac_get_group_done(struct tevent_req *subreq)
dbus_uint32_t err_min;
char *err_msg;
gid_t gid;
+ char *sid;
struct sss_domain_info *grp_dom;
struct pac_req_ctx *pr_ctx = state->pr_ctx;
+ hash_key_t key;
+ hash_value_t value;
+
+ key.type = HASH_KEY_STRING;
ret = sss_dp_get_account_recv(req, subreq,
&err_maj, &err_min,
@@ -658,17 +859,27 @@ static void pac_get_group_done(struct tevent_req *subreq)
goto error;
}
- gid = pr_ctx->add_gids[state->dom_iter].gids[state->gid_iter];
- grp_dom = pr_ctx->add_gids[state->dom_iter].grp_dom;
- ret = pac_store_membership(state->pr_ctx, state->user_dn, gid, grp_dom);
+ sid = pr_ctx->add_sids[state->sid_iter];
+ ret = responder_get_domain_by_id(pr_ctx->pac_ctx->rctx,sid, &grp_dom);
if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("responder_get_domain_by_id failed.\n"));
goto error;
}
- state->gid_iter++;
- if (state->gid_iter >= pr_ctx->add_gids[state->dom_iter].gid_count) {
- state->dom_iter++;
- state->gid_iter = 0;
+
+ key.str = sid;
+ ret = hash_lookup(pr_ctx->sid_table, &key, &value);
+ if (ret != HASH_SUCCESS) {
+ DEBUG(SSSDBG_OP_FAILURE, ("hash_lookup failed.\n"));
+ ret = EIO;
+ goto error;
}
+ gid = value.ul;
+
+ ret = pac_store_membership(state->pr_ctx, state->user_dn, gid, grp_dom);
+ if (ret != EOK) {
+ goto error;
+ }
+ state->sid_iter++;
ret = pac_save_memberships_next(req);
if (ret == EOK) {
@@ -765,6 +976,117 @@ static void pac_save_memberships_done(struct tevent_req *req)
pac_cmd_done(cctx, ret);
}
+struct pac_lookup_sids_state {
+ struct pac_ctx *pac_ctx;
+ struct pac_req_ctx *pr_ctx;
+ hash_table_t *sid_table;
+ struct hash_iter_context_t *iter;
+};
+
+static errno_t pac_lookup_sids_next(struct tevent_req *req);
+static void pac_lookup_sids_next_done(struct tevent_req *subreq);
+
+static struct tevent_req *pac_lookup_sids_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct pac_req_ctx *pr_ctx,
+ struct pac_ctx *pac_ctx,
+ hash_table_t *sid_table)
+{
+ struct tevent_req *req;
+ struct pac_lookup_sids_state *state;
+ int ret;
+
+ req = tevent_req_create(mem_ctx, &state, struct pac_lookup_sids_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ state->pac_ctx = pac_ctx;
+ state->pr_ctx = pr_ctx;
+ state->sid_table = sid_table;
+ state->iter = talloc_steal(state, new_hash_iter_context(state->sid_table));
+
+ ret = pac_lookup_sids_next(req);
+
+ if (ret != EAGAIN) {
+ if (ret == EOK) {
+ tevent_req_done(req);
+ } else {
+ tevent_req_error(req, ret);
+ }
+ tevent_req_post(req, ev);
+ }
+
+ return req;
+}
+
+
+static errno_t pac_lookup_sids_next(struct tevent_req *req)
+{
+ struct pac_lookup_sids_state *state;
+ state = tevent_req_data(req, struct pac_lookup_sids_state);
+ hash_entry_t *entry;
+ struct tevent_req *subreq;
+ struct sss_domain_info *dom;
+ int ret;
+
+ while ((entry = state->iter->next(state->iter)) != NULL) {
+ if (entry->value.ul == 0) {
+ ret = responder_get_domain_by_id(state->pac_ctx->rctx,
+ entry->key.str, &dom);
+ if (ret == EOK && dom != NULL) {
+ subreq = sss_dp_get_account_send(state,
+ state->pr_ctx->cctx->rctx,
+ dom, true,
+ SSS_DP_SECID, entry->key.str,
+ 0, NULL);
+ if (subreq == NULL) {
+ return ENOMEM;
+ }
+ tevent_req_set_callback(subreq, pac_lookup_sids_next_done, req);
+ return EAGAIN;
+ }
+ }
+ }
+
+ return EOK;
+}
+
+static void pac_lookup_sids_next_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+
+ errno_t ret;
+ dbus_uint16_t err_maj;
+ dbus_uint32_t err_min;
+ char *err_msg;
+
+ ret = sss_dp_get_account_recv(req, subreq,
+ &err_maj, &err_min,
+ &err_msg);
+ talloc_zfree(subreq);
+ talloc_zfree(err_msg);
+ /* Errors during individual lookups are ignored. */
+
+ ret = pac_lookup_sids_next(req);
+ if (ret == EOK) {
+ tevent_req_done(req);
+ } else if (ret != EAGAIN) {
+ tevent_req_error(req, ret);
+ }
+
+ return;
+}
+
+static errno_t pac_lookup_sids_recv(struct tevent_req *req)
+{
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ return EOK;
+}
+
struct cli_protocol_version *register_cli_protocol_version(void)
{
static struct cli_protocol_version pac_cli_protocol_version[] = {