summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am21
-rw-r--r--src/man/sssd.conf.5.xml20
-rw-r--r--src/responder/pac/pacsrv.h61
-rw-r--r--src/responder/pac/pacsrv_cmd.c588
-rw-r--r--src/responder/pac/pacsrv_utils.c937
-rw-r--r--src/sss_client/sssd_pac.c62
-rw-r--r--src/tests/pac_responder-tests.c524
7 files changed, 716 insertions, 1497 deletions
diff --git a/Makefile.am b/Makefile.am
index 71ddf05d1..b5cc58971 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -134,10 +134,6 @@ if HAVE_CHECK
sss_idmap-tests \
responder_socket_access-tests
-if BUILD_PAC_RESPONDER
- non_interactive_check_based_tests += pac_responder-tests
-endif
-
if BUILD_SSH
non_interactive_check_based_tests += sysdb_ssh-tests
endif
@@ -1152,23 +1148,6 @@ sss_idmap_tests_LDADD = \
libsss_test_common.la \
libsss_idmap.la
-pac_responder_tests_SOURCES = \
- src/tests/pac_responder-tests.c \
- src/responder/pac/pacsrv_utils.c
-pac_responder_tests_CFLAGS = \
- $(AM_CFLAGS) \
- $(NDR_KRB5PAC_CFLAGS) \
- $(CHECK_CFLAGS)
-pac_responder_tests_LDADD = \
- $(CHECK_LIBS) \
- $(TALLOC_LIBS) \
- $(NDR_KRB5PAC_LIBS) \
- $(SSSD_LIBS) \
- -lm \
- libsss_idmap.la \
- $(SSSD_INTERNAL_LTLIBS) \
- libsss_test_common.la
-
responder_socket_access_tests_SOURCES = \
src/tests/responder_socket_access-tests.c \
src/responder/common/responder_common.c \
diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
index 3bb1ca760..c2e475b5a 100644
--- a/src/man/sssd.conf.5.xml
+++ b/src/man/sssd.conf.5.xml
@@ -848,16 +848,16 @@ override_homedir = /home/%u
following operations are done:
<itemizedlist>
<listitem><para>If the remote user does not exist in the
- cache, it is created. The uid is calculated based on the
- SID, trusted domains will have UPGs and the gid will have
- the same value as the uid. The home directory is set based
- on the subdomain_homedir parameter. The shell will be empty
- by default, i.e. the system defaults are used, but can be
- overwritten with the default_shell parameter.</para>
- </listitem>
- <listitem><para>If there are SIDs of groups from the domain
- the sssd client belongs to, the user will be added to those
- groups.</para></listitem>
+ cache, it is created. The uid is determined with the help
+ of the SID, trusted domains will have UPGs and the gid
+ will have the same value as the uid. The home directory is
+ set based on the subdomain_homedir parameter. The shell will
+ be empty by default, i.e. the system defaults are used, but
+ can be overwritten with the default_shell parameter.</para>
+ </listitem>
+ <listitem><para>If there are SIDs of groups from domains
+ sssd knows about, the user will be added to those groups.
+ </para></listitem>
</itemizedlist>
</para>
<para>
diff --git a/src/responder/pac/pacsrv.h b/src/responder/pac/pacsrv.h
index 71c24f979..6477e4499 100644
--- a/src/responder/pac/pacsrv.h
+++ b/src/responder/pac/pacsrv.h
@@ -54,80 +54,33 @@ struct pac_ctx {
struct local_mapping_ranges *range_map;
};
-struct range {
- uint32_t min;
- uint32_t max;
-};
-
-struct local_mapping_ranges {
- struct range local_ids;
- struct range primary_rids;
- struct range secondary_rids;
-};
-
struct grp_info {
gid_t gid;
char *orig_dn;
struct ldb_dn *dn;
};
-struct pac_dom_grps {
- struct sss_domain_info *grp_dom;
- size_t gid_count;
- gid_t *gids;
-};
-
struct sss_cmd_table *get_pac_cmds(void);
-errno_t local_sid_to_id(struct local_mapping_ranges *map, struct dom_sid *sid,
- uint32_t *id);
-
-errno_t add_idmap_domain(struct sss_idmap_ctx *idmap_ctx,
- struct sysdb_ctx *sysdb,
- const char *domain_name,
- const char *dom_sid_str);
-
-errno_t domsid_rid_to_uid(struct pac_ctx *pac_ctx,
- struct sysdb_ctx *sysdb,
- const char *domain_name,
- struct dom_sid2 *domsid, uint32_t rid,
- uid_t *uid);
-
-errno_t get_parent_domain_data(struct pac_ctx *pac_ctx,
- struct sss_domain_info *dom,
- struct dom_sid **_sid,
- struct local_mapping_ranges **_range_map);
-
-errno_t get_gids_from_pac(TALLOC_CTX *mem_ctx,
+errno_t get_sids_from_pac(TALLOC_CTX *mem_ctx,
struct pac_ctx *pac_ctx,
- struct local_mapping_ranges *range_map,
- struct dom_sid *domain_sid,
struct PAC_LOGON_INFO *logon_info,
- size_t *_gid_count, struct pac_dom_grps **_gids);
+ char **_user_sid_str,
+ char **_primary_group_sid_str,
+ hash_table_t **_sid_table);
errno_t get_data_from_pac(TALLOC_CTX *mem_ctx,
uint8_t *pac_blob, size_t pac_len,
struct PAC_LOGON_INFO **_logon_info);
errno_t get_pwd_from_pac(TALLOC_CTX *mem_ctx,
- struct pac_ctx *pac_ctx,
struct sss_domain_info *dom,
+ char *user_sid_str,
+ char *primary_group_sid_str,
+ hash_table_t *sid_table,
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,
- struct pac_dom_grps *new_gid_list,
- size_t *_add_gid_num,
- struct pac_dom_grps **_add_gid_list,
- size_t *_del_gid_num,
- struct grp_info ***_del_gid_list);
-
-struct sss_domain_info *find_domain_by_id(struct sss_domain_info *domains,
- const char *id_str);
-
bool new_and_cached_user_differs(struct passwd *pwd, struct ldb_message *msg);
#endif /* __PACSRV_H__ */
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[] = {
diff --git a/src/responder/pac/pacsrv_utils.c b/src/responder/pac/pacsrv_utils.c
index bcea640b8..e7e15ac50 100644
--- a/src/responder/pac/pacsrv_utils.c
+++ b/src/responder/pac/pacsrv_utils.c
@@ -25,355 +25,6 @@
#include "util/util.h"
#include "responder/pac/pacsrv.h"
-static errno_t get_rid(struct dom_sid *sid, uint32_t *rid)
-{
- if (sid == NULL || sid->num_auths < 1 || rid == NULL) {
- return EINVAL;
- }
-
- *rid = sid->sub_auths[sid->num_auths - 1];
-
- return EOK;
-}
-
-/**
- * Find the Posix ID to a SID from the local IPA domain
- */
-errno_t local_sid_to_id(struct local_mapping_ranges *map, struct dom_sid *sid,
- uint32_t *id)
-{
- int ret;
- uint32_t rid;
-
- if (map == NULL || sid == NULL || id == NULL) {
- return EINVAL;
- }
-
- ret = get_rid(sid, &rid);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, ("get_rid failed.\n"));
- return ret;
- }
-
- if (rid >= map->primary_rids.min && rid <= map->primary_rids.max) {
- *id = map->local_ids.min + (rid - map->primary_rids.min);
- } else if (rid >= map->secondary_rids.min &&
- rid <= map->secondary_rids.max) {
- *id = map->local_ids.min + (rid - map->secondary_rids.min);
- } else {
- return ENOENT;
- }
-
- if (*id < map->local_ids.min || *id > map->local_ids.max) {
- return ERANGE;
- }
-
- return EOK;
-}
-
-struct sss_domain_info *find_domain_by_id(struct sss_domain_info *domains,
- const char *id_str)
-{
- struct sss_domain_info *dom;
- struct sss_domain_info *ret_dom = NULL;
-
- if (id_str == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("Missing domain id.\n"));
- return NULL;
- }
-
- for (dom = domains; dom; dom = get_next_domain(dom, true)) {
- if (dom->domain_id == NULL) {
- continue;
- }
-
- if (strcasecmp(dom->domain_id, id_str) == 0) {
- ret_dom = dom;
- break;
- }
- }
-
- if (!ret_dom) {
- DEBUG(SSSDBG_OP_FAILURE, ("No domain with domain ID [%s] found.\n",
- id_str));
- }
-
- return ret_dom;
-}
-
-/**
- * Add a new remote domain and the corresponding ID range to the context of
- * the libsss_idmap. Without this it is not possible to find the Posix UID for
- * a user fo the remote domain.
- */
-errno_t add_idmap_domain(struct sss_idmap_ctx *idmap_ctx,
- struct sysdb_ctx *sysdb,
- const char *domain_name,
- const char *dom_sid_str)
-{
- struct sss_idmap_range range = {0, 0};
- enum idmap_error_code err;
- TALLOC_CTX *tmp_ctx = NULL;
- size_t range_count;
- struct range_info **range_list;
- size_t c;
- int ret;
-
- if (domain_name == NULL || dom_sid_str == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("Missing domain name or SID.\n"));
- return EINVAL;
- }
-
- tmp_ctx = talloc_new(NULL);
- if (tmp_ctx == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("talloc_new failed.\n"));
- return ENOMEM;
- }
-
- ret = sysdb_get_ranges(tmp_ctx, sysdb, &range_count, &range_list);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, ("sysdb_get_ranges failed.\n"));
- goto done;
- }
-
- for (c = 0; c < range_count; c++) {
- if (range_list[c]->trusted_dom_sid != NULL &&
- strcmp(range_list[c]->trusted_dom_sid, dom_sid_str) == 0) {
- range.min = range_list[c]->base_id;
- range.max = range_list[c]->base_id +
- range_list[c]->id_range_size - 1;
- /* TODO: add support for multiple ranges. */
- break;
- }
- }
-
- if (range.min == 0 && range.max == 0) {
- DEBUG(SSSDBG_OP_FAILURE, ("Failed to find mapping range for domain "
- "[%s][%s].\n", domain_name, dom_sid_str));
- ret = ENOENT;
- goto done;
- }
-
- err = sss_idmap_add_domain(idmap_ctx, domain_name, dom_sid_str, &range);
- if (err != IDMAP_SUCCESS) {
- DEBUG(SSSDBG_OP_FAILURE, ("sss_idmap_add_domain failed.\n"));
- return EFAULT;
- }
-
- ret = EOK;
-
-done:
- talloc_free(tmp_ctx);
- return ret;
-}
-
-/**
- * Find the corresponding UID for a user from a remote domain based on the
- * domain SID of the remote domain and the RID of the user.
- */
-errno_t domsid_rid_to_uid(struct pac_ctx *pac_ctx,
- struct sysdb_ctx *sysdb,
- const char *domain_name,
- struct dom_sid2 *domsid, uint32_t rid,
- uid_t *uid)
-{
- enum idmap_error_code err;
- char *sid_str = NULL;
- char *dom_sid_str = NULL;
- uint32_t id;
- int ret;
-
- err = sss_idmap_smb_sid_to_sid(pac_ctx->idmap_ctx, domsid,
- &dom_sid_str);
- if (err != IDMAP_SUCCESS) {
- DEBUG(SSSDBG_OP_FAILURE, ("sss_idmap_smb_sid_to_sid failed.\n"));
- ret = EFAULT;
- goto done;
- }
-
- sid_str = talloc_asprintf(NULL, "%s-%lu", dom_sid_str, (unsigned long) rid);
- if (sid_str == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("dom_sid_and_rid_string failed.\n"));
- return ENOMEM;
- }
-
- err = sss_idmap_sid_to_unix(pac_ctx->idmap_ctx, sid_str, &id);
- if (err == IDMAP_NO_DOMAIN) {
- ret = add_idmap_domain(pac_ctx->idmap_ctx, sysdb, domain_name,
- dom_sid_str);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, ("add_idmap_domain failed.\n"));
- goto done;
- }
-
- err = sss_idmap_sid_to_unix(pac_ctx->idmap_ctx, sid_str, &id);
- if (err != IDMAP_SUCCESS) {
- DEBUG(SSSDBG_FATAL_FAILURE, ("sss_idmap_sid_to_unix failed "
- "even in the second attempt.\n"));
- ret = ENOENT;
- goto done;
- }
- } else if (err != IDMAP_SUCCESS && err != IDMAP_NO_DOMAIN) {
- DEBUG(SSSDBG_OP_FAILURE, ("sss_idmap_sid_to_unix failed.\n"));
- ret = EFAULT;
- goto done;
- }
-
- *uid = (uid_t) id;
-
- ret = EOK;
-
-done:
- talloc_free(dom_sid_str);
- talloc_free(sid_str);
- return ret;
-}
-
-/**
- * Return information about the local domain from the main PAC responder
- * context or try to read it from cache and store it in the context.
- */
-errno_t get_parent_domain_data(struct pac_ctx *pac_ctx,
- struct sss_domain_info *dom,
- struct dom_sid **_sid,
- struct local_mapping_ranges **_range_map)
-{
- struct sysdb_ctx *sysdb;
- int ret;
- struct ldb_dn *basedn;
- const char *attrs[] = {SYSDB_SUBDOMAIN_ID,
- NULL};
- size_t msgs_count;
- const char *sid_str;
- struct ldb_message **msgs;
- TALLOC_CTX *tmp_ctx = NULL;
- struct dom_sid *sid = NULL;
- enum idmap_error_code err;
- size_t range_count;
- struct range_info **range_list;
- struct local_mapping_ranges *r_map = NULL;
- size_t c;
-
- if (pac_ctx->my_dom_sid == NULL || pac_ctx->range_map == NULL) {
- sysdb = dom->sysdb;
-
- if (sysdb == NULL) {
- DEBUG(SSSDBG_FATAL_FAILURE, ("Missing sysdb context.\n"));
- ret = EINVAL;
- goto done;
- }
-
- tmp_ctx = talloc_new(NULL);
- if (tmp_ctx == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("talloc_new failed.\n"));
- ret = ENOMEM;
- goto done;
- }
-
- /* The data of the parent domain should be read here. */
- basedn = sysdb_domain_dn(sysdb, tmp_ctx,
- IS_SUBDOMAIN(dom) ? dom->parent : dom);
- if (basedn == NULL) {
- ret = ENOMEM;
- goto done;
- }
-
- if (pac_ctx->my_dom_sid == NULL) {
- ret = sysdb_search_entry(tmp_ctx, sysdb, basedn, LDB_SCOPE_BASE, NULL,
- attrs, &msgs_count, &msgs);
- if (ret != LDB_SUCCESS) {
- ret = EIO;
- goto done;
- }
-
- if (msgs_count != 1) {
- DEBUG(SSSDBG_OP_FAILURE, ("Base search returned [%d] results, "
- "expected 1.\n", msgs_count));
- ret = EINVAL;
- goto done;
- }
-
- sid_str = ldb_msg_find_attr_as_string(msgs[0], SYSDB_SUBDOMAIN_ID, NULL);
- if (sid_str == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("SID of my domain is not available.\n"));
- ret = EINVAL;
- goto done;
- }
-
- err = sss_idmap_sid_to_smb_sid(pac_ctx->idmap_ctx, sid_str, &sid);
- if (err != IDMAP_SUCCESS) {
- DEBUG(SSSDBG_OP_FAILURE, ("sss_idmap_sid_to_smb_sid failed.\n"));
- ret = EFAULT;
- goto done;
- }
-
- pac_ctx->my_dom_sid = talloc_memdup(pac_ctx, sid,
- sizeof(struct dom_sid));
- if (pac_ctx->my_dom_sid == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("talloc_memdup failed.\n"));
- ret = ENOMEM;
- goto done;
- }
- }
-
- if (pac_ctx->range_map == NULL) {
- ret = sysdb_get_ranges(tmp_ctx, sysdb, &range_count, &range_list);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, ("sysdb_get_ranges failed.\n"));
- goto done;
- }
-
- for (c = 0; c < range_count; c++) {
- if (range_list[c]->trusted_dom_sid == NULL &&
- range_list[c]->secondary_base_rid != 0) {
- r_map = talloc_zero(pac_ctx,
- struct local_mapping_ranges);
- if (r_map == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("talloc_zero failed.\n"));
- ret = ENOMEM;
- goto done;
- }
-
- r_map->local_ids.min = range_list[c]->base_id;
- r_map->local_ids.max = range_list[c]->base_id +
- range_list[c]->id_range_size - 1;
-
- r_map->primary_rids.min = range_list[c]->base_rid;
- r_map->primary_rids.max = range_list[c]->base_rid +
- range_list[c]->id_range_size - 1;
-
- r_map->secondary_rids.min = range_list[c]->secondary_base_rid;
- r_map->secondary_rids.max = range_list[c]->secondary_base_rid +
- range_list[c]->id_range_size - 1;
-
- /* TODO: add support for multiple ranges. */
- break;
- }
- }
-
- if (r_map == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("Failed to find local id map.\n"));
- ret = ENOENT;
- goto done;
- }
-
- pac_ctx->range_map = r_map;
- }
-
- }
-
- *_sid = pac_ctx->my_dom_sid;
- *_range_map = pac_ctx->range_map;
-
- ret = EOK;
-
-done:
- talloc_free(sid);
- talloc_free(tmp_ctx);
-
- return ret;
-}
-
/**
* Check if a given SID belongs to a domain identified by the domain SID.
*/
@@ -409,234 +60,167 @@ bool dom_sid_in_domain(const struct dom_sid *domain_sid,
return true;
}
-
-static errno_t get_dom_grps_from_hash(TALLOC_CTX *mem_ctx,
- hash_table_t *gid_table,
- struct sss_domain_info *grp_dom,
- struct pac_dom_grps *dom_grps)
-{
- int ret;
- size_t gid_count;
- size_t g;
- struct hash_iter_context_t *iter;
- hash_entry_t *entry;
- gid_t *gids = NULL;
-
- if (grp_dom == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("Missing domain for groups.\n"));
- return EINVAL;
- }
-
- gid_count = hash_count(gid_table);
- if (gid_count == 0) {
- DEBUG(SSSDBG_TRACE_FUNC, ("No groups found.\n"));
- ret = EOK;
- goto done;
- }
-
- gids = talloc_zero_array(mem_ctx, gid_t, gid_count);
- if (gids == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("talloc_array failed.\n"));
- ret = ENOMEM;
- goto done;
- }
-
-
- iter = new_hash_iter_context(gid_table);
- if (iter == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("new_hash_iter_context failed.\n"));
- ret = EIO;
- goto done;
- }
-
- g = 0;
- while ((entry = iter->next(iter)) != NULL) {
- gids[g] = entry->key.ul;
- g++;
- }
-
- if (gid_count != g) {
- DEBUG(SSSDBG_OP_FAILURE, ("Number of hash entries and groups do not "
- "match.\n"));
- ret = EINVAL;
- goto done;
- }
-
- ret = EOK;
-
-done:
- if (ret != EOK) {
- talloc_free(gids);
- } else {
- dom_grps->grp_dom = grp_dom;
- dom_grps->gid_count = gid_count;
- dom_grps->gids = gids;
- }
-
- return ret;
-}
-
-/**
- * Find all Posix GIDs from a PAC by searching for group SIDs from the local
- * domain and convert them to GIDs.
- */
-errno_t get_gids_from_pac(TALLOC_CTX *mem_ctx,
+errno_t get_sids_from_pac(TALLOC_CTX *mem_ctx,
struct pac_ctx *pac_ctx,
- struct local_mapping_ranges *range_map,
- struct dom_sid *domain_sid,
struct PAC_LOGON_INFO *logon_info,
- size_t *_gid_count, struct pac_dom_grps **_gids)
+ char **_user_sid_str,
+ char **_primary_group_sid_str,
+ hash_table_t **_sid_table)
{
int ret;
- size_t gid_count = 0;
size_t s;
struct netr_SamInfo3 *info3;
- struct pac_dom_grps *gids = NULL;
- struct sss_domain_info *grp_dom;
+ struct sss_domain_info *user_dom;
+ struct sss_domain_info *group_dom;
char *sid_str = NULL;
+ char *user_dom_sid_str = NULL;
+ size_t user_dom_sid_str_len;
enum idmap_error_code err;
- struct dom_sid *grp_sid = NULL;
- uint32_t id;
- hash_table_t *gid_table;
+ hash_table_t *sid_table = NULL;
hash_key_t key;
hash_value_t value;
- TALLOC_CTX *tmp_ctx = NULL;
+ char *rid_start;
+ struct ldb_result *msg;
+ char *user_sid_str = NULL;
+ char *primary_group_sid_str = NULL;
- if (pac_ctx == NULL || range_map == NULL || domain_sid == NULL ||
- logon_info == NULL || _gid_count == NULL || _gids == NULL) {
+ if (pac_ctx == NULL || logon_info == NULL || _sid_table == NULL) {
DEBUG(SSSDBG_OP_FAILURE, ("Missing parameter.\n"));
return EINVAL;
}
info3 = &logon_info->info3;
- if (info3->sidcount == 0 && info3->base.groups.count == 0) {
- DEBUG(SSSDBG_TRACE_ALL, ("No extra groups found.\n"));
- ret = EOK;
+ ret = sss_hash_create(mem_ctx,
+ info3->sidcount + info3->base.groups.count + 2,
+ &sid_table);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("sss_hash_create failed.\n"));
goto done;
}
- tmp_ctx = talloc_new(NULL);
- if (tmp_ctx == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("talloc_new failed.\n"));
- ret = ENOMEM;
+ key.type = HASH_KEY_STRING;
+ value.type = HASH_VALUE_ULONG;
+
+ err = sss_idmap_smb_sid_to_sid(pac_ctx->idmap_ctx, info3->base.domain_sid,
+ &user_dom_sid_str);
+ if (err != IDMAP_SUCCESS) {
+ DEBUG(SSSDBG_OP_FAILURE, ("sss_idmap_smb_sid_to_sid failed.\n"));
+ ret = EFAULT;
goto done;
}
- /* Currently three group containers are allocated, one for the IPA domain, one
- * for the trusted AD domain and an empty one to indicate the end of the
- * list. */
- gids = talloc_zero_array(tmp_ctx, struct pac_dom_grps, 3);
- if (gids == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("talloc_zero_array failed.\n"));
- ret = ENOMEM;
+ ret = responder_get_domain_by_id(pac_ctx->rctx, user_dom_sid_str,
+ &user_dom);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("responder_get_domain_by_id failed.\n"));
+ ret = EINVAL;
goto done;
}
- ret = sss_hash_create(tmp_ctx, info3->sidcount, &gid_table);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, ("sss_hash_create failed.\n"));
+ user_dom_sid_str_len = strlen(user_dom_sid_str);
+ sid_str = talloc_zero_size(mem_ctx, user_dom_sid_str_len + 12);
+ if (sid_str == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("talloc_zero_size failed.\n"));
+ ret = ENOMEM;
goto done;
}
+ rid_start = sid_str + user_dom_sid_str_len;
- key.type = HASH_KEY_ULONG;
- value.type = HASH_VALUE_PTR;
+ memcpy(sid_str, user_dom_sid_str, user_dom_sid_str_len);
- err = sss_idmap_smb_sid_to_sid(pac_ctx->idmap_ctx, domain_sid,
- &sid_str);
- if (err != IDMAP_SUCCESS) {
- DEBUG(SSSDBG_OP_FAILURE, ("sss_idmap_smb_sid_to_sid failed.\n"));
- ret = EFAULT;
+ memset(rid_start, '\0', 12);
+ ret = snprintf(rid_start, 12, "-%lu",
+ (unsigned long) info3->base.rid);
+ if (ret < 0 || ret > 12) {
+ DEBUG(SSSDBG_OP_FAILURE, ("snprintf failed.\n"));
+ ret = EIO;
goto done;
}
- grp_dom = find_domain_by_id(pac_ctx->rctx->domains, sid_str);
- if (grp_dom == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("find_domain_by_id failed.\n"));
- ret = EINVAL;
+ user_sid_str = talloc_strdup(mem_ctx, sid_str);
+ if (user_sid_str == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n"));
+ ret = ENOMEM;
goto done;
}
- for(s = 0; s < info3->sidcount; s++) {
- if (dom_sid_in_domain(domain_sid, info3->sids[s].sid)) {
- ret = local_sid_to_id(range_map, info3->sids[s].sid,
- &id);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, ("get_rid failed.\n"));
- goto done;
- }
-
- key.ul = id;
- value.ptr = grp_dom;
+ key.str = sid_str;
+ value.ul = 0;
- ret = hash_enter(gid_table, &key, &value);
- if (ret != HASH_SUCCESS) {
- DEBUG(SSSDBG_OP_FAILURE, ("hash_enter failed [%d][%s].\n",
- ret, hash_error_string(ret)));
- ret = EIO;
- goto done;
- }
-
- DEBUG(SSSDBG_TRACE_ALL, ("Found extra group with gid [%d].\n", id));
- }
+ ret = sysdb_search_object_by_sid(mem_ctx, user_dom->sysdb, user_dom,
+ sid_str, NULL, &msg);
+ if (ret == EOK && msg->count == 1) {
+ value.ul = ldb_msg_find_attr_as_uint64(msg->msgs[0], SYSDB_UIDNUM, 0);
+ talloc_free(msg);
}
- ret = get_dom_grps_from_hash(gids, gid_table, grp_dom, &gids[0]);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, ("get_dom_grps_from_hash failed.\n"));
+ ret = hash_enter(sid_table, &key, &value);
+ if (ret != HASH_SUCCESS) {
+ DEBUG(SSSDBG_OP_FAILURE, ("hash_enter failed [%d][%s].\n",
+ ret, hash_error_string(ret)));
+ ret = EIO;
goto done;
}
- gid_count += gids[0].gid_count;
- talloc_free(gid_table);
- ret = sss_hash_create(tmp_ctx, info3->base.groups.count, &gid_table);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, ("sss_hash_create failed.\n"));
+
+ memset(rid_start, '\0', 12);
+ ret = snprintf(rid_start, 12, "-%lu",
+ (unsigned long) info3->base.primary_gid);
+ if (ret < 0 || ret > 12) {
+ DEBUG(SSSDBG_OP_FAILURE, ("snprintf failed.\n"));
+ ret = EIO;
goto done;
}
- talloc_zfree(sid_str);
- err = sss_idmap_smb_sid_to_sid(pac_ctx->idmap_ctx, info3->base.domain_sid,
- &sid_str);
- if (err != IDMAP_SUCCESS) {
- DEBUG(SSSDBG_OP_FAILURE, ("sss_idmap_smb_sid_to_sid failed.\n"));
- ret = EFAULT;
+ primary_group_sid_str = talloc_strdup(mem_ctx, sid_str);
+ if (primary_group_sid_str == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n"));
+ ret = ENOMEM;
goto done;
}
- grp_dom = find_domain_by_id(pac_ctx->rctx->domains, sid_str);
- if (grp_dom == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("find_domain_by_id failed.\n"));
- ret = EINVAL;
- goto done;
+ key.str = sid_str;
+ value.ul = 0;
+
+ ret = sysdb_search_object_by_sid(mem_ctx, user_dom->sysdb, user_dom,
+ sid_str, NULL, &msg);
+ if (ret == EOK && msg->count == 1) {
+ value.ul = ldb_msg_find_attr_as_uint64(msg->msgs[0], SYSDB_GIDNUM, 0);
+ talloc_free(msg);
}
- err = sss_idmap_sid_to_smb_sid(pac_ctx->idmap_ctx, sid_str, &grp_sid);
- if (err != IDMAP_SUCCESS) {
- DEBUG(SSSDBG_OP_FAILURE, ("sss_idmap_sid_to_smb_sid failed.\n"));
- ret = EFAULT;
+ ret = hash_enter(sid_table, &key, &value);
+ if (ret != HASH_SUCCESS) {
+ DEBUG(SSSDBG_OP_FAILURE, ("hash_enter failed [%d][%s].\n",
+ ret, hash_error_string(ret)));
+ ret = EIO;
goto done;
}
- grp_sid->num_auths++;
for (s = 0; s < info3->base.groups.count; s++) {
- grp_sid->sub_auths[grp_sid->num_auths - 1] =
- info3->base.groups.rids[s].rid;
- err = sss_idmap_smb_sid_to_unix(pac_ctx->idmap_ctx, grp_sid,
- &id);
- if (err != IDMAP_SUCCESS) {
- DEBUG(SSSDBG_FATAL_FAILURE, ("sss_idmap_smb_sid_to_unix failed for"
- "[%s] [%d].\n", sid_str,
- info3->base.groups.rids[s].rid));
- ret = ENOENT;
+ memset(rid_start, '\0', 12);
+ ret = snprintf(rid_start, 12, "-%lu",
+ (unsigned long) info3->base.groups.rids[s].rid);
+ if (ret < 0 || ret > 12) {
+ DEBUG(SSSDBG_OP_FAILURE, ("snprintf failed.\n"));
+ ret = EIO;
goto done;
}
- key.ul = id;
- value.ptr = grp_dom;
+ key.str = sid_str;
+ value.ul = 0;
+
+ ret = sysdb_search_object_by_sid(mem_ctx, user_dom->sysdb, user_dom,
+ sid_str, NULL, &msg);
+ if (ret == EOK && msg->count == 1) {
+ value.ul = ldb_msg_find_attr_as_uint64(msg->msgs[0],
+ SYSDB_GIDNUM, 0);
+ talloc_free(msg);
+ }
- ret = hash_enter(gid_table, &key, &value);
+ ret = hash_enter(sid_table, &key, &value);
if (ret != HASH_SUCCESS) {
DEBUG(SSSDBG_OP_FAILURE, ("hash_enter failed [%d][%s].\n",
ret, hash_error_string(ret)));
@@ -644,29 +228,60 @@ errno_t get_gids_from_pac(TALLOC_CTX *mem_ctx,
goto done;
}
- DEBUG(SSSDBG_TRACE_ALL, ("Found extra group with gid [%d].\n", id));
}
- ret = get_dom_grps_from_hash(gids, gid_table, grp_dom, &gids[1]);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, ("get_dom_grps_from_hash failed.\n"));
- goto done;
+ talloc_zfree(sid_str);
+
+ for(s = 0; s < info3->sidcount; s++) {
+ err = sss_idmap_smb_sid_to_sid(pac_ctx->idmap_ctx, info3->sids[s].sid,
+ &sid_str);
+ if (err != IDMAP_SUCCESS) {
+ DEBUG(SSSDBG_OP_FAILURE, ("sss_idmap_smb_sid_to_sid failed.\n"));
+ ret = EFAULT;
+ goto done;
+ }
+
+ key.str = sid_str;
+ value.ul = 0;
+
+ ret = responder_get_domain_by_id(pac_ctx->rctx, sid_str, &group_dom);
+ if (ret == EOK) {
+ ret = sysdb_search_object_by_sid(mem_ctx, group_dom->sysdb,
+ group_dom, sid_str, NULL, &msg);
+ if (ret == EOK && msg->count == 1 ) {
+ value.ul = ldb_msg_find_attr_as_uint64(msg->msgs[0],
+ SYSDB_GIDNUM, 0);
+ talloc_free(msg);
+ }
+ }
+
+ ret = hash_enter(sid_table, &key, &value);
+ if (ret != HASH_SUCCESS) {
+ DEBUG(SSSDBG_OP_FAILURE, ("hash_enter failed [%d][%s].\n",
+ ret, hash_error_string(ret)));
+ ret = EIO;
+ goto done;
+ }
+
+ talloc_zfree(sid_str);
}
- gid_count += gids[1].gid_count;
ret = EOK;
done:
talloc_free(sid_str);
- talloc_free(grp_sid);
+ talloc_free(user_dom_sid_str);
if (ret == EOK) {
- *_gid_count = gid_count;
- *_gids = talloc_steal(mem_ctx, gids);
+ *_sid_table = sid_table;
+ *_user_sid_str = user_sid_str;
+ *_primary_group_sid_str = primary_group_sid_str;
+ } else {
+ hash_destroy(sid_table);
+ talloc_free(user_sid_str);
+ talloc_free(primary_group_sid_str);
}
- talloc_free(tmp_ctx);
-
return ret;
}
@@ -724,8 +339,10 @@ errno_t get_data_from_pac(TALLOC_CTX *mem_ctx,
* Fill up the passwd struct with data from the PAC logon info
*/
errno_t get_pwd_from_pac(TALLOC_CTX *mem_ctx,
- struct pac_ctx *pac_ctx,
struct sss_domain_info *dom,
+ char *user_sid_str,
+ char *primary_group_sid_str,
+ hash_table_t *sid_table,
struct PAC_LOGON_INFO *logon_info,
struct passwd **_pwd,
struct sysdb_attrs **_attrs)
@@ -737,6 +354,8 @@ errno_t get_pwd_from_pac(TALLOC_CTX *mem_ctx,
char *lname;
char *uc_realm;
char *upn;
+ hash_key_t key;
+ hash_value_t value;
pwd = talloc_zero(mem_ctx, struct passwd);
if (pwd == NULL) {
@@ -765,22 +384,52 @@ errno_t get_pwd_from_pac(TALLOC_CTX *mem_ctx,
ret = ENOMEM;
goto done;
}
- pwd->pw_name = sss_tc_fqname(pwd, dom->names, dom, lname);
+
+ /* Subdomain use fully qualified names */
+ if (IS_SUBDOMAIN(dom)) {
+ pwd->pw_name = sss_tc_fqname(pwd, dom->names, dom, lname);
+ } else {
+ pwd->pw_name = talloc_strdup(pwd, lname);
+ }
if (!pwd->pw_name) {
DEBUG(SSSDBG_OP_FAILURE, ("talloc_sprintf failed.\n"));
ret = ENOMEM;
goto done;
}
- ret = domsid_rid_to_uid(pac_ctx, dom->sysdb, dom->name,
- base_info->domain_sid,
- base_info->rid, &pwd->pw_uid);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, ("domsid_rid_to_uid failed.\n"));
+ key.type = HASH_KEY_STRING;
+ key.str = user_sid_str;
+ ret = hash_lookup(sid_table, &key, &value);
+ if (ret != HASH_SUCCESS) {
+ DEBUG(SSSDBG_OP_FAILURE, ("hash_lookup failed.\n"));
+ ret = EIO;
goto done;
}
+ if (value.type != HASH_VALUE_ULONG) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Wrong value type.\n"));
+ ret = EIO;
+ goto done;
+ }
+ pwd->pw_uid = value.ul;
- pwd->pw_gid = 0; /* We use MPGs for sub-domains */
+ if (IS_SUBDOMAIN(dom) || dom->mpg) {
+ pwd->pw_gid = 0; /* We use MPGs for sub-domains */
+ } else {
+ key.type = HASH_KEY_STRING;
+ key.str = primary_group_sid_str;
+ ret = hash_lookup(sid_table, &key, &value);
+ if (ret != HASH_SUCCESS) {
+ DEBUG(SSSDBG_OP_FAILURE, ("hash_lookup failed.\n"));
+ ret = EIO;
+ goto done;
+ }
+ if (value.type != HASH_VALUE_ULONG) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Wrong value type.\n"));
+ ret = EIO;
+ goto done;
+ }
+ pwd->pw_gid = value.ul;
+ }
if (base_info->full_name.size != 0) {
pwd->pw_gecos = talloc_strdup(pwd, base_info->full_name.string);
@@ -794,7 +443,9 @@ errno_t get_pwd_from_pac(TALLOC_CTX *mem_ctx,
"gecos field will by empty.\n "));
}
- if (dom->subdomain_homedir) {
+ /* Check if there is a special homedir template for sub-domains. If not a
+ * fallback will be added by the NSS responder. */
+ if (IS_SUBDOMAIN(dom) && dom->subdomain_homedir) {
pwd->pw_dir = expand_homedir_template(pwd, dom->subdomain_homedir,
lname, pwd->pw_uid, NULL,
dom->name, dom->flat_name);
@@ -841,213 +492,22 @@ errno_t get_pwd_from_pac(TALLOC_CTX *mem_ctx,
goto done;
}
- *_pwd = pwd;
- *_attrs = attrs;
-
- ret = EOK;
-
-done:
+ ret = sysdb_attrs_add_string(attrs, SYSDB_SID_STR, user_sid_str);
if (ret != EOK) {
- talloc_free(pwd);
- }
-
- 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,
- struct pac_dom_grps *new_gid_list,
- size_t *_add_gid_num,
- struct pac_dom_grps **_add_gid_list,
- size_t *_del_grp_num,
- struct grp_info ***_del_grp_list)
-{
- int ret;
- size_t c;
- size_t g;
- hash_table_t *table;
- hash_key_t key;
- hash_value_t value;
- size_t add_gid_num = 0;
- struct pac_dom_grps *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;
- size_t new_dom_num = 0;
-
- 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 (new_gid_num != 0) {
- for (new_dom_num = 0; new_gid_list[new_dom_num].grp_dom != NULL;
- new_dom_num++);
- }
-
- if (cur_grp_num == 0 && new_gid_num != 0) {
- add_gid_num = new_gid_num;
- add_gid_list = talloc_zero_array(tmp_ctx, struct pac_dom_grps,
- new_dom_num + 1);
- if (add_gid_list == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("talloc_array failed.\n"));
- ret = ENOMEM;
- goto done;
- }
-
- for (c = 0; c < new_dom_num; c++) {
- add_gid_list[c].grp_dom = new_gid_list[c].grp_dom;
- add_gid_list[c].gid_count = new_gid_list[c].gid_count;
- if (new_gid_list[c].gid_count != 0) {
- add_gid_list[c].gids = talloc_zero_array(add_gid_list, gid_t,
- new_gid_list[c].gid_count);
- if (add_gid_list[c].gids == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("talloc_zero_array failed.\n"));
- ret = ENOMEM;
- goto done;
- }
-
- for (g = 0; g < new_gid_list[c].gid_count; g++) {
- add_gid_list[c].gids[g] = new_gid_list[c].gids[g];
- }
- }
- }
-
- 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;
- }
- }
-
- add_gid_list = talloc_zero_array(tmp_ctx, struct pac_dom_grps,
- new_dom_num + 1);
- if (add_gid_list == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("talloc_array failed.\n"));
- ret = ENOMEM;
- goto done;
- }
-
- for (c = 0; c < new_dom_num; c++) {
- add_gid_list[c].grp_dom = new_gid_list[c].grp_dom;
- add_gid_list[c].gid_count = 0;
-
- for (g = 0; g < new_gid_list[c].gid_count; g++) {
- key.ul = (unsigned long) new_gid_list[c].gids[g];
-
- ret = hash_delete(table, &key);
- if (ret == HASH_ERROR_KEY_NOT_FOUND) {
- /* gid not found, must be added */
- add_gid_list[c].gid_count++;
- add_gid_list[c].gids = talloc_realloc(add_gid_list,
- add_gid_list,
- gid_t,
- add_gid_list[c].gid_count);
- if (add_gid_list[c].gids == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("talloc_realloc failed.\n"));
- ret = ENOMEM;
- goto done;
- }
-
- add_gid_list[c].gids[add_gid_list[c].gid_count - 1] =
- new_gid_list[c].gids[g];
- } else if (ret != HASH_SUCCESS) {
- DEBUG(SSSDBG_OP_FAILURE, ("hash_delete failed.\n"));
- ret = EIO;
- goto done;
- }
- }
-
- add_gid_num += add_gid_list[c].gid_count;
- }
-
- /* 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;
+ DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_add_string failed.\n"));
goto done;
}
- for (c = 0; c < del_grp_num; c++) {
- del_grp_list[c] = (struct grp_info *) values[c].ptr;
- }
+ *_pwd = pwd;
+ *_attrs = attrs;
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);
+ if (ret != EOK) {
+ talloc_free(pwd);
}
- talloc_free(tmp_ctx);
-
return ret;
}
@@ -1071,14 +531,11 @@ bool new_and_cached_user_differs(struct passwd *pwd, struct ldb_message *msg)
return true;
}
- if (!compare_string_with_attr(pwd->pw_name, msg, SYSDB_NAME)) {
+ if (!compare_string_with_attr(pwd->pw_name, msg, SYSDB_NAME) &&
+ !compare_string_with_attr(pwd->pw_name, msg, SYSDB_NAME_ALIAS)) {
DEBUG(SSSDBG_TRACE_FUNC, ("Names differ."));
return true;
}
- if (!compare_string_with_attr(pwd->pw_gecos, msg, SYSDB_GECOS)) {
- DEBUG(SSSDBG_TRACE_FUNC, ("Gecos fields differ."));
- return true;
- }
if (!compare_string_with_attr(pwd->pw_dir, msg, SYSDB_HOMEDIR)) {
DEBUG(SSSDBG_TRACE_FUNC, ("Home directories differ."));
diff --git a/src/sss_client/sssd_pac.c b/src/sss_client/sssd_pac.c
index 0cce43dd7..469758a65 100644
--- a/src/sss_client/sssd_pac.c
+++ b/src/sss_client/sssd_pac.c
@@ -2,7 +2,7 @@
Authors:
Sumit Bose <sbose@redhat.com>
- Copyright (C) 2011 Red Hat
+ Copyright (C) 2011, 2012, 2013 Red Hat
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
@@ -45,7 +45,7 @@ sssdpac_flags(krb5_context kcontext,
krb5_authdatatype ad_type,
krb5_flags *flags)
{
- *flags = AD_USAGE_KDC_ISSUED | AD_INFORMATIONAL | AD_USAGE_TGS_REQ;
+ *flags = AD_USAGE_KDC_ISSUED | AD_USAGE_TGS_REQ;
}
static void
@@ -81,9 +81,6 @@ sssdpac_import_authdata(krb5_context kcontext,
krb5_boolean kdc_issued,
krb5_const_principal kdc_issuer)
{
- struct sss_cli_req_data sss_data;
- int ret;
- int errnop;
char *data = NULL;
struct sssd_context *sssdctx = (struct sssd_context *)request_context;
@@ -91,15 +88,6 @@ sssdpac_import_authdata(krb5_context kcontext,
return EINVAL;
}
- sss_data.len = authdata[0]->length;
- sss_data.data = authdata[0]->contents;
-
- ret = sss_pac_make_request(SSS_PAC_ADD_PAC_USER, &sss_data,
- NULL, NULL, &errnop);
- if (ret != 0) {
- /* Ignore the error */
- }
-
if (authdata[0]->length > 0) {
data = malloc(sizeof(char) * authdata[0]->length);
if (data == NULL) {
@@ -134,6 +122,50 @@ sssdpac_request_fini(krb5_context kcontext,
}
}
+static krb5_error_code sssdpac_verify(krb5_context kcontext,
+ krb5_authdata_context context,
+ void *plugin_context,
+ void *request_context,
+ const krb5_auth_context *auth_context,
+ const krb5_keyblock *key,
+ const krb5_ap_req *req)
+{
+ krb5_error_code kerr;
+ int ret;
+ krb5_pac pac;
+ struct sssd_context *sssdctx = (struct sssd_context *)request_context;
+ struct sss_cli_req_data sss_data;
+ int errnop;
+
+ if (sssdctx == NULL || sssdctx->data.data == NULL) {
+ return EINVAL;
+ }
+
+ kerr = krb5_pac_parse(kcontext, sssdctx->data.data,
+ sssdctx->data.length, &pac);
+ if (kerr != 0) {
+ return EINVAL;
+ }
+
+ kerr = krb5_pac_verify(kcontext, pac,
+ req->ticket->enc_part2->times.authtime,
+ req->ticket->enc_part2->client, key, NULL);
+ if (kerr != 0) {
+ return EINVAL;
+ }
+
+ sss_data.len = sssdctx->data.length;
+ sss_data.data = sssdctx->data.data;
+
+ ret = sss_pac_make_request(SSS_PAC_ADD_PAC_USER, &sss_data,
+ NULL, NULL, &errnop);
+ if (ret != 0) {
+ /* Ignore the error */
+ }
+
+ return 0;
+}
+
static krb5_error_code
sssdpac_size(krb5_context kcontext,
krb5_authdata_context context,
@@ -272,7 +304,7 @@ krb5plugin_authdata_client_ftable_v0 authdata_client_0 = {
sssdpac_import_authdata,
NULL,
NULL,
- NULL,
+ sssdpac_verify,
sssdpac_size,
sssdpac_externalize,
sssdpac_internalize,
diff --git a/src/tests/pac_responder-tests.c b/src/tests/pac_responder-tests.c
deleted file mode 100644
index ed8c9170d..000000000
--- a/src/tests/pac_responder-tests.c
+++ /dev/null
@@ -1,524 +0,0 @@
-/*
- SSSD - Test for PAC reponder functions
-
- Authors:
- Sumit Bose <sbose@redhat.com>
-
- Copyright (C) 2012 Red Hat
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <check.h>
-
-#include <stdbool.h>
-#include <math.h>
-#include <util/data_blob.h>
-#include <gen_ndr/security.h>
-
-#include "tests/common_check.h"
-#include "responder/pac/pacsrv.h"
-#include "lib/idmap/sss_idmap.h"
-
-struct dom_sid test_dom_sid = {1, 4, {0, 0, 0, 0, 0, 5},
- {21, 2127521184, 1604012920, 1887927527, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
-const char *test_dom_sid_str = "S-1-5-21-2127521184-1604012920-1887927527";
-
-struct dom_sid test_remote_dom_sid = {1, 4, {0, 0, 0, 0, 0, 5},
- {21, 123, 456, 789, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
-const char *test_remote_dom_sid_str = "S-1-5-21-123-456-789";
-
-struct dom_sid test_smb_sid = {1, 5, {0, 0, 0, 0, 0, 5},
- {21, 2127521184, 1604012920, 1887927527, 1123,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
-const uint32_t test_id = 1200123;
-
-struct dom_sid test_smb_sid_2nd = {1, 5, {0, 0, 0, 0, 0, 5},
- {21, 2127521184, 1604012920, 1887927527, 201456,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
-const uint32_t test_id_2nd = 1200456;
-
-struct local_mapping_ranges test_map = {{1200000, 1399999},
- {1000, 200999},
- {201000, 400999}};
-
-static void *idmap_talloc(size_t size, void *pvt)
-{
- return talloc_size(pvt, size);
-}
-
-static void idmap_talloc_free(void *ptr, void *pvt)
-{
- talloc_free(ptr);
-}
-
-struct pac_ctx *pac_ctx;
-
-#define IDMAP_RANGE_MIN 1234
-#define IDMAP_RANGE_MAX 9876543
-
-void pac_setup(void) {
- enum idmap_error_code err;
- struct sss_idmap_range remote_range = {IDMAP_RANGE_MIN, IDMAP_RANGE_MAX};
- struct sss_domain_info *sd;
-
- pac_ctx = talloc_zero(global_talloc_context, struct pac_ctx);
- fail_unless(pac_ctx != NULL, "talloc_zero failed.\n");
-
- pac_ctx->rctx = talloc_zero(pac_ctx, struct resp_ctx);
- fail_unless(pac_ctx->rctx != NULL, "talloc_zero failed.");
-
- pac_ctx->rctx->domains = talloc_zero(pac_ctx->rctx, struct sss_domain_info);
- fail_unless(pac_ctx->rctx->domains != NULL, "talloc_zero failed.");
-
- pac_ctx->rctx->domains->name = talloc_strdup(pac_ctx->rctx->domains,
- "TEST.DOM");
- fail_unless(pac_ctx->rctx->domains->name != NULL, "talloc_strdup failed.");
-
- pac_ctx->rctx->domains->flat_name = talloc_strdup(pac_ctx->rctx->domains,
- "TESTDOM");
- fail_unless(pac_ctx->rctx->domains->flat_name != NULL,
- "talloc_strdup failed.");
-
- pac_ctx->rctx->domains->domain_id = talloc_strdup(pac_ctx->rctx->domains,
- test_dom_sid_str);
- fail_unless(pac_ctx->rctx->domains->domain_id != NULL,
- "talloc_strdup failed.");
-
- sd = talloc_zero(pac_ctx->rctx->domains, struct sss_domain_info);
- fail_unless(sd != NULL, "talloc_zero failed.");
-
- sd->name = talloc_strdup(sd, "remote.dom");
- fail_unless(sd->name != NULL, "talloc_strdup failed");
-
- sd->flat_name = talloc_strdup(sd, "REMOTEDOM");
- fail_unless(sd->flat_name != NULL, "talloc_strdup failed");
-
- sd->domain_id = talloc_strdup(sd, test_remote_dom_sid_str);
- fail_unless(sd->domain_id != NULL, "talloc_strdup failed");
-
- pac_ctx->rctx->domains->subdomains = sd;
-
- err = sss_idmap_init(idmap_talloc, pac_ctx, idmap_talloc_free,
- &pac_ctx->idmap_ctx);
-
- fail_unless(err == IDMAP_SUCCESS, "sss_idmap_init failed.");
- fail_unless(pac_ctx->idmap_ctx != NULL, "sss_idmap_init returned NULL.");
-
- err = sss_idmap_add_domain(pac_ctx->idmap_ctx, "remote.dom",
- test_remote_dom_sid_str, &remote_range);
-
- pac_ctx->my_dom_sid = &test_dom_sid;
-
- pac_ctx->range_map = &test_map;
-}
-
-void pac_teardown(void)
-{
- talloc_free(pac_ctx);
-}
-
-
-START_TEST(pac_test_local_sid_to_id)
-{
- int ret;
- uint32_t id;
-
- ret = local_sid_to_id(&test_map, &test_smb_sid, &id);
- fail_unless(ret == EOK,
- "Failed to convert local sid to id.");
- fail_unless(id == test_id, "Wrong id returne, expected [%d], got [%d].",
- test_id, id);
-}
-END_TEST
-
-START_TEST(pac_test_seondary_local_sid_to_id)
-{
- int ret;
- uint32_t id;
-
- ret = local_sid_to_id(&test_map, &test_smb_sid_2nd, &id);
- fail_unless(ret == EOK,
- "Failed to convert local sid to id.");
- fail_unless(id == test_id_2nd, "Wrong id returne, expected [%d], got [%d].",
- test_id_2nd, 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;
- struct pac_dom_grps *add_gids = NULL;
- size_t del_gid_count = 0;
- struct grp_info **del_gids = NULL;
- struct sss_domain_info grp_dom;
-
- memset(&grp_dom, 0, sizeof(grp_dom));
-
- gid_t gid_list_2[] = {2};
- gid_t gid_list_3[] = {3};
- gid_t gid_list_23[] = {2, 3};
- struct pac_dom_grps empty_dom = {NULL, 0, NULL};
-
- struct pac_dom_grps pac_grp_2 = {&grp_dom, 1, gid_list_2};
- struct pac_dom_grps pac_grp_3 = {&grp_dom, 1, gid_list_3};
- struct pac_dom_grps pac_grp_23 = {&grp_dom, 2, gid_list_23};
-
- struct pac_dom_grps dom_grp_list_2[] = {pac_grp_2, empty_dom};
- struct pac_dom_grps dom_grp_list_3[] = {pac_grp_3, empty_dom};
- struct pac_dom_grps dom_grp_list_23[] = {pac_grp_23, empty_dom};
-
- 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;
- struct pac_dom_grps *gids;
- int exp_ret;
- size_t exp_add_gid_count;
- struct pac_dom_grps *exp_add_gids;
- size_t exp_del_gid_count;
- struct grp_info *exp_del_gids;
- } a_and_r_data[] = {
- {1, grp_list_1, 1, dom_grp_list_2, EOK, 1, dom_grp_list_2, 1, grp_list_1},
- {1, grp_list_1, 0, NULL, EOK, 0, NULL, 1, grp_list_1},
- {0, NULL, 1, dom_grp_list_2, EOK, 1, dom_grp_list_2, 0, NULL},
- {2, grp_list_12, 1, dom_grp_list_2, EOK, 0, NULL, 1, grp_list_1},
- {2, grp_list_12, 2, dom_grp_list_23, EOK, 1, dom_grp_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].gids[0] == a_and_r_data[c].exp_add_gids[0].gids[0],
- "Unexpected gid to add for test data #%d, " \
- "expected [%d], got [%d]",
- c, a_and_r_data[c].exp_add_gids[0].gids[0], add_gids[0].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
-
-#define NUM_DOMAINS 10
-START_TEST(pac_test_find_domain_by_id)
-{
- struct sss_domain_info *domains;
- struct sss_domain_info *dom;
- size_t c;
- char *id;
-
- dom = find_domain_by_id(NULL, NULL);
- fail_unless(dom == NULL, "Domain returned without any input.");
-
- dom = find_domain_by_id(NULL, "id");
- fail_unless(dom == NULL, "Domain returned without domain list.");
-
- domains = NULL;
- for (c = 0; c < NUM_DOMAINS; c++) {
- dom = talloc_zero(domains, struct sss_domain_info);
- fail_unless(dom != NULL, "talloc_zero failed.");
-
- dom->domain_id = talloc_asprintf(dom, "ID-of-domains-%zu", c);
- fail_unless(dom->domain_id != NULL, "talloc_aprintf failed.");
-
- DLIST_ADD(domains, dom);
- }
-
- dom = find_domain_by_id(domains, NULL);
- fail_unless(dom == NULL, "Domain returned without search domain.");
-
- dom = find_domain_by_id(domains, "DOES-NOT_EXISTS");
- fail_unless(dom == NULL, "Domain returned with non existing id.");
-
- for (c = 0; c < NUM_DOMAINS; c++) {
- id = talloc_asprintf(global_talloc_context, "ID-of-domains-%zu", c);
- fail_unless(id != NULL, "talloc_asprintf failed.\n");
-
- dom = find_domain_by_id(domains, id);
- fail_unless(dom != NULL, "Domain %zu not found by id.", c);
- fail_unless((strcmp(dom->domain_id, id) == 0),
- "Wrong domain returned for id [%s].", id);
-
- talloc_free(id);
- }
-
- talloc_free(domains);
-}
-END_TEST
-
-START_TEST(pac_test_get_gids_from_pac)
-{
- int ret;
- size_t c;
- size_t d;
- size_t g;
- size_t t;
- size_t gid_count;
- struct pac_dom_grps *gids;
- struct PAC_LOGON_INFO *logon_info;
- bool found;
- gid_t exp_gid;
- struct timeval start_time;
- struct timeval end_time;
- struct timeval diff_time;
-
- ret = get_gids_from_pac(NULL, NULL, NULL, NULL, NULL, NULL, NULL);
- fail_unless(ret == EINVAL, "Unexpected return value for NULL parameters");
-
- logon_info = talloc_zero(global_talloc_context, struct PAC_LOGON_INFO);
- fail_unless(logon_info != NULL, "talloc_zero failed.\n");
-
- ret = get_gids_from_pac(global_talloc_context, pac_ctx, pac_ctx->range_map,
- pac_ctx->my_dom_sid, logon_info, &gid_count, &gids);
- fail_unless(ret == EOK, "Failed with empty PAC");
- fail_unless(gid_count == 0, "O groups expected, got [%d]", gid_count);
- fail_unless(gids == NULL, "Expected NULL gid array.");
-
- logon_info->info3.base.domain_sid = &test_smb_sid_2nd; /* unknown SID */
- logon_info->info3.base.groups.count = 10;
- logon_info->info3.base.groups.rids = talloc_array(logon_info,
- struct samr_RidWithAttribute,
- logon_info->info3.base.groups.count);
- fail_unless(logon_info->info3.base.groups.rids != NULL, "talloc_array failed.");
-
- for (c = 0; c < logon_info->info3.base.groups.count; c++) {
- logon_info->info3.base.groups.rids[c].rid = 500 + c;
- }
-
- ret = get_gids_from_pac(global_talloc_context, pac_ctx, pac_ctx->range_map,
- pac_ctx->my_dom_sid, logon_info, &gid_count, &gids);
- fail_unless(ret == EINVAL, "Unexpected return code [%d] with unknown SID.",
- ret);
-
- /* change SID to a known one */
- logon_info->info3.base.domain_sid = &test_remote_dom_sid;
-
- ret = get_gids_from_pac(global_talloc_context, pac_ctx, pac_ctx->range_map,
- pac_ctx->my_dom_sid, logon_info, &gid_count, &gids);
- fail_unless(ret == EOK, "Failed with 10 RIDs in PAC");
- fail_unless(gid_count == logon_info->info3.base.groups.count,
- "[%d] groups expected, got [%d]",
- logon_info->info3.base.groups.count, gid_count);
- fail_unless(gids != NULL, "Expected gid array.");
-
- for (c = 0; c < logon_info->info3.base.groups.count; c++) {
- found = false;
- exp_gid = IDMAP_RANGE_MIN + 500 + c;
- for (g = 0; g < gid_count; g++) {
- if (gids[1].gids[g] == exp_gid) {
- found = true;
- break;
- }
- }
- fail_unless(found, "[%d] not found in group list", exp_gid);
- }
-
- talloc_free(gids);
- gids = NULL;
-
- /* duplicated RIDs */
- for (c = 0; c < logon_info->info3.base.groups.count; c++) {
- logon_info->info3.base.groups.rids[c].rid = 500;
- }
-
- ret = get_gids_from_pac(global_talloc_context, pac_ctx, pac_ctx->range_map,
- pac_ctx->my_dom_sid, logon_info, &gid_count, &gids);
- fail_unless(ret == EOK, "Failed with 10 duplicated RIDs in PAC");
- fail_unless(gid_count == 1, "[%d] groups expected, got [%d]", 1, gid_count);
- fail_unless(gids != NULL, "Expected gid array.");
- fail_unless(gids[1].gids[0] == IDMAP_RANGE_MIN + 500,
- "Wrong gid returned, got [%d], expected [%d].", gids[1].gids[0],
- IDMAP_RANGE_MIN + 500);
- talloc_free(gids);
- gids = NULL;
-
- logon_info->info3.sidcount = 2;
- logon_info->info3.sids = talloc_zero_array(logon_info, struct netr_SidAttr,
- logon_info->info3.sidcount);
- fail_unless(logon_info->info3.sids != NULL, "talloc_zero_array failed.");
-
- logon_info->info3.sids[0].sid = &test_smb_sid;
- logon_info->info3.sids[1].sid = &test_smb_sid_2nd;
-
- ret = get_gids_from_pac(global_talloc_context, pac_ctx, pac_ctx->range_map,
- pac_ctx->my_dom_sid, logon_info, &gid_count, &gids);
- fail_unless(ret == EOK, "Failed with 10 duplicated RIDs and local SIDS in PAC");
- fail_unless(gid_count == 3, "[%d] groups expected, got [%d]", 3, gid_count);
- fail_unless(gids != NULL, "Expected gid array.");
-
- gid_t exp_gids[] = {IDMAP_RANGE_MIN + 500, test_id, test_id_2nd, 0};
-
- for (c = 0; exp_gids[c] != 0; c++) {
- found = false;
- for (d = 0; d < 2; d++) {
- for (g = 0; g < gids[d].gid_count; g++) {
- if (gids[d].gids[g] == exp_gids[c]) {
- found = true;
- break;
- }
- }
- if (found) {
- break;
- }
- }
- fail_unless(found, "[%d] not found in group list", exp_gids[c]);
- }
-
- talloc_free(gids);
- gids = NULL;
-
- talloc_free(logon_info->info3.base.groups.rids);
-
- for (t = 0; t < 7; t++) {
- logon_info->info3.base.groups.count = powl(10, t);
- logon_info->info3.base.groups.rids = talloc_array(logon_info,
- struct samr_RidWithAttribute,
- logon_info->info3.base.groups.count);
- fail_unless(logon_info->info3.base.groups.rids != NULL, "talloc_array failed.");
-
- for (c = 0; c < logon_info->info3.base.groups.count; c++) {
- logon_info->info3.base.groups.rids[c].rid = 500 + c;
- }
-
- ret = gettimeofday(&start_time, NULL);
- fail_unless(ret == 0, "gettimeofday failed.");
-
- ret = get_gids_from_pac(global_talloc_context, pac_ctx, pac_ctx->range_map,
- pac_ctx->my_dom_sid, logon_info, &gid_count, &gids);
- fail_unless(ret == EOK, "Unexpected return code [%d].", ret);
-
- ret = gettimeofday(&end_time, NULL);
- fail_unless(ret == 0, "gettimeofday failed.");
-
- timersub(&end_time, &start_time, &diff_time);
- fprintf(stderr, "Testcase [%zu], number of groups [%u], " \
- "duration [%ds %dus]\n", t,
- logon_info->info3.base.groups.count,
- (int) diff_time.tv_sec,
- (int) diff_time.tv_usec);
-
- talloc_free(gids);
- gids = NULL;
-
- talloc_free(logon_info->info3.base.groups.rids);
- }
-
- talloc_free(logon_info);
-}
-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_pac,
- ck_leak_check_setup,
- ck_leak_check_teardown);
-
- tcase_add_checked_fixture(tc_pac,
- pac_setup,
- pac_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);
- tcase_add_test(tc_pac, pac_test_find_domain_by_id);
- tcase_add_test(tc_pac, pac_test_get_gids_from_pac);
-
- suite_add_tcase(s, tc_pac);
-
- return s;
-}
-
-int main(int argc, const char *argv[])
-{
- int number_failed;
-
- tests_set_cwd();
-
- Suite *s = idmap_test_suite();
- SRunner *sr = srunner_create(s);
-
- /* If CK_VERBOSITY is set, use that, otherwise it defaults to CK_NORMAL */
- srunner_run_all(sr, CK_ENV);
- number_failed = srunner_ntests_failed (sr);
- srunner_free (sr);
-
- return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
-}