diff options
Diffstat (limited to 'src/responder/pac/pacsrv_utils.c')
-rw-r--r-- | src/responder/pac/pacsrv_utils.c | 937 |
1 files changed, 197 insertions, 740 deletions
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.")); |