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