The branch, v4-17-test has been updated via e2df45934ab dsdb: Avoid ERROR(ldb): uncaught exception - Deleted target CN=NTDS Settings... in join via eaff4ef6162 selftest/drs: Demonstrate ERROR(ldb): uncaught exception - Deleted target CN=NTDS Settings... in join via 3ecdec683b6 CVE-2020-25720 pydsdb: Add AD schema GUID constants via b1c7df203d0 tsocket: Increase tcp_user_timeout max_loops via bf5ccd5a140 idmap_hash: remember new domain sids in idmap_hash_sid_to_id() via f27cff23350 idmap_hash: don't return ID_REQUIRE_TYPE if the domain is known in the netsamlogon cache via 182410af7de idmap_hash: only return ID_REQUIRE_TYPE if we don't know about the domain yet via 13a593254af idmap_hash: return ID_REQUIRE_TYPE only if there's a chance to get a mapping later via e5c9a3597af idmap_hash: split out a idmap_hash_sid_to_id() helper function via da270642918 idmap_hash: split out a idmap_hash_id_to_sid() helper function via 61f3e674076 idmap_hash: mirror the NT_STATUS_NONE_MAPPED/STATUS_SOME_UNMAPPED logic from idmap_autorid via a19fe930199 idmap_hash: we don't need to call idmap_hash_initialize() over an over again via 5a754810dea idmap_hash: remove unused error checks via 1e6eeb8efb2 idmap_hash: fix comments about the algorithm via bac09f85daa idmap_hash: provide ID_TYPE_BOTH mappings also for unixids_to_sids via edc8659b505 idmap_autorid: fix ID_REQUIRE_TYPE for more than one SID for an unknown domain via 148d5ad7698 winbindd: don't call set_domain_online_request() in the idmap child from cb204cfc69b VERSION: Bump version up to Samba 4.17.8...
https://git.samba.org/?p=samba.git;a=shortlog;h=v4-17-test - Log ----------------------------------------------------------------- commit e2df45934ab415732f7f0377601774119b37e7b3 Author: Andrew Bartlett <abart...@samba.org> Date: Thu Mar 9 20:25:06 2023 +1300 dsdb: Avoid ERROR(ldb): uncaught exception - Deleted target CN=NTDS Settings... in join "samba-tool domain join" uses the replication API in a strange way, perhaps no longer required, except that we often still have folks upgrading from very old Samba versions. When deferring the writing out to the DB of link replication to the very end, there is a greater opportunity for the deletion of an object to have been sent with the other objects, and have the link applied later. This tells the repl_meta_data code to behave as if GET_TGT had been sent at the time the link was returned, allowing a link to a deleted object to be silently discarded. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15329 Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Joseph Sutton <josephsut...@catalyst.net.nz> (cherry picked from commit bfc33b47bb428233e100f75e7a725ac52179f823) Autobuild-User(v4-17-test): Jule Anger <jan...@samba.org> Autobuild-Date(v4-17-test): Thu Mar 30 16:10:35 UTC 2023 on sn-devel-184 commit eaff4ef61624276b16dc0dcb11868e2778d2e46f Author: Andrew Bartlett <abart...@samba.org> Date: Thu Mar 9 17:02:35 2023 +1300 selftest/drs: Demonstrate ERROR(ldb): uncaught exception - Deleted target CN=NTDS Settings... in join "samba-tool domain join" uses the replication API in a strange way, perhaps no longer required, except that we often still have folks upgrading from very old Samba versions. By deferring the writing out to the DB of link replication to the very end, we have a better chance that all the objects required are present, however the situation may have changed during the cycle, and a link could still be sent, pointing to a deleted object. We currently fail in this situation. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15329 Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Joseph Sutton <josephsut...@catalyst.net.nz> (cherry picked from commit 2d41bcce83a976b85636c92d6fc38c63fdde5431) commit 3ecdec683b60cf100b1c031841b709c91191c8f2 Author: Joseph Sutton <josephsut...@catalyst.net.nz> Date: Wed Sep 14 13:21:34 2022 +1200 CVE-2020-25720 pydsdb: Add AD schema GUID constants This helps reduce the profusion of magic constant values in Python tests. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14810 BUG: https://bugzilla.samba.org/show_bug.cgi?id=15329 Signed-off-by: Joseph Sutton <josephsut...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> (cherry picked from commit 2563f85237bd4260b7b527f3695f27da4cc61a74) [abart...@samba.org Required context for backport of bug 15329 to Samba 4.17] commit b1c7df203d02410d829381f7b7fcfbc7c8d4bfd1 Author: Andrew Bartlett <abart...@samba.org> Date: Thu Mar 9 10:06:26 2023 +1300 tsocket: Increase tcp_user_timeout max_loops Often, on rackspace GitLab CI runners, we get: UNEXPECTED(failure): samba.unittests.tsocket_tstream.test_tstream_more_tcp_user_timeout_spin(none) REASON: Exception: Exception: 0xf == 0xf ../../lib/tsocket/tests/test_tstream.c:405: error: Failure! This allows us more spins before we fail the test. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15328 Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Joseph Sutton <josephsut...@catalyst.net.nz> (cherry picked from commit 5a7a28cc45870949fc11d30586a06c309aa517dc) commit bf5ccd5a14062dc31c09e167dadff9782ba1caba Author: Stefan Metzmacher <me...@samba.org> Date: Thu Mar 21 16:54:31 2019 +0100 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 <me...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> Autobuild-User(master): Stefan Metzmacher <me...@samba.org> Autobuild-Date(master): Fri Mar 10 11:35:06 UTC 2023 on atb-devel-224 (cherry picked from commit 7ee725f2860d835e9619fa594a2ee6faedbc6d21) commit f27cff23350dc332515a66d98335418d20e94a0e Author: Stefan Metzmacher <me...@samba.org> Date: Thu Mar 21 16:54:31 2019 +0100 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 <me...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> (cherry picked from commit ee820553fd2c6ada966a0160cbb0240049f9d9f7) commit 182410af7de4fdfb8100cc83e53d0371e59d6a81 Author: Stefan Metzmacher <me...@samba.org> Date: Thu Mar 21 16:54:31 2019 +0100 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 <me...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> (cherry picked from commit ede88d9f83fb77fa8eff226fb6a85ac71e415098) commit 13a593254afa9cfdfbcefb51da88b1a8309ef723 Author: Stefan Metzmacher <me...@samba.org> Date: Thu Mar 21 16:54:31 2019 +0100 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 <me...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> (cherry picked from commit 42dcb3db05530179a991fe58e7b96b52bbbcc607) commit e5c9a3597af05da7236e284422adca5294ff31c4 Author: Stefan Metzmacher <me...@samba.org> Date: Thu Mar 21 14:05:13 2019 +0100 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 <me...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> (cherry picked from commit c158b075b0b5035615fa8848f1f3d8ef27696861) commit da2706429185ec6724d91f409f78ffbf10f7208c Author: Stefan Metzmacher <me...@samba.org> Date: Thu Mar 21 14:05:13 2019 +0100 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 <me...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> (cherry picked from commit 57150b463fb8e27c048670f7b4902bd091ee3ae9) commit 61f3e6740765c92cd84c28ee69fe410c18b548fc Author: Stefan Metzmacher <me...@samba.org> Date: Thu Mar 21 14:00:16 2019 +0100 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 <me...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> (cherry picked from commit 14102b05f3744c67178bd719d41e67fc3e049ee4) commit a19fe9301999a0ce308f06643ff3be1bbac7beb7 Author: Stefan Metzmacher <me...@samba.org> Date: Thu Mar 21 10:54:49 2019 +0100 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 <me...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> (cherry picked from commit 0da13ab3ad7278eafdcd988f39e891242eb46d37) commit 5a754810dead1225554b5a9c5c5265079ae5c0a9 Author: Stefan Metzmacher <me...@samba.org> Date: Thu Mar 21 13:54:10 2019 +0100 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 <me...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> (cherry picked from commit 2cfcff3101fce94b365eccde114432dfa980bbd0) commit 1e6eeb8efb21a836c08d203d379817598d6ea447 Author: Stefan Metzmacher <me...@samba.org> Date: Thu Mar 21 13:37:16 2019 +0100 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 <me...@samba.org> Reviewed-by: Ralph Boehme <s...@samba.org> (cherry picked from commit 0f96c4b419a59ea884e68a460910e5c8a45bfcec) commit bac09f85daa6f610347fd467c27d1b5197b3a662 Author: Stefan Metzmacher <me...@samba.org> Date: Thu Mar 21 16:38:35 2019 +0100 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 <me...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> (cherry picked from commit 9a24570d3d69f51b6d50bb04b739815ec67c1a3d) commit edc8659b5055e3b8adec83417846a76147ee1408 Author: Stefan Metzmacher <me...@samba.org> Date: Fri Feb 17 16:51:42 2023 +0100 idmap_autorid: fix ID_REQUIRE_TYPE for more than one SID for an unknown domain When we see a trusted domain SID for the first time, idmap_autorid returns ID_REQUIRE_TYPE only for the first sid and leaves the others with ID_TYPE_NOT_SPECIFIED. It means the winbindd parent only retries the first sid. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15318 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> (cherry picked from commit a9583b5f96fe3fbf9c1ee545fa868fd705aef3e0) commit 148d5ad7698d154731dfa092b0c6314c71f38086 Author: Stefan Metzmacher <me...@samba.org> Date: Thu Feb 16 16:31:34 2023 +0100 winbindd: don't call set_domain_online_request() in the idmap child Most idmap backends don't need access to the domain controllers. And the related code is not needed for the backends. Commit 17c86a2c5a5a5e2b194362e5f36f0f99910222c5 changed the logic of set_domain_online_request() completely! Instead of triggering a dc probe in the background, it is now doing a blocking connection. And doing this in the idmap child is completely useless. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15317 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> (cherry picked from commit ad242a20643c930eb00a8b700f7bd9638f8821a8) ----------------------------------------------------------------------- Summary of changes: lib/tsocket/tests/test_tstream.c | 2 +- libds/common/flags.h | 14 ++ python/samba/join.py | 19 ++ source3/winbindd/idmap_autorid.c | 15 +- source3/winbindd/idmap_hash/idmap_hash.c | 302 +++++++++++++++--------- source3/winbindd/winbindd_dual.c | 7 - source4/dsdb/pydsdb.c | 15 ++ source4/dsdb/samdb/ldb_modules/repl_meta_data.c | 13 +- source4/dsdb/samdb/samdb.h | 2 + source4/torture/drs/python/ridalloc_exop.py | 135 +++++++++++ 10 files changed, 406 insertions(+), 118 deletions(-) Changeset truncated at 500 lines: diff --git a/lib/tsocket/tests/test_tstream.c b/lib/tsocket/tests/test_tstream.c index a920e671cda..47008bb8bf8 100644 --- a/lib/tsocket/tests/test_tstream.c +++ b/lib/tsocket/tests/test_tstream.c @@ -322,7 +322,7 @@ static void test_tstream_server_spin_client_tcp_user_timeout(struct socket_pair rc = write(sp->socket_client, TEST_STRING, sizeof(TEST_STRING)); assert_return_code(rc, errno); sp->expected_errno = ETIMEDOUT; - sp->max_loops = 15; + sp->max_loops = 30; } static void test_tstream_server_spin_client_both_timer(struct tevent_context *ev, diff --git a/libds/common/flags.h b/libds/common/flags.h index bee1016b294..c013d2f0f25 100644 --- a/libds/common/flags.h +++ b/libds/common/flags.h @@ -237,6 +237,20 @@ /* wellknown GUIDs for optional directory features */ #define DS_GUID_FEATURE_RECYCLE_BIN "766ddcd8-acd0-445e-f3b9-a7f9b6744f2a" +/* GUIDs for AD schema attributes and classes */ +#define DS_GUID_SCHEMA_ATTR_DEPARTMENT "bf96794f-0de6-11d0-a285-00aa003049e2" +#define DS_GUID_SCHEMA_ATTR_DNS_HOST_NAME "72e39547-7b18-11d1-adef-00c04fd8d5cd" +#define DS_GUID_SCHEMA_ATTR_INSTANCE_TYPE "bf96798c-0de6-11d0-a285-00aa003049e2" +#define DS_GUID_SCHEMA_ATTR_MS_SFU_30 "16c5d1d3-35c2-4061-a870-a5cefda804f0" +#define DS_GUID_SCHEMA_ATTR_NT_SECURITY_DESCRIPTOR "bf9679e3-0de6-11d0-a285-00aa003049e2" +#define DS_GUID_SCHEMA_ATTR_PRIMARY_GROUP_ID "bf967a00-0de6-11d0-a285-00aa003049e2" +#define DS_GUID_SCHEMA_ATTR_SERVICE_PRINCIPAL_NAME "f3a64788-5306-11d1-a9c5-0000f80367c1" +#define DS_GUID_SCHEMA_ATTR_USER_ACCOUNT_CONTROL "bf967a68-0de6-11d0-a285-00aa003049e2" +#define DS_GUID_SCHEMA_ATTR_USER_PASSWORD "bf967a6e-0de6-11d0-a285-00aa003049e2" +#define DS_GUID_SCHEMA_CLASS_COMPUTER "bf967a86-0de6-11d0-a285-00aa003049e2" +#define DS_GUID_SCHEMA_CLASS_MANAGED_SERVICE_ACCOUNT "ce206244-5827-4a86-ba1c-1c0c386c1b64" +#define DS_GUID_SCHEMA_CLASS_USER "bf967aba-0de6-11d0-a285-00aa003049e2" + /* dsHeuristics character indexes see MS-ADTS 7.1.1.2.4.1.2 */ #define DS_HR_SUPFIRSTLASTANR 0x00000001 diff --git a/python/samba/join.py b/python/samba/join.py index 650bb5a08ae..30d33d43f11 100644 --- a/python/samba/join.py +++ b/python/samba/join.py @@ -50,6 +50,7 @@ import tempfile from collections import OrderedDict from samba.common import get_string from samba.netcmd import CommandError +from samba import dsdb class DCJoinException(Exception): @@ -937,6 +938,10 @@ class DCJoinContext(object): """Replicate the SAM.""" ctx.logger.info("Starting replication") + + # A global transaction is started so that linked attributes + # are applied at the very end, once all partitions are + # replicated. This helps get all cross-partition links. ctx.local_samdb.transaction_start() try: source_dsa_invocation_id = misc.GUID(ctx.samdb.get_invocation_id()) @@ -1057,7 +1062,21 @@ class DCJoinContext(object): ctx.local_samdb.transaction_cancel() raise else: + + # This is a special case, we have completed a full + # replication so if a link comes to us that points to a + # deleted object, and we asked for all objects already, we + # just have to ignore it, the chance to re-try the + # replication with GET_TGT has long gone. This can happen + # if the object is deleted and sent to us after the link + # was sent, as we are processing all links in the + # transaction_commit(). + if not ctx.domain_replica_flags & drsuapi.DRSUAPI_DRS_CRITICAL_ONLY: + ctx.local_samdb.set_opaque_integer(dsdb.DSDB_FULL_JOIN_REPLICATION_COMPLETED_OPAQUE_NAME, + 1) ctx.local_samdb.transaction_commit() + ctx.local_samdb.set_opaque_integer(dsdb.DSDB_FULL_JOIN_REPLICATION_COMPLETED_OPAQUE_NAME, + 0) ctx.logger.info("Committed SAM database") # A large replication may have caused our LDB connection to the diff --git a/source3/winbindd/idmap_autorid.c b/source3/winbindd/idmap_autorid.c index c7d56a37684..bf5947a9b43 100644 --- a/source3/winbindd/idmap_autorid.c +++ b/source3/winbindd/idmap_autorid.c @@ -697,9 +697,10 @@ static NTSTATUS idmap_autorid_sids_to_unixids(struct idmap_domain *dom, { struct idmap_tdb_common_context *commoncfg; NTSTATUS ret; - int i; - int num_tomap = 0; - int num_mapped = 0; + size_t i; + size_t num_tomap = 0; + size_t num_mapped = 0; + size_t num_required = 0; /* initialize the status to avoid surprise */ for (i = 0; ids[i]; i++) { @@ -713,6 +714,12 @@ static NTSTATUS idmap_autorid_sids_to_unixids(struct idmap_domain *dom, for (i = 0; ids[i]; i++) { ret = idmap_autorid_sid_to_id(commoncfg, dom, ids[i]); + if (NT_STATUS_EQUAL(ret, NT_STATUS_SOME_NOT_MAPPED) && + ids[i]->status == ID_REQUIRE_TYPE) + { + num_required++; + continue; + } if ((!NT_STATUS_IS_OK(ret)) && (!NT_STATUS_EQUAL(ret, NT_STATUS_NONE_MAPPED))) { struct dom_sid_buf buf; @@ -729,6 +736,8 @@ static NTSTATUS idmap_autorid_sids_to_unixids(struct idmap_domain *dom, 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; } diff --git a/source3/winbindd/idmap_hash/idmap_hash.c b/source3/winbindd/idmap_hash/idmap_hash.c index d0bed7631a6..e9d90e3d02b 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 @@ -60,13 +61,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 +83,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); @@ -123,14 +132,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); @@ -183,135 +184,224 @@ 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) { 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; - - if (!ids) { - nt_status = NT_STATUS_INVALID_PARAMETER; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } + 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++; } - nt_status = idmap_hash_initialize(dom); - BAIL_ON_NTSTATUS_ERROR(nt_status); - for (i=0; ids[i]; i++) { - uint32_t h_domain, h_rid; + 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]->status = ID_UNMAPPED; + if (ids[i]->status == ID_MAPPED) { + num_mapped++; + } + } - separate_hashes(ids[i]->xid.id, &h_domain, &h_rid); + if (num_tomap == num_mapped) { + return NT_STATUS_OK; + } else if (num_mapped == 0) { + return NT_STATUS_NONE_MAPPED; + } - /* Make sure the caller allocated memor for us */ + return STATUS_SOME_UNMAPPED; +} - 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 */ +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 (!hashed_domains[h_domain].sid) - continue; + id->status = ID_UNMAPPED; - sid_compose(ids[i]->sid, hashed_domains[h_domain].sid, h_rid); - ids[i]->status = ID_MAPPED; + 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; } -done: - return nt_status; -} + /* + * 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; + } -/********************************************************************* - ********************************************************************/ + /* + * 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)) { + /* + * The domain is valid, so we'll + * remember it in order to + * allow reverse mappings to work. + */ + goto remember_domain; + } + + 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; + } + + /* + * 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 + * 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. + */ +return_mapping: + 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) { - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - int i; - - if (!ids) { - nt_status = NT_STATUS_INVALID_PARAMETER; - BAIL_ON_NTSTATUS_ERROR(nt_status); - } + 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; + 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++; } - 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; - 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; - 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++; } } -done: - return nt_status; + 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; + } + -- Samba Shared Repository