From 205a0b78f2f7d53add7dc33b93d53e15bf4d5e13 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 21 Mar 2019 16:38:35 +0100 Subject: [PATCH 01/11] idmap_hash: provide ID_TYPE_BOTH mappings also for unixids_to_sids While sids_to_unixids returns ID_TYPE_BOTH mappings, unixids_to_sids() returns the callers asked for, which fills gencache with the non ID_TYPE_BOTH mappings. As a result also the sids_to_unixids fast path via gencache won't return ID_TYPE_BOTH mappings. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15319 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison (cherry picked from commit 9a24570d3d69f51b6d50bb04b739815ec67c1a3d) --- source3/winbindd/idmap_hash/idmap_hash.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source3/winbindd/idmap_hash/idmap_hash.c b/source3/winbindd/idmap_hash/idmap_hash.c index d0bed7631a6..ec85119b063 100644 --- a/source3/winbindd/idmap_hash/idmap_hash.c +++ b/source3/winbindd/idmap_hash/idmap_hash.c @@ -224,6 +224,7 @@ static NTSTATUS unixids_to_sids(struct idmap_domain *dom, if (!hashed_domains[h_domain].sid) continue; + ids[i]->xid.type = ID_TYPE_BOTH; sid_compose(ids[i]->sid, hashed_domains[h_domain].sid, h_rid); ids[i]->status = ID_MAPPED; } -- 2.34.1 From 7acbdc9d3d1974897e9b94b95d7476e483a03613 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 21 Mar 2019 13:37:16 +0100 Subject: [PATCH 02/11] idmap_hash: fix comments about the algorithm Only support ~ 50k users per domain. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15319 Signed-off-by: Stefan Metzmacher Reviewed-by: Ralph Boehme (cherry picked from commit 0f96c4b419a59ea884e68a460910e5c8a45bfcec) --- source3/winbindd/idmap_hash/idmap_hash.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/source3/winbindd/idmap_hash/idmap_hash.c b/source3/winbindd/idmap_hash/idmap_hash.c index ec85119b063..99341bc6fab 100644 --- a/source3/winbindd/idmap_hash/idmap_hash.c +++ b/source3/winbindd/idmap_hash/idmap_hash.c @@ -60,13 +60,16 @@ static uint32_t hash_domain_sid(const struct dom_sid *sid) } /********************************************************************* - Hash a Relative ID to a 20 bit number + Hash a Relative ID to a 19 bit number ********************************************************************/ static uint32_t hash_rid(uint32_t rid) { - /* 20 bits for the rid which allows us to support - the first 100K users/groups in a domain */ + /* + * 19 bits for the rid which allows us to support + * the first 50K users/groups in a domain + * + */ return (rid & 0x0007FFFF); } @@ -79,8 +82,13 @@ static uint32_t combine_hashes(uint32_t h_domain, { uint32_t return_id = 0; - /* shift the hash_domain 19 bits to the left and OR with the - hash_rid */ + /* + * shift the hash_domain 19 bits to the left and OR with the + * hash_rid + * + * This will generate a 31 bit number out of + * 12 bit domain and 19 bit rid. + */ return_id = ((h_domain<<19) | h_rid); -- 2.34.1 From d1411c6c308097f539a97770e6e2ecaf3610d07c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 21 Mar 2019 13:54:10 +0100 Subject: [PATCH 03/11] idmap_hash: remove unused error checks id_map_ptrs_init() is used in the callers in order to set everything up as expected. Other backends also just trust the caller. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15319 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison (cherry picked from commit 2cfcff3101fce94b365eccde114432dfa980bbd0) --- source3/winbindd/idmap_hash/idmap_hash.c | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/source3/winbindd/idmap_hash/idmap_hash.c b/source3/winbindd/idmap_hash/idmap_hash.c index 99341bc6fab..ce324bfd240 100644 --- a/source3/winbindd/idmap_hash/idmap_hash.c +++ b/source3/winbindd/idmap_hash/idmap_hash.c @@ -199,11 +199,6 @@ static NTSTATUS unixids_to_sids(struct idmap_domain *dom, NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; int i; - if (!ids) { - nt_status = NT_STATUS_INVALID_PARAMETER; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - /* initialize the status to avoid suprise */ for (i = 0; ids[i]; i++) { ids[i]->status = ID_UNKNOWN; @@ -219,13 +214,6 @@ static NTSTATUS unixids_to_sids(struct idmap_domain *dom, separate_hashes(ids[i]->xid.id, &h_domain, &h_rid); - /* Make sure the caller allocated memor for us */ - - if (!ids[i]->sid) { - nt_status = NT_STATUS_INVALID_PARAMETER; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - /* If the domain hash doesn't find a SID in the table, skip it */ @@ -250,11 +238,6 @@ static NTSTATUS sids_to_unixids(struct idmap_domain *dom, NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; int i; - if (!ids) { - nt_status = NT_STATUS_INVALID_PARAMETER; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } - /* initialize the status to avoid suprise */ for (i = 0; ids[i]; i++) { ids[i]->status = ID_UNKNOWN; -- 2.34.1 From e8361d4ed2aa57bc55458d8c55d2d82a38b7c674 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 21 Mar 2019 10:54:49 +0100 Subject: [PATCH 04/11] idmap_hash: we don't need to call idmap_hash_initialize() over an over again It's always the first function that's called from idmap_methods. This also demonstrates that we currently always return NT_STATUS_OK, even if we haven't mapped all map entries. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15319 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison (cherry picked from commit 0da13ab3ad7278eafdcd988f39e891242eb46d37) --- source3/winbindd/idmap_hash/idmap_hash.c | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/source3/winbindd/idmap_hash/idmap_hash.c b/source3/winbindd/idmap_hash/idmap_hash.c index ce324bfd240..7b849aa0259 100644 --- a/source3/winbindd/idmap_hash/idmap_hash.c +++ b/source3/winbindd/idmap_hash/idmap_hash.c @@ -131,14 +131,6 @@ static NTSTATUS idmap_hash_initialize(struct idmap_domain *dom) return NT_STATUS_INVALID_PARAMETER; } - /* If the domain SID hash table has been initialized, assume - that we completed this function previously */ - - if (dom->private_data != NULL) { - nt_status = NT_STATUS_OK; - goto done; - } - if (!wcache_tdc_fetch_list(&dom_list, &num_domains)) { nt_status = NT_STATUS_TRUSTED_DOMAIN_FAILURE; BAIL_ON_NTSTATUS_ERROR(nt_status); @@ -196,7 +188,6 @@ static NTSTATUS unixids_to_sids(struct idmap_domain *dom, { struct sid_hash_table *hashed_domains = talloc_get_type_abort( dom->private_data, struct sid_hash_table); - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; int i; /* initialize the status to avoid suprise */ @@ -204,9 +195,6 @@ static NTSTATUS unixids_to_sids(struct idmap_domain *dom, ids[i]->status = ID_UNKNOWN; } - nt_status = idmap_hash_initialize(dom); - BAIL_ON_NTSTATUS_ERROR(nt_status); - for (i=0; ids[i]; i++) { uint32_t h_domain, h_rid; @@ -225,8 +213,7 @@ static NTSTATUS unixids_to_sids(struct idmap_domain *dom, ids[i]->status = ID_MAPPED; } -done: - return nt_status; + return NT_STATUS_OK; } /********************************************************************* @@ -235,7 +222,6 @@ done: static NTSTATUS sids_to_unixids(struct idmap_domain *dom, struct id_map **ids) { - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; int i; /* initialize the status to avoid suprise */ @@ -243,9 +229,6 @@ static NTSTATUS sids_to_unixids(struct idmap_domain *dom, ids[i]->status = ID_UNKNOWN; } - nt_status = idmap_hash_initialize(dom); - BAIL_ON_NTSTATUS_ERROR(nt_status); - for (i=0; ids[i]; i++) { struct dom_sid sid; uint32_t rid; @@ -302,8 +285,7 @@ static NTSTATUS sids_to_unixids(struct idmap_domain *dom, } } -done: - return nt_status; + return NT_STATUS_OK; } /********************************************************************* -- 2.34.1 From 78fe1bdca024ba530158321ff4e8232f9c867b72 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 21 Mar 2019 14:00:16 +0100 Subject: [PATCH 05/11] idmap_hash: mirror the NT_STATUS_NONE_MAPPED/STATUS_SOME_UNMAPPED logic from idmap_autorid BUG: https://bugzilla.samba.org/show_bug.cgi?id=15319 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison (cherry picked from commit 14102b05f3744c67178bd719d41e67fc3e049ee4) --- source3/winbindd/idmap_hash/idmap_hash.c | 36 ++++++++++++++++++++---- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/source3/winbindd/idmap_hash/idmap_hash.c b/source3/winbindd/idmap_hash/idmap_hash.c index 7b849aa0259..ff9f86b6676 100644 --- a/source3/winbindd/idmap_hash/idmap_hash.c +++ b/source3/winbindd/idmap_hash/idmap_hash.c @@ -188,11 +188,14 @@ static NTSTATUS unixids_to_sids(struct idmap_domain *dom, { struct sid_hash_table *hashed_domains = talloc_get_type_abort( dom->private_data, struct sid_hash_table); - int i; + size_t i; + size_t num_tomap = 0; + size_t num_mapped = 0; - /* initialize the status to avoid suprise */ + /* initialize the status to avoid surprise */ for (i = 0; ids[i]; i++) { ids[i]->status = ID_UNKNOWN; + num_tomap++; } for (i=0; ids[i]; i++) { @@ -211,9 +214,16 @@ static NTSTATUS unixids_to_sids(struct idmap_domain *dom, ids[i]->xid.type = ID_TYPE_BOTH; sid_compose(ids[i]->sid, hashed_domains[h_domain].sid, h_rid); ids[i]->status = ID_MAPPED; + num_mapped++; } - return NT_STATUS_OK; + if (num_tomap == num_mapped) { + return NT_STATUS_OK; + } else if (num_mapped == 0) { + return NT_STATUS_NONE_MAPPED; + } + + return STATUS_SOME_UNMAPPED; } /********************************************************************* @@ -222,11 +232,15 @@ static NTSTATUS unixids_to_sids(struct idmap_domain *dom, static NTSTATUS sids_to_unixids(struct idmap_domain *dom, struct id_map **ids) { - int i; + size_t i; + size_t num_tomap = 0; + size_t num_mapped = 0; + size_t num_required = 0; - /* initialize the status to avoid suprise */ + /* initialize the status to avoid surprise */ for (i = 0; ids[i]; i++) { ids[i]->status = ID_UNKNOWN; + num_tomap++; } for (i=0; ids[i]; i++) { @@ -252,6 +266,7 @@ static NTSTATUS sids_to_unixids(struct idmap_domain *dom, * if the domain is not known yet. */ ids[i]->status = ID_REQUIRE_TYPE; + num_required++; continue; } @@ -282,10 +297,19 @@ static NTSTATUS sids_to_unixids(struct idmap_domain *dom, ids[i]->xid.type = ID_TYPE_BOTH; ids[i]->xid.id = combine_hashes(h_domain, h_rid); ids[i]->status = ID_MAPPED; + num_mapped++; } } - return NT_STATUS_OK; + if (num_tomap == num_mapped) { + return NT_STATUS_OK; + } else if (num_required > 0) { + return STATUS_SOME_UNMAPPED; + } else if (num_mapped == 0) { + return NT_STATUS_NONE_MAPPED; + } + + return STATUS_SOME_UNMAPPED; } /********************************************************************* -- 2.34.1 From d693e1ff8c9c8c1eb6f93cdf4d0c01b370ff163e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 21 Mar 2019 14:05:13 +0100 Subject: [PATCH 06/11] idmap_hash: split out a idmap_hash_id_to_sid() helper function BUG: https://bugzilla.samba.org/show_bug.cgi?id=15319 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison (cherry picked from commit 57150b463fb8e27c048670f7b4902bd091ee3ae9) --- source3/winbindd/idmap_hash/idmap_hash.c | 54 +++++++++++++++++------- 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/source3/winbindd/idmap_hash/idmap_hash.c b/source3/winbindd/idmap_hash/idmap_hash.c index ff9f86b6676..1f353c331d5 100644 --- a/source3/winbindd/idmap_hash/idmap_hash.c +++ b/source3/winbindd/idmap_hash/idmap_hash.c @@ -183,6 +183,32 @@ done: /********************************************************************* ********************************************************************/ +static NTSTATUS idmap_hash_id_to_sid(struct sid_hash_table *hashed_domains, + struct idmap_domain *dom, + struct id_map *id) +{ + uint32_t h_domain = 0, h_rid = 0; + + id->status = ID_UNMAPPED; + + separate_hashes(id->xid.id, &h_domain, &h_rid); + + /* + * If the domain hash doesn't find a SID in the table, + * skip it + */ + if (hashed_domains[h_domain].sid == NULL) { + /* keep ID_UNMAPPED */ + return NT_STATUS_OK; + } + + id->xid.type = ID_TYPE_BOTH; + sid_compose(id->sid, hashed_domains[h_domain].sid, h_rid); + id->status = ID_MAPPED; + + return NT_STATUS_OK; +} + static NTSTATUS unixids_to_sids(struct idmap_domain *dom, struct id_map **ids) { @@ -199,22 +225,20 @@ static NTSTATUS unixids_to_sids(struct idmap_domain *dom, } for (i=0; ids[i]; i++) { - uint32_t h_domain, h_rid; - - ids[i]->status = ID_UNMAPPED; - - separate_hashes(ids[i]->xid.id, &h_domain, &h_rid); - - /* If the domain hash doesn't find a SID in the table, - skip it */ - - if (!hashed_domains[h_domain].sid) - continue; + NTSTATUS ret; + + ret = idmap_hash_id_to_sid(hashed_domains, dom, ids[i]); + if (!NT_STATUS_IS_OK(ret)) { + /* some fatal error occurred, log it */ + DBG_NOTICE("Unexpected error resolving an ID " + "(%d): %s\n", ids[i]->xid.id, + nt_errstr(ret)); + return ret; + } - ids[i]->xid.type = ID_TYPE_BOTH; - sid_compose(ids[i]->sid, hashed_domains[h_domain].sid, h_rid); - ids[i]->status = ID_MAPPED; - num_mapped++; + if (ids[i]->status == ID_MAPPED) { + num_mapped++; + } } if (num_tomap == num_mapped) { -- 2.34.1 From dddf06a3576fb53774997addc7327cec49d128e2 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 21 Mar 2019 14:05:13 +0100 Subject: [PATCH 07/11] idmap_hash: split out a idmap_hash_sid_to_id() helper function BUG: https://bugzilla.samba.org/show_bug.cgi?id=15319 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison (cherry picked from commit c158b075b0b5035615fa8848f1f3d8ef27696861) --- source3/winbindd/idmap_hash/idmap_hash.c | 135 ++++++++++++++--------- 1 file changed, 84 insertions(+), 51 deletions(-) diff --git a/source3/winbindd/idmap_hash/idmap_hash.c b/source3/winbindd/idmap_hash/idmap_hash.c index 1f353c331d5..726338473ea 100644 --- a/source3/winbindd/idmap_hash/idmap_hash.c +++ b/source3/winbindd/idmap_hash/idmap_hash.c @@ -253,9 +253,78 @@ static NTSTATUS unixids_to_sids(struct idmap_domain *dom, /********************************************************************* ********************************************************************/ +static NTSTATUS idmap_hash_sid_to_id(struct sid_hash_table *hashed_domains, + struct idmap_domain *dom, + struct id_map *id) +{ + struct dom_sid sid; + uint32_t rid; + uint32_t h_domain, h_rid; + + if (id->xid.type == ID_TYPE_NOT_SPECIFIED) { + /* + * idmap_hash used to bounce back the requested type, + * which was ID_TYPE_UID, ID_TYPE_GID or + * ID_TYPE_NOT_SPECIFIED before as the winbindd parent + * always used a lookupsids. When the lookupsids + * failed because of an unknown domain, the idmap child + * weren't requested at all and the caller sees + * ID_TYPE_NOT_SPECIFIED. + * + * Now that the winbindd parent will pass ID_TYPE_BOTH + * in order to indicate that the domain exists. + * We should ask the parent to fallback to lookupsids + * if the domain is not known yet. + */ + id->status = ID_REQUIRE_TYPE; + return NT_STATUS_OK; + } + + id->status = ID_UNMAPPED; + + sid_copy(&sid, id->sid); + sid_split_rid(&sid, &rid); + + h_domain = hash_domain_sid(&sid); + h_rid = hash_rid(rid); + + /* Check that both hashes are non-zero*/ + if (h_domain == 0) { + /* keep ID_UNMAPPED */ + return NT_STATUS_OK; + } + if (h_rid == 0) { + /* keep ID_UNMAPPED */ + return NT_STATUS_OK; + } + + /* + * idmap_hash used to bounce back the requested type, + * which was ID_TYPE_UID, ID_TYPE_GID or + * ID_TYPE_NOT_SPECIFIED before as the winbindd parent + * always used a lookupsids. + * + * This module should have supported ID_TYPE_BOTH since + * samba-4.1.0, similar to idmap_rid and idmap_autorid. + * + * Now that the winbindd parent will pass ID_TYPE_BOTH + * in order to indicate that the domain exists, it's + * better to always return ID_TYPE_BOTH instead of a + * random mix of ID_TYPE_UID, ID_TYPE_GID or + * ID_TYPE_BOTH. + */ + id->xid.type = ID_TYPE_BOTH; + id->xid.id = combine_hashes(h_domain, h_rid); + id->status = ID_MAPPED; + + return NT_STATUS_OK; +} + static NTSTATUS sids_to_unixids(struct idmap_domain *dom, struct id_map **ids) { + struct sid_hash_table *hashed_domains = talloc_get_type_abort( + dom->private_data, struct sid_hash_table); size_t i; size_t num_tomap = 0; size_t num_mapped = 0; @@ -268,61 +337,25 @@ static NTSTATUS sids_to_unixids(struct idmap_domain *dom, } for (i=0; ids[i]; i++) { - struct dom_sid sid; - uint32_t rid; - uint32_t h_domain, h_rid; - - ids[i]->status = ID_UNMAPPED; - - if (ids[i]->xid.type == ID_TYPE_NOT_SPECIFIED) { - /* - * idmap_hash used to bounce back the requested type, - * which was ID_TYPE_UID, ID_TYPE_GID or - * ID_TYPE_NOT_SPECIFIED before as the winbindd parent - * always used a lookupsids. When the lookupsids - * failed because of an unknown domain, the idmap child - * weren't requested at all and the caller sees - * ID_TYPE_NOT_SPECIFIED. - * - * Now that the winbindd parent will pass ID_TYPE_BOTH - * in order to indicate that the domain exists. - * We should ask the parent to fallback to lookupsids - * if the domain is not known yet. - */ - ids[i]->status = ID_REQUIRE_TYPE; - num_required++; - continue; + NTSTATUS ret; + + ret = idmap_hash_sid_to_id(hashed_domains, dom, ids[i]); + if (!NT_STATUS_IS_OK(ret)) { + struct dom_sid_buf buf; + /* some fatal error occurred, log it */ + DBG_NOTICE("Unexpected error resolving a SID " + "(%s): %s\n", + dom_sid_str_buf(ids[i]->sid, &buf), + nt_errstr(ret)); + return ret; } - sid_copy(&sid, ids[i]->sid); - sid_split_rid(&sid, &rid); - - h_domain = hash_domain_sid(&sid); - h_rid = hash_rid(rid); - - /* Check that both hashes are non-zero*/ - - if (h_domain && h_rid) { - /* - * idmap_hash used to bounce back the requested type, - * which was ID_TYPE_UID, ID_TYPE_GID or - * ID_TYPE_NOT_SPECIFIED before as the winbindd parent - * always used a lookupsids. - * - * This module should have supported ID_TYPE_BOTH since - * samba-4.1.0, similar to idmap_rid and idmap_autorid. - * - * Now that the winbindd parent will pass ID_TYPE_BOTH - * in order to indicate that the domain exists, it's - * better to always return ID_TYPE_BOTH instead of a - * random mix of ID_TYPE_UID, ID_TYPE_GID or - * ID_TYPE_BOTH. - */ - ids[i]->xid.type = ID_TYPE_BOTH; - ids[i]->xid.id = combine_hashes(h_domain, h_rid); - ids[i]->status = ID_MAPPED; + if (ids[i]->status == ID_MAPPED) { num_mapped++; } + if (ids[i]->status == ID_REQUIRE_TYPE) { + num_required++; + } } if (num_tomap == num_mapped) { -- 2.34.1 From 2c90796767a1740ca3d1b2218343d04ba2c0ff9d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 21 Mar 2019 16:54:31 +0100 Subject: [PATCH 08/11] idmap_hash: return ID_REQUIRE_TYPE only if there's a chance to get a mapping later If we are going to return ID_UNMAPPED later anyway, there's no need to defer that decision by returning ID_REQUIRE_TYPE first. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15319 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison (cherry picked from commit 42dcb3db05530179a991fe58e7b96b52bbbcc607) --- source3/winbindd/idmap_hash/idmap_hash.c | 36 ++++++++++++------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/source3/winbindd/idmap_hash/idmap_hash.c b/source3/winbindd/idmap_hash/idmap_hash.c index 726338473ea..ed20a5e8bed 100644 --- a/source3/winbindd/idmap_hash/idmap_hash.c +++ b/source3/winbindd/idmap_hash/idmap_hash.c @@ -261,6 +261,24 @@ static NTSTATUS idmap_hash_sid_to_id(struct sid_hash_table *hashed_domains, uint32_t rid; uint32_t h_domain, h_rid; + id->status = ID_UNMAPPED; + + sid_copy(&sid, id->sid); + sid_split_rid(&sid, &rid); + + h_domain = hash_domain_sid(&sid); + h_rid = hash_rid(rid); + + /* Check that both hashes are non-zero*/ + if (h_domain == 0) { + /* keep ID_UNMAPPED */ + return NT_STATUS_OK; + } + if (h_rid == 0) { + /* keep ID_UNMAPPED */ + return NT_STATUS_OK; + } + if (id->xid.type == ID_TYPE_NOT_SPECIFIED) { /* * idmap_hash used to bounce back the requested type, @@ -280,24 +298,6 @@ static NTSTATUS idmap_hash_sid_to_id(struct sid_hash_table *hashed_domains, return NT_STATUS_OK; } - id->status = ID_UNMAPPED; - - sid_copy(&sid, id->sid); - sid_split_rid(&sid, &rid); - - h_domain = hash_domain_sid(&sid); - h_rid = hash_rid(rid); - - /* Check that both hashes are non-zero*/ - if (h_domain == 0) { - /* keep ID_UNMAPPED */ - return NT_STATUS_OK; - } - if (h_rid == 0) { - /* keep ID_UNMAPPED */ - return NT_STATUS_OK; - } - /* * idmap_hash used to bounce back the requested type, * which was ID_TYPE_UID, ID_TYPE_GID or -- 2.34.1 From 6d3bdf649ce8b96a69e40907b37a00a84b77d829 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 21 Mar 2019 16:54:31 +0100 Subject: [PATCH 09/11] idmap_hash: only return ID_REQUIRE_TYPE if we don't know about the domain yet BUG: https://bugzilla.samba.org/show_bug.cgi?id=15319 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison (cherry picked from commit ede88d9f83fb77fa8eff226fb6a85ac71e415098) --- source3/winbindd/idmap_hash/idmap_hash.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/source3/winbindd/idmap_hash/idmap_hash.c b/source3/winbindd/idmap_hash/idmap_hash.c index ed20a5e8bed..fb900617ec3 100644 --- a/source3/winbindd/idmap_hash/idmap_hash.c +++ b/source3/winbindd/idmap_hash/idmap_hash.c @@ -279,6 +279,14 @@ static NTSTATUS idmap_hash_sid_to_id(struct sid_hash_table *hashed_domains, return NT_STATUS_OK; } + /* + * If the domain hash already exists find a SID in the table, + * just return the mapping. + */ + if (hashed_domains[h_domain].sid != NULL) { + goto return_mapping; + } + if (id->xid.type == ID_TYPE_NOT_SPECIFIED) { /* * idmap_hash used to bounce back the requested type, @@ -313,6 +321,7 @@ static NTSTATUS idmap_hash_sid_to_id(struct sid_hash_table *hashed_domains, * random mix of ID_TYPE_UID, ID_TYPE_GID or * ID_TYPE_BOTH. */ +return_mapping: id->xid.type = ID_TYPE_BOTH; id->xid.id = combine_hashes(h_domain, h_rid); id->status = ID_MAPPED; -- 2.34.1 From 86e6013ddf3994b31dfddcb12aca4a7c1f717462 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 21 Mar 2019 16:54:31 +0100 Subject: [PATCH 10/11] idmap_hash: don't return ID_REQUIRE_TYPE if the domain is known in the netsamlogon cache BUG: https://bugzilla.samba.org/show_bug.cgi?id=15319 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison (cherry picked from commit ee820553fd2c6ada966a0160cbb0240049f9d9f7) --- source3/winbindd/idmap_hash/idmap_hash.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/source3/winbindd/idmap_hash/idmap_hash.c b/source3/winbindd/idmap_hash/idmap_hash.c index fb900617ec3..a3430350625 100644 --- a/source3/winbindd/idmap_hash/idmap_hash.c +++ b/source3/winbindd/idmap_hash/idmap_hash.c @@ -25,6 +25,7 @@ #include "ads.h" #include "nss_info.h" #include "../libcli/security/dom_sid.h" +#include "libsmb/samlogon_cache.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_IDMAP @@ -287,6 +288,21 @@ static NTSTATUS idmap_hash_sid_to_id(struct sid_hash_table *hashed_domains, goto return_mapping; } + /* + * Check of last resort: A domain is valid if a user from that + * domain has recently logged in. The samlogon_cache these + * days also stores the domain sid. + */ + if (netsamlogon_cache_have(&sid)) { + /* + * We keep the legacy behavior and + * just return the mapping, but + * the reverse mapping would not + * still not work. + */ + goto return_mapping; + } + if (id->xid.type == ID_TYPE_NOT_SPECIFIED) { /* * idmap_hash used to bounce back the requested type, -- 2.34.1 From eec373c1570035d1e5ab0c692237d092f781746e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 21 Mar 2019 16:54:31 +0100 Subject: [PATCH 11/11] idmap_hash: remember new domain sids in idmap_hash_sid_to_id() This change means that idmap_hash_id_to_sid() can return mappings for new domains learned in idmap_hash_sid_to_id(). BUG: https://bugzilla.samba.org/show_bug.cgi?id=15319 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison Autobuild-User(master): Stefan Metzmacher Autobuild-Date(master): Fri Mar 10 11:35:06 UTC 2023 on atb-devel-224 (cherry picked from commit 7ee725f2860d835e9619fa594a2ee6faedbc6d21) --- source3/winbindd/idmap_hash/idmap_hash.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/source3/winbindd/idmap_hash/idmap_hash.c b/source3/winbindd/idmap_hash/idmap_hash.c index a3430350625..e9d90e3d02b 100644 --- a/source3/winbindd/idmap_hash/idmap_hash.c +++ b/source3/winbindd/idmap_hash/idmap_hash.c @@ -295,12 +295,11 @@ static NTSTATUS idmap_hash_sid_to_id(struct sid_hash_table *hashed_domains, */ if (netsamlogon_cache_have(&sid)) { /* - * We keep the legacy behavior and - * just return the mapping, but - * the reverse mapping would not - * still not work. + * The domain is valid, so we'll + * remember it in order to + * allow reverse mappings to work. */ - goto return_mapping; + goto remember_domain; } if (id->xid.type == ID_TYPE_NOT_SPECIFIED) { @@ -322,6 +321,17 @@ static NTSTATUS idmap_hash_sid_to_id(struct sid_hash_table *hashed_domains, return NT_STATUS_OK; } + /* + * Now we're sure the domain exist, remember + * the domain in order to return reverse mappings + * in future. + */ +remember_domain: + hashed_domains[h_domain].sid = dom_sid_dup(hashed_domains, &sid); + if (hashed_domains[h_domain].sid == NULL) { + return NT_STATUS_NO_MEMORY; + } + /* * idmap_hash used to bounce back the requested type, * which was ID_TYPE_UID, ID_TYPE_GID or -- 2.34.1