From 2372bd7d0ce6bfe2ce2cc64c1b368b6cc876c70d Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 11 Apr 2014 19:14:41 +0200 Subject: [PATCH] autorid: Add allocation from above in alloc range for well known sids This way, we achieve a better determinism for the id mappings of the well knowns without wasting a separate range. Signed-off-by: Michael Adam Reviewed-by: Stefan Metzmacher Autobuild-User(master): Michael Adam Autobuild-Date(master): Fri Apr 25 17:52:10 CEST 2014 on sn-devel-104 --- source3/winbindd/idmap_autorid.c | 86 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/source3/winbindd/idmap_autorid.c b/source3/winbindd/idmap_autorid.c index 8741b84809f..37612c2f535 100644 --- a/source3/winbindd/idmap_autorid.c +++ b/source3/winbindd/idmap_autorid.c @@ -340,6 +340,76 @@ static NTSTATUS idmap_autorid_unixids_to_sids(struct idmap_domain *dom, return ret; } +static bool idmap_autorid_sid_is_special(struct dom_sid *sid) +{ + bool match; + + match = sid_check_is_in_wellknown_domain(sid); + if (match) { + return true; + } + + return false; +} + +static NTSTATUS idmap_autorid_sid_to_id_special(struct idmap_domain *dom, + struct id_map *map) +{ + struct idmap_tdb_common_context *common = + talloc_get_type_abort(dom->private_data, + struct idmap_tdb_common_context); + uint32_t count; + struct autorid_range_config range; + NTSTATUS status; + uint32_t free_id; + + status = idmap_autorid_get_alloc_range(dom, &range); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + /* Take the next free ID, counting from the top */ + free_id = 0; + for (count = 0; count < IDMAP_AUTORID_ALLOC_RESERVED; count++) { + struct id_map test_map; + struct dom_sid sid; + + test_map.sid = &sid; + test_map.xid.type = map->xid.type; + test_map.xid.id = range.high_id - count; + test_map.status = ID_UNKNOWN; + + status = idmap_tdb_common_unixid_to_sid(dom, &test_map); + if (NT_STATUS_EQUAL(NT_STATUS_NONE_MAPPED, status)) { + free_id = test_map.xid.id; + break; + } + + if (!NT_STATUS_IS_OK(status)) { + /* error - get out */ + return status; + } + + /* mapping exists - try next ID */ + } + + if (free_id == 0) { + return NT_STATUS_NONE_MAPPED; + } + + map->status = ID_MAPPED; + map->xid.id = free_id; + + status = common->rw_ops->set_mapping(dom, map); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(2, ("Error storing new mapping: %s\n", + nt_errstr(status))); + return status; + } + + return NT_STATUS_OK; +} + struct idmap_autorid_sid_to_id_alloc_ctx { struct idmap_domain *dom; struct id_map *map; @@ -353,6 +423,22 @@ static NTSTATUS idmap_autorid_sid_to_id_alloc_action( ctx = (struct idmap_autorid_sid_to_id_alloc_ctx *)private_data; + if (idmap_autorid_sid_is_special(ctx->map->sid)) { + NTSTATUS ret; + + ret = idmap_autorid_sid_to_id_special(ctx->dom, ctx->map); + if (NT_STATUS_IS_OK(ret)) { + return NT_STATUS_OK; + } + if (!NT_STATUS_EQUAL(NT_STATUS_NONE_MAPPED, ret)) { + return ret; + } + + DEBUG(10, ("Sepecial sid %s not mapped. falling back to " + "regular allocation\n", + sid_string_dbg(ctx->map->sid))); + } + return idmap_tdb_common_new_mapping(ctx->dom, ctx->map); } -- 2.11.4.GIT