summaryrefslogtreecommitdiffstats
path: root/src/responder/pac/pacsrv_utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/responder/pac/pacsrv_utils.c')
-rw-r--r--src/responder/pac/pacsrv_utils.c937
1 files changed, 197 insertions, 740 deletions
diff --git a/src/responder/pac/pacsrv_utils.c b/src/responder/pac/pacsrv_utils.c
index bcea640b8..e7e15ac50 100644
--- a/src/responder/pac/pacsrv_utils.c
+++ b/src/responder/pac/pacsrv_utils.c
@@ -25,355 +25,6 @@
#include "util/util.h"
#include "responder/pac/pacsrv.h"
-static errno_t get_rid(struct dom_sid *sid, uint32_t *rid)
-{
- if (sid == NULL || sid->num_auths < 1 || rid == NULL) {
- return EINVAL;
- }
-
- *rid = sid->sub_auths[sid->num_auths - 1];
-
- return EOK;
-}
-
-/**
- * Find the Posix ID to a SID from the local IPA domain
- */
-errno_t local_sid_to_id(struct local_mapping_ranges *map, struct dom_sid *sid,
- uint32_t *id)
-{
- int ret;
- uint32_t rid;
-
- if (map == NULL || sid == NULL || id == NULL) {
- return EINVAL;
- }
-
- ret = get_rid(sid, &rid);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, ("get_rid failed.\n"));
- return ret;
- }
-
- if (rid >= map->primary_rids.min && rid <= map->primary_rids.max) {
- *id = map->local_ids.min + (rid - map->primary_rids.min);
- } else if (rid >= map->secondary_rids.min &&
- rid <= map->secondary_rids.max) {
- *id = map->local_ids.min + (rid - map->secondary_rids.min);
- } else {
- return ENOENT;
- }
-
- if (*id < map->local_ids.min || *id > map->local_ids.max) {
- return ERANGE;
- }
-
- return EOK;
-}
-
-struct sss_domain_info *find_domain_by_id(struct sss_domain_info *domains,
- const char *id_str)
-{
- struct sss_domain_info *dom;
- struct sss_domain_info *ret_dom = NULL;
-
- if (id_str == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("Missing domain id.\n"));
- return NULL;
- }
-
- for (dom = domains; dom; dom = get_next_domain(dom, true)) {
- if (dom->domain_id == NULL) {
- continue;
- }
-
- if (strcasecmp(dom->domain_id, id_str) == 0) {
- ret_dom = dom;
- break;
- }
- }
-
- if (!ret_dom) {
- DEBUG(SSSDBG_OP_FAILURE, ("No domain with domain ID [%s] found.\n",
- id_str));
- }
-
- return ret_dom;
-}
-
-/**
- * Add a new remote domain and the corresponding ID range to the context of
- * the libsss_idmap. Without this it is not possible to find the Posix UID for
- * a user fo the remote domain.
- */
-errno_t add_idmap_domain(struct sss_idmap_ctx *idmap_ctx,
- struct sysdb_ctx *sysdb,
- const char *domain_name,
- const char *dom_sid_str)
-{
- struct sss_idmap_range range = {0, 0};
- enum idmap_error_code err;
- TALLOC_CTX *tmp_ctx = NULL;
- size_t range_count;
- struct range_info **range_list;
- size_t c;
- int ret;
-
- if (domain_name == NULL || dom_sid_str == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("Missing domain name or SID.\n"));
- return EINVAL;
- }
-
- tmp_ctx = talloc_new(NULL);
- if (tmp_ctx == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("talloc_new failed.\n"));
- return ENOMEM;
- }
-
- ret = sysdb_get_ranges(tmp_ctx, sysdb, &range_count, &range_list);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, ("sysdb_get_ranges failed.\n"));
- goto done;
- }
-
- for (c = 0; c < range_count; c++) {
- if (range_list[c]->trusted_dom_sid != NULL &&
- strcmp(range_list[c]->trusted_dom_sid, dom_sid_str) == 0) {
- range.min = range_list[c]->base_id;
- range.max = range_list[c]->base_id +
- range_list[c]->id_range_size - 1;
- /* TODO: add support for multiple ranges. */
- break;
- }
- }
-
- if (range.min == 0 && range.max == 0) {
- DEBUG(SSSDBG_OP_FAILURE, ("Failed to find mapping range for domain "
- "[%s][%s].\n", domain_name, dom_sid_str));
- ret = ENOENT;
- goto done;
- }
-
- err = sss_idmap_add_domain(idmap_ctx, domain_name, dom_sid_str, &range);
- if (err != IDMAP_SUCCESS) {
- DEBUG(SSSDBG_OP_FAILURE, ("sss_idmap_add_domain failed.\n"));
- return EFAULT;
- }
-
- ret = EOK;
-
-done:
- talloc_free(tmp_ctx);
- return ret;
-}
-
-/**
- * Find the corresponding UID for a user from a remote domain based on the
- * domain SID of the remote domain and the RID of the user.
- */
-errno_t domsid_rid_to_uid(struct pac_ctx *pac_ctx,
- struct sysdb_ctx *sysdb,
- const char *domain_name,
- struct dom_sid2 *domsid, uint32_t rid,
- uid_t *uid)
-{
- enum idmap_error_code err;
- char *sid_str = NULL;
- char *dom_sid_str = NULL;
- uint32_t id;
- int ret;
-
- err = sss_idmap_smb_sid_to_sid(pac_ctx->idmap_ctx, domsid,
- &dom_sid_str);
- if (err != IDMAP_SUCCESS) {
- DEBUG(SSSDBG_OP_FAILURE, ("sss_idmap_smb_sid_to_sid failed.\n"));
- ret = EFAULT;
- goto done;
- }
-
- sid_str = talloc_asprintf(NULL, "%s-%lu", dom_sid_str, (unsigned long) rid);
- if (sid_str == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("dom_sid_and_rid_string failed.\n"));
- return ENOMEM;
- }
-
- err = sss_idmap_sid_to_unix(pac_ctx->idmap_ctx, sid_str, &id);
- if (err == IDMAP_NO_DOMAIN) {
- ret = add_idmap_domain(pac_ctx->idmap_ctx, sysdb, domain_name,
- dom_sid_str);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, ("add_idmap_domain failed.\n"));
- goto done;
- }
-
- err = sss_idmap_sid_to_unix(pac_ctx->idmap_ctx, sid_str, &id);
- if (err != IDMAP_SUCCESS) {
- DEBUG(SSSDBG_FATAL_FAILURE, ("sss_idmap_sid_to_unix failed "
- "even in the second attempt.\n"));
- ret = ENOENT;
- goto done;
- }
- } else if (err != IDMAP_SUCCESS && err != IDMAP_NO_DOMAIN) {
- DEBUG(SSSDBG_OP_FAILURE, ("sss_idmap_sid_to_unix failed.\n"));
- ret = EFAULT;
- goto done;
- }
-
- *uid = (uid_t) id;
-
- ret = EOK;
-
-done:
- talloc_free(dom_sid_str);
- talloc_free(sid_str);
- return ret;
-}
-
-/**
- * Return information about the local domain from the main PAC responder
- * context or try to read it from cache and store it in the context.
- */
-errno_t get_parent_domain_data(struct pac_ctx *pac_ctx,
- struct sss_domain_info *dom,
- struct dom_sid **_sid,
- struct local_mapping_ranges **_range_map)
-{
- struct sysdb_ctx *sysdb;
- int ret;
- struct ldb_dn *basedn;
- const char *attrs[] = {SYSDB_SUBDOMAIN_ID,
- NULL};
- size_t msgs_count;
- const char *sid_str;
- struct ldb_message **msgs;
- TALLOC_CTX *tmp_ctx = NULL;
- struct dom_sid *sid = NULL;
- enum idmap_error_code err;
- size_t range_count;
- struct range_info **range_list;
- struct local_mapping_ranges *r_map = NULL;
- size_t c;
-
- if (pac_ctx->my_dom_sid == NULL || pac_ctx->range_map == NULL) {
- sysdb = dom->sysdb;
-
- if (sysdb == NULL) {
- DEBUG(SSSDBG_FATAL_FAILURE, ("Missing sysdb context.\n"));
- ret = EINVAL;
- goto done;
- }
-
- tmp_ctx = talloc_new(NULL);
- if (tmp_ctx == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("talloc_new failed.\n"));
- ret = ENOMEM;
- goto done;
- }
-
- /* The data of the parent domain should be read here. */
- basedn = sysdb_domain_dn(sysdb, tmp_ctx,
- IS_SUBDOMAIN(dom) ? dom->parent : dom);
- if (basedn == NULL) {
- ret = ENOMEM;
- goto done;
- }
-
- if (pac_ctx->my_dom_sid == NULL) {
- ret = sysdb_search_entry(tmp_ctx, sysdb, basedn, LDB_SCOPE_BASE, NULL,
- attrs, &msgs_count, &msgs);
- if (ret != LDB_SUCCESS) {
- ret = EIO;
- goto done;
- }
-
- if (msgs_count != 1) {
- DEBUG(SSSDBG_OP_FAILURE, ("Base search returned [%d] results, "
- "expected 1.\n", msgs_count));
- ret = EINVAL;
- goto done;
- }
-
- sid_str = ldb_msg_find_attr_as_string(msgs[0], SYSDB_SUBDOMAIN_ID, NULL);
- if (sid_str == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("SID of my domain is not available.\n"));
- ret = EINVAL;
- goto done;
- }
-
- err = sss_idmap_sid_to_smb_sid(pac_ctx->idmap_ctx, sid_str, &sid);
- if (err != IDMAP_SUCCESS) {
- DEBUG(SSSDBG_OP_FAILURE, ("sss_idmap_sid_to_smb_sid failed.\n"));
- ret = EFAULT;
- goto done;
- }
-
- pac_ctx->my_dom_sid = talloc_memdup(pac_ctx, sid,
- sizeof(struct dom_sid));
- if (pac_ctx->my_dom_sid == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("talloc_memdup failed.\n"));
- ret = ENOMEM;
- goto done;
- }
- }
-
- if (pac_ctx->range_map == NULL) {
- ret = sysdb_get_ranges(tmp_ctx, sysdb, &range_count, &range_list);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, ("sysdb_get_ranges failed.\n"));
- goto done;
- }
-
- for (c = 0; c < range_count; c++) {
- if (range_list[c]->trusted_dom_sid == NULL &&
- range_list[c]->secondary_base_rid != 0) {
- r_map = talloc_zero(pac_ctx,
- struct local_mapping_ranges);
- if (r_map == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("talloc_zero failed.\n"));
- ret = ENOMEM;
- goto done;
- }
-
- r_map->local_ids.min = range_list[c]->base_id;
- r_map->local_ids.max = range_list[c]->base_id +
- range_list[c]->id_range_size - 1;
-
- r_map->primary_rids.min = range_list[c]->base_rid;
- r_map->primary_rids.max = range_list[c]->base_rid +
- range_list[c]->id_range_size - 1;
-
- r_map->secondary_rids.min = range_list[c]->secondary_base_rid;
- r_map->secondary_rids.max = range_list[c]->secondary_base_rid +
- range_list[c]->id_range_size - 1;
-
- /* TODO: add support for multiple ranges. */
- break;
- }
- }
-
- if (r_map == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("Failed to find local id map.\n"));
- ret = ENOENT;
- goto done;
- }
-
- pac_ctx->range_map = r_map;
- }
-
- }
-
- *_sid = pac_ctx->my_dom_sid;
- *_range_map = pac_ctx->range_map;
-
- ret = EOK;
-
-done:
- talloc_free(sid);
- talloc_free(tmp_ctx);
-
- return ret;
-}
-
/**
* Check if a given SID belongs to a domain identified by the domain SID.
*/
@@ -409,234 +60,167 @@ bool dom_sid_in_domain(const struct dom_sid *domain_sid,
return true;
}
-
-static errno_t get_dom_grps_from_hash(TALLOC_CTX *mem_ctx,
- hash_table_t *gid_table,
- struct sss_domain_info *grp_dom,
- struct pac_dom_grps *dom_grps)
-{
- int ret;
- size_t gid_count;
- size_t g;
- struct hash_iter_context_t *iter;
- hash_entry_t *entry;
- gid_t *gids = NULL;
-
- if (grp_dom == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("Missing domain for groups.\n"));
- return EINVAL;
- }
-
- gid_count = hash_count(gid_table);
- if (gid_count == 0) {
- DEBUG(SSSDBG_TRACE_FUNC, ("No groups found.\n"));
- ret = EOK;
- goto done;
- }
-
- gids = talloc_zero_array(mem_ctx, gid_t, gid_count);
- if (gids == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("talloc_array failed.\n"));
- ret = ENOMEM;
- goto done;
- }
-
-
- iter = new_hash_iter_context(gid_table);
- if (iter == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("new_hash_iter_context failed.\n"));
- ret = EIO;
- goto done;
- }
-
- g = 0;
- while ((entry = iter->next(iter)) != NULL) {
- gids[g] = entry->key.ul;
- g++;
- }
-
- if (gid_count != g) {
- DEBUG(SSSDBG_OP_FAILURE, ("Number of hash entries and groups do not "
- "match.\n"));
- ret = EINVAL;
- goto done;
- }
-
- ret = EOK;
-
-done:
- if (ret != EOK) {
- talloc_free(gids);
- } else {
- dom_grps->grp_dom = grp_dom;
- dom_grps->gid_count = gid_count;
- dom_grps->gids = gids;
- }
-
- return ret;
-}
-
-/**
- * Find all Posix GIDs from a PAC by searching for group SIDs from the local
- * domain and convert them to GIDs.
- */
-errno_t get_gids_from_pac(TALLOC_CTX *mem_ctx,
+errno_t get_sids_from_pac(TALLOC_CTX *mem_ctx,
struct pac_ctx *pac_ctx,
- struct local_mapping_ranges *range_map,
- struct dom_sid *domain_sid,
struct PAC_LOGON_INFO *logon_info,
- size_t *_gid_count, struct pac_dom_grps **_gids)
+ char **_user_sid_str,
+ char **_primary_group_sid_str,
+ hash_table_t **_sid_table)
{
int ret;
- size_t gid_count = 0;
size_t s;
struct netr_SamInfo3 *info3;
- struct pac_dom_grps *gids = NULL;
- struct sss_domain_info *grp_dom;
+ struct sss_domain_info *user_dom;
+ struct sss_domain_info *group_dom;
char *sid_str = NULL;
+ char *user_dom_sid_str = NULL;
+ size_t user_dom_sid_str_len;
enum idmap_error_code err;
- struct dom_sid *grp_sid = NULL;
- uint32_t id;
- hash_table_t *gid_table;
+ hash_table_t *sid_table = NULL;
hash_key_t key;
hash_value_t value;
- TALLOC_CTX *tmp_ctx = NULL;
+ char *rid_start;
+ struct ldb_result *msg;
+ char *user_sid_str = NULL;
+ char *primary_group_sid_str = NULL;
- if (pac_ctx == NULL || range_map == NULL || domain_sid == NULL ||
- logon_info == NULL || _gid_count == NULL || _gids == NULL) {
+ if (pac_ctx == NULL || logon_info == NULL || _sid_table == NULL) {
DEBUG(SSSDBG_OP_FAILURE, ("Missing parameter.\n"));
return EINVAL;
}
info3 = &logon_info->info3;
- if (info3->sidcount == 0 && info3->base.groups.count == 0) {
- DEBUG(SSSDBG_TRACE_ALL, ("No extra groups found.\n"));
- ret = EOK;
+ ret = sss_hash_create(mem_ctx,
+ info3->sidcount + info3->base.groups.count + 2,
+ &sid_table);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("sss_hash_create failed.\n"));
goto done;
}
- tmp_ctx = talloc_new(NULL);
- if (tmp_ctx == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("talloc_new failed.\n"));
- ret = ENOMEM;
+ key.type = HASH_KEY_STRING;
+ value.type = HASH_VALUE_ULONG;
+
+ err = sss_idmap_smb_sid_to_sid(pac_ctx->idmap_ctx, info3->base.domain_sid,
+ &user_dom_sid_str);
+ if (err != IDMAP_SUCCESS) {
+ DEBUG(SSSDBG_OP_FAILURE, ("sss_idmap_smb_sid_to_sid failed.\n"));
+ ret = EFAULT;
goto done;
}
- /* Currently three group containers are allocated, one for the IPA domain, one
- * for the trusted AD domain and an empty one to indicate the end of the
- * list. */
- gids = talloc_zero_array(tmp_ctx, struct pac_dom_grps, 3);
- if (gids == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("talloc_zero_array failed.\n"));
- ret = ENOMEM;
+ ret = responder_get_domain_by_id(pac_ctx->rctx, user_dom_sid_str,
+ &user_dom);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("responder_get_domain_by_id failed.\n"));
+ ret = EINVAL;
goto done;
}
- ret = sss_hash_create(tmp_ctx, info3->sidcount, &gid_table);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, ("sss_hash_create failed.\n"));
+ user_dom_sid_str_len = strlen(user_dom_sid_str);
+ sid_str = talloc_zero_size(mem_ctx, user_dom_sid_str_len + 12);
+ if (sid_str == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("talloc_zero_size failed.\n"));
+ ret = ENOMEM;
goto done;
}
+ rid_start = sid_str + user_dom_sid_str_len;
- key.type = HASH_KEY_ULONG;
- value.type = HASH_VALUE_PTR;
+ memcpy(sid_str, user_dom_sid_str, user_dom_sid_str_len);
- err = sss_idmap_smb_sid_to_sid(pac_ctx->idmap_ctx, domain_sid,
- &sid_str);
- if (err != IDMAP_SUCCESS) {
- DEBUG(SSSDBG_OP_FAILURE, ("sss_idmap_smb_sid_to_sid failed.\n"));
- ret = EFAULT;
+ memset(rid_start, '\0', 12);
+ ret = snprintf(rid_start, 12, "-%lu",
+ (unsigned long) info3->base.rid);
+ if (ret < 0 || ret > 12) {
+ DEBUG(SSSDBG_OP_FAILURE, ("snprintf failed.\n"));
+ ret = EIO;
goto done;
}
- grp_dom = find_domain_by_id(pac_ctx->rctx->domains, sid_str);
- if (grp_dom == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("find_domain_by_id failed.\n"));
- ret = EINVAL;
+ user_sid_str = talloc_strdup(mem_ctx, sid_str);
+ if (user_sid_str == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n"));
+ ret = ENOMEM;
goto done;
}
- for(s = 0; s < info3->sidcount; s++) {
- if (dom_sid_in_domain(domain_sid, info3->sids[s].sid)) {
- ret = local_sid_to_id(range_map, info3->sids[s].sid,
- &id);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, ("get_rid failed.\n"));
- goto done;
- }
-
- key.ul = id;
- value.ptr = grp_dom;
+ key.str = sid_str;
+ value.ul = 0;
- ret = hash_enter(gid_table, &key, &value);
- if (ret != HASH_SUCCESS) {
- DEBUG(SSSDBG_OP_FAILURE, ("hash_enter failed [%d][%s].\n",
- ret, hash_error_string(ret)));
- ret = EIO;
- goto done;
- }
-
- DEBUG(SSSDBG_TRACE_ALL, ("Found extra group with gid [%d].\n", id));
- }
+ ret = sysdb_search_object_by_sid(mem_ctx, user_dom->sysdb, user_dom,
+ sid_str, NULL, &msg);
+ if (ret == EOK && msg->count == 1) {
+ value.ul = ldb_msg_find_attr_as_uint64(msg->msgs[0], SYSDB_UIDNUM, 0);
+ talloc_free(msg);
}
- ret = get_dom_grps_from_hash(gids, gid_table, grp_dom, &gids[0]);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, ("get_dom_grps_from_hash failed.\n"));
+ ret = hash_enter(sid_table, &key, &value);
+ if (ret != HASH_SUCCESS) {
+ DEBUG(SSSDBG_OP_FAILURE, ("hash_enter failed [%d][%s].\n",
+ ret, hash_error_string(ret)));
+ ret = EIO;
goto done;
}
- gid_count += gids[0].gid_count;
- talloc_free(gid_table);
- ret = sss_hash_create(tmp_ctx, info3->base.groups.count, &gid_table);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, ("sss_hash_create failed.\n"));
+
+ memset(rid_start, '\0', 12);
+ ret = snprintf(rid_start, 12, "-%lu",
+ (unsigned long) info3->base.primary_gid);
+ if (ret < 0 || ret > 12) {
+ DEBUG(SSSDBG_OP_FAILURE, ("snprintf failed.\n"));
+ ret = EIO;
goto done;
}
- talloc_zfree(sid_str);
- err = sss_idmap_smb_sid_to_sid(pac_ctx->idmap_ctx, info3->base.domain_sid,
- &sid_str);
- if (err != IDMAP_SUCCESS) {
- DEBUG(SSSDBG_OP_FAILURE, ("sss_idmap_smb_sid_to_sid failed.\n"));
- ret = EFAULT;
+ primary_group_sid_str = talloc_strdup(mem_ctx, sid_str);
+ if (primary_group_sid_str == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n"));
+ ret = ENOMEM;
goto done;
}
- grp_dom = find_domain_by_id(pac_ctx->rctx->domains, sid_str);
- if (grp_dom == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("find_domain_by_id failed.\n"));
- ret = EINVAL;
- goto done;
+ key.str = sid_str;
+ value.ul = 0;
+
+ ret = sysdb_search_object_by_sid(mem_ctx, user_dom->sysdb, user_dom,
+ sid_str, NULL, &msg);
+ if (ret == EOK && msg->count == 1) {
+ value.ul = ldb_msg_find_attr_as_uint64(msg->msgs[0], SYSDB_GIDNUM, 0);
+ talloc_free(msg);
}
- err = sss_idmap_sid_to_smb_sid(pac_ctx->idmap_ctx, sid_str, &grp_sid);
- if (err != IDMAP_SUCCESS) {
- DEBUG(SSSDBG_OP_FAILURE, ("sss_idmap_sid_to_smb_sid failed.\n"));
- ret = EFAULT;
+ ret = hash_enter(sid_table, &key, &value);
+ if (ret != HASH_SUCCESS) {
+ DEBUG(SSSDBG_OP_FAILURE, ("hash_enter failed [%d][%s].\n",
+ ret, hash_error_string(ret)));
+ ret = EIO;
goto done;
}
- grp_sid->num_auths++;
for (s = 0; s < info3->base.groups.count; s++) {
- grp_sid->sub_auths[grp_sid->num_auths - 1] =
- info3->base.groups.rids[s].rid;
- err = sss_idmap_smb_sid_to_unix(pac_ctx->idmap_ctx, grp_sid,
- &id);
- if (err != IDMAP_SUCCESS) {
- DEBUG(SSSDBG_FATAL_FAILURE, ("sss_idmap_smb_sid_to_unix failed for"
- "[%s] [%d].\n", sid_str,
- info3->base.groups.rids[s].rid));
- ret = ENOENT;
+ memset(rid_start, '\0', 12);
+ ret = snprintf(rid_start, 12, "-%lu",
+ (unsigned long) info3->base.groups.rids[s].rid);
+ if (ret < 0 || ret > 12) {
+ DEBUG(SSSDBG_OP_FAILURE, ("snprintf failed.\n"));
+ ret = EIO;
goto done;
}
- key.ul = id;
- value.ptr = grp_dom;
+ key.str = sid_str;
+ value.ul = 0;
+
+ ret = sysdb_search_object_by_sid(mem_ctx, user_dom->sysdb, user_dom,
+ sid_str, NULL, &msg);
+ if (ret == EOK && msg->count == 1) {
+ value.ul = ldb_msg_find_attr_as_uint64(msg->msgs[0],
+ SYSDB_GIDNUM, 0);
+ talloc_free(msg);
+ }
- ret = hash_enter(gid_table, &key, &value);
+ ret = hash_enter(sid_table, &key, &value);
if (ret != HASH_SUCCESS) {
DEBUG(SSSDBG_OP_FAILURE, ("hash_enter failed [%d][%s].\n",
ret, hash_error_string(ret)));
@@ -644,29 +228,60 @@ errno_t get_gids_from_pac(TALLOC_CTX *mem_ctx,
goto done;
}
- DEBUG(SSSDBG_TRACE_ALL, ("Found extra group with gid [%d].\n", id));
}
- ret = get_dom_grps_from_hash(gids, gid_table, grp_dom, &gids[1]);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, ("get_dom_grps_from_hash failed.\n"));
- goto done;
+ talloc_zfree(sid_str);
+
+ for(s = 0; s < info3->sidcount; s++) {
+ err = sss_idmap_smb_sid_to_sid(pac_ctx->idmap_ctx, info3->sids[s].sid,
+ &sid_str);
+ if (err != IDMAP_SUCCESS) {
+ DEBUG(SSSDBG_OP_FAILURE, ("sss_idmap_smb_sid_to_sid failed.\n"));
+ ret = EFAULT;
+ goto done;
+ }
+
+ key.str = sid_str;
+ value.ul = 0;
+
+ ret = responder_get_domain_by_id(pac_ctx->rctx, sid_str, &group_dom);
+ if (ret == EOK) {
+ ret = sysdb_search_object_by_sid(mem_ctx, group_dom->sysdb,
+ group_dom, sid_str, NULL, &msg);
+ if (ret == EOK && msg->count == 1 ) {
+ value.ul = ldb_msg_find_attr_as_uint64(msg->msgs[0],
+ SYSDB_GIDNUM, 0);
+ talloc_free(msg);
+ }
+ }
+
+ ret = hash_enter(sid_table, &key, &value);
+ if (ret != HASH_SUCCESS) {
+ DEBUG(SSSDBG_OP_FAILURE, ("hash_enter failed [%d][%s].\n",
+ ret, hash_error_string(ret)));
+ ret = EIO;
+ goto done;
+ }
+
+ talloc_zfree(sid_str);
}
- gid_count += gids[1].gid_count;
ret = EOK;
done:
talloc_free(sid_str);
- talloc_free(grp_sid);
+ talloc_free(user_dom_sid_str);
if (ret == EOK) {
- *_gid_count = gid_count;
- *_gids = talloc_steal(mem_ctx, gids);
+ *_sid_table = sid_table;
+ *_user_sid_str = user_sid_str;
+ *_primary_group_sid_str = primary_group_sid_str;
+ } else {
+ hash_destroy(sid_table);
+ talloc_free(user_sid_str);
+ talloc_free(primary_group_sid_str);
}
- talloc_free(tmp_ctx);
-
return ret;
}
@@ -724,8 +339,10 @@ errno_t get_data_from_pac(TALLOC_CTX *mem_ctx,
* Fill up the passwd struct with data from the PAC logon info
*/
errno_t get_pwd_from_pac(TALLOC_CTX *mem_ctx,
- struct pac_ctx *pac_ctx,
struct sss_domain_info *dom,
+ char *user_sid_str,
+ char *primary_group_sid_str,
+ hash_table_t *sid_table,
struct PAC_LOGON_INFO *logon_info,
struct passwd **_pwd,
struct sysdb_attrs **_attrs)
@@ -737,6 +354,8 @@ errno_t get_pwd_from_pac(TALLOC_CTX *mem_ctx,
char *lname;
char *uc_realm;
char *upn;
+ hash_key_t key;
+ hash_value_t value;
pwd = talloc_zero(mem_ctx, struct passwd);
if (pwd == NULL) {
@@ -765,22 +384,52 @@ errno_t get_pwd_from_pac(TALLOC_CTX *mem_ctx,
ret = ENOMEM;
goto done;
}
- pwd->pw_name = sss_tc_fqname(pwd, dom->names, dom, lname);
+
+ /* Subdomain use fully qualified names */
+ if (IS_SUBDOMAIN(dom)) {
+ pwd->pw_name = sss_tc_fqname(pwd, dom->names, dom, lname);
+ } else {
+ pwd->pw_name = talloc_strdup(pwd, lname);
+ }
if (!pwd->pw_name) {
DEBUG(SSSDBG_OP_FAILURE, ("talloc_sprintf failed.\n"));
ret = ENOMEM;
goto done;
}
- ret = domsid_rid_to_uid(pac_ctx, dom->sysdb, dom->name,
- base_info->domain_sid,
- base_info->rid, &pwd->pw_uid);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, ("domsid_rid_to_uid failed.\n"));
+ key.type = HASH_KEY_STRING;
+ key.str = user_sid_str;
+ ret = hash_lookup(sid_table, &key, &value);
+ if (ret != HASH_SUCCESS) {
+ DEBUG(SSSDBG_OP_FAILURE, ("hash_lookup failed.\n"));
+ ret = EIO;
goto done;
}
+ if (value.type != HASH_VALUE_ULONG) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Wrong value type.\n"));
+ ret = EIO;
+ goto done;
+ }
+ pwd->pw_uid = value.ul;
- pwd->pw_gid = 0; /* We use MPGs for sub-domains */
+ if (IS_SUBDOMAIN(dom) || dom->mpg) {
+ pwd->pw_gid = 0; /* We use MPGs for sub-domains */
+ } else {
+ key.type = HASH_KEY_STRING;
+ key.str = primary_group_sid_str;
+ ret = hash_lookup(sid_table, &key, &value);
+ if (ret != HASH_SUCCESS) {
+ DEBUG(SSSDBG_OP_FAILURE, ("hash_lookup failed.\n"));
+ ret = EIO;
+ goto done;
+ }
+ if (value.type != HASH_VALUE_ULONG) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Wrong value type.\n"));
+ ret = EIO;
+ goto done;
+ }
+ pwd->pw_gid = value.ul;
+ }
if (base_info->full_name.size != 0) {
pwd->pw_gecos = talloc_strdup(pwd, base_info->full_name.string);
@@ -794,7 +443,9 @@ errno_t get_pwd_from_pac(TALLOC_CTX *mem_ctx,
"gecos field will by empty.\n "));
}
- if (dom->subdomain_homedir) {
+ /* Check if there is a special homedir template for sub-domains. If not a
+ * fallback will be added by the NSS responder. */
+ if (IS_SUBDOMAIN(dom) && dom->subdomain_homedir) {
pwd->pw_dir = expand_homedir_template(pwd, dom->subdomain_homedir,
lname, pwd->pw_uid, NULL,
dom->name, dom->flat_name);
@@ -841,213 +492,22 @@ errno_t get_pwd_from_pac(TALLOC_CTX *mem_ctx,
goto done;
}
- *_pwd = pwd;
- *_attrs = attrs;
-
- ret = EOK;
-
-done:
+ ret = sysdb_attrs_add_string(attrs, SYSDB_SID_STR, user_sid_str);
if (ret != EOK) {
- talloc_free(pwd);
- }
-
- return ret;
-}
-
-errno_t diff_gid_lists(TALLOC_CTX *mem_ctx,
- size_t cur_grp_num,
- struct grp_info *cur_grp_list,
- size_t new_gid_num,
- struct pac_dom_grps *new_gid_list,
- size_t *_add_gid_num,
- struct pac_dom_grps **_add_gid_list,
- size_t *_del_grp_num,
- struct grp_info ***_del_grp_list)
-{
- int ret;
- size_t c;
- size_t g;
- hash_table_t *table;
- hash_key_t key;
- hash_value_t value;
- size_t add_gid_num = 0;
- struct pac_dom_grps *add_gid_list = NULL;
- size_t del_grp_num = 0;
- struct grp_info **del_grp_list = NULL;
- TALLOC_CTX *tmp_ctx = NULL;
- unsigned long value_count;
- hash_value_t *values;
- size_t new_dom_num = 0;
-
- if ((cur_grp_num != 0 && cur_grp_list == NULL) ||
- (new_gid_num != 0 && new_gid_list == NULL)) {
- DEBUG(SSSDBG_OP_FAILURE, ("Missing group array.\n"));
- return EINVAL;
- }
-
- if (cur_grp_num == 0 && new_gid_num == 0) {
- ret = EOK;
- goto done;
- }
-
- tmp_ctx = talloc_new(NULL);
- if (tmp_ctx == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("talloc_new failed.\n"));
- ret = ENOMEM;
- goto done;
- }
-
- if (new_gid_num != 0) {
- for (new_dom_num = 0; new_gid_list[new_dom_num].grp_dom != NULL;
- new_dom_num++);
- }
-
- if (cur_grp_num == 0 && new_gid_num != 0) {
- add_gid_num = new_gid_num;
- add_gid_list = talloc_zero_array(tmp_ctx, struct pac_dom_grps,
- new_dom_num + 1);
- if (add_gid_list == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("talloc_array failed.\n"));
- ret = ENOMEM;
- goto done;
- }
-
- for (c = 0; c < new_dom_num; c++) {
- add_gid_list[c].grp_dom = new_gid_list[c].grp_dom;
- add_gid_list[c].gid_count = new_gid_list[c].gid_count;
- if (new_gid_list[c].gid_count != 0) {
- add_gid_list[c].gids = talloc_zero_array(add_gid_list, gid_t,
- new_gid_list[c].gid_count);
- if (add_gid_list[c].gids == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("talloc_zero_array failed.\n"));
- ret = ENOMEM;
- goto done;
- }
-
- for (g = 0; g < new_gid_list[c].gid_count; g++) {
- add_gid_list[c].gids[g] = new_gid_list[c].gids[g];
- }
- }
- }
-
- ret = EOK;
- goto done;
- }
-
- if (cur_grp_num != 0 && new_gid_num == 0) {
- del_grp_num = cur_grp_num;
- del_grp_list = talloc_array(tmp_ctx, struct grp_info *, del_grp_num);
- if (del_grp_list == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("talloc_array failed.\n"));
- ret = ENOMEM;
- goto done;
- }
-
- for (c = 0; c < del_grp_num; c++) {
- del_grp_list[c] = &cur_grp_list[c];
- }
-
- ret = EOK;
- goto done;
- }
-
- /* Add all current GIDs to a hash and then compare with the new ones in a
- * single loop */
- ret = sss_hash_create(tmp_ctx, cur_grp_num, &table);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, ("sss_hash_create failed.\n"));
- goto done;
- }
-
- key.type = HASH_KEY_ULONG;
- value.type = HASH_VALUE_PTR;
- for (c = 0; c < cur_grp_num; c++) {
- key.ul = (unsigned long) cur_grp_list[c].gid;
- value.ptr = &cur_grp_list[c];
-
- ret = hash_enter(table, &key, &value);
- if (ret != HASH_SUCCESS) {
- DEBUG(SSSDBG_OP_FAILURE, ("hash_enter failed.\n"));
- ret = EIO;
- goto done;
- }
- }
-
- add_gid_list = talloc_zero_array(tmp_ctx, struct pac_dom_grps,
- new_dom_num + 1);
- if (add_gid_list == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("talloc_array failed.\n"));
- ret = ENOMEM;
- goto done;
- }
-
- for (c = 0; c < new_dom_num; c++) {
- add_gid_list[c].grp_dom = new_gid_list[c].grp_dom;
- add_gid_list[c].gid_count = 0;
-
- for (g = 0; g < new_gid_list[c].gid_count; g++) {
- key.ul = (unsigned long) new_gid_list[c].gids[g];
-
- ret = hash_delete(table, &key);
- if (ret == HASH_ERROR_KEY_NOT_FOUND) {
- /* gid not found, must be added */
- add_gid_list[c].gid_count++;
- add_gid_list[c].gids = talloc_realloc(add_gid_list,
- add_gid_list,
- gid_t,
- add_gid_list[c].gid_count);
- if (add_gid_list[c].gids == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("talloc_realloc failed.\n"));
- ret = ENOMEM;
- goto done;
- }
-
- add_gid_list[c].gids[add_gid_list[c].gid_count - 1] =
- new_gid_list[c].gids[g];
- } else if (ret != HASH_SUCCESS) {
- DEBUG(SSSDBG_OP_FAILURE, ("hash_delete failed.\n"));
- ret = EIO;
- goto done;
- }
- }
-
- add_gid_num += add_gid_list[c].gid_count;
- }
-
- /* the remaining entries in the hash are not in the new list anymore and
- * must be deleted */
- ret = hash_values(table, &value_count, &values);
- if (ret != HASH_SUCCESS) {
- DEBUG(SSSDBG_OP_FAILURE, ("hash_keys failed.\n"));
- ret = EIO;
- goto done;
- }
-
- del_grp_num = value_count;
- del_grp_list = talloc_array(tmp_ctx, struct grp_info *, del_grp_num);
- if (del_grp_list == NULL) {
- DEBUG(SSSDBG_OP_FAILURE, ("talloc_array failed.\n"));
- ret = ENOMEM;
+ DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_add_string failed.\n"));
goto done;
}
- for (c = 0; c < del_grp_num; c++) {
- del_grp_list[c] = (struct grp_info *) values[c].ptr;
- }
+ *_pwd = pwd;
+ *_attrs = attrs;
ret = EOK;
done:
-
- if (ret == EOK) {
- *_add_gid_num = add_gid_num;
- *_add_gid_list = talloc_steal(mem_ctx, add_gid_list);
- *_del_grp_num = del_grp_num;
- *_del_grp_list = talloc_steal(mem_ctx, del_grp_list);
+ if (ret != EOK) {
+ talloc_free(pwd);
}
- talloc_free(tmp_ctx);
-
return ret;
}
@@ -1071,14 +531,11 @@ bool new_and_cached_user_differs(struct passwd *pwd, struct ldb_message *msg)
return true;
}
- if (!compare_string_with_attr(pwd->pw_name, msg, SYSDB_NAME)) {
+ if (!compare_string_with_attr(pwd->pw_name, msg, SYSDB_NAME) &&
+ !compare_string_with_attr(pwd->pw_name, msg, SYSDB_NAME_ALIAS)) {
DEBUG(SSSDBG_TRACE_FUNC, ("Names differ."));
return true;
}
- if (!compare_string_with_attr(pwd->pw_gecos, msg, SYSDB_GECOS)) {
- DEBUG(SSSDBG_TRACE_FUNC, ("Gecos fields differ."));
- return true;
- }
if (!compare_string_with_attr(pwd->pw_dir, msg, SYSDB_HOMEDIR)) {
DEBUG(SSSDBG_TRACE_FUNC, ("Home directories differ."));