summaryrefslogtreecommitdiffstats
path: root/src/responder/pac/pacsrv_cmd.c
diff options
context:
space:
mode:
authorSumit Bose <sbose@redhat.com>2013-05-10 09:55:31 +0200
committerJakub Hrozek <jhrozek@redhat.com>2013-06-06 23:58:56 +0200
commit92af6f25864b5c389b57d0f659686801b45ca58c (patch)
tree739bd3da9da35820d45c2b2c4bdb0c65ae8777d4 /src/responder/pac/pacsrv_cmd.c
parent3680bb9c72ea5c60e6ac2fd2cf500b801341ca59 (diff)
downloadsssd-92af6f25864b5c389b57d0f659686801b45ca58c.tar.gz
sssd-92af6f25864b5c389b57d0f659686801b45ca58c.tar.xz
sssd-92af6f25864b5c389b57d0f659686801b45ca58c.zip
Enhance PAC responder for AD users
This patch modifies the PAC responder so that it can be used with the AD provider as well. The main difference is that the POSIX UIDs and GIDs are now lookup up with the help of the SID instead of being calculated algorithmically. This was necessary because the AD provider allows either algorithmic mapping or reading the value from attributes stored in AD. Fixes https://fedorahosted.org/sssd/ticket/1558
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 8f5617c7f..c3f1115e7 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[] = {